xref: /dpdk/drivers/net/ice/base/ice_switch.c (revision 85cf6dc3)
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2001-2019
3  */
4 
5 #include "ice_switch.h"
6 #include "ice_flex_type.h"
7 #include "ice_flow.h"
8 
9 
10 #define ICE_ETH_DA_OFFSET		0
11 #define ICE_ETH_ETHTYPE_OFFSET		12
12 #define ICE_ETH_VLAN_TCI_OFFSET		14
13 #define ICE_MAX_VLAN_ID			0xFFF
14 
15 /* Dummy ethernet header needed in the ice_aqc_sw_rules_elem
16  * struct to configure any switch filter rules.
17  * {DA (6 bytes), SA(6 bytes),
18  * Ether type (2 bytes for header without VLAN tag) OR
19  * VLAN tag (4 bytes for header with VLAN tag) }
20  *
21  * Word on Hardcoded values
22  * byte 0 = 0x2: to identify it as locally administered DA MAC
23  * byte 6 = 0x2: to identify it as locally administered SA MAC
24  * byte 12 = 0x81 & byte 13 = 0x00:
25  *	In case of VLAN filter first two bytes defines ether type (0x8100)
26  *	and remaining two bytes are placeholder for programming a given VLAN ID
27  *	In case of Ether type filter it is treated as header without VLAN tag
28  *	and byte 12 and 13 is used to program a given Ether type instead
29  */
30 #define DUMMY_ETH_HDR_LEN		16
31 static const u8 dummy_eth_header[DUMMY_ETH_HDR_LEN] = { 0x2, 0, 0, 0, 0, 0,
32 							0x2, 0, 0, 0, 0, 0,
33 							0x81, 0, 0, 0};
34 
35 #define ICE_SW_RULE_RX_TX_ETH_HDR_SIZE \
36 	(sizeof(struct ice_aqc_sw_rules_elem) - \
37 	 sizeof(((struct ice_aqc_sw_rules_elem *)0)->pdata) + \
38 	 sizeof(struct ice_sw_rule_lkup_rx_tx) + DUMMY_ETH_HDR_LEN - 1)
39 #define ICE_SW_RULE_RX_TX_NO_HDR_SIZE \
40 	(sizeof(struct ice_aqc_sw_rules_elem) - \
41 	 sizeof(((struct ice_aqc_sw_rules_elem *)0)->pdata) + \
42 	 sizeof(struct ice_sw_rule_lkup_rx_tx) - 1)
43 #define ICE_SW_RULE_LG_ACT_SIZE(n) \
44 	(sizeof(struct ice_aqc_sw_rules_elem) - \
45 	 sizeof(((struct ice_aqc_sw_rules_elem *)0)->pdata) + \
46 	 sizeof(struct ice_sw_rule_lg_act) - \
47 	 sizeof(((struct ice_sw_rule_lg_act *)0)->act) + \
48 	 ((n) * sizeof(((struct ice_sw_rule_lg_act *)0)->act)))
49 #define ICE_SW_RULE_VSI_LIST_SIZE(n) \
50 	(sizeof(struct ice_aqc_sw_rules_elem) - \
51 	 sizeof(((struct ice_aqc_sw_rules_elem *)0)->pdata) + \
52 	 sizeof(struct ice_sw_rule_vsi_list) - \
53 	 sizeof(((struct ice_sw_rule_vsi_list *)0)->vsi) + \
54 	 ((n) * sizeof(((struct ice_sw_rule_vsi_list *)0)->vsi)))
55 
56 struct ice_dummy_pkt_offsets {
57 	enum ice_protocol_type type;
58 	u16 offset; /* ICE_PROTOCOL_LAST indicates end of list */
59 };
60 
61 static const
62 struct ice_dummy_pkt_offsets dummy_gre_packet_offsets[] = {
63 	{ ICE_MAC_OFOS,		0 },
64 	{ ICE_ETYPE_OL,		12 },
65 	{ ICE_IPV4_OFOS,	14 },
66 	{ ICE_NVGRE,		34 },
67 	{ ICE_MAC_IL,		42 },
68 	{ ICE_IPV4_IL,		56 },
69 	{ ICE_PROTOCOL_LAST,	0 },
70 };
71 
72 static const
73 u8 dummy_gre_packet[] = { 0, 0, 0, 0,		/* ICE_MAC_OFOS 0 */
74 			  0, 0, 0, 0,
75 			  0, 0, 0, 0,
76 			  0x08, 0,		/* ICE_ETYPE_OL 12 */
77 			  0x45, 0, 0, 0x3E,	/* ICE_IPV4_OFOS 14 */
78 			  0, 0, 0, 0,
79 			  0, 0x2F, 0, 0,
80 			  0, 0, 0, 0,
81 			  0, 0, 0, 0,
82 			  0x80, 0, 0x65, 0x58,	/* ICE_NVGRE 34 */
83 			  0, 0, 0, 0,
84 			  0, 0, 0, 0,		/* ICE_MAC_IL 42 */
85 			  0, 0, 0, 0,
86 			  0, 0, 0, 0,
87 			  0x08, 0,
88 			  0x45, 0, 0, 0x14,	/* ICE_IPV4_IL 54 */
89 			  0, 0, 0, 0,
90 			  0, 0, 0, 0,
91 			  0, 0, 0, 0,
92 			  0, 0, 0, 0
93 			};
94 
95 static const
96 struct ice_dummy_pkt_offsets dummy_udp_tun_tcp_packet_offsets[] = {
97 	{ ICE_MAC_OFOS,		0 },
98 	{ ICE_ETYPE_OL,		12 },
99 	{ ICE_IPV4_OFOS,	14 },
100 	{ ICE_UDP_OF,		34 },
101 	{ ICE_VXLAN,		42 },
102 	{ ICE_MAC_IL,		50 },
103 	{ ICE_IPV4_IL,		64 },
104 	{ ICE_TCP_IL,		84 },
105 	{ ICE_PROTOCOL_LAST,	0 },
106 };
107 
108 static const
109 u8 dummy_udp_tun_tcp_packet[] = {
110 	0x00, 0x00, 0x00, 0x00,  /* ICE_MAC_OFOS 0 */
111 	0x00, 0x00, 0x00, 0x00,
112 	0x00, 0x00, 0x00, 0x00,
113 
114 	0x08, 0x00,		/* ICE_ETYPE_OL 12 */
115 
116 	0x45, 0x00, 0x00, 0x5a, /* ICE_IPV4_OFOS 14 */
117 	0x00, 0x01, 0x00, 0x00,
118 	0x40, 0x11, 0x00, 0x00,
119 	0x00, 0x00, 0x00, 0x00,
120 	0x00, 0x00, 0x00, 0x00,
121 
122 	0x00, 0x00, 0x12, 0xb5, /* ICE_UDP_OF 34 */
123 	0x00, 0x46, 0x00, 0x00,
124 
125 	0x04, 0x00, 0x00, 0x03, /* ICE_VXLAN 42 */
126 	0x00, 0x00, 0x00, 0x00,
127 
128 	0x00, 0x00, 0x00, 0x00, /* ICE_MAC_IL 50 */
129 	0x00, 0x00, 0x00, 0x00,
130 	0x00, 0x00, 0x00, 0x00,
131 	0x08, 0x00,
132 
133 	0x45, 0x00, 0x00, 0x28, /* ICE_IPV4_IL 64 */
134 	0x00, 0x01, 0x00, 0x00,
135 	0x40, 0x06, 0x00, 0x00,
136 	0x00, 0x00, 0x00, 0x00,
137 	0x00, 0x00, 0x00, 0x00,
138 
139 	0x00, 0x00, 0x00, 0x00, /* ICE_TCP_IL 84 */
140 	0x00, 0x00, 0x00, 0x00,
141 	0x00, 0x00, 0x00, 0x00,
142 	0x50, 0x02, 0x20, 0x00,
143 	0x00, 0x00, 0x00, 0x00
144 };
145 
146 static const
147 struct ice_dummy_pkt_offsets dummy_udp_tun_udp_packet_offsets[] = {
148 	{ ICE_MAC_OFOS,		0 },
149 	{ ICE_ETYPE_OL,		12 },
150 	{ ICE_IPV4_OFOS,	14 },
151 	{ ICE_UDP_OF,		34 },
152 	{ ICE_VXLAN,		42 },
153 	{ ICE_MAC_IL,		50 },
154 	{ ICE_IPV4_IL,		64 },
155 	{ ICE_UDP_ILOS,		84 },
156 	{ ICE_PROTOCOL_LAST,	0 },
157 };
158 
159 static const
160 u8 dummy_udp_tun_udp_packet[] = {
161 	0x00, 0x00, 0x00, 0x00,  /* ICE_MAC_OFOS 0 */
162 	0x00, 0x00, 0x00, 0x00,
163 	0x00, 0x00, 0x00, 0x00,
164 
165 	0x08, 0x00,		/* ICE_ETYPE_OL 12 */
166 
167 	0x45, 0x00, 0x00, 0x4e, /* ICE_IPV4_OFOS 14 */
168 	0x00, 0x01, 0x00, 0x00,
169 	0x00, 0x11, 0x00, 0x00,
170 	0x00, 0x00, 0x00, 0x00,
171 	0x00, 0x00, 0x00, 0x00,
172 
173 	0x00, 0x00, 0x12, 0xb5, /* ICE_UDP_OF 34 */
174 	0x00, 0x3a, 0x00, 0x00,
175 
176 	0x0c, 0x00, 0x00, 0x03, /* ICE_VXLAN 42 */
177 	0x00, 0x00, 0x00, 0x00,
178 
179 	0x00, 0x00, 0x00, 0x00, /* ICE_MAC_IL 50 */
180 	0x00, 0x00, 0x00, 0x00,
181 	0x00, 0x00, 0x00, 0x00,
182 	0x08, 0x00,
183 
184 	0x45, 0x00, 0x00, 0x1c, /* ICE_IPV4_IL 64 */
185 	0x00, 0x01, 0x00, 0x00,
186 	0x00, 0x11, 0x00, 0x00,
187 	0x00, 0x00, 0x00, 0x00,
188 	0x00, 0x00, 0x00, 0x00,
189 
190 	0x00, 0x00, 0x00, 0x00, /* ICE_UDP_ILOS 84 */
191 	0x00, 0x08, 0x00, 0x00,
192 };
193 
194 static const
195 struct ice_dummy_pkt_offsets dummy_udp_packet_offsets[] = {
196 	{ ICE_MAC_OFOS,		0 },
197 	{ ICE_ETYPE_OL,		12 },
198 	{ ICE_IPV4_OFOS,	14 },
199 	{ ICE_UDP_ILOS,		34 },
200 	{ ICE_PROTOCOL_LAST,	0 },
201 };
202 
203 static const u8
204 dummy_udp_packet[] = {
205 	0x00, 0x00, 0x00, 0x00, /* ICE_MAC_OFOS 0 */
206 	0x00, 0x00, 0x00, 0x00,
207 	0x00, 0x00, 0x00, 0x00,
208 
209 	0x08, 0x00,		/* ICE_ETYPE_OL 12 */
210 
211 	0x45, 0x00, 0x00, 0x1c, /* ICE_IPV4_OFOS 14 */
212 	0x00, 0x01, 0x00, 0x00,
213 	0x00, 0x11, 0x00, 0x00,
214 	0x00, 0x00, 0x00, 0x00,
215 	0x00, 0x00, 0x00, 0x00,
216 
217 	0x00, 0x00, 0x00, 0x00, /* ICE_UDP_ILOS 34 */
218 	0x00, 0x08, 0x00, 0x00,
219 
220 	0x00, 0x00,	/* 2 bytes for 4 byte alignment */
221 };
222 
223 static const
224 struct ice_dummy_pkt_offsets dummy_tcp_packet_offsets[] = {
225 	{ ICE_MAC_OFOS,		0 },
226 	{ ICE_ETYPE_OL,		12 },
227 	{ ICE_IPV4_OFOS,	14 },
228 	{ ICE_TCP_IL,		34 },
229 	{ ICE_PROTOCOL_LAST,	0 },
230 };
231 
232 static const u8
233 dummy_tcp_packet[] = {
234 	0x00, 0x00, 0x00, 0x00, /* ICE_MAC_OFOS 0 */
235 	0x00, 0x00, 0x00, 0x00,
236 	0x00, 0x00, 0x00, 0x00,
237 
238 	0x08, 0x00,		/* ICE_ETYPE_OL 12 */
239 
240 	0x45, 0x00, 0x00, 0x28, /* ICE_IPV4_OFOS 14 */
241 	0x00, 0x01, 0x00, 0x00,
242 	0x00, 0x06, 0x00, 0x00,
243 	0x00, 0x00, 0x00, 0x00,
244 	0x00, 0x00, 0x00, 0x00,
245 
246 	0x00, 0x00, 0x00, 0x00, /* ICE_TCP_IL 34 */
247 	0x00, 0x00, 0x00, 0x00,
248 	0x00, 0x00, 0x00, 0x00,
249 	0x50, 0x00, 0x00, 0x00,
250 	0x00, 0x00, 0x00, 0x00,
251 
252 	0x00, 0x00,	/* 2 bytes for 4 byte alignment */
253 };
254 
255 static const
256 struct ice_dummy_pkt_offsets dummy_tcp_ipv6_packet_offsets[] = {
257 	{ ICE_MAC_OFOS,		0 },
258 	{ ICE_ETYPE_OL,		12 },
259 	{ ICE_IPV6_OFOS,	14 },
260 	{ ICE_TCP_IL,		54 },
261 	{ ICE_PROTOCOL_LAST,	0 },
262 };
263 
264 static const u8
265 dummy_tcp_ipv6_packet[] = {
266 	0x00, 0x00, 0x00, 0x00, /* ICE_MAC_OFOS 0 */
267 	0x00, 0x00, 0x00, 0x00,
268 	0x00, 0x00, 0x00, 0x00,
269 
270 	0x86, 0xDD,		/* ICE_ETYPE_OL 12 */
271 
272 	0x60, 0x00, 0x00, 0x00, /* ICE_IPV6_OFOS 40 */
273 	0x00, 0x14, 0x06, 0x00, /* Next header is TCP */
274 	0x00, 0x00, 0x00, 0x00,
275 	0x00, 0x00, 0x00, 0x00,
276 	0x00, 0x00, 0x00, 0x00,
277 	0x00, 0x00, 0x00, 0x00,
278 	0x00, 0x00, 0x00, 0x00,
279 	0x00, 0x00, 0x00, 0x00,
280 	0x00, 0x00, 0x00, 0x00,
281 	0x00, 0x00, 0x00, 0x00,
282 
283 	0x00, 0x00, 0x00, 0x00, /* ICE_TCP_IL 54 */
284 	0x00, 0x00, 0x00, 0x00,
285 	0x00, 0x00, 0x00, 0x00,
286 	0x50, 0x00, 0x00, 0x00,
287 	0x00, 0x00, 0x00, 0x00,
288 
289 	0x00, 0x00, /* 2 bytes for 4 byte alignment */
290 };
291 
292 static const
293 struct ice_dummy_pkt_offsets dummy_udp_ipv6_packet_offsets[] = {
294 	{ ICE_MAC_OFOS,		0 },
295 	{ ICE_ETYPE_OL,		12 },
296 	{ ICE_IPV6_OFOS,	14 },
297 	{ ICE_UDP_ILOS,		54 },
298 	{ ICE_PROTOCOL_LAST,	0 },
299 };
300 
301 static const u8
302 dummy_udp_ipv6_packet[] = {
303 	0x00, 0x00, 0x00, 0x00, /* ICE_MAC_OFOS 0 */
304 	0x00, 0x00, 0x00, 0x00,
305 	0x00, 0x00, 0x00, 0x00,
306 
307 	0x86, 0xDD,		/* ICE_ETYPE_OL 12 */
308 
309 	0x60, 0x00, 0x00, 0x00, /* ICE_IPV6_OFOS 40 */
310 	0x00, 0x08, 0x11, 0x00, /* Next header UDP*/
311 	0x00, 0x00, 0x00, 0x00,
312 	0x00, 0x00, 0x00, 0x00,
313 	0x00, 0x00, 0x00, 0x00,
314 	0x00, 0x00, 0x00, 0x00,
315 	0x00, 0x00, 0x00, 0x00,
316 	0x00, 0x00, 0x00, 0x00,
317 	0x00, 0x00, 0x00, 0x00,
318 	0x00, 0x00, 0x00, 0x00,
319 
320 	0x00, 0x00, 0x00, 0x00, /* ICE_UDP_ILOS 54 */
321 	0x00, 0x08, 0x00, 0x00,
322 
323 	0x00, 0x00, /* 2 bytes for 4 byte alignment */
324 };
325 
326 /* this is a recipe to profile bitmap association */
327 static ice_declare_bitmap(recipe_to_profile[ICE_MAX_NUM_RECIPES],
328 			  ICE_MAX_NUM_PROFILES);
329 static ice_declare_bitmap(available_result_ids, ICE_CHAIN_FV_INDEX_START + 1);
330 
331 static void ice_get_recp_to_prof_map(struct ice_hw *hw);
332 
333 /**
334  * ice_get_recp_frm_fw - update SW bookkeeping from FW recipe entries
335  * @hw: pointer to hardware structure
336  * @recps: struct that we need to populate
337  * @rid: recipe ID that we are populating
338  * @refresh_required: true if we should get recipe to profile mapping from FW
339  *
340  * This function is used to populate all the necessary entries into our
341  * bookkeeping so that we have a current list of all the recipes that are
342  * programmed in the firmware.
343  */
344 static enum ice_status
345 ice_get_recp_frm_fw(struct ice_hw *hw, struct ice_sw_recipe *recps, u8 rid,
346 		    bool *refresh_required)
347 {
348 	u16 i, sub_recps, fv_word_idx = 0, result_idx = 0;
349 	ice_declare_bitmap(r_bitmap, ICE_MAX_NUM_PROFILES);
350 	u16 result_idxs[ICE_MAX_CHAIN_RECIPE] = { 0 };
351 	struct ice_aqc_recipe_data_elem *tmp;
352 	u16 num_recps = ICE_MAX_NUM_RECIPES;
353 	struct ice_prot_lkup_ext *lkup_exts;
354 	enum ice_status status;
355 
356 	/* we need a buffer big enough to accommodate all the recipes */
357 	tmp = (struct ice_aqc_recipe_data_elem *)ice_calloc(hw,
358 		ICE_MAX_NUM_RECIPES, sizeof(*tmp));
359 	if (!tmp)
360 		return ICE_ERR_NO_MEMORY;
361 
362 	tmp[0].recipe_indx = rid;
363 	status = ice_aq_get_recipe(hw, tmp, &num_recps, rid, NULL);
364 	/* non-zero status meaning recipe doesn't exist */
365 	if (status)
366 		goto err_unroll;
367 
368 	/* Get recipe to profile map so that we can get the fv from lkups that
369 	 * we read for a recipe from FW. Since we want to minimize the number of
370 	 * times we make this FW call, just make one call and cache the copy
371 	 * until a new recipe is added. This operation is only required the
372 	 * first time to get the changes from FW. Then to search existing
373 	 * entries we don't need to update the cache again until another recipe
374 	 * gets added.
375 	 */
376 	if (*refresh_required) {
377 		ice_get_recp_to_prof_map(hw);
378 		*refresh_required = false;
379 	}
380 	lkup_exts = &recps[rid].lkup_exts;
381 	/* start populating all the entries for recps[rid] based on lkups from
382 	 * firmware
383 	 */
384 	for (sub_recps = 0; sub_recps < num_recps; sub_recps++) {
385 		struct ice_aqc_recipe_data_elem root_bufs = tmp[sub_recps];
386 		struct ice_recp_grp_entry *rg_entry;
387 		u8 prof_id, prot = 0;
388 		u16 off = 0;
389 
390 		rg_entry = (struct ice_recp_grp_entry *)
391 			ice_malloc(hw, sizeof(*rg_entry));
392 		if (!rg_entry) {
393 			status = ICE_ERR_NO_MEMORY;
394 			goto err_unroll;
395 		}
396 		/* Avoid 8th bit since its result enable bit */
397 		result_idxs[result_idx] = root_bufs.content.result_indx &
398 			~ICE_AQ_RECIPE_RESULT_EN;
399 		/* Check if result enable bit is set */
400 		if (root_bufs.content.result_indx & ICE_AQ_RECIPE_RESULT_EN)
401 			ice_clear_bit(ICE_CHAIN_FV_INDEX_START -
402 				      result_idxs[result_idx++],
403 				      available_result_ids);
404 		ice_memcpy(r_bitmap,
405 			   recipe_to_profile[tmp[sub_recps].recipe_indx],
406 			   sizeof(r_bitmap), ICE_NONDMA_TO_NONDMA);
407 		/* get the first profile that is associated with rid */
408 		prof_id = ice_find_first_bit(r_bitmap, ICE_MAX_NUM_PROFILES);
409 		for (i = 0; i < ICE_NUM_WORDS_RECIPE; i++) {
410 			u8 lkup_indx = root_bufs.content.lkup_indx[i + 1];
411 
412 			rg_entry->fv_idx[i] = lkup_indx;
413 			rg_entry->fv_mask[i] =
414 				LE16_TO_CPU(root_bufs.content.mask[i + 1]);
415 
416 			/* If the recipe is a chained recipe then all its
417 			 * child recipe's result will have a result index.
418 			 * To fill fv_words we should not use those result
419 			 * index, we only need the protocol ids and offsets.
420 			 * We will skip all the fv_idx which stores result
421 			 * index in them. We also need to skip any fv_idx which
422 			 * has ICE_AQ_RECIPE_LKUP_IGNORE or 0 since it isn't a
423 			 * valid offset value.
424 			 */
425 			if (result_idxs[0] == rg_entry->fv_idx[i] ||
426 			    result_idxs[1] == rg_entry->fv_idx[i] ||
427 			    result_idxs[2] == rg_entry->fv_idx[i] ||
428 			    result_idxs[3] == rg_entry->fv_idx[i] ||
429 			    result_idxs[4] == rg_entry->fv_idx[i] ||
430 			    rg_entry->fv_idx[i] == ICE_AQ_RECIPE_LKUP_IGNORE ||
431 			    rg_entry->fv_idx[i] == 0)
432 				continue;
433 
434 			ice_find_prot_off(hw, ICE_BLK_SW, prof_id,
435 					  rg_entry->fv_idx[i], &prot, &off);
436 			lkup_exts->fv_words[fv_word_idx].prot_id = prot;
437 			lkup_exts->fv_words[fv_word_idx].off = off;
438 			fv_word_idx++;
439 		}
440 		/* populate rg_list with the data from the child entry of this
441 		 * recipe
442 		 */
443 		LIST_ADD(&rg_entry->l_entry, &recps[rid].rg_list);
444 	}
445 	lkup_exts->n_val_words = fv_word_idx;
446 	recps[rid].n_grp_count = num_recps;
447 	recps[rid].root_buf = (struct ice_aqc_recipe_data_elem *)
448 		ice_calloc(hw, recps[rid].n_grp_count,
449 			   sizeof(struct ice_aqc_recipe_data_elem));
450 	if (!recps[rid].root_buf)
451 		goto err_unroll;
452 
453 	ice_memcpy(recps[rid].root_buf, tmp, recps[rid].n_grp_count *
454 		   sizeof(*recps[rid].root_buf), ICE_NONDMA_TO_NONDMA);
455 	recps[rid].recp_created = true;
456 	if (tmp[sub_recps].content.rid & ICE_AQ_RECIPE_ID_IS_ROOT)
457 		recps[rid].root_rid = rid;
458 err_unroll:
459 	ice_free(hw, tmp);
460 	return status;
461 }
462 
463 /**
464  * ice_get_recp_to_prof_map - updates recipe to profile mapping
465  * @hw: pointer to hardware structure
466  *
467  * This function is used to populate recipe_to_profile matrix where index to
468  * this array is the recipe ID and the element is the mapping of which profiles
469  * is this recipe mapped to.
470  */
471 static void
472 ice_get_recp_to_prof_map(struct ice_hw *hw)
473 {
474 	ice_declare_bitmap(r_bitmap, ICE_MAX_NUM_RECIPES);
475 	u16 i;
476 
477 	for (i = 0; i < ICE_MAX_NUM_PROFILES; i++) {
478 		u16 j;
479 
480 		ice_zero_bitmap(r_bitmap, ICE_MAX_NUM_RECIPES);
481 		if (ice_aq_get_recipe_to_profile(hw, i, (u8 *)r_bitmap, NULL))
482 			continue;
483 
484 		for (j = 0; j < ICE_MAX_NUM_RECIPES; j++)
485 			if (ice_is_bit_set(r_bitmap, j))
486 				ice_set_bit(i, recipe_to_profile[j]);
487 	}
488 }
489 
490 /**
491  * ice_init_def_sw_recp - initialize the recipe book keeping tables
492  * @hw: pointer to the HW struct
493  *
494  * Allocate memory for the entire recipe table and initialize the structures/
495  * entries corresponding to basic recipes.
496  */
497 enum ice_status ice_init_def_sw_recp(struct ice_hw *hw)
498 {
499 	struct ice_sw_recipe *recps;
500 	u8 i;
501 
502 	recps = (struct ice_sw_recipe *)
503 		ice_calloc(hw, ICE_MAX_NUM_RECIPES, sizeof(*recps));
504 	if (!recps)
505 		return ICE_ERR_NO_MEMORY;
506 
507 	for (i = 0; i < ICE_MAX_NUM_RECIPES; i++) {
508 		recps[i].root_rid = i;
509 		INIT_LIST_HEAD(&recps[i].filt_rules);
510 		INIT_LIST_HEAD(&recps[i].filt_replay_rules);
511 		INIT_LIST_HEAD(&recps[i].rg_list);
512 		ice_init_lock(&recps[i].filt_rule_lock);
513 	}
514 
515 	hw->switch_info->recp_list = recps;
516 
517 	return ICE_SUCCESS;
518 }
519 
520 /**
521  * ice_aq_get_sw_cfg - get switch configuration
522  * @hw: pointer to the hardware structure
523  * @buf: pointer to the result buffer
524  * @buf_size: length of the buffer available for response
525  * @req_desc: pointer to requested descriptor
526  * @num_elems: pointer to number of elements
527  * @cd: pointer to command details structure or NULL
528  *
529  * Get switch configuration (0x0200) to be placed in 'buff'.
530  * This admin command returns information such as initial VSI/port number
531  * and switch ID it belongs to.
532  *
533  * NOTE: *req_desc is both an input/output parameter.
534  * The caller of this function first calls this function with *request_desc set
535  * to 0. If the response from f/w has *req_desc set to 0, all the switch
536  * configuration information has been returned; if non-zero (meaning not all
537  * the information was returned), the caller should call this function again
538  * with *req_desc set to the previous value returned by f/w to get the
539  * next block of switch configuration information.
540  *
541  * *num_elems is output only parameter. This reflects the number of elements
542  * in response buffer. The caller of this function to use *num_elems while
543  * parsing the response buffer.
544  */
545 static enum ice_status
546 ice_aq_get_sw_cfg(struct ice_hw *hw, struct ice_aqc_get_sw_cfg_resp *buf,
547 		  u16 buf_size, u16 *req_desc, u16 *num_elems,
548 		  struct ice_sq_cd *cd)
549 {
550 	struct ice_aqc_get_sw_cfg *cmd;
551 	enum ice_status status;
552 	struct ice_aq_desc desc;
553 
554 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_get_sw_cfg);
555 	cmd = &desc.params.get_sw_conf;
556 	cmd->element = CPU_TO_LE16(*req_desc);
557 
558 	status = ice_aq_send_cmd(hw, &desc, buf, buf_size, cd);
559 	if (!status) {
560 		*req_desc = LE16_TO_CPU(cmd->element);
561 		*num_elems = LE16_TO_CPU(cmd->num_elems);
562 	}
563 
564 	return status;
565 }
566 
567 
568 /**
569  * ice_alloc_sw - allocate resources specific to switch
570  * @hw: pointer to the HW struct
571  * @ena_stats: true to turn on VEB stats
572  * @shared_res: true for shared resource, false for dedicated resource
573  * @sw_id: switch ID returned
574  * @counter_id: VEB counter ID returned
575  *
576  * allocates switch resources (SWID and VEB counter) (0x0208)
577  */
578 enum ice_status
579 ice_alloc_sw(struct ice_hw *hw, bool ena_stats, bool shared_res, u16 *sw_id,
580 	     u16 *counter_id)
581 {
582 	struct ice_aqc_alloc_free_res_elem *sw_buf;
583 	struct ice_aqc_res_elem *sw_ele;
584 	enum ice_status status;
585 	u16 buf_len;
586 
587 	buf_len = sizeof(*sw_buf);
588 	sw_buf = (struct ice_aqc_alloc_free_res_elem *)
589 		   ice_malloc(hw, buf_len);
590 	if (!sw_buf)
591 		return ICE_ERR_NO_MEMORY;
592 
593 	/* Prepare buffer for switch ID.
594 	 * The number of resource entries in buffer is passed as 1 since only a
595 	 * single switch/VEB instance is allocated, and hence a single sw_id
596 	 * is requested.
597 	 */
598 	sw_buf->num_elems = CPU_TO_LE16(1);
599 	sw_buf->res_type =
600 		CPU_TO_LE16(ICE_AQC_RES_TYPE_SWID |
601 			    (shared_res ? ICE_AQC_RES_TYPE_FLAG_SHARED :
602 			    ICE_AQC_RES_TYPE_FLAG_DEDICATED));
603 
604 	status = ice_aq_alloc_free_res(hw, 1, sw_buf, buf_len,
605 				       ice_aqc_opc_alloc_res, NULL);
606 
607 	if (status)
608 		goto ice_alloc_sw_exit;
609 
610 	sw_ele = &sw_buf->elem[0];
611 	*sw_id = LE16_TO_CPU(sw_ele->e.sw_resp);
612 
613 	if (ena_stats) {
614 		/* Prepare buffer for VEB Counter */
615 		enum ice_adminq_opc opc = ice_aqc_opc_alloc_res;
616 		struct ice_aqc_alloc_free_res_elem *counter_buf;
617 		struct ice_aqc_res_elem *counter_ele;
618 
619 		counter_buf = (struct ice_aqc_alloc_free_res_elem *)
620 				ice_malloc(hw, buf_len);
621 		if (!counter_buf) {
622 			status = ICE_ERR_NO_MEMORY;
623 			goto ice_alloc_sw_exit;
624 		}
625 
626 		/* The number of resource entries in buffer is passed as 1 since
627 		 * only a single switch/VEB instance is allocated, and hence a
628 		 * single VEB counter is requested.
629 		 */
630 		counter_buf->num_elems = CPU_TO_LE16(1);
631 		counter_buf->res_type =
632 			CPU_TO_LE16(ICE_AQC_RES_TYPE_VEB_COUNTER |
633 				    ICE_AQC_RES_TYPE_FLAG_DEDICATED);
634 		status = ice_aq_alloc_free_res(hw, 1, counter_buf, buf_len,
635 					       opc, NULL);
636 
637 		if (status) {
638 			ice_free(hw, counter_buf);
639 			goto ice_alloc_sw_exit;
640 		}
641 		counter_ele = &counter_buf->elem[0];
642 		*counter_id = LE16_TO_CPU(counter_ele->e.sw_resp);
643 		ice_free(hw, counter_buf);
644 	}
645 
646 ice_alloc_sw_exit:
647 	ice_free(hw, sw_buf);
648 	return status;
649 }
650 
651 /**
652  * ice_free_sw - free resources specific to switch
653  * @hw: pointer to the HW struct
654  * @sw_id: switch ID returned
655  * @counter_id: VEB counter ID returned
656  *
657  * free switch resources (SWID and VEB counter) (0x0209)
658  *
659  * NOTE: This function frees multiple resources. It continues
660  * releasing other resources even after it encounters error.
661  * The error code returned is the last error it encountered.
662  */
663 enum ice_status ice_free_sw(struct ice_hw *hw, u16 sw_id, u16 counter_id)
664 {
665 	struct ice_aqc_alloc_free_res_elem *sw_buf, *counter_buf;
666 	enum ice_status status, ret_status;
667 	u16 buf_len;
668 
669 	buf_len = sizeof(*sw_buf);
670 	sw_buf = (struct ice_aqc_alloc_free_res_elem *)
671 		   ice_malloc(hw, buf_len);
672 	if (!sw_buf)
673 		return ICE_ERR_NO_MEMORY;
674 
675 	/* Prepare buffer to free for switch ID res.
676 	 * The number of resource entries in buffer is passed as 1 since only a
677 	 * single switch/VEB instance is freed, and hence a single sw_id
678 	 * is released.
679 	 */
680 	sw_buf->num_elems = CPU_TO_LE16(1);
681 	sw_buf->res_type = CPU_TO_LE16(ICE_AQC_RES_TYPE_SWID);
682 	sw_buf->elem[0].e.sw_resp = CPU_TO_LE16(sw_id);
683 
684 	ret_status = ice_aq_alloc_free_res(hw, 1, sw_buf, buf_len,
685 					   ice_aqc_opc_free_res, NULL);
686 
687 	if (ret_status)
688 		ice_debug(hw, ICE_DBG_SW, "CQ CMD Buffer:\n");
689 
690 	/* Prepare buffer to free for VEB Counter resource */
691 	counter_buf = (struct ice_aqc_alloc_free_res_elem *)
692 			ice_malloc(hw, buf_len);
693 	if (!counter_buf) {
694 		ice_free(hw, sw_buf);
695 		return ICE_ERR_NO_MEMORY;
696 	}
697 
698 	/* The number of resource entries in buffer is passed as 1 since only a
699 	 * single switch/VEB instance is freed, and hence a single VEB counter
700 	 * is released
701 	 */
702 	counter_buf->num_elems = CPU_TO_LE16(1);
703 	counter_buf->res_type = CPU_TO_LE16(ICE_AQC_RES_TYPE_VEB_COUNTER);
704 	counter_buf->elem[0].e.sw_resp = CPU_TO_LE16(counter_id);
705 
706 	status = ice_aq_alloc_free_res(hw, 1, counter_buf, buf_len,
707 				       ice_aqc_opc_free_res, NULL);
708 	if (status) {
709 		ice_debug(hw, ICE_DBG_SW,
710 			  "VEB counter resource could not be freed\n");
711 		ret_status = status;
712 	}
713 
714 	ice_free(hw, counter_buf);
715 	ice_free(hw, sw_buf);
716 	return ret_status;
717 }
718 
719 /**
720  * ice_aq_add_vsi
721  * @hw: pointer to the HW struct
722  * @vsi_ctx: pointer to a VSI context struct
723  * @cd: pointer to command details structure or NULL
724  *
725  * Add a VSI context to the hardware (0x0210)
726  */
727 enum ice_status
728 ice_aq_add_vsi(struct ice_hw *hw, struct ice_vsi_ctx *vsi_ctx,
729 	       struct ice_sq_cd *cd)
730 {
731 	struct ice_aqc_add_update_free_vsi_resp *res;
732 	struct ice_aqc_add_get_update_free_vsi *cmd;
733 	struct ice_aq_desc desc;
734 	enum ice_status status;
735 
736 	cmd = &desc.params.vsi_cmd;
737 	res = &desc.params.add_update_free_vsi_res;
738 
739 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_add_vsi);
740 
741 	if (!vsi_ctx->alloc_from_pool)
742 		cmd->vsi_num = CPU_TO_LE16(vsi_ctx->vsi_num |
743 					   ICE_AQ_VSI_IS_VALID);
744 
745 	cmd->vsi_flags = CPU_TO_LE16(vsi_ctx->flags);
746 
747 	desc.flags |= CPU_TO_LE16(ICE_AQ_FLAG_RD);
748 
749 	status = ice_aq_send_cmd(hw, &desc, &vsi_ctx->info,
750 				 sizeof(vsi_ctx->info), cd);
751 
752 	if (!status) {
753 		vsi_ctx->vsi_num = LE16_TO_CPU(res->vsi_num) & ICE_AQ_VSI_NUM_M;
754 		vsi_ctx->vsis_allocd = LE16_TO_CPU(res->vsi_used);
755 		vsi_ctx->vsis_unallocated = LE16_TO_CPU(res->vsi_free);
756 	}
757 
758 	return status;
759 }
760 
761 /**
762  * ice_aq_free_vsi
763  * @hw: pointer to the HW struct
764  * @vsi_ctx: pointer to a VSI context struct
765  * @keep_vsi_alloc: keep VSI allocation as part of this PF's resources
766  * @cd: pointer to command details structure or NULL
767  *
768  * Free VSI context info from hardware (0x0213)
769  */
770 enum ice_status
771 ice_aq_free_vsi(struct ice_hw *hw, struct ice_vsi_ctx *vsi_ctx,
772 		bool keep_vsi_alloc, struct ice_sq_cd *cd)
773 {
774 	struct ice_aqc_add_update_free_vsi_resp *resp;
775 	struct ice_aqc_add_get_update_free_vsi *cmd;
776 	struct ice_aq_desc desc;
777 	enum ice_status status;
778 
779 	cmd = &desc.params.vsi_cmd;
780 	resp = &desc.params.add_update_free_vsi_res;
781 
782 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_free_vsi);
783 
784 	cmd->vsi_num = CPU_TO_LE16(vsi_ctx->vsi_num | ICE_AQ_VSI_IS_VALID);
785 	if (keep_vsi_alloc)
786 		cmd->cmd_flags = CPU_TO_LE16(ICE_AQ_VSI_KEEP_ALLOC);
787 
788 	status = ice_aq_send_cmd(hw, &desc, NULL, 0, cd);
789 	if (!status) {
790 		vsi_ctx->vsis_allocd = LE16_TO_CPU(resp->vsi_used);
791 		vsi_ctx->vsis_unallocated = LE16_TO_CPU(resp->vsi_free);
792 	}
793 
794 	return status;
795 }
796 
797 /**
798  * ice_aq_update_vsi
799  * @hw: pointer to the HW struct
800  * @vsi_ctx: pointer to a VSI context struct
801  * @cd: pointer to command details structure or NULL
802  *
803  * Update VSI context in the hardware (0x0211)
804  */
805 enum ice_status
806 ice_aq_update_vsi(struct ice_hw *hw, struct ice_vsi_ctx *vsi_ctx,
807 		  struct ice_sq_cd *cd)
808 {
809 	struct ice_aqc_add_update_free_vsi_resp *resp;
810 	struct ice_aqc_add_get_update_free_vsi *cmd;
811 	struct ice_aq_desc desc;
812 	enum ice_status status;
813 
814 	cmd = &desc.params.vsi_cmd;
815 	resp = &desc.params.add_update_free_vsi_res;
816 
817 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_update_vsi);
818 
819 	cmd->vsi_num = CPU_TO_LE16(vsi_ctx->vsi_num | ICE_AQ_VSI_IS_VALID);
820 
821 	desc.flags |= CPU_TO_LE16(ICE_AQ_FLAG_RD);
822 
823 	status = ice_aq_send_cmd(hw, &desc, &vsi_ctx->info,
824 				 sizeof(vsi_ctx->info), cd);
825 
826 	if (!status) {
827 		vsi_ctx->vsis_allocd = LE16_TO_CPU(resp->vsi_used);
828 		vsi_ctx->vsis_unallocated = LE16_TO_CPU(resp->vsi_free);
829 	}
830 
831 	return status;
832 }
833 
834 /**
835  * ice_is_vsi_valid - check whether the VSI is valid or not
836  * @hw: pointer to the HW struct
837  * @vsi_handle: VSI handle
838  *
839  * check whether the VSI is valid or not
840  */
841 bool ice_is_vsi_valid(struct ice_hw *hw, u16 vsi_handle)
842 {
843 	return vsi_handle < ICE_MAX_VSI && hw->vsi_ctx[vsi_handle];
844 }
845 
846 /**
847  * ice_get_hw_vsi_num - return the HW VSI number
848  * @hw: pointer to the HW struct
849  * @vsi_handle: VSI handle
850  *
851  * return the HW VSI number
852  * Caution: call this function only if VSI is valid (ice_is_vsi_valid)
853  */
854 u16 ice_get_hw_vsi_num(struct ice_hw *hw, u16 vsi_handle)
855 {
856 	return hw->vsi_ctx[vsi_handle]->vsi_num;
857 }
858 
859 /**
860  * ice_get_vsi_ctx - return the VSI context entry for a given VSI handle
861  * @hw: pointer to the HW struct
862  * @vsi_handle: VSI handle
863  *
864  * return the VSI context entry for a given VSI handle
865  */
866 struct ice_vsi_ctx *ice_get_vsi_ctx(struct ice_hw *hw, u16 vsi_handle)
867 {
868 	return (vsi_handle >= ICE_MAX_VSI) ? NULL : hw->vsi_ctx[vsi_handle];
869 }
870 
871 /**
872  * ice_save_vsi_ctx - save the VSI context for a given VSI handle
873  * @hw: pointer to the HW struct
874  * @vsi_handle: VSI handle
875  * @vsi: VSI context pointer
876  *
877  * save the VSI context entry for a given VSI handle
878  */
879 static void
880 ice_save_vsi_ctx(struct ice_hw *hw, u16 vsi_handle, struct ice_vsi_ctx *vsi)
881 {
882 	hw->vsi_ctx[vsi_handle] = vsi;
883 }
884 
885 /**
886  * ice_clear_vsi_q_ctx - clear VSI queue contexts for all TCs
887  * @hw: pointer to the HW struct
888  * @vsi_handle: VSI handle
889  */
890 static void ice_clear_vsi_q_ctx(struct ice_hw *hw, u16 vsi_handle)
891 {
892 	struct ice_vsi_ctx *vsi;
893 	u8 i;
894 
895 	vsi = ice_get_vsi_ctx(hw, vsi_handle);
896 	if (!vsi)
897 		return;
898 	ice_for_each_traffic_class(i) {
899 		if (vsi->lan_q_ctx[i]) {
900 			ice_free(hw, vsi->lan_q_ctx[i]);
901 			vsi->lan_q_ctx[i] = NULL;
902 		}
903 	}
904 }
905 
906 /**
907  * ice_clear_vsi_ctx - clear the VSI context entry
908  * @hw: pointer to the HW struct
909  * @vsi_handle: VSI handle
910  *
911  * clear the VSI context entry
912  */
913 static void ice_clear_vsi_ctx(struct ice_hw *hw, u16 vsi_handle)
914 {
915 	struct ice_vsi_ctx *vsi;
916 
917 	vsi = ice_get_vsi_ctx(hw, vsi_handle);
918 	if (vsi) {
919 		ice_clear_vsi_q_ctx(hw, vsi_handle);
920 		ice_free(hw, vsi);
921 		hw->vsi_ctx[vsi_handle] = NULL;
922 	}
923 }
924 
925 /**
926  * ice_clear_all_vsi_ctx - clear all the VSI context entries
927  * @hw: pointer to the HW struct
928  */
929 void ice_clear_all_vsi_ctx(struct ice_hw *hw)
930 {
931 	u16 i;
932 
933 	for (i = 0; i < ICE_MAX_VSI; i++)
934 		ice_clear_vsi_ctx(hw, i);
935 }
936 
937 /**
938  * ice_add_vsi - add VSI context to the hardware and VSI handle list
939  * @hw: pointer to the HW struct
940  * @vsi_handle: unique VSI handle provided by drivers
941  * @vsi_ctx: pointer to a VSI context struct
942  * @cd: pointer to command details structure or NULL
943  *
944  * Add a VSI context to the hardware also add it into the VSI handle list.
945  * If this function gets called after reset for existing VSIs then update
946  * with the new HW VSI number in the corresponding VSI handle list entry.
947  */
948 enum ice_status
949 ice_add_vsi(struct ice_hw *hw, u16 vsi_handle, struct ice_vsi_ctx *vsi_ctx,
950 	    struct ice_sq_cd *cd)
951 {
952 	struct ice_vsi_ctx *tmp_vsi_ctx;
953 	enum ice_status status;
954 
955 	if (vsi_handle >= ICE_MAX_VSI)
956 		return ICE_ERR_PARAM;
957 	status = ice_aq_add_vsi(hw, vsi_ctx, cd);
958 	if (status)
959 		return status;
960 	tmp_vsi_ctx = ice_get_vsi_ctx(hw, vsi_handle);
961 	if (!tmp_vsi_ctx) {
962 		/* Create a new VSI context */
963 		tmp_vsi_ctx = (struct ice_vsi_ctx *)
964 			ice_malloc(hw, sizeof(*tmp_vsi_ctx));
965 		if (!tmp_vsi_ctx) {
966 			ice_aq_free_vsi(hw, vsi_ctx, false, cd);
967 			return ICE_ERR_NO_MEMORY;
968 		}
969 		*tmp_vsi_ctx = *vsi_ctx;
970 
971 		ice_save_vsi_ctx(hw, vsi_handle, tmp_vsi_ctx);
972 	} else {
973 		/* update with new HW VSI num */
974 		if (tmp_vsi_ctx->vsi_num != vsi_ctx->vsi_num)
975 			tmp_vsi_ctx->vsi_num = vsi_ctx->vsi_num;
976 	}
977 
978 	return ICE_SUCCESS;
979 }
980 
981 /**
982  * ice_free_vsi- free VSI context from hardware and VSI handle list
983  * @hw: pointer to the HW struct
984  * @vsi_handle: unique VSI handle
985  * @vsi_ctx: pointer to a VSI context struct
986  * @keep_vsi_alloc: keep VSI allocation as part of this PF's resources
987  * @cd: pointer to command details structure or NULL
988  *
989  * Free VSI context info from hardware as well as from VSI handle list
990  */
991 enum ice_status
992 ice_free_vsi(struct ice_hw *hw, u16 vsi_handle, struct ice_vsi_ctx *vsi_ctx,
993 	     bool keep_vsi_alloc, struct ice_sq_cd *cd)
994 {
995 	enum ice_status status;
996 
997 	if (!ice_is_vsi_valid(hw, vsi_handle))
998 		return ICE_ERR_PARAM;
999 	vsi_ctx->vsi_num = ice_get_hw_vsi_num(hw, vsi_handle);
1000 	status = ice_aq_free_vsi(hw, vsi_ctx, keep_vsi_alloc, cd);
1001 	if (!status)
1002 		ice_clear_vsi_ctx(hw, vsi_handle);
1003 	return status;
1004 }
1005 
1006 /**
1007  * ice_update_vsi
1008  * @hw: pointer to the HW struct
1009  * @vsi_handle: unique VSI handle
1010  * @vsi_ctx: pointer to a VSI context struct
1011  * @cd: pointer to command details structure or NULL
1012  *
1013  * Update VSI context in the hardware
1014  */
1015 enum ice_status
1016 ice_update_vsi(struct ice_hw *hw, u16 vsi_handle, struct ice_vsi_ctx *vsi_ctx,
1017 	       struct ice_sq_cd *cd)
1018 {
1019 	if (!ice_is_vsi_valid(hw, vsi_handle))
1020 		return ICE_ERR_PARAM;
1021 	vsi_ctx->vsi_num = ice_get_hw_vsi_num(hw, vsi_handle);
1022 	return ice_aq_update_vsi(hw, vsi_ctx, cd);
1023 }
1024 
1025 /**
1026  * ice_aq_get_vsi_params
1027  * @hw: pointer to the HW struct
1028  * @vsi_ctx: pointer to a VSI context struct
1029  * @cd: pointer to command details structure or NULL
1030  *
1031  * Get VSI context info from hardware (0x0212)
1032  */
1033 enum ice_status
1034 ice_aq_get_vsi_params(struct ice_hw *hw, struct ice_vsi_ctx *vsi_ctx,
1035 		      struct ice_sq_cd *cd)
1036 {
1037 	struct ice_aqc_add_get_update_free_vsi *cmd;
1038 	struct ice_aqc_get_vsi_resp *resp;
1039 	struct ice_aq_desc desc;
1040 	enum ice_status status;
1041 
1042 	cmd = &desc.params.vsi_cmd;
1043 	resp = &desc.params.get_vsi_resp;
1044 
1045 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_get_vsi_params);
1046 
1047 	cmd->vsi_num = CPU_TO_LE16(vsi_ctx->vsi_num | ICE_AQ_VSI_IS_VALID);
1048 
1049 	status = ice_aq_send_cmd(hw, &desc, &vsi_ctx->info,
1050 				 sizeof(vsi_ctx->info), cd);
1051 	if (!status) {
1052 		vsi_ctx->vsi_num = LE16_TO_CPU(resp->vsi_num) &
1053 					ICE_AQ_VSI_NUM_M;
1054 		vsi_ctx->vsis_allocd = LE16_TO_CPU(resp->vsi_used);
1055 		vsi_ctx->vsis_unallocated = LE16_TO_CPU(resp->vsi_free);
1056 	}
1057 
1058 	return status;
1059 }
1060 
1061 /**
1062  * ice_aq_add_update_mir_rule - add/update a mirror rule
1063  * @hw: pointer to the HW struct
1064  * @rule_type: Rule Type
1065  * @dest_vsi: VSI number to which packets will be mirrored
1066  * @count: length of the list
1067  * @mr_buf: buffer for list of mirrored VSI numbers
1068  * @cd: pointer to command details structure or NULL
1069  * @rule_id: Rule ID
1070  *
1071  * Add/Update Mirror Rule (0x260).
1072  */
1073 enum ice_status
1074 ice_aq_add_update_mir_rule(struct ice_hw *hw, u16 rule_type, u16 dest_vsi,
1075 			   u16 count, struct ice_mir_rule_buf *mr_buf,
1076 			   struct ice_sq_cd *cd, u16 *rule_id)
1077 {
1078 	struct ice_aqc_add_update_mir_rule *cmd;
1079 	struct ice_aq_desc desc;
1080 	enum ice_status status;
1081 	__le16 *mr_list = NULL;
1082 	u16 buf_size = 0;
1083 
1084 	switch (rule_type) {
1085 	case ICE_AQC_RULE_TYPE_VPORT_INGRESS:
1086 	case ICE_AQC_RULE_TYPE_VPORT_EGRESS:
1087 		/* Make sure count and mr_buf are set for these rule_types */
1088 		if (!(count && mr_buf))
1089 			return ICE_ERR_PARAM;
1090 
1091 		buf_size = count * sizeof(__le16);
1092 		mr_list = (_FORCE_ __le16 *)ice_malloc(hw, buf_size);
1093 		if (!mr_list)
1094 			return ICE_ERR_NO_MEMORY;
1095 		break;
1096 	case ICE_AQC_RULE_TYPE_PPORT_INGRESS:
1097 	case ICE_AQC_RULE_TYPE_PPORT_EGRESS:
1098 		/* Make sure count and mr_buf are not set for these
1099 		 * rule_types
1100 		 */
1101 		if (count || mr_buf)
1102 			return ICE_ERR_PARAM;
1103 		break;
1104 	default:
1105 		ice_debug(hw, ICE_DBG_SW,
1106 			  "Error due to unsupported rule_type %u\n", rule_type);
1107 		return ICE_ERR_OUT_OF_RANGE;
1108 	}
1109 
1110 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_add_update_mir_rule);
1111 
1112 	/* Pre-process 'mr_buf' items for add/update of virtual port
1113 	 * ingress/egress mirroring (but not physical port ingress/egress
1114 	 * mirroring)
1115 	 */
1116 	if (mr_buf) {
1117 		int i;
1118 
1119 		for (i = 0; i < count; i++) {
1120 			u16 id;
1121 
1122 			id = mr_buf[i].vsi_idx & ICE_AQC_RULE_MIRRORED_VSI_M;
1123 
1124 			/* Validate specified VSI number, make sure it is less
1125 			 * than ICE_MAX_VSI, if not return with error.
1126 			 */
1127 			if (id >= ICE_MAX_VSI) {
1128 				ice_debug(hw, ICE_DBG_SW,
1129 					  "Error VSI index (%u) out-of-range\n",
1130 					  id);
1131 				ice_free(hw, mr_list);
1132 				return ICE_ERR_OUT_OF_RANGE;
1133 			}
1134 
1135 			/* add VSI to mirror rule */
1136 			if (mr_buf[i].add)
1137 				mr_list[i] =
1138 					CPU_TO_LE16(id | ICE_AQC_RULE_ACT_M);
1139 			else /* remove VSI from mirror rule */
1140 				mr_list[i] = CPU_TO_LE16(id);
1141 		}
1142 	}
1143 
1144 	cmd = &desc.params.add_update_rule;
1145 	if ((*rule_id) != ICE_INVAL_MIRROR_RULE_ID)
1146 		cmd->rule_id = CPU_TO_LE16(((*rule_id) & ICE_AQC_RULE_ID_M) |
1147 					   ICE_AQC_RULE_ID_VALID_M);
1148 	cmd->rule_type = CPU_TO_LE16(rule_type & ICE_AQC_RULE_TYPE_M);
1149 	cmd->num_entries = CPU_TO_LE16(count);
1150 	cmd->dest = CPU_TO_LE16(dest_vsi);
1151 
1152 	status = ice_aq_send_cmd(hw, &desc, mr_list, buf_size, cd);
1153 	if (!status)
1154 		*rule_id = LE16_TO_CPU(cmd->rule_id) & ICE_AQC_RULE_ID_M;
1155 
1156 	ice_free(hw, mr_list);
1157 
1158 	return status;
1159 }
1160 
1161 /**
1162  * ice_aq_delete_mir_rule - delete a mirror rule
1163  * @hw: pointer to the HW struct
1164  * @rule_id: Mirror rule ID (to be deleted)
1165  * @keep_allocd: if set, the VSI stays part of the PF allocated res,
1166  *		 otherwise it is returned to the shared pool
1167  * @cd: pointer to command details structure or NULL
1168  *
1169  * Delete Mirror Rule (0x261).
1170  */
1171 enum ice_status
1172 ice_aq_delete_mir_rule(struct ice_hw *hw, u16 rule_id, bool keep_allocd,
1173 		       struct ice_sq_cd *cd)
1174 {
1175 	struct ice_aqc_delete_mir_rule *cmd;
1176 	struct ice_aq_desc desc;
1177 
1178 	/* rule_id should be in the range 0...63 */
1179 	if (rule_id >= ICE_MAX_NUM_MIRROR_RULES)
1180 		return ICE_ERR_OUT_OF_RANGE;
1181 
1182 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_del_mir_rule);
1183 
1184 	cmd = &desc.params.del_rule;
1185 	rule_id |= ICE_AQC_RULE_ID_VALID_M;
1186 	cmd->rule_id = CPU_TO_LE16(rule_id);
1187 
1188 	if (keep_allocd)
1189 		cmd->flags = CPU_TO_LE16(ICE_AQC_FLAG_KEEP_ALLOCD_M);
1190 
1191 	return ice_aq_send_cmd(hw, &desc, NULL, 0, cd);
1192 }
1193 
1194 /**
1195  * ice_aq_alloc_free_vsi_list
1196  * @hw: pointer to the HW struct
1197  * @vsi_list_id: VSI list ID returned or used for lookup
1198  * @lkup_type: switch rule filter lookup type
1199  * @opc: switch rules population command type - pass in the command opcode
1200  *
1201  * allocates or free a VSI list resource
1202  */
1203 static enum ice_status
1204 ice_aq_alloc_free_vsi_list(struct ice_hw *hw, u16 *vsi_list_id,
1205 			   enum ice_sw_lkup_type lkup_type,
1206 			   enum ice_adminq_opc opc)
1207 {
1208 	struct ice_aqc_alloc_free_res_elem *sw_buf;
1209 	struct ice_aqc_res_elem *vsi_ele;
1210 	enum ice_status status;
1211 	u16 buf_len;
1212 
1213 	buf_len = sizeof(*sw_buf);
1214 	sw_buf = (struct ice_aqc_alloc_free_res_elem *)
1215 		ice_malloc(hw, buf_len);
1216 	if (!sw_buf)
1217 		return ICE_ERR_NO_MEMORY;
1218 	sw_buf->num_elems = CPU_TO_LE16(1);
1219 
1220 	if (lkup_type == ICE_SW_LKUP_MAC ||
1221 	    lkup_type == ICE_SW_LKUP_MAC_VLAN ||
1222 	    lkup_type == ICE_SW_LKUP_ETHERTYPE ||
1223 	    lkup_type == ICE_SW_LKUP_ETHERTYPE_MAC ||
1224 	    lkup_type == ICE_SW_LKUP_PROMISC ||
1225 	    lkup_type == ICE_SW_LKUP_PROMISC_VLAN ||
1226 	    lkup_type == ICE_SW_LKUP_LAST) {
1227 		sw_buf->res_type = CPU_TO_LE16(ICE_AQC_RES_TYPE_VSI_LIST_REP);
1228 	} else if (lkup_type == ICE_SW_LKUP_VLAN) {
1229 		sw_buf->res_type =
1230 			CPU_TO_LE16(ICE_AQC_RES_TYPE_VSI_LIST_PRUNE);
1231 	} else {
1232 		status = ICE_ERR_PARAM;
1233 		goto ice_aq_alloc_free_vsi_list_exit;
1234 	}
1235 
1236 	if (opc == ice_aqc_opc_free_res)
1237 		sw_buf->elem[0].e.sw_resp = CPU_TO_LE16(*vsi_list_id);
1238 
1239 	status = ice_aq_alloc_free_res(hw, 1, sw_buf, buf_len, opc, NULL);
1240 	if (status)
1241 		goto ice_aq_alloc_free_vsi_list_exit;
1242 
1243 	if (opc == ice_aqc_opc_alloc_res) {
1244 		vsi_ele = &sw_buf->elem[0];
1245 		*vsi_list_id = LE16_TO_CPU(vsi_ele->e.sw_resp);
1246 	}
1247 
1248 ice_aq_alloc_free_vsi_list_exit:
1249 	ice_free(hw, sw_buf);
1250 	return status;
1251 }
1252 
1253 /**
1254  * ice_aq_set_storm_ctrl - Sets storm control configuration
1255  * @hw: pointer to the HW struct
1256  * @bcast_thresh: represents the upper threshold for broadcast storm control
1257  * @mcast_thresh: represents the upper threshold for multicast storm control
1258  * @ctl_bitmask: storm control control knobs
1259  *
1260  * Sets the storm control configuration (0x0280)
1261  */
1262 enum ice_status
1263 ice_aq_set_storm_ctrl(struct ice_hw *hw, u32 bcast_thresh, u32 mcast_thresh,
1264 		      u32 ctl_bitmask)
1265 {
1266 	struct ice_aqc_storm_cfg *cmd;
1267 	struct ice_aq_desc desc;
1268 
1269 	cmd = &desc.params.storm_conf;
1270 
1271 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_set_storm_cfg);
1272 
1273 	cmd->bcast_thresh_size = CPU_TO_LE32(bcast_thresh & ICE_AQ_THRESHOLD_M);
1274 	cmd->mcast_thresh_size = CPU_TO_LE32(mcast_thresh & ICE_AQ_THRESHOLD_M);
1275 	cmd->storm_ctrl_ctrl = CPU_TO_LE32(ctl_bitmask);
1276 
1277 	return ice_aq_send_cmd(hw, &desc, NULL, 0, NULL);
1278 }
1279 
1280 /**
1281  * ice_aq_get_storm_ctrl - gets storm control configuration
1282  * @hw: pointer to the HW struct
1283  * @bcast_thresh: represents the upper threshold for broadcast storm control
1284  * @mcast_thresh: represents the upper threshold for multicast storm control
1285  * @ctl_bitmask: storm control control knobs
1286  *
1287  * Gets the storm control configuration (0x0281)
1288  */
1289 enum ice_status
1290 ice_aq_get_storm_ctrl(struct ice_hw *hw, u32 *bcast_thresh, u32 *mcast_thresh,
1291 		      u32 *ctl_bitmask)
1292 {
1293 	enum ice_status status;
1294 	struct ice_aq_desc desc;
1295 
1296 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_get_storm_cfg);
1297 
1298 	status = ice_aq_send_cmd(hw, &desc, NULL, 0, NULL);
1299 	if (!status) {
1300 		struct ice_aqc_storm_cfg *resp = &desc.params.storm_conf;
1301 
1302 		if (bcast_thresh)
1303 			*bcast_thresh = LE32_TO_CPU(resp->bcast_thresh_size) &
1304 				ICE_AQ_THRESHOLD_M;
1305 		if (mcast_thresh)
1306 			*mcast_thresh = LE32_TO_CPU(resp->mcast_thresh_size) &
1307 				ICE_AQ_THRESHOLD_M;
1308 		if (ctl_bitmask)
1309 			*ctl_bitmask = LE32_TO_CPU(resp->storm_ctrl_ctrl);
1310 	}
1311 
1312 	return status;
1313 }
1314 
1315 /**
1316  * ice_aq_sw_rules - add/update/remove switch rules
1317  * @hw: pointer to the HW struct
1318  * @rule_list: pointer to switch rule population list
1319  * @rule_list_sz: total size of the rule list in bytes
1320  * @num_rules: number of switch rules in the rule_list
1321  * @opc: switch rules population command type - pass in the command opcode
1322  * @cd: pointer to command details structure or NULL
1323  *
1324  * Add(0x02a0)/Update(0x02a1)/Remove(0x02a2) switch rules commands to firmware
1325  */
1326 static enum ice_status
1327 ice_aq_sw_rules(struct ice_hw *hw, void *rule_list, u16 rule_list_sz,
1328 		u8 num_rules, enum ice_adminq_opc opc, struct ice_sq_cd *cd)
1329 {
1330 	struct ice_aq_desc desc;
1331 
1332 	ice_debug(hw, ICE_DBG_TRACE, "ice_aq_sw_rules");
1333 
1334 	if (opc != ice_aqc_opc_add_sw_rules &&
1335 	    opc != ice_aqc_opc_update_sw_rules &&
1336 	    opc != ice_aqc_opc_remove_sw_rules)
1337 		return ICE_ERR_PARAM;
1338 
1339 	ice_fill_dflt_direct_cmd_desc(&desc, opc);
1340 
1341 	desc.flags |= CPU_TO_LE16(ICE_AQ_FLAG_RD);
1342 	desc.params.sw_rules.num_rules_fltr_entry_index =
1343 		CPU_TO_LE16(num_rules);
1344 	return ice_aq_send_cmd(hw, &desc, rule_list, rule_list_sz, cd);
1345 }
1346 
1347 /**
1348  * ice_aq_add_recipe - add switch recipe
1349  * @hw: pointer to the HW struct
1350  * @s_recipe_list: pointer to switch rule population list
1351  * @num_recipes: number of switch recipes in the list
1352  * @cd: pointer to command details structure or NULL
1353  *
1354  * Add(0x0290)
1355  */
1356 enum ice_status
1357 ice_aq_add_recipe(struct ice_hw *hw,
1358 		  struct ice_aqc_recipe_data_elem *s_recipe_list,
1359 		  u16 num_recipes, struct ice_sq_cd *cd)
1360 {
1361 	struct ice_aqc_add_get_recipe *cmd;
1362 	struct ice_aq_desc desc;
1363 	u16 buf_size;
1364 
1365 	ice_debug(hw, ICE_DBG_TRACE, "ice_aq_add_recipe");
1366 	cmd = &desc.params.add_get_recipe;
1367 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_add_recipe);
1368 
1369 	cmd->num_sub_recipes = CPU_TO_LE16(num_recipes);
1370 	desc.flags |= CPU_TO_LE16(ICE_AQ_FLAG_RD);
1371 
1372 	buf_size = num_recipes * sizeof(*s_recipe_list);
1373 
1374 	return ice_aq_send_cmd(hw, &desc, s_recipe_list, buf_size, cd);
1375 }
1376 
1377 /**
1378  * ice_aq_get_recipe - get switch recipe
1379  * @hw: pointer to the HW struct
1380  * @s_recipe_list: pointer to switch rule population list
1381  * @num_recipes: pointer to the number of recipes (input and output)
1382  * @recipe_root: root recipe number of recipe(s) to retrieve
1383  * @cd: pointer to command details structure or NULL
1384  *
1385  * Get(0x0292)
1386  *
1387  * On input, *num_recipes should equal the number of entries in s_recipe_list.
1388  * On output, *num_recipes will equal the number of entries returned in
1389  * s_recipe_list.
1390  *
1391  * The caller must supply enough space in s_recipe_list to hold all possible
1392  * recipes and *num_recipes must equal ICE_MAX_NUM_RECIPES.
1393  */
1394 enum ice_status
1395 ice_aq_get_recipe(struct ice_hw *hw,
1396 		  struct ice_aqc_recipe_data_elem *s_recipe_list,
1397 		  u16 *num_recipes, u16 recipe_root, struct ice_sq_cd *cd)
1398 {
1399 	struct ice_aqc_add_get_recipe *cmd;
1400 	struct ice_aq_desc desc;
1401 	enum ice_status status;
1402 	u16 buf_size;
1403 
1404 	if (*num_recipes != ICE_MAX_NUM_RECIPES)
1405 		return ICE_ERR_PARAM;
1406 
1407 	ice_debug(hw, ICE_DBG_TRACE, "ice_aq_get_recipe");
1408 	cmd = &desc.params.add_get_recipe;
1409 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_get_recipe);
1410 
1411 	cmd->return_index = CPU_TO_LE16(recipe_root);
1412 	cmd->num_sub_recipes = 0;
1413 
1414 	buf_size = *num_recipes * sizeof(*s_recipe_list);
1415 
1416 	status = ice_aq_send_cmd(hw, &desc, s_recipe_list, buf_size, cd);
1417 	/* cppcheck-suppress constArgument */
1418 	*num_recipes = LE16_TO_CPU(cmd->num_sub_recipes);
1419 
1420 	return status;
1421 }
1422 
1423 /**
1424  * ice_aq_map_recipe_to_profile - Map recipe to packet profile
1425  * @hw: pointer to the HW struct
1426  * @profile_id: package profile ID to associate the recipe with
1427  * @r_bitmap: Recipe bitmap filled in and need to be returned as response
1428  * @cd: pointer to command details structure or NULL
1429  * Recipe to profile association (0x0291)
1430  */
1431 enum ice_status
1432 ice_aq_map_recipe_to_profile(struct ice_hw *hw, u32 profile_id, u8 *r_bitmap,
1433 			     struct ice_sq_cd *cd)
1434 {
1435 	struct ice_aqc_recipe_to_profile *cmd;
1436 	struct ice_aq_desc desc;
1437 
1438 	ice_debug(hw, ICE_DBG_TRACE, "ice_aq_assoc_recipe_to_prof");
1439 	cmd = &desc.params.recipe_to_profile;
1440 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_recipe_to_profile);
1441 	cmd->profile_id = CPU_TO_LE16(profile_id);
1442 	/* Set the recipe ID bit in the bitmask to let the device know which
1443 	 * profile we are associating the recipe to
1444 	 */
1445 	ice_memcpy(cmd->recipe_assoc, r_bitmap, sizeof(cmd->recipe_assoc),
1446 		   ICE_NONDMA_TO_NONDMA);
1447 
1448 	return ice_aq_send_cmd(hw, &desc, NULL, 0, cd);
1449 }
1450 
1451 /**
1452  * ice_aq_get_recipe_to_profile - Map recipe to packet profile
1453  * @hw: pointer to the HW struct
1454  * @profile_id: package profile ID to associate the recipe with
1455  * @r_bitmap: Recipe bitmap filled in and need to be returned as response
1456  * @cd: pointer to command details structure or NULL
1457  * Associate profile ID with given recipe (0x0293)
1458  */
1459 enum ice_status
1460 ice_aq_get_recipe_to_profile(struct ice_hw *hw, u32 profile_id, u8 *r_bitmap,
1461 			     struct ice_sq_cd *cd)
1462 {
1463 	struct ice_aqc_recipe_to_profile *cmd;
1464 	struct ice_aq_desc desc;
1465 	enum ice_status status;
1466 
1467 	ice_debug(hw, ICE_DBG_TRACE, "ice_aq_get_recipe_to_prof");
1468 	cmd = &desc.params.recipe_to_profile;
1469 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_get_recipe_to_profile);
1470 	cmd->profile_id = CPU_TO_LE16(profile_id);
1471 
1472 	status = ice_aq_send_cmd(hw, &desc, NULL, 0, cd);
1473 	if (!status)
1474 		ice_memcpy(r_bitmap, cmd->recipe_assoc,
1475 			   sizeof(cmd->recipe_assoc), ICE_NONDMA_TO_NONDMA);
1476 
1477 	return status;
1478 }
1479 
1480 /**
1481  * ice_alloc_recipe - add recipe resource
1482  * @hw: pointer to the hardware structure
1483  * @rid: recipe ID returned as response to AQ call
1484  */
1485 enum ice_status ice_alloc_recipe(struct ice_hw *hw, u16 *rid)
1486 {
1487 	struct ice_aqc_alloc_free_res_elem *sw_buf;
1488 	enum ice_status status;
1489 	u16 buf_len;
1490 
1491 	buf_len = sizeof(*sw_buf);
1492 	sw_buf = (struct ice_aqc_alloc_free_res_elem *)ice_malloc(hw, buf_len);
1493 	if (!sw_buf)
1494 		return ICE_ERR_NO_MEMORY;
1495 
1496 	sw_buf->num_elems = CPU_TO_LE16(1);
1497 	sw_buf->res_type = CPU_TO_LE16((ICE_AQC_RES_TYPE_RECIPE <<
1498 					ICE_AQC_RES_TYPE_S) |
1499 					ICE_AQC_RES_TYPE_FLAG_SHARED);
1500 	status = ice_aq_alloc_free_res(hw, 1, sw_buf, buf_len,
1501 				       ice_aqc_opc_alloc_res, NULL);
1502 	if (!status)
1503 		*rid = LE16_TO_CPU(sw_buf->elem[0].e.sw_resp);
1504 	ice_free(hw, sw_buf);
1505 
1506 	return status;
1507 }
1508 
1509 /* ice_init_port_info - Initialize port_info with switch configuration data
1510  * @pi: pointer to port_info
1511  * @vsi_port_num: VSI number or port number
1512  * @type: Type of switch element (port or VSI)
1513  * @swid: switch ID of the switch the element is attached to
1514  * @pf_vf_num: PF or VF number
1515  * @is_vf: true if the element is a VF, false otherwise
1516  */
1517 static void
1518 ice_init_port_info(struct ice_port_info *pi, u16 vsi_port_num, u8 type,
1519 		   u16 swid, u16 pf_vf_num, bool is_vf)
1520 {
1521 	switch (type) {
1522 	case ICE_AQC_GET_SW_CONF_RESP_PHYS_PORT:
1523 		pi->lport = (u8)(vsi_port_num & ICE_LPORT_MASK);
1524 		pi->sw_id = swid;
1525 		pi->pf_vf_num = pf_vf_num;
1526 		pi->is_vf = is_vf;
1527 		pi->dflt_tx_vsi_num = ICE_DFLT_VSI_INVAL;
1528 		pi->dflt_rx_vsi_num = ICE_DFLT_VSI_INVAL;
1529 		break;
1530 	default:
1531 		ice_debug(pi->hw, ICE_DBG_SW,
1532 			  "incorrect VSI/port type received\n");
1533 		break;
1534 	}
1535 }
1536 
1537 /* ice_get_initial_sw_cfg - Get initial port and default VSI data
1538  * @hw: pointer to the hardware structure
1539  */
1540 enum ice_status ice_get_initial_sw_cfg(struct ice_hw *hw)
1541 {
1542 	struct ice_aqc_get_sw_cfg_resp *rbuf;
1543 	enum ice_status status;
1544 	u16 num_total_ports;
1545 	u16 req_desc = 0;
1546 	u16 num_elems;
1547 	u16 j = 0;
1548 	u16 i;
1549 
1550 	num_total_ports = 1;
1551 
1552 	rbuf = (struct ice_aqc_get_sw_cfg_resp *)
1553 		ice_malloc(hw, ICE_SW_CFG_MAX_BUF_LEN);
1554 
1555 	if (!rbuf)
1556 		return ICE_ERR_NO_MEMORY;
1557 
1558 	/* Multiple calls to ice_aq_get_sw_cfg may be required
1559 	 * to get all the switch configuration information. The need
1560 	 * for additional calls is indicated by ice_aq_get_sw_cfg
1561 	 * writing a non-zero value in req_desc
1562 	 */
1563 	do {
1564 		status = ice_aq_get_sw_cfg(hw, rbuf, ICE_SW_CFG_MAX_BUF_LEN,
1565 					   &req_desc, &num_elems, NULL);
1566 
1567 		if (status)
1568 			break;
1569 
1570 		for (i = 0; i < num_elems; i++) {
1571 			struct ice_aqc_get_sw_cfg_resp_elem *ele;
1572 			u16 pf_vf_num, swid, vsi_port_num;
1573 			bool is_vf = false;
1574 			u8 type;
1575 
1576 			ele = rbuf[i].elements;
1577 			vsi_port_num = LE16_TO_CPU(ele->vsi_port_num) &
1578 				ICE_AQC_GET_SW_CONF_RESP_VSI_PORT_NUM_M;
1579 
1580 			pf_vf_num = LE16_TO_CPU(ele->pf_vf_num) &
1581 				ICE_AQC_GET_SW_CONF_RESP_FUNC_NUM_M;
1582 
1583 			swid = LE16_TO_CPU(ele->swid);
1584 
1585 			if (LE16_TO_CPU(ele->pf_vf_num) &
1586 			    ICE_AQC_GET_SW_CONF_RESP_IS_VF)
1587 				is_vf = true;
1588 
1589 			type = LE16_TO_CPU(ele->vsi_port_num) >>
1590 				ICE_AQC_GET_SW_CONF_RESP_TYPE_S;
1591 
1592 			switch (type) {
1593 			case ICE_AQC_GET_SW_CONF_RESP_PHYS_PORT:
1594 			case ICE_AQC_GET_SW_CONF_RESP_VIRT_PORT:
1595 				if (j == num_total_ports) {
1596 					ice_debug(hw, ICE_DBG_SW,
1597 						  "more ports than expected\n");
1598 					status = ICE_ERR_CFG;
1599 					goto out;
1600 				}
1601 				ice_init_port_info(hw->port_info,
1602 						   vsi_port_num, type, swid,
1603 						   pf_vf_num, is_vf);
1604 				j++;
1605 				break;
1606 			default:
1607 				break;
1608 			}
1609 		}
1610 	} while (req_desc && !status);
1611 
1612 
1613 out:
1614 	ice_free(hw, (void *)rbuf);
1615 	return status;
1616 }
1617 
1618 
1619 /**
1620  * ice_fill_sw_info - Helper function to populate lb_en and lan_en
1621  * @hw: pointer to the hardware structure
1622  * @fi: filter info structure to fill/update
1623  *
1624  * This helper function populates the lb_en and lan_en elements of the provided
1625  * ice_fltr_info struct using the switch's type and characteristics of the
1626  * switch rule being configured.
1627  */
1628 static void ice_fill_sw_info(struct ice_hw *hw, struct ice_fltr_info *fi)
1629 {
1630 	fi->lb_en = false;
1631 	fi->lan_en = false;
1632 	if ((fi->flag & ICE_FLTR_TX) &&
1633 	    (fi->fltr_act == ICE_FWD_TO_VSI ||
1634 	     fi->fltr_act == ICE_FWD_TO_VSI_LIST ||
1635 	     fi->fltr_act == ICE_FWD_TO_Q ||
1636 	     fi->fltr_act == ICE_FWD_TO_QGRP)) {
1637 		/* Setting LB for prune actions will result in replicated
1638 		 * packets to the internal switch that will be dropped.
1639 		 */
1640 		if (fi->lkup_type != ICE_SW_LKUP_VLAN)
1641 			fi->lb_en = true;
1642 
1643 		/* Set lan_en to TRUE if
1644 		 * 1. The switch is a VEB AND
1645 		 * 2
1646 		 * 2.1 The lookup is a directional lookup like ethertype,
1647 		 * promiscuous, ethertype-MAC, promiscuous-VLAN
1648 		 * and default-port OR
1649 		 * 2.2 The lookup is VLAN, OR
1650 		 * 2.3 The lookup is MAC with mcast or bcast addr for MAC, OR
1651 		 * 2.4 The lookup is MAC_VLAN with mcast or bcast addr for MAC.
1652 		 *
1653 		 * OR
1654 		 *
1655 		 * The switch is a VEPA.
1656 		 *
1657 		 * In all other cases, the LAN enable has to be set to false.
1658 		 */
1659 		if (hw->evb_veb) {
1660 			if (fi->lkup_type == ICE_SW_LKUP_ETHERTYPE ||
1661 			    fi->lkup_type == ICE_SW_LKUP_PROMISC ||
1662 			    fi->lkup_type == ICE_SW_LKUP_ETHERTYPE_MAC ||
1663 			    fi->lkup_type == ICE_SW_LKUP_PROMISC_VLAN ||
1664 			    fi->lkup_type == ICE_SW_LKUP_DFLT ||
1665 			    fi->lkup_type == ICE_SW_LKUP_VLAN ||
1666 			    (fi->lkup_type == ICE_SW_LKUP_MAC &&
1667 			     !IS_UNICAST_ETHER_ADDR(fi->l_data.mac.mac_addr)) ||
1668 			    (fi->lkup_type == ICE_SW_LKUP_MAC_VLAN &&
1669 			     !IS_UNICAST_ETHER_ADDR(fi->l_data.mac.mac_addr)))
1670 				fi->lan_en = true;
1671 		} else {
1672 			fi->lan_en = true;
1673 		}
1674 	}
1675 }
1676 
1677 /**
1678  * ice_ilog2 - Calculates integer log base 2 of a number
1679  * @n: number on which to perform operation
1680  */
1681 static int ice_ilog2(u64 n)
1682 {
1683 	int i;
1684 
1685 	for (i = 63; i >= 0; i--)
1686 		if (((u64)1 << i) & n)
1687 			return i;
1688 
1689 	return -1;
1690 }
1691 
1692 /**
1693  * ice_fill_sw_rule - Helper function to fill switch rule structure
1694  * @hw: pointer to the hardware structure
1695  * @f_info: entry containing packet forwarding information
1696  * @s_rule: switch rule structure to be filled in based on mac_entry
1697  * @opc: switch rules population command type - pass in the command opcode
1698  */
1699 static void
1700 ice_fill_sw_rule(struct ice_hw *hw, struct ice_fltr_info *f_info,
1701 		 struct ice_aqc_sw_rules_elem *s_rule, enum ice_adminq_opc opc)
1702 {
1703 	u16 vlan_id = ICE_MAX_VLAN_ID + 1;
1704 	void *daddr = NULL;
1705 	u16 eth_hdr_sz;
1706 	u8 *eth_hdr;
1707 	u32 act = 0;
1708 	__be16 *off;
1709 	u8 q_rgn;
1710 
1711 	if (opc == ice_aqc_opc_remove_sw_rules) {
1712 		s_rule->pdata.lkup_tx_rx.act = 0;
1713 		s_rule->pdata.lkup_tx_rx.index =
1714 			CPU_TO_LE16(f_info->fltr_rule_id);
1715 		s_rule->pdata.lkup_tx_rx.hdr_len = 0;
1716 		return;
1717 	}
1718 
1719 	eth_hdr_sz = sizeof(dummy_eth_header);
1720 	eth_hdr = s_rule->pdata.lkup_tx_rx.hdr;
1721 
1722 	/* initialize the ether header with a dummy header */
1723 	ice_memcpy(eth_hdr, dummy_eth_header, eth_hdr_sz, ICE_NONDMA_TO_NONDMA);
1724 	ice_fill_sw_info(hw, f_info);
1725 
1726 	switch (f_info->fltr_act) {
1727 	case ICE_FWD_TO_VSI:
1728 		act |= (f_info->fwd_id.hw_vsi_id << ICE_SINGLE_ACT_VSI_ID_S) &
1729 			ICE_SINGLE_ACT_VSI_ID_M;
1730 		if (f_info->lkup_type != ICE_SW_LKUP_VLAN)
1731 			act |= ICE_SINGLE_ACT_VSI_FORWARDING |
1732 				ICE_SINGLE_ACT_VALID_BIT;
1733 		break;
1734 	case ICE_FWD_TO_VSI_LIST:
1735 		act |= ICE_SINGLE_ACT_VSI_LIST;
1736 		act |= (f_info->fwd_id.vsi_list_id <<
1737 			ICE_SINGLE_ACT_VSI_LIST_ID_S) &
1738 			ICE_SINGLE_ACT_VSI_LIST_ID_M;
1739 		if (f_info->lkup_type != ICE_SW_LKUP_VLAN)
1740 			act |= ICE_SINGLE_ACT_VSI_FORWARDING |
1741 				ICE_SINGLE_ACT_VALID_BIT;
1742 		break;
1743 	case ICE_FWD_TO_Q:
1744 		act |= ICE_SINGLE_ACT_TO_Q;
1745 		act |= (f_info->fwd_id.q_id << ICE_SINGLE_ACT_Q_INDEX_S) &
1746 			ICE_SINGLE_ACT_Q_INDEX_M;
1747 		break;
1748 	case ICE_DROP_PACKET:
1749 		act |= ICE_SINGLE_ACT_VSI_FORWARDING | ICE_SINGLE_ACT_DROP |
1750 			ICE_SINGLE_ACT_VALID_BIT;
1751 		break;
1752 	case ICE_FWD_TO_QGRP:
1753 		q_rgn = f_info->qgrp_size > 0 ?
1754 			(u8)ice_ilog2(f_info->qgrp_size) : 0;
1755 		act |= ICE_SINGLE_ACT_TO_Q;
1756 		act |= (f_info->fwd_id.q_id << ICE_SINGLE_ACT_Q_INDEX_S) &
1757 			ICE_SINGLE_ACT_Q_INDEX_M;
1758 		act |= (q_rgn << ICE_SINGLE_ACT_Q_REGION_S) &
1759 			ICE_SINGLE_ACT_Q_REGION_M;
1760 		break;
1761 	default:
1762 		return;
1763 	}
1764 
1765 	if (f_info->lb_en)
1766 		act |= ICE_SINGLE_ACT_LB_ENABLE;
1767 	if (f_info->lan_en)
1768 		act |= ICE_SINGLE_ACT_LAN_ENABLE;
1769 
1770 	switch (f_info->lkup_type) {
1771 	case ICE_SW_LKUP_MAC:
1772 		daddr = f_info->l_data.mac.mac_addr;
1773 		break;
1774 	case ICE_SW_LKUP_VLAN:
1775 		vlan_id = f_info->l_data.vlan.vlan_id;
1776 		if (f_info->fltr_act == ICE_FWD_TO_VSI ||
1777 		    f_info->fltr_act == ICE_FWD_TO_VSI_LIST) {
1778 			act |= ICE_SINGLE_ACT_PRUNE;
1779 			act |= ICE_SINGLE_ACT_EGRESS | ICE_SINGLE_ACT_INGRESS;
1780 		}
1781 		break;
1782 	case ICE_SW_LKUP_ETHERTYPE_MAC:
1783 		daddr = f_info->l_data.ethertype_mac.mac_addr;
1784 		/* fall-through */
1785 	case ICE_SW_LKUP_ETHERTYPE:
1786 		off = (_FORCE_ __be16 *)(eth_hdr + ICE_ETH_ETHTYPE_OFFSET);
1787 		*off = CPU_TO_BE16(f_info->l_data.ethertype_mac.ethertype);
1788 		break;
1789 	case ICE_SW_LKUP_MAC_VLAN:
1790 		daddr = f_info->l_data.mac_vlan.mac_addr;
1791 		vlan_id = f_info->l_data.mac_vlan.vlan_id;
1792 		break;
1793 	case ICE_SW_LKUP_PROMISC_VLAN:
1794 		vlan_id = f_info->l_data.mac_vlan.vlan_id;
1795 		/* fall-through */
1796 	case ICE_SW_LKUP_PROMISC:
1797 		daddr = f_info->l_data.mac_vlan.mac_addr;
1798 		break;
1799 	default:
1800 		break;
1801 	}
1802 
1803 	s_rule->type = (f_info->flag & ICE_FLTR_RX) ?
1804 		CPU_TO_LE16(ICE_AQC_SW_RULES_T_LKUP_RX) :
1805 		CPU_TO_LE16(ICE_AQC_SW_RULES_T_LKUP_TX);
1806 
1807 	/* Recipe set depending on lookup type */
1808 	s_rule->pdata.lkup_tx_rx.recipe_id = CPU_TO_LE16(f_info->lkup_type);
1809 	s_rule->pdata.lkup_tx_rx.src = CPU_TO_LE16(f_info->src);
1810 	s_rule->pdata.lkup_tx_rx.act = CPU_TO_LE32(act);
1811 
1812 	if (daddr)
1813 		ice_memcpy(eth_hdr + ICE_ETH_DA_OFFSET, daddr, ETH_ALEN,
1814 			   ICE_NONDMA_TO_NONDMA);
1815 
1816 	if (!(vlan_id > ICE_MAX_VLAN_ID)) {
1817 		off = (_FORCE_ __be16 *)(eth_hdr + ICE_ETH_VLAN_TCI_OFFSET);
1818 		*off = CPU_TO_BE16(vlan_id);
1819 	}
1820 
1821 	/* Create the switch rule with the final dummy Ethernet header */
1822 	if (opc != ice_aqc_opc_update_sw_rules)
1823 		s_rule->pdata.lkup_tx_rx.hdr_len = CPU_TO_LE16(eth_hdr_sz);
1824 }
1825 
1826 /**
1827  * ice_add_marker_act
1828  * @hw: pointer to the hardware structure
1829  * @m_ent: the management entry for which sw marker needs to be added
1830  * @sw_marker: sw marker to tag the Rx descriptor with
1831  * @l_id: large action resource ID
1832  *
1833  * Create a large action to hold software marker and update the switch rule
1834  * entry pointed by m_ent with newly created large action
1835  */
1836 static enum ice_status
1837 ice_add_marker_act(struct ice_hw *hw, struct ice_fltr_mgmt_list_entry *m_ent,
1838 		   u16 sw_marker, u16 l_id)
1839 {
1840 	struct ice_aqc_sw_rules_elem *lg_act, *rx_tx;
1841 	/* For software marker we need 3 large actions
1842 	 * 1. FWD action: FWD TO VSI or VSI LIST
1843 	 * 2. GENERIC VALUE action to hold the profile ID
1844 	 * 3. GENERIC VALUE action to hold the software marker ID
1845 	 */
1846 	const u16 num_lg_acts = 3;
1847 	enum ice_status status;
1848 	u16 lg_act_size;
1849 	u16 rules_size;
1850 	u32 act;
1851 	u16 id;
1852 
1853 	if (m_ent->fltr_info.lkup_type != ICE_SW_LKUP_MAC)
1854 		return ICE_ERR_PARAM;
1855 
1856 	/* Create two back-to-back switch rules and submit them to the HW using
1857 	 * one memory buffer:
1858 	 *    1. Large Action
1859 	 *    2. Look up Tx Rx
1860 	 */
1861 	lg_act_size = (u16)ICE_SW_RULE_LG_ACT_SIZE(num_lg_acts);
1862 	rules_size = lg_act_size + ICE_SW_RULE_RX_TX_ETH_HDR_SIZE;
1863 	lg_act = (struct ice_aqc_sw_rules_elem *)ice_malloc(hw, rules_size);
1864 	if (!lg_act)
1865 		return ICE_ERR_NO_MEMORY;
1866 
1867 	rx_tx = (struct ice_aqc_sw_rules_elem *)((u8 *)lg_act + lg_act_size);
1868 
1869 	/* Fill in the first switch rule i.e. large action */
1870 	lg_act->type = CPU_TO_LE16(ICE_AQC_SW_RULES_T_LG_ACT);
1871 	lg_act->pdata.lg_act.index = CPU_TO_LE16(l_id);
1872 	lg_act->pdata.lg_act.size = CPU_TO_LE16(num_lg_acts);
1873 
1874 	/* First action VSI forwarding or VSI list forwarding depending on how
1875 	 * many VSIs
1876 	 */
1877 	id = (m_ent->vsi_count > 1) ? m_ent->fltr_info.fwd_id.vsi_list_id :
1878 		m_ent->fltr_info.fwd_id.hw_vsi_id;
1879 
1880 	act = ICE_LG_ACT_VSI_FORWARDING | ICE_LG_ACT_VALID_BIT;
1881 	act |= (id << ICE_LG_ACT_VSI_LIST_ID_S) &
1882 		ICE_LG_ACT_VSI_LIST_ID_M;
1883 	if (m_ent->vsi_count > 1)
1884 		act |= ICE_LG_ACT_VSI_LIST;
1885 	lg_act->pdata.lg_act.act[0] = CPU_TO_LE32(act);
1886 
1887 	/* Second action descriptor type */
1888 	act = ICE_LG_ACT_GENERIC;
1889 
1890 	act |= (1 << ICE_LG_ACT_GENERIC_VALUE_S) & ICE_LG_ACT_GENERIC_VALUE_M;
1891 	lg_act->pdata.lg_act.act[1] = CPU_TO_LE32(act);
1892 
1893 	act = (ICE_LG_ACT_GENERIC_OFF_RX_DESC_PROF_IDX <<
1894 	       ICE_LG_ACT_GENERIC_OFFSET_S) & ICE_LG_ACT_GENERIC_OFFSET_M;
1895 
1896 	/* Third action Marker value */
1897 	act |= ICE_LG_ACT_GENERIC;
1898 	act |= (sw_marker << ICE_LG_ACT_GENERIC_VALUE_S) &
1899 		ICE_LG_ACT_GENERIC_VALUE_M;
1900 
1901 	lg_act->pdata.lg_act.act[2] = CPU_TO_LE32(act);
1902 
1903 	/* call the fill switch rule to fill the lookup Tx Rx structure */
1904 	ice_fill_sw_rule(hw, &m_ent->fltr_info, rx_tx,
1905 			 ice_aqc_opc_update_sw_rules);
1906 
1907 	/* Update the action to point to the large action ID */
1908 	rx_tx->pdata.lkup_tx_rx.act =
1909 		CPU_TO_LE32(ICE_SINGLE_ACT_PTR |
1910 			    ((l_id << ICE_SINGLE_ACT_PTR_VAL_S) &
1911 			     ICE_SINGLE_ACT_PTR_VAL_M));
1912 
1913 	/* Use the filter rule ID of the previously created rule with single
1914 	 * act. Once the update happens, hardware will treat this as large
1915 	 * action
1916 	 */
1917 	rx_tx->pdata.lkup_tx_rx.index =
1918 		CPU_TO_LE16(m_ent->fltr_info.fltr_rule_id);
1919 
1920 	status = ice_aq_sw_rules(hw, lg_act, rules_size, 2,
1921 				 ice_aqc_opc_update_sw_rules, NULL);
1922 	if (!status) {
1923 		m_ent->lg_act_idx = l_id;
1924 		m_ent->sw_marker_id = sw_marker;
1925 	}
1926 
1927 	ice_free(hw, lg_act);
1928 	return status;
1929 }
1930 
1931 /**
1932  * ice_add_counter_act - add/update filter rule with counter action
1933  * @hw: pointer to the hardware structure
1934  * @m_ent: the management entry for which counter needs to be added
1935  * @counter_id: VLAN counter ID returned as part of allocate resource
1936  * @l_id: large action resource ID
1937  */
1938 static enum ice_status
1939 ice_add_counter_act(struct ice_hw *hw, struct ice_fltr_mgmt_list_entry *m_ent,
1940 		    u16 counter_id, u16 l_id)
1941 {
1942 	struct ice_aqc_sw_rules_elem *lg_act;
1943 	struct ice_aqc_sw_rules_elem *rx_tx;
1944 	enum ice_status status;
1945 	/* 2 actions will be added while adding a large action counter */
1946 	const int num_acts = 2;
1947 	u16 lg_act_size;
1948 	u16 rules_size;
1949 	u16 f_rule_id;
1950 	u32 act;
1951 	u16 id;
1952 
1953 	if (m_ent->fltr_info.lkup_type != ICE_SW_LKUP_MAC)
1954 		return ICE_ERR_PARAM;
1955 
1956 	/* Create two back-to-back switch rules and submit them to the HW using
1957 	 * one memory buffer:
1958 	 * 1. Large Action
1959 	 * 2. Look up Tx Rx
1960 	 */
1961 	lg_act_size = (u16)ICE_SW_RULE_LG_ACT_SIZE(num_acts);
1962 	rules_size = lg_act_size + ICE_SW_RULE_RX_TX_ETH_HDR_SIZE;
1963 	lg_act = (struct ice_aqc_sw_rules_elem *)ice_malloc(hw,
1964 								 rules_size);
1965 	if (!lg_act)
1966 		return ICE_ERR_NO_MEMORY;
1967 
1968 	rx_tx = (struct ice_aqc_sw_rules_elem *)
1969 		((u8 *)lg_act + lg_act_size);
1970 
1971 	/* Fill in the first switch rule i.e. large action */
1972 	lg_act->type = CPU_TO_LE16(ICE_AQC_SW_RULES_T_LG_ACT);
1973 	lg_act->pdata.lg_act.index = CPU_TO_LE16(l_id);
1974 	lg_act->pdata.lg_act.size = CPU_TO_LE16(num_acts);
1975 
1976 	/* First action VSI forwarding or VSI list forwarding depending on how
1977 	 * many VSIs
1978 	 */
1979 	id = (m_ent->vsi_count > 1) ?  m_ent->fltr_info.fwd_id.vsi_list_id :
1980 		m_ent->fltr_info.fwd_id.hw_vsi_id;
1981 
1982 	act = ICE_LG_ACT_VSI_FORWARDING | ICE_LG_ACT_VALID_BIT;
1983 	act |= (id << ICE_LG_ACT_VSI_LIST_ID_S) &
1984 		ICE_LG_ACT_VSI_LIST_ID_M;
1985 	if (m_ent->vsi_count > 1)
1986 		act |= ICE_LG_ACT_VSI_LIST;
1987 	lg_act->pdata.lg_act.act[0] = CPU_TO_LE32(act);
1988 
1989 	/* Second action counter ID */
1990 	act = ICE_LG_ACT_STAT_COUNT;
1991 	act |= (counter_id << ICE_LG_ACT_STAT_COUNT_S) &
1992 		ICE_LG_ACT_STAT_COUNT_M;
1993 	lg_act->pdata.lg_act.act[1] = CPU_TO_LE32(act);
1994 
1995 	/* call the fill switch rule to fill the lookup Tx Rx structure */
1996 	ice_fill_sw_rule(hw, &m_ent->fltr_info, rx_tx,
1997 			 ice_aqc_opc_update_sw_rules);
1998 
1999 	act = ICE_SINGLE_ACT_PTR;
2000 	act |= (l_id << ICE_SINGLE_ACT_PTR_VAL_S) & ICE_SINGLE_ACT_PTR_VAL_M;
2001 	rx_tx->pdata.lkup_tx_rx.act = CPU_TO_LE32(act);
2002 
2003 	/* Use the filter rule ID of the previously created rule with single
2004 	 * act. Once the update happens, hardware will treat this as large
2005 	 * action
2006 	 */
2007 	f_rule_id = m_ent->fltr_info.fltr_rule_id;
2008 	rx_tx->pdata.lkup_tx_rx.index = CPU_TO_LE16(f_rule_id);
2009 
2010 	status = ice_aq_sw_rules(hw, lg_act, rules_size, 2,
2011 				 ice_aqc_opc_update_sw_rules, NULL);
2012 	if (!status) {
2013 		m_ent->lg_act_idx = l_id;
2014 		m_ent->counter_index = counter_id;
2015 	}
2016 
2017 	ice_free(hw, lg_act);
2018 	return status;
2019 }
2020 
2021 /**
2022  * ice_create_vsi_list_map
2023  * @hw: pointer to the hardware structure
2024  * @vsi_handle_arr: array of VSI handles to set in the VSI mapping
2025  * @num_vsi: number of VSI handles in the array
2026  * @vsi_list_id: VSI list ID generated as part of allocate resource
2027  *
2028  * Helper function to create a new entry of VSI list ID to VSI mapping
2029  * using the given VSI list ID
2030  */
2031 static struct ice_vsi_list_map_info *
2032 ice_create_vsi_list_map(struct ice_hw *hw, u16 *vsi_handle_arr, u16 num_vsi,
2033 			u16 vsi_list_id)
2034 {
2035 	struct ice_switch_info *sw = hw->switch_info;
2036 	struct ice_vsi_list_map_info *v_map;
2037 	int i;
2038 
2039 	v_map = (struct ice_vsi_list_map_info *)ice_calloc(hw, 1,
2040 		sizeof(*v_map));
2041 	if (!v_map)
2042 		return NULL;
2043 
2044 	v_map->vsi_list_id = vsi_list_id;
2045 	v_map->ref_cnt = 1;
2046 	for (i = 0; i < num_vsi; i++)
2047 		ice_set_bit(vsi_handle_arr[i], v_map->vsi_map);
2048 
2049 	LIST_ADD(&v_map->list_entry, &sw->vsi_list_map_head);
2050 	return v_map;
2051 }
2052 
2053 /**
2054  * ice_update_vsi_list_rule
2055  * @hw: pointer to the hardware structure
2056  * @vsi_handle_arr: array of VSI handles to form a VSI list
2057  * @num_vsi: number of VSI handles in the array
2058  * @vsi_list_id: VSI list ID generated as part of allocate resource
2059  * @remove: Boolean value to indicate if this is a remove action
2060  * @opc: switch rules population command type - pass in the command opcode
2061  * @lkup_type: lookup type of the filter
2062  *
2063  * Call AQ command to add a new switch rule or update existing switch rule
2064  * using the given VSI list ID
2065  */
2066 static enum ice_status
2067 ice_update_vsi_list_rule(struct ice_hw *hw, u16 *vsi_handle_arr, u16 num_vsi,
2068 			 u16 vsi_list_id, bool remove, enum ice_adminq_opc opc,
2069 			 enum ice_sw_lkup_type lkup_type)
2070 {
2071 	struct ice_aqc_sw_rules_elem *s_rule;
2072 	enum ice_status status;
2073 	u16 s_rule_size;
2074 	u16 type;
2075 	int i;
2076 
2077 	if (!num_vsi)
2078 		return ICE_ERR_PARAM;
2079 
2080 	if (lkup_type == ICE_SW_LKUP_MAC ||
2081 	    lkup_type == ICE_SW_LKUP_MAC_VLAN ||
2082 	    lkup_type == ICE_SW_LKUP_ETHERTYPE ||
2083 	    lkup_type == ICE_SW_LKUP_ETHERTYPE_MAC ||
2084 	    lkup_type == ICE_SW_LKUP_PROMISC ||
2085 	    lkup_type == ICE_SW_LKUP_PROMISC_VLAN ||
2086 	    lkup_type == ICE_SW_LKUP_LAST)
2087 		type = remove ? ICE_AQC_SW_RULES_T_VSI_LIST_CLEAR :
2088 				ICE_AQC_SW_RULES_T_VSI_LIST_SET;
2089 	else if (lkup_type == ICE_SW_LKUP_VLAN)
2090 		type = remove ? ICE_AQC_SW_RULES_T_PRUNE_LIST_CLEAR :
2091 				ICE_AQC_SW_RULES_T_PRUNE_LIST_SET;
2092 	else
2093 		return ICE_ERR_PARAM;
2094 
2095 	s_rule_size = (u16)ICE_SW_RULE_VSI_LIST_SIZE(num_vsi);
2096 	s_rule = (struct ice_aqc_sw_rules_elem *)ice_malloc(hw, s_rule_size);
2097 	if (!s_rule)
2098 		return ICE_ERR_NO_MEMORY;
2099 	for (i = 0; i < num_vsi; i++) {
2100 		if (!ice_is_vsi_valid(hw, vsi_handle_arr[i])) {
2101 			status = ICE_ERR_PARAM;
2102 			goto exit;
2103 		}
2104 		/* AQ call requires hw_vsi_id(s) */
2105 		s_rule->pdata.vsi_list.vsi[i] =
2106 			CPU_TO_LE16(ice_get_hw_vsi_num(hw, vsi_handle_arr[i]));
2107 	}
2108 
2109 	s_rule->type = CPU_TO_LE16(type);
2110 	s_rule->pdata.vsi_list.number_vsi = CPU_TO_LE16(num_vsi);
2111 	s_rule->pdata.vsi_list.index = CPU_TO_LE16(vsi_list_id);
2112 
2113 	status = ice_aq_sw_rules(hw, s_rule, s_rule_size, 1, opc, NULL);
2114 
2115 exit:
2116 	ice_free(hw, s_rule);
2117 	return status;
2118 }
2119 
2120 /**
2121  * ice_create_vsi_list_rule - Creates and populates a VSI list rule
2122  * @hw: pointer to the HW struct
2123  * @vsi_handle_arr: array of VSI handles to form a VSI list
2124  * @num_vsi: number of VSI handles in the array
2125  * @vsi_list_id: stores the ID of the VSI list to be created
2126  * @lkup_type: switch rule filter's lookup type
2127  */
2128 static enum ice_status
2129 ice_create_vsi_list_rule(struct ice_hw *hw, u16 *vsi_handle_arr, u16 num_vsi,
2130 			 u16 *vsi_list_id, enum ice_sw_lkup_type lkup_type)
2131 {
2132 	enum ice_status status;
2133 
2134 	status = ice_aq_alloc_free_vsi_list(hw, vsi_list_id, lkup_type,
2135 					    ice_aqc_opc_alloc_res);
2136 	if (status)
2137 		return status;
2138 
2139 	/* Update the newly created VSI list to include the specified VSIs */
2140 	return ice_update_vsi_list_rule(hw, vsi_handle_arr, num_vsi,
2141 					*vsi_list_id, false,
2142 					ice_aqc_opc_add_sw_rules, lkup_type);
2143 }
2144 
2145 /**
2146  * ice_create_pkt_fwd_rule
2147  * @hw: pointer to the hardware structure
2148  * @f_entry: entry containing packet forwarding information
2149  *
2150  * Create switch rule with given filter information and add an entry
2151  * to the corresponding filter management list to track this switch rule
2152  * and VSI mapping
2153  */
2154 static enum ice_status
2155 ice_create_pkt_fwd_rule(struct ice_hw *hw,
2156 			struct ice_fltr_list_entry *f_entry)
2157 {
2158 	struct ice_fltr_mgmt_list_entry *fm_entry;
2159 	struct ice_aqc_sw_rules_elem *s_rule;
2160 	enum ice_sw_lkup_type l_type;
2161 	struct ice_sw_recipe *recp;
2162 	enum ice_status status;
2163 
2164 	s_rule = (struct ice_aqc_sw_rules_elem *)
2165 		ice_malloc(hw, ICE_SW_RULE_RX_TX_ETH_HDR_SIZE);
2166 	if (!s_rule)
2167 		return ICE_ERR_NO_MEMORY;
2168 	fm_entry = (struct ice_fltr_mgmt_list_entry *)
2169 		   ice_malloc(hw, sizeof(*fm_entry));
2170 	if (!fm_entry) {
2171 		status = ICE_ERR_NO_MEMORY;
2172 		goto ice_create_pkt_fwd_rule_exit;
2173 	}
2174 
2175 	fm_entry->fltr_info = f_entry->fltr_info;
2176 
2177 	/* Initialize all the fields for the management entry */
2178 	fm_entry->vsi_count = 1;
2179 	fm_entry->lg_act_idx = ICE_INVAL_LG_ACT_INDEX;
2180 	fm_entry->sw_marker_id = ICE_INVAL_SW_MARKER_ID;
2181 	fm_entry->counter_index = ICE_INVAL_COUNTER_ID;
2182 
2183 	ice_fill_sw_rule(hw, &fm_entry->fltr_info, s_rule,
2184 			 ice_aqc_opc_add_sw_rules);
2185 
2186 	status = ice_aq_sw_rules(hw, s_rule, ICE_SW_RULE_RX_TX_ETH_HDR_SIZE, 1,
2187 				 ice_aqc_opc_add_sw_rules, NULL);
2188 	if (status) {
2189 		ice_free(hw, fm_entry);
2190 		goto ice_create_pkt_fwd_rule_exit;
2191 	}
2192 
2193 	f_entry->fltr_info.fltr_rule_id =
2194 		LE16_TO_CPU(s_rule->pdata.lkup_tx_rx.index);
2195 	fm_entry->fltr_info.fltr_rule_id =
2196 		LE16_TO_CPU(s_rule->pdata.lkup_tx_rx.index);
2197 
2198 	/* The book keeping entries will get removed when base driver
2199 	 * calls remove filter AQ command
2200 	 */
2201 	l_type = fm_entry->fltr_info.lkup_type;
2202 	recp = &hw->switch_info->recp_list[l_type];
2203 	LIST_ADD(&fm_entry->list_entry, &recp->filt_rules);
2204 
2205 ice_create_pkt_fwd_rule_exit:
2206 	ice_free(hw, s_rule);
2207 	return status;
2208 }
2209 
2210 /**
2211  * ice_update_pkt_fwd_rule
2212  * @hw: pointer to the hardware structure
2213  * @f_info: filter information for switch rule
2214  *
2215  * Call AQ command to update a previously created switch rule with a
2216  * VSI list ID
2217  */
2218 static enum ice_status
2219 ice_update_pkt_fwd_rule(struct ice_hw *hw, struct ice_fltr_info *f_info)
2220 {
2221 	struct ice_aqc_sw_rules_elem *s_rule;
2222 	enum ice_status status;
2223 
2224 	s_rule = (struct ice_aqc_sw_rules_elem *)
2225 		ice_malloc(hw, ICE_SW_RULE_RX_TX_ETH_HDR_SIZE);
2226 	if (!s_rule)
2227 		return ICE_ERR_NO_MEMORY;
2228 
2229 	ice_fill_sw_rule(hw, f_info, s_rule, ice_aqc_opc_update_sw_rules);
2230 
2231 	s_rule->pdata.lkup_tx_rx.index = CPU_TO_LE16(f_info->fltr_rule_id);
2232 
2233 	/* Update switch rule with new rule set to forward VSI list */
2234 	status = ice_aq_sw_rules(hw, s_rule, ICE_SW_RULE_RX_TX_ETH_HDR_SIZE, 1,
2235 				 ice_aqc_opc_update_sw_rules, NULL);
2236 
2237 	ice_free(hw, s_rule);
2238 	return status;
2239 }
2240 
2241 /**
2242  * ice_update_sw_rule_bridge_mode
2243  * @hw: pointer to the HW struct
2244  *
2245  * Updates unicast switch filter rules based on VEB/VEPA mode
2246  */
2247 enum ice_status ice_update_sw_rule_bridge_mode(struct ice_hw *hw)
2248 {
2249 	struct ice_switch_info *sw = hw->switch_info;
2250 	struct ice_fltr_mgmt_list_entry *fm_entry;
2251 	enum ice_status status = ICE_SUCCESS;
2252 	struct LIST_HEAD_TYPE *rule_head;
2253 	struct ice_lock *rule_lock; /* Lock to protect filter rule list */
2254 
2255 	rule_lock = &sw->recp_list[ICE_SW_LKUP_MAC].filt_rule_lock;
2256 	rule_head = &sw->recp_list[ICE_SW_LKUP_MAC].filt_rules;
2257 
2258 	ice_acquire_lock(rule_lock);
2259 	LIST_FOR_EACH_ENTRY(fm_entry, rule_head, ice_fltr_mgmt_list_entry,
2260 			    list_entry) {
2261 		struct ice_fltr_info *fi = &fm_entry->fltr_info;
2262 		u8 *addr = fi->l_data.mac.mac_addr;
2263 
2264 		/* Update unicast Tx rules to reflect the selected
2265 		 * VEB/VEPA mode
2266 		 */
2267 		if ((fi->flag & ICE_FLTR_TX) && IS_UNICAST_ETHER_ADDR(addr) &&
2268 		    (fi->fltr_act == ICE_FWD_TO_VSI ||
2269 		     fi->fltr_act == ICE_FWD_TO_VSI_LIST ||
2270 		     fi->fltr_act == ICE_FWD_TO_Q ||
2271 		     fi->fltr_act == ICE_FWD_TO_QGRP)) {
2272 			status = ice_update_pkt_fwd_rule(hw, fi);
2273 			if (status)
2274 				break;
2275 		}
2276 	}
2277 
2278 	ice_release_lock(rule_lock);
2279 
2280 	return status;
2281 }
2282 
2283 /**
2284  * ice_add_update_vsi_list
2285  * @hw: pointer to the hardware structure
2286  * @m_entry: pointer to current filter management list entry
2287  * @cur_fltr: filter information from the book keeping entry
2288  * @new_fltr: filter information with the new VSI to be added
2289  *
2290  * Call AQ command to add or update previously created VSI list with new VSI.
2291  *
2292  * Helper function to do book keeping associated with adding filter information
2293  * The algorithm to do the book keeping is described below :
2294  * When a VSI needs to subscribe to a given filter (MAC/VLAN/Ethtype etc.)
2295  *	if only one VSI has been added till now
2296  *		Allocate a new VSI list and add two VSIs
2297  *		to this list using switch rule command
2298  *		Update the previously created switch rule with the
2299  *		newly created VSI list ID
2300  *	if a VSI list was previously created
2301  *		Add the new VSI to the previously created VSI list set
2302  *		using the update switch rule command
2303  */
2304 static enum ice_status
2305 ice_add_update_vsi_list(struct ice_hw *hw,
2306 			struct ice_fltr_mgmt_list_entry *m_entry,
2307 			struct ice_fltr_info *cur_fltr,
2308 			struct ice_fltr_info *new_fltr)
2309 {
2310 	enum ice_status status = ICE_SUCCESS;
2311 	u16 vsi_list_id = 0;
2312 
2313 	if ((cur_fltr->fltr_act == ICE_FWD_TO_Q ||
2314 	     cur_fltr->fltr_act == ICE_FWD_TO_QGRP))
2315 		return ICE_ERR_NOT_IMPL;
2316 
2317 	if ((new_fltr->fltr_act == ICE_FWD_TO_Q ||
2318 	     new_fltr->fltr_act == ICE_FWD_TO_QGRP) &&
2319 	    (cur_fltr->fltr_act == ICE_FWD_TO_VSI ||
2320 	     cur_fltr->fltr_act == ICE_FWD_TO_VSI_LIST))
2321 		return ICE_ERR_NOT_IMPL;
2322 
2323 	if (m_entry->vsi_count < 2 && !m_entry->vsi_list_info) {
2324 		/* Only one entry existed in the mapping and it was not already
2325 		 * a part of a VSI list. So, create a VSI list with the old and
2326 		 * new VSIs.
2327 		 */
2328 		struct ice_fltr_info tmp_fltr;
2329 		u16 vsi_handle_arr[2];
2330 
2331 		/* A rule already exists with the new VSI being added */
2332 		if (cur_fltr->fwd_id.hw_vsi_id == new_fltr->fwd_id.hw_vsi_id)
2333 			return ICE_ERR_ALREADY_EXISTS;
2334 
2335 		vsi_handle_arr[0] = cur_fltr->vsi_handle;
2336 		vsi_handle_arr[1] = new_fltr->vsi_handle;
2337 		status = ice_create_vsi_list_rule(hw, &vsi_handle_arr[0], 2,
2338 						  &vsi_list_id,
2339 						  new_fltr->lkup_type);
2340 		if (status)
2341 			return status;
2342 
2343 		tmp_fltr = *new_fltr;
2344 		tmp_fltr.fltr_rule_id = cur_fltr->fltr_rule_id;
2345 		tmp_fltr.fltr_act = ICE_FWD_TO_VSI_LIST;
2346 		tmp_fltr.fwd_id.vsi_list_id = vsi_list_id;
2347 		/* Update the previous switch rule of "MAC forward to VSI" to
2348 		 * "MAC fwd to VSI list"
2349 		 */
2350 		status = ice_update_pkt_fwd_rule(hw, &tmp_fltr);
2351 		if (status)
2352 			return status;
2353 
2354 		cur_fltr->fwd_id.vsi_list_id = vsi_list_id;
2355 		cur_fltr->fltr_act = ICE_FWD_TO_VSI_LIST;
2356 		m_entry->vsi_list_info =
2357 			ice_create_vsi_list_map(hw, &vsi_handle_arr[0], 2,
2358 						vsi_list_id);
2359 
2360 		/* If this entry was large action then the large action needs
2361 		 * to be updated to point to FWD to VSI list
2362 		 */
2363 		if (m_entry->sw_marker_id != ICE_INVAL_SW_MARKER_ID)
2364 			status =
2365 			    ice_add_marker_act(hw, m_entry,
2366 					       m_entry->sw_marker_id,
2367 					       m_entry->lg_act_idx);
2368 	} else {
2369 		u16 vsi_handle = new_fltr->vsi_handle;
2370 		enum ice_adminq_opc opcode;
2371 
2372 		if (!m_entry->vsi_list_info)
2373 			return ICE_ERR_CFG;
2374 
2375 		/* A rule already exists with the new VSI being added */
2376 		if (ice_is_bit_set(m_entry->vsi_list_info->vsi_map, vsi_handle))
2377 			return ICE_SUCCESS;
2378 
2379 		/* Update the previously created VSI list set with
2380 		 * the new VSI ID passed in
2381 		 */
2382 		vsi_list_id = cur_fltr->fwd_id.vsi_list_id;
2383 		opcode = ice_aqc_opc_update_sw_rules;
2384 
2385 		status = ice_update_vsi_list_rule(hw, &vsi_handle, 1,
2386 						  vsi_list_id, false, opcode,
2387 						  new_fltr->lkup_type);
2388 		/* update VSI list mapping info with new VSI ID */
2389 		if (!status)
2390 			ice_set_bit(vsi_handle,
2391 				    m_entry->vsi_list_info->vsi_map);
2392 	}
2393 	if (!status)
2394 		m_entry->vsi_count++;
2395 	return status;
2396 }
2397 
2398 /**
2399  * ice_find_rule_entry - Search a rule entry
2400  * @hw: pointer to the hardware structure
2401  * @recp_id: lookup type for which the specified rule needs to be searched
2402  * @f_info: rule information
2403  *
2404  * Helper function to search for a given rule entry
2405  * Returns pointer to entry storing the rule if found
2406  */
2407 static struct ice_fltr_mgmt_list_entry *
2408 ice_find_rule_entry(struct ice_hw *hw, u8 recp_id, struct ice_fltr_info *f_info)
2409 {
2410 	struct ice_fltr_mgmt_list_entry *list_itr, *ret = NULL;
2411 	struct ice_switch_info *sw = hw->switch_info;
2412 	struct LIST_HEAD_TYPE *list_head;
2413 
2414 	list_head = &sw->recp_list[recp_id].filt_rules;
2415 	LIST_FOR_EACH_ENTRY(list_itr, list_head, ice_fltr_mgmt_list_entry,
2416 			    list_entry) {
2417 		if (!memcmp(&f_info->l_data, &list_itr->fltr_info.l_data,
2418 			    sizeof(f_info->l_data)) &&
2419 		    f_info->flag == list_itr->fltr_info.flag) {
2420 			ret = list_itr;
2421 			break;
2422 		}
2423 	}
2424 	return ret;
2425 }
2426 
2427 /**
2428  * ice_find_vsi_list_entry - Search VSI list map with VSI count 1
2429  * @hw: pointer to the hardware structure
2430  * @recp_id: lookup type for which VSI lists needs to be searched
2431  * @vsi_handle: VSI handle to be found in VSI list
2432  * @vsi_list_id: VSI list ID found containing vsi_handle
2433  *
2434  * Helper function to search a VSI list with single entry containing given VSI
2435  * handle element. This can be extended further to search VSI list with more
2436  * than 1 vsi_count. Returns pointer to VSI list entry if found.
2437  */
2438 static struct ice_vsi_list_map_info *
2439 ice_find_vsi_list_entry(struct ice_hw *hw, u8 recp_id, u16 vsi_handle,
2440 			u16 *vsi_list_id)
2441 {
2442 	struct ice_vsi_list_map_info *map_info = NULL;
2443 	struct ice_switch_info *sw = hw->switch_info;
2444 	struct LIST_HEAD_TYPE *list_head;
2445 
2446 	list_head = &sw->recp_list[recp_id].filt_rules;
2447 	if (sw->recp_list[recp_id].adv_rule) {
2448 		struct ice_adv_fltr_mgmt_list_entry *list_itr;
2449 
2450 		LIST_FOR_EACH_ENTRY(list_itr, list_head,
2451 				    ice_adv_fltr_mgmt_list_entry,
2452 				    list_entry) {
2453 			if (list_itr->vsi_list_info) {
2454 				map_info = list_itr->vsi_list_info;
2455 				if (ice_is_bit_set(map_info->vsi_map,
2456 						   vsi_handle)) {
2457 					*vsi_list_id = map_info->vsi_list_id;
2458 					return map_info;
2459 				}
2460 			}
2461 		}
2462 	} else {
2463 		struct ice_fltr_mgmt_list_entry *list_itr;
2464 
2465 		LIST_FOR_EACH_ENTRY(list_itr, list_head,
2466 				    ice_fltr_mgmt_list_entry,
2467 				    list_entry) {
2468 			if (list_itr->vsi_count == 1 &&
2469 			    list_itr->vsi_list_info) {
2470 				map_info = list_itr->vsi_list_info;
2471 				if (ice_is_bit_set(map_info->vsi_map,
2472 						   vsi_handle)) {
2473 					*vsi_list_id = map_info->vsi_list_id;
2474 					return map_info;
2475 				}
2476 			}
2477 		}
2478 	}
2479 	return NULL;
2480 }
2481 
2482 /**
2483  * ice_add_rule_internal - add rule for a given lookup type
2484  * @hw: pointer to the hardware structure
2485  * @recp_id: lookup type (recipe ID) for which rule has to be added
2486  * @f_entry: structure containing MAC forwarding information
2487  *
2488  * Adds or updates the rule lists for a given recipe
2489  */
2490 static enum ice_status
2491 ice_add_rule_internal(struct ice_hw *hw, u8 recp_id,
2492 		      struct ice_fltr_list_entry *f_entry)
2493 {
2494 	struct ice_switch_info *sw = hw->switch_info;
2495 	struct ice_fltr_info *new_fltr, *cur_fltr;
2496 	struct ice_fltr_mgmt_list_entry *m_entry;
2497 	struct ice_lock *rule_lock; /* Lock to protect filter rule list */
2498 	enum ice_status status = ICE_SUCCESS;
2499 
2500 	if (!ice_is_vsi_valid(hw, f_entry->fltr_info.vsi_handle))
2501 		return ICE_ERR_PARAM;
2502 
2503 	/* Load the hw_vsi_id only if the fwd action is fwd to VSI */
2504 	if (f_entry->fltr_info.fltr_act == ICE_FWD_TO_VSI)
2505 		f_entry->fltr_info.fwd_id.hw_vsi_id =
2506 			ice_get_hw_vsi_num(hw, f_entry->fltr_info.vsi_handle);
2507 
2508 	rule_lock = &sw->recp_list[recp_id].filt_rule_lock;
2509 
2510 	ice_acquire_lock(rule_lock);
2511 	new_fltr = &f_entry->fltr_info;
2512 	if (new_fltr->flag & ICE_FLTR_RX)
2513 		new_fltr->src = hw->port_info->lport;
2514 	else if (new_fltr->flag & ICE_FLTR_TX)
2515 		new_fltr->src =
2516 			ice_get_hw_vsi_num(hw, f_entry->fltr_info.vsi_handle);
2517 
2518 	m_entry = ice_find_rule_entry(hw, recp_id, new_fltr);
2519 	if (!m_entry) {
2520 		status = ice_create_pkt_fwd_rule(hw, f_entry);
2521 		goto exit_add_rule_internal;
2522 	}
2523 
2524 	cur_fltr = &m_entry->fltr_info;
2525 	status = ice_add_update_vsi_list(hw, m_entry, cur_fltr, new_fltr);
2526 
2527 exit_add_rule_internal:
2528 	ice_release_lock(rule_lock);
2529 	return status;
2530 }
2531 
2532 /**
2533  * ice_remove_vsi_list_rule
2534  * @hw: pointer to the hardware structure
2535  * @vsi_list_id: VSI list ID generated as part of allocate resource
2536  * @lkup_type: switch rule filter lookup type
2537  *
2538  * The VSI list should be emptied before this function is called to remove the
2539  * VSI list.
2540  */
2541 static enum ice_status
2542 ice_remove_vsi_list_rule(struct ice_hw *hw, u16 vsi_list_id,
2543 			 enum ice_sw_lkup_type lkup_type)
2544 {
2545 	struct ice_aqc_sw_rules_elem *s_rule;
2546 	enum ice_status status;
2547 	u16 s_rule_size;
2548 
2549 	s_rule_size = (u16)ICE_SW_RULE_VSI_LIST_SIZE(0);
2550 	s_rule = (struct ice_aqc_sw_rules_elem *)ice_malloc(hw, s_rule_size);
2551 	if (!s_rule)
2552 		return ICE_ERR_NO_MEMORY;
2553 
2554 	s_rule->type = CPU_TO_LE16(ICE_AQC_SW_RULES_T_VSI_LIST_CLEAR);
2555 	s_rule->pdata.vsi_list.index = CPU_TO_LE16(vsi_list_id);
2556 
2557 	/* Free the vsi_list resource that we allocated. It is assumed that the
2558 	 * list is empty at this point.
2559 	 */
2560 	status = ice_aq_alloc_free_vsi_list(hw, &vsi_list_id, lkup_type,
2561 					    ice_aqc_opc_free_res);
2562 
2563 	ice_free(hw, s_rule);
2564 	return status;
2565 }
2566 
2567 /**
2568  * ice_rem_update_vsi_list
2569  * @hw: pointer to the hardware structure
2570  * @vsi_handle: VSI handle of the VSI to remove
2571  * @fm_list: filter management entry for which the VSI list management needs to
2572  *	     be done
2573  */
2574 static enum ice_status
2575 ice_rem_update_vsi_list(struct ice_hw *hw, u16 vsi_handle,
2576 			struct ice_fltr_mgmt_list_entry *fm_list)
2577 {
2578 	enum ice_sw_lkup_type lkup_type;
2579 	enum ice_status status = ICE_SUCCESS;
2580 	u16 vsi_list_id;
2581 
2582 	if (fm_list->fltr_info.fltr_act != ICE_FWD_TO_VSI_LIST ||
2583 	    fm_list->vsi_count == 0)
2584 		return ICE_ERR_PARAM;
2585 
2586 	/* A rule with the VSI being removed does not exist */
2587 	if (!ice_is_bit_set(fm_list->vsi_list_info->vsi_map, vsi_handle))
2588 		return ICE_ERR_DOES_NOT_EXIST;
2589 
2590 	lkup_type = fm_list->fltr_info.lkup_type;
2591 	vsi_list_id = fm_list->fltr_info.fwd_id.vsi_list_id;
2592 	status = ice_update_vsi_list_rule(hw, &vsi_handle, 1, vsi_list_id, true,
2593 					  ice_aqc_opc_update_sw_rules,
2594 					  lkup_type);
2595 	if (status)
2596 		return status;
2597 
2598 	fm_list->vsi_count--;
2599 	ice_clear_bit(vsi_handle, fm_list->vsi_list_info->vsi_map);
2600 
2601 	if (fm_list->vsi_count == 1 && lkup_type != ICE_SW_LKUP_VLAN) {
2602 		struct ice_fltr_info tmp_fltr_info = fm_list->fltr_info;
2603 		struct ice_vsi_list_map_info *vsi_list_info =
2604 			fm_list->vsi_list_info;
2605 		u16 rem_vsi_handle;
2606 
2607 		rem_vsi_handle = ice_find_first_bit(vsi_list_info->vsi_map,
2608 						    ICE_MAX_VSI);
2609 		if (!ice_is_vsi_valid(hw, rem_vsi_handle))
2610 			return ICE_ERR_OUT_OF_RANGE;
2611 
2612 		/* Make sure VSI list is empty before removing it below */
2613 		status = ice_update_vsi_list_rule(hw, &rem_vsi_handle, 1,
2614 						  vsi_list_id, true,
2615 						  ice_aqc_opc_update_sw_rules,
2616 						  lkup_type);
2617 		if (status)
2618 			return status;
2619 
2620 		tmp_fltr_info.fltr_act = ICE_FWD_TO_VSI;
2621 		tmp_fltr_info.fwd_id.hw_vsi_id =
2622 			ice_get_hw_vsi_num(hw, rem_vsi_handle);
2623 		tmp_fltr_info.vsi_handle = rem_vsi_handle;
2624 		status = ice_update_pkt_fwd_rule(hw, &tmp_fltr_info);
2625 		if (status) {
2626 			ice_debug(hw, ICE_DBG_SW,
2627 				  "Failed to update pkt fwd rule to FWD_TO_VSI on HW VSI %d, error %d\n",
2628 				  tmp_fltr_info.fwd_id.hw_vsi_id, status);
2629 			return status;
2630 		}
2631 
2632 		fm_list->fltr_info = tmp_fltr_info;
2633 	}
2634 
2635 	if ((fm_list->vsi_count == 1 && lkup_type != ICE_SW_LKUP_VLAN) ||
2636 	    (fm_list->vsi_count == 0 && lkup_type == ICE_SW_LKUP_VLAN)) {
2637 		struct ice_vsi_list_map_info *vsi_list_info =
2638 			fm_list->vsi_list_info;
2639 
2640 		/* Remove the VSI list since it is no longer used */
2641 		status = ice_remove_vsi_list_rule(hw, vsi_list_id, lkup_type);
2642 		if (status) {
2643 			ice_debug(hw, ICE_DBG_SW,
2644 				  "Failed to remove VSI list %d, error %d\n",
2645 				  vsi_list_id, status);
2646 			return status;
2647 		}
2648 
2649 		LIST_DEL(&vsi_list_info->list_entry);
2650 		ice_free(hw, vsi_list_info);
2651 		fm_list->vsi_list_info = NULL;
2652 	}
2653 
2654 	return status;
2655 }
2656 
2657 /**
2658  * ice_remove_rule_internal - Remove a filter rule of a given type
2659  *
2660  * @hw: pointer to the hardware structure
2661  * @recp_id: recipe ID for which the rule needs to removed
2662  * @f_entry: rule entry containing filter information
2663  */
2664 static enum ice_status
2665 ice_remove_rule_internal(struct ice_hw *hw, u8 recp_id,
2666 			 struct ice_fltr_list_entry *f_entry)
2667 {
2668 	struct ice_switch_info *sw = hw->switch_info;
2669 	struct ice_fltr_mgmt_list_entry *list_elem;
2670 	struct ice_lock *rule_lock; /* Lock to protect filter rule list */
2671 	enum ice_status status = ICE_SUCCESS;
2672 	bool remove_rule = false;
2673 	u16 vsi_handle;
2674 
2675 	if (!ice_is_vsi_valid(hw, f_entry->fltr_info.vsi_handle))
2676 		return ICE_ERR_PARAM;
2677 	f_entry->fltr_info.fwd_id.hw_vsi_id =
2678 		ice_get_hw_vsi_num(hw, f_entry->fltr_info.vsi_handle);
2679 
2680 	rule_lock = &sw->recp_list[recp_id].filt_rule_lock;
2681 	ice_acquire_lock(rule_lock);
2682 	list_elem = ice_find_rule_entry(hw, recp_id, &f_entry->fltr_info);
2683 	if (!list_elem) {
2684 		status = ICE_ERR_DOES_NOT_EXIST;
2685 		goto exit;
2686 	}
2687 
2688 	if (list_elem->fltr_info.fltr_act != ICE_FWD_TO_VSI_LIST) {
2689 		remove_rule = true;
2690 	} else if (!list_elem->vsi_list_info) {
2691 		status = ICE_ERR_DOES_NOT_EXIST;
2692 		goto exit;
2693 	} else if (list_elem->vsi_list_info->ref_cnt > 1) {
2694 		/* a ref_cnt > 1 indicates that the vsi_list is being
2695 		 * shared by multiple rules. Decrement the ref_cnt and
2696 		 * remove this rule, but do not modify the list, as it
2697 		 * is in-use by other rules.
2698 		 */
2699 		list_elem->vsi_list_info->ref_cnt--;
2700 		remove_rule = true;
2701 	} else {
2702 		/* a ref_cnt of 1 indicates the vsi_list is only used
2703 		 * by one rule. However, the original removal request is only
2704 		 * for a single VSI. Update the vsi_list first, and only
2705 		 * remove the rule if there are no further VSIs in this list.
2706 		 */
2707 		vsi_handle = f_entry->fltr_info.vsi_handle;
2708 		status = ice_rem_update_vsi_list(hw, vsi_handle, list_elem);
2709 		if (status)
2710 			goto exit;
2711 		/* if VSI count goes to zero after updating the VSI list */
2712 		if (list_elem->vsi_count == 0)
2713 			remove_rule = true;
2714 	}
2715 
2716 	if (remove_rule) {
2717 		/* Remove the lookup rule */
2718 		struct ice_aqc_sw_rules_elem *s_rule;
2719 
2720 		s_rule = (struct ice_aqc_sw_rules_elem *)
2721 			ice_malloc(hw, ICE_SW_RULE_RX_TX_NO_HDR_SIZE);
2722 		if (!s_rule) {
2723 			status = ICE_ERR_NO_MEMORY;
2724 			goto exit;
2725 		}
2726 
2727 		ice_fill_sw_rule(hw, &list_elem->fltr_info, s_rule,
2728 				 ice_aqc_opc_remove_sw_rules);
2729 
2730 		status = ice_aq_sw_rules(hw, s_rule,
2731 					 ICE_SW_RULE_RX_TX_NO_HDR_SIZE, 1,
2732 					 ice_aqc_opc_remove_sw_rules, NULL);
2733 		if (status)
2734 			goto exit;
2735 
2736 		/* Remove a book keeping from the list */
2737 		ice_free(hw, s_rule);
2738 
2739 		LIST_DEL(&list_elem->list_entry);
2740 		ice_free(hw, list_elem);
2741 	}
2742 exit:
2743 	ice_release_lock(rule_lock);
2744 	return status;
2745 }
2746 
2747 /**
2748  * ice_aq_get_res_alloc - get allocated resources
2749  * @hw: pointer to the HW struct
2750  * @num_entries: pointer to u16 to store the number of resource entries returned
2751  * @buf: pointer to user-supplied buffer
2752  * @buf_size: size of buff
2753  * @cd: pointer to command details structure or NULL
2754  *
2755  * The user-supplied buffer must be large enough to store the resource
2756  * information for all resource types. Each resource type is an
2757  * ice_aqc_get_res_resp_data_elem structure.
2758  */
2759 enum ice_status
2760 ice_aq_get_res_alloc(struct ice_hw *hw, u16 *num_entries, void *buf,
2761 		     u16 buf_size, struct ice_sq_cd *cd)
2762 {
2763 	struct ice_aqc_get_res_alloc *resp;
2764 	enum ice_status status;
2765 	struct ice_aq_desc desc;
2766 
2767 	if (!buf)
2768 		return ICE_ERR_BAD_PTR;
2769 
2770 	if (buf_size < ICE_AQ_GET_RES_ALLOC_BUF_LEN)
2771 		return ICE_ERR_INVAL_SIZE;
2772 
2773 	resp = &desc.params.get_res;
2774 
2775 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_get_res_alloc);
2776 	status = ice_aq_send_cmd(hw, &desc, buf, buf_size, cd);
2777 
2778 	if (!status && num_entries)
2779 		*num_entries = LE16_TO_CPU(resp->resp_elem_num);
2780 
2781 	return status;
2782 }
2783 
2784 /**
2785  * ice_aq_get_res_descs - get allocated resource descriptors
2786  * @hw: pointer to the hardware structure
2787  * @num_entries: number of resource entries in buffer
2788  * @buf: Indirect buffer to hold data parameters and response
2789  * @buf_size: size of buffer for indirect commands
2790  * @res_type: resource type
2791  * @res_shared: is resource shared
2792  * @desc_id: input - first desc ID to start; output - next desc ID
2793  * @cd: pointer to command details structure or NULL
2794  */
2795 enum ice_status
2796 ice_aq_get_res_descs(struct ice_hw *hw, u16 num_entries,
2797 		     struct ice_aqc_get_allocd_res_desc_resp *buf,
2798 		     u16 buf_size, u16 res_type, bool res_shared, u16 *desc_id,
2799 		     struct ice_sq_cd *cd)
2800 {
2801 	struct ice_aqc_get_allocd_res_desc *cmd;
2802 	struct ice_aq_desc desc;
2803 	enum ice_status status;
2804 
2805 	ice_debug(hw, ICE_DBG_TRACE, "ice_aq_get_res_descs");
2806 
2807 	cmd = &desc.params.get_res_desc;
2808 
2809 	if (!buf)
2810 		return ICE_ERR_PARAM;
2811 
2812 	if (buf_size != (num_entries * sizeof(*buf)))
2813 		return ICE_ERR_PARAM;
2814 
2815 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_get_allocd_res_desc);
2816 
2817 	cmd->ops.cmd.res = CPU_TO_LE16(((res_type << ICE_AQC_RES_TYPE_S) &
2818 					 ICE_AQC_RES_TYPE_M) | (res_shared ?
2819 					ICE_AQC_RES_TYPE_FLAG_SHARED : 0));
2820 	cmd->ops.cmd.first_desc = CPU_TO_LE16(*desc_id);
2821 
2822 	desc.flags |= CPU_TO_LE16(ICE_AQ_FLAG_RD);
2823 
2824 	status = ice_aq_send_cmd(hw, &desc, buf, buf_size, cd);
2825 	if (!status)
2826 		*desc_id = LE16_TO_CPU(cmd->ops.resp.next_desc);
2827 
2828 	return status;
2829 }
2830 
2831 /**
2832  * ice_add_mac - Add a MAC address based filter rule
2833  * @hw: pointer to the hardware structure
2834  * @m_list: list of MAC addresses and forwarding information
2835  *
2836  * IMPORTANT: When the ucast_shared flag is set to false and m_list has
2837  * multiple unicast addresses, the function assumes that all the
2838  * addresses are unique in a given add_mac call. It doesn't
2839  * check for duplicates in this case, removing duplicates from a given
2840  * list should be taken care of in the caller of this function.
2841  */
2842 enum ice_status
2843 ice_add_mac(struct ice_hw *hw, struct LIST_HEAD_TYPE *m_list)
2844 {
2845 	struct ice_aqc_sw_rules_elem *s_rule, *r_iter;
2846 	struct ice_fltr_list_entry *m_list_itr;
2847 	struct LIST_HEAD_TYPE *rule_head;
2848 	u16 elem_sent, total_elem_left;
2849 	struct ice_switch_info *sw;
2850 	struct ice_lock *rule_lock; /* Lock to protect filter rule list */
2851 	enum ice_status status = ICE_SUCCESS;
2852 	u16 num_unicast = 0;
2853 	u16 s_rule_size;
2854 
2855 	if (!m_list || !hw)
2856 		return ICE_ERR_PARAM;
2857 	s_rule = NULL;
2858 	sw = hw->switch_info;
2859 	rule_lock = &sw->recp_list[ICE_SW_LKUP_MAC].filt_rule_lock;
2860 	LIST_FOR_EACH_ENTRY(m_list_itr, m_list, ice_fltr_list_entry,
2861 			    list_entry) {
2862 		u8 *add = &m_list_itr->fltr_info.l_data.mac.mac_addr[0];
2863 		u16 vsi_handle;
2864 		u16 hw_vsi_id;
2865 
2866 		m_list_itr->fltr_info.flag = ICE_FLTR_TX;
2867 		vsi_handle = m_list_itr->fltr_info.vsi_handle;
2868 		if (!ice_is_vsi_valid(hw, vsi_handle))
2869 			return ICE_ERR_PARAM;
2870 		hw_vsi_id = ice_get_hw_vsi_num(hw, vsi_handle);
2871 		m_list_itr->fltr_info.fwd_id.hw_vsi_id = hw_vsi_id;
2872 		/* update the src in case it is VSI num */
2873 		if (m_list_itr->fltr_info.src_id != ICE_SRC_ID_VSI)
2874 			return ICE_ERR_PARAM;
2875 		m_list_itr->fltr_info.src = hw_vsi_id;
2876 		if (m_list_itr->fltr_info.lkup_type != ICE_SW_LKUP_MAC ||
2877 		    IS_ZERO_ETHER_ADDR(add))
2878 			return ICE_ERR_PARAM;
2879 		if (IS_UNICAST_ETHER_ADDR(add) && !hw->ucast_shared) {
2880 			/* Don't overwrite the unicast address */
2881 			ice_acquire_lock(rule_lock);
2882 			if (ice_find_rule_entry(hw, ICE_SW_LKUP_MAC,
2883 						&m_list_itr->fltr_info)) {
2884 				ice_release_lock(rule_lock);
2885 				return ICE_ERR_ALREADY_EXISTS;
2886 			}
2887 			ice_release_lock(rule_lock);
2888 			num_unicast++;
2889 		} else if (IS_MULTICAST_ETHER_ADDR(add) ||
2890 			   (IS_UNICAST_ETHER_ADDR(add) && hw->ucast_shared)) {
2891 			m_list_itr->status =
2892 				ice_add_rule_internal(hw, ICE_SW_LKUP_MAC,
2893 						      m_list_itr);
2894 			if (m_list_itr->status)
2895 				return m_list_itr->status;
2896 		}
2897 	}
2898 
2899 	ice_acquire_lock(rule_lock);
2900 	/* Exit if no suitable entries were found for adding bulk switch rule */
2901 	if (!num_unicast) {
2902 		status = ICE_SUCCESS;
2903 		goto ice_add_mac_exit;
2904 	}
2905 
2906 	rule_head = &sw->recp_list[ICE_SW_LKUP_MAC].filt_rules;
2907 
2908 	/* Allocate switch rule buffer for the bulk update for unicast */
2909 	s_rule_size = ICE_SW_RULE_RX_TX_ETH_HDR_SIZE;
2910 	s_rule = (struct ice_aqc_sw_rules_elem *)
2911 		ice_calloc(hw, num_unicast, s_rule_size);
2912 	if (!s_rule) {
2913 		status = ICE_ERR_NO_MEMORY;
2914 		goto ice_add_mac_exit;
2915 	}
2916 
2917 	r_iter = s_rule;
2918 	LIST_FOR_EACH_ENTRY(m_list_itr, m_list, ice_fltr_list_entry,
2919 			    list_entry) {
2920 		struct ice_fltr_info *f_info = &m_list_itr->fltr_info;
2921 		u8 *mac_addr = &f_info->l_data.mac.mac_addr[0];
2922 
2923 		if (IS_UNICAST_ETHER_ADDR(mac_addr)) {
2924 			ice_fill_sw_rule(hw, &m_list_itr->fltr_info, r_iter,
2925 					 ice_aqc_opc_add_sw_rules);
2926 			r_iter = (struct ice_aqc_sw_rules_elem *)
2927 				((u8 *)r_iter + s_rule_size);
2928 		}
2929 	}
2930 
2931 	/* Call AQ bulk switch rule update for all unicast addresses */
2932 	r_iter = s_rule;
2933 	/* Call AQ switch rule in AQ_MAX chunk */
2934 	for (total_elem_left = num_unicast; total_elem_left > 0;
2935 	     total_elem_left -= elem_sent) {
2936 		struct ice_aqc_sw_rules_elem *entry = r_iter;
2937 
2938 		elem_sent = min(total_elem_left,
2939 				(u16)(ICE_AQ_MAX_BUF_LEN / s_rule_size));
2940 		status = ice_aq_sw_rules(hw, entry, elem_sent * s_rule_size,
2941 					 elem_sent, ice_aqc_opc_add_sw_rules,
2942 					 NULL);
2943 		if (status)
2944 			goto ice_add_mac_exit;
2945 		r_iter = (struct ice_aqc_sw_rules_elem *)
2946 			((u8 *)r_iter + (elem_sent * s_rule_size));
2947 	}
2948 
2949 	/* Fill up rule ID based on the value returned from FW */
2950 	r_iter = s_rule;
2951 	LIST_FOR_EACH_ENTRY(m_list_itr, m_list, ice_fltr_list_entry,
2952 			    list_entry) {
2953 		struct ice_fltr_info *f_info = &m_list_itr->fltr_info;
2954 		u8 *mac_addr = &f_info->l_data.mac.mac_addr[0];
2955 		struct ice_fltr_mgmt_list_entry *fm_entry;
2956 
2957 		if (IS_UNICAST_ETHER_ADDR(mac_addr)) {
2958 			f_info->fltr_rule_id =
2959 				LE16_TO_CPU(r_iter->pdata.lkup_tx_rx.index);
2960 			f_info->fltr_act = ICE_FWD_TO_VSI;
2961 			/* Create an entry to track this MAC address */
2962 			fm_entry = (struct ice_fltr_mgmt_list_entry *)
2963 				ice_malloc(hw, sizeof(*fm_entry));
2964 			if (!fm_entry) {
2965 				status = ICE_ERR_NO_MEMORY;
2966 				goto ice_add_mac_exit;
2967 			}
2968 			fm_entry->fltr_info = *f_info;
2969 			fm_entry->vsi_count = 1;
2970 			/* The book keeping entries will get removed when
2971 			 * base driver calls remove filter AQ command
2972 			 */
2973 
2974 			LIST_ADD(&fm_entry->list_entry, rule_head);
2975 			r_iter = (struct ice_aqc_sw_rules_elem *)
2976 				((u8 *)r_iter + s_rule_size);
2977 		}
2978 	}
2979 
2980 ice_add_mac_exit:
2981 	ice_release_lock(rule_lock);
2982 	if (s_rule)
2983 		ice_free(hw, s_rule);
2984 	return status;
2985 }
2986 
2987 /**
2988  * ice_add_vlan_internal - Add one VLAN based filter rule
2989  * @hw: pointer to the hardware structure
2990  * @f_entry: filter entry containing one VLAN information
2991  */
2992 static enum ice_status
2993 ice_add_vlan_internal(struct ice_hw *hw, struct ice_fltr_list_entry *f_entry)
2994 {
2995 	struct ice_switch_info *sw = hw->switch_info;
2996 	struct ice_fltr_mgmt_list_entry *v_list_itr;
2997 	struct ice_fltr_info *new_fltr, *cur_fltr;
2998 	enum ice_sw_lkup_type lkup_type;
2999 	u16 vsi_list_id = 0, vsi_handle;
3000 	struct ice_lock *rule_lock; /* Lock to protect filter rule list */
3001 	enum ice_status status = ICE_SUCCESS;
3002 
3003 	if (!ice_is_vsi_valid(hw, f_entry->fltr_info.vsi_handle))
3004 		return ICE_ERR_PARAM;
3005 
3006 	f_entry->fltr_info.fwd_id.hw_vsi_id =
3007 		ice_get_hw_vsi_num(hw, f_entry->fltr_info.vsi_handle);
3008 	new_fltr = &f_entry->fltr_info;
3009 
3010 	/* VLAN ID should only be 12 bits */
3011 	if (new_fltr->l_data.vlan.vlan_id > ICE_MAX_VLAN_ID)
3012 		return ICE_ERR_PARAM;
3013 
3014 	if (new_fltr->src_id != ICE_SRC_ID_VSI)
3015 		return ICE_ERR_PARAM;
3016 
3017 	new_fltr->src = new_fltr->fwd_id.hw_vsi_id;
3018 	lkup_type = new_fltr->lkup_type;
3019 	vsi_handle = new_fltr->vsi_handle;
3020 	rule_lock = &sw->recp_list[ICE_SW_LKUP_VLAN].filt_rule_lock;
3021 	ice_acquire_lock(rule_lock);
3022 	v_list_itr = ice_find_rule_entry(hw, ICE_SW_LKUP_VLAN, new_fltr);
3023 	if (!v_list_itr) {
3024 		struct ice_vsi_list_map_info *map_info = NULL;
3025 
3026 		if (new_fltr->fltr_act == ICE_FWD_TO_VSI) {
3027 			/* All VLAN pruning rules use a VSI list. Check if
3028 			 * there is already a VSI list containing VSI that we
3029 			 * want to add. If found, use the same vsi_list_id for
3030 			 * this new VLAN rule or else create a new list.
3031 			 */
3032 			map_info = ice_find_vsi_list_entry(hw, ICE_SW_LKUP_VLAN,
3033 							   vsi_handle,
3034 							   &vsi_list_id);
3035 			if (!map_info) {
3036 				status = ice_create_vsi_list_rule(hw,
3037 								  &vsi_handle,
3038 								  1,
3039 								  &vsi_list_id,
3040 								  lkup_type);
3041 				if (status)
3042 					goto exit;
3043 			}
3044 			/* Convert the action to forwarding to a VSI list. */
3045 			new_fltr->fltr_act = ICE_FWD_TO_VSI_LIST;
3046 			new_fltr->fwd_id.vsi_list_id = vsi_list_id;
3047 		}
3048 
3049 		status = ice_create_pkt_fwd_rule(hw, f_entry);
3050 		if (!status) {
3051 			v_list_itr = ice_find_rule_entry(hw, ICE_SW_LKUP_VLAN,
3052 							 new_fltr);
3053 			if (!v_list_itr) {
3054 				status = ICE_ERR_DOES_NOT_EXIST;
3055 				goto exit;
3056 			}
3057 			/* reuse VSI list for new rule and increment ref_cnt */
3058 			if (map_info) {
3059 				v_list_itr->vsi_list_info = map_info;
3060 				map_info->ref_cnt++;
3061 			} else {
3062 				v_list_itr->vsi_list_info =
3063 					ice_create_vsi_list_map(hw, &vsi_handle,
3064 								1, vsi_list_id);
3065 			}
3066 		}
3067 	} else if (v_list_itr->vsi_list_info->ref_cnt == 1) {
3068 		/* Update existing VSI list to add new VSI ID only if it used
3069 		 * by one VLAN rule.
3070 		 */
3071 		cur_fltr = &v_list_itr->fltr_info;
3072 		status = ice_add_update_vsi_list(hw, v_list_itr, cur_fltr,
3073 						 new_fltr);
3074 	} else {
3075 		/* If VLAN rule exists and VSI list being used by this rule is
3076 		 * referenced by more than 1 VLAN rule. Then create a new VSI
3077 		 * list appending previous VSI with new VSI and update existing
3078 		 * VLAN rule to point to new VSI list ID
3079 		 */
3080 		struct ice_fltr_info tmp_fltr;
3081 		u16 vsi_handle_arr[2];
3082 		u16 cur_handle;
3083 
3084 		/* Current implementation only supports reusing VSI list with
3085 		 * one VSI count. We should never hit below condition
3086 		 */
3087 		if (v_list_itr->vsi_count > 1 &&
3088 		    v_list_itr->vsi_list_info->ref_cnt > 1) {
3089 			ice_debug(hw, ICE_DBG_SW,
3090 				  "Invalid configuration: Optimization to reuse VSI list with more than one VSI is not being done yet\n");
3091 			status = ICE_ERR_CFG;
3092 			goto exit;
3093 		}
3094 
3095 		cur_handle =
3096 			ice_find_first_bit(v_list_itr->vsi_list_info->vsi_map,
3097 					   ICE_MAX_VSI);
3098 
3099 		/* A rule already exists with the new VSI being added */
3100 		if (cur_handle == vsi_handle) {
3101 			status = ICE_ERR_ALREADY_EXISTS;
3102 			goto exit;
3103 		}
3104 
3105 		vsi_handle_arr[0] = cur_handle;
3106 		vsi_handle_arr[1] = vsi_handle;
3107 		status = ice_create_vsi_list_rule(hw, &vsi_handle_arr[0], 2,
3108 						  &vsi_list_id, lkup_type);
3109 		if (status)
3110 			goto exit;
3111 
3112 		tmp_fltr = v_list_itr->fltr_info;
3113 		tmp_fltr.fltr_rule_id = v_list_itr->fltr_info.fltr_rule_id;
3114 		tmp_fltr.fwd_id.vsi_list_id = vsi_list_id;
3115 		tmp_fltr.fltr_act = ICE_FWD_TO_VSI_LIST;
3116 		/* Update the previous switch rule to a new VSI list which
3117 		 * includes current VSI that is requested
3118 		 */
3119 		status = ice_update_pkt_fwd_rule(hw, &tmp_fltr);
3120 		if (status)
3121 			goto exit;
3122 
3123 		/* before overriding VSI list map info. decrement ref_cnt of
3124 		 * previous VSI list
3125 		 */
3126 		v_list_itr->vsi_list_info->ref_cnt--;
3127 
3128 		/* now update to newly created list */
3129 		v_list_itr->fltr_info.fwd_id.vsi_list_id = vsi_list_id;
3130 		v_list_itr->vsi_list_info =
3131 			ice_create_vsi_list_map(hw, &vsi_handle_arr[0], 2,
3132 						vsi_list_id);
3133 		v_list_itr->vsi_count++;
3134 	}
3135 
3136 exit:
3137 	ice_release_lock(rule_lock);
3138 	return status;
3139 }
3140 
3141 /**
3142  * ice_add_vlan - Add VLAN based filter rule
3143  * @hw: pointer to the hardware structure
3144  * @v_list: list of VLAN entries and forwarding information
3145  */
3146 enum ice_status
3147 ice_add_vlan(struct ice_hw *hw, struct LIST_HEAD_TYPE *v_list)
3148 {
3149 	struct ice_fltr_list_entry *v_list_itr;
3150 
3151 	if (!v_list || !hw)
3152 		return ICE_ERR_PARAM;
3153 
3154 	LIST_FOR_EACH_ENTRY(v_list_itr, v_list, ice_fltr_list_entry,
3155 			    list_entry) {
3156 		if (v_list_itr->fltr_info.lkup_type != ICE_SW_LKUP_VLAN)
3157 			return ICE_ERR_PARAM;
3158 		v_list_itr->fltr_info.flag = ICE_FLTR_TX;
3159 		v_list_itr->status = ice_add_vlan_internal(hw, v_list_itr);
3160 		if (v_list_itr->status)
3161 			return v_list_itr->status;
3162 	}
3163 	return ICE_SUCCESS;
3164 }
3165 
3166 /**
3167  * ice_add_mac_vlan - Add MAC and VLAN pair based filter rule
3168  * @hw: pointer to the hardware structure
3169  * @mv_list: list of MAC and VLAN filters
3170  *
3171  * If the VSI on which the MAC-VLAN pair has to be added has Rx and Tx VLAN
3172  * pruning bits enabled, then it is the responsibility of the caller to make
3173  * sure to add a VLAN only filter on the same VSI. Packets belonging to that
3174  * VLAN won't be received on that VSI otherwise.
3175  */
3176 enum ice_status
3177 ice_add_mac_vlan(struct ice_hw *hw, struct LIST_HEAD_TYPE *mv_list)
3178 {
3179 	struct ice_fltr_list_entry *mv_list_itr;
3180 
3181 	if (!mv_list || !hw)
3182 		return ICE_ERR_PARAM;
3183 
3184 	LIST_FOR_EACH_ENTRY(mv_list_itr, mv_list, ice_fltr_list_entry,
3185 			    list_entry) {
3186 		enum ice_sw_lkup_type l_type =
3187 			mv_list_itr->fltr_info.lkup_type;
3188 
3189 		if (l_type != ICE_SW_LKUP_MAC_VLAN)
3190 			return ICE_ERR_PARAM;
3191 		mv_list_itr->fltr_info.flag = ICE_FLTR_TX;
3192 		mv_list_itr->status =
3193 			ice_add_rule_internal(hw, ICE_SW_LKUP_MAC_VLAN,
3194 					      mv_list_itr);
3195 		if (mv_list_itr->status)
3196 			return mv_list_itr->status;
3197 	}
3198 	return ICE_SUCCESS;
3199 }
3200 
3201 /**
3202  * ice_add_eth_mac - Add ethertype and MAC based filter rule
3203  * @hw: pointer to the hardware structure
3204  * @em_list: list of ether type MAC filter, MAC is optional
3205  *
3206  * This function requires the caller to populate the entries in
3207  * the filter list with the necessary fields (including flags to
3208  * indicate Tx or Rx rules).
3209  */
3210 enum ice_status
3211 ice_add_eth_mac(struct ice_hw *hw, struct LIST_HEAD_TYPE *em_list)
3212 {
3213 	struct ice_fltr_list_entry *em_list_itr;
3214 
3215 	if (!em_list || !hw)
3216 		return ICE_ERR_PARAM;
3217 
3218 	LIST_FOR_EACH_ENTRY(em_list_itr, em_list, ice_fltr_list_entry,
3219 			    list_entry) {
3220 		enum ice_sw_lkup_type l_type =
3221 			em_list_itr->fltr_info.lkup_type;
3222 
3223 		if (l_type != ICE_SW_LKUP_ETHERTYPE_MAC &&
3224 		    l_type != ICE_SW_LKUP_ETHERTYPE)
3225 			return ICE_ERR_PARAM;
3226 
3227 		em_list_itr->status = ice_add_rule_internal(hw, l_type,
3228 							    em_list_itr);
3229 		if (em_list_itr->status)
3230 			return em_list_itr->status;
3231 	}
3232 	return ICE_SUCCESS;
3233 }
3234 
3235 /**
3236  * ice_remove_eth_mac - Remove an ethertype (or MAC) based filter rule
3237  * @hw: pointer to the hardware structure
3238  * @em_list: list of ethertype or ethertype MAC entries
3239  */
3240 enum ice_status
3241 ice_remove_eth_mac(struct ice_hw *hw, struct LIST_HEAD_TYPE *em_list)
3242 {
3243 	struct ice_fltr_list_entry *em_list_itr, *tmp;
3244 
3245 	if (!em_list || !hw)
3246 		return ICE_ERR_PARAM;
3247 
3248 	LIST_FOR_EACH_ENTRY_SAFE(em_list_itr, tmp, em_list, ice_fltr_list_entry,
3249 				 list_entry) {
3250 		enum ice_sw_lkup_type l_type =
3251 			em_list_itr->fltr_info.lkup_type;
3252 
3253 		if (l_type != ICE_SW_LKUP_ETHERTYPE_MAC &&
3254 		    l_type != ICE_SW_LKUP_ETHERTYPE)
3255 			return ICE_ERR_PARAM;
3256 
3257 		em_list_itr->status = ice_remove_rule_internal(hw, l_type,
3258 							       em_list_itr);
3259 		if (em_list_itr->status)
3260 			return em_list_itr->status;
3261 	}
3262 	return ICE_SUCCESS;
3263 }
3264 
3265 
3266 /**
3267  * ice_rem_sw_rule_info
3268  * @hw: pointer to the hardware structure
3269  * @rule_head: pointer to the switch list structure that we want to delete
3270  */
3271 static void
3272 ice_rem_sw_rule_info(struct ice_hw *hw, struct LIST_HEAD_TYPE *rule_head)
3273 {
3274 	if (!LIST_EMPTY(rule_head)) {
3275 		struct ice_fltr_mgmt_list_entry *entry;
3276 		struct ice_fltr_mgmt_list_entry *tmp;
3277 
3278 		LIST_FOR_EACH_ENTRY_SAFE(entry, tmp, rule_head,
3279 					 ice_fltr_mgmt_list_entry, list_entry) {
3280 			LIST_DEL(&entry->list_entry);
3281 			ice_free(hw, entry);
3282 		}
3283 	}
3284 }
3285 
3286 /**
3287  * ice_rem_adv_rule_info
3288  * @hw: pointer to the hardware structure
3289  * @rule_head: pointer to the switch list structure that we want to delete
3290  */
3291 static void
3292 ice_rem_adv_rule_info(struct ice_hw *hw, struct LIST_HEAD_TYPE *rule_head)
3293 {
3294 	struct ice_adv_fltr_mgmt_list_entry *tmp_entry;
3295 	struct ice_adv_fltr_mgmt_list_entry *lst_itr;
3296 
3297 	if (LIST_EMPTY(rule_head))
3298 		return;
3299 
3300 	LIST_FOR_EACH_ENTRY_SAFE(lst_itr, tmp_entry, rule_head,
3301 				 ice_adv_fltr_mgmt_list_entry, list_entry) {
3302 		LIST_DEL(&lst_itr->list_entry);
3303 		ice_free(hw, lst_itr->lkups);
3304 		ice_free(hw, lst_itr);
3305 	}
3306 }
3307 
3308 /**
3309  * ice_rem_all_sw_rules_info
3310  * @hw: pointer to the hardware structure
3311  */
3312 void ice_rem_all_sw_rules_info(struct ice_hw *hw)
3313 {
3314 	struct ice_switch_info *sw = hw->switch_info;
3315 	u8 i;
3316 
3317 	for (i = 0; i < ICE_MAX_NUM_RECIPES; i++) {
3318 		struct LIST_HEAD_TYPE *rule_head;
3319 
3320 		rule_head = &sw->recp_list[i].filt_rules;
3321 		if (!sw->recp_list[i].adv_rule)
3322 			ice_rem_sw_rule_info(hw, rule_head);
3323 		else
3324 			ice_rem_adv_rule_info(hw, rule_head);
3325 	}
3326 }
3327 
3328 /**
3329  * ice_cfg_dflt_vsi - change state of VSI to set/clear default
3330  * @pi: pointer to the port_info structure
3331  * @vsi_handle: VSI handle to set as default
3332  * @set: true to add the above mentioned switch rule, false to remove it
3333  * @direction: ICE_FLTR_RX or ICE_FLTR_TX
3334  *
3335  * add filter rule to set/unset given VSI as default VSI for the switch
3336  * (represented by swid)
3337  */
3338 enum ice_status
3339 ice_cfg_dflt_vsi(struct ice_port_info *pi, u16 vsi_handle, bool set,
3340 		 u8 direction)
3341 {
3342 	struct ice_aqc_sw_rules_elem *s_rule;
3343 	struct ice_fltr_info f_info;
3344 	struct ice_hw *hw = pi->hw;
3345 	enum ice_adminq_opc opcode;
3346 	enum ice_status status;
3347 	u16 s_rule_size;
3348 	u16 hw_vsi_id;
3349 
3350 	if (!ice_is_vsi_valid(hw, vsi_handle))
3351 		return ICE_ERR_PARAM;
3352 	hw_vsi_id = ice_get_hw_vsi_num(hw, vsi_handle);
3353 
3354 	s_rule_size = set ? ICE_SW_RULE_RX_TX_ETH_HDR_SIZE :
3355 			    ICE_SW_RULE_RX_TX_NO_HDR_SIZE;
3356 	s_rule = (struct ice_aqc_sw_rules_elem *)ice_malloc(hw, s_rule_size);
3357 	if (!s_rule)
3358 		return ICE_ERR_NO_MEMORY;
3359 
3360 	ice_memset(&f_info, 0, sizeof(f_info), ICE_NONDMA_MEM);
3361 
3362 	f_info.lkup_type = ICE_SW_LKUP_DFLT;
3363 	f_info.flag = direction;
3364 	f_info.fltr_act = ICE_FWD_TO_VSI;
3365 	f_info.fwd_id.hw_vsi_id = hw_vsi_id;
3366 
3367 	if (f_info.flag & ICE_FLTR_RX) {
3368 		f_info.src = pi->lport;
3369 		f_info.src_id = ICE_SRC_ID_LPORT;
3370 		if (!set)
3371 			f_info.fltr_rule_id =
3372 				pi->dflt_rx_vsi_rule_id;
3373 	} else if (f_info.flag & ICE_FLTR_TX) {
3374 		f_info.src_id = ICE_SRC_ID_VSI;
3375 		f_info.src = hw_vsi_id;
3376 		if (!set)
3377 			f_info.fltr_rule_id =
3378 				pi->dflt_tx_vsi_rule_id;
3379 	}
3380 
3381 	if (set)
3382 		opcode = ice_aqc_opc_add_sw_rules;
3383 	else
3384 		opcode = ice_aqc_opc_remove_sw_rules;
3385 
3386 	ice_fill_sw_rule(hw, &f_info, s_rule, opcode);
3387 
3388 	status = ice_aq_sw_rules(hw, s_rule, s_rule_size, 1, opcode, NULL);
3389 	if (status || !(f_info.flag & ICE_FLTR_TX_RX))
3390 		goto out;
3391 	if (set) {
3392 		u16 index = LE16_TO_CPU(s_rule->pdata.lkup_tx_rx.index);
3393 
3394 		if (f_info.flag & ICE_FLTR_TX) {
3395 			pi->dflt_tx_vsi_num = hw_vsi_id;
3396 			pi->dflt_tx_vsi_rule_id = index;
3397 		} else if (f_info.flag & ICE_FLTR_RX) {
3398 			pi->dflt_rx_vsi_num = hw_vsi_id;
3399 			pi->dflt_rx_vsi_rule_id = index;
3400 		}
3401 	} else {
3402 		if (f_info.flag & ICE_FLTR_TX) {
3403 			pi->dflt_tx_vsi_num = ICE_DFLT_VSI_INVAL;
3404 			pi->dflt_tx_vsi_rule_id = ICE_INVAL_ACT;
3405 		} else if (f_info.flag & ICE_FLTR_RX) {
3406 			pi->dflt_rx_vsi_num = ICE_DFLT_VSI_INVAL;
3407 			pi->dflt_rx_vsi_rule_id = ICE_INVAL_ACT;
3408 		}
3409 	}
3410 
3411 out:
3412 	ice_free(hw, s_rule);
3413 	return status;
3414 }
3415 
3416 /**
3417  * ice_find_ucast_rule_entry - Search for a unicast MAC filter rule entry
3418  * @hw: pointer to the hardware structure
3419  * @recp_id: lookup type for which the specified rule needs to be searched
3420  * @f_info: rule information
3421  *
3422  * Helper function to search for a unicast rule entry - this is to be used
3423  * to remove unicast MAC filter that is not shared with other VSIs on the
3424  * PF switch.
3425  *
3426  * Returns pointer to entry storing the rule if found
3427  */
3428 static struct ice_fltr_mgmt_list_entry *
3429 ice_find_ucast_rule_entry(struct ice_hw *hw, u8 recp_id,
3430 			  struct ice_fltr_info *f_info)
3431 {
3432 	struct ice_switch_info *sw = hw->switch_info;
3433 	struct ice_fltr_mgmt_list_entry *list_itr;
3434 	struct LIST_HEAD_TYPE *list_head;
3435 
3436 	list_head = &sw->recp_list[recp_id].filt_rules;
3437 	LIST_FOR_EACH_ENTRY(list_itr, list_head, ice_fltr_mgmt_list_entry,
3438 			    list_entry) {
3439 		if (!memcmp(&f_info->l_data, &list_itr->fltr_info.l_data,
3440 			    sizeof(f_info->l_data)) &&
3441 		    f_info->fwd_id.hw_vsi_id ==
3442 		    list_itr->fltr_info.fwd_id.hw_vsi_id &&
3443 		    f_info->flag == list_itr->fltr_info.flag)
3444 			return list_itr;
3445 	}
3446 	return NULL;
3447 }
3448 
3449 /**
3450  * ice_remove_mac - remove a MAC address based filter rule
3451  * @hw: pointer to the hardware structure
3452  * @m_list: list of MAC addresses and forwarding information
3453  *
3454  * This function removes either a MAC filter rule or a specific VSI from a
3455  * VSI list for a multicast MAC address.
3456  *
3457  * Returns ICE_ERR_DOES_NOT_EXIST if a given entry was not added by
3458  * ice_add_mac. Caller should be aware that this call will only work if all
3459  * the entries passed into m_list were added previously. It will not attempt to
3460  * do a partial remove of entries that were found.
3461  */
3462 enum ice_status
3463 ice_remove_mac(struct ice_hw *hw, struct LIST_HEAD_TYPE *m_list)
3464 {
3465 	struct ice_fltr_list_entry *list_itr, *tmp;
3466 	struct ice_lock *rule_lock; /* Lock to protect filter rule list */
3467 
3468 	if (!m_list)
3469 		return ICE_ERR_PARAM;
3470 
3471 	rule_lock = &hw->switch_info->recp_list[ICE_SW_LKUP_MAC].filt_rule_lock;
3472 	LIST_FOR_EACH_ENTRY_SAFE(list_itr, tmp, m_list, ice_fltr_list_entry,
3473 				 list_entry) {
3474 		enum ice_sw_lkup_type l_type = list_itr->fltr_info.lkup_type;
3475 		u8 *add = &list_itr->fltr_info.l_data.mac.mac_addr[0];
3476 		u16 vsi_handle;
3477 
3478 		if (l_type != ICE_SW_LKUP_MAC)
3479 			return ICE_ERR_PARAM;
3480 
3481 		vsi_handle = list_itr->fltr_info.vsi_handle;
3482 		if (!ice_is_vsi_valid(hw, vsi_handle))
3483 			return ICE_ERR_PARAM;
3484 
3485 		list_itr->fltr_info.fwd_id.hw_vsi_id =
3486 					ice_get_hw_vsi_num(hw, vsi_handle);
3487 		if (IS_UNICAST_ETHER_ADDR(add) && !hw->ucast_shared) {
3488 			/* Don't remove the unicast address that belongs to
3489 			 * another VSI on the switch, since it is not being
3490 			 * shared...
3491 			 */
3492 			ice_acquire_lock(rule_lock);
3493 			if (!ice_find_ucast_rule_entry(hw, ICE_SW_LKUP_MAC,
3494 						       &list_itr->fltr_info)) {
3495 				ice_release_lock(rule_lock);
3496 				return ICE_ERR_DOES_NOT_EXIST;
3497 			}
3498 			ice_release_lock(rule_lock);
3499 		}
3500 		list_itr->status = ice_remove_rule_internal(hw,
3501 							    ICE_SW_LKUP_MAC,
3502 							    list_itr);
3503 		if (list_itr->status)
3504 			return list_itr->status;
3505 	}
3506 	return ICE_SUCCESS;
3507 }
3508 
3509 /**
3510  * ice_remove_vlan - Remove VLAN based filter rule
3511  * @hw: pointer to the hardware structure
3512  * @v_list: list of VLAN entries and forwarding information
3513  */
3514 enum ice_status
3515 ice_remove_vlan(struct ice_hw *hw, struct LIST_HEAD_TYPE *v_list)
3516 {
3517 	struct ice_fltr_list_entry *v_list_itr, *tmp;
3518 
3519 	if (!v_list || !hw)
3520 		return ICE_ERR_PARAM;
3521 
3522 	LIST_FOR_EACH_ENTRY_SAFE(v_list_itr, tmp, v_list, ice_fltr_list_entry,
3523 				 list_entry) {
3524 		enum ice_sw_lkup_type l_type = v_list_itr->fltr_info.lkup_type;
3525 
3526 		if (l_type != ICE_SW_LKUP_VLAN)
3527 			return ICE_ERR_PARAM;
3528 		v_list_itr->status = ice_remove_rule_internal(hw,
3529 							      ICE_SW_LKUP_VLAN,
3530 							      v_list_itr);
3531 		if (v_list_itr->status)
3532 			return v_list_itr->status;
3533 	}
3534 	return ICE_SUCCESS;
3535 }
3536 
3537 /**
3538  * ice_remove_mac_vlan - Remove MAC VLAN based filter rule
3539  * @hw: pointer to the hardware structure
3540  * @v_list: list of MAC VLAN entries and forwarding information
3541  */
3542 enum ice_status
3543 ice_remove_mac_vlan(struct ice_hw *hw, struct LIST_HEAD_TYPE *v_list)
3544 {
3545 	struct ice_fltr_list_entry *v_list_itr, *tmp;
3546 
3547 	if (!v_list || !hw)
3548 		return ICE_ERR_PARAM;
3549 
3550 	LIST_FOR_EACH_ENTRY_SAFE(v_list_itr, tmp, v_list, ice_fltr_list_entry,
3551 				 list_entry) {
3552 		enum ice_sw_lkup_type l_type = v_list_itr->fltr_info.lkup_type;
3553 
3554 		if (l_type != ICE_SW_LKUP_MAC_VLAN)
3555 			return ICE_ERR_PARAM;
3556 		v_list_itr->status =
3557 			ice_remove_rule_internal(hw, ICE_SW_LKUP_MAC_VLAN,
3558 						 v_list_itr);
3559 		if (v_list_itr->status)
3560 			return v_list_itr->status;
3561 	}
3562 	return ICE_SUCCESS;
3563 }
3564 
3565 /**
3566  * ice_vsi_uses_fltr - Determine if given VSI uses specified filter
3567  * @fm_entry: filter entry to inspect
3568  * @vsi_handle: VSI handle to compare with filter info
3569  */
3570 static bool
3571 ice_vsi_uses_fltr(struct ice_fltr_mgmt_list_entry *fm_entry, u16 vsi_handle)
3572 {
3573 	return ((fm_entry->fltr_info.fltr_act == ICE_FWD_TO_VSI &&
3574 		 fm_entry->fltr_info.vsi_handle == vsi_handle) ||
3575 		(fm_entry->fltr_info.fltr_act == ICE_FWD_TO_VSI_LIST &&
3576 		 (ice_is_bit_set(fm_entry->vsi_list_info->vsi_map,
3577 				 vsi_handle))));
3578 }
3579 
3580 /**
3581  * ice_add_entry_to_vsi_fltr_list - Add copy of fltr_list_entry to remove list
3582  * @hw: pointer to the hardware structure
3583  * @vsi_handle: VSI handle to remove filters from
3584  * @vsi_list_head: pointer to the list to add entry to
3585  * @fi: pointer to fltr_info of filter entry to copy & add
3586  *
3587  * Helper function, used when creating a list of filters to remove from
3588  * a specific VSI. The entry added to vsi_list_head is a COPY of the
3589  * original filter entry, with the exception of fltr_info.fltr_act and
3590  * fltr_info.fwd_id fields. These are set such that later logic can
3591  * extract which VSI to remove the fltr from, and pass on that information.
3592  */
3593 static enum ice_status
3594 ice_add_entry_to_vsi_fltr_list(struct ice_hw *hw, u16 vsi_handle,
3595 			       struct LIST_HEAD_TYPE *vsi_list_head,
3596 			       struct ice_fltr_info *fi)
3597 {
3598 	struct ice_fltr_list_entry *tmp;
3599 
3600 	/* this memory is freed up in the caller function
3601 	 * once filters for this VSI are removed
3602 	 */
3603 	tmp = (struct ice_fltr_list_entry *)ice_malloc(hw, sizeof(*tmp));
3604 	if (!tmp)
3605 		return ICE_ERR_NO_MEMORY;
3606 
3607 	tmp->fltr_info = *fi;
3608 
3609 	/* Overwrite these fields to indicate which VSI to remove filter from,
3610 	 * so find and remove logic can extract the information from the
3611 	 * list entries. Note that original entries will still have proper
3612 	 * values.
3613 	 */
3614 	tmp->fltr_info.fltr_act = ICE_FWD_TO_VSI;
3615 	tmp->fltr_info.vsi_handle = vsi_handle;
3616 	tmp->fltr_info.fwd_id.hw_vsi_id = ice_get_hw_vsi_num(hw, vsi_handle);
3617 
3618 	LIST_ADD(&tmp->list_entry, vsi_list_head);
3619 
3620 	return ICE_SUCCESS;
3621 }
3622 
3623 /**
3624  * ice_add_to_vsi_fltr_list - Add VSI filters to the list
3625  * @hw: pointer to the hardware structure
3626  * @vsi_handle: VSI handle to remove filters from
3627  * @lkup_list_head: pointer to the list that has certain lookup type filters
3628  * @vsi_list_head: pointer to the list pertaining to VSI with vsi_handle
3629  *
3630  * Locates all filters in lkup_list_head that are used by the given VSI,
3631  * and adds COPIES of those entries to vsi_list_head (intended to be used
3632  * to remove the listed filters).
3633  * Note that this means all entries in vsi_list_head must be explicitly
3634  * deallocated by the caller when done with list.
3635  */
3636 static enum ice_status
3637 ice_add_to_vsi_fltr_list(struct ice_hw *hw, u16 vsi_handle,
3638 			 struct LIST_HEAD_TYPE *lkup_list_head,
3639 			 struct LIST_HEAD_TYPE *vsi_list_head)
3640 {
3641 	struct ice_fltr_mgmt_list_entry *fm_entry;
3642 	enum ice_status status = ICE_SUCCESS;
3643 
3644 	/* check to make sure VSI ID is valid and within boundary */
3645 	if (!ice_is_vsi_valid(hw, vsi_handle))
3646 		return ICE_ERR_PARAM;
3647 
3648 	LIST_FOR_EACH_ENTRY(fm_entry, lkup_list_head,
3649 			    ice_fltr_mgmt_list_entry, list_entry) {
3650 		struct ice_fltr_info *fi;
3651 
3652 		fi = &fm_entry->fltr_info;
3653 		if (!fi || !ice_vsi_uses_fltr(fm_entry, vsi_handle))
3654 			continue;
3655 
3656 		status = ice_add_entry_to_vsi_fltr_list(hw, vsi_handle,
3657 							vsi_list_head, fi);
3658 		if (status)
3659 			return status;
3660 	}
3661 	return status;
3662 }
3663 
3664 
3665 /**
3666  * ice_determine_promisc_mask
3667  * @fi: filter info to parse
3668  *
3669  * Helper function to determine which ICE_PROMISC_ mask corresponds
3670  * to given filter into.
3671  */
3672 static u8 ice_determine_promisc_mask(struct ice_fltr_info *fi)
3673 {
3674 	u16 vid = fi->l_data.mac_vlan.vlan_id;
3675 	u8 *macaddr = fi->l_data.mac.mac_addr;
3676 	bool is_tx_fltr = false;
3677 	u8 promisc_mask = 0;
3678 
3679 	if (fi->flag == ICE_FLTR_TX)
3680 		is_tx_fltr = true;
3681 
3682 	if (IS_BROADCAST_ETHER_ADDR(macaddr))
3683 		promisc_mask |= is_tx_fltr ?
3684 			ICE_PROMISC_BCAST_TX : ICE_PROMISC_BCAST_RX;
3685 	else if (IS_MULTICAST_ETHER_ADDR(macaddr))
3686 		promisc_mask |= is_tx_fltr ?
3687 			ICE_PROMISC_MCAST_TX : ICE_PROMISC_MCAST_RX;
3688 	else if (IS_UNICAST_ETHER_ADDR(macaddr))
3689 		promisc_mask |= is_tx_fltr ?
3690 			ICE_PROMISC_UCAST_TX : ICE_PROMISC_UCAST_RX;
3691 	if (vid)
3692 		promisc_mask |= is_tx_fltr ?
3693 			ICE_PROMISC_VLAN_TX : ICE_PROMISC_VLAN_RX;
3694 
3695 	return promisc_mask;
3696 }
3697 
3698 /**
3699  * ice_get_vsi_promisc - get promiscuous mode of given VSI
3700  * @hw: pointer to the hardware structure
3701  * @vsi_handle: VSI handle to retrieve info from
3702  * @promisc_mask: pointer to mask to be filled in
3703  * @vid: VLAN ID of promisc VLAN VSI
3704  */
3705 enum ice_status
3706 ice_get_vsi_promisc(struct ice_hw *hw, u16 vsi_handle, u8 *promisc_mask,
3707 		    u16 *vid)
3708 {
3709 	struct ice_switch_info *sw = hw->switch_info;
3710 	struct ice_fltr_mgmt_list_entry *itr;
3711 	struct LIST_HEAD_TYPE *rule_head;
3712 	struct ice_lock *rule_lock;	/* Lock to protect filter rule list */
3713 
3714 	if (!ice_is_vsi_valid(hw, vsi_handle))
3715 		return ICE_ERR_PARAM;
3716 
3717 	*vid = 0;
3718 	*promisc_mask = 0;
3719 	rule_head = &sw->recp_list[ICE_SW_LKUP_PROMISC].filt_rules;
3720 	rule_lock = &sw->recp_list[ICE_SW_LKUP_PROMISC].filt_rule_lock;
3721 
3722 	ice_acquire_lock(rule_lock);
3723 	LIST_FOR_EACH_ENTRY(itr, rule_head,
3724 			    ice_fltr_mgmt_list_entry, list_entry) {
3725 		/* Continue if this filter doesn't apply to this VSI or the
3726 		 * VSI ID is not in the VSI map for this filter
3727 		 */
3728 		if (!ice_vsi_uses_fltr(itr, vsi_handle))
3729 			continue;
3730 
3731 		*promisc_mask |= ice_determine_promisc_mask(&itr->fltr_info);
3732 	}
3733 	ice_release_lock(rule_lock);
3734 
3735 	return ICE_SUCCESS;
3736 }
3737 
3738 /**
3739  * ice_get_vsi_vlan_promisc - get VLAN promiscuous mode of given VSI
3740  * @hw: pointer to the hardware structure
3741  * @vsi_handle: VSI handle to retrieve info from
3742  * @promisc_mask: pointer to mask to be filled in
3743  * @vid: VLAN ID of promisc VLAN VSI
3744  */
3745 enum ice_status
3746 ice_get_vsi_vlan_promisc(struct ice_hw *hw, u16 vsi_handle, u8 *promisc_mask,
3747 			 u16 *vid)
3748 {
3749 	struct ice_switch_info *sw = hw->switch_info;
3750 	struct ice_fltr_mgmt_list_entry *itr;
3751 	struct LIST_HEAD_TYPE *rule_head;
3752 	struct ice_lock *rule_lock;	/* Lock to protect filter rule list */
3753 
3754 	if (!ice_is_vsi_valid(hw, vsi_handle))
3755 		return ICE_ERR_PARAM;
3756 
3757 	*vid = 0;
3758 	*promisc_mask = 0;
3759 	rule_head = &sw->recp_list[ICE_SW_LKUP_PROMISC_VLAN].filt_rules;
3760 	rule_lock = &sw->recp_list[ICE_SW_LKUP_PROMISC_VLAN].filt_rule_lock;
3761 
3762 	ice_acquire_lock(rule_lock);
3763 	LIST_FOR_EACH_ENTRY(itr, rule_head, ice_fltr_mgmt_list_entry,
3764 			    list_entry) {
3765 		/* Continue if this filter doesn't apply to this VSI or the
3766 		 * VSI ID is not in the VSI map for this filter
3767 		 */
3768 		if (!ice_vsi_uses_fltr(itr, vsi_handle))
3769 			continue;
3770 
3771 		*promisc_mask |= ice_determine_promisc_mask(&itr->fltr_info);
3772 	}
3773 	ice_release_lock(rule_lock);
3774 
3775 	return ICE_SUCCESS;
3776 }
3777 
3778 /**
3779  * ice_remove_promisc - Remove promisc based filter rules
3780  * @hw: pointer to the hardware structure
3781  * @recp_id: recipe ID for which the rule needs to removed
3782  * @v_list: list of promisc entries
3783  */
3784 static enum ice_status
3785 ice_remove_promisc(struct ice_hw *hw, u8 recp_id,
3786 		   struct LIST_HEAD_TYPE *v_list)
3787 {
3788 	struct ice_fltr_list_entry *v_list_itr, *tmp;
3789 
3790 	LIST_FOR_EACH_ENTRY_SAFE(v_list_itr, tmp, v_list, ice_fltr_list_entry,
3791 				 list_entry) {
3792 		v_list_itr->status =
3793 			ice_remove_rule_internal(hw, recp_id, v_list_itr);
3794 		if (v_list_itr->status)
3795 			return v_list_itr->status;
3796 	}
3797 	return ICE_SUCCESS;
3798 }
3799 
3800 /**
3801  * ice_clear_vsi_promisc - clear specified promiscuous mode(s) for given VSI
3802  * @hw: pointer to the hardware structure
3803  * @vsi_handle: VSI handle to clear mode
3804  * @promisc_mask: mask of promiscuous config bits to clear
3805  * @vid: VLAN ID to clear VLAN promiscuous
3806  */
3807 enum ice_status
3808 ice_clear_vsi_promisc(struct ice_hw *hw, u16 vsi_handle, u8 promisc_mask,
3809 		      u16 vid)
3810 {
3811 	struct ice_switch_info *sw = hw->switch_info;
3812 	struct ice_fltr_list_entry *fm_entry, *tmp;
3813 	struct LIST_HEAD_TYPE remove_list_head;
3814 	struct ice_fltr_mgmt_list_entry *itr;
3815 	struct LIST_HEAD_TYPE *rule_head;
3816 	struct ice_lock *rule_lock;	/* Lock to protect filter rule list */
3817 	enum ice_status status = ICE_SUCCESS;
3818 	u8 recipe_id;
3819 
3820 	if (!ice_is_vsi_valid(hw, vsi_handle))
3821 		return ICE_ERR_PARAM;
3822 
3823 	if (vid)
3824 		recipe_id = ICE_SW_LKUP_PROMISC_VLAN;
3825 	else
3826 		recipe_id = ICE_SW_LKUP_PROMISC;
3827 
3828 	rule_head = &sw->recp_list[recipe_id].filt_rules;
3829 	rule_lock = &sw->recp_list[recipe_id].filt_rule_lock;
3830 
3831 	INIT_LIST_HEAD(&remove_list_head);
3832 
3833 	ice_acquire_lock(rule_lock);
3834 	LIST_FOR_EACH_ENTRY(itr, rule_head,
3835 			    ice_fltr_mgmt_list_entry, list_entry) {
3836 		u8 fltr_promisc_mask = 0;
3837 
3838 		if (!ice_vsi_uses_fltr(itr, vsi_handle))
3839 			continue;
3840 
3841 		fltr_promisc_mask |=
3842 			ice_determine_promisc_mask(&itr->fltr_info);
3843 
3844 		/* Skip if filter is not completely specified by given mask */
3845 		if (fltr_promisc_mask & ~promisc_mask)
3846 			continue;
3847 
3848 		status = ice_add_entry_to_vsi_fltr_list(hw, vsi_handle,
3849 							&remove_list_head,
3850 							&itr->fltr_info);
3851 		if (status) {
3852 			ice_release_lock(rule_lock);
3853 			goto free_fltr_list;
3854 		}
3855 	}
3856 	ice_release_lock(rule_lock);
3857 
3858 	status = ice_remove_promisc(hw, recipe_id, &remove_list_head);
3859 
3860 free_fltr_list:
3861 	LIST_FOR_EACH_ENTRY_SAFE(fm_entry, tmp, &remove_list_head,
3862 				 ice_fltr_list_entry, list_entry) {
3863 		LIST_DEL(&fm_entry->list_entry);
3864 		ice_free(hw, fm_entry);
3865 	}
3866 
3867 	return status;
3868 }
3869 
3870 /**
3871  * ice_set_vsi_promisc - set given VSI to given promiscuous mode(s)
3872  * @hw: pointer to the hardware structure
3873  * @vsi_handle: VSI handle to configure
3874  * @promisc_mask: mask of promiscuous config bits
3875  * @vid: VLAN ID to set VLAN promiscuous
3876  */
3877 enum ice_status
3878 ice_set_vsi_promisc(struct ice_hw *hw, u16 vsi_handle, u8 promisc_mask, u16 vid)
3879 {
3880 	enum { UCAST_FLTR = 1, MCAST_FLTR, BCAST_FLTR };
3881 	struct ice_fltr_list_entry f_list_entry;
3882 	struct ice_fltr_info new_fltr;
3883 	enum ice_status status = ICE_SUCCESS;
3884 	bool is_tx_fltr;
3885 	u16 hw_vsi_id;
3886 	int pkt_type;
3887 	u8 recipe_id;
3888 
3889 	ice_debug(hw, ICE_DBG_TRACE, "ice_set_vsi_promisc\n");
3890 
3891 	if (!ice_is_vsi_valid(hw, vsi_handle))
3892 		return ICE_ERR_PARAM;
3893 	hw_vsi_id = ice_get_hw_vsi_num(hw, vsi_handle);
3894 
3895 	ice_memset(&new_fltr, 0, sizeof(new_fltr), ICE_NONDMA_MEM);
3896 
3897 	if (promisc_mask & (ICE_PROMISC_VLAN_RX | ICE_PROMISC_VLAN_TX)) {
3898 		new_fltr.lkup_type = ICE_SW_LKUP_PROMISC_VLAN;
3899 		new_fltr.l_data.mac_vlan.vlan_id = vid;
3900 		recipe_id = ICE_SW_LKUP_PROMISC_VLAN;
3901 	} else {
3902 		new_fltr.lkup_type = ICE_SW_LKUP_PROMISC;
3903 		recipe_id = ICE_SW_LKUP_PROMISC;
3904 	}
3905 
3906 	/* Separate filters must be set for each direction/packet type
3907 	 * combination, so we will loop over the mask value, store the
3908 	 * individual type, and clear it out in the input mask as it
3909 	 * is found.
3910 	 */
3911 	while (promisc_mask) {
3912 		u8 *mac_addr;
3913 
3914 		pkt_type = 0;
3915 		is_tx_fltr = false;
3916 
3917 		if (promisc_mask & ICE_PROMISC_UCAST_RX) {
3918 			promisc_mask &= ~ICE_PROMISC_UCAST_RX;
3919 			pkt_type = UCAST_FLTR;
3920 		} else if (promisc_mask & ICE_PROMISC_UCAST_TX) {
3921 			promisc_mask &= ~ICE_PROMISC_UCAST_TX;
3922 			pkt_type = UCAST_FLTR;
3923 			is_tx_fltr = true;
3924 		} else if (promisc_mask & ICE_PROMISC_MCAST_RX) {
3925 			promisc_mask &= ~ICE_PROMISC_MCAST_RX;
3926 			pkt_type = MCAST_FLTR;
3927 		} else if (promisc_mask & ICE_PROMISC_MCAST_TX) {
3928 			promisc_mask &= ~ICE_PROMISC_MCAST_TX;
3929 			pkt_type = MCAST_FLTR;
3930 			is_tx_fltr = true;
3931 		} else if (promisc_mask & ICE_PROMISC_BCAST_RX) {
3932 			promisc_mask &= ~ICE_PROMISC_BCAST_RX;
3933 			pkt_type = BCAST_FLTR;
3934 		} else if (promisc_mask & ICE_PROMISC_BCAST_TX) {
3935 			promisc_mask &= ~ICE_PROMISC_BCAST_TX;
3936 			pkt_type = BCAST_FLTR;
3937 			is_tx_fltr = true;
3938 		}
3939 
3940 		/* Check for VLAN promiscuous flag */
3941 		if (promisc_mask & ICE_PROMISC_VLAN_RX) {
3942 			promisc_mask &= ~ICE_PROMISC_VLAN_RX;
3943 		} else if (promisc_mask & ICE_PROMISC_VLAN_TX) {
3944 			promisc_mask &= ~ICE_PROMISC_VLAN_TX;
3945 			is_tx_fltr = true;
3946 		}
3947 
3948 		/* Set filter DA based on packet type */
3949 		mac_addr = new_fltr.l_data.mac.mac_addr;
3950 		if (pkt_type == BCAST_FLTR) {
3951 			ice_memset(mac_addr, 0xff, ETH_ALEN, ICE_NONDMA_MEM);
3952 		} else if (pkt_type == MCAST_FLTR ||
3953 			   pkt_type == UCAST_FLTR) {
3954 			/* Use the dummy ether header DA */
3955 			ice_memcpy(mac_addr, dummy_eth_header, ETH_ALEN,
3956 				   ICE_NONDMA_TO_NONDMA);
3957 			if (pkt_type == MCAST_FLTR)
3958 				mac_addr[0] |= 0x1;	/* Set multicast bit */
3959 		}
3960 
3961 		/* Need to reset this to zero for all iterations */
3962 		new_fltr.flag = 0;
3963 		if (is_tx_fltr) {
3964 			new_fltr.flag |= ICE_FLTR_TX;
3965 			new_fltr.src = hw_vsi_id;
3966 		} else {
3967 			new_fltr.flag |= ICE_FLTR_RX;
3968 			new_fltr.src = hw->port_info->lport;
3969 		}
3970 
3971 		new_fltr.fltr_act = ICE_FWD_TO_VSI;
3972 		new_fltr.vsi_handle = vsi_handle;
3973 		new_fltr.fwd_id.hw_vsi_id = hw_vsi_id;
3974 		f_list_entry.fltr_info = new_fltr;
3975 
3976 		status = ice_add_rule_internal(hw, recipe_id, &f_list_entry);
3977 		if (status != ICE_SUCCESS)
3978 			goto set_promisc_exit;
3979 	}
3980 
3981 set_promisc_exit:
3982 	return status;
3983 }
3984 
3985 /**
3986  * ice_set_vlan_vsi_promisc
3987  * @hw: pointer to the hardware structure
3988  * @vsi_handle: VSI handle to configure
3989  * @promisc_mask: mask of promiscuous config bits
3990  * @rm_vlan_promisc: Clear VLANs VSI promisc mode
3991  *
3992  * Configure VSI with all associated VLANs to given promiscuous mode(s)
3993  */
3994 enum ice_status
3995 ice_set_vlan_vsi_promisc(struct ice_hw *hw, u16 vsi_handle, u8 promisc_mask,
3996 			 bool rm_vlan_promisc)
3997 {
3998 	struct ice_switch_info *sw = hw->switch_info;
3999 	struct ice_fltr_list_entry *list_itr, *tmp;
4000 	struct LIST_HEAD_TYPE vsi_list_head;
4001 	struct LIST_HEAD_TYPE *vlan_head;
4002 	struct ice_lock *vlan_lock; /* Lock to protect filter rule list */
4003 	enum ice_status status;
4004 	u16 vlan_id;
4005 
4006 	INIT_LIST_HEAD(&vsi_list_head);
4007 	vlan_lock = &sw->recp_list[ICE_SW_LKUP_VLAN].filt_rule_lock;
4008 	vlan_head = &sw->recp_list[ICE_SW_LKUP_VLAN].filt_rules;
4009 	ice_acquire_lock(vlan_lock);
4010 	status = ice_add_to_vsi_fltr_list(hw, vsi_handle, vlan_head,
4011 					  &vsi_list_head);
4012 	ice_release_lock(vlan_lock);
4013 	if (status)
4014 		goto free_fltr_list;
4015 
4016 	LIST_FOR_EACH_ENTRY(list_itr, &vsi_list_head, ice_fltr_list_entry,
4017 			    list_entry) {
4018 		vlan_id = list_itr->fltr_info.l_data.vlan.vlan_id;
4019 		if (rm_vlan_promisc)
4020 			status = ice_clear_vsi_promisc(hw, vsi_handle,
4021 						       promisc_mask, vlan_id);
4022 		else
4023 			status = ice_set_vsi_promisc(hw, vsi_handle,
4024 						     promisc_mask, vlan_id);
4025 		if (status)
4026 			break;
4027 	}
4028 
4029 free_fltr_list:
4030 	LIST_FOR_EACH_ENTRY_SAFE(list_itr, tmp, &vsi_list_head,
4031 				 ice_fltr_list_entry, list_entry) {
4032 		LIST_DEL(&list_itr->list_entry);
4033 		ice_free(hw, list_itr);
4034 	}
4035 	return status;
4036 }
4037 
4038 /**
4039  * ice_remove_vsi_lkup_fltr - Remove lookup type filters for a VSI
4040  * @hw: pointer to the hardware structure
4041  * @vsi_handle: VSI handle to remove filters from
4042  * @lkup: switch rule filter lookup type
4043  */
4044 static void
4045 ice_remove_vsi_lkup_fltr(struct ice_hw *hw, u16 vsi_handle,
4046 			 enum ice_sw_lkup_type lkup)
4047 {
4048 	struct ice_switch_info *sw = hw->switch_info;
4049 	struct ice_fltr_list_entry *fm_entry;
4050 	struct LIST_HEAD_TYPE remove_list_head;
4051 	struct LIST_HEAD_TYPE *rule_head;
4052 	struct ice_fltr_list_entry *tmp;
4053 	struct ice_lock *rule_lock;	/* Lock to protect filter rule list */
4054 	enum ice_status status;
4055 
4056 	INIT_LIST_HEAD(&remove_list_head);
4057 	rule_lock = &sw->recp_list[lkup].filt_rule_lock;
4058 	rule_head = &sw->recp_list[lkup].filt_rules;
4059 	ice_acquire_lock(rule_lock);
4060 	status = ice_add_to_vsi_fltr_list(hw, vsi_handle, rule_head,
4061 					  &remove_list_head);
4062 	ice_release_lock(rule_lock);
4063 	if (status)
4064 		return;
4065 
4066 	switch (lkup) {
4067 	case ICE_SW_LKUP_MAC:
4068 		ice_remove_mac(hw, &remove_list_head);
4069 		break;
4070 	case ICE_SW_LKUP_VLAN:
4071 		ice_remove_vlan(hw, &remove_list_head);
4072 		break;
4073 	case ICE_SW_LKUP_PROMISC:
4074 	case ICE_SW_LKUP_PROMISC_VLAN:
4075 		ice_remove_promisc(hw, lkup, &remove_list_head);
4076 		break;
4077 	case ICE_SW_LKUP_MAC_VLAN:
4078 		ice_remove_mac_vlan(hw, &remove_list_head);
4079 		break;
4080 	case ICE_SW_LKUP_ETHERTYPE:
4081 	case ICE_SW_LKUP_ETHERTYPE_MAC:
4082 		ice_remove_eth_mac(hw, &remove_list_head);
4083 		break;
4084 	case ICE_SW_LKUP_DFLT:
4085 		ice_debug(hw, ICE_DBG_SW,
4086 			  "Remove filters for this lookup type hasn't been implemented yet\n");
4087 		break;
4088 	case ICE_SW_LKUP_LAST:
4089 		ice_debug(hw, ICE_DBG_SW, "Unsupported lookup type\n");
4090 		break;
4091 	}
4092 
4093 	LIST_FOR_EACH_ENTRY_SAFE(fm_entry, tmp, &remove_list_head,
4094 				 ice_fltr_list_entry, list_entry) {
4095 		LIST_DEL(&fm_entry->list_entry);
4096 		ice_free(hw, fm_entry);
4097 	}
4098 }
4099 
4100 /**
4101  * ice_remove_vsi_fltr - Remove all filters for a VSI
4102  * @hw: pointer to the hardware structure
4103  * @vsi_handle: VSI handle to remove filters from
4104  */
4105 void ice_remove_vsi_fltr(struct ice_hw *hw, u16 vsi_handle)
4106 {
4107 	ice_debug(hw, ICE_DBG_TRACE, "ice_remove_vsi_fltr\n");
4108 
4109 	ice_remove_vsi_lkup_fltr(hw, vsi_handle, ICE_SW_LKUP_MAC);
4110 	ice_remove_vsi_lkup_fltr(hw, vsi_handle, ICE_SW_LKUP_MAC_VLAN);
4111 	ice_remove_vsi_lkup_fltr(hw, vsi_handle, ICE_SW_LKUP_PROMISC);
4112 	ice_remove_vsi_lkup_fltr(hw, vsi_handle, ICE_SW_LKUP_VLAN);
4113 	ice_remove_vsi_lkup_fltr(hw, vsi_handle, ICE_SW_LKUP_DFLT);
4114 	ice_remove_vsi_lkup_fltr(hw, vsi_handle, ICE_SW_LKUP_ETHERTYPE);
4115 	ice_remove_vsi_lkup_fltr(hw, vsi_handle, ICE_SW_LKUP_ETHERTYPE_MAC);
4116 	ice_remove_vsi_lkup_fltr(hw, vsi_handle, ICE_SW_LKUP_PROMISC_VLAN);
4117 }
4118 
4119 /**
4120  * ice_alloc_res_cntr - allocating resource counter
4121  * @hw: pointer to the hardware structure
4122  * @type: type of resource
4123  * @alloc_shared: if set it is shared else dedicated
4124  * @num_items: number of entries requested for FD resource type
4125  * @counter_id: counter index returned by AQ call
4126  */
4127 enum ice_status
4128 ice_alloc_res_cntr(struct ice_hw *hw, u8 type, u8 alloc_shared, u16 num_items,
4129 		   u16 *counter_id)
4130 {
4131 	struct ice_aqc_alloc_free_res_elem *buf;
4132 	enum ice_status status;
4133 	u16 buf_len;
4134 
4135 	/* Allocate resource */
4136 	buf_len = sizeof(*buf);
4137 	buf = (struct ice_aqc_alloc_free_res_elem *)
4138 		ice_malloc(hw, buf_len);
4139 	if (!buf)
4140 		return ICE_ERR_NO_MEMORY;
4141 
4142 	buf->num_elems = CPU_TO_LE16(num_items);
4143 	buf->res_type = CPU_TO_LE16(((type << ICE_AQC_RES_TYPE_S) &
4144 				      ICE_AQC_RES_TYPE_M) | alloc_shared);
4145 
4146 	status = ice_aq_alloc_free_res(hw, 1, buf, buf_len,
4147 				       ice_aqc_opc_alloc_res, NULL);
4148 	if (status)
4149 		goto exit;
4150 
4151 	*counter_id = LE16_TO_CPU(buf->elem[0].e.sw_resp);
4152 
4153 exit:
4154 	ice_free(hw, buf);
4155 	return status;
4156 }
4157 
4158 /**
4159  * ice_free_res_cntr - free resource counter
4160  * @hw: pointer to the hardware structure
4161  * @type: type of resource
4162  * @alloc_shared: if set it is shared else dedicated
4163  * @num_items: number of entries to be freed for FD resource type
4164  * @counter_id: counter ID resource which needs to be freed
4165  */
4166 enum ice_status
4167 ice_free_res_cntr(struct ice_hw *hw, u8 type, u8 alloc_shared, u16 num_items,
4168 		  u16 counter_id)
4169 {
4170 	struct ice_aqc_alloc_free_res_elem *buf;
4171 	enum ice_status status;
4172 	u16 buf_len;
4173 
4174 	/* Free resource */
4175 	buf_len = sizeof(*buf);
4176 	buf = (struct ice_aqc_alloc_free_res_elem *)
4177 		ice_malloc(hw, buf_len);
4178 	if (!buf)
4179 		return ICE_ERR_NO_MEMORY;
4180 
4181 	buf->num_elems = CPU_TO_LE16(num_items);
4182 	buf->res_type = CPU_TO_LE16(((type << ICE_AQC_RES_TYPE_S) &
4183 				      ICE_AQC_RES_TYPE_M) | alloc_shared);
4184 	buf->elem[0].e.sw_resp = CPU_TO_LE16(counter_id);
4185 
4186 	status = ice_aq_alloc_free_res(hw, 1, buf, buf_len,
4187 				       ice_aqc_opc_free_res, NULL);
4188 	if (status)
4189 		ice_debug(hw, ICE_DBG_SW,
4190 			  "counter resource could not be freed\n");
4191 
4192 	ice_free(hw, buf);
4193 	return status;
4194 }
4195 
4196 /**
4197  * ice_alloc_vlan_res_counter - obtain counter resource for VLAN type
4198  * @hw: pointer to the hardware structure
4199  * @counter_id: returns counter index
4200  */
4201 enum ice_status ice_alloc_vlan_res_counter(struct ice_hw *hw, u16 *counter_id)
4202 {
4203 	return ice_alloc_res_cntr(hw, ICE_AQC_RES_TYPE_VLAN_COUNTER,
4204 				  ICE_AQC_RES_TYPE_FLAG_DEDICATED, 1,
4205 				  counter_id);
4206 }
4207 
4208 /**
4209  * ice_free_vlan_res_counter - Free counter resource for VLAN type
4210  * @hw: pointer to the hardware structure
4211  * @counter_id: counter index to be freed
4212  */
4213 enum ice_status ice_free_vlan_res_counter(struct ice_hw *hw, u16 counter_id)
4214 {
4215 	return ice_free_res_cntr(hw, ICE_AQC_RES_TYPE_VLAN_COUNTER,
4216 				 ICE_AQC_RES_TYPE_FLAG_DEDICATED, 1,
4217 				 counter_id);
4218 }
4219 
4220 /**
4221  * ice_alloc_res_lg_act - add large action resource
4222  * @hw: pointer to the hardware structure
4223  * @l_id: large action ID to fill it in
4224  * @num_acts: number of actions to hold with a large action entry
4225  */
4226 static enum ice_status
4227 ice_alloc_res_lg_act(struct ice_hw *hw, u16 *l_id, u16 num_acts)
4228 {
4229 	struct ice_aqc_alloc_free_res_elem *sw_buf;
4230 	enum ice_status status;
4231 	u16 buf_len;
4232 
4233 	if (num_acts > ICE_MAX_LG_ACT || num_acts == 0)
4234 		return ICE_ERR_PARAM;
4235 
4236 	/* Allocate resource for large action */
4237 	buf_len = sizeof(*sw_buf);
4238 	sw_buf = (struct ice_aqc_alloc_free_res_elem *)
4239 		ice_malloc(hw, buf_len);
4240 	if (!sw_buf)
4241 		return ICE_ERR_NO_MEMORY;
4242 
4243 	sw_buf->num_elems = CPU_TO_LE16(1);
4244 
4245 	/* If num_acts is 1, use ICE_AQC_RES_TYPE_WIDE_TABLE_1.
4246 	 * If num_acts is 2, use ICE_AQC_RES_TYPE_WIDE_TABLE_3.
4247 	 * If num_acts is greater than 2, then use
4248 	 * ICE_AQC_RES_TYPE_WIDE_TABLE_4.
4249 	 * The num_acts cannot exceed 4. This was ensured at the
4250 	 * beginning of the function.
4251 	 */
4252 	if (num_acts == 1)
4253 		sw_buf->res_type = CPU_TO_LE16(ICE_AQC_RES_TYPE_WIDE_TABLE_1);
4254 	else if (num_acts == 2)
4255 		sw_buf->res_type = CPU_TO_LE16(ICE_AQC_RES_TYPE_WIDE_TABLE_2);
4256 	else
4257 		sw_buf->res_type = CPU_TO_LE16(ICE_AQC_RES_TYPE_WIDE_TABLE_4);
4258 
4259 	status = ice_aq_alloc_free_res(hw, 1, sw_buf, buf_len,
4260 				       ice_aqc_opc_alloc_res, NULL);
4261 	if (!status)
4262 		*l_id = LE16_TO_CPU(sw_buf->elem[0].e.sw_resp);
4263 
4264 	ice_free(hw, sw_buf);
4265 	return status;
4266 }
4267 
4268 /**
4269  * ice_add_mac_with_sw_marker - add filter with sw marker
4270  * @hw: pointer to the hardware structure
4271  * @f_info: filter info structure containing the MAC filter information
4272  * @sw_marker: sw marker to tag the Rx descriptor with
4273  */
4274 enum ice_status
4275 ice_add_mac_with_sw_marker(struct ice_hw *hw, struct ice_fltr_info *f_info,
4276 			   u16 sw_marker)
4277 {
4278 	struct ice_switch_info *sw = hw->switch_info;
4279 	struct ice_fltr_mgmt_list_entry *m_entry;
4280 	struct ice_fltr_list_entry fl_info;
4281 	struct LIST_HEAD_TYPE l_head;
4282 	struct ice_lock *rule_lock;	/* Lock to protect filter rule list */
4283 	enum ice_status ret;
4284 	bool entry_exists;
4285 	u16 lg_act_id;
4286 
4287 	if (f_info->fltr_act != ICE_FWD_TO_VSI)
4288 		return ICE_ERR_PARAM;
4289 
4290 	if (f_info->lkup_type != ICE_SW_LKUP_MAC)
4291 		return ICE_ERR_PARAM;
4292 
4293 	if (sw_marker == ICE_INVAL_SW_MARKER_ID)
4294 		return ICE_ERR_PARAM;
4295 
4296 	if (!ice_is_vsi_valid(hw, f_info->vsi_handle))
4297 		return ICE_ERR_PARAM;
4298 	f_info->fwd_id.hw_vsi_id = ice_get_hw_vsi_num(hw, f_info->vsi_handle);
4299 
4300 	/* Add filter if it doesn't exist so then the adding of large
4301 	 * action always results in update
4302 	 */
4303 
4304 	INIT_LIST_HEAD(&l_head);
4305 	fl_info.fltr_info = *f_info;
4306 	LIST_ADD(&fl_info.list_entry, &l_head);
4307 
4308 	entry_exists = false;
4309 	ret = ice_add_mac(hw, &l_head);
4310 	if (ret == ICE_ERR_ALREADY_EXISTS)
4311 		entry_exists = true;
4312 	else if (ret)
4313 		return ret;
4314 
4315 	rule_lock = &sw->recp_list[ICE_SW_LKUP_MAC].filt_rule_lock;
4316 	ice_acquire_lock(rule_lock);
4317 	/* Get the book keeping entry for the filter */
4318 	m_entry = ice_find_rule_entry(hw, ICE_SW_LKUP_MAC, f_info);
4319 	if (!m_entry)
4320 		goto exit_error;
4321 
4322 	/* If counter action was enabled for this rule then don't enable
4323 	 * sw marker large action
4324 	 */
4325 	if (m_entry->counter_index != ICE_INVAL_COUNTER_ID) {
4326 		ret = ICE_ERR_PARAM;
4327 		goto exit_error;
4328 	}
4329 
4330 	/* if same marker was added before */
4331 	if (m_entry->sw_marker_id == sw_marker) {
4332 		ret = ICE_ERR_ALREADY_EXISTS;
4333 		goto exit_error;
4334 	}
4335 
4336 	/* Allocate a hardware table entry to hold large act. Three actions
4337 	 * for marker based large action
4338 	 */
4339 	ret = ice_alloc_res_lg_act(hw, &lg_act_id, 3);
4340 	if (ret)
4341 		goto exit_error;
4342 
4343 	if (lg_act_id == ICE_INVAL_LG_ACT_INDEX)
4344 		goto exit_error;
4345 
4346 	/* Update the switch rule to add the marker action */
4347 	ret = ice_add_marker_act(hw, m_entry, sw_marker, lg_act_id);
4348 	if (!ret) {
4349 		ice_release_lock(rule_lock);
4350 		return ret;
4351 	}
4352 
4353 exit_error:
4354 	ice_release_lock(rule_lock);
4355 	/* only remove entry if it did not exist previously */
4356 	if (!entry_exists)
4357 		ret = ice_remove_mac(hw, &l_head);
4358 
4359 	return ret;
4360 }
4361 
4362 /**
4363  * ice_add_mac_with_counter - add filter with counter enabled
4364  * @hw: pointer to the hardware structure
4365  * @f_info: pointer to filter info structure containing the MAC filter
4366  *          information
4367  */
4368 enum ice_status
4369 ice_add_mac_with_counter(struct ice_hw *hw, struct ice_fltr_info *f_info)
4370 {
4371 	struct ice_switch_info *sw = hw->switch_info;
4372 	struct ice_fltr_mgmt_list_entry *m_entry;
4373 	struct ice_fltr_list_entry fl_info;
4374 	struct LIST_HEAD_TYPE l_head;
4375 	struct ice_lock *rule_lock;	/* Lock to protect filter rule list */
4376 	enum ice_status ret;
4377 	bool entry_exist;
4378 	u16 counter_id;
4379 	u16 lg_act_id;
4380 
4381 	if (f_info->fltr_act != ICE_FWD_TO_VSI)
4382 		return ICE_ERR_PARAM;
4383 
4384 	if (f_info->lkup_type != ICE_SW_LKUP_MAC)
4385 		return ICE_ERR_PARAM;
4386 
4387 	if (!ice_is_vsi_valid(hw, f_info->vsi_handle))
4388 		return ICE_ERR_PARAM;
4389 	f_info->fwd_id.hw_vsi_id = ice_get_hw_vsi_num(hw, f_info->vsi_handle);
4390 
4391 	entry_exist = false;
4392 
4393 	rule_lock = &sw->recp_list[ICE_SW_LKUP_MAC].filt_rule_lock;
4394 
4395 	/* Add filter if it doesn't exist so then the adding of large
4396 	 * action always results in update
4397 	 */
4398 	INIT_LIST_HEAD(&l_head);
4399 
4400 	fl_info.fltr_info = *f_info;
4401 	LIST_ADD(&fl_info.list_entry, &l_head);
4402 
4403 	ret = ice_add_mac(hw, &l_head);
4404 	if (ret == ICE_ERR_ALREADY_EXISTS)
4405 		entry_exist = true;
4406 	else if (ret)
4407 		return ret;
4408 
4409 	ice_acquire_lock(rule_lock);
4410 	m_entry = ice_find_rule_entry(hw, ICE_SW_LKUP_MAC, f_info);
4411 	if (!m_entry) {
4412 		ret = ICE_ERR_BAD_PTR;
4413 		goto exit_error;
4414 	}
4415 
4416 	/* Don't enable counter for a filter for which sw marker was enabled */
4417 	if (m_entry->sw_marker_id != ICE_INVAL_SW_MARKER_ID) {
4418 		ret = ICE_ERR_PARAM;
4419 		goto exit_error;
4420 	}
4421 
4422 	/* If a counter was already enabled then don't need to add again */
4423 	if (m_entry->counter_index != ICE_INVAL_COUNTER_ID) {
4424 		ret = ICE_ERR_ALREADY_EXISTS;
4425 		goto exit_error;
4426 	}
4427 
4428 	/* Allocate a hardware table entry to VLAN counter */
4429 	ret = ice_alloc_vlan_res_counter(hw, &counter_id);
4430 	if (ret)
4431 		goto exit_error;
4432 
4433 	/* Allocate a hardware table entry to hold large act. Two actions for
4434 	 * counter based large action
4435 	 */
4436 	ret = ice_alloc_res_lg_act(hw, &lg_act_id, 2);
4437 	if (ret)
4438 		goto exit_error;
4439 
4440 	if (lg_act_id == ICE_INVAL_LG_ACT_INDEX)
4441 		goto exit_error;
4442 
4443 	/* Update the switch rule to add the counter action */
4444 	ret = ice_add_counter_act(hw, m_entry, counter_id, lg_act_id);
4445 	if (!ret) {
4446 		ice_release_lock(rule_lock);
4447 		return ret;
4448 	}
4449 
4450 exit_error:
4451 	ice_release_lock(rule_lock);
4452 	/* only remove entry if it did not exist previously */
4453 	if (!entry_exist)
4454 		ret = ice_remove_mac(hw, &l_head);
4455 
4456 	return ret;
4457 }
4458 
4459 /* This is mapping table entry that maps every word within a given protocol
4460  * structure to the real byte offset as per the specification of that
4461  * protocol header.
4462  * for example dst address is 3 words in ethertype header and corresponding
4463  * bytes are 0, 2, 3 in the actual packet header and src address is at 4, 6, 8
4464  * IMPORTANT: Every structure part of "ice_prot_hdr" union should have a
4465  * matching entry describing its field. This needs to be updated if new
4466  * structure is added to that union.
4467  */
4468 static const struct ice_prot_ext_tbl_entry ice_prot_ext[] = {
4469 	{ ICE_MAC_OFOS,		{ 0, 2, 4, 6, 8, 10, 12 } },
4470 	{ ICE_MAC_IL,		{ 0, 2, 4, 6, 8, 10, 12 } },
4471 	{ ICE_ETYPE_OL,		{ 0 } },
4472 	{ ICE_IPV4_OFOS,	{ 0, 2, 4, 6, 8, 10, 12, 14, 16, 18 } },
4473 	{ ICE_IPV4_IL,		{ 0, 2, 4, 6, 8, 10, 12, 14, 16, 18 } },
4474 	{ ICE_IPV6_IL,		{ 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24,
4475 				 26, 28, 30, 32, 34, 36, 38 } },
4476 	{ ICE_IPV6_OFOS,	{ 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24,
4477 				 26, 28, 30, 32, 34, 36, 38 } },
4478 	{ ICE_TCP_IL,		{ 0, 2 } },
4479 	{ ICE_UDP_OF,		{ 0, 2 } },
4480 	{ ICE_UDP_ILOS,		{ 0, 2 } },
4481 	{ ICE_SCTP_IL,		{ 0, 2 } },
4482 	{ ICE_VXLAN,		{ 8, 10, 12, 14 } },
4483 	{ ICE_GENEVE,		{ 8, 10, 12, 14 } },
4484 	{ ICE_VXLAN_GPE,	{ 0, 2, 4 } },
4485 	{ ICE_NVGRE,		{ 0, 2, 4, 6 } },
4486 	{ ICE_PROTOCOL_LAST,	{ 0 } }
4487 };
4488 
4489 /* The following table describes preferred grouping of recipes.
4490  * If a recipe that needs to be programmed is a superset or matches one of the
4491  * following combinations, then the recipe needs to be chained as per the
4492  * following policy.
4493  */
4494 static const struct ice_pref_recipe_group ice_recipe_pack[] = {
4495 	{3, { { ICE_MAC_OFOS_HW, 0, 0 }, { ICE_MAC_OFOS_HW, 2, 0 },
4496 	      { ICE_MAC_OFOS_HW, 4, 0 } }, { 0xffff, 0xffff, 0xffff, 0xffff } },
4497 	{4, { { ICE_MAC_IL_HW, 0, 0 }, { ICE_MAC_IL_HW, 2, 0 },
4498 	      { ICE_MAC_IL_HW, 4, 0 }, { ICE_META_DATA_ID_HW, 44, 0 } },
4499 		{ 0xffff, 0xffff, 0xffff, 0xffff } },
4500 	{2, { { ICE_IPV4_IL_HW, 0, 0 }, { ICE_IPV4_IL_HW, 2, 0 } },
4501 		{ 0xffff, 0xffff, 0xffff, 0xffff } },
4502 	{2, { { ICE_IPV4_IL_HW, 12, 0 }, { ICE_IPV4_IL_HW, 14, 0 } },
4503 		{ 0xffff, 0xffff, 0xffff, 0xffff } },
4504 };
4505 
4506 static const struct ice_protocol_entry ice_prot_id_tbl[] = {
4507 	{ ICE_MAC_OFOS,		ICE_MAC_OFOS_HW },
4508 	{ ICE_MAC_IL,		ICE_MAC_IL_HW },
4509 	{ ICE_ETYPE_OL,		ICE_ETYPE_OL_HW },
4510 	{ ICE_IPV4_OFOS,	ICE_IPV4_OFOS_HW },
4511 	{ ICE_IPV4_IL,		ICE_IPV4_IL_HW },
4512 	{ ICE_IPV6_OFOS,	ICE_IPV6_OFOS_HW },
4513 	{ ICE_IPV6_IL,		ICE_IPV6_IL_HW },
4514 	{ ICE_TCP_IL,		ICE_TCP_IL_HW },
4515 	{ ICE_UDP_OF,		ICE_UDP_OF_HW },
4516 	{ ICE_UDP_ILOS,		ICE_UDP_ILOS_HW },
4517 	{ ICE_SCTP_IL,		ICE_SCTP_IL_HW },
4518 	{ ICE_VXLAN,		ICE_UDP_OF_HW },
4519 	{ ICE_GENEVE,		ICE_UDP_OF_HW },
4520 	{ ICE_VXLAN_GPE,	ICE_UDP_OF_HW },
4521 	{ ICE_NVGRE,		ICE_GRE_OF_HW },
4522 	{ ICE_PROTOCOL_LAST,	0 }
4523 };
4524 
4525 /**
4526  * ice_find_recp - find a recipe
4527  * @hw: pointer to the hardware structure
4528  * @lkup_exts: extension sequence to match
4529  *
4530  * Returns index of matching recipe, or ICE_MAX_NUM_RECIPES if not found.
4531  */
4532 static u16 ice_find_recp(struct ice_hw *hw, struct ice_prot_lkup_ext *lkup_exts)
4533 {
4534 	bool refresh_required = true;
4535 	struct ice_sw_recipe *recp;
4536 	u16 i;
4537 
4538 	/* Initialize available_result_ids which tracks available result idx */
4539 	for (i = 0; i <= ICE_CHAIN_FV_INDEX_START; i++)
4540 		ice_set_bit(ICE_CHAIN_FV_INDEX_START - i,
4541 			    available_result_ids);
4542 
4543 	/* Walk through existing recipes to find a match */
4544 	recp = hw->switch_info->recp_list;
4545 	for (i = 0; i < ICE_MAX_NUM_RECIPES; i++) {
4546 		/* If recipe was not created for this ID, in SW bookkeeping,
4547 		 * check if FW has an entry for this recipe. If the FW has an
4548 		 * entry update it in our SW bookkeeping and continue with the
4549 		 * matching.
4550 		 */
4551 		if (!recp[i].recp_created)
4552 			if (ice_get_recp_frm_fw(hw,
4553 						hw->switch_info->recp_list, i,
4554 						&refresh_required))
4555 				continue;
4556 
4557 		/* if number of words we are looking for match */
4558 		if (lkup_exts->n_val_words == recp[i].lkup_exts.n_val_words) {
4559 			struct ice_fv_word *a = lkup_exts->fv_words;
4560 			struct ice_fv_word *b = recp[i].lkup_exts.fv_words;
4561 			bool found = true;
4562 			u8 p, q;
4563 
4564 			for (p = 0; p < lkup_exts->n_val_words; p++) {
4565 				for (q = 0; q < recp[i].lkup_exts.n_val_words;
4566 				     q++) {
4567 					if (a[p].off == b[q].off &&
4568 					    a[p].prot_id == b[q].prot_id)
4569 						/* Found the "p"th word in the
4570 						 * given recipe
4571 						 */
4572 						break;
4573 				}
4574 				/* After walking through all the words in the
4575 				 * "i"th recipe if "p"th word was not found then
4576 				 * this recipe is not what we are looking for.
4577 				 * So break out from this loop and try the next
4578 				 * recipe
4579 				 */
4580 				if (q >= recp[i].lkup_exts.n_val_words) {
4581 					found = false;
4582 					break;
4583 				}
4584 			}
4585 			/* If for "i"th recipe the found was never set to false
4586 			 * then it means we found our match
4587 			 */
4588 			if (found)
4589 				return i; /* Return the recipe ID */
4590 		}
4591 	}
4592 	return ICE_MAX_NUM_RECIPES;
4593 }
4594 
4595 /**
4596  * ice_prot_type_to_id - get protocol ID from protocol type
4597  * @type: protocol type
4598  * @id: pointer to variable that will receive the ID
4599  *
4600  * Returns true if found, false otherwise
4601  */
4602 static bool ice_prot_type_to_id(enum ice_protocol_type type, u16 *id)
4603 {
4604 	u16 i;
4605 
4606 	for (i = 0; ice_prot_id_tbl[i].type != ICE_PROTOCOL_LAST; i++)
4607 		if (ice_prot_id_tbl[i].type == type) {
4608 			*id = ice_prot_id_tbl[i].protocol_id;
4609 			return true;
4610 		}
4611 	return false;
4612 }
4613 
4614 /**
4615  * ice_find_valid_words - count valid words
4616  * @rule: advanced rule with lookup information
4617  * @lkup_exts: byte offset extractions of the words that are valid
4618  *
4619  * calculate valid words in a lookup rule using mask value
4620  */
4621 static u16
4622 ice_fill_valid_words(struct ice_adv_lkup_elem *rule,
4623 		     struct ice_prot_lkup_ext *lkup_exts)
4624 {
4625 	u16 j, word = 0;
4626 	u16 prot_id;
4627 	u16 ret_val;
4628 
4629 	if (!ice_prot_type_to_id(rule->type, &prot_id))
4630 		return 0;
4631 
4632 	word = lkup_exts->n_val_words;
4633 
4634 	for (j = 0; j < sizeof(rule->m_u) / sizeof(u16); j++)
4635 		if (((u16 *)&rule->m_u)[j] &&
4636 		    (unsigned long)rule->type < ARRAY_SIZE(ice_prot_ext)) {
4637 			/* No more space to accommodate */
4638 			if (word >= ICE_MAX_CHAIN_WORDS)
4639 				return 0;
4640 			lkup_exts->fv_words[word].off =
4641 				ice_prot_ext[rule->type].offs[j];
4642 			lkup_exts->fv_words[word].prot_id =
4643 				ice_prot_id_tbl[rule->type].protocol_id;
4644 			lkup_exts->field_mask[word] = ((u16 *)&rule->m_u)[j];
4645 			word++;
4646 		}
4647 
4648 	ret_val = word - lkup_exts->n_val_words;
4649 	lkup_exts->n_val_words = word;
4650 
4651 	return ret_val;
4652 }
4653 
4654 /**
4655  * ice_find_prot_off_ind - check for specific ID and offset in rule
4656  * @lkup_exts: an array of protocol header extractions
4657  * @prot_type: protocol type to check
4658  * @off: expected offset of the extraction
4659  *
4660  * Check if the prot_ext has given protocol ID and offset
4661  */
4662 static u8
4663 ice_find_prot_off_ind(struct ice_prot_lkup_ext *lkup_exts, u8 prot_type,
4664 		      u16 off)
4665 {
4666 	u8 j;
4667 
4668 	for (j = 0; j < lkup_exts->n_val_words; j++)
4669 		if (lkup_exts->fv_words[j].off == off &&
4670 		    lkup_exts->fv_words[j].prot_id == prot_type)
4671 			return j;
4672 
4673 	return ICE_MAX_CHAIN_WORDS;
4674 }
4675 
4676 /**
4677  * ice_is_recipe_subset - check if recipe group policy is a subset of lookup
4678  * @lkup_exts: an array of protocol header extractions
4679  * @r_policy: preferred recipe grouping policy
4680  *
4681  * Helper function to check if given recipe group is subset we need to check if
4682  * all the words described by the given recipe group exist in the advanced rule
4683  * look up information
4684  */
4685 static bool
4686 ice_is_recipe_subset(struct ice_prot_lkup_ext *lkup_exts,
4687 		     const struct ice_pref_recipe_group *r_policy)
4688 {
4689 	u8 ind[ICE_NUM_WORDS_RECIPE];
4690 	u8 count = 0;
4691 	u8 i;
4692 
4693 	/* check if everything in the r_policy is part of the entire rule */
4694 	for (i = 0; i < r_policy->n_val_pairs; i++) {
4695 		u8 j;
4696 
4697 		j = ice_find_prot_off_ind(lkup_exts, r_policy->pairs[i].prot_id,
4698 					  r_policy->pairs[i].off);
4699 		if (j >= ICE_MAX_CHAIN_WORDS)
4700 			return false;
4701 
4702 		/* store the indexes temporarily found by the find function
4703 		 * this will be used to mark the words as 'done'
4704 		 */
4705 		ind[count++] = j;
4706 	}
4707 
4708 	/* If the entire policy recipe was a true match, then mark the fields
4709 	 * that are covered by the recipe as 'done' meaning that these words
4710 	 * will be clumped together in one recipe.
4711 	 * "Done" here means in our searching if certain recipe group
4712 	 * matches or is subset of the given rule, then we mark all
4713 	 * the corresponding offsets as found. So the remaining recipes should
4714 	 * be created with whatever words that were left.
4715 	 */
4716 	for (i = 0; i < count; i++) {
4717 		u8 in = ind[i];
4718 
4719 		ice_set_bit(in, lkup_exts->done);
4720 	}
4721 	return true;
4722 }
4723 
4724 /**
4725  * ice_create_first_fit_recp_def - Create a recipe grouping
4726  * @hw: pointer to the hardware structure
4727  * @lkup_exts: an array of protocol header extractions
4728  * @rg_list: pointer to a list that stores new recipe groups
4729  * @recp_cnt: pointer to a variable that stores returned number of recipe groups
4730  *
4731  * Using first fit algorithm, take all the words that are still not done
4732  * and start grouping them in 4-word groups. Each group makes up one
4733  * recipe.
4734  */
4735 static enum ice_status
4736 ice_create_first_fit_recp_def(struct ice_hw *hw,
4737 			      struct ice_prot_lkup_ext *lkup_exts,
4738 			      struct LIST_HEAD_TYPE *rg_list,
4739 			      u8 *recp_cnt)
4740 {
4741 	struct ice_pref_recipe_group *grp = NULL;
4742 	u8 j;
4743 
4744 	*recp_cnt = 0;
4745 
4746 	/* Walk through every word in the rule to check if it is not done. If so
4747 	 * then this word needs to be part of a new recipe.
4748 	 */
4749 	for (j = 0; j < lkup_exts->n_val_words; j++)
4750 		if (!ice_is_bit_set(lkup_exts->done, j)) {
4751 			if (!grp ||
4752 			    grp->n_val_pairs == ICE_NUM_WORDS_RECIPE) {
4753 				struct ice_recp_grp_entry *entry;
4754 
4755 				entry = (struct ice_recp_grp_entry *)
4756 					ice_malloc(hw, sizeof(*entry));
4757 				if (!entry)
4758 					return ICE_ERR_NO_MEMORY;
4759 				LIST_ADD(&entry->l_entry, rg_list);
4760 				grp = &entry->r_group;
4761 				(*recp_cnt)++;
4762 			}
4763 
4764 			grp->pairs[grp->n_val_pairs].prot_id =
4765 				lkup_exts->fv_words[j].prot_id;
4766 			grp->pairs[grp->n_val_pairs].off =
4767 				lkup_exts->fv_words[j].off;
4768 			grp->mask[grp->n_val_pairs] = lkup_exts->field_mask[j];
4769 			grp->n_val_pairs++;
4770 		}
4771 
4772 	return ICE_SUCCESS;
4773 }
4774 
4775 /**
4776  * ice_fill_fv_word_index - fill in the field vector indices for a recipe group
4777  * @hw: pointer to the hardware structure
4778  * @fv_list: field vector with the extraction sequence information
4779  * @rg_list: recipe groupings with protocol-offset pairs
4780  *
4781  * Helper function to fill in the field vector indices for protocol-offset
4782  * pairs. These indexes are then ultimately programmed into a recipe.
4783  */
4784 static void
4785 ice_fill_fv_word_index(struct ice_hw *hw, struct LIST_HEAD_TYPE *fv_list,
4786 		       struct LIST_HEAD_TYPE *rg_list)
4787 {
4788 	struct ice_sw_fv_list_entry *fv;
4789 	struct ice_recp_grp_entry *rg;
4790 	struct ice_fv_word *fv_ext;
4791 
4792 	if (LIST_EMPTY(fv_list))
4793 		return;
4794 
4795 	fv = LIST_FIRST_ENTRY(fv_list, struct ice_sw_fv_list_entry, list_entry);
4796 	fv_ext = fv->fv_ptr->ew;
4797 
4798 	LIST_FOR_EACH_ENTRY(rg, rg_list, ice_recp_grp_entry, l_entry) {
4799 		u8 i;
4800 
4801 		for (i = 0; i < rg->r_group.n_val_pairs; i++) {
4802 			struct ice_fv_word *pr;
4803 			u16 mask;
4804 			u8 j;
4805 
4806 			pr = &rg->r_group.pairs[i];
4807 			mask = rg->r_group.mask[i];
4808 
4809 			for (j = 0; j < hw->blk[ICE_BLK_SW].es.fvw; j++)
4810 				if (fv_ext[j].prot_id == pr->prot_id &&
4811 				    fv_ext[j].off == pr->off) {
4812 					/* Store index of field vector */
4813 					rg->fv_idx[i] = j;
4814 					/* Mask is given by caller as big
4815 					 * endian, but sent to FW as little
4816 					 * endian
4817 					 */
4818 					rg->fv_mask[i] = mask << 8 | mask >> 8;
4819 					break;
4820 				}
4821 		}
4822 	}
4823 }
4824 
4825 /**
4826  * ice_add_sw_recipe - function to call AQ calls to create switch recipe
4827  * @hw: pointer to hardware structure
4828  * @rm: recipe management list entry
4829  * @match_tun: if field vector index for tunnel needs to be programmed
4830  */
4831 static enum ice_status
4832 ice_add_sw_recipe(struct ice_hw *hw, struct ice_sw_recipe *rm,
4833 		  bool match_tun)
4834 {
4835 	struct ice_aqc_recipe_data_elem *tmp;
4836 	struct ice_aqc_recipe_data_elem *buf;
4837 	struct ice_recp_grp_entry *entry;
4838 	enum ice_status status;
4839 	u16 recipe_count;
4840 	u8 chain_idx;
4841 	u8 recps = 0;
4842 
4843 	/* When more than one recipe are required, another recipe is needed to
4844 	 * chain them together. Matching a tunnel metadata ID takes up one of
4845 	 * the match fields in the chaining recipe reducing the number of
4846 	 * chained recipes by one.
4847 	 */
4848 	if (rm->n_grp_count > 1)
4849 		rm->n_grp_count++;
4850 	if (rm->n_grp_count > ICE_MAX_CHAIN_RECIPE ||
4851 	    (match_tun && rm->n_grp_count > (ICE_MAX_CHAIN_RECIPE - 1)))
4852 		return ICE_ERR_MAX_LIMIT;
4853 
4854 	tmp = (struct ice_aqc_recipe_data_elem *)ice_calloc(hw,
4855 							    ICE_MAX_NUM_RECIPES,
4856 							    sizeof(*tmp));
4857 	if (!tmp)
4858 		return ICE_ERR_NO_MEMORY;
4859 
4860 	buf = (struct ice_aqc_recipe_data_elem *)
4861 		ice_calloc(hw, rm->n_grp_count, sizeof(*buf));
4862 	if (!buf) {
4863 		status = ICE_ERR_NO_MEMORY;
4864 		goto err_mem;
4865 	}
4866 
4867 	ice_zero_bitmap(rm->r_bitmap, ICE_MAX_NUM_RECIPES);
4868 	recipe_count = ICE_MAX_NUM_RECIPES;
4869 	status = ice_aq_get_recipe(hw, tmp, &recipe_count, ICE_SW_LKUP_MAC,
4870 				   NULL);
4871 	if (status || recipe_count == 0)
4872 		goto err_unroll;
4873 
4874 	/* Allocate the recipe resources, and configure them according to the
4875 	 * match fields from protocol headers and extracted field vectors.
4876 	 */
4877 	chain_idx = ICE_CHAIN_FV_INDEX_START -
4878 		ice_find_first_bit(available_result_ids,
4879 				   ICE_CHAIN_FV_INDEX_START + 1);
4880 	LIST_FOR_EACH_ENTRY(entry, &rm->rg_list, ice_recp_grp_entry, l_entry) {
4881 		u8 i;
4882 
4883 		status = ice_alloc_recipe(hw, &entry->rid);
4884 		if (status)
4885 			goto err_unroll;
4886 
4887 		/* Clear the result index of the located recipe, as this will be
4888 		 * updated, if needed, later in the recipe creation process.
4889 		 */
4890 		tmp[0].content.result_indx = 0;
4891 
4892 		buf[recps] = tmp[0];
4893 		buf[recps].recipe_indx = (u8)entry->rid;
4894 		/* if the recipe is a non-root recipe RID should be programmed
4895 		 * as 0 for the rules to be applied correctly.
4896 		 */
4897 		buf[recps].content.rid = 0;
4898 		ice_memset(&buf[recps].content.lkup_indx, 0,
4899 			   sizeof(buf[recps].content.lkup_indx),
4900 			   ICE_NONDMA_MEM);
4901 
4902 		/* All recipes use look-up index 0 to match switch ID. */
4903 		buf[recps].content.lkup_indx[0] = ICE_AQ_SW_ID_LKUP_IDX;
4904 		buf[recps].content.mask[0] =
4905 			CPU_TO_LE16(ICE_AQ_SW_ID_LKUP_MASK);
4906 		/* Setup lkup_indx 1..4 to INVALID/ignore and set the mask
4907 		 * to be 0
4908 		 */
4909 		for (i = 1; i <= ICE_NUM_WORDS_RECIPE; i++) {
4910 			buf[recps].content.lkup_indx[i] = 0x80;
4911 			buf[recps].content.mask[i] = 0;
4912 		}
4913 
4914 		for (i = 0; i < entry->r_group.n_val_pairs; i++) {
4915 			buf[recps].content.lkup_indx[i + 1] = entry->fv_idx[i];
4916 			buf[recps].content.mask[i + 1] =
4917 				CPU_TO_LE16(entry->fv_mask[i]);
4918 		}
4919 
4920 		if (rm->n_grp_count > 1) {
4921 			entry->chain_idx = chain_idx;
4922 			buf[recps].content.result_indx =
4923 				ICE_AQ_RECIPE_RESULT_EN |
4924 				((chain_idx << ICE_AQ_RECIPE_RESULT_DATA_S) &
4925 				 ICE_AQ_RECIPE_RESULT_DATA_M);
4926 			ice_clear_bit(ICE_CHAIN_FV_INDEX_START - chain_idx,
4927 				      available_result_ids);
4928 			chain_idx = ICE_CHAIN_FV_INDEX_START -
4929 				ice_find_first_bit(available_result_ids,
4930 						   ICE_CHAIN_FV_INDEX_START +
4931 						   1);
4932 		}
4933 
4934 		/* fill recipe dependencies */
4935 		ice_zero_bitmap((ice_bitmap_t *)buf[recps].recipe_bitmap,
4936 				ICE_MAX_NUM_RECIPES);
4937 		ice_set_bit(buf[recps].recipe_indx,
4938 			    (ice_bitmap_t *)buf[recps].recipe_bitmap);
4939 		buf[recps].content.act_ctrl_fwd_priority = rm->priority;
4940 		recps++;
4941 	}
4942 
4943 	if (rm->n_grp_count == 1) {
4944 		rm->root_rid = buf[0].recipe_indx;
4945 		ice_set_bit(buf[0].recipe_indx, rm->r_bitmap);
4946 		buf[0].content.rid = rm->root_rid | ICE_AQ_RECIPE_ID_IS_ROOT;
4947 		if (sizeof(buf[0].recipe_bitmap) >= sizeof(rm->r_bitmap)) {
4948 			ice_memcpy(buf[0].recipe_bitmap, rm->r_bitmap,
4949 				   sizeof(buf[0].recipe_bitmap),
4950 				   ICE_NONDMA_TO_NONDMA);
4951 		} else {
4952 			status = ICE_ERR_BAD_PTR;
4953 			goto err_unroll;
4954 		}
4955 		/* Applicable only for ROOT_RECIPE, set the fwd_priority for
4956 		 * the recipe which is getting created if specified
4957 		 * by user. Usually any advanced switch filter, which results
4958 		 * into new extraction sequence, ended up creating a new recipe
4959 		 * of type ROOT and usually recipes are associated with profiles
4960 		 * Switch rule referreing newly created recipe, needs to have
4961 		 * either/or 'fwd' or 'join' priority, otherwise switch rule
4962 		 * evaluation will not happen correctly. In other words, if
4963 		 * switch rule to be evaluated on priority basis, then recipe
4964 		 * needs to have priority, otherwise it will be evaluated last.
4965 		 */
4966 		buf[0].content.act_ctrl_fwd_priority = rm->priority;
4967 	} else {
4968 		struct ice_recp_grp_entry *last_chain_entry;
4969 		u16 rid, i;
4970 
4971 		/* Allocate the last recipe that will chain the outcomes of the
4972 		 * other recipes together
4973 		 */
4974 		status = ice_alloc_recipe(hw, &rid);
4975 		if (status)
4976 			goto err_unroll;
4977 
4978 		buf[recps].recipe_indx = (u8)rid;
4979 		buf[recps].content.rid = (u8)rid;
4980 		buf[recps].content.rid |= ICE_AQ_RECIPE_ID_IS_ROOT;
4981 		/* the new entry created should also be part of rg_list to
4982 		 * make sure we have complete recipe
4983 		 */
4984 		last_chain_entry = (struct ice_recp_grp_entry *)ice_malloc(hw,
4985 			sizeof(*last_chain_entry));
4986 		if (!last_chain_entry) {
4987 			status = ICE_ERR_NO_MEMORY;
4988 			goto err_unroll;
4989 		}
4990 		last_chain_entry->rid = rid;
4991 		ice_memset(&buf[recps].content.lkup_indx, 0,
4992 			   sizeof(buf[recps].content.lkup_indx),
4993 			   ICE_NONDMA_MEM);
4994 		/* All recipes use look-up index 0 to match switch ID. */
4995 		buf[recps].content.lkup_indx[0] = ICE_AQ_SW_ID_LKUP_IDX;
4996 		buf[recps].content.mask[0] =
4997 			CPU_TO_LE16(ICE_AQ_SW_ID_LKUP_MASK);
4998 		for (i = 1; i <= ICE_NUM_WORDS_RECIPE; i++) {
4999 			buf[recps].content.lkup_indx[i] =
5000 				ICE_AQ_RECIPE_LKUP_IGNORE;
5001 			buf[recps].content.mask[i] = 0;
5002 		}
5003 
5004 		i = 1;
5005 		/* update r_bitmap with the recp that is used for chaining */
5006 		ice_set_bit(rid, rm->r_bitmap);
5007 		/* this is the recipe that chains all the other recipes so it
5008 		 * should not have a chaining ID to indicate the same
5009 		 */
5010 		last_chain_entry->chain_idx = ICE_INVAL_CHAIN_IND;
5011 		LIST_FOR_EACH_ENTRY(entry, &rm->rg_list, ice_recp_grp_entry,
5012 				    l_entry) {
5013 			last_chain_entry->fv_idx[i] = entry->chain_idx;
5014 			buf[recps].content.lkup_indx[i] = entry->chain_idx;
5015 			buf[recps].content.mask[i++] = CPU_TO_LE16(0xFFFF);
5016 			ice_set_bit(entry->rid, rm->r_bitmap);
5017 		}
5018 		LIST_ADD(&last_chain_entry->l_entry, &rm->rg_list);
5019 		if (sizeof(buf[recps].recipe_bitmap) >=
5020 		    sizeof(rm->r_bitmap)) {
5021 			ice_memcpy(buf[recps].recipe_bitmap, rm->r_bitmap,
5022 				   sizeof(buf[recps].recipe_bitmap),
5023 				   ICE_NONDMA_TO_NONDMA);
5024 		} else {
5025 			status = ICE_ERR_BAD_PTR;
5026 			goto err_unroll;
5027 		}
5028 		buf[recps].content.act_ctrl_fwd_priority = rm->priority;
5029 
5030 		/* To differentiate among different UDP tunnels, a meta data ID
5031 		 * flag is used.
5032 		 */
5033 		if (match_tun) {
5034 			buf[recps].content.lkup_indx[i] = ICE_TUN_FLAG_FV_IND;
5035 			buf[recps].content.mask[i] =
5036 				CPU_TO_LE16(ICE_TUN_FLAG_MASK);
5037 		}
5038 
5039 		recps++;
5040 		rm->root_rid = (u8)rid;
5041 	}
5042 	status = ice_acquire_change_lock(hw, ICE_RES_WRITE);
5043 	if (status)
5044 		goto err_unroll;
5045 
5046 	status = ice_aq_add_recipe(hw, buf, rm->n_grp_count, NULL);
5047 	ice_release_change_lock(hw);
5048 	if (status)
5049 		goto err_unroll;
5050 
5051 	/* Every recipe that just got created add it to the recipe
5052 	 * book keeping list
5053 	 */
5054 	LIST_FOR_EACH_ENTRY(entry, &rm->rg_list, ice_recp_grp_entry, l_entry) {
5055 		struct ice_switch_info *sw = hw->switch_info;
5056 		struct ice_sw_recipe *recp;
5057 
5058 		recp = &sw->recp_list[entry->rid];
5059 		recp->root_rid = entry->rid;
5060 		ice_memcpy(&recp->ext_words, entry->r_group.pairs,
5061 			   entry->r_group.n_val_pairs *
5062 			   sizeof(struct ice_fv_word),
5063 			   ICE_NONDMA_TO_NONDMA);
5064 
5065 		recp->n_ext_words = entry->r_group.n_val_pairs;
5066 		recp->chain_idx = entry->chain_idx;
5067 		recp->recp_created = true;
5068 		recp->big_recp = false;
5069 	}
5070 	rm->root_buf = buf;
5071 	ice_free(hw, tmp);
5072 	return status;
5073 
5074 err_unroll:
5075 err_mem:
5076 	ice_free(hw, tmp);
5077 	ice_free(hw, buf);
5078 	return status;
5079 }
5080 
5081 /**
5082  * ice_create_recipe_group - creates recipe group
5083  * @hw: pointer to hardware structure
5084  * @rm: recipe management list entry
5085  * @lkup_exts: lookup elements
5086  */
5087 static enum ice_status
5088 ice_create_recipe_group(struct ice_hw *hw, struct ice_sw_recipe *rm,
5089 			struct ice_prot_lkup_ext *lkup_exts)
5090 {
5091 	struct ice_recp_grp_entry *entry;
5092 	struct ice_recp_grp_entry *tmp;
5093 	enum ice_status status;
5094 	u8 recp_count = 0;
5095 	u16 groups, i;
5096 
5097 	rm->n_grp_count = 0;
5098 
5099 	/* Each switch recipe can match up to 5 words or metadata. One word in
5100 	 * each recipe is used to match the switch ID. Four words are left for
5101 	 * matching other values. If the new advanced recipe requires more than
5102 	 * 4 words, it needs to be split into multiple recipes which are chained
5103 	 * together using the intermediate result that each produces as input to
5104 	 * the other recipes in the sequence.
5105 	 */
5106 	groups = ARRAY_SIZE(ice_recipe_pack);
5107 
5108 	/* Check if any of the preferred recipes from the grouping policy
5109 	 * matches.
5110 	 */
5111 	for (i = 0; i < groups; i++)
5112 		/* Check if the recipe from the preferred grouping matches
5113 		 * or is a subset of the fields that needs to be looked up.
5114 		 */
5115 		if (ice_is_recipe_subset(lkup_exts, &ice_recipe_pack[i])) {
5116 			/* This recipe can be used by itself or grouped with
5117 			 * other recipes.
5118 			 */
5119 			entry = (struct ice_recp_grp_entry *)
5120 				ice_malloc(hw, sizeof(*entry));
5121 			if (!entry) {
5122 				status = ICE_ERR_NO_MEMORY;
5123 				goto err_unroll;
5124 			}
5125 			entry->r_group = ice_recipe_pack[i];
5126 			LIST_ADD(&entry->l_entry, &rm->rg_list);
5127 			rm->n_grp_count++;
5128 		}
5129 
5130 	/* Create recipes for words that are marked not done by packing them
5131 	 * as best fit.
5132 	 */
5133 	status = ice_create_first_fit_recp_def(hw, lkup_exts,
5134 					       &rm->rg_list, &recp_count);
5135 	if (!status) {
5136 		rm->n_grp_count += recp_count;
5137 		rm->n_ext_words = lkup_exts->n_val_words;
5138 		ice_memcpy(&rm->ext_words, lkup_exts->fv_words,
5139 			   sizeof(rm->ext_words), ICE_NONDMA_TO_NONDMA);
5140 		ice_memcpy(rm->word_masks, lkup_exts->field_mask,
5141 			   sizeof(rm->word_masks), ICE_NONDMA_TO_NONDMA);
5142 		goto out;
5143 	}
5144 
5145 err_unroll:
5146 	LIST_FOR_EACH_ENTRY_SAFE(entry, tmp, &rm->rg_list, ice_recp_grp_entry,
5147 				 l_entry) {
5148 		LIST_DEL(&entry->l_entry);
5149 		ice_free(hw, entry);
5150 	}
5151 
5152 out:
5153 	return status;
5154 }
5155 
5156 /**
5157  * ice_get_fv - get field vectors/extraction sequences for spec. lookup types
5158  * @hw: pointer to hardware structure
5159  * @lkups: lookup elements or match criteria for the advanced recipe, one
5160  *	   structure per protocol header
5161  * @lkups_cnt: number of protocols
5162  * @fv_list: pointer to a list that holds the returned field vectors
5163  */
5164 static enum ice_status
5165 ice_get_fv(struct ice_hw *hw, struct ice_adv_lkup_elem *lkups, u16 lkups_cnt,
5166 	   struct LIST_HEAD_TYPE *fv_list)
5167 {
5168 	enum ice_status status;
5169 	u16 *prot_ids;
5170 	u16 i;
5171 
5172 	prot_ids = (u16 *)ice_calloc(hw, lkups_cnt, sizeof(*prot_ids));
5173 	if (!prot_ids)
5174 		return ICE_ERR_NO_MEMORY;
5175 
5176 	for (i = 0; i < lkups_cnt; i++)
5177 		if (!ice_prot_type_to_id(lkups[i].type, &prot_ids[i])) {
5178 			status = ICE_ERR_CFG;
5179 			goto free_mem;
5180 		}
5181 
5182 	/* Find field vectors that include all specified protocol types */
5183 	status = ice_get_sw_fv_list(hw, prot_ids, lkups_cnt, fv_list);
5184 
5185 free_mem:
5186 	ice_free(hw, prot_ids);
5187 	return status;
5188 }
5189 
5190 /**
5191  * ice_add_adv_recipe - Add an advanced recipe that is not part of the default
5192  * @hw: pointer to hardware structure
5193  * @lkups: lookup elements or match criteria for the advanced recipe, one
5194  *  structure per protocol header
5195  * @lkups_cnt: number of protocols
5196  * @rinfo: other information regarding the rule e.g. priority and action info
5197  * @rid: return the recipe ID of the recipe created
5198  */
5199 static enum ice_status
5200 ice_add_adv_recipe(struct ice_hw *hw, struct ice_adv_lkup_elem *lkups,
5201 		   u16 lkups_cnt, struct ice_adv_rule_info *rinfo, u16 *rid)
5202 {
5203 	struct ice_prot_lkup_ext *lkup_exts;
5204 	struct ice_recp_grp_entry *r_entry;
5205 	struct ice_sw_fv_list_entry *fvit;
5206 	struct ice_recp_grp_entry *r_tmp;
5207 	struct ice_sw_fv_list_entry *tmp;
5208 	enum ice_status status = ICE_SUCCESS;
5209 	struct ice_sw_recipe *rm;
5210 	bool match_tun = false;
5211 	u8 i;
5212 
5213 	if (!lkups_cnt)
5214 		return ICE_ERR_PARAM;
5215 
5216 	lkup_exts = (struct ice_prot_lkup_ext *)
5217 		ice_malloc(hw, sizeof(*lkup_exts));
5218 	if (!lkup_exts)
5219 		return ICE_ERR_NO_MEMORY;
5220 
5221 	/* Determine the number of words to be matched and if it exceeds a
5222 	 * recipe's restrictions
5223 	 */
5224 	for (i = 0; i < lkups_cnt; i++) {
5225 		u16 count;
5226 
5227 		if (lkups[i].type >= ICE_PROTOCOL_LAST) {
5228 			status = ICE_ERR_CFG;
5229 			goto err_free_lkup_exts;
5230 		}
5231 
5232 		count = ice_fill_valid_words(&lkups[i], lkup_exts);
5233 		if (!count) {
5234 			status = ICE_ERR_CFG;
5235 			goto err_free_lkup_exts;
5236 		}
5237 	}
5238 
5239 	*rid = ice_find_recp(hw, lkup_exts);
5240 	if (*rid < ICE_MAX_NUM_RECIPES)
5241 		/* Success if found a recipe that match the existing criteria */
5242 		goto err_free_lkup_exts;
5243 
5244 	/* Recipe we need does not exist, add a recipe */
5245 
5246 	rm = (struct ice_sw_recipe *)ice_malloc(hw, sizeof(*rm));
5247 	if (!rm) {
5248 		status = ICE_ERR_NO_MEMORY;
5249 		goto err_free_lkup_exts;
5250 	}
5251 
5252 	/* Get field vectors that contain fields extracted from all the protocol
5253 	 * headers being programmed.
5254 	 */
5255 	INIT_LIST_HEAD(&rm->fv_list);
5256 	INIT_LIST_HEAD(&rm->rg_list);
5257 
5258 	status = ice_get_fv(hw, lkups, lkups_cnt, &rm->fv_list);
5259 	if (status)
5260 		goto err_unroll;
5261 
5262 	/* Group match words into recipes using preferred recipe grouping
5263 	 * criteria.
5264 	 */
5265 	status = ice_create_recipe_group(hw, rm, lkup_exts);
5266 	if (status)
5267 		goto err_unroll;
5268 
5269 	/* There is only profile for UDP tunnels. So, it is necessary to use a
5270 	 * metadata ID flag to differentiate different tunnel types. A separate
5271 	 * recipe needs to be used for the metadata.
5272 	 */
5273 	if ((rinfo->tun_type == ICE_SW_TUN_VXLAN_GPE ||
5274 	     rinfo->tun_type == ICE_SW_TUN_GENEVE ||
5275 	     rinfo->tun_type == ICE_SW_TUN_VXLAN) && rm->n_grp_count > 1)
5276 		match_tun = true;
5277 
5278 	/* set the recipe priority if specified */
5279 	rm->priority = rinfo->priority ? rinfo->priority : 0;
5280 
5281 	/* Find offsets from the field vector. Pick the first one for all the
5282 	 * recipes.
5283 	 */
5284 	ice_fill_fv_word_index(hw, &rm->fv_list, &rm->rg_list);
5285 	status = ice_add_sw_recipe(hw, rm, match_tun);
5286 	if (status)
5287 		goto err_unroll;
5288 
5289 	/* Associate all the recipes created with all the profiles in the
5290 	 * common field vector.
5291 	 */
5292 	LIST_FOR_EACH_ENTRY(fvit, &rm->fv_list, ice_sw_fv_list_entry,
5293 			    list_entry) {
5294 		ice_declare_bitmap(r_bitmap, ICE_MAX_NUM_RECIPES);
5295 
5296 		status = ice_aq_get_recipe_to_profile(hw, fvit->profile_id,
5297 						      (u8 *)r_bitmap, NULL);
5298 		if (status)
5299 			goto err_unroll;
5300 
5301 		ice_or_bitmap(rm->r_bitmap, r_bitmap, rm->r_bitmap,
5302 			      ICE_MAX_NUM_RECIPES);
5303 		status = ice_acquire_change_lock(hw, ICE_RES_WRITE);
5304 		if (status)
5305 			goto err_unroll;
5306 
5307 		status = ice_aq_map_recipe_to_profile(hw, fvit->profile_id,
5308 						      (u8 *)rm->r_bitmap,
5309 						      NULL);
5310 		ice_release_change_lock(hw);
5311 
5312 		if (status)
5313 			goto err_unroll;
5314 	}
5315 
5316 	*rid = rm->root_rid;
5317 	ice_memcpy(&hw->switch_info->recp_list[*rid].lkup_exts,
5318 		   lkup_exts, sizeof(*lkup_exts), ICE_NONDMA_TO_NONDMA);
5319 err_unroll:
5320 	LIST_FOR_EACH_ENTRY_SAFE(r_entry, r_tmp, &rm->rg_list,
5321 				 ice_recp_grp_entry, l_entry) {
5322 		LIST_DEL(&r_entry->l_entry);
5323 		ice_free(hw, r_entry);
5324 	}
5325 
5326 	LIST_FOR_EACH_ENTRY_SAFE(fvit, tmp, &rm->fv_list, ice_sw_fv_list_entry,
5327 				 list_entry) {
5328 		LIST_DEL(&fvit->list_entry);
5329 		ice_free(hw, fvit);
5330 	}
5331 
5332 	if (rm->root_buf)
5333 		ice_free(hw, rm->root_buf);
5334 
5335 	ice_free(hw, rm);
5336 
5337 err_free_lkup_exts:
5338 	ice_free(hw, lkup_exts);
5339 
5340 	return status;
5341 }
5342 
5343 /**
5344  * ice_find_dummy_packet - find dummy packet by tunnel type
5345  *
5346  * @lkups: lookup elements or match criteria for the advanced recipe, one
5347  *	   structure per protocol header
5348  * @lkups_cnt: number of protocols
5349  * @tun_type: tunnel type from the match criteria
5350  * @pkt: dummy packet to fill according to filter match criteria
5351  * @pkt_len: packet length of dummy packet
5352  * @offsets: pointer to receive the pointer to the offsets for the packet
5353  */
5354 static void
5355 ice_find_dummy_packet(struct ice_adv_lkup_elem *lkups, u16 lkups_cnt,
5356 		      enum ice_sw_tunnel_type tun_type, const u8 **pkt,
5357 		      u16 *pkt_len,
5358 		      const struct ice_dummy_pkt_offsets **offsets)
5359 {
5360 	bool tcp = false, udp = false, ipv6 = false;
5361 	u16 i;
5362 
5363 	for (i = 0; i < lkups_cnt; i++) {
5364 		if (lkups[i].type == ICE_UDP_ILOS)
5365 			udp = true;
5366 		else if (lkups[i].type == ICE_TCP_IL)
5367 			tcp = true;
5368 		else if (lkups[i].type == ICE_IPV6_OFOS)
5369 			ipv6 = true;
5370 	}
5371 
5372 	if (tun_type == ICE_SW_TUN_NVGRE || tun_type == ICE_ALL_TUNNELS) {
5373 		*pkt = dummy_gre_packet;
5374 		*pkt_len = sizeof(dummy_gre_packet);
5375 		*offsets = dummy_gre_packet_offsets;
5376 		return;
5377 	}
5378 
5379 	if (tun_type == ICE_SW_TUN_VXLAN || tun_type == ICE_SW_TUN_GENEVE ||
5380 	    tun_type == ICE_SW_TUN_VXLAN_GPE || tun_type == ICE_SW_TUN_UDP) {
5381 		if (tcp) {
5382 			*pkt = dummy_udp_tun_tcp_packet;
5383 			*pkt_len = sizeof(dummy_udp_tun_tcp_packet);
5384 			*offsets = dummy_udp_tun_tcp_packet_offsets;
5385 			return;
5386 		}
5387 
5388 		*pkt = dummy_udp_tun_udp_packet;
5389 		*pkt_len = sizeof(dummy_udp_tun_udp_packet);
5390 		*offsets = dummy_udp_tun_udp_packet_offsets;
5391 		return;
5392 	}
5393 
5394 	if (udp && !ipv6) {
5395 		*pkt = dummy_udp_packet;
5396 		*pkt_len = sizeof(dummy_udp_packet);
5397 		*offsets = dummy_udp_packet_offsets;
5398 		return;
5399 	} else if (udp && ipv6) {
5400 		*pkt = dummy_udp_ipv6_packet;
5401 		*pkt_len = sizeof(dummy_udp_ipv6_packet);
5402 		*offsets = dummy_udp_ipv6_packet_offsets;
5403 		return;
5404 	} else if ((tcp && ipv6) || ipv6) {
5405 		*pkt = dummy_tcp_ipv6_packet;
5406 		*pkt_len = sizeof(dummy_tcp_ipv6_packet);
5407 		*offsets = dummy_tcp_ipv6_packet_offsets;
5408 		return;
5409 	}
5410 
5411 	*pkt = dummy_tcp_packet;
5412 	*pkt_len = sizeof(dummy_tcp_packet);
5413 	*offsets = dummy_tcp_packet_offsets;
5414 }
5415 
5416 /**
5417  * ice_fill_adv_dummy_packet - fill a dummy packet with given match criteria
5418  *
5419  * @lkups: lookup elements or match criteria for the advanced recipe, one
5420  *	   structure per protocol header
5421  * @lkups_cnt: number of protocols
5422  * @s_rule: stores rule information from the match criteria
5423  * @dummy_pkt: dummy packet to fill according to filter match criteria
5424  * @pkt_len: packet length of dummy packet
5425  * @offsets: offset info for the dummy packet
5426  */
5427 static enum ice_status
5428 ice_fill_adv_dummy_packet(struct ice_adv_lkup_elem *lkups, u16 lkups_cnt,
5429 			  struct ice_aqc_sw_rules_elem *s_rule,
5430 			  const u8 *dummy_pkt, u16 pkt_len,
5431 			  const struct ice_dummy_pkt_offsets *offsets)
5432 {
5433 	u8 *pkt;
5434 	u16 i;
5435 
5436 	/* Start with a packet with a pre-defined/dummy content. Then, fill
5437 	 * in the header values to be looked up or matched.
5438 	 */
5439 	pkt = s_rule->pdata.lkup_tx_rx.hdr;
5440 
5441 	ice_memcpy(pkt, dummy_pkt, pkt_len, ICE_NONDMA_TO_NONDMA);
5442 
5443 	for (i = 0; i < lkups_cnt; i++) {
5444 		enum ice_protocol_type type;
5445 		u16 offset = 0, len = 0, j;
5446 		bool found = false;
5447 
5448 		/* find the start of this layer; it should be found since this
5449 		 * was already checked when search for the dummy packet
5450 		 */
5451 		type = lkups[i].type;
5452 		for (j = 0; offsets[j].type != ICE_PROTOCOL_LAST; j++) {
5453 			if (type == offsets[j].type) {
5454 				offset = offsets[j].offset;
5455 				found = true;
5456 				break;
5457 			}
5458 		}
5459 		/* this should never happen in a correct calling sequence */
5460 		if (!found)
5461 			return ICE_ERR_PARAM;
5462 
5463 		switch (lkups[i].type) {
5464 		case ICE_MAC_OFOS:
5465 		case ICE_MAC_IL:
5466 			len = sizeof(struct ice_ether_hdr);
5467 			break;
5468 		case ICE_ETYPE_OL:
5469 			len = sizeof(struct ice_ethtype_hdr);
5470 			break;
5471 		case ICE_IPV4_OFOS:
5472 		case ICE_IPV4_IL:
5473 			len = sizeof(struct ice_ipv4_hdr);
5474 			break;
5475 		case ICE_IPV6_OFOS:
5476 		case ICE_IPV6_IL:
5477 			len = sizeof(struct ice_ipv6_hdr);
5478 			break;
5479 		case ICE_TCP_IL:
5480 		case ICE_UDP_OF:
5481 		case ICE_UDP_ILOS:
5482 			len = sizeof(struct ice_l4_hdr);
5483 			break;
5484 		case ICE_SCTP_IL:
5485 			len = sizeof(struct ice_sctp_hdr);
5486 			break;
5487 		case ICE_NVGRE:
5488 			len = sizeof(struct ice_nvgre);
5489 			break;
5490 		case ICE_VXLAN:
5491 		case ICE_GENEVE:
5492 		case ICE_VXLAN_GPE:
5493 			len = sizeof(struct ice_udp_tnl_hdr);
5494 			break;
5495 		default:
5496 			return ICE_ERR_PARAM;
5497 		}
5498 
5499 		/* the length should be a word multiple */
5500 		if (len % ICE_BYTES_PER_WORD)
5501 			return ICE_ERR_CFG;
5502 
5503 		/* We have the offset to the header start, the length, the
5504 		 * caller's header values and mask. Use this information to
5505 		 * copy the data into the dummy packet appropriately based on
5506 		 * the mask. Note that we need to only write the bits as
5507 		 * indicated by the mask to make sure we don't improperly write
5508 		 * over any significant packet data.
5509 		 */
5510 		for (j = 0; j < len / sizeof(u16); j++)
5511 			if (((u16 *)&lkups[i].m_u)[j])
5512 				((u16 *)(pkt + offset))[j] =
5513 					(((u16 *)(pkt + offset))[j] &
5514 					 ~((u16 *)&lkups[i].m_u)[j]) |
5515 					(((u16 *)&lkups[i].h_u)[j] &
5516 					 ((u16 *)&lkups[i].m_u)[j]);
5517 	}
5518 
5519 	s_rule->pdata.lkup_tx_rx.hdr_len = CPU_TO_LE16(pkt_len);
5520 
5521 	return ICE_SUCCESS;
5522 }
5523 
5524 /**
5525  * ice_find_adv_rule_entry - Search a rule entry
5526  * @hw: pointer to the hardware structure
5527  * @lkups: lookup elements or match criteria for the advanced recipe, one
5528  *	   structure per protocol header
5529  * @lkups_cnt: number of protocols
5530  * @recp_id: recipe ID for which we are finding the rule
5531  * @rinfo: other information regarding the rule e.g. priority and action info
5532  *
5533  * Helper function to search for a given advance rule entry
5534  * Returns pointer to entry storing the rule if found
5535  */
5536 static struct ice_adv_fltr_mgmt_list_entry *
5537 ice_find_adv_rule_entry(struct ice_hw *hw, struct ice_adv_lkup_elem *lkups,
5538 			u16 lkups_cnt, u8 recp_id,
5539 			struct ice_adv_rule_info *rinfo)
5540 {
5541 	struct ice_adv_fltr_mgmt_list_entry *list_itr;
5542 	struct ice_switch_info *sw = hw->switch_info;
5543 	int i;
5544 
5545 	LIST_FOR_EACH_ENTRY(list_itr, &sw->recp_list[recp_id].filt_rules,
5546 			    ice_adv_fltr_mgmt_list_entry, list_entry) {
5547 		bool lkups_matched = true;
5548 
5549 		if (lkups_cnt != list_itr->lkups_cnt)
5550 			continue;
5551 		for (i = 0; i < list_itr->lkups_cnt; i++)
5552 			if (memcmp(&list_itr->lkups[i], &lkups[i],
5553 				   sizeof(*lkups))) {
5554 				lkups_matched = false;
5555 				break;
5556 			}
5557 		if (rinfo->sw_act.flag == list_itr->rule_info.sw_act.flag &&
5558 		    rinfo->tun_type == list_itr->rule_info.tun_type &&
5559 		    lkups_matched)
5560 			return list_itr;
5561 	}
5562 	return NULL;
5563 }
5564 
5565 /**
5566  * ice_adv_add_update_vsi_list
5567  * @hw: pointer to the hardware structure
5568  * @m_entry: pointer to current adv filter management list entry
5569  * @cur_fltr: filter information from the book keeping entry
5570  * @new_fltr: filter information with the new VSI to be added
5571  *
5572  * Call AQ command to add or update previously created VSI list with new VSI.
5573  *
5574  * Helper function to do book keeping associated with adding filter information
5575  * The algorithm to do the booking keeping is described below :
5576  * When a VSI needs to subscribe to a given advanced filter
5577  *	if only one VSI has been added till now
5578  *		Allocate a new VSI list and add two VSIs
5579  *		to this list using switch rule command
5580  *		Update the previously created switch rule with the
5581  *		newly created VSI list ID
5582  *	if a VSI list was previously created
5583  *		Add the new VSI to the previously created VSI list set
5584  *		using the update switch rule command
5585  */
5586 static enum ice_status
5587 ice_adv_add_update_vsi_list(struct ice_hw *hw,
5588 			    struct ice_adv_fltr_mgmt_list_entry *m_entry,
5589 			    struct ice_adv_rule_info *cur_fltr,
5590 			    struct ice_adv_rule_info *new_fltr)
5591 {
5592 	enum ice_status status;
5593 	u16 vsi_list_id = 0;
5594 
5595 	if (cur_fltr->sw_act.fltr_act == ICE_FWD_TO_Q ||
5596 	    cur_fltr->sw_act.fltr_act == ICE_FWD_TO_QGRP)
5597 		return ICE_ERR_NOT_IMPL;
5598 
5599 	if (cur_fltr->sw_act.fltr_act == ICE_DROP_PACKET &&
5600 	    new_fltr->sw_act.fltr_act == ICE_DROP_PACKET)
5601 		return ICE_ERR_ALREADY_EXISTS;
5602 
5603 	if ((new_fltr->sw_act.fltr_act == ICE_FWD_TO_Q ||
5604 	     new_fltr->sw_act.fltr_act == ICE_FWD_TO_QGRP) &&
5605 	    (cur_fltr->sw_act.fltr_act == ICE_FWD_TO_VSI ||
5606 	     cur_fltr->sw_act.fltr_act == ICE_FWD_TO_VSI_LIST))
5607 		return ICE_ERR_NOT_IMPL;
5608 
5609 	if (m_entry->vsi_count < 2 && !m_entry->vsi_list_info) {
5610 		 /* Only one entry existed in the mapping and it was not already
5611 		  * a part of a VSI list. So, create a VSI list with the old and
5612 		  * new VSIs.
5613 		  */
5614 		struct ice_fltr_info tmp_fltr;
5615 		u16 vsi_handle_arr[2];
5616 
5617 		/* A rule already exists with the new VSI being added */
5618 		if (cur_fltr->sw_act.fwd_id.hw_vsi_id ==
5619 		    new_fltr->sw_act.fwd_id.hw_vsi_id)
5620 			return ICE_ERR_ALREADY_EXISTS;
5621 
5622 		vsi_handle_arr[0] = cur_fltr->sw_act.vsi_handle;
5623 		vsi_handle_arr[1] = new_fltr->sw_act.vsi_handle;
5624 		status = ice_create_vsi_list_rule(hw, &vsi_handle_arr[0], 2,
5625 						  &vsi_list_id,
5626 						  ICE_SW_LKUP_LAST);
5627 		if (status)
5628 			return status;
5629 
5630 		tmp_fltr.fltr_rule_id = cur_fltr->fltr_rule_id;
5631 		tmp_fltr.fltr_act = ICE_FWD_TO_VSI_LIST;
5632 		tmp_fltr.fwd_id.vsi_list_id = vsi_list_id;
5633 		/* Update the previous switch rule of "forward to VSI" to
5634 		 * "fwd to VSI list"
5635 		 */
5636 		status = ice_update_pkt_fwd_rule(hw, &tmp_fltr);
5637 		if (status)
5638 			return status;
5639 
5640 		cur_fltr->sw_act.fwd_id.vsi_list_id = vsi_list_id;
5641 		cur_fltr->sw_act.fltr_act = ICE_FWD_TO_VSI_LIST;
5642 		m_entry->vsi_list_info =
5643 			ice_create_vsi_list_map(hw, &vsi_handle_arr[0], 2,
5644 						vsi_list_id);
5645 	} else {
5646 		u16 vsi_handle = new_fltr->sw_act.vsi_handle;
5647 
5648 		if (!m_entry->vsi_list_info)
5649 			return ICE_ERR_CFG;
5650 
5651 		/* A rule already exists with the new VSI being added */
5652 		if (ice_is_bit_set(m_entry->vsi_list_info->vsi_map, vsi_handle))
5653 			return ICE_SUCCESS;
5654 
5655 		/* Update the previously created VSI list set with
5656 		 * the new VSI ID passed in
5657 		 */
5658 		vsi_list_id = cur_fltr->sw_act.fwd_id.vsi_list_id;
5659 
5660 		status = ice_update_vsi_list_rule(hw, &vsi_handle, 1,
5661 						  vsi_list_id, false,
5662 						  ice_aqc_opc_update_sw_rules,
5663 						  ICE_SW_LKUP_LAST);
5664 		/* update VSI list mapping info with new VSI ID */
5665 		if (!status)
5666 			ice_set_bit(vsi_handle,
5667 				    m_entry->vsi_list_info->vsi_map);
5668 	}
5669 	if (!status)
5670 		m_entry->vsi_count++;
5671 	return status;
5672 }
5673 
5674 /**
5675  * ice_add_adv_rule - helper function to create an advanced switch rule
5676  * @hw: pointer to the hardware structure
5677  * @lkups: information on the words that needs to be looked up. All words
5678  * together makes one recipe
5679  * @lkups_cnt: num of entries in the lkups array
5680  * @rinfo: other information related to the rule that needs to be programmed
5681  * @added_entry: this will return recipe_id, rule_id and vsi_handle. should be
5682  *               ignored is case of error.
5683  *
5684  * This function can program only 1 rule at a time. The lkups is used to
5685  * describe the all the words that forms the "lookup" portion of the recipe.
5686  * These words can span multiple protocols. Callers to this function need to
5687  * pass in a list of protocol headers with lookup information along and mask
5688  * that determines which words are valid from the given protocol header.
5689  * rinfo describes other information related to this rule such as forwarding
5690  * IDs, priority of this rule, etc.
5691  */
5692 enum ice_status
5693 ice_add_adv_rule(struct ice_hw *hw, struct ice_adv_lkup_elem *lkups,
5694 		 u16 lkups_cnt, struct ice_adv_rule_info *rinfo,
5695 		 struct ice_rule_query_data *added_entry)
5696 {
5697 	struct ice_adv_fltr_mgmt_list_entry *m_entry, *adv_fltr = NULL;
5698 	u16 rid = 0, i, pkt_len, rule_buf_sz, vsi_handle;
5699 	const struct ice_dummy_pkt_offsets *pkt_offsets;
5700 	struct ice_aqc_sw_rules_elem *s_rule = NULL;
5701 	struct LIST_HEAD_TYPE *rule_head;
5702 	struct ice_switch_info *sw;
5703 	enum ice_status status;
5704 	const u8 *pkt = NULL;
5705 	bool found = false;
5706 	u32 act = 0;
5707 	u8 q_rgn;
5708 
5709 	if (!lkups_cnt)
5710 		return ICE_ERR_PARAM;
5711 
5712 	for (i = 0; i < lkups_cnt; i++) {
5713 		u16 j, *ptr;
5714 
5715 		/* Validate match masks to make sure that there is something
5716 		 * to match.
5717 		 */
5718 		ptr = (u16 *)&lkups[i].m_u;
5719 		for (j = 0; j < sizeof(lkups->m_u) / sizeof(u16); j++)
5720 			if (ptr[j] != 0) {
5721 				found = true;
5722 				break;
5723 			}
5724 	}
5725 	if (!found)
5726 		return ICE_ERR_PARAM;
5727 
5728 	/* make sure that we can locate a dummy packet */
5729 	ice_find_dummy_packet(lkups, lkups_cnt, rinfo->tun_type, &pkt, &pkt_len,
5730 			      &pkt_offsets);
5731 	if (!pkt) {
5732 		status = ICE_ERR_PARAM;
5733 		goto err_ice_add_adv_rule;
5734 	}
5735 
5736 	if (!(rinfo->sw_act.fltr_act == ICE_FWD_TO_VSI ||
5737 	      rinfo->sw_act.fltr_act == ICE_FWD_TO_Q ||
5738 	      rinfo->sw_act.fltr_act == ICE_FWD_TO_QGRP ||
5739 	      rinfo->sw_act.fltr_act == ICE_DROP_PACKET))
5740 		return ICE_ERR_CFG;
5741 
5742 	vsi_handle = rinfo->sw_act.vsi_handle;
5743 	if (!ice_is_vsi_valid(hw, vsi_handle))
5744 		return ICE_ERR_PARAM;
5745 
5746 	if (rinfo->sw_act.fltr_act == ICE_FWD_TO_VSI)
5747 		rinfo->sw_act.fwd_id.hw_vsi_id =
5748 			ice_get_hw_vsi_num(hw, vsi_handle);
5749 	if (rinfo->sw_act.flag & ICE_FLTR_TX)
5750 		rinfo->sw_act.src = ice_get_hw_vsi_num(hw, vsi_handle);
5751 
5752 	status = ice_add_adv_recipe(hw, lkups, lkups_cnt, rinfo, &rid);
5753 	if (status)
5754 		return status;
5755 	m_entry = ice_find_adv_rule_entry(hw, lkups, lkups_cnt, rid, rinfo);
5756 	if (m_entry) {
5757 		/* we have to add VSI to VSI_LIST and increment vsi_count.
5758 		 * Also Update VSI list so that we can change forwarding rule
5759 		 * if the rule already exists, we will check if it exists with
5760 		 * same vsi_id, if not then add it to the VSI list if it already
5761 		 * exists if not then create a VSI list and add the existing VSI
5762 		 * ID and the new VSI ID to the list
5763 		 * We will add that VSI to the list
5764 		 */
5765 		status = ice_adv_add_update_vsi_list(hw, m_entry,
5766 						     &m_entry->rule_info,
5767 						     rinfo);
5768 		if (added_entry) {
5769 			added_entry->rid = rid;
5770 			added_entry->rule_id = m_entry->rule_info.fltr_rule_id;
5771 			added_entry->vsi_handle = rinfo->sw_act.vsi_handle;
5772 		}
5773 		return status;
5774 	}
5775 	rule_buf_sz = ICE_SW_RULE_RX_TX_NO_HDR_SIZE + pkt_len;
5776 	s_rule = (struct ice_aqc_sw_rules_elem *)ice_malloc(hw, rule_buf_sz);
5777 	if (!s_rule)
5778 		return ICE_ERR_NO_MEMORY;
5779 	act |= ICE_SINGLE_ACT_LB_ENABLE | ICE_SINGLE_ACT_LAN_ENABLE;
5780 	switch (rinfo->sw_act.fltr_act) {
5781 	case ICE_FWD_TO_VSI:
5782 		act |= (rinfo->sw_act.fwd_id.hw_vsi_id <<
5783 			ICE_SINGLE_ACT_VSI_ID_S) & ICE_SINGLE_ACT_VSI_ID_M;
5784 		act |= ICE_SINGLE_ACT_VSI_FORWARDING | ICE_SINGLE_ACT_VALID_BIT;
5785 		break;
5786 	case ICE_FWD_TO_Q:
5787 		act |= ICE_SINGLE_ACT_TO_Q;
5788 		act |= (rinfo->sw_act.fwd_id.q_id << ICE_SINGLE_ACT_Q_INDEX_S) &
5789 		       ICE_SINGLE_ACT_Q_INDEX_M;
5790 		break;
5791 	case ICE_FWD_TO_QGRP:
5792 		q_rgn = rinfo->sw_act.qgrp_size > 0 ?
5793 			(u8)ice_ilog2(rinfo->sw_act.qgrp_size) : 0;
5794 		act |= ICE_SINGLE_ACT_TO_Q;
5795 		act |= (rinfo->sw_act.fwd_id.q_id << ICE_SINGLE_ACT_Q_INDEX_S) &
5796 		       ICE_SINGLE_ACT_Q_INDEX_M;
5797 		act |= (q_rgn << ICE_SINGLE_ACT_Q_REGION_S) &
5798 		       ICE_SINGLE_ACT_Q_REGION_M;
5799 		break;
5800 	case ICE_DROP_PACKET:
5801 		act |= ICE_SINGLE_ACT_VSI_FORWARDING | ICE_SINGLE_ACT_DROP |
5802 		       ICE_SINGLE_ACT_VALID_BIT;
5803 		break;
5804 	default:
5805 		status = ICE_ERR_CFG;
5806 		goto err_ice_add_adv_rule;
5807 	}
5808 
5809 	/* set the rule LOOKUP type based on caller specified 'RX'
5810 	 * instead of hardcoding it to be either LOOKUP_TX/RX
5811 	 *
5812 	 * for 'RX' set the source to be the port number
5813 	 * for 'TX' set the source to be the source HW VSI number (determined
5814 	 * by caller)
5815 	 */
5816 	if (rinfo->rx) {
5817 		s_rule->type = CPU_TO_LE16(ICE_AQC_SW_RULES_T_LKUP_RX);
5818 		s_rule->pdata.lkup_tx_rx.src =
5819 			CPU_TO_LE16(hw->port_info->lport);
5820 	} else {
5821 		s_rule->type = CPU_TO_LE16(ICE_AQC_SW_RULES_T_LKUP_TX);
5822 		s_rule->pdata.lkup_tx_rx.src = CPU_TO_LE16(rinfo->sw_act.src);
5823 	}
5824 
5825 	s_rule->pdata.lkup_tx_rx.recipe_id = CPU_TO_LE16(rid);
5826 	s_rule->pdata.lkup_tx_rx.act = CPU_TO_LE32(act);
5827 
5828 	ice_fill_adv_dummy_packet(lkups, lkups_cnt, s_rule, pkt, pkt_len,
5829 				  pkt_offsets);
5830 
5831 	status = ice_aq_sw_rules(hw, (struct ice_aqc_sw_rules *)s_rule,
5832 				 rule_buf_sz, 1, ice_aqc_opc_add_sw_rules,
5833 				 NULL);
5834 	if (status)
5835 		goto err_ice_add_adv_rule;
5836 	adv_fltr = (struct ice_adv_fltr_mgmt_list_entry *)
5837 		ice_malloc(hw, sizeof(struct ice_adv_fltr_mgmt_list_entry));
5838 	if (!adv_fltr) {
5839 		status = ICE_ERR_NO_MEMORY;
5840 		goto err_ice_add_adv_rule;
5841 	}
5842 
5843 	adv_fltr->lkups = (struct ice_adv_lkup_elem *)
5844 		ice_memdup(hw, lkups, lkups_cnt * sizeof(*lkups),
5845 			   ICE_NONDMA_TO_NONDMA);
5846 	if (!adv_fltr->lkups) {
5847 		status = ICE_ERR_NO_MEMORY;
5848 		goto err_ice_add_adv_rule;
5849 	}
5850 
5851 	adv_fltr->lkups_cnt = lkups_cnt;
5852 	adv_fltr->rule_info = *rinfo;
5853 	adv_fltr->rule_info.fltr_rule_id =
5854 		LE16_TO_CPU(s_rule->pdata.lkup_tx_rx.index);
5855 	sw = hw->switch_info;
5856 	sw->recp_list[rid].adv_rule = true;
5857 	rule_head = &sw->recp_list[rid].filt_rules;
5858 
5859 	if (rinfo->sw_act.fltr_act == ICE_FWD_TO_VSI) {
5860 		struct ice_fltr_info tmp_fltr;
5861 
5862 		tmp_fltr.fltr_rule_id =
5863 			LE16_TO_CPU(s_rule->pdata.lkup_tx_rx.index);
5864 		tmp_fltr.fltr_act = ICE_FWD_TO_VSI;
5865 		tmp_fltr.fwd_id.hw_vsi_id =
5866 			ice_get_hw_vsi_num(hw, vsi_handle);
5867 		tmp_fltr.vsi_handle = vsi_handle;
5868 		/* Update the previous switch rule of "forward to VSI" to
5869 		 * "fwd to VSI list"
5870 		 */
5871 		status = ice_update_pkt_fwd_rule(hw, &tmp_fltr);
5872 		if (status)
5873 			goto err_ice_add_adv_rule;
5874 		adv_fltr->vsi_count = 1;
5875 	}
5876 
5877 	/* Add rule entry to book keeping list */
5878 	LIST_ADD(&adv_fltr->list_entry, rule_head);
5879 	if (added_entry) {
5880 		added_entry->rid = rid;
5881 		added_entry->rule_id = adv_fltr->rule_info.fltr_rule_id;
5882 		added_entry->vsi_handle = rinfo->sw_act.vsi_handle;
5883 	}
5884 err_ice_add_adv_rule:
5885 	if (status && adv_fltr) {
5886 		ice_free(hw, adv_fltr->lkups);
5887 		ice_free(hw, adv_fltr);
5888 	}
5889 
5890 	ice_free(hw, s_rule);
5891 
5892 	return status;
5893 }
5894 
5895 /**
5896  * ice_adv_rem_update_vsi_list
5897  * @hw: pointer to the hardware structure
5898  * @vsi_handle: VSI handle of the VSI to remove
5899  * @fm_list: filter management entry for which the VSI list management needs to
5900  *	     be done
5901  */
5902 static enum ice_status
5903 ice_adv_rem_update_vsi_list(struct ice_hw *hw, u16 vsi_handle,
5904 			    struct ice_adv_fltr_mgmt_list_entry *fm_list)
5905 {
5906 	struct ice_vsi_list_map_info *vsi_list_info;
5907 	enum ice_sw_lkup_type lkup_type;
5908 	enum ice_status status;
5909 	u16 vsi_list_id;
5910 
5911 	if (fm_list->rule_info.sw_act.fltr_act != ICE_FWD_TO_VSI_LIST ||
5912 	    fm_list->vsi_count == 0)
5913 		return ICE_ERR_PARAM;
5914 
5915 	/* A rule with the VSI being removed does not exist */
5916 	if (!ice_is_bit_set(fm_list->vsi_list_info->vsi_map, vsi_handle))
5917 		return ICE_ERR_DOES_NOT_EXIST;
5918 
5919 	lkup_type = ICE_SW_LKUP_LAST;
5920 	vsi_list_id = fm_list->rule_info.sw_act.fwd_id.vsi_list_id;
5921 	status = ice_update_vsi_list_rule(hw, &vsi_handle, 1, vsi_list_id, true,
5922 					  ice_aqc_opc_update_sw_rules,
5923 					  lkup_type);
5924 	if (status)
5925 		return status;
5926 
5927 	fm_list->vsi_count--;
5928 	ice_clear_bit(vsi_handle, fm_list->vsi_list_info->vsi_map);
5929 	vsi_list_info = fm_list->vsi_list_info;
5930 	if (fm_list->vsi_count == 1) {
5931 		struct ice_fltr_info tmp_fltr;
5932 		u16 rem_vsi_handle;
5933 
5934 		rem_vsi_handle = ice_find_first_bit(vsi_list_info->vsi_map,
5935 						    ICE_MAX_VSI);
5936 		if (!ice_is_vsi_valid(hw, rem_vsi_handle))
5937 			return ICE_ERR_OUT_OF_RANGE;
5938 
5939 		/* Make sure VSI list is empty before removing it below */
5940 		status = ice_update_vsi_list_rule(hw, &rem_vsi_handle, 1,
5941 						  vsi_list_id, true,
5942 						  ice_aqc_opc_update_sw_rules,
5943 						  lkup_type);
5944 		if (status)
5945 			return status;
5946 		tmp_fltr.fltr_rule_id = fm_list->rule_info.fltr_rule_id;
5947 		fm_list->rule_info.sw_act.fltr_act = ICE_FWD_TO_VSI;
5948 		tmp_fltr.fltr_act = ICE_FWD_TO_VSI;
5949 		tmp_fltr.fwd_id.hw_vsi_id =
5950 			ice_get_hw_vsi_num(hw, rem_vsi_handle);
5951 		fm_list->rule_info.sw_act.fwd_id.hw_vsi_id =
5952 			ice_get_hw_vsi_num(hw, rem_vsi_handle);
5953 
5954 		/* Update the previous switch rule of "MAC forward to VSI" to
5955 		 * "MAC fwd to VSI list"
5956 		 */
5957 		status = ice_update_pkt_fwd_rule(hw, &tmp_fltr);
5958 		if (status) {
5959 			ice_debug(hw, ICE_DBG_SW,
5960 				  "Failed to update pkt fwd rule to FWD_TO_VSI on HW VSI %d, error %d\n",
5961 				  tmp_fltr.fwd_id.hw_vsi_id, status);
5962 			return status;
5963 		}
5964 	}
5965 
5966 	if (fm_list->vsi_count == 1) {
5967 		/* Remove the VSI list since it is no longer used */
5968 		status = ice_remove_vsi_list_rule(hw, vsi_list_id, lkup_type);
5969 		if (status) {
5970 			ice_debug(hw, ICE_DBG_SW,
5971 				  "Failed to remove VSI list %d, error %d\n",
5972 				  vsi_list_id, status);
5973 			return status;
5974 		}
5975 
5976 		LIST_DEL(&vsi_list_info->list_entry);
5977 		ice_free(hw, vsi_list_info);
5978 		fm_list->vsi_list_info = NULL;
5979 	}
5980 
5981 	return status;
5982 }
5983 
5984 /**
5985  * ice_rem_adv_rule - removes existing advanced switch rule
5986  * @hw: pointer to the hardware structure
5987  * @lkups: information on the words that needs to be looked up. All words
5988  *         together makes one recipe
5989  * @lkups_cnt: num of entries in the lkups array
5990  * @rinfo: Its the pointer to the rule information for the rule
5991  *
5992  * This function can be used to remove 1 rule at a time. The lkups is
5993  * used to describe all the words that forms the "lookup" portion of the
5994  * rule. These words can span multiple protocols. Callers to this function
5995  * need to pass in a list of protocol headers with lookup information along
5996  * and mask that determines which words are valid from the given protocol
5997  * header. rinfo describes other information related to this rule such as
5998  * forwarding IDs, priority of this rule, etc.
5999  */
6000 enum ice_status
6001 ice_rem_adv_rule(struct ice_hw *hw, struct ice_adv_lkup_elem *lkups,
6002 		 u16 lkups_cnt, struct ice_adv_rule_info *rinfo)
6003 {
6004 	struct ice_adv_fltr_mgmt_list_entry *list_elem;
6005 	const struct ice_dummy_pkt_offsets *offsets;
6006 	struct ice_prot_lkup_ext lkup_exts;
6007 	u16 rule_buf_sz, pkt_len, i, rid;
6008 	struct ice_lock *rule_lock; /* Lock to protect filter rule list */
6009 	enum ice_status status = ICE_SUCCESS;
6010 	bool remove_rule = false;
6011 	const u8 *pkt = NULL;
6012 	u16 vsi_handle;
6013 
6014 	ice_memset(&lkup_exts, 0, sizeof(lkup_exts), ICE_NONDMA_MEM);
6015 	for (i = 0; i < lkups_cnt; i++) {
6016 		u16 count;
6017 
6018 		if (lkups[i].type >= ICE_PROTOCOL_LAST)
6019 			return ICE_ERR_CFG;
6020 
6021 		count = ice_fill_valid_words(&lkups[i], &lkup_exts);
6022 		if (!count)
6023 			return ICE_ERR_CFG;
6024 	}
6025 	rid = ice_find_recp(hw, &lkup_exts);
6026 	/* If did not find a recipe that match the existing criteria */
6027 	if (rid == ICE_MAX_NUM_RECIPES)
6028 		return ICE_ERR_PARAM;
6029 
6030 	rule_lock = &hw->switch_info->recp_list[rid].filt_rule_lock;
6031 	list_elem = ice_find_adv_rule_entry(hw, lkups, lkups_cnt, rid, rinfo);
6032 	/* the rule is already removed */
6033 	if (!list_elem)
6034 		return ICE_SUCCESS;
6035 	ice_acquire_lock(rule_lock);
6036 	if (list_elem->rule_info.sw_act.fltr_act != ICE_FWD_TO_VSI_LIST) {
6037 		remove_rule = true;
6038 	} else if (list_elem->vsi_count > 1) {
6039 		list_elem->vsi_list_info->ref_cnt--;
6040 		remove_rule = false;
6041 		vsi_handle = rinfo->sw_act.vsi_handle;
6042 		status = ice_adv_rem_update_vsi_list(hw, vsi_handle, list_elem);
6043 	} else {
6044 		vsi_handle = rinfo->sw_act.vsi_handle;
6045 		status = ice_adv_rem_update_vsi_list(hw, vsi_handle, list_elem);
6046 		if (status) {
6047 			ice_release_lock(rule_lock);
6048 			return status;
6049 		}
6050 		if (list_elem->vsi_count == 0)
6051 			remove_rule = true;
6052 	}
6053 	ice_release_lock(rule_lock);
6054 	if (remove_rule) {
6055 		struct ice_aqc_sw_rules_elem *s_rule;
6056 
6057 		ice_find_dummy_packet(lkups, lkups_cnt, rinfo->tun_type, &pkt,
6058 				      &pkt_len, &offsets);
6059 		rule_buf_sz = ICE_SW_RULE_RX_TX_NO_HDR_SIZE + pkt_len;
6060 		s_rule =
6061 			(struct ice_aqc_sw_rules_elem *)ice_malloc(hw,
6062 								   rule_buf_sz);
6063 		if (!s_rule)
6064 			return ICE_ERR_NO_MEMORY;
6065 		s_rule->pdata.lkup_tx_rx.act = 0;
6066 		s_rule->pdata.lkup_tx_rx.index =
6067 			CPU_TO_LE16(list_elem->rule_info.fltr_rule_id);
6068 		s_rule->pdata.lkup_tx_rx.hdr_len = 0;
6069 		status = ice_aq_sw_rules(hw, (struct ice_aqc_sw_rules *)s_rule,
6070 					 rule_buf_sz, 1,
6071 					 ice_aqc_opc_remove_sw_rules, NULL);
6072 		if (status == ICE_SUCCESS) {
6073 			ice_acquire_lock(rule_lock);
6074 			LIST_DEL(&list_elem->list_entry);
6075 			ice_free(hw, list_elem->lkups);
6076 			ice_free(hw, list_elem);
6077 			ice_release_lock(rule_lock);
6078 		}
6079 		ice_free(hw, s_rule);
6080 	}
6081 	return status;
6082 }
6083 
6084 /**
6085  * ice_rem_adv_rule_by_id - removes existing advanced switch rule by ID
6086  * @hw: pointer to the hardware structure
6087  * @remove_entry: data struct which holds rule_id, VSI handle and recipe ID
6088  *
6089  * This function is used to remove 1 rule at a time. The removal is based on
6090  * the remove_entry parameter. This function will remove rule for a given
6091  * vsi_handle with a given rule_id which is passed as parameter in remove_entry
6092  */
6093 enum ice_status
6094 ice_rem_adv_rule_by_id(struct ice_hw *hw,
6095 		       struct ice_rule_query_data *remove_entry)
6096 {
6097 	struct ice_adv_fltr_mgmt_list_entry *list_itr;
6098 	struct LIST_HEAD_TYPE *list_head;
6099 	struct ice_adv_rule_info rinfo;
6100 	struct ice_switch_info *sw;
6101 
6102 	sw = hw->switch_info;
6103 	if (!sw->recp_list[remove_entry->rid].recp_created)
6104 		return ICE_ERR_PARAM;
6105 	list_head = &sw->recp_list[remove_entry->rid].filt_rules;
6106 	LIST_FOR_EACH_ENTRY(list_itr, list_head, ice_adv_fltr_mgmt_list_entry,
6107 			    list_entry) {
6108 		if (list_itr->rule_info.fltr_rule_id ==
6109 		    remove_entry->rule_id) {
6110 			rinfo = list_itr->rule_info;
6111 			rinfo.sw_act.vsi_handle = remove_entry->vsi_handle;
6112 			return ice_rem_adv_rule(hw, list_itr->lkups,
6113 						list_itr->lkups_cnt, &rinfo);
6114 		}
6115 	}
6116 	return ICE_ERR_PARAM;
6117 }
6118 
6119 /**
6120  * ice_rem_adv_for_vsi - removes existing advanced switch rules for a
6121  *                       given VSI handle
6122  * @hw: pointer to the hardware structure
6123  * @vsi_handle: VSI handle for which we are supposed to remove all the rules.
6124  *
6125  * This function is used to remove all the rules for a given VSI and as soon
6126  * as removing a rule fails, it will return immediately with the error code,
6127  * else it will return ICE_SUCCESS
6128  */
6129 enum ice_status
6130 ice_rem_adv_rule_for_vsi(struct ice_hw *hw, u16 vsi_handle)
6131 {
6132 	struct ice_adv_fltr_mgmt_list_entry *list_itr;
6133 	struct ice_vsi_list_map_info *map_info;
6134 	struct LIST_HEAD_TYPE *list_head;
6135 	struct ice_adv_rule_info rinfo;
6136 	struct ice_switch_info *sw;
6137 	enum ice_status status;
6138 	u16 vsi_list_id = 0;
6139 	u8 rid;
6140 
6141 	sw = hw->switch_info;
6142 	for (rid = 0; rid < ICE_MAX_NUM_RECIPES; rid++) {
6143 		if (!sw->recp_list[rid].recp_created)
6144 			continue;
6145 		if (!sw->recp_list[rid].adv_rule)
6146 			continue;
6147 		list_head = &sw->recp_list[rid].filt_rules;
6148 		map_info = NULL;
6149 		LIST_FOR_EACH_ENTRY(list_itr, list_head,
6150 				    ice_adv_fltr_mgmt_list_entry, list_entry) {
6151 			map_info = ice_find_vsi_list_entry(hw, rid, vsi_handle,
6152 							   &vsi_list_id);
6153 			if (!map_info)
6154 				continue;
6155 			rinfo = list_itr->rule_info;
6156 			rinfo.sw_act.vsi_handle = vsi_handle;
6157 			status = ice_rem_adv_rule(hw, list_itr->lkups,
6158 						  list_itr->lkups_cnt, &rinfo);
6159 			if (status)
6160 				return status;
6161 			map_info = NULL;
6162 		}
6163 	}
6164 	return ICE_SUCCESS;
6165 }
6166 
6167 /**
6168  * ice_replay_fltr - Replay all the filters stored by a specific list head
6169  * @hw: pointer to the hardware structure
6170  * @list_head: list for which filters needs to be replayed
6171  * @recp_id: Recipe ID for which rules need to be replayed
6172  */
6173 static enum ice_status
6174 ice_replay_fltr(struct ice_hw *hw, u8 recp_id, struct LIST_HEAD_TYPE *list_head)
6175 {
6176 	struct ice_fltr_mgmt_list_entry *itr;
6177 	struct LIST_HEAD_TYPE l_head;
6178 	enum ice_status status = ICE_SUCCESS;
6179 
6180 	if (LIST_EMPTY(list_head))
6181 		return status;
6182 
6183 	/* Move entries from the given list_head to a temporary l_head so that
6184 	 * they can be replayed. Otherwise when trying to re-add the same
6185 	 * filter, the function will return already exists
6186 	 */
6187 	LIST_REPLACE_INIT(list_head, &l_head);
6188 
6189 	/* Mark the given list_head empty by reinitializing it so filters
6190 	 * could be added again by *handler
6191 	 */
6192 	LIST_FOR_EACH_ENTRY(itr, &l_head, ice_fltr_mgmt_list_entry,
6193 			    list_entry) {
6194 		struct ice_fltr_list_entry f_entry;
6195 
6196 		f_entry.fltr_info = itr->fltr_info;
6197 		if (itr->vsi_count < 2 && recp_id != ICE_SW_LKUP_VLAN) {
6198 			status = ice_add_rule_internal(hw, recp_id, &f_entry);
6199 			if (status != ICE_SUCCESS)
6200 				goto end;
6201 			continue;
6202 		}
6203 
6204 		/* Add a filter per VSI separately */
6205 		while (1) {
6206 			u16 vsi_handle;
6207 
6208 			vsi_handle =
6209 				ice_find_first_bit(itr->vsi_list_info->vsi_map,
6210 						   ICE_MAX_VSI);
6211 			if (!ice_is_vsi_valid(hw, vsi_handle))
6212 				break;
6213 
6214 			ice_clear_bit(vsi_handle, itr->vsi_list_info->vsi_map);
6215 			f_entry.fltr_info.vsi_handle = vsi_handle;
6216 			f_entry.fltr_info.fwd_id.hw_vsi_id =
6217 				ice_get_hw_vsi_num(hw, vsi_handle);
6218 			f_entry.fltr_info.fltr_act = ICE_FWD_TO_VSI;
6219 			if (recp_id == ICE_SW_LKUP_VLAN)
6220 				status = ice_add_vlan_internal(hw, &f_entry);
6221 			else
6222 				status = ice_add_rule_internal(hw, recp_id,
6223 							       &f_entry);
6224 			if (status != ICE_SUCCESS)
6225 				goto end;
6226 		}
6227 	}
6228 end:
6229 	/* Clear the filter management list */
6230 	ice_rem_sw_rule_info(hw, &l_head);
6231 	return status;
6232 }
6233 
6234 /**
6235  * ice_replay_all_fltr - replay all filters stored in bookkeeping lists
6236  * @hw: pointer to the hardware structure
6237  *
6238  * NOTE: This function does not clean up partially added filters on error.
6239  * It is up to caller of the function to issue a reset or fail early.
6240  */
6241 enum ice_status ice_replay_all_fltr(struct ice_hw *hw)
6242 {
6243 	struct ice_switch_info *sw = hw->switch_info;
6244 	enum ice_status status = ICE_SUCCESS;
6245 	u8 i;
6246 
6247 	for (i = 0; i < ICE_MAX_NUM_RECIPES; i++) {
6248 		struct LIST_HEAD_TYPE *head = &sw->recp_list[i].filt_rules;
6249 
6250 		status = ice_replay_fltr(hw, i, head);
6251 		if (status != ICE_SUCCESS)
6252 			return status;
6253 	}
6254 	return status;
6255 }
6256 
6257 /**
6258  * ice_replay_vsi_fltr - Replay filters for requested VSI
6259  * @hw: pointer to the hardware structure
6260  * @vsi_handle: driver VSI handle
6261  * @recp_id: Recipe ID for which rules need to be replayed
6262  * @list_head: list for which filters need to be replayed
6263  *
6264  * Replays the filter of recipe recp_id for a VSI represented via vsi_handle.
6265  * It is required to pass valid VSI handle.
6266  */
6267 static enum ice_status
6268 ice_replay_vsi_fltr(struct ice_hw *hw, u16 vsi_handle, u8 recp_id,
6269 		    struct LIST_HEAD_TYPE *list_head)
6270 {
6271 	struct ice_fltr_mgmt_list_entry *itr;
6272 	enum ice_status status = ICE_SUCCESS;
6273 	u16 hw_vsi_id;
6274 
6275 	if (LIST_EMPTY(list_head))
6276 		return status;
6277 	hw_vsi_id = ice_get_hw_vsi_num(hw, vsi_handle);
6278 
6279 	LIST_FOR_EACH_ENTRY(itr, list_head, ice_fltr_mgmt_list_entry,
6280 			    list_entry) {
6281 		struct ice_fltr_list_entry f_entry;
6282 
6283 		f_entry.fltr_info = itr->fltr_info;
6284 		if (itr->vsi_count < 2 && recp_id != ICE_SW_LKUP_VLAN &&
6285 		    itr->fltr_info.vsi_handle == vsi_handle) {
6286 			/* update the src in case it is VSI num */
6287 			if (f_entry.fltr_info.src_id == ICE_SRC_ID_VSI)
6288 				f_entry.fltr_info.src = hw_vsi_id;
6289 			status = ice_add_rule_internal(hw, recp_id, &f_entry);
6290 			if (status != ICE_SUCCESS)
6291 				goto end;
6292 			continue;
6293 		}
6294 		if (!itr->vsi_list_info ||
6295 		    !ice_is_bit_set(itr->vsi_list_info->vsi_map, vsi_handle))
6296 			continue;
6297 		/* Clearing it so that the logic can add it back */
6298 		ice_clear_bit(vsi_handle, itr->vsi_list_info->vsi_map);
6299 		f_entry.fltr_info.vsi_handle = vsi_handle;
6300 		f_entry.fltr_info.fltr_act = ICE_FWD_TO_VSI;
6301 		/* update the src in case it is VSI num */
6302 		if (f_entry.fltr_info.src_id == ICE_SRC_ID_VSI)
6303 			f_entry.fltr_info.src = hw_vsi_id;
6304 		if (recp_id == ICE_SW_LKUP_VLAN)
6305 			status = ice_add_vlan_internal(hw, &f_entry);
6306 		else
6307 			status = ice_add_rule_internal(hw, recp_id, &f_entry);
6308 		if (status != ICE_SUCCESS)
6309 			goto end;
6310 	}
6311 end:
6312 	return status;
6313 }
6314 
6315 /**
6316  * ice_replay_vsi_adv_rule - Replay advanced rule for requested VSI
6317  * @hw: pointer to the hardware structure
6318  * @vsi_handle: driver VSI handle
6319  * @list_head: list for which filters need to be replayed
6320  *
6321  * Replay the advanced rule for the given VSI.
6322  */
6323 static enum ice_status
6324 ice_replay_vsi_adv_rule(struct ice_hw *hw, u16 vsi_handle,
6325 			struct LIST_HEAD_TYPE *list_head)
6326 {
6327 	struct ice_rule_query_data added_entry = { 0 };
6328 	struct ice_adv_fltr_mgmt_list_entry *adv_fltr;
6329 	enum ice_status status = ICE_SUCCESS;
6330 
6331 	if (LIST_EMPTY(list_head))
6332 		return status;
6333 	LIST_FOR_EACH_ENTRY(adv_fltr, list_head, ice_adv_fltr_mgmt_list_entry,
6334 			    list_entry) {
6335 		struct ice_adv_rule_info *rinfo = &adv_fltr->rule_info;
6336 		u16 lk_cnt = adv_fltr->lkups_cnt;
6337 
6338 		if (vsi_handle != rinfo->sw_act.vsi_handle)
6339 			continue;
6340 		status = ice_add_adv_rule(hw, adv_fltr->lkups, lk_cnt, rinfo,
6341 					  &added_entry);
6342 		if (status)
6343 			break;
6344 	}
6345 	return status;
6346 }
6347 
6348 /**
6349  * ice_replay_vsi_all_fltr - replay all filters stored in bookkeeping lists
6350  * @hw: pointer to the hardware structure
6351  * @vsi_handle: driver VSI handle
6352  *
6353  * Replays filters for requested VSI via vsi_handle.
6354  */
6355 enum ice_status ice_replay_vsi_all_fltr(struct ice_hw *hw, u16 vsi_handle)
6356 {
6357 	struct ice_switch_info *sw = hw->switch_info;
6358 	enum ice_status status;
6359 	u8 i;
6360 
6361 	/* Update the recipes that were created */
6362 	for (i = 0; i < ICE_MAX_NUM_RECIPES; i++) {
6363 		struct LIST_HEAD_TYPE *head;
6364 
6365 		head = &sw->recp_list[i].filt_replay_rules;
6366 		if (!sw->recp_list[i].adv_rule)
6367 			status = ice_replay_vsi_fltr(hw, vsi_handle, i, head);
6368 		else
6369 			status = ice_replay_vsi_adv_rule(hw, vsi_handle, head);
6370 		if (status != ICE_SUCCESS)
6371 			return status;
6372 	}
6373 
6374 	return ICE_SUCCESS;
6375 }
6376 
6377 /**
6378  * ice_rm_all_sw_replay_rule_info - deletes filter replay rules
6379  * @hw: pointer to the HW struct
6380  *
6381  * Deletes the filter replay rules.
6382  */
6383 void ice_rm_all_sw_replay_rule_info(struct ice_hw *hw)
6384 {
6385 	struct ice_switch_info *sw = hw->switch_info;
6386 	u8 i;
6387 
6388 	if (!sw)
6389 		return;
6390 
6391 	for (i = 0; i < ICE_MAX_NUM_RECIPES; i++) {
6392 		if (!LIST_EMPTY(&sw->recp_list[i].filt_replay_rules)) {
6393 			struct LIST_HEAD_TYPE *l_head;
6394 
6395 			l_head = &sw->recp_list[i].filt_replay_rules;
6396 			if (!sw->recp_list[i].adv_rule)
6397 				ice_rem_sw_rule_info(hw, l_head);
6398 			else
6399 				ice_rem_adv_rule_info(hw, l_head);
6400 		}
6401 	}
6402 }
6403