Skip to content

Commit c51ab83

Browse files
emuslnPaolo Abeni
authored andcommitted
ionic: extend the QSFP module sprom for more pages
Some QSFP modules have more eeprom to be read by ethtool than the initial high and low page 0 that is currently available in the DSC's ionic sprom[] buffer. Since the current sprom[] is baked into the middle of an existing API struct, to make the high end of page 1 and page 2 available a block is carved from a reserved space of the existing port_info struct and the ionic_get_module_eeprom() service is taught how to get there. Newer firmware writes the additional QSFP page info here, yet this remains backward compatible because older firmware sets this space to all 0 and older ionic drivers do not use the reserved space. Reviewed-by: Brett Creeley <brett.creeley@amd.com> Signed-off-by: Shannon Nelson <shannon.nelson@amd.com> Reviewed-by: Simon Horman <horms@kernel.org> Link: https://patch.msgid.link/20250415231317.40616-2-shannon.nelson@amd.com Signed-off-by: Paolo Abeni <pabeni@redhat.com>
1 parent 30af0cb commit c51ab83

File tree

2 files changed

+56
-17
lines changed

2 files changed

+56
-17
lines changed

drivers/net/ethernet/pensando/ionic/ionic_ethtool.c

Lines changed: 51 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -968,10 +968,13 @@ static int ionic_get_module_info(struct net_device *netdev,
968968
break;
969969
case SFF8024_ID_QSFP_8436_8636:
970970
case SFF8024_ID_QSFP28_8636:
971-
case SFF8024_ID_QSFP_PLUS_CMIS:
972971
modinfo->type = ETH_MODULE_SFF_8436;
973972
modinfo->eeprom_len = ETH_MODULE_SFF_8436_LEN;
974973
break;
974+
case SFF8024_ID_QSFP_PLUS_CMIS:
975+
modinfo->type = ETH_MODULE_SFF_8472;
976+
modinfo->eeprom_len = ETH_MODULE_SFF_8472_LEN;
977+
break;
975978
default:
976979
netdev_info(netdev, "unknown xcvr type 0x%02x\n",
977980
xcvr->sprom[0]);
@@ -983,29 +986,20 @@ static int ionic_get_module_info(struct net_device *netdev,
983986
return 0;
984987
}
985988

986-
static int ionic_get_module_eeprom(struct net_device *netdev,
987-
struct ethtool_eeprom *ee,
988-
u8 *data)
989+
static int ionic_do_module_copy(u8 *dst, u8 *src, u32 len)
989990
{
990-
struct ionic_lif *lif = netdev_priv(netdev);
991-
struct ionic_dev *idev = &lif->ionic->idev;
992-
struct ionic_xcvr_status *xcvr;
993-
char tbuf[sizeof(xcvr->sprom)];
991+
char tbuf[sizeof_field(struct ionic_xcvr_status, sprom)];
994992
int count = 10;
995-
u32 len;
996993

997994
/* The NIC keeps the module prom up-to-date in the DMA space
998995
* so we can simply copy the module bytes into the data buffer.
999996
*/
1000-
xcvr = &idev->port_info->status.xcvr;
1001-
len = min_t(u32, sizeof(xcvr->sprom), ee->len);
1002-
1003997
do {
1004-
memcpy(data, &xcvr->sprom[ee->offset], len);
1005-
memcpy(tbuf, &xcvr->sprom[ee->offset], len);
998+
memcpy(dst, src, len);
999+
memcpy(tbuf, src, len);
10061000

10071001
/* Let's make sure we got a consistent copy */
1008-
if (!memcmp(data, tbuf, len))
1002+
if (!memcmp(dst, tbuf, len))
10091003
break;
10101004

10111005
} while (--count);
@@ -1016,6 +1010,48 @@ static int ionic_get_module_eeprom(struct net_device *netdev,
10161010
return 0;
10171011
}
10181012

1013+
static int ionic_get_module_eeprom(struct net_device *netdev,
1014+
struct ethtool_eeprom *ee,
1015+
u8 *data)
1016+
{
1017+
struct ionic_lif *lif = netdev_priv(netdev);
1018+
struct ionic_dev *idev = &lif->ionic->idev;
1019+
u32 start = ee->offset;
1020+
u32 err = -EINVAL;
1021+
u32 size = 0;
1022+
u8 *src;
1023+
1024+
if (start < ETH_MODULE_SFF_8079_LEN) {
1025+
if (start + ee->len > ETH_MODULE_SFF_8079_LEN)
1026+
size = ETH_MODULE_SFF_8079_LEN - start;
1027+
else
1028+
size = ee->len;
1029+
1030+
src = &idev->port_info->status.xcvr.sprom[start];
1031+
err = ionic_do_module_copy(data, src, size);
1032+
if (err)
1033+
return err;
1034+
1035+
data += size;
1036+
start += size;
1037+
}
1038+
1039+
if (start >= ETH_MODULE_SFF_8079_LEN &&
1040+
start < ETH_MODULE_SFF_8472_LEN) {
1041+
size = ee->len - size;
1042+
if (start + size > ETH_MODULE_SFF_8472_LEN)
1043+
size = ETH_MODULE_SFF_8472_LEN - start;
1044+
1045+
start -= ETH_MODULE_SFF_8079_LEN;
1046+
src = &idev->port_info->sprom_epage[start];
1047+
err = ionic_do_module_copy(data, src, size);
1048+
if (err)
1049+
return err;
1050+
}
1051+
1052+
return err;
1053+
}
1054+
10191055
static int ionic_get_ts_info(struct net_device *netdev,
10201056
struct kernel_ethtool_ts_info *info)
10211057
{

drivers/net/ethernet/pensando/ionic/ionic_if.h

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2839,6 +2839,7 @@ union ionic_port_identity {
28392839
* @status: Port status data
28402840
* @stats: Port statistics data
28412841
* @mgmt_stats: Port management statistics data
2842+
* @sprom_epage: Extended Transceiver sprom, high page 1 and 2
28422843
* @rsvd: reserved byte(s)
28432844
* @pb_stats: uplink pb drop stats
28442845
*/
@@ -2849,8 +2850,10 @@ struct ionic_port_info {
28492850
struct ionic_port_stats stats;
28502851
struct ionic_mgmt_port_stats mgmt_stats;
28512852
};
2852-
/* room for pb_stats to start at 2k offset */
2853-
u8 rsvd[760];
2853+
u8 sprom_epage[256];
2854+
u8 rsvd[504];
2855+
2856+
/* pb_stats must start at 2k offset */
28542857
struct ionic_port_pb_stats pb_stats;
28552858
};
28562859

0 commit comments

Comments
 (0)