Skip to contentSkip to conversation

runtime PM usage_count during driver_probe_device()?

PATCH Applied Kevin Hilman 5 participants 39 messages Jun 30, 2011 – Jul 1, 2011

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

Continuing on the theme of runtime PM interactions with other parts of the driver core...

In drivers/base/dd.c:driver_probe_device(), the driver core increments the usage count around ->probe():

        [...]
	pm_runtime_get_noresume(dev);
	pm_runtime_barrier(dev);
	ret = really_probe(dev, drv);
	pm_runtime_put_sync(dev);

I'm not following the reason for this. On driver's I'm familar with, it's not until ->probe where pm_runtime_enable() is called. What is being protected against here?

These seem to exist since the introduction of the runtime PM core, but I can't find any explanation.

The documentation refers to the increment by the core, but not the reasons why:

If the device bus type's or driver's ->probe() or ->remove() callback runs pm_runtime_suspend() or pm_runtime_idle() or their asynchronous counterparts, they will fail returning -EAGAIN, because the device's usage counter is incremented by the core before executing ->probe() and ->remove(). Still, it may be desirable to suspend the device as soon as ->probe() or ->remove() has finished, so the PM core uses pm_runtime_idle_sync() to invoke the subsystem-level idle callback for the device at that time.

On a side note, the bit about -EAGAIN above is not accurate with today's code. For example, __pm_runtime_suspend() returns zero when the usage count decrement is non-zero, so callers can't currently know that doing a pm_runtime_suspend() or pm_runtime_put_sync() in their ->probe() actually didn't happen.

Another curiosity is that, contrary to the above documentation, there is no usage_count increment before the bus/driver ->remove() (although there is a _get_sync/_put_sync around the sysfs_remove and notifier just before the bus/driver->remove().

Also, below is a patch for a typo in the above Documentation exerpt.

Kevin

Quoted 1 line

From 069484f8d2bb86473a271c27733e10fbfd410c2c Mon Sep 17 00:00:00 2001

From: Kevin Hilman <[email protected]>
Date: Thu, 30 Jun 2011 15:07:31 -0700
Subject: [PATCH] PM: Documentation: fix typo: pm_runtime_idle_sync() doesn't exist.

Replace reference to pm_runtime_idle_sync() in the driver core with pm_runtime_put_sync() which is used in the code.

---
 Documentation/power/runtime_pm.txt |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)
Documentation/power/runtime_pm.txt +1 -1
index 22accb3..518d9be 100644
@@ -506,7 +506,7 @@ pm_runtime_suspend() or pm_runtime_idle() or their asynchronous counterparts,
 they will fail returning -EAGAIN, because the device's usage counter is
 incremented by the core before executing ->probe() and ->remove().  Still, it
 may be desirable to suspend the device as soon as ->probe() or ->remove() has
-finished, so the PM core uses pm_runtime_idle_sync() to invoke the
+finished, so the PM core uses pm_runtime_put_sync() to invoke the
 subsystem-level idle callback for the device at that time.
 
 The user space can effectively disallow the driver of the device to power manage
Signature · 1 line
1.7.4
#1 lore raw
Quoted 31 lines · Kevin Hilman

Continuing on the theme of runtime PM interactions with other parts of the driver core...

In drivers/base/dd.c:driver_probe_device(), the driver core increments the usage count around ->probe():

        [...]
	pm_runtime_get_noresume(dev);
	pm_runtime_barrier(dev);
	ret = really_probe(dev, drv);
	pm_runtime_put_sync(dev);

I'm not following the reason for this. On driver's I'm familar with, it's not until ->probe where pm_runtime_enable() is called. What is being protected against here?

These seem to exist since the introduction of the runtime PM core, but I can't find any explanation.

The documentation refers to the increment by the core, but not the reasons why:

If the device bus type's or driver's ->probe() or ->remove() callback runs pm_runtime_suspend() or pm_runtime_idle() or their asynchronous counterparts, they will fail returning -EAGAIN, because the device's usage counter is incremented by the core before executing ->probe() and ->remove(). Still, it may be desirable to suspend the device as soon as ->probe() or ->remove() has finished, so the PM core uses pm_runtime_idle_sync() to invoke the subsystem-level idle callback for the device at that time.

Quoted 5 lines

On a side note, the bit about -EAGAIN above is not accurate with today's code. For example, __pm_runtime_suspend() returns zero when the usage count decrement is non-zero, so callers can't currently know that doing a pm_runtime_suspend() or pm_runtime_put_sync() in their ->probe() actually didn't happen.

Oops, I'm not quite right here.

The doc is actually right here if the driver uses pm_runtime_suspend() or pm_runtime_idle() in ->probe(). It's only when drivers use pm_runtime_put_sync() where there wouldn't be an -EAGAIN, but that seems correct. Sorry for the noise.

I'm still confused about the usage_count increment around ->probe though.

Kevin

Quoted 37 lines

Another curiosity is that, contrary to the above documentation, there is no usage_count increment before the bus/driver ->remove() (although there is a _get_sync/_put_sync around the sysfs_remove and notifier just before the bus/driver->remove().

Also, below is a patch for a typo in the above Documentation exerpt.

Kevin

From 069484f8d2bb86473a271c27733e10fbfd410c2c Mon Sep 17 00:00:00 2001
From: Kevin Hilman <[email protected]>
Date: Thu, 30 Jun 2011 15:07:31 -0700
Subject: [PATCH] PM: Documentation: fix typo: pm_runtime_idle_sync() doesn't exist.

Replace reference to pm_runtime_idle_sync() in the driver core with pm_runtime_put_sync() which is used in the code.

---
 Documentation/power/runtime_pm.txt |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)
Documentation/power/runtime_pm.txt +1 -1
index 22accb3..518d9be 100644
@@ -506,7 +506,7 @@ pm_runtime_suspend() or pm_runtime_idle() or their asynchronous counterparts,
 they will fail returning -EAGAIN, because the device's usage counter is
 incremented by the core before executing ->probe() and ->remove().  Still, it
 may be desirable to suspend the device as soon as ->probe() or ->remove() has
-finished, so the PM core uses pm_runtime_idle_sync() to invoke the
+finished, so the PM core uses pm_runtime_put_sync() to invoke the
 subsystem-level idle callback for the device at that time.
 
 The user space can effectively disallow the driver of the device to power manage
#2 lore raw
In reply to Kevin Hilman
Quoted 31 lines · Kevin Hilman

Continuing on the theme of runtime PM interactions with other parts of the driver core...

In drivers/base/dd.c:driver_probe_device(), the driver core increments the usage count around ->probe():

        [...]
	pm_runtime_get_noresume(dev);
	pm_runtime_barrier(dev);
	ret = really_probe(dev, drv);
	pm_runtime_put_sync(dev);

I'm not following the reason for this. On driver's I'm familar with, it's not until ->probe where pm_runtime_enable() is called. What is being protected against here?

These seem to exist since the introduction of the runtime PM core, but I can't find any explanation.

The documentation refers to the increment by the core, but not the reasons why:

If the device bus type's or driver's ->probe() or ->remove() callback runs pm_runtime_suspend() or pm_runtime_idle() or their asynchronous counterparts, they will fail returning -EAGAIN, because the device's usage counter is incremented by the core before executing ->probe() and ->remove(). Still, it may be desirable to suspend the device as soon as ->probe() or ->remove() has finished, so the PM core uses pm_runtime_idle_sync() to invoke the subsystem-level idle callback for the device at that time.

Quoted 5 lines

On a side note, the bit about -EAGAIN above is not accurate with today's code. For example, __pm_runtime_suspend() returns zero when the usage count decrement is non-zero, so callers can't currently know that doing a pm_runtime_suspend() or pm_runtime_put_sync() in their ->probe() actually didn't happen.

Oops, I'm not quite right here.

The doc is actually right here if the driver uses pm_runtime_suspend() or pm_runtime_idle() in ->probe(). It's only when drivers use pm_runtime_put_sync() where there wouldn't be an -EAGAIN, but that seems correct. Sorry for the noise.

I'm still confused about the usage_count increment around ->probe though.

Kevin

Quoted 37 lines

Another curiosity is that, contrary to the above documentation, there is no usage_count increment before the bus/driver ->remove() (although there is a _get_sync/_put_sync around the sysfs_remove and notifier just before the bus/driver->remove().

Also, below is a patch for a typo in the above Documentation exerpt.

Kevin

From 069484f8d2bb86473a271c27733e10fbfd410c2c Mon Sep 17 00:00:00 2001
From: Kevin Hilman <[email protected]>
Date: Thu, 30 Jun 2011 15:07:31 -0700
Subject: [PATCH] PM: Documentation: fix typo: pm_runtime_idle_sync() doesn't exist.

Replace reference to pm_runtime_idle_sync() in the driver core with pm_runtime_put_sync() which is used in the code.

---
 Documentation/power/runtime_pm.txt |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)
Documentation/power/runtime_pm.txt +1 -1
index 22accb3..518d9be 100644
@@ -506,7 +506,7 @@ pm_runtime_suspend() or pm_runtime_idle() or their asynchronous counterparts,
 they will fail returning -EAGAIN, because the device's usage counter is
 incremented by the core before executing ->probe() and ->remove().  Still, it
 may be desirable to suspend the device as soon as ->probe() or ->remove() has
-finished, so the PM core uses pm_runtime_idle_sync() to invoke the
+finished, so the PM core uses pm_runtime_put_sync() to invoke the
 subsystem-level idle callback for the device at that time.
 
 The user space can effectively disallow the driver of the device to power manage
#3 lore raw
Quoted 41 lines · Kevin Hilman
Quoted 31 lines · Kevin Hilman

Continuing on the theme of runtime PM interactions with other parts of the driver core...

In drivers/base/dd.c:driver_probe_device(), the driver core increments the usage count around ->probe():

        [...]
	pm_runtime_get_noresume(dev);
	pm_runtime_barrier(dev);
	ret = really_probe(dev, drv);
	pm_runtime_put_sync(dev);

I'm not following the reason for this. On driver's I'm familar with, it's not until ->probe where pm_runtime_enable() is called. What is being protected against here?

These seem to exist since the introduction of the runtime PM core, but I can't find any explanation.

The documentation refers to the increment by the core, but not the reasons why:

If the device bus type's or driver's ->probe() or ->remove() callback runs pm_runtime_suspend() or pm_runtime_idle() or their asynchronous counterparts, they will fail returning -EAGAIN, because the device's usage counter is incremented by the core before executing ->probe() and ->remove(). Still, it may be desirable to suspend the device as soon as ->probe() or ->remove() has finished, so the PM core uses pm_runtime_idle_sync() to invoke the subsystem-level idle callback for the device at that time.

Quoted 5 lines

On a side note, the bit about -EAGAIN above is not accurate with today's code. For example, __pm_runtime_suspend() returns zero when the usage count decrement is non-zero, so callers can't currently know that doing a pm_runtime_suspend() or pm_runtime_put_sync() in their ->probe() actually didn't happen.

Oops, I'm not quite right here.

Quoted 7 lines

The doc is actually right here if the driver uses pm_runtime_suspend() or pm_runtime_idle() in ->probe(). It's only when drivers use pm_runtime_put_sync() where there wouldn't be an -EAGAIN, but that seems correct. Sorry for the noise.

I'm still confused about the usage_count increment around ->probe though.

In theory it is possible that a subsystem (e.g. bus type) will enable runtime PM for devices without drivers and will (for example) put them into low power states until the drivers are loaded. Then, it makes sense for the core to prevent such transitions from racing with .probe().

I'm not sure if this happens in practice, though, but also I'm not sure whether or not that's used by USB. Moreover, even if that doesn't happen right now, it may start to happen at one point.

Thanks,
Rafael

#4 lore raw
Quoted 6 lines · Rafael J. Wysocki

In theory it is possible that a subsystem (e.g. bus type) will enable runtime PM for devices without drivers and will (for example) put them into low power states until the drivers are loaded.  Then, it makes sense for the core to prevent such transitions from racing with .probe().

I'm not sure if this happens in practice, though,

Yeah, this is exactly what the SDIO subsystem is doing.

#5 lore raw
In reply to Rafael J. Wysocki
Quoted 6 lines · Rafael J. Wysocki

In theory it is possible that a subsystem (e.g. bus type) will enable runtime PM for devices without drivers and will (for example) put them into low power states until the drivers are loaded.  Then, it makes sense for the core to prevent such transitions from racing with .probe().

I'm not sure if this happens in practice, though,

Yeah, this is exactly what the SDIO subsystem is doing.
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html

#6 lore raw
Quoted 9 lines · Ohad Ben-Cohen
Quoted 6 lines · Rafael J. Wysocki

In theory it is possible that a subsystem (e.g. bus type) will enable runtime PM for devices without drivers and will (for example) put them into low power states until the drivers are loaded.  Then, it makes sense for the core to prevent such transitions from racing with .probe().

I'm not sure if this happens in practice, though,

Yeah, this is exactly what the SDIO subsystem is doing.

Thanks, this makes sense.

Maybe runtime_pm.txt should be updated to explain this as well.

Kevin
_______________________________________________
linux-pm mailing list
[email protected]
https://lists.linux-foundation.org/mailman/listinfo/linux-pm

#7 lore raw
In reply to Ohad Ben-Cohen
Quoted 9 lines · Ohad Ben-Cohen
Quoted 6 lines · Rafael J. Wysocki

In theory it is possible that a subsystem (e.g. bus type) will enable runtime PM for devices without drivers and will (for example) put them into low power states until the drivers are loaded.  Then, it makes sense for the core to prevent such transitions from racing with .probe().

I'm not sure if this happens in practice, though,

Yeah, this is exactly what the SDIO subsystem is doing.

Thanks, this makes sense.

Maybe runtime_pm.txt should be updated to explain this as well.

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

#8 lore raw
In reply to Rafael J. Wysocki

Hi,

Quoted 8 lines · Rafael J. Wysocki

In theory it is possible that a subsystem (e.g. bus type) will enable runtime PM for devices without drivers and will (for example) put them into low power states until the drivers are loaded.  Then, it makes sense for the core to prevent such transitions from racing with .probe().

I'm not sure if this happens in practice, though, but also I'm not sure whether or not that's used by USB.  Moreover, even if that doesn't happen right now, it may start to happen at one point.

It should be used by USB, for example, uvcvideo driver has enabled auto suspend already:

- rmmod uvcvideo

- usb video class device auto suspended

- modprobe uvcvideo #driver_probe_device()

thanks,

Signature · 5 lines
Ming Lei
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
#9 lore raw
In reply to Rafael J. Wysocki

Hi,

Quoted 8 lines · Rafael J. Wysocki

In theory it is possible that a subsystem (e.g. bus type) will enable runtime PM for devices without drivers and will (for example) put them into low power states until the drivers are loaded.  Then, it makes sense for the core to prevent such transitions from racing with .probe().

I'm not sure if this happens in practice, though, but also I'm not sure whether or not that's used by USB.  Moreover, even if that doesn't happen right now, it may start to happen at one point.

It should be used by USB, for example, uvcvideo driver has enabled auto suspend already:

- rmmod uvcvideo

- usb video class device auto suspended

- modprobe uvcvideo #driver_probe_device()

thanks,

Signature · 1 line
Ming Lei
#10 lore raw
In reply to Kevin Hilman
Quoted 41 lines · Kevin Hilman
Quoted 31 lines · Kevin Hilman

Continuing on the theme of runtime PM interactions with other parts of the driver core...

In drivers/base/dd.c:driver_probe_device(), the driver core increments the usage count around ->probe():

        [...]
	pm_runtime_get_noresume(dev);
	pm_runtime_barrier(dev);
	ret = really_probe(dev, drv);
	pm_runtime_put_sync(dev);

I'm not following the reason for this. On driver's I'm familar with, it's not until ->probe where pm_runtime_enable() is called. What is being protected against here?

These seem to exist since the introduction of the runtime PM core, but I can't find any explanation.

The documentation refers to the increment by the core, but not the reasons why:

If the device bus type's or driver's ->probe() or ->remove() callback runs pm_runtime_suspend() or pm_runtime_idle() or their asynchronous counterparts, they will fail returning -EAGAIN, because the device's usage counter is incremented by the core before executing ->probe() and ->remove(). Still, it may be desirable to suspend the device as soon as ->probe() or ->remove() has finished, so the PM core uses pm_runtime_idle_sync() to invoke the subsystem-level idle callback for the device at that time.

Quoted 5 lines

On a side note, the bit about -EAGAIN above is not accurate with today's code. For example, __pm_runtime_suspend() returns zero when the usage count decrement is non-zero, so callers can't currently know that doing a pm_runtime_suspend() or pm_runtime_put_sync() in their ->probe() actually didn't happen.

Oops, I'm not quite right here.

Quoted 7 lines

The doc is actually right here if the driver uses pm_runtime_suspend() or pm_runtime_idle() in ->probe(). It's only when drivers use pm_runtime_put_sync() where there wouldn't be an -EAGAIN, but that seems correct. Sorry for the noise.

I'm still confused about the usage_count increment around ->probe though.

In theory it is possible that a subsystem (e.g. bus type) will enable runtime PM for devices without drivers and will (for example) put them into low power states until the drivers are loaded. Then, it makes sense for the core to prevent such transitions from racing with .probe().

I'm not sure if this happens in practice, though, but also I'm not sure whether or not that's used by USB. Moreover, even if that doesn't happen right now, it may start to happen at one point.

Thanks,
Rafael

#11 lore raw
In reply to Kevin Hilman
Quoted 2 lines · Kevin Hilman

I'm still confused about the usage_count increment around ->probe though.

As a few people have already pointed out, some subsystems do perform runtime PM on driverless devices.

The basic idea is simple: We don't want any PM callbacks to race with each other or with other driver-core callbacks. Incrementing the usage_count prevents runtime_suspend callbacks while the probe callback is running.

This does leave open the possibility of runtime_resume occurring concurrently with probe. For the most part this should be okay because without a driver, no part of the kernel will try to resume the device.

Hmmm, but a resume could occur as a result of userspace writing to a sysfs attribute. It looks like we need to add some lock_device() calls to control_store() and autosuspend_delay_ms_store().

Alan Stern

#12 lore raw
In reply to Kevin Hilman
Quoted 2 lines · Kevin Hilman

I'm still confused about the usage_count increment around ->probe though.

As a few people have already pointed out, some subsystems do perform runtime PM on driverless devices.

The basic idea is simple: We don't want any PM callbacks to race with each other or with other driver-core callbacks. Incrementing the usage_count prevents runtime_suspend callbacks while the probe callback is running.

This does leave open the possibility of runtime_resume occurring concurrently with probe. For the most part this should be okay because without a driver, no part of the kernel will try to resume the device.

Hmmm, but a resume could occur as a result of userspace writing to a sysfs attribute. It looks like we need to add some lock_device() calls to control_store() and autosuspend_delay_ms_store().

Alan Stern

#13 lore raw

PATCH 1/1 PM: prevent runtime_resume from racing with probe

This patch (as1475) adds device_lock() and device_unlock() calls to the store methods for the power/control and power/autosuspend_delay_ms sysfs attribute files. We don't want badly timed writes to these files to cause runtime_resume callbacks to occur while a driver is being probed for a device.

---

 drivers/base/power/sysfs.c |    6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)
drivers/base/power/sysfs.c +5 -1
Index: usb-3.0/drivers/base/power/sysfs.c
===================================================================
@@ -116,12 +116,14 @@ static ssize_t control_store(struct devi
 	cp = memchr(buf, '\n', n);
 	if (cp)
 		len = cp - buf;
+	device_lock(dev);
 	if (len == sizeof ctrl_auto - 1 && strncmp(buf, ctrl_auto, len) == 0)
 		pm_runtime_allow(dev);
 	else if (len == sizeof ctrl_on - 1 && strncmp(buf, ctrl_on, len) == 0)
 		pm_runtime_forbid(dev);
 	else
-		return -EINVAL;
+		n = -EINVAL;
+	device_unlock(dev);
 	return n;
 }
 
@@ -205,7 +207,9 @@ static ssize_t autosuspend_delay_ms_stor
 	if (strict_strtol(buf, 10, &delay) != 0 || delay != (int) delay)
 		return -EINVAL;
 
+	device_lock(dev);
 	pm_runtime_set_autosuspend_delay(dev, delay);
+	device_unlock(dev);
 	return n;
 }
 
#14 lore raw

Re: [PATCH] PM: prevent runtime_resume from racing with probe

Quoted 7 lines · Alan Stern

This patch (as1475) adds device_lock() and device_unlock() calls to the store methods for the power/control and power/autosuspend_delay_ms sysfs attribute files. We don't want badly timed writes to these files to cause runtime_resume callbacks to occur while a driver is being probed for a device.

Applied to suspend-2.6/linux-next.

Thanks,
Rafael

Quoted 38 lines

---

 drivers/base/power/sysfs.c |    6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

Index: usb-3.0/drivers/base/power/sysfs.c
===================================================================

drivers/base/power/sysfs.c +5 -1
@@ -116,12 +116,14 @@ static ssize_t control_store(struct devi
 	cp = memchr(buf, '\n', n);
 	if (cp)
 		len = cp - buf;
+	device_lock(dev);
 	if (len == sizeof ctrl_auto - 1 && strncmp(buf, ctrl_auto, len) == 0)
 		pm_runtime_allow(dev);
 	else if (len == sizeof ctrl_on - 1 && strncmp(buf, ctrl_on, len) == 0)
 		pm_runtime_forbid(dev);
 	else
-		return -EINVAL;
+		n = -EINVAL;
+	device_unlock(dev);
 	return n;
 }
 
@@ -205,7 +207,9 @@ static ssize_t autosuspend_delay_ms_stor
 	if (strict_strtol(buf, 10, &delay) != 0 || delay != (int) delay)
 		return -EINVAL;
 
+	device_lock(dev);
 	pm_runtime_set_autosuspend_delay(dev, delay);
+	device_unlock(dev);
 	return n;
 }
 
#15 lore raw
In reply to Kevin Hilman
Quoted 4 lines · Kevin Hilman

Another curiosity is that, contrary to the above documentation, there is no usage_count increment before the bus/driver ->remove() (although there is a _get_sync/_put_sync around the sysfs_remove and notifier just before the bus/driver->remove().

I hadn't noticed that. There may be a reason for using get_sync instead of get_noresume, but it isn't explained anywhere. And it certainly looks like a mistake for the put_sync to occur before the ->remove() call instead of after.

This needs to be fixed.

Alan Stern

#16 lore raw
In reply to Kevin Hilman
Quoted 4 lines · Kevin Hilman

Another curiosity is that, contrary to the above documentation, there is no usage_count increment before the bus/driver ->remove() (although there is a _get_sync/_put_sync around the sysfs_remove and notifier just before the bus/driver->remove().

I hadn't noticed that. There may be a reason for using get_sync instead of get_noresume, but it isn't explained anywhere. And it certainly looks like a mistake for the put_sync to occur before the ->remove() call instead of after.

This needs to be fixed.

Alan Stern

#17 lore raw
In reply to Kevin Hilman

Kevin Hilman <[email protected]> writes:

[...]

Quoted 8 lines

If the device bus type's or driver's ->probe() or ->remove() callback runs pm_runtime_suspend() or pm_runtime_idle() or their asynchronous counterparts, they will fail returning -EAGAIN, because the device's usage counter is incremented by the core before executing ->probe() and ->remove(). Still, it may be desirable to suspend the device as soon as ->probe() or ->remove() has finished, so the PM core uses pm_runtime_idle_sync() to invoke the subsystem-level idle callback for the device at that time.

[...]

Quoted 4 lines

Another curiosity is that, contrary to the above documentation, there is no usage_count increment before the bus/driver ->remove() (although there is a _get_sync/_put_sync around the sysfs_remove and notifier just before the bus/driver->remove().

OK, so the ->probe() part has been explained and makes sense, but I would expect ->remove() to be similarily protected (as the documentation states.) But that is not the case. Is that a bug? If so, patch below makes the code match the documentation.

Kevin

Quoted 1 line

From eef73ab2feb203bacb57dc35862f2a9969b61593 Mon Sep 17 00:00:00 2001

From: Kevin Hilman <[email protected]>
Date: Fri, 1 Jul 2011 07:37:47 -0700
Subject: [PATCH] driver core: prevent runtime PM races with ->remove()

Runtime PM Documentation states that the runtime PM usage count is incremented during driver ->probe() and ->remove(). This is designed to prevent driver runtime PM races with subsystems which may initiate runtime PM transitions before during and after drivers are loaded.

Current code increments the usage_count during ->probe() but not during ->remove(). This patch fixes the ->remove() part and makes the code match the documentation.

---
 drivers/base/dd.c |    6 +++---
 1 files changed, 3 insertions(+), 3 deletions(-)
drivers/base/dd.c +3 -3
index 6658da7..47e079d 100644
@@ -329,13 +329,13 @@ static void __device_release_driver(struct device *dev)
 			blocking_notifier_call_chain(&dev->bus->p->bus_notifier,
 						     BUS_NOTIFY_UNBIND_DRIVER,
 						     dev);
-
-		pm_runtime_put_sync(dev);
-
 		if (dev->bus && dev->bus->remove)
 			dev->bus->remove(dev);
 		else if (drv->remove)
 			drv->remove(dev);
+
+		pm_runtime_put_sync(dev);
+
 		devres_release_all(dev);
 		dev->driver = NULL;
 		klist_remove(&dev->p->knode_driver);
Signature · 1 line
1.7.4
#18 lore raw
In reply to Kevin Hilman

Kevin Hilman <[email protected]> writes:

[...]

Quoted 8 lines

If the device bus type's or driver's ->probe() or ->remove() callback runs pm_runtime_suspend() or pm_runtime_idle() or their asynchronous counterparts, they will fail returning -EAGAIN, because the device's usage counter is incremented by the core before executing ->probe() and ->remove(). Still, it may be desirable to suspend the device as soon as ->probe() or ->remove() has finished, so the PM core uses pm_runtime_idle_sync() to invoke the subsystem-level idle callback for the device at that time.

[...]

Quoted 4 lines

Another curiosity is that, contrary to the above documentation, there is no usage_count increment before the bus/driver ->remove() (although there is a _get_sync/_put_sync around the sysfs_remove and notifier just before the bus/driver->remove().

OK, so the ->probe() part has been explained and makes sense, but I would expect ->remove() to be similarily protected (as the documentation states.) But that is not the case. Is that a bug? If so, patch below makes the code match the documentation.

Kevin

Quoted 1 line

From eef73ab2feb203bacb57dc35862f2a9969b61593 Mon Sep 17 00:00:00 2001

From: Kevin Hilman <[email protected]>
Date: Fri, 1 Jul 2011 07:37:47 -0700
Subject: [PATCH] driver core: prevent runtime PM races with ->remove()

Runtime PM Documentation states that the runtime PM usage count is incremented during driver ->probe() and ->remove(). This is designed to prevent driver runtime PM races with subsystems which may initiate runtime PM transitions before during and after drivers are loaded.

Current code increments the usage_count during ->probe() but not during ->remove(). This patch fixes the ->remove() part and makes the code match the documentation.

---
 drivers/base/dd.c |    6 +++---
 1 files changed, 3 insertions(+), 3 deletions(-)
drivers/base/dd.c +3 -3
index 6658da7..47e079d 100644
@@ -329,13 +329,13 @@ static void __device_release_driver(struct device *dev)
 			blocking_notifier_call_chain(&dev->bus->p->bus_notifier,
 						     BUS_NOTIFY_UNBIND_DRIVER,
 						     dev);
-
-		pm_runtime_put_sync(dev);
-
 		if (dev->bus && dev->bus->remove)
 			dev->bus->remove(dev);
 		else if (drv->remove)
 			drv->remove(dev);
+
+		pm_runtime_put_sync(dev);
+
 		devres_release_all(dev);
 		dev->driver = NULL;
 		klist_remove(&dev->p->knode_driver);
Signature · 1 line
1.7.4
#19 lore raw
Quoted 4 lines · Kevin Hilman

OK, so the ->probe() part has been explained and makes sense, but I would expect ->remove() to be similarily protected (as the documentation states.) But that is not the case. Is that a bug? If so, patch below makes the code match the documentation.

I suspect it is a bug, but it's hard to be sure. It's so _blatantly_ wrong that it looks like it was done deliberately.

Quoted 32 lines

Kevin

From eef73ab2feb203bacb57dc35862f2a9969b61593 Mon Sep 17 00:00:00 2001
From: Kevin Hilman <[email protected]>
Date: Fri, 1 Jul 2011 07:37:47 -0700
Subject: [PATCH] driver core: prevent runtime PM races with ->remove()

Runtime PM Documentation states that the runtime PM usage count is incremented during driver ->probe() and ->remove(). This is designed to prevent driver runtime PM races with subsystems which may initiate runtime PM transitions before during and after drivers are loaded.

Current code increments the usage_count during ->probe() but not during ->remove(). This patch fixes the ->remove() part and makes the code match the documentation.

---
 drivers/base/dd.c |    6 +++---
 1 files changed, 3 insertions(+), 3 deletions(-)
drivers/base/dd.c +0 -3
index 6658da7..47e079d 100644
@@ -329,13 +329,13 @@ static void __device_release_driver(struct device *dev)
 			blocking_notifier_call_chain(&dev->bus->p->bus_notifier,
 						     BUS_NOTIFY_UNBIND_DRIVER,
 						     dev);
-
-		pm_runtime_put_sync(dev);
-

drivers/base/dd.c static void __device_release_driver(struct device *dev) · line 341

Quoted 10 lines
drivers/base/dd.c +3 -0
 		if (dev->bus && dev->bus->remove)
 			dev->bus->remove(dev);
 		else if (drv->remove)
 			drv->remove(dev);
+
+		pm_runtime_put_sync(dev);
+
 		devres_release_all(dev);
 		dev->driver = NULL;
 		klist_remove(&dev->p->knode_driver);

To be safer, the put_sync() call should be moved down here. Or maybe even after the blocking_notifier_call_chain() that occurs here.

Alan Stern

#20 lore raw
In reply to Kevin Hilman
Quoted 4 lines · Kevin Hilman

OK, so the ->probe() part has been explained and makes sense, but I would expect ->remove() to be similarily protected (as the documentation states.) But that is not the case. Is that a bug? If so, patch below makes the code match the documentation.

I suspect it is a bug, but it's hard to be sure. It's so _blatantly_ wrong that it looks like it was done deliberately.

Quoted 32 lines

Kevin

From eef73ab2feb203bacb57dc35862f2a9969b61593 Mon Sep 17 00:00:00 2001
From: Kevin Hilman <[email protected]>
Date: Fri, 1 Jul 2011 07:37:47 -0700
Subject: [PATCH] driver core: prevent runtime PM races with ->remove()

Runtime PM Documentation states that the runtime PM usage count is incremented during driver ->probe() and ->remove(). This is designed to prevent driver runtime PM races with subsystems which may initiate runtime PM transitions before during and after drivers are loaded.

Current code increments the usage_count during ->probe() but not during ->remove(). This patch fixes the ->remove() part and makes the code match the documentation.

---
 drivers/base/dd.c |    6 +++---
 1 files changed, 3 insertions(+), 3 deletions(-)
drivers/base/dd.c +0 -3
index 6658da7..47e079d 100644
@@ -329,13 +329,13 @@ static void __device_release_driver(struct device *dev)
 			blocking_notifier_call_chain(&dev->bus->p->bus_notifier,
 						     BUS_NOTIFY_UNBIND_DRIVER,
 						     dev);
-
-		pm_runtime_put_sync(dev);
-

drivers/base/dd.c static void __device_release_driver(struct device *dev) · line 341

Quoted 10 lines
drivers/base/dd.c +3 -0
 		if (dev->bus && dev->bus->remove)
 			dev->bus->remove(dev);
 		else if (drv->remove)
 			drv->remove(dev);
+
+		pm_runtime_put_sync(dev);
+
 		devres_release_all(dev);
 		dev->driver = NULL;
 		klist_remove(&dev->p->knode_driver);

To be safer, the put_sync() call should be moved down here. Or maybe even after the blocking_notifier_call_chain() that occurs here.

Alan Stern

#21 lore raw
Quoted 9 lines · Alan Stern
Quoted 4 lines · Kevin Hilman

OK, so the ->probe() part has been explained and makes sense, but I would expect ->remove() to be similarily protected (as the documentation states.) But that is not the case. Is that a bug? If so, patch below makes the code match the documentation.

I suspect it is a bug, but it's hard to be sure. It's so _blatantly_ wrong that it looks like it was done deliberately.

heh

Quoted 37 lines
Quoted 37 lines

Kevin

From eef73ab2feb203bacb57dc35862f2a9969b61593 Mon Sep 17 00:00:00 2001
From: Kevin Hilman <[email protected]>
Date: Fri, 1 Jul 2011 07:37:47 -0700
Subject: [PATCH] driver core: prevent runtime PM races with ->remove()

Runtime PM Documentation states that the runtime PM usage count is incremented during driver ->probe() and ->remove(). This is designed to prevent driver runtime PM races with subsystems which may initiate runtime PM transitions before during and after drivers are loaded.

Current code increments the usage_count during ->probe() but not during ->remove(). This patch fixes the ->remove() part and makes the code match the documentation.

---
 drivers/base/dd.c |    6 +++---
 1 files changed, 3 insertions(+), 3 deletions(-)
drivers/base/dd.c +1 -3
index 6658da7..47e079d 100644
@@ -329,13 +329,13 @@ static void __device_release_driver(struct device *dev)
 			blocking_notifier_call_chain(&dev->bus->p->bus_notifier,
 						     BUS_NOTIFY_UNBIND_DRIVER,
 						     dev);
-
-		pm_runtime_put_sync(dev);
-
 		if (dev->bus && dev->bus->remove)
 			dev->bus->remove(dev);
 		else if (drv->remove)
 			drv->remove(dev);
+
Quoted 8 lines

drivers/base/dd.c static void __device_release_driver(struct device *dev) · line 341

Quoted 5 lines
drivers/base/dd.c +2 -0
+		pm_runtime_put_sync(dev);
+
 		devres_release_all(dev);
 		dev->driver = NULL;
 		klist_remove(&dev->p->knode_driver);

To be safer, the put_sync() call should be moved down here. Or maybe even after the blocking_notifier_call_chain() that occurs here.

I was actually thinking about the other direction: moving the get_sync after the first notifier chain. IOW, the get_sync/put_sync only protects the ->remove() calls, not the notifiers.

The protection around the notifiers doesn't make sense to me, at least in the context of driver runtime PM racing with the subsystem. Especially since these notifiers are likely how the subsystem/bus/pm_domain code getting notified that there may be a device to manage in the first place.

Kevin

#22 lore raw
In reply to Alan Stern
Quoted 9 lines · Alan Stern
Quoted 4 lines · Kevin Hilman

OK, so the ->probe() part has been explained and makes sense, but I would expect ->remove() to be similarily protected (as the documentation states.) But that is not the case. Is that a bug? If so, patch below makes the code match the documentation.

I suspect it is a bug, but it's hard to be sure. It's so _blatantly_ wrong that it looks like it was done deliberately.

heh

Quoted 37 lines
Quoted 37 lines

Kevin

From eef73ab2feb203bacb57dc35862f2a9969b61593 Mon Sep 17 00:00:00 2001
From: Kevin Hilman <[email protected]>
Date: Fri, 1 Jul 2011 07:37:47 -0700
Subject: [PATCH] driver core: prevent runtime PM races with ->remove()

Runtime PM Documentation states that the runtime PM usage count is incremented during driver ->probe() and ->remove(). This is designed to prevent driver runtime PM races with subsystems which may initiate runtime PM transitions before during and after drivers are loaded.

Current code increments the usage_count during ->probe() but not during ->remove(). This patch fixes the ->remove() part and makes the code match the documentation.

---
 drivers/base/dd.c |    6 +++---
 1 files changed, 3 insertions(+), 3 deletions(-)
drivers/base/dd.c +1 -3
index 6658da7..47e079d 100644
@@ -329,13 +329,13 @@ static void __device_release_driver(struct device *dev)
 			blocking_notifier_call_chain(&dev->bus->p->bus_notifier,
 						     BUS_NOTIFY_UNBIND_DRIVER,
 						     dev);
-
-		pm_runtime_put_sync(dev);
-
 		if (dev->bus && dev->bus->remove)
 			dev->bus->remove(dev);
 		else if (drv->remove)
 			drv->remove(dev);
+
Quoted 8 lines

drivers/base/dd.c static void __device_release_driver(struct device *dev) · line 341

Quoted 5 lines
drivers/base/dd.c +2 -0
+		pm_runtime_put_sync(dev);
+
 		devres_release_all(dev);
 		dev->driver = NULL;
 		klist_remove(&dev->p->knode_driver);

To be safer, the put_sync() call should be moved down here. Or maybe even after the blocking_notifier_call_chain() that occurs here.

I was actually thinking about the other direction: moving the get_sync after the first notifier chain. IOW, the get_sync/put_sync only protects the ->remove() calls, not the notifiers.

The protection around the notifiers doesn't make sense to me, at least in the context of driver runtime PM racing with the subsystem. Especially since these notifiers are likely how the subsystem/bus/pm_domain code getting notified that there may be a device to manage in the first place.

Kevin

#23 lore raw
Quoted 27 lines · Kevin Hilman
Quoted 14 lines
Quoted 14 lines
drivers/base/dd.c +1 -3
@@ -329,13 +329,13 @@ static void __device_release_driver(struct device *dev)
 			blocking_notifier_call_chain(&dev->bus->p->bus_notifier,
 						     BUS_NOTIFY_UNBIND_DRIVER,
 						     dev);
-
-		pm_runtime_put_sync(dev);
-
 		if (dev->bus && dev->bus->remove)
 			dev->bus->remove(dev);
 		else if (drv->remove)
 			drv->remove(dev);
+
Quoted 8 lines

drivers/base/dd.c static void __device_release_driver(struct device *dev) · line 341

Quoted 5 lines
drivers/base/dd.c +2 -0
+		pm_runtime_put_sync(dev);
+
 		devres_release_all(dev);
 		dev->driver = NULL;
 		klist_remove(&dev->p->knode_driver);

To be safer, the put_sync() call should be moved down here. Or maybe even after the blocking_notifier_call_chain() that occurs here.

I was actually thinking about the other direction: moving the get_sync after the first notifier chain. IOW, the get_sync/put_sync only protects the ->remove() calls, not the notifiers.

Quoted 5 lines

The protection around the notifiers doesn't make sense to me, at least in the context of driver runtime PM racing with the subsystem. Especially since these notifiers are likely how the subsystem/bus/pm_domain code getting notified that there may be a device to manage in the first place.

The get_sync part doesn't matter so much. Moving it past the notifier call would probably be okay -- unless one of the listeners on the notifier chain expects the device to be active. Changing the get_sync to get_noresume would probably also be okay -- subject to a similar reservation.

The problem with the put_sync isn't the notifier. If you leave it where you've got it now, you'll end up invoking a callback at a time when the driver thinks it no longer controls the device but the driver-model core still thinks it does. You certainly want to do the

	dev->driver = NULL;

first.

Alan Stern

#24 lore raw
In reply to Kevin Hilman
Quoted 27 lines · Kevin Hilman
Quoted 14 lines
Quoted 14 lines
drivers/base/dd.c +1 -3
@@ -329,13 +329,13 @@ static void __device_release_driver(struct device *dev)
 			blocking_notifier_call_chain(&dev->bus->p->bus_notifier,
 						     BUS_NOTIFY_UNBIND_DRIVER,
 						     dev);
-
-		pm_runtime_put_sync(dev);
-
 		if (dev->bus && dev->bus->remove)
 			dev->bus->remove(dev);
 		else if (drv->remove)
 			drv->remove(dev);
+
Quoted 8 lines

drivers/base/dd.c static void __device_release_driver(struct device *dev) · line 341

Quoted 5 lines
drivers/base/dd.c +2 -0
+		pm_runtime_put_sync(dev);
+
 		devres_release_all(dev);
 		dev->driver = NULL;
 		klist_remove(&dev->p->knode_driver);

To be safer, the put_sync() call should be moved down here. Or maybe even after the blocking_notifier_call_chain() that occurs here.

I was actually thinking about the other direction: moving the get_sync after the first notifier chain. IOW, the get_sync/put_sync only protects the ->remove() calls, not the notifiers.

Quoted 5 lines

The protection around the notifiers doesn't make sense to me, at least in the context of driver runtime PM racing with the subsystem. Especially since these notifiers are likely how the subsystem/bus/pm_domain code getting notified that there may be a device to manage in the first place.

The get_sync part doesn't matter so much. Moving it past the notifier call would probably be okay -- unless one of the listeners on the notifier chain expects the device to be active. Changing the get_sync to get_noresume would probably also be okay -- subject to a similar reservation.

The problem with the put_sync isn't the notifier. If you leave it where you've got it now, you'll end up invoking a callback at a time when the driver thinks it no longer controls the device but the driver-model core still thinks it does. You certainly want to do the

	dev->driver = NULL;

first.

Alan Stern

#25 lore raw
Quoted 35 lines · Alan Stern
Quoted 27 lines · Kevin Hilman
Quoted 14 lines
Quoted 14 lines
drivers/base/dd.c +1 -3
@@ -329,13 +329,13 @@ static void __device_release_driver(struct device *dev)
 			blocking_notifier_call_chain(&dev->bus->p->bus_notifier,
 						     BUS_NOTIFY_UNBIND_DRIVER,
 						     dev);
-
-		pm_runtime_put_sync(dev);
-
 		if (dev->bus && dev->bus->remove)
 			dev->bus->remove(dev);
 		else if (drv->remove)
 			drv->remove(dev);
+
Quoted 8 lines

drivers/base/dd.c static void __device_release_driver(struct device *dev) · line 341

Quoted 5 lines
drivers/base/dd.c +2 -0
+		pm_runtime_put_sync(dev);
+
 		devres_release_all(dev);
 		dev->driver = NULL;
 		klist_remove(&dev->p->knode_driver);

To be safer, the put_sync() call should be moved down here. Or maybe even after the blocking_notifier_call_chain() that occurs here.

I was actually thinking about the other direction: moving the get_sync after the first notifier chain. IOW, the get_sync/put_sync only protects the ->remove() calls, not the notifiers.

Quoted 5 lines

The protection around the notifiers doesn't make sense to me, at least in the context of driver runtime PM racing with the subsystem. Especially since these notifiers are likely how the subsystem/bus/pm_domain code getting notified that there may be a device to manage in the first place.

Quoted 5 lines

The get_sync part doesn't matter so much. Moving it past the notifier call would probably be okay -- unless one of the listeners on the notifier chain expects the device to be active. Changing the get_sync to get_noresume would probably also be okay -- subject to a similar reservation.

There are enough "probably"s in the above to make me a bit uncomfortable making this change. Maybe you can take this patch forward?

Kevin

Quoted 10 lines

The problem with the put_sync isn't the notifier. If you leave it where you've got it now, you'll end up invoking a callback at a time when the driver thinks it no longer controls the device but the driver-model core still thinks it does. You certainly want to do the

	dev->driver = NULL;

first.

Alan Stern

#26 lore raw
In reply to Alan Stern
Quoted 35 lines · Alan Stern
Quoted 27 lines · Kevin Hilman
Quoted 14 lines
Quoted 14 lines
drivers/base/dd.c +1 -3
@@ -329,13 +329,13 @@ static void __device_release_driver(struct device *dev)
 			blocking_notifier_call_chain(&dev->bus->p->bus_notifier,
 						     BUS_NOTIFY_UNBIND_DRIVER,
 						     dev);
-
-		pm_runtime_put_sync(dev);
-
 		if (dev->bus && dev->bus->remove)
 			dev->bus->remove(dev);
 		else if (drv->remove)
 			drv->remove(dev);
+
Quoted 8 lines

drivers/base/dd.c static void __device_release_driver(struct device *dev) · line 341

Quoted 5 lines
drivers/base/dd.c +2 -0
+		pm_runtime_put_sync(dev);
+
 		devres_release_all(dev);
 		dev->driver = NULL;
 		klist_remove(&dev->p->knode_driver);

To be safer, the put_sync() call should be moved down here. Or maybe even after the blocking_notifier_call_chain() that occurs here.

I was actually thinking about the other direction: moving the get_sync after the first notifier chain. IOW, the get_sync/put_sync only protects the ->remove() calls, not the notifiers.

Quoted 5 lines

The protection around the notifiers doesn't make sense to me, at least in the context of driver runtime PM racing with the subsystem. Especially since these notifiers are likely how the subsystem/bus/pm_domain code getting notified that there may be a device to manage in the first place.

Quoted 5 lines

The get_sync part doesn't matter so much. Moving it past the notifier call would probably be okay -- unless one of the listeners on the notifier chain expects the device to be active. Changing the get_sync to get_noresume would probably also be okay -- subject to a similar reservation.

There are enough "probably"s in the above to make me a bit uncomfortable making this change. Maybe you can take this patch forward?

Kevin

Quoted 10 lines

The problem with the put_sync isn't the notifier. If you leave it where you've got it now, you'll end up invoking a callback at a time when the driver thinks it no longer controls the device but the driver-model core still thinks it does. You certainly want to do the

	dev->driver = NULL;

first.

Alan Stern

#27 lore raw
In reply to Kevin Hilman

Hi,

Quoted 9 lines · Kevin Hilman
Quoted 7 lines · Alan Stern
Quoted 4 lines · Kevin Hilman

OK, so the ->probe() part has been explained and makes sense, but I would expect ->remove() to be similarily protected (as the documentation states.) But that is not the case. Is that a bug? If so, patch below makes the code match the documentation.

Quoted 4 lines
Quoted 2 lines

I suspect it is a bug, but it's hard to be sure. It's so _blatantly_ wrong that it looks like it was done deliberately.

heh

I seem to remeber having a problem with the pm_runtime_put_sync() after drv->remove(dev) ...

So the code in question was introduced by

commit e1866b33b1e89f077b7132daae3dfd9a594e9a1a

Author: Rafael J. Wysocki <[email protected]>
Date:   Fri Apr 29 00:33:45 2011 +0200

PM / Runtime: Rework runtime PM handling during driver removal

with a long changelog explaining the reason why. Which seems to make sense. ;-)

So I'm not sure.

Thanks,
Rafael

#28 lore raw
Quoted 22 lines · Rafael J. Wysocki

Hi,

Quoted 9 lines · Kevin Hilman
Quoted 7 lines · Alan Stern
Quoted 4 lines · Kevin Hilman

OK, so the ->probe() part has been explained and makes sense, but I would expect ->remove() to be similarily protected (as the documentation states.) But that is not the case. Is that a bug? If so, patch below makes the code match the documentation.

Quoted 4 lines
Quoted 2 lines

I suspect it is a bug, but it's hard to be sure. It's so _blatantly_ wrong that it looks like it was done deliberately.

heh

I seem to remeber having a problem with the pm_runtime_put_sync() after drv->remove(dev) ...

So the code in question was introduced by

Quoted 7 lines

commit e1866b33b1e89f077b7132daae3dfd9a594e9a1a

Author: Rafael J. Wysocki <[email protected]>
Date:   Fri Apr 29 00:33:45 2011 +0200

PM / Runtime: Rework runtime PM handling during driver removal

with a long changelog explaining the reason why. Which seems to make sense. ;-)

Okay, that seems fair enough. Looks like the documentation needs to be updated to match, though.

And we probably still want to make sure that access to the power/control and related attribute files is mutually exclusive with probe and remove.

Alan Stern

#29 lore raw
In reply to Rafael J. Wysocki
Quoted 22 lines · Rafael J. Wysocki

Hi,

Quoted 9 lines · Kevin Hilman
Quoted 7 lines · Alan Stern
Quoted 4 lines · Kevin Hilman

OK, so the ->probe() part has been explained and makes sense, but I would expect ->remove() to be similarily protected (as the documentation states.) But that is not the case. Is that a bug? If so, patch below makes the code match the documentation.

Quoted 4 lines
Quoted 2 lines

I suspect it is a bug, but it's hard to be sure. It's so _blatantly_ wrong that it looks like it was done deliberately.

heh

I seem to remeber having a problem with the pm_runtime_put_sync() after drv->remove(dev) ...

So the code in question was introduced by

Quoted 7 lines

commit e1866b33b1e89f077b7132daae3dfd9a594e9a1a

Author: Rafael J. Wysocki <[email protected]>
Date:   Fri Apr 29 00:33:45 2011 +0200

PM / Runtime: Rework runtime PM handling during driver removal

with a long changelog explaining the reason why. Which seems to make sense. ;-)

Okay, that seems fair enough. Looks like the documentation needs to be updated to match, though.

And we probably still want to make sure that access to the power/control and related attribute files is mutually exclusive with probe and remove.

Alan Stern

#30 lore raw
Quoted 28 lines · Alan Stern
Quoted 26 lines · Rafael J. Wysocki

Hi,

Quoted 9 lines · Kevin Hilman
Quoted 7 lines · Alan Stern
Quoted 4 lines · Kevin Hilman

OK, so the ->probe() part has been explained and makes sense, but I would expect ->remove() to be similarily protected (as the documentation states.) But that is not the case. Is that a bug? If so, patch below makes the code match the documentation.

Quoted 4 lines
Quoted 2 lines

I suspect it is a bug, but it's hard to be sure. It's so _blatantly_ wrong that it looks like it was done deliberately.

heh

I seem to remeber having a problem with the pm_runtime_put_sync() after drv->remove(dev) ...

So the code in question was introduced by

commit e1866b33b1e89f077b7132daae3dfd9a594e9a1a

Author: Rafael J. Wysocki <[email protected]>
Date:   Fri Apr 29 00:33:45 2011 +0200
Quoted 6 lines
Quoted 3 lines

PM / Runtime: Rework runtime PM handling during driver removal

with a long changelog explaining the reason why. Which seems to make sense. ;-)

Okay, that seems fair enough. Looks like the documentation needs to be updated to match, though.

Yes, it does.

Quoted 3 lines

And we probably still want to make sure that access to the power/control and related attribute files is mutually exclusive with probe and remove.

I agree.

Thanks,
Rafael

#31 lore raw
In reply to Alan Stern
Quoted 28 lines · Alan Stern
Quoted 26 lines · Rafael J. Wysocki

Hi,

Quoted 9 lines · Kevin Hilman
Quoted 7 lines · Alan Stern
Quoted 4 lines · Kevin Hilman

OK, so the ->probe() part has been explained and makes sense, but I would expect ->remove() to be similarily protected (as the documentation states.) But that is not the case. Is that a bug? If so, patch below makes the code match the documentation.

Quoted 4 lines
Quoted 2 lines

I suspect it is a bug, but it's hard to be sure. It's so _blatantly_ wrong that it looks like it was done deliberately.

heh

I seem to remeber having a problem with the pm_runtime_put_sync() after drv->remove(dev) ...

So the code in question was introduced by

commit e1866b33b1e89f077b7132daae3dfd9a594e9a1a

Author: Rafael J. Wysocki <[email protected]>
Date:   Fri Apr 29 00:33:45 2011 +0200
Quoted 6 lines
Quoted 3 lines

PM / Runtime: Rework runtime PM handling during driver removal

with a long changelog explaining the reason why. Which seems to make sense. ;-)

Okay, that seems fair enough. Looks like the documentation needs to be updated to match, though.

Yes, it does.

Quoted 3 lines

And we probably still want to make sure that access to the power/control and related attribute files is mutually exclusive with probe and remove.

I agree.

Thanks,
Rafael

#32 lore raw

PATCH 1/1 PM / Runtime: Update documentation regarding driver removal

In reply to Alan Stern

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

Commit e1866b33b1e89f077b7132daae3dfd9a594e9a1a (PM / Runtime: Rework runtime PM handling during driver removal) forgot to update the documentation in Documentation/power/runtime_pm.txt to match the new code in drivers/base/dd.c. Update that documentation to match the code it describes.

---
 Documentation/power/runtime_pm.txt |   26 +++++++++++++++++++++-----
 1 file changed, 21 insertions(+), 5 deletions(-)
Documentation/power/runtime_pm.txt +21 -5
Index: linux-2.6/Documentation/power/runtime_pm.txt
===================================================================
@@ -513,13 +513,29 @@ helper functions described in Section 4.
 should be used.  Of course, for this purpose the device's runtime PM has to be
 enabled earlier by calling pm_runtime_enable().
 
-If the device bus type's or driver's ->probe() or ->remove() callback runs
+If the device bus type's or driver's ->probe() callback runs
 pm_runtime_suspend() or pm_runtime_idle() or their asynchronous counterparts,
 they will fail returning -EAGAIN, because the device's usage counter is
-incremented by the core before executing ->probe() and ->remove().  Still, it
-may be desirable to suspend the device as soon as ->probe() or ->remove() has
-finished, so the PM core uses pm_runtime_put_sync() to invoke the
-subsystem-level idle callback for the device at that time.
+incremented by the driver core before executing ->probe().  Still, it may be
+desirable to suspend the device as soon as ->probe() has finished, so the driver
+core uses pm_runtime_put_sync() to invoke the subsystem-level idle callback for
+the device at that time.
+
+Moreover, the driver core prevents runtime PM callbacks from racing with the bus
+notifier callback in __device_release_driver(), which is necessary, because the
+notifier is used by some subsystems to carry out operations affecting the
+runtime PM functionality.  It does so by calling pm_runtime_get_sync() before
+driver_sysfs_remove() and the BUS_NOTIFY_UNBIND_DRIVER notifications.  This
+resumes the device if it's in the suspended state and prevents it from
+being suspended again while those routines are being executed.
+
+To allow bus types and drivers to put devices into the suspended state by
+calling pm_runtime_suspend() from their ->remove() routines, the driver core
+executes pm_runtime_put_sync() after running the BUS_NOTIFY_UNBIND_DRIVER
+notifications in __device_release_driver().  This requires bus types and
+drivers to make their ->remove() callbacks avoid races with runtime PM directly,
+but also it allows of more flexibility in the handling of devices during the
+removal of their drivers.
 
 The user space can effectively disallow the driver of the device to power manage
 it at run time by changing the value of its /sys/devices/.../power/control
author Reviewed-by on v1 1/1
#33 lore raw

Re: [PATCH] PM / Runtime: Update documentation regarding driver removal

Quoted 9 lines · Rafael J. Wysocki

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

Commit e1866b33b1e89f077b7132daae3dfd9a594e9a1a (PM / Runtime: Rework runtime PM handling during driver removal) forgot to update the documentation in Documentation/power/runtime_pm.txt to match the new code in drivers/base/dd.c. Update that documentation to match the code it describes.

Thanks, it's clear now.

Kevin

author Reviewed-by on v1 1/1
#34 lore raw

Re: [PATCH] PM / Runtime: Update documentation regarding driver removal

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

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

Commit e1866b33b1e89f077b7132daae3dfd9a594e9a1a (PM / Runtime: Rework runtime PM handling during driver removal) forgot to update the documentation in Documentation/power/runtime_pm.txt to match the new code in drivers/base/dd.c. Update that documentation to match the code it describes.

Thanks, it's clear now.

Kevin

#35 lore raw

PATCH 1/1 PM / Runtime: Update documentation regarding driver removal

In reply to Alan Stern

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

Commit e1866b33b1e89f077b7132daae3dfd9a594e9a1a (PM / Runtime: Rework runtime PM handling during driver removal) forgot to update the documentation in Documentation/power/runtime_pm.txt to match the new code in drivers/base/dd.c. Update that documentation to match the code it describes.

---
 Documentation/power/runtime_pm.txt |   26 +++++++++++++++++++++-----
 1 file changed, 21 insertions(+), 5 deletions(-)
Documentation/power/runtime_pm.txt +21 -5
Index: linux-2.6/Documentation/power/runtime_pm.txt
===================================================================
@@ -513,13 +513,29 @@ helper functions described in Section 4.
 should be used.  Of course, for this purpose the device's runtime PM has to be
 enabled earlier by calling pm_runtime_enable().
 
-If the device bus type's or driver's ->probe() or ->remove() callback runs
+If the device bus type's or driver's ->probe() callback runs
 pm_runtime_suspend() or pm_runtime_idle() or their asynchronous counterparts,
 they will fail returning -EAGAIN, because the device's usage counter is
-incremented by the core before executing ->probe() and ->remove().  Still, it
-may be desirable to suspend the device as soon as ->probe() or ->remove() has
-finished, so the PM core uses pm_runtime_put_sync() to invoke the
-subsystem-level idle callback for the device at that time.
+incremented by the driver core before executing ->probe().  Still, it may be
+desirable to suspend the device as soon as ->probe() has finished, so the driver
+core uses pm_runtime_put_sync() to invoke the subsystem-level idle callback for
+the device at that time.
+
+Moreover, the driver core prevents runtime PM callbacks from racing with the bus
+notifier callback in __device_release_driver(), which is necessary, because the
+notifier is used by some subsystems to carry out operations affecting the
+runtime PM functionality.  It does so by calling pm_runtime_get_sync() before
+driver_sysfs_remove() and the BUS_NOTIFY_UNBIND_DRIVER notifications.  This
+resumes the device if it's in the suspended state and prevents it from
+being suspended again while those routines are being executed.
+
+To allow bus types and drivers to put devices into the suspended state by
+calling pm_runtime_suspend() from their ->remove() routines, the driver core
+executes pm_runtime_put_sync() after running the BUS_NOTIFY_UNBIND_DRIVER
+notifications in __device_release_driver().  This requires bus types and
+drivers to make their ->remove() callbacks avoid races with runtime PM directly,
+but also it allows of more flexibility in the handling of devices during the
+removal of their drivers.
 
 The user space can effectively disallow the driver of the device to power manage
 it at run time by changing the value of its /sys/devices/.../power/control
#36 lore raw
In reply to Kevin Hilman

Hi,

Quoted 9 lines · Kevin Hilman
Quoted 7 lines · Alan Stern
Quoted 4 lines · Kevin Hilman

OK, so the ->probe() part has been explained and makes sense, but I would expect ->remove() to be similarily protected (as the documentation states.) But that is not the case. Is that a bug? If so, patch below makes the code match the documentation.

Quoted 4 lines
Quoted 2 lines

I suspect it is a bug, but it's hard to be sure. It's so _blatantly_ wrong that it looks like it was done deliberately.

heh

I seem to remeber having a problem with the pm_runtime_put_sync() after drv->remove(dev) ...

So the code in question was introduced by

commit e1866b33b1e89f077b7132daae3dfd9a594e9a1a

Author: Rafael J. Wysocki <[email protected]>
Date:   Fri Apr 29 00:33:45 2011 +0200

PM / Runtime: Rework runtime PM handling during driver removal

with a long changelog explaining the reason why. Which seems to make sense. ;-)

So I'm not sure.

Thanks,
Rafael

#37 lore raw
In reply to Kevin Hilman
Quoted 53 lines · Kevin Hilman

Continuing on the theme of runtime PM interactions with other parts of the driver core...

In drivers/base/dd.c:driver_probe_device(), the driver core increments the usage count around ->probe():

        [...]
	pm_runtime_get_noresume(dev);
	pm_runtime_barrier(dev);
	ret = really_probe(dev, drv);
	pm_runtime_put_sync(dev);

I'm not following the reason for this. On driver's I'm familar with, it's not until ->probe where pm_runtime_enable() is called. What is being protected against here?

These seem to exist since the introduction of the runtime PM core, but I can't find any explanation.

The documentation refers to the increment by the core, but not the reasons why:

If the device bus type's or driver's ->probe() or ->remove() callback runs pm_runtime_suspend() or pm_runtime_idle() or their asynchronous counterparts, they will fail returning -EAGAIN, because the device's usage counter is incremented by the core before executing ->probe() and ->remove(). Still, it may be desirable to suspend the device as soon as ->probe() or ->remove() has finished, so the PM core uses pm_runtime_idle_sync() to invoke the subsystem-level idle callback for the device at that time.

On a side note, the bit about -EAGAIN above is not accurate with today's code. For example, __pm_runtime_suspend() returns zero when the usage count decrement is non-zero, so callers can't currently know that doing a pm_runtime_suspend() or pm_runtime_put_sync() in their ->probe() actually didn't happen.

Another curiosity is that, contrary to the above documentation, there is no usage_count increment before the bus/driver ->remove() (although there is a _get_sync/_put_sync around the sysfs_remove and notifier just before the bus/driver->remove().

Also, below is a patch for a typo in the above Documentation exerpt.

Kevin

From 069484f8d2bb86473a271c27733e10fbfd410c2c Mon Sep 17 00:00:00 2001
From: Kevin Hilman <[email protected]>
Date: Thu, 30 Jun 2011 15:07:31 -0700
Subject: [PATCH] PM: Documentation: fix typo: pm_runtime_idle_sync() doesn't exist.

Quoted 4 lines

Replace reference to pm_runtime_idle_sync() in the driver core with pm_runtime_put_sync() which is used in the code.

Applied to suspend-2.6/linux-next.

Thanks,
Rafael

Quoted 18 lines
---
 Documentation/power/runtime_pm.txt |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)
Documentation/power/runtime_pm.txt +1 -1
index 22accb3..518d9be 100644
@@ -506,7 +506,7 @@ pm_runtime_suspend() or pm_runtime_idle() or their asynchronous counterparts,
 they will fail returning -EAGAIN, because the device's usage counter is
 incremented by the core before executing ->probe() and ->remove().  Still, it
 may be desirable to suspend the device as soon as ->probe() or ->remove() has
-finished, so the PM core uses pm_runtime_idle_sync() to invoke the
+finished, so the PM core uses pm_runtime_put_sync() to invoke the
 subsystem-level idle callback for the device at that time.
 
 The user space can effectively disallow the driver of the device to power manage
#38 lore raw
In reply to Kevin Hilman
Quoted 53 lines · Kevin Hilman

Continuing on the theme of runtime PM interactions with other parts of the driver core...

In drivers/base/dd.c:driver_probe_device(), the driver core increments the usage count around ->probe():

        [...]
	pm_runtime_get_noresume(dev);
	pm_runtime_barrier(dev);
	ret = really_probe(dev, drv);
	pm_runtime_put_sync(dev);

I'm not following the reason for this. On driver's I'm familar with, it's not until ->probe where pm_runtime_enable() is called. What is being protected against here?

These seem to exist since the introduction of the runtime PM core, but I can't find any explanation.

The documentation refers to the increment by the core, but not the reasons why:

If the device bus type's or driver's ->probe() or ->remove() callback runs pm_runtime_suspend() or pm_runtime_idle() or their asynchronous counterparts, they will fail returning -EAGAIN, because the device's usage counter is incremented by the core before executing ->probe() and ->remove(). Still, it may be desirable to suspend the device as soon as ->probe() or ->remove() has finished, so the PM core uses pm_runtime_idle_sync() to invoke the subsystem-level idle callback for the device at that time.

On a side note, the bit about -EAGAIN above is not accurate with today's code. For example, __pm_runtime_suspend() returns zero when the usage count decrement is non-zero, so callers can't currently know that doing a pm_runtime_suspend() or pm_runtime_put_sync() in their ->probe() actually didn't happen.

Another curiosity is that, contrary to the above documentation, there is no usage_count increment before the bus/driver ->remove() (although there is a _get_sync/_put_sync around the sysfs_remove and notifier just before the bus/driver->remove().

Also, below is a patch for a typo in the above Documentation exerpt.

Kevin

From 069484f8d2bb86473a271c27733e10fbfd410c2c Mon Sep 17 00:00:00 2001
From: Kevin Hilman <[email protected]>
Date: Thu, 30 Jun 2011 15:07:31 -0700
Subject: [PATCH] PM: Documentation: fix typo: pm_runtime_idle_sync() doesn't exist.

Quoted 4 lines

Replace reference to pm_runtime_idle_sync() in the driver core with pm_runtime_put_sync() which is used in the code.

Applied to suspend-2.6/linux-next.

Thanks,
Rafael

Quoted 18 lines
---
 Documentation/power/runtime_pm.txt |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)
Documentation/power/runtime_pm.txt +1 -1
index 22accb3..518d9be 100644
@@ -506,7 +506,7 @@ pm_runtime_suspend() or pm_runtime_idle() or their asynchronous counterparts,
 they will fail returning -EAGAIN, because the device's usage counter is
 incremented by the core before executing ->probe() and ->remove().  Still, it
 may be desirable to suspend the device as soon as ->probe() or ->remove() has
-finished, so the PM core uses pm_runtime_idle_sync() to invoke the
+finished, so the PM core uses pm_runtime_put_sync() to invoke the
 subsystem-level idle callback for the device at that time.
 
 The user space can effectively disallow the driver of the device to power manage