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