1348 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * ACPI-WMI mapping driver4 *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 Altaparmakov10 * 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 Lutomirski14 * Copyright (C) 2017 VMware, Inc. All Rights Reserved.15 */16 17#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt18 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/module.h>27#include <linux/platform_device.h>28#include <linux/rwsem.h>29#include <linux/slab.h>30#include <linux/sysfs.h>31#include <linux/types.h>32#include <linux/uuid.h>33#include <linux/wmi.h>34#include <linux/fs.h>35 36MODULE_AUTHOR("Carlos Corbacho");37MODULE_DESCRIPTION("ACPI-WMI Mapping Driver");38MODULE_LICENSE("GPL");39 40static LIST_HEAD(wmi_block_list);41 42struct guid_block {43 guid_t guid;44 union {45 char object_id[2];46 struct {47 unsigned char notify_id;48 unsigned char reserved;49 };50 };51 u8 instance_count;52 u8 flags;53} __packed;54static_assert(sizeof(typeof_member(struct guid_block, guid)) == 16);55static_assert(sizeof(struct guid_block) == 20);56static_assert(__alignof__(struct guid_block) == 1);57 58enum { /* wmi_block flags */59 WMI_READ_TAKES_NO_ARGS,60 WMI_GUID_DUPLICATED,61 WMI_NO_EVENT_DATA,62};63 64struct wmi_block {65 struct wmi_device dev;66 struct list_head list;67 struct guid_block gblock;68 struct acpi_device *acpi_device;69 struct rw_semaphore notify_lock; /* Protects notify callback add/remove */70 wmi_notify_handler handler;71 void *handler_data;72 bool driver_ready;73 unsigned long flags;74};75 76 77/*78 * If the GUID data block is marked as expensive, we must enable and79 * explicitily disable data collection.80 */81#define ACPI_WMI_EXPENSIVE BIT(0)82#define ACPI_WMI_METHOD BIT(1) /* GUID is a method */83#define ACPI_WMI_STRING BIT(2) /* GUID takes & returns a string */84#define ACPI_WMI_EVENT BIT(3) /* GUID is an event */85 86static const struct acpi_device_id wmi_device_ids[] = {87 {"PNP0C14", 0},88 {"pnp0c14", 0},89 { }90};91MODULE_DEVICE_TABLE(acpi, wmi_device_ids);92 93#define dev_to_wblock(__dev) container_of_const(__dev, struct wmi_block, dev.dev)94#define dev_to_wdev(__dev) container_of_const(__dev, struct wmi_device, dev)95 96/*97 * GUID parsing functions98 */99 100static bool guid_parse_and_compare(const char *string, const guid_t *guid)101{102 guid_t guid_input;103 104 if (guid_parse(string, &guid_input))105 return false;106 107 return guid_equal(&guid_input, guid);108}109 110static const void *find_guid_context(struct wmi_block *wblock,111 struct wmi_driver *wdriver)112{113 const struct wmi_device_id *id;114 115 id = wdriver->id_table;116 if (!id)117 return NULL;118 119 while (*id->guid_string) {120 if (guid_parse_and_compare(id->guid_string, &wblock->gblock.guid))121 return id->context;122 id++;123 }124 return NULL;125}126 127static acpi_status wmi_method_enable(struct wmi_block *wblock, bool enable)128{129 struct guid_block *block;130 char method[5];131 acpi_status status;132 acpi_handle handle;133 134 block = &wblock->gblock;135 handle = wblock->acpi_device->handle;136 137 snprintf(method, 5, "WE%02X", block->notify_id);138 status = acpi_execute_simple_method(handle, method, enable);139 if (status == AE_NOT_FOUND)140 return AE_OK;141 142 return status;143}144 145#define WMI_ACPI_METHOD_NAME_SIZE 5146 147static inline void get_acpi_method_name(const struct wmi_block *wblock,148 const char method,149 char buffer[static WMI_ACPI_METHOD_NAME_SIZE])150{151 static_assert(ARRAY_SIZE(wblock->gblock.object_id) == 2);152 static_assert(WMI_ACPI_METHOD_NAME_SIZE >= 5);153 154 buffer[0] = 'W';155 buffer[1] = method;156 buffer[2] = wblock->gblock.object_id[0];157 buffer[3] = wblock->gblock.object_id[1];158 buffer[4] = '\0';159}160 161static inline acpi_object_type get_param_acpi_type(const struct wmi_block *wblock)162{163 if (wblock->gblock.flags & ACPI_WMI_STRING)164 return ACPI_TYPE_STRING;165 else166 return ACPI_TYPE_BUFFER;167}168 169static int wmidev_match_guid(struct device *dev, const void *data)170{171 struct wmi_block *wblock = dev_to_wblock(dev);172 const guid_t *guid = data;173 174 /* Legacy GUID-based functions are restricted to only see175 * a single WMI device for each GUID.176 */177 if (test_bit(WMI_GUID_DUPLICATED, &wblock->flags))178 return 0;179 180 if (guid_equal(guid, &wblock->gblock.guid))181 return 1;182 183 return 0;184}185 186static const struct bus_type wmi_bus_type;187 188static struct wmi_device *wmi_find_device_by_guid(const char *guid_string)189{190 struct device *dev;191 guid_t guid;192 int ret;193 194 ret = guid_parse(guid_string, &guid);195 if (ret < 0)196 return ERR_PTR(ret);197 198 dev = bus_find_device(&wmi_bus_type, NULL, &guid, wmidev_match_guid);199 if (!dev)200 return ERR_PTR(-ENODEV);201 202 return dev_to_wdev(dev);203}204 205static void wmi_device_put(struct wmi_device *wdev)206{207 put_device(&wdev->dev);208}209 210/*211 * Exported WMI functions212 */213 214/**215 * wmi_instance_count - Get number of WMI object instances216 * @guid_string: 36 char string of the form fa50ff2b-f2e8-45de-83fa-65417f2f49ba217 *218 * Get the number of WMI object instances.219 *220 * Returns: Number of WMI object instances or negative error code.221 */222int wmi_instance_count(const char *guid_string)223{224 struct wmi_device *wdev;225 int ret;226 227 wdev = wmi_find_device_by_guid(guid_string);228 if (IS_ERR(wdev))229 return PTR_ERR(wdev);230 231 ret = wmidev_instance_count(wdev);232 wmi_device_put(wdev);233 234 return ret;235}236EXPORT_SYMBOL_GPL(wmi_instance_count);237 238/**239 * wmidev_instance_count - Get number of WMI object instances240 * @wdev: A wmi bus device from a driver241 *242 * Get the number of WMI object instances.243 *244 * Returns: Number of WMI object instances.245 */246u8 wmidev_instance_count(struct wmi_device *wdev)247{248 struct wmi_block *wblock = container_of(wdev, struct wmi_block, dev);249 250 return wblock->gblock.instance_count;251}252EXPORT_SYMBOL_GPL(wmidev_instance_count);253 254/**255 * wmi_evaluate_method - Evaluate a WMI method (deprecated)256 * @guid_string: 36 char string of the form fa50ff2b-f2e8-45de-83fa-65417f2f49ba257 * @instance: Instance index258 * @method_id: Method ID to call259 * @in: Mandatory buffer containing input for the method call260 * @out: Empty buffer to return the method results261 *262 * Call an ACPI-WMI method, the caller must free @out.263 *264 * Return: acpi_status signaling success or error.265 */266acpi_status wmi_evaluate_method(const char *guid_string, u8 instance, u32 method_id,267 const struct acpi_buffer *in, struct acpi_buffer *out)268{269 struct wmi_device *wdev;270 acpi_status status;271 272 wdev = wmi_find_device_by_guid(guid_string);273 if (IS_ERR(wdev))274 return AE_ERROR;275 276 status = wmidev_evaluate_method(wdev, instance, method_id, in, out);277 278 wmi_device_put(wdev);279 280 return status;281}282EXPORT_SYMBOL_GPL(wmi_evaluate_method);283 284/**285 * wmidev_evaluate_method - Evaluate a WMI method286 * @wdev: A wmi bus device from a driver287 * @instance: Instance index288 * @method_id: Method ID to call289 * @in: Mandatory buffer containing input for the method call290 * @out: Empty buffer to return the method results291 *292 * Call an ACPI-WMI method, the caller must free @out.293 *294 * Return: acpi_status signaling success or error.295 */296acpi_status wmidev_evaluate_method(struct wmi_device *wdev, u8 instance, u32 method_id,297 const struct acpi_buffer *in, struct acpi_buffer *out)298{299 struct guid_block *block;300 struct wmi_block *wblock;301 acpi_handle handle;302 struct acpi_object_list input;303 union acpi_object params[3];304 char method[WMI_ACPI_METHOD_NAME_SIZE];305 306 wblock = container_of(wdev, struct wmi_block, dev);307 block = &wblock->gblock;308 handle = wblock->acpi_device->handle;309 310 if (!in)311 return AE_BAD_DATA;312 313 if (!(block->flags & ACPI_WMI_METHOD))314 return AE_BAD_DATA;315 316 if (block->instance_count <= instance)317 return AE_BAD_PARAMETER;318 319 input.count = 3;320 input.pointer = params;321 322 params[0].type = ACPI_TYPE_INTEGER;323 params[0].integer.value = instance;324 params[1].type = ACPI_TYPE_INTEGER;325 params[1].integer.value = method_id;326 params[2].type = get_param_acpi_type(wblock);327 params[2].buffer.length = in->length;328 params[2].buffer.pointer = in->pointer;329 330 get_acpi_method_name(wblock, 'M', method);331 332 return acpi_evaluate_object(handle, method, &input, out);333}334EXPORT_SYMBOL_GPL(wmidev_evaluate_method);335 336static acpi_status __query_block(struct wmi_block *wblock, u8 instance,337 struct acpi_buffer *out)338{339 struct guid_block *block;340 acpi_handle handle;341 acpi_status status, wc_status = AE_ERROR;342 struct acpi_object_list input;343 union acpi_object wq_params[1];344 char wc_method[WMI_ACPI_METHOD_NAME_SIZE];345 char method[WMI_ACPI_METHOD_NAME_SIZE];346 347 if (!out)348 return AE_BAD_PARAMETER;349 350 block = &wblock->gblock;351 handle = wblock->acpi_device->handle;352 353 if (block->instance_count <= instance)354 return AE_BAD_PARAMETER;355 356 /* Check GUID is a data block */357 if (block->flags & (ACPI_WMI_EVENT | ACPI_WMI_METHOD))358 return AE_ERROR;359 360 input.count = 1;361 input.pointer = wq_params;362 wq_params[0].type = ACPI_TYPE_INTEGER;363 wq_params[0].integer.value = instance;364 365 if (instance == 0 && test_bit(WMI_READ_TAKES_NO_ARGS, &wblock->flags))366 input.count = 0;367 368 /*369 * If ACPI_WMI_EXPENSIVE, call the relevant WCxx method first to370 * enable collection.371 */372 if (block->flags & ACPI_WMI_EXPENSIVE) {373 get_acpi_method_name(wblock, 'C', wc_method);374 375 /*376 * Some GUIDs break the specification by declaring themselves377 * expensive, but have no corresponding WCxx method. So we378 * should not fail if this happens.379 */380 wc_status = acpi_execute_simple_method(handle, wc_method, 1);381 }382 383 get_acpi_method_name(wblock, 'Q', method);384 status = acpi_evaluate_object(handle, method, &input, out);385 386 /*387 * If ACPI_WMI_EXPENSIVE, call the relevant WCxx method, even if388 * the WQxx method failed - we should disable collection anyway.389 */390 if ((block->flags & ACPI_WMI_EXPENSIVE) && ACPI_SUCCESS(wc_status)) {391 /*392 * Ignore whether this WCxx call succeeds or not since393 * the previously executed WQxx method call might have394 * succeeded, and returning the failing status code395 * of this call would throw away the result of the WQxx396 * call, potentially leaking memory.397 */398 acpi_execute_simple_method(handle, wc_method, 0);399 }400 401 return status;402}403 404/**405 * wmi_query_block - Return contents of a WMI block (deprecated)406 * @guid_string: 36 char string of the form fa50ff2b-f2e8-45de-83fa-65417f2f49ba407 * @instance: Instance index408 * @out: Empty buffer to return the contents of the data block to409 *410 * Query a ACPI-WMI block, the caller must free @out.411 *412 * Return: ACPI object containing the content of the WMI block.413 */414acpi_status wmi_query_block(const char *guid_string, u8 instance,415 struct acpi_buffer *out)416{417 struct wmi_block *wblock;418 struct wmi_device *wdev;419 acpi_status status;420 421 wdev = wmi_find_device_by_guid(guid_string);422 if (IS_ERR(wdev))423 return AE_ERROR;424 425 wblock = container_of(wdev, struct wmi_block, dev);426 status = __query_block(wblock, instance, out);427 428 wmi_device_put(wdev);429 430 return status;431}432EXPORT_SYMBOL_GPL(wmi_query_block);433 434/**435 * wmidev_block_query - Return contents of a WMI block436 * @wdev: A wmi bus device from a driver437 * @instance: Instance index438 *439 * Query an ACPI-WMI block, the caller must free the result.440 *441 * Return: ACPI object containing the content of the WMI block.442 */443union acpi_object *wmidev_block_query(struct wmi_device *wdev, u8 instance)444{445 struct acpi_buffer out = { ACPI_ALLOCATE_BUFFER, NULL };446 struct wmi_block *wblock = container_of(wdev, struct wmi_block, dev);447 448 if (ACPI_FAILURE(__query_block(wblock, instance, &out)))449 return NULL;450 451 return out.pointer;452}453EXPORT_SYMBOL_GPL(wmidev_block_query);454 455/**456 * wmi_set_block - Write to a WMI block (deprecated)457 * @guid_string: 36 char string of the form fa50ff2b-f2e8-45de-83fa-65417f2f49ba458 * @instance: Instance index459 * @in: Buffer containing new values for the data block460 *461 * Write the contents of the input buffer to an ACPI-WMI data block.462 *463 * Return: acpi_status signaling success or error.464 */465acpi_status wmi_set_block(const char *guid_string, u8 instance, const struct acpi_buffer *in)466{467 struct wmi_device *wdev;468 acpi_status status;469 470 wdev = wmi_find_device_by_guid(guid_string);471 if (IS_ERR(wdev))472 return AE_ERROR;473 474 status = wmidev_block_set(wdev, instance, in);475 wmi_device_put(wdev);476 477 return status;478}479EXPORT_SYMBOL_GPL(wmi_set_block);480 481/**482 * wmidev_block_set - Write to a WMI block483 * @wdev: A wmi bus device from a driver484 * @instance: Instance index485 * @in: Buffer containing new values for the data block486 *487 * Write contents of the input buffer to an ACPI-WMI data block.488 *489 * Return: acpi_status signaling success or error.490 */491acpi_status wmidev_block_set(struct wmi_device *wdev, u8 instance, const struct acpi_buffer *in)492{493 struct wmi_block *wblock = container_of(wdev, struct wmi_block, dev);494 acpi_handle handle = wblock->acpi_device->handle;495 struct guid_block *block = &wblock->gblock;496 char method[WMI_ACPI_METHOD_NAME_SIZE];497 struct acpi_object_list input;498 union acpi_object params[2];499 500 if (!in)501 return AE_BAD_DATA;502 503 if (block->instance_count <= instance)504 return AE_BAD_PARAMETER;505 506 /* Check GUID is a data block */507 if (block->flags & (ACPI_WMI_EVENT | ACPI_WMI_METHOD))508 return AE_ERROR;509 510 input.count = 2;511 input.pointer = params;512 params[0].type = ACPI_TYPE_INTEGER;513 params[0].integer.value = instance;514 params[1].type = get_param_acpi_type(wblock);515 params[1].buffer.length = in->length;516 params[1].buffer.pointer = in->pointer;517 518 get_acpi_method_name(wblock, 'S', method);519 520 return acpi_evaluate_object(handle, method, &input, NULL);521}522EXPORT_SYMBOL_GPL(wmidev_block_set);523 524/**525 * wmi_install_notify_handler - Register handler for WMI events (deprecated)526 * @guid: 36 char string of the form fa50ff2b-f2e8-45de-83fa-65417f2f49ba527 * @handler: Function to handle notifications528 * @data: Data to be returned to handler when event is fired529 *530 * Register a handler for events sent to the ACPI-WMI mapper device.531 *532 * Return: acpi_status signaling success or error.533 */534acpi_status wmi_install_notify_handler(const char *guid,535 wmi_notify_handler handler,536 void *data)537{538 struct wmi_block *wblock;539 struct wmi_device *wdev;540 acpi_status status;541 542 wdev = wmi_find_device_by_guid(guid);543 if (IS_ERR(wdev))544 return AE_ERROR;545 546 wblock = container_of(wdev, struct wmi_block, dev);547 548 down_write(&wblock->notify_lock);549 if (wblock->handler) {550 status = AE_ALREADY_ACQUIRED;551 } else {552 wblock->handler = handler;553 wblock->handler_data = data;554 555 if (ACPI_FAILURE(wmi_method_enable(wblock, true)))556 dev_warn(&wblock->dev.dev, "Failed to enable device\n");557 558 status = AE_OK;559 }560 up_write(&wblock->notify_lock);561 562 wmi_device_put(wdev);563 564 return status;565}566EXPORT_SYMBOL_GPL(wmi_install_notify_handler);567 568/**569 * wmi_remove_notify_handler - Unregister handler for WMI events (deprecated)570 * @guid: 36 char string of the form fa50ff2b-f2e8-45de-83fa-65417f2f49ba571 *572 * Unregister handler for events sent to the ACPI-WMI mapper device.573 *574 * Return: acpi_status signaling success or error.575 */576acpi_status wmi_remove_notify_handler(const char *guid)577{578 struct wmi_block *wblock;579 struct wmi_device *wdev;580 acpi_status status;581 582 wdev = wmi_find_device_by_guid(guid);583 if (IS_ERR(wdev))584 return AE_ERROR;585 586 wblock = container_of(wdev, struct wmi_block, dev);587 588 down_write(&wblock->notify_lock);589 if (!wblock->handler) {590 status = AE_NULL_ENTRY;591 } else {592 if (ACPI_FAILURE(wmi_method_enable(wblock, false)))593 dev_warn(&wblock->dev.dev, "Failed to disable device\n");594 595 wblock->handler = NULL;596 wblock->handler_data = NULL;597 598 status = AE_OK;599 }600 up_write(&wblock->notify_lock);601 602 wmi_device_put(wdev);603 604 return status;605}606EXPORT_SYMBOL_GPL(wmi_remove_notify_handler);607 608/**609 * wmi_has_guid - Check if a GUID is available610 * @guid_string: 36 char string of the form fa50ff2b-f2e8-45de-83fa-65417f2f49ba611 *612 * Check if a given GUID is defined by _WDG.613 *614 * Return: True if GUID is available, false otherwise.615 */616bool wmi_has_guid(const char *guid_string)617{618 struct wmi_device *wdev;619 620 wdev = wmi_find_device_by_guid(guid_string);621 if (IS_ERR(wdev))622 return false;623 624 wmi_device_put(wdev);625 626 return true;627}628EXPORT_SYMBOL_GPL(wmi_has_guid);629 630/**631 * wmi_get_acpi_device_uid() - Get _UID name of ACPI device that defines GUID (deprecated)632 * @guid_string: 36 char string of the form fa50ff2b-f2e8-45de-83fa-65417f2f49ba633 *634 * Find the _UID of ACPI device associated with this WMI GUID.635 *636 * Return: The ACPI _UID field value or NULL if the WMI GUID was not found.637 */638char *wmi_get_acpi_device_uid(const char *guid_string)639{640 struct wmi_block *wblock;641 struct wmi_device *wdev;642 char *uid;643 644 wdev = wmi_find_device_by_guid(guid_string);645 if (IS_ERR(wdev))646 return NULL;647 648 wblock = container_of(wdev, struct wmi_block, dev);649 uid = acpi_device_uid(wblock->acpi_device);650 651 wmi_device_put(wdev);652 653 return uid;654}655EXPORT_SYMBOL_GPL(wmi_get_acpi_device_uid);656 657#define drv_to_wdrv(__drv) container_of_const(__drv, struct wmi_driver, driver)658 659/*660 * sysfs interface661 */662static ssize_t modalias_show(struct device *dev, struct device_attribute *attr,663 char *buf)664{665 struct wmi_block *wblock = dev_to_wblock(dev);666 667 return sysfs_emit(buf, "wmi:%pUL\n", &wblock->gblock.guid);668}669static DEVICE_ATTR_RO(modalias);670 671static ssize_t guid_show(struct device *dev, struct device_attribute *attr,672 char *buf)673{674 struct wmi_block *wblock = dev_to_wblock(dev);675 676 return sysfs_emit(buf, "%pUL\n", &wblock->gblock.guid);677}678static DEVICE_ATTR_RO(guid);679 680static ssize_t instance_count_show(struct device *dev,681 struct device_attribute *attr, char *buf)682{683 struct wmi_block *wblock = dev_to_wblock(dev);684 685 return sysfs_emit(buf, "%d\n", (int)wblock->gblock.instance_count);686}687static DEVICE_ATTR_RO(instance_count);688 689static ssize_t expensive_show(struct device *dev,690 struct device_attribute *attr, char *buf)691{692 struct wmi_block *wblock = dev_to_wblock(dev);693 694 return sysfs_emit(buf, "%d\n",695 (wblock->gblock.flags & ACPI_WMI_EXPENSIVE) != 0);696}697static DEVICE_ATTR_RO(expensive);698 699static ssize_t driver_override_show(struct device *dev, struct device_attribute *attr,700 char *buf)701{702 struct wmi_device *wdev = to_wmi_device(dev);703 ssize_t ret;704 705 device_lock(dev);706 ret = sysfs_emit(buf, "%s\n", wdev->driver_override);707 device_unlock(dev);708 709 return ret;710}711 712static ssize_t driver_override_store(struct device *dev, struct device_attribute *attr,713 const char *buf, size_t count)714{715 struct wmi_device *wdev = to_wmi_device(dev);716 int ret;717 718 ret = driver_set_override(dev, &wdev->driver_override, buf, count);719 if (ret < 0)720 return ret;721 722 return count;723}724static DEVICE_ATTR_RW(driver_override);725 726static struct attribute *wmi_attrs[] = {727 &dev_attr_modalias.attr,728 &dev_attr_guid.attr,729 &dev_attr_instance_count.attr,730 &dev_attr_expensive.attr,731 &dev_attr_driver_override.attr,732 NULL733};734ATTRIBUTE_GROUPS(wmi);735 736static ssize_t notify_id_show(struct device *dev, struct device_attribute *attr,737 char *buf)738{739 struct wmi_block *wblock = dev_to_wblock(dev);740 741 return sysfs_emit(buf, "%02X\n", (unsigned int)wblock->gblock.notify_id);742}743static DEVICE_ATTR_RO(notify_id);744 745static struct attribute *wmi_event_attrs[] = {746 &dev_attr_notify_id.attr,747 NULL748};749ATTRIBUTE_GROUPS(wmi_event);750 751static ssize_t object_id_show(struct device *dev, struct device_attribute *attr,752 char *buf)753{754 struct wmi_block *wblock = dev_to_wblock(dev);755 756 return sysfs_emit(buf, "%c%c\n", wblock->gblock.object_id[0],757 wblock->gblock.object_id[1]);758}759static DEVICE_ATTR_RO(object_id);760 761static ssize_t setable_show(struct device *dev, struct device_attribute *attr,762 char *buf)763{764 struct wmi_device *wdev = dev_to_wdev(dev);765 766 return sysfs_emit(buf, "%d\n", (int)wdev->setable);767}768static DEVICE_ATTR_RO(setable);769 770static struct attribute *wmi_data_attrs[] = {771 &dev_attr_object_id.attr,772 &dev_attr_setable.attr,773 NULL774};775ATTRIBUTE_GROUPS(wmi_data);776 777static struct attribute *wmi_method_attrs[] = {778 &dev_attr_object_id.attr,779 NULL780};781ATTRIBUTE_GROUPS(wmi_method);782 783static int wmi_dev_uevent(const struct device *dev, struct kobj_uevent_env *env)784{785 const struct wmi_block *wblock = dev_to_wblock(dev);786 787 if (add_uevent_var(env, "MODALIAS=wmi:%pUL", &wblock->gblock.guid))788 return -ENOMEM;789 790 if (add_uevent_var(env, "WMI_GUID=%pUL", &wblock->gblock.guid))791 return -ENOMEM;792 793 return 0;794}795 796static void wmi_dev_release(struct device *dev)797{798 struct wmi_block *wblock = dev_to_wblock(dev);799 800 kfree(wblock->dev.driver_override);801 kfree(wblock);802}803 804static int wmi_dev_match(struct device *dev, const struct device_driver *driver)805{806 const struct wmi_driver *wmi_driver = drv_to_wdrv(driver);807 struct wmi_block *wblock = dev_to_wblock(dev);808 const struct wmi_device_id *id = wmi_driver->id_table;809 810 /* When driver_override is set, only bind to the matching driver */811 if (wblock->dev.driver_override)812 return !strcmp(wblock->dev.driver_override, driver->name);813 814 if (id == NULL)815 return 0;816 817 while (*id->guid_string) {818 if (guid_parse_and_compare(id->guid_string, &wblock->gblock.guid))819 return 1;820 821 id++;822 }823 824 return 0;825}826 827static int wmi_dev_probe(struct device *dev)828{829 struct wmi_block *wblock = dev_to_wblock(dev);830 struct wmi_driver *wdriver = drv_to_wdrv(dev->driver);831 int ret = 0;832 833 /* Some older WMI drivers will break if instantiated multiple times,834 * so they are blocked from probing WMI devices with a duplicated GUID.835 *836 * New WMI drivers should support being instantiated multiple times.837 */838 if (test_bit(WMI_GUID_DUPLICATED, &wblock->flags) && !wdriver->no_singleton) {839 dev_warn(dev, "Legacy driver %s cannot be instantiated multiple times\n",840 dev->driver->name);841 842 return -ENODEV;843 }844 845 if (wdriver->notify) {846 if (test_bit(WMI_NO_EVENT_DATA, &wblock->flags) && !wdriver->no_notify_data)847 return -ENODEV;848 }849 850 if (ACPI_FAILURE(wmi_method_enable(wblock, true)))851 dev_warn(dev, "failed to enable device -- probing anyway\n");852 853 if (wdriver->probe) {854 ret = wdriver->probe(dev_to_wdev(dev),855 find_guid_context(wblock, wdriver));856 if (ret) {857 if (ACPI_FAILURE(wmi_method_enable(wblock, false)))858 dev_warn(dev, "Failed to disable device\n");859 860 return ret;861 }862 }863 864 down_write(&wblock->notify_lock);865 wblock->driver_ready = true;866 up_write(&wblock->notify_lock);867 868 return 0;869}870 871static void wmi_dev_remove(struct device *dev)872{873 struct wmi_block *wblock = dev_to_wblock(dev);874 struct wmi_driver *wdriver = drv_to_wdrv(dev->driver);875 876 down_write(&wblock->notify_lock);877 wblock->driver_ready = false;878 up_write(&wblock->notify_lock);879 880 if (wdriver->remove)881 wdriver->remove(dev_to_wdev(dev));882 883 if (ACPI_FAILURE(wmi_method_enable(wblock, false)))884 dev_warn(dev, "failed to disable device\n");885}886 887static struct class wmi_bus_class = {888 .name = "wmi_bus",889};890 891static const struct bus_type wmi_bus_type = {892 .name = "wmi",893 .dev_groups = wmi_groups,894 .match = wmi_dev_match,895 .uevent = wmi_dev_uevent,896 .probe = wmi_dev_probe,897 .remove = wmi_dev_remove,898};899 900static const struct device_type wmi_type_event = {901 .name = "event",902 .groups = wmi_event_groups,903 .release = wmi_dev_release,904};905 906static const struct device_type wmi_type_method = {907 .name = "method",908 .groups = wmi_method_groups,909 .release = wmi_dev_release,910};911 912static const struct device_type wmi_type_data = {913 .name = "data",914 .groups = wmi_data_groups,915 .release = wmi_dev_release,916};917 918/*919 * _WDG is a static list that is only parsed at startup,920 * so it's safe to count entries without extra protection.921 */922static int guid_count(const guid_t *guid)923{924 struct wmi_block *wblock;925 int count = 0;926 927 list_for_each_entry(wblock, &wmi_block_list, list) {928 if (guid_equal(&wblock->gblock.guid, guid))929 count++;930 }931 932 return count;933}934 935static int wmi_create_device(struct device *wmi_bus_dev,936 struct wmi_block *wblock,937 struct acpi_device *device)938{939 char method[WMI_ACPI_METHOD_NAME_SIZE];940 struct acpi_device_info *info;941 acpi_handle method_handle;942 acpi_status status;943 uint count;944 945 if (wblock->gblock.flags & ACPI_WMI_EVENT) {946 wblock->dev.dev.type = &wmi_type_event;947 goto out_init;948 }949 950 if (wblock->gblock.flags & ACPI_WMI_METHOD) {951 get_acpi_method_name(wblock, 'M', method);952 if (!acpi_has_method(device->handle, method)) {953 dev_warn(wmi_bus_dev,954 FW_BUG "%s method block execution control method not found\n",955 method);956 957 return -ENXIO;958 }959 960 wblock->dev.dev.type = &wmi_type_method;961 goto out_init;962 }963 964 /*965 * Data Block Query Control Method (WQxx by convention) is966 * required per the WMI documentation. If it is not present,967 * we ignore this data block.968 */969 get_acpi_method_name(wblock, 'Q', method);970 status = acpi_get_handle(device->handle, method, &method_handle);971 if (ACPI_FAILURE(status)) {972 dev_warn(wmi_bus_dev,973 FW_BUG "%s data block query control method not found\n",974 method);975 976 return -ENXIO;977 }978 979 status = acpi_get_object_info(method_handle, &info);980 if (ACPI_FAILURE(status))981 return -EIO;982 983 wblock->dev.dev.type = &wmi_type_data;984 985 /*986 * The Microsoft documentation specifically states:987 *988 * Data blocks registered with only a single instance989 * can ignore the parameter.990 *991 * ACPICA will get mad at us if we call the method with the wrong number992 * of arguments, so check what our method expects. (On some Dell993 * laptops, WQxx may not be a method at all.)994 */995 if (info->type != ACPI_TYPE_METHOD || info->param_count == 0)996 set_bit(WMI_READ_TAKES_NO_ARGS, &wblock->flags);997 998 kfree(info);999 1000 get_acpi_method_name(wblock, 'S', method);1001 if (acpi_has_method(device->handle, method))1002 wblock->dev.setable = true;1003 1004 out_init:1005 init_rwsem(&wblock->notify_lock);1006 wblock->driver_ready = false;1007 wblock->dev.dev.bus = &wmi_bus_type;1008 wblock->dev.dev.parent = wmi_bus_dev;1009 1010 count = guid_count(&wblock->gblock.guid);1011 if (count) {1012 dev_set_name(&wblock->dev.dev, "%pUL-%d", &wblock->gblock.guid, count);1013 set_bit(WMI_GUID_DUPLICATED, &wblock->flags);1014 } else {1015 dev_set_name(&wblock->dev.dev, "%pUL", &wblock->gblock.guid);1016 }1017 1018 device_initialize(&wblock->dev.dev);1019 1020 return 0;1021}1022 1023static int wmi_add_device(struct platform_device *pdev, struct wmi_device *wdev)1024{1025 struct device_link *link;1026 1027 /*1028 * Many aggregate WMI drivers do not use -EPROBE_DEFER when they1029 * are unable to find a WMI device during probe, instead they require1030 * all WMI devices associated with an platform device to become available1031 * at once. This device link thus prevents WMI drivers from probing until1032 * the associated platform device has finished probing (and has registered1033 * all discovered WMI devices).1034 */1035 1036 link = device_link_add(&wdev->dev, &pdev->dev, DL_FLAG_AUTOREMOVE_SUPPLIER);1037 if (!link)1038 return -EINVAL;1039 1040 return device_add(&wdev->dev);1041}1042 1043/*1044 * Parse the _WDG method for the GUID data blocks1045 */1046static int parse_wdg(struct device *wmi_bus_dev, struct platform_device *pdev)1047{1048 struct acpi_device *device = ACPI_COMPANION(&pdev->dev);1049 struct acpi_buffer out = {ACPI_ALLOCATE_BUFFER, NULL};1050 const struct guid_block *gblock;1051 bool event_data_available;1052 struct wmi_block *wblock;1053 union acpi_object *obj;1054 acpi_status status;1055 u32 i, total;1056 int retval;1057 1058 status = acpi_evaluate_object(device->handle, "_WDG", NULL, &out);1059 if (ACPI_FAILURE(status))1060 return -ENXIO;1061 1062 obj = out.pointer;1063 if (!obj)1064 return -ENXIO;1065 1066 if (obj->type != ACPI_TYPE_BUFFER) {1067 kfree(obj);1068 return -ENXIO;1069 }1070 1071 event_data_available = acpi_has_method(device->handle, "_WED");1072 gblock = (const struct guid_block *)obj->buffer.pointer;1073 total = obj->buffer.length / sizeof(struct guid_block);1074 1075 for (i = 0; i < total; i++) {1076 if (!gblock[i].instance_count) {1077 dev_info(wmi_bus_dev, FW_INFO "%pUL has zero instances\n", &gblock[i].guid);1078 continue;1079 }1080 1081 wblock = kzalloc(sizeof(*wblock), GFP_KERNEL);1082 if (!wblock)1083 continue;1084 1085 wblock->acpi_device = device;1086 wblock->gblock = gblock[i];1087 if (gblock[i].flags & ACPI_WMI_EVENT && !event_data_available)1088 set_bit(WMI_NO_EVENT_DATA, &wblock->flags);1089 1090 retval = wmi_create_device(wmi_bus_dev, wblock, device);1091 if (retval) {1092 kfree(wblock);1093 continue;1094 }1095 1096 list_add_tail(&wblock->list, &wmi_block_list);1097 1098 retval = wmi_add_device(pdev, &wblock->dev);1099 if (retval) {1100 dev_err(wmi_bus_dev, "failed to register %pUL\n",1101 &wblock->gblock.guid);1102 1103 list_del(&wblock->list);1104 put_device(&wblock->dev.dev);1105 }1106 }1107 1108 kfree(obj);1109 1110 return 0;1111}1112 1113static int wmi_get_notify_data(struct wmi_block *wblock, union acpi_object **obj)1114{1115 struct acpi_buffer data = { ACPI_ALLOCATE_BUFFER, NULL };1116 union acpi_object param = {1117 .integer = {1118 .type = ACPI_TYPE_INTEGER,1119 .value = wblock->gblock.notify_id,1120 }1121 };1122 struct acpi_object_list input = {1123 .count = 1,1124 .pointer = ¶m,1125 };1126 acpi_status status;1127 1128 status = acpi_evaluate_object(wblock->acpi_device->handle, "_WED", &input, &data);1129 if (ACPI_FAILURE(status)) {1130 dev_warn(&wblock->dev.dev, "Failed to get event data\n");1131 return -EIO;1132 }1133 1134 *obj = data.pointer;1135 1136 return 0;1137}1138 1139static void wmi_notify_driver(struct wmi_block *wblock, union acpi_object *obj)1140{1141 struct wmi_driver *driver = drv_to_wdrv(wblock->dev.dev.driver);1142 1143 if (!obj && !driver->no_notify_data) {1144 dev_warn(&wblock->dev.dev, "Event contains no event data\n");1145 return;1146 }1147 1148 if (driver->notify)1149 driver->notify(&wblock->dev, obj);1150}1151 1152static int wmi_notify_device(struct device *dev, void *data)1153{1154 struct wmi_block *wblock = dev_to_wblock(dev);1155 union acpi_object *obj = NULL;1156 u32 *event = data;1157 int ret;1158 1159 if (!(wblock->gblock.flags & ACPI_WMI_EVENT && wblock->gblock.notify_id == *event))1160 return 0;1161 1162 /* The ACPI WMI specification says that _WED should be1163 * evaluated every time an notification is received, even1164 * if no consumers are present.1165 *1166 * Some firmware implementations actually depend on this1167 * by using a queue for events which will fill up if the1168 * WMI driver core stops evaluating _WED due to missing1169 * WMI event consumers.1170 */1171 if (!test_bit(WMI_NO_EVENT_DATA, &wblock->flags)) {1172 ret = wmi_get_notify_data(wblock, &obj);1173 if (ret < 0)1174 return -EIO;1175 }1176 1177 down_read(&wblock->notify_lock);1178 1179 if (wblock->dev.dev.driver && wblock->driver_ready)1180 wmi_notify_driver(wblock, obj);1181 1182 if (wblock->handler)1183 wblock->handler(obj, wblock->handler_data);1184 1185 up_read(&wblock->notify_lock);1186 1187 kfree(obj);1188 1189 acpi_bus_generate_netlink_event("wmi", acpi_dev_name(wblock->acpi_device), *event, 0);1190 1191 return -EBUSY;1192}1193 1194static void acpi_wmi_notify_handler(acpi_handle handle, u32 event, void *context)1195{1196 struct device *wmi_bus_dev = context;1197 1198 device_for_each_child(wmi_bus_dev, &event, wmi_notify_device);1199}1200 1201static int wmi_remove_device(struct device *dev, void *data)1202{1203 struct wmi_block *wblock = dev_to_wblock(dev);1204 1205 list_del(&wblock->list);1206 device_unregister(dev);1207 1208 return 0;1209}1210 1211static void acpi_wmi_remove(struct platform_device *device)1212{1213 struct device *wmi_bus_device = dev_get_drvdata(&device->dev);1214 1215 device_for_each_child_reverse(wmi_bus_device, NULL, wmi_remove_device);1216}1217 1218static void acpi_wmi_remove_notify_handler(void *data)1219{1220 struct acpi_device *acpi_device = data;1221 1222 acpi_remove_notify_handler(acpi_device->handle, ACPI_ALL_NOTIFY, acpi_wmi_notify_handler);1223}1224 1225static void acpi_wmi_remove_bus_device(void *data)1226{1227 struct device *wmi_bus_dev = data;1228 1229 device_unregister(wmi_bus_dev);1230}1231 1232static int acpi_wmi_probe(struct platform_device *device)1233{1234 struct acpi_device *acpi_device;1235 struct device *wmi_bus_dev;1236 acpi_status status;1237 int error;1238 1239 acpi_device = ACPI_COMPANION(&device->dev);1240 if (!acpi_device) {1241 dev_err(&device->dev, "ACPI companion is missing\n");1242 return -ENODEV;1243 }1244 1245 wmi_bus_dev = device_create(&wmi_bus_class, &device->dev, MKDEV(0, 0), NULL, "wmi_bus-%s",1246 dev_name(&device->dev));1247 if (IS_ERR(wmi_bus_dev))1248 return PTR_ERR(wmi_bus_dev);1249 1250 error = devm_add_action_or_reset(&device->dev, acpi_wmi_remove_bus_device, wmi_bus_dev);1251 if (error < 0)1252 return error;1253 1254 dev_set_drvdata(&device->dev, wmi_bus_dev);1255 1256 status = acpi_install_notify_handler(acpi_device->handle, ACPI_ALL_NOTIFY,1257 acpi_wmi_notify_handler, wmi_bus_dev);1258 if (ACPI_FAILURE(status)) {1259 dev_err(&device->dev, "Error installing notify handler\n");1260 return -ENODEV;1261 }1262 error = devm_add_action_or_reset(&device->dev, acpi_wmi_remove_notify_handler,1263 acpi_device);1264 if (error < 0)1265 return error;1266 1267 error = parse_wdg(wmi_bus_dev, device);1268 if (error) {1269 dev_err(&device->dev, "Failed to parse _WDG method\n");1270 return error;1271 }1272 1273 return 0;1274}1275 1276int __must_check __wmi_driver_register(struct wmi_driver *driver,1277 struct module *owner)1278{1279 driver->driver.owner = owner;1280 driver->driver.bus = &wmi_bus_type;1281 1282 return driver_register(&driver->driver);1283}1284EXPORT_SYMBOL(__wmi_driver_register);1285 1286/**1287 * wmi_driver_unregister() - Unregister a WMI driver1288 * @driver: WMI driver to unregister1289 *1290 * Unregisters a WMI driver from the WMI bus.1291 */1292void wmi_driver_unregister(struct wmi_driver *driver)1293{1294 driver_unregister(&driver->driver);1295}1296EXPORT_SYMBOL(wmi_driver_unregister);1297 1298static struct platform_driver acpi_wmi_driver = {1299 .driver = {1300 .name = "acpi-wmi",1301 .acpi_match_table = wmi_device_ids,1302 },1303 .probe = acpi_wmi_probe,1304 .remove_new = acpi_wmi_remove,1305};1306 1307static int __init acpi_wmi_init(void)1308{1309 int error;1310 1311 if (acpi_disabled)1312 return -ENODEV;1313 1314 error = class_register(&wmi_bus_class);1315 if (error)1316 return error;1317 1318 error = bus_register(&wmi_bus_type);1319 if (error)1320 goto err_unreg_class;1321 1322 error = platform_driver_register(&acpi_wmi_driver);1323 if (error) {1324 pr_err("Error loading mapper\n");1325 goto err_unreg_bus;1326 }1327 1328 return 0;1329 1330err_unreg_bus:1331 bus_unregister(&wmi_bus_type);1332 1333err_unreg_class:1334 class_unregister(&wmi_bus_class);1335 1336 return error;1337}1338 1339static void __exit acpi_wmi_exit(void)1340{1341 platform_driver_unregister(&acpi_wmi_driver);1342 bus_unregister(&wmi_bus_type);1343 class_unregister(&wmi_bus_class);1344}1345 1346subsys_initcall_sync(acpi_wmi_init);1347module_exit(acpi_wmi_exit);1348