Re: b43_suspend problem

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Monday 21 January 2008, Rafael J. Wysocki wrote:
> I modified the patch to implement something like this.  This still is one big
> patch against everything what's necessary.  [BTW, in the current version
> of the code, b43_resume() may leave wl->mutex locked in the error paths,
> which also is fixed by the patch.]

Whoopsy, thanks for catching this.

> 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_resume_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;
>  }
>

This part looks OK.

> 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.

> -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 */

I like comments. Can never have enough of them. _Especially_ for data structures. :)
_______________________________________________
linux-pm mailing list
linux-pm@xxxxxxxxxxxxxxxxxxxxxxxxxx
https://lists.linux-foundation.org/mailman/listinfo/linux-pm

[Index of Archives]     [Linux ACPI]     [Netdev]     [Ethernet Bridging]     [Linux Wireless]     [CPU Freq]     [Kernel Newbies]     [Fedora Kernel]     [Security]     [Linux for Hams]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux RAID]     [Linux Admin]     [Samba]

  Powered by Linux