2008-01-25 00:49:49

by Rafael J. Wysocki

[permalink] [raw]
Subject: [PATCH -mm 0/5] b43: Fix suspend/resume deadlock

Hi,

The following series of patches is intended to fix the suspend/resume deadlock
occuring as a result of unregistering device objects, locked by the PM core,
during suspend/resume cycles by the b43 driver.

In short, the b43 driver is modified to avoid unregistering device objects
during suspend/resume cycles except for the resume code path, in which the
devices are unregistered using the recently introduced suspend-safe method.
For this purpose, it is necessary to introduce the possibility to safely remove
misc devices, leds classdevs and hwrng devices during suspend/resume cycles
(patches 2/5, 4/5, 3/5, respectively).

Please consider for applying.

Thanks,
Rafael


2008-01-25 00:49:19

by Rafael J. Wysocki

[permalink] [raw]
Subject: [PATCH -mm 3/5] HWRNG: Add possibility to remove hwrng devices during suspend/resume

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

Make it possible to unregister a Hardware Random Number Generator
device object in a safe way during a suspend/resume cycle.

Signed-off-by: Rafael J. Wysocki <[email protected]>
Acked-by: Michael Buesch <[email protected]>
---
drivers/char/hw_random/core.c | 10 +++++-----
include/linux/hw_random.h | 10 +++++++++-
2 files changed, 14 insertions(+), 6 deletions(-)

Index: linux-2.6.24-rc8-mm1/drivers/char/hw_random/core.c
===================================================================
--- linux-2.6.24-rc8-mm1.orig/drivers/char/hw_random/core.c
+++ linux-2.6.24-rc8-mm1/drivers/char/hw_random/core.c
@@ -234,11 +234,11 @@ static DEVICE_ATTR(rng_available, S_IRUG
NULL);


-static void unregister_miscdev(void)
+static void unregister_miscdev(bool suspended)
{
device_remove_file(rng_miscdev.this_device, &dev_attr_rng_available);
device_remove_file(rng_miscdev.this_device, &dev_attr_rng_current);
- misc_deregister(&rng_miscdev);
+ __misc_deregister(&rng_miscdev, suspended);
}

static int register_miscdev(void)
@@ -313,7 +313,7 @@ out:
}
EXPORT_SYMBOL_GPL(hwrng_register);

-void hwrng_unregister(struct hwrng *rng)
+void __hwrng_unregister(struct hwrng *rng, bool suspended)
{
int err;

@@ -332,11 +332,11 @@ void hwrng_unregister(struct hwrng *rng)
}
}
if (list_empty(&rng_list))
- unregister_miscdev();
+ unregister_miscdev(suspended);

mutex_unlock(&rng_mutex);
}
-EXPORT_SYMBOL_GPL(hwrng_unregister);
+EXPORT_SYMBOL_GPL(__hwrng_unregister);


MODULE_DESCRIPTION("H/W Random Number Generator (RNG) driver");
Index: linux-2.6.24-rc8-mm1/include/linux/hw_random.h
===================================================================
--- linux-2.6.24-rc8-mm1.orig/include/linux/hw_random.h
+++ linux-2.6.24-rc8-mm1/include/linux/hw_random.h
@@ -44,7 +44,15 @@ struct hwrng {
/** Register a new Hardware Random Number Generator driver. */
extern int hwrng_register(struct hwrng *rng);
/** Unregister a Hardware Random Number Generator driver. */
-extern void hwrng_unregister(struct hwrng *rng);
+extern void __hwrng_unregister(struct hwrng *rng, bool suspended);
+static inline void hwrng_unregister(struct hwrng *rng)
+{
+ __hwrng_unregister(rng, false);
+}
+static inline void hwrng_unregister_suspended(struct hwrng *rng)
+{
+ __hwrng_unregister(rng, true);
+}

#endif /* __KERNEL__ */
#endif /* LINUX_HWRANDOM_H_ */

2008-01-25 00:49:34

by Rafael J. Wysocki

[permalink] [raw]
Subject: [PATCH -mm 2/5] Misc: Add possibility to remove misc devices during suspend/resume

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

Make it possible to unregister a misc device object in a safe way
during a suspend/resume cycle.

Signed-off-by: Rafael J. Wysocki <[email protected]>
---
drivers/char/misc.c | 13 +++++++++----
include/linux/miscdevice.h | 10 +++++++++-
2 files changed, 18 insertions(+), 5 deletions(-)

Index: linux-2.6.24-rc8-mm1/include/linux/miscdevice.h
===================================================================
--- linux-2.6.24-rc8-mm1.orig/include/linux/miscdevice.h
+++ linux-2.6.24-rc8-mm1/include/linux/miscdevice.h
@@ -43,7 +43,15 @@ struct miscdevice {
};

extern int misc_register(struct miscdevice * misc);
-extern int misc_deregister(struct miscdevice * misc);
+extern int __misc_deregister(struct miscdevice *misc, bool suspended);
+static inline int misc_deregister(struct miscdevice *misc)
+{
+ return __misc_deregister(misc, false);
+}
+static inline int misc_deregister_suspended(struct miscdevice *misc)
+{
+ return __misc_deregister(misc, true);
+}

#define MODULE_ALIAS_MISCDEV(minor) \
MODULE_ALIAS("char-major-" __stringify(MISC_MAJOR) \
Index: linux-2.6.24-rc8-mm1/drivers/char/misc.c
===================================================================
--- linux-2.6.24-rc8-mm1.orig/drivers/char/misc.c
+++ linux-2.6.24-rc8-mm1/drivers/char/misc.c
@@ -232,8 +232,9 @@ int misc_register(struct miscdevice * mi
}

/**
- * misc_deregister - unregister a miscellaneous device
+ * __misc_deregister - unregister a miscellaneous device
* @misc: device to unregister
+ * @suspended: to be set if the function is used during suspend/resume
*
* Unregister a miscellaneous device that was previously
* successfully registered with misc_register(). Success
@@ -241,7 +242,7 @@ int misc_register(struct miscdevice * mi
* indicates an error.
*/

-int misc_deregister(struct miscdevice * misc)
+int __misc_deregister(struct miscdevice *misc, bool suspended)
{
int i = misc->minor;

@@ -250,7 +251,11 @@ int misc_deregister(struct miscdevice *

mutex_lock(&misc_mtx);
list_del(&misc->list);
- device_destroy(misc_class, MKDEV(MISC_MAJOR, misc->minor));
+ if (suspended)
+ destroy_suspended_device(misc_class,
+ MKDEV(MISC_MAJOR, misc->minor));
+ else
+ device_destroy(misc_class, MKDEV(MISC_MAJOR, misc->minor));
if (i < DYNAMIC_MINORS && i>0) {
misc_minors[i>>3] &= ~(1 << (misc->minor & 7));
}
@@ -259,7 +264,7 @@ int misc_deregister(struct miscdevice *
}

EXPORT_SYMBOL(misc_register);
-EXPORT_SYMBOL(misc_deregister);
+EXPORT_SYMBOL(__misc_deregister);

static int __init misc_init(void)
{

2008-01-25 00:50:38

by Rafael J. Wysocki

[permalink] [raw]
Subject: [PATCH -mm 5/5] b43: Avoid unregistering device objects during suspend

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

Modify the b43 driver to avoid deadlocking suspend and resume,
which happens as a result of attempting to unregister device objects
locked by the PM core during suspend/resume cycles. Also, make it
use a suspend-safe method of unregistering device object in the
resume error path.

Signed-off-by: Rafael J. Wysocki <[email protected]>
Acked-by: Michael Buesch <[email protected]>
---
drivers/net/wireless/b43/b43.h | 1 +
drivers/net/wireless/b43/leds.c | 5 ++++-
drivers/net/wireless/b43/main.c | 25 ++++++++++++++++---------
3 files changed, 21 insertions(+), 10 deletions(-)

Index: linux-2.6.24-rc8-mm1/drivers/net/wireless/b43/b43.h
===================================================================
--- linux-2.6.24-rc8-mm1.orig/drivers/net/wireless/b43/b43.h
+++ linux-2.6.24-rc8-mm1/drivers/net/wireless/b43/b43.h
@@ -706,6 +706,7 @@ struct b43_wldev {
bool short_preamble; /* TRUE, if short preamble is enabled. */
bool short_slot; /* TRUE, if short slot timing is enabled. */
bool radio_hw_enable; /* saved state of radio hardware enabled state */
+ bool suspend_in_progress; /* TRUE, if we are in a suspend/resume cycle */

/* PHY/Radio device. */
struct b43_phy phy;
Index: linux-2.6.24-rc8-mm1/drivers/net/wireless/b43/main.c
===================================================================
--- linux-2.6.24-rc8-mm1.orig/drivers/net/wireless/b43/main.c
+++ linux-2.6.24-rc8-mm1/drivers/net/wireless/b43/main.c
@@ -2470,10 +2470,10 @@ static int b43_rng_read(struct hwrng *rn
return (sizeof(u16));
}

-static void b43_rng_exit(struct b43_wl *wl)
+static void b43_rng_exit(struct b43_wl *wl, bool suspended)
{
if (wl->rng_initialized)
- hwrng_unregister(&wl->rng);
+ __hwrng_unregister(&wl->rng, suspended);
}

static int b43_rng_init(struct b43_wl *wl)
@@ -3298,8 +3298,10 @@ static void b43_wireless_core_exit(struc
return;
b43_set_status(dev, B43_STAT_UNINIT);

- b43_leds_exit(dev);
- b43_rng_exit(dev->wl);
+ if (!dev->suspend_in_progress) {
+ b43_leds_exit(dev);
+ b43_rng_exit(dev->wl, false);
+ }
b43_pio_free(dev);
b43_dma_free(dev);
b43_chip_exit(dev);
@@ -3420,11 +3422,13 @@ static int b43_wireless_core_init(struct
memset(wl->mac_addr, 0, ETH_ALEN);
b43_upload_card_macaddress(dev);
b43_security_init(dev);
- b43_rng_init(wl);
+ if (!dev->suspend_in_progress)
+ b43_rng_init(wl);

b43_set_status(dev, B43_STAT_INITIALIZED);

- b43_leds_init(dev);
+ if (!dev->suspend_in_progress)
+ b43_leds_init(dev);
out:
return err;

@@ -4024,6 +4028,7 @@ static int b43_suspend(struct ssb_device
b43dbg(wl, "Suspending...\n");

mutex_lock(&wl->mutex);
+ wldev->suspend_in_progress = true;
wldev->suspend_init_status = b43_status(wldev);
if (wldev->suspend_init_status >= B43_STAT_STARTED)
b43_wireless_core_stop(wldev);
@@ -4055,15 +4060,17 @@ static int b43_resume(struct ssb_device
if (wldev->suspend_init_status >= B43_STAT_STARTED) {
err = b43_wireless_core_start(wldev);
if (err) {
+ b43_leds_exit(wldev);
+ b43_rng_exit(wldev->wl, true);
b43_wireless_core_exit(wldev);
b43err(wl, "Resume failed at core start\n");
goto out;
}
}
- mutex_unlock(&wl->mutex);
-
b43dbg(wl, "Device resumed.\n");
- out:
+ out:
+ wldev->suspend_in_progress = false;
+ mutex_unlock(&wl->mutex);
return err;
}

Index: linux-2.6.24-rc8-mm1/drivers/net/wireless/b43/leds.c
===================================================================
--- linux-2.6.24-rc8-mm1.orig/drivers/net/wireless/b43/leds.c
+++ linux-2.6.24-rc8-mm1/drivers/net/wireless/b43/leds.c
@@ -116,7 +116,10 @@ static void b43_unregister_led(struct b4
{
if (!led->dev)
return;
- led_classdev_unregister(&led->led_dev);
+ if (led->dev->suspend_in_progress)
+ led_classdev_unregister_suspended(&led->led_dev);
+ else
+ led_classdev_unregister(&led->led_dev);
b43_led_turn_off(led->dev, led->index, led->activelow);
led->dev = NULL;
}

2008-01-25 00:50:53

by Rafael J. Wysocki

[permalink] [raw]
Subject: [PATCH -mm 1/5] PM: Export device_pm_schedule_removal

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

Move the declaration of device_pm_schedule_removal() to device.h
and make it exported, as it will be used directly by some drivers
for unregistering device objects during suspend/resume cycles in a
safe way.

Signed-off-by: Rafael J. Wysocki <[email protected]>
---
drivers/base/power/main.c | 1 +
drivers/base/power/power.h | 1 -
include/linux/device.h | 6 ++++++
3 files changed, 7 insertions(+), 1 deletion(-)

Index: linux-2.6.24-rc8-mm1/drivers/base/power/main.c
===================================================================
--- linux-2.6.24-rc8-mm1.orig/drivers/base/power/main.c
+++ linux-2.6.24-rc8-mm1/drivers/base/power/main.c
@@ -129,6 +129,7 @@ void device_pm_schedule_removal(struct d
list_move_tail(&dev->power.entry, &dpm_destroy);
mutex_unlock(&dpm_list_mtx);
}
+EXPORT_SYMBOL_GPL(device_pm_schedule_removal);

/**
* pm_sleep_lock - mutual exclusion for registration and suspend
Index: linux-2.6.24-rc8-mm1/include/linux/device.h
===================================================================
--- linux-2.6.24-rc8-mm1.orig/include/linux/device.h
+++ linux-2.6.24-rc8-mm1/include/linux/device.h
@@ -532,11 +532,17 @@ extern struct device *device_create(stru
extern void device_destroy(struct class *cls, dev_t devt);
#ifdef CONFIG_PM_SLEEP
extern void destroy_suspended_device(struct class *cls, dev_t devt);
+extern void device_pm_schedule_removal(struct device *);
#else /* !CONFIG_PM_SLEEP */
static inline void destroy_suspended_device(struct class *cls, dev_t devt)
{
device_destroy(cls, devt);
}
+
+static inline void device_pm_schedule_removal(struct device *dev)
+{
+ device_unregister(dev);
+}
#endif /* !CONFIG_PM_SLEEP */

/*
Index: linux-2.6.24-rc8-mm1/drivers/base/power/power.h
===================================================================
--- linux-2.6.24-rc8-mm1.orig/drivers/base/power/power.h
+++ linux-2.6.24-rc8-mm1/drivers/base/power/power.h
@@ -13,7 +13,6 @@ static inline struct device *to_device(s

extern void device_pm_add(struct device *);
extern void device_pm_remove(struct device *);
-extern void device_pm_schedule_removal(struct device *);
extern int pm_sleep_lock(void);
extern void pm_sleep_unlock(void);

2008-01-25 00:51:16

by Rafael J. Wysocki

[permalink] [raw]
Subject: [PATCH -mm 4/5] Leds: Add possibility to remove leds classdevs during suspend/resume

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

Make it possible to unregister a led classdev object in a safe way
during a suspend/resume cycle.

Signed-off-by: Rafael J. Wysocki <[email protected]>
---
drivers/leds/led-class.c | 13 +++++++++----
include/linux/leds.h | 10 +++++++++-
2 files changed, 18 insertions(+), 5 deletions(-)

Index: linux-2.6.24-rc8-mm1/drivers/leds/led-class.c
===================================================================
--- linux-2.6.24-rc8-mm1.orig/drivers/leds/led-class.c
+++ linux-2.6.24-rc8-mm1/drivers/leds/led-class.c
@@ -137,12 +137,14 @@ err_out:
EXPORT_SYMBOL_GPL(led_classdev_register);

/**
- * led_classdev_unregister - unregisters a object of led_properties class.
+ * __led_classdev_unregister - unregisters a object of led_properties class.
* @led_cdev: the led device to unregister
+ * @suspended: indicates whether system-wide suspend or resume is in progress
*
* Unregisters a previously registered via led_classdev_register object.
*/
-void led_classdev_unregister(struct led_classdev *led_cdev)
+void __led_classdev_unregister(struct led_classdev *led_cdev,
+ bool suspended)
{
device_remove_file(led_cdev->dev, &dev_attr_brightness);
#ifdef CONFIG_LEDS_TRIGGERS
@@ -153,13 +155,16 @@ void led_classdev_unregister(struct led_
up_write(&led_cdev->trigger_lock);
#endif

- device_unregister(led_cdev->dev);
+ if (suspended)
+ device_pm_schedule_removal(led_cdev->dev);
+ else
+ device_unregister(led_cdev->dev);

down_write(&leds_list_lock);
list_del(&led_cdev->node);
up_write(&leds_list_lock);
}
-EXPORT_SYMBOL_GPL(led_classdev_unregister);
+EXPORT_SYMBOL_GPL(__led_classdev_unregister);

static int __init leds_init(void)
{
Index: linux-2.6.24-rc8-mm1/include/linux/leds.h
===================================================================
--- linux-2.6.24-rc8-mm1.orig/include/linux/leds.h
+++ linux-2.6.24-rc8-mm1/include/linux/leds.h
@@ -59,7 +59,15 @@ struct led_classdev {

extern int led_classdev_register(struct device *parent,
struct led_classdev *led_cdev);
-extern void led_classdev_unregister(struct led_classdev *led_cdev);
+extern void __led_classdev_unregister(struct led_classdev *led_cdev, bool sus);
+static inline void led_classdev_unregister(struct led_classdev *lcd)
+{
+ __led_classdev_unregister(lcd, false);
+}
+static inline void led_classdev_unregister_suspended(struct led_classdev *lcd)
+{
+ __led_classdev_unregister(lcd, true);
+}
extern void led_classdev_suspend(struct led_classdev *led_cdev);
extern void led_classdev_resume(struct led_classdev *led_cdev);

2008-01-25 08:00:34

by Pavel Machek

[permalink] [raw]
Subject: Re: [PATCH -mm 1/5] PM: Export device_pm_schedule_removal

On Fri 2008-01-25 01:30:25, Rafael J. Wysocki wrote:
> From: Rafael J. Wysocki <[email protected]>
>
> Move the declaration of device_pm_schedule_removal() to device.h
> and make it exported, as it will be used directly by some drivers
> for unregistering device objects during suspend/resume cycles in a
> safe way.
>
> Signed-off-by: Rafael J. Wysocki <[email protected]>

ACK.

--
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

2008-01-25 08:01:01

by Pavel Machek

[permalink] [raw]
Subject: Re: [PATCH -mm 5/5] b43: Avoid unregistering device objects during suspend

On Fri 2008-01-25 01:37:33, Rafael J. Wysocki wrote:
> From: Rafael J. Wysocki <[email protected]>
>
> Modify the b43 driver to avoid deadlocking suspend and resume,
> which happens as a result of attempting to unregister device objects
> locked by the PM core during suspend/resume cycles. Also, make it
> use a suspend-safe method of unregistering device object in the
> resume error path.
>
> Signed-off-by: Rafael J. Wysocki <[email protected]>
> Acked-by: Michael Buesch <[email protected]>

Maybe we should have global suspend_in_progress (or maybe system_state
== suspending?) and automatically switch to schedule_removal() while
it is set?

--
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

2008-01-25 10:15:38

by Michael Büsch

[permalink] [raw]
Subject: Re: [PATCH -mm 5/5] b43: Avoid unregistering device objects during suspend

On Friday 25 January 2008 08:47:46 Pavel Machek wrote:
> On Fri 2008-01-25 01:37:33, Rafael J. Wysocki wrote:
> > From: Rafael J. Wysocki <[email protected]>
> >
> > Modify the b43 driver to avoid deadlocking suspend and resume,
> > which happens as a result of attempting to unregister device objects
> > locked by the PM core during suspend/resume cycles. Also, make it
> > use a suspend-safe method of unregistering device object in the
> > resume error path.
> >
> > Signed-off-by: Rafael J. Wysocki <[email protected]>
> > Acked-by: Michael Buesch <[email protected]>
>
> Maybe we should have global suspend_in_progress (or maybe system_state
> == suspending?) and automatically switch to schedule_removal() while
> it is set?
>

That would be great, from my perspective :)

--
Greetings Michael.

2008-01-25 11:47:52

by Rafael J. Wysocki

[permalink] [raw]
Subject: Re: [PATCH -mm 5/5] b43: Avoid unregistering device objects during suspend

On Friday, 25 of January 2008, Michael Buesch wrote:
> On Friday 25 January 2008 08:47:46 Pavel Machek wrote:
> > On Fri 2008-01-25 01:37:33, Rafael J. Wysocki wrote:
> > > From: Rafael J. Wysocki <[email protected]>
> > >
> > > Modify the b43 driver to avoid deadlocking suspend and resume,
> > > which happens as a result of attempting to unregister device objects
> > > locked by the PM core during suspend/resume cycles. Also, make it
> > > use a suspend-safe method of unregistering device object in the
> > > resume error path.
> > >
> > > Signed-off-by: Rafael J. Wysocki <[email protected]>
> > > Acked-by: Michael Buesch <[email protected]>
> >
> > Maybe we should have global suspend_in_progress (or maybe system_state
> > == suspending?) and automatically switch to schedule_removal() while
> > it is set?
> >
>
> That would be great, from my perspective :)

Let's see how many drivers are going to need that. If there's more than a
couple, it will certainly make sense to have a global variable like this.

Thanks,
Rafael

2008-01-25 14:58:19

by Alan Stern

[permalink] [raw]
Subject: Re: [PATCH -mm 5/5] b43: Avoid unregistering device objects during suspend

On Fri, 25 Jan 2008, Pavel Machek wrote:

> Maybe we should have global suspend_in_progress (or maybe system_state
> == suspending?) and automatically switch to schedule_removal() while
> it is set?

:-) There was a time a couple of years ago when you objected violently
to the mere suggestion of such a global variable!

It's not a bad idea IMO. But if it does get implemented, a global
function would be better than a global variable. It would provide
more encapsulation.

Alan Stern

2008-01-25 21:16:17

by Pavel Machek

[permalink] [raw]
Subject: Re: [PATCH -mm 5/5] b43: Avoid unregistering device objects during suspend

On Fri 2008-01-25 09:58:00, Alan Stern wrote:
> On Fri, 25 Jan 2008, Pavel Machek wrote:
>
> > Maybe we should have global suspend_in_progress (or maybe system_state
> > == suspending?) and automatically switch to schedule_removal() while
> > it is set?
>
> :-) There was a time a couple of years ago when you objected violently
> to the mere suggestion of such a global variable!

Lets say I was young at stupid...? ;-).

> It's not a bad idea IMO. But if it does get implemented, a global
> function would be better than a global variable. It would provide
> more encapsulation.

Agreed.
Pavel

--
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html

2008-01-28 18:02:19

by Greg KH

[permalink] [raw]
Subject: patch pm-export-device_pm_schedule_removal.patch added to gregkh-2.6 tree


This is a note to let you know that I've just added the patch titled

Subject: PM: Export device_pm_schedule_removal

to my gregkh-2.6 tree. Its filename is

pm-export-device_pm_schedule_removal.patch

This tree can be found at
http://www.kernel.org/pub/linux/kernel/people/gregkh/gregkh-2.6/patches/


>From [email protected] Mon Jan 28 08:57:01 2008
From: "Rafael J. Wysocki" <[email protected]>
Date: Fri, 25 Jan 2008 01:30:25 +0100
Subject: PM: Export device_pm_schedule_removal
To: Andrew Morton <[email protected]>
Cc: Michael Buesch <[email protected]>, pm list <[email protected]>, Alan Stern <[email protected]>, Len Brown <[email protected]>, LKML <[email protected]>, Pavel Machek <[email protected]>, [email protected], Alessandro Rubini <[email protected]>, Richard Purdie <[email protected]>, Greg KH <[email protected]>
Message-ID: <[email protected]>
Content-Disposition: inline


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

Move the declaration of device_pm_schedule_removal() to device.h
and make it exported, as it will be used directly by some drivers
for unregistering device objects during suspend/resume cycles in a
safe way.

Signed-off-by: Rafael J. Wysocki <[email protected]>
Acked-by: Pavel Machek <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>

---
drivers/base/power/main.c | 1 +
drivers/base/power/power.h | 1 -
include/linux/device.h | 6 ++++++
3 files changed, 7 insertions(+), 1 deletion(-)

--- a/drivers/base/power/main.c
+++ b/drivers/base/power/main.c
@@ -129,6 +129,7 @@ void device_pm_schedule_removal(struct d
list_move_tail(&dev->power.entry, &dpm_destroy);
mutex_unlock(&dpm_list_mtx);
}
+EXPORT_SYMBOL_GPL(device_pm_schedule_removal);

/**
* pm_sleep_lock - mutual exclusion for registration and suspend
--- a/drivers/base/power/power.h
+++ b/drivers/base/power/power.h
@@ -13,7 +13,6 @@ static inline struct device *to_device(s

extern void device_pm_add(struct device *);
extern void device_pm_remove(struct device *);
-extern void device_pm_schedule_removal(struct device *);
extern int pm_sleep_lock(void);
extern void pm_sleep_unlock(void);

--- a/include/linux/device.h
+++ b/include/linux/device.h
@@ -534,11 +534,17 @@ extern struct device *device_create(stru
extern void device_destroy(struct class *cls, dev_t devt);
#ifdef CONFIG_PM_SLEEP
extern void destroy_suspended_device(struct class *cls, dev_t devt);
+extern void device_pm_schedule_removal(struct device *);
#else /* !CONFIG_PM_SLEEP */
static inline void destroy_suspended_device(struct class *cls, dev_t devt)
{
device_destroy(cls, devt);
}
+
+static inline void device_pm_schedule_removal(struct device *dev)
+{
+ device_unregister(dev);
+}
#endif /* !CONFIG_PM_SLEEP */

/*


Patches currently in gregkh-2.6 which might be from [email protected] are

driver/pm-export-device_pm_schedule_removal.patch