Commit 8ef1dc4d authored by David S. Miller's avatar David S. Miller

Merge tag 'mlx5-updates-2022-03-10' of git://git.kernel.org/pub/scm/linux/kernel/git/saeed/linux

Saeed Mahameed says:

====================
mlx5-updates-2022-03-10

1) Leon removes useless includes from both mlx5 and mlx4
2) Tariq adds node awareness to some object allocations
3) Gal Cleanups and improvements to EEPROM query
4) Paul adds Software steering to Connection Tracking, to speed up
   CT Rules insertion.

Paul Blakey Says:
=================
To improve insertion rate, this series allows for using software
steering API directly instead of going through the fs_core layer.
This can be done for CT because it doesn't need fs_core layer extra
facilities, such as autogroups, FTE IDs and modifications (which require
a copy of the flow key/mask). Skipping fs_core layer also allows to
create the software steering objects (dr_* objects) ahead of time and
re-use them for multiple rules, whereas software steering under fs_core
creates them on the fly and discards them. This in turn increased insertion
rate.

The series first introduces a lightweight CT flow steering provider
with the first implementations using fs_core layer, and moves CT to use it.
The next patches implement a provider using software steering directly,
bypassing fs_core, and uses it if software steering is available.

=================

====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 63f13b2e 970adfb7
......@@ -42,7 +42,6 @@
#include <linux/tcp.h>
#include <linux/ip.h>
#include <linux/ipv6.h>
#include <linux/moduleparam.h>
#include <linux/indirect_call_wrapper.h>
#include "mlx4_en.h"
......
......@@ -55,7 +55,11 @@ mlx5_core-$(CONFIG_MLX5_CLS_ACT) += en/tc/act/act.o en/tc/act/drop.o en/tc/a
en/tc/act/ct.o en/tc/act/sample.o en/tc/act/ptype.o \
en/tc/act/redirect_ingress.o
mlx5_core-$(CONFIG_MLX5_TC_CT) += en/tc_ct.o
ifneq ($(CONFIG_MLX5_TC_CT),)
mlx5_core-y += en/tc_ct.o en/tc/ct_fs_dmfs.o
mlx5_core-$(CONFIG_MLX5_SW_STEERING) += en/tc/ct_fs_smfs.o
endif
mlx5_core-$(CONFIG_MLX5_TC_SAMPLE) += en/tc/sample.o
#
......@@ -106,7 +110,7 @@ mlx5_core-$(CONFIG_MLX5_SW_STEERING) += steering/dr_domain.o steering/dr_table.o
steering/dr_ste_v2.o \
steering/dr_cmd.o steering/dr_fw.o \
steering/dr_action.o steering/fs_dr.o \
steering/dr_dbg.o
steering/dr_dbg.o lib/smfs.o
#
# SF device
#
......
......@@ -183,11 +183,11 @@ static struct mlx5_db_pgdir *mlx5_alloc_db_pgdir(struct mlx5_core_dev *dev,
u32 db_per_page = PAGE_SIZE / cache_line_size();
struct mlx5_db_pgdir *pgdir;
pgdir = kzalloc(sizeof(*pgdir), GFP_KERNEL);
pgdir = kzalloc_node(sizeof(*pgdir), GFP_KERNEL, node);
if (!pgdir)
return NULL;
pgdir->bitmap = bitmap_zalloc(db_per_page, GFP_KERNEL);
pgdir->bitmap = bitmap_zalloc_node(db_per_page, GFP_KERNEL, node);
if (!pgdir->bitmap) {
kfree(pgdir);
return NULL;
......
......@@ -31,7 +31,6 @@
*/
#include <linux/highmem.h>
#include <linux/module.h>
#include <linux/errno.h>
#include <linux/pci.h>
#include <linux/dma-mapping.h>
......
......@@ -31,7 +31,6 @@
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/hardirq.h>
#include <linux/mlx5/driver.h>
#include <rdma/ib_verbs.h>
......
......@@ -30,7 +30,6 @@
* SOFTWARE.
*/
#include <linux/module.h>
#include <linux/debugfs.h>
#include <linux/mlx5/qp.h>
#include <linux/mlx5/cq.h>
......
/* SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB */
/* Copyright (c) 2021, NVIDIA CORPORATION & AFFILIATES. */
#ifndef __MLX5_EN_TC_CT_FS_H__
#define __MLX5_EN_TC_CT_FS_H__
struct mlx5_ct_fs {
const struct net_device *netdev;
struct mlx5_core_dev *dev;
/* private data */
void *priv_data[];
};
struct mlx5_ct_fs_rule {
};
struct mlx5_ct_fs_ops {
int (*init)(struct mlx5_ct_fs *fs, struct mlx5_flow_table *ct,
struct mlx5_flow_table *ct_nat, struct mlx5_flow_table *post_ct);
void (*destroy)(struct mlx5_ct_fs *fs);
struct mlx5_ct_fs_rule * (*ct_rule_add)(struct mlx5_ct_fs *fs,
struct mlx5_flow_spec *spec,
struct mlx5_flow_attr *attr,
struct flow_rule *flow_rule);
void (*ct_rule_del)(struct mlx5_ct_fs *fs, struct mlx5_ct_fs_rule *fs_rule);
size_t priv_size;
};
static inline void *mlx5_ct_fs_priv(struct mlx5_ct_fs *fs)
{
return &fs->priv_data;
}
struct mlx5_ct_fs_ops *mlx5_ct_fs_dmfs_ops_get(void);
#if IS_ENABLED(CONFIG_MLX5_SW_STEERING)
struct mlx5_ct_fs_ops *mlx5_ct_fs_smfs_ops_get(void);
#else
static inline struct mlx5_ct_fs_ops *
mlx5_ct_fs_smfs_ops_get(void)
{
return NULL;
}
#endif /* IS_ENABLED(CONFIG_MLX5_SW_STEERING) */
#endif /* __MLX5_EN_TC_CT_FS_H__ */
// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
/* Copyright (c) 2021, NVIDIA CORPORATION & AFFILIATES. */
#include "en_tc.h"
#include "en/tc_ct.h"
#include "en/tc/ct_fs.h"
#define ct_dbg(fmt, args...)\
netdev_dbg(fs->netdev, "ct_fs_dmfs debug: " fmt "\n", ##args)
struct mlx5_ct_fs_dmfs_rule {
struct mlx5_ct_fs_rule fs_rule;
struct mlx5_flow_handle *rule;
struct mlx5_flow_attr *attr;
};
static int
mlx5_ct_fs_dmfs_init(struct mlx5_ct_fs *fs, struct mlx5_flow_table *ct,
struct mlx5_flow_table *ct_nat, struct mlx5_flow_table *post_ct)
{
return 0;
}
static void
mlx5_ct_fs_dmfs_destroy(struct mlx5_ct_fs *fs)
{
}
static struct mlx5_ct_fs_rule *
mlx5_ct_fs_dmfs_ct_rule_add(struct mlx5_ct_fs *fs, struct mlx5_flow_spec *spec,
struct mlx5_flow_attr *attr, struct flow_rule *flow_rule)
{
struct mlx5e_priv *priv = netdev_priv(fs->netdev);
struct mlx5_ct_fs_dmfs_rule *dmfs_rule;
int err;
dmfs_rule = kzalloc(sizeof(*dmfs_rule), GFP_KERNEL);
if (!dmfs_rule)
return ERR_PTR(-ENOMEM);
dmfs_rule->rule = mlx5_tc_rule_insert(priv, spec, attr);
if (IS_ERR(dmfs_rule->rule)) {
err = PTR_ERR(dmfs_rule->rule);
ct_dbg("Failed to add ct entry fs rule");
goto err_insert;
}
dmfs_rule->attr = attr;
return &dmfs_rule->fs_rule;
err_insert:
kfree(dmfs_rule);
return ERR_PTR(err);
}
static void
mlx5_ct_fs_dmfs_ct_rule_del(struct mlx5_ct_fs *fs, struct mlx5_ct_fs_rule *fs_rule)
{
struct mlx5_ct_fs_dmfs_rule *dmfs_rule = container_of(fs_rule,
struct mlx5_ct_fs_dmfs_rule,
fs_rule);
mlx5_tc_rule_delete(netdev_priv(fs->netdev), dmfs_rule->rule, dmfs_rule->attr);
kfree(dmfs_rule);
}
static struct mlx5_ct_fs_ops dmfs_ops = {
.ct_rule_add = mlx5_ct_fs_dmfs_ct_rule_add,
.ct_rule_del = mlx5_ct_fs_dmfs_ct_rule_del,
.init = mlx5_ct_fs_dmfs_init,
.destroy = mlx5_ct_fs_dmfs_destroy,
};
struct mlx5_ct_fs_ops *mlx5_ct_fs_dmfs_ops_get(void)
{
return &dmfs_ops;
}
// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
/* Copyright (c) 2021, NVIDIA CORPORATION & AFFILIATES. */
#include <linux/refcount.h>
#include "en_tc.h"
#include "en/tc_priv.h"
#include "en/tc_ct.h"
#include "en/tc/ct_fs.h"
#include "lib/smfs.h"
#define INIT_ERR_PREFIX "ct_fs_smfs init failed"
#define ct_dbg(fmt, args...)\
netdev_dbg(fs->netdev, "ct_fs_smfs debug: " fmt "\n", ##args)
#define MLX5_CT_TCP_FLAGS_MASK cpu_to_be16(be32_to_cpu(TCP_FLAG_RST | TCP_FLAG_FIN) >> 16)
struct mlx5_ct_fs_smfs_matcher {
struct mlx5dr_matcher *dr_matcher;
struct list_head list;
int prio;
refcount_t ref;
};
struct mlx5_ct_fs_smfs_matchers {
struct mlx5_ct_fs_smfs_matcher smfs_matchers[4];
struct list_head used;
};
struct mlx5_ct_fs_smfs {
struct mlx5dr_table *ct_tbl, *ct_nat_tbl;
struct mlx5_ct_fs_smfs_matchers matchers;
struct mlx5_ct_fs_smfs_matchers matchers_nat;
struct mlx5dr_action *fwd_action;
struct mlx5_flow_table *ct_nat;
struct mutex lock; /* Guards matchers */
};
struct mlx5_ct_fs_smfs_rule {
struct mlx5_ct_fs_rule fs_rule;
struct mlx5dr_rule *rule;
struct mlx5dr_action *count_action;
struct mlx5_ct_fs_smfs_matcher *smfs_matcher;
};
static inline void
mlx5_ct_fs_smfs_fill_mask(struct mlx5_ct_fs *fs, struct mlx5_flow_spec *spec, bool ipv4, bool tcp)
{
void *headers_c = MLX5_ADDR_OF(fte_match_param, spec->match_criteria, outer_headers);
if (likely(MLX5_CAP_FLOWTABLE_NIC_RX(fs->dev, ft_field_support.outer_ip_version)))
MLX5_SET_TO_ONES(fte_match_set_lyr_2_4, headers_c, ip_version);
else
MLX5_SET_TO_ONES(fte_match_set_lyr_2_4, headers_c, ethertype);
MLX5_SET_TO_ONES(fte_match_set_lyr_2_4, headers_c, ip_protocol);
if (likely(ipv4)) {
MLX5_SET_TO_ONES(fte_match_set_lyr_2_4, headers_c,
src_ipv4_src_ipv6.ipv4_layout.ipv4);
MLX5_SET_TO_ONES(fte_match_set_lyr_2_4, headers_c,
dst_ipv4_dst_ipv6.ipv4_layout.ipv4);
} else {
memset(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_c,
dst_ipv4_dst_ipv6.ipv6_layout.ipv6),
0xFF,
MLX5_FLD_SZ_BYTES(fte_match_set_lyr_2_4,
dst_ipv4_dst_ipv6.ipv6_layout.ipv6));
memset(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_c,
src_ipv4_src_ipv6.ipv6_layout.ipv6),
0xFF,
MLX5_FLD_SZ_BYTES(fte_match_set_lyr_2_4,
src_ipv4_src_ipv6.ipv6_layout.ipv6));
}
if (likely(tcp)) {
MLX5_SET_TO_ONES(fte_match_set_lyr_2_4, headers_c, tcp_sport);
MLX5_SET_TO_ONES(fte_match_set_lyr_2_4, headers_c, tcp_dport);
MLX5_SET(fte_match_set_lyr_2_4, headers_c, tcp_flags,
ntohs(MLX5_CT_TCP_FLAGS_MASK));
} else {
MLX5_SET_TO_ONES(fte_match_set_lyr_2_4, headers_c, udp_sport);
MLX5_SET_TO_ONES(fte_match_set_lyr_2_4, headers_c, udp_dport);
}
mlx5e_tc_match_to_reg_match(spec, ZONE_TO_REG, 0, MLX5_CT_ZONE_MASK);
}
static struct mlx5dr_matcher *
mlx5_ct_fs_smfs_matcher_create(struct mlx5_ct_fs *fs, struct mlx5dr_table *tbl, bool ipv4,
bool tcp, u32 priority)
{
struct mlx5dr_matcher *dr_matcher;
struct mlx5_flow_spec *spec;
spec = kvzalloc(sizeof(*spec), GFP_KERNEL);
if (!spec)
return ERR_PTR(-ENOMEM);
mlx5_ct_fs_smfs_fill_mask(fs, spec, ipv4, tcp);
spec->match_criteria_enable = MLX5_MATCH_MISC_PARAMETERS_2 | MLX5_MATCH_OUTER_HEADERS;
dr_matcher = mlx5_smfs_matcher_create(tbl, priority, spec);
kfree(spec);
if (!dr_matcher)
return ERR_PTR(-EINVAL);
return dr_matcher;
}
static struct mlx5_ct_fs_smfs_matcher *
mlx5_ct_fs_smfs_matcher_get(struct mlx5_ct_fs *fs, bool nat, bool ipv4, bool tcp)
{
struct mlx5_ct_fs_smfs *fs_smfs = mlx5_ct_fs_priv(fs);
struct mlx5_ct_fs_smfs_matcher *m, *smfs_matcher;
struct mlx5_ct_fs_smfs_matchers *matchers;
struct mlx5dr_matcher *dr_matcher;
struct mlx5dr_table *tbl;
struct list_head *prev;
int prio;
matchers = nat ? &fs_smfs->matchers_nat : &fs_smfs->matchers;
smfs_matcher = &matchers->smfs_matchers[ipv4 * 2 + tcp];
if (refcount_inc_not_zero(&smfs_matcher->ref))
return smfs_matcher;
mutex_lock(&fs_smfs->lock);
/* Retry with lock, as another thread might have already created the relevant matcher
* till we acquired the lock
*/
if (refcount_inc_not_zero(&smfs_matcher->ref))
goto out_unlock;
// Find next available priority in sorted used list
prio = 0;
prev = &matchers->used;
list_for_each_entry(m, &matchers->used, list) {
prev = &m->list;
if (m->prio == prio)
prio = m->prio + 1;
else
break;
}
tbl = nat ? fs_smfs->ct_nat_tbl : fs_smfs->ct_tbl;
dr_matcher = mlx5_ct_fs_smfs_matcher_create(fs, tbl, ipv4, tcp, prio);
if (IS_ERR(dr_matcher)) {
netdev_warn(fs->netdev,
"ct_fs_smfs: failed to create matcher (nat %d, ipv4 %d, tcp %d), err: %ld\n",
nat, ipv4, tcp, PTR_ERR(dr_matcher));
smfs_matcher = ERR_CAST(dr_matcher);
goto out_unlock;
}
smfs_matcher->dr_matcher = dr_matcher;
smfs_matcher->prio = prio;
list_add(&smfs_matcher->list, prev);
refcount_set(&smfs_matcher->ref, 1);
out_unlock:
mutex_unlock(&fs_smfs->lock);
return smfs_matcher;
}
static void
mlx5_ct_fs_smfs_matcher_put(struct mlx5_ct_fs *fs, struct mlx5_ct_fs_smfs_matcher *smfs_matcher)
{
struct mlx5_ct_fs_smfs *fs_smfs = mlx5_ct_fs_priv(fs);
if (!refcount_dec_and_mutex_lock(&smfs_matcher->ref, &fs_smfs->lock))
return;
mlx5_smfs_matcher_destroy(smfs_matcher->dr_matcher);
list_del(&smfs_matcher->list);
mutex_unlock(&fs_smfs->lock);
}
static int
mlx5_ct_fs_smfs_init(struct mlx5_ct_fs *fs, struct mlx5_flow_table *ct,
struct mlx5_flow_table *ct_nat, struct mlx5_flow_table *post_ct)
{
struct mlx5dr_table *ct_tbl, *ct_nat_tbl, *post_ct_tbl;
struct mlx5_ct_fs_smfs *fs_smfs = mlx5_ct_fs_priv(fs);
post_ct_tbl = mlx5_smfs_table_get_from_fs_ft(post_ct);
ct_nat_tbl = mlx5_smfs_table_get_from_fs_ft(ct_nat);
ct_tbl = mlx5_smfs_table_get_from_fs_ft(ct);
fs_smfs->ct_nat = ct_nat;
if (!ct_tbl || !ct_nat_tbl || !post_ct_tbl) {
netdev_warn(fs->netdev, "ct_fs_smfs: failed to init, missing backing dr tables");
return -EOPNOTSUPP;
}
ct_dbg("using smfs steering");
fs_smfs->fwd_action = mlx5_smfs_action_create_dest_table(post_ct_tbl);
if (!fs_smfs->fwd_action) {
return -EINVAL;
}
fs_smfs->ct_tbl = ct_tbl;
fs_smfs->ct_nat_tbl = ct_nat_tbl;
mutex_init(&fs_smfs->lock);
INIT_LIST_HEAD(&fs_smfs->matchers.used);
INIT_LIST_HEAD(&fs_smfs->matchers_nat.used);
return 0;
}
static void
mlx5_ct_fs_smfs_destroy(struct mlx5_ct_fs *fs)
{
struct mlx5_ct_fs_smfs *fs_smfs = mlx5_ct_fs_priv(fs);
mlx5_smfs_action_destroy(fs_smfs->fwd_action);
}
static inline bool
mlx5_tc_ct_valid_used_dissector_keys(const u32 used_keys)
{
#define DISSECTOR_BIT(name) BIT(FLOW_DISSECTOR_KEY_ ## name)
const u32 basic_keys = DISSECTOR_BIT(BASIC) | DISSECTOR_BIT(CONTROL) |
DISSECTOR_BIT(PORTS) | DISSECTOR_BIT(META);
const u32 ipv4_tcp = basic_keys | DISSECTOR_BIT(IPV4_ADDRS) | DISSECTOR_BIT(TCP);
const u32 ipv4_udp = basic_keys | DISSECTOR_BIT(IPV4_ADDRS);
const u32 ipv6_tcp = basic_keys | DISSECTOR_BIT(IPV6_ADDRS) | DISSECTOR_BIT(TCP);
const u32 ipv6_udp = basic_keys | DISSECTOR_BIT(IPV6_ADDRS);
return (used_keys == ipv4_tcp || used_keys == ipv4_udp || used_keys == ipv6_tcp ||
used_keys == ipv6_udp);
}
static bool
mlx5_ct_fs_smfs_ct_validate_flow_rule(struct mlx5_ct_fs *fs, struct flow_rule *flow_rule)
{
struct flow_match_ipv4_addrs ipv4_addrs;
struct flow_match_ipv6_addrs ipv6_addrs;
struct flow_match_control control;
struct flow_match_basic basic;
struct flow_match_ports ports;
struct flow_match_tcp tcp;
if (!mlx5_tc_ct_valid_used_dissector_keys(flow_rule->match.dissector->used_keys)) {
ct_dbg("rule uses unexpected dissectors (0x%08x)",
flow_rule->match.dissector->used_keys);
return false;
}
flow_rule_match_basic(flow_rule, &basic);
flow_rule_match_control(flow_rule, &control);
flow_rule_match_ipv4_addrs(flow_rule, &ipv4_addrs);
flow_rule_match_ipv6_addrs(flow_rule, &ipv6_addrs);
flow_rule_match_ports(flow_rule, &ports);
flow_rule_match_tcp(flow_rule, &tcp);
if (basic.mask->n_proto != htons(0xFFFF) ||
(basic.key->n_proto != htons(ETH_P_IP) && basic.key->n_proto != htons(ETH_P_IPV6)) ||
basic.mask->ip_proto != 0xFF ||
(basic.key->ip_proto != IPPROTO_UDP && basic.key->ip_proto != IPPROTO_TCP)) {
ct_dbg("rule uses unexpected basic match (n_proto 0x%04x/0x%04x, ip_proto 0x%02x/0x%02x)",
ntohs(basic.key->n_proto), ntohs(basic.mask->n_proto),
basic.key->ip_proto, basic.mask->ip_proto);
return false;
}
if (ports.mask->src != htons(0xFFFF) || ports.mask->dst != htons(0xFFFF)) {
ct_dbg("rule uses ports match (src 0x%04x, dst 0x%04x)",
ports.mask->src, ports.mask->dst);
return false;
}
if (basic.key->ip_proto == IPPROTO_TCP && tcp.mask->flags != MLX5_CT_TCP_FLAGS_MASK) {
ct_dbg("rule uses unexpected tcp match (flags 0x%02x)", tcp.mask->flags);
return false;
}
return true;
}
static struct mlx5_ct_fs_rule *
mlx5_ct_fs_smfs_ct_rule_add(struct mlx5_ct_fs *fs, struct mlx5_flow_spec *spec,
struct mlx5_flow_attr *attr, struct flow_rule *flow_rule)
{
struct mlx5_ct_fs_smfs *fs_smfs = mlx5_ct_fs_priv(fs);
struct mlx5_ct_fs_smfs_matcher *smfs_matcher;
struct mlx5_ct_fs_smfs_rule *smfs_rule;
struct mlx5dr_action *actions[5];
struct mlx5dr_rule *rule;
int num_actions = 0, err;
bool nat, tcp, ipv4;
if (!mlx5_ct_fs_smfs_ct_validate_flow_rule(fs, flow_rule))
return ERR_PTR(-EOPNOTSUPP);
smfs_rule = kzalloc(sizeof(*smfs_rule), GFP_KERNEL);
if (!smfs_rule)
return ERR_PTR(-ENOMEM);
smfs_rule->count_action = mlx5_smfs_action_create_flow_counter(mlx5_fc_id(attr->counter));
if (!smfs_rule->count_action) {
err = -EINVAL;
goto err_count;
}
actions[num_actions++] = smfs_rule->count_action;
actions[num_actions++] = attr->modify_hdr->action.dr_action;
actions[num_actions++] = fs_smfs->fwd_action;
nat = (attr->ft == fs_smfs->ct_nat);
ipv4 = mlx5e_tc_get_ip_version(spec, true) == 4;
tcp = MLX5_GET(fte_match_param, spec->match_value,
outer_headers.ip_protocol) == IPPROTO_TCP;
smfs_matcher = mlx5_ct_fs_smfs_matcher_get(fs, nat, ipv4, tcp);
if (IS_ERR(smfs_matcher)) {
err = PTR_ERR(smfs_matcher);
goto err_matcher;
}
rule = mlx5_smfs_rule_create(smfs_matcher->dr_matcher, spec, num_actions, actions,
MLX5_FLOW_CONTEXT_FLOW_SOURCE_ANY_VPORT);
if (!rule) {
err = -EINVAL;
goto err_create;
}
smfs_rule->rule = rule;
smfs_rule->smfs_matcher = smfs_matcher;
return &smfs_rule->fs_rule;
err_create:
mlx5_ct_fs_smfs_matcher_put(fs, smfs_matcher);
err_matcher:
mlx5_smfs_action_destroy(smfs_rule->count_action);
err_count:
kfree(smfs_rule);
return ERR_PTR(err);
}
static void
mlx5_ct_fs_smfs_ct_rule_del(struct mlx5_ct_fs *fs, struct mlx5_ct_fs_rule *fs_rule)
{
struct mlx5_ct_fs_smfs_rule *smfs_rule = container_of(fs_rule,
struct mlx5_ct_fs_smfs_rule,
fs_rule);
mlx5_smfs_rule_destroy(smfs_rule->rule);
mlx5_ct_fs_smfs_matcher_put(fs, smfs_rule->smfs_matcher);
mlx5_smfs_action_destroy(smfs_rule->count_action);
kfree(smfs_rule);
}
static struct mlx5_ct_fs_ops fs_smfs_ops = {
.ct_rule_add = mlx5_ct_fs_smfs_ct_rule_add,
.ct_rule_del = mlx5_ct_fs_smfs_ct_rule_del,
.init = mlx5_ct_fs_smfs_init,
.destroy = mlx5_ct_fs_smfs_destroy,
.priv_size = sizeof(struct mlx5_ct_fs_smfs),
};
struct mlx5_ct_fs_ops *
mlx5_ct_fs_smfs_ops_get(void)
{
return &fs_smfs_ops;
}
......@@ -18,6 +18,7 @@
#include "lib/fs_chains.h"
#include "en/tc_ct.h"
#include "en/tc/ct_fs.h"
#include "en/tc_priv.h"
#include "en/mod_hdr.h"
#include "en/mapping.h"
......@@ -25,9 +26,8 @@
#include "en.h"
#include "en_tc.h"
#include "en_rep.h"
#include "fs_core.h"
#define MLX5_CT_ZONE_BITS (mlx5e_tc_attr_to_reg_mappings[ZONE_TO_REG].mlen)
#define MLX5_CT_ZONE_MASK GENMASK(MLX5_CT_ZONE_BITS - 1, 0)
#define MLX5_CT_STATE_ESTABLISHED_BIT BIT(1)
#define MLX5_CT_STATE_TRK_BIT BIT(2)
#define MLX5_CT_STATE_NAT_BIT BIT(3)
......@@ -63,6 +63,8 @@ struct mlx5_tc_ct_priv {
struct mapping_ctx *labels_mapping;
enum mlx5_flow_namespace_type ns_type;
struct mlx5_fs_chains *chains;
struct mlx5_ct_fs *fs;
struct mlx5_ct_fs_ops *fs_ops;
spinlock_t ht_lock; /* protects ft entries */
};
......@@ -74,7 +76,7 @@ struct mlx5_ct_flow {
};
struct mlx5_ct_zone_rule {
struct mlx5_flow_handle *rule;
struct mlx5_ct_fs_rule *rule;
struct mlx5e_mod_hdr_handle *mh;
struct mlx5_flow_attr *attr;
bool nat;
......@@ -505,7 +507,7 @@ mlx5_tc_ct_entry_del_rule(struct mlx5_tc_ct_priv *ct_priv,
ct_dbg("Deleting ct entry rule in zone %d", entry->tuple.zone);
mlx5_tc_rule_delete(netdev_priv(ct_priv->netdev), zone_rule->rule, attr);
ct_priv->fs_ops->ct_rule_del(ct_priv->fs, zone_rule->rule);
mlx5_tc_ct_entry_destroy_mod_hdr(ct_priv, zone_rule->attr, zone_rule->mh);
mlx5_put_label_mapping(ct_priv, attr->ct_attr.ct_labels_id);
kfree(attr);
......@@ -816,7 +818,7 @@ mlx5_tc_ct_entry_add_rule(struct mlx5_tc_ct_priv *ct_priv,
mlx5_tc_ct_set_tuple_match(ct_priv, spec, flow_rule);
mlx5e_tc_match_to_reg_match(spec, ZONE_TO_REG, entry->tuple.zone, MLX5_CT_ZONE_MASK);
zone_rule->rule = mlx5_tc_rule_insert(priv, spec, attr);
zone_rule->rule = ct_priv->fs_ops->ct_rule_add(ct_priv->fs, spec, attr, flow_rule);
if (IS_ERR(zone_rule->rule)) {
err = PTR_ERR(zone_rule->rule);
ct_dbg("Failed to add ct entry rule, nat: %d", nat);
......@@ -1960,6 +1962,38 @@ mlx5_tc_ct_delete_flow(struct mlx5_tc_ct_priv *priv,
mutex_unlock(&priv->control_lock);
}
static int
mlx5_tc_ct_fs_init(struct mlx5_tc_ct_priv *ct_priv)
{
struct mlx5_flow_table *post_ct = mlx5e_tc_post_act_get_ft(ct_priv->post_act);
struct mlx5_ct_fs_ops *fs_ops = mlx5_ct_fs_dmfs_ops_get();
int err;
if (ct_priv->ns_type == MLX5_FLOW_NAMESPACE_FDB &&
ct_priv->dev->priv.steering->mode == MLX5_FLOW_STEERING_MODE_SMFS) {
ct_dbg("Using SMFS ct flow steering provider");
fs_ops = mlx5_ct_fs_smfs_ops_get();
}
ct_priv->fs = kzalloc(sizeof(*ct_priv->fs) + fs_ops->priv_size, GFP_KERNEL);
if (!ct_priv->fs)
return -ENOMEM;
ct_priv->fs->netdev = ct_priv->netdev;
ct_priv->fs->dev = ct_priv->dev;
ct_priv->fs_ops = fs_ops;
err = ct_priv->fs_ops->init(ct_priv->fs, ct_priv->ct, ct_priv->ct_nat, post_ct);
if (err)
goto err_init;
return 0;
err_init:
kfree(ct_priv->fs);
return err;
}
static int
mlx5_tc_ct_init_check_esw_support(struct mlx5_eswitch *esw,
const char **err_msg)
......@@ -2098,8 +2132,14 @@ mlx5_tc_ct_init(struct mlx5e_priv *priv, struct mlx5_fs_chains *chains,
if (rhashtable_init(&ct_priv->ct_tuples_nat_ht, &tuples_nat_ht_params))
goto err_ct_tuples_nat_ht;
err = mlx5_tc_ct_fs_init(ct_priv);
if (err)
goto err_init_fs;
return ct_priv;
err_init_fs:
rhashtable_destroy(&ct_priv->ct_tuples_nat_ht);
err_ct_tuples_nat_ht:
rhashtable_destroy(&ct_priv->ct_tuples_ht);
err_ct_tuples_ht:
......@@ -2130,6 +2170,9 @@ mlx5_tc_ct_clean(struct mlx5_tc_ct_priv *ct_priv)
chains = ct_priv->chains;
ct_priv->fs_ops->destroy(ct_priv->fs);
kfree(ct_priv->fs);
mlx5_chains_destroy_global_table(chains, ct_priv->ct_nat);
mlx5_chains_destroy_global_table(chains, ct_priv->ct);
mapping_destroy(ct_priv->zone_mapping);
......
......@@ -86,6 +86,8 @@ struct mlx5_ct_attr {
#define REG_MAPPING_MLEN(reg) (mlx5e_tc_attr_to_reg_mappings[reg].mlen)
#define REG_MAPPING_MOFFSET(reg) (mlx5e_tc_attr_to_reg_mappings[reg].moffset)
#define MLX5_CT_ZONE_BITS (mlx5e_tc_attr_to_reg_mappings[ZONE_TO_REG].mlen)
#define MLX5_CT_ZONE_MASK GENMASK(MLX5_CT_ZONE_BITS - 1, 0)
#if IS_ENABLED(CONFIG_MLX5_TC_CT)
......
......@@ -35,7 +35,6 @@
#include <crypto/aead.h>
#include <linux/inetdevice.h>
#include <linux/netdevice.h>
#include <linux/module.h>
#include "en.h"
#include "en_accel/ipsec.h"
......
......@@ -5,7 +5,6 @@
#include <linux/interrupt.h>
#include <linux/notifier.h>
#include <linux/module.h>
#include <linux/mlx5/driver.h>
#include <linux/mlx5/vport.h>
#include <linux/mlx5/eq.h>
......@@ -439,7 +438,8 @@ int mlx5_eq_table_init(struct mlx5_core_dev *dev)
struct mlx5_eq_table *eq_table;
int i;
eq_table = kvzalloc(sizeof(*eq_table), GFP_KERNEL);
eq_table = kvzalloc_node(sizeof(*eq_table), GFP_KERNEL,
dev->priv.numa_node);
if (!eq_table)
return -ENOMEM;
......@@ -728,7 +728,8 @@ struct mlx5_eq *
mlx5_eq_create_generic(struct mlx5_core_dev *dev,
struct mlx5_eq_param *param)
{
struct mlx5_eq *eq = kvzalloc(sizeof(*eq), GFP_KERNEL);
struct mlx5_eq *eq = kvzalloc_node(sizeof(*eq), GFP_KERNEL,
dev->priv.numa_node);
int err;
if (!eq)
......@@ -888,10 +889,11 @@ static int create_comp_eqs(struct mlx5_core_dev *dev)
return ncomp_eqs;
INIT_LIST_HEAD(&table->comp_eqs_list);
nent = comp_eq_depth_devlink_param_get(dev);
for (i = 0; i < ncomp_eqs; i++) {
struct mlx5_eq_param param = {};
eq = kzalloc(sizeof(*eq), GFP_KERNEL);
eq = kzalloc_node(sizeof(*eq), GFP_KERNEL, dev->priv.numa_node);
if (!eq) {
err = -ENOMEM;
goto clean;
......
......@@ -30,7 +30,6 @@
* SOFTWARE.
*/
#include <linux/module.h>
#include <linux/etherdevice.h>
#include <linux/mlx5/driver.h>
......
......@@ -32,7 +32,6 @@
#include <linux/mlx5/driver.h>
#include <linux/mlx5/eswitch.h>
#include <linux/module.h>
#include "mlx5_core.h"
#include "../../mlxfw/mlxfw.h"
#include "lib/tout.h"
......
......@@ -31,7 +31,6 @@
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/random.h>
#include <linux/vmalloc.h>
#include <linux/hardirq.h>
......
/* SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB */
/* Copyright (c) 2019 Mellanox Technologies. */
#include <linux/module.h>
#include <linux/mlx5/driver.h>
#include <linux/mlx5/port.h>
#include "mlx5_core.h"
......
// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
/* Copyright (c) 2021, NVIDIA CORPORATION & AFFILIATES. */
#include <linux/kernel.h>
#include <linux/mlx5/driver.h>
#include "smfs.h"
struct mlx5dr_matcher *
mlx5_smfs_matcher_create(struct mlx5dr_table *table, u32 priority, struct mlx5_flow_spec *spec)
{
struct mlx5dr_match_parameters matcher_mask = {};
matcher_mask.match_buf = (u64 *)&spec->match_criteria;
matcher_mask.match_sz = DR_SZ_MATCH_PARAM;
return mlx5dr_matcher_create(table, priority, spec->match_criteria_enable, &matcher_mask);
}
void
mlx5_smfs_matcher_destroy(struct mlx5dr_matcher *matcher)
{
mlx5dr_matcher_destroy(matcher);
}
struct mlx5dr_table *
mlx5_smfs_table_get_from_fs_ft(struct mlx5_flow_table *ft)
{
return mlx5dr_table_get_from_fs_ft(ft);
}
struct mlx5dr_action *
mlx5_smfs_action_create_dest_table(struct mlx5dr_table *table)
{
return mlx5dr_action_create_dest_table(table);
}
struct mlx5dr_action *
mlx5_smfs_action_create_flow_counter(u32 counter_id)
{
return mlx5dr_action_create_flow_counter(counter_id);
}
void
mlx5_smfs_action_destroy(struct mlx5dr_action *action)
{
mlx5dr_action_destroy(action);
}
struct mlx5dr_rule *
mlx5_smfs_rule_create(struct mlx5dr_matcher *matcher, struct mlx5_flow_spec *spec,
size_t num_actions, struct mlx5dr_action *actions[],
u32 flow_source)
{
struct mlx5dr_match_parameters value = {};
value.match_buf = (u64 *)spec->match_value;
value.match_sz = DR_SZ_MATCH_PARAM;
return mlx5dr_rule_create(matcher, &value, num_actions, actions, flow_source);
}
void
mlx5_smfs_rule_destroy(struct mlx5dr_rule *rule)
{
mlx5dr_rule_destroy(rule);
}
/* SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB */
/* Copyright (c) 2021, NVIDIA CORPORATION & AFFILIATES. */
#ifndef __MLX5_LIB_SMFS_H__
#define __MLX5_LIB_SMFS_H__
#include "steering/mlx5dr.h"
#include "steering/dr_types.h"
struct mlx5dr_matcher *
mlx5_smfs_matcher_create(struct mlx5dr_table *table, u32 priority, struct mlx5_flow_spec *spec);
void
mlx5_smfs_matcher_destroy(struct mlx5dr_matcher *matcher);
struct mlx5dr_table *
mlx5_smfs_table_get_from_fs_ft(struct mlx5_flow_table *ft);
struct mlx5dr_action *
mlx5_smfs_action_create_dest_table(struct mlx5dr_table *table);
struct mlx5dr_action *
mlx5_smfs_action_create_flow_counter(u32 counter_id);
void
mlx5_smfs_action_destroy(struct mlx5dr_action *action);
struct mlx5dr_rule *
mlx5_smfs_rule_create(struct mlx5dr_matcher *matcher, struct mlx5_flow_spec *spec,
size_t num_actions, struct mlx5dr_action *actions[],
u32 flow_source);
void
mlx5_smfs_rule_destroy(struct mlx5dr_rule *rule);
#endif /* __MLX5_LIB_SMFS_H__ */
......@@ -31,7 +31,6 @@
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/refcount.h>
#include <linux/mlx5/driver.h>
#include <net/vxlan.h>
......
......@@ -31,7 +31,6 @@
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/mlx5/driver.h>
#include <rdma/ib_verbs.h>
#include "mlx5_core.h"
......
......@@ -31,7 +31,6 @@
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/mlx5/driver.h>
#include "mlx5_core.h"
......
......@@ -32,7 +32,6 @@
#include <linux/highmem.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/delay.h>
#include <linux/mlx5/driver.h>
#include <linux/xarray.h>
......
......@@ -3,7 +3,6 @@
#include <linux/interrupt.h>
#include <linux/notifier.h>
#include <linux/module.h>
#include <linux/mlx5/driver.h>
#include "mlx5_core.h"
#include "mlx5_irq.h"
......@@ -601,7 +600,8 @@ int mlx5_irq_table_init(struct mlx5_core_dev *dev)
if (mlx5_core_is_sf(dev))
return 0;
irq_table = kvzalloc(sizeof(*irq_table), GFP_KERNEL);
irq_table = kvzalloc_node(sizeof(*irq_table), GFP_KERNEL,
dev->priv.numa_node);
if (!irq_table)
return -ENOMEM;
......
......@@ -31,7 +31,6 @@
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/mlx5/driver.h>
#include "mlx5_core.h"
......
......@@ -275,7 +275,6 @@ static int mlx5_query_module_num(struct mlx5_core_dev *dev, int *module_num)
{
u32 in[MLX5_ST_SZ_DW(pmlp_reg)] = {0};
u32 out[MLX5_ST_SZ_DW(pmlp_reg)];
int module_mapping;
int err;
MLX5_SET(pmlp_reg, in, local_port, 1);
......@@ -284,8 +283,9 @@ static int mlx5_query_module_num(struct mlx5_core_dev *dev, int *module_num)
if (err)
return err;
module_mapping = MLX5_GET(pmlp_reg, out, lane0_module_mapping);
*module_num = module_mapping & MLX5_EEPROM_IDENTIFIER_BYTE_MASK;
*module_num = MLX5_GET(lane_2_module_mapping,
MLX5_ADDR_OF(pmlp_reg, out, lane0_module_mapping),
module);
return 0;
}
......@@ -365,6 +365,12 @@ static void mlx5_sfp_eeprom_params_set(u16 *i2c_addr, int *page_num, u16 *offset
*offset -= MLX5_EEPROM_PAGE_LENGTH;
}
static int mlx5_mcia_max_bytes(struct mlx5_core_dev *dev)
{
/* mcia supports either 12 dwords or 32 dwords */
return (MLX5_CAP_MCAM_FEATURE(dev, mcia_32dwords) ? 32 : 12) * sizeof(u32);
}
static int mlx5_query_mcia(struct mlx5_core_dev *dev,
struct mlx5_module_eeprom_query_params *params, u8 *data)
{
......@@ -374,7 +380,7 @@ static int mlx5_query_mcia(struct mlx5_core_dev *dev,
void *ptr;
u16 size;
size = min_t(int, params->size, MLX5_EEPROM_MAX_BYTES);
size = min_t(int, params->size, mlx5_mcia_max_bytes(dev));
MLX5_SET(mcia_reg, in, l, 0);
MLX5_SET(mcia_reg, in, size, size);
......@@ -445,35 +451,12 @@ int mlx5_query_module_eeprom_by_page(struct mlx5_core_dev *dev,
struct mlx5_module_eeprom_query_params *params,
u8 *data)
{
u8 module_id;
int err;
err = mlx5_query_module_num(dev, &params->module_number);
if (err)
return err;
err = mlx5_query_module_id(dev, params->module_number, &module_id);
if (err)
return err;
switch (module_id) {
case MLX5_MODULE_ID_SFP:
if (params->page > 0)
return -EINVAL;
break;
case MLX5_MODULE_ID_QSFP:
case MLX5_MODULE_ID_QSFP28:
case MLX5_MODULE_ID_QSFP_PLUS:
if (params->page > 3)
return -EINVAL;
break;
case MLX5_MODULE_ID_DSFP:
break;
default:
mlx5_core_err(dev, "Module ID not recognized: 0x%x\n", module_id);
return -EINVAL;
}
if (params->i2c_address != MLX5_I2C_ADDR_HIGH &&
params->i2c_address != MLX5_I2C_ADDR_LOW) {
mlx5_core_err(dev, "I2C address not recognized: 0x%x\n", params->i2c_address);
......
......@@ -31,7 +31,6 @@
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/mlx5/driver.h>
#include "mlx5_core.h"
......
......@@ -3,7 +3,6 @@
#include <linux/debugfs.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/seq_file.h>
#include "dr_types.h"
......
......@@ -305,3 +305,8 @@ u32 mlx5dr_table_get_id(struct mlx5dr_table *tbl)
{
return tbl->table_id;
}
struct mlx5dr_table *mlx5dr_table_get_from_fs_ft(struct mlx5_flow_table *ft)
{
return ft->fs_dr_table.dr_table;
}
......@@ -53,6 +53,9 @@ void mlx5dr_domain_set_peer(struct mlx5dr_domain *dmn,
struct mlx5dr_table *
mlx5dr_table_create(struct mlx5dr_domain *domain, u32 level, u32 flags);
struct mlx5dr_table *
mlx5dr_table_get_from_fs_ft(struct mlx5_flow_table *ft);
int mlx5dr_table_destroy(struct mlx5dr_table *table);
u32 mlx5dr_table_get_id(struct mlx5dr_table *table);
......
......@@ -31,7 +31,6 @@
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/io-mapping.h>
#include <linux/mlx5/driver.h>
#include "mlx5_core.h"
......@@ -100,19 +99,21 @@ static struct mlx5_uars_page *alloc_uars_page(struct mlx5_core_dev *mdev,
int err = -ENOMEM;
phys_addr_t pfn;
int bfregs;
int node;
int i;
bfregs = uars_per_sys_page(mdev) * MLX5_BFREGS_PER_UAR;
up = kzalloc(sizeof(*up), GFP_KERNEL);
node = mdev->priv.numa_node;
up = kzalloc_node(sizeof(*up), GFP_KERNEL, node);
if (!up)
return ERR_PTR(err);
up->mdev = mdev;
up->reg_bitmap = bitmap_zalloc(bfregs, GFP_KERNEL);
up->reg_bitmap = bitmap_zalloc_node(bfregs, GFP_KERNEL, node);
if (!up->reg_bitmap)
goto error1;
up->fp_bitmap = bitmap_zalloc(bfregs, GFP_KERNEL);
up->fp_bitmap = bitmap_zalloc_node(bfregs, GFP_KERNEL, node);
if (!up->fp_bitmap)
goto error1;
......
......@@ -9691,7 +9691,9 @@ struct mlx5_ifc_pcam_reg_bits {
};
struct mlx5_ifc_mcam_enhanced_features_bits {
u8 reserved_at_0[0x6a];
u8 reserved_at_0[0x5d];
u8 mcia_32dwords[0x1];
u8 reserved_at_5e[0xc];
u8 reset_state[0x1];
u8 ptpcyc2realtime_modify[0x1];
u8 reserved_at_6c[0x2];
......@@ -9886,10 +9888,10 @@ struct mlx5_ifc_pcmr_reg_bits {
};
struct mlx5_ifc_lane_2_module_mapping_bits {
u8 reserved_at_0[0x6];
u8 rx_lane[0x2];
u8 reserved_at_8[0x6];
u8 tx_lane[0x2];
u8 reserved_at_0[0x4];
u8 rx_lane[0x4];
u8 reserved_at_8[0x4];
u8 tx_lane[0x4];
u8 reserved_at_10[0x8];
u8 module[0x8];
};
......
......@@ -56,8 +56,6 @@ enum mlx5_an_status {
MLX5_AN_LINK_DOWN = 4,
};
#define MLX5_EEPROM_MAX_BYTES 32
#define MLX5_EEPROM_IDENTIFIER_BYTE_MASK 0x000000ff
#define MLX5_I2C_ADDR_LOW 0x50
#define MLX5_I2C_ADDR_HIGH 0x51
#define MLX5_EEPROM_PAGE_LENGTH 256
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment