]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
net/mlx5: E-Switch, Fix peer miss rules to use peer eswitch
authorShahar Shitrit <shshitrit@nvidia.com>
Thu, 17 Jul 2025 12:06:10 +0000 (15:06 +0300)
committerJakub Kicinski <kuba@kernel.org>
Sat, 19 Jul 2025 00:32:58 +0000 (17:32 -0700)
In the original design, it is assumed local and peer eswitches have the
same number of vfs. However, in new firmware, local and peer eswitches
can have different number of vfs configured by mlxconfig.  In such
configuration, it is incorrect to derive the number of vfs from the
local device's eswitch.

Fix this by updating the peer miss rules add and delete functions to use
the peer device's eswitch and vf count instead of the local device's
information, ensuring correct behavior regardless of vf configuration
differences.

Fixes: ac004b832128 ("net/mlx5e: E-Switch, Add peer miss rules")
Signed-off-by: Shahar Shitrit <shshitrit@nvidia.com>
Reviewed-by: Mark Bloch <mbloch@nvidia.com>
Signed-off-by: Tariq Toukan <tariqt@nvidia.com>
Reviewed-by: Simon Horman <horms@kernel.org>
Link: https://patch.msgid.link/1752753970-261832-3-git-send-email-tariqt@nvidia.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c

index 0e3a977d533298a21977d3b42b98b7445433767a..bee906661282aa2e5c7a83afc82ceb2be5ce691b 100644 (file)
@@ -1182,19 +1182,19 @@ static void esw_set_peer_miss_rule_source_port(struct mlx5_eswitch *esw,
 static int esw_add_fdb_peer_miss_rules(struct mlx5_eswitch *esw,
                                       struct mlx5_core_dev *peer_dev)
 {
+       struct mlx5_eswitch *peer_esw = peer_dev->priv.eswitch;
        struct mlx5_flow_destination dest = {};
        struct mlx5_flow_act flow_act = {0};
        struct mlx5_flow_handle **flows;
-       /* total vports is the same for both e-switches */
-       int nvports = esw->total_vports;
        struct mlx5_flow_handle *flow;
+       struct mlx5_vport *peer_vport;
        struct mlx5_flow_spec *spec;
-       struct mlx5_vport *vport;
        int err, pfindex;
        unsigned long i;
        void *misc;
 
-       if (!MLX5_VPORT_MANAGER(esw->dev) && !mlx5_core_is_ecpf_esw_manager(esw->dev))
+       if (!MLX5_VPORT_MANAGER(peer_dev) &&
+           !mlx5_core_is_ecpf_esw_manager(peer_dev))
                return 0;
 
        spec = kvzalloc(sizeof(*spec), GFP_KERNEL);
@@ -1203,7 +1203,7 @@ static int esw_add_fdb_peer_miss_rules(struct mlx5_eswitch *esw,
 
        peer_miss_rules_setup(esw, peer_dev, spec, &dest);
 
-       flows = kvcalloc(nvports, sizeof(*flows), GFP_KERNEL);
+       flows = kvcalloc(peer_esw->total_vports, sizeof(*flows), GFP_KERNEL);
        if (!flows) {
                err = -ENOMEM;
                goto alloc_flows_err;
@@ -1213,10 +1213,10 @@ static int esw_add_fdb_peer_miss_rules(struct mlx5_eswitch *esw,
        misc = MLX5_ADDR_OF(fte_match_param, spec->match_value,
                            misc_parameters);
 
-       if (mlx5_core_is_ecpf_esw_manager(esw->dev)) {
-               vport = mlx5_eswitch_get_vport(esw, MLX5_VPORT_PF);
-               esw_set_peer_miss_rule_source_port(esw, peer_dev->priv.eswitch,
-                                                  spec, MLX5_VPORT_PF);
+       if (mlx5_core_is_ecpf_esw_manager(peer_dev)) {
+               peer_vport = mlx5_eswitch_get_vport(peer_esw, MLX5_VPORT_PF);
+               esw_set_peer_miss_rule_source_port(esw, peer_esw, spec,
+                                                  MLX5_VPORT_PF);
 
                flow = mlx5_add_flow_rules(mlx5_eswitch_get_slow_fdb(esw),
                                           spec, &flow_act, &dest, 1);
@@ -1224,11 +1224,11 @@ static int esw_add_fdb_peer_miss_rules(struct mlx5_eswitch *esw,
                        err = PTR_ERR(flow);
                        goto add_pf_flow_err;
                }
-               flows[vport->index] = flow;
+               flows[peer_vport->index] = flow;
        }
 
-       if (mlx5_ecpf_vport_exists(esw->dev)) {
-               vport = mlx5_eswitch_get_vport(esw, MLX5_VPORT_ECPF);
+       if (mlx5_ecpf_vport_exists(peer_dev)) {
+               peer_vport = mlx5_eswitch_get_vport(peer_esw, MLX5_VPORT_ECPF);
                MLX5_SET(fte_match_set_misc, misc, source_port, MLX5_VPORT_ECPF);
                flow = mlx5_add_flow_rules(mlx5_eswitch_get_slow_fdb(esw),
                                           spec, &flow_act, &dest, 1);
@@ -1236,13 +1236,14 @@ static int esw_add_fdb_peer_miss_rules(struct mlx5_eswitch *esw,
                        err = PTR_ERR(flow);
                        goto add_ecpf_flow_err;
                }
-               flows[vport->index] = flow;
+               flows[peer_vport->index] = flow;
        }
 
-       mlx5_esw_for_each_vf_vport(esw, i, vport, mlx5_core_max_vfs(esw->dev)) {
+       mlx5_esw_for_each_vf_vport(peer_esw, i, peer_vport,
+                                  mlx5_core_max_vfs(peer_dev)) {
                esw_set_peer_miss_rule_source_port(esw,
-                                                  peer_dev->priv.eswitch,
-                                                  spec, vport->vport);
+                                                  peer_esw,
+                                                  spec, peer_vport->vport);
 
                flow = mlx5_add_flow_rules(mlx5_eswitch_get_slow_fdb(esw),
                                           spec, &flow_act, &dest, 1);
@@ -1250,22 +1251,22 @@ static int esw_add_fdb_peer_miss_rules(struct mlx5_eswitch *esw,
                        err = PTR_ERR(flow);
                        goto add_vf_flow_err;
                }
-               flows[vport->index] = flow;
+               flows[peer_vport->index] = flow;
        }
 
-       if (mlx5_core_ec_sriov_enabled(esw->dev)) {
-               mlx5_esw_for_each_ec_vf_vport(esw, i, vport, mlx5_core_max_ec_vfs(esw->dev)) {
-                       if (i >= mlx5_core_max_ec_vfs(peer_dev))
-                               break;
-                       esw_set_peer_miss_rule_source_port(esw, peer_dev->priv.eswitch,
-                                                          spec, vport->vport);
+       if (mlx5_core_ec_sriov_enabled(peer_dev)) {
+               mlx5_esw_for_each_ec_vf_vport(peer_esw, i, peer_vport,
+                                             mlx5_core_max_ec_vfs(peer_dev)) {
+                       esw_set_peer_miss_rule_source_port(esw, peer_esw,
+                                                          spec,
+                                                          peer_vport->vport);
                        flow = mlx5_add_flow_rules(esw->fdb_table.offloads.slow_fdb,
                                                   spec, &flow_act, &dest, 1);
                        if (IS_ERR(flow)) {
                                err = PTR_ERR(flow);
                                goto add_ec_vf_flow_err;
                        }
-                       flows[vport->index] = flow;
+                       flows[peer_vport->index] = flow;
                }
        }
 
@@ -1282,25 +1283,27 @@ static int esw_add_fdb_peer_miss_rules(struct mlx5_eswitch *esw,
        return 0;
 
 add_ec_vf_flow_err:
-       mlx5_esw_for_each_ec_vf_vport(esw, i, vport, mlx5_core_max_ec_vfs(esw->dev)) {
-               if (!flows[vport->index])
+       mlx5_esw_for_each_ec_vf_vport(peer_esw, i, peer_vport,
+                                     mlx5_core_max_ec_vfs(peer_dev)) {
+               if (!flows[peer_vport->index])
                        continue;
-               mlx5_del_flow_rules(flows[vport->index]);
+               mlx5_del_flow_rules(flows[peer_vport->index]);
        }
 add_vf_flow_err:
-       mlx5_esw_for_each_vf_vport(esw, i, vport, mlx5_core_max_vfs(esw->dev)) {
-               if (!flows[vport->index])
+       mlx5_esw_for_each_vf_vport(peer_esw, i, peer_vport,
+                                  mlx5_core_max_vfs(peer_dev)) {
+               if (!flows[peer_vport->index])
                        continue;
-               mlx5_del_flow_rules(flows[vport->index]);
+               mlx5_del_flow_rules(flows[peer_vport->index]);
        }
-       if (mlx5_ecpf_vport_exists(esw->dev)) {
-               vport = mlx5_eswitch_get_vport(esw, MLX5_VPORT_ECPF);
-               mlx5_del_flow_rules(flows[vport->index]);
+       if (mlx5_ecpf_vport_exists(peer_dev)) {
+               peer_vport = mlx5_eswitch_get_vport(peer_esw, MLX5_VPORT_ECPF);
+               mlx5_del_flow_rules(flows[peer_vport->index]);
        }
 add_ecpf_flow_err:
-       if (mlx5_core_is_ecpf_esw_manager(esw->dev)) {
-               vport = mlx5_eswitch_get_vport(esw, MLX5_VPORT_PF);
-               mlx5_del_flow_rules(flows[vport->index]);
+       if (mlx5_core_is_ecpf_esw_manager(peer_dev)) {
+               peer_vport = mlx5_eswitch_get_vport(peer_esw, MLX5_VPORT_PF);
+               mlx5_del_flow_rules(flows[peer_vport->index]);
        }
 add_pf_flow_err:
        esw_warn(esw->dev, "FDB: Failed to add peer miss flow rule err %d\n", err);
@@ -1313,37 +1316,34 @@ alloc_flows_err:
 static void esw_del_fdb_peer_miss_rules(struct mlx5_eswitch *esw,
                                        struct mlx5_core_dev *peer_dev)
 {
+       struct mlx5_eswitch *peer_esw = peer_dev->priv.eswitch;
        u16 peer_index = mlx5_get_dev_index(peer_dev);
        struct mlx5_flow_handle **flows;
-       struct mlx5_vport *vport;
+       struct mlx5_vport *peer_vport;
        unsigned long i;
 
        flows = esw->fdb_table.offloads.peer_miss_rules[peer_index];
        if (!flows)
                return;
 
-       if (mlx5_core_ec_sriov_enabled(esw->dev)) {
-               mlx5_esw_for_each_ec_vf_vport(esw, i, vport, mlx5_core_max_ec_vfs(esw->dev)) {
-                       /* The flow for a particular vport could be NULL if the other ECPF
-                        * has fewer or no VFs enabled
-                        */
-                       if (!flows[vport->index])
-                               continue;
-                       mlx5_del_flow_rules(flows[vport->index]);
-               }
+       if (mlx5_core_ec_sriov_enabled(peer_dev)) {
+               mlx5_esw_for_each_ec_vf_vport(peer_esw, i, peer_vport,
+                                             mlx5_core_max_ec_vfs(peer_dev))
+                       mlx5_del_flow_rules(flows[peer_vport->index]);
        }
 
-       mlx5_esw_for_each_vf_vport(esw, i, vport, mlx5_core_max_vfs(esw->dev))
-               mlx5_del_flow_rules(flows[vport->index]);
+       mlx5_esw_for_each_vf_vport(peer_esw, i, peer_vport,
+                                  mlx5_core_max_vfs(peer_dev))
+               mlx5_del_flow_rules(flows[peer_vport->index]);
 
-       if (mlx5_ecpf_vport_exists(esw->dev)) {
-               vport = mlx5_eswitch_get_vport(esw, MLX5_VPORT_ECPF);
-               mlx5_del_flow_rules(flows[vport->index]);
+       if (mlx5_ecpf_vport_exists(peer_dev)) {
+               peer_vport = mlx5_eswitch_get_vport(peer_esw, MLX5_VPORT_ECPF);
+               mlx5_del_flow_rules(flows[peer_vport->index]);
        }
 
-       if (mlx5_core_is_ecpf_esw_manager(esw->dev)) {
-               vport = mlx5_eswitch_get_vport(esw, MLX5_VPORT_PF);
-               mlx5_del_flow_rules(flows[vport->index]);
+       if (mlx5_core_is_ecpf_esw_manager(peer_dev)) {
+               peer_vport = mlx5_eswitch_get_vport(peer_esw, MLX5_VPORT_PF);
+               mlx5_del_flow_rules(flows[peer_vport->index]);
        }
 
        kvfree(flows);