diff options
author | Johannes Berg <johannes@sipsolutions.net> | 2009-06-12 16:22:48 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2009-06-15 15:05:52 -0400 |
commit | d7129e190c3107db8ac11a9e51035641b68d2aa7 (patch) | |
tree | 5ff7d6bb71d3f37121c415ff049031dcb44e3e44 /drivers/net | |
parent | 87e501b351ed9d837e63f6506b7e66331a69ed58 (diff) |
iwlwifi: revamp bss_info_changed
My earlier patch,
"mac80211: unify config_interface and bss_info_changed"
introduced a bug in iwlwifi where it will do some things
incorrectly now when reassociating.
Revamp iwl_bss_info_changed to fix that issue and make it
easier to read. Also, while at it, add comments about things
that it should do but currently doesn't.
Finally, also improve the locking in the function.
Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
Signed-off-by: Reinette Chatre <reinette.chatre@intel.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net')
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-core.c | 114 |
1 files changed, 70 insertions, 44 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index f9d16ca5b3d9..e05faa004dae 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c | |||
@@ -2390,39 +2390,46 @@ void iwl_bss_info_changed(struct ieee80211_hw *hw, | |||
2390 | priv->ibss_beacon = ieee80211_beacon_get(hw, vif); | 2390 | priv->ibss_beacon = ieee80211_beacon_get(hw, vif); |
2391 | } | 2391 | } |
2392 | 2392 | ||
2393 | if ((changes & BSS_CHANGED_BSSID) && !iwl_is_rfkill(priv)) { | 2393 | if (changes & BSS_CHANGED_BEACON_INT) { |
2394 | /* If there is currently a HW scan going on in the background | 2394 | priv->beacon_int = bss_conf->beacon_int; |
2395 | * then we need to cancel it else the RXON below will fail. */ | 2395 | /* TODO: in AP mode, do something to make this take effect */ |
2396 | } | ||
2397 | |||
2398 | if (changes & BSS_CHANGED_BSSID) { | ||
2399 | IWL_DEBUG_MAC80211(priv, "BSSID %pM\n", bss_conf->bssid); | ||
2400 | |||
2401 | /* | ||
2402 | * If there is currently a HW scan going on in the | ||
2403 | * background then we need to cancel it else the RXON | ||
2404 | * below/in post_associate will fail. | ||
2405 | */ | ||
2396 | if (iwl_scan_cancel_timeout(priv, 100)) { | 2406 | if (iwl_scan_cancel_timeout(priv, 100)) { |
2397 | IWL_WARN(priv, "Aborted scan still in progress " | 2407 | IWL_WARN(priv, "Aborted scan still in progress after 100ms\n"); |
2398 | "after 100ms\n"); | ||
2399 | IWL_DEBUG_MAC80211(priv, "leaving - scan abort failed.\n"); | 2408 | IWL_DEBUG_MAC80211(priv, "leaving - scan abort failed.\n"); |
2400 | mutex_unlock(&priv->mutex); | 2409 | mutex_unlock(&priv->mutex); |
2401 | return; | 2410 | return; |
2402 | } | 2411 | } |
2403 | memcpy(priv->staging_rxon.bssid_addr, | ||
2404 | bss_conf->bssid, ETH_ALEN); | ||
2405 | 2412 | ||
2406 | /* TODO: Audit driver for usage of these members and see | 2413 | /* mac80211 only sets assoc when in STATION mode */ |
2407 | * if mac80211 deprecates them (priv->bssid looks like it | 2414 | if (priv->iw_mode == NL80211_IFTYPE_ADHOC || |
2408 | * shouldn't be there, but I haven't scanned the IBSS code | 2415 | bss_conf->assoc) { |
2409 | * to verify) - jpk */ | 2416 | memcpy(priv->staging_rxon.bssid_addr, |
2410 | memcpy(priv->bssid, bss_conf->bssid, ETH_ALEN); | 2417 | bss_conf->bssid, ETH_ALEN); |
2411 | 2418 | ||
2412 | if (priv->iw_mode == NL80211_IFTYPE_AP) | 2419 | /* currently needed in a few places */ |
2413 | iwlcore_config_ap(priv); | 2420 | memcpy(priv->bssid, bss_conf->bssid, ETH_ALEN); |
2414 | else { | 2421 | } else { |
2415 | int rc = iwlcore_commit_rxon(priv); | 2422 | priv->staging_rxon.filter_flags &= |
2416 | if ((priv->iw_mode == NL80211_IFTYPE_STATION) && rc) | 2423 | ~RXON_FILTER_ASSOC_MSK; |
2417 | iwl_rxon_add_station( | ||
2418 | priv, priv->active_rxon.bssid_addr, 1); | ||
2419 | } | 2424 | } |
2420 | } else if (!iwl_is_rfkill(priv)) { | 2425 | |
2421 | iwl_scan_cancel_timeout(priv, 100); | ||
2422 | priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK; | ||
2423 | iwlcore_commit_rxon(priv); | ||
2424 | } | 2426 | } |
2425 | 2427 | ||
2428 | /* | ||
2429 | * This needs to be after setting the BSSID in case | ||
2430 | * mac80211 decides to do both changes at once because | ||
2431 | * it will invoke post_associate. | ||
2432 | */ | ||
2426 | if (priv->iw_mode == NL80211_IFTYPE_ADHOC && | 2433 | if (priv->iw_mode == NL80211_IFTYPE_ADHOC && |
2427 | changes & BSS_CHANGED_BEACON) { | 2434 | changes & BSS_CHANGED_BEACON) { |
2428 | struct sk_buff *beacon = ieee80211_beacon_get(hw, vif); | 2435 | struct sk_buff *beacon = ieee80211_beacon_get(hw, vif); |
@@ -2431,8 +2438,6 @@ void iwl_bss_info_changed(struct ieee80211_hw *hw, | |||
2431 | iwl_mac_beacon_update(hw, beacon); | 2438 | iwl_mac_beacon_update(hw, beacon); |
2432 | } | 2439 | } |
2433 | 2440 | ||
2434 | mutex_unlock(&priv->mutex); | ||
2435 | |||
2436 | if (changes & BSS_CHANGED_ERP_PREAMBLE) { | 2441 | if (changes & BSS_CHANGED_ERP_PREAMBLE) { |
2437 | IWL_DEBUG_MAC80211(priv, "ERP_PREAMBLE %d\n", | 2442 | IWL_DEBUG_MAC80211(priv, "ERP_PREAMBLE %d\n", |
2438 | bss_conf->use_short_preamble); | 2443 | bss_conf->use_short_preamble); |
@@ -2450,6 +2455,23 @@ void iwl_bss_info_changed(struct ieee80211_hw *hw, | |||
2450 | priv->staging_rxon.flags &= ~RXON_FLG_TGG_PROTECT_MSK; | 2455 | priv->staging_rxon.flags &= ~RXON_FLG_TGG_PROTECT_MSK; |
2451 | } | 2456 | } |
2452 | 2457 | ||
2458 | if (changes & BSS_CHANGED_BASIC_RATES) { | ||
2459 | /* XXX use this information | ||
2460 | * | ||
2461 | * To do that, remove code from iwl_set_rate() and put something | ||
2462 | * like this here: | ||
2463 | * | ||
2464 | if (A-band) | ||
2465 | priv->staging_rxon.ofdm_basic_rates = | ||
2466 | bss_conf->basic_rates; | ||
2467 | else | ||
2468 | priv->staging_rxon.ofdm_basic_rates = | ||
2469 | bss_conf->basic_rates >> 4; | ||
2470 | priv->staging_rxon.cck_basic_rates = | ||
2471 | bss_conf->basic_rates & 0xF; | ||
2472 | */ | ||
2473 | } | ||
2474 | |||
2453 | if (changes & BSS_CHANGED_HT) { | 2475 | if (changes & BSS_CHANGED_HT) { |
2454 | iwl_ht_conf(priv, bss_conf); | 2476 | iwl_ht_conf(priv, bss_conf); |
2455 | 2477 | ||
@@ -2459,10 +2481,6 @@ void iwl_bss_info_changed(struct ieee80211_hw *hw, | |||
2459 | 2481 | ||
2460 | if (changes & BSS_CHANGED_ASSOC) { | 2482 | if (changes & BSS_CHANGED_ASSOC) { |
2461 | IWL_DEBUG_MAC80211(priv, "ASSOC %d\n", bss_conf->assoc); | 2483 | IWL_DEBUG_MAC80211(priv, "ASSOC %d\n", bss_conf->assoc); |
2462 | /* This should never happen as this function should | ||
2463 | * never be called from interrupt context. */ | ||
2464 | if (WARN_ON_ONCE(in_interrupt())) | ||
2465 | return; | ||
2466 | if (bss_conf->assoc) { | 2484 | if (bss_conf->assoc) { |
2467 | priv->assoc_id = bss_conf->aid; | 2485 | priv->assoc_id = bss_conf->aid; |
2468 | priv->beacon_int = bss_conf->beacon_int; | 2486 | priv->beacon_int = bss_conf->beacon_int; |
@@ -2470,27 +2488,35 @@ void iwl_bss_info_changed(struct ieee80211_hw *hw, | |||
2470 | priv->timestamp = bss_conf->timestamp; | 2488 | priv->timestamp = bss_conf->timestamp; |
2471 | priv->assoc_capability = bss_conf->assoc_capability; | 2489 | priv->assoc_capability = bss_conf->assoc_capability; |
2472 | 2490 | ||
2473 | /* we have just associated, don't start scan too early | 2491 | /* |
2474 | * leave time for EAPOL exchange to complete | 2492 | * We have just associated, don't start scan too early |
2493 | * leave time for EAPOL exchange to complete. | ||
2494 | * | ||
2495 | * XXX: do this in mac80211 | ||
2475 | */ | 2496 | */ |
2476 | priv->next_scan_jiffies = jiffies + | 2497 | priv->next_scan_jiffies = jiffies + |
2477 | IWL_DELAY_NEXT_SCAN_AFTER_ASSOC; | 2498 | IWL_DELAY_NEXT_SCAN_AFTER_ASSOC; |
2478 | mutex_lock(&priv->mutex); | 2499 | if (!iwl_is_rfkill(priv)) |
2479 | priv->cfg->ops->lib->post_associate(priv); | 2500 | priv->cfg->ops->lib->post_associate(priv); |
2480 | mutex_unlock(&priv->mutex); | 2501 | } else |
2481 | } else { | ||
2482 | priv->assoc_id = 0; | 2502 | priv->assoc_id = 0; |
2483 | IWL_DEBUG_MAC80211(priv, "DISASSOC %d\n", bss_conf->assoc); | 2503 | |
2504 | } | ||
2505 | |||
2506 | if (changes && iwl_is_associated(priv) && priv->assoc_id) { | ||
2507 | IWL_DEBUG_MAC80211(priv, "Changes (%#x) while associated\n", | ||
2508 | changes); | ||
2509 | ret = iwl_send_rxon_assoc(priv); | ||
2510 | if (!ret) { | ||
2511 | /* Sync active_rxon with latest change. */ | ||
2512 | memcpy((void *)&priv->active_rxon, | ||
2513 | &priv->staging_rxon, | ||
2514 | sizeof(struct iwl_rxon_cmd)); | ||
2484 | } | 2515 | } |
2485 | } else if (changes && iwl_is_associated(priv) && priv->assoc_id) { | ||
2486 | IWL_DEBUG_MAC80211(priv, "Associated Changes %d\n", changes); | ||
2487 | ret = iwl_send_rxon_assoc(priv); | ||
2488 | if (!ret) | ||
2489 | /* Sync active_rxon with latest change. */ | ||
2490 | memcpy((void *)&priv->active_rxon, | ||
2491 | &priv->staging_rxon, | ||
2492 | sizeof(struct iwl_rxon_cmd)); | ||
2493 | } | 2516 | } |
2517 | |||
2518 | mutex_unlock(&priv->mutex); | ||
2519 | |||
2494 | IWL_DEBUG_MAC80211(priv, "leave\n"); | 2520 | IWL_DEBUG_MAC80211(priv, "leave\n"); |
2495 | } | 2521 | } |
2496 | EXPORT_SYMBOL(iwl_bss_info_changed); | 2522 | EXPORT_SYMBOL(iwl_bss_info_changed); |