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