Commit 6cb437ac authored by Rafael J. Wysocki's avatar Rafael J. Wysocki

Merge branch 'pm-fixes' into fixes

* pm-fixes:
  cpufreq: Correct header guards typo
  cpufreq: check OF node /cpus presence before dereferencing it
  PM / devfreq: Fix compiler warnings for CONFIG_PM_DEVFREQ unset
  PM / QoS: Avoid possible deadlock related to sysfs access
  USB / PM: Don't try to hide PM QoS flags from usb_port_device_release()
parents fc1a7fe8 beb0ff39
...@@ -46,6 +46,7 @@ ...@@ -46,6 +46,7 @@
#include "power.h" #include "power.h"
static DEFINE_MUTEX(dev_pm_qos_mtx); static DEFINE_MUTEX(dev_pm_qos_mtx);
static DEFINE_MUTEX(dev_pm_qos_sysfs_mtx);
static BLOCKING_NOTIFIER_HEAD(dev_pm_notifiers); static BLOCKING_NOTIFIER_HEAD(dev_pm_notifiers);
...@@ -216,12 +217,17 @@ void dev_pm_qos_constraints_destroy(struct device *dev) ...@@ -216,12 +217,17 @@ void dev_pm_qos_constraints_destroy(struct device *dev)
struct pm_qos_constraints *c; struct pm_qos_constraints *c;
struct pm_qos_flags *f; struct pm_qos_flags *f;
mutex_lock(&dev_pm_qos_mtx); mutex_lock(&dev_pm_qos_sysfs_mtx);
/* /*
* If the device's PM QoS resume latency limit or PM QoS flags have been * If the device's PM QoS resume latency limit or PM QoS flags have been
* exposed to user space, they have to be hidden at this point. * exposed to user space, they have to be hidden at this point.
*/ */
pm_qos_sysfs_remove_latency(dev);
pm_qos_sysfs_remove_flags(dev);
mutex_lock(&dev_pm_qos_mtx);
__dev_pm_qos_hide_latency_limit(dev); __dev_pm_qos_hide_latency_limit(dev);
__dev_pm_qos_hide_flags(dev); __dev_pm_qos_hide_flags(dev);
...@@ -254,6 +260,8 @@ void dev_pm_qos_constraints_destroy(struct device *dev) ...@@ -254,6 +260,8 @@ void dev_pm_qos_constraints_destroy(struct device *dev)
out: out:
mutex_unlock(&dev_pm_qos_mtx); mutex_unlock(&dev_pm_qos_mtx);
mutex_unlock(&dev_pm_qos_sysfs_mtx);
} }
/** /**
...@@ -558,6 +566,14 @@ static void __dev_pm_qos_drop_user_request(struct device *dev, ...@@ -558,6 +566,14 @@ static void __dev_pm_qos_drop_user_request(struct device *dev,
kfree(req); kfree(req);
} }
static void dev_pm_qos_drop_user_request(struct device *dev,
enum dev_pm_qos_req_type type)
{
mutex_lock(&dev_pm_qos_mtx);
__dev_pm_qos_drop_user_request(dev, type);
mutex_unlock(&dev_pm_qos_mtx);
}
/** /**
* dev_pm_qos_expose_latency_limit - Expose PM QoS latency limit to user space. * dev_pm_qos_expose_latency_limit - Expose PM QoS latency limit to user space.
* @dev: Device whose PM QoS latency limit is to be exposed to user space. * @dev: Device whose PM QoS latency limit is to be exposed to user space.
...@@ -581,6 +597,8 @@ int dev_pm_qos_expose_latency_limit(struct device *dev, s32 value) ...@@ -581,6 +597,8 @@ int dev_pm_qos_expose_latency_limit(struct device *dev, s32 value)
return ret; return ret;
} }
mutex_lock(&dev_pm_qos_sysfs_mtx);
mutex_lock(&dev_pm_qos_mtx); mutex_lock(&dev_pm_qos_mtx);
if (IS_ERR_OR_NULL(dev->power.qos)) if (IS_ERR_OR_NULL(dev->power.qos))
...@@ -591,26 +609,27 @@ int dev_pm_qos_expose_latency_limit(struct device *dev, s32 value) ...@@ -591,26 +609,27 @@ int dev_pm_qos_expose_latency_limit(struct device *dev, s32 value)
if (ret < 0) { if (ret < 0) {
__dev_pm_qos_remove_request(req); __dev_pm_qos_remove_request(req);
kfree(req); kfree(req);
mutex_unlock(&dev_pm_qos_mtx);
goto out; goto out;
} }
dev->power.qos->latency_req = req; dev->power.qos->latency_req = req;
mutex_unlock(&dev_pm_qos_mtx);
ret = pm_qos_sysfs_add_latency(dev); ret = pm_qos_sysfs_add_latency(dev);
if (ret) if (ret)
__dev_pm_qos_drop_user_request(dev, DEV_PM_QOS_LATENCY); dev_pm_qos_drop_user_request(dev, DEV_PM_QOS_LATENCY);
out: out:
mutex_unlock(&dev_pm_qos_mtx); mutex_unlock(&dev_pm_qos_sysfs_mtx);
return ret; return ret;
} }
EXPORT_SYMBOL_GPL(dev_pm_qos_expose_latency_limit); EXPORT_SYMBOL_GPL(dev_pm_qos_expose_latency_limit);
static void __dev_pm_qos_hide_latency_limit(struct device *dev) static void __dev_pm_qos_hide_latency_limit(struct device *dev)
{ {
if (!IS_ERR_OR_NULL(dev->power.qos) && dev->power.qos->latency_req) { if (!IS_ERR_OR_NULL(dev->power.qos) && dev->power.qos->latency_req)
pm_qos_sysfs_remove_latency(dev);
__dev_pm_qos_drop_user_request(dev, DEV_PM_QOS_LATENCY); __dev_pm_qos_drop_user_request(dev, DEV_PM_QOS_LATENCY);
}
} }
/** /**
...@@ -619,9 +638,15 @@ static void __dev_pm_qos_hide_latency_limit(struct device *dev) ...@@ -619,9 +638,15 @@ static void __dev_pm_qos_hide_latency_limit(struct device *dev)
*/ */
void dev_pm_qos_hide_latency_limit(struct device *dev) void dev_pm_qos_hide_latency_limit(struct device *dev)
{ {
mutex_lock(&dev_pm_qos_sysfs_mtx);
pm_qos_sysfs_remove_latency(dev);
mutex_lock(&dev_pm_qos_mtx); mutex_lock(&dev_pm_qos_mtx);
__dev_pm_qos_hide_latency_limit(dev); __dev_pm_qos_hide_latency_limit(dev);
mutex_unlock(&dev_pm_qos_mtx); mutex_unlock(&dev_pm_qos_mtx);
mutex_unlock(&dev_pm_qos_sysfs_mtx);
} }
EXPORT_SYMBOL_GPL(dev_pm_qos_hide_latency_limit); EXPORT_SYMBOL_GPL(dev_pm_qos_hide_latency_limit);
...@@ -649,6 +674,8 @@ int dev_pm_qos_expose_flags(struct device *dev, s32 val) ...@@ -649,6 +674,8 @@ int dev_pm_qos_expose_flags(struct device *dev, s32 val)
} }
pm_runtime_get_sync(dev); pm_runtime_get_sync(dev);
mutex_lock(&dev_pm_qos_sysfs_mtx);
mutex_lock(&dev_pm_qos_mtx); mutex_lock(&dev_pm_qos_mtx);
if (IS_ERR_OR_NULL(dev->power.qos)) if (IS_ERR_OR_NULL(dev->power.qos))
...@@ -659,16 +686,19 @@ int dev_pm_qos_expose_flags(struct device *dev, s32 val) ...@@ -659,16 +686,19 @@ int dev_pm_qos_expose_flags(struct device *dev, s32 val)
if (ret < 0) { if (ret < 0) {
__dev_pm_qos_remove_request(req); __dev_pm_qos_remove_request(req);
kfree(req); kfree(req);
mutex_unlock(&dev_pm_qos_mtx);
goto out; goto out;
} }
dev->power.qos->flags_req = req; dev->power.qos->flags_req = req;
mutex_unlock(&dev_pm_qos_mtx);
ret = pm_qos_sysfs_add_flags(dev); ret = pm_qos_sysfs_add_flags(dev);
if (ret) if (ret)
__dev_pm_qos_drop_user_request(dev, DEV_PM_QOS_FLAGS); dev_pm_qos_drop_user_request(dev, DEV_PM_QOS_FLAGS);
out: out:
mutex_unlock(&dev_pm_qos_mtx); mutex_unlock(&dev_pm_qos_sysfs_mtx);
pm_runtime_put(dev); pm_runtime_put(dev);
return ret; return ret;
} }
...@@ -676,10 +706,8 @@ EXPORT_SYMBOL_GPL(dev_pm_qos_expose_flags); ...@@ -676,10 +706,8 @@ EXPORT_SYMBOL_GPL(dev_pm_qos_expose_flags);
static void __dev_pm_qos_hide_flags(struct device *dev) static void __dev_pm_qos_hide_flags(struct device *dev)
{ {
if (!IS_ERR_OR_NULL(dev->power.qos) && dev->power.qos->flags_req) { if (!IS_ERR_OR_NULL(dev->power.qos) && dev->power.qos->flags_req)
pm_qos_sysfs_remove_flags(dev);
__dev_pm_qos_drop_user_request(dev, DEV_PM_QOS_FLAGS); __dev_pm_qos_drop_user_request(dev, DEV_PM_QOS_FLAGS);
}
} }
/** /**
...@@ -689,9 +717,15 @@ static void __dev_pm_qos_hide_flags(struct device *dev) ...@@ -689,9 +717,15 @@ static void __dev_pm_qos_hide_flags(struct device *dev)
void dev_pm_qos_hide_flags(struct device *dev) void dev_pm_qos_hide_flags(struct device *dev)
{ {
pm_runtime_get_sync(dev); pm_runtime_get_sync(dev);
mutex_lock(&dev_pm_qos_sysfs_mtx);
pm_qos_sysfs_remove_flags(dev);
mutex_lock(&dev_pm_qos_mtx); mutex_lock(&dev_pm_qos_mtx);
__dev_pm_qos_hide_flags(dev); __dev_pm_qos_hide_flags(dev);
mutex_unlock(&dev_pm_qos_mtx); mutex_unlock(&dev_pm_qos_mtx);
mutex_unlock(&dev_pm_qos_sysfs_mtx);
pm_runtime_put(dev); pm_runtime_put(dev);
} }
EXPORT_SYMBOL_GPL(dev_pm_qos_hide_flags); EXPORT_SYMBOL_GPL(dev_pm_qos_hide_flags);
......
...@@ -178,10 +178,16 @@ static struct cpufreq_driver cpu0_cpufreq_driver = { ...@@ -178,10 +178,16 @@ static struct cpufreq_driver cpu0_cpufreq_driver = {
static int cpu0_cpufreq_probe(struct platform_device *pdev) static int cpu0_cpufreq_probe(struct platform_device *pdev)
{ {
struct device_node *np; struct device_node *np, *parent;
int ret; int ret;
for_each_child_of_node(of_find_node_by_path("/cpus"), np) { parent = of_find_node_by_path("/cpus");
if (!parent) {
pr_err("failed to find OF /cpus\n");
return -ENOENT;
}
for_each_child_of_node(parent, np) {
if (of_get_property(np, "operating-points", NULL)) if (of_get_property(np, "operating-points", NULL))
break; break;
} }
......
...@@ -14,8 +14,8 @@ ...@@ -14,8 +14,8 @@
* published by the Free Software Foundation. * published by the Free Software Foundation.
*/ */
#ifndef _CPUFREQ_GOVERNER_H #ifndef _CPUFREQ_GOVERNOR_H
#define _CPUFREQ_GOVERNER_H #define _CPUFREQ_GOVERNOR_H
#include <linux/cpufreq.h> #include <linux/cpufreq.h>
#include <linux/kobject.h> #include <linux/kobject.h>
...@@ -175,4 +175,4 @@ bool need_load_eval(struct cpu_dbs_common_info *cdbs, ...@@ -175,4 +175,4 @@ bool need_load_eval(struct cpu_dbs_common_info *cdbs,
unsigned int sampling_rate); unsigned int sampling_rate);
int cpufreq_governor_dbs(struct dbs_data *dbs_data, int cpufreq_governor_dbs(struct dbs_data *dbs_data,
struct cpufreq_policy *policy, unsigned int event); struct cpufreq_policy *policy, unsigned int event);
#endif /* _CPUFREQ_GOVERNER_H */ #endif /* _CPUFREQ_GOVERNOR_H */
...@@ -67,7 +67,6 @@ static void usb_port_device_release(struct device *dev) ...@@ -67,7 +67,6 @@ static void usb_port_device_release(struct device *dev)
{ {
struct usb_port *port_dev = to_usb_port(dev); struct usb_port *port_dev = to_usb_port(dev);
dev_pm_qos_hide_flags(dev);
kfree(port_dev); kfree(port_dev);
} }
......
...@@ -213,7 +213,7 @@ struct devfreq_simple_ondemand_data { ...@@ -213,7 +213,7 @@ struct devfreq_simple_ondemand_data {
#endif #endif
#else /* !CONFIG_PM_DEVFREQ */ #else /* !CONFIG_PM_DEVFREQ */
static struct devfreq *devfreq_add_device(struct device *dev, static inline struct devfreq *devfreq_add_device(struct device *dev,
struct devfreq_dev_profile *profile, struct devfreq_dev_profile *profile,
const char *governor_name, const char *governor_name,
void *data) void *data)
...@@ -221,34 +221,34 @@ static struct devfreq *devfreq_add_device(struct device *dev, ...@@ -221,34 +221,34 @@ static struct devfreq *devfreq_add_device(struct device *dev,
return NULL; return NULL;
} }
static int devfreq_remove_device(struct devfreq *devfreq) static inline int devfreq_remove_device(struct devfreq *devfreq)
{ {
return 0; return 0;
} }
static int devfreq_suspend_device(struct devfreq *devfreq) static inline int devfreq_suspend_device(struct devfreq *devfreq)
{ {
return 0; return 0;
} }
static int devfreq_resume_device(struct devfreq *devfreq) static inline int devfreq_resume_device(struct devfreq *devfreq)
{ {
return 0; return 0;
} }
static struct opp *devfreq_recommended_opp(struct device *dev, static inline struct opp *devfreq_recommended_opp(struct device *dev,
unsigned long *freq, u32 flags) unsigned long *freq, u32 flags)
{ {
return -EINVAL; return ERR_PTR(-EINVAL);
} }
static int devfreq_register_opp_notifier(struct device *dev, static inline int devfreq_register_opp_notifier(struct device *dev,
struct devfreq *devfreq) struct devfreq *devfreq)
{ {
return -EINVAL; return -EINVAL;
} }
static int devfreq_unregister_opp_notifier(struct device *dev, static inline int devfreq_unregister_opp_notifier(struct device *dev,
struct devfreq *devfreq) struct devfreq *devfreq)
{ {
return -EINVAL; return -EINVAL;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment