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