diff options
Diffstat (limited to 'drivers/net/ethernet/intel/ice/ice_switch.c')
| -rw-r--r-- | drivers/net/ethernet/intel/ice/ice_switch.c | 150 |
1 files changed, 110 insertions, 40 deletions
diff --git a/drivers/net/ethernet/intel/ice/ice_switch.c b/drivers/net/ethernet/intel/ice/ice_switch.c index 51825a203e35..c3a6c41385ee 100644 --- a/drivers/net/ethernet/intel/ice/ice_switch.c +++ b/drivers/net/ethernet/intel/ice/ice_switch.c @@ -29,25 +29,17 @@ static const u8 dummy_eth_header[DUMMY_ETH_HDR_LEN] = { 0x2, 0, 0, 0, 0, 0, 0x81, 0, 0, 0}; #define ICE_SW_RULE_RX_TX_ETH_HDR_SIZE \ - (sizeof(struct ice_aqc_sw_rules_elem) - \ - sizeof(((struct ice_aqc_sw_rules_elem *)0)->pdata) + \ - sizeof(struct ice_sw_rule_lkup_rx_tx) + DUMMY_ETH_HDR_LEN - 1) + (offsetof(struct ice_aqc_sw_rules_elem, pdata.lkup_tx_rx.hdr) + \ + (DUMMY_ETH_HDR_LEN * \ + sizeof(((struct ice_sw_rule_lkup_rx_tx *)0)->hdr[0]))) #define ICE_SW_RULE_RX_TX_NO_HDR_SIZE \ - (sizeof(struct ice_aqc_sw_rules_elem) - \ - sizeof(((struct ice_aqc_sw_rules_elem *)0)->pdata) + \ - sizeof(struct ice_sw_rule_lkup_rx_tx) - 1) + (offsetof(struct ice_aqc_sw_rules_elem, pdata.lkup_tx_rx.hdr)) #define ICE_SW_RULE_LG_ACT_SIZE(n) \ - (sizeof(struct ice_aqc_sw_rules_elem) - \ - sizeof(((struct ice_aqc_sw_rules_elem *)0)->pdata) + \ - sizeof(struct ice_sw_rule_lg_act) - \ - sizeof(((struct ice_sw_rule_lg_act *)0)->act) + \ - ((n) * sizeof(((struct ice_sw_rule_lg_act *)0)->act))) + (offsetof(struct ice_aqc_sw_rules_elem, pdata.lg_act.act) + \ + ((n) * sizeof(((struct ice_sw_rule_lg_act *)0)->act[0]))) #define ICE_SW_RULE_VSI_LIST_SIZE(n) \ - (sizeof(struct ice_aqc_sw_rules_elem) - \ - sizeof(((struct ice_aqc_sw_rules_elem *)0)->pdata) + \ - sizeof(struct ice_sw_rule_vsi_list) - \ - sizeof(((struct ice_sw_rule_vsi_list *)0)->vsi) + \ - ((n) * sizeof(((struct ice_sw_rule_vsi_list *)0)->vsi))) + (offsetof(struct ice_aqc_sw_rules_elem, pdata.vsi_list.vsi) + \ + ((n) * sizeof(((struct ice_sw_rule_vsi_list *)0)->vsi[0]))) /** * ice_init_def_sw_recp - initialize the recipe book keeping tables @@ -87,7 +79,7 @@ enum ice_status ice_init_def_sw_recp(struct ice_hw *hw) * @num_elems: pointer to number of elements * @cd: pointer to command details structure or NULL * - * Get switch configuration (0x0200) to be placed in 'buff'. + * Get switch configuration (0x0200) to be placed in buf. * This admin command returns information such as initial VSI/port number * and switch ID it belongs to. * @@ -104,13 +96,13 @@ enum ice_status ice_init_def_sw_recp(struct ice_hw *hw) * parsing the response buffer. */ static enum ice_status -ice_aq_get_sw_cfg(struct ice_hw *hw, struct ice_aqc_get_sw_cfg_resp *buf, +ice_aq_get_sw_cfg(struct ice_hw *hw, struct ice_aqc_get_sw_cfg_resp_elem *buf, u16 buf_size, u16 *req_desc, u16 *num_elems, struct ice_sq_cd *cd) { struct ice_aqc_get_sw_cfg *cmd; - enum ice_status status; struct ice_aq_desc desc; + enum ice_status status; ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_get_sw_cfg); cmd = &desc.params.get_sw_conf; @@ -449,7 +441,7 @@ ice_aq_alloc_free_vsi_list(struct ice_hw *hw, u16 *vsi_list_id, enum ice_status status; u16 buf_len; - buf_len = sizeof(*sw_buf); + buf_len = struct_size(sw_buf, elem, 1); sw_buf = devm_kzalloc(ice_hw_to_dev(hw), buf_len, GFP_KERNEL); if (!sw_buf) return ICE_ERR_NO_MEMORY; @@ -503,6 +495,7 @@ ice_aq_sw_rules(struct ice_hw *hw, void *rule_list, u16 rule_list_sz, u8 num_rules, enum ice_adminq_opc opc, struct ice_sq_cd *cd) { struct ice_aq_desc desc; + enum ice_status status; if (opc != ice_aqc_opc_add_sw_rules && opc != ice_aqc_opc_update_sw_rules && @@ -514,7 +507,12 @@ ice_aq_sw_rules(struct ice_hw *hw, void *rule_list, u16 rule_list_sz, desc.flags |= cpu_to_le16(ICE_AQ_FLAG_RD); desc.params.sw_rules.num_rules_fltr_entry_index = cpu_to_le16(num_rules); - return ice_aq_send_cmd(hw, &desc, rule_list, rule_list_sz, cd); + status = ice_aq_send_cmd(hw, &desc, rule_list, rule_list_sz, cd); + if (opc != ice_aqc_opc_add_sw_rules && + hw->adminq.sq_last_status == ICE_AQ_RC_ENOENT) + status = ICE_ERR_DOES_NOT_EXIST; + + return status; } /* ice_init_port_info - Initialize port_info with switch configuration data @@ -550,7 +548,7 @@ ice_init_port_info(struct ice_port_info *pi, u16 vsi_port_num, u8 type, */ enum ice_status ice_get_initial_sw_cfg(struct ice_hw *hw) { - struct ice_aqc_get_sw_cfg_resp *rbuf; + struct ice_aqc_get_sw_cfg_resp_elem *rbuf; enum ice_status status; u16 req_desc = 0; u16 num_elems; @@ -568,19 +566,19 @@ enum ice_status ice_get_initial_sw_cfg(struct ice_hw *hw) * writing a non-zero value in req_desc */ do { + struct ice_aqc_get_sw_cfg_resp_elem *ele; + status = ice_aq_get_sw_cfg(hw, rbuf, ICE_SW_CFG_MAX_BUF_LEN, &req_desc, &num_elems, NULL); if (status) break; - for (i = 0; i < num_elems; i++) { - struct ice_aqc_get_sw_cfg_resp_elem *ele; + for (i = 0, ele = rbuf; i < num_elems; i++, ele++) { u16 pf_vf_num, swid, vsi_port_num; bool is_vf = false; u8 res_type; - ele = rbuf[i].elements; vsi_port_num = le16_to_cpu(ele->vsi_port_num) & ICE_AQC_GET_SW_CONF_RESP_VSI_PORT_NUM_M; @@ -593,8 +591,8 @@ enum ice_status ice_get_initial_sw_cfg(struct ice_hw *hw) ICE_AQC_GET_SW_CONF_RESP_IS_VF) is_vf = true; - res_type = le16_to_cpu(ele->vsi_port_num) >> - ICE_AQC_GET_SW_CONF_RESP_TYPE_S; + res_type = (u8)(le16_to_cpu(ele->vsi_port_num) >> + ICE_AQC_GET_SW_CONF_RESP_TYPE_S); if (res_type == ICE_AQC_GET_SW_CONF_RESP_VSI) { /* FW VSI is not needed. Just continue. */ @@ -856,8 +854,7 @@ ice_add_marker_act(struct ice_hw *hw, struct ice_fltr_mgmt_list_entry *m_ent, m_ent->fltr_info.fwd_id.hw_vsi_id; act = ICE_LG_ACT_VSI_FORWARDING | ICE_LG_ACT_VALID_BIT; - act |= (id << ICE_LG_ACT_VSI_LIST_ID_S) & - ICE_LG_ACT_VSI_LIST_ID_M; + act |= (id << ICE_LG_ACT_VSI_LIST_ID_S) & ICE_LG_ACT_VSI_LIST_ID_M; if (m_ent->vsi_count > 1) act |= ICE_LG_ACT_VSI_LIST; lg_act->pdata.lg_act.act[0] = cpu_to_le32(act); @@ -1612,18 +1609,17 @@ exit: * check for duplicates in this case, removing duplicates from a given * list should be taken care of in the caller of this function. */ -enum ice_status -ice_add_mac(struct ice_hw *hw, struct list_head *m_list) +enum ice_status ice_add_mac(struct ice_hw *hw, struct list_head *m_list) { struct ice_aqc_sw_rules_elem *s_rule, *r_iter; struct ice_fltr_list_entry *m_list_itr; struct list_head *rule_head; - u16 elem_sent, total_elem_left; + u16 total_elem_left, s_rule_size; struct ice_switch_info *sw; struct mutex *rule_lock; /* Lock to protect filter rule list */ enum ice_status status = 0; u16 num_unicast = 0; - u16 s_rule_size; + u8 elem_sent; if (!m_list || !hw) return ICE_ERR_PARAM; @@ -1707,8 +1703,8 @@ ice_add_mac(struct ice_hw *hw, struct list_head *m_list) total_elem_left -= elem_sent) { struct ice_aqc_sw_rules_elem *entry = r_iter; - elem_sent = min(total_elem_left, - (u16)(ICE_AQ_MAX_BUF_LEN / s_rule_size)); + elem_sent = min_t(u8, total_elem_left, + (ICE_AQ_MAX_BUF_LEN / s_rule_size)); status = ice_aq_sw_rules(hw, entry, elem_sent * s_rule_size, elem_sent, ice_aqc_opc_add_sw_rules, NULL); @@ -1914,8 +1910,7 @@ exit: * @hw: pointer to the hardware structure * @v_list: list of VLAN entries and forwarding information */ -enum ice_status -ice_add_vlan(struct ice_hw *hw, struct list_head *v_list) +enum ice_status ice_add_vlan(struct ice_hw *hw, struct list_head *v_list) { struct ice_fltr_list_entry *v_list_itr; @@ -2039,7 +2034,8 @@ ice_cfg_dflt_vsi(struct ice_hw *hw, u16 vsi_handle, bool set, u8 direction) hw_vsi_id = ice_get_hw_vsi_num(hw, vsi_handle); s_rule_size = set ? ICE_SW_RULE_RX_TX_ETH_HDR_SIZE : - ICE_SW_RULE_RX_TX_NO_HDR_SIZE; + ICE_SW_RULE_RX_TX_NO_HDR_SIZE; + s_rule = devm_kzalloc(ice_hw_to_dev(hw), s_rule_size, GFP_KERNEL); if (!s_rule) return ICE_ERR_NO_MEMORY; @@ -2145,8 +2141,7 @@ ice_find_ucast_rule_entry(struct ice_hw *hw, u8 recp_id, * the entries passed into m_list were added previously. It will not attempt to * do a partial remove of entries that were found. */ -enum ice_status -ice_remove_mac(struct ice_hw *hw, struct list_head *m_list) +enum ice_status ice_remove_mac(struct ice_hw *hw, struct list_head *m_list) { struct ice_fltr_list_entry *list_itr, *tmp; struct mutex *rule_lock; /* Lock to protect filter rule list */ @@ -2678,6 +2673,81 @@ void ice_remove_vsi_fltr(struct ice_hw *hw, u16 vsi_handle) } /** + * ice_alloc_res_cntr - allocating resource counter + * @hw: pointer to the hardware structure + * @type: type of resource + * @alloc_shared: if set it is shared else dedicated + * @num_items: number of entries requested for FD resource type + * @counter_id: counter index returned by AQ call + */ +enum ice_status +ice_alloc_res_cntr(struct ice_hw *hw, u8 type, u8 alloc_shared, u16 num_items, + u16 *counter_id) +{ + struct ice_aqc_alloc_free_res_elem *buf; + enum ice_status status; + u16 buf_len; + + /* Allocate resource */ + buf_len = struct_size(buf, elem, 1); + buf = kzalloc(buf_len, GFP_KERNEL); + if (!buf) + return ICE_ERR_NO_MEMORY; + + buf->num_elems = cpu_to_le16(num_items); + buf->res_type = cpu_to_le16(((type << ICE_AQC_RES_TYPE_S) & + ICE_AQC_RES_TYPE_M) | alloc_shared); + + status = ice_aq_alloc_free_res(hw, 1, buf, buf_len, + ice_aqc_opc_alloc_res, NULL); + if (status) + goto exit; + + *counter_id = le16_to_cpu(buf->elem[0].e.sw_resp); + +exit: + kfree(buf); + return status; +} + +/** + * ice_free_res_cntr - free resource counter + * @hw: pointer to the hardware structure + * @type: type of resource + * @alloc_shared: if set it is shared else dedicated + * @num_items: number of entries to be freed for FD resource type + * @counter_id: counter ID resource which needs to be freed + */ +enum ice_status +ice_free_res_cntr(struct ice_hw *hw, u8 type, u8 alloc_shared, u16 num_items, + u16 counter_id) +{ + struct ice_aqc_alloc_free_res_elem *buf; + enum ice_status status; + u16 buf_len; + + /* Free resource */ + buf_len = struct_size(buf, elem, 1); + buf = kzalloc(buf_len, GFP_KERNEL); + if (!buf) + return ICE_ERR_NO_MEMORY; + + buf->num_elems = cpu_to_le16(num_items); + buf->res_type = cpu_to_le16(((type << ICE_AQC_RES_TYPE_S) & + ICE_AQC_RES_TYPE_M) | alloc_shared); + buf->elem[0].e.sw_resp = cpu_to_le16(counter_id); + + status = ice_aq_alloc_free_res(hw, 1, buf, buf_len, + ice_aqc_opc_free_res, NULL); + if (status) + ice_debug(hw, ICE_DBG_SW, + "counter resource could not be freed\n"); + + kfree(buf); + return status; +} + +/** * ice_replay_vsi_fltr - Replay filters for requested VSI * @hw: pointer to the hardware structure * @vsi_handle: driver VSI handle |