libertas: terminate scan when stopping interface
authorDaniel Drake <dsd@laptop.org>
Thu, 4 Nov 2010 21:21:52 +0000 (21:21 +0000)
committerJohn W. Linville <linville@tuxdriver.com>
Mon, 8 Nov 2010 21:53:47 +0000 (16:53 -0500)
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@laptop.org>
Acked-by: Dan Williams <dcbw@redhat.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
drivers/net/wireless/libertas/cfg.c
drivers/net/wireless/libertas/dev.h
drivers/net/wireless/libertas/main.c

index 5046a00..373930a 100644 (file)
@@ -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 */
index f062ed5..cb14c38 100644 (file)
@@ -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;
index 47ce5a6..46b88b1 100644 (file)
@@ -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;