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