aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/ide/ide-cd.c
diff options
context:
space:
mode:
authorAlan Cox <alan@lxorguk.ukuu.org.uk>2006-06-25 08:47:44 -0400
committerLinus Torvalds <torvalds@g5.osdl.org>2006-06-25 13:01:06 -0400
commitdbe217af3be08346f4b1abb885c2d9ec29c98fac (patch)
tree493ee2547ba3095d7aa468d6ddffc1a82f18ce56 /drivers/ide/ide-cd.c
parent8e3a67a99231f9f3f476bc3449e93c9a6a17f2e0 (diff)
[PATCH] IDE CD end-of media error fix
This is a patch from Alan that fixes a real ide-cd.c regression causing bogus "Media Check" failures for perfectly valid Fedora install ISOs, on certain CD-ROM drives. This is a forward port to 2.6.16 (from RHEL) of the minimal changes for the end of media problem. It may not be sufficient for some controllers (promise notably) and it does not touch the locking so the error path locking is as horked as in mainstream. From: Ingo Molnar <mingo@elte.hu> I have ported the patch to 2.6.17-rc4 and tested it by provoking end-of-media IO errors with an unaligned ISO image. Unlike the vanilla kernel, the patched kernel interpreted the error condition correctly with 512 byte granularity: hdc: command error: status=0x51 { DriveReady SeekComplete Error } hdc: command error: error=0x54 { AbortedCommand LastFailedSense=0x05 } ide: failed opcode was: unknown ATAPI device hdc: Error: Illegal request -- (Sense key=0x05) Illegal mode for this track or incompatible medium -- (asc=0x64, ascq=0x00) The failed "Read 10" packet command was: "28 00 00 04 fb 78 00 00 06 00 00 00 00 00 00 00 " end_request: I/O error, dev hdc, sector 1306080 Buffer I/O error on device hdc, logical block 163260 Buffer I/O error on device hdc, logical block 163261 Buffer I/O error on device hdc, logical block 163262 the unpatched kernel produces an incorrect error dump: hdc: command error: status=0x51 { DriveReady SeekComplete Error } hdc: command error: error=0x54 { AbortedCommand LastFailedSense=0x05 } ide: failed opcode was: unknown end_request: I/O error, dev hdc, sector 1306080 Buffer I/O error on device hdc, logical block 163260 hdc: command error: status=0x51 { DriveReady SeekComplete Error } hdc: command error: error=0x54 { AbortedCommand LastFailedSense=0x05 } ide: failed opcode was: unknown end_request: I/O error, dev hdc, sector 1306088 Buffer I/O error on device hdc, logical block 163261 hdc: command error: status=0x51 { DriveReady SeekComplete Error } hdc: command error: error=0x54 { AbortedCommand LastFailedSense=0x05 } ide: failed opcode was: unknown end_request: I/O error, dev hdc, sector 1306096 Buffer I/O error on device hdc, logical block 163262 I do not have the right type of CD-ROM drive to reproduce the end-of-media data corruption bug myself, but this same patch in RHEL solved it. Signed-off-by: Ingo Molnar <mingo@elte.hu> Cc: Alan Cox <alan@lxorguk.ukuu.org.uk> Cc: Bartlomiej Zolnierkiewicz <B.Zolnierkiewicz@elka.pw.edu.pl> Cc: Jens Axboe <axboe@suse.de> Cc: Matt Mackall <mpm@selenic.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'drivers/ide/ide-cd.c')
-rw-r--r--drivers/ide/ide-cd.c120
1 files changed, 92 insertions, 28 deletions
diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c
index 6de3cd3d6e8e..99fa42402e71 100644
--- a/drivers/ide/ide-cd.c
+++ b/drivers/ide/ide-cd.c
@@ -395,7 +395,8 @@ static int cdrom_log_sense(ide_drive_t *drive, struct request *rq,
395 * we cannot reliably check if drive can auto-close 395 * we cannot reliably check if drive can auto-close
396 */ 396 */
397 if (rq->cmd[0] == GPCMD_START_STOP_UNIT && sense->asc == 0x24) 397 if (rq->cmd[0] == GPCMD_START_STOP_UNIT && sense->asc == 0x24)
398 log = 0; 398 break;
399 log = 1;
399 break; 400 break;
400 case UNIT_ATTENTION: 401 case UNIT_ATTENTION:
401 /* 402 /*
@@ -417,6 +418,11 @@ void cdrom_analyze_sense_data(ide_drive_t *drive,
417 struct request *failed_command, 418 struct request *failed_command,
418 struct request_sense *sense) 419 struct request_sense *sense)
419{ 420{
421 unsigned long sector;
422 unsigned long bio_sectors;
423 unsigned long valid;
424 struct cdrom_info *info = drive->driver_data;
425
420 if (!cdrom_log_sense(drive, failed_command, sense)) 426 if (!cdrom_log_sense(drive, failed_command, sense))
421 return; 427 return;
422 428
@@ -429,6 +435,37 @@ void cdrom_analyze_sense_data(ide_drive_t *drive,
429 if (sense->sense_key == 0x05 && sense->asc == 0x24) 435 if (sense->sense_key == 0x05 && sense->asc == 0x24)
430 return; 436 return;
431 437
438 if (sense->error_code == 0x70) { /* Current Error */
439 switch(sense->sense_key) {
440 case MEDIUM_ERROR:
441 case VOLUME_OVERFLOW:
442 case ILLEGAL_REQUEST:
443 if (!sense->valid)
444 break;
445 if (failed_command == NULL ||
446 !blk_fs_request(failed_command))
447 break;
448 sector = (sense->information[0] << 24) |
449 (sense->information[1] << 16) |
450 (sense->information[2] << 8) |
451 (sense->information[3]);
452
453 bio_sectors = bio_sectors(failed_command->bio);
454 if (bio_sectors < 4)
455 bio_sectors = 4;
456 if (drive->queue->hardsect_size == 2048)
457 sector <<= 2; /* Device sector size is 2K */
458 sector &= ~(bio_sectors -1);
459 valid = (sector - failed_command->sector) << 9;
460
461 if (valid < 0)
462 valid = 0;
463 if (sector < get_capacity(info->disk) &&
464 drive->probed_capacity - sector < 4 * 75) {
465 set_capacity(info->disk, sector);
466 }
467 }
468 }
432#if VERBOSE_IDE_CD_ERRORS 469#if VERBOSE_IDE_CD_ERRORS
433 { 470 {
434 int i; 471 int i;
@@ -609,17 +646,23 @@ static void cdrom_end_request (ide_drive_t *drive, int uptodate)
609 sense = failed->sense; 646 sense = failed->sense;
610 failed->sense_len = rq->sense_len; 647 failed->sense_len = rq->sense_len;
611 } 648 }
612 649 cdrom_analyze_sense_data(drive, failed, sense);
613 /* 650 /*
614 * now end failed request 651 * now end failed request
615 */ 652 */
616 spin_lock_irqsave(&ide_lock, flags); 653 if (blk_fs_request(failed)) {
617 end_that_request_chunk(failed, 0, failed->data_len); 654 if (ide_end_dequeued_request(drive, failed, 0,
618 end_that_request_last(failed, 0); 655 failed->hard_nr_sectors))
619 spin_unlock_irqrestore(&ide_lock, flags); 656 BUG();
620 } 657 } else {
621 658 spin_lock_irqsave(&ide_lock, flags);
622 cdrom_analyze_sense_data(drive, failed, sense); 659 end_that_request_chunk(failed, 0,
660 failed->data_len);
661 end_that_request_last(failed, 0);
662 spin_unlock_irqrestore(&ide_lock, flags);
663 }
664 } else
665 cdrom_analyze_sense_data(drive, NULL, sense);
623 } 666 }
624 667
625 if (!rq->current_nr_sectors && blk_fs_request(rq)) 668 if (!rq->current_nr_sectors && blk_fs_request(rq))
@@ -633,6 +676,13 @@ static void cdrom_end_request (ide_drive_t *drive, int uptodate)
633 ide_end_request(drive, uptodate, nsectors); 676 ide_end_request(drive, uptodate, nsectors);
634} 677}
635 678
679static void ide_dump_status_no_sense(ide_drive_t *drive, const char *msg, u8 stat)
680{
681 if (stat & 0x80)
682 return;
683 ide_dump_status(drive, msg, stat);
684}
685
636/* Returns 0 if the request should be continued. 686/* Returns 0 if the request should be continued.
637 Returns 1 if the request was ended. */ 687 Returns 1 if the request was ended. */
638static int cdrom_decode_status(ide_drive_t *drive, int good_stat, int *stat_ret) 688static int cdrom_decode_status(ide_drive_t *drive, int good_stat, int *stat_ret)
@@ -761,16 +811,16 @@ static int cdrom_decode_status(ide_drive_t *drive, int good_stat, int *stat_ret)
761 sense_key == DATA_PROTECT) { 811 sense_key == DATA_PROTECT) {
762 /* No point in retrying after an illegal 812 /* No point in retrying after an illegal
763 request or data protect error.*/ 813 request or data protect error.*/
764 ide_dump_status (drive, "command error", stat); 814 ide_dump_status_no_sense (drive, "command error", stat);
765 do_end_request = 1; 815 do_end_request = 1;
766 } else if (sense_key == MEDIUM_ERROR) { 816 } else if (sense_key == MEDIUM_ERROR) {
767 /* No point in re-trying a zillion times on a bad 817 /* No point in re-trying a zillion times on a bad
768 * sector... If we got here the error is not correctable */ 818 * sector... If we got here the error is not correctable */
769 ide_dump_status (drive, "media error (bad sector)", stat); 819 ide_dump_status_no_sense (drive, "media error (bad sector)", stat);
770 do_end_request = 1; 820 do_end_request = 1;
771 } else if (sense_key == BLANK_CHECK) { 821 } else if (sense_key == BLANK_CHECK) {
772 /* Disk appears blank ?? */ 822 /* Disk appears blank ?? */
773 ide_dump_status (drive, "media error (blank)", stat); 823 ide_dump_status_no_sense (drive, "media error (blank)", stat);
774 do_end_request = 1; 824 do_end_request = 1;
775 } else if ((err & ~ABRT_ERR) != 0) { 825 } else if ((err & ~ABRT_ERR) != 0) {
776 /* Go to the default handler 826 /* Go to the default handler
@@ -782,13 +832,27 @@ static int cdrom_decode_status(ide_drive_t *drive, int good_stat, int *stat_ret)
782 do_end_request = 1; 832 do_end_request = 1;
783 } 833 }
784 834
785 if (do_end_request) 835 /* End a request through request sense analysis when we have
786 cdrom_end_request(drive, 0); 836 sense data. We need this in order to perform end of media
787 837 processing */
788 /* If we got a CHECK_CONDITION status, 838
789 queue a request sense command. */ 839 if (do_end_request) {
790 if ((stat & ERR_STAT) != 0) 840 if (stat & ERR_STAT) {
791 cdrom_queue_request_sense(drive, NULL, NULL); 841 unsigned long flags;
842 spin_lock_irqsave(&ide_lock, flags);
843 blkdev_dequeue_request(rq);
844 HWGROUP(drive)->rq = NULL;
845 spin_unlock_irqrestore(&ide_lock, flags);
846
847 cdrom_queue_request_sense(drive, rq->sense, rq);
848 } else
849 cdrom_end_request(drive, 0);
850 } else {
851 /* If we got a CHECK_CONDITION status,
852 queue a request sense command. */
853 if (stat & ERR_STAT)
854 cdrom_queue_request_sense(drive, NULL, NULL);
855 }
792 } else { 856 } else {
793 blk_dump_rq_flags(rq, "ide-cd: bad rq"); 857 blk_dump_rq_flags(rq, "ide-cd: bad rq");
794 cdrom_end_request(drive, 0); 858 cdrom_end_request(drive, 0);
@@ -1491,8 +1555,7 @@ static ide_startstop_t cdrom_do_packet_command (ide_drive_t *drive)
1491} 1555}
1492 1556
1493 1557
1494static 1558static int cdrom_queue_packet_command(ide_drive_t *drive, struct request *rq)
1495int cdrom_queue_packet_command(ide_drive_t *drive, struct request *rq)
1496{ 1559{
1497 struct request_sense sense; 1560 struct request_sense sense;
1498 int retries = 10; 1561 int retries = 10;
@@ -2220,6 +2283,9 @@ static int cdrom_read_toc(ide_drive_t *drive, struct request_sense *sense)
2220 toc->capacity = 0x1fffff; 2283 toc->capacity = 0x1fffff;
2221 2284
2222 set_capacity(info->disk, toc->capacity * sectors_per_frame); 2285 set_capacity(info->disk, toc->capacity * sectors_per_frame);
2286 /* Save a private copy of te TOC capacity for error handling */
2287 drive->probed_capacity = toc->capacity * sectors_per_frame;
2288
2223 blk_queue_hardsect_size(drive->queue, 2289 blk_queue_hardsect_size(drive->queue,
2224 sectors_per_frame << SECTOR_BITS); 2290 sectors_per_frame << SECTOR_BITS);
2225 2291
@@ -2342,6 +2408,7 @@ static int cdrom_read_toc(ide_drive_t *drive, struct request_sense *sense)
2342 if (!stat && (last_written > toc->capacity)) { 2408 if (!stat && (last_written > toc->capacity)) {
2343 toc->capacity = last_written; 2409 toc->capacity = last_written;
2344 set_capacity(info->disk, toc->capacity * sectors_per_frame); 2410 set_capacity(info->disk, toc->capacity * sectors_per_frame);
2411 drive->probed_capacity = toc->capacity * sectors_per_frame;
2345 } 2412 }
2346 2413
2347 /* Remember that we've read this stuff. */ 2414 /* Remember that we've read this stuff. */
@@ -2698,14 +2765,11 @@ int ide_cdrom_drive_status (struct cdrom_device_info *cdi, int slot_nr)
2698 * any other way to detect this... 2765 * any other way to detect this...
2699 */ 2766 */
2700 if (sense.sense_key == NOT_READY) { 2767 if (sense.sense_key == NOT_READY) {
2701 if (sense.asc == 0x3a) { 2768 if (sense.asc == 0x3a && sense.ascq == 1)
2702 if (sense.ascq == 1) 2769 return CDS_NO_DISC;
2703 return CDS_NO_DISC; 2770 else
2704 else if (sense.ascq == 0 || sense.ascq == 2) 2771 return CDS_TRAY_OPEN;
2705 return CDS_TRAY_OPEN;
2706 }
2707 } 2772 }
2708
2709 return CDS_DRIVE_NOT_READY; 2773 return CDS_DRIVE_NOT_READY;
2710} 2774}
2711 2775