aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/ath9k
diff options
context:
space:
mode:
authorJohannes Berg <johannes@sipsolutions.net>2008-10-14 10:58:37 -0400
committerJohn W. Linville <linville@tuxdriver.com>2008-10-31 19:00:16 -0400
commitae5eb02641233a4e9d1b92d22090f1b1afa14466 (patch)
tree117b7cb5efa3ff1cf714218098fc6db3820ed4e0 /drivers/net/wireless/ath9k
parentbda3933a8aceedd03e0dd410844bd310033ca756 (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')
-rw-r--r--drivers/net/wireless/ath9k/core.h6
-rw-r--r--drivers/net/wireless/ath9k/main.c41
-rw-r--r--drivers/net/wireless/ath9k/rc.c8
-rw-r--r--drivers/net/wireless/ath9k/recv.c3
-rw-r--r--drivers/net/wireless/ath9k/xmit.c17
5 files changed, 38 insertions, 37 deletions
diff --git a/drivers/net/wireless/ath9k/core.h b/drivers/net/wireless/ath9k/core.h
index cb3e61e57c4d..59d835b72cd8 100644
--- a/drivers/net/wireless/ath9k/core.h
+++ b/drivers/net/wireless/ath9k/core.h
@@ -380,7 +380,6 @@ void ath_rx_cleanup(struct ath_softc *sc);
380int ath_rx_tasklet(struct ath_softc *sc, int flush); 380int ath_rx_tasklet(struct ath_softc *sc, int flush);
381int ath_rx_input(struct ath_softc *sc, 381int ath_rx_input(struct ath_softc *sc,
382 struct ath_node *node, 382 struct ath_node *node,
383 int is_ampdu,
384 struct sk_buff *skb, 383 struct sk_buff *skb,
385 struct ath_recv_status *rx_status, 384 struct ath_recv_status *rx_status,
386 enum ATH_RX_TYPE *status); 385 enum ATH_RX_TYPE *status);
@@ -650,6 +649,9 @@ struct ath_node {
650 u8 an_smmode; /* SM Power save mode */ 649 u8 an_smmode; /* SM Power save mode */
651 u8 an_flags; 650 u8 an_flags;
652 u8 an_addr[ETH_ALEN]; 651 u8 an_addr[ETH_ALEN];
652
653 u16 maxampdu;
654 u8 mpdudensity;
653}; 655};
654 656
655void ath_tx_resume_tid(struct ath_softc *sc, 657void ath_tx_resume_tid(struct ath_softc *sc,
@@ -919,8 +921,6 @@ enum RATE_TYPE {
919 921
920struct ath_ht_info { 922struct ath_ht_info {
921 enum ath9k_ht_macmode tx_chan_width; 923 enum ath9k_ht_macmode tx_chan_width;
922 u16 maxampdu;
923 u8 mpdudensity;
924 u8 ext_chan_offset; 924 u8 ext_chan_offset;
925}; 925};
926 926
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
diff --git a/drivers/net/wireless/ath9k/rc.c b/drivers/net/wireless/ath9k/rc.c
index ee2dbce42b4d..9b2526030965 100644
--- a/drivers/net/wireless/ath9k/rc.c
+++ b/drivers/net/wireless/ath9k/rc.c
@@ -1838,7 +1838,7 @@ void ath_rc_node_update(struct ieee80211_hw *hw, struct ath_rate_node *rc_priv)
1838 struct ath_softc *sc = hw->priv; 1838 struct ath_softc *sc = hw->priv;
1839 u32 capflag = 0; 1839 u32 capflag = 0;
1840 1840
1841 if (hw->conf.ht_cap.ht_supported) { 1841 if (hw->conf.ht.enabled) {
1842 capflag |= ATH_RC_HT_FLAG | ATH_RC_DS_FLAG; 1842 capflag |= ATH_RC_HT_FLAG | ATH_RC_DS_FLAG;
1843 if (sc->sc_ht_info.tx_chan_width == ATH9K_HT_MACMODE_2040) 1843 if (sc->sc_ht_info.tx_chan_width == ATH9K_HT_MACMODE_2040)
1844 capflag |= ATH_RC_CW40_FLAG; 1844 capflag |= ATH_RC_CW40_FLAG;
@@ -1979,7 +1979,7 @@ static void ath_get_rate(void *priv, struct ieee80211_supported_band *sband,
1979 1979
1980 /* Check if aggregation has to be enabled for this tid */ 1980 /* Check if aggregation has to be enabled for this tid */
1981 1981
1982 if (hw->conf.ht_cap.ht_supported) { 1982 if (hw->conf.ht.enabled) {
1983 if (ieee80211_is_data_qos(fc)) { 1983 if (ieee80211_is_data_qos(fc)) {
1984 qc = ieee80211_get_qos_ctl(hdr); 1984 qc = ieee80211_get_qos_ctl(hdr);
1985 tid = qc[0] & 0xf; 1985 tid = qc[0] & 0xf;
@@ -2026,9 +2026,9 @@ static void ath_rate_init(void *priv, struct ieee80211_supported_band *sband,
2026 DPRINTF(sc, ATH_DBG_RATE, "%s\n", __func__); 2026 DPRINTF(sc, ATH_DBG_RATE, "%s\n", __func__);
2027 2027
2028 ath_setup_rates(sc, sband, sta, ath_rc_priv); 2028 ath_setup_rates(sc, sband, sta, ath_rc_priv);
2029 if (sc->hw->conf.flags & IEEE80211_CONF_SUPPORT_HT_MODE) { 2029 if (sc->hw->conf.ht.enabled) {
2030 for (i = 0; i < 77; i++) { 2030 for (i = 0; i < 77; i++) {
2031 if (sc->hw->conf.ht_cap.mcs.rx_mask[i/8] & (1<<(i%8))) 2031 if (sta->ht_cap.mcs.rx_mask[i/8] & (1<<(i%8)))
2032 ath_rc_priv->neg_ht_rates.rs_rates[j++] = i; 2032 ath_rc_priv->neg_ht_rates.rs_rates[j++] = i;
2033 if (j == ATH_RATE_MAX) 2033 if (j == ATH_RATE_MAX)
2034 break; 2034 break;
diff --git a/drivers/net/wireless/ath9k/recv.c b/drivers/net/wireless/ath9k/recv.c
index 010fcdfec3f6..828322840a86 100644
--- a/drivers/net/wireless/ath9k/recv.c
+++ b/drivers/net/wireless/ath9k/recv.c
@@ -720,12 +720,11 @@ void ath_flushrecv(struct ath_softc *sc)
720 720
721int ath_rx_input(struct ath_softc *sc, 721int ath_rx_input(struct ath_softc *sc,
722 struct ath_node *an, 722 struct ath_node *an,
723 int is_ampdu,
724 struct sk_buff *skb, 723 struct sk_buff *skb,
725 struct ath_recv_status *rx_status, 724 struct ath_recv_status *rx_status,
726 enum ATH_RX_TYPE *status) 725 enum ATH_RX_TYPE *status)
727{ 726{
728 if (is_ampdu && (sc->sc_flags & SC_OP_RXAGGR)) { 727 if (sc->sc_flags & SC_OP_RXAGGR) {
729 *status = ATH_RX_CONSUMED; 728 *status = ATH_RX_CONSUMED;
730 return ath_ampdu_input(sc, an, skb, rx_status); 729 return ath_ampdu_input(sc, an, skb, rx_status);
731 } else { 730 } else {
diff --git a/drivers/net/wireless/ath9k/xmit.c b/drivers/net/wireless/ath9k/xmit.c
index 3770fbe84fce..ba818cc2fb5c 100644
--- a/drivers/net/wireless/ath9k/xmit.c
+++ b/drivers/net/wireless/ath9k/xmit.c
@@ -300,7 +300,8 @@ static int ath_tx_prepare(struct ath_softc *sc,
300 if (ieee80211_is_data(fc) && !txctl->use_minrate) { 300 if (ieee80211_is_data(fc) && !txctl->use_minrate) {
301 301
302 /* Enable HT only for DATA frames and not for EAPOL */ 302 /* Enable HT only for DATA frames and not for EAPOL */
303 txctl->ht = (hw->conf.ht_cap.ht_supported && 303 /* XXX why AMPDU only?? */
304 txctl->ht = (hw->conf.ht.enabled &&
304 (tx_info->flags & IEEE80211_TX_CTL_AMPDU)); 305 (tx_info->flags & IEEE80211_TX_CTL_AMPDU));
305 306
306 if (is_multicast_ether_addr(hdr->addr1)) { 307 if (is_multicast_ether_addr(hdr->addr1)) {
@@ -1450,7 +1451,8 @@ static int ath_tx_send_ampdu(struct ath_softc *sc,
1450 */ 1451 */
1451 1452
1452static u32 ath_lookup_rate(struct ath_softc *sc, 1453static u32 ath_lookup_rate(struct ath_softc *sc,
1453 struct ath_buf *bf) 1454 struct ath_buf *bf,
1455 struct ath_atx_tid *tid)
1454{ 1456{
1455 const struct ath9k_rate_table *rt = sc->sc_currates; 1457 const struct ath9k_rate_table *rt = sc->sc_currates;
1456 struct sk_buff *skb; 1458 struct sk_buff *skb;
@@ -1504,7 +1506,7 @@ static u32 ath_lookup_rate(struct ath_softc *sc,
1504 * The IE, however can hold upto 65536, which shows up here 1506 * The IE, however can hold upto 65536, which shows up here
1505 * as zero. Ignore 65536 since we are constrained by hw. 1507 * as zero. Ignore 65536 since we are constrained by hw.
1506 */ 1508 */
1507 maxampdu = sc->sc_ht_info.maxampdu; 1509 maxampdu = tid->an->maxampdu;
1508 if (maxampdu) 1510 if (maxampdu)
1509 aggr_limit = min(aggr_limit, maxampdu); 1511 aggr_limit = min(aggr_limit, maxampdu);
1510 1512
@@ -1518,6 +1520,7 @@ static u32 ath_lookup_rate(struct ath_softc *sc,
1518 */ 1520 */
1519 1521
1520static int ath_compute_num_delims(struct ath_softc *sc, 1522static int ath_compute_num_delims(struct ath_softc *sc,
1523 struct ath_atx_tid *tid,
1521 struct ath_buf *bf, 1524 struct ath_buf *bf,
1522 u16 frmlen) 1525 u16 frmlen)
1523{ 1526{
@@ -1545,7 +1548,7 @@ static int ath_compute_num_delims(struct ath_softc *sc,
1545 * required minimum length for subframe. Take into account 1548 * required minimum length for subframe. Take into account
1546 * whether high rate is 20 or 40Mhz and half or full GI. 1549 * whether high rate is 20 or 40Mhz and half or full GI.
1547 */ 1550 */
1548 mpdudensity = sc->sc_ht_info.mpdudensity; 1551 mpdudensity = tid->an->mpdudensity;
1549 1552
1550 /* 1553 /*
1551 * If there is no mpdu density restriction, no further calculation 1554 * If there is no mpdu density restriction, no further calculation
@@ -1619,7 +1622,7 @@ static enum ATH_AGGR_STATUS ath_tx_form_aggr(struct ath_softc *sc,
1619 } 1622 }
1620 1623
1621 if (!rl) { 1624 if (!rl) {
1622 aggr_limit = ath_lookup_rate(sc, bf); 1625 aggr_limit = ath_lookup_rate(sc, bf, tid);
1623 rl = 1; 1626 rl = 1;
1624 /* 1627 /*
1625 * Is rate dual stream 1628 * Is rate dual stream
@@ -1657,7 +1660,7 @@ static enum ATH_AGGR_STATUS ath_tx_form_aggr(struct ath_softc *sc,
1657 * Get the delimiters needed to meet the MPDU 1660 * Get the delimiters needed to meet the MPDU
1658 * density for this node. 1661 * density for this node.
1659 */ 1662 */
1660 ndelim = ath_compute_num_delims(sc, bf_first, bf->bf_frmlen); 1663 ndelim = ath_compute_num_delims(sc, tid, bf_first, bf->bf_frmlen);
1661 1664
1662 bpad = PADBYTES(al_delta) + (ndelim << 2); 1665 bpad = PADBYTES(al_delta) + (ndelim << 2);
1663 1666
@@ -2629,7 +2632,7 @@ void ath_tx_node_init(struct ath_softc *sc, struct ath_node *an)
2629 struct ath_atx_ac *ac; 2632 struct ath_atx_ac *ac;
2630 int tidno, acno; 2633 int tidno, acno;
2631 2634
2632 sc->sc_ht_info.maxampdu = ATH_AMPDU_LIMIT_DEFAULT; 2635 an->maxampdu = ATH_AMPDU_LIMIT_DEFAULT;
2633 2636
2634 /* 2637 /*
2635 * Init per tid tx state 2638 * Init per tid tx state