Re: [PATCH] 2.5.67-ac1 IDE - fix Taskfile IOCTLs

From: Bartlomiej Zolnierkiewicz (B.Zolnierkiewicz@elka.pw.edu.pl)
Date: Thu Apr 17 2003 - 18:20:43 EST


tf-ioctls-2.diff:

# Taskfile and flagged Taskfile PIO handlers unification [1/2].
# Incremental to tf-ioctls-1 patch.
#
# Detailed changelog:
# - add request validity checking present in flagged PIO handlers
# to execute_drive_cmd(), so we now check also not flagged Taskfile
# and we abort bad requests early
# - add flagged_wait_drive_ready() for wating for non-busy drive status
# - add check for DATA_READY to task_out_intr() and task_mulout_intr()
#
# Bartlomiej Zolnierkiewicz <bzolnier@elka.pw.edu.pl>

diff -uNr linux-2.5.67-ac1-tf1/drivers/ide/ide-io.c linux/drivers/ide/ide-io.c
--- linux-2.5.67-ac1-tf1/drivers/ide/ide-io.c Thu Apr 17 20:03:36 2003
+++ linux/drivers/ide/ide-io.c Thu Apr 17 21:49:49 2003
@@ -496,7 +496,23 @@

                 if (!args)
                         goto done;
-
+
+ /* Some validity checking. */
+ if (!rq->hard_nr_sectors &&
+ (args->command_type != IDE_DRIVE_TASK_NO_DATA &&
+ args->command_type != IDE_DRIVE_TASK_SET_XFER)) {
+ printk(KERN_ERR "%s: %s: no data to transfer\n",
+ drive->name, __FUNCTION__);
+ goto abort;
+ }
+ if (!drive->mult_count &&
+ (args->data_phase == TASKFILE_MULTI_IN ||
+ args->data_phase == TASKFILE_MULTI_OUT)) {
+ printk(KERN_ERR "%s: %s: multimode not set\n",
+ drive->name, __FUNCTION__);
+ goto abort;
+ }
+
                 if (args->tf_out_flags.all != 0)
                         return flagged_taskfile(drive, args);
                 return do_rw_taskfile(drive, args);
@@ -559,6 +575,7 @@
 #ifdef DEBUG
          printk("%s: DRIVE_CMD (null)\n", drive->name);
 #endif
+abort:
          ide_end_drive_cmd(drive,
                         hwif->INB(IDE_STATUS_REG),
                         hwif->INB(IDE_ERROR_REG));
diff -uNr linux-2.5.67-ac1-tf1/drivers/ide/ide-taskfile.c linux/drivers/ide/ide-taskfile.c
--- linux-2.5.67-ac1-tf1/drivers/ide/ide-taskfile.c Thu Apr 17 20:10:59 2003
+++ linux/drivers/ide/ide-taskfile.c Thu Apr 17 21:17:43 2003
@@ -355,6 +355,20 @@

 EXPORT_SYMBOL(task_no_data_intr);

+static u8 flagged_wait_drive_ready(ide_drive_t *drive)
+{
+ ide_hwif_t *hwif = HWIF(drive);
+ int retries = 5;
+ u8 stat;
+ /*
+ * (ks) Last sector was transfered, wait until drive is ready.
+ * This can take up to 10 usec. We willl wait max 50 us.
+ */
+ while (((stat = hwif->INB(IDE_STATUS_REG)) & BUSY_STAT) && retries--)
+ udelay(10);
+ return stat;
+}
+
 #define PIO_IN 0
 #define PIO_OUT 1

@@ -386,11 +400,12 @@
 ide_startstop_t task_in_intr (ide_drive_t *drive)
 {
         struct request *rq = HWGROUP(drive)->rq;
+ ide_task_t *task = (ide_task_t *) rq->special;
         u8 stat, good_stat;

         good_stat = DATA_READY;
-check_status:
         stat = HWIF(drive)->INB(IDE_STATUS_REG);
+check_status:
         if (!OK_STAT(stat, good_stat, BAD_R_STAT)) {
                 if (stat & (ERR_STAT|DRQ_STAT))
                         return DRIVER(drive)->error(drive, __FUNCTION__, stat);
@@ -417,6 +432,11 @@

         /* If it was the last datablock check status and finish transfer. */
         if (!rq->nr_sectors) {
+ /* FIXME: Use for all requests? --bzolnier */
+ if (!blk_fs_request(rq) && task->tf_out_flags.all != 0)
+ stat = flagged_wait_drive_ready(drive);
+ else
+ stat = HWIF(drive)->INB(IDE_STATUS_REG);
                 good_stat = 0;
                 goto check_status;
         }
@@ -435,13 +455,14 @@
 ide_startstop_t task_mulin_intr (ide_drive_t *drive)
 {
         struct request *rq = HWGROUP(drive)->rq;
+ ide_task_t *task = (ide_task_t *) rq->special;
         unsigned int msect = drive->mult_count;
         unsigned int nsect;
         u8 stat, good_stat;

         good_stat = DATA_READY;
-check_status:
         stat = HWIF(drive)->INB(IDE_STATUS_REG);
+check_status:
         if (!OK_STAT(stat, good_stat, BAD_R_STAT)) {
                 if (stat & (ERR_STAT|DRQ_STAT))
                         return DRIVER(drive)->error(drive, __FUNCTION__, stat);
@@ -479,6 +500,11 @@

         /* If it was the last datablock check status and finish transfer. */
         if (!rq->nr_sectors) {
+ /* FIXME: Use for all requests? --bzolnier */
+ if (!blk_fs_request(rq) && task->tf_out_flags.all != 0)
+ stat = flagged_wait_drive_ready(drive);
+ else
+ stat = HWIF(drive)->INB(IDE_STATUS_REG);
                 good_stat = 0;
                 goto check_status;
         }
@@ -513,6 +539,11 @@
                 }
         }

+ /* Deal with unexpected ATA data phase. */
+ ok_stat = OK_STAT(stat, DATA_READY, drive->bad_wstat);
+ if (!ok_stat && rq->nr_sectors)
+ return DRIVER(drive)->error(drive, __FUNCTION__, stat);
+
         /*
          * Complete previously submitted bios (if any).
          * Status was already verifyied.
@@ -577,6 +608,11 @@
                 }
         }

+ /* Deal with unexpected ATA data phase. */
+ ok_stat = OK_STAT(stat, DATA_READY, drive->bad_wstat);
+ if (!ok_stat && rq->nr_sectors)
+ return DRIVER(drive)->error(drive, __FUNCTION__, stat);
+
         /*
          * Complete previously submitted bios (if any).
          * Status was already verifyied.
@@ -1619,7 +1655,6 @@
         u8 stat = hwif->INB(IDE_STATUS_REG);
         struct request *rq = HWGROUP(drive)->rq;
         char *pBuf = NULL;
- int retries = 5;

         if (rq->current_nr_sectors == 0)
                 return DRIVER(drive)->error(drive, "flagged_task_in_intr (no data requested)", stat);
@@ -1650,12 +1685,7 @@
                 ide_set_handler(drive, &flagged_task_in_intr, WAIT_WORSTCASE, NULL);
                 return ide_started;
         }
- /*
- * (ks) Last sector was transfered, wait until drive is ready.
- * This can take up to 10 usec. We willl wait max 50 us.
- */
- while (((stat = hwif->INB(IDE_STATUS_REG)) & BUSY_STAT) && retries--)
- udelay(10);
+ stat = flagged_wait_drive_ready(drive);
         ide_end_drive_cmd (drive, stat, hwif->INB(IDE_ERROR_REG));

         return ide_stopped;
@@ -1667,7 +1697,6 @@
         u8 stat = hwif->INB(IDE_STATUS_REG);
         struct request *rq = HWGROUP(drive)->rq;
         char *pBuf = NULL;
- int retries = 5;
         unsigned int msect, nsect;

         if (rq->current_nr_sectors == 0)
@@ -1707,13 +1736,7 @@
                 ide_set_handler(drive, &flagged_task_mulin_intr, WAIT_WORSTCASE, NULL);
                 return ide_started;
         }
-
- /*
- * (ks) Last sector was transfered, wait until drive is ready.
- * This can take up to 10 usec. We willl wait max 50 us.
- */
- while (((stat = hwif->INB(IDE_STATUS_REG)) & BUSY_STAT) && retries--)
- udelay(10);
+ stat = flagged_wait_drive_ready(drive);
         ide_end_drive_cmd (drive, stat, hwif->INB(IDE_ERROR_REG));

         return ide_stopped;

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/



This archive was generated by hypermail 2b29 : Wed Apr 23 2003 - 22:00:22 EST