]> git.proxmox.com Git - mirror_ubuntu-kernels.git/commitdiff
net/mlx5: E-Switch, Consider ECPF vport depends on eswitch ownership
authorBodong Wang <bodong@mellanox.com>
Mon, 10 Dec 2018 17:59:33 +0000 (11:59 -0600)
committerSaeed Mahameed <saeedm@mellanox.com>
Sat, 16 Feb 2019 01:25:58 +0000 (17:25 -0800)
ECPF connects to the eswitch through vport 0xfffe. ECPF may or may
not be the eswitch manager depending on firmware configuration.

1. If ECPF is eswitch manager: ECPF will take over the eswitch manager
   responsibility. A rep of the host PF shall be created at the ECPF
   side for the eswitch manager to control.

2. If ECPF is not eswitch manager: host PF will be the eswitch manager,
   ECPF acts similar as a VF to the host PF. Host PF will be aware
   of the ECPF vport presence and control it's rep.

Signed-off-by: Bodong Wang <bodong@mellanox.com>
Reviewed-by: Or Gerlitz <ogerlitz@mellanox.com>
Signed-off-by: Saeed Mahameed <saeedm@mellanox.com>
drivers/net/ethernet/mellanox/mlx5/core/eswitch.c
drivers/net/ethernet/mellanox/mlx5/core/eswitch.h
drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c
include/linux/mlx5/driver.h
include/linux/mlx5/mlx5_ifc.h
include/linux/mlx5/vport.h

index bb7f72467df9fb7db27b8a0d839fda5fb2ca36c2..d2ab1ee19b2a73d8edecdaa2b41f5c243b905172 100644 (file)
@@ -1667,7 +1667,7 @@ int mlx5_eswitch_enable_sriov(struct mlx5_eswitch *esw, int nvfs, int mode)
                mlx5_reload_interface(esw->dev, MLX5_INTERFACE_PROTOCOL_ETH);
                mlx5_reload_interface(esw->dev, MLX5_INTERFACE_PROTOCOL_IB);
                err = esw_offloads_init(esw, nvfs,
-                                       nvfs + MLX5_SPECIAL_VPORTS);
+                                       nvfs + MLX5_SPECIAL_VPORTS(esw->dev));
        }
 
        if (err)
@@ -1687,6 +1687,12 @@ int mlx5_eswitch_enable_sriov(struct mlx5_eswitch *esw, int nvfs, int mode)
        vport = mlx5_eswitch_get_vport(esw, MLX5_VPORT_PF);
        esw_enable_vport(esw, vport, enabled_events);
 
+       /* Enable ECPF vports */
+       if (mlx5_ecpf_vport_exists(esw->dev)) {
+               vport = mlx5_eswitch_get_vport(esw, MLX5_VPORT_ECPF);
+               esw_enable_vport(esw, vport, enabled_events);
+       }
+
        /* Enable VF vports */
        mlx5_esw_for_each_vf_vport(esw, i, vport, nvfs)
                esw_enable_vport(esw, vport, enabled_events);
index 2951c1296c3eddb2ca8a6562fd7da168cbb9489e..2baa0d71380c19d2aedff9c668e8fef27d8b8ae0 100644 (file)
@@ -380,9 +380,20 @@ static inline int mlx5_eswitch_uplink_idx(struct mlx5_eswitch *esw)
        return esw->total_vports - 1;
 }
 
+static inline int mlx5_eswitch_ecpf_idx(struct mlx5_eswitch *esw)
+{
+       return esw->total_vports - 2;
+}
+
 static inline int mlx5_eswitch_vport_num_to_index(struct mlx5_eswitch *esw,
                                                  u16 vport_num)
 {
+       if (vport_num == MLX5_VPORT_ECPF) {
+               if (!mlx5_ecpf_vport_exists(esw->dev))
+                       esw_warn(esw->dev, "ECPF vport doesn't exist!\n");
+               return mlx5_eswitch_ecpf_idx(esw);
+       }
+
        if (vport_num == MLX5_VPORT_UPLINK)
                return mlx5_eswitch_uplink_idx(esw);
 
@@ -392,6 +403,10 @@ static inline int mlx5_eswitch_vport_num_to_index(struct mlx5_eswitch *esw,
 static inline int mlx5_eswitch_index_to_vport_num(struct mlx5_eswitch *esw,
                                                  int index)
 {
+       if (index == mlx5_eswitch_ecpf_idx(esw) &&
+           mlx5_ecpf_vport_exists(esw->dev))
+               return MLX5_VPORT_ECPF;
+
        if (index == mlx5_eswitch_uplink_idx(esw))
                return MLX5_VPORT_UPLINK;
 
index e787e9212174c69e06c6260ec1f0c5bdea34f7bf..84a33f8e3350db253bdefe976102b277c2908e48 100644 (file)
@@ -639,14 +639,35 @@ 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)) {
+               MLX5_SET(fte_match_set_misc, misc, source_port, MLX5_VPORT_PF);
+               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_pf_flow_err;
+               }
+               flows[MLX5_VPORT_PF] = flow;
+       }
+
+       if (mlx5_ecpf_vport_exists(esw->dev)) {
+               MLX5_SET(fte_match_set_misc, misc, source_port, MLX5_VPORT_ECPF);
+               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_ecpf_flow_err;
+               }
+               flows[mlx5_eswitch_ecpf_idx(esw)] = flow;
+       }
+
        mlx5_esw_for_each_vf_vport(esw, i, mlx5_core_max_vfs(esw->dev)) {
                MLX5_SET(fte_match_set_misc, misc, source_port, i);
                flow = mlx5_add_flow_rules(esw->fdb_table.offloads.slow_fdb,
                                           spec, &flow_act, &dest, 1);
                if (IS_ERR(flow)) {
                        err = PTR_ERR(flow);
-                       esw_warn(esw->dev, "FDB: Failed to add peer miss flow rule err %d\n", err);
-                       goto add_flow_err;
+                       goto add_vf_flow_err;
                }
                flows[i] = flow;
        }
@@ -656,10 +677,18 @@ static int esw_add_fdb_peer_miss_rules(struct mlx5_eswitch *esw,
        kvfree(spec);
        return 0;
 
-add_flow_err:
+add_vf_flow_err:
        nvports = --i;
        mlx5_esw_for_each_vf_vport_reverse(esw, i, nvports)
                mlx5_del_flow_rules(flows[i]);
+
+       if (mlx5_ecpf_vport_exists(esw->dev))
+               mlx5_del_flow_rules(flows[mlx5_eswitch_ecpf_idx(esw)]);
+add_ecpf_flow_err:
+       if (mlx5_core_is_ecpf_esw_manager(esw->dev))
+               mlx5_del_flow_rules(flows[MLX5_VPORT_PF]);
+add_pf_flow_err:
+       esw_warn(esw->dev, "FDB: Failed to add peer miss flow rule err %d\n", err);
        kvfree(flows);
 alloc_flows_err:
        kvfree(spec);
@@ -676,6 +705,12 @@ static void esw_del_fdb_peer_miss_rules(struct mlx5_eswitch *esw)
        mlx5_esw_for_each_vf_vport_reverse(esw, i, mlx5_core_max_vfs(esw->dev))
                mlx5_del_flow_rules(flows[i]);
 
+       if (mlx5_ecpf_vport_exists(esw->dev))
+               mlx5_del_flow_rules(flows[mlx5_eswitch_ecpf_idx(esw)]);
+
+       if (mlx5_core_is_ecpf_esw_manager(esw->dev))
+               mlx5_del_flow_rules(flows[MLX5_VPORT_PF]);
+
        kvfree(flows);
 }
 
@@ -1288,6 +1323,16 @@ static void __unload_reps_special_vport(struct mlx5_eswitch *esw, u8 rep_type)
 {
        struct mlx5_eswitch_rep *rep;
 
+       if (mlx5_ecpf_vport_exists(esw->dev)) {
+               rep = mlx5_eswitch_get_rep(esw, MLX5_VPORT_ECPF);
+               __esw_offloads_unload_rep(esw, rep, rep_type);
+       }
+
+       if (mlx5_core_is_ecpf_esw_manager(esw->dev)) {
+               rep = mlx5_eswitch_get_rep(esw, MLX5_VPORT_PF);
+               __esw_offloads_unload_rep(esw, rep, rep_type);
+       }
+
        rep = mlx5_eswitch_get_rep(esw, MLX5_VPORT_UPLINK);
        __esw_offloads_unload_rep(esw, rep, rep_type);
 }
@@ -1351,6 +1396,34 @@ static int __load_reps_special_vport(struct mlx5_eswitch *esw, u8 rep_type)
 
        rep = mlx5_eswitch_get_rep(esw, MLX5_VPORT_UPLINK);
        err = __esw_offloads_load_rep(esw, rep, rep_type);
+       if (err)
+               return err;
+
+       if (mlx5_core_is_ecpf_esw_manager(esw->dev)) {
+               rep = mlx5_eswitch_get_rep(esw, MLX5_VPORT_PF);
+               err = __esw_offloads_load_rep(esw, rep, rep_type);
+               if (err)
+                       goto err_pf;
+       }
+
+       if (mlx5_ecpf_vport_exists(esw->dev)) {
+               rep = mlx5_eswitch_get_rep(esw, MLX5_VPORT_ECPF);
+               err = __esw_offloads_load_rep(esw, rep, rep_type);
+               if (err)
+                       goto err_ecpf;
+       }
+
+       return 0;
+
+err_ecpf:
+       if (mlx5_core_is_ecpf_esw_manager(esw->dev)) {
+               rep = mlx5_eswitch_get_rep(esw, MLX5_VPORT_PF);
+               __esw_offloads_unload_rep(esw, rep, rep_type);
+       }
+
+err_pf:
+       rep = mlx5_eswitch_get_rep(esw, MLX5_VPORT_UPLINK);
+       __esw_offloads_unload_rep(esw, rep, rep_type);
        return err;
 }
 
index c5454f985e1db2ce898b284647f7f0ef4185007b..c2de50f02b3370f218f4600e279f6fa79fa12d3e 100644 (file)
@@ -1088,6 +1088,11 @@ static inline bool mlx5_core_is_ecpf_esw_manager(struct mlx5_core_dev *dev)
        return dev->caps.embedded_cpu && MLX5_CAP_GEN(dev, eswitch_manager);
 }
 
+static inline bool mlx5_ecpf_vport_exists(struct mlx5_core_dev *dev)
+{
+       return mlx5_core_is_pf(dev) && MLX5_CAP_ESW(dev, ecpf_vport_exists);
+}
+
 #define MLX5_HOST_PF_MAX_VFS   (127u)
 static inline u16 mlx5_core_max_vfs(struct mlx5_core_dev *dev)
 {
index 5decffe565fb5bd0f6823eba52d4a2fc08488eb7..b7bb774b57b0a556a11161638ed2fad52740b8d9 100644 (file)
@@ -631,7 +631,8 @@ struct mlx5_ifc_e_switch_cap_bits {
        u8         vport_svlan_insert[0x1];
        u8         vport_cvlan_insert_if_not_exist[0x1];
        u8         vport_cvlan_insert_overwrite[0x1];
-       u8         reserved_at_5[0x17];
+       u8         reserved_at_5[0x16];
+       u8         ecpf_vport_exists[0x1];
        u8         counter_eswitch_affinity[0x1];
        u8         merged_eswitch[0x1];
        u8         nic_vport_node_guid_modify[0x1];
index 134248c0278623503d2fd1cc920f741740535f53..0eef548b994696c69a2c44d0f9e1babd9c9516b5 100644 (file)
 
 #define MLX5_VPORT_PF_PLACEHOLDER              (1u)
 #define MLX5_VPORT_UPLINK_PLACEHOLDER          (1u)
+#define MLX5_VPORT_ECPF_PLACEHOLDER(mdev)      (mlx5_ecpf_vport_exists(mdev))
 
-#define MLX5_SPECIAL_VPORTS    (MLX5_VPORT_PF_PLACEHOLDER +            \
-                                MLX5_VPORT_UPLINK_PLACEHOLDER)
+#define MLX5_SPECIAL_VPORTS(mdev) (MLX5_VPORT_PF_PLACEHOLDER +         \
+                                  MLX5_VPORT_UPLINK_PLACEHOLDER +      \
+                                  MLX5_VPORT_ECPF_PLACEHOLDER(mdev))
 
-#define MLX5_TOTAL_VPORTS(mdev)        (MLX5_SPECIAL_VPORTS +                  \
+#define MLX5_TOTAL_VPORTS(mdev)        (MLX5_SPECIAL_VPORTS(mdev) +            \
                                 mlx5_core_max_vfs(mdev))
 
 #define MLX5_VPORT_MANAGER(mdev)                                       \