Skip to content

Commit de0aa06

Browse files
jonhunterrafaeljw
authored andcommitted
PM / Domains: Store the provider in the PM domain structure
It is possible that a device has more than one provider of PM domains and to support the removal of a PM domain by provider, it is necessary to store a reference to the provider in the PM domain structure. Therefore, store a reference to the firmware node handle in the PM domain structure and populate it when providers (only device-tree based providers are currently supported by PM domains) are registered. Please note that when removing PM domains, it is necessary to verify that the PM domain provider has been removed from the list of providers before the PM domain can be removed. To do this add another member to the PM domain structure that indicates if the provider is present and set this member accordingly when providers are added and removed. Initialise the 'provider' and 'has_provider' members of the generic_pm_domain structure when a PM domains is added by calling pm_genpd_init(). Signed-off-by: Jon Hunter <[email protected]> Acked-by: Ulf Hansson <[email protected]> Signed-off-by: Rafael J. Wysocki <[email protected]>
1 parent 19efa5f commit de0aa06

File tree

2 files changed

+39
-5
lines changed

2 files changed

+39
-5
lines changed

drivers/base/power/domain.c

Lines changed: 37 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1306,6 +1306,8 @@ int pm_genpd_init(struct generic_pm_domain *genpd,
13061306
genpd->device_count = 0;
13071307
genpd->max_off_time_ns = -1;
13081308
genpd->max_off_time_changed = true;
1309+
genpd->provider = NULL;
1310+
genpd->has_provider = false;
13091311
genpd->domain.ops.runtime_suspend = genpd_runtime_suspend;
13101312
genpd->domain.ops.runtime_resume = genpd_runtime_resume;
13111313
genpd->domain.ops.prepare = pm_genpd_prepare;
@@ -1491,6 +1493,11 @@ int of_genpd_add_provider_simple(struct device_node *np,
14911493
if (pm_genpd_present(genpd))
14921494
ret = genpd_add_provider(np, genpd_xlate_simple, genpd);
14931495

1496+
if (!ret) {
1497+
genpd->provider = &np->fwnode;
1498+
genpd->has_provider = true;
1499+
}
1500+
14941501
mutex_unlock(&gpd_list_lock);
14951502

14961503
return ret;
@@ -1506,21 +1513,34 @@ int of_genpd_add_provider_onecell(struct device_node *np,
15061513
struct genpd_onecell_data *data)
15071514
{
15081515
unsigned int i;
1509-
int ret;
1516+
int ret = -EINVAL;
15101517

15111518
if (!np || !data)
15121519
return -EINVAL;
15131520

15141521
mutex_lock(&gpd_list_lock);
15151522

15161523
for (i = 0; i < data->num_domains; i++) {
1517-
if (!pm_genpd_present(data->domains[i])) {
1518-
mutex_unlock(&gpd_list_lock);
1519-
return -EINVAL;
1520-
}
1524+
if (!pm_genpd_present(data->domains[i]))
1525+
goto error;
1526+
1527+
data->domains[i]->provider = &np->fwnode;
1528+
data->domains[i]->has_provider = true;
15211529
}
15221530

15231531
ret = genpd_add_provider(np, genpd_xlate_onecell, data);
1532+
if (ret < 0)
1533+
goto error;
1534+
1535+
mutex_unlock(&gpd_list_lock);
1536+
1537+
return 0;
1538+
1539+
error:
1540+
while (i--) {
1541+
data->domains[i]->provider = NULL;
1542+
data->domains[i]->has_provider = false;
1543+
}
15241544

15251545
mutex_unlock(&gpd_list_lock);
15261546

@@ -1535,17 +1555,29 @@ EXPORT_SYMBOL_GPL(of_genpd_add_provider_onecell);
15351555
void of_genpd_del_provider(struct device_node *np)
15361556
{
15371557
struct of_genpd_provider *cp;
1558+
struct generic_pm_domain *gpd;
15381559

1560+
mutex_lock(&gpd_list_lock);
15391561
mutex_lock(&of_genpd_mutex);
15401562
list_for_each_entry(cp, &of_genpd_providers, link) {
15411563
if (cp->node == np) {
1564+
/*
1565+
* For each PM domain associated with the
1566+
* provider, set the 'has_provider' to false
1567+
* so that the PM domain can be safely removed.
1568+
*/
1569+
list_for_each_entry(gpd, &gpd_list, gpd_list_node)
1570+
if (gpd->provider == &np->fwnode)
1571+
gpd->has_provider = false;
1572+
15421573
list_del(&cp->link);
15431574
of_node_put(cp->node);
15441575
kfree(cp);
15451576
break;
15461577
}
15471578
}
15481579
mutex_unlock(&of_genpd_mutex);
1580+
mutex_unlock(&gpd_list_lock);
15491581
}
15501582
EXPORT_SYMBOL_GPL(of_genpd_del_provider);
15511583

include/linux/pm_domain.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,8 @@ struct generic_pm_domain {
5151
struct mutex lock;
5252
struct dev_power_governor *gov;
5353
struct work_struct power_off_work;
54+
struct fwnode_handle *provider; /* Identity of the domain provider */
55+
bool has_provider;
5456
const char *name;
5557
atomic_t sd_count; /* Number of subdomains with power "on" */
5658
enum gpd_status status; /* Current state of the domain */

0 commit comments

Comments
 (0)