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