|
Denis Kirjanov |
ebb326 |
From 2f7126038cc52b506702bdc7056f36298b8a28ce Mon Sep 17 00:00:00 2001
|
|
Denis Kirjanov |
ebb326 |
From: Vladyslav Tarasiuk <vladyslavt@nvidia.com>
|
|
Denis Kirjanov |
ebb326 |
Date: Sun, 9 May 2021 09:43:18 +0300
|
|
Denis Kirjanov |
ebb326 |
Subject: [PATCH 16/19] net/mlx4: Fix EEPROM dump support
|
|
Denis Kirjanov |
ebb326 |
Git-commit: db825feefc6868896fed5e361787ba3bee2fd906
|
|
Denis Kirjanov |
ebb326 |
Patch-mainline: v5.13-rc4
|
|
Denis Kirjanov |
ebb326 |
References: git-fixes
|
|
Denis Kirjanov |
ebb326 |
|
|
Denis Kirjanov |
ebb326 |
Fix SFP and QSFP* EEPROM queries by setting i2c_address, offset and page
|
|
Denis Kirjanov |
ebb326 |
number correctly. For SFP set the following params:
|
|
Denis Kirjanov |
ebb326 |
- I2C address for offsets 0-255 is 0x50. For 256-511 - 0x51.
|
|
Denis Kirjanov |
ebb326 |
- Page number is zero.
|
|
Denis Kirjanov |
ebb326 |
- Offset is 0-255.
|
|
Denis Kirjanov |
ebb326 |
|
|
Denis Kirjanov |
ebb326 |
At the same time, QSFP* parameters are different:
|
|
Denis Kirjanov |
ebb326 |
- I2C address is always 0x50.
|
|
Denis Kirjanov |
ebb326 |
- Page number is not limited to zero.
|
|
Denis Kirjanov |
ebb326 |
- Offset is 0-255 for page zero and 128-255 for others.
|
|
Denis Kirjanov |
ebb326 |
|
|
Denis Kirjanov |
ebb326 |
To set parameters accordingly to cable used, implement function to query
|
|
Denis Kirjanov |
ebb326 |
module ID and implement respective helper functions to set parameters
|
|
Denis Kirjanov |
ebb326 |
correctly.
|
|
Denis Kirjanov |
ebb326 |
|
|
Denis Kirjanov |
ebb326 |
Fixes: 135dd9594f12 ("net/mlx4_en: ethtool, Remove unsupported SFP EEPROM high pages query")
|
|
Denis Kirjanov |
ebb326 |
Signed-off-by: Vladyslav Tarasiuk <vladyslavt@nvidia.com>
|
|
Denis Kirjanov |
ebb326 |
Signed-off-by: Tariq Toukan <tariqt@nvidia.com>
|
|
Denis Kirjanov |
ebb326 |
Signed-off-by: David S. Miller <davem@davemloft.net>
|
|
Denis Kirjanov |
ebb326 |
Signed-off-by: Denis Kirjanov <denis.kirjanov@suse.com>
|
|
Denis Kirjanov |
ebb326 |
---
|
|
Denis Kirjanov |
ebb326 |
drivers/net/ethernet/mellanox/mlx4/en_ethtool.c | 4 +-
|
|
Denis Kirjanov |
ebb326 |
drivers/net/ethernet/mellanox/mlx4/port.c | 107 +++++++++++++++++++++++-
|
|
Denis Kirjanov |
ebb326 |
2 files changed, 104 insertions(+), 7 deletions(-)
|
|
Denis Kirjanov |
ebb326 |
|
|
Denis Kirjanov |
ebb326 |
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c b/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c
|
|
Denis Kirjanov |
ebb326 |
index 7a99eb1572fd..6a005014d46a 100644
|
|
Denis Kirjanov |
ebb326 |
--- a/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c
|
|
Denis Kirjanov |
ebb326 |
+++ b/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c
|
|
Denis Kirjanov |
ebb326 |
@@ -2011,8 +2011,6 @@ static int mlx4_en_set_tunable(struct net_device *dev,
|
|
Denis Kirjanov |
ebb326 |
return ret;
|
|
Denis Kirjanov |
ebb326 |
}
|
|
Denis Kirjanov |
ebb326 |
|
|
Denis Kirjanov |
ebb326 |
-#define MLX4_EEPROM_PAGE_LEN 256
|
|
Denis Kirjanov |
ebb326 |
-
|
|
Denis Kirjanov |
ebb326 |
static int mlx4_en_get_module_info(struct net_device *dev,
|
|
Denis Kirjanov |
ebb326 |
struct ethtool_modinfo *modinfo)
|
|
Denis Kirjanov |
ebb326 |
{
|
|
Denis Kirjanov |
ebb326 |
@@ -2047,7 +2045,7 @@ static int mlx4_en_get_module_info(struct net_device *dev,
|
|
Denis Kirjanov |
ebb326 |
break;
|
|
Denis Kirjanov |
ebb326 |
case MLX4_MODULE_ID_SFP:
|
|
Denis Kirjanov |
ebb326 |
modinfo->type = ETH_MODULE_SFF_8472;
|
|
Denis Kirjanov |
ebb326 |
- modinfo->eeprom_len = MLX4_EEPROM_PAGE_LEN;
|
|
Denis Kirjanov |
ebb326 |
+ modinfo->eeprom_len = ETH_MODULE_SFF_8472_LEN;
|
|
Denis Kirjanov |
ebb326 |
break;
|
|
Denis Kirjanov |
ebb326 |
default:
|
|
Denis Kirjanov |
ebb326 |
return -EINVAL;
|
|
Denis Kirjanov |
ebb326 |
diff --git a/drivers/net/ethernet/mellanox/mlx4/port.c b/drivers/net/ethernet/mellanox/mlx4/port.c
|
|
Denis Kirjanov |
ebb326 |
index ba6ac31a339d..256a06b3c096 100644
|
|
Denis Kirjanov |
ebb326 |
--- a/drivers/net/ethernet/mellanox/mlx4/port.c
|
|
Denis Kirjanov |
ebb326 |
+++ b/drivers/net/ethernet/mellanox/mlx4/port.c
|
|
Denis Kirjanov |
ebb326 |
@@ -1973,6 +1973,7 @@ EXPORT_SYMBOL(mlx4_get_roce_gid_from_slave);
|
|
Denis Kirjanov |
ebb326 |
#define I2C_ADDR_LOW 0x50
|
|
Denis Kirjanov |
ebb326 |
#define I2C_ADDR_HIGH 0x51
|
|
Denis Kirjanov |
ebb326 |
#define I2C_PAGE_SIZE 256
|
|
Denis Kirjanov |
ebb326 |
+#define I2C_HIGH_PAGE_SIZE 128
|
|
Denis Kirjanov |
ebb326 |
|
|
Denis Kirjanov |
ebb326 |
/* Module Info Data */
|
|
Denis Kirjanov |
ebb326 |
struct mlx4_cable_info {
|
|
Denis Kirjanov |
ebb326 |
@@ -2026,6 +2027,88 @@ static inline const char *cable_info_mad_err_str(u16 mad_status)
|
|
Denis Kirjanov |
ebb326 |
return "Unknown Error";
|
|
Denis Kirjanov |
ebb326 |
}
|
|
Denis Kirjanov |
ebb326 |
|
|
Denis Kirjanov |
ebb326 |
+static int mlx4_get_module_id(struct mlx4_dev *dev, u8 port, u8 *module_id)
|
|
Denis Kirjanov |
ebb326 |
+{
|
|
Denis Kirjanov |
ebb326 |
+ struct mlx4_cmd_mailbox *inbox, *outbox;
|
|
Denis Kirjanov |
ebb326 |
+ struct mlx4_mad_ifc *inmad, *outmad;
|
|
Denis Kirjanov |
ebb326 |
+ struct mlx4_cable_info *cable_info;
|
|
Denis Kirjanov |
ebb326 |
+ int ret;
|
|
Denis Kirjanov |
ebb326 |
+
|
|
Denis Kirjanov |
ebb326 |
+ inbox = mlx4_alloc_cmd_mailbox(dev);
|
|
Denis Kirjanov |
ebb326 |
+ if (IS_ERR(inbox))
|
|
Denis Kirjanov |
ebb326 |
+ return PTR_ERR(inbox);
|
|
Denis Kirjanov |
ebb326 |
+
|
|
Denis Kirjanov |
ebb326 |
+ outbox = mlx4_alloc_cmd_mailbox(dev);
|
|
Denis Kirjanov |
ebb326 |
+ if (IS_ERR(outbox)) {
|
|
Denis Kirjanov |
ebb326 |
+ mlx4_free_cmd_mailbox(dev, inbox);
|
|
Denis Kirjanov |
ebb326 |
+ return PTR_ERR(outbox);
|
|
Denis Kirjanov |
ebb326 |
+ }
|
|
Denis Kirjanov |
ebb326 |
+
|
|
Denis Kirjanov |
ebb326 |
+ inmad = (struct mlx4_mad_ifc *)(inbox->buf);
|
|
Denis Kirjanov |
ebb326 |
+ outmad = (struct mlx4_mad_ifc *)(outbox->buf);
|
|
Denis Kirjanov |
ebb326 |
+
|
|
Denis Kirjanov |
ebb326 |
+ inmad->method = 0x1; /* Get */
|
|
Denis Kirjanov |
ebb326 |
+ inmad->class_version = 0x1;
|
|
Denis Kirjanov |
ebb326 |
+ inmad->mgmt_class = 0x1;
|
|
Denis Kirjanov |
ebb326 |
+ inmad->base_version = 0x1;
|
|
Denis Kirjanov |
ebb326 |
+ inmad->attr_id = cpu_to_be16(0xFF60); /* Module Info */
|
|
Denis Kirjanov |
ebb326 |
+
|
|
Denis Kirjanov |
ebb326 |
+ cable_info = (struct mlx4_cable_info *)inmad->data;
|
|
Denis Kirjanov |
ebb326 |
+ cable_info->dev_mem_address = 0;
|
|
Denis Kirjanov |
ebb326 |
+ cable_info->page_num = 0;
|
|
Denis Kirjanov |
ebb326 |
+ cable_info->i2c_addr = I2C_ADDR_LOW;
|
|
Denis Kirjanov |
ebb326 |
+ cable_info->size = cpu_to_be16(1);
|
|
Denis Kirjanov |
ebb326 |
+
|
|
Denis Kirjanov |
ebb326 |
+ ret = mlx4_cmd_box(dev, inbox->dma, outbox->dma, port, 3,
|
|
Denis Kirjanov |
ebb326 |
+ MLX4_CMD_MAD_IFC, MLX4_CMD_TIME_CLASS_C,
|
|
Denis Kirjanov |
ebb326 |
+ MLX4_CMD_NATIVE);
|
|
Denis Kirjanov |
ebb326 |
+ if (ret)
|
|
Denis Kirjanov |
ebb326 |
+ goto out;
|
|
Denis Kirjanov |
ebb326 |
+
|
|
Denis Kirjanov |
ebb326 |
+ if (be16_to_cpu(outmad->status)) {
|
|
Denis Kirjanov |
ebb326 |
+ /* Mad returned with bad status */
|
|
Denis Kirjanov |
ebb326 |
+ ret = be16_to_cpu(outmad->status);
|
|
Denis Kirjanov |
ebb326 |
+ mlx4_warn(dev,
|
|
Denis Kirjanov |
ebb326 |
+ "MLX4_CMD_MAD_IFC Get Module ID attr(%x) port(%d) i2c_addr(%x) offset(%d) size(%d): Response Mad Status(%x) - %s\n",
|
|
Denis Kirjanov |
ebb326 |
+ 0xFF60, port, I2C_ADDR_LOW, 0, 1, ret,
|
|
Denis Kirjanov |
ebb326 |
+ cable_info_mad_err_str(ret));
|
|
Denis Kirjanov |
ebb326 |
+ ret = -ret;
|
|
Denis Kirjanov |
ebb326 |
+ goto out;
|
|
Denis Kirjanov |
ebb326 |
+ }
|
|
Denis Kirjanov |
ebb326 |
+ cable_info = (struct mlx4_cable_info *)outmad->data;
|
|
Denis Kirjanov |
ebb326 |
+ *module_id = cable_info->data[0];
|
|
Denis Kirjanov |
ebb326 |
+out:
|
|
Denis Kirjanov |
ebb326 |
+ mlx4_free_cmd_mailbox(dev, inbox);
|
|
Denis Kirjanov |
ebb326 |
+ mlx4_free_cmd_mailbox(dev, outbox);
|
|
Denis Kirjanov |
ebb326 |
+ return ret;
|
|
Denis Kirjanov |
ebb326 |
+}
|
|
Denis Kirjanov |
ebb326 |
+
|
|
Denis Kirjanov |
ebb326 |
+static void mlx4_sfp_eeprom_params_set(u8 *i2c_addr, u8 *page_num, u16 *offset)
|
|
Denis Kirjanov |
ebb326 |
+{
|
|
Denis Kirjanov |
ebb326 |
+ *i2c_addr = I2C_ADDR_LOW;
|
|
Denis Kirjanov |
ebb326 |
+ *page_num = 0;
|
|
Denis Kirjanov |
ebb326 |
+
|
|
Denis Kirjanov |
ebb326 |
+ if (*offset < I2C_PAGE_SIZE)
|
|
Denis Kirjanov |
ebb326 |
+ return;
|
|
Denis Kirjanov |
ebb326 |
+
|
|
Denis Kirjanov |
ebb326 |
+ *i2c_addr = I2C_ADDR_HIGH;
|
|
Denis Kirjanov |
ebb326 |
+ *offset -= I2C_PAGE_SIZE;
|
|
Denis Kirjanov |
ebb326 |
+}
|
|
Denis Kirjanov |
ebb326 |
+
|
|
Denis Kirjanov |
ebb326 |
+static void mlx4_qsfp_eeprom_params_set(u8 *i2c_addr, u8 *page_num, u16 *offset)
|
|
Denis Kirjanov |
ebb326 |
+{
|
|
Denis Kirjanov |
ebb326 |
+ /* Offsets 0-255 belong to page 0.
|
|
Denis Kirjanov |
ebb326 |
+ * Offsets 256-639 belong to pages 01, 02, 03.
|
|
Denis Kirjanov |
ebb326 |
+ * For example, offset 400 is page 02: 1 + (400 - 256) / 128 = 2
|
|
Denis Kirjanov |
ebb326 |
+ */
|
|
Denis Kirjanov |
ebb326 |
+ if (*offset < I2C_PAGE_SIZE)
|
|
Denis Kirjanov |
ebb326 |
+ *page_num = 0;
|
|
Denis Kirjanov |
ebb326 |
+ else
|
|
Denis Kirjanov |
ebb326 |
+ *page_num = 1 + (*offset - I2C_PAGE_SIZE) / I2C_HIGH_PAGE_SIZE;
|
|
Denis Kirjanov |
ebb326 |
+ *i2c_addr = I2C_ADDR_LOW;
|
|
Denis Kirjanov |
ebb326 |
+ *offset -= *page_num * I2C_HIGH_PAGE_SIZE;
|
|
Denis Kirjanov |
ebb326 |
+}
|
|
Denis Kirjanov |
ebb326 |
+
|
|
Denis Kirjanov |
ebb326 |
/**
|
|
Denis Kirjanov |
ebb326 |
* mlx4_get_module_info - Read cable module eeprom data
|
|
Denis Kirjanov |
ebb326 |
* @dev: mlx4_dev.
|
|
Denis Kirjanov |
ebb326 |
@@ -2045,12 +2128,30 @@ int mlx4_get_module_info(struct mlx4_dev *dev, u8 port,
|
|
Denis Kirjanov |
ebb326 |
struct mlx4_cmd_mailbox *inbox, *outbox;
|
|
Denis Kirjanov |
ebb326 |
struct mlx4_mad_ifc *inmad, *outmad;
|
|
Denis Kirjanov |
ebb326 |
struct mlx4_cable_info *cable_info;
|
|
Denis Kirjanov |
ebb326 |
- u16 i2c_addr;
|
|
Denis Kirjanov |
ebb326 |
+ u8 module_id, i2c_addr, page_num;
|
|
Denis Kirjanov |
ebb326 |
int ret;
|
|
Denis Kirjanov |
ebb326 |
|
|
Denis Kirjanov |
ebb326 |
if (size > MODULE_INFO_MAX_READ)
|
|
Denis Kirjanov |
ebb326 |
size = MODULE_INFO_MAX_READ;
|
|
Denis Kirjanov |
ebb326 |
|
|
Denis Kirjanov |
ebb326 |
+ ret = mlx4_get_module_id(dev, port, &module_id);
|
|
Denis Kirjanov |
ebb326 |
+ if (ret)
|
|
Denis Kirjanov |
ebb326 |
+ return ret;
|
|
Denis Kirjanov |
ebb326 |
+
|
|
Denis Kirjanov |
ebb326 |
+ switch (module_id) {
|
|
Denis Kirjanov |
ebb326 |
+ case MLX4_MODULE_ID_SFP:
|
|
Denis Kirjanov |
ebb326 |
+ mlx4_sfp_eeprom_params_set(&i2c_addr, &page_num, &offset);
|
|
Denis Kirjanov |
ebb326 |
+ break;
|
|
Denis Kirjanov |
ebb326 |
+ case MLX4_MODULE_ID_QSFP:
|
|
Denis Kirjanov |
ebb326 |
+ case MLX4_MODULE_ID_QSFP_PLUS:
|
|
Denis Kirjanov |
ebb326 |
+ case MLX4_MODULE_ID_QSFP28:
|
|
Denis Kirjanov |
ebb326 |
+ mlx4_qsfp_eeprom_params_set(&i2c_addr, &page_num, &offset);
|
|
Denis Kirjanov |
ebb326 |
+ break;
|
|
Denis Kirjanov |
ebb326 |
+ default:
|
|
Denis Kirjanov |
ebb326 |
+ mlx4_err(dev, "Module ID not recognized: %#x\n", module_id);
|
|
Denis Kirjanov |
ebb326 |
+ return -EINVAL;
|
|
Denis Kirjanov |
ebb326 |
+ }
|
|
Denis Kirjanov |
ebb326 |
+
|
|
Denis Kirjanov |
ebb326 |
inbox = mlx4_alloc_cmd_mailbox(dev);
|
|
Denis Kirjanov |
ebb326 |
if (IS_ERR(inbox))
|
|
Denis Kirjanov |
ebb326 |
return PTR_ERR(inbox);
|
|
Denis Kirjanov |
ebb326 |
@@ -2076,11 +2177,9 @@ int mlx4_get_module_info(struct mlx4_dev *dev, u8 port,
|
|
Denis Kirjanov |
ebb326 |
*/
|
|
Denis Kirjanov |
ebb326 |
size -= offset + size - I2C_PAGE_SIZE;
|
|
Denis Kirjanov |
ebb326 |
|
|
Denis Kirjanov |
ebb326 |
- i2c_addr = I2C_ADDR_LOW;
|
|
Denis Kirjanov |
ebb326 |
-
|
|
Denis Kirjanov |
ebb326 |
cable_info = (struct mlx4_cable_info *)inmad->data;
|
|
Denis Kirjanov |
ebb326 |
cable_info->dev_mem_address = cpu_to_be16(offset);
|
|
Denis Kirjanov |
ebb326 |
- cable_info->page_num = 0;
|
|
Denis Kirjanov |
ebb326 |
+ cable_info->page_num = page_num;
|
|
Denis Kirjanov |
ebb326 |
cable_info->i2c_addr = i2c_addr;
|
|
Denis Kirjanov |
ebb326 |
cable_info->size = cpu_to_be16(size);
|
|
Denis Kirjanov |
ebb326 |
|
|
Denis Kirjanov |
ebb326 |
--
|
|
Denis Kirjanov |
ebb326 |
2.16.4
|
|
Denis Kirjanov |
ebb326 |
|