octeontx2-af: Block VFs from clobbering special CGX PKIND state

PF and VF NIX LFs that share a CGX LMAC reuse the same hardware PKIND
programming. When HiGig2 or EDSA parsing is enabled, a VF NIX LF alloc must
not reset the LMAC RX PKIND or default TX parse config over the PF setup.

Add cgx_get_pkind() and rvu_cgx_is_pkind_config_permitted() so VFs skip
cgx_set_pkind(), rvu_npc_set_pkind(), and NIX_AF_LFX_TX_PARSE_CFG updates
when the LMAC is using NPC_RX_HIGIG_PKIND or NPC_RX_EDSA_PKIND.

Fixes: 94d942c5fb ("octeontx2-af: Config pkind for CGX mapped PFs")
Cc: Geetha sowjanya <gakula@marvell.com>
Signed-off-by: Hariprasad Kelam <hkelam@marvell.com>
Signed-off-by: Ratheesh Kannoth <rkannoth@marvell.com>
Link: https://patch.msgid.link/20260722081229.1653619-1-rkannoth@marvell.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
Hariprasad Kelam
2026-07-28 18:52:58 -07:00
committed by Jakub Kicinski
parent 0fe1e3e8f3
commit 3bd438a58e
6 changed files with 131 additions and 14 deletions
@@ -518,6 +518,18 @@ int cgx_set_pkind(void *cgxd, u8 lmac_id, int pkind)
return 0;
}
int cgx_get_pkind(void *cgxd, u8 lmac_id, int *pkind)
{
struct cgx *cgx = cgxd;
if (!is_lmac_valid(cgx, lmac_id))
return -ENODEV;
*pkind = cgx_read(cgx, lmac_id, cgx->mac_ops->rxid_map_offset);
*pkind = *pkind & 0x3F;
return 0;
}
static u8 cgx_get_lmac_type(void *cgxd, int lmac_id)
{
struct cgx *cgx = cgxd;
@@ -141,6 +141,7 @@ int cgx_get_cgxid(void *cgxd);
int cgx_get_lmac_cnt(void *cgxd);
void *cgx_get_pdata(int cgx_id);
int cgx_set_pkind(void *cgxd, u8 lmac_id, int pkind);
int cgx_get_pkind(void *cgxd, u8 lmac_id, int *pkind);
int cgx_lmac_evh_register(struct cgx_event_cb *cb, void *cgxd, int lmac_id);
int cgx_lmac_evh_unregister(void *cgxd, int lmac_id);
int cgx_get_tx_stats(void *cgxd, int lmac_id, int idx, u64 *tx_stat);
@@ -1115,6 +1115,8 @@ void npc_read_mcam_entry(struct rvu *rvu, struct npc_mcam *mcam,
u8 *intf, u8 *ena);
int npc_config_cntr_default_entries(struct rvu *rvu, bool enable);
bool is_cgx_config_permitted(struct rvu *rvu, u16 pcifunc);
bool rvu_cgx_check_permission_and_set_pkind(struct rvu *rvu, u16 pcifunc, int pkind);
bool rvu_cgx_is_pkind_config_permitted(struct rvu *rvu, u16 pcifunc);
bool is_mac_feature_supported(struct rvu *rvu, int pf, int feature);
u32 rvu_cgx_get_fifolen(struct rvu *rvu);
void *rvu_first_cgx_pdata(struct rvu *rvu);
@@ -1355,3 +1355,82 @@ void rvu_mac_reset(struct rvu *rvu, u16 pcifunc)
if (mac_ops->mac_reset(cgxd, lmac, !is_vf(pcifunc)))
dev_err(rvu->dev, "Failed to reset MAC\n");
}
/* Do not allow CGX-mapped VFs to overwrite PKIND when special parse kinds
* (HiGig, EDSA, etc.) are in use on the shared LMAC. VFs must not program
* NPC_TX_DEF_PKIND on NIX_AF_LFX_TX_PARSE_CFG in that case: the PF owns
* parse mode and no separate NPC_TX_HIGIG_PKIND is installed on the VF LF.
* TX-parse callers skip the write when denied; rvu_lf_reset() clears each LF
* before alloc so the next permitted owner programs NPC_TX_DEF_PKIND.
*/
bool rvu_cgx_is_pkind_config_permitted(struct rvu *rvu, u16 pcifunc)
{
int pf, err, rxpkind;
u8 cgx_id, lmac_id;
void *cgxd;
pf = rvu_get_pf(rvu->pdev, pcifunc);
if (!(pcifunc & RVU_PFVF_FUNC_MASK))
return true;
if (!is_pf_cgxmapped(rvu, pf))
return true;
rvu_get_cgx_lmac_id(rvu->pf2cgxlmac_map[pf], &cgx_id, &lmac_id);
cgxd = rvu_cgx_pdata(cgx_id, rvu);
err = cgx_get_pkind(cgxd, lmac_id, &rxpkind);
if (err)
return false;
switch (rxpkind) {
case NPC_RX_HIGIG_PKIND:
case NPC_RX_EDSA_PKIND:
return false;
default:
return true;
}
}
/* Do not allow CGX-mapped VFs to overwrite PKIND when special parse kinds
* (HiGig, EDSA, etc.) are in use on the shared LMAC.
*/
bool rvu_cgx_check_permission_and_set_pkind(struct rvu *rvu, u16 pcifunc, int pkind)
{
int pf, err, rxpkind;
u8 cgx_id, lmac_id;
struct cgx *cgxd;
pf = rvu_get_pf(rvu->pdev, pcifunc);
if (!is_pf_cgxmapped(rvu, pf))
return false;
rvu_get_cgx_lmac_id(rvu->pf2cgxlmac_map[pf], &cgx_id, &lmac_id);
cgxd = rvu_cgx_pdata(cgx_id, rvu);
mutex_lock(&cgxd->lock);
if (!is_vf(pcifunc))
goto set;
err = cgx_get_pkind(cgxd, lmac_id, &rxpkind);
if (err)
goto err;
switch (rxpkind) {
case NPC_RX_HIGIG_PKIND:
case NPC_RX_EDSA_PKIND:
goto err;
default:
break;
}
set:
cgx_set_pkind(rvu_cgx_pdata(cgx_id, rvu), lmac_id, pkind);
mutex_unlock(&cgxd->lock);
return true;
err:
mutex_unlock(&cgxd->lock);
return false;
}
@@ -363,8 +363,8 @@ static int nix_interface_init(struct rvu *rvu, u16 pcifunc, int type, int nixlf,
pfvf->tx_chan_cnt = 1;
rsp->tx_link = cgx_id * hw->lmac_per_cgx + lmac_id;
cgx_set_pkind(rvu_cgx_pdata(cgx_id, rvu), lmac_id, pkind);
rvu_npc_set_pkind(rvu, pkind, pfvf);
if (rvu_cgx_check_permission_and_set_pkind(rvu, pcifunc, pkind))
rvu_npc_set_pkind(rvu, pkind, pfvf);
break;
case NIX_INTF_TYPE_LBK:
vf = (pcifunc & RVU_PFVF_FUNC_MASK) - 1;
@@ -1505,13 +1505,15 @@ int rvu_mbox_handler_nix_lf_alloc(struct rvu *rvu,
struct nix_lf_alloc_req *req,
struct nix_lf_alloc_rsp *rsp)
{
int nixlf, qints, hwctx_size, intf, rc = 0;
int nixlf, qints, hwctx_size, intf, rc = 0, pf;
u16 bcast, mcast, promisc, ucast;
struct rvu_hwinfo *hw = rvu->hw;
u16 pcifunc = req->hdr.pcifunc;
u8 cgx_id = 0, lmac_id = 0;
bool rules_created = false;
struct rvu_block *block;
struct rvu_pfvf *pfvf;
struct cgx *cgxd;
u64 cfg, ctx_cfg;
int blkaddr;
@@ -1685,8 +1687,20 @@ int rvu_mbox_handler_nix_lf_alloc(struct rvu *rvu,
rvu_write64(rvu, blkaddr, NIX_AF_LFX_RX_CFG(nixlf), req->rx_cfg);
/* Configure pkind for TX parse config */
pf = rvu_get_pf(rvu->pdev, pcifunc);
cfg = NPC_TX_DEF_PKIND;
rvu_write64(rvu, blkaddr, NIX_AF_LFX_TX_PARSE_CFG(nixlf), cfg);
if (is_pf_cgxmapped(rvu, pf) && is_vf(pcifunc)) {
rvu_get_cgx_lmac_id(rvu->pf2cgxlmac_map[pf], &cgx_id, &lmac_id);
cgxd = rvu_cgx_pdata(cgx_id, rvu);
mutex_lock(&cgxd->lock);
if (rvu_cgx_is_pkind_config_permitted(rvu, pcifunc))
rvu_write64(rvu, blkaddr, NIX_AF_LFX_TX_PARSE_CFG(nixlf), cfg);
mutex_unlock(&cgxd->lock);
} else {
rvu_write64(rvu, blkaddr, NIX_AF_LFX_TX_PARSE_CFG(nixlf), cfg);
}
if (is_rep_dev(rvu, pcifunc)) {
pfvf->tx_chan_base = RVU_SWITCH_LBK_CHAN;
@@ -19,6 +19,7 @@
#include "cn20k/npc.h"
#include "rvu_npc.h"
#include "cn20k/reg.h"
#include "lmac_common.h"
#define RSVD_MCAM_ENTRIES_PER_PF 3 /* Broadcast, Promisc and AllMulticast */
#define RSVD_MCAM_ENTRIES_PER_NIXLF 1 /* Ucast for LFs */
@@ -4200,10 +4201,11 @@ int rvu_npc_set_parse_mode(struct rvu *rvu, u16 pcifunc, u64 mode, u8 dir,
{
struct rvu_pfvf *pfvf = rvu_get_pfvf(rvu, pcifunc);
int blkaddr, nixlf, rc, intf_mode;
int pf = rvu_get_pf(rvu->pdev, pcifunc);
int blkaddr, nixlf, rc, intf_mode;
u8 cgx_id = 0, lmac_id = 0;
u64 rxpkind, txpkind;
u8 cgx_id, lmac_id;
struct cgx *cgxd;
/* use default pkind to disable edsa/higig */
rxpkind = rvu_npc_get_pkind(rvu, pf);
@@ -4227,12 +4229,8 @@ int rvu_npc_set_parse_mode(struct rvu *rvu, u16 pcifunc, u64 mode, u8 dir,
/* rx pkind set req valid only for cgx mapped PFs */
if (!is_cgx_config_permitted(rvu, pcifunc))
return 0;
rvu_get_cgx_lmac_id(rvu->pf2cgxlmac_map[pf], &cgx_id, &lmac_id);
rc = cgx_set_pkind(rvu_cgx_pdata(cgx_id, rvu), lmac_id,
rxpkind);
if (rc)
return rc;
if (!rvu_cgx_check_permission_and_set_pkind(rvu, pcifunc, rxpkind))
return -EINVAL;
}
if (dir & PKIND_TX) {
@@ -4241,8 +4239,19 @@ int rvu_npc_set_parse_mode(struct rvu *rvu, u16 pcifunc, u64 mode, u8 dir,
if (rc)
return rc;
rvu_write64(rvu, blkaddr, NIX_AF_LFX_TX_PARSE_CFG(nixlf),
txpkind);
if (is_pf_cgxmapped(rvu, pf) && is_vf(pcifunc)) {
rvu_get_cgx_lmac_id(rvu->pf2cgxlmac_map[pf], &cgx_id,
&lmac_id);
cgxd = rvu_cgx_pdata(cgx_id, rvu);
mutex_lock(&cgxd->lock);
if (rvu_cgx_is_pkind_config_permitted(rvu, pcifunc))
rvu_write64(rvu, blkaddr, NIX_AF_LFX_TX_PARSE_CFG(nixlf),
txpkind);
mutex_unlock(&cgxd->lock);
} else {
rvu_write64(rvu, blkaddr, NIX_AF_LFX_TX_PARSE_CFG(nixlf),
txpkind);
}
}
pfvf->intf_mode = intf_mode;