@@ -106,6 +106,13 @@
16, 4, buf, __len, false); \
} while (0)
+#define ufshcd_force_error_recovery(hba) do { \
+ spin_lock_irq(hba->host->host_lock); \
+ hba->force_reset = true; \
+ ufshcd_schedule_eh_work(hba); \
+ spin_unlock_irq(hba->host->host_lock); \
+} while (0)
+
int ufshcd_dump_regs(struct ufs_hba *hba, size_t offset, size_t len,
const char *prefix)
{
@@ -9049,6 +9056,15 @@ static int __ufshcd_wl_suspend(struct ufs_hba *hba, enum ufs_pm_op pm_op)
if (!hba->dev_info.b_rpm_dev_flush_capable) {
ret = ufshcd_set_dev_pwr_mode(hba, req_dev_pwr_mode);
+ if (ret && pm_op != UFS_SHUTDOWN_PM) {
+ /*
+ * If return err in suspend flow, IO will hang.
+ * Trigger error handler and break suspend for
+ * error recovery.
+ */
+ ufshcd_force_error_recovery(hba);
+ ret = -EBUSY;
+ }
if (ret)
goto enable_scaling;
}
@@ -9060,6 +9076,15 @@ static int __ufshcd_wl_suspend(struct ufs_hba *hba, enum ufs_pm_op pm_op)
*/
check_for_bkops = !ufshcd_is_ufs_dev_deepsleep(hba);
ret = ufshcd_link_state_transition(hba, req_link_state, check_for_bkops);
+ if (ret && pm_op != UFS_SHUTDOWN_PM) {
+ /*
+ * If return err in suspend flow, IO will hang.
+ * Trigger error handler and break suspend for
+ * error recovery.
+ */
+ ufshcd_force_error_recovery(hba);
+ ret = -EBUSY;
+ }
if (ret)
goto set_dev_active;