diff options
author | Johannes Berg <johannes@sipsolutions.net> | 2008-10-14 10:58:37 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2008-10-31 19:00:16 -0400 |
commit | ae5eb02641233a4e9d1b92d22090f1b1afa14466 (patch) | |
tree | 117b7cb5efa3ff1cf714218098fc6db3820ed4e0 /drivers/net/wireless/ath9k/main.c | |
parent | bda3933a8aceedd03e0dd410844bd310033ca756 (diff) |
mac80211: rewrite HT handling
The HT handling has the following deficiencies, which I've
(partially) fixed:
* it always uses the AP info even if there is no AP,
hence has no chance of working as an AP
* it pretends to be HW config, but really is per-BSS
* channel sanity checking is left to the drivers
* it generally lets the driver control too much
HT enabling is still wrong with this patch if you have more than
one virtual STA mode interface, but that never happens currently.
Once WDS, IBSS or AP/VLAN gets HT capabilities, it will also be
wrong, see the comment in ieee80211_enable_ht().
Additionally, this fixes a number of bugs:
* mac80211: ieee80211_set_disassoc doesn't notify the driver any
more since the refactoring
* iwl-agn-rs: always uses the HT capabilities from the wrong stuff
mac80211 gives it rather than the actual peer STA
* ath9k: a number of bugs resulting from the broken HT API
I'm not entirely happy with putting the HT capabilities into
struct ieee80211_sta as restricted to our own HT TX capabilities,
but I see no cleaner solution for now.
Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/ath9k/main.c')
-rw-r--r-- | drivers/net/wireless/ath9k/main.c | 41 |
1 files changed, 20 insertions, 21 deletions
diff --git a/drivers/net/wireless/ath9k/main.c b/drivers/net/wireless/ath9k/main.c index 41cd114c438c..7555c3413384 100644 --- a/drivers/net/wireless/ath9k/main.c +++ b/drivers/net/wireless/ath9k/main.c | |||
@@ -330,25 +330,15 @@ static void ath9k_ht_conf(struct ath_softc *sc, | |||
330 | { | 330 | { |
331 | struct ath_ht_info *ht_info = &sc->sc_ht_info; | 331 | struct ath_ht_info *ht_info = &sc->sc_ht_info; |
332 | 332 | ||
333 | if (bss_conf->assoc_ht) { | 333 | if (sc->hw->conf.ht.enabled) { |
334 | ht_info->ext_chan_offset = | 334 | ht_info->ext_chan_offset = bss_conf->ht.secondary_channel_offset; |
335 | bss_conf->ht_bss_conf->bss_cap & | 335 | |
336 | IEEE80211_HT_PARAM_CHA_SEC_OFFSET; | 336 | if (bss_conf->ht.width_40_ok) |
337 | |||
338 | if (!(bss_conf->ht_cap->cap & | ||
339 | IEEE80211_HT_CAP_40MHZ_INTOLERANT) && | ||
340 | (bss_conf->ht_bss_conf->bss_cap & | ||
341 | IEEE80211_HT_PARAM_CHAN_WIDTH_ANY)) | ||
342 | ht_info->tx_chan_width = ATH9K_HT_MACMODE_2040; | 337 | ht_info->tx_chan_width = ATH9K_HT_MACMODE_2040; |
343 | else | 338 | else |
344 | ht_info->tx_chan_width = ATH9K_HT_MACMODE_20; | 339 | ht_info->tx_chan_width = ATH9K_HT_MACMODE_20; |
345 | 340 | ||
346 | ath9k_hw_set11nmac2040(sc->sc_ah, ht_info->tx_chan_width); | 341 | ath9k_hw_set11nmac2040(sc->sc_ah, ht_info->tx_chan_width); |
347 | ht_info->maxampdu = 1 << (IEEE80211_HTCAP_MAXRXAMPDU_FACTOR + | ||
348 | bss_conf->ht_cap->ampdu_factor); | ||
349 | ht_info->mpdudensity = | ||
350 | parse_mpdudensity(bss_conf->ht_cap->ampdu_density); | ||
351 | |||
352 | } | 342 | } |
353 | } | 343 | } |
354 | 344 | ||
@@ -390,7 +380,7 @@ static void ath9k_bss_assoc_info(struct ath_softc *sc, | |||
390 | sc->sc_halstats.ns_avgtxrate = ATH_RATE_DUMMY_MARKER; | 380 | sc->sc_halstats.ns_avgtxrate = ATH_RATE_DUMMY_MARKER; |
391 | 381 | ||
392 | /* Update chainmask */ | 382 | /* Update chainmask */ |
393 | ath_update_chainmask(sc, bss_conf->assoc_ht); | 383 | ath_update_chainmask(sc, hw->conf.ht.enabled); |
394 | 384 | ||
395 | DPRINTF(sc, ATH_DBG_CONFIG, | 385 | DPRINTF(sc, ATH_DBG_CONFIG, |
396 | "%s: bssid %pM aid 0x%x\n", | 386 | "%s: bssid %pM aid 0x%x\n", |
@@ -408,7 +398,7 @@ static void ath9k_bss_assoc_info(struct ath_softc *sc, | |||
408 | return; | 398 | return; |
409 | } | 399 | } |
410 | 400 | ||
411 | if (hw->conf.ht_cap.ht_supported) | 401 | if (hw->conf.ht.enabled) |
412 | sc->sc_ah->ah_channels[pos].chanmode = | 402 | sc->sc_ah->ah_channels[pos].chanmode = |
413 | ath_get_extchanmode(sc, curchan); | 403 | ath_get_extchanmode(sc, curchan); |
414 | else | 404 | else |
@@ -531,7 +521,6 @@ int _ath_rx_indicate(struct ath_softc *sc, | |||
531 | 521 | ||
532 | if (an) { | 522 | if (an) { |
533 | ath_rx_input(sc, an, | 523 | ath_rx_input(sc, an, |
534 | hw->conf.ht_cap.ht_supported, | ||
535 | skb, status, &st); | 524 | skb, status, &st); |
536 | } | 525 | } |
537 | if (!an || (st != ATH_RX_CONSUMED)) | 526 | if (!an || (st != ATH_RX_CONSUMED)) |
@@ -1241,6 +1230,9 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed) | |||
1241 | __func__, | 1230 | __func__, |
1242 | curchan->center_freq); | 1231 | curchan->center_freq); |
1243 | 1232 | ||
1233 | /* Update chainmask */ | ||
1234 | ath_update_chainmask(sc, conf->ht.enabled); | ||
1235 | |||
1244 | pos = ath_get_channel(sc, curchan); | 1236 | pos = ath_get_channel(sc, curchan); |
1245 | if (pos == -1) { | 1237 | if (pos == -1) { |
1246 | DPRINTF(sc, ATH_DBG_FATAL, "%s: Invalid channel\n", __func__); | 1238 | DPRINTF(sc, ATH_DBG_FATAL, "%s: Invalid channel\n", __func__); |
@@ -1251,7 +1243,7 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed) | |||
1251 | (curchan->band == IEEE80211_BAND_2GHZ) ? | 1243 | (curchan->band == IEEE80211_BAND_2GHZ) ? |
1252 | CHANNEL_G : CHANNEL_A; | 1244 | CHANNEL_G : CHANNEL_A; |
1253 | 1245 | ||
1254 | if (sc->sc_curaid && hw->conf.ht_cap.ht_supported) | 1246 | if (sc->sc_curaid && hw->conf.ht.enabled) |
1255 | sc->sc_ah->ah_channels[pos].chanmode = | 1247 | sc->sc_ah->ah_channels[pos].chanmode = |
1256 | ath_get_extchanmode(sc, curchan); | 1248 | ath_get_extchanmode(sc, curchan); |
1257 | 1249 | ||
@@ -1434,6 +1426,14 @@ static void ath9k_sta_notify(struct ieee80211_hw *hw, | |||
1434 | } else { | 1426 | } else { |
1435 | ath_node_get(sc, sta->addr); | 1427 | ath_node_get(sc, sta->addr); |
1436 | } | 1428 | } |
1429 | |||
1430 | /* XXX: Is this right? Can the capabilities change? */ | ||
1431 | an = ath_node_find(sc, sta->addr); | ||
1432 | an->maxampdu = 1 << (IEEE80211_HTCAP_MAXRXAMPDU_FACTOR + | ||
1433 | sta->ht_cap.ampdu_factor); | ||
1434 | an->mpdudensity = | ||
1435 | parse_mpdudensity(sta->ht_cap.ampdu_density); | ||
1436 | |||
1437 | spin_unlock_irqrestore(&sc->node_lock, flags); | 1437 | spin_unlock_irqrestore(&sc->node_lock, flags); |
1438 | break; | 1438 | break; |
1439 | case STA_NOTIFY_REMOVE: | 1439 | case STA_NOTIFY_REMOVE: |
@@ -1552,9 +1552,8 @@ static void ath9k_bss_info_changed(struct ieee80211_hw *hw, | |||
1552 | } | 1552 | } |
1553 | 1553 | ||
1554 | if (changed & BSS_CHANGED_HT) { | 1554 | if (changed & BSS_CHANGED_HT) { |
1555 | DPRINTF(sc, ATH_DBG_CONFIG, "%s: BSS Changed HT %d\n", | 1555 | DPRINTF(sc, ATH_DBG_CONFIG, "%s: BSS Changed HT\n", |
1556 | __func__, | 1556 | __func__); |
1557 | bss_conf->assoc_ht); | ||
1558 | ath9k_ht_conf(sc, bss_conf); | 1557 | ath9k_ht_conf(sc, bss_conf); |
1559 | } | 1558 | } |
1560 | 1559 | ||