aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/ath/ath9k/main.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/ath/ath9k/main.c')
-rw-r--r--drivers/net/wireless/ath/ath9k/main.c206
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
190static void ath_setup_rates(struct ath_softc *sc, enum ieee80211_band band) 190static 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
2376static 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,