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