linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [git patches] libata update
@ 2006-06-27  1:24 Jeff Garzik
  2006-06-28  1:23 ` Linus Torvalds
  0 siblings, 1 reply; 15+ messages in thread
From: Jeff Garzik @ 2006-06-27  1:24 UTC (permalink / raw)
  To: Andrew Morton, Linus Torvalds; +Cc: linux-ide, linux-kernel


Bug fixes, better suspend/resume prep, bump versions.

Also, a drivers/ide patch that Andrew queued for me.  This is an
exception, rather than a rule...  I'm not interested in patching
drivers/ide in general, and don't want other patches to start coming
my way.


Please pull from 'upstream-linus' branch of
master.kernel.org:/pub/scm/linux/kernel/git/jgarzik/libata-dev.git

to receive the following updates:

 drivers/ide/pci/amd74xx.c  |    7 +-
 drivers/scsi/Kconfig       |    2 
 drivers/scsi/ahci.c        |    2 
 drivers/scsi/ata_piix.c    |    2 
 drivers/scsi/libata-core.c |  151 ++++++++++++++++++++++++++++-----------------
 drivers/scsi/libata-eh.c   |   63 +++++++++++-------
 drivers/scsi/libata.h      |    4 -
 drivers/scsi/sata_nv.c     |    2 
 drivers/scsi/sata_sil.c    |   31 +++++++--
 drivers/scsi/sata_sil24.c  |    2 
 drivers/scsi/sata_svw.c    |    2 
 drivers/scsi/sata_uli.c    |    2 
 drivers/scsi/sata_via.c    |    2 
 drivers/scsi/sata_vsc.c    |   12 +--
 include/linux/libata.h     |   15 ++++
 include/linux/pci_ids.h    |    2 
 16 files changed, 191 insertions(+), 110 deletions(-)

Andrew Morton:
      libata.h needs scatterlist.h
      libata reduce timeouts

Auke Kok:
      ata_piix: add ICH6/7/8 to Kconfig

Jeff Garzik:
      [libata] Bump versions
      [libata] sata_vsc: partially revert a PCI ID-related commit

Randy Dunlap:
      ata: add some NVIDIA chipset IDs

Tejun Heo:
      libata: move ata_eh_clear_action() upward
      libata: implement and use ata_deh_dev_action()
      libata: clear EH action on device detach
      libata: move ata_do_simple_cmd() below ata_exec_internal()
      libata: update ata_do_simple_cmd()
      libata: make two functions global
      libata: implement ata_port_max_devices()
      libata: cosmetic updates
      sata_sil: disable hotplug interrupts on two ATI IXPs

diff --git a/drivers/ide/pci/amd74xx.c b/drivers/ide/pci/amd74xx.c
index 6e9dbf4..85007cb 100644
--- a/drivers/ide/pci/amd74xx.c
+++ b/drivers/ide/pci/amd74xx.c
@@ -75,6 +75,7 @@ static struct amd_ide_chip {
 	{ PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_IDE,	0x50, AMD_UDMA_133 },
 	{ PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_IDE,	0x50, AMD_UDMA_133 },
 	{ PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_IDE,	0x50, AMD_UDMA_133 },
+	{ PCI_DEVICE_ID_NVIDIA_NFORCE_MCP65_IDE,	0x50, AMD_UDMA_133 },
 	{ PCI_DEVICE_ID_AMD_CS5536_IDE,			0x40, AMD_UDMA_100 },
 	{ 0 }
 };
@@ -490,7 +491,8 @@ static ide_pci_device_t amd74xx_chipsets
 	/* 15 */ DECLARE_NV_DEV("NFORCE-MCP51"),
 	/* 16 */ DECLARE_NV_DEV("NFORCE-MCP55"),
 	/* 17 */ DECLARE_NV_DEV("NFORCE-MCP61"),
-	/* 18 */ DECLARE_AMD_DEV("AMD5536"),
+	/* 18 */ DECLARE_NV_DEV("NFORCE-MCP65"),
+	/* 19 */ DECLARE_AMD_DEV("AMD5536"),
 };
 
 static int __devinit amd74xx_probe(struct pci_dev *dev, const struct pci_device_id *id)
@@ -528,7 +530,8 @@ #endif
 	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_IDE,	PCI_ANY_ID, PCI_ANY_ID, 0, 0, 15 },
 	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_IDE,	PCI_ANY_ID, PCI_ANY_ID, 0, 0, 16 },
 	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_IDE,	PCI_ANY_ID, PCI_ANY_ID, 0, 0, 17 },
-	{ PCI_VENDOR_ID_AMD,	PCI_DEVICE_ID_AMD_CS5536_IDE,		PCI_ANY_ID, PCI_ANY_ID, 0, 0, 18 },
+	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP65_IDE,  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 18 },
+	{ PCI_VENDOR_ID_AMD,	PCI_DEVICE_ID_AMD_CS5536_IDE,		PCI_ANY_ID, PCI_ANY_ID, 0, 0, 19 },
 	{ 0, },
 };
 MODULE_DEVICE_TABLE(pci, amd74xx_pci_tbl);
diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig
index c84b02a..96a81cd 100644
--- a/drivers/scsi/Kconfig
+++ b/drivers/scsi/Kconfig
@@ -501,7 +501,7 @@ config SCSI_ATA_PIIX
 	tristate "Intel PIIX/ICH SATA support"
 	depends on SCSI_SATA && PCI
 	help
-	  This option enables support for ICH5 Serial ATA.
+	  This option enables support for ICH5/6/7/8 Serial ATA.
 	  If PATA support was enabled previously, this enables
 	  support for select Intel PIIX/ICH PATA host controllers.
 
diff --git a/drivers/scsi/ahci.c b/drivers/scsi/ahci.c
index 4bb77f6..f059467 100644
--- a/drivers/scsi/ahci.c
+++ b/drivers/scsi/ahci.c
@@ -48,7 +48,7 @@ #include <linux/libata.h>
 #include <asm/io.h>
 
 #define DRV_NAME	"ahci"
-#define DRV_VERSION	"1.3"
+#define DRV_VERSION	"2.0"
 
 
 enum {
diff --git a/drivers/scsi/ata_piix.c b/drivers/scsi/ata_piix.c
index 521b718..94b1261 100644
--- a/drivers/scsi/ata_piix.c
+++ b/drivers/scsi/ata_piix.c
@@ -93,7 +93,7 @@ #include <scsi/scsi_host.h>
 #include <linux/libata.h>
 
 #define DRV_NAME	"ata_piix"
-#define DRV_VERSION	"1.10"
+#define DRV_VERSION	"2.00"
 
 enum {
 	PIIX_IOCFG		= 0x54, /* IDE I/O configuration register */
diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c
index 6c66877..47fff7b 100644
--- a/drivers/scsi/libata-core.c
+++ b/drivers/scsi/libata-core.c
@@ -88,6 +88,10 @@ int libata_fua = 0;
 module_param_named(fua, libata_fua, int, 0444);
 MODULE_PARM_DESC(fua, "FUA support (0=off, 1=on)");
 
+static int ata_probe_timeout = ATA_TMOUT_INTERNAL / HZ;
+module_param(ata_probe_timeout, int, 0444);
+MODULE_PARM_DESC(ata_probe_timeout, "Set ATA probing timeout (seconds)");
+
 MODULE_AUTHOR("Jeff Garzik");
 MODULE_DESCRIPTION("Library module for ATA devices");
 MODULE_LICENSE("GPL");
@@ -777,11 +781,9 @@ void ata_std_dev_select (struct ata_port
 void ata_dev_select(struct ata_port *ap, unsigned int device,
 			   unsigned int wait, unsigned int can_sleep)
 {
-	if (ata_msg_probe(ap)) {
+	if (ata_msg_probe(ap))
 		ata_port_printk(ap, KERN_INFO, "ata_dev_select: ENTER, ata%u: "
-				"device %u, wait %u\n",
-				ap->id, device, wait);
-	}
+				"device %u, wait %u\n", ap->id, device, wait);
 
 	if (wait)
 		ata_wait_idle(ap);
@@ -950,7 +952,8 @@ void ata_port_flush_task(struct ata_port
 	 */
 	if (!cancel_delayed_work(&ap->port_task)) {
 		if (ata_msg_ctl(ap))
-			ata_port_printk(ap, KERN_DEBUG, "%s: flush #2\n", __FUNCTION__);
+			ata_port_printk(ap, KERN_DEBUG, "%s: flush #2\n",
+					__FUNCTION__);
 		flush_workqueue(ata_wq);
 	}
 
@@ -1059,7 +1062,7 @@ unsigned ata_exec_internal(struct ata_de
 
 	spin_unlock_irqrestore(ap->lock, flags);
 
-	rc = wait_for_completion_timeout(&wait, ATA_TMOUT_INTERNAL);
+	rc = wait_for_completion_timeout(&wait, ata_probe_timeout);
 
 	ata_port_flush_task(ap);
 
@@ -1081,7 +1084,7 @@ unsigned ata_exec_internal(struct ata_de
 
 			if (ata_msg_warn(ap))
 				ata_dev_printk(dev, KERN_WARNING,
-				       "qc timeout (cmd 0x%x)\n", command);
+					"qc timeout (cmd 0x%x)\n", command);
 		}
 
 		spin_unlock_irqrestore(ap->lock, flags);
@@ -1093,9 +1096,9 @@ unsigned ata_exec_internal(struct ata_de
 
 	if (qc->flags & ATA_QCFLAG_FAILED && !qc->err_mask) {
 		if (ata_msg_warn(ap))
-			ata_dev_printk(dev, KERN_WARNING, 
+			ata_dev_printk(dev, KERN_WARNING,
 				"zero err_mask for failed "
-			       "internal command, assuming AC_ERR_OTHER\n");
+				"internal command, assuming AC_ERR_OTHER\n");
 		qc->err_mask |= AC_ERR_OTHER;
 	}
 
@@ -1132,6 +1135,33 @@ unsigned ata_exec_internal(struct ata_de
 }
 
 /**
+ *	ata_do_simple_cmd - execute simple internal command
+ *	@dev: Device to which the command is sent
+ *	@cmd: Opcode to execute
+ *
+ *	Execute a 'simple' command, that only consists of the opcode
+ *	'cmd' itself, without filling any other registers
+ *
+ *	LOCKING:
+ *	Kernel thread context (may sleep).
+ *
+ *	RETURNS:
+ *	Zero on success, AC_ERR_* mask on failure
+ */
+unsigned int ata_do_simple_cmd(struct ata_device *dev, u8 cmd)
+{
+	struct ata_taskfile tf;
+
+	ata_tf_init(dev, &tf);
+
+	tf.command = cmd;
+	tf.flags |= ATA_TFLAG_DEVICE;
+	tf.protocol = ATA_PROT_NODATA;
+
+	return ata_exec_internal(dev, &tf, NULL, DMA_NONE, NULL, 0);
+}
+
+/**
  *	ata_pio_need_iordy	-	check if iordy needed
  *	@adev: ATA device
  *
@@ -1193,8 +1223,8 @@ int ata_dev_read_id(struct ata_device *d
 	int rc;
 
 	if (ata_msg_ctl(ap))
-		ata_dev_printk(dev, KERN_DEBUG, "%s: ENTER, host %u, dev %u\n", 
-				__FUNCTION__, ap->id, dev->devno);
+		ata_dev_printk(dev, KERN_DEBUG, "%s: ENTER, host %u, dev %u\n",
+			       __FUNCTION__, ap->id, dev->devno);
 
 	ata_dev_select(ap, dev->devno, 1, 1); /* select device 0/1 */
 
@@ -1263,9 +1293,9 @@ int ata_dev_read_id(struct ata_device *d
 	return 0;
 
  err_out:
-	if (ata_msg_warn(ap)) 
+	if (ata_msg_warn(ap))
 		ata_dev_printk(dev, KERN_WARNING, "failed to IDENTIFY "
-		       "(%s, err_mask=0x%x)\n", reason, err_mask);
+			       "(%s, err_mask=0x%x)\n", reason, err_mask);
 	return rc;
 }
 
@@ -1318,19 +1348,21 @@ int ata_dev_configure(struct ata_device 
 	int i, rc;
 
 	if (!ata_dev_enabled(dev) && ata_msg_info(ap)) {
-		ata_dev_printk(dev, KERN_INFO, "%s: ENTER/EXIT (host %u, dev %u) -- nodev\n",
-			__FUNCTION__, ap->id, dev->devno);
+		ata_dev_printk(dev, KERN_INFO,
+			       "%s: ENTER/EXIT (host %u, dev %u) -- nodev\n",
+			       __FUNCTION__, ap->id, dev->devno);
 		return 0;
 	}
 
 	if (ata_msg_probe(ap))
-		ata_dev_printk(dev, KERN_DEBUG, "%s: ENTER, host %u, dev %u\n", 
-			__FUNCTION__, ap->id, dev->devno);
+		ata_dev_printk(dev, KERN_DEBUG, "%s: ENTER, host %u, dev %u\n",
+			       __FUNCTION__, ap->id, dev->devno);
 
 	/* print device capabilities */
 	if (ata_msg_probe(ap))
-		ata_dev_printk(dev, KERN_DEBUG, "%s: cfg 49:%04x 82:%04x 83:%04x "
-			       "84:%04x 85:%04x 86:%04x 87:%04x 88:%04x\n",
+		ata_dev_printk(dev, KERN_DEBUG,
+			       "%s: cfg 49:%04x 82:%04x 83:%04x 84:%04x "
+			       "85:%04x 86:%04x 87:%04x 88:%04x\n",
 			       __FUNCTION__,
 			       id[49], id[82], id[83], id[84],
 			       id[85], id[86], id[87], id[88]);
@@ -1402,14 +1434,16 @@ int ata_dev_configure(struct ata_device 
 					ata_id_major_version(id),
 					ata_mode_string(xfer_mask),
 					(unsigned long long)dev->n_sectors,
-					dev->cylinders, dev->heads, dev->sectors);
+					dev->cylinders, dev->heads,
+					dev->sectors);
 		}
 
 		if (dev->id[59] & 0x100) {
 			dev->multi_count = dev->id[59] & 0xff;
 			if (ata_msg_info(ap))
-				ata_dev_printk(dev, KERN_INFO, "ata%u: dev %u multi count %u\n",
-				ap->id, dev->devno, dev->multi_count);
+				ata_dev_printk(dev, KERN_INFO,
+					"ata%u: dev %u multi count %u\n",
+					ap->id, dev->devno, dev->multi_count);
 		}
 
 		dev->cdb_len = 16;
@@ -1422,8 +1456,8 @@ int ata_dev_configure(struct ata_device 
 		rc = atapi_cdb_len(id);
 		if ((rc < 12) || (rc > ATAPI_CDB_LEN)) {
 			if (ata_msg_warn(ap))
-				ata_dev_printk(dev, KERN_WARNING, 
-					"unsupported CDB len\n");
+				ata_dev_printk(dev, KERN_WARNING,
+					       "unsupported CDB len\n");
 			rc = -EINVAL;
 			goto err_out_nosup;
 		}
@@ -1466,8 +1500,8 @@ int ata_dev_configure(struct ata_device 
 
 err_out_nosup:
 	if (ata_msg_probe(ap))
-		ata_dev_printk(dev, KERN_DEBUG, 
-				"%s: EXIT, err\n", __FUNCTION__);
+		ata_dev_printk(dev, KERN_DEBUG,
+			       "%s: EXIT, err\n", __FUNCTION__);
 	return rc;
 }
 
@@ -3527,7 +3561,7 @@ #endif /* __BIG_ENDIAN */
  *	Inherited from caller.
  */
 
-void ata_mmio_data_xfer(struct ata_device *adev, unsigned char *buf, 
+void ata_mmio_data_xfer(struct ata_device *adev, unsigned char *buf,
 			unsigned int buflen, int write_data)
 {
 	struct ata_port *ap = adev->ap;
@@ -3573,7 +3607,7 @@ void ata_mmio_data_xfer(struct ata_devic
  *	Inherited from caller.
  */
 
-void ata_pio_data_xfer(struct ata_device *adev, unsigned char *buf, 
+void ata_pio_data_xfer(struct ata_device *adev, unsigned char *buf,
 		       unsigned int buflen, int write_data)
 {
 	struct ata_port *ap = adev->ap;
@@ -3607,7 +3641,7 @@ void ata_pio_data_xfer(struct ata_device
  *	@buflen: buffer length
  *	@write_data: read/write
  *
- *	Transfer data from/to the device data register by PIO. Do the 
+ *	Transfer data from/to the device data register by PIO. Do the
  *	transfer with interrupts disabled.
  *
  *	LOCKING:
@@ -4946,31 +4980,9 @@ int ata_port_offline(struct ata_port *ap
 	return 0;
 }
 
-/*
- * Execute a 'simple' command, that only consists of the opcode 'cmd' itself,
- * without filling any other registers
- */
-static int ata_do_simple_cmd(struct ata_device *dev, u8 cmd)
-{
-	struct ata_taskfile tf;
-	int err;
-
-	ata_tf_init(dev, &tf);
-
-	tf.command = cmd;
-	tf.flags |= ATA_TFLAG_DEVICE;
-	tf.protocol = ATA_PROT_NODATA;
-
-	err = ata_exec_internal(dev, &tf, NULL, DMA_NONE, NULL, 0);
-	if (err)
-		ata_dev_printk(dev, KERN_ERR, "%s: ata command failed: %d\n",
-			       __FUNCTION__, err);
-
-	return err;
-}
-
-static int ata_flush_cache(struct ata_device *dev)
+int ata_flush_cache(struct ata_device *dev)
 {
+	unsigned int err_mask;
 	u8 cmd;
 
 	if (!ata_try_flush_cache(dev))
@@ -4981,17 +4993,41 @@ static int ata_flush_cache(struct ata_de
 	else
 		cmd = ATA_CMD_FLUSH;
 
-	return ata_do_simple_cmd(dev, cmd);
+	err_mask = ata_do_simple_cmd(dev, cmd);
+	if (err_mask) {
+		ata_dev_printk(dev, KERN_ERR, "failed to flush cache\n");
+		return -EIO;
+	}
+
+	return 0;
 }
 
 static int ata_standby_drive(struct ata_device *dev)
 {
-	return ata_do_simple_cmd(dev, ATA_CMD_STANDBYNOW1);
+	unsigned int err_mask;
+
+	err_mask = ata_do_simple_cmd(dev, ATA_CMD_STANDBYNOW1);
+	if (err_mask) {
+		ata_dev_printk(dev, KERN_ERR, "failed to standby drive "
+			       "(err_mask=0x%x)\n", err_mask);
+		return -EIO;
+	}
+
+	return 0;
 }
 
 static int ata_start_drive(struct ata_device *dev)
 {
-	return ata_do_simple_cmd(dev, ATA_CMD_IDLEIMMEDIATE);
+	unsigned int err_mask;
+
+	err_mask = ata_do_simple_cmd(dev, ATA_CMD_IDLEIMMEDIATE);
+	if (err_mask) {
+		ata_dev_printk(dev, KERN_ERR, "failed to start drive "
+			       "(err_mask=0x%x)\n", err_mask);
+		return -EIO;
+	}
+
+	return 0;
 }
 
 /**
@@ -5212,7 +5248,7 @@ #if defined(ATA_VERBOSE_DEBUG)
 	ap->msg_enable = 0x00FF;
 #elif defined(ATA_DEBUG)
 	ap->msg_enable = ATA_MSG_DRV | ATA_MSG_INFO | ATA_MSG_CTL | ATA_MSG_WARN | ATA_MSG_ERR;
-#else 
+#else
 	ap->msg_enable = ATA_MSG_DRV | ATA_MSG_ERR | ATA_MSG_WARN;
 #endif
 
@@ -5709,6 +5745,7 @@ #endif /* CONFIG_PCI */
 
 static int __init ata_init(void)
 {
+	ata_probe_timeout *= HZ;
 	ata_wq = create_workqueue("ata");
 	if (!ata_wq)
 		return -ENOMEM;
diff --git a/drivers/scsi/libata-eh.c b/drivers/scsi/libata-eh.c
index 8233859..bf5a72a 100644
--- a/drivers/scsi/libata-eh.c
+++ b/drivers/scsi/libata-eh.c
@@ -93,6 +93,38 @@ static int ata_ering_map(struct ata_erin
 	return rc;
 }
 
+static unsigned int ata_eh_dev_action(struct ata_device *dev)
+{
+	struct ata_eh_context *ehc = &dev->ap->eh_context;
+
+	return ehc->i.action | ehc->i.dev_action[dev->devno];
+}
+
+static void ata_eh_clear_action(struct ata_device *dev,
+				struct ata_eh_info *ehi, unsigned int action)
+{
+	int i;
+
+	if (!dev) {
+		ehi->action &= ~action;
+		for (i = 0; i < ATA_MAX_DEVICES; i++)
+			ehi->dev_action[i] &= ~action;
+	} else {
+		/* doesn't make sense for port-wide EH actions */
+		WARN_ON(!(action & ATA_EH_PERDEV_MASK));
+
+		/* break ehi->action into ehi->dev_action */
+		if (ehi->action & action) {
+			for (i = 0; i < ATA_MAX_DEVICES; i++)
+				ehi->dev_action[i] |= ehi->action & action;
+			ehi->action &= ~action;
+		}
+
+		/* turn off the specified per-dev action */
+		ehi->dev_action[dev->devno] &= ~action;
+	}
+}
+
 /**
  *	ata_scsi_timed_out - SCSI layer time out callback
  *	@cmd: timed out SCSI command
@@ -702,32 +734,11 @@ static void ata_eh_detach_dev(struct ata
 		ap->flags |= ATA_FLAG_SCSI_HOTPLUG;
 	}
 
-	spin_unlock_irqrestore(ap->lock, flags);
-}
-
-static void ata_eh_clear_action(struct ata_device *dev,
-				struct ata_eh_info *ehi, unsigned int action)
-{
-	int i;
+	/* clear per-dev EH actions */
+	ata_eh_clear_action(dev, &ap->eh_info, ATA_EH_PERDEV_MASK);
+	ata_eh_clear_action(dev, &ap->eh_context.i, ATA_EH_PERDEV_MASK);
 
-	if (!dev) {
-		ehi->action &= ~action;
-		for (i = 0; i < ATA_MAX_DEVICES; i++)
-			ehi->dev_action[i] &= ~action;
-	} else {
-		/* doesn't make sense for port-wide EH actions */
-		WARN_ON(!(action & ATA_EH_PERDEV_MASK));
-
-		/* break ehi->action into ehi->dev_action */
-		if (ehi->action & action) {
-			for (i = 0; i < ATA_MAX_DEVICES; i++)
-				ehi->dev_action[i] |= ehi->action & action;
-			ehi->action &= ~action;
-		}
-
-		/* turn off the specified per-dev action */
-		ehi->dev_action[dev->devno] &= ~action;
-	}
+	spin_unlock_irqrestore(ap->lock, flags);
 }
 
 /**
@@ -1592,7 +1603,7 @@ static int ata_eh_revalidate_and_attach(
 		unsigned int action;
 
 		dev = &ap->device[i];
-		action = ehc->i.action | ehc->i.dev_action[dev->devno];
+		action = ata_eh_dev_action(dev);
 
 		if (action & ATA_EH_REVALIDATE && ata_dev_enabled(dev)) {
 			if (ata_port_offline(ap)) {
diff --git a/drivers/scsi/libata.h b/drivers/scsi/libata.h
index bdd4888..c325679 100644
--- a/drivers/scsi/libata.h
+++ b/drivers/scsi/libata.h
@@ -29,7 +29,7 @@ #ifndef __LIBATA_H__
 #define __LIBATA_H__
 
 #define DRV_NAME	"libata"
-#define DRV_VERSION	"1.30"	/* must be exactly four chars */
+#define DRV_VERSION	"2.00"	/* must be exactly four chars */
 
 struct ata_scsi_args {
 	struct ata_device	*dev;
@@ -50,6 +50,7 @@ extern void ata_port_flush_task(struct a
 extern unsigned ata_exec_internal(struct ata_device *dev,
 				  struct ata_taskfile *tf, const u8 *cdb,
 				  int dma_dir, void *buf, unsigned int buflen);
+extern unsigned int ata_do_simple_cmd(struct ata_device *dev, u8 cmd);
 extern int ata_dev_read_id(struct ata_device *dev, unsigned int *p_class,
 			   int post_reset, u16 *id);
 extern int ata_dev_configure(struct ata_device *dev, int print_info);
@@ -64,6 +65,7 @@ extern int ata_check_atapi_dma(struct at
 extern void ata_dev_select(struct ata_port *ap, unsigned int device,
                            unsigned int wait, unsigned int can_sleep);
 extern void swap_buf_le16(u16 *buf, unsigned int buf_words);
+extern int ata_flush_cache(struct ata_device *dev);
 extern void ata_dev_init(struct ata_device *dev);
 extern int ata_task_ioctl(struct scsi_device *scsidev, void __user *arg);
 extern int ata_cmd_ioctl(struct scsi_device *scsidev, void __user *arg);
diff --git a/drivers/scsi/sata_nv.c b/drivers/scsi/sata_nv.c
index d18e7e0..5cc42c6 100644
--- a/drivers/scsi/sata_nv.c
+++ b/drivers/scsi/sata_nv.c
@@ -44,7 +44,7 @@ #include <scsi/scsi_host.h>
 #include <linux/libata.h>
 
 #define DRV_NAME			"sata_nv"
-#define DRV_VERSION			"0.9"
+#define DRV_VERSION			"2.0"
 
 enum {
 	NV_PORTS			= 2,
diff --git a/drivers/scsi/sata_sil.c b/drivers/scsi/sata_sil.c
index bc9f918..51d86d7 100644
--- a/drivers/scsi/sata_sil.c
+++ b/drivers/scsi/sata_sil.c
@@ -46,12 +46,13 @@ #include <scsi/scsi_host.h>
 #include <linux/libata.h>
 
 #define DRV_NAME	"sata_sil"
-#define DRV_VERSION	"1.0"
+#define DRV_VERSION	"2.0"
 
 enum {
 	/*
 	 * host flags
 	 */
+	SIL_FLAG_NO_SATA_IRQ	= (1 << 28),
 	SIL_FLAG_RERR_ON_DMA_ACT = (1 << 29),
 	SIL_FLAG_MOD15WRITE	= (1 << 30),
 
@@ -62,8 +63,9 @@ enum {
 	 * Controller IDs
 	 */
 	sil_3112		= 0,
-	sil_3512		= 1,
-	sil_3114		= 2,
+	sil_3112_no_sata_irq	= 1,
+	sil_3512		= 2,
+	sil_3114		= 3,
 
 	/*
 	 * Register offsets
@@ -123,8 +125,8 @@ static const struct pci_device_id sil_pc
 	{ 0x1095, 0x3512, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3512 },
 	{ 0x1095, 0x3114, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3114 },
 	{ 0x1002, 0x436e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112 },
-	{ 0x1002, 0x4379, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112 },
-	{ 0x1002, 0x437a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112 },
+	{ 0x1002, 0x4379, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112_no_sata_irq },
+	{ 0x1002, 0x437a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112_no_sata_irq },
 	{ }	/* terminate list */
 };
 
@@ -217,6 +219,16 @@ static const struct ata_port_info sil_po
 		.udma_mask	= 0x3f,			/* udma0-5 */
 		.port_ops	= &sil_ops,
 	},
+	/* sil_3112_no_sata_irq */
+	{
+		.sht		= &sil_sht,
+		.host_flags	= SIL_DFL_HOST_FLAGS | SIL_FLAG_MOD15WRITE |
+				  SIL_FLAG_NO_SATA_IRQ,
+		.pio_mask	= 0x1f,			/* pio0-4 */
+		.mwdma_mask	= 0x07,			/* mwdma0-2 */
+		.udma_mask	= 0x3f,			/* udma0-5 */
+		.port_ops	= &sil_ops,
+	},
 	/* sil_3512 */
 	{
 		.sht		= &sil_sht,
@@ -437,6 +449,10 @@ static irqreturn_t sil_interrupt(int irq
 		if (unlikely(!ap || ap->flags & ATA_FLAG_DISABLED))
 			continue;
 
+		/* turn off SATA_IRQ if not supported */
+		if (ap->flags & SIL_FLAG_NO_SATA_IRQ)
+			bmdma2 &= ~SIL_DMA_SATA_IRQ;
+
 		if (bmdma2 == 0xffffffff ||
 		    !(bmdma2 & (SIL_DMA_COMPLETE | SIL_DMA_SATA_IRQ)))
 			continue;
@@ -474,8 +490,9 @@ static void sil_thaw(struct ata_port *ap
 	ata_chk_status(ap);
 	ata_bmdma_irq_clear(ap);
 
-	/* turn on SATA IRQ */
-	writel(SIL_SIEN_N, mmio_base + sil_port[ap->port_no].sien);
+	/* turn on SATA IRQ if supported */
+	if (!(ap->flags & SIL_FLAG_NO_SATA_IRQ))
+		writel(SIL_SIEN_N, mmio_base + sil_port[ap->port_no].sien);
 
 	/* turn on IRQ */
 	tmp = readl(mmio_base + SIL_SYSCFG);
diff --git a/drivers/scsi/sata_sil24.c b/drivers/scsi/sata_sil24.c
index c8b477c..b5f8fa9 100644
--- a/drivers/scsi/sata_sil24.c
+++ b/drivers/scsi/sata_sil24.c
@@ -31,7 +31,7 @@ #include <linux/libata.h>
 #include <asm/io.h>
 
 #define DRV_NAME	"sata_sil24"
-#define DRV_VERSION	"0.24"
+#define DRV_VERSION	"0.3"
 
 /*
  * Port request block (PRB) 32 bytes
diff --git a/drivers/scsi/sata_svw.c b/drivers/scsi/sata_svw.c
index c94b870..7566c2c 100644
--- a/drivers/scsi/sata_svw.c
+++ b/drivers/scsi/sata_svw.c
@@ -54,7 +54,7 @@ #include <asm/pci-bridge.h>
 #endif /* CONFIG_PPC_OF */
 
 #define DRV_NAME	"sata_svw"
-#define DRV_VERSION	"1.8"
+#define DRV_VERSION	"2.0"
 
 enum {
 	/* Taskfile registers offsets */
diff --git a/drivers/scsi/sata_uli.c b/drivers/scsi/sata_uli.c
index f668c99..64f3c1a 100644
--- a/drivers/scsi/sata_uli.c
+++ b/drivers/scsi/sata_uli.c
@@ -37,7 +37,7 @@ #include <scsi/scsi_host.h>
 #include <linux/libata.h>
 
 #define DRV_NAME	"sata_uli"
-#define DRV_VERSION	"0.6"
+#define DRV_VERSION	"1.0"
 
 enum {
 	uli_5289		= 0,
diff --git a/drivers/scsi/sata_via.c b/drivers/scsi/sata_via.c
index 322890b..67c3d29 100644
--- a/drivers/scsi/sata_via.c
+++ b/drivers/scsi/sata_via.c
@@ -47,7 +47,7 @@ #include <linux/libata.h>
 #include <asm/io.h>
 
 #define DRV_NAME	"sata_via"
-#define DRV_VERSION	"1.2"
+#define DRV_VERSION	"2.0"
 
 enum board_ids_enum {
 	vt6420,
diff --git a/drivers/scsi/sata_vsc.c b/drivers/scsi/sata_vsc.c
index 6d0c4f1..616fd96 100644
--- a/drivers/scsi/sata_vsc.c
+++ b/drivers/scsi/sata_vsc.c
@@ -47,7 +47,7 @@ #include <scsi/scsi_host.h>
 #include <linux/libata.h>
 
 #define DRV_NAME	"sata_vsc"
-#define DRV_VERSION	"1.2"
+#define DRV_VERSION	"2.0"
 
 enum {
 	/* Interrupt register offsets (from chip base address) */
@@ -443,16 +443,12 @@ err_out:
 }
 
 
-/*
- * Intel 31244 is supposed to be identical.
- * Compatibility is untested as of yet.
- */
 static const struct pci_device_id vsc_sata_pci_tbl[] = {
-	{ PCI_VENDOR_ID_VITESSE, PCI_DEVICE_ID_VITESSE_VSC7174,
+	{ PCI_VENDOR_ID_VITESSE, 0x7174,
 	  PCI_ANY_ID, PCI_ANY_ID, 0x10600, 0xFFFFFF, 0 },
-	{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_GD31244,
+	{ PCI_VENDOR_ID_INTEL, 0x3200,
 	  PCI_ANY_ID, PCI_ANY_ID, 0x10600, 0xFFFFFF, 0 },
-	{ }
+	{ }	/* terminate list */
 };
 
 
diff --git a/include/linux/libata.h b/include/linux/libata.h
index 20b1cf5..f4284bf 100644
--- a/include/linux/libata.h
+++ b/include/linux/libata.h
@@ -30,6 +30,7 @@ #include <linux/delay.h>
 #include <linux/interrupt.h>
 #include <linux/pci.h>
 #include <linux/dma-mapping.h>
+#include <asm/scatterlist.h>
 #include <asm/io.h>
 #include <linux/ata.h>
 #include <linux/workqueue.h>
@@ -887,6 +888,9 @@ static inline unsigned int ata_tag_inter
 	return tag == ATA_MAX_QUEUE - 1;
 }
 
+/*
+ * device helpers
+ */
 static inline unsigned int ata_class_enabled(unsigned int class)
 {
 	return class == ATA_DEV_ATA || class == ATA_DEV_ATAPI;
@@ -917,6 +921,17 @@ static inline unsigned int ata_dev_absen
 	return ata_class_absent(dev->class);
 }
 
+/*
+ * port helpers
+ */
+static inline int ata_port_max_devices(const struct ata_port *ap)
+{
+	if (ap->flags & ATA_FLAG_SLAVE_POSS)
+		return 2;
+	return 1;
+}
+
+
 static inline u8 ata_chk_status(struct ata_port *ap)
 {
 	return ap->ops->check_status(ap);
diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h
index c2fd2d1..9ae6b1a 100644
--- a/include/linux/pci_ids.h
+++ b/include/linux/pci_ids.h
@@ -1202,6 +1202,7 @@ #define PCI_DEVICE_ID_NVIDIA_NVENET_18  
 #define PCI_DEVICE_ID_NVIDIA_NVENET_19              0x03EF
 #define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_SATA2     0x03F6
 #define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_SATA3     0x03F7
+#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP65_IDE	    0x0448
 #define PCI_DEVICE_ID_NVIDIA_NVENET_20              0x0450
 #define PCI_DEVICE_ID_NVIDIA_NVENET_21              0x0451
 #define PCI_DEVICE_ID_NVIDIA_NVENET_22              0x0452
@@ -2170,7 +2171,6 @@ #define PCI_DEVICE_ID_INTEL_ICH8_3	0x281
 #define PCI_DEVICE_ID_INTEL_ICH8_4	0x2815
 #define PCI_DEVICE_ID_INTEL_ICH8_5	0x283e
 #define PCI_DEVICE_ID_INTEL_ICH8_6	0x2850
-#define PCI_DEVICE_ID_INTEL_GD31244	0x3200
 #define PCI_DEVICE_ID_INTEL_82855PM_HB	0x3340
 #define PCI_DEVICE_ID_INTEL_82830_HB	0x3575
 #define PCI_DEVICE_ID_INTEL_82830_CGC	0x3577

^ permalink raw reply related	[flat|nested] 15+ messages in thread

* Re: [git patches] libata update
  2006-06-27  1:24 [git patches] libata update Jeff Garzik
@ 2006-06-28  1:23 ` Linus Torvalds
  2006-06-28  1:34   ` Jeff Garzik
  0 siblings, 1 reply; 15+ messages in thread
From: Linus Torvalds @ 2006-06-28  1:23 UTC (permalink / raw)
  To: Jeff Garzik; +Cc: Andrew Morton, linux-ide, linux-kernel



On Mon, 26 Jun 2006, Jeff Garzik wrote:
> 
> Please pull from 'upstream-linus' branch of
> master.kernel.org:/pub/scm/linux/kernel/git/jgarzik/libata-dev.git

I get a "Already up-to-date".

Did you perhaps forget to push?

		Linus

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [git patches] libata update
  2006-06-28  1:23 ` Linus Torvalds
@ 2006-06-28  1:34   ` Jeff Garzik
  0 siblings, 0 replies; 15+ messages in thread
From: Jeff Garzik @ 2006-06-28  1:34 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: Andrew Morton, linux-ide, linux-kernel

Linus Torvalds wrote:
> 
> On Mon, 26 Jun 2006, Jeff Garzik wrote:
>> Please pull from 'upstream-linus' branch of
>> master.kernel.org:/pub/scm/linux/kernel/git/jgarzik/libata-dev.git
> 
> I get a "Already up-to-date".
> 
> Did you perhaps forget to push?

Apparently I had pushed everything except the "bookmark" (the new 
upstream-linus branch head).

It should be there now...

	Jeff




^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [git patches] libata update
  2007-10-13 10:55   ` Jeff Garzik
@ 2007-10-26  3:02     ` Tejun Heo
  0 siblings, 0 replies; 15+ messages in thread
From: Tejun Heo @ 2007-10-26  3:02 UTC (permalink / raw)
  To: Jeff Garzik; +Cc: Andrey Borzenkov, linux-kernel, linux-ide, linux-scsi

Jeff Garzik wrote:
> Andrey Borzenkov wrote:
>> Jeff Garzik wrote:
>>
>>> * Asynchronous notification -- finally userspace CD-ROM polling can go
>>> away!
>>>   (NOTE: waiting on James B to apply the piece that actually makes this
>>>   work...)
>>
>> Does it depend on hardware offering suitable support? What are chances
>> for
>> it to work on 5 years old DVD-ROM?
> 
> Correct -- it requires a new SATA CD-ROM with the AN capability.

And some SATA CD-ROMs lie about AN capability and sends nothing when
media event occurs.  Do we need to start a blacklist or whitelist?  :-)

-- 
tejun

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [git patches] libata update
  2007-10-13  1:42 ` Bartlomiej Zolnierkiewicz
@ 2007-10-15 22:31   ` Jeff Garzik
  0 siblings, 0 replies; 15+ messages in thread
From: Jeff Garzik @ 2007-10-15 22:31 UTC (permalink / raw)
  To: Bartlomiej Zolnierkiewicz
  Cc: linux-ide, LKML, linux-scsi, Sonic Zhang, Kristoffer Nyborg Gregertsen

Bartlomiej Zolnierkiewicz wrote:
> On Friday 12 October 2007, Jeff Garzik wrote:
>> [ I just sent this upstream to Andrew and Linus ]
>>
>> Now that I have nailed down the corruption problem, I can attend to
>> this...  Fun stuff:
>>
>> * port multiplier support (like an ethernet hub, only dumber)
> 
> Great to see this here.
> 
>> * Asynchronous notification -- finally userspace CD-ROM polling can go away!
> 
> Is this AHCI specific or could be used by some other SATA hosts?

Can be used by any controller that supports SNotification (or is able to 
capture and parse the raw FIS's).

And FWIW, Tejun's PMP work also uses a few bits of same async-notify stuff.

I agree with your review items, and will look at those if others don't 
beat me to it.

	Jeff




^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [git patches] libata update
  2007-10-14 10:35 ` Torsten Kaiser
@ 2007-10-14 12:21   ` Alan Cox
  0 siblings, 0 replies; 15+ messages in thread
From: Alan Cox @ 2007-10-14 12:21 UTC (permalink / raw)
  To: Torsten Kaiser; +Cc: Jeff Garzik, linux-ide, LKML, linux-scsi, linux-acpi

> ACPI Exception (exoparg2-0442): AE_AML_PACKAGE_LIMIT, Index
> (0FFFFFFFF) is beyond end of object [20070126]
> ACPI Error (psparse-0537): Method parse/execution failed
> [\_SB_.PCI0.IDE0.GTM_] (Node ffff810100318a20), AE_AML_PACKAGE_LIMIT
> ACPI Error (psparse-0537): Method parse/execution failed
> [\_SB_.PCI0.IDE0.CHN0._GTM] (Node ffff8101003187c0),
> AE_AML_PACKAGE_LIMIT
> ata9: ACPI get timing mode failed (AE 0x300d)

Looks like an ACPI BIOS problem. In that situation we'll just give up on
using ACPI information

Not much else we can do as Nvidia don't document how to do a reliable
40/80 wire test and just told us to use the BIOS.

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [git patches] libata update
  2007-10-12 19:40 Jeff Garzik
                   ` (2 preceding siblings ...)
  2007-10-13  7:05 ` Andrey Borzenkov
@ 2007-10-14 10:35 ` Torsten Kaiser
  2007-10-14 12:21   ` Alan Cox
  3 siblings, 1 reply; 15+ messages in thread
From: Torsten Kaiser @ 2007-10-14 10:35 UTC (permalink / raw)
  To: Jeff Garzik; +Cc: linux-ide, LKML, linux-scsi, linux-acpi

On 10/12/07, Jeff Garzik <jeff@garzik.org> wrote:
> [ I just sent this upstream to Andrew and Linus ]
> * Turn on ACPI by default (watch for bug reports!).  This should make
>   suspend/resume work a lot better.

Bug report for 2.6.23-mm1:
scsi8 : pata_amd
scsi9 : pata_amd
ata9: PATA max UDMA/133 cmd 0x1f0 ctl 0x3f6 bmdma 0xffa0 irq 14
ata10: PATA max UDMA/133 cmd 0x170 ctl 0x376 bmdma 0xffa8 irq 15
ACPI Exception (exoparg2-0442): AE_AML_PACKAGE_LIMIT, Index
(0FFFFFFFF) is beyond end of object [20070126]
ACPI Error (psparse-0537): Method parse/execution failed
[\_SB_.PCI0.IDE0.GTM_] (Node ffff810100318a20), AE_AML_PACKAGE_LIMIT
ACPI Error (psparse-0537): Method parse/execution failed
[\_SB_.PCI0.IDE0.CHN0._GTM] (Node ffff8101003187c0),
AE_AML_PACKAGE_LIMIT
ata9: ACPI get timing mode failed (AE 0x300d)
ata9.01: ATA-7: Maxtor 6L250R0, BAH41G10, max UDMA/133
ata9.01: 490234752 sectors, multi 16: LBA48
ata9.01: limited to UDMA/33 due to 40-wire cable
ata9.01: configured for UDMA/33
ata10: port disabled. ignoring.

libata-Bug, ACPI-Bug or just bad code in the BIOS?
The detection of the 40-wire cable is correct, also that there is only
one drive at this IDE port.

pata_amd is build as module and is driving the IDE part of a nVidia MCP55.

Torsten

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [git patches] libata update
  2007-10-13  7:05 ` Andrey Borzenkov
@ 2007-10-13 10:55   ` Jeff Garzik
  2007-10-26  3:02     ` Tejun Heo
  0 siblings, 1 reply; 15+ messages in thread
From: Jeff Garzik @ 2007-10-13 10:55 UTC (permalink / raw)
  To: Andrey Borzenkov; +Cc: linux-kernel, linux-ide, linux-scsi

Andrey Borzenkov wrote:
> Jeff Garzik wrote:
> 
>> * Asynchronous notification -- finally userspace CD-ROM polling can go
>> away!
>>   (NOTE: waiting on James B to apply the piece that actually makes this
>>   work...)
> 
> Does it depend on hardware offering suitable support? What are chances for
> it to work on 5 years old DVD-ROM?

Correct -- it requires a new SATA CD-ROM with the AN capability.

	Jeff




^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [git patches] libata update
  2007-10-12 19:40 Jeff Garzik
  2007-10-13  0:06 ` Luben Tuikov
  2007-10-13  1:42 ` Bartlomiej Zolnierkiewicz
@ 2007-10-13  7:05 ` Andrey Borzenkov
  2007-10-13 10:55   ` Jeff Garzik
  2007-10-14 10:35 ` Torsten Kaiser
  3 siblings, 1 reply; 15+ messages in thread
From: Andrey Borzenkov @ 2007-10-13  7:05 UTC (permalink / raw)
  To: linux-kernel, linux-ide, linux-scsi

Jeff Garzik wrote:

> * Asynchronous notification -- finally userspace CD-ROM polling can go
> away!
>   (NOTE: waiting on James B to apply the piece that actually makes this
>   work...)

Does it depend on hardware offering suitable support? What are chances for
it to work on 5 years old DVD-ROM?


^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [git patches] libata update
  2007-10-12 19:40 Jeff Garzik
  2007-10-13  0:06 ` Luben Tuikov
@ 2007-10-13  1:42 ` Bartlomiej Zolnierkiewicz
  2007-10-15 22:31   ` Jeff Garzik
  2007-10-13  7:05 ` Andrey Borzenkov
  2007-10-14 10:35 ` Torsten Kaiser
  3 siblings, 1 reply; 15+ messages in thread
From: Bartlomiej Zolnierkiewicz @ 2007-10-13  1:42 UTC (permalink / raw)
  To: Jeff Garzik
  Cc: linux-ide, LKML, linux-scsi, Sonic Zhang, Kristoffer Nyborg Gregertsen


On Friday 12 October 2007, Jeff Garzik wrote:
> 
> [ I just sent this upstream to Andrew and Linus ]
> 
> Now that I have nailed down the corruption problem, I can attend to
> this...  Fun stuff:
> 
> * port multiplier support (like an ethernet hub, only dumber)

Great to see this here.

> * Asynchronous notification -- finally userspace CD-ROM polling can go away!

Is this AHCI specific or could be used by some other SATA hosts?

>   (NOTE: waiting on James B to apply the piece that actually makes this
>   work...)
> 
> * Alan continues to hammer out edge cases in generic ATA support.  An
>   amazing amount of ancient and/or obscure hardware works with libata   thanks to him :)

Worth to mention that this update also contains two new drivers from Alan,
pata_acpi and pata_ns87415. :)

> * Turn on ACPI by default (watch for bug reports!).  This should make
>   suspend/resume work a lot better.
> 
> * New drivers for embedded ATA chips.

Unfortunately both are broken ATM, details below.

[ added Sonic Zhang and Kristoffer Nyborg Gregertsen to cc: ]

> Please pull from 'upstream-linus' branch of
> master.kernel.org:/pub/scm/linux/kernel/git/jgarzik/libata-dev.git upstream-linus

[ ... ]

> Alan Cox (22):
>       pata_cmd64x: Set up MWDMA modes properly

two minor things:

a.

@@ -88,14 +88,15 @@ static int cmd648_cable_detect(struct ata_port *ap)
 }
 
 /**
- *     cmd64x_set_piomode      -       set initial PIO mode data
+ *     cmd64x_set_piomode      -       set PIO and MWDMA timing
  *     @ap: ATA interface
  *     @adev: ATA device
+ *     @mode: mode
  *
- *     Called to do the PIO mode setup.
+ *     Called to do the PIO and MWDMA mode setup.
  */
 
-static void cmd64x_set_piomode(struct ata_port *ap, struct ata_device *adev)
+static void cmd64x_set_timing(struct ata_port *ap, struct ata_device *adev, u8 mode)
 {
        struct pci_dev *pdev = to_pci_dev(ap->host->dev);
        struct ata_timing t;

function name in the documentation needs fixing

b.

regD fiddling in cmd64x_set_dmamode() could be removed completly

>       libata: correct handling of SRST reset sequences

This potentially adds a regression for nVidia boxes (but ACPI cable
detection should compensate for it):

pata_amd's ->cable_detect checks UDMA timings to get the cable type
(cable detection is done before the SRST) but pata_amd's ->set_piomode
messes with UDMA timings.  It seems that both methods need fixing.

> Jeff Garzik (14):

>       [libata] Turn on ACPI by default

-MODULE_PARM_DESC(noacpi, "Disables the use of ACPI in suspend/resume when set");
+MODULE_PARM_DESC(noacpi, "Disables the use of ACPI in probe/suspend/resume when set");

Would be nice to have Documentation/kernel-parameters.txt updated as well.

> Kristoffer Nyborg Gregertsen (1):
>       AVR32 PATA driver

Won't build because this libata update removes ->irq_ack and ->port_disable
methods from struct ata_port.

> Sonic Zhang (1):
>       libata driver for bf548 on chip ATAPI controller.

Won't build, same problem as with AVR32 PATA driver + needs update to
accomodate for libata-link patches.

There are some other problems:

a.

+config PATA_BF54X_DMA
+       bool "DMA mode"
+       depends on PATA_BF54X
+       default y
+       help
+         Enable DMA mode for Blackfin ATAPI controller.

The preferred solution would be to use module parameter.

If this option is on by default it may be even possible to remove it
completly since this libata update also contains patch from Alan allowing
DMA disable per different classes of ATA devices.

b.

+static struct ata_port_info bfin_port_info[] = {
+       {
+               .sht            = &bfin_sht,
+               .flags          = ATA_FLAG_SLAVE_POSS
+                               | ATA_FLAG_MMIO
+                               | ATA_FLAG_NO_LEGACY,
+               .pio_mask       = 0x1f, /* pio0-4 */
+               .mwdma_mask     = 0,
+#ifdef CONFIG_PATA_BF54X_DMA
+               .udma_mask      = ATA_UDMA5,
+#else
+               .udma_mask      = 0,
+#endif
+               .port_ops       = &bfin_pata_ops,
+       },
+};

MWDMA is never enabled (even if CONFIG_PATA_BF54X_DMA=y) but the driver
contains MWDMA support...

c.

+/**
+ *
+ *    Function:       wait_complete
+ *
+ *    Description:    Waits the interrupt from device
+ *
+ */
+static inline void wait_complete(void __iomem *base, unsigned short mask)
+{
+       unsigned short status;
+       unsigned int i = 0;
+
+#define PATA_BF54X_WAIT_TIMEOUT                10000
+
+       for (i = 0; i < PATA_BF54X_WAIT_TIMEOUT; i++) {
+               status = ATAPI_GET_INT_STATUS(base) & mask;
+               if (status)
+                       break;
+       }
+
+       ATAPI_SET_INT_STATUS(base, mask);
+}

udelay() between retries?

d.

* write_atapi_register()
* read_atapi_register()
* write_atapi_data()
* read_atapi_data()

and

* wait_complete()

need a proper documentation (DocBook-ized etc).

Thanks,
Bart

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [git patches] libata update
  2007-10-12 19:40 Jeff Garzik
@ 2007-10-13  0:06 ` Luben Tuikov
  2007-10-13  1:42 ` Bartlomiej Zolnierkiewicz
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 15+ messages in thread
From: Luben Tuikov @ 2007-10-13  0:06 UTC (permalink / raw)
  To: Jeff Garzik, linux-ide; +Cc: LKML, linux-scsi

You should run "git-update-server-info" in 
pub/scm/linux/kernel/git/jgarzik/libata-dev.git.

info/refs disagrees with refs/heads/* .

   Luben

--- Jeff Garzik <jeff@garzik.org> wrote:

> 
> [ I just sent this upstream to Andrew and Linus ]
> 
> Now that I have nailed down the corruption problem, I can attend to
> this...  Fun stuff:
> 
> * port multiplier support (like an ethernet hub, only dumber)
> 
> * Asynchronous notification -- finally userspace CD-ROM polling can go away!
>   (NOTE: waiting on James B to apply the piece that actually makes this
>   work...)
> 
> * Alan continues to hammer out edge cases in generic ATA support.  An
>   amazing amount of ancient and/or obscure hardware works with libata   thanks to him :)
> 
> * Turn on ACPI by default (watch for bug reports!).  This should make
>   suspend/resume work a lot better.
> 
> * New drivers for embedded ATA chips.
> 
> 
> Please pull from 'upstream-linus' branch of
> master.kernel.org:/pub/scm/linux/kernel/git/jgarzik/libata-dev.git upstream-linus
> 
> to receive the following updates:
> 
>  Documentation/kernel-parameters.txt  |    8 +-
>  drivers/ata/Kconfig                  |   59 ++-
>  drivers/ata/Makefile                 |    8 +-
>  drivers/ata/ahci.c                   |  451 +++++++---
>  drivers/ata/ata_generic.c            |   16 +-
>  drivers/ata/ata_piix.c               |   71 +-
>  drivers/ata/libata-acpi.c            |  165 +++-
>  drivers/ata/libata-core.c            | 1329 ++++++++++++++++++----------
>  drivers/ata/libata-eh.c              |  922 ++++++++++++++------
>  drivers/ata/libata-pmp.c             | 1191 +++++++++++++++++++++++++
>  drivers/ata/libata-scsi.c            |  496 +++++++----
>  drivers/ata/libata-sff.c             |   69 +-
>  drivers/ata/libata.h                 |   41 +-
>  drivers/ata/pata_acpi.c              |  395 ++++++++
>  drivers/ata/pata_ali.c               |   17 +-
>  drivers/ata/pata_amd.c               |   43 +-
>  drivers/ata/pata_artop.c             |   20 +-
>  drivers/ata/pata_at32.c              |  441 +++++++++
>  drivers/ata/pata_atiixp.c            |   15 +-
>  drivers/ata/pata_bf54x.c             | 1627 ++++++++++++++++++++++++++++++++++
>  drivers/ata/pata_cmd640.c            |    4 +-
>  drivers/ata/pata_cmd64x.c            |   43 +-
>  drivers/ata/pata_cs5520.c            |   47 +-
>  drivers/ata/pata_cs5530.c            |    4 +-
>  drivers/ata/pata_cs5535.c            |    4 +-
>  drivers/ata/pata_cypress.c           |    4 +-
>  drivers/ata/pata_efar.c              |   11 +-
>  drivers/ata/pata_hpt366.c            |    4 +-
>  drivers/ata/pata_hpt37x.c            |   28 +-
>  drivers/ata/pata_hpt3x2n.c           |   11 +-
>  drivers/ata/pata_hpt3x3.c            |   10 +-
>  drivers/ata/pata_icside.c            |   39 +-
>  drivers/ata/pata_isapnp.c            |    8 +-
>  drivers/ata/pata_it8213.c            |   11 +-
>  drivers/ata/pata_it821x.c            |   17 +-
>  drivers/ata/pata_ixp4xx_cf.c         |   24 +-
>  drivers/ata/pata_jmicron.c           |   24 +-
>  drivers/ata/pata_legacy.c            |   27 +-
>  drivers/ata/pata_marvell.c           |   12 +-
>  drivers/ata/pata_mpc52xx.c           |    9 +-
>  drivers/ata/pata_mpiix.c             |   25 +-
>  drivers/ata/pata_netcell.c           |    5 +-
>  drivers/ata/pata_ns87410.c           |   11 +-
>  drivers/ata/pata_ns87415.c           |  467 ++++++++++
>  drivers/ata/pata_oldpiix.c           |   11 +-
>  drivers/ata/pata_opti.c              |   11 +-
>  drivers/ata/pata_optidma.c           |   26 +-
>  drivers/ata/pata_pcmcia.c            |   16 +-
>  drivers/ata/pata_pdc2027x.c          |  114 ++--
>  drivers/ata/pata_pdc202xx_old.c      |   23 +-
>  drivers/ata/pata_platform.c          |   16 +-
>  drivers/ata/pata_qdi.c               |   15 +-
>  drivers/ata/pata_radisys.c           |    4 +-
>  drivers/ata/pata_rz1000.c            |   13 +-
>  drivers/ata/pata_sc1200.c            |    4 +-
>  drivers/ata/pata_scc.c               |   66 +-
>  drivers/ata/pata_serverworks.c       |    8 +-
>  drivers/ata/pata_sil680.c            |   11 +-
>  drivers/ata/pata_sis.c               |   33 +-
>  drivers/ata/pata_sl82c105.c          |   11 +-
>  drivers/ata/pata_triflex.c           |   11 +-
>  drivers/ata/pata_via.c               |   16 +-
>  drivers/ata/pata_winbond.c           |   13 +-
>  drivers/ata/pdc_adma.c               |  103 ++-
>  drivers/ata/sata_inic162x.c          |   34 +-
>  drivers/ata/sata_mv.c                |   68 +-
>  drivers/ata/sata_nv.c                |   53 +-
>  drivers/ata/sata_promise.c           |   27 +-
>  drivers/ata/sata_qstor.c             |   17 +-
>  drivers/ata/sata_sil.c               |   53 +-
>  drivers/ata/sata_sil24.c             |  341 ++++++--
>  drivers/ata/sata_sis.c               |    2 -
>  drivers/ata/sata_svw.c               |   14 +-
>  drivers/ata/sata_sx4.c               |   25 +-
>  drivers/ata/sata_uli.c               |   16 +-
>  drivers/ata/sata_via.c               |   35 +-
>  drivers/ata/sata_vsc.c               |   16 +-
>  drivers/scsi/ipr.c                   |   19 +-
>  drivers/scsi/libsas/sas_ata.c        |   11 +-
>  include/asm-generic/libata-portmap.h |    5 -
>  include/linux/ata.h                  |  116 +++-
>  include/linux/libata.h               |  320 +++++--
>  82 files changed, 7866 insertions(+), 2064 deletions(-)
>  create mode 100644 drivers/ata/libata-pmp.c
>  create mode 100644 drivers/ata/pata_acpi.c
>  create mode 100644 drivers/ata/pata_at32.c
>  create mode 100644 drivers/ata/pata_bf54x.c
>  create mode 100644 drivers/ata/pata_ns87415.c
> 
> Alan Cox (22):
>       libata: Correct IORDY handling
>       libata-core: Document some limits/assumptions about ID_ATA
>       libata: Note that our cache flush code needs fixing up
>       pata_cmd64x: Set up MWDMA modes properly
>       [libata] add ACPI cable detect API
>       libata pata_amd: ACPI checks for 80wire cable
>       libata pata_via: ACPI checks for 80wire cable
>       libata: Switch most of the remaining SFF drivers to ata_sff_port_start
>       libata-portmap: Remove unused definitions
>       libata: Spot bridge chips
>       libata: Strict checking for identify reporting
>       libata: Update experimental tags to reflect reality better
>       pdc2027x: Switch properly to ioread/iowrite
>       pata_atiixp: Audit notes on locking
>       pata_pdc202xx_old MWDMA fixes, and notes
>       pata_ns87415: Initial cut at 87415/87560 IDE support
>       libata: Fix HPA handling regression
>       libata: Add a drivers/ide style DMA disable
>       libata: correct handling of SRST reset sequences
>       libata_scsi: Fix ATAPI transfer lengths
>       libata-core: Expose gtm methods for driver use
>       pata_acpi: ACPI driver support
> 
> Albert Lee (2):
>       libata: move ata_altstatus() to pio data xfer functions
>       libata: pata_pdc2027x PLL detection minor cleanup
> 
> Andrew Morton (1):
>       libata-add-irq_flags-to-struct-pata_platform_info-fix
> 
> Boaz Harrosh (2):
>       libata-scsi: Remove !use_sg code paths
>       libata-scsi: convert to use the data buffer accessors
> 
> Christian Lamparter (1):
>       ata_piix: disallow UDMA 133 on ICH5 & ICH7
> 
> Dave Jones (1):
>       libata: correct kernel parameter in documentation.
> 
> David Milburn (1):
>       libata-core: blacklist HITACHI HDS drives using wildcard blacklist matching
> 
> Jason Gaston (2):
>       ata_piix: replace spaces with tabs
>       ahci: RAID mode SATA patch for Intel Tolapai
> 
> Jeff Garzik (14):
>       [libata] pdc_adma: convert to new exception handling (EH) framework
>       [libata] Remove ->irq_ack() hook, and ata_dummy_irq_on()
>       [libata] Remove ->port_disable() hook
>       [libata] ata_piix: Use more-robust form of array initialization
>       [libata] blacklist Maxtor*BANC* using new wildcard blacklist matching
>       [libata] SCSI: support INQUIRY page 89h (ATA info page)
>       [libata] Slightly improved no-op REQUEST SENSE, SEND DIAGNOSTIC
>       [libata] SCSI: improve FORMAT UNIT; minor code cleanups
>       [libata] SCSI: clean up R/W recovery mode page
>       [libata] SCSI: simulator version, not device version, belongs in VPD
>       [libata] AHCI: enable AHCI mode, before using AHCI reset
>       [libata] ata_piix: add HP compaq laptop to short cable list
>       [libata] Turn on ACPI by default
>       [libata] struct pci_dev related cleanups
> 
> Kristen Carlson Accardi (4):
>       [libata] check for SATA async notify support
>       [libata] ahci: send event when AN received
>       ahci: Store interrupt value
>       ata: increase allowed config flags
> 
> Kristoffer Nyborg Gregertsen (1):
>       AVR32 PATA driver
> 
> Mark Lord (1):
>       libata: add support for ATA_16 on ATAPI
> 
> Matthew Garrett (1):
>       libata: Integrate ACPI-based PATA/SATA hotplug - version 5
> 
> Paolo Ornati (1):
>       libata: blacklist NCQ on Seagate Barracuda ST380817AS
> 
> Peer Chen (1):
>       ahci: Add MCP79 support to AHCI driver
> 
> Robert Hancock (1):
>       libata: add human-readable error value decoding
> 
> Satyam Sharma (1):
>       libata: Fix build failure on ppc64 drivers/ata/pata_scc.c
> 
> Sonic Zhang (1):
>       libata driver for bf548 on chip ATAPI controller.
> 
> Tejun Heo (61):
>       libata-link: introduce ata_link
>       libata-link: implement and use link/device iterators
>       libata-link: linkify PHY-related functions
>       libata-link: linkify EH action helpers
>       libata-link: linkify reset
>       libata-link: linkify config/EH related functions
>       libata-link: make two port flags HRST_TO_RESUME and SKIP_D2H_BSY link flags
>       libata-link: separate out link initialization functions
>       libata-link: implement ata_link_abort()
>       libata-link: add PMP links
>       libata-link: update ata_scsi_error() to handle PMP links
>       libata-link: update EH to deal with PMP links
>       libata-link: update hotplug to handle PMP links
>       libata-link: update Power Management to handle PMP links
>       libata: use ata_port_printk() in ata_wait_idle()
>       libata: add printf format attribute to ehi desc functions
>       libata: implement and use ata_port_desc() to report port configuration
>       libata: move EH repeat reporting into ata_eh_report()
>       libata: move ata_id_n_sectors() upward
>       libata: clean up read/set native_max address functions
>       libata: remiplement ata_hpa_resize()
>       ahci: reimplement port_map handling
>       libata: update ata_dev_try_classify() arguments
>       libata: assume ATA_DEV_ATA on diagnostic failure
>       libata: misc updates for AN
>       libata-pmp-prep: add PMP related constants, fields, ops and update helpers
>       libata-pmp-prep: add @new_class to ata_dev_revalidate()
>       libata-pmp-prep: make a number of functions global to libata
>       libata-pmp-prep: implement ops->qc_defer()
>       libata-pmp-prep: implement qc_defer helpers
>       libata-pmp-prep: implement ATA_LFLAG_NO_SRST, ASSUME_ATA and ASSUME_SEMB
>       libata-pmp-prep: implement ATA_LFLAG_NO_RETRY
>       libata-pmp-prep: implement ATA_LFLAG_DISABLED
>       libata-pmp-prep: implement EH fast-fail path
>       libata-pmp-prep: implement ATA_HORKAGE_SKIP_PM
>       libata-pmp-prep: implement sata_async_notification()
>       libata: fix ata_set_max_sectors()
>       sata_via: kill SATA_PATA_SHARING register handling
>       libata: update spurious NCQ completion blacklist
>       libata-pmp: update ata_eh_reset() for PMP
>       libata-pmp: implement Port Multiplier support
>       libata-pmp: hook PMP support and enable it
>       libata-pmp: extend ACPI support to cover PMP
>       libata-pmp: implement qc_defer for command switching PMP support
>       sata_sil24: implement PMP support
>       sata_sil24: implement PORT_RST
>       ahci: implement PMP support
>       ahci: move host flags over to pi.private_data
>       ahci: implement AHCI_HFLAG_NO_PMP
>       libata: add HDT722516DLA380 to NCQ blacklist
>       libata: add ST9160821AS / 3.ALD to NCQ blacklist
>       pata_jmicron: match vendor and class code only
>       libata: clear ehi description after initial host report
>       libata: skip suppress reporting if ATA_EHI_QUIET
>       libata: wrap schedule_timeout_uninterruptible() in loop
>       ahci: kill leftover from enabling NCQ over PMP
>       ahci: clean up PORT_IRQ_BAD_PMP enabling
>       ahci: fix notification handling
>       libata: add @timeout to ata_exec_internal[_sg]()
>       libata: implement ATA_PFLAG_RESETTING
>       libata: use ata_exec_internal() for PMP register access
> 
> [patch snipped due to size; grab it from git]
> 
> -
> To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 


^ permalink raw reply	[flat|nested] 15+ messages in thread

* [git patches] libata update
@ 2007-10-12 19:40 Jeff Garzik
  2007-10-13  0:06 ` Luben Tuikov
                   ` (3 more replies)
  0 siblings, 4 replies; 15+ messages in thread
From: Jeff Garzik @ 2007-10-12 19:40 UTC (permalink / raw)
  To: linux-ide; +Cc: LKML, linux-scsi


[ I just sent this upstream to Andrew and Linus ]

Now that I have nailed down the corruption problem, I can attend to
this...  Fun stuff:

* port multiplier support (like an ethernet hub, only dumber)

* Asynchronous notification -- finally userspace CD-ROM polling can go away!
  (NOTE: waiting on James B to apply the piece that actually makes this
  work...)

* Alan continues to hammer out edge cases in generic ATA support.  An
  amazing amount of ancient and/or obscure hardware works with libata   thanks to him :)

* Turn on ACPI by default (watch for bug reports!).  This should make
  suspend/resume work a lot better.

* New drivers for embedded ATA chips.


Please pull from 'upstream-linus' branch of
master.kernel.org:/pub/scm/linux/kernel/git/jgarzik/libata-dev.git upstream-linus

to receive the following updates:

 Documentation/kernel-parameters.txt  |    8 +-
 drivers/ata/Kconfig                  |   59 ++-
 drivers/ata/Makefile                 |    8 +-
 drivers/ata/ahci.c                   |  451 +++++++---
 drivers/ata/ata_generic.c            |   16 +-
 drivers/ata/ata_piix.c               |   71 +-
 drivers/ata/libata-acpi.c            |  165 +++-
 drivers/ata/libata-core.c            | 1329 ++++++++++++++++++----------
 drivers/ata/libata-eh.c              |  922 ++++++++++++++------
 drivers/ata/libata-pmp.c             | 1191 +++++++++++++++++++++++++
 drivers/ata/libata-scsi.c            |  496 +++++++----
 drivers/ata/libata-sff.c             |   69 +-
 drivers/ata/libata.h                 |   41 +-
 drivers/ata/pata_acpi.c              |  395 ++++++++
 drivers/ata/pata_ali.c               |   17 +-
 drivers/ata/pata_amd.c               |   43 +-
 drivers/ata/pata_artop.c             |   20 +-
 drivers/ata/pata_at32.c              |  441 +++++++++
 drivers/ata/pata_atiixp.c            |   15 +-
 drivers/ata/pata_bf54x.c             | 1627 ++++++++++++++++++++++++++++++++++
 drivers/ata/pata_cmd640.c            |    4 +-
 drivers/ata/pata_cmd64x.c            |   43 +-
 drivers/ata/pata_cs5520.c            |   47 +-
 drivers/ata/pata_cs5530.c            |    4 +-
 drivers/ata/pata_cs5535.c            |    4 +-
 drivers/ata/pata_cypress.c           |    4 +-
 drivers/ata/pata_efar.c              |   11 +-
 drivers/ata/pata_hpt366.c            |    4 +-
 drivers/ata/pata_hpt37x.c            |   28 +-
 drivers/ata/pata_hpt3x2n.c           |   11 +-
 drivers/ata/pata_hpt3x3.c            |   10 +-
 drivers/ata/pata_icside.c            |   39 +-
 drivers/ata/pata_isapnp.c            |    8 +-
 drivers/ata/pata_it8213.c            |   11 +-
 drivers/ata/pata_it821x.c            |   17 +-
 drivers/ata/pata_ixp4xx_cf.c         |   24 +-
 drivers/ata/pata_jmicron.c           |   24 +-
 drivers/ata/pata_legacy.c            |   27 +-
 drivers/ata/pata_marvell.c           |   12 +-
 drivers/ata/pata_mpc52xx.c           |    9 +-
 drivers/ata/pata_mpiix.c             |   25 +-
 drivers/ata/pata_netcell.c           |    5 +-
 drivers/ata/pata_ns87410.c           |   11 +-
 drivers/ata/pata_ns87415.c           |  467 ++++++++++
 drivers/ata/pata_oldpiix.c           |   11 +-
 drivers/ata/pata_opti.c              |   11 +-
 drivers/ata/pata_optidma.c           |   26 +-
 drivers/ata/pata_pcmcia.c            |   16 +-
 drivers/ata/pata_pdc2027x.c          |  114 ++--
 drivers/ata/pata_pdc202xx_old.c      |   23 +-
 drivers/ata/pata_platform.c          |   16 +-
 drivers/ata/pata_qdi.c               |   15 +-
 drivers/ata/pata_radisys.c           |    4 +-
 drivers/ata/pata_rz1000.c            |   13 +-
 drivers/ata/pata_sc1200.c            |    4 +-
 drivers/ata/pata_scc.c               |   66 +-
 drivers/ata/pata_serverworks.c       |    8 +-
 drivers/ata/pata_sil680.c            |   11 +-
 drivers/ata/pata_sis.c               |   33 +-
 drivers/ata/pata_sl82c105.c          |   11 +-
 drivers/ata/pata_triflex.c           |   11 +-
 drivers/ata/pata_via.c               |   16 +-
 drivers/ata/pata_winbond.c           |   13 +-
 drivers/ata/pdc_adma.c               |  103 ++-
 drivers/ata/sata_inic162x.c          |   34 +-
 drivers/ata/sata_mv.c                |   68 +-
 drivers/ata/sata_nv.c                |   53 +-
 drivers/ata/sata_promise.c           |   27 +-
 drivers/ata/sata_qstor.c             |   17 +-
 drivers/ata/sata_sil.c               |   53 +-
 drivers/ata/sata_sil24.c             |  341 ++++++--
 drivers/ata/sata_sis.c               |    2 -
 drivers/ata/sata_svw.c               |   14 +-
 drivers/ata/sata_sx4.c               |   25 +-
 drivers/ata/sata_uli.c               |   16 +-
 drivers/ata/sata_via.c               |   35 +-
 drivers/ata/sata_vsc.c               |   16 +-
 drivers/scsi/ipr.c                   |   19 +-
 drivers/scsi/libsas/sas_ata.c        |   11 +-
 include/asm-generic/libata-portmap.h |    5 -
 include/linux/ata.h                  |  116 +++-
 include/linux/libata.h               |  320 +++++--
 82 files changed, 7866 insertions(+), 2064 deletions(-)
 create mode 100644 drivers/ata/libata-pmp.c
 create mode 100644 drivers/ata/pata_acpi.c
 create mode 100644 drivers/ata/pata_at32.c
 create mode 100644 drivers/ata/pata_bf54x.c
 create mode 100644 drivers/ata/pata_ns87415.c

Alan Cox (22):
      libata: Correct IORDY handling
      libata-core: Document some limits/assumptions about ID_ATA
      libata: Note that our cache flush code needs fixing up
      pata_cmd64x: Set up MWDMA modes properly
      [libata] add ACPI cable detect API
      libata pata_amd: ACPI checks for 80wire cable
      libata pata_via: ACPI checks for 80wire cable
      libata: Switch most of the remaining SFF drivers to ata_sff_port_start
      libata-portmap: Remove unused definitions
      libata: Spot bridge chips
      libata: Strict checking for identify reporting
      libata: Update experimental tags to reflect reality better
      pdc2027x: Switch properly to ioread/iowrite
      pata_atiixp: Audit notes on locking
      pata_pdc202xx_old MWDMA fixes, and notes
      pata_ns87415: Initial cut at 87415/87560 IDE support
      libata: Fix HPA handling regression
      libata: Add a drivers/ide style DMA disable
      libata: correct handling of SRST reset sequences
      libata_scsi: Fix ATAPI transfer lengths
      libata-core: Expose gtm methods for driver use
      pata_acpi: ACPI driver support

Albert Lee (2):
      libata: move ata_altstatus() to pio data xfer functions
      libata: pata_pdc2027x PLL detection minor cleanup

Andrew Morton (1):
      libata-add-irq_flags-to-struct-pata_platform_info-fix

Boaz Harrosh (2):
      libata-scsi: Remove !use_sg code paths
      libata-scsi: convert to use the data buffer accessors

Christian Lamparter (1):
      ata_piix: disallow UDMA 133 on ICH5 & ICH7

Dave Jones (1):
      libata: correct kernel parameter in documentation.

David Milburn (1):
      libata-core: blacklist HITACHI HDS drives using wildcard blacklist matching

Jason Gaston (2):
      ata_piix: replace spaces with tabs
      ahci: RAID mode SATA patch for Intel Tolapai

Jeff Garzik (14):
      [libata] pdc_adma: convert to new exception handling (EH) framework
      [libata] Remove ->irq_ack() hook, and ata_dummy_irq_on()
      [libata] Remove ->port_disable() hook
      [libata] ata_piix: Use more-robust form of array initialization
      [libata] blacklist Maxtor*BANC* using new wildcard blacklist matching
      [libata] SCSI: support INQUIRY page 89h (ATA info page)
      [libata] Slightly improved no-op REQUEST SENSE, SEND DIAGNOSTIC
      [libata] SCSI: improve FORMAT UNIT; minor code cleanups
      [libata] SCSI: clean up R/W recovery mode page
      [libata] SCSI: simulator version, not device version, belongs in VPD
      [libata] AHCI: enable AHCI mode, before using AHCI reset
      [libata] ata_piix: add HP compaq laptop to short cable list
      [libata] Turn on ACPI by default
      [libata] struct pci_dev related cleanups

Kristen Carlson Accardi (4):
      [libata] check for SATA async notify support
      [libata] ahci: send event when AN received
      ahci: Store interrupt value
      ata: increase allowed config flags

Kristoffer Nyborg Gregertsen (1):
      AVR32 PATA driver

Mark Lord (1):
      libata: add support for ATA_16 on ATAPI

Matthew Garrett (1):
      libata: Integrate ACPI-based PATA/SATA hotplug - version 5

Paolo Ornati (1):
      libata: blacklist NCQ on Seagate Barracuda ST380817AS

Peer Chen (1):
      ahci: Add MCP79 support to AHCI driver

Robert Hancock (1):
      libata: add human-readable error value decoding

Satyam Sharma (1):
      libata: Fix build failure on ppc64 drivers/ata/pata_scc.c

Sonic Zhang (1):
      libata driver for bf548 on chip ATAPI controller.

Tejun Heo (61):
      libata-link: introduce ata_link
      libata-link: implement and use link/device iterators
      libata-link: linkify PHY-related functions
      libata-link: linkify EH action helpers
      libata-link: linkify reset
      libata-link: linkify config/EH related functions
      libata-link: make two port flags HRST_TO_RESUME and SKIP_D2H_BSY link flags
      libata-link: separate out link initialization functions
      libata-link: implement ata_link_abort()
      libata-link: add PMP links
      libata-link: update ata_scsi_error() to handle PMP links
      libata-link: update EH to deal with PMP links
      libata-link: update hotplug to handle PMP links
      libata-link: update Power Management to handle PMP links
      libata: use ata_port_printk() in ata_wait_idle()
      libata: add printf format attribute to ehi desc functions
      libata: implement and use ata_port_desc() to report port configuration
      libata: move EH repeat reporting into ata_eh_report()
      libata: move ata_id_n_sectors() upward
      libata: clean up read/set native_max address functions
      libata: remiplement ata_hpa_resize()
      ahci: reimplement port_map handling
      libata: update ata_dev_try_classify() arguments
      libata: assume ATA_DEV_ATA on diagnostic failure
      libata: misc updates for AN
      libata-pmp-prep: add PMP related constants, fields, ops and update helpers
      libata-pmp-prep: add @new_class to ata_dev_revalidate()
      libata-pmp-prep: make a number of functions global to libata
      libata-pmp-prep: implement ops->qc_defer()
      libata-pmp-prep: implement qc_defer helpers
      libata-pmp-prep: implement ATA_LFLAG_NO_SRST, ASSUME_ATA and ASSUME_SEMB
      libata-pmp-prep: implement ATA_LFLAG_NO_RETRY
      libata-pmp-prep: implement ATA_LFLAG_DISABLED
      libata-pmp-prep: implement EH fast-fail path
      libata-pmp-prep: implement ATA_HORKAGE_SKIP_PM
      libata-pmp-prep: implement sata_async_notification()
      libata: fix ata_set_max_sectors()
      sata_via: kill SATA_PATA_SHARING register handling
      libata: update spurious NCQ completion blacklist
      libata-pmp: update ata_eh_reset() for PMP
      libata-pmp: implement Port Multiplier support
      libata-pmp: hook PMP support and enable it
      libata-pmp: extend ACPI support to cover PMP
      libata-pmp: implement qc_defer for command switching PMP support
      sata_sil24: implement PMP support
      sata_sil24: implement PORT_RST
      ahci: implement PMP support
      ahci: move host flags over to pi.private_data
      ahci: implement AHCI_HFLAG_NO_PMP
      libata: add HDT722516DLA380 to NCQ blacklist
      libata: add ST9160821AS / 3.ALD to NCQ blacklist
      pata_jmicron: match vendor and class code only
      libata: clear ehi description after initial host report
      libata: skip suppress reporting if ATA_EHI_QUIET
      libata: wrap schedule_timeout_uninterruptible() in loop
      ahci: kill leftover from enabling NCQ over PMP
      ahci: clean up PORT_IRQ_BAD_PMP enabling
      ahci: fix notification handling
      libata: add @timeout to ata_exec_internal[_sg]()
      libata: implement ATA_PFLAG_RESETTING
      libata: use ata_exec_internal() for PMP register access

[patch snipped due to size; grab it from git]


^ permalink raw reply	[flat|nested] 15+ messages in thread

* [git patches] libata update
@ 2006-09-24 16:29 Jeff Garzik
  0 siblings, 0 replies; 15+ messages in thread
From: Jeff Garzik @ 2006-09-24 16:29 UTC (permalink / raw)
  To: linux-ide; +Cc: LKML

[just sent upstream; patch in git, it's too big to post]

Notable changes:
* move to drivers/ata
* add Alan's PATA drivers; drivers/ide still primary PATA for some time
* AHCI suspend/resume

Please pull from 'upstream-linus' branch of
master.kernel.org:/pub/scm/linux/kernel/git/jgarzik/libata-dev.git upstream-linus

to receive the following updates:

 Documentation/DocBook/libata.tmpl    |   12 
 drivers/Kconfig                      |    2 
 drivers/Makefile                     |    1 
 drivers/ata/Kconfig                  |  484 ++
 drivers/ata/Makefile                 |   62 
 drivers/ata/ahci.c                   | 1684 +++++++++
 drivers/ata/ata_generic.c            |  252 +
 drivers/ata/ata_piix.c               | 1258 +++++++
 drivers/ata/libata-core.c            | 6171 +++++++++++++++++++++++++++++++++++
 drivers/ata/libata-eh.c              | 2245 ++++++++++++
 drivers/ata/libata-scsi.c            | 3322 ++++++++++++++++++
 drivers/ata/libata-sff.c             | 1121 ++++++
 drivers/ata/libata.h                 |  122 
 drivers/ata/pata_ali.c               |  679 +++
 drivers/ata/pata_amd.c               |  718 ++++
 drivers/ata/pata_artop.c             |  518 ++
 drivers/ata/pata_atiixp.c            |  306 +
 drivers/ata/pata_cmd64x.c            |  505 ++
 drivers/ata/pata_cs5520.c            |  336 +
 drivers/ata/pata_cs5530.c            |  387 ++
 drivers/ata/pata_cs5535.c            |  291 +
 drivers/ata/pata_cypress.c           |  227 +
 drivers/ata/pata_efar.c              |  342 +
 drivers/ata/pata_hpt366.c            |  478 ++
 drivers/ata/pata_hpt37x.c            | 1257 +++++++
 drivers/ata/pata_hpt3x2n.c           |  597 +++
 drivers/ata/pata_hpt3x3.c            |  226 +
 drivers/ata/pata_isapnp.c            |  156 
 drivers/ata/pata_it821x.c            |  847 ++++
 drivers/ata/pata_jmicron.c           |  266 +
 drivers/ata/pata_legacy.c            |  949 +++++
 drivers/ata/pata_mpiix.c             |  313 +
 drivers/ata/pata_netcell.c           |  175 
 drivers/ata/pata_ns87410.c           |  236 +
 drivers/ata/pata_oldpiix.c           |  339 +
 drivers/ata/pata_opti.c              |  292 +
 drivers/ata/pata_optidma.c           |  547 +++
 drivers/ata/pata_pcmcia.c            |  393 ++
 drivers/ata/pata_pdc2027x.c          |  869 ++++
 drivers/ata/pata_pdc202xx_old.c      |  423 ++
 drivers/ata/pata_qdi.c               |  403 ++
 drivers/ata/pata_radisys.c           |  335 +
 drivers/ata/pata_rz1000.c            |  205 +
 drivers/ata/pata_sc1200.c            |  287 +
 drivers/ata/pata_serverworks.c       |  587 +++
 drivers/ata/pata_sil680.c            |  381 ++
 drivers/ata/pata_sis.c               | 1034 +++++
 drivers/ata/pata_sl82c105.c          |  388 ++
 drivers/ata/pata_triflex.c           |  285 +
 drivers/ata/pata_via.c               |  568 +++
 drivers/ata/pdc_adma.c               |  740 ++++
 drivers/ata/sata_mv.c                | 2465 +++++++++++++
 drivers/ata/sata_nv.c                |  595 +++
 drivers/ata/sata_promise.c           |  844 ++++
 drivers/ata/sata_promise.h           |  157 
 drivers/ata/sata_qstor.c             |  730 ++++
 drivers/ata/sata_sil.c               |  728 ++++
 drivers/ata/sata_sil24.c             | 1227 ++++++
 drivers/ata/sata_sis.c               |  347 +
 drivers/ata/sata_svw.c               |  508 ++
 drivers/ata/sata_sx4.c               | 1502 ++++++++
 drivers/ata/sata_uli.c               |  300 +
 drivers/ata/sata_via.c               |  502 ++
 drivers/ata/sata_vsc.c               |  482 ++
 drivers/pci/quirks.c                 |    6 
 drivers/scsi/Kconfig                 |  138 
 drivers/scsi/Makefile                |   16 
 drivers/scsi/ahci.c                  | 1473 --------
 drivers/scsi/ata_piix.c              | 1040 -----
 drivers/scsi/libata-bmdma.c          | 1149 ------
 drivers/scsi/libata-core.c           | 6020 ----------------------------------
 drivers/scsi/libata-eh.c             | 2245 ------------
 drivers/scsi/libata-scsi.c           | 3173 -----------------
 drivers/scsi/libata.h                |  117 
 drivers/scsi/pdc_adma.c              |  740 ----
 drivers/scsi/sata_mv.c               | 2467 -------------
 drivers/scsi/sata_nv.c               |  595 ---
 drivers/scsi/sata_promise.c          |  844 ----
 drivers/scsi/sata_promise.h          |  157 
 drivers/scsi/sata_qstor.c            |  730 ----
 drivers/scsi/sata_sil.c              |  727 ----
 drivers/scsi/sata_sil24.c            | 1222 ------
 drivers/scsi/sata_sis.c              |  347 -
 drivers/scsi/sata_svw.c              |  508 --
 drivers/scsi/sata_sx4.c              | 1502 --------
 drivers/scsi/sata_uli.c              |  300 -
 drivers/scsi/sata_via.c              |  502 --
 drivers/scsi/sata_vsc.c              |  482 --
 include/asm-alpha/libata-portmap.h   |    1 
 include/asm-generic/libata-portmap.h |   12 
 include/asm-i386/libata-portmap.h    |    1 
 include/asm-ia64/libata-portmap.h    |    1 
 include/asm-powerpc/libata-portmap.h |    1 
 include/asm-sparc/libata-portmap.h   |    1 
 include/asm-sparc64/libata-portmap.h |    1 
 include/asm-x86_64/libata-portmap.h  |    1 
 include/linux/ata.h                  |   26 
 include/linux/libata.h               |   90 
 98 files changed, 45107 insertions(+), 26536 deletions(-)

Alan Cox:
      libata: rework legacy handling to remove much of the cruft
      libata: Add CompactFlash support
      Update SiS PATA
      pata_amd: Check enable bits on Nvidia
      libata: improve handling of diagostic fail (and hardware that misreports it)

Alexey Dobriyan:
      CONFIG_PM=n slim: drivers/scsi/sata_sil*

Arnaud Patard:
      Fix libata resource conflict for legacy mode

Brian King:
      libata: Add ata_host_set_init
      libata: Add ata_port_init
      libata: Move ata_probe_ent_alloc to libata_core
      libata: Add support for SATA attachment to SAS adapters

Henrik Kretzschmar:
      libata: change path to libata in libata.tmpl

Jay Cliburn:
      sata_via: Add SATA support for vt8237a

Jeff Garzik:
      [libata] ahci: add SiS PCI IDs
      [libata] some function renaming
      [libata] Kill 'count' var in ata_device_add()
      [ATA] Increase lba48 max-sectors from 200 to 256.
      Move libata to drivers/ata.
      libata: Remove SCSI_ prefix from Kconfig symbols
      libata: Separate libata.ko build from individual driver builds
      [libata] ata_piix: add missing kfree()
      libata: Make sure drivers/ata is a separate Kconfig menu
      Clean up drivers/ata/Kconfig a bit.
      libata: Grand renaming.
      Rename libata-bmdma.c to libata-sff.c.
      [libata] Add a bunch of PATA drivers.
      [libata] Trim trailing whitespace.
      [libata #pata-drivers] Trim trailing whitespace.
      [libata] Add pata_jmicron driver to Kconfig, Makefile
      [libata] ata_piix: build fix
      [libata] Delete pata_it8172 driver

Pavel Roskin:
      libata: replace pci_module_init() with pci_register_driver()

Tejun Heo:
      sata_sil: remove unaffected drives from m15w blacklist
      ahci: relocate several internal functions
      ahci: cosmetic changes to ahci_start/stop_engine()
      ahci: simplify ahci_start_engine()
      libata: improve driver initialization and deinitialization
      ahci: separate out ahci_reset_controller() and ahci_init_controller()
      ahci: implement Power Management support
      libata: cosmetic changes to PM functions
      ahci: remove IRQ mask clearing from init_controller()
      libata: update ata_host_init() and rename it to ata_port_init_shost()
      libata: implement per-dev xfermask
      libata: implement dummy port
      libata: use dummy port for stolen legacy ports
      libata: replace ap->hard_port_no with ap->port_no
      libata: kill unused hard_port_no and legacy_mode
      libata: s/CONFIG_SCSI_SATA/CONFIG_[S]ATA/g in pci/quirks.c
      libata: fix non-uniform ports handling

zhao, forrest:
      The redefinition of ahci_start_engine() and ahci_stop_engine()


^ permalink raw reply	[flat|nested] 15+ messages in thread

* [git patches] libata update
@ 2006-07-06  3:07 Jeff Garzik
  0 siblings, 0 replies; 15+ messages in thread
From: Jeff Garzik @ 2006-07-06  3:07 UTC (permalink / raw)
  To: Andrew Morton, Linus Torvalds; +Cc: linux-ide, linux-kernel


Please pull from 'upstream-linus' branch of
master.kernel.org:/pub/scm/linux/kernel/git/jgarzik/libata-dev.git upstream-linus

to receive the following updates:

 drivers/scsi/ahci.c        |   17 +
 drivers/scsi/libata-core.c |  289 ++++++++++++++++++++------------
 drivers/scsi/libata-eh.c   |  405 +++++++++++++++++++++++++++++++++++++++------
 drivers/scsi/libata-scsi.c |  124 +++++++++++++
 drivers/scsi/sata_sil.c    |  105 +++++++----
 drivers/scsi/sata_sil24.c  |  134 +++++++++-----
 drivers/scsi/sata_vsc.c    |    2 
 include/linux/libata.h     |   85 +++++++--
 include/linux/pci_ids.h    |    7 
 9 files changed, 897 insertions(+), 271 deletions(-)

Borislav Petkov:
      libata-core.c: restore configuration boot messages in ata_dev_configure(), v2

Brian King:
      libata: Conditionally set host->max_cmd_len

Jeff Garzik:
      [PCI] Add JMicron PCI ID constants

Martin Hicks:
      sata_vsc: data_xfer should use mmio

root:
      ahci: Ensure that we don't grab both functions

Tejun Heo:
      libata: add ap->pflags and move core dynamic flags to it
      libata: fix ehc->i.action setting in ata_eh_autopsy()
      libata: replace ap_lock w/ ap->lock in ata_scsi_error()
      libata: implement ATA_EHI_RESUME_LINK
      libata: clean up debounce parameters and improve parameter selection
      libata: implement ATA_EHI_NO_AUTOPSY and QUIET
      libata: separate out __ata_ehi_hotplugged()
      libata: implement PM EH actions
      libata: reimplement per-dev PM
      libata: reimplement controller-wide PM
      sata_sil: separate out sil_init_controller()
      sata_sil: add suspend/sleep support
      sata_sil24: separate out sil24_init_controller()
      sata_sil24: add suspend/sleep support

diff --git a/drivers/scsi/ahci.c b/drivers/scsi/ahci.c
index 15f6cd4..77e7202 100644
--- a/drivers/scsi/ahci.c
+++ b/drivers/scsi/ahci.c
@@ -1052,7 +1052,7 @@ static void ahci_thaw(struct ata_port *a
 
 static void ahci_error_handler(struct ata_port *ap)
 {
-	if (!(ap->flags & ATA_FLAG_FROZEN)) {
+	if (!(ap->pflags & ATA_PFLAG_FROZEN)) {
 		/* restart engine */
 		ahci_stop_engine(ap);
 		ahci_start_engine(ap);
@@ -1323,6 +1323,17 @@ static int ahci_init_one (struct pci_dev
 	if (!printed_version++)
 		dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n");
 
+	/* JMicron-specific fixup: make sure we're in AHCI mode */
+	/* This is protected from races with ata_jmicron by the pci probe
+	   locking */
+	if (pdev->vendor == PCI_VENDOR_ID_JMICRON) {
+		/* AHCI enable, AHCI on function 0 */
+		pci_write_config_byte(pdev, 0x41, 0xa1);
+		/* Function 1 is the PATA controller */
+		if (PCI_FUNC(pdev->devfn))
+			return -ENODEV;
+	}
+
 	rc = pci_enable_device(pdev);
 	if (rc)
 		return rc;
@@ -1378,10 +1389,6 @@ static int ahci_init_one (struct pci_dev
 	if (have_msi)
 		hpriv->flags |= AHCI_FLAG_MSI;
 
-	/* JMicron-specific fixup: make sure we're in AHCI mode */
-	if (pdev->vendor == 0x197b)
-		pci_write_config_byte(pdev, 0x41, 0xa1);
-
 	/* initialize adapter */
 	rc = ahci_host_init(probe_ent);
 	if (rc)
diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c
index 1c960ac..386e5f2 100644
--- a/drivers/scsi/libata-core.c
+++ b/drivers/scsi/libata-core.c
@@ -61,9 +61,9 @@ #include <asm/byteorder.h>
 #include "libata.h"
 
 /* debounce timing parameters in msecs { interval, duration, timeout } */
-const unsigned long sata_deb_timing_boot[]		= {   5,  100, 2000 };
-const unsigned long sata_deb_timing_eh[]		= {  25,  500, 2000 };
-const unsigned long sata_deb_timing_before_fsrst[]	= { 100, 2000, 5000 };
+const unsigned long sata_deb_timing_normal[]		= {   5,  100, 2000 };
+const unsigned long sata_deb_timing_hotplug[]		= {  25,  500, 2000 };
+const unsigned long sata_deb_timing_long[]		= { 100, 2000, 5000 };
 
 static unsigned int ata_dev_init_params(struct ata_device *dev,
 					u16 heads, u16 sectors);
@@ -907,7 +907,7 @@ void ata_port_queue_task(struct ata_port
 {
 	int rc;
 
-	if (ap->flags & ATA_FLAG_FLUSH_PORT_TASK)
+	if (ap->pflags & ATA_PFLAG_FLUSH_PORT_TASK)
 		return;
 
 	PREPARE_WORK(&ap->port_task, fn, data);
@@ -938,7 +938,7 @@ void ata_port_flush_task(struct ata_port
 	DPRINTK("ENTER\n");
 
 	spin_lock_irqsave(ap->lock, flags);
-	ap->flags |= ATA_FLAG_FLUSH_PORT_TASK;
+	ap->pflags |= ATA_PFLAG_FLUSH_PORT_TASK;
 	spin_unlock_irqrestore(ap->lock, flags);
 
 	DPRINTK("flush #1\n");
@@ -957,7 +957,7 @@ void ata_port_flush_task(struct ata_port
 	}
 
 	spin_lock_irqsave(ap->lock, flags);
-	ap->flags &= ~ATA_FLAG_FLUSH_PORT_TASK;
+	ap->pflags &= ~ATA_PFLAG_FLUSH_PORT_TASK;
 	spin_unlock_irqrestore(ap->lock, flags);
 
 	if (ata_msg_ctl(ap))
@@ -1009,7 +1009,7 @@ unsigned ata_exec_internal(struct ata_de
 	spin_lock_irqsave(ap->lock, flags);
 
 	/* no internal command while frozen */
-	if (ap->flags & ATA_FLAG_FROZEN) {
+	if (ap->pflags & ATA_PFLAG_FROZEN) {
 		spin_unlock_irqrestore(ap->lock, flags);
 		return AC_ERR_SYSTEM;
 	}
@@ -1325,6 +1325,19 @@ static void ata_dev_config_ncq(struct at
 		snprintf(desc, desc_sz, "NCQ (depth %d/%d)", hdepth, ddepth);
 }
 
+static void ata_set_port_max_cmd_len(struct ata_port *ap)
+{
+	int i;
+
+	if (ap->host) {
+		ap->host->max_cmd_len = 0;
+		for (i = 0; i < ATA_MAX_DEVICES; i++)
+			ap->host->max_cmd_len = max_t(unsigned int,
+						      ap->host->max_cmd_len,
+						      ap->device[i].cdb_len);
+	}
+}
+
 /**
  *	ata_dev_configure - Configure the specified ATA/ATAPI device
  *	@dev: Target device to configure
@@ -1344,7 +1357,7 @@ int ata_dev_configure(struct ata_device 
 	struct ata_port *ap = dev->ap;
 	const u16 *id = dev->id;
 	unsigned int xfer_mask;
-	int i, rc;
+	int rc;
 
 	if (!ata_dev_enabled(dev) && ata_msg_info(ap)) {
 		ata_dev_printk(dev, KERN_INFO,
@@ -1404,7 +1417,7 @@ int ata_dev_configure(struct ata_device 
 			ata_dev_config_ncq(dev, ncq_desc, sizeof(ncq_desc));
 
 			/* print device info to dmesg */
-			if (ata_msg_info(ap))
+			if (ata_msg_drv(ap) && print_info)
 				ata_dev_printk(dev, KERN_INFO, "ATA-%d, "
 					"max %s, %Lu sectors: %s %s\n",
 					ata_id_major_version(id),
@@ -1427,7 +1440,7 @@ int ata_dev_configure(struct ata_device 
 			}
 
 			/* print device info to dmesg */
-			if (ata_msg_info(ap))
+			if (ata_msg_drv(ap) && print_info)
 				ata_dev_printk(dev, KERN_INFO, "ATA-%d, "
 					"max %s, %Lu sectors: CHS %u/%u/%u\n",
 					ata_id_major_version(id),
@@ -1439,7 +1452,7 @@ int ata_dev_configure(struct ata_device 
 
 		if (dev->id[59] & 0x100) {
 			dev->multi_count = dev->id[59] & 0xff;
-			if (ata_msg_info(ap))
+			if (ata_msg_drv(ap) && print_info)
 				ata_dev_printk(dev, KERN_INFO,
 					"ata%u: dev %u multi count %u\n",
 					ap->id, dev->devno, dev->multi_count);
@@ -1468,21 +1481,17 @@ int ata_dev_configure(struct ata_device 
 		}
 
 		/* print device info to dmesg */
-		if (ata_msg_info(ap))
+		if (ata_msg_drv(ap) && print_info)
 			ata_dev_printk(dev, KERN_INFO, "ATAPI, max %s%s\n",
 				       ata_mode_string(xfer_mask),
 				       cdb_intr_string);
 	}
 
-	ap->host->max_cmd_len = 0;
-	for (i = 0; i < ATA_MAX_DEVICES; i++)
-		ap->host->max_cmd_len = max_t(unsigned int,
-					      ap->host->max_cmd_len,
-					      ap->device[i].cdb_len);
+	ata_set_port_max_cmd_len(ap);
 
 	/* limit bridge transfers to udma5, 200 sectors */
 	if (ata_dev_knobble(dev)) {
-		if (ata_msg_info(ap))
+		if (ata_msg_drv(ap) && print_info)
 			ata_dev_printk(dev, KERN_INFO,
 				       "applying bridge limits\n");
 		dev->udma_mask &= ATA_UDMA5;
@@ -2137,7 +2146,7 @@ int ata_set_mode(struct ata_port *ap, st
 		 * return error code and failing device on failure.
 		 */
 		for (i = 0; i < ATA_MAX_DEVICES; i++) {
-			if (ata_dev_enabled(&ap->device[i])) {
+			if (ata_dev_ready(&ap->device[i])) {
 				ap->ops->set_mode(ap);
 				break;
 			}
@@ -2203,7 +2212,8 @@ int ata_set_mode(struct ata_port *ap, st
 	for (i = 0; i < ATA_MAX_DEVICES; i++) {
 		dev = &ap->device[i];
 
-		if (!ata_dev_enabled(dev))
+		/* don't udpate suspended devices' xfer mode */
+		if (!ata_dev_ready(dev))
 			continue;
 
 		rc = ata_dev_set_mode(dev);
@@ -2579,7 +2589,7 @@ static void ata_wait_spinup(struct ata_p
 
 	/* first, debounce phy if SATA */
 	if (ap->cbl == ATA_CBL_SATA) {
-		rc = sata_phy_debounce(ap, sata_deb_timing_eh);
+		rc = sata_phy_debounce(ap, sata_deb_timing_hotplug);
 
 		/* if debounced successfully and offline, no need to wait */
 		if ((rc == 0 || rc == -EOPNOTSUPP) && ata_port_offline(ap))
@@ -2615,16 +2625,17 @@ static void ata_wait_spinup(struct ata_p
 int ata_std_prereset(struct ata_port *ap)
 {
 	struct ata_eh_context *ehc = &ap->eh_context;
-	const unsigned long *timing;
+	const unsigned long *timing = sata_ehc_deb_timing(ehc);
 	int rc;
 
-	/* hotplug? */
-	if (ehc->i.flags & ATA_EHI_HOTPLUGGED) {
-		if (ap->flags & ATA_FLAG_HRST_TO_RESUME)
-			ehc->i.action |= ATA_EH_HARDRESET;
-		if (ap->flags & ATA_FLAG_SKIP_D2H_BSY)
-			ata_wait_spinup(ap);
-	}
+	/* handle link resume & hotplug spinup */
+	if ((ehc->i.flags & ATA_EHI_RESUME_LINK) &&
+	    (ap->flags & ATA_FLAG_HRST_TO_RESUME))
+		ehc->i.action |= ATA_EH_HARDRESET;
+
+	if ((ehc->i.flags & ATA_EHI_HOTPLUGGED) &&
+	    (ap->flags & ATA_FLAG_SKIP_D2H_BSY))
+		ata_wait_spinup(ap);
 
 	/* if we're about to do hardreset, nothing more to do */
 	if (ehc->i.action & ATA_EH_HARDRESET)
@@ -2632,11 +2643,6 @@ int ata_std_prereset(struct ata_port *ap
 
 	/* if SATA, resume phy */
 	if (ap->cbl == ATA_CBL_SATA) {
-		if (ap->flags & ATA_FLAG_LOADING)
-			timing = sata_deb_timing_boot;
-		else
-			timing = sata_deb_timing_eh;
-
 		rc = sata_phy_resume(ap, timing);
 		if (rc && rc != -EOPNOTSUPP) {
 			/* phy resume failed */
@@ -2724,6 +2730,8 @@ int ata_std_softreset(struct ata_port *a
  */
 int sata_std_hardreset(struct ata_port *ap, unsigned int *class)
 {
+	struct ata_eh_context *ehc = &ap->eh_context;
+	const unsigned long *timing = sata_ehc_deb_timing(ehc);
 	u32 scontrol;
 	int rc;
 
@@ -2761,7 +2769,7 @@ int sata_std_hardreset(struct ata_port *
 	msleep(1);
 
 	/* bring phy back */
-	sata_phy_resume(ap, sata_deb_timing_eh);
+	sata_phy_resume(ap, timing);
 
 	/* TODO: phy layer with polling, timeouts, etc. */
 	if (ata_port_offline(ap)) {
@@ -4285,7 +4293,7 @@ static struct ata_queued_cmd *ata_qc_new
 	unsigned int i;
 
 	/* no command while frozen */
-	if (unlikely(ap->flags & ATA_FLAG_FROZEN))
+	if (unlikely(ap->pflags & ATA_PFLAG_FROZEN))
 		return NULL;
 
 	/* the last tag is reserved for internal command. */
@@ -4407,7 +4415,7 @@ void ata_qc_complete(struct ata_queued_c
 	 * taken care of.
 	 */
 	if (ap->ops->error_handler) {
-		WARN_ON(ap->flags & ATA_FLAG_FROZEN);
+		WARN_ON(ap->pflags & ATA_PFLAG_FROZEN);
 
 		if (unlikely(qc->err_mask))
 			qc->flags |= ATA_QCFLAG_FAILED;
@@ -5001,86 +5009,120 @@ int ata_flush_cache(struct ata_device *d
 	return 0;
 }
 
-static int ata_standby_drive(struct ata_device *dev)
+static int ata_host_set_request_pm(struct ata_host_set *host_set,
+				   pm_message_t mesg, unsigned int action,
+				   unsigned int ehi_flags, int wait)
 {
-	unsigned int err_mask;
+	unsigned long flags;
+	int i, rc;
 
-	err_mask = ata_do_simple_cmd(dev, ATA_CMD_STANDBYNOW1);
-	if (err_mask) {
-		ata_dev_printk(dev, KERN_ERR, "failed to standby drive "
-			       "(err_mask=0x%x)\n", err_mask);
-		return -EIO;
-	}
+	for (i = 0; i < host_set->n_ports; i++) {
+		struct ata_port *ap = host_set->ports[i];
 
-	return 0;
-}
+		/* Previous resume operation might still be in
+		 * progress.  Wait for PM_PENDING to clear.
+		 */
+		if (ap->pflags & ATA_PFLAG_PM_PENDING) {
+			ata_port_wait_eh(ap);
+			WARN_ON(ap->pflags & ATA_PFLAG_PM_PENDING);
+		}
 
-static int ata_start_drive(struct ata_device *dev)
-{
-	unsigned int err_mask;
+		/* request PM ops to EH */
+		spin_lock_irqsave(ap->lock, flags);
 
-	err_mask = ata_do_simple_cmd(dev, ATA_CMD_IDLEIMMEDIATE);
-	if (err_mask) {
-		ata_dev_printk(dev, KERN_ERR, "failed to start drive "
-			       "(err_mask=0x%x)\n", err_mask);
-		return -EIO;
+		ap->pm_mesg = mesg;
+		if (wait) {
+			rc = 0;
+			ap->pm_result = &rc;
+		}
+
+		ap->pflags |= ATA_PFLAG_PM_PENDING;
+		ap->eh_info.action |= action;
+		ap->eh_info.flags |= ehi_flags;
+
+		ata_port_schedule_eh(ap);
+
+		spin_unlock_irqrestore(ap->lock, flags);
+
+		/* wait and check result */
+		if (wait) {
+			ata_port_wait_eh(ap);
+			WARN_ON(ap->pflags & ATA_PFLAG_PM_PENDING);
+			if (rc)
+				return rc;
+		}
 	}
 
 	return 0;
 }
 
 /**
- *	ata_device_resume - wakeup a previously suspended devices
- *	@dev: the device to resume
+ *	ata_host_set_suspend - suspend host_set
+ *	@host_set: host_set to suspend
+ *	@mesg: PM message
  *
- *	Kick the drive back into action, by sending it an idle immediate
- *	command and making sure its transfer mode matches between drive
- *	and host.
+ *	Suspend @host_set.  Actual operation is performed by EH.  This
+ *	function requests EH to perform PM operations and waits for EH
+ *	to finish.
  *
+ *	LOCKING:
+ *	Kernel thread context (may sleep).
+ *
+ *	RETURNS:
+ *	0 on success, -errno on failure.
  */
-int ata_device_resume(struct ata_device *dev)
+int ata_host_set_suspend(struct ata_host_set *host_set, pm_message_t mesg)
 {
-	struct ata_port *ap = dev->ap;
+	int i, j, rc;
 
-	if (ap->flags & ATA_FLAG_SUSPENDED) {
-		struct ata_device *failed_dev;
+	rc = ata_host_set_request_pm(host_set, mesg, 0, ATA_EHI_QUIET, 1);
+	if (rc)
+		goto fail;
 
-		ata_busy_sleep(ap, ATA_TMOUT_BOOT_QUICK, ATA_TMOUT_BOOT);
-		ata_busy_wait(ap, ATA_BUSY | ATA_DRQ, 200000);
+	/* EH is quiescent now.  Fail if we have any ready device.
+	 * This happens if hotplug occurs between completion of device
+	 * suspension and here.
+	 */
+	for (i = 0; i < host_set->n_ports; i++) {
+		struct ata_port *ap = host_set->ports[i];
 
-		ap->flags &= ~ATA_FLAG_SUSPENDED;
-		while (ata_set_mode(ap, &failed_dev))
-			ata_dev_disable(failed_dev);
+		for (j = 0; j < ATA_MAX_DEVICES; j++) {
+			struct ata_device *dev = &ap->device[j];
+
+			if (ata_dev_ready(dev)) {
+				ata_port_printk(ap, KERN_WARNING,
+						"suspend failed, device %d "
+						"still active\n", dev->devno);
+				rc = -EBUSY;
+				goto fail;
+			}
+		}
 	}
-	if (!ata_dev_enabled(dev))
-		return 0;
-	if (dev->class == ATA_DEV_ATA)
-		ata_start_drive(dev);
 
+	host_set->dev->power.power_state = mesg;
 	return 0;
+
+ fail:
+	ata_host_set_resume(host_set);
+	return rc;
 }
 
 /**
- *	ata_device_suspend - prepare a device for suspend
- *	@dev: the device to suspend
- *	@state: target power management state
+ *	ata_host_set_resume - resume host_set
+ *	@host_set: host_set to resume
+ *
+ *	Resume @host_set.  Actual operation is performed by EH.  This
+ *	function requests EH to perform PM operations and returns.
+ *	Note that all resume operations are performed parallely.
  *
- *	Flush the cache on the drive, if appropriate, then issue a
- *	standbynow command.
+ *	LOCKING:
+ *	Kernel thread context (may sleep).
  */
-int ata_device_suspend(struct ata_device *dev, pm_message_t state)
+void ata_host_set_resume(struct ata_host_set *host_set)
 {
-	struct ata_port *ap = dev->ap;
-
-	if (!ata_dev_enabled(dev))
-		return 0;
-	if (dev->class == ATA_DEV_ATA)
-		ata_flush_cache(dev);
-
-	if (state.event != PM_EVENT_FREEZE)
-		ata_standby_drive(dev);
-	ap->flags |= ATA_FLAG_SUSPENDED;
-	return 0;
+	ata_host_set_request_pm(host_set, PMSG_ON, ATA_EH_SOFTRESET,
+				ATA_EHI_NO_AUTOPSY | ATA_EHI_QUIET, 0);
+	host_set->dev->power.power_state = PMSG_ON;
 }
 
 /**
@@ -5440,6 +5482,7 @@ int ata_device_add(const struct ata_prob
 		}
 
 		if (ap->ops->error_handler) {
+			struct ata_eh_info *ehi = &ap->eh_info;
 			unsigned long flags;
 
 			ata_port_probe(ap);
@@ -5447,10 +5490,11 @@ int ata_device_add(const struct ata_prob
 			/* kick EH for boot probing */
 			spin_lock_irqsave(ap->lock, flags);
 
-			ap->eh_info.probe_mask = (1 << ATA_MAX_DEVICES) - 1;
-			ap->eh_info.action |= ATA_EH_SOFTRESET;
+			ehi->probe_mask = (1 << ATA_MAX_DEVICES) - 1;
+			ehi->action |= ATA_EH_SOFTRESET;
+			ehi->flags |= ATA_EHI_NO_AUTOPSY | ATA_EHI_QUIET;
 
-			ap->flags |= ATA_FLAG_LOADING;
+			ap->pflags |= ATA_PFLAG_LOADING;
 			ata_port_schedule_eh(ap);
 
 			spin_unlock_irqrestore(ap->lock, flags);
@@ -5518,7 +5562,7 @@ void ata_port_detach(struct ata_port *ap
 
 	/* tell EH we're leaving & flush EH */
 	spin_lock_irqsave(ap->lock, flags);
-	ap->flags |= ATA_FLAG_UNLOADING;
+	ap->pflags |= ATA_PFLAG_UNLOADING;
 	spin_unlock_irqrestore(ap->lock, flags);
 
 	ata_port_wait_eh(ap);
@@ -5723,20 +5767,55 @@ int pci_test_config_bits(struct pci_dev 
 	return (tmp == bits->val) ? 1 : 0;
 }
 
-int ata_pci_device_suspend(struct pci_dev *pdev, pm_message_t state)
+void ata_pci_device_do_suspend(struct pci_dev *pdev, pm_message_t state)
 {
 	pci_save_state(pdev);
-	pci_disable_device(pdev);
-	pci_set_power_state(pdev, PCI_D3hot);
-	return 0;
+
+	if (state.event == PM_EVENT_SUSPEND) {
+		pci_disable_device(pdev);
+		pci_set_power_state(pdev, PCI_D3hot);
+	}
 }
 
-int ata_pci_device_resume(struct pci_dev *pdev)
+void ata_pci_device_do_resume(struct pci_dev *pdev)
 {
 	pci_set_power_state(pdev, PCI_D0);
 	pci_restore_state(pdev);
 	pci_enable_device(pdev);
 	pci_set_master(pdev);
+}
+
+int ata_pci_device_suspend(struct pci_dev *pdev, pm_message_t state)
+{
+	struct ata_host_set *host_set = dev_get_drvdata(&pdev->dev);
+	int rc = 0;
+
+	rc = ata_host_set_suspend(host_set, state);
+	if (rc)
+		return rc;
+
+	if (host_set->next) {
+		rc = ata_host_set_suspend(host_set->next, state);
+		if (rc) {
+			ata_host_set_resume(host_set);
+			return rc;
+		}
+	}
+
+	ata_pci_device_do_suspend(pdev, state);
+
+	return 0;
+}
+
+int ata_pci_device_resume(struct pci_dev *pdev)
+{
+	struct ata_host_set *host_set = dev_get_drvdata(&pdev->dev);
+
+	ata_pci_device_do_resume(pdev);
+	ata_host_set_resume(host_set);
+	if (host_set->next)
+		ata_host_set_resume(host_set->next);
+
 	return 0;
 }
 #endif /* CONFIG_PCI */
@@ -5842,9 +5921,9 @@ u32 ata_wait_register(void __iomem *reg,
  * Do not depend on ABI/API stability.
  */
 
-EXPORT_SYMBOL_GPL(sata_deb_timing_boot);
-EXPORT_SYMBOL_GPL(sata_deb_timing_eh);
-EXPORT_SYMBOL_GPL(sata_deb_timing_before_fsrst);
+EXPORT_SYMBOL_GPL(sata_deb_timing_normal);
+EXPORT_SYMBOL_GPL(sata_deb_timing_hotplug);
+EXPORT_SYMBOL_GPL(sata_deb_timing_long);
 EXPORT_SYMBOL_GPL(ata_std_bios_param);
 EXPORT_SYMBOL_GPL(ata_std_ports);
 EXPORT_SYMBOL_GPL(ata_device_add);
@@ -5916,6 +5995,8 @@ EXPORT_SYMBOL_GPL(sata_scr_write);
 EXPORT_SYMBOL_GPL(sata_scr_write_flush);
 EXPORT_SYMBOL_GPL(ata_port_online);
 EXPORT_SYMBOL_GPL(ata_port_offline);
+EXPORT_SYMBOL_GPL(ata_host_set_suspend);
+EXPORT_SYMBOL_GPL(ata_host_set_resume);
 EXPORT_SYMBOL_GPL(ata_id_string);
 EXPORT_SYMBOL_GPL(ata_id_c_string);
 EXPORT_SYMBOL_GPL(ata_scsi_simulate);
@@ -5930,14 +6011,14 @@ EXPORT_SYMBOL_GPL(ata_pci_host_stop);
 EXPORT_SYMBOL_GPL(ata_pci_init_native_mode);
 EXPORT_SYMBOL_GPL(ata_pci_init_one);
 EXPORT_SYMBOL_GPL(ata_pci_remove_one);
+EXPORT_SYMBOL_GPL(ata_pci_device_do_suspend);
+EXPORT_SYMBOL_GPL(ata_pci_device_do_resume);
 EXPORT_SYMBOL_GPL(ata_pci_device_suspend);
 EXPORT_SYMBOL_GPL(ata_pci_device_resume);
 EXPORT_SYMBOL_GPL(ata_pci_default_filter);
 EXPORT_SYMBOL_GPL(ata_pci_clear_simplex);
 #endif /* CONFIG_PCI */
 
-EXPORT_SYMBOL_GPL(ata_device_suspend);
-EXPORT_SYMBOL_GPL(ata_device_resume);
 EXPORT_SYMBOL_GPL(ata_scsi_device_suspend);
 EXPORT_SYMBOL_GPL(ata_scsi_device_resume);
 
diff --git a/drivers/scsi/libata-eh.c b/drivers/scsi/libata-eh.c
index bf5a72a..4b6aa30 100644
--- a/drivers/scsi/libata-eh.c
+++ b/drivers/scsi/libata-eh.c
@@ -47,6 +47,8 @@ #include "libata.h"
 
 static void __ata_port_freeze(struct ata_port *ap);
 static void ata_eh_finish(struct ata_port *ap);
+static void ata_eh_handle_port_suspend(struct ata_port *ap);
+static void ata_eh_handle_port_resume(struct ata_port *ap);
 
 static void ata_ering_record(struct ata_ering *ering, int is_io,
 			     unsigned int err_mask)
@@ -190,7 +192,6 @@ enum scsi_eh_timer_return ata_scsi_timed
 void ata_scsi_error(struct Scsi_Host *host)
 {
 	struct ata_port *ap = ata_shost_to_port(host);
-	spinlock_t *ap_lock = ap->lock;
 	int i, repeat_cnt = ATA_EH_MAX_REPEAT;
 	unsigned long flags;
 
@@ -217,7 +218,7 @@ void ata_scsi_error(struct Scsi_Host *ho
 		struct scsi_cmnd *scmd, *tmp;
 		int nr_timedout = 0;
 
-		spin_lock_irqsave(ap_lock, flags);
+		spin_lock_irqsave(ap->lock, flags);
 
 		list_for_each_entry_safe(scmd, tmp, &host->eh_cmd_q, eh_entry) {
 			struct ata_queued_cmd *qc;
@@ -256,43 +257,49 @@ void ata_scsi_error(struct Scsi_Host *ho
 		if (nr_timedout)
 			__ata_port_freeze(ap);
 
-		spin_unlock_irqrestore(ap_lock, flags);
+		spin_unlock_irqrestore(ap->lock, flags);
 	} else
-		spin_unlock_wait(ap_lock);
+		spin_unlock_wait(ap->lock);
 
  repeat:
 	/* invoke error handler */
 	if (ap->ops->error_handler) {
+		/* process port resume request */
+		ata_eh_handle_port_resume(ap);
+
 		/* fetch & clear EH info */
-		spin_lock_irqsave(ap_lock, flags);
+		spin_lock_irqsave(ap->lock, flags);
 
 		memset(&ap->eh_context, 0, sizeof(ap->eh_context));
 		ap->eh_context.i = ap->eh_info;
 		memset(&ap->eh_info, 0, sizeof(ap->eh_info));
 
-		ap->flags |= ATA_FLAG_EH_IN_PROGRESS;
-		ap->flags &= ~ATA_FLAG_EH_PENDING;
+		ap->pflags |= ATA_PFLAG_EH_IN_PROGRESS;
+		ap->pflags &= ~ATA_PFLAG_EH_PENDING;
 
-		spin_unlock_irqrestore(ap_lock, flags);
+		spin_unlock_irqrestore(ap->lock, flags);
 
-		/* invoke EH.  if unloading, just finish failed qcs */
-		if (!(ap->flags & ATA_FLAG_UNLOADING))
+		/* invoke EH, skip if unloading or suspended */
+		if (!(ap->pflags & (ATA_PFLAG_UNLOADING | ATA_PFLAG_SUSPENDED)))
 			ap->ops->error_handler(ap);
 		else
 			ata_eh_finish(ap);
 
+		/* process port suspend request */
+		ata_eh_handle_port_suspend(ap);
+
 		/* Exception might have happend after ->error_handler
 		 * recovered the port but before this point.  Repeat
 		 * EH in such case.
 		 */
-		spin_lock_irqsave(ap_lock, flags);
+		spin_lock_irqsave(ap->lock, flags);
 
-		if (ap->flags & ATA_FLAG_EH_PENDING) {
+		if (ap->pflags & ATA_PFLAG_EH_PENDING) {
 			if (--repeat_cnt) {
 				ata_port_printk(ap, KERN_INFO,
 					"EH pending after completion, "
 					"repeating EH (cnt=%d)\n", repeat_cnt);
-				spin_unlock_irqrestore(ap_lock, flags);
+				spin_unlock_irqrestore(ap->lock, flags);
 				goto repeat;
 			}
 			ata_port_printk(ap, KERN_ERR, "EH pending after %d "
@@ -302,14 +309,14 @@ void ata_scsi_error(struct Scsi_Host *ho
 		/* this run is complete, make sure EH info is clear */
 		memset(&ap->eh_info, 0, sizeof(ap->eh_info));
 
-		/* Clear host_eh_scheduled while holding ap_lock such
+		/* Clear host_eh_scheduled while holding ap->lock such
 		 * that if exception occurs after this point but
 		 * before EH completion, SCSI midlayer will
 		 * re-initiate EH.
 		 */
 		host->host_eh_scheduled = 0;
 
-		spin_unlock_irqrestore(ap_lock, flags);
+		spin_unlock_irqrestore(ap->lock, flags);
 	} else {
 		WARN_ON(ata_qc_from_tag(ap, ap->active_tag) == NULL);
 		ap->ops->eng_timeout(ap);
@@ -321,24 +328,23 @@ void ata_scsi_error(struct Scsi_Host *ho
 	scsi_eh_flush_done_q(&ap->eh_done_q);
 
 	/* clean up */
-	spin_lock_irqsave(ap_lock, flags);
+	spin_lock_irqsave(ap->lock, flags);
 
-	if (ap->flags & ATA_FLAG_LOADING) {
-		ap->flags &= ~ATA_FLAG_LOADING;
-	} else {
-		if (ap->flags & ATA_FLAG_SCSI_HOTPLUG)
-			queue_work(ata_aux_wq, &ap->hotplug_task);
-		if (ap->flags & ATA_FLAG_RECOVERED)
-			ata_port_printk(ap, KERN_INFO, "EH complete\n");
-	}
+	if (ap->pflags & ATA_PFLAG_LOADING)
+		ap->pflags &= ~ATA_PFLAG_LOADING;
+	else if (ap->pflags & ATA_PFLAG_SCSI_HOTPLUG)
+		queue_work(ata_aux_wq, &ap->hotplug_task);
+
+	if (ap->pflags & ATA_PFLAG_RECOVERED)
+		ata_port_printk(ap, KERN_INFO, "EH complete\n");
 
-	ap->flags &= ~(ATA_FLAG_SCSI_HOTPLUG | ATA_FLAG_RECOVERED);
+	ap->pflags &= ~(ATA_PFLAG_SCSI_HOTPLUG | ATA_PFLAG_RECOVERED);
 
 	/* tell wait_eh that we're done */
-	ap->flags &= ~ATA_FLAG_EH_IN_PROGRESS;
+	ap->pflags &= ~ATA_PFLAG_EH_IN_PROGRESS;
 	wake_up_all(&ap->eh_wait_q);
 
-	spin_unlock_irqrestore(ap_lock, flags);
+	spin_unlock_irqrestore(ap->lock, flags);
 
 	DPRINTK("EXIT\n");
 }
@@ -360,7 +366,7 @@ void ata_port_wait_eh(struct ata_port *a
  retry:
 	spin_lock_irqsave(ap->lock, flags);
 
-	while (ap->flags & (ATA_FLAG_EH_PENDING | ATA_FLAG_EH_IN_PROGRESS)) {
+	while (ap->pflags & (ATA_PFLAG_EH_PENDING | ATA_PFLAG_EH_IN_PROGRESS)) {
 		prepare_to_wait(&ap->eh_wait_q, &wait, TASK_UNINTERRUPTIBLE);
 		spin_unlock_irqrestore(ap->lock, flags);
 		schedule();
@@ -489,7 +495,7 @@ void ata_qc_schedule_eh(struct ata_queue
 	WARN_ON(!ap->ops->error_handler);
 
 	qc->flags |= ATA_QCFLAG_FAILED;
-	qc->ap->flags |= ATA_FLAG_EH_PENDING;
+	qc->ap->pflags |= ATA_PFLAG_EH_PENDING;
 
 	/* The following will fail if timeout has already expired.
 	 * ata_scsi_error() takes care of such scmds on EH entry.
@@ -513,7 +519,7 @@ void ata_port_schedule_eh(struct ata_por
 {
 	WARN_ON(!ap->ops->error_handler);
 
-	ap->flags |= ATA_FLAG_EH_PENDING;
+	ap->pflags |= ATA_PFLAG_EH_PENDING;
 	scsi_schedule_eh(ap->host);
 
 	DPRINTK("port EH scheduled\n");
@@ -578,7 +584,7 @@ static void __ata_port_freeze(struct ata
 	if (ap->ops->freeze)
 		ap->ops->freeze(ap);
 
-	ap->flags |= ATA_FLAG_FROZEN;
+	ap->pflags |= ATA_PFLAG_FROZEN;
 
 	DPRINTK("ata%u port frozen\n", ap->id);
 }
@@ -646,7 +652,7 @@ void ata_eh_thaw_port(struct ata_port *a
 
 	spin_lock_irqsave(ap->lock, flags);
 
-	ap->flags &= ~ATA_FLAG_FROZEN;
+	ap->pflags &= ~ATA_PFLAG_FROZEN;
 
 	if (ap->ops->thaw)
 		ap->ops->thaw(ap);
@@ -731,7 +737,7 @@ static void ata_eh_detach_dev(struct ata
 
 	if (ata_scsi_offline_dev(dev)) {
 		dev->flags |= ATA_DFLAG_DETACHED;
-		ap->flags |= ATA_FLAG_SCSI_HOTPLUG;
+		ap->pflags |= ATA_PFLAG_SCSI_HOTPLUG;
 	}
 
 	/* clear per-dev EH actions */
@@ -760,8 +766,12 @@ static void ata_eh_about_to_do(struct at
 	unsigned long flags;
 
 	spin_lock_irqsave(ap->lock, flags);
+
 	ata_eh_clear_action(dev, &ap->eh_info, action);
-	ap->flags |= ATA_FLAG_RECOVERED;
+
+	if (!(ap->eh_context.i.flags & ATA_EHI_QUIET))
+		ap->pflags |= ATA_PFLAG_RECOVERED;
+
 	spin_unlock_irqrestore(ap->lock, flags);
 }
 
@@ -1027,7 +1037,7 @@ static void ata_eh_analyze_ncq_error(str
 	int tag, rc;
 
 	/* if frozen, we can't do much */
-	if (ap->flags & ATA_FLAG_FROZEN)
+	if (ap->pflags & ATA_PFLAG_FROZEN)
 		return;
 
 	/* is it NCQ device error? */
@@ -1275,6 +1285,9 @@ static void ata_eh_autopsy(struct ata_po
 
 	DPRINTK("ENTER\n");
 
+	if (ehc->i.flags & ATA_EHI_NO_AUTOPSY)
+		return;
+
 	/* obtain and analyze SError */
 	rc = sata_scr_read(ap, SCR_ERROR, &serror);
 	if (rc == 0) {
@@ -1327,7 +1340,7 @@ static void ata_eh_autopsy(struct ata_po
 	}
 
 	/* enforce default EH actions */
-	if (ap->flags & ATA_FLAG_FROZEN ||
+	if (ap->pflags & ATA_PFLAG_FROZEN ||
 	    all_err_mask & (AC_ERR_HSM | AC_ERR_TIMEOUT))
 		action |= ATA_EH_SOFTRESET;
 	else if (all_err_mask)
@@ -1346,7 +1359,7 @@ static void ata_eh_autopsy(struct ata_po
 
 	/* record autopsy result */
 	ehc->i.dev = failed_dev;
-	ehc->i.action = action;
+	ehc->i.action |= action;
 
 	DPRINTK("EXIT\n");
 }
@@ -1385,7 +1398,7 @@ static void ata_eh_report(struct ata_por
 		return;
 
 	frozen = "";
-	if (ap->flags & ATA_FLAG_FROZEN)
+	if (ap->pflags & ATA_PFLAG_FROZEN)
 		frozen = " frozen";
 
 	if (ehc->i.dev) {
@@ -1465,7 +1478,7 @@ static int ata_eh_reset(struct ata_port 
 	struct ata_eh_context *ehc = &ap->eh_context;
 	unsigned int *classes = ehc->classes;
 	int tries = ATA_EH_RESET_TRIES;
-	int verbose = !(ap->flags & ATA_FLAG_LOADING);
+	int verbose = !(ehc->i.flags & ATA_EHI_QUIET);
 	unsigned int action;
 	ata_reset_fn_t reset;
 	int i, did_followup_srst, rc;
@@ -1605,7 +1618,7 @@ static int ata_eh_revalidate_and_attach(
 		dev = &ap->device[i];
 		action = ata_eh_dev_action(dev);
 
-		if (action & ATA_EH_REVALIDATE && ata_dev_enabled(dev)) {
+		if (action & ATA_EH_REVALIDATE && ata_dev_ready(dev)) {
 			if (ata_port_offline(ap)) {
 				rc = -EIO;
 				break;
@@ -1636,7 +1649,7 @@ static int ata_eh_revalidate_and_attach(
 			}
 
 			spin_lock_irqsave(ap->lock, flags);
-			ap->flags |= ATA_FLAG_SCSI_HOTPLUG;
+			ap->pflags |= ATA_PFLAG_SCSI_HOTPLUG;
 			spin_unlock_irqrestore(ap->lock, flags);
 		}
 	}
@@ -1648,6 +1661,164 @@ static int ata_eh_revalidate_and_attach(
 	return rc;
 }
 
+/**
+ *	ata_eh_suspend - handle suspend EH action
+ *	@ap: target host port
+ *	@r_failed_dev: result parameter to indicate failing device
+ *
+ *	Handle suspend EH action.  Disk devices are spinned down and
+ *	other types of devices are just marked suspended.  Once
+ *	suspended, no EH action to the device is allowed until it is
+ *	resumed.
+ *
+ *	LOCKING:
+ *	Kernel thread context (may sleep).
+ *
+ *	RETURNS:
+ *	0 on success, -errno otherwise
+ */
+static int ata_eh_suspend(struct ata_port *ap, struct ata_device **r_failed_dev)
+{
+	struct ata_device *dev;
+	int i, rc = 0;
+
+	DPRINTK("ENTER\n");
+
+	for (i = 0; i < ATA_MAX_DEVICES; i++) {
+		unsigned long flags;
+		unsigned int action, err_mask;
+
+		dev = &ap->device[i];
+		action = ata_eh_dev_action(dev);
+
+		if (!ata_dev_enabled(dev) || !(action & ATA_EH_SUSPEND))
+			continue;
+
+		WARN_ON(dev->flags & ATA_DFLAG_SUSPENDED);
+
+		ata_eh_about_to_do(ap, dev, ATA_EH_SUSPEND);
+
+		if (dev->class == ATA_DEV_ATA && !(action & ATA_EH_PM_FREEZE)) {
+			/* flush cache */
+			rc = ata_flush_cache(dev);
+			if (rc)
+				break;
+
+			/* spin down */
+			err_mask = ata_do_simple_cmd(dev, ATA_CMD_STANDBYNOW1);
+			if (err_mask) {
+				ata_dev_printk(dev, KERN_ERR, "failed to "
+					       "spin down (err_mask=0x%x)\n",
+					       err_mask);
+				rc = -EIO;
+				break;
+			}
+		}
+
+		spin_lock_irqsave(ap->lock, flags);
+		dev->flags |= ATA_DFLAG_SUSPENDED;
+		spin_unlock_irqrestore(ap->lock, flags);
+
+		ata_eh_done(ap, dev, ATA_EH_SUSPEND);
+	}
+
+	if (rc)
+		*r_failed_dev = dev;
+
+	DPRINTK("EXIT\n");
+	return 0;
+}
+
+/**
+ *	ata_eh_prep_resume - prep for resume EH action
+ *	@ap: target host port
+ *
+ *	Clear SUSPENDED in preparation for scheduled resume actions.
+ *	This allows other parts of EH to access the devices being
+ *	resumed.
+ *
+ *	LOCKING:
+ *	Kernel thread context (may sleep).
+ */
+static void ata_eh_prep_resume(struct ata_port *ap)
+{
+	struct ata_device *dev;
+	unsigned long flags;
+	int i;
+
+	DPRINTK("ENTER\n");
+
+	for (i = 0; i < ATA_MAX_DEVICES; i++) {
+		unsigned int action;
+
+		dev = &ap->device[i];
+		action = ata_eh_dev_action(dev);
+
+		if (!ata_dev_enabled(dev) || !(action & ATA_EH_RESUME))
+			continue;
+
+		spin_lock_irqsave(ap->lock, flags);
+		dev->flags &= ~ATA_DFLAG_SUSPENDED;
+		spin_unlock_irqrestore(ap->lock, flags);
+	}
+
+	DPRINTK("EXIT\n");
+}
+
+/**
+ *	ata_eh_resume - handle resume EH action
+ *	@ap: target host port
+ *	@r_failed_dev: result parameter to indicate failing device
+ *
+ *	Handle resume EH action.  Target devices are already reset and
+ *	revalidated.  Spinning up is the only operation left.
+ *
+ *	LOCKING:
+ *	Kernel thread context (may sleep).
+ *
+ *	RETURNS:
+ *	0 on success, -errno otherwise
+ */
+static int ata_eh_resume(struct ata_port *ap, struct ata_device **r_failed_dev)
+{
+	struct ata_device *dev;
+	int i, rc = 0;
+
+	DPRINTK("ENTER\n");
+
+	for (i = 0; i < ATA_MAX_DEVICES; i++) {
+		unsigned int action, err_mask;
+
+		dev = &ap->device[i];
+		action = ata_eh_dev_action(dev);
+
+		if (!ata_dev_enabled(dev) || !(action & ATA_EH_RESUME))
+			continue;
+
+		ata_eh_about_to_do(ap, dev, ATA_EH_RESUME);
+
+		if (dev->class == ATA_DEV_ATA && !(action & ATA_EH_PM_FREEZE)) {
+			err_mask = ata_do_simple_cmd(dev,
+						     ATA_CMD_IDLEIMMEDIATE);
+			if (err_mask) {
+				ata_dev_printk(dev, KERN_ERR, "failed to "
+					       "spin up (err_mask=0x%x)\n",
+					       err_mask);
+				rc = -EIO;
+				break;
+			}
+		}
+
+		ata_eh_done(ap, dev, ATA_EH_RESUME);
+	}
+
+	if (rc)
+		*r_failed_dev = dev;
+
+	DPRINTK("EXIT\n");
+	return 0;
+}
+
 static int ata_port_nr_enabled(struct ata_port *ap)
 {
 	int i, cnt = 0;
@@ -1673,7 +1844,19 @@ static int ata_eh_skip_recovery(struct a
 	struct ata_eh_context *ehc = &ap->eh_context;
 	int i;
 
-	if (ap->flags & ATA_FLAG_FROZEN || ata_port_nr_enabled(ap))
+	/* skip if all possible devices are suspended */
+	for (i = 0; i < ata_port_max_devices(ap); i++) {
+		struct ata_device *dev = &ap->device[i];
+
+		if (ata_dev_absent(dev) || ata_dev_ready(dev))
+			break;
+	}
+
+	if (i == ata_port_max_devices(ap))
+		return 1;
+
+	/* always thaw frozen port and recover failed devices */
+	if (ap->pflags & ATA_PFLAG_FROZEN || ata_port_nr_enabled(ap))
 		return 0;
 
 	/* skip if class codes for all vacant slots are ATA_DEV_NONE */
@@ -1744,9 +1927,12 @@ static int ata_eh_recover(struct ata_por
 	rc = 0;
 
 	/* if UNLOADING, finish immediately */
-	if (ap->flags & ATA_FLAG_UNLOADING)
+	if (ap->pflags & ATA_PFLAG_UNLOADING)
 		goto out;
 
+	/* prep for resume */
+	ata_eh_prep_resume(ap);
+
 	/* skip EH if possible. */
 	if (ata_eh_skip_recovery(ap))
 		ehc->i.action = 0;
@@ -1774,6 +1960,11 @@ static int ata_eh_recover(struct ata_por
 	if (rc)
 		goto dev_fail;
 
+	/* resume devices */
+	rc = ata_eh_resume(ap, &dev);
+	if (rc)
+		goto dev_fail;
+
 	/* configure transfer mode if the port has been reset */
 	if (ehc->i.flags & ATA_EHI_DID_RESET) {
 		rc = ata_set_mode(ap, &dev);
@@ -1783,6 +1974,11 @@ static int ata_eh_recover(struct ata_por
 		}
 	}
 
+	/* suspend devices */
+	rc = ata_eh_suspend(ap, &dev);
+	if (rc)
+		goto dev_fail;
+
 	goto out;
 
  dev_fail:
@@ -1908,11 +2104,124 @@ void ata_do_eh(struct ata_port *ap, ata_
 	       ata_reset_fn_t softreset, ata_reset_fn_t hardreset,
 	       ata_postreset_fn_t postreset)
 {
-	if (!(ap->flags & ATA_FLAG_LOADING)) {
-		ata_eh_autopsy(ap);
-		ata_eh_report(ap);
-	}
-
+	ata_eh_autopsy(ap);
+	ata_eh_report(ap);
 	ata_eh_recover(ap, prereset, softreset, hardreset, postreset);
 	ata_eh_finish(ap);
 }
+
+/**
+ *	ata_eh_handle_port_suspend - perform port suspend operation
+ *	@ap: port to suspend
+ *
+ *	Suspend @ap.
+ *
+ *	LOCKING:
+ *	Kernel thread context (may sleep).
+ */
+static void ata_eh_handle_port_suspend(struct ata_port *ap)
+{
+	unsigned long flags;
+	int rc = 0;
+
+	/* are we suspending? */
+	spin_lock_irqsave(ap->lock, flags);
+	if (!(ap->pflags & ATA_PFLAG_PM_PENDING) ||
+	    ap->pm_mesg.event == PM_EVENT_ON) {
+		spin_unlock_irqrestore(ap->lock, flags);
+		return;
+	}
+	spin_unlock_irqrestore(ap->lock, flags);
+
+	WARN_ON(ap->pflags & ATA_PFLAG_SUSPENDED);
+
+	/* suspend */
+	ata_eh_freeze_port(ap);
+
+	if (ap->ops->port_suspend)
+		rc = ap->ops->port_suspend(ap, ap->pm_mesg);
+
+	/* report result */
+	spin_lock_irqsave(ap->lock, flags);
+
+	ap->pflags &= ~ATA_PFLAG_PM_PENDING;
+	if (rc == 0)
+		ap->pflags |= ATA_PFLAG_SUSPENDED;
+	else
+		ata_port_schedule_eh(ap);
+
+	if (ap->pm_result) {
+		*ap->pm_result = rc;
+		ap->pm_result = NULL;
+	}
+
+	spin_unlock_irqrestore(ap->lock, flags);
+
+	return;
+}
+
+/**
+ *	ata_eh_handle_port_resume - perform port resume operation
+ *	@ap: port to resume
+ *
+ *	Resume @ap.
+ *
+ *	This function also waits upto one second until all devices
+ *	hanging off this port requests resume EH action.  This is to
+ *	prevent invoking EH and thus reset multiple times on resume.
+ *
+ *	On DPM resume, where some of devices might not be resumed
+ *	together, this may delay port resume upto one second, but such
+ *	DPM resumes are rare and 1 sec delay isn't too bad.
+ *
+ *	LOCKING:
+ *	Kernel thread context (may sleep).
+ */
+static void ata_eh_handle_port_resume(struct ata_port *ap)
+{
+	unsigned long timeout;
+	unsigned long flags;
+	int i, rc = 0;
+
+	/* are we resuming? */
+	spin_lock_irqsave(ap->lock, flags);
+	if (!(ap->pflags & ATA_PFLAG_PM_PENDING) ||
+	    ap->pm_mesg.event != PM_EVENT_ON) {
+		spin_unlock_irqrestore(ap->lock, flags);
+		return;
+	}
+	spin_unlock_irqrestore(ap->lock, flags);
+
+	/* spurious? */
+	if (!(ap->pflags & ATA_PFLAG_SUSPENDED))
+		goto done;
+
+	if (ap->ops->port_resume)
+		rc = ap->ops->port_resume(ap);
+
+	/* give devices time to request EH */
+	timeout = jiffies + HZ; /* 1s max */
+	while (1) {
+		for (i = 0; i < ATA_MAX_DEVICES; i++) {
+			struct ata_device *dev = &ap->device[i];
+			unsigned int action = ata_eh_dev_action(dev);
+
+			if ((dev->flags & ATA_DFLAG_SUSPENDED) &&
+			    !(action & ATA_EH_RESUME))
+				break;
+		}
+
+		if (i == ATA_MAX_DEVICES || time_after(jiffies, timeout))
+			break;
+		msleep(10);
+	}
+
+ done:
+	spin_lock_irqsave(ap->lock, flags);
+	ap->pflags &= ~(ATA_PFLAG_PM_PENDING | ATA_PFLAG_SUSPENDED);
+	if (ap->pm_result) {
+		*ap->pm_result = rc;
+		ap->pm_result = NULL;
+	}
+	spin_unlock_irqrestore(ap->lock, flags);
+}
diff --git a/drivers/scsi/libata-scsi.c b/drivers/scsi/libata-scsi.c
index 2915bca..7ced41e 100644
--- a/drivers/scsi/libata-scsi.c
+++ b/drivers/scsi/libata-scsi.c
@@ -397,20 +397,129 @@ void ata_dump_status(unsigned id, struct
 	}
 }
 
-int ata_scsi_device_resume(struct scsi_device *sdev)
+/**
+ *	ata_scsi_device_suspend - suspend ATA device associated with sdev
+ *	@sdev: the SCSI device to suspend
+ *	@state: target power management state
+ *
+ *	Request suspend EH action on the ATA device associated with
+ *	@sdev and wait for the operation to complete.
+ *
+ *	LOCKING:
+ *	Kernel thread context (may sleep).
+ *
+ *	RETURNS:
+ *	0 on success, -errno otherwise.
+ */
+int ata_scsi_device_suspend(struct scsi_device *sdev, pm_message_t state)
 {
 	struct ata_port *ap = ata_shost_to_port(sdev->host);
-	struct ata_device *dev = __ata_scsi_find_dev(ap, sdev);
+	struct ata_device *dev = ata_scsi_find_dev(ap, sdev);
+	unsigned long flags;
+	unsigned int action;
+	int rc = 0;
+
+	if (!dev)
+		goto out;
+
+	spin_lock_irqsave(ap->lock, flags);
+
+	/* wait for the previous resume to complete */
+	while (dev->flags & ATA_DFLAG_SUSPENDED) {
+		spin_unlock_irqrestore(ap->lock, flags);
+		ata_port_wait_eh(ap);
+		spin_lock_irqsave(ap->lock, flags);
+	}
+
+	/* if @sdev is already detached, nothing to do */
+	if (sdev->sdev_state == SDEV_OFFLINE ||
+	    sdev->sdev_state == SDEV_CANCEL || sdev->sdev_state == SDEV_DEL)
+		goto out_unlock;
+
+	/* request suspend */
+	action = ATA_EH_SUSPEND;
+	if (state.event != PM_EVENT_SUSPEND)
+		action |= ATA_EH_PM_FREEZE;
+	ap->eh_info.dev_action[dev->devno] |= action;
+	ap->eh_info.flags |= ATA_EHI_QUIET;
+	ata_port_schedule_eh(ap);
+
+	spin_unlock_irqrestore(ap->lock, flags);
+
+	/* wait for EH to do the job */
+	ata_port_wait_eh(ap);
+
+	spin_lock_irqsave(ap->lock, flags);
+
+	/* If @sdev is still attached but the associated ATA device
+	 * isn't suspended, the operation failed.
+	 */
+	if (sdev->sdev_state != SDEV_OFFLINE &&
+	    sdev->sdev_state != SDEV_CANCEL && sdev->sdev_state != SDEV_DEL &&
+	    !(dev->flags & ATA_DFLAG_SUSPENDED))
+		rc = -EIO;
 
-	return ata_device_resume(dev);
+ out_unlock:
+	spin_unlock_irqrestore(ap->lock, flags);
+ out:
+	if (rc == 0)
+		sdev->sdev_gendev.power.power_state = state;
+	return rc;
 }
 
-int ata_scsi_device_suspend(struct scsi_device *sdev, pm_message_t state)
+/**
+ *	ata_scsi_device_resume - resume ATA device associated with sdev
+ *	@sdev: the SCSI device to resume
+ *
+ *	Request resume EH action on the ATA device associated with
+ *	@sdev and return immediately.  This enables parallel
+ *	wakeup/spinup of devices.
+ *
+ *	LOCKING:
+ *	Kernel thread context (may sleep).
+ *
+ *	RETURNS:
+ *	0.
+ */
+int ata_scsi_device_resume(struct scsi_device *sdev)
 {
 	struct ata_port *ap = ata_shost_to_port(sdev->host);
-	struct ata_device *dev = __ata_scsi_find_dev(ap, sdev);
+	struct ata_device *dev = ata_scsi_find_dev(ap, sdev);
+	struct ata_eh_info *ehi = &ap->eh_info;
+	unsigned long flags;
+	unsigned int action;
+
+	if (!dev)
+		goto out;
+
+	spin_lock_irqsave(ap->lock, flags);
+
+	/* if @sdev is already detached, nothing to do */
+	if (sdev->sdev_state == SDEV_OFFLINE ||
+	    sdev->sdev_state == SDEV_CANCEL || sdev->sdev_state == SDEV_DEL)
+		goto out_unlock;
 
-	return ata_device_suspend(dev, state);
+	/* request resume */
+	action = ATA_EH_RESUME;
+	if (sdev->sdev_gendev.power.power_state.event == PM_EVENT_SUSPEND)
+		__ata_ehi_hotplugged(ehi);
+	else
+		action |= ATA_EH_PM_FREEZE | ATA_EH_SOFTRESET;
+	ehi->dev_action[dev->devno] |= action;
+
+	/* We don't want autopsy and verbose EH messages.  Disable
+	 * those if we're the only device on this link.
+	 */
+	if (ata_port_max_devices(ap) == 1)
+		ehi->flags |= ATA_EHI_NO_AUTOPSY | ATA_EHI_QUIET;
+
+	ata_port_schedule_eh(ap);
+
+ out_unlock:
+	spin_unlock_irqrestore(ap->lock, flags);
+ out:
+	sdev->sdev_gendev.power.power_state = PMSG_ON;
+	return 0;
 }
 
 /**
@@ -2930,7 +3039,7 @@ void ata_scsi_hotplug(void *data)
 	struct ata_port *ap = data;
 	int i;
 
-	if (ap->flags & ATA_FLAG_UNLOADING) {
+	if (ap->pflags & ATA_PFLAG_UNLOADING) {
 		DPRINTK("ENTER/EXIT - unloading\n");
 		return;
 	}
@@ -3011,6 +3120,7 @@ static int ata_scsi_user_scan(struct Scs
 		if (dev) {
 			ap->eh_info.probe_mask |= 1 << dev->devno;
 			ap->eh_info.action |= ATA_EH_SOFTRESET;
+			ap->eh_info.flags |= ATA_EHI_RESUME_LINK;
 		} else
 			rc = -EINVAL;
 	}
diff --git a/drivers/scsi/sata_sil.c b/drivers/scsi/sata_sil.c
index 7aabb45..d0a8507 100644
--- a/drivers/scsi/sata_sil.c
+++ b/drivers/scsi/sata_sil.c
@@ -109,6 +109,7 @@ enum {
 };
 
 static int sil_init_one (struct pci_dev *pdev, const struct pci_device_id *ent);
+static int sil_pci_device_resume(struct pci_dev *pdev);
 static void sil_dev_config(struct ata_port *ap, struct ata_device *dev);
 static u32 sil_scr_read (struct ata_port *ap, unsigned int sc_reg);
 static void sil_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val);
@@ -160,6 +161,8 @@ static struct pci_driver sil_pci_driver 
 	.id_table		= sil_pci_tbl,
 	.probe			= sil_init_one,
 	.remove			= ata_pci_remove_one,
+	.suspend		= ata_pci_device_suspend,
+	.resume			= sil_pci_device_resume,
 };
 
 static struct scsi_host_template sil_sht = {
@@ -178,6 +181,8 @@ static struct scsi_host_template sil_sht
 	.slave_configure	= ata_scsi_slave_config,
 	.slave_destroy		= ata_scsi_slave_destroy,
 	.bios_param		= ata_std_bios_param,
+	.suspend		= ata_scsi_device_suspend,
+	.resume			= ata_scsi_device_resume,
 };
 
 static const struct ata_port_operations sil_ops = {
@@ -370,7 +375,7 @@ static void sil_host_intr(struct ata_por
 		 * during hardreset makes controllers with broken SIEN
 		 * repeat probing needlessly.
 		 */
-		if (!(ap->flags & ATA_FLAG_FROZEN)) {
+		if (!(ap->pflags & ATA_PFLAG_FROZEN)) {
 			ata_ehi_hotplugged(&ap->eh_info);
 			ap->eh_info.serror |= serror;
 		}
@@ -561,6 +566,52 @@ static void sil_dev_config(struct ata_po
 	}
 }
 
+static void sil_init_controller(struct pci_dev *pdev,
+				int n_ports, unsigned long host_flags,
+				void __iomem *mmio_base)
+{
+	u8 cls;
+	u32 tmp;
+	int i;
+
+	/* Initialize FIFO PCI bus arbitration */
+	cls = sil_get_device_cache_line(pdev);
+	if (cls) {
+		cls >>= 3;
+		cls++;  /* cls = (line_size/8)+1 */
+		for (i = 0; i < n_ports; i++)
+			writew(cls << 8 | cls,
+			       mmio_base + sil_port[i].fifo_cfg);
+	} else
+		dev_printk(KERN_WARNING, &pdev->dev,
+			   "cache line size not set.  Driver may not function\n");
+
+	/* Apply R_ERR on DMA activate FIS errata workaround */
+	if (host_flags & SIL_FLAG_RERR_ON_DMA_ACT) {
+		int cnt;
+
+		for (i = 0, cnt = 0; i < n_ports; i++) {
+			tmp = readl(mmio_base + sil_port[i].sfis_cfg);
+			if ((tmp & 0x3) != 0x01)
+				continue;
+			if (!cnt)
+				dev_printk(KERN_INFO, &pdev->dev,
+					   "Applying R_ERR on DMA activate "
+					   "FIS errata fix\n");
+			writel(tmp & ~0x3, mmio_base + sil_port[i].sfis_cfg);
+			cnt++;
+		}
+	}
+
+	if (n_ports == 4) {
+		/* flip the magic "make 4 ports work" bit */
+		tmp = readl(mmio_base + sil_port[2].bmdma);
+		if ((tmp & SIL_INTR_STEERING) == 0)
+			writel(tmp | SIL_INTR_STEERING,
+			       mmio_base + sil_port[2].bmdma);
+	}
+}
+
 static int sil_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
 {
 	static int printed_version;
@@ -570,8 +621,6 @@ static int sil_init_one (struct pci_dev 
 	int rc;
 	unsigned int i;
 	int pci_dev_busy = 0;
-	u32 tmp;
-	u8 cls;
 
 	if (!printed_version++)
 		dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n");
@@ -630,42 +679,8 @@ static int sil_init_one (struct pci_dev 
 		ata_std_ports(&probe_ent->port[i]);
 	}
 
-	/* Initialize FIFO PCI bus arbitration */
-	cls = sil_get_device_cache_line(pdev);
-	if (cls) {
-		cls >>= 3;
-		cls++;  /* cls = (line_size/8)+1 */
-		for (i = 0; i < probe_ent->n_ports; i++)
-			writew(cls << 8 | cls,
-			       mmio_base + sil_port[i].fifo_cfg);
-	} else
-		dev_printk(KERN_WARNING, &pdev->dev,
-			   "cache line size not set.  Driver may not function\n");
-
-	/* Apply R_ERR on DMA activate FIS errata workaround */
-	if (probe_ent->host_flags & SIL_FLAG_RERR_ON_DMA_ACT) {
-		int cnt;
-
-		for (i = 0, cnt = 0; i < probe_ent->n_ports; i++) {
-			tmp = readl(mmio_base + sil_port[i].sfis_cfg);
-			if ((tmp & 0x3) != 0x01)
-				continue;
-			if (!cnt)
-				dev_printk(KERN_INFO, &pdev->dev,
-					   "Applying R_ERR on DMA activate "
-					   "FIS errata fix\n");
-			writel(tmp & ~0x3, mmio_base + sil_port[i].sfis_cfg);
-			cnt++;
-		}
-	}
-
-	if (ent->driver_data == sil_3114) {
-		/* flip the magic "make 4 ports work" bit */
-		tmp = readl(mmio_base + sil_port[2].bmdma);
-		if ((tmp & SIL_INTR_STEERING) == 0)
-			writel(tmp | SIL_INTR_STEERING,
-			       mmio_base + sil_port[2].bmdma);
-	}
+	sil_init_controller(pdev, probe_ent->n_ports, probe_ent->host_flags,
+			    mmio_base);
 
 	pci_set_master(pdev);
 
@@ -685,6 +700,18 @@ err_out:
 	return rc;
 }
 
+static int sil_pci_device_resume(struct pci_dev *pdev)
+{
+	struct ata_host_set *host_set = dev_get_drvdata(&pdev->dev);
+
+	ata_pci_device_do_resume(pdev);
+	sil_init_controller(pdev, host_set->n_ports, host_set->ports[0]->flags,
+			    host_set->mmio_base);
+	ata_host_set_resume(host_set);
+
+	return 0;
+}
+
 static int __init sil_init(void)
 {
 	return pci_module_init(&sil_pci_driver);
diff --git a/drivers/scsi/sata_sil24.c b/drivers/scsi/sata_sil24.c
index 07a1c6a..2e0f4a4 100644
--- a/drivers/scsi/sata_sil24.c
+++ b/drivers/scsi/sata_sil24.c
@@ -92,6 +92,7 @@ enum {
 	HOST_CTRL_STOP		= (1 << 18), /* latched PCI STOP */
 	HOST_CTRL_DEVSEL	= (1 << 19), /* latched PCI DEVSEL */
 	HOST_CTRL_REQ64		= (1 << 20), /* latched PCI REQ64 */
+	HOST_CTRL_GLOBAL_RST	= (1 << 31), /* global reset */
 
 	/*
 	 * Port registers
@@ -338,6 +339,7 @@ static int sil24_port_start(struct ata_p
 static void sil24_port_stop(struct ata_port *ap);
 static void sil24_host_stop(struct ata_host_set *host_set);
 static int sil24_init_one(struct pci_dev *pdev, const struct pci_device_id *ent);
+static int sil24_pci_device_resume(struct pci_dev *pdev);
 
 static const struct pci_device_id sil24_pci_tbl[] = {
 	{ 0x1095, 0x3124, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BID_SIL3124 },
@@ -353,6 +355,8 @@ static struct pci_driver sil24_pci_drive
 	.id_table		= sil24_pci_tbl,
 	.probe			= sil24_init_one,
 	.remove			= ata_pci_remove_one, /* safe? */
+	.suspend		= ata_pci_device_suspend,
+	.resume			= sil24_pci_device_resume,
 };
 
 static struct scsi_host_template sil24_sht = {
@@ -372,6 +376,8 @@ static struct scsi_host_template sil24_s
 	.slave_configure	= ata_scsi_slave_config,
 	.slave_destroy		= ata_scsi_slave_destroy,
 	.bios_param		= ata_std_bios_param,
+	.suspend		= ata_scsi_device_suspend,
+	.resume			= ata_scsi_device_resume,
 };
 
 static const struct ata_port_operations sil24_ops = {
@@ -607,7 +613,7 @@ static int sil24_hardreset(struct ata_po
 	/* SStatus oscillates between zero and valid status after
 	 * DEV_RST, debounce it.
 	 */
-	rc = sata_phy_debounce(ap, sata_deb_timing_before_fsrst);
+	rc = sata_phy_debounce(ap, sata_deb_timing_long);
 	if (rc) {
 		reason = "PHY debouncing failed";
 		goto err;
@@ -988,6 +994,64 @@ static void sil24_host_stop(struct ata_h
 	kfree(hpriv);
 }
 
+static void sil24_init_controller(struct pci_dev *pdev, int n_ports,
+				  unsigned long host_flags,
+				  void __iomem *host_base,
+				  void __iomem *port_base)
+{
+	u32 tmp;
+	int i;
+
+	/* GPIO off */
+	writel(0, host_base + HOST_FLASH_CMD);
+
+	/* clear global reset & mask interrupts during initialization */
+	writel(0, host_base + HOST_CTRL);
+
+	/* init ports */
+	for (i = 0; i < n_ports; i++) {
+		void __iomem *port = port_base + i * PORT_REGS_SIZE;
+
+		/* Initial PHY setting */
+		writel(0x20c, port + PORT_PHY_CFG);
+
+		/* Clear port RST */
+		tmp = readl(port + PORT_CTRL_STAT);
+		if (tmp & PORT_CS_PORT_RST) {
+			writel(PORT_CS_PORT_RST, port + PORT_CTRL_CLR);
+			tmp = ata_wait_register(port + PORT_CTRL_STAT,
+						PORT_CS_PORT_RST,
+						PORT_CS_PORT_RST, 10, 100);
+			if (tmp & PORT_CS_PORT_RST)
+				dev_printk(KERN_ERR, &pdev->dev,
+				           "failed to clear port RST\n");
+		}
+
+		/* Configure IRQ WoC */
+		if (host_flags & SIL24_FLAG_PCIX_IRQ_WOC)
+			writel(PORT_CS_IRQ_WOC, port + PORT_CTRL_STAT);
+		else
+			writel(PORT_CS_IRQ_WOC, port + PORT_CTRL_CLR);
+
+		/* Zero error counters. */
+		writel(0x8000, port + PORT_DECODE_ERR_THRESH);
+		writel(0x8000, port + PORT_CRC_ERR_THRESH);
+		writel(0x8000, port + PORT_HSHK_ERR_THRESH);
+		writel(0x0000, port + PORT_DECODE_ERR_CNT);
+		writel(0x0000, port + PORT_CRC_ERR_CNT);
+		writel(0x0000, port + PORT_HSHK_ERR_CNT);
+
+		/* Always use 64bit activation */
+		writel(PORT_CS_32BIT_ACTV, port + PORT_CTRL_CLR);
+
+		/* Clear port multiplier enable and resume bits */
+		writel(PORT_CS_PM_EN | PORT_CS_RESUME, port + PORT_CTRL_CLR);
+	}
+
+	/* Turn on interrupts */
+	writel(IRQ_STAT_4PORTS, host_base + HOST_CTRL);
+}
+
 static int sil24_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
 	static int printed_version = 0;
@@ -1076,9 +1140,6 @@ static int sil24_init_one(struct pci_dev
 		}
 	}
 
-	/* GPIO off */
-	writel(0, host_base + HOST_FLASH_CMD);
-
 	/* Apply workaround for completion IRQ loss on PCI-X errata */
 	if (probe_ent->host_flags & SIL24_FLAG_PCIX_IRQ_WOC) {
 		tmp = readl(host_base + HOST_CTRL);
@@ -1090,56 +1151,18 @@ static int sil24_init_one(struct pci_dev
 			probe_ent->host_flags &= ~SIL24_FLAG_PCIX_IRQ_WOC;
 	}
 
-	/* clear global reset & mask interrupts during initialization */
-	writel(0, host_base + HOST_CTRL);
-
 	for (i = 0; i < probe_ent->n_ports; i++) {
-		void __iomem *port = port_base + i * PORT_REGS_SIZE;
-		unsigned long portu = (unsigned long)port;
+		unsigned long portu =
+			(unsigned long)port_base + i * PORT_REGS_SIZE;
 
 		probe_ent->port[i].cmd_addr = portu;
 		probe_ent->port[i].scr_addr = portu + PORT_SCONTROL;
 
 		ata_std_ports(&probe_ent->port[i]);
-
-		/* Initial PHY setting */
-		writel(0x20c, port + PORT_PHY_CFG);
-
-		/* Clear port RST */
-		tmp = readl(port + PORT_CTRL_STAT);
-		if (tmp & PORT_CS_PORT_RST) {
-			writel(PORT_CS_PORT_RST, port + PORT_CTRL_CLR);
-			tmp = ata_wait_register(port + PORT_CTRL_STAT,
-						PORT_CS_PORT_RST,
-						PORT_CS_PORT_RST, 10, 100);
-			if (tmp & PORT_CS_PORT_RST)
-				dev_printk(KERN_ERR, &pdev->dev,
-				           "failed to clear port RST\n");
-		}
-
-		/* Configure IRQ WoC */
-		if (probe_ent->host_flags & SIL24_FLAG_PCIX_IRQ_WOC)
-			writel(PORT_CS_IRQ_WOC, port + PORT_CTRL_STAT);
-		else
-			writel(PORT_CS_IRQ_WOC, port + PORT_CTRL_CLR);
-
-		/* Zero error counters. */
-		writel(0x8000, port + PORT_DECODE_ERR_THRESH);
-		writel(0x8000, port + PORT_CRC_ERR_THRESH);
-		writel(0x8000, port + PORT_HSHK_ERR_THRESH);
-		writel(0x0000, port + PORT_DECODE_ERR_CNT);
-		writel(0x0000, port + PORT_CRC_ERR_CNT);
-		writel(0x0000, port + PORT_HSHK_ERR_CNT);
-
-		/* Always use 64bit activation */
-		writel(PORT_CS_32BIT_ACTV, port + PORT_CTRL_CLR);
-
-		/* Clear port multiplier enable and resume bits */
-		writel(PORT_CS_PM_EN | PORT_CS_RESUME, port + PORT_CTRL_CLR);
 	}
 
-	/* Turn on interrupts */
-	writel(IRQ_STAT_4PORTS, host_base + HOST_CTRL);
+	sil24_init_controller(pdev, probe_ent->n_ports, probe_ent->host_flags,
+			      host_base, port_base);
 
 	pci_set_master(pdev);
 
@@ -1162,6 +1185,25 @@ static int sil24_init_one(struct pci_dev
 	return rc;
 }
 
+static int sil24_pci_device_resume(struct pci_dev *pdev)
+{
+	struct ata_host_set *host_set = dev_get_drvdata(&pdev->dev);
+	struct sil24_host_priv *hpriv = host_set->private_data;
+
+	ata_pci_device_do_resume(pdev);
+
+	if (pdev->dev.power.power_state.event == PM_EVENT_SUSPEND)
+		writel(HOST_CTRL_GLOBAL_RST, hpriv->host_base + HOST_CTRL);
+
+	sil24_init_controller(pdev, host_set->n_ports,
+			      host_set->ports[0]->flags,
+			      hpriv->host_base, hpriv->port_base);
+
+	ata_host_set_resume(host_set);
+
+	return 0;
+}
+
 static int __init sil24_init(void)
 {
 	return pci_module_init(&sil24_pci_driver);
diff --git a/drivers/scsi/sata_vsc.c b/drivers/scsi/sata_vsc.c
index 916fe6f..ad37871 100644
--- a/drivers/scsi/sata_vsc.c
+++ b/drivers/scsi/sata_vsc.c
@@ -297,7 +297,7 @@ static const struct ata_port_operations 
 	.bmdma_status		= ata_bmdma_status,
 	.qc_prep		= ata_qc_prep,
 	.qc_issue		= ata_qc_issue_prot,
-	.data_xfer		= ata_pio_data_xfer,
+	.data_xfer		= ata_mmio_data_xfer,
 	.freeze			= ata_bmdma_freeze,
 	.thaw			= ata_bmdma_thaw,
 	.error_handler		= ata_bmdma_error_handler,
diff --git a/include/linux/libata.h b/include/linux/libata.h
index f4284bf..6cc497a 100644
--- a/include/linux/libata.h
+++ b/include/linux/libata.h
@@ -131,6 +131,7 @@ enum {
 	ATA_DFLAG_CFG_MASK	= (1 << 8) - 1,
 
 	ATA_DFLAG_PIO		= (1 << 8), /* device currently in PIO mode */
+	ATA_DFLAG_SUSPENDED	= (1 << 9), /* device suspended */
 	ATA_DFLAG_INIT_MASK	= (1 << 16) - 1,
 
 	ATA_DFLAG_DETACH	= (1 << 16),
@@ -160,22 +161,28 @@ enum {
 	ATA_FLAG_HRST_TO_RESUME	= (1 << 11), /* hardreset to resume phy */
 	ATA_FLAG_SKIP_D2H_BSY	= (1 << 12), /* can't wait for the first D2H
 					      * Register FIS clearing BSY */
-
 	ATA_FLAG_DEBUGMSG	= (1 << 13),
-	ATA_FLAG_FLUSH_PORT_TASK = (1 << 14), /* flush port task */
 
-	ATA_FLAG_EH_PENDING	= (1 << 15), /* EH pending */
-	ATA_FLAG_EH_IN_PROGRESS	= (1 << 16), /* EH in progress */
-	ATA_FLAG_FROZEN		= (1 << 17), /* port is frozen */
-	ATA_FLAG_RECOVERED	= (1 << 18), /* recovery action performed */
-	ATA_FLAG_LOADING	= (1 << 19), /* boot/loading probe */
-	ATA_FLAG_UNLOADING	= (1 << 20), /* module is unloading */
-	ATA_FLAG_SCSI_HOTPLUG	= (1 << 21), /* SCSI hotplug scheduled */
+	/* The following flag belongs to ap->pflags but is kept in
+	 * ap->flags because it's referenced in many LLDs and will be
+	 * removed in not-too-distant future.
+	 */
+	ATA_FLAG_DISABLED	= (1 << 23), /* port is disabled, ignore it */
+
+	/* bits 24:31 of ap->flags are reserved for LLD specific flags */
 
-	ATA_FLAG_DISABLED	= (1 << 22), /* port is disabled, ignore it */
-	ATA_FLAG_SUSPENDED	= (1 << 23), /* port is suspended (power) */
+	/* struct ata_port pflags */
+	ATA_PFLAG_EH_PENDING	= (1 << 0), /* EH pending */
+	ATA_PFLAG_EH_IN_PROGRESS = (1 << 1), /* EH in progress */
+	ATA_PFLAG_FROZEN	= (1 << 2), /* port is frozen */
+	ATA_PFLAG_RECOVERED	= (1 << 3), /* recovery action performed */
+	ATA_PFLAG_LOADING	= (1 << 4), /* boot/loading probe */
+	ATA_PFLAG_UNLOADING	= (1 << 5), /* module is unloading */
+	ATA_PFLAG_SCSI_HOTPLUG	= (1 << 6), /* SCSI hotplug scheduled */
 
-	/* bits 24:31 of ap->flags are reserved for LLDD specific flags */
+	ATA_PFLAG_FLUSH_PORT_TASK = (1 << 16), /* flush port task */
+	ATA_PFLAG_SUSPENDED	= (1 << 17), /* port is suspended (power) */
+	ATA_PFLAG_PM_PENDING	= (1 << 18), /* PM operation pending */
 
 	/* struct ata_queued_cmd flags */
 	ATA_QCFLAG_ACTIVE	= (1 << 0), /* cmd not yet ack'd to scsi lyer */
@@ -248,12 +255,19 @@ enum {
 	ATA_EH_REVALIDATE	= (1 << 0),
 	ATA_EH_SOFTRESET	= (1 << 1),
 	ATA_EH_HARDRESET	= (1 << 2),
+	ATA_EH_SUSPEND		= (1 << 3),
+	ATA_EH_RESUME		= (1 << 4),
+	ATA_EH_PM_FREEZE	= (1 << 5),
 
 	ATA_EH_RESET_MASK	= ATA_EH_SOFTRESET | ATA_EH_HARDRESET,
-	ATA_EH_PERDEV_MASK	= ATA_EH_REVALIDATE,
+	ATA_EH_PERDEV_MASK	= ATA_EH_REVALIDATE | ATA_EH_SUSPEND |
+				  ATA_EH_RESUME | ATA_EH_PM_FREEZE,
 
 	/* ata_eh_info->flags */
 	ATA_EHI_HOTPLUGGED	= (1 << 0),  /* could have been hotplugged */
+	ATA_EHI_RESUME_LINK	= (1 << 1),  /* need to resume link */
+	ATA_EHI_NO_AUTOPSY	= (1 << 2),  /* no autopsy */
+	ATA_EHI_QUIET		= (1 << 3),  /* be quiet */
 
 	ATA_EHI_DID_RESET	= (1 << 16), /* already reset this port */
 
@@ -486,6 +500,7 @@ struct ata_port {
 	const struct ata_port_operations *ops;
 	spinlock_t		*lock;
 	unsigned long		flags;	/* ATA_FLAG_xxx */
+	unsigned int		pflags; /* ATA_PFLAG_xxx */
 	unsigned int		id;	/* unique id req'd by scsi midlyr */
 	unsigned int		port_no; /* unique port #; from zero */
 	unsigned int		hard_port_no;	/* hardware port #; from zero */
@@ -535,6 +550,9 @@ struct ata_port {
 	struct list_head	eh_done_q;
 	wait_queue_head_t	eh_wait_q;
 
+	pm_message_t		pm_mesg;
+	int			*pm_result;
+
 	void			*private_data;
 
 	u8			sector_buf[ATA_SECT_SIZE]; /* owned by EH */
@@ -589,6 +607,9 @@ struct ata_port_operations {
 	void (*scr_write) (struct ata_port *ap, unsigned int sc_reg,
 			   u32 val);
 
+	int (*port_suspend) (struct ata_port *ap, pm_message_t mesg);
+	int (*port_resume) (struct ata_port *ap);
+
 	int (*port_start) (struct ata_port *ap);
 	void (*port_stop) (struct ata_port *ap);
 
@@ -622,9 +643,18 @@ struct ata_timing {
 
 #define FIT(v,vmin,vmax)	max_t(short,min_t(short,v,vmax),vmin)
 
-extern const unsigned long sata_deb_timing_boot[];
-extern const unsigned long sata_deb_timing_eh[];
-extern const unsigned long sata_deb_timing_before_fsrst[];
+extern const unsigned long sata_deb_timing_normal[];
+extern const unsigned long sata_deb_timing_hotplug[];
+extern const unsigned long sata_deb_timing_long[];
+
+static inline const unsigned long *
+sata_ehc_deb_timing(struct ata_eh_context *ehc)
+{
+	if (ehc->i.flags & ATA_EHI_HOTPLUGGED)
+		return sata_deb_timing_hotplug;
+	else
+		return sata_deb_timing_normal;
+}
 
 extern void ata_port_probe(struct ata_port *);
 extern void __sata_phy_reset(struct ata_port *ap);
@@ -644,6 +674,8 @@ #ifdef CONFIG_PCI
 extern int ata_pci_init_one (struct pci_dev *pdev, struct ata_port_info **port_info,
 			     unsigned int n_ports);
 extern void ata_pci_remove_one (struct pci_dev *pdev);
+extern void ata_pci_device_do_suspend(struct pci_dev *pdev, pm_message_t state);
+extern void ata_pci_device_do_resume(struct pci_dev *pdev);
 extern int ata_pci_device_suspend(struct pci_dev *pdev, pm_message_t state);
 extern int ata_pci_device_resume(struct pci_dev *pdev);
 extern int ata_pci_clear_simplex(struct pci_dev *pdev);
@@ -664,8 +696,9 @@ extern int ata_port_online(struct ata_po
 extern int ata_port_offline(struct ata_port *ap);
 extern int ata_scsi_device_resume(struct scsi_device *);
 extern int ata_scsi_device_suspend(struct scsi_device *, pm_message_t state);
-extern int ata_device_resume(struct ata_device *);
-extern int ata_device_suspend(struct ata_device *, pm_message_t state);
+extern int ata_host_set_suspend(struct ata_host_set *host_set,
+				pm_message_t mesg);
+extern void ata_host_set_resume(struct ata_host_set *host_set);
 extern int ata_ratelimit(void);
 extern unsigned int ata_busy_sleep(struct ata_port *ap,
 				   unsigned long timeout_pat,
@@ -825,19 +858,24 @@ #define ata_ehi_clear_desc(ehi) do { \
 	(ehi)->desc_len = 0; \
 } while (0)
 
-static inline void ata_ehi_hotplugged(struct ata_eh_info *ehi)
+static inline void __ata_ehi_hotplugged(struct ata_eh_info *ehi)
 {
 	if (ehi->flags & ATA_EHI_HOTPLUGGED)
 		return;
 
-	ehi->flags |= ATA_EHI_HOTPLUGGED;
+	ehi->flags |= ATA_EHI_HOTPLUGGED | ATA_EHI_RESUME_LINK;
 	ehi->hotplug_timestamp = jiffies;
 
-	ehi->err_mask |= AC_ERR_ATA_BUS;
 	ehi->action |= ATA_EH_SOFTRESET;
 	ehi->probe_mask |= (1 << ATA_MAX_DEVICES) - 1;
 }
 
+static inline void ata_ehi_hotplugged(struct ata_eh_info *ehi)
+{
+	__ata_ehi_hotplugged(ehi);
+	ehi->err_mask |= AC_ERR_ATA_BUS;
+}
+
 /*
  * qc helpers
  */
@@ -921,6 +959,11 @@ static inline unsigned int ata_dev_absen
 	return ata_class_absent(dev->class);
 }
 
+static inline unsigned int ata_dev_ready(const struct ata_device *dev)
+{
+	return ata_dev_enabled(dev) && !(dev->flags & ATA_DFLAG_SUSPENDED);
+}
+
 /*
  * port helpers
  */
diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h
index 685081c..c09396d 100644
--- a/include/linux/pci_ids.h
+++ b/include/linux/pci_ids.h
@@ -2019,6 +2019,13 @@ #define PCI_VENDOR_ID_TOPSPIN		0x1867
 #define PCI_VENDOR_ID_TDI               0x192E
 #define PCI_DEVICE_ID_TDI_EHCI          0x0101
 
+#define PCI_VENDOR_ID_JMICRON		0x197B
+#define PCI_DEVICE_ID_JMICRON_JMB360	0x2360
+#define PCI_DEVICE_ID_JMICRON_JMB361	0x2361
+#define PCI_DEVICE_ID_JMICRON_JMB363	0x2363
+#define PCI_DEVICE_ID_JMICRON_JMB365	0x2365
+#define PCI_DEVICE_ID_JMICRON_JMB366	0x2366
+#define PCI_DEVICE_ID_JMICRON_JMB368	0x2368
 
 #define PCI_VENDOR_ID_TEKRAM		0x1de1
 #define PCI_DEVICE_ID_TEKRAM_DC290	0xdc29

^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [git patches] libata update
@ 2005-09-05  9:33 Jeff Garzik
  0 siblings, 0 replies; 15+ messages in thread
From: Jeff Garzik @ 2005-09-05  9:33 UTC (permalink / raw)
  To: Andrew Morton, Linus Torvalds; +Cc: linux-ide, linux-kernel



Please pull from the 'upstream' branch of
rsync://rsync.kernel.org/pub/scm/linux/kernel/git/jgarzik/libata-dev.git

to receive some libata updates, described below.

This does two vaguely notable things:

* converts ATAPI from compile-time to runtime option, making it easier
  for people to test.  ATAPI will be turned on by default when its ready
  for production use.  Its not there yet.

* uses pci_iomap() in several drivers, which gets us one step closer
  to killing all those iomap-related warnings when building libata.




 drivers/scsi/ahci.c         |   52 +++++++++++++++++-------------------------
 drivers/scsi/ata_piix.c     |   11 ++++----
 drivers/scsi/libata-core.c  |   15 +++++++++++-
 drivers/scsi/libata-scsi.c  |    8 +++---
 drivers/scsi/libata.h       |    1 
 drivers/scsi/sata_nv.c      |    9 ++++---
 drivers/scsi/sata_promise.c |   20 ++++++++--------
 drivers/scsi/sata_qstor.c   |    8 +++---
 drivers/scsi/sata_sil.c     |   12 +++++----
 drivers/scsi/sata_svw.c     |    7 ++---
 drivers/scsi/sata_sx4.c     |   54 ++++++++++++++++++++++----------------------
 drivers/scsi/sata_vsc.c     |    5 +---
 include/linux/libata.h      |    2 -
 13 files changed, 104 insertions(+), 100 deletions(-)



Jeff Garzik:
  [libata] allow ATAPI to be enabled with new atapi_enabled module option
  [libata ahci] minor remove/unplug path cleanup
  [libata] __iomem annotations for various drivers
  [libata] update several drivers to use pci_iomap()/pci_iounmap()
  [libata] fix ATAPI-enable typo
  /spare/repo/libata-dev branch 'master'
  /spare/repo/libata-dev branch 'iomap-try3'



diff --git a/drivers/scsi/ahci.c b/drivers/scsi/ahci.c
--- a/drivers/scsi/ahci.c
+++ b/drivers/scsi/ahci.c
@@ -189,7 +189,6 @@ static void ahci_irq_clear(struct ata_po
 static void ahci_eng_timeout(struct ata_port *ap);
 static int ahci_port_start(struct ata_port *ap);
 static void ahci_port_stop(struct ata_port *ap);
-static void ahci_host_stop(struct ata_host_set *host_set);
 static void ahci_tf_read(struct ata_port *ap, struct ata_taskfile *tf);
 static void ahci_qc_prep(struct ata_queued_cmd *qc);
 static u8 ahci_check_status(struct ata_port *ap);
@@ -242,7 +241,6 @@ static struct ata_port_operations ahci_o
 
 	.port_start		= ahci_port_start,
 	.port_stop		= ahci_port_stop,
-	.host_stop		= ahci_host_stop,
 };
 
 static struct ata_port_info ahci_port_info[] = {
@@ -296,17 +294,9 @@ static inline unsigned long ahci_port_ba
 	return base + 0x100 + (port * 0x80);
 }
 
-static inline void *ahci_port_base (void *base, unsigned int port)
+static inline void __iomem *ahci_port_base (void __iomem *base, unsigned int port)
 {
-	return (void *) ahci_port_base_ul((unsigned long)base, port);
-}
-
-static void ahci_host_stop(struct ata_host_set *host_set)
-{
-	struct ahci_host_priv *hpriv = host_set->private_data;
-	kfree(hpriv);
-
-	ata_host_stop(host_set);
+	return (void __iomem *) ahci_port_base_ul((unsigned long)base, port);
 }
 
 static int ahci_port_start(struct ata_port *ap)
@@ -314,8 +304,9 @@ static int ahci_port_start(struct ata_po
 	struct device *dev = ap->host_set->dev;
 	struct ahci_host_priv *hpriv = ap->host_set->private_data;
 	struct ahci_port_priv *pp;
-	void *mem, *mmio = ap->host_set->mmio_base;
-	void *port_mmio = ahci_port_base(mmio, ap->port_no);
+	void __iomem *mmio = ap->host_set->mmio_base;
+	void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
+	void *mem;
 	dma_addr_t mem_dma;
 
 	pp = kmalloc(sizeof(*pp), GFP_KERNEL);
@@ -383,8 +374,8 @@ static void ahci_port_stop(struct ata_po
 {
 	struct device *dev = ap->host_set->dev;
 	struct ahci_port_priv *pp = ap->private_data;
-	void *mmio = ap->host_set->mmio_base;
-	void *port_mmio = ahci_port_base(mmio, ap->port_no);
+	void __iomem *mmio = ap->host_set->mmio_base;
+	void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
 	u32 tmp;
 
 	tmp = readl(port_mmio + PORT_CMD);
@@ -546,8 +537,8 @@ static void ahci_qc_prep(struct ata_queu
 
 static void ahci_intr_error(struct ata_port *ap, u32 irq_stat)
 {
-	void *mmio = ap->host_set->mmio_base;
-	void *port_mmio = ahci_port_base(mmio, ap->port_no);
+	void __iomem *mmio = ap->host_set->mmio_base;
+	void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
 	u32 tmp;
 	int work;
 
@@ -595,8 +586,8 @@ static void ahci_intr_error(struct ata_p
 static void ahci_eng_timeout(struct ata_port *ap)
 {
 	struct ata_host_set *host_set = ap->host_set;
-	void *mmio = host_set->mmio_base;
-	void *port_mmio = ahci_port_base(mmio, ap->port_no);
+	void __iomem *mmio = host_set->mmio_base;
+	void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
 	struct ata_queued_cmd *qc;
 	unsigned long flags;
 
@@ -626,8 +617,8 @@ static void ahci_eng_timeout(struct ata_
 
 static inline int ahci_host_intr(struct ata_port *ap, struct ata_queued_cmd *qc)
 {
-	void *mmio = ap->host_set->mmio_base;
-	void *port_mmio = ahci_port_base(mmio, ap->port_no);
+	void __iomem *mmio = ap->host_set->mmio_base;
+	void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no);
 	u32 status, serr, ci;
 
 	serr = readl(port_mmio + PORT_SCR_ERR);
@@ -663,7 +654,7 @@ static irqreturn_t ahci_interrupt (int i
 	struct ata_host_set *host_set = dev_instance;
 	struct ahci_host_priv *hpriv;
 	unsigned int i, handled = 0;
-	void *mmio;
+	void __iomem *mmio;
 	u32 irq_stat, irq_ack = 0;
 
 	VPRINTK("ENTER\n");
@@ -709,7 +700,7 @@ static irqreturn_t ahci_interrupt (int i
 static int ahci_qc_issue(struct ata_queued_cmd *qc)
 {
 	struct ata_port *ap = qc->ap;
-	void *port_mmio = (void *) ap->ioaddr.cmd_addr;
+	void __iomem *port_mmio = (void __iomem *) ap->ioaddr.cmd_addr;
 
 	writel(1, port_mmio + PORT_CMD_ISSUE);
 	readl(port_mmio + PORT_CMD_ISSUE);	/* flush */
@@ -894,7 +885,7 @@ static void ahci_print_info(struct ata_p
 {
 	struct ahci_host_priv *hpriv = probe_ent->private_data;
 	struct pci_dev *pdev = to_pci_dev(probe_ent->dev);
-	void *mmio = probe_ent->mmio_base;
+	void __iomem *mmio = probe_ent->mmio_base;
 	u32 vers, cap, impl, speed;
 	const char *speed_s;
 	u16 cc;
@@ -967,7 +958,7 @@ static int ahci_init_one (struct pci_dev
 	struct ata_probe_ent *probe_ent = NULL;
 	struct ahci_host_priv *hpriv;
 	unsigned long base;
-	void *mmio_base;
+	void __iomem *mmio_base;
 	unsigned int board_idx = (unsigned int) ent->driver_data;
 	int have_msi, pci_dev_busy = 0;
 	int rc;
@@ -1004,8 +995,7 @@ static int ahci_init_one (struct pci_dev
 	probe_ent->dev = pci_dev_to_dev(pdev);
 	INIT_LIST_HEAD(&probe_ent->node);
 
-	mmio_base = ioremap(pci_resource_start(pdev, AHCI_PCI_BAR),
-		            pci_resource_len(pdev, AHCI_PCI_BAR));
+	mmio_base = pci_iomap(pdev, AHCI_PCI_BAR, 0);
 	if (mmio_base == NULL) {
 		rc = -ENOMEM;
 		goto err_out_free_ent;
@@ -1049,7 +1039,7 @@ static int ahci_init_one (struct pci_dev
 err_out_hpriv:
 	kfree(hpriv);
 err_out_iounmap:
-	iounmap(mmio_base);
+	pci_iounmap(pdev, mmio_base);
 err_out_free_ent:
 	kfree(probe_ent);
 err_out_msi:
@@ -1089,7 +1079,8 @@ static void ahci_remove_one (struct pci_
 		scsi_host_put(ap->host);
 	}
 
-	host_set->ops->host_stop(host_set);
+	kfree(hpriv);
+	pci_iounmap(pdev, host_set->mmio_base);
 	kfree(host_set);
 
 	if (have_msi)
@@ -1106,7 +1097,6 @@ static int __init ahci_init(void)
 	return pci_module_init(&ahci_pci_driver);
 }
 
-
 static void __exit ahci_exit(void)
 {
 	pci_unregister_driver(&ahci_pci_driver);
diff --git a/drivers/scsi/ata_piix.c b/drivers/scsi/ata_piix.c
--- a/drivers/scsi/ata_piix.c
+++ b/drivers/scsi/ata_piix.c
@@ -583,8 +583,7 @@ static void pci_enable_intx(struct pci_d
 #define AHCI_ENABLE (1 << 31)
 static int piix_disable_ahci(struct pci_dev *pdev)
 {
-	void *mmio;
-	unsigned long addr;
+	void __iomem *mmio;
 	u32 tmp;
 	int rc = 0;
 
@@ -592,11 +591,11 @@ static int piix_disable_ahci(struct pci_
 	 * works because this device is usually set up by BIOS.
 	 */
 
-	addr = pci_resource_start(pdev, AHCI_PCI_BAR);
-	if (!addr || !pci_resource_len(pdev, AHCI_PCI_BAR))
+	if (!pci_resource_start(pdev, AHCI_PCI_BAR) ||
+	    !pci_resource_len(pdev, AHCI_PCI_BAR))
 		return 0;
 
-	mmio = ioremap(addr, 64);
+	mmio = pci_iomap(pdev, AHCI_PCI_BAR, 64);
 	if (!mmio)
 		return -ENOMEM;
 
@@ -610,7 +609,7 @@ static int piix_disable_ahci(struct pci_
 			rc = -EIO;
 	}
 
-	iounmap(mmio);
+	pci_iounmap(pdev, mmio);
 	return rc;
 }
 
diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c
--- a/drivers/scsi/libata-core.c
+++ b/drivers/scsi/libata-core.c
@@ -75,6 +75,10 @@ static void __ata_qc_complete(struct ata
 static unsigned int ata_unique_id = 1;
 static struct workqueue_struct *ata_wq;
 
+int atapi_enabled = 0;
+module_param(atapi_enabled, int, 0444);
+MODULE_PARM_DESC(atapi_enabled, "Enable discovery of ATAPI devices (0=off, 1=on)");
+
 MODULE_AUTHOR("Jeff Garzik");
 MODULE_DESCRIPTION("Library module for ATA devices");
 MODULE_LICENSE("GPL");
@@ -4200,6 +4204,15 @@ ata_probe_ent_alloc(struct device *dev, 
 
 
 
+#ifdef CONFIG_PCI
+
+void ata_pci_host_stop (struct ata_host_set *host_set)
+{
+	struct pci_dev *pdev = to_pci_dev(host_set->dev);
+
+	pci_iounmap(pdev, host_set->mmio_base);
+}
+
 /**
  *	ata_pci_init_native_mode - Initialize native-mode driver
  *	@pdev:  pci device to be initialized
@@ -4212,7 +4225,6 @@ ata_probe_ent_alloc(struct device *dev, 
  *	ata_probe_ent structure should then be freed with kfree().
  */
 
-#ifdef CONFIG_PCI
 struct ata_probe_ent *
 ata_pci_init_native_mode(struct pci_dev *pdev, struct ata_port_info **port)
 {
@@ -4595,6 +4607,7 @@ EXPORT_SYMBOL_GPL(ata_scsi_simulate);
 
 #ifdef CONFIG_PCI
 EXPORT_SYMBOL_GPL(pci_test_config_bits);
+EXPORT_SYMBOL_GPL(ata_pci_host_stop);
 EXPORT_SYMBOL_GPL(ata_pci_init_native_mode);
 EXPORT_SYMBOL_GPL(ata_pci_init_one);
 EXPORT_SYMBOL_GPL(ata_pci_remove_one);
diff --git a/drivers/scsi/libata-scsi.c b/drivers/scsi/libata-scsi.c
--- a/drivers/scsi/libata-scsi.c
+++ b/drivers/scsi/libata-scsi.c
@@ -1470,10 +1470,10 @@ ata_scsi_find_dev(struct ata_port *ap, s
 	if (unlikely(!ata_dev_present(dev)))
 		return NULL;
 
-#ifndef ATA_ENABLE_ATAPI
-	if (unlikely(dev->class == ATA_DEV_ATAPI))
-		return NULL;
-#endif
+	if (!atapi_enabled) {
+		if (unlikely(dev->class == ATA_DEV_ATAPI))
+			return NULL;
+	}
 
 	return dev;
 }
diff --git a/drivers/scsi/libata.h b/drivers/scsi/libata.h
--- a/drivers/scsi/libata.h
+++ b/drivers/scsi/libata.h
@@ -38,6 +38,7 @@ struct ata_scsi_args {
 };
 
 /* libata-core.c */
+extern int atapi_enabled;
 extern struct ata_queued_cmd *ata_qc_new_init(struct ata_port *ap,
 				      struct ata_device *dev);
 extern void ata_qc_free(struct ata_queued_cmd *qc);
diff --git a/drivers/scsi/sata_nv.c b/drivers/scsi/sata_nv.c
--- a/drivers/scsi/sata_nv.c
+++ b/drivers/scsi/sata_nv.c
@@ -351,6 +351,7 @@ static void nv_scr_write (struct ata_por
 static void nv_host_stop (struct ata_host_set *host_set)
 {
 	struct nv_host *host = host_set->private_data;
+	struct pci_dev *pdev = to_pci_dev(host_set->dev);
 
 	// Disable hotplug event interrupts.
 	if (host->host_desc->disable_hotplug)
@@ -358,7 +359,8 @@ static void nv_host_stop (struct ata_hos
 
 	kfree(host);
 
-	ata_host_stop(host_set);
+	if (host_set->mmio_base)
+		pci_iounmap(pdev, host_set->mmio_base);
 }
 
 static int nv_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
@@ -420,8 +422,7 @@ static int nv_init_one (struct pci_dev *
 	if (host->host_flags & NV_HOST_FLAGS_SCR_MMIO) {
 		unsigned long base;
 
-		probe_ent->mmio_base = ioremap(pci_resource_start(pdev, 5),
-				pci_resource_len(pdev, 5));
+		probe_ent->mmio_base = pci_iomap(pdev, 5, 0);
 		if (probe_ent->mmio_base == NULL) {
 			rc = -EIO;
 			goto err_out_free_host;
@@ -457,7 +458,7 @@ static int nv_init_one (struct pci_dev *
 
 err_out_iounmap:
 	if (host->host_flags & NV_HOST_FLAGS_SCR_MMIO)
-		iounmap(probe_ent->mmio_base);
+		pci_iounmap(pdev, probe_ent->mmio_base);
 err_out_free_host:
 	kfree(host);
 err_out_free_ent:
diff --git a/drivers/scsi/sata_promise.c b/drivers/scsi/sata_promise.c
--- a/drivers/scsi/sata_promise.c
+++ b/drivers/scsi/sata_promise.c
@@ -92,6 +92,7 @@ static void pdc_exec_command_mmio(struct
 static void pdc_irq_clear(struct ata_port *ap);
 static int pdc_qc_issue_prot(struct ata_queued_cmd *qc);
 
+
 static Scsi_Host_Template pdc_ata_sht = {
 	.module			= THIS_MODULE,
 	.name			= DRV_NAME,
@@ -132,7 +133,7 @@ static struct ata_port_operations pdc_sa
 	.scr_write		= pdc_sata_scr_write,
 	.port_start		= pdc_port_start,
 	.port_stop		= pdc_port_stop,
-	.host_stop		= ata_host_stop,
+	.host_stop		= ata_pci_host_stop,
 };
 
 static struct ata_port_operations pdc_pata_ops = {
@@ -153,7 +154,7 @@ static struct ata_port_operations pdc_pa
 
 	.port_start		= pdc_port_start,
 	.port_stop		= pdc_port_stop,
-	.host_stop		= ata_host_stop,
+	.host_stop		= ata_pci_host_stop,
 };
 
 static struct ata_port_info pdc_port_info[] = {
@@ -282,7 +283,7 @@ static void pdc_port_stop(struct ata_por
 
 static void pdc_reset_port(struct ata_port *ap)
 {
-	void *mmio = (void *) ap->ioaddr.cmd_addr + PDC_CTLSTAT;
+	void __iomem *mmio = (void __iomem *) ap->ioaddr.cmd_addr + PDC_CTLSTAT;
 	unsigned int i;
 	u32 tmp;
 
@@ -418,7 +419,7 @@ static inline unsigned int pdc_host_intr
 	u8 status;
 	unsigned int handled = 0, have_err = 0;
 	u32 tmp;
-	void *mmio = (void *) ap->ioaddr.cmd_addr + PDC_GLOBAL_CTL;
+	void __iomem *mmio = (void __iomem *) ap->ioaddr.cmd_addr + PDC_GLOBAL_CTL;
 
 	tmp = readl(mmio);
 	if (tmp & PDC_ERR_MASK) {
@@ -447,7 +448,7 @@ static inline unsigned int pdc_host_intr
 static void pdc_irq_clear(struct ata_port *ap)
 {
 	struct ata_host_set *host_set = ap->host_set;
-	void *mmio = host_set->mmio_base;
+	void __iomem *mmio = host_set->mmio_base;
 
 	readl(mmio + PDC_INT_SEQMASK);
 }
@@ -459,7 +460,7 @@ static irqreturn_t pdc_interrupt (int ir
 	u32 mask = 0;
 	unsigned int i, tmp;
 	unsigned int handled = 0;
-	void *mmio_base;
+	void __iomem *mmio_base;
 
 	VPRINTK("ENTER\n");
 
@@ -581,7 +582,7 @@ static void pdc_ata_setup_port(struct at
 
 static void pdc_host_init(unsigned int chip_id, struct ata_probe_ent *pe)
 {
-	void *mmio = pe->mmio_base;
+	void __iomem *mmio = pe->mmio_base;
 	u32 tmp;
 
 	/*
@@ -624,7 +625,7 @@ static int pdc_ata_init_one (struct pci_
 	static int printed_version;
 	struct ata_probe_ent *probe_ent = NULL;
 	unsigned long base;
-	void *mmio_base;
+	void __iomem *mmio_base;
 	unsigned int board_idx = (unsigned int) ent->driver_data;
 	int pci_dev_busy = 0;
 	int rc;
@@ -663,8 +664,7 @@ static int pdc_ata_init_one (struct pci_
 	probe_ent->dev = pci_dev_to_dev(pdev);
 	INIT_LIST_HEAD(&probe_ent->node);
 
-	mmio_base = ioremap(pci_resource_start(pdev, 3),
-		            pci_resource_len(pdev, 3));
+	mmio_base = pci_iomap(pdev, 3, 0);
 	if (mmio_base == NULL) {
 		rc = -ENOMEM;
 		goto err_out_free_ent;
diff --git a/drivers/scsi/sata_qstor.c b/drivers/scsi/sata_qstor.c
--- a/drivers/scsi/sata_qstor.c
+++ b/drivers/scsi/sata_qstor.c
@@ -538,11 +538,12 @@ static void qs_port_stop(struct ata_port
 static void qs_host_stop(struct ata_host_set *host_set)
 {
 	void __iomem *mmio_base = host_set->mmio_base;
+	struct pci_dev *pdev = to_pci_dev(host_set->dev);
 
 	writeb(0, mmio_base + QS_HCT_CTRL); /* disable host interrupts */
 	writeb(QS_CNFG3_GSRST, mmio_base + QS_HCF_CNFG3); /* global reset */
 
-	ata_host_stop(host_set);
+	pci_iounmap(pdev, mmio_base);
 }
 
 static void qs_host_init(unsigned int chip_id, struct ata_probe_ent *pe)
@@ -646,8 +647,7 @@ static int qs_ata_init_one(struct pci_de
 		goto err_out_regions;
 	}
 
-	mmio_base = ioremap(pci_resource_start(pdev, 4),
-		            pci_resource_len(pdev, 4));
+	mmio_base = pci_iomap(pdev, 4, 0);
 	if (mmio_base == NULL) {
 		rc = -ENOMEM;
 		goto err_out_regions;
@@ -697,7 +697,7 @@ static int qs_ata_init_one(struct pci_de
 	return 0;
 
 err_out_iounmap:
-	iounmap(mmio_base);
+	pci_iounmap(pdev, mmio_base);
 err_out_regions:
 	pci_release_regions(pdev);
 err_out:
diff --git a/drivers/scsi/sata_sil.c b/drivers/scsi/sata_sil.c
--- a/drivers/scsi/sata_sil.c
+++ b/drivers/scsi/sata_sil.c
@@ -86,6 +86,7 @@ static u32 sil_scr_read (struct ata_port
 static void sil_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val);
 static void sil_post_set_mode (struct ata_port *ap);
 
+
 static struct pci_device_id sil_pci_tbl[] = {
 	{ 0x1095, 0x3112, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112_m15w },
 	{ 0x1095, 0x0240, PCI_ANY_ID, PCI_ANY_ID, 0, 0, sil_3112_m15w },
@@ -172,7 +173,7 @@ static struct ata_port_operations sil_op
 	.scr_write		= sil_scr_write,
 	.port_start		= ata_port_start,
 	.port_stop		= ata_port_stop,
-	.host_stop		= ata_host_stop,
+	.host_stop		= ata_pci_host_stop,
 };
 
 static struct ata_port_info sil_port_info[] = {
@@ -231,6 +232,7 @@ MODULE_LICENSE("GPL");
 MODULE_DEVICE_TABLE(pci, sil_pci_tbl);
 MODULE_VERSION(DRV_VERSION);
 
+
 static unsigned char sil_get_device_cache_line(struct pci_dev *pdev)
 {
 	u8 cache_line = 0;
@@ -242,7 +244,8 @@ static void sil_post_set_mode (struct at
 {
 	struct ata_host_set *host_set = ap->host_set;
 	struct ata_device *dev;
-	void *addr = host_set->mmio_base + sil_port[ap->port_no].xfer_mode;
+	void __iomem *addr =
+		host_set->mmio_base + sil_port[ap->port_no].xfer_mode;
 	u32 tmp, dev_mode[2];
 	unsigned int i;
 
@@ -375,7 +378,7 @@ static int sil_init_one (struct pci_dev 
 	static int printed_version;
 	struct ata_probe_ent *probe_ent = NULL;
 	unsigned long base;
-	void *mmio_base;
+	void __iomem *mmio_base;
 	int rc;
 	unsigned int i;
 	int pci_dev_busy = 0;
@@ -425,8 +428,7 @@ static int sil_init_one (struct pci_dev 
        	probe_ent->irq_flags = SA_SHIRQ;
 	probe_ent->host_flags = sil_port_info[ent->driver_data].host_flags;
 
-	mmio_base = ioremap(pci_resource_start(pdev, 5),
-		            pci_resource_len(pdev, 5));
+	mmio_base = pci_iomap(pdev, 5, 0);
 	if (mmio_base == NULL) {
 		rc = -ENOMEM;
 		goto err_out_free_ent;
diff --git a/drivers/scsi/sata_svw.c b/drivers/scsi/sata_svw.c
--- a/drivers/scsi/sata_svw.c
+++ b/drivers/scsi/sata_svw.c
@@ -318,7 +318,7 @@ static struct ata_port_operations k2_sat
 	.scr_write		= k2_sata_scr_write,
 	.port_start		= ata_port_start,
 	.port_stop		= ata_port_stop,
-	.host_stop		= ata_host_stop,
+	.host_stop		= ata_pci_host_stop,
 };
 
 static void k2_sata_setup_port(struct ata_ioports *port, unsigned long base)
@@ -346,7 +346,7 @@ static int k2_sata_init_one (struct pci_
 	static int printed_version;
 	struct ata_probe_ent *probe_ent = NULL;
 	unsigned long base;
-	void *mmio_base;
+	void __iomem *mmio_base;
 	int pci_dev_busy = 0;
 	int rc;
 	int i;
@@ -392,8 +392,7 @@ static int k2_sata_init_one (struct pci_
 	probe_ent->dev = pci_dev_to_dev(pdev);
 	INIT_LIST_HEAD(&probe_ent->node);
 
-	mmio_base = ioremap(pci_resource_start(pdev, 5),
-		            pci_resource_len(pdev, 5));
+	mmio_base = pci_iomap(pdev, 5, 0);
 	if (mmio_base == NULL) {
 		rc = -ENOMEM;
 		goto err_out_free_ent;
diff --git a/drivers/scsi/sata_sx4.c b/drivers/scsi/sata_sx4.c
--- a/drivers/scsi/sata_sx4.c
+++ b/drivers/scsi/sata_sx4.c
@@ -245,13 +245,14 @@ static struct pci_driver pdc_sata_pci_dr
 
 static void pdc20621_host_stop(struct ata_host_set *host_set)
 {
+	struct pci_dev *pdev = to_pci_dev(host_set->dev);
 	struct pdc_host_priv *hpriv = host_set->private_data;
 	void *dimm_mmio = hpriv->dimm_mmio;
 
-	iounmap(dimm_mmio);
+	pci_iounmap(pdev, dimm_mmio);
 	kfree(hpriv);
 
-	ata_host_stop(host_set);
+	pci_iounmap(pdev, host_set->mmio_base);
 }
 
 static int pdc_port_start(struct ata_port *ap)
@@ -451,9 +452,9 @@ static void pdc20621_dma_prep(struct ata
 	struct scatterlist *sg = qc->sg;
 	struct ata_port *ap = qc->ap;
 	struct pdc_port_priv *pp = ap->private_data;
-	void *mmio = ap->host_set->mmio_base;
+	void __iomem *mmio = ap->host_set->mmio_base;
 	struct pdc_host_priv *hpriv = ap->host_set->private_data;
-	void *dimm_mmio = hpriv->dimm_mmio;
+	void __iomem *dimm_mmio = hpriv->dimm_mmio;
 	unsigned int portno = ap->port_no;
 	unsigned int i, last, idx, total_len = 0, sgt_len;
 	u32 *buf = (u32 *) &pp->dimm_buf[PDC_DIMM_HEADER_SZ];
@@ -513,9 +514,9 @@ static void pdc20621_nodata_prep(struct 
 {
 	struct ata_port *ap = qc->ap;
 	struct pdc_port_priv *pp = ap->private_data;
-	void *mmio = ap->host_set->mmio_base;
+	void __iomem *mmio = ap->host_set->mmio_base;
 	struct pdc_host_priv *hpriv = ap->host_set->private_data;
-	void *dimm_mmio = hpriv->dimm_mmio;
+	void __iomem *dimm_mmio = hpriv->dimm_mmio;
 	unsigned int portno = ap->port_no;
 	unsigned int i;
 
@@ -565,7 +566,7 @@ static void __pdc20621_push_hdma(struct 
 {
 	struct ata_port *ap = qc->ap;
 	struct ata_host_set *host_set = ap->host_set;
-	void *mmio = host_set->mmio_base;
+	void __iomem *mmio = host_set->mmio_base;
 
 	/* hard-code chip #0 */
 	mmio += PDC_CHIP0_OFS;
@@ -639,7 +640,7 @@ static void pdc20621_packet_start(struct
 	struct ata_port *ap = qc->ap;
 	struct ata_host_set *host_set = ap->host_set;
 	unsigned int port_no = ap->port_no;
-	void *mmio = host_set->mmio_base;
+	void __iomem *mmio = host_set->mmio_base;
 	unsigned int rw = (qc->tf.flags & ATA_TFLAG_WRITE);
 	u8 seq = (u8) (port_no + 1);
 	unsigned int port_ofs;
@@ -699,7 +700,7 @@ static int pdc20621_qc_issue_prot(struct
 static inline unsigned int pdc20621_host_intr( struct ata_port *ap,
                                           struct ata_queued_cmd *qc,
 					  unsigned int doing_hdma,
-					  void *mmio)
+					  void __iomem *mmio)
 {
 	unsigned int port_no = ap->port_no;
 	unsigned int port_ofs =
@@ -778,7 +779,7 @@ static inline unsigned int pdc20621_host
 static void pdc20621_irq_clear(struct ata_port *ap)
 {
 	struct ata_host_set *host_set = ap->host_set;
-	void *mmio = host_set->mmio_base;
+	void __iomem *mmio = host_set->mmio_base;
 
 	mmio += PDC_CHIP0_OFS;
 
@@ -792,7 +793,7 @@ static irqreturn_t pdc20621_interrupt (i
 	u32 mask = 0;
 	unsigned int i, tmp, port_no;
 	unsigned int handled = 0;
-	void *mmio_base;
+	void __iomem *mmio_base;
 
 	VPRINTK("ENTER\n");
 
@@ -940,9 +941,9 @@ static void pdc20621_get_from_dimm(struc
 	u16 idx;
 	u8 page_mask;
 	long dist;
-	void *mmio = pe->mmio_base;
+	void __iomem *mmio = pe->mmio_base;
 	struct pdc_host_priv *hpriv = pe->private_data;
-	void *dimm_mmio = hpriv->dimm_mmio;
+	void __iomem *dimm_mmio = hpriv->dimm_mmio;
 
 	/* hard-code chip #0 */
 	mmio += PDC_CHIP0_OFS;
@@ -996,9 +997,9 @@ static void pdc20621_put_to_dimm(struct 
 	u16 idx;
 	u8 page_mask;
 	long dist;
-	void *mmio = pe->mmio_base;
+	void __iomem *mmio = pe->mmio_base;
 	struct pdc_host_priv *hpriv = pe->private_data;
-	void *dimm_mmio = hpriv->dimm_mmio;
+	void __iomem *dimm_mmio = hpriv->dimm_mmio;
 
 	/* hard-code chip #0 */
 	mmio += PDC_CHIP0_OFS;
@@ -1044,7 +1045,7 @@ static void pdc20621_put_to_dimm(struct 
 static unsigned int pdc20621_i2c_read(struct ata_probe_ent *pe, u32 device,
 				      u32 subaddr, u32 *pdata)
 {
-	void *mmio = pe->mmio_base;
+	void __iomem *mmio = pe->mmio_base;
 	u32 i2creg  = 0;
 	u32 status;
 	u32 count =0;
@@ -1103,7 +1104,7 @@ static int pdc20621_prog_dimm0(struct at
 	u32 data = 0;
    	int size, i;
    	u8 bdimmsize;
-   	void *mmio = pe->mmio_base;
+   	void __iomem *mmio = pe->mmio_base;
 	static const struct {
 		unsigned int reg;
 		unsigned int ofs;
@@ -1166,7 +1167,7 @@ static unsigned int pdc20621_prog_dimm_g
 {
 	u32 data, spd0;
    	int error, i;
-   	void *mmio = pe->mmio_base;
+   	void __iomem *mmio = pe->mmio_base;
 
 	/* hard-code chip #0 */
    	mmio += PDC_CHIP0_OFS;
@@ -1220,7 +1221,7 @@ static unsigned int pdc20621_dimm_init(s
 	u32 ticks=0;
 	u32 clock=0;
 	u32 fparam=0;
-   	void *mmio = pe->mmio_base;
+   	void __iomem *mmio = pe->mmio_base;
 
 	/* hard-code chip #0 */
    	mmio += PDC_CHIP0_OFS;
@@ -1344,7 +1345,7 @@ static unsigned int pdc20621_dimm_init(s
 static void pdc_20621_init(struct ata_probe_ent *pe)
 {
 	u32 tmp;
-	void *mmio = pe->mmio_base;
+	void __iomem *mmio = pe->mmio_base;
 
 	/* hard-code chip #0 */
 	mmio += PDC_CHIP0_OFS;
@@ -1377,7 +1378,8 @@ static int pdc_sata_init_one (struct pci
 	static int printed_version;
 	struct ata_probe_ent *probe_ent = NULL;
 	unsigned long base;
-	void *mmio_base, *dimm_mmio = NULL;
+	void __iomem *mmio_base;
+	void __iomem *dimm_mmio = NULL;
 	struct pdc_host_priv *hpriv = NULL;
 	unsigned int board_idx = (unsigned int) ent->driver_data;
 	int pci_dev_busy = 0;
@@ -1417,8 +1419,7 @@ static int pdc_sata_init_one (struct pci
 	probe_ent->dev = pci_dev_to_dev(pdev);
 	INIT_LIST_HEAD(&probe_ent->node);
 
-	mmio_base = ioremap(pci_resource_start(pdev, 3),
-		            pci_resource_len(pdev, 3));
+	mmio_base = pci_iomap(pdev, 3, 0);
 	if (mmio_base == NULL) {
 		rc = -ENOMEM;
 		goto err_out_free_ent;
@@ -1432,8 +1433,7 @@ static int pdc_sata_init_one (struct pci
 	}
 	memset(hpriv, 0, sizeof(*hpriv));
 
-	dimm_mmio = ioremap(pci_resource_start(pdev, 4),
-			    pci_resource_len(pdev, 4));
+	dimm_mmio = pci_iomap(pdev, 4, 0);
 	if (!dimm_mmio) {
 		kfree(hpriv);
 		rc = -ENOMEM;
@@ -1480,9 +1480,9 @@ static int pdc_sata_init_one (struct pci
 
 err_out_iounmap_dimm:		/* only get to this label if 20621 */
 	kfree(hpriv);
-	iounmap(dimm_mmio);
+	pci_iounmap(pdev, dimm_mmio);
 err_out_iounmap:
-	iounmap(mmio_base);
+	pci_iounmap(pdev, mmio_base);
 err_out_free_ent:
 	kfree(probe_ent);
 err_out_regions:
diff --git a/drivers/scsi/sata_vsc.c b/drivers/scsi/sata_vsc.c
--- a/drivers/scsi/sata_vsc.c
+++ b/drivers/scsi/sata_vsc.c
@@ -252,7 +252,7 @@ static struct ata_port_operations vsc_sa
 	.scr_write		= vsc_sata_scr_write,
 	.port_start		= ata_port_start,
 	.port_stop		= ata_port_stop,
-	.host_stop		= ata_host_stop,
+	.host_stop		= ata_pci_host_stop,
 };
 
 static void __devinit vsc_sata_setup_port(struct ata_ioports *port, unsigned long base)
@@ -326,8 +326,7 @@ static int __devinit vsc_sata_init_one (
 	probe_ent->dev = pci_dev_to_dev(pdev);
 	INIT_LIST_HEAD(&probe_ent->node);
 
-	mmio_base = ioremap(pci_resource_start(pdev, 0),
-		            pci_resource_len(pdev, 0));
+	mmio_base = pci_iomap(pdev, 0, 0);
 	if (mmio_base == NULL) {
 		rc = -ENOMEM;
 		goto err_out_free_ent;
diff --git a/include/linux/libata.h b/include/linux/libata.h
--- a/include/linux/libata.h
+++ b/include/linux/libata.h
@@ -40,7 +40,6 @@
 #undef ATA_VERBOSE_DEBUG	/* yet more debugging output */
 #undef ATA_IRQ_TRAP		/* define to ack screaming irqs */
 #undef ATA_NDEBUG		/* define to disable quick runtime checks */
-#undef ATA_ENABLE_ATAPI		/* define to enable ATAPI support */
 #undef ATA_ENABLE_PATA		/* define to enable PATA support in some
 				 * low-level drivers */
 #undef ATAPI_ENABLE_DMADIR	/* enables ATAPI DMADIR bridge support */
@@ -450,6 +449,7 @@ struct pci_bits {
 	unsigned long		val;
 };
 
+extern void ata_pci_host_stop (struct ata_host_set *host_set);
 extern struct ata_probe_ent *
 ata_pci_init_native_mode(struct pci_dev *pdev, struct ata_port_info **port);
 extern int pci_test_config_bits(struct pci_dev *pdev, struct pci_bits *bits);

^ permalink raw reply	[flat|nested] 15+ messages in thread

end of thread, other threads:[~2007-10-26  3:02 UTC | newest]

Thread overview: 15+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2006-06-27  1:24 [git patches] libata update Jeff Garzik
2006-06-28  1:23 ` Linus Torvalds
2006-06-28  1:34   ` Jeff Garzik
  -- strict thread matches above, loose matches on Subject: below --
2007-10-12 19:40 Jeff Garzik
2007-10-13  0:06 ` Luben Tuikov
2007-10-13  1:42 ` Bartlomiej Zolnierkiewicz
2007-10-15 22:31   ` Jeff Garzik
2007-10-13  7:05 ` Andrey Borzenkov
2007-10-13 10:55   ` Jeff Garzik
2007-10-26  3:02     ` Tejun Heo
2007-10-14 10:35 ` Torsten Kaiser
2007-10-14 12:21   ` Alan Cox
2006-09-24 16:29 Jeff Garzik
2006-07-06  3:07 Jeff Garzik
2005-09-05  9:33 Jeff Garzik

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).