On Monday, 21 of January 2008, Michael Buesch wrote: > On Monday 21 January 2008, Rafael J. Wysocki wrote: [--snip--] > > > Index: linux-2.6.24-rc8-mm1/drivers/net/wireless/b43/leds.h > > =================================================================== > > --- linux-2.6.24-rc8-mm1.orig/drivers/net/wireless/b43/leds.h > > +++ linux-2.6.24-rc8-mm1/drivers/net/wireless/b43/leds.h > > @@ -43,8 +43,15 @@ enum b43_led_behaviour { > > }; > > > > void b43_leds_init(struct b43_wldev *dev); > > -void b43_leds_exit(struct b43_wldev *dev); > > - > > +void __b43_leds_exit(struct b43_wldev *dev, bool suspended); > > +static inline void b43_leds_exit(struct b43_wldev *dev) > > +{ > > + __b43_leds_exit(dev, false); > > +} > > +static inline void b43_leds_resume_exit(struct b43_wldev *dev) > > +{ > > + __b43_leds_exit(dev, true); > > +} > > I still don't like this function wrapping. > I'm pretty sure the additional parameter to the function is not > needed. We can check dev->suspend_in_progress to find out > if we are in a up/down or in a suspend/resume cycle. You're right, I overlooked that. > > -static void b43_unregister_led(struct b43_led *led) > > +static void b43_unregister_led(struct b43_led *led, bool suspended) > > { > > if (!led->dev) > > return; > > - led_classdev_unregister(&led->led_dev); > > + if (suspended) > > You can check led->dev->suspend_in_progress here. > > > + 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; > > } > > @@ -230,10 +233,10 @@ void b43_leds_init(struct b43_wldev *dev > > } > > } > > > > -void b43_leds_exit(struct b43_wldev *dev) > > +void __b43_leds_exit(struct b43_wldev *dev, bool suspended) > > { > > - b43_unregister_led(&dev->led_tx); > > - b43_unregister_led(&dev->led_rx); > > - b43_unregister_led(&dev->led_assoc); > > - b43_unregister_led(&dev->led_radio); > > + b43_unregister_led(&dev->led_tx, suspended); > > + b43_unregister_led(&dev->led_rx, suspended); > > + b43_unregister_led(&dev->led_assoc, suspended); > > + b43_unregister_led(&dev->led_radio, suspended); > > } > > Don't need this hunk. Check led->dev->suspend_in_progress in > b43_unregister_led. > > > #endif /* __KERNEL__ */ > > #endif /* LINUX_HWRANDOM_H_ */ > > 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; > > Please add a comment like: /* TRUE, if we are in a suspend/resume cycle */ Sure, I just didn't know what to write in the comment. :-) Revised patch below, please have a look. Thanks, Rafael --- drivers/base/power/main.c | 1 + drivers/base/power/power.h | 1 - drivers/char/hw_random/core.c | 10 +++++----- drivers/char/misc.c | 13 +++++++++---- drivers/leds/led-class.c | 13 +++++++++---- drivers/net/wireless/b43/b43.h | 1 + drivers/net/wireless/b43/leds.c | 5 ++++- drivers/net/wireless/b43/main.c | 25 ++++++++++++++++--------- include/linux/device.h | 6 ++++++ include/linux/hw_random.h | 10 +++++++++- include/linux/leds.h | 10 +++++++++- include/linux/miscdevice.h | 10 +++++++++- 12 files changed, 78 insertions(+), 27 deletions(-) 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; } 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); 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); 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) { 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/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_ */ 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; _______________________________________________ linux-pm mailing list linux-pm@xxxxxxxxxxxxxxxxxxxxxxxxxx https://lists.linux-foundation.org/mailman/listinfo/linux-pm