All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 1/6] libata_suspend (Jens)
       [not found] <20051202100119.032b242e.randy_d_dunlap@linux.intel.com>
@ 2005-12-02 18:03 ` Randy Dunlap
  2005-12-02 18:04 ` [PATCH 2/6] SATA ACPI: make/config changes Randy Dunlap
                   ` (5 subsequent siblings)
  6 siblings, 0 replies; 24+ messages in thread
From: Randy Dunlap @ 2005-12-02 18:03 UTC (permalink / raw)
  To: ide; +Cc: axboe, jgarzik

From: Jens Axboe <axboe@suse.de>

SATA suspend/resume patch.

---
 drivers/scsi/ata_piix.c    |    4 +
 drivers/scsi/libata-core.c |  122 +++++++++++++++++++++++++++++++++++++++++++++
 drivers/scsi/libata-scsi.c |   16 +++++
 drivers/scsi/scsi_sysfs.c  |   35 ++++++++++++
 include/linux/ata.h        |    2 
 include/linux/libata.h     |    7 ++
 include/scsi/scsi_host.h   |    6 ++
 7 files changed, 190 insertions(+), 2 deletions(-)

--- linux-2615-rc4.orig/drivers/scsi/ata_piix.c
+++ linux-2615-rc4/drivers/scsi/ata_piix.c
@@ -125,6 +125,8 @@ static struct pci_driver piix_pci_driver
 	.id_table		= piix_pci_tbl,
 	.probe			= piix_init_one,
 	.remove			= ata_pci_remove_one,
+	.suspend		= ata_pci_device_suspend,
+	.resume			= ata_pci_device_resume,
 };
 
 static struct scsi_host_template piix_sht = {
@@ -145,6 +147,8 @@ static struct scsi_host_template piix_sh
 	.slave_configure	= ata_scsi_slave_config,
 	.bios_param		= ata_std_bios_param,
 	.ordered_flush		= 1,
+	.suspend		= ata_scsi_device_suspend,
+	.resume			= ata_scsi_device_resume,
 };
 
 static const struct ata_port_operations piix_pata_ops = {
--- linux-2615-rc4.orig/drivers/scsi/libata-core.c
+++ linux-2615-rc4/drivers/scsi/libata-core.c
@@ -4099,6 +4099,104 @@ err_out:
 }
 
 
+/*
+ * 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_port *ap, struct ata_device *dev,
+			     u8 cmd)
+{
+	DECLARE_COMPLETION(wait);
+	struct ata_queued_cmd *qc;
+	unsigned long flags;
+	int rc;
+
+	while ((qc = ata_qc_new_init(ap, dev)) == NULL)
+		msleep(10);
+
+	qc->tf.command = cmd;
+	qc->tf.flags |= ATA_TFLAG_DEVICE;
+	qc->tf.protocol = ATA_PROT_NODATA;
+
+	qc->waiting = &wait;
+	qc->complete_fn = ata_qc_complete_noop;
+
+	spin_lock_irqsave(&ap->host_set->lock, flags);
+	rc = ata_qc_issue(qc);
+	spin_unlock_irqrestore(&ap->host_set->lock, flags);
+
+	if (!rc)
+		wait_for_completion(&wait);
+
+	return rc;
+}
+
+static int ata_flush_cache(struct ata_port *ap, struct ata_device *dev)
+{
+	u8 cmd;
+
+	if (!ata_try_flush_cache(dev))
+		return 0;
+
+	if (ata_id_has_flush_ext(dev->id))
+		cmd = ATA_CMD_FLUSH_EXT;
+	else
+		cmd = ATA_CMD_FLUSH;
+
+	return ata_do_simple_cmd(ap, dev, cmd);
+}
+
+static int ata_standby_drive(struct ata_port *ap, struct ata_device *dev)
+{
+	return ata_do_simple_cmd(ap, dev, ATA_CMD_STANDBYNOW1);
+}
+
+static int ata_start_drive(struct ata_port *ap, struct ata_device *dev)
+{
+	return ata_do_simple_cmd(ap, dev, ATA_CMD_IDLEIMMEDIATE);
+}
+
+/**
+ *	ata_device_resume - wakeup a previously suspended devices
+ *
+ *	Kick the drive back into action, by sending it an idle immediate
+ *	command and making sure its transfer mode matches between drive
+ *	and host.
+ *
+ */
+int ata_device_resume(struct ata_port *ap, struct ata_device *dev)
+{
+	if (ap->flags & ATA_FLAG_SUSPENDED) {
+		ap->flags &= ~ATA_FLAG_SUSPENDED;
+		ata_set_mode(ap);
+	}
+	if (!ata_dev_present(dev))
+		return 0;
+	if (dev->class == ATA_DEV_ATA)
+		ata_start_drive(ap, dev);
+
+	return 0;
+}
+
+/**
+ *	ata_device_suspend - prepare a device for suspend
+ *
+ *	Flush the cache on the drive, if appropriate, then issue a
+ *	standbynow command.
+ *
+ */
+int ata_device_suspend(struct ata_port *ap, struct ata_device *dev)
+{
+	if (!ata_dev_present(dev))
+		return 0;
+	if (dev->class == ATA_DEV_ATA)
+		ata_flush_cache(ap, dev);
+
+	ata_standby_drive(ap, dev);
+	ap->flags |= ATA_FLAG_SUSPENDED;
+	return 0;
+}
+
 /**
  *	ata_port_start - Set port up for dma.
  *	@ap: Port to initialize
@@ -4860,6 +4958,23 @@ 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)
+{
+	pci_save_state(pdev);
+	pci_disable_device(pdev);
+	pci_set_power_state(pdev, PCI_D3hot);
+	return 0;
+}
+
+int ata_pci_device_resume(struct pci_dev *pdev)
+{
+	pci_set_power_state(pdev, PCI_D0);
+	pci_restore_state(pdev);
+	pci_enable_device(pdev);
+	pci_set_master(pdev);
+	return 0;
+}
 #endif /* CONFIG_PCI */
 
 
@@ -4963,4 +5078,11 @@ 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_suspend);
+EXPORT_SYMBOL_GPL(ata_pci_device_resume);
 #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);
--- linux-2615-rc4.orig/drivers/scsi/libata-scsi.c
+++ linux-2615-rc4/drivers/scsi/libata-scsi.c
@@ -396,6 +396,22 @@ void ata_dump_status(unsigned id, struct
 	}
 }
 
+int ata_scsi_device_resume(struct scsi_device *sdev)
+{
+	struct ata_port *ap = (struct ata_port *) &sdev->host->hostdata[0];
+	struct ata_device *dev = &ap->device[sdev->id];
+
+	return ata_device_resume(ap, dev);
+}
+
+int ata_scsi_device_suspend(struct scsi_device *sdev)
+{
+	struct ata_port *ap = (struct ata_port *) &sdev->host->hostdata[0];
+	struct ata_device *dev = &ap->device[sdev->id];
+
+	return ata_device_suspend(ap, dev);
+}
+
 /**
  *	ata_to_sense_error - convert ATA error to SCSI error
  *	@id: ATA device number
--- linux-2615-rc4.orig/drivers/scsi/scsi_sysfs.c
+++ linux-2615-rc4/drivers/scsi/scsi_sysfs.c
@@ -263,9 +263,40 @@ static int scsi_bus_match(struct device 
 	return (sdp->inq_periph_qual == SCSI_INQ_PQ_CON)? 1: 0;
 }
 
+static int scsi_bus_suspend(struct device * dev, pm_message_t state)
+{
+	struct scsi_device *sdev = to_scsi_device(dev);
+	struct scsi_host_template *sht = sdev->host->hostt;
+	int err;
+
+	err = scsi_device_quiesce(sdev);
+	if (err)
+		return err;
+
+	if (sht->suspend)
+		err = sht->suspend(sdev);
+
+	return err;
+}
+
+static int scsi_bus_resume(struct device * dev)
+{
+	struct scsi_device *sdev = to_scsi_device(dev);
+	struct scsi_host_template *sht = sdev->host->hostt;
+	int err = 0;
+
+	if (sht->resume)
+		err = sht->resume(sdev);
+
+	scsi_device_resume(sdev);
+	return err;
+}
+
 struct bus_type scsi_bus_type = {
-        .name		= "scsi",
-        .match		= scsi_bus_match,
+	.name		= "scsi",
+	.match		= scsi_bus_match,
+	.suspend	= scsi_bus_suspend,
+	.resume		= scsi_bus_resume,
 };
 
 int scsi_sysfs_register(void)
--- linux-2615-rc4.orig/include/linux/ata.h
+++ linux-2615-rc4/include/linux/ata.h
@@ -141,6 +141,8 @@ enum {
 	ATA_CMD_PACKET		= 0xA0,
 	ATA_CMD_VERIFY		= 0x40,
 	ATA_CMD_VERIFY_EXT	= 0x42,
+ 	ATA_CMD_STANDBYNOW1	= 0xE0,
+ 	ATA_CMD_IDLEIMMEDIATE	= 0xE1,
 	ATA_CMD_INIT_DEV_PARAMS	= 0x91,
 
 	/* SETFEATURES stuff */
--- linux-2615-rc4.orig/include/linux/libata.h
+++ linux-2615-rc4/include/linux/libata.h
@@ -122,6 +122,7 @@ enum {
 	ATA_FLAG_NOINTR		= (1 << 9), /* FIXME: Remove this once
 					     * proper HSM is in place. */
 	ATA_FLAG_DEBUGMSG	= (1 << 10),
+	ATA_FLAG_SUSPENDED	= (1 << 11), /* port is suspended */
 
 	ATA_QCFLAG_ACTIVE	= (1 << 1), /* cmd not yet ack'd to scsi lyer */
 	ATA_QCFLAG_SG		= (1 << 3), /* have s/g table? */
@@ -435,6 +436,8 @@ extern void ata_std_ports(struct ata_iop
 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 int ata_pci_device_suspend(struct pci_dev *pdev, pm_message_t state);
+extern int ata_pci_device_resume(struct pci_dev *pdev);
 #endif /* CONFIG_PCI */
 extern int ata_device_add(const struct ata_probe_ent *ent);
 extern void ata_host_set_remove(struct ata_host_set *host_set);
@@ -444,6 +447,10 @@ extern int ata_scsi_queuecmd(struct scsi
 extern int ata_scsi_error(struct Scsi_Host *host);
 extern int ata_scsi_release(struct Scsi_Host *host);
 extern unsigned int ata_host_intr(struct ata_port *ap, struct ata_queued_cmd *qc);
+extern int ata_scsi_device_resume(struct scsi_device *);
+extern int ata_scsi_device_suspend(struct scsi_device *);
+extern int ata_device_resume(struct ata_port *, struct ata_device *);
+extern int ata_device_suspend(struct ata_port *, struct ata_device *);
 extern int ata_ratelimit(void);
 
 /*
--- linux-2615-rc4.orig/include/scsi/scsi_host.h
+++ linux-2615-rc4/include/scsi/scsi_host.h
@@ -296,6 +296,12 @@ struct scsi_host_template {
 	int (*proc_info)(struct Scsi_Host *, char *, char **, off_t, int, int);
 
 	/*
+	 * suspend support
+	 */
+	int (*suspend)(struct scsi_device *);
+	int (*resume)(struct scsi_device *);
+
+	/*
 	 * Name of proc directory
 	 */
 	char *proc_name;



---

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

* [PATCH 2/6] SATA ACPI: make/config changes
       [not found] <20051202100119.032b242e.randy_d_dunlap@linux.intel.com>
  2005-12-02 18:03 ` [PATCH 1/6] libata_suspend (Jens) Randy Dunlap
@ 2005-12-02 18:04 ` Randy Dunlap
  2005-12-02 18:05 ` [PATCH 3/6] SATA ACPI: libata.h changes Randy Dunlap
                   ` (4 subsequent siblings)
  6 siblings, 0 replies; 24+ messages in thread
From: Randy Dunlap @ 2005-12-02 18:04 UTC (permalink / raw)
  To: ide; +Cc: axboe, jgarzik

From: Randy Dunlap <randy_d_dunlap@linux.intel.com>

Add ata_acpi in Makefile and Kconfig.

Signed-off-by: Randy Dunlap <randy_d_dunlap@linux.intel.com>
---
 drivers/scsi/Kconfig  |    5 +++++
 drivers/scsi/Makefile |    1 +
 2 files changed, 6 insertions(+)

--- linux-2615-rc4.orig/drivers/scsi/Makefile
+++ linux-2615-rc4/drivers/scsi/Makefile
@@ -138,6 +138,7 @@ obj-$(CONFIG_SCSI_SATA_NV)	+= libata.o s
 obj-$(CONFIG_SCSI_SATA_ULI)	+= libata.o sata_uli.o
 obj-$(CONFIG_SCSI_SATA_MV)	+= libata.o sata_mv.o
 obj-$(CONFIG_SCSI_PDC_ADMA)	+= libata.o pdc_adma.o
+obj-$(CONFIG_SCSI_SATA_ACPI)	+= libata.o ata_acpi.o
 
 obj-$(CONFIG_ARM)		+= arm/
 
--- linux-2615-rc4.orig/drivers/scsi/Kconfig
+++ linux-2615-rc4/drivers/scsi/Kconfig
@@ -598,6 +598,11 @@ config SCSI_SATA_INTEL_COMBINED
 	depends on IDE=y && !BLK_DEV_IDE_SATA && (SCSI_SATA_AHCI || SCSI_ATA_PIIX)
 	default y
 
+config SCSI_SATA_ACPI
+	bool
+	depends on SCSI_SATA && ACPI
+	default y
+
 config SCSI_BUSLOGIC
 	tristate "BusLogic SCSI support"
 	depends on (PCI || ISA || MCA) && SCSI && ISA_DMA_API


---

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

* [PATCH 3/6] SATA ACPI: libata.h changes
       [not found] <20051202100119.032b242e.randy_d_dunlap@linux.intel.com>
  2005-12-02 18:03 ` [PATCH 1/6] libata_suspend (Jens) Randy Dunlap
  2005-12-02 18:04 ` [PATCH 2/6] SATA ACPI: make/config changes Randy Dunlap
@ 2005-12-02 18:05 ` Randy Dunlap
  2005-12-02 18:07 ` [PATCH 4/6] SATA ACPI: call new ACPI functions Randy Dunlap
                   ` (3 subsequent siblings)
  6 siblings, 0 replies; 24+ messages in thread
From: Randy Dunlap @ 2005-12-02 18:05 UTC (permalink / raw)
  To: ide; +Cc: axboe, jgarzik

From: Randy Dunlap <randy_d_dunlap@linux.intel.com>

Add ACPI data pointer/length holders.

Signed-off-by: Randy Dunlap <randy_d_dunlap@linux.intel.com>
---
 include/linux/libata.h |    6 ++++++
 1 files changed, 6 insertions(+)

--- linux-2615-rc4.orig/include/linux/libata.h
+++ linux-2615-rc4/include/linux/libata.h
@@ -33,6 +33,7 @@
 #include <asm/io.h>
 #include <linux/ata.h>
 #include <linux/workqueue.h>
+#include <acpi/acpi.h>
 
 /*
  * compile-time options
@@ -311,6 +312,11 @@ struct ata_device {
 	u16			cylinders;	/* Number of cylinders */
 	u16			heads;		/* Number of heads */
 	u16			sectors;	/* Number of sectors per track */
+
+	/* ACPI objects info */
+	acpi_handle		obj_handle;
+	acpi_size		gtf_length;
+	u8			*gtf_address;
 };
 
 struct ata_port {



---

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

* [PATCH 4/6] SATA ACPI: call new ACPI functions
       [not found] <20051202100119.032b242e.randy_d_dunlap@linux.intel.com>
                   ` (2 preceding siblings ...)
  2005-12-02 18:05 ` [PATCH 3/6] SATA ACPI: libata.h changes Randy Dunlap
@ 2005-12-02 18:07 ` Randy Dunlap
  2005-12-02 18:07 ` [PATCH 5/6] SATA ACPI: kernel-doc Randy Dunlap
                   ` (2 subsequent siblings)
  6 siblings, 0 replies; 24+ messages in thread
From: Randy Dunlap @ 2005-12-02 18:07 UTC (permalink / raw)
  To: ide; +Cc: axboe, jgarzik

From: Randy Dunlap <randy_d_dunlap@linux.intel.com>

Add calls to ACPI methods for SATA drives.

Signed-off-by: Randy Dunlap <randy_d_dunlap@linux.intel.com>
---
 drivers/scsi/libata-core.c |    4 ++++
 drivers/scsi/libata.h      |    7 +++++++
 2 files changed, 11 insertions(+)

--- linux-2615-rc4.orig/drivers/scsi/libata-core.c
+++ linux-2615-rc4/drivers/scsi/libata-core.c
@@ -1345,6 +1345,8 @@ void ata_dev_config(struct ata_port *ap,
 
 	if (ap->ops->dev_config)
 		ap->ops->dev_config(ap, &ap->device[i]);
+
+	do_drive_SDD(ap, i);
 }
 
 /**
@@ -1784,6 +1786,8 @@ static void ata_set_mode(struct ata_port
 	if (ap->flags & ATA_FLAG_PORT_DISABLED)
 		return;
 
+	do_drive_update_taskfiles(ap);
+
 	if (ap->ops->post_set_mode)
 		ap->ops->post_set_mode(ap);
 
--- linux-2615-rc4.orig/drivers/scsi/libata.h
+++ linux-2615-rc4/drivers/scsi/libata.h
@@ -53,6 +53,13 @@ extern int ata_task_ioctl(struct scsi_de
 extern int ata_cmd_ioctl(struct scsi_device *scsidev, void __user *arg);
 
 
+/* ata_acpi.c */
+extern int do_drive_SDD(struct ata_port *ap, unsigned int ix);
+extern int do_drive_get_GTF(struct ata_port *ap, struct ata_device *atadev);
+extern int do_drive_set_taskfiles(struct ata_port *ap, struct ata_device *atadev);
+extern int do_drive_update_taskfiles(struct ata_port *ap);
+
+
 /* libata-scsi.c */
 extern void ata_scsi_scan_host(struct ata_port *ap);
 extern int ata_scsi_error(struct Scsi_Host *host);



---

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

* [PATCH 5/6] SATA ACPI: kernel-doc
       [not found] <20051202100119.032b242e.randy_d_dunlap@linux.intel.com>
                   ` (3 preceding siblings ...)
  2005-12-02 18:07 ` [PATCH 4/6] SATA ACPI: call new ACPI functions Randy Dunlap
@ 2005-12-02 18:07 ` Randy Dunlap
  2005-12-02 18:08 ` [PATCH 6/6] SATA ACPI: ata_acpi functions Randy Dunlap
  2005-12-02 18:15 ` [PATCH 0/6] SATA use ACPI methods for PM Randy Dunlap
  6 siblings, 0 replies; 24+ messages in thread
From: Randy Dunlap @ 2005-12-02 18:07 UTC (permalink / raw)
  To: ide; +Cc: axboe, jgarzik

From: Randy Dunlap <randy_d_dunlap@linux.intel.com>

Add ata_acpi.c to libata kernel-doc template file.

Signed-off-by: Randy Dunlap <randy_d_dunlap@linux.intel.com>
---
 Documentation/DocBook/libata.tmpl |    6 ++++++
 1 files changed, 6 insertions(+)

--- linux-2615-rc4.orig/Documentation/DocBook/libata.tmpl
+++ linux-2615-rc4/Documentation/DocBook/libata.tmpl
@@ -787,6 +787,12 @@ and other resources, etc.
 !Idrivers/scsi/libata-scsi.c
   </chapter>
 
+  <chapter id="libataAcpi">
+     <title>libata ACPI interfaces/methods</title>
+!Edrivers/scsi/ata_acpi.c
+!Idrivers/scsi/ata_acpi.c
+  </chapter>
+
   <chapter id="ataExceptions">
      <title>ATA errors &amp; exceptions</title>
 


---

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

* [PATCH 6/6] SATA ACPI: ata_acpi functions
       [not found] <20051202100119.032b242e.randy_d_dunlap@linux.intel.com>
                   ` (4 preceding siblings ...)
  2005-12-02 18:07 ` [PATCH 5/6] SATA ACPI: kernel-doc Randy Dunlap
@ 2005-12-02 18:08 ` Randy Dunlap
  2005-12-06 21:58   ` [PATCH 6/6 update] " Randy Dunlap
  2005-12-02 18:15 ` [PATCH 0/6] SATA use ACPI methods for PM Randy Dunlap
  6 siblings, 1 reply; 24+ messages in thread
From: Randy Dunlap @ 2005-12-02 18:08 UTC (permalink / raw)
  To: ide; +Cc: axboe, jgarzik

From: Randy Dunlap <randy_d_dunlap@linux.intel.com>

Add support for ACPI methods to SATA suspend/resume.

Signed-off-by: Randy Dunlap <randy_d_dunlap@linux.intel.com>
---
 drivers/scsi/ata_acpi.c |  488 ++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 488 insertions(+)

--- /dev/null
+++ linux-2615-rc4/drivers/scsi/ata_acpi.c
@@ -0,0 +1,488 @@
+/*
+ * ata-acpi.c
+ * Provides ACPI support for PATA/SATA.
+ *
+ * Copyright (C) 2005 Intel Corp.
+ * Copyright (C) 2005 Randy Dunlap
+ */
+
+#include <linux/ata.h>
+#include <linux/device.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <acpi/acpi.h>
+#include "scsi.h"
+#include <linux/libata.h>
+#include <linux/pci.h>
+#include "libata.h"
+
+#include <acpi/acpi_bus.h>
+#include <acpi/acnames.h>
+#include <acpi/acnamesp.h>
+#include <acpi/acparser.h>
+#include <acpi/acexcep.h>
+#include <acpi/acmacros.h>
+#include <acpi/actypes.h>
+
+#define SATA_ROOT_PORT(x)	(((x) >> 16) & 0xffff)
+#define SATA_PORT_NUMBER(x)	((x) & 0xffff)	/* or NO_PORT_MULT */
+#define NO_PORT_MULT		0xffff
+#define SATA_ADR_RSVD		0xffffffff
+
+#define REGS_PER_GTF		7
+struct taskfile_array {
+	u8	tfa[REGS_PER_GTF];	/* regs. 0x1f1 - 0x1f7 */
+};
+
+#define DEBUGGING	1
+/* note: adds function name and KERN_DEBUG */
+#ifdef DEBUGGING
+#define DEBPRINT(fmt, args...)	\
+		printk(KERN_DEBUG "%s: " fmt, __FUNCTION__, ## args)
+#else
+#define DEBPRINT(fmt, args...)	do {} while (0)
+#endif	/* DEBUGGING */
+
+static u8 *acpi_path_name(acpi_handle handle)
+{
+	acpi_status		status;
+	static u8		path_name[ACPI_PATHNAME_MAX];
+	struct acpi_buffer	ret_buf = { ACPI_PATHNAME_MAX, path_name };
+
+	memset(path_name, 0, sizeof (path_name));
+	status = acpi_get_name(handle, ACPI_FULL_PATHNAME, &ret_buf);
+
+	if (ACPI_FAILURE(status))
+		return NULL;
+
+	return path_name;
+}
+
+/**
+ * pci_acpi_get_dev_handle - finds acpi_handle and pci device.function
+ * @dev: device to locate
+ * @handle: returned acpi_handle for @dev
+ * @pcidevfn: return PCI device.func for @dev
+ *
+ * Returns 0 on success, <0 on error.
+ */
+static int pci_acpi_get_dev_handle(struct device *dev, acpi_handle *handle,
+					acpi_integer *pcidevfn)
+{
+	struct pci_dev	*pci_dev;
+	acpi_integer	addr;
+
+	pci_dev = to_pci_dev(dev);
+	/* Please refer to the ACPI spec for the syntax of _ADR. */
+	addr = (PCI_SLOT(pci_dev->devfn) << 16) | PCI_FUNC(pci_dev->devfn);
+	*pcidevfn = addr;
+	*handle = acpi_get_child(DEVICE_ACPI_HANDLE(dev->parent), addr);
+	DEBPRINT("pcidevfn: 0x%llx\n",
+		(unsigned long long)*pcidevfn);
+	if (!*handle)
+		return -ENODEV;
+	return 0;
+}
+
+struct walk_info {		/* can be trimmed some */
+	struct device	*dev;
+	struct acpi_device *adev;
+	acpi_handle	handle;
+	acpi_integer	pcidevfn;
+	unsigned int	drivenum;
+	acpi_handle	obj_handle;
+	struct ata_port *ataport;
+	struct ata_device *atadev;
+	u32		sata_adr;
+	int		status;
+	char		basepath[ACPI_PATHNAME_MAX];
+	int		basepath_len;
+};
+
+static acpi_status get_devices(acpi_handle handle,
+				u32 level, void *context, void **return_value)
+{
+	acpi_status		status;
+	struct walk_info	*winfo = context;
+	u8			*path_name = acpi_path_name(handle);
+	struct acpi_buffer	buffer;
+	struct acpi_device_info	*dinfo;
+
+	buffer.length = ACPI_ALLOCATE_LOCAL_BUFFER;
+	buffer.pointer = NULL;
+	status = acpi_get_object_info(handle, &buffer);
+
+	if (ACPI_SUCCESS(status)) {
+		dinfo = buffer.pointer;
+
+		/* find full device path name for pcidevfn */
+		if (dinfo && (dinfo->valid & ACPI_VALID_ADR) &&
+		    dinfo->address == winfo->pcidevfn) {
+			DEBPRINT(":%s: matches pcidevfn (0x%llx)\n",
+				path_name, winfo->pcidevfn);
+			strlcpy(winfo->basepath, path_name,
+				sizeof(winfo->basepath));
+			winfo->basepath_len = strlen(path_name);
+			goto out;
+		}
+
+		/* if basepath is not yet known, ignore this object */
+		if (!winfo->basepath_len)
+			goto out;
+
+		/* if this object is in scope of basepath, maybe use it */
+		if (strncmp(path_name, winfo->basepath,
+		    winfo->basepath_len) == 0) {
+			if (!(dinfo->valid & ACPI_VALID_ADR))
+				goto out;
+			DEBPRINT("GOT ONE: "
+				"(%s) root_port = 0x%llx, port_num = 0x%llx\n",
+				path_name,
+				SATA_ROOT_PORT(dinfo->address),
+				SATA_PORT_NUMBER(dinfo->address));
+			/* heuristics: */
+			if (SATA_PORT_NUMBER(dinfo->address) != NO_PORT_MULT)
+				DEBPRINT("warning: don't know how to handle SATA port multiplier\n");
+			if (SATA_ROOT_PORT(dinfo->address) ==
+				winfo->ataport->port_no &&
+			    SATA_PORT_NUMBER(dinfo->address) == NO_PORT_MULT) {
+				DEBPRINT("THIS ^^^^^ is the requested SATA drive (handle = 0x%p)\n",
+					handle);
+				winfo->sata_adr = dinfo->address;
+				winfo->obj_handle = handle;
+			}
+		}
+out:
+		ACPI_MEM_FREE(dinfo);
+	}
+
+	return status;
+}
+
+/* Get the SATA drive _ADR object. */
+static int get_sata_adr(struct device *dev, acpi_handle handle,
+			acpi_integer pcidevfn, unsigned int drive,
+			struct ata_port *ap,
+			struct ata_device *atadev, u32 *dev_adr)
+{
+	acpi_status	status;
+	struct walk_info *winfo;
+	int		err = -ENOMEM;
+
+	winfo = kzalloc(sizeof(struct walk_info), GFP_KERNEL);
+	if (!winfo)
+		goto out;
+
+	winfo->dev = dev;
+	winfo->atadev = atadev;
+	winfo->ataport = ap;
+	if (acpi_bus_get_device(handle, &winfo->adev) < 0)
+		DEBPRINT("acpi_bus_get_device failed\n");
+	winfo->handle = handle;
+	winfo->pcidevfn = pcidevfn;
+	winfo->drivenum = drive;
+
+	status = acpi_get_devices(NULL, get_devices, winfo, NULL);
+	if (ACPI_FAILURE(status))
+		err = -ENODEV;
+	else {
+		*dev_adr = winfo->sata_adr;
+		atadev->obj_handle = winfo->obj_handle;
+		err = 0;
+	}
+	kfree(winfo);
+out:
+	return err;
+}
+
+/**
+ * do_drive_SDD - send Identify data to a drive
+ * @ap: the ata_port for the drive
+ * @ix: drive index
+ *
+ * Must be after Identify (Packet) Device -- uses its data.
+ */
+int do_drive_SDD(struct ata_port *ap, unsigned int ix)
+{
+	acpi_handle			handle;
+	acpi_integer			pcidevfn;
+	int				err = -ENODEV;
+	struct device			*dev = ap->host_set->dev;
+	struct ata_device		*atadev = &ap->device[ix];
+	u32				dev_adr;
+	acpi_status			status;
+	struct acpi_object_list		input;
+	union acpi_object 		in_params[1];
+
+	printk(KERN_DEBUG
+		"%s: ap->id: %d, ix = %d, port#: %d, hard_port#: %d\n",
+		__FUNCTION__, ap->id, ix, ap->port_no, ap->hard_port_no);
+
+	/* Don't continue if not a SATA device. */
+	if (!ata_id_is_sata(atadev->id))
+		goto out;
+
+	/* Don't continue if device has no _ADR method.
+	 * _SDD is intended for known motherboard devices. */
+	err = pci_acpi_get_dev_handle(dev, &handle, &pcidevfn);
+	if (err < 0)
+		goto out;
+	/* Get this drive's _ADR info. */
+	dev_adr = SATA_ADR_RSVD;
+	err = get_sata_adr(dev, handle, pcidevfn, ix, ap, atadev, &dev_adr);
+	if (err < 0 || dev_adr == SATA_ADR_RSVD || atadev->obj_handle == NULL)
+		goto out;
+
+	/* Give the drive Identify data to the drive via the _SDD method */
+	/* _SDD: set up input parameters */
+	input.count = 1;
+	input.pointer = in_params;
+	in_params[0].type 		= ACPI_TYPE_BUFFER;
+	in_params[0].buffer.length 	= sizeof(atadev->id);
+	in_params[0].buffer.pointer	= (u8 *)atadev->id;
+	/* Output buffer: _SDD has no output */
+
+	/* It's OK for _SDD to be missing too. */
+	status = acpi_evaluate_object(atadev->obj_handle, "_SDD", &input, NULL);
+	err = ACPI_FAILURE(status) ? -EIO : 0;
+	if (err < 0) {
+		printk(KERN_DEBUG
+			"ata%u(%u): %s _SDD error: status = 0x%x\n",
+			ap->id, ap->device->devno, __FUNCTION__, status);
+	}
+out:
+	return err;
+}
+EXPORT_SYMBOL_GPL(do_drive_SDD);
+
+/**
+ * do_drive_get_GTF - get the drive bootup default taskfile settings
+ * @ap: the ata_port for the drive
+ * @atadev: target ata_device
+ *
+ * This applies to both PATA and SATA drives.
+ *
+ * The _GTF method has no input parameters.
+ * It returns a variable number of register set values (registers
+ * hex 1F1..1F7, taskfiles).
+ * The <variable number> is not known in advance, so have ACPI-CA
+ * allocate the buffer as needed and return it, then free it later.
+ *
+ */
+int do_drive_get_GTF(struct ata_port *ap, struct ata_device *atadev)
+{
+	acpi_status			status;
+	acpi_handle			handle;
+	acpi_integer			pcidevfn;
+	struct acpi_buffer		output;
+	union acpi_object 		*out_obj;
+	struct device			*dev = ap->host_set->dev;
+	int				err = -ENODEV;
+
+	if (!ata_dev_present(atadev))	/* or port disabled ? */
+		goto out;
+
+	/* Don't continue if device has no _ADR method.
+	 * _GTF is intended for known motherboard devices. */
+	err = pci_acpi_get_dev_handle(dev, &handle, &pcidevfn);
+	if (err < 0)
+		goto out;
+
+	/* Setting up output buffer */
+	output.length = ACPI_ALLOCATE_BUFFER;
+	output.pointer = NULL;	/* ACPI-CA sets this; save/free it later */
+
+	/* _GTF has no input parameters */
+	err = -EIO;
+	status = acpi_evaluate_object(atadev->obj_handle, "_GTF",
+					NULL, &output);
+	if (ACPI_FAILURE(status)) {
+		ACPI_MEM_FREE(output.pointer);
+		printk(KERN_DEBUG
+			"%s: Run _GTF error: status = 0x%x\n",
+			__FUNCTION__, status);
+		goto out;
+	}
+
+	if (!output.length || !output.pointer) {
+		printk(KERN_DEBUG
+			"%s: Run _GTF: length or ptr is NULL (0x%llx, 0x%p)\n",
+			__FUNCTION__,
+			(unsigned long long)output.length, output.pointer);
+		ACPI_MEM_FREE(output.pointer);
+		goto out;
+	}
+
+	out_obj = output.pointer;
+	if (out_obj->type != ACPI_TYPE_BUFFER) {
+		ACPI_MEM_FREE(output.pointer);
+		printk(KERN_DEBUG "%s: Run _GTF: error: "
+			"expected object type of ACPI_TYPE_BUFFER, got 0x%x\n",
+			__FUNCTION__, out_obj->type);
+		err = -ENOENT;
+		goto out;
+	}
+
+	atadev->gtf_length = out_obj->buffer.length;
+	atadev->gtf_address = out_obj->buffer.pointer;
+	err = 0;
+out:
+	return err;
+}
+EXPORT_SYMBOL_GPL(do_drive_get_GTF);
+
+/**
+ *	taskfile_load_raw - send taskfile registers to host controller
+ *	@ap: Port to which output is sent
+ *	@gtf: raw ATA taskfile register set (0x1f1 - 0x1f7)
+ *
+ *	Outputs ATA taskfile to standard ATA host controller using MMIO
+ *	or PIO as indicated by the ATA_FLAG_MMIO flag.
+ *	Writes the control, feature, nsect, lbal, lbam, and lbah registers.
+ *	Optionally (ATA_TFLAG_LBA48) writes hob_feature, hob_nsect,
+ *	hob_lbal, hob_lbam, and hob_lbah.
+ *
+ *	This function waits for idle (!BUSY and !DRQ) after writing
+ *	registers.  If the control register has a new value, this
+ *	function also waits for idle after writing control and before
+ *	writing the remaining registers.
+ *
+ *	LOCKING: TBD:
+ *	Inherited from caller.
+ */
+static void taskfile_load_raw(struct ata_port *ap,
+				struct ata_device *atadev,
+				const struct taskfile_array *gtf)
+{
+	DEBPRINT("(0x1f1-1f7): hex: %02x %02x %02x %02x %02x %02x %02x\n",
+		gtf->tfa[0], gtf->tfa[1], gtf->tfa[2],
+		gtf->tfa[3], gtf->tfa[4], gtf->tfa[5], gtf->tfa[6]);
+
+	if (ap->ops->tf_load && ap->ops->exec_command) {
+		struct ata_taskfile atf;
+
+		/* convert gtf to atf */
+		ata_tf_init(ap, &atf, 0);
+		atf.flags = ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE; /* TBD */
+		atf.protocol = ATA_PROT_NODATA; /* or ATA_PROT_ATAPI_NODATA */
+		atf.feature = gtf->tfa[0];	/* 0x1f1 */
+		atf.nsect   = gtf->tfa[1];	/* 0x1f2 */
+		atf.lbal    = gtf->tfa[2];	/* 0x1f3 */
+		atf.lbam    = gtf->tfa[3];	/* 0x1f4 */
+		atf.lbah    = gtf->tfa[4];	/* 0x1f5 */
+		atf.device  = gtf->tfa[5];	/* 0x1f6 */
+		atf.command = gtf->tfa[6];	/* 0x1f7 */
+
+		DEBPRINT("call tf_load:\n");
+		ap->ops->tf_load(ap, &atf);
+		DEBPRINT("call exec_command:\n");
+		ap->ops->exec_command(ap, &atf);
+		DEBPRINT("tf_load & exec_command done.\n");
+	} else if (ap->ops->qc_issue && ap->ops->qc_prep) {
+		int ret;
+		struct ata_queued_cmd *qc;
+		unsigned long flags;
+		DECLARE_COMPLETION(wait);
+
+		qc = ata_qc_new_init(ap, atadev);
+		if (!qc) {
+			printk(KERN_DEBUG "%s: ata_qc_new_init ret. NULL\n",
+				__FUNCTION__);
+			return;
+		}
+
+		/* convert gtf to qc.tf */
+		qc->tf.flags = ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE; /* TBD */
+		qc->tf.protocol = ATA_PROT_NODATA; /* or ATA_PROT_ATAPI_NODATA */
+		qc->tf.feature = gtf->tfa[0];	/* 0x1f1 */
+		qc->tf.nsect   = gtf->tfa[1];	/* 0x1f2 */
+		qc->tf.lbal    = gtf->tfa[2];	/* 0x1f3 */
+		qc->tf.lbam    = gtf->tfa[3];	/* 0x1f4 */
+		qc->tf.lbah    = gtf->tfa[4];	/* 0x1f5 */
+		qc->tf.device  = gtf->tfa[5];	/* 0x1f6 */
+		qc->tf.command = gtf->tfa[6];	/* 0x1f7 */
+
+		qc->waiting = &wait;
+		qc->complete_fn = ata_qc_complete_noop;
+
+		// TBD: fix locking and return value/wait_for_completion here:
+		DEBPRINT("call ata_qc_issue:\n");
+		spin_lock_irqsave(&ap->host_set->lock, flags);
+		ret = ata_qc_issue(qc);
+		spin_unlock_irqrestore(&ap->host_set->lock, flags);
+		DEBPRINT("ata_qc_issue done: ret = 0x%x\n", ret);
+
+		if (!ret)
+			wait_for_completion(&wait);
+	} else
+		printk(KERN_WARNING "%s: SATA driver is missing tf_load/exec_command or qc_issue function entry points\n",
+			__FUNCTION__);
+}
+
+/**
+ * do_drive_set_taskfiles - write the drive taskfile settings from _GTF
+ * @ap: the ata_port for the drive
+ * @atadev: target ata_device
+ *
+ * This applies to both PATA and SATA drives.
+ *
+ * Write {atadev->gtf_address, length atadev->gtf_length} in groups of
+ * REGS_PER_GTF bytes.
+ *
+ */
+int do_drive_set_taskfiles(struct ata_port *ap, struct ata_device *atadev)
+{
+	int				err = -ENODEV;
+	int				gtf_count =
+					atadev->gtf_length / REGS_PER_GTF;
+	int				ix;
+	struct taskfile_array		*gtf;
+
+	if (!ata_dev_present(atadev))	/* or port disabled ? */
+		goto out;
+	if (!gtf_count)		/* shouldn't be here */
+		goto out;
+
+	DEBPRINT("total GTF bytes = %lld (0x%llx), gtf_count = %d\n",
+		(unsigned long long)atadev->gtf_length,
+		(unsigned long long)atadev->gtf_length, gtf_count);
+	if (atadev->gtf_length % REGS_PER_GTF) {
+		printk(KERN_ERR "%s: unexpected GTF length (%zd)\n",
+			__FUNCTION__, atadev->gtf_length);
+		goto out;
+	}
+
+	for (ix = 0; ix < gtf_count; ix++) {
+		gtf = (struct taskfile_array *)
+			(atadev->gtf_address + ix * REGS_PER_GTF);
+
+		/* send all TaskFile registers (0x1f1-0x1f7) *in*that*order* */
+		taskfile_load_raw(ap, atadev, gtf);
+	}
+
+	err = 0;
+out:
+	return err;
+}
+EXPORT_SYMBOL_GPL(do_drive_set_taskfiles);
+
+/**
+ * do_drive_update_taskfiles - get then write drive taskfile settings
+ * @ap: the ata_port for the drive
+ *
+ * This applies to both PATA and SATA drives.
+ */
+int do_drive_update_taskfiles(struct ata_port *ap)
+{
+	int ix;
+	int ret;
+
+	for (ix = 0; ix < ATA_MAX_DEVICES; ix++) {
+		ret = do_drive_get_GTF(ap, &ap->device[ix]);
+		if (ret >= 0)
+			ret = do_drive_set_taskfiles(ap, &ap->device[ix]);
+	}
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(do_drive_update_taskfiles);


---

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

* Re: [PATCH 0/6] SATA use ACPI methods for PM
       [not found] <20051202100119.032b242e.randy_d_dunlap@linux.intel.com>
                   ` (5 preceding siblings ...)
  2005-12-02 18:08 ` [PATCH 6/6] SATA ACPI: ata_acpi functions Randy Dunlap
@ 2005-12-02 18:15 ` Randy Dunlap
  6 siblings, 0 replies; 24+ messages in thread
From: Randy Dunlap @ 2005-12-02 18:15 UTC (permalink / raw)
  To: ide; +Cc: axboe, jgarzik


more comments:

Yes, the patch still contains some debugging code.
If you try it out and have problems, please give me as much of
the debug output as possible.  It is likely that I will also
want to see your ACPI tables.  To dump those, use
'acpidump' from the latest pmtools release at:
  http://www.kernel.org/pub/linux/kernel/people/lenb/acpi/utils/

The patch series is available at:
  http://www.xenotime.net/linux/SATA/2.6.15-rc/

---
~Randy

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

* [PATCH 6/6 update] SATA ACPI: ata_acpi functions
  2005-12-02 18:08 ` [PATCH 6/6] SATA ACPI: ata_acpi functions Randy Dunlap
@ 2005-12-06 21:58   ` Randy Dunlap
  2005-12-07 16:36     ` Dominic Ijichi
  0 siblings, 1 reply; 24+ messages in thread
From: Randy Dunlap @ 2005-12-06 21:58 UTC (permalink / raw)
  To: ide; +Cc: axboe, jgarzik

From: Randy Dunlap <randy_d_dunlap@linux.intel.com>

Add support for ACPI methods to SATA suspend/resume.
do_drive_get_GTF() is changed to get the ACPI obj_handle
in case do_drive_SDD() did not set that value.


Signed-off-by: Randy Dunlap <randy_d_dunlap@linux.intel.com>
---

All patch files are available at
  http://www.xenotime.net/linux/SATA/2.6.15-rc/


 drivers/scsi/ata_acpi.c |  497 ++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 497 insertions(+)

--- /dev/null
+++ linux-2615-rc4/drivers/scsi/ata_acpi.c
@@ -0,0 +1,497 @@
+/*
+ * ata-acpi.c
+ * Provides ACPI support for PATA/SATA.
+ *
+ * Copyright (C) 2005 Intel Corp.
+ * Copyright (C) 2005 Randy Dunlap
+ */
+
+#include <linux/ata.h>
+#include <linux/device.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <acpi/acpi.h>
+#include "scsi.h"
+#include <linux/libata.h>
+#include <linux/pci.h>
+#include "libata.h"
+
+#include <acpi/acpi_bus.h>
+#include <acpi/acnames.h>
+#include <acpi/acnamesp.h>
+#include <acpi/acparser.h>
+#include <acpi/acexcep.h>
+#include <acpi/acmacros.h>
+#include <acpi/actypes.h>
+
+#define SATA_ROOT_PORT(x)	(((x) >> 16) & 0xffff)
+#define SATA_PORT_NUMBER(x)	((x) & 0xffff)	/* or NO_PORT_MULT */
+#define NO_PORT_MULT		0xffff
+#define SATA_ADR_RSVD		0xffffffff
+
+#define REGS_PER_GTF		7
+struct taskfile_array {
+	u8	tfa[REGS_PER_GTF];	/* regs. 0x1f1 - 0x1f7 */
+};
+
+#define DEBUGGING	1
+/* note: adds function name and KERN_DEBUG */
+#ifdef DEBUGGING
+#define DEBPRINT(fmt, args...)	\
+		printk(KERN_DEBUG "%s: " fmt, __FUNCTION__, ## args)
+#else
+#define DEBPRINT(fmt, args...)	do {} while (0)
+#endif	/* DEBUGGING */
+
+static u8 *acpi_path_name(acpi_handle handle)
+{
+	acpi_status		status;
+	static u8		path_name[ACPI_PATHNAME_MAX];
+	struct acpi_buffer	ret_buf = { ACPI_PATHNAME_MAX, path_name };
+
+	memset(path_name, 0, sizeof (path_name));
+	status = acpi_get_name(handle, ACPI_FULL_PATHNAME, &ret_buf);
+
+	if (ACPI_FAILURE(status))
+		return NULL;
+
+	return path_name;
+}
+
+/**
+ * pci_acpi_get_dev_handle - finds acpi_handle and pci device.function
+ * @dev: device to locate
+ * @handle: returned acpi_handle for @dev
+ * @pcidevfn: return PCI device.func for @dev
+ *
+ * Returns 0 on success, <0 on error.
+ */
+static int pci_acpi_get_dev_handle(struct device *dev, acpi_handle *handle,
+					acpi_integer *pcidevfn)
+{
+	struct pci_dev	*pci_dev;
+	acpi_integer	addr;
+
+	pci_dev = to_pci_dev(dev);
+	/* Please refer to the ACPI spec for the syntax of _ADR. */
+	addr = (PCI_SLOT(pci_dev->devfn) << 16) | PCI_FUNC(pci_dev->devfn);
+	*pcidevfn = addr;
+	*handle = acpi_get_child(DEVICE_ACPI_HANDLE(dev->parent), addr);
+	DEBPRINT("pcidevfn: 0x%llx\n",
+		(unsigned long long)*pcidevfn);
+	if (!*handle)
+		return -ENODEV;
+	return 0;
+}
+
+struct walk_info {		/* can be trimmed some */
+	struct device	*dev;
+	struct acpi_device *adev;
+	acpi_handle	handle;
+	acpi_integer	pcidevfn;
+	unsigned int	drivenum;
+	acpi_handle	obj_handle;
+	struct ata_port *ataport;
+	struct ata_device *atadev;
+	u32		sata_adr;
+	int		status;
+	char		basepath[ACPI_PATHNAME_MAX];
+	int		basepath_len;
+};
+
+static acpi_status get_devices(acpi_handle handle,
+				u32 level, void *context, void **return_value)
+{
+	acpi_status		status;
+	struct walk_info	*winfo = context;
+	u8			*path_name = acpi_path_name(handle);
+	struct acpi_buffer	buffer;
+	struct acpi_device_info	*dinfo;
+
+	buffer.length = ACPI_ALLOCATE_LOCAL_BUFFER;
+	buffer.pointer = NULL;
+	status = acpi_get_object_info(handle, &buffer);
+
+	if (ACPI_SUCCESS(status)) {
+		dinfo = buffer.pointer;
+
+		/* find full device path name for pcidevfn */
+		if (dinfo && (dinfo->valid & ACPI_VALID_ADR) &&
+		    dinfo->address == winfo->pcidevfn) {
+			DEBPRINT(":%s: matches pcidevfn (0x%llx)\n",
+				path_name, winfo->pcidevfn);
+			strlcpy(winfo->basepath, path_name,
+				sizeof(winfo->basepath));
+			winfo->basepath_len = strlen(path_name);
+			goto out;
+		}
+
+		/* if basepath is not yet known, ignore this object */
+		if (!winfo->basepath_len)
+			goto out;
+
+		/* if this object is in scope of basepath, maybe use it */
+		if (strncmp(path_name, winfo->basepath,
+		    winfo->basepath_len) == 0) {
+			if (!(dinfo->valid & ACPI_VALID_ADR))
+				goto out;
+			DEBPRINT("GOT ONE: "
+				"(%s) root_port = 0x%llx, port_num = 0x%llx\n",
+				path_name,
+				SATA_ROOT_PORT(dinfo->address),
+				SATA_PORT_NUMBER(dinfo->address));
+			/* heuristics: */
+			if (SATA_PORT_NUMBER(dinfo->address) != NO_PORT_MULT)
+				DEBPRINT("warning: don't know how to handle SATA port multiplier\n");
+			if (SATA_ROOT_PORT(dinfo->address) ==
+				winfo->ataport->port_no &&
+			    SATA_PORT_NUMBER(dinfo->address) == NO_PORT_MULT) {
+				DEBPRINT("THIS ^^^^^ is the requested SATA drive (handle = 0x%p)\n",
+					handle);
+				winfo->sata_adr = dinfo->address;
+				winfo->obj_handle = handle;
+			}
+		}
+out:
+		ACPI_MEM_FREE(dinfo);
+	}
+
+	return status;
+}
+
+/* Get the SATA drive _ADR object. */
+static int get_sata_adr(struct device *dev, acpi_handle handle,
+			acpi_integer pcidevfn, unsigned int drive,
+			struct ata_port *ap,
+			struct ata_device *atadev, u32 *dev_adr)
+{
+	acpi_status	status;
+	struct walk_info *winfo;
+	int		err = -ENOMEM;
+
+	winfo = kzalloc(sizeof(struct walk_info), GFP_KERNEL);
+	if (!winfo)
+		goto out;
+
+	winfo->dev = dev;
+	winfo->atadev = atadev;
+	winfo->ataport = ap;
+	if (acpi_bus_get_device(handle, &winfo->adev) < 0)
+		DEBPRINT("acpi_bus_get_device failed\n");
+	winfo->handle = handle;
+	winfo->pcidevfn = pcidevfn;
+	winfo->drivenum = drive;
+
+	status = acpi_get_devices(NULL, get_devices, winfo, NULL);
+	if (ACPI_FAILURE(status))
+		err = -ENODEV;
+	else {
+		*dev_adr = winfo->sata_adr;
+		atadev->obj_handle = winfo->obj_handle;
+		err = 0;
+	}
+	kfree(winfo);
+out:
+	return err;
+}
+
+/**
+ * do_drive_SDD - send Identify data to a drive
+ * @ap: the ata_port for the drive
+ * @ix: drive index
+ *
+ * Must be after Identify (Packet) Device -- uses its data.
+ */
+int do_drive_SDD(struct ata_port *ap, unsigned int ix)
+{
+	acpi_handle			handle;
+	acpi_integer			pcidevfn;
+	int				err = -ENODEV;
+	struct device			*dev = ap->host_set->dev;
+	struct ata_device		*atadev = &ap->device[ix];
+	u32				dev_adr;
+	acpi_status			status;
+	struct acpi_object_list		input;
+	union acpi_object 		in_params[1];
+
+	printk(KERN_DEBUG
+		"%s: ap->id: %d, ix = %d, port#: %d, hard_port#: %d\n",
+		__FUNCTION__, ap->id, ix, ap->port_no, ap->hard_port_no);
+
+	/* Don't continue if not a SATA device. */
+	if (!ata_id_is_sata(atadev->id))
+		goto out;
+
+	/* Don't continue if device has no _ADR method.
+	 * _SDD is intended for known motherboard devices. */
+	err = pci_acpi_get_dev_handle(dev, &handle, &pcidevfn);
+	if (err < 0)
+		goto out;
+	/* Get this drive's _ADR info. */
+	dev_adr = SATA_ADR_RSVD;
+	err = get_sata_adr(dev, handle, pcidevfn, ix, ap, atadev, &dev_adr);
+	if (err < 0 || dev_adr == SATA_ADR_RSVD || !atadev->obj_handle)
+		goto out;
+
+	/* Give the drive Identify data to the drive via the _SDD method */
+	/* _SDD: set up input parameters */
+	input.count = 1;
+	input.pointer = in_params;
+	in_params[0].type 		= ACPI_TYPE_BUFFER;
+	in_params[0].buffer.length 	= sizeof(atadev->id);
+	in_params[0].buffer.pointer	= (u8 *)atadev->id;
+	/* Output buffer: _SDD has no output */
+
+	/* It's OK for _SDD to be missing too. */
+	status = acpi_evaluate_object(atadev->obj_handle, "_SDD", &input, NULL);
+	err = ACPI_FAILURE(status) ? -EIO : 0;
+	if (err < 0) {
+		printk(KERN_DEBUG
+			"ata%u(%u): %s _SDD error: status = 0x%x\n",
+			ap->id, ap->device->devno, __FUNCTION__, status);
+	}
+out:
+	return err;
+}
+EXPORT_SYMBOL_GPL(do_drive_SDD);
+
+/**
+ * do_drive_get_GTF - get the drive bootup default taskfile settings
+ * @ap: the ata_port for the drive
+ * @atadev: target ata_device
+ *
+ * This applies to both PATA and SATA drives.
+ *
+ * The _GTF method has no input parameters.
+ * It returns a variable number of register set values (registers
+ * hex 1F1..1F7, taskfiles).
+ * The <variable number> is not known in advance, so have ACPI-CA
+ * allocate the buffer as needed and return it, then free it later.
+ *
+ */
+int do_drive_get_GTF(struct ata_port *ap, struct ata_device *atadev)
+{
+	acpi_status			status;
+	acpi_handle			handle;
+	acpi_integer			pcidevfn;
+	u32				dev_adr;
+	struct acpi_buffer		output;
+	union acpi_object 		*out_obj;
+	struct device			*dev = ap->host_set->dev;
+	int				err = -ENODEV;
+
+	if (!ata_dev_present(atadev))	/* or port disabled ? */
+		goto out;
+
+	/* Don't continue if device has no _ADR method.
+	 * _GTF is intended for known motherboard devices. */
+	err = pci_acpi_get_dev_handle(dev, &handle, &pcidevfn);
+	if (err < 0)
+		goto out;
+
+	/* Get this drive's _ADR info. if _SDD didn't get it. */
+	if (!atadev->obj_handle) {
+		dev_adr = SATA_ADR_RSVD;
+		err = get_sata_adr(dev, handle, pcidevfn, 0, ap, atadev, &dev_adr);
+		if (err < 0 || dev_adr == SATA_ADR_RSVD || !atadev->obj_handle)
+			goto out;
+	}
+
+	/* Setting up output buffer */
+	output.length = ACPI_ALLOCATE_BUFFER;
+	output.pointer = NULL;	/* ACPI-CA sets this; save/free it later */
+
+	/* _GTF has no input parameters */
+	err = -EIO;
+	status = acpi_evaluate_object(atadev->obj_handle, "_GTF",
+					NULL, &output);
+	if (ACPI_FAILURE(status)) {
+		ACPI_MEM_FREE(output.pointer);
+		printk(KERN_DEBUG
+			"%s: Run _GTF error: status = 0x%x\n",
+			__FUNCTION__, status);
+		goto out;
+	}
+
+	if (!output.length || !output.pointer) {
+		printk(KERN_DEBUG
+			"%s: Run _GTF: length or ptr is NULL (0x%llx, 0x%p)\n",
+			__FUNCTION__,
+			(unsigned long long)output.length, output.pointer);
+		ACPI_MEM_FREE(output.pointer);
+		goto out;
+	}
+
+	out_obj = output.pointer;
+	if (out_obj->type != ACPI_TYPE_BUFFER) {
+		ACPI_MEM_FREE(output.pointer);
+		printk(KERN_DEBUG "%s: Run _GTF: error: "
+			"expected object type of ACPI_TYPE_BUFFER, got 0x%x\n",
+			__FUNCTION__, out_obj->type);
+		err = -ENOENT;
+		goto out;
+	}
+
+	atadev->gtf_length = out_obj->buffer.length;
+	atadev->gtf_address = out_obj->buffer.pointer;
+	err = 0;
+out:
+	return err;
+}
+EXPORT_SYMBOL_GPL(do_drive_get_GTF);
+
+/**
+ *	taskfile_load_raw - send taskfile registers to host controller
+ *	@ap: Port to which output is sent
+ *	@gtf: raw ATA taskfile register set (0x1f1 - 0x1f7)
+ *
+ *	Outputs ATA taskfile to standard ATA host controller using MMIO
+ *	or PIO as indicated by the ATA_FLAG_MMIO flag.
+ *	Writes the control, feature, nsect, lbal, lbam, and lbah registers.
+ *	Optionally (ATA_TFLAG_LBA48) writes hob_feature, hob_nsect,
+ *	hob_lbal, hob_lbam, and hob_lbah.
+ *
+ *	This function waits for idle (!BUSY and !DRQ) after writing
+ *	registers.  If the control register has a new value, this
+ *	function also waits for idle after writing control and before
+ *	writing the remaining registers.
+ *
+ *	LOCKING: TBD:
+ *	Inherited from caller.
+ */
+static void taskfile_load_raw(struct ata_port *ap,
+				struct ata_device *atadev,
+				const struct taskfile_array *gtf)
+{
+	DEBPRINT("(0x1f1-1f7): hex: %02x %02x %02x %02x %02x %02x %02x\n",
+		gtf->tfa[0], gtf->tfa[1], gtf->tfa[2],
+		gtf->tfa[3], gtf->tfa[4], gtf->tfa[5], gtf->tfa[6]);
+
+	if (ap->ops->tf_load && ap->ops->exec_command) {
+		struct ata_taskfile atf;
+
+		/* convert gtf to atf */
+		ata_tf_init(ap, &atf, 0);
+		atf.flags = ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE; /* TBD */
+		atf.protocol = ATA_PROT_NODATA; /* or ATA_PROT_ATAPI_NODATA */
+		atf.feature = gtf->tfa[0];	/* 0x1f1 */
+		atf.nsect   = gtf->tfa[1];	/* 0x1f2 */
+		atf.lbal    = gtf->tfa[2];	/* 0x1f3 */
+		atf.lbam    = gtf->tfa[3];	/* 0x1f4 */
+		atf.lbah    = gtf->tfa[4];	/* 0x1f5 */
+		atf.device  = gtf->tfa[5];	/* 0x1f6 */
+		atf.command = gtf->tfa[6];	/* 0x1f7 */
+
+		DEBPRINT("call tf_load:\n");
+		ap->ops->tf_load(ap, &atf);
+		DEBPRINT("call exec_command:\n");
+		ap->ops->exec_command(ap, &atf);
+		DEBPRINT("tf_load & exec_command done.\n");
+	} else if (ap->ops->qc_issue && ap->ops->qc_prep) {
+		int ret;
+		struct ata_queued_cmd *qc;
+		unsigned long flags;
+		DECLARE_COMPLETION(wait);
+
+		qc = ata_qc_new_init(ap, atadev);
+		if (!qc) {
+			printk(KERN_DEBUG "%s: ata_qc_new_init ret. NULL\n",
+				__FUNCTION__);
+			return;
+		}
+
+		/* convert gtf to qc.tf */
+		qc->tf.flags = ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE; /* TBD */
+		qc->tf.protocol = ATA_PROT_NODATA; /* or ATA_PROT_ATAPI_NODATA */
+		qc->tf.feature = gtf->tfa[0];	/* 0x1f1 */
+		qc->tf.nsect   = gtf->tfa[1];	/* 0x1f2 */
+		qc->tf.lbal    = gtf->tfa[2];	/* 0x1f3 */
+		qc->tf.lbam    = gtf->tfa[3];	/* 0x1f4 */
+		qc->tf.lbah    = gtf->tfa[4];	/* 0x1f5 */
+		qc->tf.device  = gtf->tfa[5];	/* 0x1f6 */
+		qc->tf.command = gtf->tfa[6];	/* 0x1f7 */
+
+		qc->waiting = &wait;
+		qc->complete_fn = ata_qc_complete_noop;
+
+		// TBD: fix locking and return value/wait_for_completion here:
+		DEBPRINT("call ata_qc_issue:\n");
+		spin_lock_irqsave(&ap->host_set->lock, flags);
+		ret = ata_qc_issue(qc);
+		spin_unlock_irqrestore(&ap->host_set->lock, flags);
+		DEBPRINT("ata_qc_issue done: ret = 0x%x\n", ret);
+
+		if (!ret)
+			wait_for_completion(&wait);
+	} else
+		printk(KERN_WARNING "%s: SATA driver is missing tf_load/exec_command or qc_issue function entry points\n",
+			__FUNCTION__);
+}
+
+/**
+ * do_drive_set_taskfiles - write the drive taskfile settings from _GTF
+ * @ap: the ata_port for the drive
+ * @atadev: target ata_device
+ *
+ * This applies to both PATA and SATA drives.
+ *
+ * Write {atadev->gtf_address, length atadev->gtf_length} in groups of
+ * REGS_PER_GTF bytes.
+ *
+ */
+int do_drive_set_taskfiles(struct ata_port *ap, struct ata_device *atadev)
+{
+	int				err = -ENODEV;
+	int				gtf_count =
+					atadev->gtf_length / REGS_PER_GTF;
+	int				ix;
+	struct taskfile_array		*gtf;
+
+	if (!ata_dev_present(atadev))	/* or port disabled ? */
+		goto out;
+	if (!gtf_count)		/* shouldn't be here */
+		goto out;
+
+	DEBPRINT("total GTF bytes = %lld (0x%llx), gtf_count = %d\n",
+		(unsigned long long)atadev->gtf_length,
+		(unsigned long long)atadev->gtf_length, gtf_count);
+	if (atadev->gtf_length % REGS_PER_GTF) {
+		printk(KERN_ERR "%s: unexpected GTF length (%zd)\n",
+			__FUNCTION__, atadev->gtf_length);
+		goto out;
+	}
+
+	for (ix = 0; ix < gtf_count; ix++) {
+		gtf = (struct taskfile_array *)
+			(atadev->gtf_address + ix * REGS_PER_GTF);
+
+		/* send all TaskFile registers (0x1f1-0x1f7) *in*that*order* */
+		taskfile_load_raw(ap, atadev, gtf);
+	}
+
+	err = 0;
+out:
+	return err;
+}
+EXPORT_SYMBOL_GPL(do_drive_set_taskfiles);
+
+/**
+ * do_drive_update_taskfiles - get then write drive taskfile settings
+ * @ap: the ata_port for the drive
+ *
+ * This applies to both PATA and SATA drives.
+ */
+int do_drive_update_taskfiles(struct ata_port *ap)
+{
+	int ix;
+	int ret;
+
+	for (ix = 0; ix < ATA_MAX_DEVICES; ix++) {
+		ret = do_drive_get_GTF(ap, &ap->device[ix]);
+		if (ret >= 0)
+			ret = do_drive_set_taskfiles(ap, &ap->device[ix]);
+	}
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(do_drive_update_taskfiles);

---

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

* Re: [PATCH 6/6 update] SATA ACPI: ata_acpi functions
  2005-12-06 21:58   ` [PATCH 6/6 update] " Randy Dunlap
@ 2005-12-07 16:36     ` Dominic Ijichi
  2005-12-07 17:16       ` Randy Dunlap
  0 siblings, 1 reply; 24+ messages in thread
From: Dominic Ijichi @ 2005-12-07 16:36 UTC (permalink / raw)
  To: Randy Dunlap; +Cc: ide, axboe, jgarzik

I get a segfault when applying these patches to 2.6.15-rc4.  ahci compiled as
module and inserted through initrd so the module fails with segfault and kernel
doesnt go any further through boot, hence no logging.  last thing screen shows is:

Code: e3 36 34 c0 c7 44 24 18 29 02 00 00 59 5b 5e 5f 5d e9 f3 05 00 00 53 8b 5c
2408 e8 e9 03 00 00 a1 dc 0c 42 c0 eb 04 39 d8 74 07 <8b> 40 04 85 c0 75 f5 5b
c3 55 57 56 53 50 8b 44 24 20 8b 5c 24

also, is there a working archive for this list?  the MARC archive died on 25th
november.


Quoting Randy Dunlap <randy_d_dunlap@linux.intel.com>:

> From: Randy Dunlap <randy_d_dunlap@linux.intel.com>
> 
> Add support for ACPI methods to SATA suspend/resume.
> do_drive_get_GTF() is changed to get the ACPI obj_handle
> in case do_drive_SDD() did not set that value.
> 
> 
> Signed-off-by: Randy Dunlap <randy_d_dunlap@linux.intel.com>
> ---
> 
> All patch files are available at
>   http://www.xenotime.net/linux/SATA/2.6.15-rc/
> 
> 
>  drivers/scsi/ata_acpi.c |  497
> ++++++++++++++++++++++++++++++++++++++++++++++++
>  1 files changed, 497 insertions(+)
> 
> --- /dev/null
> +++ linux-2615-rc4/drivers/scsi/ata_acpi.c
> @@ -0,0 +1,497 @@
> +/*
> + * ata-acpi.c
> + * Provides ACPI support for PATA/SATA.
> + *
> + * Copyright (C) 2005 Intel Corp.
> + * Copyright (C) 2005 Randy Dunlap
> + */
> +
> +#include <linux/ata.h>
> +#include <linux/device.h>
> +#include <linux/errno.h>
> +#include <linux/kernel.h>
> +#include <acpi/acpi.h>
> +#include "scsi.h"
> +#include <linux/libata.h>
> +#include <linux/pci.h>
> +#include "libata.h"
> +
> +#include <acpi/acpi_bus.h>
> +#include <acpi/acnames.h>
> +#include <acpi/acnamesp.h>
> +#include <acpi/acparser.h>
> +#include <acpi/acexcep.h>
> +#include <acpi/acmacros.h>
> +#include <acpi/actypes.h>
> +
> +#define SATA_ROOT_PORT(x)	(((x) >> 16) & 0xffff)
> +#define SATA_PORT_NUMBER(x)	((x) & 0xffff)	/* or NO_PORT_MULT */
> +#define NO_PORT_MULT		0xffff
> +#define SATA_ADR_RSVD		0xffffffff
> +
> +#define REGS_PER_GTF		7
> +struct taskfile_array {
> +	u8	tfa[REGS_PER_GTF];	/* regs. 0x1f1 - 0x1f7 */
> +};
> +
> +#define DEBUGGING	1
> +/* note: adds function name and KERN_DEBUG */
> +#ifdef DEBUGGING
> +#define DEBPRINT(fmt, args...)	\
> +		printk(KERN_DEBUG "%s: " fmt, __FUNCTION__, ## args)
> +#else
> +#define DEBPRINT(fmt, args...)	do {} while (0)
> +#endif	/* DEBUGGING */
> +
> +static u8 *acpi_path_name(acpi_handle handle)
> +{
> +	acpi_status		status;
> +	static u8		path_name[ACPI_PATHNAME_MAX];
> +	struct acpi_buffer	ret_buf = { ACPI_PATHNAME_MAX, path_name };
> +
> +	memset(path_name, 0, sizeof (path_name));
> +	status = acpi_get_name(handle, ACPI_FULL_PATHNAME, &ret_buf);
> +
> +	if (ACPI_FAILURE(status))
> +		return NULL;
> +
> +	return path_name;
> +}
> +
> +/**
> + * pci_acpi_get_dev_handle - finds acpi_handle and pci device.function
> + * @dev: device to locate
> + * @handle: returned acpi_handle for @dev
> + * @pcidevfn: return PCI device.func for @dev
> + *
> + * Returns 0 on success, <0 on error.
> + */
> +static int pci_acpi_get_dev_handle(struct device *dev, acpi_handle *handle,
> +					acpi_integer *pcidevfn)
> +{
> +	struct pci_dev	*pci_dev;
> +	acpi_integer	addr;
> +
> +	pci_dev = to_pci_dev(dev);
> +	/* Please refer to the ACPI spec for the syntax of _ADR. */
> +	addr = (PCI_SLOT(pci_dev->devfn) << 16) | PCI_FUNC(pci_dev->devfn);
> +	*pcidevfn = addr;
> +	*handle = acpi_get_child(DEVICE_ACPI_HANDLE(dev->parent), addr);
> +	DEBPRINT("pcidevfn: 0x%llx\n",
> +		(unsigned long long)*pcidevfn);
> +	if (!*handle)
> +		return -ENODEV;
> +	return 0;
> +}
> +
> +struct walk_info {		/* can be trimmed some */
> +	struct device	*dev;
> +	struct acpi_device *adev;
> +	acpi_handle	handle;
> +	acpi_integer	pcidevfn;
> +	unsigned int	drivenum;
> +	acpi_handle	obj_handle;
> +	struct ata_port *ataport;
> +	struct ata_device *atadev;
> +	u32		sata_adr;
> +	int		status;
> +	char		basepath[ACPI_PATHNAME_MAX];
> +	int		basepath_len;
> +};
> +
> +static acpi_status get_devices(acpi_handle handle,
> +				u32 level, void *context, void **return_value)
> +{
> +	acpi_status		status;
> +	struct walk_info	*winfo = context;
> +	u8			*path_name = acpi_path_name(handle);
> +	struct acpi_buffer	buffer;
> +	struct acpi_device_info	*dinfo;
> +
> +	buffer.length = ACPI_ALLOCATE_LOCAL_BUFFER;
> +	buffer.pointer = NULL;
> +	status = acpi_get_object_info(handle, &buffer);
> +
> +	if (ACPI_SUCCESS(status)) {
> +		dinfo = buffer.pointer;
> +
> +		/* find full device path name for pcidevfn */
> +		if (dinfo && (dinfo->valid & ACPI_VALID_ADR) &&
> +		    dinfo->address == winfo->pcidevfn) {
> +			DEBPRINT(":%s: matches pcidevfn (0x%llx)\n",
> +				path_name, winfo->pcidevfn);
> +			strlcpy(winfo->basepath, path_name,
> +				sizeof(winfo->basepath));
> +			winfo->basepath_len = strlen(path_name);
> +			goto out;
> +		}
> +
> +		/* if basepath is not yet known, ignore this object */
> +		if (!winfo->basepath_len)
> +			goto out;
> +
> +		/* if this object is in scope of basepath, maybe use it */
> +		if (strncmp(path_name, winfo->basepath,
> +		    winfo->basepath_len) == 0) {
> +			if (!(dinfo->valid & ACPI_VALID_ADR))
> +				goto out;
> +			DEBPRINT("GOT ONE: "
> +				"(%s) root_port = 0x%llx, port_num = 0x%llx\n",
> +				path_name,
> +				SATA_ROOT_PORT(dinfo->address),
> +				SATA_PORT_NUMBER(dinfo->address));
> +			/* heuristics: */
> +			if (SATA_PORT_NUMBER(dinfo->address) != NO_PORT_MULT)
> +				DEBPRINT("warning: don't know how to handle SATA port multiplier\n");
> +			if (SATA_ROOT_PORT(dinfo->address) ==
> +				winfo->ataport->port_no &&
> +			    SATA_PORT_NUMBER(dinfo->address) == NO_PORT_MULT) {
> +				DEBPRINT("THIS ^^^^^ is the requested SATA drive (handle = 0x%p)\n",
> +					handle);
> +				winfo->sata_adr = dinfo->address;
> +				winfo->obj_handle = handle;
> +			}
> +		}
> +out:
> +		ACPI_MEM_FREE(dinfo);
> +	}
> +
> +	return status;
> +}
> +
> +/* Get the SATA drive _ADR object. */
> +static int get_sata_adr(struct device *dev, acpi_handle handle,
> +			acpi_integer pcidevfn, unsigned int drive,
> +			struct ata_port *ap,
> +			struct ata_device *atadev, u32 *dev_adr)
> +{
> +	acpi_status	status;
> +	struct walk_info *winfo;
> +	int		err = -ENOMEM;
> +
> +	winfo = kzalloc(sizeof(struct walk_info), GFP_KERNEL);
> +	if (!winfo)
> +		goto out;
> +
> +	winfo->dev = dev;
> +	winfo->atadev = atadev;
> +	winfo->ataport = ap;
> +	if (acpi_bus_get_device(handle, &winfo->adev) < 0)
> +		DEBPRINT("acpi_bus_get_device failed\n");
> +	winfo->handle = handle;
> +	winfo->pcidevfn = pcidevfn;
> +	winfo->drivenum = drive;
> +
> +	status = acpi_get_devices(NULL, get_devices, winfo, NULL);
> +	if (ACPI_FAILURE(status))
> +		err = -ENODEV;
> +	else {
> +		*dev_adr = winfo->sata_adr;
> +		atadev->obj_handle = winfo->obj_handle;
> +		err = 0;
> +	}
> +	kfree(winfo);
> +out:
> +	return err;
> +}
> +
> +/**
> + * do_drive_SDD - send Identify data to a drive
> + * @ap: the ata_port for the drive
> + * @ix: drive index
> + *
> + * Must be after Identify (Packet) Device -- uses its data.
> + */
> +int do_drive_SDD(struct ata_port *ap, unsigned int ix)
> +{
> +	acpi_handle			handle;
> +	acpi_integer			pcidevfn;
> +	int				err = -ENODEV;
> +	struct device			*dev = ap->host_set->dev;
> +	struct ata_device		*atadev = &ap->device[ix];
> +	u32				dev_adr;
> +	acpi_status			status;
> +	struct acpi_object_list		input;
> +	union acpi_object 		in_params[1];
> +
> +	printk(KERN_DEBUG
> +		"%s: ap->id: %d, ix = %d, port#: %d, hard_port#: %d\n",
> +		__FUNCTION__, ap->id, ix, ap->port_no, ap->hard_port_no);
> +
> +	/* Don't continue if not a SATA device. */
> +	if (!ata_id_is_sata(atadev->id))
> +		goto out;
> +
> +	/* Don't continue if device has no _ADR method.
> +	 * _SDD is intended for known motherboard devices. */
> +	err = pci_acpi_get_dev_handle(dev, &handle, &pcidevfn);
> +	if (err < 0)
> +		goto out;
> +	/* Get this drive's _ADR info. */
> +	dev_adr = SATA_ADR_RSVD;
> +	err = get_sata_adr(dev, handle, pcidevfn, ix, ap, atadev, &dev_adr);
> +	if (err < 0 || dev_adr == SATA_ADR_RSVD || !atadev->obj_handle)
> +		goto out;
> +
> +	/* Give the drive Identify data to the drive via the _SDD method */
> +	/* _SDD: set up input parameters */
> +	input.count = 1;
> +	input.pointer = in_params;
> +	in_params[0].type 		= ACPI_TYPE_BUFFER;
> +	in_params[0].buffer.length 	= sizeof(atadev->id);
> +	in_params[0].buffer.pointer	= (u8 *)atadev->id;
> +	/* Output buffer: _SDD has no output */
> +
> +	/* It's OK for _SDD to be missing too. */
> +	status = acpi_evaluate_object(atadev->obj_handle, "_SDD", &input, NULL);
> +	err = ACPI_FAILURE(status) ? -EIO : 0;
> +	if (err < 0) {
> +		printk(KERN_DEBUG
> +			"ata%u(%u): %s _SDD error: status = 0x%x\n",
> +			ap->id, ap->device->devno, __FUNCTION__, status);
> +	}
> +out:
> +	return err;
> +}
> +EXPORT_SYMBOL_GPL(do_drive_SDD);
> +
> +/**
> + * do_drive_get_GTF - get the drive bootup default taskfile settings
> + * @ap: the ata_port for the drive
> + * @atadev: target ata_device
> + *
> + * This applies to both PATA and SATA drives.
> + *
> + * The _GTF method has no input parameters.
> + * It returns a variable number of register set values (registers
> + * hex 1F1..1F7, taskfiles).
> + * The <variable number> is not known in advance, so have ACPI-CA
> + * allocate the buffer as needed and return it, then free it later.
> + *
> + */
> +int do_drive_get_GTF(struct ata_port *ap, struct ata_device *atadev)
> +{
> +	acpi_status			status;
> +	acpi_handle			handle;
> +	acpi_integer			pcidevfn;
> +	u32				dev_adr;
> +	struct acpi_buffer		output;
> +	union acpi_object 		*out_obj;
> +	struct device			*dev = ap->host_set->dev;
> +	int				err = -ENODEV;
> +
> +	if (!ata_dev_present(atadev))	/* or port disabled ? */
> +		goto out;
> +
> +	/* Don't continue if device has no _ADR method.
> +	 * _GTF is intended for known motherboard devices. */
> +	err = pci_acpi_get_dev_handle(dev, &handle, &pcidevfn);
> +	if (err < 0)
> +		goto out;
> +
> +	/* Get this drive's _ADR info. if _SDD didn't get it. */
> +	if (!atadev->obj_handle) {
> +		dev_adr = SATA_ADR_RSVD;
> +		err = get_sata_adr(dev, handle, pcidevfn, 0, ap, atadev, &dev_adr);
> +		if (err < 0 || dev_adr == SATA_ADR_RSVD || !atadev->obj_handle)
> +			goto out;
> +	}
> +
> +	/* Setting up output buffer */
> +	output.length = ACPI_ALLOCATE_BUFFER;
> +	output.pointer = NULL;	/* ACPI-CA sets this; save/free it later */
> +
> +	/* _GTF has no input parameters */
> +	err = -EIO;
> +	status = acpi_evaluate_object(atadev->obj_handle, "_GTF",
> +					NULL, &output);
> +	if (ACPI_FAILURE(status)) {
> +		ACPI_MEM_FREE(output.pointer);
> +		printk(KERN_DEBUG
> +			"%s: Run _GTF error: status = 0x%x\n",
> +			__FUNCTION__, status);
> +		goto out;
> +	}
> +
> +	if (!output.length || !output.pointer) {
> +		printk(KERN_DEBUG
> +			"%s: Run _GTF: length or ptr is NULL (0x%llx, 0x%p)\n",
> +			__FUNCTION__,
> +			(unsigned long long)output.length, output.pointer);
> +		ACPI_MEM_FREE(output.pointer);
> +		goto out;
> +	}
> +
> +	out_obj = output.pointer;
> +	if (out_obj->type != ACPI_TYPE_BUFFER) {
> +		ACPI_MEM_FREE(output.pointer);
> +		printk(KERN_DEBUG "%s: Run _GTF: error: "
> +			"expected object type of ACPI_TYPE_BUFFER, got 0x%x\n",
> +			__FUNCTION__, out_obj->type);
> +		err = -ENOENT;
> +		goto out;
> +	}
> +
> +	atadev->gtf_length = out_obj->buffer.length;
> +	atadev->gtf_address = out_obj->buffer.pointer;
> +	err = 0;
> +out:
> +	return err;
> +}
> +EXPORT_SYMBOL_GPL(do_drive_get_GTF);
> +
> +/**
> + *	taskfile_load_raw - send taskfile registers to host controller
> + *	@ap: Port to which output is sent
> + *	@gtf: raw ATA taskfile register set (0x1f1 - 0x1f7)
> + *
> + *	Outputs ATA taskfile to standard ATA host controller using MMIO
> + *	or PIO as indicated by the ATA_FLAG_MMIO flag.
> + *	Writes the control, feature, nsect, lbal, lbam, and lbah registers.
> + *	Optionally (ATA_TFLAG_LBA48) writes hob_feature, hob_nsect,
> + *	hob_lbal, hob_lbam, and hob_lbah.
> + *
> + *	This function waits for idle (!BUSY and !DRQ) after writing
> + *	registers.  If the control register has a new value, this
> + *	function also waits for idle after writing control and before
> + *	writing the remaining registers.
> + *
> + *	LOCKING: TBD:
> + *	Inherited from caller.
> + */
> +static void taskfile_load_raw(struct ata_port *ap,
> +				struct ata_device *atadev,
> +				const struct taskfile_array *gtf)
> +{
> +	DEBPRINT("(0x1f1-1f7): hex: %02x %02x %02x %02x %02x %02x %02x\n",
> +		gtf->tfa[0], gtf->tfa[1], gtf->tfa[2],
> +		gtf->tfa[3], gtf->tfa[4], gtf->tfa[5], gtf->tfa[6]);
> +
> +	if (ap->ops->tf_load && ap->ops->exec_command) {
> +		struct ata_taskfile atf;
> +
> +		/* convert gtf to atf */
> +		ata_tf_init(ap, &atf, 0);
> +		atf.flags = ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE; /* TBD */
> +		atf.protocol = ATA_PROT_NODATA; /* or ATA_PROT_ATAPI_NODATA */
> +		atf.feature = gtf->tfa[0];	/* 0x1f1 */
> +		atf.nsect   = gtf->tfa[1];	/* 0x1f2 */
> +		atf.lbal    = gtf->tfa[2];	/* 0x1f3 */
> +		atf.lbam    = gtf->tfa[3];	/* 0x1f4 */
> +		atf.lbah    = gtf->tfa[4];	/* 0x1f5 */
> +		atf.device  = gtf->tfa[5];	/* 0x1f6 */
> +		atf.command = gtf->tfa[6];	/* 0x1f7 */
> +
> +		DEBPRINT("call tf_load:\n");
> +		ap->ops->tf_load(ap, &atf);
> +		DEBPRINT("call exec_command:\n");
> +		ap->ops->exec_command(ap, &atf);
> +		DEBPRINT("tf_load & exec_command done.\n");
> +	} else if (ap->ops->qc_issue && ap->ops->qc_prep) {
> +		int ret;
> +		struct ata_queued_cmd *qc;
> +		unsigned long flags;
> +		DECLARE_COMPLETION(wait);
> +
> +		qc = ata_qc_new_init(ap, atadev);
> +		if (!qc) {
> +			printk(KERN_DEBUG "%s: ata_qc_new_init ret. NULL\n",
> +				__FUNCTION__);
> +			return;
> +		}
> +
> +		/* convert gtf to qc.tf */
> +		qc->tf.flags = ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE; /* TBD */
> +		qc->tf.protocol = ATA_PROT_NODATA; /* or ATA_PROT_ATAPI_NODATA */
> +		qc->tf.feature = gtf->tfa[0];	/* 0x1f1 */
> +		qc->tf.nsect   = gtf->tfa[1];	/* 0x1f2 */
> +		qc->tf.lbal    = gtf->tfa[2];	/* 0x1f3 */
> +		qc->tf.lbam    = gtf->tfa[3];	/* 0x1f4 */
> +		qc->tf.lbah    = gtf->tfa[4];	/* 0x1f5 */
> +		qc->tf.device  = gtf->tfa[5];	/* 0x1f6 */
> +		qc->tf.command = gtf->tfa[6];	/* 0x1f7 */
> +
> +		qc->waiting = &wait;
> +		qc->complete_fn = ata_qc_complete_noop;
> +
> +		// TBD: fix locking and return value/wait_for_completion here:
> +		DEBPRINT("call ata_qc_issue:\n");
> +		spin_lock_irqsave(&ap->host_set->lock, flags);
> +		ret = ata_qc_issue(qc);
> +		spin_unlock_irqrestore(&ap->host_set->lock, flags);
> +		DEBPRINT("ata_qc_issue done: ret = 0x%x\n", ret);
> +
> +		if (!ret)
> +			wait_for_completion(&wait);
> +	} else
> +		printk(KERN_WARNING "%s: SATA driver is missing tf_load/exec_command or
> qc_issue function entry points\n",
> +			__FUNCTION__);
> +}
> +
> +/**
> + * do_drive_set_taskfiles - write the drive taskfile settings from _GTF
> + * @ap: the ata_port for the drive
> + * @atadev: target ata_device
> + *
> + * This applies to both PATA and SATA drives.
> + *
> + * Write {atadev->gtf_address, length atadev->gtf_length} in groups of
> + * REGS_PER_GTF bytes.
> + *
> + */
> +int do_drive_set_taskfiles(struct ata_port *ap, struct ata_device *atadev)
> +{
> +	int				err = -ENODEV;
> +	int				gtf_count =
> +					atadev->gtf_length / REGS_PER_GTF;
> +	int				ix;
> +	struct taskfile_array		*gtf;
> +
> +	if (!ata_dev_present(atadev))	/* or port disabled ? */
> +		goto out;
> +	if (!gtf_count)		/* shouldn't be here */
> +		goto out;
> +
> +	DEBPRINT("total GTF bytes = %lld (0x%llx), gtf_count = %d\n",
> +		(unsigned long long)atadev->gtf_length,
> +		(unsigned long long)atadev->gtf_length, gtf_count);
> +	if (atadev->gtf_length % REGS_PER_GTF) {
> +		printk(KERN_ERR "%s: unexpected GTF length (%zd)\n",
> +			__FUNCTION__, atadev->gtf_length);
> +		goto out;
> +	}
> +
> +	for (ix = 0; ix < gtf_count; ix++) {
> +		gtf = (struct taskfile_array *)
> +			(atadev->gtf_address + ix * REGS_PER_GTF);
> +
> +		/* send all TaskFile registers (0x1f1-0x1f7) *in*that*order* */
> +		taskfile_load_raw(ap, atadev, gtf);
> +	}
> +
> +	err = 0;
> +out:
> +	return err;
> +}
> +EXPORT_SYMBOL_GPL(do_drive_set_taskfiles);
> +
> +/**
> + * do_drive_update_taskfiles - get then write drive taskfile settings
> + * @ap: the ata_port for the drive
> + *
> + * This applies to both PATA and SATA drives.
> + */
> +int do_drive_update_taskfiles(struct ata_port *ap)
> +{
> +	int ix;
> +	int ret;
> +
> +	for (ix = 0; ix < ATA_MAX_DEVICES; ix++) {
> +		ret = do_drive_get_GTF(ap, &ap->device[ix]);
> +		if (ret >= 0)
> +			ret = do_drive_set_taskfiles(ap, &ap->device[ix]);
> +	}
> +
> +	return ret;
> +}
> +EXPORT_SYMBOL_GPL(do_drive_update_taskfiles);
> 
> ---
> -
> To unsubscribe from this list: send the line "unsubscribe linux-ide" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html


------------------------------------------
This message was penned by the hand of Domw

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

* Re: [PATCH 6/6 update] SATA ACPI: ata_acpi functions
  2005-12-07 16:36     ` Dominic Ijichi
@ 2005-12-07 17:16       ` Randy Dunlap
  2005-12-07 17:24         ` Dominic Ijichi
  0 siblings, 1 reply; 24+ messages in thread
From: Randy Dunlap @ 2005-12-07 17:16 UTC (permalink / raw)
  To: Dominic Ijichi; +Cc: linux-ide, axboe, jgarzik

On Wed, 07 Dec 2005 16:36:47 +0000
Dominic Ijichi <dom@ijichi.org> wrote:

> I get a segfault when applying these patches to 2.6.15-rc4.  ahci compiled as
> module and inserted through initrd so the module fails with segfault and kernel
> doesnt go any further through boot, hence no logging.  last thing screen shows is:
> 
> Code: e3 36 34 c0 c7 44 24 18 29 02 00 00 59 5b 5e 5f 5d e9 f3 05 00 00 53 8b 5c
> 2408 e8 e9 03 00 00 a1 dc 0c 42 c0 eb 04 39 d8 74 07 <8b> 40 04 85 c0 75 f5 5b
> c3 55 57 56 53 50 8b 44 24 20 8b 5c 24

Can you provide any more of the segfault messages?  That one
isn't particularly helpful.

Is this on your Fujitsu notebook, with the same hardware
configuration as last week?

> also, is there a working archive for this list?  the MARC archive died on 25th
> november.

I contacted them.  It appears that their subscription to linux-ide
was dropped, so they resubscribed.  However, they are missing
linux-ide archives from Nov. 25 - Dec. 7, so if anyone has those,
they would like to get them and stuff those into the archives.
If you have linux-ide archives from that period, please let me
know or (even better) send them to hlein at progressive-comp.com .

Thanks,
---
~Randy

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

* Re: [PATCH 6/6 update] SATA ACPI: ata_acpi functions
  2005-12-07 17:16       ` Randy Dunlap
@ 2005-12-07 17:24         ` Dominic Ijichi
  2005-12-07 18:34           ` Randy Dunlap
  0 siblings, 1 reply; 24+ messages in thread
From: Dominic Ijichi @ 2005-12-07 17:24 UTC (permalink / raw)
  To: Randy Dunlap; +Cc: linux-ide, axboe, jgarzik

Quoting Randy Dunlap <randy_d_dunlap@linux.intel.com>:

> On Wed, 07 Dec 2005 16:36:47 +0000
> Dominic Ijichi <dom@ijichi.org> wrote:
> 
> > I get a segfault when applying these patches to 2.6.15-rc4.  ahci compiled
> as
> > module and inserted through initrd so the module fails with segfault and
> kernel
> > doesnt go any further through boot, hence no logging.  last thing screen
> shows is:
> >
> > Code: e3 36 34 c0 c7 44 24 18 29 02 00 00 59 5b 5e 5f 5d e9 f3 05 00 00 53
> 8b 5c
> > 2408 e8 e9 03 00 00 a1 dc 0c 42 c0 eb 04 39 d8 74 07 <8b> 40 04 85 c0 75 f5
> 5b
> > c3 55 57 56 53 50 8b 44 24 20 8b 5c 24
> 
> Can you provide any more of the segfault messages?  That one
> isn't particularly helpful.

ok, see below. this is typed in on another computer, i'll try to minimise typos!
 
> Is this on your Fujitsu notebook, with the same hardware
> configuration as last week?

yup

--

[<c02516c9>] ata_device_add+0x1e9/0x2b0
[<e082d850>] ahci_interrupt+0x0/0x1e0 [achi]
[<e082e263>] ahci_init_one+0x1a3/0x270 [achi]
[<c01cb5d6>] __pci_device_probe+0x56/0x70
[<c01cb61f>] pci_device_probe+0x2f/0x50
[<c023b313>] driver_probe_device+0x43/0xd0
[<c023b420>] __driver_attach+0x0/0x50
[<c023b461>] __driver_attach+0x41/0x50
[<c023a84d>] bus_for_each_dev+0x5d/0x80
[<c023b495>] driver_attach+0x25/0x30
[<c023b420>] __driver_attach+0x0/0x50
[<c023ada9>] bus_add_driver+0x89/0xf0
[<c01cb8a4>] __pci_register_driver+0x74/0xa0
[<e0832018>] ahci_init+0x18/0x1c [achi]
[c01364c2>] sys_init_module+0xd/0x210
[<c0103291>] syscall_call+0x7/0xb

then the Code: line

thats all that's left on the screen unfortunately, the rest scrolls off the top.

cheers
dom







> > also, is there a working archive for this list?  the MARC archive died on
> 25th
> > november.
> 
> I contacted them.  It appears that their subscription to linux-ide
> was dropped, so they resubscribed.  However, they are missing
> linux-ide archives from Nov. 25 - Dec. 7, so if anyone has those,
> they would like to get them and stuff those into the archives.
> If you have linux-ide archives from that period, please let me
> know or (even better) send them to hlein at progressive-comp.com .
> 
> Thanks,
> ---
> ~Randy


------------------------------------------
This message was penned by the hand of Dom

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

* Re: [PATCH 6/6 update] SATA ACPI: ata_acpi functions
  2005-12-07 17:24         ` Dominic Ijichi
@ 2005-12-07 18:34           ` Randy Dunlap
  2005-12-08  9:43             ` Dominic Ijichi
  0 siblings, 1 reply; 24+ messages in thread
From: Randy Dunlap @ 2005-12-07 18:34 UTC (permalink / raw)
  To: Dominic Ijichi; +Cc: linux-ide, axboe, jgarzik

On Wed, 07 Dec 2005 17:24:30 +0000
Dominic Ijichi <dom@ijichi.org> wrote:

> Quoting Randy Dunlap <randy_d_dunlap@linux.intel.com>:
> 
> > On Wed, 07 Dec 2005 16:36:47 +0000
> > Dominic Ijichi <dom@ijichi.org> wrote:
> > 
> > > I get a segfault when applying these patches to 2.6.15-rc4.  ahci compiled
> > as
> > > module and inserted through initrd so the module fails with segfault and
> > kernel
> > > doesnt go any further through boot, hence no logging.  last thing screen
> > shows is:
> > >
> > > Code: e3 36 34 c0 c7 44 24 18 29 02 00 00 59 5b 5e 5f 5d e9 f3 05 00 00 53
> > 8b 5c
> > > 2408 e8 e9 03 00 00 a1 dc 0c 42 c0 eb 04 39 d8 74 07 <8b> 40 04 85 c0 75 f5
> > 5b
> > > c3 55 57 56 53 50 8b 44 24 20 8b 5c 24
> > 
> > Can you provide any more of the segfault messages?  That one
> > isn't particularly helpful.
> 
> ok, see below. this is typed in on another computer, i'll try to minimise typos!

OK, well, that's a little better, but the top of the backtrace
is where the nitty gritty info is.
Is it possible for you to use any other method of capturing
more fault messages, like serial console, netconsole,
or even higher resolution video (and smaller font)
so that I can see where the fault is actually happening?

Thanks.

> > Is this on your Fujitsu notebook, with the same hardware
> > configuration as last week?
> 
> yup
> 
> --
> 
> [<c02516c9>] ata_device_add+0x1e9/0x2b0
> [<e082d850>] ahci_interrupt+0x0/0x1e0 [achi]
> [<e082e263>] ahci_init_one+0x1a3/0x270 [achi]
> [<c01cb5d6>] __pci_device_probe+0x56/0x70
> [<c01cb61f>] pci_device_probe+0x2f/0x50
> [<c023b313>] driver_probe_device+0x43/0xd0
> [<c023b420>] __driver_attach+0x0/0x50
> [<c023b461>] __driver_attach+0x41/0x50
> [<c023a84d>] bus_for_each_dev+0x5d/0x80
> [<c023b495>] driver_attach+0x25/0x30
> [<c023b420>] __driver_attach+0x0/0x50
> [<c023ada9>] bus_add_driver+0x89/0xf0
> [<c01cb8a4>] __pci_register_driver+0x74/0xa0
> [<e0832018>] ahci_init+0x18/0x1c [achi]
> [c01364c2>] sys_init_module+0xd/0x210
> [<c0103291>] syscall_call+0x7/0xb
> 
> then the Code: line
> 
> thats all that's left on the screen unfortunately, the rest scrolls off the top.

---
~Randy

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

* Re: [PATCH 6/6 update] SATA ACPI: ata_acpi functions
  2005-12-07 18:34           ` Randy Dunlap
@ 2005-12-08  9:43             ` Dominic Ijichi
  2005-12-09  0:16               ` Randy Dunlap
  0 siblings, 1 reply; 24+ messages in thread
From: Dominic Ijichi @ 2005-12-08  9:43 UTC (permalink / raw)
  To: Randy Dunlap; +Cc: linux-ide, axboe, jgarzik

Quoting Randy Dunlap <randy_d_dunlap@linux.intel.com>:

> On Wed, 07 Dec 2005 17:24:30 +0000
> Dominic Ijichi <dom@ijichi.org> wrote:
> 
> > Quoting Randy Dunlap <randy_d_dunlap@linux.intel.com>:
> >
> > > On Wed, 07 Dec 2005 16:36:47 +0000
> > > Dominic Ijichi <dom@ijichi.org> wrote:
> > >
> > > > I get a segfault when applying these patches to 2.6.15-rc4.  ahci
> compiled
> > > as
> > > > module and inserted through initrd so the module fails with segfault
> and
> > > kernel
> > > > doesnt go any further through boot, hence no logging.  last thing
> screen
> > > shows is:
> > > >
> > > > Code: e3 36 34 c0 c7 44 24 18 29 02 00 00 59 5b 5e 5f 5d e9 f3 05 00 00
> 53
> > > 8b 5c
> > > > 2408 e8 e9 03 00 00 a1 dc 0c 42 c0 eb 04 39 d8 74 07 <8b> 40 04 85 c0
> 75 f5
> > > 5b
> > > > c3 55 57 56 53 50 8b 44 24 20 8b 5c 24
> > >
> > > Can you provide any more of the segfault messages?  That one
> > > isn't particularly helpful.
> >
> > ok, see below. this is typed in on another computer, i'll try to minimise
> typos!
> 
> OK, well, that's a little better, but the top of the backtrace
> is where the nitty gritty info is.
> Is it possible for you to use any other method of capturing
> more fault messages, like serial console, netconsole,
> or even higher resolution video (and smaller font)
> so that I can see where the fault is actually happening?
> 
> Thanks.

ok.  eye-watering font, but here's what it says:

ata1: dev 0 configured for UDMA/100
Unable to handle kernel paging request at virtual address eaeaeaee
 printing eip:
c0218c67
*pde = 00000000
Oops: 0000 [#1]
PREEMPT
Modules linked in: ahci piix ide_disk ide_core
CPU: 0
EIP: 0060:[<c0218c67>] Not tainted VLI
EFLAGS: 00010202 (2.6.15-rc4)
EIP is at acpi_ut_find_allocation+0x15/0x1e
eax: eaeaeaea ebx: df0d8c00 ec: 00000000 edx: 00000007
esi: c0388b0d edi: 00000000 ebp: dffd0e40 esp: c17e9bdc
ds: 007b es: 007b ss: 0068
Process modprobe (pid: 1353, threadinfo=c17e8000 task=deeb3070)
Stack: df0d8c00 c0218cd8 df0d8c00 0000001 df0d8c00 000001ef 00000010 c0388b0d
 c0218b04 df0d8c00 00000008 00000001 00000010 c0388b0d 000001ef c03890d5
 c17e9c40 c17e9c74 c03890d5 c020ea16 00000008 00000010 c0388b0d 000001ef
Call Trace:
[<c0218cd8>] acpi_ut_track_allocation+0x68/0x127
[<c0218b04>] acpi_ut_callocate_and_track+0x55/0x83
[<c020ea16>] acpi_ns_internalize_name+0x82/0x113
[<c020dcf6>] acpi_ns_evaluate_relatvie+0x66/0x1ca
[<c02195de>] acpi_ut_evaluate_object+0x46/0x22a
[<c0219ba3>] acpi_ut_execute_STA+0x35/0xc4
[<c020d468>] acpi_ns_get_device_callback+0x4e/0x151
[<c02104ec>] acpi_ns_walk_namespace+0xbb/0x1b7
[<c020d604>] acpi_get_devices+0x99/0xc4
[<c020d41a>] acpi_ns_get_device_callback+0x0/0x151
[<c0277280>] get_devices+0x0/0x220
[<c0277539>] get_sata_adr+0x99/0x110
[<c0277280>] get_devices+0x0/0x220
[<c02778e6>] do_drive_get_GTF+0x136/0x200
[<c0277d8f>] do_drive_update_taskfiles+0x2f/0x70
[<c0270578>] ata_set_mode+0x98/0xb0
[<c026fc0b>] ata_bus_probe+0xab/0xc0
> > [<c02516c9>] ata_device_add+0x1e9/0x2b0
> > [<e082d850>] ahci_interrupt+0x0/0x1e0 [achi]
> > [<e082e263>] ahci_init_one+0x1a3/0x270 [achi]
> > [<c01cb5d6>] __pci_device_probe+0x56/0x70
> > [<c01cb61f>] pci_device_probe+0x2f/0x50
> > [<c023b313>] driver_probe_device+0x43/0xd0
> > [<c023b420>] __driver_attach+0x0/0x50
> > [<c023b461>] __driver_attach+0x41/0x50
> > [<c023a84d>] bus_for_each_dev+0x5d/0x80
> > [<c023b495>] driver_attach+0x25/0x30
> > [<c023b420>] __driver_attach+0x0/0x50
> > [<c023ada9>] bus_add_driver+0x89/0xf0
> > [<c01cb8a4>] __pci_register_driver+0x74/0xa0
> > [<e0832018>] ahci_init+0x18/0x1c [achi]
> > [c01364c2>] sys_init_module+0xd/0x210
> > [<c0103291>] syscall_call+0x7/0xb


> 
> > > Is this on your Fujitsu notebook, with the same hardware
> > > configuration as last week?
> >
> > yup
> >
> > --
> >
> > [<c02516c9>] ata_device_add+0x1e9/0x2b0
> > [<e082d850>] ahci_interrupt+0x0/0x1e0 [achi]
> > [<e082e263>] ahci_init_one+0x1a3/0x270 [achi]
> > [<c01cb5d6>] __pci_device_probe+0x56/0x70
> > [<c01cb61f>] pci_device_probe+0x2f/0x50
> > [<c023b313>] driver_probe_device+0x43/0xd0
> > [<c023b420>] __driver_attach+0x0/0x50
> > [<c023b461>] __driver_attach+0x41/0x50
> > [<c023a84d>] bus_for_each_dev+0x5d/0x80
> > [<c023b495>] driver_attach+0x25/0x30
> > [<c023b420>] __driver_attach+0x0/0x50
> > [<c023ada9>] bus_add_driver+0x89/0xf0
> > [<c01cb8a4>] __pci_register_driver+0x74/0xa0
> > [<e0832018>] ahci_init+0x18/0x1c [achi]
> > [c01364c2>] sys_init_module+0xd/0x210
> > [<c0103291>] syscall_call+0x7/0xb
> >
> > then the Code: line
> >
> > thats all that's left on the screen unfortunately, the rest scrolls off the
> top.
> 
> ---
> ~Randy


------------------------------------------
This message was penned by the hand of Dom

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

* Re: [PATCH 6/6 update] SATA ACPI: ata_acpi functions
  2005-12-08  9:43             ` Dominic Ijichi
@ 2005-12-09  0:16               ` Randy Dunlap
  2005-12-09  0:20                 ` Dominic Ijichi
  0 siblings, 1 reply; 24+ messages in thread
From: Randy Dunlap @ 2005-12-09  0:16 UTC (permalink / raw)
  To: Dominic Ijichi; +Cc: linux-ide, axboe, jgarzik

On Thu, 08 Dec 2005 09:43:30 +0000
Dominic Ijichi <dom@ijichi.org> wrote:

> Quoting Randy Dunlap <randy_d_dunlap@linux.intel.com>:
> 
> > On Wed, 07 Dec 2005 17:24:30 +0000
> > Dominic Ijichi <dom@ijichi.org> wrote:
> > 
> > > Quoting Randy Dunlap <randy_d_dunlap@linux.intel.com>:
> > >
> > > > On Wed, 07 Dec 2005 16:36:47 +0000
> > > > Dominic Ijichi <dom@ijichi.org> wrote:
> > > >
> > > > > I get a segfault when applying these patches to 2.6.15-rc4.  ahci
> > compiled
> > > > as
> > > > > module and inserted through initrd so the module fails with segfault
> > and
> > > > kernel
> > > > > doesnt go any further through boot, hence no logging.  last thing
> > screen
> > > > shows is:
> > > > >
> > > > > Code: e3 36 34 c0 c7 44 24 18 29 02 00 00 59 5b 5e 5f 5d e9 f3 05 00 00
> > 53
> > > > 8b 5c
> > > > > 2408 e8 e9 03 00 00 a1 dc 0c 42 c0 eb 04 39 d8 74 07 <8b> 40 04 85 c0
> > 75 f5
> > > > 5b
> > > > > c3 55 57 56 53 50 8b 44 24 20 8b 5c 24
> > > >
> > > > Can you provide any more of the segfault messages?  That one
> > > > isn't particularly helpful.
> > >
> > > ok, see below. this is typed in on another computer, i'll try to minimise
> > typos!
> > 
> > OK, well, that's a little better, but the top of the backtrace
> > is where the nitty gritty info is.
> > Is it possible for you to use any other method of capturing
> > more fault messages, like serial console, netconsole,
> > or even higher resolution video (and smaller font)
> > so that I can see where the fault is actually happening?
> > 
> > Thanks.
> 
> ok.  eye-watering font, but here's what it says:

Thanks for doing that.
Did you enable ACPI debug output?  If so, how?
(in .config or by modifying a header file?
if by modifying a header file, please tell us
exactly.)

> ata1: dev 0 configured for UDMA/100
> Unable to handle kernel paging request at virtual address eaeaeaee
>  printing eip:
> c0218c67
> *pde = 00000000
> Oops: 0000 [#1]
> PREEMPT
> Modules linked in: ahci piix ide_disk ide_core
> CPU: 0
> EIP: 0060:[<c0218c67>] Not tainted VLI
> EFLAGS: 00010202 (2.6.15-rc4)
> EIP is at acpi_ut_find_allocation+0x15/0x1e
> eax: eaeaeaea ebx: df0d8c00 ec: 00000000 edx: 00000007
> esi: c0388b0d edi: 00000000 ebp: dffd0e40 esp: c17e9bdc
> ds: 007b es: 007b ss: 0068
> Process modprobe (pid: 1353, threadinfo=c17e8000 task=deeb3070)
> Stack: df0d8c00 c0218cd8 df0d8c00 0000001 df0d8c00 000001ef 00000010 c0388b0d
>  c0218b04 df0d8c00 00000008 00000001 00000010 c0388b0d 000001ef c03890d5
>  c17e9c40 c17e9c74 c03890d5 c020ea16 00000008 00000010 c0388b0d 000001ef
> Call Trace:
> [<c0218cd8>] acpi_ut_track_allocation+0x68/0x127
> [<c0218b04>] acpi_ut_callocate_and_track+0x55/0x83
> [<c020ea16>] acpi_ns_internalize_name+0x82/0x113
> [<c020dcf6>] acpi_ns_evaluate_relatvie+0x66/0x1ca
> [<c02195de>] acpi_ut_evaluate_object+0x46/0x22a
> [<c0219ba3>] acpi_ut_execute_STA+0x35/0xc4
> [<c020d468>] acpi_ns_get_device_callback+0x4e/0x151
> [<c02104ec>] acpi_ns_walk_namespace+0xbb/0x1b7
> [<c020d604>] acpi_get_devices+0x99/0xc4
> [<c020d41a>] acpi_ns_get_device_callback+0x0/0x151
> [<c0277280>] get_devices+0x0/0x220
> [<c0277539>] get_sata_adr+0x99/0x110
> [<c0277280>] get_devices+0x0/0x220
> [<c02778e6>] do_drive_get_GTF+0x136/0x200
> [<c0277d8f>] do_drive_update_taskfiles+0x2f/0x70
> [<c0270578>] ata_set_mode+0x98/0xb0
> [<c026fc0b>] ata_bus_probe+0xab/0xc0
> > > [<c02516c9>] ata_device_add+0x1e9/0x2b0
> > > [<e082d850>] ahci_interrupt+0x0/0x1e0 [achi]
> > > [<e082e263>] ahci_init_one+0x1a3/0x270 [achi]
> > > [<c01cb5d6>] __pci_device_probe+0x56/0x70
> > > [<c01cb61f>] pci_device_probe+0x2f/0x50
> > > [<c023b313>] driver_probe_device+0x43/0xd0
> > > [<c023b420>] __driver_attach+0x0/0x50
> > > [<c023b461>] __driver_attach+0x41/0x50
> > > [<c023a84d>] bus_for_each_dev+0x5d/0x80
> > > [<c023b495>] driver_attach+0x25/0x30
> > > [<c023b420>] __driver_attach+0x0/0x50
> > > [<c023ada9>] bus_add_driver+0x89/0xf0
> > > [<c01cb8a4>] __pci_register_driver+0x74/0xa0
> > > [<e0832018>] ahci_init+0x18/0x1c [achi]
> > > [c01364c2>] sys_init_module+0xd/0x210
> > > [<c0103291>] syscall_call+0x7/0xb
> 
> 
> > 
> > > > Is this on your Fujitsu notebook, with the same hardware
> > > > configuration as last week?
> > >
> > > yup
> > >
> > > --
> > >
> > > [<c02516c9>] ata_device_add+0x1e9/0x2b0
> > > [<e082d850>] ahci_interrupt+0x0/0x1e0 [achi]
> > > [<e082e263>] ahci_init_one+0x1a3/0x270 [achi]
> > > [<c01cb5d6>] __pci_device_probe+0x56/0x70
> > > [<c01cb61f>] pci_device_probe+0x2f/0x50
> > > [<c023b313>] driver_probe_device+0x43/0xd0
> > > [<c023b420>] __driver_attach+0x0/0x50
> > > [<c023b461>] __driver_attach+0x41/0x50
> > > [<c023a84d>] bus_for_each_dev+0x5d/0x80
> > > [<c023b495>] driver_attach+0x25/0x30
> > > [<c023b420>] __driver_attach+0x0/0x50
> > > [<c023ada9>] bus_add_driver+0x89/0xf0
> > > [<c01cb8a4>] __pci_register_driver+0x74/0xa0
> > > [<e0832018>] ahci_init+0x18/0x1c [achi]
> > > [c01364c2>] sys_init_module+0xd/0x210
> > > [<c0103291>] syscall_call+0x7/0xb
> > >
> > > then the Code: line
> > >
> > > thats all that's left on the screen unfortunately, the rest scrolls off the
> > top.
> > 
> > ---

---
~Randy

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

* Re: [PATCH 6/6 update] SATA ACPI: ata_acpi functions
  2005-12-09  0:16               ` Randy Dunlap
@ 2005-12-09  0:20                 ` Dominic Ijichi
  2005-12-09  1:03                   ` Randy Dunlap
  0 siblings, 1 reply; 24+ messages in thread
From: Dominic Ijichi @ 2005-12-09  0:20 UTC (permalink / raw)
  To: Randy Dunlap; +Cc: linux-ide, axboe, jgarzik

Quoting Randy Dunlap <randy_d_dunlap@linux.intel.com>:

> On Thu, 08 Dec 2005 09:43:30 +0000
> Dominic Ijichi <dom@ijichi.org> wrote:
> 
> > Quoting Randy Dunlap <randy_d_dunlap@linux.intel.com>:
> >
> > > On Wed, 07 Dec 2005 17:24:30 +0000
> > > Dominic Ijichi <dom@ijichi.org> wrote:
> > >
> > > > Quoting Randy Dunlap <randy_d_dunlap@linux.intel.com>:
> > > >
> > > > > On Wed, 07 Dec 2005 16:36:47 +0000
> > > > > Dominic Ijichi <dom@ijichi.org> wrote:
> > > > >
> > > > > > I get a segfault when applying these patches to 2.6.15-rc4.  ahci
> > > compiled
> > > > > as
> > > > > > module and inserted through initrd so the module fails with
> segfault
> > > and
> > > > > kernel
> > > > > > doesnt go any further through boot, hence no logging.  last thing
> > > screen
> > > > > shows is:
> > > > > >
> > > > > > Code: e3 36 34 c0 c7 44 24 18 29 02 00 00 59 5b 5e 5f 5d e9 f3 05
> 00 00
> > > 53
> > > > > 8b 5c
> > > > > > 2408 e8 e9 03 00 00 a1 dc 0c 42 c0 eb 04 39 d8 74 07 <8b> 40 04 85
> c0
> > > 75 f5
> > > > > 5b
> > > > > > c3 55 57 56 53 50 8b 44 24 20 8b 5c 24
> > > > >
> > > > > Can you provide any more of the segfault messages?  That one
> > > > > isn't particularly helpful.
> > > >
> > > > ok, see below. this is typed in on another computer, i'll try to
> minimise
> > > typos!
> > >
> > > OK, well, that's a little better, but the top of the backtrace
> > > is where the nitty gritty info is.
> > > Is it possible for you to use any other method of capturing
> > > more fault messages, like serial console, netconsole,
> > > or even higher resolution video (and smaller font)
> > > so that I can see where the fault is actually happening?
> > >
> > > Thanks.
> >
> > ok.  eye-watering font, but here's what it says:
> 
> Thanks for doing that.
> Did you enable ACPI debug output?  If so, how?
> (in .config or by modifying a header file?
> if by modifying a header file, please tell us
> exactly.)

ACPI_DEBUG in .config and also applied your debug patch

> 
> > ata1: dev 0 configured for UDMA/100
> > Unable to handle kernel paging request at virtual address eaeaeaee
> >  printing eip:
> > c0218c67
> > *pde = 00000000
> > Oops: 0000 [#1]
> > PREEMPT
> > Modules linked in: ahci piix ide_disk ide_core
> > CPU: 0
> > EIP: 0060:[<c0218c67>] Not tainted VLI
> > EFLAGS: 00010202 (2.6.15-rc4)
> > EIP is at acpi_ut_find_allocation+0x15/0x1e
> > eax: eaeaeaea ebx: df0d8c00 ec: 00000000 edx: 00000007
> > esi: c0388b0d edi: 00000000 ebp: dffd0e40 esp: c17e9bdc
> > ds: 007b es: 007b ss: 0068
> > Process modprobe (pid: 1353, threadinfo=c17e8000 task=deeb3070)
> > Stack: df0d8c00 c0218cd8 df0d8c00 0000001 df0d8c00 000001ef 00000010
> c0388b0d
> >  c0218b04 df0d8c00 00000008 00000001 00000010 c0388b0d 000001ef c03890d5
> >  c17e9c40 c17e9c74 c03890d5 c020ea16 00000008 00000010 c0388b0d 000001ef
> > Call Trace:
> > [<c0218cd8>] acpi_ut_track_allocation+0x68/0x127
> > [<c0218b04>] acpi_ut_callocate_and_track+0x55/0x83
> > [<c020ea16>] acpi_ns_internalize_name+0x82/0x113
> > [<c020dcf6>] acpi_ns_evaluate_relatvie+0x66/0x1ca
> > [<c02195de>] acpi_ut_evaluate_object+0x46/0x22a
> > [<c0219ba3>] acpi_ut_execute_STA+0x35/0xc4
> > [<c020d468>] acpi_ns_get_device_callback+0x4e/0x151
> > [<c02104ec>] acpi_ns_walk_namespace+0xbb/0x1b7
> > [<c020d604>] acpi_get_devices+0x99/0xc4
> > [<c020d41a>] acpi_ns_get_device_callback+0x0/0x151
> > [<c0277280>] get_devices+0x0/0x220
> > [<c0277539>] get_sata_adr+0x99/0x110
> > [<c0277280>] get_devices+0x0/0x220
> > [<c02778e6>] do_drive_get_GTF+0x136/0x200
> > [<c0277d8f>] do_drive_update_taskfiles+0x2f/0x70
> > [<c0270578>] ata_set_mode+0x98/0xb0
> > [<c026fc0b>] ata_bus_probe+0xab/0xc0
> > > > [<c02516c9>] ata_device_add+0x1e9/0x2b0
> > > > [<e082d850>] ahci_interrupt+0x0/0x1e0 [achi]
> > > > [<e082e263>] ahci_init_one+0x1a3/0x270 [achi]
> > > > [<c01cb5d6>] __pci_device_probe+0x56/0x70
> > > > [<c01cb61f>] pci_device_probe+0x2f/0x50
> > > > [<c023b313>] driver_probe_device+0x43/0xd0
> > > > [<c023b420>] __driver_attach+0x0/0x50
> > > > [<c023b461>] __driver_attach+0x41/0x50
> > > > [<c023a84d>] bus_for_each_dev+0x5d/0x80
> > > > [<c023b495>] driver_attach+0x25/0x30
> > > > [<c023b420>] __driver_attach+0x0/0x50
> > > > [<c023ada9>] bus_add_driver+0x89/0xf0
> > > > [<c01cb8a4>] __pci_register_driver+0x74/0xa0
> > > > [<e0832018>] ahci_init+0x18/0x1c [achi]
> > > > [c01364c2>] sys_init_module+0xd/0x210
> > > > [<c0103291>] syscall_call+0x7/0xb
> >
> >
> > >
> > > > > Is this on your Fujitsu notebook, with the same hardware
> > > > > configuration as last week?
> > > >
> > > > yup
> > > >
> > > > --
> > > >
> > > > [<c02516c9>] ata_device_add+0x1e9/0x2b0
> > > > [<e082d850>] ahci_interrupt+0x0/0x1e0 [achi]
> > > > [<e082e263>] ahci_init_one+0x1a3/0x270 [achi]
> > > > [<c01cb5d6>] __pci_device_probe+0x56/0x70
> > > > [<c01cb61f>] pci_device_probe+0x2f/0x50
> > > > [<c023b313>] driver_probe_device+0x43/0xd0
> > > > [<c023b420>] __driver_attach+0x0/0x50
> > > > [<c023b461>] __driver_attach+0x41/0x50
> > > > [<c023a84d>] bus_for_each_dev+0x5d/0x80
> > > > [<c023b495>] driver_attach+0x25/0x30
> > > > [<c023b420>] __driver_attach+0x0/0x50
> > > > [<c023ada9>] bus_add_driver+0x89/0xf0
> > > > [<c01cb8a4>] __pci_register_driver+0x74/0xa0
> > > > [<e0832018>] ahci_init+0x18/0x1c [achi]
> > > > [c01364c2>] sys_init_module+0xd/0x210
> > > > [<c0103291>] syscall_call+0x7/0xb
> > > >
> > > > then the Code: line
> > > >
> > > > thats all that's left on the screen unfortunately, the rest scrolls off
> the
> > > top.
> > >
> > > ---
> 
> ---
> ~Randy


------------------------------------------
This message was penned by the hand of Dom

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

* Re: [PATCH 6/6 update] SATA ACPI: ata_acpi functions
  2005-12-09  0:20                 ` Dominic Ijichi
@ 2005-12-09  1:03                   ` Randy Dunlap
  2005-12-09  1:10                     ` Randy Dunlap
  0 siblings, 1 reply; 24+ messages in thread
From: Randy Dunlap @ 2005-12-09  1:03 UTC (permalink / raw)
  To: Dominic Ijichi; +Cc: linux-ide, axboe, jgarzik


> > > > OK, well, that's a little better, but the top of the backtrace
> > > > is where the nitty gritty info is.
> > > > Is it possible for you to use any other method of capturing
> > > > more fault messages, like serial console, netconsole,
> > > > or even higher resolution video (and smaller font)
> > > > so that I can see where the fault is actually happening?
> > > >
> > > > Thanks.
> > >
> > > ok.  eye-watering font, but here's what it says:
> > 
> > Thanks for doing that.
> > Did you enable ACPI debug output?  If so, how?
> > (in .config or by modifying a header file?
> > if by modifying a header file, please tell us
> > exactly.)
> 
> ACPI_DEBUG in .config and also applied your debug patch

Yes, easy to reproduce with CONFIG_ACPI_DEBUG=y.

My new code frees a buffer that it does not own.

Just comment out or delete line 156 in drivers/scsi/ata_acpi.c,
which is:
		ACPI_MEM_FREE(dinfo);

It shouldn't be there.

Thanks!
---
~Randy

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

* Re: [PATCH 6/6 update] SATA ACPI: ata_acpi functions
  2005-12-09  1:03                   ` Randy Dunlap
@ 2005-12-09  1:10                     ` Randy Dunlap
  2005-12-09 18:52                       ` Randy Dunlap
  0 siblings, 1 reply; 24+ messages in thread
From: Randy Dunlap @ 2005-12-09  1:10 UTC (permalink / raw)
  To: Randy Dunlap; +Cc: dom, linux-ide, axboe, jgarzik

On Thu, 8 Dec 2005 17:03:02 -0800
Randy Dunlap <randy_d_dunlap@linux.intel.com> wrote:

> 
> > > > > OK, well, that's a little better, but the top of the backtrace
> > > > > is where the nitty gritty info is.
> > > > > Is it possible for you to use any other method of capturing
> > > > > more fault messages, like serial console, netconsole,
> > > > > or even higher resolution video (and smaller font)
> > > > > so that I can see where the fault is actually happening?
> > > > >
> > > > > Thanks.
> > > >
> > > > ok.  eye-watering font, but here's what it says:
> > > 
> > > Thanks for doing that.
> > > Did you enable ACPI debug output?  If so, how?
> > > (in .config or by modifying a header file?
> > > if by modifying a header file, please tell us
> > > exactly.)
> > 
> > ACPI_DEBUG in .config and also applied your debug patch
> 
> Yes, easy to reproduce with CONFIG_ACPI_DEBUG=y.
> 
> My new code frees a buffer that it does not own.
> 
> Just comment out or delete line 156 in drivers/scsi/ata_acpi.c,
> which is:
> 		ACPI_MEM_FREE(dinfo);
> 
> It shouldn't be there.

That's not quite correct.  It will boot & run with that
change, but now the buffer isn't being freed at all.
I'll rethink that and post a patch.

---
~Randy

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

* Re: [PATCH 6/6 update] SATA ACPI: ata_acpi functions
  2005-12-09  1:10                     ` Randy Dunlap
@ 2005-12-09 18:52                       ` Randy Dunlap
  2005-12-10 19:01                         ` Dominic Ijichi
  0 siblings, 1 reply; 24+ messages in thread
From: Randy Dunlap @ 2005-12-09 18:52 UTC (permalink / raw)
  To: Randy Dunlap; +Cc: dom, linux-ide, axboe, jgarzik

On Thu, 8 Dec 2005 17:10:08 -0800
Randy Dunlap <randy_d_dunlap@linux.intel.com> wrote:

> > > 
> > > ACPI_DEBUG in .config and also applied your debug patch
> > 
> > Yes, easy to reproduce with CONFIG_ACPI_DEBUG=y.
> > 
> > My new code frees a buffer that it does not own.
> > 
> > Just comment out or delete line 156 in drivers/scsi/ata_acpi.c,
> > which is:
> > 		ACPI_MEM_FREE(dinfo);
> > 
> > It shouldn't be there.
> 
> That's not quite correct.  It will boot & run with that
> change, but now the buffer isn't being freed at all.
> I'll rethink that and post a patch.

Dom,

I've updated the ata_apci.patch file to fix this bug.
I was misusing some of the ACPI memory alloc/free interfaces.

Updated file is at
http://www.xenotime.net/linux/SATA/2.6.15-rc/ata_acpi.patch

Thanks,
---
~Randy

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

* Re: [PATCH 6/6 update] SATA ACPI: ata_acpi functions
  2005-12-09 18:52                       ` Randy Dunlap
@ 2005-12-10 19:01                         ` Dominic Ijichi
  2005-12-12  0:16                           ` Randy.Dunlap
  0 siblings, 1 reply; 24+ messages in thread
From: Dominic Ijichi @ 2005-12-10 19:01 UTC (permalink / raw)
  To: Randy Dunlap; +Cc: linux-ide, axboe, jgarzik

[-- Attachment #1: Type: text/plain, Size: 1239 bytes --]

Quoting Randy Dunlap <randy_d_dunlap@linux.intel.com>:

> On Thu, 8 Dec 2005 17:10:08 -0800
> Randy Dunlap <randy_d_dunlap@linux.intel.com> wrote:
> 
> > > >
> > > > ACPI_DEBUG in .config and also applied your debug patch
> > >
> > > Yes, easy to reproduce with CONFIG_ACPI_DEBUG=y.
> > >
> > > My new code frees a buffer that it does not own.
> > >
> > > Just comment out or delete line 156 in drivers/scsi/ata_acpi.c,
> > > which is:
> > > 		ACPI_MEM_FREE(dinfo);
> > >
> > > It shouldn't be there.
> >
> > That's not quite correct.  It will boot & run with that
> > change, but now the buffer isn't being freed at all.
> > I'll rethink that and post a patch.
> 
> Dom,
> 
> I've updated the ata_apci.patch file to fix this bug.
> I was misusing some of the ACPI memory alloc/free interfaces.
> 
> Updated file is at
> http://www.xenotime.net/linux/SATA/2.6.15-rc/ata_acpi.patch

hi

it applies cleanly now, but unfortunately this doesnt seem to work in my case. 
on waking from S3 sleep there is still no disk activity and terminals hang on
first disk access.  dmesg attached, there's some more debug now which hopefully
will be helpful!

cheers
dom

------------------------------------------
This message was penned by the hand of Dom

[-- Attachment #2: rc5.patched.dmesg.txt --]
[-- Type: text/plain, Size: 15472 bytes --]

.......................................................
Table [DSDT](id 0007) - 671 Objects with 65 Devices 181 Methods 18 Regions
Parsing all Control Methods:...
Table [SSDT](id 0004) - 5 Objects with 0 Devices 3 Methods 0 Regions
Parsing all Control Methods:.
Table [SSDT](id 0005) - 1 Objects with 0 Devices 1 Methods 0 Regions
ACPI Namespace successfully loaded at root c043cc58
ACPI: setting ELCR to 0200 (from 0ca0)
evxfevnt-0091 [03] enable                : Transition to ACPI mode successful
checking if image is initramfs... it is
Freeing initrd memory: 1623k freed
NET: Registered protocol family 16
ACPI: bus type pci registered
PCI: PCI BIOS revision 2.10 entry at 0xeafc4, last bus=6
PCI: Using MMCONFIG
ACPI: Subsystem revision 20050902
evgpeblk-0988 [06] ev_create_gpe_block   : GPE 00 to 1F [_GPE] 4 regs on int 0x9
evgpeblk-0996 [06] ev_create_gpe_block   : Found 4 Wake, Enabled 2 Runtime GPEs in this block
Completing Region/Field/Buffer/Package initialization:.......................................................
Initialized 18/18 Regions 0/0 Fields 23/23 Buffers 14/20 Packages (686 nodes)
Executing all Device _STA and_INI methods:......................................................................
70 Devices found containing: 70 _STA, 2 _INI methods
ACPI: Interpreter enabled
ACPI: Using PIC for interrupt routing
ACPI: PCI Root Bridge [PCI0] (0000:00)
PCI: Probing PCI hardware (bus 00)
PCI quirk: region 1000-107f claimed by ICH6 ACPI/GPIO/TCO
PCI quirk: region 1300-133f claimed by ICH6 GPIO
PCI: Ignoring BAR0-3 of IDE controller 0000:00:1f.1
Boot video device is 0000:01:00.0
PCI: Transparent bridge - 0000:00:1e.0
ACPI: PCI Interrupt Routing Table [\_SB_.PCI0._PRT]
ACPI: PCI Interrupt Routing Table [\_SB_.PCI0.PEGP._PRT]
ACPI: PCI Interrupt Routing Table [\_SB_.PCI0.RP01._PRT]
ACPI: PCI Interrupt Routing Table [\_SB_.PCI0.PCIB._PRT]
ACPI: PCI Interrupt Link [LNKA] (IRQs 10) *11
ACPI: PCI Interrupt Link [LNKB] (IRQs *10)
ACPI: PCI Interrupt Link [LNKC] (IRQs *10)
ACPI: PCI Interrupt Link [LNKD] (IRQs *10)
ACPI: PCI Interrupt Link [LNKE] (IRQs 10) *7
ACPI: PCI Interrupt Link [LNKF] (IRQs 10) *0, disabled.
ACPI: PCI Interrupt Link [LNKG] (IRQs 10) *0, disabled.
ACPI: PCI Interrupt Link [LNKH] (IRQs 10) *5
ACPI: Embedded Controller [EC0] (gpe 28)
ACPI: Power Resource [QFAN] (off)
Linux Plug and Play Support v0.97 (c) Adam Belay
pnp: PnP ACPI init
pnp: ACPI device : hid PNP0C02
pnp: ACPI device : hid PNP0200
pnp: ACPI device : hid INT0800
pnp: ACPI device : hid PNP0C04
pnp: ACPI device : hid PNP0C02
pnp: ACPI device : hid PNP0B00
pnp: ACPI device : hid PNP0303
pnp: ACPI device : hid PNP0F13
pnp: ACPI device : hid FUJ02B1
pnp: PnP ACPI: found 9 devices
PnPBIOS: Disabled by ACPI PNP
SCSI subsystem initialized
usbcore: registered new driver usbfs
usbcore: registered new driver hub
PCI: Using ACPI for IRQ routing
PCI: If a device doesn't work, try "pci=routeirq".  If it helps, post a report
pnp: the driver 'system' has been registered
pnp: match found with the PnP device '00:00' and the driver 'system'
pnp: match found with the PnP device '00:04' and the driver 'system'
PCI: Bridge: 0000:00:01.0
  IO window: c000-dfff
  MEM window: c0000000-cfffffff
  PREFETCH window: 90000000-9fffffff
PCI: Bridge: 0000:00:1c.0
  IO window: a000-bfff
  MEM window: bc000000-bfffffff
  PREFETCH window: 8c000000-8fffffff
PCI: Bus 7, cardbus bridge: 0000:06:06.0
  IO window: 00008000-000080ff
  IO window: 00008400-000084ff
  PREFETCH window: 84000000-85ffffff
  MEM window: b6000000-b7ffffff
PCI: Bridge: 0000:00:1e.0
  IO window: 8000-9fff
  MEM window: b4000000-bbffffff
  PREFETCH window: 84000000-8bffffff
acpi_bus-0201 [01] bus_set_power         : Device is not power manageable
ACPI: PCI Interrupt Link [LNKA] enabled at IRQ 10
PCI: setting IRQ 10 as level-triggered
ACPI: PCI Interrupt 0000:00:01.0[A] -> Link [LNKA] -> GSI 10 (level, low) -> IRQ 10
PCI: Setting latency timer of device 0000:00:01.0 to 64
acpi_bus-0201 [01] bus_set_power         : Device is not power manageable
ACPI: PCI Interrupt Link [LNKB] enabled at IRQ 10
ACPI: PCI Interrupt 0000:00:1c.0[A] -> Link [LNKB] -> GSI 10 (level, low) -> IRQ 10
PCI: Setting latency timer of device 0000:00:1c.0 to 64
PCI: Setting latency timer of device 0000:00:1e.0 to 64
acpi_bus-0201 [01] bus_set_power         : Device is not power manageable
ACPI: PCI Interrupt 0000:06:06.0[A] -> Link [LNKB] -> GSI 10 (level, low) -> IRQ 10
Machine check exception polling timer started.
audit: initializing netlink socket (disabled)
audit(1134240289.108:1): initialized
Initializing Cryptographic API
io scheduler noop registered
io scheduler anticipatory registered
io scheduler deadline registered
io scheduler cfq registered
Linux agpgart interface v0.101 (c) Dave Jones
agpgart: Detected an Intel 915GM Chipset.
agpgart: AGP aperture is 256M @ 0x0
[drm] Initialized drm 1.0.0 20040925
pnp: the driver 'i8042 kbd' has been registered
pnp: match found with the PnP device '00:06' and the driver 'i8042 kbd'
pnp: the driver 'i8042 aux' has been registered
pnp: match found with the PnP device '00:07' and the driver 'i8042 aux'
PNP: PS/2 Controller [PNP0303:PS2K,PNP0f13:PS2M] at 0x60,0x64 irq 1,12
serio: i8042 AUX port at 0x60,0x64 irq 12
serio: i8042 KBD port at 0x60,0x64 irq 1
Serial: 8250/16550 driver $Revision: 1.90 $ 4 ports, IRQ sharing disabled
pnp: the driver 'serial' has been registered
acpi_bus-0201 [01] bus_set_power         : Device is not power manageable
ACPI: PCI Interrupt Link [LNKE] enabled at IRQ 10
ACPI: PCI Interrupt 0000:00:1e.3[B] -> Link [LNKE] -> GSI 10 (level, low) -> IRQ 10
ACPI: PCI interrupt for device 0000:00:1e.3 disabled
Floppy drive(s): fd0 is 1.44M
floppy0: no floppy controllers found
RAMDISK driver initialized: 16 RAM disks of 4096K size 1024 blocksize
libata version 1.20 loaded.
ohci1394: $Rev: 1313 $ Ben Collins <bcollins@debian.org>
acpi_bus-0201 [01] bus_set_power         : Device is not power manageable
ACPI: PCI Interrupt Link [LNKD] enabled at IRQ 10
ACPI: PCI Interrupt 0000:06:06.2[C] -> Link [LNKD] -> GSI 10 (level, low) -> IRQ 10
ohci1394: fw-host0: OHCI-1394 1.1 (PCI): IRQ=[10]  MMIO=[b4000000-b40007ff]  Max Packet=[2048]
ieee1394: raw1394: /dev/raw1394 device initialized
usbmon: debugfs is not available
acpi_bus-0201 [01] bus_set_power         : Device is not power manageable
ACPI: PCI Interrupt Link [LNKH] enabled at IRQ 10
ACPI: PCI Interrupt 0000:00:1d.7[A] -> Link [LNKH] -> GSI 10 (level, low) -> IRQ 10
PCI: Setting latency timer of device 0000:00:1d.7 to 64
ehci_hcd 0000:00:1d.7: EHCI Host Controller
ehci_hcd 0000:00:1d.7: debug port 1
PCI: cache line size of 32 is not supported by device 0000:00:1d.7
ehci_hcd 0000:00:1d.7: new USB bus registered, assigned bus number 1
ehci_hcd 0000:00:1d.7: irq 10, io mem 0xd0000400
ehci_hcd 0000:00:1d.7: USB 2.0 started, EHCI 1.00, driver 10 Dec 2004
hub 1-0:1.0: USB hub found
hub 1-0:1.0: 8 ports detected
USB Universal Host Controller Interface driver v2.3
ACPI: PCI Interrupt 0000:00:1d.0[A] -> Link [LNKH] -> GSI 10 (level, low) -> IRQ 10
PCI: Setting latency timer of device 0000:00:1d.0 to 64
uhci_hcd 0000:00:1d.0: UHCI Host Controller
uhci_hcd 0000:00:1d.0: new USB bus registered, assigned bus number 2
uhci_hcd 0000:00:1d.0: irq 10, io base 0x00001200
hub 2-0:1.0: USB hub found
hub 2-0:1.0: 2 ports detected
ACPI: PCI Interrupt 0000:00:1d.1[B] -> Link [LNKD] -> GSI 10 (level, low) -> IRQ 10
PCI: Setting latency timer of device 0000:00:1d.1 to 64
uhci_hcd 0000:00:1d.1: UHCI Host Controller
uhci_hcd 0000:00:1d.1: new USB bus registered, assigned bus number 3
uhci_hcd 0000:00:1d.1: irq 10, io base 0x00001220
hub 3-0:1.0: USB hub found
hub 3-0:1.0: 2 ports detected
ACPI: PCI Interrupt Link [LNKC] enabled at IRQ 10
ACPI: PCI Interrupt 0000:00:1d.2[C] -> Link [LNKC] -> GSI 10 (level, low) -> IRQ 10
PCI: Setting latency timer of device 0000:00:1d.2 to 64
uhci_hcd 0000:00:1d.2: UHCI Host Controller
uhci_hcd 0000:00:1d.2: new USB bus registered, assigned bus number 4
uhci_hcd 0000:00:1d.2: irq 10, io base 0x0000e380
hub 4-0:1.0: USB hub found
hub 4-0:1.0: 2 ports detected
ACPI: PCI Interrupt 0000:00:1d.3[D] -> Link [LNKA] -> GSI 10 (level, low) -> IRQ 10
PCI: Setting latency timer of device 0000:00:1d.3 to 64
uhci_hcd 0000:00:1d.3: UHCI Host Controller
uhci_hcd 0000:00:1d.3: new USB bus registered, assigned bus number 5
uhci_hcd 0000:00:1d.3: irq 10, io base 0x0000e3a0
hub 5-0:1.0: USB hub found
hub 5-0:1.0: 0 ports detected
usb 3-2: new low speed USB device using uhci_hcd and address 2
usbcore: registered new driver usblp
drivers/usb/class/usblp.c: v0.13: USB Printer Device Class driver
Initializing USB Mass Storage driver...
usbcore: registered new driver usb-storage
USB Mass Storage support registered.
input: Microsoft Microsoft USB Wireless Mouse as /class/input/input0
input: USB HID v1.11 Mouse [Microsoft Microsoft USB Wireless Mouse] on usb-0000:00:1d.1-2
usbcore: registered new driver usbhid
drivers/usb/input/hid-core.c: v2.6:USB HID core driver
mice: PS/2 mouse device common for all mice
Advanced Linux Sound Architecture Driver Version 1.0.10rc3 (Mon Nov 07 13:30:21 2005 UTC).
acpi_bus-0201 [01] bus_set_power         : Device is not power manageable
ACPI: PCI Interrupt 0000:00:1e.2[A] -> Link [LNKB] -> GSI 10 (level, low) -> IRQ 10
PCI: Setting latency timer of device 0000:00:1e.2 to 64
input: AT Translated Set 2 keyboard as /class/input/input1
input: PS/2 Mouse as /class/input/input2
input: AlpsPS/2 ALPS GlidePoint as /class/input/input3
ieee1394: Host added: ID:BUS[0-00:1023]  GUID[00000e10000d9124]
intel8x0_measure_ac97_clock: measured 55488 usecs
intel8x0: clocking to 48000
ALSA device list:
  #0: Intel ICH6 with ALC203 at 0xd0000000, irq 10
oprofile: using timer interrupt.
NET: Registered protocol family 2
IP route cache hash table entries: 8192 (order: 3, 32768 bytes)
TCP established hash table entries: 32768 (order: 5, 131072 bytes)
TCP bind hash table entries: 32768 (order: 5, 131072 bytes)
TCP: Hash tables configured (established 32768 bind 32768)
TCP reno registered
ip_conntrack version 2.4 (4095 buckets, 32760 max) - 212 bytes per conntrack
ip_tables: (C) 2000-2002 Netfilter core team
ipt_recent v0.3.1: Stephen Frost <sfrost@snowman.net>.  http://snowman.net/projects/ipt_recent/
arp_tables: (C) 2002 David S. Miller
TCP bic registered
NET: Registered protocol family 1
NET: Registered protocol family 17
Using IPI Shortcut mode
ACPI wakeup devices: 
 LID AZAL RP01 MINI  LAN MODM 
ACPI: (supports S0 S3 S4 S5)
Freeing unused kernel memory: 196k freed
Uniform Multi-Platform E-IDE driver Revision: 7.00alpha2
ide: Assuming 33MHz system bus speed for PIO modes; override with idebus=xx
pnp: the driver 'ide' has been registered
ICH6: IDE controller at PCI slot 0000:00:1f.1
ACPI: PCI Interrupt 0000:00:1f.1[A] -> Link [LNKC] -> GSI 10 (level, low) -> IRQ 10
ICH6: chipset revision 4
ICH6: not 100% native mode: will probe irqs later
    ide0: BM-DMA at 0x1100-0x1107, BIOS settings: hda:DMA, hdb:pio
    ide1: BM-DMA at 0x1108-0x110f, BIOS settings: hdc:DMA, hdd:pio
Probing IDE interface ide0...
hda: DW-224E-B, ATAPI CD/DVD-ROM drive
ide0 at 0x1f0-0x1f7,0x3f6 on irq 14
Probing IDE interface ide1...
ahci 0000:00:1f.2: version 1.2
acpi_bus-0201 [01] bus_set_power         : Device is not power manageable
ACPI: PCI Interrupt 0000:00:1f.2[D] -> Link [LNKA] -> GSI 10 (level, low) -> IRQ 10
PCI: Setting latency timer of device 0000:00:1f.2 to 64
ahci 0000:00:1f.2: AHCI 0001.0000 32 slots 4 ports 1.5 Gbps 0x5 impl IDE mode
ahci 0000:00:1f.2: flags: 64bit stag led pmp 
ata1: SATA max UDMA/133 cmd 0xE085A100 ctl 0x0 bmdma 0x0 irq 10
ata2: SATA max UDMA/133 cmd 0xE085A180 ctl 0x0 bmdma 0x0 irq 10
ata3: SATA max UDMA/133 cmd 0xE085A200 ctl 0x0 bmdma 0x0 irq 10
ata4: SATA max UDMA/133 cmd 0xE085A280 ctl 0x0 bmdma 0x0 irq 10
ata1: dev 0 cfg 00:045a 49:0b00 82:746b 83:5988 84:4003 85:7469 86:1808 87:4003 88:003f 93:600b
ata1: dev 0 ATA-5, max UDMA/100, 117210240 sectors: LBA
ata1(0): applying bridge limits
do_drive_SDD: ap->id: 1, ix = 0, port#: 0, hard_port#: 0
do_drive_SDD: ata_id_is_sata is False
ata1: dev 0 configured for UDMA/100
pci_acpi_get_dev_handle: pcidevfn: 0x1f0002
get_devices: :\_SB_.PCI0.SATA: matches pcidevfn (0x1f0002)
get_devices: GOT ONE: (\_SB_.PCI0.SATA.PRID) root_port = 0x0, port_num = 0x0
get_devices: warning: don't know how to handle SATA port multiplier
get_devices: GOT ONE: (\_SB_.PCI0.SATA.PRID.P_D0) root_port = 0x0, port_num = 0x0
get_devices: warning: don't know how to handle SATA port multiplier
get_devices: GOT ONE: (\_SB_.PCI0.SATA.PRID.P_D1) root_port = 0x0, port_num = 0x1
get_devices: warning: don't know how to handle SATA port multiplier
get_devices: GOT ONE: (\_SB_.PCI0.SATA.SECD) root_port = 0x0, port_num = 0x1
get_devices: warning: don't know how to handle SATA port multiplier
get_devices: GOT ONE: (\_SB_.PCI0.SATA.SECD.S_D0) root_port = 0x0, port_num = 0x0
get_devices: warning: don't know how to handle SATA port multiplier
get_devices: GOT ONE: (\_SB_.PCI0.SATA.SECD.S_D1) root_port = 0x0, port_num = 0x1
get_devices: warning: don't know how to handle SATA port multiplier
scsi0 : ahci
ata2: no device found (phy stat 00000000)
scsi1 : ahci
ata3: no device found (phy stat 00000000)
scsi2 : ahci
ata4: no device found (phy stat 00000000)
scsi3 : ahci
  Vendor: ATA       Model: HITACHI_DK23FA-6  Rev: 00M4
  Type:   Direct-Access                      ANSI SCSI revision: 05
ACPI: CPU0 (power states: C1[C1] C2[C2] C3[C3] C4[C3])
ACPI: Processor [CPU0] (supports 8 throttling states)
acpi_processor-0507 [06] processor_get_info    : Error getting cpuindex for acpiid 0x1
[ACPI Debug]  String: [0x13] "THERM: _SCP(Active)"
ACPI: Thermal Zone [THRM] (72 C)
ACPI: Fan [FAN] (on)
SCSI device sda: 117210240 512-byte hdwr sectors (60012 MB)
SCSI device sda: drive cache: write back
SCSI device sda: 117210240 512-byte hdwr sectors (60012 MB)
SCSI device sda: drive cache: write back
 sda: sda1 sda2 sda3 sda4
sd 0:0:0:0: Attached scsi disk sda
sd 0:0:0:0: Attached scsi generic sg0 type 0
ReiserFS: sda4: found reiserfs format "3.6" with standard journal
ReiserFS: sda4: using ordered data mode
ReiserFS: sda4: journal params: device sda4, size 8192, journal first block 18, max trans len 1024, max batch 900, max commit age 30, max trans age 30
ReiserFS: sda4: checking transaction log (sda4)
ReiserFS: sda4: Using r5 hash to sort names
ReiserFS: sda4: Removing [48544 68043 0x0 SD]..done
ReiserFS: sda4: There were 1 uncompleted unlinks/truncates. Completed
Adding 1052248k swap on /dev/sda2.  Priority:-1 extents:1 across:1052248k
NTFS driver 2.1.25 [Flags: R/W MODULE].
NTFS volume version 3.1.
hda: ATAPI 24X DVD-ROM CD-R/RW drive, 1654kB Cache, UDMA(33)
Uniform CD-ROM driver Revision: 3.20
cdrom: open failed.
BIOS EDD facility v0.16 2004-Jun-25, 1 devices found
ACPI: AC Adapter [ACAD] (off-line)
ACPI: Battery Slot [BAT1] (battery present)
ACPI: Power Button (FF) [PWRF]
ACPI: Lid Switch [LID]
ACPI: Power Button (CM) [PWRB]
acpi-cpufreq: CPU0 - ACPI performance management activated.
     osl-0854 [83] os_wait_semaphore     : Failed to acquire semaphore[dffde5c0|1|0], AE_TIME
     osl-0854 [83] os_wait_semaphore     : Failed to acquire semaphore[dffde5c0|1|20480], AE_TIME
 exmutex-0258: *** Error: Thread C cannot release Mutex [MUT0] acquired by thread 1430
 psparse-0508: *** Error: Method execution failed [\_SB_.BAT1._STA] (Node dfe2ae28), AE_AML_NOT_OWNER
[ACPI Debug]  String: [0x13] "THERM: _SCP(Active)"

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

* Re: [PATCH 6/6 update] SATA ACPI: ata_acpi functions
  2005-12-10 19:01                         ` Dominic Ijichi
@ 2005-12-12  0:16                           ` Randy.Dunlap
  0 siblings, 0 replies; 24+ messages in thread
From: Randy.Dunlap @ 2005-12-12  0:16 UTC (permalink / raw)
  To: Dominic Ijichi; +Cc: randy_d_dunlap, linux-ide, axboe, jgarzik

On Sat, 10 Dec 2005 19:01:50 +0000 Dominic Ijichi wrote:

> Quoting Randy Dunlap <randy_d_dunlap@linux.intel.com>:
> 
> > Dom,
> > 
> > I've updated the ata_apci.patch file to fix this bug.
> > I was misusing some of the ACPI memory alloc/free interfaces.
> > 
> > Updated file is at
> > http://www.xenotime.net/linux/SATA/2.6.15-rc/ata_acpi.patch
> 
> hi
> 
> it applies cleanly now, but unfortunately this doesnt seem to work in my case. 
> on waking from S3 sleep there is still no disk activity and terminals hang on
> first disk access.  dmesg attached, there's some more debug now which hopefully
> will be helpful!

partial dmesg:
ata1: dev 0 cfg 00:045a 49:0b00 82:746b 83:5988 84:4003 85:7469 86:1808 87:4003 88:003f 93:600b
ata1: dev 0 ATA-5, max UDMA/100, 117210240 sectors: LBA
ata1(0): applying bridge limits
do_drive_SDD: ap->id: 1, ix = 0, port#: 0, hard_port#: 0
do_drive_SDD: ata_id_is_sata is False
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

The drive is not reported as a SATA drive, so the patch that I wrote
won't work for it.  Have you tried this patch to see if it works/helps
on your machine?

From:	Shaohua Li <shaohua.li@intel.com>
To:	linux-ide <linux-ide@vger.kernel.org>, lkml <linux-kernel@vger.kernel.org>
Subject: [RFC]add ACPI hooks for IDE suspend/resume
Date:	Tue, 06 Dec 2005 14:10:04 +0800


Thanks,
---
~Randy

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

* Re: [PATCH 6/6 update] SATA ACPI: ata_acpi functions
  2005-12-12  1:24 Dominic ES. Ijichi
@ 2005-12-12  2:13 ` Randy.Dunlap
  0 siblings, 0 replies; 24+ messages in thread
From: Randy.Dunlap @ 2005-12-12  2:13 UTC (permalink / raw)
  To: Dominic ES. Ijichi; +Cc: randy_d_dunlap, linux-ide, axboe, jgarzik

On Mon, 12 Dec 2005 01:24:04 +0000 (GMT) Dominic ES. Ijichi wrote:

> ----- Randy.Dunlap <rdunlap@xenotime.net> wrote:
> > On Mon, 12 Dec 2005 00:24:53 +0000 (GMT) Dominic ES. Ijichi wrote:
> > 
> > > ----- Randy.Dunlap <rdunlap@xenotime.net> wrote:
> > > > On Sat, 10 Dec 2005 19:01:50 +0000 Dominic Ijichi wrote:
> > > > 
> > > 
> > > oh right.  sorry to trouble you but the list archive has a 'hole'
> > when that patch was released, could you possibly forward it to me?
> > 
> > Sure, I forgot about that.  It's below for anyone who wants to try
> > it.
> 
> apologies if i'm being a bit thick here (ssh!), but don't i need to be running the ahci module, which doesnt use the ide code?  i could never get the machine to boot with the ide driver, and my suse10 distro has this note in /etc/modprobe.conf:
> 
> # ata_piix can't handle ICH6 in AHCI mode
> install ata_piix /sbin/modprobe ahci; /sbin/modprobe --ignore-install ata_piix
> 
> i believe this controller is an intel ih6 sata controller in ahci mode, with a physical old-style ide port and udma100 ide drive plugged into it.


Good question.  I wish that I could answer it, but I'm confused about
it too.  Hopefully someone else will jump in and answer it.

---
~Randy

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

* Re: [PATCH 6/6 update] SATA ACPI: ata_acpi functions
@ 2005-12-12  1:24 Dominic ES. Ijichi
  2005-12-12  2:13 ` Randy.Dunlap
  0 siblings, 1 reply; 24+ messages in thread
From: Dominic ES. Ijichi @ 2005-12-12  1:24 UTC (permalink / raw)
  To: Randy; +Cc: randy d dunlap, linux-ide, axboe, jgarzik

----- Randy.Dunlap <rdunlap@xenotime.net> wrote:
> On Mon, 12 Dec 2005 00:24:53 +0000 (GMT) Dominic ES. Ijichi wrote:
> 
> > ----- Randy.Dunlap <rdunlap@xenotime.net> wrote:
> > > On Sat, 10 Dec 2005 19:01:50 +0000 Dominic Ijichi wrote:
> > > 
> > > > Quoting Randy Dunlap <randy_d_dunlap@linux.intel.com>:
> > > > 
> > > > > Dom,
> > > > > 
> > > > > I've updated the ata_apci.patch file to fix this bug.
> > > > > I was misusing some of the ACPI memory alloc/free interfaces.
> > > > > 
> > > > > Updated file is at
> > > > > http://www.xenotime.net/linux/SATA/2.6.15-rc/ata_acpi.patch
> > > > 
> > > > hi
> > > > 
> > > > it applies cleanly now, but unfortunately this doesnt seem to
> work
> > > in my case. 
> > > > on waking from S3 sleep there is still no disk activity and
> > > terminals hang on
> > > > first disk access.  dmesg attached, there's some more debug now
> > > which hopefully
> > > > will be helpful!
> > > 
> > > partial dmesg:
> > > ata1: dev 0 cfg 00:045a 49:0b00 82:746b 83:5988 84:4003 85:7469
> > > 86:1808 87:4003 88:003f 93:600b
> > > ata1: dev 0 ATA-5, max UDMA/100, 117210240 sectors: LBA
> > > ata1(0): applying bridge limits
> > > do_drive_SDD: ap->id: 1, ix = 0, port#: 0, hard_port#: 0
> > > do_drive_SDD: ata_id_is_sata is False
> > > ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> > > 
> > > The drive is not reported as a SATA drive, so the patch that I
> wrote
> > > won't work for it.  Have you tried this patch to see if it
> > > works/helps
> > > on your machine?
> > 
> > oh right.  sorry to trouble you but the list archive has a 'hole'
> when that patch was released, could you possibly forward it to me?
> 
> Sure, I forgot about that.  It's below for anyone who wants to try
> it.

apologies if i'm being a bit thick here (ssh!), but don't i need to be running the ahci module, which doesnt use the ide code?  i could never get the machine to boot with the ide driver, and my suse10 distro has this note in /etc/modprobe.conf:

# ata_piix can't handle ICH6 in AHCI mode
install ata_piix /sbin/modprobe ahci; /sbin/modprobe --ignore-install ata_piix

i believe this controller is an intel ih6 sata controller in ahci mode, with a physical old-style ide port and udma100 ide drive plugged into it.

dom

> 
> > > From:	Shaohua Li <shaohua.li@intel.com>
> > > To:	linux-ide <linux-ide@vger.kernel.org>, lkml
> > > <linux-kernel@vger.kernel.org>
> > > Subject: [RFC]add ACPI hooks for IDE suspend/resume
> > > Date:	Tue, 06 Dec 2005 14:10:04 +0800
> 
> 
> 
> Hi,
> Adding ACPI IDE hook in IDE suspend/resume. The ACPI spec
> explicitly says we must call some ACPI methods to restore IDE drives.
> The sequences defined by ACPI spec are:
> suspend:
> 1. Get the DMA and PIO info from IDE channel's _GTM method.
> 
> resume:
> 1. Calling IDE channel's _STM to set the transfer timing setting.
> 2. For each drive on the IDE channel, running drive's _GTF to get the
> ATA commands required to reinitialize each drive.
> 3. Sending the ATA commands gotton from step 2 to drives.
> 
> TODO: invoking ATA commands.
> 
> Though we didn't invoke ATA commands, this patch fixes the bug at 
> http://bugzilla.kernel.org/show_bug.cgi?id=5604. And Matthew said
> this
> actually fixes a lot of systems in his test.
> I'm not familiar with IDE, so comments/suggestions are welcome.
> 
> Thanks,
> Shaohua
> 
> ---
> 
>  linux-2.6.15-rc5-root/drivers/ide/ide.c |  282
> ++++++++++++++++++++++++++++++++
>  1 files changed, 282 insertions(+)
> 
> diff -puN drivers/ide/ide.c~acpi-ide drivers/ide/ide.c
> --- linux-2.6.15-rc5/drivers/ide/ide.c~acpi-ide	2005-12-07
> 03:01:36.000000000 +0800
> +++ linux-2.6.15-rc5-root/drivers/ide/ide.c	2005-12-07
> 03:01:36.000000000 +0800
> @@ -155,6 +155,10 @@
>  #include <linux/device.h>
>  #include <linux/bitops.h>
>  
> +#ifdef CONFIG_ACPI
> +#include <linux/acpi.h>
> +#endif
> +
>  #include <asm/byteorder.h>
>  #include <asm/irq.h>
>  #include <asm/uaccess.h>
> @@ -1214,6 +1218,279 @@ int system_bus_clock (void)
>  
>  EXPORT_SYMBOL(system_bus_clock);
>  
> +#ifdef CONFIG_ACPI
> +static int ide_acpi_find_device(struct device *dev, acpi_handle
> *handle)
> +{
> +	int i, tmp;
> +	acpi_integer addr;
> +
> +	if (sscanf(dev->bus_id, "%u.%u", &tmp, &i) != 2)
> +		return -ENODEV;
> +
> +	addr = (acpi_integer)i;
> +	*handle = acpi_get_child(DEVICE_ACPI_HANDLE(dev->parent), addr);
> +	if (!*handle)
> +		return -ENODEV;
> +	return 0;
> +}
> +
> +/* This assumes the ide controller is a PCI device */
> +static int ide_acpi_find_channel(struct device *dev, acpi_handle
> *handle)
> +{
> +	int num;
> +	int channel;
> +	acpi_integer addr;
> +
> +	num = sscanf(dev->bus_id, "ide%x", &channel);
> +
> +	if (num != 1 || !dev->parent)
> +		return -ENODEV;
> +	addr = (acpi_integer)channel;
> +	*handle = acpi_get_child(DEVICE_ACPI_HANDLE(dev->parent), addr);
> +	if (!*handle)
> +		return -ENODEV;
> +	return 0;
> +}
> +
> +static struct acpi_bus_type ide_acpi_bus = {
> +	.bus = &ide_bus_type,
> +	.find_device = ide_acpi_find_device,
> +	.find_bridge = ide_acpi_find_channel,
> +};
> +
> +static int __init ide_acpi_init(void)
> +{
> +	return register_acpi_bus_type(&ide_acpi_bus);
> +}
> +
> +/* The _GTM return package length is 5 dwords */
> +#define GTM_LEN (sizeof(u32) * 5)
> +struct acpi_ide_state {
> +	acpi_handle handle; /* channel device's handle */
> +	u32 gtm[GTM_LEN/sizeof(u32)]; /* info from _GTM */
> +	struct hd_driveid id_buff[2]; /* one chanel has two drives */
> +	int suspend_drives;
> +	int resume_drives;
> +};
> +
> +static void acpi_ide_data_handler(acpi_handle handle,
> +	u32 function, void *context)
> +{
> +	/* nothing to do */
> +}
> +
> +/* acpi data for a chanel */
> +static struct acpi_ide_state *ide_alloc_acpi_state(acpi_handle
> handle)
> +{
> +	struct acpi_ide_state * state;
> +	acpi_status status;
> +
> +	state = kzalloc(sizeof(struct acpi_ide_state), GFP_KERNEL);
> +	if (!state)
> +		return NULL;
> +	status = acpi_attach_data(handle, acpi_ide_data_handler, state);
> +	if (ACPI_FAILURE(status))
> +		return NULL;
> +	return state;
> +}
> +
> +static struct acpi_ide_state *ide_get_acpi_state(acpi_handle handle)
> +{
> +	struct acpi_ide_state * state;
> +	acpi_status status;
> +
> +	status = acpi_get_data(handle, acpi_ide_data_handler, (void
> **)&state);
> +	if (ACPI_FAILURE(status))
> +		return NULL;
> +	return state;
> +}
> +
> +static void ide_free_acpi_state(acpi_handle handle)
> +{
> +	struct acpi_ide_state *state;
> +
> +	state = ide_get_acpi_state(handle);
> +	acpi_detach_data(handle, acpi_ide_data_handler);
> +	kfree(state);
> +}
> +
> +static int acpi_ide_suspend(struct device *dev)
> +{
> +	acpi_handle handle, parent_handle;
> +	struct acpi_ide_state *state;
> +	acpi_status status;
> +	struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
> +	union acpi_object *package;
> +	ide_drive_t *drive = dev->driver_data;
> +	int drive_id = 0;
> +
> +	handle = DEVICE_ACPI_HANDLE(dev);
> +	if (!handle) {
> +		printk(KERN_DEBUG "IDE device's ACPI handler is NULL\n");
> +		return -ENODEV;
> +	}
> +	if (ACPI_FAILURE(acpi_get_parent(handle, &parent_handle))) {
> +		printk(KERN_ERR "ACPI get parent handler error\n");
> +		return -ENODEV;
> +	}
> +	state = ide_get_acpi_state(parent_handle);
> +	if (!state) {
> +		state = ide_alloc_acpi_state(parent_handle);
> +		if (!state)
> +			return -ENODEV;
> +	}
> +
> +	/* invoke _GTM only once */
> +	state->suspend_drives++;
> +	if (state->suspend_drives > 1) {
> +		drive_id = 1;
> +		goto id;
> +	}
> +
> +	status = acpi_evaluate_object(parent_handle, "_GTM", NULL,
> &buffer);
> +	if (ACPI_FAILURE(status)) {
> +		printk(KERN_ERR "Error evaluating _GTM\n");
> +		return -ENODEV;
> +	}
> +	package = (union acpi_object *) buffer.pointer;
> +	if (package->buffer.length != GTM_LEN) {
> +		printk(KERN_ERR "Buffer length returned by _GTM is wrong\n");
> +		acpi_os_free(buffer.pointer);
> +		return -ENODEV;
> +	}
> +	memcpy(state->gtm, package->buffer.pointer, GTM_LEN);
> +	state->handle = parent_handle;
> +	acpi_os_free(buffer.pointer);
> +id:
> +	taskfile_lib_get_identify(drive, (u8*)&state->id_buff[drive_id]);
> +	return 0;
> +}
> +
> +static int acpi_ide_invoke_stm(struct acpi_ide_state *state)
> +{
> +	struct acpi_object_list input;
> +	union acpi_object params[3];
> +	acpi_status status;
> +
> +	input.count = 3;
> +	input.pointer = params;
> +	params[0].type = ACPI_TYPE_BUFFER;
> +	params[0].buffer.length = sizeof(state->gtm);
> +	params[0].buffer.pointer = (char*)state->gtm;
> +
> +	params[1].type = ACPI_TYPE_BUFFER;
> +	params[1].buffer.length = sizeof(state->id_buff[0]);
> +	params[1].buffer.pointer = (char *)&state->id_buff[0];
> +
> +	params[2].type = ACPI_TYPE_BUFFER;
> +	params[2].buffer.length = sizeof(state->id_buff[1]);
> +	params[2].buffer.pointer = (char *)&state->id_buff[1];
> +
> +	status = acpi_evaluate_object(state->handle, "_STM", &input, NULL);
> +	if (ACPI_FAILURE(status)) {
> +		printk(KERN_ERR "Evaluating _STM error\n");
> +		return -ENODEV;
> +	}
> +	return 0;
> +}
> +
> +static int acpi_ide_invoke_gtf(acpi_handle handle, ide_drive_t
> *drive)
> +{
> +	struct acpi_buffer output = {ACPI_ALLOCATE_BUFFER, NULL};
> +#if 0
> +	ide_task_t args;
> +	int index = 0;
> +	unsigned char *data;
> +#endif
> +	union acpi_object *package;
> +	acpi_status status;
> +
> +	status = acpi_evaluate_object(handle, "_GTF", NULL, &output);
> +	if (ACPI_FAILURE(status)) {
> +		printk(KERN_ERR "evaluate _GTF error\n");
> +		return -ENODEV;
> +	}
> +
> +	package = (union acpi_object *) output.pointer;
> +	if (package->type != ACPI_TYPE_BUFFER
> +			|| (package->buffer.length % 7) != 0) {
> +		acpi_os_free(output.pointer);
> +		printk(KERN_ERR "_GTF returned value is wrong\n");
> +		return -ENODEV;
> +	}
> +#if 0
> +	printk(KERN_DEBUG "Start invoking _GTF commands\n");
> +
> +	data = package->buffer.pointer;
> +	/* sumbit ATA commands */
> +	while (index < package->buffer.length) {
> +		memset(&args, 0, sizeof(ide_task_t));
> +		args.tfRegister[IDE_ERROR_OFFSET] = data[index];
> +		args.tfRegister[IDE_NSECTOR_OFFSET] = data[index + 1];
> +		args.tfRegister[IDE_SECTOR_OFFSET] = data[index + 2];
> +		args.tfRegister[IDE_LCYL_OFFSET] = data[index + 3];
> +		args.tfRegister[IDE_HCYL_OFFSET] = data[index + 4];
> +		args.tfRegister[IDE_SELECT_OFFSET] = data[index + 5];
> +		args.tfRegister[IDE_STATUS_OFFSET] = data[index + 6];
> +		args.command_type = IDE_DRIVE_TASK_NO_DATA;
> +		args.handler = &task_no_data_intr;
> +		/* submit command */
> +		index += 7;
> +	}
> +#endif
> +	acpi_os_free(output.pointer);
> +	return 0;
> +}
> +
> +static int acpi_ide_resume(struct device *dev)
> +{
> +	acpi_handle handle, parent_handle;
> +	struct acpi_ide_state *state;
> +	ide_drive_t *drive = dev->driver_data;
> +
> +	handle = DEVICE_ACPI_HANDLE(dev);
> +	if (!handle) {
> +		printk(KERN_DEBUG "IDE device's ACPI handler is NULL\n");
> +		return -ENODEV;
> +	}
> +	if (ACPI_FAILURE(acpi_get_parent(handle, &parent_handle))) {
> +		printk(KERN_ERR "ACPI get parent handler error\n");
> +		return -ENODEV;
> +	}
> +	state = ide_get_acpi_state(parent_handle);
> +	if (state == NULL)
> +		return -ENODEV;
> +
> +	/* invoke _STM only once */
> +	state->resume_drives++;
> +	if (state->resume_drives == 1) {
> +		printk(KERN_DEBUG "Start invoking _STM\n");
> +		if (acpi_ide_invoke_stm(state))
> +			return -ENODEV;
> +	}
> +
> +	if (state->resume_drives == state->suspend_drives)
> +		ide_free_acpi_state(parent_handle);
> +	return acpi_ide_invoke_gtf(handle, drive);
> +}
> +
> +#else
> +static int __init ide_acpi_init(void)
> +{
> +	return 0;
> +}
> +
> +static int acpi_ide_suspend(struct device *dev)
> +{
> +	return 0;
> +}
> +
> +static int acpi_ide_resume(struct device *dev)
> +{
> +	return 0;
> +}
> +#endif
> +
>  static int generic_ide_suspend(struct device *dev, pm_message_t
> state)
>  {
>  	ide_drive_t *drive = dev->driver_data;
> @@ -1221,6 +1498,8 @@ static int generic_ide_suspend(struct de
>  	struct request_pm_state rqpm;
>  	ide_task_t args;
>  
> +	acpi_ide_suspend(dev);
> +
>  	memset(&rq, 0, sizeof(rq));
>  	memset(&rqpm, 0, sizeof(rqpm));
>  	memset(&args, 0, sizeof(args));
> @@ -1240,6 +1519,8 @@ static int generic_ide_resume(struct dev
>  	struct request_pm_state rqpm;
>  	ide_task_t args;
>  
> +	acpi_ide_resume(dev);
> +
>  	memset(&rq, 0, sizeof(rq));
>  	memset(&rqpm, 0, sizeof(rqpm));
>  	memset(&args, 0, sizeof(args));
> @@ -1923,6 +2204,7 @@ static int __init ide_init(void)
>  	system_bus_speed = ide_system_bus_speed();
>  
>  	bus_register(&ide_bus_type);
> +	ide_acpi_init();
>  
>  	init_ide_data();
>  
> _
> 
> 
> -
> To unsubscribe from this list: send the line "unsubscribe linux-ide"
> in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 
> -
> To unsubscribe from this list: send the line "unsubscribe linux-ide"
> in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html


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

* Re: [PATCH 6/6 update] SATA ACPI: ata_acpi functions
  2005-12-12  0:24 [PATCH 6/6 update] SATA ACPI: ata_acpi functions Dominic ES. Ijichi
@ 2005-12-12  0:44 ` Randy.Dunlap
  0 siblings, 0 replies; 24+ messages in thread
From: Randy.Dunlap @ 2005-12-12  0:44 UTC (permalink / raw)
  To: Dominic ES. Ijichi; +Cc: randy_d_dunlap, linux-ide, axboe, jgarzik

On Mon, 12 Dec 2005 00:24:53 +0000 (GMT) Dominic ES. Ijichi wrote:

> ----- Randy.Dunlap <rdunlap@xenotime.net> wrote:
> > On Sat, 10 Dec 2005 19:01:50 +0000 Dominic Ijichi wrote:
> > 
> > > Quoting Randy Dunlap <randy_d_dunlap@linux.intel.com>:
> > > 
> > > > Dom,
> > > > 
> > > > I've updated the ata_apci.patch file to fix this bug.
> > > > I was misusing some of the ACPI memory alloc/free interfaces.
> > > > 
> > > > Updated file is at
> > > > http://www.xenotime.net/linux/SATA/2.6.15-rc/ata_acpi.patch
> > > 
> > > hi
> > > 
> > > it applies cleanly now, but unfortunately this doesnt seem to work
> > in my case. 
> > > on waking from S3 sleep there is still no disk activity and
> > terminals hang on
> > > first disk access.  dmesg attached, there's some more debug now
> > which hopefully
> > > will be helpful!
> > 
> > partial dmesg:
> > ata1: dev 0 cfg 00:045a 49:0b00 82:746b 83:5988 84:4003 85:7469
> > 86:1808 87:4003 88:003f 93:600b
> > ata1: dev 0 ATA-5, max UDMA/100, 117210240 sectors: LBA
> > ata1(0): applying bridge limits
> > do_drive_SDD: ap->id: 1, ix = 0, port#: 0, hard_port#: 0
> > do_drive_SDD: ata_id_is_sata is False
> > ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> > 
> > The drive is not reported as a SATA drive, so the patch that I wrote
> > won't work for it.  Have you tried this patch to see if it
> > works/helps
> > on your machine?
> 
> oh right.  sorry to trouble you but the list archive has a 'hole' when that patch was released, could you possibly forward it to me?

Sure, I forgot about that.  It's below for anyone who wants to try it.


> > From:	Shaohua Li <shaohua.li@intel.com>
> > To:	linux-ide <linux-ide@vger.kernel.org>, lkml
> > <linux-kernel@vger.kernel.org>
> > Subject: [RFC]add ACPI hooks for IDE suspend/resume
> > Date:	Tue, 06 Dec 2005 14:10:04 +0800



Hi,
Adding ACPI IDE hook in IDE suspend/resume. The ACPI spec
explicitly says we must call some ACPI methods to restore IDE drives.
The sequences defined by ACPI spec are:
suspend:
1. Get the DMA and PIO info from IDE channel's _GTM method.

resume:
1. Calling IDE channel's _STM to set the transfer timing setting.
2. For each drive on the IDE channel, running drive's _GTF to get the
ATA commands required to reinitialize each drive.
3. Sending the ATA commands gotton from step 2 to drives.

TODO: invoking ATA commands.

Though we didn't invoke ATA commands, this patch fixes the bug at 
http://bugzilla.kernel.org/show_bug.cgi?id=5604. And Matthew said this
actually fixes a lot of systems in his test.
I'm not familiar with IDE, so comments/suggestions are welcome.

Thanks,
Shaohua

---

 linux-2.6.15-rc5-root/drivers/ide/ide.c |  282 ++++++++++++++++++++++++++++++++
 1 files changed, 282 insertions(+)

diff -puN drivers/ide/ide.c~acpi-ide drivers/ide/ide.c
--- linux-2.6.15-rc5/drivers/ide/ide.c~acpi-ide	2005-12-07 03:01:36.000000000 +0800
+++ linux-2.6.15-rc5-root/drivers/ide/ide.c	2005-12-07 03:01:36.000000000 +0800
@@ -155,6 +155,10 @@
 #include <linux/device.h>
 #include <linux/bitops.h>
 
+#ifdef CONFIG_ACPI
+#include <linux/acpi.h>
+#endif
+
 #include <asm/byteorder.h>
 #include <asm/irq.h>
 #include <asm/uaccess.h>
@@ -1214,6 +1218,279 @@ int system_bus_clock (void)
 
 EXPORT_SYMBOL(system_bus_clock);
 
+#ifdef CONFIG_ACPI
+static int ide_acpi_find_device(struct device *dev, acpi_handle *handle)
+{
+	int i, tmp;
+	acpi_integer addr;
+
+	if (sscanf(dev->bus_id, "%u.%u", &tmp, &i) != 2)
+		return -ENODEV;
+
+	addr = (acpi_integer)i;
+	*handle = acpi_get_child(DEVICE_ACPI_HANDLE(dev->parent), addr);
+	if (!*handle)
+		return -ENODEV;
+	return 0;
+}
+
+/* This assumes the ide controller is a PCI device */
+static int ide_acpi_find_channel(struct device *dev, acpi_handle *handle)
+{
+	int num;
+	int channel;
+	acpi_integer addr;
+
+	num = sscanf(dev->bus_id, "ide%x", &channel);
+
+	if (num != 1 || !dev->parent)
+		return -ENODEV;
+	addr = (acpi_integer)channel;
+	*handle = acpi_get_child(DEVICE_ACPI_HANDLE(dev->parent), addr);
+	if (!*handle)
+		return -ENODEV;
+	return 0;
+}
+
+static struct acpi_bus_type ide_acpi_bus = {
+	.bus = &ide_bus_type,
+	.find_device = ide_acpi_find_device,
+	.find_bridge = ide_acpi_find_channel,
+};
+
+static int __init ide_acpi_init(void)
+{
+	return register_acpi_bus_type(&ide_acpi_bus);
+}
+
+/* The _GTM return package length is 5 dwords */
+#define GTM_LEN (sizeof(u32) * 5)
+struct acpi_ide_state {
+	acpi_handle handle; /* channel device's handle */
+	u32 gtm[GTM_LEN/sizeof(u32)]; /* info from _GTM */
+	struct hd_driveid id_buff[2]; /* one chanel has two drives */
+	int suspend_drives;
+	int resume_drives;
+};
+
+static void acpi_ide_data_handler(acpi_handle handle,
+	u32 function, void *context)
+{
+	/* nothing to do */
+}
+
+/* acpi data for a chanel */
+static struct acpi_ide_state *ide_alloc_acpi_state(acpi_handle handle)
+{
+	struct acpi_ide_state * state;
+	acpi_status status;
+
+	state = kzalloc(sizeof(struct acpi_ide_state), GFP_KERNEL);
+	if (!state)
+		return NULL;
+	status = acpi_attach_data(handle, acpi_ide_data_handler, state);
+	if (ACPI_FAILURE(status))
+		return NULL;
+	return state;
+}
+
+static struct acpi_ide_state *ide_get_acpi_state(acpi_handle handle)
+{
+	struct acpi_ide_state * state;
+	acpi_status status;
+
+	status = acpi_get_data(handle, acpi_ide_data_handler, (void **)&state);
+	if (ACPI_FAILURE(status))
+		return NULL;
+	return state;
+}
+
+static void ide_free_acpi_state(acpi_handle handle)
+{
+	struct acpi_ide_state *state;
+
+	state = ide_get_acpi_state(handle);
+	acpi_detach_data(handle, acpi_ide_data_handler);
+	kfree(state);
+}
+
+static int acpi_ide_suspend(struct device *dev)
+{
+	acpi_handle handle, parent_handle;
+	struct acpi_ide_state *state;
+	acpi_status status;
+	struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
+	union acpi_object *package;
+	ide_drive_t *drive = dev->driver_data;
+	int drive_id = 0;
+
+	handle = DEVICE_ACPI_HANDLE(dev);
+	if (!handle) {
+		printk(KERN_DEBUG "IDE device's ACPI handler is NULL\n");
+		return -ENODEV;
+	}
+	if (ACPI_FAILURE(acpi_get_parent(handle, &parent_handle))) {
+		printk(KERN_ERR "ACPI get parent handler error\n");
+		return -ENODEV;
+	}
+	state = ide_get_acpi_state(parent_handle);
+	if (!state) {
+		state = ide_alloc_acpi_state(parent_handle);
+		if (!state)
+			return -ENODEV;
+	}
+
+	/* invoke _GTM only once */
+	state->suspend_drives++;
+	if (state->suspend_drives > 1) {
+		drive_id = 1;
+		goto id;
+	}
+
+	status = acpi_evaluate_object(parent_handle, "_GTM", NULL, &buffer);
+	if (ACPI_FAILURE(status)) {
+		printk(KERN_ERR "Error evaluating _GTM\n");
+		return -ENODEV;
+	}
+	package = (union acpi_object *) buffer.pointer;
+	if (package->buffer.length != GTM_LEN) {
+		printk(KERN_ERR "Buffer length returned by _GTM is wrong\n");
+		acpi_os_free(buffer.pointer);
+		return -ENODEV;
+	}
+	memcpy(state->gtm, package->buffer.pointer, GTM_LEN);
+	state->handle = parent_handle;
+	acpi_os_free(buffer.pointer);
+id:
+	taskfile_lib_get_identify(drive, (u8*)&state->id_buff[drive_id]);
+	return 0;
+}
+
+static int acpi_ide_invoke_stm(struct acpi_ide_state *state)
+{
+	struct acpi_object_list input;
+	union acpi_object params[3];
+	acpi_status status;
+
+	input.count = 3;
+	input.pointer = params;
+	params[0].type = ACPI_TYPE_BUFFER;
+	params[0].buffer.length = sizeof(state->gtm);
+	params[0].buffer.pointer = (char*)state->gtm;
+
+	params[1].type = ACPI_TYPE_BUFFER;
+	params[1].buffer.length = sizeof(state->id_buff[0]);
+	params[1].buffer.pointer = (char *)&state->id_buff[0];
+
+	params[2].type = ACPI_TYPE_BUFFER;
+	params[2].buffer.length = sizeof(state->id_buff[1]);
+	params[2].buffer.pointer = (char *)&state->id_buff[1];
+
+	status = acpi_evaluate_object(state->handle, "_STM", &input, NULL);
+	if (ACPI_FAILURE(status)) {
+		printk(KERN_ERR "Evaluating _STM error\n");
+		return -ENODEV;
+	}
+	return 0;
+}
+
+static int acpi_ide_invoke_gtf(acpi_handle handle, ide_drive_t *drive)
+{
+	struct acpi_buffer output = {ACPI_ALLOCATE_BUFFER, NULL};
+#if 0
+	ide_task_t args;
+	int index = 0;
+	unsigned char *data;
+#endif
+	union acpi_object *package;
+	acpi_status status;
+
+	status = acpi_evaluate_object(handle, "_GTF", NULL, &output);
+	if (ACPI_FAILURE(status)) {
+		printk(KERN_ERR "evaluate _GTF error\n");
+		return -ENODEV;
+	}
+
+	package = (union acpi_object *) output.pointer;
+	if (package->type != ACPI_TYPE_BUFFER
+			|| (package->buffer.length % 7) != 0) {
+		acpi_os_free(output.pointer);
+		printk(KERN_ERR "_GTF returned value is wrong\n");
+		return -ENODEV;
+	}
+#if 0
+	printk(KERN_DEBUG "Start invoking _GTF commands\n");
+
+	data = package->buffer.pointer;
+	/* sumbit ATA commands */
+	while (index < package->buffer.length) {
+		memset(&args, 0, sizeof(ide_task_t));
+		args.tfRegister[IDE_ERROR_OFFSET] = data[index];
+		args.tfRegister[IDE_NSECTOR_OFFSET] = data[index + 1];
+		args.tfRegister[IDE_SECTOR_OFFSET] = data[index + 2];
+		args.tfRegister[IDE_LCYL_OFFSET] = data[index + 3];
+		args.tfRegister[IDE_HCYL_OFFSET] = data[index + 4];
+		args.tfRegister[IDE_SELECT_OFFSET] = data[index + 5];
+		args.tfRegister[IDE_STATUS_OFFSET] = data[index + 6];
+		args.command_type = IDE_DRIVE_TASK_NO_DATA;
+		args.handler = &task_no_data_intr;
+		/* submit command */
+		index += 7;
+	}
+#endif
+	acpi_os_free(output.pointer);
+	return 0;
+}
+
+static int acpi_ide_resume(struct device *dev)
+{
+	acpi_handle handle, parent_handle;
+	struct acpi_ide_state *state;
+	ide_drive_t *drive = dev->driver_data;
+
+	handle = DEVICE_ACPI_HANDLE(dev);
+	if (!handle) {
+		printk(KERN_DEBUG "IDE device's ACPI handler is NULL\n");
+		return -ENODEV;
+	}
+	if (ACPI_FAILURE(acpi_get_parent(handle, &parent_handle))) {
+		printk(KERN_ERR "ACPI get parent handler error\n");
+		return -ENODEV;
+	}
+	state = ide_get_acpi_state(parent_handle);
+	if (state == NULL)
+		return -ENODEV;
+
+	/* invoke _STM only once */
+	state->resume_drives++;
+	if (state->resume_drives == 1) {
+		printk(KERN_DEBUG "Start invoking _STM\n");
+		if (acpi_ide_invoke_stm(state))
+			return -ENODEV;
+	}
+
+	if (state->resume_drives == state->suspend_drives)
+		ide_free_acpi_state(parent_handle);
+	return acpi_ide_invoke_gtf(handle, drive);
+}
+
+#else
+static int __init ide_acpi_init(void)
+{
+	return 0;
+}
+
+static int acpi_ide_suspend(struct device *dev)
+{
+	return 0;
+}
+
+static int acpi_ide_resume(struct device *dev)
+{
+	return 0;
+}
+#endif
+
 static int generic_ide_suspend(struct device *dev, pm_message_t state)
 {
 	ide_drive_t *drive = dev->driver_data;
@@ -1221,6 +1498,8 @@ static int generic_ide_suspend(struct de
 	struct request_pm_state rqpm;
 	ide_task_t args;
 
+	acpi_ide_suspend(dev);
+
 	memset(&rq, 0, sizeof(rq));
 	memset(&rqpm, 0, sizeof(rqpm));
 	memset(&args, 0, sizeof(args));
@@ -1240,6 +1519,8 @@ static int generic_ide_resume(struct dev
 	struct request_pm_state rqpm;
 	ide_task_t args;
 
+	acpi_ide_resume(dev);
+
 	memset(&rq, 0, sizeof(rq));
 	memset(&rqpm, 0, sizeof(rqpm));
 	memset(&args, 0, sizeof(args));
@@ -1923,6 +2204,7 @@ static int __init ide_init(void)
 	system_bus_speed = ide_system_bus_speed();
 
 	bus_register(&ide_bus_type);
+	ide_acpi_init();
 
 	init_ide_data();
 
_


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


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

* Re: [PATCH 6/6 update] SATA ACPI: ata_acpi functions
@ 2005-12-12  0:24 Dominic ES. Ijichi
  2005-12-12  0:44 ` Randy.Dunlap
  0 siblings, 1 reply; 24+ messages in thread
From: Dominic ES. Ijichi @ 2005-12-12  0:24 UTC (permalink / raw)
  To: Randy; +Cc: randy d dunlap, linux-ide, axboe, jgarzik

----- Randy.Dunlap <rdunlap@xenotime.net> wrote:
> On Sat, 10 Dec 2005 19:01:50 +0000 Dominic Ijichi wrote:
> 
> > Quoting Randy Dunlap <randy_d_dunlap@linux.intel.com>:
> > 
> > > Dom,
> > > 
> > > I've updated the ata_apci.patch file to fix this bug.
> > > I was misusing some of the ACPI memory alloc/free interfaces.
> > > 
> > > Updated file is at
> > > http://www.xenotime.net/linux/SATA/2.6.15-rc/ata_acpi.patch
> > 
> > hi
> > 
> > it applies cleanly now, but unfortunately this doesnt seem to work
> in my case. 
> > on waking from S3 sleep there is still no disk activity and
> terminals hang on
> > first disk access.  dmesg attached, there's some more debug now
> which hopefully
> > will be helpful!
> 
> partial dmesg:
> ata1: dev 0 cfg 00:045a 49:0b00 82:746b 83:5988 84:4003 85:7469
> 86:1808 87:4003 88:003f 93:600b
> ata1: dev 0 ATA-5, max UDMA/100, 117210240 sectors: LBA
> ata1(0): applying bridge limits
> do_drive_SDD: ap->id: 1, ix = 0, port#: 0, hard_port#: 0
> do_drive_SDD: ata_id_is_sata is False
> ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> 
> The drive is not reported as a SATA drive, so the patch that I wrote
> won't work for it.  Have you tried this patch to see if it
> works/helps
> on your machine?

oh right.  sorry to trouble you but the list archive has a 'hole' when that patch was released, could you possibly forward it to me?

cheers
dom

> 
> From:	Shaohua Li <shaohua.li@intel.com>
> To:	linux-ide <linux-ide@vger.kernel.org>, lkml
> <linux-kernel@vger.kernel.org>
> Subject: [RFC]add ACPI hooks for IDE suspend/resume
> Date:	Tue, 06 Dec 2005 14:10:04 +0800
> 
> 
> Thanks,
> ---
> ~Randy
> -
> To unsubscribe from this list: send the line "unsubscribe linux-ide"
> in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html


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

end of thread, other threads:[~2005-12-12  2:12 UTC | newest]

Thread overview: 24+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
     [not found] <20051202100119.032b242e.randy_d_dunlap@linux.intel.com>
2005-12-02 18:03 ` [PATCH 1/6] libata_suspend (Jens) Randy Dunlap
2005-12-02 18:04 ` [PATCH 2/6] SATA ACPI: make/config changes Randy Dunlap
2005-12-02 18:05 ` [PATCH 3/6] SATA ACPI: libata.h changes Randy Dunlap
2005-12-02 18:07 ` [PATCH 4/6] SATA ACPI: call new ACPI functions Randy Dunlap
2005-12-02 18:07 ` [PATCH 5/6] SATA ACPI: kernel-doc Randy Dunlap
2005-12-02 18:08 ` [PATCH 6/6] SATA ACPI: ata_acpi functions Randy Dunlap
2005-12-06 21:58   ` [PATCH 6/6 update] " Randy Dunlap
2005-12-07 16:36     ` Dominic Ijichi
2005-12-07 17:16       ` Randy Dunlap
2005-12-07 17:24         ` Dominic Ijichi
2005-12-07 18:34           ` Randy Dunlap
2005-12-08  9:43             ` Dominic Ijichi
2005-12-09  0:16               ` Randy Dunlap
2005-12-09  0:20                 ` Dominic Ijichi
2005-12-09  1:03                   ` Randy Dunlap
2005-12-09  1:10                     ` Randy Dunlap
2005-12-09 18:52                       ` Randy Dunlap
2005-12-10 19:01                         ` Dominic Ijichi
2005-12-12  0:16                           ` Randy.Dunlap
2005-12-02 18:15 ` [PATCH 0/6] SATA use ACPI methods for PM Randy Dunlap
2005-12-12  0:24 [PATCH 6/6 update] SATA ACPI: ata_acpi functions Dominic ES. Ijichi
2005-12-12  0:44 ` Randy.Dunlap
2005-12-12  1:24 Dominic ES. Ijichi
2005-12-12  2:13 ` Randy.Dunlap

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.