X-Git-Url: http://git.droids-corp.org/?a=blobdiff_plain;f=drivers%2Fcommon%2Fcnxk%2Froc_npc.c;h=503c74748f6b926a516918bd89eb23794033a0ec;hb=edbe962fa18d5133bae10f81bf6f13b43901a30b;hp=8a7682369881bf3e6d9d1dff6b34ac89f13915c9;hpb=19f3cc2374d0e5d2cb35bede4198911a8401c901;p=dpdk.git diff --git a/drivers/common/cnxk/roc_npc.c b/drivers/common/cnxk/roc_npc.c index 8a76823698..503c74748f 100644 --- a/drivers/common/cnxk/roc_npc.c +++ b/drivers/common/cnxk/roc_npc.c @@ -10,7 +10,7 @@ roc_npc_vtag_actions_get(struct roc_npc *roc_npc) { struct npc *npc = roc_npc_to_npc_priv(roc_npc); - return npc->vtag_actions; + return npc->vtag_strip_actions; } int @@ -18,8 +18,8 @@ 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_actions -= count; - return npc->vtag_actions; + npc->vtag_strip_actions -= count; + return npc->vtag_strip_actions; } int @@ -108,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); } @@ -177,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) { @@ -225,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; @@ -279,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; @@ -311,40 +253,49 @@ 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; @@ -356,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++) { @@ -404,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; @@ -425,15 +385,16 @@ 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; @@ -447,6 +408,12 @@ npc_parse_actions(struct npc *npc, const struct roc_npc_attr *attr, 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; goto err_exit; @@ -481,6 +448,23 @@ npc_parse_actions(struct npc *npc, const struct roc_npc_attr *attr, goto err_exit; } + 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; + } + + 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) || @@ -526,14 +510,14 @@ npc_parse_actions(struct npc *npc, const struct roc_npc_attr *attr, } if (req_act & ROC_NPC_ACTION_TYPE_VLAN_STRIP) - npc->vtag_actions++; - - /* Only VLAN action is provided */ - if (req_act == ROC_NPC_ACTION_TYPE_VLAN_STRIP) - flow->npc_action = NIX_RX_ACTIONOP_UCAST; + 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; @@ -660,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 */ @@ -678,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; @@ -694,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; @@ -872,6 +858,11 @@ npc_vtag_cfg_delete(struct roc_npc *roc_npc, struct roc_npc_flow *flow) 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; @@ -880,120 +871,271 @@ npc_vtag_cfg_delete(struct roc_npc *roc_npc, struct roc_npc_flow *flow) } static int -npc_vtag_action_program(struct roc_npc *roc_npc, - const struct roc_npc_action actions[], - struct roc_npc_flow *flow) +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) { - uint16_t vlan_id = 0, vlan_ethtype = ROC_ETHER_TYPE_VLAN; - struct npc *npc = roc_npc_to_npc_priv(roc_npc); - struct roc_nix *roc_nix = roc_npc->roc_nix; - struct nix_vtag_config *vtag_cfg; - struct nix_vtag_config_rsp *rsp; - uint64_t rx_vtag_action = 0; - uint8_t vlan_pcp = 0; - struct mbox *mbox; - struct nix *nix; - int rc; - - 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; - - flow->vtag_insert_enabled = false; + bool vlan_id_found = false, ethtype_found = false, pcp_found = false; + int count = 0; - for (; actions->type != ROC_NPC_ACTION_TYPE_END; actions++) { - if (actions->type == ROC_NPC_ACTION_TYPE_VLAN_STRIP) { - if (npc->vtag_actions == 1) { - vtag_cfg = mbox_alloc_msg_nix_vtag_cfg(mbox); + *parsed_cnt = 0; - if (vtag_cfg == NULL) - return -ENOSPC; + /* 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. + */ - 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; + for (; count < NPC_ACTION_MAX_VLAN_PARAMS; count++, actions++) { + if (actions->type == ROC_NPC_ACTION_TYPE_VLAN_INSERT) { + if (vlan_id_found) + return 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; - flow->vtag_action = rx_vtag_action; - } else if (actions->type == ROC_NPC_ACTION_TYPE_VLAN_INSERT) { const struct roc_npc_action_of_set_vlan_vid *vtag = (const struct roc_npc_action_of_set_vlan_vid *) actions->conf; - vlan_id = plt_be_to_cpu_16(vtag->vlan_vid); - if (vlan_id > 0xfff) { + + 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_ethtype = plt_be_to_cpu_16(ethtype->ethertype); - if (vlan_ethtype != ROC_ETHER_TYPE_VLAN && - vlan_ethtype != ROC_ETHER_TYPE_QINQ) { + 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_pcp = pcp->vlan_pcp; - if (vlan_pcp > 0x7) { + 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; } } - if (flow->vtag_insert_enabled) { - vtag_cfg = mbox_alloc_msg_nix_vtag_cfg(mbox); + return 0; +} - if (vtag_cfg == NULL) - return -ENOSPC; +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; - vtag_cfg->cfg_type = VTAG_TX; - vtag_cfg->vtag_size = NIX_VTAGSIZE_T4; - vtag_cfg->tx.vtag0 = - ((vlan_ethtype << 16) | (vlan_pcp << 13) | vlan_id); + union { + uint64_t reg; + struct nix_tx_vtag_action_s act; + } tx_vtag_action; - vtag_cfg->tx.cfg_vtag0 = 1; - rc = mbox_process_msg(mbox, (void *)&rsp); - if (rc) - return rc; + vtag_cfg = mbox_alloc_msg_nix_vtag_cfg(mbox); - if (rsp->vtag0_idx < 0) { - plt_err("Failed to config TX VTAG action"); - return -EINVAL; - } + 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; + } - 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 = + 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; + } + + 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; } @@ -1009,6 +1151,8 @@ 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; + flow = plt_zmalloc(sizeof(*flow), 0); if (flow == NULL) { *errcode = NPC_ERR_NO_MEM; @@ -1016,7 +1160,8 @@ 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; @@ -1087,7 +1232,6 @@ 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; int rc; rc = npc_rss_group_free(npc, flow); @@ -1108,8 +1252,7 @@ roc_npc_flow_destroy(struct roc_npc *roc_npc, struct roc_npc_flow *flow) 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; @@ -1134,3 +1277,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; +}