SATA ACPI make/config
Subsystems (3)
A message that is not in the archive (sent off-list or not yet received): [email protected]
PATCH 1/7 SATA suspend/resume support (Jens)
From: Jens Axboe <[email protected]>
Add libata suspend/resume support.
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(-)
---
drivers/scsi/ata_piix.c +4 -0
@@ -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 = {
drivers/scsi/libata-core.c +122 -0
138 lines not on this page · raw message
drivers/scsi/libata-scsi.c +16 -0
@@ -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
drivers/scsi/scsi_sysfs.c +33 -2
@@ -263,9 +263,40 @@ static int scsi_bus_match(struct devicereturn (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 )
include/linux/ata.h +2 -0
@@ -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 */
include/linux/libata.h +7 -0
@@ -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_iopextern 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 scsiextern 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 );/*
include/scsi/scsi_host.h +6 -0
@@ -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;
---
Re: [PATCH 1/7] SATA suspend/resume support (Jens)
Quoted 4 lines · Randy Dunlap
From: Jens Axboe <[email protected]>
Add libata suspend/resume support.
Quoted 8 lines
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(-)
What happened to the patch you were attempting to resurrect, which implemented scsi suspend/resume a better way?
Jeff
Re: [PATCH 1/7] SATA suspend/resume support (Jens)
Quoted 14 lines · On Wed, 14 Dec 2005 17:07:38 -0500 Jeff Garzik <[email protected]> wrote:
Quoted 4 lines · Randy Dunlap
From: Jens Axboe <[email protected]>
Add libata suspend/resume support.
Quoted 8 lines
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(-)
Quoted 2 lines
What happened to the patch you were attempting to resurrect, which implemented scsi suspend/resume a better way?
The last incarnation of it is still at
http://www.xenotime.net/linux/scsi/scsi-susres-devattr.patch
It is missing some linkage (maybe ->ops) between layers. I was getting close to zero feedback on it --> it went stale, so I decided to try make make Jens's patch work with ACPI additions.
---
~Randy
PATCH 2/7 SATA ACPI make/config
In reply to a message not in the archiveFrom: Randy Dunlap <[email protected]>
Add ata_acpi in Makefile and Kconfig.
--- drivers/scsi/Kconfig | 5 +++++ drivers/scsi/Makefile | 1 + 2 files changed, 6 insertions(+)
drivers/scsi/Makefile +1 -0
@@ -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/
drivers/scsi/Kconfig +5 -0
@@ -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
---
Quoted 5 lines · Randy Dunlap
From: Randy Dunlap <[email protected]>
Add
ata_acpiinMakefileandKconfig.Signed-off-by Randy Dunlap <[email protected]>
obviously OK (depending on other things)
PATCH 3/7 SATA ACPI linux/libata.h update
In reply to a message not in the archiveFrom: Randy Dunlap <[email protected]>
Add ACPI data pointer/length holders.
--- include/linux/libata.h | 8 ++++++++ 1 files changed, 8 insertions(+)
include/linux/libata.h +8 -0
@@ -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,13 @@ struct ata_device {u16 cylinders;/* Number of cylinders */ u16 heads;/* Number of heads */ u16 sectors;/* Number of sectors per track */ + +#ifdef CONFIG_SCSI_SATA_ACPI +/* ACPI objects info */ +acpi_handle obj_handle; +acpi_size gtf_length; +u8 *gtf_address; +#endif };struct ata_port {
---
Re: [PATCH 3/7] SATA ACPI linux/libata.h update
Quoted 5 lines · Randy Dunlap
From: Randy Dunlap <[email protected]>
Add ACPI data pointer/length holders.
Signed-off-by Randy Dunlap <[email protected]>
Why does struct ata_device need to remember this info at all?
Jeff
Re: [PATCH 3/7] SATA ACPI linux/libata.h update
Quoted 8 lines · On Wed, 14 Dec 2005 17:08:33 -0500 Jeff Garzik <[email protected]> wrote:
Quoted 5 lines · Randy Dunlap
From: Randy Dunlap <[email protected]>
Add ACPI data pointer/length holders.
Signed-off-by Randy Dunlap <[email protected]>Why does struct
ata_deviceneed to remember this info at all?
Uh... I dunno. I'll see if I can just read that data during resume.
---
~Randy
PATCH 4/7 call/invoke SATA ACPI suspend/resume functions
In reply to a message not in the archiveFrom: Randy Dunlap <[email protected]>
Add calls to ACPI methods for SATA drives.
--- drivers/scsi/libata-core.c | 4 ++++ drivers/scsi/libata.h | 26 ++++++++++++++++++++++++++ 2 files changed, 30 insertions(+)
drivers/scsi/libata-core.c +4 -0
@@ -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_portif (ap->flags &ATA_FLAG_PORT_DISABLED )return ; +do_drive_update_taskfiles (ap); +if (ap->ops->post_set_mode) ap->ops->post_set_mode (ap);
drivers/scsi/libata.h +26 -0
@@ -53,6 +53,32 @@ extern int ata_task_ioctl(struct scsi_deextern int ata_cmd_ioctl (struct scsi_device *scsidev,void __user *arg); +/* ata_acpi.c */ +#ifdef CONFIG_SCSI_SATA_ACPI +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); +#else +static inline int do_drive_SDD (struct ata_port *ap,unsigned int ix) +{ +return 0 ; +} +static inline int do_drive_get_GTF (struct ata_port *ap,struct ata_device *atadev) +{ +return 0 ; +} +static inline int do_drive_set_taskfiles (struct ata_port *ap,struct ata_device *atadev) +{ +return 0 ; +} +static inline int do_drive_update_taskfiles (struct ata_port *ap) +{ +return 0 ; +} +#endif + +/* libata-scsi.c */ extern void ata_scsi_scan_host (struct ata_port *ap);extern int ata_scsi_error (struct Scsi_Host *host);
---
Re: [PATCH 4/7] call/invoke SATA ACPI suspend/resume functions
Quoted 22 lines · Randy Dunlap
From: Randy Dunlap <[email protected]>
Add calls to ACPI methods for SATA drives.
Signed-off-by Randy Dunlap <[email protected]>--- drivers/scsi/libata-core.c | 4 ++++ drivers/scsi/libata.h | 26 ++++++++++++++++++++++++++ 2 files changed, 30 insertions(+)drivers/scsi/libata-core.c +2
-0@@ -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); }/**
drivers/scsi/libata-core.c static void ata_set_mode(struct ata_port · line 1793
Quoted 8 lines
drivers/scsi/libata-core.c +2
-0@@ -1784,6 +1786,8 @@ static void ata_set_mode(struct ata_portif (ap->flags &ATA_FLAG_PORT_DISABLED )return ; +do_drive_update_taskfiles (ap); +if (ap->ops->post_set_mode) ap->ops->post_set_mode (ap);
Mostly OK.
1) The function names are awful. I would suggest ata_acpi_push_id() and ata_acpi_exec_tfs() instead.
2) The call to do_drive_update_taskfiles() should be done in ata_bus_probe(), not inside ata_set_mode() where it is essentially hidden amongst code that is dedicated to a single purpose, getting the data xfer timings.
Jeff
PATCH 5/7 SATA ACPI kernel-doc
In reply to a message not in the archiveFrom: Randy Dunlap <[email protected]>
Add ata_acpi.c to libata kernel-doc template file.
--- Documentation/DocBook/libata.tmpl | 6 ++++++ 1 files changed, 6 insertions(+)
Documentation/DocBook/libata.tmpl +6 -0
@@ -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 & exceptions</title>
---
Re: [PATCH 5/7] SATA ACPI kernel-doc
Quoted 5 lines · Randy Dunlap
From: Randy Dunlap <[email protected]>
Add
ata_acpi.cto libata kernel-doc template file.Signed-off-by Randy Dunlap <[email protected]>
obviously OK
PATCH 6/7 SATA ACPI suspend/resume functions
In reply to a message not in the archiveFrom: Randy Dunlap <[email protected]>
Add support for ACPI methods to SATA suspend/resume.
--- drivers/scsi/ata_acpi.c | 496 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 496 insertions(+)
drivers/scsi/ata_acpi.c new file +496 -0
@@ -0,0 +1,496 @@ +/* +* 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_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_os_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)) { +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_os_free (output.pointer); + goto out; + } + + out_obj = output.pointer; +if (out_obj->type !=ACPI_TYPE_BUFFER ) { +acpi_os_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);
---
Re: [PATCH 6/7] SATA ACPI suspend/resume functions
Quoted 61 lines · Randy Dunlap
From: Randy Dunlap <[email protected]>
Add support for ACPI methods to SATA suspend/resume.
Signed-off-by Randy Dunlap <[email protected]>--- drivers/scsi/ata_acpi.c | 496 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 496 insertions(+)drivers/scsi/ata_acpi.c new file +49
-0@@ -0,0 +1,496 @@ +/* +* 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 ];
drivers/scsi/ata_acpi.c line 59
Quoted 10 lines
drivers/scsi/ata_acpi.c new file +10
-0+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; +}
this should be in generic code somewhere
Quoted 15 lines
drivers/scsi/ata_acpi.c new file +15
-0+/** +* 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);
drivers/scsi/ata_acpi.c line 85
Quoted 10 lines
drivers/scsi/ata_acpi.c new file +10
-0+/* 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 ; +}
this should be in generic code somewhere
Quoted 147 lines
drivers/scsi/ata_acpi.c new file +145
-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_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_os_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);
drivers/scsi/ata_acpi.c line 242
Quoted 10 lines
drivers/scsi/ata_acpi.c new file +10
-0+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;
libata runs swap_buf_le16() on atadev->id. Are you sure you don't need swap the buffer before sending?
Quoted 31 lines
drivers/scsi/ata_acpi.c new file +31
-0+/* 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) +{
drivers/scsi/ata_acpi.c line 283
Quoted 10 lines
drivers/scsi/ata_acpi.c new file +10
-0+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 ? */
yes, you should check for port disabled too
Quoted 95 lines
drivers/scsi/ata_acpi.c new file +95
-0+ 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)) { +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_os_free (output.pointer); + goto out; + } + + out_obj = output.pointer; +if (out_obj->type !=ACPI_TYPE_BUFFER ) { +acpi_os_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 */
drivers/scsi/ata_acpi.c line 388
Quoted 10 lines
drivers/scsi/ata_acpi.c new file +10
-0+ 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" );
delete this entire code block
Quoted 26 lines
drivers/scsi/ata_acpi.c new file +26
-0+ }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;
drivers/scsi/ata_acpi.c line 424
Quoted 10 lines
drivers/scsi/ata_acpi.c new file +10
-0+ +// 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);
always use this code block.
note that 'upstream' branch has Tejun's ata_exec_internal() changes, which cause Jens' suspend patch as well as the above code to change.
Quoted 35 lines
drivers/scsi/ata_acpi.c new file +35
-0+ }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);
drivers/scsi/ata_acpi.c line 469
Quoted 10 lines
drivers/scsi/ata_acpi.c new file +10
-0+ 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); + }
stop the loop on error
Quoted 11 lines
drivers/scsi/ata_acpi.c new file +11
-0+ 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.
drivers/scsi/ata_acpi.c line 491
Quoted 10 lines
drivers/scsi/ata_acpi.c new file +10
-0+*/ +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]);
what's the point of continuing to loop, but simply avoiding the call, on error? why not just stop the loop?
Quoted 10 lines
drivers/scsi/ata_acpi.c new file +5
-1+ } + +return ret; +} +EXPORT_SYMBOL_GPL (do_drive_update_taskfiles); ---
PATCH 7/7 SATA ACPI debug-only output
In reply to a message not in the archiveFrom: Randy Dunlap <[email protected]>
Add some extra debug-only output.
--- drivers/scsi/ata_acpi.c | 17 ++++++++++++----- drivers/scsi/libata-core.c | 6 +++--- 2 files changed, 15 insertions(+), 8 deletions(-)
drivers/scsi/ata_acpi.c +12 -5
@@ -183,9 +183,10 @@ static int get_sata_adr(struct device *d winfo->drivenum = drive; status =acpi_get_devices (NULL , get_devices, winfo,NULL ); -if (ACPI_FAILURE (status)) +if (ACPI_FAILURE (status)) { +DEBPRINT ("acpi_get_devices failed\n" ); err = -ENODEV ; -else { + }else { *dev_adr = winfo->sata_adr; atadev->obj_handle = winfo->obj_handle; err =0 ;
@@ -219,19 +220,25 @@ int do_drive_SDD(struct ata_port *ap, un __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)) +if (!ata_id_is_sata (atadev->id)) { +DEBPRINT ("ata_id_is_sata is False\n" ); 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 ) +if (err <0 ) { +DEBPRINT ("get_dev_handle failed\n" ); 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) +if (err <0 || dev_adr ==SATA_ADR_RSVD || !atadev->obj_handle) { +DEBPRINT ("get_sata_adr failed\n" ); goto out; + }/* Give the drive Identify data to the drive via the _SDD method */ /* _SDD: set up input parameters */
drivers/scsi/libata-core.c +3 -3
@@ -1185,11 +1185,11 @@ retry:/* print device capabilities */ printk (KERN_DEBUG "ata%u: dev %u cfg " -"49:%04x 82:%04x 83:%04x 84:%04x 85:%04x 86:%04x 87:%04x 88:%04x\n" , - ap->id, device, dev->id[49 ], +"00:%04x 49:%04x 82:%04x 83:%04x 84:%04x 85:%04x 86:%04x 87:%04x 88:%04x 93:%04x\n" , + ap->id, device, dev->id[0 ], dev->id[49 ], dev->id[82 ], dev->id[83 ], dev->id[84 ], dev->id[85 ], dev->id[86 ], dev->id[87 ], - dev->id[88 ]); + dev->id[88 ], dev->id[93 ]);/* * common ATA, ATAPI feature tests
---
Re: [PATCH 7/7] SATA ACPI debug-only output
Quoted 13 lines · Randy Dunlap
From: Randy Dunlap <[email protected]>
Add some extra debug-only output.
Signed-off-by Randy Dunlap <[email protected]>--- drivers/scsi/ata_acpi.c | 17 ++++++++++++----- drivers/scsi/libata-core.c | 6 +++--- 2 files changed, 15 insertions(+), 8 deletions(-)
drivers/scsi/ata_acpi.c static int get_sata_adr(struct device *d · line 187
Quoted 6 lines
drivers/scsi/ata_acpi.c +2
-1@@ -183,9 +183,10 @@ static int get_sata_adr(struct device *d winfo->drivenum = drive; status =acpi_get_devices (NULL , get_devices, winfo,NULL ); -if (ACPI_FAILURE (status)) +if (ACPI_FAILURE (status)) { +DEBPRINT ("acpi_get_devices failed\n" );
don't invent your own debugprint, use libata's
Re: [PATCH 7/7] SATA ACPI debug-only output
Quoted 6 lines · On Wed, 14 Dec 2005 17:23:58 -0500 Jeff Garzik <[email protected]> wrote:
Quoted 5 lines · Randy Dunlap
From: Randy Dunlap <[email protected]>
Add some extra debug-only output.
Quoted 6 lines
drivers/scsi/ata_acpi.c static int get_sata_adr(struct device *d · line 187
Quoted 4 lines
drivers/scsi/ata_acpi.c +2
-1status =acpi_get_devices (NULL , get_devices, winfo,NULL ); -if (ACPI_FAILURE (status)) +if (ACPI_FAILURE (status)) { +DEBPRINT ("acpi_get_devices failed\n" );don't invent your own debugprint, use libata's
DPRINTK() is too verbose for me. Would you accept something that just does debug printing for probe/discovery/enumeration and not on every I/O? then I could use the probe/discovery/enumeration level of debug printing.
---
~Randy
Re: [PATCH 7/7] SATA ACPI debug-only output
Quoted 19 lines · Randy Dunlap
Quoted 7 lines · On Wed, 14 Dec 2005 17:23:58 -0500 Jeff Garzik <[email protected]> wrote:
Quoted 5 lines · Randy Dunlap
From: Randy Dunlap <[email protected]>
Add some extra debug-only output.
Quoted 6 lines
drivers/scsi/ata_acpi.c static int get_sata_adr(struct device *d · line 187
Quoted 4 lines
status = acpi_get_devices(NULL, get_devices, winfo, NULL);drivers/scsi/ata_acpi.c +2
-1-if (ACPI_FAILURE (status)) +if (ACPI_FAILURE (status)) { +DEBPRINT ("acpi_get_devices failed\n" );don't invent your own debugprint, use libata's
Quoted 4 lines
DPRINTK()is too verbose for me. Would you accept something that just does debug printing for probe/discovery/enumeration and not on every I/O? then I could use the probe/discovery/enumeration level of debug printing.
Dig up the patches from Borislav Petkov on linux-ide that made debug messages more fine-grained. Then we can specific things on and off at runtime...
Jeff
Re: [PATCH 7/7] SATA ACPI debug-only output
Quoted 20 lines · On Wed, 14 Dec 2005 17:42:00 -0500 Jeff Garzik <[email protected]> wrote:
Quoted 19 lines · Randy Dunlap
Quoted 13 lines · On Wed, 14 Dec 2005 17:23:58 -0500 Jeff Garzik <[email protected]> wrote:
drivers/scsi/ata_acpi.c static int get_sata_adr(struct device *d · line 187
Quoted 9 lines · Randy Dunlap
From: Randy Dunlap <[email protected]>
Add some extra debug-only output.
status = acpi_get_devices(NULL, get_devices, winfo, NULL);drivers/scsi/ata_acpi.c +2
-1-if (ACPI_FAILURE (status)) +if (ACPI_FAILURE (status)) { +DEBPRINT ("acpi_get_devices failed\n" );don't invent your own debugprint, use libata's
Quoted 8 lines
Quoted 4 lines
DPRINTK()is too verbose for me. Would you accept something that just does debug printing for probe/discovery/enumeration and not on every I/O? then I could use the probe/discovery/enumeration level of debug printing.Dig up the patches from Borislav Petkov on linux-ide that made debug messages more fine-grained. Then we can specific things on and off at runtime...
OK, I found 1/2 in the archive but not 2/2. Borislav, did you send 2/2? Can you resend it, please?
---
~Randy