Patchwork [85/86] libata: add ->init_host method

login
register
mail settings
Submitter Bartlomiej Zolnierkiewicz
Date Nov. 25, 2009, 5:12 p.m.
Message ID <20091125171240.5446.31841.sendpatchset@localhost>
Download mbox | patch
Permalink /patch/39375/
State Not Applicable
Delegated to: David Miller
Headers show

Comments

Bartlomiej Zolnierkiewicz - Nov. 25, 2009, 5:12 p.m.
From: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
Subject: [PATCH] libata: add ->init_host method

Add ->init_host method for re-initialization of the controller
in ata_pci_device_resume().

Then teach ata_pci_sff_init_one() and host drivers about it.

Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
---
 drivers/ata/libata-core.c   |   14 ++++++++++---
 drivers/ata/libata-sff.c    |   10 ++++++---
 drivers/ata/pata_ali.c      |   29 ++++++++-------------------
 drivers/ata/pata_amd.c      |   45 +++++++++++++++++--------------------------
 drivers/ata/pata_artop.c    |   30 ++++++++--------------------
 drivers/ata/pata_cmd640.c   |   27 +++++++------------------
 drivers/ata/pata_cmd64x.c   |   29 +++++++--------------------
 drivers/ata/pata_cs5530.c   |   31 ++++++-----------------------
 drivers/ata/pata_hpt366.c   |   30 +++++++++-------------------
 drivers/ata/pata_hpt3x3.c   |   32 ++++++++++--------------------
 drivers/ata/pata_it821x.c   |   31 +++++++++++------------------
 drivers/ata/pata_ninja32.c  |   30 ++++++++++------------------
 drivers/ata/pata_ns87415.c  |   30 ++++++++--------------------
 drivers/ata/pata_pdc2027x.c |   46 ++++++++++++++------------------------------
 drivers/ata/pata_sl82c105.c |   29 +++++++--------------------
 drivers/ata/sata_sil.c      |   33 ++++++++-----------------------
 include/linux/libata.h      |   14 ++++++++++---
 17 files changed, 173 insertions(+), 317 deletions(-)

--
To unsubscribe from this list: send the line "unsubscribe linux-ide" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Alan Cox - Nov. 25, 2009, 5:56 p.m.
On Wed, 25 Nov 2009 18:12:40 +0100
Bartlomiej Zolnierkiewicz <bzolnier@gmail.com> wrote:

> From: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
> Subject: [PATCH] libata: add ->init_host method
> 
> Add ->init_host method for re-initialization of the controller
> in ata_pci_device_resume().

Would be much cleaner if the init_host method was in the ops stuff
somewhere rather than assigned all over the place separately - because
then folks forget and its not part of the inheriting.

Definitely a good thing though
--
To unsubscribe from this list: send the line "unsubscribe linux-ide" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Patch

Index: b/drivers/ata/libata-core.c
===================================================================
--- a/drivers/ata/libata-core.c
+++ b/drivers/ata/libata-core.c
@@ -6426,9 +6426,17 @@  int ata_pci_device_resume(struct pci_dev
 	int rc;
 
 	rc = ata_pci_device_do_resume(pdev);
-	if (rc == 0)
-		ata_host_resume(host);
-	return rc;
+	if (rc)
+		return rc;
+
+	if (host->init_host) {
+		rc = host->init_host(&pdev->dev);
+		if (rc)
+			return rc;
+	}
+
+	ata_host_resume(host);
+	return 0;
 }
 #endif /* CONFIG_PM */
 
Index: b/drivers/ata/libata-sff.c
===================================================================
--- a/drivers/ata/libata-sff.c
+++ b/drivers/ata/libata-sff.c
@@ -3003,11 +3003,12 @@  out:
 EXPORT_SYMBOL_GPL(ata_pci_sff_activate_host);
 
 /**
- *	ata_pci_sff_init_one - Initialize/register PCI IDE host controller
+ *	__ata_pci_sff_init_one - Initialize/register PCI IDE host controller
  *	@pdev: Controller to be initialized
  *	@ppi: array of port_info, must be enough for two ports
  *	@sht: scsi_host_template to use when registering the host
  *	@host_priv: host private_data
+ *	@init_host: host initialization method (optional)
  *
  *	This is a helper function which can be called from a driver's
  *	xxx_init_one() probe function if the hardware uses traditional
@@ -3027,9 +3028,10 @@  EXPORT_SYMBOL_GPL(ata_pci_sff_activate_h
  *	RETURNS:
  *	Zero on success, negative on errno-based value on error.
  */
-int ata_pci_sff_init_one(struct pci_dev *pdev,
+int __ata_pci_sff_init_one(struct pci_dev *pdev,
 			 const struct ata_port_info * const *ppi,
-			 struct scsi_host_template *sht, void *host_priv)
+			 struct scsi_host_template *sht, void *host_priv,
+			 int (*init_host)(struct device *dev))
 {
 	struct device *dev = &pdev->dev;
 	const struct ata_port_info *pi = NULL;
@@ -3063,7 +3065,9 @@  int ata_pci_sff_init_one(struct pci_dev
 	rc = ata_pci_sff_prepare_host(pdev, ppi, &host);
 	if (rc)
 		goto out;
+
 	host->private_data = host_priv;
+	host->init_host = init_host;
 
 	pci_set_master(pdev);
 	rc = ata_pci_sff_activate_host(host, ata_sff_interrupt, sht);
Index: b/drivers/ata/pata_ali.c
===================================================================
--- a/drivers/ata/pata_ali.c
+++ b/drivers/ata/pata_ali.c
@@ -424,14 +424,15 @@  static struct ata_port_operations ali_c5
 
 /**
  *	ali_init_chipset	-	chip setup function
- *	@pdev: PCI device of ATA controller
+ *	@dev: device of ATA controller
  *
  *	Perform the setup on the device that must be done both at boot
  *	and at resume time.
  */
 
-static void ali_init_chipset(struct pci_dev *pdev)
+static int ali_init_chipset(struct device *dev)
 {
+	struct pci_dev *pdev = to_pci_dev(dev);
 	u8 tmp;
 	struct pci_dev *north;
 
@@ -478,7 +479,9 @@  static void ali_init_chipset(struct pci_
 	}
 	pci_dev_put(north);
 	ata_pci_bmdma_clear_simplex(pdev);
+	return 0;
 }
+
 /**
  *	ali_init_one		-	discovery callback
  *	@pdev: PCI device ID
@@ -574,7 +577,7 @@  static int ali_init_one(struct pci_dev *
 	} else
         	ppi[0] = &info_c5;
 
-	ali_init_chipset(pdev);
+	ali_init_chipset(&pdev->dev);
 
 	if (ali_isa_bridge && pdev->revision >= 0x20 && pdev->revision < 0xC2) {
 		/* Are we paired with a UDMA capable chip */
@@ -583,23 +586,9 @@  static int ali_init_one(struct pci_dev *
 	        	ppi[0] = &info_20_udma;
 	}
 
-	return ata_pci_sff_init_one(pdev, ppi, &ali_sht, NULL);
-}
-
-#ifdef CONFIG_PM
-static int ali_reinit_one(struct pci_dev *pdev)
-{
-	struct ata_host *host = dev_get_drvdata(&pdev->dev);
-	int rc;
-
-	rc = ata_pci_device_do_resume(pdev);
-	if (rc)
-		return rc;
-	ali_init_chipset(pdev);
-	ata_host_resume(host);
-	return 0;
+	return __ata_pci_sff_init_one(pdev, ppi, &ali_sht, NULL,
+				      ali_init_chipset);
 }
-#endif
 
 static const struct pci_device_id ali[] = {
 	{ PCI_VDEVICE(AL, PCI_DEVICE_ID_AL_M5228), },
@@ -615,7 +604,7 @@  static struct pci_driver ali_pci_driver
 	.remove		= ata_pci_remove_one,
 #ifdef CONFIG_PM
 	.suspend	= ata_pci_device_suspend,
-	.resume		= ali_reinit_one,
+	.resume		= ata_pci_device_resume,
 #endif
 };
 
Index: b/drivers/ata/pata_amd.c
===================================================================
--- a/drivers/ata/pata_amd.c
+++ b/drivers/ata/pata_amd.c
@@ -455,6 +455,20 @@  static void amd_clear_fifo(struct pci_de
 	pci_write_config_byte(pdev, 0x41, fifo);
 }
 
+static int amd_fixup(struct device *dev)
+{
+	struct pci_dev *pdev = to_pci_dev(dev);
+
+	if (pdev->vendor == PCI_VENDOR_ID_AMD) {
+		amd_clear_fifo(pdev);
+		if (pdev->device == PCI_DEVICE_ID_AMD_VIPER_7409 ||
+		    pdev->device == PCI_DEVICE_ID_AMD_COBRA_7401)
+			ata_pci_bmdma_clear_simplex(pdev);
+	}
+
+	return 0;
+}
+
 static int amd_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
 {
 	static const struct ata_port_info info[10] = {
@@ -559,10 +573,8 @@  static int amd_init_one(struct pci_dev *
 	 */
 	ppi[0] = &info[type];
 
-	if (type < 3)
-		ata_pci_bmdma_clear_simplex(pdev);
-	if (pdev->vendor == PCI_VENDOR_ID_AMD)
-		amd_clear_fifo(pdev);
+	amd_fixup(&pdev->dev);
+
 	/* Cable detection on Nvidia chips doesn't work too well,
 	 * cache BIOS programmed UDMA mode.
 	 */
@@ -574,30 +586,9 @@  static int amd_init_one(struct pci_dev *
 	}
 
 	/* And fire it up */
-	return ata_pci_sff_init_one(pdev, ppi, &amd_sht, hpriv);
+	return __ata_pci_sff_init_one(pdev, ppi, &amd_sht, hpriv, amd_fixup);
 }
 
-#ifdef CONFIG_PM
-static int amd_reinit_one(struct pci_dev *pdev)
-{
-	struct ata_host *host = dev_get_drvdata(&pdev->dev);
-	int rc;
-
-	rc = ata_pci_device_do_resume(pdev);
-	if (rc)
-		return rc;
-
-	if (pdev->vendor == PCI_VENDOR_ID_AMD) {
-		amd_clear_fifo(pdev);
-		if (pdev->device == PCI_DEVICE_ID_AMD_VIPER_7409 ||
-		    pdev->device == PCI_DEVICE_ID_AMD_COBRA_7401)
-			ata_pci_bmdma_clear_simplex(pdev);
-	}
-	ata_host_resume(host);
-	return 0;
-}
-#endif
-
 static const struct pci_device_id amd[] = {
 	{ PCI_VDEVICE(AMD,	PCI_DEVICE_ID_AMD_COBRA_7401),		0 },
 	{ PCI_VDEVICE(AMD,	PCI_DEVICE_ID_AMD_VIPER_7409),		1 },
@@ -630,7 +621,7 @@  static struct pci_driver amd_pci_driver
 	.remove		= ata_pci_remove_one,
 #ifdef CONFIG_PM
 	.suspend	= ata_pci_device_suspend,
-	.resume		= amd_reinit_one,
+	.resume		= ata_pci_device_resume,
 #endif
 };
 
Index: b/drivers/ata/pata_artop.c
===================================================================
--- a/drivers/ata/pata_artop.c
+++ b/drivers/ata/pata_artop.c
@@ -302,8 +302,10 @@  static struct ata_port_operations atp86x
 	.prereset		= atp8xx_prereset,
 };
 
-static void atp8xx_fixup(struct pci_dev *pdev)
+static int atp8xx_fixup(struct device *dev)
 {
+	struct pci_dev *pdev = to_pci_dev(dev);
+
 	if (pdev->device == 0x0005)
 		/* BIOS may have left us in UDMA, clear it before probe */
 		pci_write_config_byte(pdev, 0x54, 0);
@@ -328,6 +330,8 @@  static void atp8xx_fixup(struct pci_dev
 		pci_read_config_byte(pdev, 0x4a, &reg);
 		pci_write_config_byte(pdev, 0x4a, (reg & ~0x01) | 0x80);
 	}
+
+	return 0;
 }
 
 /**
@@ -400,28 +404,12 @@  static int artop_init_one (struct pci_de
 
 	BUG_ON(ppi[0] == NULL);
 
-	atp8xx_fixup(pdev);
+	atp8xx_fixup(&pdev->dev);
 
-	return ata_pci_sff_init_one(pdev, ppi, &artop_sht, NULL);
+	return __ata_pci_sff_init_one(pdev, ppi, &artop_sht, NULL,
+				      atp8xx_fixup);
 }
 
-#ifdef CONFIG_PM
-static int atp8xx_reinit_one(struct pci_dev *pdev)
-{
-	struct ata_host *host = dev_get_drvdata(&pdev->dev);
-	int rc;
-
-	rc = ata_pci_device_do_resume(pdev);
-	if (rc)
-		return rc;
-
-	atp8xx_fixup(pdev);
-
-	ata_host_resume(host);
-	return 0;
-}
-#endif
-
 static const struct pci_device_id artop_pci_tbl[] = {
 	{ PCI_VDEVICE(ARTOP, 0x0005), 0 },
 	{ PCI_VDEVICE(ARTOP, 0x0006), 1 },
@@ -439,7 +427,7 @@  static struct pci_driver artop_pci_drive
 	.remove			= ata_pci_remove_one,
 #ifdef CONFIG_PM
 	.suspend		= ata_pci_device_suspend,
-	.resume			= atp8xx_reinit_one,
+	.resume			= ata_pci_device_resume,
 #endif
 };
 
Index: b/drivers/ata/pata_cmd640.c
===================================================================
--- a/drivers/ata/pata_cmd640.c
+++ b/drivers/ata/pata_cmd640.c
@@ -178,8 +178,9 @@  static struct ata_port_operations cmd640
 	.port_start	= cmd640_port_start,
 };
 
-static void cmd640_hardware_init(struct pci_dev *pdev)
+static int cmd640_hardware_init(struct device *dev)
 {
+	struct pci_dev *pdev = to_pci_dev(dev);
 	u8 r;
 	u8 ctrl;
 
@@ -205,6 +206,8 @@  static void cmd640_hardware_init(struct
 	pci_read_config_byte(pdev, ARTIM23, &ctrl);
 	ctrl |= 0x0C;
 	pci_write_config_byte(pdev, ARTIM23, ctrl);
+
+	return 0;
 }
 
 static int cmd640_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
@@ -221,25 +224,11 @@  static int cmd640_init_one(struct pci_de
 	if (rc)
 		return rc;
 
-	cmd640_hardware_init(pdev);
-
-	return ata_pci_sff_init_one(pdev, ppi, &cmd640_sht, NULL);
-}
-
-#ifdef CONFIG_PM
-static int cmd640_reinit_one(struct pci_dev *pdev)
-{
-	struct ata_host *host = dev_get_drvdata(&pdev->dev);
-	int rc;
+	cmd640_hardware_init(&pdev->dev);
 
-	rc = ata_pci_device_do_resume(pdev);
-	if (rc)
-		return rc;
-	cmd640_hardware_init(pdev);
-	ata_host_resume(host);
-	return 0;
+	return __ata_pci_sff_init_one(pdev, ppi, &cmd640_sht, NULL,
+				      cmd640_hardware_init);
 }
-#endif
 
 static const struct pci_device_id cmd640[] = {
 	{ PCI_VDEVICE(CMD, 0x640), 0 },
@@ -253,7 +242,7 @@  static struct pci_driver cmd640_pci_driv
 	.remove		= ata_pci_remove_one,
 #ifdef CONFIG_PM
 	.suspend	= ata_pci_device_suspend,
-	.resume		= cmd640_reinit_one,
+	.resume		= ata_pci_device_resume,
 #endif
 };
 
Index: b/drivers/ata/pata_cmd64x.c
===================================================================
--- a/drivers/ata/pata_cmd64x.c
+++ b/drivers/ata/pata_cmd64x.c
@@ -328,8 +328,9 @@  static struct ata_port_operations cmd648
 	.cable_detect	= cmd648_cable_detect,
 };
 
-static void cmd64x_fixup(struct pci_dev *pdev)
+static int cmd64x_fixup(struct device *dev)
 {
+	struct pci_dev *pdev = to_pci_dev(dev);
 	u8 mrdmode;
 
 	pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 64);
@@ -342,6 +343,8 @@  static void cmd64x_fixup(struct pci_dev
 #ifdef CONFIG_PPC
 	pci_write_config_byte(pdev, UDIDETCR0, 0xF0);
 #endif
+
+	return 0;
 }
 
 static int cmd64x_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
@@ -411,27 +414,11 @@  static int cmd64x_init_one(struct pci_de
 			ppi[0] = &cmd_info[3];
 	}
 
-	cmd64x_fixup(pdev);
-
-	return ata_pci_sff_init_one(pdev, ppi, &cmd64x_sht, NULL);
-}
-
-#ifdef CONFIG_PM
-static int cmd64x_reinit_one(struct pci_dev *pdev)
-{
-	struct ata_host *host = dev_get_drvdata(&pdev->dev);
-	int rc;
-
-	rc = ata_pci_device_do_resume(pdev);
-	if (rc)
-		return rc;
+	cmd64x_fixup(&pdev->dev);
 
-	cmd64x_fixup(pdev);
-
-	ata_host_resume(host);
-	return 0;
+	return __ata_pci_sff_init_one(pdev, ppi, &cmd64x_sht, NULL,
+				      cmd64x_fixup);
 }
-#endif
 
 static const struct pci_device_id cmd64x[] = {
 	{ PCI_VDEVICE(CMD, PCI_DEVICE_ID_CMD_643), 0 },
@@ -449,7 +436,7 @@  static struct pci_driver cmd64x_pci_driv
 	.remove		= ata_pci_remove_one,
 #ifdef CONFIG_PM
 	.suspend	= ata_pci_device_suspend,
-	.resume		= cmd64x_reinit_one,
+	.resume		= ata_pci_device_resume,
 #endif
 };
 
Index: b/drivers/ata/pata_cs5530.c
===================================================================
--- a/drivers/ata/pata_cs5530.c
+++ b/drivers/ata/pata_cs5530.c
@@ -198,12 +198,13 @@  static int cs5530_is_palmax(void)
 
 /**
  *	cs5530_init_chip	-	Chipset init
+ *	@gendev: device
  *
  *	Perform the chip initialisation work that is shared between both
  *	setup and resume paths
  */
 
-static int cs5530_init_chip(void)
+static int cs5530_init_chip(struct device *gendev)
 {
 	struct pci_dev *master_0 = NULL, *cs5530_0 = NULL, *dev = NULL;
 
@@ -281,7 +282,7 @@  fail_put:
 		pci_dev_put(master_0);
 	if (cs5530_0)
 		pci_dev_put(cs5530_0);
-	return -ENODEV;
+	return -EIO;
 }
 
 /**
@@ -317,35 +318,17 @@  static int cs5530_init_one(struct pci_de
 		return rc;
 
 	/* Chip initialisation */
-	if (cs5530_init_chip())
+	if (cs5530_init_chip(NULL))
 		return -ENODEV;
 
 	if (cs5530_is_palmax())
 		ppi[1] = &info_palmax_secondary;
 
 	/* Now kick off ATA set up */
-	return ata_pci_sff_init_one(pdev, ppi, &cs5530_sht, NULL);
+	return __ata_pci_sff_init_one(pdev, ppi, &cs5530_sht, NULL,
+				      cs5530_init_chip);
 }
 
-#ifdef CONFIG_PM
-static int cs5530_reinit_one(struct pci_dev *pdev)
-{
-	struct ata_host *host = dev_get_drvdata(&pdev->dev);
-	int rc;
-
-	rc = ata_pci_device_do_resume(pdev);
-	if (rc)
-		return rc;
-
-	/* If we fail on resume we are doomed */
-	if (cs5530_init_chip())
-		return -EIO;
-
-	ata_host_resume(host);
-	return 0;
-}
-#endif /* CONFIG_PM */
-
 static const struct pci_device_id cs5530[] = {
 	{ PCI_VDEVICE(CYRIX, PCI_DEVICE_ID_CYRIX_5530_IDE), },
 
@@ -359,7 +342,7 @@  static struct pci_driver cs5530_pci_driv
 	.remove		= ata_pci_remove_one,
 #ifdef CONFIG_PM
 	.suspend	= ata_pci_device_suspend,
-	.resume		= cs5530_reinit_one,
+	.resume		= ata_pci_device_resume,
 #endif
 };
 
Index: b/drivers/ata/pata_hpt366.c
===================================================================
--- a/drivers/ata/pata_hpt366.c
+++ b/drivers/ata/pata_hpt366.c
@@ -292,15 +292,17 @@  static struct ata_port_operations hpt366
 
 /**
  *	hpt36x_init_chipset	-	common chip setup
- *	@dev: PCI device
+ *	@gendev: device
  *
  *	Perform the chip setup work that must be done at both init and
  *	resume time
  */
 
-static void hpt36x_init_chipset(struct pci_dev *dev)
+static int hpt36x_init_chipset(struct device *gendev)
 {
+	struct pci_dev *dev = to_pci_dev(gendev);
 	u8 drive_fast;
+
 	pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, (L1_CACHE_BYTES / 4));
 	pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x78);
 	pci_write_config_byte(dev, PCI_MIN_GNT, 0x08);
@@ -309,6 +311,8 @@  static void hpt36x_init_chipset(struct p
 	pci_read_config_byte(dev, 0x51, &drive_fast);
 	if (drive_fast & 0x80)
 		pci_write_config_byte(dev, 0x51, drive_fast & ~0x80);
+
+	return 0;
 }
 
 /**
@@ -360,7 +364,7 @@  static int hpt36x_init_one(struct pci_de
 	if (class_rev > 2)
 			return -ENODEV;
 
-	hpt36x_init_chipset(dev);
+	hpt36x_init_chipset(&dev->dev);
 
 	pci_read_config_dword(dev, 0x40,  &reg1);
 
@@ -378,23 +382,9 @@  static int hpt36x_init_one(struct pci_de
 			break;
 	}
 	/* Now kick off ATA set up */
-	return ata_pci_sff_init_one(dev, ppi, &hpt36x_sht, hpriv);
-}
-
-#ifdef CONFIG_PM
-static int hpt36x_reinit_one(struct pci_dev *dev)
-{
-	struct ata_host *host = dev_get_drvdata(&dev->dev);
-	int rc;
-
-	rc = ata_pci_device_do_resume(dev);
-	if (rc)
-		return rc;
-	hpt36x_init_chipset(dev);
-	ata_host_resume(host);
-	return 0;
+	return __ata_pci_sff_init_one(dev, ppi, &hpt36x_sht, hpriv,
+				      hpt36x_init_chipset);
 }
-#endif
 
 static const struct pci_device_id hpt36x[] = {
 	{ PCI_VDEVICE(TTI, PCI_DEVICE_ID_TTI_HPT366), },
@@ -408,7 +398,7 @@  static struct pci_driver hpt36x_pci_driv
 	.remove		= ata_pci_remove_one,
 #ifdef CONFIG_PM
 	.suspend	= ata_pci_device_suspend,
-	.resume		= hpt36x_reinit_one,
+	.resume		= ata_pci_device_resume,
 #endif
 };
 
Index: b/drivers/ata/pata_hpt3x3.c
===================================================================
--- a/drivers/ata/pata_hpt3x3.c
+++ b/drivers/ata/pata_hpt3x3.c
@@ -156,14 +156,16 @@  static struct ata_port_operations hpt3x3
 
 /**
  *	hpt3x3_init_chipset	-	chip setup
- *	@dev: PCI device
+ *	@gendev: device
  *
  *	Perform the setup required at boot and on resume.
  */
 
-static void hpt3x3_init_chipset(struct pci_dev *dev)
+static int hpt3x3_init_chipset(struct device *gendev)
 {
+	struct pci_dev *dev = to_pci_dev(gendev);
 	u16 cmd;
+
 	/* Initialize the board */
 	pci_write_config_word(dev, 0x80, 0x00);
 	/* Check if it is a 343 or a 363. 363 has COMMAND_MEMORY set */
@@ -172,6 +174,8 @@  static void hpt3x3_init_chipset(struct p
 		pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0xF0);
 	else
 		pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x20);
+
+	return 0;
 }
 
 /**
@@ -204,7 +208,7 @@  static int hpt3x3_init_one(struct pci_de
 	int i, rc;
 	void __iomem *base;
 
-	hpt3x3_init_chipset(pdev);
+	hpt3x3_init_chipset(&pdev->dev);
 
 	if (!printed_version++)
 		dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n");
@@ -212,6 +216,9 @@  static int hpt3x3_init_one(struct pci_de
 	host = ata_host_alloc_pinfo(&pdev->dev, ppi, 2);
 	if (!host)
 		return -ENOMEM;
+
+	host->init_host = hpt3x3_init_chipset;
+
 	/* acquire resources and fill host */
 	rc = pcim_enable_device(pdev);
 	if (rc)
@@ -252,23 +259,6 @@  static int hpt3x3_init_one(struct pci_de
 				 IRQF_SHARED, &hpt3x3_sht);
 }
 
-#ifdef CONFIG_PM
-static int hpt3x3_reinit_one(struct pci_dev *dev)
-{
-	struct ata_host *host = dev_get_drvdata(&dev->dev);
-	int rc;
-
-	rc = ata_pci_device_do_resume(dev);
-	if (rc)
-		return rc;
-
-	hpt3x3_init_chipset(dev);
-
-	ata_host_resume(host);
-	return 0;
-}
-#endif
-
 static const struct pci_device_id hpt3x3[] = {
 	{ PCI_VDEVICE(TTI, PCI_DEVICE_ID_TTI_HPT343), },
 
@@ -282,7 +272,7 @@  static struct pci_driver hpt3x3_pci_driv
 	.remove		= ata_pci_remove_one,
 #ifdef CONFIG_PM
 	.suspend	= ata_pci_device_suspend,
-	.resume		= hpt3x3_reinit_one,
+	.resume		= ata_pci_device_resume,
 #endif
 };
 
Index: b/drivers/ata/pata_it821x.c
===================================================================
--- a/drivers/ata/pata_it821x.c
+++ b/drivers/ata/pata_it821x.c
@@ -868,6 +868,15 @@  static void it821x_disable_raid(struct p
 	pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0x20);
 }
 
+static int it821x_fixup(struct device *dev)
+{
+	struct pci_dev *pdev = to_pci_dev(dev);
+
+	if (pdev->vendor != PCI_VENDOR_ID_RDC && it8212_noraid)
+		it821x_disable_raid(pdev);
+
+	return 0;
+}
 
 static int it821x_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
 {
@@ -932,26 +941,10 @@  static int it821x_init_one(struct pci_de
 		else
 			ppi[0] = &info_smart;
 	}
-	return ata_pci_sff_init_one(pdev, ppi, &it821x_sht, NULL);
+	return __ata_pci_sff_init_one(pdev, ppi, &it821x_sht, NULL,
+				      it821x_fixup);
 }
 
-#ifdef CONFIG_PM
-static int it821x_reinit_one(struct pci_dev *pdev)
-{
-	struct ata_host *host = dev_get_drvdata(&pdev->dev);
-	int rc;
-
-	rc = ata_pci_device_do_resume(pdev);
-	if (rc)
-		return rc;
-	/* Resume - turn raid back off if need be */
-	if (it8212_noraid)
-		it821x_disable_raid(pdev);
-	ata_host_resume(host);
-	return rc;
-}
-#endif
-
 static const struct pci_device_id it821x[] = {
 	{ PCI_VDEVICE(ITE, PCI_DEVICE_ID_ITE_8211), },
 	{ PCI_VDEVICE(ITE, PCI_DEVICE_ID_ITE_8212), },
@@ -967,7 +960,7 @@  static struct pci_driver it821x_pci_driv
 	.remove		= ata_pci_remove_one,
 #ifdef CONFIG_PM
 	.suspend	= ata_pci_device_suspend,
-	.resume		= it821x_reinit_one,
+	.resume		= ata_pci_device_resume,
 #endif
 };
 
Index: b/drivers/ata/pata_ninja32.c
===================================================================
--- a/drivers/ata/pata_ninja32.c
+++ b/drivers/ata/pata_ninja32.c
@@ -89,8 +89,11 @@  static struct ata_port_operations ninja3
 	.sff_data_xfer	= ata_sff_data_xfer32
 };
 
-static void ninja32_program(void __iomem *base)
+static int ninja32_program(struct device *dev)
 {
+	struct ata_host *host = dev_get_drvdata(dev);
+	void __iomem *base = host->iomap[0];
+
 	iowrite8(0x05, base + 0x01);	/* Enable interrupt lines */
 	iowrite8(0xBE, base + 0x02);	/* Burst, ?? setup */
 	iowrite8(0x01, base + 0x03);	/* Unknown */
@@ -98,6 +101,8 @@  static void ninja32_program(void __iomem
 	iowrite8(0x8f, base + 0x05);	/* Unknown */
 	iowrite8(0xa4, base + 0x1c);	/* Unknown */
 	iowrite8(0x83, base + 0x1d);	/* BMDMA control: WAIT0 */
+
+	return 0;
 }
 
 static int ninja32_init_one(struct pci_dev *dev, const struct pci_device_id *id)
@@ -110,6 +115,8 @@  static int ninja32_init_one(struct pci_d
 	host = ata_host_alloc(&dev->dev, 1);
 	if (!host)
 		return -ENOMEM;
+
+	host->init_host = ninja32_program;
 	ap = host->ports[0];
 
 	/* Set up the PCI device */
@@ -147,28 +154,13 @@  static int ninja32_init_one(struct pci_d
 	ata_sff_std_ports(&ap->ioaddr);
 	ap->pflags = ATA_PFLAG_PIO32 | ATA_PFLAG_PIO32CHANGE;
 
-	ninja32_program(base);
+	ninja32_program(&dev->dev);
+
 	/* FIXME: Should we disable them at remove ? */
 	return ata_host_activate(host, dev->irq, ata_sff_interrupt,
 				 IRQF_SHARED, &ninja32_sht);
 }
 
-#ifdef CONFIG_PM
-
-static int ninja32_reinit_one(struct pci_dev *pdev)
-{
-	struct ata_host *host = dev_get_drvdata(&pdev->dev);
-	int rc;
-
-	rc = ata_pci_device_do_resume(pdev);
-	if (rc)
-		return rc;
-	ninja32_program(host->iomap[0]);
-	ata_host_resume(host);
-	return 0;			
-}
-#endif
-
 static const struct pci_device_id ninja32[] = {
 	{ 0x10FC, 0x0003, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
 	{ 0x1145, 0x8008, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
@@ -186,7 +178,7 @@  static struct pci_driver ninja32_pci_dri
 	.remove		= ata_pci_remove_one,
 #ifdef CONFIG_PM
 	.suspend	= ata_pci_device_suspend,
-	.resume		= ninja32_reinit_one,
+	.resume		= ata_pci_device_resume,
 #endif
 };
 
Index: b/drivers/ata/pata_ns87415.c
===================================================================
--- a/drivers/ata/pata_ns87415.c
+++ b/drivers/ata/pata_ns87415.c
@@ -325,12 +325,16 @@  static struct scsi_host_template ns87415
 	ATA_BMDMA_SHT(DRV_NAME),
 };
 
-static void ns87415_fixup(struct pci_dev *pdev)
+static int ns87415_fixup(struct device *dev)
 {
+	struct pci_dev *pdev = to_pci_dev(dev);
+
 	/* Select 512 byte sectors */
 	pci_write_config_byte(pdev, 0x55, 0xEE);
 	/* Select PIO0 8bit clocking */
 	pci_write_config_byte(pdev, 0x54, 0xB7);
+
+	return 0;
 }
 
 /**
@@ -378,9 +382,10 @@  static int ns87415_init_one (struct pci_
 	if (rc)
 		return rc;
 
-	ns87415_fixup(pdev);
+	ns87415_fixup(&pdev->dev);
 
-	return ata_pci_sff_init_one(pdev, ppi, &ns87415_sht, NULL);
+	return __ata_pci_sff_init_one(pdev, ppi, &ns87415_sht, NULL,
+				      ns87415_fixup);
 }
 
 static const struct pci_device_id ns87415_pci_tbl[] = {
@@ -389,23 +394,6 @@  static const struct pci_device_id ns8741
 	{ }	/* terminate list */
 };
 
-#ifdef CONFIG_PM
-static int ns87415_reinit_one(struct pci_dev *pdev)
-{
-	struct ata_host *host = dev_get_drvdata(&pdev->dev);
-	int rc;
-
-	rc = ata_pci_device_do_resume(pdev);
-	if (rc)
-		return rc;
-
-	ns87415_fixup(pdev);
-
-	ata_host_resume(host);
-	return 0;
-}
-#endif
-
 static struct pci_driver ns87415_pci_driver = {
 	.name			= DRV_NAME,
 	.id_table		= ns87415_pci_tbl,
@@ -413,7 +401,7 @@  static struct pci_driver ns87415_pci_dri
 	.remove			= ata_pci_remove_one,
 #ifdef CONFIG_PM
 	.suspend		= ata_pci_device_suspend,
-	.resume			= ns87415_reinit_one,
+	.resume			= ata_pci_device_resume,
 #endif
 };
 
Index: b/drivers/ata/pata_pdc2027x.c
===================================================================
--- a/drivers/ata/pata_pdc2027x.c
+++ b/drivers/ata/pata_pdc2027x.c
@@ -63,7 +63,6 @@  enum {
 };
 
 static int pdc2027x_init_one(struct pci_dev *pdev, const struct pci_device_id *ent);
-static int pdc2027x_reinit_one(struct pci_dev *pdev);
 static int pdc2027x_prereset(struct ata_link *link, unsigned long deadline);
 static void pdc2027x_set_piomode(struct ata_port *ap, struct ata_device *adev);
 static void pdc2027x_set_dmamode(struct ata_port *ap, struct ata_device *adev);
@@ -129,7 +128,7 @@  static struct pci_driver pdc2027x_pci_dr
 	.remove			= ata_pci_remove_one,
 #ifdef CONFIG_PM
 	.suspend		= ata_pci_device_suspend,
-	.resume			= pdc2027x_reinit_one,
+	.resume			= ata_pci_device_resume,
 #endif
 };
 
@@ -647,13 +646,21 @@  static long pdc_detect_pll_input_clock(s
 
 /**
  * pdc_hardware_init - Initialize the hardware.
- * @host: target ATA host
- * @board_idx: board identifier
+ * @dev: device
  */
-static int pdc_hardware_init(struct ata_host *host, unsigned int board_idx)
+static int pdc_hardware_init(struct device *dev)
 {
+	struct pci_dev *pdev = to_pci_dev(dev);
+	struct ata_host *host = dev_get_drvdata(dev);
+	unsigned int board_idx;
 	long pll_clock;
 
+	if (pdev->device == PCI_DEVICE_ID_PROMISE_20268 ||
+	    pdev->device == PCI_DEVICE_ID_PROMISE_20270)
+		board_idx = PDC_UDMA_100;
+	else
+		board_idx = PDC_UDMA_133;
+
 	/*
 	 * Detect PLL input clock rate.
 	 * On some system, where PCI bus is running at non-standard clock rate.
@@ -722,6 +729,8 @@  static int __devinit pdc2027x_init_one(s
 	if (!host)
 		return -ENOMEM;
 
+	host->init_host = pdc_hardware_init;
+
 	/* acquire resources and fill host */
 	rc = pcim_enable_device(pdev);
 	if (rc)
@@ -755,7 +764,7 @@  static int __devinit pdc2027x_init_one(s
 	//pci_enable_intx(pdev);
 
 	/* initialize adapter */
-	if (pdc_hardware_init(host, board_idx) != 0)
+	if (pdc_hardware_init(&pdev->dev))
 		return -EIO;
 
 	pci_set_master(pdev);
@@ -763,31 +772,6 @@  static int __devinit pdc2027x_init_one(s
 				 IRQF_SHARED, &pdc2027x_sht);
 }
 
-#ifdef CONFIG_PM
-static int pdc2027x_reinit_one(struct pci_dev *pdev)
-{
-	struct ata_host *host = dev_get_drvdata(&pdev->dev);
-	unsigned int board_idx;
-	int rc;
-
-	rc = ata_pci_device_do_resume(pdev);
-	if (rc)
-		return rc;
-
-	if (pdev->device == PCI_DEVICE_ID_PROMISE_20268 ||
-	    pdev->device == PCI_DEVICE_ID_PROMISE_20270)
-		board_idx = PDC_UDMA_100;
-	else
-		board_idx = PDC_UDMA_133;
-
-	if (pdc_hardware_init(host, board_idx))
-		return -EIO;
-
-	ata_host_resume(host);
-	return 0;
-}
-#endif
-
 /**
  * pdc2027x_init - Called after this module is loaded into the kernel.
  */
Index: b/drivers/ata/pata_sl82c105.c
===================================================================
--- a/drivers/ata/pata_sl82c105.c
+++ b/drivers/ata/pata_sl82c105.c
@@ -279,13 +279,16 @@  static int sl82c105_bridge_revision(stru
 	return bridge->revision;
 }
 
-static void sl82c105_fixup(struct pci_dev *pdev)
+static int sl82c105_fixup(struct device *dev)
 {
+	struct pci_dev *pdev = to_pci_dev(dev);
 	u32 val;
 
 	pci_read_config_dword(pdev, 0x40, &val);
 	val |= CTRL_P0EN | CTRL_P0F16 | CTRL_P1F16;
 	pci_write_config_dword(pdev, 0x40, val);
+
+	return 0;
 }
 
 static int sl82c105_init_one(struct pci_dev *dev, const struct pci_device_id *id)
@@ -320,27 +323,11 @@  static int sl82c105_init_one(struct pci_
 	else
 		ppi[0] = &info_dma;
 
-	sl82c105_fixup(dev);
-
-	return ata_pci_sff_init_one(dev, ppi, &sl82c105_sht, NULL);
-}
-
-#ifdef CONFIG_PM
-static int sl82c105_reinit_one(struct pci_dev *pdev)
-{
-	struct ata_host *host = dev_get_drvdata(&pdev->dev);
-	int rc;
-
-	rc = ata_pci_device_do_resume(pdev);
-	if (rc)
-		return rc;
+	sl82c105_fixup(&dev->dev);
 
-	sl82c105_fixup(pdev);
-
-	ata_host_resume(host);
-	return 0;
+	return __ata_pci_sff_init_one(dev, ppi, &sl82c105_sht, NULL,
+				      sl82c105_fixup);
 }
-#endif
 
 static const struct pci_device_id sl82c105[] = {
 	{ PCI_VDEVICE(WINBOND, PCI_DEVICE_ID_WINBOND_82C105), },
@@ -355,7 +342,7 @@  static struct pci_driver sl82c105_pci_dr
 	.remove		= ata_pci_remove_one,
 #ifdef CONFIG_PM
 	.suspend	= ata_pci_device_suspend,
-	.resume		= sl82c105_reinit_one,
+	.resume		= ata_pci_device_resume,
 #endif
 };
 
Index: b/drivers/ata/sata_sil.c
===================================================================
--- a/drivers/ata/sata_sil.c
+++ b/drivers/ata/sata_sil.c
@@ -114,9 +114,6 @@  enum {
 };
 
 static int sil_init_one(struct pci_dev *pdev, const struct pci_device_id *ent);
-#ifdef CONFIG_PM
-static int sil_pci_device_resume(struct pci_dev *pdev);
-#endif
 static void sil_dev_config(struct ata_device *dev);
 static int sil_scr_read(struct ata_link *link, unsigned int sc_reg, u32 *val);
 static int sil_scr_write(struct ata_link *link, unsigned int sc_reg, u32 val);
@@ -169,7 +166,7 @@  static struct pci_driver sil_pci_driver
 	.remove			= ata_pci_remove_one,
 #ifdef CONFIG_PM
 	.suspend		= ata_pci_device_suspend,
-	.resume			= sil_pci_device_resume,
+	.resume			= ata_pci_device_resume,
 #endif
 };
 
@@ -663,9 +660,10 @@  static void sil_dev_config(struct ata_de
 	}
 }
 
-static void sil_init_controller(struct ata_host *host)
+static int sil_init_controller(struct device *dev)
 {
-	struct pci_dev *pdev = to_pci_dev(host->dev);
+	struct ata_host *host = dev_get_drvdata(dev);
+	struct pci_dev *pdev = to_pci_dev(dev);
 	void __iomem *mmio_base = host->iomap[SIL_MMIO_BAR];
 	u8 cls;
 	u32 tmp;
@@ -707,6 +705,8 @@  static void sil_init_controller(struct a
 			writel(tmp | SIL_INTR_STEERING,
 			       mmio_base + sil_port[2].bmdma);
 	}
+
+	return 0;
 }
 
 static bool sil_broken_system_poweroff(struct pci_dev *pdev)
@@ -765,6 +765,8 @@  static int sil_init_one(struct pci_dev *
 	if (!host)
 		return -ENOMEM;
 
+	host->init_host = sil_init_controller;
+
 	/* acquire resources and fill host */
 	rc = pcim_enable_device(pdev);
 	if (rc)
@@ -802,30 +804,13 @@  static int sil_init_one(struct pci_dev *
 	}
 
 	/* initialize and activate */
-	sil_init_controller(host);
+	sil_init_controller(&pdev->dev);
 
 	pci_set_master(pdev);
 	return ata_host_activate(host, pdev->irq, sil_interrupt, IRQF_SHARED,
 				 &sil_sht);
 }
 
-#ifdef CONFIG_PM
-static int sil_pci_device_resume(struct pci_dev *pdev)
-{
-	struct ata_host *host = dev_get_drvdata(&pdev->dev);
-	int rc;
-
-	rc = ata_pci_device_do_resume(pdev);
-	if (rc)
-		return rc;
-
-	sil_init_controller(host);
-	ata_host_resume(host);
-
-	return 0;
-}
-#endif
-
 static int __init sil_init(void)
 {
 	return pci_register_driver(&sil_pci_driver);
Index: b/include/linux/libata.h
===================================================================
--- a/include/linux/libata.h
+++ b/include/linux/libata.h
@@ -526,6 +526,7 @@  struct ata_host {
 	unsigned int		n_ports;
 	void			*private_data;
 	struct ata_port_operations *ops;
+	int			(*init_host)(struct device *dev);
 	unsigned long		flags;
 #ifdef CONFIG_ATA_ACPI
 	acpi_handle		acpi_handle;
@@ -1637,9 +1638,16 @@  extern int ata_pci_sff_prepare_host(stru
 extern int ata_pci_sff_activate_host(struct ata_host *host,
 				     irq_handler_t irq_handler,
 				     struct scsi_host_template *sht);
-extern int ata_pci_sff_init_one(struct pci_dev *pdev,
-				const struct ata_port_info * const * ppi,
-				struct scsi_host_template *sht, void *host_priv);
+extern int __ata_pci_sff_init_one(struct pci_dev *pdev,
+				const struct ata_port_info * const *ppi,
+				struct scsi_host_template *sht, void *host_priv,
+				int (*init_host)(struct device *dev));
+static inline int ata_pci_sff_init_one(struct pci_dev *pdev,
+				const struct ata_port_info * const *ppi,
+				struct scsi_host_template *sht, void *host_priv)
+{
+	return __ata_pci_sff_init_one(pdev, ppi, sht, host_priv, NULL);
+}
 #endif /* CONFIG_PCI */
 
 /**