mirror of
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-09-04 20:19:47 +08:00
platform/x86: dell-smbios-wmi: Stop touching WMI device ID
The Dell SMBIOS driver uses the "id" field inside struct device for
prioritizing the WMI backend over the SMM backend. Because of this
the WMI backend modifies the "id" field of the underlying WMI device.
However the WMI core itself uses wdev->dev.id internally to track
device IDs, so modifying this value will result in a resource leak.
Fix this by not using the "id" field inside struct device for SMBIOS
prioritization. Instead extend struct smbios_device with a separate
"priority" field.
Tested on a Dell Inspiron 3505.
Fixes: 73f0f2b52c
("platform/x86: wmi: Fix WMI device naming issue")
Signed-off-by: Armin Wolf <W_Armin@gmx.de>
Link: https://lore.kernel.org/r/20250722183841.9552-1-W_Armin@gmx.de
Reviewed-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
This commit is contained in:
parent
8f5ae30d69
commit
d26a9f4f0a
@ -39,6 +39,7 @@ struct token_sysfs_data {
|
||||
struct smbios_device {
|
||||
struct list_head list;
|
||||
struct device *device;
|
||||
int priority;
|
||||
int (*call_fn)(struct calling_interface_buffer *arg);
|
||||
};
|
||||
|
||||
@ -145,7 +146,7 @@ int dell_smbios_error(int value)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(dell_smbios_error);
|
||||
|
||||
int dell_smbios_register_device(struct device *d, void *call_fn)
|
||||
int dell_smbios_register_device(struct device *d, int priority, void *call_fn)
|
||||
{
|
||||
struct smbios_device *priv;
|
||||
|
||||
@ -154,6 +155,7 @@ int dell_smbios_register_device(struct device *d, void *call_fn)
|
||||
return -ENOMEM;
|
||||
get_device(d);
|
||||
priv->device = d;
|
||||
priv->priority = priority;
|
||||
priv->call_fn = call_fn;
|
||||
mutex_lock(&smbios_mutex);
|
||||
list_add_tail(&priv->list, &smbios_device_list);
|
||||
@ -292,28 +294,25 @@ EXPORT_SYMBOL_GPL(dell_smbios_call_filter);
|
||||
|
||||
int dell_smbios_call(struct calling_interface_buffer *buffer)
|
||||
{
|
||||
int (*call_fn)(struct calling_interface_buffer *) = NULL;
|
||||
struct device *selected_dev = NULL;
|
||||
struct smbios_device *selected = NULL;
|
||||
struct smbios_device *priv;
|
||||
int ret;
|
||||
|
||||
mutex_lock(&smbios_mutex);
|
||||
list_for_each_entry(priv, &smbios_device_list, list) {
|
||||
if (!selected_dev || priv->device->id >= selected_dev->id) {
|
||||
dev_dbg(priv->device, "Trying device ID: %d\n",
|
||||
priv->device->id);
|
||||
call_fn = priv->call_fn;
|
||||
selected_dev = priv->device;
|
||||
if (!selected || priv->priority >= selected->priority) {
|
||||
dev_dbg(priv->device, "Trying device ID: %d\n", priv->priority);
|
||||
selected = priv;
|
||||
}
|
||||
}
|
||||
|
||||
if (!selected_dev) {
|
||||
if (!selected) {
|
||||
ret = -ENODEV;
|
||||
pr_err("No dell-smbios drivers are loaded\n");
|
||||
goto out_smbios_call;
|
||||
}
|
||||
|
||||
ret = call_fn(buffer);
|
||||
ret = selected->call_fn(buffer);
|
||||
|
||||
out_smbios_call:
|
||||
mutex_unlock(&smbios_mutex);
|
||||
|
@ -125,8 +125,7 @@ int init_dell_smbios_smm(void)
|
||||
if (ret)
|
||||
goto fail_platform_device_add;
|
||||
|
||||
ret = dell_smbios_register_device(&platform_device->dev,
|
||||
&dell_smbios_smm_call);
|
||||
ret = dell_smbios_register_device(&platform_device->dev, 0, &dell_smbios_smm_call);
|
||||
if (ret)
|
||||
goto fail_register;
|
||||
|
||||
|
@ -264,9 +264,7 @@ static int dell_smbios_wmi_probe(struct wmi_device *wdev, const void *context)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* ID is used by dell-smbios to set priority of drivers */
|
||||
wdev->dev.id = 1;
|
||||
ret = dell_smbios_register_device(&wdev->dev, &dell_smbios_wmi_call);
|
||||
ret = dell_smbios_register_device(&wdev->dev, 1, &dell_smbios_wmi_call);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
|
@ -64,7 +64,7 @@ struct calling_interface_structure {
|
||||
struct calling_interface_token tokens[];
|
||||
} __packed;
|
||||
|
||||
int dell_smbios_register_device(struct device *d, void *call_fn);
|
||||
int dell_smbios_register_device(struct device *d, int priority, void *call_fn);
|
||||
void dell_smbios_unregister_device(struct device *d);
|
||||
|
||||
int dell_smbios_error(int value);
|
||||
|
Loading…
Reference in New Issue
Block a user