aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/sd.c
diff options
context:
space:
mode:
authorOliver Neukum <oneukum@suse.de>2013-09-16 07:28:15 -0400
committerJames Bottomley <JBottomley@Parallels.com>2013-10-25 04:58:13 -0400
commit95897910a5b8ecdc7e86ca2c38e21e84324c98bd (patch)
tree8bcc6ac1c69edbc663c8cd0ec3255cce44e1674e /drivers/scsi/sd.c
parentaf73623f5f10eb3832c87a169b28f7df040a875b (diff)
[SCSI] sd: Add error handling during flushing caches
It makes no sense to flush the cache of a device without medium. Errors during suspend must be handled according to their causes. Errors due to missing media or unplugged devices must be ignored. Errors due to devices being offlined must also be ignored. The error returns must be modified so that the generic layer understands them. [jejb: fix up whitespace and other formatting problems] Signed-off-by: Oliver Neukum <oneukum@suse.de> Acked-by: Alan Stern <stern@rowland.harvard.edu> Signed-off-by: James Bottomley <JBottomley@Parallels.com>
Diffstat (limited to 'drivers/scsi/sd.c')
-rw-r--r--drivers/scsi/sd.c70
1 files changed, 57 insertions, 13 deletions
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
index ab96b793f904..3824e754ca1d 100644
--- a/drivers/scsi/sd.c
+++ b/drivers/scsi/sd.c
@@ -105,7 +105,8 @@ static void sd_unlock_native_capacity(struct gendisk *disk);
105static int sd_probe(struct device *); 105static int sd_probe(struct device *);
106static int sd_remove(struct device *); 106static int sd_remove(struct device *);
107static void sd_shutdown(struct device *); 107static void sd_shutdown(struct device *);
108static int sd_suspend(struct device *); 108static int sd_suspend_system(struct device *);
109static int sd_suspend_runtime(struct device *);
109static int sd_resume(struct device *); 110static int sd_resume(struct device *);
110static void sd_rescan(struct device *); 111static void sd_rescan(struct device *);
111static int sd_done(struct scsi_cmnd *); 112static int sd_done(struct scsi_cmnd *);
@@ -484,11 +485,11 @@ static struct class sd_disk_class = {
484}; 485};
485 486
486static const struct dev_pm_ops sd_pm_ops = { 487static const struct dev_pm_ops sd_pm_ops = {
487 .suspend = sd_suspend, 488 .suspend = sd_suspend_system,
488 .resume = sd_resume, 489 .resume = sd_resume,
489 .poweroff = sd_suspend, 490 .poweroff = sd_suspend_system,
490 .restore = sd_resume, 491 .restore = sd_resume,
491 .runtime_suspend = sd_suspend, 492 .runtime_suspend = sd_suspend_runtime,
492 .runtime_resume = sd_resume, 493 .runtime_resume = sd_resume,
493}; 494};
494 495
@@ -1438,7 +1439,6 @@ static int sd_sync_cache(struct scsi_disk *sdkp)
1438 if (!scsi_device_online(sdp)) 1439 if (!scsi_device_online(sdp))
1439 return -ENODEV; 1440 return -ENODEV;
1440 1441
1441
1442 for (retries = 3; retries > 0; --retries) { 1442 for (retries = 3; retries > 0; --retries) {
1443 unsigned char cmd[10] = { 0 }; 1443 unsigned char cmd[10] = { 0 };
1444 1444
@@ -1456,12 +1456,31 @@ static int sd_sync_cache(struct scsi_disk *sdkp)
1456 1456
1457 if (res) { 1457 if (res) {
1458 sd_print_result(sdkp, res); 1458 sd_print_result(sdkp, res);
1459
1459 if (driver_byte(res) & DRIVER_SENSE) 1460 if (driver_byte(res) & DRIVER_SENSE)
1460 sd_print_sense_hdr(sdkp, &sshdr); 1461 sd_print_sense_hdr(sdkp, &sshdr);
1462 /* we need to evaluate the error return */
1463 if (scsi_sense_valid(&sshdr) &&
1464 /* 0x3a is medium not present */
1465 sshdr.asc == 0x3a)
1466 /* this is no error here */
1467 return 0;
1468
1469 switch (host_byte(res)) {
1470 /* ignore errors due to racing a disconnection */
1471 case DID_BAD_TARGET:
1472 case DID_NO_CONNECT:
1473 return 0;
1474 /* signal the upper layer it might try again */
1475 case DID_BUS_BUSY:
1476 case DID_IMM_RETRY:
1477 case DID_REQUEUE:
1478 case DID_SOFT_ERROR:
1479 return -EBUSY;
1480 default:
1481 return -EIO;
1482 }
1461 } 1483 }
1462
1463 if (res)
1464 return -EIO;
1465 return 0; 1484 return 0;
1466} 1485}
1467 1486
@@ -3061,9 +3080,17 @@ static int sd_start_stop_device(struct scsi_disk *sdkp, int start)
3061 sd_print_result(sdkp, res); 3080 sd_print_result(sdkp, res);
3062 if (driver_byte(res) & DRIVER_SENSE) 3081 if (driver_byte(res) & DRIVER_SENSE)
3063 sd_print_sense_hdr(sdkp, &sshdr); 3082 sd_print_sense_hdr(sdkp, &sshdr);
3083 if (scsi_sense_valid(&sshdr) &&
3084 /* 0x3a is medium not present */
3085 sshdr.asc == 0x3a)
3086 res = 0;
3064 } 3087 }
3065 3088
3066 return res; 3089 /* SCSI error codes must not go to the generic layer */
3090 if (res)
3091 return -EIO;
3092
3093 return 0;
3067} 3094}
3068 3095
3069/* 3096/*
@@ -3081,7 +3108,7 @@ static void sd_shutdown(struct device *dev)
3081 if (pm_runtime_suspended(dev)) 3108 if (pm_runtime_suspended(dev))
3082 goto exit; 3109 goto exit;
3083 3110
3084 if (sdkp->WCE) { 3111 if (sdkp->WCE && sdkp->media_present) {
3085 sd_printk(KERN_NOTICE, sdkp, "Synchronizing SCSI cache\n"); 3112 sd_printk(KERN_NOTICE, sdkp, "Synchronizing SCSI cache\n");
3086 sd_sync_cache(sdkp); 3113 sd_sync_cache(sdkp);
3087 } 3114 }
@@ -3095,7 +3122,7 @@ exit:
3095 scsi_disk_put(sdkp); 3122 scsi_disk_put(sdkp);
3096} 3123}
3097 3124
3098static int sd_suspend(struct device *dev) 3125static int sd_suspend_common(struct device *dev, bool ignore_stop_errors)
3099{ 3126{
3100 struct scsi_disk *sdkp = scsi_disk_get_from_dev(dev); 3127 struct scsi_disk *sdkp = scsi_disk_get_from_dev(dev);
3101 int ret = 0; 3128 int ret = 0;
@@ -3103,16 +3130,23 @@ static int sd_suspend(struct device *dev)
3103 if (!sdkp) 3130 if (!sdkp)
3104 return 0; /* this can happen */ 3131 return 0; /* this can happen */
3105 3132
3106 if (sdkp->WCE) { 3133 if (sdkp->WCE && sdkp->media_present) {
3107 sd_printk(KERN_NOTICE, sdkp, "Synchronizing SCSI cache\n"); 3134 sd_printk(KERN_NOTICE, sdkp, "Synchronizing SCSI cache\n");
3108 ret = sd_sync_cache(sdkp); 3135 ret = sd_sync_cache(sdkp);
3109 if (ret) 3136 if (ret) {
3137 /* ignore OFFLINE device */
3138 if (ret == -ENODEV)
3139 ret = 0;
3110 goto done; 3140 goto done;
3141 }
3111 } 3142 }
3112 3143
3113 if (sdkp->device->manage_start_stop) { 3144 if (sdkp->device->manage_start_stop) {
3114 sd_printk(KERN_NOTICE, sdkp, "Stopping disk\n"); 3145 sd_printk(KERN_NOTICE, sdkp, "Stopping disk\n");
3146 /* an error is not worth aborting a system sleep */
3115 ret = sd_start_stop_device(sdkp, 0); 3147 ret = sd_start_stop_device(sdkp, 0);
3148 if (ignore_stop_errors)
3149 ret = 0;
3116 } 3150 }
3117 3151
3118done: 3152done:
@@ -3120,6 +3154,16 @@ done:
3120 return ret; 3154 return ret;
3121} 3155}
3122 3156
3157static int sd_suspend_system(struct device *dev)
3158{
3159 return sd_suspend_common(dev, true);
3160}
3161
3162static int sd_suspend_runtime(struct device *dev)
3163{
3164 return sd_suspend_common(dev, false);
3165}
3166
3123static int sd_resume(struct device *dev) 3167static int sd_resume(struct device *dev)
3124{ 3168{
3125 struct scsi_disk *sdkp = scsi_disk_get_from_dev(dev); 3169 struct scsi_disk *sdkp = scsi_disk_get_from_dev(dev);