All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v4 0/13] SATA ZPODD support
@ 2012-05-28  5:08 Lin Ming
  2012-05-28  5:08 ` [PATCH v4 01/13] [SCSI]: add wrapper to access and set scsi_bus_type in struct acpi_bus_type Lin Ming
                   ` (13 more replies)
  0 siblings, 14 replies; 27+ messages in thread
From: Lin Ming @ 2012-05-28  5:08 UTC (permalink / raw)
  To: Jeff Garzik, David Woodhouse, Aaron Lu, Holger Macht, Matthew Garrett
  Cc: linux-kernel, linux-pm, linux-scsi, linux-ide, linux-acpi

Hi all,

This is the v4 patches to add SATA ZPODD support, to try it:
git pull git://git.kernel.org/pub/scm/linux/kernel/git/mlin/linux.git zpodd

Holger and Mathtew,
Patch 1 to Patch 4 are the libata acpi binding patches from you.
I removed dock related code from your original version.
Would you help to review?

v4:
- Includes libata acpi binding patches from Holger Macht and Matthew Garrett.
- tell scsi layer device supports runtime power off
- check support for device busy class events

v3:
https://lkml.org/lkml/2012/3/28/20
- Split the ACPI D3Cold state support patches out
- Adds "Device Attention" bit check

v2:
https://lkml.org/lkml/2012/3/1/61
- _PR3 indicates D3Cold support
- move can_power_off flag to pm_subsys_data
- allow all combinations of power resource and device
- split patches into smaller ones to make review easy

v1:
https://lkml.org/lkml/2012/2/13/86


Aaron Lu (5):
      libata: tell scsi layer device supports runtime power off
      [SCSI] pm: resume device if suspend failed
      [SCSI] sr: check support for device busy class events
      [SCSI] sr: support zero power ODD
      [SCSI] sr: make sure ODD is in resumed state in block ioctl

Holger Macht (2):
      [SCSI]: add wrapper to access and set scsi_bus_type in struct acpi_bus_type
      libata: use correct PCI devices

Lin Ming (4):
      libata-acpi: set acpi state for SATA port
      libata-acpi: add ata port runtime D3Cold support
      libata-acpi: register/unregister device to/from power resource
      libata: detect Device Attention support

Matthew Garrett (2):
      libata: bind the Linux device tree to the ACPI device tree
      libata: migrate ACPI code over to new bindings


 drivers/acpi/glue.c        |    2 +
 drivers/acpi/power.c       |    2 +
 drivers/ata/libata-acpi.c  |  389 +++++++++++++++++++++++++++++++-------------
 drivers/ata/libata-core.c  |    9 +-
 drivers/ata/libata-pmp.c   |    4 -
 drivers/ata/libata-scsi.c  |    3 +
 drivers/ata/libata.h       |   13 +-
 drivers/ata/pata_acpi.c    |    4 +-
 drivers/scsi/scsi_lib.c    |   17 ++
 drivers/scsi/scsi_pm.c     |    5 +-
 drivers/scsi/sr.c          |  160 ++++++++++++++++++-
 drivers/scsi/sr.h          |    3 +
 include/linux/ata.h        |    1 +
 include/linux/cdrom.h      |   43 +++++
 include/linux/libata.h     |    9 +-
 include/scsi/scsi.h        |   10 +
 include/scsi/scsi_device.h |    2 +
 17 files changed, 538 insertions(+), 138 deletions(-)

                                                          

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

* [PATCH v4 01/13] [SCSI]: add wrapper to access and set scsi_bus_type in struct acpi_bus_type
  2012-05-28  5:08 [PATCH v4 0/13] SATA ZPODD support Lin Ming
@ 2012-05-28  5:08 ` Lin Ming
  2012-05-29 12:26   ` Sergei Shtylyov
  2012-05-28  5:08 ` [PATCH v4 02/13] libata: bind the Linux device tree to the ACPI device tree Lin Ming
                   ` (12 subsequent siblings)
  13 siblings, 1 reply; 27+ messages in thread
From: Lin Ming @ 2012-05-28  5:08 UTC (permalink / raw)
  To: Jeff Garzik, David Woodhouse, Aaron Lu, Holger Macht, Matthew Garrett
  Cc: linux-kernel, linux-pm, linux-scsi, linux-ide, linux-acpi

From: Holger Macht <holger@homac.de>

For being able to bind ata devices against acpi devices, scsi_bus_type
needs to be set as bus in struct acpi_bus_type. So add wrapper to
scsi_lib to accomplish that.

Signed-off-by: Holger Macht <holger@homac.de>
Signed-off-by: Lin Ming <ming.m.lin@intel.com>
---
 drivers/scsi/scsi_lib.c |   17 +++++++++++++++++
 include/scsi/scsi.h     |   10 ++++++++++
 2 files changed, 27 insertions(+), 0 deletions(-)

diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
index 5dfd749..a243212 100644
--- a/drivers/scsi/scsi_lib.c
+++ b/drivers/scsi/scsi_lib.c
@@ -68,6 +68,23 @@ static struct scsi_host_sg_pool scsi_sg_pools[] = {
 
 struct kmem_cache *scsi_sdb_cache;
 
+#ifdef CONFIG_ACPI
+#include <acpi/acpi_bus.h>
+
+int scsi_register_acpi_bus_type(struct acpi_bus_type *bus)
+{
+        bus->bus = &scsi_bus_type;
+        return register_acpi_bus_type(bus);
+}
+EXPORT_SYMBOL_GPL(scsi_register_acpi_bus_type);
+
+void scsi_unregister_acpi_bus_type(struct acpi_bus_type *bus)
+{
+	unregister_acpi_bus_type(bus);
+}
+EXPORT_SYMBOL_GPL(scsi_unregister_acpi_bus_type);
+#endif
+
 /*
  * When to reinvoke queueing after a resource shortage. It's 3 msecs to
  * not change behaviour from the previous unplug mechanism, experimentation
diff --git a/include/scsi/scsi.h b/include/scsi/scsi.h
index f34a5a8..4527b3a 100644
--- a/include/scsi/scsi.h
+++ b/include/scsi/scsi.h
@@ -214,6 +214,16 @@ scsi_command_size(const unsigned char *cmnd)
 		scsi_varlen_cdb_length(cmnd) : COMMAND_SIZE(cmnd[0]);
 }
 
+#ifdef CONFIG_ACPI
+struct acpi_bus_type;
+
+extern int
+scsi_register_acpi_bus_type(struct acpi_bus_type *bus);
+
+extern void
+scsi_unregister_acpi_bus_type(struct acpi_bus_type *bus);
+#endif
+
 /*
  *  SCSI Architecture Model (SAM) Status codes. Taken from SAM-3 draft
  *  T10/1561-D Revision 4 Draft dated 7th November 2002.
-- 
1.7.2.5

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

* [PATCH v4 02/13] libata: bind the Linux device tree to the ACPI device tree
  2012-05-28  5:08 [PATCH v4 0/13] SATA ZPODD support Lin Ming
  2012-05-28  5:08 ` [PATCH v4 01/13] [SCSI]: add wrapper to access and set scsi_bus_type in struct acpi_bus_type Lin Ming
@ 2012-05-28  5:08 ` Lin Ming
  2012-05-28  9:51   ` Alan Cox
  2012-05-28  5:08 ` [PATCH v4 03/13] libata: migrate ACPI code over to new bindings Lin Ming
                   ` (11 subsequent siblings)
  13 siblings, 1 reply; 27+ messages in thread
From: Lin Ming @ 2012-05-28  5:08 UTC (permalink / raw)
  To: Jeff Garzik, David Woodhouse, Aaron Lu, Holger Macht, Matthew Garrett
  Cc: linux-kernel, linux-pm, linux-scsi, linux-ide, linux-acpi

From: Matthew Garrett <mjg@redhat.com>

Associate the ACPI device tree and libata devices.
This patch uses the generic ACPI glue framework to do so.

Signed-off-by: Matthew Garrett <mjg@redhat.com>
Signed-off-by: Holger Macht <holger@homac.de>
Signed-off-by: Lin Ming <ming.m.lin@intel.com>
---
 drivers/acpi/glue.c       |    2 +
 drivers/ata/libata-acpi.c |  114 +++++++++++++++++++++++++++++++++++++++++++++
 drivers/ata/libata-core.c |    3 +
 drivers/ata/libata.h      |    4 ++
 4 files changed, 123 insertions(+), 0 deletions(-)

diff --git a/drivers/acpi/glue.c b/drivers/acpi/glue.c
index 29a4a5c..18d6812 100644
--- a/drivers/acpi/glue.c
+++ b/drivers/acpi/glue.c
@@ -39,6 +39,7 @@ int register_acpi_bus_type(struct acpi_bus_type *type)
 	}
 	return -ENODEV;
 }
+EXPORT_SYMBOL(register_acpi_bus_type);
 
 int unregister_acpi_bus_type(struct acpi_bus_type *type)
 {
@@ -54,6 +55,7 @@ int unregister_acpi_bus_type(struct acpi_bus_type *type)
 	}
 	return -ENODEV;
 }
+EXPORT_SYMBOL(unregister_acpi_bus_type);
 
 static struct acpi_bus_type *acpi_get_bus_type(struct bus_type *type)
 {
diff --git a/drivers/ata/libata-acpi.c b/drivers/ata/libata-acpi.c
index bb7c5f1..96a5775 100644
--- a/drivers/ata/libata-acpi.c
+++ b/drivers/ata/libata-acpi.c
@@ -47,6 +47,28 @@ static void ata_acpi_clear_gtf(struct ata_device *dev)
 	dev->gtf_cache = NULL;
 }
 
+static acpi_handle ap_acpi_handle(struct ata_port *ap)
+{
+	if (ap->flags & ATA_FLAG_ACPI_SATA)
+		return NULL;
+	return DEVICE_ACPI_HANDLE(&ap->scsi_host->shost_gendev);
+}
+
+static acpi_handle dev_acpi_handle(struct ata_device *dev)
+{
+	acpi_integer adr;
+	struct ata_port *ap = dev->link->ap;
+
+	if (ap->flags & ATA_FLAG_ACPI_SATA) {
+		if (!sata_pmp_attached(ap))
+			adr = SATA_ADR(ap->port_no, NO_PORT_MULT);
+		else
+			adr = SATA_ADR(ap->port_no, dev->link->pmp);
+		return acpi_get_child(DEVICE_ACPI_HANDLE(ap->host->dev), adr);
+	} else
+		return acpi_get_child(ap_acpi_handle(ap), dev->devno);
+}
+
 /**
  * ata_acpi_associate_sata_port - associate SATA port with ACPI objects
  * @ap: target SATA port
@@ -1018,3 +1040,95 @@ void ata_acpi_on_disable(struct ata_device *dev)
 {
 	ata_acpi_clear_gtf(dev);
 }
+
+static int is_pci_ata(struct device *dev)
+{
+	struct pci_dev *pdev;
+
+	if (!is_pci_dev(dev))
+		return 0;
+
+	pdev = to_pci_dev(dev);
+
+	if ((pdev->class >> 8) != PCI_CLASS_STORAGE_SATA &&
+	    (pdev->class >> 8) != PCI_CLASS_STORAGE_IDE)
+		return 0;
+
+	return 1;
+}
+
+static int ata_acpi_bind_host(struct device *dev, int host, acpi_handle *handle)
+{
+	struct Scsi_Host *shost = dev_to_shost(dev);
+	struct ata_port *ap = ata_shost_to_port(shost);
+
+	if (ap->flags & ATA_FLAG_ACPI_SATA)
+		return -ENODEV;
+
+	*handle = acpi_get_child(DEVICE_ACPI_HANDLE(dev->parent), ap->port_no);
+
+	if (!*handle)
+		return -ENODEV;
+
+	return 0;
+}
+
+static int ata_acpi_bind_device(struct device *dev, int channel, int id,
+				acpi_handle *handle)
+{
+	struct device *host = dev->parent->parent;
+	struct Scsi_Host *shost = dev_to_shost(host);
+	struct ata_port *ap = ata_shost_to_port(shost);
+	struct ata_device *ata_dev;
+
+	if (ap->flags & ATA_FLAG_ACPI_SATA)
+		ata_dev = &ap->link.device[channel];
+	else
+		ata_dev = &ap->link.device[id];
+
+	*handle = dev_acpi_handle(ata_dev);
+
+	if (!*handle)
+		return -ENODEV;
+
+	return 0;
+}
+
+static int ata_acpi_find_device(struct device *dev, acpi_handle *handle)
+{
+	unsigned int host, channel, id, lun;
+
+	if (sscanf(dev_name(dev), "host%u", &host) == 1) {
+		if (!is_pci_ata(dev->parent))
+			return -ENODEV;
+
+		return ata_acpi_bind_host(dev, host, handle);
+	} else if (sscanf(dev_name(dev), "%d:%d:%d:%d",
+			&host, &channel, &id, &lun) == 4) {
+		if (!is_pci_ata(dev->parent->parent->parent))
+			return -ENODEV;
+
+		return ata_acpi_bind_device(dev, channel, id, handle);
+	} else
+		return -ENODEV;
+}
+
+static int ata_acpi_find_dummy(struct device *dev, acpi_handle *handle)
+{
+	return -ENODEV;
+}
+
+static struct acpi_bus_type ata_acpi_bus = {
+	.find_bridge = ata_acpi_find_dummy,
+	.find_device = ata_acpi_find_device,
+};
+
+int ata_acpi_register(void)
+{
+	return scsi_register_acpi_bus_type(&ata_acpi_bus);
+}
+
+void ata_acpi_unregister(void)
+{
+	scsi_unregister_acpi_bus_type(&ata_acpi_bus);
+}
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
index 23763a1..8908f9f 100644
--- a/drivers/ata/libata-core.c
+++ b/drivers/ata/libata-core.c
@@ -6506,6 +6506,8 @@ static int __init ata_init(void)
 
 	ata_parse_force_param();
 
+	ata_acpi_register();
+
 	rc = ata_sff_init();
 	if (rc) {
 		kfree(ata_force_tbl);
@@ -6532,6 +6534,7 @@ static void __exit ata_exit(void)
 	ata_release_transport(ata_scsi_transport_template);
 	libata_transport_exit();
 	ata_sff_exit();
+	ata_acpi_unregister();
 	kfree(ata_force_tbl);
 }
 
diff --git a/drivers/ata/libata.h b/drivers/ata/libata.h
index 9d0fd0b..3df3362 100644
--- a/drivers/ata/libata.h
+++ b/drivers/ata/libata.h
@@ -119,6 +119,8 @@ extern void ata_acpi_on_resume(struct ata_port *ap);
 extern int ata_acpi_on_devcfg(struct ata_device *dev);
 extern void ata_acpi_on_disable(struct ata_device *dev);
 extern void ata_acpi_set_state(struct ata_port *ap, pm_message_t state);
+extern int ata_acpi_register(void);
+extern void ata_acpi_unregister(void);
 #else
 static inline void ata_acpi_associate_sata_port(struct ata_port *ap) { }
 static inline void ata_acpi_associate(struct ata_host *host) { }
@@ -129,6 +131,8 @@ static inline int ata_acpi_on_devcfg(struct ata_device *dev) { return 0; }
 static inline void ata_acpi_on_disable(struct ata_device *dev) { }
 static inline void ata_acpi_set_state(struct ata_port *ap,
 				      pm_message_t state) { }
+static inline int ata_acpi_register(void) { return 0; }
+static void ata_acpi_unregister(void) { }
 #endif
 
 /* libata-scsi.c */
-- 
1.7.2.5


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

* [PATCH v4 03/13] libata: migrate ACPI code over to new bindings
  2012-05-28  5:08 [PATCH v4 0/13] SATA ZPODD support Lin Ming
  2012-05-28  5:08 ` [PATCH v4 01/13] [SCSI]: add wrapper to access and set scsi_bus_type in struct acpi_bus_type Lin Ming
  2012-05-28  5:08 ` [PATCH v4 02/13] libata: bind the Linux device tree to the ACPI device tree Lin Ming
@ 2012-05-28  5:08 ` Lin Ming
  2012-05-28  5:08 ` [PATCH v4 04/13] libata: use correct PCI devices Lin Ming
                   ` (10 subsequent siblings)
  13 siblings, 0 replies; 27+ messages in thread
From: Lin Ming @ 2012-05-28  5:08 UTC (permalink / raw)
  To: Jeff Garzik, David Woodhouse, Aaron Lu, Holger Macht, Matthew Garrett
  Cc: linux-kernel, linux-pm, linux-scsi, linux-ide, linux-acpi

From: Matthew Garrett <mjg@redhat.com>

Now that we have the ability to directly glue the ACPI namespace to the
driver model in libata, we don't need the custom code to handle the same
thing. Remove it and migrate the functions over to the new code.

Signed-off-by: Matthew Garrett <mjg@redhat.com>
Signed-off-by: Holger Macht <holger@homac.de>
Signed-off-by: Lin Ming <ming.m.lin@intel.com>
---
 drivers/ata/libata-acpi.c |  161 ++++++++++-----------------------------------
 drivers/ata/libata-core.c |    3 -
 drivers/ata/libata-pmp.c  |    4 -
 drivers/ata/libata.h      |    5 --
 drivers/ata/pata_acpi.c   |    4 +-
 include/linux/libata.h    |    7 +--
 6 files changed, 40 insertions(+), 144 deletions(-)

diff --git a/drivers/ata/libata-acpi.c b/drivers/ata/libata-acpi.c
index 96a5775..762e0c8 100644
--- a/drivers/ata/libata-acpi.c
+++ b/drivers/ata/libata-acpi.c
@@ -47,14 +47,29 @@ static void ata_acpi_clear_gtf(struct ata_device *dev)
 	dev->gtf_cache = NULL;
 }
 
-static acpi_handle ap_acpi_handle(struct ata_port *ap)
+/**
+ * ata_ap_acpi_handle - provide the acpi_handle for an ata_port
+ * @ap: the acpi_handle returned will correspond to this port
+ *
+ * Returns the acpi_handle for the ACPI namespace object corresponding to
+ * the ata_port passed into the function, or NULL if no such object exists
+ */
+acpi_handle ata_ap_acpi_handle(struct ata_port *ap)
 {
 	if (ap->flags & ATA_FLAG_ACPI_SATA)
 		return NULL;
 	return DEVICE_ACPI_HANDLE(&ap->scsi_host->shost_gendev);
 }
+EXPORT_SYMBOL(ata_ap_acpi_handle);
 
-static acpi_handle dev_acpi_handle(struct ata_device *dev)
+/**
+ * ata_dev_acpi_handle - provide the acpi_handle for an ata_device
+ * @dev: the acpi_device returned will correspond to this port
+ *
+ * Returns the acpi_handle for the ACPI namespace object corresponding to
+ * the ata_device passed into the function, or NULL if no such object exists
+ */
+acpi_handle ata_dev_acpi_handle(struct ata_device *dev)
 {
 	acpi_integer adr;
 	struct ata_port *ap = dev->link->ap;
@@ -66,66 +81,9 @@ static acpi_handle dev_acpi_handle(struct ata_device *dev)
 			adr = SATA_ADR(ap->port_no, dev->link->pmp);
 		return acpi_get_child(DEVICE_ACPI_HANDLE(ap->host->dev), adr);
 	} else
-		return acpi_get_child(ap_acpi_handle(ap), dev->devno);
-}
-
-/**
- * ata_acpi_associate_sata_port - associate SATA port with ACPI objects
- * @ap: target SATA port
- *
- * Look up ACPI objects associated with @ap and initialize acpi_handle
- * fields of @ap, the port and devices accordingly.
- *
- * LOCKING:
- * EH context.
- *
- * RETURNS:
- * 0 on success, -errno on failure.
- */
-void ata_acpi_associate_sata_port(struct ata_port *ap)
-{
-	WARN_ON(!(ap->flags & ATA_FLAG_ACPI_SATA));
-
-	if (!sata_pmp_attached(ap)) {
-		u64 adr = SATA_ADR(ap->port_no, NO_PORT_MULT);
-
-		ap->link.device->acpi_handle =
-			acpi_get_child(ap->host->acpi_handle, adr);
-	} else {
-		struct ata_link *link;
-
-		ap->link.device->acpi_handle = NULL;
-
-		ata_for_each_link(link, ap, EDGE) {
-			u64 adr = SATA_ADR(ap->port_no, link->pmp);
-
-			link->device->acpi_handle =
-				acpi_get_child(ap->host->acpi_handle, adr);
-		}
-	}
-}
-
-static void ata_acpi_associate_ide_port(struct ata_port *ap)
-{
-	int max_devices, i;
-
-	ap->acpi_handle = acpi_get_child(ap->host->acpi_handle, ap->port_no);
-	if (!ap->acpi_handle)
-		return;
-
-	max_devices = 1;
-	if (ap->flags & ATA_FLAG_SLAVE_POSS)
-		max_devices++;
-
-	for (i = 0; i < max_devices; i++) {
-		struct ata_device *dev = &ap->link.device[i];
-
-		dev->acpi_handle = acpi_get_child(ap->acpi_handle, i);
-	}
-
-	if (ata_acpi_gtm(ap, &ap->__acpi_init_gtm) == 0)
-		ap->pflags |= ATA_PFLAG_INIT_GTM_VALID;
+		return acpi_get_child(ata_ap_acpi_handle(ap), dev->devno);
 }
+EXPORT_SYMBOL(ata_dev_acpi_handle);
 
 /* @ap and @dev are the same as ata_acpi_handle_hotplug() */
 static void ata_acpi_detach_device(struct ata_port *ap, struct ata_device *dev)
@@ -251,56 +209,6 @@ static const struct acpi_dock_ops ata_acpi_ap_dock_ops = {
 };
 
 /**
- * ata_acpi_associate - associate ATA host with ACPI objects
- * @host: target ATA host
- *
- * Look up ACPI objects associated with @host and initialize
- * acpi_handle fields of @host, its ports and devices accordingly.
- *
- * LOCKING:
- * EH context.
- *
- * RETURNS:
- * 0 on success, -errno on failure.
- */
-void ata_acpi_associate(struct ata_host *host)
-{
-	int i, j;
-
-	if (!is_pci_dev(host->dev) || libata_noacpi)
-		return;
-
-	host->acpi_handle = DEVICE_ACPI_HANDLE(host->dev);
-	if (!host->acpi_handle)
-		return;
-
-	for (i = 0; i < host->n_ports; i++) {
-		struct ata_port *ap = host->ports[i];
-
-		if (host->ports[0]->flags & ATA_FLAG_ACPI_SATA)
-			ata_acpi_associate_sata_port(ap);
-		else
-			ata_acpi_associate_ide_port(ap);
-
-		if (ap->acpi_handle) {
-			/* we might be on a docking station */
-			register_hotplug_dock_device(ap->acpi_handle,
-					     &ata_acpi_ap_dock_ops, ap);
-		}
-
-		for (j = 0; j < ata_link_max_devices(&ap->link); j++) {
-			struct ata_device *dev = &ap->link.device[j];
-
-			if (dev->acpi_handle) {
-				/* we might be on a docking station */
-				register_hotplug_dock_device(dev->acpi_handle,
-					     &ata_acpi_dev_dock_ops, dev);
-			}
-		}
-	}
-}
-
-/**
  * ata_acpi_dissociate - dissociate ATA host from ACPI objects
  * @host: target ATA host
  *
@@ -321,7 +229,7 @@ void ata_acpi_dissociate(struct ata_host *host)
 		struct ata_port *ap = host->ports[i];
 		const struct ata_acpi_gtm *gtm = ata_acpi_init_gtm(ap);
 
-		if (ap->acpi_handle && gtm)
+		if (ata_ap_acpi_handle(ap) && gtm)
 			ata_acpi_stm(ap, gtm);
 	}
 }
@@ -346,7 +254,8 @@ int ata_acpi_gtm(struct ata_port *ap, struct ata_acpi_gtm *gtm)
 	acpi_status status;
 	int rc = 0;
 
-	status = acpi_evaluate_object(ap->acpi_handle, "_GTM", NULL, &output);
+	status = acpi_evaluate_object(ata_ap_acpi_handle(ap), "_GTM", NULL,
+				      &output);
 
 	rc = -ENOENT;
 	if (status == AE_NOT_FOUND)
@@ -416,7 +325,8 @@ int ata_acpi_stm(struct ata_port *ap, const struct ata_acpi_gtm *stm)
 	input.count = 3;
 	input.pointer = in_params;
 
-	status = acpi_evaluate_object(ap->acpi_handle, "_STM", &input, NULL);
+	status = acpi_evaluate_object(ata_ap_acpi_handle(ap), "_STM", &input,
+				      NULL);
 
 	if (status == AE_NOT_FOUND)
 		return -ENOENT;
@@ -473,7 +383,8 @@ static int ata_dev_get_GTF(struct ata_device *dev, struct ata_acpi_gtf **gtf)
 			    __func__, ap->port_no);
 
 	/* _GTF has no input parameters */
-	status = acpi_evaluate_object(dev->acpi_handle, "_GTF", NULL, &output);
+	status = acpi_evaluate_object(ata_dev_acpi_handle(dev), "_GTF", NULL,
+				      &output);
 	out_obj = dev->gtf_cache = output.pointer;
 
 	if (ACPI_FAILURE(status)) {
@@ -839,7 +750,8 @@ static int ata_acpi_push_id(struct ata_device *dev)
 
 	/* It's OK for _SDD to be missing too. */
 	swap_buf_le16(dev->id, ATA_ID_WORDS);
-	status = acpi_evaluate_object(dev->acpi_handle, "_SDD", &input, NULL);
+	status = acpi_evaluate_object(ata_dev_acpi_handle(dev), "_SDD", &input,
+				      NULL);
 	swap_buf_le16(dev->id, ATA_ID_WORDS);
 
 	if (status == AE_NOT_FOUND)
@@ -889,7 +801,7 @@ void ata_acpi_on_resume(struct ata_port *ap)
 	const struct ata_acpi_gtm *gtm = ata_acpi_init_gtm(ap);
 	struct ata_device *dev;
 
-	if (ap->acpi_handle && gtm) {
+	if (ata_ap_acpi_handle(ap) && gtm) {
 		/* _GTM valid */
 
 		/* restore timing parameters */
@@ -930,22 +842,22 @@ void ata_acpi_set_state(struct ata_port *ap, pm_message_t state)
 {
 	struct ata_device *dev;
 
-	if (!ap->acpi_handle || (ap->flags & ATA_FLAG_ACPI_SATA))
+	if (!ata_ap_acpi_handle(ap) || (ap->flags & ATA_FLAG_ACPI_SATA))
 		return;
 
 	/* channel first and then drives for power on and vica versa
 	   for power off */
 	if (state.event == PM_EVENT_ON)
-		acpi_bus_set_power(ap->acpi_handle, ACPI_STATE_D0);
+		acpi_bus_set_power(ata_ap_acpi_handle(ap), ACPI_STATE_D0);
 
 	ata_for_each_dev(dev, &ap->link, ENABLED) {
-		if (dev->acpi_handle)
-			acpi_bus_set_power(dev->acpi_handle,
+		if (ata_dev_acpi_handle(dev))
+			acpi_bus_set_power(ata_dev_acpi_handle(dev),
 				state.event == PM_EVENT_ON ?
 					ACPI_STATE_D0 : ACPI_STATE_D3);
 	}
 	if (state.event != PM_EVENT_ON)
-		acpi_bus_set_power(ap->acpi_handle, ACPI_STATE_D3);
+		acpi_bus_set_power(ata_ap_acpi_handle(ap), ACPI_STATE_D3);
 }
 
 /**
@@ -970,7 +882,7 @@ int ata_acpi_on_devcfg(struct ata_device *dev)
 	int nr_executed = 0;
 	int rc;
 
-	if (!dev->acpi_handle)
+	if (!ata_dev_acpi_handle(dev))
 		return 0;
 
 	/* do we need to do _GTF? */
@@ -1016,7 +928,6 @@ int ata_acpi_on_devcfg(struct ata_device *dev)
 	}
 
 	ata_dev_warn(dev, "ACPI: failed the second time, disabled\n");
-	dev->acpi_handle = NULL;
 
 	/* We can safely continue if no _GTF command has been executed
 	 * and port is not frozen.
@@ -1086,7 +997,7 @@ static int ata_acpi_bind_device(struct device *dev, int channel, int id,
 	else
 		ata_dev = &ap->link.device[id];
 
-	*handle = dev_acpi_handle(ata_dev);
+	*handle = ata_dev_acpi_handle(ata_dev);
 
 	if (!*handle)
 		return -ENODEV;
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
index 8908f9f..3aef6da 100644
--- a/drivers/ata/libata-core.c
+++ b/drivers/ata/libata-core.c
@@ -6044,9 +6044,6 @@ int ata_host_register(struct ata_host *host, struct scsi_host_template *sht)
 	if (rc)
 		goto err_tadd;
 
-	/* associate with ACPI nodes */
-	ata_acpi_associate(host);
-
 	/* set cable, sata_spd_limit and report */
 	for (i = 0; i < host->n_ports; i++) {
 		struct ata_port *ap = host->ports[i];
diff --git a/drivers/ata/libata-pmp.c b/drivers/ata/libata-pmp.c
index 21b80c5..61c59ee 100644
--- a/drivers/ata/libata-pmp.c
+++ b/drivers/ata/libata-pmp.c
@@ -529,8 +529,6 @@ int sata_pmp_attach(struct ata_device *dev)
 	ata_for_each_link(tlink, ap, EDGE)
 		sata_link_init_spd(tlink);
 
-	ata_acpi_associate_sata_port(ap);
-
 	return 0;
 
  fail:
@@ -570,8 +568,6 @@ static void sata_pmp_detach(struct ata_device *dev)
 	ap->nr_pmp_links = 0;
 	link->pmp = 0;
 	spin_unlock_irqrestore(ap->lock, flags);
-
-	ata_acpi_associate_sata_port(ap);
 }
 
 /**
diff --git a/drivers/ata/libata.h b/drivers/ata/libata.h
index 3df3362..6aba606 100644
--- a/drivers/ata/libata.h
+++ b/drivers/ata/libata.h
@@ -110,9 +110,6 @@ extern void __ata_port_probe(struct ata_port *ap);
 /* libata-acpi.c */
 #ifdef CONFIG_ATA_ACPI
 extern unsigned int ata_acpi_gtf_filter;
-
-extern void ata_acpi_associate_sata_port(struct ata_port *ap);
-extern void ata_acpi_associate(struct ata_host *host);
 extern void ata_acpi_dissociate(struct ata_host *host);
 extern int ata_acpi_on_suspend(struct ata_port *ap);
 extern void ata_acpi_on_resume(struct ata_port *ap);
@@ -122,8 +119,6 @@ extern void ata_acpi_set_state(struct ata_port *ap, pm_message_t state);
 extern int ata_acpi_register(void);
 extern void ata_acpi_unregister(void);
 #else
-static inline void ata_acpi_associate_sata_port(struct ata_port *ap) { }
-static inline void ata_acpi_associate(struct ata_host *host) { }
 static inline void ata_acpi_dissociate(struct ata_host *host) { }
 static inline int ata_acpi_on_suspend(struct ata_port *ap) { return 0; }
 static inline void ata_acpi_on_resume(struct ata_port *ap) { }
diff --git a/drivers/ata/pata_acpi.c b/drivers/ata/pata_acpi.c
index 54145ed..b63ca3b 100644
--- a/drivers/ata/pata_acpi.c
+++ b/drivers/ata/pata_acpi.c
@@ -39,7 +39,7 @@ static int pacpi_pre_reset(struct ata_link *link, unsigned long deadline)
 {
 	struct ata_port *ap = link->ap;
 	struct pata_acpi *acpi = ap->private_data;
-	if (ap->acpi_handle == NULL || ata_acpi_gtm(ap, &acpi->gtm) < 0)
+	if (ata_ap_acpi_handle(ap) == NULL || ata_acpi_gtm(ap, &acpi->gtm) < 0)
 		return -ENODEV;
 
 	return ata_sff_prereset(link, deadline);
@@ -195,7 +195,7 @@ static int pacpi_port_start(struct ata_port *ap)
 	struct pci_dev *pdev = to_pci_dev(ap->host->dev);
 	struct pata_acpi *acpi;
 
-	if (ap->acpi_handle == NULL)
+	if (ata_ap_acpi_handle(ap) == NULL)
 		return -ENODEV;
 
 	acpi = ap->private_data = devm_kzalloc(&pdev->dev, sizeof(struct pata_acpi), GFP_KERNEL);
diff --git a/include/linux/libata.h b/include/linux/libata.h
index e926df7..61e36ce 100644
--- a/include/linux/libata.h
+++ b/include/linux/libata.h
@@ -544,9 +544,6 @@ struct ata_host {
 	struct mutex		eh_mutex;
 	struct task_struct	*eh_owner;
 
-#ifdef CONFIG_ATA_ACPI
-	acpi_handle		acpi_handle;
-#endif
 	struct ata_port		*simplex_claimed;	/* channel owning the DMA */
 	struct ata_port		*ports[0];
 };
@@ -614,7 +611,6 @@ struct ata_device {
 	struct scsi_device	*sdev;		/* attached SCSI device */
 	void			*private_data;
 #ifdef CONFIG_ATA_ACPI
-	acpi_handle		acpi_handle;
 	union acpi_object	*gtf_cache;
 	unsigned int		gtf_filter;
 #endif
@@ -796,7 +792,6 @@ struct ata_port {
 	void			*private_data;
 
 #ifdef CONFIG_ATA_ACPI
-	acpi_handle		acpi_handle;
 	struct ata_acpi_gtm	__acpi_init_gtm; /* use ata_acpi_init_gtm() */
 #endif
 	/* owned by EH */
@@ -1113,6 +1108,8 @@ int ata_acpi_stm(struct ata_port *ap, const struct ata_acpi_gtm *stm);
 int ata_acpi_gtm(struct ata_port *ap, struct ata_acpi_gtm *stm);
 unsigned long ata_acpi_gtm_xfermask(struct ata_device *dev,
 				    const struct ata_acpi_gtm *gtm);
+acpi_handle ata_ap_acpi_handle(struct ata_port *ap);
+acpi_handle ata_dev_acpi_handle(struct ata_device *dev);
 int ata_acpi_cbl_80wire(struct ata_port *ap, const struct ata_acpi_gtm *gtm);
 #else
 static inline const struct ata_acpi_gtm *ata_acpi_init_gtm(struct ata_port *ap)
-- 
1.7.2.5


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

* [PATCH v4 04/13] libata: use correct PCI devices
  2012-05-28  5:08 [PATCH v4 0/13] SATA ZPODD support Lin Ming
                   ` (2 preceding siblings ...)
  2012-05-28  5:08 ` [PATCH v4 03/13] libata: migrate ACPI code over to new bindings Lin Ming
@ 2012-05-28  5:08 ` Lin Ming
  2012-05-29 12:22   ` Sergei Shtylyov
  2012-05-28  5:08 ` [PATCH v4 05/13] libata-acpi: set acpi state for SATA port Lin Ming
                   ` (9 subsequent siblings)
  13 siblings, 1 reply; 27+ messages in thread
From: Lin Ming @ 2012-05-28  5:08 UTC (permalink / raw)
  To: Jeff Garzik, David Woodhouse, Aaron Lu, Holger Macht, Matthew Garrett
  Cc: linux-kernel, linux-pm, linux-scsi, linux-ide, linux-acpi

From: Holger Macht <holger@homac.de>

Commit 9a6d6a2ddabbd32c07f6a38b659e5f3db319fa5a made ata ports parent
devices of scsi hosts, so we need to go yet another level up to be able
to use the correct PCI devices.

Signed-off-by: Holger Macht <holger@homac.de>
Signed-off-by: Lin Ming <ming.m.lin@intel.com>
---
 drivers/ata/libata-acpi.c |    6 +++---
 1 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/ata/libata-acpi.c b/drivers/ata/libata-acpi.c
index 762e0c8..df4e21a 100644
--- a/drivers/ata/libata-acpi.c
+++ b/drivers/ata/libata-acpi.c
@@ -976,7 +976,7 @@ static int ata_acpi_bind_host(struct device *dev, int host, acpi_handle *handle)
 	if (ap->flags & ATA_FLAG_ACPI_SATA)
 		return -ENODEV;
 
-	*handle = acpi_get_child(DEVICE_ACPI_HANDLE(dev->parent), ap->port_no);
+	*handle = acpi_get_child(DEVICE_ACPI_HANDLE(dev->parent->parent), ap->port_no);
 
 	if (!*handle)
 		return -ENODEV;
@@ -1010,13 +1010,13 @@ static int ata_acpi_find_device(struct device *dev, acpi_handle *handle)
 	unsigned int host, channel, id, lun;
 
 	if (sscanf(dev_name(dev), "host%u", &host) == 1) {
-		if (!is_pci_ata(dev->parent))
+		if (!is_pci_ata(dev->parent->parent))
 			return -ENODEV;
 
 		return ata_acpi_bind_host(dev, host, handle);
 	} else if (sscanf(dev_name(dev), "%d:%d:%d:%d",
 			&host, &channel, &id, &lun) == 4) {
-		if (!is_pci_ata(dev->parent->parent->parent))
+		if (!is_pci_ata(dev->parent->parent->parent->parent))
 			return -ENODEV;
 
 		return ata_acpi_bind_device(dev, channel, id, handle);
-- 
1.7.2.5

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

* [PATCH v4 05/13] libata-acpi: set acpi state for SATA port
  2012-05-28  5:08 [PATCH v4 0/13] SATA ZPODD support Lin Ming
                   ` (3 preceding siblings ...)
  2012-05-28  5:08 ` [PATCH v4 04/13] libata: use correct PCI devices Lin Ming
@ 2012-05-28  5:08 ` Lin Ming
  2012-05-28  5:08 ` [PATCH v4 06/13] libata-acpi: add ata port runtime D3Cold support Lin Ming
                   ` (8 subsequent siblings)
  13 siblings, 0 replies; 27+ messages in thread
From: Lin Ming @ 2012-05-28  5:08 UTC (permalink / raw)
  To: Jeff Garzik, David Woodhouse, Aaron Lu, Holger Macht, Matthew Garrett
  Cc: linux-kernel, linux-pm, linux-scsi, linux-ide, linux-acpi

Currently, ata_acpi_set_state() only sets acpi sate for IDE port.
Remove this limitation.

Acked-by: Aaron Lu <aaron.lu@amd.com>
Signed-off-by: Lin Ming <ming.m.lin@intel.com>
---
 drivers/ata/libata-acpi.c |   21 ++++++++++++---------
 1 files changed, 12 insertions(+), 9 deletions(-)

diff --git a/drivers/ata/libata-acpi.c b/drivers/ata/libata-acpi.c
index df4e21a..bf14010 100644
--- a/drivers/ata/libata-acpi.c
+++ b/drivers/ata/libata-acpi.c
@@ -841,23 +841,26 @@ void ata_acpi_on_resume(struct ata_port *ap)
 void ata_acpi_set_state(struct ata_port *ap, pm_message_t state)
 {
 	struct ata_device *dev;
-
-	if (!ata_ap_acpi_handle(ap) || (ap->flags & ATA_FLAG_ACPI_SATA))
-		return;
+	acpi_handle handle;
+	int acpi_state;
 
 	/* channel first and then drives for power on and vica versa
 	   for power off */
-	if (state.event == PM_EVENT_ON)
-		acpi_bus_set_power(ata_ap_acpi_handle(ap), ACPI_STATE_D0);
+	handle = ata_ap_acpi_handle(ap);
+	if (handle && state.event == PM_EVENT_ON)
+		acpi_bus_set_power(handle, ACPI_STATE_D0);
 
 	ata_for_each_dev(dev, &ap->link, ENABLED) {
-		if (ata_dev_acpi_handle(dev))
-			acpi_bus_set_power(ata_dev_acpi_handle(dev),
+		handle = ata_dev_acpi_handle(dev);
+		if (handle)
+			acpi_bus_set_power(handle,
 				state.event == PM_EVENT_ON ?
 					ACPI_STATE_D0 : ACPI_STATE_D3);
 	}
-	if (state.event != PM_EVENT_ON)
-		acpi_bus_set_power(ata_ap_acpi_handle(ap), ACPI_STATE_D3);
+
+	handle = ata_ap_acpi_handle(ap);
+	if (handle && state.event != PM_EVENT_ON)
+		acpi_bus_set_power(handle, ACPI_STATE_D3);
 }
 
 /**
-- 
1.7.2.5

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

* [PATCH v4 06/13] libata-acpi: add ata port runtime D3Cold support
  2012-05-28  5:08 [PATCH v4 0/13] SATA ZPODD support Lin Ming
                   ` (4 preceding siblings ...)
  2012-05-28  5:08 ` [PATCH v4 05/13] libata-acpi: set acpi state for SATA port Lin Ming
@ 2012-05-28  5:08 ` Lin Ming
  2012-05-28  5:08 ` [PATCH v4 07/13] libata-acpi: register/unregister device to/from power resource Lin Ming
                   ` (7 subsequent siblings)
  13 siblings, 0 replies; 27+ messages in thread
From: Lin Ming @ 2012-05-28  5:08 UTC (permalink / raw)
  To: Jeff Garzik, David Woodhouse, Aaron Lu, Holger Macht, Matthew Garrett
  Cc: linux-kernel, linux-pm, linux-scsi, linux-ide, linux-acpi

ATA port may support runtime D3Cold state, for example, Zero-power ODD case.
This patch adds wakeup notifier and enable/disable run_wake during
supend/resume.

Signed-off-by: Lin Ming <ming.m.lin@intel.com>
---
 drivers/ata/libata-acpi.c |   77 ++++++++++++++++++++++++++++++++++++++++++--
 drivers/ata/libata-scsi.c |    3 ++
 drivers/ata/libata.h      |    4 ++
 3 files changed, 80 insertions(+), 4 deletions(-)

diff --git a/drivers/ata/libata-acpi.c b/drivers/ata/libata-acpi.c
index bf14010..23c0d3b 100644
--- a/drivers/ata/libata-acpi.c
+++ b/drivers/ata/libata-acpi.c
@@ -16,6 +16,7 @@
 #include <linux/libata.h>
 #include <linux/pci.h>
 #include <linux/slab.h>
+#include <linux/pm_runtime.h>
 #include <scsi/scsi_device.h>
 #include "libata.h"
 
@@ -852,10 +853,23 @@ void ata_acpi_set_state(struct ata_port *ap, pm_message_t state)
 
 	ata_for_each_dev(dev, &ap->link, ENABLED) {
 		handle = ata_dev_acpi_handle(dev);
-		if (handle)
-			acpi_bus_set_power(handle,
-				state.event == PM_EVENT_ON ?
-					ACPI_STATE_D0 : ACPI_STATE_D3);
+		if (!handle)
+			continue;
+
+		if (state.event != PM_EVENT_ON) {
+			acpi_state = acpi_pm_device_sleep_state(
+				&dev->sdev->sdev_gendev, NULL);
+			if (acpi_state > 0)
+				acpi_bus_set_power(handle, acpi_state);
+			/* TBD: need to check if it's runtime pm request */
+			acpi_pm_device_run_wake(
+				&dev->sdev->sdev_gendev, true);
+		} else {
+			/* Ditto */
+			acpi_pm_device_run_wake(
+				&dev->sdev->sdev_gendev, false);
+			acpi_bus_set_power(handle, ACPI_STATE_D0);
+		}
 	}
 
 	handle = ata_ap_acpi_handle(ap);
@@ -955,6 +969,61 @@ void ata_acpi_on_disable(struct ata_device *dev)
 	ata_acpi_clear_gtf(dev);
 }
 
+static void ata_acpi_wake_dev(acpi_handle handle, u32 event, void *context)
+{
+	struct ata_device *ata_dev = context;
+
+	if (event == ACPI_NOTIFY_DEVICE_WAKE && ata_dev &&
+			pm_runtime_suspended(&ata_dev->sdev->sdev_gendev))
+		scsi_autopm_get_device(ata_dev->sdev);
+}
+
+static void ata_acpi_add_pm_notifier(struct ata_device *dev)
+{
+	struct acpi_device *acpi_dev;
+	acpi_handle handle;
+	acpi_status status;
+
+	handle = ata_dev_acpi_handle(dev);
+	if (!handle)
+		return;
+
+	status = acpi_bus_get_device(handle, &acpi_dev);
+	if (ACPI_SUCCESS(status)) {
+		acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY,
+			ata_acpi_wake_dev, dev);
+		device_set_run_wake(&dev->sdev->sdev_gendev, true);
+	}
+}
+
+static void ata_acpi_remove_pm_notifier(struct ata_device *dev)
+{
+	struct acpi_device *acpi_dev;
+	acpi_handle handle;
+	acpi_status status;
+
+	handle = ata_dev_acpi_handle(dev);
+	if (!handle)
+		return;
+
+	status = acpi_bus_get_device(handle, &acpi_dev);
+	if (ACPI_SUCCESS(status)) {
+		device_set_run_wake(&dev->sdev->sdev_gendev, false);
+		acpi_remove_notify_handler(handle, ACPI_SYSTEM_NOTIFY,
+			ata_acpi_wake_dev);
+	}
+}
+
+void ata_acpi_bind(struct ata_device *dev)
+{
+	ata_acpi_add_pm_notifier(dev);
+}
+
+void ata_acpi_unbind(struct ata_device *dev)
+{
+	ata_acpi_remove_pm_notifier(dev);
+}
+
 static int is_pci_ata(struct device *dev)
 {
 	struct pci_dev *pdev;
diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c
index 2222635..8ec81ca 100644
--- a/drivers/ata/libata-scsi.c
+++ b/drivers/ata/libata-scsi.c
@@ -3445,6 +3445,7 @@ void ata_scsi_scan_host(struct ata_port *ap, int sync)
 			if (!IS_ERR(sdev)) {
 				dev->sdev = sdev;
 				scsi_device_put(sdev);
+				ata_acpi_bind(dev);
 			} else {
 				dev->sdev = NULL;
 			}
@@ -3541,6 +3542,8 @@ static void ata_scsi_remove_dev(struct ata_device *dev)
 	mutex_lock(&ap->scsi_host->scan_mutex);
 	spin_lock_irqsave(ap->lock, flags);
 
+	ata_acpi_unbind(dev);
+
 	/* clearing dev->sdev is protected by host lock */
 	sdev = dev->sdev;
 	dev->sdev = NULL;
diff --git a/drivers/ata/libata.h b/drivers/ata/libata.h
index 6aba606..b0ba924 100644
--- a/drivers/ata/libata.h
+++ b/drivers/ata/libata.h
@@ -118,6 +118,8 @@ extern void ata_acpi_on_disable(struct ata_device *dev);
 extern void ata_acpi_set_state(struct ata_port *ap, pm_message_t state);
 extern int ata_acpi_register(void);
 extern void ata_acpi_unregister(void);
+extern void ata_acpi_bind(struct ata_device *dev);
+extern void ata_acpi_unbind(struct ata_device *dev);
 #else
 static inline void ata_acpi_dissociate(struct ata_host *host) { }
 static inline int ata_acpi_on_suspend(struct ata_port *ap) { return 0; }
@@ -128,6 +130,8 @@ static inline void ata_acpi_set_state(struct ata_port *ap,
 				      pm_message_t state) { }
 static inline int ata_acpi_register(void) { return 0; }
 static void ata_acpi_unregister(void) { }
+static void ata_acpi_bind(struct ata_device *dev) { }
+static void ata_acpi_unbind(struct ata_device *dev) { }
 #endif
 
 /* libata-scsi.c */
-- 
1.7.2.5

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

* [PATCH v4 07/13] libata-acpi: register/unregister device to/from power resource
  2012-05-28  5:08 [PATCH v4 0/13] SATA ZPODD support Lin Ming
                   ` (5 preceding siblings ...)
  2012-05-28  5:08 ` [PATCH v4 06/13] libata-acpi: add ata port runtime D3Cold support Lin Ming
@ 2012-05-28  5:08 ` Lin Ming
  2012-05-28  5:08 ` [PATCH v4 08/13] libata: detect Device Attention support Lin Ming
                   ` (6 subsequent siblings)
  13 siblings, 0 replies; 27+ messages in thread
From: Lin Ming @ 2012-05-28  5:08 UTC (permalink / raw)
  To: Jeff Garzik, David Woodhouse, Aaron Lu, Holger Macht, Matthew Garrett
  Cc: linux-kernel, linux-pm, linux-scsi, linux-ide, linux-acpi

Signed-off-by: Lin Ming <ming.m.lin@intel.com>
---
 drivers/acpi/power.c      |    2 ++
 drivers/ata/libata-acpi.c |   32 ++++++++++++++++++++++++++++++++
 2 files changed, 34 insertions(+), 0 deletions(-)

diff --git a/drivers/acpi/power.c b/drivers/acpi/power.c
index 0500f71..d21d1a1 100644
--- a/drivers/acpi/power.c
+++ b/drivers/acpi/power.c
@@ -390,6 +390,7 @@ void acpi_power_resource_unregister_device(struct device *dev, acpi_handle handl
 		__acpi_power_resource_unregister_device(dev,
 			list->handles[i]);
 }
+EXPORT_SYMBOL_GPL(acpi_power_resource_unregister_device);
 
 static int __acpi_power_resource_register_device(
 	struct acpi_power_managed_device *powered_device, acpi_handle handle)
@@ -460,6 +461,7 @@ int acpi_power_resource_register_device(struct device *dev, acpi_handle handle)
 	printk(KERN_WARNING PREFIX "Invalid Power Resource to register!");
 	return -ENODEV;
 }
+EXPORT_SYMBOL_GPL(acpi_power_resource_register_device);
 
 /**
  * acpi_device_sleep_wake - execute _DSW (Device Sleep Wake) or (deprecated in
diff --git a/drivers/ata/libata-acpi.c b/drivers/ata/libata-acpi.c
index 23c0d3b..5431f1d 100644
--- a/drivers/ata/libata-acpi.c
+++ b/drivers/ata/libata-acpi.c
@@ -1014,14 +1014,46 @@ static void ata_acpi_remove_pm_notifier(struct ata_device *dev)
 	}
 }
 
+static void ata_acpi_register_power_resource(struct ata_device *dev)
+{
+	struct scsi_device *sdev = dev->sdev;
+	acpi_handle handle;
+	struct device *device;
+
+	handle = ata_dev_acpi_handle(dev);
+	if (!handle)
+		return;
+
+	device = &sdev->sdev_gendev;
+
+	acpi_power_resource_register_device(device, handle);
+}
+
+static void ata_acpi_unregister_power_resource(struct ata_device *dev)
+{
+	struct scsi_device *sdev = dev->sdev;
+	acpi_handle handle;
+	struct device *device;
+
+	handle = ata_dev_acpi_handle(dev);
+	if (!handle)
+		return;
+
+	device = &sdev->sdev_gendev;
+
+	acpi_power_resource_unregister_device(device, handle);
+}
+
 void ata_acpi_bind(struct ata_device *dev)
 {
 	ata_acpi_add_pm_notifier(dev);
+	ata_acpi_register_power_resource(dev);
 }
 
 void ata_acpi_unbind(struct ata_device *dev)
 {
 	ata_acpi_remove_pm_notifier(dev);
+	ata_acpi_unregister_power_resource(dev);
 }
 
 static int is_pci_ata(struct device *dev)
-- 
1.7.2.5

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

* [PATCH v4 08/13] libata: detect Device Attention support
  2012-05-28  5:08 [PATCH v4 0/13] SATA ZPODD support Lin Ming
                   ` (6 preceding siblings ...)
  2012-05-28  5:08 ` [PATCH v4 07/13] libata-acpi: register/unregister device to/from power resource Lin Ming
@ 2012-05-28  5:08 ` Lin Ming
  2012-05-28  5:08 ` [PATCH v4 09/13] libata: tell scsi layer device supports runtime power off Lin Ming
                   ` (5 subsequent siblings)
  13 siblings, 0 replies; 27+ messages in thread
From: Lin Ming @ 2012-05-28  5:08 UTC (permalink / raw)
  To: Jeff Garzik, David Woodhouse, Aaron Lu, Holger Macht, Matthew Garrett
  Cc: linux-kernel, linux-pm, linux-scsi, linux-ide, linux-acpi

Add a new flag ATA_DFLAG_DA to indicate that device supports "Device
Attention".

Acked-by: Aaron Lu <aaron.lu@amd.com>
Signed-off-by: Lin Ming <ming.m.lin@intel.com>
---
 drivers/ata/libata-core.c |    3 +++
 include/linux/ata.h       |    1 +
 include/linux/libata.h    |    2 ++
 3 files changed, 6 insertions(+), 0 deletions(-)

diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
index 3aef6da..f08d6cb 100644
--- a/drivers/ata/libata-core.c
+++ b/drivers/ata/libata-core.c
@@ -2368,6 +2368,9 @@ int ata_dev_configure(struct ata_device *dev)
 			dma_dir_string = ", DMADIR";
 		}
 
+		if (ata_id_has_da(dev->id))
+			dev->flags |= ATA_DFLAG_DA;
+
 		/* print device info to dmesg */
 		if (ata_msg_drv(ap) && print_info)
 			ata_dev_info(dev,
diff --git a/include/linux/ata.h b/include/linux/ata.h
index 32df2b6..5713d3a 100644
--- a/include/linux/ata.h
+++ b/include/linux/ata.h
@@ -578,6 +578,7 @@ static inline int ata_is_data(u8 prot)
 	  ((u64) (id)[(n) + 0]) )
 
 #define ata_id_cdb_intr(id)	(((id)[ATA_ID_CONFIG] & 0x60) == 0x20)
+#define ata_id_has_da(id)	((id)[77] & (1 << 4))
 
 static inline bool ata_id_has_hipm(const u16 *id)
 {
diff --git a/include/linux/libata.h b/include/linux/libata.h
index 61e36ce..b61922c 100644
--- a/include/linux/libata.h
+++ b/include/linux/libata.h
@@ -161,6 +161,8 @@ enum {
 	ATA_DFLAG_DETACH	= (1 << 24),
 	ATA_DFLAG_DETACHED	= (1 << 25),
 
+	ATA_DFLAG_DA		= (1 << 26), /* device supports Device Attention */
+
 	ATA_DEV_UNKNOWN		= 0,	/* unknown device */
 	ATA_DEV_ATA		= 1,	/* ATA device */
 	ATA_DEV_ATA_UNSUP	= 2,	/* ATA device (unsupported) */
-- 
1.7.2.5

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

* [PATCH v4 09/13] libata: tell scsi layer device supports runtime power off
  2012-05-28  5:08 [PATCH v4 0/13] SATA ZPODD support Lin Ming
                   ` (7 preceding siblings ...)
  2012-05-28  5:08 ` [PATCH v4 08/13] libata: detect Device Attention support Lin Ming
@ 2012-05-28  5:08 ` Lin Ming
  2012-05-28  5:08 ` [PATCH v4 10/13] [SCSI] pm: resume device if suspend failed Lin Ming
                   ` (4 subsequent siblings)
  13 siblings, 0 replies; 27+ messages in thread
From: Lin Ming @ 2012-05-28  5:08 UTC (permalink / raw)
  To: Jeff Garzik, David Woodhouse, Aaron Lu, Holger Macht, Matthew Garrett
  Cc: linux-kernel, linux-pm, linux-scsi, linux-ide, linux-acpi

From: Aaron Lu <aaron.lu@amd.com>

If ATA device supports "Device Attention", then tell scsi layer that
the device supports runtime power off.

Signed-off-by: Aaron Lu <aaron.lu@amd.com>
Signed-off-by: Lin Ming <ming.m.lin@intel.com>
---
 drivers/ata/libata-acpi.c  |   32 ++++++++++++++++++++++++++++----
 include/scsi/scsi_device.h |    1 +
 2 files changed, 29 insertions(+), 4 deletions(-)

diff --git a/drivers/ata/libata-acpi.c b/drivers/ata/libata-acpi.c
index 5431f1d..f0fa115 100644
--- a/drivers/ata/libata-acpi.c
+++ b/drivers/ata/libata-acpi.c
@@ -989,7 +989,10 @@ static void ata_acpi_add_pm_notifier(struct ata_device *dev)
 		return;
 
 	status = acpi_bus_get_device(handle, &acpi_dev);
-	if (ACPI_SUCCESS(status)) {
+	if (ACPI_FAILURE(status))
+		return;
+
+	if (dev->sdev->can_power_off) {
 		acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY,
 			ata_acpi_wake_dev, dev);
 		device_set_run_wake(&dev->sdev->sdev_gendev, true);
@@ -1007,7 +1010,10 @@ static void ata_acpi_remove_pm_notifier(struct ata_device *dev)
 		return;
 
 	status = acpi_bus_get_device(handle, &acpi_dev);
-	if (ACPI_SUCCESS(status)) {
+	if (ACPI_FAILURE(status))
+		return;
+
+	if (dev->sdev->can_power_off) {
 		device_set_run_wake(&dev->sdev->sdev_gendev, false);
 		acpi_remove_notify_handler(handle, ACPI_SYSTEM_NOTIFY,
 			ata_acpi_wake_dev);
@@ -1091,10 +1097,13 @@ static int ata_acpi_bind_host(struct device *dev, int host, acpi_handle *handle)
 static int ata_acpi_bind_device(struct device *dev, int channel, int id,
 				acpi_handle *handle)
 {
-	struct device *host = dev->parent->parent;
-	struct Scsi_Host *shost = dev_to_shost(host);
+	struct scsi_device *sdev = to_scsi_device(dev);
+	struct Scsi_Host *shost = sdev->host;
 	struct ata_port *ap = ata_shost_to_port(shost);
 	struct ata_device *ata_dev;
+	acpi_status status;
+	struct acpi_device *acpi_dev;
+	struct acpi_device_power_state *states;
 
 	if (ap->flags & ATA_FLAG_ACPI_SATA)
 		ata_dev = &ap->link.device[channel];
@@ -1106,6 +1115,21 @@ static int ata_acpi_bind_device(struct device *dev, int channel, int id,
 	if (!*handle)
 		return -ENODEV;
 
+	status = acpi_bus_get_device(*handle, &acpi_dev);
+	if (ACPI_FAILURE(status))
+		return 0;
+
+	/*
+	 * If firmware has _PS3 or _PR3 for this device,
+	 * and this ata ODD device support device attention,
+	 * it means this device can be powered off
+	 */
+	states = acpi_dev->power.states;
+	if ((states[ACPI_STATE_D3_HOT].flags.valid ||
+			states[ACPI_STATE_D3_COLD].flags.explicit_set) &&
+			ata_dev->flags & ATA_DFLAG_DA)
+		sdev->can_power_off = 1;
+
 	return 0;
 }
 
diff --git a/include/scsi/scsi_device.h b/include/scsi/scsi_device.h
index 6efb2e1..1237fac 100644
--- a/include/scsi/scsi_device.h
+++ b/include/scsi/scsi_device.h
@@ -152,6 +152,7 @@ struct scsi_device {
 	unsigned no_read_disc_info:1;	/* Avoid READ_DISC_INFO cmds */
 	unsigned no_read_capacity_16:1; /* Avoid READ_CAPACITY_16 cmds */
 	unsigned is_visible:1;	/* is the device visible in sysfs */
+	unsigned can_power_off:1; /* Device supports runtime power off */
 
 	DECLARE_BITMAP(supported_events, SDEV_EVT_MAXBITS); /* supported events */
 	struct list_head event_list;	/* asserted events */
-- 
1.7.2.5

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

* [PATCH v4 10/13] [SCSI] pm: resume device if suspend failed
  2012-05-28  5:08 [PATCH v4 0/13] SATA ZPODD support Lin Ming
                   ` (8 preceding siblings ...)
  2012-05-28  5:08 ` [PATCH v4 09/13] libata: tell scsi layer device supports runtime power off Lin Ming
@ 2012-05-28  5:08 ` Lin Ming
  2012-05-28  5:08 ` [PATCH v4 11/13] [SCSI] sr: check support for device busy class events Lin Ming
                   ` (3 subsequent siblings)
  13 siblings, 0 replies; 27+ messages in thread
From: Lin Ming @ 2012-05-28  5:08 UTC (permalink / raw)
  To: Jeff Garzik, David Woodhouse, Aaron Lu, Holger Macht, Matthew Garrett
  Cc: linux-kernel, linux-pm, linux-scsi, linux-ide, linux-acpi

From: Aaron Lu <aaron.lu@amd.com>

V2: use scsi_device instead of device in scsi_device_resume

V1:
For scsi devices which use scsi bus runtime callback, runtime suspend
will call scsi_dev_type_suspend, and if the drv->suspend failed, the
device will still be in active state. But since scsi_device_quiesce is
called, the device will not be able to respond any more commands.
So add a check here to see if err occured, if so, bring the device back
to normal state with scsi_device_resume.

Signed-off-by: Aaron Lu <aaron.lu@amd.com>
Acked-by: Alan Stern <stern@rowland.harvard.edu>
---
 drivers/scsi/scsi_pm.c |    5 ++++-
 1 files changed, 4 insertions(+), 1 deletions(-)

diff --git a/drivers/scsi/scsi_pm.c b/drivers/scsi/scsi_pm.c
index c467064..a06dd56 100644
--- a/drivers/scsi/scsi_pm.c
+++ b/drivers/scsi/scsi_pm.c
@@ -24,8 +24,11 @@ static int scsi_dev_type_suspend(struct device *dev, pm_message_t msg)
 	err = scsi_device_quiesce(to_scsi_device(dev));
 	if (err == 0) {
 		drv = dev->driver;
-		if (drv && drv->suspend)
+		if (drv && drv->suspend) {
 			err = drv->suspend(dev, msg);
+			if (err)
+				scsi_device_resume(to_scsi_device(dev));
+		}
 	}
 	dev_dbg(dev, "scsi suspend: %d\n", err);
 	return err;
-- 
1.7.2.5

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

* [PATCH v4 11/13] [SCSI] sr: check support for device busy class events
  2012-05-28  5:08 [PATCH v4 0/13] SATA ZPODD support Lin Ming
                   ` (9 preceding siblings ...)
  2012-05-28  5:08 ` [PATCH v4 10/13] [SCSI] pm: resume device if suspend failed Lin Ming
@ 2012-05-28  5:08 ` Lin Ming
  2012-05-28  5:08 ` [PATCH v4 12/13] [SCSI] sr: support zero power ODD Lin Ming
                   ` (2 subsequent siblings)
  13 siblings, 0 replies; 27+ messages in thread
From: Lin Ming @ 2012-05-28  5:08 UTC (permalink / raw)
  To: Jeff Garzik, David Woodhouse, Aaron Lu, Holger Macht, Matthew Garrett
  Cc: linux-kernel, linux-pm, linux-scsi, linux-ide, linux-acpi

From: Aaron Lu <aaron.lu@amd.com>

Signed-off-by: Aaron Lu <aaron.lu@amd.com>
---
 drivers/scsi/sr.c     |   23 +++++++++++++++++++++++
 drivers/scsi/sr.h     |    1 +
 include/linux/cdrom.h |   43 +++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 67 insertions(+), 0 deletions(-)

diff --git a/drivers/scsi/sr.c b/drivers/scsi/sr.c
index 5fc97d2..abfefab 100644
--- a/drivers/scsi/sr.c
+++ b/drivers/scsi/sr.c
@@ -101,6 +101,7 @@ static DEFINE_MUTEX(sr_ref_mutex);
 static int sr_open(struct cdrom_device_info *, int);
 static void sr_release(struct cdrom_device_info *);
 
+static void check_dbml(struct scsi_cd *);
 static void get_sectorsize(struct scsi_cd *);
 static void get_capabilities(struct scsi_cd *);
 
@@ -728,6 +729,28 @@ static int sr_probe(struct device *dev)
 	return error;
 }
 
+static void check_dbml(struct scsi_cd *cd)
+{
+	struct packet_command cgc;
+	unsigned char buffer[16];
+	struct rm_feature_desc *rfd;
+
+	init_cdrom_command(&cgc, buffer, sizeof(buffer), CGC_DATA_READ);
+	cgc.cmd[0] = GPCMD_GET_CONFIGURATION;
+	cgc.cmd[3] = CDF_RM;
+	cgc.cmd[8] = sizeof(buffer);
+	cgc.quiet = 1;
+
+	if (cd->cdi.ops->generic_packet(&cd->cdi, &cgc))
+		return;
+
+	rfd = (struct rm_feature_desc *)&buffer[sizeof(struct feature_header)];
+	if (be16_to_cpu(rfd->feature_code) != CDF_RM)
+		return;
+
+	if (rfd->dbml)
+		cd->dbml = 1;
+}
 
 static void get_sectorsize(struct scsi_cd *cd)
 {
diff --git a/drivers/scsi/sr.h b/drivers/scsi/sr.h
index 37c8f6b..7cc40ad 100644
--- a/drivers/scsi/sr.h
+++ b/drivers/scsi/sr.h
@@ -41,6 +41,7 @@ typedef struct scsi_cd {
 	unsigned readcd_known:1;	/* drive supports READ_CD (0xbe) */
 	unsigned readcd_cdda:1;	/* reading audio data using READ_CD */
 	unsigned media_present:1;	/* media is present */
+	unsigned dbml:1;	/* generates device busy class events */
 
 	/* GET_EVENT spurious event handling, blk layer guarantees exclusion */
 	int tur_mismatch;		/* nr of get_event TUR mismatches */
diff --git a/include/linux/cdrom.h b/include/linux/cdrom.h
index dfd7f18..25f305c 100644
--- a/include/linux/cdrom.h
+++ b/include/linux/cdrom.h
@@ -727,6 +727,7 @@ struct request_sense {
 /*
  * feature profile
  */
+#define CDF_RM		0x0003	/* "Removeable Medium" */
 #define CDF_RWRT	0x0020	/* "Random Writable" */
 #define CDF_HWDM	0x0024	/* "Hardware Defect Management" */
 #define CDF_MRW 	0x0028
@@ -739,6 +740,48 @@ struct request_sense {
 #define CDM_MRW_BGFORMAT_ACTIVE		2
 #define CDM_MRW_BGFORMAT_COMPLETE	3
 
+/* Removable medium feature descriptor */
+struct rm_feature_desc {
+	__be16 feature_code;
+#if defined(__BIG_ENDIAN_BITFIELD)
+	__u8 reserved1		: 2;
+	__u8 feature_version	: 4;
+	__u8 persistent		: 1;
+	__u8 curr		: 1;
+#elif defined(__LITTLE_ENDIAN_BITFIELD)
+	__u8 curr		: 1;
+	__u8 persistent		: 1;
+	__u8 feature_version	: 4;
+	__u8 reserved1		: 2;
+#endif
+	__u8 add_len;
+#if defined(__BIG_ENDIAN_BITFIELD)
+	__u8 mech_type		: 3;
+	__u8 load		: 1;
+	__u8 eject		: 1;
+	__u8 pvnt_jmpr		: 1;
+	__u8 dbml		: 1;
+	__u8 lock		: 1;
+#elif defined(__LITTLE_ENDIAN_BITFIELD)
+	__u8 lock		: 1;
+	__u8 dbml		: 1;
+	__u8 pvnt_jmpr		: 1;
+	__u8 eject		: 1;
+	__u8 load		: 1;
+	__u8 mech_type		: 3;
+#endif
+	__u8 reserved2;
+	__u8 reserved3;
+	__u8 reserved4;
+};
+
+struct device_busy_event_desc {
+	__u8 device_busy_event	: 4;
+	__u8 reserved1		: 4;
+	__u8 device_busy_status;
+	__u8 time;
+};
+
 /*
  * mrw address spaces
  */
-- 
1.7.2.5

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

* [PATCH v4 12/13] [SCSI] sr: support zero power ODD
  2012-05-28  5:08 [PATCH v4 0/13] SATA ZPODD support Lin Ming
                   ` (10 preceding siblings ...)
  2012-05-28  5:08 ` [PATCH v4 11/13] [SCSI] sr: check support for device busy class events Lin Ming
@ 2012-05-28  5:08 ` Lin Ming
  2012-05-28  5:08 ` [PATCH v4 13/13] [SCSI] sr: make sure ODD is in resumed state in block ioctl Lin Ming
  2012-05-28  9:44 ` [PATCH v4 0/13] SATA ZPODD support Alan Cox
  13 siblings, 0 replies; 27+ messages in thread
From: Lin Ming @ 2012-05-28  5:08 UTC (permalink / raw)
  To: Jeff Garzik, David Woodhouse, Aaron Lu, Holger Macht, Matthew Garrett
  Cc: linux-kernel, linux-pm, linux-scsi, linux-ide, linux-acpi

From: Aaron Lu <aaron.lu@amd.com>

If there is no media inside the ODD and the ODD's tray is closed, it's
safe to omit power. When user ejects the tray by pressing the button or
inserts a disc into the slot, the ODD will gets resumed from acpi
notifier handler.

Signed-off-by: Aaron Lu <aaron.lu@amd.com>
Signed-off-by: Lin Ming <ming.m.lin@intel.com>
---
 drivers/ata/libata-acpi.c  |    4 +-
 drivers/scsi/sr.c          |  128 +++++++++++++++++++++++++++++++++++++++++++-
 drivers/scsi/sr.h          |    2 +
 include/scsi/scsi_device.h |    1 +
 4 files changed, 133 insertions(+), 2 deletions(-)

diff --git a/drivers/ata/libata-acpi.c b/drivers/ata/libata-acpi.c
index f0fa115..6de8f32 100644
--- a/drivers/ata/libata-acpi.c
+++ b/drivers/ata/libata-acpi.c
@@ -974,8 +974,10 @@ static void ata_acpi_wake_dev(acpi_handle handle, u32 event, void *context)
 	struct ata_device *ata_dev = context;
 
 	if (event == ACPI_NOTIFY_DEVICE_WAKE && ata_dev &&
-			pm_runtime_suspended(&ata_dev->sdev->sdev_gendev))
+			pm_runtime_suspended(&ata_dev->sdev->sdev_gendev)) {
+		ata_dev->sdev->wakeup_by_user = 1;
 		scsi_autopm_get_device(ata_dev->sdev);
+	}
 }
 
 static void ata_acpi_add_pm_notifier(struct ata_device *dev)
diff --git a/drivers/scsi/sr.c b/drivers/scsi/sr.c
index abfefab..72488c2 100644
--- a/drivers/scsi/sr.c
+++ b/drivers/scsi/sr.c
@@ -46,6 +46,7 @@
 #include <linux/mutex.h>
 #include <linux/slab.h>
 #include <asm/uaccess.h>
+#include <linux/pm_runtime.h>
 
 #include <scsi/scsi.h>
 #include <scsi/scsi_dbg.h>
@@ -79,6 +80,8 @@ static DEFINE_MUTEX(sr_mutex);
 static int sr_probe(struct device *);
 static int sr_remove(struct device *);
 static int sr_done(struct scsi_cmnd *);
+static int sr_suspend(struct device *dev, pm_message_t msg);
+static int sr_resume(struct device *dev);
 
 static struct scsi_driver sr_template = {
 	.owner			= THIS_MODULE,
@@ -86,6 +89,8 @@ static struct scsi_driver sr_template = {
 		.name   	= "sr",
 		.probe		= sr_probe,
 		.remove		= sr_remove,
+		.suspend	= sr_suspend,
+		.resume		= sr_resume,
 	},
 	.done			= sr_done,
 };
@@ -167,6 +172,58 @@ static void scsi_cd_put(struct scsi_cd *cd)
 	mutex_unlock(&sr_ref_mutex);
 }
 
+static int sr_suspend(struct device *dev, pm_message_t msg)
+{
+	int poweroff;
+	struct scsi_sense_hdr sshdr;
+	struct scsi_cd *cd = dev_get_drvdata(dev);
+
+	/* no action for system suspend */
+	if (msg.event == PM_EVENT_SUSPEND)
+		return 0;
+
+	/* do another TUR to see if the ODD is still ready to be powered off */
+	scsi_test_unit_ready(cd->device, SR_TIMEOUT, MAX_RETRIES, &sshdr);
+
+	if (cd->cdi.mask & CDC_CLOSE_TRAY)
+		/* no media for caddy/slot type ODD */
+		poweroff = scsi_sense_valid(&sshdr) && sshdr.asc == 0x3a;
+	else
+		/* no media and door closed for tray type ODD */
+		poweroff = scsi_sense_valid(&sshdr) && sshdr.asc == 0x3a &&
+				sshdr.ascq == 0x01;
+
+	if (!poweroff) {
+		pm_runtime_get_noresume(dev);
+		atomic_set(&cd->suspend_count, 1);
+		return -EBUSY;
+	}
+
+	return 0;
+}
+
+static int sr_resume(struct device *dev)
+{
+	struct scsi_cd *cd;
+	struct scsi_sense_hdr sshdr;
+
+	cd = dev_get_drvdata(dev);
+
+	/* get the disk ready */
+	scsi_test_unit_ready(cd->device, SR_TIMEOUT, MAX_RETRIES, &sshdr);
+
+	/* if user wakes up the ODD, eject the tray */
+	if (cd->device->wakeup_by_user) {
+		cd->device->wakeup_by_user = 0;
+		if (!(cd->cdi.mask & CDC_CLOSE_TRAY))
+			sr_tray_move(&cd->cdi, 1);
+	}
+
+	atomic_set(&cd->suspend_count, 1);
+
+	return 0;
+}
+
 static unsigned int sr_get_events(struct scsi_device *sdev)
 {
 	u8 buf[8];
@@ -201,6 +258,37 @@ static unsigned int sr_get_events(struct scsi_device *sdev)
 	return 0;
 }
 
+static int sr_unit_load_done(struct scsi_cd *cd)
+{
+	u8 buf[8];
+	u8 cmd[] = { GET_EVENT_STATUS_NOTIFICATION,
+		     1,			/* polled */
+		     0, 0,		/* reserved */
+		     1 << 6,		/* notification class: Device Busy */
+		     0, 0,		/* reserved */
+		     0, sizeof(buf),	/* allocation length */
+		     0,			/* control */
+	};
+	struct event_header *eh = (void *)buf;
+	struct device_busy_event_desc *desc = (void *)(buf + 4);
+	struct scsi_sense_hdr sshdr;
+	int result;
+
+	result = scsi_execute_req(cd->device, cmd, DMA_FROM_DEVICE, buf,
+			sizeof(buf), &sshdr, SR_TIMEOUT, MAX_RETRIES, NULL);
+
+	if (result || be16_to_cpu(eh->data_len) < sizeof(*desc))
+		return 0;
+
+	if (eh->nea || eh->notification_class != 0x6)
+		return 0;
+
+	if (desc->device_busy_event == 2 && desc->device_busy_status == 0)
+		return 1;
+	else
+		return 0;
+}
+
 /*
  * This function checks to see if the media has been changed or eject
  * button has been pressed.  It is possible that we have already
@@ -215,12 +303,21 @@ static unsigned int sr_check_events(struct cdrom_device_info *cdi,
 	bool last_present;
 	struct scsi_sense_hdr sshdr;
 	unsigned int events;
-	int ret;
+	int ret, poweroff;
 
 	/* no changer support */
 	if (CDSL_CURRENT != slot)
 		return 0;
 
+	if (pm_runtime_suspended(&cd->device->sdev_gendev))
+		return 0;
+
+	/* if the logical unit just finished loading/unloading, do a TUR */
+	if (cd->device->can_power_off && cd->dbml && sr_unit_load_done(cd)) {
+		events = 0;
+		goto do_tur;
+	}
+
 	events = sr_get_events(cd->device);
 	cd->get_event_changed |= events & DISK_EVENT_MEDIA_CHANGE;
 
@@ -270,6 +367,22 @@ static unsigned int sr_check_events(struct cdrom_device_info *cdi,
 		cd->tur_changed = true;
 	}
 
+	if (cd->device->can_power_off && !cd->media_present) {
+		if (cd->cdi.mask & CDC_CLOSE_TRAY)
+			poweroff = 1;
+		else
+			poweroff = sshdr.ascq == 0x01;
+		/*
+		 * This function might be called concurrently by a kernel
+		 * thread (in-kernel polling) and old versions of udisks,
+		 * to avoid put the device twice, an atomic operation is used.
+		 */
+		if (poweroff && atomic_add_unless(&cd->suspend_count, -1, 0)) {
+			pm_runtime_mark_last_busy(&cd->device->sdev_gendev);
+			pm_runtime_put_autosuspend(&cd->device->sdev_gendev);
+		}
+	}
+
 	if (cd->ignore_get_event)
 		return events;
 
@@ -704,6 +817,15 @@ static int sr_probe(struct device *dev)
 	blk_queue_prep_rq(sdev->request_queue, sr_prep_fn);
 	sr_vendor_init(cd);
 
+	/* zero power support */
+	if (sdev->can_power_off) {
+		check_dbml(cd);
+		/* default delay time is 3 minutes */
+		pm_runtime_set_autosuspend_delay(dev, 180 * 1000);
+		pm_runtime_use_autosuspend(dev);
+		atomic_set(&cd->suspend_count, 1);
+	}
+
 	disk->driverfs_dev = &sdev->sdev_gendev;
 	set_capacity(disk, cd->capacity);
 	disk->private_data = &cd->driver;
@@ -988,6 +1110,10 @@ static int sr_remove(struct device *dev)
 {
 	struct scsi_cd *cd = dev_get_drvdata(dev);
 
+	/* disable runtime pm and possibly resume the device */
+	if (!atomic_dec_and_test(&cd->suspend_count))
+		pm_runtime_get_sync(dev);
+
 	blk_queue_prep_rq(cd->device->request_queue, scsi_prep_fn);
 	del_gendisk(cd->disk);
 
diff --git a/drivers/scsi/sr.h b/drivers/scsi/sr.h
index 7cc40ad..fd5c550 100644
--- a/drivers/scsi/sr.h
+++ b/drivers/scsi/sr.h
@@ -49,6 +49,8 @@ typedef struct scsi_cd {
 	bool get_event_changed:1;	/* changed according to GET_EVENT */
 	bool ignore_get_event:1;	/* GET_EVENT is unreliable, use TUR */
 
+	atomic_t suspend_count;	/* we should request autosuspend only once */
+
 	struct cdrom_device_info cdi;
 	/* We hold gendisk and scsi_device references on probe and use
 	 * the refs on this kref to decide when to release them */
diff --git a/include/scsi/scsi_device.h b/include/scsi/scsi_device.h
index 1237fac..65b9732 100644
--- a/include/scsi/scsi_device.h
+++ b/include/scsi/scsi_device.h
@@ -153,6 +153,7 @@ struct scsi_device {
 	unsigned no_read_capacity_16:1; /* Avoid READ_CAPACITY_16 cmds */
 	unsigned is_visible:1;	/* is the device visible in sysfs */
 	unsigned can_power_off:1; /* Device supports runtime power off */
+	unsigned wakeup_by_user:1;	/* user wakes up the ODD */
 
 	DECLARE_BITMAP(supported_events, SDEV_EVT_MAXBITS); /* supported events */
 	struct list_head event_list;	/* asserted events */
-- 
1.7.2.5

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

* [PATCH v4 13/13] [SCSI] sr: make sure ODD is in resumed state in block ioctl
  2012-05-28  5:08 [PATCH v4 0/13] SATA ZPODD support Lin Ming
                   ` (11 preceding siblings ...)
  2012-05-28  5:08 ` [PATCH v4 12/13] [SCSI] sr: support zero power ODD Lin Ming
@ 2012-05-28  5:08 ` Lin Ming
  2012-05-28  9:44 ` [PATCH v4 0/13] SATA ZPODD support Alan Cox
  13 siblings, 0 replies; 27+ messages in thread
From: Lin Ming @ 2012-05-28  5:08 UTC (permalink / raw)
  To: Jeff Garzik, David Woodhouse, Aaron Lu, Holger Macht, Matthew Garrett
  Cc: linux-kernel, linux-pm, linux-scsi, linux-ide, linux-acpi

From: Aaron Lu <aaron.lu@amd.com>

When application tries to access the ODD's block device by ioctl,
make sure ODD is in an active state.

Signed-off-by: Aaron Lu <aaron.lu@amd.com>
Signed-off-by: Lin Ming <ming.m.lin@intel.com>
---
 drivers/scsi/sr.c |    9 +++++++++
 1 files changed, 9 insertions(+), 0 deletions(-)

diff --git a/drivers/scsi/sr.c b/drivers/scsi/sr.c
index 72488c2..3da0879 100644
--- a/drivers/scsi/sr.c
+++ b/drivers/scsi/sr.c
@@ -654,6 +654,13 @@ static int sr_block_ioctl(struct block_device *bdev, fmode_t mode, unsigned cmd,
 	void __user *argp = (void __user *)arg;
 	int ret;
 
+	/* Make sure the ODD is not suspended */
+	ret = pm_runtime_get_sync(&sdev->sdev_gendev);
+	if (ret < 0) {
+		pm_runtime_put_noidle(&sdev->sdev_gendev);
+		return -EACCES;
+	}
+
 	mutex_lock(&sr_mutex);
 
 	/*
@@ -685,6 +692,8 @@ static int sr_block_ioctl(struct block_device *bdev, fmode_t mode, unsigned cmd,
 
 out:
 	mutex_unlock(&sr_mutex);
+	pm_runtime_mark_last_busy(&cd->device->sdev_gendev);
+	pm_runtime_put_autosuspend(&cd->device->sdev_gendev);
 	return ret;
 }
 
-- 
1.7.2.5


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

* Re: [PATCH v4 0/13] SATA ZPODD support
  2012-05-28  5:08 [PATCH v4 0/13] SATA ZPODD support Lin Ming
                   ` (12 preceding siblings ...)
  2012-05-28  5:08 ` [PATCH v4 13/13] [SCSI] sr: make sure ODD is in resumed state in block ioctl Lin Ming
@ 2012-05-28  9:44 ` Alan Cox
  2012-05-28  9:54   ` Alan Cox
  13 siblings, 1 reply; 27+ messages in thread
From: Alan Cox @ 2012-05-28  9:44 UTC (permalink / raw)
  To: Lin Ming
  Cc: Jeff Garzik, David Woodhouse, Aaron Lu, Holger Macht,
	Matthew Garrett, linux-kernel, linux-pm, linux-scsi, linux-ide,
	linux-acpi

On Mon, 28 May 2012 13:08:27 +0800
Lin Ming <ming.m.lin@intel.com> wrote:

> Hi all,
> 
> This is the v4 patches to add SATA ZPODD support, to try it:
> git pull git://git.kernel.org/pub/scm/linux/kernel/git/mlin/linux.git zpodd
> 
> Holger and Mathtew,
> Patch 1 to Patch 4 are the libata acpi binding patches from you.
> I removed dock related code from your original version.
> Would you help to review?
> 
> v4:
> - Includes libata acpi binding patches from Holger Macht and Matthew Garrett.
> - tell scsi layer device supports runtime power off
> - check support for device busy class events

Have you fixed the fact that Matthews patches broke things like pata_acpi
last time ? Until that is fixed properly I don't see that these patches
can make any progress.

Alan

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

* Re: [PATCH v4 02/13] libata: bind the Linux device tree to the ACPI device tree
  2012-05-28  5:08 ` [PATCH v4 02/13] libata: bind the Linux device tree to the ACPI device tree Lin Ming
@ 2012-05-28  9:51   ` Alan Cox
  2012-06-13  8:03     ` Lin Ming
  0 siblings, 1 reply; 27+ messages in thread
From: Alan Cox @ 2012-05-28  9:51 UTC (permalink / raw)
  To: Lin Ming
  Cc: Jeff Garzik, David Woodhouse, Aaron Lu, Holger Macht,
	Matthew Garrett, linux-kernel, linux-pm, linux-scsi, linux-ide,
	linux-acpi

> +static int is_pci_ata(struct device *dev)
> +{
> +	struct pci_dev *pdev;
> +
> +	if (!is_pci_dev(dev))
> +		return 0;
> +
> +	pdev = to_pci_dev(dev);
> +
> +	if ((pdev->class >> 8) != PCI_CLASS_STORAGE_SATA &&
> +	    (pdev->class >> 8) != PCI_CLASS_STORAGE_IDE)
> +		return 0;

This needs a better name. It doesn't check if a device is PCI ATA or
anything of the sort, it checks if its probably a device in compatibility
mode. A lot of controllers will in fact report RAID class or similar in
native mode.

Alan

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

* Re: [PATCH v4 0/13] SATA ZPODD support
  2012-05-28  9:44 ` [PATCH v4 0/13] SATA ZPODD support Alan Cox
@ 2012-05-28  9:54   ` Alan Cox
  2012-05-29 12:32     ` Lin Ming
  0 siblings, 1 reply; 27+ messages in thread
From: Alan Cox @ 2012-05-28  9:54 UTC (permalink / raw)
  To: Lin Ming
  Cc: Jeff Garzik, David Woodhouse, Aaron Lu, Holger Macht,
	Matthew Garrett, linux-kernel, linux-pm, linux-scsi, linux-ide,
	linux-acpi

> Have you fixed the fact that Matthews patches broke things like pata_acpi
> last time ? Until that is fixed properly I don't see that these patches
> can make any progress.

https://lkml.org/lkml/2012/2/24/2

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

* Re: [PATCH v4 04/13] libata: use correct PCI devices
  2012-05-28  5:08 ` [PATCH v4 04/13] libata: use correct PCI devices Lin Ming
@ 2012-05-29 12:22   ` Sergei Shtylyov
  0 siblings, 0 replies; 27+ messages in thread
From: Sergei Shtylyov @ 2012-05-29 12:22 UTC (permalink / raw)
  To: Lin Ming
  Cc: Jeff Garzik, David Woodhouse, Aaron Lu, Holger Macht,
	Matthew Garrett, linux-kernel, linux-pm, linux-scsi, linux-ide,
	linux-acpi

Hello.

On 28-05-2012 9:08, Lin Ming wrote:

> From: Holger Macht<holger@homac.de>

> Commit 9a6d6a2ddabbd32c07f6a38b659e5f3db319fa5a

    Please also specify that commit's summary in parens.

> made ata ports parent
> devices of scsi hosts, so we need to go yet another level up to be able
> to use the correct PCI devices.

> Signed-off-by: Holger Macht <holger@homac.de>
> Signed-off-by: Lin Ming <ming.m.lin@intel.com>

WBR, Sergei

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

* Re: [PATCH v4 01/13] [SCSI]: add wrapper to access and set scsi_bus_type in struct acpi_bus_type
  2012-05-28  5:08 ` [PATCH v4 01/13] [SCSI]: add wrapper to access and set scsi_bus_type in struct acpi_bus_type Lin Ming
@ 2012-05-29 12:26   ` Sergei Shtylyov
  0 siblings, 0 replies; 27+ messages in thread
From: Sergei Shtylyov @ 2012-05-29 12:26 UTC (permalink / raw)
  To: Lin Ming
  Cc: Jeff Garzik, David Woodhouse, Aaron Lu, Holger Macht,
	Matthew Garrett, linux-kernel, linux-pm, linux-scsi, linux-ide,
	linux-acpi

Hello.

On 28-05-2012 9:08, Lin Ming wrote:

> From: Holger Macht<holger@homac.de>

> For being able to bind ata devices against acpi devices, scsi_bus_type
> needs to be set as bus in struct acpi_bus_type. So add wrapper to
> scsi_lib to accomplish that.

> Signed-off-by: Holger Macht<holger@homac.de>
> Signed-off-by: Lin Ming<ming.m.lin@intel.com>
> ---
>   drivers/scsi/scsi_lib.c |   17 +++++++++++++++++
>   include/scsi/scsi.h     |   10 ++++++++++
>   2 files changed, 27 insertions(+), 0 deletions(-)

> diff --git a/include/scsi/scsi.h b/include/scsi/scsi.h
> index f34a5a8..4527b3a 100644
> --- a/include/scsi/scsi.h
> +++ b/include/scsi/scsi.h
> @@ -214,6 +214,16 @@ scsi_command_size(const unsigned char *cmnd)
>   		scsi_varlen_cdb_length(cmnd) : COMMAND_SIZE(cmnd[0]);
>   }
>
> +#ifdef CONFIG_ACPI

    You don't have to enclode declarations into #ifdef.

> +struct acpi_bus_type;
> +
> +extern int

    'extern' is the default memory class for function, no need to specidy it.
And don't break the line here.

> +scsi_register_acpi_bus_type(struct acpi_bus_type *bus);
> +
> +extern void

    Same comment.

> +scsi_unregister_acpi_bus_type(struct acpi_bus_type *bus);
> +#endif

MBR, Sergei

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

* Re: [PATCH v4 0/13] SATA ZPODD support
  2012-05-28  9:54   ` Alan Cox
@ 2012-05-29 12:32     ` Lin Ming
  2012-05-30  5:43         ` Aaron Lu
  0 siblings, 1 reply; 27+ messages in thread
From: Lin Ming @ 2012-05-29 12:32 UTC (permalink / raw)
  To: Alan Cox
  Cc: Jeff Garzik, David Woodhouse, Aaron Lu, Holger Macht,
	Matthew Garrett, linux-kernel, linux-pm, linux-scsi, linux-ide,
	linux-acpi

On Mon, May 28, 2012 at 5:54 PM, Alan Cox <alan@lxorguk.ukuu.org.uk> wrote:
>> Have you fixed the fact that Matthews patches broke things like pata_acpi
>> last time ? Until that is fixed properly I don't see that these patches
>> can make any progress.
>
> https://lkml.org/lkml/2012/2/24/2

Aaron has a fix.
We'll do more test.

Thanks for the info.
Lin Ming

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

* Re: [PATCH v4 0/13] SATA ZPODD support
  2012-05-29 12:32     ` Lin Ming
@ 2012-05-30  5:43         ` Aaron Lu
  0 siblings, 0 replies; 27+ messages in thread
From: Aaron Lu @ 2012-05-30  5:43 UTC (permalink / raw)
  To: Lin Ming, Fuzhou Chen
  Cc: Alan Cox, Jeff Garzik, David Woodhouse, Holger Macht,
	Matthew Garrett, linux-kernel, linux-pm, linux-scsi, linux-ide,
	linux-acpi

On Tue, May 29, 2012 at 08:32:49PM +0800, Lin Ming wrote:
> On Mon, May 28, 2012 at 5:54 PM, Alan Cox <alan@lxorguk.ukuu.org.uk> wrote:
> >> Have you fixed the fact that Matthews patches broke things like pata_acpi
> >> last time ? Until that is fixed properly I don't see that these patches
> >> can make any progress.
> >
> > https://lkml.org/lkml/2012/2/24/2
> 
> Aaron has a fix.
> We'll do more test.

Here is the patch, apply on top of the ZPODD patch set.

Hi Fuzhou,
Can you please give it a test? Thanks.
I tested on my system with a ATI IDE controller and it could work with
pata_acpi module.

diff --git a/drivers/ata/libata-acpi.c b/drivers/ata/libata-acpi.c
index 6de8f32..c53266a 100644
--- a/drivers/ata/libata-acpi.c
+++ b/drivers/ata/libata-acpi.c
@@ -59,7 +59,18 @@ acpi_handle ata_ap_acpi_handle(struct ata_port *ap)
 {
 	if (ap->flags & ATA_FLAG_ACPI_SATA)
 		return NULL;
-	return DEVICE_ACPI_HANDLE(&ap->scsi_host->shost_gendev);
+
+	/*
+	 * If acpi bind operation has already happened, we can get the handle
+	 * for the port by checking the corresponding scsi_host device's
+	 * firmware node, otherwise we will need to find out the handle from
+	 * its parent's acpi node.
+	 */
+	if (ap->scsi_host)
+		return DEVICE_ACPI_HANDLE(&ap->scsi_host->shost_gendev);
+	else
+		return acpi_get_child(DEVICE_ACPI_HANDLE(ap->host->dev),
+				ap->port_no);
 }
 EXPORT_SYMBOL(ata_ap_acpi_handle);

-Aaron

> 
> Thanks for the info.
> Lin Ming
> --
> 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 related	[flat|nested] 27+ messages in thread

* Re: [PATCH v4 0/13] SATA ZPODD support
@ 2012-05-30  5:43         ` Aaron Lu
  0 siblings, 0 replies; 27+ messages in thread
From: Aaron Lu @ 2012-05-30  5:43 UTC (permalink / raw)
  To: Lin Ming, Fuzhou Chen
  Cc: Alan Cox, Jeff Garzik, David Woodhouse, Holger Macht,
	Matthew Garrett, linux-kernel, linux-pm, linux-scsi, linux-ide,
	linux-acpi

On Tue, May 29, 2012 at 08:32:49PM +0800, Lin Ming wrote:
> On Mon, May 28, 2012 at 5:54 PM, Alan Cox <alan@lxorguk.ukuu.org.uk> wrote:
> >> Have you fixed the fact that Matthews patches broke things like pata_acpi
> >> last time ? Until that is fixed properly I don't see that these patches
> >> can make any progress.
> >
> > https://lkml.org/lkml/2012/2/24/2
> 
> Aaron has a fix.
> We'll do more test.

Here is the patch, apply on top of the ZPODD patch set.

Hi Fuzhou,
Can you please give it a test? Thanks.
I tested on my system with a ATI IDE controller and it could work with
pata_acpi module.

diff --git a/drivers/ata/libata-acpi.c b/drivers/ata/libata-acpi.c
index 6de8f32..c53266a 100644
--- a/drivers/ata/libata-acpi.c
+++ b/drivers/ata/libata-acpi.c
@@ -59,7 +59,18 @@ acpi_handle ata_ap_acpi_handle(struct ata_port *ap)
 {
 	if (ap->flags & ATA_FLAG_ACPI_SATA)
 		return NULL;
-	return DEVICE_ACPI_HANDLE(&ap->scsi_host->shost_gendev);
+
+	/*
+	 * If acpi bind operation has already happened, we can get the handle
+	 * for the port by checking the corresponding scsi_host device's
+	 * firmware node, otherwise we will need to find out the handle from
+	 * its parent's acpi node.
+	 */
+	if (ap->scsi_host)
+		return DEVICE_ACPI_HANDLE(&ap->scsi_host->shost_gendev);
+	else
+		return acpi_get_child(DEVICE_ACPI_HANDLE(ap->host->dev),
+				ap->port_no);
 }
 EXPORT_SYMBOL(ata_ap_acpi_handle);

-Aaron

> 
> Thanks for the info.
> Lin Ming
> --
> 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 related	[flat|nested] 27+ messages in thread

* RE: [PATCH v4 0/13] SATA ZPODD support
  2012-05-30  5:43         ` Aaron Lu
  (?)
@ 2012-05-30  9:06         ` Fuzhou Chen
  -1 siblings, 0 replies; 27+ messages in thread
From: Fuzhou Chen @ 2012-05-30  9:06 UTC (permalink / raw)
  To: Aaron Lu, Lin Ming, Hashir Abdi
  Cc: Alan Cox, Jeff Garzik, David Woodhouse, Holger Macht,
	Matthew Garrett, linux-kernel, linux-pm, linux-scsi, linux-ide,
	linux-acpi

Sorry Aaron, but I have left Microsoft Open Source team for a while. Due to policy limitations, I can't touch Linux kernel source now. 

Hi Hashir, could you help find current owner of our HDD driver to verify this fix? This is a ata-acpi module bug I reported last year. Our daily BVT in linux-next tree should be able to handle this verification

Thanks,
Fuzhou

-----Original Message-----
From: Aaron Lu [mailto:aaron.lu@amd.com] 
Sent: Wednesday, May 30, 2012 1:43 PM
To: Lin Ming; Fuzhou Chen
Cc: Alan Cox; Jeff Garzik; David Woodhouse; Holger Macht; Matthew Garrett; linux-kernel@vger.kernel.org; linux-pm@vger.kernel.org; linux-scsi@vger.kernel.org; linux-ide@vger.kernel.org; linux-acpi@vger.kernel.org
Subject: Re: [PATCH v4 0/13] SATA ZPODD support

On Tue, May 29, 2012 at 08:32:49PM +0800, Lin Ming wrote:
> On Mon, May 28, 2012 at 5:54 PM, Alan Cox <alan@lxorguk.ukuu.org.uk> wrote:
> >> Have you fixed the fact that Matthews patches broke things like 
> >> pata_acpi last time ? Until that is fixed properly I don't see that 
> >> these patches can make any progress.
> >
> > https://lkml.org/lkml/2012/2/24/2
> 
> Aaron has a fix.
> We'll do more test.

Here is the patch, apply on top of the ZPODD patch set.

Hi Fuzhou,
Can you please give it a test? Thanks.
I tested on my system with a ATI IDE controller and it could work with pata_acpi module.

diff --git a/drivers/ata/libata-acpi.c b/drivers/ata/libata-acpi.c index 6de8f32..c53266a 100644
--- a/drivers/ata/libata-acpi.c
+++ b/drivers/ata/libata-acpi.c
@@ -59,7 +59,18 @@ acpi_handle ata_ap_acpi_handle(struct ata_port *ap)  {
 	if (ap->flags & ATA_FLAG_ACPI_SATA)
 		return NULL;
-	return DEVICE_ACPI_HANDLE(&ap->scsi_host->shost_gendev);
+
+	/*
+	 * If acpi bind operation has already happened, we can get the handle
+	 * for the port by checking the corresponding scsi_host device's
+	 * firmware node, otherwise we will need to find out the handle from
+	 * its parent's acpi node.
+	 */
+	if (ap->scsi_host)
+		return DEVICE_ACPI_HANDLE(&ap->scsi_host->shost_gendev);
+	else
+		return acpi_get_child(DEVICE_ACPI_HANDLE(ap->host->dev),
+				ap->port_no);
 }
 EXPORT_SYMBOL(ata_ap_acpi_handle);

-Aaron

> 
> Thanks for the info.
> Lin Ming
> --
> 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] 27+ messages in thread

* Re: [PATCH v4 02/13] libata: bind the Linux device tree to the ACPI device tree
  2012-05-28  9:51   ` Alan Cox
@ 2012-06-13  8:03     ` Lin Ming
  2012-06-13 11:00         ` Alan Cox
  0 siblings, 1 reply; 27+ messages in thread
From: Lin Ming @ 2012-06-13  8:03 UTC (permalink / raw)
  To: Alan Cox
  Cc: Jeff Garzik, David Woodhouse, Aaron Lu, Holger Macht,
	Matthew Garrett, linux-kernel, linux-pm, linux-scsi, linux-ide,
	linux-acpi

On Mon, May 28, 2012 at 5:51 PM, Alan Cox <alan@lxorguk.ukuu.org.uk> wrote:
>> +static int is_pci_ata(struct device *dev)
>> +{
>> +     struct pci_dev *pdev;
>> +
>> +     if (!is_pci_dev(dev))
>> +             return 0;
>> +
>> +     pdev = to_pci_dev(dev);
>> +
>> +     if ((pdev->class >> 8) != PCI_CLASS_STORAGE_SATA &&
>> +         (pdev->class >> 8) != PCI_CLASS_STORAGE_IDE)
>> +             return 0;
>
> This needs a better name. It doesn't check if a device is PCI ATA or
> anything of the sort, it checks if its probably a device in compatibility
> mode. A lot of controllers will in fact report RAID class or similar in
> native mode.

How about compat_pci_ata?

>
> Alan

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

* Re: [PATCH v4 02/13] libata: bind the Linux device tree to the ACPI device tree
  2012-06-13  8:03     ` Lin Ming
@ 2012-06-13 11:00         ` Alan Cox
  0 siblings, 0 replies; 27+ messages in thread
From: Alan Cox @ 2012-06-13 11:00 UTC (permalink / raw)
  To: Lin Ming
  Cc: Jeff Garzik, David Woodhouse, Aaron Lu, Holger Macht,
	Matthew Garrett, linux-kernel, linux-pm, linux-scsi, linux-ide,
	linux-acpi

On Wed, 13 Jun 2012 16:03:23 +0800
Lin Ming <ming.m.lin@intel.com> wrote:

> On Mon, May 28, 2012 at 5:51 PM, Alan Cox <alan@lxorguk.ukuu.org.uk> wrote:
> >> +static int is_pci_ata(struct device *dev)
> >> +{
> >> +     struct pci_dev *pdev;
> >> +
> >> +     if (!is_pci_dev(dev))
> >> +             return 0;
> >> +
> >> +     pdev = to_pci_dev(dev);
> >> +
> >> +     if ((pdev->class >> 8) != PCI_CLASS_STORAGE_SATA &&
> >> +         (pdev->class >> 8) != PCI_CLASS_STORAGE_IDE)
> >> +             return 0;
> >
> > This needs a better name. It doesn't check if a device is PCI ATA or
> > anything of the sort, it checks if its probably a device in compatibility
> > mode. A lot of controllers will in fact report RAID class or similar in
> > native mode.
> 
> How about compat_pci_ata?

Sounds reasonable. I'm not btw sure the test is entirely right, but I'm
not sure quite what you are trying to figure out from it and how ACPI
expects this mapping to work.

Alan
--
To unsubscribe from this list: send the line "unsubscribe linux-acpi" 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] 27+ messages in thread

* Re: [PATCH v4 02/13] libata: bind the Linux device tree to the ACPI device tree
@ 2012-06-13 11:00         ` Alan Cox
  0 siblings, 0 replies; 27+ messages in thread
From: Alan Cox @ 2012-06-13 11:00 UTC (permalink / raw)
  To: Lin Ming
  Cc: Jeff Garzik, David Woodhouse, Aaron Lu, Holger Macht,
	Matthew Garrett, linux-kernel, linux-pm, linux-scsi, linux-ide,
	linux-acpi

On Wed, 13 Jun 2012 16:03:23 +0800
Lin Ming <ming.m.lin@intel.com> wrote:

> On Mon, May 28, 2012 at 5:51 PM, Alan Cox <alan@lxorguk.ukuu.org.uk> wrote:
> >> +static int is_pci_ata(struct device *dev)
> >> +{
> >> +     struct pci_dev *pdev;
> >> +
> >> +     if (!is_pci_dev(dev))
> >> +             return 0;
> >> +
> >> +     pdev = to_pci_dev(dev);
> >> +
> >> +     if ((pdev->class >> 8) != PCI_CLASS_STORAGE_SATA &&
> >> +         (pdev->class >> 8) != PCI_CLASS_STORAGE_IDE)
> >> +             return 0;
> >
> > This needs a better name. It doesn't check if a device is PCI ATA or
> > anything of the sort, it checks if its probably a device in compatibility
> > mode. A lot of controllers will in fact report RAID class or similar in
> > native mode.
> 
> How about compat_pci_ata?

Sounds reasonable. I'm not btw sure the test is entirely right, but I'm
not sure quite what you are trying to figure out from it and how ACPI
expects this mapping to work.

Alan

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

* Re: [PATCH v4 02/13] libata: bind the Linux device tree to the ACPI device tree
  2012-06-13 11:00         ` Alan Cox
  (?)
@ 2012-06-14  7:43         ` Lin Ming
  -1 siblings, 0 replies; 27+ messages in thread
From: Lin Ming @ 2012-06-14  7:43 UTC (permalink / raw)
  To: Alan Cox
  Cc: Jeff Garzik, David Woodhouse, Aaron Lu, Holger Macht,
	Matthew Garrett, linux-kernel, linux-pm, linux-scsi, linux-ide,
	linux-acpi

On Wed, Jun 13, 2012 at 7:00 PM, Alan Cox <alan@lxorguk.ukuu.org.uk> wrote:
> On Wed, 13 Jun 2012 16:03:23 +0800
> Lin Ming <ming.m.lin@intel.com> wrote:
>
>> On Mon, May 28, 2012 at 5:51 PM, Alan Cox <alan@lxorguk.ukuu.org.uk> wrote:
>> >> +static int is_pci_ata(struct device *dev)
>> >> +{
>> >> +     struct pci_dev *pdev;
>> >> +
>> >> +     if (!is_pci_dev(dev))
>> >> +             return 0;
>> >> +
>> >> +     pdev = to_pci_dev(dev);
>> >> +
>> >> +     if ((pdev->class >> 8) != PCI_CLASS_STORAGE_SATA &&
>> >> +         (pdev->class >> 8) != PCI_CLASS_STORAGE_IDE)
>> >> +             return 0;
>> >
>> > This needs a better name. It doesn't check if a device is PCI ATA or
>> > anything of the sort, it checks if its probably a device in compatibility
>> > mode. A lot of controllers will in fact report RAID class or similar in
>> > native mode.
>>
>> How about compat_pci_ata?
>
> Sounds reasonable. I'm not btw sure the test is entirely right, but I'm
> not sure quite what you are trying to figure out from it and how ACPI
> expects this mapping to work.

It's used to figure out if the dev passed in from scsi layer is a ata device.

scsi_sysfs_add_sdev
device_add
acpi_platform_notify
ata_acpi_find_device
is_pci_ata

Thanks,
Lin Ming

>
> Alan

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

end of thread, other threads:[~2012-06-14  7:43 UTC | newest]

Thread overview: 27+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-05-28  5:08 [PATCH v4 0/13] SATA ZPODD support Lin Ming
2012-05-28  5:08 ` [PATCH v4 01/13] [SCSI]: add wrapper to access and set scsi_bus_type in struct acpi_bus_type Lin Ming
2012-05-29 12:26   ` Sergei Shtylyov
2012-05-28  5:08 ` [PATCH v4 02/13] libata: bind the Linux device tree to the ACPI device tree Lin Ming
2012-05-28  9:51   ` Alan Cox
2012-06-13  8:03     ` Lin Ming
2012-06-13 11:00       ` Alan Cox
2012-06-13 11:00         ` Alan Cox
2012-06-14  7:43         ` Lin Ming
2012-05-28  5:08 ` [PATCH v4 03/13] libata: migrate ACPI code over to new bindings Lin Ming
2012-05-28  5:08 ` [PATCH v4 04/13] libata: use correct PCI devices Lin Ming
2012-05-29 12:22   ` Sergei Shtylyov
2012-05-28  5:08 ` [PATCH v4 05/13] libata-acpi: set acpi state for SATA port Lin Ming
2012-05-28  5:08 ` [PATCH v4 06/13] libata-acpi: add ata port runtime D3Cold support Lin Ming
2012-05-28  5:08 ` [PATCH v4 07/13] libata-acpi: register/unregister device to/from power resource Lin Ming
2012-05-28  5:08 ` [PATCH v4 08/13] libata: detect Device Attention support Lin Ming
2012-05-28  5:08 ` [PATCH v4 09/13] libata: tell scsi layer device supports runtime power off Lin Ming
2012-05-28  5:08 ` [PATCH v4 10/13] [SCSI] pm: resume device if suspend failed Lin Ming
2012-05-28  5:08 ` [PATCH v4 11/13] [SCSI] sr: check support for device busy class events Lin Ming
2012-05-28  5:08 ` [PATCH v4 12/13] [SCSI] sr: support zero power ODD Lin Ming
2012-05-28  5:08 ` [PATCH v4 13/13] [SCSI] sr: make sure ODD is in resumed state in block ioctl Lin Ming
2012-05-28  9:44 ` [PATCH v4 0/13] SATA ZPODD support Alan Cox
2012-05-28  9:54   ` Alan Cox
2012-05-29 12:32     ` Lin Ming
2012-05-30  5:43       ` Aaron Lu
2012-05-30  5:43         ` Aaron Lu
2012-05-30  9:06         ` Fuzhou Chen

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.