diff options
-rw-r--r-- | drivers/ide/ide-cd.c | 120 | ||||
-rw-r--r-- | drivers/ide/ide-io.c | 57 | ||||
-rw-r--r-- | include/linux/ide.h | 3 |
3 files changed, 152 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 | ||
679 | static 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. */ |
638 | static int cdrom_decode_status(ide_drive_t *drive, int good_stat, int *stat_ret) | 688 | static 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 | ||
1494 | static | 1558 | static int cdrom_queue_packet_command(ide_drive_t *drive, struct request *rq) |
1495 | int 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 | ||
diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c index 4f2f138de2ca..622a55c72f03 100644 --- a/drivers/ide/ide-io.c +++ b/drivers/ide/ide-io.c | |||
@@ -223,6 +223,63 @@ static ide_startstop_t ide_start_power_step(ide_drive_t *drive, struct request * | |||
223 | } | 223 | } |
224 | 224 | ||
225 | /** | 225 | /** |
226 | * ide_end_dequeued_request - complete an IDE I/O | ||
227 | * @drive: IDE device for the I/O | ||
228 | * @uptodate: | ||
229 | * @nr_sectors: number of sectors completed | ||
230 | * | ||
231 | * Complete an I/O that is no longer on the request queue. This | ||
232 | * typically occurs when we pull the request and issue a REQUEST_SENSE. | ||
233 | * We must still finish the old request but we must not tamper with the | ||
234 | * queue in the meantime. | ||
235 | * | ||
236 | * NOTE: This path does not handle barrier, but barrier is not supported | ||
237 | * on ide-cd anyway. | ||
238 | */ | ||
239 | |||
240 | int ide_end_dequeued_request(ide_drive_t *drive, struct request *rq, | ||
241 | int uptodate, int nr_sectors) | ||
242 | { | ||
243 | unsigned long flags; | ||
244 | int ret = 1; | ||
245 | |||
246 | spin_lock_irqsave(&ide_lock, flags); | ||
247 | |||
248 | BUG_ON(!(rq->flags & REQ_STARTED)); | ||
249 | |||
250 | /* | ||
251 | * if failfast is set on a request, override number of sectors and | ||
252 | * complete the whole request right now | ||
253 | */ | ||
254 | if (blk_noretry_request(rq) && end_io_error(uptodate)) | ||
255 | nr_sectors = rq->hard_nr_sectors; | ||
256 | |||
257 | if (!blk_fs_request(rq) && end_io_error(uptodate) && !rq->errors) | ||
258 | rq->errors = -EIO; | ||
259 | |||
260 | /* | ||
261 | * decide whether to reenable DMA -- 3 is a random magic for now, | ||
262 | * if we DMA timeout more than 3 times, just stay in PIO | ||
263 | */ | ||
264 | if (drive->state == DMA_PIO_RETRY && drive->retry_pio <= 3) { | ||
265 | drive->state = 0; | ||
266 | HWGROUP(drive)->hwif->ide_dma_on(drive); | ||
267 | } | ||
268 | |||
269 | if (!end_that_request_first(rq, uptodate, nr_sectors)) { | ||
270 | add_disk_randomness(rq->rq_disk); | ||
271 | if (blk_rq_tagged(rq)) | ||
272 | blk_queue_end_tag(drive->queue, rq); | ||
273 | end_that_request_last(rq, uptodate); | ||
274 | ret = 0; | ||
275 | } | ||
276 | spin_unlock_irqrestore(&ide_lock, flags); | ||
277 | return ret; | ||
278 | } | ||
279 | EXPORT_SYMBOL_GPL(ide_end_dequeued_request); | ||
280 | |||
281 | |||
282 | /** | ||
226 | * ide_complete_pm_request - end the current Power Management request | 283 | * ide_complete_pm_request - end the current Power Management request |
227 | * @drive: target drive | 284 | * @drive: target drive |
228 | * @rq: request | 285 | * @rq: request |
diff --git a/include/linux/ide.h b/include/linux/ide.h index 77e66d055f5b..ef7bef207f48 100644 --- a/include/linux/ide.h +++ b/include/linux/ide.h | |||
@@ -630,6 +630,7 @@ typedef struct ide_drive_s { | |||
630 | unsigned int usage; /* current "open()" count for drive */ | 630 | unsigned int usage; /* current "open()" count for drive */ |
631 | unsigned int failures; /* current failure count */ | 631 | unsigned int failures; /* current failure count */ |
632 | unsigned int max_failures; /* maximum allowed failure count */ | 632 | unsigned int max_failures; /* maximum allowed failure count */ |
633 | u64 probed_capacity;/* initial reported media capacity (ide-cd only currently) */ | ||
633 | 634 | ||
634 | u64 capacity64; /* total number of sectors */ | 635 | u64 capacity64; /* total number of sectors */ |
635 | 636 | ||
@@ -1005,6 +1006,8 @@ extern ide_hwif_t ide_hwifs[]; /* master data repository */ | |||
1005 | extern int noautodma; | 1006 | extern int noautodma; |
1006 | 1007 | ||
1007 | extern int ide_end_request (ide_drive_t *drive, int uptodate, int nrsecs); | 1008 | extern int ide_end_request (ide_drive_t *drive, int uptodate, int nrsecs); |
1009 | int ide_end_dequeued_request(ide_drive_t *drive, struct request *rq, | ||
1010 | int uptodate, int nr_sectors); | ||
1008 | 1011 | ||
1009 | /* | 1012 | /* |
1010 | * This is used on exit from the driver to designate the next irq handler | 1013 | * This is used on exit from the driver to designate the next irq handler |