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