diff options
| author | Johannes Berg <johannes.berg@intel.com> | 2011-09-22 17:59:04 -0400 |
|---|---|---|
| committer | John W. Linville <linville@tuxdriver.com> | 2011-09-26 14:55:50 -0400 |
| commit | 6c80c39d9a6986a566c30d797aae37bfb697eea3 (patch) | |
| tree | 8ce4d0e71e4daacf3724ab15a8265f1a53926325 | |
| parent | 1b9ca0272ffae212e726380f66777b30a56ed7a5 (diff) | |
iwlagn: fix dangling scan request
If iwl_scan_initiate() fails for any reason,
priv->scan_request and priv->scan_vif are left
dangling. This can lead to a crash later when
iwl_bg_scan_completed() tries to run a pending
scan request.
In practice, this seems to be very rare due to
the STATUS_SCANNING check earlier. That check,
however, is wrong -- it should allow a scan to
be queued when a reset/roc scan is going on.
When a normal scan is already going on, a new
one can't be issued by mac80211, so that code
can be removed completely. I introduced this
bug when adding off-channel support in commit
266af4c745952e9bebf687dd68af58df553cb59d.
Cc: stable@kernel.org [3.0]
Reported-by: Peng Yan <peng.yan@intel.com>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Wey-Yi Guy <wey-yi.w.guy@intel.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
| -rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-scan.c | 30 |
1 files changed, 16 insertions, 14 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-scan.c b/drivers/net/wireless/iwlwifi/iwl-scan.c index dd6937e97055..77e528f5db88 100644 --- a/drivers/net/wireless/iwlwifi/iwl-scan.c +++ b/drivers/net/wireless/iwlwifi/iwl-scan.c | |||
| @@ -405,31 +405,33 @@ int iwl_mac_hw_scan(struct ieee80211_hw *hw, | |||
| 405 | 405 | ||
| 406 | mutex_lock(&priv->mutex); | 406 | mutex_lock(&priv->mutex); |
| 407 | 407 | ||
| 408 | if (test_bit(STATUS_SCANNING, &priv->status) && | ||
| 409 | priv->scan_type != IWL_SCAN_NORMAL) { | ||
| 410 | IWL_DEBUG_SCAN(priv, "Scan already in progress.\n"); | ||
| 411 | ret = -EAGAIN; | ||
| 412 | goto out_unlock; | ||
| 413 | } | ||
| 414 | |||
| 415 | /* mac80211 will only ask for one band at a time */ | ||
| 416 | priv->scan_request = req; | ||
| 417 | priv->scan_vif = vif; | ||
| 418 | |||
| 419 | /* | 408 | /* |
| 420 | * If an internal scan is in progress, just set | 409 | * If an internal scan is in progress, just set |
| 421 | * up the scan_request as per above. | 410 | * up the scan_request as per above. |
| 422 | */ | 411 | */ |
| 423 | if (priv->scan_type != IWL_SCAN_NORMAL) { | 412 | if (priv->scan_type != IWL_SCAN_NORMAL) { |
| 424 | IWL_DEBUG_SCAN(priv, "SCAN request during internal scan\n"); | 413 | IWL_DEBUG_SCAN(priv, |
| 414 | "SCAN request during internal scan - defer\n"); | ||
| 415 | priv->scan_request = req; | ||
| 416 | priv->scan_vif = vif; | ||
| 425 | ret = 0; | 417 | ret = 0; |
| 426 | } else | 418 | } else { |
| 419 | priv->scan_request = req; | ||
| 420 | priv->scan_vif = vif; | ||
| 421 | /* | ||
| 422 | * mac80211 will only ask for one band at a time | ||
| 423 | * so using channels[0] here is ok | ||
| 424 | */ | ||
| 427 | ret = iwl_scan_initiate(priv, vif, IWL_SCAN_NORMAL, | 425 | ret = iwl_scan_initiate(priv, vif, IWL_SCAN_NORMAL, |
| 428 | req->channels[0]->band); | 426 | req->channels[0]->band); |
| 427 | if (ret) { | ||
| 428 | priv->scan_request = NULL; | ||
| 429 | priv->scan_vif = NULL; | ||
| 430 | } | ||
| 431 | } | ||
| 429 | 432 | ||
| 430 | IWL_DEBUG_MAC80211(priv, "leave\n"); | 433 | IWL_DEBUG_MAC80211(priv, "leave\n"); |
| 431 | 434 | ||
| 432 | out_unlock: | ||
| 433 | mutex_unlock(&priv->mutex); | 435 | mutex_unlock(&priv->mutex); |
| 434 | 436 | ||
| 435 | return ret; | 437 | return ret; |
