mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-06 19:08:57 +09:00
UPSTREAM: 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>
Bug: 204438323
(cherry picked from commit 54a4045342)
Signed-off-by: Bart Van Assche <bvanassche@google.com>
Change-Id: Ibfa8f43aaa256c96efbfcb8e185067beb655d603
This commit is contained in:
committed by
Bart Van Assche
parent
e2919fba76
commit
ccba7d5b8e
@@ -7157,31 +7157,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.
|
||||
|
||||
Reference in New Issue
Block a user