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