From 41a2ea4df8f036c9420616f29deb8ef5744dfd65 Mon Sep 17 00:00:00 2001 From: Rong Zhang Date: Mon, 19 Oct 2026 23:02:31 +0800 Subject: [PATCH] platform/x86: lenovo-wmi-capdata: Detect stubbed capdata device MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Some devices may stub the capdata device's WMI query method because it doesn't support the relevant interfaces at all. For example, most ThinkBook devices doesn't support GameZone or Other Mode thermal tuning, so capdata 01 is useless and stubbed. Keeping the capability data list with empty data is meaningless and causes lenovo-wmi-other to call lwmi_cd*_get_data() to retrieve nonexistent capdata in vain. Therefore, stub the device and release (or skip allocating) needless resources, e.g., the capability data list and the debugfs directory. 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-9-71557d28d058@rong.moe Reviewed-by: Ilpo Järvinen Signed-off-by: Ilpo Järvinen --- drivers/platform/x86/lenovo/wmi-capdata.c | 33 +++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/drivers/platform/x86/lenovo/wmi-capdata.c b/drivers/platform/x86/lenovo/wmi-capdata.c index 7310b72e8c2f..b86bc7a57a04 100644 --- a/drivers/platform/x86/lenovo/wmi-capdata.c +++ b/drivers/platform/x86/lenovo/wmi-capdata.c @@ -691,6 +691,7 @@ static int lwmi_cd_stub(struct lwmi_cd_priv *priv, int err) */ static int __lwmi_cd_cache(struct lwmi_cd_priv *priv) { + bool got_data = false; size_t size; int idx; void *p; @@ -725,8 +726,31 @@ static int __lwmi_cd_cache(struct lwmi_cd_priv *priv) struct capdata00 *capdata __free(kfree) = wbuf.data; memcpy(p, capdata, size); + + /* + * A valid attribute always has a non-zero id. IOW, a zero id + * implies a stubbed item (or the query method being stubbed). + * + * The stubbed item is still copied to the cache slot anyway, in + * case the firmware dynamically stubs the capdata item after + * switching Game Zone mode. In this manner, the previously + * exposed capdata can be void. + */ + if (capdata->id) + got_data = true; } + /* + * Some devices may stub the query method because it doesn't support the + * relevant interfaces at all. For example, most ThinkBook devices + * doesn't support Game Zone or Other Mode thermal tuning, so capdata 01 + * is useless and stubbed. + * + * Stub the device and release needless resources. + */ + if (!got_data) + return lwmi_cd_stub(priv, -ENODATA); + return 0; } @@ -772,6 +796,7 @@ struct lwmi_cd_fan_block { static int lwmi_cd_fan_list_alloc_cache(struct lwmi_cd_priv *priv) { struct wmi_buffer wbuf; + bool got_data = false; struct cd_list *list; int ret, idx; u32 count; @@ -808,13 +833,21 @@ static int lwmi_cd_fan_list_alloc_cache(struct lwmi_cd_priv *priv) priv->list = list; for (idx = 0; idx < count; idx++) { + if (!block->data[idx]) /* Ignore stub. */ + continue; + list->cd_fan[idx] = (struct capdata_fan) { .id = block->data[idx], .max_rpm = block->data[idx + count], .min_rpm = block->data[idx + (2 * count)], }; + + got_data = true; } + if (!got_data) + return lwmi_cd_stub(priv, -ENODATA); + return 0; }