diff options
author | Stanislaw Gruszka <sgruszka@redhat.com> | 2010-07-29 05:37:41 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2010-07-29 12:55:00 -0400 |
commit | d28232b461b8d54b09e59325dbac8b0913ce2049 (patch) | |
tree | 86b9fbd210d63f60056f9d8fb6b4dc5ded6a40d2 /drivers/net/wireless | |
parent | 16345910d927556878a82621ebb9a7bcad13e8d8 (diff) |
iwlwifi: fix scan abort
Fix possible double priv->mutex lock introduced by commit
a69b03e941abae00380fc6bc1877fb797a1b31e6
"iwlwifi: cancel scan watchdog in iwl_bg_abort_scan" .
We can not call cancel_delayed_work_sync(&priv->scan_check) with
priv->mutex locked because workqueue function iwl_bg_scan_check()
take that lock internally.
We do not need to synchronize when canceling priv->scan_check work.
We can avoid races (sending double abort command or send no
command at all) using STATUS_SCAN_ABORT bit. Moreover
current iwl_bg_scan_check() code seems to be broken, as
we should not send abort commands when currently aborting.
Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
CC: stable@kernel.org
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless')
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-scan.c | 18 |
1 files changed, 8 insertions, 10 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-scan.c b/drivers/net/wireless/iwlwifi/iwl-scan.c index 2a7c399fee1e..b0c6b0473901 100644 --- a/drivers/net/wireless/iwlwifi/iwl-scan.c +++ b/drivers/net/wireless/iwlwifi/iwl-scan.c | |||
@@ -429,11 +429,10 @@ void iwl_bg_scan_check(struct work_struct *data) | |||
429 | return; | 429 | return; |
430 | 430 | ||
431 | mutex_lock(&priv->mutex); | 431 | mutex_lock(&priv->mutex); |
432 | if (test_bit(STATUS_SCANNING, &priv->status) || | 432 | if (test_bit(STATUS_SCANNING, &priv->status) && |
433 | test_bit(STATUS_SCAN_ABORTING, &priv->status)) { | 433 | !test_bit(STATUS_SCAN_ABORTING, &priv->status)) { |
434 | IWL_DEBUG_SCAN(priv, "Scan completion watchdog resetting " | 434 | IWL_DEBUG_SCAN(priv, "Scan completion watchdog (%dms)\n", |
435 | "adapter (%dms)\n", | 435 | jiffies_to_msecs(IWL_SCAN_CHECK_WATCHDOG)); |
436 | jiffies_to_msecs(IWL_SCAN_CHECK_WATCHDOG)); | ||
437 | 436 | ||
438 | if (!test_bit(STATUS_EXIT_PENDING, &priv->status)) | 437 | if (!test_bit(STATUS_EXIT_PENDING, &priv->status)) |
439 | iwl_send_scan_abort(priv); | 438 | iwl_send_scan_abort(priv); |
@@ -498,12 +497,11 @@ void iwl_bg_abort_scan(struct work_struct *work) | |||
498 | !test_bit(STATUS_GEO_CONFIGURED, &priv->status)) | 497 | !test_bit(STATUS_GEO_CONFIGURED, &priv->status)) |
499 | return; | 498 | return; |
500 | 499 | ||
501 | mutex_lock(&priv->mutex); | 500 | cancel_delayed_work(&priv->scan_check); |
502 | |||
503 | cancel_delayed_work_sync(&priv->scan_check); | ||
504 | set_bit(STATUS_SCAN_ABORTING, &priv->status); | ||
505 | iwl_send_scan_abort(priv); | ||
506 | 501 | ||
502 | mutex_lock(&priv->mutex); | ||
503 | if (test_bit(STATUS_SCAN_ABORTING, &priv->status)) | ||
504 | iwl_send_scan_abort(priv); | ||
507 | mutex_unlock(&priv->mutex); | 505 | mutex_unlock(&priv->mutex); |
508 | } | 506 | } |
509 | EXPORT_SYMBOL(iwl_bg_abort_scan); | 507 | EXPORT_SYMBOL(iwl_bg_abort_scan); |