From 44ff5057d75c5680090743233de5a721eb9dabe4 Mon Sep 17 00:00:00 2001 From: "Kevin Hilman (TI)" Date: Thu, 24 Sep 2026 13:29:58 -0700 Subject: [PATCH] pmdomain: core: add genpd_for_each_child() helper Add a new internal helper function genpd_for_each_child() that recursively iterates over all devices in a PM domain and its child domains (subdomains). This helper is useful for governors and other core PM domain code that needs to examine or apply operations to all devices within a domain hierarchy. The function takes a callback that is invoked for each device, and supports early termination if the callback returns a non-zero value. The helper is defined in a new internal header drivers/pmdomain/core.h and implemented in drivers/pmdomain/core.c, making it available to other PM domain subsystem components. The first user of this helper is the cpu_system_power_down_ok() governor function, which uses it to check device QoS latency constraints across the entire domain hierarchy. Reviewed-by: Abel Vesa Signed-off-by: Kevin Hilman (TI) Signed-off-by: Ulf Hansson --- drivers/pmdomain/core.c | 44 +++++++++++++++++++++++++++++++++++++++++ drivers/pmdomain/core.h | 18 +++++++++++++++++ 2 files changed, 62 insertions(+) create mode 100644 drivers/pmdomain/core.h diff --git a/drivers/pmdomain/core.c b/drivers/pmdomain/core.c index b99c2dcf3d8f..964e44c2f78f 100644 --- a/drivers/pmdomain/core.c +++ b/drivers/pmdomain/core.c @@ -27,6 +27,7 @@ #include #include +#include "core.h" /* Provides a unique ID for each genpd device */ static DEFINE_IDA(genpd_ida); @@ -283,6 +284,49 @@ static void genpd_sd_counter_inc(struct generic_pm_domain *genpd) smp_mb__after_atomic(); } +/** + * genpd_for_each_child - Recursively iterate over all devices + * in a PM domain and its subdomains. + * @genpd: PM domain to iterate over. + * @fn: Callback function to invoke for each device. + * @data: Data to pass to the callback function. + * + * This function recursively walks through all devices in the given PM domain + * and all devices in its child PM domains (subdomains). For each device found, + * the callback function @fn is invoked with the device and @data as arguments. + * + * Note: this function is inteded for use by the core and governors, + * not for pmdomain providers. + * + * Returns: 0 on success, or the first non-zero value returned by @fn. + */ +int genpd_for_each_child(struct generic_pm_domain *genpd, + int (*fn)(struct device *dev, void *data), + void *data) +{ + struct pm_domain_data *pdd; + struct gpd_link *link; + int ret; + + /* First, iterate over all devices in this domain */ + list_for_each_entry(pdd, &genpd->dev_list, list_node) { + ret = fn(pdd->dev, data); + if (ret) + return ret; + } + + /* Then, recursively iterate over all child domains (subdomains) */ + list_for_each_entry(link, &genpd->parent_links, parent_node) { + struct generic_pm_domain *child_pd = link->child; + + ret = genpd_for_each_child(child_pd, fn, data); + if (ret) + return ret; + } + + return 0; +} + #ifdef CONFIG_DEBUG_FS static struct dentry *genpd_debugfs_dir; diff --git a/drivers/pmdomain/core.h b/drivers/pmdomain/core.h new file mode 100644 index 000000000000..d1df535a834a --- /dev/null +++ b/drivers/pmdomain/core.h @@ -0,0 +1,18 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Internal header for PM domain core + * + * Copyright (C) 2026 Kevin Hilman , Texas Instruments + */ + +#ifndef __PM_DOMAIN_CORE_H__ +#define __PM_DOMAIN_CORE_H__ + +struct device; +struct generic_pm_domain; + +int genpd_for_each_child(struct generic_pm_domain *genpd, + int (*fn)(struct device *dev, void *data), + void *data); + +#endif /* __PM_DOMAIN_CORE_H__ */