mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-29 03:01:39 -04:00
More power management updates for 5.3-rc1
- Add MMIO interface support to the Intel RAPL power capping
driver and update the int340X thermal driver to provide a
RAPL MMIO interface (Zhang Rui, Stephen Rothwell).
- Add Intel Ice Lake CPU IDs to the RAPL driver (Zhang Rui,
Rajneesh Bhardwaj).
- Make cpufreq use the PM QoS framework (instead of notifiers) for
managing the min and max frequency constraints (Viresh Kumar).
- Add i.MX8MN support to the imx-cpufreq-dt cpufreq driver (Anson
Huang).
-----BEGIN PGP SIGNATURE-----
iQJGBAABCAAwFiEE4fcc61cGeeHD/fCwgsRv/nhiVHEFAl0wLTgSHHJqd0Byand5
c29ja2kubmV0AAoJEILEb/54YlRxpckP/2DmQ5ydn1EvY47mpMtdEcnptCaMUwoM
xL6oo3hcpZsmHL8uslESW/LCE+Zadq1oz0k8rCiMKIzbujTzaDD+Pbzd/8ueY8nK
YHyNMQaVS23iixix0/UqTsDd2zk2HNvaBGihHhnQAS0tXdJKgvWa7lgIpG2rBQL3
7P/aug1xum1r6DSbDA1+4dQ7XAZcLzK8mw25mdBRo+exBxGCJreOUu1K8DaQ4wrw
aw2DuvBUk4+wmE1acq693uLbDjGA26F6H2Ul/BpcvYK2Bdn+Ec8sOK1N/xkRxdbc
0IxozORawIG6SQRrP1+N+3Tmau79iOnSSAOAtum6XJ06bRvRXo48IrbtnTHuYCrO
gLLzG9DkjYeJx1ymcqQXscAhH4cwm2zEvBqCdy9RXXViZVHmWfN9LeGlYTc9lV33
+X9Co7XevOA3f4DRVhbDFJi/neVEu+RIeBfd7F0dnU0nY2pbtHrBducmTiQOQG2N
HiQ0HPTrMJI7qmr56AxnXQPqvlDP3ys/dygid/vIZL/7Pjqa2T6oWqixvQR+T5/X
wajJM5k8d+KVW0QuuKBGTzhRCjnD+fqGagn+X9kaF8F66i9tMeeSYhd7abIBxMQV
nU61DsOgLWmulrk3f1BSdKaig0U9QMxQLIZI15/CuLH8hv/ctuodCDJLxXykfxlG
CaJOoWC18kj2
=Svee
-----END PGP SIGNATURE-----
Merge tag 'pm-5.3-rc1-2' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm
Pull more power management updates from Rafael Wysocki:
"These modify the Intel RAPL driver to allow it to use an MMIO
interface to the hardware, make the int340X thermal driver provide
such an interface for it, add Intel Ice Lake CPU IDs to the RAPL
driver (these changes depend on the previously merged x86 arch
changes), update cpufreq to use the PM QoS framework for managing the
min and max frequency limits, and add update the imx-cpufreq-dt
cpufreq driver to support i.MX8MN.
Specifics:
- Add MMIO interface support to the Intel RAPL power capping driver
and update the int340X thermal driver to provide a RAPL MMIO
interface (Zhang Rui, Stephen Rothwell).
- Add Intel Ice Lake CPU IDs to the RAPL driver (Zhang Rui, Rajneesh
Bhardwaj).
- Make cpufreq use the PM QoS framework (instead of notifiers) for
managing the min and max frequency constraints (Viresh Kumar).
- Add i.MX8MN support to the imx-cpufreq-dt cpufreq driver (Anson
Huang)"
* tag 'pm-5.3-rc1-2' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm: (27 commits)
cpufreq: Make cpufreq_generic_init() return void
intel_rapl: need linux/cpuhotplug.h for enum cpuhp_state
powercap/rapl: Add Ice Lake NNPI support to RAPL driver
powercap/intel_rapl: add support for ICX-D
powercap/intel_rapl: add support for ICX
powercap/intel_rapl: add support for IceLake desktop
intel_rapl: Fix module autoloading issue
int340X/processor_thermal_device: add support for MMIO RAPL
intel_rapl: support two power limits for every RAPL domain
intel_rapl: support 64 bit register
intel_rapl: abstract RAPL common code
intel_rapl: cleanup hardcoded MSR access
intel_rapl: cleanup some functions
intel_rapl: abstract register access operations
intel_rapl: abstract register address
intel_rapl: introduce struct rapl_if_private
intel_rapl: introduce intel_rapl.h
intel_rapl: remove hardcoded register index
intel_rapl: use reg instead of msr
cpufreq: imx-cpufreq-dt: Add i.MX8MN support
...
This commit is contained in:
commit
d0411ec8ca
37 changed files with 1196 additions and 699 deletions
|
|
@ -1536,7 +1536,8 @@ static int genpd_add_device(struct generic_pm_domain *genpd, struct device *dev,
|
|||
if (ret)
|
||||
genpd_free_dev_data(dev, gpd_data);
|
||||
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;
|
||||
}
|
||||
|
|
@ -1569,7 +1570,8 @@ static int genpd_remove_device(struct generic_pm_domain *genpd,
|
|||
|
||||
pdd = dev->power.subsys_data->domain_data;
|
||||
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);
|
||||
|
||||
|
|
@ -1597,7 +1599,7 @@ static int genpd_remove_device(struct generic_pm_domain *genpd,
|
|||
|
||||
out:
|
||||
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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
* 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;
|
||||
}
|
||||
|
||||
|
|
@ -66,7 +66,7 @@ static bool default_suspend_ok(struct device *dev)
|
|||
td->constraint_changed = false;
|
||||
td->cached_suspend_ok = false;
|
||||
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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
/**
|
||||
* __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.
|
||||
*
|
||||
* 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);
|
||||
|
||||
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: 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;
|
||||
s32 ret;
|
||||
|
||||
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);
|
||||
|
||||
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);
|
||||
}
|
||||
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:
|
||||
ret = pm_qos_update_flags(&qos->flags, &req->data.flr,
|
||||
action, value);
|
||||
|
|
@ -177,12 +205,11 @@ static int dev_pm_qos_constraints_allocate(struct device *dev)
|
|||
if (!qos)
|
||||
return -ENOMEM;
|
||||
|
||||
n = kzalloc(sizeof(*n), GFP_KERNEL);
|
||||
n = kzalloc(3 * sizeof(*n), GFP_KERNEL);
|
||||
if (!n) {
|
||||
kfree(qos);
|
||||
return -ENOMEM;
|
||||
}
|
||||
BLOCKING_INIT_NOTIFIER_HEAD(n);
|
||||
|
||||
c = &qos->resume_latency;
|
||||
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->type = PM_QOS_MIN;
|
||||
c->notifiers = n;
|
||||
BLOCKING_INIT_NOTIFIER_HEAD(n);
|
||||
|
||||
c = &qos->latency_tolerance;
|
||||
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->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);
|
||||
|
||||
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);
|
||||
memset(req, 0, sizeof(*req));
|
||||
}
|
||||
|
||||
c = &qos->latency_tolerance;
|
||||
plist_for_each_entry_safe(req, tmp, &c->list, data.pnode) {
|
||||
apply_constraint(req, PM_QOS_REMOVE_REQ, PM_QOS_DEFAULT_VALUE);
|
||||
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;
|
||||
list_for_each_entry_safe(req, tmp, &f->list, data.flr.node) {
|
||||
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) {
|
||||
case DEV_PM_QOS_RESUME_LATENCY:
|
||||
case DEV_PM_QOS_LATENCY_TOLERANCE:
|
||||
case DEV_PM_QOS_MIN_FREQUENCY:
|
||||
case DEV_PM_QOS_MAX_FREQUENCY:
|
||||
curr_value = req->data.pnode.prio;
|
||||
break;
|
||||
case DEV_PM_QOS_FLAGS:
|
||||
|
|
@ -467,6 +529,7 @@ EXPORT_SYMBOL_GPL(dev_pm_qos_remove_request);
|
|||
*
|
||||
* @dev: target device for the constraint
|
||||
* @notifier: notifier block managed by caller.
|
||||
* @type: request type.
|
||||
*
|
||||
* Will register the notifier into a notification chain that gets called
|
||||
* 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,
|
||||
* 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;
|
||||
|
||||
|
|
@ -485,10 +549,28 @@ int dev_pm_qos_add_notifier(struct device *dev, struct notifier_block *notifier)
|
|||
else if (!dev->power.qos)
|
||||
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,
|
||||
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);
|
||||
return ret;
|
||||
}
|
||||
|
|
@ -500,24 +582,44 @@ EXPORT_SYMBOL_GPL(dev_pm_qos_add_notifier);
|
|||
*
|
||||
* @dev: target device for the constraint
|
||||
* @notifier: notifier block to be removed.
|
||||
* @type: request type.
|
||||
*
|
||||
* Will remove the notifier from the notification chain that gets called
|
||||
* upon changes to the target value.
|
||||
*/
|
||||
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);
|
||||
|
||||
/* Silently return if the constraints object is not present. */
|
||||
if (!IS_ERR_OR_NULL(dev->power.qos))
|
||||
retval = blocking_notifier_chain_unregister(dev->power.qos->resume_latency.notifiers,
|
||||
notifier);
|
||||
if (IS_ERR_OR_NULL(dev->power.qos))
|
||||
goto unlock;
|
||||
|
||||
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);
|
||||
return retval;
|
||||
return ret;
|
||||
}
|
||||
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;
|
||||
dev->power.qos->flags_req = NULL;
|
||||
break;
|
||||
default:
|
||||
WARN_ON(1);
|
||||
return;
|
||||
}
|
||||
__dev_pm_qos_remove_request(req);
|
||||
kfree(req);
|
||||
|
|
|
|||
|
|
@ -275,7 +275,7 @@ static int rpm_check_suspend_allowed(struct device *dev)
|
|||
|| (dev->power.request_pending
|
||||
&& dev->power.request == RPM_REQ_RESUME))
|
||||
retval = -EAGAIN;
|
||||
else if (__dev_pm_qos_read_value(dev) == 0)
|
||||
else if (__dev_pm_qos_resume_latency(dev) == 0)
|
||||
retval = -EPERM;
|
||||
else if (dev->power.runtime_status == RPM_SUSPENDED)
|
||||
retval = 1;
|
||||
|
|
|
|||
Loading…
Reference in a new issue