]> git.proxmox.com Git - mirror_ubuntu-jammy-kernel.git/commitdiff
net/mlx5: Implement get_module_eeprom_by_page()
authorVladyslav Tarasiuk <vladyslavt@nvidia.com>
Fri, 9 Apr 2021 08:06:36 +0000 (11:06 +0300)
committerDavid S. Miller <davem@davemloft.net>
Sun, 11 Apr 2021 23:34:56 +0000 (16:34 -0700)
Implement ethtool_ops::get_module_eeprom_by_page() to enable
support of new SFP standards.

Signed-off-by: Vladyslav Tarasiuk <vladyslavt@nvidia.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c
drivers/net/ethernet/mellanox/mlx5/core/port.c
include/linux/mlx5/port.h

index b185a045262982e2e96d9971341f52a7cd35a8c0..c8057a44d5ab5988d2924247e8d52bf3f6e1823e 100644 (file)
@@ -1770,6 +1770,49 @@ static int mlx5e_get_module_eeprom(struct net_device *netdev,
        return 0;
 }
 
+static int mlx5e_get_module_eeprom_by_page(struct net_device *netdev,
+                                          const struct ethtool_module_eeprom *page_data,
+                                          struct netlink_ext_ack *extack)
+{
+       struct mlx5e_priv *priv = netdev_priv(netdev);
+       struct mlx5_module_eeprom_query_params query;
+       struct mlx5_core_dev *mdev = priv->mdev;
+       u8 *data = page_data->data;
+       int size_read;
+       int i = 0;
+
+       if (!page_data->length)
+               return -EINVAL;
+
+       memset(data, 0, page_data->length);
+
+       query.offset = page_data->offset;
+       query.i2c_address = page_data->i2c_address;
+       query.bank = page_data->bank;
+       query.page = page_data->page;
+       while (i < page_data->length) {
+               query.size = page_data->length - i;
+               size_read = mlx5_query_module_eeprom_by_page(mdev, &query, data + i);
+
+               /* Done reading, return how many bytes was read */
+               if (!size_read)
+                       return i;
+
+               if (size_read == -EINVAL)
+                       return -EINVAL;
+               if (size_read < 0) {
+                       netdev_err(priv->netdev, "%s: mlx5_query_module_eeprom_by_page failed:0x%x\n",
+                                  __func__, size_read);
+                       return i;
+               }
+
+               i += size_read;
+               query.offset += size_read;
+       }
+
+       return i;
+}
+
 int mlx5e_ethtool_flash_device(struct mlx5e_priv *priv,
                               struct ethtool_flash *flash)
 {
@@ -2159,6 +2202,7 @@ const struct ethtool_ops mlx5e_ethtool_ops = {
        .set_wol           = mlx5e_set_wol,
        .get_module_info   = mlx5e_get_module_info,
        .get_module_eeprom = mlx5e_get_module_eeprom,
+       .get_module_eeprom_by_page = mlx5e_get_module_eeprom_by_page,
        .flash_device      = mlx5e_flash_device,
        .get_priv_flags    = mlx5e_get_priv_flags,
        .set_priv_flags    = mlx5e_set_priv_flags,
index 9b9f870d67a42d6e8fbeefc6e0cf3f672f93f2c5..522a41f8f1e25ed1dc4ecefadeb35b50e3539eda 100644 (file)
@@ -428,6 +428,47 @@ int mlx5_query_module_eeprom(struct mlx5_core_dev *dev,
 }
 EXPORT_SYMBOL_GPL(mlx5_query_module_eeprom);
 
+int mlx5_query_module_eeprom_by_page(struct mlx5_core_dev *dev,
+                                    struct mlx5_module_eeprom_query_params *params,
+                                    u8 *data)
+{
+       u8 module_id;
+       int err;
+
+       err = mlx5_query_module_num(dev, &params->module_number);
+       if (err)
+               return err;
+
+       err = mlx5_query_module_id(dev, params->module_number, &module_id);
+       if (err)
+               return err;
+
+       switch (module_id) {
+       case MLX5_MODULE_ID_SFP:
+               if (params->page > 0)
+                       return -EINVAL;
+               break;
+       case MLX5_MODULE_ID_QSFP:
+       case MLX5_MODULE_ID_QSFP28:
+       case MLX5_MODULE_ID_QSFP_PLUS:
+               if (params->page > 3)
+                       return -EINVAL;
+               break;
+       default:
+               mlx5_core_err(dev, "Module ID not recognized: 0x%x\n", module_id);
+               return -EINVAL;
+       }
+
+       if (params->i2c_address != MLX5_I2C_ADDR_HIGH &&
+           params->i2c_address != MLX5_I2C_ADDR_LOW) {
+               mlx5_core_err(dev, "I2C address not recognized: 0x%x\n", params->i2c_address);
+               return -EINVAL;
+       }
+
+       return mlx5_query_mcia(dev, params, data);
+}
+EXPORT_SYMBOL_GPL(mlx5_query_module_eeprom_by_page);
+
 static int mlx5_query_port_pvlc(struct mlx5_core_dev *dev, u32 *pvlc,
                                int pvlc_size,  u8 local_port)
 {
index 90b87aa82db318e308bb154ea3f066edf16bc197..58d56adb984208fbdc1be327f34cfb749adbf4c1 100644 (file)
@@ -209,6 +209,8 @@ void mlx5_query_port_fcs(struct mlx5_core_dev *mdev, bool *supported,
                         bool *enabled);
 int mlx5_query_module_eeprom(struct mlx5_core_dev *dev,
                             u16 offset, u16 size, u8 *data);
+int mlx5_query_module_eeprom_by_page(struct mlx5_core_dev *dev,
+                                    struct mlx5_module_eeprom_query_params *params, u8 *data);
 
 int mlx5_query_port_dcbx_param(struct mlx5_core_dev *mdev, u32 *out);
 int mlx5_set_port_dcbx_param(struct mlx5_core_dev *mdev, u32 *in);