net/mlx5e: ethtool, Add support for EEPROM high pages query
authorErez Alfasi <ereza@mellanox.com>
Thu, 21 Mar 2019 13:02:13 +0000 (15:02 +0200)
committerSaeed Mahameed <saeedm@mellanox.com>
Wed, 1 May 2019 21:39:16 +0000 (14:39 -0700)
Add the support to read additional EEPROM information from high pages.
Information for modules such as SFF-8436 and SFF-8636:
 1) Application select table
 2) User writable EEPROM
 3) Thresholds and alarms

Signed-off-by: Erez Alfasi <ereza@mellanox.com>
Signed-off-by: Saeed Mahameed <saeedm@mellanox.com>
drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c
drivers/net/ethernet/mellanox/mlx5/core/port.c
include/linux/mlx5/port.h

index 78dc8fe2a83c3499d290ceffcb273ebcd7ef1932..7efaa58ae034a0f9f4f016db37cddde72c0884a0 100644 (file)
@@ -1561,7 +1561,7 @@ static int mlx5e_get_module_info(struct net_device *netdev,
        struct mlx5e_priv *priv = netdev_priv(netdev);
        struct mlx5_core_dev *dev = priv->mdev;
        int size_read = 0;
-       u8 data[4];
+       u8 data[4] = {0};
 
        size_read = mlx5_query_module_eeprom(dev, 0, 2, data);
        if (size_read < 2)
@@ -1571,17 +1571,17 @@ static int mlx5e_get_module_info(struct net_device *netdev,
        switch (data[0]) {
        case MLX5_MODULE_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 MLX5_MODULE_ID_QSFP_PLUS:
        case MLX5_MODULE_ID_QSFP28:
                /* data[1] = revision id */
                if (data[0] == MLX5_MODULE_ID_QSFP28 || data[1] >= 0x3) {
                        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 MLX5_MODULE_ID_SFP:
index 361468e0435dcc9fbb667716e483c4104ebf7fea..cc262b30aed532ca4240d7aaf985ba288384911f 100644 (file)
@@ -293,15 +293,36 @@ static int mlx5_query_module_num(struct mlx5_core_dev *dev, int *module_num)
        return 0;
 }
 
+static int mlx5_eeprom_page(int offset)
+{
+       if (offset < MLX5_EEPROM_PAGE_LENGTH)
+               /* Addresses between 0-255 - page 00 */
+               return 0;
+
+       /* Addresses between 256 - 639 belongs to pages 01, 02 and 03
+        * For example, offset = 400 belongs to page 02:
+        * 1 + ((400 - 256)/128) = 2
+        */
+       return 1 + ((offset - MLX5_EEPROM_PAGE_LENGTH) /
+                   MLX5_EEPROM_HIGH_PAGE_LENGTH);
+}
+
+static int mlx5_eeprom_high_page_offset(int page_num)
+{
+       if (!page_num) /* Page 0 always start from low page */
+               return 0;
+
+       /* High page */
+       return page_num * MLX5_EEPROM_HIGH_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;
        u32 out[MLX5_ST_SZ_DW(mcia_reg)];
        u32 in[MLX5_ST_SZ_DW(mcia_reg)];
-       int module_num;
        u16 i2c_addr;
-       int status;
-       int err;
        void *ptr = MLX5_ADDR_OF(mcia_reg, out, dword_0);
 
        err = mlx5_query_module_num(dev, &module_num);
@@ -311,8 +332,15 @@ int mlx5_query_module_eeprom(struct mlx5_core_dev *dev,
        memset(in, 0, sizeof(in));
        size = min_t(int, size, MLX5_EEPROM_MAX_BYTES);
 
-       if (offset < MLX5_EEPROM_PAGE_LENGTH &&
-           offset + size > MLX5_EEPROM_PAGE_LENGTH)
+       /* 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);
+
+       if (offset + size > MLX5_EEPROM_PAGE_LENGTH)
                /* Cross pages read, read until offset 256 in low page */
                size -= offset + size - MLX5_EEPROM_PAGE_LENGTH;
 
@@ -321,7 +349,7 @@ int mlx5_query_module_eeprom(struct mlx5_core_dev *dev,
        MLX5_SET(mcia_reg, in, l, 0);
        MLX5_SET(mcia_reg, in, module, module_num);
        MLX5_SET(mcia_reg, in, i2c_device_address, i2c_addr);
-       MLX5_SET(mcia_reg, in, page_number, 0);
+       MLX5_SET(mcia_reg, in, page_number, page_num);
        MLX5_SET(mcia_reg, in, device_address, offset);
        MLX5_SET(mcia_reg, in, size, size);
 
index 64e78394fc9c3e4169fa8e8fecc28f678c73932b..de9a272c9f3d64f560104d269dcd905ace67cc70 100644 (file)
@@ -60,6 +60,7 @@ enum mlx5_an_status {
 #define MLX5_I2C_ADDR_LOW              0x50
 #define MLX5_I2C_ADDR_HIGH             0x51
 #define MLX5_EEPROM_PAGE_LENGTH                256
+#define MLX5_EEPROM_HIGH_PAGE_LENGTH   128
 
 enum mlx5e_link_mode {
        MLX5E_1000BASE_CX_SGMII  = 0,