summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorUlf Hansson <ulf.hansson@linaro.org>2015-09-29 15:12:37 +0200
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2015-10-12 23:19:55 +0200
commitf96b3c4f34b294a2293a5aa1d55e12e66aee055d (patch)
tree8d47b988d288d30c437d1ff7ca9ffdcfef2aa042
parent1462206cbccebf2b61e05cf786d458afe49d5509 (diff)
downloadlwn-f96b3c4f34b294a2293a5aa1d55e12e66aee055d.tar.gz
lwn-f96b3c4f34b294a2293a5aa1d55e12e66aee055d.zip
PM / Domains: Remove in_progress counter from struct generic_pm_domain
Commit ba2bbfbf6307 ("PM / Domains: Remove intermediate states..") changed the power off sequence (pm_genpd_poweroff()), which from locking point of view means the genpd mutex is held throughout the sequence. The above change means the in_progress counter can't be updated while pm_genpd_poweroff() is executing, which allows us to remove the counter. Instead we inform pm_genpd_poweroff() via a bool parameter, to indicate whether we call it from the scheduled work or from the ->runtime_suspend() callback, since that all that matters. Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org> Reviewed-by: Lina Iyer <lina.iyer@linaro.org> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
-rw-r--r--drivers/base/power/domain.c12
-rw-r--r--include/linux/pm_domain.h1
2 files changed, 5 insertions, 8 deletions
diff --git a/drivers/base/power/domain.c b/drivers/base/power/domain.c
index cf4950d92937..c785f2e398b9 100644
--- a/drivers/base/power/domain.c
+++ b/drivers/base/power/domain.c
@@ -315,11 +315,12 @@ static int genpd_dev_pm_qos_notifier(struct notifier_block *nb,
/**
* pm_genpd_poweroff - Remove power from a given PM domain.
* @genpd: PM domain to power down.
+ * @is_async: PM domain is powered down from a scheduled work
*
* If all of the @genpd's devices have been suspended and all of its subdomains
* have been powered down, remove power from @genpd.
*/
-static int pm_genpd_poweroff(struct generic_pm_domain *genpd)
+static int pm_genpd_poweroff(struct generic_pm_domain *genpd, bool is_async)
{
struct pm_domain_data *pdd;
struct gpd_link *link;
@@ -351,7 +352,7 @@ static int pm_genpd_poweroff(struct generic_pm_domain *genpd)
not_suspended++;
}
- if (not_suspended > genpd->in_progress)
+ if (not_suspended > 1 || (not_suspended == 1 && is_async))
return -EBUSY;
if (genpd->gov && genpd->gov->power_down_ok) {
@@ -399,7 +400,7 @@ static void genpd_power_off_work_fn(struct work_struct *work)
genpd = container_of(work, struct generic_pm_domain, power_off_work);
mutex_lock(&genpd->lock);
- pm_genpd_poweroff(genpd);
+ pm_genpd_poweroff(genpd, true);
mutex_unlock(&genpd->lock);
}
@@ -445,9 +446,7 @@ static int pm_genpd_runtime_suspend(struct device *dev)
return 0;
mutex_lock(&genpd->lock);
- genpd->in_progress++;
- pm_genpd_poweroff(genpd);
- genpd->in_progress--;
+ pm_genpd_poweroff(genpd, false);
mutex_unlock(&genpd->lock);
return 0;
@@ -1462,7 +1461,6 @@ void pm_genpd_init(struct generic_pm_domain *genpd,
mutex_init(&genpd->lock);
genpd->gov = gov;
INIT_WORK(&genpd->power_off_work, genpd_power_off_work_fn);
- genpd->in_progress = 0;
atomic_set(&genpd->sd_count, 0);
genpd->status = is_off ? GPD_STATE_POWER_OFF : GPD_STATE_ACTIVE;
genpd->device_count = 0;
diff --git a/include/linux/pm_domain.h b/include/linux/pm_domain.h
index 384b1d193707..0eaa730c890d 100644
--- a/include/linux/pm_domain.h
+++ b/include/linux/pm_domain.h
@@ -47,7 +47,6 @@ struct generic_pm_domain {
struct dev_power_governor *gov;
struct work_struct power_off_work;
const char *name;
- unsigned int in_progress; /* Number of devices being suspended now */
atomic_t sd_count; /* Number of subdomains with power "on" */
enum gpd_status status; /* Current state of the domain */
unsigned int device_count; /* Number of devices */