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