]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/dev/ice/ice_switch.c
sys/contrib/zstd: Import zstd 1.4.8
[FreeBSD/FreeBSD.git] / sys / dev / ice / ice_switch.c
1 /* SPDX-License-Identifier: BSD-3-Clause */
2 /*  Copyright (c) 2020, Intel Corporation
3  *  All rights reserved.
4  *
5  *  Redistribution and use in source and binary forms, with or without
6  *  modification, are permitted provided that the following conditions are met:
7  *
8  *   1. Redistributions of source code must retain the above copyright notice,
9  *      this list of conditions and the following disclaimer.
10  *
11  *   2. Redistributions in binary form must reproduce the above copyright
12  *      notice, this list of conditions and the following disclaimer in the
13  *      documentation and/or other materials provided with the distribution.
14  *
15  *   3. Neither the name of the Intel Corporation nor the names of its
16  *      contributors may be used to endorse or promote products derived from
17  *      this software without specific prior written permission.
18  *
19  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20  *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21  *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22  *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
23  *  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24  *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25  *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26  *  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27  *  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28  *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29  *  POSSIBILITY OF SUCH DAMAGE.
30  */
31 /*$FreeBSD$*/
32
33 #include "ice_switch.h"
34 #include "ice_flex_type.h"
35 #include "ice_flow.h"
36
37 #define ICE_ETH_DA_OFFSET               0
38 #define ICE_ETH_ETHTYPE_OFFSET          12
39 #define ICE_ETH_VLAN_TCI_OFFSET         14
40 #define ICE_MAX_VLAN_ID                 0xFFF
41
42 /* Dummy ethernet header needed in the ice_aqc_sw_rules_elem
43  * struct to configure any switch filter rules.
44  * {DA (6 bytes), SA(6 bytes),
45  * Ether type (2 bytes for header without VLAN tag) OR
46  * VLAN tag (4 bytes for header with VLAN tag) }
47  *
48  * Word on Hardcoded values
49  * byte 0 = 0x2: to identify it as locally administered DA MAC
50  * byte 6 = 0x2: to identify it as locally administered SA MAC
51  * byte 12 = 0x81 & byte 13 = 0x00:
52  *      In case of VLAN filter first two bytes defines ether type (0x8100)
53  *      and remaining two bytes are placeholder for programming a given VLAN ID
54  *      In case of Ether type filter it is treated as header without VLAN tag
55  *      and byte 12 and 13 is used to program a given Ether type instead
56  */
57 static const u8 dummy_eth_header[DUMMY_ETH_HDR_LEN] = { 0x2, 0, 0, 0, 0, 0,
58                                                         0x2, 0, 0, 0, 0, 0,
59                                                         0x81, 0, 0, 0};
60
61 /**
62  * ice_init_def_sw_recp - initialize the recipe book keeping tables
63  * @hw: pointer to the HW struct
64  * @recp_list: pointer to sw recipe list
65  *
66  * Allocate memory for the entire recipe table and initialize the structures/
67  * entries corresponding to basic recipes.
68  */
69 enum ice_status
70 ice_init_def_sw_recp(struct ice_hw *hw, struct ice_sw_recipe **recp_list)
71 {
72         struct ice_sw_recipe *recps;
73         u8 i;
74
75         recps = (struct ice_sw_recipe *)
76                 ice_calloc(hw, ICE_MAX_NUM_RECIPES, sizeof(*recps));
77         if (!recps)
78                 return ICE_ERR_NO_MEMORY;
79
80         for (i = 0; i < ICE_MAX_NUM_RECIPES; i++) {
81                 recps[i].root_rid = i;
82                 INIT_LIST_HEAD(&recps[i].filt_rules);
83                 INIT_LIST_HEAD(&recps[i].filt_replay_rules);
84                 INIT_LIST_HEAD(&recps[i].rg_list);
85                 ice_init_lock(&recps[i].filt_rule_lock);
86         }
87
88         *recp_list = recps;
89
90         return ICE_SUCCESS;
91 }
92
93 /**
94  * ice_aq_get_sw_cfg - get switch configuration
95  * @hw: pointer to the hardware structure
96  * @buf: pointer to the result buffer
97  * @buf_size: length of the buffer available for response
98  * @req_desc: pointer to requested descriptor
99  * @num_elems: pointer to number of elements
100  * @cd: pointer to command details structure or NULL
101  *
102  * Get switch configuration (0x0200) to be placed in buf.
103  * This admin command returns information such as initial VSI/port number
104  * and switch ID it belongs to.
105  *
106  * NOTE: *req_desc is both an input/output parameter.
107  * The caller of this function first calls this function with *request_desc set
108  * to 0. If the response from f/w has *req_desc set to 0, all the switch
109  * configuration information has been returned; if non-zero (meaning not all
110  * the information was returned), the caller should call this function again
111  * with *req_desc set to the previous value returned by f/w to get the
112  * next block of switch configuration information.
113  *
114  * *num_elems is output only parameter. This reflects the number of elements
115  * in response buffer. The caller of this function to use *num_elems while
116  * parsing the response buffer.
117  */
118 static enum ice_status
119 ice_aq_get_sw_cfg(struct ice_hw *hw, struct ice_aqc_get_sw_cfg_resp_elem *buf,
120                   u16 buf_size, u16 *req_desc, u16 *num_elems,
121                   struct ice_sq_cd *cd)
122 {
123         struct ice_aqc_get_sw_cfg *cmd;
124         struct ice_aq_desc desc;
125         enum ice_status status;
126
127         ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_get_sw_cfg);
128         cmd = &desc.params.get_sw_conf;
129         cmd->element = CPU_TO_LE16(*req_desc);
130
131         status = ice_aq_send_cmd(hw, &desc, buf, buf_size, cd);
132         if (!status) {
133                 *req_desc = LE16_TO_CPU(cmd->element);
134                 *num_elems = LE16_TO_CPU(cmd->num_elems);
135         }
136
137         return status;
138 }
139
140 /**
141  * ice_alloc_sw - allocate resources specific to switch
142  * @hw: pointer to the HW struct
143  * @ena_stats: true to turn on VEB stats
144  * @shared_res: true for shared resource, false for dedicated resource
145  * @sw_id: switch ID returned
146  * @counter_id: VEB counter ID returned
147  *
148  * allocates switch resources (SWID and VEB counter) (0x0208)
149  */
150 enum ice_status
151 ice_alloc_sw(struct ice_hw *hw, bool ena_stats, bool shared_res, u16 *sw_id,
152              u16 *counter_id)
153 {
154         struct ice_aqc_alloc_free_res_elem *sw_buf;
155         struct ice_aqc_res_elem *sw_ele;
156         enum ice_status status;
157         u16 buf_len;
158
159         buf_len = ice_struct_size(sw_buf, elem, 1);
160         sw_buf = (struct ice_aqc_alloc_free_res_elem *)ice_malloc(hw, buf_len);
161         if (!sw_buf)
162                 return ICE_ERR_NO_MEMORY;
163
164         /* Prepare buffer for switch ID.
165          * The number of resource entries in buffer is passed as 1 since only a
166          * single switch/VEB instance is allocated, and hence a single sw_id
167          * is requested.
168          */
169         sw_buf->num_elems = CPU_TO_LE16(1);
170         sw_buf->res_type =
171                 CPU_TO_LE16(ICE_AQC_RES_TYPE_SWID |
172                             (shared_res ? ICE_AQC_RES_TYPE_FLAG_SHARED :
173                             ICE_AQC_RES_TYPE_FLAG_DEDICATED));
174
175         status = ice_aq_alloc_free_res(hw, 1, sw_buf, buf_len,
176                                        ice_aqc_opc_alloc_res, NULL);
177
178         if (status)
179                 goto ice_alloc_sw_exit;
180
181         sw_ele = &sw_buf->elem[0];
182         *sw_id = LE16_TO_CPU(sw_ele->e.sw_resp);
183
184         if (ena_stats) {
185                 /* Prepare buffer for VEB Counter */
186                 enum ice_adminq_opc opc = ice_aqc_opc_alloc_res;
187                 struct ice_aqc_alloc_free_res_elem *counter_buf;
188                 struct ice_aqc_res_elem *counter_ele;
189
190                 counter_buf = (struct ice_aqc_alloc_free_res_elem *)
191                                 ice_malloc(hw, buf_len);
192                 if (!counter_buf) {
193                         status = ICE_ERR_NO_MEMORY;
194                         goto ice_alloc_sw_exit;
195                 }
196
197                 /* The number of resource entries in buffer is passed as 1 since
198                  * only a single switch/VEB instance is allocated, and hence a
199                  * single VEB counter is requested.
200                  */
201                 counter_buf->num_elems = CPU_TO_LE16(1);
202                 counter_buf->res_type =
203                         CPU_TO_LE16(ICE_AQC_RES_TYPE_VEB_COUNTER |
204                                     ICE_AQC_RES_TYPE_FLAG_DEDICATED);
205                 status = ice_aq_alloc_free_res(hw, 1, counter_buf, buf_len,
206                                                opc, NULL);
207
208                 if (status) {
209                         ice_free(hw, counter_buf);
210                         goto ice_alloc_sw_exit;
211                 }
212                 counter_ele = &counter_buf->elem[0];
213                 *counter_id = LE16_TO_CPU(counter_ele->e.sw_resp);
214                 ice_free(hw, counter_buf);
215         }
216
217 ice_alloc_sw_exit:
218         ice_free(hw, sw_buf);
219         return status;
220 }
221
222 /**
223  * ice_free_sw - free resources specific to switch
224  * @hw: pointer to the HW struct
225  * @sw_id: switch ID returned
226  * @counter_id: VEB counter ID returned
227  *
228  * free switch resources (SWID and VEB counter) (0x0209)
229  *
230  * NOTE: This function frees multiple resources. It continues
231  * releasing other resources even after it encounters error.
232  * The error code returned is the last error it encountered.
233  */
234 enum ice_status ice_free_sw(struct ice_hw *hw, u16 sw_id, u16 counter_id)
235 {
236         struct ice_aqc_alloc_free_res_elem *sw_buf, *counter_buf;
237         enum ice_status status, ret_status;
238         u16 buf_len;
239
240         buf_len = ice_struct_size(sw_buf, elem, 1);
241         sw_buf = (struct ice_aqc_alloc_free_res_elem *)ice_malloc(hw, buf_len);
242         if (!sw_buf)
243                 return ICE_ERR_NO_MEMORY;
244
245         /* Prepare buffer to free for switch ID res.
246          * The number of resource entries in buffer is passed as 1 since only a
247          * single switch/VEB instance is freed, and hence a single sw_id
248          * is released.
249          */
250         sw_buf->num_elems = CPU_TO_LE16(1);
251         sw_buf->res_type = CPU_TO_LE16(ICE_AQC_RES_TYPE_SWID);
252         sw_buf->elem[0].e.sw_resp = CPU_TO_LE16(sw_id);
253
254         ret_status = ice_aq_alloc_free_res(hw, 1, sw_buf, buf_len,
255                                            ice_aqc_opc_free_res, NULL);
256
257         if (ret_status)
258                 ice_debug(hw, ICE_DBG_SW, "CQ CMD Buffer:\n");
259
260         /* Prepare buffer to free for VEB Counter resource */
261         counter_buf = (struct ice_aqc_alloc_free_res_elem *)
262                         ice_malloc(hw, buf_len);
263         if (!counter_buf) {
264                 ice_free(hw, sw_buf);
265                 return ICE_ERR_NO_MEMORY;
266         }
267
268         /* The number of resource entries in buffer is passed as 1 since only a
269          * single switch/VEB instance is freed, and hence a single VEB counter
270          * is released
271          */
272         counter_buf->num_elems = CPU_TO_LE16(1);
273         counter_buf->res_type = CPU_TO_LE16(ICE_AQC_RES_TYPE_VEB_COUNTER);
274         counter_buf->elem[0].e.sw_resp = CPU_TO_LE16(counter_id);
275
276         status = ice_aq_alloc_free_res(hw, 1, counter_buf, buf_len,
277                                        ice_aqc_opc_free_res, NULL);
278         if (status) {
279                 ice_debug(hw, ICE_DBG_SW, "VEB counter resource could not be freed\n");
280                 ret_status = status;
281         }
282
283         ice_free(hw, counter_buf);
284         ice_free(hw, sw_buf);
285         return ret_status;
286 }
287
288 /**
289  * ice_aq_add_vsi
290  * @hw: pointer to the HW struct
291  * @vsi_ctx: pointer to a VSI context struct
292  * @cd: pointer to command details structure or NULL
293  *
294  * Add a VSI context to the hardware (0x0210)
295  */
296 enum ice_status
297 ice_aq_add_vsi(struct ice_hw *hw, struct ice_vsi_ctx *vsi_ctx,
298                struct ice_sq_cd *cd)
299 {
300         struct ice_aqc_add_update_free_vsi_resp *res;
301         struct ice_aqc_add_get_update_free_vsi *cmd;
302         struct ice_aq_desc desc;
303         enum ice_status status;
304
305         cmd = &desc.params.vsi_cmd;
306         res = &desc.params.add_update_free_vsi_res;
307
308         ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_add_vsi);
309
310         if (!vsi_ctx->alloc_from_pool)
311                 cmd->vsi_num = CPU_TO_LE16(vsi_ctx->vsi_num |
312                                            ICE_AQ_VSI_IS_VALID);
313         cmd->vf_id = vsi_ctx->vf_num;
314
315         cmd->vsi_flags = CPU_TO_LE16(vsi_ctx->flags);
316
317         desc.flags |= CPU_TO_LE16(ICE_AQ_FLAG_RD);
318
319         status = ice_aq_send_cmd(hw, &desc, &vsi_ctx->info,
320                                  sizeof(vsi_ctx->info), cd);
321
322         if (!status) {
323                 vsi_ctx->vsi_num = LE16_TO_CPU(res->vsi_num) & ICE_AQ_VSI_NUM_M;
324                 vsi_ctx->vsis_allocd = LE16_TO_CPU(res->vsi_used);
325                 vsi_ctx->vsis_unallocated = LE16_TO_CPU(res->vsi_free);
326         }
327
328         return status;
329 }
330
331 /**
332  * ice_aq_free_vsi
333  * @hw: pointer to the HW struct
334  * @vsi_ctx: pointer to a VSI context struct
335  * @keep_vsi_alloc: keep VSI allocation as part of this PF's resources
336  * @cd: pointer to command details structure or NULL
337  *
338  * Free VSI context info from hardware (0x0213)
339  */
340 enum ice_status
341 ice_aq_free_vsi(struct ice_hw *hw, struct ice_vsi_ctx *vsi_ctx,
342                 bool keep_vsi_alloc, struct ice_sq_cd *cd)
343 {
344         struct ice_aqc_add_update_free_vsi_resp *resp;
345         struct ice_aqc_add_get_update_free_vsi *cmd;
346         struct ice_aq_desc desc;
347         enum ice_status status;
348
349         cmd = &desc.params.vsi_cmd;
350         resp = &desc.params.add_update_free_vsi_res;
351
352         ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_free_vsi);
353
354         cmd->vsi_num = CPU_TO_LE16(vsi_ctx->vsi_num | ICE_AQ_VSI_IS_VALID);
355         if (keep_vsi_alloc)
356                 cmd->cmd_flags = CPU_TO_LE16(ICE_AQ_VSI_KEEP_ALLOC);
357
358         status = ice_aq_send_cmd(hw, &desc, NULL, 0, cd);
359         if (!status) {
360                 vsi_ctx->vsis_allocd = LE16_TO_CPU(resp->vsi_used);
361                 vsi_ctx->vsis_unallocated = LE16_TO_CPU(resp->vsi_free);
362         }
363
364         return status;
365 }
366
367 /**
368  * ice_aq_update_vsi
369  * @hw: pointer to the HW struct
370  * @vsi_ctx: pointer to a VSI context struct
371  * @cd: pointer to command details structure or NULL
372  *
373  * Update VSI context in the hardware (0x0211)
374  */
375 enum ice_status
376 ice_aq_update_vsi(struct ice_hw *hw, struct ice_vsi_ctx *vsi_ctx,
377                   struct ice_sq_cd *cd)
378 {
379         struct ice_aqc_add_update_free_vsi_resp *resp;
380         struct ice_aqc_add_get_update_free_vsi *cmd;
381         struct ice_aq_desc desc;
382         enum ice_status status;
383
384         cmd = &desc.params.vsi_cmd;
385         resp = &desc.params.add_update_free_vsi_res;
386
387         ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_update_vsi);
388
389         cmd->vsi_num = CPU_TO_LE16(vsi_ctx->vsi_num | ICE_AQ_VSI_IS_VALID);
390
391         desc.flags |= CPU_TO_LE16(ICE_AQ_FLAG_RD);
392
393         status = ice_aq_send_cmd(hw, &desc, &vsi_ctx->info,
394                                  sizeof(vsi_ctx->info), cd);
395
396         if (!status) {
397                 vsi_ctx->vsis_allocd = LE16_TO_CPU(resp->vsi_used);
398                 vsi_ctx->vsis_unallocated = LE16_TO_CPU(resp->vsi_free);
399         }
400
401         return status;
402 }
403
404 /**
405  * ice_is_vsi_valid - check whether the VSI is valid or not
406  * @hw: pointer to the HW struct
407  * @vsi_handle: VSI handle
408  *
409  * check whether the VSI is valid or not
410  */
411 bool ice_is_vsi_valid(struct ice_hw *hw, u16 vsi_handle)
412 {
413         return vsi_handle < ICE_MAX_VSI && hw->vsi_ctx[vsi_handle];
414 }
415
416 /**
417  * ice_get_hw_vsi_num - return the HW VSI number
418  * @hw: pointer to the HW struct
419  * @vsi_handle: VSI handle
420  *
421  * return the HW VSI number
422  * Caution: call this function only if VSI is valid (ice_is_vsi_valid)
423  */
424 u16 ice_get_hw_vsi_num(struct ice_hw *hw, u16 vsi_handle)
425 {
426         return hw->vsi_ctx[vsi_handle]->vsi_num;
427 }
428
429 /**
430  * ice_get_vsi_ctx - return the VSI context entry for a given VSI handle
431  * @hw: pointer to the HW struct
432  * @vsi_handle: VSI handle
433  *
434  * return the VSI context entry for a given VSI handle
435  */
436 struct ice_vsi_ctx *ice_get_vsi_ctx(struct ice_hw *hw, u16 vsi_handle)
437 {
438         return (vsi_handle >= ICE_MAX_VSI) ? NULL : hw->vsi_ctx[vsi_handle];
439 }
440
441 /**
442  * ice_save_vsi_ctx - save the VSI context for a given VSI handle
443  * @hw: pointer to the HW struct
444  * @vsi_handle: VSI handle
445  * @vsi: VSI context pointer
446  *
447  * save the VSI context entry for a given VSI handle
448  */
449 static void
450 ice_save_vsi_ctx(struct ice_hw *hw, u16 vsi_handle, struct ice_vsi_ctx *vsi)
451 {
452         hw->vsi_ctx[vsi_handle] = vsi;
453 }
454
455 /**
456  * ice_clear_vsi_q_ctx - clear VSI queue contexts for all TCs
457  * @hw: pointer to the HW struct
458  * @vsi_handle: VSI handle
459  */
460 static void ice_clear_vsi_q_ctx(struct ice_hw *hw, u16 vsi_handle)
461 {
462         struct ice_vsi_ctx *vsi;
463         u8 i;
464
465         vsi = ice_get_vsi_ctx(hw, vsi_handle);
466         if (!vsi)
467                 return;
468         ice_for_each_traffic_class(i) {
469                 if (vsi->lan_q_ctx[i]) {
470                         ice_free(hw, vsi->lan_q_ctx[i]);
471                         vsi->lan_q_ctx[i] = NULL;
472                 }
473         }
474 }
475
476 /**
477  * ice_clear_vsi_ctx - clear the VSI context entry
478  * @hw: pointer to the HW struct
479  * @vsi_handle: VSI handle
480  *
481  * clear the VSI context entry
482  */
483 static void ice_clear_vsi_ctx(struct ice_hw *hw, u16 vsi_handle)
484 {
485         struct ice_vsi_ctx *vsi;
486
487         vsi = ice_get_vsi_ctx(hw, vsi_handle);
488         if (vsi) {
489                 ice_clear_vsi_q_ctx(hw, vsi_handle);
490                 ice_free(hw, vsi);
491                 hw->vsi_ctx[vsi_handle] = NULL;
492         }
493 }
494
495 /**
496  * ice_clear_all_vsi_ctx - clear all the VSI context entries
497  * @hw: pointer to the HW struct
498  */
499 void ice_clear_all_vsi_ctx(struct ice_hw *hw)
500 {
501         u16 i;
502
503         for (i = 0; i < ICE_MAX_VSI; i++)
504                 ice_clear_vsi_ctx(hw, i);
505 }
506
507 /**
508  * ice_add_vsi - add VSI context to the hardware and VSI handle list
509  * @hw: pointer to the HW struct
510  * @vsi_handle: unique VSI handle provided by drivers
511  * @vsi_ctx: pointer to a VSI context struct
512  * @cd: pointer to command details structure or NULL
513  *
514  * Add a VSI context to the hardware also add it into the VSI handle list.
515  * If this function gets called after reset for existing VSIs then update
516  * with the new HW VSI number in the corresponding VSI handle list entry.
517  */
518 enum ice_status
519 ice_add_vsi(struct ice_hw *hw, u16 vsi_handle, struct ice_vsi_ctx *vsi_ctx,
520             struct ice_sq_cd *cd)
521 {
522         struct ice_vsi_ctx *tmp_vsi_ctx;
523         enum ice_status status;
524
525         if (vsi_handle >= ICE_MAX_VSI)
526                 return ICE_ERR_PARAM;
527         status = ice_aq_add_vsi(hw, vsi_ctx, cd);
528         if (status)
529                 return status;
530         tmp_vsi_ctx = ice_get_vsi_ctx(hw, vsi_handle);
531         if (!tmp_vsi_ctx) {
532                 /* Create a new VSI context */
533                 tmp_vsi_ctx = (struct ice_vsi_ctx *)
534                         ice_malloc(hw, sizeof(*tmp_vsi_ctx));
535                 if (!tmp_vsi_ctx) {
536                         ice_aq_free_vsi(hw, vsi_ctx, false, cd);
537                         return ICE_ERR_NO_MEMORY;
538                 }
539                 *tmp_vsi_ctx = *vsi_ctx;
540
541                 ice_save_vsi_ctx(hw, vsi_handle, tmp_vsi_ctx);
542         } else {
543                 /* update with new HW VSI num */
544                 tmp_vsi_ctx->vsi_num = vsi_ctx->vsi_num;
545         }
546
547         return ICE_SUCCESS;
548 }
549
550 /**
551  * ice_free_vsi- free VSI context from hardware and VSI handle list
552  * @hw: pointer to the HW struct
553  * @vsi_handle: unique VSI handle
554  * @vsi_ctx: pointer to a VSI context struct
555  * @keep_vsi_alloc: keep VSI allocation as part of this PF's resources
556  * @cd: pointer to command details structure or NULL
557  *
558  * Free VSI context info from hardware as well as from VSI handle list
559  */
560 enum ice_status
561 ice_free_vsi(struct ice_hw *hw, u16 vsi_handle, struct ice_vsi_ctx *vsi_ctx,
562              bool keep_vsi_alloc, struct ice_sq_cd *cd)
563 {
564         enum ice_status status;
565
566         if (!ice_is_vsi_valid(hw, vsi_handle))
567                 return ICE_ERR_PARAM;
568         vsi_ctx->vsi_num = ice_get_hw_vsi_num(hw, vsi_handle);
569         status = ice_aq_free_vsi(hw, vsi_ctx, keep_vsi_alloc, cd);
570         if (!status)
571                 ice_clear_vsi_ctx(hw, vsi_handle);
572         return status;
573 }
574
575 /**
576  * ice_update_vsi
577  * @hw: pointer to the HW struct
578  * @vsi_handle: unique VSI handle
579  * @vsi_ctx: pointer to a VSI context struct
580  * @cd: pointer to command details structure or NULL
581  *
582  * Update VSI context in the hardware
583  */
584 enum ice_status
585 ice_update_vsi(struct ice_hw *hw, u16 vsi_handle, struct ice_vsi_ctx *vsi_ctx,
586                struct ice_sq_cd *cd)
587 {
588         if (!ice_is_vsi_valid(hw, vsi_handle))
589                 return ICE_ERR_PARAM;
590         vsi_ctx->vsi_num = ice_get_hw_vsi_num(hw, vsi_handle);
591         return ice_aq_update_vsi(hw, vsi_ctx, cd);
592 }
593
594 /**
595  * ice_aq_get_vsi_params
596  * @hw: pointer to the HW struct
597  * @vsi_ctx: pointer to a VSI context struct
598  * @cd: pointer to command details structure or NULL
599  *
600  * Get VSI context info from hardware (0x0212)
601  */
602 enum ice_status
603 ice_aq_get_vsi_params(struct ice_hw *hw, struct ice_vsi_ctx *vsi_ctx,
604                       struct ice_sq_cd *cd)
605 {
606         struct ice_aqc_add_get_update_free_vsi *cmd;
607         struct ice_aqc_get_vsi_resp *resp;
608         struct ice_aq_desc desc;
609         enum ice_status status;
610
611         cmd = &desc.params.vsi_cmd;
612         resp = &desc.params.get_vsi_resp;
613
614         ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_get_vsi_params);
615
616         cmd->vsi_num = CPU_TO_LE16(vsi_ctx->vsi_num | ICE_AQ_VSI_IS_VALID);
617
618         status = ice_aq_send_cmd(hw, &desc, &vsi_ctx->info,
619                                  sizeof(vsi_ctx->info), cd);
620         if (!status) {
621                 vsi_ctx->vsi_num = LE16_TO_CPU(resp->vsi_num) &
622                                         ICE_AQ_VSI_NUM_M;
623                 vsi_ctx->vf_num = resp->vf_id;
624                 vsi_ctx->vsis_allocd = LE16_TO_CPU(resp->vsi_used);
625                 vsi_ctx->vsis_unallocated = LE16_TO_CPU(resp->vsi_free);
626         }
627
628         return status;
629 }
630
631 /**
632  * ice_aq_add_update_mir_rule - add/update a mirror rule
633  * @hw: pointer to the HW struct
634  * @rule_type: Rule Type
635  * @dest_vsi: VSI number to which packets will be mirrored
636  * @count: length of the list
637  * @mr_buf: buffer for list of mirrored VSI numbers
638  * @cd: pointer to command details structure or NULL
639  * @rule_id: Rule ID
640  *
641  * Add/Update Mirror Rule (0x260).
642  */
643 enum ice_status
644 ice_aq_add_update_mir_rule(struct ice_hw *hw, u16 rule_type, u16 dest_vsi,
645                            u16 count, struct ice_mir_rule_buf *mr_buf,
646                            struct ice_sq_cd *cd, u16 *rule_id)
647 {
648         struct ice_aqc_add_update_mir_rule *cmd;
649         struct ice_aq_desc desc;
650         enum ice_status status;
651         __le16 *mr_list = NULL;
652         u16 buf_size = 0;
653
654         switch (rule_type) {
655         case ICE_AQC_RULE_TYPE_VPORT_INGRESS:
656         case ICE_AQC_RULE_TYPE_VPORT_EGRESS:
657                 /* Make sure count and mr_buf are set for these rule_types */
658                 if (!(count && mr_buf))
659                         return ICE_ERR_PARAM;
660
661                 buf_size = count * sizeof(__le16);
662                 mr_list = (_FORCE_ __le16 *)ice_malloc(hw, buf_size);
663                 if (!mr_list)
664                         return ICE_ERR_NO_MEMORY;
665                 break;
666         case ICE_AQC_RULE_TYPE_PPORT_INGRESS:
667         case ICE_AQC_RULE_TYPE_PPORT_EGRESS:
668                 /* Make sure count and mr_buf are not set for these
669                  * rule_types
670                  */
671                 if (count || mr_buf)
672                         return ICE_ERR_PARAM;
673                 break;
674         default:
675                 ice_debug(hw, ICE_DBG_SW, "Error due to unsupported rule_type %u\n", rule_type);
676                 return ICE_ERR_OUT_OF_RANGE;
677         }
678
679         ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_add_update_mir_rule);
680
681         /* Pre-process 'mr_buf' items for add/update of virtual port
682          * ingress/egress mirroring (but not physical port ingress/egress
683          * mirroring)
684          */
685         if (mr_buf) {
686                 int i;
687
688                 for (i = 0; i < count; i++) {
689                         u16 id;
690
691                         id = mr_buf[i].vsi_idx & ICE_AQC_RULE_MIRRORED_VSI_M;
692
693                         /* Validate specified VSI number, make sure it is less
694                          * than ICE_MAX_VSI, if not return with error.
695                          */
696                         if (id >= ICE_MAX_VSI) {
697                                 ice_debug(hw, ICE_DBG_SW, "Error VSI index (%u) out-of-range\n",
698                                           id);
699                                 ice_free(hw, mr_list);
700                                 return ICE_ERR_OUT_OF_RANGE;
701                         }
702
703                         /* add VSI to mirror rule */
704                         if (mr_buf[i].add)
705                                 mr_list[i] =
706                                         CPU_TO_LE16(id | ICE_AQC_RULE_ACT_M);
707                         else /* remove VSI from mirror rule */
708                                 mr_list[i] = CPU_TO_LE16(id);
709                 }
710         }
711
712         cmd = &desc.params.add_update_rule;
713         if ((*rule_id) != ICE_INVAL_MIRROR_RULE_ID)
714                 cmd->rule_id = CPU_TO_LE16(((*rule_id) & ICE_AQC_RULE_ID_M) |
715                                            ICE_AQC_RULE_ID_VALID_M);
716         cmd->rule_type = CPU_TO_LE16(rule_type & ICE_AQC_RULE_TYPE_M);
717         cmd->num_entries = CPU_TO_LE16(count);
718         cmd->dest = CPU_TO_LE16(dest_vsi);
719
720         status = ice_aq_send_cmd(hw, &desc, mr_list, buf_size, cd);
721         if (!status)
722                 *rule_id = LE16_TO_CPU(cmd->rule_id) & ICE_AQC_RULE_ID_M;
723
724         ice_free(hw, mr_list);
725
726         return status;
727 }
728
729 /**
730  * ice_aq_delete_mir_rule - delete a mirror rule
731  * @hw: pointer to the HW struct
732  * @rule_id: Mirror rule ID (to be deleted)
733  * @keep_allocd: if set, the VSI stays part of the PF allocated res,
734  *               otherwise it is returned to the shared pool
735  * @cd: pointer to command details structure or NULL
736  *
737  * Delete Mirror Rule (0x261).
738  */
739 enum ice_status
740 ice_aq_delete_mir_rule(struct ice_hw *hw, u16 rule_id, bool keep_allocd,
741                        struct ice_sq_cd *cd)
742 {
743         struct ice_aqc_delete_mir_rule *cmd;
744         struct ice_aq_desc desc;
745
746         /* rule_id should be in the range 0...63 */
747         if (rule_id >= ICE_MAX_NUM_MIRROR_RULES)
748                 return ICE_ERR_OUT_OF_RANGE;
749
750         ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_del_mir_rule);
751
752         cmd = &desc.params.del_rule;
753         rule_id |= ICE_AQC_RULE_ID_VALID_M;
754         cmd->rule_id = CPU_TO_LE16(rule_id);
755
756         if (keep_allocd)
757                 cmd->flags = CPU_TO_LE16(ICE_AQC_FLAG_KEEP_ALLOCD_M);
758
759         return ice_aq_send_cmd(hw, &desc, NULL, 0, cd);
760 }
761
762 /**
763  * ice_aq_alloc_free_vsi_list
764  * @hw: pointer to the HW struct
765  * @vsi_list_id: VSI list ID returned or used for lookup
766  * @lkup_type: switch rule filter lookup type
767  * @opc: switch rules population command type - pass in the command opcode
768  *
769  * allocates or free a VSI list resource
770  */
771 static enum ice_status
772 ice_aq_alloc_free_vsi_list(struct ice_hw *hw, u16 *vsi_list_id,
773                            enum ice_sw_lkup_type lkup_type,
774                            enum ice_adminq_opc opc)
775 {
776         struct ice_aqc_alloc_free_res_elem *sw_buf;
777         struct ice_aqc_res_elem *vsi_ele;
778         enum ice_status status;
779         u16 buf_len;
780
781         buf_len = ice_struct_size(sw_buf, elem, 1);
782         sw_buf = (struct ice_aqc_alloc_free_res_elem *)ice_malloc(hw, buf_len);
783         if (!sw_buf)
784                 return ICE_ERR_NO_MEMORY;
785         sw_buf->num_elems = CPU_TO_LE16(1);
786
787         if (lkup_type == ICE_SW_LKUP_MAC ||
788             lkup_type == ICE_SW_LKUP_MAC_VLAN ||
789             lkup_type == ICE_SW_LKUP_ETHERTYPE ||
790             lkup_type == ICE_SW_LKUP_ETHERTYPE_MAC ||
791             lkup_type == ICE_SW_LKUP_PROMISC ||
792             lkup_type == ICE_SW_LKUP_PROMISC_VLAN ||
793             lkup_type == ICE_SW_LKUP_LAST) {
794                 sw_buf->res_type = CPU_TO_LE16(ICE_AQC_RES_TYPE_VSI_LIST_REP);
795         } else if (lkup_type == ICE_SW_LKUP_VLAN) {
796                 sw_buf->res_type =
797                         CPU_TO_LE16(ICE_AQC_RES_TYPE_VSI_LIST_PRUNE);
798         } else {
799                 status = ICE_ERR_PARAM;
800                 goto ice_aq_alloc_free_vsi_list_exit;
801         }
802
803         if (opc == ice_aqc_opc_free_res)
804                 sw_buf->elem[0].e.sw_resp = CPU_TO_LE16(*vsi_list_id);
805
806         status = ice_aq_alloc_free_res(hw, 1, sw_buf, buf_len, opc, NULL);
807         if (status)
808                 goto ice_aq_alloc_free_vsi_list_exit;
809
810         if (opc == ice_aqc_opc_alloc_res) {
811                 vsi_ele = &sw_buf->elem[0];
812                 *vsi_list_id = LE16_TO_CPU(vsi_ele->e.sw_resp);
813         }
814
815 ice_aq_alloc_free_vsi_list_exit:
816         ice_free(hw, sw_buf);
817         return status;
818 }
819
820 /**
821  * ice_aq_set_storm_ctrl - Sets storm control configuration
822  * @hw: pointer to the HW struct
823  * @bcast_thresh: represents the upper threshold for broadcast storm control
824  * @mcast_thresh: represents the upper threshold for multicast storm control
825  * @ctl_bitmask: storm control knobs
826  *
827  * Sets the storm control configuration (0x0280)
828  */
829 enum ice_status
830 ice_aq_set_storm_ctrl(struct ice_hw *hw, u32 bcast_thresh, u32 mcast_thresh,
831                       u32 ctl_bitmask)
832 {
833         struct ice_aqc_storm_cfg *cmd;
834         struct ice_aq_desc desc;
835
836         cmd = &desc.params.storm_conf;
837
838         ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_set_storm_cfg);
839
840         cmd->bcast_thresh_size = CPU_TO_LE32(bcast_thresh & ICE_AQ_THRESHOLD_M);
841         cmd->mcast_thresh_size = CPU_TO_LE32(mcast_thresh & ICE_AQ_THRESHOLD_M);
842         cmd->storm_ctrl_ctrl = CPU_TO_LE32(ctl_bitmask);
843
844         return ice_aq_send_cmd(hw, &desc, NULL, 0, NULL);
845 }
846
847 /**
848  * ice_aq_get_storm_ctrl - gets storm control configuration
849  * @hw: pointer to the HW struct
850  * @bcast_thresh: represents the upper threshold for broadcast storm control
851  * @mcast_thresh: represents the upper threshold for multicast storm control
852  * @ctl_bitmask: storm control knobs
853  *
854  * Gets the storm control configuration (0x0281)
855  */
856 enum ice_status
857 ice_aq_get_storm_ctrl(struct ice_hw *hw, u32 *bcast_thresh, u32 *mcast_thresh,
858                       u32 *ctl_bitmask)
859 {
860         enum ice_status status;
861         struct ice_aq_desc desc;
862
863         ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_get_storm_cfg);
864
865         status = ice_aq_send_cmd(hw, &desc, NULL, 0, NULL);
866         if (!status) {
867                 struct ice_aqc_storm_cfg *resp = &desc.params.storm_conf;
868
869                 if (bcast_thresh)
870                         *bcast_thresh = LE32_TO_CPU(resp->bcast_thresh_size) &
871                                 ICE_AQ_THRESHOLD_M;
872                 if (mcast_thresh)
873                         *mcast_thresh = LE32_TO_CPU(resp->mcast_thresh_size) &
874                                 ICE_AQ_THRESHOLD_M;
875                 if (ctl_bitmask)
876                         *ctl_bitmask = LE32_TO_CPU(resp->storm_ctrl_ctrl);
877         }
878
879         return status;
880 }
881
882 /**
883  * ice_aq_sw_rules - add/update/remove switch rules
884  * @hw: pointer to the HW struct
885  * @rule_list: pointer to switch rule population list
886  * @rule_list_sz: total size of the rule list in bytes
887  * @num_rules: number of switch rules in the rule_list
888  * @opc: switch rules population command type - pass in the command opcode
889  * @cd: pointer to command details structure or NULL
890  *
891  * Add(0x02a0)/Update(0x02a1)/Remove(0x02a2) switch rules commands to firmware
892  */
893 static enum ice_status
894 ice_aq_sw_rules(struct ice_hw *hw, void *rule_list, u16 rule_list_sz,
895                 u8 num_rules, enum ice_adminq_opc opc, struct ice_sq_cd *cd)
896 {
897         struct ice_aq_desc desc;
898         enum ice_status status;
899
900         ice_debug(hw, ICE_DBG_TRACE, "%s\n", __func__);
901
902         if (opc != ice_aqc_opc_add_sw_rules &&
903             opc != ice_aqc_opc_update_sw_rules &&
904             opc != ice_aqc_opc_remove_sw_rules)
905                 return ICE_ERR_PARAM;
906
907         ice_fill_dflt_direct_cmd_desc(&desc, opc);
908
909         desc.flags |= CPU_TO_LE16(ICE_AQ_FLAG_RD);
910         desc.params.sw_rules.num_rules_fltr_entry_index =
911                 CPU_TO_LE16(num_rules);
912         status = ice_aq_send_cmd(hw, &desc, rule_list, rule_list_sz, cd);
913         if (opc != ice_aqc_opc_add_sw_rules &&
914             hw->adminq.sq_last_status == ICE_AQ_RC_ENOENT)
915                 status = ICE_ERR_DOES_NOT_EXIST;
916
917         return status;
918 }
919
920 /* ice_init_port_info - Initialize port_info with switch configuration data
921  * @pi: pointer to port_info
922  * @vsi_port_num: VSI number or port number
923  * @type: Type of switch element (port or VSI)
924  * @swid: switch ID of the switch the element is attached to
925  * @pf_vf_num: PF or VF number
926  * @is_vf: true if the element is a VF, false otherwise
927  */
928 static void
929 ice_init_port_info(struct ice_port_info *pi, u16 vsi_port_num, u8 type,
930                    u16 swid, u16 pf_vf_num, bool is_vf)
931 {
932         switch (type) {
933         case ICE_AQC_GET_SW_CONF_RESP_PHYS_PORT:
934                 pi->lport = (u8)(vsi_port_num & ICE_LPORT_MASK);
935                 pi->sw_id = swid;
936                 pi->pf_vf_num = pf_vf_num;
937                 pi->is_vf = is_vf;
938                 pi->dflt_tx_vsi_num = ICE_DFLT_VSI_INVAL;
939                 pi->dflt_rx_vsi_num = ICE_DFLT_VSI_INVAL;
940                 break;
941         default:
942                 ice_debug(pi->hw, ICE_DBG_SW, "incorrect VSI/port type received\n");
943                 break;
944         }
945 }
946
947 /* ice_get_initial_sw_cfg - Get initial port and default VSI data
948  * @hw: pointer to the hardware structure
949  */
950 enum ice_status ice_get_initial_sw_cfg(struct ice_hw *hw)
951 {
952         struct ice_aqc_get_sw_cfg_resp_elem *rbuf;
953         enum ice_status status;
954         u8 num_total_ports;
955         u16 req_desc = 0;
956         u16 num_elems;
957         u8 j = 0;
958         u16 i;
959
960         num_total_ports = 1;
961
962         rbuf = (struct ice_aqc_get_sw_cfg_resp_elem *)
963                 ice_malloc(hw, ICE_SW_CFG_MAX_BUF_LEN);
964
965         if (!rbuf)
966                 return ICE_ERR_NO_MEMORY;
967
968         /* Multiple calls to ice_aq_get_sw_cfg may be required
969          * to get all the switch configuration information. The need
970          * for additional calls is indicated by ice_aq_get_sw_cfg
971          * writing a non-zero value in req_desc
972          */
973         do {
974                 struct ice_aqc_get_sw_cfg_resp_elem *ele;
975
976                 status = ice_aq_get_sw_cfg(hw, rbuf, ICE_SW_CFG_MAX_BUF_LEN,
977                                            &req_desc, &num_elems, NULL);
978
979                 if (status)
980                         break;
981
982                 for (i = 0, ele = rbuf; i < num_elems; i++, ele++) {
983                         u16 pf_vf_num, swid, vsi_port_num;
984                         bool is_vf = false;
985                         u8 res_type;
986
987                         vsi_port_num = LE16_TO_CPU(ele->vsi_port_num) &
988                                 ICE_AQC_GET_SW_CONF_RESP_VSI_PORT_NUM_M;
989
990                         pf_vf_num = LE16_TO_CPU(ele->pf_vf_num) &
991                                 ICE_AQC_GET_SW_CONF_RESP_FUNC_NUM_M;
992
993                         swid = LE16_TO_CPU(ele->swid);
994
995                         if (LE16_TO_CPU(ele->pf_vf_num) &
996                             ICE_AQC_GET_SW_CONF_RESP_IS_VF)
997                                 is_vf = true;
998
999                         res_type = (u8)(LE16_TO_CPU(ele->vsi_port_num) >>
1000                                         ICE_AQC_GET_SW_CONF_RESP_TYPE_S);
1001
1002                         switch (res_type) {
1003                         case ICE_AQC_GET_SW_CONF_RESP_PHYS_PORT:
1004                         case ICE_AQC_GET_SW_CONF_RESP_VIRT_PORT:
1005                                 if (j == num_total_ports) {
1006                                         ice_debug(hw, ICE_DBG_SW, "more ports than expected\n");
1007                                         status = ICE_ERR_CFG;
1008                                         goto out;
1009                                 }
1010                                 ice_init_port_info(hw->port_info,
1011                                                    vsi_port_num, res_type, swid,
1012                                                    pf_vf_num, is_vf);
1013                                 j++;
1014                                 break;
1015                         default:
1016                                 break;
1017                         }
1018                 }
1019         } while (req_desc && !status);
1020
1021 out:
1022         ice_free(hw, rbuf);
1023         return status;
1024 }
1025
1026 /**
1027  * ice_fill_sw_info - Helper function to populate lb_en and lan_en
1028  * @hw: pointer to the hardware structure
1029  * @fi: filter info structure to fill/update
1030  *
1031  * This helper function populates the lb_en and lan_en elements of the provided
1032  * ice_fltr_info struct using the switch's type and characteristics of the
1033  * switch rule being configured.
1034  */
1035 static void ice_fill_sw_info(struct ice_hw *hw, struct ice_fltr_info *fi)
1036 {
1037         fi->lb_en = false;
1038         fi->lan_en = false;
1039         if ((fi->flag & ICE_FLTR_TX) &&
1040             (fi->fltr_act == ICE_FWD_TO_VSI ||
1041              fi->fltr_act == ICE_FWD_TO_VSI_LIST ||
1042              fi->fltr_act == ICE_FWD_TO_Q ||
1043              fi->fltr_act == ICE_FWD_TO_QGRP)) {
1044                 /* Setting LB for prune actions will result in replicated
1045                  * packets to the internal switch that will be dropped.
1046                  */
1047                 if (fi->lkup_type != ICE_SW_LKUP_VLAN)
1048                         fi->lb_en = true;
1049
1050                 /* Set lan_en to TRUE if
1051                  * 1. The switch is a VEB AND
1052                  * 2
1053                  * 2.1 The lookup is a directional lookup like ethertype,
1054                  * promiscuous, ethertype-MAC, promiscuous-VLAN
1055                  * and default-port OR
1056                  * 2.2 The lookup is VLAN, OR
1057                  * 2.3 The lookup is MAC with mcast or bcast addr for MAC, OR
1058                  * 2.4 The lookup is MAC_VLAN with mcast or bcast addr for MAC.
1059                  *
1060                  * OR
1061                  *
1062                  * The switch is a VEPA.
1063                  *
1064                  * In all other cases, the LAN enable has to be set to false.
1065                  */
1066                 if (hw->evb_veb) {
1067                         if (fi->lkup_type == ICE_SW_LKUP_ETHERTYPE ||
1068                             fi->lkup_type == ICE_SW_LKUP_PROMISC ||
1069                             fi->lkup_type == ICE_SW_LKUP_ETHERTYPE_MAC ||
1070                             fi->lkup_type == ICE_SW_LKUP_PROMISC_VLAN ||
1071                             fi->lkup_type == ICE_SW_LKUP_DFLT ||
1072                             fi->lkup_type == ICE_SW_LKUP_VLAN ||
1073                             (fi->lkup_type == ICE_SW_LKUP_MAC &&
1074                              !IS_UNICAST_ETHER_ADDR(fi->l_data.mac.mac_addr)) ||
1075                             (fi->lkup_type == ICE_SW_LKUP_MAC_VLAN &&
1076                              !IS_UNICAST_ETHER_ADDR(fi->l_data.mac.mac_addr)))
1077                                 fi->lan_en = true;
1078                 } else {
1079                         fi->lan_en = true;
1080                 }
1081         }
1082 }
1083
1084 /**
1085  * ice_fill_sw_rule - Helper function to fill switch rule structure
1086  * @hw: pointer to the hardware structure
1087  * @f_info: entry containing packet forwarding information
1088  * @s_rule: switch rule structure to be filled in based on mac_entry
1089  * @opc: switch rules population command type - pass in the command opcode
1090  */
1091 static void
1092 ice_fill_sw_rule(struct ice_hw *hw, struct ice_fltr_info *f_info,
1093                  struct ice_aqc_sw_rules_elem *s_rule, enum ice_adminq_opc opc)
1094 {
1095         u16 vlan_id = ICE_MAX_VLAN_ID + 1;
1096         void *daddr = NULL;
1097         u16 eth_hdr_sz;
1098         u8 *eth_hdr;
1099         u32 act = 0;
1100         __be16 *off;
1101         u8 q_rgn;
1102
1103         if (opc == ice_aqc_opc_remove_sw_rules) {
1104                 s_rule->pdata.lkup_tx_rx.act = 0;
1105                 s_rule->pdata.lkup_tx_rx.index =
1106                         CPU_TO_LE16(f_info->fltr_rule_id);
1107                 s_rule->pdata.lkup_tx_rx.hdr_len = 0;
1108                 return;
1109         }
1110
1111         eth_hdr_sz = sizeof(dummy_eth_header);
1112         eth_hdr = s_rule->pdata.lkup_tx_rx.hdr;
1113
1114         /* initialize the ether header with a dummy header */
1115         ice_memcpy(eth_hdr, dummy_eth_header, eth_hdr_sz, ICE_NONDMA_TO_NONDMA);
1116         ice_fill_sw_info(hw, f_info);
1117
1118         switch (f_info->fltr_act) {
1119         case ICE_FWD_TO_VSI:
1120                 act |= (f_info->fwd_id.hw_vsi_id << ICE_SINGLE_ACT_VSI_ID_S) &
1121                         ICE_SINGLE_ACT_VSI_ID_M;
1122                 if (f_info->lkup_type != ICE_SW_LKUP_VLAN)
1123                         act |= ICE_SINGLE_ACT_VSI_FORWARDING |
1124                                 ICE_SINGLE_ACT_VALID_BIT;
1125                 break;
1126         case ICE_FWD_TO_VSI_LIST:
1127                 act |= ICE_SINGLE_ACT_VSI_LIST;
1128                 act |= (f_info->fwd_id.vsi_list_id <<
1129                         ICE_SINGLE_ACT_VSI_LIST_ID_S) &
1130                         ICE_SINGLE_ACT_VSI_LIST_ID_M;
1131                 if (f_info->lkup_type != ICE_SW_LKUP_VLAN)
1132                         act |= ICE_SINGLE_ACT_VSI_FORWARDING |
1133                                 ICE_SINGLE_ACT_VALID_BIT;
1134                 break;
1135         case ICE_FWD_TO_Q:
1136                 act |= ICE_SINGLE_ACT_TO_Q;
1137                 act |= (f_info->fwd_id.q_id << ICE_SINGLE_ACT_Q_INDEX_S) &
1138                         ICE_SINGLE_ACT_Q_INDEX_M;
1139                 break;
1140         case ICE_DROP_PACKET:
1141                 act |= ICE_SINGLE_ACT_VSI_FORWARDING | ICE_SINGLE_ACT_DROP |
1142                         ICE_SINGLE_ACT_VALID_BIT;
1143                 break;
1144         case ICE_FWD_TO_QGRP:
1145                 q_rgn = f_info->qgrp_size > 0 ?
1146                         (u8)ice_ilog2(f_info->qgrp_size) : 0;
1147                 act |= ICE_SINGLE_ACT_TO_Q;
1148                 act |= (f_info->fwd_id.q_id << ICE_SINGLE_ACT_Q_INDEX_S) &
1149                         ICE_SINGLE_ACT_Q_INDEX_M;
1150                 act |= (q_rgn << ICE_SINGLE_ACT_Q_REGION_S) &
1151                         ICE_SINGLE_ACT_Q_REGION_M;
1152                 break;
1153         default:
1154                 return;
1155         }
1156
1157         if (f_info->lb_en)
1158                 act |= ICE_SINGLE_ACT_LB_ENABLE;
1159         if (f_info->lan_en)
1160                 act |= ICE_SINGLE_ACT_LAN_ENABLE;
1161
1162         switch (f_info->lkup_type) {
1163         case ICE_SW_LKUP_MAC:
1164                 daddr = f_info->l_data.mac.mac_addr;
1165                 break;
1166         case ICE_SW_LKUP_VLAN:
1167                 vlan_id = f_info->l_data.vlan.vlan_id;
1168                 if (f_info->fltr_act == ICE_FWD_TO_VSI ||
1169                     f_info->fltr_act == ICE_FWD_TO_VSI_LIST) {
1170                         act |= ICE_SINGLE_ACT_PRUNE;
1171                         act |= ICE_SINGLE_ACT_EGRESS | ICE_SINGLE_ACT_INGRESS;
1172                 }
1173                 break;
1174         case ICE_SW_LKUP_ETHERTYPE_MAC:
1175                 daddr = f_info->l_data.ethertype_mac.mac_addr;
1176                 /* fall-through */
1177         case ICE_SW_LKUP_ETHERTYPE:
1178                 off = (_FORCE_ __be16 *)(eth_hdr + ICE_ETH_ETHTYPE_OFFSET);
1179                 *off = CPU_TO_BE16(f_info->l_data.ethertype_mac.ethertype);
1180                 break;
1181         case ICE_SW_LKUP_MAC_VLAN:
1182                 daddr = f_info->l_data.mac_vlan.mac_addr;
1183                 vlan_id = f_info->l_data.mac_vlan.vlan_id;
1184                 break;
1185         case ICE_SW_LKUP_PROMISC_VLAN:
1186                 vlan_id = f_info->l_data.mac_vlan.vlan_id;
1187                 /* fall-through */
1188         case ICE_SW_LKUP_PROMISC:
1189                 daddr = f_info->l_data.mac_vlan.mac_addr;
1190                 break;
1191         default:
1192                 break;
1193         }
1194
1195         s_rule->type = (f_info->flag & ICE_FLTR_RX) ?
1196                 CPU_TO_LE16(ICE_AQC_SW_RULES_T_LKUP_RX) :
1197                 CPU_TO_LE16(ICE_AQC_SW_RULES_T_LKUP_TX);
1198
1199         /* Recipe set depending on lookup type */
1200         s_rule->pdata.lkup_tx_rx.recipe_id = CPU_TO_LE16(f_info->lkup_type);
1201         s_rule->pdata.lkup_tx_rx.src = CPU_TO_LE16(f_info->src);
1202         s_rule->pdata.lkup_tx_rx.act = CPU_TO_LE32(act);
1203
1204         if (daddr)
1205                 ice_memcpy(eth_hdr + ICE_ETH_DA_OFFSET, daddr, ETH_ALEN,
1206                            ICE_NONDMA_TO_NONDMA);
1207
1208         if (!(vlan_id > ICE_MAX_VLAN_ID)) {
1209                 off = (_FORCE_ __be16 *)(eth_hdr + ICE_ETH_VLAN_TCI_OFFSET);
1210                 *off = CPU_TO_BE16(vlan_id);
1211         }
1212
1213         /* Create the switch rule with the final dummy Ethernet header */
1214         if (opc != ice_aqc_opc_update_sw_rules)
1215                 s_rule->pdata.lkup_tx_rx.hdr_len = CPU_TO_LE16(eth_hdr_sz);
1216 }
1217
1218 /**
1219  * ice_add_marker_act
1220  * @hw: pointer to the hardware structure
1221  * @m_ent: the management entry for which sw marker needs to be added
1222  * @sw_marker: sw marker to tag the Rx descriptor with
1223  * @l_id: large action resource ID
1224  *
1225  * Create a large action to hold software marker and update the switch rule
1226  * entry pointed by m_ent with newly created large action
1227  */
1228 static enum ice_status
1229 ice_add_marker_act(struct ice_hw *hw, struct ice_fltr_mgmt_list_entry *m_ent,
1230                    u16 sw_marker, u16 l_id)
1231 {
1232         struct ice_aqc_sw_rules_elem *lg_act, *rx_tx;
1233         /* For software marker we need 3 large actions
1234          * 1. FWD action: FWD TO VSI or VSI LIST
1235          * 2. GENERIC VALUE action to hold the profile ID
1236          * 3. GENERIC VALUE action to hold the software marker ID
1237          */
1238         const u16 num_lg_acts = 3;
1239         enum ice_status status;
1240         u16 lg_act_size;
1241         u16 rules_size;
1242         u32 act;
1243         u16 id;
1244
1245         if (m_ent->fltr_info.lkup_type != ICE_SW_LKUP_MAC)
1246                 return ICE_ERR_PARAM;
1247
1248         /* Create two back-to-back switch rules and submit them to the HW using
1249          * one memory buffer:
1250          *    1. Large Action
1251          *    2. Look up Tx Rx
1252          */
1253         lg_act_size = (u16)ICE_SW_RULE_LG_ACT_SIZE(num_lg_acts);
1254         rules_size = lg_act_size + ICE_SW_RULE_RX_TX_ETH_HDR_SIZE;
1255         lg_act = (struct ice_aqc_sw_rules_elem *)ice_malloc(hw, rules_size);
1256         if (!lg_act)
1257                 return ICE_ERR_NO_MEMORY;
1258
1259         rx_tx = (struct ice_aqc_sw_rules_elem *)((u8 *)lg_act + lg_act_size);
1260
1261         /* Fill in the first switch rule i.e. large action */
1262         lg_act->type = CPU_TO_LE16(ICE_AQC_SW_RULES_T_LG_ACT);
1263         lg_act->pdata.lg_act.index = CPU_TO_LE16(l_id);
1264         lg_act->pdata.lg_act.size = CPU_TO_LE16(num_lg_acts);
1265
1266         /* First action VSI forwarding or VSI list forwarding depending on how
1267          * many VSIs
1268          */
1269         id = (m_ent->vsi_count > 1) ? m_ent->fltr_info.fwd_id.vsi_list_id :
1270                 m_ent->fltr_info.fwd_id.hw_vsi_id;
1271
1272         act = ICE_LG_ACT_VSI_FORWARDING | ICE_LG_ACT_VALID_BIT;
1273         act |= (id << ICE_LG_ACT_VSI_LIST_ID_S) & ICE_LG_ACT_VSI_LIST_ID_M;
1274         if (m_ent->vsi_count > 1)
1275                 act |= ICE_LG_ACT_VSI_LIST;
1276         lg_act->pdata.lg_act.act[0] = CPU_TO_LE32(act);
1277
1278         /* Second action descriptor type */
1279         act = ICE_LG_ACT_GENERIC;
1280
1281         act |= (1 << ICE_LG_ACT_GENERIC_VALUE_S) & ICE_LG_ACT_GENERIC_VALUE_M;
1282         lg_act->pdata.lg_act.act[1] = CPU_TO_LE32(act);
1283
1284         act = (ICE_LG_ACT_GENERIC_OFF_RX_DESC_PROF_IDX <<
1285                ICE_LG_ACT_GENERIC_OFFSET_S) & ICE_LG_ACT_GENERIC_OFFSET_M;
1286
1287         /* Third action Marker value */
1288         act |= ICE_LG_ACT_GENERIC;
1289         act |= (sw_marker << ICE_LG_ACT_GENERIC_VALUE_S) &
1290                 ICE_LG_ACT_GENERIC_VALUE_M;
1291
1292         lg_act->pdata.lg_act.act[2] = CPU_TO_LE32(act);
1293
1294         /* call the fill switch rule to fill the lookup Tx Rx structure */
1295         ice_fill_sw_rule(hw, &m_ent->fltr_info, rx_tx,
1296                          ice_aqc_opc_update_sw_rules);
1297
1298         /* Update the action to point to the large action ID */
1299         rx_tx->pdata.lkup_tx_rx.act =
1300                 CPU_TO_LE32(ICE_SINGLE_ACT_PTR |
1301                             ((l_id << ICE_SINGLE_ACT_PTR_VAL_S) &
1302                              ICE_SINGLE_ACT_PTR_VAL_M));
1303
1304         /* Use the filter rule ID of the previously created rule with single
1305          * act. Once the update happens, hardware will treat this as large
1306          * action
1307          */
1308         rx_tx->pdata.lkup_tx_rx.index =
1309                 CPU_TO_LE16(m_ent->fltr_info.fltr_rule_id);
1310
1311         status = ice_aq_sw_rules(hw, lg_act, rules_size, 2,
1312                                  ice_aqc_opc_update_sw_rules, NULL);
1313         if (!status) {
1314                 m_ent->lg_act_idx = l_id;
1315                 m_ent->sw_marker_id = sw_marker;
1316         }
1317
1318         ice_free(hw, lg_act);
1319         return status;
1320 }
1321
1322 /**
1323  * ice_add_counter_act - add/update filter rule with counter action
1324  * @hw: pointer to the hardware structure
1325  * @m_ent: the management entry for which counter needs to be added
1326  * @counter_id: VLAN counter ID returned as part of allocate resource
1327  * @l_id: large action resource ID
1328  */
1329 static enum ice_status
1330 ice_add_counter_act(struct ice_hw *hw, struct ice_fltr_mgmt_list_entry *m_ent,
1331                     u16 counter_id, u16 l_id)
1332 {
1333         struct ice_aqc_sw_rules_elem *lg_act;
1334         struct ice_aqc_sw_rules_elem *rx_tx;
1335         enum ice_status status;
1336         /* 2 actions will be added while adding a large action counter */
1337         const int num_acts = 2;
1338         u16 lg_act_size;
1339         u16 rules_size;
1340         u16 f_rule_id;
1341         u32 act;
1342         u16 id;
1343
1344         if (m_ent->fltr_info.lkup_type != ICE_SW_LKUP_MAC)
1345                 return ICE_ERR_PARAM;
1346
1347         /* Create two back-to-back switch rules and submit them to the HW using
1348          * one memory buffer:
1349          * 1. Large Action
1350          * 2. Look up Tx Rx
1351          */
1352         lg_act_size = (u16)ICE_SW_RULE_LG_ACT_SIZE(num_acts);
1353         rules_size = lg_act_size + ICE_SW_RULE_RX_TX_ETH_HDR_SIZE;
1354         lg_act = (struct ice_aqc_sw_rules_elem *)ice_malloc(hw, rules_size);
1355         if (!lg_act)
1356                 return ICE_ERR_NO_MEMORY;
1357
1358         rx_tx = (struct ice_aqc_sw_rules_elem *)((u8 *)lg_act + lg_act_size);
1359
1360         /* Fill in the first switch rule i.e. large action */
1361         lg_act->type = CPU_TO_LE16(ICE_AQC_SW_RULES_T_LG_ACT);
1362         lg_act->pdata.lg_act.index = CPU_TO_LE16(l_id);
1363         lg_act->pdata.lg_act.size = CPU_TO_LE16(num_acts);
1364
1365         /* First action VSI forwarding or VSI list forwarding depending on how
1366          * many VSIs
1367          */
1368         id = (m_ent->vsi_count > 1) ?  m_ent->fltr_info.fwd_id.vsi_list_id :
1369                 m_ent->fltr_info.fwd_id.hw_vsi_id;
1370
1371         act = ICE_LG_ACT_VSI_FORWARDING | ICE_LG_ACT_VALID_BIT;
1372         act |= (id << ICE_LG_ACT_VSI_LIST_ID_S) &
1373                 ICE_LG_ACT_VSI_LIST_ID_M;
1374         if (m_ent->vsi_count > 1)
1375                 act |= ICE_LG_ACT_VSI_LIST;
1376         lg_act->pdata.lg_act.act[0] = CPU_TO_LE32(act);
1377
1378         /* Second action counter ID */
1379         act = ICE_LG_ACT_STAT_COUNT;
1380         act |= (counter_id << ICE_LG_ACT_STAT_COUNT_S) &
1381                 ICE_LG_ACT_STAT_COUNT_M;
1382         lg_act->pdata.lg_act.act[1] = CPU_TO_LE32(act);
1383
1384         /* call the fill switch rule to fill the lookup Tx Rx structure */
1385         ice_fill_sw_rule(hw, &m_ent->fltr_info, rx_tx,
1386                          ice_aqc_opc_update_sw_rules);
1387
1388         act = ICE_SINGLE_ACT_PTR;
1389         act |= (l_id << ICE_SINGLE_ACT_PTR_VAL_S) & ICE_SINGLE_ACT_PTR_VAL_M;
1390         rx_tx->pdata.lkup_tx_rx.act = CPU_TO_LE32(act);
1391
1392         /* Use the filter rule ID of the previously created rule with single
1393          * act. Once the update happens, hardware will treat this as large
1394          * action
1395          */
1396         f_rule_id = m_ent->fltr_info.fltr_rule_id;
1397         rx_tx->pdata.lkup_tx_rx.index = CPU_TO_LE16(f_rule_id);
1398
1399         status = ice_aq_sw_rules(hw, lg_act, rules_size, 2,
1400                                  ice_aqc_opc_update_sw_rules, NULL);
1401         if (!status) {
1402                 m_ent->lg_act_idx = l_id;
1403                 m_ent->counter_index = counter_id;
1404         }
1405
1406         ice_free(hw, lg_act);
1407         return status;
1408 }
1409
1410 /**
1411  * ice_create_vsi_list_map
1412  * @hw: pointer to the hardware structure
1413  * @vsi_handle_arr: array of VSI handles to set in the VSI mapping
1414  * @num_vsi: number of VSI handles in the array
1415  * @vsi_list_id: VSI list ID generated as part of allocate resource
1416  *
1417  * Helper function to create a new entry of VSI list ID to VSI mapping
1418  * using the given VSI list ID
1419  */
1420 static struct ice_vsi_list_map_info *
1421 ice_create_vsi_list_map(struct ice_hw *hw, u16 *vsi_handle_arr, u16 num_vsi,
1422                         u16 vsi_list_id)
1423 {
1424         struct ice_switch_info *sw = hw->switch_info;
1425         struct ice_vsi_list_map_info *v_map;
1426         int i;
1427
1428         v_map = (struct ice_vsi_list_map_info *)ice_calloc(hw, 1,
1429                 sizeof(*v_map));
1430         if (!v_map)
1431                 return NULL;
1432
1433         v_map->vsi_list_id = vsi_list_id;
1434         v_map->ref_cnt = 1;
1435         for (i = 0; i < num_vsi; i++)
1436                 ice_set_bit(vsi_handle_arr[i], v_map->vsi_map);
1437
1438         LIST_ADD(&v_map->list_entry, &sw->vsi_list_map_head);
1439         return v_map;
1440 }
1441
1442 /**
1443  * ice_update_vsi_list_rule
1444  * @hw: pointer to the hardware structure
1445  * @vsi_handle_arr: array of VSI handles to form a VSI list
1446  * @num_vsi: number of VSI handles in the array
1447  * @vsi_list_id: VSI list ID generated as part of allocate resource
1448  * @remove: Boolean value to indicate if this is a remove action
1449  * @opc: switch rules population command type - pass in the command opcode
1450  * @lkup_type: lookup type of the filter
1451  *
1452  * Call AQ command to add a new switch rule or update existing switch rule
1453  * using the given VSI list ID
1454  */
1455 static enum ice_status
1456 ice_update_vsi_list_rule(struct ice_hw *hw, u16 *vsi_handle_arr, u16 num_vsi,
1457                          u16 vsi_list_id, bool remove, enum ice_adminq_opc opc,
1458                          enum ice_sw_lkup_type lkup_type)
1459 {
1460         struct ice_aqc_sw_rules_elem *s_rule;
1461         enum ice_status status;
1462         u16 s_rule_size;
1463         u16 rule_type;
1464         int i;
1465
1466         if (!num_vsi)
1467                 return ICE_ERR_PARAM;
1468
1469         if (lkup_type == ICE_SW_LKUP_MAC ||
1470             lkup_type == ICE_SW_LKUP_MAC_VLAN ||
1471             lkup_type == ICE_SW_LKUP_ETHERTYPE ||
1472             lkup_type == ICE_SW_LKUP_ETHERTYPE_MAC ||
1473             lkup_type == ICE_SW_LKUP_PROMISC ||
1474             lkup_type == ICE_SW_LKUP_PROMISC_VLAN ||
1475             lkup_type == ICE_SW_LKUP_LAST)
1476                 rule_type = remove ? ICE_AQC_SW_RULES_T_VSI_LIST_CLEAR :
1477                         ICE_AQC_SW_RULES_T_VSI_LIST_SET;
1478         else if (lkup_type == ICE_SW_LKUP_VLAN)
1479                 rule_type = remove ? ICE_AQC_SW_RULES_T_PRUNE_LIST_CLEAR :
1480                         ICE_AQC_SW_RULES_T_PRUNE_LIST_SET;
1481         else
1482                 return ICE_ERR_PARAM;
1483
1484         s_rule_size = (u16)ICE_SW_RULE_VSI_LIST_SIZE(num_vsi);
1485         s_rule = (struct ice_aqc_sw_rules_elem *)ice_malloc(hw, s_rule_size);
1486         if (!s_rule)
1487                 return ICE_ERR_NO_MEMORY;
1488         for (i = 0; i < num_vsi; i++) {
1489                 if (!ice_is_vsi_valid(hw, vsi_handle_arr[i])) {
1490                         status = ICE_ERR_PARAM;
1491                         goto exit;
1492                 }
1493                 /* AQ call requires hw_vsi_id(s) */
1494                 s_rule->pdata.vsi_list.vsi[i] =
1495                         CPU_TO_LE16(ice_get_hw_vsi_num(hw, vsi_handle_arr[i]));
1496         }
1497
1498         s_rule->type = CPU_TO_LE16(rule_type);
1499         s_rule->pdata.vsi_list.number_vsi = CPU_TO_LE16(num_vsi);
1500         s_rule->pdata.vsi_list.index = CPU_TO_LE16(vsi_list_id);
1501
1502         status = ice_aq_sw_rules(hw, s_rule, s_rule_size, 1, opc, NULL);
1503
1504 exit:
1505         ice_free(hw, s_rule);
1506         return status;
1507 }
1508
1509 /**
1510  * ice_create_vsi_list_rule - Creates and populates a VSI list rule
1511  * @hw: pointer to the HW struct
1512  * @vsi_handle_arr: array of VSI handles to form a VSI list
1513  * @num_vsi: number of VSI handles in the array
1514  * @vsi_list_id: stores the ID of the VSI list to be created
1515  * @lkup_type: switch rule filter's lookup type
1516  */
1517 static enum ice_status
1518 ice_create_vsi_list_rule(struct ice_hw *hw, u16 *vsi_handle_arr, u16 num_vsi,
1519                          u16 *vsi_list_id, enum ice_sw_lkup_type lkup_type)
1520 {
1521         enum ice_status status;
1522
1523         status = ice_aq_alloc_free_vsi_list(hw, vsi_list_id, lkup_type,
1524                                             ice_aqc_opc_alloc_res);
1525         if (status)
1526                 return status;
1527
1528         /* Update the newly created VSI list to include the specified VSIs */
1529         return ice_update_vsi_list_rule(hw, vsi_handle_arr, num_vsi,
1530                                         *vsi_list_id, false,
1531                                         ice_aqc_opc_add_sw_rules, lkup_type);
1532 }
1533
1534 /**
1535  * ice_create_pkt_fwd_rule
1536  * @hw: pointer to the hardware structure
1537  * @recp_list: corresponding filter management list
1538  * @f_entry: entry containing packet forwarding information
1539  *
1540  * Create switch rule with given filter information and add an entry
1541  * to the corresponding filter management list to track this switch rule
1542  * and VSI mapping
1543  */
1544 static enum ice_status
1545 ice_create_pkt_fwd_rule(struct ice_hw *hw, struct ice_sw_recipe *recp_list,
1546                         struct ice_fltr_list_entry *f_entry)
1547 {
1548         struct ice_fltr_mgmt_list_entry *fm_entry;
1549         struct ice_aqc_sw_rules_elem *s_rule;
1550         enum ice_status status;
1551
1552         s_rule = (struct ice_aqc_sw_rules_elem *)
1553                 ice_malloc(hw, ICE_SW_RULE_RX_TX_ETH_HDR_SIZE);
1554         if (!s_rule)
1555                 return ICE_ERR_NO_MEMORY;
1556         fm_entry = (struct ice_fltr_mgmt_list_entry *)
1557                    ice_malloc(hw, sizeof(*fm_entry));
1558         if (!fm_entry) {
1559                 status = ICE_ERR_NO_MEMORY;
1560                 goto ice_create_pkt_fwd_rule_exit;
1561         }
1562
1563         fm_entry->fltr_info = f_entry->fltr_info;
1564
1565         /* Initialize all the fields for the management entry */
1566         fm_entry->vsi_count = 1;
1567         fm_entry->lg_act_idx = ICE_INVAL_LG_ACT_INDEX;
1568         fm_entry->sw_marker_id = ICE_INVAL_SW_MARKER_ID;
1569         fm_entry->counter_index = ICE_INVAL_COUNTER_ID;
1570
1571         ice_fill_sw_rule(hw, &fm_entry->fltr_info, s_rule,
1572                          ice_aqc_opc_add_sw_rules);
1573
1574         status = ice_aq_sw_rules(hw, s_rule, ICE_SW_RULE_RX_TX_ETH_HDR_SIZE, 1,
1575                                  ice_aqc_opc_add_sw_rules, NULL);
1576         if (status) {
1577                 ice_free(hw, fm_entry);
1578                 goto ice_create_pkt_fwd_rule_exit;
1579         }
1580
1581         f_entry->fltr_info.fltr_rule_id =
1582                 LE16_TO_CPU(s_rule->pdata.lkup_tx_rx.index);
1583         fm_entry->fltr_info.fltr_rule_id =
1584                 LE16_TO_CPU(s_rule->pdata.lkup_tx_rx.index);
1585
1586         /* The book keeping entries will get removed when base driver
1587          * calls remove filter AQ command
1588          */
1589         LIST_ADD(&fm_entry->list_entry, &recp_list->filt_rules);
1590
1591 ice_create_pkt_fwd_rule_exit:
1592         ice_free(hw, s_rule);
1593         return status;
1594 }
1595
1596 /**
1597  * ice_update_pkt_fwd_rule
1598  * @hw: pointer to the hardware structure
1599  * @f_info: filter information for switch rule
1600  *
1601  * Call AQ command to update a previously created switch rule with a
1602  * VSI list ID
1603  */
1604 static enum ice_status
1605 ice_update_pkt_fwd_rule(struct ice_hw *hw, struct ice_fltr_info *f_info)
1606 {
1607         struct ice_aqc_sw_rules_elem *s_rule;
1608         enum ice_status status;
1609
1610         s_rule = (struct ice_aqc_sw_rules_elem *)
1611                 ice_malloc(hw, ICE_SW_RULE_RX_TX_ETH_HDR_SIZE);
1612         if (!s_rule)
1613                 return ICE_ERR_NO_MEMORY;
1614
1615         ice_fill_sw_rule(hw, f_info, s_rule, ice_aqc_opc_update_sw_rules);
1616
1617         s_rule->pdata.lkup_tx_rx.index = CPU_TO_LE16(f_info->fltr_rule_id);
1618
1619         /* Update switch rule with new rule set to forward VSI list */
1620         status = ice_aq_sw_rules(hw, s_rule, ICE_SW_RULE_RX_TX_ETH_HDR_SIZE, 1,
1621                                  ice_aqc_opc_update_sw_rules, NULL);
1622
1623         ice_free(hw, s_rule);
1624         return status;
1625 }
1626
1627 /**
1628  * ice_update_sw_rule_bridge_mode
1629  * @hw: pointer to the HW struct
1630  *
1631  * Updates unicast switch filter rules based on VEB/VEPA mode
1632  */
1633 enum ice_status ice_update_sw_rule_bridge_mode(struct ice_hw *hw)
1634 {
1635         struct ice_switch_info *sw = hw->switch_info;
1636         struct ice_fltr_mgmt_list_entry *fm_entry;
1637         enum ice_status status = ICE_SUCCESS;
1638         struct LIST_HEAD_TYPE *rule_head;
1639         struct ice_lock *rule_lock; /* Lock to protect filter rule list */
1640
1641         rule_lock = &sw->recp_list[ICE_SW_LKUP_MAC].filt_rule_lock;
1642         rule_head = &sw->recp_list[ICE_SW_LKUP_MAC].filt_rules;
1643
1644         ice_acquire_lock(rule_lock);
1645         LIST_FOR_EACH_ENTRY(fm_entry, rule_head, ice_fltr_mgmt_list_entry,
1646                             list_entry) {
1647                 struct ice_fltr_info *fi = &fm_entry->fltr_info;
1648                 u8 *addr = fi->l_data.mac.mac_addr;
1649
1650                 /* Update unicast Tx rules to reflect the selected
1651                  * VEB/VEPA mode
1652                  */
1653                 if ((fi->flag & ICE_FLTR_TX) && IS_UNICAST_ETHER_ADDR(addr) &&
1654                     (fi->fltr_act == ICE_FWD_TO_VSI ||
1655                      fi->fltr_act == ICE_FWD_TO_VSI_LIST ||
1656                      fi->fltr_act == ICE_FWD_TO_Q ||
1657                      fi->fltr_act == ICE_FWD_TO_QGRP)) {
1658                         status = ice_update_pkt_fwd_rule(hw, fi);
1659                         if (status)
1660                                 break;
1661                 }
1662         }
1663
1664         ice_release_lock(rule_lock);
1665
1666         return status;
1667 }
1668
1669 /**
1670  * ice_add_update_vsi_list
1671  * @hw: pointer to the hardware structure
1672  * @m_entry: pointer to current filter management list entry
1673  * @cur_fltr: filter information from the book keeping entry
1674  * @new_fltr: filter information with the new VSI to be added
1675  *
1676  * Call AQ command to add or update previously created VSI list with new VSI.
1677  *
1678  * Helper function to do book keeping associated with adding filter information
1679  * The algorithm to do the book keeping is described below :
1680  * When a VSI needs to subscribe to a given filter (MAC/VLAN/Ethtype etc.)
1681  *      if only one VSI has been added till now
1682  *              Allocate a new VSI list and add two VSIs
1683  *              to this list using switch rule command
1684  *              Update the previously created switch rule with the
1685  *              newly created VSI list ID
1686  *      if a VSI list was previously created
1687  *              Add the new VSI to the previously created VSI list set
1688  *              using the update switch rule command
1689  */
1690 static enum ice_status
1691 ice_add_update_vsi_list(struct ice_hw *hw,
1692                         struct ice_fltr_mgmt_list_entry *m_entry,
1693                         struct ice_fltr_info *cur_fltr,
1694                         struct ice_fltr_info *new_fltr)
1695 {
1696         enum ice_status status = ICE_SUCCESS;
1697         u16 vsi_list_id = 0;
1698
1699         if ((cur_fltr->fltr_act == ICE_FWD_TO_Q ||
1700              cur_fltr->fltr_act == ICE_FWD_TO_QGRP))
1701                 return ICE_ERR_NOT_IMPL;
1702
1703         if ((new_fltr->fltr_act == ICE_FWD_TO_Q ||
1704              new_fltr->fltr_act == ICE_FWD_TO_QGRP) &&
1705             (cur_fltr->fltr_act == ICE_FWD_TO_VSI ||
1706              cur_fltr->fltr_act == ICE_FWD_TO_VSI_LIST))
1707                 return ICE_ERR_NOT_IMPL;
1708
1709         if (m_entry->vsi_count < 2 && !m_entry->vsi_list_info) {
1710                 /* Only one entry existed in the mapping and it was not already
1711                  * a part of a VSI list. So, create a VSI list with the old and
1712                  * new VSIs.
1713                  */
1714                 struct ice_fltr_info tmp_fltr;
1715                 u16 vsi_handle_arr[2];
1716
1717                 /* A rule already exists with the new VSI being added */
1718                 if (cur_fltr->fwd_id.hw_vsi_id == new_fltr->fwd_id.hw_vsi_id)
1719                         return ICE_ERR_ALREADY_EXISTS;
1720
1721                 vsi_handle_arr[0] = cur_fltr->vsi_handle;
1722                 vsi_handle_arr[1] = new_fltr->vsi_handle;
1723                 status = ice_create_vsi_list_rule(hw, &vsi_handle_arr[0], 2,
1724                                                   &vsi_list_id,
1725                                                   new_fltr->lkup_type);
1726                 if (status)
1727                         return status;
1728
1729                 tmp_fltr = *new_fltr;
1730                 tmp_fltr.fltr_rule_id = cur_fltr->fltr_rule_id;
1731                 tmp_fltr.fltr_act = ICE_FWD_TO_VSI_LIST;
1732                 tmp_fltr.fwd_id.vsi_list_id = vsi_list_id;
1733                 /* Update the previous switch rule of "MAC forward to VSI" to
1734                  * "MAC fwd to VSI list"
1735                  */
1736                 status = ice_update_pkt_fwd_rule(hw, &tmp_fltr);
1737                 if (status)
1738                         return status;
1739
1740                 cur_fltr->fwd_id.vsi_list_id = vsi_list_id;
1741                 cur_fltr->fltr_act = ICE_FWD_TO_VSI_LIST;
1742                 m_entry->vsi_list_info =
1743                         ice_create_vsi_list_map(hw, &vsi_handle_arr[0], 2,
1744                                                 vsi_list_id);
1745
1746                 /* If this entry was large action then the large action needs
1747                  * to be updated to point to FWD to VSI list
1748                  */
1749                 if (m_entry->sw_marker_id != ICE_INVAL_SW_MARKER_ID)
1750                         status =
1751                             ice_add_marker_act(hw, m_entry,
1752                                                m_entry->sw_marker_id,
1753                                                m_entry->lg_act_idx);
1754         } else {
1755                 u16 vsi_handle = new_fltr->vsi_handle;
1756                 enum ice_adminq_opc opcode;
1757
1758                 if (!m_entry->vsi_list_info)
1759                         return ICE_ERR_CFG;
1760
1761                 /* A rule already exists with the new VSI being added */
1762                 if (ice_is_bit_set(m_entry->vsi_list_info->vsi_map, vsi_handle))
1763                         return ICE_SUCCESS;
1764
1765                 /* Update the previously created VSI list set with
1766                  * the new VSI ID passed in
1767                  */
1768                 vsi_list_id = cur_fltr->fwd_id.vsi_list_id;
1769                 opcode = ice_aqc_opc_update_sw_rules;
1770
1771                 status = ice_update_vsi_list_rule(hw, &vsi_handle, 1,
1772                                                   vsi_list_id, false, opcode,
1773                                                   new_fltr->lkup_type);
1774                 /* update VSI list mapping info with new VSI ID */
1775                 if (!status)
1776                         ice_set_bit(vsi_handle,
1777                                     m_entry->vsi_list_info->vsi_map);
1778         }
1779         if (!status)
1780                 m_entry->vsi_count++;
1781         return status;
1782 }
1783
1784 /**
1785  * ice_find_rule_entry - Search a rule entry
1786  * @list_head: head of rule list
1787  * @f_info: rule information
1788  *
1789  * Helper function to search for a given rule entry
1790  * Returns pointer to entry storing the rule if found
1791  */
1792 static struct ice_fltr_mgmt_list_entry *
1793 ice_find_rule_entry(struct LIST_HEAD_TYPE *list_head,
1794                     struct ice_fltr_info *f_info)
1795 {
1796         struct ice_fltr_mgmt_list_entry *list_itr, *ret = NULL;
1797
1798         LIST_FOR_EACH_ENTRY(list_itr, list_head, ice_fltr_mgmt_list_entry,
1799                             list_entry) {
1800                 if (!memcmp(&f_info->l_data, &list_itr->fltr_info.l_data,
1801                             sizeof(f_info->l_data)) &&
1802                     f_info->flag == list_itr->fltr_info.flag) {
1803                         ret = list_itr;
1804                         break;
1805                 }
1806         }
1807         return ret;
1808 }
1809
1810 /**
1811  * ice_find_vsi_list_entry - Search VSI list map with VSI count 1
1812  * @recp_list: VSI lists needs to be searched
1813  * @vsi_handle: VSI handle to be found in VSI list
1814  * @vsi_list_id: VSI list ID found containing vsi_handle
1815  *
1816  * Helper function to search a VSI list with single entry containing given VSI
1817  * handle element. This can be extended further to search VSI list with more
1818  * than 1 vsi_count. Returns pointer to VSI list entry if found.
1819  */
1820 static struct ice_vsi_list_map_info *
1821 ice_find_vsi_list_entry(struct ice_sw_recipe *recp_list, u16 vsi_handle,
1822                         u16 *vsi_list_id)
1823 {
1824         struct ice_vsi_list_map_info *map_info = NULL;
1825         struct LIST_HEAD_TYPE *list_head;
1826
1827         list_head = &recp_list->filt_rules;
1828         if (recp_list->adv_rule) {
1829                 struct ice_adv_fltr_mgmt_list_entry *list_itr;
1830
1831                 LIST_FOR_EACH_ENTRY(list_itr, list_head,
1832                                     ice_adv_fltr_mgmt_list_entry,
1833                                     list_entry) {
1834                         if (list_itr->vsi_list_info) {
1835                                 map_info = list_itr->vsi_list_info;
1836                                 if (ice_is_bit_set(map_info->vsi_map,
1837                                                    vsi_handle)) {
1838                                         *vsi_list_id = map_info->vsi_list_id;
1839                                         return map_info;
1840                                 }
1841                         }
1842                 }
1843         } else {
1844                 struct ice_fltr_mgmt_list_entry *list_itr;
1845
1846                 LIST_FOR_EACH_ENTRY(list_itr, list_head,
1847                                     ice_fltr_mgmt_list_entry,
1848                                     list_entry) {
1849                         if (list_itr->vsi_count == 1 &&
1850                             list_itr->vsi_list_info) {
1851                                 map_info = list_itr->vsi_list_info;
1852                                 if (ice_is_bit_set(map_info->vsi_map,
1853                                                    vsi_handle)) {
1854                                         *vsi_list_id = map_info->vsi_list_id;
1855                                         return map_info;
1856                                 }
1857                         }
1858                 }
1859         }
1860         return NULL;
1861 }
1862
1863 /**
1864  * ice_add_rule_internal - add rule for a given lookup type
1865  * @hw: pointer to the hardware structure
1866  * @recp_list: recipe list for which rule has to be added
1867  * @lport: logic port number on which function add rule
1868  * @f_entry: structure containing MAC forwarding information
1869  *
1870  * Adds or updates the rule lists for a given recipe
1871  */
1872 static enum ice_status
1873 ice_add_rule_internal(struct ice_hw *hw, struct ice_sw_recipe *recp_list,
1874                       u8 lport, struct ice_fltr_list_entry *f_entry)
1875 {
1876         struct ice_fltr_info *new_fltr, *cur_fltr;
1877         struct ice_fltr_mgmt_list_entry *m_entry;
1878         struct ice_lock *rule_lock; /* Lock to protect filter rule list */
1879         enum ice_status status = ICE_SUCCESS;
1880
1881         if (!ice_is_vsi_valid(hw, f_entry->fltr_info.vsi_handle))
1882                 return ICE_ERR_PARAM;
1883
1884         /* Load the hw_vsi_id only if the fwd action is fwd to VSI */
1885         if (f_entry->fltr_info.fltr_act == ICE_FWD_TO_VSI)
1886                 f_entry->fltr_info.fwd_id.hw_vsi_id =
1887                         ice_get_hw_vsi_num(hw, f_entry->fltr_info.vsi_handle);
1888
1889         rule_lock = &recp_list->filt_rule_lock;
1890
1891         ice_acquire_lock(rule_lock);
1892         new_fltr = &f_entry->fltr_info;
1893         if (new_fltr->flag & ICE_FLTR_RX)
1894                 new_fltr->src = lport;
1895         else if (new_fltr->flag & ICE_FLTR_TX)
1896                 new_fltr->src =
1897                         ice_get_hw_vsi_num(hw, f_entry->fltr_info.vsi_handle);
1898
1899         m_entry = ice_find_rule_entry(&recp_list->filt_rules, new_fltr);
1900         if (!m_entry) {
1901                 status = ice_create_pkt_fwd_rule(hw, recp_list, f_entry);
1902                 goto exit_add_rule_internal;
1903         }
1904
1905         cur_fltr = &m_entry->fltr_info;
1906         status = ice_add_update_vsi_list(hw, m_entry, cur_fltr, new_fltr);
1907
1908 exit_add_rule_internal:
1909         ice_release_lock(rule_lock);
1910         return status;
1911 }
1912
1913 /**
1914  * ice_remove_vsi_list_rule
1915  * @hw: pointer to the hardware structure
1916  * @vsi_list_id: VSI list ID generated as part of allocate resource
1917  * @lkup_type: switch rule filter lookup type
1918  *
1919  * The VSI list should be emptied before this function is called to remove the
1920  * VSI list.
1921  */
1922 static enum ice_status
1923 ice_remove_vsi_list_rule(struct ice_hw *hw, u16 vsi_list_id,
1924                          enum ice_sw_lkup_type lkup_type)
1925 {
1926         /* Free the vsi_list resource that we allocated. It is assumed that the
1927          * list is empty at this point.
1928          */
1929         return ice_aq_alloc_free_vsi_list(hw, &vsi_list_id, lkup_type,
1930                                             ice_aqc_opc_free_res);
1931 }
1932
1933 /**
1934  * ice_rem_update_vsi_list
1935  * @hw: pointer to the hardware structure
1936  * @vsi_handle: VSI handle of the VSI to remove
1937  * @fm_list: filter management entry for which the VSI list management needs to
1938  *           be done
1939  */
1940 static enum ice_status
1941 ice_rem_update_vsi_list(struct ice_hw *hw, u16 vsi_handle,
1942                         struct ice_fltr_mgmt_list_entry *fm_list)
1943 {
1944         enum ice_sw_lkup_type lkup_type;
1945         enum ice_status status = ICE_SUCCESS;
1946         u16 vsi_list_id;
1947
1948         if (fm_list->fltr_info.fltr_act != ICE_FWD_TO_VSI_LIST ||
1949             fm_list->vsi_count == 0)
1950                 return ICE_ERR_PARAM;
1951
1952         /* A rule with the VSI being removed does not exist */
1953         if (!ice_is_bit_set(fm_list->vsi_list_info->vsi_map, vsi_handle))
1954                 return ICE_ERR_DOES_NOT_EXIST;
1955
1956         lkup_type = fm_list->fltr_info.lkup_type;
1957         vsi_list_id = fm_list->fltr_info.fwd_id.vsi_list_id;
1958         status = ice_update_vsi_list_rule(hw, &vsi_handle, 1, vsi_list_id, true,
1959                                           ice_aqc_opc_update_sw_rules,
1960                                           lkup_type);
1961         if (status)
1962                 return status;
1963
1964         fm_list->vsi_count--;
1965         ice_clear_bit(vsi_handle, fm_list->vsi_list_info->vsi_map);
1966
1967         if (fm_list->vsi_count == 1 && lkup_type != ICE_SW_LKUP_VLAN) {
1968                 struct ice_fltr_info tmp_fltr_info = fm_list->fltr_info;
1969                 struct ice_vsi_list_map_info *vsi_list_info =
1970                         fm_list->vsi_list_info;
1971                 u16 rem_vsi_handle;
1972
1973                 rem_vsi_handle = ice_find_first_bit(vsi_list_info->vsi_map,
1974                                                     ICE_MAX_VSI);
1975                 if (!ice_is_vsi_valid(hw, rem_vsi_handle))
1976                         return ICE_ERR_OUT_OF_RANGE;
1977
1978                 /* Make sure VSI list is empty before removing it below */
1979                 status = ice_update_vsi_list_rule(hw, &rem_vsi_handle, 1,
1980                                                   vsi_list_id, true,
1981                                                   ice_aqc_opc_update_sw_rules,
1982                                                   lkup_type);
1983                 if (status)
1984                         return status;
1985
1986                 tmp_fltr_info.fltr_act = ICE_FWD_TO_VSI;
1987                 tmp_fltr_info.fwd_id.hw_vsi_id =
1988                         ice_get_hw_vsi_num(hw, rem_vsi_handle);
1989                 tmp_fltr_info.vsi_handle = rem_vsi_handle;
1990                 status = ice_update_pkt_fwd_rule(hw, &tmp_fltr_info);
1991                 if (status) {
1992                         ice_debug(hw, ICE_DBG_SW, "Failed to update pkt fwd rule to FWD_TO_VSI on HW VSI %d, error %d\n",
1993                                   tmp_fltr_info.fwd_id.hw_vsi_id, status);
1994                         return status;
1995                 }
1996
1997                 fm_list->fltr_info = tmp_fltr_info;
1998         }
1999
2000         if ((fm_list->vsi_count == 1 && lkup_type != ICE_SW_LKUP_VLAN) ||
2001             (fm_list->vsi_count == 0 && lkup_type == ICE_SW_LKUP_VLAN)) {
2002                 struct ice_vsi_list_map_info *vsi_list_info =
2003                         fm_list->vsi_list_info;
2004
2005                 /* Remove the VSI list since it is no longer used */
2006                 status = ice_remove_vsi_list_rule(hw, vsi_list_id, lkup_type);
2007                 if (status) {
2008                         ice_debug(hw, ICE_DBG_SW, "Failed to remove VSI list %d, error %d\n",
2009                                   vsi_list_id, status);
2010                         return status;
2011                 }
2012
2013                 LIST_DEL(&vsi_list_info->list_entry);
2014                 ice_free(hw, vsi_list_info);
2015                 fm_list->vsi_list_info = NULL;
2016         }
2017
2018         return status;
2019 }
2020
2021 /**
2022  * ice_remove_rule_internal - Remove a filter rule of a given type
2023  *
2024  * @hw: pointer to the hardware structure
2025  * @recp_list: recipe list for which the rule needs to removed
2026  * @f_entry: rule entry containing filter information
2027  */
2028 static enum ice_status
2029 ice_remove_rule_internal(struct ice_hw *hw, struct ice_sw_recipe *recp_list,
2030                          struct ice_fltr_list_entry *f_entry)
2031 {
2032         struct ice_fltr_mgmt_list_entry *list_elem;
2033         struct ice_lock *rule_lock; /* Lock to protect filter rule list */
2034         enum ice_status status = ICE_SUCCESS;
2035         bool remove_rule = false;
2036         u16 vsi_handle;
2037
2038         if (!ice_is_vsi_valid(hw, f_entry->fltr_info.vsi_handle))
2039                 return ICE_ERR_PARAM;
2040         f_entry->fltr_info.fwd_id.hw_vsi_id =
2041                 ice_get_hw_vsi_num(hw, f_entry->fltr_info.vsi_handle);
2042
2043         rule_lock = &recp_list->filt_rule_lock;
2044         ice_acquire_lock(rule_lock);
2045         list_elem = ice_find_rule_entry(&recp_list->filt_rules,
2046                                         &f_entry->fltr_info);
2047         if (!list_elem) {
2048                 status = ICE_ERR_DOES_NOT_EXIST;
2049                 goto exit;
2050         }
2051
2052         if (list_elem->fltr_info.fltr_act != ICE_FWD_TO_VSI_LIST) {
2053                 remove_rule = true;
2054         } else if (!list_elem->vsi_list_info) {
2055                 status = ICE_ERR_DOES_NOT_EXIST;
2056                 goto exit;
2057         } else if (list_elem->vsi_list_info->ref_cnt > 1) {
2058                 /* a ref_cnt > 1 indicates that the vsi_list is being
2059                  * shared by multiple rules. Decrement the ref_cnt and
2060                  * remove this rule, but do not modify the list, as it
2061                  * is in-use by other rules.
2062                  */
2063                 list_elem->vsi_list_info->ref_cnt--;
2064                 remove_rule = true;
2065         } else {
2066                 /* a ref_cnt of 1 indicates the vsi_list is only used
2067                  * by one rule. However, the original removal request is only
2068                  * for a single VSI. Update the vsi_list first, and only
2069                  * remove the rule if there are no further VSIs in this list.
2070                  */
2071                 vsi_handle = f_entry->fltr_info.vsi_handle;
2072                 status = ice_rem_update_vsi_list(hw, vsi_handle, list_elem);
2073                 if (status)
2074                         goto exit;
2075                 /* if VSI count goes to zero after updating the VSI list */
2076                 if (list_elem->vsi_count == 0)
2077                         remove_rule = true;
2078         }
2079
2080         if (remove_rule) {
2081                 /* Remove the lookup rule */
2082                 struct ice_aqc_sw_rules_elem *s_rule;
2083
2084                 s_rule = (struct ice_aqc_sw_rules_elem *)
2085                         ice_malloc(hw, ICE_SW_RULE_RX_TX_NO_HDR_SIZE);
2086                 if (!s_rule) {
2087                         status = ICE_ERR_NO_MEMORY;
2088                         goto exit;
2089                 }
2090
2091                 ice_fill_sw_rule(hw, &list_elem->fltr_info, s_rule,
2092                                  ice_aqc_opc_remove_sw_rules);
2093
2094                 status = ice_aq_sw_rules(hw, s_rule,
2095                                          ICE_SW_RULE_RX_TX_NO_HDR_SIZE, 1,
2096                                          ice_aqc_opc_remove_sw_rules, NULL);
2097
2098                 /* Remove a book keeping from the list */
2099                 ice_free(hw, s_rule);
2100
2101                 if (status)
2102                         goto exit;
2103
2104                 LIST_DEL(&list_elem->list_entry);
2105                 ice_free(hw, list_elem);
2106         }
2107 exit:
2108         ice_release_lock(rule_lock);
2109         return status;
2110 }
2111
2112 /**
2113  * ice_aq_get_res_alloc - get allocated resources
2114  * @hw: pointer to the HW struct
2115  * @num_entries: pointer to u16 to store the number of resource entries returned
2116  * @buf: pointer to buffer
2117  * @buf_size: size of buf
2118  * @cd: pointer to command details structure or NULL
2119  *
2120  * The caller-supplied buffer must be large enough to store the resource
2121  * information for all resource types. Each resource type is an
2122  * ice_aqc_get_res_resp_elem structure.
2123  */
2124 enum ice_status
2125 ice_aq_get_res_alloc(struct ice_hw *hw, u16 *num_entries,
2126                      struct ice_aqc_get_res_resp_elem *buf, u16 buf_size,
2127                      struct ice_sq_cd *cd)
2128 {
2129         struct ice_aqc_get_res_alloc *resp;
2130         enum ice_status status;
2131         struct ice_aq_desc desc;
2132
2133         if (!buf)
2134                 return ICE_ERR_BAD_PTR;
2135
2136         if (buf_size < ICE_AQ_GET_RES_ALLOC_BUF_LEN)
2137                 return ICE_ERR_INVAL_SIZE;
2138
2139         resp = &desc.params.get_res;
2140
2141         ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_get_res_alloc);
2142         status = ice_aq_send_cmd(hw, &desc, buf, buf_size, cd);
2143
2144         if (!status && num_entries)
2145                 *num_entries = LE16_TO_CPU(resp->resp_elem_num);
2146
2147         return status;
2148 }
2149
2150 /**
2151  * ice_aq_get_res_descs - get allocated resource descriptors
2152  * @hw: pointer to the hardware structure
2153  * @num_entries: number of resource entries in buffer
2154  * @buf: structure to hold response data buffer
2155  * @buf_size: size of buffer
2156  * @res_type: resource type
2157  * @res_shared: is resource shared
2158  * @desc_id: input - first desc ID to start; output - next desc ID
2159  * @cd: pointer to command details structure or NULL
2160  */
2161 enum ice_status
2162 ice_aq_get_res_descs(struct ice_hw *hw, u16 num_entries,
2163                      struct ice_aqc_res_elem *buf, u16 buf_size, u16 res_type,
2164                      bool res_shared, u16 *desc_id, struct ice_sq_cd *cd)
2165 {
2166         struct ice_aqc_get_allocd_res_desc *cmd;
2167         struct ice_aq_desc desc;
2168         enum ice_status status;
2169
2170         ice_debug(hw, ICE_DBG_TRACE, "%s\n", __func__);
2171
2172         cmd = &desc.params.get_res_desc;
2173
2174         if (!buf)
2175                 return ICE_ERR_PARAM;
2176
2177         if (buf_size != (num_entries * sizeof(*buf)))
2178                 return ICE_ERR_PARAM;
2179
2180         ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_get_allocd_res_desc);
2181
2182         cmd->ops.cmd.res = CPU_TO_LE16(((res_type << ICE_AQC_RES_TYPE_S) &
2183                                          ICE_AQC_RES_TYPE_M) | (res_shared ?
2184                                         ICE_AQC_RES_TYPE_FLAG_SHARED : 0));
2185         cmd->ops.cmd.first_desc = CPU_TO_LE16(*desc_id);
2186
2187         status = ice_aq_send_cmd(hw, &desc, buf, buf_size, cd);
2188         if (!status)
2189                 *desc_id = LE16_TO_CPU(cmd->ops.resp.next_desc);
2190
2191         return status;
2192 }
2193
2194 /**
2195  * ice_add_mac_rule - Add a MAC address based filter rule
2196  * @hw: pointer to the hardware structure
2197  * @m_list: list of MAC addresses and forwarding information
2198  * @sw: pointer to switch info struct for which function add rule
2199  * @lport: logic port number on which function add rule
2200  *
2201  * IMPORTANT: When the ucast_shared flag is set to false and m_list has
2202  * multiple unicast addresses, the function assumes that all the
2203  * addresses are unique in a given add_mac call. It doesn't
2204  * check for duplicates in this case, removing duplicates from a given
2205  * list should be taken care of in the caller of this function.
2206  */
2207 static enum ice_status
2208 ice_add_mac_rule(struct ice_hw *hw, struct LIST_HEAD_TYPE *m_list,
2209                  struct ice_switch_info *sw, u8 lport)
2210 {
2211         struct ice_sw_recipe *recp_list = &sw->recp_list[ICE_SW_LKUP_MAC];
2212         struct ice_aqc_sw_rules_elem *s_rule, *r_iter;
2213         struct ice_fltr_list_entry *m_list_itr;
2214         struct LIST_HEAD_TYPE *rule_head;
2215         u16 total_elem_left, s_rule_size;
2216         struct ice_lock *rule_lock; /* Lock to protect filter rule list */
2217         enum ice_status status = ICE_SUCCESS;
2218         u16 num_unicast = 0;
2219         u8 elem_sent;
2220
2221         s_rule = NULL;
2222         rule_lock = &recp_list->filt_rule_lock;
2223         rule_head = &recp_list->filt_rules;
2224
2225         LIST_FOR_EACH_ENTRY(m_list_itr, m_list, ice_fltr_list_entry,
2226                             list_entry) {
2227                 u8 *add = &m_list_itr->fltr_info.l_data.mac.mac_addr[0];
2228                 u16 vsi_handle;
2229                 u16 hw_vsi_id;
2230
2231                 m_list_itr->fltr_info.flag = ICE_FLTR_TX;
2232                 vsi_handle = m_list_itr->fltr_info.vsi_handle;
2233                 if (!ice_is_vsi_valid(hw, vsi_handle))
2234                         return ICE_ERR_PARAM;
2235                 hw_vsi_id = ice_get_hw_vsi_num(hw, vsi_handle);
2236                 m_list_itr->fltr_info.fwd_id.hw_vsi_id = hw_vsi_id;
2237                 /* update the src in case it is VSI num */
2238                 if (m_list_itr->fltr_info.src_id != ICE_SRC_ID_VSI)
2239                         return ICE_ERR_PARAM;
2240                 m_list_itr->fltr_info.src = hw_vsi_id;
2241                 if (m_list_itr->fltr_info.lkup_type != ICE_SW_LKUP_MAC ||
2242                     IS_ZERO_ETHER_ADDR(add))
2243                         return ICE_ERR_PARAM;
2244                 if (IS_UNICAST_ETHER_ADDR(add) && !hw->ucast_shared) {
2245                         /* Don't overwrite the unicast address */
2246                         ice_acquire_lock(rule_lock);
2247                         if (ice_find_rule_entry(rule_head,
2248                                                 &m_list_itr->fltr_info)) {
2249                                 ice_release_lock(rule_lock);
2250                                 return ICE_ERR_ALREADY_EXISTS;
2251                         }
2252                         ice_release_lock(rule_lock);
2253                         num_unicast++;
2254                 } else if (IS_MULTICAST_ETHER_ADDR(add) ||
2255                            (IS_UNICAST_ETHER_ADDR(add) && hw->ucast_shared)) {
2256                         m_list_itr->status =
2257                                 ice_add_rule_internal(hw, recp_list, lport,
2258                                                       m_list_itr);
2259                         if (m_list_itr->status)
2260                                 return m_list_itr->status;
2261                 }
2262         }
2263
2264         ice_acquire_lock(rule_lock);
2265         /* Exit if no suitable entries were found for adding bulk switch rule */
2266         if (!num_unicast) {
2267                 status = ICE_SUCCESS;
2268                 goto ice_add_mac_exit;
2269         }
2270
2271         /* Allocate switch rule buffer for the bulk update for unicast */
2272         s_rule_size = ICE_SW_RULE_RX_TX_ETH_HDR_SIZE;
2273         s_rule = (struct ice_aqc_sw_rules_elem *)
2274                 ice_calloc(hw, num_unicast, s_rule_size);
2275         if (!s_rule) {
2276                 status = ICE_ERR_NO_MEMORY;
2277                 goto ice_add_mac_exit;
2278         }
2279
2280         r_iter = s_rule;
2281         LIST_FOR_EACH_ENTRY(m_list_itr, m_list, ice_fltr_list_entry,
2282                             list_entry) {
2283                 struct ice_fltr_info *f_info = &m_list_itr->fltr_info;
2284                 u8 *mac_addr = &f_info->l_data.mac.mac_addr[0];
2285
2286                 if (IS_UNICAST_ETHER_ADDR(mac_addr)) {
2287                         ice_fill_sw_rule(hw, &m_list_itr->fltr_info, r_iter,
2288                                          ice_aqc_opc_add_sw_rules);
2289                         r_iter = (struct ice_aqc_sw_rules_elem *)
2290                                 ((u8 *)r_iter + s_rule_size);
2291                 }
2292         }
2293
2294         /* Call AQ bulk switch rule update for all unicast addresses */
2295         r_iter = s_rule;
2296         /* Call AQ switch rule in AQ_MAX chunk */
2297         for (total_elem_left = num_unicast; total_elem_left > 0;
2298              total_elem_left -= elem_sent) {
2299                 struct ice_aqc_sw_rules_elem *entry = r_iter;
2300
2301                 elem_sent = MIN_T(u8, total_elem_left,
2302                                   (ICE_AQ_MAX_BUF_LEN / s_rule_size));
2303                 status = ice_aq_sw_rules(hw, entry, elem_sent * s_rule_size,
2304                                          elem_sent, ice_aqc_opc_add_sw_rules,
2305                                          NULL);
2306                 if (status)
2307                         goto ice_add_mac_exit;
2308                 r_iter = (struct ice_aqc_sw_rules_elem *)
2309                         ((u8 *)r_iter + (elem_sent * s_rule_size));
2310         }
2311
2312         /* Fill up rule ID based on the value returned from FW */
2313         r_iter = s_rule;
2314         LIST_FOR_EACH_ENTRY(m_list_itr, m_list, ice_fltr_list_entry,
2315                             list_entry) {
2316                 struct ice_fltr_info *f_info = &m_list_itr->fltr_info;
2317                 u8 *mac_addr = &f_info->l_data.mac.mac_addr[0];
2318                 struct ice_fltr_mgmt_list_entry *fm_entry;
2319
2320                 if (IS_UNICAST_ETHER_ADDR(mac_addr)) {
2321                         f_info->fltr_rule_id =
2322                                 LE16_TO_CPU(r_iter->pdata.lkup_tx_rx.index);
2323                         f_info->fltr_act = ICE_FWD_TO_VSI;
2324                         /* Create an entry to track this MAC address */
2325                         fm_entry = (struct ice_fltr_mgmt_list_entry *)
2326                                 ice_malloc(hw, sizeof(*fm_entry));
2327                         if (!fm_entry) {
2328                                 status = ICE_ERR_NO_MEMORY;
2329                                 goto ice_add_mac_exit;
2330                         }
2331                         fm_entry->fltr_info = *f_info;
2332                         fm_entry->vsi_count = 1;
2333                         /* The book keeping entries will get removed when
2334                          * base driver calls remove filter AQ command
2335                          */
2336
2337                         LIST_ADD(&fm_entry->list_entry, rule_head);
2338                         r_iter = (struct ice_aqc_sw_rules_elem *)
2339                                 ((u8 *)r_iter + s_rule_size);
2340                 }
2341         }
2342
2343 ice_add_mac_exit:
2344         ice_release_lock(rule_lock);
2345         if (s_rule)
2346                 ice_free(hw, s_rule);
2347         return status;
2348 }
2349
2350 /**
2351  * ice_add_mac - Add a MAC address based filter rule
2352  * @hw: pointer to the hardware structure
2353  * @m_list: list of MAC addresses and forwarding information
2354  *
2355  * Function add MAC rule for logical port from HW struct
2356  */
2357 enum ice_status ice_add_mac(struct ice_hw *hw, struct LIST_HEAD_TYPE *m_list)
2358 {
2359         if (!m_list || !hw)
2360                 return ICE_ERR_PARAM;
2361
2362         return ice_add_mac_rule(hw, m_list, hw->switch_info,
2363                                 hw->port_info->lport);
2364 }
2365
2366 /**
2367  * ice_add_vlan_internal - Add one VLAN based filter rule
2368  * @hw: pointer to the hardware structure
2369  * @recp_list: recipe list for which rule has to be added
2370  * @f_entry: filter entry containing one VLAN information
2371  */
2372 static enum ice_status
2373 ice_add_vlan_internal(struct ice_hw *hw, struct ice_sw_recipe *recp_list,
2374                       struct ice_fltr_list_entry *f_entry)
2375 {
2376         struct ice_fltr_mgmt_list_entry *v_list_itr;
2377         struct ice_fltr_info *new_fltr, *cur_fltr;
2378         enum ice_sw_lkup_type lkup_type;
2379         u16 vsi_list_id = 0, vsi_handle;
2380         struct ice_lock *rule_lock; /* Lock to protect filter rule list */
2381         enum ice_status status = ICE_SUCCESS;
2382
2383         if (!ice_is_vsi_valid(hw, f_entry->fltr_info.vsi_handle))
2384                 return ICE_ERR_PARAM;
2385
2386         f_entry->fltr_info.fwd_id.hw_vsi_id =
2387                 ice_get_hw_vsi_num(hw, f_entry->fltr_info.vsi_handle);
2388         new_fltr = &f_entry->fltr_info;
2389
2390         /* VLAN ID should only be 12 bits */
2391         if (new_fltr->l_data.vlan.vlan_id > ICE_MAX_VLAN_ID)
2392                 return ICE_ERR_PARAM;
2393
2394         if (new_fltr->src_id != ICE_SRC_ID_VSI)
2395                 return ICE_ERR_PARAM;
2396
2397         new_fltr->src = new_fltr->fwd_id.hw_vsi_id;
2398         lkup_type = new_fltr->lkup_type;
2399         vsi_handle = new_fltr->vsi_handle;
2400         rule_lock = &recp_list->filt_rule_lock;
2401         ice_acquire_lock(rule_lock);
2402         v_list_itr = ice_find_rule_entry(&recp_list->filt_rules, new_fltr);
2403         if (!v_list_itr) {
2404                 struct ice_vsi_list_map_info *map_info = NULL;
2405
2406                 if (new_fltr->fltr_act == ICE_FWD_TO_VSI) {
2407                         /* All VLAN pruning rules use a VSI list. Check if
2408                          * there is already a VSI list containing VSI that we
2409                          * want to add. If found, use the same vsi_list_id for
2410                          * this new VLAN rule or else create a new list.
2411                          */
2412                         map_info = ice_find_vsi_list_entry(recp_list,
2413                                                            vsi_handle,
2414                                                            &vsi_list_id);
2415                         if (!map_info) {
2416                                 status = ice_create_vsi_list_rule(hw,
2417                                                                   &vsi_handle,
2418                                                                   1,
2419                                                                   &vsi_list_id,
2420                                                                   lkup_type);
2421                                 if (status)
2422                                         goto exit;
2423                         }
2424                         /* Convert the action to forwarding to a VSI list. */
2425                         new_fltr->fltr_act = ICE_FWD_TO_VSI_LIST;
2426                         new_fltr->fwd_id.vsi_list_id = vsi_list_id;
2427                 }
2428
2429                 status = ice_create_pkt_fwd_rule(hw, recp_list, f_entry);
2430                 if (!status) {
2431                         v_list_itr = ice_find_rule_entry(&recp_list->filt_rules,
2432                                                          new_fltr);
2433                         if (!v_list_itr) {
2434                                 status = ICE_ERR_DOES_NOT_EXIST;
2435                                 goto exit;
2436                         }
2437                         /* reuse VSI list for new rule and increment ref_cnt */
2438                         if (map_info) {
2439                                 v_list_itr->vsi_list_info = map_info;
2440                                 map_info->ref_cnt++;
2441                         } else {
2442                                 v_list_itr->vsi_list_info =
2443                                         ice_create_vsi_list_map(hw, &vsi_handle,
2444                                                                 1, vsi_list_id);
2445                         }
2446                 }
2447         } else if (v_list_itr->vsi_list_info->ref_cnt == 1) {
2448                 /* Update existing VSI list to add new VSI ID only if it used
2449                  * by one VLAN rule.
2450                  */
2451                 cur_fltr = &v_list_itr->fltr_info;
2452                 status = ice_add_update_vsi_list(hw, v_list_itr, cur_fltr,
2453                                                  new_fltr);
2454         } else {
2455                 /* If VLAN rule exists and VSI list being used by this rule is
2456                  * referenced by more than 1 VLAN rule. Then create a new VSI
2457                  * list appending previous VSI with new VSI and update existing
2458                  * VLAN rule to point to new VSI list ID
2459                  */
2460                 struct ice_fltr_info tmp_fltr;
2461                 u16 vsi_handle_arr[2];
2462                 u16 cur_handle;
2463
2464                 /* Current implementation only supports reusing VSI list with
2465                  * one VSI count. We should never hit below condition
2466                  */
2467                 if (v_list_itr->vsi_count > 1 &&
2468                     v_list_itr->vsi_list_info->ref_cnt > 1) {
2469                         ice_debug(hw, ICE_DBG_SW, "Invalid configuration: Optimization to reuse VSI list with more than one VSI is not being done yet\n");
2470                         status = ICE_ERR_CFG;
2471                         goto exit;
2472                 }
2473
2474                 cur_handle =
2475                         ice_find_first_bit(v_list_itr->vsi_list_info->vsi_map,
2476                                            ICE_MAX_VSI);
2477
2478                 /* A rule already exists with the new VSI being added */
2479                 if (cur_handle == vsi_handle) {
2480                         status = ICE_ERR_ALREADY_EXISTS;
2481                         goto exit;
2482                 }
2483
2484                 vsi_handle_arr[0] = cur_handle;
2485                 vsi_handle_arr[1] = vsi_handle;
2486                 status = ice_create_vsi_list_rule(hw, &vsi_handle_arr[0], 2,
2487                                                   &vsi_list_id, lkup_type);
2488                 if (status)
2489                         goto exit;
2490
2491                 tmp_fltr = v_list_itr->fltr_info;
2492                 tmp_fltr.fltr_rule_id = v_list_itr->fltr_info.fltr_rule_id;
2493                 tmp_fltr.fwd_id.vsi_list_id = vsi_list_id;
2494                 tmp_fltr.fltr_act = ICE_FWD_TO_VSI_LIST;
2495                 /* Update the previous switch rule to a new VSI list which
2496                  * includes current VSI that is requested
2497                  */
2498                 status = ice_update_pkt_fwd_rule(hw, &tmp_fltr);
2499                 if (status)
2500                         goto exit;
2501
2502                 /* before overriding VSI list map info. decrement ref_cnt of
2503                  * previous VSI list
2504                  */
2505                 v_list_itr->vsi_list_info->ref_cnt--;
2506
2507                 /* now update to newly created list */
2508                 v_list_itr->fltr_info.fwd_id.vsi_list_id = vsi_list_id;
2509                 v_list_itr->vsi_list_info =
2510                         ice_create_vsi_list_map(hw, &vsi_handle_arr[0], 2,
2511                                                 vsi_list_id);
2512                 v_list_itr->vsi_count++;
2513         }
2514
2515 exit:
2516         ice_release_lock(rule_lock);
2517         return status;
2518 }
2519
2520 /**
2521  * ice_add_vlan_rule - Add VLAN based filter rule
2522  * @hw: pointer to the hardware structure
2523  * @v_list: list of VLAN entries and forwarding information
2524  * @sw: pointer to switch info struct for which function add rule
2525  */
2526 static enum ice_status
2527 ice_add_vlan_rule(struct ice_hw *hw, struct LIST_HEAD_TYPE *v_list,
2528                   struct ice_switch_info *sw)
2529 {
2530         struct ice_fltr_list_entry *v_list_itr;
2531         struct ice_sw_recipe *recp_list;
2532
2533         recp_list = &sw->recp_list[ICE_SW_LKUP_VLAN];
2534         LIST_FOR_EACH_ENTRY(v_list_itr, v_list, ice_fltr_list_entry,
2535                             list_entry) {
2536                 if (v_list_itr->fltr_info.lkup_type != ICE_SW_LKUP_VLAN)
2537                         return ICE_ERR_PARAM;
2538                 v_list_itr->fltr_info.flag = ICE_FLTR_TX;
2539                 v_list_itr->status = ice_add_vlan_internal(hw, recp_list,
2540                                                            v_list_itr);
2541                 if (v_list_itr->status)
2542                         return v_list_itr->status;
2543         }
2544         return ICE_SUCCESS;
2545 }
2546
2547 /**
2548  * ice_add_vlan - Add a VLAN based filter rule
2549  * @hw: pointer to the hardware structure
2550  * @v_list: list of VLAN and forwarding information
2551  *
2552  * Function add VLAN rule for logical port from HW struct
2553  */
2554 enum ice_status ice_add_vlan(struct ice_hw *hw, struct LIST_HEAD_TYPE *v_list)
2555 {
2556         if (!v_list || !hw)
2557                 return ICE_ERR_PARAM;
2558
2559         return ice_add_vlan_rule(hw, v_list, hw->switch_info);
2560 }
2561
2562 /**
2563  * ice_add_eth_mac_rule - Add ethertype and MAC based filter rule
2564  * @hw: pointer to the hardware structure
2565  * @em_list: list of ether type MAC filter, MAC is optional
2566  * @sw: pointer to switch info struct for which function add rule
2567  * @lport: logic port number on which function add rule
2568  *
2569  * This function requires the caller to populate the entries in
2570  * the filter list with the necessary fields (including flags to
2571  * indicate Tx or Rx rules).
2572  */
2573 static enum ice_status
2574 ice_add_eth_mac_rule(struct ice_hw *hw, struct LIST_HEAD_TYPE *em_list,
2575                      struct ice_switch_info *sw, u8 lport)
2576 {
2577         struct ice_fltr_list_entry *em_list_itr;
2578
2579         LIST_FOR_EACH_ENTRY(em_list_itr, em_list, ice_fltr_list_entry,
2580                             list_entry) {
2581                 struct ice_sw_recipe *recp_list;
2582                 enum ice_sw_lkup_type l_type;
2583
2584                 l_type = em_list_itr->fltr_info.lkup_type;
2585                 recp_list = &sw->recp_list[l_type];
2586
2587                 if (l_type != ICE_SW_LKUP_ETHERTYPE_MAC &&
2588                     l_type != ICE_SW_LKUP_ETHERTYPE)
2589                         return ICE_ERR_PARAM;
2590
2591                 em_list_itr->status = ice_add_rule_internal(hw, recp_list,
2592                                                             lport,
2593                                                             em_list_itr);
2594                 if (em_list_itr->status)
2595                         return em_list_itr->status;
2596         }
2597         return ICE_SUCCESS;
2598 }
2599
2600 /**
2601  * ice_add_eth_mac - Add a ethertype based filter rule
2602  * @hw: pointer to the hardware structure
2603  * @em_list: list of ethertype and forwarding information
2604  *
2605  * Function add ethertype rule for logical port from HW struct
2606  */
2607 enum ice_status
2608 ice_add_eth_mac(struct ice_hw *hw, struct LIST_HEAD_TYPE *em_list)
2609 {
2610         if (!em_list || !hw)
2611                 return ICE_ERR_PARAM;
2612
2613         return ice_add_eth_mac_rule(hw, em_list, hw->switch_info,
2614                                     hw->port_info->lport);
2615 }
2616
2617 /**
2618  * ice_remove_eth_mac_rule - Remove an ethertype (or MAC) based filter rule
2619  * @hw: pointer to the hardware structure
2620  * @em_list: list of ethertype or ethertype MAC entries
2621  * @sw: pointer to switch info struct for which function add rule
2622  */
2623 static enum ice_status
2624 ice_remove_eth_mac_rule(struct ice_hw *hw, struct LIST_HEAD_TYPE *em_list,
2625                         struct ice_switch_info *sw)
2626 {
2627         struct ice_fltr_list_entry *em_list_itr, *tmp;
2628
2629         LIST_FOR_EACH_ENTRY_SAFE(em_list_itr, tmp, em_list, ice_fltr_list_entry,
2630                                  list_entry) {
2631                 struct ice_sw_recipe *recp_list;
2632                 enum ice_sw_lkup_type l_type;
2633
2634                 l_type = em_list_itr->fltr_info.lkup_type;
2635
2636                 if (l_type != ICE_SW_LKUP_ETHERTYPE_MAC &&
2637                     l_type != ICE_SW_LKUP_ETHERTYPE)
2638                         return ICE_ERR_PARAM;
2639
2640                 recp_list = &sw->recp_list[l_type];
2641                 em_list_itr->status = ice_remove_rule_internal(hw, recp_list,
2642                                                                em_list_itr);
2643                 if (em_list_itr->status)
2644                         return em_list_itr->status;
2645         }
2646         return ICE_SUCCESS;
2647 }
2648
2649 /**
2650  * ice_remove_eth_mac - remove a ethertype based filter rule
2651  * @hw: pointer to the hardware structure
2652  * @em_list: list of ethertype and forwarding information
2653  *
2654  */
2655 enum ice_status
2656 ice_remove_eth_mac(struct ice_hw *hw, struct LIST_HEAD_TYPE *em_list)
2657 {
2658         if (!em_list || !hw)
2659                 return ICE_ERR_PARAM;
2660
2661         return ice_remove_eth_mac_rule(hw, em_list, hw->switch_info);
2662 }
2663
2664 /**
2665  * ice_rem_sw_rule_info
2666  * @hw: pointer to the hardware structure
2667  * @rule_head: pointer to the switch list structure that we want to delete
2668  */
2669 static void
2670 ice_rem_sw_rule_info(struct ice_hw *hw, struct LIST_HEAD_TYPE *rule_head)
2671 {
2672         if (!LIST_EMPTY(rule_head)) {
2673                 struct ice_fltr_mgmt_list_entry *entry;
2674                 struct ice_fltr_mgmt_list_entry *tmp;
2675
2676                 LIST_FOR_EACH_ENTRY_SAFE(entry, tmp, rule_head,
2677                                          ice_fltr_mgmt_list_entry, list_entry) {
2678                         LIST_DEL(&entry->list_entry);
2679                         ice_free(hw, entry);
2680                 }
2681         }
2682 }
2683
2684 /**
2685  * ice_rem_all_sw_rules_info
2686  * @hw: pointer to the hardware structure
2687  */
2688 void ice_rem_all_sw_rules_info(struct ice_hw *hw)
2689 {
2690         struct ice_switch_info *sw = hw->switch_info;
2691         u8 i;
2692
2693         for (i = 0; i < ICE_MAX_NUM_RECIPES; i++) {
2694                 struct LIST_HEAD_TYPE *rule_head;
2695
2696                 rule_head = &sw->recp_list[i].filt_rules;
2697                 if (!sw->recp_list[i].adv_rule)
2698                         ice_rem_sw_rule_info(hw, rule_head);
2699         }
2700 }
2701
2702 /**
2703  * ice_cfg_dflt_vsi - change state of VSI to set/clear default
2704  * @pi: pointer to the port_info structure
2705  * @vsi_handle: VSI handle to set as default
2706  * @set: true to add the above mentioned switch rule, false to remove it
2707  * @direction: ICE_FLTR_RX or ICE_FLTR_TX
2708  *
2709  * add filter rule to set/unset given VSI as default VSI for the switch
2710  * (represented by swid)
2711  */
2712 enum ice_status
2713 ice_cfg_dflt_vsi(struct ice_port_info *pi, u16 vsi_handle, bool set,
2714                  u8 direction)
2715 {
2716         struct ice_aqc_sw_rules_elem *s_rule;
2717         struct ice_fltr_info f_info;
2718         struct ice_hw *hw = pi->hw;
2719         enum ice_adminq_opc opcode;
2720         enum ice_status status;
2721         u16 s_rule_size;
2722         u16 hw_vsi_id;
2723
2724         if (!ice_is_vsi_valid(hw, vsi_handle))
2725                 return ICE_ERR_PARAM;
2726         hw_vsi_id = ice_get_hw_vsi_num(hw, vsi_handle);
2727
2728         s_rule_size = set ? ICE_SW_RULE_RX_TX_ETH_HDR_SIZE :
2729                 ICE_SW_RULE_RX_TX_NO_HDR_SIZE;
2730
2731         s_rule = (struct ice_aqc_sw_rules_elem *)ice_malloc(hw, s_rule_size);
2732         if (!s_rule)
2733                 return ICE_ERR_NO_MEMORY;
2734
2735         ice_memset(&f_info, 0, sizeof(f_info), ICE_NONDMA_MEM);
2736
2737         f_info.lkup_type = ICE_SW_LKUP_DFLT;
2738         f_info.flag = direction;
2739         f_info.fltr_act = ICE_FWD_TO_VSI;
2740         f_info.fwd_id.hw_vsi_id = hw_vsi_id;
2741
2742         if (f_info.flag & ICE_FLTR_RX) {
2743                 f_info.src = pi->lport;
2744                 f_info.src_id = ICE_SRC_ID_LPORT;
2745                 if (!set)
2746                         f_info.fltr_rule_id =
2747                                 pi->dflt_rx_vsi_rule_id;
2748         } else if (f_info.flag & ICE_FLTR_TX) {
2749                 f_info.src_id = ICE_SRC_ID_VSI;
2750                 f_info.src = hw_vsi_id;
2751                 if (!set)
2752                         f_info.fltr_rule_id =
2753                                 pi->dflt_tx_vsi_rule_id;
2754         }
2755
2756         if (set)
2757                 opcode = ice_aqc_opc_add_sw_rules;
2758         else
2759                 opcode = ice_aqc_opc_remove_sw_rules;
2760
2761         ice_fill_sw_rule(hw, &f_info, s_rule, opcode);
2762
2763         status = ice_aq_sw_rules(hw, s_rule, s_rule_size, 1, opcode, NULL);
2764         if (status || !(f_info.flag & ICE_FLTR_TX_RX))
2765                 goto out;
2766         if (set) {
2767                 u16 index = LE16_TO_CPU(s_rule->pdata.lkup_tx_rx.index);
2768
2769                 if (f_info.flag & ICE_FLTR_TX) {
2770                         pi->dflt_tx_vsi_num = hw_vsi_id;
2771                         pi->dflt_tx_vsi_rule_id = index;
2772                 } else if (f_info.flag & ICE_FLTR_RX) {
2773                         pi->dflt_rx_vsi_num = hw_vsi_id;
2774                         pi->dflt_rx_vsi_rule_id = index;
2775                 }
2776         } else {
2777                 if (f_info.flag & ICE_FLTR_TX) {
2778                         pi->dflt_tx_vsi_num = ICE_DFLT_VSI_INVAL;
2779                         pi->dflt_tx_vsi_rule_id = ICE_INVAL_ACT;
2780                 } else if (f_info.flag & ICE_FLTR_RX) {
2781                         pi->dflt_rx_vsi_num = ICE_DFLT_VSI_INVAL;
2782                         pi->dflt_rx_vsi_rule_id = ICE_INVAL_ACT;
2783                 }
2784         }
2785
2786 out:
2787         ice_free(hw, s_rule);
2788         return status;
2789 }
2790
2791 /**
2792  * ice_find_ucast_rule_entry - Search for a unicast MAC filter rule entry
2793  * @list_head: head of rule list
2794  * @f_info: rule information
2795  *
2796  * Helper function to search for a unicast rule entry - this is to be used
2797  * to remove unicast MAC filter that is not shared with other VSIs on the
2798  * PF switch.
2799  *
2800  * Returns pointer to entry storing the rule if found
2801  */
2802 static struct ice_fltr_mgmt_list_entry *
2803 ice_find_ucast_rule_entry(struct LIST_HEAD_TYPE *list_head,
2804                           struct ice_fltr_info *f_info)
2805 {
2806         struct ice_fltr_mgmt_list_entry *list_itr;
2807
2808         LIST_FOR_EACH_ENTRY(list_itr, list_head, ice_fltr_mgmt_list_entry,
2809                             list_entry) {
2810                 if (!memcmp(&f_info->l_data, &list_itr->fltr_info.l_data,
2811                             sizeof(f_info->l_data)) &&
2812                     f_info->fwd_id.hw_vsi_id ==
2813                     list_itr->fltr_info.fwd_id.hw_vsi_id &&
2814                     f_info->flag == list_itr->fltr_info.flag)
2815                         return list_itr;
2816         }
2817         return NULL;
2818 }
2819
2820 /**
2821  * ice_remove_mac_rule - remove a MAC based filter rule
2822  * @hw: pointer to the hardware structure
2823  * @m_list: list of MAC addresses and forwarding information
2824  * @recp_list: list from which function remove MAC address
2825  *
2826  * This function removes either a MAC filter rule or a specific VSI from a
2827  * VSI list for a multicast MAC address.
2828  *
2829  * Returns ICE_ERR_DOES_NOT_EXIST if a given entry was not added by
2830  * ice_add_mac. Caller should be aware that this call will only work if all
2831  * the entries passed into m_list were added previously. It will not attempt to
2832  * do a partial remove of entries that were found.
2833  */
2834 static enum ice_status
2835 ice_remove_mac_rule(struct ice_hw *hw, struct LIST_HEAD_TYPE *m_list,
2836                     struct ice_sw_recipe *recp_list)
2837 {
2838         struct ice_fltr_list_entry *list_itr, *tmp;
2839         struct ice_lock *rule_lock; /* Lock to protect filter rule list */
2840
2841         if (!m_list)
2842                 return ICE_ERR_PARAM;
2843
2844         rule_lock = &recp_list->filt_rule_lock;
2845         LIST_FOR_EACH_ENTRY_SAFE(list_itr, tmp, m_list, ice_fltr_list_entry,
2846                                  list_entry) {
2847                 enum ice_sw_lkup_type l_type = list_itr->fltr_info.lkup_type;
2848                 u8 *add = &list_itr->fltr_info.l_data.mac.mac_addr[0];
2849                 u16 vsi_handle;
2850
2851                 if (l_type != ICE_SW_LKUP_MAC)
2852                         return ICE_ERR_PARAM;
2853
2854                 vsi_handle = list_itr->fltr_info.vsi_handle;
2855                 if (!ice_is_vsi_valid(hw, vsi_handle))
2856                         return ICE_ERR_PARAM;
2857
2858                 list_itr->fltr_info.fwd_id.hw_vsi_id =
2859                                         ice_get_hw_vsi_num(hw, vsi_handle);
2860                 if (IS_UNICAST_ETHER_ADDR(add) && !hw->ucast_shared) {
2861                         /* Don't remove the unicast address that belongs to
2862                          * another VSI on the switch, since it is not being
2863                          * shared...
2864                          */
2865                         ice_acquire_lock(rule_lock);
2866                         if (!ice_find_ucast_rule_entry(&recp_list->filt_rules,
2867                                                        &list_itr->fltr_info)) {
2868                                 ice_release_lock(rule_lock);
2869                                 return ICE_ERR_DOES_NOT_EXIST;
2870                         }
2871                         ice_release_lock(rule_lock);
2872                 }
2873                 list_itr->status = ice_remove_rule_internal(hw, recp_list,
2874                                                             list_itr);
2875                 if (list_itr->status)
2876                         return list_itr->status;
2877         }
2878         return ICE_SUCCESS;
2879 }
2880
2881 /**
2882  * ice_remove_mac - remove a MAC address based filter rule
2883  * @hw: pointer to the hardware structure
2884  * @m_list: list of MAC addresses and forwarding information
2885  *
2886  */
2887 enum ice_status ice_remove_mac(struct ice_hw *hw, struct LIST_HEAD_TYPE *m_list)
2888 {
2889         struct ice_sw_recipe *recp_list;
2890
2891         recp_list = &hw->switch_info->recp_list[ICE_SW_LKUP_MAC];
2892         return ice_remove_mac_rule(hw, m_list, recp_list);
2893 }
2894
2895 /**
2896  * ice_remove_vlan_rule - Remove VLAN based filter rule
2897  * @hw: pointer to the hardware structure
2898  * @v_list: list of VLAN entries and forwarding information
2899  * @recp_list: list from which function remove VLAN
2900  */
2901 static enum ice_status
2902 ice_remove_vlan_rule(struct ice_hw *hw, struct LIST_HEAD_TYPE *v_list,
2903                      struct ice_sw_recipe *recp_list)
2904 {
2905         struct ice_fltr_list_entry *v_list_itr, *tmp;
2906
2907         LIST_FOR_EACH_ENTRY_SAFE(v_list_itr, tmp, v_list, ice_fltr_list_entry,
2908                                  list_entry) {
2909                 enum ice_sw_lkup_type l_type = v_list_itr->fltr_info.lkup_type;
2910
2911                 if (l_type != ICE_SW_LKUP_VLAN)
2912                         return ICE_ERR_PARAM;
2913                 v_list_itr->status = ice_remove_rule_internal(hw, recp_list,
2914                                                               v_list_itr);
2915                 if (v_list_itr->status)
2916                         return v_list_itr->status;
2917         }
2918         return ICE_SUCCESS;
2919 }
2920
2921 /**
2922  * ice_remove_vlan - remove a VLAN address based filter rule
2923  * @hw: pointer to the hardware structure
2924  * @v_list: list of VLAN and forwarding information
2925  *
2926  */
2927 enum ice_status
2928 ice_remove_vlan(struct ice_hw *hw, struct LIST_HEAD_TYPE *v_list)
2929 {
2930         struct ice_sw_recipe *recp_list;
2931
2932         if (!v_list || !hw)
2933                 return ICE_ERR_PARAM;
2934
2935         recp_list = &hw->switch_info->recp_list[ICE_SW_LKUP_VLAN];
2936         return ice_remove_vlan_rule(hw, v_list, recp_list);
2937 }
2938
2939 /**
2940  * ice_vsi_uses_fltr - Determine if given VSI uses specified filter
2941  * @fm_entry: filter entry to inspect
2942  * @vsi_handle: VSI handle to compare with filter info
2943  */
2944 static bool
2945 ice_vsi_uses_fltr(struct ice_fltr_mgmt_list_entry *fm_entry, u16 vsi_handle)
2946 {
2947         return ((fm_entry->fltr_info.fltr_act == ICE_FWD_TO_VSI &&
2948                  fm_entry->fltr_info.vsi_handle == vsi_handle) ||
2949                 (fm_entry->fltr_info.fltr_act == ICE_FWD_TO_VSI_LIST &&
2950                  (ice_is_bit_set(fm_entry->vsi_list_info->vsi_map,
2951                                  vsi_handle))));
2952 }
2953
2954 /**
2955  * ice_add_entry_to_vsi_fltr_list - Add copy of fltr_list_entry to remove list
2956  * @hw: pointer to the hardware structure
2957  * @vsi_handle: VSI handle to remove filters from
2958  * @vsi_list_head: pointer to the list to add entry to
2959  * @fi: pointer to fltr_info of filter entry to copy & add
2960  *
2961  * Helper function, used when creating a list of filters to remove from
2962  * a specific VSI. The entry added to vsi_list_head is a COPY of the
2963  * original filter entry, with the exception of fltr_info.fltr_act and
2964  * fltr_info.fwd_id fields. These are set such that later logic can
2965  * extract which VSI to remove the fltr from, and pass on that information.
2966  */
2967 static enum ice_status
2968 ice_add_entry_to_vsi_fltr_list(struct ice_hw *hw, u16 vsi_handle,
2969                                struct LIST_HEAD_TYPE *vsi_list_head,
2970                                struct ice_fltr_info *fi)
2971 {
2972         struct ice_fltr_list_entry *tmp;
2973
2974         /* this memory is freed up in the caller function
2975          * once filters for this VSI are removed
2976          */
2977         tmp = (struct ice_fltr_list_entry *)ice_malloc(hw, sizeof(*tmp));
2978         if (!tmp)
2979                 return ICE_ERR_NO_MEMORY;
2980
2981         tmp->fltr_info = *fi;
2982
2983         /* Overwrite these fields to indicate which VSI to remove filter from,
2984          * so find and remove logic can extract the information from the
2985          * list entries. Note that original entries will still have proper
2986          * values.
2987          */
2988         tmp->fltr_info.fltr_act = ICE_FWD_TO_VSI;
2989         tmp->fltr_info.vsi_handle = vsi_handle;
2990         tmp->fltr_info.fwd_id.hw_vsi_id = ice_get_hw_vsi_num(hw, vsi_handle);
2991
2992         LIST_ADD(&tmp->list_entry, vsi_list_head);
2993
2994         return ICE_SUCCESS;
2995 }
2996
2997 /**
2998  * ice_add_to_vsi_fltr_list - Add VSI filters to the list
2999  * @hw: pointer to the hardware structure
3000  * @vsi_handle: VSI handle to remove filters from
3001  * @lkup_list_head: pointer to the list that has certain lookup type filters
3002  * @vsi_list_head: pointer to the list pertaining to VSI with vsi_handle
3003  *
3004  * Locates all filters in lkup_list_head that are used by the given VSI,
3005  * and adds COPIES of those entries to vsi_list_head (intended to be used
3006  * to remove the listed filters).
3007  * Note that this means all entries in vsi_list_head must be explicitly
3008  * deallocated by the caller when done with list.
3009  */
3010 static enum ice_status
3011 ice_add_to_vsi_fltr_list(struct ice_hw *hw, u16 vsi_handle,
3012                          struct LIST_HEAD_TYPE *lkup_list_head,
3013                          struct LIST_HEAD_TYPE *vsi_list_head)
3014 {
3015         struct ice_fltr_mgmt_list_entry *fm_entry;
3016         enum ice_status status = ICE_SUCCESS;
3017
3018         /* check to make sure VSI ID is valid and within boundary */
3019         if (!ice_is_vsi_valid(hw, vsi_handle))
3020                 return ICE_ERR_PARAM;
3021
3022         LIST_FOR_EACH_ENTRY(fm_entry, lkup_list_head,
3023                             ice_fltr_mgmt_list_entry, list_entry) {
3024                 struct ice_fltr_info *fi;
3025
3026                 fi = &fm_entry->fltr_info;
3027                 if (!fi || !ice_vsi_uses_fltr(fm_entry, vsi_handle))
3028                         continue;
3029
3030                 status = ice_add_entry_to_vsi_fltr_list(hw, vsi_handle,
3031                                                         vsi_list_head, fi);
3032                 if (status)
3033                         return status;
3034         }
3035         return status;
3036 }
3037
3038 /**
3039  * ice_determine_promisc_mask
3040  * @fi: filter info to parse
3041  *
3042  * Helper function to determine which ICE_PROMISC_ mask corresponds
3043  * to given filter into.
3044  */
3045 static u8 ice_determine_promisc_mask(struct ice_fltr_info *fi)
3046 {
3047         u16 vid = fi->l_data.mac_vlan.vlan_id;
3048         u8 *macaddr = fi->l_data.mac.mac_addr;
3049         bool is_tx_fltr = false;
3050         u8 promisc_mask = 0;
3051
3052         if (fi->flag == ICE_FLTR_TX)
3053                 is_tx_fltr = true;
3054
3055         if (IS_BROADCAST_ETHER_ADDR(macaddr))
3056                 promisc_mask |= is_tx_fltr ?
3057                         ICE_PROMISC_BCAST_TX : ICE_PROMISC_BCAST_RX;
3058         else if (IS_MULTICAST_ETHER_ADDR(macaddr))
3059                 promisc_mask |= is_tx_fltr ?
3060                         ICE_PROMISC_MCAST_TX : ICE_PROMISC_MCAST_RX;
3061         else if (IS_UNICAST_ETHER_ADDR(macaddr))
3062                 promisc_mask |= is_tx_fltr ?
3063                         ICE_PROMISC_UCAST_TX : ICE_PROMISC_UCAST_RX;
3064         if (vid)
3065                 promisc_mask |= is_tx_fltr ?
3066                         ICE_PROMISC_VLAN_TX : ICE_PROMISC_VLAN_RX;
3067
3068         return promisc_mask;
3069 }
3070
3071 /**
3072  * _ice_get_vsi_promisc - get promiscuous mode of given VSI
3073  * @hw: pointer to the hardware structure
3074  * @vsi_handle: VSI handle to retrieve info from
3075  * @promisc_mask: pointer to mask to be filled in
3076  * @vid: VLAN ID of promisc VLAN VSI
3077  * @sw: pointer to switch info struct for which function add rule
3078  */
3079 static enum ice_status
3080 _ice_get_vsi_promisc(struct ice_hw *hw, u16 vsi_handle, u8 *promisc_mask,
3081                      u16 *vid, struct ice_switch_info *sw)
3082 {
3083         struct ice_fltr_mgmt_list_entry *itr;
3084         struct LIST_HEAD_TYPE *rule_head;
3085         struct ice_lock *rule_lock;     /* Lock to protect filter rule list */
3086
3087         if (!ice_is_vsi_valid(hw, vsi_handle))
3088                 return ICE_ERR_PARAM;
3089
3090         *vid = 0;
3091         *promisc_mask = 0;
3092         rule_head = &sw->recp_list[ICE_SW_LKUP_PROMISC].filt_rules;
3093         rule_lock = &sw->recp_list[ICE_SW_LKUP_PROMISC].filt_rule_lock;
3094
3095         ice_acquire_lock(rule_lock);
3096         LIST_FOR_EACH_ENTRY(itr, rule_head,
3097                             ice_fltr_mgmt_list_entry, list_entry) {
3098                 /* Continue if this filter doesn't apply to this VSI or the
3099                  * VSI ID is not in the VSI map for this filter
3100                  */
3101                 if (!ice_vsi_uses_fltr(itr, vsi_handle))
3102                         continue;
3103
3104                 *promisc_mask |= ice_determine_promisc_mask(&itr->fltr_info);
3105         }
3106         ice_release_lock(rule_lock);
3107
3108         return ICE_SUCCESS;
3109 }
3110
3111 /**
3112  * ice_get_vsi_promisc - get promiscuous mode of given VSI
3113  * @hw: pointer to the hardware structure
3114  * @vsi_handle: VSI handle to retrieve info from
3115  * @promisc_mask: pointer to mask to be filled in
3116  * @vid: VLAN ID of promisc VLAN VSI
3117  */
3118 enum ice_status
3119 ice_get_vsi_promisc(struct ice_hw *hw, u16 vsi_handle, u8 *promisc_mask,
3120                     u16 *vid)
3121 {
3122         return _ice_get_vsi_promisc(hw, vsi_handle, promisc_mask,
3123                                     vid, hw->switch_info);
3124 }
3125
3126 /**
3127  * ice_get_vsi_vlan_promisc - get VLAN promiscuous mode of given VSI
3128  * @hw: pointer to the hardware structure
3129  * @vsi_handle: VSI handle to retrieve info from
3130  * @promisc_mask: pointer to mask to be filled in
3131  * @vid: VLAN ID of promisc VLAN VSI
3132  * @sw: pointer to switch info struct for which function add rule
3133  */
3134 static enum ice_status
3135 _ice_get_vsi_vlan_promisc(struct ice_hw *hw, u16 vsi_handle, u8 *promisc_mask,
3136                           u16 *vid, struct ice_switch_info *sw)
3137 {
3138         struct ice_fltr_mgmt_list_entry *itr;
3139         struct LIST_HEAD_TYPE *rule_head;
3140         struct ice_lock *rule_lock;     /* Lock to protect filter rule list */
3141
3142         if (!ice_is_vsi_valid(hw, vsi_handle))
3143                 return ICE_ERR_PARAM;
3144
3145         *vid = 0;
3146         *promisc_mask = 0;
3147         rule_head = &sw->recp_list[ICE_SW_LKUP_PROMISC_VLAN].filt_rules;
3148         rule_lock = &sw->recp_list[ICE_SW_LKUP_PROMISC_VLAN].filt_rule_lock;
3149
3150         ice_acquire_lock(rule_lock);
3151         LIST_FOR_EACH_ENTRY(itr, rule_head, ice_fltr_mgmt_list_entry,
3152                             list_entry) {
3153                 /* Continue if this filter doesn't apply to this VSI or the
3154                  * VSI ID is not in the VSI map for this filter
3155                  */
3156                 if (!ice_vsi_uses_fltr(itr, vsi_handle))
3157                         continue;
3158
3159                 *promisc_mask |= ice_determine_promisc_mask(&itr->fltr_info);
3160         }
3161         ice_release_lock(rule_lock);
3162
3163         return ICE_SUCCESS;
3164 }
3165
3166 /**
3167  * ice_get_vsi_vlan_promisc - get VLAN promiscuous mode of given VSI
3168  * @hw: pointer to the hardware structure
3169  * @vsi_handle: VSI handle to retrieve info from
3170  * @promisc_mask: pointer to mask to be filled in
3171  * @vid: VLAN ID of promisc VLAN VSI
3172  */
3173 enum ice_status
3174 ice_get_vsi_vlan_promisc(struct ice_hw *hw, u16 vsi_handle, u8 *promisc_mask,
3175                          u16 *vid)
3176 {
3177         return _ice_get_vsi_vlan_promisc(hw, vsi_handle, promisc_mask,
3178                                          vid, hw->switch_info);
3179 }
3180
3181 /**
3182  * ice_remove_promisc - Remove promisc based filter rules
3183  * @hw: pointer to the hardware structure
3184  * @recp_id: recipe ID for which the rule needs to removed
3185  * @v_list: list of promisc entries
3186  */
3187 static enum ice_status
3188 ice_remove_promisc(struct ice_hw *hw, u8 recp_id,
3189                    struct LIST_HEAD_TYPE *v_list)
3190 {
3191         struct ice_fltr_list_entry *v_list_itr, *tmp;
3192         struct ice_sw_recipe *recp_list;
3193
3194         recp_list = &hw->switch_info->recp_list[recp_id];
3195         LIST_FOR_EACH_ENTRY_SAFE(v_list_itr, tmp, v_list, ice_fltr_list_entry,
3196                                  list_entry) {
3197                 v_list_itr->status =
3198                         ice_remove_rule_internal(hw, recp_list, v_list_itr);
3199                 if (v_list_itr->status)
3200                         return v_list_itr->status;
3201         }
3202         return ICE_SUCCESS;
3203 }
3204
3205 /**
3206  * _ice_clear_vsi_promisc - clear specified promiscuous mode(s)
3207  * @hw: pointer to the hardware structure
3208  * @vsi_handle: VSI handle to clear mode
3209  * @promisc_mask: mask of promiscuous config bits to clear
3210  * @vid: VLAN ID to clear VLAN promiscuous
3211  * @sw: pointer to switch info struct for which function add rule
3212  */
3213 static enum ice_status
3214 _ice_clear_vsi_promisc(struct ice_hw *hw, u16 vsi_handle, u8 promisc_mask,
3215                        u16 vid, struct ice_switch_info *sw)
3216 {
3217         struct ice_fltr_list_entry *fm_entry, *tmp;
3218         struct LIST_HEAD_TYPE remove_list_head;
3219         struct ice_fltr_mgmt_list_entry *itr;
3220         struct LIST_HEAD_TYPE *rule_head;
3221         struct ice_lock *rule_lock;     /* Lock to protect filter rule list */
3222         enum ice_status status = ICE_SUCCESS;
3223         u8 recipe_id;
3224
3225         if (!ice_is_vsi_valid(hw, vsi_handle))
3226                 return ICE_ERR_PARAM;
3227
3228         if (promisc_mask & (ICE_PROMISC_VLAN_RX | ICE_PROMISC_VLAN_TX))
3229                 recipe_id = ICE_SW_LKUP_PROMISC_VLAN;
3230         else
3231                 recipe_id = ICE_SW_LKUP_PROMISC;
3232
3233         rule_head = &sw->recp_list[recipe_id].filt_rules;
3234         rule_lock = &sw->recp_list[recipe_id].filt_rule_lock;
3235
3236         INIT_LIST_HEAD(&remove_list_head);
3237
3238         ice_acquire_lock(rule_lock);
3239         LIST_FOR_EACH_ENTRY(itr, rule_head,
3240                             ice_fltr_mgmt_list_entry, list_entry) {
3241                 struct ice_fltr_info *fltr_info;
3242                 u8 fltr_promisc_mask = 0;
3243
3244                 if (!ice_vsi_uses_fltr(itr, vsi_handle))
3245                         continue;
3246                 fltr_info = &itr->fltr_info;
3247
3248                 if (recipe_id == ICE_SW_LKUP_PROMISC_VLAN &&
3249                     vid != fltr_info->l_data.mac_vlan.vlan_id)
3250                         continue;
3251
3252                 fltr_promisc_mask |= ice_determine_promisc_mask(fltr_info);
3253
3254                 /* Skip if filter is not completely specified by given mask */
3255                 if (fltr_promisc_mask & ~promisc_mask)
3256                         continue;
3257
3258                 status = ice_add_entry_to_vsi_fltr_list(hw, vsi_handle,
3259                                                         &remove_list_head,
3260                                                         fltr_info);
3261                 if (status) {
3262                         ice_release_lock(rule_lock);
3263                         goto free_fltr_list;
3264                 }
3265         }
3266         ice_release_lock(rule_lock);
3267
3268         status = ice_remove_promisc(hw, recipe_id, &remove_list_head);
3269
3270 free_fltr_list:
3271         LIST_FOR_EACH_ENTRY_SAFE(fm_entry, tmp, &remove_list_head,
3272                                  ice_fltr_list_entry, list_entry) {
3273                 LIST_DEL(&fm_entry->list_entry);
3274                 ice_free(hw, fm_entry);
3275         }
3276
3277         return status;
3278 }
3279
3280 /**
3281  * ice_clear_vsi_promisc - clear specified promiscuous mode(s) for given VSI
3282  * @hw: pointer to the hardware structure
3283  * @vsi_handle: VSI handle to clear mode
3284  * @promisc_mask: mask of promiscuous config bits to clear
3285  * @vid: VLAN ID to clear VLAN promiscuous
3286  */
3287 enum ice_status
3288 ice_clear_vsi_promisc(struct ice_hw *hw, u16 vsi_handle,
3289                       u8 promisc_mask, u16 vid)
3290 {
3291         return _ice_clear_vsi_promisc(hw, vsi_handle, promisc_mask,
3292                                       vid, hw->switch_info);
3293 }
3294
3295 /**
3296  * _ice_set_vsi_promisc - set given VSI to given promiscuous mode(s)
3297  * @hw: pointer to the hardware structure
3298  * @vsi_handle: VSI handle to configure
3299  * @promisc_mask: mask of promiscuous config bits
3300  * @vid: VLAN ID to set VLAN promiscuous
3301  * @lport: logical port number to configure promisc mode
3302  * @sw: pointer to switch info struct for which function add rule
3303  */
3304 static enum ice_status
3305 _ice_set_vsi_promisc(struct ice_hw *hw, u16 vsi_handle, u8 promisc_mask,
3306                      u16 vid, u8 lport, struct ice_switch_info *sw)
3307 {
3308         enum { UCAST_FLTR = 1, MCAST_FLTR, BCAST_FLTR };
3309         struct ice_fltr_list_entry f_list_entry;
3310         struct ice_fltr_info new_fltr;
3311         enum ice_status status = ICE_SUCCESS;
3312         bool is_tx_fltr;
3313         u16 hw_vsi_id;
3314         int pkt_type;
3315         u8 recipe_id;
3316
3317         ice_debug(hw, ICE_DBG_TRACE, "%s\n", __func__);
3318
3319         if (!ice_is_vsi_valid(hw, vsi_handle))
3320                 return ICE_ERR_PARAM;
3321         hw_vsi_id = ice_get_hw_vsi_num(hw, vsi_handle);
3322
3323         ice_memset(&new_fltr, 0, sizeof(new_fltr), ICE_NONDMA_MEM);
3324
3325         if (promisc_mask & (ICE_PROMISC_VLAN_RX | ICE_PROMISC_VLAN_TX)) {
3326                 new_fltr.lkup_type = ICE_SW_LKUP_PROMISC_VLAN;
3327                 new_fltr.l_data.mac_vlan.vlan_id = vid;
3328                 recipe_id = ICE_SW_LKUP_PROMISC_VLAN;
3329         } else {
3330                 new_fltr.lkup_type = ICE_SW_LKUP_PROMISC;
3331                 recipe_id = ICE_SW_LKUP_PROMISC;
3332         }
3333
3334         /* Separate filters must be set for each direction/packet type
3335          * combination, so we will loop over the mask value, store the
3336          * individual type, and clear it out in the input mask as it
3337          * is found.
3338          */
3339         while (promisc_mask) {
3340                 struct ice_sw_recipe *recp_list;
3341                 u8 *mac_addr;
3342
3343                 pkt_type = 0;
3344                 is_tx_fltr = false;
3345
3346                 if (promisc_mask & ICE_PROMISC_UCAST_RX) {
3347                         promisc_mask &= ~ICE_PROMISC_UCAST_RX;
3348                         pkt_type = UCAST_FLTR;
3349                 } else if (promisc_mask & ICE_PROMISC_UCAST_TX) {
3350                         promisc_mask &= ~ICE_PROMISC_UCAST_TX;
3351                         pkt_type = UCAST_FLTR;
3352                         is_tx_fltr = true;
3353                 } else if (promisc_mask & ICE_PROMISC_MCAST_RX) {
3354                         promisc_mask &= ~ICE_PROMISC_MCAST_RX;
3355                         pkt_type = MCAST_FLTR;
3356                 } else if (promisc_mask & ICE_PROMISC_MCAST_TX) {
3357                         promisc_mask &= ~ICE_PROMISC_MCAST_TX;
3358                         pkt_type = MCAST_FLTR;
3359                         is_tx_fltr = true;
3360                 } else if (promisc_mask & ICE_PROMISC_BCAST_RX) {
3361                         promisc_mask &= ~ICE_PROMISC_BCAST_RX;
3362                         pkt_type = BCAST_FLTR;
3363                 } else if (promisc_mask & ICE_PROMISC_BCAST_TX) {
3364                         promisc_mask &= ~ICE_PROMISC_BCAST_TX;
3365                         pkt_type = BCAST_FLTR;
3366                         is_tx_fltr = true;
3367                 }
3368
3369                 /* Check for VLAN promiscuous flag */
3370                 if (promisc_mask & ICE_PROMISC_VLAN_RX) {
3371                         promisc_mask &= ~ICE_PROMISC_VLAN_RX;
3372                 } else if (promisc_mask & ICE_PROMISC_VLAN_TX) {
3373                         promisc_mask &= ~ICE_PROMISC_VLAN_TX;
3374                         is_tx_fltr = true;
3375                 }
3376
3377                 /* Set filter DA based on packet type */
3378                 mac_addr = new_fltr.l_data.mac.mac_addr;
3379                 if (pkt_type == BCAST_FLTR) {
3380                         ice_memset(mac_addr, 0xff, ETH_ALEN, ICE_NONDMA_MEM);
3381                 } else if (pkt_type == MCAST_FLTR ||
3382                            pkt_type == UCAST_FLTR) {
3383                         /* Use the dummy ether header DA */
3384                         ice_memcpy(mac_addr, dummy_eth_header, ETH_ALEN,
3385                                    ICE_NONDMA_TO_NONDMA);
3386                         if (pkt_type == MCAST_FLTR)
3387                                 mac_addr[0] |= 0x1;     /* Set multicast bit */
3388                 }
3389
3390                 /* Need to reset this to zero for all iterations */
3391                 new_fltr.flag = 0;
3392                 if (is_tx_fltr) {
3393                         new_fltr.flag |= ICE_FLTR_TX;
3394                         new_fltr.src = hw_vsi_id;
3395                 } else {
3396                         new_fltr.flag |= ICE_FLTR_RX;
3397                         new_fltr.src = lport;
3398                 }
3399
3400                 new_fltr.fltr_act = ICE_FWD_TO_VSI;
3401                 new_fltr.vsi_handle = vsi_handle;
3402                 new_fltr.fwd_id.hw_vsi_id = hw_vsi_id;
3403                 f_list_entry.fltr_info = new_fltr;
3404                 recp_list = &sw->recp_list[recipe_id];
3405
3406                 status = ice_add_rule_internal(hw, recp_list, lport,
3407                                                &f_list_entry);
3408                 if (status != ICE_SUCCESS)
3409                         goto set_promisc_exit;
3410         }
3411
3412 set_promisc_exit:
3413         return status;
3414 }
3415
3416 /**
3417  * ice_set_vsi_promisc - set given VSI to given promiscuous mode(s)
3418  * @hw: pointer to the hardware structure
3419  * @vsi_handle: VSI handle to configure
3420  * @promisc_mask: mask of promiscuous config bits
3421  * @vid: VLAN ID to set VLAN promiscuous
3422  */
3423 enum ice_status
3424 ice_set_vsi_promisc(struct ice_hw *hw, u16 vsi_handle, u8 promisc_mask,
3425                     u16 vid)
3426 {
3427         return _ice_set_vsi_promisc(hw, vsi_handle, promisc_mask, vid,
3428                                     hw->port_info->lport,
3429                                     hw->switch_info);
3430 }
3431
3432 /**
3433  * _ice_set_vlan_vsi_promisc
3434  * @hw: pointer to the hardware structure
3435  * @vsi_handle: VSI handle to configure
3436  * @promisc_mask: mask of promiscuous config bits
3437  * @rm_vlan_promisc: Clear VLANs VSI promisc mode
3438  * @lport: logical port number to configure promisc mode
3439  * @sw: pointer to switch info struct for which function add rule
3440  *
3441  * Configure VSI with all associated VLANs to given promiscuous mode(s)
3442  */
3443 static enum ice_status
3444 _ice_set_vlan_vsi_promisc(struct ice_hw *hw, u16 vsi_handle, u8 promisc_mask,
3445                           bool rm_vlan_promisc, u8 lport,
3446                           struct ice_switch_info *sw)
3447 {
3448         struct ice_fltr_list_entry *list_itr, *tmp;
3449         struct LIST_HEAD_TYPE vsi_list_head;
3450         struct LIST_HEAD_TYPE *vlan_head;
3451         struct ice_lock *vlan_lock; /* Lock to protect filter rule list */
3452         enum ice_status status;
3453         u16 vlan_id;
3454
3455         INIT_LIST_HEAD(&vsi_list_head);
3456         vlan_lock = &sw->recp_list[ICE_SW_LKUP_VLAN].filt_rule_lock;
3457         vlan_head = &sw->recp_list[ICE_SW_LKUP_VLAN].filt_rules;
3458         ice_acquire_lock(vlan_lock);
3459         status = ice_add_to_vsi_fltr_list(hw, vsi_handle, vlan_head,
3460                                           &vsi_list_head);
3461         ice_release_lock(vlan_lock);
3462         if (status)
3463                 goto free_fltr_list;
3464
3465         LIST_FOR_EACH_ENTRY(list_itr, &vsi_list_head, ice_fltr_list_entry,
3466                             list_entry) {
3467                 vlan_id = list_itr->fltr_info.l_data.vlan.vlan_id;
3468                 if (rm_vlan_promisc)
3469                         status =  _ice_clear_vsi_promisc(hw, vsi_handle,
3470                                                          promisc_mask,
3471                                                          vlan_id, sw);
3472                 else
3473                         status =  _ice_set_vsi_promisc(hw, vsi_handle,
3474                                                        promisc_mask, vlan_id,
3475                                                        lport, sw);
3476                 if (status)
3477                         break;
3478         }
3479
3480 free_fltr_list:
3481         LIST_FOR_EACH_ENTRY_SAFE(list_itr, tmp, &vsi_list_head,
3482                                  ice_fltr_list_entry, list_entry) {
3483                 LIST_DEL(&list_itr->list_entry);
3484                 ice_free(hw, list_itr);
3485         }
3486         return status;
3487 }
3488
3489 /**
3490  * ice_set_vlan_vsi_promisc
3491  * @hw: pointer to the hardware structure
3492  * @vsi_handle: VSI handle to configure
3493  * @promisc_mask: mask of promiscuous config bits
3494  * @rm_vlan_promisc: Clear VLANs VSI promisc mode
3495  *
3496  * Configure VSI with all associated VLANs to given promiscuous mode(s)
3497  */
3498 enum ice_status
3499 ice_set_vlan_vsi_promisc(struct ice_hw *hw, u16 vsi_handle, u8 promisc_mask,
3500                          bool rm_vlan_promisc)
3501 {
3502         return _ice_set_vlan_vsi_promisc(hw, vsi_handle, promisc_mask,
3503                                          rm_vlan_promisc, hw->port_info->lport,
3504                                          hw->switch_info);
3505 }
3506
3507 /**
3508  * ice_remove_vsi_lkup_fltr - Remove lookup type filters for a VSI
3509  * @hw: pointer to the hardware structure
3510  * @vsi_handle: VSI handle to remove filters from
3511  * @recp_list: recipe list from which function remove fltr
3512  * @lkup: switch rule filter lookup type
3513  */
3514 static void
3515 ice_remove_vsi_lkup_fltr(struct ice_hw *hw, u16 vsi_handle,
3516                          struct ice_sw_recipe *recp_list,
3517                          enum ice_sw_lkup_type lkup)
3518 {
3519         struct ice_fltr_list_entry *fm_entry;
3520         struct LIST_HEAD_TYPE remove_list_head;
3521         struct LIST_HEAD_TYPE *rule_head;
3522         struct ice_fltr_list_entry *tmp;
3523         struct ice_lock *rule_lock;     /* Lock to protect filter rule list */
3524         enum ice_status status;
3525
3526         INIT_LIST_HEAD(&remove_list_head);
3527         rule_lock = &recp_list[lkup].filt_rule_lock;
3528         rule_head = &recp_list[lkup].filt_rules;
3529         ice_acquire_lock(rule_lock);
3530         status = ice_add_to_vsi_fltr_list(hw, vsi_handle, rule_head,
3531                                           &remove_list_head);
3532         ice_release_lock(rule_lock);
3533         if (status)
3534                 return;
3535
3536         switch (lkup) {
3537         case ICE_SW_LKUP_MAC:
3538                 ice_remove_mac_rule(hw, &remove_list_head, &recp_list[lkup]);
3539                 break;
3540         case ICE_SW_LKUP_VLAN:
3541                 ice_remove_vlan_rule(hw, &remove_list_head, &recp_list[lkup]);
3542                 break;
3543         case ICE_SW_LKUP_PROMISC:
3544         case ICE_SW_LKUP_PROMISC_VLAN:
3545                 ice_remove_promisc(hw, lkup, &remove_list_head);
3546                 break;
3547         case ICE_SW_LKUP_MAC_VLAN:
3548                 ice_debug(hw, ICE_DBG_SW, "MAC VLAN look up is not supported yet\n");
3549                 break;
3550         case ICE_SW_LKUP_ETHERTYPE:
3551         case ICE_SW_LKUP_ETHERTYPE_MAC:
3552                 ice_remove_eth_mac(hw, &remove_list_head);
3553                 break;
3554         case ICE_SW_LKUP_DFLT:
3555                 ice_debug(hw, ICE_DBG_SW, "Remove filters for this lookup type hasn't been implemented yet\n");
3556                 break;
3557         case ICE_SW_LKUP_LAST:
3558                 ice_debug(hw, ICE_DBG_SW, "Unsupported lookup type\n");
3559                 break;
3560         }
3561
3562         LIST_FOR_EACH_ENTRY_SAFE(fm_entry, tmp, &remove_list_head,
3563                                  ice_fltr_list_entry, list_entry) {
3564                 LIST_DEL(&fm_entry->list_entry);
3565                 ice_free(hw, fm_entry);
3566         }
3567 }
3568
3569 /**
3570  * ice_remove_vsi_fltr_rule - Remove all filters for a VSI
3571  * @hw: pointer to the hardware structure
3572  * @vsi_handle: VSI handle to remove filters from
3573  * @sw: pointer to switch info struct
3574  */
3575 static void
3576 ice_remove_vsi_fltr_rule(struct ice_hw *hw, u16 vsi_handle,
3577                          struct ice_switch_info *sw)
3578 {
3579         ice_debug(hw, ICE_DBG_TRACE, "%s\n", __func__);
3580
3581         ice_remove_vsi_lkup_fltr(hw, vsi_handle,
3582                                  sw->recp_list, ICE_SW_LKUP_MAC);
3583         ice_remove_vsi_lkup_fltr(hw, vsi_handle,
3584                                  sw->recp_list, ICE_SW_LKUP_MAC_VLAN);
3585         ice_remove_vsi_lkup_fltr(hw, vsi_handle,
3586                                  sw->recp_list, ICE_SW_LKUP_PROMISC);
3587         ice_remove_vsi_lkup_fltr(hw, vsi_handle,
3588                                  sw->recp_list, ICE_SW_LKUP_VLAN);
3589         ice_remove_vsi_lkup_fltr(hw, vsi_handle,
3590                                  sw->recp_list, ICE_SW_LKUP_DFLT);
3591         ice_remove_vsi_lkup_fltr(hw, vsi_handle,
3592                                  sw->recp_list, ICE_SW_LKUP_ETHERTYPE);
3593         ice_remove_vsi_lkup_fltr(hw, vsi_handle,
3594                                  sw->recp_list, ICE_SW_LKUP_ETHERTYPE_MAC);
3595         ice_remove_vsi_lkup_fltr(hw, vsi_handle,
3596                                  sw->recp_list, ICE_SW_LKUP_PROMISC_VLAN);
3597 }
3598
3599 /**
3600  * ice_remove_vsi_fltr - Remove all filters for a VSI
3601  * @hw: pointer to the hardware structure
3602  * @vsi_handle: VSI handle to remove filters from
3603  */
3604 void ice_remove_vsi_fltr(struct ice_hw *hw, u16 vsi_handle)
3605 {
3606         ice_remove_vsi_fltr_rule(hw, vsi_handle, hw->switch_info);
3607 }
3608
3609 /**
3610  * ice_alloc_res_cntr - allocating resource counter
3611  * @hw: pointer to the hardware structure
3612  * @type: type of resource
3613  * @alloc_shared: if set it is shared else dedicated
3614  * @num_items: number of entries requested for FD resource type
3615  * @counter_id: counter index returned by AQ call
3616  */
3617 static enum ice_status
3618 ice_alloc_res_cntr(struct ice_hw *hw, u8 type, u8 alloc_shared, u16 num_items,
3619                    u16 *counter_id)
3620 {
3621         struct ice_aqc_alloc_free_res_elem *buf;
3622         enum ice_status status;
3623         u16 buf_len;
3624
3625         /* Allocate resource */
3626         buf_len = ice_struct_size(buf, elem, 1);
3627         buf = (struct ice_aqc_alloc_free_res_elem *)ice_malloc(hw, buf_len);
3628         if (!buf)
3629                 return ICE_ERR_NO_MEMORY;
3630
3631         buf->num_elems = CPU_TO_LE16(num_items);
3632         buf->res_type = CPU_TO_LE16(((type << ICE_AQC_RES_TYPE_S) &
3633                                       ICE_AQC_RES_TYPE_M) | alloc_shared);
3634
3635         status = ice_aq_alloc_free_res(hw, 1, buf, buf_len,
3636                                        ice_aqc_opc_alloc_res, NULL);
3637         if (status)
3638                 goto exit;
3639
3640         *counter_id = LE16_TO_CPU(buf->elem[0].e.sw_resp);
3641
3642 exit:
3643         ice_free(hw, buf);
3644         return status;
3645 }
3646
3647 /**
3648  * ice_free_res_cntr - free resource counter
3649  * @hw: pointer to the hardware structure
3650  * @type: type of resource
3651  * @alloc_shared: if set it is shared else dedicated
3652  * @num_items: number of entries to be freed for FD resource type
3653  * @counter_id: counter ID resource which needs to be freed
3654  */
3655 static enum ice_status
3656 ice_free_res_cntr(struct ice_hw *hw, u8 type, u8 alloc_shared, u16 num_items,
3657                   u16 counter_id)
3658 {
3659         struct ice_aqc_alloc_free_res_elem *buf;
3660         enum ice_status status;
3661         u16 buf_len;
3662
3663         /* Free resource */
3664         buf_len = ice_struct_size(buf, elem, 1);
3665         buf = (struct ice_aqc_alloc_free_res_elem *)ice_malloc(hw, buf_len);
3666         if (!buf)
3667                 return ICE_ERR_NO_MEMORY;
3668
3669         buf->num_elems = CPU_TO_LE16(num_items);
3670         buf->res_type = CPU_TO_LE16(((type << ICE_AQC_RES_TYPE_S) &
3671                                       ICE_AQC_RES_TYPE_M) | alloc_shared);
3672         buf->elem[0].e.sw_resp = CPU_TO_LE16(counter_id);
3673
3674         status = ice_aq_alloc_free_res(hw, 1, buf, buf_len,
3675                                        ice_aqc_opc_free_res, NULL);
3676         if (status)
3677                 ice_debug(hw, ICE_DBG_SW, "counter resource could not be freed\n");
3678
3679         ice_free(hw, buf);
3680         return status;
3681 }
3682
3683 /**
3684  * ice_alloc_vlan_res_counter - obtain counter resource for VLAN type
3685  * @hw: pointer to the hardware structure
3686  * @counter_id: returns counter index
3687  */
3688 enum ice_status ice_alloc_vlan_res_counter(struct ice_hw *hw, u16 *counter_id)
3689 {
3690         return ice_alloc_res_cntr(hw, ICE_AQC_RES_TYPE_VLAN_COUNTER,
3691                                   ICE_AQC_RES_TYPE_FLAG_DEDICATED, 1,
3692                                   counter_id);
3693 }
3694
3695 /**
3696  * ice_free_vlan_res_counter - Free counter resource for VLAN type
3697  * @hw: pointer to the hardware structure
3698  * @counter_id: counter index to be freed
3699  */
3700 enum ice_status ice_free_vlan_res_counter(struct ice_hw *hw, u16 counter_id)
3701 {
3702         return ice_free_res_cntr(hw, ICE_AQC_RES_TYPE_VLAN_COUNTER,
3703                                  ICE_AQC_RES_TYPE_FLAG_DEDICATED, 1,
3704                                  counter_id);
3705 }
3706
3707 /**
3708  * ice_alloc_res_lg_act - add large action resource
3709  * @hw: pointer to the hardware structure
3710  * @l_id: large action ID to fill it in
3711  * @num_acts: number of actions to hold with a large action entry
3712  */
3713 static enum ice_status
3714 ice_alloc_res_lg_act(struct ice_hw *hw, u16 *l_id, u16 num_acts)
3715 {
3716         struct ice_aqc_alloc_free_res_elem *sw_buf;
3717         enum ice_status status;
3718         u16 buf_len;
3719
3720         if (num_acts > ICE_MAX_LG_ACT || num_acts == 0)
3721                 return ICE_ERR_PARAM;
3722
3723         /* Allocate resource for large action */
3724         buf_len = ice_struct_size(sw_buf, elem, 1);
3725         sw_buf = (struct ice_aqc_alloc_free_res_elem *)ice_malloc(hw, buf_len);
3726         if (!sw_buf)
3727                 return ICE_ERR_NO_MEMORY;
3728
3729         sw_buf->num_elems = CPU_TO_LE16(1);
3730
3731         /* If num_acts is 1, use ICE_AQC_RES_TYPE_WIDE_TABLE_1.
3732          * If num_acts is 2, use ICE_AQC_RES_TYPE_WIDE_TABLE_3.
3733          * If num_acts is greater than 2, then use
3734          * ICE_AQC_RES_TYPE_WIDE_TABLE_4.
3735          * The num_acts cannot exceed 4. This was ensured at the
3736          * beginning of the function.
3737          */
3738         if (num_acts == 1)
3739                 sw_buf->res_type = CPU_TO_LE16(ICE_AQC_RES_TYPE_WIDE_TABLE_1);
3740         else if (num_acts == 2)
3741                 sw_buf->res_type = CPU_TO_LE16(ICE_AQC_RES_TYPE_WIDE_TABLE_2);
3742         else
3743                 sw_buf->res_type = CPU_TO_LE16(ICE_AQC_RES_TYPE_WIDE_TABLE_4);
3744
3745         status = ice_aq_alloc_free_res(hw, 1, sw_buf, buf_len,
3746                                        ice_aqc_opc_alloc_res, NULL);
3747         if (!status)
3748                 *l_id = LE16_TO_CPU(sw_buf->elem[0].e.sw_resp);
3749
3750         ice_free(hw, sw_buf);
3751         return status;
3752 }
3753
3754 /**
3755  * ice_add_mac_with_sw_marker - add filter with sw marker
3756  * @hw: pointer to the hardware structure
3757  * @f_info: filter info structure containing the MAC filter information
3758  * @sw_marker: sw marker to tag the Rx descriptor with
3759  */
3760 enum ice_status
3761 ice_add_mac_with_sw_marker(struct ice_hw *hw, struct ice_fltr_info *f_info,
3762                            u16 sw_marker)
3763 {
3764         struct ice_fltr_mgmt_list_entry *m_entry;
3765         struct ice_fltr_list_entry fl_info;
3766         struct ice_sw_recipe *recp_list;
3767         struct LIST_HEAD_TYPE l_head;
3768         struct ice_lock *rule_lock;     /* Lock to protect filter rule list */
3769         enum ice_status ret;
3770         bool entry_exists;
3771         u16 lg_act_id;
3772
3773         if (f_info->fltr_act != ICE_FWD_TO_VSI)
3774                 return ICE_ERR_PARAM;
3775
3776         if (f_info->lkup_type != ICE_SW_LKUP_MAC)
3777                 return ICE_ERR_PARAM;
3778
3779         if (sw_marker == ICE_INVAL_SW_MARKER_ID)
3780                 return ICE_ERR_PARAM;
3781
3782         if (!ice_is_vsi_valid(hw, f_info->vsi_handle))
3783                 return ICE_ERR_PARAM;
3784         f_info->fwd_id.hw_vsi_id = ice_get_hw_vsi_num(hw, f_info->vsi_handle);
3785
3786         /* Add filter if it doesn't exist so then the adding of large
3787          * action always results in update
3788          */
3789
3790         INIT_LIST_HEAD(&l_head);
3791         fl_info.fltr_info = *f_info;
3792         LIST_ADD(&fl_info.list_entry, &l_head);
3793
3794         entry_exists = false;
3795         ret = ice_add_mac_rule(hw, &l_head, hw->switch_info,
3796                                hw->port_info->lport);
3797         if (ret == ICE_ERR_ALREADY_EXISTS)
3798                 entry_exists = true;
3799         else if (ret)
3800                 return ret;
3801
3802         recp_list = &hw->switch_info->recp_list[ICE_SW_LKUP_MAC];
3803         rule_lock = &recp_list->filt_rule_lock;
3804         ice_acquire_lock(rule_lock);
3805         /* Get the book keeping entry for the filter */
3806         m_entry = ice_find_rule_entry(&recp_list->filt_rules, f_info);
3807         if (!m_entry)
3808                 goto exit_error;
3809
3810         /* If counter action was enabled for this rule then don't enable
3811          * sw marker large action
3812          */
3813         if (m_entry->counter_index != ICE_INVAL_COUNTER_ID) {
3814                 ret = ICE_ERR_PARAM;
3815                 goto exit_error;
3816         }
3817
3818         /* if same marker was added before */
3819         if (m_entry->sw_marker_id == sw_marker) {
3820                 ret = ICE_ERR_ALREADY_EXISTS;
3821                 goto exit_error;
3822         }
3823
3824         /* Allocate a hardware table entry to hold large act. Three actions
3825          * for marker based large action
3826          */
3827         ret = ice_alloc_res_lg_act(hw, &lg_act_id, 3);
3828         if (ret)
3829                 goto exit_error;
3830
3831         if (lg_act_id == ICE_INVAL_LG_ACT_INDEX)
3832                 goto exit_error;
3833
3834         /* Update the switch rule to add the marker action */
3835         ret = ice_add_marker_act(hw, m_entry, sw_marker, lg_act_id);
3836         if (!ret) {
3837                 ice_release_lock(rule_lock);
3838                 return ret;
3839         }
3840
3841 exit_error:
3842         ice_release_lock(rule_lock);
3843         /* only remove entry if it did not exist previously */
3844         if (!entry_exists)
3845                 ret = ice_remove_mac(hw, &l_head);
3846
3847         return ret;
3848 }
3849
3850 /**
3851  * ice_add_mac_with_counter - add filter with counter enabled
3852  * @hw: pointer to the hardware structure
3853  * @f_info: pointer to filter info structure containing the MAC filter
3854  *          information
3855  */
3856 enum ice_status
3857 ice_add_mac_with_counter(struct ice_hw *hw, struct ice_fltr_info *f_info)
3858 {
3859         struct ice_fltr_mgmt_list_entry *m_entry;
3860         struct ice_fltr_list_entry fl_info;
3861         struct ice_sw_recipe *recp_list;
3862         struct LIST_HEAD_TYPE l_head;
3863         struct ice_lock *rule_lock;     /* Lock to protect filter rule list */
3864         enum ice_status ret;
3865         bool entry_exist;
3866         u16 counter_id;
3867         u16 lg_act_id;
3868
3869         if (f_info->fltr_act != ICE_FWD_TO_VSI)
3870                 return ICE_ERR_PARAM;
3871
3872         if (f_info->lkup_type != ICE_SW_LKUP_MAC)
3873                 return ICE_ERR_PARAM;
3874
3875         if (!ice_is_vsi_valid(hw, f_info->vsi_handle))
3876                 return ICE_ERR_PARAM;
3877         f_info->fwd_id.hw_vsi_id = ice_get_hw_vsi_num(hw, f_info->vsi_handle);
3878         recp_list = &hw->switch_info->recp_list[ICE_SW_LKUP_MAC];
3879
3880         entry_exist = false;
3881
3882         rule_lock = &recp_list->filt_rule_lock;
3883
3884         /* Add filter if it doesn't exist so then the adding of large
3885          * action always results in update
3886          */
3887         INIT_LIST_HEAD(&l_head);
3888
3889         fl_info.fltr_info = *f_info;
3890         LIST_ADD(&fl_info.list_entry, &l_head);
3891
3892         ret = ice_add_mac_rule(hw, &l_head, hw->switch_info,
3893                                hw->port_info->lport);
3894         if (ret == ICE_ERR_ALREADY_EXISTS)
3895                 entry_exist = true;
3896         else if (ret)
3897                 return ret;
3898
3899         ice_acquire_lock(rule_lock);
3900         m_entry = ice_find_rule_entry(&recp_list->filt_rules, f_info);
3901         if (!m_entry) {
3902                 ret = ICE_ERR_BAD_PTR;
3903                 goto exit_error;
3904         }
3905
3906         /* Don't enable counter for a filter for which sw marker was enabled */
3907         if (m_entry->sw_marker_id != ICE_INVAL_SW_MARKER_ID) {
3908                 ret = ICE_ERR_PARAM;
3909                 goto exit_error;
3910         }
3911
3912         /* If a counter was already enabled then don't need to add again */
3913         if (m_entry->counter_index != ICE_INVAL_COUNTER_ID) {
3914                 ret = ICE_ERR_ALREADY_EXISTS;
3915                 goto exit_error;
3916         }
3917
3918         /* Allocate a hardware table entry to VLAN counter */
3919         ret = ice_alloc_vlan_res_counter(hw, &counter_id);
3920         if (ret)
3921                 goto exit_error;
3922
3923         /* Allocate a hardware table entry to hold large act. Two actions for
3924          * counter based large action
3925          */
3926         ret = ice_alloc_res_lg_act(hw, &lg_act_id, 2);
3927         if (ret)
3928                 goto exit_error;
3929
3930         if (lg_act_id == ICE_INVAL_LG_ACT_INDEX)
3931                 goto exit_error;
3932
3933         /* Update the switch rule to add the counter action */
3934         ret = ice_add_counter_act(hw, m_entry, counter_id, lg_act_id);
3935         if (!ret) {
3936                 ice_release_lock(rule_lock);
3937                 return ret;
3938         }
3939
3940 exit_error:
3941         ice_release_lock(rule_lock);
3942         /* only remove entry if it did not exist previously */
3943         if (!entry_exist)
3944                 ret = ice_remove_mac(hw, &l_head);
3945
3946         return ret;
3947 }
3948
3949 /**
3950  * ice_replay_fltr - Replay all the filters stored by a specific list head
3951  * @hw: pointer to the hardware structure
3952  * @list_head: list for which filters needs to be replayed
3953  * @recp_id: Recipe ID for which rules need to be replayed
3954  */
3955 static enum ice_status
3956 ice_replay_fltr(struct ice_hw *hw, u8 recp_id, struct LIST_HEAD_TYPE *list_head)
3957 {
3958         struct ice_fltr_mgmt_list_entry *itr;
3959         enum ice_status status = ICE_SUCCESS;
3960         struct ice_sw_recipe *recp_list;
3961         u8 lport = hw->port_info->lport;
3962         struct LIST_HEAD_TYPE l_head;
3963
3964         if (LIST_EMPTY(list_head))
3965                 return status;
3966
3967         recp_list = &hw->switch_info->recp_list[recp_id];
3968         /* Move entries from the given list_head to a temporary l_head so that
3969          * they can be replayed. Otherwise when trying to re-add the same
3970          * filter, the function will return already exists
3971          */
3972         LIST_REPLACE_INIT(list_head, &l_head);
3973
3974         /* Mark the given list_head empty by reinitializing it so filters
3975          * could be added again by *handler
3976          */
3977         LIST_FOR_EACH_ENTRY(itr, &l_head, ice_fltr_mgmt_list_entry,
3978                             list_entry) {
3979                 struct ice_fltr_list_entry f_entry;
3980                 u16 vsi_handle;
3981
3982                 f_entry.fltr_info = itr->fltr_info;
3983                 if (itr->vsi_count < 2 && recp_id != ICE_SW_LKUP_VLAN) {
3984                         status = ice_add_rule_internal(hw, recp_list, lport,
3985                                                        &f_entry);
3986                         if (status != ICE_SUCCESS)
3987                                 goto end;
3988                         continue;
3989                 }
3990
3991                 /* Add a filter per VSI separately */
3992                 ice_for_each_set_bit(vsi_handle, itr->vsi_list_info->vsi_map,
3993                                      ICE_MAX_VSI) {
3994                         if (!ice_is_vsi_valid(hw, vsi_handle))
3995                                 break;
3996
3997                         ice_clear_bit(vsi_handle, itr->vsi_list_info->vsi_map);
3998                         f_entry.fltr_info.vsi_handle = vsi_handle;
3999                         f_entry.fltr_info.fwd_id.hw_vsi_id =
4000                                 ice_get_hw_vsi_num(hw, vsi_handle);
4001                         f_entry.fltr_info.fltr_act = ICE_FWD_TO_VSI;
4002                         if (recp_id == ICE_SW_LKUP_VLAN)
4003                                 status = ice_add_vlan_internal(hw, recp_list,
4004                                                                &f_entry);
4005                         else
4006                                 status = ice_add_rule_internal(hw, recp_list,
4007                                                                lport,
4008                                                                &f_entry);
4009                         if (status != ICE_SUCCESS)
4010                                 goto end;
4011                 }
4012         }
4013 end:
4014         /* Clear the filter management list */
4015         ice_rem_sw_rule_info(hw, &l_head);
4016         return status;
4017 }
4018
4019 /**
4020  * ice_replay_all_fltr - replay all filters stored in bookkeeping lists
4021  * @hw: pointer to the hardware structure
4022  *
4023  * NOTE: This function does not clean up partially added filters on error.
4024  * It is up to caller of the function to issue a reset or fail early.
4025  */
4026 enum ice_status ice_replay_all_fltr(struct ice_hw *hw)
4027 {
4028         struct ice_switch_info *sw = hw->switch_info;
4029         enum ice_status status = ICE_SUCCESS;
4030         u8 i;
4031
4032         for (i = 0; i < ICE_MAX_NUM_RECIPES; i++) {
4033                 struct LIST_HEAD_TYPE *head = &sw->recp_list[i].filt_rules;
4034
4035                 status = ice_replay_fltr(hw, i, head);
4036                 if (status != ICE_SUCCESS)
4037                         return status;
4038         }
4039         return status;
4040 }
4041
4042 /**
4043  * ice_replay_vsi_fltr - Replay filters for requested VSI
4044  * @hw: pointer to the hardware structure
4045  * @pi: pointer to port information structure
4046  * @sw: pointer to switch info struct for which function replays filters
4047  * @vsi_handle: driver VSI handle
4048  * @recp_id: Recipe ID for which rules need to be replayed
4049  * @list_head: list for which filters need to be replayed
4050  *
4051  * Replays the filter of recipe recp_id for a VSI represented via vsi_handle.
4052  * It is required to pass valid VSI handle.
4053  */
4054 static enum ice_status
4055 ice_replay_vsi_fltr(struct ice_hw *hw, struct ice_port_info *pi,
4056                     struct ice_switch_info *sw, u16 vsi_handle, u8 recp_id,
4057                     struct LIST_HEAD_TYPE *list_head)
4058 {
4059         struct ice_fltr_mgmt_list_entry *itr;
4060         enum ice_status status = ICE_SUCCESS;
4061         struct ice_sw_recipe *recp_list;
4062         u16 hw_vsi_id;
4063
4064         if (LIST_EMPTY(list_head))
4065                 return status;
4066         recp_list = &sw->recp_list[recp_id];
4067         hw_vsi_id = ice_get_hw_vsi_num(hw, vsi_handle);
4068
4069         LIST_FOR_EACH_ENTRY(itr, list_head, ice_fltr_mgmt_list_entry,
4070                             list_entry) {
4071                 struct ice_fltr_list_entry f_entry;
4072
4073                 f_entry.fltr_info = itr->fltr_info;
4074                 if (itr->vsi_count < 2 && recp_id != ICE_SW_LKUP_VLAN &&
4075                     itr->fltr_info.vsi_handle == vsi_handle) {
4076                         /* update the src in case it is VSI num */
4077                         if (f_entry.fltr_info.src_id == ICE_SRC_ID_VSI)
4078                                 f_entry.fltr_info.src = hw_vsi_id;
4079                         status = ice_add_rule_internal(hw, recp_list,
4080                                                        pi->lport,
4081                                                        &f_entry);
4082                         if (status != ICE_SUCCESS)
4083                                 goto end;
4084                         continue;
4085                 }
4086                 if (!itr->vsi_list_info ||
4087                     !ice_is_bit_set(itr->vsi_list_info->vsi_map, vsi_handle))
4088                         continue;
4089                 /* Clearing it so that the logic can add it back */
4090                 ice_clear_bit(vsi_handle, itr->vsi_list_info->vsi_map);
4091                 f_entry.fltr_info.vsi_handle = vsi_handle;
4092                 f_entry.fltr_info.fltr_act = ICE_FWD_TO_VSI;
4093                 /* update the src in case it is VSI num */
4094                 if (f_entry.fltr_info.src_id == ICE_SRC_ID_VSI)
4095                         f_entry.fltr_info.src = hw_vsi_id;
4096                 if (recp_id == ICE_SW_LKUP_VLAN)
4097                         status = ice_add_vlan_internal(hw, recp_list, &f_entry);
4098                 else
4099                         status = ice_add_rule_internal(hw, recp_list,
4100                                                        pi->lport,
4101                                                        &f_entry);
4102                 if (status != ICE_SUCCESS)
4103                         goto end;
4104         }
4105 end:
4106         return status;
4107 }
4108
4109 /**
4110  * ice_replay_vsi_all_fltr - replay all filters stored in bookkeeping lists
4111  * @hw: pointer to the hardware structure
4112  * @pi: pointer to port information structure
4113  * @vsi_handle: driver VSI handle
4114  *
4115  * Replays filters for requested VSI via vsi_handle.
4116  */
4117 enum ice_status
4118 ice_replay_vsi_all_fltr(struct ice_hw *hw, struct ice_port_info *pi,
4119                         u16 vsi_handle)
4120 {
4121         struct ice_switch_info *sw = hw->switch_info;
4122         enum ice_status status = ICE_SUCCESS;
4123         u8 i;
4124
4125         /* Update the recipes that were created */
4126         for (i = 0; i < ICE_MAX_NUM_RECIPES; i++) {
4127                 struct LIST_HEAD_TYPE *head;
4128
4129                 head = &sw->recp_list[i].filt_replay_rules;
4130                 if (!sw->recp_list[i].adv_rule)
4131                         status = ice_replay_vsi_fltr(hw, pi, sw, vsi_handle, i,
4132                                                      head);
4133                 if (status != ICE_SUCCESS)
4134                         return status;
4135         }
4136
4137         return ICE_SUCCESS;
4138 }
4139
4140 /**
4141  * ice_rm_all_sw_replay_rule - helper function to delete filter replay rules
4142  * @hw: pointer to the HW struct
4143  * @sw: pointer to switch info struct for which function removes filters
4144  *
4145  * Deletes the filter replay rules for given switch
4146  */
4147 void ice_rm_sw_replay_rule_info(struct ice_hw *hw, struct ice_switch_info *sw)
4148 {
4149         u8 i;
4150
4151         if (!sw)
4152                 return;
4153
4154         for (i = 0; i < ICE_MAX_NUM_RECIPES; i++) {
4155                 if (!LIST_EMPTY(&sw->recp_list[i].filt_replay_rules)) {
4156                         struct LIST_HEAD_TYPE *l_head;
4157
4158                         l_head = &sw->recp_list[i].filt_replay_rules;
4159                         if (!sw->recp_list[i].adv_rule)
4160                                 ice_rem_sw_rule_info(hw, l_head);
4161                 }
4162         }
4163 }
4164
4165 /**
4166  * ice_rm_all_sw_replay_rule_info - deletes filter replay rules
4167  * @hw: pointer to the HW struct
4168  *
4169  * Deletes the filter replay rules.
4170  */
4171 void ice_rm_all_sw_replay_rule_info(struct ice_hw *hw)
4172 {
4173         ice_rm_sw_replay_rule_info(hw, hw->switch_info);
4174 }
4175