Merge branch 'pm-cpufreq'
* pm-cpufreq: cpufreq: Make cpufreq_generic_init() return void cpufreq: imx-cpufreq-dt: Add i.MX8MN support cpufreq: Add QoS requests for userspace constraints cpufreq: intel_pstate: Reuse refresh_frequency_limits() cpufreq: Register notifiers with the PM QoS framework PM / QoS: Add support for MIN/MAX frequency constraints PM / QOS: Pass request type to dev_pm_qos_read_value() PM / QOS: Rename __dev_pm_qos_read_value() and dev_pm_qos_raw_read_value() PM / QOS: Pass request type to dev_pm_qos_{add|remove}_notifier()
This commit is contained in:
commit
918e162e6a
@ -123,7 +123,7 @@ Will remove the element. After removal it will update the aggregate target and
|
|||||||
call the notification trees if the target was changed as a result of removing
|
call the notification trees if the target was changed as a result of removing
|
||||||
the request.
|
the request.
|
||||||
|
|
||||||
s32 dev_pm_qos_read_value(device):
|
s32 dev_pm_qos_read_value(device, type):
|
||||||
Returns the aggregated value for a given device's constraints list.
|
Returns the aggregated value for a given device's constraints list.
|
||||||
|
|
||||||
enum pm_qos_flags_status dev_pm_qos_flags(device, mask)
|
enum pm_qos_flags_status dev_pm_qos_flags(device, mask)
|
||||||
@ -164,12 +164,14 @@ directory.
|
|||||||
Notification mechanisms:
|
Notification mechanisms:
|
||||||
The per-device PM QoS framework has a per-device notification tree.
|
The per-device PM QoS framework has a per-device notification tree.
|
||||||
|
|
||||||
int dev_pm_qos_add_notifier(device, notifier):
|
int dev_pm_qos_add_notifier(device, notifier, type):
|
||||||
Adds a notification callback function for the device.
|
Adds a notification callback function for the device for a particular request
|
||||||
The callback is called when the aggregated value of the device constraints list
|
type.
|
||||||
is changed (for resume latency device PM QoS only).
|
|
||||||
|
|
||||||
int dev_pm_qos_remove_notifier(device, notifier):
|
The callback is called when the aggregated value of the device constraints list
|
||||||
|
is changed.
|
||||||
|
|
||||||
|
int dev_pm_qos_remove_notifier(device, notifier, type):
|
||||||
Removes the notification callback function for the device.
|
Removes the notification callback function for the device.
|
||||||
|
|
||||||
|
|
||||||
|
@ -1536,7 +1536,8 @@ static int genpd_add_device(struct generic_pm_domain *genpd, struct device *dev,
|
|||||||
if (ret)
|
if (ret)
|
||||||
genpd_free_dev_data(dev, gpd_data);
|
genpd_free_dev_data(dev, gpd_data);
|
||||||
else
|
else
|
||||||
dev_pm_qos_add_notifier(dev, &gpd_data->nb);
|
dev_pm_qos_add_notifier(dev, &gpd_data->nb,
|
||||||
|
DEV_PM_QOS_RESUME_LATENCY);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -1569,7 +1570,8 @@ static int genpd_remove_device(struct generic_pm_domain *genpd,
|
|||||||
|
|
||||||
pdd = dev->power.subsys_data->domain_data;
|
pdd = dev->power.subsys_data->domain_data;
|
||||||
gpd_data = to_gpd_data(pdd);
|
gpd_data = to_gpd_data(pdd);
|
||||||
dev_pm_qos_remove_notifier(dev, &gpd_data->nb);
|
dev_pm_qos_remove_notifier(dev, &gpd_data->nb,
|
||||||
|
DEV_PM_QOS_RESUME_LATENCY);
|
||||||
|
|
||||||
genpd_lock(genpd);
|
genpd_lock(genpd);
|
||||||
|
|
||||||
@ -1597,7 +1599,7 @@ static int genpd_remove_device(struct generic_pm_domain *genpd,
|
|||||||
|
|
||||||
out:
|
out:
|
||||||
genpd_unlock(genpd);
|
genpd_unlock(genpd);
|
||||||
dev_pm_qos_add_notifier(dev, &gpd_data->nb);
|
dev_pm_qos_add_notifier(dev, &gpd_data->nb, DEV_PM_QOS_RESUME_LATENCY);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -33,7 +33,7 @@ static int dev_update_qos_constraint(struct device *dev, void *data)
|
|||||||
* take its current PM QoS constraint (that's the only thing
|
* take its current PM QoS constraint (that's the only thing
|
||||||
* known at this point anyway).
|
* known at this point anyway).
|
||||||
*/
|
*/
|
||||||
constraint_ns = dev_pm_qos_read_value(dev);
|
constraint_ns = dev_pm_qos_read_value(dev, DEV_PM_QOS_RESUME_LATENCY);
|
||||||
constraint_ns *= NSEC_PER_USEC;
|
constraint_ns *= NSEC_PER_USEC;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -66,7 +66,7 @@ static bool default_suspend_ok(struct device *dev)
|
|||||||
td->constraint_changed = false;
|
td->constraint_changed = false;
|
||||||
td->cached_suspend_ok = false;
|
td->cached_suspend_ok = false;
|
||||||
td->effective_constraint_ns = 0;
|
td->effective_constraint_ns = 0;
|
||||||
constraint_ns = __dev_pm_qos_read_value(dev);
|
constraint_ns = __dev_pm_qos_resume_latency(dev);
|
||||||
|
|
||||||
spin_unlock_irqrestore(&dev->power.lock, flags);
|
spin_unlock_irqrestore(&dev->power.lock, flags);
|
||||||
|
|
||||||
|
@ -90,29 +90,49 @@ enum pm_qos_flags_status dev_pm_qos_flags(struct device *dev, s32 mask)
|
|||||||
EXPORT_SYMBOL_GPL(dev_pm_qos_flags);
|
EXPORT_SYMBOL_GPL(dev_pm_qos_flags);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* __dev_pm_qos_read_value - Get PM QoS constraint for a given device.
|
* __dev_pm_qos_resume_latency - Get resume latency constraint for a given device.
|
||||||
* @dev: Device to get the PM QoS constraint value for.
|
* @dev: Device to get the PM QoS constraint value for.
|
||||||
*
|
*
|
||||||
* This routine must be called with dev->power.lock held.
|
* This routine must be called with dev->power.lock held.
|
||||||
*/
|
*/
|
||||||
s32 __dev_pm_qos_read_value(struct device *dev)
|
s32 __dev_pm_qos_resume_latency(struct device *dev)
|
||||||
{
|
{
|
||||||
lockdep_assert_held(&dev->power.lock);
|
lockdep_assert_held(&dev->power.lock);
|
||||||
|
|
||||||
return dev_pm_qos_raw_read_value(dev);
|
return dev_pm_qos_raw_resume_latency(dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* dev_pm_qos_read_value - Get PM QoS constraint for a given device (locked).
|
* dev_pm_qos_read_value - Get PM QoS constraint for a given device (locked).
|
||||||
* @dev: Device to get the PM QoS constraint value for.
|
* @dev: Device to get the PM QoS constraint value for.
|
||||||
|
* @type: QoS request type.
|
||||||
*/
|
*/
|
||||||
s32 dev_pm_qos_read_value(struct device *dev)
|
s32 dev_pm_qos_read_value(struct device *dev, enum dev_pm_qos_req_type type)
|
||||||
{
|
{
|
||||||
|
struct dev_pm_qos *qos = dev->power.qos;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
s32 ret;
|
s32 ret;
|
||||||
|
|
||||||
spin_lock_irqsave(&dev->power.lock, flags);
|
spin_lock_irqsave(&dev->power.lock, flags);
|
||||||
ret = __dev_pm_qos_read_value(dev);
|
|
||||||
|
switch (type) {
|
||||||
|
case DEV_PM_QOS_RESUME_LATENCY:
|
||||||
|
ret = IS_ERR_OR_NULL(qos) ? PM_QOS_RESUME_LATENCY_NO_CONSTRAINT
|
||||||
|
: pm_qos_read_value(&qos->resume_latency);
|
||||||
|
break;
|
||||||
|
case DEV_PM_QOS_MIN_FREQUENCY:
|
||||||
|
ret = IS_ERR_OR_NULL(qos) ? PM_QOS_MIN_FREQUENCY_DEFAULT_VALUE
|
||||||
|
: pm_qos_read_value(&qos->min_frequency);
|
||||||
|
break;
|
||||||
|
case DEV_PM_QOS_MAX_FREQUENCY:
|
||||||
|
ret = IS_ERR_OR_NULL(qos) ? PM_QOS_MAX_FREQUENCY_DEFAULT_VALUE
|
||||||
|
: pm_qos_read_value(&qos->max_frequency);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
WARN_ON(1);
|
||||||
|
ret = 0;
|
||||||
|
}
|
||||||
|
|
||||||
spin_unlock_irqrestore(&dev->power.lock, flags);
|
spin_unlock_irqrestore(&dev->power.lock, flags);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
@ -149,6 +169,14 @@ static int apply_constraint(struct dev_pm_qos_request *req,
|
|||||||
req->dev->power.set_latency_tolerance(req->dev, value);
|
req->dev->power.set_latency_tolerance(req->dev, value);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case DEV_PM_QOS_MIN_FREQUENCY:
|
||||||
|
ret = pm_qos_update_target(&qos->min_frequency,
|
||||||
|
&req->data.pnode, action, value);
|
||||||
|
break;
|
||||||
|
case DEV_PM_QOS_MAX_FREQUENCY:
|
||||||
|
ret = pm_qos_update_target(&qos->max_frequency,
|
||||||
|
&req->data.pnode, action, value);
|
||||||
|
break;
|
||||||
case DEV_PM_QOS_FLAGS:
|
case DEV_PM_QOS_FLAGS:
|
||||||
ret = pm_qos_update_flags(&qos->flags, &req->data.flr,
|
ret = pm_qos_update_flags(&qos->flags, &req->data.flr,
|
||||||
action, value);
|
action, value);
|
||||||
@ -177,12 +205,11 @@ static int dev_pm_qos_constraints_allocate(struct device *dev)
|
|||||||
if (!qos)
|
if (!qos)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
n = kzalloc(sizeof(*n), GFP_KERNEL);
|
n = kzalloc(3 * sizeof(*n), GFP_KERNEL);
|
||||||
if (!n) {
|
if (!n) {
|
||||||
kfree(qos);
|
kfree(qos);
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
BLOCKING_INIT_NOTIFIER_HEAD(n);
|
|
||||||
|
|
||||||
c = &qos->resume_latency;
|
c = &qos->resume_latency;
|
||||||
plist_head_init(&c->list);
|
plist_head_init(&c->list);
|
||||||
@ -191,6 +218,7 @@ static int dev_pm_qos_constraints_allocate(struct device *dev)
|
|||||||
c->no_constraint_value = PM_QOS_RESUME_LATENCY_NO_CONSTRAINT;
|
c->no_constraint_value = PM_QOS_RESUME_LATENCY_NO_CONSTRAINT;
|
||||||
c->type = PM_QOS_MIN;
|
c->type = PM_QOS_MIN;
|
||||||
c->notifiers = n;
|
c->notifiers = n;
|
||||||
|
BLOCKING_INIT_NOTIFIER_HEAD(n);
|
||||||
|
|
||||||
c = &qos->latency_tolerance;
|
c = &qos->latency_tolerance;
|
||||||
plist_head_init(&c->list);
|
plist_head_init(&c->list);
|
||||||
@ -199,6 +227,24 @@ static int dev_pm_qos_constraints_allocate(struct device *dev)
|
|||||||
c->no_constraint_value = PM_QOS_LATENCY_TOLERANCE_NO_CONSTRAINT;
|
c->no_constraint_value = PM_QOS_LATENCY_TOLERANCE_NO_CONSTRAINT;
|
||||||
c->type = PM_QOS_MIN;
|
c->type = PM_QOS_MIN;
|
||||||
|
|
||||||
|
c = &qos->min_frequency;
|
||||||
|
plist_head_init(&c->list);
|
||||||
|
c->target_value = PM_QOS_MIN_FREQUENCY_DEFAULT_VALUE;
|
||||||
|
c->default_value = PM_QOS_MIN_FREQUENCY_DEFAULT_VALUE;
|
||||||
|
c->no_constraint_value = PM_QOS_MIN_FREQUENCY_DEFAULT_VALUE;
|
||||||
|
c->type = PM_QOS_MAX;
|
||||||
|
c->notifiers = ++n;
|
||||||
|
BLOCKING_INIT_NOTIFIER_HEAD(n);
|
||||||
|
|
||||||
|
c = &qos->max_frequency;
|
||||||
|
plist_head_init(&c->list);
|
||||||
|
c->target_value = PM_QOS_MAX_FREQUENCY_DEFAULT_VALUE;
|
||||||
|
c->default_value = PM_QOS_MAX_FREQUENCY_DEFAULT_VALUE;
|
||||||
|
c->no_constraint_value = PM_QOS_MAX_FREQUENCY_DEFAULT_VALUE;
|
||||||
|
c->type = PM_QOS_MIN;
|
||||||
|
c->notifiers = ++n;
|
||||||
|
BLOCKING_INIT_NOTIFIER_HEAD(n);
|
||||||
|
|
||||||
INIT_LIST_HEAD(&qos->flags.list);
|
INIT_LIST_HEAD(&qos->flags.list);
|
||||||
|
|
||||||
spin_lock_irq(&dev->power.lock);
|
spin_lock_irq(&dev->power.lock);
|
||||||
@ -252,11 +298,25 @@ void dev_pm_qos_constraints_destroy(struct device *dev)
|
|||||||
apply_constraint(req, PM_QOS_REMOVE_REQ, PM_QOS_DEFAULT_VALUE);
|
apply_constraint(req, PM_QOS_REMOVE_REQ, PM_QOS_DEFAULT_VALUE);
|
||||||
memset(req, 0, sizeof(*req));
|
memset(req, 0, sizeof(*req));
|
||||||
}
|
}
|
||||||
|
|
||||||
c = &qos->latency_tolerance;
|
c = &qos->latency_tolerance;
|
||||||
plist_for_each_entry_safe(req, tmp, &c->list, data.pnode) {
|
plist_for_each_entry_safe(req, tmp, &c->list, data.pnode) {
|
||||||
apply_constraint(req, PM_QOS_REMOVE_REQ, PM_QOS_DEFAULT_VALUE);
|
apply_constraint(req, PM_QOS_REMOVE_REQ, PM_QOS_DEFAULT_VALUE);
|
||||||
memset(req, 0, sizeof(*req));
|
memset(req, 0, sizeof(*req));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
c = &qos->min_frequency;
|
||||||
|
plist_for_each_entry_safe(req, tmp, &c->list, data.pnode) {
|
||||||
|
apply_constraint(req, PM_QOS_REMOVE_REQ, PM_QOS_MIN_FREQUENCY_DEFAULT_VALUE);
|
||||||
|
memset(req, 0, sizeof(*req));
|
||||||
|
}
|
||||||
|
|
||||||
|
c = &qos->max_frequency;
|
||||||
|
plist_for_each_entry_safe(req, tmp, &c->list, data.pnode) {
|
||||||
|
apply_constraint(req, PM_QOS_REMOVE_REQ, PM_QOS_MAX_FREQUENCY_DEFAULT_VALUE);
|
||||||
|
memset(req, 0, sizeof(*req));
|
||||||
|
}
|
||||||
|
|
||||||
f = &qos->flags;
|
f = &qos->flags;
|
||||||
list_for_each_entry_safe(req, tmp, &f->list, data.flr.node) {
|
list_for_each_entry_safe(req, tmp, &f->list, data.flr.node) {
|
||||||
apply_constraint(req, PM_QOS_REMOVE_REQ, PM_QOS_DEFAULT_VALUE);
|
apply_constraint(req, PM_QOS_REMOVE_REQ, PM_QOS_DEFAULT_VALUE);
|
||||||
@ -368,6 +428,8 @@ static int __dev_pm_qos_update_request(struct dev_pm_qos_request *req,
|
|||||||
switch(req->type) {
|
switch(req->type) {
|
||||||
case DEV_PM_QOS_RESUME_LATENCY:
|
case DEV_PM_QOS_RESUME_LATENCY:
|
||||||
case DEV_PM_QOS_LATENCY_TOLERANCE:
|
case DEV_PM_QOS_LATENCY_TOLERANCE:
|
||||||
|
case DEV_PM_QOS_MIN_FREQUENCY:
|
||||||
|
case DEV_PM_QOS_MAX_FREQUENCY:
|
||||||
curr_value = req->data.pnode.prio;
|
curr_value = req->data.pnode.prio;
|
||||||
break;
|
break;
|
||||||
case DEV_PM_QOS_FLAGS:
|
case DEV_PM_QOS_FLAGS:
|
||||||
@ -467,6 +529,7 @@ EXPORT_SYMBOL_GPL(dev_pm_qos_remove_request);
|
|||||||
*
|
*
|
||||||
* @dev: target device for the constraint
|
* @dev: target device for the constraint
|
||||||
* @notifier: notifier block managed by caller.
|
* @notifier: notifier block managed by caller.
|
||||||
|
* @type: request type.
|
||||||
*
|
*
|
||||||
* Will register the notifier into a notification chain that gets called
|
* Will register the notifier into a notification chain that gets called
|
||||||
* upon changes to the target value for the device.
|
* upon changes to the target value for the device.
|
||||||
@ -474,7 +537,8 @@ EXPORT_SYMBOL_GPL(dev_pm_qos_remove_request);
|
|||||||
* If the device's constraints object doesn't exist when this routine is called,
|
* If the device's constraints object doesn't exist when this routine is called,
|
||||||
* it will be created (or error code will be returned if that fails).
|
* it will be created (or error code will be returned if that fails).
|
||||||
*/
|
*/
|
||||||
int dev_pm_qos_add_notifier(struct device *dev, struct notifier_block *notifier)
|
int dev_pm_qos_add_notifier(struct device *dev, struct notifier_block *notifier,
|
||||||
|
enum dev_pm_qos_req_type type)
|
||||||
{
|
{
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
@ -485,10 +549,28 @@ int dev_pm_qos_add_notifier(struct device *dev, struct notifier_block *notifier)
|
|||||||
else if (!dev->power.qos)
|
else if (!dev->power.qos)
|
||||||
ret = dev_pm_qos_constraints_allocate(dev);
|
ret = dev_pm_qos_constraints_allocate(dev);
|
||||||
|
|
||||||
if (!ret)
|
if (ret)
|
||||||
|
goto unlock;
|
||||||
|
|
||||||
|
switch (type) {
|
||||||
|
case DEV_PM_QOS_RESUME_LATENCY:
|
||||||
ret = blocking_notifier_chain_register(dev->power.qos->resume_latency.notifiers,
|
ret = blocking_notifier_chain_register(dev->power.qos->resume_latency.notifiers,
|
||||||
notifier);
|
notifier);
|
||||||
|
break;
|
||||||
|
case DEV_PM_QOS_MIN_FREQUENCY:
|
||||||
|
ret = blocking_notifier_chain_register(dev->power.qos->min_frequency.notifiers,
|
||||||
|
notifier);
|
||||||
|
break;
|
||||||
|
case DEV_PM_QOS_MAX_FREQUENCY:
|
||||||
|
ret = blocking_notifier_chain_register(dev->power.qos->max_frequency.notifiers,
|
||||||
|
notifier);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
WARN_ON(1);
|
||||||
|
ret = -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
unlock:
|
||||||
mutex_unlock(&dev_pm_qos_mtx);
|
mutex_unlock(&dev_pm_qos_mtx);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -500,24 +582,44 @@ EXPORT_SYMBOL_GPL(dev_pm_qos_add_notifier);
|
|||||||
*
|
*
|
||||||
* @dev: target device for the constraint
|
* @dev: target device for the constraint
|
||||||
* @notifier: notifier block to be removed.
|
* @notifier: notifier block to be removed.
|
||||||
|
* @type: request type.
|
||||||
*
|
*
|
||||||
* Will remove the notifier from the notification chain that gets called
|
* Will remove the notifier from the notification chain that gets called
|
||||||
* upon changes to the target value.
|
* upon changes to the target value.
|
||||||
*/
|
*/
|
||||||
int dev_pm_qos_remove_notifier(struct device *dev,
|
int dev_pm_qos_remove_notifier(struct device *dev,
|
||||||
struct notifier_block *notifier)
|
struct notifier_block *notifier,
|
||||||
|
enum dev_pm_qos_req_type type)
|
||||||
{
|
{
|
||||||
int retval = 0;
|
int ret = 0;
|
||||||
|
|
||||||
mutex_lock(&dev_pm_qos_mtx);
|
mutex_lock(&dev_pm_qos_mtx);
|
||||||
|
|
||||||
/* Silently return if the constraints object is not present. */
|
/* Silently return if the constraints object is not present. */
|
||||||
if (!IS_ERR_OR_NULL(dev->power.qos))
|
if (IS_ERR_OR_NULL(dev->power.qos))
|
||||||
retval = blocking_notifier_chain_unregister(dev->power.qos->resume_latency.notifiers,
|
goto unlock;
|
||||||
notifier);
|
|
||||||
|
|
||||||
|
switch (type) {
|
||||||
|
case DEV_PM_QOS_RESUME_LATENCY:
|
||||||
|
ret = blocking_notifier_chain_unregister(dev->power.qos->resume_latency.notifiers,
|
||||||
|
notifier);
|
||||||
|
break;
|
||||||
|
case DEV_PM_QOS_MIN_FREQUENCY:
|
||||||
|
ret = blocking_notifier_chain_unregister(dev->power.qos->min_frequency.notifiers,
|
||||||
|
notifier);
|
||||||
|
break;
|
||||||
|
case DEV_PM_QOS_MAX_FREQUENCY:
|
||||||
|
ret = blocking_notifier_chain_unregister(dev->power.qos->max_frequency.notifiers,
|
||||||
|
notifier);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
WARN_ON(1);
|
||||||
|
ret = -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
unlock:
|
||||||
mutex_unlock(&dev_pm_qos_mtx);
|
mutex_unlock(&dev_pm_qos_mtx);
|
||||||
return retval;
|
return ret;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(dev_pm_qos_remove_notifier);
|
EXPORT_SYMBOL_GPL(dev_pm_qos_remove_notifier);
|
||||||
|
|
||||||
@ -577,6 +679,9 @@ static void __dev_pm_qos_drop_user_request(struct device *dev,
|
|||||||
req = dev->power.qos->flags_req;
|
req = dev->power.qos->flags_req;
|
||||||
dev->power.qos->flags_req = NULL;
|
dev->power.qos->flags_req = NULL;
|
||||||
break;
|
break;
|
||||||
|
default:
|
||||||
|
WARN_ON(1);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
__dev_pm_qos_remove_request(req);
|
__dev_pm_qos_remove_request(req);
|
||||||
kfree(req);
|
kfree(req);
|
||||||
|
@ -275,7 +275,7 @@ static int rpm_check_suspend_allowed(struct device *dev)
|
|||||||
|| (dev->power.request_pending
|
|| (dev->power.request_pending
|
||||||
&& dev->power.request == RPM_REQ_RESUME))
|
&& dev->power.request == RPM_REQ_RESUME))
|
||||||
retval = -EAGAIN;
|
retval = -EAGAIN;
|
||||||
else if (__dev_pm_qos_read_value(dev) == 0)
|
else if (__dev_pm_qos_resume_latency(dev) == 0)
|
||||||
retval = -EPERM;
|
retval = -EPERM;
|
||||||
else if (dev->power.runtime_status == RPM_SUSPENDED)
|
else if (dev->power.runtime_status == RPM_SUSPENDED)
|
||||||
retval = 1;
|
retval = 1;
|
||||||
|
@ -131,23 +131,18 @@ static int bmips_cpufreq_exit(struct cpufreq_policy *policy)
|
|||||||
static int bmips_cpufreq_init(struct cpufreq_policy *policy)
|
static int bmips_cpufreq_init(struct cpufreq_policy *policy)
|
||||||
{
|
{
|
||||||
struct cpufreq_frequency_table *freq_table;
|
struct cpufreq_frequency_table *freq_table;
|
||||||
int ret;
|
|
||||||
|
|
||||||
freq_table = bmips_cpufreq_get_freq_table(policy);
|
freq_table = bmips_cpufreq_get_freq_table(policy);
|
||||||
if (IS_ERR(freq_table)) {
|
if (IS_ERR(freq_table)) {
|
||||||
ret = PTR_ERR(freq_table);
|
pr_err("%s: couldn't determine frequency table (%ld).\n",
|
||||||
pr_err("%s: couldn't determine frequency table (%d).\n",
|
BMIPS_CPUFREQ_NAME, PTR_ERR(freq_table));
|
||||||
BMIPS_CPUFREQ_NAME, ret);
|
return PTR_ERR(freq_table);
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = cpufreq_generic_init(policy, freq_table, TRANSITION_LATENCY);
|
cpufreq_generic_init(policy, freq_table, TRANSITION_LATENCY);
|
||||||
if (ret)
|
pr_info("%s: registered\n", BMIPS_CPUFREQ_NAME);
|
||||||
bmips_cpufreq_exit(policy);
|
|
||||||
else
|
|
||||||
pr_info("%s: registered\n", BMIPS_CPUFREQ_NAME);
|
|
||||||
|
|
||||||
return ret;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct cpufreq_driver bmips_cpufreq_driver = {
|
static struct cpufreq_driver bmips_cpufreq_driver = {
|
||||||
|
@ -23,6 +23,7 @@
|
|||||||
#include <linux/kernel_stat.h>
|
#include <linux/kernel_stat.h>
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/mutex.h>
|
#include <linux/mutex.h>
|
||||||
|
#include <linux/pm_qos.h>
|
||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
#include <linux/suspend.h>
|
#include <linux/suspend.h>
|
||||||
#include <linux/syscore_ops.h>
|
#include <linux/syscore_ops.h>
|
||||||
@ -158,7 +159,7 @@ EXPORT_SYMBOL_GPL(arch_set_freq_scale);
|
|||||||
* - set policies transition latency
|
* - set policies transition latency
|
||||||
* - policy->cpus with all possible CPUs
|
* - policy->cpus with all possible CPUs
|
||||||
*/
|
*/
|
||||||
int cpufreq_generic_init(struct cpufreq_policy *policy,
|
void cpufreq_generic_init(struct cpufreq_policy *policy,
|
||||||
struct cpufreq_frequency_table *table,
|
struct cpufreq_frequency_table *table,
|
||||||
unsigned int transition_latency)
|
unsigned int transition_latency)
|
||||||
{
|
{
|
||||||
@ -170,8 +171,6 @@ int cpufreq_generic_init(struct cpufreq_policy *policy,
|
|||||||
* share the clock and voltage and clock.
|
* share the clock and voltage and clock.
|
||||||
*/
|
*/
|
||||||
cpumask_setall(policy->cpus);
|
cpumask_setall(policy->cpus);
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(cpufreq_generic_init);
|
EXPORT_SYMBOL_GPL(cpufreq_generic_init);
|
||||||
|
|
||||||
@ -714,23 +713,15 @@ static ssize_t show_scaling_cur_freq(struct cpufreq_policy *policy, char *buf)
|
|||||||
static ssize_t store_##file_name \
|
static ssize_t store_##file_name \
|
||||||
(struct cpufreq_policy *policy, const char *buf, size_t count) \
|
(struct cpufreq_policy *policy, const char *buf, size_t count) \
|
||||||
{ \
|
{ \
|
||||||
int ret, temp; \
|
unsigned long val; \
|
||||||
struct cpufreq_policy new_policy; \
|
int ret; \
|
||||||
\
|
\
|
||||||
memcpy(&new_policy, policy, sizeof(*policy)); \
|
ret = sscanf(buf, "%lu", &val); \
|
||||||
new_policy.min = policy->user_policy.min; \
|
|
||||||
new_policy.max = policy->user_policy.max; \
|
|
||||||
\
|
|
||||||
ret = sscanf(buf, "%u", &new_policy.object); \
|
|
||||||
if (ret != 1) \
|
if (ret != 1) \
|
||||||
return -EINVAL; \
|
return -EINVAL; \
|
||||||
\
|
\
|
||||||
temp = new_policy.object; \
|
ret = dev_pm_qos_update_request(policy->object##_freq_req, val);\
|
||||||
ret = cpufreq_set_policy(policy, &new_policy); \
|
return ret >= 0 ? count : ret; \
|
||||||
if (!ret) \
|
|
||||||
policy->user_policy.object = temp; \
|
|
||||||
\
|
|
||||||
return ret ? ret : count; \
|
|
||||||
}
|
}
|
||||||
|
|
||||||
store_one(scaling_min_freq, min);
|
store_one(scaling_min_freq, min);
|
||||||
@ -996,7 +987,7 @@ static void add_cpu_dev_symlink(struct cpufreq_policy *policy, unsigned int cpu)
|
|||||||
{
|
{
|
||||||
struct device *dev = get_cpu_device(cpu);
|
struct device *dev = get_cpu_device(cpu);
|
||||||
|
|
||||||
if (!dev)
|
if (unlikely(!dev))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (cpumask_test_and_set_cpu(cpu, policy->real_cpus))
|
if (cpumask_test_and_set_cpu(cpu, policy->real_cpus))
|
||||||
@ -1112,17 +1103,18 @@ static int cpufreq_add_policy_cpu(struct cpufreq_policy *policy, unsigned int cp
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void refresh_frequency_limits(struct cpufreq_policy *policy)
|
void refresh_frequency_limits(struct cpufreq_policy *policy)
|
||||||
{
|
{
|
||||||
struct cpufreq_policy new_policy = *policy;
|
struct cpufreq_policy new_policy;
|
||||||
|
|
||||||
pr_debug("updating policy for CPU %u\n", policy->cpu);
|
if (!policy_is_inactive(policy)) {
|
||||||
|
new_policy = *policy;
|
||||||
|
pr_debug("updating policy for CPU %u\n", policy->cpu);
|
||||||
|
|
||||||
new_policy.min = policy->user_policy.min;
|
cpufreq_set_policy(policy, &new_policy);
|
||||||
new_policy.max = policy->user_policy.max;
|
}
|
||||||
|
|
||||||
cpufreq_set_policy(policy, &new_policy);
|
|
||||||
}
|
}
|
||||||
|
EXPORT_SYMBOL(refresh_frequency_limits);
|
||||||
|
|
||||||
static void handle_update(struct work_struct *work)
|
static void handle_update(struct work_struct *work)
|
||||||
{
|
{
|
||||||
@ -1130,60 +1122,27 @@ static void handle_update(struct work_struct *work)
|
|||||||
container_of(work, struct cpufreq_policy, update);
|
container_of(work, struct cpufreq_policy, update);
|
||||||
|
|
||||||
pr_debug("handle_update for cpu %u called\n", policy->cpu);
|
pr_debug("handle_update for cpu %u called\n", policy->cpu);
|
||||||
|
down_write(&policy->rwsem);
|
||||||
refresh_frequency_limits(policy);
|
refresh_frequency_limits(policy);
|
||||||
|
up_write(&policy->rwsem);
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct cpufreq_policy *cpufreq_policy_alloc(unsigned int cpu)
|
static int cpufreq_notifier_min(struct notifier_block *nb, unsigned long freq,
|
||||||
|
void *data)
|
||||||
{
|
{
|
||||||
struct cpufreq_policy *policy;
|
struct cpufreq_policy *policy = container_of(nb, struct cpufreq_policy, nb_min);
|
||||||
int ret;
|
|
||||||
|
|
||||||
policy = kzalloc(sizeof(*policy), GFP_KERNEL);
|
schedule_work(&policy->update);
|
||||||
if (!policy)
|
return 0;
|
||||||
return NULL;
|
}
|
||||||
|
|
||||||
if (!alloc_cpumask_var(&policy->cpus, GFP_KERNEL))
|
static int cpufreq_notifier_max(struct notifier_block *nb, unsigned long freq,
|
||||||
goto err_free_policy;
|
void *data)
|
||||||
|
{
|
||||||
|
struct cpufreq_policy *policy = container_of(nb, struct cpufreq_policy, nb_max);
|
||||||
|
|
||||||
if (!zalloc_cpumask_var(&policy->related_cpus, GFP_KERNEL))
|
schedule_work(&policy->update);
|
||||||
goto err_free_cpumask;
|
return 0;
|
||||||
|
|
||||||
if (!zalloc_cpumask_var(&policy->real_cpus, GFP_KERNEL))
|
|
||||||
goto err_free_rcpumask;
|
|
||||||
|
|
||||||
ret = kobject_init_and_add(&policy->kobj, &ktype_cpufreq,
|
|
||||||
cpufreq_global_kobject, "policy%u", cpu);
|
|
||||||
if (ret) {
|
|
||||||
pr_err("%s: failed to init policy->kobj: %d\n", __func__, ret);
|
|
||||||
/*
|
|
||||||
* The entire policy object will be freed below, but the extra
|
|
||||||
* memory allocated for the kobject name needs to be freed by
|
|
||||||
* releasing the kobject.
|
|
||||||
*/
|
|
||||||
kobject_put(&policy->kobj);
|
|
||||||
goto err_free_real_cpus;
|
|
||||||
}
|
|
||||||
|
|
||||||
INIT_LIST_HEAD(&policy->policy_list);
|
|
||||||
init_rwsem(&policy->rwsem);
|
|
||||||
spin_lock_init(&policy->transition_lock);
|
|
||||||
init_waitqueue_head(&policy->transition_wait);
|
|
||||||
init_completion(&policy->kobj_unregister);
|
|
||||||
INIT_WORK(&policy->update, handle_update);
|
|
||||||
|
|
||||||
policy->cpu = cpu;
|
|
||||||
return policy;
|
|
||||||
|
|
||||||
err_free_real_cpus:
|
|
||||||
free_cpumask_var(policy->real_cpus);
|
|
||||||
err_free_rcpumask:
|
|
||||||
free_cpumask_var(policy->related_cpus);
|
|
||||||
err_free_cpumask:
|
|
||||||
free_cpumask_var(policy->cpus);
|
|
||||||
err_free_policy:
|
|
||||||
kfree(policy);
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void cpufreq_policy_put_kobj(struct cpufreq_policy *policy)
|
static void cpufreq_policy_put_kobj(struct cpufreq_policy *policy)
|
||||||
@ -1208,8 +1167,90 @@ static void cpufreq_policy_put_kobj(struct cpufreq_policy *policy)
|
|||||||
pr_debug("wait complete\n");
|
pr_debug("wait complete\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static struct cpufreq_policy *cpufreq_policy_alloc(unsigned int cpu)
|
||||||
|
{
|
||||||
|
struct cpufreq_policy *policy;
|
||||||
|
struct device *dev = get_cpu_device(cpu);
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (!dev)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
policy = kzalloc(sizeof(*policy), GFP_KERNEL);
|
||||||
|
if (!policy)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (!alloc_cpumask_var(&policy->cpus, GFP_KERNEL))
|
||||||
|
goto err_free_policy;
|
||||||
|
|
||||||
|
if (!zalloc_cpumask_var(&policy->related_cpus, GFP_KERNEL))
|
||||||
|
goto err_free_cpumask;
|
||||||
|
|
||||||
|
if (!zalloc_cpumask_var(&policy->real_cpus, GFP_KERNEL))
|
||||||
|
goto err_free_rcpumask;
|
||||||
|
|
||||||
|
ret = kobject_init_and_add(&policy->kobj, &ktype_cpufreq,
|
||||||
|
cpufreq_global_kobject, "policy%u", cpu);
|
||||||
|
if (ret) {
|
||||||
|
dev_err(dev, "%s: failed to init policy->kobj: %d\n", __func__, ret);
|
||||||
|
/*
|
||||||
|
* The entire policy object will be freed below, but the extra
|
||||||
|
* memory allocated for the kobject name needs to be freed by
|
||||||
|
* releasing the kobject.
|
||||||
|
*/
|
||||||
|
kobject_put(&policy->kobj);
|
||||||
|
goto err_free_real_cpus;
|
||||||
|
}
|
||||||
|
|
||||||
|
policy->nb_min.notifier_call = cpufreq_notifier_min;
|
||||||
|
policy->nb_max.notifier_call = cpufreq_notifier_max;
|
||||||
|
|
||||||
|
ret = dev_pm_qos_add_notifier(dev, &policy->nb_min,
|
||||||
|
DEV_PM_QOS_MIN_FREQUENCY);
|
||||||
|
if (ret) {
|
||||||
|
dev_err(dev, "Failed to register MIN QoS notifier: %d (%*pbl)\n",
|
||||||
|
ret, cpumask_pr_args(policy->cpus));
|
||||||
|
goto err_kobj_remove;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = dev_pm_qos_add_notifier(dev, &policy->nb_max,
|
||||||
|
DEV_PM_QOS_MAX_FREQUENCY);
|
||||||
|
if (ret) {
|
||||||
|
dev_err(dev, "Failed to register MAX QoS notifier: %d (%*pbl)\n",
|
||||||
|
ret, cpumask_pr_args(policy->cpus));
|
||||||
|
goto err_min_qos_notifier;
|
||||||
|
}
|
||||||
|
|
||||||
|
INIT_LIST_HEAD(&policy->policy_list);
|
||||||
|
init_rwsem(&policy->rwsem);
|
||||||
|
spin_lock_init(&policy->transition_lock);
|
||||||
|
init_waitqueue_head(&policy->transition_wait);
|
||||||
|
init_completion(&policy->kobj_unregister);
|
||||||
|
INIT_WORK(&policy->update, handle_update);
|
||||||
|
|
||||||
|
policy->cpu = cpu;
|
||||||
|
return policy;
|
||||||
|
|
||||||
|
err_min_qos_notifier:
|
||||||
|
dev_pm_qos_remove_notifier(dev, &policy->nb_min,
|
||||||
|
DEV_PM_QOS_MIN_FREQUENCY);
|
||||||
|
err_kobj_remove:
|
||||||
|
cpufreq_policy_put_kobj(policy);
|
||||||
|
err_free_real_cpus:
|
||||||
|
free_cpumask_var(policy->real_cpus);
|
||||||
|
err_free_rcpumask:
|
||||||
|
free_cpumask_var(policy->related_cpus);
|
||||||
|
err_free_cpumask:
|
||||||
|
free_cpumask_var(policy->cpus);
|
||||||
|
err_free_policy:
|
||||||
|
kfree(policy);
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
static void cpufreq_policy_free(struct cpufreq_policy *policy)
|
static void cpufreq_policy_free(struct cpufreq_policy *policy)
|
||||||
{
|
{
|
||||||
|
struct device *dev = get_cpu_device(policy->cpu);
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
int cpu;
|
int cpu;
|
||||||
|
|
||||||
@ -1221,6 +1262,14 @@ static void cpufreq_policy_free(struct cpufreq_policy *policy)
|
|||||||
per_cpu(cpufreq_cpu_data, cpu) = NULL;
|
per_cpu(cpufreq_cpu_data, cpu) = NULL;
|
||||||
write_unlock_irqrestore(&cpufreq_driver_lock, flags);
|
write_unlock_irqrestore(&cpufreq_driver_lock, flags);
|
||||||
|
|
||||||
|
dev_pm_qos_remove_notifier(dev, &policy->nb_max,
|
||||||
|
DEV_PM_QOS_MAX_FREQUENCY);
|
||||||
|
dev_pm_qos_remove_notifier(dev, &policy->nb_min,
|
||||||
|
DEV_PM_QOS_MIN_FREQUENCY);
|
||||||
|
dev_pm_qos_remove_request(policy->max_freq_req);
|
||||||
|
dev_pm_qos_remove_request(policy->min_freq_req);
|
||||||
|
kfree(policy->min_freq_req);
|
||||||
|
|
||||||
cpufreq_policy_put_kobj(policy);
|
cpufreq_policy_put_kobj(policy);
|
||||||
free_cpumask_var(policy->real_cpus);
|
free_cpumask_var(policy->real_cpus);
|
||||||
free_cpumask_var(policy->related_cpus);
|
free_cpumask_var(policy->related_cpus);
|
||||||
@ -1298,16 +1347,50 @@ static int cpufreq_online(unsigned int cpu)
|
|||||||
cpumask_and(policy->cpus, policy->cpus, cpu_online_mask);
|
cpumask_and(policy->cpus, policy->cpus, cpu_online_mask);
|
||||||
|
|
||||||
if (new_policy) {
|
if (new_policy) {
|
||||||
policy->user_policy.min = policy->min;
|
struct device *dev = get_cpu_device(cpu);
|
||||||
policy->user_policy.max = policy->max;
|
|
||||||
|
|
||||||
for_each_cpu(j, policy->related_cpus) {
|
for_each_cpu(j, policy->related_cpus) {
|
||||||
per_cpu(cpufreq_cpu_data, j) = policy;
|
per_cpu(cpufreq_cpu_data, j) = policy;
|
||||||
add_cpu_dev_symlink(policy, j);
|
add_cpu_dev_symlink(policy, j);
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
policy->min = policy->user_policy.min;
|
policy->min_freq_req = kzalloc(2 * sizeof(*policy->min_freq_req),
|
||||||
policy->max = policy->user_policy.max;
|
GFP_KERNEL);
|
||||||
|
if (!policy->min_freq_req)
|
||||||
|
goto out_destroy_policy;
|
||||||
|
|
||||||
|
ret = dev_pm_qos_add_request(dev, policy->min_freq_req,
|
||||||
|
DEV_PM_QOS_MIN_FREQUENCY,
|
||||||
|
policy->min);
|
||||||
|
if (ret < 0) {
|
||||||
|
/*
|
||||||
|
* So we don't call dev_pm_qos_remove_request() for an
|
||||||
|
* uninitialized request.
|
||||||
|
*/
|
||||||
|
kfree(policy->min_freq_req);
|
||||||
|
policy->min_freq_req = NULL;
|
||||||
|
|
||||||
|
dev_err(dev, "Failed to add min-freq constraint (%d)\n",
|
||||||
|
ret);
|
||||||
|
goto out_destroy_policy;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This must be initialized right here to avoid calling
|
||||||
|
* dev_pm_qos_remove_request() on uninitialized request in case
|
||||||
|
* of errors.
|
||||||
|
*/
|
||||||
|
policy->max_freq_req = policy->min_freq_req + 1;
|
||||||
|
|
||||||
|
ret = dev_pm_qos_add_request(dev, policy->max_freq_req,
|
||||||
|
DEV_PM_QOS_MAX_FREQUENCY,
|
||||||
|
policy->max);
|
||||||
|
if (ret < 0) {
|
||||||
|
policy->max_freq_req = NULL;
|
||||||
|
dev_err(dev, "Failed to add max-freq constraint (%d)\n",
|
||||||
|
ret);
|
||||||
|
goto out_destroy_policy;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cpufreq_driver->get && has_target()) {
|
if (cpufreq_driver->get && has_target()) {
|
||||||
@ -2280,6 +2363,7 @@ int cpufreq_set_policy(struct cpufreq_policy *policy,
|
|||||||
struct cpufreq_policy *new_policy)
|
struct cpufreq_policy *new_policy)
|
||||||
{
|
{
|
||||||
struct cpufreq_governor *old_gov;
|
struct cpufreq_governor *old_gov;
|
||||||
|
struct device *cpu_dev = get_cpu_device(policy->cpu);
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
pr_debug("setting new policy for CPU %u: %u - %u kHz\n",
|
pr_debug("setting new policy for CPU %u: %u - %u kHz\n",
|
||||||
@ -2288,17 +2372,21 @@ int cpufreq_set_policy(struct cpufreq_policy *policy,
|
|||||||
memcpy(&new_policy->cpuinfo, &policy->cpuinfo, sizeof(policy->cpuinfo));
|
memcpy(&new_policy->cpuinfo, &policy->cpuinfo, sizeof(policy->cpuinfo));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This check works well when we store new min/max freq attributes,
|
* PM QoS framework collects all the requests from users and provide us
|
||||||
* because new_policy is a copy of policy with one field updated.
|
* the final aggregated value here.
|
||||||
*/
|
*/
|
||||||
if (new_policy->min > new_policy->max)
|
new_policy->min = dev_pm_qos_read_value(cpu_dev, DEV_PM_QOS_MIN_FREQUENCY);
|
||||||
return -EINVAL;
|
new_policy->max = dev_pm_qos_read_value(cpu_dev, DEV_PM_QOS_MAX_FREQUENCY);
|
||||||
|
|
||||||
/* verify the cpu speed can be set within this limit */
|
/* verify the cpu speed can be set within this limit */
|
||||||
ret = cpufreq_driver->verify(new_policy);
|
ret = cpufreq_driver->verify(new_policy);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The notifier-chain shall be removed once all the users of
|
||||||
|
* CPUFREQ_ADJUST are moved to use the QoS framework.
|
||||||
|
*/
|
||||||
/* adjust if necessary - all reasons */
|
/* adjust if necessary - all reasons */
|
||||||
blocking_notifier_call_chain(&cpufreq_policy_notifier_list,
|
blocking_notifier_call_chain(&cpufreq_policy_notifier_list,
|
||||||
CPUFREQ_ADJUST, new_policy);
|
CPUFREQ_ADJUST, new_policy);
|
||||||
@ -2377,10 +2465,9 @@ int cpufreq_set_policy(struct cpufreq_policy *policy,
|
|||||||
* @cpu: CPU to re-evaluate the policy for.
|
* @cpu: CPU to re-evaluate the policy for.
|
||||||
*
|
*
|
||||||
* Update the current frequency for the cpufreq policy of @cpu and use
|
* Update the current frequency for the cpufreq policy of @cpu and use
|
||||||
* cpufreq_set_policy() to re-apply the min and max limits saved in the
|
* cpufreq_set_policy() to re-apply the min and max limits, which triggers the
|
||||||
* user_policy sub-structure of that policy, which triggers the evaluation
|
* evaluation of policy notifiers and the cpufreq driver's ->verify() callback
|
||||||
* of policy notifiers and the cpufreq driver's ->verify() callback for the
|
* for the policy in question, among other things.
|
||||||
* policy in question, among other things.
|
|
||||||
*/
|
*/
|
||||||
void cpufreq_update_policy(unsigned int cpu)
|
void cpufreq_update_policy(unsigned int cpu)
|
||||||
{
|
{
|
||||||
@ -2440,10 +2527,9 @@ static int cpufreq_boost_set_sw(int state)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
down_write(&policy->rwsem);
|
ret = dev_pm_qos_update_request(policy->max_freq_req, policy->max);
|
||||||
policy->user_policy.max = policy->max;
|
if (ret)
|
||||||
cpufreq_governor_limits(policy);
|
break;
|
||||||
up_write(&policy->rwsem);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -90,7 +90,8 @@ static int davinci_cpu_init(struct cpufreq_policy *policy)
|
|||||||
* Setting the latency to 2000 us to accommodate addition of drivers
|
* Setting the latency to 2000 us to accommodate addition of drivers
|
||||||
* to pre/post change notification list.
|
* to pre/post change notification list.
|
||||||
*/
|
*/
|
||||||
return cpufreq_generic_init(policy, freq_table, 2000 * 1000);
|
cpufreq_generic_init(policy, freq_table, 2000 * 1000);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct cpufreq_driver davinci_driver = {
|
static struct cpufreq_driver davinci_driver = {
|
||||||
|
@ -44,10 +44,11 @@ static int imx_cpufreq_dt_probe(struct platform_device *pdev)
|
|||||||
* According to datasheet minimum speed grading is not supported for
|
* According to datasheet minimum speed grading is not supported for
|
||||||
* consumer parts so clamp to 1 to avoid warning for "no OPPs"
|
* consumer parts so clamp to 1 to avoid warning for "no OPPs"
|
||||||
*
|
*
|
||||||
* Applies to 8mq and 8mm.
|
* Applies to i.MX8M series SoCs.
|
||||||
*/
|
*/
|
||||||
if (mkt_segment == 0 && speed_grade == 0 && (
|
if (mkt_segment == 0 && speed_grade == 0 && (
|
||||||
of_machine_is_compatible("fsl,imx8mm") ||
|
of_machine_is_compatible("fsl,imx8mm") ||
|
||||||
|
of_machine_is_compatible("fsl,imx8mn") ||
|
||||||
of_machine_is_compatible("fsl,imx8mq")))
|
of_machine_is_compatible("fsl,imx8mq")))
|
||||||
speed_grade = 1;
|
speed_grade = 1;
|
||||||
|
|
||||||
|
@ -190,14 +190,12 @@ static int imx6q_set_target(struct cpufreq_policy *policy, unsigned int index)
|
|||||||
|
|
||||||
static int imx6q_cpufreq_init(struct cpufreq_policy *policy)
|
static int imx6q_cpufreq_init(struct cpufreq_policy *policy)
|
||||||
{
|
{
|
||||||
int ret;
|
|
||||||
|
|
||||||
policy->clk = clks[ARM].clk;
|
policy->clk = clks[ARM].clk;
|
||||||
ret = cpufreq_generic_init(policy, freq_table, transition_latency);
|
cpufreq_generic_init(policy, freq_table, transition_latency);
|
||||||
policy->suspend_freq = max_freq;
|
policy->suspend_freq = max_freq;
|
||||||
dev_pm_opp_of_register_em(policy->cpus);
|
dev_pm_opp_of_register_em(policy->cpus);
|
||||||
|
|
||||||
return ret;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct cpufreq_driver imx6q_cpufreq_driver = {
|
static struct cpufreq_driver imx6q_cpufreq_driver = {
|
||||||
|
@ -898,7 +898,6 @@ static void intel_pstate_update_policies(void)
|
|||||||
static void intel_pstate_update_max_freq(unsigned int cpu)
|
static void intel_pstate_update_max_freq(unsigned int cpu)
|
||||||
{
|
{
|
||||||
struct cpufreq_policy *policy = cpufreq_cpu_acquire(cpu);
|
struct cpufreq_policy *policy = cpufreq_cpu_acquire(cpu);
|
||||||
struct cpufreq_policy new_policy;
|
|
||||||
struct cpudata *cpudata;
|
struct cpudata *cpudata;
|
||||||
|
|
||||||
if (!policy)
|
if (!policy)
|
||||||
@ -908,11 +907,7 @@ static void intel_pstate_update_max_freq(unsigned int cpu)
|
|||||||
policy->cpuinfo.max_freq = global.turbo_disabled_mf ?
|
policy->cpuinfo.max_freq = global.turbo_disabled_mf ?
|
||||||
cpudata->pstate.max_freq : cpudata->pstate.turbo_freq;
|
cpudata->pstate.max_freq : cpudata->pstate.turbo_freq;
|
||||||
|
|
||||||
memcpy(&new_policy, policy, sizeof(*policy));
|
refresh_frequency_limits(policy);
|
||||||
new_policy.max = min(policy->user_policy.max, policy->cpuinfo.max_freq);
|
|
||||||
new_policy.min = min(policy->user_policy.min, new_policy.max);
|
|
||||||
|
|
||||||
cpufreq_set_policy(policy, &new_policy);
|
|
||||||
|
|
||||||
cpufreq_cpu_release(policy);
|
cpufreq_cpu_release(policy);
|
||||||
}
|
}
|
||||||
|
@ -85,7 +85,8 @@ static int kirkwood_cpufreq_target(struct cpufreq_policy *policy,
|
|||||||
/* Module init and exit code */
|
/* Module init and exit code */
|
||||||
static int kirkwood_cpufreq_cpu_init(struct cpufreq_policy *policy)
|
static int kirkwood_cpufreq_cpu_init(struct cpufreq_policy *policy)
|
||||||
{
|
{
|
||||||
return cpufreq_generic_init(policy, kirkwood_freq_table, 5000);
|
cpufreq_generic_init(policy, kirkwood_freq_table, 5000);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct cpufreq_driver kirkwood_cpufreq_driver = {
|
static struct cpufreq_driver kirkwood_cpufreq_driver = {
|
||||||
|
@ -81,7 +81,7 @@ static int ls1x_cpufreq_init(struct cpufreq_policy *policy)
|
|||||||
struct device *cpu_dev = get_cpu_device(policy->cpu);
|
struct device *cpu_dev = get_cpu_device(policy->cpu);
|
||||||
struct cpufreq_frequency_table *freq_tbl;
|
struct cpufreq_frequency_table *freq_tbl;
|
||||||
unsigned int pll_freq, freq;
|
unsigned int pll_freq, freq;
|
||||||
int steps, i, ret;
|
int steps, i;
|
||||||
|
|
||||||
pll_freq = clk_get_rate(cpufreq->pll_clk) / 1000;
|
pll_freq = clk_get_rate(cpufreq->pll_clk) / 1000;
|
||||||
|
|
||||||
@ -103,11 +103,9 @@ static int ls1x_cpufreq_init(struct cpufreq_policy *policy)
|
|||||||
freq_tbl[i].frequency = CPUFREQ_TABLE_END;
|
freq_tbl[i].frequency = CPUFREQ_TABLE_END;
|
||||||
|
|
||||||
policy->clk = cpufreq->clk;
|
policy->clk = cpufreq->clk;
|
||||||
ret = cpufreq_generic_init(policy, freq_tbl, 0);
|
cpufreq_generic_init(policy, freq_tbl, 0);
|
||||||
if (ret)
|
|
||||||
kfree(freq_tbl);
|
|
||||||
|
|
||||||
return ret;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ls1x_cpufreq_exit(struct cpufreq_policy *policy)
|
static int ls1x_cpufreq_exit(struct cpufreq_policy *policy)
|
||||||
|
@ -95,7 +95,8 @@ static int loongson2_cpufreq_cpu_init(struct cpufreq_policy *policy)
|
|||||||
}
|
}
|
||||||
|
|
||||||
policy->clk = cpuclk;
|
policy->clk = cpuclk;
|
||||||
return cpufreq_generic_init(policy, &loongson2_clockmod_table[0], 0);
|
cpufreq_generic_init(policy, &loongson2_clockmod_table[0], 0);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int loongson2_cpufreq_exit(struct cpufreq_policy *policy)
|
static int loongson2_cpufreq_exit(struct cpufreq_policy *policy)
|
||||||
|
@ -140,7 +140,8 @@ static unsigned int maple_cpufreq_get_speed(unsigned int cpu)
|
|||||||
|
|
||||||
static int maple_cpufreq_cpu_init(struct cpufreq_policy *policy)
|
static int maple_cpufreq_cpu_init(struct cpufreq_policy *policy)
|
||||||
{
|
{
|
||||||
return cpufreq_generic_init(policy, maple_cpu_freqs, 12000);
|
cpufreq_generic_init(policy, maple_cpu_freqs, 12000);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct cpufreq_driver maple_cpufreq_driver = {
|
static struct cpufreq_driver maple_cpufreq_driver = {
|
||||||
|
@ -122,23 +122,18 @@ static int omap_cpu_init(struct cpufreq_policy *policy)
|
|||||||
dev_err(mpu_dev,
|
dev_err(mpu_dev,
|
||||||
"%s: cpu%d: failed creating freq table[%d]\n",
|
"%s: cpu%d: failed creating freq table[%d]\n",
|
||||||
__func__, policy->cpu, result);
|
__func__, policy->cpu, result);
|
||||||
goto fail;
|
clk_put(policy->clk);
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
atomic_inc_return(&freq_table_users);
|
atomic_inc_return(&freq_table_users);
|
||||||
|
|
||||||
/* FIXME: what's the actual transition time? */
|
/* FIXME: what's the actual transition time? */
|
||||||
result = cpufreq_generic_init(policy, freq_table, 300 * 1000);
|
cpufreq_generic_init(policy, freq_table, 300 * 1000);
|
||||||
if (!result) {
|
dev_pm_opp_of_register_em(policy->cpus);
|
||||||
dev_pm_opp_of_register_em(policy->cpus);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
freq_table_free();
|
return 0;
|
||||||
fail:
|
|
||||||
clk_put(policy->clk);
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int omap_cpu_exit(struct cpufreq_policy *policy)
|
static int omap_cpu_exit(struct cpufreq_policy *policy)
|
||||||
|
@ -196,7 +196,8 @@ static int pas_cpufreq_cpu_init(struct cpufreq_policy *policy)
|
|||||||
policy->cur = pas_freqs[cur_astate].frequency;
|
policy->cur = pas_freqs[cur_astate].frequency;
|
||||||
ppc_proc_freq = policy->cur * 1000ul;
|
ppc_proc_freq = policy->cur * 1000ul;
|
||||||
|
|
||||||
return cpufreq_generic_init(policy, pas_freqs, get_gizmo_latency());
|
cpufreq_generic_init(policy, pas_freqs, get_gizmo_latency());
|
||||||
|
return 0;
|
||||||
|
|
||||||
out_unmap_sdcpwr:
|
out_unmap_sdcpwr:
|
||||||
iounmap(sdcpwr_mapbase);
|
iounmap(sdcpwr_mapbase);
|
||||||
|
@ -372,7 +372,8 @@ static int pmac_cpufreq_target( struct cpufreq_policy *policy,
|
|||||||
|
|
||||||
static int pmac_cpufreq_cpu_init(struct cpufreq_policy *policy)
|
static int pmac_cpufreq_cpu_init(struct cpufreq_policy *policy)
|
||||||
{
|
{
|
||||||
return cpufreq_generic_init(policy, pmac_cpu_freqs, transition_latency);
|
cpufreq_generic_init(policy, pmac_cpu_freqs, transition_latency);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static u32 read_gpio(struct device_node *np)
|
static u32 read_gpio(struct device_node *np)
|
||||||
|
@ -321,7 +321,8 @@ static unsigned int g5_cpufreq_get_speed(unsigned int cpu)
|
|||||||
|
|
||||||
static int g5_cpufreq_cpu_init(struct cpufreq_policy *policy)
|
static int g5_cpufreq_cpu_init(struct cpufreq_policy *policy)
|
||||||
{
|
{
|
||||||
return cpufreq_generic_init(policy, g5_cpu_freqs, transition_latency);
|
cpufreq_generic_init(policy, g5_cpu_freqs, transition_latency);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct cpufreq_driver g5_cpufreq_driver = {
|
static struct cpufreq_driver g5_cpufreq_driver = {
|
||||||
|
@ -447,21 +447,16 @@ static int s3c2416_cpufreq_driver_init(struct cpufreq_policy *policy)
|
|||||||
/* Datasheet says PLL stabalisation time must be at least 300us,
|
/* Datasheet says PLL stabalisation time must be at least 300us,
|
||||||
* so but add some fudge. (reference in LOCKCON0 register description)
|
* so but add some fudge. (reference in LOCKCON0 register description)
|
||||||
*/
|
*/
|
||||||
ret = cpufreq_generic_init(policy, s3c_freq->freq_table,
|
cpufreq_generic_init(policy, s3c_freq->freq_table,
|
||||||
(500 * 1000) + s3c_freq->regulator_latency);
|
(500 * 1000) + s3c_freq->regulator_latency);
|
||||||
if (ret)
|
|
||||||
goto err_freq_table;
|
|
||||||
|
|
||||||
register_reboot_notifier(&s3c2416_cpufreq_reboot_notifier);
|
register_reboot_notifier(&s3c2416_cpufreq_reboot_notifier);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
err_freq_table:
|
|
||||||
#ifdef CONFIG_ARM_S3C2416_CPUFREQ_VCORESCALE
|
#ifdef CONFIG_ARM_S3C2416_CPUFREQ_VCORESCALE
|
||||||
regulator_put(s3c_freq->vddarm);
|
|
||||||
err_vddarm:
|
err_vddarm:
|
||||||
#endif
|
|
||||||
clk_put(s3c_freq->armclk);
|
clk_put(s3c_freq->armclk);
|
||||||
|
#endif
|
||||||
err_armclk:
|
err_armclk:
|
||||||
clk_put(s3c_freq->hclk);
|
clk_put(s3c_freq->hclk);
|
||||||
err_hclk:
|
err_hclk:
|
||||||
|
@ -144,7 +144,6 @@ static void s3c64xx_cpufreq_config_regulator(void)
|
|||||||
|
|
||||||
static int s3c64xx_cpufreq_driver_init(struct cpufreq_policy *policy)
|
static int s3c64xx_cpufreq_driver_init(struct cpufreq_policy *policy)
|
||||||
{
|
{
|
||||||
int ret;
|
|
||||||
struct cpufreq_frequency_table *freq;
|
struct cpufreq_frequency_table *freq;
|
||||||
|
|
||||||
if (policy->cpu != 0)
|
if (policy->cpu != 0)
|
||||||
@ -165,8 +164,7 @@ static int s3c64xx_cpufreq_driver_init(struct cpufreq_policy *policy)
|
|||||||
#ifdef CONFIG_REGULATOR
|
#ifdef CONFIG_REGULATOR
|
||||||
vddarm = regulator_get(NULL, "vddarm");
|
vddarm = regulator_get(NULL, "vddarm");
|
||||||
if (IS_ERR(vddarm)) {
|
if (IS_ERR(vddarm)) {
|
||||||
ret = PTR_ERR(vddarm);
|
pr_err("Failed to obtain VDDARM: %ld\n", PTR_ERR(vddarm));
|
||||||
pr_err("Failed to obtain VDDARM: %d\n", ret);
|
|
||||||
pr_err("Only frequency scaling available\n");
|
pr_err("Only frequency scaling available\n");
|
||||||
vddarm = NULL;
|
vddarm = NULL;
|
||||||
} else {
|
} else {
|
||||||
@ -196,16 +194,9 @@ static int s3c64xx_cpufreq_driver_init(struct cpufreq_policy *policy)
|
|||||||
* the PLLs, which we don't currently) is ~300us worst case,
|
* the PLLs, which we don't currently) is ~300us worst case,
|
||||||
* but add some fudge.
|
* but add some fudge.
|
||||||
*/
|
*/
|
||||||
ret = cpufreq_generic_init(policy, s3c64xx_freq_table,
|
cpufreq_generic_init(policy, s3c64xx_freq_table,
|
||||||
(500 * 1000) + regulator_latency);
|
(500 * 1000) + regulator_latency);
|
||||||
if (ret != 0) {
|
return 0;
|
||||||
pr_err("Failed to configure frequency table: %d\n",
|
|
||||||
ret);
|
|
||||||
regulator_put(vddarm);
|
|
||||||
clk_put(policy->clk);
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct cpufreq_driver s3c64xx_cpufreq_driver = {
|
static struct cpufreq_driver s3c64xx_cpufreq_driver = {
|
||||||
|
@ -541,7 +541,8 @@ static int s5pv210_cpu_init(struct cpufreq_policy *policy)
|
|||||||
s5pv210_dram_conf[1].freq = clk_get_rate(dmc1_clk);
|
s5pv210_dram_conf[1].freq = clk_get_rate(dmc1_clk);
|
||||||
|
|
||||||
policy->suspend_freq = SLEEP_FREQ;
|
policy->suspend_freq = SLEEP_FREQ;
|
||||||
return cpufreq_generic_init(policy, s5pv210_freq_table, 40000);
|
cpufreq_generic_init(policy, s5pv210_freq_table, 40000);
|
||||||
|
return 0;
|
||||||
|
|
||||||
out_dmc1:
|
out_dmc1:
|
||||||
clk_put(dmc0_clk);
|
clk_put(dmc0_clk);
|
||||||
|
@ -181,7 +181,8 @@ static int sa1100_target(struct cpufreq_policy *policy, unsigned int ppcr)
|
|||||||
|
|
||||||
static int __init sa1100_cpu_init(struct cpufreq_policy *policy)
|
static int __init sa1100_cpu_init(struct cpufreq_policy *policy)
|
||||||
{
|
{
|
||||||
return cpufreq_generic_init(policy, sa11x0_freq_table, 0);
|
cpufreq_generic_init(policy, sa11x0_freq_table, 0);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct cpufreq_driver sa1100_driver __refdata = {
|
static struct cpufreq_driver sa1100_driver __refdata = {
|
||||||
|
@ -303,7 +303,8 @@ static int sa1110_target(struct cpufreq_policy *policy, unsigned int ppcr)
|
|||||||
|
|
||||||
static int __init sa1110_cpu_init(struct cpufreq_policy *policy)
|
static int __init sa1110_cpu_init(struct cpufreq_policy *policy)
|
||||||
{
|
{
|
||||||
return cpufreq_generic_init(policy, sa11x0_freq_table, 0);
|
cpufreq_generic_init(policy, sa11x0_freq_table, 0);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* sa1110_driver needs __refdata because it must remain after init registers
|
/* sa1110_driver needs __refdata because it must remain after init registers
|
||||||
|
@ -153,8 +153,9 @@ static int spear_cpufreq_target(struct cpufreq_policy *policy,
|
|||||||
static int spear_cpufreq_init(struct cpufreq_policy *policy)
|
static int spear_cpufreq_init(struct cpufreq_policy *policy)
|
||||||
{
|
{
|
||||||
policy->clk = spear_cpufreq.clk;
|
policy->clk = spear_cpufreq.clk;
|
||||||
return cpufreq_generic_init(policy, spear_cpufreq.freq_tbl,
|
cpufreq_generic_init(policy, spear_cpufreq.freq_tbl,
|
||||||
spear_cpufreq.transition_latency);
|
spear_cpufreq.transition_latency);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct cpufreq_driver spear_cpufreq_driver = {
|
static struct cpufreq_driver spear_cpufreq_driver = {
|
||||||
|
@ -118,17 +118,11 @@ static int tegra_target(struct cpufreq_policy *policy, unsigned int index)
|
|||||||
static int tegra_cpu_init(struct cpufreq_policy *policy)
|
static int tegra_cpu_init(struct cpufreq_policy *policy)
|
||||||
{
|
{
|
||||||
struct tegra20_cpufreq *cpufreq = cpufreq_get_driver_data();
|
struct tegra20_cpufreq *cpufreq = cpufreq_get_driver_data();
|
||||||
int ret;
|
|
||||||
|
|
||||||
clk_prepare_enable(cpufreq->cpu_clk);
|
clk_prepare_enable(cpufreq->cpu_clk);
|
||||||
|
|
||||||
/* FIXME: what's the actual transition time? */
|
/* FIXME: what's the actual transition time? */
|
||||||
ret = cpufreq_generic_init(policy, freq_table, 300 * 1000);
|
cpufreq_generic_init(policy, freq_table, 300 * 1000);
|
||||||
if (ret) {
|
|
||||||
clk_disable_unprepare(cpufreq->cpu_clk);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
policy->clk = cpufreq->cpu_clk;
|
policy->clk = cpufreq->cpu_clk;
|
||||||
policy->suspend_freq = freq_table[0].frequency;
|
policy->suspend_freq = freq_table[0].frequency;
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -110,7 +110,7 @@ int cpuidle_governor_latency_req(unsigned int cpu)
|
|||||||
{
|
{
|
||||||
int global_req = pm_qos_request(PM_QOS_CPU_DMA_LATENCY);
|
int global_req = pm_qos_request(PM_QOS_CPU_DMA_LATENCY);
|
||||||
struct device *device = get_cpu_device(cpu);
|
struct device *device = get_cpu_device(cpu);
|
||||||
int device_req = dev_pm_qos_raw_read_value(device);
|
int device_req = dev_pm_qos_raw_resume_latency(device);
|
||||||
|
|
||||||
return device_req < global_req ? device_req : global_req;
|
return device_req < global_req ? device_req : global_req;
|
||||||
}
|
}
|
||||||
|
@ -47,11 +47,6 @@ struct cpufreq_cpuinfo {
|
|||||||
unsigned int transition_latency;
|
unsigned int transition_latency;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct cpufreq_user_policy {
|
|
||||||
unsigned int min; /* in kHz */
|
|
||||||
unsigned int max; /* in kHz */
|
|
||||||
};
|
|
||||||
|
|
||||||
struct cpufreq_policy {
|
struct cpufreq_policy {
|
||||||
/* CPUs sharing clock, require sw coordination */
|
/* CPUs sharing clock, require sw coordination */
|
||||||
cpumask_var_t cpus; /* Online CPUs only */
|
cpumask_var_t cpus; /* Online CPUs only */
|
||||||
@ -81,7 +76,8 @@ struct cpufreq_policy {
|
|||||||
struct work_struct update; /* if update_policy() needs to be
|
struct work_struct update; /* if update_policy() needs to be
|
||||||
* called, but you're in IRQ context */
|
* called, but you're in IRQ context */
|
||||||
|
|
||||||
struct cpufreq_user_policy user_policy;
|
struct dev_pm_qos_request *min_freq_req;
|
||||||
|
struct dev_pm_qos_request *max_freq_req;
|
||||||
struct cpufreq_frequency_table *freq_table;
|
struct cpufreq_frequency_table *freq_table;
|
||||||
enum cpufreq_table_sorting freq_table_sorted;
|
enum cpufreq_table_sorting freq_table_sorted;
|
||||||
|
|
||||||
@ -144,6 +140,9 @@ struct cpufreq_policy {
|
|||||||
|
|
||||||
/* Pointer to the cooling device if used for thermal mitigation */
|
/* Pointer to the cooling device if used for thermal mitigation */
|
||||||
struct thermal_cooling_device *cdev;
|
struct thermal_cooling_device *cdev;
|
||||||
|
|
||||||
|
struct notifier_block nb_min;
|
||||||
|
struct notifier_block nb_max;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct cpufreq_freqs {
|
struct cpufreq_freqs {
|
||||||
@ -201,6 +200,7 @@ void cpufreq_cpu_release(struct cpufreq_policy *policy);
|
|||||||
int cpufreq_get_policy(struct cpufreq_policy *policy, unsigned int cpu);
|
int cpufreq_get_policy(struct cpufreq_policy *policy, unsigned int cpu);
|
||||||
int cpufreq_set_policy(struct cpufreq_policy *policy,
|
int cpufreq_set_policy(struct cpufreq_policy *policy,
|
||||||
struct cpufreq_policy *new_policy);
|
struct cpufreq_policy *new_policy);
|
||||||
|
void refresh_frequency_limits(struct cpufreq_policy *policy);
|
||||||
void cpufreq_update_policy(unsigned int cpu);
|
void cpufreq_update_policy(unsigned int cpu);
|
||||||
void cpufreq_update_limits(unsigned int cpu);
|
void cpufreq_update_limits(unsigned int cpu);
|
||||||
bool have_governor_per_policy(void);
|
bool have_governor_per_policy(void);
|
||||||
@ -992,7 +992,7 @@ extern struct freq_attr *cpufreq_generic_attr[];
|
|||||||
int cpufreq_table_validate_and_sort(struct cpufreq_policy *policy);
|
int cpufreq_table_validate_and_sort(struct cpufreq_policy *policy);
|
||||||
|
|
||||||
unsigned int cpufreq_generic_get(unsigned int cpu);
|
unsigned int cpufreq_generic_get(unsigned int cpu);
|
||||||
int cpufreq_generic_init(struct cpufreq_policy *policy,
|
void cpufreq_generic_init(struct cpufreq_policy *policy,
|
||||||
struct cpufreq_frequency_table *table,
|
struct cpufreq_frequency_table *table,
|
||||||
unsigned int transition_latency);
|
unsigned int transition_latency);
|
||||||
#endif /* _LINUX_CPUFREQ_H */
|
#endif /* _LINUX_CPUFREQ_H */
|
||||||
|
@ -40,6 +40,8 @@ enum pm_qos_flags_status {
|
|||||||
#define PM_QOS_RESUME_LATENCY_NO_CONSTRAINT PM_QOS_LATENCY_ANY
|
#define PM_QOS_RESUME_LATENCY_NO_CONSTRAINT PM_QOS_LATENCY_ANY
|
||||||
#define PM_QOS_RESUME_LATENCY_NO_CONSTRAINT_NS PM_QOS_LATENCY_ANY_NS
|
#define PM_QOS_RESUME_LATENCY_NO_CONSTRAINT_NS PM_QOS_LATENCY_ANY_NS
|
||||||
#define PM_QOS_LATENCY_TOLERANCE_DEFAULT_VALUE 0
|
#define PM_QOS_LATENCY_TOLERANCE_DEFAULT_VALUE 0
|
||||||
|
#define PM_QOS_MIN_FREQUENCY_DEFAULT_VALUE 0
|
||||||
|
#define PM_QOS_MAX_FREQUENCY_DEFAULT_VALUE (-1)
|
||||||
#define PM_QOS_LATENCY_TOLERANCE_NO_CONSTRAINT (-1)
|
#define PM_QOS_LATENCY_TOLERANCE_NO_CONSTRAINT (-1)
|
||||||
|
|
||||||
#define PM_QOS_FLAG_NO_POWER_OFF (1 << 0)
|
#define PM_QOS_FLAG_NO_POWER_OFF (1 << 0)
|
||||||
@ -58,6 +60,8 @@ struct pm_qos_flags_request {
|
|||||||
enum dev_pm_qos_req_type {
|
enum dev_pm_qos_req_type {
|
||||||
DEV_PM_QOS_RESUME_LATENCY = 1,
|
DEV_PM_QOS_RESUME_LATENCY = 1,
|
||||||
DEV_PM_QOS_LATENCY_TOLERANCE,
|
DEV_PM_QOS_LATENCY_TOLERANCE,
|
||||||
|
DEV_PM_QOS_MIN_FREQUENCY,
|
||||||
|
DEV_PM_QOS_MAX_FREQUENCY,
|
||||||
DEV_PM_QOS_FLAGS,
|
DEV_PM_QOS_FLAGS,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -99,10 +103,14 @@ struct pm_qos_flags {
|
|||||||
struct dev_pm_qos {
|
struct dev_pm_qos {
|
||||||
struct pm_qos_constraints resume_latency;
|
struct pm_qos_constraints resume_latency;
|
||||||
struct pm_qos_constraints latency_tolerance;
|
struct pm_qos_constraints latency_tolerance;
|
||||||
|
struct pm_qos_constraints min_frequency;
|
||||||
|
struct pm_qos_constraints max_frequency;
|
||||||
struct pm_qos_flags flags;
|
struct pm_qos_flags flags;
|
||||||
struct dev_pm_qos_request *resume_latency_req;
|
struct dev_pm_qos_request *resume_latency_req;
|
||||||
struct dev_pm_qos_request *latency_tolerance_req;
|
struct dev_pm_qos_request *latency_tolerance_req;
|
||||||
struct dev_pm_qos_request *flags_req;
|
struct dev_pm_qos_request *flags_req;
|
||||||
|
struct dev_pm_qos_request *min_frequency_req;
|
||||||
|
struct dev_pm_qos_request *max_frequency_req;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Action requested to pm_qos_update_target */
|
/* Action requested to pm_qos_update_target */
|
||||||
@ -139,16 +147,18 @@ s32 pm_qos_read_value(struct pm_qos_constraints *c);
|
|||||||
#ifdef CONFIG_PM
|
#ifdef CONFIG_PM
|
||||||
enum pm_qos_flags_status __dev_pm_qos_flags(struct device *dev, s32 mask);
|
enum pm_qos_flags_status __dev_pm_qos_flags(struct device *dev, s32 mask);
|
||||||
enum pm_qos_flags_status dev_pm_qos_flags(struct device *dev, s32 mask);
|
enum pm_qos_flags_status dev_pm_qos_flags(struct device *dev, s32 mask);
|
||||||
s32 __dev_pm_qos_read_value(struct device *dev);
|
s32 __dev_pm_qos_resume_latency(struct device *dev);
|
||||||
s32 dev_pm_qos_read_value(struct device *dev);
|
s32 dev_pm_qos_read_value(struct device *dev, enum dev_pm_qos_req_type type);
|
||||||
int dev_pm_qos_add_request(struct device *dev, struct dev_pm_qos_request *req,
|
int dev_pm_qos_add_request(struct device *dev, struct dev_pm_qos_request *req,
|
||||||
enum dev_pm_qos_req_type type, s32 value);
|
enum dev_pm_qos_req_type type, s32 value);
|
||||||
int dev_pm_qos_update_request(struct dev_pm_qos_request *req, s32 new_value);
|
int dev_pm_qos_update_request(struct dev_pm_qos_request *req, s32 new_value);
|
||||||
int dev_pm_qos_remove_request(struct dev_pm_qos_request *req);
|
int dev_pm_qos_remove_request(struct dev_pm_qos_request *req);
|
||||||
int dev_pm_qos_add_notifier(struct device *dev,
|
int dev_pm_qos_add_notifier(struct device *dev,
|
||||||
struct notifier_block *notifier);
|
struct notifier_block *notifier,
|
||||||
|
enum dev_pm_qos_req_type type);
|
||||||
int dev_pm_qos_remove_notifier(struct device *dev,
|
int dev_pm_qos_remove_notifier(struct device *dev,
|
||||||
struct notifier_block *notifier);
|
struct notifier_block *notifier,
|
||||||
|
enum dev_pm_qos_req_type type);
|
||||||
void dev_pm_qos_constraints_init(struct device *dev);
|
void dev_pm_qos_constraints_init(struct device *dev);
|
||||||
void dev_pm_qos_constraints_destroy(struct device *dev);
|
void dev_pm_qos_constraints_destroy(struct device *dev);
|
||||||
int dev_pm_qos_add_ancestor_request(struct device *dev,
|
int dev_pm_qos_add_ancestor_request(struct device *dev,
|
||||||
@ -174,7 +184,7 @@ static inline s32 dev_pm_qos_requested_flags(struct device *dev)
|
|||||||
return dev->power.qos->flags_req->data.flr.flags;
|
return dev->power.qos->flags_req->data.flr.flags;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline s32 dev_pm_qos_raw_read_value(struct device *dev)
|
static inline s32 dev_pm_qos_raw_resume_latency(struct device *dev)
|
||||||
{
|
{
|
||||||
return IS_ERR_OR_NULL(dev->power.qos) ?
|
return IS_ERR_OR_NULL(dev->power.qos) ?
|
||||||
PM_QOS_RESUME_LATENCY_NO_CONSTRAINT :
|
PM_QOS_RESUME_LATENCY_NO_CONSTRAINT :
|
||||||
@ -187,10 +197,24 @@ static inline enum pm_qos_flags_status __dev_pm_qos_flags(struct device *dev,
|
|||||||
static inline enum pm_qos_flags_status dev_pm_qos_flags(struct device *dev,
|
static inline enum pm_qos_flags_status dev_pm_qos_flags(struct device *dev,
|
||||||
s32 mask)
|
s32 mask)
|
||||||
{ return PM_QOS_FLAGS_UNDEFINED; }
|
{ return PM_QOS_FLAGS_UNDEFINED; }
|
||||||
static inline s32 __dev_pm_qos_read_value(struct device *dev)
|
static inline s32 __dev_pm_qos_resume_latency(struct device *dev)
|
||||||
{ return PM_QOS_RESUME_LATENCY_NO_CONSTRAINT; }
|
|
||||||
static inline s32 dev_pm_qos_read_value(struct device *dev)
|
|
||||||
{ return PM_QOS_RESUME_LATENCY_NO_CONSTRAINT; }
|
{ return PM_QOS_RESUME_LATENCY_NO_CONSTRAINT; }
|
||||||
|
static inline s32 dev_pm_qos_read_value(struct device *dev,
|
||||||
|
enum dev_pm_qos_req_type type)
|
||||||
|
{
|
||||||
|
switch (type) {
|
||||||
|
case DEV_PM_QOS_RESUME_LATENCY:
|
||||||
|
return PM_QOS_RESUME_LATENCY_NO_CONSTRAINT;
|
||||||
|
case DEV_PM_QOS_MIN_FREQUENCY:
|
||||||
|
return PM_QOS_MIN_FREQUENCY_DEFAULT_VALUE;
|
||||||
|
case DEV_PM_QOS_MAX_FREQUENCY:
|
||||||
|
return PM_QOS_MAX_FREQUENCY_DEFAULT_VALUE;
|
||||||
|
default:
|
||||||
|
WARN_ON(1);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static inline int dev_pm_qos_add_request(struct device *dev,
|
static inline int dev_pm_qos_add_request(struct device *dev,
|
||||||
struct dev_pm_qos_request *req,
|
struct dev_pm_qos_request *req,
|
||||||
enum dev_pm_qos_req_type type,
|
enum dev_pm_qos_req_type type,
|
||||||
@ -202,10 +226,12 @@ static inline int dev_pm_qos_update_request(struct dev_pm_qos_request *req,
|
|||||||
static inline int dev_pm_qos_remove_request(struct dev_pm_qos_request *req)
|
static inline int dev_pm_qos_remove_request(struct dev_pm_qos_request *req)
|
||||||
{ return 0; }
|
{ return 0; }
|
||||||
static inline int dev_pm_qos_add_notifier(struct device *dev,
|
static inline int dev_pm_qos_add_notifier(struct device *dev,
|
||||||
struct notifier_block *notifier)
|
struct notifier_block *notifier,
|
||||||
|
enum dev_pm_qos_req_type type)
|
||||||
{ return 0; }
|
{ return 0; }
|
||||||
static inline int dev_pm_qos_remove_notifier(struct device *dev,
|
static inline int dev_pm_qos_remove_notifier(struct device *dev,
|
||||||
struct notifier_block *notifier)
|
struct notifier_block *notifier,
|
||||||
|
enum dev_pm_qos_req_type type)
|
||||||
{ return 0; }
|
{ return 0; }
|
||||||
static inline void dev_pm_qos_constraints_init(struct device *dev)
|
static inline void dev_pm_qos_constraints_init(struct device *dev)
|
||||||
{
|
{
|
||||||
@ -241,7 +267,7 @@ static inline s32 dev_pm_qos_requested_resume_latency(struct device *dev)
|
|||||||
return PM_QOS_RESUME_LATENCY_NO_CONSTRAINT;
|
return PM_QOS_RESUME_LATENCY_NO_CONSTRAINT;
|
||||||
}
|
}
|
||||||
static inline s32 dev_pm_qos_requested_flags(struct device *dev) { return 0; }
|
static inline s32 dev_pm_qos_requested_flags(struct device *dev) { return 0; }
|
||||||
static inline s32 dev_pm_qos_raw_read_value(struct device *dev)
|
static inline s32 dev_pm_qos_raw_resume_latency(struct device *dev)
|
||||||
{
|
{
|
||||||
return PM_QOS_RESUME_LATENCY_NO_CONSTRAINT;
|
return PM_QOS_RESUME_LATENCY_NO_CONSTRAINT;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user