aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c38
1 files changed, 30 insertions, 8 deletions
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
index 5150e9e2b718..d64559e4aff7 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
@@ -1030,13 +1030,14 @@ static void mlxsw_sp_fdb_notify_mac_process(struct mlxsw_sp *mlxsw_sp,
char mac[ETH_ALEN];
u8 local_port;
u16 vid, fid;
+ bool do_notification = true;
int err;
mlxsw_reg_sfn_mac_unpack(sfn_pl, rec_index, mac, &fid, &local_port);
mlxsw_sp_port = mlxsw_sp->ports[local_port];
if (!mlxsw_sp_port) {
dev_err_ratelimited(mlxsw_sp->bus_info->dev, "Incorrect local port in FDB notification\n");
- return;
+ goto just_remove;
}
if (mlxsw_sp_fid_is_vfid(fid)) {
@@ -1047,9 +1048,8 @@ static void mlxsw_sp_fdb_notify_mac_process(struct mlxsw_sp *mlxsw_sp,
vfid);
if (!mlxsw_sp_vport) {
netdev_err(mlxsw_sp_port->dev, "Failed to find a matching vPort following FDB notification\n");
- return;
+ goto just_remove;
}
-
vid = mlxsw_sp_vport_vid_get(mlxsw_sp_vport);
/* Override the physical port with the vPort. */
mlxsw_sp_port = mlxsw_sp_vport;
@@ -1057,17 +1057,28 @@ static void mlxsw_sp_fdb_notify_mac_process(struct mlxsw_sp *mlxsw_sp,
vid = fid;
}
+ adding = adding && mlxsw_sp_port->learning;
+
+do_fdb_op:
err = mlxsw_sp_port_fdb_uc_op(mlxsw_sp, local_port, mac, fid,
- adding && mlxsw_sp_port->learning, true);
+ adding, true);
if (err) {
if (net_ratelimit())
netdev_err(mlxsw_sp_port->dev, "Failed to set FDB entry\n");
return;
}
+ if (!do_notification)
+ return;
mlxsw_sp_fdb_call_notifiers(mlxsw_sp_port->learning,
mlxsw_sp_port->learning_sync,
adding, mac, vid, mlxsw_sp_port->dev);
+ return;
+
+just_remove:
+ adding = false;
+ do_notification = false;
+ goto do_fdb_op;
}
static void mlxsw_sp_fdb_notify_mac_lag_process(struct mlxsw_sp *mlxsw_sp,
@@ -1079,13 +1090,14 @@ static void mlxsw_sp_fdb_notify_mac_lag_process(struct mlxsw_sp *mlxsw_sp,
u16 lag_vid = 0;
u16 lag_id;
u16 vid, fid;
+ bool do_notification = true;
int err;
mlxsw_reg_sfn_mac_lag_unpack(sfn_pl, rec_index, mac, &fid, &lag_id);
mlxsw_sp_port = mlxsw_sp_lag_rep_port(mlxsw_sp, lag_id);
if (!mlxsw_sp_port) {
dev_err_ratelimited(mlxsw_sp->bus_info->dev, "Cannot find port representor for LAG\n");
- return;
+ goto just_remove;
}
if (mlxsw_sp_fid_is_vfid(fid)) {
@@ -1096,7 +1108,7 @@ static void mlxsw_sp_fdb_notify_mac_lag_process(struct mlxsw_sp *mlxsw_sp,
vfid);
if (!mlxsw_sp_vport) {
netdev_err(mlxsw_sp_port->dev, "Failed to find a matching vPort following FDB notification\n");
- return;
+ goto just_remove;
}
vid = mlxsw_sp_vport_vid_get(mlxsw_sp_vport);
@@ -1107,19 +1119,29 @@ static void mlxsw_sp_fdb_notify_mac_lag_process(struct mlxsw_sp *mlxsw_sp,
vid = fid;
}
+ adding = adding && mlxsw_sp_port->learning;
+
+do_fdb_op:
err = mlxsw_sp_port_fdb_uc_lag_op(mlxsw_sp, lag_id, mac, fid, lag_vid,
- adding && mlxsw_sp_port->learning,
- true);
+ adding, true);
if (err) {
if (net_ratelimit())
netdev_err(mlxsw_sp_port->dev, "Failed to set FDB entry\n");
return;
}
+ if (!do_notification)
+ return;
mlxsw_sp_fdb_call_notifiers(mlxsw_sp_port->learning,
mlxsw_sp_port->learning_sync,
adding, mac, vid,
mlxsw_sp_lag_get(mlxsw_sp, lag_id)->dev);
+ return;
+
+just_remove:
+ adding = false;
+ do_notification = false;
+ goto do_fdb_op;
}
static void mlxsw_sp_fdb_notify_rec_process(struct mlxsw_sp *mlxsw_sp,