1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright(c) 2001-2020 Intel Corporation 3 */ 4 5 #include "ice_acl.h" 6 #include "ice_flow.h" 7 8 /* Determine the TCAM index of entry 'e' within the ACL table */ 9 #define ICE_ACL_TBL_TCAM_IDX(e) ((e) / ICE_AQC_ACL_TCAM_DEPTH) 10 11 /* Determine the entry index within the TCAM */ 12 #define ICE_ACL_TBL_TCAM_ENTRY_IDX(e) ((e) % ICE_AQC_ACL_TCAM_DEPTH) 13 14 #define ICE_ACL_SCEN_ENTRY_INVAL 0xFFFF 15 16 /** 17 * ice_acl_init_entry 18 * @scen: pointer to the scenario struct 19 * 20 * Initialize the scenario control structure. 21 */ 22 static void ice_acl_init_entry(struct ice_acl_scen *scen) 23 { 24 /* low priority: start from the highest index, 25% of total entries 25 * normal priority: start from the highest index, 50% of total entries 26 * high priority: start from the lowest index, 25% of total entries 27 */ 28 scen->first_idx[ICE_LOW] = scen->num_entry - 1; 29 scen->first_idx[ICE_NORMAL] = scen->num_entry - scen->num_entry / 4 - 1; 30 scen->first_idx[ICE_HIGH] = 0; 31 32 scen->last_idx[ICE_LOW] = scen->num_entry - scen->num_entry / 4; 33 scen->last_idx[ICE_NORMAL] = scen->num_entry / 4; 34 scen->last_idx[ICE_HIGH] = scen->num_entry / 4 - 1; 35 } 36 37 /** 38 * ice_acl_scen_assign_entry_idx 39 * @scen: pointer to the scenario struct 40 * @prior: the priority of the flow entry being allocated 41 * 42 * To find the index of an available entry in scenario 43 * 44 * Returns ICE_ACL_SCEN_ENTRY_INVAL if fails 45 * Returns index on success 46 */ 47 static u16 48 ice_acl_scen_assign_entry_idx(struct ice_acl_scen *scen, 49 enum ice_acl_entry_prior prior) 50 { 51 u16 first_idx, last_idx, i; 52 s8 step; 53 54 if (prior >= ICE_MAX_PRIOR) 55 return ICE_ACL_SCEN_ENTRY_INVAL; 56 57 first_idx = scen->first_idx[prior]; 58 last_idx = scen->last_idx[prior]; 59 step = first_idx <= last_idx ? 1 : -1; 60 61 for (i = first_idx; i != last_idx + step; i += step) 62 if (!ice_test_and_set_bit(i, scen->entry_bitmap)) 63 return i; 64 65 return ICE_ACL_SCEN_ENTRY_INVAL; 66 } 67 68 /** 69 * ice_acl_scen_free_entry_idx 70 * @scen: pointer to the scenario struct 71 * @idx: the index of the flow entry being de-allocated 72 * 73 * To mark an entry available in scenario 74 */ 75 static enum ice_status 76 ice_acl_scen_free_entry_idx(struct ice_acl_scen *scen, u16 idx) 77 { 78 if (idx >= scen->num_entry) 79 return ICE_ERR_MAX_LIMIT; 80 81 if (!ice_test_and_clear_bit(idx, scen->entry_bitmap)) 82 return ICE_ERR_DOES_NOT_EXIST; 83 84 return ICE_SUCCESS; 85 } 86 87 /** 88 * ice_acl_tbl_calc_end_idx 89 * @start: start index of the TCAM entry of this partition 90 * @num_entries: number of entries in this partition 91 * @width: width of a partition in number of TCAMs 92 * 93 * Calculate the end entry index for a partition with starting entry index 94 * 'start', entries 'num_entries', and width 'width'. 95 */ 96 static u16 ice_acl_tbl_calc_end_idx(u16 start, u16 num_entries, u16 width) 97 { 98 u16 end_idx, add_entries = 0; 99 100 end_idx = start + (num_entries - 1); 101 102 /* In case that our ACL partition requires cascading TCAMs */ 103 if (width > 1) { 104 u16 num_stack_level; 105 106 /* Figure out the TCAM stacked level in this ACL scenario */ 107 num_stack_level = (start % ICE_AQC_ACL_TCAM_DEPTH) + 108 num_entries; 109 num_stack_level = DIVIDE_AND_ROUND_UP(num_stack_level, 110 ICE_AQC_ACL_TCAM_DEPTH); 111 112 /* In this case, each entries in our ACL partition span 113 * multiple TCAMs. Thus, we will need to add 114 * ((width - 1) * num_stack_level) TCAM's entries to 115 * end_idx. 116 * 117 * For example : In our case, our scenario is 2x2: 118 * [TCAM 0] [TCAM 1] 119 * [TCAM 2] [TCAM 3] 120 * Assuming that a TCAM will have 512 entries. If "start" 121 * is 500, "num_entries" is 3 and "width" = 2, then end_idx 122 * should be 1024 (belongs to TCAM 2). 123 * Before going to this if statement, end_idx will have the 124 * value of 512. If "width" is 1, then the final value of 125 * end_idx is 512. However, in our case, width is 2, then we 126 * will need add (2 - 1) * 1 * 512. As result, end_idx will 127 * have the value of 1024. 128 */ 129 add_entries = (width - 1) * num_stack_level * 130 ICE_AQC_ACL_TCAM_DEPTH; 131 } 132 133 return end_idx + add_entries; 134 } 135 136 /** 137 * ice_acl_init_tbl 138 * @hw: pointer to the hardware structure 139 * 140 * Initialize the ACL table by invalidating TCAM entries and action pairs. 141 */ 142 static enum ice_status ice_acl_init_tbl(struct ice_hw *hw) 143 { 144 struct ice_aqc_actpair act_buf; 145 struct ice_aqc_acl_data buf; 146 enum ice_status status = ICE_SUCCESS; 147 struct ice_acl_tbl *tbl; 148 u8 tcam_idx, i; 149 u16 idx; 150 151 tbl = hw->acl_tbl; 152 if (!tbl) { 153 status = ICE_ERR_CFG; 154 return status; 155 } 156 157 ice_memset(&buf, 0, sizeof(buf), ICE_NONDMA_MEM); 158 ice_memset(&act_buf, 0, sizeof(act_buf), ICE_NONDMA_MEM); 159 160 tcam_idx = tbl->first_tcam; 161 idx = tbl->first_entry; 162 while (tcam_idx < tbl->last_tcam || 163 (tcam_idx == tbl->last_tcam && idx <= tbl->last_entry)) { 164 /* Use the same value for entry_key and entry_key_inv since 165 * we are initializing the fields to 0 166 */ 167 status = ice_aq_program_acl_entry(hw, tcam_idx, idx, &buf, 168 NULL); 169 if (status) 170 return status; 171 172 if (++idx > tbl->last_entry) { 173 tcam_idx++; 174 idx = tbl->first_entry; 175 } 176 } 177 178 for (i = 0; i < ICE_AQC_MAX_ACTION_MEMORIES; i++) { 179 u16 act_entry_idx, start, end; 180 181 if (tbl->act_mems[i].act_mem == ICE_ACL_ACT_PAIR_MEM_INVAL) 182 continue; 183 184 start = tbl->first_entry; 185 end = tbl->last_entry; 186 187 for (act_entry_idx = start; act_entry_idx <= end; 188 act_entry_idx++) { 189 /* Invalidate all allocated action pairs */ 190 status = ice_aq_program_actpair(hw, i, act_entry_idx, 191 &act_buf, NULL); 192 if (status) 193 return status; 194 } 195 } 196 197 return status; 198 } 199 200 /** 201 * ice_acl_assign_act_mems_to_tcam 202 * @tbl: pointer to ACL table structure 203 * @cur_tcam: Index of current TCAM. Value = 0 to (ICE_AQC_ACL_SLICES - 1) 204 * @cur_mem_idx: Index of current action memory bank. Value = 0 to 205 * (ICE_AQC_MAX_ACTION_MEMORIES - 1) 206 * @num_mem: Number of action memory banks for this TCAM 207 * 208 * Assign "num_mem" valid action memory banks from "curr_mem_idx" to 209 * "curr_tcam" TCAM. 210 */ 211 static void 212 ice_acl_assign_act_mems_to_tcam(struct ice_acl_tbl *tbl, u8 cur_tcam, 213 u8 *cur_mem_idx, u8 num_mem) 214 { 215 u8 mem_cnt; 216 217 for (mem_cnt = 0; 218 *cur_mem_idx < ICE_AQC_MAX_ACTION_MEMORIES && mem_cnt < num_mem; 219 (*cur_mem_idx)++) { 220 struct ice_acl_act_mem *p_mem = &tbl->act_mems[*cur_mem_idx]; 221 222 if (p_mem->act_mem == ICE_ACL_ACT_PAIR_MEM_INVAL) 223 continue; 224 225 p_mem->member_of_tcam = cur_tcam; 226 227 mem_cnt++; 228 } 229 } 230 231 /** 232 * ice_acl_divide_act_mems_to_tcams 233 * @tbl: pointer to ACL table structure 234 * 235 * Figure out how to divide given action memory banks to given TCAMs. This 236 * division is for SW book keeping. In the time when scenario is created, 237 * an action memory bank can be used for different TCAM. 238 * 239 * For example, given that we have 2x2 ACL table with each table entry has 240 * 2 action memory pairs. As the result, we will have 4 TCAMs (T1,T2,T3,T4) 241 * and 4 action memory banks (A1,A2,A3,A4) 242 * [T1 - T2] { A1 - A2 } 243 * [T3 - T4] { A3 - A4 } 244 * In the time when we need to create a scenario, for example, 2x1 scenario, 245 * we will use [T3,T4] in a cascaded layout. As it is a requirement that all 246 * action memory banks in a cascaded TCAM's row will need to associate with 247 * the last TCAM. Thus, we will associate action memory banks [A3] and [A4] 248 * for TCAM [T4]. 249 * For SW book-keeping purpose, we will keep theoretical maps between TCAM 250 * [Tn] to action memory bank [An]. 251 */ 252 static void ice_acl_divide_act_mems_to_tcams(struct ice_acl_tbl *tbl) 253 { 254 u16 num_cscd, stack_level, stack_idx, min_act_mem; 255 u8 tcam_idx = tbl->first_tcam; 256 u16 max_idx_to_get_extra; 257 u8 mem_idx = 0; 258 259 /* Determine number of stacked TCAMs */ 260 stack_level = DIVIDE_AND_ROUND_UP(tbl->info.depth, 261 ICE_AQC_ACL_TCAM_DEPTH); 262 263 /* Determine number of cascaded TCAMs */ 264 num_cscd = DIVIDE_AND_ROUND_UP(tbl->info.width, 265 ICE_AQC_ACL_KEY_WIDTH_BYTES); 266 267 /* In a line of cascaded TCAM, given the number of action memory 268 * banks per ACL table entry, we want to fairly divide these action 269 * memory banks between these TCAMs. 270 * 271 * For example, there are 3 TCAMs (TCAM 3,4,5) in a line of 272 * cascaded TCAM, and there are 7 act_mems for each ACL table entry. 273 * The result is: 274 * [TCAM_3 will have 3 act_mems] 275 * [TCAM_4 will have 2 act_mems] 276 * [TCAM_5 will have 2 act_mems] 277 */ 278 min_act_mem = tbl->info.entry_act_pairs / num_cscd; 279 max_idx_to_get_extra = tbl->info.entry_act_pairs % num_cscd; 280 281 for (stack_idx = 0; stack_idx < stack_level; stack_idx++) { 282 u16 i; 283 284 for (i = 0; i < num_cscd; i++) { 285 u8 total_act_mem = min_act_mem; 286 287 if (i < max_idx_to_get_extra) 288 total_act_mem++; 289 290 ice_acl_assign_act_mems_to_tcam(tbl, tcam_idx, 291 &mem_idx, 292 total_act_mem); 293 294 tcam_idx++; 295 } 296 } 297 } 298 299 /** 300 * ice_acl_create_tbl 301 * @hw: pointer to the HW struct 302 * @params: parameters for the table to be created 303 * 304 * Create a LEM table for ACL usage. We are currently starting with some fixed 305 * values for the size of the table, but this will need to grow as more flow 306 * entries are added by the user level. 307 */ 308 enum ice_status 309 ice_acl_create_tbl(struct ice_hw *hw, struct ice_acl_tbl_params *params) 310 { 311 u16 width, depth, first_e, last_e, i; 312 struct ice_aqc_acl_generic *resp_buf; 313 struct ice_acl_alloc_tbl tbl_alloc; 314 struct ice_acl_tbl *tbl; 315 enum ice_status status; 316 317 if (hw->acl_tbl) 318 return ICE_ERR_ALREADY_EXISTS; 319 320 if (!params) 321 return ICE_ERR_PARAM; 322 323 /* round up the width to the next TCAM width boundary. */ 324 width = ROUND_UP(params->width, (u16)ICE_AQC_ACL_KEY_WIDTH_BYTES); 325 /* depth should be provided in chunk (64 entry) increments */ 326 depth = ICE_ALIGN(params->depth, ICE_ACL_ENTRY_ALLOC_UNIT); 327 328 if (params->entry_act_pairs < width / ICE_AQC_ACL_KEY_WIDTH_BYTES) { 329 params->entry_act_pairs = width / ICE_AQC_ACL_KEY_WIDTH_BYTES; 330 331 if (params->entry_act_pairs > ICE_AQC_TBL_MAX_ACTION_PAIRS) 332 params->entry_act_pairs = ICE_AQC_TBL_MAX_ACTION_PAIRS; 333 } 334 335 /* Validate that width*depth will not exceed the TCAM limit */ 336 if ((DIVIDE_AND_ROUND_UP(depth, ICE_AQC_ACL_TCAM_DEPTH) * 337 (width / ICE_AQC_ACL_KEY_WIDTH_BYTES)) > ICE_AQC_ACL_SLICES) 338 return ICE_ERR_MAX_LIMIT; 339 340 ice_memset(&tbl_alloc, 0, sizeof(tbl_alloc), ICE_NONDMA_MEM); 341 tbl_alloc.width = width; 342 tbl_alloc.depth = depth; 343 tbl_alloc.act_pairs_per_entry = params->entry_act_pairs; 344 tbl_alloc.concurr = params->concurr; 345 /* Set dependent_alloc_id only for concurrent table type */ 346 if (params->concurr) { 347 tbl_alloc.num_dependent_alloc_ids = 348 ICE_AQC_MAX_CONCURRENT_ACL_TBL; 349 350 for (i = 0; i < ICE_AQC_MAX_CONCURRENT_ACL_TBL; i++) 351 tbl_alloc.buf.data_buf.alloc_ids[i] = 352 CPU_TO_LE16(params->dep_tbls[i]); 353 } 354 355 /* call the AQ command to create the ACL table with these values */ 356 status = ice_aq_alloc_acl_tbl(hw, &tbl_alloc, NULL); 357 358 if (status) { 359 if (LE16_TO_CPU(tbl_alloc.buf.resp_buf.alloc_id) < 360 ICE_AQC_ALLOC_ID_LESS_THAN_4K) 361 ice_debug(hw, ICE_DBG_ACL, 362 "Alloc ACL table failed. Unavailable resource.\n"); 363 else 364 ice_debug(hw, ICE_DBG_ACL, 365 "AQ allocation of ACL failed with error. status: %d\n", 366 status); 367 return status; 368 } 369 370 tbl = (struct ice_acl_tbl *)ice_malloc(hw, sizeof(*tbl)); 371 if (!tbl) { 372 status = ICE_ERR_NO_MEMORY; 373 374 goto out; 375 } 376 377 resp_buf = &tbl_alloc.buf.resp_buf; 378 379 /* Retrieve information of the allocated table */ 380 tbl->id = LE16_TO_CPU(resp_buf->alloc_id); 381 tbl->first_tcam = resp_buf->ops.table.first_tcam; 382 tbl->last_tcam = resp_buf->ops.table.last_tcam; 383 tbl->first_entry = LE16_TO_CPU(resp_buf->first_entry); 384 tbl->last_entry = LE16_TO_CPU(resp_buf->last_entry); 385 386 tbl->info = *params; 387 tbl->info.width = width; 388 tbl->info.depth = depth; 389 hw->acl_tbl = tbl; 390 391 for (i = 0; i < ICE_AQC_MAX_ACTION_MEMORIES; i++) 392 tbl->act_mems[i].act_mem = resp_buf->act_mem[i]; 393 394 /* Figure out which TCAMs that these newly allocated action memories 395 * belong to. 396 */ 397 ice_acl_divide_act_mems_to_tcams(tbl); 398 399 /* Initialize the resources allocated by invalidating all TCAM entries 400 * and all the action pairs 401 */ 402 status = ice_acl_init_tbl(hw); 403 if (status) { 404 ice_free(hw, tbl); 405 hw->acl_tbl = NULL; 406 ice_debug(hw, ICE_DBG_ACL, 407 "Initialization of TCAM entries failed. status: %d\n", 408 status); 409 goto out; 410 } 411 412 first_e = (tbl->first_tcam * ICE_AQC_MAX_TCAM_ALLOC_UNITS) + 413 (tbl->first_entry / ICE_ACL_ENTRY_ALLOC_UNIT); 414 last_e = (tbl->last_tcam * ICE_AQC_MAX_TCAM_ALLOC_UNITS) + 415 (tbl->last_entry / ICE_ACL_ENTRY_ALLOC_UNIT); 416 417 /* Indicate available entries in the table */ 418 for (i = first_e; i <= last_e; i++) 419 ice_set_bit(i, tbl->avail); 420 421 INIT_LIST_HEAD(&tbl->scens); 422 out: 423 424 return status; 425 } 426 427 /** 428 * ice_acl_alloc_partition - Allocate a partition from the ACL table 429 * @hw: pointer to the hardware structure 430 * @req: info of partition being allocated 431 */ 432 static enum ice_status 433 ice_acl_alloc_partition(struct ice_hw *hw, struct ice_acl_scen *req) 434 { 435 u16 start = 0, cnt = 0, off = 0; 436 u16 width, r_entries, row; 437 bool done = false; 438 int dir; 439 440 /* Determine the number of TCAMs each entry overlaps */ 441 width = DIVIDE_AND_ROUND_UP(req->width, ICE_AQC_ACL_KEY_WIDTH_BYTES); 442 443 /* Check if we have enough TCAMs to accommodate the width */ 444 if (width > hw->acl_tbl->last_tcam - hw->acl_tbl->first_tcam + 1) 445 return ICE_ERR_MAX_LIMIT; 446 447 /* Number of entries must be multiple of ICE_ACL_ENTRY_ALLOC_UNIT's */ 448 r_entries = ICE_ALIGN(req->num_entry, ICE_ACL_ENTRY_ALLOC_UNIT); 449 450 /* To look for an available partition that can accommodate the request, 451 * the process first logically arranges available TCAMs in rows such 452 * that each row produces entries with the requested width. It then 453 * scans the TCAMs' available bitmap, one bit at a time, and 454 * accumulates contiguous available 64-entry chunks until there are 455 * enough of them or when all TCAM configurations have been checked. 456 * 457 * For width of 1 TCAM, the scanning process starts from the top most 458 * TCAM, and goes downward. Available bitmaps are examined from LSB 459 * to MSB. 460 * 461 * For width of multiple TCAMs, the process starts from the bottom-most 462 * row of TCAMs, and goes upward. Available bitmaps are examined from 463 * the MSB to the LSB. 464 * 465 * To make sure that adjacent TCAMs can be logically arranged in the 466 * same row, the scanning process may have multiple passes. In each 467 * pass, the first TCAM of the bottom-most row is displaced by one 468 * additional TCAM. The width of the row and the number of the TCAMs 469 * available determine the number of passes. When the displacement is 470 * more than the size of width, the TCAM row configurations will 471 * repeat. The process will terminate when the configurations repeat. 472 * 473 * Available partitions can span more than one row of TCAMs. 474 */ 475 if (width == 1) { 476 row = hw->acl_tbl->first_tcam; 477 dir = 1; 478 } else { 479 /* Start with the bottom-most row, and scan for available 480 * entries upward 481 */ 482 row = hw->acl_tbl->last_tcam + 1 - width; 483 dir = -1; 484 } 485 486 do { 487 u16 i; 488 489 /* Scan all 64-entry chunks, one chunk at a time, in the 490 * current TCAM row 491 */ 492 for (i = 0; 493 i < ICE_AQC_MAX_TCAM_ALLOC_UNITS && cnt < r_entries; 494 i++) { 495 bool avail = true; 496 u16 w, p; 497 498 /* Compute the cumulative available mask across the 499 * TCAM row to determine if the current 64-entry chunk 500 * is available. 501 */ 502 p = dir > 0 ? i : ICE_AQC_MAX_TCAM_ALLOC_UNITS - i - 1; 503 for (w = row; w < row + width && avail; w++) { 504 u16 b; 505 506 b = (w * ICE_AQC_MAX_TCAM_ALLOC_UNITS) + p; 507 avail &= ice_is_bit_set(hw->acl_tbl->avail, b); 508 } 509 510 if (!avail) { 511 cnt = 0; 512 } else { 513 /* Compute the starting index of the newly 514 * found partition. When 'dir' is negative, the 515 * scan processes is going upward. If so, the 516 * starting index needs to be updated for every 517 * available 64-entry chunk found. 518 */ 519 if (!cnt || dir < 0) 520 start = (row * ICE_AQC_ACL_TCAM_DEPTH) + 521 (p * ICE_ACL_ENTRY_ALLOC_UNIT); 522 cnt += ICE_ACL_ENTRY_ALLOC_UNIT; 523 } 524 } 525 526 if (cnt >= r_entries) { 527 req->start = start; 528 req->num_entry = r_entries; 529 req->end = ice_acl_tbl_calc_end_idx(start, r_entries, 530 width); 531 break; 532 } 533 534 row = (dir > 0) ? (row + width) : (row - width); 535 if (row > hw->acl_tbl->last_tcam || 536 row < hw->acl_tbl->first_tcam) { 537 /* All rows have been checked. Increment 'off' that 538 * will help yield a different TCAM configuration in 539 * which adjacent TCAMs can be alternatively in the 540 * same row. 541 */ 542 off++; 543 544 /* However, if the new 'off' value yields previously 545 * checked configurations, then exit. 546 */ 547 if (off >= width) 548 done = true; 549 else 550 row = dir > 0 ? off : 551 hw->acl_tbl->last_tcam + 1 - off - 552 width; 553 } 554 } while (!done); 555 556 return cnt >= r_entries ? ICE_SUCCESS : ICE_ERR_MAX_LIMIT; 557 } 558 559 /** 560 * ice_acl_fill_tcam_select 561 * @scen_buf: Pointer to the scenario buffer that needs to be populated 562 * @scen: Pointer to the available space for the scenario 563 * @tcam_idx: Index of the TCAM used for this scenario 564 * @tcam_idx_in_cascade : Local index of the TCAM in the cascade scenario 565 * 566 * For all TCAM that participate in this scenario, fill out the tcam_select 567 * value. 568 */ 569 static void 570 ice_acl_fill_tcam_select(struct ice_aqc_acl_scen *scen_buf, 571 struct ice_acl_scen *scen, u16 tcam_idx, 572 u16 tcam_idx_in_cascade) 573 { 574 u16 cascade_cnt, idx; 575 u8 j; 576 577 idx = tcam_idx_in_cascade * ICE_AQC_ACL_KEY_WIDTH_BYTES; 578 cascade_cnt = DIVIDE_AND_ROUND_UP(scen->width, 579 ICE_AQC_ACL_KEY_WIDTH_BYTES); 580 581 /* For each scenario, we reserved last three bytes of scenario width for 582 * profile ID, range checker, and packet direction. Thus, the last three 583 * bytes of the last cascaded TCAMs will have value of 1st, 31st and 584 * 32nd byte location of BYTE selection base. 585 * 586 * For other bytes in the TCAMs: 587 * For non-cascade mode (1 TCAM wide) scenario, TCAM[x]'s Select {0-1} 588 * select indices 0-1 of the Byte Selection Base 589 * For cascade mode, the leftmost TCAM of the first cascade row selects 590 * indices 0-4 of the Byte Selection Base; the second TCAM in the 591 * cascade row selects indices starting with 5-n 592 */ 593 for (j = 0; j < ICE_AQC_ACL_KEY_WIDTH_BYTES; j++) { 594 /* PKT DIR uses the 1st location of Byte Selection Base: + 1 */ 595 u8 val = ICE_AQC_ACL_BYTE_SEL_BASE + 1 + idx; 596 597 if (tcam_idx_in_cascade == cascade_cnt - 1) { 598 if (j == ICE_ACL_SCEN_RNG_CHK_IDX_IN_TCAM) 599 val = ICE_AQC_ACL_BYTE_SEL_BASE_RNG_CHK; 600 else if (j == ICE_ACL_SCEN_PID_IDX_IN_TCAM) 601 val = ICE_AQC_ACL_BYTE_SEL_BASE_PID; 602 else if (j == ICE_ACL_SCEN_PKT_DIR_IDX_IN_TCAM) 603 val = ICE_AQC_ACL_BYTE_SEL_BASE_PKT_DIR; 604 } 605 606 /* In case that scenario's width is greater than the width of 607 * the Byte selection base, we will not assign a value to the 608 * tcam_select[j]. As a result, the tcam_select[j] will have 609 * default value which is zero. 610 */ 611 if (val > ICE_AQC_ACL_BYTE_SEL_BASE_RNG_CHK) 612 continue; 613 614 scen_buf->tcam_cfg[tcam_idx].tcam_select[j] = val; 615 616 idx++; 617 } 618 } 619 620 /** 621 * ice_acl_set_scen_chnk_msk 622 * @scen_buf: Pointer to the scenario buffer that needs to be populated 623 * @scen: pointer to the available space for the scenario 624 * 625 * Set the chunk mask for the entries that will be used by this scenario 626 */ 627 static void 628 ice_acl_set_scen_chnk_msk(struct ice_aqc_acl_scen *scen_buf, 629 struct ice_acl_scen *scen) 630 { 631 u16 tcam_idx, num_cscd, units, cnt; 632 u8 chnk_offst; 633 634 /* Determine the starting TCAM index and offset of the start entry */ 635 tcam_idx = ICE_ACL_TBL_TCAM_IDX(scen->start); 636 chnk_offst = (u8)((scen->start % ICE_AQC_ACL_TCAM_DEPTH) / 637 ICE_ACL_ENTRY_ALLOC_UNIT); 638 639 /* Entries are allocated and tracked in multiple of 64's */ 640 units = scen->num_entry / ICE_ACL_ENTRY_ALLOC_UNIT; 641 642 /* Determine number of cascaded TCAMs */ 643 num_cscd = scen->width / ICE_AQC_ACL_KEY_WIDTH_BYTES; 644 645 for (cnt = 0; cnt < units; cnt++) { 646 u16 i; 647 648 /* Set the corresponding bitmap of individual 64-entry 649 * chunk spans across a cascade of 1 or more TCAMs 650 * For each TCAM, there will be (ICE_AQC_ACL_TCAM_DEPTH 651 * / ICE_ACL_ENTRY_ALLOC_UNIT) or 8 chunks. 652 */ 653 for (i = tcam_idx; i < tcam_idx + num_cscd; i++) 654 scen_buf->tcam_cfg[i].chnk_msk |= BIT(chnk_offst); 655 656 chnk_offst = (chnk_offst + 1) % ICE_AQC_MAX_TCAM_ALLOC_UNITS; 657 if (!chnk_offst) 658 tcam_idx += num_cscd; 659 } 660 } 661 662 /** 663 * ice_acl_assign_act_mem_for_scen 664 * @tbl: pointer to ACL table structure 665 * @scen: pointer to the scenario struct 666 * @scen_buf: pointer to the available space for the scenario 667 * @current_tcam_idx: theoretical index of the TCAM that we associated those 668 * action memory banks with, at the table creation time. 669 * @target_tcam_idx: index of the TCAM that we want to associate those action 670 * memory banks with. 671 */ 672 static void 673 ice_acl_assign_act_mem_for_scen(struct ice_acl_tbl *tbl, 674 struct ice_acl_scen *scen, 675 struct ice_aqc_acl_scen *scen_buf, 676 u8 current_tcam_idx, 677 u8 target_tcam_idx) 678 { 679 u8 i; 680 681 for (i = 0; i < ICE_AQC_MAX_ACTION_MEMORIES; i++) { 682 struct ice_acl_act_mem *p_mem = &tbl->act_mems[i]; 683 684 if (p_mem->act_mem == ICE_ACL_ACT_PAIR_MEM_INVAL || 685 p_mem->member_of_tcam != current_tcam_idx) 686 continue; 687 688 scen_buf->act_mem_cfg[i] = target_tcam_idx; 689 scen_buf->act_mem_cfg[i] |= ICE_AQC_ACL_SCE_ACT_MEM_EN; 690 ice_set_bit(i, scen->act_mem_bitmap); 691 } 692 } 693 694 /** 695 * ice_acl_commit_partition - Indicate if the specified partition is active 696 * @hw: pointer to the hardware structure 697 * @scen: pointer to the scenario struct 698 * @commit: true if the partition is being commit 699 */ 700 static void 701 ice_acl_commit_partition(struct ice_hw *hw, struct ice_acl_scen *scen, 702 bool commit) 703 { 704 u16 tcam_idx, off, num_cscd, units, cnt; 705 706 /* Determine the starting TCAM index and offset of the start entry */ 707 tcam_idx = ICE_ACL_TBL_TCAM_IDX(scen->start); 708 off = (scen->start % ICE_AQC_ACL_TCAM_DEPTH) / 709 ICE_ACL_ENTRY_ALLOC_UNIT; 710 711 /* Entries are allocated and tracked in multiple of 64's */ 712 units = scen->num_entry / ICE_ACL_ENTRY_ALLOC_UNIT; 713 714 /* Determine number of cascaded TCAM */ 715 num_cscd = scen->width / ICE_AQC_ACL_KEY_WIDTH_BYTES; 716 717 for (cnt = 0; cnt < units; cnt++) { 718 u16 w; 719 720 /* Set/clear the corresponding bitmap of individual 64-entry 721 * chunk spans across a row of 1 or more TCAMs 722 */ 723 for (w = 0; w < num_cscd; w++) { 724 u16 b; 725 726 b = ((tcam_idx + w) * ICE_AQC_MAX_TCAM_ALLOC_UNITS) + 727 off; 728 if (commit) 729 ice_set_bit(b, hw->acl_tbl->avail); 730 else 731 ice_clear_bit(b, hw->acl_tbl->avail); 732 } 733 734 off = (off + 1) % ICE_AQC_MAX_TCAM_ALLOC_UNITS; 735 if (!off) 736 tcam_idx += num_cscd; 737 } 738 } 739 740 /** 741 * ice_acl_create_scen 742 * @hw: pointer to the hardware structure 743 * @match_width: number of bytes to be matched in this scenario 744 * @num_entries: number of entries to be allocated for the scenario 745 * @scen_id: holds returned scenario ID if successful 746 */ 747 enum ice_status 748 ice_acl_create_scen(struct ice_hw *hw, u16 match_width, u16 num_entries, 749 u16 *scen_id) 750 { 751 u8 cascade_cnt, first_tcam, last_tcam, i, k; 752 struct ice_aqc_acl_scen scen_buf; 753 struct ice_acl_scen *scen; 754 enum ice_status status; 755 756 if (!hw->acl_tbl) 757 return ICE_ERR_DOES_NOT_EXIST; 758 759 scen = (struct ice_acl_scen *)ice_malloc(hw, sizeof(*scen)); 760 if (!scen) 761 return ICE_ERR_NO_MEMORY; 762 763 scen->start = hw->acl_tbl->first_entry; 764 scen->width = ICE_AQC_ACL_KEY_WIDTH_BYTES * 765 DIVIDE_AND_ROUND_UP(match_width, ICE_AQC_ACL_KEY_WIDTH_BYTES); 766 scen->num_entry = num_entries; 767 768 status = ice_acl_alloc_partition(hw, scen); 769 if (status) { 770 ice_free(hw, scen); 771 return status; 772 } 773 774 ice_memset(&scen_buf, 0, sizeof(scen_buf), ICE_NONDMA_MEM); 775 776 /* Determine the number of cascade TCAMs, given the scenario's width */ 777 cascade_cnt = DIVIDE_AND_ROUND_UP(scen->width, 778 ICE_AQC_ACL_KEY_WIDTH_BYTES); 779 first_tcam = ICE_ACL_TBL_TCAM_IDX(scen->start); 780 last_tcam = ICE_ACL_TBL_TCAM_IDX(scen->end); 781 782 /* For each scenario, we reserved last three bytes of scenario width for 783 * packet direction flag, profile ID and range checker. Thus, we want to 784 * return back to the caller the eff_width, pkt_dir_idx, rng_chk_idx and 785 * pid_idx. 786 */ 787 scen->eff_width = cascade_cnt * ICE_AQC_ACL_KEY_WIDTH_BYTES - 788 ICE_ACL_SCEN_MIN_WIDTH; 789 scen->rng_chk_idx = (cascade_cnt - 1) * ICE_AQC_ACL_KEY_WIDTH_BYTES + 790 ICE_ACL_SCEN_RNG_CHK_IDX_IN_TCAM; 791 scen->pid_idx = (cascade_cnt - 1) * ICE_AQC_ACL_KEY_WIDTH_BYTES + 792 ICE_ACL_SCEN_PID_IDX_IN_TCAM; 793 scen->pkt_dir_idx = (cascade_cnt - 1) * ICE_AQC_ACL_KEY_WIDTH_BYTES + 794 ICE_ACL_SCEN_PKT_DIR_IDX_IN_TCAM; 795 796 /* set the chunk mask for the tcams */ 797 ice_acl_set_scen_chnk_msk(&scen_buf, scen); 798 799 /* set the TCAM select and start_cmp and start_set bits */ 800 k = first_tcam; 801 /* set the START_SET bit at the beginning of the stack */ 802 scen_buf.tcam_cfg[k].start_cmp_set |= ICE_AQC_ACL_ALLOC_SCE_START_SET; 803 while (k <= last_tcam) { 804 u8 last_tcam_idx_cascade = cascade_cnt + k - 1; 805 806 /* set start_cmp for the first cascaded TCAM */ 807 scen_buf.tcam_cfg[k].start_cmp_set |= 808 ICE_AQC_ACL_ALLOC_SCE_START_CMP; 809 810 /* cascade TCAMs up to the width of the scenario */ 811 for (i = k; i < cascade_cnt + k; i++) { 812 ice_acl_fill_tcam_select(&scen_buf, scen, i, i - k); 813 ice_acl_assign_act_mem_for_scen(hw->acl_tbl, scen, 814 &scen_buf, 815 i, 816 last_tcam_idx_cascade); 817 } 818 819 k = i; 820 } 821 822 /* We need to set the start_cmp bit for the unused TCAMs. */ 823 i = 0; 824 while (i < first_tcam) 825 scen_buf.tcam_cfg[i++].start_cmp_set = 826 ICE_AQC_ACL_ALLOC_SCE_START_CMP; 827 828 i = last_tcam + 1; 829 while (i < ICE_AQC_ACL_SLICES) 830 scen_buf.tcam_cfg[i++].start_cmp_set = 831 ICE_AQC_ACL_ALLOC_SCE_START_CMP; 832 833 status = ice_aq_alloc_acl_scen(hw, scen_id, &scen_buf, NULL); 834 if (status) { 835 ice_debug(hw, ICE_DBG_ACL, 836 "AQ allocation of ACL scenario failed. status: %d\n", 837 status); 838 ice_free(hw, scen); 839 return status; 840 } 841 842 scen->id = *scen_id; 843 ice_acl_commit_partition(hw, scen, false); 844 ice_acl_init_entry(scen); 845 LIST_ADD(&scen->list_entry, &hw->acl_tbl->scens); 846 847 return status; 848 } 849 850 /** 851 * ice_acl_destroy_tbl - Destroy a previously created LEM table for ACL 852 * @hw: pointer to the HW struct 853 */ 854 enum ice_status ice_acl_destroy_tbl(struct ice_hw *hw) 855 { 856 struct ice_acl_scen *pos_scen, *tmp_scen; 857 struct ice_aqc_acl_generic resp_buf; 858 struct ice_aqc_acl_scen buf; 859 enum ice_status status; 860 u8 i; 861 862 if (!hw->acl_tbl) 863 return ICE_ERR_DOES_NOT_EXIST; 864 865 /* Mark all the created scenario's TCAM to stop the packet lookup and 866 * delete them afterward 867 */ 868 LIST_FOR_EACH_ENTRY_SAFE(pos_scen, tmp_scen, &hw->acl_tbl->scens, 869 ice_acl_scen, list_entry) { 870 status = ice_aq_query_acl_scen(hw, pos_scen->id, &buf, NULL); 871 if (status) { 872 ice_debug(hw, ICE_DBG_ACL, "ice_aq_query_acl_scen() failed. status: %d\n", 873 status); 874 return status; 875 } 876 877 for (i = 0; i < ICE_AQC_ACL_SLICES; i++) { 878 buf.tcam_cfg[i].chnk_msk = 0; 879 buf.tcam_cfg[i].start_cmp_set = 880 ICE_AQC_ACL_ALLOC_SCE_START_CMP; 881 } 882 883 for (i = 0; i < ICE_AQC_MAX_ACTION_MEMORIES; i++) 884 buf.act_mem_cfg[i] = 0; 885 886 status = ice_aq_update_acl_scen(hw, pos_scen->id, &buf, NULL); 887 if (status) { 888 ice_debug(hw, ICE_DBG_ACL, "ice_aq_update_acl_scen() failed. status: %d\n", 889 status); 890 return status; 891 } 892 893 status = ice_acl_destroy_scen(hw, pos_scen->id); 894 if (status) { 895 ice_debug(hw, ICE_DBG_ACL, "deletion of scenario failed. status: %d\n", 896 status); 897 return status; 898 } 899 } 900 901 /* call the AQ command to destroy the ACL table */ 902 status = ice_aq_dealloc_acl_tbl(hw, hw->acl_tbl->id, &resp_buf, NULL); 903 904 if (status) { 905 ice_debug(hw, ICE_DBG_ACL, 906 "AQ de-allocation of ACL failed. status: %d\n", 907 status); 908 return status; 909 } 910 911 ice_free(hw, hw->acl_tbl); 912 hw->acl_tbl = NULL; 913 914 return ICE_SUCCESS; 915 } 916 917 /** 918 * ice_acl_add_entry - Add a flow entry to an ACL scenario 919 * @hw: pointer to the HW struct 920 * @scen: scenario to add the entry to 921 * @prior: priority level of the entry being added 922 * @keys: buffer of the value of the key to be programmed to the ACL entry 923 * @inverts: buffer of the value of the key inverts to be programmed 924 * @acts: pointer to a buffer containing formatted actions 925 * @acts_cnt: indicates the number of actions stored in "acts" 926 * @entry_idx: returned scenario relative index of the added flow entry 927 * 928 * Given an ACL table and a scenario, to add the specified key and key invert 929 * to an available entry in the specified scenario. 930 * The "keys" and "inverts" buffers must be of the size which is the same as 931 * the scenario's width 932 */ 933 enum ice_status 934 ice_acl_add_entry(struct ice_hw *hw, struct ice_acl_scen *scen, 935 enum ice_acl_entry_prior prior, u8 *keys, u8 *inverts, 936 struct ice_acl_act_entry *acts, u8 acts_cnt, u16 *entry_idx) 937 { 938 u8 i, entry_tcam, num_cscd, offset; 939 struct ice_aqc_acl_data buf; 940 enum ice_status status = ICE_SUCCESS; 941 u16 idx; 942 943 if (!scen) 944 return ICE_ERR_DOES_NOT_EXIST; 945 946 *entry_idx = ice_acl_scen_assign_entry_idx(scen, prior); 947 if (*entry_idx >= scen->num_entry) { 948 *entry_idx = 0; 949 return ICE_ERR_MAX_LIMIT; 950 } 951 952 /* Determine number of cascaded TCAMs */ 953 num_cscd = DIVIDE_AND_ROUND_UP(scen->width, 954 ICE_AQC_ACL_KEY_WIDTH_BYTES); 955 956 entry_tcam = ICE_ACL_TBL_TCAM_IDX(scen->start); 957 idx = ICE_ACL_TBL_TCAM_ENTRY_IDX(scen->start + *entry_idx); 958 959 ice_memset(&buf, 0, sizeof(buf), ICE_NONDMA_MEM); 960 for (i = 0; i < num_cscd; i++) { 961 /* If the key spans more than one TCAM in the case of cascaded 962 * TCAMs, the key and key inverts need to be properly split 963 * among TCAMs.E.g.bytes 0 - 4 go to an index in the first TCAM 964 * and bytes 5 - 9 go to the same index in the next TCAM, etc. 965 * If the entry spans more than one TCAM in a cascaded TCAM 966 * mode, the programming of the entries in the TCAMs must be in 967 * reversed order - the TCAM entry of the rightmost TCAM should 968 * be programmed first; the TCAM entry of the leftmost TCAM 969 * should be programmed last. 970 */ 971 offset = num_cscd - i - 1; 972 ice_memcpy(&buf.entry_key.val, 973 &keys[offset * sizeof(buf.entry_key.val)], 974 sizeof(buf.entry_key.val), ICE_NONDMA_TO_NONDMA); 975 ice_memcpy(&buf.entry_key_invert.val, 976 &inverts[offset * sizeof(buf.entry_key_invert.val)], 977 sizeof(buf.entry_key_invert.val), 978 ICE_NONDMA_TO_NONDMA); 979 status = ice_aq_program_acl_entry(hw, entry_tcam + offset, idx, 980 &buf, NULL); 981 if (status) { 982 ice_debug(hw, ICE_DBG_ACL, 983 "aq program acl entry failed status: %d\n", 984 status); 985 goto out; 986 } 987 } 988 989 /* Program the action memory */ 990 status = ice_acl_prog_act(hw, scen, acts, acts_cnt, *entry_idx); 991 992 out: 993 if (status) { 994 ice_acl_rem_entry(hw, scen, *entry_idx); 995 *entry_idx = 0; 996 } 997 998 return status; 999 } 1000 1001 /** 1002 * ice_acl_prog_act - Program a scenario's action memory 1003 * @hw: pointer to the HW struct 1004 * @scen: scenario to add the entry to 1005 * @acts: pointer to a buffer containing formatted actions 1006 * @acts_cnt: indicates the number of actions stored in "acts" 1007 * @entry_idx: scenario relative index of the added flow entry 1008 * 1009 * Program a scenario's action memory 1010 */ 1011 enum ice_status 1012 ice_acl_prog_act(struct ice_hw *hw, struct ice_acl_scen *scen, 1013 struct ice_acl_act_entry *acts, u8 acts_cnt, 1014 u16 entry_idx) 1015 { 1016 u8 entry_tcam, num_cscd, i, actx_idx = 0; 1017 struct ice_aqc_actpair act_buf; 1018 enum ice_status status = ICE_SUCCESS; 1019 u16 idx; 1020 1021 if (entry_idx >= scen->num_entry) 1022 return ICE_ERR_MAX_LIMIT; 1023 1024 ice_memset(&act_buf, 0, sizeof(act_buf), ICE_NONDMA_MEM); 1025 1026 /* Determine number of cascaded TCAMs */ 1027 num_cscd = DIVIDE_AND_ROUND_UP(scen->width, 1028 ICE_AQC_ACL_KEY_WIDTH_BYTES); 1029 1030 entry_tcam = ICE_ACL_TBL_TCAM_IDX(scen->start); 1031 idx = ICE_ACL_TBL_TCAM_ENTRY_IDX(scen->start + entry_idx); 1032 1033 i = ice_find_first_bit(scen->act_mem_bitmap, 1034 ICE_AQC_MAX_ACTION_MEMORIES); 1035 while (i < ICE_AQC_MAX_ACTION_MEMORIES) { 1036 struct ice_acl_act_mem *mem = &hw->acl_tbl->act_mems[i]; 1037 1038 if (actx_idx >= acts_cnt) 1039 break; 1040 if (mem->member_of_tcam >= entry_tcam && 1041 mem->member_of_tcam < entry_tcam + num_cscd) { 1042 ice_memcpy(&act_buf.act[0], &acts[actx_idx], 1043 sizeof(struct ice_acl_act_entry), 1044 ICE_NONDMA_TO_NONDMA); 1045 1046 if (++actx_idx < acts_cnt) { 1047 ice_memcpy(&act_buf.act[1], &acts[actx_idx], 1048 sizeof(struct ice_acl_act_entry), 1049 ICE_NONDMA_TO_NONDMA); 1050 } 1051 1052 status = ice_aq_program_actpair(hw, i, idx, &act_buf, 1053 NULL); 1054 if (status) { 1055 ice_debug(hw, ICE_DBG_ACL, 1056 "program actpair failed status: %d\n", 1057 status); 1058 break; 1059 } 1060 actx_idx++; 1061 } 1062 1063 i = ice_find_next_bit(scen->act_mem_bitmap, 1064 ICE_AQC_MAX_ACTION_MEMORIES, i + 1); 1065 } 1066 1067 if (!status && actx_idx < acts_cnt) 1068 status = ICE_ERR_MAX_LIMIT; 1069 1070 return status; 1071 } 1072 1073 /** 1074 * ice_acl_rem_entry - Remove a flow entry from an ACL scenario 1075 * @hw: pointer to the HW struct 1076 * @scen: scenario to remove the entry from 1077 * @entry_idx: the scenario-relative index of the flow entry being removed 1078 */ 1079 enum ice_status 1080 ice_acl_rem_entry(struct ice_hw *hw, struct ice_acl_scen *scen, u16 entry_idx) 1081 { 1082 struct ice_aqc_actpair act_buf; 1083 struct ice_aqc_acl_data buf; 1084 u8 entry_tcam, num_cscd, i; 1085 enum ice_status status = ICE_SUCCESS; 1086 u16 idx; 1087 1088 if (!scen) 1089 return ICE_ERR_DOES_NOT_EXIST; 1090 1091 if (entry_idx >= scen->num_entry) 1092 return ICE_ERR_MAX_LIMIT; 1093 1094 if (!ice_is_bit_set(scen->entry_bitmap, entry_idx)) 1095 return ICE_ERR_DOES_NOT_EXIST; 1096 1097 /* Determine number of cascaded TCAMs */ 1098 num_cscd = DIVIDE_AND_ROUND_UP(scen->width, 1099 ICE_AQC_ACL_KEY_WIDTH_BYTES); 1100 1101 entry_tcam = ICE_ACL_TBL_TCAM_IDX(scen->start); 1102 idx = ICE_ACL_TBL_TCAM_ENTRY_IDX(scen->start + entry_idx); 1103 1104 /* invalidate the flow entry */ 1105 ice_memset(&buf, 0, sizeof(buf), ICE_NONDMA_MEM); 1106 for (i = 0; i < num_cscd; i++) { 1107 status = ice_aq_program_acl_entry(hw, entry_tcam + i, idx, &buf, 1108 NULL); 1109 if (status) 1110 ice_debug(hw, ICE_DBG_ACL, 1111 "AQ program ACL entry failed status: %d\n", 1112 status); 1113 } 1114 1115 ice_memset(&act_buf, 0, sizeof(act_buf), ICE_NONDMA_MEM); 1116 i = ice_find_first_bit(scen->act_mem_bitmap, 1117 ICE_AQC_MAX_ACTION_MEMORIES); 1118 while (i < ICE_AQC_MAX_ACTION_MEMORIES) { 1119 struct ice_acl_act_mem *mem = &hw->acl_tbl->act_mems[i]; 1120 1121 if (mem->member_of_tcam >= entry_tcam && 1122 mem->member_of_tcam < entry_tcam + num_cscd) { 1123 /* Invalidate allocated action pairs */ 1124 status = ice_aq_program_actpair(hw, i, idx, &act_buf, 1125 NULL); 1126 if (status) 1127 ice_debug(hw, ICE_DBG_ACL, 1128 "program actpair failed.status: %d\n", 1129 status); 1130 } 1131 1132 i = ice_find_next_bit(scen->act_mem_bitmap, 1133 ICE_AQC_MAX_ACTION_MEMORIES, i + 1); 1134 } 1135 1136 ice_acl_scen_free_entry_idx(scen, entry_idx); 1137 1138 return status; 1139 } 1140 1141 /** 1142 * ice_acl_destroy_scen - Destroy an ACL scenario 1143 * @hw: pointer to the HW struct 1144 * @scen_id: ID of the remove scenario 1145 */ 1146 enum ice_status ice_acl_destroy_scen(struct ice_hw *hw, u16 scen_id) 1147 { 1148 struct ice_acl_scen *scen, *tmp_scen; 1149 struct ice_flow_prof *p, *tmp; 1150 enum ice_status status; 1151 1152 if (!hw->acl_tbl) 1153 return ICE_ERR_DOES_NOT_EXIST; 1154 1155 /* Remove profiles that use "scen_id" scenario */ 1156 LIST_FOR_EACH_ENTRY_SAFE(p, tmp, &hw->fl_profs[ICE_BLK_ACL], 1157 ice_flow_prof, l_entry) 1158 if (p->cfg.scen && p->cfg.scen->id == scen_id) { 1159 status = ice_flow_rem_prof(hw, ICE_BLK_ACL, p->id); 1160 if (status) { 1161 ice_debug(hw, ICE_DBG_ACL, 1162 "ice_flow_rem_prof failed. status: %d\n", 1163 status); 1164 goto exit; 1165 } 1166 } 1167 1168 /* Call the AQ command to destroy the targeted scenario */ 1169 status = ice_aq_dealloc_acl_scen(hw, scen_id, NULL); 1170 1171 if (status) { 1172 ice_debug(hw, ICE_DBG_ACL, 1173 "AQ de-allocation of scenario failed. status: %d\n", 1174 status); 1175 goto exit; 1176 } 1177 1178 /* Remove scenario from hw->acl_tbl->scens */ 1179 LIST_FOR_EACH_ENTRY_SAFE(scen, tmp_scen, &hw->acl_tbl->scens, 1180 ice_acl_scen, list_entry) 1181 if (scen->id == scen_id) { 1182 LIST_DEL(&scen->list_entry); 1183 ice_free(hw, scen); 1184 } 1185 exit: 1186 return status; 1187 } 1188