scsi: ufs: Minor adjustments to error handling
In error handling prepare stage, after SCSI requests are blocked, do a down/up_write(clk_scaling_lock) to clean up the queuecommand() path. Meanwhile, stop eeh_work in case it disturbs error recovery. Moreover, reset ufshcd_state at the entrance of ufshcd_probe_hba(), since it may be called multiple times during error recovery. Link: https://lore.kernel.org/r/1614145010-36079-2-git-send-email-cang@codeaurora.org Reviewed-by: Avri Altman <avri.altman@wdc.com> Signed-off-by: Can Guo <cang@codeaurora.org> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
This commit is contained in:
parent
dbdbb81bde
commit
aa53f580e6
@ -4987,6 +4987,7 @@ ufshcd_transfer_rsp_status(struct ufs_hba *hba, struct ufshcd_lrb *lrbp)
|
||||
* UFS device needs urgent BKOPs.
|
||||
*/
|
||||
if (!hba->pm_op_in_progress &&
|
||||
!ufshcd_eh_in_progress(hba) &&
|
||||
ufshcd_is_exception_event(lrbp->ucd_rsp_ptr) &&
|
||||
schedule_work(&hba->eeh_work)) {
|
||||
/*
|
||||
@ -5784,13 +5785,20 @@ static void ufshcd_err_handling_prepare(struct ufs_hba *hba)
|
||||
ufshcd_suspend_clkscaling(hba);
|
||||
ufshcd_clk_scaling_allow(hba, false);
|
||||
}
|
||||
ufshcd_scsi_block_requests(hba);
|
||||
/* Drain ufshcd_queuecommand() */
|
||||
down_write(&hba->clk_scaling_lock);
|
||||
up_write(&hba->clk_scaling_lock);
|
||||
cancel_work_sync(&hba->eeh_work);
|
||||
}
|
||||
|
||||
static void ufshcd_err_handling_unprepare(struct ufs_hba *hba)
|
||||
{
|
||||
ufshcd_scsi_unblock_requests(hba);
|
||||
ufshcd_release(hba);
|
||||
if (ufshcd_is_clkscaling_supported(hba))
|
||||
ufshcd_clk_scaling_suspend(hba, false);
|
||||
ufshcd_clear_ua_wluns(hba);
|
||||
pm_runtime_put(hba->dev);
|
||||
}
|
||||
|
||||
@ -5882,8 +5890,8 @@ static void ufshcd_err_handler(struct work_struct *work)
|
||||
spin_unlock_irqrestore(hba->host->host_lock, flags);
|
||||
ufshcd_err_handling_prepare(hba);
|
||||
spin_lock_irqsave(hba->host->host_lock, flags);
|
||||
ufshcd_scsi_block_requests(hba);
|
||||
hba->ufshcd_state = UFSHCD_STATE_RESET;
|
||||
if (hba->ufshcd_state != UFSHCD_STATE_ERROR)
|
||||
hba->ufshcd_state = UFSHCD_STATE_RESET;
|
||||
|
||||
/* Complete requests that have door-bell cleared by h/w */
|
||||
ufshcd_complete_requests(hba);
|
||||
@ -6042,12 +6050,8 @@ skip_err_handling:
|
||||
}
|
||||
ufshcd_clear_eh_in_progress(hba);
|
||||
spin_unlock_irqrestore(hba->host->host_lock, flags);
|
||||
ufshcd_scsi_unblock_requests(hba);
|
||||
ufshcd_err_handling_unprepare(hba);
|
||||
up(&hba->host_sem);
|
||||
|
||||
if (!err && needs_reset)
|
||||
ufshcd_clear_ua_wluns(hba);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -7858,6 +7862,8 @@ static int ufshcd_probe_hba(struct ufs_hba *hba, bool async)
|
||||
unsigned long flags;
|
||||
ktime_t start = ktime_get();
|
||||
|
||||
hba->ufshcd_state = UFSHCD_STATE_RESET;
|
||||
|
||||
ret = ufshcd_link_startup(hba);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
Loading…
x
Reference in New Issue
Block a user