Commit e109d2b2 authored by Vladyslav Tarasiuk's avatar Vladyslav Tarasiuk Committed by David S. Miller
Browse files

net/mlx5: Implement get_module_eeprom_by_page()



Implement ethtool_ops::get_module_eeprom_by_page() to enable
support of new SFP standards.

Signed-off-by: default avatarVladyslav Tarasiuk <vladyslavt@nvidia.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent e19b0a34
Loading
Loading
Loading
Loading
+44 −0
Original line number Diff line number Diff line
@@ -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,
+41 −0
Original line number Diff line number Diff line
@@ -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)
{
+2 −0
Original line number Diff line number Diff line
@@ -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);