diff options
Diffstat (limited to 'drivers/net/wireless/ath/ath9k/main.c')
-rw-r--r-- | drivers/net/wireless/ath/ath9k/main.c | 206 |
1 files changed, 96 insertions, 110 deletions
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index 2398d4f45f28..bbbfdcde2727 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c | |||
@@ -189,7 +189,7 @@ static u8 parse_mpdudensity(u8 mpdudensity) | |||
189 | 189 | ||
190 | static void ath_setup_rates(struct ath_softc *sc, enum ieee80211_band band) | 190 | static void ath_setup_rates(struct ath_softc *sc, enum ieee80211_band band) |
191 | { | 191 | { |
192 | struct ath_rate_table *rate_table = NULL; | 192 | const struct ath_rate_table *rate_table = NULL; |
193 | struct ieee80211_supported_band *sband; | 193 | struct ieee80211_supported_band *sband; |
194 | struct ieee80211_rate *rate; | 194 | struct ieee80211_rate *rate; |
195 | int i, maxrates; | 195 | int i, maxrates; |
@@ -2358,114 +2358,6 @@ skip_chan_change: | |||
2358 | if (changed & IEEE80211_CONF_CHANGE_POWER) | 2358 | if (changed & IEEE80211_CONF_CHANGE_POWER) |
2359 | sc->config.txpowlimit = 2 * conf->power_level; | 2359 | sc->config.txpowlimit = 2 * conf->power_level; |
2360 | 2360 | ||
2361 | /* | ||
2362 | * The HW TSF has to be reset when the beacon interval changes. | ||
2363 | * We set the flag here, and ath_beacon_config_ap() would take this | ||
2364 | * into account when it gets called through the subsequent | ||
2365 | * config_interface() call - with IFCC_BEACON in the changed field. | ||
2366 | */ | ||
2367 | |||
2368 | if (changed & IEEE80211_CONF_CHANGE_BEACON_INTERVAL) | ||
2369 | sc->sc_flags |= SC_OP_TSF_RESET; | ||
2370 | |||
2371 | mutex_unlock(&sc->mutex); | ||
2372 | |||
2373 | return 0; | ||
2374 | } | ||
2375 | |||
2376 | static int ath9k_config_interface(struct ieee80211_hw *hw, | ||
2377 | struct ieee80211_vif *vif, | ||
2378 | struct ieee80211_if_conf *conf) | ||
2379 | { | ||
2380 | struct ath_wiphy *aphy = hw->priv; | ||
2381 | struct ath_softc *sc = aphy->sc; | ||
2382 | struct ath_hw *ah = sc->sc_ah; | ||
2383 | struct ath_vif *avp = (void *)vif->drv_priv; | ||
2384 | u32 rfilt = 0; | ||
2385 | int error, i; | ||
2386 | |||
2387 | mutex_lock(&sc->mutex); | ||
2388 | |||
2389 | /* TODO: Need to decide which hw opmode to use for multi-interface | ||
2390 | * cases */ | ||
2391 | if (vif->type == NL80211_IFTYPE_AP && | ||
2392 | ah->opmode != NL80211_IFTYPE_AP) { | ||
2393 | ah->opmode = NL80211_IFTYPE_STATION; | ||
2394 | ath9k_hw_setopmode(ah); | ||
2395 | memcpy(sc->curbssid, sc->sc_ah->macaddr, ETH_ALEN); | ||
2396 | sc->curaid = 0; | ||
2397 | ath9k_hw_write_associd(sc); | ||
2398 | /* Request full reset to get hw opmode changed properly */ | ||
2399 | sc->sc_flags |= SC_OP_FULL_RESET; | ||
2400 | } | ||
2401 | |||
2402 | if ((conf->changed & IEEE80211_IFCC_BSSID) && | ||
2403 | !is_zero_ether_addr(conf->bssid)) { | ||
2404 | switch (vif->type) { | ||
2405 | case NL80211_IFTYPE_STATION: | ||
2406 | case NL80211_IFTYPE_ADHOC: | ||
2407 | case NL80211_IFTYPE_MESH_POINT: | ||
2408 | /* Set BSSID */ | ||
2409 | memcpy(sc->curbssid, conf->bssid, ETH_ALEN); | ||
2410 | memcpy(avp->bssid, conf->bssid, ETH_ALEN); | ||
2411 | sc->curaid = 0; | ||
2412 | ath9k_hw_write_associd(sc); | ||
2413 | |||
2414 | /* Set aggregation protection mode parameters */ | ||
2415 | sc->config.ath_aggr_prot = 0; | ||
2416 | |||
2417 | DPRINTF(sc, ATH_DBG_CONFIG, | ||
2418 | "RX filter 0x%x bssid %pM aid 0x%x\n", | ||
2419 | rfilt, sc->curbssid, sc->curaid); | ||
2420 | |||
2421 | /* need to reconfigure the beacon */ | ||
2422 | sc->sc_flags &= ~SC_OP_BEACONS ; | ||
2423 | |||
2424 | break; | ||
2425 | default: | ||
2426 | break; | ||
2427 | } | ||
2428 | } | ||
2429 | |||
2430 | if ((vif->type == NL80211_IFTYPE_ADHOC) || | ||
2431 | (vif->type == NL80211_IFTYPE_AP) || | ||
2432 | (vif->type == NL80211_IFTYPE_MESH_POINT)) { | ||
2433 | if ((conf->changed & IEEE80211_IFCC_BEACON) || | ||
2434 | (conf->changed & IEEE80211_IFCC_BEACON_ENABLED && | ||
2435 | conf->enable_beacon)) { | ||
2436 | /* | ||
2437 | * Allocate and setup the beacon frame. | ||
2438 | * | ||
2439 | * Stop any previous beacon DMA. This may be | ||
2440 | * necessary, for example, when an ibss merge | ||
2441 | * causes reconfiguration; we may be called | ||
2442 | * with beacon transmission active. | ||
2443 | */ | ||
2444 | ath9k_hw_stoptxdma(sc->sc_ah, sc->beacon.beaconq); | ||
2445 | |||
2446 | error = ath_beacon_alloc(aphy, vif); | ||
2447 | if (error != 0) { | ||
2448 | mutex_unlock(&sc->mutex); | ||
2449 | return error; | ||
2450 | } | ||
2451 | |||
2452 | ath_beacon_config(sc, vif); | ||
2453 | } | ||
2454 | } | ||
2455 | |||
2456 | /* Check for WLAN_CAPABILITY_PRIVACY ? */ | ||
2457 | if ((avp->av_opmode != NL80211_IFTYPE_STATION)) { | ||
2458 | for (i = 0; i < IEEE80211_WEP_NKID; i++) | ||
2459 | if (ath9k_hw_keyisvalid(sc->sc_ah, (u16)i)) | ||
2460 | ath9k_hw_keysetmac(sc->sc_ah, | ||
2461 | (u16)i, | ||
2462 | sc->curbssid); | ||
2463 | } | ||
2464 | |||
2465 | /* Only legacy IBSS for now */ | ||
2466 | if (vif->type == NL80211_IFTYPE_ADHOC) | ||
2467 | ath_update_chainmask(sc, 0); | ||
2468 | |||
2469 | mutex_unlock(&sc->mutex); | 2361 | mutex_unlock(&sc->mutex); |
2470 | 2362 | ||
2471 | return 0; | 2363 | return 0; |
@@ -2607,9 +2499,92 @@ static void ath9k_bss_info_changed(struct ieee80211_hw *hw, | |||
2607 | { | 2499 | { |
2608 | struct ath_wiphy *aphy = hw->priv; | 2500 | struct ath_wiphy *aphy = hw->priv; |
2609 | struct ath_softc *sc = aphy->sc; | 2501 | struct ath_softc *sc = aphy->sc; |
2502 | struct ath_hw *ah = sc->sc_ah; | ||
2503 | struct ath_vif *avp = (void *)vif->drv_priv; | ||
2504 | u32 rfilt = 0; | ||
2505 | int error, i; | ||
2610 | 2506 | ||
2611 | mutex_lock(&sc->mutex); | 2507 | mutex_lock(&sc->mutex); |
2612 | 2508 | ||
2509 | /* | ||
2510 | * TODO: Need to decide which hw opmode to use for | ||
2511 | * multi-interface cases | ||
2512 | * XXX: This belongs into add_interface! | ||
2513 | */ | ||
2514 | if (vif->type == NL80211_IFTYPE_AP && | ||
2515 | ah->opmode != NL80211_IFTYPE_AP) { | ||
2516 | ah->opmode = NL80211_IFTYPE_STATION; | ||
2517 | ath9k_hw_setopmode(ah); | ||
2518 | memcpy(sc->curbssid, sc->sc_ah->macaddr, ETH_ALEN); | ||
2519 | sc->curaid = 0; | ||
2520 | ath9k_hw_write_associd(sc); | ||
2521 | /* Request full reset to get hw opmode changed properly */ | ||
2522 | sc->sc_flags |= SC_OP_FULL_RESET; | ||
2523 | } | ||
2524 | |||
2525 | if ((changed & BSS_CHANGED_BSSID) && | ||
2526 | !is_zero_ether_addr(bss_conf->bssid)) { | ||
2527 | switch (vif->type) { | ||
2528 | case NL80211_IFTYPE_STATION: | ||
2529 | case NL80211_IFTYPE_ADHOC: | ||
2530 | case NL80211_IFTYPE_MESH_POINT: | ||
2531 | /* Set BSSID */ | ||
2532 | memcpy(sc->curbssid, bss_conf->bssid, ETH_ALEN); | ||
2533 | memcpy(avp->bssid, bss_conf->bssid, ETH_ALEN); | ||
2534 | sc->curaid = 0; | ||
2535 | ath9k_hw_write_associd(sc); | ||
2536 | |||
2537 | /* Set aggregation protection mode parameters */ | ||
2538 | sc->config.ath_aggr_prot = 0; | ||
2539 | |||
2540 | DPRINTF(sc, ATH_DBG_CONFIG, | ||
2541 | "RX filter 0x%x bssid %pM aid 0x%x\n", | ||
2542 | rfilt, sc->curbssid, sc->curaid); | ||
2543 | |||
2544 | /* need to reconfigure the beacon */ | ||
2545 | sc->sc_flags &= ~SC_OP_BEACONS ; | ||
2546 | |||
2547 | break; | ||
2548 | default: | ||
2549 | break; | ||
2550 | } | ||
2551 | } | ||
2552 | |||
2553 | if ((vif->type == NL80211_IFTYPE_ADHOC) || | ||
2554 | (vif->type == NL80211_IFTYPE_AP) || | ||
2555 | (vif->type == NL80211_IFTYPE_MESH_POINT)) { | ||
2556 | if ((changed & BSS_CHANGED_BEACON) || | ||
2557 | (changed & BSS_CHANGED_BEACON_ENABLED && | ||
2558 | bss_conf->enable_beacon)) { | ||
2559 | /* | ||
2560 | * Allocate and setup the beacon frame. | ||
2561 | * | ||
2562 | * Stop any previous beacon DMA. This may be | ||
2563 | * necessary, for example, when an ibss merge | ||
2564 | * causes reconfiguration; we may be called | ||
2565 | * with beacon transmission active. | ||
2566 | */ | ||
2567 | ath9k_hw_stoptxdma(sc->sc_ah, sc->beacon.beaconq); | ||
2568 | |||
2569 | error = ath_beacon_alloc(aphy, vif); | ||
2570 | if (!error) | ||
2571 | ath_beacon_config(sc, vif); | ||
2572 | } | ||
2573 | } | ||
2574 | |||
2575 | /* Check for WLAN_CAPABILITY_PRIVACY ? */ | ||
2576 | if ((avp->av_opmode != NL80211_IFTYPE_STATION)) { | ||
2577 | for (i = 0; i < IEEE80211_WEP_NKID; i++) | ||
2578 | if (ath9k_hw_keyisvalid(sc->sc_ah, (u16)i)) | ||
2579 | ath9k_hw_keysetmac(sc->sc_ah, | ||
2580 | (u16)i, | ||
2581 | sc->curbssid); | ||
2582 | } | ||
2583 | |||
2584 | /* Only legacy IBSS for now */ | ||
2585 | if (vif->type == NL80211_IFTYPE_ADHOC) | ||
2586 | ath_update_chainmask(sc, 0); | ||
2587 | |||
2613 | if (changed & BSS_CHANGED_ERP_PREAMBLE) { | 2588 | if (changed & BSS_CHANGED_ERP_PREAMBLE) { |
2614 | DPRINTF(sc, ATH_DBG_CONFIG, "BSS Changed PREAMBLE %d\n", | 2589 | DPRINTF(sc, ATH_DBG_CONFIG, "BSS Changed PREAMBLE %d\n", |
2615 | bss_conf->use_short_preamble); | 2590 | bss_conf->use_short_preamble); |
@@ -2635,6 +2610,18 @@ static void ath9k_bss_info_changed(struct ieee80211_hw *hw, | |||
2635 | ath9k_bss_assoc_info(sc, vif, bss_conf); | 2610 | ath9k_bss_assoc_info(sc, vif, bss_conf); |
2636 | } | 2611 | } |
2637 | 2612 | ||
2613 | /* | ||
2614 | * The HW TSF has to be reset when the beacon interval changes. | ||
2615 | * We set the flag here, and ath_beacon_config_ap() would take this | ||
2616 | * into account when it gets called through the subsequent | ||
2617 | * config_interface() call - with IFCC_BEACON in the changed field. | ||
2618 | */ | ||
2619 | |||
2620 | if (changed & BSS_CHANGED_BEACON_INT) { | ||
2621 | sc->sc_flags |= SC_OP_TSF_RESET; | ||
2622 | sc->beacon_interval = bss_conf->beacon_int; | ||
2623 | } | ||
2624 | |||
2638 | mutex_unlock(&sc->mutex); | 2625 | mutex_unlock(&sc->mutex); |
2639 | } | 2626 | } |
2640 | 2627 | ||
@@ -2755,7 +2742,6 @@ struct ieee80211_ops ath9k_ops = { | |||
2755 | .add_interface = ath9k_add_interface, | 2742 | .add_interface = ath9k_add_interface, |
2756 | .remove_interface = ath9k_remove_interface, | 2743 | .remove_interface = ath9k_remove_interface, |
2757 | .config = ath9k_config, | 2744 | .config = ath9k_config, |
2758 | .config_interface = ath9k_config_interface, | ||
2759 | .configure_filter = ath9k_configure_filter, | 2745 | .configure_filter = ath9k_configure_filter, |
2760 | .sta_notify = ath9k_sta_notify, | 2746 | .sta_notify = ath9k_sta_notify, |
2761 | .conf_tx = ath9k_conf_tx, | 2747 | .conf_tx = ath9k_conf_tx, |