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