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