Linux kernel mirror (for testing)
git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel
os
linux
1// SPDX-License-Identifier: GPL-2.0-or-later
2/*
3 * ACPI-WMI mapping driver
4 *
5 * Copyright (C) 2007-2008 Carlos Corbacho <carlos@strangeworlds.co.uk>
6 *
7 * GUID parsing code from ldm.c is:
8 * Copyright (C) 2001,2002 Richard Russon <ldm@flatcap.org>
9 * Copyright (c) 2001-2007 Anton Altaparmakov
10 * Copyright (C) 2001,2002 Jakob Kemi <jakob.kemi@telia.com>
11 *
12 * WMI bus infrastructure by Andrew Lutomirski and Darren Hart:
13 * Copyright (C) 2015 Andrew Lutomirski
14 * Copyright (C) 2017 VMware, Inc. All Rights Reserved.
15 */
16
17#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
18
19#include <linux/acpi.h>
20#include <linux/bits.h>
21#include <linux/build_bug.h>
22#include <linux/device.h>
23#include <linux/init.h>
24#include <linux/kernel.h>
25#include <linux/list.h>
26#include <linux/miscdevice.h>
27#include <linux/module.h>
28#include <linux/platform_device.h>
29#include <linux/slab.h>
30#include <linux/sysfs.h>
31#include <linux/types.h>
32#include <linux/uaccess.h>
33#include <linux/uuid.h>
34#include <linux/wmi.h>
35#include <linux/fs.h>
36#include <uapi/linux/wmi.h>
37
38MODULE_AUTHOR("Carlos Corbacho");
39MODULE_DESCRIPTION("ACPI-WMI Mapping Driver");
40MODULE_LICENSE("GPL");
41
42static LIST_HEAD(wmi_block_list);
43
44struct guid_block {
45 guid_t guid;
46 union {
47 char object_id[2];
48 struct {
49 unsigned char notify_id;
50 unsigned char reserved;
51 };
52 };
53 u8 instance_count;
54 u8 flags;
55} __packed;
56static_assert(sizeof(typeof_member(struct guid_block, guid)) == 16);
57static_assert(sizeof(struct guid_block) == 20);
58static_assert(__alignof__(struct guid_block) == 1);
59
60enum { /* wmi_block flags */
61 WMI_READ_TAKES_NO_ARGS,
62 WMI_PROBED,
63};
64
65struct wmi_block {
66 struct wmi_device dev;
67 struct list_head list;
68 struct guid_block gblock;
69 struct miscdevice char_dev;
70 struct mutex char_mutex;
71 struct acpi_device *acpi_device;
72 wmi_notify_handler handler;
73 void *handler_data;
74 u64 req_buf_size;
75 unsigned long flags;
76};
77
78
79/*
80 * If the GUID data block is marked as expensive, we must enable and
81 * explicitily disable data collection.
82 */
83#define ACPI_WMI_EXPENSIVE BIT(0)
84#define ACPI_WMI_METHOD BIT(1) /* GUID is a method */
85#define ACPI_WMI_STRING BIT(2) /* GUID takes & returns a string */
86#define ACPI_WMI_EVENT BIT(3) /* GUID is an event */
87
88static bool debug_event;
89module_param(debug_event, bool, 0444);
90MODULE_PARM_DESC(debug_event,
91 "Log WMI Events [0/1]");
92
93static bool debug_dump_wdg;
94module_param(debug_dump_wdg, bool, 0444);
95MODULE_PARM_DESC(debug_dump_wdg,
96 "Dump available WMI interfaces [0/1]");
97
98static int acpi_wmi_remove(struct platform_device *device);
99static int acpi_wmi_probe(struct platform_device *device);
100
101static const struct acpi_device_id wmi_device_ids[] = {
102 {"PNP0C14", 0},
103 {"pnp0c14", 0},
104 { }
105};
106MODULE_DEVICE_TABLE(acpi, wmi_device_ids);
107
108static struct platform_driver acpi_wmi_driver = {
109 .driver = {
110 .name = "acpi-wmi",
111 .acpi_match_table = wmi_device_ids,
112 },
113 .probe = acpi_wmi_probe,
114 .remove = acpi_wmi_remove,
115};
116
117/*
118 * GUID parsing functions
119 */
120
121static acpi_status find_guid(const char *guid_string, struct wmi_block **out)
122{
123 guid_t guid_input;
124 struct wmi_block *wblock;
125
126 if (!guid_string)
127 return AE_BAD_PARAMETER;
128
129 if (guid_parse(guid_string, &guid_input))
130 return AE_BAD_PARAMETER;
131
132 list_for_each_entry(wblock, &wmi_block_list, list) {
133 if (guid_equal(&wblock->gblock.guid, &guid_input)) {
134 if (out)
135 *out = wblock;
136
137 return AE_OK;
138 }
139 }
140
141 return AE_NOT_FOUND;
142}
143
144static const void *find_guid_context(struct wmi_block *wblock,
145 struct wmi_driver *wdriver)
146{
147 const struct wmi_device_id *id;
148
149 id = wdriver->id_table;
150 if (!id)
151 return NULL;
152
153 while (*id->guid_string) {
154 guid_t guid_input;
155
156 if (guid_parse(id->guid_string, &guid_input))
157 continue;
158 if (guid_equal(&wblock->gblock.guid, &guid_input))
159 return id->context;
160 id++;
161 }
162 return NULL;
163}
164
165static int get_subobj_info(acpi_handle handle, const char *pathname,
166 struct acpi_device_info **info)
167{
168 struct acpi_device_info *dummy_info, **info_ptr;
169 acpi_handle subobj_handle;
170 acpi_status status;
171
172 status = acpi_get_handle(handle, (char *)pathname, &subobj_handle);
173 if (status == AE_NOT_FOUND)
174 return -ENOENT;
175 else if (ACPI_FAILURE(status))
176 return -EIO;
177
178 info_ptr = info ? info : &dummy_info;
179 status = acpi_get_object_info(subobj_handle, info_ptr);
180 if (ACPI_FAILURE(status))
181 return -EIO;
182
183 if (!info)
184 kfree(dummy_info);
185
186 return 0;
187}
188
189static acpi_status wmi_method_enable(struct wmi_block *wblock, bool enable)
190{
191 struct guid_block *block;
192 char method[5];
193 acpi_status status;
194 acpi_handle handle;
195
196 block = &wblock->gblock;
197 handle = wblock->acpi_device->handle;
198
199 snprintf(method, 5, "WE%02X", block->notify_id);
200 status = acpi_execute_simple_method(handle, method, enable);
201 if (status == AE_NOT_FOUND)
202 return AE_OK;
203
204 return status;
205}
206
207#define WMI_ACPI_METHOD_NAME_SIZE 5
208
209static inline void get_acpi_method_name(const struct wmi_block *wblock,
210 const char method,
211 char buffer[static WMI_ACPI_METHOD_NAME_SIZE])
212{
213 static_assert(ARRAY_SIZE(wblock->gblock.object_id) == 2);
214 static_assert(WMI_ACPI_METHOD_NAME_SIZE >= 5);
215
216 buffer[0] = 'W';
217 buffer[1] = method;
218 buffer[2] = wblock->gblock.object_id[0];
219 buffer[3] = wblock->gblock.object_id[1];
220 buffer[4] = '\0';
221}
222
223static inline acpi_object_type get_param_acpi_type(const struct wmi_block *wblock)
224{
225 if (wblock->gblock.flags & ACPI_WMI_STRING)
226 return ACPI_TYPE_STRING;
227 else
228 return ACPI_TYPE_BUFFER;
229}
230
231static acpi_status get_event_data(const struct wmi_block *wblock, struct acpi_buffer *out)
232{
233 union acpi_object param = {
234 .integer = {
235 .type = ACPI_TYPE_INTEGER,
236 .value = wblock->gblock.notify_id,
237 }
238 };
239 struct acpi_object_list input = {
240 .count = 1,
241 .pointer = ¶m,
242 };
243
244 return acpi_evaluate_object(wblock->acpi_device->handle, "_WED", &input, out);
245}
246
247/*
248 * Exported WMI functions
249 */
250
251/**
252 * set_required_buffer_size - Sets the buffer size needed for performing IOCTL
253 * @wdev: A wmi bus device from a driver
254 * @length: Required buffer size
255 *
256 * Allocates memory needed for buffer, stores the buffer size in that memory
257 */
258int set_required_buffer_size(struct wmi_device *wdev, u64 length)
259{
260 struct wmi_block *wblock;
261
262 wblock = container_of(wdev, struct wmi_block, dev);
263 wblock->req_buf_size = length;
264
265 return 0;
266}
267EXPORT_SYMBOL_GPL(set_required_buffer_size);
268
269/**
270 * wmi_evaluate_method - Evaluate a WMI method
271 * @guid_string: 36 char string of the form fa50ff2b-f2e8-45de-83fa-65417f2f49ba
272 * @instance: Instance index
273 * @method_id: Method ID to call
274 * @in: Buffer containing input for the method call
275 * @out: Empty buffer to return the method results
276 *
277 * Call an ACPI-WMI method
278 */
279acpi_status wmi_evaluate_method(const char *guid_string, u8 instance, u32 method_id,
280 const struct acpi_buffer *in, struct acpi_buffer *out)
281{
282 struct wmi_block *wblock = NULL;
283 acpi_status status;
284
285 status = find_guid(guid_string, &wblock);
286 if (ACPI_FAILURE(status))
287 return status;
288
289 return wmidev_evaluate_method(&wblock->dev, instance, method_id,
290 in, out);
291}
292EXPORT_SYMBOL_GPL(wmi_evaluate_method);
293
294/**
295 * wmidev_evaluate_method - Evaluate a WMI method
296 * @wdev: A wmi bus device from a driver
297 * @instance: Instance index
298 * @method_id: Method ID to call
299 * @in: Buffer containing input for the method call
300 * @out: Empty buffer to return the method results
301 *
302 * Call an ACPI-WMI method
303 */
304acpi_status wmidev_evaluate_method(struct wmi_device *wdev, u8 instance, u32 method_id,
305 const struct acpi_buffer *in, struct acpi_buffer *out)
306{
307 struct guid_block *block;
308 struct wmi_block *wblock;
309 acpi_handle handle;
310 struct acpi_object_list input;
311 union acpi_object params[3];
312 char method[WMI_ACPI_METHOD_NAME_SIZE];
313
314 wblock = container_of(wdev, struct wmi_block, dev);
315 block = &wblock->gblock;
316 handle = wblock->acpi_device->handle;
317
318 if (!(block->flags & ACPI_WMI_METHOD))
319 return AE_BAD_DATA;
320
321 if (block->instance_count <= instance)
322 return AE_BAD_PARAMETER;
323
324 input.count = 2;
325 input.pointer = params;
326 params[0].type = ACPI_TYPE_INTEGER;
327 params[0].integer.value = instance;
328 params[1].type = ACPI_TYPE_INTEGER;
329 params[1].integer.value = method_id;
330
331 if (in) {
332 input.count = 3;
333
334 params[2].type = get_param_acpi_type(wblock);
335 params[2].buffer.length = in->length;
336 params[2].buffer.pointer = in->pointer;
337 }
338
339 get_acpi_method_name(wblock, 'M', method);
340
341 return acpi_evaluate_object(handle, method, &input, out);
342}
343EXPORT_SYMBOL_GPL(wmidev_evaluate_method);
344
345static acpi_status __query_block(struct wmi_block *wblock, u8 instance,
346 struct acpi_buffer *out)
347{
348 struct guid_block *block;
349 acpi_handle handle;
350 acpi_status status, wc_status = AE_ERROR;
351 struct acpi_object_list input;
352 union acpi_object wq_params[1];
353 char wc_method[WMI_ACPI_METHOD_NAME_SIZE];
354 char method[WMI_ACPI_METHOD_NAME_SIZE];
355
356 if (!out)
357 return AE_BAD_PARAMETER;
358
359 block = &wblock->gblock;
360 handle = wblock->acpi_device->handle;
361
362 if (block->instance_count <= instance)
363 return AE_BAD_PARAMETER;
364
365 /* Check GUID is a data block */
366 if (block->flags & (ACPI_WMI_EVENT | ACPI_WMI_METHOD))
367 return AE_ERROR;
368
369 input.count = 1;
370 input.pointer = wq_params;
371 wq_params[0].type = ACPI_TYPE_INTEGER;
372 wq_params[0].integer.value = instance;
373
374 if (instance == 0 && test_bit(WMI_READ_TAKES_NO_ARGS, &wblock->flags))
375 input.count = 0;
376
377 /*
378 * If ACPI_WMI_EXPENSIVE, call the relevant WCxx method first to
379 * enable collection.
380 */
381 if (block->flags & ACPI_WMI_EXPENSIVE) {
382 get_acpi_method_name(wblock, 'C', wc_method);
383
384 /*
385 * Some GUIDs break the specification by declaring themselves
386 * expensive, but have no corresponding WCxx method. So we
387 * should not fail if this happens.
388 */
389 wc_status = acpi_execute_simple_method(handle, wc_method, 1);
390 }
391
392 get_acpi_method_name(wblock, 'Q', method);
393 status = acpi_evaluate_object(handle, method, &input, out);
394
395 /*
396 * If ACPI_WMI_EXPENSIVE, call the relevant WCxx method, even if
397 * the WQxx method failed - we should disable collection anyway.
398 */
399 if ((block->flags & ACPI_WMI_EXPENSIVE) && ACPI_SUCCESS(wc_status)) {
400 /*
401 * Ignore whether this WCxx call succeeds or not since
402 * the previously executed WQxx method call might have
403 * succeeded, and returning the failing status code
404 * of this call would throw away the result of the WQxx
405 * call, potentially leaking memory.
406 */
407 acpi_execute_simple_method(handle, wc_method, 0);
408 }
409
410 return status;
411}
412
413/**
414 * wmi_query_block - Return contents of a WMI block (deprecated)
415 * @guid_string: 36 char string of the form fa50ff2b-f2e8-45de-83fa-65417f2f49ba
416 * @instance: Instance index
417 * @out: Empty buffer to return the contents of the data block to
418 *
419 * Return the contents of an ACPI-WMI data block to a buffer
420 */
421acpi_status wmi_query_block(const char *guid_string, u8 instance,
422 struct acpi_buffer *out)
423{
424 struct wmi_block *wblock;
425 acpi_status status;
426
427 status = find_guid(guid_string, &wblock);
428 if (ACPI_FAILURE(status))
429 return status;
430
431 return __query_block(wblock, instance, out);
432}
433EXPORT_SYMBOL_GPL(wmi_query_block);
434
435union acpi_object *wmidev_block_query(struct wmi_device *wdev, u8 instance)
436{
437 struct acpi_buffer out = { ACPI_ALLOCATE_BUFFER, NULL };
438 struct wmi_block *wblock = container_of(wdev, struct wmi_block, dev);
439
440 if (ACPI_FAILURE(__query_block(wblock, instance, &out)))
441 return NULL;
442
443 return out.pointer;
444}
445EXPORT_SYMBOL_GPL(wmidev_block_query);
446
447/**
448 * wmi_set_block - Write to a WMI block
449 * @guid_string: 36 char string of the form fa50ff2b-f2e8-45de-83fa-65417f2f49ba
450 * @instance: Instance index
451 * @in: Buffer containing new values for the data block
452 *
453 * Write the contents of the input buffer to an ACPI-WMI data block
454 */
455acpi_status wmi_set_block(const char *guid_string, u8 instance,
456 const struct acpi_buffer *in)
457{
458 struct wmi_block *wblock = NULL;
459 struct guid_block *block;
460 acpi_handle handle;
461 struct acpi_object_list input;
462 union acpi_object params[2];
463 char method[WMI_ACPI_METHOD_NAME_SIZE];
464 acpi_status status;
465
466 if (!in)
467 return AE_BAD_DATA;
468
469 status = find_guid(guid_string, &wblock);
470 if (ACPI_FAILURE(status))
471 return status;
472
473 block = &wblock->gblock;
474 handle = wblock->acpi_device->handle;
475
476 if (block->instance_count <= instance)
477 return AE_BAD_PARAMETER;
478
479 /* Check GUID is a data block */
480 if (block->flags & (ACPI_WMI_EVENT | ACPI_WMI_METHOD))
481 return AE_ERROR;
482
483 input.count = 2;
484 input.pointer = params;
485 params[0].type = ACPI_TYPE_INTEGER;
486 params[0].integer.value = instance;
487 params[1].type = get_param_acpi_type(wblock);
488 params[1].buffer.length = in->length;
489 params[1].buffer.pointer = in->pointer;
490
491 get_acpi_method_name(wblock, 'S', method);
492
493 return acpi_evaluate_object(handle, method, &input, NULL);
494}
495EXPORT_SYMBOL_GPL(wmi_set_block);
496
497static void wmi_dump_wdg(const struct guid_block *g)
498{
499 pr_info("%pUL:\n", &g->guid);
500 if (g->flags & ACPI_WMI_EVENT)
501 pr_info("\tnotify_id: 0x%02X\n", g->notify_id);
502 else
503 pr_info("\tobject_id: %2pE\n", g->object_id);
504 pr_info("\tinstance_count: %d\n", g->instance_count);
505 pr_info("\tflags: %#x", g->flags);
506 if (g->flags) {
507 if (g->flags & ACPI_WMI_EXPENSIVE)
508 pr_cont(" ACPI_WMI_EXPENSIVE");
509 if (g->flags & ACPI_WMI_METHOD)
510 pr_cont(" ACPI_WMI_METHOD");
511 if (g->flags & ACPI_WMI_STRING)
512 pr_cont(" ACPI_WMI_STRING");
513 if (g->flags & ACPI_WMI_EVENT)
514 pr_cont(" ACPI_WMI_EVENT");
515 }
516 pr_cont("\n");
517
518}
519
520static void wmi_notify_debug(u32 value, void *context)
521{
522 struct acpi_buffer response = { ACPI_ALLOCATE_BUFFER, NULL };
523 union acpi_object *obj;
524 acpi_status status;
525
526 status = wmi_get_event_data(value, &response);
527 if (status != AE_OK) {
528 pr_info("bad event status 0x%x\n", status);
529 return;
530 }
531
532 obj = response.pointer;
533 if (!obj)
534 return;
535
536 pr_info("DEBUG: event 0x%02X ", value);
537 switch (obj->type) {
538 case ACPI_TYPE_BUFFER:
539 pr_cont("BUFFER_TYPE - length %u\n", obj->buffer.length);
540 break;
541 case ACPI_TYPE_STRING:
542 pr_cont("STRING_TYPE - %s\n", obj->string.pointer);
543 break;
544 case ACPI_TYPE_INTEGER:
545 pr_cont("INTEGER_TYPE - %llu\n", obj->integer.value);
546 break;
547 case ACPI_TYPE_PACKAGE:
548 pr_cont("PACKAGE_TYPE - %u elements\n", obj->package.count);
549 break;
550 default:
551 pr_cont("object type 0x%X\n", obj->type);
552 }
553 kfree(obj);
554}
555
556/**
557 * wmi_install_notify_handler - Register handler for WMI events
558 * @guid: 36 char string of the form fa50ff2b-f2e8-45de-83fa-65417f2f49ba
559 * @handler: Function to handle notifications
560 * @data: Data to be returned to handler when event is fired
561 *
562 * Register a handler for events sent to the ACPI-WMI mapper device.
563 */
564acpi_status wmi_install_notify_handler(const char *guid,
565 wmi_notify_handler handler,
566 void *data)
567{
568 struct wmi_block *block;
569 acpi_status status = AE_NOT_EXIST;
570 guid_t guid_input;
571
572 if (!guid || !handler)
573 return AE_BAD_PARAMETER;
574
575 if (guid_parse(guid, &guid_input))
576 return AE_BAD_PARAMETER;
577
578 list_for_each_entry(block, &wmi_block_list, list) {
579 acpi_status wmi_status;
580
581 if (guid_equal(&block->gblock.guid, &guid_input)) {
582 if (block->handler &&
583 block->handler != wmi_notify_debug)
584 return AE_ALREADY_ACQUIRED;
585
586 block->handler = handler;
587 block->handler_data = data;
588
589 wmi_status = wmi_method_enable(block, true);
590 if ((wmi_status != AE_OK) ||
591 ((wmi_status == AE_OK) && (status == AE_NOT_EXIST)))
592 status = wmi_status;
593 }
594 }
595
596 return status;
597}
598EXPORT_SYMBOL_GPL(wmi_install_notify_handler);
599
600/**
601 * wmi_remove_notify_handler - Unregister handler for WMI events
602 * @guid: 36 char string of the form fa50ff2b-f2e8-45de-83fa-65417f2f49ba
603 *
604 * Unregister handler for events sent to the ACPI-WMI mapper device.
605 */
606acpi_status wmi_remove_notify_handler(const char *guid)
607{
608 struct wmi_block *block;
609 acpi_status status = AE_NOT_EXIST;
610 guid_t guid_input;
611
612 if (!guid)
613 return AE_BAD_PARAMETER;
614
615 if (guid_parse(guid, &guid_input))
616 return AE_BAD_PARAMETER;
617
618 list_for_each_entry(block, &wmi_block_list, list) {
619 acpi_status wmi_status;
620
621 if (guid_equal(&block->gblock.guid, &guid_input)) {
622 if (!block->handler ||
623 block->handler == wmi_notify_debug)
624 return AE_NULL_ENTRY;
625
626 if (debug_event) {
627 block->handler = wmi_notify_debug;
628 status = AE_OK;
629 } else {
630 wmi_status = wmi_method_enable(block, false);
631 block->handler = NULL;
632 block->handler_data = NULL;
633 if ((wmi_status != AE_OK) ||
634 ((wmi_status == AE_OK) &&
635 (status == AE_NOT_EXIST)))
636 status = wmi_status;
637 }
638 }
639 }
640
641 return status;
642}
643EXPORT_SYMBOL_GPL(wmi_remove_notify_handler);
644
645/**
646 * wmi_get_event_data - Get WMI data associated with an event
647 *
648 * @event: Event to find
649 * @out: Buffer to hold event data. out->pointer should be freed with kfree()
650 *
651 * Returns extra data associated with an event in WMI.
652 */
653acpi_status wmi_get_event_data(u32 event, struct acpi_buffer *out)
654{
655 struct wmi_block *wblock;
656
657 list_for_each_entry(wblock, &wmi_block_list, list) {
658 struct guid_block *gblock = &wblock->gblock;
659
660 if ((gblock->flags & ACPI_WMI_EVENT) && gblock->notify_id == event)
661 return get_event_data(wblock, out);
662 }
663
664 return AE_NOT_FOUND;
665}
666EXPORT_SYMBOL_GPL(wmi_get_event_data);
667
668/**
669 * wmi_has_guid - Check if a GUID is available
670 * @guid_string: 36 char string of the form fa50ff2b-f2e8-45de-83fa-65417f2f49ba
671 *
672 * Check if a given GUID is defined by _WDG
673 */
674bool wmi_has_guid(const char *guid_string)
675{
676 return ACPI_SUCCESS(find_guid(guid_string, NULL));
677}
678EXPORT_SYMBOL_GPL(wmi_has_guid);
679
680/**
681 * wmi_get_acpi_device_uid() - Get _UID name of ACPI device that defines GUID
682 * @guid_string: 36 char string of the form fa50ff2b-f2e8-45de-83fa-65417f2f49ba
683 *
684 * Find the _UID of ACPI device associated with this WMI GUID.
685 *
686 * Return: The ACPI _UID field value or NULL if the WMI GUID was not found
687 */
688char *wmi_get_acpi_device_uid(const char *guid_string)
689{
690 struct wmi_block *wblock = NULL;
691 acpi_status status;
692
693 status = find_guid(guid_string, &wblock);
694 if (ACPI_FAILURE(status))
695 return NULL;
696
697 return acpi_device_uid(wblock->acpi_device);
698}
699EXPORT_SYMBOL_GPL(wmi_get_acpi_device_uid);
700
701static struct wmi_block *dev_to_wblock(struct device *dev)
702{
703 return container_of(dev, struct wmi_block, dev.dev);
704}
705
706static struct wmi_device *dev_to_wdev(struct device *dev)
707{
708 return container_of(dev, struct wmi_device, dev);
709}
710
711static inline struct wmi_driver *drv_to_wdrv(struct device_driver *drv)
712{
713 return container_of(drv, struct wmi_driver, driver);
714}
715
716/*
717 * sysfs interface
718 */
719static ssize_t modalias_show(struct device *dev, struct device_attribute *attr,
720 char *buf)
721{
722 struct wmi_block *wblock = dev_to_wblock(dev);
723
724 return sysfs_emit(buf, "wmi:%pUL\n", &wblock->gblock.guid);
725}
726static DEVICE_ATTR_RO(modalias);
727
728static ssize_t guid_show(struct device *dev, struct device_attribute *attr,
729 char *buf)
730{
731 struct wmi_block *wblock = dev_to_wblock(dev);
732
733 return sysfs_emit(buf, "%pUL\n", &wblock->gblock.guid);
734}
735static DEVICE_ATTR_RO(guid);
736
737static ssize_t instance_count_show(struct device *dev,
738 struct device_attribute *attr, char *buf)
739{
740 struct wmi_block *wblock = dev_to_wblock(dev);
741
742 return sysfs_emit(buf, "%d\n", (int)wblock->gblock.instance_count);
743}
744static DEVICE_ATTR_RO(instance_count);
745
746static ssize_t expensive_show(struct device *dev,
747 struct device_attribute *attr, char *buf)
748{
749 struct wmi_block *wblock = dev_to_wblock(dev);
750
751 return sysfs_emit(buf, "%d\n",
752 (wblock->gblock.flags & ACPI_WMI_EXPENSIVE) != 0);
753}
754static DEVICE_ATTR_RO(expensive);
755
756static struct attribute *wmi_attrs[] = {
757 &dev_attr_modalias.attr,
758 &dev_attr_guid.attr,
759 &dev_attr_instance_count.attr,
760 &dev_attr_expensive.attr,
761 NULL
762};
763ATTRIBUTE_GROUPS(wmi);
764
765static ssize_t notify_id_show(struct device *dev, struct device_attribute *attr,
766 char *buf)
767{
768 struct wmi_block *wblock = dev_to_wblock(dev);
769
770 return sysfs_emit(buf, "%02X\n", (unsigned int)wblock->gblock.notify_id);
771}
772static DEVICE_ATTR_RO(notify_id);
773
774static struct attribute *wmi_event_attrs[] = {
775 &dev_attr_notify_id.attr,
776 NULL
777};
778ATTRIBUTE_GROUPS(wmi_event);
779
780static ssize_t object_id_show(struct device *dev, struct device_attribute *attr,
781 char *buf)
782{
783 struct wmi_block *wblock = dev_to_wblock(dev);
784
785 return sysfs_emit(buf, "%c%c\n", wblock->gblock.object_id[0],
786 wblock->gblock.object_id[1]);
787}
788static DEVICE_ATTR_RO(object_id);
789
790static ssize_t setable_show(struct device *dev, struct device_attribute *attr,
791 char *buf)
792{
793 struct wmi_device *wdev = dev_to_wdev(dev);
794
795 return sysfs_emit(buf, "%d\n", (int)wdev->setable);
796}
797static DEVICE_ATTR_RO(setable);
798
799static struct attribute *wmi_data_attrs[] = {
800 &dev_attr_object_id.attr,
801 &dev_attr_setable.attr,
802 NULL
803};
804ATTRIBUTE_GROUPS(wmi_data);
805
806static struct attribute *wmi_method_attrs[] = {
807 &dev_attr_object_id.attr,
808 NULL
809};
810ATTRIBUTE_GROUPS(wmi_method);
811
812static int wmi_dev_uevent(struct device *dev, struct kobj_uevent_env *env)
813{
814 struct wmi_block *wblock = dev_to_wblock(dev);
815
816 if (add_uevent_var(env, "MODALIAS=wmi:%pUL", &wblock->gblock.guid))
817 return -ENOMEM;
818
819 if (add_uevent_var(env, "WMI_GUID=%pUL", &wblock->gblock.guid))
820 return -ENOMEM;
821
822 return 0;
823}
824
825static void wmi_dev_release(struct device *dev)
826{
827 struct wmi_block *wblock = dev_to_wblock(dev);
828
829 kfree(wblock);
830}
831
832static int wmi_dev_match(struct device *dev, struct device_driver *driver)
833{
834 struct wmi_driver *wmi_driver = drv_to_wdrv(driver);
835 struct wmi_block *wblock = dev_to_wblock(dev);
836 const struct wmi_device_id *id = wmi_driver->id_table;
837
838 if (id == NULL)
839 return 0;
840
841 while (*id->guid_string) {
842 guid_t driver_guid;
843
844 if (WARN_ON(guid_parse(id->guid_string, &driver_guid)))
845 continue;
846 if (guid_equal(&driver_guid, &wblock->gblock.guid))
847 return 1;
848
849 id++;
850 }
851
852 return 0;
853}
854static int wmi_char_open(struct inode *inode, struct file *filp)
855{
856 const char *driver_name = filp->f_path.dentry->d_iname;
857 struct wmi_block *wblock;
858 struct wmi_block *next;
859
860 list_for_each_entry_safe(wblock, next, &wmi_block_list, list) {
861 if (!wblock->dev.dev.driver)
862 continue;
863 if (strcmp(driver_name, wblock->dev.dev.driver->name) == 0) {
864 filp->private_data = wblock;
865 break;
866 }
867 }
868
869 if (!filp->private_data)
870 return -ENODEV;
871
872 return nonseekable_open(inode, filp);
873}
874
875static ssize_t wmi_char_read(struct file *filp, char __user *buffer,
876 size_t length, loff_t *offset)
877{
878 struct wmi_block *wblock = filp->private_data;
879
880 return simple_read_from_buffer(buffer, length, offset,
881 &wblock->req_buf_size,
882 sizeof(wblock->req_buf_size));
883}
884
885static long wmi_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
886{
887 struct wmi_ioctl_buffer __user *input =
888 (struct wmi_ioctl_buffer __user *) arg;
889 struct wmi_block *wblock = filp->private_data;
890 struct wmi_ioctl_buffer *buf;
891 struct wmi_driver *wdriver;
892 int ret;
893
894 if (_IOC_TYPE(cmd) != WMI_IOC)
895 return -ENOTTY;
896
897 /* make sure we're not calling a higher instance than exists*/
898 if (_IOC_NR(cmd) >= wblock->gblock.instance_count)
899 return -EINVAL;
900
901 mutex_lock(&wblock->char_mutex);
902 buf = wblock->handler_data;
903 if (get_user(buf->length, &input->length)) {
904 dev_dbg(&wblock->dev.dev, "Read length from user failed\n");
905 ret = -EFAULT;
906 goto out_ioctl;
907 }
908 /* if it's too small, abort */
909 if (buf->length < wblock->req_buf_size) {
910 dev_err(&wblock->dev.dev,
911 "Buffer %lld too small, need at least %lld\n",
912 buf->length, wblock->req_buf_size);
913 ret = -EINVAL;
914 goto out_ioctl;
915 }
916 /* if it's too big, warn, driver will only use what is needed */
917 if (buf->length > wblock->req_buf_size)
918 dev_warn(&wblock->dev.dev,
919 "Buffer %lld is bigger than required %lld\n",
920 buf->length, wblock->req_buf_size);
921
922 /* copy the structure from userspace */
923 if (copy_from_user(buf, input, wblock->req_buf_size)) {
924 dev_dbg(&wblock->dev.dev, "Copy %llu from user failed\n",
925 wblock->req_buf_size);
926 ret = -EFAULT;
927 goto out_ioctl;
928 }
929
930 /* let the driver do any filtering and do the call */
931 wdriver = drv_to_wdrv(wblock->dev.dev.driver);
932 if (!try_module_get(wdriver->driver.owner)) {
933 ret = -EBUSY;
934 goto out_ioctl;
935 }
936 ret = wdriver->filter_callback(&wblock->dev, cmd, buf);
937 module_put(wdriver->driver.owner);
938 if (ret)
939 goto out_ioctl;
940
941 /* return the result (only up to our internal buffer size) */
942 if (copy_to_user(input, buf, wblock->req_buf_size)) {
943 dev_dbg(&wblock->dev.dev, "Copy %llu to user failed\n",
944 wblock->req_buf_size);
945 ret = -EFAULT;
946 }
947
948out_ioctl:
949 mutex_unlock(&wblock->char_mutex);
950 return ret;
951}
952
953static const struct file_operations wmi_fops = {
954 .owner = THIS_MODULE,
955 .read = wmi_char_read,
956 .open = wmi_char_open,
957 .unlocked_ioctl = wmi_ioctl,
958 .compat_ioctl = compat_ptr_ioctl,
959};
960
961static int wmi_dev_probe(struct device *dev)
962{
963 struct wmi_block *wblock = dev_to_wblock(dev);
964 struct wmi_driver *wdriver = drv_to_wdrv(dev->driver);
965 int ret = 0;
966 char *buf;
967
968 if (ACPI_FAILURE(wmi_method_enable(wblock, true)))
969 dev_warn(dev, "failed to enable device -- probing anyway\n");
970
971 if (wdriver->probe) {
972 ret = wdriver->probe(dev_to_wdev(dev),
973 find_guid_context(wblock, wdriver));
974 if (ret != 0)
975 goto probe_failure;
976 }
977
978 /* driver wants a character device made */
979 if (wdriver->filter_callback) {
980 /* check that required buffer size declared by driver or MOF */
981 if (!wblock->req_buf_size) {
982 dev_err(&wblock->dev.dev,
983 "Required buffer size not set\n");
984 ret = -EINVAL;
985 goto probe_failure;
986 }
987
988 wblock->handler_data = kmalloc(wblock->req_buf_size,
989 GFP_KERNEL);
990 if (!wblock->handler_data) {
991 ret = -ENOMEM;
992 goto probe_failure;
993 }
994
995 buf = kasprintf(GFP_KERNEL, "wmi/%s", wdriver->driver.name);
996 if (!buf) {
997 ret = -ENOMEM;
998 goto probe_string_failure;
999 }
1000 wblock->char_dev.minor = MISC_DYNAMIC_MINOR;
1001 wblock->char_dev.name = buf;
1002 wblock->char_dev.fops = &wmi_fops;
1003 wblock->char_dev.mode = 0444;
1004 ret = misc_register(&wblock->char_dev);
1005 if (ret) {
1006 dev_warn(dev, "failed to register char dev: %d\n", ret);
1007 ret = -ENOMEM;
1008 goto probe_misc_failure;
1009 }
1010 }
1011
1012 set_bit(WMI_PROBED, &wblock->flags);
1013 return 0;
1014
1015probe_misc_failure:
1016 kfree(buf);
1017probe_string_failure:
1018 kfree(wblock->handler_data);
1019probe_failure:
1020 if (ACPI_FAILURE(wmi_method_enable(wblock, false)))
1021 dev_warn(dev, "failed to disable device\n");
1022 return ret;
1023}
1024
1025static void wmi_dev_remove(struct device *dev)
1026{
1027 struct wmi_block *wblock = dev_to_wblock(dev);
1028 struct wmi_driver *wdriver = drv_to_wdrv(dev->driver);
1029
1030 clear_bit(WMI_PROBED, &wblock->flags);
1031
1032 if (wdriver->filter_callback) {
1033 misc_deregister(&wblock->char_dev);
1034 kfree(wblock->char_dev.name);
1035 kfree(wblock->handler_data);
1036 }
1037
1038 if (wdriver->remove)
1039 wdriver->remove(dev_to_wdev(dev));
1040
1041 if (ACPI_FAILURE(wmi_method_enable(wblock, false)))
1042 dev_warn(dev, "failed to disable device\n");
1043}
1044
1045static struct class wmi_bus_class = {
1046 .name = "wmi_bus",
1047};
1048
1049static struct bus_type wmi_bus_type = {
1050 .name = "wmi",
1051 .dev_groups = wmi_groups,
1052 .match = wmi_dev_match,
1053 .uevent = wmi_dev_uevent,
1054 .probe = wmi_dev_probe,
1055 .remove = wmi_dev_remove,
1056};
1057
1058static const struct device_type wmi_type_event = {
1059 .name = "event",
1060 .groups = wmi_event_groups,
1061 .release = wmi_dev_release,
1062};
1063
1064static const struct device_type wmi_type_method = {
1065 .name = "method",
1066 .groups = wmi_method_groups,
1067 .release = wmi_dev_release,
1068};
1069
1070static const struct device_type wmi_type_data = {
1071 .name = "data",
1072 .groups = wmi_data_groups,
1073 .release = wmi_dev_release,
1074};
1075
1076static int wmi_create_device(struct device *wmi_bus_dev,
1077 struct wmi_block *wblock,
1078 struct acpi_device *device)
1079{
1080 struct acpi_device_info *info;
1081 char method[WMI_ACPI_METHOD_NAME_SIZE];
1082 int result;
1083
1084 if (wblock->gblock.flags & ACPI_WMI_EVENT) {
1085 wblock->dev.dev.type = &wmi_type_event;
1086 goto out_init;
1087 }
1088
1089 if (wblock->gblock.flags & ACPI_WMI_METHOD) {
1090 wblock->dev.dev.type = &wmi_type_method;
1091 mutex_init(&wblock->char_mutex);
1092 goto out_init;
1093 }
1094
1095 /*
1096 * Data Block Query Control Method (WQxx by convention) is
1097 * required per the WMI documentation. If it is not present,
1098 * we ignore this data block.
1099 */
1100 get_acpi_method_name(wblock, 'Q', method);
1101 result = get_subobj_info(device->handle, method, &info);
1102
1103 if (result) {
1104 dev_warn(wmi_bus_dev,
1105 "%s data block query control method not found\n",
1106 method);
1107 return result;
1108 }
1109
1110 wblock->dev.dev.type = &wmi_type_data;
1111
1112 /*
1113 * The Microsoft documentation specifically states:
1114 *
1115 * Data blocks registered with only a single instance
1116 * can ignore the parameter.
1117 *
1118 * ACPICA will get mad at us if we call the method with the wrong number
1119 * of arguments, so check what our method expects. (On some Dell
1120 * laptops, WQxx may not be a method at all.)
1121 */
1122 if (info->type != ACPI_TYPE_METHOD || info->param_count == 0)
1123 set_bit(WMI_READ_TAKES_NO_ARGS, &wblock->flags);
1124
1125 kfree(info);
1126
1127 get_acpi_method_name(wblock, 'S', method);
1128 result = get_subobj_info(device->handle, method, NULL);
1129
1130 if (result == 0)
1131 wblock->dev.setable = true;
1132
1133 out_init:
1134 wblock->dev.dev.bus = &wmi_bus_type;
1135 wblock->dev.dev.parent = wmi_bus_dev;
1136
1137 dev_set_name(&wblock->dev.dev, "%pUL", &wblock->gblock.guid);
1138
1139 device_initialize(&wblock->dev.dev);
1140
1141 return 0;
1142}
1143
1144static void wmi_free_devices(struct acpi_device *device)
1145{
1146 struct wmi_block *wblock, *next;
1147
1148 /* Delete devices for all the GUIDs */
1149 list_for_each_entry_safe(wblock, next, &wmi_block_list, list) {
1150 if (wblock->acpi_device == device) {
1151 list_del(&wblock->list);
1152 device_unregister(&wblock->dev.dev);
1153 }
1154 }
1155}
1156
1157static bool guid_already_parsed(struct acpi_device *device, const guid_t *guid)
1158{
1159 struct wmi_block *wblock;
1160
1161 list_for_each_entry(wblock, &wmi_block_list, list) {
1162 if (guid_equal(&wblock->gblock.guid, guid)) {
1163 /*
1164 * Because we historically didn't track the relationship
1165 * between GUIDs and ACPI nodes, we don't know whether
1166 * we need to suppress GUIDs that are unique on a
1167 * given node but duplicated across nodes.
1168 */
1169 dev_warn(&device->dev, "duplicate WMI GUID %pUL (first instance was on %s)\n",
1170 guid, dev_name(&wblock->acpi_device->dev));
1171 return true;
1172 }
1173 }
1174
1175 return false;
1176}
1177
1178/*
1179 * Parse the _WDG method for the GUID data blocks
1180 */
1181static int parse_wdg(struct device *wmi_bus_dev, struct acpi_device *device)
1182{
1183 struct acpi_buffer out = {ACPI_ALLOCATE_BUFFER, NULL};
1184 const struct guid_block *gblock;
1185 struct wmi_block *wblock, *next;
1186 union acpi_object *obj;
1187 acpi_status status;
1188 int retval = 0;
1189 u32 i, total;
1190
1191 status = acpi_evaluate_object(device->handle, "_WDG", NULL, &out);
1192 if (ACPI_FAILURE(status))
1193 return -ENXIO;
1194
1195 obj = out.pointer;
1196 if (!obj)
1197 return -ENXIO;
1198
1199 if (obj->type != ACPI_TYPE_BUFFER) {
1200 retval = -ENXIO;
1201 goto out_free_pointer;
1202 }
1203
1204 gblock = (const struct guid_block *)obj->buffer.pointer;
1205 total = obj->buffer.length / sizeof(struct guid_block);
1206
1207 for (i = 0; i < total; i++) {
1208 if (debug_dump_wdg)
1209 wmi_dump_wdg(&gblock[i]);
1210
1211 /*
1212 * Some WMI devices, like those for nVidia hooks, have a
1213 * duplicate GUID. It's not clear what we should do in this
1214 * case yet, so for now, we'll just ignore the duplicate
1215 * for device creation.
1216 */
1217 if (guid_already_parsed(device, &gblock[i].guid))
1218 continue;
1219
1220 wblock = kzalloc(sizeof(*wblock), GFP_KERNEL);
1221 if (!wblock) {
1222 retval = -ENOMEM;
1223 break;
1224 }
1225
1226 wblock->acpi_device = device;
1227 wblock->gblock = gblock[i];
1228
1229 retval = wmi_create_device(wmi_bus_dev, wblock, device);
1230 if (retval) {
1231 kfree(wblock);
1232 continue;
1233 }
1234
1235 list_add_tail(&wblock->list, &wmi_block_list);
1236
1237 if (debug_event) {
1238 wblock->handler = wmi_notify_debug;
1239 wmi_method_enable(wblock, true);
1240 }
1241 }
1242
1243 /*
1244 * Now that all of the devices are created, add them to the
1245 * device tree and probe subdrivers.
1246 */
1247 list_for_each_entry_safe(wblock, next, &wmi_block_list, list) {
1248 if (wblock->acpi_device != device)
1249 continue;
1250
1251 retval = device_add(&wblock->dev.dev);
1252 if (retval) {
1253 dev_err(wmi_bus_dev, "failed to register %pUL\n",
1254 &wblock->gblock.guid);
1255 if (debug_event)
1256 wmi_method_enable(wblock, false);
1257 list_del(&wblock->list);
1258 put_device(&wblock->dev.dev);
1259 }
1260 }
1261
1262out_free_pointer:
1263 kfree(out.pointer);
1264 return retval;
1265}
1266
1267/*
1268 * WMI can have EmbeddedControl access regions. In which case, we just want to
1269 * hand these off to the EC driver.
1270 */
1271static acpi_status
1272acpi_wmi_ec_space_handler(u32 function, acpi_physical_address address,
1273 u32 bits, u64 *value,
1274 void *handler_context, void *region_context)
1275{
1276 int result = 0, i = 0;
1277 u8 temp = 0;
1278
1279 if ((address > 0xFF) || !value)
1280 return AE_BAD_PARAMETER;
1281
1282 if (function != ACPI_READ && function != ACPI_WRITE)
1283 return AE_BAD_PARAMETER;
1284
1285 if (bits != 8)
1286 return AE_BAD_PARAMETER;
1287
1288 if (function == ACPI_READ) {
1289 result = ec_read(address, &temp);
1290 (*value) |= ((u64)temp) << i;
1291 } else {
1292 temp = 0xff & ((*value) >> i);
1293 result = ec_write(address, temp);
1294 }
1295
1296 switch (result) {
1297 case -EINVAL:
1298 return AE_BAD_PARAMETER;
1299 case -ENODEV:
1300 return AE_NOT_FOUND;
1301 case -ETIME:
1302 return AE_TIME;
1303 default:
1304 return AE_OK;
1305 }
1306}
1307
1308static void acpi_wmi_notify_handler(acpi_handle handle, u32 event,
1309 void *context)
1310{
1311 struct wmi_block *wblock;
1312 bool found_it = false;
1313
1314 list_for_each_entry(wblock, &wmi_block_list, list) {
1315 struct guid_block *block = &wblock->gblock;
1316
1317 if (wblock->acpi_device->handle == handle &&
1318 (block->flags & ACPI_WMI_EVENT) &&
1319 (block->notify_id == event)) {
1320 found_it = true;
1321 break;
1322 }
1323 }
1324
1325 if (!found_it)
1326 return;
1327
1328 /* If a driver is bound, then notify the driver. */
1329 if (test_bit(WMI_PROBED, &wblock->flags) && wblock->dev.dev.driver) {
1330 struct wmi_driver *driver = drv_to_wdrv(wblock->dev.dev.driver);
1331 struct acpi_buffer evdata = { ACPI_ALLOCATE_BUFFER, NULL };
1332 acpi_status status;
1333
1334 if (!driver->no_notify_data) {
1335 status = get_event_data(wblock, &evdata);
1336 if (ACPI_FAILURE(status)) {
1337 dev_warn(&wblock->dev.dev, "failed to get event data\n");
1338 return;
1339 }
1340 }
1341
1342 if (driver->notify)
1343 driver->notify(&wblock->dev, evdata.pointer);
1344
1345 kfree(evdata.pointer);
1346 } else if (wblock->handler) {
1347 /* Legacy handler */
1348 wblock->handler(event, wblock->handler_data);
1349 }
1350
1351 if (debug_event)
1352 pr_info("DEBUG: GUID %pUL event 0x%02X\n", &wblock->gblock.guid, event);
1353
1354 acpi_bus_generate_netlink_event(
1355 wblock->acpi_device->pnp.device_class,
1356 dev_name(&wblock->dev.dev),
1357 event, 0);
1358}
1359
1360static int acpi_wmi_remove(struct platform_device *device)
1361{
1362 struct acpi_device *acpi_device = ACPI_COMPANION(&device->dev);
1363
1364 acpi_remove_notify_handler(acpi_device->handle, ACPI_ALL_NOTIFY,
1365 acpi_wmi_notify_handler);
1366 acpi_remove_address_space_handler(acpi_device->handle,
1367 ACPI_ADR_SPACE_EC, &acpi_wmi_ec_space_handler);
1368 wmi_free_devices(acpi_device);
1369 device_unregister(dev_get_drvdata(&device->dev));
1370
1371 return 0;
1372}
1373
1374static int acpi_wmi_probe(struct platform_device *device)
1375{
1376 struct acpi_device *acpi_device;
1377 struct device *wmi_bus_dev;
1378 acpi_status status;
1379 int error;
1380
1381 acpi_device = ACPI_COMPANION(&device->dev);
1382 if (!acpi_device) {
1383 dev_err(&device->dev, "ACPI companion is missing\n");
1384 return -ENODEV;
1385 }
1386
1387 status = acpi_install_address_space_handler(acpi_device->handle,
1388 ACPI_ADR_SPACE_EC,
1389 &acpi_wmi_ec_space_handler,
1390 NULL, NULL);
1391 if (ACPI_FAILURE(status)) {
1392 dev_err(&device->dev, "Error installing EC region handler\n");
1393 return -ENODEV;
1394 }
1395
1396 status = acpi_install_notify_handler(acpi_device->handle,
1397 ACPI_ALL_NOTIFY,
1398 acpi_wmi_notify_handler,
1399 NULL);
1400 if (ACPI_FAILURE(status)) {
1401 dev_err(&device->dev, "Error installing notify handler\n");
1402 error = -ENODEV;
1403 goto err_remove_ec_handler;
1404 }
1405
1406 wmi_bus_dev = device_create(&wmi_bus_class, &device->dev, MKDEV(0, 0),
1407 NULL, "wmi_bus-%s", dev_name(&device->dev));
1408 if (IS_ERR(wmi_bus_dev)) {
1409 error = PTR_ERR(wmi_bus_dev);
1410 goto err_remove_notify_handler;
1411 }
1412 dev_set_drvdata(&device->dev, wmi_bus_dev);
1413
1414 error = parse_wdg(wmi_bus_dev, acpi_device);
1415 if (error) {
1416 pr_err("Failed to parse WDG method\n");
1417 goto err_remove_busdev;
1418 }
1419
1420 return 0;
1421
1422err_remove_busdev:
1423 device_unregister(wmi_bus_dev);
1424
1425err_remove_notify_handler:
1426 acpi_remove_notify_handler(acpi_device->handle, ACPI_ALL_NOTIFY,
1427 acpi_wmi_notify_handler);
1428
1429err_remove_ec_handler:
1430 acpi_remove_address_space_handler(acpi_device->handle,
1431 ACPI_ADR_SPACE_EC,
1432 &acpi_wmi_ec_space_handler);
1433
1434 return error;
1435}
1436
1437int __must_check __wmi_driver_register(struct wmi_driver *driver,
1438 struct module *owner)
1439{
1440 driver->driver.owner = owner;
1441 driver->driver.bus = &wmi_bus_type;
1442
1443 return driver_register(&driver->driver);
1444}
1445EXPORT_SYMBOL(__wmi_driver_register);
1446
1447void wmi_driver_unregister(struct wmi_driver *driver)
1448{
1449 driver_unregister(&driver->driver);
1450}
1451EXPORT_SYMBOL(wmi_driver_unregister);
1452
1453static int __init acpi_wmi_init(void)
1454{
1455 int error;
1456
1457 if (acpi_disabled)
1458 return -ENODEV;
1459
1460 error = class_register(&wmi_bus_class);
1461 if (error)
1462 return error;
1463
1464 error = bus_register(&wmi_bus_type);
1465 if (error)
1466 goto err_unreg_class;
1467
1468 error = platform_driver_register(&acpi_wmi_driver);
1469 if (error) {
1470 pr_err("Error loading mapper\n");
1471 goto err_unreg_bus;
1472 }
1473
1474 return 0;
1475
1476err_unreg_bus:
1477 bus_unregister(&wmi_bus_type);
1478
1479err_unreg_class:
1480 class_unregister(&wmi_bus_class);
1481
1482 return error;
1483}
1484
1485static void __exit acpi_wmi_exit(void)
1486{
1487 platform_driver_unregister(&acpi_wmi_driver);
1488 bus_unregister(&wmi_bus_type);
1489 class_unregister(&wmi_bus_class);
1490}
1491
1492subsys_initcall_sync(acpi_wmi_init);
1493module_exit(acpi_wmi_exit);