diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_env.c b/drivers/net/ethernet/mellanox/mlxsw/core_env.c index d2c7ce67c300d9e7e0846498c92795af49699dfc..08215fed193d309c64bf18286d2881afe4948527 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core_env.c +++ b/drivers/net/ethernet/mellanox/mlxsw/core_env.c @@ -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: diff --git a/drivers/net/ethernet/mellanox/mlxsw/reg.h b/drivers/net/ethernet/mellanox/mlxsw/reg.h index f5e39758c6ac82eed70612b265ceebf140271495..adb63a266fc751effb1a1f7740bc6a023eb876b7 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/reg.h +++ b/drivers/net/ethernet/mellanox/mlxsw/reg.h @@ -8412,6 +8412,7 @@ MLXSW_ITEM32(reg, mcia, device_address, 0x04, 0, 16); MLXSW_ITEM32(reg, mcia, size, 0x08, 0, 16); #define MLXSW_REG_MCIA_EEPROM_PAGE_LENGTH 256 +#define MLXSW_REG_MCIA_EEPROM_UP_PAGE_LENGTH 128 #define MLXSW_REG_MCIA_EEPROM_SIZE 48 #define MLXSW_REG_MCIA_I2C_ADDR_LOW 0x50 #define MLXSW_REG_MCIA_I2C_ADDR_HIGH 0x51 @@ -8447,6 +8448,14 @@ enum mlxsw_reg_mcia_eeprom_module_info { */ MLXSW_ITEM_BUF(reg, mcia, eeprom, 0x10, MLXSW_REG_MCIA_EEPROM_SIZE); +/* This is used to access the optional upper pages (1-3) in the QSFP+ + * memory map. Page 1 is available on offset 256 through 383, page 2 - + * on offset 384 through 511, page 3 - on offset 512 through 639. + */ +#define MLXSW_REG_MCIA_PAGE_GET(off) (((off) - \ + MLXSW_REG_MCIA_EEPROM_PAGE_LENGTH) / \ + MLXSW_REG_MCIA_EEPROM_UP_PAGE_LENGTH + 1) + static inline void mlxsw_reg_mcia_pack(char *payload, u8 module, u8 lock, u8 page_number, u16 device_addr, u8 size, u8 i2c_device_addr)