mirror of
https://github.com/torvalds/linux.git
synced 2026-07-27 17:47:41 +02:00
octeontx2-af: npc: cn20k: add subbank search order control
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> Link: https://patch.msgid.link/20260609040453.711932-6-rkannoth@marvell.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
parent
eb7b4d458e
commit
7ac9d4c407
|
|
@ -3372,7 +3372,7 @@ rvu_mbox_handler_npc_cn20k_get_kex_cfg(struct rvu *rvu,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int *subbank_srch_order;
|
static u32 *subbank_srch_order;
|
||||||
|
|
||||||
static void npc_populate_restricted_idxs(int num_subbanks)
|
static void npc_populate_restricted_idxs(int num_subbanks)
|
||||||
{
|
{
|
||||||
|
|
@ -3384,7 +3384,7 @@ static int npc_create_srch_order(int cnt)
|
||||||
{
|
{
|
||||||
int val = 0;
|
int val = 0;
|
||||||
|
|
||||||
subbank_srch_order = kcalloc(cnt, sizeof(int),
|
subbank_srch_order = kcalloc(cnt, sizeof(u32),
|
||||||
GFP_KERNEL);
|
GFP_KERNEL);
|
||||||
if (!subbank_srch_order)
|
if (!subbank_srch_order)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
@ -3902,6 +3902,122 @@ static void npc_unlock_all_subbank(void)
|
||||||
mutex_unlock(&npc_priv.sb[i].lock);
|
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;
|
||||||
|
int rsrc[2][MAX_NUM_SUB_BANKS] = { };
|
||||||
|
u8 save[MAX_NUM_SUB_BANKS] = { };
|
||||||
|
struct npc_subbank *sb;
|
||||||
|
struct xarray *xa;
|
||||||
|
int prio, rc, err;
|
||||||
|
int sb_idx;
|
||||||
|
enum {
|
||||||
|
FREE = 0,
|
||||||
|
USED = 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
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();
|
||||||
|
|
||||||
|
for (sb_idx = 0; sb_idx < cnt; sb_idx++) {
|
||||||
|
sb = &npc_priv.sb[sb_idx];
|
||||||
|
save[sb->idx] = sb->arr_idx;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (prio = 0; prio < cnt; prio++) {
|
||||||
|
sb_idx = narr[prio];
|
||||||
|
sb = &npc_priv.sb[sb_idx];
|
||||||
|
|
||||||
|
if (sb->flags & NPC_SUBBANK_FLAG_USED)
|
||||||
|
xa = &npc_priv.xa_sb_used;
|
||||||
|
else
|
||||||
|
xa = &npc_priv.xa_sb_free;
|
||||||
|
|
||||||
|
rc = xa_err(xa_store(xa, prio,
|
||||||
|
xa_mk_value(sb_idx), GFP_KERNEL));
|
||||||
|
if (rc) {
|
||||||
|
dev_err(rvu->dev,
|
||||||
|
"Setting arr_idx=%d for sb=%d failed\n",
|
||||||
|
sb->arr_idx, sb_idx);
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sb->flags & NPC_SUBBANK_FLAG_USED) {
|
||||||
|
rsrc[USED][sb->arr_idx] -= 1;
|
||||||
|
rsrc[USED][prio] += 1;
|
||||||
|
} else {
|
||||||
|
rsrc[FREE][sb->arr_idx] -= 1;
|
||||||
|
rsrc[FREE][prio] += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
sb->arr_idx = prio;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (prio = 0; prio < cnt; prio++) {
|
||||||
|
if (rsrc[FREE][prio] == -1)
|
||||||
|
xa_erase(&npc_priv.xa_sb_free, prio);
|
||||||
|
|
||||||
|
if (rsrc[USED][prio] == -1)
|
||||||
|
xa_erase(&npc_priv.xa_sb_used, prio);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < cnt; i++)
|
||||||
|
subbank_srch_order[i] = (u32)narr[i];
|
||||||
|
|
||||||
|
restrict_valid = false;
|
||||||
|
|
||||||
|
npc_unlock_all_subbank();
|
||||||
|
mutex_unlock(&mcam->lock);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
fail:
|
||||||
|
for (prio = 0; prio < cnt; prio++) {
|
||||||
|
if (rsrc[FREE][prio] == 1)
|
||||||
|
xa_erase(&npc_priv.xa_sb_free, prio);
|
||||||
|
|
||||||
|
if (rsrc[USED][prio] == 1)
|
||||||
|
xa_erase(&npc_priv.xa_sb_used, prio);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (sb_idx = 0; sb_idx < cnt; sb_idx++) {
|
||||||
|
sb = &npc_priv.sb[sb_idx];
|
||||||
|
sb->arr_idx = save[sb_idx];
|
||||||
|
|
||||||
|
if (sb->flags & NPC_SUBBANK_FLAG_USED)
|
||||||
|
xa = &npc_priv.xa_sb_used;
|
||||||
|
else
|
||||||
|
xa = &npc_priv.xa_sb_free;
|
||||||
|
|
||||||
|
/* Since the entry already exists, xa_store() replaces
|
||||||
|
* the value without a kmalloc(), making failure highly unlikely.
|
||||||
|
*/
|
||||||
|
err = xa_err(xa_store(xa, sb->arr_idx,
|
||||||
|
xa_mk_value(sb->idx), GFP_KERNEL));
|
||||||
|
WARN(!!err, "Failed to rollback sb=%u idx=%u\n",
|
||||||
|
sb->idx, sb->arr_idx);
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
/* Only non-ref non-contigous mcam indexes
|
||||||
* are picked for defrag process
|
* are picked for defrag process
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -347,5 +347,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,
|
int npc_mcam_idx_2_subbank_idx(struct rvu *rvu, u16 mcam_idx,
|
||||||
struct npc_subbank **sb,
|
struct npc_subbank **sb,
|
||||||
int *sb_off);
|
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 */
|
#endif /* NPC_CN20K_H */
|
||||||
|
|
|
||||||
|
|
@ -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_EXACT_FEATURE_DISABLE,
|
||||||
RVU_AF_DEVLINK_PARAM_ID_NPC_DEF_RULE_CNTR_ENABLE,
|
RVU_AF_DEVLINK_PARAM_ID_NPC_DEF_RULE_CNTR_ENABLE,
|
||||||
RVU_AF_DEVLINK_PARAM_ID_NPC_DEFRAG,
|
RVU_AF_DEVLINK_PARAM_ID_NPC_DEFRAG,
|
||||||
|
RVU_AF_DEVLINK_PARAM_ID_NPC_SRCH_ORDER,
|
||||||
RVU_AF_DEVLINK_PARAM_ID_NIX_MAXLF,
|
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;
|
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 = {
|
static const struct devlink_ops rvu_devlink_ops = {
|
||||||
.eswitch_mode_get = rvu_devlink_eswitch_mode_get,
|
.eswitch_mode_get = rvu_devlink_eswitch_mode_get,
|
||||||
.eswitch_mode_set = rvu_devlink_eswitch_mode_set,
|
.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,
|
DEVLINK_PARAM_DRIVER(RVU_AF_DEVLINK_PARAM_ID_NPC_DEFRAG,
|
||||||
"npc_defrag", DEVLINK_PARAM_TYPE_STRING,
|
"npc_defrag", DEVLINK_PARAM_TYPE_STRING,
|
||||||
BIT(DEVLINK_PARAM_CMODE_RUNTIME),
|
BIT(DEVLINK_PARAM_CMODE_RUNTIME),
|
||||||
|
|
@ -1666,13 +1738,13 @@ int rvu_register_dl(struct rvu *rvu)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (is_cn20k(rvu->pdev)) {
|
if (is_cn20k(rvu->pdev)) {
|
||||||
err = devlink_params_register(dl, rvu_af_dl_param_defrag,
|
err = devlink_params_register(dl, rvu_af_dl_cn20k_params,
|
||||||
ARRAY_SIZE(rvu_af_dl_param_defrag));
|
ARRAY_SIZE(rvu_af_dl_cn20k_params));
|
||||||
if (err) {
|
if (err) {
|
||||||
dev_err(rvu->dev,
|
dev_err(rvu->dev,
|
||||||
"devlink defrag params register failed with error %d",
|
"devlink cn20k params register failed with error %d",
|
||||||
err);
|
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:
|
err_dl_exact_match:
|
||||||
if (is_cn20k(rvu->pdev))
|
if (is_cn20k(rvu->pdev))
|
||||||
devlink_params_unregister(dl, rvu_af_dl_param_defrag,
|
devlink_params_unregister(dl, rvu_af_dl_cn20k_params,
|
||||||
ARRAY_SIZE(rvu_af_dl_param_defrag));
|
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));
|
devlink_params_unregister(dl, rvu_af_dl_params, ARRAY_SIZE(rvu_af_dl_params));
|
||||||
|
|
||||||
err_dl_health:
|
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));
|
devlink_params_unregister(dl, rvu_af_dl_params, ARRAY_SIZE(rvu_af_dl_params));
|
||||||
|
|
||||||
if (is_cn20k(rvu->pdev))
|
if (is_cn20k(rvu->pdev))
|
||||||
devlink_params_unregister(dl, rvu_af_dl_param_defrag,
|
devlink_params_unregister(dl, rvu_af_dl_cn20k_params,
|
||||||
ARRAY_SIZE(rvu_af_dl_param_defrag));
|
ARRAY_SIZE(rvu_af_dl_cn20k_params));
|
||||||
|
|
||||||
/* Unregister exact match devlink only for CN10K-B */
|
/* Unregister exact match devlink only for CN10K-B */
|
||||||
if (rvu_npc_exact_has_match_table(rvu))
|
if (rvu_npc_exact_has_match_table(rvu))
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user