xref: /dpdk/drivers/net/ice/base/ice_acl_ctrl.c (revision c14ef1ec)
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