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: default avatarSergei Shtylyov <sshtylyov@ru.mvista.com>
Signed-off-by: default avatarBartlomiej Zolnierkiewicz <bzolnier@gmail.com>
parent fd553ce8
...@@ -505,25 +505,19 @@ int wait_for_ready (ide_drive_t *drive, int timeout) ...@@ -505,25 +505,19 @@ int wait_for_ready (ide_drive_t *drive, int timeout)
* This routine busy-waits for the drive status to be not "busy". * This routine busy-waits for the drive status to be not "busy".
* It then checks the status for all of the "good" bits and none * It then checks the status for all of the "good" bits and none
* of the "bad" bits, and if all is okay it returns 0. All other * of the "bad" bits, and if all is okay it returns 0. All other
* cases return 1 after invoking ide_error() -- caller should just return. * cases return error -- caller may then invoke ide_error().
* *
* This routine should get fixed to not hog the cpu during extra long waits.. * This routine should get fixed to not hog the cpu during extra long waits..
* That could be done by busy-waiting for the first jiffy or two, and then * That could be done by busy-waiting for the first jiffy or two, and then
* setting a timer to wake up at half second intervals thereafter, * setting a timer to wake up at half second intervals thereafter,
* until timeout is achieved, before timing out. * until timeout is achieved, before timing out.
*/ */
int ide_wait_stat (ide_startstop_t *startstop, ide_drive_t *drive, u8 good, u8 bad, unsigned long timeout) static int __ide_wait_stat(ide_drive_t *drive, u8 good, u8 bad, unsigned long timeout, u8 *rstat)
{ {
ide_hwif_t *hwif = HWIF(drive); ide_hwif_t *hwif = drive->hwif;
u8 stat;
int i;
unsigned long flags; unsigned long flags;
int i;
/* bail early if we've exceeded max_failures */ u8 stat;
if (drive->max_failures && (drive->failures > drive->max_failures)) {
*startstop = ide_stopped;
return 1;
}
udelay(1); /* spec allows drive 400ns to assert "BUSY" */ udelay(1); /* spec allows drive 400ns to assert "BUSY" */
if ((stat = hwif->INB(IDE_STATUS_REG)) & BUSY_STAT) { 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,8 +535,8 @@ int ide_wait_stat (ide_startstop_t *startstop, ide_drive_t *drive, u8 good, u8 b
break; break;
local_irq_restore(flags); local_irq_restore(flags);
*startstop = ide_error(drive, "status timeout", stat); *rstat = stat;
return 1; return -EBUSY;
} }
} }
local_irq_restore(flags); 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,11 +550,39 @@ int ide_wait_stat (ide_startstop_t *startstop, ide_drive_t *drive, u8 good, u8 b
*/ */
for (i = 0; i < 10; i++) { for (i = 0; i < 10; i++) {
udelay(1); udelay(1);
if (OK_STAT((stat = hwif->INB(IDE_STATUS_REG)), good, bad)) if (OK_STAT((stat = hwif->INB(IDE_STATUS_REG)), good, bad)) {
*rstat = stat;
return 0; return 0;
}
} }
*startstop = ide_error(drive, "status error", stat); *rstat = stat;
return 1; return -EFAULT;
}
/*
* In case of error returns error value after doing "*startstop = ide_error()".
* The caller should return the updated value of "startstop" in this case,
* "startstop" is unchanged when the function returns 0.
*/
int ide_wait_stat(ide_startstop_t *startstop, ide_drive_t *drive, u8 good, u8 bad, unsigned long timeout)
{
int err;
u8 stat;
/* bail early if we've exceeded max_failures */
if (drive->max_failures && (drive->failures > drive->max_failures)) {
*startstop = ide_stopped;
return 1;
}
err = __ide_wait_stat(drive, good, bad, timeout, &stat);
if (err) {
char *s = (err == -EBUSY) ? "status timeout" : "status error";
*startstop = ide_error(drive, s, stat);
}
return err;
} }
EXPORT_SYMBOL(ide_wait_stat); EXPORT_SYMBOL(ide_wait_stat);
...@@ -778,15 +800,10 @@ int ide_driveid_update (ide_drive_t *drive) ...@@ -778,15 +800,10 @@ int ide_driveid_update (ide_drive_t *drive)
#endif #endif
} }
/* int ide_config_drive_speed(ide_drive_t *drive, u8 speed)
* Similar to ide_wait_stat(), except it never calls ide_error internally.
*
* const char *msg == consider adding for verbose errors.
*/
int ide_config_drive_speed (ide_drive_t *drive, u8 speed)
{ {
ide_hwif_t *hwif = HWIF(drive); ide_hwif_t *hwif = drive->hwif;
int i, error = 1; int error;
u8 stat; u8 stat;
// while (HWGROUP(drive)->busy) // while (HWGROUP(drive)->busy)
...@@ -826,35 +843,10 @@ int ide_config_drive_speed (ide_drive_t *drive, u8 speed) ...@@ -826,35 +843,10 @@ int ide_config_drive_speed (ide_drive_t *drive, u8 speed)
hwif->OUTBSYNC(drive, WIN_SETFEATURES, IDE_COMMAND_REG); hwif->OUTBSYNC(drive, WIN_SETFEATURES, IDE_COMMAND_REG);
if ((IDE_CONTROL_REG) && (drive->quirk_list == 2)) if ((IDE_CONTROL_REG) && (drive->quirk_list == 2))
hwif->OUTB(drive->ctl, IDE_CONTROL_REG); hwif->OUTB(drive->ctl, IDE_CONTROL_REG);
udelay(1);
/*
* Wait for drive to become non-BUSY
*/
if ((stat = hwif->INB(IDE_STATUS_REG)) & BUSY_STAT) {
unsigned long flags, timeout;
local_irq_set(flags);
timeout = jiffies + WAIT_CMD;
while ((stat = hwif->INB(IDE_STATUS_REG)) & BUSY_STAT) {
if (time_after(jiffies, timeout))
break;
}
local_irq_restore(flags);
}
/* error = __ide_wait_stat(drive, drive->ready_stat,
* Allow status to settle, then read it again. BUSY_STAT|DRQ_STAT|ERR_STAT,
* A few rare drives vastly violate the 400ns spec here, WAIT_CMD, &stat);
* so we'll wait up to 10usec for a "good" status
* rather than expensively fail things immediately.
* This fix courtesy of Matthew Faupel & Niccolo Rigacci.
*/
for (i = 0; i < 10; i++) {
udelay(1);
if (OK_STAT((stat = hwif->INB(IDE_STATUS_REG)), drive->ready_stat, BUSY_STAT|DRQ_STAT|ERR_STAT)) {
error = 0;
break;
}
}
SELECT_MASK(drive, 0); SELECT_MASK(drive, 0);
......
...@@ -1079,16 +1079,7 @@ extern void ide_fix_driveid(struct hd_driveid *); ...@@ -1079,16 +1079,7 @@ extern void ide_fix_driveid(struct hd_driveid *);
*/ */
extern void ide_fixstring(u8 *, const int, const int); extern void ide_fixstring(u8 *, const int, const int);
/* int ide_wait_stat(ide_startstop_t *, ide_drive_t *, u8, u8, unsigned long);
* This routine busy-waits for the drive status to be not "busy".
* It then checks the status for all of the "good" bits and none
* of the "bad" bits, and if all is okay it returns 0. All other
* cases return 1 after doing "*startstop = ide_error()", and the
* caller should return the updated value of "startstop" in this case.
* "startstop" is unchanged when the function returns 0;
* (startstop, drive, good, bad, timeout)
*/
extern int ide_wait_stat(ide_startstop_t *, ide_drive_t *, u8, u8, unsigned long);
/* /*
* Start a reset operation for an IDE interface. * Start a reset operation for an IDE interface.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment