[PATCH v2 09/12] platform/x86: lenovo-wmi-capdata: Detect stubbed capdata device
From: Rong Zhang
Date: Fri Oct 09 2026 - 08:59:38 EST
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.
Signed-off-by: Rong Zhang <i@xxxxxxxx>
---
Changes in v2:
- Replace the term "poison" with "stub" (thanks 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 d913176d2061..79c72717ea40 100644
--- a/drivers/platform/x86/lenovo/wmi-capdata.c
+++ b/drivers/platform/x86/lenovo/wmi-capdata.c
@@ -693,6 +693,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;
@@ -727,8 +728,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;
}
@@ -769,6 +793,7 @@ static int lwmi_cd_cache(struct lwmi_cd_priv *priv)
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;
@@ -811,13 +836,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;
}
--
2.55.0