aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/sr.c
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2011-01-24 16:17:06 -0500
committerDavid S. Miller <davem@davemloft.net>2011-01-24 16:17:06 -0500
commite92427b289d252cfbd4cb5282d92f4ce1a5bb1fb (patch)
tree6d30e5e7b7f8e9aaa51d43b7128ac56860fa03bb /drivers/scsi/sr.c
parentc506653d35249bb4738bb139c24362e1ae724bc1 (diff)
parentec30f343d61391ab23705e50a525da1d55395780 (diff)
Merge branch 'master' of master.kernel.org:/pub/scm/linux/kernel/git/torvalds/linux-2.6
Diffstat (limited to 'drivers/scsi/sr.c')
-rw-r--r--drivers/scsi/sr.c174
1 files changed, 97 insertions, 77 deletions
diff --git a/drivers/scsi/sr.c b/drivers/scsi/sr.c
index d7b383c96d5d..aefadc6a1607 100644
--- a/drivers/scsi/sr.c
+++ b/drivers/scsi/sr.c
@@ -104,14 +104,15 @@ static void sr_release(struct cdrom_device_info *);
104static void get_sectorsize(struct scsi_cd *); 104static void get_sectorsize(struct scsi_cd *);
105static void get_capabilities(struct scsi_cd *); 105static void get_capabilities(struct scsi_cd *);
106 106
107static int sr_media_change(struct cdrom_device_info *, int); 107static unsigned int sr_check_events(struct cdrom_device_info *cdi,
108 unsigned int clearing, int slot);
108static int sr_packet(struct cdrom_device_info *, struct packet_command *); 109static int sr_packet(struct cdrom_device_info *, struct packet_command *);
109 110
110static struct cdrom_device_ops sr_dops = { 111static struct cdrom_device_ops sr_dops = {
111 .open = sr_open, 112 .open = sr_open,
112 .release = sr_release, 113 .release = sr_release,
113 .drive_status = sr_drive_status, 114 .drive_status = sr_drive_status,
114 .media_changed = sr_media_change, 115 .check_events = sr_check_events,
115 .tray_move = sr_tray_move, 116 .tray_move = sr_tray_move,
116 .lock_door = sr_lock_door, 117 .lock_door = sr_lock_door,
117 .select_speed = sr_select_speed, 118 .select_speed = sr_select_speed,
@@ -165,90 +166,92 @@ static void scsi_cd_put(struct scsi_cd *cd)
165 mutex_unlock(&sr_ref_mutex); 166 mutex_unlock(&sr_ref_mutex);
166} 167}
167 168
168/* identical to scsi_test_unit_ready except that it doesn't 169static unsigned int sr_get_events(struct scsi_device *sdev)
169 * eat the NOT_READY returns for removable media */
170int sr_test_unit_ready(struct scsi_device *sdev, struct scsi_sense_hdr *sshdr)
171{ 170{
172 int retries = MAX_RETRIES; 171 u8 buf[8];
173 int the_result; 172 u8 cmd[] = { GET_EVENT_STATUS_NOTIFICATION,
174 u8 cmd[] = {TEST_UNIT_READY, 0, 0, 0, 0, 0 }; 173 1, /* polled */
174 0, 0, /* reserved */
175 1 << 4, /* notification class: media */
176 0, 0, /* reserved */
177 0, sizeof(buf), /* allocation length */
178 0, /* control */
179 };
180 struct event_header *eh = (void *)buf;
181 struct media_event_desc *med = (void *)(buf + 4);
182 struct scsi_sense_hdr sshdr;
183 int result;
175 184
176 /* issue TEST_UNIT_READY until the initial startup UNIT_ATTENTION 185 result = scsi_execute_req(sdev, cmd, DMA_FROM_DEVICE, buf, sizeof(buf),
177 * conditions are gone, or a timeout happens 186 &sshdr, SR_TIMEOUT, MAX_RETRIES, NULL);
178 */ 187 if (scsi_sense_valid(&sshdr) && sshdr.sense_key == UNIT_ATTENTION)
179 do { 188 return DISK_EVENT_MEDIA_CHANGE;
180 the_result = scsi_execute_req(sdev, cmd, DMA_NONE, NULL, 189
181 0, sshdr, SR_TIMEOUT, 190 if (result || be16_to_cpu(eh->data_len) < sizeof(*med))
182 retries--, NULL); 191 return 0;
183 if (scsi_sense_valid(sshdr) && 192
184 sshdr->sense_key == UNIT_ATTENTION) 193 if (eh->nea || eh->notification_class != 0x4)
185 sdev->changed = 1; 194 return 0;
186 195
187 } while (retries > 0 && 196 if (med->media_event_code == 1)
188 (!scsi_status_is_good(the_result) || 197 return DISK_EVENT_EJECT_REQUEST;
189 (scsi_sense_valid(sshdr) && 198 else if (med->media_event_code == 2)
190 sshdr->sense_key == UNIT_ATTENTION))); 199 return DISK_EVENT_MEDIA_CHANGE;
191 return the_result; 200 return 0;
192} 201}
193 202
194/* 203/*
195 * This function checks to see if the media has been changed in the 204 * This function checks to see if the media has been changed or eject
196 * CDROM drive. It is possible that we have already sensed a change, 205 * button has been pressed. It is possible that we have already
197 * or the drive may have sensed one and not yet reported it. We must 206 * sensed a change, or the drive may have sensed one and not yet
198 * be ready for either case. This function always reports the current 207 * reported it. The past events are accumulated in sdev->changed and
199 * value of the changed bit. If flag is 0, then the changed bit is reset. 208 * returned together with the current state.
200 * This function could be done as an ioctl, but we would need to have
201 * an inode for that to work, and we do not always have one.
202 */ 209 */
203 210static unsigned int sr_check_events(struct cdrom_device_info *cdi,
204static int sr_media_change(struct cdrom_device_info *cdi, int slot) 211 unsigned int clearing, int slot)
205{ 212{
206 struct scsi_cd *cd = cdi->handle; 213 struct scsi_cd *cd = cdi->handle;
207 int retval; 214 bool last_present;
208 struct scsi_sense_hdr *sshdr; 215 struct scsi_sense_hdr sshdr;
216 unsigned int events;
217 int ret;
209 218
210 if (CDSL_CURRENT != slot) { 219 /* no changer support */
211 /* no changer support */ 220 if (CDSL_CURRENT != slot)
212 return -EINVAL; 221 return 0;
213 }
214 222
215 sshdr = kzalloc(sizeof(*sshdr), GFP_KERNEL); 223 events = sr_get_events(cd->device);
216 retval = sr_test_unit_ready(cd->device, sshdr); 224 /*
217 if (retval || (scsi_sense_valid(sshdr) && 225 * GET_EVENT_STATUS_NOTIFICATION is enough unless MEDIA_CHANGE
218 /* 0x3a is medium not present */ 226 * is being cleared. Note that there are devices which hang
219 sshdr->asc == 0x3a)) { 227 * if asked to execute TUR repeatedly.
220 /* Media not present or unable to test, unit probably not 228 */
221 * ready. This usually means there is no disc in the drive. 229 if (!(clearing & DISK_EVENT_MEDIA_CHANGE))
222 * Mark as changed, and we will figure it out later once 230 goto skip_tur;
223 * the drive is available again. 231
224 */ 232 /* let's see whether the media is there with TUR */
225 cd->device->changed = 1; 233 last_present = cd->media_present;
226 /* This will force a flush, if called from check_disk_change */ 234 ret = scsi_test_unit_ready(cd->device, SR_TIMEOUT, MAX_RETRIES, &sshdr);
227 retval = 1; 235
228 goto out; 236 /*
229 }; 237 * Media is considered to be present if TUR succeeds or fails with
238 * sense data indicating something other than media-not-present
239 * (ASC 0x3a).
240 */
241 cd->media_present = scsi_status_is_good(ret) ||
242 (scsi_sense_valid(&sshdr) && sshdr.asc != 0x3a);
230 243
231 retval = cd->device->changed; 244 if (last_present != cd->media_present)
232 cd->device->changed = 0; 245 events |= DISK_EVENT_MEDIA_CHANGE;
233 /* If the disk changed, the capacity will now be different, 246skip_tur:
234 * so we force a re-read of this information */ 247 if (cd->device->changed) {
235 if (retval) { 248 events |= DISK_EVENT_MEDIA_CHANGE;
236 /* check multisession offset etc */ 249 cd->device->changed = 0;
237 sr_cd_check(cdi);
238 get_sectorsize(cd);
239 } 250 }
240 251
241out: 252 return events;
242 /* Notify userspace, that media has changed. */
243 if (retval != cd->previous_state)
244 sdev_evt_send_simple(cd->device, SDEV_EVT_MEDIA_CHANGE,
245 GFP_KERNEL);
246 cd->previous_state = retval;
247 kfree(sshdr);
248
249 return retval;
250} 253}
251 254
252/* 255/*
253 * sr_done is the interrupt routine for the device driver. 256 * sr_done is the interrupt routine for the device driver.
254 * 257 *
@@ -533,10 +536,25 @@ out:
533 return ret; 536 return ret;
534} 537}
535 538
536static int sr_block_media_changed(struct gendisk *disk) 539static unsigned int sr_block_check_events(struct gendisk *disk,
540 unsigned int clearing)
537{ 541{
538 struct scsi_cd *cd = scsi_cd(disk); 542 struct scsi_cd *cd = scsi_cd(disk);
539 return cdrom_media_changed(&cd->cdi); 543 return cdrom_check_events(&cd->cdi, clearing);
544}
545
546static int sr_block_revalidate_disk(struct gendisk *disk)
547{
548 struct scsi_cd *cd = scsi_cd(disk);
549 struct scsi_sense_hdr sshdr;
550
551 /* if the unit is not ready, nothing more to do */
552 if (scsi_test_unit_ready(cd->device, SR_TIMEOUT, MAX_RETRIES, &sshdr))
553 return 0;
554
555 sr_cd_check(&cd->cdi);
556 get_sectorsize(cd);
557 return 0;
540} 558}
541 559
542static const struct block_device_operations sr_bdops = 560static const struct block_device_operations sr_bdops =
@@ -545,7 +563,8 @@ static const struct block_device_operations sr_bdops =
545 .open = sr_block_open, 563 .open = sr_block_open,
546 .release = sr_block_release, 564 .release = sr_block_release,
547 .ioctl = sr_block_ioctl, 565 .ioctl = sr_block_ioctl,
548 .media_changed = sr_block_media_changed, 566 .check_events = sr_block_check_events,
567 .revalidate_disk = sr_block_revalidate_disk,
549 /* 568 /*
550 * No compat_ioctl for now because sr_block_ioctl never 569 * No compat_ioctl for now because sr_block_ioctl never
551 * seems to pass arbitary ioctls down to host drivers. 570 * seems to pass arbitary ioctls down to host drivers.
@@ -618,6 +637,7 @@ static int sr_probe(struct device *dev)
618 sprintf(disk->disk_name, "sr%d", minor); 637 sprintf(disk->disk_name, "sr%d", minor);
619 disk->fops = &sr_bdops; 638 disk->fops = &sr_bdops;
620 disk->flags = GENHD_FL_CD; 639 disk->flags = GENHD_FL_CD;
640 disk->events = DISK_EVENT_MEDIA_CHANGE | DISK_EVENT_EJECT_REQUEST;
621 641
622 blk_queue_rq_timeout(sdev->request_queue, SR_TIMEOUT); 642 blk_queue_rq_timeout(sdev->request_queue, SR_TIMEOUT);
623 643
@@ -627,7 +647,7 @@ static int sr_probe(struct device *dev)
627 cd->disk = disk; 647 cd->disk = disk;
628 cd->capacity = 0x1fffff; 648 cd->capacity = 0x1fffff;
629 cd->device->changed = 1; /* force recheck CD type */ 649 cd->device->changed = 1; /* force recheck CD type */
630 cd->previous_state = 1; 650 cd->media_present = 1;
631 cd->use = 1; 651 cd->use = 1;
632 cd->readcd_known = 0; 652 cd->readcd_known = 0;
633 cd->readcd_cdda = 0; 653 cd->readcd_cdda = 0;
@@ -780,7 +800,7 @@ static void get_capabilities(struct scsi_cd *cd)
780 } 800 }
781 801
782 /* eat unit attentions */ 802 /* eat unit attentions */
783 sr_test_unit_ready(cd->device, &sshdr); 803 scsi_test_unit_ready(cd->device, SR_TIMEOUT, MAX_RETRIES, &sshdr);
784 804
785 /* ask for mode page 0x2a */ 805 /* ask for mode page 0x2a */
786 rc = scsi_mode_sense(cd->device, 0, 0x2a, buffer, 128, 806 rc = scsi_mode_sense(cd->device, 0, 0x2a, buffer, 128,