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