Power management fixes for v4.14-rc2

- 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).
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v2
 
 iQIcBAABCAAGBQJZxYXOAAoJEILEb/54YlRxgkQP/1tQha6hykoryGscv1XGFPsc
 VP7tpsf00gjMcUnbuRFbgD+jF60SAWtt48sIACUOqtxSXRTGdPHS8zggLo9pa0+A
 A0Y8QlFXYHlk6up2iUyNOE0C2+UfD1pnh1fGfDtNLKob+hDhrrmRI2foMRVij9Cw
 0+szDkUENcVwLcCzyWgv7uCdrG823kzBS0gCOJT4cpYid+s7lfFEwRZMz7m2Q/2Y
 s0MMELdhBaaMAZyGIh28B2D+bAS1QTTxLr++nSiiIejVplraWlUYRToGlQMpZbJn
 yPjKld5Zc6+VJ4sPl3oRw3wnfo4Rndwgx0VDGDdne1e0S7pQtIjNRbyGTbl2n6yS
 +nckLpW767l9Mt9TVQzQBgnalUUZX78sqHqa3Ca9j8QXFcG0Khn5aewq76+9KVdv
 uSAxUmthvErJUGa6GTkhBGywZxKtuIdA/eg23XDN/P2PSVW8hj+z4Fn8DylXSEo7
 H3KMOJgSRWDFvAaYsusNEdQwy6+UWN9OiMoZYMVL6XcDYyFZrAaXtaZIb7MjOL5i
 U9cv3QCU4CWtsbKoQb3qvQZudUa92MIHtLWILTuLT/lWPIPGiUGLbIYRE+hzRzkj
 26J21Ex8veYuGEJT+YP6GBqtywX9aKuec2RZVSfqtAK/x/zXxwjFP6T3JHVril3T
 /mxhLZIg/aJwIeJQ3JTG
 =Cbgd
 -----END PGP SIGNATURE-----

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
This commit is contained in:
Linus Torvalds 2017-09-22 17:28:59 -10:00
commit 6876eb3720
7 changed files with 30 additions and 13 deletions

View file

@ -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

View file

@ -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);
} }

View file

@ -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,
{ {
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),

View file

@ -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", },
{ } { }
}; };

View file

@ -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 },
{}, {},
}; };

View file

@ -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)
} }
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);

View file

@ -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.