X-Git-Url: http://git.droids-corp.org/?a=blobdiff_plain;f=drivers%2Fcommon%2Fcnxk%2Froc_npc.c;h=e3961bfbc6a75f2e27879dd4aad37ca5952a9104;hb=da718c1919bd49faa83ded38b0549500c7e77f91;hp=e6a503648319568ec1a2da2f55fa037fe08e303c;hpb=0c22452d475e28e76bafefa6dcd97868a4c772d4;p=dpdk.git diff --git a/drivers/common/cnxk/roc_npc.c b/drivers/common/cnxk/roc_npc.c index e6a5036483..e3961bfbc6 100644 --- a/drivers/common/cnxk/roc_npc.c +++ b/drivers/common/cnxk/roc_npc.c @@ -5,6 +5,23 @@ #include "roc_api.h" #include "roc_priv.h" +int +roc_npc_vtag_actions_get(struct roc_npc *roc_npc) +{ + struct npc *npc = roc_npc_to_npc_priv(roc_npc); + + return npc->vtag_strip_actions; +} + +int +roc_npc_vtag_actions_sub_return(struct roc_npc *roc_npc, uint32_t count) +{ + struct npc *npc = roc_npc_to_npc_priv(roc_npc); + + npc->vtag_strip_actions -= count; + return npc->vtag_strip_actions; +} + int roc_npc_mcam_free_counter(struct roc_npc *roc_npc, uint16_t ctr_id) { @@ -91,6 +108,8 @@ roc_npc_get_low_priority_mcam(struct roc_npc *roc_npc) if (roc_model_is_cn10k()) return (npc->mcam_entries - NPC_MCAME_RESVD_10XX - 1); + else if (roc_model_is_cn98xx()) + return (npc->mcam_entries - NPC_MCAME_RESVD_98XX - 1); else return (npc->mcam_entries - NPC_MCAME_RESVD_9XXX - 1); } @@ -101,7 +120,7 @@ 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()) + if (roc_model_is_cn10k() || roc_model_is_cn98xx()) return 16 * 1024; /* MCAM_BANKS = 4, BANK_DEPTH_EXT = 4096 */ else return 4 * 1024; /* MCAM_BANKS = 4, BANK_DEPTH_EXT = 1024 */ @@ -160,46 +179,6 @@ roc_npc_init(struct roc_npc *roc_npc) 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) { @@ -208,30 +187,18 @@ roc_npc_init(struct roc_npc *roc_npc) goto done; } + sz = npc->flow_max_priority * sizeof(struct npc_prio_flow_list_head); + npc->prio_flow_list = plt_zmalloc(sz, 0); + if (npc->prio_flow_list == NULL) { + plt_err("prio_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); + TAILQ_INIT(&npc->prio_flow_list[idx]); } npc->rss_grps = NPC_RSS_GRPS; @@ -262,16 +229,8 @@ roc_npc_init(struct roc_npc *roc_npc) 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->prio_flow_list) + plt_free(npc->prio_flow_list); if (npc_mem) plt_free(npc_mem); return rc; @@ -294,42 +253,52 @@ roc_npc_fini(struct roc_npc *roc_npc) npc->flow_list = NULL; } - if (npc->live_entries_rev) { - plt_free(npc->live_entries_rev); - npc->live_entries_rev = NULL; + if (npc->prio_flow_list) { + plt_free(npc->prio_flow_list); + npc->prio_flow_list = NULL; } - if (npc->live_entries) { - plt_free(npc->live_entries); - npc->live_entries = NULL; - } + return 0; +} - if (npc->free_entries_rev) { - plt_free(npc->free_entries_rev); - npc->free_entries_rev = NULL; +int +roc_npc_validate_portid_action(struct roc_npc *roc_npc_src, + struct roc_npc *roc_npc_dst) +{ + struct roc_nix *roc_nix_src = roc_npc_src->roc_nix; + struct nix *nix_src = roc_nix_to_nix_priv(roc_nix_src); + struct roc_nix *roc_nix_dst = roc_npc_dst->roc_nix; + struct nix *nix_dst = roc_nix_to_nix_priv(roc_nix_dst); + + if (roc_nix_is_pf(roc_npc_dst->roc_nix)) { + plt_err("Output port should be VF"); + return -EINVAL; } - if (npc->free_entries) { - plt_free(npc->free_entries); - npc->free_entries = NULL; + if (nix_dst->dev.vf >= nix_src->dev.maxvf) { + plt_err("Invalid VF for output port"); + return -EINVAL; } - if (npc->flow_entry_info) { - plt_free(npc->flow_entry_info); - npc->flow_entry_info = NULL; + if (nix_src->dev.pf != nix_dst->dev.pf) { + plt_err("Output port should be VF of ingress PF"); + return -EINVAL; } - return 0; } static int -npc_parse_actions(struct npc *npc, const struct roc_npc_attr *attr, +npc_parse_actions(struct roc_npc *roc_npc, const struct roc_npc_attr *attr, const struct roc_npc_action actions[], struct roc_npc_flow *flow) { + const struct roc_npc_action_port_id *act_portid; + struct npc *npc = roc_npc_to_npc_priv(roc_npc); const struct roc_npc_action_mark *act_mark; + const struct roc_npc_action_meter *act_mtr; const struct roc_npc_action_queue *act_q; const struct roc_npc_action_vf *vf_act; + bool vlan_insert_action = false; int sel_act, req_act = 0; uint16_t pf_func, vf_id; int errcode = 0; @@ -338,6 +307,7 @@ npc_parse_actions(struct npc *npc, const struct roc_npc_attr *attr, /* Initialize actions */ flow->ctr_id = NPC_COUNTER_NONE; + flow->mtr_id = ROC_NIX_MTR_ID_INVALID; pf_func = npc->pf_func; for (; actions->type != ROC_NPC_ACTION_TYPE_END; actions++) { @@ -386,6 +356,14 @@ npc_parse_actions(struct npc *npc, const struct roc_npc_attr *attr, pf_func = (pf_func | (vf_id + 1)); break; + case ROC_NPC_ACTION_TYPE_PORT_ID: + act_portid = (const struct roc_npc_action_port_id *) + actions->conf; + pf_func &= (0xfc00); + pf_func = (pf_func | (act_portid->id + 1)); + req_act |= ROC_NPC_ACTION_TYPE_VF; + break; + case ROC_NPC_ACTION_TYPE_QUEUE: act_q = (const struct roc_npc_action_queue *) actions->conf; @@ -407,15 +385,34 @@ npc_parse_actions(struct npc *npc, const struct roc_npc_attr *attr, * 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; + + /* Special processing when with inline device */ + if (roc_nix_inb_is_with_inl_dev(roc_npc->roc_nix) && + roc_nix_inl_dev_is_probed()) { + rq = 0; + pf_func = nix_inl_dev_pffunc_get(); + } + break; + case ROC_NPC_ACTION_TYPE_VLAN_STRIP: + req_act |= ROC_NPC_ACTION_TYPE_VLAN_STRIP; + break; + case ROC_NPC_ACTION_TYPE_VLAN_INSERT: + req_act |= ROC_NPC_ACTION_TYPE_VLAN_INSERT; + break; + case ROC_NPC_ACTION_TYPE_VLAN_ETHTYPE_INSERT: + req_act |= ROC_NPC_ACTION_TYPE_VLAN_ETHTYPE_INSERT; + break; + case ROC_NPC_ACTION_TYPE_VLAN_PCP_INSERT: + req_act |= ROC_NPC_ACTION_TYPE_VLAN_PCP_INSERT; + break; + case ROC_NPC_ACTION_TYPE_METER: + act_mtr = (const struct roc_npc_action_meter *) + actions->conf; + flow->mtr_id = act_mtr->mtr_id; + req_act |= ROC_NPC_ACTION_TYPE_METER; break; default: errcode = NPC_ERR_ACTION_NOTSUP; @@ -423,19 +420,68 @@ npc_parse_actions(struct npc *npc, const struct roc_npc_attr *attr, } } + if (req_act & (ROC_NPC_ACTION_TYPE_VLAN_INSERT | + ROC_NPC_ACTION_TYPE_VLAN_ETHTYPE_INSERT | + ROC_NPC_ACTION_TYPE_VLAN_PCP_INSERT)) + vlan_insert_action = true; + + if ((req_act & (ROC_NPC_ACTION_TYPE_VLAN_INSERT | + ROC_NPC_ACTION_TYPE_VLAN_ETHTYPE_INSERT | + ROC_NPC_ACTION_TYPE_VLAN_PCP_INSERT)) == + ROC_NPC_ACTION_TYPE_VLAN_PCP_INSERT) { + plt_err("PCP insert action can't be supported alone"); + errcode = NPC_ERR_ACTION_NOTSUP; + goto err_exit; + } + + /* Both STRIP and INSERT actions are not supported */ + if (vlan_insert_action && (req_act & ROC_NPC_ACTION_TYPE_VLAN_STRIP)) { + 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)) { + if (req_act & ROC_NPC_ACTION_TYPE_VLAN_STRIP) { + plt_err("VLAN pop action is not supported on Egress"); errcode = NPC_ERR_ACTION_NOTSUP; goto err_exit; - } else if (req_act & ~(ROC_NPC_ACTION_TYPE_DROP | - ROC_NPC_ACTION_TYPE_COUNT)) { + } + + if (req_act & + ~(ROC_NPC_ACTION_TYPE_VLAN_INSERT | + ROC_NPC_ACTION_TYPE_VLAN_ETHTYPE_INSERT | + ROC_NPC_ACTION_TYPE_VLAN_PCP_INSERT | + ROC_NPC_ACTION_TYPE_DROP | ROC_NPC_ACTION_TYPE_COUNT)) { + plt_err("Only VLAN insert, drop, count supported on Egress"); errcode = NPC_ERR_ACTION_NOTSUP; goto err_exit; } - flow->npc_action = NIX_TX_ACTIONOP_DROP; + + if (vlan_insert_action && + (req_act & ROC_NPC_ACTION_TYPE_DROP)) { + plt_err("Both VLAN insert and drop actions cannot be supported"); + errcode = NPC_ERR_ACTION_NOTSUP; + goto err_exit; + } + + if (req_act & ROC_NPC_ACTION_TYPE_DROP) { + flow->npc_action = NIX_TX_ACTIONOP_DROP; + } else if ((req_act & ROC_NPC_ACTION_TYPE_COUNT) || + vlan_insert_action) { + flow->npc_action = NIX_TX_ACTIONOP_UCAST_DEFAULT; + } else { + plt_err("Unsupported action for egress"); + errcode = NPC_ERR_ACTION_NOTSUP; + goto err_exit; + } + goto set_pf_func; + } else { + if (vlan_insert_action) { + errcode = NPC_ERR_ACTION_NOTSUP; + goto err_exit; + } } /* We have already verified the attr, this is ingress. @@ -463,8 +509,15 @@ npc_parse_actions(struct npc *npc, const struct roc_npc_attr *attr, goto err_exit; } + if (req_act & ROC_NPC_ACTION_TYPE_VLAN_STRIP) + npc->vtag_strip_actions++; + /* Set NIX_RX_ACTIONOP */ - if (req_act & (ROC_NPC_ACTION_TYPE_PF | ROC_NPC_ACTION_TYPE_VF)) { + if (req_act == ROC_NPC_ACTION_TYPE_VLAN_STRIP) { + /* Only VLAN action is provided */ + flow->npc_action = NIX_RX_ACTIONOP_UCAST; + } else 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; @@ -513,10 +566,10 @@ 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, + npc_parse_meta_items, npc_parse_pre_l2, 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; @@ -591,11 +644,12 @@ npc_parse_attr(struct npc *npc, const struct roc_npc_attr *attr, } static int -npc_parse_rule(struct npc *npc, const struct roc_npc_attr *attr, +npc_parse_rule(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_parse_state *pst) { + struct npc *npc = roc_npc_to_npc_priv(roc_npc); int err; /* Check attr */ @@ -609,7 +663,7 @@ npc_parse_rule(struct npc *npc, const struct roc_npc_attr *attr, return err; /* Check action */ - err = npc_parse_actions(npc, attr, actions, flow); + err = npc_parse_actions(roc_npc, attr, actions, flow); if (err) return err; return 0; @@ -625,7 +679,8 @@ roc_npc_flow_parse(struct roc_npc *roc_npc, const struct roc_npc_attr *attr, struct npc_parse_state parse_state = {0}; int rc; - rc = npc_parse_rule(npc, attr, pattern, actions, flow, &parse_state); + rc = npc_parse_rule(roc_npc, attr, pattern, actions, flow, + &parse_state); if (rc) return rc; @@ -774,6 +829,317 @@ roc_npc_mark_actions_sub_return(struct roc_npc *roc_npc, uint32_t count) return npc->mark_actions; } +static int +npc_vtag_cfg_delete(struct roc_npc *roc_npc, struct roc_npc_flow *flow) +{ + struct roc_nix *roc_nix = roc_npc->roc_nix; + struct nix_vtag_config *vtag_cfg; + struct nix_vtag_config_rsp *rsp; + struct mbox *mbox; + struct nix *nix; + int rc = 0; + + union { + uint64_t reg; + struct nix_tx_vtag_action_s act; + } tx_vtag_action; + + nix = roc_nix_to_nix_priv(roc_nix); + mbox = (&nix->dev)->mbox; + + tx_vtag_action.reg = flow->vtag_action; + vtag_cfg = mbox_alloc_msg_nix_vtag_cfg(mbox); + + if (vtag_cfg == NULL) + return -ENOSPC; + + vtag_cfg->cfg_type = VTAG_TX; + vtag_cfg->vtag_size = NIX_VTAGSIZE_T4; + vtag_cfg->tx.vtag0_idx = tx_vtag_action.act.vtag0_def; + vtag_cfg->tx.free_vtag0 = true; + + if (flow->vtag_insert_count == 2) { + vtag_cfg->tx.vtag1_idx = tx_vtag_action.act.vtag1_def; + vtag_cfg->tx.free_vtag1 = true; + } + + rc = mbox_process_msg(mbox, (void *)&rsp); + if (rc) + return rc; + + return 0; +} + +static int +npc_vtag_insert_action_parse(const struct roc_npc_action actions[], + struct roc_npc_flow *flow, + struct npc_action_vtag_info *vlan_info, + int *parsed_cnt) +{ + bool vlan_id_found = false, ethtype_found = false, pcp_found = false; + int count = 0; + + *parsed_cnt = 0; + + /* This function parses parameters of one VLAN. When a parameter is + * found repeated, it treats it as the end of first VLAN's parameters + * and returns. The caller calls again to parse the parameters of the + * second VLAN. + */ + + for (; count < NPC_ACTION_MAX_VLAN_PARAMS; count++, actions++) { + if (actions->type == ROC_NPC_ACTION_TYPE_VLAN_INSERT) { + if (vlan_id_found) + return 0; + + const struct roc_npc_action_of_set_vlan_vid *vtag = + (const struct roc_npc_action_of_set_vlan_vid *) + actions->conf; + + vlan_info->vlan_id = plt_be_to_cpu_16(vtag->vlan_vid); + + if (vlan_info->vlan_id > 0xfff) { + plt_err("Invalid vlan_id for set vlan action"); + return -EINVAL; + } + + flow->vtag_insert_enabled = true; + (*parsed_cnt)++; + vlan_id_found = true; + } else if (actions->type == + ROC_NPC_ACTION_TYPE_VLAN_ETHTYPE_INSERT) { + if (ethtype_found) + return 0; + + const struct roc_npc_action_of_push_vlan *ethtype = + (const struct roc_npc_action_of_push_vlan *) + actions->conf; + vlan_info->vlan_ethtype = + plt_be_to_cpu_16(ethtype->ethertype); + if (vlan_info->vlan_ethtype != ROC_ETHER_TYPE_VLAN && + vlan_info->vlan_ethtype != ROC_ETHER_TYPE_QINQ) { + plt_err("Invalid ethtype specified for push" + " vlan action"); + return -EINVAL; + } + flow->vtag_insert_enabled = true; + (*parsed_cnt)++; + ethtype_found = true; + } else if (actions->type == + ROC_NPC_ACTION_TYPE_VLAN_PCP_INSERT) { + if (pcp_found) + return 0; + const struct roc_npc_action_of_set_vlan_pcp *pcp = + (const struct roc_npc_action_of_set_vlan_pcp *) + actions->conf; + vlan_info->vlan_pcp = pcp->vlan_pcp; + if (vlan_info->vlan_pcp > 0x7) { + plt_err("Invalid PCP value for pcp action"); + return -EINVAL; + } + flow->vtag_insert_enabled = true; + (*parsed_cnt)++; + pcp_found = true; + } else { + return 0; + } + } + + return 0; +} + +static int +npc_vtag_insert_action_configure(struct mbox *mbox, struct roc_npc_flow *flow, + struct npc_action_vtag_info *vlan_info) +{ + struct nix_vtag_config *vtag_cfg; + struct nix_vtag_config_rsp *rsp; + int rc = 0; + + union { + uint64_t reg; + struct nix_tx_vtag_action_s act; + } tx_vtag_action; + + vtag_cfg = mbox_alloc_msg_nix_vtag_cfg(mbox); + + if (vtag_cfg == NULL) + return -ENOSPC; + + vtag_cfg->cfg_type = VTAG_TX; + vtag_cfg->vtag_size = NIX_VTAGSIZE_T4; + vtag_cfg->tx.vtag0 = + ((vlan_info[0].vlan_ethtype << 16) | + (vlan_info[0].vlan_pcp << 13) | vlan_info[0].vlan_id); + + vtag_cfg->tx.cfg_vtag0 = 1; + + if (flow->vtag_insert_count == 2) { + vtag_cfg->tx.vtag1 = + ((vlan_info[1].vlan_ethtype << 16) | + (vlan_info[1].vlan_pcp << 13) | vlan_info[1].vlan_id); + + vtag_cfg->tx.cfg_vtag1 = 1; + } + + rc = mbox_process_msg(mbox, (void *)&rsp); + if (rc) + return rc; + + if (rsp->vtag0_idx < 0 || + ((flow->vtag_insert_count == 2) && (rsp->vtag1_idx < 0))) { + plt_err("Failed to config TX VTAG action"); + return -EINVAL; + } + + tx_vtag_action.reg = 0; + tx_vtag_action.act.vtag0_def = rsp->vtag0_idx; + tx_vtag_action.act.vtag0_lid = NPC_LID_LA; + tx_vtag_action.act.vtag0_op = NIX_TX_VTAGOP_INSERT; + tx_vtag_action.act.vtag0_relptr = NIX_TX_VTAGACTION_VTAG0_RELPTR; + + if (flow->vtag_insert_count == 2) { + tx_vtag_action.act.vtag1_def = rsp->vtag1_idx; + tx_vtag_action.act.vtag1_lid = NPC_LID_LA; + tx_vtag_action.act.vtag1_op = NIX_TX_VTAGOP_INSERT; + /* NIX_TX_VTAG_ACTION_S + * If Vtag 0 is inserted, hardware adjusts the Vtag 1 byte + * offset accordingly. Thus, if the two offsets are equal in + * the structure, hardware inserts Vtag 1 immediately after + * Vtag 0 in the packet. + */ + tx_vtag_action.act.vtag1_relptr = + NIX_TX_VTAGACTION_VTAG0_RELPTR; + } + + flow->vtag_action = tx_vtag_action.reg; + + return 0; +} + +static int +npc_vtag_strip_action_configure(struct mbox *mbox, + const struct roc_npc_action actions[], + struct roc_npc_flow *flow, int *strip_cnt) +{ + struct nix_vtag_config *vtag_cfg; + uint64_t rx_vtag_action = 0; + int count = 0, rc = 0; + + *strip_cnt = 0; + + for (; count < NPC_ACTION_MAX_VLANS_STRIPPED; count++, actions++) { + if (actions->type == ROC_NPC_ACTION_TYPE_VLAN_STRIP) + (*strip_cnt)++; + } + + vtag_cfg = mbox_alloc_msg_nix_vtag_cfg(mbox); + + if (vtag_cfg == NULL) + return -ENOSPC; + + vtag_cfg->cfg_type = VTAG_RX; + vtag_cfg->rx.strip_vtag = 1; + /* Always capture */ + vtag_cfg->rx.capture_vtag = 1; + vtag_cfg->vtag_size = NIX_VTAGSIZE_T4; + vtag_cfg->rx.vtag_type = 0; + + rc = mbox_process(mbox); + if (rc) + return rc; + + rx_vtag_action |= (NIX_RX_VTAGACTION_VTAG_VALID << 15); + rx_vtag_action |= ((uint64_t)NPC_LID_LB << 8); + rx_vtag_action |= NIX_RX_VTAGACTION_VTAG0_RELPTR; + + if (*strip_cnt == 2) { + rx_vtag_action |= (NIX_RX_VTAGACTION_VTAG_VALID << 47); + rx_vtag_action |= ((uint64_t)NPC_LID_LB << 40); + rx_vtag_action |= NIX_RX_VTAGACTION_VTAG0_RELPTR << 32; + } + flow->vtag_action = rx_vtag_action; + + return 0; +} + +static int +npc_vtag_action_program(struct roc_npc *roc_npc, + const struct roc_npc_action actions[], + struct roc_npc_flow *flow) +{ + bool vlan_strip_parsed = false, vlan_insert_parsed = false; + const struct roc_npc_action *insert_actions; + struct roc_nix *roc_nix = roc_npc->roc_nix; + struct npc_action_vtag_info vlan_info[2]; + int parsed_cnt = 0, strip_cnt = 0; + int tot_vlan_params = 0; + struct mbox *mbox; + struct nix *nix; + int i, rc; + + nix = roc_nix_to_nix_priv(roc_nix); + mbox = (&nix->dev)->mbox; + + memset(vlan_info, 0, sizeof(vlan_info)); + + flow->vtag_insert_enabled = false; + + for (; actions->type != ROC_NPC_ACTION_TYPE_END; actions++) { + if (actions->type == ROC_NPC_ACTION_TYPE_VLAN_STRIP) { + if (vlan_strip_parsed) { + plt_err("Incorrect VLAN strip actions"); + return -EINVAL; + } + rc = npc_vtag_strip_action_configure(mbox, actions, + flow, &strip_cnt); + if (rc) + return rc; + + if (strip_cnt == 2) + actions++; + + vlan_strip_parsed = true; + } else if (actions->type == ROC_NPC_ACTION_TYPE_VLAN_INSERT || + actions->type == + ROC_NPC_ACTION_TYPE_VLAN_ETHTYPE_INSERT || + actions->type == + ROC_NPC_ACTION_TYPE_VLAN_PCP_INSERT) { + if (vlan_insert_parsed) { + plt_err("Incorrect VLAN insert actions"); + return -EINVAL; + } + + insert_actions = actions; + + for (i = 0; i < 2; i++) { + rc = npc_vtag_insert_action_parse( + insert_actions, flow, &vlan_info[i], + &parsed_cnt); + + if (rc) + return rc; + + if (parsed_cnt) { + insert_actions += parsed_cnt; + tot_vlan_params += parsed_cnt; + flow->vtag_insert_count++; + } + } + actions += tot_vlan_params - 1; + vlan_insert_parsed = true; + } + } + + if (flow->vtag_insert_enabled) { + rc = npc_vtag_insert_action_configure(mbox, flow, vlan_info); + + if (rc) + return rc; + } + return 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[], @@ -785,6 +1151,21 @@ roc_npc_flow_create(struct roc_npc *roc_npc, const struct roc_npc_attr *attr, struct npc_flow_list *list; int rc; + npc->channel = roc_npc->channel; + npc->is_sdp_link = roc_nix_is_sdp(roc_npc->roc_nix); + if (npc->is_sdp_link) { + if (roc_npc->is_sdp_mask_set) { + npc->sdp_channel = roc_npc->sdp_channel; + npc->sdp_channel_mask = roc_npc->sdp_channel_mask; + } else { + /* By default set the channel and mask to cover + * the whole SDP channel range. + */ + npc->sdp_channel = (uint16_t)NIX_CHAN_SDP_CH_START; + npc->sdp_channel_mask = (uint16_t)NIX_CHAN_SDP_CH_START; + } + } + flow = plt_zmalloc(sizeof(*flow), 0); if (flow == NULL) { *errcode = NPC_ERR_NO_MEM; @@ -792,7 +1173,14 @@ roc_npc_flow_create(struct roc_npc *roc_npc, const struct roc_npc_attr *attr, } memset(flow, 0, sizeof(*flow)); - rc = npc_parse_rule(npc, attr, pattern, actions, flow, &parse_state); + rc = npc_parse_rule(roc_npc, attr, pattern, actions, flow, + &parse_state); + if (rc != 0) { + *errcode = rc; + goto err_exit; + } + + rc = npc_vtag_action_program(roc_npc, actions, flow); if (rc != 0) { *errcode = rc; goto err_exit; @@ -857,32 +1245,27 @@ 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_rss_group_free(npc, flow); if (rc != 0) { plt_err("Failed to free rss action rc = %d", rc); return rc; } + if (flow->vtag_insert_enabled) { + rc = npc_vtag_cfg_delete(roc_npc, flow); + if (rc != 0) + return rc; + } + 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); + npc_delete_prio_list_entry(npc, flow); plt_free(flow); return 0; @@ -907,3 +1290,30 @@ roc_npc_flow_dump(FILE *file, struct roc_npc *roc_npc) } } } + +int +roc_npc_mcam_merge_base_steering_rule(struct roc_npc *roc_npc, + struct roc_npc_flow *flow) +{ + struct npc_mcam_read_base_rule_rsp *base_rule_rsp; + struct npc *npc = roc_npc_to_npc_priv(roc_npc); + struct mcam_entry *base_entry; + int idx, rc; + + if (roc_nix_is_pf(roc_npc->roc_nix)) + return 0; + + (void)mbox_alloc_msg_npc_read_base_steer_rule(npc->mbox); + rc = mbox_process_msg(npc->mbox, (void *)&base_rule_rsp); + if (rc) { + plt_err("Failed to fetch VF's base MCAM entry"); + return rc; + } + base_entry = &base_rule_rsp->entry_data; + for (idx = 0; idx < ROC_NPC_MAX_MCAM_WIDTH_DWORDS; idx++) { + flow->mcam_data[idx] |= base_entry->kw[idx]; + flow->mcam_mask[idx] |= base_entry->kw_mask[idx]; + } + + return 0; +}