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