summaryrefslogtreecommitdiffstats
path: root/drivers/scsi/sr.c
diff options
context:
space:
mode:
authorJames Bottomley <James.Bottomley@SteelEye.com>2007-12-02 18:10:40 +0100
committerJames Bottomley <James.Bottomley@HansenPartnership.com>2008-01-12 01:22:50 +0100
commit001aac257cf8adbe90cdcba6e07f8d12dfc8fa6b (patch)
tree0eb6294049245e05f47fdb76e3f878c78c015d88 /drivers/scsi/sr.c
parent[SCSI] BUG_ON() impossible condition in sg list counting (diff)
downloadlinux-001aac257cf8adbe90cdcba6e07f8d12dfc8fa6b.tar.xz
linux-001aac257cf8adbe90cdcba6e07f8d12dfc8fa6b.zip
[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/sr.c')
-rw-r--r--drivers/scsi/sr.c19
1 files changed, 13 insertions, 6 deletions
diff --git a/drivers/scsi/sr.c b/drivers/scsi/sr.c
index 7702681d93f9..896be4ab285d 100644
--- a/drivers/scsi/sr.c
+++ b/drivers/scsi/sr.c
@@ -179,18 +179,24 @@ static int sr_media_change(struct cdrom_device_info *cdi, int slot)
{
struct scsi_cd *cd = cdi->handle;
int retval;
+ struct scsi_sense_hdr *sshdr;
if (CDSL_CURRENT != slot) {
/* no changer support */
return -EINVAL;
}
- retval = scsi_test_unit_ready(cd->device, SR_TIMEOUT, MAX_RETRIES);
- if (retval) {
- /* Unable to test, unit probably not ready. This usually
- * means there is no disc in the drive. Mark as changed,
- * and we will figure it out later once the drive is
- * available again. */
+ sshdr = kzalloc(sizeof(*sshdr), GFP_KERNEL);
+ retval = scsi_test_unit_ready(cd->device, SR_TIMEOUT, MAX_RETRIES,
+ sshdr);
+ if (retval || (scsi_sense_valid(sshdr) &&
+ /* 0x3a is medium not present */
+ sshdr->asc == 0x3a)) {
+ /* Media not present or unable to test, unit probably not
+ * ready. This usually means there is no disc in the drive.
+ * Mark as changed, and we will figure it out later once
+ * the drive is available again.
+ */
cd->device->changed = 1;
/* This will force a flush, if called from check_disk_change */
retval = 1;
@@ -213,6 +219,7 @@ out:
sdev_evt_send_simple(cd->device, SDEV_EVT_MEDIA_CHANGE,
GFP_KERNEL);
cd->previous_state = retval;
+ kfree(sshdr);
return retval;
}