wmi.c (df46426745ac58618c822ce3f93d2bb25b9a5060) wmi.c (73f0f2b52c5ea67b3140b23f58d8079d158839c8)
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>

--- 6 unchanged lines hidden (view full) ---

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>
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>

--- 6 unchanged lines hidden (view full) ---

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/idr.h>
23#include <linux/init.h>
24#include <linux/kernel.h>
25#include <linux/module.h>
26#include <linux/platform_device.h>
27#include <linux/rwsem.h>
28#include <linux/slab.h>
29#include <linux/sysfs.h>
30#include <linux/types.h>

--- 38 unchanged lines hidden (view full) ---

69 unsigned long flags;
70};
71
72struct wmi_guid_count_context {
73 const guid_t *guid;
74 int count;
75};
76
24#include <linux/init.h>
25#include <linux/kernel.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>

--- 38 unchanged lines hidden (view full) ---

70 unsigned long flags;
71};
72
73struct wmi_guid_count_context {
74 const guid_t *guid;
75 int count;
76};
77
78static DEFINE_IDA(wmi_ida);
79
77/*
78 * If the GUID data block is marked as expensive, we must enable and
79 * 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 */

--- 87 unchanged lines hidden (view full) ---

172
173static int wmi_device_enable(struct wmi_device *wdev, bool enable)
174{
175 struct wmi_block *wblock = container_of(wdev, struct wmi_block, dev);
176 char method[WMI_ACPI_METHOD_NAME_SIZE];
177 acpi_handle handle;
178 acpi_status status;
179
80/*
81 * If the GUID data block is marked as expensive, we must enable and
82 * explicitily disable data collection.
83 */
84#define ACPI_WMI_EXPENSIVE BIT(0)
85#define ACPI_WMI_METHOD BIT(1) /* GUID is a method */
86#define ACPI_WMI_STRING BIT(2) /* GUID takes & returns a string */
87#define ACPI_WMI_EVENT BIT(3) /* GUID is an event */

--- 87 unchanged lines hidden (view full) ---

175
176static int wmi_device_enable(struct wmi_device *wdev, bool enable)
177{
178 struct wmi_block *wblock = container_of(wdev, struct wmi_block, dev);
179 char method[WMI_ACPI_METHOD_NAME_SIZE];
180 acpi_handle handle;
181 acpi_status status;
182
183 if (!(wblock->gblock.flags & ACPI_WMI_EXPENSIVE))
184 return 0;
185
180 if (wblock->dev.dev.type == &wmi_type_method)
181 return 0;
182
186 if (wblock->dev.dev.type == &wmi_type_method)
187 return 0;
188
183 if (wblock->dev.dev.type == &wmi_type_event) {
184 /*
185 * Windows always enables/disables WMI events, even when they are
186 * not marked as being expensive. We follow this behavior for
187 * compatibility reasons.
188 */
189 if (wblock->dev.dev.type == &wmi_type_event)
189 snprintf(method, sizeof(method), "WE%02X", wblock->gblock.notify_id);
190 snprintf(method, sizeof(method), "WE%02X", wblock->gblock.notify_id);
190 } else {
191 if (!(wblock->gblock.flags & ACPI_WMI_EXPENSIVE))
192 return 0;
193
191 else
194 get_acpi_method_name(wblock, 'C', method);
192 get_acpi_method_name(wblock, 'C', method);
195 }
196
197 /*
198 * Not all WMI devices marked as expensive actually implement the
199 * necessary ACPI method. Ignore this missing ACPI method to match
200 * the behaviour of the Windows driver.
201 */
202 status = acpi_get_handle(wblock->acpi_device->handle, method, &handle);
203 if (ACPI_FAILURE(status))

--- 775 unchanged lines hidden (view full) ---

979
980 ret = bus_for_each_dev(&wmi_bus_type, NULL, &context, wmi_count_guids);
981 if (ret < 0)
982 return ret;
983
984 return context.count;
985}
986
193
194 /*
195 * Not all WMI devices marked as expensive actually implement the
196 * necessary ACPI method. Ignore this missing ACPI method to match
197 * the behaviour of the Windows driver.
198 */
199 status = acpi_get_handle(wblock->acpi_device->handle, method, &handle);
200 if (ACPI_FAILURE(status))

--- 775 unchanged lines hidden (view full) ---

976
977 ret = bus_for_each_dev(&wmi_bus_type, NULL, &context, wmi_count_guids);
978 if (ret < 0)
979 return ret;
980
981 return context.count;
982}
983
984static int wmi_dev_set_name(struct wmi_block *wblock, int count)
985{
986 if (IS_ENABLED(CONFIG_ACPI_WMI_LEGACY_DEVICE_NAMES)) {
987 if (count)
988 return dev_set_name(&wblock->dev.dev, "%pUL-%d", &wblock->gblock.guid,
989 count);
990 else
991 return dev_set_name(&wblock->dev.dev, "%pUL", &wblock->gblock.guid);
992 }
993
994 return dev_set_name(&wblock->dev.dev, "%pUL-%d", &wblock->gblock.guid, wblock->dev.dev.id);
995}
996
987static int wmi_create_device(struct device *wmi_bus_dev,
988 struct wmi_block *wblock,
989 struct acpi_device *device)
990{
991 char method[WMI_ACPI_METHOD_NAME_SIZE];
992 struct acpi_device_info *info;
993 acpi_handle method_handle;
994 acpi_status status;
997static int wmi_create_device(struct device *wmi_bus_dev,
998 struct wmi_block *wblock,
999 struct acpi_device *device)
1000{
1001 char method[WMI_ACPI_METHOD_NAME_SIZE];
1002 struct acpi_device_info *info;
1003 acpi_handle method_handle;
1004 acpi_status status;
995 int count;
1005 int count, ret;
996
997 if (wblock->gblock.flags & ACPI_WMI_EVENT) {
998 wblock->dev.dev.type = &wmi_type_event;
999 goto out_init;
1000 }
1001
1002 if (wblock->gblock.flags & ACPI_WMI_METHOD) {
1003 get_acpi_method_name(wblock, 'M', method);

--- 54 unchanged lines hidden (view full) ---

1058 wblock->driver_ready = false;
1059 wblock->dev.dev.bus = &wmi_bus_type;
1060 wblock->dev.dev.parent = wmi_bus_dev;
1061
1062 count = guid_count(&wblock->gblock.guid);
1063 if (count < 0)
1064 return count;
1065
1006
1007 if (wblock->gblock.flags & ACPI_WMI_EVENT) {
1008 wblock->dev.dev.type = &wmi_type_event;
1009 goto out_init;
1010 }
1011
1012 if (wblock->gblock.flags & ACPI_WMI_METHOD) {
1013 get_acpi_method_name(wblock, 'M', method);

--- 54 unchanged lines hidden (view full) ---

1068 wblock->driver_ready = false;
1069 wblock->dev.dev.bus = &wmi_bus_type;
1070 wblock->dev.dev.parent = wmi_bus_dev;
1071
1072 count = guid_count(&wblock->gblock.guid);
1073 if (count < 0)
1074 return count;
1075
1066 if (count) {
1067 dev_set_name(&wblock->dev.dev, "%pUL-%d", &wblock->gblock.guid, count);
1076 if (count)
1068 set_bit(WMI_GUID_DUPLICATED, &wblock->flags);
1077 set_bit(WMI_GUID_DUPLICATED, &wblock->flags);
1069 } else {
1070 dev_set_name(&wblock->dev.dev, "%pUL", &wblock->gblock.guid);
1078
1079 ret = ida_alloc(&wmi_ida, GFP_KERNEL);
1080 if (ret < 0)
1081 return ret;
1082
1083 wblock->dev.dev.id = ret;
1084 ret = wmi_dev_set_name(wblock, count);
1085 if (ret < 0) {
1086 ida_free(&wmi_ida, wblock->dev.dev.id);
1087 return ret;
1071 }
1072
1073 device_initialize(&wblock->dev.dev);
1074
1075 return 0;
1076}
1077
1078static int wmi_add_device(struct platform_device *pdev, struct wmi_device *wdev)

--- 69 unchanged lines hidden (view full) ---

1148 continue;
1149 }
1150
1151 retval = wmi_add_device(pdev, &wblock->dev);
1152 if (retval) {
1153 dev_err(wmi_bus_dev, "failed to register %pUL\n",
1154 &wblock->gblock.guid);
1155
1088 }
1089
1090 device_initialize(&wblock->dev.dev);
1091
1092 return 0;
1093}
1094
1095static int wmi_add_device(struct platform_device *pdev, struct wmi_device *wdev)

--- 69 unchanged lines hidden (view full) ---

1165 continue;
1166 }
1167
1168 retval = wmi_add_device(pdev, &wblock->dev);
1169 if (retval) {
1170 dev_err(wmi_bus_dev, "failed to register %pUL\n",
1171 &wblock->gblock.guid);
1172
1173 ida_free(&wmi_ida, wblock->dev.dev.id);
1156 put_device(&wblock->dev.dev);
1157 }
1158 }
1159
1160 kfree(obj);
1161
1162 return 0;
1163}

--- 83 unchanged lines hidden (view full) ---

1247{
1248 struct device *wmi_bus_dev = context;
1249
1250 device_for_each_child(wmi_bus_dev, &event, wmi_notify_device);
1251}
1252
1253static int wmi_remove_device(struct device *dev, void *data)
1254{
1174 put_device(&wblock->dev.dev);
1175 }
1176 }
1177
1178 kfree(obj);
1179
1180 return 0;
1181}

--- 83 unchanged lines hidden (view full) ---

1265{
1266 struct device *wmi_bus_dev = context;
1267
1268 device_for_each_child(wmi_bus_dev, &event, wmi_notify_device);
1269}
1270
1271static int wmi_remove_device(struct device *dev, void *data)
1272{
1273 int id = dev->id;
1274
1255 device_unregister(dev);
1275 device_unregister(dev);
1276 ida_free(&wmi_ida, id);
1256
1257 return 0;
1258}
1259
1260static void acpi_wmi_remove(struct platform_device *device)
1261{
1262 struct device *wmi_bus_device = dev_get_drvdata(&device->dev);
1263

--- 133 unchanged lines hidden ---
1277
1278 return 0;
1279}
1280
1281static void acpi_wmi_remove(struct platform_device *device)
1282{
1283 struct device *wmi_bus_device = dev_get_drvdata(&device->dev);
1284

--- 133 unchanged lines hidden ---