===================================================================
@@ -603,10 +603,16 @@ extern void dev_pm_put_subsys_data(struc
* Power domains provide callbacks that are executed during system suspend,
* hibernation, system resume and during runtime PM transitions along with
* subsystem-level and driver-level callbacks.
+ *
+ * @detach: Called when removing a device from the domain.
+ * @activate: Called before executing probe routines for bus types and drivers.
+ * @sync: Called after driver probe and removal.
*/
struct dev_pm_domain {
struct dev_pm_ops ops;
void (*detach)(struct device *dev, bool power_off);
+ int (*activate)(struct device *dev);
+ void (*sync)(struct device *dev);
};
/*
===================================================================
@@ -279,6 +279,7 @@ static int really_probe(struct device *d
{
int ret = 0;
int local_trigger_count = atomic_read(&deferred_trigger_count);
+ struct dev_pm_domain *pm_domain = dev->pm_domain;
atomic_inc(&probe_count);
pr_debug("bus: '%s': %s: probing driver %s with device %s\n",
@@ -298,16 +299,23 @@ static int really_probe(struct device *d
goto probe_failed;
}
- if (dev->bus->probe) {
- ret = dev->bus->probe(dev);
- if (ret)
- goto probe_failed;
- } else if (drv->probe) {
- ret = drv->probe(dev);
+ if (pm_domain && pm_domain->activate) {
+ ret = pm_domain->activate(dev);
if (ret)
goto probe_failed;
}
+ if (dev->bus->probe)
+ ret = dev->bus->probe(dev);
+ else if (drv->probe)
+ ret = drv->probe(dev);
+
+ if (pm_domain && pm_domain->sync)
+ pm_domain->sync(dev);
+
+ if (ret)
+ goto probe_failed;
+
driver_bound(dev);
ret = 1;
pr_debug("bus: '%s': %s: bound device %s to driver %s\n",
@@ -522,6 +530,10 @@ static void __device_release_driver(stru
dev->bus->remove(dev);
else if (drv->remove)
drv->remove(dev);
+
+ if (dev->pm_domain && dev->pm_domain->sync)
+ dev->pm_domain->sync(dev);
+
devres_release_all(dev);
dev->driver = NULL;
dev_set_drvdata(dev, NULL);