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