Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

driver core / PM: Add PM domain callbacks for device setup/cleanup

If PM domains are in use, it may be necessary to prepare the code
handling a PM domain for driver probing. For example, in some
cases device drivers rely on the ability to power on the devices
with the help of the IO runtime PM framework and the PM domain
code needs to be ready for that. Also, if that code has not been
fully initialized yet, the driver probing should be deferred.

Moreover, after the probing is complete, it may be necessary to
put the PM domain in question into the state reflecting the current
needs of the devices in it, for example, so that power is not drawn
in vain. The same should be done after removing a driver from
a device, as the PM domain state may need to be changed to reflect
the new situation.

For these reasons, introduce new PM domain callbacks, ->activate,
->sync and ->dismiss called, respectively, before probing for a
device driver, after the probing has completed successfully and
if the probing has failed or the driver has been removed.

Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Acked-by: Ulf Hansson <ulf.hansson@linaro.org>
Reviewed-by: Kevin Hilman <khilman@linaro.org>
Acked-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

+22
+14
drivers/base/dd.c
··· 298 298 goto probe_failed; 299 299 } 300 300 301 + if (dev->pm_domain && dev->pm_domain->activate) { 302 + ret = dev->pm_domain->activate(dev); 303 + if (ret) 304 + goto probe_failed; 305 + } 306 + 301 307 if (dev->bus->probe) { 302 308 ret = dev->bus->probe(dev); 303 309 if (ret) ··· 313 307 if (ret) 314 308 goto probe_failed; 315 309 } 310 + 311 + if (dev->pm_domain && dev->pm_domain->sync) 312 + dev->pm_domain->sync(dev); 316 313 317 314 driver_bound(dev); 318 315 ret = 1; ··· 328 319 driver_sysfs_remove(dev); 329 320 dev->driver = NULL; 330 321 dev_set_drvdata(dev, NULL); 322 + if (dev->pm_domain && dev->pm_domain->dismiss) 323 + dev->pm_domain->dismiss(dev); 331 324 332 325 if (ret == -EPROBE_DEFER) { 333 326 /* Driver requested deferred probing */ ··· 536 525 devres_release_all(dev); 537 526 dev->driver = NULL; 538 527 dev_set_drvdata(dev, NULL); 528 + if (dev->pm_domain && dev->pm_domain->dismiss) 529 + dev->pm_domain->dismiss(dev); 530 + 539 531 klist_remove(&dev->p->knode_driver); 540 532 if (dev->bus) 541 533 blocking_notifier_call_chain(&dev->bus->p->bus_notifier,
+8
include/linux/pm.h
··· 603 603 * Power domains provide callbacks that are executed during system suspend, 604 604 * hibernation, system resume and during runtime PM transitions along with 605 605 * subsystem-level and driver-level callbacks. 606 + * 607 + * @detach: Called when removing a device from the domain. 608 + * @activate: Called before executing probe routines for bus types and drivers. 609 + * @sync: Called after successful driver probe. 610 + * @dismiss: Called after unsuccessful driver probe and after driver removal. 606 611 */ 607 612 struct dev_pm_domain { 608 613 struct dev_pm_ops ops; 609 614 void (*detach)(struct device *dev, bool power_off); 615 + int (*activate)(struct device *dev); 616 + void (*sync)(struct device *dev); 617 + void (*dismiss)(struct device *dev); 610 618 }; 611 619 612 620 /*