mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2025-01-18 14:56:19 +07:00
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>
This commit is contained in:
parent
3a858ba392
commit
9daf8208dd
@ -8,6 +8,7 @@
|
||||
* descriptor format. It is shared between Firmware and Software.
|
||||
*/
|
||||
|
||||
#define ICE_MAX_VSI 768
|
||||
#define ICE_AQC_TOPO_MAX_LEVEL_NUM 0x9
|
||||
#define ICE_AQ_SET_MAC_FRAME_SIZE_MAX 9728
|
||||
|
||||
@ -191,6 +192,46 @@ struct ice_aqc_get_sw_cfg_resp {
|
||||
struct ice_aqc_get_sw_cfg_resp_elem elements[1];
|
||||
};
|
||||
|
||||
/* These resource type defines are used for all switch resource
|
||||
* commands where a resource type is required, such as:
|
||||
* Get Resource Allocation command (indirect 0x0204)
|
||||
* Allocate Resources command (indirect 0x0208)
|
||||
* Free Resources command (indirect 0x0209)
|
||||
* Get Allocated Resource Descriptors Command (indirect 0x020A)
|
||||
*/
|
||||
#define ICE_AQC_RES_TYPE_VSI_LIST_REP 0x03
|
||||
#define ICE_AQC_RES_TYPE_VSI_LIST_PRUNE 0x04
|
||||
|
||||
/* Allocate Resources command (indirect 0x0208)
|
||||
* Free Resources command (indirect 0x0209)
|
||||
*/
|
||||
struct ice_aqc_alloc_free_res_cmd {
|
||||
__le16 num_entries; /* Number of Resource entries */
|
||||
u8 reserved[6];
|
||||
__le32 addr_high;
|
||||
__le32 addr_low;
|
||||
};
|
||||
|
||||
/* Resource descriptor */
|
||||
struct ice_aqc_res_elem {
|
||||
union {
|
||||
__le16 sw_resp;
|
||||
__le16 flu_resp;
|
||||
} e;
|
||||
};
|
||||
|
||||
/* Buffer for Allocate/Free Resources commands */
|
||||
struct ice_aqc_alloc_free_res_elem {
|
||||
__le16 res_type; /* Types defined above cmd 0x0204 */
|
||||
#define ICE_AQC_RES_TYPE_SHARED_S 7
|
||||
#define ICE_AQC_RES_TYPE_SHARED_M (0x1 << ICE_AQC_RES_TYPE_SHARED_S)
|
||||
#define ICE_AQC_RES_TYPE_VSI_PRUNE_LIST_S 8
|
||||
#define ICE_AQC_RES_TYPE_VSI_PRUNE_LIST_M \
|
||||
(0xF << ICE_AQC_RES_TYPE_VSI_PRUNE_LIST_S)
|
||||
__le16 num_elems;
|
||||
struct ice_aqc_res_elem elem[1];
|
||||
};
|
||||
|
||||
/* Add VSI (indirect 0x0210)
|
||||
* Update VSI (indirect 0x0211)
|
||||
* Get VSI (indirect 0x0212)
|
||||
@ -384,6 +425,202 @@ struct ice_aqc_vsi_props {
|
||||
u8 reserved[24];
|
||||
};
|
||||
|
||||
/* Add/Update/Remove/Get switch rules (indirect 0x02A0, 0x02A1, 0x02A2, 0x02A3)
|
||||
*/
|
||||
struct ice_aqc_sw_rules {
|
||||
/* ops: add switch rules, referring the number of rules.
|
||||
* ops: update switch rules, referring the number of filters
|
||||
* ops: remove switch rules, referring the entry index.
|
||||
* ops: get switch rules, referring to the number of filters.
|
||||
*/
|
||||
__le16 num_rules_fltr_entry_index;
|
||||
u8 reserved[6];
|
||||
__le32 addr_high;
|
||||
__le32 addr_low;
|
||||
};
|
||||
|
||||
/* Add/Update/Get/Remove lookup Rx/Tx command/response entry
|
||||
* This structures describes the lookup rules and associated actions. "index"
|
||||
* is returned as part of a response to a successful Add command, and can be
|
||||
* used to identify the rule for Update/Get/Remove commands.
|
||||
*/
|
||||
struct ice_sw_rule_lkup_rx_tx {
|
||||
__le16 recipe_id;
|
||||
#define ICE_SW_RECIPE_LOGICAL_PORT_FWD 10
|
||||
/* Source port for LOOKUP_RX and source VSI in case of LOOKUP_TX */
|
||||
__le16 src;
|
||||
__le32 act;
|
||||
|
||||
/* Bit 0:1 - Action type */
|
||||
#define ICE_SINGLE_ACT_TYPE_S 0x00
|
||||
#define ICE_SINGLE_ACT_TYPE_M (0x3 << ICE_SINGLE_ACT_TYPE_S)
|
||||
|
||||
/* Bit 2 - Loop back enable
|
||||
* Bit 3 - LAN enable
|
||||
*/
|
||||
#define ICE_SINGLE_ACT_LB_ENABLE BIT(2)
|
||||
#define ICE_SINGLE_ACT_LAN_ENABLE BIT(3)
|
||||
|
||||
/* Action type = 0 - Forward to VSI or VSI list */
|
||||
#define ICE_SINGLE_ACT_VSI_FORWARDING 0x0
|
||||
|
||||
#define ICE_SINGLE_ACT_VSI_ID_S 4
|
||||
#define ICE_SINGLE_ACT_VSI_ID_M (0x3FF << ICE_SINGLE_ACT_VSI_ID_S)
|
||||
#define ICE_SINGLE_ACT_VSI_LIST_ID_S 4
|
||||
#define ICE_SINGLE_ACT_VSI_LIST_ID_M (0x3FF << ICE_SINGLE_ACT_VSI_LIST_ID_S)
|
||||
/* This bit needs to be set if action is forward to VSI list */
|
||||
#define ICE_SINGLE_ACT_VSI_LIST BIT(14)
|
||||
#define ICE_SINGLE_ACT_VALID_BIT BIT(17)
|
||||
#define ICE_SINGLE_ACT_DROP BIT(18)
|
||||
|
||||
/* Action type = 1 - Forward to Queue of Queue group */
|
||||
#define ICE_SINGLE_ACT_TO_Q 0x1
|
||||
#define ICE_SINGLE_ACT_Q_INDEX_S 4
|
||||
#define ICE_SINGLE_ACT_Q_INDEX_M (0x7FF << ICE_SINGLE_ACT_Q_INDEX_S)
|
||||
#define ICE_SINGLE_ACT_Q_REGION_S 15
|
||||
#define ICE_SINGLE_ACT_Q_REGION_M (0x7 << ICE_SINGLE_ACT_Q_REGION_S)
|
||||
#define ICE_SINGLE_ACT_Q_PRIORITY BIT(18)
|
||||
|
||||
/* Action type = 2 - Prune */
|
||||
#define ICE_SINGLE_ACT_PRUNE 0x2
|
||||
#define ICE_SINGLE_ACT_EGRESS BIT(15)
|
||||
#define ICE_SINGLE_ACT_INGRESS BIT(16)
|
||||
#define ICE_SINGLE_ACT_PRUNET BIT(17)
|
||||
/* Bit 18 should be set to 0 for this action */
|
||||
|
||||
/* Action type = 2 - Pointer */
|
||||
#define ICE_SINGLE_ACT_PTR 0x2
|
||||
#define ICE_SINGLE_ACT_PTR_VAL_S 4
|
||||
#define ICE_SINGLE_ACT_PTR_VAL_M (0x1FFF << ICE_SINGLE_ACT_PTR_VAL_S)
|
||||
/* Bit 18 should be set to 1 */
|
||||
#define ICE_SINGLE_ACT_PTR_BIT BIT(18)
|
||||
|
||||
/* Action type = 3 - Other actions. Last two bits
|
||||
* are other action identifier
|
||||
*/
|
||||
#define ICE_SINGLE_ACT_OTHER_ACTS 0x3
|
||||
#define ICE_SINGLE_OTHER_ACT_IDENTIFIER_S 17
|
||||
#define ICE_SINGLE_OTHER_ACT_IDENTIFIER_M \
|
||||
(0x3 << \ ICE_SINGLE_OTHER_ACT_IDENTIFIER_S)
|
||||
|
||||
/* Bit 17:18 - Defines other actions */
|
||||
/* Other action = 0 - Mirror VSI */
|
||||
#define ICE_SINGLE_OTHER_ACT_MIRROR 0
|
||||
#define ICE_SINGLE_ACT_MIRROR_VSI_ID_S 4
|
||||
#define ICE_SINGLE_ACT_MIRROR_VSI_ID_M \
|
||||
(0x3FF << ICE_SINGLE_ACT_MIRROR_VSI_ID_S)
|
||||
|
||||
/* Other action = 3 - Set Stat count */
|
||||
#define ICE_SINGLE_OTHER_ACT_STAT_COUNT 3
|
||||
#define ICE_SINGLE_ACT_STAT_COUNT_INDEX_S 4
|
||||
#define ICE_SINGLE_ACT_STAT_COUNT_INDEX_M \
|
||||
(0x7F << ICE_SINGLE_ACT_STAT_COUNT_INDEX_S)
|
||||
|
||||
__le16 index; /* The index of the rule in the lookup table */
|
||||
/* Length and values of the header to be matched per recipe or
|
||||
* lookup-type
|
||||
*/
|
||||
__le16 hdr_len;
|
||||
u8 hdr[1];
|
||||
} __packed;
|
||||
|
||||
/* Add/Update/Remove large action command/response entry
|
||||
* "index" is returned as part of a response to a successful Add command, and
|
||||
* can be used to identify the action for Update/Get/Remove commands.
|
||||
*/
|
||||
struct ice_sw_rule_lg_act {
|
||||
__le16 index; /* Index in large action table */
|
||||
__le16 size;
|
||||
__le32 act[1]; /* array of size for actions */
|
||||
/* Max number of large actions */
|
||||
#define ICE_MAX_LG_ACT 4
|
||||
/* Bit 0:1 - Action type */
|
||||
#define ICE_LG_ACT_TYPE_S 0
|
||||
#define ICE_LG_ACT_TYPE_M (0x7 << ICE_LG_ACT_TYPE_S)
|
||||
|
||||
/* Action type = 0 - Forward to VSI or VSI list */
|
||||
#define ICE_LG_ACT_VSI_FORWARDING 0
|
||||
#define ICE_LG_ACT_VSI_ID_S 3
|
||||
#define ICE_LG_ACT_VSI_ID_M (0x3FF << ICE_LG_ACT_VSI_ID_S)
|
||||
#define ICE_LG_ACT_VSI_LIST_ID_S 3
|
||||
#define ICE_LG_ACT_VSI_LIST_ID_M (0x3FF << ICE_LG_ACT_VSI_LIST_ID_S)
|
||||
/* This bit needs to be set if action is forward to VSI list */
|
||||
#define ICE_LG_ACT_VSI_LIST BIT(13)
|
||||
|
||||
#define ICE_LG_ACT_VALID_BIT BIT(16)
|
||||
|
||||
/* Action type = 1 - Forward to Queue of Queue group */
|
||||
#define ICE_LG_ACT_TO_Q 0x1
|
||||
#define ICE_LG_ACT_Q_INDEX_S 3
|
||||
#define ICE_LG_ACT_Q_INDEX_M (0x7FF << ICE_LG_ACT_Q_INDEX_S)
|
||||
#define ICE_LG_ACT_Q_REGION_S 14
|
||||
#define ICE_LG_ACT_Q_REGION_M (0x7 << ICE_LG_ACT_Q_REGION_S)
|
||||
#define ICE_LG_ACT_Q_PRIORITY_SET BIT(17)
|
||||
|
||||
/* Action type = 2 - Prune */
|
||||
#define ICE_LG_ACT_PRUNE 0x2
|
||||
#define ICE_LG_ACT_EGRESS BIT(14)
|
||||
#define ICE_LG_ACT_INGRESS BIT(15)
|
||||
#define ICE_LG_ACT_PRUNET BIT(16)
|
||||
|
||||
/* Action type = 3 - Mirror VSI */
|
||||
#define ICE_LG_OTHER_ACT_MIRROR 0x3
|
||||
#define ICE_LG_ACT_MIRROR_VSI_ID_S 3
|
||||
#define ICE_LG_ACT_MIRROR_VSI_ID_M (0x3FF << ICE_LG_ACT_MIRROR_VSI_ID_S)
|
||||
|
||||
/* Action type = 5 - Large Action */
|
||||
#define ICE_LG_ACT_GENERIC 0x5
|
||||
#define ICE_LG_ACT_GENERIC_VALUE_S 3
|
||||
#define ICE_LG_ACT_GENERIC_VALUE_M (0xFFFF << ICE_LG_ACT_GENERIC_VALUE_S)
|
||||
#define ICE_LG_ACT_GENERIC_OFFSET_S 19
|
||||
#define ICE_LG_ACT_GENERIC_OFFSET_M (0x7 << ICE_LG_ACT_GENERIC_OFFSET_S)
|
||||
#define ICE_LG_ACT_GENERIC_PRIORITY_S 22
|
||||
#define ICE_LG_ACT_GENERIC_PRIORITY_M (0x7 << ICE_LG_ACT_GENERIC_PRIORITY_S)
|
||||
|
||||
/* Action = 7 - Set Stat count */
|
||||
#define ICE_LG_ACT_STAT_COUNT 0x7
|
||||
#define ICE_LG_ACT_STAT_COUNT_S 3
|
||||
#define ICE_LG_ACT_STAT_COUNT_M (0x7F << ICE_LG_ACT_STAT_COUNT_S)
|
||||
};
|
||||
|
||||
/* Add/Update/Remove VSI list command/response entry
|
||||
* "index" is returned as part of a response to a successful Add command, and
|
||||
* can be used to identify the VSI list for Update/Get/Remove commands.
|
||||
*/
|
||||
struct ice_sw_rule_vsi_list {
|
||||
__le16 index; /* Index of VSI/Prune list */
|
||||
__le16 number_vsi;
|
||||
__le16 vsi[1]; /* Array of number_vsi VSI numbers */
|
||||
};
|
||||
|
||||
/* Query VSI list command/response entry */
|
||||
struct ice_sw_rule_vsi_list_query {
|
||||
__le16 index;
|
||||
DECLARE_BITMAP(vsi_list, ICE_MAX_VSI);
|
||||
} __packed;
|
||||
|
||||
/* Add switch rule response:
|
||||
* Content of return buffer is same as the input buffer. The status field and
|
||||
* LUT index are updated as part of the response
|
||||
*/
|
||||
struct ice_aqc_sw_rules_elem {
|
||||
__le16 type; /* Switch rule type, one of T_... */
|
||||
#define ICE_AQC_SW_RULES_T_LKUP_RX 0x0
|
||||
#define ICE_AQC_SW_RULES_T_LKUP_TX 0x1
|
||||
#define ICE_AQC_SW_RULES_T_LG_ACT 0x2
|
||||
#define ICE_AQC_SW_RULES_T_VSI_LIST_SET 0x3
|
||||
#define ICE_AQC_SW_RULES_T_VSI_LIST_CLEAR 0x4
|
||||
#define ICE_AQC_SW_RULES_T_PRUNE_LIST_SET 0x5
|
||||
#define ICE_AQC_SW_RULES_T_PRUNE_LIST_CLEAR 0x6
|
||||
__le16 status;
|
||||
union {
|
||||
struct ice_sw_rule_lkup_rx_tx lkup_tx_rx;
|
||||
struct ice_sw_rule_lg_act lg_act;
|
||||
struct ice_sw_rule_vsi_list vsi_list;
|
||||
struct ice_sw_rule_vsi_list_query vsi_list_query;
|
||||
} __packed pdata;
|
||||
};
|
||||
|
||||
/* Get Default Topology (indirect 0x0400) */
|
||||
struct ice_aqc_get_topo {
|
||||
u8 port_num;
|
||||
@ -766,11 +1003,13 @@ struct ice_aq_desc {
|
||||
struct ice_aqc_list_caps get_cap;
|
||||
struct ice_aqc_get_phy_caps get_phy;
|
||||
struct ice_aqc_get_sw_cfg get_sw_conf;
|
||||
struct ice_aqc_sw_rules sw_rules;
|
||||
struct ice_aqc_get_topo get_topo;
|
||||
struct ice_aqc_query_txsched_res query_sched_res;
|
||||
struct ice_aqc_add_move_delete_elem add_move_delete_elem;
|
||||
struct ice_aqc_nvm nvm;
|
||||
struct ice_aqc_add_get_update_free_vsi vsi_cmd;
|
||||
struct ice_aqc_alloc_free_res_cmd sw_res_ctrl;
|
||||
struct ice_aqc_get_link_status get_link_status;
|
||||
} params;
|
||||
};
|
||||
@ -821,10 +1060,20 @@ enum ice_adminq_opc {
|
||||
/* internal switch commands */
|
||||
ice_aqc_opc_get_sw_cfg = 0x0200,
|
||||
|
||||
/* Alloc/Free/Get Resources */
|
||||
ice_aqc_opc_alloc_res = 0x0208,
|
||||
ice_aqc_opc_free_res = 0x0209,
|
||||
|
||||
/* VSI commands */
|
||||
ice_aqc_opc_add_vsi = 0x0210,
|
||||
ice_aqc_opc_update_vsi = 0x0211,
|
||||
ice_aqc_opc_free_vsi = 0x0213,
|
||||
|
||||
/* switch rules population commands */
|
||||
ice_aqc_opc_add_sw_rules = 0x02A0,
|
||||
ice_aqc_opc_update_sw_rules = 0x02A1,
|
||||
ice_aqc_opc_remove_sw_rules = 0x02A2,
|
||||
|
||||
ice_aqc_opc_clear_pf_cfg = 0x02A4,
|
||||
|
||||
/* transmit scheduler commands */
|
||||
|
@ -258,6 +258,66 @@ ice_aq_get_link_info(struct ice_port_info *pi, bool ena_lse,
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* ice_init_fltr_mgmt_struct - initializes filter management list and locks
|
||||
* @hw: pointer to the hw struct
|
||||
*/
|
||||
static enum ice_status ice_init_fltr_mgmt_struct(struct ice_hw *hw)
|
||||
{
|
||||
struct ice_switch_info *sw;
|
||||
|
||||
hw->switch_info = devm_kzalloc(ice_hw_to_dev(hw),
|
||||
sizeof(*hw->switch_info), GFP_KERNEL);
|
||||
sw = hw->switch_info;
|
||||
|
||||
if (!sw)
|
||||
return ICE_ERR_NO_MEMORY;
|
||||
|
||||
INIT_LIST_HEAD(&sw->vsi_list_map_head);
|
||||
|
||||
mutex_init(&sw->mac_list_lock);
|
||||
INIT_LIST_HEAD(&sw->mac_list_head);
|
||||
|
||||
mutex_init(&sw->vlan_list_lock);
|
||||
INIT_LIST_HEAD(&sw->vlan_list_head);
|
||||
|
||||
mutex_init(&sw->eth_m_list_lock);
|
||||
INIT_LIST_HEAD(&sw->eth_m_list_head);
|
||||
|
||||
mutex_init(&sw->promisc_list_lock);
|
||||
INIT_LIST_HEAD(&sw->promisc_list_head);
|
||||
|
||||
mutex_init(&sw->mac_vlan_list_lock);
|
||||
INIT_LIST_HEAD(&sw->mac_vlan_list_head);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* ice_cleanup_fltr_mgmt_struct - cleanup filter management list and locks
|
||||
* @hw: pointer to the hw struct
|
||||
*/
|
||||
static void ice_cleanup_fltr_mgmt_struct(struct ice_hw *hw)
|
||||
{
|
||||
struct ice_switch_info *sw = hw->switch_info;
|
||||
struct ice_vsi_list_map_info *v_pos_map;
|
||||
struct ice_vsi_list_map_info *v_tmp_map;
|
||||
|
||||
list_for_each_entry_safe(v_pos_map, v_tmp_map, &sw->vsi_list_map_head,
|
||||
list_entry) {
|
||||
list_del(&v_pos_map->list_entry);
|
||||
devm_kfree(ice_hw_to_dev(hw), v_pos_map);
|
||||
}
|
||||
|
||||
mutex_destroy(&sw->mac_list_lock);
|
||||
mutex_destroy(&sw->vlan_list_lock);
|
||||
mutex_destroy(&sw->eth_m_list_lock);
|
||||
mutex_destroy(&sw->promisc_list_lock);
|
||||
mutex_destroy(&sw->mac_vlan_list_lock);
|
||||
|
||||
devm_kfree(ice_hw_to_dev(hw), sw);
|
||||
}
|
||||
|
||||
/**
|
||||
* ice_init_hw - main hardware initialization routine
|
||||
* @hw: pointer to the hardware structure
|
||||
@ -321,6 +381,8 @@ enum ice_status ice_init_hw(struct ice_hw *hw)
|
||||
if (status)
|
||||
goto err_unroll_alloc;
|
||||
|
||||
hw->evb_veb = true;
|
||||
|
||||
/* Query the allocated resources for tx scheduler */
|
||||
status = ice_sched_query_res_alloc(hw);
|
||||
if (status) {
|
||||
@ -352,21 +414,27 @@ enum ice_status ice_init_hw(struct ice_hw *hw)
|
||||
if (status)
|
||||
goto err_unroll_sched;
|
||||
|
||||
status = ice_init_fltr_mgmt_struct(hw);
|
||||
if (status)
|
||||
goto err_unroll_sched;
|
||||
|
||||
/* Get port MAC information */
|
||||
mac_buf_len = sizeof(struct ice_aqc_manage_mac_read_resp);
|
||||
mac_buf = devm_kzalloc(ice_hw_to_dev(hw), mac_buf_len, GFP_KERNEL);
|
||||
|
||||
if (!mac_buf)
|
||||
goto err_unroll_sched;
|
||||
goto err_unroll_fltr_mgmt_struct;
|
||||
|
||||
status = ice_aq_manage_mac_read(hw, mac_buf, mac_buf_len, NULL);
|
||||
devm_kfree(ice_hw_to_dev(hw), mac_buf);
|
||||
|
||||
if (status)
|
||||
goto err_unroll_sched;
|
||||
goto err_unroll_fltr_mgmt_struct;
|
||||
|
||||
return 0;
|
||||
|
||||
err_unroll_fltr_mgmt_struct:
|
||||
ice_cleanup_fltr_mgmt_struct(hw);
|
||||
err_unroll_sched:
|
||||
ice_sched_cleanup_all(hw);
|
||||
err_unroll_alloc:
|
||||
@ -389,6 +457,8 @@ void ice_deinit_hw(struct ice_hw *hw)
|
||||
devm_kfree(ice_hw_to_dev(hw), hw->port_info);
|
||||
hw->port_info = NULL;
|
||||
}
|
||||
|
||||
ice_cleanup_fltr_mgmt_struct(hw);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -162,6 +162,57 @@ static int ice_free_res(struct ice_res_tracker *res, u16 index, u16 id)
|
||||
return count;
|
||||
}
|
||||
|
||||
/**
|
||||
* ice_add_mac_to_list - Add a mac address filter entry to the list
|
||||
* @vsi: the VSI to be forwarded to
|
||||
* @add_list: pointer to the list which contains MAC filter entries
|
||||
* @macaddr: the MAC address to be added.
|
||||
*
|
||||
* Adds mac address filter entry to the temp list
|
||||
*
|
||||
* Returns 0 on success or ENOMEM on failure.
|
||||
*/
|
||||
static int ice_add_mac_to_list(struct ice_vsi *vsi, struct list_head *add_list,
|
||||
const u8 *macaddr)
|
||||
{
|
||||
struct ice_fltr_list_entry *tmp;
|
||||
struct ice_pf *pf = vsi->back;
|
||||
|
||||
tmp = devm_kzalloc(&pf->pdev->dev, sizeof(*tmp), GFP_ATOMIC);
|
||||
if (!tmp)
|
||||
return -ENOMEM;
|
||||
|
||||
tmp->fltr_info.flag = ICE_FLTR_TX;
|
||||
tmp->fltr_info.src = vsi->vsi_num;
|
||||
tmp->fltr_info.lkup_type = ICE_SW_LKUP_MAC;
|
||||
tmp->fltr_info.fltr_act = ICE_FWD_TO_VSI;
|
||||
tmp->fltr_info.fwd_id.vsi_id = vsi->vsi_num;
|
||||
ether_addr_copy(tmp->fltr_info.l_data.mac.mac_addr, macaddr);
|
||||
|
||||
INIT_LIST_HEAD(&tmp->list_entry);
|
||||
list_add(&tmp->list_entry, add_list);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* ice_free_fltr_list - free filter lists helper
|
||||
* @dev: pointer to the device struct
|
||||
* @h: pointer to the list head to be freed
|
||||
*
|
||||
* Helper function to free filter lists previously created using
|
||||
* ice_add_mac_to_list
|
||||
*/
|
||||
static void ice_free_fltr_list(struct device *dev, struct list_head *h)
|
||||
{
|
||||
struct ice_fltr_list_entry *e, *tmp;
|
||||
|
||||
list_for_each_entry_safe(e, tmp, h, list_entry) {
|
||||
list_del(&e->list_entry);
|
||||
devm_kfree(dev, e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* __ice_clean_ctrlq - helper function to clean controlq rings
|
||||
* @pf: ptr to struct ice_pf
|
||||
@ -1519,6 +1570,8 @@ ice_vsi_setup(struct ice_pf *pf, enum ice_vsi_type type,
|
||||
*/
|
||||
static int ice_setup_pf_sw(struct ice_pf *pf)
|
||||
{
|
||||
LIST_HEAD(tmp_add_list);
|
||||
u8 broadcast[ETH_ALEN];
|
||||
struct ice_vsi *vsi;
|
||||
int status = 0;
|
||||
|
||||
@ -1528,7 +1581,37 @@ static int ice_setup_pf_sw(struct ice_pf *pf)
|
||||
goto error_exit;
|
||||
}
|
||||
|
||||
/* tmp_add_list contains a list of MAC addresses for which MAC
|
||||
* filters need to be programmed. Add the VSI's unicast MAC to
|
||||
* this list
|
||||
*/
|
||||
status = ice_add_mac_to_list(vsi, &tmp_add_list,
|
||||
vsi->port_info->mac.perm_addr);
|
||||
if (status)
|
||||
goto error_exit;
|
||||
|
||||
/* VSI needs to receive broadcast traffic, so add the broadcast
|
||||
* MAC address to the list.
|
||||
*/
|
||||
eth_broadcast_addr(broadcast);
|
||||
status = ice_add_mac_to_list(vsi, &tmp_add_list, broadcast);
|
||||
if (status)
|
||||
goto error_exit;
|
||||
|
||||
/* program MAC filters for entries in tmp_add_list */
|
||||
status = ice_add_mac(&pf->hw, &tmp_add_list);
|
||||
if (status) {
|
||||
dev_err(&pf->pdev->dev, "Could not add MAC filters\n");
|
||||
status = -ENOMEM;
|
||||
goto error_exit;
|
||||
}
|
||||
|
||||
ice_free_fltr_list(&pf->pdev->dev, &tmp_add_list);
|
||||
return status;
|
||||
|
||||
error_exit:
|
||||
ice_free_fltr_list(&pf->pdev->dev, &tmp_add_list);
|
||||
|
||||
if (vsi) {
|
||||
ice_vsi_free_q_vectors(vsi);
|
||||
if (vsi->netdev && vsi->netdev->reg_state == NETREG_REGISTERED)
|
||||
@ -1537,6 +1620,7 @@ static int ice_setup_pf_sw(struct ice_pf *pf)
|
||||
free_netdev(vsi->netdev);
|
||||
vsi->netdev = NULL;
|
||||
}
|
||||
|
||||
ice_vsi_delete(vsi);
|
||||
ice_vsi_put_qs(vsi);
|
||||
pf->q_left_tx += vsi->alloc_txq;
|
||||
@ -1869,6 +1953,13 @@ static int ice_probe(struct pci_dev *pdev,
|
||||
"probe failed due to setup pf switch:%d\n", err);
|
||||
goto err_alloc_sw_unroll;
|
||||
}
|
||||
|
||||
/* Driver is mostly up */
|
||||
clear_bit(__ICE_DOWN, pf->state);
|
||||
|
||||
/* since everything is good, start the service timer */
|
||||
mod_timer(&pf->serv_tmr, round_jiffies(jiffies + pf->serv_tmr_period));
|
||||
|
||||
return 0;
|
||||
|
||||
err_alloc_sw_unroll:
|
||||
@ -2012,6 +2103,7 @@ static int ice_vsi_release(struct ice_vsi *vsi)
|
||||
ice_free_res(vsi->back->irq_tracker, vsi->base_vector, vsi->idx);
|
||||
pf->num_avail_msix += vsi->num_q_vectors;
|
||||
|
||||
ice_remove_vsi_fltr(&pf->hw, vsi->vsi_num);
|
||||
ice_vsi_delete(vsi);
|
||||
ice_vsi_free_q_vectors(vsi);
|
||||
ice_vsi_clear_rings(vsi);
|
||||
|
@ -7,6 +7,7 @@
|
||||
/* Error Codes */
|
||||
enum ice_status {
|
||||
ICE_ERR_PARAM = -1,
|
||||
ICE_ERR_NOT_IMPL = -2,
|
||||
ICE_ERR_NOT_READY = -3,
|
||||
ICE_ERR_INVAL_SIZE = -6,
|
||||
ICE_ERR_DEVICE_NOT_SUPPORTED = -8,
|
||||
@ -15,6 +16,8 @@ enum ice_status {
|
||||
ICE_ERR_NO_MEMORY = -11,
|
||||
ICE_ERR_CFG = -12,
|
||||
ICE_ERR_OUT_OF_RANGE = -13,
|
||||
ICE_ERR_ALREADY_EXISTS = -14,
|
||||
ICE_ERR_DOES_NOT_EXIST = -15,
|
||||
ICE_ERR_BUF_TOO_SHORT = -52,
|
||||
ICE_ERR_NVM_BLANK_MODE = -53,
|
||||
ICE_ERR_AQ_ERROR = -100,
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -19,6 +19,122 @@ struct ice_vsi_ctx {
|
||||
bool alloc_from_pool;
|
||||
};
|
||||
|
||||
enum ice_sw_fwd_act_type {
|
||||
ICE_FWD_TO_VSI = 0,
|
||||
ICE_FWD_TO_VSI_LIST, /* Do not use this when adding filter */
|
||||
ICE_FWD_TO_Q,
|
||||
ICE_FWD_TO_QGRP,
|
||||
ICE_DROP_PACKET,
|
||||
ICE_INVAL_ACT
|
||||
};
|
||||
|
||||
/* Switch recipe ID enum values are specific to hardware */
|
||||
enum ice_sw_lkup_type {
|
||||
ICE_SW_LKUP_ETHERTYPE = 0,
|
||||
ICE_SW_LKUP_MAC = 1,
|
||||
ICE_SW_LKUP_MAC_VLAN = 2,
|
||||
ICE_SW_LKUP_PROMISC = 3,
|
||||
ICE_SW_LKUP_VLAN = 4,
|
||||
ICE_SW_LKUP_DFLT = 5,
|
||||
ICE_SW_LKUP_ETHERTYPE_MAC = 8,
|
||||
ICE_SW_LKUP_PROMISC_VLAN = 9,
|
||||
};
|
||||
|
||||
struct ice_fltr_info {
|
||||
/* Look up information: how to look up packet */
|
||||
enum ice_sw_lkup_type lkup_type;
|
||||
/* Forward action: filter action to do after lookup */
|
||||
enum ice_sw_fwd_act_type fltr_act;
|
||||
/* rule ID returned by firmware once filter rule is created */
|
||||
u16 fltr_rule_id;
|
||||
u16 flag;
|
||||
#define ICE_FLTR_RX BIT(0)
|
||||
#define ICE_FLTR_TX BIT(1)
|
||||
#define ICE_FLTR_TX_RX (ICE_FLTR_RX | ICE_FLTR_TX)
|
||||
|
||||
/* Source VSI for LOOKUP_TX or source port for LOOKUP_RX */
|
||||
u16 src;
|
||||
|
||||
union {
|
||||
struct {
|
||||
u8 mac_addr[ETH_ALEN];
|
||||
} mac;
|
||||
struct {
|
||||
u8 mac_addr[ETH_ALEN];
|
||||
u16 vlan_id;
|
||||
} mac_vlan;
|
||||
struct {
|
||||
u16 vlan_id;
|
||||
} vlan;
|
||||
/* Set lkup_type as ICE_SW_LKUP_ETHERTYPE
|
||||
* if just using ethertype as filter. Set lkup_type as
|
||||
* ICE_SW_LKUP_ETHERTYPE_MAC if MAC also needs to be
|
||||
* passed in as filter.
|
||||
*/
|
||||
struct {
|
||||
u16 ethertype;
|
||||
u8 mac_addr[ETH_ALEN]; /* optional */
|
||||
} ethertype_mac;
|
||||
} l_data;
|
||||
|
||||
/* Depending on filter action */
|
||||
union {
|
||||
/* queue id in case of ICE_FWD_TO_Q and starting
|
||||
* queue id in case of ICE_FWD_TO_QGRP.
|
||||
*/
|
||||
u16 q_id:11;
|
||||
u16 vsi_id:10;
|
||||
u16 vsi_list_id:10;
|
||||
} fwd_id;
|
||||
|
||||
/* Set to num_queues if action is ICE_FWD_TO_QGRP. This field
|
||||
* determines the range of queues the packet needs to be forwarded to
|
||||
*/
|
||||
u8 qgrp_size;
|
||||
|
||||
/* Rule creations populate these indicators basing on the switch type */
|
||||
bool lb_en; /* Indicate if packet can be looped back */
|
||||
bool lan_en; /* Indicate if packet can be forwarded to the uplink */
|
||||
};
|
||||
|
||||
/* Bookkeeping structure to hold bitmap of VSIs corresponding to VSI list id */
|
||||
struct ice_vsi_list_map_info {
|
||||
struct list_head list_entry;
|
||||
DECLARE_BITMAP(vsi_map, ICE_MAX_VSI);
|
||||
u16 vsi_list_id;
|
||||
};
|
||||
|
||||
enum ice_sw_fltr_status {
|
||||
ICE_FLTR_STATUS_NEW = 0,
|
||||
ICE_FLTR_STATUS_FW_SUCCESS,
|
||||
ICE_FLTR_STATUS_FW_FAIL,
|
||||
};
|
||||
|
||||
struct ice_fltr_list_entry {
|
||||
struct list_head list_entry;
|
||||
enum ice_sw_fltr_status status;
|
||||
struct ice_fltr_info fltr_info;
|
||||
};
|
||||
|
||||
/* This defines an entry in the list that maintains MAC or VLAN membership
|
||||
* to HW list mapping, since multiple VSIs can subscribe to the same MAC or
|
||||
* VLAN. As an optimization the VSI list should be created only when a
|
||||
* second VSI becomes a subscriber to the VLAN address.
|
||||
*/
|
||||
struct ice_fltr_mgmt_list_entry {
|
||||
/* back pointer to VSI list id to VSI list mapping */
|
||||
struct ice_vsi_list_map_info *vsi_list_info;
|
||||
u16 vsi_count;
|
||||
#define ICE_INVAL_LG_ACT_INDEX 0xffff
|
||||
u16 lg_act_idx;
|
||||
#define ICE_INVAL_SW_MARKER_ID 0xffff
|
||||
u16 sw_marker_id;
|
||||
struct list_head list_entry;
|
||||
struct ice_fltr_info fltr_info;
|
||||
#define ICE_INVAL_COUNTER_ID 0xff
|
||||
u8 counter_index;
|
||||
};
|
||||
|
||||
/* VSI related commands */
|
||||
enum ice_status
|
||||
ice_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,
|
||||
|
||||
enum ice_status ice_get_initial_sw_cfg(struct ice_hw *hw);
|
||||
|
||||
/* Switch/bridge related commands */
|
||||
enum ice_status ice_add_mac(struct ice_hw *hw, struct list_head *m_lst);
|
||||
enum ice_status ice_remove_mac(struct ice_hw *hw, struct list_head *m_lst);
|
||||
void ice_remove_vsi_fltr(struct ice_hw *hw, u16 vsi_id);
|
||||
#endif /* _ICE_SWITCH_H_ */
|
||||
|
@ -223,6 +223,22 @@ struct ice_port_info {
|
||||
bool is_vf;
|
||||
};
|
||||
|
||||
struct ice_switch_info {
|
||||
/* Switch VSI lists to MAC/VLAN translation */
|
||||
struct mutex mac_list_lock; /* protect MAC list */
|
||||
struct list_head mac_list_head;
|
||||
struct mutex vlan_list_lock; /* protect VLAN list */
|
||||
struct list_head vlan_list_head;
|
||||
struct mutex eth_m_list_lock; /* protect ethtype list */
|
||||
struct list_head eth_m_list_head;
|
||||
struct mutex promisc_list_lock; /* protect promisc mode list */
|
||||
struct list_head promisc_list_head;
|
||||
struct mutex mac_vlan_list_lock; /* protect MAC-VLAN list */
|
||||
struct list_head mac_vlan_list_head;
|
||||
|
||||
struct list_head vsi_list_map_head;
|
||||
};
|
||||
|
||||
/* Port hardware description */
|
||||
struct ice_hw {
|
||||
u8 __iomem *hw_addr;
|
||||
@ -248,11 +264,14 @@ struct ice_hw {
|
||||
u8 max_cgds;
|
||||
u8 sw_entry_point_layer;
|
||||
|
||||
bool evb_veb; /* true for VEB, false for VEPA */
|
||||
struct ice_bus_info bus;
|
||||
struct ice_nvm_info nvm;
|
||||
struct ice_hw_dev_caps dev_caps; /* device capabilities */
|
||||
struct ice_hw_func_caps func_caps; /* function capabilities */
|
||||
|
||||
struct ice_switch_info *switch_info; /* switch filter lists */
|
||||
|
||||
/* Control Queue info */
|
||||
struct ice_ctl_q_info adminq;
|
||||
|
||||
@ -276,6 +295,8 @@ struct ice_hw {
|
||||
u8 itr_gran_100;
|
||||
u8 itr_gran_50;
|
||||
u8 itr_gran_25;
|
||||
bool ucast_shared; /* true if VSIs can share unicast addr */
|
||||
|
||||
};
|
||||
|
||||
/* Checksum and Shadow RAM pointers */
|
||||
|
Loading…
Reference in New Issue
Block a user