1 /* 2 * ACPI-WMI mapping driver 3 * 4 * Copyright (C) 2007-2008 Carlos Corbacho <carlos@strangeworlds.co.uk> 5 * 6 * GUID parsing code from ldm.c is: 7 * Copyright (C) 2001,2002 Richard Russon <ldm@flatcap.org> 8 * Copyright (c) 2001-2007 Anton Altaparmakov 9 * Copyright (C) 2001,2002 Jakob Kemi <jakob.kemi@telia.com> 10 * 11 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 12 * 13 * This program is free software; you can redistribute it and/or modify 14 * it under the terms of the GNU General Public License as published by 15 * the Free Software Foundation; either version 2 of the License, or (at 16 * your option) any later version. 17 * 18 * This program is distributed in the hope that it will be useful, but 19 * WITHOUT ANY WARRANTY; without even the implied warranty of 20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 21 * General Public License for more details. 22 * 23 * You should have received a copy of the GNU General Public License along 24 * with this program; if not, write to the Free Software Foundation, Inc., 25 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. 26 * 27 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 28 */ 29 30 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 31 32 #include <linux/kernel.h> 33 #include <linux/init.h> 34 #include <linux/types.h> 35 #include <linux/device.h> 36 #include <linux/list.h> 37 #include <linux/acpi.h> 38 #include <linux/slab.h> 39 #include <linux/module.h> 40 #include <linux/uuid.h> 41 42 ACPI_MODULE_NAME("wmi"); 43 MODULE_AUTHOR("Carlos Corbacho"); 44 MODULE_DESCRIPTION("ACPI-WMI Mapping Driver"); 45 MODULE_LICENSE("GPL"); 46 47 #define ACPI_WMI_CLASS "wmi" 48 49 static LIST_HEAD(wmi_block_list); 50 51 struct guid_block { 52 char guid[16]; 53 union { 54 char object_id[2]; 55 struct { 56 unsigned char notify_id; 57 unsigned char reserved; 58 }; 59 }; 60 u8 instance_count; 61 u8 flags; 62 }; 63 64 struct wmi_block { 65 struct list_head list; 66 struct guid_block gblock; 67 acpi_handle handle; 68 wmi_notify_handler handler; 69 void *handler_data; 70 struct device dev; 71 }; 72 73 74 /* 75 * If the GUID data block is marked as expensive, we must enable and 76 * explicitily disable data collection. 77 */ 78 #define ACPI_WMI_EXPENSIVE 0x1 79 #define ACPI_WMI_METHOD 0x2 /* GUID is a method */ 80 #define ACPI_WMI_STRING 0x4 /* GUID takes & returns a string */ 81 #define ACPI_WMI_EVENT 0x8 /* GUID is an event */ 82 83 static bool debug_event; 84 module_param(debug_event, bool, 0444); 85 MODULE_PARM_DESC(debug_event, 86 "Log WMI Events [0/1]"); 87 88 static bool debug_dump_wdg; 89 module_param(debug_dump_wdg, bool, 0444); 90 MODULE_PARM_DESC(debug_dump_wdg, 91 "Dump available WMI interfaces [0/1]"); 92 93 static int acpi_wmi_remove(struct acpi_device *device); 94 static int acpi_wmi_add(struct acpi_device *device); 95 static void acpi_wmi_notify(struct acpi_device *device, u32 event); 96 97 static const struct acpi_device_id wmi_device_ids[] = { 98 {"PNP0C14", 0}, 99 {"pnp0c14", 0}, 100 {"", 0}, 101 }; 102 MODULE_DEVICE_TABLE(acpi, wmi_device_ids); 103 104 static struct acpi_driver acpi_wmi_driver = { 105 .name = "wmi", 106 .class = ACPI_WMI_CLASS, 107 .ids = wmi_device_ids, 108 .ops = { 109 .add = acpi_wmi_add, 110 .remove = acpi_wmi_remove, 111 .notify = acpi_wmi_notify, 112 }, 113 }; 114 115 /* 116 * GUID parsing functions 117 */ 118 119 static bool find_guid(const char *guid_string, struct wmi_block **out) 120 { 121 uuid_le guid_input; 122 struct wmi_block *wblock; 123 struct guid_block *block; 124 struct list_head *p; 125 126 if (uuid_le_to_bin(guid_string, &guid_input)) 127 return false; 128 129 list_for_each(p, &wmi_block_list) { 130 wblock = list_entry(p, struct wmi_block, list); 131 block = &wblock->gblock; 132 133 if (memcmp(block->guid, &guid_input, 16) == 0) { 134 if (out) 135 *out = wblock; 136 return true; 137 } 138 } 139 return false; 140 } 141 142 static acpi_status wmi_method_enable(struct wmi_block *wblock, int enable) 143 { 144 struct guid_block *block = NULL; 145 char method[5]; 146 acpi_status status; 147 acpi_handle handle; 148 149 block = &wblock->gblock; 150 handle = wblock->handle; 151 152 snprintf(method, 5, "WE%02X", block->notify_id); 153 status = acpi_execute_simple_method(handle, method, enable); 154 155 if (status != AE_OK && status != AE_NOT_FOUND) 156 return status; 157 else 158 return AE_OK; 159 } 160 161 /* 162 * Exported WMI functions 163 */ 164 /** 165 * wmi_evaluate_method - Evaluate a WMI method 166 * @guid_string: 36 char string of the form fa50ff2b-f2e8-45de-83fa-65417f2f49ba 167 * @instance: Instance index 168 * @method_id: Method ID to call 169 * &in: Buffer containing input for the method call 170 * &out: Empty buffer to return the method results 171 * 172 * Call an ACPI-WMI method 173 */ 174 acpi_status wmi_evaluate_method(const char *guid_string, u8 instance, 175 u32 method_id, const struct acpi_buffer *in, struct acpi_buffer *out) 176 { 177 struct guid_block *block = NULL; 178 struct wmi_block *wblock = NULL; 179 acpi_handle handle; 180 acpi_status status; 181 struct acpi_object_list input; 182 union acpi_object params[3]; 183 char method[5] = "WM"; 184 185 if (!find_guid(guid_string, &wblock)) 186 return AE_ERROR; 187 188 block = &wblock->gblock; 189 handle = wblock->handle; 190 191 if (!(block->flags & ACPI_WMI_METHOD)) 192 return AE_BAD_DATA; 193 194 if (block->instance_count < instance) 195 return AE_BAD_PARAMETER; 196 197 input.count = 2; 198 input.pointer = params; 199 params[0].type = ACPI_TYPE_INTEGER; 200 params[0].integer.value = instance; 201 params[1].type = ACPI_TYPE_INTEGER; 202 params[1].integer.value = method_id; 203 204 if (in) { 205 input.count = 3; 206 207 if (block->flags & ACPI_WMI_STRING) { 208 params[2].type = ACPI_TYPE_STRING; 209 } else { 210 params[2].type = ACPI_TYPE_BUFFER; 211 } 212 params[2].buffer.length = in->length; 213 params[2].buffer.pointer = in->pointer; 214 } 215 216 strncat(method, block->object_id, 2); 217 218 status = acpi_evaluate_object(handle, method, &input, out); 219 220 return status; 221 } 222 EXPORT_SYMBOL_GPL(wmi_evaluate_method); 223 224 /** 225 * wmi_query_block - Return contents of a WMI block 226 * @guid_string: 36 char string of the form fa50ff2b-f2e8-45de-83fa-65417f2f49ba 227 * @instance: Instance index 228 * &out: Empty buffer to return the contents of the data block to 229 * 230 * Return the contents of an ACPI-WMI data block to a buffer 231 */ 232 acpi_status wmi_query_block(const char *guid_string, u8 instance, 233 struct acpi_buffer *out) 234 { 235 struct guid_block *block = NULL; 236 struct wmi_block *wblock = NULL; 237 acpi_handle handle; 238 acpi_status status, wc_status = AE_ERROR; 239 struct acpi_object_list input; 240 union acpi_object wq_params[1]; 241 char method[5]; 242 char wc_method[5] = "WC"; 243 244 if (!guid_string || !out) 245 return AE_BAD_PARAMETER; 246 247 if (!find_guid(guid_string, &wblock)) 248 return AE_ERROR; 249 250 block = &wblock->gblock; 251 handle = wblock->handle; 252 253 if (block->instance_count < instance) 254 return AE_BAD_PARAMETER; 255 256 /* Check GUID is a data block */ 257 if (block->flags & (ACPI_WMI_EVENT | ACPI_WMI_METHOD)) 258 return AE_ERROR; 259 260 input.count = 1; 261 input.pointer = wq_params; 262 wq_params[0].type = ACPI_TYPE_INTEGER; 263 wq_params[0].integer.value = instance; 264 265 /* 266 * If ACPI_WMI_EXPENSIVE, call the relevant WCxx method first to 267 * enable collection. 268 */ 269 if (block->flags & ACPI_WMI_EXPENSIVE) { 270 strncat(wc_method, block->object_id, 2); 271 272 /* 273 * Some GUIDs break the specification by declaring themselves 274 * expensive, but have no corresponding WCxx method. So we 275 * should not fail if this happens. 276 */ 277 if (acpi_has_method(handle, wc_method)) 278 wc_status = acpi_execute_simple_method(handle, 279 wc_method, 1); 280 } 281 282 strcpy(method, "WQ"); 283 strncat(method, block->object_id, 2); 284 285 status = acpi_evaluate_object(handle, method, &input, out); 286 287 /* 288 * If ACPI_WMI_EXPENSIVE, call the relevant WCxx method, even if 289 * the WQxx method failed - we should disable collection anyway. 290 */ 291 if ((block->flags & ACPI_WMI_EXPENSIVE) && ACPI_SUCCESS(wc_status)) { 292 status = acpi_execute_simple_method(handle, wc_method, 0); 293 } 294 295 return status; 296 } 297 EXPORT_SYMBOL_GPL(wmi_query_block); 298 299 /** 300 * wmi_set_block - Write to a WMI block 301 * @guid_string: 36 char string of the form fa50ff2b-f2e8-45de-83fa-65417f2f49ba 302 * @instance: Instance index 303 * &in: Buffer containing new values for the data block 304 * 305 * Write the contents of the input buffer to an ACPI-WMI data block 306 */ 307 acpi_status wmi_set_block(const char *guid_string, u8 instance, 308 const struct acpi_buffer *in) 309 { 310 struct guid_block *block = NULL; 311 struct wmi_block *wblock = NULL; 312 acpi_handle handle; 313 struct acpi_object_list input; 314 union acpi_object params[2]; 315 char method[5] = "WS"; 316 317 if (!guid_string || !in) 318 return AE_BAD_DATA; 319 320 if (!find_guid(guid_string, &wblock)) 321 return AE_ERROR; 322 323 block = &wblock->gblock; 324 handle = wblock->handle; 325 326 if (block->instance_count < instance) 327 return AE_BAD_PARAMETER; 328 329 /* Check GUID is a data block */ 330 if (block->flags & (ACPI_WMI_EVENT | ACPI_WMI_METHOD)) 331 return AE_ERROR; 332 333 input.count = 2; 334 input.pointer = params; 335 params[0].type = ACPI_TYPE_INTEGER; 336 params[0].integer.value = instance; 337 338 if (block->flags & ACPI_WMI_STRING) { 339 params[1].type = ACPI_TYPE_STRING; 340 } else { 341 params[1].type = ACPI_TYPE_BUFFER; 342 } 343 params[1].buffer.length = in->length; 344 params[1].buffer.pointer = in->pointer; 345 346 strncat(method, block->object_id, 2); 347 348 return acpi_evaluate_object(handle, method, &input, NULL); 349 } 350 EXPORT_SYMBOL_GPL(wmi_set_block); 351 352 static void wmi_dump_wdg(const struct guid_block *g) 353 { 354 pr_info("%pUL:\n", g->guid); 355 pr_info("\tobject_id: %c%c\n", g->object_id[0], g->object_id[1]); 356 pr_info("\tnotify_id: %02X\n", g->notify_id); 357 pr_info("\treserved: %02X\n", g->reserved); 358 pr_info("\tinstance_count: %d\n", g->instance_count); 359 pr_info("\tflags: %#x", g->flags); 360 if (g->flags) { 361 if (g->flags & ACPI_WMI_EXPENSIVE) 362 pr_cont(" ACPI_WMI_EXPENSIVE"); 363 if (g->flags & ACPI_WMI_METHOD) 364 pr_cont(" ACPI_WMI_METHOD"); 365 if (g->flags & ACPI_WMI_STRING) 366 pr_cont(" ACPI_WMI_STRING"); 367 if (g->flags & ACPI_WMI_EVENT) 368 pr_cont(" ACPI_WMI_EVENT"); 369 } 370 pr_cont("\n"); 371 372 } 373 374 static void wmi_notify_debug(u32 value, void *context) 375 { 376 struct acpi_buffer response = { ACPI_ALLOCATE_BUFFER, NULL }; 377 union acpi_object *obj; 378 acpi_status status; 379 380 status = wmi_get_event_data(value, &response); 381 if (status != AE_OK) { 382 pr_info("bad event status 0x%x\n", status); 383 return; 384 } 385 386 obj = (union acpi_object *)response.pointer; 387 388 if (!obj) 389 return; 390 391 pr_info("DEBUG Event "); 392 switch(obj->type) { 393 case ACPI_TYPE_BUFFER: 394 pr_cont("BUFFER_TYPE - length %d\n", obj->buffer.length); 395 break; 396 case ACPI_TYPE_STRING: 397 pr_cont("STRING_TYPE - %s\n", obj->string.pointer); 398 break; 399 case ACPI_TYPE_INTEGER: 400 pr_cont("INTEGER_TYPE - %llu\n", obj->integer.value); 401 break; 402 case ACPI_TYPE_PACKAGE: 403 pr_cont("PACKAGE_TYPE - %d elements\n", obj->package.count); 404 break; 405 default: 406 pr_cont("object type 0x%X\n", obj->type); 407 } 408 kfree(obj); 409 } 410 411 /** 412 * wmi_install_notify_handler - Register handler for WMI events 413 * @handler: Function to handle notifications 414 * @data: Data to be returned to handler when event is fired 415 * 416 * Register a handler for events sent to the ACPI-WMI mapper device. 417 */ 418 acpi_status wmi_install_notify_handler(const char *guid, 419 wmi_notify_handler handler, void *data) 420 { 421 struct wmi_block *block; 422 acpi_status status = AE_NOT_EXIST; 423 uuid_le guid_input; 424 struct list_head *p; 425 426 if (!guid || !handler) 427 return AE_BAD_PARAMETER; 428 429 if (uuid_le_to_bin(guid, &guid_input)) 430 return AE_BAD_PARAMETER; 431 432 list_for_each(p, &wmi_block_list) { 433 acpi_status wmi_status; 434 block = list_entry(p, struct wmi_block, list); 435 436 if (memcmp(block->gblock.guid, &guid_input, 16) == 0) { 437 if (block->handler && 438 block->handler != wmi_notify_debug) 439 return AE_ALREADY_ACQUIRED; 440 441 block->handler = handler; 442 block->handler_data = data; 443 444 wmi_status = wmi_method_enable(block, 1); 445 if ((wmi_status != AE_OK) || 446 ((wmi_status == AE_OK) && (status == AE_NOT_EXIST))) 447 status = wmi_status; 448 } 449 } 450 451 return status; 452 } 453 EXPORT_SYMBOL_GPL(wmi_install_notify_handler); 454 455 /** 456 * wmi_uninstall_notify_handler - Unregister handler for WMI events 457 * 458 * Unregister handler for events sent to the ACPI-WMI mapper device. 459 */ 460 acpi_status wmi_remove_notify_handler(const char *guid) 461 { 462 struct wmi_block *block; 463 acpi_status status = AE_NOT_EXIST; 464 uuid_le guid_input; 465 struct list_head *p; 466 467 if (!guid) 468 return AE_BAD_PARAMETER; 469 470 if (uuid_le_to_bin(guid, &guid_input)) 471 return AE_BAD_PARAMETER; 472 473 list_for_each(p, &wmi_block_list) { 474 acpi_status wmi_status; 475 block = list_entry(p, struct wmi_block, list); 476 477 if (memcmp(block->gblock.guid, &guid_input, 16) == 0) { 478 if (!block->handler || 479 block->handler == wmi_notify_debug) 480 return AE_NULL_ENTRY; 481 482 if (debug_event) { 483 block->handler = wmi_notify_debug; 484 status = AE_OK; 485 } else { 486 wmi_status = wmi_method_enable(block, 0); 487 block->handler = NULL; 488 block->handler_data = NULL; 489 if ((wmi_status != AE_OK) || 490 ((wmi_status == AE_OK) && 491 (status == AE_NOT_EXIST))) 492 status = wmi_status; 493 } 494 } 495 } 496 497 return status; 498 } 499 EXPORT_SYMBOL_GPL(wmi_remove_notify_handler); 500 501 /** 502 * wmi_get_event_data - Get WMI data associated with an event 503 * 504 * @event: Event to find 505 * @out: Buffer to hold event data. out->pointer should be freed with kfree() 506 * 507 * Returns extra data associated with an event in WMI. 508 */ 509 acpi_status wmi_get_event_data(u32 event, struct acpi_buffer *out) 510 { 511 struct acpi_object_list input; 512 union acpi_object params[1]; 513 struct guid_block *gblock; 514 struct wmi_block *wblock; 515 struct list_head *p; 516 517 input.count = 1; 518 input.pointer = params; 519 params[0].type = ACPI_TYPE_INTEGER; 520 params[0].integer.value = event; 521 522 list_for_each(p, &wmi_block_list) { 523 wblock = list_entry(p, struct wmi_block, list); 524 gblock = &wblock->gblock; 525 526 if ((gblock->flags & ACPI_WMI_EVENT) && 527 (gblock->notify_id == event)) 528 return acpi_evaluate_object(wblock->handle, "_WED", 529 &input, out); 530 } 531 532 return AE_NOT_FOUND; 533 } 534 EXPORT_SYMBOL_GPL(wmi_get_event_data); 535 536 /** 537 * wmi_has_guid - Check if a GUID is available 538 * @guid_string: 36 char string of the form fa50ff2b-f2e8-45de-83fa-65417f2f49ba 539 * 540 * Check if a given GUID is defined by _WDG 541 */ 542 bool wmi_has_guid(const char *guid_string) 543 { 544 return find_guid(guid_string, NULL); 545 } 546 EXPORT_SYMBOL_GPL(wmi_has_guid); 547 548 /* 549 * sysfs interface 550 */ 551 static ssize_t modalias_show(struct device *dev, struct device_attribute *attr, 552 char *buf) 553 { 554 struct wmi_block *wblock; 555 556 wblock = dev_get_drvdata(dev); 557 if (!wblock) { 558 strcat(buf, "\n"); 559 return strlen(buf); 560 } 561 562 return sprintf(buf, "wmi:%pUL\n", wblock->gblock.guid); 563 } 564 static DEVICE_ATTR_RO(modalias); 565 566 static struct attribute *wmi_attrs[] = { 567 &dev_attr_modalias.attr, 568 NULL, 569 }; 570 ATTRIBUTE_GROUPS(wmi); 571 572 static int wmi_dev_uevent(struct device *dev, struct kobj_uevent_env *env) 573 { 574 char guid_string[37]; 575 576 struct wmi_block *wblock; 577 578 if (add_uevent_var(env, "MODALIAS=")) 579 return -ENOMEM; 580 581 wblock = dev_get_drvdata(dev); 582 if (!wblock) 583 return -ENOMEM; 584 585 sprintf(guid_string, "%pUL", wblock->gblock.guid); 586 587 strcpy(&env->buf[env->buflen - 1], "wmi:"); 588 memcpy(&env->buf[env->buflen - 1 + 4], guid_string, 36); 589 env->buflen += 40; 590 591 return 0; 592 } 593 594 static void wmi_dev_free(struct device *dev) 595 { 596 struct wmi_block *wmi_block = container_of(dev, struct wmi_block, dev); 597 598 kfree(wmi_block); 599 } 600 601 static struct class wmi_class = { 602 .name = "wmi", 603 .dev_release = wmi_dev_free, 604 .dev_uevent = wmi_dev_uevent, 605 .dev_groups = wmi_groups, 606 }; 607 608 static int wmi_create_device(const struct guid_block *gblock, 609 struct wmi_block *wblock, acpi_handle handle) 610 { 611 wblock->dev.class = &wmi_class; 612 613 dev_set_name(&wblock->dev, "%pUL", gblock->guid); 614 615 dev_set_drvdata(&wblock->dev, wblock); 616 617 return device_register(&wblock->dev); 618 } 619 620 static void wmi_free_devices(void) 621 { 622 struct wmi_block *wblock, *next; 623 624 /* Delete devices for all the GUIDs */ 625 list_for_each_entry_safe(wblock, next, &wmi_block_list, list) { 626 list_del(&wblock->list); 627 if (wblock->dev.class) 628 device_unregister(&wblock->dev); 629 else 630 kfree(wblock); 631 } 632 } 633 634 static bool guid_already_parsed(const char *guid_string) 635 { 636 struct wmi_block *wblock; 637 638 list_for_each_entry(wblock, &wmi_block_list, list) 639 if (memcmp(wblock->gblock.guid, guid_string, 16) == 0) 640 return true; 641 642 return false; 643 } 644 645 /* 646 * Parse the _WDG method for the GUID data blocks 647 */ 648 static int parse_wdg(acpi_handle handle) 649 { 650 struct acpi_buffer out = {ACPI_ALLOCATE_BUFFER, NULL}; 651 union acpi_object *obj; 652 const struct guid_block *gblock; 653 struct wmi_block *wblock; 654 acpi_status status; 655 int retval; 656 u32 i, total; 657 658 status = acpi_evaluate_object(handle, "_WDG", NULL, &out); 659 if (ACPI_FAILURE(status)) 660 return -ENXIO; 661 662 obj = (union acpi_object *) out.pointer; 663 if (!obj) 664 return -ENXIO; 665 666 if (obj->type != ACPI_TYPE_BUFFER) { 667 retval = -ENXIO; 668 goto out_free_pointer; 669 } 670 671 gblock = (const struct guid_block *)obj->buffer.pointer; 672 total = obj->buffer.length / sizeof(struct guid_block); 673 674 for (i = 0; i < total; i++) { 675 if (debug_dump_wdg) 676 wmi_dump_wdg(&gblock[i]); 677 678 wblock = kzalloc(sizeof(struct wmi_block), GFP_KERNEL); 679 if (!wblock) 680 return -ENOMEM; 681 682 wblock->handle = handle; 683 wblock->gblock = gblock[i]; 684 685 /* 686 Some WMI devices, like those for nVidia hooks, have a 687 duplicate GUID. It's not clear what we should do in this 688 case yet, so for now, we'll just ignore the duplicate 689 for device creation. 690 */ 691 if (!guid_already_parsed(gblock[i].guid)) { 692 retval = wmi_create_device(&gblock[i], wblock, handle); 693 if (retval) { 694 wmi_free_devices(); 695 goto out_free_pointer; 696 } 697 } 698 699 list_add_tail(&wblock->list, &wmi_block_list); 700 701 if (debug_event) { 702 wblock->handler = wmi_notify_debug; 703 wmi_method_enable(wblock, 1); 704 } 705 } 706 707 retval = 0; 708 709 out_free_pointer: 710 kfree(out.pointer); 711 712 return retval; 713 } 714 715 /* 716 * WMI can have EmbeddedControl access regions. In which case, we just want to 717 * hand these off to the EC driver. 718 */ 719 static acpi_status 720 acpi_wmi_ec_space_handler(u32 function, acpi_physical_address address, 721 u32 bits, u64 *value, 722 void *handler_context, void *region_context) 723 { 724 int result = 0, i = 0; 725 u8 temp = 0; 726 727 if ((address > 0xFF) || !value) 728 return AE_BAD_PARAMETER; 729 730 if (function != ACPI_READ && function != ACPI_WRITE) 731 return AE_BAD_PARAMETER; 732 733 if (bits != 8) 734 return AE_BAD_PARAMETER; 735 736 if (function == ACPI_READ) { 737 result = ec_read(address, &temp); 738 (*value) |= ((u64)temp) << i; 739 } else { 740 temp = 0xff & ((*value) >> i); 741 result = ec_write(address, temp); 742 } 743 744 switch (result) { 745 case -EINVAL: 746 return AE_BAD_PARAMETER; 747 break; 748 case -ENODEV: 749 return AE_NOT_FOUND; 750 break; 751 case -ETIME: 752 return AE_TIME; 753 break; 754 default: 755 return AE_OK; 756 } 757 } 758 759 static void acpi_wmi_notify(struct acpi_device *device, u32 event) 760 { 761 struct guid_block *block; 762 struct wmi_block *wblock; 763 struct list_head *p; 764 765 list_for_each(p, &wmi_block_list) { 766 wblock = list_entry(p, struct wmi_block, list); 767 block = &wblock->gblock; 768 769 if ((block->flags & ACPI_WMI_EVENT) && 770 (block->notify_id == event)) { 771 if (wblock->handler) 772 wblock->handler(event, wblock->handler_data); 773 if (debug_event) { 774 pr_info("DEBUG Event GUID: %pUL\n", 775 wblock->gblock.guid); 776 } 777 778 acpi_bus_generate_netlink_event( 779 device->pnp.device_class, dev_name(&device->dev), 780 event, 0); 781 break; 782 } 783 } 784 } 785 786 static int acpi_wmi_remove(struct acpi_device *device) 787 { 788 acpi_remove_address_space_handler(device->handle, 789 ACPI_ADR_SPACE_EC, &acpi_wmi_ec_space_handler); 790 wmi_free_devices(); 791 792 return 0; 793 } 794 795 static int acpi_wmi_add(struct acpi_device *device) 796 { 797 acpi_status status; 798 int error; 799 800 status = acpi_install_address_space_handler(device->handle, 801 ACPI_ADR_SPACE_EC, 802 &acpi_wmi_ec_space_handler, 803 NULL, NULL); 804 if (ACPI_FAILURE(status)) { 805 pr_err("Error installing EC region handler\n"); 806 return -ENODEV; 807 } 808 809 error = parse_wdg(device->handle); 810 if (error) { 811 acpi_remove_address_space_handler(device->handle, 812 ACPI_ADR_SPACE_EC, 813 &acpi_wmi_ec_space_handler); 814 pr_err("Failed to parse WDG method\n"); 815 return error; 816 } 817 818 return 0; 819 } 820 821 static int __init acpi_wmi_init(void) 822 { 823 int error; 824 825 if (acpi_disabled) 826 return -ENODEV; 827 828 error = class_register(&wmi_class); 829 if (error) 830 return error; 831 832 error = acpi_bus_register_driver(&acpi_wmi_driver); 833 if (error) { 834 pr_err("Error loading mapper\n"); 835 class_unregister(&wmi_class); 836 return error; 837 } 838 839 pr_info("Mapper loaded\n"); 840 return 0; 841 } 842 843 static void __exit acpi_wmi_exit(void) 844 { 845 acpi_bus_unregister_driver(&acpi_wmi_driver); 846 class_unregister(&wmi_class); 847 848 pr_info("Mapper unloaded\n"); 849 } 850 851 subsys_initcall(acpi_wmi_init); 852 module_exit(acpi_wmi_exit); 853