|
|
|
|
@@ -1303,7 +1303,7 @@ static u32 ufshcd_pending_cmds(struct ufs_hba *hba)
|
|
|
|
|
*
|
|
|
|
|
* Return: 0 upon success; -EBUSY upon timeout.
|
|
|
|
|
*/
|
|
|
|
|
static int ufshcd_wait_for_doorbell_clr(struct ufs_hba *hba,
|
|
|
|
|
static int ufshcd_wait_for_pending_cmds(struct ufs_hba *hba,
|
|
|
|
|
u64 wait_timeout_us)
|
|
|
|
|
{
|
|
|
|
|
int ret = 0;
|
|
|
|
|
@@ -1431,7 +1431,7 @@ static int ufshcd_clock_scaling_prepare(struct ufs_hba *hba, u64 timeout_us)
|
|
|
|
|
down_write(&hba->clk_scaling_lock);
|
|
|
|
|
|
|
|
|
|
if (!hba->clk_scaling.is_allowed ||
|
|
|
|
|
ufshcd_wait_for_doorbell_clr(hba, timeout_us)) {
|
|
|
|
|
ufshcd_wait_for_pending_cmds(hba, timeout_us)) {
|
|
|
|
|
ret = -EBUSY;
|
|
|
|
|
up_write(&hba->clk_scaling_lock);
|
|
|
|
|
mutex_unlock(&hba->wb_mutex);
|
|
|
|
|
@@ -3199,7 +3199,8 @@ ufshcd_dev_cmd_completion(struct ufs_hba *hba, struct ufshcd_lrb *lrbp)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Return: 0 upon success; < 0 upon failure.
|
|
|
|
|
* Return: 0 upon success; > 0 in case the UFS device reported an OCS error;
|
|
|
|
|
* < 0 if another error occurred.
|
|
|
|
|
*/
|
|
|
|
|
static int ufshcd_wait_for_dev_cmd(struct ufs_hba *hba,
|
|
|
|
|
struct ufshcd_lrb *lrbp, int max_timeout)
|
|
|
|
|
@@ -3275,7 +3276,6 @@ static int ufshcd_wait_for_dev_cmd(struct ufs_hba *hba,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
WARN_ONCE(err > 0, "Incorrect return value %d > 0\n", err);
|
|
|
|
|
return err;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -3294,7 +3294,8 @@ static void ufshcd_dev_man_unlock(struct ufs_hba *hba)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Return: 0 upon success; < 0 upon failure.
|
|
|
|
|
* Return: 0 upon success; > 0 in case the UFS device reported an OCS error;
|
|
|
|
|
* < 0 if another error occurred.
|
|
|
|
|
*/
|
|
|
|
|
static int ufshcd_issue_dev_cmd(struct ufs_hba *hba, struct ufshcd_lrb *lrbp,
|
|
|
|
|
const u32 tag, int timeout)
|
|
|
|
|
@@ -3317,7 +3318,8 @@ static int ufshcd_issue_dev_cmd(struct ufs_hba *hba, struct ufshcd_lrb *lrbp,
|
|
|
|
|
* @cmd_type: specifies the type (NOP, Query...)
|
|
|
|
|
* @timeout: timeout in milliseconds
|
|
|
|
|
*
|
|
|
|
|
* Return: 0 upon success; < 0 upon failure.
|
|
|
|
|
* Return: 0 upon success; > 0 in case the UFS device reported an OCS error;
|
|
|
|
|
* < 0 if another error occurred.
|
|
|
|
|
*
|
|
|
|
|
* NOTE: Since there is only one available tag for device management commands,
|
|
|
|
|
* it is expected you hold the hba->dev_cmd.lock mutex.
|
|
|
|
|
@@ -3363,6 +3365,10 @@ static inline void ufshcd_init_query(struct ufs_hba *hba,
|
|
|
|
|
(*request)->upiu_req.selector = selector;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Return: 0 upon success; > 0 in case the UFS device reported an OCS error;
|
|
|
|
|
* < 0 if another error occurred.
|
|
|
|
|
*/
|
|
|
|
|
static int ufshcd_query_flag_retry(struct ufs_hba *hba,
|
|
|
|
|
enum query_opcode opcode, enum flag_idn idn, u8 index, bool *flag_res)
|
|
|
|
|
{
|
|
|
|
|
@@ -3383,7 +3389,6 @@ static int ufshcd_query_flag_retry(struct ufs_hba *hba,
|
|
|
|
|
dev_err(hba->dev,
|
|
|
|
|
"%s: query flag, opcode %d, idn %d, failed with error %d after %d retries\n",
|
|
|
|
|
__func__, opcode, idn, ret, retries);
|
|
|
|
|
WARN_ONCE(ret > 0, "Incorrect return value %d > 0\n", ret);
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -3395,7 +3400,8 @@ static int ufshcd_query_flag_retry(struct ufs_hba *hba,
|
|
|
|
|
* @index: flag index to access
|
|
|
|
|
* @flag_res: the flag value after the query request completes
|
|
|
|
|
*
|
|
|
|
|
* Return: 0 for success; < 0 upon failure.
|
|
|
|
|
* Return: 0 upon success; > 0 in case the UFS device reported an OCS error;
|
|
|
|
|
* < 0 if another error occurred.
|
|
|
|
|
*/
|
|
|
|
|
int ufshcd_query_flag(struct ufs_hba *hba, enum query_opcode opcode,
|
|
|
|
|
enum flag_idn idn, u8 index, bool *flag_res)
|
|
|
|
|
@@ -3451,7 +3457,6 @@ int ufshcd_query_flag(struct ufs_hba *hba, enum query_opcode opcode,
|
|
|
|
|
|
|
|
|
|
out_unlock:
|
|
|
|
|
ufshcd_dev_man_unlock(hba);
|
|
|
|
|
WARN_ONCE(err > 0, "Incorrect return value %d > 0\n", err);
|
|
|
|
|
return err;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -3464,8 +3469,9 @@ int ufshcd_query_flag(struct ufs_hba *hba, enum query_opcode opcode,
|
|
|
|
|
* @selector: selector field
|
|
|
|
|
* @attr_val: the attribute value after the query request completes
|
|
|
|
|
*
|
|
|
|
|
* Return: 0 upon success; < 0 upon failure.
|
|
|
|
|
*/
|
|
|
|
|
* Return: 0 upon success; > 0 in case the UFS device reported an OCS error;
|
|
|
|
|
* < 0 if another error occurred.
|
|
|
|
|
*/
|
|
|
|
|
int ufshcd_query_attr(struct ufs_hba *hba, enum query_opcode opcode,
|
|
|
|
|
enum attr_idn idn, u8 index, u8 selector, u32 *attr_val)
|
|
|
|
|
{
|
|
|
|
|
@@ -3513,7 +3519,6 @@ int ufshcd_query_attr(struct ufs_hba *hba, enum query_opcode opcode,
|
|
|
|
|
|
|
|
|
|
out_unlock:
|
|
|
|
|
ufshcd_dev_man_unlock(hba);
|
|
|
|
|
WARN_ONCE(err > 0, "Incorrect return value %d > 0\n", err);
|
|
|
|
|
return err;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -3528,8 +3533,9 @@ int ufshcd_query_attr(struct ufs_hba *hba, enum query_opcode opcode,
|
|
|
|
|
* @attr_val: the attribute value after the query request
|
|
|
|
|
* completes
|
|
|
|
|
*
|
|
|
|
|
* Return: 0 for success; < 0 upon failure.
|
|
|
|
|
*/
|
|
|
|
|
* Return: 0 upon success; > 0 in case the UFS device reported an OCS error;
|
|
|
|
|
* < 0 if another error occurred.
|
|
|
|
|
*/
|
|
|
|
|
int ufshcd_query_attr_retry(struct ufs_hba *hba,
|
|
|
|
|
enum query_opcode opcode, enum attr_idn idn, u8 index, u8 selector,
|
|
|
|
|
u32 *attr_val)
|
|
|
|
|
@@ -3551,12 +3557,12 @@ int ufshcd_query_attr_retry(struct ufs_hba *hba,
|
|
|
|
|
dev_err(hba->dev,
|
|
|
|
|
"%s: query attribute, idn %d, failed with error %d after %d retries\n",
|
|
|
|
|
__func__, idn, ret, QUERY_REQ_RETRIES);
|
|
|
|
|
WARN_ONCE(ret > 0, "Incorrect return value %d > 0\n", ret);
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Return: 0 if successful; < 0 upon failure.
|
|
|
|
|
* Return: 0 upon success; > 0 in case the UFS device reported an OCS error;
|
|
|
|
|
* < 0 if another error occurred.
|
|
|
|
|
*/
|
|
|
|
|
static int __ufshcd_query_descriptor(struct ufs_hba *hba,
|
|
|
|
|
enum query_opcode opcode, enum desc_idn idn, u8 index,
|
|
|
|
|
@@ -3615,7 +3621,6 @@ static int __ufshcd_query_descriptor(struct ufs_hba *hba,
|
|
|
|
|
out_unlock:
|
|
|
|
|
hba->dev_cmd.query.descriptor = NULL;
|
|
|
|
|
ufshcd_dev_man_unlock(hba);
|
|
|
|
|
WARN_ONCE(err > 0, "Incorrect return value %d > 0\n", err);
|
|
|
|
|
return err;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -3632,7 +3637,8 @@ static int __ufshcd_query_descriptor(struct ufs_hba *hba,
|
|
|
|
|
* The buf_len parameter will contain, on return, the length parameter
|
|
|
|
|
* received on the response.
|
|
|
|
|
*
|
|
|
|
|
* Return: 0 for success; < 0 upon failure.
|
|
|
|
|
* Return: 0 upon success; > 0 in case the UFS device reported an OCS error;
|
|
|
|
|
* < 0 if another error occurred.
|
|
|
|
|
*/
|
|
|
|
|
int ufshcd_query_descriptor_retry(struct ufs_hba *hba,
|
|
|
|
|
enum query_opcode opcode,
|
|
|
|
|
@@ -3650,7 +3656,6 @@ int ufshcd_query_descriptor_retry(struct ufs_hba *hba,
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
WARN_ONCE(err > 0, "Incorrect return value %d > 0\n", err);
|
|
|
|
|
return err;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -3663,7 +3668,8 @@ int ufshcd_query_descriptor_retry(struct ufs_hba *hba,
|
|
|
|
|
* @param_read_buf: pointer to buffer where parameter would be read
|
|
|
|
|
* @param_size: sizeof(param_read_buf)
|
|
|
|
|
*
|
|
|
|
|
* Return: 0 in case of success; < 0 upon failure.
|
|
|
|
|
* Return: 0 upon success; > 0 in case the UFS device reported an OCS error;
|
|
|
|
|
* < 0 if another error occurred.
|
|
|
|
|
*/
|
|
|
|
|
int ufshcd_read_desc_param(struct ufs_hba *hba,
|
|
|
|
|
enum desc_idn desc_id,
|
|
|
|
|
@@ -3730,7 +3736,6 @@ int ufshcd_read_desc_param(struct ufs_hba *hba,
|
|
|
|
|
out:
|
|
|
|
|
if (is_kmalloc)
|
|
|
|
|
kfree(desc_buf);
|
|
|
|
|
WARN_ONCE(ret > 0, "Incorrect return value %d > 0\n", ret);
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -4781,7 +4786,8 @@ EXPORT_SYMBOL_GPL(ufshcd_config_pwr_mode);
|
|
|
|
|
*
|
|
|
|
|
* Set fDeviceInit flag and poll until device toggles it.
|
|
|
|
|
*
|
|
|
|
|
* Return: 0 upon success; < 0 upon failure.
|
|
|
|
|
* Return: 0 upon success; > 0 in case the UFS device reported an OCS error;
|
|
|
|
|
* < 0 if another error occurred.
|
|
|
|
|
*/
|
|
|
|
|
static int ufshcd_complete_dev_init(struct ufs_hba *hba)
|
|
|
|
|
{
|
|
|
|
|
@@ -5135,7 +5141,8 @@ static int ufshcd_link_startup(struct ufs_hba *hba)
|
|
|
|
|
* not respond with NOP IN UPIU within timeout of %NOP_OUT_TIMEOUT
|
|
|
|
|
* and we retry sending NOP OUT for %NOP_OUT_RETRIES iterations.
|
|
|
|
|
*
|
|
|
|
|
* Return: 0 upon success; < 0 upon failure.
|
|
|
|
|
* Return: 0 upon success; > 0 in case the UFS device reported an OCS error;
|
|
|
|
|
* < 0 if another error occurred.
|
|
|
|
|
*/
|
|
|
|
|
static int ufshcd_verify_dev_init(struct ufs_hba *hba)
|
|
|
|
|
{
|
|
|
|
|
@@ -5559,9 +5566,9 @@ static irqreturn_t ufshcd_uic_cmd_compl(struct ufs_hba *hba, u32 intr_status)
|
|
|
|
|
irqreturn_t retval = IRQ_NONE;
|
|
|
|
|
struct uic_command *cmd;
|
|
|
|
|
|
|
|
|
|
spin_lock(hba->host->host_lock);
|
|
|
|
|
guard(spinlock_irqsave)(hba->host->host_lock);
|
|
|
|
|
cmd = hba->active_uic_cmd;
|
|
|
|
|
if (WARN_ON_ONCE(!cmd))
|
|
|
|
|
if (!cmd)
|
|
|
|
|
goto unlock;
|
|
|
|
|
|
|
|
|
|
if (ufshcd_is_auto_hibern8_error(hba, intr_status))
|
|
|
|
|
@@ -5586,8 +5593,6 @@ static irqreturn_t ufshcd_uic_cmd_compl(struct ufs_hba *hba, u32 intr_status)
|
|
|
|
|
ufshcd_add_uic_command_trace(hba, cmd, UFS_CMD_COMP);
|
|
|
|
|
|
|
|
|
|
unlock:
|
|
|
|
|
spin_unlock(hba->host->host_lock);
|
|
|
|
|
|
|
|
|
|
return retval;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -5869,7 +5874,8 @@ static inline int ufshcd_enable_ee(struct ufs_hba *hba, u16 mask)
|
|
|
|
|
* as the device is allowed to manage its own way of handling background
|
|
|
|
|
* operations.
|
|
|
|
|
*
|
|
|
|
|
* Return: zero on success, non-zero on failure.
|
|
|
|
|
* Return: 0 upon success; > 0 in case the UFS device reported an OCS error;
|
|
|
|
|
* < 0 if another error occurred.
|
|
|
|
|
*/
|
|
|
|
|
static int ufshcd_enable_auto_bkops(struct ufs_hba *hba)
|
|
|
|
|
{
|
|
|
|
|
@@ -5908,7 +5914,8 @@ static int ufshcd_enable_auto_bkops(struct ufs_hba *hba)
|
|
|
|
|
* host is idle so that BKOPS are managed effectively without any negative
|
|
|
|
|
* impacts.
|
|
|
|
|
*
|
|
|
|
|
* Return: zero on success, non-zero on failure.
|
|
|
|
|
* Return: 0 upon success; > 0 in case the UFS device reported an OCS error;
|
|
|
|
|
* < 0 if another error occurred.
|
|
|
|
|
*/
|
|
|
|
|
static int ufshcd_disable_auto_bkops(struct ufs_hba *hba)
|
|
|
|
|
{
|
|
|
|
|
@@ -6058,6 +6065,10 @@ static void ufshcd_bkops_exception_event_handler(struct ufs_hba *hba)
|
|
|
|
|
__func__, err);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Return: 0 upon success; > 0 in case the UFS device reported an OCS error;
|
|
|
|
|
* < 0 if another error occurred.
|
|
|
|
|
*/
|
|
|
|
|
int ufshcd_read_device_lvl_exception_id(struct ufs_hba *hba, u64 *exception_id)
|
|
|
|
|
{
|
|
|
|
|
struct utp_upiu_query_v4_0 *upiu_resp;
|
|
|
|
|
@@ -6920,7 +6931,7 @@ static irqreturn_t ufshcd_check_errors(struct ufs_hba *hba, u32 intr_status)
|
|
|
|
|
bool queue_eh_work = false;
|
|
|
|
|
irqreturn_t retval = IRQ_NONE;
|
|
|
|
|
|
|
|
|
|
spin_lock(hba->host->host_lock);
|
|
|
|
|
guard(spinlock_irqsave)(hba->host->host_lock);
|
|
|
|
|
hba->errors |= UFSHCD_ERROR_MASK & intr_status;
|
|
|
|
|
|
|
|
|
|
if (hba->errors & INT_FATAL_ERRORS) {
|
|
|
|
|
@@ -6979,7 +6990,7 @@ static irqreturn_t ufshcd_check_errors(struct ufs_hba *hba, u32 intr_status)
|
|
|
|
|
*/
|
|
|
|
|
hba->errors = 0;
|
|
|
|
|
hba->uic_error = 0;
|
|
|
|
|
spin_unlock(hba->host->host_lock);
|
|
|
|
|
|
|
|
|
|
return retval;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -7454,7 +7465,8 @@ int ufshcd_exec_raw_upiu_cmd(struct ufs_hba *hba,
|
|
|
|
|
* @sg_list: Pointer to SG list when DATA IN/OUT UPIU is required in ARPMB operation
|
|
|
|
|
* @dir: DMA direction
|
|
|
|
|
*
|
|
|
|
|
* Return: zero on success, non-zero on failure.
|
|
|
|
|
* Return: 0 upon success; > 0 in case the UFS device reported an OCS error;
|
|
|
|
|
* < 0 if another error occurred.
|
|
|
|
|
*/
|
|
|
|
|
int ufshcd_advanced_rpmb_req_handler(struct ufs_hba *hba, struct utp_upiu_req *req_upiu,
|
|
|
|
|
struct utp_upiu_req *rsp_upiu, struct ufs_ehs *req_ehs,
|
|
|
|
|
|