projects
/
firefly-linux-kernel-4.4.55.git
/ blobdiff
commit
grep
author
committer
pickaxe
?
search:
re
summary
|
shortlog
|
log
|
commit
|
commitdiff
|
tree
raw
|
inline
| side by side
PM / Domains: Avoid infinite loops in attach/detach code
[firefly-linux-kernel-4.4.55.git]
/
drivers
/
base
/
power
/
domain.c
diff --git
a/drivers/base/power/domain.c
b/drivers/base/power/domain.c
index cdd547bd67df82184dd201b4e1cf9626cf90dd2e..0ee43c1056e045bd6a402908e8a11cf9dac8f34e 100644
(file)
--- a/
drivers/base/power/domain.c
+++ b/
drivers/base/power/domain.c
@@
-6,6
+6,7
@@
* This file is released under the GPLv2.
*/
* This file is released under the GPLv2.
*/
+#include <linux/delay.h>
#include <linux/kernel.h>
#include <linux/io.h>
#include <linux/platform_device.h>
#include <linux/kernel.h>
#include <linux/io.h>
#include <linux/platform_device.h>
@@
-19,6
+20,8
@@
#include <linux/suspend.h>
#include <linux/export.h>
#include <linux/suspend.h>
#include <linux/export.h>
+#define GENPD_RETRY_MAX_MS 250 /* Approximate */
+
#define GENPD_DEV_CALLBACK(genpd, type, callback, dev) \
({ \
type (*__routine)(struct device *__d); \
#define GENPD_DEV_CALLBACK(genpd, type, callback, dev) \
({ \
type (*__routine)(struct device *__d); \
@@
-2131,6
+2134,7
@@
EXPORT_SYMBOL_GPL(of_genpd_get_from_provider);
static void genpd_dev_pm_detach(struct device *dev, bool power_off)
{
struct generic_pm_domain *pd;
static void genpd_dev_pm_detach(struct device *dev, bool power_off)
{
struct generic_pm_domain *pd;
+ unsigned int i;
int ret = 0;
pd = pm_genpd_lookup_dev(dev);
int ret = 0;
pd = pm_genpd_lookup_dev(dev);
@@
-2139,10
+2143,12
@@
static void genpd_dev_pm_detach(struct device *dev, bool power_off)
dev_dbg(dev, "removing from PM domain %s\n", pd->name);
dev_dbg(dev, "removing from PM domain %s\n", pd->name);
-
while (
1) {
+
for (i = 1; i < GENPD_RETRY_MAX_MS; i <<=
1) {
ret = pm_genpd_remove_device(pd, dev);
if (ret != -EAGAIN)
break;
ret = pm_genpd_remove_device(pd, dev);
if (ret != -EAGAIN)
break;
+
+ mdelay(i);
cond_resched();
}
cond_resched();
}
@@
-2183,6
+2189,7
@@
int genpd_dev_pm_attach(struct device *dev)
{
struct of_phandle_args pd_args;
struct generic_pm_domain *pd;
{
struct of_phandle_args pd_args;
struct generic_pm_domain *pd;
+ unsigned int i;
int ret;
if (!dev->of_node)
int ret;
if (!dev->of_node)
@@
-2218,10
+2225,12
@@
int genpd_dev_pm_attach(struct device *dev)
dev_dbg(dev, "adding to PM domain %s\n", pd->name);
dev_dbg(dev, "adding to PM domain %s\n", pd->name);
-
while (
1) {
+
for (i = 1; i < GENPD_RETRY_MAX_MS; i <<=
1) {
ret = pm_genpd_add_device(pd, dev);
if (ret != -EAGAIN)
break;
ret = pm_genpd_add_device(pd, dev);
if (ret != -EAGAIN)
break;
+
+ mdelay(i);
cond_resched();
}
cond_resched();
}