Depending on ACPI version (1.0 -> 32 bit) an integer could be 32 or 64 bit long. _WED internal concatenates two integers and the return value will be 8 byte (2* 32 bit) or 16 byte (2* 64 bit) long, depending on the ACPI version. Also the data send with the WMI event is defined to be splitted into: - Event ID -> 4 bytes - Event Data -> 4 bytes This gets messed up with new ACPI versions. But it's a HP BIOS bug that may get fixed in the future -> Support both, 16 and 8 byte _WED buffers. Also the wrong assumption that from the event data sent, only the first byte is relevant got cleaned up that it fits event_id/event_data as described above. Signed-off-by: Thomas Renninger <trenn@xxxxxxx> CC: robert.moore@xxxxxxxxx CC: mjg@xxxxxxxxxx CC: platform-driver-x86@xxxxxxxxxxxxxxx CC: linux-acpi@xxxxxxxxxxxxxxx --- drivers/platform/x86/hp-wmi.c | 37 +++++++++++++++++++++++++++++-------- 1 files changed, 29 insertions(+), 8 deletions(-) diff --git a/drivers/platform/x86/hp-wmi.c b/drivers/platform/x86/hp-wmi.c index f869fae..0ba7015 100644 --- a/drivers/platform/x86/hp-wmi.c +++ b/drivers/platform/x86/hp-wmi.c @@ -352,7 +352,9 @@ static void hp_wmi_notify(u32 value, void *context) struct acpi_buffer response = { ACPI_ALLOCATE_BUFFER, NULL }; static struct key_entry *key; union acpi_object *obj; - int eventcode, key_code; + u32 event_id, event_data; + int key_code; + u32 *location; acpi_status status; status = wmi_get_event_data(value, &response); @@ -363,15 +365,33 @@ static void hp_wmi_notify(u32 value, void *context) obj = (union acpi_object *)response.pointer; - if (!obj || obj->type != ACPI_TYPE_BUFFER || obj->buffer.length != 8) { - printk(KERN_INFO PREFIX "Unknown response received\n"); + if (obj || obj->type != ACPI_TYPE_BUFFER) { + printk(KERN_INFO "hp-wmi: Unknown response received %d\n", + obj->type); kfree(obj); return; } - eventcode = *((u8 *) obj->buffer.pointer); + /* + * Depending on ACPI version the concatenation of id and event data + * inside _WED function will result in a 8 or 16 byte buffer. + */ + location = (u32 *)obj->buffer.pointer; + if (obj->buffer.length == 8) { + event_id = *location; + event_data = *(location + 1); + } else if (obj->buffer.length == 16) { + event_id = *location; + event_data = *(location + 2); + } else { + printk(KERN_INFO "hp-wmi: Unknown buffer length %d\n", + obj->buffer.length); + kfree(obj); + return; + } kfree(obj); - switch (eventcode) { + + switch (event_id) { case HPWMI_DOCK_EVENT: input_report_switch(hp_wmi_input_dev, SW_DOCK, hp_wmi_dock_state()); @@ -380,7 +400,8 @@ static void hp_wmi_notify(u32 value, void *context) input_sync(hp_wmi_input_dev); break; case HPWMI_PARK_HDD: - printk(KERN_INFO PREFIX UNIMP "HDD park event detected\n"); + printk(KERN_INFO PREFIX UNIMP "HDD park event detected -" + " 0x%x\n", event_data); break; case HPWMI_SMART_ADAPTER: printk(KERN_INFO PREFIX UNIMP "Smart adapter event detected\n"); @@ -426,8 +447,8 @@ static void hp_wmi_notify(u32 value, void *context) printk(KERN_INFO PREFIX UNIMP "Lock switch event detected\n"); break; default: - printk(KERN_INFO PREFIX "Unknown eventcode - %d\n", - eventcode); + printk(KERN_INFO PREFIX "Unknown event_id - %d - 0x%x\n", + event_id, event_data); break; } } -- 1.6.3 -- To unsubscribe from this list: send the line "unsubscribe linux-acpi" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html