Skip to content

Commit 47afbdd

Browse files
Eran Ben ElishaSaeed Mahameed
authored andcommitted
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: a708fb7 ("net/mlx5e: ethtool, Add support for EEPROM high pages query") Signed-off-by: Eran Ben Elisha <[email protected]> Signed-off-by: Huy Nguyen <[email protected]> Signed-off-by: Saeed Mahameed <[email protected]>
1 parent ce69e56 commit 47afbdd

File tree

1 file changed

+77
-16
lines changed
  • drivers/net/ethernet/mellanox/mlx5/core

1 file changed

+77
-16
lines changed

drivers/net/ethernet/mellanox/mlx5/core/port.c

Lines changed: 77 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -293,7 +293,40 @@ static int mlx5_query_module_num(struct mlx5_core_dev *dev, int *module_num)
293293
return 0;
294294
}
295295

296-
static int mlx5_eeprom_page(int offset)
296+
static int mlx5_query_module_id(struct mlx5_core_dev *dev, int module_num,
297+
u8 *module_id)
298+
{
299+
u32 in[MLX5_ST_SZ_DW(mcia_reg)] = {};
300+
u32 out[MLX5_ST_SZ_DW(mcia_reg)];
301+
int err, status;
302+
u8 *ptr;
303+
304+
MLX5_SET(mcia_reg, in, i2c_device_address, MLX5_I2C_ADDR_LOW);
305+
MLX5_SET(mcia_reg, in, module, module_num);
306+
MLX5_SET(mcia_reg, in, device_address, 0);
307+
MLX5_SET(mcia_reg, in, page_number, 0);
308+
MLX5_SET(mcia_reg, in, size, 1);
309+
MLX5_SET(mcia_reg, in, l, 0);
310+
311+
err = mlx5_core_access_reg(dev, in, sizeof(in), out,
312+
sizeof(out), MLX5_REG_MCIA, 0, 0);
313+
if (err)
314+
return err;
315+
316+
status = MLX5_GET(mcia_reg, out, status);
317+
if (status) {
318+
mlx5_core_err(dev, "query_mcia_reg failed: status: 0x%x\n",
319+
status);
320+
return -EIO;
321+
}
322+
ptr = MLX5_ADDR_OF(mcia_reg, out, dword_0);
323+
324+
*module_id = ptr[0];
325+
326+
return 0;
327+
}
328+
329+
static int mlx5_qsfp_eeprom_page(u16 offset)
297330
{
298331
if (offset < MLX5_EEPROM_PAGE_LENGTH)
299332
/* Addresses between 0-255 - page 00 */
@@ -307,7 +340,7 @@ static int mlx5_eeprom_page(int offset)
307340
MLX5_EEPROM_HIGH_PAGE_LENGTH);
308341
}
309342

310-
static int mlx5_eeprom_high_page_offset(int page_num)
343+
static int mlx5_qsfp_eeprom_high_page_offset(int page_num)
311344
{
312345
if (!page_num) /* Page 0 always start from low page */
313346
return 0;
@@ -316,35 +349,62 @@ static int mlx5_eeprom_high_page_offset(int page_num)
316349
return page_num * MLX5_EEPROM_HIGH_PAGE_LENGTH;
317350
}
318351

352+
static void mlx5_qsfp_eeprom_params_set(u16 *i2c_addr, int *page_num, u16 *offset)
353+
{
354+
*i2c_addr = MLX5_I2C_ADDR_LOW;
355+
*page_num = mlx5_qsfp_eeprom_page(*offset);
356+
*offset -= mlx5_qsfp_eeprom_high_page_offset(*page_num);
357+
}
358+
359+
static void mlx5_sfp_eeprom_params_set(u16 *i2c_addr, int *page_num, u16 *offset)
360+
{
361+
*i2c_addr = MLX5_I2C_ADDR_LOW;
362+
*page_num = 0;
363+
364+
if (*offset < MLX5_EEPROM_PAGE_LENGTH)
365+
return;
366+
367+
*i2c_addr = MLX5_I2C_ADDR_HIGH;
368+
*offset -= MLX5_EEPROM_PAGE_LENGTH;
369+
}
370+
319371
int mlx5_query_module_eeprom(struct mlx5_core_dev *dev,
320372
u16 offset, u16 size, u8 *data)
321373
{
322-
int module_num, page_num, status, err;
374+
int module_num, status, err, page_num = 0;
375+
u32 in[MLX5_ST_SZ_DW(mcia_reg)] = {};
323376
u32 out[MLX5_ST_SZ_DW(mcia_reg)];
324-
u32 in[MLX5_ST_SZ_DW(mcia_reg)];
325-
u16 i2c_addr;
326-
void *ptr = MLX5_ADDR_OF(mcia_reg, out, dword_0);
377+
u16 i2c_addr = 0;
378+
u8 module_id;
379+
void *ptr;
327380

328381
err = mlx5_query_module_num(dev, &module_num);
329382
if (err)
330383
return err;
331384

332-
memset(in, 0, sizeof(in));
333-
size = min_t(int, size, MLX5_EEPROM_MAX_BYTES);
334-
335-
/* Get the page number related to the given offset */
336-
page_num = mlx5_eeprom_page(offset);
385+
err = mlx5_query_module_id(dev, module_num, &module_id);
386+
if (err)
387+
return err;
337388

338-
/* Set the right offset according to the page number,
339-
* For page_num > 0, relative offset is always >= 128 (high page).
340-
*/
341-
offset -= mlx5_eeprom_high_page_offset(page_num);
389+
switch (module_id) {
390+
case MLX5_MODULE_ID_SFP:
391+
mlx5_sfp_eeprom_params_set(&i2c_addr, &page_num, &offset);
392+
break;
393+
case MLX5_MODULE_ID_QSFP:
394+
case MLX5_MODULE_ID_QSFP_PLUS:
395+
case MLX5_MODULE_ID_QSFP28:
396+
mlx5_qsfp_eeprom_params_set(&i2c_addr, &page_num, &offset);
397+
break;
398+
default:
399+
mlx5_core_err(dev, "Module ID not recognized: 0x%x\n", module_id);
400+
return -EINVAL;
401+
}
342402

343403
if (offset + size > MLX5_EEPROM_PAGE_LENGTH)
344404
/* Cross pages read, read until offset 256 in low page */
345405
size -= offset + size - MLX5_EEPROM_PAGE_LENGTH;
346406

347-
i2c_addr = MLX5_I2C_ADDR_LOW;
407+
size = min_t(int, size, MLX5_EEPROM_MAX_BYTES);
348408

349409
MLX5_SET(mcia_reg, in, l, 0);
350410
MLX5_SET(mcia_reg, in, module, module_num);
@@ -365,6 +425,7 @@ int mlx5_query_module_eeprom(struct mlx5_core_dev *dev,
365425
return -EIO;
366426
}
367427

428+
ptr = MLX5_ADDR_OF(mcia_reg, out, dword_0);
368429
memcpy(data, ptr, size);
369430

370431
return size;

0 commit comments

Comments
 (0)