Commit 54a40453 authored by Adrian Hunter's avatar Adrian Hunter Committed by Martin K. Petersen
Browse files

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: default avatarAvri altman <avri.altman@wdc.com>
Signed-off-by: default avatarAdrian Hunter <adrian.hunter@intel.com>
Signed-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
parent edc0596c
Loading
Loading
Loading
Loading
+23 −13
Original line number Diff line number Diff line
@@ -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;

	spin_lock_irqsave(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.
		 */
	spin_lock_irqsave(hba->host->host_lock, flags);
	saved_err = hba->saved_err;
	saved_uic_err = hba->saved_uic_err;
		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);

	do {
		/* Reset the attached device */
		ufshcd_device_reset(hba);

		err = ufshcd_host_reset_and_restore(hba);
	} while (err && --retries);

		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);

	/*
	 * Inform scsi mid-layer that we did reset and allow to handle
	 * Unit Attention properly.