* [PATCH v12 net-next 1/9] octeontx2-af: npc: cn20k: debugfs enhancements
2026-05-08 3:49 [PATCH v12 net-next 0/9] octeontx2-af: npc: Enhancements Ratheesh Kannoth
@ 2026-05-08 3:49 ` Ratheesh Kannoth
2026-05-11 2:25 ` Ratheesh Kannoth
2026-05-08 3:49 ` [PATCH v12 net-next 2/9] net/mlx5e: trim stack use in PCIe congestion threshold helper Ratheesh Kannoth
` (7 subsequent siblings)
8 siblings, 1 reply; 22+ messages in thread
From: Ratheesh Kannoth @ 2026-05-08 3:49 UTC (permalink / raw)
To: intel-wired-lan, linux-kernel, linux-rdma, netdev, oss-drivers
Cc: akiyano, andrew+netdev, anthony.l.nguyen, arkadiusz.kubalewski,
brett.creeley, darinzon, davem, donald.hunter, edumazet, horms,
idosch, ivecera, jiri, kuba, leon, mbloch, michael.chan, pabeni,
pavan.chebbi, petrm, Prathosh.Satish, przemyslaw.kitszel, saeedm,
sgoutham, tariqt, vadim.fedorenko, Ratheesh Kannoth
Improve MCAM visibility and field debugging for CN20K NPC.
- Extend "mcam_layout" to show enabled (+) or disabled state per entry
so status can be verified without parsing the full "mcam_entry" dump.
- Add "dstats" debugfs entry: reports recently hit MCAM indices with
packet counts; stats are cleared on read so each read shows deltas.
- Add "mismatch" debugfs entry: lists MCAM entries that are enabled
but not explicitly allocated, helping diagnose allocation/field issues.
Signed-off-by: Ratheesh Kannoth <rkannoth@marvell.com>
---
.../marvell/octeontx2/af/cn20k/debugfs.c | 157 +++++++++++++++++-
.../ethernet/marvell/octeontx2/af/cn20k/npc.c | 16 +-
.../ethernet/marvell/octeontx2/af/cn20k/npc.h | 7 +
3 files changed, 169 insertions(+), 11 deletions(-)
diff --git a/drivers/net/ethernet/marvell/octeontx2/af/cn20k/debugfs.c b/drivers/net/ethernet/marvell/octeontx2/af/cn20k/debugfs.c
index 6f13296303cb..9a4c2ea5b19e 100644
--- a/drivers/net/ethernet/marvell/octeontx2/af/cn20k/debugfs.c
+++ b/drivers/net/ethernet/marvell/octeontx2/af/cn20k/debugfs.c
@@ -13,6 +13,7 @@
#include "struct.h"
#include "rvu.h"
#include "debugfs.h"
+#include "cn20k/reg.h"
#include "cn20k/npc.h"
static int npc_mcam_layout_show(struct seq_file *s, void *unused)
@@ -58,7 +59,8 @@ static int npc_mcam_layout_show(struct seq_file *s, void *unused)
"v:%u", vidx0);
}
- seq_printf(s, "\t%u(%#x) %s\n", idx0, pf1,
+ seq_printf(s, "\t%u(%#x)%c %s\n", idx0, pf1,
+ test_bit(idx0, npc_priv->en_map) ? '+' : ' ',
map ? buf0 : " ");
}
goto next;
@@ -101,9 +103,13 @@ static int npc_mcam_layout_show(struct seq_file *s, void *unused)
vidx1);
}
- seq_printf(s, "%05u(%#x) %s\t\t%05u(%#x) %s\n",
- idx1, pf2, v1 ? buf1 : " ",
- idx0, pf1, v0 ? buf0 : " ");
+ seq_printf(s, "%05u(%#x)%c %s\t\t%05u(%#x)%c %s\n",
+ idx1, pf2,
+ test_bit(idx1, npc_priv->en_map) ? '+' : ' ',
+ v1 ? buf1 : " ",
+ idx0, pf1,
+ test_bit(idx0, npc_priv->en_map) ? '+' : ' ',
+ v0 ? buf0 : " ");
continue;
}
@@ -120,8 +126,9 @@ static int npc_mcam_layout_show(struct seq_file *s, void *unused)
vidx0);
}
- seq_printf(s, "\t\t \t\t%05u(%#x) %s\n", idx0,
- pf1, map ? buf0 : " ");
+ seq_printf(s, "\t\t \t\t%05u(%#x)%c %s\n", idx0, pf1,
+ test_bit(idx0, npc_priv->en_map) ? '+' : ' ',
+ map ? buf0 : " ");
continue;
}
@@ -134,7 +141,8 @@ static int npc_mcam_layout_show(struct seq_file *s, void *unused)
snprintf(buf1, sizeof(buf1), "v:%05u", vidx1);
}
- seq_printf(s, "%05u(%#x) %s\n", idx1, pf1,
+ seq_printf(s, "%05u(%#x)%c %s\n", idx1, pf1,
+ test_bit(idx1, npc_priv->en_map) ? '+' : ' ',
map ? buf1 : " ");
}
next:
@@ -145,6 +153,135 @@ static int npc_mcam_layout_show(struct seq_file *s, void *unused)
DEFINE_SHOW_ATTRIBUTE(npc_mcam_layout);
+#define __OCTEONTX2_DEBUGFS_ATTRIBUTE_FOPS(__name) \
+static const struct file_operations __name ## _fops = { \
+ .owner = THIS_MODULE, \
+ .open = __name ## _open, \
+ .read = seq_read, \
+ .llseek = seq_lseek, \
+ .release = single_release, \
+}
+
+#define DEFINE_OCTEONTX2_DEBUGFS_ATTRIBUTE_WITH_SIZE(__name, __size) \
+static int __name ## _open(struct inode *inode, struct file *file) \
+{ \
+ return single_open_size(file, __name ## _show, inode->i_private, \
+ __size); \
+} \
+__OCTEONTX2_DEBUGFS_ATTRIBUTE_FOPS(__name)
+
+static DEFINE_MUTEX(stats_lock);
+
+static u64 dstats[MAX_NUM_BANKS][MAX_SUBBANK_DEPTH * MAX_NUM_SUB_BANKS] = {};
+static int npc_mcam_dstats_show(struct seq_file *s, void *unused)
+{
+ struct npc_priv_t *npc_priv;
+ int blkaddr, pf, mcam_idx;
+ u64 stats, delta;
+ struct rvu *rvu;
+ char buff[64];
+ u8 key_type;
+ void *map;
+
+ npc_priv = npc_priv_get();
+ rvu = s->private;
+ blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NPC, 0);
+ if (blkaddr < 0)
+ return 0;
+
+ mutex_lock(&stats_lock);
+ seq_puts(s, "idx\tpfunc\tstats\n");
+ for (int bank = npc_priv->num_banks - 1; bank >= 0; bank--) {
+ for (int idx = npc_priv->bank_depth - 1; idx >= 0; idx--) {
+ mcam_idx = bank * npc_priv->bank_depth + idx;
+
+ npc_mcam_idx_2_key_type(rvu, mcam_idx, &key_type);
+ if (key_type == NPC_MCAM_KEY_X4 && bank != 0)
+ continue;
+
+ if (!test_bit(mcam_idx, npc_priv->en_map))
+ continue;
+
+ stats = rvu_read64(rvu, blkaddr,
+ NPC_AF_CN20K_MCAMEX_BANKX_STAT_EXT(idx, bank));
+ if (!stats)
+ continue;
+ if (stats == dstats[bank][idx])
+ continue;
+
+ if (stats < dstats[bank][idx])
+ dstats[bank][idx] = 0;
+
+ pf = 0xFFFF;
+ map = xa_load(&npc_priv->xa_idx2pf_map, mcam_idx);
+ if (map)
+ pf = xa_to_value(map);
+
+ if (stats > dstats[bank][idx])
+ delta = stats - dstats[bank][idx];
+ else
+ delta = stats;
+
+ snprintf(buff, sizeof(buff), "%u\t%#04x\t%llu\n",
+ mcam_idx, pf, delta);
+ seq_puts(s, buff);
+
+ dstats[bank][idx] = stats;
+ }
+ }
+
+ mutex_unlock(&stats_lock);
+ return 0;
+}
+
+/* "%u\t%#04x\t%llu\n" needs less than 64 characters to print */
+#define TOTAL_SZ (MAX_NUM_BANKS * MAX_NUM_SUB_BANKS * MAX_SUBBANK_DEPTH * 64)
+DEFINE_OCTEONTX2_DEBUGFS_ATTRIBUTE_WITH_SIZE(npc_mcam_dstats, TOTAL_SZ);
+
+static int npc_mcam_mismatch_show(struct seq_file *s, void *unused)
+{
+ struct npc_priv_t *npc_priv;
+ struct npc_subbank *sb;
+ int mcam_idx, sb_off;
+ struct rvu *rvu;
+ char buff[64];
+ void *map;
+ int rc;
+
+ npc_priv = npc_priv_get();
+ rvu = s->private;
+
+ seq_puts(s, "index\tsb idx\tkw type\n");
+ mutex_lock(&stats_lock);
+ for (int bank = npc_priv->num_banks - 1; bank >= 0; bank--) {
+ for (int idx = npc_priv->bank_depth - 1; idx >= 0; idx--) {
+ mcam_idx = bank * npc_priv->bank_depth + idx;
+
+ if (!test_bit(mcam_idx, npc_priv->en_map))
+ continue;
+
+ map = xa_load(&npc_priv->xa_idx2pf_map, mcam_idx);
+ if (map)
+ continue;
+
+ rc = npc_mcam_idx_2_subbank_idx(rvu, mcam_idx,
+ &sb, &sb_off);
+ if (rc)
+ continue;
+
+ snprintf(buff, sizeof(buff), "%u\t%d\t%u\n",
+ mcam_idx, sb->idx, sb->key_type);
+
+ seq_puts(s, buff);
+ }
+ }
+ mutex_unlock(&stats_lock);
+ return 0;
+}
+
+/* "%u\t%d\t%u\n" needs less than 64 characters to print. */
+DEFINE_OCTEONTX2_DEBUGFS_ATTRIBUTE_WITH_SIZE(npc_mcam_mismatch, TOTAL_SZ);
+
static int npc_mcam_default_show(struct seq_file *s, void *unused)
{
struct npc_priv_t *npc_priv;
@@ -259,6 +396,12 @@ int npc_cn20k_debugfs_init(struct rvu *rvu)
debugfs_create_file("vidx2idx", 0444, rvu->rvu_dbg.npc,
npc_priv, &npc_vidx2idx_map_fops);
+ debugfs_create_file("dstats", 0444, rvu->rvu_dbg.npc, rvu,
+ &npc_mcam_dstats_fops);
+
+ debugfs_create_file("mismatch", 0444, rvu->rvu_dbg.npc, rvu,
+ &npc_mcam_mismatch_fops);
+
debugfs_create_file("idx2vidx", 0444, rvu->rvu_dbg.npc,
npc_priv, &npc_idx2vidx_map_fops);
diff --git a/drivers/net/ethernet/marvell/octeontx2/af/cn20k/npc.c b/drivers/net/ethernet/marvell/octeontx2/af/cn20k/npc.c
index 6b3f453fd500..e9aad0ad3fa6 100644
--- a/drivers/net/ethernet/marvell/octeontx2/af/cn20k/npc.c
+++ b/drivers/net/ethernet/marvell/octeontx2/af/cn20k/npc.c
@@ -824,7 +824,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 0;
+ goto update_en_map;
}
/* For NPC_CN20K_MCAM_KEY_X4 keys, both the banks
@@ -842,6 +842,12 @@ npc_cn20k_enable_mcam_entry(struct rvu *rvu, int blkaddr,
cfg);
}
+update_en_map:
+ if (enable)
+ set_bit(index, npc_priv.en_map);
+ else
+ clear_bit(index, npc_priv.en_map);
+
return 0;
}
@@ -1789,9 +1795,9 @@ static int npc_subbank_idx_2_mcam_idx(struct rvu *rvu, struct npc_subbank *sb,
return 0;
}
-static int npc_mcam_idx_2_subbank_idx(struct rvu *rvu, u16 mcam_idx,
- struct npc_subbank **sb,
- int *sb_off)
+int npc_mcam_idx_2_subbank_idx(struct rvu *rvu, u16 mcam_idx,
+ struct npc_subbank **sb,
+ int *sb_off)
{
int bank_off, sb_id;
@@ -4605,6 +4611,8 @@ void npc_cn20k_deinit(struct rvu *rvu)
*/
kfree(npc_priv.sb);
kfree(subbank_srch_order);
+ bitmap_clear(npc_priv.en_map, 0, MAX_NUM_BANKS * MAX_NUM_SUB_BANKS *
+ MAX_SUBBANK_DEPTH);
}
static int npc_setup_mcam_section(struct rvu *rvu, int key_type)
diff --git a/drivers/net/ethernet/marvell/octeontx2/af/cn20k/npc.h b/drivers/net/ethernet/marvell/octeontx2/af/cn20k/npc.h
index 3d5eb952cc07..9567a2d80b58 100644
--- a/drivers/net/ethernet/marvell/octeontx2/af/cn20k/npc.h
+++ b/drivers/net/ethernet/marvell/octeontx2/af/cn20k/npc.h
@@ -170,6 +170,7 @@ struct npc_defrag_show_node {
* @num_banks: Number of banks.
* @num_subbanks: Number of subbanks.
* @subbank_depth: Depth of subbank.
+ * @en_map: Enable/disable status.
* @kw: Kex configured key type.
* @sb: Subbank array.
* @xa_sb_used: Array of used subbanks.
@@ -193,6 +194,9 @@ struct npc_priv_t {
const int num_banks;
int num_subbanks;
int subbank_depth;
+ DECLARE_BITMAP(en_map, MAX_NUM_BANKS *
+ MAX_NUM_SUB_BANKS *
+ MAX_SUBBANK_DEPTH);
u8 kw;
struct npc_subbank *sb;
struct xarray xa_sb_used;
@@ -336,5 +340,8 @@ u16 npc_cn20k_vidx2idx(u16 index);
u16 npc_cn20k_idx2vidx(u16 idx);
int npc_cn20k_defrag(struct rvu *rvu);
bool npc_is_cgx_or_lbk(struct rvu *rvu, u16 pcifunc);
+int npc_mcam_idx_2_subbank_idx(struct rvu *rvu, u16 mcam_idx,
+ struct npc_subbank **sb,
+ int *sb_off);
#endif /* NPC_CN20K_H */
--
2.43.0
^ permalink raw reply related [flat|nested] 22+ messages in thread* Re: [PATCH v12 net-next 1/9] octeontx2-af: npc: cn20k: debugfs enhancements
2026-05-08 3:49 ` [PATCH v12 net-next 1/9] octeontx2-af: npc: cn20k: debugfs enhancements Ratheesh Kannoth
@ 2026-05-11 2:25 ` Ratheesh Kannoth
0 siblings, 0 replies; 22+ messages in thread
From: Ratheesh Kannoth @ 2026-05-11 2:25 UTC (permalink / raw)
To: intel-wired-lan, linux-kernel, linux-rdma, netdev, oss-drivers
Cc: akiyano, andrew+netdev, anthony.l.nguyen, arkadiusz.kubalewski,
brett.creeley, darinzon, davem, donald.hunter, edumazet, horms,
idosch, ivecera, jiri, kuba, leon, mbloch, michael.chan, pabeni,
pavan.chebbi, petrm, Prathosh.Satish, przemyslaw.kitszel, saeedm,
sgoutham, tariqt, vadim.fedorenko
On 2026-05-08 at 09:19:04, Ratheesh Kannoth (rkannoth@marvell.com) wrote:
> Improve MCAM visibility and field debugging for CN20K NPC.
>
> - Extend "mcam_layout" to show enabled (+) or disabled state per entry
> so status can be verified without parsing the full "mcam_entry" dump.
> - Add "dstats" debugfs entry: reports recently hit MCAM indices with
> packet counts; stats are cleared on read so each read shows deltas.
> - Add "mismatch" debugfs entry: lists MCAM entries that are enabled
> but not explicitly allocated, helping diagnose allocation/field issues.
>
> Signed-off-by: Ratheesh Kannoth <rkannoth@marvell.com>
>+
>> + snprintf(buff, sizeof(buff), "%u\t%#04x\t%llu\n",
>> + mcam_idx, pf, delta);
>> + seq_puts(s, buff);
>> +
>> + dstats[bank][idx] = stats;
>> + }
>> + }
>> +
>> + mutex_unlock(&stats_lock);
>> + return 0;
>> +}
>> +
>> +/* "%u\t%#04x\t%llu\n" needs less than 64 characters to print */
>> +#define TOTAL_SZ (MAX_NUM_BANKS * MAX_NUM_SUB_BANKS * MAX_SUBBANK_DEPTH * 64)
>> +DEFINE_OCTEONTX2_DEBUGFS_ATTRIBUTE_WITH_SIZE(npc_mcam_dstats, TOTAL_SZ);
>Will this single_open_size() allocation reliably succeed on a running system?
>Because single_open_size() uses kmalloc(), it requires a physically
>contiguous memory block. TOTAL_SZ is the product of multiple maximum
>hardware limits, which can be hundreds of kilobytes. This could result
>in a high-order allocation that fails with an out of memory error due to
>fragmentation.
No. single_open_size() is calling seq_buf_alloc() which uses kvmalloc.
^ permalink raw reply [flat|nested] 22+ messages in thread
* [PATCH v12 net-next 2/9] net/mlx5e: trim stack use in PCIe congestion threshold helper
2026-05-08 3:49 [PATCH v12 net-next 0/9] octeontx2-af: npc: Enhancements Ratheesh Kannoth
2026-05-08 3:49 ` [PATCH v12 net-next 1/9] octeontx2-af: npc: cn20k: debugfs enhancements Ratheesh Kannoth
@ 2026-05-08 3:49 ` Ratheesh Kannoth
2026-05-08 9:02 ` David Laight
2026-05-08 3:49 ` [PATCH v12 net-next 3/9] devlink: pass param values by pointer Ratheesh Kannoth
` (6 subsequent siblings)
8 siblings, 1 reply; 22+ messages in thread
From: Ratheesh Kannoth @ 2026-05-08 3:49 UTC (permalink / raw)
To: intel-wired-lan, linux-kernel, linux-rdma, netdev, oss-drivers
Cc: akiyano, andrew+netdev, anthony.l.nguyen, arkadiusz.kubalewski,
brett.creeley, darinzon, davem, donald.hunter, edumazet, horms,
idosch, ivecera, jiri, kuba, leon, mbloch, michael.chan, pabeni,
pavan.chebbi, petrm, Prathosh.Satish, przemyslaw.kitszel, saeedm,
sgoutham, tariqt, vadim.fedorenko, Ratheesh Kannoth
union devlink_param_value grew when U64 array parameters were added.
Keeping a four-element array of that union in
mlx5e_pcie_cong_get_thresh_config() inflated the stack frame past the
-Wframe-larger-than limit.
Read each driverinit value into a single reused union, then store the
four u16 thresholds in struct mlx5e_pcie_cong_thresh field order via a
temporary u16 pointer to config.
Signed-off-by: Ratheesh Kannoth <rkannoth@marvell.com>
---
.../mellanox/mlx5/core/en/pcie_cong_event.c | 34 +++++++++++--------
1 file changed, 19 insertions(+), 15 deletions(-)
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/pcie_cong_event.c b/drivers/net/ethernet/mellanox/mlx5/core/en/pcie_cong_event.c
index 2eb666a46f39..88e76be3a73d 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en/pcie_cong_event.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en/pcie_cong_event.c
@@ -252,28 +252,32 @@ static int
mlx5e_pcie_cong_get_thresh_config(struct mlx5_core_dev *dev,
struct mlx5e_pcie_cong_thresh *config)
{
+ enum {
+ INBOUND_HIGH,
+ INBOUND_LOW,
+ OUTBOUND_HIGH,
+ OUTBOUND_LOW,
+ };
+
u32 ids[4] = {
- MLX5_DEVLINK_PARAM_ID_PCIE_CONG_IN_LOW,
- MLX5_DEVLINK_PARAM_ID_PCIE_CONG_IN_HIGH,
- MLX5_DEVLINK_PARAM_ID_PCIE_CONG_OUT_LOW,
- MLX5_DEVLINK_PARAM_ID_PCIE_CONG_OUT_HIGH,
+ [INBOUND_LOW] = MLX5_DEVLINK_PARAM_ID_PCIE_CONG_IN_LOW,
+ [INBOUND_HIGH] = MLX5_DEVLINK_PARAM_ID_PCIE_CONG_IN_HIGH,
+ [OUTBOUND_LOW] = MLX5_DEVLINK_PARAM_ID_PCIE_CONG_OUT_LOW,
+ [OUTBOUND_HIGH] = MLX5_DEVLINK_PARAM_ID_PCIE_CONG_OUT_HIGH,
};
- struct devlink *devlink = priv_to_devlink(dev);
- union devlink_param_value val[4];
- for (int i = 0; i < 4; i++) {
- u32 id = ids[i];
- int err;
+ struct devlink *devlink = priv_to_devlink(dev);
+ union devlink_param_value val;
+ u16 *dst = (u16 *)config;
+ int err;
- err = devl_param_driverinit_value_get(devlink, id, &val[i]);
+ for (int i = 0; i < ARRAY_SIZE(ids); i++) {
+ err = devl_param_driverinit_value_get(devlink, ids[i], &val);
if (err)
return err;
- }
- config->inbound_low = val[0].vu16;
- config->inbound_high = val[1].vu16;
- config->outbound_low = val[2].vu16;
- config->outbound_high = val[3].vu16;
+ dst[i] = val.vu16;
+ }
return 0;
}
--
2.43.0
^ permalink raw reply related [flat|nested] 22+ messages in thread* Re: [PATCH v12 net-next 2/9] net/mlx5e: trim stack use in PCIe congestion threshold helper
2026-05-08 3:49 ` [PATCH v12 net-next 2/9] net/mlx5e: trim stack use in PCIe congestion threshold helper Ratheesh Kannoth
@ 2026-05-08 9:02 ` David Laight
0 siblings, 0 replies; 22+ messages in thread
From: David Laight @ 2026-05-08 9:02 UTC (permalink / raw)
To: Ratheesh Kannoth
Cc: intel-wired-lan, linux-kernel, linux-rdma, netdev, oss-drivers,
akiyano, andrew+netdev, anthony.l.nguyen, arkadiusz.kubalewski,
brett.creeley, darinzon, davem, donald.hunter, edumazet, horms,
idosch, ivecera, jiri, kuba, leon, mbloch, michael.chan, pabeni,
pavan.chebbi, petrm, Prathosh.Satish, przemyslaw.kitszel, saeedm,
sgoutham, tariqt, vadim.fedorenko
On Fri, 8 May 2026 09:19:05 +0530
Ratheesh Kannoth <rkannoth@marvell.com> wrote:
> union devlink_param_value grew when U64 array parameters were added.
> Keeping a four-element array of that union in
> mlx5e_pcie_cong_get_thresh_config() inflated the stack frame past the
> -Wframe-larger-than limit.
>
> Read each driverinit value into a single reused union, then store the
> four u16 thresholds in struct mlx5e_pcie_cong_thresh field order via a
> temporary u16 pointer to config.
>
> Signed-off-by: Ratheesh Kannoth <rkannoth@marvell.com>
> ---
> .../mellanox/mlx5/core/en/pcie_cong_event.c | 34 +++++++++++--------
> 1 file changed, 19 insertions(+), 15 deletions(-)
>
> diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/pcie_cong_event.c b/drivers/net/ethernet/mellanox/mlx5/core/en/pcie_cong_event.c
> index 2eb666a46f39..88e76be3a73d 100644
> --- a/drivers/net/ethernet/mellanox/mlx5/core/en/pcie_cong_event.c
> +++ b/drivers/net/ethernet/mellanox/mlx5/core/en/pcie_cong_event.c
> @@ -252,28 +252,32 @@ static int
> mlx5e_pcie_cong_get_thresh_config(struct mlx5_core_dev *dev,
> struct mlx5e_pcie_cong_thresh *config)
> {
> + enum {
> + INBOUND_HIGH,
> + INBOUND_LOW,
> + OUTBOUND_HIGH,
> + OUTBOUND_LOW,
> + };
> +
> u32 ids[4] = {
Someone will suggest that should be 'static const'.
It may make the code smaller.
> - MLX5_DEVLINK_PARAM_ID_PCIE_CONG_IN_LOW,
> - MLX5_DEVLINK_PARAM_ID_PCIE_CONG_IN_HIGH,
> - MLX5_DEVLINK_PARAM_ID_PCIE_CONG_OUT_LOW,
> - MLX5_DEVLINK_PARAM_ID_PCIE_CONG_OUT_HIGH,
> + [INBOUND_LOW] = MLX5_DEVLINK_PARAM_ID_PCIE_CONG_IN_LOW,
> + [INBOUND_HIGH] = MLX5_DEVLINK_PARAM_ID_PCIE_CONG_IN_HIGH,
> + [OUTBOUND_LOW] = MLX5_DEVLINK_PARAM_ID_PCIE_CONG_OUT_LOW,
> + [OUTBOUND_HIGH] = MLX5_DEVLINK_PARAM_ID_PCIE_CONG_OUT_HIGH,
> };
> - struct devlink *devlink = priv_to_devlink(dev);
> - union devlink_param_value val[4];
>
> - for (int i = 0; i < 4; i++) {
> - u32 id = ids[i];
> - int err;
> + struct devlink *devlink = priv_to_devlink(dev);
> + union devlink_param_value val;
> + u16 *dst = (u16 *)config;
You can't do that - far too fragile.
Maybe &config->inbound_low - but even that assumes the values are in order.
A safer way would be using a temporary 'u16 val16[4]'.
(Or even overwrite ids[] with the result.)
But the code might even be smaller if you just unroll the loop:
err = devl_param_driverinit_value_get(devlink, MLX5_DEVLINK_PARAM_ID_PCIE_CONG_IN_LOW, &val);
if (err)
return err;
config->inbound_low = val.vu16;
err = devl_param_driverinit_value_get(devlink, MLX5_DEVLINK_PARAM_ID_PCIE_CONG_IN_HIGH, &val);
if (err)
return err;
config->inbound_high = val.vu16;
err = devl_param_driverinit_value_get(devlink, MLX5_DEVLINK_PARAM_ID_PCIE_CONG_OUT_LOW, &val);
if (err)
return err;
config->outbound_low = val.vu16;
err = devl_param_driverinit_value_get(devlink, MLX5_DEVLINK_PARAM_ID_PCIE_CONG_OUT_HIGH, &val);
if (err)
return err;
config->outbound_high = val.vu16;
-- David
> + int err;
>
> - err = devl_param_driverinit_value_get(devlink, id, &val[i]);
> + for (int i = 0; i < ARRAY_SIZE(ids); i++) {
> + err = devl_param_driverinit_value_get(devlink, ids[i], &val);
> if (err)
> return err;
> - }
>
> - config->inbound_low = val[0].vu16;
> - config->inbound_high = val[1].vu16;
> - config->outbound_low = val[2].vu16;
> - config->outbound_high = val[3].vu16;
> + dst[i] = val.vu16;
> + }
>
> return 0;
> }
^ permalink raw reply [flat|nested] 22+ messages in thread
* [PATCH v12 net-next 3/9] devlink: pass param values by pointer
2026-05-08 3:49 [PATCH v12 net-next 0/9] octeontx2-af: npc: Enhancements Ratheesh Kannoth
2026-05-08 3:49 ` [PATCH v12 net-next 1/9] octeontx2-af: npc: cn20k: debugfs enhancements Ratheesh Kannoth
2026-05-08 3:49 ` [PATCH v12 net-next 2/9] net/mlx5e: trim stack use in PCIe congestion threshold helper Ratheesh Kannoth
@ 2026-05-08 3:49 ` Ratheesh Kannoth
2026-05-11 13:39 ` Przemek Kitszel
2026-05-08 3:49 ` [PATCH v12 net-next 4/9] devlink: Implement devlink param multi attribute nested data values Ratheesh Kannoth
` (5 subsequent siblings)
8 siblings, 1 reply; 22+ messages in thread
From: Ratheesh Kannoth @ 2026-05-08 3:49 UTC (permalink / raw)
To: intel-wired-lan, linux-kernel, linux-rdma, netdev, oss-drivers
Cc: akiyano, andrew+netdev, anthony.l.nguyen, arkadiusz.kubalewski,
brett.creeley, darinzon, davem, donald.hunter, edumazet, horms,
idosch, ivecera, jiri, kuba, leon, mbloch, michael.chan, pabeni,
pavan.chebbi, petrm, Prathosh.Satish, przemyslaw.kitszel, saeedm,
sgoutham, tariqt, vadim.fedorenko, Ratheesh Kannoth
union devlink_param_value grows substantially once U64 array
parameters are added to devlink (from 32 bytes to over 264 bytes).
devlink_nl_param_value_fill_one() and devlink_nl_param_value_put()
copy the union by value in several places. Passing two instances as
value arguments alone consumes over 528 bytes of stack; combined with
deeper call chains the parameter stack can approach 800 bytes and trip
CONFIG_FRAME_WARN more easily.
Switch internal helpers and exported driver APIs to pass pointers to
union devlink_param_value rather than passing the union by value.
Signed-off-by: Ratheesh Kannoth <rkannoth@marvell.com>
---
drivers/dpll/zl3073x/devlink.c | 6 +-
drivers/net/ethernet/amazon/ena/ena_devlink.c | 8 +--
drivers/net/ethernet/amd/pds_core/core.h | 2 +-
drivers/net/ethernet/amd/pds_core/devlink.c | 2 +-
.../net/ethernet/broadcom/bnxt/bnxt_devlink.c | 6 +-
.../net/ethernet/intel/ice/devlink/devlink.c | 30 ++++----
.../marvell/octeontx2/af/rvu_devlink.c | 22 +++---
.../marvell/octeontx2/nic/otx2_devlink.c | 4 +-
drivers/net/ethernet/mellanox/mlx4/main.c | 14 ++--
.../net/ethernet/mellanox/mlx5/core/devlink.c | 72 +++++++++----------
.../mellanox/mlx5/core/eswitch_offloads.c | 2 +-
.../net/ethernet/mellanox/mlx5/core/fs_core.c | 4 +-
.../mellanox/mlx5/core/lib/nv_param.c | 12 ++--
drivers/net/ethernet/mellanox/mlxsw/core.c | 8 +--
.../ethernet/netronome/nfp/devlink_param.c | 6 +-
drivers/net/netdevsim/dev.c | 4 +-
include/net/devlink.h | 4 +-
net/devlink/param.c | 32 ++++-----
18 files changed, 119 insertions(+), 119 deletions(-)
diff --git a/drivers/dpll/zl3073x/devlink.c b/drivers/dpll/zl3073x/devlink.c
index ccc22332b346..218b08fd8a30 100644
--- a/drivers/dpll/zl3073x/devlink.c
+++ b/drivers/dpll/zl3073x/devlink.c
@@ -315,10 +315,10 @@ EXPORT_SYMBOL_NS_GPL(zl3073x_devm_alloc, "ZL3073X");
static int
zl3073x_devlink_param_clock_id_validate(struct devlink *devlink, u32 id,
- union devlink_param_value val,
+ union devlink_param_value *val,
struct netlink_ext_ack *extack)
{
- if (!val.vu64) {
+ if (!val->vu64) {
NL_SET_ERR_MSG_MOD(extack, "'clock_id' must be non-zero");
return -EINVAL;
}
@@ -377,7 +377,7 @@ int zl3073x_devlink_register(struct zl3073x_dev *zldev)
value.vu64 = zldev->clock_id;
devl_param_driverinit_value_set(devlink,
DEVLINK_PARAM_GENERIC_ID_CLOCK_ID,
- value);
+ &value);
/* Register devlink instance */
devl_register(devlink);
diff --git a/drivers/net/ethernet/amazon/ena/ena_devlink.c b/drivers/net/ethernet/amazon/ena/ena_devlink.c
index 4772185e669d..5ea9fef149aa 100644
--- a/drivers/net/ethernet/amazon/ena/ena_devlink.c
+++ b/drivers/net/ethernet/amazon/ena/ena_devlink.c
@@ -8,12 +8,12 @@
#include "ena_phc.h"
static int ena_devlink_enable_phc_validate(struct devlink *devlink, u32 id,
- union devlink_param_value val,
+ union devlink_param_value *val,
struct netlink_ext_ack *extack)
{
struct ena_adapter *adapter = ENA_DEVLINK_PRIV(devlink);
- if (!val.vbool)
+ if (!val->vbool)
return 0;
if (!ena_com_phc_supported(adapter->ena_dev)) {
@@ -57,7 +57,7 @@ void ena_devlink_disable_phc_param(struct devlink *devlink)
value.vbool = false;
devl_param_driverinit_value_set(devlink,
DEVLINK_PARAM_GENERIC_ID_ENABLE_PHC,
- value);
+ &value);
devl_unlock(devlink);
}
@@ -151,7 +151,7 @@ static int ena_devlink_configure_params(struct devlink *devlink)
value.vbool = ena_phc_is_enabled(adapter);
devl_param_driverinit_value_set(devlink,
DEVLINK_PARAM_GENERIC_ID_ENABLE_PHC,
- value);
+ &value);
devl_unlock(devlink);
return 0;
diff --git a/drivers/net/ethernet/amd/pds_core/core.h b/drivers/net/ethernet/amd/pds_core/core.h
index 4a6b35c84dab..b7fe9ad73349 100644
--- a/drivers/net/ethernet/amd/pds_core/core.h
+++ b/drivers/net/ethernet/amd/pds_core/core.h
@@ -261,7 +261,7 @@ int pdsc_dl_enable_set(struct devlink *dl, u32 id,
struct devlink_param_gset_ctx *ctx,
struct netlink_ext_ack *extack);
int pdsc_dl_enable_validate(struct devlink *dl, u32 id,
- union devlink_param_value val,
+ union devlink_param_value *val,
struct netlink_ext_ack *extack);
void __iomem *pdsc_map_dbpage(struct pdsc *pdsc, int page_num);
diff --git a/drivers/net/ethernet/amd/pds_core/devlink.c b/drivers/net/ethernet/amd/pds_core/devlink.c
index b576be626a29..fe0595d31683 100644
--- a/drivers/net/ethernet/amd/pds_core/devlink.c
+++ b/drivers/net/ethernet/amd/pds_core/devlink.c
@@ -68,7 +68,7 @@ int pdsc_dl_enable_set(struct devlink *dl, u32 id,
}
int pdsc_dl_enable_validate(struct devlink *dl, u32 id,
- union devlink_param_value val,
+ union devlink_param_value *val,
struct netlink_ext_ack *extack)
{
struct pdsc *pdsc = devlink_priv(dl);
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_devlink.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_devlink.c
index 835f2b413931..eb17a3454b4c 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt_devlink.c
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_devlink.c
@@ -1123,7 +1123,7 @@ static int bnxt_dl_nvm_param_set(struct devlink *dl, u32 id,
}
static int bnxt_dl_roce_validate(struct devlink *dl, u32 id,
- union devlink_param_value val,
+ union devlink_param_value *val,
struct netlink_ext_ack *extack)
{
const struct bnxt_dl_nvm_param nvm_roce_cap = {0, NVM_OFF_RDMA_CAPABLE,
@@ -1149,7 +1149,7 @@ static int bnxt_dl_roce_validate(struct devlink *dl, u32 id,
}
static int bnxt_dl_msix_validate(struct devlink *dl, u32 id,
- union devlink_param_value val,
+ union devlink_param_value *val,
struct netlink_ext_ack *extack)
{
int max_val = -1;
@@ -1160,7 +1160,7 @@ static int bnxt_dl_msix_validate(struct devlink *dl, u32 id,
if (id == DEVLINK_PARAM_GENERIC_ID_MSIX_VEC_PER_PF_MIN)
max_val = BNXT_MSIX_VEC_MIN_MAX;
- if (val.vu32 > max_val) {
+ if (val->vu32 > max_val) {
NL_SET_ERR_MSG_MOD(extack, "MSIX value is exceeding the range");
return -EINVAL;
}
diff --git a/drivers/net/ethernet/intel/ice/devlink/devlink.c b/drivers/net/ethernet/intel/ice/devlink/devlink.c
index 641d6e289d5c..22b7d8e6bd9e 100644
--- a/drivers/net/ethernet/intel/ice/devlink/devlink.c
+++ b/drivers/net/ethernet/intel/ice/devlink/devlink.c
@@ -671,10 +671,10 @@ static int ice_devlink_tx_sched_layers_set(struct devlink *devlink, u32 id,
* error.
*/
static int ice_devlink_tx_sched_layers_validate(struct devlink *devlink, u32 id,
- union devlink_param_value val,
+ union devlink_param_value *val,
struct netlink_ext_ack *extack)
{
- if (val.vu8 != ICE_SCHED_5_LAYERS && val.vu8 != ICE_SCHED_9_LAYERS) {
+ if (val->vu8 != ICE_SCHED_5_LAYERS && val->vu8 != ICE_SCHED_9_LAYERS) {
NL_SET_ERR_MSG_MOD(extack,
"Wrong number of tx scheduler layers provided.");
return -EINVAL;
@@ -1398,7 +1398,7 @@ static int ice_devlink_enable_roce_set(struct devlink *devlink, u32 id,
static int
ice_devlink_enable_roce_validate(struct devlink *devlink, u32 id,
- union devlink_param_value val,
+ union devlink_param_value *val,
struct netlink_ext_ack *extack)
{
struct ice_pf *pf = devlink_priv(devlink);
@@ -1465,7 +1465,7 @@ static int ice_devlink_enable_iw_set(struct devlink *devlink, u32 id,
static int
ice_devlink_enable_iw_validate(struct devlink *devlink, u32 id,
- union devlink_param_value val,
+ union devlink_param_value *val,
struct netlink_ext_ack *extack)
{
struct ice_pf *pf = devlink_priv(devlink);
@@ -1591,10 +1591,10 @@ static int ice_devlink_local_fwd_set(struct devlink *devlink, u32 id,
* error.
*/
static int ice_devlink_local_fwd_validate(struct devlink *devlink, u32 id,
- union devlink_param_value val,
+ union devlink_param_value *val,
struct netlink_ext_ack *extack)
{
- if (ice_devlink_local_fwd_str_to_mode(val.vstr) < 0) {
+ if (ice_devlink_local_fwd_str_to_mode(val->vstr) < 0) {
NL_SET_ERR_MSG_MOD(extack, "Error: Requested value is not supported.");
return -EINVAL;
}
@@ -1604,12 +1604,12 @@ static int ice_devlink_local_fwd_validate(struct devlink *devlink, u32 id,
static int
ice_devlink_msix_max_pf_validate(struct devlink *devlink, u32 id,
- union devlink_param_value val,
+ union devlink_param_value *val,
struct netlink_ext_ack *extack)
{
struct ice_pf *pf = devlink_priv(devlink);
- if (val.vu32 > pf->hw.func_caps.common_cap.num_msix_vectors)
+ if (val->vu32 > pf->hw.func_caps.common_cap.num_msix_vectors)
return -EINVAL;
return 0;
@@ -1617,21 +1617,21 @@ ice_devlink_msix_max_pf_validate(struct devlink *devlink, u32 id,
static int
ice_devlink_msix_min_pf_validate(struct devlink *devlink, u32 id,
- union devlink_param_value val,
+ union devlink_param_value *val,
struct netlink_ext_ack *extack)
{
- if (val.vu32 < ICE_MIN_MSIX)
+ if (val->vu32 < ICE_MIN_MSIX)
return -EINVAL;
return 0;
}
static int ice_devlink_enable_rdma_validate(struct devlink *devlink, u32 id,
- union devlink_param_value val,
+ union devlink_param_value *val,
struct netlink_ext_ack *extack)
{
struct ice_pf *pf = devlink_priv(devlink);
- bool new_state = val.vbool;
+ bool new_state = val->vbool;
if (new_state && !test_bit(ICE_FLAG_RDMA_ENA, pf->flags))
return -EOPNOTSUPP;
@@ -1791,16 +1791,16 @@ int ice_devlink_register_params(struct ice_pf *pf)
value.vu32 = pf->msix.max;
devl_param_driverinit_value_set(devlink,
DEVLINK_PARAM_GENERIC_ID_MSIX_VEC_PER_PF_MAX,
- value);
+ &value);
value.vu32 = pf->msix.min;
devl_param_driverinit_value_set(devlink,
DEVLINK_PARAM_GENERIC_ID_MSIX_VEC_PER_PF_MIN,
- value);
+ &value);
value.vbool = test_bit(ICE_FLAG_RDMA_ENA, pf->flags);
devl_param_driverinit_value_set(devlink,
DEVLINK_PARAM_GENERIC_ID_ENABLE_RDMA,
- value);
+ &value);
return 0;
diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_devlink.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu_devlink.c
index 6494a9ee2f0d..a42404e6db7c 100644
--- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_devlink.c
+++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_devlink.c
@@ -1180,12 +1180,12 @@ static void rvu_health_reporters_destroy(struct rvu *rvu)
/* Devlink Params APIs */
static int rvu_af_dl_dwrr_mtu_validate(struct devlink *devlink, u32 id,
- union devlink_param_value val,
+ union devlink_param_value *val,
struct netlink_ext_ack *extack)
{
struct rvu_devlink *rvu_dl = devlink_priv(devlink);
struct rvu *rvu = rvu_dl->rvu;
- int dwrr_mtu = val.vu32;
+ int dwrr_mtu = val->vu32;
struct nix_txsch *txsch;
struct nix_hw *nix_hw;
@@ -1295,14 +1295,14 @@ static int rvu_af_npc_defrag(struct devlink *devlink, u32 id,
}
static int rvu_af_npc_defrag_feature_validate(struct devlink *devlink, u32 id,
- union devlink_param_value val,
+ 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)) {
+ if (kstrtoull(val->vstr, 10, &enable)) {
NL_SET_ERR_MSG_MOD(extack,
"Only 1 value is supported");
return -EINVAL;
@@ -1351,14 +1351,14 @@ static int rvu_af_npc_exact_feature_disable(struct devlink *devlink, u32 id,
}
static int rvu_af_npc_exact_feature_validate(struct devlink *devlink, u32 id,
- union devlink_param_value val,
+ 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)) {
+ if (kstrtoull(val->vstr, 10, &enable)) {
NL_SET_ERR_MSG_MOD(extack,
"Only 1 value is supported");
return -EINVAL;
@@ -1414,7 +1414,7 @@ static int rvu_af_dl_npc_mcam_high_zone_percent_set(struct devlink *devlink, u32
}
static int rvu_af_dl_npc_mcam_high_zone_percent_validate(struct devlink *devlink, u32 id,
- union devlink_param_value val,
+ union devlink_param_value *val,
struct netlink_ext_ack *extack)
{
struct rvu_devlink *rvu_dl = devlink_priv(devlink);
@@ -1422,7 +1422,7 @@ static int rvu_af_dl_npc_mcam_high_zone_percent_validate(struct devlink *devlink
struct npc_mcam *mcam;
/* The percent of high prio zone must range from 12% to 100% of unreserved mcam space */
- if (val.vu8 < 12 || val.vu8 > 100) {
+ if (val->vu8 < 12 || val->vu8 > 100) {
NL_SET_ERR_MSG_MOD(extack,
"mcam high zone percent must be between 12% to 100%");
return -EINVAL;
@@ -1504,7 +1504,7 @@ static int rvu_af_dl_nix_maxlf_set(struct devlink *devlink, u32 id,
}
static int rvu_af_dl_nix_maxlf_validate(struct devlink *devlink, u32 id,
- union devlink_param_value val,
+ union devlink_param_value *val,
struct netlink_ext_ack *extack)
{
struct rvu_devlink *rvu_dl = devlink_priv(devlink);
@@ -1528,13 +1528,13 @@ static int rvu_af_dl_nix_maxlf_validate(struct devlink *devlink, u32 id,
return -EPERM;
}
- if (max_nix0_lf && val.vu16 > max_nix0_lf) {
+ if (max_nix0_lf && val->vu16 > max_nix0_lf) {
NL_SET_ERR_MSG_MOD(extack,
"requested nixlf is greater than the max supported nix0_lf");
return -EPERM;
}
- if (max_nix1_lf && val.vu16 > max_nix1_lf) {
+ if (max_nix1_lf && val->vu16 > max_nix1_lf) {
NL_SET_ERR_MSG_MOD(extack,
"requested nixlf is greater than the max supported nix1_lf");
return -EINVAL;
diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_devlink.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_devlink.c
index a72694219df4..4a5ce0e67dda 100644
--- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_devlink.c
+++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_devlink.c
@@ -8,7 +8,7 @@
/* Devlink Params APIs */
static int otx2_dl_mcam_count_validate(struct devlink *devlink, u32 id,
- union devlink_param_value val,
+ union devlink_param_value *val,
struct netlink_ext_ack *extack)
{
struct otx2_devlink *otx2_dl = devlink_priv(devlink);
@@ -97,7 +97,7 @@ static int otx2_dl_ucast_flt_cnt_get(struct devlink *devlink, u32 id,
}
static int otx2_dl_ucast_flt_cnt_validate(struct devlink *devlink, u32 id,
- union devlink_param_value val,
+ union devlink_param_value *val,
struct netlink_ext_ack *extack)
{
struct otx2_devlink *otx2_dl = devlink_priv(devlink);
diff --git a/drivers/net/ethernet/mellanox/mlx4/main.c b/drivers/net/ethernet/mellanox/mlx4/main.c
index e6b7e75894ff..401bef135a90 100644
--- a/drivers/net/ethernet/mellanox/mlx4/main.c
+++ b/drivers/net/ethernet/mellanox/mlx4/main.c
@@ -213,10 +213,10 @@ static int mlx4_devlink_crdump_snapshot_set(struct devlink *devlink, u32 id,
static int
mlx4_devlink_max_macs_validate(struct devlink *devlink, u32 id,
- union devlink_param_value val,
+ union devlink_param_value *val,
struct netlink_ext_ack *extack)
{
- u32 value = val.vu32;
+ u32 value = val->vu32;
if (value < 1 || value > 128)
return -ERANGE;
@@ -266,27 +266,27 @@ static void mlx4_devlink_set_params_init_values(struct devlink *devlink)
value.vbool = !!mlx4_internal_err_reset;
devl_param_driverinit_value_set(devlink,
DEVLINK_PARAM_GENERIC_ID_INT_ERR_RESET,
- value);
+ &value);
value.vu32 = 1UL << log_num_mac;
devl_param_driverinit_value_set(devlink,
DEVLINK_PARAM_GENERIC_ID_MAX_MACS,
- value);
+ &value);
value.vbool = enable_64b_cqe_eqe;
devl_param_driverinit_value_set(devlink,
MLX4_DEVLINK_PARAM_ID_ENABLE_64B_CQE_EQE,
- value);
+ &value);
value.vbool = enable_4k_uar;
devl_param_driverinit_value_set(devlink,
MLX4_DEVLINK_PARAM_ID_ENABLE_4K_UAR,
- value);
+ &value);
value.vbool = false;
devl_param_driverinit_value_set(devlink,
DEVLINK_PARAM_GENERIC_ID_REGION_SNAPSHOT,
- value);
+ &value);
}
static inline void mlx4_set_num_reserved_uars(struct mlx4_dev *dev,
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/devlink.c b/drivers/net/ethernet/mellanox/mlx5/core/devlink.c
index 73cf0321bb86..c31e05529fc4 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/devlink.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/devlink.c
@@ -459,11 +459,11 @@ void mlx5_devlink_free(struct devlink *devlink)
}
static int mlx5_devlink_enable_roce_validate(struct devlink *devlink, u32 id,
- union devlink_param_value val,
+ union devlink_param_value *val,
struct netlink_ext_ack *extack)
{
struct mlx5_core_dev *dev = devlink_priv(devlink);
- bool new_state = val.vbool;
+ bool new_state = val->vbool;
if (new_state && !MLX5_CAP_GEN(dev, roce) &&
!(MLX5_CAP_GEN(dev, roce_rw_supported) && MLX5_CAP_GEN_MAX(dev, roce))) {
@@ -480,10 +480,10 @@ static int mlx5_devlink_enable_roce_validate(struct devlink *devlink, u32 id,
#ifdef CONFIG_MLX5_ESWITCH
static int mlx5_devlink_large_group_num_validate(struct devlink *devlink, u32 id,
- union devlink_param_value val,
+ union devlink_param_value *val,
struct netlink_ext_ack *extack)
{
- int group_num = val.vu32;
+ int group_num = val->vu32;
if (group_num < 1 || group_num > 1024) {
NL_SET_ERR_MSG_MOD(extack,
@@ -496,27 +496,27 @@ static int mlx5_devlink_large_group_num_validate(struct devlink *devlink, u32 id
#endif
static int mlx5_devlink_eq_depth_validate(struct devlink *devlink, u32 id,
- union devlink_param_value val,
+ union devlink_param_value *val,
struct netlink_ext_ack *extack)
{
- return (val.vu32 >= 64 && val.vu32 <= 4096) ? 0 : -EINVAL;
+ return (val->vu32 >= 64 && val->vu32 <= 4096) ? 0 : -EINVAL;
}
static int
mlx5_devlink_hairpin_num_queues_validate(struct devlink *devlink, u32 id,
- union devlink_param_value val,
+ union devlink_param_value *val,
struct netlink_ext_ack *extack)
{
- return val.vu32 ? 0 : -EINVAL;
+ return val->vu32 ? 0 : -EINVAL;
}
static int
mlx5_devlink_hairpin_queue_size_validate(struct devlink *devlink, u32 id,
- union devlink_param_value val,
+ union devlink_param_value *val,
struct netlink_ext_ack *extack)
{
struct mlx5_core_dev *dev = devlink_priv(devlink);
- u32 val32 = val.vu32;
+ u32 val32 = val->vu32;
if (!is_power_of_2(val32)) {
NL_SET_ERR_MSG_MOD(extack, "Value is not power of two");
@@ -534,11 +534,11 @@ mlx5_devlink_hairpin_queue_size_validate(struct devlink *devlink, u32 id,
}
static int mlx5_devlink_num_doorbells_validate(struct devlink *devlink, u32 id,
- union devlink_param_value val,
+ union devlink_param_value *val,
struct netlink_ext_ack *extack)
{
struct mlx5_core_dev *mdev = devlink_priv(devlink);
- u32 val32 = val.vu32;
+ u32 val32 = val->vu32;
u32 max_num_channels;
max_num_channels = mlx5e_get_max_num_channels(mdev);
@@ -567,13 +567,13 @@ static void mlx5_devlink_hairpin_params_init_values(struct devlink *devlink)
value.vu32 = link_speed64;
devl_param_driverinit_value_set(
- devlink, MLX5_DEVLINK_PARAM_ID_HAIRPIN_NUM_QUEUES, value);
+ devlink, MLX5_DEVLINK_PARAM_ID_HAIRPIN_NUM_QUEUES, &value);
value.vu32 =
BIT(min_t(u32, 16 - MLX5_MPWRQ_MIN_LOG_STRIDE_SZ(dev),
MLX5_CAP_GEN(dev, log_max_hairpin_num_packets)));
devl_param_driverinit_value_set(
- devlink, MLX5_DEVLINK_PARAM_ID_HAIRPIN_QUEUE_SIZE, value);
+ devlink, MLX5_DEVLINK_PARAM_ID_HAIRPIN_QUEUE_SIZE, &value);
}
static const struct devlink_param mlx5_devlink_params[] = {
@@ -600,24 +600,24 @@ static void mlx5_devlink_set_params_init_values(struct devlink *devlink)
value.vbool = MLX5_CAP_GEN(dev, roce) && !mlx5_dev_is_lightweight(dev);
devl_param_driverinit_value_set(devlink,
DEVLINK_PARAM_GENERIC_ID_ENABLE_ROCE,
- value);
+ &value);
#ifdef CONFIG_MLX5_ESWITCH
value.vu32 = ESW_OFFLOADS_DEFAULT_NUM_GROUPS;
devl_param_driverinit_value_set(devlink,
MLX5_DEVLINK_PARAM_ID_ESW_LARGE_GROUP_NUM,
- value);
+ &value);
#endif
value.vu32 = MLX5_COMP_EQ_SIZE;
devl_param_driverinit_value_set(devlink,
DEVLINK_PARAM_GENERIC_ID_IO_EQ_SIZE,
- value);
+ &value);
value.vu32 = MLX5_NUM_ASYNC_EQE;
devl_param_driverinit_value_set(devlink,
DEVLINK_PARAM_GENERIC_ID_EVENT_EQ_SIZE,
- value);
+ &value);
}
static const struct devlink_param mlx5_devlink_eth_params[] = {
@@ -653,14 +653,14 @@ static int mlx5_devlink_eth_params_register(struct devlink *devlink)
value.vbool = !mlx5_dev_is_lightweight(dev);
devl_param_driverinit_value_set(devlink,
DEVLINK_PARAM_GENERIC_ID_ENABLE_ETH,
- value);
+ &value);
mlx5_devlink_hairpin_params_init_values(devlink);
value.vu32 = MLX5_DEFAULT_NUM_DOORBELLS;
devl_param_driverinit_value_set(devlink,
DEVLINK_PARAM_GENERIC_ID_NUM_DOORBELLS,
- value);
+ &value);
return 0;
}
@@ -681,12 +681,12 @@ static void mlx5_devlink_eth_params_unregister(struct devlink *devlink)
static int
mlx5_devlink_pcie_cong_thresh_validate(struct devlink *devl, u32 id,
- union devlink_param_value val,
+ union devlink_param_value *val,
struct netlink_ext_ack *extack)
{
- if (val.vu16 > MLX5_PCIE_CONG_THRESH_MAX) {
+ if (val->vu16 > MLX5_PCIE_CONG_THRESH_MAX) {
NL_SET_ERR_MSG_FMT_MOD(extack, "Value %u > max supported (%u)",
- val.vu16, MLX5_PCIE_CONG_THRESH_MAX);
+ val->vu16, MLX5_PCIE_CONG_THRESH_MAX);
return -EINVAL;
}
@@ -711,19 +711,19 @@ static void mlx5_devlink_pcie_cong_init_values(struct devlink *devlink)
value.vu16 = MLX5_PCIE_CONG_THRESH_DEF_LOW;
id = MLX5_DEVLINK_PARAM_ID_PCIE_CONG_IN_LOW;
- devl_param_driverinit_value_set(devlink, id, value);
+ devl_param_driverinit_value_set(devlink, id, &value);
value.vu16 = MLX5_PCIE_CONG_THRESH_DEF_HIGH;
id = MLX5_DEVLINK_PARAM_ID_PCIE_CONG_IN_HIGH;
- devl_param_driverinit_value_set(devlink, id, value);
+ devl_param_driverinit_value_set(devlink, id, &value);
value.vu16 = MLX5_PCIE_CONG_THRESH_DEF_LOW;
id = MLX5_DEVLINK_PARAM_ID_PCIE_CONG_OUT_LOW;
- devl_param_driverinit_value_set(devlink, id, value);
+ devl_param_driverinit_value_set(devlink, id, &value);
value.vu16 = MLX5_PCIE_CONG_THRESH_DEF_HIGH;
id = MLX5_DEVLINK_PARAM_ID_PCIE_CONG_OUT_HIGH;
- devl_param_driverinit_value_set(devlink, id, value);
+ devl_param_driverinit_value_set(devlink, id, &value);
}
static const struct devlink_param mlx5_devlink_pcie_cong_params[] = {
@@ -775,11 +775,11 @@ static void mlx5_devlink_pcie_cong_params_unregister(struct devlink *devlink)
}
static int mlx5_devlink_enable_rdma_validate(struct devlink *devlink, u32 id,
- union devlink_param_value val,
+ union devlink_param_value *val,
struct netlink_ext_ack *extack)
{
struct mlx5_core_dev *dev = devlink_priv(devlink);
- bool new_state = val.vbool;
+ bool new_state = val->vbool;
if (new_state && !mlx5_rdma_supported(dev))
return -EOPNOTSUPP;
@@ -808,7 +808,7 @@ static int mlx5_devlink_rdma_params_register(struct devlink *devlink)
value.vbool = !mlx5_dev_is_lightweight(dev);
devl_param_driverinit_value_set(devlink,
DEVLINK_PARAM_GENERIC_ID_ENABLE_RDMA,
- value);
+ &value);
return 0;
}
@@ -843,7 +843,7 @@ static int mlx5_devlink_vnet_params_register(struct devlink *devlink)
value.vbool = !mlx5_dev_is_lightweight(dev);
devl_param_driverinit_value_set(devlink,
DEVLINK_PARAM_GENERIC_ID_ENABLE_VNET,
- value);
+ &value);
return 0;
}
@@ -890,22 +890,22 @@ static void mlx5_devlink_auxdev_params_unregister(struct devlink *devlink)
}
static int mlx5_devlink_max_uc_list_validate(struct devlink *devlink, u32 id,
- union devlink_param_value val,
+ union devlink_param_value *val,
struct netlink_ext_ack *extack)
{
struct mlx5_core_dev *dev = devlink_priv(devlink);
- if (val.vu32 == 0) {
+ if (val->vu32 == 0) {
NL_SET_ERR_MSG_MOD(extack, "max_macs value must be greater than 0");
return -EINVAL;
}
- if (!is_power_of_2(val.vu32)) {
+ if (!is_power_of_2(val->vu32)) {
NL_SET_ERR_MSG_MOD(extack, "Only power of 2 values are supported for max_macs");
return -EINVAL;
}
- if (ilog2(val.vu32) >
+ if (ilog2(val->vu32) >
MLX5_CAP_GEN_MAX(dev, log_max_current_uc_list)) {
NL_SET_ERR_MSG_MOD(extack, "max_macs value is out of the supported range");
return -EINVAL;
@@ -936,7 +936,7 @@ static int mlx5_devlink_max_uc_list_params_register(struct devlink *devlink)
value.vu32 = 1 << MLX5_CAP_GEN(dev, log_max_current_uc_list);
devl_param_driverinit_value_set(devlink,
DEVLINK_PARAM_GENERIC_ID_MAX_MACS,
- value);
+ &value);
return 0;
}
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c
index dea5647de548..c46c3a462a40 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c
@@ -2728,7 +2728,7 @@ static int esw_port_metadata_get(struct devlink *devlink, u32 id,
}
static int esw_port_metadata_validate(struct devlink *devlink, u32 id,
- union devlink_param_value val,
+ union devlink_param_value *val,
struct netlink_ext_ack *extack)
{
struct mlx5_core_dev *dev = devlink_priv(devlink);
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c b/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c
index 61a6ba1e49dd..c8f6adae6f51 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c
@@ -3765,11 +3765,11 @@ static int init_egress_root_ns(struct mlx5_flow_steering *steering)
}
static int mlx5_fs_mode_validate(struct devlink *devlink, u32 id,
- union devlink_param_value val,
+ union devlink_param_value *val,
struct netlink_ext_ack *extack)
{
struct mlx5_core_dev *dev = devlink_priv(devlink);
- char *value = val.vstr;
+ char *value = val->vstr;
u8 eswitch_mode;
eswitch_mode = mlx5_eswitch_mode(dev);
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lib/nv_param.c b/drivers/net/ethernet/mellanox/mlx5/core/lib/nv_param.c
index 19bb620b7436..4a7275e8b62e 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/lib/nv_param.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/lib/nv_param.c
@@ -270,13 +270,13 @@ mlx5_nv_param_devlink_cqe_compress_get(struct devlink *devlink, u32 id,
static int
mlx5_nv_param_devlink_cqe_compress_validate(struct devlink *devlink, u32 id,
- union devlink_param_value val,
+ union devlink_param_value *val,
struct netlink_ext_ack *extack)
{
int i;
for (i = 0; i < ARRAY_SIZE(cqe_compress_str); i++) {
- if (!strcmp(val.vstr, cqe_compress_str[i]))
+ if (!strcmp(val->vstr, cqe_compress_str[i]))
return 0;
}
@@ -374,7 +374,7 @@ mlx5_devlink_swp_l4_csum_mode_get(struct devlink *devlink, u32 id,
static int
mlx5_devlink_swp_l4_csum_mode_validate(struct devlink *devlink, u32 id,
- union devlink_param_value val,
+ union devlink_param_value *val,
struct netlink_ext_ack *extack)
{
struct mlx5_core_dev *dev = devlink_priv(devlink);
@@ -383,7 +383,7 @@ mlx5_devlink_swp_l4_csum_mode_validate(struct devlink *devlink, u32 id,
int err, i;
for (i = 0; i < ARRAY_SIZE(swp_l4_csum_mode_str); i++) {
- if (!strcmp(val.vstr, swp_l4_csum_mode_str[i]))
+ if (!strcmp(val->vstr, swp_l4_csum_mode_str[i]))
break;
}
@@ -727,7 +727,7 @@ static int mlx5_devlink_total_vfs_set(struct devlink *devlink, u32 id,
}
static int mlx5_devlink_total_vfs_validate(struct devlink *devlink, u32 id,
- union devlink_param_value val,
+ union devlink_param_value *val,
struct netlink_ext_ack *extack)
{
struct mlx5_core_dev *dev = devlink_priv(devlink);
@@ -746,7 +746,7 @@ static int mlx5_devlink_total_vfs_validate(struct devlink *devlink, u32 id,
return 0; /* optimistic, but set might fail later */
max = MLX5_GET(nv_global_pci_cap, data, max_vfs_per_pf);
- if (val.vu16 > max) {
+ if (val->vu16 > max) {
NL_SET_ERR_MSG_FMT_MOD(extack,
"Max allowed by device is %u", max);
return -EINVAL;
diff --git a/drivers/net/ethernet/mellanox/mlxsw/core.c b/drivers/net/ethernet/mellanox/mlxsw/core.c
index d76246301f67..308d8a94865f 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/core.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/core.c
@@ -1306,11 +1306,11 @@ static int mlxsw_core_fw_flash_update(struct mlxsw_core *mlxsw_core,
}
static int mlxsw_core_devlink_param_fw_load_policy_validate(struct devlink *devlink, u32 id,
- union devlink_param_value val,
+ union devlink_param_value *val,
struct netlink_ext_ack *extack)
{
- if (val.vu8 != DEVLINK_PARAM_FW_LOAD_POLICY_VALUE_DRIVER &&
- val.vu8 != DEVLINK_PARAM_FW_LOAD_POLICY_VALUE_FLASH) {
+ if (val->vu8 != DEVLINK_PARAM_FW_LOAD_POLICY_VALUE_DRIVER &&
+ val->vu8 != DEVLINK_PARAM_FW_LOAD_POLICY_VALUE_FLASH) {
NL_SET_ERR_MSG_MOD(extack, "'fw_load_policy' must be 'driver' or 'flash'");
return -EINVAL;
}
@@ -1337,7 +1337,7 @@ static int mlxsw_core_fw_params_register(struct mlxsw_core *mlxsw_core)
value.vu8 = DEVLINK_PARAM_FW_LOAD_POLICY_VALUE_DRIVER;
devl_param_driverinit_value_set(devlink,
DEVLINK_PARAM_GENERIC_ID_FW_LOAD_POLICY,
- value);
+ &value);
return 0;
}
diff --git a/drivers/net/ethernet/netronome/nfp/devlink_param.c b/drivers/net/ethernet/netronome/nfp/devlink_param.c
index 85e3b19e6165..826527992e4a 100644
--- a/drivers/net/ethernet/netronome/nfp/devlink_param.c
+++ b/drivers/net/ethernet/netronome/nfp/devlink_param.c
@@ -170,7 +170,7 @@ nfp_devlink_param_u8_set(struct devlink *devlink, u32 id,
static int
nfp_devlink_param_u8_validate(struct devlink *devlink, u32 id,
- union devlink_param_value val,
+ union devlink_param_value *val,
struct netlink_ext_ack *extack)
{
const struct nfp_devlink_param_u8_arg *arg;
@@ -180,12 +180,12 @@ nfp_devlink_param_u8_validate(struct devlink *devlink, u32 id,
arg = &nfp_devlink_u8_args[id];
- if (val.vu8 > arg->max_dl_val) {
+ if (val->vu8 > arg->max_dl_val) {
NL_SET_ERR_MSG_MOD(extack, "parameter out of range");
return -EINVAL;
}
- if (val.vu8 == arg->invalid_dl_val) {
+ if (val->vu8 == arg->invalid_dl_val) {
NL_SET_ERR_MSG_MOD(extack, "unknown/invalid value specified");
return -EINVAL;
}
diff --git a/drivers/net/netdevsim/dev.c b/drivers/net/netdevsim/dev.c
index f00fc2f9ebde..aed9ad5f1b43 100644
--- a/drivers/net/netdevsim/dev.c
+++ b/drivers/net/netdevsim/dev.c
@@ -597,11 +597,11 @@ static void nsim_devlink_set_params_init_values(struct nsim_dev *nsim_dev,
value.vu32 = nsim_dev->max_macs;
devl_param_driverinit_value_set(devlink,
DEVLINK_PARAM_GENERIC_ID_MAX_MACS,
- value);
+ &value);
value.vbool = nsim_dev->test1;
devl_param_driverinit_value_set(devlink,
NSIM_DEVLINK_PARAM_ID_TEST1,
- value);
+ &value);
}
static void nsim_devlink_param_load_driverinit_values(struct devlink *devlink)
diff --git a/include/net/devlink.h b/include/net/devlink.h
index bcd31de1f890..5f4083dc4345 100644
--- a/include/net/devlink.h
+++ b/include/net/devlink.h
@@ -501,7 +501,7 @@ struct devlink_param {
struct devlink_param_gset_ctx *ctx,
struct netlink_ext_ack *extack);
int (*validate)(struct devlink *devlink, u32 id,
- union devlink_param_value val,
+ union devlink_param_value *val,
struct netlink_ext_ack *extack);
int (*get_default)(struct devlink *devlink, u32 id,
struct devlink_param_gset_ctx *ctx,
@@ -1923,7 +1923,7 @@ void devlink_params_unregister(struct devlink *devlink,
int devl_param_driverinit_value_get(struct devlink *devlink, u32 param_id,
union devlink_param_value *val);
void devl_param_driverinit_value_set(struct devlink *devlink, u32 param_id,
- union devlink_param_value init_val);
+ union devlink_param_value *init_val);
void devl_param_value_changed(struct devlink *devlink, u32 param_id);
struct devlink_region *devl_region_create(struct devlink *devlink,
const struct devlink_region_ops *ops,
diff --git a/net/devlink/param.c b/net/devlink/param.c
index cf95268da5b0..1a196d3a843d 100644
--- a/net/devlink/param.c
+++ b/net/devlink/param.c
@@ -216,28 +216,28 @@ static int devlink_param_reset_default(struct devlink *devlink,
static int
devlink_nl_param_value_put(struct sk_buff *msg, enum devlink_param_type type,
- int nla_type, union devlink_param_value val,
+ int nla_type, union devlink_param_value *val,
bool flag_as_u8)
{
switch (type) {
case DEVLINK_PARAM_TYPE_U8:
- if (nla_put_u8(msg, nla_type, val.vu8))
+ if (nla_put_u8(msg, nla_type, val->vu8))
return -EMSGSIZE;
break;
case DEVLINK_PARAM_TYPE_U16:
- if (nla_put_u16(msg, nla_type, val.vu16))
+ if (nla_put_u16(msg, nla_type, val->vu16))
return -EMSGSIZE;
break;
case DEVLINK_PARAM_TYPE_U32:
- if (nla_put_u32(msg, nla_type, val.vu32))
+ if (nla_put_u32(msg, nla_type, val->vu32))
return -EMSGSIZE;
break;
case DEVLINK_PARAM_TYPE_U64:
- if (devlink_nl_put_u64(msg, nla_type, val.vu64))
+ if (devlink_nl_put_u64(msg, nla_type, val->vu64))
return -EMSGSIZE;
break;
case DEVLINK_PARAM_TYPE_STRING:
- if (nla_put_string(msg, nla_type, val.vstr))
+ if (nla_put_string(msg, nla_type, val->vstr))
return -EMSGSIZE;
break;
case DEVLINK_PARAM_TYPE_BOOL:
@@ -245,10 +245,10 @@ devlink_nl_param_value_put(struct sk_buff *msg, enum devlink_param_type type,
* false can be distinguished from not present
*/
if (flag_as_u8) {
- if (nla_put_u8(msg, nla_type, val.vbool))
+ if (nla_put_u8(msg, nla_type, val->vbool))
return -EMSGSIZE;
} else {
- if (val.vbool && nla_put_flag(msg, nla_type))
+ if (val->vbool && nla_put_flag(msg, nla_type))
return -EMSGSIZE;
}
break;
@@ -260,8 +260,8 @@ static int
devlink_nl_param_value_fill_one(struct sk_buff *msg,
enum devlink_param_type type,
enum devlink_param_cmode cmode,
- union devlink_param_value val,
- union devlink_param_value default_val,
+ union devlink_param_value *val,
+ union devlink_param_value *default_val,
bool has_default)
{
struct nlattr *param_value_attr;
@@ -383,8 +383,8 @@ static int devlink_nl_param_fill(struct sk_buff *msg, struct devlink *devlink,
if (!param_value_set[i])
continue;
err = devlink_nl_param_value_fill_one(msg, param->type,
- i, param_value[i],
- default_value[i],
+ i, ¶m_value[i],
+ &default_value[i],
default_value_set[i]);
if (err)
goto values_list_nest_cancel;
@@ -621,7 +621,7 @@ static int __devlink_nl_cmd_param_set_doit(struct devlink *devlink,
if (err)
return err;
if (param->validate) {
- err = param->validate(devlink, param->id, value,
+ err = param->validate(devlink, param->id, &value,
info->extack);
if (err)
return err;
@@ -888,7 +888,7 @@ EXPORT_SYMBOL_GPL(devl_param_driverinit_value_get);
* configuration mode default value.
*/
void devl_param_driverinit_value_set(struct devlink *devlink, u32 param_id,
- union devlink_param_value init_val)
+ union devlink_param_value *init_val)
{
struct devlink_param_item *param_item;
@@ -902,9 +902,9 @@ void devl_param_driverinit_value_set(struct devlink *devlink, u32 param_id,
DEVLINK_PARAM_CMODE_DRIVERINIT)))
return;
- param_item->driverinit_value = init_val;
+ param_item->driverinit_value = *init_val;
param_item->driverinit_value_valid = true;
- param_item->driverinit_default = init_val;
+ param_item->driverinit_default = *init_val;
devlink_param_notify(devlink, 0, param_item, DEVLINK_CMD_PARAM_NEW);
}
--
2.43.0
^ permalink raw reply related [flat|nested] 22+ messages in thread* Re: [PATCH v12 net-next 3/9] devlink: pass param values by pointer
2026-05-08 3:49 ` [PATCH v12 net-next 3/9] devlink: pass param values by pointer Ratheesh Kannoth
@ 2026-05-11 13:39 ` Przemek Kitszel
0 siblings, 0 replies; 22+ messages in thread
From: Przemek Kitszel @ 2026-05-11 13:39 UTC (permalink / raw)
To: Ratheesh Kannoth, intel-wired-lan, netdev
Cc: akiyano, andrew+netdev, anthony.l.nguyen, arkadiusz.kubalewski,
brett.creeley, darinzon, davem, donald.hunter, edumazet,
linux-rdma, linux-kernel, horms, idosch, ivecera, jiri, kuba,
leon, mbloch, michael.chan, pabeni, pavan.chebbi, petrm,
Prathosh.Satish, saeedm, sgoutham, tariqt, vadim.fedorenko,
oss-drivers
On 5/8/26 05:49, Ratheesh Kannoth wrote:
> union devlink_param_value grows substantially once U64 array
> parameters are added to devlink (from 32 bytes to over 264 bytes).
> devlink_nl_param_value_fill_one() and devlink_nl_param_value_put()
> copy the union by value in several places. Passing two instances as
> value arguments alone consumes over 528 bytes of stack; combined with
> deeper call chains the parameter stack can approach 800 bytes and trip
> CONFIG_FRAME_WARN more easily.
>
> Switch internal helpers and exported driver APIs to pass pointers to
> union devlink_param_value rather than passing the union by value.
>
> Signed-off-by: Ratheesh Kannoth <rkannoth@marvell.com>
> ---
> drivers/dpll/zl3073x/devlink.c | 6 +-
> drivers/net/ethernet/amazon/ena/ena_devlink.c | 8 +--
> drivers/net/ethernet/amd/pds_core/core.h | 2 +-
> drivers/net/ethernet/amd/pds_core/devlink.c | 2 +-
> .../net/ethernet/broadcom/bnxt/bnxt_devlink.c | 6 +-
> .../net/ethernet/intel/ice/devlink/devlink.c | 30 ++++----
those are pure mechanical changes, no problem for me
Acked-by: Przemek Kitszel <przemyslaw.kitszel@intel.com>
> .../marvell/octeontx2/af/rvu_devlink.c | 22 +++---
> .../marvell/octeontx2/nic/otx2_devlink.c | 4 +-
> drivers/net/ethernet/mellanox/mlx4/main.c | 14 ++--
> .../net/ethernet/mellanox/mlx5/core/devlink.c | 72 +++++++++----------
> .../mellanox/mlx5/core/eswitch_offloads.c | 2 +-
> .../net/ethernet/mellanox/mlx5/core/fs_core.c | 4 +-
> .../mellanox/mlx5/core/lib/nv_param.c | 12 ++--
> drivers/net/ethernet/mellanox/mlxsw/core.c | 8 +--
> .../ethernet/netronome/nfp/devlink_param.c | 6 +-
> drivers/net/netdevsim/dev.c | 4 +-
> include/net/devlink.h | 4 +-
> net/devlink/param.c | 32 ++++-----
> 18 files changed, 119 insertions(+), 119 deletions(-)
>
^ permalink raw reply [flat|nested] 22+ messages in thread
* [PATCH v12 net-next 4/9] devlink: Implement devlink param multi attribute nested data values
2026-05-08 3:49 [PATCH v12 net-next 0/9] octeontx2-af: npc: Enhancements Ratheesh Kannoth
` (2 preceding siblings ...)
2026-05-08 3:49 ` [PATCH v12 net-next 3/9] devlink: pass param values by pointer Ratheesh Kannoth
@ 2026-05-08 3:49 ` Ratheesh Kannoth
2026-05-11 2:31 ` Ratheesh Kannoth
2026-05-08 3:49 ` [PATCH v12 net-next 5/9] octeontx2-af: npc: cn20k: add subbank search order control Ratheesh Kannoth
` (4 subsequent siblings)
8 siblings, 1 reply; 22+ messages in thread
From: Ratheesh Kannoth @ 2026-05-08 3:49 UTC (permalink / raw)
To: intel-wired-lan, linux-kernel, linux-rdma, netdev, oss-drivers
Cc: akiyano, andrew+netdev, anthony.l.nguyen, arkadiusz.kubalewski,
brett.creeley, darinzon, davem, donald.hunter, edumazet, horms,
idosch, ivecera, jiri, kuba, leon, mbloch, michael.chan, pabeni,
pavan.chebbi, petrm, Prathosh.Satish, przemyslaw.kitszel, saeedm,
sgoutham, tariqt, vadim.fedorenko, Ratheesh Kannoth
From: Saeed Mahameed <saeedm@nvidia.com>
Devlink param value attribute is not defined since devlink is handling
the value validating and parsing internally, this allows us to implement
multi attribute values without breaking any policies.
Devlink param multi-attribute values are considered to be dynamically
sized arrays of u64 values, by introducing a new devlink param type
DEVLINK_PARAM_TYPE_U64_ARRAY, driver and user space can set a variable
count of u32 values into the DEVLINK_ATTR_PARAM_VALUE_DATA attribute.
Implement get/set parsing and add to the internal value structure passed
to drivers.
This is useful for devices that need to configure a list of values for
a specific configuration.
example:
$ devlink dev param show pci/... name multi-value-param
name multi-value-param type driver-specific
values:
cmode permanent value: 0,1,2,3,4,5,6,7
$ devlink dev param set pci/... name multi-value-param \
value 4,5,6,7,0,1,2,3 cmode permanent
Signed-off-by: Saeed Mahameed <saeedm@nvidia.com>
Signed-off-by: Ratheesh Kannoth <rkannoth@marvell.com>
---
Documentation/netlink/specs/devlink.yaml | 4 ++
include/net/devlink.h | 8 +++
include/uapi/linux/devlink.h | 1 +
net/devlink/netlink_gen.c | 2 +
net/devlink/param.c | 88 +++++++++++++++++++-----
5 files changed, 86 insertions(+), 17 deletions(-)
diff --git a/Documentation/netlink/specs/devlink.yaml b/Documentation/netlink/specs/devlink.yaml
index 247b147d689f..52ad1e7805d1 100644
--- a/Documentation/netlink/specs/devlink.yaml
+++ b/Documentation/netlink/specs/devlink.yaml
@@ -234,6 +234,10 @@ definitions:
value: 10
-
name: binary
+ -
+ name: u64-array
+ value: 129
+
-
name: rate-tc-index-max
type: const
diff --git a/include/net/devlink.h b/include/net/devlink.h
index 5f4083dc4345..dd546dbd57cf 100644
--- a/include/net/devlink.h
+++ b/include/net/devlink.h
@@ -433,6 +433,13 @@ enum devlink_param_type {
DEVLINK_PARAM_TYPE_U64 = DEVLINK_VAR_ATTR_TYPE_U64,
DEVLINK_PARAM_TYPE_STRING = DEVLINK_VAR_ATTR_TYPE_STRING,
DEVLINK_PARAM_TYPE_BOOL = DEVLINK_VAR_ATTR_TYPE_FLAG,
+ DEVLINK_PARAM_TYPE_U64_ARRAY = DEVLINK_VAR_ATTR_TYPE_U64_ARRAY,
+};
+
+#define __DEVLINK_PARAM_MAX_ARRAY_SIZE 32
+struct devlink_param_u64_array {
+ u64 size;
+ u64 val[__DEVLINK_PARAM_MAX_ARRAY_SIZE];
};
union devlink_param_value {
@@ -442,6 +449,7 @@ union devlink_param_value {
u64 vu64;
char vstr[__DEVLINK_PARAM_MAX_STRING_VALUE];
bool vbool;
+ struct devlink_param_u64_array u64arr;
};
struct devlink_param_gset_ctx {
diff --git a/include/uapi/linux/devlink.h b/include/uapi/linux/devlink.h
index 0b165eac7619..ca713bcc47b9 100644
--- a/include/uapi/linux/devlink.h
+++ b/include/uapi/linux/devlink.h
@@ -406,6 +406,7 @@ enum devlink_var_attr_type {
DEVLINK_VAR_ATTR_TYPE_BINARY,
__DEVLINK_VAR_ATTR_TYPE_CUSTOM_BASE = 0x80,
/* Any possible custom types, unrelated to NLA_* values go below */
+ DEVLINK_VAR_ATTR_TYPE_U64_ARRAY,
};
enum devlink_attr {
diff --git a/net/devlink/netlink_gen.c b/net/devlink/netlink_gen.c
index 81899786fd98..f52b0c2b19ed 100644
--- a/net/devlink/netlink_gen.c
+++ b/net/devlink/netlink_gen.c
@@ -37,6 +37,8 @@ devlink_attr_param_type_validate(const struct nlattr *attr,
case DEVLINK_VAR_ATTR_TYPE_NUL_STRING:
fallthrough;
case DEVLINK_VAR_ATTR_TYPE_BINARY:
+ fallthrough;
+ case DEVLINK_VAR_ATTR_TYPE_U64_ARRAY:
return 0;
}
NL_SET_ERR_MSG_ATTR(extack, attr, "invalid enum value");
diff --git a/net/devlink/param.c b/net/devlink/param.c
index 1a196d3a843d..4cc479bd019f 100644
--- a/net/devlink/param.c
+++ b/net/devlink/param.c
@@ -252,6 +252,11 @@ devlink_nl_param_value_put(struct sk_buff *msg, enum devlink_param_type type,
return -EMSGSIZE;
}
break;
+ case DEVLINK_PARAM_TYPE_U64_ARRAY:
+ for (int i = 0; i < val->u64arr.size; i++)
+ if (nla_put_uint(msg, nla_type, val->u64arr.val[i]))
+ return -EMSGSIZE;
+ break;
}
return 0;
}
@@ -304,56 +309,78 @@ static int devlink_nl_param_fill(struct sk_buff *msg, struct devlink *devlink,
u32 portid, u32 seq, int flags,
struct netlink_ext_ack *extack)
{
- union devlink_param_value default_value[DEVLINK_PARAM_CMODE_MAX + 1];
- union devlink_param_value param_value[DEVLINK_PARAM_CMODE_MAX + 1];
bool default_value_set[DEVLINK_PARAM_CMODE_MAX + 1] = {};
bool param_value_set[DEVLINK_PARAM_CMODE_MAX + 1] = {};
const struct devlink_param *param = param_item->param;
- struct devlink_param_gset_ctx ctx;
+ union devlink_param_value *default_value;
+ union devlink_param_value *param_value;
+ struct devlink_param_gset_ctx *ctx;
struct nlattr *param_values_list;
struct nlattr *param_attr;
void *hdr;
int err;
int i;
+ default_value = kcalloc(DEVLINK_PARAM_CMODE_MAX + 1,
+ sizeof(*default_value), GFP_KERNEL);
+ if (!default_value)
+ return -ENOMEM;
+
+ param_value = kcalloc(DEVLINK_PARAM_CMODE_MAX + 1,
+ sizeof(*param_value), GFP_KERNEL);
+ if (!param_value) {
+ kfree(default_value);
+ return -ENOMEM;
+ }
+
+ ctx = kmalloc_obj(*ctx);
+ if (!ctx) {
+ kfree(param_value);
+ kfree(default_value);
+ return -ENOMEM;
+ }
+
/* Get value from driver part to driverinit configuration mode */
for (i = 0; i <= DEVLINK_PARAM_CMODE_MAX; i++) {
if (!devlink_param_cmode_is_supported(param, i))
continue;
if (i == DEVLINK_PARAM_CMODE_DRIVERINIT) {
- if (param_item->driverinit_value_new_valid)
+ if (param_item->driverinit_value_new_valid) {
param_value[i] = param_item->driverinit_value_new;
- else if (param_item->driverinit_value_valid)
+ } else if (param_item->driverinit_value_valid) {
param_value[i] = param_item->driverinit_value;
- else
- return -EOPNOTSUPP;
+ } else {
+ err = -EOPNOTSUPP;
+ goto get_put_fail;
+ }
if (param_item->driverinit_value_valid) {
default_value[i] = param_item->driverinit_default;
default_value_set[i] = true;
}
} else {
- ctx.cmode = i;
- err = devlink_param_get(devlink, param, &ctx, extack);
+ ctx->cmode = i;
+ err = devlink_param_get(devlink, param, ctx, extack);
if (err)
- return err;
- param_value[i] = ctx.val;
+ goto get_put_fail;
+ param_value[i] = ctx->val;
- err = devlink_param_get_default(devlink, param, &ctx,
+ err = devlink_param_get_default(devlink, param, ctx,
extack);
if (!err) {
- default_value[i] = ctx.val;
+ default_value[i] = ctx->val;
default_value_set[i] = true;
} else if (err != -EOPNOTSUPP) {
- return err;
+ goto get_put_fail;
}
}
param_value_set[i] = true;
}
+ err = -EMSGSIZE;
hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd);
if (!hdr)
- return -EMSGSIZE;
+ goto get_put_fail;
if (devlink_nl_put_handle(msg, devlink))
goto genlmsg_cancel;
@@ -393,6 +420,9 @@ static int devlink_nl_param_fill(struct sk_buff *msg, struct devlink *devlink,
nla_nest_end(msg, param_values_list);
nla_nest_end(msg, param_attr);
genlmsg_end(msg, hdr);
+ kfree(default_value);
+ kfree(param_value);
+ kfree(ctx);
return 0;
values_list_nest_cancel:
@@ -401,7 +431,11 @@ static int devlink_nl_param_fill(struct sk_buff *msg, struct devlink *devlink,
nla_nest_cancel(msg, param_attr);
genlmsg_cancel:
genlmsg_cancel(msg, hdr);
- return -EMSGSIZE;
+get_put_fail:
+ kfree(default_value);
+ kfree(param_value);
+ kfree(ctx);
+ return err;
}
static void devlink_param_notify(struct devlink *devlink,
@@ -507,7 +541,7 @@ devlink_param_value_get_from_info(const struct devlink_param *param,
union devlink_param_value *value)
{
struct nlattr *param_data;
- int len;
+ int len, cnt, rem;
param_data = info->attrs[DEVLINK_ATTR_PARAM_VALUE_DATA];
@@ -547,6 +581,26 @@ devlink_param_value_get_from_info(const struct devlink_param *param,
return -EINVAL;
value->vbool = nla_get_flag(param_data);
break;
+
+ case DEVLINK_PARAM_TYPE_U64_ARRAY:
+ cnt = 0;
+ nla_for_each_attr_type(param_data,
+ DEVLINK_ATTR_PARAM_VALUE_DATA,
+ genlmsg_data(info->genlhdr),
+ genlmsg_len(info->genlhdr), rem) {
+ if (cnt >= __DEVLINK_PARAM_MAX_ARRAY_SIZE)
+ return -EMSGSIZE;
+
+ if ((nla_len(param_data) != sizeof(u64)) &&
+ (nla_len(param_data) != sizeof(u32)))
+ return -EINVAL;
+
+ value->u64arr.val[cnt] = (u64)nla_get_uint(param_data);
+ cnt++;
+ }
+
+ value->u64arr.size = cnt;
+ break;
}
return 0;
}
--
2.43.0
^ permalink raw reply related [flat|nested] 22+ messages in thread* Re: [PATCH v12 net-next 4/9] devlink: Implement devlink param multi attribute nested data values
2026-05-08 3:49 ` [PATCH v12 net-next 4/9] devlink: Implement devlink param multi attribute nested data values Ratheesh Kannoth
@ 2026-05-11 2:31 ` Ratheesh Kannoth
0 siblings, 0 replies; 22+ messages in thread
From: Ratheesh Kannoth @ 2026-05-11 2:31 UTC (permalink / raw)
To: intel-wired-lan, linux-kernel, linux-rdma, netdev, oss-drivers
Cc: akiyano, andrew+netdev, anthony.l.nguyen, arkadiusz.kubalewski,
brett.creeley, darinzon, davem, donald.hunter, edumazet, horms,
idosch, ivecera, jiri, kuba, leon, mbloch, michael.chan, pabeni,
pavan.chebbi, petrm, Prathosh.Satish, przemyslaw.kitszel, saeedm,
sgoutham, tariqt, vadim.fedorenko
On 2026-05-08 at 09:19:07, Ratheesh Kannoth (rkannoth@marvell.com) wrote:
> From: Saeed Mahameed <saeedm@nvidia.com>
>
>Separately, the commit message justifies this new UAPI type only with
>"without breaking any policies". DEVLINK_VAR_ATTR_TYPE_BINARY already
>exists and can carry an arbitrary-length payload in a single
>attribute. Could the commit message say why BINARY (with a small
>in-payload framing) was not sufficient, given that a new UAPI enum
>value is permanent?
This is for array of UINT32 or UINT64 types. And commit message clearly mention the same.
>Also, the 32-element cap and the fact that elements are encoded as
>repeated top-level DEVLINK_ATTR_PARAM_VALUE_DATA attributes (rather
>than nested) are not mentioned anywhere userspace-visible. Would it
>make sense to add a short section to Documentation/networking/devlink/
>covering the encoding, the per-element width rules, and the maximum
>element count so that iproute2 devlink, ynl and third-party libraries
>can implement this without reading the kernel source?
DEVLINK_VAR_ATTR_TYPE_U64_ARRAY defined in include/uapi/linux/devlink.h, which is uapi.
>Does adding u64arr to this union bloat every instance of union
>devlink_param_value?
>Before this change the union was dominated by char vstr[32] so it was
>32 bytes. With struct devlink_param_u64_array { u64 size; u64
>val[32]; } it becomes 264 bytes, and the size is paid by every union
>regardless of the param's actual type. struct devlink_param_item
>embeds the union three times (driverinit_value, driverinit_value_new,
>driverinit_default), so every registered devlink param grows by
>roughly 700 bytes even if it is a bool or u8.
We did modify to alloc from heap to reduce size in stack frame.
>Would storing the array out-of-line (a pointer plus a length) keep the
>cost on the users of U64_ARRAY only?
I dont think it is a good design. We need to contain every thing from userspace to kernelspace
(and vice versa) in this structure itself.
>Since the in-kernel cap is 32, is there a reason for the size field to
>be u64? A narrower type (for example u8, paired with a
>BUILD_BUG_ON(__DEVLINK_PARAM_MAX_ARRAY_SIZE > U8_MAX)) would
>structurally prevent the put path from trusting an out-of-range size.
but there is no saving as such by defining only size as u32, as each array element is
64 bit, due to alignment padding another 32bit is lost. So we made size as well 64bit.
>> __DEVLINK_VAR_ATTR_TYPE_CUSTOM_BASE = 0x80,
>> /* Any possible custom types, unrelated to NLA_* values go below */
>> + DEVLINK_VAR_ATTR_TYPE_U64_ARRAY,
>> };
>This is a permanent UAPI addition. The name says U64_ARRAY but the
>kernel parser accepts either u32- or u64-encoded elements per-entry
>(nla_get_uint() in devlink_param_value_get_from_info() below). Is
>there a reason to keep both widths accepted under a name that promises
>u64? A single message can mix u32- and u64-encoded elements today,
>which is surprising given the type name.
This is a design suggested by maintainers, as it allows to pass both u32 and u64 size
arrays from userspace to kernel.
>Is __DEVLINK_PARAM_MAX_ARRAY_SIZE intended to be visible to userspace?
>It is defined only in include/net/devlink.h, not in this uapi header,
>not in the yaml spec, and not in Documentation/. As a result the
>request above 32 elements is rejected without userspace having any
>way to discover the cap in advance.
I followed __DEVLINK_PARAM_MAX_STRING_VALUE, which is also defined in devlink.h.
So i dont think, we need to do it.
>> + case DEVLINK_PARAM_TYPE_U64_ARRAY:
>> + for (int i = 0; i < val->u64arr.size; i++)
>> + if (nla_put_uint(msg, nla_type, val->u64arr.val[i]))
>> + return -EMSGSIZE;
>> + break;
>> }
>> return 0;
>> }
>Can this loop read past val->u64arr.val[]?
>The ingress path in devlink_param_value_get_from_info() caps cnt at
>__DEVLINK_PARAM_MAX_ARRAY_SIZE (32), but this put path loops to
>val->u64arr.size with no equivalent clamp. If a driver's ->get()
>callback returns 0 but leaves u64arr.size unset (see the kmalloc note
>on ctx below) or sets it above 32, this loop indexes past the 32-entry
>val[] and emits those bytes back to the requester over netlink.
This is okay, we can send as many u64, which can be fitted into msg (skb).
If this reads past u64arr.size, it is an issue with the driver.
Please see jiri comment- https://lore.kernel.org/netdev/3pk4hkzgwy3a55zveapgmk23bsevru55xv75vhkzbpmzkfofcx@rlnkrvynofig/
^ permalink raw reply [flat|nested] 22+ messages in thread
* [PATCH v12 net-next 5/9] octeontx2-af: npc: cn20k: add subbank search order control
2026-05-08 3:49 [PATCH v12 net-next 0/9] octeontx2-af: npc: Enhancements Ratheesh Kannoth
` (3 preceding siblings ...)
2026-05-08 3:49 ` [PATCH v12 net-next 4/9] devlink: Implement devlink param multi attribute nested data values Ratheesh Kannoth
@ 2026-05-08 3:49 ` Ratheesh Kannoth
2026-05-11 2:32 ` Ratheesh Kannoth
2026-05-08 3:49 ` [PATCH v12 net-next 6/9] octeontx2: cn20k: Coordinate default rules with NIX LF lifecycle Ratheesh Kannoth
` (3 subsequent siblings)
8 siblings, 1 reply; 22+ messages in thread
From: Ratheesh Kannoth @ 2026-05-08 3:49 UTC (permalink / raw)
To: intel-wired-lan, linux-kernel, linux-rdma, netdev, oss-drivers
Cc: akiyano, andrew+netdev, anthony.l.nguyen, arkadiusz.kubalewski,
brett.creeley, darinzon, davem, donald.hunter, edumazet, horms,
idosch, ivecera, jiri, kuba, leon, mbloch, michael.chan, pabeni,
pavan.chebbi, petrm, Prathosh.Satish, przemyslaw.kitszel, saeedm,
sgoutham, tariqt, vadim.fedorenko, Ratheesh Kannoth
CN20K NPC MCAM is split into 32 subbanks that are searched in a
predefined order during allocation. Lower-numbered subbanks have
higher priority than higher-numbered ones.
Add a runtime "srch_order" to control the order in which
subbanks are searched during MCAM allocation.
Signed-off-by: Ratheesh Kannoth <rkannoth@marvell.com>
---
.../ethernet/marvell/octeontx2/af/cn20k/npc.c | 54 ++++++++++-
.../ethernet/marvell/octeontx2/af/cn20k/npc.h | 3 +
.../marvell/octeontx2/af/rvu_devlink.c | 92 +++++++++++++++++--
3 files changed, 137 insertions(+), 12 deletions(-)
diff --git a/drivers/net/ethernet/marvell/octeontx2/af/cn20k/npc.c b/drivers/net/ethernet/marvell/octeontx2/af/cn20k/npc.c
index e9aad0ad3fa6..6f8f42234b06 100644
--- a/drivers/net/ethernet/marvell/octeontx2/af/cn20k/npc.c
+++ b/drivers/net/ethernet/marvell/octeontx2/af/cn20k/npc.c
@@ -3376,7 +3376,7 @@ rvu_mbox_handler_npc_cn20k_get_kex_cfg(struct rvu *rvu,
return 0;
}
-static int *subbank_srch_order;
+static u32 *subbank_srch_order;
static void npc_populate_restricted_idxs(int num_subbanks)
{
@@ -3388,7 +3388,7 @@ static int npc_create_srch_order(int cnt)
{
int val = 0;
- subbank_srch_order = kcalloc(cnt, sizeof(int),
+ subbank_srch_order = kcalloc(cnt, sizeof(u32),
GFP_KERNEL);
if (!subbank_srch_order)
return -ENOMEM;
@@ -3906,6 +3906,56 @@ static void npc_unlock_all_subbank(void)
mutex_unlock(&npc_priv.sb[i].lock);
}
+int npc_cn20k_search_order_set(struct rvu *rvu,
+ u64 narr[MAX_NUM_SUB_BANKS], int cnt)
+{
+ struct npc_mcam *mcam = &rvu->hw->mcam;
+ struct npc_subbank *sb;
+ struct xarray *xa;
+ int sb_idx, rc;
+
+ if (cnt != npc_priv.num_subbanks) {
+ dev_err(rvu->dev, "Number of entries(%u) != %u\n",
+ cnt, npc_priv.num_subbanks);
+ return -EINVAL;
+ }
+
+ mutex_lock(&mcam->lock);
+ npc_lock_all_subbank();
+ restrict_valid = false;
+
+ for (sb_idx = 0; sb_idx < cnt; sb_idx++) {
+ sb = &npc_priv.sb[sb_idx];
+
+ xa = &npc_priv.xa_sb_free;
+ if (sb->flags & NPC_SUBBANK_FLAG_USED)
+ xa = &npc_priv.xa_sb_used;
+
+ sb->arr_idx = narr[sb_idx];
+
+ rc = xa_err(xa_store(xa, sb->arr_idx,
+ xa_mk_value(sb_idx), GFP_KERNEL));
+ if (rc)
+ goto fail;
+ }
+
+ for (int i = 0; i < cnt; i++)
+ subbank_srch_order[i] = (u32)narr[i];
+
+fail:
+ npc_unlock_all_subbank();
+ mutex_unlock(&mcam->lock);
+
+ return rc;
+}
+
+const u32 *npc_cn20k_search_order_get(bool *restricted_order, u32 *sz)
+{
+ *restricted_order = restrict_valid;
+ *sz = npc_priv.num_subbanks;
+ return subbank_srch_order;
+}
+
/* Only non-ref non-contigous mcam indexes
* are picked for defrag process
*/
diff --git a/drivers/net/ethernet/marvell/octeontx2/af/cn20k/npc.h b/drivers/net/ethernet/marvell/octeontx2/af/cn20k/npc.h
index 9567a2d80b58..bf030e40fbf9 100644
--- a/drivers/net/ethernet/marvell/octeontx2/af/cn20k/npc.h
+++ b/drivers/net/ethernet/marvell/octeontx2/af/cn20k/npc.h
@@ -343,5 +343,8 @@ bool npc_is_cgx_or_lbk(struct rvu *rvu, u16 pcifunc);
int npc_mcam_idx_2_subbank_idx(struct rvu *rvu, u16 mcam_idx,
struct npc_subbank **sb,
int *sb_off);
+const u32 *npc_cn20k_search_order_get(bool *restricted_order, u32 *sz);
+int npc_cn20k_search_order_set(struct rvu *rvu, u64 narr[MAX_NUM_SUB_BANKS],
+ int cnt);
#endif /* NPC_CN20K_H */
diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_devlink.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu_devlink.c
index a42404e6db7c..aa3ecab5ebd8 100644
--- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_devlink.c
+++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_devlink.c
@@ -1258,6 +1258,7 @@ enum rvu_af_dl_param_id {
RVU_AF_DEVLINK_PARAM_ID_NPC_EXACT_FEATURE_DISABLE,
RVU_AF_DEVLINK_PARAM_ID_NPC_DEF_RULE_CNTR_ENABLE,
RVU_AF_DEVLINK_PARAM_ID_NPC_DEFRAG,
+ RVU_AF_DEVLINK_PARAM_ID_NPC_SRCH_ORDER,
RVU_AF_DEVLINK_PARAM_ID_NIX_MAXLF,
};
@@ -1619,12 +1620,83 @@ static int rvu_devlink_eswitch_mode_set(struct devlink *devlink, u16 mode,
return 0;
}
+static int rvu_af_dl_npc_srch_order_set(struct devlink *devlink, u32 id,
+ struct devlink_param_gset_ctx *ctx,
+ struct netlink_ext_ack *extack)
+{
+ struct rvu_devlink *rvu_dl = devlink_priv(devlink);
+ struct rvu *rvu = rvu_dl->rvu;
+
+ return npc_cn20k_search_order_set(rvu,
+ ctx->val.u64arr.val,
+ ctx->val.u64arr.size);
+}
+
+static int rvu_af_dl_npc_srch_order_get(struct devlink *devlink, u32 id,
+ struct devlink_param_gset_ctx *ctx,
+ struct netlink_ext_ack *extack)
+{
+ bool restricted_order;
+ const u32 *order;
+ u32 sz;
+
+ order = npc_cn20k_search_order_get(&restricted_order, &sz);
+ ctx->val.u64arr.size = sz;
+ for (int i = 0; i < sz; i++)
+ ctx->val.u64arr.val[i] = order[i];
+
+ return 0;
+}
+
+static int rvu_af_dl_npc_srch_order_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;
+ bool restricted_order;
+ unsigned long w = 0;
+ u64 *arr;
+ u32 sz;
+
+ npc_cn20k_search_order_get(&restricted_order, &sz);
+ if (sz != val->u64arr.size) {
+ dev_err(rvu->dev,
+ "Wrong size %llu, should be %u\n",
+ val->u64arr.size, sz);
+ return -EINVAL;
+ }
+
+ arr = val->u64arr.val;
+ for (int i = 0; i < sz; i++) {
+ if (arr[i] >= sz)
+ return -EINVAL;
+
+ w |= BIT_ULL(arr[i]);
+ }
+
+ if (bitmap_weight(&w, sz) != sz) {
+ dev_err(rvu->dev,
+ "Duplicate or out-of-range subbank index. %lu\n",
+ find_first_zero_bit(&w, sz));
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
static const struct devlink_ops rvu_devlink_ops = {
.eswitch_mode_get = rvu_devlink_eswitch_mode_get,
.eswitch_mode_set = rvu_devlink_eswitch_mode_set,
};
-static const struct devlink_param rvu_af_dl_param_defrag[] = {
+static const struct devlink_param rvu_af_dl_cn20k_params[] = {
+ DEVLINK_PARAM_DRIVER(RVU_AF_DEVLINK_PARAM_ID_NPC_SRCH_ORDER,
+ "npc_srch_order", DEVLINK_PARAM_TYPE_U64_ARRAY,
+ BIT(DEVLINK_PARAM_CMODE_RUNTIME),
+ rvu_af_dl_npc_srch_order_get,
+ rvu_af_dl_npc_srch_order_set,
+ rvu_af_dl_npc_srch_order_validate),
DEVLINK_PARAM_DRIVER(RVU_AF_DEVLINK_PARAM_ID_NPC_DEFRAG,
"npc_defrag", DEVLINK_PARAM_TYPE_STRING,
BIT(DEVLINK_PARAM_CMODE_RUNTIME),
@@ -1666,13 +1738,13 @@ int rvu_register_dl(struct rvu *rvu)
}
if (is_cn20k(rvu->pdev)) {
- err = devlink_params_register(dl, rvu_af_dl_param_defrag,
- ARRAY_SIZE(rvu_af_dl_param_defrag));
+ err = devlink_params_register(dl, rvu_af_dl_cn20k_params,
+ ARRAY_SIZE(rvu_af_dl_cn20k_params));
if (err) {
dev_err(rvu->dev,
- "devlink defrag params register failed with error %d",
+ "devlink cn20k params register failed with error %d",
err);
- goto err_dl_defrag;
+ goto err_dl_cn20k_params;
}
}
@@ -1695,10 +1767,10 @@ int rvu_register_dl(struct rvu *rvu)
err_dl_exact_match:
if (is_cn20k(rvu->pdev))
- devlink_params_unregister(dl, rvu_af_dl_param_defrag,
- ARRAY_SIZE(rvu_af_dl_param_defrag));
+ devlink_params_unregister(dl, rvu_af_dl_cn20k_params,
+ ARRAY_SIZE(rvu_af_dl_cn20k_params));
-err_dl_defrag:
+err_dl_cn20k_params:
devlink_params_unregister(dl, rvu_af_dl_params, ARRAY_SIZE(rvu_af_dl_params));
err_dl_health:
@@ -1717,8 +1789,8 @@ void rvu_unregister_dl(struct rvu *rvu)
devlink_params_unregister(dl, rvu_af_dl_params, ARRAY_SIZE(rvu_af_dl_params));
if (is_cn20k(rvu->pdev))
- devlink_params_unregister(dl, rvu_af_dl_param_defrag,
- ARRAY_SIZE(rvu_af_dl_param_defrag));
+ devlink_params_unregister(dl, rvu_af_dl_cn20k_params,
+ ARRAY_SIZE(rvu_af_dl_cn20k_params));
/* Unregister exact match devlink only for CN10K-B */
if (rvu_npc_exact_has_match_table(rvu))
--
2.43.0
^ permalink raw reply related [flat|nested] 22+ messages in thread* Re: [PATCH v12 net-next 5/9] octeontx2-af: npc: cn20k: add subbank search order control
2026-05-08 3:49 ` [PATCH v12 net-next 5/9] octeontx2-af: npc: cn20k: add subbank search order control Ratheesh Kannoth
@ 2026-05-11 2:32 ` Ratheesh Kannoth
0 siblings, 0 replies; 22+ messages in thread
From: Ratheesh Kannoth @ 2026-05-11 2:32 UTC (permalink / raw)
To: intel-wired-lan, linux-kernel, linux-rdma, netdev, oss-drivers
Cc: akiyano, andrew+netdev, anthony.l.nguyen, arkadiusz.kubalewski,
brett.creeley, darinzon, davem, donald.hunter, edumazet, horms,
idosch, ivecera, jiri, kuba, leon, mbloch, michael.chan, pabeni,
pavan.chebbi, petrm, Prathosh.Satish, przemyslaw.kitszel, saeedm,
sgoutham, tariqt, vadim.fedorenko
On 2026-05-08 at 09:19:08, Ratheesh Kannoth (rkannoth@marvell.com) wrote:
> CN20K NPC MCAM is split into 32 subbanks that are searched in a
> predefined order during allocation. Lower-numbered subbanks have
> higher priority than higher-numbered ones.
pw-bot: changes-requested
> + for (sb_idx = 0; sb_idx < cnt; sb_idx++) {
>> + sb = &npc_priv.sb[sb_idx];
>> +
>> + xa = &npc_priv.xa_sb_free;
>> + if (sb->flags & NPC_SUBBANK_FLAG_USED)
>> + xa = &npc_priv.xa_sb_used;
>> +
>> + sb->arr_idx = narr[sb_idx];
>> +
>> + rc = xa_err(xa_store(xa, sb->arr_idx,
>> + xa_mk_value(sb_idx), GFP_KERNEL));
>If the new index assignment swaps indices between a free subbank and a used
>subbank, is the old index in the original xarray ever overwritten?
>Since xa_erase() is not called on the old arr_idx, this might leave the
>subbank mapped at both its old and new arr_idx if they don't overwrite each
>other.
>Can this result in stale duplicate entries?
No. npc_cn20k_search_order_set() is only rearranging indexes in free and used subbank.
indexes wont move from free subbank to used subbank.
>If xa_store() fails (for example, due to -ENOMEM from GFP_KERNEL) and returns
>an error, the code jumps to the fail label. Are the successful modifications
>made to previously processed subbanks rolled back?
>If not, could this leave the system in a torn state where restrict_valid is
>false, and some subbanks have updated indices while others keep their old
>ones?
ACK, but, There is no way, we can gracefully rollback, as rollback can also fail due to memory
pressurem while reinserting old index using xa_store. This is fatal error, will add
a err print to alert user.
>> + union devlink_param_value *val,
>> + struct netlink_ext_ack *extack)
>> +{
>> + struct rvu_devlink *rvu_dl = devlink_priv(devlink);
>> + struct rvu *rvu = rvu_dl->rvu;
>> + bool restricted_order;
>> + unsigned long w = 0;
>> + u64 *arr;
>> + u32 sz;
>> +
>> + npc_cn20k_search_order_get(&restricted_order, &sz);
>> + if (sz != val->u64arr.size) {
>> + dev_err(rvu->dev,
>> + "Wrong size %llu, should be %u\n",
>> + val->u64arr.size, sz);
>The size field in devlink array values is a 32-bit unsigned integer (u32),
>but the error message uses the %llu format specifier.
>On some architectures, could this cause printk to consume 8 bytes from the
>arguments and read garbage from adjacent memory?
>> + return -EINVAL;
>> + }
No. %llu is used for val->u64arr.size, which is 64bit.
^ permalink raw reply [flat|nested] 22+ messages in thread
* [PATCH v12 net-next 6/9] octeontx2: cn20k: Coordinate default rules with NIX LF lifecycle
2026-05-08 3:49 [PATCH v12 net-next 0/9] octeontx2-af: npc: Enhancements Ratheesh Kannoth
` (4 preceding siblings ...)
2026-05-08 3:49 ` [PATCH v12 net-next 5/9] octeontx2-af: npc: cn20k: add subbank search order control Ratheesh Kannoth
@ 2026-05-08 3:49 ` Ratheesh Kannoth
2026-05-11 2:44 ` Ratheesh Kannoth
2026-05-08 3:49 ` [PATCH v12 net-next 7/9] octeontx2-af: npc: Support for custom KPU profile from filesystem Ratheesh Kannoth
` (2 subsequent siblings)
8 siblings, 1 reply; 22+ messages in thread
From: Ratheesh Kannoth @ 2026-05-08 3:49 UTC (permalink / raw)
To: intel-wired-lan, linux-kernel, linux-rdma, netdev, oss-drivers
Cc: akiyano, andrew+netdev, anthony.l.nguyen, arkadiusz.kubalewski,
brett.creeley, darinzon, davem, donald.hunter, edumazet, horms,
idosch, ivecera, jiri, kuba, leon, mbloch, michael.chan, pabeni,
pavan.chebbi, petrm, Prathosh.Satish, przemyslaw.kitszel, saeedm,
sgoutham, tariqt, vadim.fedorenko, Ratheesh Kannoth
Add NIX_LF_DONT_FREE_DFT_IDXS so the PF can send NIX LF free during hw
reinit or teardown without the AF freeing CN20K default NPC rule indexes
while the driver still owns that state (otx2_init_hw_resources and
otx2_free_hw_resources).
On CN20K, allocate default NPC rules from NIX LF alloc before
nix_interface_init, roll back with npc_cn20k_dft_rules_free on failure,
and free from NIX LF free when the new flag is not set. Tighten
rvu_mbox_handler_nix_lf_alloc error handling: use a single rc, propagate
qmem_alloc and other errors, and set -ENOMEM only when kcalloc fails
(remove the blanket -ENOMEM at the free_mem path).
Signed-off-by: Ratheesh Kannoth <rkannoth@marvell.com>
---
.../net/ethernet/marvell/octeontx2/af/mbox.h | 1 +
.../ethernet/marvell/octeontx2/af/rvu_nix.c | 69 ++++++++++++-------
.../ethernet/marvell/octeontx2/af/rvu_npc.c | 22 ++++--
.../ethernet/marvell/octeontx2/nic/otx2_pf.c | 6 +-
4 files changed, 62 insertions(+), 36 deletions(-)
diff --git a/drivers/net/ethernet/marvell/octeontx2/af/mbox.h b/drivers/net/ethernet/marvell/octeontx2/af/mbox.h
index dc42c81c0942..e07fbf842b94 100644
--- a/drivers/net/ethernet/marvell/octeontx2/af/mbox.h
+++ b/drivers/net/ethernet/marvell/octeontx2/af/mbox.h
@@ -1009,6 +1009,7 @@ struct nix_lf_free_req {
struct mbox_msghdr hdr;
#define NIX_LF_DISABLE_FLOWS BIT_ULL(0)
#define NIX_LF_DONT_FREE_TX_VTAG BIT_ULL(1)
+#define NIX_LF_DONT_FREE_DFT_IDXS BIT_ULL(2)
u64 flags;
};
diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_nix.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu_nix.c
index f977734ae712..7df256a9e01c 100644
--- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_nix.c
+++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_nix.c
@@ -16,6 +16,7 @@
#include "cgx.h"
#include "lmac_common.h"
#include "rvu_npc_hash.h"
+#include "cn20k/npc.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,
@@ -1499,7 +1500,7 @@ 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, err, rc = 0;
+ int nixlf, qints, hwctx_size, intf, rc = 0;
struct rvu_hwinfo *hw = rvu->hw;
u16 pcifunc = req->hdr.pcifunc;
struct rvu_block *block;
@@ -1555,8 +1556,8 @@ int rvu_mbox_handler_nix_lf_alloc(struct rvu *rvu,
return NIX_AF_ERR_RSS_GRPS_INVALID;
/* Reset this NIX LF */
- err = rvu_lf_reset(rvu, block, nixlf);
- if (err) {
+ rc = rvu_lf_reset(rvu, block, nixlf);
+ if (rc) {
dev_err(rvu->dev, "Failed to reset NIX%d LF%d\n",
block->addr - BLKADDR_NIX0, nixlf);
return NIX_AF_ERR_LF_RESET;
@@ -1566,13 +1567,15 @@ int rvu_mbox_handler_nix_lf_alloc(struct rvu *rvu,
/* Alloc NIX RQ HW context memory and config the base */
hwctx_size = 1UL << ((ctx_cfg >> 4) & 0xF);
- err = qmem_alloc(rvu->dev, &pfvf->rq_ctx, req->rq_cnt, hwctx_size);
- if (err)
+ rc = qmem_alloc(rvu->dev, &pfvf->rq_ctx, req->rq_cnt, hwctx_size);
+ if (rc)
goto free_mem;
pfvf->rq_bmap = kcalloc(req->rq_cnt, sizeof(long), GFP_KERNEL);
- if (!pfvf->rq_bmap)
+ if (!pfvf->rq_bmap) {
+ rc = -ENOMEM;
goto free_mem;
+ }
rvu_write64(rvu, blkaddr, NIX_AF_LFX_RQS_BASE(nixlf),
(u64)pfvf->rq_ctx->iova);
@@ -1583,13 +1586,15 @@ int rvu_mbox_handler_nix_lf_alloc(struct rvu *rvu,
/* Alloc NIX SQ HW context memory and config the base */
hwctx_size = 1UL << (ctx_cfg & 0xF);
- err = qmem_alloc(rvu->dev, &pfvf->sq_ctx, req->sq_cnt, hwctx_size);
- if (err)
+ rc = qmem_alloc(rvu->dev, &pfvf->sq_ctx, req->sq_cnt, hwctx_size);
+ if (rc)
goto free_mem;
pfvf->sq_bmap = kcalloc(req->sq_cnt, sizeof(long), GFP_KERNEL);
- if (!pfvf->sq_bmap)
+ if (!pfvf->sq_bmap) {
+ rc = -ENOMEM;
goto free_mem;
+ }
rvu_write64(rvu, blkaddr, NIX_AF_LFX_SQS_BASE(nixlf),
(u64)pfvf->sq_ctx->iova);
@@ -1599,13 +1604,15 @@ int rvu_mbox_handler_nix_lf_alloc(struct rvu *rvu,
/* Alloc NIX CQ HW context memory and config the base */
hwctx_size = 1UL << ((ctx_cfg >> 8) & 0xF);
- err = qmem_alloc(rvu->dev, &pfvf->cq_ctx, req->cq_cnt, hwctx_size);
- if (err)
+ rc = qmem_alloc(rvu->dev, &pfvf->cq_ctx, req->cq_cnt, hwctx_size);
+ if (rc)
goto free_mem;
pfvf->cq_bmap = kcalloc(req->cq_cnt, sizeof(long), GFP_KERNEL);
- if (!pfvf->cq_bmap)
+ if (!pfvf->cq_bmap) {
+ rc = -ENOMEM;
goto free_mem;
+ }
rvu_write64(rvu, blkaddr, NIX_AF_LFX_CQS_BASE(nixlf),
(u64)pfvf->cq_ctx->iova);
@@ -1615,18 +1622,18 @@ int rvu_mbox_handler_nix_lf_alloc(struct rvu *rvu,
/* Initialize receive side scaling (RSS) */
hwctx_size = 1UL << ((ctx_cfg >> 12) & 0xF);
- err = nixlf_rss_ctx_init(rvu, blkaddr, pfvf, nixlf, req->rss_sz,
- req->rss_grps, hwctx_size, req->way_mask,
- !!(req->flags & NIX_LF_RSS_TAG_LSB_AS_ADDER));
- if (err)
+ rc = nixlf_rss_ctx_init(rvu, blkaddr, pfvf, nixlf, req->rss_sz,
+ req->rss_grps, hwctx_size, req->way_mask,
+ !!(req->flags & NIX_LF_RSS_TAG_LSB_AS_ADDER));
+ if (rc)
goto free_mem;
/* Alloc memory for CQINT's HW contexts */
cfg = rvu_read64(rvu, blkaddr, NIX_AF_CONST2);
qints = (cfg >> 24) & 0xFFF;
hwctx_size = 1UL << ((ctx_cfg >> 24) & 0xF);
- err = qmem_alloc(rvu->dev, &pfvf->cq_ints_ctx, qints, hwctx_size);
- if (err)
+ rc = qmem_alloc(rvu->dev, &pfvf->cq_ints_ctx, qints, hwctx_size);
+ if (rc)
goto free_mem;
rvu_write64(rvu, blkaddr, NIX_AF_LFX_CINTS_BASE(nixlf),
@@ -1639,8 +1646,8 @@ int rvu_mbox_handler_nix_lf_alloc(struct rvu *rvu,
cfg = rvu_read64(rvu, blkaddr, NIX_AF_CONST2);
qints = (cfg >> 12) & 0xFFF;
hwctx_size = 1UL << ((ctx_cfg >> 20) & 0xF);
- err = qmem_alloc(rvu->dev, &pfvf->nix_qints_ctx, qints, hwctx_size);
- if (err)
+ rc = qmem_alloc(rvu->dev, &pfvf->nix_qints_ctx, qints, hwctx_size);
+ if (rc)
goto free_mem;
rvu_write64(rvu, blkaddr, NIX_AF_LFX_QINTS_BASE(nixlf),
@@ -1684,10 +1691,16 @@ int rvu_mbox_handler_nix_lf_alloc(struct rvu *rvu,
if (is_sdp_pfvf(rvu, pcifunc))
intf = NIX_INTF_TYPE_SDP;
- err = nix_interface_init(rvu, pcifunc, intf, nixlf, rsp,
- !!(req->flags & NIX_LF_LBK_BLK_SEL));
- if (err)
- goto free_mem;
+ if (is_cn20k(rvu->pdev)) {
+ rc = npc_cn20k_dft_rules_alloc(rvu, pcifunc);
+ if (rc)
+ goto free_mem;
+ }
+
+ rc = nix_interface_init(rvu, pcifunc, intf, nixlf, rsp,
+ !!(req->flags & NIX_LF_LBK_BLK_SEL));
+ if (rc)
+ goto free_dft;
/* Disable NPC entries as NIXLF's contexts are not initialized yet */
rvu_npc_disable_default_entries(rvu, pcifunc, nixlf);
@@ -1699,9 +1712,12 @@ int rvu_mbox_handler_nix_lf_alloc(struct rvu *rvu,
goto exit;
+free_dft:
+ if (is_cn20k(rvu->pdev))
+ npc_cn20k_dft_rules_free(rvu, pcifunc);
+
free_mem:
nix_ctx_free(rvu, pfvf);
- rc = -ENOMEM;
exit:
/* Set macaddr of this PF/VF */
@@ -1775,6 +1791,9 @@ int rvu_mbox_handler_nix_lf_free(struct rvu *rvu, struct nix_lf_free_req *req,
nix_ctx_free(rvu, pfvf);
+ if (is_cn20k(rvu->pdev) && !(req->flags & NIX_LF_DONT_FREE_DFT_IDXS))
+ npc_cn20k_dft_rules_free(rvu, pcifunc);
+
return 0;
}
diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.c
index 3c814d157ab9..5fa9e1c7ae9f 100644
--- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.c
+++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.c
@@ -990,7 +990,7 @@ void rvu_npc_install_allmulti_entry(struct rvu *rvu, u16 pcifunc, int nixlf,
u16 vf_func;
/* Only CGX PF/VF can add allmulticast entry */
- if (is_lbk_vf(rvu, pcifunc) && is_sdp_vf(rvu, pcifunc))
+ if (is_lbk_vf(rvu, pcifunc) || is_sdp_vf(rvu, pcifunc))
return;
blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NPC, 0);
@@ -1285,11 +1285,18 @@ void npc_enadis_default_mce_entry(struct rvu *rvu, u16 pcifunc,
struct nix_mce_list *mce_list;
int index, blkaddr, mce_idx;
struct rvu_pfvf *pfvf;
+ u16 ptr[4];
/* multicast pkt replication is not enabled for AF's VFs & SDP links */
if (is_lbk_vf(rvu, pcifunc) || is_sdp_pfvf(rvu, pcifunc))
return;
+ /* In cn20k, only CGX mapped devices have default MCAST entry */
+ if (is_cn20k(rvu->pdev) &&
+ npc_cn20k_dft_rules_idx_get(rvu, pcifunc, &ptr[0], &ptr[1],
+ &ptr[2], &ptr[3]))
+ return;
+
blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NPC, 0);
if (blkaddr < 0)
return;
@@ -1329,9 +1336,12 @@ static void npc_enadis_default_entries(struct rvu *rvu, u16 pcifunc,
struct rvu_pfvf *pfvf = rvu_get_pfvf(rvu, pcifunc);
struct npc_mcam *mcam = &rvu->hw->mcam;
int index, blkaddr;
+ u16 ptr[4];
/* only CGX or LBK interfaces have default entries */
- if (is_cn20k(rvu->pdev) && !npc_is_cgx_or_lbk(rvu, pcifunc))
+ if (is_cn20k(rvu->pdev) &&
+ npc_cn20k_dft_rules_idx_get(rvu, pcifunc, &ptr[0], &ptr[1],
+ &ptr[2], &ptr[3]))
return;
blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NPC, 0);
@@ -4085,12 +4095,10 @@ void rvu_npc_clear_ucast_entry(struct rvu *rvu, int pcifunc, int nixlf)
ucast_idx = npc_get_nixlf_mcam_index(mcam, pcifunc,
nixlf, NIXLF_UCAST_ENTRY);
- if (ucast_idx < 0) {
- dev_err(rvu->dev,
- "%s: Error to get ucast entry for pcifunc=%#x\n",
- __func__, pcifunc);
+
+ /* In cn20k, default rules are freed before detach rsrc */
+ if (ucast_idx < 0)
return;
- }
npc_enable_mcam_entry(rvu, mcam, blkaddr, ucast_idx, false);
diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c
index ee623476e5ff..81b088f5a016 100644
--- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c
+++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c
@@ -1053,7 +1053,6 @@ irqreturn_t otx2_pfaf_mbox_intr_handler(int irq, void *pf_irq)
/* Clear the IRQ */
otx2_write64(pf, RVU_PF_INT, BIT_ULL(0));
-
mbox_data = otx2_read64(pf, RVU_PF_PFAF_MBOX0);
if (mbox_data & MBOX_UP_MSG) {
@@ -1729,7 +1728,7 @@ int otx2_init_hw_resources(struct otx2_nic *pf)
mutex_lock(&mbox->lock);
free_req = otx2_mbox_alloc_msg_nix_lf_free(mbox);
if (free_req) {
- free_req->flags = NIX_LF_DISABLE_FLOWS;
+ free_req->flags = NIX_LF_DISABLE_FLOWS | NIX_LF_DONT_FREE_DFT_IDXS;
if (otx2_sync_mbox_msg(mbox))
dev_err(pf->dev, "%s failed to free nixlf\n", __func__);
}
@@ -1803,7 +1802,7 @@ void otx2_free_hw_resources(struct otx2_nic *pf)
/* Reset NIX LF */
free_req = otx2_mbox_alloc_msg_nix_lf_free(mbox);
if (free_req) {
- free_req->flags = NIX_LF_DISABLE_FLOWS;
+ free_req->flags = NIX_LF_DISABLE_FLOWS | NIX_LF_DONT_FREE_DFT_IDXS;
if (!(pf->flags & OTX2_FLAG_PF_SHUTDOWN))
free_req->flags |= NIX_LF_DONT_FREE_TX_VTAG;
if (otx2_sync_mbox_msg(mbox))
@@ -1926,7 +1925,6 @@ int otx2_alloc_queue_mem(struct otx2_nic *pf)
struct otx2_qset *qset = &pf->qset;
struct otx2_cq_poll *cq_poll;
-
/* RQ and SQs are mapped to different CQs,
* so find out max CQ IRQs (i.e CINTs) needed.
*/
--
2.43.0
^ permalink raw reply related [flat|nested] 22+ messages in thread* Re: [PATCH v12 net-next 6/9] octeontx2: cn20k: Coordinate default rules with NIX LF lifecycle
2026-05-08 3:49 ` [PATCH v12 net-next 6/9] octeontx2: cn20k: Coordinate default rules with NIX LF lifecycle Ratheesh Kannoth
@ 2026-05-11 2:44 ` Ratheesh Kannoth
0 siblings, 0 replies; 22+ messages in thread
From: Ratheesh Kannoth @ 2026-05-11 2:44 UTC (permalink / raw)
To: intel-wired-lan, linux-kernel, linux-rdma, netdev, oss-drivers
Cc: akiyano, andrew+netdev, anthony.l.nguyen, arkadiusz.kubalewski,
brett.creeley, darinzon, davem, donald.hunter, edumazet, horms,
idosch, ivecera, jiri, kuba, leon, mbloch, michael.chan, pabeni,
pavan.chebbi, petrm, Prathosh.Satish, przemyslaw.kitszel, saeedm,
sgoutham, tariqt, vadim.fedorenko
On 2026-05-08 at 09:19:09, Ratheesh Kannoth (rkannoth@marvell.com) wrote:
> Add NIX_LF_DONT_FREE_DFT_IDXS so the PF can send NIX LF free during hw
> reinit or teardown without the AF freeing CN20K default NPC rule indexes
> while the driver still owns that state (otx2_init_hw_resources and
> otx2_free_hw_resources).
pw-bot: changes-requested
>> diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.c
>> --- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.c
>> +++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.c
>> @@ -990,7 +990,7 @@ void rvu_npc_install_allmulti_entry(struct rvu *rvu, u16 pcifunc, int nixlf,
>> u16 vf_func;
>>
>> /* Only CGX PF/VF can add allmulticast entry */
>> - if (is_lbk_vf(rvu, pcifunc) && is_sdp_vf(rvu, pcifunc))
>> + if (is_lbk_vf(rvu, pcifunc) || is_sdp_vf(rvu, pcifunc))
>Is this logic change intended to be part of this commit?
>The commit message focuses on coordinating default rules with the NIX LF
>lifecycle, but this silently changes the condition from a logical AND to a
>logical OR. While this appears to correctly fix a bug where the condition
>could never be true (since a device cannot simultaneously be both an LBK VF
>and an SDP VF), including an undocumented bug fix in a patch about a
>different topic obscures the commit's intent.
>Should this be split into a separate patch, or explicitly mentioned in the
>commit message?
ACK. This is a fix, i will post as seperate patch after this net-next series merged.
^ permalink raw reply [flat|nested] 22+ messages in thread
* [PATCH v12 net-next 7/9] octeontx2-af: npc: Support for custom KPU profile from filesystem
2026-05-08 3:49 [PATCH v12 net-next 0/9] octeontx2-af: npc: Enhancements Ratheesh Kannoth
` (5 preceding siblings ...)
2026-05-08 3:49 ` [PATCH v12 net-next 6/9] octeontx2: cn20k: Coordinate default rules with NIX LF lifecycle Ratheesh Kannoth
@ 2026-05-08 3:49 ` Ratheesh Kannoth
2026-05-11 3:23 ` Ratheesh Kannoth
` (2 more replies)
2026-05-08 3:49 ` [PATCH v12 net-next 8/9] octeontx2: cn20k: Respect NPC MCAM X2/X4 profile in flows and DFT alloc Ratheesh Kannoth
2026-05-08 3:49 ` [PATCH v12 net-next 9/9] octeontx2-af: npc: cn20k: Allocate npc_priv and dstats dynamically Ratheesh Kannoth
8 siblings, 3 replies; 22+ messages in thread
From: Ratheesh Kannoth @ 2026-05-08 3:49 UTC (permalink / raw)
To: intel-wired-lan, linux-kernel, linux-rdma, netdev, oss-drivers
Cc: akiyano, andrew+netdev, anthony.l.nguyen, arkadiusz.kubalewski,
brett.creeley, darinzon, davem, donald.hunter, edumazet, horms,
idosch, ivecera, jiri, kuba, leon, mbloch, michael.chan, pabeni,
pavan.chebbi, petrm, Prathosh.Satish, przemyslaw.kitszel, saeedm,
sgoutham, tariqt, vadim.fedorenko, Ratheesh Kannoth
Flashing updated firmware on deployed devices is cumbersome. Provide a
mechanism to load a custom KPU (Key Parse Unit) profile directly from
the filesystem at module load time.
When the rvu_af module is loaded with the kpu_profile parameter, the
specified profile is read from /lib/firmware/kpu and programmed into
the KPU registers. Add npc_kpu_profile_cam2 for the extended cam format
used by filesystem-loaded profiles and support ptype/ptype_mask in
npc_config_kpucam when profile->from_fs is set.
Usage:
1. Copy the KPU profile file to /lib/firmware/kpu.
2. Build OCTEONTX2_AF as a module.
3. Load: insmod rvu_af.ko kpu_profile=<profile_name>
Signed-off-by: Ratheesh Kannoth <rkannoth@marvell.com>
---
.../ethernet/marvell/octeontx2/af/cn20k/npc.c | 57 ++-
.../net/ethernet/marvell/octeontx2/af/npc.h | 17 +
.../net/ethernet/marvell/octeontx2/af/rvu.h | 12 +-
.../ethernet/marvell/octeontx2/af/rvu_npc.c | 456 ++++++++++++++----
.../ethernet/marvell/octeontx2/af/rvu_npc.h | 17 +
.../ethernet/marvell/octeontx2/af/rvu_reg.h | 1 +
6 files changed, 449 insertions(+), 111 deletions(-)
diff --git a/drivers/net/ethernet/marvell/octeontx2/af/cn20k/npc.c b/drivers/net/ethernet/marvell/octeontx2/af/cn20k/npc.c
index 6f8f42234b06..67dfbe5ca903 100644
--- a/drivers/net/ethernet/marvell/octeontx2/af/cn20k/npc.c
+++ b/drivers/net/ethernet/marvell/octeontx2/af/cn20k/npc.c
@@ -521,13 +521,17 @@ npc_program_single_kpm_profile(struct rvu *rvu, int blkaddr,
int kpm, int start_entry,
const struct npc_kpu_profile *profile)
{
+ int num_cam_entries, num_action_entries;
int entry, num_entries, max_entries;
u64 idx;
- if (profile->cam_entries != profile->action_entries) {
+ num_cam_entries = npc_get_num_kpu_cam_entries(rvu, profile);
+ num_action_entries = npc_get_num_kpu_action_entries(rvu, profile);
+
+ if (num_cam_entries != num_action_entries) {
dev_err(rvu->dev,
"kpm%d: CAM and action entries [%d != %d] not equal\n",
- kpm, profile->cam_entries, profile->action_entries);
+ kpm, num_cam_entries, num_action_entries);
WARN(1, "Fatal error\n");
return;
@@ -536,16 +540,18 @@ npc_program_single_kpm_profile(struct rvu *rvu, int blkaddr,
max_entries = rvu->hw->npc_kpu_entries / 2;
entry = start_entry;
/* Program CAM match entries for previous kpm extracted data */
- num_entries = min_t(int, profile->cam_entries, max_entries);
+ num_entries = min_t(int, num_cam_entries, max_entries);
for (idx = 0; entry < num_entries + start_entry; entry++, idx++)
- npc_config_kpmcam(rvu, blkaddr, &profile->cam[idx],
+ npc_config_kpmcam(rvu, blkaddr,
+ npc_get_kpu_cam_nth_entry(rvu, profile, idx),
kpm, entry);
entry = start_entry;
/* Program this kpm's actions */
- num_entries = min_t(int, profile->action_entries, max_entries);
+ num_entries = min_t(int, num_action_entries, max_entries);
for (idx = 0; entry < num_entries + start_entry; entry++, idx++)
- npc_config_kpmaction(rvu, blkaddr, &profile->action[idx],
+ npc_config_kpmaction(rvu, blkaddr,
+ npc_get_kpu_action_nth_entry(rvu, profile, idx),
kpm, entry, false);
}
@@ -611,20 +617,23 @@ npc_enable_kpm_entry(struct rvu *rvu, int blkaddr, int kpm, int num_entries)
static void npc_program_kpm_profile(struct rvu *rvu, int blkaddr, int num_kpms)
{
const struct npc_kpu_profile *profile1, *profile2;
+ int pfl1_num_cam_entries, pfl2_num_cam_entries;
int idx, total_cam_entries;
for (idx = 0; idx < num_kpms; idx++) {
profile1 = &rvu->kpu.kpu[idx];
+ pfl1_num_cam_entries = npc_get_num_kpu_cam_entries(rvu, profile1);
npc_program_single_kpm_profile(rvu, blkaddr, idx, 0, profile1);
profile2 = &rvu->kpu.kpu[idx + KPU_OFFSET];
+ pfl2_num_cam_entries = npc_get_num_kpu_cam_entries(rvu, profile2);
+
npc_program_single_kpm_profile(rvu, blkaddr, idx,
- profile1->cam_entries,
+ pfl1_num_cam_entries,
profile2);
- total_cam_entries = profile1->cam_entries +
- profile2->cam_entries;
+ total_cam_entries = pfl1_num_cam_entries + pfl2_num_cam_entries;
npc_enable_kpm_entry(rvu, blkaddr, idx, total_cam_entries);
rvu_write64(rvu, blkaddr, NPC_AF_KPMX_PASS2_OFFSET(idx),
- profile1->cam_entries);
+ pfl1_num_cam_entries);
/* Enable the KPUs associated with this KPM */
rvu_write64(rvu, blkaddr, NPC_AF_KPUX_CFG(idx), 0x01);
rvu_write64(rvu, blkaddr, NPC_AF_KPUX_CFG(idx + KPU_OFFSET),
@@ -634,6 +643,7 @@ static void npc_program_kpm_profile(struct rvu *rvu, int blkaddr, int num_kpms)
void npc_cn20k_parser_profile_init(struct rvu *rvu, int blkaddr)
{
+ struct npc_kpu_profile_action *act;
struct rvu_hwinfo *hw = rvu->hw;
int num_pkinds, idx;
@@ -665,9 +675,15 @@ void npc_cn20k_parser_profile_init(struct rvu *rvu, int blkaddr)
num_pkinds = rvu->kpu.pkinds;
num_pkinds = min_t(int, hw->npc_pkinds, num_pkinds);
- for (idx = 0; idx < num_pkinds; idx++)
- npc_config_kpmaction(rvu, blkaddr, &rvu->kpu.ikpu[idx],
+ /* Cn20k does not support Custom profile from filesystem */
+ for (idx = 0; idx < num_pkinds; idx++) {
+ act = npc_get_ikpu_nth_entry(rvu, idx);
+ if (!act)
+ continue;
+
+ npc_config_kpmaction(rvu, blkaddr, act,
0, idx, true);
+ }
/* Program KPM CAM and Action profiles */
npc_program_kpm_profile(rvu, blkaddr, hw->npc_kpms);
@@ -679,7 +695,7 @@ struct npc_priv_t *npc_priv_get(void)
}
static void npc_program_mkex_rx(struct rvu *rvu, int blkaddr,
- struct npc_mcam_kex_extr *mkex_extr,
+ const struct npc_mcam_kex_extr *mkex_extr,
u8 intf)
{
u8 num_extr = rvu->hw->npc_kex_extr;
@@ -708,7 +724,7 @@ static void npc_program_mkex_rx(struct rvu *rvu, int blkaddr,
}
static void npc_program_mkex_tx(struct rvu *rvu, int blkaddr,
- struct npc_mcam_kex_extr *mkex_extr,
+ const struct npc_mcam_kex_extr *mkex_extr,
u8 intf)
{
u8 num_extr = rvu->hw->npc_kex_extr;
@@ -737,7 +753,7 @@ static void npc_program_mkex_tx(struct rvu *rvu, int blkaddr,
}
static void npc_program_mkex_profile(struct rvu *rvu, int blkaddr,
- struct npc_mcam_kex_extr *mkex_extr)
+ const struct npc_mcam_kex_extr *mkex_extr)
{
struct rvu_hwinfo *hw = rvu->hw;
u8 intf;
@@ -1630,8 +1646,8 @@ npc_cn20k_update_action_entries_n_flags(struct rvu *rvu,
int npc_cn20k_apply_custom_kpu(struct rvu *rvu,
struct npc_kpu_profile_adapter *profile)
{
+ const struct npc_cn20k_kpu_profile_fwdata *fw = rvu->kpu_fwdata;
size_t hdr_sz = sizeof(struct npc_cn20k_kpu_profile_fwdata);
- struct npc_cn20k_kpu_profile_fwdata *fw = rvu->kpu_fwdata;
struct npc_kpu_profile_action *action;
struct npc_kpu_profile_cam *cam;
struct npc_kpu_fwdata *fw_kpu;
@@ -1676,8 +1692,15 @@ int npc_cn20k_apply_custom_kpu(struct rvu *rvu,
}
/* Verify if profile fits the HW */
+ if (fw->kpus > rvu->hw->npc_kpus) {
+ dev_warn(rvu->dev, "Not enough KPUs: %d > %d\n", fw->kpus,
+ rvu->hw->npc_kpus);
+ return -EINVAL;
+ }
+
+ /* Check if there is enough memory */
if (fw->kpus > profile->kpus) {
- dev_warn(rvu->dev, "Not enough KPUs: %d > %ld\n", fw->kpus,
+ dev_warn(rvu->dev, "Not enough KPUs: %d > %zu\n", fw->kpus,
profile->kpus);
return -EINVAL;
}
diff --git a/drivers/net/ethernet/marvell/octeontx2/af/npc.h b/drivers/net/ethernet/marvell/octeontx2/af/npc.h
index cefc5d70f3e4..c8c0cb68535c 100644
--- a/drivers/net/ethernet/marvell/octeontx2/af/npc.h
+++ b/drivers/net/ethernet/marvell/octeontx2/af/npc.h
@@ -265,6 +265,19 @@ struct npc_kpu_profile_cam {
u16 dp2_mask;
} __packed;
+struct npc_kpu_profile_cam2 {
+ u8 state;
+ u8 state_mask;
+ u16 dp0;
+ u16 dp0_mask;
+ u16 dp1;
+ u16 dp1_mask;
+ u16 dp2;
+ u16 dp2_mask;
+ u8 ptype;
+ u8 ptype_mask;
+} __packed;
+
struct npc_kpu_profile_action {
u8 errlev;
u8 errcode;
@@ -290,6 +303,10 @@ struct npc_kpu_profile {
int action_entries;
struct npc_kpu_profile_cam *cam;
struct npc_kpu_profile_action *action;
+ int cam_entries2;
+ int action_entries2;
+ struct npc_kpu_profile_action *action2;
+ struct npc_kpu_profile_cam2 *cam2;
};
/* NPC KPU register formats */
diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu.h b/drivers/net/ethernet/marvell/octeontx2/af/rvu.h
index a466181cf908..2a2f2287e0c0 100644
--- a/drivers/net/ethernet/marvell/octeontx2/af/rvu.h
+++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu.h
@@ -553,17 +553,19 @@ struct npc_kpu_profile_adapter {
const char *name;
u64 version;
const struct npc_lt_def_cfg *lt_def;
- const struct npc_kpu_profile_action *ikpu; /* array[pkinds] */
- const struct npc_kpu_profile *kpu; /* array[kpus] */
+ struct npc_kpu_profile_action *ikpu; /* array[pkinds] */
+ struct npc_kpu_profile_action *ikpu2; /* array[pkinds] */
+ struct npc_kpu_profile *kpu; /* array[kpus] */
union npc_mcam_key_prfl {
- struct npc_mcam_kex *mkex;
+ const struct npc_mcam_kex *mkex;
/* used for cn9k and cn10k */
- struct npc_mcam_kex_extr *mkex_extr; /* used for cn20k */
+ const struct npc_mcam_kex_extr *mkex_extr; /* used for cn20k */
} mcam_kex_prfl;
struct npc_mcam_kex_hash *mkex_hash;
bool custom;
size_t pkinds;
size_t kpus;
+ bool from_fs;
};
#define RVU_SWITCH_LBK_CHAN 63
@@ -634,7 +636,7 @@ struct rvu {
/* Firmware data */
struct rvu_fwdata *fwdata;
- void *kpu_fwdata;
+ const void *kpu_fwdata;
size_t kpu_fwdata_sz;
void __iomem *kpu_prfl_addr;
diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.c
index 5fa9e1c7ae9f..a0f97e683145 100644
--- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.c
+++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.c
@@ -1495,7 +1495,8 @@ void rvu_npc_free_mcam_entries(struct rvu *rvu, u16 pcifunc, int nixlf)
}
static void npc_program_mkex_rx(struct rvu *rvu, int blkaddr,
- struct npc_mcam_kex *mkex, u8 intf)
+ const struct npc_mcam_kex *mkex,
+ u8 intf)
{
int lid, lt, ld, fl;
@@ -1524,7 +1525,8 @@ static void npc_program_mkex_rx(struct rvu *rvu, int blkaddr,
}
static void npc_program_mkex_tx(struct rvu *rvu, int blkaddr,
- struct npc_mcam_kex *mkex, u8 intf)
+ const struct npc_mcam_kex *mkex,
+ u8 intf)
{
int lid, lt, ld, fl;
@@ -1553,7 +1555,7 @@ static void npc_program_mkex_tx(struct rvu *rvu, int blkaddr,
}
static void npc_program_mkex_profile(struct rvu *rvu, int blkaddr,
- struct npc_mcam_kex *mkex)
+ const struct npc_mcam_kex *mkex)
{
struct rvu_hwinfo *hw = rvu->hw;
u8 intf;
@@ -1693,8 +1695,12 @@ static void npc_config_kpucam(struct rvu *rvu, int blkaddr,
const struct npc_kpu_profile_cam *kpucam,
int kpu, int entry)
{
+ const struct npc_kpu_profile_cam2 *kpucam2 = (void *)kpucam;
+ struct npc_kpu_profile_adapter *profile = &rvu->kpu;
struct npc_kpu_cam cam0 = {0};
struct npc_kpu_cam cam1 = {0};
+ u64 *val = (u64 *)&cam1;
+ u64 *mask = (u64 *)&cam0;
cam1.state = kpucam->state & kpucam->state_mask;
cam1.dp0_data = kpucam->dp0 & kpucam->dp0_mask;
@@ -1706,6 +1712,14 @@ static void npc_config_kpucam(struct rvu *rvu, int blkaddr,
cam0.dp1_data = ~kpucam->dp1 & kpucam->dp1_mask;
cam0.dp2_data = ~kpucam->dp2 & kpucam->dp2_mask;
+ if (profile->from_fs) {
+ u8 ptype = kpucam2->ptype;
+ u8 pmask = kpucam2->ptype_mask;
+
+ *val |= FIELD_PREP(GENMASK_ULL(57, 56), ptype & pmask);
+ *mask |= FIELD_PREP(GENMASK_ULL(57, 56), ~ptype & pmask);
+ }
+
rvu_write64(rvu, blkaddr,
NPC_AF_KPUX_ENTRYX_CAMX(kpu, entry, 0), *(u64 *)&cam0);
rvu_write64(rvu, blkaddr,
@@ -1717,34 +1731,104 @@ u64 npc_enable_mask(int count)
return (((count) < 64) ? ~(BIT_ULL(count) - 1) : (0x00ULL));
}
+struct npc_kpu_profile_action *
+npc_get_ikpu_nth_entry(struct rvu *rvu, int n)
+{
+ struct npc_kpu_profile_adapter *profile = &rvu->kpu;
+
+ if (profile->from_fs)
+ return &profile->ikpu2[n];
+
+ return &profile->ikpu[n];
+}
+
+int
+npc_get_num_kpu_cam_entries(struct rvu *rvu,
+ const struct npc_kpu_profile *kpu_pfl)
+{
+ struct npc_kpu_profile_adapter *profile = &rvu->kpu;
+
+ if (profile->from_fs)
+ return kpu_pfl->cam_entries2;
+
+ return kpu_pfl->cam_entries;
+}
+
+struct npc_kpu_profile_cam *
+npc_get_kpu_cam_nth_entry(struct rvu *rvu,
+ const struct npc_kpu_profile *kpu_pfl, int n)
+{
+ struct npc_kpu_profile_adapter *profile = &rvu->kpu;
+
+ if (profile->from_fs)
+ return (void *)&kpu_pfl->cam2[n];
+
+ return (void *)&kpu_pfl->cam[n];
+}
+
+int
+npc_get_num_kpu_action_entries(struct rvu *rvu,
+ const struct npc_kpu_profile *kpu_pfl)
+{
+ struct npc_kpu_profile_adapter *profile = &rvu->kpu;
+
+ if (profile->from_fs)
+ return kpu_pfl->action_entries2;
+
+ return kpu_pfl->action_entries;
+}
+
+struct npc_kpu_profile_action *
+npc_get_kpu_action_nth_entry(struct rvu *rvu,
+ const struct npc_kpu_profile *kpu_pfl,
+ int n)
+{
+ struct npc_kpu_profile_adapter *profile = &rvu->kpu;
+
+ if (profile->from_fs)
+ return (void *)&kpu_pfl->action2[n];
+
+ return (void *)&kpu_pfl->action[n];
+}
+
static void npc_program_kpu_profile(struct rvu *rvu, int blkaddr, int kpu,
const struct npc_kpu_profile *profile)
{
+ int num_cam_entries, num_action_entries;
int entry, num_entries, max_entries;
u64 entry_mask;
- if (profile->cam_entries != profile->action_entries) {
+ num_cam_entries = npc_get_num_kpu_cam_entries(rvu, profile);
+ num_action_entries = npc_get_num_kpu_action_entries(rvu, profile);
+
+ if (num_cam_entries != num_action_entries) {
dev_err(rvu->dev,
"KPU%d: CAM and action entries [%d != %d] not equal\n",
- kpu, profile->cam_entries, profile->action_entries);
+ kpu, num_cam_entries, num_action_entries);
}
max_entries = rvu->hw->npc_kpu_entries;
+ WARN(num_cam_entries > max_entries,
+ "KPU%u: err: hw max entries=%u, input entries=%u\n",
+ kpu, rvu->hw->npc_kpu_entries, num_cam_entries);
+
/* Program CAM match entries for previous KPU extracted data */
- num_entries = min_t(int, profile->cam_entries, max_entries);
+ num_entries = min_t(int, num_cam_entries, max_entries);
for (entry = 0; entry < num_entries; entry++)
npc_config_kpucam(rvu, blkaddr,
- &profile->cam[entry], kpu, entry);
+ (void *)npc_get_kpu_cam_nth_entry(rvu, profile, entry),
+ kpu, entry);
/* Program this KPU's actions */
- num_entries = min_t(int, profile->action_entries, max_entries);
+ num_entries = min_t(int, num_action_entries, max_entries);
for (entry = 0; entry < num_entries; entry++)
- npc_config_kpuaction(rvu, blkaddr, &profile->action[entry],
+ npc_config_kpuaction(rvu, blkaddr,
+ (void *)npc_get_kpu_action_nth_entry(rvu, profile, entry),
kpu, entry, false);
/* Enable all programmed entries */
- num_entries = min_t(int, profile->action_entries, profile->cam_entries);
+ num_entries = min_t(int, num_action_entries, num_cam_entries);
entry_mask = npc_enable_mask(num_entries);
/* Disable first KPU_MAX_CST_ENT entries for built-in profile */
if (!rvu->kpu.custom)
@@ -1788,26 +1872,168 @@ static void npc_prepare_default_kpu(struct rvu *rvu,
npc_cn20k_update_action_entries_n_flags(rvu, profile);
}
-static int npc_apply_custom_kpu(struct rvu *rvu,
- struct npc_kpu_profile_adapter *profile)
+static int npc_alloc_kpu_cam2_n_action2(struct rvu *rvu, int kpu_num,
+ int num_entries)
+{
+ struct npc_kpu_profile_adapter *adapter = &rvu->kpu;
+ struct npc_kpu_profile *kpu;
+
+ kpu = &adapter->kpu[kpu_num];
+
+ kpu->cam2 = devm_kcalloc(rvu->dev, num_entries,
+ sizeof(*kpu->cam2), GFP_KERNEL);
+ if (!kpu->cam2)
+ return -ENOMEM;
+
+ kpu->action2 = devm_kcalloc(rvu->dev, num_entries,
+ sizeof(*kpu->action2), GFP_KERNEL);
+ if (!kpu->action2)
+ return -ENOMEM;
+
+ return 0;
+}
+
+static int npc_apply_custom_kpu_from_fw(struct rvu *rvu,
+ struct npc_kpu_profile_adapter *profile)
{
size_t hdr_sz = sizeof(struct npc_kpu_profile_fwdata), offset = 0;
+ const struct npc_kpu_profile_fwdata *fw;
struct npc_kpu_profile_action *action;
- struct npc_kpu_profile_fwdata *fw;
struct npc_kpu_profile_cam *cam;
struct npc_kpu_fwdata *fw_kpu;
- int entries;
- u16 kpu, entry;
+ int entries, entry, kpu;
- if (is_cn20k(rvu->pdev))
- return npc_cn20k_apply_custom_kpu(rvu, profile);
+ fw = rvu->kpu_fwdata;
+
+ for (kpu = 0; kpu < fw->kpus; kpu++) {
+ if (rvu->kpu_fwdata_sz < hdr_sz + offset) {
+ dev_warn(rvu->dev,
+ "Profile size mismatch on KPU%i parsing\n",
+ kpu + 1);
+ return -EINVAL;
+ }
+
+ fw_kpu = (struct npc_kpu_fwdata *)(fw->data + offset);
+ if (fw_kpu->entries > KPU_MAX_CST_ENT)
+ dev_warn(rvu->dev,
+ "Too many custom entries on KPU%d: %d > %d\n",
+ kpu, fw_kpu->entries, KPU_MAX_CST_ENT);
+ entries = min_t(int, fw_kpu->entries, KPU_MAX_CST_ENT);
+ cam = (struct npc_kpu_profile_cam *)fw_kpu->data;
+ offset += sizeof(*fw_kpu) + fw_kpu->entries * sizeof(*cam);
+ action = (struct npc_kpu_profile_action *)(fw->data + offset);
+ offset += fw_kpu->entries * sizeof(*action);
+ if (rvu->kpu_fwdata_sz < hdr_sz + offset) {
+ dev_warn(rvu->dev,
+ "Profile size mismatch on KPU%i parsing.\n",
+ kpu + 1);
+ return -EINVAL;
+ }
+ for (entry = 0; entry < entries; entry++) {
+ profile->kpu[kpu].cam[entry] = cam[entry];
+ profile->kpu[kpu].action[entry] = action[entry];
+ }
+ }
+
+ return 0;
+}
+
+static int npc_apply_custom_kpu_from_fs(struct rvu *rvu,
+ struct npc_kpu_profile_adapter *profile)
+{
+ size_t hdr_sz = sizeof(struct npc_kpu_profile_fwdata), offset = 0;
+ const struct npc_kpu_profile_fwdata *fw;
+ struct npc_kpu_profile_action *action;
+ struct npc_kpu_profile_cam2 *cam2;
+ struct npc_kpu_fwdata *fw_kpu;
+ int entries, ret, entry, kpu;
fw = rvu->kpu_fwdata;
+ /* Binary blob contains ikpu actions entries at start of data[0] */
+ profile->ikpu2 = devm_kcalloc(rvu->dev, 1,
+ sizeof(ikpu_action_entries),
+ GFP_KERNEL);
+ if (!profile->ikpu2)
+ return -ENOMEM;
+
+ action = (struct npc_kpu_profile_action *)(fw->data + offset);
+
+ if (rvu->kpu_fwdata_sz < hdr_sz + sizeof(ikpu_action_entries))
+ return -EINVAL;
+
+ /* The firmware layout does dependent on the internal size of
+ * ikpu_action_entries.
+ */
+ memcpy((void *)profile->ikpu2, action, sizeof(ikpu_action_entries));
+ offset += sizeof(ikpu_action_entries);
+
+ for (kpu = 0; kpu < fw->kpus; kpu++) {
+ if (rvu->kpu_fwdata_sz < hdr_sz + offset + sizeof(*fw_kpu)) {
+ dev_warn(rvu->dev,
+ "profile size mismatch on kpu%i parsing\n",
+ kpu + 1);
+ return -EINVAL;
+ }
+
+ fw_kpu = (struct npc_kpu_fwdata *)(fw->data + offset);
+ if (fw_kpu->entries <= 0) {
+ dev_warn(rvu->dev,
+ "Invalid kpu entries on KPU%d\n", kpu);
+ return -EINVAL;
+ }
+
+ entries = min_t(int, fw_kpu->entries, rvu->hw->npc_kpu_entries);
+ dev_info(rvu->dev,
+ "Loading %u entries on KPU%d\n", entries, kpu);
+
+ cam2 = (struct npc_kpu_profile_cam2 *)fw_kpu->data;
+ offset += sizeof(*fw_kpu) + fw_kpu->entries * sizeof(*cam2);
+ action = (struct npc_kpu_profile_action *)(fw->data + offset);
+ offset += fw_kpu->entries * sizeof(*action);
+ if (rvu->kpu_fwdata_sz < hdr_sz + offset) {
+ dev_warn(rvu->dev,
+ "profile size mismatch on kpu%i parsing.\n",
+ kpu + 1);
+ return -EINVAL;
+ }
+
+ profile->kpu[kpu].cam_entries2 = entries;
+ profile->kpu[kpu].action_entries2 = entries;
+ ret = npc_alloc_kpu_cam2_n_action2(rvu, kpu, entries);
+ if (ret) {
+ dev_warn(rvu->dev,
+ "profile entry allocation failed for kpu=%d for %d entries\n",
+ kpu, entries);
+ return -EINVAL;
+ }
+
+ for (entry = 0; entry < entries; entry++) {
+ profile->kpu[kpu].cam2[entry] = cam2[entry];
+ profile->kpu[kpu].action2[entry] = action[entry];
+ }
+ }
+
+ return 0;
+}
+
+static int npc_apply_custom_kpu(struct rvu *rvu,
+ struct npc_kpu_profile_adapter *profile,
+ bool from_fs, int *fw_kpus)
+{
+ size_t hdr_sz = sizeof(struct npc_kpu_profile_fwdata);
+ const struct npc_kpu_profile_fwdata *fw;
+ struct npc_kpu_profile_fwdata *sfw;
+
+ if (is_cn20k(rvu->pdev))
+ return npc_cn20k_apply_custom_kpu(rvu, profile);
+
if (rvu->kpu_fwdata_sz < hdr_sz) {
dev_warn(rvu->dev, "Invalid KPU profile size\n");
return -EINVAL;
}
+
+ fw = rvu->kpu_fwdata;
if (le64_to_cpu(fw->signature) != KPU_SIGN) {
dev_warn(rvu->dev, "Invalid KPU profile signature %llx\n",
fw->signature);
@@ -1835,42 +2061,38 @@ static int npc_apply_custom_kpu(struct rvu *rvu,
return -EINVAL;
}
/* Verify if profile fits the HW */
+ if (fw->kpus > rvu->hw->npc_kpus) {
+ dev_warn(rvu->dev, "Not enough KPUs: %d > %d\n", fw->kpus,
+ rvu->hw->npc_kpus);
+ return -EINVAL;
+ }
+
+ /* Check if there is enough memory for fw loading.
+ * Check if there is enough entries for profile->kpu[] to
+ * set cam_entries2 and action_entries2
+ */
if (fw->kpus > profile->kpus) {
- dev_warn(rvu->dev, "Not enough KPUs: %d > %ld\n", fw->kpus,
+ dev_warn(rvu->dev, "Not enough KPUs: %d > %zu\n", fw->kpus,
profile->kpus);
return -EINVAL;
}
+ *fw_kpus = fw->kpus;
+
+ sfw = devm_kcalloc(rvu->dev, 1, sizeof(*sfw), GFP_KERNEL);
+ if (!sfw)
+ return -ENOMEM;
+
+ memcpy(sfw, fw, sizeof(*sfw));
+
profile->custom = 1;
- profile->name = fw->name;
+ profile->name = sfw->name;
profile->version = le64_to_cpu(fw->version);
- profile->mcam_kex_prfl.mkex = &fw->mkex;
- profile->lt_def = &fw->lt_def;
+ profile->mcam_kex_prfl.mkex = &sfw->mkex;
+ profile->lt_def = &sfw->lt_def;
- for (kpu = 0; kpu < fw->kpus; kpu++) {
- fw_kpu = (struct npc_kpu_fwdata *)(fw->data + offset);
- if (fw_kpu->entries > KPU_MAX_CST_ENT)
- dev_warn(rvu->dev,
- "Too many custom entries on KPU%d: %d > %d\n",
- kpu, fw_kpu->entries, KPU_MAX_CST_ENT);
- entries = min(fw_kpu->entries, KPU_MAX_CST_ENT);
- cam = (struct npc_kpu_profile_cam *)fw_kpu->data;
- offset += sizeof(*fw_kpu) + fw_kpu->entries * sizeof(*cam);
- action = (struct npc_kpu_profile_action *)(fw->data + offset);
- offset += fw_kpu->entries * sizeof(*action);
- if (rvu->kpu_fwdata_sz < hdr_sz + offset) {
- dev_warn(rvu->dev,
- "Profile size mismatch on KPU%i parsing.\n",
- kpu + 1);
- return -EINVAL;
- }
- for (entry = 0; entry < entries; entry++) {
- profile->kpu[kpu].cam[entry] = cam[entry];
- profile->kpu[kpu].action[entry] = action[entry];
- }
- }
-
- return 0;
+ return from_fs ? npc_apply_custom_kpu_from_fs(rvu, profile) :
+ npc_apply_custom_kpu_from_fw(rvu, profile);
}
static int npc_load_kpu_prfl_img(struct rvu *rvu, void __iomem *prfl_addr,
@@ -1958,45 +2180,19 @@ static int npc_load_kpu_profile_fwdb(struct rvu *rvu, const char *kpu_profile)
return ret;
}
-void npc_load_kpu_profile(struct rvu *rvu)
+static int npc_load_kpu_profile_from_fw(struct rvu *rvu)
{
struct npc_kpu_profile_adapter *profile = &rvu->kpu;
const char *kpu_profile = rvu->kpu_pfl_name;
- const struct firmware *fw = NULL;
- bool retry_fwdb = false;
-
- /* If user not specified profile customization */
- if (!strncmp(kpu_profile, def_pfl_name, KPU_NAME_LEN))
- goto revert_to_default;
- /* First prepare default KPU, then we'll customize top entries. */
- npc_prepare_default_kpu(rvu, profile);
+ int fw_kpus = 0;
- /* Order of preceedence for load loading NPC profile (high to low)
- * Firmware binary in filesystem.
- * Firmware database method.
- * Default KPU profile.
- */
- if (!request_firmware_direct(&fw, kpu_profile, rvu->dev)) {
- dev_info(rvu->dev, "Loading KPU profile from firmware: %s\n",
- kpu_profile);
- rvu->kpu_fwdata = kzalloc(fw->size, GFP_KERNEL);
- if (rvu->kpu_fwdata) {
- memcpy(rvu->kpu_fwdata, fw->data, fw->size);
- rvu->kpu_fwdata_sz = fw->size;
- }
- release_firmware(fw);
- retry_fwdb = true;
- goto program_kpu;
- }
-
-load_image_fwdb:
/* Loading the KPU profile using firmware database */
if (npc_load_kpu_profile_fwdb(rvu, kpu_profile))
- goto revert_to_default;
+ return -EFAULT;
-program_kpu:
/* Apply profile customization if firmware was loaded. */
- if (!rvu->kpu_fwdata_sz || npc_apply_custom_kpu(rvu, profile)) {
+ if (!rvu->kpu_fwdata_sz ||
+ npc_apply_custom_kpu(rvu, profile, false, &fw_kpus)) {
/* If image from firmware filesystem fails to load or invalid
* retry with firmware database method.
*/
@@ -2010,10 +2206,6 @@ void npc_load_kpu_profile(struct rvu *rvu)
}
rvu->kpu_fwdata = NULL;
rvu->kpu_fwdata_sz = 0;
- if (retry_fwdb) {
- retry_fwdb = false;
- goto load_image_fwdb;
- }
}
dev_warn(rvu->dev,
@@ -2021,22 +2213,98 @@ void npc_load_kpu_profile(struct rvu *rvu)
kpu_profile);
kfree(rvu->kpu_fwdata);
rvu->kpu_fwdata = NULL;
- goto revert_to_default;
+ return -EFAULT;
}
- dev_info(rvu->dev, "Using custom profile '%s', version %d.%d.%d\n",
+ dev_info(rvu->dev, "Using custom profile '%.32s', version %d.%d.%d\n",
profile->name, NPC_KPU_VER_MAJ(profile->version),
NPC_KPU_VER_MIN(profile->version),
NPC_KPU_VER_PATCH(profile->version));
- return;
+ return 0;
+}
+
+static int npc_load_kpu_profile_from_fs(struct rvu *rvu)
+{
+ struct npc_kpu_profile_adapter *profile = &rvu->kpu;
+ const char *kpu_profile = rvu->kpu_pfl_name;
+ const struct firmware *fw = NULL;
+ int ret, fw_kpus = 0;
+ char path[512] = "kpu/";
+
+ if (strlen(kpu_profile) > sizeof(path) - strlen("kpu/") - 1) {
+ dev_err(rvu->dev, "kpu profile name is too big\n");
+ return -ENOSPC;
+ }
+
+ strcat(path, kpu_profile);
+
+ if (request_firmware_direct(&fw, path, rvu->dev))
+ return -ENOENT;
+
+ dev_info(rvu->dev, "Loading KPU profile from filesystem: %s\n",
+ path);
+
+ rvu->kpu_fwdata = fw->data;
+ rvu->kpu_fwdata_sz = fw->size;
+
+ ret = npc_apply_custom_kpu(rvu, profile, true, &fw_kpus);
+ release_firmware(fw);
+ rvu->kpu_fwdata = NULL;
+
+ if (ret) {
+ rvu->kpu_fwdata_sz = 0;
+ dev_err(rvu->dev,
+ "Loading KPU profile from filesystem failed\n");
+ return ret;
+ }
+
+ rvu->kpu.kpus = fw_kpus;
+ profile->kpus = fw_kpus;
+ profile->from_fs = true;
+ return 0;
+}
+
+void npc_load_kpu_profile(struct rvu *rvu)
+{
+ struct npc_kpu_profile_adapter *profile = &rvu->kpu;
+ const char *kpu_profile = rvu->kpu_pfl_name;
+
+ profile->from_fs = false;
+
+ npc_prepare_default_kpu(rvu, profile);
+
+ /* If user not specified profile customization */
+ if (!strncmp(kpu_profile, def_pfl_name, KPU_NAME_LEN))
+ return;
+
+ /* Order of preceedence for load loading NPC profile (high to low)
+ * Firmware binary in filesystem.
+ * Firmware database method.
+ * Default KPU profile.
+ */
+
+ /* Filesystem-based KPU loading is not supported on cn20k.
+ * npc_prepare_default_kpu() was invoked earlier, but control
+ * reached this point because the default profile was not selected.
+ * No need to call it again.
+ */
+ if (!is_cn20k(rvu->pdev)) {
+ if (!npc_load_kpu_profile_from_fs(rvu))
+ return;
+ }
+
+ /* First prepare default KPU, then we'll customize top entries. */
+ npc_prepare_default_kpu(rvu, profile);
+ if (!npc_load_kpu_profile_from_fw(rvu))
+ return;
-revert_to_default:
npc_prepare_default_kpu(rvu, profile);
}
static void npc_parser_profile_init(struct rvu *rvu, int blkaddr)
{
+ struct npc_kpu_profile_adapter *profile = &rvu->kpu;
struct rvu_hwinfo *hw = rvu->hw;
int num_pkinds, num_kpus, idx;
@@ -2060,7 +2328,9 @@ static void npc_parser_profile_init(struct rvu *rvu, int blkaddr)
num_pkinds = min_t(int, hw->npc_pkinds, num_pkinds);
for (idx = 0; idx < num_pkinds; idx++)
- npc_config_kpuaction(rvu, blkaddr, &rvu->kpu.ikpu[idx], 0, idx, true);
+ npc_config_kpuaction(rvu, blkaddr,
+ npc_get_ikpu_nth_entry(rvu, idx),
+ 0, idx, true);
/* Program KPU CAM and Action profiles */
num_kpus = rvu->kpu.kpus;
@@ -2068,6 +2338,11 @@ static void npc_parser_profile_init(struct rvu *rvu, int blkaddr)
for (idx = 0; idx < num_kpus; idx++)
npc_program_kpu_profile(rvu, blkaddr, idx, &rvu->kpu.kpu[idx]);
+
+ if (profile->from_fs) {
+ rvu_write64(rvu, blkaddr, NPC_AF_PKINDX_TYPE(54), 0x03);
+ rvu_write64(rvu, blkaddr, NPC_AF_PKINDX_TYPE(58), 0x03);
+ }
}
void npc_mcam_rsrcs_deinit(struct rvu *rvu)
@@ -2297,18 +2572,21 @@ static void rvu_npc_hw_init(struct rvu *rvu, int blkaddr)
static void rvu_npc_setup_interfaces(struct rvu *rvu, int blkaddr)
{
- struct npc_mcam_kex_extr *mkex_extr = rvu->kpu.mcam_kex_prfl.mkex_extr;
- struct npc_mcam_kex *mkex = rvu->kpu.mcam_kex_prfl.mkex;
+ const struct npc_mcam_kex_extr *mkex_extr;
struct npc_mcam *mcam = &rvu->hw->mcam;
struct rvu_hwinfo *hw = rvu->hw;
+ const struct npc_mcam_kex *mkex;
u64 nibble_ena, rx_kex, tx_kex;
u64 *keyx_cfg, reg;
u8 intf;
+ mkex_extr = rvu->kpu.mcam_kex_prfl.mkex_extr;
+ mkex = rvu->kpu.mcam_kex_prfl.mkex;
+
if (is_cn20k(rvu->pdev)) {
- keyx_cfg = mkex_extr->keyx_cfg;
+ keyx_cfg = (u64 *)mkex_extr->keyx_cfg;
} else {
- keyx_cfg = mkex->keyx_cfg;
+ keyx_cfg = (u64 *)mkex->keyx_cfg;
/* Reserve last counter for MCAM RX miss action which is set to
* drop packet. This way we will know how many pkts didn't
* match any MCAM entry.
diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.h b/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.h
index 83c5e32e2afc..662f6693cfe9 100644
--- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.h
+++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.h
@@ -18,4 +18,21 @@ int npc_fwdb_prfl_img_map(struct rvu *rvu, void __iomem **prfl_img_addr,
void npc_mcam_clear_bit(struct npc_mcam *mcam, u16 index);
void npc_mcam_set_bit(struct npc_mcam *mcam, u16 index);
+
+struct npc_kpu_profile_action *
+npc_get_ikpu_nth_entry(struct rvu *rvu, int n);
+
+int
+npc_get_num_kpu_cam_entries(struct rvu *rvu,
+ const struct npc_kpu_profile *kpu_pfl);
+struct npc_kpu_profile_cam *
+npc_get_kpu_cam_nth_entry(struct rvu *rvu,
+ const struct npc_kpu_profile *kpu_pfl, int n);
+
+int
+npc_get_num_kpu_action_entries(struct rvu *rvu,
+ const struct npc_kpu_profile *kpu_pfl);
+struct npc_kpu_profile_action *
+npc_get_kpu_action_nth_entry(struct rvu *rvu,
+ const struct npc_kpu_profile *kpu_pfl, int n);
#endif /* RVU_NPC_H */
diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_reg.h b/drivers/net/ethernet/marvell/octeontx2/af/rvu_reg.h
index 62cdc714ba57..ab89b8c6e490 100644
--- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_reg.h
+++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_reg.h
@@ -596,6 +596,7 @@
#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)
+#define NPC_AF_PKINDX_TYPE(a) (0x80010ull | (a) << 6)
#define NPC_AF_PKINDX_CPI_DEFX(a, b) (0x80020ull | (a) << 6 | (b) << 3)
#define NPC_AF_KPUX_ENTRYX_CAMX(a, b, c) \
(0x100000 | (a) << 14 | (b) << 6 | (c) << 3)
--
2.43.0
^ permalink raw reply related [flat|nested] 22+ messages in thread* Re: [PATCH v12 net-next 7/9] octeontx2-af: npc: Support for custom KPU profile from filesystem
2026-05-08 3:49 ` [PATCH v12 net-next 7/9] octeontx2-af: npc: Support for custom KPU profile from filesystem Ratheesh Kannoth
@ 2026-05-11 3:23 ` Ratheesh Kannoth
2026-05-11 3:27 ` Ratheesh Kannoth
2026-05-11 11:55 ` [Intel-wired-lan] " Loktionov, Aleksandr
2 siblings, 0 replies; 22+ messages in thread
From: Ratheesh Kannoth @ 2026-05-11 3:23 UTC (permalink / raw)
To: intel-wired-lan, linux-kernel, linux-rdma, netdev, oss-drivers
Cc: akiyano, andrew+netdev, anthony.l.nguyen, arkadiusz.kubalewski,
brett.creeley, darinzon, davem, donald.hunter, edumazet, horms,
idosch, ivecera, jiri, kuba, leon, mbloch, michael.chan, pabeni,
pavan.chebbi, petrm, Prathosh.Satish, przemyslaw.kitszel, saeedm,
sgoutham, tariqt, vadim.fedorenko
On 2026-05-08 at 09:19:10, Ratheesh Kannoth (rkannoth@marvell.com) wrote:
> Flashing updated firmware on deployed devices is cumbersome. Provide a
> mechanism to load a custom KPU (Key Parse Unit) profile directly from
> the filesystem at module load time.
>
> When the rvu_af module is loaded with the kpu_profile parameter, the
> specified profile is read from /lib/firmware/kpu and programmed into
> the KPU registers. Add npc_kpu_profile_cam2 for the extended cam format
> used by filesystem-loaded profiles and support ptype/ptype_mask in
> npc_config_kpucam when profile->from_fs is set.
pw-bot: changes-requested
>> -static int otx2_mcam_pfl_info_get(struct otx2_nic *pfvf, bool *is_x2,
>> - u16 *x4_slots)
>> +static int otx2_mcam_pfl_info_get(struct otx2_nic *pfvf, u16 *x4_slots, u8 *kw_type)
>> {
>> struct npc_get_pfl_info_rsp *rsp;
>> struct msg_req *req;
>> static struct {
>> bool is_set;
>> - bool is_x2;
>> + u8 kw_type;
>> u16 x4_slots;
>> } pfl_info;
>Does caching this profile information in a static structure cause a data
>race across concurrent device instances?
>The accesses to this shared cache are protected by mutex_lock(&pfvf->mbox.lock).
>Since this is a per-device instance lock, multiple network devices could
>concurrently acquire their own independent locks and read or write the shared
>pfl_info structure.
>Could this lack of synchronization lead to torn reads, such as reading x4_slots
>as 0 if the compiler reorders the write to is_set before x4_slots?
PF request as thru mbox, and mbox message handling is serialized in AF. So there is
no scope for race.
^ permalink raw reply [flat|nested] 22+ messages in thread* Re: [PATCH v12 net-next 7/9] octeontx2-af: npc: Support for custom KPU profile from filesystem
2026-05-08 3:49 ` [PATCH v12 net-next 7/9] octeontx2-af: npc: Support for custom KPU profile from filesystem Ratheesh Kannoth
2026-05-11 3:23 ` Ratheesh Kannoth
@ 2026-05-11 3:27 ` Ratheesh Kannoth
2026-05-11 11:55 ` [Intel-wired-lan] " Loktionov, Aleksandr
2 siblings, 0 replies; 22+ messages in thread
From: Ratheesh Kannoth @ 2026-05-11 3:27 UTC (permalink / raw)
To: intel-wired-lan, linux-kernel, linux-rdma, netdev, oss-drivers
Cc: akiyano, andrew+netdev, anthony.l.nguyen, arkadiusz.kubalewski,
brett.creeley, darinzon, davem, donald.hunter, edumazet, horms,
idosch, ivecera, jiri, kuba, leon, mbloch, michael.chan, pabeni,
pavan.chebbi, petrm, Prathosh.Satish, przemyslaw.kitszel, saeedm,
sgoutham, tariqt, vadim.fedorenko
On 2026-05-08 at 09:19:10, Ratheesh Kannoth (rkannoth@marvell.com) wrote:
> Flashing updated firmware on deployed devices is cumbersome. Provide a
> mechanism to load a custom KPU (Key Parse Unit) profile directly from
> the filesystem at module load time.
>
> When the rvu_af module is loaded with the kpu_profile parameter, the
> specified profile is read from /lib/firmware/kpu and programmed into
> the KPU registers. Add npc_kpu_profile_cam2 for the extended cam format
> used by filesystem-loaded profiles and support ptype/ptype_mask in
pw-bot: changes-requested
>> } __packed;
>>
>> +struct npc_kpu_profile_cam2 {
>> + u8 state;
>> + u8 state_mask;
>> + u16 dp0;
>> + u16 dp0_mask;
>> + u16 dp1;
>> + u16 dp1_mask;
>> + u16 dp2;
>> + u16 dp2_mask;
>Since the firmware image is little-endian, should these fields be defined as
>__le16?
>When they are accessed as host-order integers without le16_to_cpu() conversion,
>will this lead to incorrect packet parsing rules and silent data corruption on
>big-endian architectures?
The current KPU profile loading infrastructure is architecturally
coupled to a little-endian firmware format. While I acknowledge that
defining these members as u16 instead of __le16 introduces a
potential risk of silent data corruption on big-endian hosts, the
existing OcteonTX2 driver stack is currently for
little-endian operation to match the native hardware and firmware
ecosystem.
Implementing full endian-neutrality for the KPU profile involves a
deep refactoring of the firmware parser and associated hardware
abstraction layers. Given that current deployments are exclusively
little-endian, I propose addressing host-endianness portability as a
comprehensive enhancement in a future net-next series. This ensures
that endian safety is addressed systematically across the entire
driver rather than being localized to this
>> -static int npc_apply_custom_kpu(struct rvu *rvu,
>> - struct npc_kpu_profile_adapter *profile)
>> +static int npc_alloc_kpu_cam2_n_action2(struct rvu *rvu, int kpu_num,
>> + int num_entries)
>> +{
>> + struct npc_kpu_profile_adapter *adapter = &rvu->kpu;
>> + struct npc_kpu_profile *kpu;
>> +
>> + kpu = &adapter->kpu[kpu_num];
>> +
>> + kpu->cam2 = devm_kcalloc(rvu->dev, num_entries,
>> + sizeof(*kpu->cam2), GFP_KERNEL);
>> + if (!kpu->cam2)
>> + return -ENOMEM;
>> +
>> + kpu->action2 = devm_kcalloc(rvu->dev, num_entries,
>> + sizeof(*kpu->action2), GFP_KERNEL);
>Will this cause data corruption and a use-after-free across devices?
>In npc_prepare_default_kpu(), the device's profile->kpu pointer is initialized
>to point to the statically defined npc_kpu_profiles global array.
>Here, we are assigning device-scoped devm_kcalloc memory directly into this
>globally shared array. If multiple RVU devices probe concurrently, they might
>data-race on this shared state. Additionally, upon device unbind, devres will
>free the memory, leaving dangling pointers in the global array.
No. There is only one AF device and one LF for NPC. So mutluple proble of RVU af device is not
possible.
> + fw = rvu->kpu_fwdata;
>> +
>> + for (kpu = 0; kpu < fw->kpus; kpu++) {
>> + if (rvu->kpu_fwdata_sz < hdr_sz + offset) {
>> + dev_warn(rvu->dev,
>> + "Profile size mismatch on KPU%i parsing\n",
>> + kpu + 1);
>> + return -EINVAL;
>> + }
>> +
>> + fw_kpu = (struct npc_kpu_fwdata *)(fw->data + offset);
>> + if (fw_kpu->entries > KPU_MAX_CST_ENT)
>> + dev_warn(rvu->dev,
>> + "Too many custom entries on KPU%d: %d > %d\n",
>> + kpu, fw_kpu->entries, KPU_MAX_CST_ENT);
>> + entries = min_t(int, fw_kpu->entries, KPU_MAX_CST_ENT);
>> + cam = (struct npc_kpu_profile_cam *)fw_kpu->data;
>> + offset += sizeof(*fw_kpu) + fw_kpu->entries * sizeof(*cam);
>Is there a missing bounds check here for negative values?
>Since fw_kpu->entries is read as a signed int, a malicious firmware blob
>providing a negative value (e.g., -1) could cause the offset calculation to
>underflow the unsigned size_t offset.
>This would wrap the offset backwards, allowing the boundary check
>(rvu->kpu_fwdata_sz < hdr_sz + offset) to incorrectly pass in the next
>iteration, resulting in an out-of-bounds access.
ACK. Added a check to check if fw_kpu->entries < 0 and return error.
>> + /* Binary blob contains ikpu actions entries at start of data[0] */
>> + profile->ikpu2 = devm_kcalloc(rvu->dev, 1,
>> + sizeof(ikpu_action_entries),
>> + GFP_KERNEL);
>> + if (!profile->ikpu2)
>> + return -ENOMEM;
>> +
>> + action = (struct npc_kpu_profile_action *)(fw->data + offset);
>> +
>> + if (rvu->kpu_fwdata_sz < hdr_sz + sizeof(ikpu_action_entries))
>> + return -EINVAL;
>> +
>> + /* The firmware layout does dependent on the internal size of
>> + * ikpu_action_entries.
>> + */
>> + memcpy((void *)profile->ikpu2, action, sizeof(ikpu_action_entries));
>> + offset += sizeof(ikpu_action_entries);
>Will this create a fragile firmware ABI coupled to the internal kernel
>structure size?
>Because ikpu_action_entries is a kernel-internal static array, its size
>depends on the number of port kinds (NPC_MAX_PKIND) defined in the specific
>kernel version compiling it.
>If future kernel versions add elements to this array, the parser will expect a
>larger initial block than the firmware file actually provides. This would
>misalign all subsequent read offsets, causing the driver to interpret garbage
>memory.
I agree that number of ikpu entries is not part of the structure. We dont want to
add a field and break legacy ABI. Here assumption is that ikpu section entries match
number of hardware ikpu entries.
> strcat(path, kpu_profile);
>> +
>> + if (request_firmware_direct(&fw, path, rvu->dev))
>> + return -ENOENT;
>> +
>> + dev_info(rvu->dev, "Loading KPU profile from filesystem: %s\n",
>> + path);
>> +
>> + rvu->kpu_fwdata = fw->data;
>> + rvu->kpu_fwdata_sz = fw->size;
>> +
>> + ret = npc_apply_custom_kpu(rvu, profile, true, &fw_kpus);
>> + release_firmware(fw);
>> + rvu->kpu_fwdata = NULL;
>> +
>> + if (ret) {
>> + rvu->kpu_fwdata_sz = 0;
>> + dev_err(rvu->dev,
>> + "Loading KPU profile from filesystem failed\n");
>> + return ret;
>> + }
>> +
>> + rvu->kpu.kpus = fw_kpus;
>> + profile->kpus = fw_kpus;
>Does this truncate the hardware programming loop in npc_parser_profile_init()?
>By explicitly updating profile->kpus to fw_kpus, the hardware programming loop
>will only configure up to fw_kpus. Since all KPUs are disabled at the beginning
>of npc_parser_profile_init(), the remaining hardware KPUs will be left
>completely disabled, breaking network parsing for traffic reliant on default
>KPU logic.
BInary blob contains all entries fow all kpu hw entries. There is no partial loading as in
fw binary loading.
> npc_config_kpucam when profile->from_fs is set.
^ permalink raw reply [flat|nested] 22+ messages in thread* RE: [Intel-wired-lan] [PATCH v12 net-next 7/9] octeontx2-af: npc: Support for custom KPU profile from filesystem
2026-05-08 3:49 ` [PATCH v12 net-next 7/9] octeontx2-af: npc: Support for custom KPU profile from filesystem Ratheesh Kannoth
2026-05-11 3:23 ` Ratheesh Kannoth
2026-05-11 3:27 ` Ratheesh Kannoth
@ 2026-05-11 11:55 ` Loktionov, Aleksandr
2026-05-12 2:11 ` Ratheesh Kannoth
2 siblings, 1 reply; 22+ messages in thread
From: Loktionov, Aleksandr @ 2026-05-11 11:55 UTC (permalink / raw)
To: Ratheesh Kannoth, intel-wired-lan@lists.osuosl.org,
linux-kernel@vger.kernel.org, linux-rdma@vger.kernel.org,
netdev@vger.kernel.org, oss-drivers@corigine.com
Cc: akiyano@amazon.com, andrew+netdev@lunn.ch, Nguyen, Anthony L,
Kubalewski, Arkadiusz, brett.creeley@amd.com, darinzon@amazon.com,
davem@davemloft.net, donald.hunter@gmail.com, edumazet@google.com,
horms@kernel.org, idosch@nvidia.com, Vecera, Ivan,
jiri@resnulli.us, kuba@kernel.org, leon@kernel.org,
mbloch@nvidia.com, michael.chan@broadcom.com, pabeni@redhat.com,
pavan.chebbi@broadcom.com, petrm@nvidia.com,
Prathosh.Satish@microchip.com, Kitszel, Przemyslaw,
saeedm@nvidia.com, sgoutham@marvell.com, tariqt@nvidia.com,
vadim.fedorenko@linux.dev
> -----Original Message-----
> From: Intel-wired-lan <intel-wired-lan-bounces@osuosl.org> On Behalf
> Of Ratheesh Kannoth
> Sent: Friday, May 8, 2026 5:49 AM
> To: intel-wired-lan@lists.osuosl.org; linux-kernel@vger.kernel.org;
> linux-rdma@vger.kernel.org; netdev@vger.kernel.org; oss-
> drivers@corigine.com
> Cc: akiyano@amazon.com; andrew+netdev@lunn.ch; Nguyen, Anthony L
> <anthony.l.nguyen@intel.com>; Kubalewski, Arkadiusz
> <arkadiusz.kubalewski@intel.com>; brett.creeley@amd.com;
> darinzon@amazon.com; davem@davemloft.net; donald.hunter@gmail.com;
> edumazet@google.com; horms@kernel.org; idosch@nvidia.com; Vecera, Ivan
> <ivecera@redhat.com>; jiri@resnulli.us; kuba@kernel.org;
> leon@kernel.org; mbloch@nvidia.com; michael.chan@broadcom.com;
> pabeni@redhat.com; pavan.chebbi@broadcom.com; petrm@nvidia.com;
> Prathosh.Satish@microchip.com; Kitszel, Przemyslaw
> <przemyslaw.kitszel@intel.com>; saeedm@nvidia.com;
> sgoutham@marvell.com; tariqt@nvidia.com; vadim.fedorenko@linux.dev;
> Ratheesh Kannoth <rkannoth@marvell.com>
> Subject: [Intel-wired-lan] [PATCH v12 net-next 7/9] octeontx2-af: npc:
> Support for custom KPU profile from filesystem
>
> Flashing updated firmware on deployed devices is cumbersome. Provide a
> mechanism to load a custom KPU (Key Parse Unit) profile directly from
> the filesystem at module load time.
>
> When the rvu_af module is loaded with the kpu_profile parameter, the
> specified profile is read from /lib/firmware/kpu and programmed into
> the KPU registers. Add npc_kpu_profile_cam2 for the extended cam
> format used by filesystem-loaded profiles and support ptype/ptype_mask
> in npc_config_kpucam when profile->from_fs is set.
>
> Usage:
> 1. Copy the KPU profile file to /lib/firmware/kpu.
> 2. Build OCTEONTX2_AF as a module.
> 3. Load: insmod rvu_af.ko kpu_profile=<profile_name>
>
> Signed-off-by: Ratheesh Kannoth <rkannoth@marvell.com>
> ---
> .../ethernet/marvell/octeontx2/af/cn20k/npc.c | 57 ++-
> .../net/ethernet/marvell/octeontx2/af/npc.h | 17 +
> .../net/ethernet/marvell/octeontx2/af/rvu.h | 12 +-
> .../ethernet/marvell/octeontx2/af/rvu_npc.c | 456 ++++++++++++++---
> -
> .../ethernet/marvell/octeontx2/af/rvu_npc.h | 17 +
> .../ethernet/marvell/octeontx2/af/rvu_reg.h | 1 +
> 6 files changed, 449 insertions(+), 111 deletions(-)
>
> diff --git a/drivers/net/ethernet/marvell/octeontx2/af/cn20k/npc.c
> b/drivers/net/ethernet/marvell/octeontx2/af/cn20k/npc.c
> index 6f8f42234b06..67dfbe5ca903 100644
> --- a/drivers/net/ethernet/marvell/octeontx2/af/cn20k/npc.c
> +++ b/drivers/net/ethernet/marvell/octeontx2/af/cn20k/npc.c
> @@ -521,13 +521,17 @@ npc_program_single_kpm_profile(struct rvu *rvu,
> int blkaddr,
> int kpm, int start_entry,
> const struct npc_kpu_profile *profile) {
...
> +void npc_load_kpu_profile(struct rvu *rvu) {
> + struct npc_kpu_profile_adapter *profile = &rvu->kpu;
> + const char *kpu_profile = rvu->kpu_pfl_name;
> +
> + profile->from_fs = false;
> +
> + npc_prepare_default_kpu(rvu, profile);
> +
> + /* If user not specified profile customization */
> + if (!strncmp(kpu_profile, def_pfl_name, KPU_NAME_LEN))
> + return;
> +
> + /* Order of preceedence for load loading NPC profile (high to
> low)
> + * Firmware binary in filesystem.
> + * Firmware database method.
> + * Default KPU profile.
> + */
> +
> + /* Filesystem-based KPU loading is not supported on cn20k.
> + * npc_prepare_default_kpu() was invoked earlier, but control
> + * reached this point because the default profile was not
> selected.
> + * No need to call it again.
> + */
It looks like comment contradicts with the code below?
Isn't it?
> + if (!is_cn20k(rvu->pdev)) {
> + if (!npc_load_kpu_profile_from_fs(rvu))
> + return;
> + }
> +
> + /* First prepare default KPU, then we'll customize top entries.
> */
> + npc_prepare_default_kpu(rvu, profile);
> + if (!npc_load_kpu_profile_from_fw(rvu))
> + return;
>
...
> #define NPC_AF_KPUX_ENTRYX_CAMX(a, b, c) \
> (0x100000 | (a) << 14 | (b) << 6 | (c) << 3)
> --
> 2.43.0
^ permalink raw reply [flat|nested] 22+ messages in thread* Re: [Intel-wired-lan] [PATCH v12 net-next 7/9] octeontx2-af: npc: Support for custom KPU profile from filesystem
2026-05-11 11:55 ` [Intel-wired-lan] " Loktionov, Aleksandr
@ 2026-05-12 2:11 ` Ratheesh Kannoth
0 siblings, 0 replies; 22+ messages in thread
From: Ratheesh Kannoth @ 2026-05-12 2:11 UTC (permalink / raw)
To: Loktionov, Aleksandr
Cc: linux-kernel@vger.kernel.org, linux-rdma@vger.kernel.org,
netdev@vger.kernel.org, oss-drivers@corigine.com,
akiyano@amazon.com, andrew+netdev@lunn.ch, Nguyen, Anthony L,
Kubalewski, Arkadiusz, brett.creeley@amd.com, darinzon@amazon.com,
davem@davemloft.net, donald.hunter@gmail.com, edumazet@google.com,
horms@kernel.org, idosch@nvidia.com, Vecera, Ivan,
jiri@resnulli.us, kuba@kernel.org, leon@kernel.org,
mbloch@nvidia.com, michael.chan@broadcom.com, pabeni@redhat.com,
pavan.chebbi@broadcom.com, petrm@nvidia.com,
Prathosh.Satish@microchip.com, Kitszel, Przemyslaw,
saeedm@nvidia.com, sgoutham@marvell.com, tariqt@nvidia.com,
vadim.fedorenko@linux.dev
On 2026-05-11 at 17:25:39, Loktionov, Aleksandr (aleksandr.loktionov@intel.com) wrote:
> > +
> > + npc_prepare_default_kpu(rvu, profile);
> > +
> > + /* If user not specified profile customization */
> > + if (!strncmp(kpu_profile, def_pfl_name, KPU_NAME_LEN))
> > + return;
> > +
> > + /* Order of preceedence for load loading NPC profile (high to
> > low)
> > + * Firmware binary in filesystem.
> > + * Firmware database method.
> > + * Default KPU profile.
> > + */
> > +
> > + /* Filesystem-based KPU loading is not supported on cn20k.
> > + * npc_prepare_default_kpu() was invoked earlier, but control
> > + * reached this point because the default profile was not
> > selected.
> > + * No need to call it again.
> > + */
> It looks like comment contradicts with the code below?
> Isn't it?
No, there is no contradiction. Let me clarify the intent of the
comment.
npc_prepare_default_kpu() is called unconditionally at the top of
the function to ensure the hardware is always initialized with a
valid baseline KPU profile.
The strncmp(kpu_profile, def_pfl_name, KPU_NAME_LEN) check that
follows determines whether the user has explicitly requested a
non-default profile via the kpu_profile module parameter. If the
default profile name matches, we return early -- the job is
already done by npc_prepare_default_kpu().
However, if the user has specified a custom profile name,
execution continues past the early return. At that point, the
comment is clarifying that even though we are in the "custom
profile requested" code path, we must NOT call
npc_prepare_default_kpu() again -- it was already invoked above
and the HW is already initialized.
In summary: the comment is not describing what the code below
does -- it's explaining why npc_prepare_default_kpu() is
intentionally absent from the non cn20k-specific code path that
follows.
>
> > + if (!is_cn20k(rvu->pdev)) {
> > + if (!npc_load_kpu_profile_from_fs(rvu))
> > + return;
> > + }
^ permalink raw reply [flat|nested] 22+ messages in thread
* [PATCH v12 net-next 8/9] octeontx2: cn20k: Respect NPC MCAM X2/X4 profile in flows and DFT alloc
2026-05-08 3:49 [PATCH v12 net-next 0/9] octeontx2-af: npc: Enhancements Ratheesh Kannoth
` (6 preceding siblings ...)
2026-05-08 3:49 ` [PATCH v12 net-next 7/9] octeontx2-af: npc: Support for custom KPU profile from filesystem Ratheesh Kannoth
@ 2026-05-08 3:49 ` Ratheesh Kannoth
2026-05-11 3:25 ` Ratheesh Kannoth
2026-05-08 3:49 ` [PATCH v12 net-next 9/9] octeontx2-af: npc: cn20k: Allocate npc_priv and dstats dynamically Ratheesh Kannoth
8 siblings, 1 reply; 22+ messages in thread
From: Ratheesh Kannoth @ 2026-05-08 3:49 UTC (permalink / raw)
To: intel-wired-lan, linux-kernel, linux-rdma, netdev, oss-drivers
Cc: akiyano, andrew+netdev, anthony.l.nguyen, arkadiusz.kubalewski,
brett.creeley, darinzon, davem, donald.hunter, edumazet, horms,
idosch, ivecera, jiri, kuba, leon, mbloch, michael.chan, pabeni,
pavan.chebbi, petrm, Prathosh.Satish, przemyslaw.kitszel, saeedm,
sgoutham, tariqt, vadim.fedorenko, Ratheesh Kannoth
Default CN20K NPC rule allocation now keys off the active MCAM keyword
width: use X4 with a bank-masked reference index when the silicon uses
X4 keys, and X2 with the raw index otherwise (replacing the previous
always-X2 / eidx + 1 behaviour).
In the AF flow-install path, flows that need more than 256 key bits
query the NPC profile; if the platform is fixed to X2 entries, fail
with -EOPNOTSUPP instead of requesting X4. Otherwise select X4 for the
MCAM alloc.
On the PF, cache and pass the profile kw_type from npc_get_pfl_info
through otx2_mcam_pfl_info_get(), and use it when allocating MCAM
entries for RSS/defaults and when installing ethtool flows on CN20K,
including masking the reference index for X4 slot layout.
Signed-off-by: Ratheesh Kannoth <rkannoth@marvell.com>
---
.../ethernet/marvell/octeontx2/af/cn20k/npc.c | 11 ++++-
.../marvell/octeontx2/af/rvu_npc_fs.c | 12 ++++-
.../marvell/octeontx2/nic/otx2_flows.c | 48 +++++++++++++------
3 files changed, 53 insertions(+), 18 deletions(-)
diff --git a/drivers/net/ethernet/marvell/octeontx2/af/cn20k/npc.c b/drivers/net/ethernet/marvell/octeontx2/af/cn20k/npc.c
index 67dfbe5ca903..15b3f29d60ee 100644
--- a/drivers/net/ethernet/marvell/octeontx2/af/cn20k/npc.c
+++ b/drivers/net/ethernet/marvell/octeontx2/af/cn20k/npc.c
@@ -4467,11 +4467,18 @@ int npc_cn20k_dft_rules_alloc(struct rvu *rvu, u16 pcifunc)
* as NPC_DFT_RULE_PRIO - 1 (higher hw priority)
*/
req.contig = false;
- req.kw_type = NPC_MCAM_KEY_X2;
req.count = cnt;
req.hdr.pcifunc = pcifunc;
req.ref_prio = NPC_MCAM_LOWER_PRIO;
- req.ref_entry = eidx + 1;
+
+ if (npc_priv.kw == NPC_MCAM_KEY_X4) {
+ req.kw_type = NPC_MCAM_KEY_X4;
+ req.ref_entry = eidx & (npc_priv.bank_depth - 1);
+ } else {
+ req.kw_type = NPC_MCAM_KEY_X2;
+ req.ref_entry = eidx;
+ }
+
ret = rvu_mbox_handler_npc_mcam_alloc_entry(rvu, &req, &rsp);
if (ret) {
dev_err(rvu->dev,
diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc_fs.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc_fs.c
index 6ae9cdcb608b..d20eb0e47d7d 100644
--- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc_fs.c
+++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc_fs.c
@@ -1671,9 +1671,11 @@ rvu_npc_alloc_entry_for_flow_install(struct rvu *rvu,
{
struct npc_mcam_alloc_entry_req entry_req;
struct npc_mcam_alloc_entry_rsp entry_rsp;
+ struct npc_get_pfl_info_rsp rsp = { 0 };
struct npc_get_num_kws_req kws_req;
struct npc_get_num_kws_rsp kws_rsp;
int off, kw_bits, rc;
+ struct msg_req req;
u8 *src, *dst;
if (!is_cn20k(rvu->pdev)) {
@@ -1697,8 +1699,16 @@ rvu_npc_alloc_entry_for_flow_install(struct rvu *rvu,
kw_bits = kws_rsp.kws * 64;
*kw_type = NPC_MCAM_KEY_X2;
- if (kw_bits > 256)
+ if (kw_bits > 256) {
+ rvu_mbox_handler_npc_get_pfl_info(rvu, &req, &rsp);
+ if (rsp.kw_type == NPC_MCAM_KEY_X2) {
+ dev_err(rvu->dev,
+ "Only X2 entries are supported in X2 profile\n");
+ return -EOPNOTSUPP;
+ }
+
*kw_type = NPC_MCAM_KEY_X4;
+ }
memset(&entry_req, 0, sizeof(entry_req));
memset(&entry_rsp, 0, sizeof(entry_rsp));
diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_flows.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_flows.c
index 38cc539d724d..5dd0591fed99 100644
--- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_flows.c
+++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_flows.c
@@ -37,14 +37,13 @@ static void otx2_clear_ntuple_flow_info(struct otx2_nic *pfvf, struct otx2_flow_
flow_cfg->max_flows = 0;
}
-static int otx2_mcam_pfl_info_get(struct otx2_nic *pfvf, bool *is_x2,
- u16 *x4_slots)
+static int otx2_mcam_pfl_info_get(struct otx2_nic *pfvf, u16 *x4_slots, u8 *kw_type)
{
struct npc_get_pfl_info_rsp *rsp;
struct msg_req *req;
static struct {
bool is_set;
- bool is_x2;
+ u8 kw_type;
u16 x4_slots;
} pfl_info;
@@ -53,8 +52,8 @@ static int otx2_mcam_pfl_info_get(struct otx2_nic *pfvf, bool *is_x2,
*/
mutex_lock(&pfvf->mbox.lock);
if (pfl_info.is_set) {
- *is_x2 = pfl_info.is_x2;
*x4_slots = pfl_info.x4_slots;
+ *kw_type = pfl_info.kw_type;
mutex_unlock(&pfvf->mbox.lock);
return 0;
}
@@ -79,16 +78,16 @@ static int otx2_mcam_pfl_info_get(struct otx2_nic *pfvf, bool *is_x2,
return -EFAULT;
}
- *is_x2 = (rsp->kw_type == NPC_MCAM_KEY_X2);
- if (*is_x2)
- *x4_slots = 0;
+ pfl_info.kw_type = rsp->kw_type;
+ if (rsp->kw_type == NPC_MCAM_KEY_X2)
+ pfl_info.x4_slots = 0;
else
- *x4_slots = rsp->x4_slots;
-
- pfl_info.is_x2 = *is_x2;
- pfl_info.x4_slots = *x4_slots;
+ pfl_info.x4_slots = rsp->x4_slots;
pfl_info.is_set = true;
+ *x4_slots = pfl_info.x4_slots;
+ *kw_type = pfl_info.kw_type;
+
mutex_unlock(&pfvf->mbox.lock);
return 0;
}
@@ -164,6 +163,7 @@ int otx2_alloc_mcam_entries(struct otx2_nic *pfvf, u16 count)
u16 dft_idx = 0, x4_slots = 0;
int ent, allocated = 0, ref;
bool is_x2 = false;
+ u8 kw_type = 0;
int rc;
/* Free current ones and allocate new ones with requested count */
@@ -182,12 +182,14 @@ int otx2_alloc_mcam_entries(struct otx2_nic *pfvf, u16 count)
}
if (is_cn20k(pfvf->pdev)) {
- rc = otx2_mcam_pfl_info_get(pfvf, &is_x2, &x4_slots);
+ rc = otx2_mcam_pfl_info_get(pfvf, &x4_slots, &kw_type);
if (rc) {
netdev_err(pfvf->netdev, "Error to retrieve profile info\n");
return rc;
}
+ is_x2 = kw_type == NPC_MCAM_KEY_X2;
+
rc = otx2_get_dft_rl_idx(pfvf, &dft_idx);
if (rc) {
netdev_err(pfvf->netdev,
@@ -289,6 +291,8 @@ int otx2_mcam_entry_init(struct otx2_nic *pfvf)
struct npc_mcam_alloc_entry_rsp *rsp;
int vf_vlan_max_flows, count;
int rc, ref, prio, ent;
+ u8 kw_type = 0;
+ u16 x4_slots;
u16 dft_idx;
ref = 0;
@@ -315,6 +319,16 @@ int otx2_mcam_entry_init(struct otx2_nic *pfvf)
if (!flow_cfg->def_ent)
return -ENOMEM;
+ kw_type = NPC_MCAM_KEY_X2;
+ if (is_cn20k(pfvf->pdev)) {
+ rc = otx2_mcam_pfl_info_get(pfvf, &x4_slots, &kw_type);
+ if (rc) {
+ netdev_err(pfvf->netdev,
+ "Error to get pfl info\n");
+ return rc;
+ }
+ }
+
mutex_lock(&pfvf->mbox.lock);
req = otx2_mbox_alloc_msg_npc_mcam_alloc_entry(&pfvf->mbox);
@@ -324,6 +338,10 @@ int otx2_mcam_entry_init(struct otx2_nic *pfvf)
}
req->kw_type = NPC_MCAM_KEY_X2;
+ if (is_cn20k(pfvf->pdev) && kw_type == NPC_MCAM_KEY_X4) {
+ req->kw_type = NPC_MCAM_KEY_X4;
+ ref &= (x4_slots - 1);
+ }
req->contig = false;
req->count = count;
req->ref_prio = prio;
@@ -1174,15 +1192,14 @@ static int otx2_add_flow_msg(struct otx2_nic *pfvf, struct otx2_flow *flow)
#ifdef CONFIG_DCB
int vlan_prio, qidx, pfc_rule = 0;
#endif
+ bool modify = false, is_x2;
int err, vf = 0, off, sz;
- bool modify = false;
u8 kw_type = 0;
u8 *src, *dst;
u16 x4_slots;
- bool is_x2;
if (is_cn20k(pfvf->pdev)) {
- err = otx2_mcam_pfl_info_get(pfvf, &is_x2, &x4_slots);
+ err = otx2_mcam_pfl_info_get(pfvf, &x4_slots, &kw_type);
if (err) {
netdev_err(pfvf->netdev,
"Error to retrieve NPC profile info, pcifunc=%#x\n",
@@ -1190,6 +1207,7 @@ static int otx2_add_flow_msg(struct otx2_nic *pfvf, struct otx2_flow *flow)
return -EFAULT;
}
+ is_x2 = kw_type == NPC_MCAM_KEY_X2;
if (!is_x2) {
err = otx2_prepare_flow_request(&flow->flow_spec,
&treq);
--
2.43.0
^ permalink raw reply related [flat|nested] 22+ messages in thread* Re: [PATCH v12 net-next 8/9] octeontx2: cn20k: Respect NPC MCAM X2/X4 profile in flows and DFT alloc
2026-05-08 3:49 ` [PATCH v12 net-next 8/9] octeontx2: cn20k: Respect NPC MCAM X2/X4 profile in flows and DFT alloc Ratheesh Kannoth
@ 2026-05-11 3:25 ` Ratheesh Kannoth
0 siblings, 0 replies; 22+ messages in thread
From: Ratheesh Kannoth @ 2026-05-11 3:25 UTC (permalink / raw)
To: intel-wired-lan, linux-kernel, linux-rdma, netdev, oss-drivers
Cc: akiyano, andrew+netdev, anthony.l.nguyen, arkadiusz.kubalewski,
brett.creeley, darinzon, davem, donald.hunter, edumazet, horms,
idosch, ivecera, jiri, kuba, leon, mbloch, michael.chan, pabeni,
pavan.chebbi, petrm, Prathosh.Satish, przemyslaw.kitszel, saeedm,
sgoutham, tariqt, vadim.fedorenko
On 2026-05-08 at 09:19:11, Ratheesh Kannoth (rkannoth@marvell.com) wrote:
> Default CN20K NPC rule allocation now keys off the active MCAM keyword
> width: use X4 with a bank-masked reference index when the silicon uses
> X4 keys, and X2 with the raw index otherwise (replacing the previous
> always-X2 / eidx + 1 behaviour).
>
> In the AF flow-install path, flows that need more than 256 key bits
pw-bot: changes-requested
>> -static int otx2_mcam_pfl_info_get(struct otx2_nic *pfvf, bool *is_x2,
>> - u16 *x4_slots)
>> +static int otx2_mcam_pfl_info_get(struct otx2_nic *pfvf, u16 *x4_slots, u8 *kw_type)
>> {
>> struct npc_get_pfl_info_rsp *rsp;
>> struct msg_req *req;
>> static struct {
>> bool is_set;
>> - bool is_x2;
>> + u8 kw_type;
>> u16 x4_slots;
>> } pfl_info;
>Does caching this profile information in a static structure cause a data
>race across concurrent device instances?
>The accesses to this shared cache are protected by mutex_lock(&pfvf->mbox.lock).
>Since this is a per-device instance lock, multiple network devices could
>concurrently acquire their own independent locks and read or write the shared
>pfl_info structure.
>Could this lack of synchronization lead to torn reads, such as reading x4_slots
>as 0 if the compiler reorders the write to is_set before x4_slots?
PF request as thru mbox, and mbox message handling is serialized in AF. So there is
no scope for race.
^ permalink raw reply [flat|nested] 22+ messages in thread
* [PATCH v12 net-next 9/9] octeontx2-af: npc: cn20k: Allocate npc_priv and dstats dynamically.
2026-05-08 3:49 [PATCH v12 net-next 0/9] octeontx2-af: npc: Enhancements Ratheesh Kannoth
` (7 preceding siblings ...)
2026-05-08 3:49 ` [PATCH v12 net-next 8/9] octeontx2: cn20k: Respect NPC MCAM X2/X4 profile in flows and DFT alloc Ratheesh Kannoth
@ 2026-05-08 3:49 ` Ratheesh Kannoth
2026-05-11 3:26 ` Ratheesh Kannoth
8 siblings, 1 reply; 22+ messages in thread
From: Ratheesh Kannoth @ 2026-05-08 3:49 UTC (permalink / raw)
To: intel-wired-lan, linux-kernel, linux-rdma, netdev, oss-drivers
Cc: akiyano, andrew+netdev, anthony.l.nguyen, arkadiusz.kubalewski,
brett.creeley, darinzon, davem, donald.hunter, edumazet, horms,
idosch, ivecera, jiri, kuba, leon, mbloch, michael.chan, pabeni,
pavan.chebbi, petrm, Prathosh.Satish, przemyslaw.kitszel, saeedm,
sgoutham, tariqt, vadim.fedorenko, Ratheesh Kannoth
Replace the file-scope static npc_priv with a kcalloc'd struct filled
from hardware bank/subbank geometry at init (num_banks is no longer a
const compile-time constant; drop init_done and use a non-NULL
npc_priv pointer for liveness). Thread npc_priv_get() / pointer access
through the CN20K NPC code paths, extend teardown to kfree the root
struct on failure and in npc_cn20k_deinit, and adjust MCAM section
setup to use the discovered subbank count.
Allocate MCAM debugfs dstats via devm_kzalloc instead of a static matrix,
and use the allocated backing store consistently when computing deltas
(including the counter rollover compare).
Signed-off-by: Ratheesh Kannoth <rkannoth@marvell.com>
---
.../marvell/octeontx2/af/cn20k/debugfs.c | 18 +-
.../ethernet/marvell/octeontx2/af/cn20k/npc.c | 407 +++++++++---------
.../ethernet/marvell/octeontx2/af/cn20k/npc.h | 3 +-
3 files changed, 220 insertions(+), 208 deletions(-)
diff --git a/drivers/net/ethernet/marvell/octeontx2/af/cn20k/debugfs.c b/drivers/net/ethernet/marvell/octeontx2/af/cn20k/debugfs.c
index 9a4c2ea5b19e..15af7b0ccea6 100644
--- a/drivers/net/ethernet/marvell/octeontx2/af/cn20k/debugfs.c
+++ b/drivers/net/ethernet/marvell/octeontx2/af/cn20k/debugfs.c
@@ -172,7 +172,7 @@ __OCTEONTX2_DEBUGFS_ATTRIBUTE_FOPS(__name)
static DEFINE_MUTEX(stats_lock);
-static u64 dstats[MAX_NUM_BANKS][MAX_SUBBANK_DEPTH * MAX_NUM_SUB_BANKS] = {};
+static u64 (*dstats)[MAX_NUM_BANKS][MAX_SUBBANK_DEPTH * MAX_NUM_SUB_BANKS];
static int npc_mcam_dstats_show(struct seq_file *s, void *unused)
{
struct npc_priv_t *npc_priv;
@@ -206,19 +206,19 @@ static int npc_mcam_dstats_show(struct seq_file *s, void *unused)
NPC_AF_CN20K_MCAMEX_BANKX_STAT_EXT(idx, bank));
if (!stats)
continue;
- if (stats == dstats[bank][idx])
+ if (stats == dstats[0][bank][idx])
continue;
- if (stats < dstats[bank][idx])
- dstats[bank][idx] = 0;
+ if (stats < dstats[0][bank][idx])
+ dstats[0][bank][idx] = 0;
pf = 0xFFFF;
map = xa_load(&npc_priv->xa_idx2pf_map, mcam_idx);
if (map)
pf = xa_to_value(map);
- if (stats > dstats[bank][idx])
- delta = stats - dstats[bank][idx];
+ if (stats > dstats[0][bank][idx])
+ delta = stats - dstats[0][bank][idx];
else
delta = stats;
@@ -226,7 +226,7 @@ static int npc_mcam_dstats_show(struct seq_file *s, void *unused)
mcam_idx, pf, delta);
seq_puts(s, buff);
- dstats[bank][idx] = stats;
+ dstats[0][bank][idx] = stats;
}
}
@@ -396,6 +396,10 @@ int npc_cn20k_debugfs_init(struct rvu *rvu)
debugfs_create_file("vidx2idx", 0444, rvu->rvu_dbg.npc,
npc_priv, &npc_vidx2idx_map_fops);
+ dstats = devm_kzalloc(rvu->dev, sizeof(*dstats), GFP_KERNEL);
+ if (!dstats)
+ return -ENOMEM;
+
debugfs_create_file("dstats", 0444, rvu->rvu_dbg.npc, rvu,
&npc_mcam_dstats_fops);
diff --git a/drivers/net/ethernet/marvell/octeontx2/af/cn20k/npc.c b/drivers/net/ethernet/marvell/octeontx2/af/cn20k/npc.c
index 15b3f29d60ee..ea8fc43df090 100644
--- a/drivers/net/ethernet/marvell/octeontx2/af/cn20k/npc.c
+++ b/drivers/net/ethernet/marvell/octeontx2/af/cn20k/npc.c
@@ -16,9 +16,7 @@
#include "cn20k/reg.h"
#include "rvu_npc_fs.h"
-static struct npc_priv_t npc_priv = {
- .num_banks = MAX_NUM_BANKS,
-};
+static struct npc_priv_t *npc_priv;
static const char *npc_kw_name[NPC_MCAM_KEY_MAX] = {
[NPC_MCAM_KEY_DYN] = "DYNAMIC",
@@ -226,7 +224,7 @@ static u16 npc_idx2vidx(u16 idx)
vidx = idx;
index = idx;
- map = xa_load(&npc_priv.xa_idx2vidx_map, index);
+ map = xa_load(&npc_priv->xa_idx2vidx_map, index);
if (!map)
goto done;
@@ -242,7 +240,7 @@ static u16 npc_idx2vidx(u16 idx)
static bool npc_is_vidx(u16 vidx)
{
- return vidx >= npc_priv.bank_depth * 2;
+ return vidx >= npc_priv->bank_depth * 2;
}
static u16 npc_vidx2idx(u16 vidx)
@@ -256,7 +254,7 @@ static u16 npc_vidx2idx(u16 vidx)
idx = vidx;
index = vidx;
- map = xa_load(&npc_priv.xa_vidx2idx_map, index);
+ map = xa_load(&npc_priv->xa_vidx2idx_map, index);
if (!map)
goto done;
@@ -272,7 +270,7 @@ static u16 npc_vidx2idx(u16 vidx)
u16 npc_cn20k_vidx2idx(u16 idx)
{
- if (!npc_priv.init_done)
+ if (!npc_priv)
return idx;
if (!npc_is_vidx(idx))
@@ -283,7 +281,7 @@ u16 npc_cn20k_vidx2idx(u16 idx)
u16 npc_cn20k_idx2vidx(u16 idx)
{
- if (!npc_priv.init_done)
+ if (!npc_priv)
return idx;
if (npc_is_vidx(idx))
@@ -306,7 +304,7 @@ static int npc_vidx_maps_del_entry(struct rvu *rvu, u16 vidx, u16 *old_midx)
mcam_idx = npc_vidx2idx(vidx);
- map = xa_erase(&npc_priv.xa_vidx2idx_map, vidx);
+ map = xa_erase(&npc_priv->xa_vidx2idx_map, vidx);
if (!map) {
dev_err(rvu->dev,
"%s: vidx(%u) does not map to proper mcam idx\n",
@@ -314,7 +312,7 @@ static int npc_vidx_maps_del_entry(struct rvu *rvu, u16 vidx, u16 *old_midx)
return -ESRCH;
}
- map = xa_erase(&npc_priv.xa_idx2vidx_map, mcam_idx);
+ map = xa_erase(&npc_priv->xa_idx2vidx_map, mcam_idx);
if (!map) {
dev_err(rvu->dev,
"%s: vidx(%u) is not valid\n",
@@ -341,7 +339,7 @@ static int npc_vidx_maps_modify(struct rvu *rvu, u16 vidx, u16 new_midx)
return -ESRCH;
}
- map = xa_erase(&npc_priv.xa_vidx2idx_map, vidx);
+ map = xa_erase(&npc_priv->xa_vidx2idx_map, vidx);
if (!map) {
dev_err(rvu->dev,
"%s: vidx(%u) could not be deleted from vidx2idx map\n",
@@ -351,7 +349,7 @@ static int npc_vidx_maps_modify(struct rvu *rvu, u16 vidx, u16 new_midx)
old_midx = xa_to_value(map);
- rc = xa_insert(&npc_priv.xa_vidx2idx_map, vidx,
+ rc = xa_insert(&npc_priv->xa_vidx2idx_map, vidx,
xa_mk_value(new_midx), GFP_KERNEL);
if (rc) {
dev_err(rvu->dev,
@@ -360,7 +358,7 @@ static int npc_vidx_maps_modify(struct rvu *rvu, u16 vidx, u16 new_midx)
goto fail1;
}
- map = xa_erase(&npc_priv.xa_idx2vidx_map, old_midx);
+ map = xa_erase(&npc_priv->xa_idx2vidx_map, old_midx);
if (!map) {
dev_err(rvu->dev,
"%s: old_midx(%u, vidx(%u)) cannot be added to idx2vidx map\n",
@@ -369,7 +367,7 @@ static int npc_vidx_maps_modify(struct rvu *rvu, u16 vidx, u16 new_midx)
goto fail2;
}
- rc = xa_insert(&npc_priv.xa_idx2vidx_map, new_midx,
+ rc = xa_insert(&npc_priv->xa_idx2vidx_map, new_midx,
xa_mk_value(vidx), GFP_KERNEL);
if (rc) {
dev_err(rvu->dev,
@@ -382,21 +380,21 @@ static int npc_vidx_maps_modify(struct rvu *rvu, u16 vidx, u16 new_midx)
fail3:
/* Restore vidx at old_midx location */
- if (xa_insert(&npc_priv.xa_idx2vidx_map, old_midx,
+ if (xa_insert(&npc_priv->xa_idx2vidx_map, old_midx,
xa_mk_value(vidx), GFP_KERNEL))
dev_err(rvu->dev,
"%s: Error to roll back idx2vidx old_midx=%u vidx=%u\n",
__func__, old_midx, vidx);
fail2:
/* Erase new_midx inserted at vidx */
- if (!xa_erase(&npc_priv.xa_vidx2idx_map, vidx))
+ if (!xa_erase(&npc_priv->xa_vidx2idx_map, vidx))
dev_err(rvu->dev,
"%s: Failed to roll back vidx2idx vidx=%u\n",
__func__, vidx);
fail1:
/* Restore old_midx at vidx location */
- if (xa_insert(&npc_priv.xa_vidx2idx_map, vidx,
+ if (xa_insert(&npc_priv->xa_vidx2idx_map, vidx,
xa_mk_value(old_midx), GFP_KERNEL))
dev_err(rvu->dev,
"%s: Failed to roll back vidx2idx to old_midx=%u, vidx=%u\n",
@@ -412,10 +410,10 @@ static int npc_vidx_maps_add_entry(struct rvu *rvu, u16 mcam_idx, int pcifunc,
u32 id;
/* Virtual index start from maximum mcam index + 1 */
- max = npc_priv.bank_depth * 2 * 2 - 1;
- min = npc_priv.bank_depth * 2;
+ max = npc_priv->bank_depth * 2 * 2 - 1;
+ min = npc_priv->bank_depth * 2;
- rc = xa_alloc(&npc_priv.xa_vidx2idx_map, &id,
+ rc = xa_alloc(&npc_priv->xa_vidx2idx_map, &id,
xa_mk_value(mcam_idx),
XA_LIMIT(min, max), GFP_KERNEL);
if (rc) {
@@ -425,7 +423,7 @@ static int npc_vidx_maps_add_entry(struct rvu *rvu, u16 mcam_idx, int pcifunc,
goto fail1;
}
- rc = xa_insert(&npc_priv.xa_idx2vidx_map, mcam_idx,
+ rc = xa_insert(&npc_priv->xa_idx2vidx_map, mcam_idx,
xa_mk_value(id), GFP_KERNEL);
if (rc) {
dev_err(rvu->dev,
@@ -440,7 +438,7 @@ static int npc_vidx_maps_add_entry(struct rvu *rvu, u16 mcam_idx, int pcifunc,
return 0;
fail2:
- xa_erase(&npc_priv.xa_vidx2idx_map, id);
+ xa_erase(&npc_priv->xa_vidx2idx_map, id);
fail1:
return rc;
}
@@ -691,7 +689,7 @@ void npc_cn20k_parser_profile_init(struct rvu *rvu, int blkaddr)
struct npc_priv_t *npc_priv_get(void)
{
- return &npc_priv;
+ return npc_priv;
}
static void npc_program_mkex_rx(struct rvu *rvu, int blkaddr,
@@ -860,9 +858,9 @@ npc_cn20k_enable_mcam_entry(struct rvu *rvu, int blkaddr,
update_en_map:
if (enable)
- set_bit(index, npc_priv.en_map);
+ set_bit(index, npc_priv->en_map);
else
- clear_bit(index, npc_priv.en_map);
+ clear_bit(index, npc_priv->en_map);
return 0;
}
@@ -1751,28 +1749,28 @@ int npc_mcam_idx_2_key_type(struct rvu *rvu, u16 mcam_idx, u8 *key_type)
int bank_off, sb_id;
/* mcam_idx should be less than (2 * bank depth) */
- if (mcam_idx >= npc_priv.bank_depth * 2) {
+ if (mcam_idx >= npc_priv->bank_depth * 2) {
dev_err(rvu->dev, "%s: bad params\n",
__func__);
return -EINVAL;
}
/* find mcam offset per bank */
- bank_off = mcam_idx & (npc_priv.bank_depth - 1);
+ bank_off = mcam_idx & (npc_priv->bank_depth - 1);
/* Find subbank id */
- sb_id = bank_off / npc_priv.subbank_depth;
+ sb_id = bank_off / npc_priv->subbank_depth;
/* Check if subbank id is more than maximum
* number of subbanks available
*/
- if (sb_id >= npc_priv.num_subbanks) {
+ if (sb_id >= npc_priv->num_subbanks) {
dev_err(rvu->dev, "%s: invalid subbank %d\n",
__func__, sb_id);
return -EINVAL;
}
- sb = &npc_priv.sb[sb_id];
+ sb = &npc_priv->sb[sb_id];
*key_type = sb->key_type;
@@ -1788,7 +1786,7 @@ static int npc_subbank_idx_2_mcam_idx(struct rvu *rvu, struct npc_subbank *sb,
* subsection depth - 1
*/
if (sb->key_type == NPC_MCAM_KEY_X4 &&
- sub_off >= npc_priv.subbank_depth) {
+ sub_off >= npc_priv->subbank_depth) {
dev_err(rvu->dev,
"%s: Failed to get mcam idx (x4) sb->idx=%u sub_off=%u",
__func__, sb->idx, sub_off);
@@ -1799,7 +1797,7 @@ static int npc_subbank_idx_2_mcam_idx(struct rvu *rvu, struct npc_subbank *sb,
* 2 * subsection depth - 1
*/
if (sb->key_type == NPC_MCAM_KEY_X2 &&
- sub_off >= npc_priv.subbank_depth * 2) {
+ sub_off >= npc_priv->subbank_depth * 2) {
dev_err(rvu->dev,
"%s: Failed to get mcam idx (x2) sb->idx=%u sub_off=%u",
__func__, sb->idx, sub_off);
@@ -1807,12 +1805,12 @@ static int npc_subbank_idx_2_mcam_idx(struct rvu *rvu, struct npc_subbank *sb,
}
/* Find subbank offset from respective subbank (w.r.t bank) */
- off = sub_off & (npc_priv.subbank_depth - 1);
+ off = sub_off & (npc_priv->subbank_depth - 1);
/* if subsection idx is in bank1, add bank depth,
* which is part of sb->b1b
*/
- bot = sub_off >= npc_priv.subbank_depth ? sb->b1b : sb->b0b;
+ bot = sub_off >= npc_priv->subbank_depth ? sb->b1b : sb->b0b;
*mcam_idx = bot + off;
return 0;
@@ -1825,37 +1823,37 @@ int npc_mcam_idx_2_subbank_idx(struct rvu *rvu, u16 mcam_idx,
int bank_off, sb_id;
/* mcam_idx should be less than (2 * bank depth) */
- if (mcam_idx >= npc_priv.bank_depth * 2) {
+ if (mcam_idx >= npc_priv->bank_depth * 2) {
dev_err(rvu->dev, "%s: Invalid mcam idx %u\n",
__func__, mcam_idx);
return -EINVAL;
}
/* find mcam offset per bank */
- bank_off = mcam_idx & (npc_priv.bank_depth - 1);
+ bank_off = mcam_idx & (npc_priv->bank_depth - 1);
/* Find subbank id */
- sb_id = bank_off / npc_priv.subbank_depth;
+ sb_id = bank_off / npc_priv->subbank_depth;
/* Check if subbank id is more than maximum
* number of subbanks available
*/
- if (sb_id >= npc_priv.num_subbanks) {
+ if (sb_id >= npc_priv->num_subbanks) {
dev_err(rvu->dev, "%s: invalid subbank %d\n",
__func__, sb_id);
return -EINVAL;
}
- *sb = &npc_priv.sb[sb_id];
+ *sb = &npc_priv->sb[sb_id];
/* Subbank offset per bank */
- *sb_off = bank_off % npc_priv.subbank_depth;
+ *sb_off = bank_off % npc_priv->subbank_depth;
/* Index in a subbank should add subbank depth
* if it is in bank1
*/
- if (mcam_idx >= npc_priv.bank_depth)
- *sb_off += npc_priv.subbank_depth;
+ if (mcam_idx >= npc_priv->bank_depth)
+ *sb_off += npc_priv->subbank_depth;
return 0;
}
@@ -1871,9 +1869,9 @@ static int __npc_subbank_contig_alloc(struct rvu *rvu,
int k, offset, delta = 0;
int cnt = 0, sbd;
- sbd = npc_priv.subbank_depth;
+ sbd = npc_priv->subbank_depth;
- if (sidx >= npc_priv.bank_depth)
+ if (sidx >= npc_priv->bank_depth)
delta = sbd;
switch (prio) {
@@ -1940,8 +1938,8 @@ static int __npc_subbank_non_contig_alloc(struct rvu *rvu,
int cnt = 0, delta;
int k, sbd;
- sbd = npc_priv.subbank_depth;
- delta = sidx >= npc_priv.bank_depth ? sbd : 0;
+ sbd = npc_priv->subbank_depth;
+ delta = sidx >= npc_priv->bank_depth ? sbd : 0;
switch (prio) {
/* Find an area of size 'count' from sidx to eidx */
@@ -2002,7 +2000,7 @@ static void __npc_subbank_sboff_2_off(struct rvu *rvu, struct npc_subbank *sb,
{
int sbd;
- sbd = npc_priv.subbank_depth;
+ sbd = npc_priv->subbank_depth;
*off = sb_off & (sbd - 1);
*bmap = (sb_off >= sbd) ? sb->b1map : sb->b0map;
@@ -2051,20 +2049,20 @@ static int __npc_subbank_mark_free(struct rvu *rvu, struct npc_subbank *sb)
sb->flags = NPC_SUBBANK_FLAG_FREE;
sb->key_type = 0;
- bitmap_clear(sb->b0map, 0, npc_priv.subbank_depth);
- bitmap_clear(sb->b1map, 0, npc_priv.subbank_depth);
+ bitmap_clear(sb->b0map, 0, npc_priv->subbank_depth);
+ bitmap_clear(sb->b1map, 0, npc_priv->subbank_depth);
- if (!xa_erase(&npc_priv.xa_sb_used, sb->arr_idx)) {
+ if (!xa_erase(&npc_priv->xa_sb_used, sb->arr_idx)) {
dev_err(rvu->dev,
"%s: Error to delete from xa_sb_used array\n",
__func__);
return -EFAULT;
}
- rc = xa_insert(&npc_priv.xa_sb_free, sb->arr_idx,
+ rc = xa_insert(&npc_priv->xa_sb_free, sb->arr_idx,
xa_mk_value(sb->idx), GFP_KERNEL);
if (rc) {
- rc = xa_insert(&npc_priv.xa_sb_used, sb->arr_idx,
+ rc = xa_insert(&npc_priv->xa_sb_used, sb->arr_idx,
xa_mk_value(sb->idx), GFP_KERNEL);
if (rc)
dev_err(rvu->dev,
@@ -2093,21 +2091,21 @@ static int __npc_subbank_mark_used(struct rvu *rvu, struct npc_subbank *sb,
sb->flags = NPC_SUBBANK_FLAG_USED;
sb->key_type = key_type;
if (key_type == NPC_MCAM_KEY_X4)
- sb->free_cnt = npc_priv.subbank_depth;
+ sb->free_cnt = npc_priv->subbank_depth;
else
- sb->free_cnt = 2 * npc_priv.subbank_depth;
+ sb->free_cnt = 2 * npc_priv->subbank_depth;
- bitmap_clear(sb->b0map, 0, npc_priv.subbank_depth);
- bitmap_clear(sb->b1map, 0, npc_priv.subbank_depth);
+ bitmap_clear(sb->b0map, 0, npc_priv->subbank_depth);
+ bitmap_clear(sb->b1map, 0, npc_priv->subbank_depth);
- if (!xa_erase(&npc_priv.xa_sb_free, sb->arr_idx)) {
+ if (!xa_erase(&npc_priv->xa_sb_free, sb->arr_idx)) {
dev_err(rvu->dev,
"%s: Error to delete from xa_sb_free array\n",
__func__);
return -EFAULT;
}
- rc = xa_insert(&npc_priv.xa_sb_used, sb->arr_idx,
+ rc = xa_insert(&npc_priv->xa_sb_used, sb->arr_idx,
xa_mk_value(sb->idx), GFP_KERNEL);
if (rc)
dev_err(rvu->dev,
@@ -2131,10 +2129,10 @@ static bool __npc_subbank_free(struct rvu *rvu, struct npc_subbank *sb,
/* Check whether we can mark whole subbank as free */
if (sb->key_type == NPC_MCAM_KEY_X4) {
- if (sb->free_cnt < npc_priv.subbank_depth)
+ if (sb->free_cnt < npc_priv->subbank_depth)
goto done;
} else {
- if (sb->free_cnt < 2 * npc_priv.subbank_depth)
+ if (sb->free_cnt < 2 * npc_priv->subbank_depth)
goto done;
}
@@ -2213,7 +2211,7 @@ static int __npc_subbank_alloc(struct rvu *rvu, struct npc_subbank *sb,
/* x4 indexes are from 0 to bank size as it combines two x2 banks */
if (key_type == NPC_MCAM_KEY_X4 &&
- (ref >= npc_priv.bank_depth || limit >= npc_priv.bank_depth)) {
+ (ref >= npc_priv->bank_depth || limit >= npc_priv->bank_depth)) {
dev_err(rvu->dev,
"%s: Wrong ref_enty(%d) or limit(%d) for x4\n",
__func__, ref, limit);
@@ -2223,8 +2221,8 @@ static int __npc_subbank_alloc(struct rvu *rvu, struct npc_subbank *sb,
/* This function is called either bank0 or bank1 portion of a subbank.
* so ref and limit should be on same bank.
*/
- diffbank = !!((ref & npc_priv.bank_depth) ^
- (limit & npc_priv.bank_depth));
+ diffbank = !!((ref & npc_priv->bank_depth) ^
+ (limit & npc_priv->bank_depth));
if (diffbank) {
dev_err(rvu->dev,
"%s: request ref and limit should be from same bank\n",
@@ -2248,7 +2246,7 @@ static int __npc_subbank_alloc(struct rvu *rvu, struct npc_subbank *sb,
* or equal to mcam entries available in the subbank if contig.
*/
if (sb->flags & NPC_SUBBANK_FLAG_FREE) {
- if (contig && count > npc_priv.subbank_depth) {
+ if (contig && count > npc_priv->subbank_depth) {
dev_err(rvu->dev, "%s: Less number of entries\n",
__func__);
return -ENOSPC;
@@ -2271,10 +2269,10 @@ static int __npc_subbank_alloc(struct rvu *rvu, struct npc_subbank *sb,
}
process:
- /* if ref or limit >= npc_priv.bank_depth, index are in bank1.
+ /* if ref or limit >= npc_priv->bank_depth, index are in bank1.
* else bank0.
*/
- if (ref >= npc_priv.bank_depth) {
+ if (ref >= npc_priv->bank_depth) {
bmap = sb->b1map;
t = sb->b1t;
b = sb->b1b;
@@ -2285,8 +2283,8 @@ static int __npc_subbank_alloc(struct rvu *rvu, struct npc_subbank *sb,
}
/* Calculate free slots */
- bw = bitmap_weight(bmap, npc_priv.subbank_depth);
- bfree = npc_priv.subbank_depth - bw;
+ bw = bitmap_weight(bmap, npc_priv->subbank_depth);
+ bfree = npc_priv->subbank_depth - bw;
if (!bfree) {
dev_dbg(rvu->dev, "%s: subbank is full\n", __func__);
@@ -2415,7 +2413,7 @@ npc_del_from_pf_maps(struct rvu *rvu, u16 mcam_idx)
int pcifunc, idx;
void *map;
- map = xa_erase(&npc_priv.xa_idx2pf_map, mcam_idx);
+ map = xa_erase(&npc_priv->xa_idx2pf_map, mcam_idx);
if (!map) {
dev_err(rvu->dev,
"%s: failed to erase mcam_idx(%u) from xa_idx2pf map\n",
@@ -2424,7 +2422,7 @@ npc_del_from_pf_maps(struct rvu *rvu, u16 mcam_idx)
}
pcifunc = xa_to_value(map);
- map = xa_load(&npc_priv.xa_pf_map, pcifunc);
+ map = xa_load(&npc_priv->xa_pf_map, pcifunc);
if (!map) {
dev_err(rvu->dev,
"%s: failed to find entry for (%u) from xa_pf_map, mcam=%u\n",
@@ -2434,7 +2432,7 @@ npc_del_from_pf_maps(struct rvu *rvu, u16 mcam_idx)
idx = xa_to_value(map);
- map = xa_erase(&npc_priv.xa_pf2idx_map[idx], mcam_idx);
+ map = xa_erase(&npc_priv->xa_pf2idx_map[idx], mcam_idx);
if (!map) {
dev_err(rvu->dev,
"%s: failed to erase mcam_idx(%u) from xa_pf2idx_map map\n",
@@ -2454,18 +2452,18 @@ npc_add_to_pf_maps(struct rvu *rvu, u16 mcam_idx, int pcifunc)
"%s: add2maps mcam_idx(%u) to xa_idx2pf map pcifunc=%#x\n",
__func__, mcam_idx, pcifunc);
- rc = xa_insert(&npc_priv.xa_idx2pf_map, mcam_idx,
+ rc = xa_insert(&npc_priv->xa_idx2pf_map, mcam_idx,
xa_mk_value(pcifunc), GFP_KERNEL);
if (rc) {
- map = xa_load(&npc_priv.xa_idx2pf_map, mcam_idx);
+ map = xa_load(&npc_priv->xa_idx2pf_map, mcam_idx);
dev_err(rvu->dev,
"%s: failed to insert mcam_idx(%u) to xa_idx2pf map, existing value=%lu\n",
__func__, mcam_idx, xa_to_value(map));
return -EFAULT;
}
- map = xa_load(&npc_priv.xa_pf_map, pcifunc);
+ map = xa_load(&npc_priv->xa_pf_map, pcifunc);
if (!map) {
dev_err(rvu->dev,
"%s: failed to find pf map entry for pcifunc=%#x, mcam=%u\n",
@@ -2475,12 +2473,12 @@ npc_add_to_pf_maps(struct rvu *rvu, u16 mcam_idx, int pcifunc)
idx = xa_to_value(map);
- rc = xa_insert(&npc_priv.xa_pf2idx_map[idx], mcam_idx,
+ rc = xa_insert(&npc_priv->xa_pf2idx_map[idx], mcam_idx,
xa_mk_value(pcifunc), GFP_KERNEL);
if (rc) {
- map = xa_load(&npc_priv.xa_pf2idx_map[idx], mcam_idx);
- xa_erase(&npc_priv.xa_idx2pf_map, mcam_idx);
+ map = xa_load(&npc_priv->xa_pf2idx_map[idx], mcam_idx);
+ xa_erase(&npc_priv->xa_idx2pf_map, mcam_idx);
dev_err(rvu->dev,
"%s: failed to insert mcam_idx(%u) to xa_pf2idx_map map, earlier value=%lu idx=%u\n",
__func__, mcam_idx, xa_to_value(map), idx);
@@ -2510,9 +2508,9 @@ npc_subbank_suits(struct npc_subbank *sb, int key_type)
return false;
}
-#define SB_ALIGN_UP(val) (((val) + npc_priv.subbank_depth) & \
- ~((npc_priv.subbank_depth) - 1))
-#define SB_ALIGN_DOWN(val) ALIGN_DOWN((val), npc_priv.subbank_depth)
+#define SB_ALIGN_UP(val) (((val) + npc_priv->subbank_depth) & \
+ ~((npc_priv->subbank_depth) - 1))
+#define SB_ALIGN_DOWN(val) ALIGN_DOWN((val), npc_priv->subbank_depth)
static void npc_subbank_iter_down(struct rvu *rvu,
int ref, int limit,
@@ -2538,7 +2536,7 @@ static void npc_subbank_iter_down(struct rvu *rvu,
}
*cur_ref = *cur_limit - 1;
- align = *cur_ref - npc_priv.subbank_depth + 1;
+ align = *cur_ref - npc_priv->subbank_depth + 1;
if (align <= limit) {
*stop = true;
*cur_limit = limit;
@@ -2578,7 +2576,7 @@ static void npc_subbank_iter_up(struct rvu *rvu,
}
*cur_ref = *cur_limit + 1;
- align = *cur_ref + npc_priv.subbank_depth - 1;
+ align = *cur_ref + npc_priv->subbank_depth - 1;
if (align >= limit) {
*stop = true;
@@ -2606,17 +2604,17 @@ npc_subbank_iter(struct rvu *rvu, int key_type,
/* limit and ref should < bank_depth for x4 */
if (key_type == NPC_MCAM_KEY_X4) {
- if (*cur_ref >= npc_priv.bank_depth)
+ if (*cur_ref >= npc_priv->bank_depth)
return -EINVAL;
- if (*cur_limit >= npc_priv.bank_depth)
+ if (*cur_limit >= npc_priv->bank_depth)
return -EINVAL;
}
/* limit and ref should < 2 * bank_depth, for x2 */
- if (*cur_ref >= 2 * npc_priv.bank_depth)
+ if (*cur_ref >= 2 * npc_priv->bank_depth)
return -EINVAL;
- if (*cur_limit >= 2 * npc_priv.bank_depth)
+ if (*cur_limit >= 2 * npc_priv->bank_depth)
return -EINVAL;
return 0;
@@ -2651,7 +2649,7 @@ static int npc_idx_free(struct rvu *rvu, u16 *mcam_idx, int count,
vidx = npc_idx2vidx(midx);
}
- if (midx >= npc_priv.bank_depth * npc_priv.num_banks) {
+ if (midx >= npc_priv->bank_depth * npc_priv->num_banks) {
dev_err(rvu->dev,
"%s: Invalid mcam_idx=%u cannot be deleted\n",
__func__, mcam_idx[i]);
@@ -2846,7 +2844,7 @@ static int npc_subbank_free_cnt(struct rvu *rvu, struct npc_subbank *sb,
{
int cnt, spd;
- spd = npc_priv.subbank_depth;
+ spd = npc_priv->subbank_depth;
mutex_lock(&sb->lock);
if (sb->flags & NPC_SUBBANK_FLAG_FREE)
@@ -3005,7 +3003,7 @@ static int npc_subbank_noref_alloc(struct rvu *rvu, int key_type, bool contig,
max_alloc = !contig;
/* Check used subbanks for free slots */
- xa_for_each(&npc_priv.xa_sb_used, index, val) {
+ xa_for_each(&npc_priv->xa_sb_used, index, val) {
idx = xa_to_value(val);
/* Minimize allocation from restricted subbanks
@@ -3014,7 +3012,7 @@ static int npc_subbank_noref_alloc(struct rvu *rvu, int key_type, bool contig,
if (npc_subbank_restrict_usage(rvu, idx))
continue;
- sb = &npc_priv.sb[idx];
+ sb = &npc_priv->sb[idx];
/* Skip if not suitable subbank */
if (!npc_subbank_suits(sb, key_type))
@@ -3071,9 +3069,9 @@ static int npc_subbank_noref_alloc(struct rvu *rvu, int key_type, bool contig,
}
/* Allocate in free subbanks */
- xa_for_each(&npc_priv.xa_sb_free, index, val) {
+ xa_for_each(&npc_priv->xa_sb_free, index, val) {
idx = xa_to_value(val);
- sb = &npc_priv.sb[idx];
+ sb = &npc_priv->sb[idx];
/* Minimize allocation from restricted subbanks
* in noref allocations.
@@ -3129,7 +3127,7 @@ static int npc_subbank_noref_alloc(struct rvu *rvu, int key_type, bool contig,
for (i = 0; restrict_valid &&
(i < ARRAY_SIZE(npc_subbank_restricted_idxs)); i++) {
idx = npc_subbank_restricted_idxs[i];
- sb = &npc_priv.sb[idx];
+ sb = &npc_priv->sb[idx];
/* Skip if not suitable subbank */
if (!npc_subbank_suits(sb, key_type))
@@ -3209,7 +3207,7 @@ int npc_cn20k_ref_idx_alloc(struct rvu *rvu, int pcifunc, int key_type,
bool ref_valid;
u16 vidx;
- bd = npc_priv.bank_depth;
+ bd = npc_priv->bank_depth;
/* Special case: ref == 0 && limit= 0 && prio == HIGH && count == 1
* Here user wants to allocate 0th entry
@@ -3227,7 +3225,7 @@ int npc_cn20k_ref_idx_alloc(struct rvu *rvu, int pcifunc, int key_type,
ref_valid = !!(limit || ref);
defrag_candidate = !ref_valid && !contig && virt;
if (!ref_valid) {
- if (contig && count > npc_priv.subbank_depth)
+ if (contig && count > npc_priv->subbank_depth)
goto try_noref_multi_subbank;
rc = npc_subbank_noref_alloc(rvu, key_type, contig,
@@ -3272,7 +3270,7 @@ int npc_cn20k_ref_idx_alloc(struct rvu *rvu, int pcifunc, int key_type,
return -EINVAL;
}
- if (contig && count > npc_priv.subbank_depth)
+ if (contig && count > npc_priv->subbank_depth)
goto try_ref_multi_subbank;
rc = npc_subbank_ref_alloc(rvu, key_type, ref, limit,
@@ -3334,8 +3332,8 @@ void npc_cn20k_subbank_calc_free(struct rvu *rvu, int *x2_free,
*x4_free = 0;
*sb_free = 0;
- for (i = 0; i < npc_priv.num_subbanks; i++) {
- sb = &npc_priv.sb[i];
+ for (i = 0; i < npc_priv->num_subbanks; i++) {
+ sb = &npc_priv->sb[i];
mutex_lock(&sb->lock);
/* Count number of free subbanks */
@@ -3433,11 +3431,11 @@ static void npc_subbank_init(struct rvu *rvu, struct npc_subbank *sb, int idx)
{
mutex_init(&sb->lock);
- sb->b0b = idx * npc_priv.subbank_depth;
- sb->b0t = sb->b0b + npc_priv.subbank_depth - 1;
+ sb->b0b = idx * npc_priv->subbank_depth;
+ sb->b0t = sb->b0b + npc_priv->subbank_depth - 1;
- sb->b1b = npc_priv.bank_depth + idx * npc_priv.subbank_depth;
- sb->b1t = sb->b1b + npc_priv.subbank_depth - 1;
+ sb->b1b = npc_priv->bank_depth + idx * npc_priv->subbank_depth;
+ sb->b1t = sb->b1b + npc_priv->subbank_depth - 1;
sb->flags = NPC_SUBBANK_FLAG_FREE;
sb->idx = idx;
@@ -3449,7 +3447,7 @@ static void npc_subbank_init(struct rvu *rvu, struct npc_subbank *sb, int idx)
/* Keep first and last subbank at end of free array; so that
* it will be used at last
*/
- xa_store(&npc_priv.xa_sb_free, sb->arr_idx,
+ xa_store(&npc_priv->xa_sb_free, sb->arr_idx,
xa_mk_value(sb->idx), GFP_KERNEL);
}
@@ -3474,7 +3472,7 @@ static int npc_pcifunc_map_create(struct rvu *rvu)
pcifunc = pf << 9;
- xa_store(&npc_priv.xa_pf_map, (unsigned long)pcifunc,
+ xa_store(&npc_priv->xa_pf_map, (unsigned long)pcifunc,
xa_mk_value(cnt), GFP_KERNEL);
cnt++;
@@ -3483,7 +3481,7 @@ static int npc_pcifunc_map_create(struct rvu *rvu)
for (vf = 0; vf < numvfs; vf++) {
pcifunc = (pf << 9) | (vf + 1);
- xa_store(&npc_priv.xa_pf_map, (unsigned long)pcifunc,
+ xa_store(&npc_priv->xa_pf_map, (unsigned long)pcifunc,
xa_mk_value(cnt), GFP_KERNEL);
cnt++;
}
@@ -3569,7 +3567,7 @@ static int npc_defrag_alloc_free_slots(struct rvu *rvu,
int rc, sb_off, i, err;
bool deleted;
- sb = &npc_priv.sb[f->idx];
+ sb = &npc_priv->sb[f->idx];
alloc_cnt1 = 0;
alloc_cnt2 = 0;
@@ -3639,9 +3637,9 @@ static int npc_defrag_add_2_show_list(struct rvu *rvu, u16 old_midx,
node->vidx = vidx;
INIT_LIST_HEAD(&node->list);
- mutex_lock(&npc_priv.lock);
- list_add_tail(&node->list, &npc_priv.defrag_lh);
- mutex_unlock(&npc_priv.lock);
+ mutex_lock(&npc_priv->lock);
+ list_add_tail(&node->list, &npc_priv->defrag_lh);
+ mutex_unlock(&npc_priv->lock);
return 0;
}
@@ -3745,7 +3743,7 @@ int npc_defrag_move_vdx_to_free(struct rvu *rvu,
}
/* save pcifunc */
- map = xa_load(&npc_priv.xa_idx2pf_map, old_midx);
+ map = xa_load(&npc_priv->xa_idx2pf_map, old_midx);
pcifunc = xa_to_value(map);
/* delete from pf maps */
@@ -3904,29 +3902,29 @@ static void npc_defrag_list_clear(void)
{
struct npc_defrag_show_node *node, *next;
- mutex_lock(&npc_priv.lock);
- list_for_each_entry_safe(node, next, &npc_priv.defrag_lh, list) {
+ mutex_lock(&npc_priv->lock);
+ list_for_each_entry_safe(node, next, &npc_priv->defrag_lh, list) {
list_del_init(&node->list);
kfree(node);
}
- mutex_unlock(&npc_priv.lock);
+ mutex_unlock(&npc_priv->lock);
}
static void npc_lock_all_subbank(void)
{
int i;
- for (i = 0; i < npc_priv.num_subbanks; i++)
- mutex_lock(&npc_priv.sb[i].lock);
+ for (i = 0; i < npc_priv->num_subbanks; i++)
+ mutex_lock(&npc_priv->sb[i].lock);
}
static void npc_unlock_all_subbank(void)
{
int i;
- for (i = npc_priv.num_subbanks - 1; i >= 0; i--)
- mutex_unlock(&npc_priv.sb[i].lock);
+ for (i = npc_priv->num_subbanks - 1; i >= 0; i--)
+ mutex_unlock(&npc_priv->sb[i].lock);
}
int npc_cn20k_search_order_set(struct rvu *rvu,
@@ -3937,9 +3935,9 @@ int npc_cn20k_search_order_set(struct rvu *rvu,
struct xarray *xa;
int sb_idx, rc;
- if (cnt != npc_priv.num_subbanks) {
+ if (cnt != npc_priv->num_subbanks) {
dev_err(rvu->dev, "Number of entries(%u) != %u\n",
- cnt, npc_priv.num_subbanks);
+ cnt, npc_priv->num_subbanks);
return -EINVAL;
}
@@ -3948,11 +3946,11 @@ int npc_cn20k_search_order_set(struct rvu *rvu,
restrict_valid = false;
for (sb_idx = 0; sb_idx < cnt; sb_idx++) {
- sb = &npc_priv.sb[sb_idx];
+ sb = &npc_priv->sb[sb_idx];
- xa = &npc_priv.xa_sb_free;
+ xa = &npc_priv->xa_sb_free;
if (sb->flags & NPC_SUBBANK_FLAG_USED)
- xa = &npc_priv.xa_sb_used;
+ xa = &npc_priv->xa_sb_used;
sb->arr_idx = narr[sb_idx];
@@ -3975,7 +3973,7 @@ int npc_cn20k_search_order_set(struct rvu *rvu,
const u32 *npc_cn20k_search_order_get(bool *restricted_order, u32 *sz)
{
*restricted_order = restrict_valid;
- *sz = npc_priv.num_subbanks;
+ *sz = npc_priv->num_subbanks;
return subbank_srch_order;
}
@@ -3999,7 +3997,7 @@ int npc_cn20k_defrag(struct rvu *rvu)
INIT_LIST_HEAD(&x4lh);
INIT_LIST_HEAD(&x2lh);
- node = kcalloc(npc_priv.num_subbanks, sizeof(*node), GFP_KERNEL);
+ node = kcalloc(npc_priv->num_subbanks, sizeof(*node), GFP_KERNEL);
if (!node)
return -ENOMEM;
@@ -4008,13 +4006,13 @@ int npc_cn20k_defrag(struct rvu *rvu)
npc_lock_all_subbank();
/* Fill in node with subbank properties */
- for (i = 0; i < npc_priv.num_subbanks; i++) {
- sb = &npc_priv.sb[i];
+ for (i = 0; i < npc_priv->num_subbanks; i++) {
+ sb = &npc_priv->sb[i];
node[i].idx = i;
node[i].key_type = sb->key_type;
node[i].free_cnt = sb->free_cnt;
- node[i].vidx = kcalloc(npc_priv.subbank_depth * 2,
+ node[i].vidx = kcalloc(npc_priv->subbank_depth * 2,
sizeof(*node[i].vidx),
GFP_KERNEL);
if (!node[i].vidx) {
@@ -4044,8 +4042,8 @@ int npc_cn20k_defrag(struct rvu *rvu)
}
/* Filling vidx[] array with all vidx in that subbank */
- xa_for_each_start(&npc_priv.xa_vidx2idx_map, index, map,
- npc_priv.bank_depth * 2) {
+ xa_for_each_start(&npc_priv->xa_vidx2idx_map, index, map,
+ npc_priv->bank_depth * 2) {
midx = xa_to_value(map);
rc = npc_mcam_idx_2_subbank_idx(rvu, midx,
&sb, &sb_off);
@@ -4062,14 +4060,14 @@ int npc_cn20k_defrag(struct rvu *rvu)
}
/* Mark all subbank which has ref allocation */
- for (i = 0; i < npc_priv.num_subbanks; i++) {
+ for (i = 0; i < npc_priv->num_subbanks; i++) {
tnode = &node[i];
if (!tnode->valid)
continue;
tot = (tnode->key_type == NPC_MCAM_KEY_X2) ?
- npc_priv.subbank_depth * 2 : npc_priv.subbank_depth;
+ npc_priv->subbank_depth * 2 : npc_priv->subbank_depth;
if (node[i].vidx_cnt != tot - tnode->free_cnt)
tnode->refs = true;
@@ -4086,7 +4084,7 @@ int npc_cn20k_defrag(struct rvu *rvu)
free_vidx:
npc_unlock_all_subbank();
mutex_unlock(&mcam->lock);
- for (i = 0; i < npc_priv.num_subbanks; i++)
+ for (i = 0; i < npc_priv->num_subbanks; i++)
kfree(node[i].vidx);
kfree(node);
return rc;
@@ -4114,7 +4112,7 @@ int npc_cn20k_dft_rules_idx_get(struct rvu *rvu, u16 pcifunc, u16 *bcast,
*ptr[i] = USHRT_MAX;
}
- if (!npc_priv.init_done)
+ if (!npc_priv)
return 0;
if (is_lbk_vf(rvu, pcifunc)) {
@@ -4122,7 +4120,7 @@ int npc_cn20k_dft_rules_idx_get(struct rvu *rvu, u16 pcifunc, u16 *bcast,
return -EINVAL;
idx = NPC_DFT_RULE_ID_MK(pcifunc, NPC_DFT_RULE_PROMISC_ID);
- val = xa_load(&npc_priv.xa_pf2dfl_rmap, idx);
+ val = xa_load(&npc_priv->xa_pf2dfl_rmap, idx);
if (!val) {
pr_debug("%s: Failed to find %s index for pcifunc=%#x\n",
__func__,
@@ -4141,7 +4139,7 @@ int npc_cn20k_dft_rules_idx_get(struct rvu *rvu, u16 pcifunc, u16 *bcast,
return -EINVAL;
idx = NPC_DFT_RULE_ID_MK(pcifunc, NPC_DFT_RULE_UCAST_ID);
- val = xa_load(&npc_priv.xa_pf2dfl_rmap, idx);
+ val = xa_load(&npc_priv->xa_pf2dfl_rmap, idx);
if (!val) {
pr_debug("%s: Failed to find %s index for pcifunc=%#x\n",
__func__,
@@ -4161,7 +4159,7 @@ int npc_cn20k_dft_rules_idx_get(struct rvu *rvu, u16 pcifunc, u16 *bcast,
continue;
idx = NPC_DFT_RULE_ID_MK(pcifunc, i);
- val = xa_load(&npc_priv.xa_pf2dfl_rmap, idx);
+ val = xa_load(&npc_priv->xa_pf2dfl_rmap, idx);
if (!val) {
pr_debug("%s: Failed to find %s index for pcifunc=%#x\n",
__func__,
@@ -4185,8 +4183,8 @@ int rvu_mbox_handler_npc_get_pfl_info(struct rvu *rvu, struct msg_req *req,
return -EOPNOTSUPP;
}
- rsp->kw_type = npc_priv.kw;
- rsp->x4_slots = npc_priv.bank_depth;
+ rsp->kw_type = npc_priv->kw;
+ rsp->x4_slots = npc_priv->bank_depth;
return 0;
}
@@ -4276,7 +4274,7 @@ void npc_cn20k_dft_rules_free(struct rvu *rvu, u16 pcifunc)
int blkaddr, rc, i;
void *map;
- if (!npc_priv.init_done)
+ if (!npc_priv)
return;
if (!npc_is_cgx_or_lbk(rvu, pcifunc)) {
@@ -4294,7 +4292,7 @@ void npc_cn20k_dft_rules_free(struct rvu *rvu, u16 pcifunc)
/* LBK */
if (is_lbk_vf(rvu, pcifunc)) {
index = NPC_DFT_RULE_ID_MK(pcifunc, NPC_DFT_RULE_PROMISC_ID);
- map = xa_erase(&npc_priv.xa_pf2dfl_rmap, index);
+ map = xa_erase(&npc_priv->xa_pf2dfl_rmap, index);
if (!map)
dev_dbg(rvu->dev,
"%s: Err from delete %s mcam idx from xarray (pcifunc=%#x\n",
@@ -4308,7 +4306,7 @@ void npc_cn20k_dft_rules_free(struct rvu *rvu, u16 pcifunc)
/* VF */
if (is_vf(pcifunc)) {
index = NPC_DFT_RULE_ID_MK(pcifunc, NPC_DFT_RULE_UCAST_ID);
- map = xa_erase(&npc_priv.xa_pf2dfl_rmap, index);
+ map = xa_erase(&npc_priv->xa_pf2dfl_rmap, index);
if (!map)
dev_dbg(rvu->dev,
"%s: Err from delete %s mcam idx from xarray (pcifunc=%#x\n",
@@ -4322,7 +4320,7 @@ void npc_cn20k_dft_rules_free(struct rvu *rvu, u16 pcifunc)
/* PF */
for (i = NPC_DFT_RULE_START_ID; i < NPC_DFT_RULE_MAX_ID; i++) {
index = NPC_DFT_RULE_ID_MK(pcifunc, i);
- map = xa_erase(&npc_priv.xa_pf2dfl_rmap, index);
+ map = xa_erase(&npc_priv->xa_pf2dfl_rmap, index);
if (!map)
dev_dbg(rvu->dev,
"%s: Err from delete %s mcam idx from xarray (pcifunc=%#x\n",
@@ -4382,7 +4380,7 @@ int npc_cn20k_dft_rules_alloc(struct rvu *rvu, u16 pcifunc)
struct msg_rsp free_rsp;
u16 b, m, p, u;
- if (!npc_priv.init_done)
+ if (!npc_priv)
return 0;
if (!npc_is_cgx_or_lbk(rvu, pcifunc)) {
@@ -4405,7 +4403,7 @@ int npc_cn20k_dft_rules_alloc(struct rvu *rvu, u16 pcifunc)
}
/* Set ref index as lowest priority index */
- eidx = 2 * npc_priv.bank_depth - 1;
+ eidx = 2 * npc_priv->bank_depth - 1;
/* Install only UCAST for VF */
cnt = is_vf(pcifunc) ? 1 : ARRAY_SIZE(mcam_idx);
@@ -4471,9 +4469,9 @@ int npc_cn20k_dft_rules_alloc(struct rvu *rvu, u16 pcifunc)
req.hdr.pcifunc = pcifunc;
req.ref_prio = NPC_MCAM_LOWER_PRIO;
- if (npc_priv.kw == NPC_MCAM_KEY_X4) {
+ if (npc_priv->kw == NPC_MCAM_KEY_X4) {
req.kw_type = NPC_MCAM_KEY_X4;
- req.ref_entry = eidx & (npc_priv.bank_depth - 1);
+ req.ref_entry = eidx & (npc_priv->bank_depth - 1);
} else {
req.kw_type = NPC_MCAM_KEY_X2;
req.ref_entry = eidx;
@@ -4497,7 +4495,7 @@ int npc_cn20k_dft_rules_alloc(struct rvu *rvu, u16 pcifunc)
/* LBK */
if (is_lbk_vf(rvu, pcifunc)) {
index = NPC_DFT_RULE_ID_MK(pcifunc, NPC_DFT_RULE_PROMISC_ID);
- ret = xa_insert(&npc_priv.xa_pf2dfl_rmap, index,
+ ret = xa_insert(&npc_priv->xa_pf2dfl_rmap, index,
xa_mk_value(mcam_idx[0]), GFP_KERNEL);
if (ret) {
dev_err(rvu->dev,
@@ -4514,7 +4512,7 @@ int npc_cn20k_dft_rules_alloc(struct rvu *rvu, u16 pcifunc)
/* VF */
if (is_vf(pcifunc)) {
index = NPC_DFT_RULE_ID_MK(pcifunc, NPC_DFT_RULE_UCAST_ID);
- ret = xa_insert(&npc_priv.xa_pf2dfl_rmap, index,
+ ret = xa_insert(&npc_priv->xa_pf2dfl_rmap, index,
xa_mk_value(mcam_idx[0]), GFP_KERNEL);
if (ret) {
dev_err(rvu->dev,
@@ -4532,7 +4530,7 @@ int npc_cn20k_dft_rules_alloc(struct rvu *rvu, u16 pcifunc)
for (i = NPC_DFT_RULE_START_ID, k = 0; i < NPC_DFT_RULE_MAX_ID &&
k < cnt; i++, k++) {
index = NPC_DFT_RULE_ID_MK(pcifunc, i);
- ret = xa_insert(&npc_priv.xa_pf2dfl_rmap, index,
+ ret = xa_insert(&npc_priv->xa_pf2dfl_rmap, index,
xa_mk_value(mcam_idx[k]), GFP_KERNEL);
if (ret) {
dev_err(rvu->dev,
@@ -4541,7 +4539,7 @@ int npc_cn20k_dft_rules_alloc(struct rvu *rvu, u16 pcifunc)
pcifunc);
for (int p = NPC_DFT_RULE_START_ID; p < i; p++) {
index = NPC_DFT_RULE_ID_MK(pcifunc, p);
- xa_erase(&npc_priv.xa_pf2dfl_rmap, index);
+ xa_erase(&npc_priv->xa_pf2dfl_rmap, index);
}
goto err;
}
@@ -4599,34 +4597,40 @@ static int npc_priv_init(struct rvu *rvu)
return -EINVAL;
}
- npc_priv.num_subbanks = num_subbanks;
+ npc_priv = kcalloc(1, sizeof(*npc_priv), GFP_KERNEL);
+ if (!npc_priv)
+ return -ENOMEM;
+
+ npc_priv->num_banks = num_banks;
+
+ npc_priv->num_subbanks = num_subbanks;
subbank_depth = bank_depth / num_subbanks;
- npc_priv.bank_depth = bank_depth;
- npc_priv.subbank_depth = subbank_depth;
+ npc_priv->bank_depth = bank_depth;
+ npc_priv->subbank_depth = subbank_depth;
/* Get kex configured key size */
cfg = rvu_read64(rvu, blkaddr, NPC_AF_INTFX_KEX_CFG(0));
- npc_priv.kw = FIELD_GET(GENMASK_ULL(34, 32), cfg);
+ npc_priv->kw = FIELD_GET(GENMASK_ULL(34, 32), cfg);
dev_info(rvu->dev,
"banks=%u depth=%u, subbanks=%u depth=%u, key type=%s\n",
num_banks, bank_depth, num_subbanks, subbank_depth,
- npc_kw_name[npc_priv.kw]);
+ npc_kw_name[npc_priv->kw]);
- npc_priv.sb = kcalloc(num_subbanks, sizeof(struct npc_subbank),
- GFP_KERNEL);
- if (!npc_priv.sb)
+ npc_priv->sb = kcalloc(num_subbanks, sizeof(struct npc_subbank),
+ GFP_KERNEL);
+ if (!npc_priv->sb)
return -ENOMEM;
- xa_init_flags(&npc_priv.xa_sb_used, XA_FLAGS_ALLOC);
- xa_init_flags(&npc_priv.xa_sb_free, XA_FLAGS_ALLOC);
- xa_init_flags(&npc_priv.xa_idx2pf_map, XA_FLAGS_ALLOC);
- xa_init_flags(&npc_priv.xa_pf_map, XA_FLAGS_ALLOC);
- xa_init_flags(&npc_priv.xa_pf2dfl_rmap, XA_FLAGS_ALLOC);
- xa_init_flags(&npc_priv.xa_idx2vidx_map, XA_FLAGS_ALLOC);
- xa_init_flags(&npc_priv.xa_vidx2idx_map, XA_FLAGS_ALLOC);
+ xa_init_flags(&npc_priv->xa_sb_used, XA_FLAGS_ALLOC);
+ xa_init_flags(&npc_priv->xa_sb_free, XA_FLAGS_ALLOC);
+ xa_init_flags(&npc_priv->xa_idx2pf_map, XA_FLAGS_ALLOC);
+ xa_init_flags(&npc_priv->xa_pf_map, XA_FLAGS_ALLOC);
+ xa_init_flags(&npc_priv->xa_pf2dfl_rmap, XA_FLAGS_ALLOC);
+ xa_init_flags(&npc_priv->xa_idx2vidx_map, XA_FLAGS_ALLOC);
+ xa_init_flags(&npc_priv->xa_vidx2idx_map, XA_FLAGS_ALLOC);
if (npc_create_srch_order(num_subbanks))
goto fail1;
@@ -4634,22 +4638,22 @@ static int npc_priv_init(struct rvu *rvu)
npc_populate_restricted_idxs(num_subbanks);
/* Initialize subbanks */
- for (i = 0, sb = npc_priv.sb; i < num_subbanks; i++, sb++)
+ for (i = 0, sb = npc_priv->sb; i < num_subbanks; i++, sb++)
npc_subbank_init(rvu, sb, i);
/* Get number of pcifuncs in the system */
- npc_priv.pf_cnt = npc_pcifunc_map_create(rvu);
- npc_priv.xa_pf2idx_map = kcalloc(npc_priv.pf_cnt,
- sizeof(struct xarray),
- GFP_KERNEL);
- if (!npc_priv.xa_pf2idx_map)
+ npc_priv->pf_cnt = npc_pcifunc_map_create(rvu);
+ npc_priv->xa_pf2idx_map = kcalloc(npc_priv->pf_cnt,
+ sizeof(struct xarray),
+ GFP_KERNEL);
+ if (!npc_priv->xa_pf2idx_map)
goto fail2;
- for (i = 0; i < npc_priv.pf_cnt; i++)
- xa_init_flags(&npc_priv.xa_pf2idx_map[i], XA_FLAGS_ALLOC);
+ for (i = 0; i < npc_priv->pf_cnt; i++)
+ xa_init_flags(&npc_priv->xa_pf2idx_map[i], XA_FLAGS_ALLOC);
- INIT_LIST_HEAD(&npc_priv.defrag_lh);
- mutex_init(&npc_priv.lock);
+ INIT_LIST_HEAD(&npc_priv->defrag_lh);
+ mutex_init(&npc_priv->lock);
return 0;
@@ -4658,15 +4662,17 @@ static int npc_priv_init(struct rvu *rvu)
subbank_srch_order = NULL;
fail1:
- xa_destroy(&npc_priv.xa_sb_used);
- xa_destroy(&npc_priv.xa_sb_free);
- xa_destroy(&npc_priv.xa_idx2pf_map);
- xa_destroy(&npc_priv.xa_pf_map);
- xa_destroy(&npc_priv.xa_pf2dfl_rmap);
- xa_destroy(&npc_priv.xa_idx2vidx_map);
- xa_destroy(&npc_priv.xa_vidx2idx_map);
- kfree(npc_priv.sb);
- npc_priv.sb = NULL;
+ xa_destroy(&npc_priv->xa_sb_used);
+ xa_destroy(&npc_priv->xa_sb_free);
+ xa_destroy(&npc_priv->xa_idx2pf_map);
+ xa_destroy(&npc_priv->xa_pf_map);
+ xa_destroy(&npc_priv->xa_pf2dfl_rmap);
+ xa_destroy(&npc_priv->xa_idx2vidx_map);
+ xa_destroy(&npc_priv->xa_vidx2idx_map);
+ kfree(npc_priv->sb);
+ npc_priv->sb = NULL;
+ kfree(npc_priv);
+ npc_priv = NULL;
return -ENOMEM;
}
@@ -4674,25 +4680,30 @@ void npc_cn20k_deinit(struct rvu *rvu)
{
int i;
- xa_destroy(&npc_priv.xa_sb_used);
- xa_destroy(&npc_priv.xa_sb_free);
- xa_destroy(&npc_priv.xa_idx2pf_map);
- xa_destroy(&npc_priv.xa_pf_map);
- xa_destroy(&npc_priv.xa_pf2dfl_rmap);
- xa_destroy(&npc_priv.xa_idx2vidx_map);
- xa_destroy(&npc_priv.xa_vidx2idx_map);
+ if (!npc_priv)
+ return;
+
+ xa_destroy(&npc_priv->xa_sb_used);
+ xa_destroy(&npc_priv->xa_sb_free);
+ xa_destroy(&npc_priv->xa_idx2pf_map);
+ xa_destroy(&npc_priv->xa_pf_map);
+ xa_destroy(&npc_priv->xa_pf2dfl_rmap);
+ xa_destroy(&npc_priv->xa_idx2vidx_map);
+ xa_destroy(&npc_priv->xa_vidx2idx_map);
- for (i = 0; i < npc_priv.pf_cnt; i++)
- xa_destroy(&npc_priv.xa_pf2idx_map[i]);
+ for (i = 0; i < npc_priv->pf_cnt; i++)
+ xa_destroy(&npc_priv->xa_pf2idx_map[i]);
- kfree(npc_priv.xa_pf2idx_map);
+ kfree(npc_priv->xa_pf2idx_map);
/* No need to destroy mutex lock as it is
* part of subbank structure
*/
- kfree(npc_priv.sb);
+ kfree(npc_priv->sb);
kfree(subbank_srch_order);
- bitmap_clear(npc_priv.en_map, 0, MAX_NUM_BANKS * MAX_NUM_SUB_BANKS *
+ bitmap_clear(npc_priv->en_map, 0, MAX_NUM_BANKS * MAX_NUM_SUB_BANKS *
MAX_SUBBANK_DEPTH);
+ kfree(npc_priv);
+ npc_priv = NULL;
}
static int npc_setup_mcam_section(struct rvu *rvu, int key_type)
@@ -4705,7 +4716,7 @@ static int npc_setup_mcam_section(struct rvu *rvu, int key_type)
return -ENODEV;
}
- for (sec = 0; sec < npc_priv.num_subbanks; sec++)
+ for (sec = 0; sec < npc_priv->num_subbanks; sec++)
rvu_write64(rvu, blkaddr,
NPC_AF_MCAM_SECTIONX_CFG_EXT(sec), key_type);
@@ -4730,7 +4741,5 @@ int npc_cn20k_init(struct rvu *rvu)
return err;
}
- npc_priv.init_done = true;
-
return 0;
}
diff --git a/drivers/net/ethernet/marvell/octeontx2/af/cn20k/npc.h b/drivers/net/ethernet/marvell/octeontx2/af/cn20k/npc.h
index bf030e40fbf9..ee0bbeba7f25 100644
--- a/drivers/net/ethernet/marvell/octeontx2/af/cn20k/npc.h
+++ b/drivers/net/ethernet/marvell/octeontx2/af/cn20k/npc.h
@@ -191,7 +191,7 @@ struct npc_defrag_show_node {
*/
struct npc_priv_t {
int bank_depth;
- const int num_banks;
+ int num_banks;
int num_subbanks;
int subbank_depth;
DECLARE_BITMAP(en_map, MAX_NUM_BANKS *
@@ -210,7 +210,6 @@ struct npc_priv_t {
struct list_head defrag_lh;
struct mutex lock; /* protect defrag nodes */
int pf_cnt;
- bool init_done;
};
struct npc_kpm_action0 {
--
2.43.0
^ permalink raw reply related [flat|nested] 22+ messages in thread* Re: [PATCH v12 net-next 9/9] octeontx2-af: npc: cn20k: Allocate npc_priv and dstats dynamically.
2026-05-08 3:49 ` [PATCH v12 net-next 9/9] octeontx2-af: npc: cn20k: Allocate npc_priv and dstats dynamically Ratheesh Kannoth
@ 2026-05-11 3:26 ` Ratheesh Kannoth
0 siblings, 0 replies; 22+ messages in thread
From: Ratheesh Kannoth @ 2026-05-11 3:26 UTC (permalink / raw)
To: intel-wired-lan, linux-kernel, linux-rdma, netdev, oss-drivers
Cc: akiyano, andrew+netdev, anthony.l.nguyen, arkadiusz.kubalewski,
brett.creeley, darinzon, davem, donald.hunter, edumazet, horms,
idosch, ivecera, jiri, kuba, leon, mbloch, michael.chan, pabeni,
pavan.chebbi, petrm, Prathosh.Satish, przemyslaw.kitszel, saeedm,
sgoutham, tariqt, vadim.fedorenko
On 2026-05-08 at 09:19:12, Ratheesh Kannoth (rkannoth@marvell.com) wrote:
> Replace the file-scope static npc_priv with a kcalloc'd struct filled
> from hardware bank/subbank geometry at init (num_banks is no longer a
> const compile-time constant; drop init_done and use a non-NULL
> npc_priv pointer for liveness). Thread npc_priv_get() / pointer access
> through the CN20K NPC code paths, extend teardown to kfree the root
> struct on failure and in npc_cn20k_deinit, and adjust MCAM section
> setup to use the discovered subbank count.
pw-bot: changes-requested
>> -static u64 dstats[MAX_NUM_BANKS][MAX_SUBBANK_DEPTH * MAX_NUM_SUB_BANKS] = {};
>> +static u64 (*dstats)[MAX_NUM_BANKS][MAX_SUBBANK_DEPTH * MAX_NUM_SUB_BANKS];
>[ ... ]
>> @@ -396,6 +396,10 @@ int npc_cn20k_debugfs_init(struct rvu *rvu)
>> debugfs_create_file("vidx2idx", 0444, rvu->rvu_dbg.npc,
>> npc_priv, &npc_vidx2idx_map_fops);
>>
>> + dstats = devm_kzalloc(rvu->dev, sizeof(*dstats), GFP_KERNEL);
>> + if (!dstats)
>> + return -ENOMEM;
>> +
>Since dstats is a file-scoped static pointer, will it be overwritten if
>multiple RVU PCI devices are probed on the same system?
>It looks like devm_kzalloc ties the allocation to a specific device. If that
>device is unbound, the devres framework will automatically free the memory.
>Could this leave the global pointer dangling and cause a use-after-free for
>any remaining active devices that try to access the debugfs file?
There is only one RVU AF device in the system.
>> +++ b/drivers/net/ethernet/marvell/octeontx2/af/cn20k/npc.c
>> @@ -16,9 +16,7 @@
>> #include "cn20k/reg.h"
>> #include "rvu_npc_fs.h"
>>
>> -static struct npc_priv_t npc_priv = {
>> - .num_banks = MAX_NUM_BANKS,
>> -};
>> +static struct npc_priv_t *npc_priv;
>Similarly, since npc_priv is also a file-scoped global pointer, could probing
>multiple devices cause previous allocations to be overwritten and leaked?
>Should this per-device state be stored within a device-specific context
>structure instead of a global pointer?
There is only one RVU AF device in the system.
>> - rsp->kw_type = npc_priv.kw;
>> - rsp->x4_slots = npc_priv.bank_depth;
>> + rsp->kw_type = npc_priv->kw;
>> + rsp->x4_slots = npc_priv->bank_depth;
>> return 0;
>> }
>If a Virtual Function sends a mailbox message before initialization is
>complete or after teardown, could npc_priv be NULL here? Does this handler
>need a NULL pointer check to prevent a crash?
AF is initialized first, and NPC block initialiation is part of AF initialization.
VF probe is done after that. So this won't happen.
>> - rsp->kw_type = npc_priv.kw;
>> - rsp->x4_slots = npc_priv.bank_depth;
>> + rsp->kw_type = npc_priv->kw;
>> + rsp->x4_slots = npc_priv->bank_depth;
>> return 0;
>> }
>If a Virtual Function sends a mailbox message before initialization is
>complete or after teardown, could npc_priv be NULL here? Does this handler
>need a NULL pointer check to prevent a crash?
Number of subbank is a multiple of 2.
>> + xa_destroy(&npc_priv->xa_sb_used);
>[ ... ]
>> + kfree(npc_priv);
>> + npc_priv = NULL;
>> }
>This might be a pre-existing issue, but during teardown in npc_cn20k_deinit(),
>does the defrag_lh list need to be cleared? The list appears to contain
>dynamically allocated npc_defrag_show_node structures, and they might be
>leaked if they are still present when npc_priv is freed.
ACK, this is a bug. i will post a patch post this net-next series is merged.
>> */
>> struct npc_priv_t {
>> int bank_depth;
>> - const int num_banks;
>> + int num_banks;
>> int num_subbanks;
>> int subbank_depth;
>> DECLARE_BITMAP(en_map, MAX_NUM_BANKS *
>Since num_banks and bank_depth are now dynamically read from hardware rather
>than using strict compile-time constants, is it possible for a device to
>advertise geometry larger than the static sizes used for en_map and dstats
>(MAX_NUM_BANKS, etc.)?
>Could this cause out-of-bounds reads and writes when accessing those
>structures?
ACK. This can be posted as an enhancement to net-next later.
>
> Allocate MCAM debugfs dstats via devm_kzalloc instead of a static matrix,
> and use the allocated backing store consistently when computing deltas
> (including the counter rollover compare).
>
> Signed-off-by: Ratheesh Kannoth <rkannoth@marvell.com>
> ---
> .../marvell/octeontx2/af/cn20k/debugfs.c | 18 +-
> .../ethernet/marvell/octeontx2/af/cn20k/npc.c | 407 +++++++++---------
> .../ethernet/marvell/octeontx2/af/cn20k/npc.h | 3 +-
> 3 files changed, 220 insertions(+), 208 deletions(-)
>
> diff --git a/drivers/net/ethernet/marvell/octeontx2/af/cn20k/debugfs.c b/drivers/net/ethernet/marvell/octeontx2/af/cn20k/debugfs.c
> index 9a4c2ea5b19e..15af7b0ccea6 100644
> --- a/drivers/net/ethernet/marvell/octeontx2/af/cn20k/debugfs.c
> +++ b/drivers/net/ethernet/marvell/octeontx2/af/cn20k/debugfs.c
> @@ -172,7 +172,7 @@ __OCTEONTX2_DEBUGFS_ATTRIBUTE_FOPS(__name)
>
> static DEFINE_MUTEX(stats_lock);
>
> -static u64 dstats[MAX_NUM_BANKS][MAX_SUBBANK_DEPTH * MAX_NUM_SUB_BANKS] = {};
> +static u64 (*dstats)[MAX_NUM_BANKS][MAX_SUBBANK_DEPTH * MAX_NUM_SUB_BANKS];
> static int npc_mcam_dstats_show(struct seq_file *s, void *unused)
> {
> struct npc_priv_t *npc_priv;
> @@ -206,19 +206,19 @@ static int npc_mcam_dstats_show(struct seq_file *s, void *unused)
> NPC_AF_CN20K_MCAMEX_BANKX_STAT_EXT(idx, bank));
> if (!stats)
> continue;
> - if (stats == dstats[bank][idx])
> + if (stats == dstats[0][bank][idx])
> continue;
>
> - if (stats < dstats[bank][idx])
> - dstats[bank][idx] = 0;
> + if (stats < dstats[0][bank][idx])
> + dstats[0][bank][idx] = 0;
>
> pf = 0xFFFF;
> map = xa_load(&npc_priv->xa_idx2pf_map, mcam_idx);
> if (map)
> pf = xa_to_value(map);
>
> - if (stats > dstats[bank][idx])
> - delta = stats - dstats[bank][idx];
> + if (stats > dstats[0][bank][idx])
> + delta = stats - dstats[0][bank][idx];
> else
> delta = stats;
>
> @@ -226,7 +226,7 @@ static int npc_mcam_dstats_show(struct seq_file *s, void *unused)
> mcam_idx, pf, delta);
> seq_puts(s, buff);
>
> - dstats[bank][idx] = stats;
> + dstats[0][bank][idx] = stats;
> }
> }
>
> @@ -396,6 +396,10 @@ int npc_cn20k_debugfs_init(struct rvu *rvu)
> debugfs_create_file("vidx2idx", 0444, rvu->rvu_dbg.npc,
> npc_priv, &npc_vidx2idx_map_fops);
>
> + dstats = devm_kzalloc(rvu->dev, sizeof(*dstats), GFP_KERNEL);
> + if (!dstats)
> + return -ENOMEM;
> +
> debugfs_create_file("dstats", 0444, rvu->rvu_dbg.npc, rvu,
> &npc_mcam_dstats_fops);
>
> diff --git a/drivers/net/ethernet/marvell/octeontx2/af/cn20k/npc.c b/drivers/net/ethernet/marvell/octeontx2/af/cn20k/npc.c
> index 15b3f29d60ee..ea8fc43df090 100644
> --- a/drivers/net/ethernet/marvell/octeontx2/af/cn20k/npc.c
> +++ b/drivers/net/ethernet/marvell/octeontx2/af/cn20k/npc.c
> @@ -16,9 +16,7 @@
> #include "cn20k/reg.h"
> #include "rvu_npc_fs.h"
>
> -static struct npc_priv_t npc_priv = {
> - .num_banks = MAX_NUM_BANKS,
> -};
> +static struct npc_priv_t *npc_priv;
>
> static const char *npc_kw_name[NPC_MCAM_KEY_MAX] = {
> [NPC_MCAM_KEY_DYN] = "DYNAMIC",
> @@ -226,7 +224,7 @@ static u16 npc_idx2vidx(u16 idx)
> vidx = idx;
> index = idx;
>
> - map = xa_load(&npc_priv.xa_idx2vidx_map, index);
> + map = xa_load(&npc_priv->xa_idx2vidx_map, index);
> if (!map)
> goto done;
>
> @@ -242,7 +240,7 @@ static u16 npc_idx2vidx(u16 idx)
>
> static bool npc_is_vidx(u16 vidx)
> {
> - return vidx >= npc_priv.bank_depth * 2;
> + return vidx >= npc_priv->bank_depth * 2;
> }
>
> static u16 npc_vidx2idx(u16 vidx)
> @@ -256,7 +254,7 @@ static u16 npc_vidx2idx(u16 vidx)
> idx = vidx;
> index = vidx;
>
> - map = xa_load(&npc_priv.xa_vidx2idx_map, index);
> + map = xa_load(&npc_priv->xa_vidx2idx_map, index);
> if (!map)
> goto done;
>
> @@ -272,7 +270,7 @@ static u16 npc_vidx2idx(u16 vidx)
>
> u16 npc_cn20k_vidx2idx(u16 idx)
> {
> - if (!npc_priv.init_done)
> + if (!npc_priv)
> return idx;
>
> if (!npc_is_vidx(idx))
> @@ -283,7 +281,7 @@ u16 npc_cn20k_vidx2idx(u16 idx)
>
> u16 npc_cn20k_idx2vidx(u16 idx)
> {
> - if (!npc_priv.init_done)
> + if (!npc_priv)
> return idx;
>
> if (npc_is_vidx(idx))
> @@ -306,7 +304,7 @@ static int npc_vidx_maps_del_entry(struct rvu *rvu, u16 vidx, u16 *old_midx)
>
> mcam_idx = npc_vidx2idx(vidx);
>
> - map = xa_erase(&npc_priv.xa_vidx2idx_map, vidx);
> + map = xa_erase(&npc_priv->xa_vidx2idx_map, vidx);
> if (!map) {
> dev_err(rvu->dev,
> "%s: vidx(%u) does not map to proper mcam idx\n",
> @@ -314,7 +312,7 @@ static int npc_vidx_maps_del_entry(struct rvu *rvu, u16 vidx, u16 *old_midx)
> return -ESRCH;
> }
>
> - map = xa_erase(&npc_priv.xa_idx2vidx_map, mcam_idx);
> + map = xa_erase(&npc_priv->xa_idx2vidx_map, mcam_idx);
> if (!map) {
> dev_err(rvu->dev,
> "%s: vidx(%u) is not valid\n",
> @@ -341,7 +339,7 @@ static int npc_vidx_maps_modify(struct rvu *rvu, u16 vidx, u16 new_midx)
> return -ESRCH;
> }
>
> - map = xa_erase(&npc_priv.xa_vidx2idx_map, vidx);
> + map = xa_erase(&npc_priv->xa_vidx2idx_map, vidx);
> if (!map) {
> dev_err(rvu->dev,
> "%s: vidx(%u) could not be deleted from vidx2idx map\n",
> @@ -351,7 +349,7 @@ static int npc_vidx_maps_modify(struct rvu *rvu, u16 vidx, u16 new_midx)
>
> old_midx = xa_to_value(map);
>
> - rc = xa_insert(&npc_priv.xa_vidx2idx_map, vidx,
> + rc = xa_insert(&npc_priv->xa_vidx2idx_map, vidx,
> xa_mk_value(new_midx), GFP_KERNEL);
> if (rc) {
> dev_err(rvu->dev,
> @@ -360,7 +358,7 @@ static int npc_vidx_maps_modify(struct rvu *rvu, u16 vidx, u16 new_midx)
> goto fail1;
> }
>
> - map = xa_erase(&npc_priv.xa_idx2vidx_map, old_midx);
> + map = xa_erase(&npc_priv->xa_idx2vidx_map, old_midx);
> if (!map) {
> dev_err(rvu->dev,
> "%s: old_midx(%u, vidx(%u)) cannot be added to idx2vidx map\n",
> @@ -369,7 +367,7 @@ static int npc_vidx_maps_modify(struct rvu *rvu, u16 vidx, u16 new_midx)
> goto fail2;
> }
>
> - rc = xa_insert(&npc_priv.xa_idx2vidx_map, new_midx,
> + rc = xa_insert(&npc_priv->xa_idx2vidx_map, new_midx,
> xa_mk_value(vidx), GFP_KERNEL);
> if (rc) {
> dev_err(rvu->dev,
> @@ -382,21 +380,21 @@ static int npc_vidx_maps_modify(struct rvu *rvu, u16 vidx, u16 new_midx)
>
> fail3:
> /* Restore vidx at old_midx location */
> - if (xa_insert(&npc_priv.xa_idx2vidx_map, old_midx,
> + if (xa_insert(&npc_priv->xa_idx2vidx_map, old_midx,
> xa_mk_value(vidx), GFP_KERNEL))
> dev_err(rvu->dev,
> "%s: Error to roll back idx2vidx old_midx=%u vidx=%u\n",
> __func__, old_midx, vidx);
> fail2:
> /* Erase new_midx inserted at vidx */
> - if (!xa_erase(&npc_priv.xa_vidx2idx_map, vidx))
> + if (!xa_erase(&npc_priv->xa_vidx2idx_map, vidx))
> dev_err(rvu->dev,
> "%s: Failed to roll back vidx2idx vidx=%u\n",
> __func__, vidx);
>
> fail1:
> /* Restore old_midx at vidx location */
> - if (xa_insert(&npc_priv.xa_vidx2idx_map, vidx,
> + if (xa_insert(&npc_priv->xa_vidx2idx_map, vidx,
> xa_mk_value(old_midx), GFP_KERNEL))
> dev_err(rvu->dev,
> "%s: Failed to roll back vidx2idx to old_midx=%u, vidx=%u\n",
> @@ -412,10 +410,10 @@ static int npc_vidx_maps_add_entry(struct rvu *rvu, u16 mcam_idx, int pcifunc,
> u32 id;
>
> /* Virtual index start from maximum mcam index + 1 */
> - max = npc_priv.bank_depth * 2 * 2 - 1;
> - min = npc_priv.bank_depth * 2;
> + max = npc_priv->bank_depth * 2 * 2 - 1;
> + min = npc_priv->bank_depth * 2;
>
> - rc = xa_alloc(&npc_priv.xa_vidx2idx_map, &id,
> + rc = xa_alloc(&npc_priv->xa_vidx2idx_map, &id,
> xa_mk_value(mcam_idx),
> XA_LIMIT(min, max), GFP_KERNEL);
> if (rc) {
> @@ -425,7 +423,7 @@ static int npc_vidx_maps_add_entry(struct rvu *rvu, u16 mcam_idx, int pcifunc,
> goto fail1;
> }
>
> - rc = xa_insert(&npc_priv.xa_idx2vidx_map, mcam_idx,
> + rc = xa_insert(&npc_priv->xa_idx2vidx_map, mcam_idx,
> xa_mk_value(id), GFP_KERNEL);
> if (rc) {
> dev_err(rvu->dev,
> @@ -440,7 +438,7 @@ static int npc_vidx_maps_add_entry(struct rvu *rvu, u16 mcam_idx, int pcifunc,
> return 0;
>
> fail2:
> - xa_erase(&npc_priv.xa_vidx2idx_map, id);
> + xa_erase(&npc_priv->xa_vidx2idx_map, id);
> fail1:
> return rc;
> }
> @@ -691,7 +689,7 @@ void npc_cn20k_parser_profile_init(struct rvu *rvu, int blkaddr)
>
> struct npc_priv_t *npc_priv_get(void)
> {
> - return &npc_priv;
> + return npc_priv;
> }
>
> static void npc_program_mkex_rx(struct rvu *rvu, int blkaddr,
> @@ -860,9 +858,9 @@ npc_cn20k_enable_mcam_entry(struct rvu *rvu, int blkaddr,
>
> update_en_map:
> if (enable)
> - set_bit(index, npc_priv.en_map);
> + set_bit(index, npc_priv->en_map);
> else
> - clear_bit(index, npc_priv.en_map);
> + clear_bit(index, npc_priv->en_map);
>
> return 0;
> }
> @@ -1751,28 +1749,28 @@ int npc_mcam_idx_2_key_type(struct rvu *rvu, u16 mcam_idx, u8 *key_type)
> int bank_off, sb_id;
>
> /* mcam_idx should be less than (2 * bank depth) */
> - if (mcam_idx >= npc_priv.bank_depth * 2) {
> + if (mcam_idx >= npc_priv->bank_depth * 2) {
> dev_err(rvu->dev, "%s: bad params\n",
> __func__);
> return -EINVAL;
> }
>
> /* find mcam offset per bank */
> - bank_off = mcam_idx & (npc_priv.bank_depth - 1);
> + bank_off = mcam_idx & (npc_priv->bank_depth - 1);
>
> /* Find subbank id */
> - sb_id = bank_off / npc_priv.subbank_depth;
> + sb_id = bank_off / npc_priv->subbank_depth;
>
> /* Check if subbank id is more than maximum
> * number of subbanks available
> */
> - if (sb_id >= npc_priv.num_subbanks) {
> + if (sb_id >= npc_priv->num_subbanks) {
> dev_err(rvu->dev, "%s: invalid subbank %d\n",
> __func__, sb_id);
> return -EINVAL;
> }
>
> - sb = &npc_priv.sb[sb_id];
> + sb = &npc_priv->sb[sb_id];
>
> *key_type = sb->key_type;
>
> @@ -1788,7 +1786,7 @@ static int npc_subbank_idx_2_mcam_idx(struct rvu *rvu, struct npc_subbank *sb,
> * subsection depth - 1
> */
> if (sb->key_type == NPC_MCAM_KEY_X4 &&
> - sub_off >= npc_priv.subbank_depth) {
> + sub_off >= npc_priv->subbank_depth) {
> dev_err(rvu->dev,
> "%s: Failed to get mcam idx (x4) sb->idx=%u sub_off=%u",
> __func__, sb->idx, sub_off);
> @@ -1799,7 +1797,7 @@ static int npc_subbank_idx_2_mcam_idx(struct rvu *rvu, struct npc_subbank *sb,
> * 2 * subsection depth - 1
> */
> if (sb->key_type == NPC_MCAM_KEY_X2 &&
> - sub_off >= npc_priv.subbank_depth * 2) {
> + sub_off >= npc_priv->subbank_depth * 2) {
> dev_err(rvu->dev,
> "%s: Failed to get mcam idx (x2) sb->idx=%u sub_off=%u",
> __func__, sb->idx, sub_off);
> @@ -1807,12 +1805,12 @@ static int npc_subbank_idx_2_mcam_idx(struct rvu *rvu, struct npc_subbank *sb,
> }
>
> /* Find subbank offset from respective subbank (w.r.t bank) */
> - off = sub_off & (npc_priv.subbank_depth - 1);
> + off = sub_off & (npc_priv->subbank_depth - 1);
>
> /* if subsection idx is in bank1, add bank depth,
> * which is part of sb->b1b
> */
> - bot = sub_off >= npc_priv.subbank_depth ? sb->b1b : sb->b0b;
> + bot = sub_off >= npc_priv->subbank_depth ? sb->b1b : sb->b0b;
>
> *mcam_idx = bot + off;
> return 0;
> @@ -1825,37 +1823,37 @@ int npc_mcam_idx_2_subbank_idx(struct rvu *rvu, u16 mcam_idx,
> int bank_off, sb_id;
>
> /* mcam_idx should be less than (2 * bank depth) */
> - if (mcam_idx >= npc_priv.bank_depth * 2) {
> + if (mcam_idx >= npc_priv->bank_depth * 2) {
> dev_err(rvu->dev, "%s: Invalid mcam idx %u\n",
> __func__, mcam_idx);
> return -EINVAL;
> }
>
> /* find mcam offset per bank */
> - bank_off = mcam_idx & (npc_priv.bank_depth - 1);
> + bank_off = mcam_idx & (npc_priv->bank_depth - 1);
>
> /* Find subbank id */
> - sb_id = bank_off / npc_priv.subbank_depth;
> + sb_id = bank_off / npc_priv->subbank_depth;
>
> /* Check if subbank id is more than maximum
> * number of subbanks available
> */
> - if (sb_id >= npc_priv.num_subbanks) {
> + if (sb_id >= npc_priv->num_subbanks) {
> dev_err(rvu->dev, "%s: invalid subbank %d\n",
> __func__, sb_id);
> return -EINVAL;
> }
>
> - *sb = &npc_priv.sb[sb_id];
> + *sb = &npc_priv->sb[sb_id];
>
> /* Subbank offset per bank */
> - *sb_off = bank_off % npc_priv.subbank_depth;
> + *sb_off = bank_off % npc_priv->subbank_depth;
>
> /* Index in a subbank should add subbank depth
> * if it is in bank1
> */
> - if (mcam_idx >= npc_priv.bank_depth)
> - *sb_off += npc_priv.subbank_depth;
> + if (mcam_idx >= npc_priv->bank_depth)
> + *sb_off += npc_priv->subbank_depth;
>
> return 0;
> }
> @@ -1871,9 +1869,9 @@ static int __npc_subbank_contig_alloc(struct rvu *rvu,
> int k, offset, delta = 0;
> int cnt = 0, sbd;
>
> - sbd = npc_priv.subbank_depth;
> + sbd = npc_priv->subbank_depth;
>
> - if (sidx >= npc_priv.bank_depth)
> + if (sidx >= npc_priv->bank_depth)
> delta = sbd;
>
> switch (prio) {
> @@ -1940,8 +1938,8 @@ static int __npc_subbank_non_contig_alloc(struct rvu *rvu,
> int cnt = 0, delta;
> int k, sbd;
>
> - sbd = npc_priv.subbank_depth;
> - delta = sidx >= npc_priv.bank_depth ? sbd : 0;
> + sbd = npc_priv->subbank_depth;
> + delta = sidx >= npc_priv->bank_depth ? sbd : 0;
>
> switch (prio) {
> /* Find an area of size 'count' from sidx to eidx */
> @@ -2002,7 +2000,7 @@ static void __npc_subbank_sboff_2_off(struct rvu *rvu, struct npc_subbank *sb,
> {
> int sbd;
>
> - sbd = npc_priv.subbank_depth;
> + sbd = npc_priv->subbank_depth;
>
> *off = sb_off & (sbd - 1);
> *bmap = (sb_off >= sbd) ? sb->b1map : sb->b0map;
> @@ -2051,20 +2049,20 @@ static int __npc_subbank_mark_free(struct rvu *rvu, struct npc_subbank *sb)
> sb->flags = NPC_SUBBANK_FLAG_FREE;
> sb->key_type = 0;
>
> - bitmap_clear(sb->b0map, 0, npc_priv.subbank_depth);
> - bitmap_clear(sb->b1map, 0, npc_priv.subbank_depth);
> + bitmap_clear(sb->b0map, 0, npc_priv->subbank_depth);
> + bitmap_clear(sb->b1map, 0, npc_priv->subbank_depth);
>
> - if (!xa_erase(&npc_priv.xa_sb_used, sb->arr_idx)) {
> + if (!xa_erase(&npc_priv->xa_sb_used, sb->arr_idx)) {
> dev_err(rvu->dev,
> "%s: Error to delete from xa_sb_used array\n",
> __func__);
> return -EFAULT;
> }
>
> - rc = xa_insert(&npc_priv.xa_sb_free, sb->arr_idx,
> + rc = xa_insert(&npc_priv->xa_sb_free, sb->arr_idx,
> xa_mk_value(sb->idx), GFP_KERNEL);
> if (rc) {
> - rc = xa_insert(&npc_priv.xa_sb_used, sb->arr_idx,
> + rc = xa_insert(&npc_priv->xa_sb_used, sb->arr_idx,
> xa_mk_value(sb->idx), GFP_KERNEL);
> if (rc)
> dev_err(rvu->dev,
> @@ -2093,21 +2091,21 @@ static int __npc_subbank_mark_used(struct rvu *rvu, struct npc_subbank *sb,
> sb->flags = NPC_SUBBANK_FLAG_USED;
> sb->key_type = key_type;
> if (key_type == NPC_MCAM_KEY_X4)
> - sb->free_cnt = npc_priv.subbank_depth;
> + sb->free_cnt = npc_priv->subbank_depth;
> else
> - sb->free_cnt = 2 * npc_priv.subbank_depth;
> + sb->free_cnt = 2 * npc_priv->subbank_depth;
>
> - bitmap_clear(sb->b0map, 0, npc_priv.subbank_depth);
> - bitmap_clear(sb->b1map, 0, npc_priv.subbank_depth);
> + bitmap_clear(sb->b0map, 0, npc_priv->subbank_depth);
> + bitmap_clear(sb->b1map, 0, npc_priv->subbank_depth);
>
> - if (!xa_erase(&npc_priv.xa_sb_free, sb->arr_idx)) {
> + if (!xa_erase(&npc_priv->xa_sb_free, sb->arr_idx)) {
> dev_err(rvu->dev,
> "%s: Error to delete from xa_sb_free array\n",
> __func__);
> return -EFAULT;
> }
>
> - rc = xa_insert(&npc_priv.xa_sb_used, sb->arr_idx,
> + rc = xa_insert(&npc_priv->xa_sb_used, sb->arr_idx,
> xa_mk_value(sb->idx), GFP_KERNEL);
> if (rc)
> dev_err(rvu->dev,
> @@ -2131,10 +2129,10 @@ static bool __npc_subbank_free(struct rvu *rvu, struct npc_subbank *sb,
>
> /* Check whether we can mark whole subbank as free */
> if (sb->key_type == NPC_MCAM_KEY_X4) {
> - if (sb->free_cnt < npc_priv.subbank_depth)
> + if (sb->free_cnt < npc_priv->subbank_depth)
> goto done;
> } else {
> - if (sb->free_cnt < 2 * npc_priv.subbank_depth)
> + if (sb->free_cnt < 2 * npc_priv->subbank_depth)
> goto done;
> }
>
> @@ -2213,7 +2211,7 @@ static int __npc_subbank_alloc(struct rvu *rvu, struct npc_subbank *sb,
>
> /* x4 indexes are from 0 to bank size as it combines two x2 banks */
> if (key_type == NPC_MCAM_KEY_X4 &&
> - (ref >= npc_priv.bank_depth || limit >= npc_priv.bank_depth)) {
> + (ref >= npc_priv->bank_depth || limit >= npc_priv->bank_depth)) {
> dev_err(rvu->dev,
> "%s: Wrong ref_enty(%d) or limit(%d) for x4\n",
> __func__, ref, limit);
> @@ -2223,8 +2221,8 @@ static int __npc_subbank_alloc(struct rvu *rvu, struct npc_subbank *sb,
> /* This function is called either bank0 or bank1 portion of a subbank.
> * so ref and limit should be on same bank.
> */
> - diffbank = !!((ref & npc_priv.bank_depth) ^
> - (limit & npc_priv.bank_depth));
> + diffbank = !!((ref & npc_priv->bank_depth) ^
> + (limit & npc_priv->bank_depth));
> if (diffbank) {
> dev_err(rvu->dev,
> "%s: request ref and limit should be from same bank\n",
> @@ -2248,7 +2246,7 @@ static int __npc_subbank_alloc(struct rvu *rvu, struct npc_subbank *sb,
> * or equal to mcam entries available in the subbank if contig.
> */
> if (sb->flags & NPC_SUBBANK_FLAG_FREE) {
> - if (contig && count > npc_priv.subbank_depth) {
> + if (contig && count > npc_priv->subbank_depth) {
> dev_err(rvu->dev, "%s: Less number of entries\n",
> __func__);
> return -ENOSPC;
> @@ -2271,10 +2269,10 @@ static int __npc_subbank_alloc(struct rvu *rvu, struct npc_subbank *sb,
> }
>
> process:
> - /* if ref or limit >= npc_priv.bank_depth, index are in bank1.
> + /* if ref or limit >= npc_priv->bank_depth, index are in bank1.
> * else bank0.
> */
> - if (ref >= npc_priv.bank_depth) {
> + if (ref >= npc_priv->bank_depth) {
> bmap = sb->b1map;
> t = sb->b1t;
> b = sb->b1b;
> @@ -2285,8 +2283,8 @@ static int __npc_subbank_alloc(struct rvu *rvu, struct npc_subbank *sb,
> }
>
> /* Calculate free slots */
> - bw = bitmap_weight(bmap, npc_priv.subbank_depth);
> - bfree = npc_priv.subbank_depth - bw;
> + bw = bitmap_weight(bmap, npc_priv->subbank_depth);
> + bfree = npc_priv->subbank_depth - bw;
>
> if (!bfree) {
> dev_dbg(rvu->dev, "%s: subbank is full\n", __func__);
> @@ -2415,7 +2413,7 @@ npc_del_from_pf_maps(struct rvu *rvu, u16 mcam_idx)
> int pcifunc, idx;
> void *map;
>
> - map = xa_erase(&npc_priv.xa_idx2pf_map, mcam_idx);
> + map = xa_erase(&npc_priv->xa_idx2pf_map, mcam_idx);
> if (!map) {
> dev_err(rvu->dev,
> "%s: failed to erase mcam_idx(%u) from xa_idx2pf map\n",
> @@ -2424,7 +2422,7 @@ npc_del_from_pf_maps(struct rvu *rvu, u16 mcam_idx)
> }
>
> pcifunc = xa_to_value(map);
> - map = xa_load(&npc_priv.xa_pf_map, pcifunc);
> + map = xa_load(&npc_priv->xa_pf_map, pcifunc);
> if (!map) {
> dev_err(rvu->dev,
> "%s: failed to find entry for (%u) from xa_pf_map, mcam=%u\n",
> @@ -2434,7 +2432,7 @@ npc_del_from_pf_maps(struct rvu *rvu, u16 mcam_idx)
>
> idx = xa_to_value(map);
>
> - map = xa_erase(&npc_priv.xa_pf2idx_map[idx], mcam_idx);
> + map = xa_erase(&npc_priv->xa_pf2idx_map[idx], mcam_idx);
> if (!map) {
> dev_err(rvu->dev,
> "%s: failed to erase mcam_idx(%u) from xa_pf2idx_map map\n",
> @@ -2454,18 +2452,18 @@ npc_add_to_pf_maps(struct rvu *rvu, u16 mcam_idx, int pcifunc)
> "%s: add2maps mcam_idx(%u) to xa_idx2pf map pcifunc=%#x\n",
> __func__, mcam_idx, pcifunc);
>
> - rc = xa_insert(&npc_priv.xa_idx2pf_map, mcam_idx,
> + rc = xa_insert(&npc_priv->xa_idx2pf_map, mcam_idx,
> xa_mk_value(pcifunc), GFP_KERNEL);
>
> if (rc) {
> - map = xa_load(&npc_priv.xa_idx2pf_map, mcam_idx);
> + map = xa_load(&npc_priv->xa_idx2pf_map, mcam_idx);
> dev_err(rvu->dev,
> "%s: failed to insert mcam_idx(%u) to xa_idx2pf map, existing value=%lu\n",
> __func__, mcam_idx, xa_to_value(map));
> return -EFAULT;
> }
>
> - map = xa_load(&npc_priv.xa_pf_map, pcifunc);
> + map = xa_load(&npc_priv->xa_pf_map, pcifunc);
> if (!map) {
> dev_err(rvu->dev,
> "%s: failed to find pf map entry for pcifunc=%#x, mcam=%u\n",
> @@ -2475,12 +2473,12 @@ npc_add_to_pf_maps(struct rvu *rvu, u16 mcam_idx, int pcifunc)
>
> idx = xa_to_value(map);
>
> - rc = xa_insert(&npc_priv.xa_pf2idx_map[idx], mcam_idx,
> + rc = xa_insert(&npc_priv->xa_pf2idx_map[idx], mcam_idx,
> xa_mk_value(pcifunc), GFP_KERNEL);
>
> if (rc) {
> - map = xa_load(&npc_priv.xa_pf2idx_map[idx], mcam_idx);
> - xa_erase(&npc_priv.xa_idx2pf_map, mcam_idx);
> + map = xa_load(&npc_priv->xa_pf2idx_map[idx], mcam_idx);
> + xa_erase(&npc_priv->xa_idx2pf_map, mcam_idx);
> dev_err(rvu->dev,
> "%s: failed to insert mcam_idx(%u) to xa_pf2idx_map map, earlier value=%lu idx=%u\n",
> __func__, mcam_idx, xa_to_value(map), idx);
> @@ -2510,9 +2508,9 @@ npc_subbank_suits(struct npc_subbank *sb, int key_type)
> return false;
> }
>
> -#define SB_ALIGN_UP(val) (((val) + npc_priv.subbank_depth) & \
> - ~((npc_priv.subbank_depth) - 1))
> -#define SB_ALIGN_DOWN(val) ALIGN_DOWN((val), npc_priv.subbank_depth)
> +#define SB_ALIGN_UP(val) (((val) + npc_priv->subbank_depth) & \
> + ~((npc_priv->subbank_depth) - 1))
> +#define SB_ALIGN_DOWN(val) ALIGN_DOWN((val), npc_priv->subbank_depth)
>
> static void npc_subbank_iter_down(struct rvu *rvu,
> int ref, int limit,
> @@ -2538,7 +2536,7 @@ static void npc_subbank_iter_down(struct rvu *rvu,
> }
>
> *cur_ref = *cur_limit - 1;
> - align = *cur_ref - npc_priv.subbank_depth + 1;
> + align = *cur_ref - npc_priv->subbank_depth + 1;
> if (align <= limit) {
> *stop = true;
> *cur_limit = limit;
> @@ -2578,7 +2576,7 @@ static void npc_subbank_iter_up(struct rvu *rvu,
> }
>
> *cur_ref = *cur_limit + 1;
> - align = *cur_ref + npc_priv.subbank_depth - 1;
> + align = *cur_ref + npc_priv->subbank_depth - 1;
>
> if (align >= limit) {
> *stop = true;
> @@ -2606,17 +2604,17 @@ npc_subbank_iter(struct rvu *rvu, int key_type,
>
> /* limit and ref should < bank_depth for x4 */
> if (key_type == NPC_MCAM_KEY_X4) {
> - if (*cur_ref >= npc_priv.bank_depth)
> + if (*cur_ref >= npc_priv->bank_depth)
> return -EINVAL;
>
> - if (*cur_limit >= npc_priv.bank_depth)
> + if (*cur_limit >= npc_priv->bank_depth)
> return -EINVAL;
> }
> /* limit and ref should < 2 * bank_depth, for x2 */
> - if (*cur_ref >= 2 * npc_priv.bank_depth)
> + if (*cur_ref >= 2 * npc_priv->bank_depth)
> return -EINVAL;
>
> - if (*cur_limit >= 2 * npc_priv.bank_depth)
> + if (*cur_limit >= 2 * npc_priv->bank_depth)
> return -EINVAL;
>
> return 0;
> @@ -2651,7 +2649,7 @@ static int npc_idx_free(struct rvu *rvu, u16 *mcam_idx, int count,
> vidx = npc_idx2vidx(midx);
> }
>
> - if (midx >= npc_priv.bank_depth * npc_priv.num_banks) {
> + if (midx >= npc_priv->bank_depth * npc_priv->num_banks) {
> dev_err(rvu->dev,
> "%s: Invalid mcam_idx=%u cannot be deleted\n",
> __func__, mcam_idx[i]);
> @@ -2846,7 +2844,7 @@ static int npc_subbank_free_cnt(struct rvu *rvu, struct npc_subbank *sb,
> {
> int cnt, spd;
>
> - spd = npc_priv.subbank_depth;
> + spd = npc_priv->subbank_depth;
> mutex_lock(&sb->lock);
>
> if (sb->flags & NPC_SUBBANK_FLAG_FREE)
> @@ -3005,7 +3003,7 @@ static int npc_subbank_noref_alloc(struct rvu *rvu, int key_type, bool contig,
> max_alloc = !contig;
>
> /* Check used subbanks for free slots */
> - xa_for_each(&npc_priv.xa_sb_used, index, val) {
> + xa_for_each(&npc_priv->xa_sb_used, index, val) {
> idx = xa_to_value(val);
>
> /* Minimize allocation from restricted subbanks
> @@ -3014,7 +3012,7 @@ static int npc_subbank_noref_alloc(struct rvu *rvu, int key_type, bool contig,
> if (npc_subbank_restrict_usage(rvu, idx))
> continue;
>
> - sb = &npc_priv.sb[idx];
> + sb = &npc_priv->sb[idx];
>
> /* Skip if not suitable subbank */
> if (!npc_subbank_suits(sb, key_type))
> @@ -3071,9 +3069,9 @@ static int npc_subbank_noref_alloc(struct rvu *rvu, int key_type, bool contig,
> }
>
> /* Allocate in free subbanks */
> - xa_for_each(&npc_priv.xa_sb_free, index, val) {
> + xa_for_each(&npc_priv->xa_sb_free, index, val) {
> idx = xa_to_value(val);
> - sb = &npc_priv.sb[idx];
> + sb = &npc_priv->sb[idx];
>
> /* Minimize allocation from restricted subbanks
> * in noref allocations.
> @@ -3129,7 +3127,7 @@ static int npc_subbank_noref_alloc(struct rvu *rvu, int key_type, bool contig,
> for (i = 0; restrict_valid &&
> (i < ARRAY_SIZE(npc_subbank_restricted_idxs)); i++) {
> idx = npc_subbank_restricted_idxs[i];
> - sb = &npc_priv.sb[idx];
> + sb = &npc_priv->sb[idx];
>
> /* Skip if not suitable subbank */
> if (!npc_subbank_suits(sb, key_type))
> @@ -3209,7 +3207,7 @@ int npc_cn20k_ref_idx_alloc(struct rvu *rvu, int pcifunc, int key_type,
> bool ref_valid;
> u16 vidx;
>
> - bd = npc_priv.bank_depth;
> + bd = npc_priv->bank_depth;
>
> /* Special case: ref == 0 && limit= 0 && prio == HIGH && count == 1
> * Here user wants to allocate 0th entry
> @@ -3227,7 +3225,7 @@ int npc_cn20k_ref_idx_alloc(struct rvu *rvu, int pcifunc, int key_type,
> ref_valid = !!(limit || ref);
> defrag_candidate = !ref_valid && !contig && virt;
> if (!ref_valid) {
> - if (contig && count > npc_priv.subbank_depth)
> + if (contig && count > npc_priv->subbank_depth)
> goto try_noref_multi_subbank;
>
> rc = npc_subbank_noref_alloc(rvu, key_type, contig,
> @@ -3272,7 +3270,7 @@ int npc_cn20k_ref_idx_alloc(struct rvu *rvu, int pcifunc, int key_type,
> return -EINVAL;
> }
>
> - if (contig && count > npc_priv.subbank_depth)
> + if (contig && count > npc_priv->subbank_depth)
> goto try_ref_multi_subbank;
>
> rc = npc_subbank_ref_alloc(rvu, key_type, ref, limit,
> @@ -3334,8 +3332,8 @@ void npc_cn20k_subbank_calc_free(struct rvu *rvu, int *x2_free,
> *x4_free = 0;
> *sb_free = 0;
>
> - for (i = 0; i < npc_priv.num_subbanks; i++) {
> - sb = &npc_priv.sb[i];
> + for (i = 0; i < npc_priv->num_subbanks; i++) {
> + sb = &npc_priv->sb[i];
> mutex_lock(&sb->lock);
>
> /* Count number of free subbanks */
> @@ -3433,11 +3431,11 @@ static void npc_subbank_init(struct rvu *rvu, struct npc_subbank *sb, int idx)
> {
> mutex_init(&sb->lock);
>
> - sb->b0b = idx * npc_priv.subbank_depth;
> - sb->b0t = sb->b0b + npc_priv.subbank_depth - 1;
> + sb->b0b = idx * npc_priv->subbank_depth;
> + sb->b0t = sb->b0b + npc_priv->subbank_depth - 1;
>
> - sb->b1b = npc_priv.bank_depth + idx * npc_priv.subbank_depth;
> - sb->b1t = sb->b1b + npc_priv.subbank_depth - 1;
> + sb->b1b = npc_priv->bank_depth + idx * npc_priv->subbank_depth;
> + sb->b1t = sb->b1b + npc_priv->subbank_depth - 1;
>
> sb->flags = NPC_SUBBANK_FLAG_FREE;
> sb->idx = idx;
> @@ -3449,7 +3447,7 @@ static void npc_subbank_init(struct rvu *rvu, struct npc_subbank *sb, int idx)
> /* Keep first and last subbank at end of free array; so that
> * it will be used at last
> */
> - xa_store(&npc_priv.xa_sb_free, sb->arr_idx,
> + xa_store(&npc_priv->xa_sb_free, sb->arr_idx,
> xa_mk_value(sb->idx), GFP_KERNEL);
> }
>
> @@ -3474,7 +3472,7 @@ static int npc_pcifunc_map_create(struct rvu *rvu)
>
> pcifunc = pf << 9;
>
> - xa_store(&npc_priv.xa_pf_map, (unsigned long)pcifunc,
> + xa_store(&npc_priv->xa_pf_map, (unsigned long)pcifunc,
> xa_mk_value(cnt), GFP_KERNEL);
>
> cnt++;
> @@ -3483,7 +3481,7 @@ static int npc_pcifunc_map_create(struct rvu *rvu)
> for (vf = 0; vf < numvfs; vf++) {
> pcifunc = (pf << 9) | (vf + 1);
>
> - xa_store(&npc_priv.xa_pf_map, (unsigned long)pcifunc,
> + xa_store(&npc_priv->xa_pf_map, (unsigned long)pcifunc,
> xa_mk_value(cnt), GFP_KERNEL);
> cnt++;
> }
> @@ -3569,7 +3567,7 @@ static int npc_defrag_alloc_free_slots(struct rvu *rvu,
> int rc, sb_off, i, err;
> bool deleted;
>
> - sb = &npc_priv.sb[f->idx];
> + sb = &npc_priv->sb[f->idx];
>
> alloc_cnt1 = 0;
> alloc_cnt2 = 0;
> @@ -3639,9 +3637,9 @@ static int npc_defrag_add_2_show_list(struct rvu *rvu, u16 old_midx,
> node->vidx = vidx;
> INIT_LIST_HEAD(&node->list);
>
> - mutex_lock(&npc_priv.lock);
> - list_add_tail(&node->list, &npc_priv.defrag_lh);
> - mutex_unlock(&npc_priv.lock);
> + mutex_lock(&npc_priv->lock);
> + list_add_tail(&node->list, &npc_priv->defrag_lh);
> + mutex_unlock(&npc_priv->lock);
>
> return 0;
> }
> @@ -3745,7 +3743,7 @@ int npc_defrag_move_vdx_to_free(struct rvu *rvu,
> }
>
> /* save pcifunc */
> - map = xa_load(&npc_priv.xa_idx2pf_map, old_midx);
> + map = xa_load(&npc_priv->xa_idx2pf_map, old_midx);
> pcifunc = xa_to_value(map);
>
> /* delete from pf maps */
> @@ -3904,29 +3902,29 @@ static void npc_defrag_list_clear(void)
> {
> struct npc_defrag_show_node *node, *next;
>
> - mutex_lock(&npc_priv.lock);
> - list_for_each_entry_safe(node, next, &npc_priv.defrag_lh, list) {
> + mutex_lock(&npc_priv->lock);
> + list_for_each_entry_safe(node, next, &npc_priv->defrag_lh, list) {
> list_del_init(&node->list);
> kfree(node);
> }
>
> - mutex_unlock(&npc_priv.lock);
> + mutex_unlock(&npc_priv->lock);
> }
>
> static void npc_lock_all_subbank(void)
> {
> int i;
>
> - for (i = 0; i < npc_priv.num_subbanks; i++)
> - mutex_lock(&npc_priv.sb[i].lock);
> + for (i = 0; i < npc_priv->num_subbanks; i++)
> + mutex_lock(&npc_priv->sb[i].lock);
> }
>
> static void npc_unlock_all_subbank(void)
> {
> int i;
>
> - for (i = npc_priv.num_subbanks - 1; i >= 0; i--)
> - mutex_unlock(&npc_priv.sb[i].lock);
> + for (i = npc_priv->num_subbanks - 1; i >= 0; i--)
> + mutex_unlock(&npc_priv->sb[i].lock);
> }
>
> int npc_cn20k_search_order_set(struct rvu *rvu,
> @@ -3937,9 +3935,9 @@ int npc_cn20k_search_order_set(struct rvu *rvu,
> struct xarray *xa;
> int sb_idx, rc;
>
> - if (cnt != npc_priv.num_subbanks) {
> + if (cnt != npc_priv->num_subbanks) {
> dev_err(rvu->dev, "Number of entries(%u) != %u\n",
> - cnt, npc_priv.num_subbanks);
> + cnt, npc_priv->num_subbanks);
> return -EINVAL;
> }
>
> @@ -3948,11 +3946,11 @@ int npc_cn20k_search_order_set(struct rvu *rvu,
> restrict_valid = false;
>
> for (sb_idx = 0; sb_idx < cnt; sb_idx++) {
> - sb = &npc_priv.sb[sb_idx];
> + sb = &npc_priv->sb[sb_idx];
>
> - xa = &npc_priv.xa_sb_free;
> + xa = &npc_priv->xa_sb_free;
> if (sb->flags & NPC_SUBBANK_FLAG_USED)
> - xa = &npc_priv.xa_sb_used;
> + xa = &npc_priv->xa_sb_used;
>
> sb->arr_idx = narr[sb_idx];
>
> @@ -3975,7 +3973,7 @@ int npc_cn20k_search_order_set(struct rvu *rvu,
> const u32 *npc_cn20k_search_order_get(bool *restricted_order, u32 *sz)
> {
> *restricted_order = restrict_valid;
> - *sz = npc_priv.num_subbanks;
> + *sz = npc_priv->num_subbanks;
> return subbank_srch_order;
> }
>
> @@ -3999,7 +3997,7 @@ int npc_cn20k_defrag(struct rvu *rvu)
> INIT_LIST_HEAD(&x4lh);
> INIT_LIST_HEAD(&x2lh);
>
> - node = kcalloc(npc_priv.num_subbanks, sizeof(*node), GFP_KERNEL);
> + node = kcalloc(npc_priv->num_subbanks, sizeof(*node), GFP_KERNEL);
> if (!node)
> return -ENOMEM;
>
> @@ -4008,13 +4006,13 @@ int npc_cn20k_defrag(struct rvu *rvu)
> npc_lock_all_subbank();
>
> /* Fill in node with subbank properties */
> - for (i = 0; i < npc_priv.num_subbanks; i++) {
> - sb = &npc_priv.sb[i];
> + for (i = 0; i < npc_priv->num_subbanks; i++) {
> + sb = &npc_priv->sb[i];
>
> node[i].idx = i;
> node[i].key_type = sb->key_type;
> node[i].free_cnt = sb->free_cnt;
> - node[i].vidx = kcalloc(npc_priv.subbank_depth * 2,
> + node[i].vidx = kcalloc(npc_priv->subbank_depth * 2,
> sizeof(*node[i].vidx),
> GFP_KERNEL);
> if (!node[i].vidx) {
> @@ -4044,8 +4042,8 @@ int npc_cn20k_defrag(struct rvu *rvu)
> }
>
> /* Filling vidx[] array with all vidx in that subbank */
> - xa_for_each_start(&npc_priv.xa_vidx2idx_map, index, map,
> - npc_priv.bank_depth * 2) {
> + xa_for_each_start(&npc_priv->xa_vidx2idx_map, index, map,
> + npc_priv->bank_depth * 2) {
> midx = xa_to_value(map);
> rc = npc_mcam_idx_2_subbank_idx(rvu, midx,
> &sb, &sb_off);
> @@ -4062,14 +4060,14 @@ int npc_cn20k_defrag(struct rvu *rvu)
> }
>
> /* Mark all subbank which has ref allocation */
> - for (i = 0; i < npc_priv.num_subbanks; i++) {
> + for (i = 0; i < npc_priv->num_subbanks; i++) {
> tnode = &node[i];
>
> if (!tnode->valid)
> continue;
>
> tot = (tnode->key_type == NPC_MCAM_KEY_X2) ?
> - npc_priv.subbank_depth * 2 : npc_priv.subbank_depth;
> + npc_priv->subbank_depth * 2 : npc_priv->subbank_depth;
>
> if (node[i].vidx_cnt != tot - tnode->free_cnt)
> tnode->refs = true;
> @@ -4086,7 +4084,7 @@ int npc_cn20k_defrag(struct rvu *rvu)
> free_vidx:
> npc_unlock_all_subbank();
> mutex_unlock(&mcam->lock);
> - for (i = 0; i < npc_priv.num_subbanks; i++)
> + for (i = 0; i < npc_priv->num_subbanks; i++)
> kfree(node[i].vidx);
> kfree(node);
> return rc;
> @@ -4114,7 +4112,7 @@ int npc_cn20k_dft_rules_idx_get(struct rvu *rvu, u16 pcifunc, u16 *bcast,
> *ptr[i] = USHRT_MAX;
> }
>
> - if (!npc_priv.init_done)
> + if (!npc_priv)
> return 0;
>
> if (is_lbk_vf(rvu, pcifunc)) {
> @@ -4122,7 +4120,7 @@ int npc_cn20k_dft_rules_idx_get(struct rvu *rvu, u16 pcifunc, u16 *bcast,
> return -EINVAL;
>
> idx = NPC_DFT_RULE_ID_MK(pcifunc, NPC_DFT_RULE_PROMISC_ID);
> - val = xa_load(&npc_priv.xa_pf2dfl_rmap, idx);
> + val = xa_load(&npc_priv->xa_pf2dfl_rmap, idx);
> if (!val) {
> pr_debug("%s: Failed to find %s index for pcifunc=%#x\n",
> __func__,
> @@ -4141,7 +4139,7 @@ int npc_cn20k_dft_rules_idx_get(struct rvu *rvu, u16 pcifunc, u16 *bcast,
> return -EINVAL;
>
> idx = NPC_DFT_RULE_ID_MK(pcifunc, NPC_DFT_RULE_UCAST_ID);
> - val = xa_load(&npc_priv.xa_pf2dfl_rmap, idx);
> + val = xa_load(&npc_priv->xa_pf2dfl_rmap, idx);
> if (!val) {
> pr_debug("%s: Failed to find %s index for pcifunc=%#x\n",
> __func__,
> @@ -4161,7 +4159,7 @@ int npc_cn20k_dft_rules_idx_get(struct rvu *rvu, u16 pcifunc, u16 *bcast,
> continue;
>
> idx = NPC_DFT_RULE_ID_MK(pcifunc, i);
> - val = xa_load(&npc_priv.xa_pf2dfl_rmap, idx);
> + val = xa_load(&npc_priv->xa_pf2dfl_rmap, idx);
> if (!val) {
> pr_debug("%s: Failed to find %s index for pcifunc=%#x\n",
> __func__,
> @@ -4185,8 +4183,8 @@ int rvu_mbox_handler_npc_get_pfl_info(struct rvu *rvu, struct msg_req *req,
> return -EOPNOTSUPP;
> }
>
> - rsp->kw_type = npc_priv.kw;
> - rsp->x4_slots = npc_priv.bank_depth;
> + rsp->kw_type = npc_priv->kw;
> + rsp->x4_slots = npc_priv->bank_depth;
> return 0;
> }
>
> @@ -4276,7 +4274,7 @@ void npc_cn20k_dft_rules_free(struct rvu *rvu, u16 pcifunc)
> int blkaddr, rc, i;
> void *map;
>
> - if (!npc_priv.init_done)
> + if (!npc_priv)
> return;
>
> if (!npc_is_cgx_or_lbk(rvu, pcifunc)) {
> @@ -4294,7 +4292,7 @@ void npc_cn20k_dft_rules_free(struct rvu *rvu, u16 pcifunc)
> /* LBK */
> if (is_lbk_vf(rvu, pcifunc)) {
> index = NPC_DFT_RULE_ID_MK(pcifunc, NPC_DFT_RULE_PROMISC_ID);
> - map = xa_erase(&npc_priv.xa_pf2dfl_rmap, index);
> + map = xa_erase(&npc_priv->xa_pf2dfl_rmap, index);
> if (!map)
> dev_dbg(rvu->dev,
> "%s: Err from delete %s mcam idx from xarray (pcifunc=%#x\n",
> @@ -4308,7 +4306,7 @@ void npc_cn20k_dft_rules_free(struct rvu *rvu, u16 pcifunc)
> /* VF */
> if (is_vf(pcifunc)) {
> index = NPC_DFT_RULE_ID_MK(pcifunc, NPC_DFT_RULE_UCAST_ID);
> - map = xa_erase(&npc_priv.xa_pf2dfl_rmap, index);
> + map = xa_erase(&npc_priv->xa_pf2dfl_rmap, index);
> if (!map)
> dev_dbg(rvu->dev,
> "%s: Err from delete %s mcam idx from xarray (pcifunc=%#x\n",
> @@ -4322,7 +4320,7 @@ void npc_cn20k_dft_rules_free(struct rvu *rvu, u16 pcifunc)
> /* PF */
> for (i = NPC_DFT_RULE_START_ID; i < NPC_DFT_RULE_MAX_ID; i++) {
> index = NPC_DFT_RULE_ID_MK(pcifunc, i);
> - map = xa_erase(&npc_priv.xa_pf2dfl_rmap, index);
> + map = xa_erase(&npc_priv->xa_pf2dfl_rmap, index);
> if (!map)
> dev_dbg(rvu->dev,
> "%s: Err from delete %s mcam idx from xarray (pcifunc=%#x\n",
> @@ -4382,7 +4380,7 @@ int npc_cn20k_dft_rules_alloc(struct rvu *rvu, u16 pcifunc)
> struct msg_rsp free_rsp;
> u16 b, m, p, u;
>
> - if (!npc_priv.init_done)
> + if (!npc_priv)
> return 0;
>
> if (!npc_is_cgx_or_lbk(rvu, pcifunc)) {
> @@ -4405,7 +4403,7 @@ int npc_cn20k_dft_rules_alloc(struct rvu *rvu, u16 pcifunc)
> }
>
> /* Set ref index as lowest priority index */
> - eidx = 2 * npc_priv.bank_depth - 1;
> + eidx = 2 * npc_priv->bank_depth - 1;
>
> /* Install only UCAST for VF */
> cnt = is_vf(pcifunc) ? 1 : ARRAY_SIZE(mcam_idx);
> @@ -4471,9 +4469,9 @@ int npc_cn20k_dft_rules_alloc(struct rvu *rvu, u16 pcifunc)
> req.hdr.pcifunc = pcifunc;
> req.ref_prio = NPC_MCAM_LOWER_PRIO;
>
> - if (npc_priv.kw == NPC_MCAM_KEY_X4) {
> + if (npc_priv->kw == NPC_MCAM_KEY_X4) {
> req.kw_type = NPC_MCAM_KEY_X4;
> - req.ref_entry = eidx & (npc_priv.bank_depth - 1);
> + req.ref_entry = eidx & (npc_priv->bank_depth - 1);
> } else {
> req.kw_type = NPC_MCAM_KEY_X2;
> req.ref_entry = eidx;
> @@ -4497,7 +4495,7 @@ int npc_cn20k_dft_rules_alloc(struct rvu *rvu, u16 pcifunc)
> /* LBK */
> if (is_lbk_vf(rvu, pcifunc)) {
> index = NPC_DFT_RULE_ID_MK(pcifunc, NPC_DFT_RULE_PROMISC_ID);
> - ret = xa_insert(&npc_priv.xa_pf2dfl_rmap, index,
> + ret = xa_insert(&npc_priv->xa_pf2dfl_rmap, index,
> xa_mk_value(mcam_idx[0]), GFP_KERNEL);
> if (ret) {
> dev_err(rvu->dev,
> @@ -4514,7 +4512,7 @@ int npc_cn20k_dft_rules_alloc(struct rvu *rvu, u16 pcifunc)
> /* VF */
> if (is_vf(pcifunc)) {
> index = NPC_DFT_RULE_ID_MK(pcifunc, NPC_DFT_RULE_UCAST_ID);
> - ret = xa_insert(&npc_priv.xa_pf2dfl_rmap, index,
> + ret = xa_insert(&npc_priv->xa_pf2dfl_rmap, index,
> xa_mk_value(mcam_idx[0]), GFP_KERNEL);
> if (ret) {
> dev_err(rvu->dev,
> @@ -4532,7 +4530,7 @@ int npc_cn20k_dft_rules_alloc(struct rvu *rvu, u16 pcifunc)
> for (i = NPC_DFT_RULE_START_ID, k = 0; i < NPC_DFT_RULE_MAX_ID &&
> k < cnt; i++, k++) {
> index = NPC_DFT_RULE_ID_MK(pcifunc, i);
> - ret = xa_insert(&npc_priv.xa_pf2dfl_rmap, index,
> + ret = xa_insert(&npc_priv->xa_pf2dfl_rmap, index,
> xa_mk_value(mcam_idx[k]), GFP_KERNEL);
> if (ret) {
> dev_err(rvu->dev,
> @@ -4541,7 +4539,7 @@ int npc_cn20k_dft_rules_alloc(struct rvu *rvu, u16 pcifunc)
> pcifunc);
> for (int p = NPC_DFT_RULE_START_ID; p < i; p++) {
> index = NPC_DFT_RULE_ID_MK(pcifunc, p);
> - xa_erase(&npc_priv.xa_pf2dfl_rmap, index);
> + xa_erase(&npc_priv->xa_pf2dfl_rmap, index);
> }
> goto err;
> }
> @@ -4599,34 +4597,40 @@ static int npc_priv_init(struct rvu *rvu)
> return -EINVAL;
> }
>
> - npc_priv.num_subbanks = num_subbanks;
> + npc_priv = kcalloc(1, sizeof(*npc_priv), GFP_KERNEL);
> + if (!npc_priv)
> + return -ENOMEM;
> +
> + npc_priv->num_banks = num_banks;
> +
> + npc_priv->num_subbanks = num_subbanks;
>
> subbank_depth = bank_depth / num_subbanks;
>
> - npc_priv.bank_depth = bank_depth;
> - npc_priv.subbank_depth = subbank_depth;
> + npc_priv->bank_depth = bank_depth;
> + npc_priv->subbank_depth = subbank_depth;
>
> /* Get kex configured key size */
> cfg = rvu_read64(rvu, blkaddr, NPC_AF_INTFX_KEX_CFG(0));
> - npc_priv.kw = FIELD_GET(GENMASK_ULL(34, 32), cfg);
> + npc_priv->kw = FIELD_GET(GENMASK_ULL(34, 32), cfg);
>
> dev_info(rvu->dev,
> "banks=%u depth=%u, subbanks=%u depth=%u, key type=%s\n",
> num_banks, bank_depth, num_subbanks, subbank_depth,
> - npc_kw_name[npc_priv.kw]);
> + npc_kw_name[npc_priv->kw]);
>
> - npc_priv.sb = kcalloc(num_subbanks, sizeof(struct npc_subbank),
> - GFP_KERNEL);
> - if (!npc_priv.sb)
> + npc_priv->sb = kcalloc(num_subbanks, sizeof(struct npc_subbank),
> + GFP_KERNEL);
> + if (!npc_priv->sb)
> return -ENOMEM;
>
> - xa_init_flags(&npc_priv.xa_sb_used, XA_FLAGS_ALLOC);
> - xa_init_flags(&npc_priv.xa_sb_free, XA_FLAGS_ALLOC);
> - xa_init_flags(&npc_priv.xa_idx2pf_map, XA_FLAGS_ALLOC);
> - xa_init_flags(&npc_priv.xa_pf_map, XA_FLAGS_ALLOC);
> - xa_init_flags(&npc_priv.xa_pf2dfl_rmap, XA_FLAGS_ALLOC);
> - xa_init_flags(&npc_priv.xa_idx2vidx_map, XA_FLAGS_ALLOC);
> - xa_init_flags(&npc_priv.xa_vidx2idx_map, XA_FLAGS_ALLOC);
> + xa_init_flags(&npc_priv->xa_sb_used, XA_FLAGS_ALLOC);
> + xa_init_flags(&npc_priv->xa_sb_free, XA_FLAGS_ALLOC);
> + xa_init_flags(&npc_priv->xa_idx2pf_map, XA_FLAGS_ALLOC);
> + xa_init_flags(&npc_priv->xa_pf_map, XA_FLAGS_ALLOC);
> + xa_init_flags(&npc_priv->xa_pf2dfl_rmap, XA_FLAGS_ALLOC);
> + xa_init_flags(&npc_priv->xa_idx2vidx_map, XA_FLAGS_ALLOC);
> + xa_init_flags(&npc_priv->xa_vidx2idx_map, XA_FLAGS_ALLOC);
>
> if (npc_create_srch_order(num_subbanks))
> goto fail1;
> @@ -4634,22 +4638,22 @@ static int npc_priv_init(struct rvu *rvu)
> npc_populate_restricted_idxs(num_subbanks);
>
> /* Initialize subbanks */
> - for (i = 0, sb = npc_priv.sb; i < num_subbanks; i++, sb++)
> + for (i = 0, sb = npc_priv->sb; i < num_subbanks; i++, sb++)
> npc_subbank_init(rvu, sb, i);
>
> /* Get number of pcifuncs in the system */
> - npc_priv.pf_cnt = npc_pcifunc_map_create(rvu);
> - npc_priv.xa_pf2idx_map = kcalloc(npc_priv.pf_cnt,
> - sizeof(struct xarray),
> - GFP_KERNEL);
> - if (!npc_priv.xa_pf2idx_map)
> + npc_priv->pf_cnt = npc_pcifunc_map_create(rvu);
> + npc_priv->xa_pf2idx_map = kcalloc(npc_priv->pf_cnt,
> + sizeof(struct xarray),
> + GFP_KERNEL);
> + if (!npc_priv->xa_pf2idx_map)
> goto fail2;
>
> - for (i = 0; i < npc_priv.pf_cnt; i++)
> - xa_init_flags(&npc_priv.xa_pf2idx_map[i], XA_FLAGS_ALLOC);
> + for (i = 0; i < npc_priv->pf_cnt; i++)
> + xa_init_flags(&npc_priv->xa_pf2idx_map[i], XA_FLAGS_ALLOC);
>
> - INIT_LIST_HEAD(&npc_priv.defrag_lh);
> - mutex_init(&npc_priv.lock);
> + INIT_LIST_HEAD(&npc_priv->defrag_lh);
> + mutex_init(&npc_priv->lock);
>
> return 0;
>
> @@ -4658,15 +4662,17 @@ static int npc_priv_init(struct rvu *rvu)
> subbank_srch_order = NULL;
>
> fail1:
> - xa_destroy(&npc_priv.xa_sb_used);
> - xa_destroy(&npc_priv.xa_sb_free);
> - xa_destroy(&npc_priv.xa_idx2pf_map);
> - xa_destroy(&npc_priv.xa_pf_map);
> - xa_destroy(&npc_priv.xa_pf2dfl_rmap);
> - xa_destroy(&npc_priv.xa_idx2vidx_map);
> - xa_destroy(&npc_priv.xa_vidx2idx_map);
> - kfree(npc_priv.sb);
> - npc_priv.sb = NULL;
> + xa_destroy(&npc_priv->xa_sb_used);
> + xa_destroy(&npc_priv->xa_sb_free);
> + xa_destroy(&npc_priv->xa_idx2pf_map);
> + xa_destroy(&npc_priv->xa_pf_map);
> + xa_destroy(&npc_priv->xa_pf2dfl_rmap);
> + xa_destroy(&npc_priv->xa_idx2vidx_map);
> + xa_destroy(&npc_priv->xa_vidx2idx_map);
> + kfree(npc_priv->sb);
> + npc_priv->sb = NULL;
> + kfree(npc_priv);
> + npc_priv = NULL;
> return -ENOMEM;
> }
>
> @@ -4674,25 +4680,30 @@ void npc_cn20k_deinit(struct rvu *rvu)
> {
> int i;
>
> - xa_destroy(&npc_priv.xa_sb_used);
> - xa_destroy(&npc_priv.xa_sb_free);
> - xa_destroy(&npc_priv.xa_idx2pf_map);
> - xa_destroy(&npc_priv.xa_pf_map);
> - xa_destroy(&npc_priv.xa_pf2dfl_rmap);
> - xa_destroy(&npc_priv.xa_idx2vidx_map);
> - xa_destroy(&npc_priv.xa_vidx2idx_map);
> + if (!npc_priv)
> + return;
> +
> + xa_destroy(&npc_priv->xa_sb_used);
> + xa_destroy(&npc_priv->xa_sb_free);
> + xa_destroy(&npc_priv->xa_idx2pf_map);
> + xa_destroy(&npc_priv->xa_pf_map);
> + xa_destroy(&npc_priv->xa_pf2dfl_rmap);
> + xa_destroy(&npc_priv->xa_idx2vidx_map);
> + xa_destroy(&npc_priv->xa_vidx2idx_map);
>
> - for (i = 0; i < npc_priv.pf_cnt; i++)
> - xa_destroy(&npc_priv.xa_pf2idx_map[i]);
> + for (i = 0; i < npc_priv->pf_cnt; i++)
> + xa_destroy(&npc_priv->xa_pf2idx_map[i]);
>
> - kfree(npc_priv.xa_pf2idx_map);
> + kfree(npc_priv->xa_pf2idx_map);
> /* No need to destroy mutex lock as it is
> * part of subbank structure
> */
> - kfree(npc_priv.sb);
> + kfree(npc_priv->sb);
> kfree(subbank_srch_order);
> - bitmap_clear(npc_priv.en_map, 0, MAX_NUM_BANKS * MAX_NUM_SUB_BANKS *
> + bitmap_clear(npc_priv->en_map, 0, MAX_NUM_BANKS * MAX_NUM_SUB_BANKS *
> MAX_SUBBANK_DEPTH);
> + kfree(npc_priv);
> + npc_priv = NULL;
> }
>
> static int npc_setup_mcam_section(struct rvu *rvu, int key_type)
> @@ -4705,7 +4716,7 @@ static int npc_setup_mcam_section(struct rvu *rvu, int key_type)
> return -ENODEV;
> }
>
> - for (sec = 0; sec < npc_priv.num_subbanks; sec++)
> + for (sec = 0; sec < npc_priv->num_subbanks; sec++)
> rvu_write64(rvu, blkaddr,
> NPC_AF_MCAM_SECTIONX_CFG_EXT(sec), key_type);
>
> @@ -4730,7 +4741,5 @@ int npc_cn20k_init(struct rvu *rvu)
> return err;
> }
>
> - npc_priv.init_done = true;
> -
> return 0;
> }
> diff --git a/drivers/net/ethernet/marvell/octeontx2/af/cn20k/npc.h b/drivers/net/ethernet/marvell/octeontx2/af/cn20k/npc.h
> index bf030e40fbf9..ee0bbeba7f25 100644
> --- a/drivers/net/ethernet/marvell/octeontx2/af/cn20k/npc.h
> +++ b/drivers/net/ethernet/marvell/octeontx2/af/cn20k/npc.h
> @@ -191,7 +191,7 @@ struct npc_defrag_show_node {
> */
> struct npc_priv_t {
> int bank_depth;
> - const int num_banks;
> + int num_banks;
> int num_subbanks;
> int subbank_depth;
> DECLARE_BITMAP(en_map, MAX_NUM_BANKS *
> @@ -210,7 +210,6 @@ struct npc_priv_t {
> struct list_head defrag_lh;
> struct mutex lock; /* protect defrag nodes */
> int pf_cnt;
> - bool init_done;
> };
>
> struct npc_kpm_action0 {
> --
> 2.43.0
>
^ permalink raw reply [flat|nested] 22+ messages in thread