Commit a4b6fc6b authored by Emil Tantilov's avatar Emil Tantilov Committed by Jeff Kirsher

ixgbe: fix SFF data dumps of SFP+ modules

This patch fixes several issues with the previous implementation of the
SFF data dump of SFP+ modules:

- removed the __IXGBE_READ_I2C flag - I2C access locking is handled in the
  HW specific routines

- fixed the read loop to read data from ee->offset to ee->len

- the reads fail if __IXGBE_IN_SFP_INIT is set in the process - this is
  needed because on some HW I2C operations can take long time and disrupt
  the SFP and link detection process
Signed-off-by: default avatarEmil Tantilov <emil.s.tantilov@intel.com>
Reported-by: default avatarBen Hutchings <bhutchings@solarflare.com>
Tested-by: default avatarPhil Schmitt <phillip.j.schmitt@intel.com>
Signed-off-by: default avatarJeff Kirsher <jeffrey.t.kirsher@intel.com>
parent 3dcc2f41
...@@ -754,7 +754,6 @@ enum ixgbe_state_t { ...@@ -754,7 +754,6 @@ enum ixgbe_state_t {
__IXGBE_DOWN, __IXGBE_DOWN,
__IXGBE_SERVICE_SCHED, __IXGBE_SERVICE_SCHED,
__IXGBE_IN_SFP_INIT, __IXGBE_IN_SFP_INIT,
__IXGBE_READ_I2C,
}; };
struct ixgbe_cb { struct ixgbe_cb {
......
...@@ -2910,33 +2910,21 @@ static int ixgbe_get_module_info(struct net_device *dev, ...@@ -2910,33 +2910,21 @@ static int ixgbe_get_module_info(struct net_device *dev,
struct ixgbe_hw *hw = &adapter->hw; struct ixgbe_hw *hw = &adapter->hw;
u32 status; u32 status;
u8 sff8472_rev, addr_mode; u8 sff8472_rev, addr_mode;
int ret_val = 0;
bool page_swap = false; bool page_swap = false;
/* avoid concurent i2c reads */
while (test_bit(__IXGBE_IN_SFP_INIT, &adapter->state))
msleep(100);
/* used by the service task */
set_bit(__IXGBE_READ_I2C, &adapter->state);
/* Check whether we support SFF-8472 or not */ /* Check whether we support SFF-8472 or not */
status = hw->phy.ops.read_i2c_eeprom(hw, status = hw->phy.ops.read_i2c_eeprom(hw,
IXGBE_SFF_SFF_8472_COMP, IXGBE_SFF_SFF_8472_COMP,
&sff8472_rev); &sff8472_rev);
if (status != 0) { if (status != 0)
ret_val = -EIO; return -EIO;
goto err_out;
}
/* addressing mode is not supported */ /* addressing mode is not supported */
status = hw->phy.ops.read_i2c_eeprom(hw, status = hw->phy.ops.read_i2c_eeprom(hw,
IXGBE_SFF_SFF_8472_SWAP, IXGBE_SFF_SFF_8472_SWAP,
&addr_mode); &addr_mode);
if (status != 0) { if (status != 0)
ret_val = -EIO; return -EIO;
goto err_out;
}
if (addr_mode & IXGBE_SFF_ADDRESSING_MODE) { if (addr_mode & IXGBE_SFF_ADDRESSING_MODE) {
e_err(drv, "Address change required to access page 0xA2, but not supported. Please report the module type to the driver maintainers.\n"); e_err(drv, "Address change required to access page 0xA2, but not supported. Please report the module type to the driver maintainers.\n");
...@@ -2953,9 +2941,7 @@ static int ixgbe_get_module_info(struct net_device *dev, ...@@ -2953,9 +2941,7 @@ static int ixgbe_get_module_info(struct net_device *dev,
modinfo->eeprom_len = ETH_MODULE_SFF_8472_LEN; modinfo->eeprom_len = ETH_MODULE_SFF_8472_LEN;
} }
err_out: return 0;
clear_bit(__IXGBE_READ_I2C, &adapter->state);
return ret_val;
} }
static int ixgbe_get_module_eeprom(struct net_device *dev, static int ixgbe_get_module_eeprom(struct net_device *dev,
...@@ -2969,48 +2955,25 @@ static int ixgbe_get_module_eeprom(struct net_device *dev, ...@@ -2969,48 +2955,25 @@ static int ixgbe_get_module_eeprom(struct net_device *dev,
int i = 0; int i = 0;
int ret_val = 0; int ret_val = 0;
/* ixgbe_get_module_info is called before this function in all if (ee->len == 0)
* cases, so we do not need any checks we already do above, return -EINVAL;
* and can trust ee->len to be a known value.
*/
while (test_bit(__IXGBE_IN_SFP_INIT, &adapter->state)) for (i = ee->offset; i < ee->len; i++) {
msleep(100); /* I2C reads can take long time */
set_bit(__IXGBE_READ_I2C, &adapter->state); if (test_bit(__IXGBE_IN_SFP_INIT, &adapter->state))
return -EBUSY;
/* Read the first block, SFF-8079 */ if (i < ETH_MODULE_SFF_8079_LEN)
for (i = 0; i < ETH_MODULE_SFF_8079_LEN; i++) { status = hw->phy.ops.read_i2c_eeprom(hw, i, &databyte);
status = hw->phy.ops.read_i2c_eeprom(hw, i, &databyte); else
if (status != 0) { status = hw->phy.ops.read_i2c_sff8472(hw, i, &databyte);
/* Error occured while reading module */
if (status != 0)
ret_val = -EIO; ret_val = -EIO;
goto err_out;
}
data[i] = databyte;
}
/* If the second block is requested, check if SFF-8472 is supported. */ data[i - ee->offset] = databyte;
if (ee->len == ETH_MODULE_SFF_8472_LEN) {
if (data[IXGBE_SFF_SFF_8472_COMP] == IXGBE_SFF_SFF_8472_UNSUP)
return -EOPNOTSUPP;
/* Read the second block, SFF-8472 */
for (i = ETH_MODULE_SFF_8079_LEN;
i < ETH_MODULE_SFF_8472_LEN; i++) {
status = hw->phy.ops.read_i2c_sff8472(hw,
i - ETH_MODULE_SFF_8079_LEN, &databyte);
if (status != 0) {
/* Error occured while reading module */
ret_val = -EIO;
goto err_out;
}
data[i] = databyte;
}
} }
err_out:
clear_bit(__IXGBE_READ_I2C, &adapter->state);
return ret_val; return ret_val;
} }
......
...@@ -5832,10 +5832,6 @@ static void ixgbe_sfp_detection_subtask(struct ixgbe_adapter *adapter) ...@@ -5832,10 +5832,6 @@ static void ixgbe_sfp_detection_subtask(struct ixgbe_adapter *adapter)
!(adapter->flags2 & IXGBE_FLAG2_SFP_NEEDS_RESET)) !(adapter->flags2 & IXGBE_FLAG2_SFP_NEEDS_RESET))
return; return;
/* concurent i2c reads are not supported */
if (test_bit(__IXGBE_READ_I2C, &adapter->state))
return;
/* someone else is in init, wait until next service event */ /* someone else is in init, wait until next service event */
if (test_and_set_bit(__IXGBE_IN_SFP_INIT, &adapter->state)) if (test_and_set_bit(__IXGBE_IN_SFP_INIT, &adapter->state))
return; return;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment