scsi: sd: Ignore sync failures when not supported
Some external hard drives don't support the sync command even though the hard drive has write cache enabled. In this case, ignore sync cache failures when the error is for an illegal request for suspend. There's not much we can do for these drives, so we shouldn't fail to suspend for this error case. The drive may stay powered if that's setup for the port you have it plugged into. BUG=chromium:282666 TEST=Plus Lacie hard drive into machine and make sure the machine can suspend. The Lacie hard drive may stay powered depending on the machine. Change-Id: I88248f0715b70eae33eda171df3b803a5d7513b3 Signed-off-by: Derek Basehore <dbasehore@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/172863 Reviewed-by: Grant Grundler <grundler@chromium.org> [benzh: 3.14 rebase. Merged error handling code for sd_sync_cache()] Signed-off-by: Ben Zhang <benzh@chromium.org>
This commit is contained in:
committed by
Ben Zhang
parent
9a1ed62ce8
commit
bd3c11e205
@@ -1432,7 +1432,7 @@ out:
|
||||
return retval;
|
||||
}
|
||||
|
||||
static int sd_sync_cache(struct scsi_disk *sdkp)
|
||||
static int sd_sync_cache(struct scsi_disk *sdkp, int *sense_key)
|
||||
{
|
||||
int retries, res;
|
||||
struct scsi_device *sdp = sdkp->device;
|
||||
@@ -1461,8 +1461,11 @@ static int sd_sync_cache(struct scsi_disk *sdkp)
|
||||
if (res) {
|
||||
sd_print_result(sdkp, res);
|
||||
|
||||
if (driver_byte(res) & DRIVER_SENSE)
|
||||
if (driver_byte(res) & DRIVER_SENSE) {
|
||||
sd_print_sense_hdr(sdkp, &sshdr);
|
||||
if (sense_key)
|
||||
*sense_key = sshdr.sense_key;
|
||||
}
|
||||
/* we need to evaluate the error return */
|
||||
if (scsi_sense_valid(&sshdr) &&
|
||||
/* 0x3a is medium not present */
|
||||
@@ -3123,7 +3126,7 @@ static void sd_shutdown(struct device *dev)
|
||||
|
||||
if (sdkp->WCE && sdkp->media_present) {
|
||||
sd_printk(KERN_NOTICE, sdkp, "Synchronizing SCSI cache\n");
|
||||
sd_sync_cache(sdkp);
|
||||
sd_sync_cache(sdkp, NULL);
|
||||
}
|
||||
|
||||
if (system_state != SYSTEM_RESTART && sdkp->device->manage_start_stop) {
|
||||
@@ -3138,6 +3141,7 @@ exit:
|
||||
static int sd_suspend_common(struct device *dev, bool ignore_stop_errors)
|
||||
{
|
||||
struct scsi_disk *sdkp = scsi_disk_get_from_dev(dev);
|
||||
int sense_key = 0;
|
||||
int ret = 0;
|
||||
|
||||
if (!sdkp)
|
||||
@@ -3149,12 +3153,20 @@ static int sd_suspend_common(struct device *dev, bool ignore_stop_errors)
|
||||
|
||||
if (sdkp->WCE && sdkp->media_present) {
|
||||
sd_printk(KERN_NOTICE, sdkp, "Synchronizing SCSI cache\n");
|
||||
ret = sd_sync_cache(sdkp);
|
||||
ret = sd_sync_cache(sdkp, &sense_key);
|
||||
if (ret) {
|
||||
/* ignore OFFLINE device */
|
||||
if (ret == -ENODEV)
|
||||
if (sense_key == ILLEGAL_REQUEST) {
|
||||
/*
|
||||
* If this is a bad drive that doesn't support
|
||||
* sync, there's not much to do.
|
||||
*/
|
||||
ret = 0;
|
||||
goto done;
|
||||
} else {
|
||||
/* ignore OFFLINE device */
|
||||
if (ret == -ENODEV)
|
||||
ret = 0;
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user