diff options
author | Bartlomiej Zolnierkiewicz <bzolnier@gmail.com> | 2007-10-13 11:47:49 -0400 |
---|---|---|
committer | Bartlomiej Zolnierkiewicz <bzolnier@gmail.com> | 2007-10-13 11:47:49 -0400 |
commit | 74af21cf4d0ab67df53608753a443dc7904ec12e (patch) | |
tree | 0e5cbfdc12dbd00fcde2ccf08c7df59e3424ff11 /drivers/ide | |
parent | fd553ce86893e0a54ec0d07d1f1d241f2fb2aef3 (diff) |
ide: add __ide_wait_stat() helper
* Split off checking of the status register from ide_wait_stat() to
__ide_wait_stat() helper.
* Use the new helper in ide_config_drive_speed(). The only change in the
functionality is that the function now fails if after 20 sec (WAIT_CMD)
device is still busy (BUSY_STAT bit is set) while previously instead of
failing the function continued with checking for the correct device status
(which would give the device additional 10 usec to clear BUSY_STAT bit).
* Remove stale comment for ide_config_drive_speed().
* Remove duplicate comment for ide_wait_stat() from <linux/ide.h>.
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Acked-by: Sergei Shtylyov <sshtylyov@ru.mvista.com>
Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
Diffstat (limited to 'drivers/ide')
-rw-r--r-- | drivers/ide/ide-iops.c | 96 |
1 files changed, 44 insertions, 52 deletions
diff --git a/drivers/ide/ide-iops.c b/drivers/ide/ide-iops.c index cf0678b61161..fb524cf175d5 100644 --- a/drivers/ide/ide-iops.c +++ b/drivers/ide/ide-iops.c | |||
@@ -505,25 +505,19 @@ int wait_for_ready (ide_drive_t *drive, int timeout) | |||
505 | * This routine busy-waits for the drive status to be not "busy". | 505 | * This routine busy-waits for the drive status to be not "busy". |
506 | * It then checks the status for all of the "good" bits and none | 506 | * It then checks the status for all of the "good" bits and none |
507 | * of the "bad" bits, and if all is okay it returns 0. All other | 507 | * of the "bad" bits, and if all is okay it returns 0. All other |
508 | * cases return 1 after invoking ide_error() -- caller should just return. | 508 | * cases return error -- caller may then invoke ide_error(). |
509 | * | 509 | * |
510 | * This routine should get fixed to not hog the cpu during extra long waits.. | 510 | * This routine should get fixed to not hog the cpu during extra long waits.. |
511 | * That could be done by busy-waiting for the first jiffy or two, and then | 511 | * That could be done by busy-waiting for the first jiffy or two, and then |
512 | * setting a timer to wake up at half second intervals thereafter, | 512 | * setting a timer to wake up at half second intervals thereafter, |
513 | * until timeout is achieved, before timing out. | 513 | * until timeout is achieved, before timing out. |
514 | */ | 514 | */ |
515 | int ide_wait_stat (ide_startstop_t *startstop, ide_drive_t *drive, u8 good, u8 bad, unsigned long timeout) | 515 | static int __ide_wait_stat(ide_drive_t *drive, u8 good, u8 bad, unsigned long timeout, u8 *rstat) |
516 | { | 516 | { |
517 | ide_hwif_t *hwif = HWIF(drive); | 517 | ide_hwif_t *hwif = drive->hwif; |
518 | u8 stat; | ||
519 | int i; | ||
520 | unsigned long flags; | 518 | unsigned long flags; |
521 | 519 | int i; | |
522 | /* bail early if we've exceeded max_failures */ | 520 | u8 stat; |
523 | if (drive->max_failures && (drive->failures > drive->max_failures)) { | ||
524 | *startstop = ide_stopped; | ||
525 | return 1; | ||
526 | } | ||
527 | 521 | ||
528 | udelay(1); /* spec allows drive 400ns to assert "BUSY" */ | 522 | udelay(1); /* spec allows drive 400ns to assert "BUSY" */ |
529 | if ((stat = hwif->INB(IDE_STATUS_REG)) & BUSY_STAT) { | 523 | if ((stat = hwif->INB(IDE_STATUS_REG)) & BUSY_STAT) { |
@@ -541,8 +535,8 @@ int ide_wait_stat (ide_startstop_t *startstop, ide_drive_t *drive, u8 good, u8 b | |||
541 | break; | 535 | break; |
542 | 536 | ||
543 | local_irq_restore(flags); | 537 | local_irq_restore(flags); |
544 | *startstop = ide_error(drive, "status timeout", stat); | 538 | *rstat = stat; |
545 | return 1; | 539 | return -EBUSY; |
546 | } | 540 | } |
547 | } | 541 | } |
548 | local_irq_restore(flags); | 542 | local_irq_restore(flags); |
@@ -556,11 +550,39 @@ int ide_wait_stat (ide_startstop_t *startstop, ide_drive_t *drive, u8 good, u8 b | |||
556 | */ | 550 | */ |
557 | for (i = 0; i < 10; i++) { | 551 | for (i = 0; i < 10; i++) { |
558 | udelay(1); | 552 | udelay(1); |
559 | if (OK_STAT((stat = hwif->INB(IDE_STATUS_REG)), good, bad)) | 553 | if (OK_STAT((stat = hwif->INB(IDE_STATUS_REG)), good, bad)) { |
554 | *rstat = stat; | ||
560 | return 0; | 555 | return 0; |
556 | } | ||
561 | } | 557 | } |
562 | *startstop = ide_error(drive, "status error", stat); | 558 | *rstat = stat; |
563 | return 1; | 559 | return -EFAULT; |
560 | } | ||
561 | |||
562 | /* | ||
563 | * In case of error returns error value after doing "*startstop = ide_error()". | ||
564 | * The caller should return the updated value of "startstop" in this case, | ||
565 | * "startstop" is unchanged when the function returns 0. | ||
566 | */ | ||
567 | int ide_wait_stat(ide_startstop_t *startstop, ide_drive_t *drive, u8 good, u8 bad, unsigned long timeout) | ||
568 | { | ||
569 | int err; | ||
570 | u8 stat; | ||
571 | |||
572 | /* bail early if we've exceeded max_failures */ | ||
573 | if (drive->max_failures && (drive->failures > drive->max_failures)) { | ||
574 | *startstop = ide_stopped; | ||
575 | return 1; | ||
576 | } | ||
577 | |||
578 | err = __ide_wait_stat(drive, good, bad, timeout, &stat); | ||
579 | |||
580 | if (err) { | ||
581 | char *s = (err == -EBUSY) ? "status timeout" : "status error"; | ||
582 | *startstop = ide_error(drive, s, stat); | ||
583 | } | ||
584 | |||
585 | return err; | ||
564 | } | 586 | } |
565 | 587 | ||
566 | EXPORT_SYMBOL(ide_wait_stat); | 588 | EXPORT_SYMBOL(ide_wait_stat); |
@@ -778,15 +800,10 @@ int ide_driveid_update (ide_drive_t *drive) | |||
778 | #endif | 800 | #endif |
779 | } | 801 | } |
780 | 802 | ||
781 | /* | 803 | int ide_config_drive_speed(ide_drive_t *drive, u8 speed) |
782 | * Similar to ide_wait_stat(), except it never calls ide_error internally. | ||
783 | * | ||
784 | * const char *msg == consider adding for verbose errors. | ||
785 | */ | ||
786 | int ide_config_drive_speed (ide_drive_t *drive, u8 speed) | ||
787 | { | 804 | { |
788 | ide_hwif_t *hwif = HWIF(drive); | 805 | ide_hwif_t *hwif = drive->hwif; |
789 | int i, error = 1; | 806 | int error; |
790 | u8 stat; | 807 | u8 stat; |
791 | 808 | ||
792 | // while (HWGROUP(drive)->busy) | 809 | // while (HWGROUP(drive)->busy) |
@@ -826,35 +843,10 @@ int ide_config_drive_speed (ide_drive_t *drive, u8 speed) | |||
826 | hwif->OUTBSYNC(drive, WIN_SETFEATURES, IDE_COMMAND_REG); | 843 | hwif->OUTBSYNC(drive, WIN_SETFEATURES, IDE_COMMAND_REG); |
827 | if ((IDE_CONTROL_REG) && (drive->quirk_list == 2)) | 844 | if ((IDE_CONTROL_REG) && (drive->quirk_list == 2)) |
828 | hwif->OUTB(drive->ctl, IDE_CONTROL_REG); | 845 | hwif->OUTB(drive->ctl, IDE_CONTROL_REG); |
829 | udelay(1); | ||
830 | /* | ||
831 | * Wait for drive to become non-BUSY | ||
832 | */ | ||
833 | if ((stat = hwif->INB(IDE_STATUS_REG)) & BUSY_STAT) { | ||
834 | unsigned long flags, timeout; | ||
835 | local_irq_set(flags); | ||
836 | timeout = jiffies + WAIT_CMD; | ||
837 | while ((stat = hwif->INB(IDE_STATUS_REG)) & BUSY_STAT) { | ||
838 | if (time_after(jiffies, timeout)) | ||
839 | break; | ||
840 | } | ||
841 | local_irq_restore(flags); | ||
842 | } | ||
843 | 846 | ||
844 | /* | 847 | error = __ide_wait_stat(drive, drive->ready_stat, |
845 | * Allow status to settle, then read it again. | 848 | BUSY_STAT|DRQ_STAT|ERR_STAT, |
846 | * A few rare drives vastly violate the 400ns spec here, | 849 | WAIT_CMD, &stat); |
847 | * so we'll wait up to 10usec for a "good" status | ||
848 | * rather than expensively fail things immediately. | ||
849 | * This fix courtesy of Matthew Faupel & Niccolo Rigacci. | ||
850 | */ | ||
851 | for (i = 0; i < 10; i++) { | ||
852 | udelay(1); | ||
853 | if (OK_STAT((stat = hwif->INB(IDE_STATUS_REG)), drive->ready_stat, BUSY_STAT|DRQ_STAT|ERR_STAT)) { | ||
854 | error = 0; | ||
855 | break; | ||
856 | } | ||
857 | } | ||
858 | 850 | ||
859 | SELECT_MASK(drive, 0); | 851 | SELECT_MASK(drive, 0); |
860 | 852 | ||