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