Merge branch 'ionic-support-qsfp-cmis'

Shannon Nelson says:

====================
ionic: support QSFP CMIS

This patchset sets up support for additional pages and better
handling of the QSFP CMIS data.

v1: https://lore.kernel.org/netdev/20250411182140.63158-1-shannon.nelson@amd.com/
====================

Link: https://patch.msgid.link/20250415231317.40616-1-shannon.nelson@amd.com
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
This commit is contained in:
Paolo Abeni 2025-04-22 12:27:32 +02:00
commit a86aa9c247
2 changed files with 63 additions and 53 deletions

View File

@ -948,64 +948,20 @@ static int ionic_get_tunable(struct net_device *netdev,
return 0;
}
static int ionic_get_module_info(struct net_device *netdev,
struct ethtool_modinfo *modinfo)
static int ionic_do_module_copy(u8 *dst, u8 *src, u32 len)
{
struct ionic_lif *lif = netdev_priv(netdev);
struct ionic_dev *idev = &lif->ionic->idev;
struct ionic_xcvr_status *xcvr;
struct sfp_eeprom_base *sfp;
xcvr = &idev->port_info->status.xcvr;
sfp = (struct sfp_eeprom_base *) xcvr->sprom;
/* report the module data type and length */
switch (sfp->phys_id) {
case SFF8024_ID_SFP:
modinfo->type = ETH_MODULE_SFF_8079;
modinfo->eeprom_len = ETH_MODULE_SFF_8079_LEN;
break;
case SFF8024_ID_QSFP_8436_8636:
case SFF8024_ID_QSFP28_8636:
case SFF8024_ID_QSFP_PLUS_CMIS:
modinfo->type = ETH_MODULE_SFF_8436;
modinfo->eeprom_len = ETH_MODULE_SFF_8436_LEN;
break;
default:
netdev_info(netdev, "unknown xcvr type 0x%02x\n",
xcvr->sprom[0]);
modinfo->type = 0;
modinfo->eeprom_len = ETH_MODULE_SFF_8079_LEN;
break;
}
return 0;
}
static int ionic_get_module_eeprom(struct net_device *netdev,
struct ethtool_eeprom *ee,
u8 *data)
{
struct ionic_lif *lif = netdev_priv(netdev);
struct ionic_dev *idev = &lif->ionic->idev;
struct ionic_xcvr_status *xcvr;
char tbuf[sizeof(xcvr->sprom)];
char tbuf[sizeof_field(struct ionic_xcvr_status, sprom)];
int count = 10;
u32 len;
/* The NIC keeps the module prom up-to-date in the DMA space
* so we can simply copy the module bytes into the data buffer.
*/
xcvr = &idev->port_info->status.xcvr;
len = min_t(u32, sizeof(xcvr->sprom), ee->len);
do {
memcpy(data, &xcvr->sprom[ee->offset], len);
memcpy(tbuf, &xcvr->sprom[ee->offset], len);
memcpy(dst, src, len);
memcpy(tbuf, src, len);
/* Let's make sure we got a consistent copy */
if (!memcmp(data, tbuf, len))
if (!memcmp(dst, tbuf, len))
break;
} while (--count);
@ -1016,6 +972,48 @@ static int ionic_get_module_eeprom(struct net_device *netdev,
return 0;
}
static int ionic_get_module_eeprom_by_page(struct net_device *netdev,
const struct ethtool_module_eeprom *page_data,
struct netlink_ext_ack *extack)
{
struct ionic_lif *lif = netdev_priv(netdev);
struct ionic_dev *idev = &lif->ionic->idev;
u32 err = -EINVAL;
u8 *src;
if (!page_data->length)
return -EINVAL;
if (page_data->bank != 0) {
NL_SET_ERR_MSG_MOD(extack, "Only bank 0 is supported");
return -EINVAL;
}
switch (page_data->page) {
case 0:
src = &idev->port_info->status.xcvr.sprom[page_data->offset];
break;
case 1:
src = &idev->port_info->sprom_page1[page_data->offset - 128];
break;
case 2:
src = &idev->port_info->sprom_page2[page_data->offset - 128];
break;
case 17:
src = &idev->port_info->sprom_page17[page_data->offset - 128];
break;
default:
return -EOPNOTSUPP;
}
memset(page_data->data, 0, page_data->length);
err = ionic_do_module_copy(page_data->data, src, page_data->length);
if (err)
return err;
return page_data->length;
}
static int ionic_get_ts_info(struct net_device *netdev,
struct kernel_ethtool_ts_info *info)
{
@ -1161,8 +1159,7 @@ static const struct ethtool_ops ionic_ethtool_ops = {
.set_rxfh = ionic_set_rxfh,
.get_tunable = ionic_get_tunable,
.set_tunable = ionic_set_tunable,
.get_module_info = ionic_get_module_info,
.get_module_eeprom = ionic_get_module_eeprom,
.get_module_eeprom_by_page = ionic_get_module_eeprom_by_page,
.get_pauseparam = ionic_get_pauseparam,
.set_pauseparam = ionic_set_pauseparam,
.get_fecparam = ionic_get_fecparam,

View File

@ -2839,6 +2839,10 @@ union ionic_port_identity {
* @status: Port status data
* @stats: Port statistics data
* @mgmt_stats: Port management statistics data
* @sprom_epage: Extended Transceiver sprom
* @sprom_page1: Extended Transceiver sprom, page 1
* @sprom_page2: Extended Transceiver sprom, page 2
* @sprom_page17: Extended Transceiver sprom, page 17
* @rsvd: reserved byte(s)
* @pb_stats: uplink pb drop stats
*/
@ -2849,8 +2853,17 @@ struct ionic_port_info {
struct ionic_port_stats stats;
struct ionic_mgmt_port_stats mgmt_stats;
};
/* room for pb_stats to start at 2k offset */
u8 rsvd[760];
union {
u8 sprom_epage[384];
struct {
u8 sprom_page1[128];
u8 sprom_page2[128];
u8 sprom_page17[128];
};
};
u8 rsvd[376];
/* pb_stats must start at 2k offset */
struct ionic_port_pb_stats pb_stats;
};