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_mcam_free_counter(struct roc_npc *roc_npc, uint16_t ctr_id) 10 { 11 struct npc *npc = roc_npc_to_npc_priv(roc_npc); 12 13 return npc_mcam_free_counter(npc, ctr_id); 14 } 15 16 int 17 roc_npc_mcam_read_counter(struct roc_npc *roc_npc, uint32_t ctr_id, 18 uint64_t *count) 19 { 20 struct npc *npc = roc_npc_to_npc_priv(roc_npc); 21 22 return npc_mcam_read_counter(npc, ctr_id, count); 23 } 24 25 int 26 roc_npc_mcam_clear_counter(struct roc_npc *roc_npc, uint32_t ctr_id) 27 { 28 struct npc *npc = roc_npc_to_npc_priv(roc_npc); 29 30 return npc_mcam_clear_counter(npc, ctr_id); 31 } 32 33 int 34 roc_npc_mcam_free_entry(struct roc_npc *roc_npc, uint32_t entry) 35 { 36 struct npc *npc = roc_npc_to_npc_priv(roc_npc); 37 38 return npc_mcam_free_entry(npc, entry); 39 } 40 41 int 42 roc_npc_mcam_free_all_resources(struct roc_npc *roc_npc) 43 { 44 struct npc *npc = roc_npc_to_npc_priv(roc_npc); 45 46 return npc_flow_free_all_resources(npc); 47 } 48 49 int 50 roc_npc_mcam_alloc_entries(struct roc_npc *roc_npc, int ref_entry, 51 int *alloc_entry, int req_count, int priority, 52 int *resp_count) 53 { 54 struct npc *npc = roc_npc_to_npc_priv(roc_npc); 55 56 return npc_mcam_alloc_entries(npc, ref_entry, alloc_entry, req_count, 57 priority, resp_count); 58 } 59 60 int 61 roc_npc_mcam_alloc_entry(struct roc_npc *roc_npc, struct roc_npc_flow *mcam, 62 struct roc_npc_flow *ref_mcam, int prio, 63 int *resp_count) 64 { 65 struct npc *npc = roc_npc_to_npc_priv(roc_npc); 66 67 return npc_mcam_alloc_entry(npc, mcam, ref_mcam, prio, resp_count); 68 } 69 70 int 71 roc_npc_mcam_ena_dis_entry(struct roc_npc *roc_npc, struct roc_npc_flow *mcam, 72 bool enable) 73 { 74 struct npc *npc = roc_npc_to_npc_priv(roc_npc); 75 76 return npc_mcam_ena_dis_entry(npc, mcam, enable); 77 } 78 79 int 80 roc_npc_mcam_write_entry(struct roc_npc *roc_npc, struct roc_npc_flow *mcam) 81 { 82 struct npc *npc = roc_npc_to_npc_priv(roc_npc); 83 84 return npc_mcam_write_entry(npc, mcam); 85 } 86 87 int 88 roc_npc_get_low_priority_mcam(struct roc_npc *roc_npc) 89 { 90 struct npc *npc = roc_npc_to_npc_priv(roc_npc); 91 92 if (roc_model_is_cn10k()) 93 return (npc->mcam_entries - NPC_MCAME_RESVD_10XX - 1); 94 else 95 return (npc->mcam_entries - NPC_MCAME_RESVD_9XXX - 1); 96 } 97 98 static int 99 npc_mcam_tot_entries(void) 100 { 101 /* FIXME: change to reading in AF from NPC_AF_CONST1/2 102 * MCAM_BANK_DEPTH(_EXT) * MCAM_BANKS 103 */ 104 if (roc_model_is_cn10k()) 105 return 16 * 1024; /* MCAM_BANKS = 4, BANK_DEPTH_EXT = 4096 */ 106 else 107 return 4 * 1024; /* MCAM_BANKS = 4, BANK_DEPTH_EXT = 1024 */ 108 } 109 110 const char * 111 roc_npc_profile_name_get(struct roc_npc *roc_npc) 112 { 113 struct npc *npc = roc_npc_to_npc_priv(roc_npc); 114 115 return (char *)npc->profile_name; 116 } 117 118 int 119 roc_npc_init(struct roc_npc *roc_npc) 120 { 121 uint8_t *mem = NULL, *nix_mem = NULL, *npc_mem = NULL; 122 struct nix *nix = roc_nix_to_nix_priv(roc_npc->roc_nix); 123 struct npc *npc = roc_npc_to_npc_priv(roc_npc); 124 uint32_t bmap_sz; 125 int rc = 0, idx; 126 size_t sz; 127 128 PLT_STATIC_ASSERT(sizeof(struct npc) <= ROC_NPC_MEM_SZ); 129 130 memset(npc, 0, sizeof(*npc)); 131 npc->mbox = (&nix->dev)->mbox; 132 roc_npc->channel = nix->rx_chan_base; 133 roc_npc->pf_func = (&nix->dev)->pf_func; 134 npc->channel = roc_npc->channel; 135 npc->pf_func = roc_npc->pf_func; 136 npc->flow_max_priority = roc_npc->flow_max_priority; 137 npc->switch_header_type = roc_npc->switch_header_type; 138 npc->flow_prealloc_size = roc_npc->flow_prealloc_size; 139 140 if (npc->mbox == NULL) 141 return NPC_ERR_PARAM; 142 143 rc = npc_mcam_fetch_kex_cfg(npc); 144 if (rc) 145 goto done; 146 147 roc_npc->kex_capability = npc_get_kex_capability(npc); 148 roc_npc->rx_parse_nibble = npc->keyx_supp_nmask[NPC_MCAM_RX]; 149 150 npc->mark_actions = 0; 151 152 npc->mcam_entries = npc_mcam_tot_entries() >> npc->keyw[NPC_MCAM_RX]; 153 154 /* Free, free_rev, live and live_rev entries */ 155 bmap_sz = plt_bitmap_get_memory_footprint(npc->mcam_entries); 156 mem = plt_zmalloc(4 * bmap_sz * npc->flow_max_priority, 0); 157 if (mem == NULL) { 158 plt_err("Bmap alloc failed"); 159 rc = NPC_ERR_NO_MEM; 160 return rc; 161 } 162 163 sz = npc->flow_max_priority * sizeof(struct npc_mcam_ents_info); 164 npc->flow_entry_info = plt_zmalloc(sz, 0); 165 if (npc->flow_entry_info == NULL) { 166 plt_err("flow_entry_info alloc failed"); 167 rc = NPC_ERR_NO_MEM; 168 goto done; 169 } 170 171 sz = npc->flow_max_priority * sizeof(struct plt_bitmap *); 172 npc->free_entries = plt_zmalloc(sz, 0); 173 if (npc->free_entries == NULL) { 174 plt_err("free_entries alloc failed"); 175 rc = NPC_ERR_NO_MEM; 176 goto done; 177 } 178 179 sz = npc->flow_max_priority * sizeof(struct plt_bitmap *); 180 npc->free_entries_rev = plt_zmalloc(sz, 0); 181 if (npc->free_entries_rev == NULL) { 182 plt_err("free_entries_rev alloc failed"); 183 rc = NPC_ERR_NO_MEM; 184 goto done; 185 } 186 187 sz = npc->flow_max_priority * sizeof(struct plt_bitmap *); 188 npc->live_entries = plt_zmalloc(sz, 0); 189 if (npc->live_entries == NULL) { 190 plt_err("live_entries alloc failed"); 191 rc = NPC_ERR_NO_MEM; 192 goto done; 193 } 194 195 sz = npc->flow_max_priority * sizeof(struct plt_bitmap *); 196 npc->live_entries_rev = plt_zmalloc(sz, 0); 197 if (npc->live_entries_rev == NULL) { 198 plt_err("live_entries_rev alloc failed"); 199 rc = NPC_ERR_NO_MEM; 200 goto done; 201 } 202 203 sz = npc->flow_max_priority * sizeof(struct npc_flow_list); 204 npc->flow_list = plt_zmalloc(sz, 0); 205 if (npc->flow_list == NULL) { 206 plt_err("flow_list alloc failed"); 207 rc = NPC_ERR_NO_MEM; 208 goto done; 209 } 210 211 npc_mem = mem; 212 for (idx = 0; idx < npc->flow_max_priority; idx++) { 213 TAILQ_INIT(&npc->flow_list[idx]); 214 215 npc->free_entries[idx] = 216 plt_bitmap_init(npc->mcam_entries, mem, bmap_sz); 217 mem += bmap_sz; 218 219 npc->free_entries_rev[idx] = 220 plt_bitmap_init(npc->mcam_entries, mem, bmap_sz); 221 mem += bmap_sz; 222 223 npc->live_entries[idx] = 224 plt_bitmap_init(npc->mcam_entries, mem, bmap_sz); 225 mem += bmap_sz; 226 227 npc->live_entries_rev[idx] = 228 plt_bitmap_init(npc->mcam_entries, mem, bmap_sz); 229 mem += bmap_sz; 230 231 npc->flow_entry_info[idx].free_ent = 0; 232 npc->flow_entry_info[idx].live_ent = 0; 233 npc->flow_entry_info[idx].max_id = 0; 234 npc->flow_entry_info[idx].min_id = ~(0); 235 } 236 237 npc->rss_grps = NPC_RSS_GRPS; 238 239 bmap_sz = plt_bitmap_get_memory_footprint(npc->rss_grps); 240 nix_mem = plt_zmalloc(bmap_sz, 0); 241 if (nix_mem == NULL) { 242 plt_err("Bmap alloc failed"); 243 rc = NPC_ERR_NO_MEM; 244 goto done; 245 } 246 247 npc->rss_grp_entries = plt_bitmap_init(npc->rss_grps, nix_mem, bmap_sz); 248 249 if (!npc->rss_grp_entries) { 250 plt_err("bitmap init failed"); 251 rc = NPC_ERR_NO_MEM; 252 goto done; 253 } 254 255 /* Group 0 will be used for RSS, 256 * 1 -7 will be used for npc_flow RSS action 257 */ 258 plt_bitmap_set(npc->rss_grp_entries, 0); 259 260 return rc; 261 262 done: 263 if (npc->flow_list) 264 plt_free(npc->flow_list); 265 if (npc->live_entries_rev) 266 plt_free(npc->live_entries_rev); 267 if (npc->live_entries) 268 plt_free(npc->live_entries); 269 if (npc->free_entries_rev) 270 plt_free(npc->free_entries_rev); 271 if (npc->free_entries) 272 plt_free(npc->free_entries); 273 if (npc->flow_entry_info) 274 plt_free(npc->flow_entry_info); 275 if (npc_mem) 276 plt_free(npc_mem); 277 return rc; 278 } 279 280 int 281 roc_npc_fini(struct roc_npc *roc_npc) 282 { 283 struct npc *npc = roc_npc_to_npc_priv(roc_npc); 284 int rc; 285 286 rc = npc_flow_free_all_resources(npc); 287 if (rc) { 288 plt_err("Error when deleting NPC MCAM entries, counters"); 289 return rc; 290 } 291 292 if (npc->flow_list) { 293 plt_free(npc->flow_list); 294 npc->flow_list = NULL; 295 } 296 297 if (npc->live_entries_rev) { 298 plt_free(npc->live_entries_rev); 299 npc->live_entries_rev = NULL; 300 } 301 302 if (npc->live_entries) { 303 plt_free(npc->live_entries); 304 npc->live_entries = NULL; 305 } 306 307 if (npc->free_entries_rev) { 308 plt_free(npc->free_entries_rev); 309 npc->free_entries_rev = NULL; 310 } 311 312 if (npc->free_entries) { 313 plt_free(npc->free_entries); 314 npc->free_entries = NULL; 315 } 316 317 if (npc->flow_entry_info) { 318 plt_free(npc->flow_entry_info); 319 npc->flow_entry_info = NULL; 320 } 321 322 return 0; 323 } 324 325 static int 326 npc_parse_actions(struct npc *npc, const struct roc_npc_attr *attr, 327 const struct roc_npc_action actions[], 328 struct roc_npc_flow *flow) 329 { 330 const struct roc_npc_action_mark *act_mark; 331 const struct roc_npc_action_queue *act_q; 332 const struct roc_npc_action_vf *vf_act; 333 int sel_act, req_act = 0; 334 uint16_t pf_func, vf_id; 335 int errcode = 0; 336 int mark = 0; 337 int rq = 0; 338 339 /* Initialize actions */ 340 flow->ctr_id = NPC_COUNTER_NONE; 341 pf_func = npc->pf_func; 342 343 for (; actions->type != ROC_NPC_ACTION_TYPE_END; actions++) { 344 switch (actions->type) { 345 case ROC_NPC_ACTION_TYPE_VOID: 346 break; 347 case ROC_NPC_ACTION_TYPE_MARK: 348 act_mark = (const struct roc_npc_action_mark *) 349 actions->conf; 350 if (act_mark->id > (NPC_FLOW_FLAG_VAL - 2)) { 351 plt_err("mark value must be < 0xfffe"); 352 goto err_exit; 353 } 354 mark = act_mark->id + 1; 355 req_act |= ROC_NPC_ACTION_TYPE_MARK; 356 npc->mark_actions += 1; 357 break; 358 359 case ROC_NPC_ACTION_TYPE_FLAG: 360 mark = NPC_FLOW_FLAG_VAL; 361 req_act |= ROC_NPC_ACTION_TYPE_FLAG; 362 npc->mark_actions += 1; 363 break; 364 365 case ROC_NPC_ACTION_TYPE_COUNT: 366 /* Indicates, need a counter */ 367 flow->ctr_id = 1; 368 req_act |= ROC_NPC_ACTION_TYPE_COUNT; 369 break; 370 371 case ROC_NPC_ACTION_TYPE_DROP: 372 req_act |= ROC_NPC_ACTION_TYPE_DROP; 373 break; 374 375 case ROC_NPC_ACTION_TYPE_PF: 376 req_act |= ROC_NPC_ACTION_TYPE_PF; 377 pf_func &= (0xfc00); 378 break; 379 380 case ROC_NPC_ACTION_TYPE_VF: 381 vf_act = 382 (const struct roc_npc_action_vf *)actions->conf; 383 req_act |= ROC_NPC_ACTION_TYPE_VF; 384 vf_id = vf_act->id & RVU_PFVF_FUNC_MASK; 385 pf_func &= (0xfc00); 386 pf_func = (pf_func | (vf_id + 1)); 387 break; 388 389 case ROC_NPC_ACTION_TYPE_QUEUE: 390 act_q = (const struct roc_npc_action_queue *) 391 actions->conf; 392 rq = act_q->index; 393 req_act |= ROC_NPC_ACTION_TYPE_QUEUE; 394 break; 395 396 case ROC_NPC_ACTION_TYPE_RSS: 397 req_act |= ROC_NPC_ACTION_TYPE_RSS; 398 break; 399 400 case ROC_NPC_ACTION_TYPE_SEC: 401 /* Assumes user has already configured security 402 * session for this flow. Associated conf is 403 * opaque. When security is implemented, 404 * we need to verify that for specified security 405 * session: 406 * action_type == 407 * NPC_SECURITY_ACTION_TYPE_INLINE_PROTOCOL && 408 * session_protocol == 409 * NPC_SECURITY_PROTOCOL_IPSEC 410 * 411 * RSS is not supported with inline ipsec. Get the 412 * rq from associated conf, or make 413 * ROC_NPC_ACTION_TYPE_QUEUE compulsory with this 414 * action. 415 * Currently, rq = 0 is assumed. 416 */ 417 req_act |= ROC_NPC_ACTION_TYPE_SEC; 418 rq = 0; 419 break; 420 default: 421 errcode = NPC_ERR_ACTION_NOTSUP; 422 goto err_exit; 423 } 424 } 425 426 /* Check if actions specified are compatible */ 427 if (attr->egress) { 428 /* Only DROP/COUNT is supported */ 429 if (!(req_act & ROC_NPC_ACTION_TYPE_DROP)) { 430 errcode = NPC_ERR_ACTION_NOTSUP; 431 goto err_exit; 432 } else if (req_act & ~(ROC_NPC_ACTION_TYPE_DROP | 433 ROC_NPC_ACTION_TYPE_COUNT)) { 434 errcode = NPC_ERR_ACTION_NOTSUP; 435 goto err_exit; 436 } 437 flow->npc_action = NIX_TX_ACTIONOP_DROP; 438 goto set_pf_func; 439 } 440 441 /* We have already verified the attr, this is ingress. 442 * - Exactly one terminating action is supported 443 * - Exactly one of MARK or FLAG is supported 444 * - If terminating action is DROP, only count is valid. 445 */ 446 sel_act = req_act & NPC_ACTION_TERM; 447 if ((sel_act & (sel_act - 1)) != 0) { 448 errcode = NPC_ERR_ACTION_NOTSUP; 449 goto err_exit; 450 } 451 452 if (req_act & ROC_NPC_ACTION_TYPE_DROP) { 453 sel_act = req_act & ~ROC_NPC_ACTION_TYPE_COUNT; 454 if ((sel_act & (sel_act - 1)) != 0) { 455 errcode = NPC_ERR_ACTION_NOTSUP; 456 goto err_exit; 457 } 458 } 459 460 if ((req_act & (ROC_NPC_ACTION_TYPE_FLAG | ROC_NPC_ACTION_TYPE_MARK)) == 461 (ROC_NPC_ACTION_TYPE_FLAG | ROC_NPC_ACTION_TYPE_MARK)) { 462 errcode = NPC_ERR_ACTION_NOTSUP; 463 goto err_exit; 464 } 465 466 /* Set NIX_RX_ACTIONOP */ 467 if (req_act & (ROC_NPC_ACTION_TYPE_PF | ROC_NPC_ACTION_TYPE_VF)) { 468 flow->npc_action = NIX_RX_ACTIONOP_UCAST; 469 if (req_act & ROC_NPC_ACTION_TYPE_QUEUE) 470 flow->npc_action |= (uint64_t)rq << 20; 471 } else if (req_act & ROC_NPC_ACTION_TYPE_DROP) { 472 flow->npc_action = NIX_RX_ACTIONOP_DROP; 473 } else if (req_act & ROC_NPC_ACTION_TYPE_QUEUE) { 474 flow->npc_action = NIX_RX_ACTIONOP_UCAST; 475 flow->npc_action |= (uint64_t)rq << 20; 476 } else if (req_act & ROC_NPC_ACTION_TYPE_RSS) { 477 flow->npc_action = NIX_RX_ACTIONOP_UCAST; 478 } else if (req_act & ROC_NPC_ACTION_TYPE_SEC) { 479 flow->npc_action = NIX_RX_ACTIONOP_UCAST_IPSEC; 480 flow->npc_action |= (uint64_t)rq << 20; 481 } else if (req_act & 482 (ROC_NPC_ACTION_TYPE_FLAG | ROC_NPC_ACTION_TYPE_MARK)) { 483 flow->npc_action = NIX_RX_ACTIONOP_UCAST; 484 } else if (req_act & ROC_NPC_ACTION_TYPE_COUNT) { 485 /* Keep ROC_NPC_ACTION_TYPE_COUNT_ACT always at the end 486 * This is default action, when user specify only 487 * COUNT ACTION 488 */ 489 flow->npc_action = NIX_RX_ACTIONOP_UCAST; 490 } else { 491 /* Should never reach here */ 492 errcode = NPC_ERR_ACTION_NOTSUP; 493 goto err_exit; 494 } 495 496 if (mark) 497 flow->npc_action |= (uint64_t)mark << 40; 498 499 set_pf_func: 500 /* Ideally AF must ensure that correct pf_func is set */ 501 flow->npc_action |= (uint64_t)pf_func << 4; 502 503 return 0; 504 505 err_exit: 506 return errcode; 507 } 508 509 typedef int (*npc_parse_stage_func_t)(struct npc_parse_state *pst); 510 511 static int 512 npc_parse_pattern(struct npc *npc, const struct roc_npc_item_info pattern[], 513 struct roc_npc_flow *flow, struct npc_parse_state *pst) 514 { 515 npc_parse_stage_func_t parse_stage_funcs[] = { 516 npc_parse_meta_items, npc_parse_cpt_hdr, npc_parse_higig2_hdr, 517 npc_parse_la, npc_parse_lb, npc_parse_lc, 518 npc_parse_ld, npc_parse_le, npc_parse_lf, 519 npc_parse_lg, npc_parse_lh, 520 }; 521 uint8_t layer = 0; 522 int key_offset; 523 int rc; 524 525 if (pattern == NULL) 526 return NPC_ERR_PARAM; 527 528 memset(pst, 0, sizeof(*pst)); 529 pst->npc = npc; 530 pst->flow = flow; 531 532 /* Use integral byte offset */ 533 key_offset = pst->npc->keyx_len[flow->nix_intf]; 534 key_offset = (key_offset + 7) / 8; 535 536 /* Location where LDATA would begin */ 537 pst->mcam_data = (uint8_t *)flow->mcam_data; 538 pst->mcam_mask = (uint8_t *)flow->mcam_mask; 539 540 while (pattern->type != ROC_NPC_ITEM_TYPE_END && 541 layer < PLT_DIM(parse_stage_funcs)) { 542 /* Skip place-holders */ 543 pattern = npc_parse_skip_void_and_any_items(pattern); 544 545 pst->pattern = pattern; 546 rc = parse_stage_funcs[layer](pst); 547 if (rc != 0) 548 return rc; 549 550 layer++; 551 552 /* 553 * Parse stage function sets pst->pattern to 554 * 1 past the last item it consumed. 555 */ 556 pattern = pst->pattern; 557 558 if (pst->terminate) 559 break; 560 } 561 562 /* Skip trailing place-holders */ 563 pattern = npc_parse_skip_void_and_any_items(pattern); 564 565 /* Are there more items than what we can handle? */ 566 if (pattern->type != ROC_NPC_ITEM_TYPE_END) 567 return NPC_ERR_PATTERN_NOTSUP; 568 569 return 0; 570 } 571 572 static int 573 npc_parse_attr(struct npc *npc, const struct roc_npc_attr *attr, 574 struct roc_npc_flow *flow) 575 { 576 if (attr == NULL) 577 return NPC_ERR_PARAM; 578 else if (attr->priority >= npc->flow_max_priority) 579 return NPC_ERR_PARAM; 580 else if ((!attr->egress && !attr->ingress) || 581 (attr->egress && attr->ingress)) 582 return NPC_ERR_PARAM; 583 584 if (attr->ingress) 585 flow->nix_intf = ROC_NPC_INTF_RX; 586 else 587 flow->nix_intf = ROC_NPC_INTF_TX; 588 589 flow->priority = attr->priority; 590 return 0; 591 } 592 593 static int 594 npc_parse_rule(struct npc *npc, const struct roc_npc_attr *attr, 595 const struct roc_npc_item_info pattern[], 596 const struct roc_npc_action actions[], struct roc_npc_flow *flow, 597 struct npc_parse_state *pst) 598 { 599 int err; 600 601 /* Check attr */ 602 err = npc_parse_attr(npc, attr, flow); 603 if (err) 604 return err; 605 606 /* Check pattern */ 607 err = npc_parse_pattern(npc, pattern, flow, pst); 608 if (err) 609 return err; 610 611 /* Check action */ 612 err = npc_parse_actions(npc, attr, actions, flow); 613 if (err) 614 return err; 615 return 0; 616 } 617 618 int 619 roc_npc_flow_parse(struct roc_npc *roc_npc, const struct roc_npc_attr *attr, 620 const struct roc_npc_item_info pattern[], 621 const struct roc_npc_action actions[], 622 struct roc_npc_flow *flow) 623 { 624 struct npc *npc = roc_npc_to_npc_priv(roc_npc); 625 struct npc_parse_state parse_state = {0}; 626 int rc; 627 628 rc = npc_parse_rule(npc, attr, pattern, actions, flow, &parse_state); 629 if (rc) 630 return rc; 631 632 parse_state.is_vf = !roc_nix_is_pf(roc_npc->roc_nix); 633 634 return npc_program_mcam(npc, &parse_state, 0); 635 } 636 637 int 638 npc_rss_free_grp_get(struct npc *npc, uint32_t *pos) 639 { 640 struct plt_bitmap *bmap = npc->rss_grp_entries; 641 642 for (*pos = 0; *pos < ROC_NIX_RSS_GRPS; ++*pos) { 643 if (!plt_bitmap_get(bmap, *pos)) 644 break; 645 } 646 return *pos < ROC_NIX_RSS_GRPS ? 0 : -1; 647 } 648 649 int 650 npc_rss_action_configure(struct roc_npc *roc_npc, 651 const struct roc_npc_action_rss *rss, uint8_t *alg_idx, 652 uint32_t *rss_grp, uint32_t mcam_id) 653 { 654 struct npc *npc = roc_npc_to_npc_priv(roc_npc); 655 struct roc_nix *roc_nix = roc_npc->roc_nix; 656 struct nix *nix = roc_nix_to_nix_priv(roc_nix); 657 uint32_t flowkey_cfg, rss_grp_idx, i, rem; 658 uint8_t key[ROC_NIX_RSS_KEY_LEN]; 659 const uint8_t *key_ptr; 660 uint8_t flowkey_algx; 661 uint16_t *reta; 662 int rc; 663 664 rc = npc_rss_free_grp_get(npc, &rss_grp_idx); 665 /* RSS group :0 is not usable for flow rss action */ 666 if (rc < 0 || rss_grp_idx == 0) 667 return -ENOSPC; 668 669 for (i = 0; i < rss->queue_num; i++) { 670 if (rss->queue[i] >= nix->nb_rx_queues) { 671 plt_err("queue id > max number of queues"); 672 return -EINVAL; 673 } 674 } 675 676 *rss_grp = rss_grp_idx; 677 678 if (rss->key == NULL) { 679 roc_nix_rss_key_default_fill(roc_nix, key); 680 key_ptr = key; 681 } else { 682 key_ptr = rss->key; 683 } 684 685 roc_nix_rss_key_set(roc_nix, key_ptr); 686 687 /* If queue count passed in the rss action is less than 688 * HW configured reta size, replicate rss action reta 689 * across HW reta table. 690 */ 691 reta = nix->reta[rss_grp_idx]; 692 693 if (rss->queue_num > nix->reta_sz) { 694 plt_err("too many queues for RSS context"); 695 return -ENOTSUP; 696 } 697 698 for (i = 0; i < (nix->reta_sz / rss->queue_num); i++) 699 memcpy(reta + i * rss->queue_num, rss->queue, 700 sizeof(uint16_t) * rss->queue_num); 701 702 rem = nix->reta_sz % rss->queue_num; 703 if (rem) 704 memcpy(&reta[i * rss->queue_num], rss->queue, 705 rem * sizeof(uint16_t)); 706 707 rc = roc_nix_rss_reta_set(roc_nix, *rss_grp, reta); 708 if (rc) { 709 plt_err("Failed to init rss table rc = %d", rc); 710 return rc; 711 } 712 713 flowkey_cfg = roc_npc->flowkey_cfg_state; 714 715 rc = roc_nix_rss_flowkey_set(roc_nix, &flowkey_algx, flowkey_cfg, 716 *rss_grp, mcam_id); 717 if (rc) { 718 plt_err("Failed to set rss hash function rc = %d", rc); 719 return rc; 720 } 721 722 *alg_idx = flowkey_algx; 723 724 plt_bitmap_set(npc->rss_grp_entries, *rss_grp); 725 726 return 0; 727 } 728 729 int 730 npc_rss_action_program(struct roc_npc *roc_npc, 731 const struct roc_npc_action actions[], 732 struct roc_npc_flow *flow) 733 { 734 const struct roc_npc_action_rss *rss; 735 uint32_t rss_grp; 736 uint8_t alg_idx; 737 int rc; 738 739 for (; actions->type != ROC_NPC_ACTION_TYPE_END; actions++) { 740 if (actions->type == ROC_NPC_ACTION_TYPE_RSS) { 741 rss = (const struct roc_npc_action_rss *)actions->conf; 742 rc = npc_rss_action_configure(roc_npc, rss, &alg_idx, 743 &rss_grp, flow->mcam_id); 744 if (rc) 745 return rc; 746 747 flow->npc_action &= (~(0xfULL)); 748 flow->npc_action |= NIX_RX_ACTIONOP_RSS; 749 flow->npc_action |= 750 ((uint64_t)(alg_idx & NPC_RSS_ACT_ALG_MASK) 751 << NPC_RSS_ACT_ALG_OFFSET) | 752 ((uint64_t)(rss_grp & NPC_RSS_ACT_GRP_MASK) 753 << NPC_RSS_ACT_GRP_OFFSET); 754 break; 755 } 756 } 757 return 0; 758 } 759 760 struct roc_npc_flow * 761 roc_npc_flow_create(struct roc_npc *roc_npc, const struct roc_npc_attr *attr, 762 const struct roc_npc_item_info pattern[], 763 const struct roc_npc_action actions[], int *errcode) 764 { 765 struct npc *npc = roc_npc_to_npc_priv(roc_npc); 766 struct roc_npc_flow *flow, *flow_iter; 767 struct npc_parse_state parse_state; 768 struct npc_flow_list *list; 769 int rc; 770 771 flow = plt_zmalloc(sizeof(*flow), 0); 772 if (flow == NULL) { 773 *errcode = NPC_ERR_NO_MEM; 774 return NULL; 775 } 776 memset(flow, 0, sizeof(*flow)); 777 778 rc = npc_parse_rule(npc, attr, pattern, actions, flow, &parse_state); 779 if (rc != 0) { 780 *errcode = rc; 781 goto err_exit; 782 } 783 784 parse_state.is_vf = !roc_nix_is_pf(roc_npc->roc_nix); 785 786 rc = npc_program_mcam(npc, &parse_state, 1); 787 if (rc != 0) { 788 *errcode = rc; 789 goto err_exit; 790 } 791 792 rc = npc_rss_action_program(roc_npc, actions, flow); 793 if (rc != 0) { 794 *errcode = rc; 795 goto set_rss_failed; 796 } 797 798 list = &npc->flow_list[flow->priority]; 799 /* List in ascending order of mcam entries */ 800 TAILQ_FOREACH(flow_iter, list, next) { 801 if (flow_iter->mcam_id > flow->mcam_id) { 802 TAILQ_INSERT_BEFORE(flow_iter, flow, next); 803 return flow; 804 } 805 } 806 807 TAILQ_INSERT_TAIL(list, flow, next); 808 return flow; 809 810 set_rss_failed: 811 rc = npc_mcam_free_entry(npc, flow->mcam_id); 812 if (rc != 0) { 813 *errcode = rc; 814 plt_free(flow); 815 return NULL; 816 } 817 err_exit: 818 plt_free(flow); 819 return NULL; 820 } 821 822 int 823 npc_rss_group_free(struct npc *npc, struct roc_npc_flow *flow) 824 { 825 uint32_t rss_grp; 826 827 if ((flow->npc_action & 0xF) == NIX_RX_ACTIONOP_RSS) { 828 rss_grp = (flow->npc_action >> NPC_RSS_ACT_GRP_OFFSET) & 829 NPC_RSS_ACT_GRP_MASK; 830 if (rss_grp == 0 || rss_grp >= npc->rss_grps) 831 return -EINVAL; 832 833 plt_bitmap_clear(npc->rss_grp_entries, rss_grp); 834 } 835 836 return 0; 837 } 838 839 int 840 roc_npc_flow_destroy(struct roc_npc *roc_npc, struct roc_npc_flow *flow) 841 { 842 struct npc *npc = roc_npc_to_npc_priv(roc_npc); 843 struct plt_bitmap *bmap; 844 uint16_t match_id; 845 int rc; 846 847 match_id = (flow->npc_action >> NPC_RX_ACT_MATCH_OFFSET) & 848 NPC_RX_ACT_MATCH_MASK; 849 850 if (match_id && match_id < NPC_ACTION_FLAG_DEFAULT) { 851 if (npc->mark_actions == 0) 852 return NPC_ERR_PARAM; 853 } 854 855 rc = npc_rss_group_free(npc, flow); 856 if (rc != 0) { 857 plt_err("Failed to free rss action rc = %d", rc); 858 return rc; 859 } 860 861 rc = npc_mcam_free_entry(npc, flow->mcam_id); 862 if (rc != 0) 863 return rc; 864 865 TAILQ_REMOVE(&npc->flow_list[flow->priority], flow, next); 866 867 bmap = npc->live_entries[flow->priority]; 868 plt_bitmap_clear(bmap, flow->mcam_id); 869 870 plt_free(flow); 871 return 0; 872 } 873