Commit 354e1f9d authored by David S. Miller's avatar David S. Miller
Browse files

Merge tag 'mlx5-updates-2021-08-16' of git://git.kernel.org/pub/scm/linux/kernel/git/saeed/linux



Saeed Mahameed says:

====================
mlx5-updates-2021-08-16

The following patchset provides two separate mlx5 updates
1) Ethtool RSS context and MQPRIO channel mode support:
  1.1) enable mlx5e netdev driver to allow creating Transport Interface RX
       (TIRs) objects on the fly to be used for ethtool RSS contexts and
       TX MQPRIO channel mode
  1.2) Introduce mlx5e_rss object to manage such TIRs.
  1.3) Ethtool support for RSS context
  1.4) Support MQPRIO channel mode

2) Bridge offloads Lag support:
   to allow adding bond net devices to mlx5 bridge
  2.1) Address bridge port by (vport_num, esw_owner_vhca_id) pair
       since vport_num is only unique per eswitch and in lag mode we
       need to manage ports from both eswitches.
  2.2) Allow connectivity between representors of different eswitch
       instances that are attached to same bridge
  2.3) Bridge LAG, Require representors to be in shared FDB mode and
       introduce local and peer ports representors,
       match on paired eswitch metadata in peer FDB entries,
       And finally support addition/deletion and aging of peer flows.
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents e3faa49b ff9b7521
Loading
Loading
Loading
Loading
+3 −3
Original line number Diff line number Diff line
@@ -22,13 +22,13 @@ mlx5_core-y := main.o cmd.o debugfs.o fw.o eq.o uar.o pagealloc.o \
#
# Netdev basic
#
mlx5_core-$(CONFIG_MLX5_CORE_EN) += en_main.o en_common.o en_fs.o en_ethtool.o \
mlx5_core-$(CONFIG_MLX5_CORE_EN) += en/rqt.o en/tir.o en/rss.o en/rx_res.o \
		en/channels.o en_main.o en_common.o en_fs.o en_ethtool.o \
		en_tx.o en_rx.o en_dim.o en_txrx.o en/xdp.o en_stats.o \
		en_selftest.o en/port.o en/monitor_stats.o en/health.o \
		en/reporter_tx.o en/reporter_rx.o en/params.o en/xsk/pool.o \
		en/xsk/setup.o en/xsk/rx.o en/xsk/tx.o en/devlink.o en/ptp.o \
		en/qos.o en/trap.o en/fs_tt_redirect.o en/rqt.o en/tir.o \
		en/rx_res.o en/channels.o
		en/qos.o en/trap.o en/fs_tt_redirect.o

#
# Netdev extra
+11 −1
Original line number Diff line number Diff line
@@ -72,6 +72,7 @@ struct page_pool;
#define MLX5E_SW2HW_MTU(params, swmtu) ((swmtu) + ((params)->hard_mtu))

#define MLX5E_MAX_NUM_TC	8
#define MLX5E_MAX_NUM_MQPRIO_CH_TC TC_QOPT_MAX_QUEUE

#define MLX5_RX_HEADROOM NET_SKB_PAD
#define MLX5_SKB_FRAG_SZ(len)	(SKB_DATA_ALIGN(len) +	\
@@ -248,7 +249,10 @@ struct mlx5e_params {
	u8  rq_wq_type;
	u8  log_rq_mtu_frames;
	u16 num_channels;
	struct {
		u16 mode;
		u8 num_tc;
	} mqprio;
	bool rx_cqe_compress_def;
	bool tunneled_offload_en;
	struct dim_cq_moder rx_cq_moderation;
@@ -268,6 +272,12 @@ struct mlx5e_params {
	bool ptp_rx;
};

static inline u8 mlx5e_get_dcb_num_tc(struct mlx5e_params *params)
{
	return params->mqprio.mode == TC_MQPRIO_MODE_DCB ?
		params->mqprio.num_tc : 1;
}

enum {
	MLX5E_RQ_STATE_ENABLED,
	MLX5E_RQ_STATE_RECOVERING,
+11 −7
Original line number Diff line number Diff line
@@ -326,13 +326,14 @@ static int mlx5e_ptp_open_txqsqs(struct mlx5e_ptp *c,
				 struct mlx5e_ptp_params *cparams)
{
	struct mlx5e_params *params = &cparams->params;
	u8 num_tc = mlx5e_get_dcb_num_tc(params);
	int ix_base;
	int err;
	int tc;

	ix_base = params->num_tc * params->num_channels;
	ix_base = num_tc * params->num_channels;

	for (tc = 0; tc < params->num_tc; tc++) {
	for (tc = 0; tc < num_tc; tc++) {
		int txq_ix = ix_base + tc;

		err = mlx5e_ptp_open_txqsq(c, c->priv->tisn[c->lag_port][tc], txq_ix,
@@ -365,9 +366,12 @@ static int mlx5e_ptp_open_tx_cqs(struct mlx5e_ptp *c,
	struct mlx5e_create_cq_param ccp = {};
	struct dim_cq_moder ptp_moder = {};
	struct mlx5e_cq_param *cq_param;
	u8 num_tc;
	int err;
	int tc;

	num_tc = mlx5e_get_dcb_num_tc(params);

	ccp.node     = dev_to_node(mlx5_core_dma_dev(c->mdev));
	ccp.ch_stats = c->stats;
	ccp.napi     = &c->napi;
@@ -375,7 +379,7 @@ static int mlx5e_ptp_open_tx_cqs(struct mlx5e_ptp *c,

	cq_param = &cparams->txq_sq_param.cqp;

	for (tc = 0; tc < params->num_tc; tc++) {
	for (tc = 0; tc < num_tc; tc++) {
		struct mlx5e_cq *cq = &c->ptpsq[tc].txqsq.cq;

		err = mlx5e_open_cq(c->priv, ptp_moder, cq_param, &ccp, cq);
@@ -383,7 +387,7 @@ static int mlx5e_ptp_open_tx_cqs(struct mlx5e_ptp *c,
			goto out_err_txqsq_cq;
	}

	for (tc = 0; tc < params->num_tc; tc++) {
	for (tc = 0; tc < num_tc; tc++) {
		struct mlx5e_cq *cq = &c->ptpsq[tc].ts_cq;
		struct mlx5e_ptpsq *ptpsq = &c->ptpsq[tc];

@@ -399,7 +403,7 @@ static int mlx5e_ptp_open_tx_cqs(struct mlx5e_ptp *c,
out_err_ts_cq:
	for (--tc; tc >= 0; tc--)
		mlx5e_close_cq(&c->ptpsq[tc].ts_cq);
	tc = params->num_tc;
	tc = num_tc;
out_err_txqsq_cq:
	for (--tc; tc >= 0; tc--)
		mlx5e_close_cq(&c->ptpsq[tc].txqsq.cq);
@@ -475,7 +479,7 @@ static void mlx5e_ptp_build_params(struct mlx5e_ptp *c,
	params->num_channels = orig->num_channels;
	params->hard_mtu = orig->hard_mtu;
	params->sw_mtu = orig->sw_mtu;
	params->num_tc = orig->num_tc;
	params->mqprio = orig->mqprio;

	/* SQ */
	if (test_bit(MLX5E_PTP_STATE_TX, c->state)) {
@@ -680,7 +684,7 @@ int mlx5e_ptp_open(struct mlx5e_priv *priv, struct mlx5e_params *params,
	c->pdev     = mlx5_core_dma_dev(priv->mdev);
	c->netdev   = priv->netdev;
	c->mkey_be  = cpu_to_be32(priv->mdev->mlx5e_res.hw_objs.mkey.key);
	c->num_tc   = params->num_tc;
	c->num_tc   = mlx5e_get_dcb_num_tc(params);
	c->stats    = &priv->ptp_stats.ch;
	c->lag_port = lag_port;

+1 −1
Original line number Diff line number Diff line
@@ -132,7 +132,7 @@ static u16 mlx5e_qid_from_qos(struct mlx5e_channels *chs, u16 qid)
	 */
	bool is_ptp = MLX5E_GET_PFLAG(&chs->params, MLX5E_PFLAG_TX_PORT_TS);

	return (chs->params.num_channels + is_ptp) * chs->params.num_tc + qid;
	return (chs->params.num_channels + is_ptp) * mlx5e_get_dcb_num_tc(&chs->params) + qid;
}

int mlx5e_get_txq_by_classid(struct mlx5e_priv *priv, u16 classid)
+218 −111
Original line number Diff line number Diff line
@@ -15,9 +15,116 @@ struct mlx5_bridge_switchdev_fdb_work {
	struct work_struct work;
	struct switchdev_notifier_fdb_info fdb_info;
	struct net_device *dev;
	struct mlx5_esw_bridge_offloads *br_offloads;
	bool add;
};

static bool mlx5_esw_bridge_dev_same_esw(struct net_device *dev, struct mlx5_eswitch *esw)
{
	struct mlx5e_priv *priv = netdev_priv(dev);

	return esw == priv->mdev->priv.eswitch;
}

static bool mlx5_esw_bridge_dev_same_hw(struct net_device *dev, struct mlx5_eswitch *esw)
{
	struct mlx5e_priv *priv = netdev_priv(dev);
	struct mlx5_core_dev *mdev, *esw_mdev;
	u64 system_guid, esw_system_guid;

	mdev = priv->mdev;
	esw_mdev = esw->dev;

	system_guid = mlx5_query_nic_system_image_guid(mdev);
	esw_system_guid = mlx5_query_nic_system_image_guid(esw_mdev);

	return system_guid == esw_system_guid;
}

static struct net_device *
mlx5_esw_bridge_lag_rep_get(struct net_device *dev, struct mlx5_eswitch *esw)
{
	struct net_device *lower;
	struct list_head *iter;

	netdev_for_each_lower_dev(dev, lower, iter) {
		struct mlx5_core_dev *mdev;
		struct mlx5e_priv *priv;

		if (!mlx5e_eswitch_rep(lower))
			continue;

		priv = netdev_priv(lower);
		mdev = priv->mdev;
		if (mlx5_lag_is_shared_fdb(mdev) && mlx5_esw_bridge_dev_same_esw(lower, esw))
			return lower;
	}

	return NULL;
}

static struct net_device *
mlx5_esw_bridge_rep_vport_num_vhca_id_get(struct net_device *dev, struct mlx5_eswitch *esw,
					  u16 *vport_num, u16 *esw_owner_vhca_id)
{
	struct mlx5e_rep_priv *rpriv;
	struct mlx5e_priv *priv;

	if (netif_is_lag_master(dev))
		dev = mlx5_esw_bridge_lag_rep_get(dev, esw);

	if (!dev || !mlx5e_eswitch_rep(dev) || !mlx5_esw_bridge_dev_same_hw(dev, esw))
		return NULL;

	priv = netdev_priv(dev);
	rpriv = priv->ppriv;
	*vport_num = rpriv->rep->vport;
	*esw_owner_vhca_id = MLX5_CAP_GEN(priv->mdev, vhca_id);
	return dev;
}

static struct net_device *
mlx5_esw_bridge_lower_rep_vport_num_vhca_id_get(struct net_device *dev, struct mlx5_eswitch *esw,
						u16 *vport_num, u16 *esw_owner_vhca_id)
{
	struct net_device *lower_dev;
	struct list_head *iter;

	if (netif_is_lag_master(dev) || mlx5e_eswitch_rep(dev))
		return mlx5_esw_bridge_rep_vport_num_vhca_id_get(dev, esw, vport_num,
								 esw_owner_vhca_id);

	netdev_for_each_lower_dev(dev, lower_dev, iter) {
		struct net_device *rep;

		if (netif_is_bridge_master(lower_dev))
			continue;

		rep = mlx5_esw_bridge_lower_rep_vport_num_vhca_id_get(lower_dev, esw, vport_num,
								      esw_owner_vhca_id);
		if (rep)
			return rep;
	}

	return NULL;
}

static bool mlx5_esw_bridge_is_local(struct net_device *dev, struct net_device *rep,
				     struct mlx5_eswitch *esw)
{
	struct mlx5_core_dev *mdev;
	struct mlx5e_priv *priv;

	if (!mlx5_esw_bridge_dev_same_esw(rep, esw))
		return false;

	priv = netdev_priv(rep);
	mdev = priv->mdev;
	if (netif_is_lag_master(dev))
		return mlx5_lag_is_shared_fdb(mdev) && mlx5_lag_is_master(mdev);
	return true;
}

static int mlx5_esw_bridge_port_changeupper(struct notifier_block *nb, void *ptr)
{
	struct mlx5_esw_bridge_offloads *br_offloads = container_of(nb,
@@ -25,37 +132,36 @@ static int mlx5_esw_bridge_port_changeupper(struct notifier_block *nb, void *ptr
								    netdev_nb);
	struct net_device *dev = netdev_notifier_info_to_dev(ptr);
	struct netdev_notifier_changeupper_info *info = ptr;
	struct net_device *upper = info->upper_dev, *rep;
	struct mlx5_eswitch *esw = br_offloads->esw;
	u16 vport_num, esw_owner_vhca_id;
	struct netlink_ext_ack *extack;
	struct mlx5e_rep_priv *rpriv;
	struct mlx5_eswitch *esw;
	struct mlx5_vport *vport;
	struct net_device *upper;
	struct mlx5e_priv *priv;
	u16 vport_num;

	if (!mlx5e_eswitch_rep(dev))
		return 0;
	int ifindex = upper->ifindex;
	int err;

	upper = info->upper_dev;
	if (!netif_is_bridge_master(upper))
		return 0;

	esw = br_offloads->esw;
	priv = netdev_priv(dev);
	if (esw != priv->mdev->priv.eswitch)
	rep = mlx5_esw_bridge_rep_vport_num_vhca_id_get(dev, esw, &vport_num, &esw_owner_vhca_id);
	if (!rep)
		return 0;

	rpriv = priv->ppriv;
	vport_num = rpriv->rep->vport;
	vport = mlx5_eswitch_get_vport(esw, vport_num);
	if (IS_ERR(vport))
		return PTR_ERR(vport);

	extack = netdev_notifier_info_to_extack(&info->info);

	return info->linking ?
		mlx5_esw_bridge_vport_link(upper->ifindex, br_offloads, vport, extack) :
		mlx5_esw_bridge_vport_unlink(upper->ifindex, br_offloads, vport, extack);
	if (mlx5_esw_bridge_is_local(dev, rep, esw))
		err = info->linking ?
			mlx5_esw_bridge_vport_link(ifindex, vport_num, esw_owner_vhca_id,
						   br_offloads, extack) :
			mlx5_esw_bridge_vport_unlink(ifindex, vport_num, esw_owner_vhca_id,
						     br_offloads, extack);
	else if (mlx5_esw_bridge_dev_same_hw(rep, esw))
		err = info->linking ?
			mlx5_esw_bridge_vport_peer_link(ifindex, vport_num, esw_owner_vhca_id,
							br_offloads, extack) :
			mlx5_esw_bridge_vport_peer_unlink(ifindex, vport_num, esw_owner_vhca_id,
							  br_offloads, extack);

	return err;
}

static int mlx5_esw_bridge_switchdev_port_event(struct notifier_block *nb,
@@ -75,31 +181,28 @@ static int mlx5_esw_bridge_switchdev_port_event(struct notifier_block *nb,
	return notifier_from_errno(err);
}

static int mlx5_esw_bridge_port_obj_add(struct net_device *dev,
					const void *ctx,
					const struct switchdev_obj *obj,
					struct netlink_ext_ack *extack)
static int
mlx5_esw_bridge_port_obj_add(struct net_device *dev,
			     struct switchdev_notifier_port_obj_info *port_obj_info,
			     struct mlx5_esw_bridge_offloads *br_offloads)
{
	struct netlink_ext_ack *extack = switchdev_notifier_info_to_extack(&port_obj_info->info);
	const struct switchdev_obj *obj = port_obj_info->obj;
	const struct switchdev_obj_port_vlan *vlan;
	struct mlx5e_rep_priv *rpriv;
	struct mlx5_eswitch *esw;
	struct mlx5_vport *vport;
	struct mlx5e_priv *priv;
	u16 vport_num;
	int err = 0;
	u16 vport_num, esw_owner_vhca_id;
	int err;

	priv = netdev_priv(dev);
	rpriv = priv->ppriv;
	vport_num = rpriv->rep->vport;
	esw = priv->mdev->priv.eswitch;
	vport = mlx5_eswitch_get_vport(esw, vport_num);
	if (IS_ERR(vport))
		return PTR_ERR(vport);
	if (!mlx5_esw_bridge_rep_vport_num_vhca_id_get(dev, br_offloads->esw, &vport_num,
						       &esw_owner_vhca_id))
		return 0;

	port_obj_info->handled = true;

	switch (obj->id) {
	case SWITCHDEV_OBJ_ID_PORT_VLAN:
		vlan = SWITCHDEV_OBJ_PORT_VLAN(obj);
		err = mlx5_esw_bridge_port_vlan_add(vlan->vid, vlan->flags, esw, vport, extack);
		err = mlx5_esw_bridge_port_vlan_add(vport_num, esw_owner_vhca_id, vlan->vid,
						    vlan->flags, br_offloads, extack);
		break;
	default:
		return -EOPNOTSUPP;
@@ -107,29 +210,25 @@ static int mlx5_esw_bridge_port_obj_add(struct net_device *dev,
	return err;
}

static int mlx5_esw_bridge_port_obj_del(struct net_device *dev,
					const void *ctx,
					const struct switchdev_obj *obj)
static int
mlx5_esw_bridge_port_obj_del(struct net_device *dev,
			     struct switchdev_notifier_port_obj_info *port_obj_info,
			     struct mlx5_esw_bridge_offloads *br_offloads)
{
	const struct switchdev_obj *obj = port_obj_info->obj;
	const struct switchdev_obj_port_vlan *vlan;
	struct mlx5e_rep_priv *rpriv;
	struct mlx5_eswitch *esw;
	struct mlx5_vport *vport;
	struct mlx5e_priv *priv;
	u16 vport_num;
	u16 vport_num, esw_owner_vhca_id;

	priv = netdev_priv(dev);
	rpriv = priv->ppriv;
	vport_num = rpriv->rep->vport;
	esw = priv->mdev->priv.eswitch;
	vport = mlx5_eswitch_get_vport(esw, vport_num);
	if (IS_ERR(vport))
		return PTR_ERR(vport);
	if (!mlx5_esw_bridge_rep_vport_num_vhca_id_get(dev, br_offloads->esw, &vport_num,
						       &esw_owner_vhca_id))
		return 0;

	port_obj_info->handled = true;

	switch (obj->id) {
	case SWITCHDEV_OBJ_ID_PORT_VLAN:
		vlan = SWITCHDEV_OBJ_PORT_VLAN(obj);
		mlx5_esw_bridge_port_vlan_del(vlan->vid, esw, vport);
		mlx5_esw_bridge_port_vlan_del(vport_num, esw_owner_vhca_id, vlan->vid, br_offloads);
		break;
	default:
		return -EOPNOTSUPP;
@@ -137,25 +236,21 @@ static int mlx5_esw_bridge_port_obj_del(struct net_device *dev,
	return 0;
}

static int mlx5_esw_bridge_port_obj_attr_set(struct net_device *dev,
					     const void *ctx,
					     const struct switchdev_attr *attr,
					     struct netlink_ext_ack *extack)
static int
mlx5_esw_bridge_port_obj_attr_set(struct net_device *dev,
				  struct switchdev_notifier_port_attr_info *port_attr_info,
				  struct mlx5_esw_bridge_offloads *br_offloads)
{
	struct mlx5e_rep_priv *rpriv;
	struct mlx5_eswitch *esw;
	struct mlx5_vport *vport;
	struct mlx5e_priv *priv;
	u16 vport_num;
	int err = 0;
	struct netlink_ext_ack *extack = switchdev_notifier_info_to_extack(&port_attr_info->info);
	const struct switchdev_attr *attr = port_attr_info->attr;
	u16 vport_num, esw_owner_vhca_id;
	int err;

	priv = netdev_priv(dev);
	rpriv = priv->ppriv;
	vport_num = rpriv->rep->vport;
	esw = priv->mdev->priv.eswitch;
	vport = mlx5_eswitch_get_vport(esw, vport_num);
	if (IS_ERR(vport))
		return PTR_ERR(vport);
	if (!mlx5_esw_bridge_lower_rep_vport_num_vhca_id_get(dev, br_offloads->esw, &vport_num,
							     &esw_owner_vhca_id))
		return 0;

	port_attr_info->handled = true;

	switch (attr->id) {
	case SWITCHDEV_ATTR_ID_PORT_PRE_BRIDGE_FLAGS:
@@ -167,10 +262,12 @@ static int mlx5_esw_bridge_port_obj_attr_set(struct net_device *dev,
	case SWITCHDEV_ATTR_ID_PORT_BRIDGE_FLAGS:
		break;
	case SWITCHDEV_ATTR_ID_BRIDGE_AGEING_TIME:
		err = mlx5_esw_bridge_ageing_time_set(attr->u.ageing_time, esw, vport);
		err = mlx5_esw_bridge_ageing_time_set(vport_num, esw_owner_vhca_id,
						      attr->u.ageing_time, br_offloads);
		break;
	case SWITCHDEV_ATTR_ID_BRIDGE_VLAN_FILTERING:
		err = mlx5_esw_bridge_vlan_filtering_set(attr->u.vlan_filtering, esw, vport);
		err = mlx5_esw_bridge_vlan_filtering_set(vport_num, esw_owner_vhca_id,
							 attr->u.vlan_filtering, br_offloads);
		break;
	default:
		err = -EOPNOTSUPP;
@@ -179,27 +276,24 @@ static int mlx5_esw_bridge_port_obj_attr_set(struct net_device *dev,
	return err;
}

static int mlx5_esw_bridge_event_blocking(struct notifier_block *unused,
static int mlx5_esw_bridge_event_blocking(struct notifier_block *nb,
					  unsigned long event, void *ptr)
{
	struct mlx5_esw_bridge_offloads *br_offloads = container_of(nb,
								    struct mlx5_esw_bridge_offloads,
								    nb_blk);
	struct net_device *dev = switchdev_notifier_info_to_dev(ptr);
	int err;

	switch (event) {
	case SWITCHDEV_PORT_OBJ_ADD:
		err = switchdev_handle_port_obj_add(dev, ptr,
						    mlx5e_eswitch_rep,
						    mlx5_esw_bridge_port_obj_add);
		err = mlx5_esw_bridge_port_obj_add(dev, ptr, br_offloads);
		break;
	case SWITCHDEV_PORT_OBJ_DEL:
		err = switchdev_handle_port_obj_del(dev, ptr,
						    mlx5e_eswitch_rep,
						    mlx5_esw_bridge_port_obj_del);
		err = mlx5_esw_bridge_port_obj_del(dev, ptr, br_offloads);
		break;
	case SWITCHDEV_PORT_ATTR_SET:
		err = switchdev_handle_port_attr_set(dev, ptr,
						     mlx5e_eswitch_rep,
						     mlx5_esw_bridge_port_obj_attr_set);
		err = mlx5_esw_bridge_port_obj_attr_set(dev, ptr, br_offloads);
		break;
	default:
		err = 0;
@@ -222,27 +316,23 @@ static void mlx5_esw_bridge_switchdev_fdb_event_work(struct work_struct *work)
		container_of(work, struct mlx5_bridge_switchdev_fdb_work, work);
	struct switchdev_notifier_fdb_info *fdb_info =
		&fdb_work->fdb_info;
	struct mlx5_esw_bridge_offloads *br_offloads =
		fdb_work->br_offloads;
	struct net_device *dev = fdb_work->dev;
	struct mlx5e_rep_priv *rpriv;
	struct mlx5_eswitch *esw;
	struct mlx5_vport *vport;
	struct mlx5e_priv *priv;
	u16 vport_num;
	u16 vport_num, esw_owner_vhca_id;

	rtnl_lock();

	priv = netdev_priv(dev);
	rpriv = priv->ppriv;
	vport_num = rpriv->rep->vport;
	esw = priv->mdev->priv.eswitch;
	vport = mlx5_eswitch_get_vport(esw, vport_num);
	if (IS_ERR(vport))
	if (!mlx5_esw_bridge_rep_vport_num_vhca_id_get(dev, br_offloads->esw, &vport_num,
						       &esw_owner_vhca_id))
		goto out;

	if (fdb_work->add)
		mlx5_esw_bridge_fdb_create(dev, esw, vport, fdb_info);
		mlx5_esw_bridge_fdb_create(dev, vport_num, esw_owner_vhca_id, br_offloads,
					   fdb_info);
	else
		mlx5_esw_bridge_fdb_remove(dev, esw, vport, fdb_info);
		mlx5_esw_bridge_fdb_remove(dev, vport_num, esw_owner_vhca_id, br_offloads,
					   fdb_info);

out:
	rtnl_unlock();
@@ -251,7 +341,8 @@ static void mlx5_esw_bridge_switchdev_fdb_event_work(struct work_struct *work)

static struct mlx5_bridge_switchdev_fdb_work *
mlx5_esw_bridge_init_switchdev_fdb_work(struct net_device *dev, bool add,
					struct switchdev_notifier_fdb_info *fdb_info)
					struct switchdev_notifier_fdb_info *fdb_info,
					struct mlx5_esw_bridge_offloads *br_offloads)
{
	struct mlx5_bridge_switchdev_fdb_work *work;
	u8 *addr;
@@ -273,6 +364,7 @@ mlx5_esw_bridge_init_switchdev_fdb_work(struct net_device *dev, bool add,

	dev_hold(dev);
	work->dev = dev;
	work->br_offloads = br_offloads;
	work->add = add;
	return work;
}
@@ -286,20 +378,14 @@ static int mlx5_esw_bridge_switchdev_event(struct notifier_block *nb,
	struct net_device *dev = switchdev_notifier_info_to_dev(ptr);
	struct switchdev_notifier_fdb_info *fdb_info;
	struct mlx5_bridge_switchdev_fdb_work *work;
	struct mlx5_eswitch *esw = br_offloads->esw;
	struct switchdev_notifier_info *info = ptr;
	struct net_device *upper;
	struct mlx5e_priv *priv;

	if (!mlx5e_eswitch_rep(dev))
		return NOTIFY_DONE;
	priv = netdev_priv(dev);
	if (priv->mdev->priv.eswitch != br_offloads->esw)
		return NOTIFY_DONE;
	u16 vport_num, esw_owner_vhca_id;
	struct net_device *upper, *rep;

	if (event == SWITCHDEV_PORT_ATTR_SET) {
		int err = switchdev_handle_port_attr_set(dev, ptr,
							 mlx5e_eswitch_rep,
							 mlx5_esw_bridge_port_obj_attr_set);
		int err = mlx5_esw_bridge_port_obj_attr_set(dev, ptr, br_offloads);

		return notifier_from_errno(err);
	}

@@ -309,7 +395,27 @@ static int mlx5_esw_bridge_switchdev_event(struct notifier_block *nb,
	if (!netif_is_bridge_master(upper))
		return NOTIFY_DONE;

	rep = mlx5_esw_bridge_rep_vport_num_vhca_id_get(dev, esw, &vport_num, &esw_owner_vhca_id);
	if (!rep)
		return NOTIFY_DONE;

	switch (event) {
	case SWITCHDEV_FDB_ADD_TO_BRIDGE:
		/* only handle the event on native eswtich of representor */
		if (!mlx5_esw_bridge_is_local(dev, rep, esw))
			break;

		fdb_info = container_of(info,
					struct switchdev_notifier_fdb_info,
					info);
		mlx5_esw_bridge_fdb_update_used(dev, vport_num, esw_owner_vhca_id, br_offloads,
						fdb_info);
		break;
	case SWITCHDEV_FDB_DEL_TO_BRIDGE:
		/* only handle the event on peers */
		if (mlx5_esw_bridge_is_local(dev, rep, esw))
			break;
		fallthrough;
	case SWITCHDEV_FDB_ADD_TO_DEVICE:
	case SWITCHDEV_FDB_DEL_TO_DEVICE:
		fdb_info = container_of(info,
@@ -318,7 +424,8 @@ static int mlx5_esw_bridge_switchdev_event(struct notifier_block *nb,

		work = mlx5_esw_bridge_init_switchdev_fdb_work(dev,
							       event == SWITCHDEV_FDB_ADD_TO_DEVICE,
							       fdb_info);
							       fdb_info,
							       br_offloads);
		if (IS_ERR(work)) {
			WARN_ONCE(1, "Failed to init switchdev work, err=%ld",
				  PTR_ERR(work));
Loading