scsi: ufs-mediatek: add error recovery for suspend and resume
authorStanley Chu <stanley.chu@mediatek.com>
Fri, 27 Mar 2020 09:53:29 +0000 (17:53 +0800)
committerMartin K. Petersen <martin.petersen@oracle.com>
Sun, 29 Mar 2020 22:10:58 +0000 (18:10 -0400)
Once fail happens during suspend and resume flow if the desired low power
link state is H8, link recovery is required for MediaTek UFS controller.

For resume flow, since power and clocks are already enabled before invoking
vendor's resume callback, simply using ufshcd_link_recovery() inside
callback is fine.

For suspend flow, the device power enters low power mode or is disabled
before suspend callback, thus ufshcd_link_recovery() can not be directly
used in vendor callback. One solution is to set the link to off state and
then ufshcd_host_reset_and_restore() will be executed by ufshcd_suspend().

Link: https://lore.kernel.org/r/20200327095329.10083-3-stanley.chu@mediatek.com
Reviewed-by: Avri Altman <avri.altman@wdc.com>
Signed-off-by: Stanley Chu <stanley.chu@mediatek.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
drivers/scsi/ufs/ufs-mediatek.c

index 40a66b31b31fd44b29283432bd0044fd081f6ed3..673c16596fb245fde320c04fb79c78a85c683a03 100644 (file)
@@ -499,8 +499,15 @@ static int ufs_mtk_suspend(struct ufs_hba *hba, enum ufs_pm_op pm_op)
 
        if (ufshcd_is_link_hibern8(hba)) {
                err = ufs_mtk_link_set_lpm(hba);
-               if (err)
+               if (err) {
+                       /*
+                        * Set link as off state enforcedly to trigger
+                        * ufshcd_host_reset_and_restore() in ufshcd_suspend()
+                        * for completed host reset.
+                        */
+                       ufshcd_set_link_off(hba);
                        return -EAGAIN;
+               }
        }
 
        if (!ufshcd_is_link_active(hba))
@@ -519,8 +526,10 @@ static int ufs_mtk_resume(struct ufs_hba *hba, enum ufs_pm_op pm_op)
 
        if (ufshcd_is_link_hibern8(hba)) {
                err = ufs_mtk_link_set_hpm(hba);
-               if (err)
+               if (err) {
+                       err = ufshcd_link_recovery(hba);
                        return err;
+               }
        }
 
        return 0;