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()
This commit is contained in:
@@ -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)
|
|||||||
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)
|
|||||||
|
|
||||||
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,
|
|||||||
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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
*/
|
*/
|
||||||
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)
|
|||||||
}
|
}
|
||||||
|
|
||||||
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)
|
|||||||
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);
|
|||||||
|
|
||||||
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)
|
|||||||
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 = {
|
|||||||
|
|
||||||
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 @@
|
|||||||
* 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,
|
|||||||
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)
|
|||||||
{
|
{
|
||||||
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 {
|
|||||||
#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,
|
|||||||
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;
|
||||||
|
Reference in New Issue
Block a user