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