ixgbe: Check return value on eeprom reads
authorMark Rustad <mark.d.rustad@intel.com>
Fri, 24 May 2013 07:31:09 +0000 (07:31 +0000)
committerJeff Kirsher <jeffrey.t.kirsher@intel.com>
Thu, 29 Aug 2013 09:45:38 +0000 (02:45 -0700)
This patch fixes the possible use of uninitialized memory by checking the
return value on eeprom reads. These issues were identified by static
analysis. In many cases error messages will be produced so that corrupted
eeprom issues will be more visible.

Signed-off-by: Mark Rustad <mark.d.rustad@intel.com>
Tested-by: Phil Schmitt <phillip.j.schmitt@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
drivers/net/ethernet/intel/ixgbe/ixgbe_82599.c
drivers/net/ethernet/intel/ixgbe/ixgbe_common.c
drivers/net/ethernet/intel/ixgbe/ixgbe_common.h
drivers/net/ethernet/intel/ixgbe/ixgbe_phy.c

index 51ee8ad44687927e783e4c2ed147a1f08037f0a7..e4f4f4b1878524751bdfe5a4b6fa342c4a04a02b 100644 (file)
@@ -142,11 +142,13 @@ static s32 ixgbe_setup_sfp_modules_82599(struct ixgbe_hw *hw)
                        goto setup_sfp_out;
                }
 
-               hw->eeprom.ops.read(hw, ++data_offset, &data_value);
+               if (hw->eeprom.ops.read(hw, ++data_offset, &data_value))
+                       goto setup_sfp_err;
                while (data_value != 0xffff) {
                        IXGBE_WRITE_REG(hw, IXGBE_CORECTL, data_value);
                        IXGBE_WRITE_FLUSH(hw);
-                       hw->eeprom.ops.read(hw, ++data_offset, &data_value);
+                       if (hw->eeprom.ops.read(hw, ++data_offset, &data_value))
+                               goto setup_sfp_err;
                }
 
                /* Release the semaphore */
@@ -192,6 +194,17 @@ static s32 ixgbe_setup_sfp_modules_82599(struct ixgbe_hw *hw)
 
 setup_sfp_out:
        return ret_val;
+
+setup_sfp_err:
+       /* Release the semaphore */
+       hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_MAC_CSR_SM);
+       /* Delay obtaining semaphore again to allow FW access,
+        * semaphore_delay is in ms usleep_range needs us.
+        */
+       usleep_range(hw->eeprom.semaphore_delay * 1000,
+                    hw->eeprom.semaphore_delay * 2000);
+       hw_err(hw, "eeprom read at offset %d failed\n", data_offset);
+       return IXGBE_ERR_SFP_SETUP_NOT_COMPLETE;
 }
 
 static s32 ixgbe_get_invariants_82599(struct ixgbe_hw *hw)
@@ -2180,6 +2193,7 @@ static s32 ixgbe_verify_fw_version_82599(struct ixgbe_hw *hw)
 {
        s32 status = IXGBE_ERR_EEPROM_VERSION;
        u16 fw_offset, fw_ptp_cfg_offset;
+       u16 offset;
        u16 fw_version = 0;
 
        /* firmware check is only necessary for SFI devices */
@@ -2189,29 +2203,35 @@ static s32 ixgbe_verify_fw_version_82599(struct ixgbe_hw *hw)
        }
 
        /* get the offset to the Firmware Module block */
-       hw->eeprom.ops.read(hw, IXGBE_FW_PTR, &fw_offset);
+       offset = IXGBE_FW_PTR;
+       if (hw->eeprom.ops.read(hw, offset, &fw_offset))
+               goto fw_version_err;
 
        if ((fw_offset == 0) || (fw_offset == 0xFFFF))
                goto fw_version_out;
 
        /* get the offset to the Pass Through Patch Configuration block */
-       hw->eeprom.ops.read(hw, (fw_offset +
-                                IXGBE_FW_PASSTHROUGH_PATCH_CONFIG_PTR),
-                                &fw_ptp_cfg_offset);
+       offset = fw_offset + IXGBE_FW_PASSTHROUGH_PATCH_CONFIG_PTR;
+       if (hw->eeprom.ops.read(hw, offset, &fw_ptp_cfg_offset))
+               goto fw_version_err;
 
        if ((fw_ptp_cfg_offset == 0) || (fw_ptp_cfg_offset == 0xFFFF))
                goto fw_version_out;
 
        /* get the firmware version */
-       hw->eeprom.ops.read(hw, (fw_ptp_cfg_offset +
-                                IXGBE_FW_PATCH_VERSION_4),
-                                &fw_version);
+       offset = fw_ptp_cfg_offset + IXGBE_FW_PATCH_VERSION_4;
+       if (hw->eeprom.ops.read(hw, offset, &fw_version))
+               goto fw_version_err;
 
        if (fw_version > 0x5)
                status = 0;
 
 fw_version_out:
        return status;
+
+fw_version_err:
+       hw_err(hw, "eeprom read at offset %d failed\n", offset);
+       return IXGBE_ERR_EEPROM_VERSION;
 }
 
 /**
index 50e62a2b1a65f905709c9ffffdff66fa8273a296..b5c434b617b129411abe676efef64f259ffc6518 100644 (file)
@@ -2740,13 +2740,19 @@ out:
 static s32 ixgbe_get_san_mac_addr_offset(struct ixgbe_hw *hw,
                                         u16 *san_mac_offset)
 {
+       s32 ret_val;
+
        /*
         * First read the EEPROM pointer to see if the MAC addresses are
         * available.
         */
-       hw->eeprom.ops.read(hw, IXGBE_SAN_MAC_ADDR_PTR, san_mac_offset);
+       ret_val = hw->eeprom.ops.read(hw, IXGBE_SAN_MAC_ADDR_PTR,
+                                     san_mac_offset);
+       if (ret_val)
+               hw_err(hw, "eeprom read at offset %d failed\n",
+                      IXGBE_SAN_MAC_ADDR_PTR);
 
-       return 0;
+       return ret_val;
 }
 
 /**
@@ -2763,23 +2769,16 @@ s32 ixgbe_get_san_mac_addr_generic(struct ixgbe_hw *hw, u8 *san_mac_addr)
 {
        u16 san_mac_data, san_mac_offset;
        u8 i;
+       s32 ret_val;
 
        /*
         * First read the EEPROM pointer to see if the MAC addresses are
         * available.  If they're not, no point in calling set_lan_id() here.
         */
-       ixgbe_get_san_mac_addr_offset(hw, &san_mac_offset);
+       ret_val = ixgbe_get_san_mac_addr_offset(hw, &san_mac_offset);
+       if (ret_val || san_mac_offset == 0 || san_mac_offset == 0xFFFF)
 
-       if ((san_mac_offset == 0) || (san_mac_offset == 0xFFFF)) {
-               /*
-                * No addresses available in this EEPROM.  It's not an
-                * error though, so just wipe the local address and return.
-                */
-               for (i = 0; i < 6; i++)
-                       san_mac_addr[i] = 0xFF;
-
-               goto san_mac_addr_out;
-       }
+               goto san_mac_addr_clr;
 
        /* make sure we know which port we need to program */
        hw->mac.ops.set_lan_id(hw);
@@ -2787,14 +2786,26 @@ s32 ixgbe_get_san_mac_addr_generic(struct ixgbe_hw *hw, u8 *san_mac_addr)
        (hw->bus.func) ? (san_mac_offset += IXGBE_SAN_MAC_ADDR_PORT1_OFFSET) :
                         (san_mac_offset += IXGBE_SAN_MAC_ADDR_PORT0_OFFSET);
        for (i = 0; i < 3; i++) {
-               hw->eeprom.ops.read(hw, san_mac_offset, &san_mac_data);
+               ret_val = hw->eeprom.ops.read(hw, san_mac_offset,
+                                             &san_mac_data);
+               if (ret_val) {
+                       hw_err(hw, "eeprom read at offset %d failed\n",
+                              san_mac_offset);
+                       goto san_mac_addr_clr;
+               }
                san_mac_addr[i * 2] = (u8)(san_mac_data);
                san_mac_addr[i * 2 + 1] = (u8)(san_mac_data >> 8);
                san_mac_offset++;
        }
-
-san_mac_addr_out:
        return 0;
+
+san_mac_addr_clr:
+       /* No addresses available in this EEPROM.  It's not necessarily an
+        * error though, so just wipe the local address and return.
+        */
+       for (i = 0; i < 6; i++)
+               san_mac_addr[i] = 0xFF;
+       return ret_val;
 }
 
 /**
@@ -3243,8 +3254,9 @@ s32 ixgbe_get_wwn_prefix_generic(struct ixgbe_hw *hw, u16 *wwnn_prefix,
        *wwpn_prefix = 0xFFFF;
 
        /* check if alternative SAN MAC is supported */
-       hw->eeprom.ops.read(hw, IXGBE_ALT_SAN_MAC_ADDR_BLK_PTR,
-                           &alt_san_mac_blk_offset);
+       offset = IXGBE_ALT_SAN_MAC_ADDR_BLK_PTR;
+       if (hw->eeprom.ops.read(hw, offset, &alt_san_mac_blk_offset))
+               goto wwn_prefix_err;
 
        if ((alt_san_mac_blk_offset == 0) ||
            (alt_san_mac_blk_offset == 0xFFFF))
@@ -3252,19 +3264,26 @@ s32 ixgbe_get_wwn_prefix_generic(struct ixgbe_hw *hw, u16 *wwnn_prefix,
 
        /* check capability in alternative san mac address block */
        offset = alt_san_mac_blk_offset + IXGBE_ALT_SAN_MAC_ADDR_CAPS_OFFSET;
-       hw->eeprom.ops.read(hw, offset, &caps);
+       if (hw->eeprom.ops.read(hw, offset, &caps))
+               goto wwn_prefix_err;
        if (!(caps & IXGBE_ALT_SAN_MAC_ADDR_CAPS_ALTWWN))
                goto wwn_prefix_out;
 
        /* get the corresponding prefix for WWNN/WWPN */
        offset = alt_san_mac_blk_offset + IXGBE_ALT_SAN_MAC_ADDR_WWNN_OFFSET;
-       hw->eeprom.ops.read(hw, offset, wwnn_prefix);
+       if (hw->eeprom.ops.read(hw, offset, wwnn_prefix))
+               hw_err(hw, "eeprom read at offset %d failed\n", offset);
 
        offset = alt_san_mac_blk_offset + IXGBE_ALT_SAN_MAC_ADDR_WWPN_OFFSET;
-       hw->eeprom.ops.read(hw, offset, wwpn_prefix);
+       if (hw->eeprom.ops.read(hw, offset, wwpn_prefix))
+               goto wwn_prefix_err;
 
 wwn_prefix_out:
        return 0;
+
+wwn_prefix_err:
+       hw_err(hw, "eeprom read at offset %d failed\n", offset);
+       return 0;
 }
 
 /**
@@ -3778,7 +3797,11 @@ s32 ixgbe_init_thermal_sensor_thresh_generic(struct ixgbe_hw *hw)
                u8  sensor_index;
                u8  sensor_location;
 
-               hw->eeprom.ops.read(hw, (ets_offset + 1 + i), &ets_sensor);
+               if (hw->eeprom.ops.read(hw, ets_offset + 1 + i, &ets_sensor)) {
+                       hw_err(hw, "eeprom read at offset %d failed\n",
+                              ets_offset + 1 + i);
+                       continue;
+               }
                sensor_index = ((ets_sensor & IXGBE_ETS_DATA_INDEX_MASK) >>
                                IXGBE_ETS_DATA_INDEX_SHIFT);
                sensor_location = ((ets_sensor & IXGBE_ETS_DATA_LOC_MASK) >>
index 1315b8ac7f586f9ef05b346aa070e847ac481f2a..d259dc76604ebd233d9df7a83b0ba01ed13faed2 100644 (file)
@@ -143,8 +143,12 @@ s32 ixgbe_init_thermal_sensor_thresh_generic(struct ixgbe_hw *hw);
 
 #define IXGBE_WRITE_FLUSH(a) IXGBE_READ_REG(a, IXGBE_STATUS)
 
+#define ixgbe_hw_to_netdev(hw) (((struct ixgbe_adapter *)(hw)->back)->netdev)
+
 #define hw_dbg(hw, format, arg...) \
-       netdev_dbg(((struct ixgbe_adapter *)(hw->back))->netdev, format, ##arg)
+       netdev_dbg(ixgbe_hw_to_netdev(hw), format, ## arg)
+#define hw_err(hw, format, arg...) \
+       netdev_err(ixgbe_hw_to_netdev(hw), format, ## arg)
 #define e_dev_info(format, arg...) \
        dev_info(&adapter->pdev->dev, format, ## arg)
 #define e_dev_warn(format, arg...) \
index 369eef526bc19f3d9e15809e9821ef13ae46afe9..6a4a7995d3e0316d101efd43268ace1623fee0bc 100644 (file)
@@ -791,6 +791,8 @@ s32 ixgbe_reset_phy_nl(struct ixgbe_hw *hw)
                 * Read control word from PHY init contents offset
                 */
                ret_val = hw->eeprom.ops.read(hw, data_offset, &eword);
+               if (ret_val)
+                       goto err_eeprom;
                control = (eword & IXGBE_CONTROL_MASK_NL) >>
                           IXGBE_CONTROL_SHIFT_NL;
                edata = eword & IXGBE_DATA_MASK_NL;
@@ -803,10 +805,15 @@ s32 ixgbe_reset_phy_nl(struct ixgbe_hw *hw)
                case IXGBE_DATA_NL:
                        hw_dbg(hw, "DATA:\n");
                        data_offset++;
-                       hw->eeprom.ops.read(hw, data_offset++,
-                                           &phy_offset);
+                       ret_val = hw->eeprom.ops.read(hw, data_offset++,
+                                                     &phy_offset);
+                       if (ret_val)
+                               goto err_eeprom;
                        for (i = 0; i < edata; i++) {
-                               hw->eeprom.ops.read(hw, data_offset, &eword);
+                               ret_val = hw->eeprom.ops.read(hw, data_offset,
+                                                             &eword);
+                               if (ret_val)
+                                       goto err_eeprom;
                                hw->phy.ops.write_reg(hw, phy_offset,
                                                      MDIO_MMD_PMAPMD, eword);
                                hw_dbg(hw, "Wrote %4.4x to %4.4x\n", eword,
@@ -838,6 +845,10 @@ s32 ixgbe_reset_phy_nl(struct ixgbe_hw *hw)
 
 out:
        return ret_val;
+
+err_eeprom:
+       hw_err(hw, "eeprom read at offset %d failed\n", data_offset);
+       return IXGBE_ERR_PHY;
 }
 
 /**
@@ -1339,7 +1350,11 @@ s32 ixgbe_get_sfp_init_sequence_offsets(struct ixgbe_hw *hw,
                sfp_type = ixgbe_sfp_type_srlr_core1;
 
        /* Read offset to PHY init contents */
-       hw->eeprom.ops.read(hw, IXGBE_PHY_INIT_OFFSET_NL, list_offset);
+       if (hw->eeprom.ops.read(hw, IXGBE_PHY_INIT_OFFSET_NL, list_offset)) {
+               hw_err(hw, "eeprom read at %d failed\n",
+                      IXGBE_PHY_INIT_OFFSET_NL);
+               return IXGBE_ERR_SFP_NO_INIT_SEQ_PRESENT;
+       }
 
        if ((!*list_offset) || (*list_offset == 0xFFFF))
                return IXGBE_ERR_SFP_NO_INIT_SEQ_PRESENT;
@@ -1351,12 +1366,14 @@ s32 ixgbe_get_sfp_init_sequence_offsets(struct ixgbe_hw *hw,
         * Find the matching SFP ID in the EEPROM
         * and program the init sequence
         */
-       hw->eeprom.ops.read(hw, *list_offset, &sfp_id);
+       if (hw->eeprom.ops.read(hw, *list_offset, &sfp_id))
+               goto err_phy;
 
        while (sfp_id != IXGBE_PHY_INIT_END_NL) {
                if (sfp_id == sfp_type) {
                        (*list_offset)++;
-                       hw->eeprom.ops.read(hw, *list_offset, data_offset);
+                       if (hw->eeprom.ops.read(hw, *list_offset, data_offset))
+                               goto err_phy;
                        if ((!*data_offset) || (*data_offset == 0xFFFF)) {
                                hw_dbg(hw, "SFP+ module not supported\n");
                                return IXGBE_ERR_SFP_NOT_SUPPORTED;
@@ -1366,7 +1383,7 @@ s32 ixgbe_get_sfp_init_sequence_offsets(struct ixgbe_hw *hw,
                } else {
                        (*list_offset) += 2;
                        if (hw->eeprom.ops.read(hw, *list_offset, &sfp_id))
-                               return IXGBE_ERR_PHY;
+                               goto err_phy;
                }
        }
 
@@ -1376,6 +1393,10 @@ s32 ixgbe_get_sfp_init_sequence_offsets(struct ixgbe_hw *hw,
        }
 
        return 0;
+
+err_phy:
+       hw_err(hw, "eeprom read at offset %d failed\n", *list_offset);
+       return IXGBE_ERR_PHY;
 }
 
 /**