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