GNU Linux-libre 4.9.294-gnu1
[releases.git] / drivers / platform / x86 / wmi.c
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                 /*
293                  * Ignore whether this WCxx call succeeds or not since
294                  * the previously executed WQxx method call might have
295                  * succeeded, and returning the failing status code
296                  * of this call would throw away the result of the WQxx
297                  * call, potentially leaking memory.
298                  */
299                 acpi_execute_simple_method(handle, wc_method, 0);
300         }
301
302         return status;
303 }
304 EXPORT_SYMBOL_GPL(wmi_query_block);
305
306 /**
307  * wmi_set_block - Write to a WMI block
308  * @guid_string: 36 char string of the form fa50ff2b-f2e8-45de-83fa-65417f2f49ba
309  * @instance: Instance index
310  * &in: Buffer containing new values for the data block
311  *
312  * Write the contents of the input buffer to an ACPI-WMI data block
313  */
314 acpi_status wmi_set_block(const char *guid_string, u8 instance,
315 const struct acpi_buffer *in)
316 {
317         struct guid_block *block = NULL;
318         struct wmi_block *wblock = NULL;
319         acpi_handle handle;
320         struct acpi_object_list input;
321         union acpi_object params[2];
322         char method[5] = "WS";
323
324         if (!guid_string || !in)
325                 return AE_BAD_DATA;
326
327         if (!find_guid(guid_string, &wblock))
328                 return AE_ERROR;
329
330         block = &wblock->gblock;
331         handle = wblock->handle;
332
333         if (block->instance_count < instance)
334                 return AE_BAD_PARAMETER;
335
336         /* Check GUID is a data block */
337         if (block->flags & (ACPI_WMI_EVENT | ACPI_WMI_METHOD))
338                 return AE_ERROR;
339
340         input.count = 2;
341         input.pointer = params;
342         params[0].type = ACPI_TYPE_INTEGER;
343         params[0].integer.value = instance;
344
345         if (block->flags & ACPI_WMI_STRING) {
346                 params[1].type = ACPI_TYPE_STRING;
347         } else {
348                 params[1].type = ACPI_TYPE_BUFFER;
349         }
350         params[1].buffer.length = in->length;
351         params[1].buffer.pointer = in->pointer;
352
353         strncat(method, block->object_id, 2);
354
355         return acpi_evaluate_object(handle, method, &input, NULL);
356 }
357 EXPORT_SYMBOL_GPL(wmi_set_block);
358
359 static void wmi_dump_wdg(const struct guid_block *g)
360 {
361         pr_info("%pUL:\n", g->guid);
362         pr_info("\tobject_id: %c%c\n", g->object_id[0], g->object_id[1]);
363         pr_info("\tnotify_id: %02X\n", g->notify_id);
364         pr_info("\treserved: %02X\n", g->reserved);
365         pr_info("\tinstance_count: %d\n", g->instance_count);
366         pr_info("\tflags: %#x", g->flags);
367         if (g->flags) {
368                 if (g->flags & ACPI_WMI_EXPENSIVE)
369                         pr_cont(" ACPI_WMI_EXPENSIVE");
370                 if (g->flags & ACPI_WMI_METHOD)
371                         pr_cont(" ACPI_WMI_METHOD");
372                 if (g->flags & ACPI_WMI_STRING)
373                         pr_cont(" ACPI_WMI_STRING");
374                 if (g->flags & ACPI_WMI_EVENT)
375                         pr_cont(" ACPI_WMI_EVENT");
376         }
377         pr_cont("\n");
378
379 }
380
381 static void wmi_notify_debug(u32 value, void *context)
382 {
383         struct acpi_buffer response = { ACPI_ALLOCATE_BUFFER, NULL };
384         union acpi_object *obj;
385         acpi_status status;
386
387         status = wmi_get_event_data(value, &response);
388         if (status != AE_OK) {
389                 pr_info("bad event status 0x%x\n", status);
390                 return;
391         }
392
393         obj = (union acpi_object *)response.pointer;
394
395         if (!obj)
396                 return;
397
398         pr_info("DEBUG Event ");
399         switch(obj->type) {
400         case ACPI_TYPE_BUFFER:
401                 pr_cont("BUFFER_TYPE - length %d\n", obj->buffer.length);
402                 break;
403         case ACPI_TYPE_STRING:
404                 pr_cont("STRING_TYPE - %s\n", obj->string.pointer);
405                 break;
406         case ACPI_TYPE_INTEGER:
407                 pr_cont("INTEGER_TYPE - %llu\n", obj->integer.value);
408                 break;
409         case ACPI_TYPE_PACKAGE:
410                 pr_cont("PACKAGE_TYPE - %d elements\n", obj->package.count);
411                 break;
412         default:
413                 pr_cont("object type 0x%X\n", obj->type);
414         }
415         kfree(obj);
416 }
417
418 /**
419  * wmi_install_notify_handler - Register handler for WMI events
420  * @handler: Function to handle notifications
421  * @data: Data to be returned to handler when event is fired
422  *
423  * Register a handler for events sent to the ACPI-WMI mapper device.
424  */
425 acpi_status wmi_install_notify_handler(const char *guid,
426 wmi_notify_handler handler, void *data)
427 {
428         struct wmi_block *block;
429         acpi_status status = AE_NOT_EXIST;
430         uuid_le guid_input;
431         struct list_head *p;
432
433         if (!guid || !handler)
434                 return AE_BAD_PARAMETER;
435
436         if (uuid_le_to_bin(guid, &guid_input))
437                 return AE_BAD_PARAMETER;
438
439         list_for_each(p, &wmi_block_list) {
440                 acpi_status wmi_status;
441                 block = list_entry(p, struct wmi_block, list);
442
443                 if (memcmp(block->gblock.guid, &guid_input, 16) == 0) {
444                         if (block->handler &&
445                             block->handler != wmi_notify_debug)
446                                 return AE_ALREADY_ACQUIRED;
447
448                         block->handler = handler;
449                         block->handler_data = data;
450
451                         wmi_status = wmi_method_enable(block, 1);
452                         if ((wmi_status != AE_OK) ||
453                             ((wmi_status == AE_OK) && (status == AE_NOT_EXIST)))
454                                 status = wmi_status;
455                 }
456         }
457
458         return status;
459 }
460 EXPORT_SYMBOL_GPL(wmi_install_notify_handler);
461
462 /**
463  * wmi_uninstall_notify_handler - Unregister handler for WMI events
464  *
465  * Unregister handler for events sent to the ACPI-WMI mapper device.
466  */
467 acpi_status wmi_remove_notify_handler(const char *guid)
468 {
469         struct wmi_block *block;
470         acpi_status status = AE_NOT_EXIST;
471         uuid_le guid_input;
472         struct list_head *p;
473
474         if (!guid)
475                 return AE_BAD_PARAMETER;
476
477         if (uuid_le_to_bin(guid, &guid_input))
478                 return AE_BAD_PARAMETER;
479
480         list_for_each(p, &wmi_block_list) {
481                 acpi_status wmi_status;
482                 block = list_entry(p, struct wmi_block, list);
483
484                 if (memcmp(block->gblock.guid, &guid_input, 16) == 0) {
485                         if (!block->handler ||
486                             block->handler == wmi_notify_debug)
487                                 return AE_NULL_ENTRY;
488
489                         if (debug_event) {
490                                 block->handler = wmi_notify_debug;
491                                 status = AE_OK;
492                         } else {
493                                 wmi_status = wmi_method_enable(block, 0);
494                                 block->handler = NULL;
495                                 block->handler_data = NULL;
496                                 if ((wmi_status != AE_OK) ||
497                                     ((wmi_status == AE_OK) &&
498                                      (status == AE_NOT_EXIST)))
499                                         status = wmi_status;
500                         }
501                 }
502         }
503
504         return status;
505 }
506 EXPORT_SYMBOL_GPL(wmi_remove_notify_handler);
507
508 /**
509  * wmi_get_event_data - Get WMI data associated with an event
510  *
511  * @event: Event to find
512  * @out: Buffer to hold event data. out->pointer should be freed with kfree()
513  *
514  * Returns extra data associated with an event in WMI.
515  */
516 acpi_status wmi_get_event_data(u32 event, struct acpi_buffer *out)
517 {
518         struct acpi_object_list input;
519         union acpi_object params[1];
520         struct guid_block *gblock;
521         struct wmi_block *wblock;
522         struct list_head *p;
523
524         input.count = 1;
525         input.pointer = params;
526         params[0].type = ACPI_TYPE_INTEGER;
527         params[0].integer.value = event;
528
529         list_for_each(p, &wmi_block_list) {
530                 wblock = list_entry(p, struct wmi_block, list);
531                 gblock = &wblock->gblock;
532
533                 if ((gblock->flags & ACPI_WMI_EVENT) &&
534                         (gblock->notify_id == event))
535                         return acpi_evaluate_object(wblock->handle, "_WED",
536                                 &input, out);
537         }
538
539         return AE_NOT_FOUND;
540 }
541 EXPORT_SYMBOL_GPL(wmi_get_event_data);
542
543 /**
544  * wmi_has_guid - Check if a GUID is available
545  * @guid_string: 36 char string of the form fa50ff2b-f2e8-45de-83fa-65417f2f49ba
546  *
547  * Check if a given GUID is defined by _WDG
548  */
549 bool wmi_has_guid(const char *guid_string)
550 {
551         return find_guid(guid_string, NULL);
552 }
553 EXPORT_SYMBOL_GPL(wmi_has_guid);
554
555 /*
556  * sysfs interface
557  */
558 static ssize_t modalias_show(struct device *dev, struct device_attribute *attr,
559                              char *buf)
560 {
561         struct wmi_block *wblock;
562
563         wblock = dev_get_drvdata(dev);
564         if (!wblock) {
565                 strcat(buf, "\n");
566                 return strlen(buf);
567         }
568
569         return sprintf(buf, "wmi:%pUL\n", wblock->gblock.guid);
570 }
571 static DEVICE_ATTR_RO(modalias);
572
573 static struct attribute *wmi_attrs[] = {
574         &dev_attr_modalias.attr,
575         NULL,
576 };
577 ATTRIBUTE_GROUPS(wmi);
578
579 static int wmi_dev_uevent(struct device *dev, struct kobj_uevent_env *env)
580 {
581         char guid_string[37];
582
583         struct wmi_block *wblock;
584
585         if (add_uevent_var(env, "MODALIAS="))
586                 return -ENOMEM;
587
588         wblock = dev_get_drvdata(dev);
589         if (!wblock)
590                 return -ENOMEM;
591
592         sprintf(guid_string, "%pUL", wblock->gblock.guid);
593
594         strcpy(&env->buf[env->buflen - 1], "wmi:");
595         memcpy(&env->buf[env->buflen - 1 + 4], guid_string, 36);
596         env->buflen += 40;
597
598         return 0;
599 }
600
601 static void wmi_dev_free(struct device *dev)
602 {
603         struct wmi_block *wmi_block = container_of(dev, struct wmi_block, dev);
604
605         kfree(wmi_block);
606 }
607
608 static struct class wmi_class = {
609         .name = "wmi",
610         .dev_release = wmi_dev_free,
611         .dev_uevent = wmi_dev_uevent,
612         .dev_groups = wmi_groups,
613 };
614
615 static int wmi_create_device(const struct guid_block *gblock,
616                              struct wmi_block *wblock, acpi_handle handle)
617 {
618         wblock->dev.class = &wmi_class;
619
620         dev_set_name(&wblock->dev, "%pUL", gblock->guid);
621
622         dev_set_drvdata(&wblock->dev, wblock);
623
624         return device_register(&wblock->dev);
625 }
626
627 static void wmi_free_devices(void)
628 {
629         struct wmi_block *wblock, *next;
630
631         /* Delete devices for all the GUIDs */
632         list_for_each_entry_safe(wblock, next, &wmi_block_list, list) {
633                 list_del(&wblock->list);
634                 if (wblock->dev.class)
635                         device_unregister(&wblock->dev);
636                 else
637                         kfree(wblock);
638         }
639 }
640
641 static bool guid_already_parsed(const char *guid_string)
642 {
643         struct wmi_block *wblock;
644
645         list_for_each_entry(wblock, &wmi_block_list, list)
646                 if (memcmp(wblock->gblock.guid, guid_string, 16) == 0)
647                         return true;
648
649         return false;
650 }
651
652 /*
653  * Parse the _WDG method for the GUID data blocks
654  */
655 static int parse_wdg(acpi_handle handle)
656 {
657         struct acpi_buffer out = {ACPI_ALLOCATE_BUFFER, NULL};
658         union acpi_object *obj;
659         const struct guid_block *gblock;
660         struct wmi_block *wblock;
661         acpi_status status;
662         int retval;
663         u32 i, total;
664
665         status = acpi_evaluate_object(handle, "_WDG", NULL, &out);
666         if (ACPI_FAILURE(status))
667                 return -ENXIO;
668
669         obj = (union acpi_object *) out.pointer;
670         if (!obj)
671                 return -ENXIO;
672
673         if (obj->type != ACPI_TYPE_BUFFER) {
674                 retval = -ENXIO;
675                 goto out_free_pointer;
676         }
677
678         gblock = (const struct guid_block *)obj->buffer.pointer;
679         total = obj->buffer.length / sizeof(struct guid_block);
680
681         for (i = 0; i < total; i++) {
682                 if (debug_dump_wdg)
683                         wmi_dump_wdg(&gblock[i]);
684
685                 wblock = kzalloc(sizeof(struct wmi_block), GFP_KERNEL);
686                 if (!wblock)
687                         return -ENOMEM;
688
689                 wblock->handle = handle;
690                 wblock->gblock = gblock[i];
691
692                 /*
693                   Some WMI devices, like those for nVidia hooks, have a
694                   duplicate GUID. It's not clear what we should do in this
695                   case yet, so for now, we'll just ignore the duplicate
696                   for device creation.
697                 */
698                 if (!guid_already_parsed(gblock[i].guid)) {
699                         retval = wmi_create_device(&gblock[i], wblock, handle);
700                         if (retval) {
701                                 wmi_free_devices();
702                                 goto out_free_pointer;
703                         }
704                 }
705
706                 list_add_tail(&wblock->list, &wmi_block_list);
707
708                 if (debug_event) {
709                         wblock->handler = wmi_notify_debug;
710                         wmi_method_enable(wblock, 1);
711                 }
712         }
713
714         retval = 0;
715
716 out_free_pointer:
717         kfree(out.pointer);
718
719         return retval;
720 }
721
722 /*
723  * WMI can have EmbeddedControl access regions. In which case, we just want to
724  * hand these off to the EC driver.
725  */
726 static acpi_status
727 acpi_wmi_ec_space_handler(u32 function, acpi_physical_address address,
728                       u32 bits, u64 *value,
729                       void *handler_context, void *region_context)
730 {
731         int result = 0, i = 0;
732         u8 temp = 0;
733
734         if ((address > 0xFF) || !value)
735                 return AE_BAD_PARAMETER;
736
737         if (function != ACPI_READ && function != ACPI_WRITE)
738                 return AE_BAD_PARAMETER;
739
740         if (bits != 8)
741                 return AE_BAD_PARAMETER;
742
743         if (function == ACPI_READ) {
744                 result = ec_read(address, &temp);
745                 (*value) |= ((u64)temp) << i;
746         } else {
747                 temp = 0xff & ((*value) >> i);
748                 result = ec_write(address, temp);
749         }
750
751         switch (result) {
752         case -EINVAL:
753                 return AE_BAD_PARAMETER;
754                 break;
755         case -ENODEV:
756                 return AE_NOT_FOUND;
757                 break;
758         case -ETIME:
759                 return AE_TIME;
760                 break;
761         default:
762                 return AE_OK;
763         }
764 }
765
766 static void acpi_wmi_notify(struct acpi_device *device, u32 event)
767 {
768         struct guid_block *block;
769         struct wmi_block *wblock;
770         struct list_head *p;
771
772         list_for_each(p, &wmi_block_list) {
773                 wblock = list_entry(p, struct wmi_block, list);
774                 block = &wblock->gblock;
775
776                 if ((block->flags & ACPI_WMI_EVENT) &&
777                         (block->notify_id == event)) {
778                         if (wblock->handler)
779                                 wblock->handler(event, wblock->handler_data);
780                         if (debug_event) {
781                                 pr_info("DEBUG Event GUID: %pUL\n",
782                                         wblock->gblock.guid);
783                         }
784
785                         acpi_bus_generate_netlink_event(
786                                 device->pnp.device_class, dev_name(&device->dev),
787                                 event, 0);
788                         break;
789                 }
790         }
791 }
792
793 static int acpi_wmi_remove(struct acpi_device *device)
794 {
795         acpi_remove_address_space_handler(device->handle,
796                                 ACPI_ADR_SPACE_EC, &acpi_wmi_ec_space_handler);
797         wmi_free_devices();
798
799         return 0;
800 }
801
802 static int acpi_wmi_add(struct acpi_device *device)
803 {
804         acpi_status status;
805         int error;
806
807         status = acpi_install_address_space_handler(device->handle,
808                                                     ACPI_ADR_SPACE_EC,
809                                                     &acpi_wmi_ec_space_handler,
810                                                     NULL, NULL);
811         if (ACPI_FAILURE(status)) {
812                 pr_err("Error installing EC region handler\n");
813                 return -ENODEV;
814         }
815
816         error = parse_wdg(device->handle);
817         if (error) {
818                 acpi_remove_address_space_handler(device->handle,
819                                                   ACPI_ADR_SPACE_EC,
820                                                   &acpi_wmi_ec_space_handler);
821                 pr_err("Failed to parse WDG method\n");
822                 return error;
823         }
824
825         return 0;
826 }
827
828 static int __init acpi_wmi_init(void)
829 {
830         int error;
831
832         if (acpi_disabled)
833                 return -ENODEV;
834
835         error = class_register(&wmi_class);
836         if (error)
837                 return error;
838
839         error = acpi_bus_register_driver(&acpi_wmi_driver);
840         if (error) {
841                 pr_err("Error loading mapper\n");
842                 class_unregister(&wmi_class);
843                 return error;
844         }
845
846         pr_info("Mapper loaded\n");
847         return 0;
848 }
849
850 static void __exit acpi_wmi_exit(void)
851 {
852         acpi_bus_unregister_driver(&acpi_wmi_driver);
853         class_unregister(&wmi_class);
854
855         pr_info("Mapper unloaded\n");
856 }
857
858 subsys_initcall_sync(acpi_wmi_init);
859 module_exit(acpi_wmi_exit);