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