[PATCH 2.6.11-rc2] ide: merge do_rw_taskfile() and flagged_taskfile() into do_taskfile()

From: Tejun Heo
Date: Sat Feb 05 2005 - 21:19:00 EST


Hello, Bartlomiej.

This is a new version of ide_do_taskfile.patch. Compared to the
original do_rw_task(), only one more 'if' is used in the hot path, so
I think the performance issue can be ignored now. Also, there's no
userland visible change with this patch. Everything should work just
as it did with do_rw_taskfile()/flagged_taskfile().

do_taskfile() is different from do_rw_taskfile() in that

- It uses task->data_phase to determine whether it's a DMA command
or not.

do_taskfile() is different from flagged_taskfile() in that

- No (TASKFILE_MULTI_IN && !mult_count) check. ide_taskfile_ioctl()
checks the same thing, so it doesn't change anything.
- No task->tf_out_flags handling. ide_end_drive_cmd() ignores it
anyway, so, again, it doesn't change anything.

So, what do you think?


Signed-off-by: Tejun Heo (tj@xxxxxxxxxxx)


Index: linux-ide-series3-export/drivers/ide/ide-disk.c
===================================================================
--- linux-ide-series3-export.orig/drivers/ide/ide-disk.c 2005-02-06 10:58:27.478337364 +0900
+++ linux-ide-series3-export/drivers/ide/ide-disk.c 2005-02-06 11:01:11.673688441 +0900
@@ -535,7 +535,7 @@ static ide_startstop_t idedisk_special (
args.tfRegister[IDE_COMMAND_OFFSET] = WIN_SPECIFY;
args.command_type = IDE_DRIVE_TASK_NO_DATA;
args.handler = &set_geometry_intr;
- do_rw_taskfile(drive, &args);
+ do_taskfile(drive, &args);
}
} else if (s->b.recalibrate) {
s->b.recalibrate = 0;
@@ -546,7 +546,7 @@ static ide_startstop_t idedisk_special (
args.tfRegister[IDE_COMMAND_OFFSET] = WIN_RESTORE;
args.command_type = IDE_DRIVE_TASK_NO_DATA;
args.handler = &recal_intr;
- do_rw_taskfile(drive, &args);
+ do_taskfile(drive, &args);
}
} else if (s->b.set_multmode) {
s->b.set_multmode = 0;
@@ -559,7 +559,7 @@ static ide_startstop_t idedisk_special (
args.tfRegister[IDE_COMMAND_OFFSET] = WIN_SETMULT;
args.command_type = IDE_DRIVE_TASK_NO_DATA;
args.handler = &set_multmode_intr;
- do_rw_taskfile(drive, &args);
+ do_taskfile(drive, &args);
}
} else if (s->all) {
int special = s->all;
@@ -898,19 +898,19 @@ static ide_startstop_t idedisk_start_pow
args->tfRegister[IDE_COMMAND_OFFSET] = WIN_FLUSH_CACHE;
args->command_type = IDE_DRIVE_TASK_NO_DATA;
args->handler = &task_no_data_intr;
- return do_rw_taskfile(drive, args);
+ return do_taskfile(drive, args);

case idedisk_pm_standby: /* Suspend step 2 (standby) */
args->tfRegister[IDE_COMMAND_OFFSET] = WIN_STANDBYNOW1;
args->command_type = IDE_DRIVE_TASK_NO_DATA;
args->handler = &task_no_data_intr;
- return do_rw_taskfile(drive, args);
+ return do_taskfile(drive, args);

case idedisk_pm_idle: /* Resume step 1 (idle) */
args->tfRegister[IDE_COMMAND_OFFSET] = WIN_IDLEIMMEDIATE;
args->command_type = IDE_DRIVE_TASK_NO_DATA;
args->handler = task_no_data_intr;
- return do_rw_taskfile(drive, args);
+ return do_taskfile(drive, args);

case idedisk_pm_restore_dma: /* Resume step 2 (restore DMA) */
/*
Index: linux-ide-series3-export/drivers/ide/ide-io.c
===================================================================
--- linux-ide-series3-export.orig/drivers/ide/ide-io.c 2005-02-06 10:58:27.478337364 +0900
+++ linux-ide-series3-export/drivers/ide/ide-io.c 2005-02-06 11:01:11.675688117 +0900
@@ -682,9 +682,7 @@ static ide_startstop_t execute_drive_tas
break;
}

- if (args->tf_out_flags.all != 0)
- return flagged_taskfile(drive, args);
- return do_rw_taskfile(drive, args);
+ return do_taskfile(drive, args);
}

/**
Index: linux-ide-series3-export/drivers/ide/ide-taskfile.c
===================================================================
--- linux-ide-series3-export.orig/drivers/ide/ide-taskfile.c 2005-02-06 10:58:27.479337202 +0900
+++ linux-ide-series3-export/drivers/ide/ide-taskfile.c 2005-02-06 11:01:11.676687955 +0900
@@ -96,35 +96,86 @@ int taskfile_lib_get_identify (ide_drive
return ide_raw_taskfile(drive, &args, buf);
}

-ide_startstop_t do_rw_taskfile (ide_drive_t *drive, ide_task_t *task)
+ide_startstop_t do_taskfile(ide_drive_t *drive, ide_task_t *task)
{
ide_hwif_t *hwif = HWIF(drive);
task_struct_t *taskfile = (task_struct_t *) task->tfRegister;
hob_struct_t *hobfile = (hob_struct_t *) task->hobRegister;
- u8 HIHI = (drive->addressing == 1) ? 0xE0 : 0xEF;

- /* ALL Command Block Executions SHALL clear nIEN, unless otherwise */
- if (IDE_CONTROL_REG) {
- /* clear nIEN */
+ /* ALL Command Block Executions SHALL clear nIEN, unless
+ * otherwise specified.*/
+ if (IDE_CONTROL_REG)
hwif->OUTB(drive->ctl, IDE_CONTROL_REG);
- }
SELECT_MASK(drive, 0);

- if (drive->addressing == 1) {
- hwif->OUTB(hobfile->feature, IDE_FEATURE_REG);
- hwif->OUTB(hobfile->sector_count, IDE_NSECTOR_REG);
- hwif->OUTB(hobfile->sector_number, IDE_SECTOR_REG);
- hwif->OUTB(hobfile->low_cylinder, IDE_LCYL_REG);
- hwif->OUTB(hobfile->high_cylinder, IDE_HCYL_REG);
- }
+ /*
+ * (ks) Check taskfile out flags.
+ * If set, then execute as it is defined.
+ * If not set, then,
+ * write all taskfile registers (except data)
+ * write the hob registers (feature,sector,nsector,lcyl,hcyl)
+ */
+ if (task->tf_out_flags.all == 0) {
+ /* Common path optimization */
+ if (drive->addressing == 1) {
+ /* Send hob registers first */
+ hwif->OUTB(hobfile->feature, IDE_FEATURE_REG);
+ hwif->OUTB(hobfile->sector_count, IDE_NSECTOR_REG);
+ hwif->OUTB(hobfile->sector_number, IDE_SECTOR_REG);
+ hwif->OUTB(hobfile->low_cylinder, IDE_LCYL_REG);
+ hwif->OUTB(hobfile->high_cylinder, IDE_HCYL_REG);
+ }

- hwif->OUTB(taskfile->feature, IDE_FEATURE_REG);
- hwif->OUTB(taskfile->sector_count, IDE_NSECTOR_REG);
- hwif->OUTB(taskfile->sector_number, IDE_SECTOR_REG);
- hwif->OUTB(taskfile->low_cylinder, IDE_LCYL_REG);
- hwif->OUTB(taskfile->high_cylinder, IDE_HCYL_REG);
+ /* Send now the standard registers */
+ hwif->OUTB(taskfile->feature, IDE_FEATURE_REG);
+ hwif->OUTB(taskfile->sector_count, IDE_NSECTOR_REG);
+ hwif->OUTB(taskfile->sector_number, IDE_SECTOR_REG);
+ hwif->OUTB(taskfile->low_cylinder, IDE_LCYL_REG);
+ hwif->OUTB(taskfile->high_cylinder, IDE_HCYL_REG);

- hwif->OUTB((taskfile->device_head & HIHI) | drive->select.all, IDE_SELECT_REG);
+ hwif->OUTB((taskfile->device_head & ~0x10) | drive->select.all,
+ IDE_SELECT_REG);
+ } else {
+ if (drive->addressing == 1) {
+ /* (ks) Send hob registers first */
+ if (task->tf_out_flags.b.error_feature)
+ hwif->OUTB(hobfile->feature, IDE_FEATURE_REG);
+ if (task->tf_out_flags.b.nsector_hob)
+ hwif->OUTB(hobfile->sector_count, IDE_NSECTOR_REG);
+ if (task->tf_out_flags.b.sector_hob)
+ hwif->OUTB(hobfile->sector_number, IDE_SECTOR_REG);
+ if (task->tf_out_flags.b.lcyl_hob)
+ hwif->OUTB(hobfile->low_cylinder, IDE_LCYL_REG);
+ if (task->tf_out_flags.b.hcyl_hob)
+ hwif->OUTB(hobfile->high_cylinder, IDE_HCYL_REG);
+ }
+
+ /* (ks) Send now the standard registers */
+ if (task->tf_out_flags.b.error_feature)
+ hwif->OUTB(taskfile->feature, IDE_FEATURE_REG);
+ if (task->tf_out_flags.b.nsector)
+ hwif->OUTB(taskfile->sector_count, IDE_NSECTOR_REG);
+ if (task->tf_out_flags.b.sector)
+ hwif->OUTB(taskfile->sector_number, IDE_SECTOR_REG);
+ if (task->tf_out_flags.b.lcyl)
+ hwif->OUTB(taskfile->low_cylinder, IDE_LCYL_REG);
+ if (task->tf_out_flags.b.hcyl)
+ hwif->OUTB(taskfile->high_cylinder, IDE_HCYL_REG);
+
+ if (task->tf_out_flags.b.data) {
+ u16 data = taskfile->data + (hobfile->data << 8);
+ hwif->OUTW(data, IDE_DATA_REG);
+ }
+
+ /*
+ * (ks) In the taskfile approch, we will use all specified
+ * registers and the register value will not be changed,
+ * except the select bit (master/slave) in the drive_head
+ * register. We must make sure that the desired drive is
+ * selected.
+ */
+ hwif->OUTB(taskfile->device_head | drive->select.all, IDE_SELECT_REG);
+ }

if (task->handler != NULL) {
if (task->prehandler != NULL) {
@@ -136,32 +187,23 @@ ide_startstop_t do_rw_taskfile (ide_driv
return ide_started;
}

- if (!drive->using_dma)
+ switch (task->data_phase) {
+ case TASKFILE_OUT_DMAQ:
+ case TASKFILE_OUT_DMA:
+ case TASKFILE_IN_DMAQ:
+ case TASKFILE_IN_DMA:
+ if (!hwif->dma_setup(drive)) {
+ hwif->dma_exec_cmd(drive, taskfile->command);
+ hwif->dma_start(drive);
+ return ide_started;
+ }
+ return ide_stopped;
+ default:
return ide_stopped;
-
- switch (taskfile->command) {
- case WIN_WRITEDMA_ONCE:
- case WIN_WRITEDMA:
- case WIN_WRITEDMA_EXT:
- case WIN_READDMA_ONCE:
- case WIN_READDMA:
- case WIN_READDMA_EXT:
- case WIN_IDENTIFY_DMA:
- if (!hwif->dma_setup(drive)) {
- hwif->dma_exec_cmd(drive, taskfile->command);
- hwif->dma_start(drive);
- return ide_started;
- }
- break;
- default:
- if (task->handler == NULL)
- return ide_stopped;
}
-
- return ide_stopped;
}

-EXPORT_SYMBOL(do_rw_taskfile);
+EXPORT_SYMBOL(do_taskfile);

/*
* set_multmode_intr() is invoked on completion of a WIN_SETMULT cmd.
@@ -789,124 +831,3 @@ int ide_task_ioctl(ide_drive_t *drive, u

return ret;
}
-
-/*
- * NOTICE: This is additions from IBM to provide a discrete interface,
- * for selective taskregister access operations. Nice JOB Klaus!!!
- * Glad to be able to work and co-develop this with you and IBM.
- */
-ide_startstop_t flagged_taskfile (ide_drive_t *drive, ide_task_t *task)
-{
- ide_hwif_t *hwif = HWIF(drive);
- task_struct_t *taskfile = (task_struct_t *) task->tfRegister;
- hob_struct_t *hobfile = (hob_struct_t *) task->hobRegister;
-#if DEBUG_TASKFILE
- u8 status;
-#endif
-
- if (task->data_phase == TASKFILE_MULTI_IN ||
- task->data_phase == TASKFILE_MULTI_OUT) {
- if (!drive->mult_count) {
- printk(KERN_ERR "%s: multimode not set!\n", drive->name);
- return ide_stopped;
- }
- }
-
- /*
- * (ks) Check taskfile in/out flags.
- * If set, then execute as it is defined.
- * If not set, then define default settings.
- * The default values are:
- * write and read all taskfile registers (except data)
- * write and read the hob registers (sector,nsector,lcyl,hcyl)
- */
- if (task->tf_out_flags.all == 0) {
- task->tf_out_flags.all = IDE_TASKFILE_STD_OUT_FLAGS;
- if (drive->addressing == 1)
- task->tf_out_flags.all |= (IDE_HOB_STD_OUT_FLAGS << 8);
- }
-
- if (task->tf_in_flags.all == 0) {
- task->tf_in_flags.all = IDE_TASKFILE_STD_IN_FLAGS;
- if (drive->addressing == 1)
- task->tf_in_flags.all |= (IDE_HOB_STD_IN_FLAGS << 8);
- }
-
- /* ALL Command Block Executions SHALL clear nIEN, unless otherwise */
- if (IDE_CONTROL_REG)
- /* clear nIEN */
- hwif->OUTB(drive->ctl, IDE_CONTROL_REG);
- SELECT_MASK(drive, 0);
-
-#if DEBUG_TASKFILE
- status = hwif->INB(IDE_STATUS_REG);
- if (status & 0x80) {
- printk("flagged_taskfile -> Bad status. Status = %02x. wait 100 usec ...\n", status);
- udelay(100);
- status = hwif->INB(IDE_STATUS_REG);
- printk("flagged_taskfile -> Status = %02x\n", status);
- }
-#endif
-
- if (task->tf_out_flags.b.data) {
- u16 data = taskfile->data + (hobfile->data << 8);
- hwif->OUTW(data, IDE_DATA_REG);
- }
-
- /* (ks) send hob registers first */
- if (task->tf_out_flags.b.nsector_hob)
- hwif->OUTB(hobfile->sector_count, IDE_NSECTOR_REG);
- if (task->tf_out_flags.b.sector_hob)
- hwif->OUTB(hobfile->sector_number, IDE_SECTOR_REG);
- if (task->tf_out_flags.b.lcyl_hob)
- hwif->OUTB(hobfile->low_cylinder, IDE_LCYL_REG);
- if (task->tf_out_flags.b.hcyl_hob)
- hwif->OUTB(hobfile->high_cylinder, IDE_HCYL_REG);
-
- /* (ks) Send now the standard registers */
- if (task->tf_out_flags.b.error_feature)
- hwif->OUTB(taskfile->feature, IDE_FEATURE_REG);
- /* refers to number of sectors to transfer */
- if (task->tf_out_flags.b.nsector)
- hwif->OUTB(taskfile->sector_count, IDE_NSECTOR_REG);
- /* refers to sector offset or start sector */
- if (task->tf_out_flags.b.sector)
- hwif->OUTB(taskfile->sector_number, IDE_SECTOR_REG);
- if (task->tf_out_flags.b.lcyl)
- hwif->OUTB(taskfile->low_cylinder, IDE_LCYL_REG);
- if (task->tf_out_flags.b.hcyl)
- hwif->OUTB(taskfile->high_cylinder, IDE_HCYL_REG);
-
- /*
- * (ks) In the flagged taskfile approch, we will use all specified
- * registers and the register value will not be changed, except the
- * select bit (master/slave) in the drive_head register. We must make
- * sure that the desired drive is selected.
- */
- hwif->OUTB(taskfile->device_head | drive->select.all, IDE_SELECT_REG);
- switch(task->data_phase) {
-
- case TASKFILE_OUT_DMAQ:
- case TASKFILE_OUT_DMA:
- case TASKFILE_IN_DMAQ:
- case TASKFILE_IN_DMA:
- hwif->dma_setup(drive);
- hwif->dma_exec_cmd(drive, taskfile->command);
- hwif->dma_start(drive);
- break;
-
- default:
- if (task->handler == NULL)
- return ide_stopped;
-
- /* Issue the command */
- if (task->prehandler) {
- hwif->OUTBSYNC(drive, taskfile->command, IDE_COMMAND_REG);
- ndelay(400); /* FIXME */
- return task->prehandler(drive, task->rq);
- }
- ide_execute_command(drive, taskfile->command, task->handler, WAIT_WORSTCASE, NULL);
- }
-
- return ide_started;
-}
Index: linux-ide-series3-export/include/linux/ide.h
===================================================================
--- linux-ide-series3-export.orig/include/linux/ide.h 2005-02-06 10:58:27.479337202 +0900
+++ linux-ide-series3-export/include/linux/ide.h 2005-02-06 11:01:11.678687630 +0900
@@ -1090,7 +1090,7 @@ static inline void destroy_proc_ide_inte
* - ide_started : In this case, the channel is left busy until an
* async event (interrupt) occurs.
* Typically, start_power_step() will issue a taskfile request with
- * do_rw_taskfile().
+ * do_taskfile().
*
* Upon reception of the interrupt, the core will call complete_power_step()
* with the error code if any. This routine should update the step value
@@ -1298,12 +1298,7 @@ extern int wait_for_ready(ide_drive_t *,
/*
* taskfile io for disks for now...and builds request from ide_ioctl
*/
-extern ide_startstop_t do_rw_taskfile(ide_drive_t *, ide_task_t *);
-
-/*
- * Special Flagged Register Validation Caller
- */
-extern ide_startstop_t flagged_taskfile(ide_drive_t *, ide_task_t *);
+extern ide_startstop_t do_taskfile(ide_drive_t *, ide_task_t *);

extern ide_startstop_t set_multmode_intr(ide_drive_t *);
extern ide_startstop_t set_geometry_intr(ide_drive_t *);
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/