From: Xiang Chen chenxiang66@hisilicon.com
driver inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I7BNF8 CVE: NA
----------------------------------------------------------------------
When sending START_STOP commands to resume scsi_device, it may be interrupted by exception operations such as host reset or FLR. Once the command of START_STOP is failed, the runtime_status of scsi device will be error and it is difficult for user to recover it. So try more retries to increase robustness as the process of command SYNCHRONIZE_CACHE in function sd_sync_cache() when suspending scsi device.
Signed-off-by: Xiang Chen chenxiang66@hisilicon.com Signed-off-by: xiabing xiabing12@h-partners.com --- drivers/scsi/sd.c | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-)
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index b5bd2d3c0e87..7c8bfb26c995 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -3663,6 +3663,7 @@ static int sd_suspend_common(struct device *dev, bool ignore_stop_errors) { struct scsi_disk *sdkp = dev_get_drvdata(dev); struct scsi_sense_hdr sshdr; + int retries; int ret = 0;
if (!sdkp) /* E.g.: runtime suspend following sd_remove() */ @@ -3693,9 +3694,15 @@ static int sd_suspend_common(struct device *dev, bool ignore_stop_errors) if (sdkp->device->manage_start_stop) { sd_printk(KERN_NOTICE, sdkp, "Stopping disk\n"); /* an error is not worth aborting a system sleep */ - ret = sd_start_stop_device(sdkp, 0); - if (ignore_stop_errors) - ret = 0; + for (retries = 3; retries > 0; --retries) { + ret = sd_start_stop_device(sdkp, 0); + if (!ret) + break; + if (ignore_stop_errors) { + ret = 0; + break; + } + } }
return ret; @@ -3714,6 +3721,7 @@ static int sd_suspend_runtime(struct device *dev) static int sd_resume(struct device *dev) { struct scsi_disk *sdkp = dev_get_drvdata(dev); + int retries; int ret;
if (!sdkp) /* E.g.: runtime resume at the start of sd_probe() */ @@ -3723,9 +3731,13 @@ static int sd_resume(struct device *dev) return 0;
sd_printk(KERN_NOTICE, sdkp, "Starting disk\n"); - ret = sd_start_stop_device(sdkp, 1); - if (!ret) - opal_unlock_from_suspend(sdkp->opal_dev); + for (retries = 3; retries > 0; --retries) { + ret = sd_start_stop_device(sdkp, 1); + if (!ret) { + opal_unlock_from_suspend(sdkp->opal_dev); + break; + } + } return ret; }