[PATCH] libertas: terminate scan when stopping interface

Sven Neumann s.neumann at raumfeld.com
Mon Nov 15 08:12:21 EST 2010


We have successfully tested this patch on Linux 2.6.36 on an ARM device
using an 8686 chip connected over SDIO. It fixes a crash that we have
been observing occasionally during suspend/resume.

On Sun, 2010-10-31 at 17:47 +0000, Daniel Drake wrote:
> There are currently no provisions in place to ensure that the scanning
> task has been stopped when the interface is stopped or removed.
> 
> This can result in a WARNING at net/wireless/core.c:643 and other badness
> when you remove the module while a scan is happening.
> 
> Terminate the scanning task during interface stop.
> 
> Signed-off-by: Daniel Drake <dsd at laptop.org>
> ---
>  drivers/net/wireless/libertas/cfg.c  |    5 +++--
>  drivers/net/wireless/libertas/dev.h  |    1 +
>  drivers/net/wireless/libertas/main.c |    7 +++++++
>  3 files changed, 11 insertions(+), 2 deletions(-)

Tested-by: Sven Neumann <s.neumann at raumfeld.com>

> diff --git a/drivers/net/wireless/libertas/cfg.c b/drivers/net/wireless/libertas/cfg.c
> index 5046a00..373930a 100644
> --- a/drivers/net/wireless/libertas/cfg.c
> +++ b/drivers/net/wireless/libertas/cfg.c
> @@ -700,8 +700,9 @@ static void lbs_scan_worker(struct work_struct *work)
>  
>  	if (priv->scan_channel < priv->scan_req->n_channels) {
>  		cancel_delayed_work(&priv->scan_work);
> -		queue_delayed_work(priv->work_thread, &priv->scan_work,
> -			msecs_to_jiffies(300));
> +		if (!priv->stopping)
> +			queue_delayed_work(priv->work_thread, &priv->scan_work,
> +				msecs_to_jiffies(300));
>  	}
>  
>  	/* This is the final data we are about to send */
> diff --git a/drivers/net/wireless/libertas/dev.h b/drivers/net/wireless/libertas/dev.h
> index f062ed5..cb14c38 100644
> --- a/drivers/net/wireless/libertas/dev.h
> +++ b/drivers/net/wireless/libertas/dev.h
> @@ -36,6 +36,7 @@ struct lbs_private {
>  	/* CFG80211 */
>  	struct wireless_dev *wdev;
>  	bool wiphy_registered;
> +	bool stopping;
>  	struct cfg80211_scan_request *scan_req;
>  	u8 assoc_bss[ETH_ALEN];
>  	u8 disassoc_reason;
> diff --git a/drivers/net/wireless/libertas/main.c b/drivers/net/wireless/libertas/main.c
> index 47ce5a6..46b88b1 100644
> --- a/drivers/net/wireless/libertas/main.c
> +++ b/drivers/net/wireless/libertas/main.c
> @@ -104,6 +104,7 @@ static int lbs_dev_open(struct net_device *dev)
>  	lbs_deb_enter(LBS_DEB_NET);
>  
>  	spin_lock_irq(&priv->driver_lock);
> +	priv->stopping = false;
>  
>  	if (priv->connect_status == LBS_CONNECTED)
>  		netif_carrier_on(dev);
> @@ -131,10 +132,16 @@ static int lbs_eth_stop(struct net_device *dev)
>  	lbs_deb_enter(LBS_DEB_NET);
>  
>  	spin_lock_irq(&priv->driver_lock);
> +	priv->stopping = true;
>  	netif_stop_queue(dev);
>  	spin_unlock_irq(&priv->driver_lock);
>  
>  	schedule_work(&priv->mcast_work);
> +	cancel_delayed_work_sync(&priv->scan_work);
> +	if (priv->scan_req) {
> +		cfg80211_scan_done(priv->scan_req, false);
> +		priv->scan_req = NULL;
> +	}
>  
>  	lbs_deb_leave(LBS_DEB_NET);
>  	return 0;





More information about the libertas-dev mailing list