From mboxrd@z Thu Jan 1 00:00:00 1970 From: "Dominic ES. Ijichi" Subject: Re: [PATCH 6/6 update] SATA ACPI: ata_acpi functions Date: Mon, 12 Dec 2005 01:24:04 +0000 (GMT) Message-ID: <20326763.31241134350644508.JavaMail.root@willow.ijichi.org> Mime-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 7bit Return-path: Received: from willow.ijichi.org ([217.206.220.50]:11436 "EHLO willow.ijichi.org") by vger.kernel.org with ESMTP id S1750923AbVLLBYG (ORCPT ); Sun, 11 Dec 2005 20:24:06 -0500 Sender: linux-ide-owner@vger.kernel.org List-Id: linux-ide@vger.kernel.org To: Randy Cc: randy d dunlap , linux-ide@vger.kernel.org, axboe@suse.de, jgarzik@pobox.com ----- Randy.Dunlap wrote: > On Mon, 12 Dec 2005 00:24:53 +0000 (GMT) Dominic ES. Ijichi wrote: > > > ----- Randy.Dunlap wrote: > > > On Sat, 10 Dec 2005 19:01:50 +0000 Dominic Ijichi wrote: > > > > > > > Quoting Randy Dunlap : > > > > > > > > > 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 > > > To: linux-ide , lkml > > > > > > 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 > #include > > +#ifdef CONFIG_ACPI > +#include > +#endif > + > #include > #include > #include > @@ -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