|
@@ -118,6 +118,11 @@ static void iwl_process_scan_complete(struct iwl_priv *priv)
|
|
|
{
|
|
|
bool aborted;
|
|
|
|
|
|
+ lockdep_assert_held(&priv->shrd->mutex);
|
|
|
+
|
|
|
+ if (!test_and_clear_bit(STATUS_SCAN_COMPLETE, &priv->shrd->status))
|
|
|
+ return;
|
|
|
+
|
|
|
IWL_DEBUG_SCAN(priv, "Completed scan.\n");
|
|
|
|
|
|
cancel_delayed_work(&priv->scan_check);
|
|
@@ -181,6 +186,7 @@ void iwl_force_scan_end(struct iwl_priv *priv)
|
|
|
clear_bit(STATUS_SCANNING, &priv->shrd->status);
|
|
|
clear_bit(STATUS_SCAN_HW, &priv->shrd->status);
|
|
|
clear_bit(STATUS_SCAN_ABORTING, &priv->shrd->status);
|
|
|
+ clear_bit(STATUS_SCAN_COMPLETE, &priv->shrd->status);
|
|
|
iwl_complete_scan(priv, true);
|
|
|
}
|
|
|
|
|
@@ -235,9 +241,24 @@ void iwl_scan_cancel_timeout(struct iwl_priv *priv, unsigned long ms)
|
|
|
|
|
|
while (time_before_eq(jiffies, timeout)) {
|
|
|
if (!test_bit(STATUS_SCAN_HW, &priv->shrd->status))
|
|
|
- break;
|
|
|
+ goto finished;
|
|
|
msleep(20);
|
|
|
}
|
|
|
+
|
|
|
+ return;
|
|
|
+
|
|
|
+ finished:
|
|
|
+ /*
|
|
|
+ * Now STATUS_SCAN_HW is clear. This means that the
|
|
|
+ * device finished, but the background work is going
|
|
|
+ * to execute at best as soon as we release the mutex.
|
|
|
+ * Since we need to be able to issue a new scan right
|
|
|
+ * after this function returns, run the complete here.
|
|
|
+ * The STATUS_SCAN_COMPLETE bit will then be cleared
|
|
|
+ * and prevent the background work from "completing"
|
|
|
+ * a possible new scan.
|
|
|
+ */
|
|
|
+ iwl_process_scan_complete(priv);
|
|
|
}
|
|
|
|
|
|
/* Service response to REPLY_SCAN_CMD (0x80) */
|
|
@@ -321,13 +342,20 @@ static int iwl_rx_scan_complete_notif(struct iwl_priv *priv,
|
|
|
scan_notif->tsf_low,
|
|
|
scan_notif->tsf_high, scan_notif->status);
|
|
|
|
|
|
- /* The HW is no longer scanning */
|
|
|
- clear_bit(STATUS_SCAN_HW, &priv->shrd->status);
|
|
|
-
|
|
|
IWL_DEBUG_SCAN(priv, "Scan on %sGHz took %dms\n",
|
|
|
(priv->scan_band == IEEE80211_BAND_2GHZ) ? "2.4" : "5.2",
|
|
|
jiffies_to_msecs(jiffies - priv->scan_start));
|
|
|
|
|
|
+ /*
|
|
|
+ * When aborting, we run the scan completed background work inline
|
|
|
+ * and the background work must then do nothing. The SCAN_COMPLETE
|
|
|
+ * bit helps implement that logic and thus needs to be set before
|
|
|
+ * queueing the work. Also, since the scan abort waits for SCAN_HW
|
|
|
+ * to clear, we need to set SCAN_COMPLETE before clearing SCAN_HW
|
|
|
+ * to avoid a race there.
|
|
|
+ */
|
|
|
+ set_bit(STATUS_SCAN_COMPLETE, &priv->shrd->status);
|
|
|
+ clear_bit(STATUS_SCAN_HW, &priv->shrd->status);
|
|
|
queue_work(priv->shrd->workqueue, &priv->scan_completed);
|
|
|
|
|
|
if (priv->iw_mode != NL80211_IFTYPE_ADHOC &&
|