Commit 416a01a4 authored by Paolo Abeni's avatar Paolo Abeni
Browse files

Merge tag 'mlx5-updates-2023-09-19' of git://git.kernel.org/pub/scm/linux/kernel/git/saeed/linux

Saeed Mahameed says:

====================
mlx5-updates-2023-09-19

Misc updates for mlx5 driver

1) From Erez, Add support for multicast forwarding to multi destination
   in bridge offloads with software steering mode (SMFS).

2) From Jianbo, Utilize the maximum aggregated link speed for police
   action rate.

3) From Moshe, Add a health error syndrome for pci data poisoned

4) From Shay, Enable 4 ports multiport E-switch

5) From Jiri, Trivial SF code cleanup

====================

Link: https://lore.kernel.org/r/20230920063552.296978-1-saeed@kernel.org


Signed-off-by: default avatarPaolo Abeni <pabeni@redhat.com>
parents c1fec890 e738e355
Loading
Loading
Loading
Loading
+2 −9
Original line number Diff line number Diff line
@@ -78,6 +78,8 @@ mlx5_esw_bridge_mdb_flow_create(u16 esw_owner_vhca_id, struct mlx5_esw_bridge_md
	xa_for_each(&entry->ports, idx, port) {
		dests[i].type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE;
		dests[i].ft = port->mcast.ft;
		if (port->vport_num == MLX5_VPORT_UPLINK)
			dests[i].ft->flags |= MLX5_FLOW_TABLE_UPLINK_VPORT;
		i++;
	}

@@ -585,10 +587,6 @@ mlx5_esw_bridge_mcast_vlan_flow_create(u16 vlan_proto, struct mlx5_esw_bridge_po
	if (!rule_spec)
		return ERR_PTR(-ENOMEM);

	if (MLX5_CAP_ESW_FLOWTABLE(bridge->br_offloads->esw->dev, flow_source) &&
	    port->vport_num == MLX5_VPORT_UPLINK)
		rule_spec->flow_context.flow_source =
			MLX5_FLOW_CONTEXT_FLOW_SOURCE_LOCAL_VPORT;
	rule_spec->match_criteria_enable = MLX5_MATCH_OUTER_HEADERS;

	flow_act.action |= MLX5_FLOW_CONTEXT_ACTION_PACKET_REFORMAT;
@@ -660,11 +658,6 @@ mlx5_esw_bridge_mcast_fwd_flow_create(struct mlx5_esw_bridge_port *port)
	if (!rule_spec)
		return ERR_PTR(-ENOMEM);

	if (MLX5_CAP_ESW_FLOWTABLE(bridge->br_offloads->esw->dev, flow_source) &&
	    port->vport_num == MLX5_VPORT_UPLINK)
		rule_spec->flow_context.flow_source =
			MLX5_FLOW_CONTEXT_FLOW_SOURCE_LOCAL_VPORT;

	if (MLX5_CAP_ESW(bridge->br_offloads->esw->dev, merged_eswitch)) {
		dest.vport.flags = MLX5_FLOW_DEST_VPORT_VHCA_ID;
		dest.vport.vhca_id = port->esw_owner_vhca_id;
+84 −12
Original line number Diff line number Diff line
@@ -2,6 +2,7 @@
/* Copyright (c) 2021, NVIDIA CORPORATION & AFFILIATES. All rights reserved. */

#include "eswitch.h"
#include "lib/mlx5.h"
#include "esw/qos.h"
#include "en/port.h"
#define CREATE_TRACE_POINTS
@@ -701,10 +702,75 @@ int mlx5_esw_qos_set_vport_rate(struct mlx5_eswitch *esw, struct mlx5_vport *vpo
	return err;
}

static u32 mlx5_esw_qos_lag_link_speed_get_locked(struct mlx5_core_dev *mdev)
{
	struct ethtool_link_ksettings lksettings;
	struct net_device *slave, *master;
	u32 speed = SPEED_UNKNOWN;

	/* Lock ensures a stable reference to master and slave netdevice
	 * while port speed of master is queried.
	 */
	ASSERT_RTNL();

	slave = mlx5_uplink_netdev_get(mdev);
	if (!slave)
		goto out;

	master = netdev_master_upper_dev_get(slave);
	if (master && !__ethtool_get_link_ksettings(master, &lksettings))
		speed = lksettings.base.speed;

out:
	return speed;
}

static int mlx5_esw_qos_max_link_speed_get(struct mlx5_core_dev *mdev, u32 *link_speed_max,
					   bool hold_rtnl_lock, struct netlink_ext_ack *extack)
{
	int err;

	if (!mlx5_lag_is_active(mdev))
		goto skip_lag;

	if (hold_rtnl_lock)
		rtnl_lock();

	*link_speed_max = mlx5_esw_qos_lag_link_speed_get_locked(mdev);

	if (hold_rtnl_lock)
		rtnl_unlock();

	if (*link_speed_max != (u32)SPEED_UNKNOWN)
		return 0;

skip_lag:
	err = mlx5_port_max_linkspeed(mdev, link_speed_max);
	if (err)
		NL_SET_ERR_MSG_MOD(extack, "Failed to get link maximum speed");

	return err;
}

static int mlx5_esw_qos_link_speed_verify(struct mlx5_core_dev *mdev,
					  const char *name, u32 link_speed_max,
					  u64 value, struct netlink_ext_ack *extack)
{
	if (value > link_speed_max) {
		pr_err("%s rate value %lluMbps exceed link maximum speed %u.\n",
		       name, value, link_speed_max);
		NL_SET_ERR_MSG_MOD(extack, "TX rate value exceed link maximum speed");
		return -EINVAL;
	}

	return 0;
}

int mlx5_esw_qos_modify_vport_rate(struct mlx5_eswitch *esw, u16 vport_num, u32 rate_mbps)
{
	u32 ctx[MLX5_ST_SZ_DW(scheduling_context)] = {};
	struct mlx5_vport *vport;
	u32 link_speed_max;
	u32 bitmask;
	int err;

@@ -712,6 +778,17 @@ int mlx5_esw_qos_modify_vport_rate(struct mlx5_eswitch *esw, u16 vport_num, u32
	if (IS_ERR(vport))
		return PTR_ERR(vport);

	if (rate_mbps) {
		err = mlx5_esw_qos_max_link_speed_get(esw->dev, &link_speed_max, false, NULL);
		if (err)
			return err;

		err = mlx5_esw_qos_link_speed_verify(esw->dev, "Police",
						     link_speed_max, rate_mbps, NULL);
		if (err)
			return err;
	}

	mutex_lock(&esw->state_lock);
	if (!vport->qos.enabled) {
		/* Eswitch QoS wasn't enabled yet. Enable it and vport QoS. */
@@ -744,12 +821,6 @@ static int esw_qos_devlink_rate_to_mbps(struct mlx5_core_dev *mdev, const char *
	u64 value;
	int err;

	err = mlx5_port_max_linkspeed(mdev, &link_speed_max);
	if (err) {
		NL_SET_ERR_MSG_MOD(extack, "Failed to get link maximum speed");
		return err;
	}

	value = div_u64_rem(*rate, MLX5_LINKSPEED_UNIT, &remainder);
	if (remainder) {
		pr_err("%s rate value %lluBps not in link speed units of 1Mbps.\n",
@@ -758,12 +829,13 @@ static int esw_qos_devlink_rate_to_mbps(struct mlx5_core_dev *mdev, const char *
		return -EINVAL;
	}

	if (value > link_speed_max) {
		pr_err("%s rate value %lluMbps exceed link maximum speed %u.\n",
		       name, value, link_speed_max);
		NL_SET_ERR_MSG_MOD(extack, "TX rate value exceed link maximum speed");
		return -EINVAL;
	}
	err = mlx5_esw_qos_max_link_speed_get(mdev, &link_speed_max, true, extack);
	if (err)
		return err;

	err = mlx5_esw_qos_link_speed_verify(mdev, name, link_speed_max, value, extack);
	if (err)
		return err;

	*rate = value;
	return 0;
+2 −0
Original line number Diff line number Diff line
@@ -365,6 +365,8 @@ static const char *hsynd_str(u8 synd)
		return "FFSER error";
	case MLX5_INITIAL_SEG_HEALTH_SYNDROME_HIGH_TEMP_ERR:
		return "High temperature";
	case MLX5_INITIAL_SEG_HEALTH_SYNDROME_ICM_PCI_POISONED_ERR:
		return "ICM fetch PCI data poisoned error";
	default:
		return "unrecognized error";
	}
+9 −9
Original line number Diff line number Diff line
@@ -65,12 +65,12 @@ static int mlx5_mpesw_metadata_set(struct mlx5_lag *ldev)
	return err;
}

#define MLX5_LAG_MPESW_OFFLOADS_SUPPORTED_PORTS 2
#define MLX5_LAG_MPESW_OFFLOADS_SUPPORTED_PORTS 4
static int enable_mpesw(struct mlx5_lag *ldev)
{
	struct mlx5_core_dev *dev0 = ldev->pf[MLX5_LAG_P1].dev;
	struct mlx5_core_dev *dev1 = ldev->pf[MLX5_LAG_P2].dev;
	int err;
	int i;

	if (ldev->mode != MLX5_LAG_MODE_NONE)
		return -EINVAL;
@@ -98,11 +98,11 @@ static int enable_mpesw(struct mlx5_lag *ldev)

	dev0->priv.flags &= ~MLX5_PRIV_FLAGS_DISABLE_IB_ADEV;
	mlx5_rescan_drivers_locked(dev0);
	err = mlx5_eswitch_reload_reps(dev0->priv.eswitch);
	if (!err)
		err = mlx5_eswitch_reload_reps(dev1->priv.eswitch);
	for (i = 0; i < ldev->ports; i++) {
		err = mlx5_eswitch_reload_reps(ldev->pf[i].dev->priv.eswitch);
		if (err)
			goto err_rescan_drivers;
	}

	return 0;

@@ -112,8 +112,8 @@ static int enable_mpesw(struct mlx5_lag *ldev)
	mlx5_deactivate_lag(ldev);
err_add_devices:
	mlx5_lag_add_devices(ldev);
	mlx5_eswitch_reload_reps(dev0->priv.eswitch);
	mlx5_eswitch_reload_reps(dev1->priv.eswitch);
	for (i = 0; i < ldev->ports; i++)
		mlx5_eswitch_reload_reps(ldev->pf[i].dev->priv.eswitch);
	mlx5_mpesw_metadata_cleanup(ldev);
	return err;
}
+0 −15
Original line number Diff line number Diff line
@@ -14,7 +14,6 @@

struct mlx5_sf_dev_table {
	struct xarray devices;
	unsigned int max_sfs;
	phys_addr_t base_address;
	u64 sf_bar_length;
	struct notifier_block nb;
@@ -110,12 +109,6 @@ static void mlx5_sf_dev_add(struct mlx5_core_dev *dev, u16 sf_index, u16 fn_id,
	sf_dev->parent_mdev = dev;
	sf_dev->fn_id = fn_id;

	if (!table->max_sfs) {
		mlx5_adev_idx_free(id);
		kfree(sf_dev);
		err = -EOPNOTSUPP;
		goto add_err;
	}
	sf_dev->bar_base_addr = table->base_address + (sf_index * table->sf_bar_length);

	trace_mlx5_sf_dev_add(dev, sf_dev, id);
@@ -296,7 +289,6 @@ static void mlx5_sf_dev_destroy_active_work(struct mlx5_sf_dev_table *table)
void mlx5_sf_dev_table_create(struct mlx5_core_dev *dev)
{
	struct mlx5_sf_dev_table *table;
	unsigned int max_sfs;
	int err;

	if (!mlx5_sf_dev_supported(dev))
@@ -310,13 +302,8 @@ void mlx5_sf_dev_table_create(struct mlx5_core_dev *dev)

	table->nb.notifier_call = mlx5_sf_dev_state_change_handler;
	table->dev = dev;
	if (MLX5_CAP_GEN(dev, max_num_sf))
		max_sfs = MLX5_CAP_GEN(dev, max_num_sf);
	else
		max_sfs = 1 << MLX5_CAP_GEN(dev, log_max_sf);
	table->sf_bar_length = 1 << (MLX5_CAP_GEN(dev, log_min_sf_size) + 12);
	table->base_address = pci_resource_start(dev->pdev, 2);
	table->max_sfs = max_sfs;
	xa_init(&table->devices);
	mutex_init(&table->table_lock);
	dev->priv.sf_dev_table = table;
@@ -332,7 +319,6 @@ void mlx5_sf_dev_table_create(struct mlx5_core_dev *dev)
	err = mlx5_sf_dev_vhca_arm_all(table);
	if (err)
		goto arm_err;
	mlx5_core_dbg(dev, "SF DEV: max sf devices=%d\n", max_sfs);
	return;

arm_err:
@@ -340,7 +326,6 @@ void mlx5_sf_dev_table_create(struct mlx5_core_dev *dev)
add_active_err:
	mlx5_vhca_event_notifier_unregister(dev, &table->nb);
vhca_err:
	table->max_sfs = 0;
	kfree(table);
	dev->priv.sf_dev_table = NULL;
table_err:
Loading