Skip to contentSkip to conversation

PM / Domains: Don't leave unused PM domains powered after ->probe()

PATCH New Ulf Hansson 10 participants 58 messages Mar 13, 2015 – Mar 22, 2015

Subsystems (9)
lore
Share & tools
lore
#0 lore raw

cover PM / Domains: Don't leave unused PM domains powered after ->probe()

Commit "PM / Domains: Power on the PM domain right after attach completes", helped to make sure a PM domain stays powered during ->probe(), but unfurtunate it also caused a regression.

In those scenario where the driver leaves its device in runtime PM suspended state, and don't bring it to active state during ->probe(), could cause an unsued PM domain to stay powered.

The intent from this patchset, is to fix this regression and to rework the solution of how to make sure PM domains stays powered during ->probe().

This patchset is a rebased version of the below earlier posted patchset. [PATCH v3 0/9] PM / Domains: Fix race conditions during boot

You may find that patchset from here:
http://marc.info/?l=linux-pm&m=141320895122707&w=2

Quoted 1 line

From that patchset, there is a "scenario 5" described, which actually is a more

detailed description the regression commit "PM / Domains: Power on the PM domain right after attach completes" was about to introduce.

Ulf Hansson (9):
PM / Domains: Add dev_pm_domain_get|put() APIs
PM / Domains: Enable genpd to support ->get|put() callbacks
amba: Keep PM domain powered during ->probe() drivercore / platform: Keep PM domain powered during ->probe()
i2c: core: Keep PM domain powered during ->probe()
spi: core: Keep PM domain powered during ->probe()
mmc: core: Attach PM domain prior probing of SDIO func driver
mmmc: core: Keep PM domain powered during ->probe() of SDIO func
driver
Revert "PM / Domains: Power on the PM domain right after attach
completes"

 drivers/amba/bus.c          |  8 ++++++++
 drivers/base/platform.c     |  7 +++++++
 drivers/base/power/common.c | 40 ++++++++++++++++++++++++++++++++++++++++
 drivers/base/power/domain.c | 27 +++++++++++++++++++++++++--
 drivers/i2c/i2c-core.c      |  7 +++++++
 drivers/mmc/core/sdio_bus.c | 21 +++++++++++++++++----
 drivers/spi/spi.c           |  7 +++++++
 include/linux/pm.h          |  2 ++
 include/linux/pm_domain.h   |  5 +++++
 9 files changed, 118 insertions(+), 6 deletions(-)
Signature · 1 line
1.9.1
#1 lore raw

PATCH 1/9 PM / Domains: Add dev_pm_domain_get|put() APIs

There may be more than one device in a PM domain which then will be probed at different points in time.

Depending on timing and runtime PM support, in for the device related driver/subsystem, a PM domain may be advised to power off after a successful probe sequence.

A general requirement for a device within a PM domain, is that the PM domain must stay powered during the probe sequence. To cope with such requirement, let's add the dev_pm_domain_get|put() APIs.

These APIs are intended to be invoked from subsystem-level code and the calls between get/put needs to be balanced.

dev_pm_domain_get(), tells the PM domain that it needs to increase a usage count and to keep supplying power. dev_pm_domain_put(), does the opposite.

For a PM domain to support this feature, it must implement the optional ->get|put() callbacks.

---
 drivers/base/power/common.c | 40 ++++++++++++++++++++++++++++++++++++++++
 include/linux/pm.h          |  2 ++
 include/linux/pm_domain.h   |  4 ++++
 3 files changed, 46 insertions(+)
drivers/base/power/common.c +40 -0
index f32b802..99225af 100644
@@ -128,3 +128,43 @@ void dev_pm_domain_detach(struct device *dev, bool power_off)
 		dev->pm_domain->detach(dev, power_off);
 }
 EXPORT_SYMBOL_GPL(dev_pm_domain_detach);
+
+/**
+ * dev_pm_domain_get - Increase usage count to keep a PM domain powered.
+ * @domain: The PM domain to operate on.
+ *
+ * This function will not by itself increase the usage count, that's up to each
+ * PM domain implementation to support. Typically it should be invoked from
+ * subsystem level code prior drivers starts probing.
+ *
+ * Do note, it's optional to implement the ->get() callback for a PM domain.
+ *
+ * Returns 0 on successfully increased usage count or negative error code.
+ */
+int dev_pm_domain_get(struct dev_pm_domain *domain)
+{
+	int ret = 0;
+
+	if (domain && domain->get)
+		ret = domain->get(domain);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(dev_pm_domain_get);
+
+/**
+ * dev_pm_domain_put - Decrease usage count to allow a PM domain to power off.
+ * @domain: The PM domain to operate on.
+ *
+ * This function will not by itself decrease the usage count, that's up to each
+ * PM domain implementation to support. Typically it should be invoked from
+ * subsystem level code after drivers has finished probing.
+ *
+ * Do note, it's optional to implement the ->put() callback for a PM domain.
+ */
+void dev_pm_domain_put(struct dev_pm_domain *domain)
+{
+	if (domain && domain->put)
+		domain->put(domain);
+}
+EXPORT_SYMBOL_GPL(dev_pm_domain_put);
include/linux/pm.h +2 -0
index e2f1be6..e62330b 100644
@@ -607,6 +607,8 @@ extern void dev_pm_put_subsys_data(struct device *dev);
 struct dev_pm_domain {
 	struct dev_pm_ops	ops;
 	void (*detach)(struct device *dev, bool power_off);
+	int (*get)(struct dev_pm_domain *domain);
+	void (*put)(struct dev_pm_domain *domain);
 };
 
 /*
include/linux/pm_domain.h +4 -0
index 080e778..c80d6ac 100644
@@ -315,12 +315,16 @@ static inline int of_genpd_add_provider_onecell(struct device_node *np,
 #ifdef CONFIG_PM
 extern int dev_pm_domain_attach(struct device *dev, bool power_on);
 extern void dev_pm_domain_detach(struct device *dev, bool power_off);
+extern int dev_pm_domain_get(struct dev_pm_domain *domain);
+extern void dev_pm_domain_put(struct dev_pm_domain *domain);
 #else
 static inline int dev_pm_domain_attach(struct device *dev, bool power_on)
 {
 	return -ENODEV;
 }
 static inline void dev_pm_domain_detach(struct device *dev, bool power_off) {}
+static inline int dev_pm_domain_get(struct dev_pm_domain *domain) { return 0; }
+static inline void dev_pm_domain_put(struct dev_pm_domain *domain) {}
 #endif
 
 #endif /* _LINUX_PM_DOMAIN_H */
Signature · 1 line
1.9.1
#2 lore raw

PATCH 1/9 PM / Domains: Add dev_pm_domain_get|put() APIs

Quoted 81 lines · Ulf Hansson

There may be more than one device in a PM domain which then will be probed at different points in time.

Depending on timing and runtime PM support, in for the device related driver/subsystem, a PM domain may be advised to power off after a successful probe sequence.

A general requirement for a device within a PM domain, is that the PM domain must stay powered during the probe sequence. To cope with such requirement, let's add the dev_pm_domain_get|put() APIs.

These APIs are intended to be invoked from subsystem-level code and the calls between get/put needs to be balanced.

dev_pm_domain_get(), tells the PM domain that it needs to increase a usage count and to keep supplying power. dev_pm_domain_put(), does the opposite.

For a PM domain to support this feature, it must implement the optional ->get|put() callbacks.

---
 drivers/base/power/common.c | 40 ++++++++++++++++++++++++++++++++++++++++
 include/linux/pm.h          |  2 ++
 include/linux/pm_domain.h   |  4 ++++
 3 files changed, 46 insertions(+)
drivers/base/power/common.c +40 -0
index f32b802..99225af 100644
@@ -128,3 +128,43 @@ void dev_pm_domain_detach(struct device *dev, bool power_off)
 		dev->pm_domain->detach(dev, power_off);
 }
 EXPORT_SYMBOL_GPL(dev_pm_domain_detach);
+
+/**
+ * dev_pm_domain_get - Increase usage count to keep a PM domain powered.
+ * @domain: The PM domain to operate on.
+ *
+ * This function will not by itself increase the usage count, that's up to each
+ * PM domain implementation to support. Typically it should be invoked from
+ * subsystem level code prior drivers starts probing.
+ *
+ * Do note, it's optional to implement the ->get() callback for a PM domain.
+ *
+ * Returns 0 on successfully increased usage count or negative error code.
+ */
+int dev_pm_domain_get(struct dev_pm_domain *domain)
+{
+	int ret = 0;
+
+	if (domain && domain->get)
+		ret = domain->get(domain);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(dev_pm_domain_get);
+
+/**
+ * dev_pm_domain_put - Decrease usage count to allow a PM domain to power off.
+ * @domain: The PM domain to operate on.
+ *
+ * This function will not by itself decrease the usage count, that's up to each
+ * PM domain implementation to support. Typically it should be invoked from
+ * subsystem level code after drivers has finished probing.
+ *
+ * Do note, it's optional to implement the ->put() callback for a PM domain.
+ */
+void dev_pm_domain_put(struct dev_pm_domain *domain)
+{
+	if (domain && domain->put)
+		domain->put(domain);
+}
+EXPORT_SYMBOL_GPL(dev_pm_domain_put);
include/linux/pm.h +0 -0
index e2f1be6..e62330b 100644

include/linux/pm.h extern void dev_pm_put_subsys_data(struct device *dev); · line 611

Quoted 5 lines
include/linux/pm.h +2 -0
@@ -607,6 +607,8 @@ extern void dev_pm_put_subsys_data(struct device *dev);
 struct dev_pm_domain {
 	struct dev_pm_ops	ops;
 	void (*detach)(struct device *dev, bool power_off);
+	int (*get)(struct dev_pm_domain *domain);
+	void (*put)(struct dev_pm_domain *domain);

I don't like these names. They suggest that it's always going to be about reference counting which doesn't have to be the case in principle.

Also what about calling these from the driver core, ie. really_probe()?

Signature · 2 lines
I speak only for myself.
Rafael J. Wysocki, Intel Open Source Technology Center.
#3 lore raw

PATCH 1/9 PM / Domains: Add dev_pm_domain_get|put() APIs

Quoted 82 lines · Rafael J. Wysocki
Quoted 81 lines · Ulf Hansson

There may be more than one device in a PM domain which then will be probed at different points in time.

Depending on timing and runtime PM support, in for the device related driver/subsystem, a PM domain may be advised to power off after a successful probe sequence.

A general requirement for a device within a PM domain, is that the PM domain must stay powered during the probe sequence. To cope with such requirement, let's add the dev_pm_domain_get|put() APIs.

These APIs are intended to be invoked from subsystem-level code and the calls between get/put needs to be balanced.

dev_pm_domain_get(), tells the PM domain that it needs to increase a usage count and to keep supplying power. dev_pm_domain_put(), does the opposite.

For a PM domain to support this feature, it must implement the optional ->get|put() callbacks.

---
 drivers/base/power/common.c | 40 ++++++++++++++++++++++++++++++++++++++++
 include/linux/pm.h          |  2 ++
 include/linux/pm_domain.h   |  4 ++++
 3 files changed, 46 insertions(+)
drivers/base/power/common.c +40 -0
index f32b802..99225af 100644
@@ -128,3 +128,43 @@ void dev_pm_domain_detach(struct device *dev, bool power_off)
              dev->pm_domain->detach(dev, power_off);
 }
 EXPORT_SYMBOL_GPL(dev_pm_domain_detach);
+
+/**
+ * dev_pm_domain_get - Increase usage count to keep a PM domain powered.
+ * @domain: The PM domain to operate on.
+ *
+ * This function will not by itself increase the usage count, that's up to each
+ * PM domain implementation to support. Typically it should be invoked from
+ * subsystem level code prior drivers starts probing.
+ *
+ * Do note, it's optional to implement the ->get() callback for a PM domain.
+ *
+ * Returns 0 on successfully increased usage count or negative error code.
+ */
+int dev_pm_domain_get(struct dev_pm_domain *domain)
+{
+     int ret = 0;
+
+     if (domain && domain->get)
+             ret = domain->get(domain);
+
+     return ret;
+}
+EXPORT_SYMBOL_GPL(dev_pm_domain_get);
+
+/**
+ * dev_pm_domain_put - Decrease usage count to allow a PM domain to power off.
+ * @domain: The PM domain to operate on.
+ *
+ * This function will not by itself decrease the usage count, that's up to each
+ * PM domain implementation to support. Typically it should be invoked from
+ * subsystem level code after drivers has finished probing.
+ *
+ * Do note, it's optional to implement the ->put() callback for a PM domain.
+ */
+void dev_pm_domain_put(struct dev_pm_domain *domain)
+{
+     if (domain && domain->put)
+             domain->put(domain);
+}
+EXPORT_SYMBOL_GPL(dev_pm_domain_put);
include/linux/pm.h +0 -0
index e2f1be6..e62330b 100644
@@ -607,6 +607,8 @@ extern void dev_pm_put_subsys_data(struct device *dev);
Quoted 8 lines

include/linux/pm.h extern void dev_pm_put_subsys_data(struct device *dev); · line 611

Quoted 5 lines
include/linux/pm.h +2 -0
 struct dev_pm_domain {
      struct dev_pm_ops       ops;
      void (*detach)(struct device *dev, bool power_off);
+     int (*get)(struct dev_pm_domain *domain);
+     void (*put)(struct dev_pm_domain *domain);

I don't like these names. They suggest that it's always going to be about reference counting which doesn't have to be the case in principle.

I am happy to change, you don't happen to have a proposal? :-)

For genpd we already have these related APIs:

pm_genpd_poweron()
pm_genpd_name_poweron()
pm_genpd_poweroff_unused()

Theoretically we should be able to replace these with dev_pm_domain_get|put() or whatever we decide to name them to.

Quoted 2 lines

Also what about calling these from the driver core, ie. really_probe()?

I like that!

That also implies moving the calls to dev_pm_domain_attach|detach() out of the buses and into the drivercore, since we need the PM domain to be attached before calling dev_pm_domain_get|put(). I assume that's what you also propose me to change, right?

Kind regards
Uffe

#4 lore raw

PATCH 1/9 PM / Domains: Add dev_pm_domain_get|put() APIs

Quoted 104 lines · Ulf Hansson
Quoted 82 lines · Rafael J. Wysocki
Quoted 81 lines · Ulf Hansson

There may be more than one device in a PM domain which then will be probed at different points in time.

Depending on timing and runtime PM support, in for the device related driver/subsystem, a PM domain may be advised to power off after a successful probe sequence.

A general requirement for a device within a PM domain, is that the PM domain must stay powered during the probe sequence. To cope with such requirement, let's add the dev_pm_domain_get|put() APIs.

These APIs are intended to be invoked from subsystem-level code and the calls between get/put needs to be balanced.

dev_pm_domain_get(), tells the PM domain that it needs to increase a usage count and to keep supplying power. dev_pm_domain_put(), does the opposite.

For a PM domain to support this feature, it must implement the optional ->get|put() callbacks.

---
 drivers/base/power/common.c | 40 ++++++++++++++++++++++++++++++++++++++++
 include/linux/pm.h          |  2 ++
 include/linux/pm_domain.h   |  4 ++++
 3 files changed, 46 insertions(+)
drivers/base/power/common.c +40 -0
index f32b802..99225af 100644
@@ -128,3 +128,43 @@ void dev_pm_domain_detach(struct device *dev, bool power_off)
              dev->pm_domain->detach(dev, power_off);
 }
 EXPORT_SYMBOL_GPL(dev_pm_domain_detach);
+
+/**
+ * dev_pm_domain_get - Increase usage count to keep a PM domain powered.
+ * @domain: The PM domain to operate on.
+ *
+ * This function will not by itself increase the usage count, that's up to each
+ * PM domain implementation to support. Typically it should be invoked from
+ * subsystem level code prior drivers starts probing.
+ *
+ * Do note, it's optional to implement the ->get() callback for a PM domain.
+ *
+ * Returns 0 on successfully increased usage count or negative error code.
+ */
+int dev_pm_domain_get(struct dev_pm_domain *domain)
+{
+     int ret = 0;
+
+     if (domain && domain->get)
+             ret = domain->get(domain);
+
+     return ret;
+}
+EXPORT_SYMBOL_GPL(dev_pm_domain_get);
+
+/**
+ * dev_pm_domain_put - Decrease usage count to allow a PM domain to power off.
+ * @domain: The PM domain to operate on.
+ *
+ * This function will not by itself decrease the usage count, that's up to each
+ * PM domain implementation to support. Typically it should be invoked from
+ * subsystem level code after drivers has finished probing.
+ *
+ * Do note, it's optional to implement the ->put() callback for a PM domain.
+ */
+void dev_pm_domain_put(struct dev_pm_domain *domain)
+{
+     if (domain && domain->put)
+             domain->put(domain);
+}
+EXPORT_SYMBOL_GPL(dev_pm_domain_put);
include/linux/pm.h +0 -0
index e2f1be6..e62330b 100644
@@ -607,6 +607,8 @@ extern void dev_pm_put_subsys_data(struct device *dev);
Quoted 8 lines

include/linux/pm.h extern void dev_pm_put_subsys_data(struct device *dev); · line 611

Quoted 5 lines
include/linux/pm.h +2 -0
 struct dev_pm_domain {
      struct dev_pm_ops       ops;
      void (*detach)(struct device *dev, bool power_off);
+     int (*get)(struct dev_pm_domain *domain);
+     void (*put)(struct dev_pm_domain *domain);

I don't like these names. They suggest that it's always going to be about reference counting which doesn't have to be the case in principle.

I am happy to change, you don't happen to have a proposal? :-)

For genpd we already have these related APIs:

pm_genpd_poweron()
pm_genpd_name_poweron()
pm_genpd_poweroff_unused()

Theoretically we should be able to replace these with dev_pm_domain_get|put() or whatever we decide to name them to.

Quoted 1 line
Quoted 8 lines
Quoted 1 line

Also what about calling these from the driver core, ie. really_probe()?

I like that!

That also implies moving the calls to dev_pm_domain_attach|detach() out of the buses and into the drivercore, since we need the PM domain to be attached before calling dev_pm_domain_get|put(). I assume that's what you also propose me to change, right?

Not really. I don't want to inflict the ACPI PM domain on every bus type that may not be prepared for using it or even may not want to use it (like PCI or PNP). That applies to genpd too to some extent.

So bus types need to be able to opt in for using "default" PM domains, but at the same time if they do, the core is a better place to invoke the callbacks.

The patch below shows how that can be done. For the bus types using genpd or the ACPI PM domain today ->pm_domain_init and ->pm_domain_exit may point to the routines initializing/detaching those (which also will help to reduce code duplication somewhat) and that guarantees that the domains will be attached to devices before probing and the core can do the ->pre_probe and ->post_probe things for everybody.

Rafael

---
 drivers/base/bus.c     |   12 +++++++++++-
 drivers/base/dd.c      |    9 +++++++++
 include/linux/device.h |    3 +++
 include/linux/pm.h     |    2 ++
 4 files changed, 25 insertions(+), 1 deletion(-)
drivers/base/bus.c +11 -1
Index: linux-pm/drivers/base/bus.c
===================================================================
@@ -509,10 +509,15 @@ int bus_add_device(struct device *dev)
 	int error = 0;
 
 	if (bus) {
+		if (bus->pm_domain_init) {
+			error = bus->pm_domain_init(dev);
+			if (error)
+				goto out_put;
+		}
 		pr_debug("bus: '%s': add device %s\n", bus->name, dev_name(dev));
 		error = device_add_attrs(bus, dev);
 		if (error)
-			goto out_put;
+			goto out_pm_domain;
 		error = device_add_groups(dev, bus->dev_groups);
 		if (error)
 			goto out_groups;
@@ -534,6 +539,9 @@ out_groups:
 	device_remove_groups(dev, bus->dev_groups);
 out_id:
 	device_remove_attrs(bus, dev);
+out_pm_domain:
+	if (bus->pm_domain_exit)
+		bus->pm_domain_exit(dev);
 out_put:
 	bus_put(dev->bus);
 	return error;
@@ -597,6 +605,8 @@ void bus_remove_device(struct device *de
 	device_remove_groups(dev, dev->bus->dev_groups);
 	if (klist_node_attached(&dev->p->knode_bus))
 		klist_del(&dev->p->knode_bus);
+	if (bus->pm_domain_exit)
+		bus->pm_domain_exit(dev);
 
 	pr_debug("bus: '%s': remove device %s\n",
 		 dev->bus->name, dev_name(dev));
include/linux/device.h +3 -0
Index: linux-pm/include/linux/device.h
===================================================================
@@ -123,6 +123,9 @@ struct bus_type {
 	int (*suspend)(struct device *dev, pm_message_t state);
 	int (*resume)(struct device *dev);
 
+	int (*pm_domain_init)(struct device *dev);
+	void (*pm_domain_exit)(struct device *dev);
+
 	const struct dev_pm_ops *pm;
 
 	const struct iommu_ops *iommu_ops;
include/linux/pm.h +2 -0
Index: linux-pm/include/linux/pm.h
===================================================================
@@ -607,6 +607,8 @@ extern void dev_pm_put_subsys_data(struc
 struct dev_pm_domain {
 	struct dev_pm_ops	ops;
 	void (*detach)(struct device *dev, bool power_off);
+	int (*pre_probe)(struct device *dev);
+	void (*post_probe)(struct device *dev);
 };
 
 /*
drivers/base/dd.c +9 -0
Index: linux-pm/drivers/base/dd.c
===================================================================
@@ -298,6 +298,12 @@ static int really_probe(struct device *d
 		goto probe_failed;
 	}
 
+	if (dev->pm_domain && dev->pm_domain->pre_probe) {
+		ret = dev->pm_domain->pre_probe(dev);
+		if (ret)
+			goto probe_failed;
+	}
+
 	if (dev->bus->probe) {
 		ret = dev->bus->probe(dev);
 		if (ret)
@@ -308,6 +314,9 @@ static int really_probe(struct device *d
 			goto probe_failed;
 	}
 
+	if (dev->pm_domain && dev->pm_domain->post_probe)
+		dev->pm_domain->post_probe(dev);
+
 	driver_bound(dev);
 	ret = 1;
 	pr_debug("bus: '%s': %s: bound device %s to driver %s\n",
#5 lore raw

PATCH 1/9 PM / Domains: Add dev_pm_domain_get|put() APIs

Quoted 114 lines · Rafael J. Wysocki
Quoted 104 lines · Ulf Hansson
Quoted 82 lines · Rafael J. Wysocki
Quoted 81 lines · Ulf Hansson

There may be more than one device in a PM domain which then will be probed at different points in time.

Depending on timing and runtime PM support, in for the device related driver/subsystem, a PM domain may be advised to power off after a successful probe sequence.

A general requirement for a device within a PM domain, is that the PM domain must stay powered during the probe sequence. To cope with such requirement, let's add the dev_pm_domain_get|put() APIs.

These APIs are intended to be invoked from subsystem-level code and the calls between get/put needs to be balanced.

dev_pm_domain_get(), tells the PM domain that it needs to increase a usage count and to keep supplying power. dev_pm_domain_put(), does the opposite.

For a PM domain to support this feature, it must implement the optional ->get|put() callbacks.

---
 drivers/base/power/common.c | 40 ++++++++++++++++++++++++++++++++++++++++
 include/linux/pm.h          |  2 ++
 include/linux/pm_domain.h   |  4 ++++
 3 files changed, 46 insertions(+)
drivers/base/power/common.c +40 -0
index f32b802..99225af 100644
@@ -128,3 +128,43 @@ void dev_pm_domain_detach(struct device *dev, bool power_off)
              dev->pm_domain->detach(dev, power_off);
 }
 EXPORT_SYMBOL_GPL(dev_pm_domain_detach);
+
+/**
+ * dev_pm_domain_get - Increase usage count to keep a PM domain powered.
+ * @domain: The PM domain to operate on.
+ *
+ * This function will not by itself increase the usage count, that's up to each
+ * PM domain implementation to support. Typically it should be invoked from
+ * subsystem level code prior drivers starts probing.
+ *
+ * Do note, it's optional to implement the ->get() callback for a PM domain.
+ *
+ * Returns 0 on successfully increased usage count or negative error code.
+ */
+int dev_pm_domain_get(struct dev_pm_domain *domain)
+{
+     int ret = 0;
+
+     if (domain && domain->get)
+             ret = domain->get(domain);
+
+     return ret;
+}
+EXPORT_SYMBOL_GPL(dev_pm_domain_get);
+
+/**
+ * dev_pm_domain_put - Decrease usage count to allow a PM domain to power off.
+ * @domain: The PM domain to operate on.
+ *
+ * This function will not by itself decrease the usage count, that's up to each
+ * PM domain implementation to support. Typically it should be invoked from
+ * subsystem level code after drivers has finished probing.
+ *
+ * Do note, it's optional to implement the ->put() callback for a PM domain.
+ */
+void dev_pm_domain_put(struct dev_pm_domain *domain)
+{
+     if (domain && domain->put)
+             domain->put(domain);
+}
+EXPORT_SYMBOL_GPL(dev_pm_domain_put);
include/linux/pm.h +0 -0
index e2f1be6..e62330b 100644
@@ -607,6 +607,8 @@ extern void dev_pm_put_subsys_data(struct device *dev);
Quoted 8 lines

include/linux/pm.h extern void dev_pm_put_subsys_data(struc

Quoted 5 lines
include/linux/pm.h +2 -0
 struct dev_pm_domain {
      struct dev_pm_ops       ops;
      void (*detach)(struct device *dev, bool power_off);
+     int (*get)(struct dev_pm_domain *domain);
+     void (*put)(struct dev_pm_domain *domain);

I don't like these names. They suggest that it's always going to be about reference counting which doesn't have to be the case in principle.

I am happy to change, you don't happen to have a proposal? :-)

For genpd we already have these related APIs:

pm_genpd_poweron()
pm_genpd_name_poweron()
pm_genpd_poweroff_unused()

Theoretically we should be able to replace these with dev_pm_domain_get|put() or whatever we decide to name them to.

Quoted 1 line
Quoted 8 lines
Quoted 1 line

Also what about calling these from the driver core, ie. really_probe()?

I like that!

That also implies moving the calls to dev_pm_domain_attach|detach() out of the buses and into the drivercore, since we need the PM domain to be attached before calling dev_pm_domain_get|put(). I assume that's what you also propose me to change, right?

Quoted 7 lines

Not really. I don't want to inflict the ACPI PM domain on every bus type that may not be prepared for using it or even may not want to use it (like PCI or PNP). That applies to genpd too to some extent.

So bus types need to be able to opt in for using "default" PM domains, but at the same time if they do, the core is a better place to invoke the callbacks.

Okay!

Quoted 7 lines

The patch below shows how that can be done. For the bus types using genpd or the ACPI PM domain today ->pm_domain_init and ->pm_domain_exit may point to the routines initializing/detaching those (which also will help to reduce code duplication somewhat) and that guarantees that the domains will be attached to devices before probing and the core can do the ->pre_probe and ->post_probe things for everybody.

Overall, this seem like a very good idea!

Quoted 33 lines

Rafael

---
 drivers/base/bus.c     |   12 +++++++++++-
 drivers/base/dd.c      |    9 +++++++++
 include/linux/device.h |    3 +++
 include/linux/pm.h     |    2 ++
 4 files changed, 25 insertions(+), 1 deletion(-)

Index: linux-pm/drivers/base/bus.c
===================================================================

drivers/base/bus.c +6 -1
@@ -509,10 +509,15 @@ int bus_add_device(struct device *dev)
        int error = 0;
 
        if (bus) {
+               if (bus->pm_domain_init) {
+                       error = bus->pm_domain_init(dev);
+                       if (error)
+                               goto out_put;
+               }
                pr_debug("bus: '%s': add device %s\n", bus->name, dev_name(dev));
                error = device_add_attrs(bus, dev);
                if (error)
-                       goto out_put;
+                       goto out_pm_domain;
                error = device_add_groups(dev, bus->dev_groups);
                if (error)
                        goto out_groups;

drivers/base/bus.c out_groups: · line 547

Quoted 9 lines
drivers/base/bus.c +3 -0
@@ -534,6 +539,9 @@ out_groups:
        device_remove_groups(dev, bus->dev_groups);
 out_id:
        device_remove_attrs(bus, dev);
+out_pm_domain:
+       if (bus->pm_domain_exit)
+               bus->pm_domain_exit(dev);
 out_put:
        bus_put(dev->bus);
        return error;

To make this work for bus_add_device(), we first need to change the registration procedure for genpd DT providers. Currently that's done when "PM domain drivers" invokes the __of_genpd_add_provider() API, from SoC specific code and from different init levels.

We need to have the available gendp DT providers registered when the ->pm_domain_init() callback is invoked.

Besides the changes above, genpd also needs to deal with attached devices, but which don't have a corresponding driver bound. I believe we have some corner cases to fix around this as well.

As an intermediate step, how about adding the similar code as above but into really_probe()? For the code in bus_remove_device() below, we could add that into __device_release_driver()?

Quoted 55 lines
drivers/base/bus.c +2 -0
@@ -597,6 +605,8 @@ void bus_remove_device(struct device *de
        device_remove_groups(dev, dev->bus->dev_groups);
        if (klist_node_attached(&dev->p->knode_bus))
                klist_del(&dev->p->knode_bus);
+       if (bus->pm_domain_exit)
+               bus->pm_domain_exit(dev);
 
        pr_debug("bus: '%s': remove device %s\n",
                 dev->bus->name, dev_name(dev));

Index: linux-pm/include/linux/device.h
===================================================================

include/linux/device.h +3 -0
@@ -123,6 +123,9 @@ struct bus_type {
        int (*suspend)(struct device *dev, pm_message_t state);
        int (*resume)(struct device *dev);
 
+       int (*pm_domain_init)(struct device *dev);
+       void (*pm_domain_exit)(struct device *dev);
+
        const struct dev_pm_ops *pm;
 
        const struct iommu_ops *iommu_ops;

Index: linux-pm/include/linux/pm.h
===================================================================

include/linux/pm.h +2 -0
@@ -607,6 +607,8 @@ extern void dev_pm_put_subsys_data(struc
 struct dev_pm_domain {
        struct dev_pm_ops       ops;
        void (*detach)(struct device *dev, bool power_off);
+       int (*pre_probe)(struct device *dev);
+       void (*post_probe)(struct device *dev);
 };
 
 /*

Index: linux-pm/drivers/base/dd.c
===================================================================

drivers/base/dd.c +6 -0
@@ -298,6 +298,12 @@ static int really_probe(struct device *d
                goto probe_failed;
        }
 
+       if (dev->pm_domain && dev->pm_domain->pre_probe) {
+               ret = dev->pm_domain->pre_probe(dev);
+               if (ret)
+                       goto probe_failed;
+       }
+
        if (dev->bus->probe) {
                ret = dev->bus->probe(dev);
                if (ret)

drivers/base/dd.c static int really_probe(struct device *d · line 322

Quoted 9 lines
drivers/base/dd.c +3 -0
@@ -308,6 +314,9 @@ static int really_probe(struct device *d
                        goto probe_failed;
        }
 
+       if (dev->pm_domain && dev->pm_domain->post_probe)
+               dev->pm_domain->post_probe(dev);
+
        driver_bound(dev);
        ret = 1;
        pr_debug("bus: '%s': %s: bound device %s to driver %s\n",

Kind regards
Uffe

#6 lore raw

PATCH 1/9 PM / Domains: Add dev_pm_domain_get|put() APIs

Quoted 186 lines · Ulf Hansson
Quoted 114 lines · Rafael J. Wysocki
Quoted 104 lines · Ulf Hansson
Quoted 82 lines · Rafael J. Wysocki
Quoted 81 lines · Ulf Hansson

There may be more than one device in a PM domain which then will be probed at different points in time.

Depending on timing and runtime PM support, in for the device related driver/subsystem, a PM domain may be advised to power off after a successful probe sequence.

A general requirement for a device within a PM domain, is that the PM domain must stay powered during the probe sequence. To cope with such requirement, let's add the dev_pm_domain_get|put() APIs.

These APIs are intended to be invoked from subsystem-level code and the calls between get/put needs to be balanced.

dev_pm_domain_get(), tells the PM domain that it needs to increase a usage count and to keep supplying power. dev_pm_domain_put(), does the opposite.

For a PM domain to support this feature, it must implement the optional ->get|put() callbacks.

---
 drivers/base/power/common.c | 40 ++++++++++++++++++++++++++++++++++++++++
 include/linux/pm.h          |  2 ++
 include/linux/pm_domain.h   |  4 ++++
 3 files changed, 46 insertions(+)
drivers/base/power/common.c +40 -0
index f32b802..99225af 100644
@@ -128,3 +128,43 @@ void dev_pm_domain_detach(struct device *dev, bool power_off)
              dev->pm_domain->detach(dev, power_off);
 }
 EXPORT_SYMBOL_GPL(dev_pm_domain_detach);
+
+/**
+ * dev_pm_domain_get - Increase usage count to keep a PM domain powered.
+ * @domain: The PM domain to operate on.
+ *
+ * This function will not by itself increase the usage count, that's up to each
+ * PM domain implementation to support. Typically it should be invoked from
+ * subsystem level code prior drivers starts probing.
+ *
+ * Do note, it's optional to implement the ->get() callback for a PM domain.
+ *
+ * Returns 0 on successfully increased usage count or negative error code.
+ */
+int dev_pm_domain_get(struct dev_pm_domain *domain)
+{
+     int ret = 0;
+
+     if (domain && domain->get)
+             ret = domain->get(domain);
+
+     return ret;
+}
+EXPORT_SYMBOL_GPL(dev_pm_domain_get);
+
+/**
+ * dev_pm_domain_put - Decrease usage count to allow a PM domain to power off.
+ * @domain: The PM domain to operate on.
+ *
+ * This function will not by itself decrease the usage count, that's up to each
+ * PM domain implementation to support. Typically it should be invoked from
+ * subsystem level code after drivers has finished probing.
+ *
+ * Do note, it's optional to implement the ->put() callback for a PM domain.
+ */
+void dev_pm_domain_put(struct dev_pm_domain *domain)
+{
+     if (domain && domain->put)
+             domain->put(domain);
+}
+EXPORT_SYMBOL_GPL(dev_pm_domain_put);
include/linux/pm.h +0 -0
index e2f1be6..e62330b 100644
@@ -607,6 +607,8 @@ extern void dev_pm_put_subsys_data(struct device *dev);
Quoted 8 lines

include/linux/pm.h extern void dev_pm_put_subsys_data(struc

Quoted 5 lines
include/linux/pm.h +2 -0
 struct dev_pm_domain {
      struct dev_pm_ops       ops;
      void (*detach)(struct device *dev, bool power_off);
+     int (*get)(struct dev_pm_domain *domain);
+     void (*put)(struct dev_pm_domain *domain);

I don't like these names. They suggest that it's always going to be about reference counting which doesn't have to be the case in principle.

I am happy to change, you don't happen to have a proposal? :-)

For genpd we already have these related APIs:

pm_genpd_poweron()
pm_genpd_name_poweron()
pm_genpd_poweroff_unused()

Theoretically we should be able to replace these with dev_pm_domain_get|put() or whatever we decide to name them to.

Quoted 1 line
Quoted 8 lines
Quoted 1 line

Also what about calling these from the driver core, ie. really_probe()?

I like that!

That also implies moving the calls to dev_pm_domain_attach|detach() out of the buses and into the drivercore, since we need the PM domain to be attached before calling dev_pm_domain_get|put(). I assume that's what you also propose me to change, right?

Quoted 7 lines

Not really. I don't want to inflict the ACPI PM domain on every bus type that may not be prepared for using it or even may not want to use it (like PCI or PNP). That applies to genpd too to some extent.

So bus types need to be able to opt in for using "default" PM domains, but at the same time if they do, the core is a better place to invoke the callbacks.

Okay!

Quoted 7 lines

The patch below shows how that can be done. For the bus types using genpd or the ACPI PM domain today ->pm_domain_init and ->pm_domain_exit may point to the routines initializing/detaching those (which also will help to reduce code duplication somewhat) and that guarantees that the domains will be attached to devices before probing and the core can do the ->pre_probe and ->post_probe things for everybody.

Overall, this seem like a very good idea!

Quoted 33 lines

Rafael

---
 drivers/base/bus.c     |   12 +++++++++++-
 drivers/base/dd.c      |    9 +++++++++
 include/linux/device.h |    3 +++
 include/linux/pm.h     |    2 ++
 4 files changed, 25 insertions(+), 1 deletion(-)

Index: linux-pm/drivers/base/bus.c
===================================================================

drivers/base/bus.c +6 -1
@@ -509,10 +509,15 @@ int bus_add_device(struct device *dev)
        int error = 0;
 
        if (bus) {
+               if (bus->pm_domain_init) {
+                       error = bus->pm_domain_init(dev);
+                       if (error)
+                               goto out_put;
+               }
                pr_debug("bus: '%s': add device %s\n", bus->name, dev_name(dev));
                error = device_add_attrs(bus, dev);
                if (error)
-                       goto out_put;
+                       goto out_pm_domain;
                error = device_add_groups(dev, bus->dev_groups);
                if (error)
                        goto out_groups;

drivers/base/bus.c out_groups: · line 547

Quoted 9 lines
drivers/base/bus.c +3 -0
@@ -534,6 +539,9 @@ out_groups:
        device_remove_groups(dev, bus->dev_groups);
 out_id:
        device_remove_attrs(bus, dev);
+out_pm_domain:
+       if (bus->pm_domain_exit)
+               bus->pm_domain_exit(dev);
 out_put:
        bus_put(dev->bus);
        return error;

To make this work for bus_add_device(), we first need to change the registration procedure for genpd DT providers. Currently that's done when "PM domain drivers" invokes the __of_genpd_add_provider() API, from SoC specific code and from different init levels.

We need to have the available gendp DT providers registered when the ->pm_domain_init() callback is invoked.

Quoted 7 lines

Besides the changes above, genpd also needs to deal with attached devices, but which don't have a corresponding driver bound. I believe we have some corner cases to fix around this as well.

As an intermediate step, how about adding the similar code as above but into really_probe()? For the code in bus_remove_device() below, we could add that into __device_release_driver()?

Well, I wouldn't really like to add new callbacks to struct bus_type for intermediate steps, because that's guaranteed to lead to confusion.

So I think the infrastructure is better added first and users may be switched over to it gradually.

I don't see any particular problems with moving the ACPI PM domain attach/detach to bus_add/remove_device(), so that can be done as the first step. As for genpd, it can implement the ->post_probe thing first and do the rest in the bus type ->probe until the generic code is ready.

Signature · 2 lines
I speak only for myself.
Rafael J. Wysocki, Intel Open Source Technology Center.
#7 lore raw

PATCH 1/9 PM / Domains: Add dev_pm_domain_get|put() APIs

Quoted 10 lines · Rafael J. Wysocki

Well, I wouldn't really like to add new callbacks to struct bus_type for intermediate steps, because that's guaranteed to lead to confusion.

So I think the infrastructure is better added first and users may be switched over to it gradually.

I don't see any particular problems with moving the ACPI PM domain attach/detach to bus_add/remove_device(), so that can be done as the first step. As for genpd, it can implement the ->post_probe thing first and do the rest in the bus type ->probe until the generic code is ready.

At what point do you see the genpd binding taking place - remembering that this can fail with -EPROBE_DEFER when DT specifies a genpd, but the domain hasn't been registered yet?

I'm guessing that needs to happen either in the bus type ->probe or the ->pre_probe callback. ->pre_probe sounds better as it can be a standard genpd function which bus types hook directly into that method.

Signature · 2 lines
FTTC broadband for 0.8mile line: currently at 10.5Mbps down 400kbps up
according to speedtest.net.
#8 lore raw

PATCH 1/9 PM / Domains: Add dev_pm_domain_get|put() APIs

Quoted 7 lines · Russell King - ARM Linux
Quoted 6 lines · Rafael J. Wysocki

Well, I wouldn't really like to add new callbacks to struct bus_type for intermediate steps, because that's guaranteed to lead to confusion.

So I think the infrastructure is better added first and users may be switched over to it gradually.

Quoted 8 lines
Quoted 4 lines

I don't see any particular problems with moving the ACPI PM domain attach/detach to bus_add/remove_device(), so that can be done as the first step. As for genpd, it can implement the ->post_probe thing first and do the rest in the bus type ->probe until the generic code is ready.

At what point do you see the genpd binding taking place - remembering that this can fail with -EPROBE_DEFER when DT specifies a genpd, but the domain hasn't been registered yet?

That -EPROBE_DEFER needs to be returned from the ->pre_probe callback I think. Otherwise bus types would need to duplicate that code.

Quoted 4 lines

I'm guessing that needs to happen either in the bus type ->probe or the ->pre_probe callback. ->pre_probe sounds better as it can be a standard genpd function which bus types hook directly into that method.

Right.

Still, I'd like the bus type's (new) ->pm_domain_init (or whatever it will be eventually) to be used for populating the devices' ->pm_domain pointers. There are two reasons for that. First, those pointers only need to be populated once per device life cycle (and not during every driver probe/remove). Second, that will make limited power management of devices without drivers possible (at least in the ACPI case).

Rafael

#9 lore raw

PATCH 1/9 PM / Domains: Add dev_pm_domain_get|put() APIs

In reply to Rafael J. Wysocki
Quoted 198 lines · Rafael J. Wysocki
Quoted 186 lines · Ulf Hansson
Quoted 114 lines · Rafael J. Wysocki
Quoted 104 lines · Ulf Hansson
Quoted 82 lines · Rafael J. Wysocki
Quoted 81 lines · Ulf Hansson

There may be more than one device in a PM domain which then will be probed at different points in time.

Depending on timing and runtime PM support, in for the device related driver/subsystem, a PM domain may be advised to power off after a successful probe sequence.

A general requirement for a device within a PM domain, is that the PM domain must stay powered during the probe sequence. To cope with such requirement, let's add the dev_pm_domain_get|put() APIs.

These APIs are intended to be invoked from subsystem-level code and the calls between get/put needs to be balanced.

dev_pm_domain_get(), tells the PM domain that it needs to increase a usage count and to keep supplying power. dev_pm_domain_put(), does the opposite.

For a PM domain to support this feature, it must implement the optional ->get|put() callbacks.

---
 drivers/base/power/common.c | 40 ++++++++++++++++++++++++++++++++++++++++
 include/linux/pm.h          |  2 ++
 include/linux/pm_domain.h   |  4 ++++
 3 files changed, 46 insertions(+)
drivers/base/power/common.c +40 -0
index f32b802..99225af 100644
@@ -128,3 +128,43 @@ void dev_pm_domain_detach(struct device *dev, bool power_off)
              dev->pm_domain->detach(dev, power_off);
 }
 EXPORT_SYMBOL_GPL(dev_pm_domain_detach);
+
+/**
+ * dev_pm_domain_get - Increase usage count to keep a PM domain powered.
+ * @domain: The PM domain to operate on.
+ *
+ * This function will not by itself increase the usage count, that's up to each
+ * PM domain implementation to support. Typically it should be invoked from
+ * subsystem level code prior drivers starts probing.
+ *
+ * Do note, it's optional to implement the ->get() callback for a PM domain.
+ *
+ * Returns 0 on successfully increased usage count or negative error code.
+ */
+int dev_pm_domain_get(struct dev_pm_domain *domain)
+{
+     int ret = 0;
+
+     if (domain && domain->get)
+             ret = domain->get(domain);
+
+     return ret;
+}
+EXPORT_SYMBOL_GPL(dev_pm_domain_get);
+
+/**
+ * dev_pm_domain_put - Decrease usage count to allow a PM domain to power off.
+ * @domain: The PM domain to operate on.
+ *
+ * This function will not by itself decrease the usage count, that's up to each
+ * PM domain implementation to support. Typically it should be invoked from
+ * subsystem level code after drivers has finished probing.
+ *
+ * Do note, it's optional to implement the ->put() callback for a PM domain.
+ */
+void dev_pm_domain_put(struct dev_pm_domain *domain)
+{
+     if (domain && domain->put)
+             domain->put(domain);
+}
+EXPORT_SYMBOL_GPL(dev_pm_domain_put);
include/linux/pm.h +0 -0
index e2f1be6..e62330b 100644
@@ -607,6 +607,8 @@ extern void dev_pm_put_subsys_data(struct device *dev);
Quoted 8 lines

include/linux/pm.h extern void dev_pm_put_subsys_data(struc

Quoted 5 lines
include/linux/pm.h +2 -0
 struct dev_pm_domain {
      struct dev_pm_ops       ops;
      void (*detach)(struct device *dev, bool power_off);
+     int (*get)(struct dev_pm_domain *domain);
+     void (*put)(struct dev_pm_domain *domain);

I don't like these names. They suggest that it's always going to be about reference counting which doesn't have to be the case in principle.

I am happy to change, you don't happen to have a proposal? :-)

For genpd we already have these related APIs:

pm_genpd_poweron()
pm_genpd_name_poweron()
pm_genpd_poweroff_unused()

Theoretically we should be able to replace these with dev_pm_domain_get|put() or whatever we decide to name them to.

Quoted 1 line
Quoted 8 lines
Quoted 1 line

Also what about calling these from the driver core, ie. really_probe()?

I like that!

That also implies moving the calls to dev_pm_domain_attach|detach() out of the buses and into the drivercore, since we need the PM domain to be attached before calling dev_pm_domain_get|put(). I assume that's what you also propose me to change, right?

Quoted 7 lines

Not really. I don't want to inflict the ACPI PM domain on every bus type that may not be prepared for using it or even may not want to use it (like PCI or PNP). That applies to genpd too to some extent.

So bus types need to be able to opt in for using "default" PM domains, but at the same time if they do, the core is a better place to invoke the callbacks.

Okay!

Quoted 7 lines

The patch below shows how that can be done. For the bus types using genpd or the ACPI PM domain today ->pm_domain_init and ->pm_domain_exit may point to the routines initializing/detaching those (which also will help to reduce code duplication somewhat) and that guarantees that the domains will be attached to devices before probing and the core can do the ->pre_probe and ->post_probe things for everybody.

Overall, this seem like a very good idea!

Quoted 33 lines

Rafael

---
 drivers/base/bus.c     |   12 +++++++++++-
 drivers/base/dd.c      |    9 +++++++++
 include/linux/device.h |    3 +++
 include/linux/pm.h     |    2 ++
 4 files changed, 25 insertions(+), 1 deletion(-)

Index: linux-pm/drivers/base/bus.c
===================================================================

drivers/base/bus.c +6 -1
@@ -509,10 +509,15 @@ int bus_add_device(struct device *dev)
        int error = 0;
 
        if (bus) {
+               if (bus->pm_domain_init) {
+                       error = bus->pm_domain_init(dev);
+                       if (error)
+                               goto out_put;
+               }
                pr_debug("bus: '%s': add device %s\n", bus->name, dev_name(dev));
                error = device_add_attrs(bus, dev);
                if (error)
-                       goto out_put;
+                       goto out_pm_domain;
                error = device_add_groups(dev, bus->dev_groups);
                if (error)
                        goto out_groups;

drivers/base/bus.c out_groups: · line 547

Quoted 9 lines
drivers/base/bus.c +3 -0
@@ -534,6 +539,9 @@ out_groups:
        device_remove_groups(dev, bus->dev_groups);
 out_id:
        device_remove_attrs(bus, dev);
+out_pm_domain:
+       if (bus->pm_domain_exit)
+               bus->pm_domain_exit(dev);
 out_put:
        bus_put(dev->bus);
        return error;

To make this work for bus_add_device(), we first need to change the registration procedure for genpd DT providers. Currently that's done when "PM domain drivers" invokes the __of_genpd_add_provider() API, from SoC specific code and from different init levels.

We need to have the available gendp DT providers registered when the ->pm_domain_init() callback is invoked.

Quoted 7 lines

Besides the changes above, genpd also needs to deal with attached devices, but which don't have a corresponding driver bound. I believe we have some corner cases to fix around this as well.

As an intermediate step, how about adding the similar code as above but into really_probe()? For the code in bus_remove_device() below, we could add that into __device_release_driver()?

Well, I wouldn't really like to add new callbacks to struct bus_type for intermediate steps, because that's guaranteed to lead to confusion.

Quoted 7 lines

So I think the infrastructure is better added first and users may be switched over to it gradually.

I don't see any particular problems with moving the ACPI PM domain attach/detach to bus_add/remove_device(), so that can be done as the first step. As for genpd, it can implement the ->post_probe thing first and do the rest in the bus type ->probe until the generic code is ready.

Yes, that works.

I will cook a new version of the patchset according to your suggestions.

Kind regards
Uffe

#10 lore raw

PATCH 1/9 PM / Domains: Add dev_pm_domain_get|put() APIs

Quoted 202 lines · Ulf Hansson
Quoted 201 lines · Rafael J. Wysocki
Quoted 186 lines · Ulf Hansson
Quoted 114 lines · Rafael J. Wysocki
Quoted 104 lines · Ulf Hansson
Quoted 82 lines · Rafael J. Wysocki
Quoted 81 lines · Ulf Hansson

There may be more than one device in a PM domain which then will be probed at different points in time.

Depending on timing and runtime PM support, in for the device related driver/subsystem, a PM domain may be advised to power off after a successful probe sequence.

A general requirement for a device within a PM domain, is that the PM domain must stay powered during the probe sequence. To cope with such requirement, let's add the dev_pm_domain_get|put() APIs.

These APIs are intended to be invoked from subsystem-level code and the calls between get/put needs to be balanced.

dev_pm_domain_get(), tells the PM domain that it needs to increase a usage count and to keep supplying power. dev_pm_domain_put(), does the opposite.

For a PM domain to support this feature, it must implement the optional ->get|put() callbacks.

---
 drivers/base/power/common.c | 40 ++++++++++++++++++++++++++++++++++++++++
 include/linux/pm.h          |  2 ++
 include/linux/pm_domain.h   |  4 ++++
 3 files changed, 46 insertions(+)
drivers/base/power/common.c +40 -0
index f32b802..99225af 100644
@@ -128,3 +128,43 @@ void dev_pm_domain_detach(struct device *dev, bool power_off)
              dev->pm_domain->detach(dev, power_off);
 }
 EXPORT_SYMBOL_GPL(dev_pm_domain_detach);
+
+/**
+ * dev_pm_domain_get - Increase usage count to keep a PM domain powered.
+ * @domain: The PM domain to operate on.
+ *
+ * This function will not by itself increase the usage count, that's up to each
+ * PM domain implementation to support. Typically it should be invoked from
+ * subsystem level code prior drivers starts probing.
+ *
+ * Do note, it's optional to implement the ->get() callback for a PM domain.
+ *
+ * Returns 0 on successfully increased usage count or negative error code.
+ */
+int dev_pm_domain_get(struct dev_pm_domain *domain)
+{
+     int ret = 0;
+
+     if (domain && domain->get)
+             ret = domain->get(domain);
+
+     return ret;
+}
+EXPORT_SYMBOL_GPL(dev_pm_domain_get);
+
+/**
+ * dev_pm_domain_put - Decrease usage count to allow a PM domain to power off.
+ * @domain: The PM domain to operate on.
+ *
+ * This function will not by itself decrease the usage count, that's up to each
+ * PM domain implementation to support. Typically it should be invoked from
+ * subsystem level code after drivers has finished probing.
+ *
+ * Do note, it's optional to implement the ->put() callback for a PM domain.
+ */
+void dev_pm_domain_put(struct dev_pm_domain *domain)
+{
+     if (domain && domain->put)
+             domain->put(domain);
+}
+EXPORT_SYMBOL_GPL(dev_pm_domain_put);
include/linux/pm.h +0 -0
index e2f1be6..e62330b 100644
@@ -607,6 +607,8 @@ extern void dev_pm_put_subsys_data(struct device *dev);
Quoted 8 lines

include/linux/pm.h extern void dev_pm_put_subsys_data(struc

Quoted 5 lines
include/linux/pm.h +2 -0
 struct dev_pm_domain {
      struct dev_pm_ops       ops;
      void (*detach)(struct device *dev, bool power_off);
+     int (*get)(struct dev_pm_domain *domain);
+     void (*put)(struct dev_pm_domain *domain);

I don't like these names. They suggest that it's always going to be about reference counting which doesn't have to be the case in principle.

I am happy to change, you don't happen to have a proposal? :-)

For genpd we already have these related APIs:

pm_genpd_poweron()
pm_genpd_name_poweron()
pm_genpd_poweroff_unused()

Theoretically we should be able to replace these with dev_pm_domain_get|put() or whatever we decide to name them to.

Quoted 1 line
Quoted 8 lines
Quoted 1 line

Also what about calling these from the driver core, ie. really_probe()?

I like that!

That also implies moving the calls to dev_pm_domain_attach|detach() out of the buses and into the drivercore, since we need the PM domain to be attached before calling dev_pm_domain_get|put(). I assume that's what you also propose me to change, right?

Quoted 7 lines

Not really. I don't want to inflict the ACPI PM domain on every bus type that may not be prepared for using it or even may not want to use it (like PCI or PNP). That applies to genpd too to some extent.

So bus types need to be able to opt in for using "default" PM domains, but at the same time if they do, the core is a better place to invoke the callbacks.

Okay!

Quoted 7 lines

The patch below shows how that can be done. For the bus types using genpd or the ACPI PM domain today ->pm_domain_init and ->pm_domain_exit may point to the routines initializing/detaching those (which also will help to reduce code duplication somewhat) and that guarantees that the domains will be attached to devices before probing and the core can do the ->pre_probe and ->post_probe things for everybody.

Overall, this seem like a very good idea!

Quoted 33 lines

Rafael

---
 drivers/base/bus.c     |   12 +++++++++++-
 drivers/base/dd.c      |    9 +++++++++
 include/linux/device.h |    3 +++
 include/linux/pm.h     |    2 ++
 4 files changed, 25 insertions(+), 1 deletion(-)

Index: linux-pm/drivers/base/bus.c
===================================================================

drivers/base/bus.c +6 -1
@@ -509,10 +509,15 @@ int bus_add_device(struct device *dev)
        int error = 0;
 
        if (bus) {
+               if (bus->pm_domain_init) {
+                       error = bus->pm_domain_init(dev);
+                       if (error)
+                               goto out_put;
+               }
                pr_debug("bus: '%s': add device %s\n", bus->name, dev_name(dev));
                error = device_add_attrs(bus, dev);
                if (error)
-                       goto out_put;
+                       goto out_pm_domain;
                error = device_add_groups(dev, bus->dev_groups);
                if (error)
                        goto out_groups;

drivers/base/bus.c out_groups: · line 547

Quoted 9 lines
drivers/base/bus.c +3 -0
@@ -534,6 +539,9 @@ out_groups:
        device_remove_groups(dev, bus->dev_groups);
 out_id:
        device_remove_attrs(bus, dev);
+out_pm_domain:
+       if (bus->pm_domain_exit)
+               bus->pm_domain_exit(dev);
 out_put:
        bus_put(dev->bus);
        return error;

To make this work for bus_add_device(), we first need to change the registration procedure for genpd DT providers. Currently that's done when "PM domain drivers" invokes the __of_genpd_add_provider() API, from SoC specific code and from different init levels.

We need to have the available gendp DT providers registered when the ->pm_domain_init() callback is invoked.

Quoted 7 lines

Besides the changes above, genpd also needs to deal with attached devices, but which don't have a corresponding driver bound. I believe we have some corner cases to fix around this as well.

As an intermediate step, how about adding the similar code as above but into really_probe()? For the code in bus_remove_device() below, we could add that into __device_release_driver()?

Well, I wouldn't really like to add new callbacks to struct bus_type for intermediate steps, because that's guaranteed to lead to confusion.

So I think the infrastructure is better added first and users may be switched over to it gradually.

Quoted 8 lines
Quoted 4 lines

I don't see any particular problems with moving the ACPI PM domain attach/detach to bus_add/remove_device(), so that can be done as the first step. As for genpd, it can implement the ->post_probe thing first and do the rest in the bus type ->probe until the generic code is ready.

Yes, that works.

I will cook a new version of the patchset according to your suggestions.

I'll send a cleaner version of my patch tomorrow (I actually would like to use different names for the new callbacks).

Also I can do the ACPI part of the work, please let me know if you want me to.

Signature · 2 lines
I speak only for myself.
Rafael J. Wysocki, Intel Open Source Technology Center.
#11 lore raw

PATCH 1/9 PM / Domains: Add dev_pm_domain_get|put() APIs

Quoted 208 lines · Rafael J. Wysocki
Quoted 207 lines · Ulf Hansson
Quoted 205 lines · Rafael J. Wysocki
Quoted 186 lines · Ulf Hansson
Quoted 114 lines · Rafael J. Wysocki
Quoted 104 lines · Ulf Hansson
Quoted 82 lines · Rafael J. Wysocki
Quoted 81 lines · Ulf Hansson

There may be more than one device in a PM domain which then will be probed at different points in time.

Depending on timing and runtime PM support, in for the device related driver/subsystem, a PM domain may be advised to power off after a successful probe sequence.

A general requirement for a device within a PM domain, is that the PM domain must stay powered during the probe sequence. To cope with such requirement, let's add the dev_pm_domain_get|put() APIs.

These APIs are intended to be invoked from subsystem-level code and the calls between get/put needs to be balanced.

dev_pm_domain_get(), tells the PM domain that it needs to increase a usage count and to keep supplying power. dev_pm_domain_put(), does the opposite.

For a PM domain to support this feature, it must implement the optional ->get|put() callbacks.

---
 drivers/base/power/common.c | 40 ++++++++++++++++++++++++++++++++++++++++
 include/linux/pm.h          |  2 ++
 include/linux/pm_domain.h   |  4 ++++
 3 files changed, 46 insertions(+)
drivers/base/power/common.c +40 -0
index f32b802..99225af 100644
@@ -128,3 +128,43 @@ void dev_pm_domain_detach(struct device *dev, bool power_off)
              dev->pm_domain->detach(dev, power_off);
 }
 EXPORT_SYMBOL_GPL(dev_pm_domain_detach);
+
+/**
+ * dev_pm_domain_get - Increase usage count to keep a PM domain powered.
+ * @domain: The PM domain to operate on.
+ *
+ * This function will not by itself increase the usage count, that's up to each
+ * PM domain implementation to support. Typically it should be invoked from
+ * subsystem level code prior drivers starts probing.
+ *
+ * Do note, it's optional to implement the ->get() callback for a PM domain.
+ *
+ * Returns 0 on successfully increased usage count or negative error code.
+ */
+int dev_pm_domain_get(struct dev_pm_domain *domain)
+{
+     int ret = 0;
+
+     if (domain && domain->get)
+             ret = domain->get(domain);
+
+     return ret;
+}
+EXPORT_SYMBOL_GPL(dev_pm_domain_get);
+
+/**
+ * dev_pm_domain_put - Decrease usage count to allow a PM domain to power off.
+ * @domain: The PM domain to operate on.
+ *
+ * This function will not by itself decrease the usage count, that's up to each
+ * PM domain implementation to support. Typically it should be invoked from
+ * subsystem level code after drivers has finished probing.
+ *
+ * Do note, it's optional to implement the ->put() callback for a PM domain.
+ */
+void dev_pm_domain_put(struct dev_pm_domain *domain)
+{
+     if (domain && domain->put)
+             domain->put(domain);
+}
+EXPORT_SYMBOL_GPL(dev_pm_domain_put);
include/linux/pm.h +0 -0
index e2f1be6..e62330b 100644
@@ -607,6 +607,8 @@ extern void dev_pm_put_subsys_data(struct device *dev);
Quoted 8 lines

include/linux/pm.h extern void dev_pm_put_subsys_data(struc

Quoted 5 lines
include/linux/pm.h +2 -0
 struct dev_pm_domain {
      struct dev_pm_ops       ops;
      void (*detach)(struct device *dev, bool power_off);
+     int (*get)(struct dev_pm_domain *domain);
+     void (*put)(struct dev_pm_domain *domain);

I don't like these names. They suggest that it's always going to be about reference counting which doesn't have to be the case in principle.

I am happy to change, you don't happen to have a proposal? :-)

For genpd we already have these related APIs:

pm_genpd_poweron()
pm_genpd_name_poweron()
pm_genpd_poweroff_unused()

Theoretically we should be able to replace these with dev_pm_domain_get|put() or whatever we decide to name them to.

Quoted 1 line
Quoted 8 lines
Quoted 1 line

Also what about calling these from the driver core, ie. really_probe()?

I like that!

That also implies moving the calls to dev_pm_domain_attach|detach() out of the buses and into the drivercore, since we need the PM domain to be attached before calling dev_pm_domain_get|put(). I assume that's what you also propose me to change, right?

Quoted 7 lines

Not really. I don't want to inflict the ACPI PM domain on every bus type that may not be prepared for using it or even may not want to use it (like PCI or PNP). That applies to genpd too to some extent.

So bus types need to be able to opt in for using "default" PM domains, but at the same time if they do, the core is a better place to invoke the callbacks.

Okay!

Quoted 7 lines

The patch below shows how that can be done. For the bus types using genpd or the ACPI PM domain today ->pm_domain_init and ->pm_domain_exit may point to the routines initializing/detaching those (which also will help to reduce code duplication somewhat) and that guarantees that the domains will be attached to devices before probing and the core can do the ->pre_probe and ->post_probe things for everybody.

Overall, this seem like a very good idea!

Quoted 33 lines

Rafael

---
 drivers/base/bus.c     |   12 +++++++++++-
 drivers/base/dd.c      |    9 +++++++++
 include/linux/device.h |    3 +++
 include/linux/pm.h     |    2 ++
 4 files changed, 25 insertions(+), 1 deletion(-)

Index: linux-pm/drivers/base/bus.c
===================================================================

drivers/base/bus.c +6 -1
@@ -509,10 +509,15 @@ int bus_add_device(struct device *dev)
        int error = 0;
 
        if (bus) {
+               if (bus->pm_domain_init) {
+                       error = bus->pm_domain_init(dev);
+                       if (error)
+                               goto out_put;
+               }
                pr_debug("bus: '%s': add device %s\n", bus->name, dev_name(dev));
                error = device_add_attrs(bus, dev);
                if (error)
-                       goto out_put;
+                       goto out_pm_domain;
                error = device_add_groups(dev, bus->dev_groups);
                if (error)
                        goto out_groups;

drivers/base/bus.c out_groups: · line 547

Quoted 9 lines
drivers/base/bus.c +3 -0
@@ -534,6 +539,9 @@ out_groups:
        device_remove_groups(dev, bus->dev_groups);
 out_id:
        device_remove_attrs(bus, dev);
+out_pm_domain:
+       if (bus->pm_domain_exit)
+               bus->pm_domain_exit(dev);
 out_put:
        bus_put(dev->bus);
        return error;

To make this work for bus_add_device(), we first need to change the registration procedure for genpd DT providers. Currently that's done when "PM domain drivers" invokes the __of_genpd_add_provider() API, from SoC specific code and from different init levels.

We need to have the available gendp DT providers registered when the ->pm_domain_init() callback is invoked.

Quoted 7 lines

Besides the changes above, genpd also needs to deal with attached devices, but which don't have a corresponding driver bound. I believe we have some corner cases to fix around this as well.

As an intermediate step, how about adding the similar code as above but into really_probe()? For the code in bus_remove_device() below, we could add that into __device_release_driver()?

Well, I wouldn't really like to add new callbacks to struct bus_type for intermediate steps, because that's guaranteed to lead to confusion.

So I think the infrastructure is better added first and users may be switched over to it gradually.

I don't see any particular problems with moving the ACPI PM domain attach/detach to bus_add/remove_device(), so that can be done as the first step. As for genpd, it can implement the ->post_probe thing first and do the rest in the bus type ->probe until the generic code is ready.

Quoted 6 lines
Quoted 3 lines

Yes, that works.

I will cook a new version of the patchset according to your suggestions.

I'll send a cleaner version of my patch tomorrow (I actually would like to use different names for the new callbacks).

Okay, great!

Quoted 2 lines

Also I can do the ACPI part of the work, please let me know if you want me to.

Appreciate your help! I wouldn't mind giving this a quick try. If I am way off, just nack the patches and then please help out implement it.

Kind regards
Uffe

#12 lore raw

PATCH 1/1 driver core / PM: Add callbacks for PM domain initialization/cleanup

From: Rafael J. Wysocki <[email protected]>

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, to prevent power from being drawn in vain.

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

That is not sufficient, however, because the device's PM domain pointer has to be populated for the ->activate callback to be executed, so setting it in bus type ->probe callback routines would be too late. Also, there are bus types where PM domains are not used at all and the core should not attempt to set the pm_domain pointer for the devices on those buses.

To overcome that difficulty, introduce two new bus type callbacks, ->init and ->release, called by bus_add_device() and bus_remove_device(), respectively. That will allow ->init to be used to populate the pm_domain pointer for the bus types that want to do that and ->release will be useful for any cleanup that may be necessary after removing a device that was part of a PM domain.

---

It occured to me that we might want to ->sync regardless of whether or not the probing had been succenssful, so I changed the code in really_probe() along these lines. Please let me know if that's not OK.

---
 drivers/base/bus.c     |   12 +++++++++++-
 drivers/base/dd.c      |   20 ++++++++++++++------
 include/linux/device.h |    5 +++++
 include/linux/pm.h     |    6 ++++++
 4 files changed, 36 insertions(+), 7 deletions(-)
drivers/base/bus.c +11 -1
Index: linux-pm/drivers/base/bus.c
===================================================================
@@ -509,10 +509,15 @@ int bus_add_device(struct device *dev)
 	int error = 0;
 
 	if (bus) {
+		if (bus->init) {
+			error = bus->init(dev);
+			if (error)
+				goto out_put;
+		}
 		pr_debug("bus: '%s': add device %s\n", bus->name, dev_name(dev));
 		error = device_add_attrs(bus, dev);
 		if (error)
-			goto out_put;
+			goto out_release;
 		error = device_add_groups(dev, bus->dev_groups);
 		if (error)
 			goto out_groups;
@@ -534,6 +539,9 @@ out_groups:
 	device_remove_groups(dev, bus->dev_groups);
 out_id:
 	device_remove_attrs(bus, dev);
+out_release:
+	if (bus->release)
+		bus->release(dev);
 out_put:
 	bus_put(dev->bus);
 	return error;
@@ -597,6 +605,8 @@ void bus_remove_device(struct device *de
 	device_remove_groups(dev, dev->bus->dev_groups);
 	if (klist_node_attached(&dev->p->knode_bus))
 		klist_del(&dev->p->knode_bus);
+	if (bus->release)
+		bus->release(dev);
 
 	pr_debug("bus: '%s': remove device %s\n",
 		 dev->bus->name, dev_name(dev));
include/linux/device.h +5 -0
Index: linux-pm/include/linux/device.h
===================================================================
@@ -69,6 +69,8 @@ extern void bus_remove_file(struct bus_t
  * @bus_groups:	Default attributes of the bus.
  * @dev_groups:	Default attributes of the devices on the bus.
  * @drv_groups: Default attributes of the device drivers on the bus.
+ * @init:	Called when registering a device on this bus.
+ * @release:	Called when unregistering a device on this bus.
  * @match:	Called, perhaps multiple times, whenever a new device or driver
  *		is added for this bus. It should return a nonzero value if the
  *		given device can be handled by the given driver.
@@ -111,6 +113,9 @@ struct bus_type {
 	const struct attribute_group **dev_groups;
 	const struct attribute_group **drv_groups;
 
+	int (*init)(struct device *dev);
+	void (*release)(struct device *dev);
+
 	int (*match)(struct device *dev, struct device_driver *drv);
 	int (*uevent)(struct device *dev, struct kobj_uevent_env *env);
 	int (*probe)(struct device *dev);
include/linux/pm.h +6 -0
Index: linux-pm/include/linux/pm.h
===================================================================
@@ -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 successful execiton of the probe routines.
  */
 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);
 };
 
 /*
drivers/base/dd.c +14 -6
Index: linux-pm/drivers/base/dd.c
===================================================================
@@ -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",
#13 lore raw

PATCH 1/1 driver core / PM: Add callbacks for PM domain initialization/cleanup

Quoted 33 lines · Rafael J. Wysocki

From: Rafael J. Wysocki <[email protected]>

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, to prevent power from being drawn in vain.

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

That is not sufficient, however, because the device's PM domain pointer has to be populated for the ->activate callback to be executed, so setting it in bus type ->probe callback routines would be too late. Also, there are bus types where PM domains are not used at all and the core should not attempt to set the pm_domain pointer for the devices on those buses.

To overcome that difficulty, introduce two new bus type callbacks, ->init and ->release, called by bus_add_device() and bus_remove_device(), respectively. That will allow ->init to be used to populate the pm_domain pointer for the bus types that want to do that and ->release will be useful for any cleanup that may be necessary after removing a device that was part of a PM domain.

Quoted 7 lines

---

It occured to me that we might want to ->sync regardless of whether or not the probing had been succenssful, so I changed the code in really_probe() along these lines. Please let me know if that's not OK.

Make perfect sense!

Quoted 40 lines
---
 drivers/base/bus.c     |   12 +++++++++++-
 drivers/base/dd.c      |   20 ++++++++++++++------
 include/linux/device.h |    5 +++++
 include/linux/pm.h     |    6 ++++++
 4 files changed, 36 insertions(+), 7 deletions(-)

Index: linux-pm/drivers/base/bus.c
===================================================================

drivers/base/bus.c +9 -1
@@ -509,10 +509,15 @@ int bus_add_device(struct device *dev)
        int error = 0;
 
        if (bus) {
+               if (bus->init) {
+                       error = bus->init(dev);
+                       if (error)
+                               goto out_put;
+               }
                pr_debug("bus: '%s': add device %s\n", bus->name, dev_name(dev));
                error = device_add_attrs(bus, dev);
                if (error)
-                       goto out_put;
+                       goto out_release;
                error = device_add_groups(dev, bus->dev_groups);
                if (error)
                        goto out_groups;
@@ -534,6 +539,9 @@ out_groups:
        device_remove_groups(dev, bus->dev_groups);
 out_id:
        device_remove_attrs(bus, dev);
+out_release:
+       if (bus->release)
+               bus->release(dev);
 out_put:
        bus_put(dev->bus);
        return error;

drivers/base/bus.c void bus_remove_device(struct device *de · line 609

Quoted 5 lines
drivers/base/bus.c +2 -0
@@ -597,6 +605,8 @@ void bus_remove_device(struct device *de
        device_remove_groups(dev, dev->bus->dev_groups);
        if (klist_node_attached(&dev->p->knode_bus))
                klist_del(&dev->p->knode_bus);
+       if (bus->release)
+               bus->release(dev);

I think we should move this new code block below the call to device_release_driver(), since else the bus'/driver's ->remove() callbacks may be invoked after the ->pm_domain pointer for the device has been removed.

Moving the code below the call to device_release_driver() also means device's devm* managed resources will be freed prior invoking the bus' ->release() callback. Genpd don't have any issues to cope with that I believe that's okay for ACPI as well, but not sure.

Moreover, considering the case where device won't be removed but only its corresponding driver. In that case, the PM domain won't be notified other than through runtime PM transitions. I don't think that's enough, we will likely need to add yet another callback in the struct dev_pm_domain, to be invoked from __device_release_driver().

Quoted 80 lines
drivers/base/bus.c +0 -0
        pr_debug("bus: '%s': remove device %s\n",
                 dev->bus->name, dev_name(dev));

Index: linux-pm/include/linux/device.h
===================================================================

include/linux/device.h +5 -0
@@ -69,6 +69,8 @@ extern void bus_remove_file(struct bus_t
  * @bus_groups:        Default attributes of the bus.
  * @dev_groups:        Default attributes of the devices on the bus.
  * @drv_groups: Default attributes of the device drivers on the bus.
+ * @init:      Called when registering a device on this bus.
+ * @release:   Called when unregistering a device on this bus.
  * @match:     Called, perhaps multiple times, whenever a new device or driver
  *             is added for this bus. It should return a nonzero value if the
  *             given device can be handled by the given driver.
@@ -111,6 +113,9 @@ struct bus_type {
        const struct attribute_group **dev_groups;
        const struct attribute_group **drv_groups;
 
+       int (*init)(struct device *dev);
+       void (*release)(struct device *dev);
+
        int (*match)(struct device *dev, struct device_driver *drv);
        int (*uevent)(struct device *dev, struct kobj_uevent_env *env);
        int (*probe)(struct device *dev);

Index: linux-pm/include/linux/pm.h
===================================================================

include/linux/pm.h +6 -0
@@ -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 successful execiton of the probe routines.
  */
 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);
 };
 
 /*

Index: linux-pm/drivers/base/dd.c
===================================================================

drivers/base/dd.c +7 -6
@@ -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);

drivers/base/dd.c static int really_probe(struct device *d · line 321

Quoted 10 lines
drivers/base/dd.c +7 -0
+
+       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",

Kind regards
Uffe

#14 lore raw

PATCH 1/1 driver core / PM: Add callbacks for PM domain initialization/cleanup

Quoted 86 lines · Ulf Hansson
Quoted 33 lines · Rafael J. Wysocki

From: Rafael J. Wysocki <[email protected]>

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, to prevent power from being drawn in vain.

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

That is not sufficient, however, because the device's PM domain pointer has to be populated for the ->activate callback to be executed, so setting it in bus type ->probe callback routines would be too late. Also, there are bus types where PM domains are not used at all and the core should not attempt to set the pm_domain pointer for the devices on those buses.

To overcome that difficulty, introduce two new bus type callbacks, ->init and ->release, called by bus_add_device() and bus_remove_device(), respectively. That will allow ->init to be used to populate the pm_domain pointer for the bus types that want to do that and ->release will be useful for any cleanup that may be necessary after removing a device that was part of a PM domain.

Quoted 7 lines

---

It occured to me that we might want to ->sync regardless of whether or not the probing had been succenssful, so I changed the code in really_probe() along these lines. Please let me know if that's not OK.

Make perfect sense!

Quoted 42 lines
---
 drivers/base/bus.c     |   12 +++++++++++-
 drivers/base/dd.c      |   20 ++++++++++++++------
 include/linux/device.h |    5 +++++
 include/linux/pm.h     |    6 ++++++
 4 files changed, 36 insertions(+), 7 deletions(-)

Index: linux-pm/drivers/base/bus.c
===================================================================

drivers/base/bus.c +9 -1
@@ -509,10 +509,15 @@ int bus_add_device(struct device *dev)
        int error = 0;
 
        if (bus) {
+               if (bus->init) {
+                       error = bus->init(dev);
+                       if (error)
+                               goto out_put;
+               }
                pr_debug("bus: '%s': add device %s\n", bus->name, dev_name(dev));
                error = device_add_attrs(bus, dev);
                if (error)
-                       goto out_put;
+                       goto out_release;
                error = device_add_groups(dev, bus->dev_groups);
                if (error)
                        goto out_groups;
@@ -534,6 +539,9 @@ out_groups:
        device_remove_groups(dev, bus->dev_groups);
 out_id:
        device_remove_attrs(bus, dev);
+out_release:
+       if (bus->release)
+               bus->release(dev);
 out_put:
        bus_put(dev->bus);
        return error;
@@ -597,6 +605,8 @@ void bus_remove_device(struct device *de
        device_remove_groups(dev, dev->bus->dev_groups);
        if (klist_node_attached(&dev->p->knode_bus))
Quoted 8 lines

drivers/base/bus.c void bus_remove_device(struct device *de · line 609

Quoted 3 lines
drivers/base/bus.c +2 -0
                klist_del(&dev->p->knode_bus);
+       if (bus->release)
+               bus->release(dev);

I think we should move this new code block below the call to device_release_driver(), since else the bus'/driver's ->remove() callbacks may be invoked after the ->pm_domain pointer for the device has been removed.

Good point, I'll fix that.

Quoted 4 lines

Moving the code below the call to device_release_driver() also means device's devm* managed resources will be freed prior invoking the bus' ->release() callback. Genpd don't have any issues to cope with that I believe that's okay for ACPI as well, but not sure.

It is.

Quoted 5 lines

Moreover, considering the case where device won't be removed but only its corresponding driver. In that case, the PM domain won't be notified other than through runtime PM transitions. I don't think that's enough, we will likely need to add yet another callback in the struct dev_pm_domain, to be invoked from __device_release_driver().

Right, so do we want to ->sync then or do we want a separate callback?

The only use case I have which is not genpd doesn't need that, so genpd will be the only user of it for the time being.

Signature · 2 lines
I speak only for myself.
Rafael J. Wysocki, Intel Open Source Technology Center.
#15 lore raw

PATCH 1/1 driver core / PM: Add callbacks for PM domain initialization/cleanup

Quoted 105 lines · Rafael J. Wysocki
Quoted 86 lines · Ulf Hansson
Quoted 33 lines · Rafael J. Wysocki

From: Rafael J. Wysocki <[email protected]>

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, to prevent power from being drawn in vain.

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

That is not sufficient, however, because the device's PM domain pointer has to be populated for the ->activate callback to be executed, so setting it in bus type ->probe callback routines would be too late. Also, there are bus types where PM domains are not used at all and the core should not attempt to set the pm_domain pointer for the devices on those buses.

To overcome that difficulty, introduce two new bus type callbacks, ->init and ->release, called by bus_add_device() and bus_remove_device(), respectively. That will allow ->init to be used to populate the pm_domain pointer for the bus types that want to do that and ->release will be useful for any cleanup that may be necessary after removing a device that was part of a PM domain.

Quoted 7 lines

---

It occured to me that we might want to ->sync regardless of whether or not the probing had been succenssful, so I changed the code in really_probe() along these lines. Please let me know if that's not OK.

Make perfect sense!

Quoted 42 lines
---
 drivers/base/bus.c     |   12 +++++++++++-
 drivers/base/dd.c      |   20 ++++++++++++++------
 include/linux/device.h |    5 +++++
 include/linux/pm.h     |    6 ++++++
 4 files changed, 36 insertions(+), 7 deletions(-)

Index: linux-pm/drivers/base/bus.c
===================================================================

drivers/base/bus.c +9 -1
@@ -509,10 +509,15 @@ int bus_add_device(struct device *dev)
        int error = 0;
 
        if (bus) {
+               if (bus->init) {
+                       error = bus->init(dev);
+                       if (error)
+                               goto out_put;
+               }
                pr_debug("bus: '%s': add device %s\n", bus->name, dev_name(dev));
                error = device_add_attrs(bus, dev);
                if (error)
-                       goto out_put;
+                       goto out_release;
                error = device_add_groups(dev, bus->dev_groups);
                if (error)
                        goto out_groups;
@@ -534,6 +539,9 @@ out_groups:
        device_remove_groups(dev, bus->dev_groups);
 out_id:
        device_remove_attrs(bus, dev);
+out_release:
+       if (bus->release)
+               bus->release(dev);
 out_put:
        bus_put(dev->bus);
        return error;
@@ -597,6 +605,8 @@ void bus_remove_device(struct device *de
        device_remove_groups(dev, dev->bus->dev_groups);
        if (klist_node_attached(&dev->p->knode_bus))
Quoted 8 lines

drivers/base/bus.c void bus_remove_device(struct device *de · line 609

Quoted 3 lines
drivers/base/bus.c +2 -0
                klist_del(&dev->p->knode_bus);
+       if (bus->release)
+               bus->release(dev);

I think we should move this new code block below the call to device_release_driver(), since else the bus'/driver's ->remove() callbacks may be invoked after the ->pm_domain pointer for the device has been removed.

Good point, I'll fix that.

Quoted 4 lines

Moving the code below the call to device_release_driver() also means device's devm* managed resources will be freed prior invoking the bus' ->release() callback. Genpd don't have any issues to cope with that I believe that's okay for ACPI as well, but not sure.

It is.

Quoted 7 lines
Quoted 5 lines

Moreover, considering the case where device won't be removed but only its corresponding driver. In that case, the PM domain won't be notified other than through runtime PM transitions. I don't think that's enough, we will likely need to add yet another callback in the struct dev_pm_domain, to be invoked from __device_release_driver().

Right, so do we want to ->sync then or do we want a separate callback?

For genpd, I guess using ->sync() should work.

Typically I envision the ->sync() callback for genpd to check whether runtime PM is enabled or disabled for the device (pm_runtime_enable()), at take appropriate actions.

The prerequisite to make this work, is that all drivers/buses make sure to disable runtime PM from their ->remove() callbacks. I guess we should expect them to behave like this, else they must be fixed.

Quoted 4 lines

The only use case I have which is not genpd doesn't need that, so genpd will be the only user of it for the time being.

Currently acpi_dev_pm_attach() do more things than just assigning the device's pm_domain pointer.

My idea was to split that into two parts.

1) The first part takes care of assigning the device's pm_domain pointer to "&acpi_general_pm_domain" which is done when bus_type's ->init() callback get invoked.

2) The second part, which basically will be the remaining operations from acpi_dev_pm_attach(), should be done from the PM domain's ->activate() callback.

To be able to reverse these actions (acpi_dev_pm_dettach()), for both device-remove and driver-remove, don't you think ACPI also will need to get some notification from a callback, during __device_release_driver()?

Kind regards
Uffe

#16 lore raw

PATCH 1/1 driver core / PM: Add callbacks for PM domain initialization/cleanup

In reply to Rafael J. Wysocki
Quoted 53 lines · Rafael J. Wysocki

From: Rafael J. Wysocki <[email protected]>

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, to prevent power from being drawn in vain.

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

That is not sufficient, however, because the device's PM domain pointer has to be populated for the ->activate callback to be executed, so setting it in bus type ->probe callback routines would be too late. Also, there are bus types where PM domains are not used at all and the core should not attempt to set the pm_domain pointer for the devices on those buses.

To overcome that difficulty, introduce two new bus type callbacks, ->init and ->release, called by bus_add_device() and bus_remove_device(), respectively. That will allow ->init to be used to populate the pm_domain pointer for the bus types that want to do that and ->release will be useful for any cleanup that may be necessary after removing a device that was part of a PM domain.

---

It occured to me that we might want to ->sync regardless of whether or not the probing had been succenssful, so I changed the code in really_probe() along these lines. Please let me know if that's not OK.

---
 drivers/base/bus.c     |   12 +++++++++++-
 drivers/base/dd.c      |   20 ++++++++++++++------
 include/linux/device.h |    5 +++++
 include/linux/pm.h     |    6 ++++++
 4 files changed, 36 insertions(+), 7 deletions(-)

Index: linux-pm/drivers/base/bus.c
===================================================================

drivers/base/bus.c int bus_add_device(struct device *dev) · line 516

Quoted 8 lines
drivers/base/bus.c +5 -0
@@ -509,10 +509,15 @@ int bus_add_device(struct device *dev)
 	int error = 0;
 
 	if (bus) {
+		if (bus->init) {
+			error = bus->init(dev);
+			if (error)
+				goto out_put;
+		}

This doesn't make sense to me. A bus just called bus_add_device, it can do whatever it wanted to right before calling this function, no need for another callback.

Quoted 20 lines
drivers/base/bus.c +4 -1
 		pr_debug("bus: '%s': add device %s\n", bus->name, dev_name(dev));
 		error = device_add_attrs(bus, dev);
 		if (error)
-			goto out_put;
+			goto out_release;
 		error = device_add_groups(dev, bus->dev_groups);
 		if (error)
 			goto out_groups;
@@ -534,6 +539,9 @@ out_groups:
 	device_remove_groups(dev, bus->dev_groups);
 out_id:
 	device_remove_attrs(bus, dev);
+out_release:
+	if (bus->release)
+		bus->release(dev);
 
 out_put:
 	bus_put(dev->bus);
drivers/base/bus.c +0 -0
 	return error;

drivers/base/bus.c void bus_remove_device(struct device *de · line 609

Quoted 5 lines
drivers/base/bus.c +2 -0
@@ -597,6 +605,8 @@ void bus_remove_device(struct device *de
 	device_remove_groups(dev, dev->bus->dev_groups);
 	if (klist_node_attached(&dev->p->knode_bus))
 		klist_del(&dev->p->knode_bus);
+	if (bus->release)
+		bus->release(dev);

Same with release(), this happens when a bus wants to remove a device, it controls this, why have a callback right away? These both shouldn't be needed.

sorry if I missed this before, I hadn't noticed these callbacks in previous patches but I wasn't paying much attention.

thanks,

greg k-h

#17 lore raw

PATCH 1/1 driver core / PM: Add callbacks for PM domain initialization/cleanup

Quoted 56 lines · Greg Kroah-Hartman
Quoted 55 lines · Rafael J. Wysocki

From: Rafael J. Wysocki <[email protected]>

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, to prevent power from being drawn in vain.

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

That is not sufficient, however, because the device's PM domain pointer has to be populated for the ->activate callback to be executed, so setting it in bus type ->probe callback routines would be too late. Also, there are bus types where PM domains are not used at all and the core should not attempt to set the pm_domain pointer for the devices on those buses.

To overcome that difficulty, introduce two new bus type callbacks, ->init and ->release, called by bus_add_device() and bus_remove_device(), respectively. That will allow ->init to be used to populate the pm_domain pointer for the bus types that want to do that and ->release will be useful for any cleanup that may be necessary after removing a device that was part of a PM domain.

---

It occured to me that we might want to ->sync regardless of whether or not the probing had been succenssful, so I changed the code in really_probe() along these lines. Please let me know if that's not OK.

---
 drivers/base/bus.c     |   12 +++++++++++-
 drivers/base/dd.c      |   20 ++++++++++++++------
 include/linux/device.h |    5 +++++
 include/linux/pm.h     |    6 ++++++
 4 files changed, 36 insertions(+), 7 deletions(-)

Index: linux-pm/drivers/base/bus.c
===================================================================

drivers/base/bus.c +0 -0
@@ -509,10 +509,15 @@ int bus_add_device(struct device *dev)
 	int error = 0;
 
Quoted 10 lines

drivers/base/bus.c int bus_add_device(struct device *dev) · line 516

Quoted 6 lines
drivers/base/bus.c +5 -0
 	if (bus) {
+		if (bus->init) {
+			error = bus->init(dev);
+			if (error)
+				goto out_put;
+		}

This doesn't make sense to me. A bus just called bus_add_device, it can do whatever it wanted to right before calling this function, no need for another callback.

The only caller of bus_add_device() is device_add().

What do you mean by "bus just called bus_add_device"? Do you think that the pm_domain pointer should be populated before calling device_add()?

That wouldn't work for the ACPI PM domain at least, because ACPI companions are generally added during device_add() and we arguably cannot point a device to the ACPI PM domain before its ACPI companion is set.

Quoted 16 lines
Quoted 15 lines
drivers/base/bus.c +4 -1
 		pr_debug("bus: '%s': add device %s\n", bus->name, dev_name(dev));
 		error = device_add_attrs(bus, dev);
 		if (error)
-			goto out_put;
+			goto out_release;
 		error = device_add_groups(dev, bus->dev_groups);
 		if (error)
 			goto out_groups;
@@ -534,6 +539,9 @@ out_groups:
 	device_remove_groups(dev, bus->dev_groups);
 out_id:
 	device_remove_attrs(bus, dev);
+out_release:
+	if (bus->release)
+		bus->release(dev);
Quoted 13 lines

drivers/base/bus.c void bus_remove_device(struct device *de · line 609

Quoted 9 lines
drivers/base/bus.c +2 -0
 out_put:
 	bus_put(dev->bus);
 	return error;
@@ -597,6 +605,8 @@ void bus_remove_device(struct device *de
 	device_remove_groups(dev, dev->bus->dev_groups);
 	if (klist_node_attached(&dev->p->knode_bus))
 		klist_del(&dev->p->knode_bus);
+	if (bus->release)
+		bus->release(dev);

Same with release(), this happens when a bus wants to remove a device, it controls this, why have a callback right away? These both shouldn't be needed.

This is for symmetry with bus_add_device() and please see the argument there.

Quoted 2 lines

sorry if I missed this before, I hadn't noticed these callbacks in previous patches but I wasn't paying much attention.

No, they were not present before.

There are two alternatives to them. One is to do PM domain attach/detach in the bus type's ->probe and ->remove, but that's suboptimal, because it is then carried out every time a driver is probed/removed for a device. The other one would be to have each interested bus type register a bus type notifier for itself, but that would be rather ugly, wouldn't it?

Rafael

#18 lore raw

PATCH 1/1 driver core / PM: Add callbacks for PM domain initialization/cleanup

Quoted 68 lines · Rafael J. Wysocki
Quoted 56 lines · Greg Kroah-Hartman
Quoted 55 lines · Rafael J. Wysocki

From: Rafael J. Wysocki <[email protected]>

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, to prevent power from being drawn in vain.

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

That is not sufficient, however, because the device's PM domain pointer has to be populated for the ->activate callback to be executed, so setting it in bus type ->probe callback routines would be too late. Also, there are bus types where PM domains are not used at all and the core should not attempt to set the pm_domain pointer for the devices on those buses.

To overcome that difficulty, introduce two new bus type callbacks, ->init and ->release, called by bus_add_device() and bus_remove_device(), respectively. That will allow ->init to be used to populate the pm_domain pointer for the bus types that want to do that and ->release will be useful for any cleanup that may be necessary after removing a device that was part of a PM domain.

---

It occured to me that we might want to ->sync regardless of whether or not the probing had been succenssful, so I changed the code in really_probe() along these lines. Please let me know if that's not OK.

---
 drivers/base/bus.c     |   12 +++++++++++-
 drivers/base/dd.c      |   20 ++++++++++++++------
 include/linux/device.h |    5 +++++
 include/linux/pm.h     |    6 ++++++
 4 files changed, 36 insertions(+), 7 deletions(-)

Index: linux-pm/drivers/base/bus.c
===================================================================

drivers/base/bus.c +0 -0
@@ -509,10 +509,15 @@ int bus_add_device(struct device *dev)
 	int error = 0;
 
Quoted 10 lines

drivers/base/bus.c int bus_add_device(struct device *dev) · line 516

Quoted 6 lines
drivers/base/bus.c +5 -0
 	if (bus) {
+		if (bus->init) {
+			error = bus->init(dev);
+			if (error)
+				goto out_put;
+		}

This doesn't make sense to me. A bus just called bus_add_device, it can do whatever it wanted to right before calling this function, no need for another callback.

Quoted 4 lines

The only caller of bus_add_device() is device_add().

What do you mean by "bus just called bus_add_device"? Do you think that the pm_domain pointer should be populated before calling device_add()?

If it's needed, sure. The bus itself (i.e. PCI, USB, etc.) just called device_add() which calls bus_add_device(), so it could set up the pm_domain pointer as it knows what is up for this device.

Quoted 3 lines

That wouldn't work for the ACPI PM domain at least, because ACPI companions are generally added during device_add() and we arguably cannot point a device to the ACPI PM domain before its ACPI companion is set.

I don't understand, what is not set up at device_add() time that is somehow set up at bus_add_device() time? Our number of callbacks seems to be getting deep and messy :)

What happens in device_pm_add(dev); in device_add()?

Quoted 35 lines
Quoted 16 lines
Quoted 15 lines
drivers/base/bus.c +4 -1
 		pr_debug("bus: '%s': add device %s\n", bus->name, dev_name(dev));
 		error = device_add_attrs(bus, dev);
 		if (error)
-			goto out_put;
+			goto out_release;
 		error = device_add_groups(dev, bus->dev_groups);
 		if (error)
 			goto out_groups;
@@ -534,6 +539,9 @@ out_groups:
 	device_remove_groups(dev, bus->dev_groups);
 out_id:
 	device_remove_attrs(bus, dev);
+out_release:
+	if (bus->release)
+		bus->release(dev);
Quoted 13 lines

drivers/base/bus.c void bus_remove_device(struct device *de · line 609

Quoted 9 lines
drivers/base/bus.c +2 -0
 out_put:
 	bus_put(dev->bus);
 	return error;
@@ -597,6 +605,8 @@ void bus_remove_device(struct device *de
 	device_remove_groups(dev, dev->bus->dev_groups);
 	if (klist_node_attached(&dev->p->knode_bus))
 		klist_del(&dev->p->knode_bus);
+	if (bus->release)
+		bus->release(dev);

Same with release(), this happens when a bus wants to remove a device, it controls this, why have a callback right away? These both shouldn't be needed.

This is for symmetry with bus_add_device() and please see the argument there.

Quoted 2 lines

sorry if I missed this before, I hadn't noticed these callbacks in previous patches but I wasn't paying much attention.

Quoted 7 lines

No, they were not present before.

There are two alternatives to them. One is to do PM domain attach/detach in the bus type's ->probe and ->remove, but that's suboptimal, because it is then carried out every time a driver is probed/removed for a device. The other one would be to have each interested bus type register a bus type notifier for itself, but that would be rather ugly, wouldn't it?

This seems really messy, and you are adding more complexity, isn't there some other easier way to do it with all of the different callbacks and notifications we have today?

thanks,

greg k-h

#19 lore raw

PATCH 1/1 driver core / PM: Add callbacks for PM domain initialization/cleanup

Quoted 69 lines · Greg Kroah-Hartman
Quoted 68 lines · Rafael J. Wysocki
Quoted 66 lines · Greg Kroah-Hartman
Quoted 53 lines · Rafael J. Wysocki

From: Rafael J. Wysocki <[email protected]>

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, to prevent power from being drawn in vain.

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

That is not sufficient, however, because the device's PM domain pointer has to be populated for the ->activate callback to be executed, so setting it in bus type ->probe callback routines would be too late. Also, there are bus types where PM domains are not used at all and the core should not attempt to set the pm_domain pointer for the devices on those buses.

To overcome that difficulty, introduce two new bus type callbacks, ->init and ->release, called by bus_add_device() and bus_remove_device(), respectively. That will allow ->init to be used to populate the pm_domain pointer for the bus types that want to do that and ->release will be useful for any cleanup that may be necessary after removing a device that was part of a PM domain.

---

It occured to me that we might want to ->sync regardless of whether or not the probing had been succenssful, so I changed the code in really_probe() along these lines. Please let me know if that's not OK.

---
 drivers/base/bus.c     |   12 +++++++++++-
 drivers/base/dd.c      |   20 ++++++++++++++------
 include/linux/device.h |    5 +++++
 include/linux/pm.h     |    6 ++++++
 4 files changed, 36 insertions(+), 7 deletions(-)

Index: linux-pm/drivers/base/bus.c
===================================================================

drivers/base/bus.c int bus_add_device(struct device *dev) · line 516

Quoted 8 lines
drivers/base/bus.c +5 -0
@@ -509,10 +509,15 @@ int bus_add_device(struct device *dev)
 	int error = 0;
 
 	if (bus) {
+		if (bus->init) {
+			error = bus->init(dev);
+			if (error)
+				goto out_put;
+		}

This doesn't make sense to me. A bus just called bus_add_device, it can do whatever it wanted to right before calling this function, no need for another callback.

Quoted 8 lines
Quoted 4 lines

The only caller of bus_add_device() is device_add().

What do you mean by "bus just called bus_add_device"? Do you think that the pm_domain pointer should be populated before calling device_add()?

If it's needed, sure. The bus itself (i.e. PCI, USB, etc.) just called device_add() which calls bus_add_device(), so it could set up the pm_domain pointer as it knows what is up for this device.

It doesn't work exactly like that. PCI, for one, doesn't know whether or not it is going to use ACPI with this particular device when it is calling device_add(). That only turns out during device_add(), when platform_notify() is called from device_add(). Fortunately, that doesn't matter for the ACPI PM domain.

For bus types that know upfront whether or not they are going to use ACPI with the device in question, we could hook the device up to the ACPI PM domain before device_add() is called. The removal part could just be covered with the PM domain's ->detach callback I suppose. I'm not sure if all bus types using the ACPI PM domain fall into this category, so I'll need to double check

However, there still is the generic PM domains framework that has grown DT support and I'm not sure if we can hook that up to devices before device_add() is called for them.

Ulf, what do you think?

Quoted 9 lines
Quoted 3 lines

That wouldn't work for the ACPI PM domain at least, because ACPI companions are generally added during device_add() and we arguably cannot point a device to the ACPI PM domain before its ACPI companion is set.

I don't understand, what is not set up at device_add() time that is somehow set up at bus_add_device() time? Our number of callbacks seems to be getting deep and messy :)

What happens in device_pm_add(dev); in device_add()?

Nothing particularly interesting. It just adds the device to the list used by system suspend/resume.

Quoted 43 lines
Quoted 35 lines
Quoted 16 lines
Quoted 15 lines
drivers/base/bus.c +4 -1
 		pr_debug("bus: '%s': add device %s\n", bus->name, dev_name(dev));
 		error = device_add_attrs(bus, dev);
 		if (error)
-			goto out_put;
+			goto out_release;
 		error = device_add_groups(dev, bus->dev_groups);
 		if (error)
 			goto out_groups;
@@ -534,6 +539,9 @@ out_groups:
 	device_remove_groups(dev, bus->dev_groups);
 out_id:
 	device_remove_attrs(bus, dev);
+out_release:
+	if (bus->release)
+		bus->release(dev);
Quoted 13 lines

drivers/base/bus.c void bus_remove_device(struct device *de · line 609

Quoted 9 lines
drivers/base/bus.c +2 -0
 out_put:
 	bus_put(dev->bus);
 	return error;
@@ -597,6 +605,8 @@ void bus_remove_device(struct device *de
 	device_remove_groups(dev, dev->bus->dev_groups);
 	if (klist_node_attached(&dev->p->knode_bus))
 		klist_del(&dev->p->knode_bus);
+	if (bus->release)
+		bus->release(dev);

Same with release(), this happens when a bus wants to remove a device, it controls this, why have a callback right away? These both shouldn't be needed.

This is for symmetry with bus_add_device() and please see the argument there.

Quoted 2 lines

sorry if I missed this before, I hadn't noticed these callbacks in previous patches but I wasn't paying much attention.

Quoted 7 lines

No, they were not present before.

There are two alternatives to them. One is to do PM domain attach/detach in the bus type's ->probe and ->remove, but that's suboptimal, because it is then carried out every time a driver is probed/removed for a device. The other one would be to have each interested bus type register a bus type notifier for itself, but that would be rather ugly, wouldn't it?

Quoted 3 lines

This seems really messy, and you are adding more complexity, isn't there some other easier way to do it with all of the different callbacks and notifications we have today?

Well, we've explored multiple alternatives already and none of them has turned out to be particularly attractive. I guess we need to explore some more of them, then. :-)

For one, I wouldn't consider adding more callbacks if I saw a clean way forward without them.

Signature · 2 lines
I speak only for myself.
Rafael J. Wysocki, Intel Open Source Technology Center.
#20 lore raw

PATCH 1/1 driver core / PM: Add callbacks for PM domain initialization/cleanup

In reply to Rafael J. Wysocki
Quoted 14 lines · Rafael J. Wysocki
Quoted 3 lines

This doesn't make sense to me. A bus just called bus_add_device, it can do whatever it wanted to right before calling this function, no need for another callback.

The only caller of bus_add_device() is device_add().

What do you mean by "bus just called bus_add_device"? Do you think that the pm_domain pointer should be populated before calling device_add()?

That wouldn't work for the ACPI PM domain at least, because ACPI companions are generally added during device_add() and we arguably cannot point a device to the ACPI PM domain before its ACPI companion is set.

Quoted 5 lines

There are two alternatives to them. One is to do PM domain attach/detach in the bus type's ->probe and ->remove, but that's suboptimal, because it is then carried out every time a driver is probed/removed for a device. The other one would be to have each interested bus type register a bus type notifier for itself, but that would be rather ugly, wouldn't it?

Driver probing and removal is not a hot path. Successful probes usually occur only once for each device. I don't know how many unsuccessful probes there are on average, but probably not many.

Doing the PM domain attach/detach in ->probe and ->remove makes sense to me.

Alan Stern

#21 lore raw

PATCH 1/1 driver core / PM: Add callbacks for PM domain initialization/cleanup

Quoted 22 lines · Alan Stern
Quoted 14 lines · Rafael J. Wysocki
Quoted 3 lines

This doesn't make sense to me. A bus just called bus_add_device, it can do whatever it wanted to right before calling this function, no need for another callback.

The only caller of bus_add_device() is device_add().

What do you mean by "bus just called bus_add_device"? Do you think that the pm_domain pointer should be populated before calling device_add()?

That wouldn't work for the ACPI PM domain at least, because ACPI companions are generally added during device_add() and we arguably cannot point a device to the ACPI PM domain before its ACPI companion is set.

Quoted 5 lines

There are two alternatives to them. One is to do PM domain attach/detach in the bus type's ->probe and ->remove, but that's suboptimal, because it is then carried out every time a driver is probed/removed for a device. The other one would be to have each interested bus type register a bus type notifier for itself, but that would be rather ugly, wouldn't it?

Quoted 6 lines

Driver probing and removal is not a hot path. Successful probes usually occur only once for each device. I don't know how many unsuccessful probes there are on average, but probably not many.

Doing the PM domain attach/detach in ->probe and ->remove makes sense to me.

Let me elaborate a bit on the current approach, with PM domain attach/detach in ->probe() and ->remove(). This comes with the following limitations.

1) If the device gets probed earlier than the PM domain has been initialized, we can't return -EPROBE_DEFER since we just don't know anything about the PM domain yet.

2) The PM domain won't be able to operate on a device without having a driver bound to it, since the device's PM domain pointer is removed at ->remove().

Perhaps Rafael want to add something to these? I don't know whether we think it's okay to keep these limitations or not.

Kind regards
Uffe

#22 lore raw

PATCH 1/1 driver core / PM: Add callbacks for PM domain initialization/cleanup

Quoted 38 lines · Ulf Hansson
Quoted 22 lines · Alan Stern
Quoted 14 lines · Rafael J. Wysocki
Quoted 3 lines

This doesn't make sense to me. A bus just called bus_add_device, it can do whatever it wanted to right before calling this function, no need for another callback.

The only caller of bus_add_device() is device_add().

What do you mean by "bus just called bus_add_device"? Do you think that the pm_domain pointer should be populated before calling device_add()?

That wouldn't work for the ACPI PM domain at least, because ACPI companions are generally added during device_add() and we arguably cannot point a device to the ACPI PM domain before its ACPI companion is set.

Quoted 5 lines

There are two alternatives to them. One is to do PM domain attach/detach in the bus type's ->probe and ->remove, but that's suboptimal, because it is then carried out every time a driver is probed/removed for a device. The other one would be to have each interested bus type register a bus type notifier for itself, but that would be rather ugly, wouldn't it?

Quoted 6 lines

Driver probing and removal is not a hot path. Successful probes usually occur only once for each device. I don't know how many unsuccessful probes there are on average, but probably not many.

Doing the PM domain attach/detach in ->probe and ->remove makes sense to me.

Let me elaborate a bit on the current approach, with PM domain attach/detach in ->probe() and ->remove(). This comes with the following limitations.

1) If the device gets probed earlier than the PM domain has been initialized, we can't return -EPROBE_DEFER since we just don't know anything about the PM domain yet.

Quoted 6 lines

2) The PM domain won't be able to operate on a device without having a driver bound to it, since the device's PM domain pointer is removed at ->remove().

Perhaps Rafael want to add something to these? I don't know whether we think it's okay to keep these limitations or not.

There are arguments both ways as you can see.

At this point, the most straightforward approach would be to apply the Russell's patch adding the ->sync callback alone.

I will then need the ->activate callback for another use case (a PM domain that may not be ready for the device to be probed), but in that case I actually know that the pm_domain pointer is populated at the really_probe() time.

Going forward we may want to move the attach/detach operations for genpd and the ACPI PM domain out of bus type ->probe, but I think that can wait.

Signature · 2 lines
I speak only for myself.
Rafael J. Wysocki, Intel Open Source Technology Center.
#23 lore raw

PATCH 1/1 driver core / PM: Add callbacks for PM domain initialization/cleanup

Quoted 46 lines · Rafael J. Wysocki
Quoted 38 lines · Ulf Hansson
Quoted 22 lines · Alan Stern
Quoted 14 lines · Rafael J. Wysocki
Quoted 3 lines

This doesn't make sense to me. A bus just called bus_add_device, it can do whatever it wanted to right before calling this function, no need for another callback.

The only caller of bus_add_device() is device_add().

What do you mean by "bus just called bus_add_device"? Do you think that the pm_domain pointer should be populated before calling device_add()?

That wouldn't work for the ACPI PM domain at least, because ACPI companions are generally added during device_add() and we arguably cannot point a device to the ACPI PM domain before its ACPI companion is set.

Quoted 5 lines

There are two alternatives to them. One is to do PM domain attach/detach in the bus type's ->probe and ->remove, but that's suboptimal, because it is then carried out every time a driver is probed/removed for a device. The other one would be to have each interested bus type register a bus type notifier for itself, but that would be rather ugly, wouldn't it?

Quoted 6 lines

Driver probing and removal is not a hot path. Successful probes usually occur only once for each device. I don't know how many unsuccessful probes there are on average, but probably not many.

Doing the PM domain attach/detach in ->probe and ->remove makes sense to me.

Let me elaborate a bit on the current approach, with PM domain attach/detach in ->probe() and ->remove(). This comes with the following limitations.

1) If the device gets probed earlier than the PM domain has been initialized, we can't return -EPROBE_DEFER since we just don't know anything about the PM domain yet.

Quoted 6 lines

2) The PM domain won't be able to operate on a device without having a driver bound to it, since the device's PM domain pointer is removed at ->remove().

Perhaps Rafael want to add something to these? I don't know whether we think it's okay to keep these limitations or not.

Quoted 8 lines

There are arguments both ways as you can see.

At this point, the most straightforward approach would be to apply the Russell's patch adding the ->sync callback alone.

I will then need the ->activate callback for another use case (a PM domain that may not be ready for the device to be probed), but in that case I actually know that the pm_domain pointer is populated at the really_probe() time.

Then, how about adding only the ->sync() and ->activate() callback in one patch - and invoke them from really_probe()? That's seems to fit both our short and long term approach.

Genpd may then implement the ->sync() callback, which is similar to Russell's patch, except that it will now cover all buses and not just the platform bus as it where before.

Quoted 3 lines

Going forward we may want to move the attach/detach operations for genpd and the ACPI PM domain out of bus type ->probe, but I think that can wait.

Agree!

Kind regards
Uffe

#24 lore raw

PATCH 1/1 driver core / PM: Add callbacks for PM domain initialization/cleanup

Quoted 56 lines · Ulf Hansson
Quoted 46 lines · Rafael J. Wysocki
Quoted 38 lines · Ulf Hansson
Quoted 22 lines · Alan Stern
Quoted 14 lines · Rafael J. Wysocki
Quoted 3 lines

This doesn't make sense to me. A bus just called bus_add_device, it can do whatever it wanted to right before calling this function, no need for another callback.

The only caller of bus_add_device() is device_add().

What do you mean by "bus just called bus_add_device"? Do you think that the pm_domain pointer should be populated before calling device_add()?

That wouldn't work for the ACPI PM domain at least, because ACPI companions are generally added during device_add() and we arguably cannot point a device to the ACPI PM domain before its ACPI companion is set.

Quoted 5 lines

There are two alternatives to them. One is to do PM domain attach/detach in the bus type's ->probe and ->remove, but that's suboptimal, because it is then carried out every time a driver is probed/removed for a device. The other one would be to have each interested bus type register a bus type notifier for itself, but that would be rather ugly, wouldn't it?

Quoted 6 lines

Driver probing and removal is not a hot path. Successful probes usually occur only once for each device. I don't know how many unsuccessful probes there are on average, but probably not many.

Doing the PM domain attach/detach in ->probe and ->remove makes sense to me.

Let me elaborate a bit on the current approach, with PM domain attach/detach in ->probe() and ->remove(). This comes with the following limitations.

1) If the device gets probed earlier than the PM domain has been initialized, we can't return -EPROBE_DEFER since we just don't know anything about the PM domain yet.

Quoted 6 lines

2) The PM domain won't be able to operate on a device without having a driver bound to it, since the device's PM domain pointer is removed at ->remove().

Perhaps Rafael want to add something to these? I don't know whether we think it's okay to keep these limitations or not.

Quoted 8 lines

There are arguments both ways as you can see.

At this point, the most straightforward approach would be to apply the Russell's patch adding the ->sync callback alone.

I will then need the ->activate callback for another use case (a PM domain that may not be ready for the device to be probed), but in that case I actually know that the pm_domain pointer is populated at the really_probe() time.

Quoted 7 lines

Then, how about adding only the ->sync() and ->activate() callback in one patch - and invoke them from really_probe()? That's seems to fit both our short and long term approach.

Genpd may then implement the ->sync() callback, which is similar to Russell's patch, except that it will now cover all buses and not just the platform bus as it where before.

OK

So do we need to do ->sync at the driver removal time too? I guess we do?

Signature · 2 lines
I speak only for myself.
Rafael J. Wysocki, Intel Open Source Technology Center.
#25 lore raw

PATCH 1/1 driver core / PM: Add callbacks for PM domain initialization/cleanup

Quoted 61 lines · Rafael J. Wysocki
Quoted 60 lines · Ulf Hansson
Quoted 46 lines · Rafael J. Wysocki
Quoted 38 lines · Ulf Hansson
Quoted 22 lines · Alan Stern
Quoted 14 lines · Rafael J. Wysocki
Quoted 3 lines

This doesn't make sense to me. A bus just called bus_add_device, it can do whatever it wanted to right before calling this function, no need for another callback.

The only caller of bus_add_device() is device_add().

What do you mean by "bus just called bus_add_device"? Do you think that the pm_domain pointer should be populated before calling device_add()?

That wouldn't work for the ACPI PM domain at least, because ACPI companions are generally added during device_add() and we arguably cannot point a device to the ACPI PM domain before its ACPI companion is set.

Quoted 5 lines

There are two alternatives to them. One is to do PM domain attach/detach in the bus type's ->probe and ->remove, but that's suboptimal, because it is then carried out every time a driver is probed/removed for a device. The other one would be to have each interested bus type register a bus type notifier for itself, but that would be rather ugly, wouldn't it?

Quoted 6 lines

Driver probing and removal is not a hot path. Successful probes usually occur only once for each device. I don't know how many unsuccessful probes there are on average, but probably not many.

Doing the PM domain attach/detach in ->probe and ->remove makes sense to me.

Let me elaborate a bit on the current approach, with PM domain attach/detach in ->probe() and ->remove(). This comes with the following limitations.

1) If the device gets probed earlier than the PM domain has been initialized, we can't return -EPROBE_DEFER since we just don't know anything about the PM domain yet.

Quoted 6 lines

2) The PM domain won't be able to operate on a device without having a driver bound to it, since the device's PM domain pointer is removed at ->remove().

Perhaps Rafael want to add something to these? I don't know whether we think it's okay to keep these limitations or not.

Quoted 8 lines

There are arguments both ways as you can see.

At this point, the most straightforward approach would be to apply the Russell's patch adding the ->sync callback alone.

I will then need the ->activate callback for another use case (a PM domain that may not be ready for the device to be probed), but in that case I actually know that the pm_domain pointer is populated at the really_probe() time.

Then, how about adding only the ->sync() and ->activate() callback in one patch - and invoke them from really_probe()? That's seems to fit both our short and long term approach.

Quoted 7 lines
Quoted 3 lines

Genpd may then implement the ->sync() callback, which is similar to Russell's patch, except that it will now cover all buses and not just the platform bus as it where before.

OK

So do we need to do ->sync at the driver removal time too? I guess we do?

For genpd, it will currently not matter since the device will be detached from its PM domain before that ->sync() would be called.

Though, to prepare for the "long term" solution we could decide to add it...

Kind regards
Uffe

#26 lore raw

PATCH 1/1 driver core / PM: Add callbacks for PM domain initialization/cleanup

Quoted 66 lines · Ulf Hansson
Quoted 65 lines · Rafael J. Wysocki
Quoted 63 lines · Ulf Hansson
Quoted 46 lines · Rafael J. Wysocki
Quoted 38 lines · Ulf Hansson
Quoted 22 lines · Alan Stern
Quoted 14 lines · Rafael J. Wysocki
Quoted 3 lines

This doesn't make sense to me. A bus just called bus_add_device, it can do whatever it wanted to right before calling this function, no need for another callback.

The only caller of bus_add_device() is device_add().

What do you mean by "bus just called bus_add_device"? Do you think that the pm_domain pointer should be populated before calling device_add()?

That wouldn't work for the ACPI PM domain at least, because ACPI companions are generally added during device_add() and we arguably cannot point a device to the ACPI PM domain before its ACPI companion is set.

Quoted 5 lines

There are two alternatives to them. One is to do PM domain attach/detach in the bus type's ->probe and ->remove, but that's suboptimal, because it is then carried out every time a driver is probed/removed for a device. The other one would be to have each interested bus type register a bus type notifier for itself, but that would be rather ugly, wouldn't it?

Quoted 6 lines

Driver probing and removal is not a hot path. Successful probes usually occur only once for each device. I don't know how many unsuccessful probes there are on average, but probably not many.

Doing the PM domain attach/detach in ->probe and ->remove makes sense to me.

Let me elaborate a bit on the current approach, with PM domain attach/detach in ->probe() and ->remove(). This comes with the following limitations.

1) If the device gets probed earlier than the PM domain has been initialized, we can't return -EPROBE_DEFER since we just don't know anything about the PM domain yet.

Quoted 6 lines

2) The PM domain won't be able to operate on a device without having a driver bound to it, since the device's PM domain pointer is removed at ->remove().

Perhaps Rafael want to add something to these? I don't know whether we think it's okay to keep these limitations or not.

Quoted 8 lines

There are arguments both ways as you can see.

At this point, the most straightforward approach would be to apply the Russell's patch adding the ->sync callback alone.

I will then need the ->activate callback for another use case (a PM domain that may not be ready for the device to be probed), but in that case I actually know that the pm_domain pointer is populated at the really_probe() time.

Then, how about adding only the ->sync() and ->activate() callback in one patch - and invoke them from really_probe()? That's seems to fit both our short and long term approach.

Genpd may then implement the ->sync() callback, which is similar to Russell's patch, except that it will now cover all buses and not just the platform bus as it where before.

Quoted 8 lines
Quoted 3 lines

OK

So do we need to do ->sync at the driver removal time too? I guess we do?

For genpd, it will currently not matter since the device will be detached from its PM domain before that ->sync() would be called.

Though, to prepare for the "long term" solution we could decide to add it...

OK, at that time.

Fine, I'll send an update, then.

Signature · 2 lines
I speak only for myself.
Rafael J. Wysocki, Intel Open Source Technology Center.
#27 lore raw

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

From: Rafael J. Wysocki <[email protected]>

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 and ->sync, called, respectively, before probing for a device driver and after the probing has been completed or the driver has been removed.

---

This is an update without the additional bus type callbacks. This should be suffucient at this point for the use cases we have.

I've decided to also call ->sync on driver removal as that is consistent with what happens for failing probe.

---
 drivers/base/dd.c  |   24 ++++++++++++++++++------
 include/linux/pm.h |    6 ++++++
 2 files changed, 24 insertions(+), 6 deletions(-)
include/linux/pm.h +6 -0
Index: linux-pm/include/linux/pm.h
===================================================================
@@ -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);
 };
 
 /*
drivers/base/dd.c +18 -6
Index: linux-pm/drivers/base/dd.c
===================================================================
@@ -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);
#28 lore raw

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

From: Rafael J. Wysocki <[email protected]>
Subject: 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 and ->sync, called, respectively, before probing for a device driver and after the probing has been completed or the driver has been removed.

---

Quoted 9 lines

---

This is an update without the additional bus type callbacks. This should be suffucient at this point for the use cases we have.

I've decided to also call ->sync on driver removal as that is consistent with what happens for failing probe.

---

One more update.

I've realized that in the PM domain's ->sync callback is called after clearing the device's driver field (in the failed probe or driver removal case) rather than before it, that could be used to distinguish between the two cases (successful probe vs no driver), so I reworked the patch accordingly.

---
 drivers/base/dd.c  |   16 ++++++++++++++++
 include/linux/pm.h |    6 ++++++
 2 files changed, 22 insertions(+)
include/linux/pm.h +6 -0
Index: linux-pm/include/linux/pm.h
===================================================================
@@ -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);
 };
 
 /*
drivers/base/dd.c +16 -0
Index: linux-pm/drivers/base/dd.c
===================================================================
@@ -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,6 +299,12 @@ static int really_probe(struct device *d
 		goto probe_failed;
 	}
 
+	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);
 		if (ret)
@@ -308,6 +315,9 @@ static int really_probe(struct device *d
 			goto probe_failed;
 	}
 
+	if (pm_domain && pm_domain->sync)
+		pm_domain->sync(dev);
+
 	driver_bound(dev);
 	ret = 1;
 	pr_debug("bus: '%s': %s: bound device %s to driver %s\n",
@@ -319,6 +329,8 @@ probe_failed:
 	driver_sysfs_remove(dev);
 	dev->driver = NULL;
 	dev_set_drvdata(dev, NULL);
+	if (pm_domain && pm_domain->sync)
+		pm_domain->sync(dev);
 
 	if (ret == -EPROBE_DEFER) {
 		/* Driver requested deferred probing */
@@ -522,9 +534,13 @@ static void __device_release_driver(stru
 			dev->bus->remove(dev);
 		else if (drv->remove)
 			drv->remove(dev);
+
 		devres_release_all(dev);
 		dev->driver = NULL;
 		dev_set_drvdata(dev, NULL);
+		if (dev->pm_domain && dev->pm_domain->sync)
+			dev->pm_domain->sync(dev);
+
 		klist_remove(&dev->p->knode_driver);
 		if (dev->bus)
 			blocking_notifier_call_chain(&dev->bus->p->bus_notifier,
#29 lore raw

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

Quoted 32 lines · Rafael J. Wysocki

From: Rafael J. Wysocki <[email protected]>
Subject: 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 and ->sync, called, respectively, before probing for a device driver and after the probing has been completed or the driver has been removed.

---

Quoted 8 lines

---

This is an update without the additional bus type callbacks. This should be suffucient at this point for the use cases we have.

I've decided to also call ->sync on driver removal as that is consistent with what happens for failing probe.

Quoted 8 lines
Quoted 1 line

---

One more update.

I've realized that in the PM domain's ->sync callback is called after clearing the device's driver field (in the failed probe or driver removal case) rather than before it, that could be used to distinguish between the two cases (successful probe vs no driver), so I reworked the patch accordingly.

That is very non-obvious. dev->drv belongs to driver core and maybe bus, nothing else should really be looking at it. Why can't we add an explicit argument to the callback indicating device state?

Thanks.

Quoted 86 lines
---
 drivers/base/dd.c  |   16 ++++++++++++++++
 include/linux/pm.h |    6 ++++++
 2 files changed, 22 insertions(+)

Index: linux-pm/include/linux/pm.h
===================================================================

include/linux/pm.h +6 -0
@@ -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);
 };
 
 /*

Index: linux-pm/drivers/base/dd.c
===================================================================

drivers/base/dd.c +16 -0
@@ -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,6 +299,12 @@ static int really_probe(struct device *d
                goto probe_failed;
        }
 
+       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);
                if (ret)
@@ -308,6 +315,9 @@ static int really_probe(struct device *d
                        goto probe_failed;
        }
 
+       if (pm_domain && pm_domain->sync)
+               pm_domain->sync(dev);
+
        driver_bound(dev);
        ret = 1;
        pr_debug("bus: '%s': %s: bound device %s to driver %s\n",
@@ -319,6 +329,8 @@ probe_failed:
        driver_sysfs_remove(dev);
        dev->driver = NULL;
        dev_set_drvdata(dev, NULL);
+       if (pm_domain && pm_domain->sync)
+               pm_domain->sync(dev);
 
        if (ret == -EPROBE_DEFER) {
                /* Driver requested deferred probing */
@@ -522,9 +534,13 @@ static void __device_release_driver(stru
                        dev->bus->remove(dev);
                else if (drv->remove)
                        drv->remove(dev);
+
                devres_release_all(dev);
                dev->driver = NULL;
                dev_set_drvdata(dev, NULL);
+               if (dev->pm_domain && dev->pm_domain->sync)
+                       dev->pm_domain->sync(dev);
+
                klist_remove(&dev->p->knode_driver);
                if (dev->bus)
                        blocking_notifier_call_chain(&dev->bus->p->bus_notifier,
Signature · 1 line
Dmitry
#30 lore raw

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

Quoted 37 lines · Dmitry Torokhov
Quoted 36 lines · Rafael J. Wysocki

From: Rafael J. Wysocki <[email protected]>
Subject: 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 and ->sync, called, respectively, before probing for a device driver and after the probing has been completed or the driver has been removed.

---

Quoted 9 lines

---

This is an update without the additional bus type callbacks. This should be suffucient at this point for the use cases we have.

I've decided to also call ->sync on driver removal as that is consistent with what happens for failing probe.

---

One more update.

Quoted 8 lines
Quoted 4 lines

I've realized that in the PM domain's ->sync callback is called after clearing the device's driver field (in the failed probe or driver removal case) rather than before it, that could be used to distinguish between the two cases (successful probe vs no driver), so I reworked the patch accordingly.

That is very non-obvious. dev->drv belongs to driver core and maybe bus, nothing else should really be looking at it. Why can't we add an explicit argument to the callback indicating device state?

Well, if that's a concern, I'd rather introduce a separate callback to be run on driver removal/failing probe, like in the patch below, as it is then clear what the conditions for each callback's execution are (and one can always define them as wrappers around the same routine if need be).

I still think that this ordering of code is the right one, though.

Rafael

---
 drivers/base/dd.c  |   16 ++++++++++++++++
 include/linux/pm.h |    8 ++++++++
 2 files changed, 24 insertions(+)
include/linux/pm.h +8 -0
Index: linux-pm/include/linux/pm.h
===================================================================
@@ -603,10 +603,18 @@ 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 successful driver probe.
+ * @dismiss: Called after unsuccessful driver probe and after driver 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);
+	void (*dismiss)(struct device *dev);
 };
 
 /*
drivers/base/dd.c +16 -0
Index: linux-pm/drivers/base/dd.c
===================================================================
@@ -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,6 +299,12 @@ static int really_probe(struct device *d
 		goto probe_failed;
 	}
 
+	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);
 		if (ret)
@@ -308,6 +315,9 @@ static int really_probe(struct device *d
 			goto probe_failed;
 	}
 
+	if (pm_domain && pm_domain->sync)
+		pm_domain->sync(dev);
+
 	driver_bound(dev);
 	ret = 1;
 	pr_debug("bus: '%s': %s: bound device %s to driver %s\n",
@@ -319,6 +329,8 @@ probe_failed:
 	driver_sysfs_remove(dev);
 	dev->driver = NULL;
 	dev_set_drvdata(dev, NULL);
+	if (pm_domain && pm_domain->dismiss)
+		pm_domain->dismiss(dev);
 
 	if (ret == -EPROBE_DEFER) {
 		/* Driver requested deferred probing */
@@ -522,9 +534,13 @@ static void __device_release_driver(stru
 			dev->bus->remove(dev);
 		else if (drv->remove)
 			drv->remove(dev);
+
 		devres_release_all(dev);
 		dev->driver = NULL;
 		dev_set_drvdata(dev, NULL);
+		if (dev->pm_domain && dev->pm_domain->dismiss)
+			dev->pm_domain->dismiss(dev);
+
 		klist_remove(&dev->p->knode_driver);
 		if (dev->bus)
 			blocking_notifier_call_chain(&dev->bus->p->bus_notifier,
#31 lore raw

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

Quoted 43 lines · Rafael J. Wysocki
Quoted 42 lines · Dmitry Torokhov
Quoted 40 lines · Rafael J. Wysocki

From: Rafael J. Wysocki <[email protected]>
Subject: 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 and ->sync, called, respectively, before probing for a device driver and after the probing has been completed or the driver has been removed.

---

Quoted 9 lines

---

This is an update without the additional bus type callbacks. This should be suffucient at this point for the use cases we have.

I've decided to also call ->sync on driver removal as that is consistent with what happens for failing probe.

---

One more update.

I've realized that in the PM domain's ->sync callback is called after clearing the device's driver field (in the failed probe or driver removal case) rather than before it, that could be used to distinguish between the two cases (successful probe vs no driver), so I reworked the patch accordingly.

Quoted 8 lines
Quoted 3 lines

That is very non-obvious. dev->drv belongs to driver core and maybe bus, nothing else should really be looking at it. Why can't we add an explicit argument to the callback indicating device state?

Well, if that's a concern, I'd rather introduce a separate callback to be run on driver removal/failing probe, like in the patch below, as it is then clear what the conditions for each callback's execution are (and one can always define them as wrappers around the same routine if need be).

Works for me.

Quoted 1 line

I still think that this ordering of code is the right one, though.

I was not arguing with that, just with the proposal of checking dev->drv in callback.

Quoted 91 lines

Rafael

---
 drivers/base/dd.c  |   16 ++++++++++++++++
 include/linux/pm.h |    8 ++++++++
 2 files changed, 24 insertions(+)

Index: linux-pm/include/linux/pm.h
===================================================================

include/linux/pm.h +8 -0
@@ -603,10 +603,18 @@ 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 successful driver probe.
+ * @dismiss: Called after unsuccessful driver probe and after driver 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);
+       void (*dismiss)(struct device *dev);
 };
 
 /*

Index: linux-pm/drivers/base/dd.c
===================================================================

drivers/base/dd.c +16 -0
@@ -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,6 +299,12 @@ static int really_probe(struct device *d
                goto probe_failed;
        }
 
+       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);
                if (ret)
@@ -308,6 +315,9 @@ static int really_probe(struct device *d
                        goto probe_failed;
        }
 
+       if (pm_domain && pm_domain->sync)
+               pm_domain->sync(dev);
+
        driver_bound(dev);
        ret = 1;
        pr_debug("bus: '%s': %s: bound device %s to driver %s\n",
@@ -319,6 +329,8 @@ probe_failed:
        driver_sysfs_remove(dev);
        dev->driver = NULL;
        dev_set_drvdata(dev, NULL);
+       if (pm_domain && pm_domain->dismiss)
+               pm_domain->dismiss(dev);
 
        if (ret == -EPROBE_DEFER) {
                /* Driver requested deferred probing */
@@ -522,9 +534,13 @@ static void __device_release_driver(stru
                        dev->bus->remove(dev);
                else if (drv->remove)
                        drv->remove(dev);
+
                devres_release_all(dev);
                dev->driver = NULL;
                dev_set_drvdata(dev, NULL);
+               if (dev->pm_domain && dev->pm_domain->dismiss)
+                       dev->pm_domain->dismiss(dev);
+
                klist_remove(&dev->p->knode_driver);
                if (dev->bus)
                        blocking_notifier_call_chain(&dev->bus->p->bus_notifier,
Signature · 1 line
Dmitry
#32 lore raw

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

In reply to Rafael J. Wysocki
Quoted 17 lines · Rafael J. Wysocki

From: Rafael J. Wysocki <[email protected]>
Subject: 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.

Quoted 6 lines

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

This looks good to me!

Quoted 103 lines

---

Quoted 9 lines

---

This is an update without the additional bus type callbacks. This should be suffucient at this point for the use cases we have.

I've decided to also call ->sync on driver removal as that is consistent with what happens for failing probe.

---

One more update.

I've realized that in the PM domain's ->sync callback is called after clearing the device's driver field (in the failed probe or driver removal case) rather than before it, that could be used to distinguish between the two cases (successful probe vs no driver), so I reworked the patch accordingly.

---
 drivers/base/dd.c  |   16 ++++++++++++++++
 include/linux/pm.h |    6 ++++++
 2 files changed, 22 insertions(+)

Index: linux-pm/include/linux/pm.h
===================================================================

include/linux/pm.h +6 -0
@@ -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);
 };
 
 /*

Index: linux-pm/drivers/base/dd.c
===================================================================

drivers/base/dd.c +16 -0
@@ -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,6 +299,12 @@ static int really_probe(struct device *d
                goto probe_failed;
        }
 
+       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);
                if (ret)
@@ -308,6 +315,9 @@ static int really_probe(struct device *d
                        goto probe_failed;
        }
 
+       if (pm_domain && pm_domain->sync)
+               pm_domain->sync(dev);
+
        driver_bound(dev);
        ret = 1;
        pr_debug("bus: '%s': %s: bound device %s to driver %s\n",
@@ -319,6 +329,8 @@ probe_failed:
        driver_sysfs_remove(dev);
        dev->driver = NULL;
        dev_set_drvdata(dev, NULL);
+       if (pm_domain && pm_domain->sync)
+               pm_domain->sync(dev);
 
        if (ret == -EPROBE_DEFER) {
                /* Driver requested deferred probing */
@@ -522,9 +534,13 @@ static void __device_release_driver(stru
                        dev->bus->remove(dev);
                else if (drv->remove)
                        drv->remove(dev);
+
                devres_release_all(dev);
                dev->driver = NULL;
                dev_set_drvdata(dev, NULL);
+               if (dev->pm_domain && dev->pm_domain->sync)
+                       dev->pm_domain->sync(dev);
+
                klist_remove(&dev->p->knode_driver);
                if (dev->bus)
                        blocking_notifier_call_chain(&dev->bus->p->bus_notifier,
#33 lore raw

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

Quoted 23 lines · Ulf Hansson
Quoted 22 lines · Rafael J. Wysocki

From: Rafael J. Wysocki <[email protected]>
Subject: 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 and ->sync, called, respectively, before probing for a device driver and after the probing has been completed or the driver has been removed.

Quoted 5 lines
Quoted 1 line

This looks good to me!

I was a bit too quick acking this a minor fix is needed. See below.

Quoted 64 lines
Quoted 61 lines

---

Quoted 9 lines

---

This is an update without the additional bus type callbacks. This should be suffucient at this point for the use cases we have.

I've decided to also call ->sync on driver removal as that is consistent with what happens for failing probe.

---

One more update.

I've realized that in the PM domain's ->sync callback is called after clearing the device's driver field (in the failed probe or driver removal case) rather than before it, that could be used to distinguish between the two cases (successful probe vs no driver), so I reworked the patch accordingly.

---
 drivers/base/dd.c  |   16 ++++++++++++++++
 include/linux/pm.h |    6 ++++++
 2 files changed, 22 insertions(+)

Index: linux-pm/include/linux/pm.h
===================================================================

include/linux/pm.h +6 -0
@@ -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);
 };
 
 /*

Index: linux-pm/drivers/base/dd.c
===================================================================

drivers/base/dd.c +1 -0
@@ -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,6 +299,12 @@ static int really_probe(struct device *d
                goto probe_failed;
        }
 
Quoted 1 line

drivers/base/dd.c static int really_probe(struct device *d · line 302

Quoted 1 line
drivers/base/dd.c +1 -0
+       if (pm_domain && pm_domain->activate) {

You need to re-fetch the pm_domain pointer at this point, since it will be updated during ->probe().

Maybe it's just safer to always do the following check:

if (dev->pm_domain && dev->pm_domain->activate|sync)
...

Quoted 34 lines
Quoted 34 lines
drivers/base/dd.c +11 -0
+               ret = pm_domain->activate(dev);
+               if (ret)
+                       goto probe_failed;
+       }
+
        if (dev->bus->probe) {
                ret = dev->bus->probe(dev);
                if (ret)
@@ -308,6 +315,9 @@ static int really_probe(struct device *d
                        goto probe_failed;
        }
 
+       if (pm_domain && pm_domain->sync)
+               pm_domain->sync(dev);
+
        driver_bound(dev);
        ret = 1;
        pr_debug("bus: '%s': %s: bound device %s to driver %s\n",
@@ -319,6 +329,8 @@ probe_failed:
        driver_sysfs_remove(dev);
        dev->driver = NULL;
        dev_set_drvdata(dev, NULL);
+       if (pm_domain && pm_domain->sync)
+               pm_domain->sync(dev);
 
        if (ret == -EPROBE_DEFER) {
                /* Driver requested deferred probing */
@@ -522,9 +534,13 @@ static void __device_release_driver(stru
                        dev->bus->remove(dev);
                else if (drv->remove)
                        drv->remove(dev);
+
                devres_release_all(dev);
                dev->driver = NULL;
Quoted 8 lines

drivers/base/dd.c static void __device_release_driver(stru · line 546

Quoted 8 lines
drivers/base/dd.c +3 -0
                dev_set_drvdata(dev, NULL);
+               if (dev->pm_domain && dev->pm_domain->sync)
+                       dev->pm_domain->sync(dev);
+
                klist_remove(&dev->p->knode_driver);
                if (dev->bus)
                        blocking_notifier_call_chain(&dev->bus->p->bus_notifier,

Kind regards
Uffe

#34 lore raw

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

Quoted 96 lines · Ulf Hansson
Quoted 23 lines · Ulf Hansson
Quoted 22 lines · Rafael J. Wysocki

From: Rafael J. Wysocki <[email protected]>
Subject: 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 and ->sync, called, respectively, before probing for a device driver and after the probing has been completed or the driver has been removed.

Quoted 5 lines
Quoted 1 line

This looks good to me!

I was a bit too quick acking this a minor fix is needed. See below.

Quoted 61 lines
Quoted 61 lines

---

Quoted 9 lines

---

This is an update without the additional bus type callbacks. This should be suffucient at this point for the use cases we have.

I've decided to also call ->sync on driver removal as that is consistent with what happens for failing probe.

---

One more update.

I've realized that in the PM domain's ->sync callback is called after clearing the device's driver field (in the failed probe or driver removal case) rather than before it, that could be used to distinguish between the two cases (successful probe vs no driver), so I reworked the patch accordingly.

---
 drivers/base/dd.c  |   16 ++++++++++++++++
 include/linux/pm.h |    6 ++++++
 2 files changed, 22 insertions(+)

Index: linux-pm/include/linux/pm.h
===================================================================

include/linux/pm.h +6 -0
@@ -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);
 };
 
 /*

Index: linux-pm/drivers/base/dd.c
===================================================================

drivers/base/dd.c +1 -0
@@ -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,6 +299,12 @@ static int really_probe(struct device *d
                goto probe_failed;
        }
 
Quoted 4 lines
Quoted 1 line

drivers/base/dd.c static int really_probe(struct device *d · line 302

Quoted 1 line
drivers/base/dd.c +1 -0
+       if (pm_domain && pm_domain->activate) {

You need to re-fetch the pm_domain pointer at this point, since it will be updated during ->probe().

Right.

Quoted 3 lines

Maybe it's just safer to always do the following check:

if (dev->pm_domain && dev->pm_domain->activate|sync)

Yes, it is.

Well, overoptimization. I seem to always forget to avoid them. :-)

Will send a v3 with that fixed and the Dmitry's comment taken into account shortly.

Signature · 2 lines
I speak only for myself.
Rafael J. Wysocki, Intel Open Source Technology Center.
#36 lore raw

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

From: Rafael J. Wysocki <[email protected]>

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.

---

One more update taking Dmitry's comments into account and fixing an overoptimization bug spotted by Ulf.

And this actually contains the patch this time (clicked on "Send" too early last time, sorry about that).

---
 drivers/base/dd.c  |   14 ++++++++++++++
 include/linux/pm.h |    8 ++++++++
 2 files changed, 22 insertions(+)
include/linux/pm.h +8 -0
Index: linux-pm/include/linux/pm.h
===================================================================
@@ -603,10 +603,18 @@ 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 successful driver probe.
+ * @dismiss: Called after unsuccessful driver probe and after driver 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);
+	void (*dismiss)(struct device *dev);
 };
 
 /*
drivers/base/dd.c +14 -0
Index: linux-pm/drivers/base/dd.c
===================================================================
@@ -298,6 +298,12 @@ static int really_probe(struct device *d
 		goto probe_failed;
 	}
 
+	if (dev->pm_domain && dev->pm_domain->activate) {
+		ret = dev->pm_domain->activate(dev);
+		if (ret)
+			goto probe_failed;
+	}
+
 	if (dev->bus->probe) {
 		ret = dev->bus->probe(dev);
 		if (ret)
@@ -308,6 +314,9 @@ static int really_probe(struct device *d
 			goto probe_failed;
 	}
 
+	if (dev->pm_domain && dev->pm_domain->sync)
+		dev->pm_domain->sync(dev);
+
 	driver_bound(dev);
 	ret = 1;
 	pr_debug("bus: '%s': %s: bound device %s to driver %s\n",
@@ -319,6 +328,8 @@ probe_failed:
 	driver_sysfs_remove(dev);
 	dev->driver = NULL;
 	dev_set_drvdata(dev, NULL);
+	if (dev->pm_domain && dev->pm_domain->dismiss)
+		dev->pm_domain->dismiss(dev);
 
 	if (ret == -EPROBE_DEFER) {
 		/* Driver requested deferred probing */
@@ -525,6 +536,9 @@ static void __device_release_driver(stru
 		devres_release_all(dev);
 		dev->driver = NULL;
 		dev_set_drvdata(dev, NULL);
+		if (dev->pm_domain && dev->pm_domain->dismiss)
+			dev->pm_domain->dismiss(dev);
+
 		klist_remove(&dev->p->knode_driver);
 		if (dev->bus)
 			blocking_notifier_call_chain(&dev->bus->p->bus_notifier,
#37 lore raw

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

Quoted 16 lines · Rafael J. Wysocki

From: Rafael J. Wysocki <[email protected]>

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.

Quoted 6 lines

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.

Quoted 83 lines

---

One more update taking Dmitry's comments into account and fixing an overoptimization bug spotted by Ulf.

And this actually contains the patch this time (clicked on "Send" too early last time, sorry about that).

---
 drivers/base/dd.c  |   14 ++++++++++++++
 include/linux/pm.h |    8 ++++++++
 2 files changed, 22 insertions(+)

Index: linux-pm/include/linux/pm.h
===================================================================

include/linux/pm.h +8 -0
@@ -603,10 +603,18 @@ 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 successful driver probe.
+ * @dismiss: Called after unsuccessful driver probe and after driver 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);
+       void (*dismiss)(struct device *dev);
 };
 
 /*

Index: linux-pm/drivers/base/dd.c
===================================================================

drivers/base/dd.c +14 -0
@@ -298,6 +298,12 @@ static int really_probe(struct device *d
                goto probe_failed;
        }
 
+       if (dev->pm_domain && dev->pm_domain->activate) {
+               ret = dev->pm_domain->activate(dev);
+               if (ret)
+                       goto probe_failed;
+       }
+
        if (dev->bus->probe) {
                ret = dev->bus->probe(dev);
                if (ret)
@@ -308,6 +314,9 @@ static int really_probe(struct device *d
                        goto probe_failed;
        }
 
+       if (dev->pm_domain && dev->pm_domain->sync)
+               dev->pm_domain->sync(dev);
+
        driver_bound(dev);
        ret = 1;
        pr_debug("bus: '%s': %s: bound device %s to driver %s\n",
@@ -319,6 +328,8 @@ probe_failed:
        driver_sysfs_remove(dev);
        dev->driver = NULL;
        dev_set_drvdata(dev, NULL);
+       if (dev->pm_domain && dev->pm_domain->dismiss)
+               dev->pm_domain->dismiss(dev);
 
        if (ret == -EPROBE_DEFER) {
                /* Driver requested deferred probing */
@@ -525,6 +536,9 @@ static void __device_release_driver(stru
                devres_release_all(dev);
                dev->driver = NULL;
                dev_set_drvdata(dev, NULL);
+               if (dev->pm_domain && dev->pm_domain->dismiss)
+                       dev->pm_domain->dismiss(dev);
+
                klist_remove(&dev->p->knode_driver);
                if (dev->bus)
                        blocking_notifier_call_chain(&dev->bus->p->bus_notifier,
#38 lore raw

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

In reply to Rafael J. Wysocki
Quoted 21 lines · Rafael J. Wysocki

From: Rafael J. Wysocki <[email protected]>

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.

Quoted 8 lines

---

One more update taking Dmitry's comments into account and fixing an overoptimization bug spotted by Ulf.

And this actually contains the patch this time (clicked on "Send" too early last time, sorry about that).

Unless I'm missing somthing, this along with the just the genpd part of Russell's patch should then fix his problem as well.

Kevin

#39 lore raw

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

In reply to Rafael J. Wysocki
Quoted 21 lines · Rafael J. Wysocki

From: Rafael J. Wysocki <[email protected]>

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.

Quoted 8 lines

---

One more update taking Dmitry's comments into account and fixing an overoptimization bug spotted by Ulf.

And this actually contains the patch this time (clicked on "Send" too early last time, sorry about that).

Hi Greg,

Since everybody seems to like this one, do you have any objectctions against it?

If not, would it be a problem if I queued it up for 4.1?

Rafael

Quoted 79 lines
---
 drivers/base/dd.c  |   14 ++++++++++++++
 include/linux/pm.h |    8 ++++++++
 2 files changed, 22 insertions(+)

Index: linux-pm/include/linux/pm.h
===================================================================

include/linux/pm.h +8 -0
@@ -603,10 +603,18 @@ 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 successful driver probe.
+ * @dismiss: Called after unsuccessful driver probe and after driver 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);
+	void (*dismiss)(struct device *dev);
 };
 
 /*

Index: linux-pm/drivers/base/dd.c
===================================================================

drivers/base/dd.c +14 -1
@@ -298,6 +298,12 @@ static int really_probe(struct device *d
 		goto probe_failed;
 	}
 
+	if (dev->pm_domain && dev->pm_domain->activate) {
+		ret = dev->pm_domain->activate(dev);
+		if (ret)
+			goto probe_failed;
+	}
+
 	if (dev->bus->probe) {
 		ret = dev->bus->probe(dev);
 		if (ret)
@@ -308,6 +314,9 @@ static int really_probe(struct device *d
 			goto probe_failed;
 	}
 
+	if (dev->pm_domain && dev->pm_domain->sync)
+		dev->pm_domain->sync(dev);
+
 	driver_bound(dev);
 	ret = 1;
 	pr_debug("bus: '%s': %s: bound device %s to driver %s\n",
@@ -319,6 +328,8 @@ probe_failed:
 	driver_sysfs_remove(dev);
 	dev->driver = NULL;
 	dev_set_drvdata(dev, NULL);
+	if (dev->pm_domain && dev->pm_domain->dismiss)
+		dev->pm_domain->dismiss(dev);
 
 	if (ret == -EPROBE_DEFER) {
 		/* Driver requested deferred probing */
@@ -525,6 +536,9 @@ static void __device_release_driver(stru
 		devres_release_all(dev);
 		dev->driver = NULL;
 		dev_set_drvdata(dev, NULL);
+		if (dev->pm_domain && dev->pm_domain->dismiss)
+			dev->pm_domain->dismiss(dev);
+
 		klist_remove(&dev->p->knode_driver);
 		if (dev->bus)
 			blocking_notifier_call_chain(&dev->bus->p->bus_notifier,
 
--

To unsubscribe from this list: send the line "unsubscribe linux-pm" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html

Signature · 2 lines
I speak only for myself.
Rafael J. Wysocki, Intel Open Source Technology Center.
#40 lore raw

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

Quoted 28 lines · Rafael J. Wysocki
Quoted 27 lines · Rafael J. Wysocki

From: Rafael J. Wysocki <[email protected]>

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.

---

One more update taking Dmitry's comments into account and fixing an overoptimization bug spotted by Ulf.

Quoted 8 lines
Quoted 2 lines

And this actually contains the patch this time (clicked on "Send" too early last time, sorry about that).

Hi Greg,

Since everybody seems to like this one, do you have any objectctions against it?

If not, would it be a problem if I queued it up for 4.1?

No problem, nice cleanup:

#41 lore raw

PATCH 1/1 driver core / PM: Add callbacks for PM domain initialization/cleanup

In reply to Alan Stern
Quoted 9 lines · Alan Stern
Quoted 5 lines

There are two alternatives to them. One is to do PM domain attach/detach in the bus type's ->probe and ->remove, but that's suboptimal, because it is then carried out every time a driver is probed/removed for a device. The other one would be to have each interested bus type register a bus type notifier for itself, but that would be rather ugly, wouldn't it?

Driver probing and removal is not a hot path. Successful probes usually occur only once for each device. I don't know how many unsuccessful probes there are on average, but probably not many.

Do not underestimate the power of deferred probing:

sh_mobile_sdhi ee100000.sd: GPIO lookup for consumer cd sh_mobile_sdhi ee100000.sd: using device tree for GPIO lookup
of_get_named_gpiod_flags: parsed 'cd-gpios' property of node '/sd at ee100000[0]' - status (0)
sh_mobile_sdhi ee100000.sd: Got CD GPIO
sh_mobile_sdhi ee100000.sd: GPIO lookup for consumer wp sh_mobile_sdhi ee100000.sd: using device tree for GPIO lookup
of_get_named_gpiod_flags: parsed 'wp-gpios' property of node '/sd at ee100000[0]' - status (0)
sh_mobile_sdhi ee100000.sd: Got WP GPIO
platform ee100000.sd: Driver sh_mobile_sdhi requests probe deferral
...
sh_mobile_sdhi ee100000.sd: GPIO lookup for consumer cd sh_mobile_sdhi ee100000.sd: using device tree for GPIO lookup
of_get_named_gpiod_flags: parsed 'cd-gpios' property of node '/sd at ee100000[0]' - status (0)
sh_mobile_sdhi ee100000.sd: Got CD GPIO
sh_mobile_sdhi ee100000.sd: GPIO lookup for consumer wp sh_mobile_sdhi ee100000.sd: using device tree for GPIO lookup
of_get_named_gpiod_flags: parsed 'wp-gpios' property of node '/sd at ee100000[0]' - status (0)
sh_mobile_sdhi ee100000.sd: Got WP GPIO
gpio_rcar e6055400.gpio: sense irq = 6, type = 3 sh_mobile_sdhi ee100000.sd: mmc0 base at 0xee100000 clock rate 97 MHz

Gr{oetje,eeting}s,

Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert at linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But when I'm talking to journalists I just say "programmer" or something like that.
-- Linus Torvalds

#42 lore raw

PATCH 1/9 PM / Domains: Add dev_pm_domain_get|put() APIs

In reply to Ulf Hansson
Quoted 209 lines · Ulf Hansson
Quoted 208 lines · Rafael J. Wysocki
Quoted 207 lines · Ulf Hansson
Quoted 205 lines · Rafael J. Wysocki
Quoted 186 lines · Ulf Hansson
Quoted 114 lines · Rafael J. Wysocki
Quoted 104 lines · Ulf Hansson
Quoted 82 lines · Rafael J. Wysocki
Quoted 81 lines · Ulf Hansson

There may be more than one device in a PM domain which then will be probed at different points in time.

Depending on timing and runtime PM support, in for the device related driver/subsystem, a PM domain may be advised to power off after a successful probe sequence.

A general requirement for a device within a PM domain, is that the PM domain must stay powered during the probe sequence. To cope with such requirement, let's add the dev_pm_domain_get|put() APIs.

These APIs are intended to be invoked from subsystem-level code and the calls between get/put needs to be balanced.

dev_pm_domain_get(), tells the PM domain that it needs to increase a usage count and to keep supplying power. dev_pm_domain_put(), does the opposite.

For a PM domain to support this feature, it must implement the optional ->get|put() callbacks.

---
 drivers/base/power/common.c | 40 ++++++++++++++++++++++++++++++++++++++++
 include/linux/pm.h          |  2 ++
 include/linux/pm_domain.h   |  4 ++++
 3 files changed, 46 insertions(+)
drivers/base/power/common.c +40 -0
index f32b802..99225af 100644
@@ -128,3 +128,43 @@ void dev_pm_domain_detach(struct device *dev, bool power_off)
              dev->pm_domain->detach(dev, power_off);
 }
 EXPORT_SYMBOL_GPL(dev_pm_domain_detach);
+
+/**
+ * dev_pm_domain_get - Increase usage count to keep a PM domain powered.
+ * @domain: The PM domain to operate on.
+ *
+ * This function will not by itself increase the usage count, that's up to each
+ * PM domain implementation to support. Typically it should be invoked from
+ * subsystem level code prior drivers starts probing.
+ *
+ * Do note, it's optional to implement the ->get() callback for a PM domain.
+ *
+ * Returns 0 on successfully increased usage count or negative error code.
+ */
+int dev_pm_domain_get(struct dev_pm_domain *domain)
+{
+     int ret = 0;
+
+     if (domain && domain->get)
+             ret = domain->get(domain);
+
+     return ret;
+}
+EXPORT_SYMBOL_GPL(dev_pm_domain_get);
+
+/**
+ * dev_pm_domain_put - Decrease usage count to allow a PM domain to power off.
+ * @domain: The PM domain to operate on.
+ *
+ * This function will not by itself decrease the usage count, that's up to each
+ * PM domain implementation to support. Typically it should be invoked from
+ * subsystem level code after drivers has finished probing.
+ *
+ * Do note, it's optional to implement the ->put() callback for a PM domain.
+ */
+void dev_pm_domain_put(struct dev_pm_domain *domain)
+{
+     if (domain && domain->put)
+             domain->put(domain);
+}
+EXPORT_SYMBOL_GPL(dev_pm_domain_put);
include/linux/pm.h +0 -0
index e2f1be6..e62330b 100644
@@ -607,6 +607,8 @@ extern void dev_pm_put_subsys_data(struct device *dev);
Quoted 8 lines

include/linux/pm.h extern void dev_pm_put_subsys_data(struc

Quoted 5 lines
include/linux/pm.h +2 -0
 struct dev_pm_domain {
      struct dev_pm_ops       ops;
      void (*detach)(struct device *dev, bool power_off);
+     int (*get)(struct dev_pm_domain *domain);
+     void (*put)(struct dev_pm_domain *domain);

I don't like these names. They suggest that it's always going to be about reference counting which doesn't have to be the case in principle.

I am happy to change, you don't happen to have a proposal? :-)

For genpd we already have these related APIs:

pm_genpd_poweron()
pm_genpd_name_poweron()
pm_genpd_poweroff_unused()

Theoretically we should be able to replace these with dev_pm_domain_get|put() or whatever we decide to name them to.

Quoted 1 line
Quoted 8 lines
Quoted 1 line

Also what about calling these from the driver core, ie. really_probe()?

I like that!

That also implies moving the calls to dev_pm_domain_attach|detach() out of the buses and into the drivercore, since we need the PM domain to be attached before calling dev_pm_domain_get|put(). I assume that's what you also propose me to change, right?

Quoted 7 lines

Not really. I don't want to inflict the ACPI PM domain on every bus type that may not be prepared for using it or even may not want to use it (like PCI or PNP). That applies to genpd too to some extent.

So bus types need to be able to opt in for using "default" PM domains, but at the same time if they do, the core is a better place to invoke the callbacks.

Okay!

Quoted 7 lines

The patch below shows how that can be done. For the bus types using genpd or the ACPI PM domain today ->pm_domain_init and ->pm_domain_exit may point to the routines initializing/detaching those (which also will help to reduce code duplication somewhat) and that guarantees that the domains will be attached to devices before probing and the core can do the ->pre_probe and ->post_probe things for everybody.

Overall, this seem like a very good idea!

Quoted 33 lines

Rafael

---
 drivers/base/bus.c     |   12 +++++++++++-
 drivers/base/dd.c      |    9 +++++++++
 include/linux/device.h |    3 +++
 include/linux/pm.h     |    2 ++
 4 files changed, 25 insertions(+), 1 deletion(-)

Index: linux-pm/drivers/base/bus.c
===================================================================

drivers/base/bus.c +6 -1
@@ -509,10 +509,15 @@ int bus_add_device(struct device *dev)
        int error = 0;
 
        if (bus) {
+               if (bus->pm_domain_init) {
+                       error = bus->pm_domain_init(dev);
+                       if (error)
+                               goto out_put;
+               }
                pr_debug("bus: '%s': add device %s\n", bus->name, dev_name(dev));
                error = device_add_attrs(bus, dev);
                if (error)
-                       goto out_put;
+                       goto out_pm_domain;
                error = device_add_groups(dev, bus->dev_groups);
                if (error)
                        goto out_groups;

drivers/base/bus.c out_groups: · line 547

Quoted 9 lines
drivers/base/bus.c +3 -0
@@ -534,6 +539,9 @@ out_groups:
        device_remove_groups(dev, bus->dev_groups);
 out_id:
        device_remove_attrs(bus, dev);
+out_pm_domain:
+       if (bus->pm_domain_exit)
+               bus->pm_domain_exit(dev);
 out_put:
        bus_put(dev->bus);
        return error;

To make this work for bus_add_device(), we first need to change the registration procedure for genpd DT providers. Currently that's done when "PM domain drivers" invokes the __of_genpd_add_provider() API, from SoC specific code and from different init levels.

We need to have the available gendp DT providers registered when the ->pm_domain_init() callback is invoked.

Quoted 7 lines

Besides the changes above, genpd also needs to deal with attached devices, but which don't have a corresponding driver bound. I believe we have some corner cases to fix around this as well.

As an intermediate step, how about adding the similar code as above but into really_probe()? For the code in bus_remove_device() below, we could add that into __device_release_driver()?

Well, I wouldn't really like to add new callbacks to struct bus_type for intermediate steps, because that's guaranteed to lead to confusion.

So I think the infrastructure is better added first and users may be switched over to it gradually.

I don't see any particular problems with moving the ACPI PM domain attach/detach to bus_add/remove_device(), so that can be done as the first step. As for genpd, it can implement the ->post_probe thing first and do the rest in the bus type ->probe until the generic code is ready.

Quoted 8 lines
Quoted 6 lines
Quoted 3 lines

Yes, that works.

I will cook a new version of the patchset according to your suggestions.

I'll send a cleaner version of my patch tomorrow (I actually would like to use different names for the new callbacks).

Okay, great!

OK, sent this one (https://patchwork.kernel.org/patch/6040241/).

Quoted 4 lines
Quoted 1 line

Also I can do the ACPI part of the work, please let me know if you want me to.

Appreciate your help! I wouldn't mind giving this a quick try. If I am way off, just nack the patches and then please help out implement it.

OK

Signature · 2 lines
I speak only for myself.
Rafael J. Wysocki, Intel Open Source Technology Center.
#43 lore raw

PATCH 2/9 PM / Domains: Enable genpd to support ->get|put() callbacks

In reply to Ulf Hansson

To provide users control over whether the power should be maintained, implement the ->get|put() callbacks for genpd's PM domain.

A usage count variable keeps track of the number of users. A positive value tells genpd to keep supplying power and also to power up if it's the first user.

Once the usage count reaches zero, genpd tries to power off its PM domain.

---
 drivers/base/power/domain.c | 26 +++++++++++++++++++++++++-
 include/linux/pm_domain.h   |  1 +
 2 files changed, 26 insertions(+), 1 deletion(-)
drivers/base/power/domain.c +25 -1
index 45937f8..7314459 100644
@@ -495,10 +495,12 @@ static int pm_genpd_poweroff(struct generic_pm_domain *genpd)
 	 * (2) The domain is waiting for its master to power up.
 	 * (3) One of the domain's devices is being resumed right now.
 	 * (4) System suspend is in progress.
+	 * (5) The usage_count > 0, since it tells us to stay powered.
 	 */
 	if (genpd->status == GPD_STATE_POWER_OFF
 	    || genpd->status == GPD_STATE_WAIT_MASTER
-	    || genpd->resume_count > 0 || genpd->prepared_count > 0)
+	    || genpd->resume_count > 0 || genpd->prepared_count > 0
+	    || atomic_read(&genpd->usage_count) > 0)
 		return 0;
 
 	if (atomic_read(&genpd->sd_count) > 0)
@@ -1377,6 +1379,25 @@ EXPORT_SYMBOL_GPL(pm_genpd_syscore_poweron);
 
 #endif /* CONFIG_PM_SLEEP */
 
+static int genpd_get(struct dev_pm_domain *domain)
+{
+	struct generic_pm_domain *genpd = pd_to_genpd(domain);
+
+	atomic_inc(&genpd->usage_count);
+
+	return pm_genpd_poweron(genpd);
+}
+
+static void genpd_put(struct dev_pm_domain *domain)
+{
+	struct generic_pm_domain *genpd = pd_to_genpd(domain);
+
+	if (!atomic_dec_and_test(&genpd->usage_count))
+		return;
+
+	genpd_queue_power_off_work(genpd);
+}
+
 static struct generic_pm_domain_data *genpd_alloc_dev_data(struct device *dev,
 					struct generic_pm_domain *genpd,
 					struct gpd_timing_data *td)
@@ -1874,10 +1895,13 @@ void pm_genpd_init(struct generic_pm_domain *genpd,
 	genpd->status = is_off ? GPD_STATE_POWER_OFF : GPD_STATE_ACTIVE;
 	init_waitqueue_head(&genpd->status_wait_queue);
 	genpd->poweroff_task = NULL;
+	atomic_set(&genpd->usage_count, 0);
 	genpd->resume_count = 0;
 	genpd->device_count = 0;
 	genpd->max_off_time_ns = -1;
 	genpd->max_off_time_changed = true;
+	genpd->domain.get = genpd_get;
+	genpd->domain.put = genpd_put;
 	genpd->domain.ops.runtime_suspend = pm_genpd_runtime_suspend;
 	genpd->domain.ops.runtime_resume = pm_genpd_runtime_resume;
 	genpd->domain.ops.prepare = pm_genpd_prepare;
include/linux/pm_domain.h +1 -0
index c80d6ac..698ecbe 100644
@@ -61,6 +61,7 @@ struct generic_pm_domain {
 	enum gpd_status status;	/* Current state of the domain */
 	wait_queue_head_t status_wait_queue;
 	struct task_struct *poweroff_task;	/* Powering off task */
+	atomic_t usage_count;		/* Number of users of the domain */
 	unsigned int resume_count;	/* Number of devices being resumed */
 	unsigned int device_count;	/* Number of devices */
 	unsigned int suspended_count;	/* System suspend device counter */
Signature · 1 line
1.9.1
#44 lore raw

PATCH 2/9 PM / Domains: Enable genpd to support ->get|put() callbacks

Quoted 61 lines · Ulf Hansson

To provide users control over whether the power should be maintained, implement the ->get|put() callbacks for genpd's PM domain.

A usage count variable keeps track of the number of users. A positive value tells genpd to keep supplying power and also to power up if it's the first user.

Once the usage count reaches zero, genpd tries to power off its PM domain.

---
drivers/base/power/domain.c | 26 +++++++++++++++++++++++++-
include/linux/pm_domain.h | 1 +

2 files changed, 26 insertions(+), 1 deletion(-)
drivers/base/power/domain.c +22 -1
index 45937f8..7314459 100644
@@ -495,10 +495,12 @@ static int pm_genpd_poweroff(struct generic_pm_domain *genpd)
 	 * (2) The domain is waiting for its master to power up.
 	 * (3) One of the domain's devices is being resumed right now.
 	 * (4) System suspend is in progress.
+	 * (5) The usage_count > 0, since it tells us to stay powered.
 	 */
 	if (genpd->status == GPD_STATE_POWER_OFF
 	    || genpd->status == GPD_STATE_WAIT_MASTER
-	    || genpd->resume_count > 0 || genpd->prepared_count > 0)
+	    || genpd->resume_count > 0 || genpd->prepared_count > 0
+	    || atomic_read(&genpd->usage_count) > 0)
 		return 0;
 
 	if (atomic_read(&genpd->sd_count) > 0)
@@ -1377,6 +1379,25 @@ EXPORT_SYMBOL_GPL(pm_genpd_syscore_poweron);
 
 #endif /* CONFIG_PM_SLEEP */
 
+static int genpd_get(struct dev_pm_domain *domain)
+{
+	struct generic_pm_domain *genpd = pd_to_genpd(domain);
+
+	atomic_inc(&genpd->usage_count);
+
+	return pm_genpd_poweron(genpd);
+}
+
+static void genpd_put(struct dev_pm_domain *domain)
+{
+	struct generic_pm_domain *genpd = pd_to_genpd(domain);
+
+	if (!atomic_dec_and_test(&genpd->usage_count))
+		return;
+
+	genpd_queue_power_off_work(genpd);
+}
+
 static struct generic_pm_domain_data *genpd_alloc_dev_data(struct device *dev,
 					struct generic_pm_domain *genpd,
 					struct gpd_timing_data *td)

drivers/base/power/domain.c void pm_genpd_init(struct generic_pm_domain *genpd, · line 1904

Quoted 10 lines
drivers/base/power/domain.c +3 -0
@@ -1874,10 +1895,13 @@ void pm_genpd_init(struct generic_pm_domain *genpd,
 	genpd->status = is_off ? GPD_STATE_POWER_OFF : GPD_STATE_ACTIVE;
 	init_waitqueue_head(&genpd->status_wait_queue);
 	genpd->poweroff_task = NULL;
+	atomic_set(&genpd->usage_count, 0);
 	genpd->resume_count = 0;
 	genpd->device_count = 0;
 	genpd->max_off_time_ns = -1;
 	genpd->max_off_time_changed = true;
+	genpd->domain.get = genpd_get;
+	genpd->domain.put = genpd_put;

What is the difference that call pm_runtime_get/put when probe device?
When the device is attached to the power domain.
We can still use pm_runtime_get/put to power on/shutdown the power domain and make the device probed correctly with power domain on.

Quoted 8 lines
Signature · 7 lines
1.9.1


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel at lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
#45 lore raw

PATCH 3/9 amba: Keep PM domain powered during ->probe()

In reply to Ulf Hansson

To sucessfully probe some devices their corresponding PM domains may need to be powered.

Use the dev_pm_domain_get|put() APIs, to control the behavior of the PM domain.

---
 drivers/amba/bus.c | 8 ++++++++
 1 file changed, 8 insertions(+)
drivers/amba/bus.c +8 -0
index f009936..19182b0 100644
@@ -241,8 +241,15 @@ static int amba_probe(struct device *dev)
 		if (ret == -EPROBE_DEFER)
 			break;
 
+		ret = dev_pm_domain_get(dev->pm_domain);
+		if (ret) {
+			dev_pm_domain_detach(dev, true);
+			break;
+		}
+
 		ret = amba_get_enable_pclk(pcdev);
 		if (ret) {
+			dev_pm_domain_put(dev->pm_domain);
 			dev_pm_domain_detach(dev, true);
 			break;
 		}
@@ -252,6 +259,7 @@ static int amba_probe(struct device *dev)
 		pm_runtime_enable(dev);
 
 		ret = pcdrv->probe(pcdev, id);
+		dev_pm_domain_put(dev->pm_domain);
 		if (ret == 0)
 			break;
 
Signature · 1 line
1.9.1
#46 lore raw

PATCH 3/9 amba: Keep PM domain powered during ->probe()

Quoted 5 lines · Ulf Hansson

To sucessfully probe some devices their corresponding PM domains may need to be powered.

Use the dev_pm_domain_get|put() APIs, to control the behavior of the PM domain.

Given that AMBA gets the runtime PM status across a probe, none of this should be necessary, as generic PM domains ensures that if runtime PM is active for any device bound to the PM domain, the PM domain will be powered up.

In that respect, AMBA is a model of how runtime PM should've been done for stuff like platform devices. :)

Signature · 2 lines
FTTC broadband for 0.8mile line: currently at 10.5Mbps down 400kbps up
according to speedtest.net.
#47 lore raw

PATCH 3/9 amba: Keep PM domain powered during ->probe()

Quoted 11 lines · Russell King - ARM Linux
Quoted 5 lines · Ulf Hansson

To sucessfully probe some devices their corresponding PM domains may need to be powered.

Use the dev_pm_domain_get|put() APIs, to control the behavior of the PM domain.

Given that AMBA gets the runtime PM status across a probe, none of this should be necessary, as generic PM domains ensures that if runtime PM is active for any device bound to the PM domain, the PM domain will be powered up.

This patch is needed to enable us to do the revert in patch 9. Since otherwise amba drivers will probe their devices when the attached PM domain may be powered off.

That should have been better explained in the commit message.

Kind regards
Uffe

Quoted 7 lines

In that respect, AMBA is a model of how runtime PM should've been done for stuff like platform devices. :)

--
FTTC broadband for 0.8mile line: currently at 10.5Mbps down 400kbps up according to speedtest.net.

#48 lore raw

PATCH 4/9 drivercore / platform: Keep PM domain powered during ->probe()

In reply to Ulf Hansson

To sucessfully probe some devices their corresponding PM domains may need to be powered.

Use the dev_pm_domain_get|put() APIs, to control the behavior of the PM domain.

---
 drivers/base/platform.c | 7 +++++++
 1 file changed, 7 insertions(+)
drivers/base/platform.c +7 -0
index 9421fed..d35fef1 100644
@@ -509,7 +509,14 @@ static int platform_drv_probe(struct device *_dev)
 
 	ret = dev_pm_domain_attach(_dev, true);
 	if (ret != -EPROBE_DEFER) {
+		ret = dev_pm_domain_get(_dev->pm_domain);
+		if (ret) {
+			dev_pm_domain_detach(_dev, true);
+			return ret;
+		}
+
 		ret = drv->probe(dev);
+		dev_pm_domain_put(_dev->pm_domain);
 		if (ret)
 			dev_pm_domain_detach(_dev, true);
 	}
Signature · 1 line
1.9.1
#49 lore raw

PATCH 5/9 i2c: core: Keep PM domain powered during ->probe()

In reply to Ulf Hansson

To sucessfully probe some devices their corresponding PM domains may need to be powered.

Use the dev_pm_domain_get|put() APIs, to control the behavior of the PM domain.

---
 drivers/i2c/i2c-core.c | 7 +++++++
 1 file changed, 7 insertions(+)
drivers/i2c/i2c-core.c +7 -0
index 210cf48..0eabe55 100644
@@ -655,8 +655,15 @@ static int i2c_device_probe(struct device *dev)
 
 	status = dev_pm_domain_attach(&client->dev, true);
 	if (status != -EPROBE_DEFER) {
+		status = dev_pm_domain_get(client->dev.pm_domain);
+		if (status) {
+			dev_pm_domain_detach(&client->dev, true);
+			return status;
+		}
+
 		status = driver->probe(client, i2c_match_id(driver->id_table,
 					client));
+		dev_pm_domain_put(client->dev.pm_domain);
 		if (status)
 			dev_pm_domain_detach(&client->dev, true);
 	}
Signature · 1 line
1.9.1
#50 lore raw

PATCH 6/9 spi: core: Keep PM domain powered during ->probe()

In reply to Ulf Hansson

To sucessfully probe some devices their corresponding PM domains may need to be powered.

Use the dev_pm_domain_get|put() APIs, to control the behavior of the PM domain.

---
 drivers/spi/spi.c | 7 +++++++
 1 file changed, 7 insertions(+)
drivers/spi/spi.c +7 -0
index c64a3e5..bb75a0f 100644
@@ -263,7 +263,14 @@ static int spi_drv_probe(struct device *dev)
 
 	ret = dev_pm_domain_attach(dev, true);
 	if (ret != -EPROBE_DEFER) {
+		ret = dev_pm_domain_get(dev->pm_domain);
+		if (ret) {
+			dev_pm_domain_detach(dev, true);
+			return ret;
+		}
+
 		ret = sdrv->probe(to_spi_device(dev));
+		dev_pm_domain_put(dev->pm_domain);
 		if (ret)
 			dev_pm_domain_detach(dev, true);
 	}
Signature · 1 line
1.9.1
#51 lore raw

PATCH 7/9 mmc: core: Attach PM domain prior probing of SDIO func driver

In reply to Ulf Hansson

Align the behvaior to how other buses are handling attachment of PM domains. Additionally, let's add error handling.

---

For reference, this change has been discussed before.
http://lists.infradead.org/pipermail/linux-arm-kernel/2014-October/294278.html

---
 drivers/mmc/core/sdio_bus.c | 14 ++++++++++----
 1 file changed, 10 insertions(+), 4 deletions(-)
drivers/mmc/core/sdio_bus.c +10 -4
index bee02e6..71357b8 100644
@@ -315,13 +315,19 @@ int sdio_add_func(struct sdio_func *func)
 
 	sdio_set_of_node(func);
 	sdio_acpi_set_handle(func);
+
+	ret = dev_pm_domain_attach(&func->dev, false);
+	if (ret)
+		return ret;
+
 	ret = device_add(&func->dev);
-	if (ret == 0) {
-		sdio_func_set_present(func);
-		dev_pm_domain_attach(&func->dev, false);
+	if (ret) {
+		dev_pm_domain_detach(&func->dev, false);
+		return ret;
 	}
 
-	return ret;
+	sdio_func_set_present(func);
+	return 0;
 }
 
 /*
Signature · 1 line
1.9.1
#52 lore raw

PATCH 7/9 mmc: core: Attach PM domain prior probing of SDIO func driver

Quoted 5 lines · Ulf Hansson

Align the behvaior to how other buses are handling attachment of PM domains. Additionally, let's add error handling.

Quoted 38 lines

---

For reference, this change has been discussed before.
http://lists.infradead.org/pipermail/linux-arm-kernel/2014-October/294278.html

---
 drivers/mmc/core/sdio_bus.c | 14 ++++++++++----
 1 file changed, 10 insertions(+), 4 deletions(-)
drivers/mmc/core/sdio_bus.c +10 -4
index bee02e6..71357b8 100644
@@ -315,13 +315,19 @@ int sdio_add_func(struct sdio_func *func)
 
 	sdio_set_of_node(func);
 	sdio_acpi_set_handle(func);
+
+	ret = dev_pm_domain_attach(&func->dev, false);
+	if (ret)
+		return ret;
+
 	ret = device_add(&func->dev);
-	if (ret == 0) {
-		sdio_func_set_present(func);
-		dev_pm_domain_attach(&func->dev, false);
+	if (ret) {
+		dev_pm_domain_detach(&func->dev, false);
+		return ret;
 	}
 
-	return ret;
+	sdio_func_set_present(func);
+	return 0;
 }
 
 /*
#53 lore raw

PATCH 8/9 mmmc: core: Keep PM domain powered during ->probe() of SDIO func driver

In reply to Ulf Hansson

To sucessfully probe some devices their corresponding PM domains may need to be powered.

Use the dev_pm_domain_get|put() APIs, to control the behavior of the PM domain.

---
 drivers/mmc/core/sdio_bus.c | 7 +++++++
 1 file changed, 7 insertions(+)
drivers/mmc/core/sdio_bus.c +7 -0
index 71357b8..0d89b4b 100644
@@ -320,7 +320,14 @@ int sdio_add_func(struct sdio_func *func)
 	if (ret)
 		return ret;
 
+	ret = dev_pm_domain_get(func->dev.pm_domain);
+	if (ret) {
+		dev_pm_domain_detach(&func->dev, false);
+		return ret;
+	}
+
 	ret = device_add(&func->dev);
+	dev_pm_domain_put(func->dev.pm_domain);
 	if (ret) {
 		dev_pm_domain_detach(&func->dev, false);
 		return ret;
Signature · 1 line
1.9.1
#54 lore raw

PATCH 8/9 mmmc: core: Keep PM domain powered during ->probe() of SDIO func driver

Quoted 17 lines · Ulf Hansson

To sucessfully probe some devices their corresponding PM domains may need to be powered.

Use the dev_pm_domain_get|put() APIs, to control the behavior of the PM domain.

---
 drivers/mmc/core/sdio_bus.c | 7 +++++++
 1 file changed, 7 insertions(+)
drivers/mmc/core/sdio_bus.c +0 -0
index 71357b8..0d89b4b 100644
@@ -320,7 +320,14 @@ int sdio_add_func(struct sdio_func *func)
 	if (ret)

drivers/mmc/core/sdio_bus.c int sdio_add_func(struct sdio_func *func) · line 330

Quoted 10 lines
drivers/mmc/core/sdio_bus.c +7 -0
 		return ret;
 
+	ret = dev_pm_domain_get(func->dev.pm_domain);
+	if (ret) {
+		dev_pm_domain_detach(&func->dev, false);
+		return ret;
+	}
+
 	ret = device_add(&func->dev);
+	dev_pm_domain_put(func->dev.pm_domain);

This is broken. It assumes that the device will be probed in device_add(). That's not always the case. Come on Ulf, I'm dismayed at you producing bad and fragile patches like this. You are the apparent maintainer for several important subsystems, and you are putting yourself up for more, yet you don't seem to know the basics about the kernel infrastructure. That makes you dangerous.

Look, device_add() adds the device to the list of available devices, publishes it in sysfs, triggers a uevent, and tries to find a driver to bind it to.

If it doesn't find a driver already registered in the kernel, that could be because the required driver is a module. In that case, device_add() will already have returned.

At some point later, the module will be loaded by user space, and that will cause the list of devices to be scanned, looking for devices which the newly registered driver can bind to. With your code above, these will _not_ result in the PM domain being "got" before probing.

Signature · 2 lines
FTTC broadband for 0.8mile line: currently at 10.5Mbps down 400kbps up
according to speedtest.net.
#55 lore raw

PATCH 8/9 mmmc: core: Keep PM domain powered during ->probe() of SDIO func driver

Quoted 40 lines · Russell King - ARM Linux
Quoted 17 lines · Ulf Hansson

To sucessfully probe some devices their corresponding PM domains may need to be powered.

Use the dev_pm_domain_get|put() APIs, to control the behavior of the PM domain.

---
 drivers/mmc/core/sdio_bus.c | 7 +++++++
 1 file changed, 7 insertions(+)
drivers/mmc/core/sdio_bus.c +0 -0
index 71357b8..0d89b4b 100644
@@ -320,7 +320,14 @@ int sdio_add_func(struct sdio_func *func)
      if (ret)

drivers/mmc/core/sdio_bus.c int sdio_add_func(struct sdio_func *func) · line 330

Quoted 10 lines
drivers/mmc/core/sdio_bus.c +7 -0
              return ret;
 
+     ret = dev_pm_domain_get(func->dev.pm_domain);
+     if (ret) {
+             dev_pm_domain_detach(&func->dev, false);
+             return ret;
+     }
+
      ret = device_add(&func->dev);
+     dev_pm_domain_put(func->dev.pm_domain);

This is broken. It assumes that the device will be probed in device_add(). That's not always the case. Come on Ulf, I'm dismayed at you producing bad and fragile patches like this. You are the apparent maintainer for several important subsystems, and you are putting yourself up for more, yet you don't seem to know the basics about the kernel infrastructure. That makes you dangerous.

Look, device_add() adds the device to the list of available devices, publishes it in sysfs, triggers a uevent, and tries to find a driver to bind it to.

Quoted 9 lines

If it doesn't find a driver already registered in the kernel, that could be because the required driver is a module. In that case, device_add() will already have returned.

At some point later, the module will be loaded by user space, and that will cause the list of devices to be scanned, looking for devices which the newly registered driver can bind to. With your code above, these will _not_ result in the PM domain being "got" before probing.

Indeed this is broken, thank you for spotting this!

For sure I know how the driver model works, but I have mistakenly looked past this for the sdio_bus.

Commit 397a0253527a (mmc: sdio: Convert to dev_pm_domain_attach|detach()), should not only have converted to the new APIs but also moved the calls into sdio_bus' ->probe() and ->remove() callbacks.

I will fix this, in one way or the other.

Kind regards
Uffe

#56 lore raw

PATCH 9/9 Revert "PM / Domains: Power on the PM domain right after attach completes"

In reply to Ulf Hansson

Due to the invent of dev_pm_domain_get|put() API and related code in the generic PM domain, we can now safely revert this commit.

---
 drivers/base/power/domain.c | 1 -
 1 file changed, 1 deletion(-)
drivers/base/power/domain.c +0 -1
index 7314459..e89eb74 100644
@@ -2220,7 +2220,6 @@ int genpd_dev_pm_attach(struct device *dev)
 	}
 
 	dev->pm_domain->detach = genpd_dev_pm_detach;
-	pm_genpd_poweron(pd);
 
 	return 0;
 }
Signature · 1 line
1.9.1
#57 lore raw

PATCH 9/9 Revert "PM / Domains: Power on the PM domain right after attach completes"

Quoted 2 lines · Ulf Hansson

Due to the invent of dev_pm_domain_get|put() API and related code in the generic PM domain, we can now safely revert this commit.

... revert commit 2ed127697eb13766 ("PM / Domains: Power on the PM domain right after attach completes").

So not everyone has to look for the commit ID.

Gr{oetje,eeting}s,

Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert at linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But when I'm talking to journalists I just say "programmer" or something like that.
-- Linus Torvalds