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