From a07f7ced436defb48596eabc189160228c2990b0 Mon Sep 17 00:00:00 2001 From: Kiran Kumar K Date: Tue, 6 Apr 2021 20:11:36 +0530 Subject: [PATCH] common/cnxk: add NPC init and fini Adding support initialize and fini the npc. Further, adding APIs to create and destroy the npc rules. Signed-off-by: Kiran Kumar K --- drivers/common/cnxk/meson.build | 1 + drivers/common/cnxk/roc_npc.c | 713 ++++++++++++++++++++++++++++++++ drivers/common/cnxk/roc_npc.h | 40 ++ drivers/common/cnxk/version.map | 16 + 4 files changed, 770 insertions(+) create mode 100644 drivers/common/cnxk/roc_npc.c diff --git a/drivers/common/cnxk/meson.build b/drivers/common/cnxk/meson.build index 9dd4c239c2..f12e34406f 100644 --- a/drivers/common/cnxk/meson.build +++ b/drivers/common/cnxk/meson.build @@ -34,6 +34,7 @@ sources = files('roc_dev.c', 'roc_npa.c', 'roc_npa_debug.c', 'roc_npa_irq.c', + 'roc_npc.c', 'roc_npc_mcam.c', 'roc_npc_parse.c', 'roc_npc_utils.c', diff --git a/drivers/common/cnxk/roc_npc.c b/drivers/common/cnxk/roc_npc.c new file mode 100644 index 0000000000..c1ac3c7fee --- /dev/null +++ b/drivers/common/cnxk/roc_npc.c @@ -0,0 +1,713 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(C) 2021 Marvell. + */ + +#include "roc_api.h" +#include "roc_priv.h" + +int +roc_npc_mcam_free_counter(struct roc_npc *roc_npc, uint16_t ctr_id) +{ + struct npc *npc = roc_npc_to_npc_priv(roc_npc); + + return npc_mcam_free_counter(npc, ctr_id); +} + +int +roc_npc_mcam_read_counter(struct roc_npc *roc_npc, uint32_t ctr_id, + uint64_t *count) +{ + struct npc *npc = roc_npc_to_npc_priv(roc_npc); + + return npc_mcam_read_counter(npc, ctr_id, count); +} + +int +roc_npc_mcam_clear_counter(struct roc_npc *roc_npc, uint32_t ctr_id) +{ + struct npc *npc = roc_npc_to_npc_priv(roc_npc); + + return npc_mcam_clear_counter(npc, ctr_id); +} + +int +roc_npc_mcam_free_entry(struct roc_npc *roc_npc, uint32_t entry) +{ + struct npc *npc = roc_npc_to_npc_priv(roc_npc); + + return npc_mcam_free_entry(npc, entry); +} + +int +roc_npc_mcam_free_all_resources(struct roc_npc *roc_npc) +{ + struct npc *npc = roc_npc_to_npc_priv(roc_npc); + + return npc_flow_free_all_resources(npc); +} + +int +roc_npc_mcam_alloc_entries(struct roc_npc *roc_npc, int ref_entry, + int *alloc_entry, int req_count, int priority, + int *resp_count) +{ + struct npc *npc = roc_npc_to_npc_priv(roc_npc); + + return npc_mcam_alloc_entries(npc, ref_entry, alloc_entry, req_count, + priority, resp_count); +} + +int +roc_npc_mcam_alloc_entry(struct roc_npc *roc_npc, struct roc_npc_flow *mcam, + struct roc_npc_flow *ref_mcam, int prio, + int *resp_count) +{ + struct npc *npc = roc_npc_to_npc_priv(roc_npc); + + return npc_mcam_alloc_entry(npc, mcam, ref_mcam, prio, resp_count); +} + +int +roc_npc_mcam_ena_dis_entry(struct roc_npc *roc_npc, struct roc_npc_flow *mcam, + bool enable) +{ + struct npc *npc = roc_npc_to_npc_priv(roc_npc); + + return npc_mcam_ena_dis_entry(npc, mcam, enable); +} + +int +roc_npc_mcam_write_entry(struct roc_npc *roc_npc, struct roc_npc_flow *mcam) +{ + struct npc *npc = roc_npc_to_npc_priv(roc_npc); + + return npc_mcam_write_entry(npc, mcam); +} + +int +roc_npc_get_low_priority_mcam(struct roc_npc *roc_npc) +{ + struct npc *npc = roc_npc_to_npc_priv(roc_npc); + + if (roc_model_is_cn10k()) + return (npc->mcam_entries - NPC_MCAME_RESVD_10XX - 1); + else + return (npc->mcam_entries - NPC_MCAME_RESVD_9XXX - 1); +} + +static int +npc_mcam_tot_entries(void) +{ + /* FIXME: change to reading in AF from NPC_AF_CONST1/2 + * MCAM_BANK_DEPTH(_EXT) * MCAM_BANKS + */ + if (roc_model_is_cn10k()) + return 16 * 1024; /* MCAM_BANKS = 4, BANK_DEPTH_EXT = 4096 */ + else + return 4 * 1024; /* MCAM_BANKS = 4, BANK_DEPTH_EXT = 1024 */ +} + +const char * +roc_npc_profile_name_get(struct roc_npc *roc_npc) +{ + struct npc *npc = roc_npc_to_npc_priv(roc_npc); + + return (char *)npc->profile_name; +} + +int +roc_npc_init(struct roc_npc *roc_npc) +{ + uint8_t *mem = NULL, *nix_mem = NULL, *npc_mem = NULL; + struct nix *nix = roc_nix_to_nix_priv(roc_npc->roc_nix); + struct npc *npc = roc_npc_to_npc_priv(roc_npc); + uint32_t bmap_sz; + int rc = 0, idx; + size_t sz; + + PLT_STATIC_ASSERT(sizeof(struct npc) <= ROC_NPC_MEM_SZ); + + memset(npc, 0, sizeof(*npc)); + npc->mbox = (&nix->dev)->mbox; + roc_npc->channel = nix->rx_chan_base; + roc_npc->pf_func = (&nix->dev)->pf_func; + npc->channel = roc_npc->channel; + npc->pf_func = roc_npc->pf_func; + npc->flow_max_priority = roc_npc->flow_max_priority; + npc->switch_header_type = roc_npc->switch_header_type; + npc->flow_prealloc_size = roc_npc->flow_prealloc_size; + + if (npc->mbox == NULL) + return NPC_ERR_PARAM; + + rc = npc_mcam_fetch_kex_cfg(npc); + if (rc) + goto done; + + roc_npc->kex_capability = npc_get_kex_capability(npc); + roc_npc->rx_parse_nibble = npc->keyx_supp_nmask[NPC_MCAM_RX]; + + npc->mark_actions = 0; + + npc->mcam_entries = npc_mcam_tot_entries() >> npc->keyw[NPC_MCAM_RX]; + + /* Free, free_rev, live and live_rev entries */ + bmap_sz = plt_bitmap_get_memory_footprint(npc->mcam_entries); + mem = plt_zmalloc(4 * bmap_sz * npc->flow_max_priority, 0); + if (mem == NULL) { + plt_err("Bmap alloc failed"); + rc = NPC_ERR_NO_MEM; + return rc; + } + + sz = npc->flow_max_priority * sizeof(struct npc_mcam_ents_info); + npc->flow_entry_info = plt_zmalloc(sz, 0); + if (npc->flow_entry_info == NULL) { + plt_err("flow_entry_info alloc failed"); + rc = NPC_ERR_NO_MEM; + goto done; + } + + sz = npc->flow_max_priority * sizeof(struct plt_bitmap *); + npc->free_entries = plt_zmalloc(sz, 0); + if (npc->free_entries == NULL) { + plt_err("free_entries alloc failed"); + rc = NPC_ERR_NO_MEM; + goto done; + } + + sz = npc->flow_max_priority * sizeof(struct plt_bitmap *); + npc->free_entries_rev = plt_zmalloc(sz, 0); + if (npc->free_entries_rev == NULL) { + plt_err("free_entries_rev alloc failed"); + rc = NPC_ERR_NO_MEM; + goto done; + } + + sz = npc->flow_max_priority * sizeof(struct plt_bitmap *); + npc->live_entries = plt_zmalloc(sz, 0); + if (npc->live_entries == NULL) { + plt_err("live_entries alloc failed"); + rc = NPC_ERR_NO_MEM; + goto done; + } + + sz = npc->flow_max_priority * sizeof(struct plt_bitmap *); + npc->live_entries_rev = plt_zmalloc(sz, 0); + if (npc->live_entries_rev == NULL) { + plt_err("live_entries_rev alloc failed"); + rc = NPC_ERR_NO_MEM; + goto done; + } + + sz = npc->flow_max_priority * sizeof(struct npc_flow_list); + npc->flow_list = plt_zmalloc(sz, 0); + if (npc->flow_list == NULL) { + plt_err("flow_list alloc failed"); + rc = NPC_ERR_NO_MEM; + goto done; + } + + npc_mem = mem; + for (idx = 0; idx < npc->flow_max_priority; idx++) { + TAILQ_INIT(&npc->flow_list[idx]); + + npc->free_entries[idx] = + plt_bitmap_init(npc->mcam_entries, mem, bmap_sz); + mem += bmap_sz; + + npc->free_entries_rev[idx] = + plt_bitmap_init(npc->mcam_entries, mem, bmap_sz); + mem += bmap_sz; + + npc->live_entries[idx] = + plt_bitmap_init(npc->mcam_entries, mem, bmap_sz); + mem += bmap_sz; + + npc->live_entries_rev[idx] = + plt_bitmap_init(npc->mcam_entries, mem, bmap_sz); + mem += bmap_sz; + + npc->flow_entry_info[idx].free_ent = 0; + npc->flow_entry_info[idx].live_ent = 0; + npc->flow_entry_info[idx].max_id = 0; + npc->flow_entry_info[idx].min_id = ~(0); + } + + npc->rss_grps = NPC_RSS_GRPS; + + bmap_sz = plt_bitmap_get_memory_footprint(npc->rss_grps); + nix_mem = plt_zmalloc(bmap_sz, 0); + if (nix_mem == NULL) { + plt_err("Bmap alloc failed"); + rc = NPC_ERR_NO_MEM; + goto done; + } + + npc->rss_grp_entries = plt_bitmap_init(npc->rss_grps, nix_mem, bmap_sz); + + if (!npc->rss_grp_entries) { + plt_err("bitmap init failed"); + rc = NPC_ERR_NO_MEM; + goto done; + } + + /* Group 0 will be used for RSS, + * 1 -7 will be used for npc_flow RSS action + */ + plt_bitmap_set(npc->rss_grp_entries, 0); + + return rc; + +done: + if (npc->flow_list) + plt_free(npc->flow_list); + if (npc->live_entries_rev) + plt_free(npc->live_entries_rev); + if (npc->live_entries) + plt_free(npc->live_entries); + if (npc->free_entries_rev) + plt_free(npc->free_entries_rev); + if (npc->free_entries) + plt_free(npc->free_entries); + if (npc->flow_entry_info) + plt_free(npc->flow_entry_info); + if (npc_mem) + plt_free(npc_mem); + return rc; +} + +int +roc_npc_fini(struct roc_npc *roc_npc) +{ + struct npc *npc = roc_npc_to_npc_priv(roc_npc); + int rc; + + rc = npc_flow_free_all_resources(npc); + if (rc) { + plt_err("Error when deleting NPC MCAM entries, counters"); + return rc; + } + + if (npc->flow_list) { + plt_free(npc->flow_list); + npc->flow_list = NULL; + } + + if (npc->live_entries_rev) { + plt_free(npc->live_entries_rev); + npc->live_entries_rev = NULL; + } + + if (npc->live_entries) { + plt_free(npc->live_entries); + npc->live_entries = NULL; + } + + if (npc->free_entries_rev) { + plt_free(npc->free_entries_rev); + npc->free_entries_rev = NULL; + } + + if (npc->free_entries) { + plt_free(npc->free_entries); + npc->free_entries = NULL; + } + + if (npc->flow_entry_info) { + plt_free(npc->flow_entry_info); + npc->flow_entry_info = NULL; + } + + return 0; +} + +static int +npc_parse_actions(struct npc *npc, const struct roc_npc_attr *attr, + const struct roc_npc_action actions[], + struct roc_npc_flow *flow) +{ + const struct roc_npc_action_mark *act_mark; + const struct roc_npc_action_queue *act_q; + const struct roc_npc_action_vf *vf_act; + int sel_act, req_act = 0; + uint16_t pf_func, vf_id; + int errcode = 0; + int mark = 0; + int rq = 0; + + /* Initialize actions */ + flow->ctr_id = NPC_COUNTER_NONE; + pf_func = npc->pf_func; + + for (; actions->type != ROC_NPC_ACTION_TYPE_END; actions++) { + switch (actions->type) { + case ROC_NPC_ACTION_TYPE_VOID: + break; + case ROC_NPC_ACTION_TYPE_MARK: + act_mark = (const struct roc_npc_action_mark *) + actions->conf; + if (act_mark->id > (NPC_FLOW_FLAG_VAL - 2)) { + plt_err("mark value must be < 0xfffe"); + goto err_exit; + } + mark = act_mark->id + 1; + req_act |= ROC_NPC_ACTION_TYPE_MARK; + npc->mark_actions += 1; + break; + + case ROC_NPC_ACTION_TYPE_FLAG: + mark = NPC_FLOW_FLAG_VAL; + req_act |= ROC_NPC_ACTION_TYPE_FLAG; + npc->mark_actions += 1; + break; + + case ROC_NPC_ACTION_TYPE_COUNT: + /* Indicates, need a counter */ + flow->ctr_id = 1; + req_act |= ROC_NPC_ACTION_TYPE_COUNT; + break; + + case ROC_NPC_ACTION_TYPE_DROP: + req_act |= ROC_NPC_ACTION_TYPE_DROP; + break; + + case ROC_NPC_ACTION_TYPE_PF: + req_act |= ROC_NPC_ACTION_TYPE_PF; + pf_func &= (0xfc00); + break; + + case ROC_NPC_ACTION_TYPE_VF: + vf_act = + (const struct roc_npc_action_vf *)actions->conf; + req_act |= ROC_NPC_ACTION_TYPE_VF; + vf_id = vf_act->id & RVU_PFVF_FUNC_MASK; + pf_func &= (0xfc00); + pf_func = (pf_func | (vf_id + 1)); + break; + + case ROC_NPC_ACTION_TYPE_QUEUE: + act_q = (const struct roc_npc_action_queue *) + actions->conf; + rq = act_q->index; + req_act |= ROC_NPC_ACTION_TYPE_QUEUE; + break; + + case ROC_NPC_ACTION_TYPE_RSS: + req_act |= ROC_NPC_ACTION_TYPE_RSS; + break; + + case ROC_NPC_ACTION_TYPE_SEC: + /* Assumes user has already configured security + * session for this flow. Associated conf is + * opaque. When security is implemented, + * we need to verify that for specified security + * session: + * action_type == + * NPC_SECURITY_ACTION_TYPE_INLINE_PROTOCOL && + * session_protocol == + * NPC_SECURITY_PROTOCOL_IPSEC + * + * RSS is not supported with inline ipsec. Get the + * rq from associated conf, or make + * ROC_NPC_ACTION_TYPE_QUEUE compulsory with this + * action. + * Currently, rq = 0 is assumed. + */ + req_act |= ROC_NPC_ACTION_TYPE_SEC; + rq = 0; + break; + default: + errcode = NPC_ERR_ACTION_NOTSUP; + goto err_exit; + } + } + + /* Check if actions specified are compatible */ + if (attr->egress) { + /* Only DROP/COUNT is supported */ + if (!(req_act & ROC_NPC_ACTION_TYPE_DROP)) { + errcode = NPC_ERR_ACTION_NOTSUP; + goto err_exit; + } else if (req_act & ~(ROC_NPC_ACTION_TYPE_DROP | + ROC_NPC_ACTION_TYPE_COUNT)) { + errcode = NPC_ERR_ACTION_NOTSUP; + goto err_exit; + } + flow->npc_action = NIX_TX_ACTIONOP_DROP; + goto set_pf_func; + } + + /* We have already verified the attr, this is ingress. + * - Exactly one terminating action is supported + * - Exactly one of MARK or FLAG is supported + * - If terminating action is DROP, only count is valid. + */ + sel_act = req_act & NPC_ACTION_TERM; + if ((sel_act & (sel_act - 1)) != 0) { + errcode = NPC_ERR_ACTION_NOTSUP; + goto err_exit; + } + + if (req_act & ROC_NPC_ACTION_TYPE_DROP) { + sel_act = req_act & ~ROC_NPC_ACTION_TYPE_COUNT; + if ((sel_act & (sel_act - 1)) != 0) { + errcode = NPC_ERR_ACTION_NOTSUP; + goto err_exit; + } + } + + if ((req_act & (ROC_NPC_ACTION_TYPE_FLAG | ROC_NPC_ACTION_TYPE_MARK)) == + (ROC_NPC_ACTION_TYPE_FLAG | ROC_NPC_ACTION_TYPE_MARK)) { + errcode = NPC_ERR_ACTION_NOTSUP; + goto err_exit; + } + + /* Set NIX_RX_ACTIONOP */ + if (req_act & (ROC_NPC_ACTION_TYPE_PF | ROC_NPC_ACTION_TYPE_VF)) { + flow->npc_action = NIX_RX_ACTIONOP_UCAST; + if (req_act & ROC_NPC_ACTION_TYPE_QUEUE) + flow->npc_action |= (uint64_t)rq << 20; + } else if (req_act & ROC_NPC_ACTION_TYPE_DROP) { + flow->npc_action = NIX_RX_ACTIONOP_DROP; + } else if (req_act & ROC_NPC_ACTION_TYPE_QUEUE) { + flow->npc_action = NIX_RX_ACTIONOP_UCAST; + flow->npc_action |= (uint64_t)rq << 20; + } else if (req_act & ROC_NPC_ACTION_TYPE_RSS) { + flow->npc_action = NIX_RX_ACTIONOP_UCAST; + } else if (req_act & ROC_NPC_ACTION_TYPE_SEC) { + flow->npc_action = NIX_RX_ACTIONOP_UCAST_IPSEC; + flow->npc_action |= (uint64_t)rq << 20; + } else if (req_act & + (ROC_NPC_ACTION_TYPE_FLAG | ROC_NPC_ACTION_TYPE_MARK)) { + flow->npc_action = NIX_RX_ACTIONOP_UCAST; + } else if (req_act & ROC_NPC_ACTION_TYPE_COUNT) { + /* Keep ROC_NPC_ACTION_TYPE_COUNT_ACT always at the end + * This is default action, when user specify only + * COUNT ACTION + */ + flow->npc_action = NIX_RX_ACTIONOP_UCAST; + } else { + /* Should never reach here */ + errcode = NPC_ERR_ACTION_NOTSUP; + goto err_exit; + } + + if (mark) + flow->npc_action |= (uint64_t)mark << 40; + +set_pf_func: + /* Ideally AF must ensure that correct pf_func is set */ + flow->npc_action |= (uint64_t)pf_func << 4; + + return 0; + +err_exit: + return errcode; +} + +typedef int (*npc_parse_stage_func_t)(struct npc_parse_state *pst); + +static int +npc_parse_pattern(struct npc *npc, const struct roc_npc_item_info pattern[], + struct roc_npc_flow *flow, struct npc_parse_state *pst) +{ + npc_parse_stage_func_t parse_stage_funcs[] = { + npc_parse_meta_items, npc_parse_cpt_hdr, npc_parse_higig2_hdr, + npc_parse_la, npc_parse_lb, npc_parse_lc, + npc_parse_ld, npc_parse_le, npc_parse_lf, + npc_parse_lg, npc_parse_lh, + }; + uint8_t layer = 0; + int key_offset; + int rc; + + if (pattern == NULL) + return NPC_ERR_PARAM; + + memset(pst, 0, sizeof(*pst)); + pst->npc = npc; + pst->flow = flow; + + /* Use integral byte offset */ + key_offset = pst->npc->keyx_len[flow->nix_intf]; + key_offset = (key_offset + 7) / 8; + + /* Location where LDATA would begin */ + pst->mcam_data = (uint8_t *)flow->mcam_data; + pst->mcam_mask = (uint8_t *)flow->mcam_mask; + + while (pattern->type != ROC_NPC_ITEM_TYPE_END && + layer < PLT_DIM(parse_stage_funcs)) { + /* Skip place-holders */ + pattern = npc_parse_skip_void_and_any_items(pattern); + + pst->pattern = pattern; + rc = parse_stage_funcs[layer](pst); + if (rc != 0) + return rc; + + layer++; + + /* + * Parse stage function sets pst->pattern to + * 1 past the last item it consumed. + */ + pattern = pst->pattern; + + if (pst->terminate) + break; + } + + /* Skip trailing place-holders */ + pattern = npc_parse_skip_void_and_any_items(pattern); + + /* Are there more items than what we can handle? */ + if (pattern->type != ROC_NPC_ITEM_TYPE_END) + return NPC_ERR_PATTERN_NOTSUP; + + return 0; +} + +static int +npc_parse_attr(struct npc *npc, const struct roc_npc_attr *attr, + struct roc_npc_flow *flow) +{ + if (attr == NULL) + return NPC_ERR_PARAM; + else if (attr->priority >= npc->flow_max_priority) + return NPC_ERR_PARAM; + else if ((!attr->egress && !attr->ingress) || + (attr->egress && attr->ingress)) + return NPC_ERR_PARAM; + + if (attr->ingress) + flow->nix_intf = ROC_NPC_INTF_RX; + else + flow->nix_intf = ROC_NPC_INTF_TX; + + flow->priority = attr->priority; + return 0; +} + +static int +npc_parse_rule(struct npc *npc, const struct roc_npc_attr *attr, + const struct roc_npc_item_info pattern[], + const struct roc_npc_action actions[], struct roc_npc_flow *flow, + struct npc_parse_state *pst) +{ + int err; + + /* Check attr */ + err = npc_parse_attr(npc, attr, flow); + if (err) + return err; + + /* Check pattern */ + err = npc_parse_pattern(npc, pattern, flow, pst); + if (err) + return err; + + /* Check action */ + err = npc_parse_actions(npc, attr, actions, flow); + if (err) + return err; + return 0; +} + +int +roc_npc_flow_parse(struct roc_npc *roc_npc, const struct roc_npc_attr *attr, + const struct roc_npc_item_info pattern[], + const struct roc_npc_action actions[], + struct roc_npc_flow *flow) +{ + struct npc *npc = roc_npc_to_npc_priv(roc_npc); + struct npc_parse_state parse_state = {0}; + int rc; + + rc = npc_parse_rule(npc, attr, pattern, actions, flow, &parse_state); + if (rc) + return rc; + + parse_state.is_vf = !roc_nix_is_pf(roc_npc->roc_nix); + + return npc_program_mcam(npc, &parse_state, 0); +} + +struct roc_npc_flow * +roc_npc_flow_create(struct roc_npc *roc_npc, const struct roc_npc_attr *attr, + const struct roc_npc_item_info pattern[], + const struct roc_npc_action actions[], int *errcode) +{ + struct npc *npc = roc_npc_to_npc_priv(roc_npc); + struct roc_npc_flow *flow, *flow_iter; + struct npc_parse_state parse_state; + struct npc_flow_list *list; + int rc; + + flow = plt_zmalloc(sizeof(*flow), 0); + if (flow == NULL) { + *errcode = NPC_ERR_NO_MEM; + return NULL; + } + memset(flow, 0, sizeof(*flow)); + + rc = npc_parse_rule(npc, attr, pattern, actions, flow, &parse_state); + if (rc != 0) { + *errcode = rc; + goto err_exit; + } + + parse_state.is_vf = !roc_nix_is_pf(roc_npc->roc_nix); + + rc = npc_program_mcam(npc, &parse_state, 1); + if (rc != 0) { + *errcode = rc; + goto err_exit; + } + + list = &npc->flow_list[flow->priority]; + /* List in ascending order of mcam entries */ + TAILQ_FOREACH(flow_iter, list, next) { + if (flow_iter->mcam_id > flow->mcam_id) { + TAILQ_INSERT_BEFORE(flow_iter, flow, next); + return flow; + } + } + + TAILQ_INSERT_TAIL(list, flow, next); + return flow; + +err_exit: + plt_free(flow); + return NULL; +} + +int +roc_npc_flow_destroy(struct roc_npc *roc_npc, struct roc_npc_flow *flow) +{ + struct npc *npc = roc_npc_to_npc_priv(roc_npc); + struct plt_bitmap *bmap; + uint16_t match_id; + int rc; + + match_id = (flow->npc_action >> NPC_RX_ACT_MATCH_OFFSET) & + NPC_RX_ACT_MATCH_MASK; + + if (match_id && match_id < NPC_ACTION_FLAG_DEFAULT) { + if (npc->mark_actions == 0) + return NPC_ERR_PARAM; + } + + rc = npc_mcam_free_entry(npc, flow->mcam_id); + if (rc != 0) + return rc; + + TAILQ_REMOVE(&npc->flow_list[flow->priority], flow, next); + + bmap = npc->live_entries[flow->priority]; + plt_bitmap_clear(bmap, flow->mcam_id); + + plt_free(flow); + return 0; +} diff --git a/drivers/common/cnxk/roc_npc.h b/drivers/common/cnxk/roc_npc.h index c841240724..996739e802 100644 --- a/drivers/common/cnxk/roc_npc.h +++ b/drivers/common/cnxk/roc_npc.h @@ -126,4 +126,44 @@ struct roc_npc { uint8_t reserved[ROC_NPC_MEM_SZ]; } __plt_cache_aligned; +int __roc_api roc_npc_init(struct roc_npc *roc_npc); +int __roc_api roc_npc_fini(struct roc_npc *roc_npc); +const char *__roc_api roc_npc_profile_name_get(struct roc_npc *roc_npc); + +struct roc_npc_flow *__roc_api +roc_npc_flow_create(struct roc_npc *roc_npc, const struct roc_npc_attr *attr, + const struct roc_npc_item_info pattern[], + const struct roc_npc_action actions[], int *errcode); +int __roc_api roc_npc_flow_destroy(struct roc_npc *roc_npc, + struct roc_npc_flow *flow); +int __roc_api roc_npc_mcam_free_entry(struct roc_npc *roc_npc, uint32_t entry); +int __roc_api roc_npc_mcam_alloc_entry(struct roc_npc *roc_npc, + struct roc_npc_flow *mcam, + struct roc_npc_flow *ref_mcam, int prio, + int *resp_count); +int __roc_api roc_npc_mcam_alloc_entries(struct roc_npc *roc_npc, int ref_entry, + int *alloc_entry, int req_count, + int priority, int *resp_count); +int __roc_api roc_npc_mcam_ena_dis_entry(struct roc_npc *roc_npc, + struct roc_npc_flow *mcam, + bool enable); +int __roc_api roc_npc_mcam_write_entry(struct roc_npc *roc_npc, + struct roc_npc_flow *mcam); +int __roc_api roc_npc_flow_parse(struct roc_npc *roc_npc, + const struct roc_npc_attr *attr, + const struct roc_npc_item_info pattern[], + const struct roc_npc_action actions[], + struct roc_npc_flow *flow); +int __roc_api roc_npc_get_low_priority_mcam(struct roc_npc *roc_npc); + +int __roc_api roc_npc_mcam_free_counter(struct roc_npc *roc_npc, + uint16_t ctr_id); + +int __roc_api roc_npc_mcam_read_counter(struct roc_npc *roc_npc, + uint32_t ctr_id, uint64_t *count); +int __roc_api roc_npc_mcam_clear_counter(struct roc_npc *roc_npc, + uint32_t ctr_id); + +int __roc_api roc_npc_mcam_free_all_resources(struct roc_npc *roc_npc); + #endif /* _ROC_NPC_H_ */ diff --git a/drivers/common/cnxk/version.map b/drivers/common/cnxk/version.map index f961a234b8..ed82b56caa 100644 --- a/drivers/common/cnxk/version.map +++ b/drivers/common/cnxk/version.map @@ -154,6 +154,22 @@ INTERNAL { roc_npa_pool_destroy; roc_npa_pool_op_pc_reset; roc_npa_pool_range_update_check; + roc_npc_fini; + roc_npc_flow_create; + roc_npc_flow_destroy; + roc_npc_flow_parse; + roc_npc_get_low_priority_mcam; + roc_npc_init; + roc_npc_mcam_alloc_entries; + roc_npc_mcam_alloc_entry; + roc_npc_mcam_clear_counter; + roc_npc_mcam_ena_dis_entry; + roc_npc_mcam_free_all_resources; + roc_npc_mcam_free_counter; + roc_npc_mcam_free_entry; + roc_npc_mcam_write_entry; + roc_npc_mcam_read_counter; + roc_npc_profile_name_get; roc_plt_init; roc_plt_init_cb_register; -- 2.20.1