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