* [PATCH 0/8] PM / Domains: Bunch of small improvements and fixes
@ 2017-06-09 16:08 Krzysztof Kozlowski
2017-06-09 16:08 ` [PATCH 1/8] PM / Domains: Constify genpd pointer Krzysztof Kozlowski
` (7 more replies)
0 siblings, 8 replies; 12+ messages in thread
From: Krzysztof Kozlowski @ 2017-06-09 16:08 UTC (permalink / raw)
To: Rafael J. Wysocki, Kevin Hilman, Ulf Hansson, Pavel Machek,
Len Brown, Greg Kroah-Hartman, linux-pm, linux-kernel
Cc: Krzysztof Kozlowski
Hi,
Except adding lockdep assert to domains list mutex (3/8), all patches
are independent. Including the fixes for unsafe loop iteration.
The last patch is RFC as this brings small overhead.
Best regards,
Krzysztof
Krzysztof Kozlowski (8):
PM / Domains: Constify genpd pointer
PM / domains: Protect reading loop over list of domains
PM / domains: Add lockdep asserts for domains list mutex
PM / domains: Fix unsafe iteration over modified list of device links
PM / domains: Fix unsafe iteration over modified list of domain
providers
PM / domains: Fix unsafe iteration over modified list of domains
PM / domains: Fix missing default_power_down_ok comment
PM / Domains: Add asserts for PM domain locks
drivers/base/power/domain.c | 66 ++++++++++++++++++++++++++++--------
drivers/base/power/domain_governor.c | 12 +++----
2 files changed, 58 insertions(+), 20 deletions(-)
--
2.9.3
^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH 1/8] PM / Domains: Constify genpd pointer
2017-06-09 16:08 [PATCH 0/8] PM / Domains: Bunch of small improvements and fixes Krzysztof Kozlowski
@ 2017-06-09 16:08 ` Krzysztof Kozlowski
2017-06-09 16:08 ` [PATCH 2/8] PM / domains: Protect reading loop over list of domains Krzysztof Kozlowski
` (6 subsequent siblings)
7 siblings, 0 replies; 12+ messages in thread
From: Krzysztof Kozlowski @ 2017-06-09 16:08 UTC (permalink / raw)
To: Rafael J. Wysocki, Kevin Hilman, Ulf Hansson, Pavel Machek,
Len Brown, Greg Kroah-Hartman, linux-pm, linux-kernel
Cc: Krzysztof Kozlowski
Mark pointer to struct generic_pm_domain const (either passed in
argument or used localy in a function), whenever it is not modifed by
the function itself.
Signed-off-by: Krzysztof Kozlowski <krzk@kernel.org>
---
drivers/base/power/domain.c | 17 ++++++++++-------
1 file changed, 10 insertions(+), 7 deletions(-)
diff --git a/drivers/base/power/domain.c b/drivers/base/power/domain.c
index da49a8383dc3..2e8d0f423507 100644
--- a/drivers/base/power/domain.c
+++ b/drivers/base/power/domain.c
@@ -126,7 +126,7 @@ static const struct genpd_lock_ops genpd_spin_ops = {
#define genpd_is_always_on(genpd) (genpd->flags & GENPD_FLAG_ALWAYS_ON)
static inline bool irq_safe_dev_in_no_sleep_domain(struct device *dev,
- struct generic_pm_domain *genpd)
+ const struct generic_pm_domain *genpd)
{
bool ret;
@@ -181,12 +181,14 @@ static struct generic_pm_domain *dev_to_genpd(struct device *dev)
return pd_to_genpd(dev->pm_domain);
}
-static int genpd_stop_dev(struct generic_pm_domain *genpd, struct device *dev)
+static int genpd_stop_dev(const struct generic_pm_domain *genpd,
+ struct device *dev)
{
return GENPD_DEV_CALLBACK(genpd, int, stop, dev);
}
-static int genpd_start_dev(struct generic_pm_domain *genpd, struct device *dev)
+static int genpd_start_dev(const struct generic_pm_domain *genpd,
+ struct device *dev)
{
return GENPD_DEV_CALLBACK(genpd, int, start, dev);
}
@@ -738,7 +740,7 @@ static bool pm_genpd_present(const struct generic_pm_domain *genpd)
#ifdef CONFIG_PM_SLEEP
-static bool genpd_dev_active_wakeup(struct generic_pm_domain *genpd,
+static bool genpd_dev_active_wakeup(const struct generic_pm_domain *genpd,
struct device *dev)
{
return GENPD_DEV_CALLBACK(genpd, bool, active_wakeup, dev);
@@ -840,7 +842,8 @@ static void genpd_sync_power_on(struct generic_pm_domain *genpd, bool use_lock,
* signal remote wakeup from the system's working state as needed by runtime PM.
* Return 'true' in either of the above cases.
*/
-static bool resume_needed(struct device *dev, struct generic_pm_domain *genpd)
+static bool resume_needed(struct device *dev,
+ const struct generic_pm_domain *genpd)
{
bool active_wakeup;
@@ -975,7 +978,7 @@ static int pm_genpd_resume_noirq(struct device *dev)
*/
static int pm_genpd_freeze_noirq(struct device *dev)
{
- struct generic_pm_domain *genpd;
+ const struct generic_pm_domain *genpd;
int ret = 0;
dev_dbg(dev, "%s()\n", __func__);
@@ -999,7 +1002,7 @@ static int pm_genpd_freeze_noirq(struct device *dev)
*/
static int pm_genpd_thaw_noirq(struct device *dev)
{
- struct generic_pm_domain *genpd;
+ const struct generic_pm_domain *genpd;
int ret = 0;
dev_dbg(dev, "%s()\n", __func__);
--
2.9.3
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH 2/8] PM / domains: Protect reading loop over list of domains
2017-06-09 16:08 [PATCH 0/8] PM / Domains: Bunch of small improvements and fixes Krzysztof Kozlowski
2017-06-09 16:08 ` [PATCH 1/8] PM / Domains: Constify genpd pointer Krzysztof Kozlowski
@ 2017-06-09 16:08 ` Krzysztof Kozlowski
2017-06-09 16:16 ` Krzysztof Kozlowski
2017-06-09 16:08 ` [PATCH 3/8] PM / domains: Add lockdep asserts for domains list mutex Krzysztof Kozlowski
` (5 subsequent siblings)
7 siblings, 1 reply; 12+ messages in thread
From: Krzysztof Kozlowski @ 2017-06-09 16:08 UTC (permalink / raw)
To: Rafael J. Wysocki, Kevin Hilman, Ulf Hansson, Pavel Machek,
Len Brown, Greg Kroah-Hartman, linux-pm, linux-kernel
Cc: Krzysztof Kozlowski
The pm_genpd_present() iterates over list of domains so grabbing a
gpd_list_lock mutex is necessary before calling it. Otherwise we could
end up in iterating over and modifying the list at the same time.
Signed-off-by: Krzysztof Kozlowski <krzk@kernel.org>
---
drivers/base/power/domain.c | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/drivers/base/power/domain.c b/drivers/base/power/domain.c
index 2e8d0f423507..2a6935dc0164 100644
--- a/drivers/base/power/domain.c
+++ b/drivers/base/power/domain.c
@@ -1099,8 +1099,13 @@ static void genpd_syscore_switch(struct device *dev, bool suspend)
struct generic_pm_domain *genpd;
genpd = dev_to_genpd(dev);
- if (!pm_genpd_present(genpd))
+
+ mutex_lock(&gpd_list_lock);
+ if (!pm_genpd_present(genpd)) {
+ mutex_unlock(&gpd_list_lock);
return;
+ }
+ mutex_unlock(&gpd_list_lock);
if (suspend) {
genpd->suspended_count++;
--
2.9.3
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH 3/8] PM / domains: Add lockdep asserts for domains list mutex
2017-06-09 16:08 [PATCH 0/8] PM / Domains: Bunch of small improvements and fixes Krzysztof Kozlowski
2017-06-09 16:08 ` [PATCH 1/8] PM / Domains: Constify genpd pointer Krzysztof Kozlowski
2017-06-09 16:08 ` [PATCH 2/8] PM / domains: Protect reading loop over list of domains Krzysztof Kozlowski
@ 2017-06-09 16:08 ` Krzysztof Kozlowski
2017-06-09 16:08 ` [PATCH 4/8] PM / domains: Fix unsafe iteration over modified list of device links Krzysztof Kozlowski
` (4 subsequent siblings)
7 siblings, 0 replies; 12+ messages in thread
From: Krzysztof Kozlowski @ 2017-06-09 16:08 UTC (permalink / raw)
To: Rafael J. Wysocki, Kevin Hilman, Ulf Hansson, Pavel Machek,
Len Brown, Greg Kroah-Hartman, linux-pm, linux-kernel
Cc: Krzysztof Kozlowski
Add lockdep checks for holding mutex protecting the list of domains.
This might expose misuse even though only file-scope functions use it
for now.
Signed-off-by: Krzysztof Kozlowski <krzk@kernel.org>
---
drivers/base/power/domain.c | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/drivers/base/power/domain.c b/drivers/base/power/domain.c
index 2a6935dc0164..0f416563479b 100644
--- a/drivers/base/power/domain.c
+++ b/drivers/base/power/domain.c
@@ -726,6 +726,8 @@ static bool pm_genpd_present(const struct generic_pm_domain *genpd)
{
const struct generic_pm_domain *gpd;
+ lockdep_assert_held(&gpd_list_lock);
+
if (IS_ERR_OR_NULL(genpd))
return false;
@@ -1326,6 +1328,8 @@ static int genpd_add_subdomain(struct generic_pm_domain *genpd,
struct gpd_link *link, *itr;
int ret = 0;
+ lockdep_assert_held(&gpd_list_lock);
+
if (IS_ERR_OR_NULL(genpd) || IS_ERR_OR_NULL(subdomain)
|| genpd == subdomain)
return -EINVAL;
@@ -1533,6 +1537,8 @@ static int genpd_remove(struct generic_pm_domain *genpd)
{
struct gpd_link *l, *link;
+ lockdep_assert_held(&gpd_list_lock);
+
if (IS_ERR_OR_NULL(genpd))
return -EINVAL;
--
2.9.3
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH 4/8] PM / domains: Fix unsafe iteration over modified list of device links
2017-06-09 16:08 [PATCH 0/8] PM / Domains: Bunch of small improvements and fixes Krzysztof Kozlowski
` (2 preceding siblings ...)
2017-06-09 16:08 ` [PATCH 3/8] PM / domains: Add lockdep asserts for domains list mutex Krzysztof Kozlowski
@ 2017-06-09 16:08 ` Krzysztof Kozlowski
2017-06-09 16:08 ` [PATCH 5/8] PM / domains: Fix unsafe iteration over modified list of domain providers Krzysztof Kozlowski
` (3 subsequent siblings)
7 siblings, 0 replies; 12+ messages in thread
From: Krzysztof Kozlowski @ 2017-06-09 16:08 UTC (permalink / raw)
To: Rafael J. Wysocki, Kevin Hilman, Ulf Hansson, Pavel Machek,
Len Brown, Greg Kroah-Hartman, linux-pm, linux-kernel
Cc: Krzysztof Kozlowski, stable
pm_genpd_remove_subdomain() iterates over domain's master_links list and
removes matching element thus it has to use safe version of list
iteration.
Fixes: f721889ff65a ("PM / Domains: Support for generic I/O PM domains (v8)")
Cc: <stable@vger.kernel.org>
Signed-off-by: Krzysztof Kozlowski <krzk@kernel.org>
---
drivers/base/power/domain.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/base/power/domain.c b/drivers/base/power/domain.c
index 0f416563479b..325962702bc8 100644
--- a/drivers/base/power/domain.c
+++ b/drivers/base/power/domain.c
@@ -1405,7 +1405,7 @@ EXPORT_SYMBOL_GPL(pm_genpd_add_subdomain);
int pm_genpd_remove_subdomain(struct generic_pm_domain *genpd,
struct generic_pm_domain *subdomain)
{
- struct gpd_link *link;
+ struct gpd_link *l, *link;
int ret = -EINVAL;
if (IS_ERR_OR_NULL(genpd) || IS_ERR_OR_NULL(subdomain))
@@ -1421,7 +1421,7 @@ int pm_genpd_remove_subdomain(struct generic_pm_domain *genpd,
goto out;
}
- list_for_each_entry(link, &genpd->master_links, master_node) {
+ list_for_each_entry_safe(link, l, &genpd->master_links, master_node) {
if (link->slave != subdomain)
continue;
--
2.9.3
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH 5/8] PM / domains: Fix unsafe iteration over modified list of domain providers
2017-06-09 16:08 [PATCH 0/8] PM / Domains: Bunch of small improvements and fixes Krzysztof Kozlowski
` (3 preceding siblings ...)
2017-06-09 16:08 ` [PATCH 4/8] PM / domains: Fix unsafe iteration over modified list of device links Krzysztof Kozlowski
@ 2017-06-09 16:08 ` Krzysztof Kozlowski
2017-06-09 16:08 ` [PATCH 6/8] PM / domains: Fix unsafe iteration over modified list of domains Krzysztof Kozlowski
` (2 subsequent siblings)
7 siblings, 0 replies; 12+ messages in thread
From: Krzysztof Kozlowski @ 2017-06-09 16:08 UTC (permalink / raw)
To: Rafael J. Wysocki, Kevin Hilman, Ulf Hansson, Pavel Machek,
Len Brown, Greg Kroah-Hartman, linux-pm, linux-kernel
Cc: Krzysztof Kozlowski, stable
of_genpd_del_provider() iterates over list of domain provides and
removes matching element thus it has to use safe version of list
iteration.
Fixes: aa42240ab254 ("PM / Domains: Add generic OF-based PM domain look-up")
Cc: <stable@vger.kernel.org>
Signed-off-by: Krzysztof Kozlowski <krzk@kernel.org>
---
drivers/base/power/domain.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/base/power/domain.c b/drivers/base/power/domain.c
index 325962702bc8..e426ceff1a59 100644
--- a/drivers/base/power/domain.c
+++ b/drivers/base/power/domain.c
@@ -1794,12 +1794,12 @@ EXPORT_SYMBOL_GPL(of_genpd_add_provider_onecell);
*/
void of_genpd_del_provider(struct device_node *np)
{
- struct of_genpd_provider *cp;
+ struct of_genpd_provider *cp, *tmp;
struct generic_pm_domain *gpd;
mutex_lock(&gpd_list_lock);
mutex_lock(&of_genpd_mutex);
- list_for_each_entry(cp, &of_genpd_providers, link) {
+ list_for_each_entry_safe(cp, tmp, &of_genpd_providers, link) {
if (cp->node == np) {
/*
* For each PM domain associated with the
--
2.9.3
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH 6/8] PM / domains: Fix unsafe iteration over modified list of domains
2017-06-09 16:08 [PATCH 0/8] PM / Domains: Bunch of small improvements and fixes Krzysztof Kozlowski
` (4 preceding siblings ...)
2017-06-09 16:08 ` [PATCH 5/8] PM / domains: Fix unsafe iteration over modified list of domain providers Krzysztof Kozlowski
@ 2017-06-09 16:08 ` Krzysztof Kozlowski
2017-06-09 16:08 ` [PATCH 7/8] PM / domains: Fix missing default_power_down_ok comment Krzysztof Kozlowski
2017-06-09 16:08 ` [RFC 8/8] PM / Domains: Add asserts for PM domain locks Krzysztof Kozlowski
7 siblings, 0 replies; 12+ messages in thread
From: Krzysztof Kozlowski @ 2017-06-09 16:08 UTC (permalink / raw)
To: Rafael J. Wysocki, Kevin Hilman, Ulf Hansson, Pavel Machek,
Len Brown, Greg Kroah-Hartman, linux-pm, linux-kernel
Cc: Krzysztof Kozlowski, stable
of_genpd_remove_last() iterates over list of domains and removes
matching element thus it has to use safe version of list iteration.
Fixes: 17926551c98a ("PM / Domains: Add support for removing nested PM domains by provider")
Cc: <stable@vger.kernel.org>
Signed-off-by: Krzysztof Kozlowski <krzk@kernel.org>
---
drivers/base/power/domain.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/base/power/domain.c b/drivers/base/power/domain.c
index e426ceff1a59..c1e22b613287 100644
--- a/drivers/base/power/domain.c
+++ b/drivers/base/power/domain.c
@@ -1939,14 +1939,14 @@ EXPORT_SYMBOL_GPL(of_genpd_add_subdomain);
*/
struct generic_pm_domain *of_genpd_remove_last(struct device_node *np)
{
- struct generic_pm_domain *gpd, *genpd = ERR_PTR(-ENOENT);
+ struct generic_pm_domain *gpd, *tmp, *genpd = ERR_PTR(-ENOENT);
int ret;
if (IS_ERR_OR_NULL(np))
return ERR_PTR(-EINVAL);
mutex_lock(&gpd_list_lock);
- list_for_each_entry(gpd, &gpd_list, gpd_list_node) {
+ list_for_each_entry_safe(gpd, tmp, &gpd_list, gpd_list_node) {
if (gpd->provider == &np->fwnode) {
ret = genpd_remove(gpd);
genpd = ret ? ERR_PTR(ret) : gpd;
--
2.9.3
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH 7/8] PM / domains: Fix missing default_power_down_ok comment
2017-06-09 16:08 [PATCH 0/8] PM / Domains: Bunch of small improvements and fixes Krzysztof Kozlowski
` (5 preceding siblings ...)
2017-06-09 16:08 ` [PATCH 6/8] PM / domains: Fix unsafe iteration over modified list of domains Krzysztof Kozlowski
@ 2017-06-09 16:08 ` Krzysztof Kozlowski
2017-06-09 16:08 ` [RFC 8/8] PM / Domains: Add asserts for PM domain locks Krzysztof Kozlowski
7 siblings, 0 replies; 12+ messages in thread
From: Krzysztof Kozlowski @ 2017-06-09 16:08 UTC (permalink / raw)
To: Rafael J. Wysocki, Kevin Hilman, Ulf Hansson, Pavel Machek,
Len Brown, Greg Kroah-Hartman, linux-pm, linux-kernel
Cc: Krzysztof Kozlowski
Commit fc5cbf0c94b6 ("PM / Domains: Support for multiple states") split
out some code out of default_power_down_ok() function so the
documentation has to be moved to appropriate place.
Signed-off-by: Krzysztof Kozlowski <krzk@kernel.org>
---
drivers/base/power/domain_governor.c | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/drivers/base/power/domain_governor.c b/drivers/base/power/domain_governor.c
index 2e0fce711135..281f949c5ffe 100644
--- a/drivers/base/power/domain_governor.c
+++ b/drivers/base/power/domain_governor.c
@@ -92,12 +92,6 @@ static bool default_suspend_ok(struct device *dev)
return td->cached_suspend_ok;
}
-/**
- * default_power_down_ok - Default generic PM domain power off governor routine.
- * @pd: PM domain to check.
- *
- * This routine must be executed under the PM domain's lock.
- */
static bool __default_power_down_ok(struct dev_pm_domain *pd,
unsigned int state)
{
@@ -187,6 +181,12 @@ static bool __default_power_down_ok(struct dev_pm_domain *pd,
return true;
}
+/**
+ * default_power_down_ok - Default generic PM domain power off governor routine.
+ * @pd: PM domain to check.
+ *
+ * This routine must be executed under the PM domain's lock.
+ */
static bool default_power_down_ok(struct dev_pm_domain *pd)
{
struct generic_pm_domain *genpd = pd_to_genpd(pd);
--
2.9.3
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [RFC 8/8] PM / Domains: Add asserts for PM domain locks
2017-06-09 16:08 [PATCH 0/8] PM / Domains: Bunch of small improvements and fixes Krzysztof Kozlowski
` (6 preceding siblings ...)
2017-06-09 16:08 ` [PATCH 7/8] PM / domains: Fix missing default_power_down_ok comment Krzysztof Kozlowski
@ 2017-06-09 16:08 ` Krzysztof Kozlowski
7 siblings, 0 replies; 12+ messages in thread
From: Krzysztof Kozlowski @ 2017-06-09 16:08 UTC (permalink / raw)
To: Rafael J. Wysocki, Kevin Hilman, Ulf Hansson, Pavel Machek,
Len Brown, Greg Kroah-Hartman, linux-pm, linux-kernel
Cc: Krzysztof Kozlowski
Add lockdep checks for holding domain lock in few places where this is
required. This might expose misuse even though only file-scope
functions use it for now.
Regular lockdep asserts can be entirely discarded by preprocessor, however
domain code uses mixed type of lock: spinlock or mutex. This means that
these asserts will not be thrown away entirely. Instead, always
at least two pointer dereferences (p->lock_ops->assert_held) and
probably one function call (assert_held()) will be made.
Signed-off-by: Krzysztof Kozlowski <krzk@kernel.org>
---
drivers/base/power/domain.c | 24 ++++++++++++++++++++++++
1 file changed, 24 insertions(+)
diff --git a/drivers/base/power/domain.c b/drivers/base/power/domain.c
index c1e22b613287..17fecfd44607 100644
--- a/drivers/base/power/domain.c
+++ b/drivers/base/power/domain.c
@@ -40,12 +40,18 @@ static LIST_HEAD(gpd_list);
static DEFINE_MUTEX(gpd_list_lock);
struct genpd_lock_ops {
+ void (*assert_held)(struct generic_pm_domain *genpd);
void (*lock)(struct generic_pm_domain *genpd);
void (*lock_nested)(struct generic_pm_domain *genpd, int depth);
int (*lock_interruptible)(struct generic_pm_domain *genpd);
void (*unlock)(struct generic_pm_domain *genpd);
};
+static void genpd_assert_held_mtx(struct generic_pm_domain *genpd)
+{
+ lockdep_assert_held(&genpd->mlock);
+}
+
static void genpd_lock_mtx(struct generic_pm_domain *genpd)
{
mutex_lock(&genpd->mlock);
@@ -68,12 +74,18 @@ static void genpd_unlock_mtx(struct generic_pm_domain *genpd)
}
static const struct genpd_lock_ops genpd_mtx_ops = {
+ .assert_held = genpd_assert_held_mtx,
.lock = genpd_lock_mtx,
.lock_nested = genpd_lock_nested_mtx,
.lock_interruptible = genpd_lock_interruptible_mtx,
.unlock = genpd_unlock_mtx,
};
+static void genpd_assert_held_spin(struct generic_pm_domain *genpd)
+{
+ lockdep_assert_held(&genpd->slock);
+}
+
static void genpd_lock_spin(struct generic_pm_domain *genpd)
__acquires(&genpd->slock)
{
@@ -110,12 +122,14 @@ static void genpd_unlock_spin(struct generic_pm_domain *genpd)
}
static const struct genpd_lock_ops genpd_spin_ops = {
+ .assert_held = genpd_assert_held_spin,
.lock = genpd_lock_spin,
.lock_nested = genpd_lock_nested_spin,
.lock_interruptible = genpd_lock_interruptible_spin,
.unlock = genpd_unlock_spin,
};
+#define genpd_assert_held(p) p->lock_ops->assert_held(p)
#define genpd_lock(p) p->lock_ops->lock(p)
#define genpd_lock_nested(p, d) p->lock_ops->lock_nested(p, d)
#define genpd_lock_interruptible(p) p->lock_ops->lock_interruptible(p)
@@ -299,6 +313,8 @@ static int genpd_power_off(struct generic_pm_domain *genpd, bool one_dev_on,
struct gpd_link *link;
unsigned int not_suspended = 0;
+ genpd_assert_held(genpd);
+
/*
* Do not try to power off the domain in the following situations:
* (1) The domain is already in the "power off" state.
@@ -385,6 +401,8 @@ static int genpd_power_on(struct generic_pm_domain *genpd, unsigned int depth)
struct gpd_link *link;
int ret = 0;
+ genpd_assert_held(genpd);
+
if (genpd_status_on(genpd))
return 0;
@@ -766,6 +784,9 @@ static void genpd_sync_power_off(struct generic_pm_domain *genpd, bool use_lock,
{
struct gpd_link *link;
+ if (use_lock)
+ genpd_assert_held(genpd);
+
if (!genpd_status_on(genpd) || genpd_is_always_on(genpd))
return;
@@ -808,6 +829,9 @@ static void genpd_sync_power_on(struct generic_pm_domain *genpd, bool use_lock,
{
struct gpd_link *link;
+ if (use_lock)
+ genpd_assert_held(genpd);
+
if (genpd_status_on(genpd))
return;
--
2.9.3
^ permalink raw reply related [flat|nested] 12+ messages in thread
* Re: [PATCH 2/8] PM / domains: Protect reading loop over list of domains
2017-06-09 16:08 ` [PATCH 2/8] PM / domains: Protect reading loop over list of domains Krzysztof Kozlowski
@ 2017-06-09 16:16 ` Krzysztof Kozlowski
2017-06-12 12:57 ` Ulf Hansson
0 siblings, 1 reply; 12+ messages in thread
From: Krzysztof Kozlowski @ 2017-06-09 16:16 UTC (permalink / raw)
To: Rafael J. Wysocki, Kevin Hilman, Ulf Hansson, Pavel Machek,
Len Brown, Greg Kroah-Hartman, linux-pm, linux-kernel
On Fri, Jun 09, 2017 at 06:08:47PM +0200, Krzysztof Kozlowski wrote:
> The pm_genpd_present() iterates over list of domains so grabbing a
> gpd_list_lock mutex is necessary before calling it. Otherwise we could
> end up in iterating over and modifying the list at the same time.
>
> Signed-off-by: Krzysztof Kozlowski <krzk@kernel.org>
> ---
> drivers/base/power/domain.c | 7 ++++++-
> 1 file changed, 6 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/base/power/domain.c b/drivers/base/power/domain.c
> index 2e8d0f423507..2a6935dc0164 100644
> --- a/drivers/base/power/domain.c
> +++ b/drivers/base/power/domain.c
> @@ -1099,8 +1099,13 @@ static void genpd_syscore_switch(struct device *dev, bool suspend)
> struct generic_pm_domain *genpd;
>
> genpd = dev_to_genpd(dev);
> - if (!pm_genpd_present(genpd))
> +
> + mutex_lock(&gpd_list_lock);
> + if (!pm_genpd_present(genpd)) {
> + mutex_unlock(&gpd_list_lock);
> return;
> + }
> + mutex_unlock(&gpd_list_lock);
Eh, I might be too fast as this is not executed on my platform. The
genpd_syscore_switch() seems to be called by clocksource_suspend() which
is called by syscore ops. Should be safe but actually not tested.
Someone with SH hardware is needed...
Best regards,
Krzysztof
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH 2/8] PM / domains: Protect reading loop over list of domains
2017-06-09 16:16 ` Krzysztof Kozlowski
@ 2017-06-12 12:57 ` Ulf Hansson
2017-06-12 13:10 ` Krzysztof Kozlowski
0 siblings, 1 reply; 12+ messages in thread
From: Ulf Hansson @ 2017-06-12 12:57 UTC (permalink / raw)
To: Krzysztof Kozlowski
Cc: Rafael J. Wysocki, Kevin Hilman, Pavel Machek, Len Brown,
Greg Kroah-Hartman, linux-pm@vger.kernel.org,
linux-kernel@vger.kernel.org
On 9 June 2017 at 18:16, Krzysztof Kozlowski <krzk@kernel.org> wrote:
> On Fri, Jun 09, 2017 at 06:08:47PM +0200, Krzysztof Kozlowski wrote:
>> The pm_genpd_present() iterates over list of domains so grabbing a
>> gpd_list_lock mutex is necessary before calling it. Otherwise we could
>> end up in iterating over and modifying the list at the same time.
>>
>> Signed-off-by: Krzysztof Kozlowski <krzk@kernel.org>
>> ---
>> drivers/base/power/domain.c | 7 ++++++-
>> 1 file changed, 6 insertions(+), 1 deletion(-)
>>
>> diff --git a/drivers/base/power/domain.c b/drivers/base/power/domain.c
>> index 2e8d0f423507..2a6935dc0164 100644
>> --- a/drivers/base/power/domain.c
>> +++ b/drivers/base/power/domain.c
>> @@ -1099,8 +1099,13 @@ static void genpd_syscore_switch(struct device *dev, bool suspend)
>> struct generic_pm_domain *genpd;
>>
>> genpd = dev_to_genpd(dev);
Actually there may be potential problem here as we may end up trying
to use the container_of() call for a PM domain, not being a genpd but
something else.
>> - if (!pm_genpd_present(genpd))
>> +
>> + mutex_lock(&gpd_list_lock);
>> + if (!pm_genpd_present(genpd)) {
>> + mutex_unlock(&gpd_list_lock);
>> return;
>> + }
>> + mutex_unlock(&gpd_list_lock);
Perhaps convert the hole thing above to call genpd_lookup_dev() instead?
>
> Eh, I might be too fast as this is not executed on my platform. The
> genpd_syscore_switch() seems to be called by clocksource_suspend() which
> is called by syscore ops. Should be safe but actually not tested.
>
> Someone with SH hardware is needed...
>
> Best regards,
> Krzysztof
>
Kind regards
Uffe
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH 2/8] PM / domains: Protect reading loop over list of domains
2017-06-12 12:57 ` Ulf Hansson
@ 2017-06-12 13:10 ` Krzysztof Kozlowski
0 siblings, 0 replies; 12+ messages in thread
From: Krzysztof Kozlowski @ 2017-06-12 13:10 UTC (permalink / raw)
To: Ulf Hansson
Cc: Rafael J. Wysocki, Kevin Hilman, Pavel Machek, Len Brown,
Greg Kroah-Hartman, linux-pm@vger.kernel.org,
linux-kernel@vger.kernel.org
On Mon, Jun 12, 2017 at 02:57:21PM +0200, Ulf Hansson wrote:
> On 9 June 2017 at 18:16, Krzysztof Kozlowski <krzk@kernel.org> wrote:
> > On Fri, Jun 09, 2017 at 06:08:47PM +0200, Krzysztof Kozlowski wrote:
> >> The pm_genpd_present() iterates over list of domains so grabbing a
> >> gpd_list_lock mutex is necessary before calling it. Otherwise we could
> >> end up in iterating over and modifying the list at the same time.
> >>
> >> Signed-off-by: Krzysztof Kozlowski <krzk@kernel.org>
> >> ---
> >> drivers/base/power/domain.c | 7 ++++++-
> >> 1 file changed, 6 insertions(+), 1 deletion(-)
> >>
> >> diff --git a/drivers/base/power/domain.c b/drivers/base/power/domain.c
> >> index 2e8d0f423507..2a6935dc0164 100644
> >> --- a/drivers/base/power/domain.c
> >> +++ b/drivers/base/power/domain.c
> >> @@ -1099,8 +1099,13 @@ static void genpd_syscore_switch(struct device *dev, bool suspend)
> >> struct generic_pm_domain *genpd;
> >>
> >> genpd = dev_to_genpd(dev);
>
> Actually there may be potential problem here as we may end up trying
> to use the container_of() call for a PM domain, not being a genpd but
> something else.
>
> >> - if (!pm_genpd_present(genpd))
> >> +
> >> + mutex_lock(&gpd_list_lock);
> >> + if (!pm_genpd_present(genpd)) {
> >> + mutex_unlock(&gpd_list_lock);
> >> return;
> >> + }
> >> + mutex_unlock(&gpd_list_lock);
>
> Perhaps convert the hole thing above to call genpd_lookup_dev() instead?
Indeed, that would solve both problems. Thanks, I'll fix this.
Best regards,
Krzysztof
^ permalink raw reply [flat|nested] 12+ messages in thread
end of thread, other threads:[~2017-06-12 13:10 UTC | newest]
Thread overview: 12+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2017-06-09 16:08 [PATCH 0/8] PM / Domains: Bunch of small improvements and fixes Krzysztof Kozlowski
2017-06-09 16:08 ` [PATCH 1/8] PM / Domains: Constify genpd pointer Krzysztof Kozlowski
2017-06-09 16:08 ` [PATCH 2/8] PM / domains: Protect reading loop over list of domains Krzysztof Kozlowski
2017-06-09 16:16 ` Krzysztof Kozlowski
2017-06-12 12:57 ` Ulf Hansson
2017-06-12 13:10 ` Krzysztof Kozlowski
2017-06-09 16:08 ` [PATCH 3/8] PM / domains: Add lockdep asserts for domains list mutex Krzysztof Kozlowski
2017-06-09 16:08 ` [PATCH 4/8] PM / domains: Fix unsafe iteration over modified list of device links Krzysztof Kozlowski
2017-06-09 16:08 ` [PATCH 5/8] PM / domains: Fix unsafe iteration over modified list of domain providers Krzysztof Kozlowski
2017-06-09 16:08 ` [PATCH 6/8] PM / domains: Fix unsafe iteration over modified list of domains Krzysztof Kozlowski
2017-06-09 16:08 ` [PATCH 7/8] PM / domains: Fix missing default_power_down_ok comment Krzysztof Kozlowski
2017-06-09 16:08 ` [RFC 8/8] PM / Domains: Add asserts for PM domain locks Krzysztof Kozlowski
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).