diff options
Diffstat (limited to 'drivers/scsi/sd.c')
-rw-r--r-- | drivers/scsi/sd.c | 83 |
1 files changed, 66 insertions, 17 deletions
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index 7fe4faaa149b..e6c4bff04339 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c | |||
@@ -105,7 +105,8 @@ static void sd_unlock_native_capacity(struct gendisk *disk); | |||
105 | static int sd_probe(struct device *); | 105 | static int sd_probe(struct device *); |
106 | static int sd_remove(struct device *); | 106 | static int sd_remove(struct device *); |
107 | static void sd_shutdown(struct device *); | 107 | static void sd_shutdown(struct device *); |
108 | static int sd_suspend(struct device *); | 108 | static int sd_suspend_system(struct device *); |
109 | static int sd_suspend_runtime(struct device *); | ||
109 | static int sd_resume(struct device *); | 110 | static int sd_resume(struct device *); |
110 | static void sd_rescan(struct device *); | 111 | static void sd_rescan(struct device *); |
111 | static int sd_done(struct scsi_cmnd *); | 112 | static int sd_done(struct scsi_cmnd *); |
@@ -484,11 +485,11 @@ static struct class sd_disk_class = { | |||
484 | }; | 485 | }; |
485 | 486 | ||
486 | static const struct dev_pm_ops sd_pm_ops = { | 487 | static 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 | ||
@@ -829,7 +830,7 @@ static int sd_setup_write_same_cmnd(struct scsi_device *sdp, struct request *rq) | |||
829 | 830 | ||
830 | static int scsi_setup_flush_cmnd(struct scsi_device *sdp, struct request *rq) | 831 | static int scsi_setup_flush_cmnd(struct scsi_device *sdp, struct request *rq) |
831 | { | 832 | { |
832 | rq->timeout = SD_FLUSH_TIMEOUT; | 833 | rq->timeout *= SD_FLUSH_TIMEOUT_MULTIPLIER; |
833 | rq->retries = SD_MAX_RETRIES; | 834 | rq->retries = SD_MAX_RETRIES; |
834 | rq->cmd[0] = SYNCHRONIZE_CACHE; | 835 | rq->cmd[0] = SYNCHRONIZE_CACHE; |
835 | rq->cmd_len = 10; | 836 | rq->cmd_len = 10; |
@@ -1433,12 +1434,13 @@ static int sd_sync_cache(struct scsi_disk *sdkp) | |||
1433 | { | 1434 | { |
1434 | int retries, res; | 1435 | int retries, res; |
1435 | struct scsi_device *sdp = sdkp->device; | 1436 | struct scsi_device *sdp = sdkp->device; |
1437 | const int timeout = sdp->request_queue->rq_timeout | ||
1438 | * SD_FLUSH_TIMEOUT_MULTIPLIER; | ||
1436 | struct scsi_sense_hdr sshdr; | 1439 | struct scsi_sense_hdr sshdr; |
1437 | 1440 | ||
1438 | if (!scsi_device_online(sdp)) | 1441 | if (!scsi_device_online(sdp)) |
1439 | return -ENODEV; | 1442 | return -ENODEV; |
1440 | 1443 | ||
1441 | |||
1442 | for (retries = 3; retries > 0; --retries) { | 1444 | for (retries = 3; retries > 0; --retries) { |
1443 | unsigned char cmd[10] = { 0 }; | 1445 | unsigned char cmd[10] = { 0 }; |
1444 | 1446 | ||
@@ -1448,20 +1450,39 @@ static int sd_sync_cache(struct scsi_disk *sdkp) | |||
1448 | * flush everything. | 1450 | * flush everything. |
1449 | */ | 1451 | */ |
1450 | res = scsi_execute_req_flags(sdp, cmd, DMA_NONE, NULL, 0, | 1452 | res = scsi_execute_req_flags(sdp, cmd, DMA_NONE, NULL, 0, |
1451 | &sshdr, SD_FLUSH_TIMEOUT, | 1453 | &sshdr, timeout, SD_MAX_RETRIES, |
1452 | SD_MAX_RETRIES, NULL, REQ_PM); | 1454 | NULL, REQ_PM); |
1453 | if (res == 0) | 1455 | if (res == 0) |
1454 | break; | 1456 | break; |
1455 | } | 1457 | } |
1456 | 1458 | ||
1457 | if (res) { | 1459 | if (res) { |
1458 | sd_print_result(sdkp, res); | 1460 | sd_print_result(sdkp, res); |
1461 | |||
1459 | if (driver_byte(res) & DRIVER_SENSE) | 1462 | if (driver_byte(res) & DRIVER_SENSE) |
1460 | sd_print_sense_hdr(sdkp, &sshdr); | 1463 | sd_print_sense_hdr(sdkp, &sshdr); |
1464 | /* we need to evaluate the error return */ | ||
1465 | if (scsi_sense_valid(&sshdr) && | ||
1466 | /* 0x3a is medium not present */ | ||
1467 | sshdr.asc == 0x3a) | ||
1468 | /* this is no error here */ | ||
1469 | return 0; | ||
1470 | |||
1471 | switch (host_byte(res)) { | ||
1472 | /* ignore errors due to racing a disconnection */ | ||
1473 | case DID_BAD_TARGET: | ||
1474 | case DID_NO_CONNECT: | ||
1475 | return 0; | ||
1476 | /* signal the upper layer it might try again */ | ||
1477 | case DID_BUS_BUSY: | ||
1478 | case DID_IMM_RETRY: | ||
1479 | case DID_REQUEUE: | ||
1480 | case DID_SOFT_ERROR: | ||
1481 | return -EBUSY; | ||
1482 | default: | ||
1483 | return -EIO; | ||
1484 | } | ||
1461 | } | 1485 | } |
1462 | |||
1463 | if (res) | ||
1464 | return -EIO; | ||
1465 | return 0; | 1486 | return 0; |
1466 | } | 1487 | } |
1467 | 1488 | ||
@@ -2639,13 +2660,16 @@ static void sd_read_write_same(struct scsi_disk *sdkp, unsigned char *buffer) | |||
2639 | struct scsi_device *sdev = sdkp->device; | 2660 | struct scsi_device *sdev = sdkp->device; |
2640 | 2661 | ||
2641 | if (scsi_report_opcode(sdev, buffer, SD_BUF_SIZE, INQUIRY) < 0) { | 2662 | if (scsi_report_opcode(sdev, buffer, SD_BUF_SIZE, INQUIRY) < 0) { |
2663 | /* too large values might cause issues with arcmsr */ | ||
2664 | int vpd_buf_len = 64; | ||
2665 | |||
2642 | sdev->no_report_opcodes = 1; | 2666 | sdev->no_report_opcodes = 1; |
2643 | 2667 | ||
2644 | /* Disable WRITE SAME if REPORT SUPPORTED OPERATION | 2668 | /* Disable WRITE SAME if REPORT SUPPORTED OPERATION |
2645 | * CODES is unsupported and the device has an ATA | 2669 | * CODES is unsupported and the device has an ATA |
2646 | * Information VPD page (SAT). | 2670 | * Information VPD page (SAT). |
2647 | */ | 2671 | */ |
2648 | if (!scsi_get_vpd_page(sdev, 0x89, buffer, SD_BUF_SIZE)) | 2672 | if (!scsi_get_vpd_page(sdev, 0x89, buffer, vpd_buf_len)) |
2649 | sdev->no_write_same = 1; | 2673 | sdev->no_write_same = 1; |
2650 | } | 2674 | } |
2651 | 2675 | ||
@@ -3058,9 +3082,17 @@ static int sd_start_stop_device(struct scsi_disk *sdkp, int start) | |||
3058 | sd_print_result(sdkp, res); | 3082 | sd_print_result(sdkp, res); |
3059 | if (driver_byte(res) & DRIVER_SENSE) | 3083 | if (driver_byte(res) & DRIVER_SENSE) |
3060 | sd_print_sense_hdr(sdkp, &sshdr); | 3084 | sd_print_sense_hdr(sdkp, &sshdr); |
3085 | if (scsi_sense_valid(&sshdr) && | ||
3086 | /* 0x3a is medium not present */ | ||
3087 | sshdr.asc == 0x3a) | ||
3088 | res = 0; | ||
3061 | } | 3089 | } |
3062 | 3090 | ||
3063 | return res; | 3091 | /* SCSI error codes must not go to the generic layer */ |
3092 | if (res) | ||
3093 | return -EIO; | ||
3094 | |||
3095 | return 0; | ||
3064 | } | 3096 | } |
3065 | 3097 | ||
3066 | /* | 3098 | /* |
@@ -3078,7 +3110,7 @@ static void sd_shutdown(struct device *dev) | |||
3078 | if (pm_runtime_suspended(dev)) | 3110 | if (pm_runtime_suspended(dev)) |
3079 | goto exit; | 3111 | goto exit; |
3080 | 3112 | ||
3081 | if (sdkp->WCE) { | 3113 | if (sdkp->WCE && sdkp->media_present) { |
3082 | sd_printk(KERN_NOTICE, sdkp, "Synchronizing SCSI cache\n"); | 3114 | sd_printk(KERN_NOTICE, sdkp, "Synchronizing SCSI cache\n"); |
3083 | sd_sync_cache(sdkp); | 3115 | sd_sync_cache(sdkp); |
3084 | } | 3116 | } |
@@ -3092,7 +3124,7 @@ exit: | |||
3092 | scsi_disk_put(sdkp); | 3124 | scsi_disk_put(sdkp); |
3093 | } | 3125 | } |
3094 | 3126 | ||
3095 | static int sd_suspend(struct device *dev) | 3127 | static int sd_suspend_common(struct device *dev, bool ignore_stop_errors) |
3096 | { | 3128 | { |
3097 | struct scsi_disk *sdkp = scsi_disk_get_from_dev(dev); | 3129 | struct scsi_disk *sdkp = scsi_disk_get_from_dev(dev); |
3098 | int ret = 0; | 3130 | int ret = 0; |
@@ -3100,16 +3132,23 @@ static int sd_suspend(struct device *dev) | |||
3100 | if (!sdkp) | 3132 | if (!sdkp) |
3101 | return 0; /* this can happen */ | 3133 | return 0; /* this can happen */ |
3102 | 3134 | ||
3103 | if (sdkp->WCE) { | 3135 | if (sdkp->WCE && sdkp->media_present) { |
3104 | sd_printk(KERN_NOTICE, sdkp, "Synchronizing SCSI cache\n"); | 3136 | sd_printk(KERN_NOTICE, sdkp, "Synchronizing SCSI cache\n"); |
3105 | ret = sd_sync_cache(sdkp); | 3137 | ret = sd_sync_cache(sdkp); |
3106 | if (ret) | 3138 | if (ret) { |
3139 | /* ignore OFFLINE device */ | ||
3140 | if (ret == -ENODEV) | ||
3141 | ret = 0; | ||
3107 | goto done; | 3142 | goto done; |
3143 | } | ||
3108 | } | 3144 | } |
3109 | 3145 | ||
3110 | if (sdkp->device->manage_start_stop) { | 3146 | if (sdkp->device->manage_start_stop) { |
3111 | sd_printk(KERN_NOTICE, sdkp, "Stopping disk\n"); | 3147 | sd_printk(KERN_NOTICE, sdkp, "Stopping disk\n"); |
3148 | /* an error is not worth aborting a system sleep */ | ||
3112 | ret = sd_start_stop_device(sdkp, 0); | 3149 | ret = sd_start_stop_device(sdkp, 0); |
3150 | if (ignore_stop_errors) | ||
3151 | ret = 0; | ||
3113 | } | 3152 | } |
3114 | 3153 | ||
3115 | done: | 3154 | done: |
@@ -3117,6 +3156,16 @@ done: | |||
3117 | return ret; | 3156 | return ret; |
3118 | } | 3157 | } |
3119 | 3158 | ||
3159 | static int sd_suspend_system(struct device *dev) | ||
3160 | { | ||
3161 | return sd_suspend_common(dev, true); | ||
3162 | } | ||
3163 | |||
3164 | static int sd_suspend_runtime(struct device *dev) | ||
3165 | { | ||
3166 | return sd_suspend_common(dev, false); | ||
3167 | } | ||
3168 | |||
3120 | static int sd_resume(struct device *dev) | 3169 | static int sd_resume(struct device *dev) |
3121 | { | 3170 | { |
3122 | struct scsi_disk *sdkp = scsi_disk_get_from_dev(dev); | 3171 | struct scsi_disk *sdkp = scsi_disk_get_from_dev(dev); |