Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 6efd3f8c authored by Rafael J. Wysocki's avatar Rafael J. Wysocki
Browse files

Merge branch 'pm-core'

* pm-core:
  driver core: Avoid NULL pointer dereferences in device_is_bound()
  platform: Do not detach from PM domains on shutdown
  USB / PM: Allow USB devices to remain runtime-suspended when sleeping
  PM / sleep: Go direct_complete if driver has no callbacks
  PM / Domains: add setter for dev.pm_domain
  device core: add device_is_bound()
parents a72aea72 3ded9104
Loading
Loading
Loading
Loading
+4 −3
Original line number Diff line number Diff line
@@ -32,6 +32,7 @@
#include <linux/io.h>
#include <linux/clk.h>
#include <linux/clkdev.h>
#include <linux/pm_domain.h>
#include <linux/pm_runtime.h>
#include <linux/of.h>
#include <linux/notifier.h>
@@ -168,7 +169,7 @@ static int omap_device_build_from_dt(struct platform_device *pdev)
			r->name = dev_name(&pdev->dev);
	}

	pdev->dev.pm_domain = &omap_device_pm_domain;
	dev_pm_domain_set(&pdev->dev, &omap_device_pm_domain);

	if (device_active) {
		omap_device_enable(pdev);
@@ -180,7 +181,7 @@ static int omap_device_build_from_dt(struct platform_device *pdev)
odbfd_exit:
	/* if data/we are at fault.. load up a fail handler */
	if (ret)
		pdev->dev.pm_domain = &omap_device_fail_pm_domain;
		dev_pm_domain_set(&pdev->dev, &omap_device_fail_pm_domain);

	return ret;
}
@@ -701,7 +702,7 @@ int omap_device_register(struct platform_device *pdev)
{
	pr_debug("omap_device: %s: registering\n", pdev->name);

	pdev->dev.pm_domain = &omap_device_pm_domain;
	dev_pm_domain_set(&pdev->dev, &omap_device_pm_domain);
	return platform_device_add(pdev);
}

+4 −1
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@
#include <linux/mutex.h>
#include <linux/platform_device.h>
#include <linux/platform_data/clk-lpss.h>
#include <linux/pm_domain.h>
#include <linux/pm_runtime.h>
#include <linux/delay.h>

@@ -875,13 +876,14 @@ static int acpi_lpss_platform_notify(struct notifier_block *nb,

	switch (action) {
	case BUS_NOTIFY_BIND_DRIVER:
		pdev->dev.pm_domain = &acpi_lpss_pm_domain;
		dev_pm_domain_set(&pdev->dev, &acpi_lpss_pm_domain);
		break;
	case BUS_NOTIFY_DRIVER_NOT_BOUND:
	case BUS_NOTIFY_UNBOUND_DRIVER:
		pdev->dev.pm_domain = NULL;
		break;
	case BUS_NOTIFY_ADD_DEVICE:
		dev_pm_domain_set(&pdev->dev, &acpi_lpss_pm_domain);
		if (pdata->dev_desc->flags & LPSS_LTR)
			return sysfs_create_group(&pdev->dev.kobj,
						  &lpss_attr_group);
@@ -889,6 +891,7 @@ static int acpi_lpss_platform_notify(struct notifier_block *nb,
	case BUS_NOTIFY_DEL_DEVICE:
		if (pdata->dev_desc->flags & LPSS_LTR)
			sysfs_remove_group(&pdev->dev.kobj, &lpss_attr_group);
		dev_pm_domain_set(&pdev->dev, NULL);
		break;
	default:
		break;
+3 −2
Original line number Diff line number Diff line
@@ -22,6 +22,7 @@
#include <linux/export.h>
#include <linux/mutex.h>
#include <linux/pm_qos.h>
#include <linux/pm_domain.h>
#include <linux/pm_runtime.h>

#include "internal.h"
@@ -1059,7 +1060,7 @@ static void acpi_dev_pm_detach(struct device *dev, bool power_off)
	struct acpi_device *adev = ACPI_COMPANION(dev);

	if (adev && dev->pm_domain == &acpi_general_pm_domain) {
		dev->pm_domain = NULL;
		dev_pm_domain_set(dev, NULL);
		acpi_remove_pm_notifier(adev);
		if (power_off) {
			/*
@@ -1111,7 +1112,7 @@ int acpi_dev_pm_attach(struct device *dev, bool power_on)
		return -EBUSY;

	acpi_add_pm_notifier(adev, dev, acpi_pm_notify_work_func);
	dev->pm_domain = &acpi_general_pm_domain;
	dev_pm_domain_set(dev, &acpi_general_pm_domain);
	if (power_on) {
		acpi_dev_pm_full_power(adev);
		acpi_device_wakeup(adev, ACPI_STATE_S0, false);
+19 −2
Original line number Diff line number Diff line
@@ -223,9 +223,23 @@ static int deferred_probe_initcall(void)
}
late_initcall(deferred_probe_initcall);

/**
 * device_is_bound() - Check if device is bound to a driver
 * @dev: device to check
 *
 * Returns true if passed device has already finished probing successfully
 * against a driver.
 *
 * This function must be called with the device lock held.
 */
bool device_is_bound(struct device *dev)
{
	return dev->p && klist_node_attached(&dev->p->knode_driver);
}

static void driver_bound(struct device *dev)
{
	if (klist_node_attached(&dev->p->knode_driver)) {
	if (device_is_bound(dev)) {
		printk(KERN_WARNING "%s: device %s already bound\n",
			__func__, kobject_name(&dev->kobj));
		return;
@@ -236,6 +250,8 @@ static void driver_bound(struct device *dev)

	klist_add_tail(&dev->p->knode_driver, &dev->driver->p->klist_devices);

	device_pm_check_callbacks(dev);

	/*
	 * Make sure the device is no longer in one of the deferred lists and
	 * kick off retrying all pending devices
@@ -601,7 +617,7 @@ static int __device_attach(struct device *dev, bool allow_async)

	device_lock(dev);
	if (dev->driver) {
		if (klist_node_attached(&dev->p->knode_driver)) {
		if (device_is_bound(dev)) {
			ret = 1;
			goto out_unlock;
		}
@@ -752,6 +768,7 @@ static void __device_release_driver(struct device *dev)
		pm_runtime_reinit(dev);

		klist_remove(&dev->p->knode_driver);
		device_pm_check_callbacks(dev);
		if (dev->bus)
			blocking_notifier_call_chain(&dev->bus->p->bus_notifier,
						     BUS_NOTIFY_UNBOUND_DRIVER,
+0 −1
Original line number Diff line number Diff line
@@ -597,7 +597,6 @@ static void platform_drv_shutdown(struct device *_dev)

	if (drv->shutdown)
		drv->shutdown(dev);
	dev_pm_domain_detach(_dev, true);
}

/**
Loading