diff options
author | Johannes Berg <johannes.berg@intel.com> | 2010-09-13 08:46:33 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2010-09-14 16:08:03 -0400 |
commit | 3eecce527c7434dfd16517ce08b49632c8a26717 (patch) | |
tree | 7495b3970b2f34d40dc0adbfc8a5a8627a515851 /drivers/net/wireless/iwlwifi/iwl-scan.c | |
parent | b5be3efc34294cc34e305903df6a388950e8d1f3 (diff) |
iwlwifi: unify scan start checks
Rather than duplicating all the checks and even
in case of errors accepting the scan request
from mac80211, we can push the checks to the
caller and in all error cases reject the scan
request right away (rather than accepting and
then saying it was aborted).
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
Acked-by: Wey-Yi W Guy <wey-yi.w.guy@intel.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/iwlwifi/iwl-scan.c')
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-scan.c | 127 |
1 files changed, 74 insertions, 53 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-scan.c b/drivers/net/wireless/iwlwifi/iwl-scan.c index 7727f0966d31..6bd14bc33478 100644 --- a/drivers/net/wireless/iwlwifi/iwl-scan.c +++ b/drivers/net/wireless/iwlwifi/iwl-scan.c | |||
@@ -324,19 +324,68 @@ void iwl_init_scan_params(struct iwl_priv *priv) | |||
324 | } | 324 | } |
325 | EXPORT_SYMBOL(iwl_init_scan_params); | 325 | EXPORT_SYMBOL(iwl_init_scan_params); |
326 | 326 | ||
327 | static int iwl_scan_initiate(struct iwl_priv *priv, struct ieee80211_vif *vif) | 327 | static int __must_check iwl_scan_initiate(struct iwl_priv *priv, |
328 | struct ieee80211_vif *vif, | ||
329 | bool internal, | ||
330 | enum nl80211_band band) | ||
328 | { | 331 | { |
332 | int ret; | ||
333 | |||
329 | lockdep_assert_held(&priv->mutex); | 334 | lockdep_assert_held(&priv->mutex); |
330 | 335 | ||
331 | IWL_DEBUG_INFO(priv, "Starting scan...\n"); | 336 | if (WARN_ON(!priv->cfg->ops->utils->request_scan)) |
337 | return -EOPNOTSUPP; | ||
338 | |||
339 | cancel_delayed_work(&priv->scan_check); | ||
340 | |||
341 | if (!iwl_is_ready(priv)) { | ||
342 | IWL_WARN(priv, "request scan called when driver not ready.\n"); | ||
343 | return -EIO; | ||
344 | } | ||
345 | |||
346 | if (test_bit(STATUS_SCAN_HW, &priv->status)) { | ||
347 | IWL_DEBUG_INFO(priv, | ||
348 | "Multiple concurrent scan requests in parallel.\n"); | ||
349 | return -EBUSY; | ||
350 | } | ||
351 | |||
352 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) { | ||
353 | IWL_DEBUG_SCAN(priv, "Aborting scan due to device shutdown\n"); | ||
354 | return -EIO; | ||
355 | } | ||
356 | |||
357 | if (test_bit(STATUS_SCAN_ABORTING, &priv->status)) { | ||
358 | IWL_DEBUG_HC(priv, "Scan request while abort pending.\n"); | ||
359 | return -EBUSY; | ||
360 | } | ||
361 | |||
362 | if (iwl_is_rfkill(priv)) { | ||
363 | IWL_DEBUG_HC(priv, "Aborting scan due to RF Kill activation\n"); | ||
364 | return -EIO; | ||
365 | } | ||
366 | |||
367 | if (!test_bit(STATUS_READY, &priv->status)) { | ||
368 | IWL_DEBUG_HC(priv, "Scan request while uninitialized.\n"); | ||
369 | return -EBUSY; | ||
370 | } | ||
371 | |||
372 | IWL_DEBUG_INFO(priv, "Starting %sscan...\n", | ||
373 | internal ? "internal short " : ""); | ||
374 | |||
332 | set_bit(STATUS_SCANNING, &priv->status); | 375 | set_bit(STATUS_SCANNING, &priv->status); |
333 | priv->is_internal_short_scan = false; | 376 | priv->is_internal_short_scan = internal; |
334 | priv->scan_start = jiffies; | 377 | priv->scan_start = jiffies; |
378 | priv->scan_band = band; | ||
335 | 379 | ||
336 | if (WARN_ON(!priv->cfg->ops->utils->request_scan)) | 380 | ret = priv->cfg->ops->utils->request_scan(priv, vif); |
337 | return -EOPNOTSUPP; | 381 | if (ret) { |
382 | clear_bit(STATUS_SCANNING, &priv->status); | ||
383 | priv->is_internal_short_scan = false; | ||
384 | return ret; | ||
385 | } | ||
338 | 386 | ||
339 | priv->cfg->ops->utils->request_scan(priv, vif); | 387 | queue_delayed_work(priv->workqueue, &priv->scan_check, |
388 | IWL_SCAN_CHECK_WATCHDOG); | ||
340 | 389 | ||
341 | return 0; | 390 | return 0; |
342 | } | 391 | } |
@@ -355,12 +404,6 @@ int iwl_mac_hw_scan(struct ieee80211_hw *hw, | |||
355 | 404 | ||
356 | mutex_lock(&priv->mutex); | 405 | mutex_lock(&priv->mutex); |
357 | 406 | ||
358 | if (!iwl_is_ready_rf(priv)) { | ||
359 | ret = -EIO; | ||
360 | IWL_DEBUG_MAC80211(priv, "leave - not ready or exit pending\n"); | ||
361 | goto out_unlock; | ||
362 | } | ||
363 | |||
364 | if (test_bit(STATUS_SCANNING, &priv->status) && | 407 | if (test_bit(STATUS_SCANNING, &priv->status) && |
365 | !priv->is_internal_short_scan) { | 408 | !priv->is_internal_short_scan) { |
366 | IWL_DEBUG_SCAN(priv, "Scan already in progress.\n"); | 409 | IWL_DEBUG_SCAN(priv, "Scan already in progress.\n"); |
@@ -368,14 +411,7 @@ int iwl_mac_hw_scan(struct ieee80211_hw *hw, | |||
368 | goto out_unlock; | 411 | goto out_unlock; |
369 | } | 412 | } |
370 | 413 | ||
371 | if (test_bit(STATUS_SCAN_ABORTING, &priv->status)) { | ||
372 | IWL_DEBUG_SCAN(priv, "Scan request while abort pending\n"); | ||
373 | ret = -EAGAIN; | ||
374 | goto out_unlock; | ||
375 | } | ||
376 | |||
377 | /* mac80211 will only ask for one band at a time */ | 414 | /* mac80211 will only ask for one band at a time */ |
378 | priv->scan_band = req->channels[0]->band; | ||
379 | priv->scan_request = req; | 415 | priv->scan_request = req; |
380 | priv->scan_vif = vif; | 416 | priv->scan_vif = vif; |
381 | 417 | ||
@@ -386,7 +422,8 @@ int iwl_mac_hw_scan(struct ieee80211_hw *hw, | |||
386 | if (priv->is_internal_short_scan) | 422 | if (priv->is_internal_short_scan) |
387 | ret = 0; | 423 | ret = 0; |
388 | else | 424 | else |
389 | ret = iwl_scan_initiate(priv, vif); | 425 | ret = iwl_scan_initiate(priv, vif, false, |
426 | req->channels[0]->band); | ||
390 | 427 | ||
391 | IWL_DEBUG_MAC80211(priv, "leave\n"); | 428 | IWL_DEBUG_MAC80211(priv, "leave\n"); |
392 | 429 | ||
@@ -418,31 +455,13 @@ static void iwl_bg_start_internal_scan(struct work_struct *work) | |||
418 | goto unlock; | 455 | goto unlock; |
419 | } | 456 | } |
420 | 457 | ||
421 | if (!iwl_is_ready_rf(priv)) { | ||
422 | IWL_DEBUG_SCAN(priv, "not ready or exit pending\n"); | ||
423 | goto unlock; | ||
424 | } | ||
425 | |||
426 | if (test_bit(STATUS_SCANNING, &priv->status)) { | 458 | if (test_bit(STATUS_SCANNING, &priv->status)) { |
427 | IWL_DEBUG_SCAN(priv, "Scan already in progress.\n"); | 459 | IWL_DEBUG_SCAN(priv, "Scan already in progress.\n"); |
428 | goto unlock; | 460 | goto unlock; |
429 | } | 461 | } |
430 | 462 | ||
431 | if (test_bit(STATUS_SCAN_ABORTING, &priv->status)) { | 463 | if (iwl_scan_initiate(priv, NULL, true, priv->band)) |
432 | IWL_DEBUG_SCAN(priv, "Scan request while abort pending\n"); | 464 | IWL_DEBUG_SCAN(priv, "failed to start internal short scan\n"); |
433 | goto unlock; | ||
434 | } | ||
435 | |||
436 | priv->scan_band = priv->band; | ||
437 | |||
438 | IWL_DEBUG_SCAN(priv, "Start internal short scan...\n"); | ||
439 | set_bit(STATUS_SCANNING, &priv->status); | ||
440 | priv->is_internal_short_scan = true; | ||
441 | |||
442 | if (WARN_ON(!priv->cfg->ops->utils->request_scan)) | ||
443 | goto unlock; | ||
444 | |||
445 | priv->cfg->ops->utils->request_scan(priv, NULL); | ||
446 | unlock: | 465 | unlock: |
447 | mutex_unlock(&priv->mutex); | 466 | mutex_unlock(&priv->mutex); |
448 | } | 467 | } |
@@ -536,7 +555,6 @@ static void iwl_bg_scan_completed(struct work_struct *work) | |||
536 | struct iwl_priv *priv = | 555 | struct iwl_priv *priv = |
537 | container_of(work, struct iwl_priv, scan_completed); | 556 | container_of(work, struct iwl_priv, scan_completed); |
538 | bool internal = false; | 557 | bool internal = false; |
539 | bool scan_completed = false; | ||
540 | struct iwl_rxon_context *ctx; | 558 | struct iwl_rxon_context *ctx; |
541 | 559 | ||
542 | IWL_DEBUG_SCAN(priv, "SCAN complete scan\n"); | 560 | IWL_DEBUG_SCAN(priv, "SCAN complete scan\n"); |
@@ -549,16 +567,27 @@ static void iwl_bg_scan_completed(struct work_struct *work) | |||
549 | IWL_DEBUG_SCAN(priv, "internal short scan completed\n"); | 567 | IWL_DEBUG_SCAN(priv, "internal short scan completed\n"); |
550 | internal = true; | 568 | internal = true; |
551 | } else if (priv->scan_request) { | 569 | } else if (priv->scan_request) { |
552 | scan_completed = true; | ||
553 | priv->scan_request = NULL; | 570 | priv->scan_request = NULL; |
554 | priv->scan_vif = NULL; | 571 | priv->scan_vif = NULL; |
572 | ieee80211_scan_completed(priv->hw, false); | ||
555 | } | 573 | } |
556 | 574 | ||
557 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) | 575 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) |
558 | goto out; | 576 | goto out; |
559 | 577 | ||
560 | if (internal && priv->scan_request) | 578 | if (internal && priv->scan_request) { |
561 | iwl_scan_initiate(priv, priv->scan_vif); | 579 | int err = iwl_scan_initiate(priv, priv->scan_vif, false, |
580 | priv->scan_request->channels[0]->band); | ||
581 | |||
582 | if (err) { | ||
583 | IWL_DEBUG_SCAN(priv, | ||
584 | "failed to initiate pending scan: %d\n", err); | ||
585 | priv->scan_request = NULL; | ||
586 | priv->scan_vif = NULL; | ||
587 | ieee80211_scan_completed(priv->hw, true); | ||
588 | } else | ||
589 | goto out; | ||
590 | } | ||
562 | 591 | ||
563 | /* Since setting the TXPOWER may have been deferred while | 592 | /* Since setting the TXPOWER may have been deferred while |
564 | * performing the scan, fire one off */ | 593 | * performing the scan, fire one off */ |
@@ -571,19 +600,11 @@ static void iwl_bg_scan_completed(struct work_struct *work) | |||
571 | for_each_context(priv, ctx) | 600 | for_each_context(priv, ctx) |
572 | iwlcore_commit_rxon(priv, ctx); | 601 | iwlcore_commit_rxon(priv, ctx); |
573 | 602 | ||
574 | out: | ||
575 | if (priv->cfg->ops->hcmd->set_pan_params) | 603 | if (priv->cfg->ops->hcmd->set_pan_params) |
576 | priv->cfg->ops->hcmd->set_pan_params(priv); | 604 | priv->cfg->ops->hcmd->set_pan_params(priv); |
577 | 605 | ||
606 | out: | ||
578 | mutex_unlock(&priv->mutex); | 607 | mutex_unlock(&priv->mutex); |
579 | |||
580 | /* | ||
581 | * Do not hold mutex here since this will cause mac80211 to call | ||
582 | * into driver again into functions that will attempt to take | ||
583 | * mutex. | ||
584 | */ | ||
585 | if (scan_completed) | ||
586 | ieee80211_scan_completed(priv->hw, false); | ||
587 | } | 608 | } |
588 | 609 | ||
589 | void iwl_setup_scan_deferred_work(struct iwl_priv *priv) | 610 | void iwl_setup_scan_deferred_work(struct iwl_priv *priv) |