mwifiex: abort scan while cancelling pending command
authorAmitkumar Karwar <akarwar@marvell.com>
Fri, 28 Feb 2014 03:35:15 +0000 (19:35 -0800)
committerJohn W. Linville <linville@tuxdriver.com>
Fri, 28 Feb 2014 19:33:41 +0000 (14:33 -0500)
mwifiex_cancel_pending_ioctl() and
mwifiex_cancel_all_pending_cmd() are called in command timeout
and driver unload paths respectively.
If scan operation is in progress, we should abort it smoothly.

Reported-by: Tim Shepard <shep@alum.mit.edu>
Signed-off-by: Amitkumar Karwar <akarwar@marvell.com>
Signed-off-by: Bing Zhao <bzhao@marvell.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
drivers/net/wireless/mwifiex/cmdevt.c

index 64e708b79f0e40f3bd70c672efca8c028a954b7e..58cf3a98f1f74ed19117fa9dbd64581e6bf7db04 100644 (file)
@@ -966,7 +966,9 @@ void
 mwifiex_cancel_all_pending_cmd(struct mwifiex_adapter *adapter)
 {
        struct cmd_ctrl_node *cmd_node = NULL, *tmp_node;
-       unsigned long flags;
+       unsigned long flags, cmd_flags;
+       struct mwifiex_private *priv;
+       int i;
 
        /* Cancel current cmd */
        if ((adapter->curr_cmd) && (adapter->curr_cmd->wait_q_enabled)) {
@@ -1006,9 +1008,21 @@ mwifiex_cancel_all_pending_cmd(struct mwifiex_adapter *adapter)
        }
        spin_unlock_irqrestore(&adapter->scan_pending_q_lock, flags);
 
-       spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags);
-       adapter->scan_processing = false;
-       spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags);
+       if (adapter->scan_processing) {
+               spin_lock_irqsave(&adapter->mwifiex_cmd_lock, cmd_flags);
+               adapter->scan_processing = false;
+               spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, cmd_flags);
+               for (i = 0; i < adapter->priv_num; i++) {
+                       priv = adapter->priv[i];
+                       if (!priv)
+                               continue;
+                       if (priv->scan_request) {
+                               dev_dbg(adapter->dev, "info: aborting scan\n");
+                               cfg80211_scan_done(priv->scan_request, 1);
+                               priv->scan_request = NULL;
+                       }
+               }
+       }
 }
 
 /*
@@ -1027,7 +1041,8 @@ mwifiex_cancel_pending_ioctl(struct mwifiex_adapter *adapter)
        struct cmd_ctrl_node *cmd_node = NULL, *tmp_node = NULL;
        unsigned long cmd_flags;
        unsigned long scan_pending_q_flags;
-       bool cancel_scan_cmd = false;
+       struct mwifiex_private *priv;
+       int i;
 
        if ((adapter->curr_cmd) &&
            (adapter->curr_cmd->wait_q_enabled)) {
@@ -1053,15 +1068,24 @@ mwifiex_cancel_pending_ioctl(struct mwifiex_adapter *adapter)
                mwifiex_insert_cmd_to_free_q(adapter, cmd_node);
                spin_lock_irqsave(&adapter->scan_pending_q_lock,
                                  scan_pending_q_flags);
-               cancel_scan_cmd = true;
        }
        spin_unlock_irqrestore(&adapter->scan_pending_q_lock,
                               scan_pending_q_flags);
 
-       if (cancel_scan_cmd) {
+       if (adapter->scan_processing) {
                spin_lock_irqsave(&adapter->mwifiex_cmd_lock, cmd_flags);
                adapter->scan_processing = false;
                spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, cmd_flags);
+               for (i = 0; i < adapter->priv_num; i++) {
+                       priv = adapter->priv[i];
+                       if (!priv)
+                               continue;
+                       if (priv->scan_request) {
+                               dev_dbg(adapter->dev, "info: aborting scan\n");
+                               cfg80211_scan_done(priv->scan_request, 1);
+                               priv->scan_request = NULL;
+                       }
+               }
        }
        adapter->cmd_wait_q.status = -1;
 }