[PATCH v3 net-next] octeontx2-af: pass devlink switch id and cache representor map
flat view
COLD22d
From: Ratheesh Kannoth <rkannoth@marvell.com>
Date: 2026-09-24 08:26:34
Also in:
lkml
Subsystem:
marvell octeontx2 physical function driver, marvell octeontx2 rvu admin function driver, networking drivers, the rest · Maintainers:
Sunil Goutham, Geetha sowjanya, Ratheesh Kannoth, Subbaraya Sundeep, Bharat Bhushan, Andrew Lunn, "David S. Miller", Eric Dumazet, Jakub Kicinski, Paolo Abeni, Linus Torvalds
Extend MBOX_MSG_ESW_CFG with the representor devlink switch_id and store it in the AF. Build rep2pfvf_map once on GET_REP_CNT, always refresh rep_pcifunc, and protect map access with rsrc_lock. Reset the cache on eswitch disable and representor FLR. Add rvu_sw_port_id() and share the representor index lookup with rvu_rep_get_vlan_id(). Signed-off-by: Ratheesh Kannoth <rkannoth@marvell.com> --- v2 -> v3: - Fix compilation issue. https://lore.kernel.org/netdev/202609241557.82GuIoAK-lkp@intel.com/ (local) v1 -> v2: - Always refresh rep_pcifunc on GET_REP_CNT instead of pinning it to the first caller. - Replace the READ_ONCE/WRITE_ONCE rep2pfvf_map fast path with rvu_rep_lookup_id() lookups under rsrc_lock. - Add rvu_rep_cache_reset() and call it on eswitch disable and representor FLR so the cached map and switch_id are torn down. - Ignore redundant ESW_CFG enable/disable requests when the mode is already in the requested state. - Validate switch_id length before allocating the ESW_CFG mailbox message. - Build the representor map from rvu_rep_create() via rvu_get_rep_cnt(). - Drop the ESW_CFG wire-format comment block; the layout change is carried only by the struct fields. - Factor rvu_rep_get_vlan_id() and rvu_sw_port_id() through a shared rvu_rep_lookup_id() helper. https://lore.kernel.org/netdev/20260918050021.1359606-1-rkannoth@marvell.com/ (local) --- .../net/ethernet/marvell/octeontx2/af/mbox.h | 2 + .../net/ethernet/marvell/octeontx2/af/rvu.c | 3 + .../net/ethernet/marvell/octeontx2/af/rvu.h | 9 ++ .../ethernet/marvell/octeontx2/af/rvu_rep.c | 117 +++++++++++++++--- .../net/ethernet/marvell/octeontx2/nic/rep.c | 81 ++++++------ 5 files changed, 160 insertions(+), 52 deletions(-)
diff --git a/drivers/net/ethernet/marvell/octeontx2/af/mbox.h b/drivers/net/ethernet/marvell/octeontx2/af/mbox.h
index cece197d1074..45c03f9294a5 100644
--- a/drivers/net/ethernet/marvell/octeontx2/af/mbox.h
+++ b/drivers/net/ethernet/marvell/octeontx2/af/mbox.h@@ -1788,6 +1788,8 @@ struct esw_cfg_req { struct mbox_msghdr hdr; u8 ena; u64 rsvd; + unsigned char switch_id[MAX_PHYS_ITEM_ID_LEN]; + u8 switch_id_len; }; struct rep_evt_data {
diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu.c
index 30e148291581..aeb6b4917f45 100644
--- a/drivers/net/ethernet/marvell/octeontx2/af/rvu.c
+++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu.c@@ -2924,6 +2924,9 @@ static void __rvu_flr_handler(struct rvu *rvu, u16 pcifunc) if (rvu->mcs_blk_cnt) rvu_mcs_flr_handler(rvu, pcifunc); + if (is_rep_dev(rvu, pcifunc)) + rvu_rep_cache_reset(rvu); + mutex_unlock(&rvu->flr_lock); }
diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu.h b/drivers/net/ethernet/marvell/octeontx2/af/rvu.h
index fb4870cd18e9..d5f69cba6d41 100644
--- a/drivers/net/ethernet/marvell/octeontx2/af/rvu.h
+++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu.h@@ -570,6 +570,7 @@ struct npc_kpu_profile_adapter { }; #define RVU_SWITCH_LBK_CHAN 63 +#define RVU_SW_INVALID_PORT_ID ((u32)~0U) struct rvu_switch { struct mutex switch_lock; /* Serialize flow installation */
@@ -577,6 +578,11 @@ struct rvu_switch { u16 *entry2pcifunc; u16 mode; u16 start_entry; + unsigned char switch_id[MAX_PHYS_ITEM_ID_LEN]; + u8 switch_id_len; +#define RVU_SWITCH_FLAG_FW_READY BIT_ULL(0) + u64 flags; + u16 pcifunc; }; struct rep_evtq_ent {
@@ -1194,9 +1200,12 @@ void rvu_mcs_ptp_cfg(struct rvu *rvu, u8 rpm_id, u8 lmac_id, bool ena); void rvu_mcs_exit(struct rvu *rvu); /* Representor APIs */ +void rvu_rep_cache_reset(struct rvu *rvu); int rvu_rep_pf_init(struct rvu *rvu); int rvu_rep_install_mcam_rules(struct rvu *rvu); void rvu_rep_update_rules(struct rvu *rvu, u16 pcifunc, bool ena); int rvu_rep_notify_pfvf_state(struct rvu *rvu, u16 pcifunc, bool enable); int npc_mcam_verify_entry(struct npc_mcam *mcam, u16 pcifunc, int entry); +u16 rvu_rep_get_vlan_id(struct rvu *rvu, u16 pcifunc); +u32 rvu_sw_port_id(struct rvu *rvu, u16 pcifunc); #endif /* RVU_H */
diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_rep.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu_rep.c
index a2781e0f504e..a3ad45f46742 100644
--- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_rep.c
+++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_rep.c@@ -6,6 +6,7 @@ */ #include <linux/bitfield.h> +#include <linux/stddef.h> #include <linux/types.h> #include <linux/device.h> #include <linux/module.h>
@@ -189,14 +190,47 @@ int rvu_mbox_handler_nix_lf_stats(struct rvu *rvu, return 0; } -static u16 rvu_rep_get_vlan_id(struct rvu *rvu, u16 pcifunc) +static bool rvu_rep_lookup_id(struct rvu *rvu, u16 pcifunc, u16 *rep_id) { - int id; + u16 *map; + int id, cnt; + bool found = false; + + mutex_lock(&rvu->rsrc_lock); + map = rvu->rep2pfvf_map; + cnt = rvu->rep_cnt; + if (map && cnt) { + for (id = 0; id < cnt; id++) { + if (map[id] == pcifunc) { + *rep_id = id; + found = true; + break; + } + } + } + mutex_unlock(&rvu->rsrc_lock); - for (id = 0; id < rvu->rep_cnt; id++) - if (rvu->rep2pfvf_map[id] == pcifunc) - return id; - return 0; + return found; +} + +u16 rvu_rep_get_vlan_id(struct rvu *rvu, u16 pcifunc) +{ + u16 rep_id; + + if (!rvu_rep_lookup_id(rvu, pcifunc, &rep_id)) + return 0; + return rep_id; +} + +u32 rvu_sw_port_id(struct rvu *rvu, u16 pcifunc) +{ + u16 rep_id; + + if (!rvu_rep_lookup_id(rvu, pcifunc, &rep_id)) + return RVU_SW_INVALID_PORT_ID; + + return FIELD_PREP(GENMASK_ULL(31, 16), rep_id) | + FIELD_PREP(GENMASK_ULL(15, 0), pcifunc); } static int rvu_rep_tx_vlan_cfg(struct rvu *rvu, u16 pcifunc,
@@ -429,16 +463,48 @@ int rvu_rep_pf_init(struct rvu *rvu) return 0; } +void rvu_rep_cache_reset(struct rvu *rvu) +{ + u16 *map; + + mutex_lock(&rvu->rsrc_lock); + rvu->rep_mode = 0; + rvu->rep_pcifunc = 0; + map = rvu->rep2pfvf_map; + rvu->rep_cnt = 0; + rvu->rep2pfvf_map = NULL; + memset(rvu->rswitch.switch_id, 0, sizeof(rvu->rswitch.switch_id)); + rvu->rswitch.switch_id_len = 0; + mutex_unlock(&rvu->rsrc_lock); + + devm_kfree(rvu->dev, map); +} + int rvu_mbox_handler_esw_cfg(struct rvu *rvu, struct esw_cfg_req *req, struct msg_rsp *rsp) { if (req->hdr.pcifunc != rvu->rep_pcifunc) return 0; + if (rvu->rep_mode && req->ena) + return 0; + + if (!rvu->rep_mode && !req->ena) + return 0; + rvu->rep_mode = req->ena; + memset(rvu->rswitch.switch_id, 0, sizeof(rvu->rswitch.switch_id)); + rvu->rswitch.switch_id_len = 0; + if (req->switch_id_len && req->switch_id_len <= MAX_PHYS_ITEM_ID_LEN) { + memcpy(rvu->rswitch.switch_id, req->switch_id, + req->switch_id_len); + rvu->rswitch.switch_id_len = req->switch_id_len; + } - if (!rvu->rep_mode) + if (!rvu->rep_mode) { rvu_npc_free_mcam_entries(rvu, req->hdr.pcifunc, -1); + rvu_rep_cache_reset(rvu); + } return 0; }
@@ -447,31 +513,48 @@ int rvu_mbox_handler_get_rep_cnt(struct rvu *rvu, struct msg_req *req, struct get_rep_cnt_rsp *rsp) { int pf, vf, numvfs, hwvf, rep = 0; - u16 pcifunc; + u16 pcifunc, rep_cnt; + u16 *map; + + mutex_lock(&rvu->rsrc_lock); rvu->rep_pcifunc = req->hdr.pcifunc; - rsp->rep_cnt = rvu->cgx_mapped_pfs + rvu->cgx_mapped_vfs; - rvu->rep_cnt = rsp->rep_cnt; - rvu->rep2pfvf_map = devm_kzalloc(rvu->dev, rvu->rep_cnt * - sizeof(u16), GFP_KERNEL); - if (!rvu->rep2pfvf_map) + if (rvu->rep2pfvf_map) { + rsp->rep_cnt = rvu->rep_cnt; + for (rep = 0; rep < rvu->rep_cnt; rep++) + rsp->rep_pf_map[rep] = rvu->rep2pfvf_map[rep]; + mutex_unlock(&rvu->rsrc_lock); + return 0; + } + + rep_cnt = rvu->cgx_mapped_pfs + rvu->cgx_mapped_vfs; + map = devm_kzalloc(rvu->dev, rep_cnt * sizeof(u16), GFP_KERNEL); + if (!map) { + mutex_unlock(&rvu->rsrc_lock); return -ENOMEM; + } for (pf = 0; pf < rvu->hw->total_pfs; pf++) { if (!is_pf_cgxmapped(rvu, pf)) continue; pcifunc = rvu_make_pcifunc(rvu->pdev, pf, 0); - rvu->rep2pfvf_map[rep] = pcifunc; + map[rep] = pcifunc; rsp->rep_pf_map[rep] = pcifunc; rep++; rvu_get_pf_numvfs(rvu, pf, &numvfs, &hwvf); for (vf = 0; vf < numvfs; vf++) { - rvu->rep2pfvf_map[rep] = pcifunc | - ((vf + 1) & RVU_PFVF_FUNC_MASK); - rsp->rep_pf_map[rep] = rvu->rep2pfvf_map[rep]; + map[rep] = pcifunc | ((vf + 1) & RVU_PFVF_FUNC_MASK); + rsp->rep_pf_map[rep] = map[rep]; rep++; } } + + rvu->rep_cnt = rep_cnt; + rvu->rep2pfvf_map = map; + rsp->rep_cnt = rep_cnt; + + mutex_unlock(&rvu->rsrc_lock); + return 0; }
diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/rep.c b/drivers/net/ethernet/marvell/octeontx2/nic/rep.c
index 0f5d5642d3f7..80b47bb333b7 100644
--- a/drivers/net/ethernet/marvell/octeontx2/nic/rep.c
+++ b/drivers/net/ethernet/marvell/octeontx2/nic/rep.c@@ -399,8 +399,13 @@ static void rvu_rep_get_stats64(struct net_device *dev, static int rvu_eswitch_config(struct otx2_nic *priv, u8 ena) { + struct devlink_port_attrs attrs = {}; struct esw_cfg_req *req; + rvu_rep_devlink_set_switch_id(priv, &attrs.switch_id); + if (attrs.switch_id.id_len > MAX_PHYS_ITEM_ID_LEN) + return -EINVAL; + mutex_lock(&priv->mbox.lock); req = otx2_mbox_alloc_msg_esw_cfg(&priv->mbox); if (!req) {
@@ -408,6 +413,8 @@ static int rvu_eswitch_config(struct otx2_nic *priv, u8 ena) return -ENOMEM; } req->ena = ena; + req->switch_id_len = attrs.switch_id.id_len; + memcpy(req->switch_id, attrs.switch_id.id, req->switch_id_len); otx2_sync_mbox_msg(&priv->mbox); mutex_unlock(&priv->mbox.lock); return 0;
@@ -645,6 +652,41 @@ void rvu_rep_destroy(struct otx2_nic *priv) rvu_rep_rsrc_free(priv); } +static int rvu_get_rep_cnt(struct otx2_nic *priv) +{ + struct get_rep_cnt_rsp *rsp; + struct mbox_msghdr *msghdr; + struct msg_req *req; + int err, rep; + + mutex_lock(&priv->mbox.lock); + req = otx2_mbox_alloc_msg_get_rep_cnt(&priv->mbox); + if (!req) { + mutex_unlock(&priv->mbox.lock); + return -ENOMEM; + } + err = otx2_sync_mbox_msg(&priv->mbox); + if (err) + goto exit; + + msghdr = otx2_mbox_get_rsp(&priv->mbox.mbox, 0, &req->hdr); + if (IS_ERR(msghdr)) { + err = PTR_ERR(msghdr); + goto exit; + } + + rsp = (struct get_rep_cnt_rsp *)msghdr; + priv->hw.tx_queues = rsp->rep_cnt; + priv->hw.rx_queues = rsp->rep_cnt; + priv->rep_cnt = rsp->rep_cnt; + for (rep = 0; rep < priv->rep_cnt; rep++) + priv->rep_pf_map[rep] = rsp->rep_pf_map[rep]; + +exit: + mutex_unlock(&priv->mbox.lock); + return err; +} + int rvu_rep_create(struct otx2_nic *priv, struct netlink_ext_ack *extack) { int rep_cnt = priv->rep_cnt;
@@ -653,6 +695,10 @@ int rvu_rep_create(struct otx2_nic *priv, struct netlink_ext_ack *extack) int rep_id, err; u16 pcifunc; + err = rvu_get_rep_cnt(priv); + if (err) + return err; + err = rvu_rep_rsrc_init(priv); if (err) return -ENOMEM;
@@ -730,41 +776,6 @@ int rvu_rep_create(struct otx2_nic *priv, struct netlink_ext_ack *extack) return err; } -static int rvu_get_rep_cnt(struct otx2_nic *priv) -{ - struct get_rep_cnt_rsp *rsp; - struct mbox_msghdr *msghdr; - struct msg_req *req; - int err, rep; - - mutex_lock(&priv->mbox.lock); - req = otx2_mbox_alloc_msg_get_rep_cnt(&priv->mbox); - if (!req) { - mutex_unlock(&priv->mbox.lock); - return -ENOMEM; - } - err = otx2_sync_mbox_msg(&priv->mbox); - if (err) - goto exit; - - msghdr = otx2_mbox_get_rsp(&priv->mbox.mbox, 0, &req->hdr); - if (IS_ERR(msghdr)) { - err = PTR_ERR(msghdr); - goto exit; - } - - rsp = (struct get_rep_cnt_rsp *)msghdr; - priv->hw.tx_queues = rsp->rep_cnt; - priv->hw.rx_queues = rsp->rep_cnt; - priv->rep_cnt = rsp->rep_cnt; - for (rep = 0; rep < priv->rep_cnt; rep++) - priv->rep_pf_map[rep] = rsp->rep_pf_map[rep]; - -exit: - mutex_unlock(&priv->mbox.lock); - return err; -} - static int rvu_rep_probe(struct pci_dev *pdev, const struct pci_device_id *id) { struct device *dev = &pdev->dev;
--
2.43.0