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