1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright(C) 2021 Marvell. 3 */ 4 5 #include "roc_api.h" 6 #include "roc_priv.h" 7 8 int 9 roc_npc_vtag_actions_get(struct roc_npc *roc_npc) 10 { 11 struct npc *npc = roc_npc_to_npc_priv(roc_npc); 12 13 return npc->vtag_strip_actions; 14 } 15 16 int 17 roc_npc_vtag_actions_sub_return(struct roc_npc *roc_npc, uint32_t count) 18 { 19 struct npc *npc = roc_npc_to_npc_priv(roc_npc); 20 21 npc->vtag_strip_actions -= count; 22 return npc->vtag_strip_actions; 23 } 24 25 int 26 roc_npc_mcam_free_counter(struct roc_npc *roc_npc, uint16_t ctr_id) 27 { 28 struct npc *npc = roc_npc_to_npc_priv(roc_npc); 29 30 return npc_mcam_free_counter(npc, ctr_id); 31 } 32 33 int 34 roc_npc_mcam_read_counter(struct roc_npc *roc_npc, uint32_t ctr_id, 35 uint64_t *count) 36 { 37 struct npc *npc = roc_npc_to_npc_priv(roc_npc); 38 39 return npc_mcam_read_counter(npc, ctr_id, count); 40 } 41 42 int 43 roc_npc_mcam_clear_counter(struct roc_npc *roc_npc, uint32_t ctr_id) 44 { 45 struct npc *npc = roc_npc_to_npc_priv(roc_npc); 46 47 return npc_mcam_clear_counter(npc, ctr_id); 48 } 49 50 int 51 roc_npc_mcam_free_entry(struct roc_npc *roc_npc, uint32_t entry) 52 { 53 struct npc *npc = roc_npc_to_npc_priv(roc_npc); 54 55 return npc_mcam_free_entry(npc, entry); 56 } 57 58 int 59 roc_npc_mcam_free_all_resources(struct roc_npc *roc_npc) 60 { 61 struct npc *npc = roc_npc_to_npc_priv(roc_npc); 62 63 return npc_flow_free_all_resources(npc); 64 } 65 66 int 67 roc_npc_mcam_alloc_entries(struct roc_npc *roc_npc, int ref_entry, 68 int *alloc_entry, int req_count, int priority, 69 int *resp_count) 70 { 71 struct npc *npc = roc_npc_to_npc_priv(roc_npc); 72 73 return npc_mcam_alloc_entries(npc, ref_entry, alloc_entry, req_count, 74 priority, resp_count); 75 } 76 77 int 78 roc_npc_mcam_alloc_entry(struct roc_npc *roc_npc, struct roc_npc_flow *mcam, 79 struct roc_npc_flow *ref_mcam, int prio, 80 int *resp_count) 81 { 82 struct npc *npc = roc_npc_to_npc_priv(roc_npc); 83 84 return npc_mcam_alloc_entry(npc, mcam, ref_mcam, prio, resp_count); 85 } 86 87 int 88 roc_npc_mcam_ena_dis_entry(struct roc_npc *roc_npc, struct roc_npc_flow *mcam, 89 bool enable) 90 { 91 struct npc *npc = roc_npc_to_npc_priv(roc_npc); 92 93 return npc_mcam_ena_dis_entry(npc, mcam, enable); 94 } 95 96 int 97 roc_npc_mcam_write_entry(struct roc_npc *roc_npc, struct roc_npc_flow *mcam) 98 { 99 struct npc *npc = roc_npc_to_npc_priv(roc_npc); 100 101 return npc_mcam_write_entry(npc, mcam); 102 } 103 104 int 105 roc_npc_get_low_priority_mcam(struct roc_npc *roc_npc) 106 { 107 struct npc *npc = roc_npc_to_npc_priv(roc_npc); 108 109 if (roc_model_is_cn10k()) 110 return (npc->mcam_entries - NPC_MCAME_RESVD_10XX - 1); 111 else if (roc_model_is_cn98xx()) 112 return (npc->mcam_entries - NPC_MCAME_RESVD_98XX - 1); 113 else 114 return (npc->mcam_entries - NPC_MCAME_RESVD_9XXX - 1); 115 } 116 117 static int 118 npc_mcam_tot_entries(void) 119 { 120 /* FIXME: change to reading in AF from NPC_AF_CONST1/2 121 * MCAM_BANK_DEPTH(_EXT) * MCAM_BANKS 122 */ 123 if (roc_model_is_cn10k() || roc_model_is_cn98xx()) 124 return 16 * 1024; /* MCAM_BANKS = 4, BANK_DEPTH_EXT = 4096 */ 125 else 126 return 4 * 1024; /* MCAM_BANKS = 4, BANK_DEPTH_EXT = 1024 */ 127 } 128 129 const char * 130 roc_npc_profile_name_get(struct roc_npc *roc_npc) 131 { 132 struct npc *npc = roc_npc_to_npc_priv(roc_npc); 133 134 return (char *)npc->profile_name; 135 } 136 137 int 138 roc_npc_init(struct roc_npc *roc_npc) 139 { 140 uint8_t *mem = NULL, *nix_mem = NULL, *npc_mem = NULL; 141 struct nix *nix = roc_nix_to_nix_priv(roc_npc->roc_nix); 142 struct npc *npc = roc_npc_to_npc_priv(roc_npc); 143 uint32_t bmap_sz; 144 int rc = 0, idx; 145 size_t sz; 146 147 PLT_STATIC_ASSERT(sizeof(struct npc) <= ROC_NPC_MEM_SZ); 148 149 memset(npc, 0, sizeof(*npc)); 150 npc->mbox = (&nix->dev)->mbox; 151 roc_npc->channel = nix->rx_chan_base; 152 roc_npc->pf_func = (&nix->dev)->pf_func; 153 npc->channel = roc_npc->channel; 154 npc->pf_func = roc_npc->pf_func; 155 npc->flow_max_priority = roc_npc->flow_max_priority; 156 npc->switch_header_type = roc_npc->switch_header_type; 157 npc->flow_prealloc_size = roc_npc->flow_prealloc_size; 158 159 if (npc->mbox == NULL) 160 return NPC_ERR_PARAM; 161 162 rc = npc_mcam_fetch_kex_cfg(npc); 163 if (rc) 164 goto done; 165 166 roc_npc->kex_capability = npc_get_kex_capability(npc); 167 roc_npc->rx_parse_nibble = npc->keyx_supp_nmask[NPC_MCAM_RX]; 168 169 npc->mark_actions = 0; 170 171 npc->mcam_entries = npc_mcam_tot_entries() >> npc->keyw[NPC_MCAM_RX]; 172 173 /* Free, free_rev, live and live_rev entries */ 174 bmap_sz = plt_bitmap_get_memory_footprint(npc->mcam_entries); 175 mem = plt_zmalloc(4 * bmap_sz * npc->flow_max_priority, 0); 176 if (mem == NULL) { 177 plt_err("Bmap alloc failed"); 178 rc = NPC_ERR_NO_MEM; 179 return rc; 180 } 181 182 sz = npc->flow_max_priority * sizeof(struct npc_flow_list); 183 npc->flow_list = plt_zmalloc(sz, 0); 184 if (npc->flow_list == NULL) { 185 plt_err("flow_list alloc failed"); 186 rc = NPC_ERR_NO_MEM; 187 goto done; 188 } 189 190 sz = npc->flow_max_priority * sizeof(struct npc_prio_flow_list_head); 191 npc->prio_flow_list = plt_zmalloc(sz, 0); 192 if (npc->prio_flow_list == NULL) { 193 plt_err("prio_flow_list alloc failed"); 194 rc = NPC_ERR_NO_MEM; 195 goto done; 196 } 197 198 npc_mem = mem; 199 for (idx = 0; idx < npc->flow_max_priority; idx++) { 200 TAILQ_INIT(&npc->flow_list[idx]); 201 TAILQ_INIT(&npc->prio_flow_list[idx]); 202 } 203 204 npc->rss_grps = NPC_RSS_GRPS; 205 206 bmap_sz = plt_bitmap_get_memory_footprint(npc->rss_grps); 207 nix_mem = plt_zmalloc(bmap_sz, 0); 208 if (nix_mem == NULL) { 209 plt_err("Bmap alloc failed"); 210 rc = NPC_ERR_NO_MEM; 211 goto done; 212 } 213 214 npc->rss_grp_entries = plt_bitmap_init(npc->rss_grps, nix_mem, bmap_sz); 215 216 if (!npc->rss_grp_entries) { 217 plt_err("bitmap init failed"); 218 rc = NPC_ERR_NO_MEM; 219 goto done; 220 } 221 222 /* Group 0 will be used for RSS, 223 * 1 -7 will be used for npc_flow RSS action 224 */ 225 plt_bitmap_set(npc->rss_grp_entries, 0); 226 227 return rc; 228 229 done: 230 if (npc->flow_list) 231 plt_free(npc->flow_list); 232 if (npc->prio_flow_list) 233 plt_free(npc->prio_flow_list); 234 if (npc_mem) 235 plt_free(npc_mem); 236 return rc; 237 } 238 239 int 240 roc_npc_fini(struct roc_npc *roc_npc) 241 { 242 struct npc *npc = roc_npc_to_npc_priv(roc_npc); 243 int rc; 244 245 rc = npc_flow_free_all_resources(npc); 246 if (rc) { 247 plt_err("Error when deleting NPC MCAM entries, counters"); 248 return rc; 249 } 250 251 if (npc->flow_list) { 252 plt_free(npc->flow_list); 253 npc->flow_list = NULL; 254 } 255 256 if (npc->prio_flow_list) { 257 plt_free(npc->prio_flow_list); 258 npc->prio_flow_list = NULL; 259 } 260 261 return 0; 262 } 263 264 int 265 roc_npc_validate_portid_action(struct roc_npc *roc_npc_src, 266 struct roc_npc *roc_npc_dst) 267 { 268 struct roc_nix *roc_nix_src = roc_npc_src->roc_nix; 269 struct nix *nix_src = roc_nix_to_nix_priv(roc_nix_src); 270 struct roc_nix *roc_nix_dst = roc_npc_dst->roc_nix; 271 struct nix *nix_dst = roc_nix_to_nix_priv(roc_nix_dst); 272 273 if (roc_nix_is_pf(roc_npc_dst->roc_nix)) { 274 plt_err("Output port should be VF"); 275 return -EINVAL; 276 } 277 278 if (nix_dst->dev.vf >= nix_src->dev.maxvf) { 279 plt_err("Invalid VF for output port"); 280 return -EINVAL; 281 } 282 283 if (nix_src->dev.pf != nix_dst->dev.pf) { 284 plt_err("Output port should be VF of ingress PF"); 285 return -EINVAL; 286 } 287 return 0; 288 } 289 290 static int 291 npc_parse_actions(struct roc_npc *roc_npc, const struct roc_npc_attr *attr, 292 const struct roc_npc_action actions[], 293 struct roc_npc_flow *flow) 294 { 295 const struct roc_npc_action_port_id *act_portid; 296 struct npc *npc = roc_npc_to_npc_priv(roc_npc); 297 const struct roc_npc_action_mark *act_mark; 298 const struct roc_npc_action_meter *act_mtr; 299 const struct roc_npc_action_queue *act_q; 300 const struct roc_npc_action_vf *vf_act; 301 bool vlan_insert_action = false; 302 int sel_act, req_act = 0; 303 uint16_t pf_func, vf_id; 304 int errcode = 0; 305 int mark = 0; 306 int rq = 0; 307 308 /* Initialize actions */ 309 flow->ctr_id = NPC_COUNTER_NONE; 310 flow->mtr_id = ROC_NIX_MTR_ID_INVALID; 311 pf_func = npc->pf_func; 312 313 for (; actions->type != ROC_NPC_ACTION_TYPE_END; actions++) { 314 switch (actions->type) { 315 case ROC_NPC_ACTION_TYPE_VOID: 316 break; 317 case ROC_NPC_ACTION_TYPE_MARK: 318 act_mark = (const struct roc_npc_action_mark *) 319 actions->conf; 320 if (act_mark->id > (NPC_FLOW_FLAG_VAL - 2)) { 321 plt_err("mark value must be < 0xfffe"); 322 goto err_exit; 323 } 324 mark = act_mark->id + 1; 325 req_act |= ROC_NPC_ACTION_TYPE_MARK; 326 npc->mark_actions += 1; 327 break; 328 329 case ROC_NPC_ACTION_TYPE_FLAG: 330 mark = NPC_FLOW_FLAG_VAL; 331 req_act |= ROC_NPC_ACTION_TYPE_FLAG; 332 npc->mark_actions += 1; 333 break; 334 335 case ROC_NPC_ACTION_TYPE_COUNT: 336 /* Indicates, need a counter */ 337 flow->ctr_id = 1; 338 req_act |= ROC_NPC_ACTION_TYPE_COUNT; 339 break; 340 341 case ROC_NPC_ACTION_TYPE_DROP: 342 req_act |= ROC_NPC_ACTION_TYPE_DROP; 343 break; 344 345 case ROC_NPC_ACTION_TYPE_PF: 346 req_act |= ROC_NPC_ACTION_TYPE_PF; 347 pf_func &= (0xfc00); 348 break; 349 350 case ROC_NPC_ACTION_TYPE_VF: 351 vf_act = 352 (const struct roc_npc_action_vf *)actions->conf; 353 req_act |= ROC_NPC_ACTION_TYPE_VF; 354 vf_id = vf_act->id & RVU_PFVF_FUNC_MASK; 355 pf_func &= (0xfc00); 356 pf_func = (pf_func | (vf_id + 1)); 357 break; 358 359 case ROC_NPC_ACTION_TYPE_PORT_ID: 360 act_portid = (const struct roc_npc_action_port_id *) 361 actions->conf; 362 pf_func &= (0xfc00); 363 pf_func = (pf_func | (act_portid->id + 1)); 364 req_act |= ROC_NPC_ACTION_TYPE_VF; 365 break; 366 367 case ROC_NPC_ACTION_TYPE_QUEUE: 368 act_q = (const struct roc_npc_action_queue *) 369 actions->conf; 370 rq = act_q->index; 371 req_act |= ROC_NPC_ACTION_TYPE_QUEUE; 372 break; 373 374 case ROC_NPC_ACTION_TYPE_RSS: 375 req_act |= ROC_NPC_ACTION_TYPE_RSS; 376 break; 377 378 case ROC_NPC_ACTION_TYPE_SEC: 379 /* Assumes user has already configured security 380 * session for this flow. Associated conf is 381 * opaque. When security is implemented, 382 * we need to verify that for specified security 383 * session: 384 * action_type == 385 * NPC_SECURITY_ACTION_TYPE_INLINE_PROTOCOL && 386 * session_protocol == 387 * NPC_SECURITY_PROTOCOL_IPSEC 388 */ 389 req_act |= ROC_NPC_ACTION_TYPE_SEC; 390 rq = 0; 391 392 /* Special processing when with inline device */ 393 if (roc_nix_inb_is_with_inl_dev(roc_npc->roc_nix) && 394 roc_nix_inl_dev_is_probed()) { 395 rq = 0; 396 pf_func = nix_inl_dev_pffunc_get(); 397 } 398 break; 399 case ROC_NPC_ACTION_TYPE_VLAN_STRIP: 400 req_act |= ROC_NPC_ACTION_TYPE_VLAN_STRIP; 401 break; 402 case ROC_NPC_ACTION_TYPE_VLAN_INSERT: 403 req_act |= ROC_NPC_ACTION_TYPE_VLAN_INSERT; 404 break; 405 case ROC_NPC_ACTION_TYPE_VLAN_ETHTYPE_INSERT: 406 req_act |= ROC_NPC_ACTION_TYPE_VLAN_ETHTYPE_INSERT; 407 break; 408 case ROC_NPC_ACTION_TYPE_VLAN_PCP_INSERT: 409 req_act |= ROC_NPC_ACTION_TYPE_VLAN_PCP_INSERT; 410 break; 411 case ROC_NPC_ACTION_TYPE_METER: 412 act_mtr = (const struct roc_npc_action_meter *) 413 actions->conf; 414 flow->mtr_id = act_mtr->mtr_id; 415 req_act |= ROC_NPC_ACTION_TYPE_METER; 416 break; 417 default: 418 errcode = NPC_ERR_ACTION_NOTSUP; 419 goto err_exit; 420 } 421 } 422 423 if (req_act & (ROC_NPC_ACTION_TYPE_VLAN_INSERT | 424 ROC_NPC_ACTION_TYPE_VLAN_ETHTYPE_INSERT | 425 ROC_NPC_ACTION_TYPE_VLAN_PCP_INSERT)) 426 vlan_insert_action = true; 427 428 if ((req_act & (ROC_NPC_ACTION_TYPE_VLAN_INSERT | 429 ROC_NPC_ACTION_TYPE_VLAN_ETHTYPE_INSERT | 430 ROC_NPC_ACTION_TYPE_VLAN_PCP_INSERT)) == 431 ROC_NPC_ACTION_TYPE_VLAN_PCP_INSERT) { 432 plt_err("PCP insert action can't be supported alone"); 433 errcode = NPC_ERR_ACTION_NOTSUP; 434 goto err_exit; 435 } 436 437 /* Both STRIP and INSERT actions are not supported */ 438 if (vlan_insert_action && (req_act & ROC_NPC_ACTION_TYPE_VLAN_STRIP)) { 439 errcode = NPC_ERR_ACTION_NOTSUP; 440 goto err_exit; 441 } 442 443 /* Check if actions specified are compatible */ 444 if (attr->egress) { 445 if (req_act & ROC_NPC_ACTION_TYPE_VLAN_STRIP) { 446 plt_err("VLAN pop action is not supported on Egress"); 447 errcode = NPC_ERR_ACTION_NOTSUP; 448 goto err_exit; 449 } 450 451 if (req_act & 452 ~(ROC_NPC_ACTION_TYPE_VLAN_INSERT | 453 ROC_NPC_ACTION_TYPE_VLAN_ETHTYPE_INSERT | 454 ROC_NPC_ACTION_TYPE_VLAN_PCP_INSERT | 455 ROC_NPC_ACTION_TYPE_DROP | ROC_NPC_ACTION_TYPE_COUNT)) { 456 plt_err("Only VLAN insert, drop, count supported on Egress"); 457 errcode = NPC_ERR_ACTION_NOTSUP; 458 goto err_exit; 459 } 460 461 if (vlan_insert_action && 462 (req_act & ROC_NPC_ACTION_TYPE_DROP)) { 463 plt_err("Both VLAN insert and drop actions cannot be supported"); 464 errcode = NPC_ERR_ACTION_NOTSUP; 465 goto err_exit; 466 } 467 468 if (req_act & ROC_NPC_ACTION_TYPE_DROP) { 469 flow->npc_action = NIX_TX_ACTIONOP_DROP; 470 } else if ((req_act & ROC_NPC_ACTION_TYPE_COUNT) || 471 vlan_insert_action) { 472 flow->npc_action = NIX_TX_ACTIONOP_UCAST_DEFAULT; 473 } else { 474 plt_err("Unsupported action for egress"); 475 errcode = NPC_ERR_ACTION_NOTSUP; 476 goto err_exit; 477 } 478 479 goto set_pf_func; 480 } else { 481 if (vlan_insert_action) { 482 errcode = NPC_ERR_ACTION_NOTSUP; 483 goto err_exit; 484 } 485 } 486 487 /* We have already verified the attr, this is ingress. 488 * - Exactly one terminating action is supported 489 * - Exactly one of MARK or FLAG is supported 490 * - If terminating action is DROP, only count is valid. 491 */ 492 sel_act = req_act & NPC_ACTION_TERM; 493 if ((sel_act & (sel_act - 1)) != 0) { 494 errcode = NPC_ERR_ACTION_NOTSUP; 495 goto err_exit; 496 } 497 498 if (req_act & ROC_NPC_ACTION_TYPE_DROP) { 499 sel_act = req_act & ~ROC_NPC_ACTION_TYPE_COUNT; 500 if ((sel_act & (sel_act - 1)) != 0) { 501 errcode = NPC_ERR_ACTION_NOTSUP; 502 goto err_exit; 503 } 504 } 505 506 if ((req_act & (ROC_NPC_ACTION_TYPE_FLAG | ROC_NPC_ACTION_TYPE_MARK)) == 507 (ROC_NPC_ACTION_TYPE_FLAG | ROC_NPC_ACTION_TYPE_MARK)) { 508 errcode = NPC_ERR_ACTION_NOTSUP; 509 goto err_exit; 510 } 511 512 if (req_act & ROC_NPC_ACTION_TYPE_VLAN_STRIP) 513 npc->vtag_strip_actions++; 514 515 /* Set NIX_RX_ACTIONOP */ 516 if (req_act == ROC_NPC_ACTION_TYPE_VLAN_STRIP) { 517 /* Only VLAN action is provided */ 518 flow->npc_action = NIX_RX_ACTIONOP_UCAST; 519 } else if (req_act & 520 (ROC_NPC_ACTION_TYPE_PF | ROC_NPC_ACTION_TYPE_VF)) { 521 flow->npc_action = NIX_RX_ACTIONOP_UCAST; 522 if (req_act & ROC_NPC_ACTION_TYPE_QUEUE) 523 flow->npc_action |= (uint64_t)rq << 20; 524 } else if (req_act & ROC_NPC_ACTION_TYPE_DROP) { 525 flow->npc_action = NIX_RX_ACTIONOP_DROP; 526 } else if (req_act & ROC_NPC_ACTION_TYPE_QUEUE) { 527 flow->npc_action = NIX_RX_ACTIONOP_UCAST; 528 flow->npc_action |= (uint64_t)rq << 20; 529 } else if (req_act & ROC_NPC_ACTION_TYPE_RSS) { 530 flow->npc_action = NIX_RX_ACTIONOP_UCAST; 531 } else if (req_act & ROC_NPC_ACTION_TYPE_SEC) { 532 flow->npc_action = NIX_RX_ACTIONOP_UCAST_IPSEC; 533 flow->npc_action |= (uint64_t)rq << 20; 534 } else if (req_act & 535 (ROC_NPC_ACTION_TYPE_FLAG | ROC_NPC_ACTION_TYPE_MARK)) { 536 flow->npc_action = NIX_RX_ACTIONOP_UCAST; 537 } else if (req_act & ROC_NPC_ACTION_TYPE_COUNT) { 538 /* Keep ROC_NPC_ACTION_TYPE_COUNT_ACT always at the end 539 * This is default action, when user specify only 540 * COUNT ACTION 541 */ 542 flow->npc_action = NIX_RX_ACTIONOP_UCAST; 543 } else { 544 /* Should never reach here */ 545 errcode = NPC_ERR_ACTION_NOTSUP; 546 goto err_exit; 547 } 548 549 if (mark) 550 flow->npc_action |= (uint64_t)mark << 40; 551 552 set_pf_func: 553 /* Ideally AF must ensure that correct pf_func is set */ 554 flow->npc_action |= (uint64_t)pf_func << 4; 555 556 return 0; 557 558 err_exit: 559 return errcode; 560 } 561 562 typedef int (*npc_parse_stage_func_t)(struct npc_parse_state *pst); 563 564 static int 565 npc_parse_pattern(struct npc *npc, const struct roc_npc_item_info pattern[], 566 struct roc_npc_flow *flow, struct npc_parse_state *pst) 567 { 568 npc_parse_stage_func_t parse_stage_funcs[] = { 569 npc_parse_meta_items, npc_parse_cpt_hdr, npc_parse_higig2_hdr, 570 npc_parse_la, npc_parse_lb, npc_parse_lc, 571 npc_parse_ld, npc_parse_le, npc_parse_lf, 572 npc_parse_lg, npc_parse_lh, 573 }; 574 uint8_t layer = 0; 575 int key_offset; 576 int rc; 577 578 if (pattern == NULL) 579 return NPC_ERR_PARAM; 580 581 memset(pst, 0, sizeof(*pst)); 582 pst->npc = npc; 583 pst->flow = flow; 584 585 /* Use integral byte offset */ 586 key_offset = pst->npc->keyx_len[flow->nix_intf]; 587 key_offset = (key_offset + 7) / 8; 588 589 /* Location where LDATA would begin */ 590 pst->mcam_data = (uint8_t *)flow->mcam_data; 591 pst->mcam_mask = (uint8_t *)flow->mcam_mask; 592 593 while (pattern->type != ROC_NPC_ITEM_TYPE_END && 594 layer < PLT_DIM(parse_stage_funcs)) { 595 /* Skip place-holders */ 596 pattern = npc_parse_skip_void_and_any_items(pattern); 597 598 pst->pattern = pattern; 599 rc = parse_stage_funcs[layer](pst); 600 if (rc != 0) 601 return rc; 602 603 layer++; 604 605 /* 606 * Parse stage function sets pst->pattern to 607 * 1 past the last item it consumed. 608 */ 609 pattern = pst->pattern; 610 611 if (pst->terminate) 612 break; 613 } 614 615 /* Skip trailing place-holders */ 616 pattern = npc_parse_skip_void_and_any_items(pattern); 617 618 /* Are there more items than what we can handle? */ 619 if (pattern->type != ROC_NPC_ITEM_TYPE_END) 620 return NPC_ERR_PATTERN_NOTSUP; 621 622 return 0; 623 } 624 625 static int 626 npc_parse_attr(struct npc *npc, const struct roc_npc_attr *attr, 627 struct roc_npc_flow *flow) 628 { 629 if (attr == NULL) 630 return NPC_ERR_PARAM; 631 else if (attr->priority >= npc->flow_max_priority) 632 return NPC_ERR_PARAM; 633 else if ((!attr->egress && !attr->ingress) || 634 (attr->egress && attr->ingress)) 635 return NPC_ERR_PARAM; 636 637 if (attr->ingress) 638 flow->nix_intf = ROC_NPC_INTF_RX; 639 else 640 flow->nix_intf = ROC_NPC_INTF_TX; 641 642 flow->priority = attr->priority; 643 return 0; 644 } 645 646 static int 647 npc_parse_rule(struct roc_npc *roc_npc, const struct roc_npc_attr *attr, 648 const struct roc_npc_item_info pattern[], 649 const struct roc_npc_action actions[], struct roc_npc_flow *flow, 650 struct npc_parse_state *pst) 651 { 652 struct npc *npc = roc_npc_to_npc_priv(roc_npc); 653 int err; 654 655 /* Check attr */ 656 err = npc_parse_attr(npc, attr, flow); 657 if (err) 658 return err; 659 660 /* Check pattern */ 661 err = npc_parse_pattern(npc, pattern, flow, pst); 662 if (err) 663 return err; 664 665 /* Check action */ 666 err = npc_parse_actions(roc_npc, attr, actions, flow); 667 if (err) 668 return err; 669 return 0; 670 } 671 672 int 673 roc_npc_flow_parse(struct roc_npc *roc_npc, const struct roc_npc_attr *attr, 674 const struct roc_npc_item_info pattern[], 675 const struct roc_npc_action actions[], 676 struct roc_npc_flow *flow) 677 { 678 struct npc *npc = roc_npc_to_npc_priv(roc_npc); 679 struct npc_parse_state parse_state = {0}; 680 int rc; 681 682 rc = npc_parse_rule(roc_npc, attr, pattern, actions, flow, 683 &parse_state); 684 if (rc) 685 return rc; 686 687 parse_state.is_vf = !roc_nix_is_pf(roc_npc->roc_nix); 688 689 return npc_program_mcam(npc, &parse_state, 0); 690 } 691 692 int 693 npc_rss_free_grp_get(struct npc *npc, uint32_t *pos) 694 { 695 struct plt_bitmap *bmap = npc->rss_grp_entries; 696 697 for (*pos = 0; *pos < ROC_NIX_RSS_GRPS; ++*pos) { 698 if (!plt_bitmap_get(bmap, *pos)) 699 break; 700 } 701 return *pos < ROC_NIX_RSS_GRPS ? 0 : -1; 702 } 703 704 int 705 npc_rss_action_configure(struct roc_npc *roc_npc, 706 const struct roc_npc_action_rss *rss, uint8_t *alg_idx, 707 uint32_t *rss_grp, uint32_t mcam_id) 708 { 709 struct npc *npc = roc_npc_to_npc_priv(roc_npc); 710 struct roc_nix *roc_nix = roc_npc->roc_nix; 711 struct nix *nix = roc_nix_to_nix_priv(roc_nix); 712 uint32_t flowkey_cfg, rss_grp_idx, i, rem; 713 uint8_t key[ROC_NIX_RSS_KEY_LEN]; 714 const uint8_t *key_ptr; 715 uint8_t flowkey_algx; 716 uint16_t *reta; 717 int rc; 718 719 rc = npc_rss_free_grp_get(npc, &rss_grp_idx); 720 /* RSS group :0 is not usable for flow rss action */ 721 if (rc < 0 || rss_grp_idx == 0) 722 return -ENOSPC; 723 724 for (i = 0; i < rss->queue_num; i++) { 725 if (rss->queue[i] >= nix->nb_rx_queues) { 726 plt_err("queue id > max number of queues"); 727 return -EINVAL; 728 } 729 } 730 731 *rss_grp = rss_grp_idx; 732 733 if (rss->key == NULL) { 734 roc_nix_rss_key_default_fill(roc_nix, key); 735 key_ptr = key; 736 } else { 737 key_ptr = rss->key; 738 } 739 740 roc_nix_rss_key_set(roc_nix, key_ptr); 741 742 /* If queue count passed in the rss action is less than 743 * HW configured reta size, replicate rss action reta 744 * across HW reta table. 745 */ 746 reta = nix->reta[rss_grp_idx]; 747 748 if (rss->queue_num > nix->reta_sz) { 749 plt_err("too many queues for RSS context"); 750 return -ENOTSUP; 751 } 752 753 for (i = 0; i < (nix->reta_sz / rss->queue_num); i++) 754 memcpy(reta + i * rss->queue_num, rss->queue, 755 sizeof(uint16_t) * rss->queue_num); 756 757 rem = nix->reta_sz % rss->queue_num; 758 if (rem) 759 memcpy(&reta[i * rss->queue_num], rss->queue, 760 rem * sizeof(uint16_t)); 761 762 rc = roc_nix_rss_reta_set(roc_nix, *rss_grp, reta); 763 if (rc) { 764 plt_err("Failed to init rss table rc = %d", rc); 765 return rc; 766 } 767 768 flowkey_cfg = roc_npc->flowkey_cfg_state; 769 770 rc = roc_nix_rss_flowkey_set(roc_nix, &flowkey_algx, flowkey_cfg, 771 *rss_grp, mcam_id); 772 if (rc) { 773 plt_err("Failed to set rss hash function rc = %d", rc); 774 return rc; 775 } 776 777 *alg_idx = flowkey_algx; 778 779 plt_bitmap_set(npc->rss_grp_entries, *rss_grp); 780 781 return 0; 782 } 783 784 int 785 npc_rss_action_program(struct roc_npc *roc_npc, 786 const struct roc_npc_action actions[], 787 struct roc_npc_flow *flow) 788 { 789 const struct roc_npc_action_rss *rss; 790 uint32_t rss_grp; 791 uint8_t alg_idx; 792 int rc; 793 794 for (; actions->type != ROC_NPC_ACTION_TYPE_END; actions++) { 795 if (actions->type == ROC_NPC_ACTION_TYPE_RSS) { 796 rss = (const struct roc_npc_action_rss *)actions->conf; 797 rc = npc_rss_action_configure(roc_npc, rss, &alg_idx, 798 &rss_grp, flow->mcam_id); 799 if (rc) 800 return rc; 801 802 flow->npc_action &= (~(0xfULL)); 803 flow->npc_action |= NIX_RX_ACTIONOP_RSS; 804 flow->npc_action |= 805 ((uint64_t)(alg_idx & NPC_RSS_ACT_ALG_MASK) 806 << NPC_RSS_ACT_ALG_OFFSET) | 807 ((uint64_t)(rss_grp & NPC_RSS_ACT_GRP_MASK) 808 << NPC_RSS_ACT_GRP_OFFSET); 809 break; 810 } 811 } 812 return 0; 813 } 814 815 int 816 roc_npc_mark_actions_get(struct roc_npc *roc_npc) 817 { 818 struct npc *npc = roc_npc_to_npc_priv(roc_npc); 819 820 return npc->mark_actions; 821 } 822 823 int 824 roc_npc_mark_actions_sub_return(struct roc_npc *roc_npc, uint32_t count) 825 { 826 struct npc *npc = roc_npc_to_npc_priv(roc_npc); 827 828 npc->mark_actions -= count; 829 return npc->mark_actions; 830 } 831 832 static int 833 npc_vtag_cfg_delete(struct roc_npc *roc_npc, struct roc_npc_flow *flow) 834 { 835 struct roc_nix *roc_nix = roc_npc->roc_nix; 836 struct nix_vtag_config *vtag_cfg; 837 struct nix_vtag_config_rsp *rsp; 838 struct mbox *mbox; 839 struct nix *nix; 840 int rc = 0; 841 842 union { 843 uint64_t reg; 844 struct nix_tx_vtag_action_s act; 845 } tx_vtag_action; 846 847 nix = roc_nix_to_nix_priv(roc_nix); 848 mbox = (&nix->dev)->mbox; 849 850 tx_vtag_action.reg = flow->vtag_action; 851 vtag_cfg = mbox_alloc_msg_nix_vtag_cfg(mbox); 852 853 if (vtag_cfg == NULL) 854 return -ENOSPC; 855 856 vtag_cfg->cfg_type = VTAG_TX; 857 vtag_cfg->vtag_size = NIX_VTAGSIZE_T4; 858 vtag_cfg->tx.vtag0_idx = tx_vtag_action.act.vtag0_def; 859 vtag_cfg->tx.free_vtag0 = true; 860 861 if (flow->vtag_insert_count == 2) { 862 vtag_cfg->tx.vtag1_idx = tx_vtag_action.act.vtag1_def; 863 vtag_cfg->tx.free_vtag1 = true; 864 } 865 866 rc = mbox_process_msg(mbox, (void *)&rsp); 867 if (rc) 868 return rc; 869 870 return 0; 871 } 872 873 static int 874 npc_vtag_insert_action_parse(const struct roc_npc_action actions[], 875 struct roc_npc_flow *flow, 876 struct npc_action_vtag_info *vlan_info, 877 int *parsed_cnt) 878 { 879 bool vlan_id_found = false, ethtype_found = false, pcp_found = false; 880 int count = 0; 881 882 *parsed_cnt = 0; 883 884 /* This function parses parameters of one VLAN. When a parameter is 885 * found repeated, it treats it as the end of first VLAN's parameters 886 * and returns. The caller calls again to parse the parameters of the 887 * second VLAN. 888 */ 889 890 for (; count < NPC_ACTION_MAX_VLAN_PARAMS; count++, actions++) { 891 if (actions->type == ROC_NPC_ACTION_TYPE_VLAN_INSERT) { 892 if (vlan_id_found) 893 return 0; 894 895 const struct roc_npc_action_of_set_vlan_vid *vtag = 896 (const struct roc_npc_action_of_set_vlan_vid *) 897 actions->conf; 898 899 vlan_info->vlan_id = plt_be_to_cpu_16(vtag->vlan_vid); 900 901 if (vlan_info->vlan_id > 0xfff) { 902 plt_err("Invalid vlan_id for set vlan action"); 903 return -EINVAL; 904 } 905 906 flow->vtag_insert_enabled = true; 907 (*parsed_cnt)++; 908 vlan_id_found = true; 909 } else if (actions->type == 910 ROC_NPC_ACTION_TYPE_VLAN_ETHTYPE_INSERT) { 911 if (ethtype_found) 912 return 0; 913 914 const struct roc_npc_action_of_push_vlan *ethtype = 915 (const struct roc_npc_action_of_push_vlan *) 916 actions->conf; 917 vlan_info->vlan_ethtype = 918 plt_be_to_cpu_16(ethtype->ethertype); 919 if (vlan_info->vlan_ethtype != ROC_ETHER_TYPE_VLAN && 920 vlan_info->vlan_ethtype != ROC_ETHER_TYPE_QINQ) { 921 plt_err("Invalid ethtype specified for push" 922 " vlan action"); 923 return -EINVAL; 924 } 925 flow->vtag_insert_enabled = true; 926 (*parsed_cnt)++; 927 ethtype_found = true; 928 } else if (actions->type == 929 ROC_NPC_ACTION_TYPE_VLAN_PCP_INSERT) { 930 if (pcp_found) 931 return 0; 932 const struct roc_npc_action_of_set_vlan_pcp *pcp = 933 (const struct roc_npc_action_of_set_vlan_pcp *) 934 actions->conf; 935 vlan_info->vlan_pcp = pcp->vlan_pcp; 936 if (vlan_info->vlan_pcp > 0x7) { 937 plt_err("Invalid PCP value for pcp action"); 938 return -EINVAL; 939 } 940 flow->vtag_insert_enabled = true; 941 (*parsed_cnt)++; 942 pcp_found = true; 943 } else { 944 return 0; 945 } 946 } 947 948 return 0; 949 } 950 951 static int 952 npc_vtag_insert_action_configure(struct mbox *mbox, struct roc_npc_flow *flow, 953 struct npc_action_vtag_info *vlan_info) 954 { 955 struct nix_vtag_config *vtag_cfg; 956 struct nix_vtag_config_rsp *rsp; 957 int rc = 0; 958 959 union { 960 uint64_t reg; 961 struct nix_tx_vtag_action_s act; 962 } tx_vtag_action; 963 964 vtag_cfg = mbox_alloc_msg_nix_vtag_cfg(mbox); 965 966 if (vtag_cfg == NULL) 967 return -ENOSPC; 968 969 vtag_cfg->cfg_type = VTAG_TX; 970 vtag_cfg->vtag_size = NIX_VTAGSIZE_T4; 971 vtag_cfg->tx.vtag0 = 972 ((vlan_info[0].vlan_ethtype << 16) | 973 (vlan_info[0].vlan_pcp << 13) | vlan_info[0].vlan_id); 974 975 vtag_cfg->tx.cfg_vtag0 = 1; 976 977 if (flow->vtag_insert_count == 2) { 978 vtag_cfg->tx.vtag1 = 979 ((vlan_info[1].vlan_ethtype << 16) | 980 (vlan_info[1].vlan_pcp << 13) | vlan_info[1].vlan_id); 981 982 vtag_cfg->tx.cfg_vtag1 = 1; 983 } 984 985 rc = mbox_process_msg(mbox, (void *)&rsp); 986 if (rc) 987 return rc; 988 989 if (rsp->vtag0_idx < 0 || 990 ((flow->vtag_insert_count == 2) && (rsp->vtag1_idx < 0))) { 991 plt_err("Failed to config TX VTAG action"); 992 return -EINVAL; 993 } 994 995 tx_vtag_action.reg = 0; 996 tx_vtag_action.act.vtag0_def = rsp->vtag0_idx; 997 tx_vtag_action.act.vtag0_lid = NPC_LID_LA; 998 tx_vtag_action.act.vtag0_op = NIX_TX_VTAGOP_INSERT; 999 tx_vtag_action.act.vtag0_relptr = NIX_TX_VTAGACTION_VTAG0_RELPTR; 1000 1001 if (flow->vtag_insert_count == 2) { 1002 tx_vtag_action.act.vtag1_def = rsp->vtag1_idx; 1003 tx_vtag_action.act.vtag1_lid = NPC_LID_LA; 1004 tx_vtag_action.act.vtag1_op = NIX_TX_VTAGOP_INSERT; 1005 /* NIX_TX_VTAG_ACTION_S 1006 * If Vtag 0 is inserted, hardware adjusts the Vtag 1 byte 1007 * offset accordingly. Thus, if the two offsets are equal in 1008 * the structure, hardware inserts Vtag 1 immediately after 1009 * Vtag 0 in the packet. 1010 */ 1011 tx_vtag_action.act.vtag1_relptr = 1012 NIX_TX_VTAGACTION_VTAG0_RELPTR; 1013 } 1014 1015 flow->vtag_action = tx_vtag_action.reg; 1016 1017 return 0; 1018 } 1019 1020 static int 1021 npc_vtag_strip_action_configure(struct mbox *mbox, 1022 const struct roc_npc_action actions[], 1023 struct roc_npc_flow *flow, int *strip_cnt) 1024 { 1025 struct nix_vtag_config *vtag_cfg; 1026 uint64_t rx_vtag_action = 0; 1027 int count = 0, rc = 0; 1028 1029 *strip_cnt = 0; 1030 1031 for (; count < NPC_ACTION_MAX_VLANS_STRIPPED; count++, actions++) { 1032 if (actions->type == ROC_NPC_ACTION_TYPE_VLAN_STRIP) 1033 (*strip_cnt)++; 1034 } 1035 1036 vtag_cfg = mbox_alloc_msg_nix_vtag_cfg(mbox); 1037 1038 if (vtag_cfg == NULL) 1039 return -ENOSPC; 1040 1041 vtag_cfg->cfg_type = VTAG_RX; 1042 vtag_cfg->rx.strip_vtag = 1; 1043 /* Always capture */ 1044 vtag_cfg->rx.capture_vtag = 1; 1045 vtag_cfg->vtag_size = NIX_VTAGSIZE_T4; 1046 vtag_cfg->rx.vtag_type = 0; 1047 1048 rc = mbox_process(mbox); 1049 if (rc) 1050 return rc; 1051 1052 rx_vtag_action |= (NIX_RX_VTAGACTION_VTAG_VALID << 15); 1053 rx_vtag_action |= ((uint64_t)NPC_LID_LB << 8); 1054 rx_vtag_action |= NIX_RX_VTAGACTION_VTAG0_RELPTR; 1055 1056 if (*strip_cnt == 2) { 1057 rx_vtag_action |= (NIX_RX_VTAGACTION_VTAG_VALID << 47); 1058 rx_vtag_action |= ((uint64_t)NPC_LID_LB << 40); 1059 rx_vtag_action |= NIX_RX_VTAGACTION_VTAG0_RELPTR << 32; 1060 } 1061 flow->vtag_action = rx_vtag_action; 1062 1063 return 0; 1064 } 1065 1066 static int 1067 npc_vtag_action_program(struct roc_npc *roc_npc, 1068 const struct roc_npc_action actions[], 1069 struct roc_npc_flow *flow) 1070 { 1071 bool vlan_strip_parsed = false, vlan_insert_parsed = false; 1072 const struct roc_npc_action *insert_actions; 1073 struct roc_nix *roc_nix = roc_npc->roc_nix; 1074 struct npc_action_vtag_info vlan_info[2]; 1075 int parsed_cnt = 0, strip_cnt = 0; 1076 int tot_vlan_params = 0; 1077 struct mbox *mbox; 1078 struct nix *nix; 1079 int i, rc; 1080 1081 nix = roc_nix_to_nix_priv(roc_nix); 1082 mbox = (&nix->dev)->mbox; 1083 1084 memset(vlan_info, 0, sizeof(vlan_info)); 1085 1086 flow->vtag_insert_enabled = false; 1087 1088 for (; actions->type != ROC_NPC_ACTION_TYPE_END; actions++) { 1089 if (actions->type == ROC_NPC_ACTION_TYPE_VLAN_STRIP) { 1090 if (vlan_strip_parsed) { 1091 plt_err("Incorrect VLAN strip actions"); 1092 return -EINVAL; 1093 } 1094 rc = npc_vtag_strip_action_configure(mbox, actions, 1095 flow, &strip_cnt); 1096 if (rc) 1097 return rc; 1098 1099 if (strip_cnt == 2) 1100 actions++; 1101 1102 vlan_strip_parsed = true; 1103 } else if (actions->type == ROC_NPC_ACTION_TYPE_VLAN_INSERT || 1104 actions->type == 1105 ROC_NPC_ACTION_TYPE_VLAN_ETHTYPE_INSERT || 1106 actions->type == 1107 ROC_NPC_ACTION_TYPE_VLAN_PCP_INSERT) { 1108 if (vlan_insert_parsed) { 1109 plt_err("Incorrect VLAN insert actions"); 1110 return -EINVAL; 1111 } 1112 1113 insert_actions = actions; 1114 1115 for (i = 0; i < 2; i++) { 1116 rc = npc_vtag_insert_action_parse( 1117 insert_actions, flow, &vlan_info[i], 1118 &parsed_cnt); 1119 1120 if (rc) 1121 return rc; 1122 1123 if (parsed_cnt) { 1124 insert_actions += parsed_cnt; 1125 tot_vlan_params += parsed_cnt; 1126 flow->vtag_insert_count++; 1127 } 1128 } 1129 actions += tot_vlan_params - 1; 1130 vlan_insert_parsed = true; 1131 } 1132 } 1133 1134 if (flow->vtag_insert_enabled) { 1135 rc = npc_vtag_insert_action_configure(mbox, flow, vlan_info); 1136 1137 if (rc) 1138 return rc; 1139 } 1140 return 0; 1141 } 1142 1143 struct roc_npc_flow * 1144 roc_npc_flow_create(struct roc_npc *roc_npc, const struct roc_npc_attr *attr, 1145 const struct roc_npc_item_info pattern[], 1146 const struct roc_npc_action actions[], int *errcode) 1147 { 1148 struct npc *npc = roc_npc_to_npc_priv(roc_npc); 1149 struct roc_npc_flow *flow, *flow_iter; 1150 struct npc_parse_state parse_state; 1151 struct npc_flow_list *list; 1152 int rc; 1153 1154 npc->channel = roc_npc->channel; 1155 1156 flow = plt_zmalloc(sizeof(*flow), 0); 1157 if (flow == NULL) { 1158 *errcode = NPC_ERR_NO_MEM; 1159 return NULL; 1160 } 1161 memset(flow, 0, sizeof(*flow)); 1162 1163 rc = npc_parse_rule(roc_npc, attr, pattern, actions, flow, 1164 &parse_state); 1165 if (rc != 0) { 1166 *errcode = rc; 1167 goto err_exit; 1168 } 1169 1170 rc = npc_vtag_action_program(roc_npc, actions, flow); 1171 if (rc != 0) { 1172 *errcode = rc; 1173 goto err_exit; 1174 } 1175 1176 parse_state.is_vf = !roc_nix_is_pf(roc_npc->roc_nix); 1177 1178 rc = npc_program_mcam(npc, &parse_state, 1); 1179 if (rc != 0) { 1180 *errcode = rc; 1181 goto err_exit; 1182 } 1183 1184 rc = npc_rss_action_program(roc_npc, actions, flow); 1185 if (rc != 0) { 1186 *errcode = rc; 1187 goto set_rss_failed; 1188 } 1189 1190 list = &npc->flow_list[flow->priority]; 1191 /* List in ascending order of mcam entries */ 1192 TAILQ_FOREACH(flow_iter, list, next) { 1193 if (flow_iter->mcam_id > flow->mcam_id) { 1194 TAILQ_INSERT_BEFORE(flow_iter, flow, next); 1195 return flow; 1196 } 1197 } 1198 1199 TAILQ_INSERT_TAIL(list, flow, next); 1200 return flow; 1201 1202 set_rss_failed: 1203 rc = npc_mcam_free_entry(npc, flow->mcam_id); 1204 if (rc != 0) { 1205 *errcode = rc; 1206 plt_free(flow); 1207 return NULL; 1208 } 1209 err_exit: 1210 plt_free(flow); 1211 return NULL; 1212 } 1213 1214 int 1215 npc_rss_group_free(struct npc *npc, struct roc_npc_flow *flow) 1216 { 1217 uint32_t rss_grp; 1218 1219 if ((flow->npc_action & 0xF) == NIX_RX_ACTIONOP_RSS) { 1220 rss_grp = (flow->npc_action >> NPC_RSS_ACT_GRP_OFFSET) & 1221 NPC_RSS_ACT_GRP_MASK; 1222 if (rss_grp == 0 || rss_grp >= npc->rss_grps) 1223 return -EINVAL; 1224 1225 plt_bitmap_clear(npc->rss_grp_entries, rss_grp); 1226 } 1227 1228 return 0; 1229 } 1230 1231 int 1232 roc_npc_flow_destroy(struct roc_npc *roc_npc, struct roc_npc_flow *flow) 1233 { 1234 struct npc *npc = roc_npc_to_npc_priv(roc_npc); 1235 int rc; 1236 1237 rc = npc_rss_group_free(npc, flow); 1238 if (rc != 0) { 1239 plt_err("Failed to free rss action rc = %d", rc); 1240 return rc; 1241 } 1242 1243 if (flow->vtag_insert_enabled) { 1244 rc = npc_vtag_cfg_delete(roc_npc, flow); 1245 if (rc != 0) 1246 return rc; 1247 } 1248 1249 rc = npc_mcam_free_entry(npc, flow->mcam_id); 1250 if (rc != 0) 1251 return rc; 1252 1253 TAILQ_REMOVE(&npc->flow_list[flow->priority], flow, next); 1254 1255 npc_delete_prio_list_entry(npc, flow); 1256 1257 plt_free(flow); 1258 return 0; 1259 } 1260 1261 void 1262 roc_npc_flow_dump(FILE *file, struct roc_npc *roc_npc) 1263 { 1264 struct npc *npc = roc_npc_to_npc_priv(roc_npc); 1265 struct roc_npc_flow *flow_iter; 1266 struct npc_flow_list *list; 1267 uint32_t max_prio, i; 1268 1269 max_prio = npc->flow_max_priority; 1270 1271 for (i = 0; i < max_prio; i++) { 1272 list = &npc->flow_list[i]; 1273 1274 /* List in ascending order of mcam entries */ 1275 TAILQ_FOREACH(flow_iter, list, next) { 1276 roc_npc_flow_mcam_dump(file, roc_npc, flow_iter); 1277 } 1278 } 1279 } 1280 1281 int 1282 roc_npc_mcam_merge_base_steering_rule(struct roc_npc *roc_npc, 1283 struct roc_npc_flow *flow) 1284 { 1285 struct npc_mcam_read_base_rule_rsp *base_rule_rsp; 1286 struct npc *npc = roc_npc_to_npc_priv(roc_npc); 1287 struct mcam_entry *base_entry; 1288 int idx, rc; 1289 1290 if (roc_nix_is_pf(roc_npc->roc_nix)) 1291 return 0; 1292 1293 (void)mbox_alloc_msg_npc_read_base_steer_rule(npc->mbox); 1294 rc = mbox_process_msg(npc->mbox, (void *)&base_rule_rsp); 1295 if (rc) { 1296 plt_err("Failed to fetch VF's base MCAM entry"); 1297 return rc; 1298 } 1299 base_entry = &base_rule_rsp->entry_data; 1300 for (idx = 0; idx < ROC_NPC_MAX_MCAM_WIDTH_DWORDS; idx++) { 1301 flow->mcam_data[idx] |= base_entry->kw[idx]; 1302 flow->mcam_mask[idx] |= base_entry->kw_mask[idx]; 1303 } 1304 1305 return 0; 1306 } 1307