ide: move ide_config_drive_speed() calls to upper layers (take 2)

* Convert {ide_hwif_t,ide_pci_device_t}->host_flag to be u16.

* Add IDE_HFLAG_POST_SET_MODE host flag to indicate the need to program 
  the host for the transfer mode after programming the device.  Set it
  in au1xxx-ide, amd74xx, cs5530, cs5535, pdc202xx_new, sc1200, pmac
  and via82cxxx host drivers.

* Add IDE_HFLAG_NO_SET_MODE host flag to indicate the need to completely
  skip programming of host/device for the transfer mode ("smart" hosts).
  Set it in it821x host driver and check it in ide_tune_dma().

* Add ide_set_pio_mode()/ide_set_dma_mode() helpers and convert all
  direct ->set_pio_mode/->speedproc users to use these helpers.

* Move ide_config_drive_speed() calls from ->set_pio_mode/->speedproc
  methods to callers.

* Rename ->speedproc method to ->set_dma_mode, make it void and update
  all implementations accordingly.

* Update ide_set_xfer_rate() comments.

* Unexport ide_config_drive_speed().

v2:
* Fix issues noticed by Sergei:
  - export ide_set_dma_mode() instead of moving ->set_pio_mode abuse wrt
    to setting DMA modes from sc1200_set_pio_mode() to do_special()
  - check IDE_HFLAG_NO_SET_MODE in ide_tune_dma()
  - check for (hwif->set_pio_mode) == NULL in ide_set_pio_mode()
  - check for (hwif->set_dma_mode) == NULL in ide_set_dma_mode()
  - return -1 from ide_set_{pio,dma}_mode() if ->set_{pio,dma}_mode == NULL
  - don't set ->set_{pio,dma}_mode on it821x in "smart" mode
  - fix build problem in pmac.c
  - minor fixes in au1xxx-ide.c/cs5530.c/siimage.c
  - improve patch description

Changes in behavior caused by this patch:
- HDIO_SET_PIO_MODE ioctl would now return -ENOSYS for attempts to change
  PIO mode if it821x controller is in "smart" mode
- removal of two debugging printk-s (from cs5530.c and sc1200.c)
- transfer modes 0x00-0x07 passed from user space may be programmed twice on
  the device (not really an issue since 0x00 is not supported correctly by
  any host driver ATM, 0x01 is not supported at all and 0x02-0x07 are invalid)

Acked-by: Sergei Shtylyov <sshtylyov@ru.mvista.com>
Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
diff --git a/drivers/ide/arm/icside.c b/drivers/ide/arm/icside.c
index 110e523..bd1f5b6 100644
--- a/drivers/ide/arm/icside.c
+++ b/drivers/ide/arm/icside.c
@@ -248,7 +248,7 @@
  *	MW1	80	50	50	150	C
  *	MW2	70	25	25	120	C
  */
-static int icside_set_speed(ide_drive_t *drive, const u8 xfer_mode)
+static void icside_set_dma_mode(ide_drive_t *drive, const u8 xfer_mode)
 {
 	int cycle_time, use_dma_info = 0;
 
@@ -273,7 +273,7 @@
 		cycle_time = 480;
 		break;
 	default:
-		return 1;
+		return;
 	}
 
 	/*
@@ -287,8 +287,6 @@
 
 	printk("%s: %s selected (peak %dMB/s)\n", drive->name,
 		ide_xfer_verbose(xfer_mode), 2000 / drive->drive_data);
-
-	return ide_config_drive_speed(drive, xfer_mode);
 }
 
 static void icside_dma_host_off(ide_drive_t *drive)
@@ -433,7 +431,7 @@
 
 	hwif->dmatable_cpu	= NULL;
 	hwif->dmatable_dma	= 0;
-	hwif->speedproc		= icside_set_speed;
+	hwif->set_dma_mode	= icside_set_dma_mode;
 	hwif->autodma		= 1;
 
 	hwif->ide_dma_check	= icside_dma_check;
diff --git a/drivers/ide/cris/ide-cris.c b/drivers/ide/cris/ide-cris.c
index 4bb42b3..2b4d2a0 100644
--- a/drivers/ide/cris/ide-cris.c
+++ b/drivers/ide/cris/ide-cris.c
@@ -716,11 +716,9 @@
 	}
 
 	cris_ide_set_speed(TYPE_PIO, setup, strobe, hold);
-
-	(void)ide_config_drive_speed(drive, XFER_PIO_0 + pio);
 }
 
-static int speed_cris_ide(ide_drive_t *drive, const u8 speed)
+static void cris_set_dma_mode(ide_drive_t *drive, const u8 speed)
 {
 	int cyc = 0, dvs = 0, strobe = 0, hold = 0;
 
@@ -759,8 +757,6 @@
 		cris_ide_set_speed(TYPE_UDMA, cyc, dvs, 0);
 	else
 		cris_ide_set_speed(TYPE_DMA, 0, strobe, hold);
-
-	return ide_config_drive_speed(drive, speed);
 }
 
 void __init
@@ -791,7 +787,7 @@
 		hwif->mmio = 1;
 		hwif->chipset = ide_etrax100;
 		hwif->set_pio_mode = &cris_set_pio_mode;
-		hwif->speedproc = &speed_cris_ide;
+		hwif->set_dma_mode = &cris_set_dma_mode;
 		hwif->ata_input_data = &cris_ide_input_data;
 		hwif->ata_output_data = &cris_ide_output_data;
 		hwif->atapi_input_bytes = &cris_atapi_input_bytes;
diff --git a/drivers/ide/ide-dma.c b/drivers/ide/ide-dma.c
index 05781fa..b453211 100644
--- a/drivers/ide/ide-dma.c
+++ b/drivers/ide/ide-dma.c
@@ -774,7 +774,10 @@
 	if (!speed)
 		return 0;
 
-	if (drive->hwif->speedproc(drive, speed))
+	if (drive->hwif->host_flags & IDE_HFLAG_NO_SET_MODE)
+		return 0;
+
+	if (ide_set_dma_mode(drive, speed))
 		return 0;
 
 	return 1;
diff --git a/drivers/ide/ide-iops.c b/drivers/ide/ide-iops.c
index e5fc2e5..f5e73e2 100644
--- a/drivers/ide/ide-iops.c
+++ b/drivers/ide/ide-iops.c
@@ -862,9 +862,6 @@
 	return error;
 }
 
-EXPORT_SYMBOL(ide_config_drive_speed);
-
-
 /*
  * This should get invoked any time we exit the driver to
  * wait for an interrupt response from a drive.  handler() points
diff --git a/drivers/ide/ide-lib.c b/drivers/ide/ide-lib.c
index d97390c..0e2562f 100644
--- a/drivers/ide/ide-lib.c
+++ b/drivers/ide/ide-lib.c
@@ -349,7 +349,7 @@
 			  drive->name, host_pio, req_pio,
 			  req_pio == 255 ? "(auto-tune)" : "", pio);
 
-	hwif->set_pio_mode(drive, pio);
+	(void)ide_set_pio_mode(drive, XFER_PIO_0 + pio);
 }
 
 EXPORT_SYMBOL_GPL(ide_set_pio);
@@ -378,39 +378,83 @@
 		blk_queue_bounce_limit(drive->queue, addr);
 }
 
+int ide_set_pio_mode(ide_drive_t *drive, const u8 mode)
+{
+	ide_hwif_t *hwif = drive->hwif;
+
+	if (hwif->set_pio_mode == NULL)
+		return -1;
+
+	/*
+	 * TODO: temporary hack for some legacy host drivers that didn't
+	 * set transfer mode on the device in ->set_pio_mode method...
+	 */
+	if (hwif->set_dma_mode == NULL) {
+		hwif->set_pio_mode(drive, mode - XFER_PIO_0);
+		return 0;
+	}
+
+	if (hwif->host_flags & IDE_HFLAG_POST_SET_MODE) {
+		if (ide_config_drive_speed(drive, mode))
+			return -1;
+		hwif->set_pio_mode(drive, mode - XFER_PIO_0);
+		return 0;
+	} else {
+		hwif->set_pio_mode(drive, mode - XFER_PIO_0);
+		return ide_config_drive_speed(drive, mode);
+	}
+}
+
+int ide_set_dma_mode(ide_drive_t *drive, const u8 mode)
+{
+	ide_hwif_t *hwif = drive->hwif;
+
+	if (hwif->set_dma_mode == NULL)
+		return -1;
+
+	if (hwif->host_flags & IDE_HFLAG_POST_SET_MODE) {
+		if (ide_config_drive_speed(drive, mode))
+			return -1;
+		hwif->set_dma_mode(drive, mode);
+		return 0;
+	} else {
+		hwif->set_dma_mode(drive, mode);
+		return ide_config_drive_speed(drive, mode);
+	}
+}
+
+EXPORT_SYMBOL_GPL(ide_set_dma_mode);
+
 /**
  *	ide_set_xfer_rate	-	set transfer rate
  *	@drive: drive to set
- *	@speed: speed to attempt to set
+ *	@rate: speed to attempt to set
  *	
  *	General helper for setting the speed of an IDE device. This
  *	function knows about user enforced limits from the configuration
- *	which speedproc() does not.  High level drivers should never
- *	invoke speedproc() directly.
+ *	which ->set_pio_mode/->set_dma_mode does not.
  */
- 
+
 int ide_set_xfer_rate(ide_drive_t *drive, u8 rate)
 {
 	ide_hwif_t *hwif = drive->hwif;
 
-	if (hwif->speedproc == NULL)
+	if (hwif->set_dma_mode == NULL)
 		return -1;
 
 	rate = ide_rate_filter(drive, rate);
 
-	if (rate >= XFER_PIO_0 && rate <= XFER_PIO_5) {
-		if (hwif->set_pio_mode)
-			hwif->set_pio_mode(drive, rate - XFER_PIO_0);
+	if (rate >= XFER_PIO_0 && rate <= XFER_PIO_5)
+		return ide_set_pio_mode(drive, rate);
 
-		/*
-		 * FIXME: this is incorrect to return zero here but
-		 * since all users of ide_set_xfer_rate() ignore
-		 * the return value it is not a problem currently
-		 */
-		return 0;
-	}
+	/*
+	 * TODO: transfer modes 0x00-0x07 passed from the user-space are
+	 * currently handled here which needs fixing (please note that such
+	 * case could happen iff the transfer mode has already been set on
+	 * the device by ide-proc.c::set_xfer_rate()).
+	 */
 
-	return hwif->speedproc(drive, rate);
+	return ide_set_dma_mode(drive, rate);
 }
 
 static void ide_dump_opcode(ide_drive_t *drive)
diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c
index a96a8b1..5c0e407 100644
--- a/drivers/ide/ide.c
+++ b/drivers/ide/ide.c
@@ -397,7 +397,7 @@
 #endif
 
 	hwif->set_pio_mode		= tmp_hwif->set_pio_mode;
-	hwif->speedproc			= tmp_hwif->speedproc;
+	hwif->set_dma_mode		= tmp_hwif->set_dma_mode;
 	hwif->mdma_filter		= tmp_hwif->mdma_filter;
 	hwif->udma_filter		= tmp_hwif->udma_filter;
 	hwif->selectproc		= tmp_hwif->selectproc;
diff --git a/drivers/ide/mips/au1xxx-ide.c b/drivers/ide/mips/au1xxx-ide.c
index c319f61..aebde49 100644
--- a/drivers/ide/mips/au1xxx-ide.c
+++ b/drivers/ide/mips/au1xxx-ide.c
@@ -101,14 +101,7 @@
 
 static void au1xxx_set_pio_mode(ide_drive_t *drive, const u8 pio)
 {
-	int mem_sttime;
-	int mem_stcfg;
-
-	if (ide_config_drive_speed(drive, pio + XFER_PIO_0))
-		return;
-
-	mem_sttime = 0;
-	mem_stcfg  = au_readl(MEM_STCFG2);
+	int mem_sttime = 0, mem_stcfg = au_readl(MEM_STCFG2);
 
 	/* set pio mode! */
 	switch(pio) {
@@ -168,13 +161,9 @@
 	au_writel(mem_stcfg,MEM_STCFG2);
 }
 
-static int auide_tune_chipset(ide_drive_t *drive, const u8 speed)
+static void auide_set_dma_mode(ide_drive_t *drive, const u8 speed)
 {
-	int mem_sttime;
-	int mem_stcfg;
-
-	mem_sttime = 0;
-	mem_stcfg  = au_readl(MEM_STCFG2);
+	int mem_sttime = 0, mem_stcfg = au_readl(MEM_STCFG2);
 
 	switch(speed) {
 #ifdef CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA
@@ -210,16 +199,11 @@
 		break;
 #endif
 	default:
-		return 1;
+		return;
 	}
 
-	if (ide_config_drive_speed(drive, speed))
-		return 1;
-
 	au_writel(mem_sttime,MEM_STTIME2);
 	au_writel(mem_stcfg,MEM_STCFG2);
-
-	return 0;
 }
 
 /*
@@ -681,6 +665,7 @@
 #endif
 
 	hwif->pio_mask = ATA_PIO4;
+	hwif->host_flags = IDE_HFLAG_POST_SET_MODE;
 
 	hwif->noprobe = 0;
 	hwif->drives[0].unmask          = 1;
@@ -701,7 +686,7 @@
 #endif
 
 	hwif->set_pio_mode		= &au1xxx_set_pio_mode;
-	hwif->speedproc                 = &auide_tune_chipset;
+	hwif->set_dma_mode		= &auide_set_dma_mode;
 
 #ifdef CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA
 	hwif->dma_off_quietly		= &auide_dma_off_quietly;
diff --git a/drivers/ide/pci/aec62xx.c b/drivers/ide/pci/aec62xx.c
index 0d5f62c..d6cb2d5 100644
--- a/drivers/ide/pci/aec62xx.c
+++ b/drivers/ide/pci/aec62xx.c
@@ -87,7 +87,7 @@
 	return chipset_table->ultra_settings;
 }
 
-static int aec6210_tune_chipset(ide_drive_t *drive, const u8 speed)
+static void aec6210_set_mode(ide_drive_t *drive, const u8 speed)
 {
 	ide_hwif_t *hwif	= HWIF(drive);
 	struct pci_dev *dev	= hwif->pci_dev;
@@ -111,10 +111,9 @@
 	tmp2 = ((ultra_conf << (2*drive->dn)) | (tmp1 & ~(3 << (2*drive->dn))));
 	pci_write_config_byte(dev, 0x54, tmp2);
 	local_irq_restore(flags);
-	return(ide_config_drive_speed(drive, speed));
 }
 
-static int aec6260_tune_chipset(ide_drive_t *drive, const u8 speed)
+static void aec6260_set_mode(ide_drive_t *drive, const u8 speed)
 {
 	ide_hwif_t *hwif	= HWIF(drive);
 	struct pci_dev *dev	= hwif->pci_dev;
@@ -135,12 +134,11 @@
 	tmp2 = ((ultra_conf << (4*unit)) | (tmp1 & ~(7 << (4*unit))));
 	pci_write_config_byte(dev, (0x44|hwif->channel), tmp2);
 	local_irq_restore(flags);
-	return(ide_config_drive_speed(drive, speed));
 }
 
 static void aec_set_pio_mode(ide_drive_t *drive, const u8 pio)
 {
-	(void) HWIF(drive)->speedproc(drive, pio + XFER_PIO_0);
+	drive->hwif->set_dma_mode(drive, pio + XFER_PIO_0);
 }
 
 static int aec62xx_config_drive_xfer_rate (ide_drive_t *drive)
@@ -205,9 +203,9 @@
 	if (dev->device == PCI_DEVICE_ID_ARTOP_ATP850UF) {
 		if(hwif->mate)
 			hwif->mate->serialized = hwif->serialized = 1;
-		hwif->speedproc = &aec6210_tune_chipset;
+		hwif->set_dma_mode = &aec6210_set_mode;
 	} else
-		hwif->speedproc = &aec6260_tune_chipset;
+		hwif->set_dma_mode = &aec6260_set_mode;
 
 	if (!hwif->dma_base) {
 		hwif->drives[0].autotune = hwif->drives[1].autotune = 1;
diff --git a/drivers/ide/pci/alim15x3.c b/drivers/ide/pci/alim15x3.c
index d04b966..88f084e 100644
--- a/drivers/ide/pci/alim15x3.c
+++ b/drivers/ide/pci/alim15x3.c
@@ -283,14 +283,14 @@
 #endif  /* defined(DISPLAY_ALI_TIMINGS) && defined(CONFIG_IDE_PROC_FS) */
 
 /**
- *	ali_tune_pio	-	set host controller for PIO mode
+ *	ali_set_pio_mode	-	set host controller for PIO mode
  *	@drive: drive
  *	@pio: PIO mode number
  *
  *	Program the controller for the given PIO mode.
  */
 
-static void ali_tune_pio(ide_drive_t *drive, const u8 pio)
+static void ali_set_pio_mode(ide_drive_t *drive, const u8 pio)
 {
 	ide_hwif_t *hwif = HWIF(drive);
 	struct pci_dev *dev = hwif->pci_dev;
@@ -358,21 +358,6 @@
 }
 
 /**
- *	ali_set_pio_mode	-	set up drive for PIO mode
- *	@drive: drive to tune
- *	@pio: desired mode
- *
- *	Program the controller with the desired PIO timing for the given drive.
- *	Then set up the drive itself.
- */
-
-static void ali_set_pio_mode(ide_drive_t *drive, const u8 pio)
-{
-	ali_tune_pio(drive, pio);
-	(void) ide_config_drive_speed(drive, XFER_PIO_0 + pio);
-}
-
-/**
  *	ali_udma_filter		-	compute UDMA mask
  *	@drive: IDE device
  *
@@ -401,15 +386,14 @@
 }
 
 /**
- *	ali15x3_tune_chipset	-	set up chipset/drive for new speed
- *	@drive: drive to configure for
- *	@speed: desired speed
+ *	ali_set_dma_mode	-	set host controller for DMA mode
+ *	@drive: drive
+ *	@speed: DMA mode
  *
  *	Configure the hardware for the desired IDE transfer mode.
- *	We also do the needed drive configuration through helpers
  */
 
-static int ali15x3_tune_chipset(ide_drive_t *drive, const u8 speed)
+static void ali_set_dma_mode(ide_drive_t *drive, const u8 speed)
 {
 	ide_hwif_t *hwif	= HWIF(drive);
 	struct pci_dev *dev	= hwif->pci_dev;
@@ -419,7 +403,7 @@
 	int m5229_udma		= (hwif->channel) ? 0x57 : 0x56;
 
 	if (speed < XFER_PIO_0)
-		return 1;
+		return;
 
 	if (speed == XFER_UDMA_6)
 		speed1 = 0x47;
@@ -450,7 +434,6 @@
 			pci_write_config_byte(dev, 0x4b, tmpbyte);
 		}
 	}
-	return (ide_config_drive_speed(drive, speed));
 }
 
 /**
@@ -699,7 +682,7 @@
 {
 	hwif->autodma = 0;
 	hwif->set_pio_mode = &ali_set_pio_mode;
-	hwif->speedproc = &ali15x3_tune_chipset;
+	hwif->set_dma_mode = &ali_set_dma_mode;
 	hwif->udma_filter = &ali_udma_filter;
 
 	/* don't use LBA48 DMA on ALi devices before rev 0xC5 */
diff --git a/drivers/ide/pci/amd74xx.c b/drivers/ide/pci/amd74xx.c
index 71d2c67..6ff4089 100644
--- a/drivers/ide/pci/amd74xx.c
+++ b/drivers/ide/pci/amd74xx.c
@@ -229,20 +229,16 @@
 }
 
 /*
- * amd_set_drive() computes timing values configures the drive and
- * the chipset to a desired transfer mode. It also can be called
- * by upper layers.
+ * amd_set_drive() computes timing values and configures the chipset
+ * to a desired transfer mode.  It also can be called by upper layers.
  */
 
-static int amd_set_drive(ide_drive_t *drive, const u8 speed)
+static void amd_set_drive(ide_drive_t *drive, const u8 speed)
 {
 	ide_drive_t *peer = HWIF(drive)->drives + (~drive->dn & 1);
 	struct ide_timing t, p;
 	int T, UT;
 
-	if (ide_config_drive_speed(drive, speed))
-		return 1;
-
 	T = 1000000000 / amd_clock;
 	UT = (amd_config->udma_mask == ATA_UDMA2) ? T : (T / 2);
 
@@ -257,8 +253,6 @@
 	if (speed == XFER_UDMA_6 && amd_clock <= 33333) t.udma = 15;
 
 	amd_set_speed(HWIF(drive)->pci_dev, drive->dn, &t);
-
-	return 0;
 }
 
 /*
@@ -395,7 +389,7 @@
 	hwif->autodma = 0;
 
 	hwif->set_pio_mode = &amd_set_pio_mode;
-	hwif->speedproc = &amd_set_drive;
+	hwif->set_dma_mode = &amd_set_drive;
 
 	for (i = 0; i < 2; i++) {
 		hwif->drives[i].io_32bit = 1;
@@ -437,7 +431,8 @@
 		.enablebits	= {{0x40,0x02,0x02}, {0x40,0x01,0x01}},	\
 		.bootable	= ON_BOARD,				\
 		.host_flags	= IDE_HFLAG_PIO_NO_BLACKLIST		\
-				| IDE_HFLAG_PIO_NO_DOWNGRADE,		\
+				| IDE_HFLAG_PIO_NO_DOWNGRADE		\
+				| IDE_HFLAG_POST_SET_MODE,		\
 		.pio_mask	= ATA_PIO5,				\
 	}
 
@@ -450,7 +445,8 @@
 		.enablebits	= {{0x50,0x02,0x02}, {0x50,0x01,0x01}},	\
 		.bootable	= ON_BOARD,				\
 		.host_flags	= IDE_HFLAG_PIO_NO_BLACKLIST		\
-				| IDE_HFLAG_PIO_NO_DOWNGRADE,		\
+				| IDE_HFLAG_PIO_NO_DOWNGRADE		\
+				| IDE_HFLAG_POST_SET_MODE,		\
 		.pio_mask	= ATA_PIO5,				\
 	}
 
diff --git a/drivers/ide/pci/atiixp.c b/drivers/ide/pci/atiixp.c
index 178876a..0eb97f0 100644
--- a/drivers/ide/pci/atiixp.c
+++ b/drivers/ide/pci/atiixp.c
@@ -122,14 +122,14 @@
 }
 
 /**
- *	atiixp_tune_pio	-	tune a drive attached to a ATIIXP
- *	@drive: drive to tune
- *	@pio: desired PIO mode
+ *	atiixp_set_pio_mode	-	set host controller for PIO mode
+ *	@drive: drive
+ *	@pio: PIO mode number
  *
  *	Set the interface PIO mode.
  */
 
-static void atiixp_tune_pio(ide_drive_t *drive, u8 pio)
+static void atiixp_set_pio_mode(ide_drive_t *drive, const u8 pio)
 {
 	struct pci_dev *dev = drive->hwif->pci_dev;
 	unsigned long flags;
@@ -153,23 +153,16 @@
 	spin_unlock_irqrestore(&atiixp_lock, flags);
 }
 
-static void atiixp_set_pio_mode(ide_drive_t *drive, const u8 pio)
-{
-	atiixp_tune_pio(drive, pio);
-	(void)ide_config_drive_speed(drive, XFER_PIO_0 + pio);
-}
-
 /**
- *	atiixp_tune_chipset	-	tune a ATIIXP interface
- *	@drive: IDE drive to tune
- *	@speed: speed to configure
+ *	atiixp_set_dma_mode	-	set host controller for DMA mode
+ *	@drive: drive
+ *	@speed: DMA mode
  *
- *	Set a ATIIXP interface channel to the desired speeds. This involves
- *	requires the right timing data into the ATIIXP configuration space
- *	then setting the drive parameters appropriately
+ *	Set a ATIIXP host controller to the desired DMA mode.  This involves
+ *	programming the right timing data into the PCI configuration space.
  */
 
-static int atiixp_speedproc(ide_drive_t *drive, const u8 speed)
+static void atiixp_set_dma_mode(ide_drive_t *drive, const u8 speed)
 {
 	struct pci_dev *dev = drive->hwif->pci_dev;
 	unsigned long flags;
@@ -204,9 +197,7 @@
 	else
 		pio = speed - XFER_PIO_0;
 
-	atiixp_tune_pio(drive, pio);
-
-	return ide_config_drive_speed(drive, speed);
+	atiixp_set_pio_mode(drive, pio);
 }
 
 /**
@@ -249,7 +240,7 @@
 
 	hwif->autodma = 0;
 	hwif->set_pio_mode = &atiixp_set_pio_mode;
-	hwif->speedproc = &atiixp_speedproc;
+	hwif->set_dma_mode = &atiixp_set_dma_mode;
 	hwif->drives[0].autotune = 1;
 	hwif->drives[1].autotune = 1;
 
diff --git a/drivers/ide/pci/cmd64x.c b/drivers/ide/pci/cmd64x.c
index 0b568c6..d50f15e 100644
--- a/drivers/ide/pci/cmd64x.c
+++ b/drivers/ide/pci/cmd64x.c
@@ -280,10 +280,9 @@
 		return;
 
 	cmd64x_tune_pio(drive, pio);
-	(void) ide_config_drive_speed(drive, XFER_PIO_0 + pio);
 }
 
-static int cmd64x_tune_chipset(ide_drive_t *drive, const u8 speed)
+static void cmd64x_set_dma_mode(ide_drive_t *drive, const u8 speed)
 {
 	ide_hwif_t *hwif	= HWIF(drive);
 	struct pci_dev *dev	= hwif->pci_dev;
@@ -324,13 +323,11 @@
 		program_cycle_times(drive, 480, 215);
 		break;
 	default:
-		return 1;
+		return;
 	}
 
 	if (speed >= XFER_SW_DMA_0)
 		(void) pci_write_config_byte(dev, pciU, regU);
-
-	return ide_config_drive_speed(drive, speed);
 }
 
 static int cmd64x_config_drive_for_dma (ide_drive_t *drive)
@@ -524,7 +521,7 @@
 	pci_read_config_byte(dev, PCI_REVISION_ID, &rev);
 
 	hwif->set_pio_mode = &cmd64x_set_pio_mode;
-	hwif->speedproc = &cmd64x_tune_chipset;
+	hwif->set_dma_mode = &cmd64x_set_dma_mode;
 
 	hwif->drives[0].autotune = hwif->drives[1].autotune = 1;
 
diff --git a/drivers/ide/pci/cs5520.c b/drivers/ide/pci/cs5520.c
index 1217d2a..cb2a102 100644
--- a/drivers/ide/pci/cs5520.c
+++ b/drivers/ide/pci/cs5520.c
@@ -96,22 +96,13 @@
 	reg = inb(hwif->dma_base + 0x02 + 8*controller);
 	reg |= 1<<((drive->dn&1)+5);
 	outb(reg, hwif->dma_base + 0x02 + 8*controller);
-
-	(void)ide_config_drive_speed(drive, XFER_PIO_0 + pio);
 }
 
-static int cs5520_tune_chipset(ide_drive_t *drive, const u8 speed)
+static void cs5520_set_dma_mode(ide_drive_t *drive, const u8 speed)
 {
 	printk(KERN_ERR "cs55x0: bad ide timing.\n");
 
 	cs5520_set_pio_mode(drive, 0);
-
-	/*
-	 * FIXME: this is incorrect to return zero here but
-	 * since all users of ide_set_xfer_rate() ignore
-	 * the return value it is not a problem currently
-	 */
-	return 0;
 }
 
 static int cs5520_config_drive_xfer_rate(ide_drive_t *drive)
@@ -150,7 +141,7 @@
 static void __devinit init_hwif_cs5520(ide_hwif_t *hwif)
 {
 	hwif->set_pio_mode = &cs5520_set_pio_mode;
-	hwif->speedproc = &cs5520_tune_chipset;
+	hwif->set_dma_mode = &cs5520_set_dma_mode;
 	hwif->ide_dma_check = &cs5520_config_drive_xfer_rate;
 	hwif->ide_dma_on = &cs5520_dma_on;
 
diff --git a/drivers/ide/pci/cs5530.c b/drivers/ide/pci/cs5530.c
index 741507b..e412157 100644
--- a/drivers/ide/pci/cs5530.c
+++ b/drivers/ide/pci/cs5530.c
@@ -30,22 +30,6 @@
 #include <asm/io.h>
 #include <asm/irq.h>
 
-/**
- *	cs5530_xfer_set_mode	-	set a new transfer mode at the drive
- *	@drive: drive to tune
- *	@mode: new mode
- *
- *	Logging wrapper to the IDE driver speed configuration. This can
- *	probably go away now.
- */
- 
-static int cs5530_set_xfer_mode (ide_drive_t *drive, u8 mode)
-{
-	printk(KERN_DEBUG "%s: cs5530_set_xfer_mode(%s)\n",
-		drive->name, ide_xfer_verbose(mode));
-	return (ide_config_drive_speed(drive, mode));
-}
-
 /*
  * Here are the standard PIO mode 0-4 timings for each "format".
  * Format-0 uses fast data reg timings, with slower command reg timings.
@@ -62,20 +46,12 @@
 #define CS5530_BAD_PIO(timings) (((timings)&~0x80000000)==0x0000e132)
 #define CS5530_BASEREG(hwif)	(((hwif)->dma_base & ~0xf) + ((hwif)->channel ? 0x30 : 0x20))
 
-static void cs5530_tunepio(ide_drive_t *drive, u8 pio)
-{
-	unsigned long basereg = CS5530_BASEREG(drive->hwif);
-	unsigned int format = (inl(basereg + 4) >> 31) & 1;
-
-	outl(cs5530_pio_timings[format][pio], basereg + ((drive->dn & 1)<<3));
-}
-
 /**
- *	cs5530_set_pio_mode	-	set PIO mode
+ *	cs5530_set_pio_mode	-	set host controller for PIO mode
  *	@drive: drive
  *	@pio: PIO mode number
  *
- *	Handles setting of PIO mode for both the chipset and drive.
+ *	Handles setting of PIO mode for the chipset.
  *
  *	The init_hwif_cs5530() routine guarantees that all drives
  *	will have valid default PIO timings set up before we get here.
@@ -83,8 +59,10 @@
 
 static void cs5530_set_pio_mode(ide_drive_t *drive, const u8 pio)
 {
-	if (cs5530_set_xfer_mode(drive, XFER_PIO_0 + pio) == 0)
-		cs5530_tunepio(drive, pio);
+	unsigned long basereg = CS5530_BASEREG(drive->hwif);
+	unsigned int format = (inl(basereg + 4) >> 31) & 1;
+
+	outl(cs5530_pio_timings[format][pio], basereg + ((drive->dn & 1)<<3));
 }
 
 /**
@@ -142,20 +120,11 @@
 	return 1;
 }
 
-static int cs5530_tune_chipset(ide_drive_t *drive, const u8 mode)
+static void cs5530_set_dma_mode(ide_drive_t *drive, const u8 mode)
 {
 	unsigned long basereg;
 	unsigned int reg, timings = 0;
 
-	/*
-	 * Tell the drive to switch to the new mode; abort on failure.
-	 */
-	if (cs5530_set_xfer_mode(drive, mode))
-		return 1;	/* failure */
-
-	/*
-	 * Now tune the chipset to match the drive:
-	 */
 	switch (mode) {
 		case XFER_UDMA_0:	timings = 0x00921250; break;
 		case XFER_UDMA_1:	timings = 0x00911140; break;
@@ -180,8 +149,6 @@
 		outl(reg, basereg + 4);		/* write drive0 config register */
 		outl(timings, basereg + 12);	/* write drive1 config register */
 	}
-
-	return 0;	/* success */
 }
 
 /**
@@ -299,7 +266,7 @@
 		hwif->serialized = hwif->mate->serialized = 1;
 
 	hwif->set_pio_mode = &cs5530_set_pio_mode;
-	hwif->speedproc = &cs5530_tune_chipset;
+	hwif->set_dma_mode = &cs5530_set_dma_mode;
 
 	basereg = CS5530_BASEREG(hwif);
 	d0_timings = inl(basereg + 0);
@@ -340,6 +307,7 @@
 	.autodma	= AUTODMA,
 	.bootable	= ON_BOARD,
 	.pio_mask	= ATA_PIO4,
+	.host_flags	= IDE_HFLAG_POST_SET_MODE,
 };
 
 static int __devinit cs5530_init_one(struct pci_dev *dev, const struct pci_device_id *id)
diff --git a/drivers/ide/pci/cs5535.c b/drivers/ide/pci/cs5535.c
index 5d1be65..da606ba 100644
--- a/drivers/ide/pci/cs5535.c
+++ b/drivers/ide/pci/cs5535.c
@@ -131,26 +131,21 @@
 	}
 }
 
-/****
- *	cs5535_set_drive         -     Configure the drive to the new speed
- *	@drive: Drive to set up
- *	@speed: desired speed
+/**
+ *	cs5535_set_dma_mode	-	set host controller for DMA mode
+ *	@drive: drive
+ *	@speed: DMA mode
  *
- *	cs5535_set_drive() configures the drive and the chipset to a
- *	new speed. It also can be called by upper layers.
+ *	Programs the chipset for DMA mode.
  */
-static int cs5535_set_drive(ide_drive_t *drive, u8 speed)
+
+static void cs5535_set_dma_mode(ide_drive_t *drive, const u8 speed)
 {
-	if (ide_config_drive_speed(drive, speed))
-		return 1;
-
 	cs5535_set_speed(drive, speed);
-
-	return 0;
 }
 
 /**
- *	cs5535_set_pio_mode	-	PIO setup
+ *	cs5535_set_pio_mode	-	set host controller for PIO mode
  *	@drive: drive
  *	@pio: PIO mode number
  *
@@ -159,9 +154,6 @@
 
 static void cs5535_set_pio_mode(ide_drive_t *drive, const u8 pio)
 {
-	if (ide_config_drive_speed(drive, XFER_PIO_0 + pio))
-		return;
-
 	cs5535_set_speed(drive, XFER_PIO_0 + pio);
 }
 
@@ -203,7 +195,7 @@
 	hwif->autodma = 0;
 
 	hwif->set_pio_mode = &cs5535_set_pio_mode;
-	hwif->speedproc = &cs5535_set_drive;
+	hwif->set_dma_mode = &cs5535_set_dma_mode;
 	hwif->ide_dma_check = &cs5535_dma_check;
 
 	hwif->atapi_dma = 1;
@@ -227,7 +219,7 @@
 	.init_hwif	= init_hwif_cs5535,
 	.autodma	= AUTODMA,
 	.bootable	= ON_BOARD,
-	.host_flags	= IDE_HFLAG_SINGLE,
+	.host_flags	= IDE_HFLAG_SINGLE | IDE_HFLAG_POST_SET_MODE,
 	.pio_mask	= ATA_PIO4,
 };
 
diff --git a/drivers/ide/pci/hpt34x.c b/drivers/ide/pci/hpt34x.c
index a1bb101..218852a 100644
--- a/drivers/ide/pci/hpt34x.c
+++ b/drivers/ide/pci/hpt34x.c
@@ -43,7 +43,7 @@
 
 #define HPT343_DEBUG_DRIVE_INFO		0
 
-static int hpt34x_tune_chipset(ide_drive_t *drive, const u8 speed)
+static void hpt34x_set_mode(ide_drive_t *drive, const u8 speed)
 {
 	struct pci_dev *dev	= HWIF(drive)->pci_dev;
 	u32 reg1= 0, tmp1 = 0, reg2 = 0, tmp2 = 0;
@@ -73,13 +73,11 @@
 		drive->dn, reg1, tmp1, reg2, tmp2,
 		hi_speed, lo_speed);
 #endif /* HPT343_DEBUG_DRIVE_INFO */
-
-	return(ide_config_drive_speed(drive, speed));
 }
 
 static void hpt34x_set_pio_mode(ide_drive_t *drive, const u8 pio)
 {
-	(void) hpt34x_tune_chipset(drive, (XFER_PIO_0 + pio));
+	hpt34x_set_mode(drive, XFER_PIO_0 + pio);
 }
 
 static int hpt34x_config_drive_xfer_rate (ide_drive_t *drive)
@@ -145,7 +143,8 @@
 	hwif->autodma = 0;
 
 	hwif->set_pio_mode = &hpt34x_set_pio_mode;
-	hwif->speedproc = &hpt34x_tune_chipset;
+	hwif->set_dma_mode = &hpt34x_set_mode;
+
 	hwif->drives[0].autotune = 1;
 	hwif->drives[1].autotune = 1;
 
diff --git a/drivers/ide/pci/hpt366.c b/drivers/ide/pci/hpt366.c
index 0e7d3b6..8812a9b 100644
--- a/drivers/ide/pci/hpt366.c
+++ b/drivers/ide/pci/hpt366.c
@@ -600,7 +600,7 @@
 	return (*info->settings)[i];
 }
 
-static int hpt36x_tune_chipset(ide_drive_t *drive, const u8 speed)
+static void hpt36x_set_mode(ide_drive_t *drive, const u8 speed)
 {
 	ide_hwif_t *hwif	= HWIF(drive);
 	struct pci_dev  *dev	= hwif->pci_dev;
@@ -623,11 +623,9 @@
 	new_itr &= ~0xc0000000;
 
 	pci_write_config_dword(dev, itr_addr, new_itr);
-
-	return ide_config_drive_speed(drive, speed);
 }
 
-static int hpt37x_tune_chipset(ide_drive_t *drive, const u8 speed)
+static void hpt37x_set_mode(ide_drive_t *drive, const u8 speed)
 {
 	ide_hwif_t *hwif	= HWIF(drive);
 	struct pci_dev  *dev	= hwif->pci_dev;
@@ -647,24 +645,22 @@
 	if (speed < XFER_MW_DMA_0)
 		new_itr &= ~0x80000000; /* Disable on-chip PIO FIFO/buffer */
 	pci_write_config_dword(dev, itr_addr, new_itr);
-
-	return ide_config_drive_speed(drive, speed);
 }
 
-static int hpt3xx_tune_chipset(ide_drive_t *drive, u8 speed)
+static void hpt3xx_set_mode(ide_drive_t *drive, const u8 speed)
 {
 	ide_hwif_t *hwif	= HWIF(drive);
 	struct hpt_info	*info	= pci_get_drvdata(hwif->pci_dev);
 
 	if (info->chip_type >= HPT370)
-		return hpt37x_tune_chipset(drive, speed);
+		hpt37x_set_mode(drive, speed);
 	else	/* hpt368: hpt_minimum_revision(dev, 2) */
-		return hpt36x_tune_chipset(drive, speed);
+		hpt36x_set_mode(drive, speed);
 }
 
 static void hpt3xx_set_pio_mode(ide_drive_t *drive, const u8 pio)
 {
-	(void) hpt3xx_tune_chipset (drive, XFER_PIO_0 + pio);
+	hpt3xx_set_mode(drive, XFER_PIO_0 + pio);
 }
 
 static int hpt3xx_quirkproc(ide_drive_t *drive)
@@ -1257,7 +1253,7 @@
 	hwif->select_data	= hwif->channel ? 0x54 : 0x50;
 
 	hwif->set_pio_mode	= &hpt3xx_set_pio_mode;
-	hwif->speedproc		= &hpt3xx_tune_chipset;
+	hwif->set_dma_mode	= &hpt3xx_set_mode;
 	hwif->quirkproc		= &hpt3xx_quirkproc;
 	hwif->intrproc		= &hpt3xx_intrproc;
 	hwif->maskproc		= &hpt3xx_maskproc;
diff --git a/drivers/ide/pci/it8213.c b/drivers/ide/pci/it8213.c
index 76e91ff..ecf4ce0 100644
--- a/drivers/ide/pci/it8213.c
+++ b/drivers/ide/pci/it8213.c
@@ -48,15 +48,15 @@
 	}
 }
 
-/*
- *	it8213_tune_pio	-	tune a drive
- *	@drive: drive to tune
- *	@pio: desired PIO mode
+/**
+ *	it8213_set_pio_mode	-	set host controller for PIO mode
+ *	@drive: drive
+ *	@pio: PIO mode number
  *
  *	Set the interface PIO mode.
  */
 
-static void it8213_tune_pio(ide_drive_t *drive, const u8 pio)
+static void it8213_set_pio_mode(ide_drive_t *drive, const u8 pio)
 {
 	ide_hwif_t *hwif	= HWIF(drive);
 	struct pci_dev *dev	= hwif->pci_dev;
@@ -105,21 +105,15 @@
 	spin_unlock_irqrestore(&tune_lock, flags);
 }
 
-static void it8213_set_pio_mode(ide_drive_t *drive, const u8 pio)
-{
-	it8213_tune_pio(drive, pio);
-	ide_config_drive_speed(drive, XFER_PIO_0 + pio);
-}
-
 /**
- *	it8213_tune_chipset	-	set controller timings
- *	@drive: Drive to set up
- *	@speed: speed we want to achieve
+ *	it8213_set_dma_mode	-	set host controller for DMA mode
+ *	@drive: drive
+ *	@speed: DMA mode
  *
- *	Tune the ITE chipset for the desired mode.
+ *	Tune the ITE chipset for the DMA mode.
  */
 
-static int it8213_tune_chipset(ide_drive_t *drive, const u8 speed)
+static void it8213_set_dma_mode(ide_drive_t *drive, const u8 speed)
 {
 	ide_hwif_t *hwif	= HWIF(drive);
 	struct pci_dev *dev	= hwif->pci_dev;
@@ -152,7 +146,7 @@
 		case XFER_SW_DMA_2:
 			break;
 		default:
-			return -1;
+			return;
 	}
 
 	if (speed >= XFER_UDMA_0) {
@@ -182,9 +176,7 @@
 			pci_write_config_byte(dev, 0x55, (u8) reg55 & ~w_flag);
 	}
 
-	it8213_tune_pio(drive, it8213_dma_2_pio(speed));
-
-	return ide_config_drive_speed(drive, speed);
+	it8213_set_pio_mode(drive, it8213_dma_2_pio(speed));
 }
 
 /**
@@ -220,7 +212,7 @@
 {
 	u8 reg42h = 0;
 
-	hwif->speedproc = &it8213_tune_chipset;
+	hwif->set_dma_mode = &it8213_set_dma_mode;
 	hwif->set_pio_mode = &it8213_set_pio_mode;
 
 	hwif->autodma = 0;
diff --git a/drivers/ide/pci/it821x.c b/drivers/ide/pci/it821x.c
index 758a982..1b69d82 100644
--- a/drivers/ide/pci/it821x.c
+++ b/drivers/ide/pci/it821x.c
@@ -229,24 +229,24 @@
 }
 
 /**
- *	it821x_tunepio	-	tune a drive
- *	@drive: drive to tune
- *	@pio: the desired PIO mode
+ *	it821x_set_pio_mode	-	set host controller for PIO mode
+ *	@drive: drive
+ *	@pio: PIO mode number
  *
- *	Try to tune the drive/host to the desired PIO mode taking into
- *	the consideration the maximum PIO mode supported by the other
- *	device on the cable.
+ *	Tune the host to the desired PIO mode taking into the consideration
+ *	the maximum PIO mode supported by the other device on the cable.
  */
 
-static int it821x_tunepio(ide_drive_t *drive, u8 set_pio)
+static void it821x_set_pio_mode(ide_drive_t *drive, const u8 pio)
 {
 	ide_hwif_t *hwif	= drive->hwif;
 	struct it821x_dev *itdev = ide_get_hwifdata(hwif);
 	int unit = drive->select.b.unit;
 	ide_drive_t *pair = &hwif->drives[1 - unit];
+	u8 set_pio = pio;
 
 	/* Spec says 89 ref driver uses 88 */
-	static u16 pio[]	= { 0xAA88, 0xA382, 0xA181, 0x3332, 0x3121 };
+	static u16 pio_timings[]= { 0xAA88, 0xA382, 0xA181, 0x3332, 0x3121 };
 	static u8 pio_want[]    = { ATA_66, ATA_66, ATA_66, ATA_66, ATA_ANY };
 
 	/*
@@ -261,22 +261,12 @@
 			set_pio = pair_pio;
 	}
 
-	if (itdev->smart)
-		return 0;
-
 	/* We prefer 66Mhz clock for PIO 0-3, don't care for PIO4 */
 	itdev->want[unit][1] = pio_want[set_pio];
 	itdev->want[unit][0] = 1;	/* PIO is lowest priority */
-	itdev->pio[unit] = pio[set_pio];
+	itdev->pio[unit] = pio_timings[set_pio];
 	it821x_clock_strategy(drive);
 	it821x_program(drive, itdev->pio[unit]);
-
-	return ide_config_drive_speed(drive, XFER_PIO_0 + set_pio);
-}
-
-static void it821x_set_pio_mode(ide_drive_t *drive, const u8 pio)
-{
-	(void)it821x_tunepio(drive, pio);
 }
 
 /**
@@ -405,47 +395,24 @@
 }
 
 /**
- *	it821x_tune_chipset	-	set controller timings
- *	@drive: Drive to set up
- *	@speed: speed we want to achieve
+ *	it821x_set_dma_mode	-	set host controller for DMA mode
+ *	@drive: drive
+ *	@speed: DMA mode
  *
- *	Tune the ITE chipset for the desired mode.
+ *	Tune the ITE chipset for the desired DMA mode.
  */
 
-static int it821x_tune_chipset(ide_drive_t *drive, const u8 speed)
+static void it821x_set_dma_mode(ide_drive_t *drive, const u8 speed)
 {
-
-	ide_hwif_t *hwif	= drive->hwif;
-	struct it821x_dev *itdev = ide_get_hwifdata(hwif);
-
-	if (itdev->smart == 0) {
-		switch (speed) {
-			/* MWDMA tuning is really hard because our MWDMA and PIO
-			   timings are kept in the same place. We can switch in the
-			   host dma on/off callbacks */
-			case XFER_MW_DMA_2:
-			case XFER_MW_DMA_1:
-			case XFER_MW_DMA_0:
-				it821x_tune_mwdma(drive, (speed - XFER_MW_DMA_0));
-				break;
-			case XFER_UDMA_6:
-			case XFER_UDMA_5:
-			case XFER_UDMA_4:
-			case XFER_UDMA_3:
-			case XFER_UDMA_2:
-			case XFER_UDMA_1:
-			case XFER_UDMA_0:
-				it821x_tune_udma(drive, (speed - XFER_UDMA_0));
-				break;
-			default:
-				return 1;
-		}
-
-		return ide_config_drive_speed(drive, speed);
-	}
-
-	/* don't touch anything in the smart mode */
-	return 0;
+	/*
+	 * MWDMA tuning is really hard because our MWDMA and PIO
+	 * timings are kept in the same place.  We can switch in the
+	 * host dma on/off callbacks.
+	 */
+	if (speed >= XFER_UDMA_0 && speed <= XFER_UDMA_6)
+		it821x_tune_udma(drive, speed - XFER_UDMA_0);
+	else if (speed >= XFER_MW_DMA_0 && speed <= XFER_MW_DMA_2)
+		it821x_tune_mwdma(drive, speed - XFER_MW_DMA_0);
 }
 
 /**
@@ -629,14 +596,15 @@
 			printk(KERN_WARNING "it821x: Revision 0x10, workarounds activated.\n");
 	}
 
-	hwif->speedproc = &it821x_tune_chipset;
-	hwif->set_pio_mode = &it821x_set_pio_mode;
+	if (idev->smart == 0) {
+		hwif->set_pio_mode = &it821x_set_pio_mode;
+		hwif->set_dma_mode = &it821x_set_dma_mode;
 
-	/* MWDMA/PIO clock switching for pass through mode */
-	if(!idev->smart) {
+		/* MWDMA/PIO clock switching for pass through mode */
 		hwif->dma_start = &it821x_dma_start;
 		hwif->ide_dma_end = &it821x_dma_end;
-	}
+	} else
+		hwif->host_flags |= IDE_HFLAG_NO_SET_MODE;
 
 	hwif->drives[0].autotune = 1;
 	hwif->drives[1].autotune = 1;
diff --git a/drivers/ide/pci/jmicron.c b/drivers/ide/pci/jmicron.c
index d379fba..582b4ca 100644
--- a/drivers/ide/pci/jmicron.c
+++ b/drivers/ide/pci/jmicron.c
@@ -85,21 +85,18 @@
 
 static void jmicron_set_pio_mode(ide_drive_t *drive, const u8 pio)
 {
-	ide_config_drive_speed(drive, XFER_PIO_0 + pio);
 }
 
 /**
- *	jmicron_tune_chipset	-	set controller timings
- *	@drive: Drive to set up
- *	@speed: speed we want to achieve
+ *	jmicron_set_dma_mode	-	set host controller for DMA mode
+ *	@drive: drive
+ *	@mode: DMA mode
  *
- *	As the JMicron snoops for timings all we actually need to do is
- *	set the transfer mode on the device.
+ *	As the JMicron snoops for timings we don't need to do anything here.
  */
 
-static int jmicron_tune_chipset(ide_drive_t *drive, const u8 speed)
+static void jmicron_set_dma_mode(ide_drive_t *drive, const u8 mode)
 {
-	return ide_config_drive_speed(drive, speed);
 }
 
 /**
@@ -129,8 +126,8 @@
 
 static void __devinit init_hwif_jmicron(ide_hwif_t *hwif)
 {
-	hwif->speedproc = &jmicron_tune_chipset;
 	hwif->set_pio_mode = &jmicron_set_pio_mode;
+	hwif->set_dma_mode = &jmicron_set_dma_mode;
 
 	hwif->drives[0].autotune = 1;
 	hwif->drives[1].autotune = 1;
diff --git a/drivers/ide/pci/pdc202xx_new.c b/drivers/ide/pci/pdc202xx_new.c
index 9560068..ad0bdcb 100644
--- a/drivers/ide/pci/pdc202xx_new.c
+++ b/drivers/ide/pci/pdc202xx_new.c
@@ -146,19 +146,16 @@
 	{ 0x1a, 0x01, 0xcb },	/* UDMA mode 6 */
 };
 
-static int pdcnew_tune_chipset(ide_drive_t *drive, const u8 speed)
+static void pdcnew_set_mode(ide_drive_t *drive, const u8 speed)
 {
 	ide_hwif_t *hwif	= HWIF(drive);
 	u8 adj			= (drive->dn & 1) ? 0x08 : 0x00;
 
 	/*
-	 * Issue SETFEATURES_XFER to the drive first. PDC202xx hardware will
+	 * IDE core issues SETFEATURES_XFER to the drive first (thanks to
+	 * IDE_HFLAG_POST_SET_MODE in ->host_flags).  PDC202xx hardware will
 	 * automatically set the timing registers based on 100 MHz PLL output.
-	 */
-	if (ide_config_drive_speed(drive, speed))
-		return 1;
-
-	/*
+	 *
 	 * As we set up the PLL to output 133 MHz for UltraDMA/133 capable
 	 * chips, we must override the default register settings...
 	 */
@@ -211,13 +208,11 @@
 
 		set_indexed_reg(hwif, 0x10 + adj, tmp & 0x7f);
  	}
-
-	return 0;
 }
 
 static void pdcnew_set_pio_mode(ide_drive_t *drive, const u8 pio)
 {
-	(void)pdcnew_tune_chipset(drive, XFER_PIO_0 + pio);
+	pdcnew_set_mode(drive, XFER_PIO_0 + pio);
 }
 
 static u8 pdcnew_cable_detect(ide_hwif_t *hwif)
@@ -490,9 +485,9 @@
 	hwif->autodma = 0;
 
 	hwif->set_pio_mode = &pdcnew_set_pio_mode;
+	hwif->set_dma_mode = &pdcnew_set_mode;
 
 	hwif->quirkproc = &pdcnew_quirkproc;
-	hwif->speedproc = &pdcnew_tune_chipset;
 	hwif->resetproc = &pdcnew_reset;
 
 	hwif->err_stops_fifo = 1;
@@ -583,6 +578,7 @@
 		.bootable	= OFF_BOARD,
 		.pio_mask	= ATA_PIO4,
 		.udma_mask	= 0x3f, /* udma0-5 */
+		.host_flags	= IDE_HFLAG_POST_SET_MODE,
 	},{	/* 1 */
 		.name		= "PDC20269",
 		.init_setup	= init_setup_pdcnew,
@@ -592,6 +588,7 @@
 		.bootable	= OFF_BOARD,
 		.pio_mask	= ATA_PIO4,
 		.udma_mask	= 0x7f, /* udma0-6*/
+		.host_flags	= IDE_HFLAG_POST_SET_MODE,
 	},{	/* 2 */
 		.name		= "PDC20270",
 		.init_setup	= init_setup_pdc20270,
@@ -601,6 +598,7 @@
 		.bootable	= OFF_BOARD,
 		.pio_mask	= ATA_PIO4,
 		.udma_mask	= 0x3f, /* udma0-5 */
+		.host_flags	= IDE_HFLAG_POST_SET_MODE,
 	},{	/* 3 */
 		.name		= "PDC20271",
 		.init_setup	= init_setup_pdcnew,
@@ -610,6 +608,7 @@
 		.bootable	= OFF_BOARD,
 		.pio_mask	= ATA_PIO4,
 		.udma_mask	= 0x7f, /* udma0-6*/
+		.host_flags	= IDE_HFLAG_POST_SET_MODE,
 	},{	/* 4 */
 		.name		= "PDC20275",
 		.init_setup	= init_setup_pdcnew,
@@ -619,6 +618,7 @@
 		.bootable	= OFF_BOARD,
 		.pio_mask	= ATA_PIO4,
 		.udma_mask	= 0x7f, /* udma0-6*/
+		.host_flags	= IDE_HFLAG_POST_SET_MODE,
 	},{	/* 5 */
 		.name		= "PDC20276",
 		.init_setup	= init_setup_pdc20276,
@@ -628,6 +628,7 @@
 		.bootable	= OFF_BOARD,
 		.pio_mask	= ATA_PIO4,
 		.udma_mask	= 0x7f, /* udma0-6*/
+		.host_flags	= IDE_HFLAG_POST_SET_MODE,
 	},{	/* 6 */
 		.name		= "PDC20277",
 		.init_setup	= init_setup_pdcnew,
@@ -637,6 +638,7 @@
 		.bootable	= OFF_BOARD,
 		.pio_mask	= ATA_PIO4,
 		.udma_mask	= 0x7f, /* udma0-6*/
+		.host_flags	= IDE_HFLAG_POST_SET_MODE,
 	}
 };
 
diff --git a/drivers/ide/pci/pdc202xx_old.c b/drivers/ide/pci/pdc202xx_old.c
index b578307..8c3e8cf 100644
--- a/drivers/ide/pci/pdc202xx_old.c
+++ b/drivers/ide/pci/pdc202xx_old.c
@@ -63,7 +63,7 @@
 
 static void pdc_old_disable_66MHz_clock(ide_hwif_t *);
 
-static int pdc202xx_tune_chipset(ide_drive_t *drive, const u8 speed)
+static void pdc202xx_set_mode(ide_drive_t *drive, const u8 speed)
 {
 	ide_hwif_t *hwif	= HWIF(drive);
 	struct pci_dev *dev	= hwif->pci_dev;
@@ -138,13 +138,11 @@
 	pci_read_config_dword(dev, drive_pci, &drive_conf);
 	printk("0x%08x\n", drive_conf);
 #endif
-
-	return ide_config_drive_speed(drive, speed);
 }
 
 static void pdc202xx_set_pio_mode(ide_drive_t *drive, const u8 pio)
 {
-	pdc202xx_tune_chipset(drive, XFER_PIO_0 + pio);
+	pdc202xx_set_mode(drive, XFER_PIO_0 + pio);
 }
 
 static u8 pdc202xx_old_cable_detect (ide_hwif_t *hwif)
@@ -330,14 +328,13 @@
 	hwif->autodma = 0;
 
 	hwif->set_pio_mode = &pdc202xx_set_pio_mode;
+	hwif->set_dma_mode = &pdc202xx_set_mode;
 
 	hwif->quirkproc = &pdc202xx_quirkproc;
 
 	if (hwif->pci_dev->device != PCI_DEVICE_ID_PROMISE_20246)
 		hwif->resetproc = &pdc202xx_reset;
 
-	hwif->speedproc = &pdc202xx_tune_chipset;
-
 	hwif->err_stops_fifo = 1;
 
 	hwif->drives[0].autotune = hwif->drives[1].autotune = 1;
diff --git a/drivers/ide/pci/piix.c b/drivers/ide/pci/piix.c
index fd8214a..38c91ba6 100644
--- a/drivers/ide/pci/piix.c
+++ b/drivers/ide/pci/piix.c
@@ -137,13 +137,14 @@
 }
 
 /**
- *	piix_tune_pio		-	tune PIIX for PIO mode
- *	@drive: drive to tune
- *	@pio: desired PIO mode
+ *	piix_set_pio_mode	-	set host controller for PIO mode
+ *	@drive: drive
+ *	@pio: PIO mode number
  *
  *	Set the interface PIO mode based upon the settings done by AMI BIOS.
  */
-static void piix_tune_pio (ide_drive_t *drive, u8 pio)
+
+static void piix_set_pio_mode(ide_drive_t *drive, const u8 pio)
 {
 	ide_hwif_t *hwif	= HWIF(drive);
 	struct pci_dev *dev	= hwif->pci_dev;
@@ -204,31 +205,15 @@
 }
 
 /**
- *	piix_set_pio_mode	-	set PIO mode
- *	@drive: drive to tune
- *	@pio: desired PIO mode
+ *	piix_set_dma_mode	-	set host controller for DMA mode
+ *	@drive: drive
+ *	@speed: DMA mode
  *
- *	Set the drive's PIO mode (might be useful if drive is not registered
- *	in CMOS for any reason).
+ *	Set a PIIX host controller to the desired DMA mode.  This involves
+ *	programming the right timing data into the PCI configuration space.
  */
 
-static void piix_set_pio_mode(ide_drive_t *drive, const u8 pio)
-{
-	piix_tune_pio(drive, pio);
-	(void) ide_config_drive_speed(drive, XFER_PIO_0 + pio);
-}
-
-/**
- *	piix_tune_chipset	-	tune a PIIX interface
- *	@drive: IDE drive to tune
- *	@speed: speed to configure
- *
- *	Set a PIIX interface channel to the desired speeds. This involves
- *	requires the right timing data into the PIIX configuration space
- *	then setting the drive parameters appropriately
- */
-
-static int piix_tune_chipset(ide_drive_t *drive, const u8 speed)
+static void piix_set_dma_mode(ide_drive_t *drive, const u8 speed)
 {
 	ide_hwif_t *hwif	= HWIF(drive);
 	struct pci_dev *dev	= hwif->pci_dev;
@@ -259,7 +244,7 @@
 		case XFER_MW_DMA_2:
 		case XFER_MW_DMA_1:
 		case XFER_SW_DMA_2:	break;
-		default:		return -1;
+		default:		return;
 	}
 
 	if (speed >= XFER_UDMA_0) {
@@ -288,9 +273,7 @@
 			pci_write_config_byte(dev, 0x55, (u8) reg55 & ~w_flag);
 	}
 
-	piix_tune_pio(drive, piix_dma_2_pio(speed));
-
-	return ide_config_drive_speed(drive, speed);
+	piix_set_pio_mode(drive, piix_dma_2_pio(speed));
 }
 
 /**
@@ -448,7 +431,8 @@
 	hwif->autodma = 0;
 
 	hwif->set_pio_mode = &piix_set_pio_mode;
-	hwif->speedproc = &piix_tune_chipset;
+	hwif->set_dma_mode = &piix_set_dma_mode;
+
 	hwif->drives[0].autotune = 1;
 	hwif->drives[1].autotune = 1;
 
diff --git a/drivers/ide/pci/sc1200.c b/drivers/ide/pci/sc1200.c
index 79ecab6..76f0868 100644
--- a/drivers/ide/pci/sc1200.c
+++ b/drivers/ide/pci/sc1200.c
@@ -68,17 +68,6 @@
 	return pci_clock;
 }
 
-extern char *ide_xfer_verbose (byte xfer_rate);
-
-/*
- * Set a new transfer mode at the drive
- */
-static int sc1200_set_xfer_mode (ide_drive_t *drive, byte mode)
-{
-	printk("%s: sc1200_set_xfer_mode(%s)\n", drive->name, ide_xfer_verbose(mode));
-	return ide_config_drive_speed(drive, mode);
-}
-
 /*
  * Here are the standard PIO mode 0-4 timings for each "format".
  * Format-0 uses fast data reg timings, with slower command reg timings.
@@ -138,7 +127,7 @@
 	return mask;
 }
 
-static int sc1200_tune_chipset(ide_drive_t *drive, const u8 mode)
+static void sc1200_set_dma_mode(ide_drive_t *drive, const u8 mode)
 {
 	ide_hwif_t		*hwif = HWIF(drive);
 	int			unit = drive->select.b.unit;
@@ -146,17 +135,9 @@
 	unsigned short		pci_clock;
 	unsigned int		basereg = hwif->channel ? 0x50 : 0x40;
 
-	/*
-	 * Tell the drive to switch to the new mode; abort on failure.
-	 */
-	if (sc1200_set_xfer_mode(drive, mode))
-		return 1;	/* failure */
-
 	pci_clock = sc1200_get_pci_clock();
 
 	/*
-	 * Now tune the chipset to match the drive:
-	 *
 	 * Note that each DMA mode has several timings associated with it.
 	 * The correct timing depends on the fast PCI clock freq.
 	 */
@@ -216,8 +197,6 @@
 	} else {
 		pci_write_config_dword(hwif->pci_dev, basereg+12, timings);
 	}
-
-	return 0;	/* success */
 }
 
 /*
@@ -286,13 +265,12 @@
 	if (mode != -1) {
 		printk("SC1200: %s: changing (U)DMA mode\n", drive->name);
 		hwif->dma_off_quietly(drive);
-		if (sc1200_tune_chipset(drive, mode) == 0)
+		if (ide_set_dma_mode(drive, mode) == 0)
 			hwif->dma_host_on(drive);
 		return;
 	}
 
-	if (sc1200_set_xfer_mode(drive, XFER_PIO_0 + pio) == 0)
-		sc1200_tunepio(drive, pio);
+	sc1200_tunepio(drive, pio);
 }
 
 #ifdef CONFIG_PM
@@ -408,7 +386,7 @@
                 	hwif->autodma = 1;
 
 		hwif->set_pio_mode = &sc1200_set_pio_mode;
-		hwif->speedproc = &sc1200_tune_chipset;
+		hwif->set_dma_mode = &sc1200_set_dma_mode;
 	}
         hwif->atapi_dma = 1;
         hwif->ultra_mask = 0x07;
@@ -423,7 +401,7 @@
 	.init_hwif	= init_hwif_sc1200,
 	.autodma	= AUTODMA,
 	.bootable	= ON_BOARD,
-	.host_flags	= IDE_HFLAG_ABUSE_DMA_MODES,
+	.host_flags	= IDE_HFLAG_ABUSE_DMA_MODES | IDE_HFLAG_POST_SET_MODE,
 	.pio_mask	= ATA_PIO4,
 };
 
diff --git a/drivers/ide/pci/scc_pata.c b/drivers/ide/pci/scc_pata.c
index 66a526e..67f06dd 100644
--- a/drivers/ide/pci/scc_pata.c
+++ b/drivers/ide/pci/scc_pata.c
@@ -190,15 +190,15 @@
 }
 
 /**
- *	scc_tune_pio	-	tune a drive PIO mode
- *	@drive: drive to tune
- *	@mode_wanted: the target operating mode
+ *	scc_set_pio_mode	-	set host controller for PIO mode
+ *	@drive: drive
+ *	@pio: PIO mode number
  *
  *	Load the timing settings for this device mode into the
  *	controller.
  */
 
-static void scc_tune_pio(ide_drive_t *drive, const u8 pio)
+static void scc_set_pio_mode(ide_drive_t *drive, const u8 pio)
 {
 	ide_hwif_t *hwif = HWIF(drive);
 	struct scc_ports *ports = ide_get_hwifdata(hwif);
@@ -221,22 +221,16 @@
 	out_be32((void __iomem *)pioct_port, reg);
 }
 
-static void scc_set_pio_mode(ide_drive_t *drive, const u8 pio)
-{
-	scc_tune_pio(drive, pio);
-	ide_config_drive_speed(drive, XFER_PIO_0 + pio);
-}
-
 /**
- *	scc_tune_chipset	-	tune a drive DMA mode
- *	@drive: Drive to set up
- *	@speed: speed we want to achieve
+ *	scc_set_dma_mode	-	set host controller for DMA mode
+ *	@drive: drive
+ *	@speed: DMA mode
  *
  *	Load the timing settings for this device mode into the
  *	controller.
  */
 
-static int scc_tune_chipset(ide_drive_t *drive, const u8 speed)
+static void scc_set_dma_mode(ide_drive_t *drive, const u8 speed)
 {
 	ide_hwif_t *hwif = HWIF(drive);
 	struct scc_ports *ports = ide_get_hwifdata(hwif);
@@ -271,7 +265,7 @@
 		idx = speed - XFER_UDMA_0;
 		break;
 	default:
-		return 1;
+		return;
 	}
 
 	jcactsel = JCACTSELtbl[offset][idx];
@@ -287,8 +281,6 @@
 	}
 	reg = JCTSStbl[offset][idx] << 16 | JCENVTtbl[offset][idx];
 	out_be32((void __iomem *)udenvt_port, reg);
-
-	return ide_config_drive_speed(drive, speed);
 }
 
 /**
@@ -708,8 +700,8 @@
 
 	hwif->dma_setup = scc_dma_setup;
 	hwif->ide_dma_end = scc_ide_dma_end;
-	hwif->speedproc = scc_tune_chipset;
 	hwif->set_pio_mode = scc_set_pio_mode;
+	hwif->set_dma_mode = scc_set_dma_mode;
 	hwif->ide_dma_check = scc_config_drive_for_dma;
 	hwif->ide_dma_test_irq = scc_dma_test_irq;
 	hwif->udma_filter = scc_udma_filter;
diff --git a/drivers/ide/pci/serverworks.c b/drivers/ide/pci/serverworks.c
index 0351cf2..49ec0ac 100644
--- a/drivers/ide/pci/serverworks.c
+++ b/drivers/ide/pci/serverworks.c
@@ -124,7 +124,7 @@
 	return 0;
 }
 
-static void svwks_tune_pio(ide_drive_t *drive, const u8 pio)
+static void svwks_set_pio_mode(ide_drive_t *drive, const u8 pio)
 {
 	static const u8 pio_modes[] = { 0x5d, 0x47, 0x34, 0x22, 0x20 };
 	static const u8 drive_pci[] = { 0x41, 0x40, 0x43, 0x42 };
@@ -145,7 +145,7 @@
 	}
 }
 
-static int svwks_tune_chipset(ide_drive_t *drive, const u8 speed)
+static void svwks_set_dma_mode(ide_drive_t *drive, const u8 speed)
 {
 	static const u8 udma_modes[]		= { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05 };
 	static const u8 dma_modes[]		= { 0x77, 0x21, 0x20 };
@@ -193,14 +193,6 @@
 	pci_write_config_byte(dev, drive_pci2[drive->dn], dma_timing);
 	pci_write_config_byte(dev, (0x56|hwif->channel), ultra_timing);
 	pci_write_config_byte(dev, 0x54, ultra_enable);
-
-	return (ide_config_drive_speed(drive, speed));
-}
-
-static void svwks_set_pio_mode(ide_drive_t *drive, const u8 pio)
-{
-	svwks_tune_pio(drive, pio);
-	(void)ide_config_drive_speed(drive, XFER_PIO_0 + pio);
 }
 
 static int svwks_config_drive_xfer_rate (ide_drive_t *drive)
@@ -384,7 +376,7 @@
 		hwif->irq = hwif->channel ? 15 : 14;
 
 	hwif->set_pio_mode = &svwks_set_pio_mode;
-	hwif->speedproc = &svwks_tune_chipset;
+	hwif->set_dma_mode = &svwks_set_dma_mode;
 	hwif->udma_filter = &svwks_udma_filter;
 
 	hwif->atapi_dma = 1;
diff --git a/drivers/ide/pci/sgiioc4.c b/drivers/ide/pci/sgiioc4.c
index c292e1d..2635262 100644
--- a/drivers/ide/pci/sgiioc4.c
+++ b/drivers/ide/pci/sgiioc4.c
@@ -291,12 +291,8 @@
 	drive->hwif->dma_host_off(drive);
 }
 
-static int sgiioc4_speedproc(ide_drive_t *drive, const u8 speed)
+static void sgiioc4_set_dma_mode(ide_drive_t *drive, const u8 speed)
 {
-	if (speed != XFER_MW_DMA_2)
-		return 1;
-
-	return ide_config_drive_speed(drive, speed);
 }
 
 static int sgiioc4_ide_dma_check(ide_drive_t *drive)
@@ -595,7 +591,7 @@
 	hwif->mwdma_mask = 0x04;
 	hwif->pio_mask = 0x00;
 	hwif->set_pio_mode = NULL; /* Sets timing for PIO mode */
-	hwif->speedproc = &sgiioc4_speedproc;
+	hwif->set_dma_mode = &sgiioc4_set_dma_mode;
 	hwif->selectproc = NULL;/* Use the default routine to select drive */
 	hwif->reset_poll = NULL;/* No HBA specific reset_poll needed */
 	hwif->pre_reset = NULL;	/* No HBA specific pre_set needed */
diff --git a/drivers/ide/pci/siimage.c b/drivers/ide/pci/siimage.c
index 5d1e5e5..ce77849 100644
--- a/drivers/ide/pci/siimage.c
+++ b/drivers/ide/pci/siimage.c
@@ -165,16 +165,16 @@
 }
 
 /**
- *	sil_tune_pio	-	tune a drive
- *	@drive: drive to tune
- *	@pio: the desired PIO mode
+ *	sil_set_pio_mode	-	set host controller for PIO mode
+ *	@drive: drive
+ *	@pio: PIO mode number
  *
  *	Load the timing settings for this device mode into the
  *	controller. If we are in PIO mode 3 or 4 turn on IORDY
  *	monitoring (bit 9). The TF timing is bits 31:16
  */
 
-static void sil_tune_pio(ide_drive_t *drive, u8 pio)
+static void sil_set_pio_mode(ide_drive_t *drive, u8 pio)
 {
 	const u16 tf_speed[]	= { 0x328a, 0x2283, 0x1281, 0x10c3, 0x10c1 };
 	const u16 data_speed[]	= { 0x328a, 0x2283, 0x1104, 0x10c3, 0x10c1 };
@@ -234,21 +234,15 @@
 	}
 }
 
-static void sil_set_pio_mode(ide_drive_t *drive, const u8 pio)
-{
-	sil_tune_pio(drive, pio);
-	(void)ide_config_drive_speed(drive, XFER_PIO_0 + pio);
-}
-
 /**
- *	siimage_tune_chipset	-	set controller timings
- *	@drive: Drive to set up
- *	@speed: speed we want to achieve
+ *	sil_set_dma_mode	-	set host controller for DMA mode
+ *	@drive: drive
+ *	@speed: DMA mode
  *
- *	Tune the SII chipset for the desired mode.
+ *	Tune the SiI chipset for the desired DMA mode.
  */
 
-static int siimage_tune_chipset(ide_drive_t *drive, const u8 speed)
+static void sil_set_dma_mode(ide_drive_t *drive, const u8 speed)
 {
 	u8 ultra6[]		= { 0x0F, 0x0B, 0x07, 0x05, 0x03, 0x02, 0x01 };
 	u8 ultra5[]		= { 0x0C, 0x07, 0x05, 0x04, 0x02, 0x01 };
@@ -303,7 +297,7 @@
 			mode |= ((unit) ? 0x30 : 0x03);
 			break;
 		default:
-			return 1;
+			return;
 	}
 
 	if (hwif->mmio) {
@@ -315,7 +309,6 @@
 		pci_write_config_word(hwif->pci_dev, ma, multi);
 		pci_write_config_word(hwif->pci_dev, ua, ultra);
 	}
-	return (ide_config_drive_speed(drive, speed));
 }
 
 /**
@@ -904,8 +897,8 @@
 	hwif->autodma = 0;
 	
 	hwif->resetproc = &siimage_reset;
-	hwif->speedproc = &siimage_tune_chipset;
 	hwif->set_pio_mode = &sil_set_pio_mode;
+	hwif->set_dma_mode = &sil_set_dma_mode;
 	hwif->reset_poll = &siimage_reset_poll;
 	hwif->pre_reset = &siimage_pre_reset;
 	hwif->udma_filter = &sil_udma_filter;
diff --git a/drivers/ide/pci/sis5513.c b/drivers/ide/pci/sis5513.c
index 3e18899..b375ee5 100644
--- a/drivers/ide/pci/sis5513.c
+++ b/drivers/ide/pci/sis5513.c
@@ -451,7 +451,7 @@
 }
 
 /* Set per-drive active and recovery time */
-static void config_art_rwp_pio (ide_drive_t *drive, u8 pio)
+static void sis_set_pio_mode(ide_drive_t *drive, const u8 pio)
 {
 	ide_hwif_t *hwif	= HWIF(drive);
 	struct pci_dev *dev	= hwif->pci_dev;
@@ -519,20 +519,14 @@
 	}
 }
 
-static void sis_set_pio_mode(ide_drive_t *drive, const u8 pio)
-{
-	config_art_rwp_pio(drive, pio);
-	(void)ide_config_drive_speed(drive, XFER_PIO_0 + pio);
-}
-
-static int sis5513_tune_chipset(ide_drive_t *drive, const u8 speed)
+static void sis_set_dma_mode(ide_drive_t *drive, const u8 speed)
 {
 	ide_hwif_t *hwif	= HWIF(drive);
 	struct pci_dev *dev	= hwif->pci_dev;
 	u32 regdw;
 	u8 drive_pci, reg;
 
-	/* See config_art_rwp_pio for drive pci config registers */
+	/* See sis_set_pio_mode() for drive PCI config registers */
 	drive_pci = 0x40;
 	if (chipset_family >= ATA_133) {
 		u32 reg54h;
@@ -600,8 +594,6 @@
 			BUG();
 			break;
 	}
-
-	return ide_config_drive_speed(drive, speed);
 }
 
 static int sis5513_config_xfer_rate(ide_drive_t *drive)
@@ -841,7 +833,7 @@
 		hwif->irq = hwif->channel ? 15 : 14;
 
 	hwif->set_pio_mode = &sis_set_pio_mode;
-	hwif->speedproc = &sis5513_tune_chipset;
+	hwif->set_dma_mode = &sis_set_dma_mode;
 
 	if (chipset_family >= ATA_133)
 		hwif->udma_filter = sis5513_ata133_udma_filter;
diff --git a/drivers/ide/pci/sl82c105.c b/drivers/ide/pci/sl82c105.c
index f492318..2ef26e3 100644
--- a/drivers/ide/pci/sl82c105.c
+++ b/drivers/ide/pci/sl82c105.c
@@ -75,7 +75,7 @@
 /*
  * Configure the chipset for PIO mode.
  */
-static void sl82c105_tune_pio(ide_drive_t *drive, const u8 pio)
+static void sl82c105_set_pio_mode(ide_drive_t *drive, const u8 pio)
 {
 	struct pci_dev *dev	= HWIF(drive)->pci_dev;
 	int reg			= 0x44 + drive->dn * 4;
@@ -105,9 +105,9 @@
 }
 
 /*
- * Configure the drive and chipset for a new transfer speed.
+ * Configure the chipset for DMA mode.
  */
-static int sl82c105_tune_chipset(ide_drive_t *drive, const u8 speed)
+static void sl82c105_set_dma_mode(ide_drive_t *drive, const u8 speed)
 {
 	static u16 mwdma_timings[] = {0x0707, 0x0201, 0x0200};
 	u16 drv_ctrl;
@@ -140,10 +140,8 @@
 		}
 		break;
 	default:
-		return -1;
+		return;
 	}
-
-	return ide_config_drive_speed(drive, speed);
 }
 
 /*
@@ -306,17 +304,6 @@
 	pci_read_config_dword(dev, 0x40, &val);
 	pci_set_drvdata(dev, (void *)val);
 }
-	
-/*
- * We only deal with PIO mode here - DMA mode 'using_dma' is not
- * initialised at the point that this function is called.
- */
-static void sl82c105_set_pio_mode(ide_drive_t *drive, const u8 pio)
-{
-	sl82c105_tune_pio(drive, pio);
-
-	(void) ide_config_drive_speed(drive, XFER_PIO_0 + pio);
-}
 
 /*
  * Return the revision of the Winbond bridge
@@ -383,7 +370,7 @@
 	DBG(("init_hwif_sl82c105(hwif: ide%d)\n", hwif->index));
 
 	hwif->set_pio_mode	= &sl82c105_set_pio_mode;
-	hwif->speedproc 	= &sl82c105_tune_chipset;
+	hwif->set_dma_mode	= &sl82c105_set_dma_mode;
 	hwif->selectproc	= &sl82c105_selectproc;
 	hwif->resetproc 	= &sl82c105_resetproc;
 
diff --git a/drivers/ide/pci/slc90e66.c b/drivers/ide/pci/slc90e66.c
index ae8e913..ebac87f 100644
--- a/drivers/ide/pci/slc90e66.c
+++ b/drivers/ide/pci/slc90e66.c
@@ -42,7 +42,7 @@
 	}
 }
 
-static void slc90e66_tune_pio (ide_drive_t *drive, u8 pio)
+static void slc90e66_set_pio_mode(ide_drive_t *drive, const u8 pio)
 {
 	ide_hwif_t *hwif	= HWIF(drive);
 	struct pci_dev *dev	= hwif->pci_dev;
@@ -95,13 +95,7 @@
 	spin_unlock_irqrestore(&ide_lock, flags);
 }
 
-static void slc90e66_set_pio_mode(ide_drive_t *drive, const u8 pio)
-{
-	slc90e66_tune_pio(drive, pio);
-	(void) ide_config_drive_speed(drive, XFER_PIO_0 + pio);
-}
-
-static int slc90e66_tune_chipset(ide_drive_t *drive, const u8 speed)
+static void slc90e66_set_dma_mode(ide_drive_t *drive, const u8 speed)
 {
 	ide_hwif_t *hwif	= HWIF(drive);
 	struct pci_dev *dev	= hwif->pci_dev;
@@ -125,7 +119,7 @@
 		case XFER_MW_DMA_2:
 		case XFER_MW_DMA_1:
 		case XFER_SW_DMA_2:	break;
-		default:		return -1;
+		default:		return;
 	}
 
 	if (speed >= XFER_UDMA_0) {
@@ -144,9 +138,7 @@
 			pci_write_config_word(dev, 0x4a, reg4a & ~a_speed);
 	}
 
-	slc90e66_tune_pio(drive, slc90e66_dma_2_pio(speed));
-
-	return ide_config_drive_speed(drive, speed);
+	slc90e66_set_pio_mode(drive, slc90e66_dma_2_pio(speed));
 }
 
 static int slc90e66_config_drive_xfer_rate (ide_drive_t *drive)
@@ -172,8 +164,8 @@
 	if (!hwif->irq)
 		hwif->irq = hwif->channel ? 15 : 14;
 
-	hwif->speedproc = &slc90e66_tune_chipset;
 	hwif->set_pio_mode = &slc90e66_set_pio_mode;
+	hwif->set_dma_mode = &slc90e66_set_dma_mode;
 
 	pci_read_config_byte(hwif->pci_dev, 0x47, &reg47);
 
diff --git a/drivers/ide/pci/tc86c001.c b/drivers/ide/pci/tc86c001.c
index e23b9cf..840415d 100644
--- a/drivers/ide/pci/tc86c001.c
+++ b/drivers/ide/pci/tc86c001.c
@@ -13,7 +13,7 @@
 #include <linux/pci.h>
 #include <linux/ide.h>
 
-static int tc86c001_tune_chipset(ide_drive_t *drive, const u8 speed)
+static void tc86c001_set_mode(ide_drive_t *drive, const u8 speed)
 {
 	ide_hwif_t *hwif	= HWIF(drive);
 	unsigned long scr_port	= hwif->config_data + (drive->dn ? 0x02 : 0x00);
@@ -39,13 +39,11 @@
 	scr &= (speed < XFER_MW_DMA_0) ? 0xf8ff : 0xff0f;
 	scr |= mode;
 	outw(scr, scr_port);
-
-	return ide_config_drive_speed(drive, speed);
 }
 
 static void tc86c001_set_pio_mode(ide_drive_t *drive, const u8 pio)
 {
-	(void) tc86c001_tune_chipset(drive, XFER_PIO_0 + pio);
+	tc86c001_set_mode(drive, XFER_PIO_0 + pio);
 }
 
 /*
@@ -193,7 +191,8 @@
 	hwif->config_data = sc_base;
 
 	hwif->set_pio_mode = &tc86c001_set_pio_mode;
-	hwif->speedproc = &tc86c001_tune_chipset;
+	hwif->set_dma_mode = &tc86c001_set_mode;
+
 	hwif->busproc	= &tc86c001_busproc;
 
 	hwif->drives[0].autotune = hwif->drives[1].autotune = 1;
diff --git a/drivers/ide/pci/triflex.c b/drivers/ide/pci/triflex.c
index c3ff066..54e411d 100644
--- a/drivers/ide/pci/triflex.c
+++ b/drivers/ide/pci/triflex.c
@@ -40,7 +40,7 @@
 #include <linux/ide.h>
 #include <linux/init.h>
 
-static int triflex_tune_chipset(ide_drive_t *drive, const u8 speed)
+static void triflex_set_mode(ide_drive_t *drive, const u8 speed)
 {
 	ide_hwif_t *hwif = HWIF(drive);
 	struct pci_dev *dev = hwif->pci_dev;
@@ -82,20 +82,18 @@
 			timing = 0x0808;
 			break;
 		default:
-			return -1;
+			return;
 	}
 
 	triflex_timings &= ~(0xFFFF << (16 * unit));
 	triflex_timings |= (timing << (16 * unit));
 	
 	pci_write_config_dword(dev, channel_offset, triflex_timings);
-	
-	return (ide_config_drive_speed(drive, speed));
 }
 
 static void triflex_set_pio_mode(ide_drive_t *drive, const u8 pio)
 {
-	(void)triflex_tune_chipset(drive, XFER_PIO_0 + pio);
+	triflex_set_mode(drive, XFER_PIO_0 + pio);
 }
 
 static int triflex_config_drive_xfer_rate(ide_drive_t *drive)
@@ -111,7 +109,7 @@
 static void __devinit init_hwif_triflex(ide_hwif_t *hwif)
 {
 	hwif->set_pio_mode = &triflex_set_pio_mode;
-	hwif->speedproc = &triflex_tune_chipset;
+	hwif->set_dma_mode = &triflex_set_mode;
 
 	if (hwif->dma_base == 0)
 		return;
diff --git a/drivers/ide/pci/via82cxxx.c b/drivers/ide/pci/via82cxxx.c
index ac094e5..479e496 100644
--- a/drivers/ide/pci/via82cxxx.c
+++ b/drivers/ide/pci/via82cxxx.c
@@ -153,21 +153,17 @@
  *	@drive: Drive to set up
  *	@speed: desired speed
  *
- *	via_set_drive() computes timing values configures the drive and
- *	the chipset to a desired transfer mode. It also can be called
- *	by upper layers.
+ *	via_set_drive() computes timing values configures the chipset to
+ *	a desired transfer mode.  It also can be called by upper layers.
  */
 
-static int via_set_drive(ide_drive_t *drive, const u8 speed)
+static void via_set_drive(ide_drive_t *drive, const u8 speed)
 {
 	ide_drive_t *peer = HWIF(drive)->drives + (~drive->dn & 1);
 	struct via82cxxx_dev *vdev = pci_get_drvdata(drive->hwif->pci_dev);
 	struct ide_timing t, p;
 	unsigned int T, UT;
 
-	if (ide_config_drive_speed(drive, speed))
-		return 1;
-
 	T = 1000000000 / via_clock;
 
 	switch (vdev->via_config->udma_mask) {
@@ -186,12 +182,10 @@
 	}
 
 	via_set_speed(HWIF(drive), drive->dn, &t);
-
-	return 0;
 }
 
 /**
- *	via_set_pio_mode	-	PIO setup
+ *	via_set_pio_mode	-	set host controller for PIO mode
  *	@drive: drive
  *	@pio: PIO mode number
  *
@@ -452,8 +446,7 @@
 	hwif->autodma = 0;
 
 	hwif->set_pio_mode = &via_set_pio_mode;
-	hwif->speedproc = &via_set_drive;
-
+	hwif->set_dma_mode = &via_set_drive;
 
 #ifdef CONFIG_PPC_CHRP
 	if(machine_is(chrp) && _chrp_type == _CHRP_Pegasos) {
@@ -496,7 +489,8 @@
 		.enablebits	= {{0x40,0x02,0x02}, {0x40,0x01,0x01}},
 		.bootable	= ON_BOARD,
 		.host_flags	= IDE_HFLAG_PIO_NO_BLACKLIST
-				| IDE_HFLAG_PIO_NO_DOWNGRADE,
+				| IDE_HFLAG_PIO_NO_DOWNGRADE
+				| IDE_HFLAG_POST_SET_MODE,
 		.pio_mask	= ATA_PIO5,
 	},{	/* 1 */
 		.name		= "VP_IDE",
@@ -506,7 +500,8 @@
 		.enablebits	= {{0x00,0x00,0x00}, {0x00,0x00,0x00}},
 		.bootable	= ON_BOARD,
 		.host_flags	= IDE_HFLAG_PIO_NO_BLACKLIST
-				| IDE_HFLAG_PIO_NO_DOWNGRADE,
+				| IDE_HFLAG_PIO_NO_DOWNGRADE
+				| IDE_HFLAG_POST_SET_MODE,
 		.pio_mask	= ATA_PIO5,
 	}
 };
diff --git a/drivers/ide/ppc/pmac.c b/drivers/ide/ppc/pmac.c
index 313194a..7d88738 100644
--- a/drivers/ide/ppc/pmac.c
+++ b/drivers/ide/ppc/pmac.c
@@ -611,9 +611,6 @@
 		drive->name, pio,  *timings);
 #endif	
 
-	if (ide_config_drive_speed(drive, XFER_PIO_0 + pio))
-		return;
-
 	*timings = t;
 	pmac_ide_do_update_timings(drive);
 }
@@ -822,11 +819,7 @@
 }
 #endif /* #ifdef CONFIG_BLK_DEV_IDEDMA_PMAC */
 
-/* 
- * Speedproc. This function is called by the core to set any of the standard
- * DMA timing (MDMA or UDMA) to both the drive and the controller.
- */
-static int pmac_ide_tune_chipset(ide_drive_t *drive, const u8 speed)
+static void pmac_ide_set_dma_mode(ide_drive_t *drive, const u8 speed)
 {
 	int unit = (drive->select.b.unit & 0x01);
 	int ret = 0;
@@ -867,25 +860,19 @@
 		case XFER_SW_DMA_2:
 		case XFER_SW_DMA_1:
 		case XFER_SW_DMA_0:
-			return 1;
+			return;
 #endif /* CONFIG_BLK_DEV_IDEDMA_PMAC */
 		default:
 			ret = 1;
 	}
 	if (ret)
-		return ret;
-
-	ret = ide_config_drive_speed(drive, speed);
-	if (ret)
-		return ret;
+		return;
 
 	/* Apply timings to controller */
 	*timings = tl[0];
 	*timings2 = tl[1];
 
 	pmac_ide_do_update_timings(drive);	
-
-	return 0;
 }
 
 /*
@@ -1147,7 +1134,8 @@
 	hwif->drives[1].unmask = 1;
 	hwif->drives[0].autotune = IDE_TUNE_AUTO;
 	hwif->drives[1].autotune = IDE_TUNE_AUTO;
-	hwif->host_flags = IDE_HFLAG_SET_PIO_MODE_KEEP_DMA;
+	hwif->host_flags = IDE_HFLAG_SET_PIO_MODE_KEEP_DMA |
+			   IDE_HFLAG_POST_SET_MODE;
 	hwif->pio_mask = ATA_PIO4;
 	hwif->set_pio_mode = pmac_ide_set_pio_mode;
 	if (pmif->kind == controller_un_ata6
@@ -1156,7 +1144,7 @@
 		hwif->selectproc = pmac_ide_kauai_selectproc;
 	else
 		hwif->selectproc = pmac_ide_selectproc;
-	hwif->speedproc = pmac_ide_tune_chipset;
+	hwif->set_dma_mode = pmac_ide_set_dma_mode;
 
 	printk(KERN_INFO "ide%d: Found Apple %s controller, bus ID %d%s, irq %d\n",
 	       hwif->index, model_name[pmif->kind], pmif->aapl_bus_id,
diff --git a/include/linux/ide.h b/include/linux/ide.h
index a7d8b4b..02a27e8 100644
--- a/include/linux/ide.h
+++ b/include/linux/ide.h
@@ -681,7 +681,7 @@
 	u8 straight8;	/* Alan's straight 8 check */
 	u8 bus_state;	/* power state of the IDE bus */
 
-	u8 host_flags;
+	u16 host_flags;
 
 	u8 pio_mask;
 
@@ -702,10 +702,10 @@
 #if 0
 	ide_hwif_ops_t	*hwifops;
 #else
-	/* routine to set PIO mode for drives */
+	/* routine to program host for PIO mode */
 	void	(*set_pio_mode)(ide_drive_t *, const u8);
-	/* routine to retune DMA modes for drives */
-	int	(*speedproc)(ide_drive_t *, const u8);
+	/* routine to program host for DMA mode */
+	void	(*set_dma_mode)(ide_drive_t *, const u8);
 	/* tweaks hardware to select drive */
 	void	(*selectproc)(ide_drive_t *);
 	/* chipset polling based on hba specifics */
@@ -1257,6 +1257,10 @@
 	 * for hosts which have separate PIO and DMA timings (ie. PMAC)
 	 */
 	IDE_HFLAG_SET_PIO_MODE_KEEP_DMA	= (1 << 7),
+	/* program host for the transfer mode after programming device */
+	IDE_HFLAG_POST_SET_MODE		= (1 << 8),
+	/* don't program host/device for the transfer mode ("smart" hosts) */
+	IDE_HFLAG_NO_SET_MODE		= (1 << 9),
 };
 
 typedef struct ide_pci_device_s {
@@ -1273,7 +1277,7 @@
 	u8			bootable;
 	unsigned int		extra;
 	struct ide_pci_device_s	*next;
-	u8			host_flags;
+	u16			host_flags;
 	u8			pio_mask;
 	u8			udma_mask;
 } ide_pci_device_t;
@@ -1414,6 +1418,9 @@
 u8 ide_get_best_pio_mode(ide_drive_t *, u8, u8);
 extern const ide_pio_timings_t ide_pio_timings[6];
 
+int ide_set_pio_mode(ide_drive_t *, u8);
+int ide_set_dma_mode(ide_drive_t *, u8);
+
 void ide_set_pio(ide_drive_t *, u8);
 
 static inline void ide_set_max_pio(ide_drive_t *drive)