aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/platform
diff options
context:
space:
mode:
authorThomas Renninger <trenn@suse.de>2010-05-21 10:41:43 -0400
committerMatthew Garrett <mjg@redhat.com>2010-08-03 09:48:43 -0400
commit8dda6b0410cfc64642b2ed5b37987292f6321d0f (patch)
tree53d27d9f692969ca081149bb6dab22950fef24f8 /drivers/platform
parent1bbdfd5961e83a1e3037d9362094bd09e0b066ab (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.c34
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}