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