net/ice/base: declare functions as external
[dpdk.git] / drivers / net / ice / base / ice_switch.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2001-2018
3  */
4
5 #include "ice_switch.h"
6
7
8 #define ICE_ETH_DA_OFFSET               0
9 #define ICE_ETH_ETHTYPE_OFFSET          12
10 #define ICE_ETH_VLAN_TCI_OFFSET         14
11 #define ICE_MAX_VLAN_ID                 0xFFF
12
13 /* Dummy ethernet header needed in the ice_aqc_sw_rules_elem
14  * struct to configure any switch filter rules.
15  * {DA (6 bytes), SA(6 bytes),
16  * Ether type (2 bytes for header without VLAN tag) OR
17  * VLAN tag (4 bytes for header with VLAN tag) }
18  *
19  * Word on Hardcoded values
20  * byte 0 = 0x2: to identify it as locally administered DA MAC
21  * byte 6 = 0x2: to identify it as locally administered SA MAC
22  * byte 12 = 0x81 & byte 13 = 0x00:
23  *      In case of VLAN filter first two bytes defines ether type (0x8100)
24  *      and remaining two bytes are placeholder for programming a given VLAN ID
25  *      In case of Ether type filter it is treated as header without VLAN tag
26  *      and byte 12 and 13 is used to program a given Ether type instead
27  */
28 #define DUMMY_ETH_HDR_LEN               16
29 static const u8 dummy_eth_header[DUMMY_ETH_HDR_LEN] = { 0x2, 0, 0, 0, 0, 0,
30                                                         0x2, 0, 0, 0, 0, 0,
31                                                         0x81, 0, 0, 0};
32
33 #define ICE_SW_RULE_RX_TX_ETH_HDR_SIZE \
34         (sizeof(struct ice_aqc_sw_rules_elem) - \
35          sizeof(((struct ice_aqc_sw_rules_elem *)0)->pdata) + \
36          sizeof(struct ice_sw_rule_lkup_rx_tx) + DUMMY_ETH_HDR_LEN - 1)
37 #define ICE_SW_RULE_RX_TX_NO_HDR_SIZE \
38         (sizeof(struct ice_aqc_sw_rules_elem) - \
39          sizeof(((struct ice_aqc_sw_rules_elem *)0)->pdata) + \
40          sizeof(struct ice_sw_rule_lkup_rx_tx) - 1)
41 #define ICE_SW_RULE_LG_ACT_SIZE(n) \
42         (sizeof(struct ice_aqc_sw_rules_elem) - \
43          sizeof(((struct ice_aqc_sw_rules_elem *)0)->pdata) + \
44          sizeof(struct ice_sw_rule_lg_act) - \
45          sizeof(((struct ice_sw_rule_lg_act *)0)->act) + \
46          ((n) * sizeof(((struct ice_sw_rule_lg_act *)0)->act)))
47 #define ICE_SW_RULE_VSI_LIST_SIZE(n) \
48         (sizeof(struct ice_aqc_sw_rules_elem) - \
49          sizeof(((struct ice_aqc_sw_rules_elem *)0)->pdata) + \
50          sizeof(struct ice_sw_rule_vsi_list) - \
51          sizeof(((struct ice_sw_rule_vsi_list *)0)->vsi) + \
52          ((n) * sizeof(((struct ice_sw_rule_vsi_list *)0)->vsi)))
53
54
55 /**
56  * ice_init_def_sw_recp - initialize the recipe book keeping tables
57  * @hw: pointer to the HW struct
58  *
59  * Allocate memory for the entire recipe table and initialize the structures/
60  * entries corresponding to basic recipes.
61  */
62 enum ice_status ice_init_def_sw_recp(struct ice_hw *hw)
63 {
64         struct ice_sw_recipe *recps;
65         u8 i;
66
67         recps = (struct ice_sw_recipe *)
68                 ice_calloc(hw, ICE_MAX_NUM_RECIPES, sizeof(*recps));
69         if (!recps)
70                 return ICE_ERR_NO_MEMORY;
71
72         for (i = 0; i < ICE_MAX_NUM_RECIPES; i++) {
73                 recps[i].root_rid = i;
74                 INIT_LIST_HEAD(&recps[i].filt_rules);
75                 INIT_LIST_HEAD(&recps[i].filt_replay_rules);
76                 ice_init_lock(&recps[i].filt_rule_lock);
77         }
78
79         hw->switch_info->recp_list = recps;
80
81         return ICE_SUCCESS;
82 }
83
84 /**
85  * ice_aq_get_sw_cfg - get switch configuration
86  * @hw: pointer to the hardware structure
87  * @buf: pointer to the result buffer
88  * @buf_size: length of the buffer available for response
89  * @req_desc: pointer to requested descriptor
90  * @num_elems: pointer to number of elements
91  * @cd: pointer to command details structure or NULL
92  *
93  * Get switch configuration (0x0200) to be placed in 'buff'.
94  * This admin command returns information such as initial VSI/port number
95  * and switch ID it belongs to.
96  *
97  * NOTE: *req_desc is both an input/output parameter.
98  * The caller of this function first calls this function with *request_desc set
99  * to 0. If the response from f/w has *req_desc set to 0, all the switch
100  * configuration information has been returned; if non-zero (meaning not all
101  * the information was returned), the caller should call this function again
102  * with *req_desc set to the previous value returned by f/w to get the
103  * next block of switch configuration information.
104  *
105  * *num_elems is output only parameter. This reflects the number of elements
106  * in response buffer. The caller of this function to use *num_elems while
107  * parsing the response buffer.
108  */
109 static enum ice_status
110 ice_aq_get_sw_cfg(struct ice_hw *hw, struct ice_aqc_get_sw_cfg_resp *buf,
111                   u16 buf_size, u16 *req_desc, u16 *num_elems,
112                   struct ice_sq_cd *cd)
113 {
114         struct ice_aqc_get_sw_cfg *cmd;
115         enum ice_status status;
116         struct ice_aq_desc desc;
117
118         ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_get_sw_cfg);
119         cmd = &desc.params.get_sw_conf;
120         cmd->element = CPU_TO_LE16(*req_desc);
121
122         status = ice_aq_send_cmd(hw, &desc, buf, buf_size, cd);
123         if (!status) {
124                 *req_desc = LE16_TO_CPU(cmd->element);
125                 *num_elems = LE16_TO_CPU(cmd->num_elems);
126         }
127
128         return status;
129 }
130
131
132 /**
133  * ice_alloc_sw - allocate resources specific to switch
134  * @hw: pointer to the HW struct
135  * @ena_stats: true to turn on VEB stats
136  * @shared_res: true for shared resource, false for dedicated resource
137  * @sw_id: switch ID returned
138  * @counter_id: VEB counter ID returned
139  *
140  * allocates switch resources (SWID and VEB counter) (0x0208)
141  */
142 enum ice_status
143 ice_alloc_sw(struct ice_hw *hw, bool ena_stats, bool shared_res, u16 *sw_id,
144              u16 *counter_id)
145 {
146         struct ice_aqc_alloc_free_res_elem *sw_buf;
147         struct ice_aqc_res_elem *sw_ele;
148         enum ice_status status;
149         u16 buf_len;
150
151         buf_len = sizeof(*sw_buf);
152         sw_buf = (struct ice_aqc_alloc_free_res_elem *)
153                    ice_malloc(hw, buf_len);
154         if (!sw_buf)
155                 return ICE_ERR_NO_MEMORY;
156
157         /* Prepare buffer for switch ID.
158          * The number of resource entries in buffer is passed as 1 since only a
159          * single switch/VEB instance is allocated, and hence a single sw_id
160          * is requested.
161          */
162         sw_buf->num_elems = CPU_TO_LE16(1);
163         sw_buf->res_type =
164                 CPU_TO_LE16(ICE_AQC_RES_TYPE_SWID |
165                             (shared_res ? ICE_AQC_RES_TYPE_FLAG_SHARED :
166                             ICE_AQC_RES_TYPE_FLAG_DEDICATED));
167
168         status = ice_aq_alloc_free_res(hw, 1, sw_buf, buf_len,
169                                        ice_aqc_opc_alloc_res, NULL);
170
171         if (status)
172                 goto ice_alloc_sw_exit;
173
174         sw_ele = &sw_buf->elem[0];
175         *sw_id = LE16_TO_CPU(sw_ele->e.sw_resp);
176
177         if (ena_stats) {
178                 /* Prepare buffer for VEB Counter */
179                 enum ice_adminq_opc opc = ice_aqc_opc_alloc_res;
180                 struct ice_aqc_alloc_free_res_elem *counter_buf;
181                 struct ice_aqc_res_elem *counter_ele;
182
183                 counter_buf = (struct ice_aqc_alloc_free_res_elem *)
184                                 ice_malloc(hw, buf_len);
185                 if (!counter_buf) {
186                         status = ICE_ERR_NO_MEMORY;
187                         goto ice_alloc_sw_exit;
188                 }
189
190                 /* The number of resource entries in buffer is passed as 1 since
191                  * only a single switch/VEB instance is allocated, and hence a
192                  * single VEB counter is requested.
193                  */
194                 counter_buf->num_elems = CPU_TO_LE16(1);
195                 counter_buf->res_type =
196                         CPU_TO_LE16(ICE_AQC_RES_TYPE_VEB_COUNTER |
197                                     ICE_AQC_RES_TYPE_FLAG_DEDICATED);
198                 status = ice_aq_alloc_free_res(hw, 1, counter_buf, buf_len,
199                                                opc, NULL);
200
201                 if (status) {
202                         ice_free(hw, counter_buf);
203                         goto ice_alloc_sw_exit;
204                 }
205                 counter_ele = &counter_buf->elem[0];
206                 *counter_id = LE16_TO_CPU(counter_ele->e.sw_resp);
207                 ice_free(hw, counter_buf);
208         }
209
210 ice_alloc_sw_exit:
211         ice_free(hw, sw_buf);
212         return status;
213 }
214
215 /**
216  * ice_free_sw - free resources specific to switch
217  * @hw: pointer to the HW struct
218  * @sw_id: switch ID returned
219  * @counter_id: VEB counter ID returned
220  *
221  * free switch resources (SWID and VEB counter) (0x0209)
222  *
223  * NOTE: This function frees multiple resources. It continues
224  * releasing other resources even after it encounters error.
225  * The error code returned is the last error it encountered.
226  */
227 enum ice_status ice_free_sw(struct ice_hw *hw, u16 sw_id, u16 counter_id)
228 {
229         struct ice_aqc_alloc_free_res_elem *sw_buf, *counter_buf;
230         enum ice_status status, ret_status;
231         u16 buf_len;
232
233         buf_len = sizeof(*sw_buf);
234         sw_buf = (struct ice_aqc_alloc_free_res_elem *)
235                    ice_malloc(hw, buf_len);
236         if (!sw_buf)
237                 return ICE_ERR_NO_MEMORY;
238
239         /* Prepare buffer to free for switch ID res.
240          * The number of resource entries in buffer is passed as 1 since only a
241          * single switch/VEB instance is freed, and hence a single sw_id
242          * is released.
243          */
244         sw_buf->num_elems = CPU_TO_LE16(1);
245         sw_buf->res_type = CPU_TO_LE16(ICE_AQC_RES_TYPE_SWID);
246         sw_buf->elem[0].e.sw_resp = CPU_TO_LE16(sw_id);
247
248         ret_status = ice_aq_alloc_free_res(hw, 1, sw_buf, buf_len,
249                                            ice_aqc_opc_free_res, NULL);
250
251         if (ret_status)
252                 ice_debug(hw, ICE_DBG_SW, "CQ CMD Buffer:\n");
253
254         /* Prepare buffer to free for VEB Counter resource */
255         counter_buf = (struct ice_aqc_alloc_free_res_elem *)
256                         ice_malloc(hw, buf_len);
257         if (!counter_buf) {
258                 ice_free(hw, sw_buf);
259                 return ICE_ERR_NO_MEMORY;
260         }
261
262         /* The number of resource entries in buffer is passed as 1 since only a
263          * single switch/VEB instance is freed, and hence a single VEB counter
264          * is released
265          */
266         counter_buf->num_elems = CPU_TO_LE16(1);
267         counter_buf->res_type = CPU_TO_LE16(ICE_AQC_RES_TYPE_VEB_COUNTER);
268         counter_buf->elem[0].e.sw_resp = CPU_TO_LE16(counter_id);
269
270         status = ice_aq_alloc_free_res(hw, 1, counter_buf, buf_len,
271                                        ice_aqc_opc_free_res, NULL);
272         if (status) {
273                 ice_debug(hw, ICE_DBG_SW,
274                           "VEB counter resource could not be freed\n");
275                 ret_status = status;
276         }
277
278         ice_free(hw, counter_buf);
279         ice_free(hw, sw_buf);
280         return ret_status;
281 }
282
283 /**
284  * ice_aq_add_vsi
285  * @hw: pointer to the HW struct
286  * @vsi_ctx: pointer to a VSI context struct
287  * @cd: pointer to command details structure or NULL
288  *
289  * Add a VSI context to the hardware (0x0210)
290  */
291 enum ice_status
292 ice_aq_add_vsi(struct ice_hw *hw, struct ice_vsi_ctx *vsi_ctx,
293                struct ice_sq_cd *cd)
294 {
295         struct ice_aqc_add_update_free_vsi_resp *res;
296         struct ice_aqc_add_get_update_free_vsi *cmd;
297         struct ice_aq_desc desc;
298         enum ice_status status;
299
300         cmd = &desc.params.vsi_cmd;
301         res = &desc.params.add_update_free_vsi_res;
302
303         ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_add_vsi);
304
305         if (!vsi_ctx->alloc_from_pool)
306                 cmd->vsi_num = CPU_TO_LE16(vsi_ctx->vsi_num |
307                                            ICE_AQ_VSI_IS_VALID);
308
309         cmd->vsi_flags = CPU_TO_LE16(vsi_ctx->flags);
310
311         desc.flags |= CPU_TO_LE16(ICE_AQ_FLAG_RD);
312
313         status = ice_aq_send_cmd(hw, &desc, &vsi_ctx->info,
314                                  sizeof(vsi_ctx->info), cd);
315
316         if (!status) {
317                 vsi_ctx->vsi_num = LE16_TO_CPU(res->vsi_num) & ICE_AQ_VSI_NUM_M;
318                 vsi_ctx->vsis_allocd = LE16_TO_CPU(res->vsi_used);
319                 vsi_ctx->vsis_unallocated = LE16_TO_CPU(res->vsi_free);
320         }
321
322         return status;
323 }
324
325 /**
326  * ice_aq_free_vsi
327  * @hw: pointer to the HW struct
328  * @vsi_ctx: pointer to a VSI context struct
329  * @keep_vsi_alloc: keep VSI allocation as part of this PF's resources
330  * @cd: pointer to command details structure or NULL
331  *
332  * Free VSI context info from hardware (0x0213)
333  */
334 enum ice_status
335 ice_aq_free_vsi(struct ice_hw *hw, struct ice_vsi_ctx *vsi_ctx,
336                 bool keep_vsi_alloc, struct ice_sq_cd *cd)
337 {
338         struct ice_aqc_add_update_free_vsi_resp *resp;
339         struct ice_aqc_add_get_update_free_vsi *cmd;
340         struct ice_aq_desc desc;
341         enum ice_status status;
342
343         cmd = &desc.params.vsi_cmd;
344         resp = &desc.params.add_update_free_vsi_res;
345
346         ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_free_vsi);
347
348         cmd->vsi_num = CPU_TO_LE16(vsi_ctx->vsi_num | ICE_AQ_VSI_IS_VALID);
349         if (keep_vsi_alloc)
350                 cmd->cmd_flags = CPU_TO_LE16(ICE_AQ_VSI_KEEP_ALLOC);
351
352         status = ice_aq_send_cmd(hw, &desc, NULL, 0, cd);
353         if (!status) {
354                 vsi_ctx->vsis_allocd = LE16_TO_CPU(resp->vsi_used);
355                 vsi_ctx->vsis_unallocated = LE16_TO_CPU(resp->vsi_free);
356         }
357
358         return status;
359 }
360
361 /**
362  * ice_aq_update_vsi
363  * @hw: pointer to the HW struct
364  * @vsi_ctx: pointer to a VSI context struct
365  * @cd: pointer to command details structure or NULL
366  *
367  * Update VSI context in the hardware (0x0211)
368  */
369 enum ice_status
370 ice_aq_update_vsi(struct ice_hw *hw, struct ice_vsi_ctx *vsi_ctx,
371                   struct ice_sq_cd *cd)
372 {
373         struct ice_aqc_add_update_free_vsi_resp *resp;
374         struct ice_aqc_add_get_update_free_vsi *cmd;
375         struct ice_aq_desc desc;
376         enum ice_status status;
377
378         cmd = &desc.params.vsi_cmd;
379         resp = &desc.params.add_update_free_vsi_res;
380
381         ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_update_vsi);
382
383         cmd->vsi_num = CPU_TO_LE16(vsi_ctx->vsi_num | ICE_AQ_VSI_IS_VALID);
384
385         desc.flags |= CPU_TO_LE16(ICE_AQ_FLAG_RD);
386
387         status = ice_aq_send_cmd(hw, &desc, &vsi_ctx->info,
388                                  sizeof(vsi_ctx->info), cd);
389
390         if (!status) {
391                 vsi_ctx->vsis_allocd = LE16_TO_CPU(resp->vsi_used);
392                 vsi_ctx->vsis_unallocated = LE16_TO_CPU(resp->vsi_free);
393         }
394
395         return status;
396 }
397
398 /**
399  * ice_is_vsi_valid - check whether the VSI is valid or not
400  * @hw: pointer to the HW struct
401  * @vsi_handle: VSI handle
402  *
403  * check whether the VSI is valid or not
404  */
405 bool ice_is_vsi_valid(struct ice_hw *hw, u16 vsi_handle)
406 {
407         return vsi_handle < ICE_MAX_VSI && hw->vsi_ctx[vsi_handle];
408 }
409
410 /**
411  * ice_get_hw_vsi_num - return the HW VSI number
412  * @hw: pointer to the HW struct
413  * @vsi_handle: VSI handle
414  *
415  * return the HW VSI number
416  * Caution: call this function only if VSI is valid (ice_is_vsi_valid)
417  */
418 u16 ice_get_hw_vsi_num(struct ice_hw *hw, u16 vsi_handle)
419 {
420         return hw->vsi_ctx[vsi_handle]->vsi_num;
421 }
422
423 /**
424  * ice_get_vsi_ctx - return the VSI context entry for a given VSI handle
425  * @hw: pointer to the HW struct
426  * @vsi_handle: VSI handle
427  *
428  * return the VSI context entry for a given VSI handle
429  */
430 struct ice_vsi_ctx *ice_get_vsi_ctx(struct ice_hw *hw, u16 vsi_handle)
431 {
432         return (vsi_handle >= ICE_MAX_VSI) ? NULL : hw->vsi_ctx[vsi_handle];
433 }
434
435 /**
436  * ice_save_vsi_ctx - save the VSI context for a given VSI handle
437  * @hw: pointer to the HW struct
438  * @vsi_handle: VSI handle
439  * @vsi: VSI context pointer
440  *
441  * save the VSI context entry for a given VSI handle
442  */
443 static void
444 ice_save_vsi_ctx(struct ice_hw *hw, u16 vsi_handle, struct ice_vsi_ctx *vsi)
445 {
446         hw->vsi_ctx[vsi_handle] = vsi;
447 }
448
449 /**
450  * ice_clear_vsi_ctx - clear the VSI context entry
451  * @hw: pointer to the HW struct
452  * @vsi_handle: VSI handle
453  *
454  * clear the VSI context entry
455  */
456 static void ice_clear_vsi_ctx(struct ice_hw *hw, u16 vsi_handle)
457 {
458         struct ice_vsi_ctx *vsi;
459
460         vsi = ice_get_vsi_ctx(hw, vsi_handle);
461         if (vsi) {
462                 ice_destroy_lock(&vsi->rss_locks);
463                 ice_free(hw, vsi);
464                 hw->vsi_ctx[vsi_handle] = NULL;
465         }
466 }
467
468 /**
469  * ice_clear_all_vsi_ctx - clear all the VSI context entries
470  * @hw: pointer to the HW struct
471  */
472 void ice_clear_all_vsi_ctx(struct ice_hw *hw)
473 {
474         u16 i;
475
476         for (i = 0; i < ICE_MAX_VSI; i++)
477                 ice_clear_vsi_ctx(hw, i);
478 }
479
480 /**
481  * ice_add_vsi - add VSI context to the hardware and VSI handle list
482  * @hw: pointer to the HW struct
483  * @vsi_handle: unique VSI handle provided by drivers
484  * @vsi_ctx: pointer to a VSI context struct
485  * @cd: pointer to command details structure or NULL
486  *
487  * Add a VSI context to the hardware also add it into the VSI handle list.
488  * If this function gets called after reset for existing VSIs then update
489  * with the new HW VSI number in the corresponding VSI handle list entry.
490  */
491 enum ice_status
492 ice_add_vsi(struct ice_hw *hw, u16 vsi_handle, struct ice_vsi_ctx *vsi_ctx,
493             struct ice_sq_cd *cd)
494 {
495         struct ice_vsi_ctx *tmp_vsi_ctx;
496         enum ice_status status;
497
498         if (vsi_handle >= ICE_MAX_VSI)
499                 return ICE_ERR_PARAM;
500         status = ice_aq_add_vsi(hw, vsi_ctx, cd);
501         if (status)
502                 return status;
503         tmp_vsi_ctx = ice_get_vsi_ctx(hw, vsi_handle);
504         if (!tmp_vsi_ctx) {
505                 /* Create a new VSI context */
506                 tmp_vsi_ctx = (struct ice_vsi_ctx *)
507                         ice_malloc(hw, sizeof(*tmp_vsi_ctx));
508                 if (!tmp_vsi_ctx) {
509                         ice_aq_free_vsi(hw, vsi_ctx, false, cd);
510                         return ICE_ERR_NO_MEMORY;
511                 }
512                 *tmp_vsi_ctx = *vsi_ctx;
513                 ice_init_lock(&tmp_vsi_ctx->rss_locks);
514                 INIT_LIST_HEAD(&tmp_vsi_ctx->rss_list_head);
515                 ice_save_vsi_ctx(hw, vsi_handle, tmp_vsi_ctx);
516         } else {
517                 /* update with new HW VSI num */
518                 if (tmp_vsi_ctx->vsi_num != vsi_ctx->vsi_num)
519                         tmp_vsi_ctx->vsi_num = vsi_ctx->vsi_num;
520         }
521
522         return ICE_SUCCESS;
523 }
524
525 /**
526  * ice_free_vsi- free VSI context from hardware and VSI handle list
527  * @hw: pointer to the HW struct
528  * @vsi_handle: unique VSI handle
529  * @vsi_ctx: pointer to a VSI context struct
530  * @keep_vsi_alloc: keep VSI allocation as part of this PF's resources
531  * @cd: pointer to command details structure or NULL
532  *
533  * Free VSI context info from hardware as well as from VSI handle list
534  */
535 enum ice_status
536 ice_free_vsi(struct ice_hw *hw, u16 vsi_handle, struct ice_vsi_ctx *vsi_ctx,
537              bool keep_vsi_alloc, struct ice_sq_cd *cd)
538 {
539         enum ice_status status;
540
541         if (!ice_is_vsi_valid(hw, vsi_handle))
542                 return ICE_ERR_PARAM;
543         vsi_ctx->vsi_num = ice_get_hw_vsi_num(hw, vsi_handle);
544         status = ice_aq_free_vsi(hw, vsi_ctx, keep_vsi_alloc, cd);
545         if (!status)
546                 ice_clear_vsi_ctx(hw, vsi_handle);
547         return status;
548 }
549
550 /**
551  * ice_update_vsi
552  * @hw: pointer to the HW struct
553  * @vsi_handle: unique VSI handle
554  * @vsi_ctx: pointer to a VSI context struct
555  * @cd: pointer to command details structure or NULL
556  *
557  * Update VSI context in the hardware
558  */
559 enum ice_status
560 ice_update_vsi(struct ice_hw *hw, u16 vsi_handle, struct ice_vsi_ctx *vsi_ctx,
561                struct ice_sq_cd *cd)
562 {
563         if (!ice_is_vsi_valid(hw, vsi_handle))
564                 return ICE_ERR_PARAM;
565         vsi_ctx->vsi_num = ice_get_hw_vsi_num(hw, vsi_handle);
566         return ice_aq_update_vsi(hw, vsi_ctx, cd);
567 }
568
569
570
571 /**
572  * ice_aq_alloc_free_vsi_list
573  * @hw: pointer to the HW struct
574  * @vsi_list_id: VSI list ID returned or used for lookup
575  * @lkup_type: switch rule filter lookup type
576  * @opc: switch rules population command type - pass in the command opcode
577  *
578  * allocates or free a VSI list resource
579  */
580 static enum ice_status
581 ice_aq_alloc_free_vsi_list(struct ice_hw *hw, u16 *vsi_list_id,
582                            enum ice_sw_lkup_type lkup_type,
583                            enum ice_adminq_opc opc)
584 {
585         struct ice_aqc_alloc_free_res_elem *sw_buf;
586         struct ice_aqc_res_elem *vsi_ele;
587         enum ice_status status;
588         u16 buf_len;
589
590         buf_len = sizeof(*sw_buf);
591         sw_buf = (struct ice_aqc_alloc_free_res_elem *)
592                 ice_malloc(hw, buf_len);
593         if (!sw_buf)
594                 return ICE_ERR_NO_MEMORY;
595         sw_buf->num_elems = CPU_TO_LE16(1);
596
597         if (lkup_type == ICE_SW_LKUP_MAC ||
598             lkup_type == ICE_SW_LKUP_MAC_VLAN ||
599             lkup_type == ICE_SW_LKUP_ETHERTYPE ||
600             lkup_type == ICE_SW_LKUP_ETHERTYPE_MAC ||
601             lkup_type == ICE_SW_LKUP_PROMISC ||
602             lkup_type == ICE_SW_LKUP_PROMISC_VLAN) {
603                 sw_buf->res_type = CPU_TO_LE16(ICE_AQC_RES_TYPE_VSI_LIST_REP);
604         } else if (lkup_type == ICE_SW_LKUP_VLAN) {
605                 sw_buf->res_type =
606                         CPU_TO_LE16(ICE_AQC_RES_TYPE_VSI_LIST_PRUNE);
607         } else {
608                 status = ICE_ERR_PARAM;
609                 goto ice_aq_alloc_free_vsi_list_exit;
610         }
611
612         if (opc == ice_aqc_opc_free_res)
613                 sw_buf->elem[0].e.sw_resp = CPU_TO_LE16(*vsi_list_id);
614
615         status = ice_aq_alloc_free_res(hw, 1, sw_buf, buf_len, opc, NULL);
616         if (status)
617                 goto ice_aq_alloc_free_vsi_list_exit;
618
619         if (opc == ice_aqc_opc_alloc_res) {
620                 vsi_ele = &sw_buf->elem[0];
621                 *vsi_list_id = LE16_TO_CPU(vsi_ele->e.sw_resp);
622         }
623
624 ice_aq_alloc_free_vsi_list_exit:
625         ice_free(hw, sw_buf);
626         return status;
627 }
628
629
630 /**
631  * ice_aq_sw_rules - add/update/remove switch rules
632  * @hw: pointer to the HW struct
633  * @rule_list: pointer to switch rule population list
634  * @rule_list_sz: total size of the rule list in bytes
635  * @num_rules: number of switch rules in the rule_list
636  * @opc: switch rules population command type - pass in the command opcode
637  * @cd: pointer to command details structure or NULL
638  *
639  * Add(0x02a0)/Update(0x02a1)/Remove(0x02a2) switch rules commands to firmware
640  */
641 static enum ice_status
642 ice_aq_sw_rules(struct ice_hw *hw, void *rule_list, u16 rule_list_sz,
643                 u8 num_rules, enum ice_adminq_opc opc, struct ice_sq_cd *cd)
644 {
645         struct ice_aq_desc desc;
646
647         ice_debug(hw, ICE_DBG_TRACE, "ice_aq_sw_rules");
648
649         if (opc != ice_aqc_opc_add_sw_rules &&
650             opc != ice_aqc_opc_update_sw_rules &&
651             opc != ice_aqc_opc_remove_sw_rules)
652                 return ICE_ERR_PARAM;
653
654         ice_fill_dflt_direct_cmd_desc(&desc, opc);
655
656         desc.flags |= CPU_TO_LE16(ICE_AQ_FLAG_RD);
657         desc.params.sw_rules.num_rules_fltr_entry_index =
658                 CPU_TO_LE16(num_rules);
659         return ice_aq_send_cmd(hw, &desc, rule_list, rule_list_sz, cd);
660 }
661
662
663 /* ice_init_port_info - Initialize port_info with switch configuration data
664  * @pi: pointer to port_info
665  * @vsi_port_num: VSI number or port number
666  * @type: Type of switch element (port or VSI)
667  * @swid: switch ID of the switch the element is attached to
668  * @pf_vf_num: PF or VF number
669  * @is_vf: true if the element is a VF, false otherwise
670  */
671 static void
672 ice_init_port_info(struct ice_port_info *pi, u16 vsi_port_num, u8 type,
673                    u16 swid, u16 pf_vf_num, bool is_vf)
674 {
675         switch (type) {
676         case ICE_AQC_GET_SW_CONF_RESP_PHYS_PORT:
677                 pi->lport = (u8)(vsi_port_num & ICE_LPORT_MASK);
678                 pi->sw_id = swid;
679                 pi->pf_vf_num = pf_vf_num;
680                 pi->is_vf = is_vf;
681                 pi->dflt_tx_vsi_num = ICE_DFLT_VSI_INVAL;
682                 pi->dflt_rx_vsi_num = ICE_DFLT_VSI_INVAL;
683                 break;
684         default:
685                 ice_debug(pi->hw, ICE_DBG_SW,
686                           "incorrect VSI/port type received\n");
687                 break;
688         }
689 }
690
691 /* ice_get_initial_sw_cfg - Get initial port and default VSI data
692  * @hw: pointer to the hardware structure
693  */
694 enum ice_status ice_get_initial_sw_cfg(struct ice_hw *hw)
695 {
696         struct ice_aqc_get_sw_cfg_resp *rbuf;
697         enum ice_status status;
698         u16 num_total_ports;
699         u16 req_desc = 0;
700         u16 num_elems;
701         u16 j = 0;
702         u16 i;
703
704         num_total_ports = 1;
705
706         rbuf = (struct ice_aqc_get_sw_cfg_resp *)
707                 ice_malloc(hw, ICE_SW_CFG_MAX_BUF_LEN);
708
709         if (!rbuf)
710                 return ICE_ERR_NO_MEMORY;
711
712         /* Multiple calls to ice_aq_get_sw_cfg may be required
713          * to get all the switch configuration information. The need
714          * for additional calls is indicated by ice_aq_get_sw_cfg
715          * writing a non-zero value in req_desc
716          */
717         do {
718                 status = ice_aq_get_sw_cfg(hw, rbuf, ICE_SW_CFG_MAX_BUF_LEN,
719                                            &req_desc, &num_elems, NULL);
720
721                 if (status)
722                         break;
723
724                 for (i = 0; i < num_elems; i++) {
725                         struct ice_aqc_get_sw_cfg_resp_elem *ele;
726                         u16 pf_vf_num, swid, vsi_port_num;
727                         bool is_vf = false;
728                         u8 type;
729
730                         ele = rbuf[i].elements;
731                         vsi_port_num = LE16_TO_CPU(ele->vsi_port_num) &
732                                 ICE_AQC_GET_SW_CONF_RESP_VSI_PORT_NUM_M;
733
734                         pf_vf_num = LE16_TO_CPU(ele->pf_vf_num) &
735                                 ICE_AQC_GET_SW_CONF_RESP_FUNC_NUM_M;
736
737                         swid = LE16_TO_CPU(ele->swid);
738
739                         if (LE16_TO_CPU(ele->pf_vf_num) &
740                             ICE_AQC_GET_SW_CONF_RESP_IS_VF)
741                                 is_vf = true;
742
743                         type = LE16_TO_CPU(ele->vsi_port_num) >>
744                                 ICE_AQC_GET_SW_CONF_RESP_TYPE_S;
745
746                         switch (type) {
747                         case ICE_AQC_GET_SW_CONF_RESP_PHYS_PORT:
748                         case ICE_AQC_GET_SW_CONF_RESP_VIRT_PORT:
749                                 if (j == num_total_ports) {
750                                         ice_debug(hw, ICE_DBG_SW,
751                                                   "more ports than expected\n");
752                                         status = ICE_ERR_CFG;
753                                         goto out;
754                                 }
755                                 ice_init_port_info(hw->port_info,
756                                                    vsi_port_num, type, swid,
757                                                    pf_vf_num, is_vf);
758                                 j++;
759                                 break;
760                         default:
761                                 break;
762                         }
763                 }
764         } while (req_desc && !status);
765
766
767 out:
768         ice_free(hw, (void *)rbuf);
769         return status;
770 }
771
772
773 /**
774  * ice_fill_sw_info - Helper function to populate lb_en and lan_en
775  * @hw: pointer to the hardware structure
776  * @fi: filter info structure to fill/update
777  *
778  * This helper function populates the lb_en and lan_en elements of the provided
779  * ice_fltr_info struct using the switch's type and characteristics of the
780  * switch rule being configured.
781  */
782 static void ice_fill_sw_info(struct ice_hw *hw, struct ice_fltr_info *fi)
783 {
784         fi->lb_en = false;
785         fi->lan_en = false;
786         if ((fi->flag & ICE_FLTR_TX) &&
787             (fi->fltr_act == ICE_FWD_TO_VSI ||
788              fi->fltr_act == ICE_FWD_TO_VSI_LIST ||
789              fi->fltr_act == ICE_FWD_TO_Q ||
790              fi->fltr_act == ICE_FWD_TO_QGRP)) {
791                 /* Setting LB for prune actions will result in replicated
792                  * packets to the internal switch that will be dropped.
793                  */
794                 if (fi->lkup_type != ICE_SW_LKUP_VLAN)
795                         fi->lb_en = true;
796
797                 /* Set lan_en to TRUE if
798                  * 1. The switch is a VEB AND
799                  * 2
800                  * 2.1 The lookup is a directional lookup like ethertype,
801                  * promiscuous, ethertype-MAC, promiscuous-VLAN
802                  * and default-port OR
803                  * 2.2 The lookup is VLAN, OR
804                  * 2.3 The lookup is MAC with mcast or bcast addr for MAC, OR
805                  * 2.4 The lookup is MAC_VLAN with mcast or bcast addr for MAC.
806                  *
807                  * OR
808                  *
809                  * The switch is a VEPA.
810                  *
811                  * In all other cases, the LAN enable has to be set to false.
812                  */
813                 if (hw->evb_veb) {
814                         if (fi->lkup_type == ICE_SW_LKUP_ETHERTYPE ||
815                             fi->lkup_type == ICE_SW_LKUP_PROMISC ||
816                             fi->lkup_type == ICE_SW_LKUP_ETHERTYPE_MAC ||
817                             fi->lkup_type == ICE_SW_LKUP_PROMISC_VLAN ||
818                             fi->lkup_type == ICE_SW_LKUP_DFLT ||
819                             fi->lkup_type == ICE_SW_LKUP_VLAN ||
820                             (fi->lkup_type == ICE_SW_LKUP_MAC &&
821                              !IS_UNICAST_ETHER_ADDR(fi->l_data.mac.mac_addr)) ||
822                             (fi->lkup_type == ICE_SW_LKUP_MAC_VLAN &&
823                              !IS_UNICAST_ETHER_ADDR(fi->l_data.mac.mac_addr)))
824                                 fi->lan_en = true;
825                 } else {
826                         fi->lan_en = true;
827                 }
828         }
829 }
830
831 /**
832  * ice_ilog2 - Calculates integer log base 2 of a number
833  * @n: number on which to perform operation
834  */
835 static int ice_ilog2(u64 n)
836 {
837         int i;
838
839         for (i = 63; i >= 0; i--)
840                 if (((u64)1 << i) & n)
841                         return i;
842
843         return -1;
844 }
845
846
847 /**
848  * ice_fill_sw_rule - Helper function to fill switch rule structure
849  * @hw: pointer to the hardware structure
850  * @f_info: entry containing packet forwarding information
851  * @s_rule: switch rule structure to be filled in based on mac_entry
852  * @opc: switch rules population command type - pass in the command opcode
853  */
854 static void
855 ice_fill_sw_rule(struct ice_hw *hw, struct ice_fltr_info *f_info,
856                  struct ice_aqc_sw_rules_elem *s_rule, enum ice_adminq_opc opc)
857 {
858         u16 vlan_id = ICE_MAX_VLAN_ID + 1;
859         void *daddr = NULL;
860         u16 eth_hdr_sz;
861         u8 *eth_hdr;
862         u32 act = 0;
863         __be16 *off;
864         u8 q_rgn;
865
866
867         if (opc == ice_aqc_opc_remove_sw_rules) {
868                 s_rule->pdata.lkup_tx_rx.act = 0;
869                 s_rule->pdata.lkup_tx_rx.index =
870                         CPU_TO_LE16(f_info->fltr_rule_id);
871                 s_rule->pdata.lkup_tx_rx.hdr_len = 0;
872                 return;
873         }
874
875         eth_hdr_sz = sizeof(dummy_eth_header);
876         eth_hdr = s_rule->pdata.lkup_tx_rx.hdr;
877
878         /* initialize the ether header with a dummy header */
879         ice_memcpy(eth_hdr, dummy_eth_header, eth_hdr_sz, ICE_NONDMA_TO_NONDMA);
880         ice_fill_sw_info(hw, f_info);
881
882         switch (f_info->fltr_act) {
883         case ICE_FWD_TO_VSI:
884                 act |= (f_info->fwd_id.hw_vsi_id << ICE_SINGLE_ACT_VSI_ID_S) &
885                         ICE_SINGLE_ACT_VSI_ID_M;
886                 if (f_info->lkup_type != ICE_SW_LKUP_VLAN)
887                         act |= ICE_SINGLE_ACT_VSI_FORWARDING |
888                                 ICE_SINGLE_ACT_VALID_BIT;
889                 break;
890         case ICE_FWD_TO_VSI_LIST:
891                 act |= ICE_SINGLE_ACT_VSI_LIST;
892                 act |= (f_info->fwd_id.vsi_list_id <<
893                         ICE_SINGLE_ACT_VSI_LIST_ID_S) &
894                         ICE_SINGLE_ACT_VSI_LIST_ID_M;
895                 if (f_info->lkup_type != ICE_SW_LKUP_VLAN)
896                         act |= ICE_SINGLE_ACT_VSI_FORWARDING |
897                                 ICE_SINGLE_ACT_VALID_BIT;
898                 break;
899         case ICE_FWD_TO_Q:
900                 act |= ICE_SINGLE_ACT_TO_Q;
901                 act |= (f_info->fwd_id.q_id << ICE_SINGLE_ACT_Q_INDEX_S) &
902                         ICE_SINGLE_ACT_Q_INDEX_M;
903                 break;
904         case ICE_DROP_PACKET:
905                 act |= ICE_SINGLE_ACT_VSI_FORWARDING | ICE_SINGLE_ACT_DROP |
906                         ICE_SINGLE_ACT_VALID_BIT;
907                 break;
908         case ICE_FWD_TO_QGRP:
909                 q_rgn = f_info->qgrp_size > 0 ?
910                         (u8)ice_ilog2(f_info->qgrp_size) : 0;
911                 act |= ICE_SINGLE_ACT_TO_Q;
912                 act |= (f_info->fwd_id.q_id << ICE_SINGLE_ACT_Q_INDEX_S) &
913                         ICE_SINGLE_ACT_Q_INDEX_M;
914                 act |= (q_rgn << ICE_SINGLE_ACT_Q_REGION_S) &
915                         ICE_SINGLE_ACT_Q_REGION_M;
916                 break;
917         default:
918                 return;
919         }
920
921         if (f_info->lb_en)
922                 act |= ICE_SINGLE_ACT_LB_ENABLE;
923         if (f_info->lan_en)
924                 act |= ICE_SINGLE_ACT_LAN_ENABLE;
925
926         switch (f_info->lkup_type) {
927         case ICE_SW_LKUP_MAC:
928                 daddr = f_info->l_data.mac.mac_addr;
929                 break;
930         case ICE_SW_LKUP_VLAN:
931                 vlan_id = f_info->l_data.vlan.vlan_id;
932                 if (f_info->fltr_act == ICE_FWD_TO_VSI ||
933                     f_info->fltr_act == ICE_FWD_TO_VSI_LIST) {
934                         act |= ICE_SINGLE_ACT_PRUNE;
935                         act |= ICE_SINGLE_ACT_EGRESS | ICE_SINGLE_ACT_INGRESS;
936                 }
937                 break;
938         case ICE_SW_LKUP_ETHERTYPE_MAC:
939                 daddr = f_info->l_data.ethertype_mac.mac_addr;
940                 /* fall-through */
941         case ICE_SW_LKUP_ETHERTYPE:
942                 off = (__be16 *)(eth_hdr + ICE_ETH_ETHTYPE_OFFSET);
943                 *off = CPU_TO_BE16(f_info->l_data.ethertype_mac.ethertype);
944                 break;
945         case ICE_SW_LKUP_MAC_VLAN:
946                 daddr = f_info->l_data.mac_vlan.mac_addr;
947                 vlan_id = f_info->l_data.mac_vlan.vlan_id;
948                 break;
949         case ICE_SW_LKUP_PROMISC_VLAN:
950                 vlan_id = f_info->l_data.mac_vlan.vlan_id;
951                 /* fall-through */
952         case ICE_SW_LKUP_PROMISC:
953                 daddr = f_info->l_data.mac_vlan.mac_addr;
954                 break;
955         default:
956                 break;
957         }
958
959         s_rule->type = (f_info->flag & ICE_FLTR_RX) ?
960                 CPU_TO_LE16(ICE_AQC_SW_RULES_T_LKUP_RX) :
961                 CPU_TO_LE16(ICE_AQC_SW_RULES_T_LKUP_TX);
962
963         /* Recipe set depending on lookup type */
964         s_rule->pdata.lkup_tx_rx.recipe_id = CPU_TO_LE16(f_info->lkup_type);
965         s_rule->pdata.lkup_tx_rx.src = CPU_TO_LE16(f_info->src);
966         s_rule->pdata.lkup_tx_rx.act = CPU_TO_LE32(act);
967
968         if (daddr)
969                 ice_memcpy(eth_hdr + ICE_ETH_DA_OFFSET, daddr, ETH_ALEN,
970                            ICE_NONDMA_TO_NONDMA);
971
972         if (!(vlan_id > ICE_MAX_VLAN_ID)) {
973                 off = (__be16 *)(eth_hdr + ICE_ETH_VLAN_TCI_OFFSET);
974                 *off = CPU_TO_BE16(vlan_id);
975         }
976
977         /* Create the switch rule with the final dummy Ethernet header */
978         if (opc != ice_aqc_opc_update_sw_rules)
979                 s_rule->pdata.lkup_tx_rx.hdr_len = CPU_TO_LE16(eth_hdr_sz);
980 }
981
982 /**
983  * ice_add_marker_act
984  * @hw: pointer to the hardware structure
985  * @m_ent: the management entry for which sw marker needs to be added
986  * @sw_marker: sw marker to tag the Rx descriptor with
987  * @l_id: large action resource ID
988  *
989  * Create a large action to hold software marker and update the switch rule
990  * entry pointed by m_ent with newly created large action
991  */
992 static enum ice_status
993 ice_add_marker_act(struct ice_hw *hw, struct ice_fltr_mgmt_list_entry *m_ent,
994                    u16 sw_marker, u16 l_id)
995 {
996         struct ice_aqc_sw_rules_elem *lg_act, *rx_tx;
997         /* For software marker we need 3 large actions
998          * 1. FWD action: FWD TO VSI or VSI LIST
999          * 2. GENERIC VALUE action to hold the profile ID
1000          * 3. GENERIC VALUE action to hold the software marker ID
1001          */
1002         const u16 num_lg_acts = 3;
1003         enum ice_status status;
1004         u16 lg_act_size;
1005         u16 rules_size;
1006         u32 act;
1007         u16 id;
1008
1009         if (m_ent->fltr_info.lkup_type != ICE_SW_LKUP_MAC)
1010                 return ICE_ERR_PARAM;
1011
1012         /* Create two back-to-back switch rules and submit them to the HW using
1013          * one memory buffer:
1014          *    1. Large Action
1015          *    2. Look up Tx Rx
1016          */
1017         lg_act_size = (u16)ICE_SW_RULE_LG_ACT_SIZE(num_lg_acts);
1018         rules_size = lg_act_size + ICE_SW_RULE_RX_TX_ETH_HDR_SIZE;
1019         lg_act = (struct ice_aqc_sw_rules_elem *)ice_malloc(hw, rules_size);
1020         if (!lg_act)
1021                 return ICE_ERR_NO_MEMORY;
1022
1023         rx_tx = (struct ice_aqc_sw_rules_elem *)((u8 *)lg_act + lg_act_size);
1024
1025         /* Fill in the first switch rule i.e. large action */
1026         lg_act->type = CPU_TO_LE16(ICE_AQC_SW_RULES_T_LG_ACT);
1027         lg_act->pdata.lg_act.index = CPU_TO_LE16(l_id);
1028         lg_act->pdata.lg_act.size = CPU_TO_LE16(num_lg_acts);
1029
1030         /* First action VSI forwarding or VSI list forwarding depending on how
1031          * many VSIs
1032          */
1033         id = (m_ent->vsi_count > 1) ? m_ent->fltr_info.fwd_id.vsi_list_id :
1034                 m_ent->fltr_info.fwd_id.hw_vsi_id;
1035
1036         act = ICE_LG_ACT_VSI_FORWARDING | ICE_LG_ACT_VALID_BIT;
1037         act |= (id << ICE_LG_ACT_VSI_LIST_ID_S) &
1038                 ICE_LG_ACT_VSI_LIST_ID_M;
1039         if (m_ent->vsi_count > 1)
1040                 act |= ICE_LG_ACT_VSI_LIST;
1041         lg_act->pdata.lg_act.act[0] = CPU_TO_LE32(act);
1042
1043         /* Second action descriptor type */
1044         act = ICE_LG_ACT_GENERIC;
1045
1046         act |= (1 << ICE_LG_ACT_GENERIC_VALUE_S) & ICE_LG_ACT_GENERIC_VALUE_M;
1047         lg_act->pdata.lg_act.act[1] = CPU_TO_LE32(act);
1048
1049         act = (ICE_LG_ACT_GENERIC_OFF_RX_DESC_PROF_IDX <<
1050                ICE_LG_ACT_GENERIC_OFFSET_S) & ICE_LG_ACT_GENERIC_OFFSET_M;
1051
1052         /* Third action Marker value */
1053         act |= ICE_LG_ACT_GENERIC;
1054         act |= (sw_marker << ICE_LG_ACT_GENERIC_VALUE_S) &
1055                 ICE_LG_ACT_GENERIC_VALUE_M;
1056
1057         lg_act->pdata.lg_act.act[2] = CPU_TO_LE32(act);
1058
1059         /* call the fill switch rule to fill the lookup Tx Rx structure */
1060         ice_fill_sw_rule(hw, &m_ent->fltr_info, rx_tx,
1061                          ice_aqc_opc_update_sw_rules);
1062
1063         /* Update the action to point to the large action ID */
1064         rx_tx->pdata.lkup_tx_rx.act =
1065                 CPU_TO_LE32(ICE_SINGLE_ACT_PTR |
1066                             ((l_id << ICE_SINGLE_ACT_PTR_VAL_S) &
1067                              ICE_SINGLE_ACT_PTR_VAL_M));
1068
1069         /* Use the filter rule ID of the previously created rule with single
1070          * act. Once the update happens, hardware will treat this as large
1071          * action
1072          */
1073         rx_tx->pdata.lkup_tx_rx.index =
1074                 CPU_TO_LE16(m_ent->fltr_info.fltr_rule_id);
1075
1076         status = ice_aq_sw_rules(hw, lg_act, rules_size, 2,
1077                                  ice_aqc_opc_update_sw_rules, NULL);
1078         if (!status) {
1079                 m_ent->lg_act_idx = l_id;
1080                 m_ent->sw_marker_id = sw_marker;
1081         }
1082
1083         ice_free(hw, lg_act);
1084         return status;
1085 }
1086
1087
1088 /**
1089  * ice_create_vsi_list_map
1090  * @hw: pointer to the hardware structure
1091  * @vsi_handle_arr: array of VSI handles to set in the VSI mapping
1092  * @num_vsi: number of VSI handles in the array
1093  * @vsi_list_id: VSI list ID generated as part of allocate resource
1094  *
1095  * Helper function to create a new entry of VSI list ID to VSI mapping
1096  * using the given VSI list ID
1097  */
1098 static struct ice_vsi_list_map_info *
1099 ice_create_vsi_list_map(struct ice_hw *hw, u16 *vsi_handle_arr, u16 num_vsi,
1100                         u16 vsi_list_id)
1101 {
1102         struct ice_switch_info *sw = hw->switch_info;
1103         struct ice_vsi_list_map_info *v_map;
1104         int i;
1105
1106         v_map = (struct ice_vsi_list_map_info *)ice_calloc(hw, 1,
1107                 sizeof(*v_map));
1108         if (!v_map)
1109                 return NULL;
1110
1111         v_map->vsi_list_id = vsi_list_id;
1112         v_map->ref_cnt = 1;
1113         for (i = 0; i < num_vsi; i++)
1114                 ice_set_bit(vsi_handle_arr[i], v_map->vsi_map);
1115
1116         LIST_ADD(&v_map->list_entry, &sw->vsi_list_map_head);
1117         return v_map;
1118 }
1119
1120 /**
1121  * ice_update_vsi_list_rule
1122  * @hw: pointer to the hardware structure
1123  * @vsi_handle_arr: array of VSI handles to form a VSI list
1124  * @num_vsi: number of VSI handles in the array
1125  * @vsi_list_id: VSI list ID generated as part of allocate resource
1126  * @remove: Boolean value to indicate if this is a remove action
1127  * @opc: switch rules population command type - pass in the command opcode
1128  * @lkup_type: lookup type of the filter
1129  *
1130  * Call AQ command to add a new switch rule or update existing switch rule
1131  * using the given VSI list ID
1132  */
1133 static enum ice_status
1134 ice_update_vsi_list_rule(struct ice_hw *hw, u16 *vsi_handle_arr, u16 num_vsi,
1135                          u16 vsi_list_id, bool remove, enum ice_adminq_opc opc,
1136                          enum ice_sw_lkup_type lkup_type)
1137 {
1138         struct ice_aqc_sw_rules_elem *s_rule;
1139         enum ice_status status;
1140         u16 s_rule_size;
1141         u16 type;
1142         int i;
1143
1144         if (!num_vsi)
1145                 return ICE_ERR_PARAM;
1146
1147         if (lkup_type == ICE_SW_LKUP_MAC ||
1148             lkup_type == ICE_SW_LKUP_MAC_VLAN ||
1149             lkup_type == ICE_SW_LKUP_ETHERTYPE ||
1150             lkup_type == ICE_SW_LKUP_ETHERTYPE_MAC ||
1151             lkup_type == ICE_SW_LKUP_PROMISC ||
1152             lkup_type == ICE_SW_LKUP_PROMISC_VLAN)
1153                 type = remove ? ICE_AQC_SW_RULES_T_VSI_LIST_CLEAR :
1154                                 ICE_AQC_SW_RULES_T_VSI_LIST_SET;
1155         else if (lkup_type == ICE_SW_LKUP_VLAN)
1156                 type = remove ? ICE_AQC_SW_RULES_T_PRUNE_LIST_CLEAR :
1157                                 ICE_AQC_SW_RULES_T_PRUNE_LIST_SET;
1158         else
1159                 return ICE_ERR_PARAM;
1160
1161         s_rule_size = (u16)ICE_SW_RULE_VSI_LIST_SIZE(num_vsi);
1162         s_rule = (struct ice_aqc_sw_rules_elem *)ice_malloc(hw, s_rule_size);
1163         if (!s_rule)
1164                 return ICE_ERR_NO_MEMORY;
1165         for (i = 0; i < num_vsi; i++) {
1166                 if (!ice_is_vsi_valid(hw, vsi_handle_arr[i])) {
1167                         status = ICE_ERR_PARAM;
1168                         goto exit;
1169                 }
1170                 /* AQ call requires hw_vsi_id(s) */
1171                 s_rule->pdata.vsi_list.vsi[i] =
1172                         CPU_TO_LE16(ice_get_hw_vsi_num(hw, vsi_handle_arr[i]));
1173         }
1174
1175         s_rule->type = CPU_TO_LE16(type);
1176         s_rule->pdata.vsi_list.number_vsi = CPU_TO_LE16(num_vsi);
1177         s_rule->pdata.vsi_list.index = CPU_TO_LE16(vsi_list_id);
1178
1179         status = ice_aq_sw_rules(hw, s_rule, s_rule_size, 1, opc, NULL);
1180
1181 exit:
1182         ice_free(hw, s_rule);
1183         return status;
1184 }
1185
1186 /**
1187  * ice_create_vsi_list_rule - Creates and populates a VSI list rule
1188  * @hw: pointer to the HW struct
1189  * @vsi_handle_arr: array of VSI handles to form a VSI list
1190  * @num_vsi: number of VSI handles in the array
1191  * @vsi_list_id: stores the ID of the VSI list to be created
1192  * @lkup_type: switch rule filter's lookup type
1193  */
1194 static enum ice_status
1195 ice_create_vsi_list_rule(struct ice_hw *hw, u16 *vsi_handle_arr, u16 num_vsi,
1196                          u16 *vsi_list_id, enum ice_sw_lkup_type lkup_type)
1197 {
1198         enum ice_status status;
1199
1200         status = ice_aq_alloc_free_vsi_list(hw, vsi_list_id, lkup_type,
1201                                             ice_aqc_opc_alloc_res);
1202         if (status)
1203                 return status;
1204
1205         /* Update the newly created VSI list to include the specified VSIs */
1206         return ice_update_vsi_list_rule(hw, vsi_handle_arr, num_vsi,
1207                                         *vsi_list_id, false,
1208                                         ice_aqc_opc_add_sw_rules, lkup_type);
1209 }
1210
1211 /**
1212  * ice_create_pkt_fwd_rule
1213  * @hw: pointer to the hardware structure
1214  * @f_entry: entry containing packet forwarding information
1215  *
1216  * Create switch rule with given filter information and add an entry
1217  * to the corresponding filter management list to track this switch rule
1218  * and VSI mapping
1219  */
1220 static enum ice_status
1221 ice_create_pkt_fwd_rule(struct ice_hw *hw,
1222                         struct ice_fltr_list_entry *f_entry)
1223 {
1224         struct ice_fltr_mgmt_list_entry *fm_entry;
1225         struct ice_aqc_sw_rules_elem *s_rule;
1226         enum ice_sw_lkup_type l_type;
1227         struct ice_sw_recipe *recp;
1228         enum ice_status status;
1229
1230         s_rule = (struct ice_aqc_sw_rules_elem *)
1231                 ice_malloc(hw, ICE_SW_RULE_RX_TX_ETH_HDR_SIZE);
1232         if (!s_rule)
1233                 return ICE_ERR_NO_MEMORY;
1234         fm_entry = (struct ice_fltr_mgmt_list_entry *)
1235                    ice_malloc(hw, sizeof(*fm_entry));
1236         if (!fm_entry) {
1237                 status = ICE_ERR_NO_MEMORY;
1238                 goto ice_create_pkt_fwd_rule_exit;
1239         }
1240
1241         fm_entry->fltr_info = f_entry->fltr_info;
1242
1243         /* Initialize all the fields for the management entry */
1244         fm_entry->vsi_count = 1;
1245         fm_entry->lg_act_idx = ICE_INVAL_LG_ACT_INDEX;
1246         fm_entry->sw_marker_id = ICE_INVAL_SW_MARKER_ID;
1247         fm_entry->counter_index = ICE_INVAL_COUNTER_ID;
1248
1249         ice_fill_sw_rule(hw, &fm_entry->fltr_info, s_rule,
1250                          ice_aqc_opc_add_sw_rules);
1251
1252         status = ice_aq_sw_rules(hw, s_rule, ICE_SW_RULE_RX_TX_ETH_HDR_SIZE, 1,
1253                                  ice_aqc_opc_add_sw_rules, NULL);
1254         if (status) {
1255                 ice_free(hw, fm_entry);
1256                 goto ice_create_pkt_fwd_rule_exit;
1257         }
1258
1259         f_entry->fltr_info.fltr_rule_id =
1260                 LE16_TO_CPU(s_rule->pdata.lkup_tx_rx.index);
1261         fm_entry->fltr_info.fltr_rule_id =
1262                 LE16_TO_CPU(s_rule->pdata.lkup_tx_rx.index);
1263
1264         /* The book keeping entries will get removed when base driver
1265          * calls remove filter AQ command
1266          */
1267         l_type = fm_entry->fltr_info.lkup_type;
1268         recp = &hw->switch_info->recp_list[l_type];
1269         LIST_ADD(&fm_entry->list_entry, &recp->filt_rules);
1270
1271 ice_create_pkt_fwd_rule_exit:
1272         ice_free(hw, s_rule);
1273         return status;
1274 }
1275
1276 /**
1277  * ice_update_pkt_fwd_rule
1278  * @hw: pointer to the hardware structure
1279  * @f_info: filter information for switch rule
1280  *
1281  * Call AQ command to update a previously created switch rule with a
1282  * VSI list ID
1283  */
1284 static enum ice_status
1285 ice_update_pkt_fwd_rule(struct ice_hw *hw, struct ice_fltr_info *f_info)
1286 {
1287         struct ice_aqc_sw_rules_elem *s_rule;
1288         enum ice_status status;
1289
1290         s_rule = (struct ice_aqc_sw_rules_elem *)
1291                 ice_malloc(hw, ICE_SW_RULE_RX_TX_ETH_HDR_SIZE);
1292         if (!s_rule)
1293                 return ICE_ERR_NO_MEMORY;
1294
1295         ice_fill_sw_rule(hw, f_info, s_rule, ice_aqc_opc_update_sw_rules);
1296
1297         s_rule->pdata.lkup_tx_rx.index = CPU_TO_LE16(f_info->fltr_rule_id);
1298
1299         /* Update switch rule with new rule set to forward VSI list */
1300         status = ice_aq_sw_rules(hw, s_rule, ICE_SW_RULE_RX_TX_ETH_HDR_SIZE, 1,
1301                                  ice_aqc_opc_update_sw_rules, NULL);
1302
1303         ice_free(hw, s_rule);
1304         return status;
1305 }
1306
1307 /**
1308  * ice_update_sw_rule_bridge_mode
1309  * @hw: pointer to the HW struct
1310  *
1311  * Updates unicast switch filter rules based on VEB/VEPA mode
1312  */
1313 enum ice_status ice_update_sw_rule_bridge_mode(struct ice_hw *hw)
1314 {
1315         struct ice_switch_info *sw = hw->switch_info;
1316         struct ice_fltr_mgmt_list_entry *fm_entry;
1317         enum ice_status status = ICE_SUCCESS;
1318         struct LIST_HEAD_TYPE *rule_head;
1319         struct ice_lock *rule_lock; /* Lock to protect filter rule list */
1320
1321         rule_lock = &sw->recp_list[ICE_SW_LKUP_MAC].filt_rule_lock;
1322         rule_head = &sw->recp_list[ICE_SW_LKUP_MAC].filt_rules;
1323
1324         ice_acquire_lock(rule_lock);
1325         LIST_FOR_EACH_ENTRY(fm_entry, rule_head, ice_fltr_mgmt_list_entry,
1326                             list_entry) {
1327                 struct ice_fltr_info *fi = &fm_entry->fltr_info;
1328                 u8 *addr = fi->l_data.mac.mac_addr;
1329
1330                 /* Update unicast Tx rules to reflect the selected
1331                  * VEB/VEPA mode
1332                  */
1333                 if ((fi->flag & ICE_FLTR_TX) && IS_UNICAST_ETHER_ADDR(addr) &&
1334                     (fi->fltr_act == ICE_FWD_TO_VSI ||
1335                      fi->fltr_act == ICE_FWD_TO_VSI_LIST ||
1336                      fi->fltr_act == ICE_FWD_TO_Q ||
1337                      fi->fltr_act == ICE_FWD_TO_QGRP)) {
1338                         status = ice_update_pkt_fwd_rule(hw, fi);
1339                         if (status)
1340                                 break;
1341                 }
1342         }
1343
1344         ice_release_lock(rule_lock);
1345
1346         return status;
1347 }
1348
1349 /**
1350  * ice_add_update_vsi_list
1351  * @hw: pointer to the hardware structure
1352  * @m_entry: pointer to current filter management list entry
1353  * @cur_fltr: filter information from the book keeping entry
1354  * @new_fltr: filter information with the new VSI to be added
1355  *
1356  * Call AQ command to add or update previously created VSI list with new VSI.
1357  *
1358  * Helper function to do book keeping associated with adding filter information
1359  * The algorithm to do the book keeping is described below :
1360  * When a VSI needs to subscribe to a given filter (MAC/VLAN/Ethtype etc.)
1361  *      if only one VSI has been added till now
1362  *              Allocate a new VSI list and add two VSIs
1363  *              to this list using switch rule command
1364  *              Update the previously created switch rule with the
1365  *              newly created VSI list ID
1366  *      if a VSI list was previously created
1367  *              Add the new VSI to the previously created VSI list set
1368  *              using the update switch rule command
1369  */
1370 static enum ice_status
1371 ice_add_update_vsi_list(struct ice_hw *hw,
1372                         struct ice_fltr_mgmt_list_entry *m_entry,
1373                         struct ice_fltr_info *cur_fltr,
1374                         struct ice_fltr_info *new_fltr)
1375 {
1376         enum ice_status status = ICE_SUCCESS;
1377         u16 vsi_list_id = 0;
1378
1379         if ((cur_fltr->fltr_act == ICE_FWD_TO_Q ||
1380              cur_fltr->fltr_act == ICE_FWD_TO_QGRP))
1381                 return ICE_ERR_NOT_IMPL;
1382
1383         if ((new_fltr->fltr_act == ICE_FWD_TO_Q ||
1384              new_fltr->fltr_act == ICE_FWD_TO_QGRP) &&
1385             (cur_fltr->fltr_act == ICE_FWD_TO_VSI ||
1386              cur_fltr->fltr_act == ICE_FWD_TO_VSI_LIST))
1387                 return ICE_ERR_NOT_IMPL;
1388
1389         if (m_entry->vsi_count < 2 && !m_entry->vsi_list_info) {
1390                 /* Only one entry existed in the mapping and it was not already
1391                  * a part of a VSI list. So, create a VSI list with the old and
1392                  * new VSIs.
1393                  */
1394                 struct ice_fltr_info tmp_fltr;
1395                 u16 vsi_handle_arr[2];
1396
1397                 /* A rule already exists with the new VSI being added */
1398                 if (cur_fltr->fwd_id.hw_vsi_id == new_fltr->fwd_id.hw_vsi_id)
1399                         return ICE_ERR_ALREADY_EXISTS;
1400
1401                 vsi_handle_arr[0] = cur_fltr->vsi_handle;
1402                 vsi_handle_arr[1] = new_fltr->vsi_handle;
1403                 status = ice_create_vsi_list_rule(hw, &vsi_handle_arr[0], 2,
1404                                                   &vsi_list_id,
1405                                                   new_fltr->lkup_type);
1406                 if (status)
1407                         return status;
1408
1409                 tmp_fltr = *new_fltr;
1410                 tmp_fltr.fltr_rule_id = cur_fltr->fltr_rule_id;
1411                 tmp_fltr.fltr_act = ICE_FWD_TO_VSI_LIST;
1412                 tmp_fltr.fwd_id.vsi_list_id = vsi_list_id;
1413                 /* Update the previous switch rule of "MAC forward to VSI" to
1414                  * "MAC fwd to VSI list"
1415                  */
1416                 status = ice_update_pkt_fwd_rule(hw, &tmp_fltr);
1417                 if (status)
1418                         return status;
1419
1420                 cur_fltr->fwd_id.vsi_list_id = vsi_list_id;
1421                 cur_fltr->fltr_act = ICE_FWD_TO_VSI_LIST;
1422                 m_entry->vsi_list_info =
1423                         ice_create_vsi_list_map(hw, &vsi_handle_arr[0], 2,
1424                                                 vsi_list_id);
1425
1426                 /* If this entry was large action then the large action needs
1427                  * to be updated to point to FWD to VSI list
1428                  */
1429                 if (m_entry->sw_marker_id != ICE_INVAL_SW_MARKER_ID)
1430                         status =
1431                             ice_add_marker_act(hw, m_entry,
1432                                                m_entry->sw_marker_id,
1433                                                m_entry->lg_act_idx);
1434         } else {
1435                 u16 vsi_handle = new_fltr->vsi_handle;
1436                 enum ice_adminq_opc opcode;
1437
1438                 if (!m_entry->vsi_list_info)
1439                         return ICE_ERR_CFG;
1440
1441                 /* A rule already exists with the new VSI being added */
1442                 if (ice_is_bit_set(m_entry->vsi_list_info->vsi_map, vsi_handle))
1443                         return ICE_SUCCESS;
1444
1445                 /* Update the previously created VSI list set with
1446                  * the new VSI ID passed in
1447                  */
1448                 vsi_list_id = cur_fltr->fwd_id.vsi_list_id;
1449                 opcode = ice_aqc_opc_update_sw_rules;
1450
1451                 status = ice_update_vsi_list_rule(hw, &vsi_handle, 1,
1452                                                   vsi_list_id, false, opcode,
1453                                                   new_fltr->lkup_type);
1454                 /* update VSI list mapping info with new VSI ID */
1455                 if (!status)
1456                         ice_set_bit(vsi_handle,
1457                                     m_entry->vsi_list_info->vsi_map);
1458         }
1459         if (!status)
1460                 m_entry->vsi_count++;
1461         return status;
1462 }
1463
1464 /**
1465  * ice_find_rule_entry - Search a rule entry
1466  * @hw: pointer to the hardware structure
1467  * @recp_id: lookup type for which the specified rule needs to be searched
1468  * @f_info: rule information
1469  *
1470  * Helper function to search for a given rule entry
1471  * Returns pointer to entry storing the rule if found
1472  */
1473 static struct ice_fltr_mgmt_list_entry *
1474 ice_find_rule_entry(struct ice_hw *hw, u8 recp_id, struct ice_fltr_info *f_info)
1475 {
1476         struct ice_fltr_mgmt_list_entry *list_itr, *ret = NULL;
1477         struct ice_switch_info *sw = hw->switch_info;
1478         struct LIST_HEAD_TYPE *list_head;
1479
1480         list_head = &sw->recp_list[recp_id].filt_rules;
1481         LIST_FOR_EACH_ENTRY(list_itr, list_head, ice_fltr_mgmt_list_entry,
1482                             list_entry) {
1483                 if (!memcmp(&f_info->l_data, &list_itr->fltr_info.l_data,
1484                             sizeof(f_info->l_data)) &&
1485                     f_info->flag == list_itr->fltr_info.flag) {
1486                         ret = list_itr;
1487                         break;
1488                 }
1489         }
1490         return ret;
1491 }
1492
1493 /**
1494  * ice_find_vsi_list_entry - Search VSI list map with VSI count 1
1495  * @hw: pointer to the hardware structure
1496  * @recp_id: lookup type for which VSI lists needs to be searched
1497  * @vsi_handle: VSI handle to be found in VSI list
1498  * @vsi_list_id: VSI list ID found containing vsi_handle
1499  *
1500  * Helper function to search a VSI list with single entry containing given VSI
1501  * handle element. This can be extended further to search VSI list with more
1502  * than 1 vsi_count. Returns pointer to VSI list entry if found.
1503  */
1504 static struct ice_vsi_list_map_info *
1505 ice_find_vsi_list_entry(struct ice_hw *hw, u8 recp_id, u16 vsi_handle,
1506                         u16 *vsi_list_id)
1507 {
1508         struct ice_vsi_list_map_info *map_info = NULL;
1509         struct ice_switch_info *sw = hw->switch_info;
1510         struct ice_fltr_mgmt_list_entry *list_itr;
1511         struct LIST_HEAD_TYPE *list_head;
1512
1513         list_head = &sw->recp_list[recp_id].filt_rules;
1514         LIST_FOR_EACH_ENTRY(list_itr, list_head, ice_fltr_mgmt_list_entry,
1515                             list_entry) {
1516                 if (list_itr->vsi_count == 1 && list_itr->vsi_list_info) {
1517                         map_info = list_itr->vsi_list_info;
1518                         if (ice_is_bit_set(map_info->vsi_map, vsi_handle)) {
1519                                 *vsi_list_id = map_info->vsi_list_id;
1520                                 return map_info;
1521                         }
1522                 }
1523         }
1524         return NULL;
1525 }
1526
1527 /**
1528  * ice_add_rule_internal - add rule for a given lookup type
1529  * @hw: pointer to the hardware structure
1530  * @recp_id: lookup type (recipe ID) for which rule has to be added
1531  * @f_entry: structure containing MAC forwarding information
1532  *
1533  * Adds or updates the rule lists for a given recipe
1534  */
1535 static enum ice_status
1536 ice_add_rule_internal(struct ice_hw *hw, u8 recp_id,
1537                       struct ice_fltr_list_entry *f_entry)
1538 {
1539         struct ice_switch_info *sw = hw->switch_info;
1540         struct ice_fltr_info *new_fltr, *cur_fltr;
1541         struct ice_fltr_mgmt_list_entry *m_entry;
1542         struct ice_lock *rule_lock; /* Lock to protect filter rule list */
1543         enum ice_status status = ICE_SUCCESS;
1544
1545         if (!ice_is_vsi_valid(hw, f_entry->fltr_info.vsi_handle))
1546                 return ICE_ERR_PARAM;
1547
1548         /* Load the hw_vsi_id only if the fwd action is fwd to VSI */
1549         if (f_entry->fltr_info.fltr_act == ICE_FWD_TO_VSI)
1550                 f_entry->fltr_info.fwd_id.hw_vsi_id =
1551                         ice_get_hw_vsi_num(hw, f_entry->fltr_info.vsi_handle);
1552
1553         rule_lock = &sw->recp_list[recp_id].filt_rule_lock;
1554
1555         ice_acquire_lock(rule_lock);
1556         new_fltr = &f_entry->fltr_info;
1557         if (new_fltr->flag & ICE_FLTR_RX)
1558                 new_fltr->src = hw->port_info->lport;
1559         else if (new_fltr->flag & ICE_FLTR_TX)
1560                 new_fltr->src =
1561                         ice_get_hw_vsi_num(hw, f_entry->fltr_info.vsi_handle);
1562
1563         m_entry = ice_find_rule_entry(hw, recp_id, new_fltr);
1564         if (!m_entry) {
1565                 ice_release_lock(rule_lock);
1566                 return ice_create_pkt_fwd_rule(hw, f_entry);
1567         }
1568
1569         cur_fltr = &m_entry->fltr_info;
1570         status = ice_add_update_vsi_list(hw, m_entry, cur_fltr, new_fltr);
1571         ice_release_lock(rule_lock);
1572
1573         return status;
1574 }
1575
1576 /**
1577  * ice_remove_vsi_list_rule
1578  * @hw: pointer to the hardware structure
1579  * @vsi_list_id: VSI list ID generated as part of allocate resource
1580  * @lkup_type: switch rule filter lookup type
1581  *
1582  * The VSI list should be emptied before this function is called to remove the
1583  * VSI list.
1584  */
1585 static enum ice_status
1586 ice_remove_vsi_list_rule(struct ice_hw *hw, u16 vsi_list_id,
1587                          enum ice_sw_lkup_type lkup_type)
1588 {
1589         struct ice_aqc_sw_rules_elem *s_rule;
1590         enum ice_status status;
1591         u16 s_rule_size;
1592
1593         s_rule_size = (u16)ICE_SW_RULE_VSI_LIST_SIZE(0);
1594         s_rule = (struct ice_aqc_sw_rules_elem *)ice_malloc(hw, s_rule_size);
1595         if (!s_rule)
1596                 return ICE_ERR_NO_MEMORY;
1597
1598         s_rule->type = CPU_TO_LE16(ICE_AQC_SW_RULES_T_VSI_LIST_CLEAR);
1599         s_rule->pdata.vsi_list.index = CPU_TO_LE16(vsi_list_id);
1600
1601         /* Free the vsi_list resource that we allocated. It is assumed that the
1602          * list is empty at this point.
1603          */
1604         status = ice_aq_alloc_free_vsi_list(hw, &vsi_list_id, lkup_type,
1605                                             ice_aqc_opc_free_res);
1606
1607         ice_free(hw, s_rule);
1608         return status;
1609 }
1610
1611 /**
1612  * ice_rem_update_vsi_list
1613  * @hw: pointer to the hardware structure
1614  * @vsi_handle: VSI handle of the VSI to remove
1615  * @fm_list: filter management entry for which the VSI list management needs to
1616  *           be done
1617  */
1618 static enum ice_status
1619 ice_rem_update_vsi_list(struct ice_hw *hw, u16 vsi_handle,
1620                         struct ice_fltr_mgmt_list_entry *fm_list)
1621 {
1622         enum ice_sw_lkup_type lkup_type;
1623         enum ice_status status = ICE_SUCCESS;
1624         u16 vsi_list_id;
1625
1626         if (fm_list->fltr_info.fltr_act != ICE_FWD_TO_VSI_LIST ||
1627             fm_list->vsi_count == 0)
1628                 return ICE_ERR_PARAM;
1629
1630         /* A rule with the VSI being removed does not exist */
1631         if (!ice_is_bit_set(fm_list->vsi_list_info->vsi_map, vsi_handle))
1632                 return ICE_ERR_DOES_NOT_EXIST;
1633
1634         lkup_type = fm_list->fltr_info.lkup_type;
1635         vsi_list_id = fm_list->fltr_info.fwd_id.vsi_list_id;
1636         status = ice_update_vsi_list_rule(hw, &vsi_handle, 1, vsi_list_id, true,
1637                                           ice_aqc_opc_update_sw_rules,
1638                                           lkup_type);
1639         if (status)
1640                 return status;
1641
1642         fm_list->vsi_count--;
1643         ice_clear_bit(vsi_handle, fm_list->vsi_list_info->vsi_map);
1644
1645         if (fm_list->vsi_count == 1 && lkup_type != ICE_SW_LKUP_VLAN) {
1646                 struct ice_fltr_info tmp_fltr_info = fm_list->fltr_info;
1647                 struct ice_vsi_list_map_info *vsi_list_info =
1648                         fm_list->vsi_list_info;
1649                 u16 rem_vsi_handle;
1650
1651                 rem_vsi_handle = ice_find_first_bit(vsi_list_info->vsi_map,
1652                                                     ICE_MAX_VSI);
1653                 if (!ice_is_vsi_valid(hw, rem_vsi_handle))
1654                         return ICE_ERR_OUT_OF_RANGE;
1655
1656                 /* Make sure VSI list is empty before removing it below */
1657                 status = ice_update_vsi_list_rule(hw, &rem_vsi_handle, 1,
1658                                                   vsi_list_id, true,
1659                                                   ice_aqc_opc_update_sw_rules,
1660                                                   lkup_type);
1661                 if (status)
1662                         return status;
1663
1664                 tmp_fltr_info.fltr_act = ICE_FWD_TO_VSI;
1665                 tmp_fltr_info.fwd_id.hw_vsi_id =
1666                         ice_get_hw_vsi_num(hw, rem_vsi_handle);
1667                 tmp_fltr_info.vsi_handle = rem_vsi_handle;
1668                 status = ice_update_pkt_fwd_rule(hw, &tmp_fltr_info);
1669                 if (status) {
1670                         ice_debug(hw, ICE_DBG_SW,
1671                                   "Failed to update pkt fwd rule to FWD_TO_VSI on HW VSI %d, error %d\n",
1672                                   tmp_fltr_info.fwd_id.hw_vsi_id, status);
1673                         return status;
1674                 }
1675
1676                 fm_list->fltr_info = tmp_fltr_info;
1677         }
1678
1679         if ((fm_list->vsi_count == 1 && lkup_type != ICE_SW_LKUP_VLAN) ||
1680             (fm_list->vsi_count == 0 && lkup_type == ICE_SW_LKUP_VLAN)) {
1681                 struct ice_vsi_list_map_info *vsi_list_info =
1682                         fm_list->vsi_list_info;
1683
1684                 /* Remove the VSI list since it is no longer used */
1685                 status = ice_remove_vsi_list_rule(hw, vsi_list_id, lkup_type);
1686                 if (status) {
1687                         ice_debug(hw, ICE_DBG_SW,
1688                                   "Failed to remove VSI list %d, error %d\n",
1689                                   vsi_list_id, status);
1690                         return status;
1691                 }
1692
1693                 LIST_DEL(&vsi_list_info->list_entry);
1694                 ice_free(hw, vsi_list_info);
1695                 fm_list->vsi_list_info = NULL;
1696         }
1697
1698         return status;
1699 }
1700
1701 /**
1702  * ice_remove_rule_internal - Remove a filter rule of a given type
1703  *
1704  * @hw: pointer to the hardware structure
1705  * @recp_id: recipe ID for which the rule needs to removed
1706  * @f_entry: rule entry containing filter information
1707  */
1708 static enum ice_status
1709 ice_remove_rule_internal(struct ice_hw *hw, u8 recp_id,
1710                          struct ice_fltr_list_entry *f_entry)
1711 {
1712         struct ice_switch_info *sw = hw->switch_info;
1713         struct ice_fltr_mgmt_list_entry *list_elem;
1714         struct ice_lock *rule_lock; /* Lock to protect filter rule list */
1715         enum ice_status status = ICE_SUCCESS;
1716         bool remove_rule = false;
1717         u16 vsi_handle;
1718
1719         if (!ice_is_vsi_valid(hw, f_entry->fltr_info.vsi_handle))
1720                 return ICE_ERR_PARAM;
1721         f_entry->fltr_info.fwd_id.hw_vsi_id =
1722                 ice_get_hw_vsi_num(hw, f_entry->fltr_info.vsi_handle);
1723
1724         rule_lock = &sw->recp_list[recp_id].filt_rule_lock;
1725         ice_acquire_lock(rule_lock);
1726         list_elem = ice_find_rule_entry(hw, recp_id, &f_entry->fltr_info);
1727         if (!list_elem) {
1728                 status = ICE_ERR_DOES_NOT_EXIST;
1729                 goto exit;
1730         }
1731
1732         if (list_elem->fltr_info.fltr_act != ICE_FWD_TO_VSI_LIST) {
1733                 remove_rule = true;
1734         } else if (!list_elem->vsi_list_info) {
1735                 status = ICE_ERR_DOES_NOT_EXIST;
1736                 goto exit;
1737         } else if (list_elem->vsi_list_info->ref_cnt > 1) {
1738                 /* a ref_cnt > 1 indicates that the vsi_list is being
1739                  * shared by multiple rules. Decrement the ref_cnt and
1740                  * remove this rule, but do not modify the list, as it
1741                  * is in-use by other rules.
1742                  */
1743                 list_elem->vsi_list_info->ref_cnt--;
1744                 remove_rule = true;
1745         } else {
1746                 /* a ref_cnt of 1 indicates the vsi_list is only used
1747                  * by one rule. However, the original removal request is only
1748                  * for a single VSI. Update the vsi_list first, and only
1749                  * remove the rule if there are no further VSIs in this list.
1750                  */
1751                 vsi_handle = f_entry->fltr_info.vsi_handle;
1752                 status = ice_rem_update_vsi_list(hw, vsi_handle, list_elem);
1753                 if (status)
1754                         goto exit;
1755                 /* if VSI count goes to zero after updating the VSI list */
1756                 if (list_elem->vsi_count == 0)
1757                         remove_rule = true;
1758         }
1759
1760         if (remove_rule) {
1761                 /* Remove the lookup rule */
1762                 struct ice_aqc_sw_rules_elem *s_rule;
1763
1764                 s_rule = (struct ice_aqc_sw_rules_elem *)
1765                         ice_malloc(hw, ICE_SW_RULE_RX_TX_NO_HDR_SIZE);
1766                 if (!s_rule) {
1767                         status = ICE_ERR_NO_MEMORY;
1768                         goto exit;
1769                 }
1770
1771                 ice_fill_sw_rule(hw, &list_elem->fltr_info, s_rule,
1772                                  ice_aqc_opc_remove_sw_rules);
1773
1774                 status = ice_aq_sw_rules(hw, s_rule,
1775                                          ICE_SW_RULE_RX_TX_NO_HDR_SIZE, 1,
1776                                          ice_aqc_opc_remove_sw_rules, NULL);
1777                 if (status)
1778                         goto exit;
1779
1780                 /* Remove a book keeping from the list */
1781                 ice_free(hw, s_rule);
1782
1783                 LIST_DEL(&list_elem->list_entry);
1784                 ice_free(hw, list_elem);
1785         }
1786 exit:
1787         ice_release_lock(rule_lock);
1788         return status;
1789 }
1790
1791
1792 /**
1793  * ice_add_mac - Add a MAC address based filter rule
1794  * @hw: pointer to the hardware structure
1795  * @m_list: list of MAC addresses and forwarding information
1796  *
1797  * IMPORTANT: When the ucast_shared flag is set to false and m_list has
1798  * multiple unicast addresses, the function assumes that all the
1799  * addresses are unique in a given add_mac call. It doesn't
1800  * check for duplicates in this case, removing duplicates from a given
1801  * list should be taken care of in the caller of this function.
1802  */
1803 enum ice_status
1804 ice_add_mac(struct ice_hw *hw, struct LIST_HEAD_TYPE *m_list)
1805 {
1806         struct ice_aqc_sw_rules_elem *s_rule, *r_iter;
1807         struct ice_fltr_list_entry *m_list_itr;
1808         struct LIST_HEAD_TYPE *rule_head;
1809         u16 elem_sent, total_elem_left;
1810         struct ice_switch_info *sw;
1811         struct ice_lock *rule_lock; /* Lock to protect filter rule list */
1812         enum ice_status status = ICE_SUCCESS;
1813         u16 num_unicast = 0;
1814         u16 s_rule_size;
1815
1816         if (!m_list || !hw)
1817                 return ICE_ERR_PARAM;
1818         s_rule = NULL;
1819         sw = hw->switch_info;
1820         rule_lock = &sw->recp_list[ICE_SW_LKUP_MAC].filt_rule_lock;
1821         LIST_FOR_EACH_ENTRY(m_list_itr, m_list, ice_fltr_list_entry,
1822                             list_entry) {
1823                 u8 *add = &m_list_itr->fltr_info.l_data.mac.mac_addr[0];
1824                 u16 vsi_handle;
1825                 u16 hw_vsi_id;
1826
1827                 m_list_itr->fltr_info.flag = ICE_FLTR_TX;
1828                 vsi_handle = m_list_itr->fltr_info.vsi_handle;
1829                 if (!ice_is_vsi_valid(hw, vsi_handle))
1830                         return ICE_ERR_PARAM;
1831                 hw_vsi_id = ice_get_hw_vsi_num(hw, vsi_handle);
1832                 m_list_itr->fltr_info.fwd_id.hw_vsi_id = hw_vsi_id;
1833                 /* update the src in case it is VSI num */
1834                 if (m_list_itr->fltr_info.src_id != ICE_SRC_ID_VSI)
1835                         return ICE_ERR_PARAM;
1836                 m_list_itr->fltr_info.src = hw_vsi_id;
1837                 if (m_list_itr->fltr_info.lkup_type != ICE_SW_LKUP_MAC ||
1838                     IS_ZERO_ETHER_ADDR(add))
1839                         return ICE_ERR_PARAM;
1840                 if (IS_UNICAST_ETHER_ADDR(add) && !hw->ucast_shared) {
1841                         /* Don't overwrite the unicast address */
1842                         ice_acquire_lock(rule_lock);
1843                         if (ice_find_rule_entry(hw, ICE_SW_LKUP_MAC,
1844                                                 &m_list_itr->fltr_info)) {
1845                                 ice_release_lock(rule_lock);
1846                                 return ICE_ERR_ALREADY_EXISTS;
1847                         }
1848                         ice_release_lock(rule_lock);
1849                         num_unicast++;
1850                 } else if (IS_MULTICAST_ETHER_ADDR(add) ||
1851                            (IS_UNICAST_ETHER_ADDR(add) && hw->ucast_shared)) {
1852                         m_list_itr->status =
1853                                 ice_add_rule_internal(hw, ICE_SW_LKUP_MAC,
1854                                                       m_list_itr);
1855                         if (m_list_itr->status)
1856                                 return m_list_itr->status;
1857                 }
1858         }
1859
1860         ice_acquire_lock(rule_lock);
1861         /* Exit if no suitable entries were found for adding bulk switch rule */
1862         if (!num_unicast) {
1863                 status = ICE_SUCCESS;
1864                 goto ice_add_mac_exit;
1865         }
1866
1867         rule_head = &sw->recp_list[ICE_SW_LKUP_MAC].filt_rules;
1868
1869         /* Allocate switch rule buffer for the bulk update for unicast */
1870         s_rule_size = ICE_SW_RULE_RX_TX_ETH_HDR_SIZE;
1871         s_rule = (struct ice_aqc_sw_rules_elem *)
1872                 ice_calloc(hw, num_unicast, s_rule_size);
1873         if (!s_rule) {
1874                 status = ICE_ERR_NO_MEMORY;
1875                 goto ice_add_mac_exit;
1876         }
1877
1878         r_iter = s_rule;
1879         LIST_FOR_EACH_ENTRY(m_list_itr, m_list, ice_fltr_list_entry,
1880                             list_entry) {
1881                 struct ice_fltr_info *f_info = &m_list_itr->fltr_info;
1882                 u8 *mac_addr = &f_info->l_data.mac.mac_addr[0];
1883
1884                 if (IS_UNICAST_ETHER_ADDR(mac_addr)) {
1885                         ice_fill_sw_rule(hw, &m_list_itr->fltr_info, r_iter,
1886                                          ice_aqc_opc_add_sw_rules);
1887                         r_iter = (struct ice_aqc_sw_rules_elem *)
1888                                 ((u8 *)r_iter + s_rule_size);
1889                 }
1890         }
1891
1892         /* Call AQ bulk switch rule update for all unicast addresses */
1893         r_iter = s_rule;
1894         /* Call AQ switch rule in AQ_MAX chunk */
1895         for (total_elem_left = num_unicast; total_elem_left > 0;
1896              total_elem_left -= elem_sent) {
1897                 struct ice_aqc_sw_rules_elem *entry = r_iter;
1898
1899                 elem_sent = min(total_elem_left,
1900                                 (u16)(ICE_AQ_MAX_BUF_LEN / s_rule_size));
1901                 status = ice_aq_sw_rules(hw, entry, elem_sent * s_rule_size,
1902                                          elem_sent, ice_aqc_opc_add_sw_rules,
1903                                          NULL);
1904                 if (status)
1905                         goto ice_add_mac_exit;
1906                 r_iter = (struct ice_aqc_sw_rules_elem *)
1907                         ((u8 *)r_iter + (elem_sent * s_rule_size));
1908         }
1909
1910         /* Fill up rule ID based on the value returned from FW */
1911         r_iter = s_rule;
1912         LIST_FOR_EACH_ENTRY(m_list_itr, m_list, ice_fltr_list_entry,
1913                             list_entry) {
1914                 struct ice_fltr_info *f_info = &m_list_itr->fltr_info;
1915                 u8 *mac_addr = &f_info->l_data.mac.mac_addr[0];
1916                 struct ice_fltr_mgmt_list_entry *fm_entry;
1917
1918                 if (IS_UNICAST_ETHER_ADDR(mac_addr)) {
1919                         f_info->fltr_rule_id =
1920                                 LE16_TO_CPU(r_iter->pdata.lkup_tx_rx.index);
1921                         f_info->fltr_act = ICE_FWD_TO_VSI;
1922                         /* Create an entry to track this MAC address */
1923                         fm_entry = (struct ice_fltr_mgmt_list_entry *)
1924                                 ice_malloc(hw, sizeof(*fm_entry));
1925                         if (!fm_entry) {
1926                                 status = ICE_ERR_NO_MEMORY;
1927                                 goto ice_add_mac_exit;
1928                         }
1929                         fm_entry->fltr_info = *f_info;
1930                         fm_entry->vsi_count = 1;
1931                         /* The book keeping entries will get removed when
1932                          * base driver calls remove filter AQ command
1933                          */
1934
1935                         LIST_ADD(&fm_entry->list_entry, rule_head);
1936                         r_iter = (struct ice_aqc_sw_rules_elem *)
1937                                 ((u8 *)r_iter + s_rule_size);
1938                 }
1939         }
1940
1941 ice_add_mac_exit:
1942         ice_release_lock(rule_lock);
1943         if (s_rule)
1944                 ice_free(hw, s_rule);
1945         return status;
1946 }
1947
1948 /**
1949  * ice_add_vlan_internal - Add one VLAN based filter rule
1950  * @hw: pointer to the hardware structure
1951  * @f_entry: filter entry containing one VLAN information
1952  */
1953 static enum ice_status
1954 ice_add_vlan_internal(struct ice_hw *hw, struct ice_fltr_list_entry *f_entry)
1955 {
1956         struct ice_switch_info *sw = hw->switch_info;
1957         struct ice_fltr_mgmt_list_entry *v_list_itr;
1958         struct ice_fltr_info *new_fltr, *cur_fltr;
1959         enum ice_sw_lkup_type lkup_type;
1960         u16 vsi_list_id = 0, vsi_handle;
1961         struct ice_lock *rule_lock; /* Lock to protect filter rule list */
1962         enum ice_status status = ICE_SUCCESS;
1963
1964         if (!ice_is_vsi_valid(hw, f_entry->fltr_info.vsi_handle))
1965                 return ICE_ERR_PARAM;
1966
1967         f_entry->fltr_info.fwd_id.hw_vsi_id =
1968                 ice_get_hw_vsi_num(hw, f_entry->fltr_info.vsi_handle);
1969         new_fltr = &f_entry->fltr_info;
1970
1971         /* VLAN ID should only be 12 bits */
1972         if (new_fltr->l_data.vlan.vlan_id > ICE_MAX_VLAN_ID)
1973                 return ICE_ERR_PARAM;
1974
1975         if (new_fltr->src_id != ICE_SRC_ID_VSI)
1976                 return ICE_ERR_PARAM;
1977
1978         new_fltr->src = new_fltr->fwd_id.hw_vsi_id;
1979         lkup_type = new_fltr->lkup_type;
1980         vsi_handle = new_fltr->vsi_handle;
1981         rule_lock = &sw->recp_list[ICE_SW_LKUP_VLAN].filt_rule_lock;
1982         ice_acquire_lock(rule_lock);
1983         v_list_itr = ice_find_rule_entry(hw, ICE_SW_LKUP_VLAN, new_fltr);
1984         if (!v_list_itr) {
1985                 struct ice_vsi_list_map_info *map_info = NULL;
1986
1987                 if (new_fltr->fltr_act == ICE_FWD_TO_VSI) {
1988                         /* All VLAN pruning rules use a VSI list. Check if
1989                          * there is already a VSI list containing VSI that we
1990                          * want to add. If found, use the same vsi_list_id for
1991                          * this new VLAN rule or else create a new list.
1992                          */
1993                         map_info = ice_find_vsi_list_entry(hw, ICE_SW_LKUP_VLAN,
1994                                                            vsi_handle,
1995                                                            &vsi_list_id);
1996                         if (!map_info) {
1997                                 status = ice_create_vsi_list_rule(hw,
1998                                                                   &vsi_handle,
1999                                                                   1,
2000                                                                   &vsi_list_id,
2001                                                                   lkup_type);
2002                                 if (status)
2003                                         goto exit;
2004                         }
2005                         /* Convert the action to forwarding to a VSI list. */
2006                         new_fltr->fltr_act = ICE_FWD_TO_VSI_LIST;
2007                         new_fltr->fwd_id.vsi_list_id = vsi_list_id;
2008                 }
2009
2010                 status = ice_create_pkt_fwd_rule(hw, f_entry);
2011                 if (!status) {
2012                         v_list_itr = ice_find_rule_entry(hw, ICE_SW_LKUP_VLAN,
2013                                                          new_fltr);
2014                         if (!v_list_itr) {
2015                                 status = ICE_ERR_DOES_NOT_EXIST;
2016                                 goto exit;
2017                         }
2018                         /* reuse VSI list for new rule and increment ref_cnt */
2019                         if (map_info) {
2020                                 v_list_itr->vsi_list_info = map_info;
2021                                 map_info->ref_cnt++;
2022                         } else {
2023                                 v_list_itr->vsi_list_info =
2024                                         ice_create_vsi_list_map(hw, &vsi_handle,
2025                                                                 1, vsi_list_id);
2026                         }
2027                 }
2028         } else if (v_list_itr->vsi_list_info->ref_cnt == 1) {
2029                 /* Update existing VSI list to add new VSI ID only if it used
2030                  * by one VLAN rule.
2031                  */
2032                 cur_fltr = &v_list_itr->fltr_info;
2033                 status = ice_add_update_vsi_list(hw, v_list_itr, cur_fltr,
2034                                                  new_fltr);
2035         } else {
2036                 /* If VLAN rule exists and VSI list being used by this rule is
2037                  * referenced by more than 1 VLAN rule. Then create a new VSI
2038                  * list appending previous VSI with new VSI and update existing
2039                  * VLAN rule to point to new VSI list ID
2040                  */
2041                 struct ice_fltr_info tmp_fltr;
2042                 u16 vsi_handle_arr[2];
2043                 u16 cur_handle;
2044
2045                 /* Current implementation only supports reusing VSI list with
2046                  * one VSI count. We should never hit below condition
2047                  */
2048                 if (v_list_itr->vsi_count > 1 &&
2049                     v_list_itr->vsi_list_info->ref_cnt > 1) {
2050                         ice_debug(hw, ICE_DBG_SW,
2051                                   "Invalid configuration: Optimization to reuse VSI list with more than one VSI is not being done yet\n");
2052                         status = ICE_ERR_CFG;
2053                         goto exit;
2054                 }
2055
2056                 cur_handle =
2057                         ice_find_first_bit(v_list_itr->vsi_list_info->vsi_map,
2058                                            ICE_MAX_VSI);
2059
2060                 /* A rule already exists with the new VSI being added */
2061                 if (cur_handle == vsi_handle) {
2062                         status = ICE_ERR_ALREADY_EXISTS;
2063                         goto exit;
2064                 }
2065
2066                 vsi_handle_arr[0] = cur_handle;
2067                 vsi_handle_arr[1] = vsi_handle;
2068                 status = ice_create_vsi_list_rule(hw, &vsi_handle_arr[0], 2,
2069                                                   &vsi_list_id, lkup_type);
2070                 if (status)
2071                         goto exit;
2072
2073                 tmp_fltr = v_list_itr->fltr_info;
2074                 tmp_fltr.fltr_rule_id = v_list_itr->fltr_info.fltr_rule_id;
2075                 tmp_fltr.fwd_id.vsi_list_id = vsi_list_id;
2076                 tmp_fltr.fltr_act = ICE_FWD_TO_VSI_LIST;
2077                 /* Update the previous switch rule to a new VSI list which
2078                  * includes current VSI that is requested
2079                  */
2080                 status = ice_update_pkt_fwd_rule(hw, &tmp_fltr);
2081                 if (status)
2082                         goto exit;
2083
2084                 /* before overriding VSI list map info. decrement ref_cnt of
2085                  * previous VSI list
2086                  */
2087                 v_list_itr->vsi_list_info->ref_cnt--;
2088
2089                 /* now update to newly created list */
2090                 v_list_itr->fltr_info.fwd_id.vsi_list_id = vsi_list_id;
2091                 v_list_itr->vsi_list_info =
2092                         ice_create_vsi_list_map(hw, &vsi_handle_arr[0], 2,
2093                                                 vsi_list_id);
2094                 v_list_itr->vsi_count++;
2095         }
2096
2097 exit:
2098         ice_release_lock(rule_lock);
2099         return status;
2100 }
2101
2102 /**
2103  * ice_add_vlan - Add VLAN based filter rule
2104  * @hw: pointer to the hardware structure
2105  * @v_list: list of VLAN entries and forwarding information
2106  */
2107 enum ice_status
2108 ice_add_vlan(struct ice_hw *hw, struct LIST_HEAD_TYPE *v_list)
2109 {
2110         struct ice_fltr_list_entry *v_list_itr;
2111
2112         if (!v_list || !hw)
2113                 return ICE_ERR_PARAM;
2114
2115         LIST_FOR_EACH_ENTRY(v_list_itr, v_list, ice_fltr_list_entry,
2116                             list_entry) {
2117                 if (v_list_itr->fltr_info.lkup_type != ICE_SW_LKUP_VLAN)
2118                         return ICE_ERR_PARAM;
2119                 v_list_itr->fltr_info.flag = ICE_FLTR_TX;
2120                 v_list_itr->status = ice_add_vlan_internal(hw, v_list_itr);
2121                 if (v_list_itr->status)
2122                         return v_list_itr->status;
2123         }
2124         return ICE_SUCCESS;
2125 }
2126
2127 #ifndef NO_MACVLAN_SUPPORT
2128 /**
2129  * ice_add_mac_vlan - Add MAC and VLAN pair based filter rule
2130  * @hw: pointer to the hardware structure
2131  * @mv_list: list of MAC and VLAN filters
2132  *
2133  * If the VSI on which the MAC-VLAN pair has to be added has Rx and Tx VLAN
2134  * pruning bits enabled, then it is the responsibility of the caller to make
2135  * sure to add a VLAN only filter on the same VSI. Packets belonging to that
2136  * VLAN won't be received on that VSI otherwise.
2137  */
2138 enum ice_status
2139 ice_add_mac_vlan(struct ice_hw *hw, struct LIST_HEAD_TYPE *mv_list)
2140 {
2141         struct ice_fltr_list_entry *mv_list_itr;
2142
2143         if (!mv_list || !hw)
2144                 return ICE_ERR_PARAM;
2145
2146         LIST_FOR_EACH_ENTRY(mv_list_itr, mv_list, ice_fltr_list_entry,
2147                             list_entry) {
2148                 enum ice_sw_lkup_type l_type =
2149                         mv_list_itr->fltr_info.lkup_type;
2150
2151                 if (l_type != ICE_SW_LKUP_MAC_VLAN)
2152                         return ICE_ERR_PARAM;
2153                 mv_list_itr->fltr_info.flag = ICE_FLTR_TX;
2154                 mv_list_itr->status =
2155                         ice_add_rule_internal(hw, ICE_SW_LKUP_MAC_VLAN,
2156                                               mv_list_itr);
2157                 if (mv_list_itr->status)
2158                         return mv_list_itr->status;
2159         }
2160         return ICE_SUCCESS;
2161 }
2162 #endif
2163
2164
2165
2166 /**
2167  * ice_rem_sw_rule_info
2168  * @hw: pointer to the hardware structure
2169  * @rule_head: pointer to the switch list structure that we want to delete
2170  */
2171 static void
2172 ice_rem_sw_rule_info(struct ice_hw *hw, struct LIST_HEAD_TYPE *rule_head)
2173 {
2174         if (!LIST_EMPTY(rule_head)) {
2175                 struct ice_fltr_mgmt_list_entry *entry;
2176                 struct ice_fltr_mgmt_list_entry *tmp;
2177
2178                 LIST_FOR_EACH_ENTRY_SAFE(entry, tmp, rule_head,
2179                                          ice_fltr_mgmt_list_entry, list_entry) {
2180                         LIST_DEL(&entry->list_entry);
2181                         ice_free(hw, entry);
2182                 }
2183         }
2184 }
2185
2186
2187
2188 /**
2189  * ice_cfg_dflt_vsi - change state of VSI to set/clear default
2190  * @pi: pointer to the port_info structure
2191  * @vsi_handle: VSI handle to set as default
2192  * @set: true to add the above mentioned switch rule, false to remove it
2193  * @direction: ICE_FLTR_RX or ICE_FLTR_TX
2194  *
2195  * add filter rule to set/unset given VSI as default VSI for the switch
2196  * (represented by swid)
2197  */
2198 enum ice_status
2199 ice_cfg_dflt_vsi(struct ice_port_info *pi, u16 vsi_handle, bool set,
2200                  u8 direction)
2201 {
2202         struct ice_aqc_sw_rules_elem *s_rule;
2203         struct ice_fltr_info f_info;
2204         struct ice_hw *hw = pi->hw;
2205         enum ice_adminq_opc opcode;
2206         enum ice_status status;
2207         u16 s_rule_size;
2208         u16 hw_vsi_id;
2209
2210         if (!ice_is_vsi_valid(hw, vsi_handle))
2211                 return ICE_ERR_PARAM;
2212         hw_vsi_id = ice_get_hw_vsi_num(hw, vsi_handle);
2213
2214         s_rule_size = set ? ICE_SW_RULE_RX_TX_ETH_HDR_SIZE :
2215                             ICE_SW_RULE_RX_TX_NO_HDR_SIZE;
2216         s_rule = (struct ice_aqc_sw_rules_elem *)ice_malloc(hw, s_rule_size);
2217         if (!s_rule)
2218                 return ICE_ERR_NO_MEMORY;
2219
2220         ice_memset(&f_info, 0, sizeof(f_info), ICE_NONDMA_MEM);
2221
2222         f_info.lkup_type = ICE_SW_LKUP_DFLT;
2223         f_info.flag = direction;
2224         f_info.fltr_act = ICE_FWD_TO_VSI;
2225         f_info.fwd_id.hw_vsi_id = hw_vsi_id;
2226
2227         if (f_info.flag & ICE_FLTR_RX) {
2228                 f_info.src = pi->lport;
2229                 f_info.src_id = ICE_SRC_ID_LPORT;
2230                 if (!set)
2231                         f_info.fltr_rule_id =
2232                                 pi->dflt_rx_vsi_rule_id;
2233         } else if (f_info.flag & ICE_FLTR_TX) {
2234                 f_info.src_id = ICE_SRC_ID_VSI;
2235                 f_info.src = hw_vsi_id;
2236                 if (!set)
2237                         f_info.fltr_rule_id =
2238                                 pi->dflt_tx_vsi_rule_id;
2239         }
2240
2241         if (set)
2242                 opcode = ice_aqc_opc_add_sw_rules;
2243         else
2244                 opcode = ice_aqc_opc_remove_sw_rules;
2245
2246         ice_fill_sw_rule(hw, &f_info, s_rule, opcode);
2247
2248         status = ice_aq_sw_rules(hw, s_rule, s_rule_size, 1, opcode, NULL);
2249         if (status || !(f_info.flag & ICE_FLTR_TX_RX))
2250                 goto out;
2251         if (set) {
2252                 u16 index = LE16_TO_CPU(s_rule->pdata.lkup_tx_rx.index);
2253
2254                 if (f_info.flag & ICE_FLTR_TX) {
2255                         pi->dflt_tx_vsi_num = hw_vsi_id;
2256                         pi->dflt_tx_vsi_rule_id = index;
2257                 } else if (f_info.flag & ICE_FLTR_RX) {
2258                         pi->dflt_rx_vsi_num = hw_vsi_id;
2259                         pi->dflt_rx_vsi_rule_id = index;
2260                 }
2261         } else {
2262                 if (f_info.flag & ICE_FLTR_TX) {
2263                         pi->dflt_tx_vsi_num = ICE_DFLT_VSI_INVAL;
2264                         pi->dflt_tx_vsi_rule_id = ICE_INVAL_ACT;
2265                 } else if (f_info.flag & ICE_FLTR_RX) {
2266                         pi->dflt_rx_vsi_num = ICE_DFLT_VSI_INVAL;
2267                         pi->dflt_rx_vsi_rule_id = ICE_INVAL_ACT;
2268                 }
2269         }
2270
2271 out:
2272         ice_free(hw, s_rule);
2273         return status;
2274 }
2275
2276 /**
2277  * ice_remove_mac - remove a MAC address based filter rule
2278  * @hw: pointer to the hardware structure
2279  * @m_list: list of MAC addresses and forwarding information
2280  *
2281  * This function removes either a MAC filter rule or a specific VSI from a
2282  * VSI list for a multicast MAC address.
2283  *
2284  * Returns ICE_ERR_DOES_NOT_EXIST if a given entry was not added by
2285  * ice_add_mac. Caller should be aware that this call will only work if all
2286  * the entries passed into m_list were added previously. It will not attempt to
2287  * do a partial remove of entries that were found.
2288  */
2289 enum ice_status
2290 ice_remove_mac(struct ice_hw *hw, struct LIST_HEAD_TYPE *m_list)
2291 {
2292         struct ice_fltr_list_entry *list_itr, *tmp;
2293
2294         if (!m_list)
2295                 return ICE_ERR_PARAM;
2296
2297         LIST_FOR_EACH_ENTRY_SAFE(list_itr, tmp, m_list, ice_fltr_list_entry,
2298                                  list_entry) {
2299                 enum ice_sw_lkup_type l_type = list_itr->fltr_info.lkup_type;
2300
2301                 if (l_type != ICE_SW_LKUP_MAC)
2302                         return ICE_ERR_PARAM;
2303                 list_itr->status = ice_remove_rule_internal(hw,
2304                                                             ICE_SW_LKUP_MAC,
2305                                                             list_itr);
2306                 if (list_itr->status)
2307                         return list_itr->status;
2308         }
2309         return ICE_SUCCESS;
2310 }
2311
2312 /**
2313  * ice_remove_vlan - Remove VLAN based filter rule
2314  * @hw: pointer to the hardware structure
2315  * @v_list: list of VLAN entries and forwarding information
2316  */
2317 enum ice_status
2318 ice_remove_vlan(struct ice_hw *hw, struct LIST_HEAD_TYPE *v_list)
2319 {
2320         struct ice_fltr_list_entry *v_list_itr, *tmp;
2321
2322         if (!v_list || !hw)
2323                 return ICE_ERR_PARAM;
2324
2325         LIST_FOR_EACH_ENTRY_SAFE(v_list_itr, tmp, v_list, ice_fltr_list_entry,
2326                                  list_entry) {
2327                 enum ice_sw_lkup_type l_type = v_list_itr->fltr_info.lkup_type;
2328
2329                 if (l_type != ICE_SW_LKUP_VLAN)
2330                         return ICE_ERR_PARAM;
2331                 v_list_itr->status = ice_remove_rule_internal(hw,
2332                                                               ICE_SW_LKUP_VLAN,
2333                                                               v_list_itr);
2334                 if (v_list_itr->status)
2335                         return v_list_itr->status;
2336         }
2337         return ICE_SUCCESS;
2338 }
2339
2340 #ifndef NO_MACVLAN_SUPPORT
2341 /**
2342  * ice_remove_mac_vlan - Remove MAC VLAN based filter rule
2343  * @hw: pointer to the hardware structure
2344  * @v_list: list of MAC VLAN entries and forwarding information
2345  */
2346 enum ice_status
2347 ice_remove_mac_vlan(struct ice_hw *hw, struct LIST_HEAD_TYPE *v_list)
2348 {
2349         struct ice_fltr_list_entry *v_list_itr, *tmp;
2350
2351         if (!v_list || !hw)
2352                 return ICE_ERR_PARAM;
2353
2354         LIST_FOR_EACH_ENTRY_SAFE(v_list_itr, tmp, v_list, ice_fltr_list_entry,
2355                                  list_entry) {
2356                 enum ice_sw_lkup_type l_type = v_list_itr->fltr_info.lkup_type;
2357
2358                 if (l_type != ICE_SW_LKUP_MAC_VLAN)
2359                         return ICE_ERR_PARAM;
2360                 v_list_itr->status =
2361                         ice_remove_rule_internal(hw, ICE_SW_LKUP_MAC_VLAN,
2362                                                  v_list_itr);
2363                 if (v_list_itr->status)
2364                         return v_list_itr->status;
2365         }
2366         return ICE_SUCCESS;
2367 }
2368 #endif /* !NO_MACVLAN_SUPPORT */
2369
2370 /**
2371  * ice_vsi_uses_fltr - Determine if given VSI uses specified filter
2372  * @fm_entry: filter entry to inspect
2373  * @vsi_handle: VSI handle to compare with filter info
2374  */
2375 static bool
2376 ice_vsi_uses_fltr(struct ice_fltr_mgmt_list_entry *fm_entry, u16 vsi_handle)
2377 {
2378         return ((fm_entry->fltr_info.fltr_act == ICE_FWD_TO_VSI &&
2379                  fm_entry->fltr_info.vsi_handle == vsi_handle) ||
2380                 (fm_entry->fltr_info.fltr_act == ICE_FWD_TO_VSI_LIST &&
2381                  (ice_is_bit_set(fm_entry->vsi_list_info->vsi_map,
2382                                  vsi_handle))));
2383 }
2384
2385 /**
2386  * ice_add_entry_to_vsi_fltr_list - Add copy of fltr_list_entry to remove list
2387  * @hw: pointer to the hardware structure
2388  * @vsi_handle: VSI handle to remove filters from
2389  * @vsi_list_head: pointer to the list to add entry to
2390  * @fi: pointer to fltr_info of filter entry to copy & add
2391  *
2392  * Helper function, used when creating a list of filters to remove from
2393  * a specific VSI. The entry added to vsi_list_head is a COPY of the
2394  * original filter entry, with the exception of fltr_info.fltr_act and
2395  * fltr_info.fwd_id fields. These are set such that later logic can
2396  * extract which VSI to remove the fltr from, and pass on that information.
2397  */
2398 static enum ice_status
2399 ice_add_entry_to_vsi_fltr_list(struct ice_hw *hw, u16 vsi_handle,
2400                                struct LIST_HEAD_TYPE *vsi_list_head,
2401                                struct ice_fltr_info *fi)
2402 {
2403         struct ice_fltr_list_entry *tmp;
2404
2405         /* this memory is freed up in the caller function
2406          * once filters for this VSI are removed
2407          */
2408         tmp = (struct ice_fltr_list_entry *)ice_malloc(hw, sizeof(*tmp));
2409         if (!tmp)
2410                 return ICE_ERR_NO_MEMORY;
2411
2412         tmp->fltr_info = *fi;
2413
2414         /* Overwrite these fields to indicate which VSI to remove filter from,
2415          * so find and remove logic can extract the information from the
2416          * list entries. Note that original entries will still have proper
2417          * values.
2418          */
2419         tmp->fltr_info.fltr_act = ICE_FWD_TO_VSI;
2420         tmp->fltr_info.vsi_handle = vsi_handle;
2421         tmp->fltr_info.fwd_id.hw_vsi_id = ice_get_hw_vsi_num(hw, vsi_handle);
2422
2423         LIST_ADD(&tmp->list_entry, vsi_list_head);
2424
2425         return ICE_SUCCESS;
2426 }
2427
2428 /**
2429  * ice_add_to_vsi_fltr_list - Add VSI filters to the list
2430  * @hw: pointer to the hardware structure
2431  * @vsi_handle: VSI handle to remove filters from
2432  * @lkup_list_head: pointer to the list that has certain lookup type filters
2433  * @vsi_list_head: pointer to the list pertaining to VSI with vsi_handle
2434  *
2435  * Locates all filters in lkup_list_head that are used by the given VSI,
2436  * and adds COPIES of those entries to vsi_list_head (intended to be used
2437  * to remove the listed filters).
2438  * Note that this means all entries in vsi_list_head must be explicitly
2439  * deallocated by the caller when done with list.
2440  */
2441 static enum ice_status
2442 ice_add_to_vsi_fltr_list(struct ice_hw *hw, u16 vsi_handle,
2443                          struct LIST_HEAD_TYPE *lkup_list_head,
2444                          struct LIST_HEAD_TYPE *vsi_list_head)
2445 {
2446         struct ice_fltr_mgmt_list_entry *fm_entry;
2447         enum ice_status status = ICE_SUCCESS;
2448
2449         /* check to make sure VSI ID is valid and within boundary */
2450         if (!ice_is_vsi_valid(hw, vsi_handle))
2451                 return ICE_ERR_PARAM;
2452
2453         LIST_FOR_EACH_ENTRY(fm_entry, lkup_list_head,
2454                             ice_fltr_mgmt_list_entry, list_entry) {
2455                 struct ice_fltr_info *fi;
2456
2457                 fi = &fm_entry->fltr_info;
2458                 if (!fi || !ice_vsi_uses_fltr(fm_entry, vsi_handle))
2459                         continue;
2460
2461                 status = ice_add_entry_to_vsi_fltr_list(hw, vsi_handle,
2462                                                         vsi_list_head, fi);
2463                 if (status)
2464                         return status;
2465         }
2466         return status;
2467 }
2468
2469
2470 /**
2471  * ice_determine_promisc_mask
2472  * @fi: filter info to parse
2473  *
2474  * Helper function to determine which ICE_PROMISC_ mask corresponds
2475  * to given filter into.
2476  */
2477 static u8 ice_determine_promisc_mask(struct ice_fltr_info *fi)
2478 {
2479         u16 vid = fi->l_data.mac_vlan.vlan_id;
2480         u8 *macaddr = fi->l_data.mac.mac_addr;
2481         bool is_tx_fltr = false;
2482         u8 promisc_mask = 0;
2483
2484         if (fi->flag == ICE_FLTR_TX)
2485                 is_tx_fltr = true;
2486
2487         if (IS_BROADCAST_ETHER_ADDR(macaddr))
2488                 promisc_mask |= is_tx_fltr ?
2489                         ICE_PROMISC_BCAST_TX : ICE_PROMISC_BCAST_RX;
2490         else if (IS_MULTICAST_ETHER_ADDR(macaddr))
2491                 promisc_mask |= is_tx_fltr ?
2492                         ICE_PROMISC_MCAST_TX : ICE_PROMISC_MCAST_RX;
2493         else if (IS_UNICAST_ETHER_ADDR(macaddr))
2494                 promisc_mask |= is_tx_fltr ?
2495                         ICE_PROMISC_UCAST_TX : ICE_PROMISC_UCAST_RX;
2496         if (vid)
2497                 promisc_mask |= is_tx_fltr ?
2498                         ICE_PROMISC_VLAN_TX : ICE_PROMISC_VLAN_RX;
2499
2500         return promisc_mask;
2501 }
2502
2503
2504 /**
2505  * ice_remove_promisc - Remove promisc based filter rules
2506  * @hw: pointer to the hardware structure
2507  * @recp_id: recipe ID for which the rule needs to removed
2508  * @v_list: list of promisc entries
2509  */
2510 static enum ice_status
2511 ice_remove_promisc(struct ice_hw *hw, u8 recp_id,
2512                    struct LIST_HEAD_TYPE *v_list)
2513 {
2514         struct ice_fltr_list_entry *v_list_itr, *tmp;
2515
2516         LIST_FOR_EACH_ENTRY_SAFE(v_list_itr, tmp, v_list, ice_fltr_list_entry,
2517                                  list_entry) {
2518                 v_list_itr->status =
2519                         ice_remove_rule_internal(hw, recp_id, v_list_itr);
2520                 if (v_list_itr->status)
2521                         return v_list_itr->status;
2522         }
2523         return ICE_SUCCESS;
2524 }
2525
2526 /**
2527  * ice_clear_vsi_promisc - clear specified promiscuous mode(s) for given VSI
2528  * @hw: pointer to the hardware structure
2529  * @vsi_handle: VSI handle to clear mode
2530  * @promisc_mask: mask of promiscuous config bits to clear
2531  * @vid: VLAN ID to clear VLAN promiscuous
2532  */
2533 enum ice_status
2534 ice_clear_vsi_promisc(struct ice_hw *hw, u16 vsi_handle, u8 promisc_mask,
2535                       u16 vid)
2536 {
2537         struct ice_switch_info *sw = hw->switch_info;
2538         struct ice_fltr_list_entry *fm_entry, *tmp;
2539         struct LIST_HEAD_TYPE remove_list_head;
2540         struct ice_fltr_mgmt_list_entry *itr;
2541         struct LIST_HEAD_TYPE *rule_head;
2542         struct ice_lock *rule_lock;     /* Lock to protect filter rule list */
2543         enum ice_status status = ICE_SUCCESS;
2544         u8 recipe_id;
2545
2546         if (!ice_is_vsi_valid(hw, vsi_handle))
2547                 return ICE_ERR_PARAM;
2548
2549         if (vid)
2550                 recipe_id = ICE_SW_LKUP_PROMISC_VLAN;
2551         else
2552                 recipe_id = ICE_SW_LKUP_PROMISC;
2553
2554         rule_head = &sw->recp_list[recipe_id].filt_rules;
2555         rule_lock = &sw->recp_list[recipe_id].filt_rule_lock;
2556
2557         INIT_LIST_HEAD(&remove_list_head);
2558
2559         ice_acquire_lock(rule_lock);
2560         LIST_FOR_EACH_ENTRY(itr, rule_head,
2561                             ice_fltr_mgmt_list_entry, list_entry) {
2562                 u8 fltr_promisc_mask = 0;
2563
2564                 if (!ice_vsi_uses_fltr(itr, vsi_handle))
2565                         continue;
2566
2567                 fltr_promisc_mask |=
2568                         ice_determine_promisc_mask(&itr->fltr_info);
2569
2570                 /* Skip if filter is not completely specified by given mask */
2571                 if (fltr_promisc_mask & ~promisc_mask)
2572                         continue;
2573
2574                 status = ice_add_entry_to_vsi_fltr_list(hw, vsi_handle,
2575                                                         &remove_list_head,
2576                                                         &itr->fltr_info);
2577                 if (status) {
2578                         ice_release_lock(rule_lock);
2579                         goto free_fltr_list;
2580                 }
2581         }
2582         ice_release_lock(rule_lock);
2583
2584         status = ice_remove_promisc(hw, recipe_id, &remove_list_head);
2585
2586 free_fltr_list:
2587         LIST_FOR_EACH_ENTRY_SAFE(fm_entry, tmp, &remove_list_head,
2588                                  ice_fltr_list_entry, list_entry) {
2589                 LIST_DEL(&fm_entry->list_entry);
2590                 ice_free(hw, fm_entry);
2591         }
2592
2593         return status;
2594 }
2595
2596 /**
2597  * ice_set_vsi_promisc - set given VSI to given promiscuous mode(s)
2598  * @hw: pointer to the hardware structure
2599  * @vsi_handle: VSI handle to configure
2600  * @promisc_mask: mask of promiscuous config bits
2601  * @vid: VLAN ID to set VLAN promiscuous
2602  */
2603 enum ice_status
2604 ice_set_vsi_promisc(struct ice_hw *hw, u16 vsi_handle, u8 promisc_mask, u16 vid)
2605 {
2606         enum { UCAST_FLTR = 1, MCAST_FLTR, BCAST_FLTR };
2607         struct ice_fltr_list_entry f_list_entry;
2608         struct ice_fltr_info new_fltr;
2609         enum ice_status status = ICE_SUCCESS;
2610         bool is_tx_fltr;
2611         u16 hw_vsi_id;
2612         int pkt_type;
2613         u8 recipe_id;
2614
2615         ice_debug(hw, ICE_DBG_TRACE, "ice_set_vsi_promisc\n");
2616
2617         if (!ice_is_vsi_valid(hw, vsi_handle))
2618                 return ICE_ERR_PARAM;
2619         hw_vsi_id = ice_get_hw_vsi_num(hw, vsi_handle);
2620
2621         ice_memset(&new_fltr, 0, sizeof(new_fltr), ICE_NONDMA_MEM);
2622
2623         if (promisc_mask & (ICE_PROMISC_VLAN_RX | ICE_PROMISC_VLAN_TX)) {
2624                 new_fltr.lkup_type = ICE_SW_LKUP_PROMISC_VLAN;
2625                 new_fltr.l_data.mac_vlan.vlan_id = vid;
2626                 recipe_id = ICE_SW_LKUP_PROMISC_VLAN;
2627         } else {
2628                 new_fltr.lkup_type = ICE_SW_LKUP_PROMISC;
2629                 recipe_id = ICE_SW_LKUP_PROMISC;
2630         }
2631
2632         /* Separate filters must be set for each direction/packet type
2633          * combination, so we will loop over the mask value, store the
2634          * individual type, and clear it out in the input mask as it
2635          * is found.
2636          */
2637         while (promisc_mask) {
2638                 u8 *mac_addr;
2639
2640                 pkt_type = 0;
2641                 is_tx_fltr = false;
2642
2643                 if (promisc_mask & ICE_PROMISC_UCAST_RX) {
2644                         promisc_mask &= ~ICE_PROMISC_UCAST_RX;
2645                         pkt_type = UCAST_FLTR;
2646                 } else if (promisc_mask & ICE_PROMISC_UCAST_TX) {
2647                         promisc_mask &= ~ICE_PROMISC_UCAST_TX;
2648                         pkt_type = UCAST_FLTR;
2649                         is_tx_fltr = true;
2650                 } else if (promisc_mask & ICE_PROMISC_MCAST_RX) {
2651                         promisc_mask &= ~ICE_PROMISC_MCAST_RX;
2652                         pkt_type = MCAST_FLTR;
2653                 } else if (promisc_mask & ICE_PROMISC_MCAST_TX) {
2654                         promisc_mask &= ~ICE_PROMISC_MCAST_TX;
2655                         pkt_type = MCAST_FLTR;
2656                         is_tx_fltr = true;
2657                 } else if (promisc_mask & ICE_PROMISC_BCAST_RX) {
2658                         promisc_mask &= ~ICE_PROMISC_BCAST_RX;
2659                         pkt_type = BCAST_FLTR;
2660                 } else if (promisc_mask & ICE_PROMISC_BCAST_TX) {
2661                         promisc_mask &= ~ICE_PROMISC_BCAST_TX;
2662                         pkt_type = BCAST_FLTR;
2663                         is_tx_fltr = true;
2664                 }
2665
2666                 /* Check for VLAN promiscuous flag */
2667                 if (promisc_mask & ICE_PROMISC_VLAN_RX) {
2668                         promisc_mask &= ~ICE_PROMISC_VLAN_RX;
2669                 } else if (promisc_mask & ICE_PROMISC_VLAN_TX) {
2670                         promisc_mask &= ~ICE_PROMISC_VLAN_TX;
2671                         is_tx_fltr = true;
2672                 }
2673
2674                 /* Set filter DA based on packet type */
2675                 mac_addr = new_fltr.l_data.mac.mac_addr;
2676                 if (pkt_type == BCAST_FLTR) {
2677                         ice_memset(mac_addr, 0xff, ETH_ALEN, ICE_NONDMA_MEM);
2678                 } else if (pkt_type == MCAST_FLTR ||
2679                            pkt_type == UCAST_FLTR) {
2680                         /* Use the dummy ether header DA */
2681                         ice_memcpy(mac_addr, dummy_eth_header, ETH_ALEN,
2682                                    ICE_NONDMA_TO_NONDMA);
2683                         if (pkt_type == MCAST_FLTR)
2684                                 mac_addr[0] |= 0x1;     /* Set multicast bit */
2685                 }
2686
2687                 /* Need to reset this to zero for all iterations */
2688                 new_fltr.flag = 0;
2689                 if (is_tx_fltr) {
2690                         new_fltr.flag |= ICE_FLTR_TX;
2691                         new_fltr.src = hw_vsi_id;
2692                 } else {
2693                         new_fltr.flag |= ICE_FLTR_RX;
2694                         new_fltr.src = hw->port_info->lport;
2695                 }
2696
2697                 new_fltr.fltr_act = ICE_FWD_TO_VSI;
2698                 new_fltr.vsi_handle = vsi_handle;
2699                 new_fltr.fwd_id.hw_vsi_id = hw_vsi_id;
2700                 f_list_entry.fltr_info = new_fltr;
2701
2702                 status = ice_add_rule_internal(hw, recipe_id, &f_list_entry);
2703                 if (status != ICE_SUCCESS)
2704                         goto set_promisc_exit;
2705         }
2706
2707 set_promisc_exit:
2708         return status;
2709 }
2710
2711 /**
2712  * ice_set_vlan_vsi_promisc
2713  * @hw: pointer to the hardware structure
2714  * @vsi_handle: VSI handle to configure
2715  * @promisc_mask: mask of promiscuous config bits
2716  * @rm_vlan_promisc: Clear VLANs VSI promisc mode
2717  *
2718  * Configure VSI with all associated VLANs to given promiscuous mode(s)
2719  */
2720 enum ice_status
2721 ice_set_vlan_vsi_promisc(struct ice_hw *hw, u16 vsi_handle, u8 promisc_mask,
2722                          bool rm_vlan_promisc)
2723 {
2724         struct ice_switch_info *sw = hw->switch_info;
2725         struct ice_fltr_list_entry *list_itr, *tmp;
2726         struct LIST_HEAD_TYPE vsi_list_head;
2727         struct LIST_HEAD_TYPE *vlan_head;
2728         struct ice_lock *vlan_lock; /* Lock to protect filter rule list */
2729         enum ice_status status;
2730         u16 vlan_id;
2731
2732         INIT_LIST_HEAD(&vsi_list_head);
2733         vlan_lock = &sw->recp_list[ICE_SW_LKUP_VLAN].filt_rule_lock;
2734         vlan_head = &sw->recp_list[ICE_SW_LKUP_VLAN].filt_rules;
2735         ice_acquire_lock(vlan_lock);
2736         status = ice_add_to_vsi_fltr_list(hw, vsi_handle, vlan_head,
2737                                           &vsi_list_head);
2738         ice_release_lock(vlan_lock);
2739         if (status)
2740                 goto free_fltr_list;
2741
2742         LIST_FOR_EACH_ENTRY(list_itr, &vsi_list_head, ice_fltr_list_entry,
2743                             list_entry) {
2744                 vlan_id = list_itr->fltr_info.l_data.vlan.vlan_id;
2745                 if (rm_vlan_promisc)
2746                         status = ice_clear_vsi_promisc(hw, vsi_handle,
2747                                                        promisc_mask, vlan_id);
2748                 else
2749                         status = ice_set_vsi_promisc(hw, vsi_handle,
2750                                                      promisc_mask, vlan_id);
2751                 if (status)
2752                         break;
2753         }
2754
2755 free_fltr_list:
2756         LIST_FOR_EACH_ENTRY_SAFE(list_itr, tmp, &vsi_list_head,
2757                                  ice_fltr_list_entry, list_entry) {
2758                 LIST_DEL(&list_itr->list_entry);
2759                 ice_free(hw, list_itr);
2760         }
2761         return status;
2762 }
2763
2764 /**
2765  * ice_remove_vsi_lkup_fltr - Remove lookup type filters for a VSI
2766  * @hw: pointer to the hardware structure
2767  * @vsi_handle: VSI handle to remove filters from
2768  * @lkup: switch rule filter lookup type
2769  */
2770 static void
2771 ice_remove_vsi_lkup_fltr(struct ice_hw *hw, u16 vsi_handle,
2772                          enum ice_sw_lkup_type lkup)
2773 {
2774         struct ice_switch_info *sw = hw->switch_info;
2775         struct ice_fltr_list_entry *fm_entry;
2776         struct LIST_HEAD_TYPE remove_list_head;
2777         struct LIST_HEAD_TYPE *rule_head;
2778         struct ice_fltr_list_entry *tmp;
2779         struct ice_lock *rule_lock;     /* Lock to protect filter rule list */
2780         enum ice_status status;
2781
2782         INIT_LIST_HEAD(&remove_list_head);
2783         rule_lock = &sw->recp_list[lkup].filt_rule_lock;
2784         rule_head = &sw->recp_list[lkup].filt_rules;
2785         ice_acquire_lock(rule_lock);
2786         status = ice_add_to_vsi_fltr_list(hw, vsi_handle, rule_head,
2787                                           &remove_list_head);
2788         ice_release_lock(rule_lock);
2789         if (status)
2790                 return;
2791
2792         switch (lkup) {
2793         case ICE_SW_LKUP_MAC:
2794                 ice_remove_mac(hw, &remove_list_head);
2795                 break;
2796         case ICE_SW_LKUP_VLAN:
2797                 ice_remove_vlan(hw, &remove_list_head);
2798                 break;
2799         case ICE_SW_LKUP_PROMISC:
2800         case ICE_SW_LKUP_PROMISC_VLAN:
2801                 ice_remove_promisc(hw, lkup, &remove_list_head);
2802                 break;
2803         case ICE_SW_LKUP_MAC_VLAN:
2804 #ifndef NO_MACVLAN_SUPPORT
2805                 ice_remove_mac_vlan(hw, &remove_list_head);
2806 #else
2807                 ice_debug(hw, ICE_DBG_SW, "MAC VLAN look up is not supported yet\n");
2808 #endif /* !NO_MACVLAN_SUPPORT */
2809                 break;
2810         case ICE_SW_LKUP_ETHERTYPE:
2811         case ICE_SW_LKUP_ETHERTYPE_MAC:
2812         case ICE_SW_LKUP_DFLT:
2813                 ice_debug(hw, ICE_DBG_SW,
2814                           "Remove filters for this lookup type hasn't been implemented yet\n");
2815                 break;
2816         case ICE_SW_LKUP_LAST:
2817                 ice_debug(hw, ICE_DBG_SW, "Unsupported lookup type\n");
2818                 break;
2819         }
2820
2821         LIST_FOR_EACH_ENTRY_SAFE(fm_entry, tmp, &remove_list_head,
2822                                  ice_fltr_list_entry, list_entry) {
2823                 LIST_DEL(&fm_entry->list_entry);
2824                 ice_free(hw, fm_entry);
2825         }
2826 }
2827
2828 /**
2829  * ice_remove_vsi_fltr - Remove all filters for a VSI
2830  * @hw: pointer to the hardware structure
2831  * @vsi_handle: VSI handle to remove filters from
2832  */
2833 void ice_remove_vsi_fltr(struct ice_hw *hw, u16 vsi_handle)
2834 {
2835         ice_debug(hw, ICE_DBG_TRACE, "ice_remove_vsi_fltr\n");
2836
2837         ice_remove_vsi_lkup_fltr(hw, vsi_handle, ICE_SW_LKUP_MAC);
2838         ice_remove_vsi_lkup_fltr(hw, vsi_handle, ICE_SW_LKUP_MAC_VLAN);
2839         ice_remove_vsi_lkup_fltr(hw, vsi_handle, ICE_SW_LKUP_PROMISC);
2840         ice_remove_vsi_lkup_fltr(hw, vsi_handle, ICE_SW_LKUP_VLAN);
2841         ice_remove_vsi_lkup_fltr(hw, vsi_handle, ICE_SW_LKUP_DFLT);
2842         ice_remove_vsi_lkup_fltr(hw, vsi_handle, ICE_SW_LKUP_ETHERTYPE);
2843         ice_remove_vsi_lkup_fltr(hw, vsi_handle, ICE_SW_LKUP_ETHERTYPE_MAC);
2844         ice_remove_vsi_lkup_fltr(hw, vsi_handle, ICE_SW_LKUP_PROMISC_VLAN);
2845 }
2846
2847
2848
2849
2850
2851 /**
2852  * ice_replay_vsi_fltr - Replay filters for requested VSI
2853  * @hw: pointer to the hardware structure
2854  * @vsi_handle: driver VSI handle
2855  * @recp_id: Recipe ID for which rules need to be replayed
2856  * @list_head: list for which filters need to be replayed
2857  *
2858  * Replays the filter of recipe recp_id for a VSI represented via vsi_handle.
2859  * It is required to pass valid VSI handle.
2860  */
2861 static enum ice_status
2862 ice_replay_vsi_fltr(struct ice_hw *hw, u16 vsi_handle, u8 recp_id,
2863                     struct LIST_HEAD_TYPE *list_head)
2864 {
2865         struct ice_fltr_mgmt_list_entry *itr;
2866         enum ice_status status = ICE_SUCCESS;
2867         u16 hw_vsi_id;
2868
2869         if (LIST_EMPTY(list_head))
2870                 return status;
2871         hw_vsi_id = ice_get_hw_vsi_num(hw, vsi_handle);
2872
2873         LIST_FOR_EACH_ENTRY(itr, list_head, ice_fltr_mgmt_list_entry,
2874                             list_entry) {
2875                 struct ice_fltr_list_entry f_entry;
2876
2877                 f_entry.fltr_info = itr->fltr_info;
2878                 if (itr->vsi_count < 2 && recp_id != ICE_SW_LKUP_VLAN &&
2879                     itr->fltr_info.vsi_handle == vsi_handle) {
2880                         /* update the src in case it is VSI num */
2881                         if (f_entry.fltr_info.src_id == ICE_SRC_ID_VSI)
2882                                 f_entry.fltr_info.src = hw_vsi_id;
2883                         status = ice_add_rule_internal(hw, recp_id, &f_entry);
2884                         if (status != ICE_SUCCESS)
2885                                 goto end;
2886                         continue;
2887                 }
2888                 if (!itr->vsi_list_info ||
2889                     !ice_is_bit_set(itr->vsi_list_info->vsi_map, vsi_handle))
2890                         continue;
2891                 /* Clearing it so that the logic can add it back */
2892                 ice_clear_bit(vsi_handle, itr->vsi_list_info->vsi_map);
2893                 f_entry.fltr_info.vsi_handle = vsi_handle;
2894                 f_entry.fltr_info.fltr_act = ICE_FWD_TO_VSI;
2895                 /* update the src in case it is VSI num */
2896                 if (f_entry.fltr_info.src_id == ICE_SRC_ID_VSI)
2897                         f_entry.fltr_info.src = hw_vsi_id;
2898                 if (recp_id == ICE_SW_LKUP_VLAN)
2899                         status = ice_add_vlan_internal(hw, &f_entry);
2900                 else
2901                         status = ice_add_rule_internal(hw, recp_id, &f_entry);
2902                 if (status != ICE_SUCCESS)
2903                         goto end;
2904         }
2905 end:
2906         return status;
2907 }
2908
2909
2910 /**
2911  * ice_replay_vsi_all_fltr - replay all filters stored in bookkeeping lists
2912  * @hw: pointer to the hardware structure
2913  * @vsi_handle: driver VSI handle
2914  *
2915  * Replays filters for requested VSI via vsi_handle.
2916  */
2917 enum ice_status ice_replay_vsi_all_fltr(struct ice_hw *hw, u16 vsi_handle)
2918 {
2919         struct ice_switch_info *sw = hw->switch_info;
2920         enum ice_status status = ICE_SUCCESS;
2921         u8 i;
2922
2923         for (i = 0; i < ICE_MAX_NUM_RECIPES; i++) {
2924                 /* Update the default recipe lines and ones that were created */
2925                 if (i < ICE_MAX_NUM_RECIPES || sw->recp_list[i].recp_created) {
2926                         struct LIST_HEAD_TYPE *head;
2927
2928                         head = &sw->recp_list[i].filt_replay_rules;
2929                         if (!sw->recp_list[i].adv_rule)
2930                                 status = ice_replay_vsi_fltr(hw, vsi_handle, i,
2931                                                              head);
2932                         if (status != ICE_SUCCESS)
2933                                 return status;
2934                 }
2935         }
2936         return status;
2937 }
2938
2939 /**
2940  * ice_rm_all_sw_replay_rule_info - deletes filter replay rules
2941  * @hw: pointer to the HW struct
2942  *
2943  * Deletes the filter replay rules.
2944  */
2945 void ice_rm_all_sw_replay_rule_info(struct ice_hw *hw)
2946 {
2947         struct ice_switch_info *sw = hw->switch_info;
2948         u8 i;
2949
2950         if (!sw)
2951                 return;
2952
2953         for (i = 0; i < ICE_MAX_NUM_RECIPES; i++) {
2954                 if (!LIST_EMPTY(&sw->recp_list[i].filt_replay_rules)) {
2955                         struct LIST_HEAD_TYPE *l_head;
2956
2957                         l_head = &sw->recp_list[i].filt_replay_rules;
2958                         if (!sw->recp_list[i].adv_rule)
2959                                 ice_rem_sw_rule_info(hw, l_head);
2960                 }
2961         }
2962 }