ice: Reimplement module reads used by ethtool
There was an excessive increment of the QSFP page, which is now fixed. Additionally, this new update now reads 8 bytes at a time and will retry each request if the module/bus is busy. Also, prevent reading from upper pages if module does not support those pages. Signed-off-by: Scott W Taylor <scott.w.taylor@intel.com> Tested-by: Tony Brelinski <tonyx.brelinski@intel.com> Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
This commit is contained in:
parent
d59684a07e
commit
e9c9692c8a
1 changed files with 39 additions and 10 deletions
|
@ -3914,30 +3914,33 @@ ice_get_module_eeprom(struct net_device *netdev,
|
||||||
struct ethtool_eeprom *ee, u8 *data)
|
struct ethtool_eeprom *ee, u8 *data)
|
||||||
{
|
{
|
||||||
struct ice_netdev_priv *np = netdev_priv(netdev);
|
struct ice_netdev_priv *np = netdev_priv(netdev);
|
||||||
|
#define SFF_READ_BLOCK_SIZE 8
|
||||||
|
u8 value[SFF_READ_BLOCK_SIZE] = { 0 };
|
||||||
u8 addr = ICE_I2C_EEPROM_DEV_ADDR;
|
u8 addr = ICE_I2C_EEPROM_DEV_ADDR;
|
||||||
struct ice_vsi *vsi = np->vsi;
|
struct ice_vsi *vsi = np->vsi;
|
||||||
struct ice_pf *pf = vsi->back;
|
struct ice_pf *pf = vsi->back;
|
||||||
struct ice_hw *hw = &pf->hw;
|
struct ice_hw *hw = &pf->hw;
|
||||||
enum ice_status status;
|
enum ice_status status;
|
||||||
bool is_sfp = false;
|
bool is_sfp = false;
|
||||||
unsigned int i;
|
unsigned int i, j;
|
||||||
u16 offset = 0;
|
u16 offset = 0;
|
||||||
u8 value = 0;
|
|
||||||
u8 page = 0;
|
u8 page = 0;
|
||||||
|
|
||||||
if (!ee || !ee->len || !data)
|
if (!ee || !ee->len || !data)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
status = ice_aq_sff_eeprom(hw, 0, addr, offset, page, 0, &value, 1, 0,
|
status = ice_aq_sff_eeprom(hw, 0, addr, offset, page, 0, value, 1, 0,
|
||||||
NULL);
|
NULL);
|
||||||
if (status)
|
if (status)
|
||||||
return -EIO;
|
return -EIO;
|
||||||
|
|
||||||
if (value == ICE_MODULE_TYPE_SFP)
|
if (value[0] == ICE_MODULE_TYPE_SFP)
|
||||||
is_sfp = true;
|
is_sfp = true;
|
||||||
|
|
||||||
for (i = 0; i < ee->len; i++) {
|
memset(data, 0, ee->len);
|
||||||
|
for (i = 0; i < ee->len; i += SFF_READ_BLOCK_SIZE) {
|
||||||
offset = i + ee->offset;
|
offset = i + ee->offset;
|
||||||
|
page = 0;
|
||||||
|
|
||||||
/* Check if we need to access the other memory page */
|
/* Check if we need to access the other memory page */
|
||||||
if (is_sfp) {
|
if (is_sfp) {
|
||||||
|
@ -3953,11 +3956,37 @@ ice_get_module_eeprom(struct net_device *netdev,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
status = ice_aq_sff_eeprom(hw, 0, addr, offset, page, !is_sfp,
|
/* Bit 2 of EEPROM address 0x02 declares upper
|
||||||
&value, 1, 0, NULL);
|
* pages are disabled on QSFP modules.
|
||||||
if (status)
|
* SFP modules only ever use page 0.
|
||||||
value = 0;
|
*/
|
||||||
data[i] = value;
|
if (page == 0 || !(data[0x2] & 0x4)) {
|
||||||
|
/* If i2c bus is busy due to slow page change or
|
||||||
|
* link management access, call can fail. This is normal.
|
||||||
|
* So we retry this a few times.
|
||||||
|
*/
|
||||||
|
for (j = 0; j < 4; j++) {
|
||||||
|
status = ice_aq_sff_eeprom(hw, 0, addr, offset, page,
|
||||||
|
!is_sfp, value,
|
||||||
|
SFF_READ_BLOCK_SIZE,
|
||||||
|
0, NULL);
|
||||||
|
netdev_dbg(netdev, "SFF %02X %02X %02X %X = %02X%02X%02X%02X.%02X%02X%02X%02X (%X)\n",
|
||||||
|
addr, offset, page, is_sfp,
|
||||||
|
value[0], value[1], value[2], value[3],
|
||||||
|
value[4], value[5], value[6], value[7],
|
||||||
|
status);
|
||||||
|
if (status) {
|
||||||
|
usleep_range(1500, 2500);
|
||||||
|
memset(value, 0, SFF_READ_BLOCK_SIZE);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Make sure we have enough room for the new block */
|
||||||
|
if ((i + SFF_READ_BLOCK_SIZE) < ee->len)
|
||||||
|
memcpy(data + i, value, SFF_READ_BLOCK_SIZE);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue