mirror of
https://github.com/torvalds/linux.git
synced 2026-06-06 13:37:36 +02:00
octeontx2-af: npc: cn20k: Propagate MCAM key-type errors on cn20k
npc_mcam_idx_2_key_type() can fail; callers used to ignore it and still
used kw_type when enabling, configuring, copying, and reading MCAM entries.
That could program or decode hardware with an undefined key type.
Return -EINVAL when key-type lookup fails. Return -EINVAL from
npc_cn20k_copy_mcam_entry() when src and dest key types differ instead of
failing silently.
Change npc_cn20k_{enable,config,copy,read}_mcam_entry() to return int on
success or error. Thread those errors through the cn20k MCAM write and read
mbox handlers, the cn20k baseline steer read path, NPC defrag move
(disable/copy/enable with dev_err and -EFAULT), and the DMAC update path in
rvu_npc_fs.c.
Make npc_copy_mcam_entry() return int so the cn20k branch can return
npc_cn20k_copy_mcam_entry() without a void/int mismatch, and fail
NPC_MCAM_SHIFT_ENTRY when copy fails.
Cc: Suman Ghosh <sumang@marvell.com>
Cc: Dan Carpenter <error27@gmail.com>
Fixes: 6d1e70282f ("octeontx2-af: npc: cn20k: Use common APIs")
Link: https://lore.kernel.org/netdev/adiQJvuKlEhq2ILx@stanley.mountain/
Signed-off-by: Ratheesh Kannoth <rkannoth@marvell.com>
Link: https://patch.msgid.link/20260429022722.1110289-2-rkannoth@marvell.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
parent
75df490c9e
commit
aaadccde31
|
|
@ -798,7 +798,7 @@ void npc_cn20k_load_mkex_profile(struct rvu *rvu, int blkaddr,
|
|||
iounmap(mkex_prfl_addr);
|
||||
}
|
||||
|
||||
void
|
||||
int
|
||||
npc_cn20k_enable_mcam_entry(struct rvu *rvu, int blkaddr,
|
||||
int index, bool enable)
|
||||
{
|
||||
|
|
@ -808,7 +808,9 @@ npc_cn20k_enable_mcam_entry(struct rvu *rvu, int blkaddr,
|
|||
u64 cfg, hw_prio;
|
||||
u8 kw_type;
|
||||
|
||||
npc_mcam_idx_2_key_type(rvu, index, &kw_type);
|
||||
if (npc_mcam_idx_2_key_type(rvu, index, &kw_type))
|
||||
return -EINVAL;
|
||||
|
||||
if (kw_type == NPC_MCAM_KEY_X2) {
|
||||
cfg = rvu_read64(rvu, blkaddr,
|
||||
NPC_AF_CN20K_MCAMEX_BANKX_CFG_EXT(mcam_idx,
|
||||
|
|
@ -819,7 +821,7 @@ npc_cn20k_enable_mcam_entry(struct rvu *rvu, int blkaddr,
|
|||
rvu_write64(rvu, blkaddr,
|
||||
NPC_AF_CN20K_MCAMEX_BANKX_CFG_EXT(mcam_idx, bank),
|
||||
cfg);
|
||||
return;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* For NPC_CN20K_MCAM_KEY_X4 keys, both the banks
|
||||
|
|
@ -836,6 +838,8 @@ npc_cn20k_enable_mcam_entry(struct rvu *rvu, int blkaddr,
|
|||
NPC_AF_CN20K_MCAMEX_BANKX_CFG_EXT(mcam_idx, bank),
|
||||
cfg);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -1042,9 +1046,9 @@ npc_cn20k_set_mcam_bank_cfg(struct rvu *rvu, int blkaddr, int mcam_idx,
|
|||
}
|
||||
}
|
||||
|
||||
void npc_cn20k_config_mcam_entry(struct rvu *rvu, int blkaddr, int index,
|
||||
u8 intf, struct cn20k_mcam_entry *entry,
|
||||
bool enable, u8 hw_prio, u8 req_kw_type)
|
||||
int npc_cn20k_config_mcam_entry(struct rvu *rvu, int blkaddr, int index,
|
||||
u8 intf, struct cn20k_mcam_entry *entry,
|
||||
bool enable, u8 hw_prio, u8 req_kw_type)
|
||||
{
|
||||
struct npc_mcam *mcam = &rvu->hw->mcam;
|
||||
int mcam_idx = index % mcam->banksize;
|
||||
|
|
@ -1052,10 +1056,13 @@ void npc_cn20k_config_mcam_entry(struct rvu *rvu, int blkaddr, int index,
|
|||
int kw = 0;
|
||||
u8 kw_type;
|
||||
|
||||
/* Disable before mcam entry update */
|
||||
npc_cn20k_enable_mcam_entry(rvu, blkaddr, index, false);
|
||||
if (npc_mcam_idx_2_key_type(rvu, index, &kw_type))
|
||||
return -EINVAL;
|
||||
|
||||
/* Disable before mcam entry update */
|
||||
if (npc_cn20k_enable_mcam_entry(rvu, blkaddr, index, false))
|
||||
return -EINVAL;
|
||||
|
||||
npc_mcam_idx_2_key_type(rvu, index, &kw_type);
|
||||
/* CAM1 takes the comparison value and
|
||||
* CAM0 specifies match for a bit in key being '0' or '1' or 'dontcare'.
|
||||
* CAM1<n> = 0 & CAM0<n> = 1 => match if key<n> = 0
|
||||
|
|
@ -1120,9 +1127,11 @@ void npc_cn20k_config_mcam_entry(struct rvu *rvu, int blkaddr, int index,
|
|||
/* PF installing VF rule */
|
||||
npc_cn20k_set_mcam_bank_cfg(rvu, blkaddr, mcam_idx, bank,
|
||||
kw_type, enable, hw_prio);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void npc_cn20k_copy_mcam_entry(struct rvu *rvu, int blkaddr, u16 src, u16 dest)
|
||||
int npc_cn20k_copy_mcam_entry(struct rvu *rvu, int blkaddr, u16 src, u16 dest)
|
||||
{
|
||||
struct npc_mcam *mcam = &rvu->hw->mcam;
|
||||
u64 cfg, sreg, dreg, soff, doff;
|
||||
|
|
@ -1132,10 +1141,15 @@ void npc_cn20k_copy_mcam_entry(struct rvu *rvu, int blkaddr, u16 src, u16 dest)
|
|||
|
||||
dbank = npc_get_bank(mcam, dest);
|
||||
sbank = npc_get_bank(mcam, src);
|
||||
npc_mcam_idx_2_key_type(rvu, src, &src_kwtype);
|
||||
npc_mcam_idx_2_key_type(rvu, dest, &dest_kwtype);
|
||||
|
||||
if (npc_mcam_idx_2_key_type(rvu, src, &src_kwtype))
|
||||
return -EINVAL;
|
||||
|
||||
if (npc_mcam_idx_2_key_type(rvu, dest, &dest_kwtype))
|
||||
return -EINVAL;
|
||||
|
||||
if (src_kwtype != dest_kwtype)
|
||||
return;
|
||||
return -EINVAL;
|
||||
|
||||
src &= (mcam->banksize - 1);
|
||||
dest &= (mcam->banksize - 1);
|
||||
|
|
@ -1170,6 +1184,8 @@ void npc_cn20k_copy_mcam_entry(struct rvu *rvu, int blkaddr, u16 src, u16 dest)
|
|||
if (src_kwtype == NPC_MCAM_KEY_X2)
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void npc_cn20k_fill_entryword(struct cn20k_mcam_entry *entry, int idx,
|
||||
|
|
@ -1179,16 +1195,17 @@ static void npc_cn20k_fill_entryword(struct cn20k_mcam_entry *entry, int idx,
|
|||
entry->kw_mask[idx] = cam1 ^ cam0;
|
||||
}
|
||||
|
||||
void npc_cn20k_read_mcam_entry(struct rvu *rvu, int blkaddr, u16 index,
|
||||
struct cn20k_mcam_entry *entry,
|
||||
u8 *intf, u8 *ena, u8 *hw_prio)
|
||||
int npc_cn20k_read_mcam_entry(struct rvu *rvu, int blkaddr, u16 index,
|
||||
struct cn20k_mcam_entry *entry,
|
||||
u8 *intf, u8 *ena, u8 *hw_prio)
|
||||
{
|
||||
struct npc_mcam *mcam = &rvu->hw->mcam;
|
||||
u64 cam0, cam1, bank_cfg, cfg;
|
||||
int kw = 0, bank;
|
||||
u8 kw_type;
|
||||
|
||||
npc_mcam_idx_2_key_type(rvu, index, &kw_type);
|
||||
if (npc_mcam_idx_2_key_type(rvu, index, &kw_type))
|
||||
return -EINVAL;
|
||||
|
||||
bank = npc_get_bank(mcam, index);
|
||||
index &= (mcam->banksize - 1);
|
||||
|
|
@ -1298,6 +1315,8 @@ void npc_cn20k_read_mcam_entry(struct rvu *rvu, int blkaddr, u16 index,
|
|||
cfg = rvu_read64(rvu, blkaddr,
|
||||
NPC_AF_CN20K_MCAMEX_BANKX_ACTIONX_EXT(index, 0, 1));
|
||||
entry->vtag_action = cfg;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int rvu_mbox_handler_npc_cn20k_mcam_write_entry(struct rvu *rvu,
|
||||
|
|
@ -1335,11 +1354,10 @@ int rvu_mbox_handler_npc_cn20k_mcam_write_entry(struct rvu *rvu,
|
|||
if (is_pffunc_af(req->hdr.pcifunc))
|
||||
nix_intf = req->intf;
|
||||
|
||||
npc_cn20k_config_mcam_entry(rvu, blkaddr, req->entry, nix_intf,
|
||||
&req->entry_data, req->enable_entry,
|
||||
req->hw_prio, req->req_kw_type);
|
||||
rc = npc_cn20k_config_mcam_entry(rvu, blkaddr, req->entry, nix_intf,
|
||||
&req->entry_data, req->enable_entry,
|
||||
req->hw_prio, req->req_kw_type);
|
||||
|
||||
rc = 0;
|
||||
exit:
|
||||
mutex_unlock(&mcam->lock);
|
||||
return rc;
|
||||
|
|
@ -1361,11 +1379,13 @@ int rvu_mbox_handler_npc_cn20k_mcam_read_entry(struct rvu *rvu,
|
|||
|
||||
mutex_lock(&mcam->lock);
|
||||
rc = npc_mcam_verify_entry(mcam, pcifunc, req->entry);
|
||||
if (!rc)
|
||||
npc_cn20k_read_mcam_entry(rvu, blkaddr, req->entry,
|
||||
&rsp->entry_data, &rsp->intf,
|
||||
&rsp->enable, &rsp->hw_prio);
|
||||
if (rc)
|
||||
goto fail;
|
||||
|
||||
rc = npc_cn20k_read_mcam_entry(rvu, blkaddr, req->entry,
|
||||
&rsp->entry_data, &rsp->intf,
|
||||
&rsp->enable, &rsp->hw_prio);
|
||||
fail:
|
||||
mutex_unlock(&mcam->lock);
|
||||
return rc;
|
||||
}
|
||||
|
|
@ -1375,11 +1395,13 @@ int rvu_mbox_handler_npc_cn20k_mcam_alloc_and_write_entry(struct rvu *rvu,
|
|||
struct npc_mcam_alloc_and_write_entry_rsp *rsp)
|
||||
{
|
||||
struct rvu_pfvf *pfvf = rvu_get_pfvf(rvu, req->hdr.pcifunc);
|
||||
struct npc_mcam_free_entry_req free_req = { 0 };
|
||||
struct npc_mcam_alloc_entry_req entry_req;
|
||||
struct npc_mcam_alloc_entry_rsp entry_rsp;
|
||||
struct npc_mcam *mcam = &rvu->hw->mcam;
|
||||
u16 entry = NPC_MCAM_ENTRY_INVALID;
|
||||
int blkaddr, rc;
|
||||
struct msg_rsp free_rsp;
|
||||
int blkaddr, rc, err;
|
||||
u8 nix_intf;
|
||||
|
||||
blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NPC, 0);
|
||||
|
|
@ -1415,12 +1437,23 @@ int rvu_mbox_handler_npc_cn20k_mcam_alloc_and_write_entry(struct rvu *rvu,
|
|||
else
|
||||
nix_intf = pfvf->nix_rx_intf;
|
||||
|
||||
npc_cn20k_config_mcam_entry(rvu, blkaddr, entry, nix_intf,
|
||||
&req->entry_data, req->enable_entry,
|
||||
req->hw_prio, req->req_kw_type);
|
||||
rc = npc_cn20k_config_mcam_entry(rvu, blkaddr, entry, nix_intf,
|
||||
&req->entry_data, req->enable_entry,
|
||||
req->hw_prio, req->req_kw_type);
|
||||
|
||||
mutex_unlock(&mcam->lock);
|
||||
|
||||
if (rc) {
|
||||
free_req.hdr.pcifunc = req->hdr.pcifunc;
|
||||
free_req.entry = entry_rsp.entry;
|
||||
err = rvu_mbox_handler_npc_mcam_free_entry(rvu, &free_req, &free_rsp);
|
||||
if (err)
|
||||
dev_err(rvu->dev,
|
||||
"%s: Error to free mcam idx %u\n",
|
||||
__func__, entry_rsp.entry);
|
||||
return rc;
|
||||
}
|
||||
|
||||
rsp->entry = entry_rsp.entry;
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -1480,9 +1513,9 @@ int rvu_mbox_handler_npc_cn20k_read_base_steer_rule(struct rvu *rvu,
|
|||
|
||||
read_entry:
|
||||
/* Read the mcam entry */
|
||||
npc_cn20k_read_mcam_entry(rvu, blkaddr, index,
|
||||
&rsp->entry, &intf,
|
||||
&enable, &hw_prio);
|
||||
rc = npc_cn20k_read_mcam_entry(rvu, blkaddr, index,
|
||||
&rsp->entry, &intf,
|
||||
&enable, &hw_prio);
|
||||
mutex_unlock(&mcam->lock);
|
||||
out:
|
||||
return rc;
|
||||
|
|
@ -3607,9 +3640,30 @@ int npc_defrag_move_vdx_to_free(struct rvu *rvu,
|
|||
NPC_AF_CN20K_MCAMEX_BANKX_STAT_EXT(midx,
|
||||
bank));
|
||||
|
||||
npc_cn20k_enable_mcam_entry(rvu, blkaddr, old_midx, false);
|
||||
npc_cn20k_copy_mcam_entry(rvu, blkaddr, old_midx, new_midx);
|
||||
npc_cn20k_enable_mcam_entry(rvu, blkaddr, new_midx, true);
|
||||
/* If bug happened during copy/enable mcam, then there is a bug in allocation
|
||||
* algorithm itself. There is no point in rewinding and returning, as it
|
||||
* will face further issue. Return error after printing error
|
||||
*/
|
||||
if (npc_cn20k_enable_mcam_entry(rvu, blkaddr, old_midx, false)) {
|
||||
dev_err(rvu->dev,
|
||||
"%s: Error happened while disabling old_mid=%u\n",
|
||||
__func__, old_midx);
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
if (npc_cn20k_copy_mcam_entry(rvu, blkaddr, old_midx, new_midx)) {
|
||||
dev_err(rvu->dev,
|
||||
"%s: Error happened while copying old_midx=%u new_midx=%u\n",
|
||||
__func__, old_midx, new_midx);
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
if (npc_cn20k_enable_mcam_entry(rvu, blkaddr, new_midx, true)) {
|
||||
dev_err(rvu->dev,
|
||||
"%s: Error happened while enabling new_mid=%u\n",
|
||||
__func__, new_midx);
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
midx = new_midx % mcam->banksize;
|
||||
bank = new_midx / mcam->banksize;
|
||||
|
|
|
|||
|
|
@ -320,16 +320,16 @@ void npc_cn20k_dft_rules_free(struct rvu *rvu, u16 pcifunc);
|
|||
int npc_cn20k_dft_rules_idx_get(struct rvu *rvu, u16 pcifunc, u16 *bcast,
|
||||
u16 *mcast, u16 *promisc, u16 *ucast);
|
||||
|
||||
void npc_cn20k_config_mcam_entry(struct rvu *rvu, int blkaddr, int index,
|
||||
u8 intf, struct cn20k_mcam_entry *entry,
|
||||
bool enable, u8 hw_prio, u8 req_kw_type);
|
||||
void npc_cn20k_enable_mcam_entry(struct rvu *rvu, int blkaddr,
|
||||
int index, bool enable);
|
||||
void npc_cn20k_copy_mcam_entry(struct rvu *rvu, int blkaddr,
|
||||
u16 src, u16 dest);
|
||||
void npc_cn20k_read_mcam_entry(struct rvu *rvu, int blkaddr, u16 index,
|
||||
struct cn20k_mcam_entry *entry, u8 *intf,
|
||||
u8 *ena, u8 *hw_prio);
|
||||
int npc_cn20k_config_mcam_entry(struct rvu *rvu, int blkaddr, int index,
|
||||
u8 intf, struct cn20k_mcam_entry *entry,
|
||||
bool enable, u8 hw_prio, u8 req_kw_type);
|
||||
int npc_cn20k_enable_mcam_entry(struct rvu *rvu, int blkaddr,
|
||||
int index, bool enable);
|
||||
int npc_cn20k_copy_mcam_entry(struct rvu *rvu, int blkaddr,
|
||||
u16 src, u16 dest);
|
||||
int npc_cn20k_read_mcam_entry(struct rvu *rvu, int blkaddr, u16 index,
|
||||
struct cn20k_mcam_entry *entry, u8 *intf,
|
||||
u8 *ena, u8 *hw_prio);
|
||||
void npc_cn20k_clear_mcam_entry(struct rvu *rvu, int blkaddr,
|
||||
int bank, int index);
|
||||
int npc_mcam_idx_2_key_type(struct rvu *rvu, u16 mcam_idx, u8 *key_type);
|
||||
|
|
|
|||
|
|
@ -241,7 +241,10 @@ void npc_enable_mcam_entry(struct rvu *rvu, struct npc_mcam *mcam,
|
|||
if (index < 0 || index >= mcam->banksize * mcam->banks)
|
||||
return;
|
||||
|
||||
return npc_cn20k_enable_mcam_entry(rvu, blkaddr, index, enable);
|
||||
if (npc_cn20k_enable_mcam_entry(rvu, blkaddr, index, enable))
|
||||
dev_err(rvu->dev, "Error to %s mcam %u entry\n",
|
||||
enable ? "enable" : "disable", index);
|
||||
return;
|
||||
}
|
||||
|
||||
index &= (mcam->banksize - 1);
|
||||
|
|
@ -589,8 +592,8 @@ void npc_read_mcam_entry(struct rvu *rvu, struct npc_mcam *mcam,
|
|||
NPC_AF_MCAMEX_BANKX_CFG(src, sbank)) & 1;
|
||||
}
|
||||
|
||||
static void npc_copy_mcam_entry(struct rvu *rvu, struct npc_mcam *mcam,
|
||||
int blkaddr, u16 src, u16 dest)
|
||||
static int npc_copy_mcam_entry(struct rvu *rvu, struct npc_mcam *mcam,
|
||||
int blkaddr, u16 src, u16 dest)
|
||||
{
|
||||
int dbank = npc_get_bank(mcam, dest);
|
||||
int sbank = npc_get_bank(mcam, src);
|
||||
|
|
@ -630,6 +633,7 @@ static void npc_copy_mcam_entry(struct rvu *rvu, struct npc_mcam *mcam,
|
|||
NPC_AF_MCAMEX_BANKX_CFG(src, sbank));
|
||||
rvu_write64(rvu, blkaddr,
|
||||
NPC_AF_MCAMEX_BANKX_CFG(dest, dbank), cfg);
|
||||
return 0;
|
||||
}
|
||||
|
||||
u64 npc_get_mcam_action(struct rvu *rvu, struct npc_mcam *mcam,
|
||||
|
|
@ -3266,7 +3270,10 @@ int rvu_mbox_handler_npc_mcam_shift_entry(struct rvu *rvu,
|
|||
npc_enable_mcam_entry(rvu, mcam, blkaddr, new_entry, false);
|
||||
|
||||
/* Copy rule from old entry to new entry */
|
||||
npc_copy_mcam_entry(rvu, mcam, blkaddr, old_entry, new_entry);
|
||||
if (npc_copy_mcam_entry(rvu, mcam, blkaddr, old_entry, new_entry)) {
|
||||
rc = NPC_MCAM_INVALID_REQ;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Copy counter mapping, if any */
|
||||
cntr = mcam->entry2cntr_map[old_entry];
|
||||
|
|
@ -3284,7 +3291,8 @@ int rvu_mbox_handler_npc_mcam_shift_entry(struct rvu *rvu,
|
|||
|
||||
/* If shift has failed then report the failed index */
|
||||
if (index != req->shift_count) {
|
||||
rc = NPC_MCAM_PERM_DENIED;
|
||||
if (!rc)
|
||||
rc = NPC_MCAM_PERM_DENIED;
|
||||
rsp->failed_entry_idx = index;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1980,13 +1980,15 @@ static int npc_update_dmac_value(struct rvu *rvu, int npcblkaddr,
|
|||
|
||||
ether_addr_copy(rule->packet.dmac, pfvf->mac_addr);
|
||||
|
||||
if (is_cn20k(rvu->pdev))
|
||||
npc_cn20k_read_mcam_entry(rvu, npcblkaddr, rule->entry,
|
||||
cn20k_entry, &intf,
|
||||
&enable, &hw_prio);
|
||||
else
|
||||
if (is_cn20k(rvu->pdev)) {
|
||||
if (npc_cn20k_read_mcam_entry(rvu, npcblkaddr, rule->entry,
|
||||
cn20k_entry, &intf,
|
||||
&enable, &hw_prio))
|
||||
return -EINVAL;
|
||||
} else {
|
||||
npc_read_mcam_entry(rvu, mcam, npcblkaddr, rule->entry,
|
||||
entry, &intf, &enable);
|
||||
}
|
||||
|
||||
npc_update_entry(rvu, NPC_DMAC, &mdata,
|
||||
ether_addr_to_u64(pfvf->mac_addr), 0,
|
||||
|
|
@ -2038,8 +2040,12 @@ void npc_mcam_enable_flows(struct rvu *rvu, u16 target)
|
|||
continue;
|
||||
}
|
||||
|
||||
if (rule->vfvlan_cfg)
|
||||
npc_update_dmac_value(rvu, blkaddr, rule, pfvf);
|
||||
if (rule->vfvlan_cfg) {
|
||||
if (npc_update_dmac_value(rvu, blkaddr, rule, pfvf))
|
||||
dev_err(rvu->dev,
|
||||
"Update dmac failed for %u, target=%#x\n",
|
||||
rule->entry, target);
|
||||
}
|
||||
|
||||
if (rule->rx_action.op == NIX_RX_ACTION_DEFAULT) {
|
||||
if (!def_ucast_rule)
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user