diff options
Diffstat (limited to 'drivers/net/ethernet/intel/ice/ice_common.c')
-rw-r--r-- | drivers/net/ethernet/intel/ice/ice_common.c | 130 |
1 files changed, 95 insertions, 35 deletions
diff --git a/drivers/net/ethernet/intel/ice/ice_common.c b/drivers/net/ethernet/intel/ice/ice_common.c index 68fbbb92d504..8cd6a2401fd9 100644 --- a/drivers/net/ethernet/intel/ice/ice_common.c +++ b/drivers/net/ethernet/intel/ice/ice_common.c @@ -43,6 +43,23 @@ static enum ice_status ice_set_mac_type(struct ice_hw *hw) } /** + * ice_dev_onetime_setup - Temporary HW/FW workarounds + * @hw: pointer to the HW structure + * + * This function provides temporary workarounds for certain issues + * that are expected to be fixed in the HW/FW. + */ +void ice_dev_onetime_setup(struct ice_hw *hw) +{ + /* configure Rx - set non pxe mode */ + wr32(hw, GLLAN_RCTL_0, 0x1); + +#define MBX_PF_VT_PFALLOC 0x00231E80 + /* set VFs per PF */ + wr32(hw, MBX_PF_VT_PFALLOC, rd32(hw, PF_VT_PFALLOC_HIF)); +} + +/** * ice_clear_pf_cfg - Clear PF configuration * @hw: pointer to the hardware structure * @@ -218,7 +235,7 @@ static enum ice_media_type ice_get_media_type(struct ice_port_info *pi) * * Get Link Status (0x607). Returns the link status of the adapter. */ -enum ice_status +static enum ice_status ice_aq_get_link_info(struct ice_port_info *pi, bool ena_lse, struct ice_link_status *link, struct ice_sq_cd *cd) { @@ -740,6 +757,8 @@ enum ice_status ice_init_hw(struct ice_hw *hw) if (status) goto err_unroll_sched; + ice_dev_onetime_setup(hw); + /* Get MAC information */ /* A single port can report up to two (LAN and WoL) addresses */ mac_buf = devm_kcalloc(ice_hw_to_dev(hw), 2, @@ -1406,6 +1425,28 @@ ice_parse_caps(struct ice_hw *hw, void *buf, u32 cap_count, u16 cap = le16_to_cpu(cap_resp->cap); switch (cap) { + case ICE_AQC_CAPS_SRIOV: + caps->sr_iov_1_1 = (number == 1); + ice_debug(hw, ICE_DBG_INIT, + "HW caps: SR-IOV = %d\n", caps->sr_iov_1_1); + break; + case ICE_AQC_CAPS_VF: + if (dev_p) { + dev_p->num_vfs_exposed = number; + ice_debug(hw, ICE_DBG_INIT, + "HW caps: VFs exposed = %d\n", + dev_p->num_vfs_exposed); + } else if (func_p) { + func_p->num_allocd_vfs = number; + func_p->vf_base_id = logical_id; + ice_debug(hw, ICE_DBG_INIT, + "HW caps: VFs allocated = %d\n", + func_p->num_allocd_vfs); + ice_debug(hw, ICE_DBG_INIT, + "HW caps: VF base_id = %d\n", + func_p->vf_base_id); + } + break; case ICE_AQC_CAPS_VSI: if (dev_p) { dev_p->num_vsi_allocd_to_host = number; @@ -1509,9 +1550,7 @@ ice_aq_discover_caps(struct ice_hw *hw, void *buf, u16 buf_size, u32 *cap_count, if (!status) ice_parse_caps(hw, buf, le32_to_cpu(cmd->count), opc); else if (hw->adminq.sq_last_status == ICE_AQ_RC_ENOMEM) - *cap_count = - DIV_ROUND_UP(le16_to_cpu(desc.datalen), - sizeof(struct ice_aqc_list_caps_elem)); + *cap_count = le32_to_cpu(cmd->count); return status; } @@ -1966,33 +2005,6 @@ ice_aq_set_link_restart_an(struct ice_port_info *pi, bool ena_link, } /** - * ice_aq_set_event_mask - * @hw: pointer to the hw struct - * @port_num: port number of the physical function - * @mask: event mask to be set - * @cd: pointer to command details structure or NULL - * - * Set event mask (0x0613) - */ -enum ice_status -ice_aq_set_event_mask(struct ice_hw *hw, u8 port_num, u16 mask, - struct ice_sq_cd *cd) -{ - struct ice_aqc_set_event_mask *cmd; - struct ice_aq_desc desc; - - cmd = &desc.params.set_event_mask; - - ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_set_event_mask); - - cmd->lport_num = port_num; - - cmd->event_mask = cpu_to_le16(mask); - - return ice_aq_send_cmd(hw, &desc, NULL, 0, cd); -} - -/** * __ice_aq_get_set_rss_lut * @hw: pointer to the hardware structure * @vsi_id: VSI FW index @@ -2265,6 +2277,8 @@ ice_aq_add_lan_txq(struct ice_hw *hw, u8 num_qgrps, * @num_qgrps: number of groups in the list * @qg_list: the list of groups to disable * @buf_size: the total size of the qg_list buffer in bytes + * @rst_src: if called due to reset, specifies the RST source + * @vmvf_num: the relative VM or VF number that is undergoing the reset * @cd: pointer to command details structure or NULL * * Disable LAN Tx queue (0x0C31) @@ -2272,6 +2286,7 @@ ice_aq_add_lan_txq(struct ice_hw *hw, u8 num_qgrps, static enum ice_status ice_aq_dis_lan_txq(struct ice_hw *hw, u8 num_qgrps, struct ice_aqc_dis_txq_item *qg_list, u16 buf_size, + enum ice_disq_rst_src rst_src, u16 vmvf_num, struct ice_sq_cd *cd) { struct ice_aqc_dis_txqs *cmd; @@ -2281,14 +2296,45 @@ ice_aq_dis_lan_txq(struct ice_hw *hw, u8 num_qgrps, cmd = &desc.params.dis_txqs; ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_dis_txqs); - if (!qg_list) + /* qg_list can be NULL only in VM/VF reset flow */ + if (!qg_list && !rst_src) return ICE_ERR_PARAM; if (num_qgrps > ICE_LAN_TXQ_MAX_QGRPS) return ICE_ERR_PARAM; - desc.flags |= cpu_to_le16(ICE_AQ_FLAG_RD); + cmd->num_entries = num_qgrps; + cmd->vmvf_and_timeout = cpu_to_le16((5 << ICE_AQC_Q_DIS_TIMEOUT_S) & + ICE_AQC_Q_DIS_TIMEOUT_M); + + switch (rst_src) { + case ICE_VM_RESET: + cmd->cmd_type = ICE_AQC_Q_DIS_CMD_VM_RESET; + cmd->vmvf_and_timeout |= + cpu_to_le16(vmvf_num & ICE_AQC_Q_DIS_VMVF_NUM_M); + break; + case ICE_VF_RESET: + cmd->cmd_type = ICE_AQC_Q_DIS_CMD_VF_RESET; + /* In this case, FW expects vmvf_num to be absolute VF id */ + cmd->vmvf_and_timeout |= + cpu_to_le16((vmvf_num + hw->func_caps.vf_base_id) & + ICE_AQC_Q_DIS_VMVF_NUM_M); + break; + case ICE_NO_RESET: + default: + break; + } + + /* If no queue group info, we are in a reset flow. Issue the AQ */ + if (!qg_list) + goto do_aq; + + /* set RD bit to indicate that command buffer is provided by the driver + * and it needs to be read by the firmware + */ + desc.flags |= cpu_to_le16(ICE_AQ_FLAG_RD); + for (i = 0; i < num_qgrps; ++i) { /* Calculate the size taken up by the queue IDs in this group */ sz += qg_list[i].num_qs * sizeof(qg_list[i].q_id); @@ -2304,6 +2350,7 @@ ice_aq_dis_lan_txq(struct ice_hw *hw, u8 num_qgrps, if (buf_size != sz) return ICE_ERR_PARAM; +do_aq: return ice_aq_send_cmd(hw, &desc, qg_list, buf_size, cd); } @@ -2610,13 +2657,16 @@ ena_txq_exit: * @num_queues: number of queues * @q_ids: pointer to the q_id array * @q_teids: pointer to queue node teids + * @rst_src: if called due to reset, specifies the RST source + * @vmvf_num: the relative VM or VF number that is undergoing the reset * @cd: pointer to command details structure or NULL * * This function removes queues and their corresponding nodes in SW DB */ enum ice_status ice_dis_vsi_txq(struct ice_port_info *pi, u8 num_queues, u16 *q_ids, - u32 *q_teids, struct ice_sq_cd *cd) + u32 *q_teids, enum ice_disq_rst_src rst_src, u16 vmvf_num, + struct ice_sq_cd *cd) { enum ice_status status = ICE_ERR_DOES_NOT_EXIST; struct ice_aqc_dis_txq_item qg_list; @@ -2625,6 +2675,15 @@ ice_dis_vsi_txq(struct ice_port_info *pi, u8 num_queues, u16 *q_ids, if (!pi || pi->port_state != ICE_SCHED_PORT_STATE_READY) return ICE_ERR_CFG; + /* if queue is disabled already yet the disable queue command has to be + * sent to complete the VF reset, then call ice_aq_dis_lan_txq without + * any queue information + */ + + if (!num_queues && rst_src) + return ice_aq_dis_lan_txq(pi->hw, 0, NULL, 0, rst_src, vmvf_num, + NULL); + mutex_lock(&pi->sched_lock); for (i = 0; i < num_queues; i++) { @@ -2637,7 +2696,8 @@ ice_dis_vsi_txq(struct ice_port_info *pi, u8 num_queues, u16 *q_ids, qg_list.num_qs = 1; qg_list.q_id[0] = cpu_to_le16(q_ids[i]); status = ice_aq_dis_lan_txq(pi->hw, 1, &qg_list, - sizeof(qg_list), cd); + sizeof(qg_list), rst_src, vmvf_num, + cd); if (status) break; |