X-Git-Url: http://git.droids-corp.org/?a=blobdiff_plain;f=drivers%2Fnet%2Fice%2Fbase%2Fice_switch.c;h=c985c1e310e5cca49dd744efeffb4a0756ebc5c7;hb=d781ccbdd15d422a65ed1794aa58a182ae870a54;hp=512e64b913b68272edcf15bfcb02f8f7d234b12b;hpb=0c451c3198dcabadf1b039fd144a5e50b69e1180;p=dpdk.git diff --git a/drivers/net/ice/base/ice_switch.c b/drivers/net/ice/base/ice_switch.c index 512e64b913..c985c1e310 100644 --- a/drivers/net/ice/base/ice_switch.c +++ b/drivers/net/ice/base/ice_switch.c @@ -3,6 +3,8 @@ */ #include "ice_switch.h" +#include "ice_flex_type.h" +#include "ice_flow.h" #define ICE_ETH_DA_OFFSET 0 @@ -288,7 +290,7 @@ enum ice_status ice_free_sw(struct ice_hw *hw, u16 sw_id, u16 counter_id) * * Add a VSI context to the hardware (0x0210) */ -static enum ice_status +enum ice_status ice_aq_add_vsi(struct ice_hw *hw, struct ice_vsi_ctx *vsi_ctx, struct ice_sq_cd *cd) { @@ -331,7 +333,7 @@ ice_aq_add_vsi(struct ice_hw *hw, struct ice_vsi_ctx *vsi_ctx, * * Free VSI context info from hardware (0x0213) */ -static enum ice_status +enum ice_status ice_aq_free_vsi(struct ice_hw *hw, struct ice_vsi_ctx *vsi_ctx, bool keep_vsi_alloc, struct ice_sq_cd *cd) { @@ -366,7 +368,7 @@ ice_aq_free_vsi(struct ice_hw *hw, struct ice_vsi_ctx *vsi_ctx, * * Update VSI context in the hardware (0x0211) */ -static enum ice_status +enum ice_status ice_aq_update_vsi(struct ice_hw *hw, struct ice_vsi_ctx *vsi_ctx, struct ice_sq_cd *cd) { @@ -446,6 +448,27 @@ ice_save_vsi_ctx(struct ice_hw *hw, u16 vsi_handle, struct ice_vsi_ctx *vsi) hw->vsi_ctx[vsi_handle] = vsi; } +/** + * ice_clear_vsi_q_ctx - clear VSI queue contexts for all TCs + * @hw: pointer to the HW struct + * @vsi_handle: VSI handle + */ +static void ice_clear_vsi_q_ctx(struct ice_hw *hw, u16 vsi_handle) +{ + struct ice_vsi_ctx *vsi; + u8 i; + + vsi = ice_get_vsi_ctx(hw, vsi_handle); + if (!vsi) + return; + ice_for_each_traffic_class(i) { + if (vsi->lan_q_ctx[i]) { + ice_free(hw, vsi->lan_q_ctx[i]); + vsi->lan_q_ctx[i] = NULL; + } + } +} + /** * ice_clear_vsi_ctx - clear the VSI context entry * @hw: pointer to the HW struct @@ -459,6 +482,9 @@ static void ice_clear_vsi_ctx(struct ice_hw *hw, u16 vsi_handle) vsi = ice_get_vsi_ctx(hw, vsi_handle); if (vsi) { + if (!LIST_EMPTY(&vsi->rss_list_head)) + ice_rem_all_rss_vsi_ctx(hw, vsi_handle); + ice_clear_vsi_q_ctx(hw, vsi_handle); ice_destroy_lock(&vsi->rss_locks); ice_free(hw, vsi); hw->vsi_ctx[vsi_handle] = NULL; @@ -566,7 +592,174 @@ ice_update_vsi(struct ice_hw *hw, u16 vsi_handle, struct ice_vsi_ctx *vsi_ctx, return ice_aq_update_vsi(hw, vsi_ctx, cd); } +/** + * ice_aq_get_vsi_params + * @hw: pointer to the HW struct + * @vsi_ctx: pointer to a VSI context struct + * @cd: pointer to command details structure or NULL + * + * Get VSI context info from hardware (0x0212) + */ +enum ice_status +ice_aq_get_vsi_params(struct ice_hw *hw, struct ice_vsi_ctx *vsi_ctx, + struct ice_sq_cd *cd) +{ + struct ice_aqc_add_get_update_free_vsi *cmd; + struct ice_aqc_get_vsi_resp *resp; + struct ice_aq_desc desc; + enum ice_status status; + + cmd = &desc.params.vsi_cmd; + resp = &desc.params.get_vsi_resp; + + ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_get_vsi_params); + + cmd->vsi_num = CPU_TO_LE16(vsi_ctx->vsi_num | ICE_AQ_VSI_IS_VALID); + + status = ice_aq_send_cmd(hw, &desc, &vsi_ctx->info, + sizeof(vsi_ctx->info), cd); + if (!status) { + vsi_ctx->vsi_num = LE16_TO_CPU(resp->vsi_num) & + ICE_AQ_VSI_NUM_M; + vsi_ctx->vsis_allocd = LE16_TO_CPU(resp->vsi_used); + vsi_ctx->vsis_unallocated = LE16_TO_CPU(resp->vsi_free); + } + + return status; +} + +/** + * ice_aq_add_update_mir_rule - add/update a mirror rule + * @hw: pointer to the HW struct + * @rule_type: Rule Type + * @dest_vsi: VSI number to which packets will be mirrored + * @count: length of the list + * @mr_buf: buffer for list of mirrored VSI numbers + * @cd: pointer to command details structure or NULL + * @rule_id: Rule ID + * + * Add/Update Mirror Rule (0x260). + */ +enum ice_status +ice_aq_add_update_mir_rule(struct ice_hw *hw, u16 rule_type, u16 dest_vsi, + u16 count, struct ice_mir_rule_buf *mr_buf, + struct ice_sq_cd *cd, u16 *rule_id) +{ + struct ice_aqc_add_update_mir_rule *cmd; + struct ice_aq_desc desc; + enum ice_status status; + __le16 *mr_list = NULL; + u16 buf_size = 0; + + switch (rule_type) { + case ICE_AQC_RULE_TYPE_VPORT_INGRESS: + case ICE_AQC_RULE_TYPE_VPORT_EGRESS: + /* Make sure count and mr_buf are set for these rule_types */ + if (!(count && mr_buf)) + return ICE_ERR_PARAM; + + buf_size = count * sizeof(__le16); + mr_list = (__le16 *)ice_malloc(hw, buf_size); + if (!mr_list) + return ICE_ERR_NO_MEMORY; + break; + case ICE_AQC_RULE_TYPE_PPORT_INGRESS: + case ICE_AQC_RULE_TYPE_PPORT_EGRESS: + /* Make sure count and mr_buf are not set for these + * rule_types + */ + if (count || mr_buf) + return ICE_ERR_PARAM; + break; + default: + ice_debug(hw, ICE_DBG_SW, + "Error due to unsupported rule_type %u\n", rule_type); + return ICE_ERR_OUT_OF_RANGE; + } + + ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_add_update_mir_rule); + + /* Pre-process 'mr_buf' items for add/update of virtual port + * ingress/egress mirroring (but not physical port ingress/egress + * mirroring) + */ + if (mr_buf) { + int i; + + for (i = 0; i < count; i++) { + u16 id; + + id = mr_buf[i].vsi_idx & ICE_AQC_RULE_MIRRORED_VSI_M; + + /* Validate specified VSI number, make sure it is less + * than ICE_MAX_VSI, if not return with error. + */ + if (id >= ICE_MAX_VSI) { + ice_debug(hw, ICE_DBG_SW, + "Error VSI index (%u) out-of-range\n", + id); + ice_free(hw, mr_list); + return ICE_ERR_OUT_OF_RANGE; + } + + /* add VSI to mirror rule */ + if (mr_buf[i].add) + mr_list[i] = + CPU_TO_LE16(id | ICE_AQC_RULE_ACT_M); + else /* remove VSI from mirror rule */ + mr_list[i] = CPU_TO_LE16(id); + } + } + + cmd = &desc.params.add_update_rule; + if ((*rule_id) != ICE_INVAL_MIRROR_RULE_ID) + cmd->rule_id = CPU_TO_LE16(((*rule_id) & ICE_AQC_RULE_ID_M) | + ICE_AQC_RULE_ID_VALID_M); + cmd->rule_type = CPU_TO_LE16(rule_type & ICE_AQC_RULE_TYPE_M); + cmd->num_entries = CPU_TO_LE16(count); + cmd->dest = CPU_TO_LE16(dest_vsi); + + status = ice_aq_send_cmd(hw, &desc, mr_list, buf_size, cd); + if (!status) + *rule_id = LE16_TO_CPU(cmd->rule_id) & ICE_AQC_RULE_ID_M; + + ice_free(hw, mr_list); + + return status; +} + +/** + * ice_aq_delete_mir_rule - delete a mirror rule + * @hw: pointer to the HW struct + * @rule_id: Mirror rule ID (to be deleted) + * @keep_allocd: if set, the VSI stays part of the PF allocated res, + * otherwise it is returned to the shared pool + * @cd: pointer to command details structure or NULL + * + * Delete Mirror Rule (0x261). + */ +enum ice_status +ice_aq_delete_mir_rule(struct ice_hw *hw, u16 rule_id, bool keep_allocd, + struct ice_sq_cd *cd) +{ + struct ice_aqc_delete_mir_rule *cmd; + struct ice_aq_desc desc; + + /* rule_id should be in the range 0...63 */ + if (rule_id >= ICE_MAX_NUM_MIRROR_RULES) + return ICE_ERR_OUT_OF_RANGE; + ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_del_mir_rule); + + cmd = &desc.params.del_rule; + rule_id |= ICE_AQC_RULE_ID_VALID_M; + cmd->rule_id = CPU_TO_LE16(rule_id); + + if (keep_allocd) + cmd->flags = CPU_TO_LE16(ICE_AQC_FLAG_KEEP_ALLOCD_M); + + return ice_aq_send_cmd(hw, &desc, NULL, 0, cd); +} /** * ice_aq_alloc_free_vsi_list @@ -626,6 +819,67 @@ ice_aq_alloc_free_vsi_list_exit: return status; } +/** + * ice_aq_set_storm_ctrl - Sets storm control configuration + * @hw: pointer to the HW struct + * @bcast_thresh: represents the upper threshold for broadcast storm control + * @mcast_thresh: represents the upper threshold for multicast storm control + * @ctl_bitmask: storm control control knobs + * + * Sets the storm control configuration (0x0280) + */ +enum ice_status +ice_aq_set_storm_ctrl(struct ice_hw *hw, u32 bcast_thresh, u32 mcast_thresh, + u32 ctl_bitmask) +{ + struct ice_aqc_storm_cfg *cmd; + struct ice_aq_desc desc; + + cmd = &desc.params.storm_conf; + + ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_set_storm_cfg); + + cmd->bcast_thresh_size = CPU_TO_LE32(bcast_thresh & ICE_AQ_THRESHOLD_M); + cmd->mcast_thresh_size = CPU_TO_LE32(mcast_thresh & ICE_AQ_THRESHOLD_M); + cmd->storm_ctrl_ctrl = CPU_TO_LE32(ctl_bitmask); + + return ice_aq_send_cmd(hw, &desc, NULL, 0, NULL); +} + +/** + * ice_aq_get_storm_ctrl - gets storm control configuration + * @hw: pointer to the HW struct + * @bcast_thresh: represents the upper threshold for broadcast storm control + * @mcast_thresh: represents the upper threshold for multicast storm control + * @ctl_bitmask: storm control control knobs + * + * Gets the storm control configuration (0x0281) + */ +enum ice_status +ice_aq_get_storm_ctrl(struct ice_hw *hw, u32 *bcast_thresh, u32 *mcast_thresh, + u32 *ctl_bitmask) +{ + enum ice_status status; + struct ice_aq_desc desc; + + ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_get_storm_cfg); + + status = ice_aq_send_cmd(hw, &desc, NULL, 0, NULL); + if (!status) { + struct ice_aqc_storm_cfg *resp = &desc.params.storm_conf; + + if (bcast_thresh) + *bcast_thresh = LE32_TO_CPU(resp->bcast_thresh_size) & + ICE_AQ_THRESHOLD_M; + if (mcast_thresh) + *mcast_thresh = LE32_TO_CPU(resp->mcast_thresh_size) & + ICE_AQ_THRESHOLD_M; + if (ctl_bitmask) + *ctl_bitmask = LE32_TO_CPU(resp->storm_ctrl_ctrl); + } + + return status; +} /** * ice_aq_sw_rules - add/update/remove switch rules @@ -1788,6 +2042,89 @@ exit: return status; } +/** + * ice_aq_get_res_alloc - get allocated resources + * @hw: pointer to the HW struct + * @num_entries: pointer to u16 to store the number of resource entries returned + * @buf: pointer to user-supplied buffer + * @buf_size: size of buff + * @cd: pointer to command details structure or NULL + * + * The user-supplied buffer must be large enough to store the resource + * information for all resource types. Each resource type is an + * ice_aqc_get_res_resp_data_elem structure. + */ +enum ice_status +ice_aq_get_res_alloc(struct ice_hw *hw, u16 *num_entries, void *buf, + u16 buf_size, struct ice_sq_cd *cd) +{ + struct ice_aqc_get_res_alloc *resp; + enum ice_status status; + struct ice_aq_desc desc; + + if (!buf) + return ICE_ERR_BAD_PTR; + + if (buf_size < ICE_AQ_GET_RES_ALLOC_BUF_LEN) + return ICE_ERR_INVAL_SIZE; + + resp = &desc.params.get_res; + + ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_get_res_alloc); + status = ice_aq_send_cmd(hw, &desc, buf, buf_size, cd); + + if (!status && num_entries) + *num_entries = LE16_TO_CPU(resp->resp_elem_num); + + return status; +} + +/** + * ice_aq_get_res_descs - get allocated resource descriptors + * @hw: pointer to the hardware structure + * @num_entries: number of resource entries in buffer + * @buf: Indirect buffer to hold data parameters and response + * @buf_size: size of buffer for indirect commands + * @res_type: resource type + * @res_shared: is resource shared + * @desc_id: input - first desc ID to start; output - next desc ID + * @cd: pointer to command details structure or NULL + */ +enum ice_status +ice_aq_get_res_descs(struct ice_hw *hw, u16 num_entries, + struct ice_aqc_get_allocd_res_desc_resp *buf, + u16 buf_size, u16 res_type, bool res_shared, u16 *desc_id, + struct ice_sq_cd *cd) +{ + struct ice_aqc_get_allocd_res_desc *cmd; + struct ice_aq_desc desc; + enum ice_status status; + + ice_debug(hw, ICE_DBG_TRACE, "ice_aq_get_res_descs"); + + cmd = &desc.params.get_res_desc; + + if (!buf) + return ICE_ERR_PARAM; + + if (buf_size != (num_entries * sizeof(*buf))) + return ICE_ERR_PARAM; + + ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_get_allocd_res_desc); + + cmd->ops.cmd.res = CPU_TO_LE16(((res_type << ICE_AQC_RES_TYPE_S) & + ICE_AQC_RES_TYPE_M) | (res_shared ? + ICE_AQC_RES_TYPE_FLAG_SHARED : 0)); + cmd->ops.cmd.first_desc = CPU_TO_LE16(*desc_id); + + desc.flags |= CPU_TO_LE16(ICE_AQ_FLAG_RD); + + status = ice_aq_send_cmd(hw, &desc, buf, buf_size, cd); + if (!status) + *desc_id = LE16_TO_CPU(cmd->ops.resp.next_desc); + + return status; +} /** * ice_add_mac - Add a MAC address based filter rule @@ -2161,6 +2498,63 @@ ice_add_mac_vlan(struct ice_hw *hw, struct LIST_HEAD_TYPE *mv_list) } #endif +/** + * ice_add_eth_mac - Add ethertype and MAC based filter rule + * @hw: pointer to the hardware structure + * @em_list: list of ether type MAC filter, MAC is optional + */ +enum ice_status +ice_add_eth_mac(struct ice_hw *hw, struct LIST_HEAD_TYPE *em_list) +{ + struct ice_fltr_list_entry *em_list_itr; + + LIST_FOR_EACH_ENTRY(em_list_itr, em_list, ice_fltr_list_entry, + list_entry) { + enum ice_sw_lkup_type l_type = + em_list_itr->fltr_info.lkup_type; + + if (l_type != ICE_SW_LKUP_ETHERTYPE_MAC && + l_type != ICE_SW_LKUP_ETHERTYPE) + return ICE_ERR_PARAM; + + em_list_itr->fltr_info.flag = ICE_FLTR_TX; + em_list_itr->status = ice_add_rule_internal(hw, l_type, + em_list_itr); + if (em_list_itr->status) + return em_list_itr->status; + } + return ICE_SUCCESS; +} + +/** + * ice_remove_eth_mac - Remove an ethertype (or MAC) based filter rule + * @hw: pointer to the hardware structure + * @em_list: list of ethertype or ethertype MAC entries + */ +enum ice_status +ice_remove_eth_mac(struct ice_hw *hw, struct LIST_HEAD_TYPE *em_list) +{ + struct ice_fltr_list_entry *em_list_itr, *tmp; + + if (!em_list || !hw) + return ICE_ERR_PARAM; + + LIST_FOR_EACH_ENTRY_SAFE(em_list_itr, tmp, em_list, ice_fltr_list_entry, + list_entry) { + enum ice_sw_lkup_type l_type = + em_list_itr->fltr_info.lkup_type; + + if (l_type != ICE_SW_LKUP_ETHERTYPE_MAC && + l_type != ICE_SW_LKUP_ETHERTYPE) + return ICE_ERR_PARAM; + + em_list_itr->status = ice_remove_rule_internal(hw, l_type, + em_list_itr); + if (em_list_itr->status) + return em_list_itr->status; + } + return ICE_SUCCESS; +} /**