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