aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAnirudh Venkataramanan <anirudh.venkataramanan@intel.com>2018-03-20 10:58:12 -0400
committerJeff Kirsher <jeffrey.t.kirsher@intel.com>2018-03-26 14:00:08 -0400
commit9daf8208dd4dee4e13079bd0520a5fb8d20e8b06 (patch)
treea7560349d58b64af409dbc5d8d335d9ae0b8b2a5
parent3a858ba392c3b19986c40a4c170ddc37b144115f (diff)
ice: Add support for switch filter programming
A VSI needs traffic directed towards it. This is done by programming filter rules on the switch (embedded vSwitch) element in the hardware, which connects the VSI to the ingress/egress port. This patch introduces data structures and functions necessary to add remove or update switch rules on the switch element. This is a pretty low level function that is generic enough to add a whole range of filters. This patch also introduces two top level functions ice_add_mac and ice_remove mac which through a series of intermediate helper functions eventually call ice_aq_sw_rules to add/delete simple MAC based filters. It's worth noting that one invocation of ice_add_mac/ice_remove_mac is capable of adding/deleting multiple MAC filters. Also worth noting is the fact that the driver maintains a list of currently active filters, so every filter addition/removal causes an update to this list. This is done for a couple of reasons: 1) If two VSIs try to add the same filters, we need to detect it and do things a little differently (i.e. use VSI lists, described below) as the same filter can't be added more than once. 2) In the event of a hardware reset we can simply walk through this list and restore the filters. VSI Lists: In a multi-VSI situation, it's possible that multiple VSIs want to add the same filter rule. For example, two VSIs that want to receive broadcast traffic would both add a filter for destination MAC ff:ff:ff:ff:ff:ff. This can become cumbersome to maintain and so this is handled using a VSI list. A VSI list is resource that can be allocated in the hardware using the ice_aq_alloc_free_res admin queue command. Simply put, a VSI list can be thought of as a subscription list containing a set of VSIs to which the packet should be forwarded, should the filter match. For example, if VSI-0 has already added a broadcast filter, and VSI-1 wants to do the same thing, the filter creation flow will detect this, allocate a VSI list and update the switch rule so that broadcast traffic will now be forwarded to the VSI list which contains VSI-0 and VSI-1. Signed-off-by: Anirudh Venkataramanan <anirudh.venkataramanan@intel.com> Tested-by: Tony Brelinski <tonyx.brelinski@intel.com> Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
-rw-r--r--drivers/net/ethernet/intel/ice/ice_adminq_cmd.h249
-rw-r--r--drivers/net/ethernet/intel/ice/ice_common.c74
-rw-r--r--drivers/net/ethernet/intel/ice/ice_main.c92
-rw-r--r--drivers/net/ethernet/intel/ice/ice_status.h3
-rw-r--r--drivers/net/ethernet/intel/ice/ice_switch.c1378
-rw-r--r--drivers/net/ethernet/intel/ice/ice_switch.h120
-rw-r--r--drivers/net/ethernet/intel/ice/ice_type.h21
7 files changed, 1935 insertions, 2 deletions
diff --git a/drivers/net/ethernet/intel/ice/ice_adminq_cmd.h b/drivers/net/ethernet/intel/ice/ice_adminq_cmd.h
index 682e8dac72cc..9237841439da 100644
--- a/drivers/net/ethernet/intel/ice/ice_adminq_cmd.h
+++ b/drivers/net/ethernet/intel/ice/ice_adminq_cmd.h
@@ -8,6 +8,7 @@
8 * descriptor format. It is shared between Firmware and Software. 8 * descriptor format. It is shared between Firmware and Software.
9 */ 9 */
10 10
11#define ICE_MAX_VSI 768
11#define ICE_AQC_TOPO_MAX_LEVEL_NUM 0x9 12#define ICE_AQC_TOPO_MAX_LEVEL_NUM 0x9
12#define ICE_AQ_SET_MAC_FRAME_SIZE_MAX 9728 13#define ICE_AQ_SET_MAC_FRAME_SIZE_MAX 9728
13 14
@@ -191,6 +192,46 @@ struct ice_aqc_get_sw_cfg_resp {
191 struct ice_aqc_get_sw_cfg_resp_elem elements[1]; 192 struct ice_aqc_get_sw_cfg_resp_elem elements[1];
192}; 193};
193 194
195/* These resource type defines are used for all switch resource
196 * commands where a resource type is required, such as:
197 * Get Resource Allocation command (indirect 0x0204)
198 * Allocate Resources command (indirect 0x0208)
199 * Free Resources command (indirect 0x0209)
200 * Get Allocated Resource Descriptors Command (indirect 0x020A)
201 */
202#define ICE_AQC_RES_TYPE_VSI_LIST_REP 0x03
203#define ICE_AQC_RES_TYPE_VSI_LIST_PRUNE 0x04
204
205/* Allocate Resources command (indirect 0x0208)
206 * Free Resources command (indirect 0x0209)
207 */
208struct ice_aqc_alloc_free_res_cmd {
209 __le16 num_entries; /* Number of Resource entries */
210 u8 reserved[6];
211 __le32 addr_high;
212 __le32 addr_low;
213};
214
215/* Resource descriptor */
216struct ice_aqc_res_elem {
217 union {
218 __le16 sw_resp;
219 __le16 flu_resp;
220 } e;
221};
222
223/* Buffer for Allocate/Free Resources commands */
224struct ice_aqc_alloc_free_res_elem {
225 __le16 res_type; /* Types defined above cmd 0x0204 */
226#define ICE_AQC_RES_TYPE_SHARED_S 7
227#define ICE_AQC_RES_TYPE_SHARED_M (0x1 << ICE_AQC_RES_TYPE_SHARED_S)
228#define ICE_AQC_RES_TYPE_VSI_PRUNE_LIST_S 8
229#define ICE_AQC_RES_TYPE_VSI_PRUNE_LIST_M \
230 (0xF << ICE_AQC_RES_TYPE_VSI_PRUNE_LIST_S)
231 __le16 num_elems;
232 struct ice_aqc_res_elem elem[1];
233};
234
194/* Add VSI (indirect 0x0210) 235/* Add VSI (indirect 0x0210)
195 * Update VSI (indirect 0x0211) 236 * Update VSI (indirect 0x0211)
196 * Get VSI (indirect 0x0212) 237 * Get VSI (indirect 0x0212)
@@ -384,6 +425,202 @@ struct ice_aqc_vsi_props {
384 u8 reserved[24]; 425 u8 reserved[24];
385}; 426};
386 427
428/* Add/Update/Remove/Get switch rules (indirect 0x02A0, 0x02A1, 0x02A2, 0x02A3)
429 */
430struct ice_aqc_sw_rules {
431 /* ops: add switch rules, referring the number of rules.
432 * ops: update switch rules, referring the number of filters
433 * ops: remove switch rules, referring the entry index.
434 * ops: get switch rules, referring to the number of filters.
435 */
436 __le16 num_rules_fltr_entry_index;
437 u8 reserved[6];
438 __le32 addr_high;
439 __le32 addr_low;
440};
441
442/* Add/Update/Get/Remove lookup Rx/Tx command/response entry
443 * This structures describes the lookup rules and associated actions. "index"
444 * is returned as part of a response to a successful Add command, and can be
445 * used to identify the rule for Update/Get/Remove commands.
446 */
447struct ice_sw_rule_lkup_rx_tx {
448 __le16 recipe_id;
449#define ICE_SW_RECIPE_LOGICAL_PORT_FWD 10
450 /* Source port for LOOKUP_RX and source VSI in case of LOOKUP_TX */
451 __le16 src;
452 __le32 act;
453
454 /* Bit 0:1 - Action type */
455#define ICE_SINGLE_ACT_TYPE_S 0x00
456#define ICE_SINGLE_ACT_TYPE_M (0x3 << ICE_SINGLE_ACT_TYPE_S)
457
458 /* Bit 2 - Loop back enable
459 * Bit 3 - LAN enable
460 */
461#define ICE_SINGLE_ACT_LB_ENABLE BIT(2)
462#define ICE_SINGLE_ACT_LAN_ENABLE BIT(3)
463
464 /* Action type = 0 - Forward to VSI or VSI list */
465#define ICE_SINGLE_ACT_VSI_FORWARDING 0x0
466
467#define ICE_SINGLE_ACT_VSI_ID_S 4
468#define ICE_SINGLE_ACT_VSI_ID_M (0x3FF << ICE_SINGLE_ACT_VSI_ID_S)
469#define ICE_SINGLE_ACT_VSI_LIST_ID_S 4
470#define ICE_SINGLE_ACT_VSI_LIST_ID_M (0x3FF << ICE_SINGLE_ACT_VSI_LIST_ID_S)
471 /* This bit needs to be set if action is forward to VSI list */
472#define ICE_SINGLE_ACT_VSI_LIST BIT(14)
473#define ICE_SINGLE_ACT_VALID_BIT BIT(17)
474#define ICE_SINGLE_ACT_DROP BIT(18)
475
476 /* Action type = 1 - Forward to Queue of Queue group */
477#define ICE_SINGLE_ACT_TO_Q 0x1
478#define ICE_SINGLE_ACT_Q_INDEX_S 4
479#define ICE_SINGLE_ACT_Q_INDEX_M (0x7FF << ICE_SINGLE_ACT_Q_INDEX_S)
480#define ICE_SINGLE_ACT_Q_REGION_S 15
481#define ICE_SINGLE_ACT_Q_REGION_M (0x7 << ICE_SINGLE_ACT_Q_REGION_S)
482#define ICE_SINGLE_ACT_Q_PRIORITY BIT(18)
483
484 /* Action type = 2 - Prune */
485#define ICE_SINGLE_ACT_PRUNE 0x2
486#define ICE_SINGLE_ACT_EGRESS BIT(15)
487#define ICE_SINGLE_ACT_INGRESS BIT(16)
488#define ICE_SINGLE_ACT_PRUNET BIT(17)
489 /* Bit 18 should be set to 0 for this action */
490
491 /* Action type = 2 - Pointer */
492#define ICE_SINGLE_ACT_PTR 0x2
493#define ICE_SINGLE_ACT_PTR_VAL_S 4
494#define ICE_SINGLE_ACT_PTR_VAL_M (0x1FFF << ICE_SINGLE_ACT_PTR_VAL_S)
495 /* Bit 18 should be set to 1 */
496#define ICE_SINGLE_ACT_PTR_BIT BIT(18)
497
498 /* Action type = 3 - Other actions. Last two bits
499 * are other action identifier
500 */
501#define ICE_SINGLE_ACT_OTHER_ACTS 0x3
502#define ICE_SINGLE_OTHER_ACT_IDENTIFIER_S 17
503#define ICE_SINGLE_OTHER_ACT_IDENTIFIER_M \
504 (0x3 << \ ICE_SINGLE_OTHER_ACT_IDENTIFIER_S)
505
506 /* Bit 17:18 - Defines other actions */
507 /* Other action = 0 - Mirror VSI */
508#define ICE_SINGLE_OTHER_ACT_MIRROR 0
509#define ICE_SINGLE_ACT_MIRROR_VSI_ID_S 4
510#define ICE_SINGLE_ACT_MIRROR_VSI_ID_M \
511 (0x3FF << ICE_SINGLE_ACT_MIRROR_VSI_ID_S)
512
513 /* Other action = 3 - Set Stat count */
514#define ICE_SINGLE_OTHER_ACT_STAT_COUNT 3
515#define ICE_SINGLE_ACT_STAT_COUNT_INDEX_S 4
516#define ICE_SINGLE_ACT_STAT_COUNT_INDEX_M \
517 (0x7F << ICE_SINGLE_ACT_STAT_COUNT_INDEX_S)
518
519 __le16 index; /* The index of the rule in the lookup table */
520 /* Length and values of the header to be matched per recipe or
521 * lookup-type
522 */
523 __le16 hdr_len;
524 u8 hdr[1];
525} __packed;
526
527/* Add/Update/Remove large action command/response entry
528 * "index" is returned as part of a response to a successful Add command, and
529 * can be used to identify the action for Update/Get/Remove commands.
530 */
531struct ice_sw_rule_lg_act {
532 __le16 index; /* Index in large action table */
533 __le16 size;
534 __le32 act[1]; /* array of size for actions */
535 /* Max number of large actions */
536#define ICE_MAX_LG_ACT 4
537 /* Bit 0:1 - Action type */
538#define ICE_LG_ACT_TYPE_S 0
539#define ICE_LG_ACT_TYPE_M (0x7 << ICE_LG_ACT_TYPE_S)
540
541 /* Action type = 0 - Forward to VSI or VSI list */
542#define ICE_LG_ACT_VSI_FORWARDING 0
543#define ICE_LG_ACT_VSI_ID_S 3
544#define ICE_LG_ACT_VSI_ID_M (0x3FF << ICE_LG_ACT_VSI_ID_S)
545#define ICE_LG_ACT_VSI_LIST_ID_S 3
546#define ICE_LG_ACT_VSI_LIST_ID_M (0x3FF << ICE_LG_ACT_VSI_LIST_ID_S)
547 /* This bit needs to be set if action is forward to VSI list */
548#define ICE_LG_ACT_VSI_LIST BIT(13)
549
550#define ICE_LG_ACT_VALID_BIT BIT(16)
551
552 /* Action type = 1 - Forward to Queue of Queue group */
553#define ICE_LG_ACT_TO_Q 0x1
554#define ICE_LG_ACT_Q_INDEX_S 3
555#define ICE_LG_ACT_Q_INDEX_M (0x7FF << ICE_LG_ACT_Q_INDEX_S)
556#define ICE_LG_ACT_Q_REGION_S 14
557#define ICE_LG_ACT_Q_REGION_M (0x7 << ICE_LG_ACT_Q_REGION_S)
558#define ICE_LG_ACT_Q_PRIORITY_SET BIT(17)
559
560 /* Action type = 2 - Prune */
561#define ICE_LG_ACT_PRUNE 0x2
562#define ICE_LG_ACT_EGRESS BIT(14)
563#define ICE_LG_ACT_INGRESS BIT(15)
564#define ICE_LG_ACT_PRUNET BIT(16)
565
566 /* Action type = 3 - Mirror VSI */
567#define ICE_LG_OTHER_ACT_MIRROR 0x3
568#define ICE_LG_ACT_MIRROR_VSI_ID_S 3
569#define ICE_LG_ACT_MIRROR_VSI_ID_M (0x3FF << ICE_LG_ACT_MIRROR_VSI_ID_S)
570
571 /* Action type = 5 - Large Action */
572#define ICE_LG_ACT_GENERIC 0x5
573#define ICE_LG_ACT_GENERIC_VALUE_S 3
574#define ICE_LG_ACT_GENERIC_VALUE_M (0xFFFF << ICE_LG_ACT_GENERIC_VALUE_S)
575#define ICE_LG_ACT_GENERIC_OFFSET_S 19
576#define ICE_LG_ACT_GENERIC_OFFSET_M (0x7 << ICE_LG_ACT_GENERIC_OFFSET_S)
577#define ICE_LG_ACT_GENERIC_PRIORITY_S 22
578#define ICE_LG_ACT_GENERIC_PRIORITY_M (0x7 << ICE_LG_ACT_GENERIC_PRIORITY_S)
579
580 /* Action = 7 - Set Stat count */
581#define ICE_LG_ACT_STAT_COUNT 0x7
582#define ICE_LG_ACT_STAT_COUNT_S 3
583#define ICE_LG_ACT_STAT_COUNT_M (0x7F << ICE_LG_ACT_STAT_COUNT_S)
584};
585
586/* Add/Update/Remove VSI list command/response entry
587 * "index" is returned as part of a response to a successful Add command, and
588 * can be used to identify the VSI list for Update/Get/Remove commands.
589 */
590struct ice_sw_rule_vsi_list {
591 __le16 index; /* Index of VSI/Prune list */
592 __le16 number_vsi;
593 __le16 vsi[1]; /* Array of number_vsi VSI numbers */
594};
595
596/* Query VSI list command/response entry */
597struct ice_sw_rule_vsi_list_query {
598 __le16 index;
599 DECLARE_BITMAP(vsi_list, ICE_MAX_VSI);
600} __packed;
601
602/* Add switch rule response:
603 * Content of return buffer is same as the input buffer. The status field and
604 * LUT index are updated as part of the response
605 */
606struct ice_aqc_sw_rules_elem {
607 __le16 type; /* Switch rule type, one of T_... */
608#define ICE_AQC_SW_RULES_T_LKUP_RX 0x0
609#define ICE_AQC_SW_RULES_T_LKUP_TX 0x1
610#define ICE_AQC_SW_RULES_T_LG_ACT 0x2
611#define ICE_AQC_SW_RULES_T_VSI_LIST_SET 0x3
612#define ICE_AQC_SW_RULES_T_VSI_LIST_CLEAR 0x4
613#define ICE_AQC_SW_RULES_T_PRUNE_LIST_SET 0x5
614#define ICE_AQC_SW_RULES_T_PRUNE_LIST_CLEAR 0x6
615 __le16 status;
616 union {
617 struct ice_sw_rule_lkup_rx_tx lkup_tx_rx;
618 struct ice_sw_rule_lg_act lg_act;
619 struct ice_sw_rule_vsi_list vsi_list;
620 struct ice_sw_rule_vsi_list_query vsi_list_query;
621 } __packed pdata;
622};
623
387/* Get Default Topology (indirect 0x0400) */ 624/* Get Default Topology (indirect 0x0400) */
388struct ice_aqc_get_topo { 625struct ice_aqc_get_topo {
389 u8 port_num; 626 u8 port_num;
@@ -766,11 +1003,13 @@ struct ice_aq_desc {
766 struct ice_aqc_list_caps get_cap; 1003 struct ice_aqc_list_caps get_cap;
767 struct ice_aqc_get_phy_caps get_phy; 1004 struct ice_aqc_get_phy_caps get_phy;
768 struct ice_aqc_get_sw_cfg get_sw_conf; 1005 struct ice_aqc_get_sw_cfg get_sw_conf;
1006 struct ice_aqc_sw_rules sw_rules;
769 struct ice_aqc_get_topo get_topo; 1007 struct ice_aqc_get_topo get_topo;
770 struct ice_aqc_query_txsched_res query_sched_res; 1008 struct ice_aqc_query_txsched_res query_sched_res;
771 struct ice_aqc_add_move_delete_elem add_move_delete_elem; 1009 struct ice_aqc_add_move_delete_elem add_move_delete_elem;
772 struct ice_aqc_nvm nvm; 1010 struct ice_aqc_nvm nvm;
773 struct ice_aqc_add_get_update_free_vsi vsi_cmd; 1011 struct ice_aqc_add_get_update_free_vsi vsi_cmd;
1012 struct ice_aqc_alloc_free_res_cmd sw_res_ctrl;
774 struct ice_aqc_get_link_status get_link_status; 1013 struct ice_aqc_get_link_status get_link_status;
775 } params; 1014 } params;
776}; 1015};
@@ -821,10 +1060,20 @@ enum ice_adminq_opc {
821 /* internal switch commands */ 1060 /* internal switch commands */
822 ice_aqc_opc_get_sw_cfg = 0x0200, 1061 ice_aqc_opc_get_sw_cfg = 0x0200,
823 1062
1063 /* Alloc/Free/Get Resources */
1064 ice_aqc_opc_alloc_res = 0x0208,
1065 ice_aqc_opc_free_res = 0x0209,
1066
824 /* VSI commands */ 1067 /* VSI commands */
825 ice_aqc_opc_add_vsi = 0x0210, 1068 ice_aqc_opc_add_vsi = 0x0210,
826 ice_aqc_opc_update_vsi = 0x0211, 1069 ice_aqc_opc_update_vsi = 0x0211,
827 ice_aqc_opc_free_vsi = 0x0213, 1070 ice_aqc_opc_free_vsi = 0x0213,
1071
1072 /* switch rules population commands */
1073 ice_aqc_opc_add_sw_rules = 0x02A0,
1074 ice_aqc_opc_update_sw_rules = 0x02A1,
1075 ice_aqc_opc_remove_sw_rules = 0x02A2,
1076
828 ice_aqc_opc_clear_pf_cfg = 0x02A4, 1077 ice_aqc_opc_clear_pf_cfg = 0x02A4,
829 1078
830 /* transmit scheduler commands */ 1079 /* transmit scheduler commands */
diff --git a/drivers/net/ethernet/intel/ice/ice_common.c b/drivers/net/ethernet/intel/ice/ice_common.c
index a4ce8a87fb0d..67301fe75482 100644
--- a/drivers/net/ethernet/intel/ice/ice_common.c
+++ b/drivers/net/ethernet/intel/ice/ice_common.c
@@ -259,6 +259,66 @@ ice_aq_get_link_info(struct ice_port_info *pi, bool ena_lse,
259} 259}
260 260
261/** 261/**
262 * ice_init_fltr_mgmt_struct - initializes filter management list and locks
263 * @hw: pointer to the hw struct
264 */
265static enum ice_status ice_init_fltr_mgmt_struct(struct ice_hw *hw)
266{
267 struct ice_switch_info *sw;
268
269 hw->switch_info = devm_kzalloc(ice_hw_to_dev(hw),
270 sizeof(*hw->switch_info), GFP_KERNEL);
271 sw = hw->switch_info;
272
273 if (!sw)
274 return ICE_ERR_NO_MEMORY;
275
276 INIT_LIST_HEAD(&sw->vsi_list_map_head);
277
278 mutex_init(&sw->mac_list_lock);
279 INIT_LIST_HEAD(&sw->mac_list_head);
280
281 mutex_init(&sw->vlan_list_lock);
282 INIT_LIST_HEAD(&sw->vlan_list_head);
283
284 mutex_init(&sw->eth_m_list_lock);
285 INIT_LIST_HEAD(&sw->eth_m_list_head);
286
287 mutex_init(&sw->promisc_list_lock);
288 INIT_LIST_HEAD(&sw->promisc_list_head);
289
290 mutex_init(&sw->mac_vlan_list_lock);
291 INIT_LIST_HEAD(&sw->mac_vlan_list_head);
292
293 return 0;
294}
295
296/**
297 * ice_cleanup_fltr_mgmt_struct - cleanup filter management list and locks
298 * @hw: pointer to the hw struct
299 */
300static void ice_cleanup_fltr_mgmt_struct(struct ice_hw *hw)
301{
302 struct ice_switch_info *sw = hw->switch_info;
303 struct ice_vsi_list_map_info *v_pos_map;
304 struct ice_vsi_list_map_info *v_tmp_map;
305
306 list_for_each_entry_safe(v_pos_map, v_tmp_map, &sw->vsi_list_map_head,
307 list_entry) {
308 list_del(&v_pos_map->list_entry);
309 devm_kfree(ice_hw_to_dev(hw), v_pos_map);
310 }
311
312 mutex_destroy(&sw->mac_list_lock);
313 mutex_destroy(&sw->vlan_list_lock);
314 mutex_destroy(&sw->eth_m_list_lock);
315 mutex_destroy(&sw->promisc_list_lock);
316 mutex_destroy(&sw->mac_vlan_list_lock);
317
318 devm_kfree(ice_hw_to_dev(hw), sw);
319}
320
321/**
262 * ice_init_hw - main hardware initialization routine 322 * ice_init_hw - main hardware initialization routine
263 * @hw: pointer to the hardware structure 323 * @hw: pointer to the hardware structure
264 */ 324 */
@@ -321,6 +381,8 @@ enum ice_status ice_init_hw(struct ice_hw *hw)
321 if (status) 381 if (status)
322 goto err_unroll_alloc; 382 goto err_unroll_alloc;
323 383
384 hw->evb_veb = true;
385
324 /* Query the allocated resources for tx scheduler */ 386 /* Query the allocated resources for tx scheduler */
325 status = ice_sched_query_res_alloc(hw); 387 status = ice_sched_query_res_alloc(hw);
326 if (status) { 388 if (status) {
@@ -352,21 +414,27 @@ enum ice_status ice_init_hw(struct ice_hw *hw)
352 if (status) 414 if (status)
353 goto err_unroll_sched; 415 goto err_unroll_sched;
354 416
417 status = ice_init_fltr_mgmt_struct(hw);
418 if (status)
419 goto err_unroll_sched;
420
355 /* Get port MAC information */ 421 /* Get port MAC information */
356 mac_buf_len = sizeof(struct ice_aqc_manage_mac_read_resp); 422 mac_buf_len = sizeof(struct ice_aqc_manage_mac_read_resp);
357 mac_buf = devm_kzalloc(ice_hw_to_dev(hw), mac_buf_len, GFP_KERNEL); 423 mac_buf = devm_kzalloc(ice_hw_to_dev(hw), mac_buf_len, GFP_KERNEL);
358 424
359 if (!mac_buf) 425 if (!mac_buf)
360 goto err_unroll_sched; 426 goto err_unroll_fltr_mgmt_struct;
361 427
362 status = ice_aq_manage_mac_read(hw, mac_buf, mac_buf_len, NULL); 428 status = ice_aq_manage_mac_read(hw, mac_buf, mac_buf_len, NULL);
363 devm_kfree(ice_hw_to_dev(hw), mac_buf); 429 devm_kfree(ice_hw_to_dev(hw), mac_buf);
364 430
365 if (status) 431 if (status)
366 goto err_unroll_sched; 432 goto err_unroll_fltr_mgmt_struct;
367 433
368 return 0; 434 return 0;
369 435
436err_unroll_fltr_mgmt_struct:
437 ice_cleanup_fltr_mgmt_struct(hw);
370err_unroll_sched: 438err_unroll_sched:
371 ice_sched_cleanup_all(hw); 439 ice_sched_cleanup_all(hw);
372err_unroll_alloc: 440err_unroll_alloc:
@@ -389,6 +457,8 @@ void ice_deinit_hw(struct ice_hw *hw)
389 devm_kfree(ice_hw_to_dev(hw), hw->port_info); 457 devm_kfree(ice_hw_to_dev(hw), hw->port_info);
390 hw->port_info = NULL; 458 hw->port_info = NULL;
391 } 459 }
460
461 ice_cleanup_fltr_mgmt_struct(hw);
392} 462}
393 463
394/** 464/**
diff --git a/drivers/net/ethernet/intel/ice/ice_main.c b/drivers/net/ethernet/intel/ice/ice_main.c
index 04e004ba2067..3b4a2691ddac 100644
--- a/drivers/net/ethernet/intel/ice/ice_main.c
+++ b/drivers/net/ethernet/intel/ice/ice_main.c
@@ -163,6 +163,57 @@ static int ice_free_res(struct ice_res_tracker *res, u16 index, u16 id)
163} 163}
164 164
165/** 165/**
166 * ice_add_mac_to_list - Add a mac address filter entry to the list
167 * @vsi: the VSI to be forwarded to
168 * @add_list: pointer to the list which contains MAC filter entries
169 * @macaddr: the MAC address to be added.
170 *
171 * Adds mac address filter entry to the temp list
172 *
173 * Returns 0 on success or ENOMEM on failure.
174 */
175static int ice_add_mac_to_list(struct ice_vsi *vsi, struct list_head *add_list,
176 const u8 *macaddr)
177{
178 struct ice_fltr_list_entry *tmp;
179 struct ice_pf *pf = vsi->back;
180
181 tmp = devm_kzalloc(&pf->pdev->dev, sizeof(*tmp), GFP_ATOMIC);
182 if (!tmp)
183 return -ENOMEM;
184
185 tmp->fltr_info.flag = ICE_FLTR_TX;
186 tmp->fltr_info.src = vsi->vsi_num;
187 tmp->fltr_info.lkup_type = ICE_SW_LKUP_MAC;
188 tmp->fltr_info.fltr_act = ICE_FWD_TO_VSI;
189 tmp->fltr_info.fwd_id.vsi_id = vsi->vsi_num;
190 ether_addr_copy(tmp->fltr_info.l_data.mac.mac_addr, macaddr);
191
192 INIT_LIST_HEAD(&tmp->list_entry);
193 list_add(&tmp->list_entry, add_list);
194
195 return 0;
196}
197
198/**
199 * ice_free_fltr_list - free filter lists helper
200 * @dev: pointer to the device struct
201 * @h: pointer to the list head to be freed
202 *
203 * Helper function to free filter lists previously created using
204 * ice_add_mac_to_list
205 */
206static void ice_free_fltr_list(struct device *dev, struct list_head *h)
207{
208 struct ice_fltr_list_entry *e, *tmp;
209
210 list_for_each_entry_safe(e, tmp, h, list_entry) {
211 list_del(&e->list_entry);
212 devm_kfree(dev, e);
213 }
214}
215
216/**
166 * __ice_clean_ctrlq - helper function to clean controlq rings 217 * __ice_clean_ctrlq - helper function to clean controlq rings
167 * @pf: ptr to struct ice_pf 218 * @pf: ptr to struct ice_pf
168 * @q_type: specific Control queue type 219 * @q_type: specific Control queue type
@@ -1519,6 +1570,8 @@ err_get_qs:
1519 */ 1570 */
1520static int ice_setup_pf_sw(struct ice_pf *pf) 1571static int ice_setup_pf_sw(struct ice_pf *pf)
1521{ 1572{
1573 LIST_HEAD(tmp_add_list);
1574 u8 broadcast[ETH_ALEN];
1522 struct ice_vsi *vsi; 1575 struct ice_vsi *vsi;
1523 int status = 0; 1576 int status = 0;
1524 1577
@@ -1528,7 +1581,37 @@ static int ice_setup_pf_sw(struct ice_pf *pf)
1528 goto error_exit; 1581 goto error_exit;
1529 } 1582 }
1530 1583
1584 /* tmp_add_list contains a list of MAC addresses for which MAC
1585 * filters need to be programmed. Add the VSI's unicast MAC to
1586 * this list
1587 */
1588 status = ice_add_mac_to_list(vsi, &tmp_add_list,
1589 vsi->port_info->mac.perm_addr);
1590 if (status)
1591 goto error_exit;
1592
1593 /* VSI needs to receive broadcast traffic, so add the broadcast
1594 * MAC address to the list.
1595 */
1596 eth_broadcast_addr(broadcast);
1597 status = ice_add_mac_to_list(vsi, &tmp_add_list, broadcast);
1598 if (status)
1599 goto error_exit;
1600
1601 /* program MAC filters for entries in tmp_add_list */
1602 status = ice_add_mac(&pf->hw, &tmp_add_list);
1603 if (status) {
1604 dev_err(&pf->pdev->dev, "Could not add MAC filters\n");
1605 status = -ENOMEM;
1606 goto error_exit;
1607 }
1608
1609 ice_free_fltr_list(&pf->pdev->dev, &tmp_add_list);
1610 return status;
1611
1531error_exit: 1612error_exit:
1613 ice_free_fltr_list(&pf->pdev->dev, &tmp_add_list);
1614
1532 if (vsi) { 1615 if (vsi) {
1533 ice_vsi_free_q_vectors(vsi); 1616 ice_vsi_free_q_vectors(vsi);
1534 if (vsi->netdev && vsi->netdev->reg_state == NETREG_REGISTERED) 1617 if (vsi->netdev && vsi->netdev->reg_state == NETREG_REGISTERED)
@@ -1537,6 +1620,7 @@ error_exit:
1537 free_netdev(vsi->netdev); 1620 free_netdev(vsi->netdev);
1538 vsi->netdev = NULL; 1621 vsi->netdev = NULL;
1539 } 1622 }
1623
1540 ice_vsi_delete(vsi); 1624 ice_vsi_delete(vsi);
1541 ice_vsi_put_qs(vsi); 1625 ice_vsi_put_qs(vsi);
1542 pf->q_left_tx += vsi->alloc_txq; 1626 pf->q_left_tx += vsi->alloc_txq;
@@ -1869,6 +1953,13 @@ static int ice_probe(struct pci_dev *pdev,
1869 "probe failed due to setup pf switch:%d\n", err); 1953 "probe failed due to setup pf switch:%d\n", err);
1870 goto err_alloc_sw_unroll; 1954 goto err_alloc_sw_unroll;
1871 } 1955 }
1956
1957 /* Driver is mostly up */
1958 clear_bit(__ICE_DOWN, pf->state);
1959
1960 /* since everything is good, start the service timer */
1961 mod_timer(&pf->serv_tmr, round_jiffies(jiffies + pf->serv_tmr_period));
1962
1872 return 0; 1963 return 0;
1873 1964
1874err_alloc_sw_unroll: 1965err_alloc_sw_unroll:
@@ -2012,6 +2103,7 @@ static int ice_vsi_release(struct ice_vsi *vsi)
2012 ice_free_res(vsi->back->irq_tracker, vsi->base_vector, vsi->idx); 2103 ice_free_res(vsi->back->irq_tracker, vsi->base_vector, vsi->idx);
2013 pf->num_avail_msix += vsi->num_q_vectors; 2104 pf->num_avail_msix += vsi->num_q_vectors;
2014 2105
2106 ice_remove_vsi_fltr(&pf->hw, vsi->vsi_num);
2015 ice_vsi_delete(vsi); 2107 ice_vsi_delete(vsi);
2016 ice_vsi_free_q_vectors(vsi); 2108 ice_vsi_free_q_vectors(vsi);
2017 ice_vsi_clear_rings(vsi); 2109 ice_vsi_clear_rings(vsi);
diff --git a/drivers/net/ethernet/intel/ice/ice_status.h b/drivers/net/ethernet/intel/ice/ice_status.h
index 144712db1ad2..365dfb86dcb9 100644
--- a/drivers/net/ethernet/intel/ice/ice_status.h
+++ b/drivers/net/ethernet/intel/ice/ice_status.h
@@ -7,6 +7,7 @@
7/* Error Codes */ 7/* Error Codes */
8enum ice_status { 8enum ice_status {
9 ICE_ERR_PARAM = -1, 9 ICE_ERR_PARAM = -1,
10 ICE_ERR_NOT_IMPL = -2,
10 ICE_ERR_NOT_READY = -3, 11 ICE_ERR_NOT_READY = -3,
11 ICE_ERR_INVAL_SIZE = -6, 12 ICE_ERR_INVAL_SIZE = -6,
12 ICE_ERR_DEVICE_NOT_SUPPORTED = -8, 13 ICE_ERR_DEVICE_NOT_SUPPORTED = -8,
@@ -15,6 +16,8 @@ enum ice_status {
15 ICE_ERR_NO_MEMORY = -11, 16 ICE_ERR_NO_MEMORY = -11,
16 ICE_ERR_CFG = -12, 17 ICE_ERR_CFG = -12,
17 ICE_ERR_OUT_OF_RANGE = -13, 18 ICE_ERR_OUT_OF_RANGE = -13,
19 ICE_ERR_ALREADY_EXISTS = -14,
20 ICE_ERR_DOES_NOT_EXIST = -15,
18 ICE_ERR_BUF_TOO_SHORT = -52, 21 ICE_ERR_BUF_TOO_SHORT = -52,
19 ICE_ERR_NVM_BLANK_MODE = -53, 22 ICE_ERR_NVM_BLANK_MODE = -53,
20 ICE_ERR_AQ_ERROR = -100, 23 ICE_ERR_AQ_ERROR = -100,
diff --git a/drivers/net/ethernet/intel/ice/ice_switch.c b/drivers/net/ethernet/intel/ice/ice_switch.c
index b438cee9521e..3944dac6cfc6 100644
--- a/drivers/net/ethernet/intel/ice/ice_switch.c
+++ b/drivers/net/ethernet/intel/ice/ice_switch.c
@@ -3,6 +3,88 @@
3 3
4#include "ice_switch.h" 4#include "ice_switch.h"
5 5
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
10
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) }
16 *
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
25 */
26#define DUMMY_ETH_HDR_LEN 16
27static const u8 dummy_eth_header[DUMMY_ETH_HDR_LEN] = { 0x2, 0, 0, 0, 0, 0,
28 0x2, 0, 0, 0, 0, 0,
29 0x81, 0, 0, 0};
30
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)))
51
52/**
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
60 *
61 * Helper function to allocate/free resources using the admin queue commands
62 */
63static enum ice_status
64ice_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)
67{
68 struct ice_aqc_alloc_free_res_cmd *cmd;
69 struct ice_aq_desc desc;
70
71 cmd = &desc.params.sw_res_ctrl;
72
73 if (!buf)
74 return ICE_ERR_PARAM;
75
76 if (buf_size < (num_entries * sizeof(buf->elem[0])))
77 return ICE_ERR_PARAM;
78
79 ice_fill_dflt_direct_cmd_desc(&desc, opc);
80
81 desc.flags |= cpu_to_le16(ICE_AQ_FLAG_RD);
82
83 cmd->num_entries = cpu_to_le16(num_entries);
84
85 return ice_aq_send_cmd(hw, &desc, buf, buf_size, cd);
86}
87
6/** 88/**
7 * ice_aq_get_sw_cfg - get switch configuration 89 * ice_aq_get_sw_cfg - get switch configuration
8 * @hw: pointer to the hardware structure 90 * @hw: pointer to the hardware structure
@@ -165,6 +247,93 @@ ice_aq_free_vsi(struct ice_hw *hw, struct ice_vsi_ctx *vsi_ctx,
165 return status; 247 return status;
166} 248}
167 249
250/**
251 * ice_aq_alloc_free_vsi_list
252 * @hw: pointer to the hw struct
253 * @vsi_list_id: VSI list id returned or used for lookup
254 * @lkup_type: switch rule filter lookup type
255 * @opc: switch rules population command type - pass in the command opcode
256 *
257 * allocates or free a VSI list resource
258 */
259static enum ice_status
260ice_aq_alloc_free_vsi_list(struct ice_hw *hw, u16 *vsi_list_id,
261 enum ice_sw_lkup_type lkup_type,
262 enum ice_adminq_opc opc)
263{
264 struct ice_aqc_alloc_free_res_elem *sw_buf;
265 struct ice_aqc_res_elem *vsi_ele;
266 enum ice_status status;
267 u16 buf_len;
268
269 buf_len = sizeof(*sw_buf);
270 sw_buf = devm_kzalloc(ice_hw_to_dev(hw), buf_len, GFP_KERNEL);
271 if (!sw_buf)
272 return ICE_ERR_NO_MEMORY;
273 sw_buf->num_elems = cpu_to_le16(1);
274
275 if (lkup_type == ICE_SW_LKUP_MAC ||
276 lkup_type == ICE_SW_LKUP_MAC_VLAN ||
277 lkup_type == ICE_SW_LKUP_ETHERTYPE ||
278 lkup_type == ICE_SW_LKUP_ETHERTYPE_MAC ||
279 lkup_type == ICE_SW_LKUP_PROMISC ||
280 lkup_type == ICE_SW_LKUP_PROMISC_VLAN) {
281 sw_buf->res_type = cpu_to_le16(ICE_AQC_RES_TYPE_VSI_LIST_REP);
282 } else if (lkup_type == ICE_SW_LKUP_VLAN) {
283 sw_buf->res_type =
284 cpu_to_le16(ICE_AQC_RES_TYPE_VSI_LIST_PRUNE);
285 } else {
286 status = ICE_ERR_PARAM;
287 goto ice_aq_alloc_free_vsi_list_exit;
288 }
289
290 if (opc == ice_aqc_opc_free_res)
291 sw_buf->elem[0].e.sw_resp = cpu_to_le16(*vsi_list_id);
292
293 status = ice_aq_alloc_free_res(hw, 1, sw_buf, buf_len, opc, NULL);
294 if (status)
295 goto ice_aq_alloc_free_vsi_list_exit;
296
297 if (opc == ice_aqc_opc_alloc_res) {
298 vsi_ele = &sw_buf->elem[0];
299 *vsi_list_id = le16_to_cpu(vsi_ele->e.sw_resp);
300 }
301
302ice_aq_alloc_free_vsi_list_exit:
303 devm_kfree(ice_hw_to_dev(hw), sw_buf);
304 return status;
305}
306
307/**
308 * ice_aq_sw_rules - add/update/remove switch rules
309 * @hw: pointer to the hw struct
310 * @rule_list: pointer to switch rule population list
311 * @rule_list_sz: total size of the rule list in bytes
312 * @num_rules: number of switch rules in the rule_list
313 * @opc: switch rules population command type - pass in the command opcode
314 * @cd: pointer to command details structure or NULL
315 *
316 * Add(0x02a0)/Update(0x02a1)/Remove(0x02a2) switch rules commands to firmware
317 */
318static enum ice_status
319ice_aq_sw_rules(struct ice_hw *hw, void *rule_list, u16 rule_list_sz,
320 u8 num_rules, enum ice_adminq_opc opc, struct ice_sq_cd *cd)
321{
322 struct ice_aq_desc desc;
323
324 if (opc != ice_aqc_opc_add_sw_rules &&
325 opc != ice_aqc_opc_update_sw_rules &&
326 opc != ice_aqc_opc_remove_sw_rules)
327 return ICE_ERR_PARAM;
328
329 ice_fill_dflt_direct_cmd_desc(&desc, opc);
330
331 desc.flags |= cpu_to_le16(ICE_AQ_FLAG_RD);
332 desc.params.sw_rules.num_rules_fltr_entry_index =
333 cpu_to_le16(num_rules);
334 return ice_aq_send_cmd(hw, &desc, rule_list, rule_list_sz, cd);
335}
336
168/* ice_init_port_info - Initialize port_info with switch configuration data 337/* ice_init_port_info - Initialize port_info with switch configuration data
169 * @pi: pointer to port_info 338 * @pi: pointer to port_info
170 * @vsi_port_num: VSI number or port number 339 * @vsi_port_num: VSI number or port number
@@ -257,3 +426,1212 @@ enum ice_status ice_get_initial_sw_cfg(struct ice_hw *hw)
257 devm_kfree(ice_hw_to_dev(hw), (void *)rbuf); 426 devm_kfree(ice_hw_to_dev(hw), (void *)rbuf);
258 return status; 427 return status;
259} 428}
429
430/**
431 * ice_fill_sw_info - Helper function to populate lb_en and lan_en
432 * @hw: pointer to the hardware structure
433 * @f_info: filter info structure to fill/update
434 *
435 * This helper function populates the lb_en and lan_en elements of the provided
436 * ice_fltr_info struct using the switch's type and characteristics of the
437 * switch rule being configured.
438 */
439static void ice_fill_sw_info(struct ice_hw *hw, struct ice_fltr_info *f_info)
440{
441 f_info->lb_en = false;
442 f_info->lan_en = false;
443 if ((f_info->flag & ICE_FLTR_TX) &&
444 (f_info->fltr_act == ICE_FWD_TO_VSI ||
445 f_info->fltr_act == ICE_FWD_TO_VSI_LIST ||
446 f_info->fltr_act == ICE_FWD_TO_Q ||
447 f_info->fltr_act == ICE_FWD_TO_QGRP)) {
448 f_info->lb_en = true;
449 if (!(hw->evb_veb && f_info->lkup_type == ICE_SW_LKUP_MAC &&
450 is_unicast_ether_addr(f_info->l_data.mac.mac_addr)))
451 f_info->lan_en = true;
452 }
453}
454
455/**
456 * ice_fill_sw_rule - Helper function to fill switch rule structure
457 * @hw: pointer to the hardware structure
458 * @f_info: entry containing packet forwarding information
459 * @s_rule: switch rule structure to be filled in based on mac_entry
460 * @opc: switch rules population command type - pass in the command opcode
461 */
462static void
463ice_fill_sw_rule(struct ice_hw *hw, struct ice_fltr_info *f_info,
464 struct ice_aqc_sw_rules_elem *s_rule, enum ice_adminq_opc opc)
465{
466 u16 vlan_id = ICE_MAX_VLAN_ID + 1;
467 u8 eth_hdr[DUMMY_ETH_HDR_LEN];
468 void *daddr = NULL;
469 u32 act = 0;
470 __be16 *off;
471
472 if (opc == ice_aqc_opc_remove_sw_rules) {
473 s_rule->pdata.lkup_tx_rx.act = 0;
474 s_rule->pdata.lkup_tx_rx.index =
475 cpu_to_le16(f_info->fltr_rule_id);
476 s_rule->pdata.lkup_tx_rx.hdr_len = 0;
477 return;
478 }
479
480 /* initialize the ether header with a dummy header */
481 memcpy(eth_hdr, dummy_eth_header, sizeof(dummy_eth_header));
482 ice_fill_sw_info(hw, f_info);
483
484 switch (f_info->fltr_act) {
485 case ICE_FWD_TO_VSI:
486 act |= (f_info->fwd_id.vsi_id << ICE_SINGLE_ACT_VSI_ID_S) &
487 ICE_SINGLE_ACT_VSI_ID_M;
488 if (f_info->lkup_type != ICE_SW_LKUP_VLAN)
489 act |= ICE_SINGLE_ACT_VSI_FORWARDING |
490 ICE_SINGLE_ACT_VALID_BIT;
491 break;
492 case ICE_FWD_TO_VSI_LIST:
493 act |= ICE_SINGLE_ACT_VSI_LIST;
494 act |= (f_info->fwd_id.vsi_list_id <<
495 ICE_SINGLE_ACT_VSI_LIST_ID_S) &
496 ICE_SINGLE_ACT_VSI_LIST_ID_M;
497 if (f_info->lkup_type != ICE_SW_LKUP_VLAN)
498 act |= ICE_SINGLE_ACT_VSI_FORWARDING |
499 ICE_SINGLE_ACT_VALID_BIT;
500 break;
501 case ICE_FWD_TO_Q:
502 act |= ICE_SINGLE_ACT_TO_Q;
503 act |= (f_info->fwd_id.q_id << ICE_SINGLE_ACT_Q_INDEX_S) &
504 ICE_SINGLE_ACT_Q_INDEX_M;
505 break;
506 case ICE_FWD_TO_QGRP:
507 act |= ICE_SINGLE_ACT_TO_Q;
508 act |= (f_info->qgrp_size << ICE_SINGLE_ACT_Q_REGION_S) &
509 ICE_SINGLE_ACT_Q_REGION_M;
510 break;
511 case ICE_DROP_PACKET:
512 act |= ICE_SINGLE_ACT_VSI_FORWARDING | ICE_SINGLE_ACT_DROP;
513 break;
514 default:
515 return;
516 }
517
518 if (f_info->lb_en)
519 act |= ICE_SINGLE_ACT_LB_ENABLE;
520 if (f_info->lan_en)
521 act |= ICE_SINGLE_ACT_LAN_ENABLE;
522
523 switch (f_info->lkup_type) {
524 case ICE_SW_LKUP_MAC:
525 daddr = f_info->l_data.mac.mac_addr;
526 break;
527 case ICE_SW_LKUP_VLAN:
528 vlan_id = f_info->l_data.vlan.vlan_id;
529 if (f_info->fltr_act == ICE_FWD_TO_VSI ||
530 f_info->fltr_act == ICE_FWD_TO_VSI_LIST) {
531 act |= ICE_SINGLE_ACT_PRUNE;
532 act |= ICE_SINGLE_ACT_EGRESS | ICE_SINGLE_ACT_INGRESS;
533 }
534 break;
535 case ICE_SW_LKUP_ETHERTYPE_MAC:
536 daddr = f_info->l_data.ethertype_mac.mac_addr;
537 /* fall-through */
538 case ICE_SW_LKUP_ETHERTYPE:
539 off = (__be16 *)&eth_hdr[ICE_ETH_ETHTYPE_OFFSET];
540 *off = cpu_to_be16(f_info->l_data.ethertype_mac.ethertype);
541 break;
542 case ICE_SW_LKUP_MAC_VLAN:
543 daddr = f_info->l_data.mac_vlan.mac_addr;
544 vlan_id = f_info->l_data.mac_vlan.vlan_id;
545 break;
546 case ICE_SW_LKUP_PROMISC_VLAN:
547 vlan_id = f_info->l_data.mac_vlan.vlan_id;
548 /* fall-through */
549 case ICE_SW_LKUP_PROMISC:
550 daddr = f_info->l_data.mac_vlan.mac_addr;
551 break;
552 default:
553 break;
554 }
555
556 s_rule->type = (f_info->flag & ICE_FLTR_RX) ?
557 cpu_to_le16(ICE_AQC_SW_RULES_T_LKUP_RX) :
558 cpu_to_le16(ICE_AQC_SW_RULES_T_LKUP_TX);
559
560 /* Recipe set depending on lookup type */
561 s_rule->pdata.lkup_tx_rx.recipe_id = cpu_to_le16(f_info->lkup_type);
562 s_rule->pdata.lkup_tx_rx.src = cpu_to_le16(f_info->src);
563 s_rule->pdata.lkup_tx_rx.act = cpu_to_le32(act);
564
565 if (daddr)
566 ether_addr_copy(&eth_hdr[ICE_ETH_DA_OFFSET], daddr);
567
568 if (!(vlan_id > ICE_MAX_VLAN_ID)) {
569 off = (__be16 *)&eth_hdr[ICE_ETH_VLAN_TCI_OFFSET];
570 *off = cpu_to_be16(vlan_id);
571 }
572
573 /* Create the switch rule with the final dummy Ethernet header */
574 if (opc != ice_aqc_opc_update_sw_rules)
575 s_rule->pdata.lkup_tx_rx.hdr_len = cpu_to_le16(sizeof(eth_hdr));
576
577 memcpy(s_rule->pdata.lkup_tx_rx.hdr, eth_hdr, sizeof(eth_hdr));
578}
579
580/**
581 * ice_add_marker_act
582 * @hw: pointer to the hardware structure
583 * @m_ent: the management entry for which sw marker needs to be added
584 * @sw_marker: sw marker to tag the Rx descriptor with
585 * @l_id: large action resource id
586 *
587 * Create a large action to hold software marker and update the switch rule
588 * entry pointed by m_ent with newly created large action
589 */
590static enum ice_status
591ice_add_marker_act(struct ice_hw *hw, struct ice_fltr_mgmt_list_entry *m_ent,
592 u16 sw_marker, u16 l_id)
593{
594 struct ice_aqc_sw_rules_elem *lg_act, *rx_tx;
595 /* For software marker we need 3 large actions
596 * 1. FWD action: FWD TO VSI or VSI LIST
597 * 2. GENERIC VALUE action to hold the profile id
598 * 3. GENERIC VALUE action to hold the software marker id
599 */
600 const u16 num_lg_acts = 3;
601 enum ice_status status;
602 u16 lg_act_size;
603 u16 rules_size;
604 u16 vsi_info;
605 u32 act;
606
607 if (m_ent->fltr_info.lkup_type != ICE_SW_LKUP_MAC)
608 return ICE_ERR_PARAM;
609
610 /* Create two back-to-back switch rules and submit them to the HW using
611 * one memory buffer:
612 * 1. Large Action
613 * 2. Look up tx rx
614 */
615 lg_act_size = (u16)ICE_SW_RULE_LG_ACT_SIZE(num_lg_acts);
616 rules_size = lg_act_size + ICE_SW_RULE_RX_TX_ETH_HDR_SIZE;
617 lg_act = devm_kzalloc(ice_hw_to_dev(hw), rules_size, GFP_KERNEL);
618 if (!lg_act)
619 return ICE_ERR_NO_MEMORY;
620
621 rx_tx = (struct ice_aqc_sw_rules_elem *)((u8 *)lg_act + lg_act_size);
622
623 /* Fill in the first switch rule i.e. large action */
624 lg_act->type = cpu_to_le16(ICE_AQC_SW_RULES_T_LG_ACT);
625 lg_act->pdata.lg_act.index = cpu_to_le16(l_id);
626 lg_act->pdata.lg_act.size = cpu_to_le16(num_lg_acts);
627
628 /* First action VSI forwarding or VSI list forwarding depending on how
629 * many VSIs
630 */
631 vsi_info = (m_ent->vsi_count > 1) ?
632 m_ent->fltr_info.fwd_id.vsi_list_id :
633 m_ent->fltr_info.fwd_id.vsi_id;
634
635 act = ICE_LG_ACT_VSI_FORWARDING | ICE_LG_ACT_VALID_BIT;
636 act |= (vsi_info << ICE_LG_ACT_VSI_LIST_ID_S) &
637 ICE_LG_ACT_VSI_LIST_ID_M;
638 if (m_ent->vsi_count > 1)
639 act |= ICE_LG_ACT_VSI_LIST;
640 lg_act->pdata.lg_act.act[0] = cpu_to_le32(act);
641
642 /* Second action descriptor type */
643 act = ICE_LG_ACT_GENERIC;
644
645 act |= (1 << ICE_LG_ACT_GENERIC_VALUE_S) & ICE_LG_ACT_GENERIC_VALUE_M;
646 lg_act->pdata.lg_act.act[1] = cpu_to_le32(act);
647
648 act = (7 << ICE_LG_ACT_GENERIC_OFFSET_S) & ICE_LG_ACT_GENERIC_VALUE_M;
649
650 /* Third action Marker value */
651 act |= ICE_LG_ACT_GENERIC;
652 act |= (sw_marker << ICE_LG_ACT_GENERIC_VALUE_S) &
653 ICE_LG_ACT_GENERIC_VALUE_M;
654
655 act |= (0 << ICE_LG_ACT_GENERIC_OFFSET_S) & ICE_LG_ACT_GENERIC_VALUE_M;
656 lg_act->pdata.lg_act.act[2] = cpu_to_le32(act);
657
658 /* call the fill switch rule to fill the lookup tx rx structure */
659 ice_fill_sw_rule(hw, &m_ent->fltr_info, rx_tx,
660 ice_aqc_opc_update_sw_rules);
661
662 /* Update the action to point to the large action id */
663 rx_tx->pdata.lkup_tx_rx.act =
664 cpu_to_le32(ICE_SINGLE_ACT_PTR |
665 ((l_id << ICE_SINGLE_ACT_PTR_VAL_S) &
666 ICE_SINGLE_ACT_PTR_VAL_M));
667
668 /* Use the filter rule id of the previously created rule with single
669 * act. Once the update happens, hardware will treat this as large
670 * action
671 */
672 rx_tx->pdata.lkup_tx_rx.index =
673 cpu_to_le16(m_ent->fltr_info.fltr_rule_id);
674
675 status = ice_aq_sw_rules(hw, lg_act, rules_size, 2,
676 ice_aqc_opc_update_sw_rules, NULL);
677 if (!status) {
678 m_ent->lg_act_idx = l_id;
679 m_ent->sw_marker_id = sw_marker;
680 }
681
682 devm_kfree(ice_hw_to_dev(hw), lg_act);
683 return status;
684}
685
686/**
687 * ice_create_vsi_list_map
688 * @hw: pointer to the hardware structure
689 * @vsi_array: array of VSIs to form a VSI list
690 * @num_vsi: num VSI in the array
691 * @vsi_list_id: VSI list id generated as part of allocate resource
692 *
693 * Helper function to create a new entry of VSI list id to VSI mapping
694 * using the given VSI list id
695 */
696static struct ice_vsi_list_map_info *
697ice_create_vsi_list_map(struct ice_hw *hw, u16 *vsi_array, u16 num_vsi,
698 u16 vsi_list_id)
699{
700 struct ice_switch_info *sw = hw->switch_info;
701 struct ice_vsi_list_map_info *v_map;
702 int i;
703
704 v_map = devm_kcalloc(ice_hw_to_dev(hw), 1, sizeof(*v_map), GFP_KERNEL);
705 if (!v_map)
706 return NULL;
707
708 v_map->vsi_list_id = vsi_list_id;
709
710 for (i = 0; i < num_vsi; i++)
711 set_bit(vsi_array[i], v_map->vsi_map);
712
713 list_add(&v_map->list_entry, &sw->vsi_list_map_head);
714 return v_map;
715}
716
717/**
718 * ice_update_vsi_list_rule
719 * @hw: pointer to the hardware structure
720 * @vsi_array: array of VSIs to form a VSI list
721 * @num_vsi: num VSI in the array
722 * @vsi_list_id: VSI list id generated as part of allocate resource
723 * @remove: Boolean value to indicate if this is a remove action
724 * @opc: switch rules population command type - pass in the command opcode
725 * @lkup_type: lookup type of the filter
726 *
727 * Call AQ command to add a new switch rule or update existing switch rule
728 * using the given VSI list id
729 */
730static enum ice_status
731ice_update_vsi_list_rule(struct ice_hw *hw, u16 *vsi_array, u16 num_vsi,
732 u16 vsi_list_id, bool remove, enum ice_adminq_opc opc,
733 enum ice_sw_lkup_type lkup_type)
734{
735 struct ice_aqc_sw_rules_elem *s_rule;
736 enum ice_status status;
737 u16 s_rule_size;
738 u16 type;
739 int i;
740
741 if (!num_vsi)
742 return ICE_ERR_PARAM;
743
744 if (lkup_type == ICE_SW_LKUP_MAC ||
745 lkup_type == ICE_SW_LKUP_MAC_VLAN ||
746 lkup_type == ICE_SW_LKUP_ETHERTYPE ||
747 lkup_type == ICE_SW_LKUP_ETHERTYPE_MAC ||
748 lkup_type == ICE_SW_LKUP_PROMISC ||
749 lkup_type == ICE_SW_LKUP_PROMISC_VLAN)
750 type = remove ? ICE_AQC_SW_RULES_T_VSI_LIST_CLEAR :
751 ICE_AQC_SW_RULES_T_VSI_LIST_SET;
752 else if (lkup_type == ICE_SW_LKUP_VLAN)
753 type = remove ? ICE_AQC_SW_RULES_T_PRUNE_LIST_CLEAR :
754 ICE_AQC_SW_RULES_T_PRUNE_LIST_SET;
755 else
756 return ICE_ERR_PARAM;
757
758 s_rule_size = (u16)ICE_SW_RULE_VSI_LIST_SIZE(num_vsi);
759 s_rule = devm_kzalloc(ice_hw_to_dev(hw), s_rule_size, GFP_KERNEL);
760 if (!s_rule)
761 return ICE_ERR_NO_MEMORY;
762
763 for (i = 0; i < num_vsi; i++)
764 s_rule->pdata.vsi_list.vsi[i] = cpu_to_le16(vsi_array[i]);
765
766 s_rule->type = cpu_to_le16(type);
767 s_rule->pdata.vsi_list.number_vsi = cpu_to_le16(num_vsi);
768 s_rule->pdata.vsi_list.index = cpu_to_le16(vsi_list_id);
769
770 status = ice_aq_sw_rules(hw, s_rule, s_rule_size, 1, opc, NULL);
771
772 devm_kfree(ice_hw_to_dev(hw), s_rule);
773 return status;
774}
775
776/**
777 * ice_create_vsi_list_rule - Creates and populates a VSI list rule
778 * @hw: pointer to the hw struct
779 * @vsi_array: array of VSIs to form a VSI list
780 * @num_vsi: number of VSIs in the array
781 * @vsi_list_id: stores the ID of the VSI list to be created
782 * @lkup_type: switch rule filter's lookup type
783 */
784static enum ice_status
785ice_create_vsi_list_rule(struct ice_hw *hw, u16 *vsi_array, u16 num_vsi,
786 u16 *vsi_list_id, enum ice_sw_lkup_type lkup_type)
787{
788 enum ice_status status;
789 int i;
790
791 for (i = 0; i < num_vsi; i++)
792 if (vsi_array[i] >= ICE_MAX_VSI)
793 return ICE_ERR_OUT_OF_RANGE;
794
795 status = ice_aq_alloc_free_vsi_list(hw, vsi_list_id, lkup_type,
796 ice_aqc_opc_alloc_res);
797 if (status)
798 return status;
799
800 /* Update the newly created VSI list to include the specified VSIs */
801 return ice_update_vsi_list_rule(hw, vsi_array, num_vsi, *vsi_list_id,
802 false, ice_aqc_opc_add_sw_rules,
803 lkup_type);
804}
805
806/**
807 * ice_create_pkt_fwd_rule
808 * @hw: pointer to the hardware structure
809 * @f_entry: entry containing packet forwarding information
810 *
811 * Create switch rule with given filter information and add an entry
812 * to the corresponding filter management list to track this switch rule
813 * and VSI mapping
814 */
815static enum ice_status
816ice_create_pkt_fwd_rule(struct ice_hw *hw,
817 struct ice_fltr_list_entry *f_entry)
818{
819 struct ice_switch_info *sw = hw->switch_info;
820 struct ice_fltr_mgmt_list_entry *fm_entry;
821 struct ice_aqc_sw_rules_elem *s_rule;
822 enum ice_sw_lkup_type l_type;
823 enum ice_status status;
824
825 s_rule = devm_kzalloc(ice_hw_to_dev(hw),
826 ICE_SW_RULE_RX_TX_ETH_HDR_SIZE, GFP_KERNEL);
827 if (!s_rule)
828 return ICE_ERR_NO_MEMORY;
829 fm_entry = devm_kzalloc(ice_hw_to_dev(hw), sizeof(*fm_entry),
830 GFP_KERNEL);
831 if (!fm_entry) {
832 status = ICE_ERR_NO_MEMORY;
833 goto ice_create_pkt_fwd_rule_exit;
834 }
835
836 fm_entry->fltr_info = f_entry->fltr_info;
837
838 /* Initialize all the fields for the management entry */
839 fm_entry->vsi_count = 1;
840 fm_entry->lg_act_idx = ICE_INVAL_LG_ACT_INDEX;
841 fm_entry->sw_marker_id = ICE_INVAL_SW_MARKER_ID;
842 fm_entry->counter_index = ICE_INVAL_COUNTER_ID;
843
844 ice_fill_sw_rule(hw, &fm_entry->fltr_info, s_rule,
845 ice_aqc_opc_add_sw_rules);
846
847 status = ice_aq_sw_rules(hw, s_rule, ICE_SW_RULE_RX_TX_ETH_HDR_SIZE, 1,
848 ice_aqc_opc_add_sw_rules, NULL);
849 if (status) {
850 devm_kfree(ice_hw_to_dev(hw), fm_entry);
851 goto ice_create_pkt_fwd_rule_exit;
852 }
853
854 f_entry->fltr_info.fltr_rule_id =
855 le16_to_cpu(s_rule->pdata.lkup_tx_rx.index);
856 fm_entry->fltr_info.fltr_rule_id =
857 le16_to_cpu(s_rule->pdata.lkup_tx_rx.index);
858
859 /* The book keeping entries will get removed when base driver
860 * calls remove filter AQ command
861 */
862 l_type = fm_entry->fltr_info.lkup_type;
863 if (l_type == ICE_SW_LKUP_MAC) {
864 mutex_lock(&sw->mac_list_lock);
865 list_add(&fm_entry->list_entry, &sw->mac_list_head);
866 mutex_unlock(&sw->mac_list_lock);
867 } else if (l_type == ICE_SW_LKUP_VLAN) {
868 mutex_lock(&sw->vlan_list_lock);
869 list_add(&fm_entry->list_entry, &sw->vlan_list_head);
870 mutex_unlock(&sw->vlan_list_lock);
871 } else if (l_type == ICE_SW_LKUP_ETHERTYPE ||
872 l_type == ICE_SW_LKUP_ETHERTYPE_MAC) {
873 mutex_lock(&sw->eth_m_list_lock);
874 list_add(&fm_entry->list_entry, &sw->eth_m_list_head);
875 mutex_unlock(&sw->eth_m_list_lock);
876 } else if (l_type == ICE_SW_LKUP_PROMISC ||
877 l_type == ICE_SW_LKUP_PROMISC_VLAN) {
878 mutex_lock(&sw->promisc_list_lock);
879 list_add(&fm_entry->list_entry, &sw->promisc_list_head);
880 mutex_unlock(&sw->promisc_list_lock);
881 } else if (fm_entry->fltr_info.lkup_type == ICE_SW_LKUP_MAC_VLAN) {
882 mutex_lock(&sw->mac_vlan_list_lock);
883 list_add(&fm_entry->list_entry, &sw->mac_vlan_list_head);
884 mutex_unlock(&sw->mac_vlan_list_lock);
885 } else {
886 status = ICE_ERR_NOT_IMPL;
887 }
888ice_create_pkt_fwd_rule_exit:
889 devm_kfree(ice_hw_to_dev(hw), s_rule);
890 return status;
891}
892
893/**
894 * ice_update_pkt_fwd_rule
895 * @hw: pointer to the hardware structure
896 * @rule_id: rule of previously created switch rule to update
897 * @vsi_list_id: VSI list id to be updated with
898 * @f_info: ice_fltr_info to pull other information for switch rule
899 *
900 * Call AQ command to update a previously created switch rule with a
901 * VSI list id
902 */
903static enum ice_status
904ice_update_pkt_fwd_rule(struct ice_hw *hw, u16 rule_id, u16 vsi_list_id,
905 struct ice_fltr_info f_info)
906{
907 struct ice_aqc_sw_rules_elem *s_rule;
908 struct ice_fltr_info tmp_fltr;
909 enum ice_status status;
910
911 s_rule = devm_kzalloc(ice_hw_to_dev(hw),
912 ICE_SW_RULE_RX_TX_ETH_HDR_SIZE, GFP_KERNEL);
913 if (!s_rule)
914 return ICE_ERR_NO_MEMORY;
915
916 tmp_fltr = f_info;
917 tmp_fltr.fltr_act = ICE_FWD_TO_VSI_LIST;
918 tmp_fltr.fwd_id.vsi_list_id = vsi_list_id;
919
920 ice_fill_sw_rule(hw, &tmp_fltr, s_rule,
921 ice_aqc_opc_update_sw_rules);
922
923 s_rule->pdata.lkup_tx_rx.index = cpu_to_le16(rule_id);
924
925 /* Update switch rule with new rule set to forward VSI list */
926 status = ice_aq_sw_rules(hw, s_rule, ICE_SW_RULE_RX_TX_ETH_HDR_SIZE, 1,
927 ice_aqc_opc_update_sw_rules, NULL);
928
929 devm_kfree(ice_hw_to_dev(hw), s_rule);
930 return status;
931}
932
933/**
934 * ice_handle_vsi_list_mgmt
935 * @hw: pointer to the hardware structure
936 * @m_entry: pointer to current filter management list entry
937 * @cur_fltr: filter information from the book keeping entry
938 * @new_fltr: filter information with the new VSI to be added
939 *
940 * Call AQ command to add or update previously created VSI list with new VSI.
941 *
942 * Helper function to do book keeping associated with adding filter information
943 * The algorithm to do the booking keeping is described below :
944 * When a VSI needs to subscribe to a given filter( MAC/VLAN/Ethtype etc.)
945 * if only one VSI has been added till now
946 * Allocate a new VSI list and add two VSIs
947 * to this list using switch rule command
948 * Update the previously created switch rule with the
949 * newly created VSI list id
950 * if a VSI list was previously created
951 * Add the new VSI to the previously created VSI list set
952 * using the update switch rule command
953 */
954static enum ice_status
955ice_handle_vsi_list_mgmt(struct ice_hw *hw,
956 struct ice_fltr_mgmt_list_entry *m_entry,
957 struct ice_fltr_info *cur_fltr,
958 struct ice_fltr_info *new_fltr)
959{
960 enum ice_status status = 0;
961 u16 vsi_list_id = 0;
962
963 if ((cur_fltr->fltr_act == ICE_FWD_TO_Q ||
964 cur_fltr->fltr_act == ICE_FWD_TO_QGRP))
965 return ICE_ERR_NOT_IMPL;
966
967 if ((new_fltr->fltr_act == ICE_FWD_TO_Q ||
968 new_fltr->fltr_act == ICE_FWD_TO_QGRP) &&
969 (cur_fltr->fltr_act == ICE_FWD_TO_VSI ||
970 cur_fltr->fltr_act == ICE_FWD_TO_VSI_LIST))
971 return ICE_ERR_NOT_IMPL;
972
973 if (m_entry->vsi_count < 2 && !m_entry->vsi_list_info) {
974 /* Only one entry existed in the mapping and it was not already
975 * a part of a VSI list. So, create a VSI list with the old and
976 * new VSIs.
977 */
978 u16 vsi_id_arr[2];
979 u16 fltr_rule;
980
981 /* A rule already exists with the new VSI being added */
982 if (cur_fltr->fwd_id.vsi_id == new_fltr->fwd_id.vsi_id)
983 return ICE_ERR_ALREADY_EXISTS;
984
985 vsi_id_arr[0] = cur_fltr->fwd_id.vsi_id;
986 vsi_id_arr[1] = new_fltr->fwd_id.vsi_id;
987 status = ice_create_vsi_list_rule(hw, &vsi_id_arr[0], 2,
988 &vsi_list_id,
989 new_fltr->lkup_type);
990 if (status)
991 return status;
992
993 fltr_rule = cur_fltr->fltr_rule_id;
994 /* Update the previous switch rule of "MAC forward to VSI" to
995 * "MAC fwd to VSI list"
996 */
997 status = ice_update_pkt_fwd_rule(hw, fltr_rule, vsi_list_id,
998 *new_fltr);
999 if (status)
1000 return status;
1001
1002 cur_fltr->fwd_id.vsi_list_id = vsi_list_id;
1003 cur_fltr->fltr_act = ICE_FWD_TO_VSI_LIST;
1004 m_entry->vsi_list_info =
1005 ice_create_vsi_list_map(hw, &vsi_id_arr[0], 2,
1006 vsi_list_id);
1007
1008 /* If this entry was large action then the large action needs
1009 * to be updated to point to FWD to VSI list
1010 */
1011 if (m_entry->sw_marker_id != ICE_INVAL_SW_MARKER_ID)
1012 status =
1013 ice_add_marker_act(hw, m_entry,
1014 m_entry->sw_marker_id,
1015 m_entry->lg_act_idx);
1016 } else {
1017 u16 vsi_id = new_fltr->fwd_id.vsi_id;
1018 enum ice_adminq_opc opcode;
1019
1020 /* A rule already exists with the new VSI being added */
1021 if (test_bit(vsi_id, m_entry->vsi_list_info->vsi_map))
1022 return 0;
1023
1024 /* Update the previously created VSI list set with
1025 * the new VSI id passed in
1026 */
1027 vsi_list_id = cur_fltr->fwd_id.vsi_list_id;
1028 opcode = ice_aqc_opc_update_sw_rules;
1029
1030 status = ice_update_vsi_list_rule(hw, &vsi_id, 1, vsi_list_id,
1031 false, opcode,
1032 new_fltr->lkup_type);
1033 /* update VSI list mapping info with new VSI id */
1034 if (!status)
1035 set_bit(vsi_id, m_entry->vsi_list_info->vsi_map);
1036 }
1037 if (!status)
1038 m_entry->vsi_count++;
1039 return status;
1040}
1041
1042/**
1043 * ice_find_mac_entry
1044 * @hw: pointer to the hardware structure
1045 * @mac_addr: MAC address to search for
1046 *
1047 * Helper function to search for a MAC entry using a given MAC address
1048 * Returns pointer to the entry if found.
1049 */
1050static struct ice_fltr_mgmt_list_entry *
1051ice_find_mac_entry(struct ice_hw *hw, u8 *mac_addr)
1052{
1053 struct ice_fltr_mgmt_list_entry *m_list_itr, *mac_ret = NULL;
1054 struct ice_switch_info *sw = hw->switch_info;
1055
1056 mutex_lock(&sw->mac_list_lock);
1057 list_for_each_entry(m_list_itr, &sw->mac_list_head, list_entry) {
1058 u8 *buf = &m_list_itr->fltr_info.l_data.mac.mac_addr[0];
1059
1060 if (ether_addr_equal(buf, mac_addr)) {
1061 mac_ret = m_list_itr;
1062 break;
1063 }
1064 }
1065 mutex_unlock(&sw->mac_list_lock);
1066 return mac_ret;
1067}
1068
1069/**
1070 * ice_add_shared_mac - Add one MAC shared filter rule
1071 * @hw: pointer to the hardware structure
1072 * @f_entry: structure containing MAC forwarding information
1073 *
1074 * Adds or updates the book keeping list for the MAC addresses
1075 */
1076static enum ice_status
1077ice_add_shared_mac(struct ice_hw *hw, struct ice_fltr_list_entry *f_entry)
1078{
1079 struct ice_fltr_info *new_fltr, *cur_fltr;
1080 struct ice_fltr_mgmt_list_entry *m_entry;
1081
1082 new_fltr = &f_entry->fltr_info;
1083
1084 m_entry = ice_find_mac_entry(hw, &new_fltr->l_data.mac.mac_addr[0]);
1085 if (!m_entry)
1086 return ice_create_pkt_fwd_rule(hw, f_entry);
1087
1088 cur_fltr = &m_entry->fltr_info;
1089
1090 return ice_handle_vsi_list_mgmt(hw, m_entry, cur_fltr, new_fltr);
1091}
1092
1093/**
1094 * ice_add_mac - Add a MAC address based filter rule
1095 * @hw: pointer to the hardware structure
1096 * @m_list: list of MAC addresses and forwarding information
1097 *
1098 * IMPORTANT: When the ucast_shared flag is set to false and m_list has
1099 * multiple unicast addresses, the function assumes that all the
1100 * addresses are unique in a given add_mac call. It doesn't
1101 * check for duplicates in this case, removing duplicates from a given
1102 * list should be taken care of in the caller of this function.
1103 */
1104enum ice_status
1105ice_add_mac(struct ice_hw *hw, struct list_head *m_list)
1106{
1107 struct ice_aqc_sw_rules_elem *s_rule, *r_iter;
1108 struct ice_fltr_list_entry *m_list_itr;
1109 u16 elem_sent, total_elem_left;
1110 enum ice_status status = 0;
1111 u16 num_unicast = 0;
1112 u16 s_rule_size;
1113
1114 if (!m_list || !hw)
1115 return ICE_ERR_PARAM;
1116
1117 list_for_each_entry(m_list_itr, m_list, list_entry) {
1118 u8 *add = &m_list_itr->fltr_info.l_data.mac.mac_addr[0];
1119
1120 if (m_list_itr->fltr_info.lkup_type != ICE_SW_LKUP_MAC)
1121 return ICE_ERR_PARAM;
1122 if (is_zero_ether_addr(add))
1123 return ICE_ERR_PARAM;
1124 if (is_unicast_ether_addr(add) && !hw->ucast_shared) {
1125 /* Don't overwrite the unicast address */
1126 if (ice_find_mac_entry(hw, add))
1127 return ICE_ERR_ALREADY_EXISTS;
1128 num_unicast++;
1129 } else if (is_multicast_ether_addr(add) ||
1130 (is_unicast_ether_addr(add) && hw->ucast_shared)) {
1131 status = ice_add_shared_mac(hw, m_list_itr);
1132 if (status) {
1133 m_list_itr->status = ICE_FLTR_STATUS_FW_FAIL;
1134 return status;
1135 }
1136 m_list_itr->status = ICE_FLTR_STATUS_FW_SUCCESS;
1137 }
1138 }
1139
1140 /* Exit if no suitable entries were found for adding bulk switch rule */
1141 if (!num_unicast)
1142 return 0;
1143
1144 /* Allocate switch rule buffer for the bulk update for unicast */
1145 s_rule_size = ICE_SW_RULE_RX_TX_ETH_HDR_SIZE;
1146 s_rule = devm_kcalloc(ice_hw_to_dev(hw), num_unicast, s_rule_size,
1147 GFP_KERNEL);
1148 if (!s_rule)
1149 return ICE_ERR_NO_MEMORY;
1150
1151 r_iter = s_rule;
1152 list_for_each_entry(m_list_itr, m_list, list_entry) {
1153 struct ice_fltr_info *f_info = &m_list_itr->fltr_info;
1154 u8 *addr = &f_info->l_data.mac.mac_addr[0];
1155
1156 if (is_unicast_ether_addr(addr)) {
1157 ice_fill_sw_rule(hw, &m_list_itr->fltr_info,
1158 r_iter, ice_aqc_opc_add_sw_rules);
1159 r_iter = (struct ice_aqc_sw_rules_elem *)
1160 ((u8 *)r_iter + s_rule_size);
1161 }
1162 }
1163
1164 /* Call AQ bulk switch rule update for all unicast addresses */
1165 r_iter = s_rule;
1166 /* Call AQ switch rule in AQ_MAX chunk */
1167 for (total_elem_left = num_unicast; total_elem_left > 0;
1168 total_elem_left -= elem_sent) {
1169 struct ice_aqc_sw_rules_elem *entry = r_iter;
1170
1171 elem_sent = min(total_elem_left,
1172 (u16)(ICE_AQ_MAX_BUF_LEN / s_rule_size));
1173 status = ice_aq_sw_rules(hw, entry, elem_sent * s_rule_size,
1174 elem_sent, ice_aqc_opc_add_sw_rules,
1175 NULL);
1176 if (status)
1177 goto ice_add_mac_exit;
1178 r_iter = (struct ice_aqc_sw_rules_elem *)
1179 ((u8 *)r_iter + (elem_sent * s_rule_size));
1180 }
1181
1182 /* Fill up rule id based on the value returned from FW */
1183 r_iter = s_rule;
1184 list_for_each_entry(m_list_itr, m_list, list_entry) {
1185 struct ice_fltr_info *f_info = &m_list_itr->fltr_info;
1186 u8 *addr = &f_info->l_data.mac.mac_addr[0];
1187 struct ice_switch_info *sw = hw->switch_info;
1188 struct ice_fltr_mgmt_list_entry *fm_entry;
1189
1190 if (is_unicast_ether_addr(addr)) {
1191 f_info->fltr_rule_id =
1192 le16_to_cpu(r_iter->pdata.lkup_tx_rx.index);
1193 f_info->fltr_act = ICE_FWD_TO_VSI;
1194 /* Create an entry to track this MAC address */
1195 fm_entry = devm_kzalloc(ice_hw_to_dev(hw),
1196 sizeof(*fm_entry), GFP_KERNEL);
1197 if (!fm_entry) {
1198 status = ICE_ERR_NO_MEMORY;
1199 goto ice_add_mac_exit;
1200 }
1201 fm_entry->fltr_info = *f_info;
1202 fm_entry->vsi_count = 1;
1203 /* The book keeping entries will get removed when
1204 * base driver calls remove filter AQ command
1205 */
1206 mutex_lock(&sw->mac_list_lock);
1207 list_add(&fm_entry->list_entry, &sw->mac_list_head);
1208 mutex_unlock(&sw->mac_list_lock);
1209
1210 r_iter = (struct ice_aqc_sw_rules_elem *)
1211 ((u8 *)r_iter + s_rule_size);
1212 }
1213 }
1214
1215ice_add_mac_exit:
1216 devm_kfree(ice_hw_to_dev(hw), s_rule);
1217 return status;
1218}
1219
1220/**
1221 * ice_remove_vsi_list_rule
1222 * @hw: pointer to the hardware structure
1223 * @vsi_list_id: VSI list id generated as part of allocate resource
1224 * @lkup_type: switch rule filter lookup type
1225 */
1226static enum ice_status
1227ice_remove_vsi_list_rule(struct ice_hw *hw, u16 vsi_list_id,
1228 enum ice_sw_lkup_type lkup_type)
1229{
1230 struct ice_aqc_sw_rules_elem *s_rule;
1231 enum ice_status status;
1232 u16 s_rule_size;
1233
1234 s_rule_size = (u16)ICE_SW_RULE_VSI_LIST_SIZE(0);
1235 s_rule = devm_kzalloc(ice_hw_to_dev(hw), s_rule_size, GFP_KERNEL);
1236 if (!s_rule)
1237 return ICE_ERR_NO_MEMORY;
1238
1239 s_rule->type = cpu_to_le16(ICE_AQC_SW_RULES_T_VSI_LIST_CLEAR);
1240 s_rule->pdata.vsi_list.index = cpu_to_le16(vsi_list_id);
1241 /* FW expects number of VSIs in vsi_list resource to be 0 for clear
1242 * command. Since memory is zero'ed out during initialization, it's not
1243 * necessary to explicitly initialize the variable to 0.
1244 */
1245
1246 status = ice_aq_sw_rules(hw, s_rule, s_rule_size, 1,
1247 ice_aqc_opc_remove_sw_rules, NULL);
1248 if (!status)
1249 /* Free the vsi_list resource that we allocated */
1250 status = ice_aq_alloc_free_vsi_list(hw, &vsi_list_id, lkup_type,
1251 ice_aqc_opc_free_res);
1252
1253 devm_kfree(ice_hw_to_dev(hw), s_rule);
1254 return status;
1255}
1256
1257/**
1258 * ice_handle_rem_vsi_list_mgmt
1259 * @hw: pointer to the hardware structure
1260 * @vsi_id: ID of the VSI to remove
1261 * @fm_list_itr: filter management entry for which the VSI list management
1262 * needs to be done
1263 */
1264static enum ice_status
1265ice_handle_rem_vsi_list_mgmt(struct ice_hw *hw, u16 vsi_id,
1266 struct ice_fltr_mgmt_list_entry *fm_list_itr)
1267{
1268 struct ice_switch_info *sw = hw->switch_info;
1269 enum ice_status status = 0;
1270 enum ice_sw_lkup_type lkup_type;
1271 bool is_last_elem = true;
1272 bool conv_list = false;
1273 bool del_list = false;
1274 u16 vsi_list_id;
1275
1276 lkup_type = fm_list_itr->fltr_info.lkup_type;
1277 vsi_list_id = fm_list_itr->fltr_info.fwd_id.vsi_list_id;
1278
1279 if (fm_list_itr->vsi_count > 1) {
1280 status = ice_update_vsi_list_rule(hw, &vsi_id, 1, vsi_list_id,
1281 true,
1282 ice_aqc_opc_update_sw_rules,
1283 lkup_type);
1284 if (status)
1285 return status;
1286 fm_list_itr->vsi_count--;
1287 is_last_elem = false;
1288 clear_bit(vsi_id, fm_list_itr->vsi_list_info->vsi_map);
1289 }
1290
1291 /* For non-VLAN rules that forward packets to a VSI list, convert them
1292 * to forwarding packets to a VSI if there is only one VSI left in the
1293 * list. Unused lists are then removed.
1294 * VLAN rules need to use VSI lists even with only one VSI.
1295 */
1296 if (fm_list_itr->fltr_info.fltr_act == ICE_FWD_TO_VSI_LIST) {
1297 if (lkup_type == ICE_SW_LKUP_VLAN) {
1298 del_list = is_last_elem;
1299 } else if (fm_list_itr->vsi_count == 1) {
1300 conv_list = true;
1301 del_list = true;
1302 }
1303 }
1304
1305 if (del_list) {
1306 /* Remove the VSI list since it is no longer used */
1307 struct ice_vsi_list_map_info *vsi_list_info =
1308 fm_list_itr->vsi_list_info;
1309
1310 status = ice_remove_vsi_list_rule(hw, vsi_list_id, lkup_type);
1311 if (status)
1312 return status;
1313
1314 if (conv_list) {
1315 u16 rem_vsi_id;
1316
1317 rem_vsi_id = find_first_bit(vsi_list_info->vsi_map,
1318 ICE_MAX_VSI);
1319
1320 /* Error out when the expected last element is not in
1321 * the VSI list map
1322 */
1323 if (rem_vsi_id == ICE_MAX_VSI)
1324 return ICE_ERR_OUT_OF_RANGE;
1325
1326 /* Change the list entry action from VSI_LIST to VSI */
1327 fm_list_itr->fltr_info.fltr_act = ICE_FWD_TO_VSI;
1328 fm_list_itr->fltr_info.fwd_id.vsi_id = rem_vsi_id;
1329 }
1330
1331 list_del(&vsi_list_info->list_entry);
1332 devm_kfree(ice_hw_to_dev(hw), vsi_list_info);
1333 fm_list_itr->vsi_list_info = NULL;
1334 }
1335
1336 if (conv_list) {
1337 /* Convert the rule's forward action to forwarding packets to
1338 * a VSI
1339 */
1340 struct ice_aqc_sw_rules_elem *s_rule;
1341
1342 s_rule = devm_kzalloc(ice_hw_to_dev(hw),
1343 ICE_SW_RULE_RX_TX_ETH_HDR_SIZE,
1344 GFP_KERNEL);
1345 if (!s_rule)
1346 return ICE_ERR_NO_MEMORY;
1347
1348 ice_fill_sw_rule(hw, &fm_list_itr->fltr_info, s_rule,
1349 ice_aqc_opc_update_sw_rules);
1350
1351 s_rule->pdata.lkup_tx_rx.index =
1352 cpu_to_le16(fm_list_itr->fltr_info.fltr_rule_id);
1353
1354 status = ice_aq_sw_rules(hw, s_rule,
1355 ICE_SW_RULE_RX_TX_ETH_HDR_SIZE, 1,
1356 ice_aqc_opc_update_sw_rules, NULL);
1357 devm_kfree(ice_hw_to_dev(hw), s_rule);
1358 if (status)
1359 return status;
1360 }
1361
1362 if (is_last_elem) {
1363 /* Remove the lookup rule */
1364 struct ice_aqc_sw_rules_elem *s_rule;
1365
1366 s_rule = devm_kzalloc(ice_hw_to_dev(hw),
1367 ICE_SW_RULE_RX_TX_NO_HDR_SIZE,
1368 GFP_KERNEL);
1369 if (!s_rule)
1370 return ICE_ERR_NO_MEMORY;
1371
1372 ice_fill_sw_rule(hw, &fm_list_itr->fltr_info, s_rule,
1373 ice_aqc_opc_remove_sw_rules);
1374
1375 status = ice_aq_sw_rules(hw, s_rule,
1376 ICE_SW_RULE_RX_TX_NO_HDR_SIZE, 1,
1377 ice_aqc_opc_remove_sw_rules, NULL);
1378 if (status)
1379 return status;
1380
1381 /* Remove a book keeping entry from the MAC address list */
1382 mutex_lock(&sw->mac_list_lock);
1383 list_del(&fm_list_itr->list_entry);
1384 mutex_unlock(&sw->mac_list_lock);
1385 devm_kfree(ice_hw_to_dev(hw), fm_list_itr);
1386 devm_kfree(ice_hw_to_dev(hw), s_rule);
1387 }
1388 return status;
1389}
1390
1391/**
1392 * ice_remove_mac_entry
1393 * @hw: pointer to the hardware structure
1394 * @f_entry: structure containing MAC forwarding information
1395 */
1396static enum ice_status
1397ice_remove_mac_entry(struct ice_hw *hw, struct ice_fltr_list_entry *f_entry)
1398{
1399 struct ice_fltr_mgmt_list_entry *m_entry;
1400 u16 vsi_id;
1401 u8 *add;
1402
1403 add = &f_entry->fltr_info.l_data.mac.mac_addr[0];
1404
1405 m_entry = ice_find_mac_entry(hw, add);
1406 if (!m_entry)
1407 return ICE_ERR_PARAM;
1408
1409 vsi_id = f_entry->fltr_info.fwd_id.vsi_id;
1410 return ice_handle_rem_vsi_list_mgmt(hw, vsi_id, m_entry);
1411}
1412
1413/**
1414 * ice_remove_mac - remove a MAC address based filter rule
1415 * @hw: pointer to the hardware structure
1416 * @m_list: list of MAC addresses and forwarding information
1417 *
1418 * This function removes either a MAC filter rule or a specific VSI from a
1419 * VSI list for a multicast MAC address.
1420 *
1421 * Returns ICE_ERR_DOES_NOT_EXIST if a given entry was not added by
1422 * ice_add_mac. Caller should be aware that this call will only work if all
1423 * the entries passed into m_list were added previously. It will not attempt to
1424 * do a partial remove of entries that were found.
1425 */
1426enum ice_status
1427ice_remove_mac(struct ice_hw *hw, struct list_head *m_list)
1428{
1429 struct ice_aqc_sw_rules_elem *s_rule, *r_iter;
1430 u8 s_rule_size = ICE_SW_RULE_RX_TX_NO_HDR_SIZE;
1431 struct ice_switch_info *sw = hw->switch_info;
1432 struct ice_fltr_mgmt_list_entry *m_entry;
1433 struct ice_fltr_list_entry *m_list_itr;
1434 u16 elem_sent, total_elem_left;
1435 enum ice_status status = 0;
1436 u16 num_unicast = 0;
1437
1438 if (!m_list)
1439 return ICE_ERR_PARAM;
1440
1441 list_for_each_entry(m_list_itr, m_list, list_entry) {
1442 u8 *addr = m_list_itr->fltr_info.l_data.mac.mac_addr;
1443
1444 if (is_unicast_ether_addr(addr) && !hw->ucast_shared)
1445 num_unicast++;
1446 else if (is_multicast_ether_addr(addr) ||
1447 (is_unicast_ether_addr(addr) && hw->ucast_shared))
1448 ice_remove_mac_entry(hw, m_list_itr);
1449 }
1450
1451 /* Exit if no unicast addresses found. Multicast switch rules
1452 * were added individually
1453 */
1454 if (!num_unicast)
1455 return 0;
1456
1457 /* Allocate switch rule buffer for the bulk update for unicast */
1458 s_rule = devm_kcalloc(ice_hw_to_dev(hw), num_unicast, s_rule_size,
1459 GFP_KERNEL);
1460 if (!s_rule)
1461 return ICE_ERR_NO_MEMORY;
1462
1463 r_iter = s_rule;
1464 list_for_each_entry(m_list_itr, m_list, list_entry) {
1465 u8 *addr = m_list_itr->fltr_info.l_data.mac.mac_addr;
1466
1467 if (is_unicast_ether_addr(addr)) {
1468 m_entry = ice_find_mac_entry(hw, addr);
1469 if (!m_entry) {
1470 status = ICE_ERR_DOES_NOT_EXIST;
1471 goto ice_remove_mac_exit;
1472 }
1473
1474 ice_fill_sw_rule(hw, &m_entry->fltr_info,
1475 r_iter, ice_aqc_opc_remove_sw_rules);
1476 r_iter = (struct ice_aqc_sw_rules_elem *)
1477 ((u8 *)r_iter + s_rule_size);
1478 }
1479 }
1480
1481 /* Call AQ bulk switch rule update for all unicast addresses */
1482 r_iter = s_rule;
1483 /* Call AQ switch rule in AQ_MAX chunk */
1484 for (total_elem_left = num_unicast; total_elem_left > 0;
1485 total_elem_left -= elem_sent) {
1486 struct ice_aqc_sw_rules_elem *entry = r_iter;
1487
1488 elem_sent = min(total_elem_left,
1489 (u16)(ICE_AQ_MAX_BUF_LEN / s_rule_size));
1490 status = ice_aq_sw_rules(hw, entry, elem_sent * s_rule_size,
1491 elem_sent, ice_aqc_opc_remove_sw_rules,
1492 NULL);
1493 if (status)
1494 break;
1495 r_iter = (struct ice_aqc_sw_rules_elem *)
1496 ((u8 *)r_iter + s_rule_size);
1497 }
1498
1499 list_for_each_entry(m_list_itr, m_list, list_entry) {
1500 u8 *addr = m_list_itr->fltr_info.l_data.mac.mac_addr;
1501
1502 if (is_unicast_ether_addr(addr)) {
1503 m_entry = ice_find_mac_entry(hw, addr);
1504 if (!m_entry)
1505 return ICE_ERR_OUT_OF_RANGE;
1506 mutex_lock(&sw->mac_list_lock);
1507 list_del(&m_entry->list_entry);
1508 mutex_unlock(&sw->mac_list_lock);
1509 devm_kfree(ice_hw_to_dev(hw), m_entry);
1510 }
1511 }
1512
1513ice_remove_mac_exit:
1514 devm_kfree(ice_hw_to_dev(hw), s_rule);
1515 return status;
1516}
1517
1518/**
1519 * ice_add_to_vsi_fltr_list - Add VSI filters to the list
1520 * @hw: pointer to the hardware structure
1521 * @vsi_id: ID of VSI to remove filters from
1522 * @lkup_list_head: pointer to the list that has certain lookup type filters
1523 * @vsi_list_head: pointer to the list pertaining to VSI with vsi_id
1524 */
1525static enum ice_status
1526ice_add_to_vsi_fltr_list(struct ice_hw *hw, u16 vsi_id,
1527 struct list_head *lkup_list_head,
1528 struct list_head *vsi_list_head)
1529{
1530 struct ice_fltr_mgmt_list_entry *fm_entry;
1531
1532 /* check to make sure VSI id is valid and within boundary */
1533 if (vsi_id >=
1534 (sizeof(fm_entry->vsi_list_info->vsi_map) * BITS_PER_BYTE - 1))
1535 return ICE_ERR_PARAM;
1536
1537 list_for_each_entry(fm_entry, lkup_list_head, list_entry) {
1538 struct ice_fltr_info *fi;
1539
1540 fi = &fm_entry->fltr_info;
1541 if ((fi->fltr_act == ICE_FWD_TO_VSI &&
1542 fi->fwd_id.vsi_id == vsi_id) ||
1543 (fi->fltr_act == ICE_FWD_TO_VSI_LIST &&
1544 (test_bit(vsi_id, fm_entry->vsi_list_info->vsi_map)))) {
1545 struct ice_fltr_list_entry *tmp;
1546
1547 /* this memory is freed up in the caller function
1548 * ice_remove_vsi_lkup_fltr() once filters for
1549 * this VSI are removed
1550 */
1551 tmp = devm_kzalloc(ice_hw_to_dev(hw), sizeof(*tmp),
1552 GFP_KERNEL);
1553 if (!tmp)
1554 return ICE_ERR_NO_MEMORY;
1555
1556 memcpy(&tmp->fltr_info, fi, sizeof(*fi));
1557
1558 /* Expected below fields to be set to ICE_FWD_TO_VSI and
1559 * the particular VSI id since we are only removing this
1560 * one VSI
1561 */
1562 if (fi->fltr_act == ICE_FWD_TO_VSI_LIST) {
1563 tmp->fltr_info.fltr_act = ICE_FWD_TO_VSI;
1564 tmp->fltr_info.fwd_id.vsi_id = vsi_id;
1565 }
1566
1567 list_add(&tmp->list_entry, vsi_list_head);
1568 }
1569 }
1570 return 0;
1571}
1572
1573/**
1574 * ice_remove_vsi_lkup_fltr - Remove lookup type filters for a VSI
1575 * @hw: pointer to the hardware structure
1576 * @vsi_id: ID of VSI to remove filters from
1577 * @lkup: switch rule filter lookup type
1578 */
1579static void
1580ice_remove_vsi_lkup_fltr(struct ice_hw *hw, u16 vsi_id,
1581 enum ice_sw_lkup_type lkup)
1582{
1583 struct ice_switch_info *sw = hw->switch_info;
1584 struct ice_fltr_list_entry *fm_entry;
1585 struct list_head remove_list_head;
1586 struct ice_fltr_list_entry *tmp;
1587 enum ice_status status;
1588
1589 INIT_LIST_HEAD(&remove_list_head);
1590 switch (lkup) {
1591 case ICE_SW_LKUP_MAC:
1592 mutex_lock(&sw->mac_list_lock);
1593 status = ice_add_to_vsi_fltr_list(hw, vsi_id,
1594 &sw->mac_list_head,
1595 &remove_list_head);
1596 mutex_unlock(&sw->mac_list_lock);
1597 if (!status) {
1598 ice_remove_mac(hw, &remove_list_head);
1599 goto free_fltr_list;
1600 }
1601 break;
1602 case ICE_SW_LKUP_VLAN:
1603 case ICE_SW_LKUP_MAC_VLAN:
1604 case ICE_SW_LKUP_ETHERTYPE:
1605 case ICE_SW_LKUP_ETHERTYPE_MAC:
1606 case ICE_SW_LKUP_PROMISC:
1607 case ICE_SW_LKUP_PROMISC_VLAN:
1608 case ICE_SW_LKUP_DFLT:
1609 ice_debug(hw, ICE_DBG_SW,
1610 "Remove filters for this lookup type hasn't been implemented yet\n");
1611 break;
1612 }
1613
1614 return;
1615free_fltr_list:
1616 list_for_each_entry_safe(fm_entry, tmp, &remove_list_head, list_entry) {
1617 list_del(&fm_entry->list_entry);
1618 devm_kfree(ice_hw_to_dev(hw), fm_entry);
1619 }
1620}
1621
1622/**
1623 * ice_remove_vsi_fltr - Remove all filters for a VSI
1624 * @hw: pointer to the hardware structure
1625 * @vsi_id: ID of VSI to remove filters from
1626 */
1627void ice_remove_vsi_fltr(struct ice_hw *hw, u16 vsi_id)
1628{
1629 ice_remove_vsi_lkup_fltr(hw, vsi_id, ICE_SW_LKUP_MAC);
1630 ice_remove_vsi_lkup_fltr(hw, vsi_id, ICE_SW_LKUP_MAC_VLAN);
1631 ice_remove_vsi_lkup_fltr(hw, vsi_id, ICE_SW_LKUP_PROMISC);
1632 ice_remove_vsi_lkup_fltr(hw, vsi_id, ICE_SW_LKUP_VLAN);
1633 ice_remove_vsi_lkup_fltr(hw, vsi_id, ICE_SW_LKUP_DFLT);
1634 ice_remove_vsi_lkup_fltr(hw, vsi_id, ICE_SW_LKUP_ETHERTYPE);
1635 ice_remove_vsi_lkup_fltr(hw, vsi_id, ICE_SW_LKUP_ETHERTYPE_MAC);
1636 ice_remove_vsi_lkup_fltr(hw, vsi_id, ICE_SW_LKUP_PROMISC_VLAN);
1637}
diff --git a/drivers/net/ethernet/intel/ice/ice_switch.h b/drivers/net/ethernet/intel/ice/ice_switch.h
index bb8612d8e07b..1b312e7ab2b5 100644
--- a/drivers/net/ethernet/intel/ice/ice_switch.h
+++ b/drivers/net/ethernet/intel/ice/ice_switch.h
@@ -19,6 +19,122 @@ struct ice_vsi_ctx {
19 bool alloc_from_pool; 19 bool alloc_from_pool;
20}; 20};
21 21
22enum ice_sw_fwd_act_type {
23 ICE_FWD_TO_VSI = 0,
24 ICE_FWD_TO_VSI_LIST, /* Do not use this when adding filter */
25 ICE_FWD_TO_Q,
26 ICE_FWD_TO_QGRP,
27 ICE_DROP_PACKET,
28 ICE_INVAL_ACT
29};
30
31/* Switch recipe ID enum values are specific to hardware */
32enum ice_sw_lkup_type {
33 ICE_SW_LKUP_ETHERTYPE = 0,
34 ICE_SW_LKUP_MAC = 1,
35 ICE_SW_LKUP_MAC_VLAN = 2,
36 ICE_SW_LKUP_PROMISC = 3,
37 ICE_SW_LKUP_VLAN = 4,
38 ICE_SW_LKUP_DFLT = 5,
39 ICE_SW_LKUP_ETHERTYPE_MAC = 8,
40 ICE_SW_LKUP_PROMISC_VLAN = 9,
41};
42
43struct ice_fltr_info {
44 /* Look up information: how to look up packet */
45 enum ice_sw_lkup_type lkup_type;
46 /* Forward action: filter action to do after lookup */
47 enum ice_sw_fwd_act_type fltr_act;
48 /* rule ID returned by firmware once filter rule is created */
49 u16 fltr_rule_id;
50 u16 flag;
51#define ICE_FLTR_RX BIT(0)
52#define ICE_FLTR_TX BIT(1)
53#define ICE_FLTR_TX_RX (ICE_FLTR_RX | ICE_FLTR_TX)
54
55 /* Source VSI for LOOKUP_TX or source port for LOOKUP_RX */
56 u16 src;
57
58 union {
59 struct {
60 u8 mac_addr[ETH_ALEN];
61 } mac;
62 struct {
63 u8 mac_addr[ETH_ALEN];
64 u16 vlan_id;
65 } mac_vlan;
66 struct {
67 u16 vlan_id;
68 } vlan;
69 /* Set lkup_type as ICE_SW_LKUP_ETHERTYPE
70 * if just using ethertype as filter. Set lkup_type as
71 * ICE_SW_LKUP_ETHERTYPE_MAC if MAC also needs to be
72 * passed in as filter.
73 */
74 struct {
75 u16 ethertype;
76 u8 mac_addr[ETH_ALEN]; /* optional */
77 } ethertype_mac;
78 } l_data;
79
80 /* Depending on filter action */
81 union {
82 /* queue id in case of ICE_FWD_TO_Q and starting
83 * queue id in case of ICE_FWD_TO_QGRP.
84 */
85 u16 q_id:11;
86 u16 vsi_id:10;
87 u16 vsi_list_id:10;
88 } fwd_id;
89
90 /* Set to num_queues if action is ICE_FWD_TO_QGRP. This field
91 * determines the range of queues the packet needs to be forwarded to
92 */
93 u8 qgrp_size;
94
95 /* Rule creations populate these indicators basing on the switch type */
96 bool lb_en; /* Indicate if packet can be looped back */
97 bool lan_en; /* Indicate if packet can be forwarded to the uplink */
98};
99
100/* Bookkeeping structure to hold bitmap of VSIs corresponding to VSI list id */
101struct ice_vsi_list_map_info {
102 struct list_head list_entry;
103 DECLARE_BITMAP(vsi_map, ICE_MAX_VSI);
104 u16 vsi_list_id;
105};
106
107enum ice_sw_fltr_status {
108 ICE_FLTR_STATUS_NEW = 0,
109 ICE_FLTR_STATUS_FW_SUCCESS,
110 ICE_FLTR_STATUS_FW_FAIL,
111};
112
113struct ice_fltr_list_entry {
114 struct list_head list_entry;
115 enum ice_sw_fltr_status status;
116 struct ice_fltr_info fltr_info;
117};
118
119/* This defines an entry in the list that maintains MAC or VLAN membership
120 * to HW list mapping, since multiple VSIs can subscribe to the same MAC or
121 * VLAN. As an optimization the VSI list should be created only when a
122 * second VSI becomes a subscriber to the VLAN address.
123 */
124struct ice_fltr_mgmt_list_entry {
125 /* back pointer to VSI list id to VSI list mapping */
126 struct ice_vsi_list_map_info *vsi_list_info;
127 u16 vsi_count;
128#define ICE_INVAL_LG_ACT_INDEX 0xffff
129 u16 lg_act_idx;
130#define ICE_INVAL_SW_MARKER_ID 0xffff
131 u16 sw_marker_id;
132 struct list_head list_entry;
133 struct ice_fltr_info fltr_info;
134#define ICE_INVAL_COUNTER_ID 0xff
135 u8 counter_index;
136};
137
22/* VSI related commands */ 138/* VSI related commands */
23enum ice_status 139enum ice_status
24ice_aq_add_vsi(struct ice_hw *hw, struct ice_vsi_ctx *vsi_ctx, 140ice_aq_add_vsi(struct ice_hw *hw, struct ice_vsi_ctx *vsi_ctx,
@@ -32,4 +148,8 @@ ice_aq_free_vsi(struct ice_hw *hw, struct ice_vsi_ctx *vsi_ctx,
32 148
33enum ice_status ice_get_initial_sw_cfg(struct ice_hw *hw); 149enum ice_status ice_get_initial_sw_cfg(struct ice_hw *hw);
34 150
151/* Switch/bridge related commands */
152enum ice_status ice_add_mac(struct ice_hw *hw, struct list_head *m_lst);
153enum ice_status ice_remove_mac(struct ice_hw *hw, struct list_head *m_lst);
154void ice_remove_vsi_fltr(struct ice_hw *hw, u16 vsi_id);
35#endif /* _ICE_SWITCH_H_ */ 155#endif /* _ICE_SWITCH_H_ */
diff --git a/drivers/net/ethernet/intel/ice/ice_type.h b/drivers/net/ethernet/intel/ice/ice_type.h
index 5f58fd84d558..8926715b76ee 100644
--- a/drivers/net/ethernet/intel/ice/ice_type.h
+++ b/drivers/net/ethernet/intel/ice/ice_type.h
@@ -223,6 +223,22 @@ struct ice_port_info {
223 bool is_vf; 223 bool is_vf;
224}; 224};
225 225
226struct ice_switch_info {
227 /* Switch VSI lists to MAC/VLAN translation */
228 struct mutex mac_list_lock; /* protect MAC list */
229 struct list_head mac_list_head;
230 struct mutex vlan_list_lock; /* protect VLAN list */
231 struct list_head vlan_list_head;
232 struct mutex eth_m_list_lock; /* protect ethtype list */
233 struct list_head eth_m_list_head;
234 struct mutex promisc_list_lock; /* protect promisc mode list */
235 struct list_head promisc_list_head;
236 struct mutex mac_vlan_list_lock; /* protect MAC-VLAN list */
237 struct list_head mac_vlan_list_head;
238
239 struct list_head vsi_list_map_head;
240};
241
226/* Port hardware description */ 242/* Port hardware description */
227struct ice_hw { 243struct ice_hw {
228 u8 __iomem *hw_addr; 244 u8 __iomem *hw_addr;
@@ -248,11 +264,14 @@ struct ice_hw {
248 u8 max_cgds; 264 u8 max_cgds;
249 u8 sw_entry_point_layer; 265 u8 sw_entry_point_layer;
250 266
267 bool evb_veb; /* true for VEB, false for VEPA */
251 struct ice_bus_info bus; 268 struct ice_bus_info bus;
252 struct ice_nvm_info nvm; 269 struct ice_nvm_info nvm;
253 struct ice_hw_dev_caps dev_caps; /* device capabilities */ 270 struct ice_hw_dev_caps dev_caps; /* device capabilities */
254 struct ice_hw_func_caps func_caps; /* function capabilities */ 271 struct ice_hw_func_caps func_caps; /* function capabilities */
255 272
273 struct ice_switch_info *switch_info; /* switch filter lists */
274
256 /* Control Queue info */ 275 /* Control Queue info */
257 struct ice_ctl_q_info adminq; 276 struct ice_ctl_q_info adminq;
258 277
@@ -276,6 +295,8 @@ struct ice_hw {
276 u8 itr_gran_100; 295 u8 itr_gran_100;
277 u8 itr_gran_50; 296 u8 itr_gran_50;
278 u8 itr_gran_25; 297 u8 itr_gran_25;
298 bool ucast_shared; /* true if VSIs can share unicast addr */
299
279}; 300};
280 301
281/* Checksum and Shadow RAM pointers */ 302/* Checksum and Shadow RAM pointers */