mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-27 14:14:24 +08:00
scsi: ufs: core: Do not exit ufshcd_reset_and_restore() unless operational or dead
Callers of ufshcd_reset_and_restore() expect it to return in an operational state. However, the code only checks direct errors and so the ufshcd_state may not be UFSHCD_STATE_OPERATIONAL due to error interrupts. Fix by also checking ufshcd_state, still allowing non-fatal errors which are left for the error handler to deal with. Link: https://lore.kernel.org/r/20211002154550.128511-2-adrian.hunter@intel.com Reviewed-by: Avri altman <avri.altman@wdc.com> Signed-off-by: Adrian Hunter <adrian.hunter@intel.com> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
This commit is contained in:
parent
edc0596cc0
commit
54a4045342
@ -7151,31 +7151,41 @@ static int ufshcd_host_reset_and_restore(struct ufs_hba *hba)
|
||||
*/
|
||||
static int ufshcd_reset_and_restore(struct ufs_hba *hba)
|
||||
{
|
||||
u32 saved_err;
|
||||
u32 saved_uic_err;
|
||||
u32 saved_err = 0;
|
||||
u32 saved_uic_err = 0;
|
||||
int err = 0;
|
||||
unsigned long flags;
|
||||
int retries = MAX_HOST_RESET_RETRIES;
|
||||
|
||||
/*
|
||||
* This is a fresh start, cache and clear saved error first,
|
||||
* in case new error generated during reset and restore.
|
||||
*/
|
||||
spin_lock_irqsave(hba->host->host_lock, flags);
|
||||
saved_err = hba->saved_err;
|
||||
saved_uic_err = hba->saved_uic_err;
|
||||
hba->saved_err = 0;
|
||||
hba->saved_uic_err = 0;
|
||||
spin_unlock_irqrestore(hba->host->host_lock, flags);
|
||||
|
||||
do {
|
||||
/*
|
||||
* This is a fresh start, cache and clear saved error first,
|
||||
* in case new error generated during reset and restore.
|
||||
*/
|
||||
saved_err |= hba->saved_err;
|
||||
saved_uic_err |= hba->saved_uic_err;
|
||||
hba->saved_err = 0;
|
||||
hba->saved_uic_err = 0;
|
||||
hba->force_reset = false;
|
||||
hba->ufshcd_state = UFSHCD_STATE_RESET;
|
||||
spin_unlock_irqrestore(hba->host->host_lock, flags);
|
||||
|
||||
/* Reset the attached device */
|
||||
ufshcd_device_reset(hba);
|
||||
|
||||
err = ufshcd_host_reset_and_restore(hba);
|
||||
|
||||
spin_lock_irqsave(hba->host->host_lock, flags);
|
||||
if (err)
|
||||
continue;
|
||||
/* Do not exit unless operational or dead */
|
||||
if (hba->ufshcd_state != UFSHCD_STATE_OPERATIONAL &&
|
||||
hba->ufshcd_state != UFSHCD_STATE_ERROR &&
|
||||
hba->ufshcd_state != UFSHCD_STATE_EH_SCHEDULED_NON_FATAL)
|
||||
err = -EAGAIN;
|
||||
} while (err && --retries);
|
||||
|
||||
spin_lock_irqsave(hba->host->host_lock, flags);
|
||||
/*
|
||||
* Inform scsi mid-layer that we did reset and allow to handle
|
||||
* Unit Attention properly.
|
||||
|
Loading…
Reference in New Issue
Block a user