mlx5-updates-2021-04-13

mlx5 core and netdev driver updates
 
 1) E-Switch updates from Parav,
   1.1) Devlink parameter to control mlx5 metadata enablement for E-Switch
   1.2) Trivial cleanups for E-Switch code
   1.3) Dynamically allocate vport steering namespaces only when required
 
 2) From Jianbo, Use variably sized data structures for Software steering
 
 3) Several minor cleanups
 -----BEGIN PGP SIGNATURE-----
 
 iQEzBAABCAAdFiEEGhZs6bAKwk/OTgTpSD+KveBX+j4FAmB3LmAACgkQSD+KveBX
 +j6pfAf+MX75+oMpkrSdyLu6ZXIlc4aFWzJmbzngZud+Du1OrUZY3GSwT65Lq6rV
 ZJ7YAuqwbRB3JzxcWO4u+yEhLoWaY/G/Hyns6OKvIeXZzKhBAQTLU5GrYppVkS9f
 1xTpbDbaOlQ0qi63NfQgTEK+XKzP8EFwt53UXZsSmq7tTzZJ85bLRRdGU5HeYBgD
 SS6q+7jdZZ8PCClpfK8qZ7L6JlEXPG91HKpRMWGz2FHZhN7tFRk5PGDiF3hOpXOn
 0fPlg4dQ6u0/fFwOoSkUoSpzR5tSm1mjByTT0MYo/sQx+lQsFAJfXkDiHNdjKBHF
 3wLpMzOkhay1iJvYYeK887Kts14LsQ==
 =sgu9
 -----END PGP SIGNATURE-----

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

Saeed Mahameed says:

====================
mlx5-updates-2021-04-13

mlx5 core and netdev driver updates

1) E-Switch updates from Parav,
  1.1) Devlink parameter to control mlx5 metadata enablement for E-Switch
  1.2) Trivial cleanups for E-Switch code
  1.3) Dynamically allocate vport steering namespaces only when required

2) From Jianbo, Use variably sized data structures for Software steering

3) Several minor cleanups
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
David S. Miller 2021-04-14 14:14:03 -07:00
commit 4a65912fde
26 changed files with 996 additions and 778 deletions

View File

@ -183,6 +183,40 @@ User command examples:
values:
cmode driverinit value true
esw_port_metadata: Eswitch port metadata state
----------------------------------------------
When applicable, disabling Eswitch metadata can increase packet rate
up to 20% depending on the use case and packet sizes.
Eswitch port metadata state controls whether to internally tag packets with
metadata. Metadata tagging must be enabled for multi-port RoCE, failover
between representors and stacked devices.
By default metadata is enabled on the supported devices in E-switch.
Metadata is applicable only for E-switch in switchdev mode and
users may disable it when NONE of the below use cases will be in use:
1. HCA is in Dual/multi-port RoCE mode.
2. VF/SF representor bonding (Usually used for Live migration)
3. Stacked devices
When metadata is disabled, the above use cases will fail to initialize if
users try to enable them.
- Show eswitch port metadata::
$ devlink dev param show pci/0000:06:00.0 name esw_port_metadata
pci/0000:06:00.0:
name esw_port_metadata type driver-specific
values:
cmode runtime value true
- Disable eswitch port metadata::
$ devlink dev param set pci/0000:06:00.0 name esw_port_metadata value false cmode runtime
- Change eswitch mode to switchdev mode where after choosing the metadata value::
$ devlink dev eswitch set pci/0000:06:00.0 mode switchdev
mlx5 subfunction
================
mlx5 supports subfunction management using devlink port (see :ref:`Documentation/networking/devlink/devlink-port.rst <devlink_port>`) interface.

View File

@ -50,7 +50,7 @@ mlx5_core-$(CONFIG_MLX5_TC_CT) += en/tc_ct.o
# Core extra
#
mlx5_core-$(CONFIG_MLX5_ESWITCH) += eswitch.o eswitch_offloads.o eswitch_offloads_termtbl.o \
ecpf.o rdma.o
ecpf.o rdma.o esw/legacy.o
mlx5_core-$(CONFIG_MLX5_ESWITCH) += esw/acl/helper.o \
esw/acl/egress_lgcy.o esw/acl/egress_ofld.o \
esw/acl/ingress_lgcy.o esw/acl/ingress_ofld.o \

View File

@ -456,6 +456,50 @@ static int mlx5_devlink_large_group_num_validate(struct devlink *devlink, u32 id
return 0;
}
static int mlx5_devlink_esw_port_metadata_set(struct devlink *devlink, u32 id,
struct devlink_param_gset_ctx *ctx)
{
struct mlx5_core_dev *dev = devlink_priv(devlink);
if (!MLX5_ESWITCH_MANAGER(dev))
return -EOPNOTSUPP;
return mlx5_esw_offloads_vport_metadata_set(dev->priv.eswitch, ctx->val.vbool);
}
static int mlx5_devlink_esw_port_metadata_get(struct devlink *devlink, u32 id,
struct devlink_param_gset_ctx *ctx)
{
struct mlx5_core_dev *dev = devlink_priv(devlink);
if (!MLX5_ESWITCH_MANAGER(dev))
return -EOPNOTSUPP;
ctx->val.vbool = mlx5_eswitch_vport_match_metadata_enabled(dev->priv.eswitch);
return 0;
}
static int mlx5_devlink_esw_port_metadata_validate(struct devlink *devlink, u32 id,
union devlink_param_value val,
struct netlink_ext_ack *extack)
{
struct mlx5_core_dev *dev = devlink_priv(devlink);
u8 esw_mode;
if (!MLX5_ESWITCH_MANAGER(dev)) {
NL_SET_ERR_MSG_MOD(extack, "E-Switch is unsupported");
return -EOPNOTSUPP;
}
esw_mode = mlx5_eswitch_mode(dev);
if (esw_mode == MLX5_ESWITCH_OFFLOADS) {
NL_SET_ERR_MSG_MOD(extack,
"E-Switch must either disabled or non switchdev mode");
return -EBUSY;
}
return 0;
}
#endif
static int mlx5_devlink_enable_remote_dev_reset_set(struct devlink *devlink, u32 id,
@ -490,6 +534,12 @@ static const struct devlink_param mlx5_devlink_params[] = {
BIT(DEVLINK_PARAM_CMODE_DRIVERINIT),
NULL, NULL,
mlx5_devlink_large_group_num_validate),
DEVLINK_PARAM_DRIVER(MLX5_DEVLINK_PARAM_ID_ESW_PORT_METADATA,
"esw_port_metadata", DEVLINK_PARAM_TYPE_BOOL,
BIT(DEVLINK_PARAM_CMODE_RUNTIME),
mlx5_devlink_esw_port_metadata_get,
mlx5_devlink_esw_port_metadata_set,
mlx5_devlink_esw_port_metadata_validate),
#endif
DEVLINK_PARAM_GENERIC(ENABLE_REMOTE_DEV_RESET, BIT(DEVLINK_PARAM_CMODE_RUNTIME),
mlx5_devlink_enable_remote_dev_reset_get,
@ -519,6 +569,18 @@ static void mlx5_devlink_set_params_init_values(struct devlink *devlink)
devlink_param_driverinit_value_set(devlink,
MLX5_DEVLINK_PARAM_ID_ESW_LARGE_GROUP_NUM,
value);
if (MLX5_ESWITCH_MANAGER(dev)) {
if (mlx5_esw_vport_match_metadata_supported(dev->priv.eswitch)) {
dev->priv.eswitch->flags |= MLX5_ESWITCH_VPORT_MATCH_METADATA;
value.vbool = true;
} else {
value.vbool = false;
}
devlink_param_driverinit_value_set(devlink,
MLX5_DEVLINK_PARAM_ID_ESW_PORT_METADATA,
value);
}
#endif
}

View File

@ -10,6 +10,7 @@ enum mlx5_devlink_param_id {
MLX5_DEVLINK_PARAM_ID_BASE = DEVLINK_PARAM_GENERIC_ID_MAX,
MLX5_DEVLINK_PARAM_ID_FLOW_STEERING_MODE,
MLX5_DEVLINK_PARAM_ID_ESW_LARGE_GROUP_NUM,
MLX5_DEVLINK_PARAM_ID_ESW_PORT_METADATA,
};
struct mlx5_trap_ctx {

View File

@ -392,11 +392,11 @@ static void arfs_may_expire_flow(struct mlx5e_priv *priv)
{
struct arfs_rule *arfs_rule;
struct hlist_node *htmp;
HLIST_HEAD(del_list);
int quota = 0;
int i;
int j;
HLIST_HEAD(del_list);
spin_lock_bh(&priv->fs.arfs->arfs_lock);
mlx5e_for_each_arfs_rule(arfs_rule, htmp, priv->fs.arfs->arfs_tables, i, j) {
if (!work_pending(&arfs_rule->arfs_work) &&
@ -422,10 +422,10 @@ static void arfs_del_rules(struct mlx5e_priv *priv)
{
struct hlist_node *htmp;
struct arfs_rule *rule;
HLIST_HEAD(del_list);
int i;
int j;
HLIST_HEAD(del_list);
spin_lock_bh(&priv->fs.arfs->arfs_lock);
mlx5e_for_each_arfs_rule(rule, htmp, priv->fs.arfs->arfs_tables, i, j) {
hlist_del_init(&rule->hlist);

View File

@ -510,8 +510,9 @@ static int mlx5e_alloc_rq(struct mlx5e_params *params,
rq->page_pool = NULL;
goto err_free_by_rq_type;
}
err = xdp_rxq_info_reg_mem_model(&rq->xdp_rxq,
MEM_TYPE_PAGE_POOL, rq->page_pool);
if (xdp_rxq_info_is_reg(&rq->xdp_rxq))
err = xdp_rxq_info_reg_mem_model(&rq->xdp_rxq,
MEM_TYPE_PAGE_POOL, rq->page_pool);
}
if (err)
goto err_free_by_rq_type;

View File

@ -52,7 +52,7 @@
#include "diag/en_rep_tracepoint.h"
#define MLX5E_REP_PARAMS_DEF_LOG_SQ_SIZE \
max(0x7, MLX5E_PARAMS_MINIMUM_LOG_SQ_SIZE)
max(0x7, MLX5E_PARAMS_MINIMUM_LOG_SQ_SIZE)
#define MLX5E_REP_PARAMS_DEF_NUM_CHANNELS 1
static const char mlx5e_rep_driver_name[] = "mlx5e_rep";

View File

@ -0,0 +1,509 @@
// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
/* Copyright (c) 2021 Mellanox Technologies Ltd */
#include <linux/etherdevice.h>
#include <linux/mlx5/driver.h>
#include <linux/mlx5/mlx5_ifc.h>
#include <linux/mlx5/vport.h>
#include <linux/mlx5/fs.h>
#include "esw/acl/lgcy.h"
#include "esw/legacy.h"
#include "mlx5_core.h"
#include "eswitch.h"
#include "fs_core.h"
enum {
LEGACY_VEPA_PRIO = 0,
LEGACY_FDB_PRIO,
};
static int esw_create_legacy_vepa_table(struct mlx5_eswitch *esw)
{
struct mlx5_flow_table_attr ft_attr = {};
struct mlx5_core_dev *dev = esw->dev;
struct mlx5_flow_namespace *root_ns;
struct mlx5_flow_table *fdb;
int err;
root_ns = mlx5_get_fdb_sub_ns(dev, 0);
if (!root_ns) {
esw_warn(dev, "Failed to get FDB flow namespace\n");
return -EOPNOTSUPP;
}
/* num FTE 2, num FG 2 */
ft_attr.prio = LEGACY_VEPA_PRIO;
ft_attr.max_fte = 2;
ft_attr.autogroup.max_num_groups = 2;
fdb = mlx5_create_auto_grouped_flow_table(root_ns, &ft_attr);
if (IS_ERR(fdb)) {
err = PTR_ERR(fdb);
esw_warn(dev, "Failed to create VEPA FDB err %d\n", err);
return err;
}
esw->fdb_table.legacy.vepa_fdb = fdb;
return 0;
}
static void esw_destroy_legacy_fdb_table(struct mlx5_eswitch *esw)
{
esw_debug(esw->dev, "Destroy FDB Table\n");
if (!esw->fdb_table.legacy.fdb)
return;
if (esw->fdb_table.legacy.promisc_grp)
mlx5_destroy_flow_group(esw->fdb_table.legacy.promisc_grp);
if (esw->fdb_table.legacy.allmulti_grp)
mlx5_destroy_flow_group(esw->fdb_table.legacy.allmulti_grp);
if (esw->fdb_table.legacy.addr_grp)
mlx5_destroy_flow_group(esw->fdb_table.legacy.addr_grp);
mlx5_destroy_flow_table(esw->fdb_table.legacy.fdb);
esw->fdb_table.legacy.fdb = NULL;
esw->fdb_table.legacy.addr_grp = NULL;
esw->fdb_table.legacy.allmulti_grp = NULL;
esw->fdb_table.legacy.promisc_grp = NULL;
atomic64_set(&esw->user_count, 0);
}
static int esw_create_legacy_fdb_table(struct mlx5_eswitch *esw)
{
int inlen = MLX5_ST_SZ_BYTES(create_flow_group_in);
struct mlx5_flow_table_attr ft_attr = {};
struct mlx5_core_dev *dev = esw->dev;
struct mlx5_flow_namespace *root_ns;
struct mlx5_flow_table *fdb;
struct mlx5_flow_group *g;
void *match_criteria;
int table_size;
u32 *flow_group_in;
u8 *dmac;
int err = 0;
esw_debug(dev, "Create FDB log_max_size(%d)\n",
MLX5_CAP_ESW_FLOWTABLE_FDB(dev, log_max_ft_size));
root_ns = mlx5_get_fdb_sub_ns(dev, 0);
if (!root_ns) {
esw_warn(dev, "Failed to get FDB flow namespace\n");
return -EOPNOTSUPP;
}
flow_group_in = kvzalloc(inlen, GFP_KERNEL);
if (!flow_group_in)
return -ENOMEM;
table_size = BIT(MLX5_CAP_ESW_FLOWTABLE_FDB(dev, log_max_ft_size));
ft_attr.max_fte = table_size;
ft_attr.prio = LEGACY_FDB_PRIO;
fdb = mlx5_create_flow_table(root_ns, &ft_attr);
if (IS_ERR(fdb)) {
err = PTR_ERR(fdb);
esw_warn(dev, "Failed to create FDB Table err %d\n", err);
goto out;
}
esw->fdb_table.legacy.fdb = fdb;
/* Addresses group : Full match unicast/multicast addresses */
MLX5_SET(create_flow_group_in, flow_group_in, match_criteria_enable,
MLX5_MATCH_OUTER_HEADERS);
match_criteria = MLX5_ADDR_OF(create_flow_group_in, flow_group_in, match_criteria);
dmac = MLX5_ADDR_OF(fte_match_param, match_criteria, outer_headers.dmac_47_16);
MLX5_SET(create_flow_group_in, flow_group_in, start_flow_index, 0);
/* Preserve 2 entries for allmulti and promisc rules*/
MLX5_SET(create_flow_group_in, flow_group_in, end_flow_index, table_size - 3);
eth_broadcast_addr(dmac);
g = mlx5_create_flow_group(fdb, flow_group_in);
if (IS_ERR(g)) {
err = PTR_ERR(g);
esw_warn(dev, "Failed to create flow group err(%d)\n", err);
goto out;
}
esw->fdb_table.legacy.addr_grp = g;
/* Allmulti group : One rule that forwards any mcast traffic */
MLX5_SET(create_flow_group_in, flow_group_in, match_criteria_enable,
MLX5_MATCH_OUTER_HEADERS);
MLX5_SET(create_flow_group_in, flow_group_in, start_flow_index, table_size - 2);
MLX5_SET(create_flow_group_in, flow_group_in, end_flow_index, table_size - 2);
eth_zero_addr(dmac);
dmac[0] = 0x01;
g = mlx5_create_flow_group(fdb, flow_group_in);
if (IS_ERR(g)) {
err = PTR_ERR(g);
esw_warn(dev, "Failed to create allmulti flow group err(%d)\n", err);
goto out;
}
esw->fdb_table.legacy.allmulti_grp = g;
/* Promiscuous group :
* One rule that forward all unmatched traffic from previous groups
*/
eth_zero_addr(dmac);
MLX5_SET(create_flow_group_in, flow_group_in, match_criteria_enable,
MLX5_MATCH_MISC_PARAMETERS);
MLX5_SET_TO_ONES(fte_match_param, match_criteria, misc_parameters.source_port);
MLX5_SET(create_flow_group_in, flow_group_in, start_flow_index, table_size - 1);
MLX5_SET(create_flow_group_in, flow_group_in, end_flow_index, table_size - 1);
g = mlx5_create_flow_group(fdb, flow_group_in);
if (IS_ERR(g)) {
err = PTR_ERR(g);
esw_warn(dev, "Failed to create promisc flow group err(%d)\n", err);
goto out;
}
esw->fdb_table.legacy.promisc_grp = g;
out:
if (err)
esw_destroy_legacy_fdb_table(esw);
kvfree(flow_group_in);
return err;
}
static void esw_destroy_legacy_vepa_table(struct mlx5_eswitch *esw)
{
esw_debug(esw->dev, "Destroy VEPA Table\n");
if (!esw->fdb_table.legacy.vepa_fdb)
return;
mlx5_destroy_flow_table(esw->fdb_table.legacy.vepa_fdb);
esw->fdb_table.legacy.vepa_fdb = NULL;
}
static int esw_create_legacy_table(struct mlx5_eswitch *esw)
{
int err;
memset(&esw->fdb_table.legacy, 0, sizeof(struct legacy_fdb));
atomic64_set(&esw->user_count, 0);
err = esw_create_legacy_vepa_table(esw);
if (err)
return err;
err = esw_create_legacy_fdb_table(esw);
if (err)
esw_destroy_legacy_vepa_table(esw);
return err;
}
static void esw_cleanup_vepa_rules(struct mlx5_eswitch *esw)
{
if (esw->fdb_table.legacy.vepa_uplink_rule)
mlx5_del_flow_rules(esw->fdb_table.legacy.vepa_uplink_rule);
if (esw->fdb_table.legacy.vepa_star_rule)
mlx5_del_flow_rules(esw->fdb_table.legacy.vepa_star_rule);
esw->fdb_table.legacy.vepa_uplink_rule = NULL;
esw->fdb_table.legacy.vepa_star_rule = NULL;
}
static void esw_destroy_legacy_table(struct mlx5_eswitch *esw)
{
esw_cleanup_vepa_rules(esw);
esw_destroy_legacy_fdb_table(esw);
esw_destroy_legacy_vepa_table(esw);
}
#define MLX5_LEGACY_SRIOV_VPORT_EVENTS (MLX5_VPORT_UC_ADDR_CHANGE | \
MLX5_VPORT_MC_ADDR_CHANGE | \
MLX5_VPORT_PROMISC_CHANGE)
int esw_legacy_enable(struct mlx5_eswitch *esw)
{
struct mlx5_vport *vport;
int ret, i;
ret = esw_create_legacy_table(esw);
if (ret)
return ret;
mlx5_esw_for_each_vf_vport(esw, i, vport, esw->esw_funcs.num_vfs)
vport->info.link_state = MLX5_VPORT_ADMIN_STATE_AUTO;
ret = mlx5_eswitch_enable_pf_vf_vports(esw, MLX5_LEGACY_SRIOV_VPORT_EVENTS);
if (ret)
esw_destroy_legacy_table(esw);
return ret;
}
void esw_legacy_disable(struct mlx5_eswitch *esw)
{
struct esw_mc_addr *mc_promisc;
mlx5_eswitch_disable_pf_vf_vports(esw);
mc_promisc = &esw->mc_promisc;
if (mc_promisc->uplink_rule)
mlx5_del_flow_rules(mc_promisc->uplink_rule);
esw_destroy_legacy_table(esw);
}
static int _mlx5_eswitch_set_vepa_locked(struct mlx5_eswitch *esw,
u8 setting)
{
struct mlx5_flow_destination dest = {};
struct mlx5_flow_act flow_act = {};
struct mlx5_flow_handle *flow_rule;
struct mlx5_flow_spec *spec;
int err = 0;
void *misc;
if (!setting) {
esw_cleanup_vepa_rules(esw);
return 0;
}
if (esw->fdb_table.legacy.vepa_uplink_rule)
return 0;
spec = kvzalloc(sizeof(*spec), GFP_KERNEL);
if (!spec)
return -ENOMEM;
/* Uplink rule forward uplink traffic to FDB */
misc = MLX5_ADDR_OF(fte_match_param, spec->match_value, misc_parameters);
MLX5_SET(fte_match_set_misc, misc, source_port, MLX5_VPORT_UPLINK);
misc = MLX5_ADDR_OF(fte_match_param, spec->match_criteria, misc_parameters);
MLX5_SET_TO_ONES(fte_match_set_misc, misc, source_port);
spec->match_criteria_enable = MLX5_MATCH_MISC_PARAMETERS;
dest.type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE;
dest.ft = esw->fdb_table.legacy.fdb;
flow_act.action = MLX5_FLOW_CONTEXT_ACTION_FWD_DEST;
flow_rule = mlx5_add_flow_rules(esw->fdb_table.legacy.vepa_fdb, spec,
&flow_act, &dest, 1);
if (IS_ERR(flow_rule)) {
err = PTR_ERR(flow_rule);
goto out;
} else {
esw->fdb_table.legacy.vepa_uplink_rule = flow_rule;
}
/* Star rule to forward all traffic to uplink vport */
memset(&dest, 0, sizeof(dest));
dest.type = MLX5_FLOW_DESTINATION_TYPE_VPORT;
dest.vport.num = MLX5_VPORT_UPLINK;
flow_act.action = MLX5_FLOW_CONTEXT_ACTION_FWD_DEST;
flow_rule = mlx5_add_flow_rules(esw->fdb_table.legacy.vepa_fdb, NULL,
&flow_act, &dest, 1);
if (IS_ERR(flow_rule)) {
err = PTR_ERR(flow_rule);
goto out;
} else {
esw->fdb_table.legacy.vepa_star_rule = flow_rule;
}
out:
kvfree(spec);
if (err)
esw_cleanup_vepa_rules(esw);
return err;
}
int mlx5_eswitch_set_vepa(struct mlx5_eswitch *esw, u8 setting)
{
int err = 0;
if (!esw)
return -EOPNOTSUPP;
if (!mlx5_esw_allowed(esw))
return -EPERM;
mutex_lock(&esw->state_lock);
if (esw->mode != MLX5_ESWITCH_LEGACY) {
err = -EOPNOTSUPP;
goto out;
}
err = _mlx5_eswitch_set_vepa_locked(esw, setting);
out:
mutex_unlock(&esw->state_lock);
return err;
}
int mlx5_eswitch_get_vepa(struct mlx5_eswitch *esw, u8 *setting)
{
if (!esw)
return -EOPNOTSUPP;
if (!mlx5_esw_allowed(esw))
return -EPERM;
if (esw->mode != MLX5_ESWITCH_LEGACY)
return -EOPNOTSUPP;
*setting = esw->fdb_table.legacy.vepa_uplink_rule ? 1 : 0;
return 0;
}
int esw_legacy_vport_acl_setup(struct mlx5_eswitch *esw, struct mlx5_vport *vport)
{
int ret;
/* Only non manager vports need ACL in legacy mode */
if (mlx5_esw_is_manager_vport(esw, vport->vport))
return 0;
ret = esw_acl_ingress_lgcy_setup(esw, vport);
if (ret)
goto ingress_err;
ret = esw_acl_egress_lgcy_setup(esw, vport);
if (ret)
goto egress_err;
return 0;
egress_err:
esw_acl_ingress_lgcy_cleanup(esw, vport);
ingress_err:
return ret;
}
void esw_legacy_vport_acl_cleanup(struct mlx5_eswitch *esw, struct mlx5_vport *vport)
{
if (mlx5_esw_is_manager_vport(esw, vport->vport))
return;
esw_acl_egress_lgcy_cleanup(esw, vport);
esw_acl_ingress_lgcy_cleanup(esw, vport);
}
int mlx5_esw_query_vport_drop_stats(struct mlx5_core_dev *dev,
struct mlx5_vport *vport,
struct mlx5_vport_drop_stats *stats)
{
u64 rx_discard_vport_down, tx_discard_vport_down;
struct mlx5_eswitch *esw = dev->priv.eswitch;
u64 bytes = 0;
int err = 0;
if (esw->mode != MLX5_ESWITCH_LEGACY)
return 0;
mutex_lock(&esw->state_lock);
if (!vport->enabled)
goto unlock;
if (!IS_ERR_OR_NULL(vport->egress.legacy.drop_counter))
mlx5_fc_query(dev, vport->egress.legacy.drop_counter,
&stats->rx_dropped, &bytes);
if (vport->ingress.legacy.drop_counter)
mlx5_fc_query(dev, vport->ingress.legacy.drop_counter,
&stats->tx_dropped, &bytes);
if (!MLX5_CAP_GEN(dev, receive_discard_vport_down) &&
!MLX5_CAP_GEN(dev, transmit_discard_vport_down))
goto unlock;
err = mlx5_query_vport_down_stats(dev, vport->vport, 1,
&rx_discard_vport_down,
&tx_discard_vport_down);
if (err)
goto unlock;
if (MLX5_CAP_GEN(dev, receive_discard_vport_down))
stats->rx_dropped += rx_discard_vport_down;
if (MLX5_CAP_GEN(dev, transmit_discard_vport_down))
stats->tx_dropped += tx_discard_vport_down;
unlock:
mutex_unlock(&esw->state_lock);
return err;
}
int mlx5_eswitch_set_vport_vlan(struct mlx5_eswitch *esw,
u16 vport, u16 vlan, u8 qos)
{
u8 set_flags = 0;
int err = 0;
if (!mlx5_esw_allowed(esw))
return -EPERM;
if (vlan || qos)
set_flags = SET_VLAN_STRIP | SET_VLAN_INSERT;
mutex_lock(&esw->state_lock);
if (esw->mode != MLX5_ESWITCH_LEGACY) {
if (!vlan)
goto unlock; /* compatibility with libvirt */
err = -EOPNOTSUPP;
goto unlock;
}
err = __mlx5_eswitch_set_vport_vlan(esw, vport, vlan, qos, set_flags);
unlock:
mutex_unlock(&esw->state_lock);
return err;
}
int mlx5_eswitch_set_vport_spoofchk(struct mlx5_eswitch *esw,
u16 vport, bool spoofchk)
{
struct mlx5_vport *evport = mlx5_eswitch_get_vport(esw, vport);
bool pschk;
int err = 0;
if (!mlx5_esw_allowed(esw))
return -EPERM;
if (IS_ERR(evport))
return PTR_ERR(evport);
mutex_lock(&esw->state_lock);
if (esw->mode != MLX5_ESWITCH_LEGACY) {
err = -EOPNOTSUPP;
goto unlock;
}
pschk = evport->info.spoofchk;
evport->info.spoofchk = spoofchk;
if (pschk && !is_valid_ether_addr(evport->info.mac))
mlx5_core_warn(esw->dev,
"Spoofchk in set while MAC is invalid, vport(%d)\n",
evport->vport);
if (evport->enabled && esw->mode == MLX5_ESWITCH_LEGACY)
err = esw_acl_ingress_lgcy_setup(esw, evport);
if (err)
evport->info.spoofchk = pschk;
unlock:
mutex_unlock(&esw->state_lock);
return err;
}
int mlx5_eswitch_set_vport_trust(struct mlx5_eswitch *esw,
u16 vport, bool setting)
{
struct mlx5_vport *evport = mlx5_eswitch_get_vport(esw, vport);
int err = 0;
if (!mlx5_esw_allowed(esw))
return -EPERM;
if (IS_ERR(evport))
return PTR_ERR(evport);
mutex_lock(&esw->state_lock);
if (esw->mode != MLX5_ESWITCH_LEGACY) {
err = -EOPNOTSUPP;
goto unlock;
}
evport->info.trusted = setting;
if (evport->enabled)
esw_vport_change_handle_locked(evport);
unlock:
mutex_unlock(&esw->state_lock);
return err;
}

View File

@ -0,0 +1,22 @@
/* SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB */
/* Copyright (c) 2021 Mellanox Technologies Ltd */
#ifndef __MLX5_ESW_LEGACY_H__
#define __MLX5_ESW_LEGACY_H__
#define MLX5_LEGACY_SRIOV_VPORT_EVENTS (MLX5_VPORT_UC_ADDR_CHANGE | \
MLX5_VPORT_MC_ADDR_CHANGE | \
MLX5_VPORT_PROMISC_CHANGE)
struct mlx5_eswitch;
int esw_legacy_enable(struct mlx5_eswitch *esw);
void esw_legacy_disable(struct mlx5_eswitch *esw);
int esw_legacy_vport_acl_setup(struct mlx5_eswitch *esw, struct mlx5_vport *vport);
void esw_legacy_vport_acl_cleanup(struct mlx5_eswitch *esw, struct mlx5_vport *vport);
int mlx5_esw_query_vport_drop_stats(struct mlx5_core_dev *dev,
struct mlx5_vport *vport,
struct mlx5_vport_drop_stats *stats);
#endif

View File

@ -36,6 +36,7 @@
#include <linux/mlx5/vport.h>
#include <linux/mlx5/fs.h>
#include "esw/acl/lgcy.h"
#include "esw/legacy.h"
#include "mlx5_core.h"
#include "lib/eq.h"
#include "eswitch.h"
@ -61,9 +62,6 @@ struct vport_addr {
bool mc_promisc;
};
static void esw_destroy_legacy_fdb_table(struct mlx5_eswitch *esw);
static void esw_cleanup_vepa_rules(struct mlx5_eswitch *esw);
static int mlx5_eswitch_check(const struct mlx5_core_dev *dev)
{
if (MLX5_CAP_GEN(dev, port_type) != MLX5_CAP_PORT_TYPE_ETH)
@ -278,226 +276,6 @@ esw_fdb_set_vport_promisc_rule(struct mlx5_eswitch *esw, u16 vport)
return __esw_fdb_set_vport_rule(esw, vport, true, mac_c, mac_v);
}
enum {
LEGACY_VEPA_PRIO = 0,
LEGACY_FDB_PRIO,
};
static int esw_create_legacy_vepa_table(struct mlx5_eswitch *esw)
{
struct mlx5_flow_table_attr ft_attr = {};
struct mlx5_core_dev *dev = esw->dev;
struct mlx5_flow_namespace *root_ns;
struct mlx5_flow_table *fdb;
int err;
root_ns = mlx5_get_fdb_sub_ns(dev, 0);
if (!root_ns) {
esw_warn(dev, "Failed to get FDB flow namespace\n");
return -EOPNOTSUPP;
}
/* num FTE 2, num FG 2 */
ft_attr.prio = LEGACY_VEPA_PRIO;
ft_attr.max_fte = 2;
ft_attr.autogroup.max_num_groups = 2;
fdb = mlx5_create_auto_grouped_flow_table(root_ns, &ft_attr);
if (IS_ERR(fdb)) {
err = PTR_ERR(fdb);
esw_warn(dev, "Failed to create VEPA FDB err %d\n", err);
return err;
}
esw->fdb_table.legacy.vepa_fdb = fdb;
return 0;
}
static int esw_create_legacy_fdb_table(struct mlx5_eswitch *esw)
{
int inlen = MLX5_ST_SZ_BYTES(create_flow_group_in);
struct mlx5_flow_table_attr ft_attr = {};
struct mlx5_core_dev *dev = esw->dev;
struct mlx5_flow_namespace *root_ns;
struct mlx5_flow_table *fdb;
struct mlx5_flow_group *g;
void *match_criteria;
int table_size;
u32 *flow_group_in;
u8 *dmac;
int err = 0;
esw_debug(dev, "Create FDB log_max_size(%d)\n",
MLX5_CAP_ESW_FLOWTABLE_FDB(dev, log_max_ft_size));
root_ns = mlx5_get_fdb_sub_ns(dev, 0);
if (!root_ns) {
esw_warn(dev, "Failed to get FDB flow namespace\n");
return -EOPNOTSUPP;
}
flow_group_in = kvzalloc(inlen, GFP_KERNEL);
if (!flow_group_in)
return -ENOMEM;
table_size = BIT(MLX5_CAP_ESW_FLOWTABLE_FDB(dev, log_max_ft_size));
ft_attr.max_fte = table_size;
ft_attr.prio = LEGACY_FDB_PRIO;
fdb = mlx5_create_flow_table(root_ns, &ft_attr);
if (IS_ERR(fdb)) {
err = PTR_ERR(fdb);
esw_warn(dev, "Failed to create FDB Table err %d\n", err);
goto out;
}
esw->fdb_table.legacy.fdb = fdb;
/* Addresses group : Full match unicast/multicast addresses */
MLX5_SET(create_flow_group_in, flow_group_in, match_criteria_enable,
MLX5_MATCH_OUTER_HEADERS);
match_criteria = MLX5_ADDR_OF(create_flow_group_in, flow_group_in, match_criteria);
dmac = MLX5_ADDR_OF(fte_match_param, match_criteria, outer_headers.dmac_47_16);
MLX5_SET(create_flow_group_in, flow_group_in, start_flow_index, 0);
/* Preserve 2 entries for allmulti and promisc rules*/
MLX5_SET(create_flow_group_in, flow_group_in, end_flow_index, table_size - 3);
eth_broadcast_addr(dmac);
g = mlx5_create_flow_group(fdb, flow_group_in);
if (IS_ERR(g)) {
err = PTR_ERR(g);
esw_warn(dev, "Failed to create flow group err(%d)\n", err);
goto out;
}
esw->fdb_table.legacy.addr_grp = g;
/* Allmulti group : One rule that forwards any mcast traffic */
MLX5_SET(create_flow_group_in, flow_group_in, match_criteria_enable,
MLX5_MATCH_OUTER_HEADERS);
MLX5_SET(create_flow_group_in, flow_group_in, start_flow_index, table_size - 2);
MLX5_SET(create_flow_group_in, flow_group_in, end_flow_index, table_size - 2);
eth_zero_addr(dmac);
dmac[0] = 0x01;
g = mlx5_create_flow_group(fdb, flow_group_in);
if (IS_ERR(g)) {
err = PTR_ERR(g);
esw_warn(dev, "Failed to create allmulti flow group err(%d)\n", err);
goto out;
}
esw->fdb_table.legacy.allmulti_grp = g;
/* Promiscuous group :
* One rule that forward all unmatched traffic from previous groups
*/
eth_zero_addr(dmac);
MLX5_SET(create_flow_group_in, flow_group_in, match_criteria_enable,
MLX5_MATCH_MISC_PARAMETERS);
MLX5_SET_TO_ONES(fte_match_param, match_criteria, misc_parameters.source_port);
MLX5_SET(create_flow_group_in, flow_group_in, start_flow_index, table_size - 1);
MLX5_SET(create_flow_group_in, flow_group_in, end_flow_index, table_size - 1);
g = mlx5_create_flow_group(fdb, flow_group_in);
if (IS_ERR(g)) {
err = PTR_ERR(g);
esw_warn(dev, "Failed to create promisc flow group err(%d)\n", err);
goto out;
}
esw->fdb_table.legacy.promisc_grp = g;
out:
if (err)
esw_destroy_legacy_fdb_table(esw);
kvfree(flow_group_in);
return err;
}
static void esw_destroy_legacy_vepa_table(struct mlx5_eswitch *esw)
{
esw_debug(esw->dev, "Destroy VEPA Table\n");
if (!esw->fdb_table.legacy.vepa_fdb)
return;
mlx5_destroy_flow_table(esw->fdb_table.legacy.vepa_fdb);
esw->fdb_table.legacy.vepa_fdb = NULL;
}
static void esw_destroy_legacy_fdb_table(struct mlx5_eswitch *esw)
{
esw_debug(esw->dev, "Destroy FDB Table\n");
if (!esw->fdb_table.legacy.fdb)
return;
if (esw->fdb_table.legacy.promisc_grp)
mlx5_destroy_flow_group(esw->fdb_table.legacy.promisc_grp);
if (esw->fdb_table.legacy.allmulti_grp)
mlx5_destroy_flow_group(esw->fdb_table.legacy.allmulti_grp);
if (esw->fdb_table.legacy.addr_grp)
mlx5_destroy_flow_group(esw->fdb_table.legacy.addr_grp);
mlx5_destroy_flow_table(esw->fdb_table.legacy.fdb);
esw->fdb_table.legacy.fdb = NULL;
esw->fdb_table.legacy.addr_grp = NULL;
esw->fdb_table.legacy.allmulti_grp = NULL;
esw->fdb_table.legacy.promisc_grp = NULL;
atomic64_set(&esw->user_count, 0);
}
static int esw_create_legacy_table(struct mlx5_eswitch *esw)
{
int err;
memset(&esw->fdb_table.legacy, 0, sizeof(struct legacy_fdb));
atomic64_set(&esw->user_count, 0);
err = esw_create_legacy_vepa_table(esw);
if (err)
return err;
err = esw_create_legacy_fdb_table(esw);
if (err)
esw_destroy_legacy_vepa_table(esw);
return err;
}
static void esw_destroy_legacy_table(struct mlx5_eswitch *esw)
{
esw_cleanup_vepa_rules(esw);
esw_destroy_legacy_fdb_table(esw);
esw_destroy_legacy_vepa_table(esw);
}
#define MLX5_LEGACY_SRIOV_VPORT_EVENTS (MLX5_VPORT_UC_ADDR_CHANGE | \
MLX5_VPORT_MC_ADDR_CHANGE | \
MLX5_VPORT_PROMISC_CHANGE)
static int esw_legacy_enable(struct mlx5_eswitch *esw)
{
struct mlx5_vport *vport;
int ret, i;
ret = esw_create_legacy_table(esw);
if (ret)
return ret;
mlx5_esw_for_each_vf_vport(esw, i, vport, esw->esw_funcs.num_vfs)
vport->info.link_state = MLX5_VPORT_ADMIN_STATE_AUTO;
ret = mlx5_eswitch_enable_pf_vf_vports(esw, MLX5_LEGACY_SRIOV_VPORT_EVENTS);
if (ret)
esw_destroy_legacy_table(esw);
return ret;
}
static void esw_legacy_disable(struct mlx5_eswitch *esw)
{
struct esw_mc_addr *mc_promisc;
mlx5_eswitch_disable_pf_vf_vports(esw);
mc_promisc = &esw->mc_promisc;
if (mc_promisc->uplink_rule)
mlx5_del_flow_rules(mc_promisc->uplink_rule);
esw_destroy_legacy_table(esw);
}
/* E-Switch vport UC/MC lists management */
typedef int (*vport_addr_action)(struct mlx5_eswitch *esw,
struct vport_addr *vaddr);
@ -919,7 +697,7 @@ static void esw_update_vport_rx_mode(struct mlx5_eswitch *esw,
(promisc_all || promisc_mc));
}
static void esw_vport_change_handle_locked(struct mlx5_vport *vport)
void esw_vport_change_handle_locked(struct mlx5_vport *vport)
{
struct mlx5_core_dev *dev = vport->dev;
struct mlx5_eswitch *esw = dev->priv.eswitch;
@ -1170,56 +948,20 @@ static void node_guid_gen_from_mac(u64 *node_guid, const u8 *mac)
((u8 *)node_guid)[0] = mac[5];
}
static int esw_vport_create_legacy_acl_tables(struct mlx5_eswitch *esw,
struct mlx5_vport *vport)
{
int ret;
/* Only non manager vports need ACL in legacy mode */
if (mlx5_esw_is_manager_vport(esw, vport->vport))
return 0;
ret = esw_acl_ingress_lgcy_setup(esw, vport);
if (ret)
goto ingress_err;
ret = esw_acl_egress_lgcy_setup(esw, vport);
if (ret)
goto egress_err;
return 0;
egress_err:
esw_acl_ingress_lgcy_cleanup(esw, vport);
ingress_err:
return ret;
}
static int esw_vport_setup_acl(struct mlx5_eswitch *esw,
struct mlx5_vport *vport)
{
if (esw->mode == MLX5_ESWITCH_LEGACY)
return esw_vport_create_legacy_acl_tables(esw, vport);
return esw_legacy_vport_acl_setup(esw, vport);
else
return esw_vport_create_offloads_acl_tables(esw, vport);
}
static void esw_vport_destroy_legacy_acl_tables(struct mlx5_eswitch *esw,
struct mlx5_vport *vport)
{
if (mlx5_esw_is_manager_vport(esw, vport->vport))
return;
esw_acl_egress_lgcy_cleanup(esw, vport);
esw_acl_ingress_lgcy_cleanup(esw, vport);
}
static void esw_vport_cleanup_acl(struct mlx5_eswitch *esw,
struct mlx5_vport *vport)
{
if (esw->mode == MLX5_ESWITCH_LEGACY)
esw_vport_destroy_legacy_acl_tables(esw, vport);
esw_legacy_vport_acl_cleanup(esw, vport);
else
esw_vport_destroy_offloads_acl_tables(esw, vport);
}
@ -1390,15 +1132,9 @@ const u32 *mlx5_esw_query_functions(struct mlx5_core_dev *dev)
{
int outlen = MLX5_ST_SZ_BYTES(query_esw_functions_out);
u32 in[MLX5_ST_SZ_DW(query_esw_functions_in)] = {};
u16 max_sf_vports;
u32 *out;
int err;
max_sf_vports = mlx5_sf_max_functions(dev);
/* Device interface is array of 64-bits */
if (max_sf_vports)
outlen += DIV_ROUND_UP(max_sf_vports, BITS_PER_TYPE(__be64)) * sizeof(__be64);
out = kvzalloc(outlen, GFP_KERNEL);
if (!out)
return ERR_PTR(-ENOMEM);
@ -1449,8 +1185,6 @@ static void mlx5_eswitch_clear_vf_vports_info(struct mlx5_eswitch *esw)
}
/* Public E-Switch API */
#define ESW_ALLOWED(esw) ((esw) && MLX5_ESWITCH_MANAGER((esw)->dev))
int mlx5_eswitch_load_vport(struct mlx5_eswitch *esw, u16 vport_num,
enum mlx5_eswitch_vport_event enabled_events)
{
@ -1633,6 +1367,47 @@ static void mlx5_esw_mode_change_notify(struct mlx5_eswitch *esw, u16 mode)
blocking_notifier_call_chain(&esw->n_head, 0, &info);
}
static int mlx5_esw_acls_ns_init(struct mlx5_eswitch *esw)
{
struct mlx5_core_dev *dev = esw->dev;
int total_vports;
int err;
total_vports = mlx5_eswitch_get_total_vports(dev);
if (MLX5_CAP_ESW_EGRESS_ACL(dev, ft_support)) {
err = mlx5_fs_egress_acls_init(dev, total_vports);
if (err)
return err;
} else {
esw_warn(dev, "engress ACL is not supported by FW\n");
}
if (MLX5_CAP_ESW_INGRESS_ACL(dev, ft_support)) {
err = mlx5_fs_ingress_acls_init(dev, total_vports);
if (err)
goto err;
} else {
esw_warn(dev, "ingress ACL is not supported by FW\n");
}
return 0;
err:
if (MLX5_CAP_ESW_EGRESS_ACL(dev, ft_support))
mlx5_fs_egress_acls_cleanup(dev);
return err;
}
static void mlx5_esw_acls_ns_cleanup(struct mlx5_eswitch *esw)
{
struct mlx5_core_dev *dev = esw->dev;
if (MLX5_CAP_ESW_INGRESS_ACL(dev, ft_support))
mlx5_fs_ingress_acls_cleanup(dev);
if (MLX5_CAP_ESW_EGRESS_ACL(dev, ft_support))
mlx5_fs_egress_acls_cleanup(dev);
}
/**
* mlx5_eswitch_enable_locked - Enable eswitch
* @esw: Pointer to eswitch
@ -1661,14 +1436,12 @@ int mlx5_eswitch_enable_locked(struct mlx5_eswitch *esw, int mode, int num_vfs)
return -EOPNOTSUPP;
}
if (!MLX5_CAP_ESW_INGRESS_ACL(esw->dev, ft_support))
esw_warn(esw->dev, "ingress ACL is not supported by FW\n");
if (!MLX5_CAP_ESW_EGRESS_ACL(esw->dev, ft_support))
esw_warn(esw->dev, "engress ACL is not supported by FW\n");
mlx5_eswitch_get_devlink_param(esw);
err = mlx5_esw_acls_ns_init(esw);
if (err)
return err;
mlx5_eswitch_update_num_of_vfs(esw, num_vfs);
esw_create_tsar(esw);
@ -1704,6 +1477,7 @@ abort:
mlx5_rescan_drivers(esw->dev);
esw_destroy_tsar(esw);
mlx5_esw_acls_ns_cleanup(esw);
return err;
}
@ -1719,7 +1493,7 @@ int mlx5_eswitch_enable(struct mlx5_eswitch *esw, int num_vfs)
{
int ret;
if (!ESW_ALLOWED(esw))
if (!mlx5_esw_allowed(esw))
return 0;
down_write(&esw->mode_lock);
@ -1772,6 +1546,7 @@ void mlx5_eswitch_disable_locked(struct mlx5_eswitch *esw, bool clear_vf)
mlx5_rescan_drivers(esw->dev);
esw_destroy_tsar(esw);
mlx5_esw_acls_ns_cleanup(esw);
if (clear_vf)
mlx5_eswitch_clear_vf_vports_info(esw);
@ -1779,7 +1554,7 @@ void mlx5_eswitch_disable_locked(struct mlx5_eswitch *esw, bool clear_vf)
void mlx5_eswitch_disable(struct mlx5_eswitch *esw, bool clear_vf)
{
if (!ESW_ALLOWED(esw))
if (!mlx5_esw_allowed(esw))
return;
down_write(&esw->mode_lock);
@ -1862,7 +1637,6 @@ int mlx5_eswitch_init(struct mlx5_core_dev *dev)
abort:
if (esw->work_queue)
destroy_workqueue(esw->work_queue);
esw_offloads_cleanup_reps(esw);
kfree(esw->vports);
kfree(esw);
return err;
@ -1877,7 +1651,6 @@ void mlx5_eswitch_cleanup(struct mlx5_eswitch *esw)
esw->dev->priv.eswitch = NULL;
destroy_workqueue(esw->work_queue);
esw_offloads_cleanup_reps(esw);
mutex_destroy(&esw->state_lock);
WARN_ON(!xa_empty(&esw->offloads.vhca_map));
xa_destroy(&esw->offloads.vhca_map);
@ -1885,6 +1658,7 @@ void mlx5_eswitch_cleanup(struct mlx5_eswitch *esw)
mlx5e_mod_hdr_tbl_destroy(&esw->offloads.mod_hdr);
mutex_destroy(&esw->offloads.encap_tbl_lock);
mutex_destroy(&esw->offloads.decap_tbl_lock);
esw_offloads_cleanup_reps(esw);
kfree(esw->vports);
kfree(esw);
}
@ -2030,7 +1804,7 @@ int mlx5_eswitch_set_vport_state(struct mlx5_eswitch *esw,
int other_vport = 1;
int err = 0;
if (!ESW_ALLOWED(esw))
if (!mlx5_esw_allowed(esw))
return -EPERM;
if (IS_ERR(evport))
return PTR_ERR(evport);
@ -2112,205 +1886,6 @@ int __mlx5_eswitch_set_vport_vlan(struct mlx5_eswitch *esw,
return err;
}
int mlx5_eswitch_set_vport_vlan(struct mlx5_eswitch *esw,
u16 vport, u16 vlan, u8 qos)
{
u8 set_flags = 0;
int err = 0;
if (!ESW_ALLOWED(esw))
return -EPERM;
if (vlan || qos)
set_flags = SET_VLAN_STRIP | SET_VLAN_INSERT;
mutex_lock(&esw->state_lock);
if (esw->mode != MLX5_ESWITCH_LEGACY) {
if (!vlan)
goto unlock; /* compatibility with libvirt */
err = -EOPNOTSUPP;
goto unlock;
}
err = __mlx5_eswitch_set_vport_vlan(esw, vport, vlan, qos, set_flags);
unlock:
mutex_unlock(&esw->state_lock);
return err;
}
int mlx5_eswitch_set_vport_spoofchk(struct mlx5_eswitch *esw,
u16 vport, bool spoofchk)
{
struct mlx5_vport *evport = mlx5_eswitch_get_vport(esw, vport);
bool pschk;
int err = 0;
if (!ESW_ALLOWED(esw))
return -EPERM;
if (IS_ERR(evport))
return PTR_ERR(evport);
mutex_lock(&esw->state_lock);
if (esw->mode != MLX5_ESWITCH_LEGACY) {
err = -EOPNOTSUPP;
goto unlock;
}
pschk = evport->info.spoofchk;
evport->info.spoofchk = spoofchk;
if (pschk && !is_valid_ether_addr(evport->info.mac))
mlx5_core_warn(esw->dev,
"Spoofchk in set while MAC is invalid, vport(%d)\n",
evport->vport);
if (evport->enabled && esw->mode == MLX5_ESWITCH_LEGACY)
err = esw_acl_ingress_lgcy_setup(esw, evport);
if (err)
evport->info.spoofchk = pschk;
unlock:
mutex_unlock(&esw->state_lock);
return err;
}
static void esw_cleanup_vepa_rules(struct mlx5_eswitch *esw)
{
if (esw->fdb_table.legacy.vepa_uplink_rule)
mlx5_del_flow_rules(esw->fdb_table.legacy.vepa_uplink_rule);
if (esw->fdb_table.legacy.vepa_star_rule)
mlx5_del_flow_rules(esw->fdb_table.legacy.vepa_star_rule);
esw->fdb_table.legacy.vepa_uplink_rule = NULL;
esw->fdb_table.legacy.vepa_star_rule = NULL;
}
static int _mlx5_eswitch_set_vepa_locked(struct mlx5_eswitch *esw,
u8 setting)
{
struct mlx5_flow_destination dest = {};
struct mlx5_flow_act flow_act = {};
struct mlx5_flow_handle *flow_rule;
struct mlx5_flow_spec *spec;
int err = 0;
void *misc;
if (!setting) {
esw_cleanup_vepa_rules(esw);
return 0;
}
if (esw->fdb_table.legacy.vepa_uplink_rule)
return 0;
spec = kvzalloc(sizeof(*spec), GFP_KERNEL);
if (!spec)
return -ENOMEM;
/* Uplink rule forward uplink traffic to FDB */
misc = MLX5_ADDR_OF(fte_match_param, spec->match_value, misc_parameters);
MLX5_SET(fte_match_set_misc, misc, source_port, MLX5_VPORT_UPLINK);
misc = MLX5_ADDR_OF(fte_match_param, spec->match_criteria, misc_parameters);
MLX5_SET_TO_ONES(fte_match_set_misc, misc, source_port);
spec->match_criteria_enable = MLX5_MATCH_MISC_PARAMETERS;
dest.type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE;
dest.ft = esw->fdb_table.legacy.fdb;
flow_act.action = MLX5_FLOW_CONTEXT_ACTION_FWD_DEST;
flow_rule = mlx5_add_flow_rules(esw->fdb_table.legacy.vepa_fdb, spec,
&flow_act, &dest, 1);
if (IS_ERR(flow_rule)) {
err = PTR_ERR(flow_rule);
goto out;
} else {
esw->fdb_table.legacy.vepa_uplink_rule = flow_rule;
}
/* Star rule to forward all traffic to uplink vport */
memset(&dest, 0, sizeof(dest));
dest.type = MLX5_FLOW_DESTINATION_TYPE_VPORT;
dest.vport.num = MLX5_VPORT_UPLINK;
flow_act.action = MLX5_FLOW_CONTEXT_ACTION_FWD_DEST;
flow_rule = mlx5_add_flow_rules(esw->fdb_table.legacy.vepa_fdb, NULL,
&flow_act, &dest, 1);
if (IS_ERR(flow_rule)) {
err = PTR_ERR(flow_rule);
goto out;
} else {
esw->fdb_table.legacy.vepa_star_rule = flow_rule;
}
out:
kvfree(spec);
if (err)
esw_cleanup_vepa_rules(esw);
return err;
}
int mlx5_eswitch_set_vepa(struct mlx5_eswitch *esw, u8 setting)
{
int err = 0;
if (!esw)
return -EOPNOTSUPP;
if (!ESW_ALLOWED(esw))
return -EPERM;
mutex_lock(&esw->state_lock);
if (esw->mode != MLX5_ESWITCH_LEGACY) {
err = -EOPNOTSUPP;
goto out;
}
err = _mlx5_eswitch_set_vepa_locked(esw, setting);
out:
mutex_unlock(&esw->state_lock);
return err;
}
int mlx5_eswitch_get_vepa(struct mlx5_eswitch *esw, u8 *setting)
{
if (!esw)
return -EOPNOTSUPP;
if (!ESW_ALLOWED(esw))
return -EPERM;
if (esw->mode != MLX5_ESWITCH_LEGACY)
return -EOPNOTSUPP;
*setting = esw->fdb_table.legacy.vepa_uplink_rule ? 1 : 0;
return 0;
}
int mlx5_eswitch_set_vport_trust(struct mlx5_eswitch *esw,
u16 vport, bool setting)
{
struct mlx5_vport *evport = mlx5_eswitch_get_vport(esw, vport);
int err = 0;
if (!ESW_ALLOWED(esw))
return -EPERM;
if (IS_ERR(evport))
return PTR_ERR(evport);
mutex_lock(&esw->state_lock);
if (esw->mode != MLX5_ESWITCH_LEGACY) {
err = -EOPNOTSUPP;
goto unlock;
}
evport->info.trusted = setting;
if (evport->enabled)
esw_vport_change_handle_locked(evport);
unlock:
mutex_unlock(&esw->state_lock);
return err;
}
static u32 calculate_vports_min_rate_divider(struct mlx5_eswitch *esw)
{
u32 fw_max_bw_share = MLX5_CAP_QOS(esw->dev, max_tsar_bw_share);
@ -2376,7 +1951,7 @@ int mlx5_eswitch_set_vport_rate(struct mlx5_eswitch *esw, u16 vport,
bool max_rate_supported;
int err = 0;
if (!ESW_ALLOWED(esw))
if (!mlx5_esw_allowed(esw))
return -EPERM;
if (IS_ERR(evport))
return PTR_ERR(evport);
@ -2415,50 +1990,6 @@ unlock:
return err;
}
static int mlx5_eswitch_query_vport_drop_stats(struct mlx5_core_dev *dev,
struct mlx5_vport *vport,
struct mlx5_vport_drop_stats *stats)
{
struct mlx5_eswitch *esw = dev->priv.eswitch;
u64 rx_discard_vport_down, tx_discard_vport_down;
u64 bytes = 0;
int err = 0;
if (esw->mode != MLX5_ESWITCH_LEGACY)
return 0;
mutex_lock(&esw->state_lock);
if (!vport->enabled)
goto unlock;
if (!IS_ERR_OR_NULL(vport->egress.legacy.drop_counter))
mlx5_fc_query(dev, vport->egress.legacy.drop_counter,
&stats->rx_dropped, &bytes);
if (vport->ingress.legacy.drop_counter)
mlx5_fc_query(dev, vport->ingress.legacy.drop_counter,
&stats->tx_dropped, &bytes);
if (!MLX5_CAP_GEN(dev, receive_discard_vport_down) &&
!MLX5_CAP_GEN(dev, transmit_discard_vport_down))
goto unlock;
err = mlx5_query_vport_down_stats(dev, vport->vport, 1,
&rx_discard_vport_down,
&tx_discard_vport_down);
if (err)
goto unlock;
if (MLX5_CAP_GEN(dev, receive_discard_vport_down))
stats->rx_dropped += rx_discard_vport_down;
if (MLX5_CAP_GEN(dev, transmit_discard_vport_down))
stats->tx_dropped += tx_discard_vport_down;
unlock:
mutex_unlock(&esw->state_lock);
return err;
}
int mlx5_eswitch_get_vport_stats(struct mlx5_eswitch *esw,
u16 vport_num,
struct ifla_vf_stats *vf_stats)
@ -2526,7 +2057,7 @@ int mlx5_eswitch_get_vport_stats(struct mlx5_eswitch *esw,
vf_stats->broadcast =
MLX5_GET_CTR(out, received_eth_broadcast.packets);
err = mlx5_eswitch_query_vport_drop_stats(esw->dev, vport, &stats);
err = mlx5_esw_query_vport_drop_stats(esw->dev, vport, &stats);
if (err)
goto free_out;
vf_stats->rx_dropped = stats.rx_dropped;
@ -2541,7 +2072,7 @@ u8 mlx5_eswitch_mode(struct mlx5_core_dev *dev)
{
struct mlx5_eswitch *esw = dev->priv.eswitch;
return ESW_ALLOWED(esw) ? esw->mode : MLX5_ESWITCH_NONE;
return mlx5_esw_allowed(esw) ? esw->mode : MLX5_ESWITCH_NONE;
}
EXPORT_SYMBOL_GPL(mlx5_eswitch_mode);
@ -2551,7 +2082,7 @@ mlx5_eswitch_get_encap_mode(const struct mlx5_core_dev *dev)
struct mlx5_eswitch *esw;
esw = dev->priv.eswitch;
return ESW_ALLOWED(esw) ? esw->offloads.encap :
return mlx5_esw_allowed(esw) ? esw->offloads.encap :
DEVLINK_ESWITCH_ENCAP_MODE_NONE;
}
EXPORT_SYMBOL(mlx5_eswitch_get_encap_mode);
@ -2597,7 +2128,7 @@ bool mlx5_esw_hold(struct mlx5_core_dev *mdev)
struct mlx5_eswitch *esw = mdev->priv.eswitch;
/* e.g. VF doesn't have eswitch so nothing to do */
if (!ESW_ALLOWED(esw))
if (!mlx5_esw_allowed(esw))
return true;
if (down_read_trylock(&esw->mode_lock) != 0)
@ -2614,7 +2145,7 @@ void mlx5_esw_release(struct mlx5_core_dev *mdev)
{
struct mlx5_eswitch *esw = mdev->priv.eswitch;
if (ESW_ALLOWED(esw))
if (mlx5_esw_allowed(esw))
up_read(&esw->mode_lock);
}
@ -2626,7 +2157,7 @@ void mlx5_esw_get(struct mlx5_core_dev *mdev)
{
struct mlx5_eswitch *esw = mdev->priv.eswitch;
if (ESW_ALLOWED(esw))
if (mlx5_esw_allowed(esw))
atomic64_inc(&esw->user_count);
}
@ -2638,7 +2169,7 @@ void mlx5_esw_put(struct mlx5_core_dev *mdev)
{
struct mlx5_eswitch *esw = mdev->priv.eswitch;
if (ESW_ALLOWED(esw))
if (mlx5_esw_allowed(esw))
atomic64_dec_if_positive(&esw->user_count);
}

View File

@ -152,7 +152,6 @@ enum mlx5_eswitch_vport_event {
struct mlx5_vport {
struct mlx5_core_dev *dev;
int vport;
struct hlist_head uc_list[MLX5_L2_ADDR_HASH_SIZE];
struct hlist_head mc_list[MLX5_L2_ADDR_HASH_SIZE];
struct mlx5_flow_handle *promisc_rule;
@ -174,6 +173,7 @@ struct mlx5_vport {
u32 max_rate;
} qos;
u16 vport;
bool enabled;
enum mlx5_eswitch_vport_event enabled_events;
struct devlink_port *dl_port;
@ -314,6 +314,8 @@ int esw_offloads_enable(struct mlx5_eswitch *esw);
void esw_offloads_cleanup_reps(struct mlx5_eswitch *esw);
int esw_offloads_init_reps(struct mlx5_eswitch *esw);
bool mlx5_esw_vport_match_metadata_supported(const struct mlx5_eswitch *esw);
int mlx5_esw_offloads_vport_metadata_set(struct mlx5_eswitch *esw, bool enable);
u32 mlx5_esw_match_metadata_alloc(struct mlx5_eswitch *esw);
void mlx5_esw_match_metadata_free(struct mlx5_eswitch *esw, u32 metadata);
@ -519,6 +521,11 @@ const u32 *mlx5_esw_query_functions(struct mlx5_core_dev *dev);
#define esw_debug(dev, format, ...) \
mlx5_core_dbg_mask(dev, MLX5_DEBUG_ESWITCH_MASK, format, ##__VA_ARGS__)
static inline bool mlx5_esw_allowed(const struct mlx5_eswitch *esw)
{
return esw && MLX5_ESWITCH_MANAGER(esw->dev);
}
/* The returned number is valid only when the dev is eswitch manager. */
static inline u16 mlx5_eswitch_manager_vport(struct mlx5_core_dev *dev)
{
@ -807,6 +814,8 @@ void mlx5_esw_put(struct mlx5_core_dev *dev);
int mlx5_esw_try_lock(struct mlx5_eswitch *esw);
void mlx5_esw_unlock(struct mlx5_eswitch *esw);
void esw_vport_change_handle_locked(struct mlx5_vport *vport);
#else /* CONFIG_MLX5_ESWITCH */
/* eswitch API stubs */
static inline int mlx5_eswitch_init(struct mlx5_core_dev *dev) { return 0; }

View File

@ -986,12 +986,13 @@ static void mlx5_eswitch_del_send_to_vport_meta_rules(struct mlx5_eswitch *esw)
static int
mlx5_eswitch_add_send_to_vport_meta_rules(struct mlx5_eswitch *esw)
{
int num_vfs, vport_num, rule_idx = 0, err = 0;
struct mlx5_flow_destination dest = {};
struct mlx5_flow_act flow_act = {0};
int num_vfs, rule_idx = 0, err = 0;
struct mlx5_flow_handle *flow_rule;
struct mlx5_flow_handle **flows;
struct mlx5_flow_spec *spec;
u16 vport_num;
num_vfs = esw->esw_funcs.num_vfs;
flows = kvzalloc(num_vfs * sizeof(*flows), GFP_KERNEL);
@ -2351,8 +2352,7 @@ static void esw_offloads_devcom_cleanup(struct mlx5_eswitch *esw)
mlx5_devcom_unregister_component(devcom, MLX5_DEVCOM_ESW_OFFLOADS);
}
static bool
esw_check_vport_match_metadata_supported(const struct mlx5_eswitch *esw)
bool mlx5_esw_vport_match_metadata_supported(const struct mlx5_eswitch *esw)
{
if (!MLX5_CAP_ESW(esw->dev, esw_uplink_ingress_acl))
return false;
@ -2452,6 +2452,28 @@ metadata_err:
return err;
}
int mlx5_esw_offloads_vport_metadata_set(struct mlx5_eswitch *esw, bool enable)
{
int err = 0;
down_write(&esw->mode_lock);
if (esw->mode != MLX5_ESWITCH_NONE) {
err = -EBUSY;
goto done;
}
if (!mlx5_esw_vport_match_metadata_supported(esw)) {
err = -EOPNOTSUPP;
goto done;
}
if (enable)
esw->flags |= MLX5_ESWITCH_VPORT_MATCH_METADATA;
else
esw->flags &= ~MLX5_ESWITCH_VPORT_MATCH_METADATA;
done:
up_write(&esw->mode_lock);
return err;
}
int
esw_vport_create_offloads_acl_tables(struct mlx5_eswitch *esw,
struct mlx5_vport *vport)
@ -2673,9 +2695,6 @@ int esw_offloads_enable(struct mlx5_eswitch *esw)
if (err)
goto err_metadata;
if (esw_check_vport_match_metadata_supported(esw))
esw->flags |= MLX5_ESWITCH_VPORT_MATCH_METADATA;
err = esw_offloads_metadata_init(esw);
if (err)
goto err_metadata;
@ -2725,7 +2744,6 @@ err_pool:
err_vport_metadata:
esw_offloads_metadata_uninit(esw);
err_metadata:
esw->flags &= ~MLX5_ESWITCH_VPORT_MATCH_METADATA;
mlx5_rdma_disable_roce(esw->dev);
mutex_destroy(&esw->offloads.termtbl_mutex);
return err;
@ -2761,7 +2779,6 @@ void esw_offloads_disable(struct mlx5_eswitch *esw)
esw_offloads_steering_cleanup(esw);
mapping_destroy(esw->offloads.reg_c0_obj_pool);
esw_offloads_metadata_uninit(esw);
esw->flags &= ~MLX5_ESWITCH_VPORT_MATCH_METADATA;
mlx5_rdma_disable_roce(esw->dev);
mutex_destroy(&esw->offloads.termtbl_mutex);
esw->offloads.encap = DEVLINK_ESWITCH_ENCAP_MODE_NONE;

View File

@ -850,7 +850,7 @@ mlx5_fpga_ipsec_release_sa_ctx(struct mlx5_fpga_ipsec_sa_ctx *sa_ctx)
return;
}
if (sa_ctx->fpga_xfrm->accel_xfrm.attrs.action &
if (sa_ctx->fpga_xfrm->accel_xfrm.attrs.action ==
MLX5_ACCEL_ESP_ACTION_DECRYPT)
ida_free(&fipsec->halloc, sa_ctx->sa_handle);
@ -1085,6 +1085,7 @@ static int fpga_ipsec_fs_create_fte(struct mlx5_flow_root_namespace *ns,
rule->ctx = mlx5_fpga_ipsec_fs_create_sa_ctx(dev, fte, is_egress);
if (IS_ERR(rule->ctx)) {
int err = PTR_ERR(rule->ctx);
kfree(rule);
return err;
}

View File

@ -2229,17 +2229,21 @@ struct mlx5_flow_namespace *mlx5_get_flow_vport_acl_namespace(struct mlx5_core_d
{
struct mlx5_flow_steering *steering = dev->priv.steering;
if (!steering || vport >= mlx5_eswitch_get_total_vports(dev))
if (!steering)
return NULL;
switch (type) {
case MLX5_FLOW_NAMESPACE_ESW_EGRESS:
if (vport >= steering->esw_egress_acl_vports)
return NULL;
if (steering->esw_egress_root_ns &&
steering->esw_egress_root_ns[vport])
return &steering->esw_egress_root_ns[vport]->ns;
else
return NULL;
case MLX5_FLOW_NAMESPACE_ESW_INGRESS:
if (vport >= steering->esw_ingress_acl_vports)
return NULL;
if (steering->esw_ingress_root_ns &&
steering->esw_ingress_root_ns[vport])
return &steering->esw_ingress_root_ns[vport]->ns;
@ -2571,43 +2575,11 @@ static void cleanup_root_ns(struct mlx5_flow_root_namespace *root_ns)
clean_tree(&root_ns->ns.node);
}
static void cleanup_egress_acls_root_ns(struct mlx5_core_dev *dev)
{
struct mlx5_flow_steering *steering = dev->priv.steering;
int i;
if (!steering->esw_egress_root_ns)
return;
for (i = 0; i < mlx5_eswitch_get_total_vports(dev); i++)
cleanup_root_ns(steering->esw_egress_root_ns[i]);
kfree(steering->esw_egress_root_ns);
steering->esw_egress_root_ns = NULL;
}
static void cleanup_ingress_acls_root_ns(struct mlx5_core_dev *dev)
{
struct mlx5_flow_steering *steering = dev->priv.steering;
int i;
if (!steering->esw_ingress_root_ns)
return;
for (i = 0; i < mlx5_eswitch_get_total_vports(dev); i++)
cleanup_root_ns(steering->esw_ingress_root_ns[i]);
kfree(steering->esw_ingress_root_ns);
steering->esw_ingress_root_ns = NULL;
}
void mlx5_cleanup_fs(struct mlx5_core_dev *dev)
{
struct mlx5_flow_steering *steering = dev->priv.steering;
cleanup_root_ns(steering->root_ns);
cleanup_egress_acls_root_ns(dev);
cleanup_ingress_acls_root_ns(dev);
cleanup_root_ns(steering->fdb_root_ns);
steering->fdb_root_ns = NULL;
kfree(steering->fdb_sub_ns);
@ -2852,10 +2824,9 @@ static int init_ingress_acl_root_ns(struct mlx5_flow_steering *steering, int vpo
return PTR_ERR_OR_ZERO(prio);
}
static int init_egress_acls_root_ns(struct mlx5_core_dev *dev)
int mlx5_fs_egress_acls_init(struct mlx5_core_dev *dev, int total_vports)
{
struct mlx5_flow_steering *steering = dev->priv.steering;
int total_vports = mlx5_eswitch_get_total_vports(dev);
int err;
int i;
@ -2871,7 +2842,7 @@ static int init_egress_acls_root_ns(struct mlx5_core_dev *dev)
if (err)
goto cleanup_root_ns;
}
steering->esw_egress_acl_vports = total_vports;
return 0;
cleanup_root_ns:
@ -2882,10 +2853,24 @@ cleanup_root_ns:
return err;
}
static int init_ingress_acls_root_ns(struct mlx5_core_dev *dev)
void mlx5_fs_egress_acls_cleanup(struct mlx5_core_dev *dev)
{
struct mlx5_flow_steering *steering = dev->priv.steering;
int i;
if (!steering->esw_egress_root_ns)
return;
for (i = 0; i < steering->esw_egress_acl_vports; i++)
cleanup_root_ns(steering->esw_egress_root_ns[i]);
kfree(steering->esw_egress_root_ns);
steering->esw_egress_root_ns = NULL;
}
int mlx5_fs_ingress_acls_init(struct mlx5_core_dev *dev, int total_vports)
{
struct mlx5_flow_steering *steering = dev->priv.steering;
int total_vports = mlx5_eswitch_get_total_vports(dev);
int err;
int i;
@ -2901,7 +2886,7 @@ static int init_ingress_acls_root_ns(struct mlx5_core_dev *dev)
if (err)
goto cleanup_root_ns;
}
steering->esw_ingress_acl_vports = total_vports;
return 0;
cleanup_root_ns:
@ -2912,6 +2897,21 @@ cleanup_root_ns:
return err;
}
void mlx5_fs_ingress_acls_cleanup(struct mlx5_core_dev *dev)
{
struct mlx5_flow_steering *steering = dev->priv.steering;
int i;
if (!steering->esw_ingress_root_ns)
return;
for (i = 0; i < steering->esw_ingress_acl_vports; i++)
cleanup_root_ns(steering->esw_ingress_root_ns[i]);
kfree(steering->esw_ingress_root_ns);
steering->esw_ingress_root_ns = NULL;
}
static int init_egress_root_ns(struct mlx5_flow_steering *steering)
{
int err;
@ -2974,16 +2974,6 @@ int mlx5_init_fs(struct mlx5_core_dev *dev)
if (err)
goto err;
}
if (MLX5_CAP_ESW_EGRESS_ACL(dev, ft_support)) {
err = init_egress_acls_root_ns(dev);
if (err)
goto err;
}
if (MLX5_CAP_ESW_INGRESS_ACL(dev, ft_support)) {
err = init_ingress_acls_root_ns(dev);
if (err)
goto err;
}
}
if (MLX5_CAP_FLOWTABLE_SNIFFER_RX(dev, ft_support)) {

View File

@ -129,6 +129,8 @@ struct mlx5_flow_steering {
struct mlx5_flow_root_namespace *rdma_rx_root_ns;
struct mlx5_flow_root_namespace *rdma_tx_root_ns;
struct mlx5_flow_root_namespace *egress_root_ns;
int esw_egress_acl_vports;
int esw_ingress_acl_vports;
};
struct fs_node {
@ -287,6 +289,11 @@ int mlx5_flow_namespace_set_mode(struct mlx5_flow_namespace *ns,
int mlx5_init_fs(struct mlx5_core_dev *dev);
void mlx5_cleanup_fs(struct mlx5_core_dev *dev);
int mlx5_fs_egress_acls_init(struct mlx5_core_dev *dev, int total_vports);
void mlx5_fs_egress_acls_cleanup(struct mlx5_core_dev *dev);
int mlx5_fs_ingress_acls_init(struct mlx5_core_dev *dev, int total_vports);
void mlx5_fs_ingress_acls_cleanup(struct mlx5_core_dev *dev);
#define fs_get_obj(v, _node) {v = container_of((_node), typeof(*v), node); }
#define fs_list_for_each_entry(pos, root) \

View File

@ -603,8 +603,6 @@ void mlx5_lag_add(struct mlx5_core_dev *dev, struct net_device *netdev)
if (err)
mlx5_core_err(dev, "Failed to init multipath lag err=%d\n",
err);
return;
}
/* Must be called with intf_mutex held */

View File

@ -167,7 +167,6 @@ static void irq_set_name(char *name, int vecidx)
snprintf(name, MLX5_MAX_IRQ_NAME, "mlx5_comp%d",
vecidx - MLX5_IRQ_VEC_COMP_BASE);
return;
}
static int request_irqs(struct mlx5_core_dev *dev, int nvec)

View File

@ -180,5 +180,4 @@ del_roce_addr:
mlx5_rdma_del_roce_addr(dev);
disable_roce:
mlx5_nic_vport_disable_roce(dev);
return;
}

View File

@ -270,15 +270,14 @@ static int mlx5_sf_add(struct mlx5_core_dev *dev, struct mlx5_sf_table *table,
{
struct mlx5_eswitch *esw = dev->priv.eswitch;
struct mlx5_sf *sf;
u16 hw_fn_id;
int err;
sf = mlx5_sf_alloc(table, new_attr->sfnum, extack);
if (IS_ERR(sf))
return PTR_ERR(sf);
hw_fn_id = mlx5_sf_sw_to_hw_id(dev, sf->id);
err = mlx5_esw_offloads_sf_vport_enable(esw, &sf->dl_port, hw_fn_id, new_attr->sfnum);
err = mlx5_esw_offloads_sf_vport_enable(esw, &sf->dl_port, sf->hw_fn_id,
new_attr->sfnum);
if (err)
goto esw_err;
*new_port_index = sf->port_index;

View File

@ -67,8 +67,8 @@ int mlx5_sf_hw_table_sf_alloc(struct mlx5_core_dev *dev, u32 usr_sfnum)
goto exist_err;
}
hw_fn_id = mlx5_sf_sw_to_hw_id(table->dev, sw_id);
err = mlx5_cmd_alloc_sf(table->dev, hw_fn_id);
hw_fn_id = mlx5_sf_sw_to_hw_id(dev, sw_id);
err = mlx5_cmd_alloc_sf(dev, hw_fn_id);
if (err)
goto err;
@ -80,7 +80,7 @@ int mlx5_sf_hw_table_sf_alloc(struct mlx5_core_dev *dev, u32 usr_sfnum)
return sw_id;
vhca_err:
mlx5_cmd_dealloc_sf(table->dev, hw_fn_id);
mlx5_cmd_dealloc_sf(dev, hw_fn_id);
err:
table->sfs[i].allocated = false;
exist_err:
@ -93,8 +93,8 @@ static void _mlx5_sf_hw_id_free(struct mlx5_core_dev *dev, u16 id)
struct mlx5_sf_hw_table *table = dev->priv.sf_hw_table;
u16 hw_fn_id;
hw_fn_id = mlx5_sf_sw_to_hw_id(table->dev, id);
mlx5_cmd_dealloc_sf(table->dev, hw_fn_id);
hw_fn_id = mlx5_sf_sw_to_hw_id(dev, id);
mlx5_cmd_dealloc_sf(dev, hw_fn_id);
table->sfs[id].allocated = false;
table->sfs[id].pending_delete = false;
}
@ -123,7 +123,7 @@ void mlx5_sf_hw_table_sf_deferred_free(struct mlx5_core_dev *dev, u16 id)
goto err;
state = MLX5_GET(query_vhca_state_out, out, vhca_state_context.vhca_state);
if (state == MLX5_VHCA_STATE_ALLOCATED) {
mlx5_cmd_dealloc_sf(table->dev, hw_fn_id);
mlx5_cmd_dealloc_sf(dev, hw_fn_id);
table->sfs[id].allocated = false;
} else {
table->sfs[id].pending_delete = true;
@ -216,7 +216,7 @@ int mlx5_sf_hw_table_create(struct mlx5_core_dev *dev)
return 0;
table->vhca_nb.notifier_call = mlx5_sf_hw_vhca_event;
return mlx5_vhca_event_notifier_register(table->dev, &table->vhca_nb);
return mlx5_vhca_event_notifier_register(dev, &table->vhca_nb);
}
void mlx5_sf_hw_table_destroy(struct mlx5_core_dev *dev)
@ -226,7 +226,7 @@ void mlx5_sf_hw_table_destroy(struct mlx5_core_dev *dev)
if (!table)
return;
mlx5_vhca_event_notifier_unregister(table->dev, &table->vhca_nb);
mlx5_vhca_event_notifier_unregister(dev, &table->vhca_nb);
/* Dealloc SFs whose firmware event has been missed. */
mlx5_sf_hw_dealloc_all(table);
}

View File

@ -313,8 +313,8 @@ static int dr_action_handle_cs_recalc(struct mlx5dr_domain *dmn,
* table, since there is an *assumption* that in such case FW
* will recalculate the CS.
*/
if (dest_action->dest_tbl.is_fw_tbl) {
*final_icm_addr = dest_action->dest_tbl.fw_tbl.rx_icm_addr;
if (dest_action->dest_tbl->is_fw_tbl) {
*final_icm_addr = dest_action->dest_tbl->fw_tbl.rx_icm_addr;
} else {
mlx5dr_dbg(dmn,
"Destination FT should be terminating when modify TTL is used\n");
@ -326,8 +326,8 @@ static int dr_action_handle_cs_recalc(struct mlx5dr_domain *dmn,
/* If destination is vport we will get the FW flow table
* that recalculates the CS and forwards to the vport.
*/
ret = mlx5dr_domain_cache_get_recalc_cs_ft_addr(dest_action->vport.dmn,
dest_action->vport.caps->num,
ret = mlx5dr_domain_cache_get_recalc_cs_ft_addr(dest_action->vport->dmn,
dest_action->vport->caps->num,
final_icm_addr);
if (ret) {
mlx5dr_err(dmn, "Failed to get FW cs recalc flow table\n");
@ -369,6 +369,7 @@ int mlx5dr_actions_build_ste_arr(struct mlx5dr_matcher *matcher,
action_domain = dr_action_get_action_domain(dmn->type, nic_dmn->ste_type);
for (i = 0; i < num_actions; i++) {
struct mlx5dr_action_dest_tbl *dest_tbl;
struct mlx5dr_action *action;
int max_actions_type = 1;
u32 action_type;
@ -382,37 +383,38 @@ int mlx5dr_actions_build_ste_arr(struct mlx5dr_matcher *matcher,
break;
case DR_ACTION_TYP_FT:
dest_action = action;
if (!action->dest_tbl.is_fw_tbl) {
if (action->dest_tbl.tbl->dmn != dmn) {
dest_tbl = action->dest_tbl;
if (!dest_tbl->is_fw_tbl) {
if (dest_tbl->tbl->dmn != dmn) {
mlx5dr_err(dmn,
"Destination table belongs to a different domain\n");
goto out_invalid_arg;
}
if (action->dest_tbl.tbl->level <= matcher->tbl->level) {
if (dest_tbl->tbl->level <= matcher->tbl->level) {
mlx5_core_warn_once(dmn->mdev,
"Connecting table to a lower/same level destination table\n");
mlx5dr_dbg(dmn,
"Connecting table at level %d to a destination table at level %d\n",
matcher->tbl->level,
action->dest_tbl.tbl->level);
dest_tbl->tbl->level);
}
attr.final_icm_addr = rx_rule ?
action->dest_tbl.tbl->rx.s_anchor->chunk->icm_addr :
action->dest_tbl.tbl->tx.s_anchor->chunk->icm_addr;
dest_tbl->tbl->rx.s_anchor->chunk->icm_addr :
dest_tbl->tbl->tx.s_anchor->chunk->icm_addr;
} else {
struct mlx5dr_cmd_query_flow_table_details output;
int ret;
/* get the relevant addresses */
if (!action->dest_tbl.fw_tbl.rx_icm_addr) {
if (!action->dest_tbl->fw_tbl.rx_icm_addr) {
ret = mlx5dr_cmd_query_flow_table(dmn->mdev,
action->dest_tbl.fw_tbl.type,
action->dest_tbl.fw_tbl.id,
dest_tbl->fw_tbl.type,
dest_tbl->fw_tbl.id,
&output);
if (!ret) {
action->dest_tbl.fw_tbl.tx_icm_addr =
dest_tbl->fw_tbl.tx_icm_addr =
output.sw_owner_icm_root_1;
action->dest_tbl.fw_tbl.rx_icm_addr =
dest_tbl->fw_tbl.rx_icm_addr =
output.sw_owner_icm_root_0;
} else {
mlx5dr_err(dmn,
@ -422,50 +424,50 @@ int mlx5dr_actions_build_ste_arr(struct mlx5dr_matcher *matcher,
}
}
attr.final_icm_addr = rx_rule ?
action->dest_tbl.fw_tbl.rx_icm_addr :
action->dest_tbl.fw_tbl.tx_icm_addr;
dest_tbl->fw_tbl.rx_icm_addr :
dest_tbl->fw_tbl.tx_icm_addr;
}
break;
case DR_ACTION_TYP_QP:
mlx5dr_info(dmn, "Domain doesn't support QP\n");
goto out_invalid_arg;
case DR_ACTION_TYP_CTR:
attr.ctr_id = action->ctr.ctr_id +
action->ctr.offeset;
attr.ctr_id = action->ctr->ctr_id +
action->ctr->offeset;
break;
case DR_ACTION_TYP_TAG:
attr.flow_tag = action->flow_tag;
attr.flow_tag = action->flow_tag->flow_tag;
break;
case DR_ACTION_TYP_TNL_L2_TO_L2:
break;
case DR_ACTION_TYP_TNL_L3_TO_L2:
attr.decap_index = action->rewrite.index;
attr.decap_actions = action->rewrite.num_of_actions;
attr.decap_index = action->rewrite->index;
attr.decap_actions = action->rewrite->num_of_actions;
attr.decap_with_vlan =
attr.decap_actions == WITH_VLAN_NUM_HW_ACTIONS;
break;
case DR_ACTION_TYP_MODIFY_HDR:
attr.modify_index = action->rewrite.index;
attr.modify_actions = action->rewrite.num_of_actions;
recalc_cs_required = action->rewrite.modify_ttl &&
attr.modify_index = action->rewrite->index;
attr.modify_actions = action->rewrite->num_of_actions;
recalc_cs_required = action->rewrite->modify_ttl &&
!mlx5dr_ste_supp_ttl_cs_recalc(&dmn->info.caps);
break;
case DR_ACTION_TYP_L2_TO_TNL_L2:
case DR_ACTION_TYP_L2_TO_TNL_L3:
attr.reformat_size = action->reformat.reformat_size;
attr.reformat_id = action->reformat.reformat_id;
attr.reformat_size = action->reformat->reformat_size;
attr.reformat_id = action->reformat->reformat_id;
break;
case DR_ACTION_TYP_VPORT:
attr.hit_gvmi = action->vport.caps->vhca_gvmi;
attr.hit_gvmi = action->vport->caps->vhca_gvmi;
dest_action = action;
if (rx_rule) {
/* Loopback on WIRE vport is not supported */
if (action->vport.caps->num == WIRE_PORT)
if (action->vport->caps->num == WIRE_PORT)
goto out_invalid_arg;
attr.final_icm_addr = action->vport.caps->icm_address_rx;
attr.final_icm_addr = action->vport->caps->icm_address_rx;
} else {
attr.final_icm_addr = action->vport.caps->icm_address_tx;
attr.final_icm_addr = action->vport->caps->icm_address_tx;
}
break;
case DR_ACTION_TYP_POP_VLAN:
@ -477,7 +479,7 @@ int mlx5dr_actions_build_ste_arr(struct mlx5dr_matcher *matcher,
if (attr.vlans.count == MLX5DR_MAX_VLANS)
return -EINVAL;
attr.vlans.headers[attr.vlans.count++] = action->push_vlan.vlan_hdr;
attr.vlans.headers[attr.vlans.count++] = action->push_vlan->vlan_hdr;
break;
default:
goto out_invalid_arg;
@ -530,17 +532,37 @@ out_invalid_arg:
return -EINVAL;
}
static unsigned int action_size[DR_ACTION_TYP_MAX] = {
[DR_ACTION_TYP_TNL_L2_TO_L2] = sizeof(struct mlx5dr_action_reformat),
[DR_ACTION_TYP_L2_TO_TNL_L2] = sizeof(struct mlx5dr_action_reformat),
[DR_ACTION_TYP_TNL_L3_TO_L2] = sizeof(struct mlx5dr_action_rewrite),
[DR_ACTION_TYP_L2_TO_TNL_L3] = sizeof(struct mlx5dr_action_reformat),
[DR_ACTION_TYP_FT] = sizeof(struct mlx5dr_action_dest_tbl),
[DR_ACTION_TYP_CTR] = sizeof(struct mlx5dr_action_ctr),
[DR_ACTION_TYP_TAG] = sizeof(struct mlx5dr_action_flow_tag),
[DR_ACTION_TYP_MODIFY_HDR] = sizeof(struct mlx5dr_action_rewrite),
[DR_ACTION_TYP_VPORT] = sizeof(struct mlx5dr_action_vport),
[DR_ACTION_TYP_PUSH_VLAN] = sizeof(struct mlx5dr_action_push_vlan),
};
static struct mlx5dr_action *
dr_action_create_generic(enum mlx5dr_action_type action_type)
{
struct mlx5dr_action *action;
int extra_size;
action = kzalloc(sizeof(*action), GFP_KERNEL);
if (action_type < DR_ACTION_TYP_MAX)
extra_size = action_size[action_type];
else
return NULL;
action = kzalloc(sizeof(*action) + extra_size, GFP_KERNEL);
if (!action)
return NULL;
action->action_type = action_type;
refcount_set(&action->refcount, 1);
action->data = action + 1;
return action;
}
@ -559,10 +581,10 @@ mlx5dr_action_create_dest_table_num(struct mlx5dr_domain *dmn, u32 table_num)
if (!action)
return NULL;
action->dest_tbl.is_fw_tbl = true;
action->dest_tbl.fw_tbl.dmn = dmn;
action->dest_tbl.fw_tbl.id = table_num;
action->dest_tbl.fw_tbl.type = FS_FT_FDB;
action->dest_tbl->is_fw_tbl = true;
action->dest_tbl->fw_tbl.dmn = dmn;
action->dest_tbl->fw_tbl.id = table_num;
action->dest_tbl->fw_tbl.type = FS_FT_FDB;
refcount_inc(&dmn->refcount);
return action;
@ -579,7 +601,7 @@ mlx5dr_action_create_dest_table(struct mlx5dr_table *tbl)
if (!action)
goto dec_ref;
action->dest_tbl.tbl = tbl;
action->dest_tbl->tbl = tbl;
return action;
@ -624,12 +646,12 @@ mlx5dr_action_create_mult_dest_tbl(struct mlx5dr_domain *dmn,
case DR_ACTION_TYP_VPORT:
hw_dests[i].vport.flags = MLX5_FLOW_DEST_VPORT_VHCA_ID;
hw_dests[i].type = MLX5_FLOW_DESTINATION_TYPE_VPORT;
hw_dests[i].vport.num = dest_action->vport.caps->num;
hw_dests[i].vport.vhca_id = dest_action->vport.caps->vhca_gvmi;
hw_dests[i].vport.num = dest_action->vport->caps->num;
hw_dests[i].vport.vhca_id = dest_action->vport->caps->vhca_gvmi;
if (reformat_action) {
reformat_req = true;
hw_dests[i].vport.reformat_id =
reformat_action->reformat.reformat_id;
reformat_action->reformat->reformat_id;
ref_actions[num_of_ref++] = reformat_action;
hw_dests[i].vport.flags |= MLX5_FLOW_DEST_VPORT_REFORMAT_ID;
}
@ -637,10 +659,10 @@ mlx5dr_action_create_mult_dest_tbl(struct mlx5dr_domain *dmn,
case DR_ACTION_TYP_FT:
hw_dests[i].type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE;
if (dest_action->dest_tbl.is_fw_tbl)
hw_dests[i].ft_id = dest_action->dest_tbl.fw_tbl.id;
if (dest_action->dest_tbl->is_fw_tbl)
hw_dests[i].ft_id = dest_action->dest_tbl->fw_tbl.id;
else
hw_dests[i].ft_id = dest_action->dest_tbl.tbl->table_id;
hw_dests[i].ft_id = dest_action->dest_tbl->tbl->table_id;
break;
default:
@ -657,8 +679,8 @@ mlx5dr_action_create_mult_dest_tbl(struct mlx5dr_domain *dmn,
hw_dests,
num_of_dests,
reformat_req,
&action->dest_tbl.fw_tbl.id,
&action->dest_tbl.fw_tbl.group_id);
&action->dest_tbl->fw_tbl.id,
&action->dest_tbl->fw_tbl.group_id);
if (ret)
goto free_action;
@ -667,11 +689,11 @@ mlx5dr_action_create_mult_dest_tbl(struct mlx5dr_domain *dmn,
for (i = 0; i < num_of_ref; i++)
refcount_inc(&ref_actions[i]->refcount);
action->dest_tbl.is_fw_tbl = true;
action->dest_tbl.fw_tbl.dmn = dmn;
action->dest_tbl.fw_tbl.type = FS_FT_FDB;
action->dest_tbl.fw_tbl.ref_actions = ref_actions;
action->dest_tbl.fw_tbl.num_of_ref_actions = num_of_ref;
action->dest_tbl->is_fw_tbl = true;
action->dest_tbl->fw_tbl.dmn = dmn;
action->dest_tbl->fw_tbl.type = FS_FT_FDB;
action->dest_tbl->fw_tbl.ref_actions = ref_actions;
action->dest_tbl->fw_tbl.num_of_ref_actions = num_of_ref;
kfree(hw_dests);
@ -696,10 +718,10 @@ mlx5dr_action_create_dest_flow_fw_table(struct mlx5dr_domain *dmn,
if (!action)
return NULL;
action->dest_tbl.is_fw_tbl = 1;
action->dest_tbl.fw_tbl.type = ft->type;
action->dest_tbl.fw_tbl.id = ft->id;
action->dest_tbl.fw_tbl.dmn = dmn;
action->dest_tbl->is_fw_tbl = 1;
action->dest_tbl->fw_tbl.type = ft->type;
action->dest_tbl->fw_tbl.id = ft->id;
action->dest_tbl->fw_tbl.dmn = dmn;
refcount_inc(&dmn->refcount);
@ -715,7 +737,7 @@ mlx5dr_action_create_flow_counter(u32 counter_id)
if (!action)
return NULL;
action->ctr.ctr_id = counter_id;
action->ctr->ctr_id = counter_id;
return action;
}
@ -728,7 +750,7 @@ struct mlx5dr_action *mlx5dr_action_create_tag(u32 tag_value)
if (!action)
return NULL;
action->flow_tag = tag_value & 0xffffff;
action->flow_tag->flow_tag = tag_value & 0xffffff;
return action;
}
@ -794,8 +816,8 @@ dr_action_create_reformat_action(struct mlx5dr_domain *dmn,
if (ret)
return ret;
action->reformat.reformat_id = reformat_id;
action->reformat.reformat_size = data_sz;
action->reformat->reformat_id = reformat_id;
action->reformat->reformat_size = data_sz;
return 0;
}
case DR_ACTION_TYP_TNL_L2_TO_L2:
@ -811,28 +833,28 @@ dr_action_create_reformat_action(struct mlx5dr_domain *dmn,
data, data_sz,
hw_actions,
ACTION_CACHE_LINE_SIZE,
&action->rewrite.num_of_actions);
&action->rewrite->num_of_actions);
if (ret) {
mlx5dr_dbg(dmn, "Failed creating decap l3 action list\n");
return ret;
}
action->rewrite.chunk = mlx5dr_icm_alloc_chunk(dmn->action_icm_pool,
DR_CHUNK_SIZE_8);
if (!action->rewrite.chunk) {
action->rewrite->chunk = mlx5dr_icm_alloc_chunk(dmn->action_icm_pool,
DR_CHUNK_SIZE_8);
if (!action->rewrite->chunk) {
mlx5dr_dbg(dmn, "Failed allocating modify header chunk\n");
return -ENOMEM;
}
action->rewrite.data = (void *)hw_actions;
action->rewrite.index = (action->rewrite.chunk->icm_addr -
action->rewrite->data = (void *)hw_actions;
action->rewrite->index = (action->rewrite->chunk->icm_addr -
dmn->info.caps.hdr_modify_icm_addr) /
ACTION_CACHE_LINE_SIZE;
ret = mlx5dr_send_postsend_action(dmn, action);
if (ret) {
mlx5dr_dbg(dmn, "Writing decap l3 actions to ICM failed\n");
mlx5dr_icm_free_chunk(action->rewrite.chunk);
mlx5dr_icm_free_chunk(action->rewrite->chunk);
return ret;
}
return 0;
@ -867,7 +889,7 @@ struct mlx5dr_action *mlx5dr_action_create_push_vlan(struct mlx5dr_domain *dmn,
if (!action)
return NULL;
action->push_vlan.vlan_hdr = vlan_hdr_h;
action->push_vlan->vlan_hdr = vlan_hdr_h;
return action;
}
@ -898,7 +920,7 @@ mlx5dr_action_create_packet_reformat(struct mlx5dr_domain *dmn,
if (!action)
goto dec_ref;
action->reformat.dmn = dmn;
action->reformat->dmn = dmn;
ret = dr_action_create_reformat_action(dmn,
data_sz,
@ -1104,17 +1126,17 @@ dr_action_modify_check_set_field_limitation(struct mlx5dr_action *action,
const __be64 *sw_action)
{
u16 sw_field = MLX5_GET(set_action_in, sw_action, field);
struct mlx5dr_domain *dmn = action->rewrite.dmn;
struct mlx5dr_domain *dmn = action->rewrite->dmn;
if (sw_field == MLX5_ACTION_IN_FIELD_METADATA_REG_A) {
action->rewrite.allow_rx = 0;
action->rewrite->allow_rx = 0;
if (dmn->type != MLX5DR_DOMAIN_TYPE_NIC_TX) {
mlx5dr_dbg(dmn, "Unsupported field %d for RX/FDB set action\n",
sw_field);
return -EINVAL;
}
} else if (sw_field == MLX5_ACTION_IN_FIELD_METADATA_REG_B) {
action->rewrite.allow_tx = 0;
action->rewrite->allow_tx = 0;
if (dmn->type != MLX5DR_DOMAIN_TYPE_NIC_RX) {
mlx5dr_dbg(dmn, "Unsupported field %d for TX/FDB set action\n",
sw_field);
@ -1122,7 +1144,7 @@ dr_action_modify_check_set_field_limitation(struct mlx5dr_action *action,
}
}
if (!action->rewrite.allow_rx && !action->rewrite.allow_tx) {
if (!action->rewrite->allow_rx && !action->rewrite->allow_tx) {
mlx5dr_dbg(dmn, "Modify SET actions not supported on both RX and TX\n");
return -EINVAL;
}
@ -1135,7 +1157,7 @@ dr_action_modify_check_add_field_limitation(struct mlx5dr_action *action,
const __be64 *sw_action)
{
u16 sw_field = MLX5_GET(set_action_in, sw_action, field);
struct mlx5dr_domain *dmn = action->rewrite.dmn;
struct mlx5dr_domain *dmn = action->rewrite->dmn;
if (sw_field != MLX5_ACTION_IN_FIELD_OUT_IP_TTL &&
sw_field != MLX5_ACTION_IN_FIELD_OUT_IPV6_HOPLIMIT &&
@ -1153,7 +1175,7 @@ static int
dr_action_modify_check_copy_field_limitation(struct mlx5dr_action *action,
const __be64 *sw_action)
{
struct mlx5dr_domain *dmn = action->rewrite.dmn;
struct mlx5dr_domain *dmn = action->rewrite->dmn;
u16 sw_fields[2];
int i;
@ -1162,14 +1184,14 @@ dr_action_modify_check_copy_field_limitation(struct mlx5dr_action *action,
for (i = 0; i < 2; i++) {
if (sw_fields[i] == MLX5_ACTION_IN_FIELD_METADATA_REG_A) {
action->rewrite.allow_rx = 0;
action->rewrite->allow_rx = 0;
if (dmn->type != MLX5DR_DOMAIN_TYPE_NIC_TX) {
mlx5dr_dbg(dmn, "Unsupported field %d for RX/FDB set action\n",
sw_fields[i]);
return -EINVAL;
}
} else if (sw_fields[i] == MLX5_ACTION_IN_FIELD_METADATA_REG_B) {
action->rewrite.allow_tx = 0;
action->rewrite->allow_tx = 0;
if (dmn->type != MLX5DR_DOMAIN_TYPE_NIC_RX) {
mlx5dr_dbg(dmn, "Unsupported field %d for TX/FDB set action\n",
sw_fields[i]);
@ -1178,7 +1200,7 @@ dr_action_modify_check_copy_field_limitation(struct mlx5dr_action *action,
}
}
if (!action->rewrite.allow_rx && !action->rewrite.allow_tx) {
if (!action->rewrite->allow_rx && !action->rewrite->allow_tx) {
mlx5dr_dbg(dmn, "Modify copy actions not supported on both RX and TX\n");
return -EINVAL;
}
@ -1190,7 +1212,7 @@ static int
dr_action_modify_check_field_limitation(struct mlx5dr_action *action,
const __be64 *sw_action)
{
struct mlx5dr_domain *dmn = action->rewrite.dmn;
struct mlx5dr_domain *dmn = action->rewrite->dmn;
u8 action_type;
int ret;
@ -1239,7 +1261,7 @@ static int dr_actions_convert_modify_header(struct mlx5dr_action *action,
{
const struct mlx5dr_ste_action_modify_field *hw_dst_action_info;
const struct mlx5dr_ste_action_modify_field *hw_src_action_info;
struct mlx5dr_domain *dmn = action->rewrite.dmn;
struct mlx5dr_domain *dmn = action->rewrite->dmn;
int ret, i, hw_idx = 0;
__be64 *sw_action;
__be64 hw_action;
@ -1249,8 +1271,8 @@ static int dr_actions_convert_modify_header(struct mlx5dr_action *action,
*modify_ttl = false;
action->rewrite.allow_rx = 1;
action->rewrite.allow_tx = 1;
action->rewrite->allow_rx = 1;
action->rewrite->allow_tx = 1;
for (i = 0; i < num_sw_actions; i++) {
sw_action = &sw_actions[i];
@ -1358,13 +1380,13 @@ static int dr_action_create_modify_action(struct mlx5dr_domain *dmn,
if (ret)
goto free_hw_actions;
action->rewrite.chunk = chunk;
action->rewrite.modify_ttl = modify_ttl;
action->rewrite.data = (u8 *)hw_actions;
action->rewrite.num_of_actions = num_hw_actions;
action->rewrite.index = (chunk->icm_addr -
dmn->info.caps.hdr_modify_icm_addr) /
ACTION_CACHE_LINE_SIZE;
action->rewrite->chunk = chunk;
action->rewrite->modify_ttl = modify_ttl;
action->rewrite->data = (u8 *)hw_actions;
action->rewrite->num_of_actions = num_hw_actions;
action->rewrite->index = (chunk->icm_addr -
dmn->info.caps.hdr_modify_icm_addr) /
ACTION_CACHE_LINE_SIZE;
ret = mlx5dr_send_postsend_action(dmn, action);
if (ret)
@ -1399,7 +1421,7 @@ mlx5dr_action_create_modify_header(struct mlx5dr_domain *dmn,
if (!action)
goto dec_ref;
action->rewrite.dmn = dmn;
action->rewrite->dmn = dmn;
ret = dr_action_create_modify_action(dmn,
actions_sz,
@ -1451,8 +1473,8 @@ mlx5dr_action_create_dest_vport(struct mlx5dr_domain *dmn,
if (!action)
return NULL;
action->vport.dmn = vport_dmn;
action->vport.caps = vport_cap;
action->vport->dmn = vport_dmn;
action->vport->caps = vport_cap;
return action;
}
@ -1464,44 +1486,44 @@ int mlx5dr_action_destroy(struct mlx5dr_action *action)
switch (action->action_type) {
case DR_ACTION_TYP_FT:
if (action->dest_tbl.is_fw_tbl)
refcount_dec(&action->dest_tbl.fw_tbl.dmn->refcount);
if (action->dest_tbl->is_fw_tbl)
refcount_dec(&action->dest_tbl->fw_tbl.dmn->refcount);
else
refcount_dec(&action->dest_tbl.tbl->refcount);
refcount_dec(&action->dest_tbl->tbl->refcount);
if (action->dest_tbl.is_fw_tbl &&
action->dest_tbl.fw_tbl.num_of_ref_actions) {
if (action->dest_tbl->is_fw_tbl &&
action->dest_tbl->fw_tbl.num_of_ref_actions) {
struct mlx5dr_action **ref_actions;
int i;
ref_actions = action->dest_tbl.fw_tbl.ref_actions;
for (i = 0; i < action->dest_tbl.fw_tbl.num_of_ref_actions; i++)
ref_actions = action->dest_tbl->fw_tbl.ref_actions;
for (i = 0; i < action->dest_tbl->fw_tbl.num_of_ref_actions; i++)
refcount_dec(&ref_actions[i]->refcount);
kfree(ref_actions);
mlx5dr_fw_destroy_md_tbl(action->dest_tbl.fw_tbl.dmn,
action->dest_tbl.fw_tbl.id,
action->dest_tbl.fw_tbl.group_id);
mlx5dr_fw_destroy_md_tbl(action->dest_tbl->fw_tbl.dmn,
action->dest_tbl->fw_tbl.id,
action->dest_tbl->fw_tbl.group_id);
}
break;
case DR_ACTION_TYP_TNL_L2_TO_L2:
refcount_dec(&action->reformat.dmn->refcount);
refcount_dec(&action->reformat->dmn->refcount);
break;
case DR_ACTION_TYP_TNL_L3_TO_L2:
mlx5dr_icm_free_chunk(action->rewrite.chunk);
refcount_dec(&action->reformat.dmn->refcount);
mlx5dr_icm_free_chunk(action->rewrite->chunk);
refcount_dec(&action->rewrite->dmn->refcount);
break;
case DR_ACTION_TYP_L2_TO_TNL_L2:
case DR_ACTION_TYP_L2_TO_TNL_L3:
mlx5dr_cmd_destroy_reformat_ctx((action->reformat.dmn)->mdev,
action->reformat.reformat_id);
refcount_dec(&action->reformat.dmn->refcount);
mlx5dr_cmd_destroy_reformat_ctx((action->reformat->dmn)->mdev,
action->reformat->reformat_id);
refcount_dec(&action->reformat->dmn->refcount);
break;
case DR_ACTION_TYP_MODIFY_HDR:
mlx5dr_icm_free_chunk(action->rewrite.chunk);
kfree(action->rewrite.data);
refcount_dec(&action->rewrite.dmn->refcount);
mlx5dr_icm_free_chunk(action->rewrite->chunk);
kfree(action->rewrite->data);
refcount_dec(&action->rewrite->dmn->refcount);
break;
default:
break;

View File

@ -287,7 +287,7 @@ int mlx5dr_cmd_create_empty_flow_group(struct mlx5_core_dev *mdev,
u32 *in;
int err;
in = kzalloc(inlen, GFP_KERNEL);
in = kvzalloc(inlen, GFP_KERNEL);
if (!in)
return -ENOMEM;
@ -302,7 +302,7 @@ int mlx5dr_cmd_create_empty_flow_group(struct mlx5_core_dev *mdev,
*group_id = MLX5_GET(create_flow_group_out, out, group_id);
out:
kfree(in);
kvfree(in);
return err;
}

View File

@ -406,7 +406,7 @@ static int dr_get_tbl_copy_details(struct mlx5dr_domain *dmn,
alloc_size = *num_stes * DR_STE_SIZE;
}
*data = kzalloc(alloc_size, GFP_KERNEL);
*data = kvzalloc(alloc_size, GFP_KERNEL);
if (!*data)
return -ENOMEM;
@ -505,7 +505,7 @@ int mlx5dr_send_postsend_htbl(struct mlx5dr_domain *dmn,
}
out_free:
kfree(data);
kvfree(data);
return ret;
}
@ -562,7 +562,7 @@ int mlx5dr_send_postsend_formatted_htbl(struct mlx5dr_domain *dmn,
}
out_free:
kfree(data);
kvfree(data);
return ret;
}
@ -572,12 +572,12 @@ int mlx5dr_send_postsend_action(struct mlx5dr_domain *dmn,
struct postsend_info send_info = {};
int ret;
send_info.write.addr = (uintptr_t)action->rewrite.data;
send_info.write.length = action->rewrite.num_of_actions *
send_info.write.addr = (uintptr_t)action->rewrite->data;
send_info.write.length = action->rewrite->num_of_actions *
DR_MODIFY_ACTION_SIZE;
send_info.write.lkey = 0;
send_info.remote_addr = action->rewrite.chunk->mr_addr;
send_info.rkey = action->rewrite.chunk->rkey;
send_info.remote_addr = action->rewrite->chunk->mr_addr;
send_info.rkey = action->rewrite->chunk->rkey;
ret = dr_postsend_icm_data(dmn, &send_info);

View File

@ -29,7 +29,7 @@ int mlx5dr_table_set_miss_action(struct mlx5dr_table *tbl,
last_htbl = tbl->rx.s_anchor;
tbl->rx.default_icm_addr = action ?
action->dest_tbl.tbl->rx.s_anchor->chunk->icm_addr :
action->dest_tbl->tbl->rx.s_anchor->chunk->icm_addr :
tbl->rx.nic_dmn->default_icm_addr;
info.type = CONNECT_MISS;
@ -53,7 +53,7 @@ int mlx5dr_table_set_miss_action(struct mlx5dr_table *tbl,
last_htbl = tbl->tx.s_anchor;
tbl->tx.default_icm_addr = action ?
action->dest_tbl.tbl->tx.s_anchor->chunk->icm_addr :
action->dest_tbl->tbl->tx.s_anchor->chunk->icm_addr :
tbl->tx.nic_dmn->default_icm_addr;
info.type = CONNECT_MISS;

View File

@ -806,53 +806,71 @@ struct mlx5dr_ste_action_modify_field {
u8 l4_type;
};
struct mlx5dr_action_rewrite {
struct mlx5dr_domain *dmn;
struct mlx5dr_icm_chunk *chunk;
u8 *data;
u16 num_of_actions;
u32 index;
u8 allow_rx:1;
u8 allow_tx:1;
u8 modify_ttl:1;
};
struct mlx5dr_action_reformat {
struct mlx5dr_domain *dmn;
u32 reformat_id;
u32 reformat_size;
};
struct mlx5dr_action_dest_tbl {
u8 is_fw_tbl:1;
union {
struct mlx5dr_table *tbl;
struct {
struct mlx5dr_domain *dmn;
u32 id;
u32 group_id;
enum fs_flow_table_type type;
u64 rx_icm_addr;
u64 tx_icm_addr;
struct mlx5dr_action **ref_actions;
u32 num_of_ref_actions;
} fw_tbl;
};
};
struct mlx5dr_action_ctr {
u32 ctr_id;
u32 offeset;
};
struct mlx5dr_action_vport {
struct mlx5dr_domain *dmn;
struct mlx5dr_cmd_vport_cap *caps;
};
struct mlx5dr_action_push_vlan {
u32 vlan_hdr; /* tpid_pcp_dei_vid */
};
struct mlx5dr_action_flow_tag {
u32 flow_tag;
};
struct mlx5dr_action {
enum mlx5dr_action_type action_type;
refcount_t refcount;
union {
struct {
struct mlx5dr_domain *dmn;
struct mlx5dr_icm_chunk *chunk;
u8 *data;
u16 num_of_actions;
u32 index;
u8 allow_rx:1;
u8 allow_tx:1;
u8 modify_ttl:1;
} rewrite;
struct {
struct mlx5dr_domain *dmn;
u32 reformat_id;
u32 reformat_size;
} reformat;
struct {
u8 is_fw_tbl:1;
union {
struct mlx5dr_table *tbl;
struct {
struct mlx5dr_domain *dmn;
u32 id;
u32 group_id;
enum fs_flow_table_type type;
u64 rx_icm_addr;
u64 tx_icm_addr;
struct mlx5dr_action **ref_actions;
u32 num_of_ref_actions;
} fw_tbl;
};
} dest_tbl;
struct {
u32 ctr_id;
u32 offeset;
} ctr;
struct {
struct mlx5dr_domain *dmn;
struct mlx5dr_cmd_vport_cap *caps;
} vport;
struct {
u32 vlan_hdr; /* tpid_pcp_dei_vid */
} push_vlan;
u32 flow_tag;
void *data;
struct mlx5dr_action_rewrite *rewrite;
struct mlx5dr_action_reformat *reformat;
struct mlx5dr_action_dest_tbl *dest_tbl;
struct mlx5dr_action_ctr *ctr;
struct mlx5dr_action_vport *vport;
struct mlx5dr_action_push_vlan *push_vlan;
struct mlx5dr_action_flow_tag *flow_tag;
};
};

View File

@ -152,8 +152,7 @@ mlx5_eswitch_vport_match_metadata_enabled(const struct mlx5_eswitch *esw)
};
static inline u32
mlx5_eswitch_get_vport_metadata_for_match(struct mlx5_eswitch *esw,
int vport_num)
mlx5_eswitch_get_vport_metadata_for_match(struct mlx5_eswitch *esw, u16 vport_num)
{
return 0;
};