summaryrefslogtreecommitdiff
path: root/drivers/scsi/sd.c
diff options
context:
space:
mode:
authorJames Bottomley <James.Bottomley@SteelEye.com>2007-12-02 20:10:40 +0300
committerJames Bottomley <James.Bottomley@HansenPartnership.com>2008-01-12 03:22:50 +0300
commit001aac257cf8adbe90cdcba6e07f8d12dfc8fa6b (patch)
tree0eb6294049245e05f47fdb76e3f878c78c015d88 /drivers/scsi/sd.c
parent4a03d90e35bc5273d27301fa669d4b2103196f94 (diff)
downloadlinux-001aac257cf8adbe90cdcba6e07f8d12dfc8fa6b.tar.xz
[SCSI] sd,sr: add early detection of medium not present
The current scsi_test_unit_ready() is updated to return sense code information (in struct scsi_sense_hdr). The sd and sr drivers are changed to interpret the sense code return asc 0x3a as no media and adjust the device status accordingly. Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
Diffstat (limited to 'drivers/scsi/sd.c')
-rw-r--r--drivers/scsi/sd.c13
1 files changed, 10 insertions, 3 deletions
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
index 18343a6acd8e..212f6bcfd457 100644
--- a/drivers/scsi/sd.c
+++ b/drivers/scsi/sd.c
@@ -736,6 +736,7 @@ static int sd_media_changed(struct gendisk *disk)
{
struct scsi_disk *sdkp = scsi_disk(disk);
struct scsi_device *sdp = sdkp->device;
+ struct scsi_sense_hdr *sshdr = NULL;
int retval;
SCSI_LOG_HLQUEUE(3, sd_printk(KERN_INFO, sdkp, "sd_media_changed\n"));
@@ -766,8 +767,11 @@ static int sd_media_changed(struct gendisk *disk)
*/
retval = -ENODEV;
- if (scsi_block_when_processing_errors(sdp))
- retval = scsi_test_unit_ready(sdp, SD_TIMEOUT, SD_MAX_RETRIES);
+ if (scsi_block_when_processing_errors(sdp)) {
+ sshdr = kzalloc(sizeof(*sshdr), GFP_KERNEL);
+ retval = scsi_test_unit_ready(sdp, SD_TIMEOUT, SD_MAX_RETRIES,
+ sshdr);
+ }
/*
* Unable to test, unit probably not ready. This usually
@@ -775,7 +779,9 @@ static int sd_media_changed(struct gendisk *disk)
* and we will figure it out later once the drive is
* available again.
*/
- if (retval) {
+ if (retval || (scsi_sense_valid(sshdr) &&
+ /* 0x3a is medium not present */
+ sshdr->asc == 0x3a)) {
set_media_not_present(sdkp);
retval = 1;
goto out;
@@ -794,6 +800,7 @@ out:
if (retval != sdkp->previous_state)
sdev_evt_send_simple(sdp, SDEV_EVT_MEDIA_CHANGE, GFP_KERNEL);
sdkp->previous_state = retval;
+ kfree(sshdr);
return retval;
}