[PATCH v2 06/12] platform/x86: lenovo-wmi-{capdata,other}: Only allocate capdata list when necessary
From: Rong Zhang
Date: Fri Oct 09 2026 - 08:58:50 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>
---
Changes in v2:
- Refine line wrap (thanks Ilpo Järvinen)
---
drivers/platform/x86/lenovo/wmi-capdata.c | 42 ++++++++++++++++++++++---------
drivers/platform/x86/lenovo/wmi-other.c | 24 +++++++++++-------
2 files changed, 45 insertions(+), 21 deletions(-)
diff --git a/drivers/platform/x86/lenovo/wmi-capdata.c b/drivers/platform/x86/lenovo/wmi-capdata.c
index e52cb2de49a6..de8044ef68b8 100644
--- a/drivers/platform/x86/lenovo/wmi-capdata.c
+++ b/drivers/platform/x86/lenovo/wmi-capdata.c
@@ -315,8 +315,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.
*/
@@ -330,7 +330,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;
@@ -462,6 +462,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) \
@@ -573,6 +576,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);
@@ -584,6 +590,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;
}
@@ -647,6 +654,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;
+
/* Synchronize mutex initialization. Paired with lwmi_cd_finalize(). */
if (!smp_load_acquire(&priv->initialized))
return __lwmi_cd_cache(priv);
@@ -710,6 +720,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;
@@ -745,6 +758,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:
@@ -894,7 +909,8 @@ 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;
@@ -915,14 +931,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;
@@ -940,7 +958,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..147e182685a1 100644
--- a/drivers/platform/x86/lenovo/wmi-other.c
+++ b/drivers/platform/x86/lenovo/wmi-other.c
@@ -1619,11 +1619,14 @@ static void lwmi_om_fw_attr_remove(struct lwmi_om_priv *priv)
* lenovo-wmi-other master driver, with a callback to collect fan info from
* capdata_fan. On success, assign the capability data list pointers to the
* driver data struct for later access. These pointers are only valid while the
- * capdata interfaces exist. Finally, collect fan info from capdata00 and
- * register all firmware attribute groups. Note that the HWMON device is
- * registered only if all fan info is collected. Hence, it is not registered
- * here. See lwmi_om_fan_info_collect_cd00() and
- * lwmi_om_fan_info_collect_cd_fan().
+ * capdata interfaces exist.
+ *
+ * If capdata00 is bound, collect fan info from capdata00 and register the power
+ * supply extension. Note that the HWMON device is registered only if all fan
+ * info is collected. Hence, it is not registered here. See
+ * lwmi_om_fan_info_collect_cd00() and lwmi_om_fan_info_collect_cd_fan().
+ *
+ * If capdata01 is bound, register all firmware attribute groups.
*
* Return: 0 on success, or an error code.
*/
@@ -1643,16 +1646,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