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