* in HP nx8220 S3 resume does not work in stock kernels 2.6.15-2.6.19. Ide light stays on.
[not found] <bcfd8020612010936h276a1d04mf2cc574cf62cd242@mail.gmail.com>
@ 2006-12-05 6:48 ` Honkala Mikko
2006-12-05 11:20 ` Pavel Machek
0 siblings, 1 reply; 2+ messages in thread
From: Honkala Mikko @ 2006-12-05 6:48 UTC (permalink / raw)
To: linux-kernel
[-- Attachment #1: Type: text/plain, Size: 312 bytes --]
Hi,
in HP nx8220 S3 resume does not work in stock kernels 2.6.15-2.6.19.
Ide light stays on.
The attached patch for ide.c for 2.6.18.2 fixes this for me, but the
patch does not apply anymore in 2.6.19.
http://bugzilla.kernel.org/show_bug.cgi?id=2039
http://bugzilla.kernel.org/show_bug.cgi?id=5604
-honkkis
[-- Attachment #2: linux-2.6.18.2_ide-gtm-stm.diff --]
[-- Type: text/plain, Size: 7281 bytes --]
--- linux-2.6.18.2-orig/drivers/ide/ide.c 2006-11-04 03:33:58.000000000 +0200
+++ linux-2.6.18.2/drivers/ide/ide.c 2006-11-11 00:44:44.000000000 +0200
@@ -1207,6 +1207,237 @@
EXPORT_SYMBOL(system_bus_clock);
+#if 1
+#include <linux/acpi.h>
+#define DBG(x...) printk(x)
+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 = 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 = 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);
+}
+
+#define MAX_DEVICES 10
+#define GTM_LEN (sizeof(u32) * 5)
+static struct acpi_ide_stat {
+ acpi_handle handle; /* channel device"s handle */
+ u32 gtm[GTM_LEN/sizeof(u32)]; /* info from _GTM */
+ struct hd_driveid id_buff[2];
+ int channel_handled;
+} device_state[MAX_DEVICES];
+
+static struct acpi_ide_stat *ide_get_acpi_state(acpi_handle handle)
+{
+ int i;
+ for (i = 0; i < MAX_DEVICES; i ++)
+ if (device_state[i].handle == handle)
+ break;
+ if (i < MAX_DEVICES)
+ return &device_state[i];
+ for (i = 0; i < MAX_DEVICES; i ++)
+ if (device_state[i].handle == NULL)
+ break;
+ if (i >= MAX_DEVICES)
+ return NULL;
+
+ memset(&device_state[i], 0, sizeof(struct acpi_ide_stat));
+ return &device_state[i];
+}
+
+int acpi_ide_suspend(struct device *dev)
+{
+ acpi_handle handle, parent_handle;
+ struct acpi_ide_stat *stat;
+ 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) {
+ DBG("IDE device 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;
+ }
+ stat = ide_get_acpi_state(parent_handle);
+ if (stat == NULL)
+ return -ENODEV;
+ if (stat->channel_handled) {
+ 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");
+ kfree(buffer.pointer);
+ return -ENODEV;
+ }
+ memcpy(stat->gtm, package->buffer.pointer, GTM_LEN);
+ stat->handle = parent_handle;
+ stat->channel_handled = 1;
+ kfree(buffer.pointer);
+id:
+ taskfile_lib_get_identify(drive, &stat->id_buff[drive_id]);
+ DBG("GTM info %x,%x,%x,%x,%x\n", stat->gtm[0],
+ stat->gtm[1], stat->gtm[2],
+ stat->gtm[3], stat->gtm[4]);
+ return 0;
+}
+
+static int acpi_ide_stm(struct acpi_ide_stat *stat)
+{
+ 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(stat->gtm);
+ params[0].buffer.pointer = (char*)stat->gtm;
+
+ params[1].type = ACPI_TYPE_BUFFER;
+ params[1].buffer.length = sizeof(stat->id_buff[0]);
+ params[1].buffer.pointer = (char *)&stat->id_buff[0];
+
+ params[2].type = ACPI_TYPE_BUFFER;
+ params[2].buffer.length = sizeof(stat->id_buff[1]);
+ params[2].buffer.pointer = (char *)&stat->id_buff[1];
+
+ status = acpi_evaluate_object(stat->handle, "_STM", &input, NULL);
+ if (ACPI_FAILURE(status)) {
+ printk(KERN_ERR "Evaluating _STM error\n");
+ return -ENODEV;
+ }
+ return 0;
+}
+
+static int acpi_ide_gtf(acpi_handle handle, ide_drive_t *drive)
+{
+ struct acpi_buffer output = {ACPI_ALLOCATE_BUFFER, NULL};
+ ide_task_t args;
+ int index = 0;
+ unsigned char *data;
+ union acpi_object *package = NULL;
+ 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) {
+ kfree(output.pointer);
+ printk(KERN_ERR "_GTF returned value is wrong\n");
+ return -ENODEV;
+ }
+ printk("start GTF\n");
+
+ data = package->buffer.pointer;
+ 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;
+ printk("data %x,%x,%x,%x,%x,%x,%x\n",
+ data[index], data[index+1], data[index+2],
+ data[index+3],data[index+4],data[index+5],
+ data[index+6]);
+ /* submit command request */
+// printk("return value %d\n", ide_raw_taskfile(drive, &args, NULL));
+ index += 7;
+ }
+ kfree(output.pointer);
+ return 0;
+}
+
+int acpi_ide_resume(struct device *dev)
+{
+ acpi_handle handle, parent_handle;
+ struct acpi_ide_stat *stat;
+ ide_drive_t *drive = dev->driver_data;
+
+ handle = DEVICE_ACPI_HANDLE(dev);
+ if (!handle) {
+ DBG("IDE device 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;
+ }
+ stat = ide_get_acpi_state(parent_handle);
+ if (stat == NULL || stat->handle != parent_handle)
+ return -ENODEV;
+
+ if (stat->channel_handled == 0) {
+ stat->handle = NULL;
+ goto gtf;
+ }
+DBG("Start STM\n");
+ if (acpi_ide_stm(stat))
+ return -ENODEV;
+ stat->channel_handled = 0;
+gtf:
+ return acpi_ide_gtf(handle, drive);
+}
+#endif
+
static int generic_ide_suspend(struct device *dev, pm_message_t state)
{
ide_drive_t *drive = dev->driver_data;
@@ -1223,6 +1454,7 @@
rqpm.pm_step = ide_pm_state_start_suspend;
rqpm.pm_state = state.event;
+ acpi_ide_suspend(dev);
return ide_do_drive_cmd(drive, &rq, ide_wait);
}
@@ -1232,7 +1464,7 @@
struct request rq;
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));
@@ -1994,6 +2226,7 @@
printk(KERN_INFO "Uniform Multi-Platform E-IDE driver " REVISION "\n");
system_bus_speed = ide_system_bus_speed();
+ide_acpi_init();
bus_register(&ide_bus_type);
init_ide_data();
^ permalink raw reply [flat|nested] 2+ messages in thread
* Re: in HP nx8220 S3 resume does not work in stock kernels 2.6.15-2.6.19. Ide light stays on.
2006-12-05 6:48 ` in HP nx8220 S3 resume does not work in stock kernels 2.6.15-2.6.19. Ide light stays on Honkala Mikko
@ 2006-12-05 11:20 ` Pavel Machek
0 siblings, 0 replies; 2+ messages in thread
From: Pavel Machek @ 2006-12-05 11:20 UTC (permalink / raw)
To: Honkala Mikko; +Cc: linux-kernel
Hi!
> in HP nx8220 S3 resume does not work in stock kernels 2.6.15-2.6.19.
> Ide light stays on.
>
> The attached patch for ide.c for 2.6.18.2 fixes this for me, but the
> patch does not apply anymore in 2.6.19.
>
> http://bugzilla.kernel.org/show_bug.cgi?id=2039
> http://bugzilla.kernel.org/show_bug.cgi?id=5604
I think I've seen better versions of this patch, already...?
Ask ACPI people.
> --- linux-2.6.18.2-orig/drivers/ide/ide.c 2006-11-04 03:33:58.000000000 +0200
> +++ linux-2.6.18.2/drivers/ide/ide.c 2006-11-11 00:44:44.000000000 +0200
> @@ -1207,6 +1207,237 @@
>
> EXPORT_SYMBOL(system_bus_clock);
>
> +#if 1
> +#include <linux/acpi.h>
> +#define DBG(x...) printk(x)
...this definitely needs to move to some ACPIish place.
Pavel
> +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 = 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 = 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);
> +}
> +
> +#define MAX_DEVICES 10
> +#define GTM_LEN (sizeof(u32) * 5)
> +static struct acpi_ide_stat {
> + acpi_handle handle; /* channel device"s handle */
> + u32 gtm[GTM_LEN/sizeof(u32)]; /* info from _GTM */
> + struct hd_driveid id_buff[2];
> + int channel_handled;
> +} device_state[MAX_DEVICES];
> +
> +static struct acpi_ide_stat *ide_get_acpi_state(acpi_handle handle)
> +{
> + int i;
> + for (i = 0; i < MAX_DEVICES; i ++)
> + if (device_state[i].handle == handle)
> + break;
> + if (i < MAX_DEVICES)
> + return &device_state[i];
> + for (i = 0; i < MAX_DEVICES; i ++)
> + if (device_state[i].handle == NULL)
> + break;
> + if (i >= MAX_DEVICES)
> + return NULL;
> +
> + memset(&device_state[i], 0, sizeof(struct acpi_ide_stat));
> + return &device_state[i];
> +}
> +
> +int acpi_ide_suspend(struct device *dev)
> +{
> + acpi_handle handle, parent_handle;
> + struct acpi_ide_stat *stat;
> + 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) {
> + DBG("IDE device 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;
> + }
> + stat = ide_get_acpi_state(parent_handle);
> + if (stat == NULL)
> + return -ENODEV;
> + if (stat->channel_handled) {
> + 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");
> + kfree(buffer.pointer);
> + return -ENODEV;
> + }
> + memcpy(stat->gtm, package->buffer.pointer, GTM_LEN);
> + stat->handle = parent_handle;
> + stat->channel_handled = 1;
> + kfree(buffer.pointer);
> +id:
> + taskfile_lib_get_identify(drive, &stat->id_buff[drive_id]);
> + DBG("GTM info %x,%x,%x,%x,%x\n", stat->gtm[0],
> + stat->gtm[1], stat->gtm[2],
> + stat->gtm[3], stat->gtm[4]);
> + return 0;
> +}
> +
> +static int acpi_ide_stm(struct acpi_ide_stat *stat)
> +{
> + 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(stat->gtm);
> + params[0].buffer.pointer = (char*)stat->gtm;
> +
> + params[1].type = ACPI_TYPE_BUFFER;
> + params[1].buffer.length = sizeof(stat->id_buff[0]);
> + params[1].buffer.pointer = (char *)&stat->id_buff[0];
> +
> + params[2].type = ACPI_TYPE_BUFFER;
> + params[2].buffer.length = sizeof(stat->id_buff[1]);
> + params[2].buffer.pointer = (char *)&stat->id_buff[1];
> +
> + status = acpi_evaluate_object(stat->handle, "_STM", &input, NULL);
> + if (ACPI_FAILURE(status)) {
> + printk(KERN_ERR "Evaluating _STM error\n");
> + return -ENODEV;
> + }
> + return 0;
> +}
> +
> +static int acpi_ide_gtf(acpi_handle handle, ide_drive_t *drive)
> +{
> + struct acpi_buffer output = {ACPI_ALLOCATE_BUFFER, NULL};
> + ide_task_t args;
> + int index = 0;
> + unsigned char *data;
> + union acpi_object *package = NULL;
> + 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) {
> + kfree(output.pointer);
> + printk(KERN_ERR "_GTF returned value is wrong\n");
> + return -ENODEV;
> + }
> + printk("start GTF\n");
> +
> + data = package->buffer.pointer;
> + 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;
> + printk("data %x,%x,%x,%x,%x,%x,%x\n",
> + data[index], data[index+1], data[index+2],
> + data[index+3],data[index+4],data[index+5],
> + data[index+6]);
> + /* submit command request */
> +// printk("return value %d\n", ide_raw_taskfile(drive, &args, NULL));
> + index += 7;
> + }
> + kfree(output.pointer);
> + return 0;
> +}
> +
> +int acpi_ide_resume(struct device *dev)
> +{
> + acpi_handle handle, parent_handle;
> + struct acpi_ide_stat *stat;
> + ide_drive_t *drive = dev->driver_data;
> +
> + handle = DEVICE_ACPI_HANDLE(dev);
> + if (!handle) {
> + DBG("IDE device 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;
> + }
> + stat = ide_get_acpi_state(parent_handle);
> + if (stat == NULL || stat->handle != parent_handle)
> + return -ENODEV;
> +
> + if (stat->channel_handled == 0) {
> + stat->handle = NULL;
> + goto gtf;
> + }
> +DBG("Start STM\n");
> + if (acpi_ide_stm(stat))
> + return -ENODEV;
> + stat->channel_handled = 0;
> +gtf:
> + return acpi_ide_gtf(handle, drive);
> +}
> +#endif
> +
> static int generic_ide_suspend(struct device *dev, pm_message_t state)
> {
> ide_drive_t *drive = dev->driver_data;
> @@ -1223,6 +1454,7 @@
> rqpm.pm_step = ide_pm_state_start_suspend;
> rqpm.pm_state = state.event;
>
> + acpi_ide_suspend(dev);
> return ide_do_drive_cmd(drive, &rq, ide_wait);
> }
>
> @@ -1232,7 +1464,7 @@
> struct request rq;
> 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));
> @@ -1994,6 +2226,7 @@
> printk(KERN_INFO "Uniform Multi-Platform E-IDE driver " REVISION "\n");
> system_bus_speed = ide_system_bus_speed();
>
> +ide_acpi_init();
> bus_register(&ide_bus_type);
>
> init_ide_data();
--
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2006-12-05 11:21 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
[not found] <bcfd8020612010936h276a1d04mf2cc574cf62cd242@mail.gmail.com>
2006-12-05 6:48 ` in HP nx8220 S3 resume does not work in stock kernels 2.6.15-2.6.19. Ide light stays on Honkala Mikko
2006-12-05 11:20 ` Pavel Machek
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox