Gitweb:     
http://git.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=74af21cf4d0ab67df53608753a443dc7904ec12e
Commit:     74af21cf4d0ab67df53608753a443dc7904ec12e
Parent:     fd553ce86893e0a54ec0d07d1f1d241f2fb2aef3
Author:     Bartlomiej Zolnierkiewicz <[EMAIL PROTECTED]>
AuthorDate: Sat Oct 13 17:47:49 2007 +0200
Committer:  Bartlomiej Zolnierkiewicz <[EMAIL PROTECTED]>
CommitDate: Sat Oct 13 17:47:49 2007 +0200

    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 <[EMAIL PROTECTED]>
    Acked-by: Sergei Shtylyov <[EMAIL PROTECTED]>
    Signed-off-by: Bartlomiej Zolnierkiewicz <[EMAIL PROTECTED]>
---
 drivers/ide/ide-iops.c |   96 ++++++++++++++++++++++--------------------------
 include/linux/ide.h    |   11 +-----
 2 files changed, 45 insertions(+), 62 deletions(-)

diff --git a/drivers/ide/ide-iops.c b/drivers/ide/ide-iops.c
index cf0678b..fb524cf 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)
  * 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 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..
  * 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,
  * 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);
-       u8 stat;
-       int i;
+       ide_hwif_t *hwif = drive->hwif;
        unsigned long flags;
- 
-       /* bail early if we've exceeded max_failures */
-       if (drive->max_failures && (drive->failures > drive->max_failures)) {
-               *startstop = ide_stopped;
-               return 1;
-       }
+       int i;
+       u8 stat;
 
        udelay(1);      /* spec allows drive 400ns to assert "BUSY" */
        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
                                        break;
 
                                local_irq_restore(flags);
-                               *startstop = ide_error(drive, "status timeout", 
stat);
-                               return 1;
+                               *rstat = stat;
+                               return -EBUSY;
                        }
                }
                local_irq_restore(flags);
@@ -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++) {
                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;
+               }
        }
-       *startstop = ide_error(drive, "status error", stat);
-       return 1;
+       *rstat = stat;
+       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);
@@ -778,15 +800,10 @@ int ide_driveid_update (ide_drive_t *drive)
 #endif
 }
 
-/*
- * 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)
+int ide_config_drive_speed(ide_drive_t *drive, u8 speed)
 {
-       ide_hwif_t *hwif        = HWIF(drive);
-       int     i, error        = 1;
+       ide_hwif_t *hwif = drive->hwif;
+       int error;
        u8 stat;
 
 //     while (HWGROUP(drive)->busy)
@@ -826,35 +843,10 @@ int ide_config_drive_speed (ide_drive_t *drive, u8 speed)
        hwif->OUTBSYNC(drive, WIN_SETFEATURES, IDE_COMMAND_REG);
        if ((IDE_CONTROL_REG) && (drive->quirk_list == 2))
                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);
-       }
 
-       /*
-        * Allow status to settle, then read it again.
-        * A few rare drives vastly violate the 400ns spec here,
-        * 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;
-               }
-       }
+       error = __ide_wait_stat(drive, drive->ready_stat,
+                               BUSY_STAT|DRQ_STAT|ERR_STAT,
+                               WAIT_CMD, &stat);
 
        SELECT_MASK(drive, 0);
 
diff --git a/include/linux/ide.h b/include/linux/ide.h
index 85d448b..3a8cb81 100644
--- a/include/linux/ide.h
+++ b/include/linux/ide.h
@@ -1079,16 +1079,7 @@ extern void ide_fix_driveid(struct hd_driveid *);
  */
 extern void ide_fixstring(u8 *, const int, const int);
 
-/*
- * 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);
+int ide_wait_stat(ide_startstop_t *, ide_drive_t *, u8, u8, unsigned long);
 
 /*
  * Start a reset operation for an IDE interface.
-
To unsubscribe from this list: send the line "unsubscribe git-commits-head" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to