Commit 6876eb37 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'pm-4.14-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm

Pull power management fixes from Rafael Wysocki:
 "These fix a cpufreq regression introduced by recent changes related to
  the generic DT driver, an initialization time memory leak in cpuidle
  on ARM, a PM core bug that may cause system suspend/resume to fail on
  some systems, a request type validation issue in the PM QoS framework
  and two documentation-related issues.

  Specifics:

   - Fix a regression in cpufreq on systems using DT as the source of
     CPU configuration information where two different code paths
     attempt to create the cpufreq-dt device object (there can be only
     one) and fix up the "compatible" matching for some TI platforms on
     top of that (Viresh Kumar, Dave Gerlach).

   - Fix an initialization time memory leak in cpuidle on ARM which
     occurs if the cpuidle driver initialization fails (Stefan Wahren).

   - Fix a PM core function that checks whether or not there are any
     system suspend/resume callbacks for a device, but forgets to check
     legacy callbacks which then may be skipped incorrectly and the
     system may crash and/or the device may become unusable after a
     suspend-resume cycle (Rafael Wysocki).

   - Fix request type validation for latency tolerance PM QoS requests
     which may lead to unexpected behavior (Jan Schönherr).

   - Fix a broken link to PM documentation from a header file and a typo
     in a PM document (Geert Uytterhoeven, Rafael Wysocki)"

* tag 'pm-4.14-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm:
  cpufreq: ti-cpufreq: Support additional am43xx platforms
  ARM: cpuidle: Avoid memleak if init fail
  cpufreq: dt-platdev: Add some missing platforms to the blacklist
  PM: core: Fix device_pm_check_callbacks()
  PM: docs: Drop an excess character from devices.rst
  PM / QoS: Use the correct variable to check the QoS request type
  driver core: Fix link to device power management documentation
parents d32e5f44 d84c97f8
...@@ -675,7 +675,7 @@ sub-domain of the parent domain. ...@@ -675,7 +675,7 @@ sub-domain of the parent domain.
Support for power domains is provided through the :c:member:`pm_domain` field of Support for power domains is provided through the :c:member:`pm_domain` field of
|struct device|. This field is a pointer to an object of type |struct device|. This field is a pointer to an object of type
|struct dev_pm_domain|, defined in :file:`include/linux/pm.h``, providing a set |struct dev_pm_domain|, defined in :file:`include/linux/pm.h`, providing a set
of power management callbacks analogous to the subsystem-level and device driver of power management callbacks analogous to the subsystem-level and device driver
callbacks that are executed for the given device during all power transitions, callbacks that are executed for the given device during all power transitions,
instead of the respective subsystem-level callbacks. Specifically, if a instead of the respective subsystem-level callbacks. Specifically, if a
......
...@@ -1860,10 +1860,13 @@ void device_pm_check_callbacks(struct device *dev) ...@@ -1860,10 +1860,13 @@ void device_pm_check_callbacks(struct device *dev)
{ {
spin_lock_irq(&dev->power.lock); spin_lock_irq(&dev->power.lock);
dev->power.no_pm_callbacks = dev->power.no_pm_callbacks =
(!dev->bus || pm_ops_is_empty(dev->bus->pm)) && (!dev->bus || (pm_ops_is_empty(dev->bus->pm) &&
(!dev->class || pm_ops_is_empty(dev->class->pm)) && !dev->bus->suspend && !dev->bus->resume)) &&
(!dev->class || (pm_ops_is_empty(dev->class->pm) &&
!dev->class->suspend && !dev->class->resume)) &&
(!dev->type || pm_ops_is_empty(dev->type->pm)) && (!dev->type || pm_ops_is_empty(dev->type->pm)) &&
(!dev->pm_domain || pm_ops_is_empty(&dev->pm_domain->ops)) && (!dev->pm_domain || pm_ops_is_empty(&dev->pm_domain->ops)) &&
(!dev->driver || pm_ops_is_empty(dev->driver->pm)); (!dev->driver || (pm_ops_is_empty(dev->driver->pm) &&
!dev->driver->suspend && !dev->driver->resume));
spin_unlock_irq(&dev->power.lock); spin_unlock_irq(&dev->power.lock);
} }
...@@ -277,11 +277,11 @@ void dev_pm_qos_constraints_destroy(struct device *dev) ...@@ -277,11 +277,11 @@ void dev_pm_qos_constraints_destroy(struct device *dev)
mutex_unlock(&dev_pm_qos_sysfs_mtx); mutex_unlock(&dev_pm_qos_sysfs_mtx);
} }
static bool dev_pm_qos_invalid_request(struct device *dev, static bool dev_pm_qos_invalid_req_type(struct device *dev,
struct dev_pm_qos_request *req) enum dev_pm_qos_req_type type)
{ {
return !req || (req->type == DEV_PM_QOS_LATENCY_TOLERANCE return type == DEV_PM_QOS_LATENCY_TOLERANCE &&
&& !dev->power.set_latency_tolerance); !dev->power.set_latency_tolerance;
} }
static int __dev_pm_qos_add_request(struct device *dev, static int __dev_pm_qos_add_request(struct device *dev,
...@@ -290,7 +290,7 @@ static int __dev_pm_qos_add_request(struct device *dev, ...@@ -290,7 +290,7 @@ static int __dev_pm_qos_add_request(struct device *dev,
{ {
int ret = 0; int ret = 0;
if (!dev || dev_pm_qos_invalid_request(dev, req)) if (!dev || !req || dev_pm_qos_invalid_req_type(dev, type))
return -EINVAL; return -EINVAL;
if (WARN(dev_pm_qos_request_active(req), if (WARN(dev_pm_qos_request_active(req),
......
...@@ -106,6 +106,18 @@ static const struct of_device_id whitelist[] __initconst = { ...@@ -106,6 +106,18 @@ static const struct of_device_id whitelist[] __initconst = {
* platforms using "operating-points-v2" property. * platforms using "operating-points-v2" property.
*/ */
static const struct of_device_id blacklist[] __initconst = { static const struct of_device_id blacklist[] __initconst = {
{ .compatible = "calxeda,highbank", },
{ .compatible = "calxeda,ecx-2000", },
{ .compatible = "marvell,armadaxp", },
{ .compatible = "nvidia,tegra124", },
{ .compatible = "st,stih407", },
{ .compatible = "st,stih410", },
{ .compatible = "sigma,tango4", },
{ } { }
}; };
......
...@@ -190,7 +190,7 @@ static int ti_cpufreq_setup_syscon_register(struct ti_cpufreq_data *opp_data) ...@@ -190,7 +190,7 @@ static int ti_cpufreq_setup_syscon_register(struct ti_cpufreq_data *opp_data)
static const struct of_device_id ti_cpufreq_of_match[] = { static const struct of_device_id ti_cpufreq_of_match[] = {
{ .compatible = "ti,am33xx", .data = &am3x_soc_data, }, { .compatible = "ti,am33xx", .data = &am3x_soc_data, },
{ .compatible = "ti,am4372", .data = &am4x_soc_data, }, { .compatible = "ti,am43", .data = &am4x_soc_data, },
{ .compatible = "ti,dra7", .data = &dra7_soc_data }, { .compatible = "ti,dra7", .data = &dra7_soc_data },
{}, {},
}; };
......
...@@ -104,13 +104,13 @@ static int __init arm_idle_init(void) ...@@ -104,13 +104,13 @@ static int __init arm_idle_init(void)
ret = dt_init_idle_driver(drv, arm_idle_state_match, 1); ret = dt_init_idle_driver(drv, arm_idle_state_match, 1);
if (ret <= 0) { if (ret <= 0) {
ret = ret ? : -ENODEV; ret = ret ? : -ENODEV;
goto out_fail; goto init_fail;
} }
ret = cpuidle_register_driver(drv); ret = cpuidle_register_driver(drv);
if (ret) { if (ret) {
pr_err("Failed to register cpuidle driver\n"); pr_err("Failed to register cpuidle driver\n");
goto out_fail; goto init_fail;
} }
/* /*
...@@ -149,6 +149,8 @@ static int __init arm_idle_init(void) ...@@ -149,6 +149,8 @@ static int __init arm_idle_init(void)
} }
return 0; return 0;
init_fail:
kfree(drv);
out_fail: out_fail:
while (--cpu >= 0) { while (--cpu >= 0) {
dev = per_cpu(cpuidle_devices, cpu); dev = per_cpu(cpuidle_devices, cpu);
......
...@@ -838,7 +838,7 @@ struct dev_links_info { ...@@ -838,7 +838,7 @@ struct dev_links_info {
* @driver_data: Private pointer for driver specific info. * @driver_data: Private pointer for driver specific info.
* @links: Links to suppliers and consumers of this device. * @links: Links to suppliers and consumers of this device.
* @power: For device power management. * @power: For device power management.
* See Documentation/power/admin-guide/devices.rst for details. * See Documentation/driver-api/pm/devices.rst for details.
* @pm_domain: Provide callbacks that are executed during system suspend, * @pm_domain: Provide callbacks that are executed during system suspend,
* hibernation, system resume and during runtime PM transitions * hibernation, system resume and during runtime PM transitions
* along with subsystem-level and driver-level callbacks. * along with subsystem-level and driver-level callbacks.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment