]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
octeontx2-af: Block VFs from clobbering special CGX PKIND state
authorHariprasad Kelam <hkelam@marvell.com>
Wed, 22 Jul 2026 08:12:29 +0000 (13:42 +0530)
committerJakub Kicinski <kuba@kernel.org>
Wed, 29 Jul 2026 01:52:58 +0000 (18:52 -0700)
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: 94d942c5fb97 ("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>
drivers/net/ethernet/marvell/octeontx2/af/cgx.c
drivers/net/ethernet/marvell/octeontx2/af/cgx.h
drivers/net/ethernet/marvell/octeontx2/af/rvu.h
drivers/net/ethernet/marvell/octeontx2/af/rvu_cgx.c
drivers/net/ethernet/marvell/octeontx2/af/rvu_nix.c
drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.c

index 2e94d5105016bf235d10429a08940025e4fdbbbe..f5fd6138c352fde2cb2a9776a705cc986c03be8c 100644 (file)
@@ -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;
index 92ccf343dfe04f6a96794033e81f679a437b8edb..8411a75dd723f9b3b5fab151e6d28bcc9e606d77 100644 (file)
@@ -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);
index 7f3505ae6860423422d15fb14f52285b229930b0..9d5b7b51bdfa591a92fa561819297fc1340c7e9a 100644 (file)
@@ -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);
index 4ff3935ed3fe846ab3b004ace231b1e42de116c8..87d21889dc49e27f954eb0d49f74d32bdbde11de 100644 (file)
@@ -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;
+}
index 6a0ce2665031d6a630551665b502b17217e88d55..964bcaae098e251722fa829c4611f2453a79f2cc 100644 (file)
@@ -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;
index c7bc0b3a29b98442f14e0e3197448e1ab8b4c2ba..38554d51164e174c0f0d8e2e9b0eef1b69e988d1 100644 (file)
@@ -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;