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