From 1e99760fb07fbe568d1163795ad3a31825952d45 Mon Sep 17 00:00:00 2001 From: Rong Zhang Date: Mon, 19 Oct 2026 23:02:32 +0800 Subject: [PATCH] platform/x86: lenovo-wmi-capdata: Do not match missing components MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Some devices do not support LENOVO_CAPABILITY_DATA_01. They either do not have the corresponding WMI GUID, or do not implement the query method. In both cases, the WMI core does not create the corresponding WMI device, leaving the component master (i.e., lenovo-wmi-other) waits for the missing component forever. Identify missing components using the new wmidev_exists() interface, and skip adding them to the match list, so that all components in the list must present, fulfilling the binding requirement. Reported-by: Navon John Lukose Closes: https://msgid.link/20260928190901.1369497-1-navonjohnlukose@gmail.com Suggested-by: Mark Pearson Link: https://msgid.link/9789f452-d7eb-4f1e-8a13-7335332193a7@app.fastmail.com Tested-by: Navon John Lukose Reviewed-by: Derek J. Clark Reviewed-by: Mark Pearson Signed-off-by: Rong Zhang Link: https://patch.msgid.link/20261019-lwmi-wmi-new-api-v5-10-71557d28d058@rong.moe Reviewed-by: Ilpo Järvinen Signed-off-by: Ilpo Järvinen --- drivers/platform/x86/lenovo/wmi-capdata.c | 41 ++++++++++++++++++++--- 1 file changed, 36 insertions(+), 5 deletions(-) diff --git a/drivers/platform/x86/lenovo/wmi-capdata.c b/drivers/platform/x86/lenovo/wmi-capdata.c index b86bc7a57a04..1d44ff83e157 100644 --- a/drivers/platform/x86/lenovo/wmi-capdata.c +++ b/drivers/platform/x86/lenovo/wmi-capdata.c @@ -49,6 +49,7 @@ #include #include #include +#include #include #include @@ -75,14 +76,19 @@ enum lwmi_cd_type { CD_TYPE_NONE = -1, }; -#define LWMI_CD_TABLE_ITEM(_type) \ - [_type] = { \ - .name = #_type, \ - .type = _type, \ +static const struct wmi_device_id lwmi_cd_id_table[]; + +/* Save some .rodata space by reusing the GUID strings from the id table. */ +#define LWMI_CD_TABLE_ITEM(_type) \ + [_type] = { \ + .name = #_type, \ + .guid_string = lwmi_cd_id_table[_type].guid_string, \ + .type = _type, \ } static const struct lwmi_cd_info { const char *name; + const char *guid_string; enum lwmi_cd_type type; } lwmi_cd_table[] = { LWMI_CD_TABLE_ITEM(LENOVO_CAPABILITY_DATA_00), @@ -153,24 +159,49 @@ static int lwmi_cd_match(struct device *dev, void *type) * * Adds all component matches to the list stored in @matchptr for the @master * device. @matchptr must be initialized to NULL. + * + * Missing components are not added to the match list, or else the master waits + * for them forever. For some components, their existence can be determined by + * querying other components, so they are handled as sub-components and thus not + * matched here. For components with no existence declaration, wmidev_exists() + * is used to determine their existence. + * + * If all components are missing, ERR_PTR(-ENXIO) is returned through @matchptr. */ void lwmi_cd_match_add_all(struct device *master, struct component_match **matchptr) { - int i; + bool matched = false; + int ret, i; if (WARN_ON(*matchptr)) return; for (i = 0; i < ARRAY_SIZE(lwmi_cd_table); i++) { + guid_t guid; + /* Skip sub-components. */ if (lwmi_cd_table[i].type == LENOVO_FAN_TEST_DATA) continue; + ret = guid_parse(lwmi_cd_table[i].guid_string, &guid); + if (ret < 0) { + *matchptr = ERR_PTR(ret); + return; + } + + if (!wmidev_exists(&guid)) + continue; + component_match_add(master, matchptr, lwmi_cd_match, (void *)&lwmi_cd_table[i].type); if (IS_ERR(*matchptr)) return; + + matched = true; } + + if (!matched) + *matchptr = ERR_PTR(-ENXIO); } EXPORT_SYMBOL_NS_GPL(lwmi_cd_match_add_all, "LENOVO_WMI_CAPDATA");