mlxsw: core: Extend QSFP EEPROM size for ethtool
authorVadim Pasternak <vadimp@mellanox.com>
Mon, 21 Oct 2019 10:30:31 +0000 (13:30 +0300)
committerJakub Kicinski <jakub.kicinski@netronome.com>
Tue, 22 Oct 2019 17:30:41 +0000 (10:30 -0700)
Extend the size of QSFP EEPROM for the cable types SSF8436 and SFF8636
from 256 to 640 bytes in order to expose all the EEPROM pages by
ethtool.

For SFF-8636 and SFF-8436 specifications, the driver exposes 256 bytes
of data for ethtool's get_module_eeprom() callback. This is because the
driver uses the below defines to specify SFF module length in ethtool's
get_module_info() callback:
'ETH_MODULE_SFF_8636_LEN' and 'ETH_MODULE_SFF_8436_LEN' (both are 256).

As a result of exposing 256 bytes only, ethtool shows wrong "zero" info
for pages 1, 2, 3.

The patch changes the length returned by callback for get_module_info()
to the values from the next defines: 'ETH_MODULE_SFF_8636_MAX_LEN' and
'ETH_MODULE_SFF_8436_MAX_LEN' (both are 640) to allow exposing of upper
page 1, 2 and 3.

Signed-off-by: Vadim Pasternak <vadimp@mellanox.com>
Acked-by: Jiri Pirko <jiri@mellanox.com>
Signed-off-by: Ido Schimmel <idosch@mellanox.com>
Signed-off-by: Jakub Kicinski <jakub.kicinski@netronome.com>
drivers/net/ethernet/mellanox/mlxsw/core_env.c

index d2c7ce67c300d9e7e0846498c92795af49699dfc..08215fed193d309c64bf18286d2881afe4948527 100644 (file)
@@ -50,6 +50,7 @@ mlxsw_env_query_module_eeprom(struct mlxsw_core *mlxsw_core, int module,
        char eeprom_tmp[MLXSW_REG_MCIA_EEPROM_SIZE];
        char mcia_pl[MLXSW_REG_MCIA_LEN];
        u16 i2c_addr;
+       u8 page = 0;
        int status;
        int err;
 
@@ -62,11 +63,21 @@ mlxsw_env_query_module_eeprom(struct mlxsw_core *mlxsw_core, int module,
 
        i2c_addr = MLXSW_REG_MCIA_I2C_ADDR_LOW;
        if (offset >= MLXSW_REG_MCIA_EEPROM_PAGE_LENGTH) {
-               i2c_addr = MLXSW_REG_MCIA_I2C_ADDR_HIGH;
-               offset -= MLXSW_REG_MCIA_EEPROM_PAGE_LENGTH;
+               page = MLXSW_REG_MCIA_PAGE_GET(offset);
+               offset -= MLXSW_REG_MCIA_EEPROM_UP_PAGE_LENGTH * page;
+               /* When reading upper pages 1, 2 and 3 the offset starts at
+                * 128. Please refer to "QSFP+ Memory Map" figure in SFF-8436
+                * specification for graphical depiction.
+                * MCIA register accepts buffer size <= 48. Page of size 128
+                * should be read by chunks of size 48, 48, 32. Align the size
+                * of the last chunk to avoid reading after the end of the
+                * page.
+                */
+               if (offset + size > MLXSW_REG_MCIA_EEPROM_PAGE_LENGTH)
+                       size = MLXSW_REG_MCIA_EEPROM_PAGE_LENGTH - offset;
        }
 
-       mlxsw_reg_mcia_pack(mcia_pl, module, 0, 0, offset, size, i2c_addr);
+       mlxsw_reg_mcia_pack(mcia_pl, module, 0, page, offset, size, i2c_addr);
 
        err = mlxsw_reg_query(mlxsw_core, MLXSW_REG(mcia), mcia_pl);
        if (err)
@@ -168,7 +179,7 @@ int mlxsw_env_get_module_info(struct mlxsw_core *mlxsw_core, int module,
        switch (module_id) {
        case MLXSW_REG_MCIA_EEPROM_MODULE_INFO_ID_QSFP:
                modinfo->type       = ETH_MODULE_SFF_8436;
-               modinfo->eeprom_len = ETH_MODULE_SFF_8436_LEN;
+               modinfo->eeprom_len = ETH_MODULE_SFF_8436_MAX_LEN;
                break;
        case MLXSW_REG_MCIA_EEPROM_MODULE_INFO_ID_QSFP_PLUS: /* fall-through */
        case MLXSW_REG_MCIA_EEPROM_MODULE_INFO_ID_QSFP28:
@@ -176,10 +187,10 @@ int mlxsw_env_get_module_info(struct mlxsw_core *mlxsw_core, int module,
                    module_rev_id >=
                    MLXSW_REG_MCIA_EEPROM_MODULE_INFO_REV_ID_8636) {
                        modinfo->type       = ETH_MODULE_SFF_8636;
-                       modinfo->eeprom_len = ETH_MODULE_SFF_8636_LEN;
+                       modinfo->eeprom_len = ETH_MODULE_SFF_8636_MAX_LEN;
                } else {
                        modinfo->type       = ETH_MODULE_SFF_8436;
-                       modinfo->eeprom_len = ETH_MODULE_SFF_8436_LEN;
+                       modinfo->eeprom_len = ETH_MODULE_SFF_8436_MAX_LEN;
                }
                break;
        case MLXSW_REG_MCIA_EEPROM_MODULE_INFO_ID_SFP: