ixgbe: extend firmware version support

Extend FW version reporting by displaying information from the iSCSI
or OEM block in the EEPROM.

This will allow us to more accurately identify the FW.

Signed-off-by: Paul Greenwalt <paul.greenwalt@intel.com>
Tested-by: Andrew Bowers <andrewx.bowers@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
This commit is contained in:
Paul Greenwalt 2017-10-27 10:32:40 -04:00 committed by Jeff Kirsher
parent 3ead7c2e86
commit 73834aec71
7 changed files with 198 additions and 14 deletions

View File

@ -723,8 +723,7 @@ struct ixgbe_adapter {
u16 bridge_mode; u16 bridge_mode;
u16 eeprom_verh; char eeprom_id[NVM_VER_SIZE];
u16 eeprom_verl;
u16 eeprom_cap; u16 eeprom_cap;
u32 interrupt_event; u32 interrupt_event;

View File

@ -4028,6 +4028,118 @@ s32 ixgbe_init_thermal_sensor_thresh_generic(struct ixgbe_hw *hw)
return 0; return 0;
} }
/**
* ixgbe_get_orom_version - Return option ROM from EEPROM
*
* @hw: pointer to hardware structure
* @nvm_ver: pointer to output structure
*
* if valid option ROM version, nvm_ver->or_valid set to true
* else nvm_ver->or_valid is false.
**/
void ixgbe_get_orom_version(struct ixgbe_hw *hw,
struct ixgbe_nvm_version *nvm_ver)
{
u16 offset, eeprom_cfg_blkh, eeprom_cfg_blkl;
nvm_ver->or_valid = false;
/* Option Rom may or may not be present. Start with pointer */
hw->eeprom.ops.read(hw, NVM_OROM_OFFSET, &offset);
/* make sure offset is valid */
if (offset == 0x0 || offset == NVM_INVALID_PTR)
return;
hw->eeprom.ops.read(hw, offset + NVM_OROM_BLK_HI, &eeprom_cfg_blkh);
hw->eeprom.ops.read(hw, offset + NVM_OROM_BLK_LOW, &eeprom_cfg_blkl);
/* option rom exists and is valid */
if ((eeprom_cfg_blkl | eeprom_cfg_blkh) == 0x0 ||
eeprom_cfg_blkl == NVM_VER_INVALID ||
eeprom_cfg_blkh == NVM_VER_INVALID)
return;
nvm_ver->or_valid = true;
nvm_ver->or_major = eeprom_cfg_blkl >> NVM_OROM_SHIFT;
nvm_ver->or_build = (eeprom_cfg_blkl << NVM_OROM_SHIFT) |
(eeprom_cfg_blkh >> NVM_OROM_SHIFT);
nvm_ver->or_patch = eeprom_cfg_blkh & NVM_OROM_PATCH_MASK;
}
/**
* ixgbe_get_oem_prod_version Etrack ID from EEPROM
*
* @hw: pointer to hardware structure
* @nvm_ver: pointer to output structure
*
* if valid OEM product version, nvm_ver->oem_valid set to true
* else nvm_ver->oem_valid is false.
**/
void ixgbe_get_oem_prod_version(struct ixgbe_hw *hw,
struct ixgbe_nvm_version *nvm_ver)
{
u16 rel_num, prod_ver, mod_len, cap, offset;
nvm_ver->oem_valid = false;
hw->eeprom.ops.read(hw, NVM_OEM_PROD_VER_PTR, &offset);
/* Return is offset to OEM Product Version block is invalid */
if (offset == 0x0 && offset == NVM_INVALID_PTR)
return;
/* Read product version block */
hw->eeprom.ops.read(hw, offset, &mod_len);
hw->eeprom.ops.read(hw, offset + NVM_OEM_PROD_VER_CAP_OFF, &cap);
/* Return if OEM product version block is invalid */
if (mod_len != NVM_OEM_PROD_VER_MOD_LEN ||
(cap & NVM_OEM_PROD_VER_CAP_MASK) != 0x0)
return;
hw->eeprom.ops.read(hw, offset + NVM_OEM_PROD_VER_OFF_L, &prod_ver);
hw->eeprom.ops.read(hw, offset + NVM_OEM_PROD_VER_OFF_H, &rel_num);
/* Return if version is invalid */
if ((rel_num | prod_ver) == 0x0 ||
rel_num == NVM_VER_INVALID || prod_ver == NVM_VER_INVALID)
return;
nvm_ver->oem_major = prod_ver >> NVM_VER_SHIFT;
nvm_ver->oem_minor = prod_ver & NVM_VER_MASK;
nvm_ver->oem_release = rel_num;
nvm_ver->oem_valid = true;
}
/**
* ixgbe_get_etk_id - Return Etrack ID from EEPROM
*
* @hw: pointer to hardware structure
* @nvm_ver: pointer to output structure
*
* word read errors will return 0xFFFF
**/
void ixgbe_get_etk_id(struct ixgbe_hw *hw,
struct ixgbe_nvm_version *nvm_ver)
{
u16 etk_id_l, etk_id_h;
if (hw->eeprom.ops.read(hw, NVM_ETK_OFF_LOW, &etk_id_l))
etk_id_l = NVM_VER_INVALID;
if (hw->eeprom.ops.read(hw, NVM_ETK_OFF_HI, &etk_id_h))
etk_id_h = NVM_VER_INVALID;
/* The word order for the version format is determined by high order
* word bit 15.
*/
if ((etk_id_h & NVM_ETK_VALID) == 0) {
nvm_ver->etk_id = etk_id_h;
nvm_ver->etk_id |= (etk_id_l << NVM_ETK_SHIFT);
} else {
nvm_ver->etk_id = etk_id_l;
nvm_ver->etk_id |= (etk_id_h << NVM_ETK_SHIFT);
}
}
void ixgbe_disable_rx_generic(struct ixgbe_hw *hw) void ixgbe_disable_rx_generic(struct ixgbe_hw *hw)
{ {
u32 rxctrl; u32 rxctrl;

View File

@ -139,6 +139,12 @@ extern const u32 ixgbe_mvals_8259X[IXGBE_MVALS_IDX_LIMIT];
s32 ixgbe_get_thermal_sensor_data_generic(struct ixgbe_hw *hw); s32 ixgbe_get_thermal_sensor_data_generic(struct ixgbe_hw *hw);
s32 ixgbe_init_thermal_sensor_thresh_generic(struct ixgbe_hw *hw); s32 ixgbe_init_thermal_sensor_thresh_generic(struct ixgbe_hw *hw);
void ixgbe_get_etk_id(struct ixgbe_hw *hw,
struct ixgbe_nvm_version *nvm_ver);
void ixgbe_get_oem_prod_version(struct ixgbe_hw *hw,
struct ixgbe_nvm_version *nvm_ver);
void ixgbe_get_orom_version(struct ixgbe_hw *hw,
struct ixgbe_nvm_version *nvm_ver);
void ixgbe_disable_rx_generic(struct ixgbe_hw *hw); void ixgbe_disable_rx_generic(struct ixgbe_hw *hw);
void ixgbe_enable_rx_generic(struct ixgbe_hw *hw); void ixgbe_enable_rx_generic(struct ixgbe_hw *hw);
s32 ixgbe_setup_mac_link_multispeed_fiber(struct ixgbe_hw *hw, s32 ixgbe_setup_mac_link_multispeed_fiber(struct ixgbe_hw *hw,

View File

@ -1014,16 +1014,13 @@ static void ixgbe_get_drvinfo(struct net_device *netdev,
struct ethtool_drvinfo *drvinfo) struct ethtool_drvinfo *drvinfo)
{ {
struct ixgbe_adapter *adapter = netdev_priv(netdev); struct ixgbe_adapter *adapter = netdev_priv(netdev);
u32 nvm_track_id;
strlcpy(drvinfo->driver, ixgbe_driver_name, sizeof(drvinfo->driver)); strlcpy(drvinfo->driver, ixgbe_driver_name, sizeof(drvinfo->driver));
strlcpy(drvinfo->version, ixgbe_driver_version, strlcpy(drvinfo->version, ixgbe_driver_version,
sizeof(drvinfo->version)); sizeof(drvinfo->version));
nvm_track_id = (adapter->eeprom_verh << 16) | strlcpy(drvinfo->fw_version, adapter->eeprom_id,
adapter->eeprom_verl; sizeof(drvinfo->fw_version));
snprintf(drvinfo->fw_version, sizeof(drvinfo->fw_version), "0x%08x",
nvm_track_id);
strlcpy(drvinfo->bus_info, pci_name(adapter->pdev), strlcpy(drvinfo->bus_info, pci_name(adapter->pdev),
sizeof(drvinfo->bus_info)); sizeof(drvinfo->bus_info));

View File

@ -1034,11 +1034,8 @@ int ixgbe_fcoe_get_hbainfo(struct net_device *netdev,
ixgbe_driver_name, ixgbe_driver_name,
ixgbe_driver_version); ixgbe_driver_version);
/* Firmware Version */ /* Firmware Version */
snprintf(info->firmware_version, strlcpy(info->firmware_version, adapter->eeprom_id,
sizeof(info->firmware_version), sizeof(info->firmware_version));
"0x%08x",
(adapter->eeprom_verh << 16) |
adapter->eeprom_verl);
/* Model */ /* Model */
if (hw->mac.type == ixgbe_mac_82599EB) { if (hw->mac.type == ixgbe_mac_82599EB) {

View File

@ -10234,6 +10234,41 @@ bool ixgbe_wol_supported(struct ixgbe_adapter *adapter, u16 device_id,
return false; return false;
} }
/**
* ixgbe_set_fw_version - Set FW version
* @adapter: the adapter private structure
*
* This function is used by probe and ethtool to determine the FW version to
* format to display. The FW version is taken from the EEPROM/NVM.
*/
static void ixgbe_set_fw_version(struct ixgbe_adapter *adapter)
{
struct ixgbe_hw *hw = &adapter->hw;
struct ixgbe_nvm_version nvm_ver;
ixgbe_get_oem_prod_version(hw, &nvm_ver);
if (nvm_ver.oem_valid) {
snprintf(adapter->eeprom_id, sizeof(adapter->eeprom_id),
"%x.%x.%x", nvm_ver.oem_major, nvm_ver.oem_minor,
nvm_ver.oem_release);
return;
}
ixgbe_get_etk_id(hw, &nvm_ver);
ixgbe_get_orom_version(hw, &nvm_ver);
if (nvm_ver.or_valid) {
snprintf(adapter->eeprom_id, sizeof(adapter->eeprom_id),
"0x%08x, %d.%d.%d", nvm_ver.etk_id, nvm_ver.or_major,
nvm_ver.or_build, nvm_ver.or_patch);
return;
}
/* Set ETrack ID format */
snprintf(adapter->eeprom_id, sizeof(adapter->eeprom_id),
"0x%08x", nvm_ver.etk_id);
}
/** /**
* ixgbe_probe - Device Initialization Routine * ixgbe_probe - Device Initialization Routine
* @pdev: PCI device information struct * @pdev: PCI device information struct
@ -10570,8 +10605,7 @@ skip_sriov:
device_set_wakeup_enable(&adapter->pdev->dev, adapter->wol); device_set_wakeup_enable(&adapter->pdev->dev, adapter->wol);
/* save off EEPROM version number */ /* save off EEPROM version number */
hw->eeprom.ops.read(hw, 0x2e, &adapter->eeprom_verh); ixgbe_set_fw_version(adapter);
hw->eeprom.ops.read(hw, 0x2d, &adapter->eeprom_verl);
/* pick up the PCI bus settings for reporting later */ /* pick up the PCI bus settings for reporting later */
if (ixgbe_pcie_from_parent(hw)) if (ixgbe_pcie_from_parent(hw))

View File

@ -235,6 +235,45 @@ struct ixgbe_thermal_sensor_data {
struct ixgbe_thermal_diode_data sensor[IXGBE_MAX_SENSORS]; struct ixgbe_thermal_diode_data sensor[IXGBE_MAX_SENSORS];
}; };
#define NVM_OROM_OFFSET 0x17
#define NVM_OROM_BLK_LOW 0x83
#define NVM_OROM_BLK_HI 0x84
#define NVM_OROM_PATCH_MASK 0xFF
#define NVM_OROM_SHIFT 8
#define NVM_VER_MASK 0x00FF /* version mask */
#define NVM_VER_SHIFT 8 /* version bit shift */
#define NVM_OEM_PROD_VER_PTR 0x1B /* OEM Product version block pointer */
#define NVM_OEM_PROD_VER_CAP_OFF 0x1 /* OEM Product version format offset */
#define NVM_OEM_PROD_VER_OFF_L 0x2 /* OEM Product version offset low */
#define NVM_OEM_PROD_VER_OFF_H 0x3 /* OEM Product version offset high */
#define NVM_OEM_PROD_VER_CAP_MASK 0xF /* OEM Product version cap mask */
#define NVM_OEM_PROD_VER_MOD_LEN 0x3 /* OEM Product version module length */
#define NVM_ETK_OFF_LOW 0x2D /* version low order word */
#define NVM_ETK_OFF_HI 0x2E /* version high order word */
#define NVM_ETK_SHIFT 16 /* high version word shift */
#define NVM_VER_INVALID 0xFFFF
#define NVM_ETK_VALID 0x8000
#define NVM_INVALID_PTR 0xFFFF
#define NVM_VER_SIZE 32 /* version sting size */
struct ixgbe_nvm_version {
u32 etk_id;
u8 nvm_major;
u16 nvm_minor;
u8 nvm_id;
bool oem_valid;
u8 oem_major;
u8 oem_minor;
u16 oem_release;
bool or_valid;
u8 or_major;
u16 or_build;
u8 or_patch;
};
/* Interrupt Registers */ /* Interrupt Registers */
#define IXGBE_EICR 0x00800 #define IXGBE_EICR 0x00800
#define IXGBE_EICS 0x00808 #define IXGBE_EICS 0x00808