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