Hi Armin, On 2/27/24 23:47, Armin Wolf wrote: > Am 27.02.24 um 21:30 schrieb Pali Rohár: > >> On Monday 26 February 2024 20:35:56 Armin Wolf wrote: >>> Many older WMI drivers cannot be instantiated multiple times for >>> two reasons: >>> >>> - they are using the legacy GUID-based WMI API >>> - they are singletons (with global state) >>> >>> Prevent such WMI drivers from binding to WMI devices with a duplicated >>> GUID, as this would mean that the WMI driver will be instantiated at >>> least two times (one for the original GUID and one for the duplicated >>> GUID). >>> WMI drivers which can be instantiated multiple times can signal this >>> by setting a flag inside struct wmi_driver. >> What do you think about opposite direction? Adding ".singleton = true" >> into every driver which is not compatible with duplicated initialization >> and having the default value that drivers are not singletons. >> >> But if the direction it to not accept new "legacy" drivers and start get >> rid of all "legacy" drivers by rewriting them, then it does not matter >> if "no_singleton" or "is_singleton" is used... > > Hi, > > i want to make sure that i wont forget any legacy WMI drivers. This way, the > older legacy WMI drivers automatically initialize no_singleton with false. > > Also i intent to not accept new legacy WMI drivers. Somewhat offtopic question, how do you plan to handle the case where there are 2 WMI GUIDs for what really is a single "thing", specifically one main WMI GUID for a vendor specific interface for say the embedded-controller and a separate GUID for events ? IIRC we have several such cases. I thought we even have a case where the main WMI GUID already is bound to using wmi_bus wmi_driver, while the event guid is listened to by using wmi_install_notify_handler() but I cannot find the code doing this, so I might be mistaken on this. Regards, Hans >>> Tested on a ASUS Prime B650-Plus. >>> >>> Signed-off-by: Armin Wolf <W_Armin@xxxxxx> >>> --- >>> drivers/hwmon/dell-smm-hwmon.c | 1 + >>> drivers/platform/x86/dell/dell-wmi-ddv.c | 1 + >>> drivers/platform/x86/intel/wmi/sbl-fw-update.c | 1 + >>> drivers/platform/x86/intel/wmi/thunderbolt.c | 1 + >>> drivers/platform/x86/wmi-bmof.c | 1 + >>> drivers/platform/x86/wmi.c | 12 ++++++++++++ >>> include/linux/wmi.h | 2 ++ >>> 7 files changed, 19 insertions(+) >>> >>> diff --git a/drivers/hwmon/dell-smm-hwmon.c b/drivers/hwmon/dell-smm-hwmon.c >>> index 6d8c0f328b7b..168d669c4eca 100644 >>> --- a/drivers/hwmon/dell-smm-hwmon.c >>> +++ b/drivers/hwmon/dell-smm-hwmon.c >>> @@ -1587,6 +1587,7 @@ static struct wmi_driver dell_smm_wmi_driver = { >>> }, >>> .id_table = dell_smm_wmi_id_table, >>> .probe = dell_smm_wmi_probe, >>> + .no_singleton = true, >>> }; >>> >>> /* >>> diff --git a/drivers/platform/x86/dell/dell-wmi-ddv.c b/drivers/platform/x86/dell/dell-wmi-ddv.c >>> index db1e9240dd02..0b2299f7a2de 100644 >>> --- a/drivers/platform/x86/dell/dell-wmi-ddv.c >>> +++ b/drivers/platform/x86/dell/dell-wmi-ddv.c >>> @@ -882,6 +882,7 @@ static struct wmi_driver dell_wmi_ddv_driver = { >>> }, >>> .id_table = dell_wmi_ddv_id_table, >>> .probe = dell_wmi_ddv_probe, >>> + .no_singleton = true, >>> }; >>> module_wmi_driver(dell_wmi_ddv_driver); >>> >>> diff --git a/drivers/platform/x86/intel/wmi/sbl-fw-update.c b/drivers/platform/x86/intel/wmi/sbl-fw-update.c >>> index 040153ad67c1..75c82c08117f 100644 >>> --- a/drivers/platform/x86/intel/wmi/sbl-fw-update.c >>> +++ b/drivers/platform/x86/intel/wmi/sbl-fw-update.c >>> @@ -131,6 +131,7 @@ static struct wmi_driver intel_wmi_sbl_fw_update_driver = { >>> .probe = intel_wmi_sbl_fw_update_probe, >>> .remove = intel_wmi_sbl_fw_update_remove, >>> .id_table = intel_wmi_sbl_id_table, >>> + .no_singleton = true, >>> }; >>> module_wmi_driver(intel_wmi_sbl_fw_update_driver); >>> >>> diff --git a/drivers/platform/x86/intel/wmi/thunderbolt.c b/drivers/platform/x86/intel/wmi/thunderbolt.c >>> index e2ad3f46f356..08df560a2c7a 100644 >>> --- a/drivers/platform/x86/intel/wmi/thunderbolt.c >>> +++ b/drivers/platform/x86/intel/wmi/thunderbolt.c >>> @@ -63,6 +63,7 @@ static struct wmi_driver intel_wmi_thunderbolt_driver = { >>> .dev_groups = tbt_groups, >>> }, >>> .id_table = intel_wmi_thunderbolt_id_table, >>> + .no_singleton = true, >>> }; >>> >>> module_wmi_driver(intel_wmi_thunderbolt_driver); >>> diff --git a/drivers/platform/x86/wmi-bmof.c b/drivers/platform/x86/wmi-bmof.c >>> index 644d2fd889c0..df6f0ae6e6c7 100644 >>> --- a/drivers/platform/x86/wmi-bmof.c >>> +++ b/drivers/platform/x86/wmi-bmof.c >>> @@ -94,6 +94,7 @@ static struct wmi_driver wmi_bmof_driver = { >>> .probe = wmi_bmof_probe, >>> .remove = wmi_bmof_remove, >>> .id_table = wmi_bmof_id_table, >>> + .no_singleton = true, >>> }; >>> >>> module_wmi_driver(wmi_bmof_driver); >>> diff --git a/drivers/platform/x86/wmi.c b/drivers/platform/x86/wmi.c >>> index 29dfe52eb802..349deced87e8 100644 >>> --- a/drivers/platform/x86/wmi.c >>> +++ b/drivers/platform/x86/wmi.c >>> @@ -883,6 +883,18 @@ static int wmi_dev_probe(struct device *dev) >>> struct wmi_driver *wdriver = drv_to_wdrv(dev->driver); >>> int ret = 0; >>> >>> + /* Some older WMI drivers will break if instantiated multiple times, >>> + * so they are blocked from probing WMI devices with a duplicated GUID. >>> + * >>> + * New WMI drivers should support being instantiated multiple times. >>> + */ >>> + if (test_bit(WMI_GUID_DUPLICATED, &wblock->flags) && !wdriver->no_singleton) { >>> + dev_warn(dev, "Legacy driver %s cannot be instantiated multiple times\n", >>> + dev->driver->name); >>> + >>> + return -ENODEV; >>> + } >>> + >>> if (wdriver->notify) { >>> if (test_bit(WMI_NO_EVENT_DATA, &wblock->flags) && !wdriver->no_notify_data) >>> return -ENODEV; >>> diff --git a/include/linux/wmi.h b/include/linux/wmi.h >>> index 781958310bfb..63cca3b58d6d 100644 >>> --- a/include/linux/wmi.h >>> +++ b/include/linux/wmi.h >>> @@ -49,6 +49,7 @@ u8 wmidev_instance_count(struct wmi_device *wdev); >>> * @driver: Driver model structure >>> * @id_table: List of WMI GUIDs supported by this driver >>> * @no_notify_data: Driver supports WMI events which provide no event data >>> + * @no_singleton: Driver can be instantiated multiple times >>> * @probe: Callback for device binding >>> * @remove: Callback for device unbinding >>> * @notify: Callback for receiving WMI events >>> @@ -59,6 +60,7 @@ struct wmi_driver { >>> struct device_driver driver; >>> const struct wmi_device_id *id_table; >>> bool no_notify_data; >>> + bool no_singleton; >>> >>> int (*probe)(struct wmi_device *wdev, const void *context); >>> void (*remove)(struct wmi_device *wdev); >>> -- >>> 2.39.2 >>> >