Commit 2ef8e39f authored by David S. Miller's avatar David S. Miller

Merge branch 'octeontx2-af-next'

Ratheesh Kannoth says:

====================
octeontx2: *** Exact Match Table and Field hash ***

*** Exact match table and Field hash support for CN10KB silicon ***

Ratheesh Kannoth (11):

These patch series enables exact match table in CN10KB silicon. Legacy
silicon used NPC mcam to do packet fields/channel matching for NPC rules.
NPC mcam resources exahausted as customer use case increased.
Supporting many DMAC filter becomes a challenge, as RPM based filter
count is less. Exact match table has 4way 2K entry table and a 32 entry
fully associative cam table. Second table is to handle hash
table collision overflows in 4way 2K entry table. Enabling exact match table
results in KEX key to be appended with Hit/Miss status. This can be used
to match in NPC mcam for a more generic rule and drop those packets than
having DMAC drop rules for each DMAC entry in NPC mcam.

  octeontx2-af: Exact match support
  octeontx2-af: Exact match scan from kex profile
  octeontx2-af: devlink configuration support
  octeontx2-af: FLR handler for exact match table.
  octeontx2-af: Drop rules for NPC MCAM
  octeontx2-af: Debugsfs support for exact match.
  octeontx2: Modify mbox request and response structures
  octeontx2-af: Wrapper functions for mac addr add/del/update/reset
  octeontx2-af: Invoke exact match functions if supported
  octeontx2-pf: Add support for exact match table.
  octeontx2-af: Enable Exact match flag in kex profile

Suman Ghosh (1):

CN10KB variant of CN10K series of silicons supports
a new feature where in a large protocol field
(eg 128bit IPv6 DIP) can be condensed into a small
hashed 32bit data. This saves a lot of space in MCAM key
and allows user to add more protocol fields into the filter.
A max of two such protocol data can be hashed.
This patch adds support for hashing IPv6 SIP and/or DIP.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents e7ce9fc9 7189d28e
......@@ -11,4 +11,4 @@ rvu_mbox-y := mbox.o rvu_trace.o
rvu_af-y := cgx.o rvu.o rvu_cgx.o rvu_npa.o rvu_nix.o \
rvu_reg.o rvu_npc.o rvu_debugfs.o ptp.o rvu_npc_fs.o \
rvu_cpt.o rvu_devlink.o rpm.o rvu_cn10k.o rvu_switch.o \
rvu_sdp.o
rvu_sdp.o rvu_npc_hash.o
......@@ -169,9 +169,10 @@ M(CGX_GET_PHY_FEC_STATS, 0x219, cgx_get_phy_fec_stats, msg_req, msg_rsp) \
M(CGX_FEATURES_GET, 0x21B, cgx_features_get, msg_req, \
cgx_features_info_msg) \
M(RPM_STATS, 0x21C, rpm_stats, msg_req, rpm_stats_rsp) \
M(CGX_MAC_ADDR_RESET, 0x21D, cgx_mac_addr_reset, msg_req, msg_rsp) \
M(CGX_MAC_ADDR_RESET, 0x21D, cgx_mac_addr_reset, cgx_mac_addr_reset_req, \
msg_rsp) \
M(CGX_MAC_ADDR_UPDATE, 0x21E, cgx_mac_addr_update, cgx_mac_addr_update_req, \
msg_rsp) \
cgx_mac_addr_update_rsp) \
M(CGX_PRIO_FLOW_CTRL_CFG, 0x21F, cgx_prio_flow_ctrl_cfg, cgx_pfc_cfg, \
cgx_pfc_rsp) \
/* NPA mbox IDs (range 0x400 - 0x5FF) */ \
......@@ -241,6 +242,9 @@ M(NPC_MCAM_READ_BASE_RULE, 0x6011, npc_read_base_steer_rule, \
M(NPC_MCAM_GET_STATS, 0x6012, npc_mcam_entry_stats, \
npc_mcam_get_stats_req, \
npc_mcam_get_stats_rsp) \
M(NPC_GET_SECRET_KEY, 0x6013, npc_get_secret_key, \
npc_get_secret_key_req, \
npc_get_secret_key_rsp) \
/* NIX mbox IDs (range 0x8000 - 0xFFFF) */ \
M(NIX_LF_ALLOC, 0x8000, nix_lf_alloc, \
nix_lf_alloc_req, nix_lf_alloc_rsp) \
......@@ -428,6 +432,7 @@ struct get_hw_cap_rsp {
struct mbox_msghdr hdr;
u8 nix_fixed_txschq_mapping; /* Schq mapping fixed or flexible */
u8 nix_shaping; /* Is shaping and coloring supported */
u8 npc_hash_extract; /* Is hash extract supported */
};
/* CGX mbox message formats */
......@@ -451,6 +456,7 @@ struct cgx_fec_stats_rsp {
struct cgx_mac_addr_set_or_get {
struct mbox_msghdr hdr;
u8 mac_addr[ETH_ALEN];
u32 index;
};
/* Structure for requesting the operation to
......@@ -466,7 +472,7 @@ struct cgx_mac_addr_add_req {
*/
struct cgx_mac_addr_add_rsp {
struct mbox_msghdr hdr;
u8 index;
u32 index;
};
/* Structure for requesting the operation to
......@@ -474,7 +480,7 @@ struct cgx_mac_addr_add_rsp {
*/
struct cgx_mac_addr_del_req {
struct mbox_msghdr hdr;
u8 index;
u32 index;
};
/* Structure for response against the operation to
......@@ -482,7 +488,7 @@ struct cgx_mac_addr_del_req {
*/
struct cgx_max_dmac_entries_get_rsp {
struct mbox_msghdr hdr;
u8 max_dmac_filters;
u32 max_dmac_filters;
};
struct cgx_link_user_info {
......@@ -583,10 +589,20 @@ struct cgx_set_link_mode_rsp {
int status;
};
struct cgx_mac_addr_reset_req {
struct mbox_msghdr hdr;
u32 index;
};
struct cgx_mac_addr_update_req {
struct mbox_msghdr hdr;
u8 mac_addr[ETH_ALEN];
u8 index;
u32 index;
};
struct cgx_mac_addr_update_rsp {
struct mbox_msghdr hdr;
u32 index;
};
#define RVU_LMAC_FEAT_FC BIT_ULL(0) /* pause frames */
......@@ -1440,6 +1456,16 @@ struct npc_mcam_get_stats_rsp {
u8 stat_ena; /* enabled */
};
struct npc_get_secret_key_req {
struct mbox_msghdr hdr;
u8 intf;
};
struct npc_get_secret_key_rsp {
struct mbox_msghdr hdr;
u64 secret_key[3];
};
enum ptp_op {
PTP_OP_ADJFINE = 0,
PTP_OP_GET_CLOCK = 1,
......@@ -1622,6 +1648,9 @@ enum cgx_af_status {
LMAC_AF_ERR_PERM_DENIED = -1103,
LMAC_AF_ERR_PFC_ENADIS_PERM_DENIED = -1104,
LMAC_AF_ERR_8023PAUSE_ENADIS_PERM_DENIED = -1105,
LMAC_AF_ERR_EXACT_MATCH_TBL_ADD_FAILED = -1108,
LMAC_AF_ERR_EXACT_MATCH_TBL_DEL_FAILED = -1109,
LMAC_AF_ERR_EXACT_MATCH_TBL_LOOK_UP_FAILED = -1110,
};
#endif /* MBOX_H */
......@@ -10,6 +10,14 @@
#define NPC_KEX_CHAN_MASK 0xFFFULL
#define SET_KEX_LD(intf, lid, ltype, ld, cfg) \
rvu_write64(rvu, blkaddr, \
NPC_AF_INTFX_LIDX_LTX_LDX_CFG(intf, lid, ltype, ld), cfg)
#define SET_KEX_LDFLAGS(intf, ld, flags, cfg) \
rvu_write64(rvu, blkaddr, \
NPC_AF_INTFX_LDATAX_FLAGSX_CFG(intf, ld, flags), cfg)
enum NPC_LID_E {
NPC_LID_LA = 0,
NPC_LID_LB,
......@@ -200,6 +208,7 @@ enum key_fields {
NPC_ERRLEV,
NPC_ERRCODE,
NPC_LXMB,
NPC_EXACT_RESULT,
NPC_LA,
NPC_LB,
NPC_LC,
......@@ -380,6 +389,22 @@ struct nix_rx_action {
#endif
};
/* NPC_AF_INTFX_KEX_CFG field masks */
#define NPC_EXACT_NIBBLE_START 40
#define NPC_EXACT_NIBBLE_END 43
#define NPC_EXACT_NIBBLE GENMASK_ULL(43, 40)
/* NPC_EXACT_KEX_S nibble definitions for each field */
#define NPC_EXACT_NIBBLE_HIT BIT_ULL(40)
#define NPC_EXACT_NIBBLE_OPC BIT_ULL(40)
#define NPC_EXACT_NIBBLE_WAY BIT_ULL(40)
#define NPC_EXACT_NIBBLE_INDEX GENMASK_ULL(43, 41)
#define NPC_EXACT_RESULT_HIT BIT_ULL(0)
#define NPC_EXACT_RESULT_OPC GENMASK_ULL(2, 1)
#define NPC_EXACT_RESULT_WAY GENMASK_ULL(4, 3)
#define NPC_EXACT_RESULT_IDX GENMASK_ULL(15, 5)
/* NPC_AF_INTFX_KEX_CFG field masks */
#define NPC_PARSE_NIBBLE GENMASK_ULL(30, 0)
......
......@@ -155,7 +155,7 @@
/* Rx parse key extract nibble enable */
#define NPC_PARSE_NIBBLE_INTF_RX (NPC_PARSE_NIBBLE_CHAN | \
NPC_PARSE_NIBBLE_ERRCODE | \
NPC_PARSE_NIBBLE_L2L3_BCAST | \
NPC_PARSE_NIBBLE_LA_LTYPE | \
NPC_PARSE_NIBBLE_LB_LTYPE | \
NPC_PARSE_NIBBLE_LC_LTYPE | \
......@@ -15123,7 +15123,8 @@ static struct npc_mcam_kex npc_mkex_default = {
.kpu_version = NPC_KPU_PROFILE_VER,
.keyx_cfg = {
/* nibble: LA..LE (ltype only) + Error code + Channel */
[NIX_INTF_RX] = ((u64)NPC_MCAM_KEY_X2 << 32) | NPC_PARSE_NIBBLE_INTF_RX,
[NIX_INTF_RX] = ((u64)NPC_MCAM_KEY_X2 << 32) | NPC_PARSE_NIBBLE_INTF_RX |
(u64)NPC_EXACT_NIBBLE_HIT,
/* nibble: LA..LE (ltype only) */
[NIX_INTF_TX] = ((u64)NPC_MCAM_KEY_X2 << 32) | NPC_PARSE_NIBBLE_INTF_TX,
},
......
......@@ -18,6 +18,7 @@
#include "ptp.h"
#include "rvu_trace.h"
#include "rvu_npc_hash.h"
#define DRV_NAME "rvu_af"
#define DRV_STRING "Marvell OcteonTX2 RVU Admin Function Driver"
......@@ -68,6 +69,8 @@ static void rvu_setup_hw_capabilities(struct rvu *rvu)
hw->cap.nix_tx_link_bp = true;
hw->cap.nix_rx_multicast = true;
hw->cap.nix_shaper_toggle_wait = false;
hw->cap.npc_hash_extract = false;
hw->cap.npc_exact_match_enabled = false;
hw->rvu = rvu;
if (is_rvu_pre_96xx_C0(rvu)) {
......@@ -85,6 +88,9 @@ static void rvu_setup_hw_capabilities(struct rvu *rvu)
if (!is_rvu_otx2(rvu))
hw->cap.per_pf_mbox_regs = true;
if (is_rvu_npc_hash_extract_en(rvu))
hw->cap.npc_hash_extract = true;
}
/* Poll a RVU block's register 'offset', for a 'zero'
......@@ -1122,6 +1128,12 @@ static int rvu_setup_hw_resources(struct rvu *rvu)
goto cgx_err;
}
err = rvu_npc_exact_init(rvu);
if (err) {
dev_err(rvu->dev, "failed to initialize exact match table\n");
return err;
}
/* Assign MACs for CGX mapped functions */
rvu_setup_pfvf_macaddress(rvu);
......@@ -1991,6 +2003,7 @@ int rvu_mbox_handler_get_hw_cap(struct rvu *rvu, struct msg_req *req,
rsp->nix_fixed_txschq_mapping = hw->cap.nix_fixed_txschq_mapping;
rsp->nix_shaping = hw->cap.nix_shaping;
rsp->npc_hash_extract = hw->cap.npc_hash_extract;
return 0;
}
......@@ -2548,6 +2561,9 @@ static void rvu_blklf_teardown(struct rvu *rvu, u16 pcifunc, u8 blkaddr)
static void __rvu_flr_handler(struct rvu *rvu, u16 pcifunc)
{
if (rvu_npc_exact_has_match_table(rvu))
rvu_npc_exact_reset(rvu, pcifunc);
mutex_lock(&rvu->flr_lock);
/* Reset order should reflect inter-block dependencies:
* 1. Reset any packet/work sources (NIX, CPT, TIM)
......
......@@ -338,6 +338,8 @@ struct hw_cap {
bool per_pf_mbox_regs; /* PF mbox specified in per PF registers ? */
bool programmable_chans; /* Channels programmable ? */
bool ipolicer;
bool npc_hash_extract; /* Hash extract enabled ? */
bool npc_exact_match_enabled; /* Exact match supported ? */
};
struct rvu_hwinfo {
......@@ -369,6 +371,7 @@ struct rvu_hwinfo {
struct rvu *rvu;
struct npc_pkind pkind;
struct npc_mcam mcam;
struct npc_exact_table *table;
};
struct mbox_wq_info {
......@@ -419,6 +422,7 @@ struct npc_kpu_profile_adapter {
const struct npc_kpu_profile_action *ikpu; /* array[pkinds] */
const struct npc_kpu_profile *kpu; /* array[kpus] */
struct npc_mcam_kex *mkex;
struct npc_mcam_kex_hash *mkex_hash;
bool custom;
size_t pkinds;
size_t kpus;
......@@ -575,6 +579,17 @@ static inline bool is_rvu_otx2(struct rvu *rvu)
midr == PCI_REVISION_ID_95XXMM || midr == PCI_REVISION_ID_95XXO);
}
static inline bool is_rvu_npc_hash_extract_en(struct rvu *rvu)
{
u64 npc_const3;
npc_const3 = rvu_read64(rvu, BLKADDR_NPC, NPC_AF_CONST3);
if (!(npc_const3 & BIT_ULL(62)))
return false;
return true;
}
static inline u16 rvu_nix_chan_cgx(struct rvu *rvu, u8 cgxid,
u8 lmacid, u8 chan)
{
......@@ -754,7 +769,6 @@ u32 convert_dwrr_mtu_to_bytes(u8 dwrr_mtu);
u32 convert_bytes_to_dwrr_mtu(u32 bytes);
/* NPC APIs */
int rvu_npc_init(struct rvu *rvu);
void rvu_npc_freemem(struct rvu *rvu);
int rvu_npc_get_pkind(struct rvu *rvu, u16 pf);
void rvu_npc_set_pkind(struct rvu *rvu, int pkind, struct rvu_pfvf *pfvf);
......@@ -773,14 +787,17 @@ void rvu_npc_install_allmulti_entry(struct rvu *rvu, u16 pcifunc, int nixlf,
u64 chan);
void rvu_npc_enable_allmulti_entry(struct rvu *rvu, u16 pcifunc, int nixlf,
bool enable);
void npc_enadis_default_mce_entry(struct rvu *rvu, u16 pcifunc,
int nixlf, int type, bool enable);
void rvu_npc_disable_mcam_entries(struct rvu *rvu, u16 pcifunc, int nixlf);
bool rvu_npc_enable_mcam_by_entry_index(struct rvu *rvu, int entry, int intf, bool enable);
void rvu_npc_free_mcam_entries(struct rvu *rvu, u16 pcifunc, int nixlf);
void rvu_npc_disable_default_entries(struct rvu *rvu, u16 pcifunc, int nixlf);
void rvu_npc_enable_default_entries(struct rvu *rvu, u16 pcifunc, int nixlf);
void rvu_npc_update_flowkey_alg_idx(struct rvu *rvu, u16 pcifunc, int nixlf,
int group, int alg_idx, int mcam_index);
void rvu_npc_get_mcam_entry_alloc_info(struct rvu *rvu, u16 pcifunc,
int blkaddr, int *alloc_cnt,
int *enable_cnt);
......@@ -815,6 +832,11 @@ int npc_get_nixlf_mcam_index(struct npc_mcam *mcam, u16 pcifunc, int nixlf,
int type);
bool is_mcam_entry_enabled(struct rvu *rvu, struct npc_mcam *mcam, int blkaddr,
int index);
int rvu_npc_init(struct rvu *rvu);
int npc_install_mcam_drop_rule(struct rvu *rvu, int mcam_idx, u16 *counter_idx,
u64 chan_val, u64 chan_mask, u64 exact_val, u64 exact_mask,
u64 bcast_mcast_val, u64 bcast_mcast_mask);
void npc_mcam_rsrcs_reserve(struct rvu *rvu, int blkaddr, int entry_idx);
/* CPT APIs */
int rvu_cpt_register_interrupts(struct rvu *rvu);
......
......@@ -14,6 +14,7 @@
#include "lmac_common.h"
#include "rvu_reg.h"
#include "rvu_trace.h"
#include "rvu_npc_hash.h"
struct cgx_evq_entry {
struct list_head evq_node;
......@@ -474,6 +475,11 @@ void rvu_cgx_disable_dmac_entries(struct rvu *rvu, u16 pcifunc)
if (!is_cgx_config_permitted(rvu, pcifunc))
return;
if (rvu_npc_exact_has_match_table(rvu)) {
rvu_npc_exact_reset(rvu, pcifunc);
return;
}
rvu_get_cgx_lmac_id(rvu->pf2cgxlmac_map[pf], &cgx_id, &lmac_id);
cgx_dev = cgx_get_pdata(cgx_id);
lmac_count = cgx_get_lmac_cnt(cgx_dev);
......@@ -584,6 +590,9 @@ int rvu_mbox_handler_cgx_mac_addr_set(struct rvu *rvu,
if (!is_cgx_config_permitted(rvu, req->hdr.pcifunc))
return -EPERM;
if (rvu_npc_exact_has_match_table(rvu))
return rvu_npc_exact_mac_addr_set(rvu, req, rsp);
rvu_get_cgx_lmac_id(rvu->pf2cgxlmac_map[pf], &cgx_id, &lmac_id);
cgx_lmac_addr_set(cgx_id, lmac_id, req->mac_addr);
......@@ -602,6 +611,9 @@ int rvu_mbox_handler_cgx_mac_addr_add(struct rvu *rvu,
if (!is_cgx_config_permitted(rvu, req->hdr.pcifunc))
return -EPERM;
if (rvu_npc_exact_has_match_table(rvu))
return rvu_npc_exact_mac_addr_add(rvu, req, rsp);
rvu_get_cgx_lmac_id(rvu->pf2cgxlmac_map[pf], &cgx_id, &lmac_id);
rc = cgx_lmac_addr_add(cgx_id, lmac_id, req->mac_addr);
if (rc >= 0) {
......@@ -622,6 +634,9 @@ int rvu_mbox_handler_cgx_mac_addr_del(struct rvu *rvu,
if (!is_cgx_config_permitted(rvu, req->hdr.pcifunc))
return -EPERM;
if (rvu_npc_exact_has_match_table(rvu))
return rvu_npc_exact_mac_addr_del(rvu, req, rsp);
rvu_get_cgx_lmac_id(rvu->pf2cgxlmac_map[pf], &cgx_id, &lmac_id);
return cgx_lmac_addr_del(cgx_id, lmac_id, req->index);
}
......@@ -643,6 +658,11 @@ int rvu_mbox_handler_cgx_mac_max_entries_get(struct rvu *rvu,
return 0;
}
if (rvu_npc_exact_has_match_table(rvu)) {
rsp->max_dmac_filters = rvu_npc_exact_get_max_entries(rvu);
return 0;
}
rvu_get_cgx_lmac_id(rvu->pf2cgxlmac_map[pf], &cgx_id, &lmac_id);
rsp->max_dmac_filters = cgx_lmac_addr_max_entries_get(cgx_id, lmac_id);
return 0;
......@@ -680,6 +700,10 @@ int rvu_mbox_handler_cgx_promisc_enable(struct rvu *rvu, struct msg_req *req,
if (!is_cgx_config_permitted(rvu, req->hdr.pcifunc))
return -EPERM;
/* Disable drop on non hit rule */
if (rvu_npc_exact_has_match_table(rvu))
return rvu_npc_exact_promisc_enable(rvu, req->hdr.pcifunc);
rvu_get_cgx_lmac_id(rvu->pf2cgxlmac_map[pf], &cgx_id, &lmac_id);
cgx_lmac_promisc_config(cgx_id, lmac_id, true);
......@@ -695,6 +719,10 @@ int rvu_mbox_handler_cgx_promisc_disable(struct rvu *rvu, struct msg_req *req,
if (!is_cgx_config_permitted(rvu, req->hdr.pcifunc))
return -EPERM;
/* Disable drop on non hit rule */
if (rvu_npc_exact_has_match_table(rvu))
return rvu_npc_exact_promisc_disable(rvu, req->hdr.pcifunc);
rvu_get_cgx_lmac_id(rvu->pf2cgxlmac_map[pf], &cgx_id, &lmac_id);
cgx_lmac_promisc_config(cgx_id, lmac_id, false);
......@@ -1088,7 +1116,7 @@ int rvu_mbox_handler_cgx_set_link_mode(struct rvu *rvu,
return 0;
}
int rvu_mbox_handler_cgx_mac_addr_reset(struct rvu *rvu, struct msg_req *req,
int rvu_mbox_handler_cgx_mac_addr_reset(struct rvu *rvu, struct cgx_mac_addr_reset_req *req,
struct msg_rsp *rsp)
{
int pf = rvu_get_pf(req->hdr.pcifunc);
......@@ -1098,12 +1126,16 @@ int rvu_mbox_handler_cgx_mac_addr_reset(struct rvu *rvu, struct msg_req *req,
return LMAC_AF_ERR_PERM_DENIED;
rvu_get_cgx_lmac_id(rvu->pf2cgxlmac_map[pf], &cgx_id, &lmac_id);
if (rvu_npc_exact_has_match_table(rvu))
return rvu_npc_exact_mac_addr_reset(rvu, req, rsp);
return cgx_lmac_addr_reset(cgx_id, lmac_id);
}
int rvu_mbox_handler_cgx_mac_addr_update(struct rvu *rvu,
struct cgx_mac_addr_update_req *req,
struct msg_rsp *rsp)
struct cgx_mac_addr_update_rsp *rsp)
{
int pf = rvu_get_pf(req->hdr.pcifunc);
u8 cgx_id, lmac_id;
......@@ -1111,6 +1143,9 @@ int rvu_mbox_handler_cgx_mac_addr_update(struct rvu *rvu,
if (!is_cgx_config_permitted(rvu, req->hdr.pcifunc))
return LMAC_AF_ERR_PERM_DENIED;
if (rvu_npc_exact_has_match_table(rvu))
return rvu_npc_exact_mac_addr_update(rvu, req, rsp);
rvu_get_cgx_lmac_id(rvu->pf2cgxlmac_map[pf], &cgx_id, &lmac_id);
return cgx_lmac_addr_update(cgx_id, lmac_id, req->mac_addr, req->index);
}
......
......@@ -18,6 +18,7 @@
#include "cgx.h"
#include "lmac_common.h"
#include "npc.h"
#include "rvu_npc_hash.h"
#define DEBUGFS_DIR_NAME "octeontx2"
......@@ -2600,6 +2601,170 @@ static int rvu_dbg_npc_mcam_show_rules(struct seq_file *s, void *unused)
RVU_DEBUG_SEQ_FOPS(npc_mcam_rules, npc_mcam_show_rules, NULL);
static int rvu_dbg_npc_exact_show_entries(struct seq_file *s, void *unused)
{
struct npc_exact_table_entry *mem_entry[NPC_EXACT_TBL_MAX_WAYS] = { 0 };
struct npc_exact_table_entry *cam_entry;
struct npc_exact_table *table;
struct rvu *rvu = s->private;
int i, j;
u8 bitmap = 0;
table = rvu->hw->table;
mutex_lock(&table->lock);
/* Check if there is at least one entry in mem table */
if (!table->mem_tbl_entry_cnt)
goto dump_cam_table;
/* Print table headers */
seq_puts(s, "\n\tExact Match MEM Table\n");
seq_puts(s, "Index\t");
for (i = 0; i < table->mem_table.ways; i++) {
mem_entry[i] = list_first_entry_or_null(&table->lhead_mem_tbl_entry[i],
struct npc_exact_table_entry, list);
seq_printf(s, "Way-%d\t\t\t\t\t", i);
}
seq_puts(s, "\n");
for (i = 0; i < table->mem_table.ways; i++)
seq_puts(s, "\tChan MAC \t");
seq_puts(s, "\n\n");
/* Print mem table entries */
for (i = 0; i < table->mem_table.depth; i++) {
bitmap = 0;
for (j = 0; j < table->mem_table.ways; j++) {
if (!mem_entry[j])
continue;
if (mem_entry[j]->index != i)
continue;
bitmap |= BIT(j);
}
/* No valid entries */
if (!bitmap)
continue;
seq_printf(s, "%d\t", i);
for (j = 0; j < table->mem_table.ways; j++) {
if (!(bitmap & BIT(j))) {
seq_puts(s, "nil\t\t\t\t\t");
continue;
}
seq_printf(s, "0x%x %pM\t\t\t", mem_entry[j]->chan,
mem_entry[j]->mac);
mem_entry[j] = list_next_entry(mem_entry[j], list);
}
seq_puts(s, "\n");
}
dump_cam_table:
if (!table->cam_tbl_entry_cnt)
goto done;
seq_puts(s, "\n\tExact Match CAM Table\n");
seq_puts(s, "index\tchan\tMAC\n");
/* Traverse cam table entries */
list_for_each_entry(cam_entry, &table->lhead_cam_tbl_entry, list) {
seq_printf(s, "%d\t0x%x\t%pM\n", cam_entry->index, cam_entry->chan,
cam_entry->mac);
}
done:
mutex_unlock(&table->lock);
return 0;
}
RVU_DEBUG_SEQ_FOPS(npc_exact_entries, npc_exact_show_entries, NULL);
static int rvu_dbg_npc_exact_show_info(struct seq_file *s, void *unused)
{
struct npc_exact_table *table;
struct rvu *rvu = s->private;
int i;
table = rvu->hw->table;
seq_puts(s, "\n\tExact Table Info\n");
seq_printf(s, "Exact Match Feature : %s\n",
rvu->hw->cap.npc_exact_match_enabled ? "enabled" : "disable");
if (!rvu->hw->cap.npc_exact_match_enabled)
return 0;
seq_puts(s, "\nMCAM Index\tMAC Filter Rules Count\n");
for (i = 0; i < table->num_drop_rules; i++)
seq_printf(s, "%d\t\t%d\n", i, table->cnt_cmd_rules[i]);
seq_puts(s, "\nMcam Index\tPromisc Mode Status\n");
for (i = 0; i < table->num_drop_rules; i++)
seq_printf(s, "%d\t\t%s\n", i, table->promisc_mode[i] ? "on" : "off");
seq_puts(s, "\n\tMEM Table Info\n");
seq_printf(s, "Ways : %d\n", table->mem_table.ways);
seq_printf(s, "Depth : %d\n", table->mem_table.depth);
seq_printf(s, "Mask : 0x%llx\n", table->mem_table.mask);
seq_printf(s, "Hash Mask : 0x%x\n", table->mem_table.hash_mask);
seq_printf(s, "Hash Offset : 0x%x\n", table->mem_table.hash_offset);
seq_puts(s, "\n\tCAM Table Info\n");
seq_printf(s, "Depth : %d\n", table->cam_table.depth);
return 0;
}
RVU_DEBUG_SEQ_FOPS(npc_exact_info, npc_exact_show_info, NULL);
static int rvu_dbg_npc_exact_drop_cnt(struct seq_file *s, void *unused)
{
struct npc_exact_table *table;
struct rvu *rvu = s->private;
struct npc_key_field *field;
u16 chan, pcifunc;
int blkaddr, i;
u64 cfg, cam1;
char *str;
blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NPC, 0);
table = rvu->hw->table;
field = &rvu->hw->mcam.rx_key_fields[NPC_CHAN];
seq_puts(s, "\n\t Exact Hit on drop status\n");
seq_puts(s, "\npcifunc\tmcam_idx\tHits\tchan\tstatus\n");
for (i = 0; i < table->num_drop_rules; i++) {
pcifunc = rvu_npc_exact_drop_rule_to_pcifunc(rvu, i);
cfg = rvu_read64(rvu, blkaddr, NPC_AF_MCAMEX_BANKX_CFG(i, 0));
/* channel will be always in keyword 0 */
cam1 = rvu_read64(rvu, blkaddr,
NPC_AF_MCAMEX_BANKX_CAMX_W0(i, 0, 1));
chan = field->kw_mask[0] & cam1;
str = (cfg & 1) ? "enabled" : "disabled";
seq_printf(s, "0x%x\t%d\t\t%llu\t0x%x\t%s\n", pcifunc, i,
rvu_read64(rvu, blkaddr,
NPC_AF_MATCH_STATX(table->counter_idx[i])),
chan, str);
}
return 0;
}
RVU_DEBUG_SEQ_FOPS(npc_exact_drop_cnt, npc_exact_drop_cnt, NULL);
static void rvu_dbg_npc_init(struct rvu *rvu)
{
rvu->rvu_dbg.npc = debugfs_create_dir("npc", rvu->rvu_dbg.root);
......@@ -2608,8 +2773,22 @@ static void rvu_dbg_npc_init(struct rvu *rvu)
&rvu_dbg_npc_mcam_info_fops);
debugfs_create_file("mcam_rules", 0444, rvu->rvu_dbg.npc, rvu,
&rvu_dbg_npc_mcam_rules_fops);
debugfs_create_file("rx_miss_act_stats", 0444, rvu->rvu_dbg.npc, rvu,
&rvu_dbg_npc_rx_miss_act_fops);
if (!rvu->hw->cap.npc_exact_match_enabled)
return;
debugfs_create_file("exact_entries", 0444, rvu->rvu_dbg.npc, rvu,
&rvu_dbg_npc_exact_entries_fops);
debugfs_create_file("exact_info", 0444, rvu->rvu_dbg.npc, rvu,
&rvu_dbg_npc_exact_info_fops);
debugfs_create_file("exact_drop_cnt", 0444, rvu->rvu_dbg.npc, rvu,
&rvu_dbg_npc_exact_drop_cnt_fops);
}
static int cpt_eng_sts_display(struct seq_file *filp, u8 eng_type)
......
......@@ -10,6 +10,7 @@
#include "rvu.h"
#include "rvu_reg.h"
#include "rvu_struct.h"
#include "rvu_npc_hash.h"
#define DRV_NAME "octeontx2-af"
......@@ -1436,14 +1437,75 @@ static int rvu_af_dl_dwrr_mtu_get(struct devlink *devlink, u32 id,
enum rvu_af_dl_param_id {
RVU_AF_DEVLINK_PARAM_ID_BASE = DEVLINK_PARAM_GENERIC_ID_MAX,
RVU_AF_DEVLINK_PARAM_ID_DWRR_MTU,
RVU_AF_DEVLINK_PARAM_ID_NPC_EXACT_FEATURE_DISABLE,
};
static int rvu_af_npc_exact_feature_get(struct devlink *devlink, u32 id,
struct devlink_param_gset_ctx *ctx)
{
struct rvu_devlink *rvu_dl = devlink_priv(devlink);
struct rvu *rvu = rvu_dl->rvu;
bool enabled;
enabled = rvu_npc_exact_has_match_table(rvu);
snprintf(ctx->val.vstr, sizeof(ctx->val.vstr), "%s",
enabled ? "enabled" : "disabled");
return 0;
}
static int rvu_af_npc_exact_feature_disable(struct devlink *devlink, u32 id,
struct devlink_param_gset_ctx *ctx)
{
struct rvu_devlink *rvu_dl = devlink_priv(devlink);
struct rvu *rvu = rvu_dl->rvu;
rvu_npc_exact_disable_feature(rvu);
return 0;
}
static int rvu_af_npc_exact_feature_validate(struct devlink *devlink, u32 id,
union devlink_param_value val,
struct netlink_ext_ack *extack)
{
struct rvu_devlink *rvu_dl = devlink_priv(devlink);
struct rvu *rvu = rvu_dl->rvu;
u64 enable;
if (kstrtoull(val.vstr, 10, &enable)) {
NL_SET_ERR_MSG_MOD(extack,
"Only 1 value is supported");
return -EINVAL;
}
if (enable != 1) {
NL_SET_ERR_MSG_MOD(extack,
"Only disabling exact match feature is supported");
return -EINVAL;
}
if (rvu_npc_exact_can_disable_feature(rvu))
return 0;
NL_SET_ERR_MSG_MOD(extack,
"Can't disable exact match feature; Please try before any configuration");
return -EFAULT;
}
static const struct devlink_param rvu_af_dl_params[] = {
DEVLINK_PARAM_DRIVER(RVU_AF_DEVLINK_PARAM_ID_DWRR_MTU,
"dwrr_mtu", DEVLINK_PARAM_TYPE_U32,
BIT(DEVLINK_PARAM_CMODE_RUNTIME),
rvu_af_dl_dwrr_mtu_get, rvu_af_dl_dwrr_mtu_set,
rvu_af_dl_dwrr_mtu_validate),
DEVLINK_PARAM_DRIVER(RVU_AF_DEVLINK_PARAM_ID_NPC_EXACT_FEATURE_DISABLE,
"npc_exact_feature_disable", DEVLINK_PARAM_TYPE_STRING,
BIT(DEVLINK_PARAM_CMODE_RUNTIME),
rvu_af_npc_exact_feature_get,
rvu_af_npc_exact_feature_disable,
rvu_af_npc_exact_feature_validate),
};
/* Devlink switch mode */
......@@ -1501,6 +1563,7 @@ int rvu_register_dl(struct rvu *rvu)
{
struct rvu_devlink *rvu_dl;
struct devlink *dl;
size_t size;
int err;
dl = devlink_alloc(&rvu_devlink_ops, sizeof(struct rvu_devlink),
......@@ -1522,8 +1585,12 @@ int rvu_register_dl(struct rvu *rvu)
goto err_dl_health;
}
err = devlink_params_register(dl, rvu_af_dl_params,
ARRAY_SIZE(rvu_af_dl_params));
/* Register exact match devlink only for CN10K-B */
size = ARRAY_SIZE(rvu_af_dl_params);
if (!rvu_npc_exact_has_match_table(rvu))
size -= 1;
err = devlink_params_register(dl, rvu_af_dl_params, size);
if (err) {
dev_err(rvu->dev,
"devlink params register failed with error %d", err);
......
......@@ -14,6 +14,7 @@
#include "npc.h"
#include "cgx.h"
#include "lmac_common.h"
#include "rvu_npc_hash.h"
static void nix_free_tx_vtag_entries(struct rvu *rvu, u16 pcifunc);
static int rvu_nix_get_bpid(struct rvu *rvu, struct nix_bp_cfg_req *req,
......@@ -3792,9 +3793,15 @@ int rvu_mbox_handler_nix_set_rx_mode(struct rvu *rvu, struct nix_rx_mode *req,
rvu_npc_install_promisc_entry(rvu, pcifunc, nixlf,
pfvf->rx_chan_base,
pfvf->rx_chan_cnt);
if (rvu_npc_exact_has_match_table(rvu))
rvu_npc_exact_promisc_enable(rvu, pcifunc);
} else {
if (!nix_rx_multicast)
rvu_npc_enable_promisc_entry(rvu, pcifunc, nixlf, false);
if (rvu_npc_exact_has_match_table(rvu))
rvu_npc_exact_promisc_disable(rvu, pcifunc);
}
return 0;
......
......@@ -15,6 +15,7 @@
#include "npc.h"
#include "cgx.h"
#include "npc_profile.h"
#include "rvu_npc_hash.h"
#define RSVD_MCAM_ENTRIES_PER_PF 3 /* Broadcast, Promisc and AllMulticast */
#define RSVD_MCAM_ENTRIES_PER_NIXLF 1 /* Ucast for LFs */
......@@ -1105,6 +1106,34 @@ void rvu_npc_disable_default_entries(struct rvu *rvu, u16 pcifunc, int nixlf)
NIXLF_PROMISC_ENTRY, false);
}
bool rvu_npc_enable_mcam_by_entry_index(struct rvu *rvu, int entry, int intf, bool enable)
{
int blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NPC, 0);
struct npc_mcam *mcam = &rvu->hw->mcam;
struct rvu_npc_mcam_rule *rule, *tmp;
mutex_lock(&mcam->lock);
list_for_each_entry_safe(rule, tmp, &mcam->mcam_rules, list) {
if (rule->intf != intf)
continue;
if (rule->entry != entry)
continue;
rule->enable = enable;
mutex_unlock(&mcam->lock);
npc_enable_mcam_entry(rvu, mcam, blkaddr,
entry, enable);
return true;
}
mutex_unlock(&mcam->lock);
return false;
}
void rvu_npc_enable_default_entries(struct rvu *rvu, u16 pcifunc, int nixlf)
{
/* Enables only broadcast match entry. Promisc/Allmulti are enabled
......@@ -1181,14 +1210,6 @@ void rvu_npc_free_mcam_entries(struct rvu *rvu, u16 pcifunc, int nixlf)
rvu_npc_disable_default_entries(rvu, pcifunc, nixlf);
}
#define SET_KEX_LD(intf, lid, ltype, ld, cfg) \
rvu_write64(rvu, blkaddr, \
NPC_AF_INTFX_LIDX_LTX_LDX_CFG(intf, lid, ltype, ld), cfg)
#define SET_KEX_LDFLAGS(intf, ld, flags, cfg) \
rvu_write64(rvu, blkaddr, \
NPC_AF_INTFX_LDATAX_FLAGSX_CFG(intf, ld, flags), cfg)
static void npc_program_mkex_rx(struct rvu *rvu, int blkaddr,
struct npc_mcam_kex *mkex, u8 intf)
{
......@@ -1262,6 +1283,9 @@ static void npc_program_mkex_profile(struct rvu *rvu, int blkaddr,
npc_program_mkex_rx(rvu, blkaddr, mkex, intf);
npc_program_mkex_tx(rvu, blkaddr, mkex, intf);
}
/* Programme mkex hash profile */
npc_program_mkex_hash(rvu, blkaddr);
}
static int npc_fwdb_prfl_img_map(struct rvu *rvu, void __iomem **prfl_img_addr,
......@@ -1463,6 +1487,7 @@ static int npc_prepare_default_kpu(struct npc_kpu_profile_adapter *profile)
profile->kpus = ARRAY_SIZE(npc_kpu_profiles);
profile->lt_def = &npc_lt_defaults;
profile->mkex = &npc_mkex_default;
profile->mkex_hash = &npc_mkex_hash_default;
return 0;
}
......@@ -1819,7 +1844,6 @@ static int npc_mcam_rsrcs_init(struct rvu *rvu, int blkaddr)
mcam->hprio_count = mcam->lprio_count;
mcam->hprio_end = mcam->hprio_count;
/* Allocate bitmap for managing MCAM counters and memory
* for saving counter to RVU PFFUNC allocation mapping.
*/
......@@ -2047,6 +2071,7 @@ int rvu_npc_init(struct rvu *rvu)
rvu_npc_setup_interfaces(rvu, blkaddr);
npc_config_secret_key(rvu, blkaddr);
/* Configure MKEX profile */
npc_load_mkex_profile(rvu, blkaddr, rvu->mkex_pfl_name);
......@@ -2562,6 +2587,14 @@ static int npc_mcam_alloc_entries(struct npc_mcam *mcam, u16 pcifunc,
return 0;
}
/* Marks bitmaps to reserved the mcam slot */
void npc_mcam_rsrcs_reserve(struct rvu *rvu, int blkaddr, int entry_idx)
{
struct npc_mcam *mcam = &rvu->hw->mcam;
npc_mcam_set_bit(mcam, entry_idx);
}
int rvu_mbox_handler_npc_mcam_alloc_entry(struct rvu *rvu,
struct npc_mcam_alloc_entry_req *req,
struct npc_mcam_alloc_entry_rsp *rsp)
......
......@@ -10,6 +10,9 @@
#include "rvu_reg.h"
#include "rvu.h"
#include "npc.h"
#include "rvu_npc_fs.h"
#include "npc_profile.h"
#include "rvu_npc_hash.h"
#define NPC_BYTESM GENMASK_ULL(19, 16)
#define NPC_HDR_OFFSET GENMASK_ULL(15, 8)
......@@ -227,6 +230,25 @@ static bool npc_check_field(struct rvu *rvu, int blkaddr, enum key_fields type,
return true;
}
static void npc_scan_exact_result(struct npc_mcam *mcam, u8 bit_number,
u8 key_nibble, u8 intf)
{
u8 offset = (key_nibble * 4) % 64; /* offset within key word */
u8 kwi = (key_nibble * 4) / 64; /* which word in key */
u8 nr_bits = 4; /* bits in a nibble */
u8 type;
switch (bit_number) {
case 40 ... 43:
type = NPC_EXACT_RESULT;
break;
default:
return;
}
npc_set_kw_masks(mcam, type, nr_bits, kwi, offset, intf);
}
static void npc_scan_parse_result(struct npc_mcam *mcam, u8 bit_number,
u8 key_nibble, u8 intf)
{
......@@ -276,6 +298,7 @@ static void npc_scan_parse_result(struct npc_mcam *mcam, u8 bit_number,
default:
return;
}
npc_set_kw_masks(mcam, type, nr_bits, kwi, offset, intf);
}
......@@ -509,8 +532,8 @@ static int npc_scan_kex(struct rvu *rvu, int blkaddr, u8 intf)
{
struct npc_mcam *mcam = &rvu->hw->mcam;
u8 lid, lt, ld, bitnr;
u64 cfg, masked_cfg;
u8 key_nibble = 0;
u64 cfg;
/* Scan and note how parse result is going to be in key.
* A bit set in PARSE_NIBBLE_ENA corresponds to a nibble from
......@@ -518,12 +541,24 @@ static int npc_scan_kex(struct rvu *rvu, int blkaddr, u8 intf)
* will be concatenated in key.
*/
cfg = rvu_read64(rvu, blkaddr, NPC_AF_INTFX_KEX_CFG(intf));
cfg &= NPC_PARSE_NIBBLE;
for_each_set_bit(bitnr, (unsigned long *)&cfg, 31) {
masked_cfg = cfg & NPC_PARSE_NIBBLE;
for_each_set_bit(bitnr, (unsigned long *)&masked_cfg, 31) {
npc_scan_parse_result(mcam, bitnr, key_nibble, intf);
key_nibble++;
}
/* Ignore exact match bits for mcam entries except the first rule
* which is drop on hit. This first rule is configured explitcitly by
* exact match code.
*/
masked_cfg = cfg & NPC_EXACT_NIBBLE;
bitnr = NPC_EXACT_NIBBLE_START;
for_each_set_bit_from(bitnr, (unsigned long *)&masked_cfg,
NPC_EXACT_NIBBLE_START) {
npc_scan_exact_result(mcam, bitnr, key_nibble, intf);
key_nibble++;
}
/* Scan and note how layer data is going to be in key */
for (lid = 0; lid < NPC_MAX_LID; lid++) {
for (lt = 0; lt < NPC_MAX_LT; lt++) {
......@@ -624,9 +659,9 @@ static int npc_check_unsupported_flows(struct rvu *rvu, u64 features, u8 intf)
* If any bits in mask are 0 then corresponding bits in value are
* dont care.
*/
static void npc_update_entry(struct rvu *rvu, enum key_fields type,
struct mcam_entry *entry, u64 val_lo,
u64 val_hi, u64 mask_lo, u64 mask_hi, u8 intf)
void npc_update_entry(struct rvu *rvu, enum key_fields type,
struct mcam_entry *entry, u64 val_lo,
u64 val_hi, u64 mask_lo, u64 mask_hi, u8 intf)
{
struct npc_mcam *mcam = &rvu->hw->mcam;
struct mcam_entry dummy = { {0} };
......@@ -705,8 +740,6 @@ static void npc_update_entry(struct rvu *rvu, enum key_fields type,
}
}
#define IPV6_WORDS 4
static void npc_update_ipv6_flow(struct rvu *rvu, struct mcam_entry *entry,
u64 features, struct flow_msg *pkt,
struct flow_msg *mask,
......@@ -779,7 +812,8 @@ static void npc_update_vlan_features(struct rvu *rvu, struct mcam_entry *entry,
static void npc_update_flow(struct rvu *rvu, struct mcam_entry *entry,
u64 features, struct flow_msg *pkt,
struct flow_msg *mask,
struct rvu_npc_mcam_rule *output, u8 intf)
struct rvu_npc_mcam_rule *output, u8 intf,
int blkaddr)
{
u64 dmac_mask = ether_addr_to_u64(mask->dmac);
u64 smac_mask = ether_addr_to_u64(mask->smac);
......@@ -828,6 +862,7 @@ do { \
} while (0)
NPC_WRITE_FLOW(NPC_DMAC, dmac, dmac_val, 0, dmac_mask, 0);
NPC_WRITE_FLOW(NPC_SMAC, smac, smac_val, 0, smac_mask, 0);
NPC_WRITE_FLOW(NPC_ETYPE, etype, ntohs(pkt->etype), 0,
ntohs(mask->etype), 0);
......@@ -854,10 +889,12 @@ do { \
npc_update_ipv6_flow(rvu, entry, features, pkt, mask, output, intf);
npc_update_vlan_features(rvu, entry, features, intf);
npc_update_field_hash(rvu, intf, entry, blkaddr, features,
pkt, mask, opkt, omask);
}
static struct rvu_npc_mcam_rule *rvu_mcam_find_rule(struct npc_mcam *mcam,
u16 entry)
static struct rvu_npc_mcam_rule *rvu_mcam_find_rule(struct npc_mcam *mcam, u16 entry)
{
struct rvu_npc_mcam_rule *iter;
......@@ -1023,8 +1060,9 @@ static int npc_install_flow(struct rvu *rvu, int blkaddr, u16 target,
u16 owner = req->hdr.pcifunc;
struct msg_rsp write_rsp;
struct mcam_entry *entry;
int entry_index, err;
bool new = false;
u16 entry_index;
int err;
installed_features = req->features;
features = req->features;
......@@ -1032,7 +1070,7 @@ static int npc_install_flow(struct rvu *rvu, int blkaddr, u16 target,
entry_index = req->entry;
npc_update_flow(rvu, entry, features, &req->packet, &req->mask, &dummy,
req->intf);
req->intf, blkaddr);
if (is_npc_intf_rx(req->intf))
npc_update_rx_entry(rvu, pfvf, entry, req, target, pf_set_vfs_mac);
......@@ -1057,7 +1095,8 @@ static int npc_install_flow(struct rvu *rvu, int blkaddr, u16 target,
npc_update_flow(rvu, entry, missing_features,
&def_ucast_rule->packet,
&def_ucast_rule->mask,
&dummy, req->intf);
&dummy, req->intf,
blkaddr);
installed_features = req->features | missing_features;
}
......@@ -1424,3 +1463,98 @@ void npc_mcam_disable_flows(struct rvu *rvu, u16 target)
}
mutex_unlock(&mcam->lock);
}
/* single drop on non hit rule starting from 0th index. This an extension
* to RPM mac filter to support more rules.
*/
int npc_install_mcam_drop_rule(struct rvu *rvu, int mcam_idx, u16 *counter_idx,
u64 chan_val, u64 chan_mask, u64 exact_val, u64 exact_mask,
u64 bcast_mcast_val, u64 bcast_mcast_mask)
{
struct npc_mcam_alloc_counter_req cntr_req = { 0 };
struct npc_mcam_alloc_counter_rsp cntr_rsp = { 0 };
struct npc_mcam_write_entry_req req = { 0 };
struct npc_mcam *mcam = &rvu->hw->mcam;
struct rvu_npc_mcam_rule *rule;
struct msg_rsp rsp;
bool enabled;
int blkaddr;
int err;
blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NPC, 0);
if (blkaddr < 0) {
dev_err(rvu->dev, "%s: NPC block not implemented\n", __func__);
return -ENODEV;
}
/* Bail out if no exact match support */
if (!rvu_npc_exact_has_match_table(rvu)) {
dev_info(rvu->dev, "%s: No support for exact match feature\n", __func__);
return -EINVAL;
}
/* If 0th entry is already used, return err */
enabled = is_mcam_entry_enabled(rvu, mcam, blkaddr, mcam_idx);
if (enabled) {
dev_err(rvu->dev, "%s: failed to add single drop on non hit rule at %d th index\n",
__func__, mcam_idx);
return -EINVAL;
}
/* Add this entry to mcam rules list */
rule = kzalloc(sizeof(*rule), GFP_KERNEL);
if (!rule)
return -ENOMEM;
/* Disable rule by default. Enable rule when first dmac filter is
* installed
*/
rule->enable = false;
rule->chan = chan_val;
rule->chan_mask = chan_mask;
rule->entry = mcam_idx;
rvu_mcam_add_rule(mcam, rule);
/* Reserve slot 0 */
npc_mcam_rsrcs_reserve(rvu, blkaddr, mcam_idx);
/* Allocate counter for this single drop on non hit rule */
cntr_req.hdr.pcifunc = 0; /* AF request */
cntr_req.contig = true;
cntr_req.count = 1;
err = rvu_mbox_handler_npc_mcam_alloc_counter(rvu, &cntr_req, &cntr_rsp);
if (err) {
dev_err(rvu->dev, "%s: Err to allocate cntr for drop rule (err=%d)\n",
__func__, err);
return -EFAULT;
}
*counter_idx = cntr_rsp.cntr;
/* Fill in fields for this mcam entry */
npc_update_entry(rvu, NPC_EXACT_RESULT, &req.entry_data, exact_val, 0,
exact_mask, 0, NIX_INTF_RX);
npc_update_entry(rvu, NPC_CHAN, &req.entry_data, chan_val, 0,
chan_mask, 0, NIX_INTF_RX);
npc_update_entry(rvu, NPC_LXMB, &req.entry_data, bcast_mcast_val, 0,
bcast_mcast_mask, 0, NIX_INTF_RX);
req.intf = NIX_INTF_RX;
req.set_cntr = true;
req.cntr = cntr_rsp.cntr;
req.entry = mcam_idx;
err = rvu_mbox_handler_npc_mcam_write_entry(rvu, &req, &rsp);
if (err) {
dev_err(rvu->dev, "%s: Installation of single drop on non hit rule at %d failed\n",
__func__, mcam_idx);
return err;
}
dev_err(rvu->dev, "%s: Installed single drop on non hit rule at %d, cntr=%d\n",
__func__, mcam_idx, req.cntr);
/* disable entry at Bank 0, index 0 */
npc_enable_mcam_entry(rvu, mcam, blkaddr, mcam_idx, false);
return 0;
}
/* SPDX-License-Identifier: GPL-2.0 */
/* Marvell RVU Admin Function driver
*
* Copyright (C) 2022 Marvell.
*
*/
#ifndef __RVU_NPC_FS_H
#define __RVU_NPC_FS_H
#define IPV6_WORDS 4
void npc_update_entry(struct rvu *rvu, enum key_fields type,
struct mcam_entry *entry, u64 val_lo,
u64 val_hi, u64 mask_lo, u64 mask_hi, u8 intf);
#endif /* RVU_NPC_FS_H */
This diff is collapsed.
/* SPDX-License-Identifier: GPL-2.0 */
/* Marvell RVU Admin Function driver
*
* Copyright (C) 2022 Marvell.
*
*/
#ifndef __RVU_NPC_HASH_H
#define __RVU_NPC_HASH_H
#define RVU_NPC_HASH_SECRET_KEY0 0xa9d5af4c9fbc76b1
#define RVU_NPC_HASH_SECRET_KEY1 0xa9d5af4c9fbc87b4
#define RVU_NPC_HASH_SECRET_KEY2 0x5954c9e7
#define NPC_MAX_HASH 2
#define NPC_MAX_HASH_MASK 2
#define KEX_LD_CFG_USE_HASH(use_hash, bytesm1, hdr_ofs, ena, flags_ena, key_ofs) \
((use_hash) << 20 | ((bytesm1) << 16) | ((hdr_ofs) << 8) | \
((ena) << 7) | ((flags_ena) << 6) | ((key_ofs) & 0x3F))
#define KEX_LD_CFG_HASH(hdr_ofs, bytesm1, lt_en, lid_en, lid, ltype_match, ltype_mask) \
(((hdr_ofs) << 32) | ((bytesm1) << 16) | \
((lt_en) << 12) | ((lid_en) << 11) | ((lid) << 8) | \
((ltype_match) << 4) | ((ltype_mask) & 0xF))
#define SET_KEX_LD_HASH(intf, ld, cfg) \
rvu_write64(rvu, blkaddr, \
NPC_AF_INTFX_HASHX_CFG(intf, ld), cfg)
#define SET_KEX_LD_HASH_MASK(intf, ld, mask_idx, cfg) \
rvu_write64(rvu, blkaddr, \
NPC_AF_INTFX_HASHX_MASKX(intf, ld, mask_idx), cfg)
#define SET_KEX_LD_HASH_CTRL(intf, ld, cfg) \
rvu_write64(rvu, blkaddr, \
NPC_AF_INTFX_HASHX_RESULT_CTRL(intf, ld), cfg)
struct npc_mcam_kex_hash {
/* NPC_AF_INTF(0..1)_LID(0..7)_LT(0..15)_LD(0..1)_CFG */
bool lid_lt_ld_hash_en[NPC_MAX_INTF][NPC_MAX_LID][NPC_MAX_LT][NPC_MAX_LD];
/* NPC_AF_INTF(0..1)_HASH(0..1)_CFG */
u64 hash[NPC_MAX_INTF][NPC_MAX_HASH];
/* NPC_AF_INTF(0..1)_HASH(0..1)_MASK(0..1) */
u64 hash_mask[NPC_MAX_INTF][NPC_MAX_HASH][NPC_MAX_HASH_MASK];
/* NPC_AF_INTF(0..1)_HASH(0..1)_RESULT_CTRL */
u64 hash_ctrl[NPC_MAX_INTF][NPC_MAX_HASH];
} __packed;
void npc_update_field_hash(struct rvu *rvu, u8 intf,
struct mcam_entry *entry,
int blkaddr,
u64 features,
struct flow_msg *pkt,
struct flow_msg *mask,
struct flow_msg *opkt,
struct flow_msg *omask);
void npc_config_secret_key(struct rvu *rvu, int blkaddr);
void npc_program_mkex_hash(struct rvu *rvu, int blkaddr);
u32 npc_field_hash_calc(u64 *ldata, struct npc_mcam_kex_hash *mkex_hash,
u64 *secret_key, u8 intf, u8 hash_idx);
static struct npc_mcam_kex_hash npc_mkex_hash_default __maybe_unused = {
.lid_lt_ld_hash_en = {
[NIX_INTF_RX] = {
[NPC_LID_LC] = {
[NPC_LT_LC_IP6] = {
true,
true,
},
},
},
[NIX_INTF_TX] = {
[NPC_LID_LC] = {
[NPC_LT_LC_IP6] = {
true,
true,
},
},
},
},
.hash = {
[NIX_INTF_RX] = {
KEX_LD_CFG_HASH(0x8ULL, 0xf, 0x1, 0x1, NPC_LID_LC, NPC_LT_LC_IP6, 0xf),
KEX_LD_CFG_HASH(0x18ULL, 0xf, 0x1, 0x1, NPC_LID_LC, NPC_LT_LC_IP6, 0xf),
},
[NIX_INTF_TX] = {
KEX_LD_CFG_HASH(0x8ULL, 0xf, 0x1, 0x1, NPC_LID_LC, NPC_LT_LC_IP6, 0xf),
KEX_LD_CFG_HASH(0x18ULL, 0xf, 0x1, 0x1, NPC_LID_LC, NPC_LT_LC_IP6, 0xf),
},
},
.hash_mask = {
[NIX_INTF_RX] = {
[0] = {
GENMASK_ULL(63, 0),
GENMASK_ULL(63, 0),
},
[1] = {
GENMASK_ULL(63, 0),
GENMASK_ULL(63, 0),
},
},
[NIX_INTF_TX] = {
[0] = {
GENMASK_ULL(63, 0),
GENMASK_ULL(63, 0),
},
[1] = {
GENMASK_ULL(63, 0),
GENMASK_ULL(63, 0),
},
},
},
.hash_ctrl = {
[NIX_INTF_RX] = {
[0] = GENMASK_ULL(63, 32), /* MSB 32 bit is mask and LSB 32 bit is offset. */
[1] = GENMASK_ULL(63, 32), /* MSB 32 bit is mask and LSB 32 bit is offset. */
},
[NIX_INTF_TX] = {
[0] = GENMASK_ULL(63, 32), /* MSB 32 bit is mask and LSB 32 bit is offset. */
[1] = GENMASK_ULL(63, 32), /* MSB 32 bit is mask and LSB 32 bit is offset. */
},
},
};
/* If exact match table support is enabled, enable drop rules */
#define NPC_MCAM_DROP_RULE_MAX 30
#define NPC_MCAM_SDP_DROP_RULE_IDX 0
#define RVU_PFFUNC(pf, func) \
((((pf) & RVU_PFVF_PF_MASK) << RVU_PFVF_PF_SHIFT) | \
(((func) & RVU_PFVF_FUNC_MASK) << RVU_PFVF_FUNC_SHIFT))
enum npc_exact_opc_type {
NPC_EXACT_OPC_MEM,
NPC_EXACT_OPC_CAM,
};
struct npc_exact_table_entry {
struct list_head list;
struct list_head glist;
u32 seq_id; /* Sequence number of entry */
u32 index; /* Mem table or cam table index */
u32 mcam_idx;
/* Mcam index. This is valid only if "cmd" field is false */
enum npc_exact_opc_type opc_type;
u16 chan;
u16 pcifunc;
u8 ways;
u8 mac[ETH_ALEN];
u8 ctype;
u8 cgx_id;
u8 lmac_id;
bool cmd; /* Is added by ethtool command ? */
};
struct npc_exact_table {
struct mutex lock; /* entries update lock */
unsigned long *id_bmap;
int num_drop_rules;
u32 tot_ids;
u16 cnt_cmd_rules[NPC_MCAM_DROP_RULE_MAX];
u16 counter_idx[NPC_MCAM_DROP_RULE_MAX];
bool promisc_mode[NPC_MCAM_DROP_RULE_MAX];
struct {
int ways;
int depth;
unsigned long *bmap;
u64 mask; // Masks before hash calculation.
u16 hash_mask; // 11 bits for hash mask
u16 hash_offset; // 11 bits offset
} mem_table;
struct {
int depth;
unsigned long *bmap;
} cam_table;
struct {
bool valid;
u16 chan_val;
u16 chan_mask;
u16 pcifunc;
u8 drop_rule_idx;
} drop_rule_map[NPC_MCAM_DROP_RULE_MAX];
#define NPC_EXACT_TBL_MAX_WAYS 4
struct list_head lhead_mem_tbl_entry[NPC_EXACT_TBL_MAX_WAYS];
int mem_tbl_entry_cnt;
struct list_head lhead_cam_tbl_entry;
int cam_tbl_entry_cnt;
struct list_head lhead_gbl;
};
bool rvu_npc_exact_has_match_table(struct rvu *rvu);
u32 rvu_npc_exact_get_max_entries(struct rvu *rvu);
int rvu_npc_exact_init(struct rvu *rvu);
int rvu_npc_exact_mac_addr_reset(struct rvu *rvu, struct cgx_mac_addr_reset_req *req,
struct msg_rsp *rsp);
int rvu_npc_exact_mac_addr_update(struct rvu *rvu,
struct cgx_mac_addr_update_req *req,
struct cgx_mac_addr_update_rsp *rsp);
int rvu_npc_exact_mac_addr_add(struct rvu *rvu,
struct cgx_mac_addr_add_req *req,
struct cgx_mac_addr_add_rsp *rsp);
int rvu_npc_exact_mac_addr_del(struct rvu *rvu,
struct cgx_mac_addr_del_req *req,
struct msg_rsp *rsp);
int rvu_npc_exact_mac_addr_set(struct rvu *rvu, struct cgx_mac_addr_set_or_get *req,
struct cgx_mac_addr_set_or_get *rsp);
void rvu_npc_exact_reset(struct rvu *rvu, u16 pcifunc);
bool rvu_npc_exact_can_disable_feature(struct rvu *rvu);
void rvu_npc_exact_disable_feature(struct rvu *rvu);
void rvu_npc_exact_reset(struct rvu *rvu, u16 pcifunc);
u16 rvu_npc_exact_drop_rule_to_pcifunc(struct rvu *rvu, u32 drop_rule_idx);
int rvu_npc_exact_promisc_disable(struct rvu *rvu, u16 pcifunc);
int rvu_npc_exact_promisc_enable(struct rvu *rvu, u16 pcifunc);
#endif /* RVU_NPC_HASH_H */
......@@ -565,7 +565,13 @@
#define NPC_AF_PCK_DEF_OIP4 (0x00620)
#define NPC_AF_PCK_DEF_OIP6 (0x00630)
#define NPC_AF_PCK_DEF_IIP4 (0x00640)
#define NPC_AF_INTFX_HASHX_RESULT_CTRL(a, b) (0x006c0 | (a) << 4 | (b) << 3)
#define NPC_AF_INTFX_HASHX_MASKX(a, b, c) (0x00700 | (a) << 5 | (b) << 4 | (c) << 3)
#define NPC_AF_KEX_LDATAX_FLAGS_CFG(a) (0x00800 | (a) << 3)
#define NPC_AF_INTFX_HASHX_CFG(a, b) (0x00b00 | (a) << 6 | (b) << 4)
#define NPC_AF_INTFX_SECRET_KEY0(a) (0x00e00 | (a) << 3)
#define NPC_AF_INTFX_SECRET_KEY1(a) (0x00e20 | (a) << 3)
#define NPC_AF_INTFX_SECRET_KEY2(a) (0x00e40 | (a) << 3)
#define NPC_AF_INTFX_KEX_CFG(a) (0x01010 | (a) << 8)
#define NPC_AF_PKINDX_ACTION0(a) (0x80000ull | (a) << 6)
#define NPC_AF_PKINDX_ACTION1(a) (0x80008ull | (a) << 6)
......@@ -599,6 +605,15 @@
#define NPC_AF_DBG_DATAX(a) (0x3001400 | (a) << 4)
#define NPC_AF_DBG_RESULTX(a) (0x3001800 | (a) << 4)
#define NPC_AF_EXACT_MEM_ENTRY(a, b) (0x300000 | (a) << 15 | (b) << 3)
#define NPC_AF_EXACT_CAM_ENTRY(a) (0xC00 | (a) << 3)
#define NPC_AF_INTFX_EXACT_MASK(a) (0x660 | (a) << 3)
#define NPC_AF_INTFX_EXACT_RESULT_CTL(a)(0x680 | (a) << 3)
#define NPC_AF_INTFX_EXACT_CFG(a) (0xA00 | (a) << 3)
#define NPC_AF_INTFX_EXACT_SECRET0(a) (0xE00 | (a) << 3)
#define NPC_AF_INTFX_EXACT_SECRET1(a) (0xE20 | (a) << 3)
#define NPC_AF_INTFX_EXACT_SECRET2(a) (0xE40 | (a) << 3)
#define NPC_AF_MCAMEX_BANKX_CAMX_INTF(a, b, c) ({ \
u64 offset; \
\
......
......@@ -314,8 +314,8 @@ struct otx2_flow_config {
#define OTX2_VF_VLAN_TX_INDEX 1
u16 max_flows;
u8 dmacflt_max_flows;
u8 *bmap_to_dmacindex;
unsigned long dmacflt_bmap;
u32 *bmap_to_dmacindex;
unsigned long *dmacflt_bmap;
struct list_head flow_list;
};
......@@ -895,9 +895,9 @@ int otx2_setup_tc(struct net_device *netdev, enum tc_setup_type type,
int otx2_tc_alloc_ent_bitmap(struct otx2_nic *nic);
/* CGX/RPM DMAC filters support */
int otx2_dmacflt_get_max_cnt(struct otx2_nic *pf);
int otx2_dmacflt_add(struct otx2_nic *pf, const u8 *mac, u8 bit_pos);
int otx2_dmacflt_remove(struct otx2_nic *pf, const u8 *mac, u8 bit_pos);
int otx2_dmacflt_update(struct otx2_nic *pf, u8 *mac, u8 bit_pos);
int otx2_dmacflt_add(struct otx2_nic *pf, const u8 *mac, u32 bit_pos);
int otx2_dmacflt_remove(struct otx2_nic *pf, const u8 *mac, u32 bit_pos);
int otx2_dmacflt_update(struct otx2_nic *pf, u8 *mac, u32 bit_pos);
void otx2_dmacflt_reinstall_flows(struct otx2_nic *pf);
void otx2_dmacflt_update_pfmac_flow(struct otx2_nic *pfvf);
......
......@@ -8,7 +8,7 @@
#include "otx2_common.h"
static int otx2_dmacflt_do_add(struct otx2_nic *pf, const u8 *mac,
u8 *dmac_index)
u32 *dmac_index)
{
struct cgx_mac_addr_add_req *req;
struct cgx_mac_addr_add_rsp *rsp;
......@@ -35,9 +35,10 @@ static int otx2_dmacflt_do_add(struct otx2_nic *pf, const u8 *mac,
return err;
}
static int otx2_dmacflt_add_pfmac(struct otx2_nic *pf)
static int otx2_dmacflt_add_pfmac(struct otx2_nic *pf, u32 *dmac_index)
{
struct cgx_mac_addr_set_or_get *req;
struct cgx_mac_addr_set_or_get *rsp;
int err;
mutex_lock(&pf->mbox.lock);
......@@ -48,16 +49,24 @@ static int otx2_dmacflt_add_pfmac(struct otx2_nic *pf)
return -ENOMEM;
}
req->index = *dmac_index;
ether_addr_copy(req->mac_addr, pf->netdev->dev_addr);
err = otx2_sync_mbox_msg(&pf->mbox);
if (!err) {
rsp = (struct cgx_mac_addr_set_or_get *)
otx2_mbox_get_rsp(&pf->mbox.mbox, 0, &req->hdr);
*dmac_index = rsp->index;
}
mutex_unlock(&pf->mbox.lock);
return err;
}
int otx2_dmacflt_add(struct otx2_nic *pf, const u8 *mac, u8 bit_pos)
int otx2_dmacflt_add(struct otx2_nic *pf, const u8 *mac, u32 bit_pos)
{
u8 *dmacindex;
u32 *dmacindex;
/* Store dmacindex returned by CGX/RPM driver which will
* be used for macaddr update/remove
......@@ -65,13 +74,13 @@ int otx2_dmacflt_add(struct otx2_nic *pf, const u8 *mac, u8 bit_pos)
dmacindex = &pf->flow_cfg->bmap_to_dmacindex[bit_pos];
if (ether_addr_equal(mac, pf->netdev->dev_addr))
return otx2_dmacflt_add_pfmac(pf);
return otx2_dmacflt_add_pfmac(pf, dmacindex);
else
return otx2_dmacflt_do_add(pf, mac, dmacindex);
}
static int otx2_dmacflt_do_remove(struct otx2_nic *pfvf, const u8 *mac,
u8 dmac_index)
u32 dmac_index)
{
struct cgx_mac_addr_del_req *req;
int err;
......@@ -91,9 +100,9 @@ static int otx2_dmacflt_do_remove(struct otx2_nic *pfvf, const u8 *mac,
return err;
}
static int otx2_dmacflt_remove_pfmac(struct otx2_nic *pf)
static int otx2_dmacflt_remove_pfmac(struct otx2_nic *pf, u32 dmac_index)
{
struct msg_req *req;
struct cgx_mac_addr_reset_req *req;
int err;
mutex_lock(&pf->mbox.lock);
......@@ -102,6 +111,7 @@ static int otx2_dmacflt_remove_pfmac(struct otx2_nic *pf)
mutex_unlock(&pf->mbox.lock);
return -ENOMEM;
}
req->index = dmac_index;
err = otx2_sync_mbox_msg(&pf->mbox);
......@@ -110,12 +120,12 @@ static int otx2_dmacflt_remove_pfmac(struct otx2_nic *pf)
}
int otx2_dmacflt_remove(struct otx2_nic *pf, const u8 *mac,
u8 bit_pos)
u32 bit_pos)
{
u8 dmacindex = pf->flow_cfg->bmap_to_dmacindex[bit_pos];
u32 dmacindex = pf->flow_cfg->bmap_to_dmacindex[bit_pos];
if (ether_addr_equal(mac, pf->netdev->dev_addr))
return otx2_dmacflt_remove_pfmac(pf);
return otx2_dmacflt_remove_pfmac(pf, dmacindex);
else
return otx2_dmacflt_do_remove(pf, mac, dmacindex);
}
......@@ -151,9 +161,10 @@ int otx2_dmacflt_get_max_cnt(struct otx2_nic *pf)
return err;
}
int otx2_dmacflt_update(struct otx2_nic *pf, u8 *mac, u8 bit_pos)
int otx2_dmacflt_update(struct otx2_nic *pf, u8 *mac, u32 bit_pos)
{
struct cgx_mac_addr_update_req *req;
struct cgx_mac_addr_update_rsp *rsp;
int rc;
mutex_lock(&pf->mbox.lock);
......@@ -167,8 +178,19 @@ int otx2_dmacflt_update(struct otx2_nic *pf, u8 *mac, u8 bit_pos)
ether_addr_copy(req->mac_addr, mac);
req->index = pf->flow_cfg->bmap_to_dmacindex[bit_pos];
/* check the response and change index */
rc = otx2_sync_mbox_msg(&pf->mbox);
if (rc)
goto out;
rsp = (struct cgx_mac_addr_update_rsp *)
otx2_mbox_get_rsp(&pf->mbox.mbox, 0, &req->hdr);
pf->flow_cfg->bmap_to_dmacindex[bit_pos] = rsp->index;
out:
mutex_unlock(&pf->mbox.lock);
return rc;
}
......@@ -18,7 +18,7 @@ struct otx2_flow {
struct ethtool_rx_flow_spec flow_spec;
struct list_head list;
u32 location;
u16 entry;
u32 entry;
bool is_vf;
u8 rss_ctx_id;
#define DMAC_FILTER_RULE BIT(0)
......@@ -232,6 +232,9 @@ static int otx2_mcam_entry_init(struct otx2_nic *pfvf)
return 0;
}
/* TODO : revisit on size */
#define OTX2_DMAC_FLTR_BITMAP_SZ (4 * 2048 + 32)
int otx2vf_mcam_flow_init(struct otx2_nic *pfvf)
{
struct otx2_flow_config *flow_cfg;
......@@ -242,6 +245,12 @@ int otx2vf_mcam_flow_init(struct otx2_nic *pfvf)
if (!pfvf->flow_cfg)
return -ENOMEM;
pfvf->flow_cfg->dmacflt_bmap = devm_kcalloc(pfvf->dev,
BITS_TO_LONGS(OTX2_DMAC_FLTR_BITMAP_SZ),
sizeof(long), GFP_KERNEL);
if (!pfvf->flow_cfg->dmacflt_bmap)
return -ENOMEM;
flow_cfg = pfvf->flow_cfg;
INIT_LIST_HEAD(&flow_cfg->flow_list);
flow_cfg->max_flows = 0;
......@@ -259,6 +268,12 @@ int otx2_mcam_flow_init(struct otx2_nic *pf)
if (!pf->flow_cfg)
return -ENOMEM;
pf->flow_cfg->dmacflt_bmap = devm_kcalloc(pf->dev,
BITS_TO_LONGS(OTX2_DMAC_FLTR_BITMAP_SZ),
sizeof(long), GFP_KERNEL);
if (!pf->flow_cfg->dmacflt_bmap)
return -ENOMEM;
INIT_LIST_HEAD(&pf->flow_cfg->flow_list);
/* Allocate bare minimum number of MCAM entries needed for
......@@ -284,7 +299,7 @@ int otx2_mcam_flow_init(struct otx2_nic *pf)
return 0;
pf->flow_cfg->bmap_to_dmacindex =
devm_kzalloc(pf->dev, sizeof(u8) *
devm_kzalloc(pf->dev, sizeof(u32) *
pf->flow_cfg->dmacflt_max_flows,
GFP_KERNEL);
......@@ -355,7 +370,7 @@ int otx2_add_macfilter(struct net_device *netdev, const u8 *mac)
{
struct otx2_nic *pf = netdev_priv(netdev);
if (!bitmap_empty(&pf->flow_cfg->dmacflt_bmap,
if (!bitmap_empty(pf->flow_cfg->dmacflt_bmap,
pf->flow_cfg->dmacflt_max_flows))
netdev_warn(netdev,
"Add %pM to CGX/RPM DMAC filters list as well\n",
......@@ -438,7 +453,7 @@ int otx2_get_maxflows(struct otx2_flow_config *flow_cfg)
return 0;
if (flow_cfg->nr_flows == flow_cfg->max_flows ||
!bitmap_empty(&flow_cfg->dmacflt_bmap,
!bitmap_empty(flow_cfg->dmacflt_bmap,
flow_cfg->dmacflt_max_flows))
return flow_cfg->max_flows + flow_cfg->dmacflt_max_flows;
else
......@@ -1010,7 +1025,7 @@ static int otx2_add_flow_with_pfmac(struct otx2_nic *pfvf,
otx2_add_flow_to_list(pfvf, pf_mac);
pfvf->flow_cfg->nr_flows++;
set_bit(0, &pfvf->flow_cfg->dmacflt_bmap);
set_bit(0, pfvf->flow_cfg->dmacflt_bmap);
return 0;
}
......@@ -1064,7 +1079,7 @@ int otx2_add_flow(struct otx2_nic *pfvf, struct ethtool_rxnfc *nfc)
return otx2_dmacflt_update(pfvf, eth_hdr->h_dest,
flow->entry);
if (bitmap_full(&flow_cfg->dmacflt_bmap,
if (bitmap_full(flow_cfg->dmacflt_bmap,
flow_cfg->dmacflt_max_flows)) {
netdev_warn(pfvf->netdev,
"Can't insert the rule %d as max allowed dmac filters are %d\n",
......@@ -1078,17 +1093,17 @@ int otx2_add_flow(struct otx2_nic *pfvf, struct ethtool_rxnfc *nfc)
}
/* Install PF mac address to DMAC filter list */
if (!test_bit(0, &flow_cfg->dmacflt_bmap))
if (!test_bit(0, flow_cfg->dmacflt_bmap))
otx2_add_flow_with_pfmac(pfvf, flow);
flow->rule_type |= DMAC_FILTER_RULE;
flow->entry = find_first_zero_bit(&flow_cfg->dmacflt_bmap,
flow->entry = find_first_zero_bit(flow_cfg->dmacflt_bmap,
flow_cfg->dmacflt_max_flows);
fsp->location = flow_cfg->max_flows + flow->entry;
flow->flow_spec.location = fsp->location;
flow->location = fsp->location;
set_bit(flow->entry, &flow_cfg->dmacflt_bmap);
set_bit(flow->entry, flow_cfg->dmacflt_bmap);
otx2_dmacflt_add(pfvf, eth_hdr->h_dest, flow->entry);
} else {
......@@ -1154,11 +1169,12 @@ static void otx2_update_rem_pfmac(struct otx2_nic *pfvf, int req)
if (req == DMAC_ADDR_DEL) {
otx2_dmacflt_remove(pfvf, eth_hdr->h_dest,
0);
clear_bit(0, &pfvf->flow_cfg->dmacflt_bmap);
clear_bit(0, pfvf->flow_cfg->dmacflt_bmap);
found = true;
} else {
ether_addr_copy(eth_hdr->h_dest,
pfvf->netdev->dev_addr);
otx2_dmacflt_update(pfvf, eth_hdr->h_dest, 0);
}
break;
......@@ -1194,12 +1210,12 @@ int otx2_remove_flow(struct otx2_nic *pfvf, u32 location)
err = otx2_dmacflt_remove(pfvf, eth_hdr->h_dest,
flow->entry);
clear_bit(flow->entry, &flow_cfg->dmacflt_bmap);
clear_bit(flow->entry, flow_cfg->dmacflt_bmap);
/* If all dmac filters are removed delete macfilter with
* interface mac address and configure CGX/RPM block in
* promiscuous mode
*/
if (bitmap_weight(&flow_cfg->dmacflt_bmap,
if (bitmap_weight(flow_cfg->dmacflt_bmap,
flow_cfg->dmacflt_max_flows) == 1)
otx2_update_rem_pfmac(pfvf, DMAC_ADDR_DEL);
} else {
......
......@@ -1120,7 +1120,7 @@ static int otx2_cgx_config_loopback(struct otx2_nic *pf, bool enable)
struct msg_req *msg;
int err;
if (enable && !bitmap_empty(&pf->flow_cfg->dmacflt_bmap,
if (enable && !bitmap_empty(pf->flow_cfg->dmacflt_bmap,
pf->flow_cfg->dmacflt_max_flows))
netdev_warn(pf->netdev,
"CGX/RPM internal loopback might not work as DMAC filters are active\n");
......
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