.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
---|
1 | 2 | /* |
---|
2 | 3 | * ACPI-WMI mapping driver |
---|
3 | 4 | * |
---|
.. | .. |
---|
11 | 12 | * WMI bus infrastructure by Andrew Lutomirski and Darren Hart: |
---|
12 | 13 | * Copyright (C) 2015 Andrew Lutomirski |
---|
13 | 14 | * Copyright (C) 2017 VMware, Inc. All Rights Reserved. |
---|
14 | | - * |
---|
15 | | - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
---|
16 | | - * |
---|
17 | | - * This program is free software; you can redistribute it and/or modify |
---|
18 | | - * it under the terms of the GNU General Public License as published by |
---|
19 | | - * the Free Software Foundation; either version 2 of the License, or (at |
---|
20 | | - * your option) any later version. |
---|
21 | | - * |
---|
22 | | - * This program is distributed in the hope that it will be useful, but |
---|
23 | | - * WITHOUT ANY WARRANTY; without even the implied warranty of |
---|
24 | | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
---|
25 | | - * General Public License for more details. |
---|
26 | | - * |
---|
27 | | - * You should have received a copy of the GNU General Public License along |
---|
28 | | - * with this program; if not, write to the Free Software Foundation, Inc., |
---|
29 | | - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. |
---|
30 | | - * |
---|
31 | | - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
---|
32 | 15 | */ |
---|
33 | 16 | |
---|
34 | 17 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt |
---|
.. | .. |
---|
46 | 29 | #include <linux/uaccess.h> |
---|
47 | 30 | #include <linux/uuid.h> |
---|
48 | 31 | #include <linux/wmi.h> |
---|
| 32 | +#include <linux/fs.h> |
---|
49 | 33 | #include <uapi/linux/wmi.h> |
---|
50 | 34 | |
---|
51 | 35 | ACPI_MODULE_NAME("wmi"); |
---|
.. | .. |
---|
127 | 111 | |
---|
128 | 112 | static bool find_guid(const char *guid_string, struct wmi_block **out) |
---|
129 | 113 | { |
---|
130 | | - uuid_le guid_input; |
---|
| 114 | + guid_t guid_input; |
---|
131 | 115 | struct wmi_block *wblock; |
---|
132 | 116 | struct guid_block *block; |
---|
133 | 117 | |
---|
134 | | - if (uuid_le_to_bin(guid_string, &guid_input)) |
---|
| 118 | + if (guid_parse(guid_string, &guid_input)) |
---|
135 | 119 | return false; |
---|
136 | 120 | |
---|
137 | 121 | list_for_each_entry(wblock, &wmi_block_list, list) { |
---|
.. | .. |
---|
144 | 128 | } |
---|
145 | 129 | } |
---|
146 | 130 | return false; |
---|
| 131 | +} |
---|
| 132 | + |
---|
| 133 | +static const void *find_guid_context(struct wmi_block *wblock, |
---|
| 134 | + struct wmi_driver *wdriver) |
---|
| 135 | +{ |
---|
| 136 | + const struct wmi_device_id *id; |
---|
| 137 | + guid_t guid_input; |
---|
| 138 | + |
---|
| 139 | + if (wblock == NULL || wdriver == NULL) |
---|
| 140 | + return NULL; |
---|
| 141 | + if (wdriver->id_table == NULL) |
---|
| 142 | + return NULL; |
---|
| 143 | + |
---|
| 144 | + id = wdriver->id_table; |
---|
| 145 | + while (*id->guid_string) { |
---|
| 146 | + if (guid_parse(id->guid_string, &guid_input)) |
---|
| 147 | + continue; |
---|
| 148 | + if (!memcmp(wblock->gblock.guid, &guid_input, 16)) |
---|
| 149 | + return id->context; |
---|
| 150 | + id++; |
---|
| 151 | + } |
---|
| 152 | + return NULL; |
---|
147 | 153 | } |
---|
148 | 154 | |
---|
149 | 155 | static int get_subobj_info(acpi_handle handle, const char *pathname, |
---|
.. | .. |
---|
196 | 202 | /** |
---|
197 | 203 | * set_required_buffer_size - Sets the buffer size needed for performing IOCTL |
---|
198 | 204 | * @wdev: A wmi bus device from a driver |
---|
199 | | - * @instance: Instance index |
---|
| 205 | + * @length: Required buffer size |
---|
200 | 206 | * |
---|
201 | 207 | * Allocates memory needed for buffer, stores the buffer size in that memory |
---|
202 | 208 | */ |
---|
.. | .. |
---|
216 | 222 | * @guid_string: 36 char string of the form fa50ff2b-f2e8-45de-83fa-65417f2f49ba |
---|
217 | 223 | * @instance: Instance index |
---|
218 | 224 | * @method_id: Method ID to call |
---|
219 | | - * &in: Buffer containing input for the method call |
---|
220 | | - * &out: Empty buffer to return the method results |
---|
| 225 | + * @in: Buffer containing input for the method call |
---|
| 226 | + * @out: Empty buffer to return the method results |
---|
221 | 227 | * |
---|
222 | 228 | * Call an ACPI-WMI method |
---|
223 | 229 | */ |
---|
.. | .. |
---|
238 | 244 | * @wdev: A wmi bus device from a driver |
---|
239 | 245 | * @instance: Instance index |
---|
240 | 246 | * @method_id: Method ID to call |
---|
241 | | - * &in: Buffer containing input for the method call |
---|
242 | | - * &out: Empty buffer to return the method results |
---|
| 247 | + * @in: Buffer containing input for the method call |
---|
| 248 | + * @out: Empty buffer to return the method results |
---|
243 | 249 | * |
---|
244 | 250 | * Call an ACPI-WMI method |
---|
245 | 251 | */ |
---|
.. | .. |
---|
335 | 341 | * expensive, but have no corresponding WCxx method. So we |
---|
336 | 342 | * should not fail if this happens. |
---|
337 | 343 | */ |
---|
338 | | - if (acpi_has_method(handle, wc_method)) |
---|
339 | | - wc_status = acpi_execute_simple_method(handle, |
---|
340 | | - wc_method, 1); |
---|
| 344 | + wc_status = acpi_execute_simple_method(handle, wc_method, 1); |
---|
341 | 345 | } |
---|
342 | 346 | |
---|
343 | 347 | strcpy(method, "WQ"); |
---|
.. | .. |
---|
367 | 371 | * wmi_query_block - Return contents of a WMI block (deprecated) |
---|
368 | 372 | * @guid_string: 36 char string of the form fa50ff2b-f2e8-45de-83fa-65417f2f49ba |
---|
369 | 373 | * @instance: Instance index |
---|
370 | | - * &out: Empty buffer to return the contents of the data block to |
---|
| 374 | + * @out: Empty buffer to return the contents of the data block to |
---|
371 | 375 | * |
---|
372 | 376 | * Return the contents of an ACPI-WMI data block to a buffer |
---|
373 | 377 | */ |
---|
.. | .. |
---|
402 | 406 | * wmi_set_block - Write to a WMI block |
---|
403 | 407 | * @guid_string: 36 char string of the form fa50ff2b-f2e8-45de-83fa-65417f2f49ba |
---|
404 | 408 | * @instance: Instance index |
---|
405 | | - * &in: Buffer containing new values for the data block |
---|
| 409 | + * @in: Buffer containing new values for the data block |
---|
406 | 410 | * |
---|
407 | 411 | * Write the contents of the input buffer to an ACPI-WMI data block |
---|
408 | 412 | */ |
---|
.. | .. |
---|
513 | 517 | |
---|
514 | 518 | /** |
---|
515 | 519 | * wmi_install_notify_handler - Register handler for WMI events |
---|
| 520 | + * @guid: 36 char string of the form fa50ff2b-f2e8-45de-83fa-65417f2f49ba |
---|
516 | 521 | * @handler: Function to handle notifications |
---|
517 | 522 | * @data: Data to be returned to handler when event is fired |
---|
518 | 523 | * |
---|
.. | .. |
---|
523 | 528 | { |
---|
524 | 529 | struct wmi_block *block; |
---|
525 | 530 | acpi_status status = AE_NOT_EXIST; |
---|
526 | | - uuid_le guid_input; |
---|
| 531 | + guid_t guid_input; |
---|
527 | 532 | |
---|
528 | 533 | if (!guid || !handler) |
---|
529 | 534 | return AE_BAD_PARAMETER; |
---|
530 | 535 | |
---|
531 | | - if (uuid_le_to_bin(guid, &guid_input)) |
---|
| 536 | + if (guid_parse(guid, &guid_input)) |
---|
532 | 537 | return AE_BAD_PARAMETER; |
---|
533 | 538 | |
---|
534 | 539 | list_for_each_entry(block, &wmi_block_list, list) { |
---|
.. | .. |
---|
555 | 560 | |
---|
556 | 561 | /** |
---|
557 | 562 | * wmi_uninstall_notify_handler - Unregister handler for WMI events |
---|
| 563 | + * @guid: 36 char string of the form fa50ff2b-f2e8-45de-83fa-65417f2f49ba |
---|
558 | 564 | * |
---|
559 | 565 | * Unregister handler for events sent to the ACPI-WMI mapper device. |
---|
560 | 566 | */ |
---|
.. | .. |
---|
562 | 568 | { |
---|
563 | 569 | struct wmi_block *block; |
---|
564 | 570 | acpi_status status = AE_NOT_EXIST; |
---|
565 | | - uuid_le guid_input; |
---|
| 571 | + guid_t guid_input; |
---|
566 | 572 | |
---|
567 | 573 | if (!guid) |
---|
568 | 574 | return AE_BAD_PARAMETER; |
---|
569 | 575 | |
---|
570 | | - if (uuid_le_to_bin(guid, &guid_input)) |
---|
| 576 | + if (guid_parse(guid, &guid_input)) |
---|
571 | 577 | return AE_BAD_PARAMETER; |
---|
572 | 578 | |
---|
573 | 579 | list_for_each_entry(block, &wmi_block_list, list) { |
---|
.. | .. |
---|
641 | 647 | return find_guid(guid_string, NULL); |
---|
642 | 648 | } |
---|
643 | 649 | EXPORT_SYMBOL_GPL(wmi_has_guid); |
---|
| 650 | + |
---|
| 651 | +/** |
---|
| 652 | + * wmi_get_acpi_device_uid() - Get _UID name of ACPI device that defines GUID |
---|
| 653 | + * @guid_string: 36 char string of the form fa50ff2b-f2e8-45de-83fa-65417f2f49ba |
---|
| 654 | + * |
---|
| 655 | + * Find the _UID of ACPI device associated with this WMI GUID. |
---|
| 656 | + * |
---|
| 657 | + * Return: The ACPI _UID field value or NULL if the WMI GUID was not found |
---|
| 658 | + */ |
---|
| 659 | +char *wmi_get_acpi_device_uid(const char *guid_string) |
---|
| 660 | +{ |
---|
| 661 | + struct wmi_block *wblock = NULL; |
---|
| 662 | + |
---|
| 663 | + if (!find_guid(guid_string, &wblock)) |
---|
| 664 | + return NULL; |
---|
| 665 | + |
---|
| 666 | + return acpi_device_uid(wblock->acpi_device); |
---|
| 667 | +} |
---|
| 668 | +EXPORT_SYMBOL_GPL(wmi_get_acpi_device_uid); |
---|
644 | 669 | |
---|
645 | 670 | static struct wmi_block *dev_to_wblock(struct device *dev) |
---|
646 | 671 | { |
---|
.. | .. |
---|
778 | 803 | if (id == NULL) |
---|
779 | 804 | return 0; |
---|
780 | 805 | |
---|
781 | | - while (id->guid_string) { |
---|
782 | | - uuid_le driver_guid; |
---|
| 806 | + while (*id->guid_string) { |
---|
| 807 | + guid_t driver_guid; |
---|
783 | 808 | |
---|
784 | | - if (WARN_ON(uuid_le_to_bin(id->guid_string, &driver_guid))) |
---|
| 809 | + if (WARN_ON(guid_parse(id->guid_string, &driver_guid))) |
---|
785 | 810 | continue; |
---|
786 | 811 | if (!memcmp(&driver_guid, wblock->gblock.guid, 16)) |
---|
787 | 812 | return 1; |
---|
.. | .. |
---|
896 | 921 | .read = wmi_char_read, |
---|
897 | 922 | .open = wmi_char_open, |
---|
898 | 923 | .unlocked_ioctl = wmi_ioctl, |
---|
899 | | - .compat_ioctl = wmi_ioctl, |
---|
| 924 | + .compat_ioctl = compat_ptr_ioctl, |
---|
900 | 925 | }; |
---|
901 | 926 | |
---|
902 | 927 | static int wmi_dev_probe(struct device *dev) |
---|
.. | .. |
---|
911 | 936 | dev_warn(dev, "failed to enable device -- probing anyway\n"); |
---|
912 | 937 | |
---|
913 | 938 | if (wdriver->probe) { |
---|
914 | | - ret = wdriver->probe(dev_to_wdev(dev)); |
---|
| 939 | + ret = wdriver->probe(dev_to_wdev(dev), |
---|
| 940 | + find_guid_context(wblock, wdriver)); |
---|
915 | 941 | if (ret != 0) |
---|
916 | 942 | goto probe_failure; |
---|
917 | 943 | } |
---|
.. | .. |
---|
997 | 1023 | .remove = wmi_dev_remove, |
---|
998 | 1024 | }; |
---|
999 | 1025 | |
---|
1000 | | -static struct device_type wmi_type_event = { |
---|
| 1026 | +static const struct device_type wmi_type_event = { |
---|
1001 | 1027 | .name = "event", |
---|
1002 | 1028 | .groups = wmi_event_groups, |
---|
1003 | 1029 | .release = wmi_dev_release, |
---|
1004 | 1030 | }; |
---|
1005 | 1031 | |
---|
1006 | | -static struct device_type wmi_type_method = { |
---|
| 1032 | +static const struct device_type wmi_type_method = { |
---|
1007 | 1033 | .name = "method", |
---|
1008 | 1034 | .groups = wmi_method_groups, |
---|
1009 | 1035 | .release = wmi_dev_release, |
---|
1010 | 1036 | }; |
---|
1011 | 1037 | |
---|
1012 | | -static struct device_type wmi_type_data = { |
---|
| 1038 | +static const struct device_type wmi_type_data = { |
---|
1013 | 1039 | .name = "data", |
---|
1014 | 1040 | .groups = wmi_data_groups, |
---|
1015 | 1041 | .release = wmi_dev_release, |
---|
.. | .. |
---|
1099 | 1125 | } |
---|
1100 | 1126 | } |
---|
1101 | 1127 | |
---|
1102 | | -static bool guid_already_parsed(struct acpi_device *device, |
---|
1103 | | - const u8 *guid) |
---|
| 1128 | +static bool guid_already_parsed(struct acpi_device *device, const u8 *guid) |
---|
1104 | 1129 | { |
---|
1105 | 1130 | struct wmi_block *wblock; |
---|
1106 | 1131 | |
---|
.. | .. |
---|
1310 | 1335 | wblock->handler(event, wblock->handler_data); |
---|
1311 | 1336 | } |
---|
1312 | 1337 | |
---|
1313 | | - if (debug_event) { |
---|
1314 | | - pr_info("DEBUG Event GUID: %pUL\n", |
---|
1315 | | - wblock->gblock.guid); |
---|
1316 | | - } |
---|
| 1338 | + if (debug_event) |
---|
| 1339 | + pr_info("DEBUG Event GUID: %pUL\n", wblock->gblock.guid); |
---|
1317 | 1340 | |
---|
1318 | 1341 | acpi_bus_generate_netlink_event( |
---|
1319 | 1342 | wblock->acpi_device->pnp.device_class, |
---|