Add capability to retrieve plug-in module EEPROM
Subsystems (3)
PATCH 3/3 Add capability to retrieve plug-in module EEPROM
Currently allows for SFP+ eeprom to be returned using the ethtool API. This can be extended in future to handle different eeprom formats and sizes
--- drivers/net/ethernet/sfc/ethtool.c | 35 ++++++++++ drivers/net/ethernet/sfc/mcdi_phy.c | 111 +++++++++++++++++++++++++++++++++ drivers/net/ethernet/sfc/net_driver.h | 5 ++ 3 files changed, 151 insertions(+), 0 deletions(-)
drivers/net/ethernet/sfc/ethtool.c +35 -0
@@ -1108,6 +1108,39 @@ static int efx_ethtool_set_rxfh_indir(struct net_device *net_dev,return 0 ; } +static int efx_ethtool_get_module_eeprom (struct net_device *net_dev, +struct ethtool_eeprom *ee, +u8 *data) +{ +struct efx_nic *efx =netdev_priv (net_dev); +int ret; + +if (!efx->phy_op || !efx->phy_op->get_module_eeprom) +return -EOPNOTSUPP ; + +mutex_lock (&efx->mac_lock); + ret = efx->phy_op->get_module_eeprom (efx, ee, data); +mutex_unlock (&efx->mac_lock); + +return ret; +} + +static int efx_ethtool_get_module_info (struct net_device *net_dev, +struct ethtool_modinfo *modinfo) +{ +struct efx_nic *efx =netdev_priv (net_dev); +int ret; + +if (!efx->phy_op || !efx->phy_op->get_module_info) +return 0 ; + +mutex_lock (&efx->mac_lock); + ret = efx->phy_op->get_module_info (efx, modinfo); +mutex_unlock (&efx->mac_lock); + +return ret; +} +const struct ethtool_ops efx_ethtool_ops = { .get_settings = efx_ethtool_get_settings, .set_settings = efx_ethtool_set_settings,
@@ -1137,4 +1170,6 @@ const struct ethtool_ops efx_ethtool_ops = { .get_rxfh_indir_size = efx_ethtool_get_rxfh_indir_size, .get_rxfh_indir = efx_ethtool_get_rxfh_indir, .set_rxfh_indir = efx_ethtool_set_rxfh_indir, + .get_module_info = efx_ethtool_get_module_info, + .get_module_eeprom = efx_ethtool_get_module_eeprom, };
drivers/net/ethernet/sfc/mcdi_phy.c +111 -0
127 lines not on this page · raw message
drivers/net/ethernet/sfc/net_driver.h +5 -0
@@ -522,6 +522,11 @@ struct efx_phy_operations {int (*test_alive) (struct efx_nic *efx);const char *(*test_name) (struct efx_nic *efx,unsigned int index);int (*run_tests) (struct efx_nic *efx,int *results,unsigned flags); +int (*get_module_eeprom) (struct efx_nic *efx, +struct ethtool_eeprom *ee, +u8 *data); +int (*get_module_info) (struct efx_nic *efx, +struct ethtool_modinfo *modinfo); };/**
Signature · 1 line
1.7.1
Quoted 3 lines · Stuart Hodgson
Currently allows for SFP+ eeprom to be returned using the ethtool API. This can be extended in future to handle different eeprom formats and sizes
[...]
Quoted 15 lines
drivers/net/ethernet/sfc/mcdi_phy.c +9
-0@@ -304,6 +304,26 @@ static u32 mcdi_to_ethtool_media(u32 media) } } +static u32 mcdi_to_module_eeprom_len (u32 media) +{ +switch (media) { +case MC_CMD_MEDIA_SFP_PLUS : +return ETH_MODULE_SFF_8079_LEN ; +default : +return 0 ; + } +}
drivers/net/ethernet/sfc/mcdi_phy.c static u32 mcdi_to_ethtool_media(u32 media) · line 325
Quoted 10 lines
drivers/net/ethernet/sfc/mcdi_phy.c +10
-0+ +static u32 mcdi_to_module_eeprom_type (u32 media) +{ +switch (media) { +case MC_CMD_MEDIA_SFP_PLUS : +return ETH_MODULE_SFF_8079 ; +default : +return 0 ; + } +}
These functions ended up unused, so don't add them. You should have got a compiler warning about this...
Quoted 16 lines
drivers/net/ethernet/sfc/mcdi_phy.c +9
-0static int efx_mcdi_phy_probe (struct efx_nic *efx) {struct efx_mcdi_phy_data *phy_data;@@ -739,6 +759,95 @@ static const char *efx_mcdi_phy_test_name(struct efx_nic *efx,return NULL ; } +#define SFP_PAGE_SIZE 128 +#define SFP_NUM_PAGES 2 +static int efx_mcdi_phy_get_module_eeprom (struct efx_nic *efx, +struct ethtool_eeprom *ee,u8 *data) +{ +u8 outbuf[MC_CMD_GET_PHY_MEDIA_INFO_OUT_LENMAX ]; +u8 inbuf[MC_CMD_GET_PHY_MEDIA_INFO_IN_LEN ]; +size_t outlen; +int rc;
drivers/net/ethernet/sfc/mcdi_phy.c static const char *efx_mcdi_phy_test_name(struct efx_nic *efx, · line 780
Quoted 10 lines
drivers/net/ethernet/sfc/mcdi_phy.c +10
-0+unsigned int payload_len; +unsigned int copied =0 ; +unsigned int space_remaining = ee->len; +unsigned int page; +unsigned int page_off; +unsigned int to_copy; +u8 *user_data = data; + +if (ee->offset > (SFP_PAGE_SIZE *SFP_NUM_PAGES )) +return -EINVAL ;
Please also add this sanity-check:
BUILD_BUG_ON(SFP_PAGE_SIZE * SFP_NUM_PAGES != ETH_MODULE_SFF_8079_LEN);
drivers/net/ethernet/sfc/mcdi_phy.c static const char *efx_mcdi_phy_test_name(struct efx_nic *efx, · line 783
Quoted 2 lines
drivers/net/ethernet/sfc/mcdi_phy.c +2
-0+ page_off = (ee->offset %SFP_PAGE_SIZE ); + page = (ee->offset >SFP_PAGE_SIZE ) ?1 :0 ;
Off-by-one error; the comparison should be >=. Why not use the straightforward calculation:
page = ee->offset / SFP_PAGE_SIZE;
[...]
Quoted 8 lines
drivers/net/ethernet/sfc/mcdi_phy.c +8
-0+static int efx_mcdi_phy_get_module_info (struct efx_nic *efx, +struct ethtool_modinfo *modinfo) +{ +/* This will return a length of the eeprom +* type of the module that was detected during the probe, +* if not modules inserted then phy_data will be NULL */ +struct efx_mcdi_phy_data *phy_cfg; +
drivers/net/ethernet/sfc/mcdi_phy.c static const char *efx_mcdi_phy_test_name(struct efx_nic *efx, · line 844
Quoted 10 lines
drivers/net/ethernet/sfc/mcdi_phy.c +10
-0+ phy_cfg = efx->phy_data; + modinfo->eeprom_len =0 ; + modinfo->type =0 ; + +switch (phy_cfg->media) { +case MC_CMD_MEDIA_SFP_PLUS : + modinfo->type =ETH_MODULE_SFF_8079 ; + modinfo->eeprom_len =ETH_MODULE_SFF_8079_LEN ; +break ; +default :
The default case should return -EOPNOTSUPP, just as if we didn't implement this operation at all. And there's no need to set modinfo->{type,eeprom_len} to 0 in that case.
Ben.
Quoted 5 lines
drivers/net/ethernet/sfc/mcdi_phy.c +5
-0+break ; + } + +return 0 ; +}
[...]
Signature · 3 lines
Ben Hutchings, Staff Engineer, Solarflare Not speaking for my employer; that's the marketing department's job. They asked us to note that Solarflare product names are trademarked.