1 // SPDX-License-Identifier: GPL-2.0
2 /* Copyright (c) 2018, Intel Corporation. */
4 #include "ice_switch.h"
6 #define ICE_ETH_DA_OFFSET 0
7 #define ICE_ETH_ETHTYPE_OFFSET 12
8 #define ICE_ETH_VLAN_TCI_OFFSET 14
9 #define ICE_MAX_VLAN_ID 0xFFF
11 /* Dummy ethernet header needed in the ice_aqc_sw_rules_elem
12 * struct to configure any switch filter rules.
13 * {DA (6 bytes), SA(6 bytes),
14 * Ether type (2 bytes for header without VLAN tag) OR
15 * VLAN tag (4 bytes for header with VLAN tag) }
17 * Word on Hardcoded values
18 * byte 0 = 0x2: to identify it as locally administered DA MAC
19 * byte 6 = 0x2: to identify it as locally administered SA MAC
20 * byte 12 = 0x81 & byte 13 = 0x00:
21 * In case of VLAN filter first two bytes defines ether type (0x8100)
22 * and remaining two bytes are placeholder for programming a given VLAN id
23 * In case of Ether type filter it is treated as header without VLAN tag
24 * and byte 12 and 13 is used to program a given Ether type instead
26 #define DUMMY_ETH_HDR_LEN 16
27 static const u8 dummy_eth_header[DUMMY_ETH_HDR_LEN] = { 0x2, 0, 0, 0, 0, 0,
31 #define ICE_SW_RULE_RX_TX_ETH_HDR_SIZE \
32 (sizeof(struct ice_aqc_sw_rules_elem) - \
33 sizeof(((struct ice_aqc_sw_rules_elem *)0)->pdata) + \
34 sizeof(struct ice_sw_rule_lkup_rx_tx) + DUMMY_ETH_HDR_LEN - 1)
35 #define ICE_SW_RULE_RX_TX_NO_HDR_SIZE \
36 (sizeof(struct ice_aqc_sw_rules_elem) - \
37 sizeof(((struct ice_aqc_sw_rules_elem *)0)->pdata) + \
38 sizeof(struct ice_sw_rule_lkup_rx_tx) - 1)
39 #define ICE_SW_RULE_LG_ACT_SIZE(n) \
40 (sizeof(struct ice_aqc_sw_rules_elem) - \
41 sizeof(((struct ice_aqc_sw_rules_elem *)0)->pdata) + \
42 sizeof(struct ice_sw_rule_lg_act) - \
43 sizeof(((struct ice_sw_rule_lg_act *)0)->act) + \
44 ((n) * sizeof(((struct ice_sw_rule_lg_act *)0)->act)))
45 #define ICE_SW_RULE_VSI_LIST_SIZE(n) \
46 (sizeof(struct ice_aqc_sw_rules_elem) - \
47 sizeof(((struct ice_aqc_sw_rules_elem *)0)->pdata) + \
48 sizeof(struct ice_sw_rule_vsi_list) - \
49 sizeof(((struct ice_sw_rule_vsi_list *)0)->vsi) + \
50 ((n) * sizeof(((struct ice_sw_rule_vsi_list *)0)->vsi)))
53 * ice_aq_alloc_free_res - command to allocate/free resources
54 * @hw: pointer to the hw struct
55 * @num_entries: number of resource entries in buffer
56 * @buf: Indirect buffer to hold data parameters and response
57 * @buf_size: size of buffer for indirect commands
58 * @opc: pass in the command opcode
59 * @cd: pointer to command details structure or NULL
61 * Helper function to allocate/free resources using the admin queue commands
63 static enum ice_status
64 ice_aq_alloc_free_res(struct ice_hw *hw, u16 num_entries,
65 struct ice_aqc_alloc_free_res_elem *buf, u16 buf_size,
66 enum ice_adminq_opc opc, struct ice_sq_cd *cd)
68 struct ice_aqc_alloc_free_res_cmd *cmd;
69 struct ice_aq_desc desc;
71 cmd = &desc.params.sw_res_ctrl;
76 if (buf_size < (num_entries * sizeof(buf->elem[0])))
79 ice_fill_dflt_direct_cmd_desc(&desc, opc);
81 desc.flags |= cpu_to_le16(ICE_AQ_FLAG_RD);
83 cmd->num_entries = cpu_to_le16(num_entries);
85 return ice_aq_send_cmd(hw, &desc, buf, buf_size, cd);
89 * ice_init_def_sw_recp - initialize the recipe book keeping tables
90 * @hw: pointer to the hw struct
92 * Allocate memory for the entire recipe table and initialize the structures/
93 * entries corresponding to basic recipes.
96 ice_init_def_sw_recp(struct ice_hw *hw)
98 struct ice_sw_recipe *recps;
101 recps = devm_kcalloc(ice_hw_to_dev(hw), ICE_MAX_NUM_RECIPES,
102 sizeof(struct ice_sw_recipe), GFP_KERNEL);
104 return ICE_ERR_NO_MEMORY;
106 for (i = 0; i < ICE_SW_LKUP_LAST; i++) {
107 recps[i].root_rid = i;
108 INIT_LIST_HEAD(&recps[i].filt_rules);
109 INIT_LIST_HEAD(&recps[i].filt_replay_rules);
110 mutex_init(&recps[i].filt_rule_lock);
113 hw->switch_info->recp_list = recps;
119 * ice_aq_get_sw_cfg - get switch configuration
120 * @hw: pointer to the hardware structure
121 * @buf: pointer to the result buffer
122 * @buf_size: length of the buffer available for response
123 * @req_desc: pointer to requested descriptor
124 * @num_elems: pointer to number of elements
125 * @cd: pointer to command details structure or NULL
127 * Get switch configuration (0x0200) to be placed in 'buff'.
128 * This admin command returns information such as initial VSI/port number
129 * and switch ID it belongs to.
131 * NOTE: *req_desc is both an input/output parameter.
132 * The caller of this function first calls this function with *request_desc set
133 * to 0. If the response from f/w has *req_desc set to 0, all the switch
134 * configuration information has been returned; if non-zero (meaning not all
135 * the information was returned), the caller should call this function again
136 * with *req_desc set to the previous value returned by f/w to get the
137 * next block of switch configuration information.
139 * *num_elems is output only parameter. This reflects the number of elements
140 * in response buffer. The caller of this function to use *num_elems while
141 * parsing the response buffer.
143 static enum ice_status
144 ice_aq_get_sw_cfg(struct ice_hw *hw, struct ice_aqc_get_sw_cfg_resp *buf,
145 u16 buf_size, u16 *req_desc, u16 *num_elems,
146 struct ice_sq_cd *cd)
148 struct ice_aqc_get_sw_cfg *cmd;
149 enum ice_status status;
150 struct ice_aq_desc desc;
152 ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_get_sw_cfg);
153 cmd = &desc.params.get_sw_conf;
154 cmd->element = cpu_to_le16(*req_desc);
156 status = ice_aq_send_cmd(hw, &desc, buf, buf_size, cd);
158 *req_desc = le16_to_cpu(cmd->element);
159 *num_elems = le16_to_cpu(cmd->num_elems);
167 * @hw: pointer to the hw struct
168 * @vsi_ctx: pointer to a VSI context struct
169 * @cd: pointer to command details structure or NULL
171 * Add a VSI context to the hardware (0x0210)
173 static enum ice_status
174 ice_aq_add_vsi(struct ice_hw *hw, struct ice_vsi_ctx *vsi_ctx,
175 struct ice_sq_cd *cd)
177 struct ice_aqc_add_update_free_vsi_resp *res;
178 struct ice_aqc_add_get_update_free_vsi *cmd;
179 struct ice_aq_desc desc;
180 enum ice_status status;
182 cmd = &desc.params.vsi_cmd;
183 res = &desc.params.add_update_free_vsi_res;
185 ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_add_vsi);
187 if (!vsi_ctx->alloc_from_pool)
188 cmd->vsi_num = cpu_to_le16(vsi_ctx->vsi_num |
189 ICE_AQ_VSI_IS_VALID);
190 cmd->vf_id = vsi_ctx->vf_num;
192 cmd->vsi_flags = cpu_to_le16(vsi_ctx->flags);
194 desc.flags |= cpu_to_le16(ICE_AQ_FLAG_RD);
196 status = ice_aq_send_cmd(hw, &desc, &vsi_ctx->info,
197 sizeof(vsi_ctx->info), cd);
200 vsi_ctx->vsi_num = le16_to_cpu(res->vsi_num) & ICE_AQ_VSI_NUM_M;
201 vsi_ctx->vsis_allocd = le16_to_cpu(res->vsi_used);
202 vsi_ctx->vsis_unallocated = le16_to_cpu(res->vsi_free);
210 * @hw: pointer to the hw struct
211 * @vsi_ctx: pointer to a VSI context struct
212 * @keep_vsi_alloc: keep VSI allocation as part of this PF's resources
213 * @cd: pointer to command details structure or NULL
215 * Free VSI context info from hardware (0x0213)
217 static enum ice_status
218 ice_aq_free_vsi(struct ice_hw *hw, struct ice_vsi_ctx *vsi_ctx,
219 bool keep_vsi_alloc, struct ice_sq_cd *cd)
221 struct ice_aqc_add_update_free_vsi_resp *resp;
222 struct ice_aqc_add_get_update_free_vsi *cmd;
223 struct ice_aq_desc desc;
224 enum ice_status status;
226 cmd = &desc.params.vsi_cmd;
227 resp = &desc.params.add_update_free_vsi_res;
229 ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_free_vsi);
231 cmd->vsi_num = cpu_to_le16(vsi_ctx->vsi_num | ICE_AQ_VSI_IS_VALID);
233 cmd->cmd_flags = cpu_to_le16(ICE_AQ_VSI_KEEP_ALLOC);
235 status = ice_aq_send_cmd(hw, &desc, NULL, 0, cd);
237 vsi_ctx->vsis_allocd = le16_to_cpu(resp->vsi_used);
238 vsi_ctx->vsis_unallocated = le16_to_cpu(resp->vsi_free);
246 * @hw: pointer to the hw struct
247 * @vsi_ctx: pointer to a VSI context struct
248 * @cd: pointer to command details structure or NULL
250 * Update VSI context in the hardware (0x0211)
252 static enum ice_status
253 ice_aq_update_vsi(struct ice_hw *hw, struct ice_vsi_ctx *vsi_ctx,
254 struct ice_sq_cd *cd)
256 struct ice_aqc_add_update_free_vsi_resp *resp;
257 struct ice_aqc_add_get_update_free_vsi *cmd;
258 struct ice_aq_desc desc;
259 enum ice_status status;
261 cmd = &desc.params.vsi_cmd;
262 resp = &desc.params.add_update_free_vsi_res;
264 ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_update_vsi);
266 cmd->vsi_num = cpu_to_le16(vsi_ctx->vsi_num | ICE_AQ_VSI_IS_VALID);
268 desc.flags |= cpu_to_le16(ICE_AQ_FLAG_RD);
270 status = ice_aq_send_cmd(hw, &desc, &vsi_ctx->info,
271 sizeof(vsi_ctx->info), cd);
274 vsi_ctx->vsis_allocd = le16_to_cpu(resp->vsi_used);
275 vsi_ctx->vsis_unallocated = le16_to_cpu(resp->vsi_free);
282 * ice_is_vsi_valid - check whether the VSI is valid or not
283 * @hw: pointer to the hw struct
284 * @vsi_handle: VSI handle
286 * check whether the VSI is valid or not
288 bool ice_is_vsi_valid(struct ice_hw *hw, u16 vsi_handle)
290 return vsi_handle < ICE_MAX_VSI && hw->vsi_ctx[vsi_handle];
294 * ice_get_hw_vsi_num - return the hw VSI number
295 * @hw: pointer to the hw struct
296 * @vsi_handle: VSI handle
298 * return the hw VSI number
299 * Caution: call this function only if VSI is valid (ice_is_vsi_valid)
301 u16 ice_get_hw_vsi_num(struct ice_hw *hw, u16 vsi_handle)
303 return hw->vsi_ctx[vsi_handle]->vsi_num;
307 * ice_get_vsi_ctx - return the VSI context entry for a given VSI handle
308 * @hw: pointer to the hw struct
309 * @vsi_handle: VSI handle
311 * return the VSI context entry for a given VSI handle
313 struct ice_vsi_ctx *ice_get_vsi_ctx(struct ice_hw *hw, u16 vsi_handle)
315 return (vsi_handle >= ICE_MAX_VSI) ? NULL : hw->vsi_ctx[vsi_handle];
319 * ice_save_vsi_ctx - save the VSI context for a given VSI handle
320 * @hw: pointer to the hw struct
321 * @vsi_handle: VSI handle
322 * @vsi: VSI context pointer
324 * save the VSI context entry for a given VSI handle
326 static void ice_save_vsi_ctx(struct ice_hw *hw, u16 vsi_handle,
327 struct ice_vsi_ctx *vsi)
329 hw->vsi_ctx[vsi_handle] = vsi;
333 * ice_clear_vsi_ctx - clear the VSI context entry
334 * @hw: pointer to the hw struct
335 * @vsi_handle: VSI handle
337 * clear the VSI context entry
339 static void ice_clear_vsi_ctx(struct ice_hw *hw, u16 vsi_handle)
341 struct ice_vsi_ctx *vsi;
343 vsi = ice_get_vsi_ctx(hw, vsi_handle);
345 devm_kfree(ice_hw_to_dev(hw), vsi);
346 hw->vsi_ctx[vsi_handle] = NULL;
351 * ice_clear_all_vsi_ctx - clear all the VSI context entries
352 * @hw: pointer to the hw struct
354 void ice_clear_all_vsi_ctx(struct ice_hw *hw)
358 for (i = 0; i < ICE_MAX_VSI; i++)
359 ice_clear_vsi_ctx(hw, i);
363 * ice_add_vsi - add VSI context to the hardware and VSI handle list
364 * @hw: pointer to the hw struct
365 * @vsi_handle: unique VSI handle provided by drivers
366 * @vsi_ctx: pointer to a VSI context struct
367 * @cd: pointer to command details structure or NULL
369 * Add a VSI context to the hardware also add it into the VSI handle list.
370 * If this function gets called after reset for existing VSIs then update
371 * with the new HW VSI number in the corresponding VSI handle list entry.
374 ice_add_vsi(struct ice_hw *hw, u16 vsi_handle, struct ice_vsi_ctx *vsi_ctx,
375 struct ice_sq_cd *cd)
377 struct ice_vsi_ctx *tmp_vsi_ctx;
378 enum ice_status status;
380 if (vsi_handle >= ICE_MAX_VSI)
381 return ICE_ERR_PARAM;
382 status = ice_aq_add_vsi(hw, vsi_ctx, cd);
385 tmp_vsi_ctx = ice_get_vsi_ctx(hw, vsi_handle);
387 /* Create a new vsi context */
388 tmp_vsi_ctx = devm_kzalloc(ice_hw_to_dev(hw),
389 sizeof(*tmp_vsi_ctx), GFP_KERNEL);
391 ice_aq_free_vsi(hw, vsi_ctx, false, cd);
392 return ICE_ERR_NO_MEMORY;
394 *tmp_vsi_ctx = *vsi_ctx;
395 ice_save_vsi_ctx(hw, vsi_handle, tmp_vsi_ctx);
397 /* update with new HW VSI num */
398 if (tmp_vsi_ctx->vsi_num != vsi_ctx->vsi_num)
399 tmp_vsi_ctx->vsi_num = vsi_ctx->vsi_num;
406 * ice_free_vsi- free VSI context from hardware and VSI handle list
407 * @hw: pointer to the hw struct
408 * @vsi_handle: unique VSI handle
409 * @vsi_ctx: pointer to a VSI context struct
410 * @keep_vsi_alloc: keep VSI allocation as part of this PF's resources
411 * @cd: pointer to command details structure or NULL
413 * Free VSI context info from hardware as well as from VSI handle list
416 ice_free_vsi(struct ice_hw *hw, u16 vsi_handle, struct ice_vsi_ctx *vsi_ctx,
417 bool keep_vsi_alloc, struct ice_sq_cd *cd)
419 enum ice_status status;
421 if (!ice_is_vsi_valid(hw, vsi_handle))
422 return ICE_ERR_PARAM;
423 vsi_ctx->vsi_num = ice_get_hw_vsi_num(hw, vsi_handle);
424 status = ice_aq_free_vsi(hw, vsi_ctx, keep_vsi_alloc, cd);
426 ice_clear_vsi_ctx(hw, vsi_handle);
432 * @hw: pointer to the hw struct
433 * @vsi_handle: unique VSI handle
434 * @vsi_ctx: pointer to a VSI context struct
435 * @cd: pointer to command details structure or NULL
437 * Update VSI context in the hardware
440 ice_update_vsi(struct ice_hw *hw, u16 vsi_handle, struct ice_vsi_ctx *vsi_ctx,
441 struct ice_sq_cd *cd)
443 if (!ice_is_vsi_valid(hw, vsi_handle))
444 return ICE_ERR_PARAM;
445 vsi_ctx->vsi_num = ice_get_hw_vsi_num(hw, vsi_handle);
446 return ice_aq_update_vsi(hw, vsi_ctx, cd);
450 * ice_aq_alloc_free_vsi_list
451 * @hw: pointer to the hw struct
452 * @vsi_list_id: VSI list id returned or used for lookup
453 * @lkup_type: switch rule filter lookup type
454 * @opc: switch rules population command type - pass in the command opcode
456 * allocates or free a VSI list resource
458 static enum ice_status
459 ice_aq_alloc_free_vsi_list(struct ice_hw *hw, u16 *vsi_list_id,
460 enum ice_sw_lkup_type lkup_type,
461 enum ice_adminq_opc opc)
463 struct ice_aqc_alloc_free_res_elem *sw_buf;
464 struct ice_aqc_res_elem *vsi_ele;
465 enum ice_status status;
468 buf_len = sizeof(*sw_buf);
469 sw_buf = devm_kzalloc(ice_hw_to_dev(hw), buf_len, GFP_KERNEL);
471 return ICE_ERR_NO_MEMORY;
472 sw_buf->num_elems = cpu_to_le16(1);
474 if (lkup_type == ICE_SW_LKUP_MAC ||
475 lkup_type == ICE_SW_LKUP_MAC_VLAN ||
476 lkup_type == ICE_SW_LKUP_ETHERTYPE ||
477 lkup_type == ICE_SW_LKUP_ETHERTYPE_MAC ||
478 lkup_type == ICE_SW_LKUP_PROMISC ||
479 lkup_type == ICE_SW_LKUP_PROMISC_VLAN) {
480 sw_buf->res_type = cpu_to_le16(ICE_AQC_RES_TYPE_VSI_LIST_REP);
481 } else if (lkup_type == ICE_SW_LKUP_VLAN) {
483 cpu_to_le16(ICE_AQC_RES_TYPE_VSI_LIST_PRUNE);
485 status = ICE_ERR_PARAM;
486 goto ice_aq_alloc_free_vsi_list_exit;
489 if (opc == ice_aqc_opc_free_res)
490 sw_buf->elem[0].e.sw_resp = cpu_to_le16(*vsi_list_id);
492 status = ice_aq_alloc_free_res(hw, 1, sw_buf, buf_len, opc, NULL);
494 goto ice_aq_alloc_free_vsi_list_exit;
496 if (opc == ice_aqc_opc_alloc_res) {
497 vsi_ele = &sw_buf->elem[0];
498 *vsi_list_id = le16_to_cpu(vsi_ele->e.sw_resp);
501 ice_aq_alloc_free_vsi_list_exit:
502 devm_kfree(ice_hw_to_dev(hw), sw_buf);
507 * ice_aq_sw_rules - add/update/remove switch rules
508 * @hw: pointer to the hw struct
509 * @rule_list: pointer to switch rule population list
510 * @rule_list_sz: total size of the rule list in bytes
511 * @num_rules: number of switch rules in the rule_list
512 * @opc: switch rules population command type - pass in the command opcode
513 * @cd: pointer to command details structure or NULL
515 * Add(0x02a0)/Update(0x02a1)/Remove(0x02a2) switch rules commands to firmware
517 static enum ice_status
518 ice_aq_sw_rules(struct ice_hw *hw, void *rule_list, u16 rule_list_sz,
519 u8 num_rules, enum ice_adminq_opc opc, struct ice_sq_cd *cd)
521 struct ice_aq_desc desc;
523 if (opc != ice_aqc_opc_add_sw_rules &&
524 opc != ice_aqc_opc_update_sw_rules &&
525 opc != ice_aqc_opc_remove_sw_rules)
526 return ICE_ERR_PARAM;
528 ice_fill_dflt_direct_cmd_desc(&desc, opc);
530 desc.flags |= cpu_to_le16(ICE_AQ_FLAG_RD);
531 desc.params.sw_rules.num_rules_fltr_entry_index =
532 cpu_to_le16(num_rules);
533 return ice_aq_send_cmd(hw, &desc, rule_list, rule_list_sz, cd);
536 /* ice_init_port_info - Initialize port_info with switch configuration data
537 * @pi: pointer to port_info
538 * @vsi_port_num: VSI number or port number
539 * @type: Type of switch element (port or VSI)
540 * @swid: switch ID of the switch the element is attached to
541 * @pf_vf_num: PF or VF number
542 * @is_vf: true if the element is a VF, false otherwise
545 ice_init_port_info(struct ice_port_info *pi, u16 vsi_port_num, u8 type,
546 u16 swid, u16 pf_vf_num, bool is_vf)
549 case ICE_AQC_GET_SW_CONF_RESP_PHYS_PORT:
550 pi->lport = (u8)(vsi_port_num & ICE_LPORT_MASK);
552 pi->pf_vf_num = pf_vf_num;
554 pi->dflt_tx_vsi_num = ICE_DFLT_VSI_INVAL;
555 pi->dflt_rx_vsi_num = ICE_DFLT_VSI_INVAL;
558 ice_debug(pi->hw, ICE_DBG_SW,
559 "incorrect VSI/port type received\n");
564 /* ice_get_initial_sw_cfg - Get initial port and default VSI data
565 * @hw: pointer to the hardware structure
567 enum ice_status ice_get_initial_sw_cfg(struct ice_hw *hw)
569 struct ice_aqc_get_sw_cfg_resp *rbuf;
570 enum ice_status status;
575 rbuf = devm_kzalloc(ice_hw_to_dev(hw), ICE_SW_CFG_MAX_BUF_LEN,
579 return ICE_ERR_NO_MEMORY;
581 /* Multiple calls to ice_aq_get_sw_cfg may be required
582 * to get all the switch configuration information. The need
583 * for additional calls is indicated by ice_aq_get_sw_cfg
584 * writing a non-zero value in req_desc
587 status = ice_aq_get_sw_cfg(hw, rbuf, ICE_SW_CFG_MAX_BUF_LEN,
588 &req_desc, &num_elems, NULL);
593 for (i = 0; i < num_elems; i++) {
594 struct ice_aqc_get_sw_cfg_resp_elem *ele;
595 u16 pf_vf_num, swid, vsi_port_num;
599 ele = rbuf[i].elements;
600 vsi_port_num = le16_to_cpu(ele->vsi_port_num) &
601 ICE_AQC_GET_SW_CONF_RESP_VSI_PORT_NUM_M;
603 pf_vf_num = le16_to_cpu(ele->pf_vf_num) &
604 ICE_AQC_GET_SW_CONF_RESP_FUNC_NUM_M;
606 swid = le16_to_cpu(ele->swid);
608 if (le16_to_cpu(ele->pf_vf_num) &
609 ICE_AQC_GET_SW_CONF_RESP_IS_VF)
612 type = le16_to_cpu(ele->vsi_port_num) >>
613 ICE_AQC_GET_SW_CONF_RESP_TYPE_S;
615 if (type == ICE_AQC_GET_SW_CONF_RESP_VSI) {
616 /* FW VSI is not needed. Just continue. */
620 ice_init_port_info(hw->port_info, vsi_port_num,
621 type, swid, pf_vf_num, is_vf);
623 } while (req_desc && !status);
625 devm_kfree(ice_hw_to_dev(hw), (void *)rbuf);
630 * ice_fill_sw_info - Helper function to populate lb_en and lan_en
631 * @hw: pointer to the hardware structure
632 * @f_info: filter info structure to fill/update
634 * This helper function populates the lb_en and lan_en elements of the provided
635 * ice_fltr_info struct using the switch's type and characteristics of the
636 * switch rule being configured.
638 static void ice_fill_sw_info(struct ice_hw *hw, struct ice_fltr_info *f_info)
640 f_info->lb_en = false;
641 f_info->lan_en = false;
642 if ((f_info->flag & ICE_FLTR_TX) &&
643 (f_info->fltr_act == ICE_FWD_TO_VSI ||
644 f_info->fltr_act == ICE_FWD_TO_VSI_LIST ||
645 f_info->fltr_act == ICE_FWD_TO_Q ||
646 f_info->fltr_act == ICE_FWD_TO_QGRP)) {
647 f_info->lb_en = true;
648 if (!(hw->evb_veb && f_info->lkup_type == ICE_SW_LKUP_MAC &&
649 is_unicast_ether_addr(f_info->l_data.mac.mac_addr)))
650 f_info->lan_en = true;
655 * ice_fill_sw_rule - Helper function to fill switch rule structure
656 * @hw: pointer to the hardware structure
657 * @f_info: entry containing packet forwarding information
658 * @s_rule: switch rule structure to be filled in based on mac_entry
659 * @opc: switch rules population command type - pass in the command opcode
662 ice_fill_sw_rule(struct ice_hw *hw, struct ice_fltr_info *f_info,
663 struct ice_aqc_sw_rules_elem *s_rule, enum ice_adminq_opc opc)
665 u16 vlan_id = ICE_MAX_VLAN_ID + 1;
673 if (opc == ice_aqc_opc_remove_sw_rules) {
674 s_rule->pdata.lkup_tx_rx.act = 0;
675 s_rule->pdata.lkup_tx_rx.index =
676 cpu_to_le16(f_info->fltr_rule_id);
677 s_rule->pdata.lkup_tx_rx.hdr_len = 0;
681 eth_hdr_sz = sizeof(dummy_eth_header);
682 eth_hdr = s_rule->pdata.lkup_tx_rx.hdr;
684 /* initialize the ether header with a dummy header */
685 memcpy(eth_hdr, dummy_eth_header, eth_hdr_sz);
686 ice_fill_sw_info(hw, f_info);
688 switch (f_info->fltr_act) {
690 act |= (f_info->fwd_id.hw_vsi_id << ICE_SINGLE_ACT_VSI_ID_S) &
691 ICE_SINGLE_ACT_VSI_ID_M;
692 if (f_info->lkup_type != ICE_SW_LKUP_VLAN)
693 act |= ICE_SINGLE_ACT_VSI_FORWARDING |
694 ICE_SINGLE_ACT_VALID_BIT;
696 case ICE_FWD_TO_VSI_LIST:
697 act |= ICE_SINGLE_ACT_VSI_LIST;
698 act |= (f_info->fwd_id.vsi_list_id <<
699 ICE_SINGLE_ACT_VSI_LIST_ID_S) &
700 ICE_SINGLE_ACT_VSI_LIST_ID_M;
701 if (f_info->lkup_type != ICE_SW_LKUP_VLAN)
702 act |= ICE_SINGLE_ACT_VSI_FORWARDING |
703 ICE_SINGLE_ACT_VALID_BIT;
706 act |= ICE_SINGLE_ACT_TO_Q;
707 act |= (f_info->fwd_id.q_id << ICE_SINGLE_ACT_Q_INDEX_S) &
708 ICE_SINGLE_ACT_Q_INDEX_M;
710 case ICE_DROP_PACKET:
711 act |= ICE_SINGLE_ACT_VSI_FORWARDING | ICE_SINGLE_ACT_DROP |
712 ICE_SINGLE_ACT_VALID_BIT;
714 case ICE_FWD_TO_QGRP:
715 q_rgn = f_info->qgrp_size > 0 ?
716 (u8)ilog2(f_info->qgrp_size) : 0;
717 act |= ICE_SINGLE_ACT_TO_Q;
718 act |= (f_info->fwd_id.q_id << ICE_SINGLE_ACT_Q_INDEX_S) &
719 ICE_SINGLE_ACT_Q_INDEX_M;
720 act |= (q_rgn << ICE_SINGLE_ACT_Q_REGION_S) &
721 ICE_SINGLE_ACT_Q_REGION_M;
728 act |= ICE_SINGLE_ACT_LB_ENABLE;
730 act |= ICE_SINGLE_ACT_LAN_ENABLE;
732 switch (f_info->lkup_type) {
733 case ICE_SW_LKUP_MAC:
734 daddr = f_info->l_data.mac.mac_addr;
736 case ICE_SW_LKUP_VLAN:
737 vlan_id = f_info->l_data.vlan.vlan_id;
738 if (f_info->fltr_act == ICE_FWD_TO_VSI ||
739 f_info->fltr_act == ICE_FWD_TO_VSI_LIST) {
740 act |= ICE_SINGLE_ACT_PRUNE;
741 act |= ICE_SINGLE_ACT_EGRESS | ICE_SINGLE_ACT_INGRESS;
744 case ICE_SW_LKUP_ETHERTYPE_MAC:
745 daddr = f_info->l_data.ethertype_mac.mac_addr;
747 case ICE_SW_LKUP_ETHERTYPE:
748 off = (__be16 *)(eth_hdr + ICE_ETH_ETHTYPE_OFFSET);
749 *off = cpu_to_be16(f_info->l_data.ethertype_mac.ethertype);
751 case ICE_SW_LKUP_MAC_VLAN:
752 daddr = f_info->l_data.mac_vlan.mac_addr;
753 vlan_id = f_info->l_data.mac_vlan.vlan_id;
755 case ICE_SW_LKUP_PROMISC_VLAN:
756 vlan_id = f_info->l_data.mac_vlan.vlan_id;
758 case ICE_SW_LKUP_PROMISC:
759 daddr = f_info->l_data.mac_vlan.mac_addr;
765 s_rule->type = (f_info->flag & ICE_FLTR_RX) ?
766 cpu_to_le16(ICE_AQC_SW_RULES_T_LKUP_RX) :
767 cpu_to_le16(ICE_AQC_SW_RULES_T_LKUP_TX);
769 /* Recipe set depending on lookup type */
770 s_rule->pdata.lkup_tx_rx.recipe_id = cpu_to_le16(f_info->lkup_type);
771 s_rule->pdata.lkup_tx_rx.src = cpu_to_le16(f_info->src);
772 s_rule->pdata.lkup_tx_rx.act = cpu_to_le32(act);
775 ether_addr_copy(eth_hdr + ICE_ETH_DA_OFFSET, daddr);
777 if (!(vlan_id > ICE_MAX_VLAN_ID)) {
778 off = (__be16 *)(eth_hdr + ICE_ETH_VLAN_TCI_OFFSET);
779 *off = cpu_to_be16(vlan_id);
782 /* Create the switch rule with the final dummy Ethernet header */
783 if (opc != ice_aqc_opc_update_sw_rules)
784 s_rule->pdata.lkup_tx_rx.hdr_len = cpu_to_le16(eth_hdr_sz);
789 * @hw: pointer to the hardware structure
790 * @m_ent: the management entry for which sw marker needs to be added
791 * @sw_marker: sw marker to tag the Rx descriptor with
792 * @l_id: large action resource id
794 * Create a large action to hold software marker and update the switch rule
795 * entry pointed by m_ent with newly created large action
797 static enum ice_status
798 ice_add_marker_act(struct ice_hw *hw, struct ice_fltr_mgmt_list_entry *m_ent,
799 u16 sw_marker, u16 l_id)
801 struct ice_aqc_sw_rules_elem *lg_act, *rx_tx;
802 /* For software marker we need 3 large actions
803 * 1. FWD action: FWD TO VSI or VSI LIST
804 * 2. GENERIC VALUE action to hold the profile id
805 * 3. GENERIC VALUE action to hold the software marker id
807 const u16 num_lg_acts = 3;
808 enum ice_status status;
814 if (m_ent->fltr_info.lkup_type != ICE_SW_LKUP_MAC)
815 return ICE_ERR_PARAM;
817 /* Create two back-to-back switch rules and submit them to the HW using
822 lg_act_size = (u16)ICE_SW_RULE_LG_ACT_SIZE(num_lg_acts);
823 rules_size = lg_act_size + ICE_SW_RULE_RX_TX_ETH_HDR_SIZE;
824 lg_act = devm_kzalloc(ice_hw_to_dev(hw), rules_size, GFP_KERNEL);
826 return ICE_ERR_NO_MEMORY;
828 rx_tx = (struct ice_aqc_sw_rules_elem *)((u8 *)lg_act + lg_act_size);
830 /* Fill in the first switch rule i.e. large action */
831 lg_act->type = cpu_to_le16(ICE_AQC_SW_RULES_T_LG_ACT);
832 lg_act->pdata.lg_act.index = cpu_to_le16(l_id);
833 lg_act->pdata.lg_act.size = cpu_to_le16(num_lg_acts);
835 /* First action VSI forwarding or VSI list forwarding depending on how
838 id = (m_ent->vsi_count > 1) ? m_ent->fltr_info.fwd_id.vsi_list_id :
839 m_ent->fltr_info.fwd_id.hw_vsi_id;
841 act = ICE_LG_ACT_VSI_FORWARDING | ICE_LG_ACT_VALID_BIT;
842 act |= (id << ICE_LG_ACT_VSI_LIST_ID_S) &
843 ICE_LG_ACT_VSI_LIST_ID_M;
844 if (m_ent->vsi_count > 1)
845 act |= ICE_LG_ACT_VSI_LIST;
846 lg_act->pdata.lg_act.act[0] = cpu_to_le32(act);
848 /* Second action descriptor type */
849 act = ICE_LG_ACT_GENERIC;
851 act |= (1 << ICE_LG_ACT_GENERIC_VALUE_S) & ICE_LG_ACT_GENERIC_VALUE_M;
852 lg_act->pdata.lg_act.act[1] = cpu_to_le32(act);
854 act = (ICE_LG_ACT_GENERIC_OFF_RX_DESC_PROF_IDX <<
855 ICE_LG_ACT_GENERIC_OFFSET_S) & ICE_LG_ACT_GENERIC_OFFSET_M;
857 /* Third action Marker value */
858 act |= ICE_LG_ACT_GENERIC;
859 act |= (sw_marker << ICE_LG_ACT_GENERIC_VALUE_S) &
860 ICE_LG_ACT_GENERIC_VALUE_M;
862 lg_act->pdata.lg_act.act[2] = cpu_to_le32(act);
864 /* call the fill switch rule to fill the lookup tx rx structure */
865 ice_fill_sw_rule(hw, &m_ent->fltr_info, rx_tx,
866 ice_aqc_opc_update_sw_rules);
868 /* Update the action to point to the large action id */
869 rx_tx->pdata.lkup_tx_rx.act =
870 cpu_to_le32(ICE_SINGLE_ACT_PTR |
871 ((l_id << ICE_SINGLE_ACT_PTR_VAL_S) &
872 ICE_SINGLE_ACT_PTR_VAL_M));
874 /* Use the filter rule id of the previously created rule with single
875 * act. Once the update happens, hardware will treat this as large
878 rx_tx->pdata.lkup_tx_rx.index =
879 cpu_to_le16(m_ent->fltr_info.fltr_rule_id);
881 status = ice_aq_sw_rules(hw, lg_act, rules_size, 2,
882 ice_aqc_opc_update_sw_rules, NULL);
884 m_ent->lg_act_idx = l_id;
885 m_ent->sw_marker_id = sw_marker;
888 devm_kfree(ice_hw_to_dev(hw), lg_act);
893 * ice_create_vsi_list_map
894 * @hw: pointer to the hardware structure
895 * @vsi_handle_arr: array of VSI handles to set in the VSI mapping
896 * @num_vsi: number of VSI handles in the array
897 * @vsi_list_id: VSI list id generated as part of allocate resource
899 * Helper function to create a new entry of VSI list id to VSI mapping
900 * using the given VSI list id
902 static struct ice_vsi_list_map_info *
903 ice_create_vsi_list_map(struct ice_hw *hw, u16 *vsi_handle_arr, u16 num_vsi,
906 struct ice_switch_info *sw = hw->switch_info;
907 struct ice_vsi_list_map_info *v_map;
910 v_map = devm_kcalloc(ice_hw_to_dev(hw), 1, sizeof(*v_map), GFP_KERNEL);
914 v_map->vsi_list_id = vsi_list_id;
916 for (i = 0; i < num_vsi; i++)
917 set_bit(vsi_handle_arr[i], v_map->vsi_map);
919 list_add(&v_map->list_entry, &sw->vsi_list_map_head);
924 * ice_update_vsi_list_rule
925 * @hw: pointer to the hardware structure
926 * @vsi_handle_arr: array of VSI handles to form a VSI list
927 * @num_vsi: number of VSI handles in the array
928 * @vsi_list_id: VSI list id generated as part of allocate resource
929 * @remove: Boolean value to indicate if this is a remove action
930 * @opc: switch rules population command type - pass in the command opcode
931 * @lkup_type: lookup type of the filter
933 * Call AQ command to add a new switch rule or update existing switch rule
934 * using the given VSI list id
936 static enum ice_status
937 ice_update_vsi_list_rule(struct ice_hw *hw, u16 *vsi_handle_arr, u16 num_vsi,
938 u16 vsi_list_id, bool remove, enum ice_adminq_opc opc,
939 enum ice_sw_lkup_type lkup_type)
941 struct ice_aqc_sw_rules_elem *s_rule;
942 enum ice_status status;
948 return ICE_ERR_PARAM;
950 if (lkup_type == ICE_SW_LKUP_MAC ||
951 lkup_type == ICE_SW_LKUP_MAC_VLAN ||
952 lkup_type == ICE_SW_LKUP_ETHERTYPE ||
953 lkup_type == ICE_SW_LKUP_ETHERTYPE_MAC ||
954 lkup_type == ICE_SW_LKUP_PROMISC ||
955 lkup_type == ICE_SW_LKUP_PROMISC_VLAN)
956 type = remove ? ICE_AQC_SW_RULES_T_VSI_LIST_CLEAR :
957 ICE_AQC_SW_RULES_T_VSI_LIST_SET;
958 else if (lkup_type == ICE_SW_LKUP_VLAN)
959 type = remove ? ICE_AQC_SW_RULES_T_PRUNE_LIST_CLEAR :
960 ICE_AQC_SW_RULES_T_PRUNE_LIST_SET;
962 return ICE_ERR_PARAM;
964 s_rule_size = (u16)ICE_SW_RULE_VSI_LIST_SIZE(num_vsi);
965 s_rule = devm_kzalloc(ice_hw_to_dev(hw), s_rule_size, GFP_KERNEL);
967 return ICE_ERR_NO_MEMORY;
968 for (i = 0; i < num_vsi; i++) {
969 if (!ice_is_vsi_valid(hw, vsi_handle_arr[i])) {
970 status = ICE_ERR_PARAM;
973 /* AQ call requires hw_vsi_id(s) */
974 s_rule->pdata.vsi_list.vsi[i] =
975 cpu_to_le16(ice_get_hw_vsi_num(hw, vsi_handle_arr[i]));
978 s_rule->type = cpu_to_le16(type);
979 s_rule->pdata.vsi_list.number_vsi = cpu_to_le16(num_vsi);
980 s_rule->pdata.vsi_list.index = cpu_to_le16(vsi_list_id);
982 status = ice_aq_sw_rules(hw, s_rule, s_rule_size, 1, opc, NULL);
985 devm_kfree(ice_hw_to_dev(hw), s_rule);
990 * ice_create_vsi_list_rule - Creates and populates a VSI list rule
991 * @hw: pointer to the hw struct
992 * @vsi_handle_arr: array of VSI handles to form a VSI list
993 * @num_vsi: number of VSI handles in the array
994 * @vsi_list_id: stores the ID of the VSI list to be created
995 * @lkup_type: switch rule filter's lookup type
997 static enum ice_status
998 ice_create_vsi_list_rule(struct ice_hw *hw, u16 *vsi_handle_arr, u16 num_vsi,
999 u16 *vsi_list_id, enum ice_sw_lkup_type lkup_type)
1001 enum ice_status status;
1003 status = ice_aq_alloc_free_vsi_list(hw, vsi_list_id, lkup_type,
1004 ice_aqc_opc_alloc_res);
1008 /* Update the newly created VSI list to include the specified VSIs */
1009 return ice_update_vsi_list_rule(hw, vsi_handle_arr, num_vsi,
1010 *vsi_list_id, false,
1011 ice_aqc_opc_add_sw_rules, lkup_type);
1015 * ice_create_pkt_fwd_rule
1016 * @hw: pointer to the hardware structure
1017 * @f_entry: entry containing packet forwarding information
1019 * Create switch rule with given filter information and add an entry
1020 * to the corresponding filter management list to track this switch rule
1023 static enum ice_status
1024 ice_create_pkt_fwd_rule(struct ice_hw *hw,
1025 struct ice_fltr_list_entry *f_entry)
1027 struct ice_fltr_mgmt_list_entry *fm_entry;
1028 struct ice_aqc_sw_rules_elem *s_rule;
1029 enum ice_sw_lkup_type l_type;
1030 struct ice_sw_recipe *recp;
1031 enum ice_status status;
1033 s_rule = devm_kzalloc(ice_hw_to_dev(hw),
1034 ICE_SW_RULE_RX_TX_ETH_HDR_SIZE, GFP_KERNEL);
1036 return ICE_ERR_NO_MEMORY;
1037 fm_entry = devm_kzalloc(ice_hw_to_dev(hw), sizeof(*fm_entry),
1040 status = ICE_ERR_NO_MEMORY;
1041 goto ice_create_pkt_fwd_rule_exit;
1044 fm_entry->fltr_info = f_entry->fltr_info;
1046 /* Initialize all the fields for the management entry */
1047 fm_entry->vsi_count = 1;
1048 fm_entry->lg_act_idx = ICE_INVAL_LG_ACT_INDEX;
1049 fm_entry->sw_marker_id = ICE_INVAL_SW_MARKER_ID;
1050 fm_entry->counter_index = ICE_INVAL_COUNTER_ID;
1052 ice_fill_sw_rule(hw, &fm_entry->fltr_info, s_rule,
1053 ice_aqc_opc_add_sw_rules);
1055 status = ice_aq_sw_rules(hw, s_rule, ICE_SW_RULE_RX_TX_ETH_HDR_SIZE, 1,
1056 ice_aqc_opc_add_sw_rules, NULL);
1058 devm_kfree(ice_hw_to_dev(hw), fm_entry);
1059 goto ice_create_pkt_fwd_rule_exit;
1062 f_entry->fltr_info.fltr_rule_id =
1063 le16_to_cpu(s_rule->pdata.lkup_tx_rx.index);
1064 fm_entry->fltr_info.fltr_rule_id =
1065 le16_to_cpu(s_rule->pdata.lkup_tx_rx.index);
1067 /* The book keeping entries will get removed when base driver
1068 * calls remove filter AQ command
1070 l_type = fm_entry->fltr_info.lkup_type;
1071 recp = &hw->switch_info->recp_list[l_type];
1072 list_add(&fm_entry->list_entry, &recp->filt_rules);
1074 ice_create_pkt_fwd_rule_exit:
1075 devm_kfree(ice_hw_to_dev(hw), s_rule);
1080 * ice_update_pkt_fwd_rule
1081 * @hw: pointer to the hardware structure
1082 * @f_info: filter information for switch rule
1084 * Call AQ command to update a previously created switch rule with a
1087 static enum ice_status
1088 ice_update_pkt_fwd_rule(struct ice_hw *hw, struct ice_fltr_info *f_info)
1090 struct ice_aqc_sw_rules_elem *s_rule;
1091 enum ice_status status;
1093 s_rule = devm_kzalloc(ice_hw_to_dev(hw),
1094 ICE_SW_RULE_RX_TX_ETH_HDR_SIZE, GFP_KERNEL);
1096 return ICE_ERR_NO_MEMORY;
1098 ice_fill_sw_rule(hw, f_info, s_rule, ice_aqc_opc_update_sw_rules);
1100 s_rule->pdata.lkup_tx_rx.index = cpu_to_le16(f_info->fltr_rule_id);
1102 /* Update switch rule with new rule set to forward VSI list */
1103 status = ice_aq_sw_rules(hw, s_rule, ICE_SW_RULE_RX_TX_ETH_HDR_SIZE, 1,
1104 ice_aqc_opc_update_sw_rules, NULL);
1106 devm_kfree(ice_hw_to_dev(hw), s_rule);
1111 * ice_update_sw_rule_bridge_mode
1112 * @hw: pointer to the hw struct
1114 * Updates unicast switch filter rules based on VEB/VEPA mode
1116 enum ice_status ice_update_sw_rule_bridge_mode(struct ice_hw *hw)
1118 struct ice_switch_info *sw = hw->switch_info;
1119 struct ice_fltr_mgmt_list_entry *fm_entry;
1120 enum ice_status status = 0;
1121 struct list_head *rule_head;
1122 struct mutex *rule_lock; /* Lock to protect filter rule list */
1124 rule_lock = &sw->recp_list[ICE_SW_LKUP_MAC].filt_rule_lock;
1125 rule_head = &sw->recp_list[ICE_SW_LKUP_MAC].filt_rules;
1127 mutex_lock(rule_lock);
1128 list_for_each_entry(fm_entry, rule_head, list_entry) {
1129 struct ice_fltr_info *fi = &fm_entry->fltr_info;
1130 u8 *addr = fi->l_data.mac.mac_addr;
1132 /* Update unicast Tx rules to reflect the selected
1135 if ((fi->flag & ICE_FLTR_TX) && is_unicast_ether_addr(addr) &&
1136 (fi->fltr_act == ICE_FWD_TO_VSI ||
1137 fi->fltr_act == ICE_FWD_TO_VSI_LIST ||
1138 fi->fltr_act == ICE_FWD_TO_Q ||
1139 fi->fltr_act == ICE_FWD_TO_QGRP)) {
1140 status = ice_update_pkt_fwd_rule(hw, fi);
1146 mutex_unlock(rule_lock);
1152 * ice_add_update_vsi_list
1153 * @hw: pointer to the hardware structure
1154 * @m_entry: pointer to current filter management list entry
1155 * @cur_fltr: filter information from the book keeping entry
1156 * @new_fltr: filter information with the new VSI to be added
1158 * Call AQ command to add or update previously created VSI list with new VSI.
1160 * Helper function to do book keeping associated with adding filter information
1161 * The algorithm to do the booking keeping is described below :
1162 * When a VSI needs to subscribe to a given filter( MAC/VLAN/Ethtype etc.)
1163 * if only one VSI has been added till now
1164 * Allocate a new VSI list and add two VSIs
1165 * to this list using switch rule command
1166 * Update the previously created switch rule with the
1167 * newly created VSI list id
1168 * if a VSI list was previously created
1169 * Add the new VSI to the previously created VSI list set
1170 * using the update switch rule command
1172 static enum ice_status
1173 ice_add_update_vsi_list(struct ice_hw *hw,
1174 struct ice_fltr_mgmt_list_entry *m_entry,
1175 struct ice_fltr_info *cur_fltr,
1176 struct ice_fltr_info *new_fltr)
1178 enum ice_status status = 0;
1179 u16 vsi_list_id = 0;
1181 if ((cur_fltr->fltr_act == ICE_FWD_TO_Q ||
1182 cur_fltr->fltr_act == ICE_FWD_TO_QGRP))
1183 return ICE_ERR_NOT_IMPL;
1185 if ((new_fltr->fltr_act == ICE_FWD_TO_Q ||
1186 new_fltr->fltr_act == ICE_FWD_TO_QGRP) &&
1187 (cur_fltr->fltr_act == ICE_FWD_TO_VSI ||
1188 cur_fltr->fltr_act == ICE_FWD_TO_VSI_LIST))
1189 return ICE_ERR_NOT_IMPL;
1191 if (m_entry->vsi_count < 2 && !m_entry->vsi_list_info) {
1192 /* Only one entry existed in the mapping and it was not already
1193 * a part of a VSI list. So, create a VSI list with the old and
1196 struct ice_fltr_info tmp_fltr;
1197 u16 vsi_handle_arr[2];
1199 /* A rule already exists with the new VSI being added */
1200 if (cur_fltr->fwd_id.hw_vsi_id == new_fltr->fwd_id.hw_vsi_id)
1201 return ICE_ERR_ALREADY_EXISTS;
1203 vsi_handle_arr[0] = cur_fltr->vsi_handle;
1204 vsi_handle_arr[1] = new_fltr->vsi_handle;
1205 status = ice_create_vsi_list_rule(hw, &vsi_handle_arr[0], 2,
1207 new_fltr->lkup_type);
1211 tmp_fltr = *new_fltr;
1212 tmp_fltr.fltr_rule_id = cur_fltr->fltr_rule_id;
1213 tmp_fltr.fltr_act = ICE_FWD_TO_VSI_LIST;
1214 tmp_fltr.fwd_id.vsi_list_id = vsi_list_id;
1215 /* Update the previous switch rule of "MAC forward to VSI" to
1216 * "MAC fwd to VSI list"
1218 status = ice_update_pkt_fwd_rule(hw, &tmp_fltr);
1222 cur_fltr->fwd_id.vsi_list_id = vsi_list_id;
1223 cur_fltr->fltr_act = ICE_FWD_TO_VSI_LIST;
1224 m_entry->vsi_list_info =
1225 ice_create_vsi_list_map(hw, &vsi_handle_arr[0], 2,
1228 /* If this entry was large action then the large action needs
1229 * to be updated to point to FWD to VSI list
1231 if (m_entry->sw_marker_id != ICE_INVAL_SW_MARKER_ID)
1233 ice_add_marker_act(hw, m_entry,
1234 m_entry->sw_marker_id,
1235 m_entry->lg_act_idx);
1237 u16 vsi_handle = new_fltr->vsi_handle;
1238 enum ice_adminq_opc opcode;
1240 /* A rule already exists with the new VSI being added */
1241 if (test_bit(vsi_handle, m_entry->vsi_list_info->vsi_map))
1244 /* Update the previously created VSI list set with
1245 * the new VSI id passed in
1247 vsi_list_id = cur_fltr->fwd_id.vsi_list_id;
1248 opcode = ice_aqc_opc_update_sw_rules;
1250 status = ice_update_vsi_list_rule(hw, &vsi_handle, 1,
1251 vsi_list_id, false, opcode,
1252 new_fltr->lkup_type);
1253 /* update VSI list mapping info with new VSI id */
1255 set_bit(vsi_handle, m_entry->vsi_list_info->vsi_map);
1258 m_entry->vsi_count++;
1263 * ice_find_rule_entry - Search a rule entry
1264 * @hw: pointer to the hardware structure
1265 * @recp_id: lookup type for which the specified rule needs to be searched
1266 * @f_info: rule information
1268 * Helper function to search for a given rule entry
1269 * Returns pointer to entry storing the rule if found
1271 static struct ice_fltr_mgmt_list_entry *
1272 ice_find_rule_entry(struct ice_hw *hw, u8 recp_id, struct ice_fltr_info *f_info)
1274 struct ice_fltr_mgmt_list_entry *list_itr, *ret = NULL;
1275 struct ice_switch_info *sw = hw->switch_info;
1276 struct list_head *list_head;
1278 list_head = &sw->recp_list[recp_id].filt_rules;
1279 list_for_each_entry(list_itr, list_head, list_entry) {
1280 if (!memcmp(&f_info->l_data, &list_itr->fltr_info.l_data,
1281 sizeof(f_info->l_data)) &&
1282 f_info->flag == list_itr->fltr_info.flag) {
1291 * ice_find_vsi_list_entry - Search VSI list map with VSI count 1
1292 * @hw: pointer to the hardware structure
1293 * @recp_id: lookup type for which VSI lists needs to be searched
1294 * @vsi_handle: VSI handle to be found in VSI list
1295 * @vsi_list_id: VSI list id found containing vsi_handle
1297 * Helper function to search a VSI list with single entry containing given VSI
1298 * handle element. This can be extended further to search VSI list with more
1299 * than 1 vsi_count. Returns pointer to VSI list entry if found.
1301 static struct ice_vsi_list_map_info *
1302 ice_find_vsi_list_entry(struct ice_hw *hw, u8 recp_id, u16 vsi_handle,
1305 struct ice_vsi_list_map_info *map_info = NULL;
1306 struct ice_switch_info *sw = hw->switch_info;
1307 struct ice_fltr_mgmt_list_entry *list_itr;
1308 struct list_head *list_head;
1310 list_head = &sw->recp_list[recp_id].filt_rules;
1311 list_for_each_entry(list_itr, list_head, list_entry) {
1312 if (list_itr->vsi_count == 1 && list_itr->vsi_list_info) {
1313 map_info = list_itr->vsi_list_info;
1314 if (test_bit(vsi_handle, map_info->vsi_map)) {
1315 *vsi_list_id = map_info->vsi_list_id;
1324 * ice_add_rule_internal - add rule for a given lookup type
1325 * @hw: pointer to the hardware structure
1326 * @recp_id: lookup type (recipe id) for which rule has to be added
1327 * @f_entry: structure containing MAC forwarding information
1329 * Adds or updates the rule lists for a given recipe
1331 static enum ice_status
1332 ice_add_rule_internal(struct ice_hw *hw, u8 recp_id,
1333 struct ice_fltr_list_entry *f_entry)
1335 struct ice_switch_info *sw = hw->switch_info;
1336 struct ice_fltr_info *new_fltr, *cur_fltr;
1337 struct ice_fltr_mgmt_list_entry *m_entry;
1338 struct mutex *rule_lock; /* Lock to protect filter rule list */
1339 enum ice_status status = 0;
1341 if (!ice_is_vsi_valid(hw, f_entry->fltr_info.vsi_handle))
1342 return ICE_ERR_PARAM;
1343 f_entry->fltr_info.fwd_id.hw_vsi_id =
1344 ice_get_hw_vsi_num(hw, f_entry->fltr_info.vsi_handle);
1346 rule_lock = &sw->recp_list[recp_id].filt_rule_lock;
1348 mutex_lock(rule_lock);
1349 new_fltr = &f_entry->fltr_info;
1350 if (new_fltr->flag & ICE_FLTR_RX)
1351 new_fltr->src = hw->port_info->lport;
1352 else if (new_fltr->flag & ICE_FLTR_TX)
1353 new_fltr->src = f_entry->fltr_info.fwd_id.hw_vsi_id;
1355 m_entry = ice_find_rule_entry(hw, recp_id, new_fltr);
1357 mutex_unlock(rule_lock);
1358 return ice_create_pkt_fwd_rule(hw, f_entry);
1361 cur_fltr = &m_entry->fltr_info;
1362 status = ice_add_update_vsi_list(hw, m_entry, cur_fltr, new_fltr);
1363 mutex_unlock(rule_lock);
1369 * ice_remove_vsi_list_rule
1370 * @hw: pointer to the hardware structure
1371 * @vsi_list_id: VSI list id generated as part of allocate resource
1372 * @lkup_type: switch rule filter lookup type
1374 * The VSI list should be emptied before this function is called to remove the
1377 static enum ice_status
1378 ice_remove_vsi_list_rule(struct ice_hw *hw, u16 vsi_list_id,
1379 enum ice_sw_lkup_type lkup_type)
1381 struct ice_aqc_sw_rules_elem *s_rule;
1382 enum ice_status status;
1385 s_rule_size = (u16)ICE_SW_RULE_VSI_LIST_SIZE(0);
1386 s_rule = devm_kzalloc(ice_hw_to_dev(hw), s_rule_size, GFP_KERNEL);
1388 return ICE_ERR_NO_MEMORY;
1390 s_rule->type = cpu_to_le16(ICE_AQC_SW_RULES_T_VSI_LIST_CLEAR);
1391 s_rule->pdata.vsi_list.index = cpu_to_le16(vsi_list_id);
1393 /* Free the vsi_list resource that we allocated. It is assumed that the
1394 * list is empty at this point.
1396 status = ice_aq_alloc_free_vsi_list(hw, &vsi_list_id, lkup_type,
1397 ice_aqc_opc_free_res);
1399 devm_kfree(ice_hw_to_dev(hw), s_rule);
1404 * ice_rem_update_vsi_list
1405 * @hw: pointer to the hardware structure
1406 * @vsi_handle: VSI handle of the VSI to remove
1407 * @fm_list: filter management entry for which the VSI list management needs to
1410 static enum ice_status
1411 ice_rem_update_vsi_list(struct ice_hw *hw, u16 vsi_handle,
1412 struct ice_fltr_mgmt_list_entry *fm_list)
1414 enum ice_sw_lkup_type lkup_type;
1415 enum ice_status status = 0;
1418 if (fm_list->fltr_info.fltr_act != ICE_FWD_TO_VSI_LIST ||
1419 fm_list->vsi_count == 0)
1420 return ICE_ERR_PARAM;
1422 /* A rule with the VSI being removed does not exist */
1423 if (!test_bit(vsi_handle, fm_list->vsi_list_info->vsi_map))
1424 return ICE_ERR_DOES_NOT_EXIST;
1426 lkup_type = fm_list->fltr_info.lkup_type;
1427 vsi_list_id = fm_list->fltr_info.fwd_id.vsi_list_id;
1428 status = ice_update_vsi_list_rule(hw, &vsi_handle, 1, vsi_list_id, true,
1429 ice_aqc_opc_update_sw_rules,
1434 fm_list->vsi_count--;
1435 clear_bit(vsi_handle, fm_list->vsi_list_info->vsi_map);
1437 if (fm_list->vsi_count == 1 && lkup_type != ICE_SW_LKUP_VLAN) {
1438 struct ice_fltr_info tmp_fltr_info = fm_list->fltr_info;
1439 struct ice_vsi_list_map_info *vsi_list_info =
1440 fm_list->vsi_list_info;
1443 rem_vsi_handle = find_first_bit(vsi_list_info->vsi_map,
1445 if (!ice_is_vsi_valid(hw, rem_vsi_handle))
1446 return ICE_ERR_OUT_OF_RANGE;
1448 /* Make sure VSI list is empty before removing it below */
1449 status = ice_update_vsi_list_rule(hw, &rem_vsi_handle, 1,
1451 ice_aqc_opc_update_sw_rules,
1456 tmp_fltr_info.fltr_act = ICE_FWD_TO_VSI;
1457 tmp_fltr_info.fwd_id.hw_vsi_id =
1458 ice_get_hw_vsi_num(hw, rem_vsi_handle);
1459 tmp_fltr_info.vsi_handle = rem_vsi_handle;
1460 status = ice_update_pkt_fwd_rule(hw, &tmp_fltr_info);
1462 ice_debug(hw, ICE_DBG_SW,
1463 "Failed to update pkt fwd rule to FWD_TO_VSI on HW VSI %d, error %d\n",
1464 tmp_fltr_info.fwd_id.hw_vsi_id, status);
1468 fm_list->fltr_info = tmp_fltr_info;
1471 if ((fm_list->vsi_count == 1 && lkup_type != ICE_SW_LKUP_VLAN) ||
1472 (fm_list->vsi_count == 0 && lkup_type == ICE_SW_LKUP_VLAN)) {
1473 struct ice_vsi_list_map_info *vsi_list_info =
1474 fm_list->vsi_list_info;
1476 /* Remove the VSI list since it is no longer used */
1477 status = ice_remove_vsi_list_rule(hw, vsi_list_id, lkup_type);
1479 ice_debug(hw, ICE_DBG_SW,
1480 "Failed to remove VSI list %d, error %d\n",
1481 vsi_list_id, status);
1485 list_del(&vsi_list_info->list_entry);
1486 devm_kfree(ice_hw_to_dev(hw), vsi_list_info);
1487 fm_list->vsi_list_info = NULL;
1494 * ice_remove_rule_internal - Remove a filter rule of a given type
1495 * @hw: pointer to the hardware structure
1496 * @recp_id: recipe id for which the rule needs to removed
1497 * @f_entry: rule entry containing filter information
1499 static enum ice_status
1500 ice_remove_rule_internal(struct ice_hw *hw, u8 recp_id,
1501 struct ice_fltr_list_entry *f_entry)
1503 struct ice_switch_info *sw = hw->switch_info;
1504 struct ice_fltr_mgmt_list_entry *list_elem;
1505 struct mutex *rule_lock; /* Lock to protect filter rule list */
1506 enum ice_status status = 0;
1507 bool remove_rule = false;
1510 if (!ice_is_vsi_valid(hw, f_entry->fltr_info.vsi_handle))
1511 return ICE_ERR_PARAM;
1512 f_entry->fltr_info.fwd_id.hw_vsi_id =
1513 ice_get_hw_vsi_num(hw, f_entry->fltr_info.vsi_handle);
1515 rule_lock = &sw->recp_list[recp_id].filt_rule_lock;
1516 mutex_lock(rule_lock);
1517 list_elem = ice_find_rule_entry(hw, recp_id, &f_entry->fltr_info);
1519 status = ICE_ERR_DOES_NOT_EXIST;
1523 if (list_elem->fltr_info.fltr_act != ICE_FWD_TO_VSI_LIST) {
1525 } else if (!list_elem->vsi_list_info) {
1526 status = ICE_ERR_DOES_NOT_EXIST;
1529 if (list_elem->vsi_list_info->ref_cnt > 1)
1530 list_elem->vsi_list_info->ref_cnt--;
1531 vsi_handle = f_entry->fltr_info.vsi_handle;
1532 status = ice_rem_update_vsi_list(hw, vsi_handle, list_elem);
1535 /* if vsi count goes to zero after updating the vsi list */
1536 if (list_elem->vsi_count == 0)
1541 /* Remove the lookup rule */
1542 struct ice_aqc_sw_rules_elem *s_rule;
1544 s_rule = devm_kzalloc(ice_hw_to_dev(hw),
1545 ICE_SW_RULE_RX_TX_NO_HDR_SIZE,
1548 status = ICE_ERR_NO_MEMORY;
1552 ice_fill_sw_rule(hw, &list_elem->fltr_info, s_rule,
1553 ice_aqc_opc_remove_sw_rules);
1555 status = ice_aq_sw_rules(hw, s_rule,
1556 ICE_SW_RULE_RX_TX_NO_HDR_SIZE, 1,
1557 ice_aqc_opc_remove_sw_rules, NULL);
1561 /* Remove a book keeping from the list */
1562 devm_kfree(ice_hw_to_dev(hw), s_rule);
1564 list_del(&list_elem->list_entry);
1565 devm_kfree(ice_hw_to_dev(hw), list_elem);
1568 mutex_unlock(rule_lock);
1573 * ice_add_mac - Add a MAC address based filter rule
1574 * @hw: pointer to the hardware structure
1575 * @m_list: list of MAC addresses and forwarding information
1577 * IMPORTANT: When the ucast_shared flag is set to false and m_list has
1578 * multiple unicast addresses, the function assumes that all the
1579 * addresses are unique in a given add_mac call. It doesn't
1580 * check for duplicates in this case, removing duplicates from a given
1581 * list should be taken care of in the caller of this function.
1584 ice_add_mac(struct ice_hw *hw, struct list_head *m_list)
1586 struct ice_aqc_sw_rules_elem *s_rule, *r_iter;
1587 struct ice_fltr_list_entry *m_list_itr;
1588 struct list_head *rule_head;
1589 u16 elem_sent, total_elem_left;
1590 struct ice_switch_info *sw;
1591 struct mutex *rule_lock; /* Lock to protect filter rule list */
1592 enum ice_status status = 0;
1593 u16 num_unicast = 0;
1597 return ICE_ERR_PARAM;
1600 sw = hw->switch_info;
1601 rule_lock = &sw->recp_list[ICE_SW_LKUP_MAC].filt_rule_lock;
1602 list_for_each_entry(m_list_itr, m_list, list_entry) {
1603 u8 *add = &m_list_itr->fltr_info.l_data.mac.mac_addr[0];
1607 m_list_itr->fltr_info.flag = ICE_FLTR_TX;
1608 vsi_handle = m_list_itr->fltr_info.vsi_handle;
1609 if (!ice_is_vsi_valid(hw, vsi_handle))
1610 return ICE_ERR_PARAM;
1611 hw_vsi_id = ice_get_hw_vsi_num(hw, vsi_handle);
1612 m_list_itr->fltr_info.fwd_id.hw_vsi_id = hw_vsi_id;
1613 /* update the src in case it is vsi num */
1614 if (m_list_itr->fltr_info.src_id != ICE_SRC_ID_VSI)
1615 return ICE_ERR_PARAM;
1616 m_list_itr->fltr_info.src = hw_vsi_id;
1617 if (m_list_itr->fltr_info.lkup_type != ICE_SW_LKUP_MAC ||
1618 is_zero_ether_addr(add))
1619 return ICE_ERR_PARAM;
1620 if (is_unicast_ether_addr(add) && !hw->ucast_shared) {
1621 /* Don't overwrite the unicast address */
1622 mutex_lock(rule_lock);
1623 if (ice_find_rule_entry(hw, ICE_SW_LKUP_MAC,
1624 &m_list_itr->fltr_info)) {
1625 mutex_unlock(rule_lock);
1626 return ICE_ERR_ALREADY_EXISTS;
1628 mutex_unlock(rule_lock);
1630 } else if (is_multicast_ether_addr(add) ||
1631 (is_unicast_ether_addr(add) && hw->ucast_shared)) {
1632 m_list_itr->status =
1633 ice_add_rule_internal(hw, ICE_SW_LKUP_MAC,
1635 if (m_list_itr->status)
1636 return m_list_itr->status;
1640 mutex_lock(rule_lock);
1641 /* Exit if no suitable entries were found for adding bulk switch rule */
1644 goto ice_add_mac_exit;
1647 rule_head = &sw->recp_list[ICE_SW_LKUP_MAC].filt_rules;
1649 /* Allocate switch rule buffer for the bulk update for unicast */
1650 s_rule_size = ICE_SW_RULE_RX_TX_ETH_HDR_SIZE;
1651 s_rule = devm_kcalloc(ice_hw_to_dev(hw), num_unicast, s_rule_size,
1654 status = ICE_ERR_NO_MEMORY;
1655 goto ice_add_mac_exit;
1659 list_for_each_entry(m_list_itr, m_list, list_entry) {
1660 struct ice_fltr_info *f_info = &m_list_itr->fltr_info;
1661 u8 *mac_addr = &f_info->l_data.mac.mac_addr[0];
1663 if (is_unicast_ether_addr(mac_addr)) {
1664 ice_fill_sw_rule(hw, &m_list_itr->fltr_info, r_iter,
1665 ice_aqc_opc_add_sw_rules);
1666 r_iter = (struct ice_aqc_sw_rules_elem *)
1667 ((u8 *)r_iter + s_rule_size);
1671 /* Call AQ bulk switch rule update for all unicast addresses */
1673 /* Call AQ switch rule in AQ_MAX chunk */
1674 for (total_elem_left = num_unicast; total_elem_left > 0;
1675 total_elem_left -= elem_sent) {
1676 struct ice_aqc_sw_rules_elem *entry = r_iter;
1678 elem_sent = min(total_elem_left,
1679 (u16)(ICE_AQ_MAX_BUF_LEN / s_rule_size));
1680 status = ice_aq_sw_rules(hw, entry, elem_sent * s_rule_size,
1681 elem_sent, ice_aqc_opc_add_sw_rules,
1684 goto ice_add_mac_exit;
1685 r_iter = (struct ice_aqc_sw_rules_elem *)
1686 ((u8 *)r_iter + (elem_sent * s_rule_size));
1689 /* Fill up rule id based on the value returned from FW */
1691 list_for_each_entry(m_list_itr, m_list, list_entry) {
1692 struct ice_fltr_info *f_info = &m_list_itr->fltr_info;
1693 u8 *mac_addr = &f_info->l_data.mac.mac_addr[0];
1694 struct ice_fltr_mgmt_list_entry *fm_entry;
1696 if (is_unicast_ether_addr(mac_addr)) {
1697 f_info->fltr_rule_id =
1698 le16_to_cpu(r_iter->pdata.lkup_tx_rx.index);
1699 f_info->fltr_act = ICE_FWD_TO_VSI;
1700 /* Create an entry to track this MAC address */
1701 fm_entry = devm_kzalloc(ice_hw_to_dev(hw),
1702 sizeof(*fm_entry), GFP_KERNEL);
1704 status = ICE_ERR_NO_MEMORY;
1705 goto ice_add_mac_exit;
1707 fm_entry->fltr_info = *f_info;
1708 fm_entry->vsi_count = 1;
1709 /* The book keeping entries will get removed when
1710 * base driver calls remove filter AQ command
1713 list_add(&fm_entry->list_entry, rule_head);
1714 r_iter = (struct ice_aqc_sw_rules_elem *)
1715 ((u8 *)r_iter + s_rule_size);
1720 mutex_unlock(rule_lock);
1722 devm_kfree(ice_hw_to_dev(hw), s_rule);
1727 * ice_add_vlan_internal - Add one VLAN based filter rule
1728 * @hw: pointer to the hardware structure
1729 * @f_entry: filter entry containing one VLAN information
1731 static enum ice_status
1732 ice_add_vlan_internal(struct ice_hw *hw, struct ice_fltr_list_entry *f_entry)
1734 struct ice_switch_info *sw = hw->switch_info;
1735 struct ice_fltr_mgmt_list_entry *v_list_itr;
1736 struct ice_fltr_info *new_fltr, *cur_fltr;
1737 enum ice_sw_lkup_type lkup_type;
1738 u16 vsi_list_id = 0, vsi_handle;
1739 struct mutex *rule_lock; /* Lock to protect filter rule list */
1740 enum ice_status status = 0;
1742 if (!ice_is_vsi_valid(hw, f_entry->fltr_info.vsi_handle))
1743 return ICE_ERR_PARAM;
1745 f_entry->fltr_info.fwd_id.hw_vsi_id =
1746 ice_get_hw_vsi_num(hw, f_entry->fltr_info.vsi_handle);
1747 new_fltr = &f_entry->fltr_info;
1749 /* VLAN id should only be 12 bits */
1750 if (new_fltr->l_data.vlan.vlan_id > ICE_MAX_VLAN_ID)
1751 return ICE_ERR_PARAM;
1753 if (new_fltr->src_id != ICE_SRC_ID_VSI)
1754 return ICE_ERR_PARAM;
1756 new_fltr->src = new_fltr->fwd_id.hw_vsi_id;
1757 lkup_type = new_fltr->lkup_type;
1758 vsi_handle = new_fltr->vsi_handle;
1759 rule_lock = &sw->recp_list[ICE_SW_LKUP_VLAN].filt_rule_lock;
1760 mutex_lock(rule_lock);
1761 v_list_itr = ice_find_rule_entry(hw, ICE_SW_LKUP_VLAN, new_fltr);
1763 struct ice_vsi_list_map_info *map_info = NULL;
1765 if (new_fltr->fltr_act == ICE_FWD_TO_VSI) {
1766 /* All VLAN pruning rules use a VSI list. Check if
1767 * there is already a VSI list containing VSI that we
1768 * want to add. If found, use the same vsi_list_id for
1769 * this new VLAN rule or else create a new list.
1771 map_info = ice_find_vsi_list_entry(hw, ICE_SW_LKUP_VLAN,
1775 status = ice_create_vsi_list_rule(hw,
1783 /* Convert the action to forwarding to a VSI list. */
1784 new_fltr->fltr_act = ICE_FWD_TO_VSI_LIST;
1785 new_fltr->fwd_id.vsi_list_id = vsi_list_id;
1788 status = ice_create_pkt_fwd_rule(hw, f_entry);
1790 v_list_itr = ice_find_rule_entry(hw, ICE_SW_LKUP_VLAN,
1793 status = ICE_ERR_DOES_NOT_EXIST;
1796 /* reuse VSI list for new rule and increment ref_cnt */
1798 v_list_itr->vsi_list_info = map_info;
1799 map_info->ref_cnt++;
1801 v_list_itr->vsi_list_info =
1802 ice_create_vsi_list_map(hw, &vsi_handle,
1806 } else if (v_list_itr->vsi_list_info->ref_cnt == 1) {
1807 /* Update existing VSI list to add new VSI id only if it used
1810 cur_fltr = &v_list_itr->fltr_info;
1811 status = ice_add_update_vsi_list(hw, v_list_itr, cur_fltr,
1814 /* If VLAN rule exists and VSI list being used by this rule is
1815 * referenced by more than 1 VLAN rule. Then create a new VSI
1816 * list appending previous VSI with new VSI and update existing
1817 * VLAN rule to point to new VSI list id
1819 struct ice_fltr_info tmp_fltr;
1820 u16 vsi_handle_arr[2];
1823 /* Current implementation only supports reusing VSI list with
1824 * one VSI count. We should never hit below condition
1826 if (v_list_itr->vsi_count > 1 &&
1827 v_list_itr->vsi_list_info->ref_cnt > 1) {
1828 ice_debug(hw, ICE_DBG_SW,
1829 "Invalid configuration: Optimization to reuse VSI list with more than one VSI is not being done yet\n");
1830 status = ICE_ERR_CFG;
1835 find_first_bit(v_list_itr->vsi_list_info->vsi_map,
1838 /* A rule already exists with the new VSI being added */
1839 if (cur_handle == vsi_handle) {
1840 status = ICE_ERR_ALREADY_EXISTS;
1844 vsi_handle_arr[0] = cur_handle;
1845 vsi_handle_arr[1] = vsi_handle;
1846 status = ice_create_vsi_list_rule(hw, &vsi_handle_arr[0], 2,
1847 &vsi_list_id, lkup_type);
1851 tmp_fltr = v_list_itr->fltr_info;
1852 tmp_fltr.fltr_rule_id = v_list_itr->fltr_info.fltr_rule_id;
1853 tmp_fltr.fwd_id.vsi_list_id = vsi_list_id;
1854 tmp_fltr.fltr_act = ICE_FWD_TO_VSI_LIST;
1855 /* Update the previous switch rule to a new VSI list which
1856 * includes current VSI thats requested
1858 status = ice_update_pkt_fwd_rule(hw, &tmp_fltr);
1862 /* before overriding VSI list map info. decrement ref_cnt of
1865 v_list_itr->vsi_list_info->ref_cnt--;
1867 /* now update to newly created list */
1868 v_list_itr->fltr_info.fwd_id.vsi_list_id = vsi_list_id;
1869 v_list_itr->vsi_list_info =
1870 ice_create_vsi_list_map(hw, &vsi_handle_arr[0], 2,
1872 v_list_itr->vsi_count++;
1876 mutex_unlock(rule_lock);
1881 * ice_add_vlan - Add VLAN based filter rule
1882 * @hw: pointer to the hardware structure
1883 * @v_list: list of VLAN entries and forwarding information
1886 ice_add_vlan(struct ice_hw *hw, struct list_head *v_list)
1888 struct ice_fltr_list_entry *v_list_itr;
1891 return ICE_ERR_PARAM;
1893 list_for_each_entry(v_list_itr, v_list, list_entry) {
1894 if (v_list_itr->fltr_info.lkup_type != ICE_SW_LKUP_VLAN)
1895 return ICE_ERR_PARAM;
1896 v_list_itr->fltr_info.flag = ICE_FLTR_TX;
1897 v_list_itr->status = ice_add_vlan_internal(hw, v_list_itr);
1898 if (v_list_itr->status)
1899 return v_list_itr->status;
1905 * ice_rem_sw_rule_info
1906 * @hw: pointer to the hardware structure
1907 * @rule_head: pointer to the switch list structure that we want to delete
1910 ice_rem_sw_rule_info(struct ice_hw *hw, struct list_head *rule_head)
1912 if (!list_empty(rule_head)) {
1913 struct ice_fltr_mgmt_list_entry *entry;
1914 struct ice_fltr_mgmt_list_entry *tmp;
1916 list_for_each_entry_safe(entry, tmp, rule_head, list_entry) {
1917 list_del(&entry->list_entry);
1918 devm_kfree(ice_hw_to_dev(hw), entry);
1924 * ice_cfg_dflt_vsi - change state of VSI to set/clear default
1925 * @hw: pointer to the hardware structure
1926 * @vsi_handle: VSI handle to set as default
1927 * @set: true to add the above mentioned switch rule, false to remove it
1928 * @direction: ICE_FLTR_RX or ICE_FLTR_TX
1930 * add filter rule to set/unset given VSI as default VSI for the switch
1931 * (represented by swid)
1934 ice_cfg_dflt_vsi(struct ice_hw *hw, u16 vsi_handle, bool set, u8 direction)
1936 struct ice_aqc_sw_rules_elem *s_rule;
1937 struct ice_fltr_info f_info;
1938 enum ice_adminq_opc opcode;
1939 enum ice_status status;
1943 if (!ice_is_vsi_valid(hw, vsi_handle))
1944 return ICE_ERR_PARAM;
1945 hw_vsi_id = ice_get_hw_vsi_num(hw, vsi_handle);
1947 s_rule_size = set ? ICE_SW_RULE_RX_TX_ETH_HDR_SIZE :
1948 ICE_SW_RULE_RX_TX_NO_HDR_SIZE;
1949 s_rule = devm_kzalloc(ice_hw_to_dev(hw), s_rule_size, GFP_KERNEL);
1951 return ICE_ERR_NO_MEMORY;
1953 memset(&f_info, 0, sizeof(f_info));
1955 f_info.lkup_type = ICE_SW_LKUP_DFLT;
1956 f_info.flag = direction;
1957 f_info.fltr_act = ICE_FWD_TO_VSI;
1958 f_info.fwd_id.hw_vsi_id = hw_vsi_id;
1960 if (f_info.flag & ICE_FLTR_RX) {
1961 f_info.src = hw->port_info->lport;
1962 f_info.src_id = ICE_SRC_ID_LPORT;
1964 f_info.fltr_rule_id =
1965 hw->port_info->dflt_rx_vsi_rule_id;
1966 } else if (f_info.flag & ICE_FLTR_TX) {
1967 f_info.src_id = ICE_SRC_ID_VSI;
1968 f_info.src = hw_vsi_id;
1970 f_info.fltr_rule_id =
1971 hw->port_info->dflt_tx_vsi_rule_id;
1975 opcode = ice_aqc_opc_add_sw_rules;
1977 opcode = ice_aqc_opc_remove_sw_rules;
1979 ice_fill_sw_rule(hw, &f_info, s_rule, opcode);
1981 status = ice_aq_sw_rules(hw, s_rule, s_rule_size, 1, opcode, NULL);
1982 if (status || !(f_info.flag & ICE_FLTR_TX_RX))
1985 u16 index = le16_to_cpu(s_rule->pdata.lkup_tx_rx.index);
1987 if (f_info.flag & ICE_FLTR_TX) {
1988 hw->port_info->dflt_tx_vsi_num = hw_vsi_id;
1989 hw->port_info->dflt_tx_vsi_rule_id = index;
1990 } else if (f_info.flag & ICE_FLTR_RX) {
1991 hw->port_info->dflt_rx_vsi_num = hw_vsi_id;
1992 hw->port_info->dflt_rx_vsi_rule_id = index;
1995 if (f_info.flag & ICE_FLTR_TX) {
1996 hw->port_info->dflt_tx_vsi_num = ICE_DFLT_VSI_INVAL;
1997 hw->port_info->dflt_tx_vsi_rule_id = ICE_INVAL_ACT;
1998 } else if (f_info.flag & ICE_FLTR_RX) {
1999 hw->port_info->dflt_rx_vsi_num = ICE_DFLT_VSI_INVAL;
2000 hw->port_info->dflt_rx_vsi_rule_id = ICE_INVAL_ACT;
2005 devm_kfree(ice_hw_to_dev(hw), s_rule);
2010 * ice_remove_mac - remove a MAC address based filter rule
2011 * @hw: pointer to the hardware structure
2012 * @m_list: list of MAC addresses and forwarding information
2014 * This function removes either a MAC filter rule or a specific VSI from a
2015 * VSI list for a multicast MAC address.
2017 * Returns ICE_ERR_DOES_NOT_EXIST if a given entry was not added by
2018 * ice_add_mac. Caller should be aware that this call will only work if all
2019 * the entries passed into m_list were added previously. It will not attempt to
2020 * do a partial remove of entries that were found.
2023 ice_remove_mac(struct ice_hw *hw, struct list_head *m_list)
2025 struct ice_fltr_list_entry *list_itr, *tmp;
2028 return ICE_ERR_PARAM;
2030 list_for_each_entry_safe(list_itr, tmp, m_list, list_entry) {
2031 enum ice_sw_lkup_type l_type = list_itr->fltr_info.lkup_type;
2033 if (l_type != ICE_SW_LKUP_MAC)
2034 return ICE_ERR_PARAM;
2035 list_itr->status = ice_remove_rule_internal(hw,
2038 if (list_itr->status)
2039 return list_itr->status;
2045 * ice_remove_vlan - Remove VLAN based filter rule
2046 * @hw: pointer to the hardware structure
2047 * @v_list: list of VLAN entries and forwarding information
2050 ice_remove_vlan(struct ice_hw *hw, struct list_head *v_list)
2052 struct ice_fltr_list_entry *v_list_itr, *tmp;
2055 return ICE_ERR_PARAM;
2057 list_for_each_entry_safe(v_list_itr, tmp, v_list, list_entry) {
2058 enum ice_sw_lkup_type l_type = v_list_itr->fltr_info.lkup_type;
2060 if (l_type != ICE_SW_LKUP_VLAN)
2061 return ICE_ERR_PARAM;
2062 v_list_itr->status = ice_remove_rule_internal(hw,
2065 if (v_list_itr->status)
2066 return v_list_itr->status;
2072 * ice_vsi_uses_fltr - Determine if given VSI uses specified filter
2073 * @fm_entry: filter entry to inspect
2074 * @vsi_handle: VSI handle to compare with filter info
2077 ice_vsi_uses_fltr(struct ice_fltr_mgmt_list_entry *fm_entry, u16 vsi_handle)
2079 return ((fm_entry->fltr_info.fltr_act == ICE_FWD_TO_VSI &&
2080 fm_entry->fltr_info.vsi_handle == vsi_handle) ||
2081 (fm_entry->fltr_info.fltr_act == ICE_FWD_TO_VSI_LIST &&
2082 (test_bit(vsi_handle, fm_entry->vsi_list_info->vsi_map))));
2086 * ice_add_entry_to_vsi_fltr_list - Add copy of fltr_list_entry to remove list
2087 * @hw: pointer to the hardware structure
2088 * @vsi_handle: VSI handle to remove filters from
2089 * @vsi_list_head: pointer to the list to add entry to
2090 * @fi: pointer to fltr_info of filter entry to copy & add
2092 * Helper function, used when creating a list of filters to remove from
2093 * a specific VSI. The entry added to vsi_list_head is a COPY of the
2094 * original filter entry, with the exception of fltr_info.fltr_act and
2095 * fltr_info.fwd_id fields. These are set such that later logic can
2096 * extract which VSI to remove the fltr from, and pass on that information.
2098 static enum ice_status
2099 ice_add_entry_to_vsi_fltr_list(struct ice_hw *hw, u16 vsi_handle,
2100 struct list_head *vsi_list_head,
2101 struct ice_fltr_info *fi)
2103 struct ice_fltr_list_entry *tmp;
2105 /* this memory is freed up in the caller function
2106 * once filters for this VSI are removed
2108 tmp = devm_kzalloc(ice_hw_to_dev(hw), sizeof(*tmp), GFP_KERNEL);
2110 return ICE_ERR_NO_MEMORY;
2112 tmp->fltr_info = *fi;
2114 /* Overwrite these fields to indicate which VSI to remove filter from,
2115 * so find and remove logic can extract the information from the
2116 * list entries. Note that original entries will still have proper
2119 tmp->fltr_info.fltr_act = ICE_FWD_TO_VSI;
2120 tmp->fltr_info.vsi_handle = vsi_handle;
2121 tmp->fltr_info.fwd_id.hw_vsi_id = ice_get_hw_vsi_num(hw, vsi_handle);
2123 list_add(&tmp->list_entry, vsi_list_head);
2129 * ice_add_to_vsi_fltr_list - Add VSI filters to the list
2130 * @hw: pointer to the hardware structure
2131 * @vsi_handle: VSI handle to remove filters from
2132 * @lkup_list_head: pointer to the list that has certain lookup type filters
2133 * @vsi_list_head: pointer to the list pertaining to VSI with vsi_handle
2135 * Locates all filters in lkup_list_head that are used by the given VSI,
2136 * and adds COPIES of those entries to vsi_list_head (intended to be used
2137 * to remove the listed filters).
2138 * Note that this means all entries in vsi_list_head must be explicitly
2139 * deallocated by the caller when done with list.
2141 static enum ice_status
2142 ice_add_to_vsi_fltr_list(struct ice_hw *hw, u16 vsi_handle,
2143 struct list_head *lkup_list_head,
2144 struct list_head *vsi_list_head)
2146 struct ice_fltr_mgmt_list_entry *fm_entry;
2147 enum ice_status status = 0;
2149 /* check to make sure VSI id is valid and within boundary */
2150 if (!ice_is_vsi_valid(hw, vsi_handle))
2151 return ICE_ERR_PARAM;
2153 list_for_each_entry(fm_entry, lkup_list_head, list_entry) {
2154 struct ice_fltr_info *fi;
2156 fi = &fm_entry->fltr_info;
2157 if (!fi || !ice_vsi_uses_fltr(fm_entry, vsi_handle))
2160 status = ice_add_entry_to_vsi_fltr_list(hw, vsi_handle,
2169 * ice_remove_vsi_lkup_fltr - Remove lookup type filters for a VSI
2170 * @hw: pointer to the hardware structure
2171 * @vsi_handle: VSI handle to remove filters from
2172 * @lkup: switch rule filter lookup type
2175 ice_remove_vsi_lkup_fltr(struct ice_hw *hw, u16 vsi_handle,
2176 enum ice_sw_lkup_type lkup)
2178 struct ice_switch_info *sw = hw->switch_info;
2179 struct ice_fltr_list_entry *fm_entry;
2180 struct list_head remove_list_head;
2181 struct list_head *rule_head;
2182 struct ice_fltr_list_entry *tmp;
2183 struct mutex *rule_lock; /* Lock to protect filter rule list */
2184 enum ice_status status;
2186 INIT_LIST_HEAD(&remove_list_head);
2187 rule_lock = &sw->recp_list[lkup].filt_rule_lock;
2188 rule_head = &sw->recp_list[lkup].filt_rules;
2189 mutex_lock(rule_lock);
2190 status = ice_add_to_vsi_fltr_list(hw, vsi_handle, rule_head,
2192 mutex_unlock(rule_lock);
2197 case ICE_SW_LKUP_MAC:
2198 ice_remove_mac(hw, &remove_list_head);
2200 case ICE_SW_LKUP_VLAN:
2201 ice_remove_vlan(hw, &remove_list_head);
2203 case ICE_SW_LKUP_MAC_VLAN:
2204 case ICE_SW_LKUP_ETHERTYPE:
2205 case ICE_SW_LKUP_ETHERTYPE_MAC:
2206 case ICE_SW_LKUP_PROMISC:
2207 case ICE_SW_LKUP_DFLT:
2208 case ICE_SW_LKUP_PROMISC_VLAN:
2209 case ICE_SW_LKUP_LAST:
2211 ice_debug(hw, ICE_DBG_SW, "Unsupported lookup type %d\n", lkup);
2215 list_for_each_entry_safe(fm_entry, tmp, &remove_list_head, list_entry) {
2216 list_del(&fm_entry->list_entry);
2217 devm_kfree(ice_hw_to_dev(hw), fm_entry);
2222 * ice_remove_vsi_fltr - Remove all filters for a VSI
2223 * @hw: pointer to the hardware structure
2224 * @vsi_handle: VSI handle to remove filters from
2226 void ice_remove_vsi_fltr(struct ice_hw *hw, u16 vsi_handle)
2228 ice_remove_vsi_lkup_fltr(hw, vsi_handle, ICE_SW_LKUP_MAC);
2229 ice_remove_vsi_lkup_fltr(hw, vsi_handle, ICE_SW_LKUP_MAC_VLAN);
2230 ice_remove_vsi_lkup_fltr(hw, vsi_handle, ICE_SW_LKUP_PROMISC);
2231 ice_remove_vsi_lkup_fltr(hw, vsi_handle, ICE_SW_LKUP_VLAN);
2232 ice_remove_vsi_lkup_fltr(hw, vsi_handle, ICE_SW_LKUP_DFLT);
2233 ice_remove_vsi_lkup_fltr(hw, vsi_handle, ICE_SW_LKUP_ETHERTYPE);
2234 ice_remove_vsi_lkup_fltr(hw, vsi_handle, ICE_SW_LKUP_ETHERTYPE_MAC);
2235 ice_remove_vsi_lkup_fltr(hw, vsi_handle, ICE_SW_LKUP_PROMISC_VLAN);
2239 * ice_replay_vsi_fltr - Replay filters for requested VSI
2240 * @hw: pointer to the hardware structure
2241 * @vsi_handle: driver VSI handle
2242 * @recp_id: Recipe id for which rules need to be replayed
2243 * @list_head: list for which filters need to be replayed
2245 * Replays the filter of recipe recp_id for a VSI represented via vsi_handle.
2246 * It is required to pass valid VSI handle.
2248 static enum ice_status
2249 ice_replay_vsi_fltr(struct ice_hw *hw, u16 vsi_handle, u8 recp_id,
2250 struct list_head *list_head)
2252 struct ice_fltr_mgmt_list_entry *itr;
2253 enum ice_status status = 0;
2256 if (list_empty(list_head))
2258 hw_vsi_id = ice_get_hw_vsi_num(hw, vsi_handle);
2260 list_for_each_entry(itr, list_head, list_entry) {
2261 struct ice_fltr_list_entry f_entry;
2263 f_entry.fltr_info = itr->fltr_info;
2264 if (itr->vsi_count < 2 && recp_id != ICE_SW_LKUP_VLAN &&
2265 itr->fltr_info.vsi_handle == vsi_handle) {
2266 /* update the src in case it is vsi num */
2267 if (f_entry.fltr_info.src_id == ICE_SRC_ID_VSI)
2268 f_entry.fltr_info.src = hw_vsi_id;
2269 status = ice_add_rule_internal(hw, recp_id, &f_entry);
2274 if (!itr->vsi_list_info ||
2275 !test_bit(vsi_handle, itr->vsi_list_info->vsi_map))
2277 /* Clearing it so that the logic can add it back */
2278 clear_bit(vsi_handle, itr->vsi_list_info->vsi_map);
2279 f_entry.fltr_info.vsi_handle = vsi_handle;
2280 f_entry.fltr_info.fltr_act = ICE_FWD_TO_VSI;
2281 /* update the src in case it is vsi num */
2282 if (f_entry.fltr_info.src_id == ICE_SRC_ID_VSI)
2283 f_entry.fltr_info.src = hw_vsi_id;
2284 if (recp_id == ICE_SW_LKUP_VLAN)
2285 status = ice_add_vlan_internal(hw, &f_entry);
2287 status = ice_add_rule_internal(hw, recp_id, &f_entry);
2296 * ice_replay_vsi_all_fltr - replay all filters stored in bookkeeping lists
2297 * @hw: pointer to the hardware structure
2298 * @vsi_handle: driver VSI handle
2300 * Replays filters for requested VSI via vsi_handle.
2302 enum ice_status ice_replay_vsi_all_fltr(struct ice_hw *hw, u16 vsi_handle)
2304 struct ice_switch_info *sw = hw->switch_info;
2305 enum ice_status status = 0;
2308 for (i = 0; i < ICE_SW_LKUP_LAST; i++) {
2309 struct list_head *head;
2311 head = &sw->recp_list[i].filt_replay_rules;
2312 status = ice_replay_vsi_fltr(hw, vsi_handle, i, head);
2320 * ice_rm_all_sw_replay_rule_info - deletes filter replay rules
2321 * @hw: pointer to the hw struct
2323 * Deletes the filter replay rules.
2325 void ice_rm_all_sw_replay_rule_info(struct ice_hw *hw)
2327 struct ice_switch_info *sw = hw->switch_info;
2333 for (i = 0; i < ICE_SW_LKUP_LAST; i++) {
2334 if (!list_empty(&sw->recp_list[i].filt_replay_rules)) {
2335 struct list_head *l_head;
2337 l_head = &sw->recp_list[i].filt_replay_rules;
2338 ice_rem_sw_rule_info(hw, l_head);