igb: Update firmware info output
authorCarolyn Wyborny <carolyn.wyborny@intel.com>
Thu, 14 Jun 2012 16:04:19 +0000 (16:04 +0000)
committerJeff Kirsher <jeffrey.t.kirsher@intel.com>
Wed, 20 Jun 2012 08:36:23 +0000 (01:36 -0700)
Our NVM image creation tools have evolved over the years and there are
multiple versions contained in them, depending on the tool used to create
them.  This patch outputs the NVM versions available in ethtool -i output.

rc2: (not sure why others show in log but not in the message)
     Added additional call to igb_set_fw_version per Community feedback.

Signed-off-by: Carolyn Wyborny <carolyn.wyborny@intel.com>
Tested-by: Jeff Pieper <jeffrey.e.pieper@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
drivers/net/ethernet/intel/igb/igb.h
drivers/net/ethernet/intel/igb/igb_ethtool.c
drivers/net/ethernet/intel/igb/igb_main.c

index 3ced7b5..9e572dd 100644 (file)
@@ -75,6 +75,20 @@ struct igb_adapter;
 #define IGB_82576_VF_DEV_ID                0x10CA
 #define IGB_I350_VF_DEV_ID                 0x1520
 
+/* NVM version defines */
+#define IGB_MAJOR_MASK                 0xF000
+#define IGB_MINOR_MASK                 0x0FF0
+#define IGB_BUILD_MASK                 0x000F
+#define IGB_COMB_VER_MASK              0x00FF
+#define IGB_MAJOR_SHIFT                        12
+#define IGB_MINOR_SHIFT                        4
+#define IGB_COMB_VER_SHFT              8
+#define IGB_NVM_VER_INVALID            0xFFFF
+#define IGB_ETRACK_SHIFT               16
+#define NVM_ETRACK_WORD                        0x0042
+#define NVM_COMB_VER_OFF               0x0083
+#define NVM_COMB_VER_PTR               0x003d
+
 struct vf_data_storage {
        unsigned char vf_mac_addresses[ETH_ALEN];
        u16 vf_mc_hashes[IGB_MAX_VF_MC_ENTRIES];
@@ -368,6 +382,7 @@ struct igb_adapter {
        spinlock_t tmreg_lock;
        struct cyclecounter cc;
        struct timecounter tc;
+       char fw_version[32];
 };
 
 #define IGB_FLAG_HAS_MSI           (1 << 0)
@@ -417,6 +432,7 @@ extern void igb_update_stats(struct igb_adapter *, struct rtnl_link_stats64 *);
 extern bool igb_has_link(struct igb_adapter *adapter);
 extern void igb_set_ethtool_ops(struct net_device *);
 extern void igb_power_up_link(struct igb_adapter *);
+extern void igb_set_fw_version(struct igb_adapter *);
 #ifdef CONFIG_IGB_PTP
 extern void igb_ptp_init(struct igb_adapter *adapter);
 extern void igb_ptp_remove(struct igb_adapter *adapter);
index 59d0f04..a19c84c 100644 (file)
@@ -710,6 +710,7 @@ static int igb_set_eeprom(struct net_device *netdev,
        if ((ret_val == 0) && ((first_word <= NVM_CHECKSUM_REG)))
                hw->nvm.ops.update(hw);
 
+       igb_set_fw_version(adapter);
        kfree(eeprom_buff);
        return ret_val;
 }
@@ -718,20 +719,16 @@ static void igb_get_drvinfo(struct net_device *netdev,
                            struct ethtool_drvinfo *drvinfo)
 {
        struct igb_adapter *adapter = netdev_priv(netdev);
-       u16 eeprom_data;
 
        strlcpy(drvinfo->driver,  igb_driver_name, sizeof(drvinfo->driver));
        strlcpy(drvinfo->version, igb_driver_version, sizeof(drvinfo->version));
 
-       /* EEPROM image version # is reported as firmware version # for
-        * 82575 controllers */
-       adapter->hw.nvm.ops.read(&adapter->hw, 5, 1, &eeprom_data);
-       snprintf(drvinfo->fw_version, sizeof(drvinfo->fw_version),
-               "%d.%d-%d",
-               (eeprom_data & 0xF000) >> 12,
-               (eeprom_data & 0x0FF0) >> 4,
-               eeprom_data & 0x000F);
-
+       /*
+        * EEPROM image version # is reported as firmware version # for
+        * 82575 controllers
+        */
+       strlcpy(drvinfo->fw_version, adapter->fw_version,
+               sizeof(drvinfo->fw_version));
        strlcpy(drvinfo->bus_info, pci_name(adapter->pdev),
                sizeof(drvinfo->bus_info));
        drvinfo->n_stats = IGB_STATS_LEN;
index a7c9c5d..1e0b94b 100644 (file)
@@ -1815,6 +1815,69 @@ static const struct net_device_ops igb_netdev_ops = {
        .ndo_set_features       = igb_set_features,
 };
 
+/**
+ * igb_set_fw_version - Configure version string for ethtool
+ * @adapter: adapter struct
+ *
+ **/
+void igb_set_fw_version(struct igb_adapter *adapter)
+{
+       struct e1000_hw *hw = &adapter->hw;
+       u16 eeprom_verh, eeprom_verl, comb_verh, comb_verl, comb_offset;
+       u16 major, build, patch, fw_version;
+       u32 etrack_id;
+
+       hw->nvm.ops.read(hw, 5, 1, &fw_version);
+       if (adapter->hw.mac.type != e1000_i211) {
+               hw->nvm.ops.read(hw, NVM_ETRACK_WORD, 1, &eeprom_verh);
+               hw->nvm.ops.read(hw, (NVM_ETRACK_WORD + 1), 1, &eeprom_verl);
+               etrack_id = (eeprom_verh << IGB_ETRACK_SHIFT) | eeprom_verl;
+
+               /* combo image version needs to be found */
+               hw->nvm.ops.read(hw, NVM_COMB_VER_PTR, 1, &comb_offset);
+               if ((comb_offset != 0x0) &&
+                   (comb_offset != IGB_NVM_VER_INVALID)) {
+                       hw->nvm.ops.read(hw, (NVM_COMB_VER_OFF + comb_offset
+                                        + 1), 1, &comb_verh);
+                       hw->nvm.ops.read(hw, (NVM_COMB_VER_OFF + comb_offset),
+                                        1, &comb_verl);
+
+                       /* Only display Option Rom if it exists and is valid */
+                       if ((comb_verh && comb_verl) &&
+                           ((comb_verh != IGB_NVM_VER_INVALID) &&
+                            (comb_verl != IGB_NVM_VER_INVALID))) {
+                               major = comb_verl >> IGB_COMB_VER_SHFT;
+                               build = (comb_verl << IGB_COMB_VER_SHFT) |
+                                       (comb_verh >> IGB_COMB_VER_SHFT);
+                               patch = comb_verh & IGB_COMB_VER_MASK;
+                               snprintf(adapter->fw_version,
+                                        sizeof(adapter->fw_version),
+                                        "%d.%d%d, 0x%08x, %d.%d.%d",
+                                        (fw_version & IGB_MAJOR_MASK) >>
+                                        IGB_MAJOR_SHIFT,
+                                        (fw_version & IGB_MINOR_MASK) >>
+                                        IGB_MINOR_SHIFT,
+                                        (fw_version & IGB_BUILD_MASK),
+                                        etrack_id, major, build, patch);
+                               goto out;
+                       }
+               }
+               snprintf(adapter->fw_version, sizeof(adapter->fw_version),
+                        "%d.%d%d, 0x%08x",
+                        (fw_version & IGB_MAJOR_MASK) >> IGB_MAJOR_SHIFT,
+                        (fw_version & IGB_MINOR_MASK) >> IGB_MINOR_SHIFT,
+                        (fw_version & IGB_BUILD_MASK), etrack_id);
+       } else {
+               snprintf(adapter->fw_version, sizeof(adapter->fw_version),
+                        "%d.%d%d",
+                        (fw_version & IGB_MAJOR_MASK) >> IGB_MAJOR_SHIFT,
+                        (fw_version & IGB_MINOR_MASK) >> IGB_MINOR_SHIFT,
+                        (fw_version & IGB_BUILD_MASK));
+       }
+out:
+       return;
+}
+
 /**
  * igb_probe - Device Initialization Routine
  * @pdev: PCI device information struct
@@ -2025,6 +2088,9 @@ static int __devinit igb_probe(struct pci_dev *pdev,
                goto err_eeprom;
        }
 
+       /* get firmware version for ethtool -i */
+       igb_set_fw_version(adapter);
+
        setup_timer(&adapter->watchdog_timer, igb_watchdog,
                    (unsigned long) adapter);
        setup_timer(&adapter->phy_info_timer, igb_update_phy_info,