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