summaryrefslogtreecommitdiffstats
path: root/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c
diff options
context:
space:
mode:
authorVu Pham <vuhuong@mellanox.com>2020-02-28 16:10:34 -0800
committerSaeed Mahameed <saeedm@mellanox.com>2020-05-27 18:13:49 -0700
commit133dcfc577eaec6538db4ebd8b9205b361f59018 (patch)
tree3618f02cd9da645a0feee85871039e1668ac1684 /drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c
parentd97555e1452943264295cd3c1f066474bc3660dd (diff)
downloadlinux-133dcfc577eaec6538db4ebd8b9205b361f59018.tar.bz2
net/mlx5: E-Switch, Alloc and free unique metadata for match
Introduce infrastructure to create unique metadata for match for vport without depending on vport_num. Vport uses its default metadata for match in standalone configuration but will share a different unique "bond_metadata" for match with other vports in bond configuration. Using ida to generate unique metadata for match for vports in default and bond configurations. Introduce APIs to generate, free metadata for match. Introduce APIs to set vport's bond_metadata and replace its ingress acl rules with bond_metatada. Signed-off-by: Vu Pham <vuhuong@mellanox.com> Reviewed-by: Parav Pandit <parav@mellanox.com> Reviewed-by: Roi Dayan <roid@mellanox.com> Reviewed-by: Mark Bloch <markb@mellanox.com> Signed-off-by: Saeed Mahameed <saeedm@mellanox.com>
Diffstat (limited to 'drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c')
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c96
1 files changed, 64 insertions, 32 deletions
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c
index 11bc9cc1d5f0..060354bb211a 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c
@@ -31,6 +31,7 @@
*/
#include <linux/etherdevice.h>
+#include <linux/idr.h>
#include <linux/mlx5/driver.h>
#include <linux/mlx5/mlx5_ifc.h>
#include <linux/mlx5/vport.h>
@@ -1877,15 +1878,69 @@ static bool esw_use_vport_metadata(const struct mlx5_eswitch *esw)
esw_check_vport_match_metadata_supported(esw);
}
+u32 mlx5_esw_match_metadata_alloc(struct mlx5_eswitch *esw)
+{
+ u32 num_vports = GENMASK(ESW_VPORT_BITS - 1, 0) - 1;
+ u32 vhca_id_mask = GENMASK(ESW_VHCA_ID_BITS - 1, 0);
+ u32 vhca_id = MLX5_CAP_GEN(esw->dev, vhca_id);
+ u32 start;
+ u32 end;
+ int id;
+
+ /* Make sure the vhca_id fits the ESW_VHCA_ID_BITS */
+ WARN_ON_ONCE(vhca_id >= BIT(ESW_VHCA_ID_BITS));
+
+ /* Trim vhca_id to ESW_VHCA_ID_BITS */
+ vhca_id &= vhca_id_mask;
+
+ start = (vhca_id << ESW_VPORT_BITS);
+ end = start + num_vports;
+ if (!vhca_id)
+ start += 1; /* zero is reserved/invalid metadata */
+ id = ida_alloc_range(&esw->offloads.vport_metadata_ida, start, end, GFP_KERNEL);
+
+ return (id < 0) ? 0 : id;
+}
+
+void mlx5_esw_match_metadata_free(struct mlx5_eswitch *esw, u32 metadata)
+{
+ ida_free(&esw->offloads.vport_metadata_ida, metadata);
+}
+
+static int esw_offloads_vport_metadata_setup(struct mlx5_eswitch *esw,
+ struct mlx5_vport *vport)
+{
+ if (vport->vport == MLX5_VPORT_UPLINK)
+ return 0;
+
+ vport->default_metadata = mlx5_esw_match_metadata_alloc(esw);
+ vport->metadata = vport->default_metadata;
+ return vport->metadata ? 0 : -ENOSPC;
+}
+
+static void esw_offloads_vport_metadata_cleanup(struct mlx5_eswitch *esw,
+ struct mlx5_vport *vport)
+{
+ if (vport->vport == MLX5_VPORT_UPLINK || !vport->default_metadata)
+ return;
+
+ WARN_ON(vport->metadata != vport->default_metadata);
+ mlx5_esw_match_metadata_free(esw, vport->default_metadata);
+}
+
int
esw_vport_create_offloads_acl_tables(struct mlx5_eswitch *esw,
struct mlx5_vport *vport)
{
int err;
+ err = esw_offloads_vport_metadata_setup(esw, vport);
+ if (err)
+ goto metadata_err;
+
err = esw_acl_ingress_ofld_setup(esw, vport);
if (err)
- return err;
+ goto ingress_err;
if (mlx5_eswitch_is_vf_vport(esw, vport->vport)) {
err = esw_acl_egress_ofld_setup(esw, vport);
@@ -1897,6 +1952,9 @@ esw_vport_create_offloads_acl_tables(struct mlx5_eswitch *esw,
egress_err:
esw_acl_ingress_ofld_cleanup(esw, vport);
+ingress_err:
+ esw_offloads_vport_metadata_cleanup(esw, vport);
+metadata_err:
return err;
}
@@ -1906,6 +1964,7 @@ esw_vport_destroy_offloads_acl_tables(struct mlx5_eswitch *esw,
{
esw_acl_egress_ofld_cleanup(vport);
esw_acl_ingress_ofld_cleanup(esw, vport);
+ esw_offloads_vport_metadata_cleanup(esw, vport);
}
static int esw_create_uplink_offloads_acl_tables(struct mlx5_eswitch *esw)
@@ -2571,38 +2630,11 @@ EXPORT_SYMBOL(mlx5_eswitch_vport_match_metadata_enabled);
u32 mlx5_eswitch_get_vport_metadata_for_match(struct mlx5_eswitch *esw,
u16 vport_num)
{
- u32 vport_num_mask = GENMASK(ESW_VPORT_BITS - 1, 0);
- u32 vhca_id_mask = GENMASK(ESW_VHCA_ID_BITS - 1, 0);
- u32 vhca_id = MLX5_CAP_GEN(esw->dev, vhca_id);
- u32 val;
+ struct mlx5_vport *vport = mlx5_eswitch_get_vport(esw, vport_num);
- /* Make sure the vhca_id fits the ESW_VHCA_ID_BITS */
- WARN_ON_ONCE(vhca_id >= BIT(ESW_VHCA_ID_BITS));
-
- /* Trim vhca_id to ESW_VHCA_ID_BITS */
- vhca_id &= vhca_id_mask;
-
- /* Make sure pf and ecpf map to end of ESW_VPORT_BITS range so they
- * don't overlap with VF numbers, and themselves, after trimming.
- */
- WARN_ON_ONCE((MLX5_VPORT_UPLINK & vport_num_mask) <
- vport_num_mask - 1);
- WARN_ON_ONCE((MLX5_VPORT_ECPF & vport_num_mask) <
- vport_num_mask - 1);
- WARN_ON_ONCE((MLX5_VPORT_UPLINK & vport_num_mask) ==
- (MLX5_VPORT_ECPF & vport_num_mask));
-
- /* Make sure that the VF vport_num fits ESW_VPORT_BITS and don't
- * overlap with pf and ecpf.
- */
- if (vport_num != MLX5_VPORT_UPLINK &&
- vport_num != MLX5_VPORT_ECPF)
- WARN_ON_ONCE(vport_num >= vport_num_mask - 1);
-
- /* We can now trim vport_num to ESW_VPORT_BITS */
- vport_num &= vport_num_mask;
+ if (WARN_ON_ONCE(IS_ERR(vport)))
+ return 0;
- val = (vhca_id << ESW_VPORT_BITS) | vport_num;
- return val << (32 - ESW_SOURCE_PORT_METADATA_BITS);
+ return vport->metadata << (32 - ESW_SOURCE_PORT_METADATA_BITS);
}
EXPORT_SYMBOL(mlx5_eswitch_get_vport_metadata_for_match);