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