summaryrefslogtreecommitdiffstats
path: root/drivers/scsi/sr.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/sr.c')
-rw-r--r--drivers/scsi/sr.c35
1 files changed, 24 insertions, 11 deletions
diff --git a/drivers/scsi/sr.c b/drivers/scsi/sr.c
index c61999031141..1fcee16fa36d 100644
--- a/drivers/scsi/sr.c
+++ b/drivers/scsi/sr.c
@@ -67,8 +67,6 @@ MODULE_ALIAS_SCSI_DEVICE(TYPE_WORM);
#define SR_DISKS 256
-#define MAX_RETRIES 3
-#define SR_TIMEOUT (30 * HZ)
#define SR_CAPABILITIES \
(CDC_CLOSE_TRAY|CDC_OPEN_TRAY|CDC_LOCK|CDC_SELECT_SPEED| \
CDC_SELECT_DISC|CDC_MULTI_SESSION|CDC_MCN|CDC_MEDIA_CHANGED| \
@@ -179,21 +177,28 @@ 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;
- return 1; /* This will force a flush, if called from
- * check_disk_change */
+ /* This will force a flush, if called from check_disk_change */
+ retval = 1;
+ goto out;
};
retval = cd->device->changed;
@@ -203,9 +208,17 @@ static int sr_media_change(struct cdrom_device_info *cdi, int slot)
if (retval) {
/* check multisession offset etc */
sr_cd_check(cdi);
-
get_sectorsize(cd);
}
+
+out:
+ /* Notify userspace, that media has changed. */
+ if (retval != cd->previous_state)
+ sdev_evt_send_simple(cd->device, SDEV_EVT_MEDIA_CHANGE,
+ GFP_KERNEL);
+ cd->previous_state = retval;
+ kfree(sshdr);
+
return retval;
}