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