forked from Minki/linux
net/mlx5: Fix eeprom support for SFP module
Fix eeprom SFP query support by setting i2c_addr, offset and page number
correctly. Unlike QSFP modules, SFP eeprom params are as follow:
- i2c_addr is 0x50 for offset 0 - 255 and 0x51 for offset 256 - 511.
- Page number is always zero.
- Page offset is always relative to zero.
As part of eeprom query, query the module ID (SFP / QSFP*) via helper
function to set the params accordingly.
In addition, change mlx5_qsfp_eeprom_page() input type to be u16 to avoid
unnecessary casting.
Fixes: a708fb7b1f
("net/mlx5e: ethtool, Add support for EEPROM high pages query")
Signed-off-by: Eran Ben Elisha <eranbe@mellanox.com>
Signed-off-by: Huy Nguyen <huyn@mellanox.com>
Signed-off-by: Saeed Mahameed <saeedm@mellanox.com>
This commit is contained in:
parent
ce69e563b3
commit
47afbdd2fa
@ -293,7 +293,40 @@ static int mlx5_query_module_num(struct mlx5_core_dev *dev, int *module_num)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mlx5_eeprom_page(int offset)
|
||||
static int mlx5_query_module_id(struct mlx5_core_dev *dev, int module_num,
|
||||
u8 *module_id)
|
||||
{
|
||||
u32 in[MLX5_ST_SZ_DW(mcia_reg)] = {};
|
||||
u32 out[MLX5_ST_SZ_DW(mcia_reg)];
|
||||
int err, status;
|
||||
u8 *ptr;
|
||||
|
||||
MLX5_SET(mcia_reg, in, i2c_device_address, MLX5_I2C_ADDR_LOW);
|
||||
MLX5_SET(mcia_reg, in, module, module_num);
|
||||
MLX5_SET(mcia_reg, in, device_address, 0);
|
||||
MLX5_SET(mcia_reg, in, page_number, 0);
|
||||
MLX5_SET(mcia_reg, in, size, 1);
|
||||
MLX5_SET(mcia_reg, in, l, 0);
|
||||
|
||||
err = mlx5_core_access_reg(dev, in, sizeof(in), out,
|
||||
sizeof(out), MLX5_REG_MCIA, 0, 0);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
status = MLX5_GET(mcia_reg, out, status);
|
||||
if (status) {
|
||||
mlx5_core_err(dev, "query_mcia_reg failed: status: 0x%x\n",
|
||||
status);
|
||||
return -EIO;
|
||||
}
|
||||
ptr = MLX5_ADDR_OF(mcia_reg, out, dword_0);
|
||||
|
||||
*module_id = ptr[0];
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mlx5_qsfp_eeprom_page(u16 offset)
|
||||
{
|
||||
if (offset < MLX5_EEPROM_PAGE_LENGTH)
|
||||
/* Addresses between 0-255 - page 00 */
|
||||
@ -307,7 +340,7 @@ static int mlx5_eeprom_page(int offset)
|
||||
MLX5_EEPROM_HIGH_PAGE_LENGTH);
|
||||
}
|
||||
|
||||
static int mlx5_eeprom_high_page_offset(int page_num)
|
||||
static int mlx5_qsfp_eeprom_high_page_offset(int page_num)
|
||||
{
|
||||
if (!page_num) /* Page 0 always start from low page */
|
||||
return 0;
|
||||
@ -316,35 +349,62 @@ static int mlx5_eeprom_high_page_offset(int page_num)
|
||||
return page_num * MLX5_EEPROM_HIGH_PAGE_LENGTH;
|
||||
}
|
||||
|
||||
static void mlx5_qsfp_eeprom_params_set(u16 *i2c_addr, int *page_num, u16 *offset)
|
||||
{
|
||||
*i2c_addr = MLX5_I2C_ADDR_LOW;
|
||||
*page_num = mlx5_qsfp_eeprom_page(*offset);
|
||||
*offset -= mlx5_qsfp_eeprom_high_page_offset(*page_num);
|
||||
}
|
||||
|
||||
static void mlx5_sfp_eeprom_params_set(u16 *i2c_addr, int *page_num, u16 *offset)
|
||||
{
|
||||
*i2c_addr = MLX5_I2C_ADDR_LOW;
|
||||
*page_num = 0;
|
||||
|
||||
if (*offset < MLX5_EEPROM_PAGE_LENGTH)
|
||||
return;
|
||||
|
||||
*i2c_addr = MLX5_I2C_ADDR_HIGH;
|
||||
*offset -= MLX5_EEPROM_PAGE_LENGTH;
|
||||
}
|
||||
|
||||
int mlx5_query_module_eeprom(struct mlx5_core_dev *dev,
|
||||
u16 offset, u16 size, u8 *data)
|
||||
{
|
||||
int module_num, page_num, status, err;
|
||||
int module_num, status, err, page_num = 0;
|
||||
u32 in[MLX5_ST_SZ_DW(mcia_reg)] = {};
|
||||
u32 out[MLX5_ST_SZ_DW(mcia_reg)];
|
||||
u32 in[MLX5_ST_SZ_DW(mcia_reg)];
|
||||
u16 i2c_addr;
|
||||
void *ptr = MLX5_ADDR_OF(mcia_reg, out, dword_0);
|
||||
u16 i2c_addr = 0;
|
||||
u8 module_id;
|
||||
void *ptr;
|
||||
|
||||
err = mlx5_query_module_num(dev, &module_num);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
memset(in, 0, sizeof(in));
|
||||
size = min_t(int, size, MLX5_EEPROM_MAX_BYTES);
|
||||
err = mlx5_query_module_id(dev, module_num, &module_id);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
/* Get the page number related to the given offset */
|
||||
page_num = mlx5_eeprom_page(offset);
|
||||
|
||||
/* Set the right offset according to the page number,
|
||||
* For page_num > 0, relative offset is always >= 128 (high page).
|
||||
*/
|
||||
offset -= mlx5_eeprom_high_page_offset(page_num);
|
||||
switch (module_id) {
|
||||
case MLX5_MODULE_ID_SFP:
|
||||
mlx5_sfp_eeprom_params_set(&i2c_addr, &page_num, &offset);
|
||||
break;
|
||||
case MLX5_MODULE_ID_QSFP:
|
||||
case MLX5_MODULE_ID_QSFP_PLUS:
|
||||
case MLX5_MODULE_ID_QSFP28:
|
||||
mlx5_qsfp_eeprom_params_set(&i2c_addr, &page_num, &offset);
|
||||
break;
|
||||
default:
|
||||
mlx5_core_err(dev, "Module ID not recognized: 0x%x\n", module_id);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (offset + size > MLX5_EEPROM_PAGE_LENGTH)
|
||||
/* Cross pages read, read until offset 256 in low page */
|
||||
size -= offset + size - MLX5_EEPROM_PAGE_LENGTH;
|
||||
|
||||
i2c_addr = MLX5_I2C_ADDR_LOW;
|
||||
size = min_t(int, size, MLX5_EEPROM_MAX_BYTES);
|
||||
|
||||
MLX5_SET(mcia_reg, in, l, 0);
|
||||
MLX5_SET(mcia_reg, in, module, module_num);
|
||||
@ -365,6 +425,7 @@ int mlx5_query_module_eeprom(struct mlx5_core_dev *dev,
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
ptr = MLX5_ADDR_OF(mcia_reg, out, dword_0);
|
||||
memcpy(data, ptr, size);
|
||||
|
||||
return size;
|
||||
|
Loading…
Reference in New Issue
Block a user