diff options
author | Thomas Renninger <trenn@suse.de> | 2010-05-21 10:41:43 -0400 |
---|---|---|
committer | Matthew Garrett <mjg@redhat.com> | 2010-08-03 09:48:43 -0400 |
commit | 8dda6b0410cfc64642b2ed5b37987292f6321d0f (patch) | |
tree | 53d27d9f692969ca081149bb6dab22950fef24f8 /drivers/platform | |
parent | 1bbdfd5961e83a1e3037d9362094bd09e0b066ab (diff) |
x86 platform drivers: hp-wmi fix buffer size depending on ACPI version
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@suse.de>
CC: robert.moore@intel.com
Signed-off-by: Matthew Garrett <mjg@redhat.com>
CC: platform-driver-x86@vger.kernel.org
CC: linux-acpi@vger.kernel.org
Diffstat (limited to 'drivers/platform')
-rw-r--r-- | drivers/platform/x86/hp-wmi.c | 34 |
1 files changed, 27 insertions, 7 deletions
diff --git a/drivers/platform/x86/hp-wmi.c b/drivers/platform/x86/hp-wmi.c index cd445019a6b7..7ebe46fe396e 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) | |||
352 | struct acpi_buffer response = { ACPI_ALLOCATE_BUFFER, NULL }; | 352 | struct acpi_buffer response = { ACPI_ALLOCATE_BUFFER, NULL }; |
353 | static struct key_entry *key; | 353 | static struct key_entry *key; |
354 | union acpi_object *obj; | 354 | union acpi_object *obj; |
355 | int eventcode, key_code; | 355 | u32 event_id, event_data; |
356 | int key_code; | ||
357 | u32 *location; | ||
356 | acpi_status status; | 358 | acpi_status status; |
357 | 359 | ||
358 | status = wmi_get_event_data(value, &response); | 360 | status = wmi_get_event_data(value, &response); |
@@ -363,15 +365,33 @@ static void hp_wmi_notify(u32 value, void *context) | |||
363 | 365 | ||
364 | obj = (union acpi_object *)response.pointer; | 366 | obj = (union acpi_object *)response.pointer; |
365 | 367 | ||
366 | if (!obj || obj->type != ACPI_TYPE_BUFFER || obj->buffer.length != 8) { | 368 | if (obj || obj->type != ACPI_TYPE_BUFFER) { |
367 | printk(KERN_INFO PREFIX "Unknown response received\n"); | 369 | printk(KERN_INFO "hp-wmi: Unknown response received %d\n", |
370 | obj->type); | ||
368 | kfree(obj); | 371 | kfree(obj); |
369 | return; | 372 | return; |
370 | } | 373 | } |
371 | 374 | ||
372 | eventcode = *((u8 *) obj->buffer.pointer); | 375 | /* |
376 | * Depending on ACPI version the concatenation of id and event data | ||
377 | * inside _WED function will result in a 8 or 16 byte buffer. | ||
378 | */ | ||
379 | location = (u32 *)obj->buffer.pointer; | ||
380 | if (obj->buffer.length == 8) { | ||
381 | event_id = *location; | ||
382 | event_data = *(location + 1); | ||
383 | } else if (obj->buffer.length == 16) { | ||
384 | event_id = *location; | ||
385 | event_data = *(location + 2); | ||
386 | } else { | ||
387 | printk(KERN_INFO "hp-wmi: Unknown buffer length %d\n", | ||
388 | obj->buffer.length); | ||
389 | kfree(obj); | ||
390 | return; | ||
391 | } | ||
373 | kfree(obj); | 392 | kfree(obj); |
374 | switch (eventcode) { | 393 | |
394 | switch (event_id) { | ||
375 | case HPWMI_DOCK_EVENT: | 395 | case HPWMI_DOCK_EVENT: |
376 | input_report_switch(hp_wmi_input_dev, SW_DOCK, | 396 | input_report_switch(hp_wmi_input_dev, SW_DOCK, |
377 | hp_wmi_dock_state()); | 397 | hp_wmi_dock_state()); |
@@ -423,8 +443,8 @@ static void hp_wmi_notify(u32 value, void *context) | |||
423 | case HPWMI_LOCK_SWITCH: | 443 | case HPWMI_LOCK_SWITCH: |
424 | break; | 444 | break; |
425 | default: | 445 | default: |
426 | printk(KERN_INFO PREFIX "Unknown eventcode - %d\n", | 446 | printk(KERN_INFO PREFIX "Unknown event_id - %d - 0x%x\n", |
427 | eventcode); | 447 | event_id, event_data); |
428 | break; | 448 | break; |
429 | } | 449 | } |
430 | } | 450 | } |