[PATCH 4/9] platform/x86: lenovo-wmi-{capdata,other}: Only allocate capdata list when necessary

From: Rong Zhang

Date: Sun Sep 13 2026 - 16:52:10 EST


When no capability data is available, there is no need to allocate
capability data list as it's basically unused except for the
priv->list->count == 0 placeholder.

Therefore, only allocate priv->list when necessary, otherwise its
absence implies the absence of capability data. In this manner,
lenovo-wmi-other can skip registering unavailable functionalities
accordingly. Meanwhile, skip creating the debugfs directory as it
provides nothing when there is no capability data.

Signed-off-by: Rong Zhang <i@xxxxxxxx>
---
drivers/platform/x86/lenovo/wmi-capdata.c | 43 ++++++++++++++++++++++---------
drivers/platform/x86/lenovo/wmi-other.c | 11 +++++---
2 files changed, 38 insertions(+), 16 deletions(-)

diff --git a/drivers/platform/x86/lenovo/wmi-capdata.c b/drivers/platform/x86/lenovo/wmi-capdata.c
index 0123ec8f7b53..793b5103d533 100644
--- a/drivers/platform/x86/lenovo/wmi-capdata.c
+++ b/drivers/platform/x86/lenovo/wmi-capdata.c
@@ -313,8 +313,8 @@ static const struct component_ops lwmi_cd_component_ops = {
* @dev: The sub-master capdata basic device.
*
* Call component_bind_all to bind the sub-component device to the sub-master
- * device. On success, collect the pointer to the sub-component list and try
- * to call the master callback.
+ * device. On success, collect the pointer (or ERR_PTR(-ENODEV) if it's stubbed)
+ * to the sub-component list and try to call the master callback.
*
* Return: 0 on success, or an error code.
*/
@@ -328,7 +328,7 @@ static int lwmi_cd_sub_master_bind(struct device *dev)
if (ret)
return ret;

- priv->sub_master->sub_component_list = sub_component_list;
+ priv->sub_master->sub_component_list = sub_component_list ?: ERR_PTR(-ENODEV);
lwmi_cd_call_master_cb(priv);

return 0;
@@ -460,6 +460,9 @@ static const struct component_ops lwmi_cd_sub_component_ops = {
{ \
u8 idx; \
\
+ if (WARN_ON(!list)) \
+ return -EINVAL; \
+ \
guard(mutex)(&list->list_mutex); \
for (idx = 0; idx < list->count; idx++) { \
if (list->_cdxx[idx].id != attribute_id) \
@@ -571,6 +574,9 @@ DEFINE_SHOW_ATTRIBUTE(lwmi_cd_debugfs);
*/
static void lwmi_cd_debugfs_add(struct lwmi_cd_priv *priv)
{
+ if (!priv->list)
+ return;
+
priv->debugfs_dir = lwmi_debugfs_create_dir(priv->wdev);

debugfs_create_file("capdata", 0444, priv->debugfs_dir, priv, &lwmi_cd_debugfs_fops);
@@ -582,6 +588,7 @@ static void lwmi_cd_debugfs_add(struct lwmi_cd_priv *priv)
*/
static void lwmi_cd_debugfs_remove(struct lwmi_cd_priv *priv)
{
+ /* Debugfs can handle NULL dir, no need to check. */
debugfs_remove_recursive(priv->debugfs_dir);
priv->debugfs_dir = NULL;
}
@@ -645,6 +652,9 @@ static int __lwmi_cd_cache(struct lwmi_cd_priv *priv)
*/
static int lwmi_cd_cache(struct lwmi_cd_priv *priv)
{
+ if (!priv->list)
+ return 0;
+
if (!priv->initialized)
return __lwmi_cd_cache(priv);

@@ -707,6 +717,9 @@ static int lwmi_cd_fan_list_alloc_cache(struct lwmi_cd_priv *priv)
count = 0;
}

+ if (!count)
+ return 0;
+
list = devm_kzalloc(&priv->wdev->dev, struct_size(list, cd_fan, count), GFP_KERNEL);
if (!list)
return -ENOMEM;
@@ -742,6 +755,8 @@ static int lwmi_cd_alloc(struct lwmi_cd_priv *priv)
int count;

count = wmidev_instance_count(priv->wdev);
+ if (!count)
+ return 0;

switch (priv->info->type) {
case LENOVO_CAPABILITY_DATA_00:
@@ -884,7 +899,9 @@ static int lwmi_cd_probe(struct wmi_device *wdev, const void *context)
enum lwmi_cd_type sub_component_type = LENOVO_FAN_TEST_DATA;
struct capdata00 capdata00;

- ret = lwmi_cd00_get_data(priv->list, LWMI_ATTR_ID_FAN_TEST, &capdata00);
+ ret = priv->list
+ ? lwmi_cd00_get_data(priv->list, LWMI_ATTR_ID_FAN_TEST, &capdata00)
+ : -ENODATA;
if (ret || !(capdata00.supported & LWMI_SUPP_VALID)) {
dev_dbg(&wdev->dev, "capdata00 declares no fan test support\n");
sub_component_type = CD_TYPE_NONE;
@@ -905,14 +922,16 @@ static int lwmi_cd_probe(struct wmi_device *wdev, const void *context)
case LENOVO_CAPABILITY_DATA_01:
priv->acpi_nb.notifier_call = lwmi_cd01_notifier_call;

- ret = register_acpi_notifier(&priv->acpi_nb);
- if (ret)
- goto out;
+ if (priv->list) {
+ ret = register_acpi_notifier(&priv->acpi_nb);
+ if (ret)
+ goto out;

- ret = devm_add_action_or_reset(&wdev->dev, lwmi_cd01_unregister,
- &priv->acpi_nb);
- if (ret)
- goto out;
+ ret = devm_add_action_or_reset(&wdev->dev, lwmi_cd01_unregister,
+ &priv->acpi_nb);
+ if (ret)
+ goto out;
+ }

ret = component_add(&wdev->dev, &lwmi_cd_component_ops);
goto out;
@@ -930,7 +949,7 @@ static int lwmi_cd_probe(struct wmi_device *wdev, const void *context)
lwmi_cd_debugfs_add(priv);

dev_dbg(&wdev->dev, "registered %s with %u items\n",
- info->name, priv->list->count);
+ info->name, priv->list ? priv->list->count : 0);
}
return ret;
}
diff --git a/drivers/platform/x86/lenovo/wmi-other.c b/drivers/platform/x86/lenovo/wmi-other.c
index fbb32bf404f2..e6c8f6bcf050 100644
--- a/drivers/platform/x86/lenovo/wmi-other.c
+++ b/drivers/platform/x86/lenovo/wmi-other.c
@@ -1643,16 +1643,19 @@ static int lwmi_om_master_bind(struct device *dev)

priv->cd00_list = binder.cd00_list;
priv->cd01_list = binder.cd01_list;
- if (!priv->cd00_list || !priv->cd01_list) {
+ if (!priv->cd00_list && !priv->cd01_list) {
component_unbind_all(dev, NULL);

return -ENODEV;
}

- lwmi_om_fan_info_collect_cd00(priv);
- lwmi_om_psy_ext_init(priv);
+ if (priv->cd00_list) {
+ lwmi_om_fan_info_collect_cd00(priv);
+ lwmi_om_psy_ext_init(priv);
+ }

- lwmi_om_fw_attr_add(priv);
+ if (priv->cd01_list)
+ lwmi_om_fw_attr_add(priv);

return 0;
}

--
2.55.0