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