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