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