aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-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
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-rs.c23
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn.c39
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-core.c17
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-dev.h1
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-sta.c33
10 files changed, 100 insertions, 88 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
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c
index cd1bff590491..e10e0ca09ce9 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c
@@ -1133,8 +1133,7 @@ static int rs_switch_to_mimo2(struct iwl_priv *priv,
1133 s32 rate; 1133 s32 rate;
1134 s8 is_green = lq_sta->is_green; 1134 s8 is_green = lq_sta->is_green;
1135 1135
1136 if (!(conf->flags & IEEE80211_CONF_SUPPORT_HT_MODE) || 1136 if (!conf->ht.enabled || !sta->ht_cap.ht_supported)
1137 !sta->ht_cap.ht_supported)
1138 return -1; 1137 return -1;
1139 1138
1140 if (((sta->ht_cap.cap & IEEE80211_HT_CAP_SM_PS) >> 2) 1139 if (((sta->ht_cap.cap & IEEE80211_HT_CAP_SM_PS) >> 2)
@@ -1201,8 +1200,7 @@ static int rs_switch_to_siso(struct iwl_priv *priv,
1201 u8 is_green = lq_sta->is_green; 1200 u8 is_green = lq_sta->is_green;
1202 s32 rate; 1201 s32 rate;
1203 1202
1204 if (!(conf->flags & IEEE80211_CONF_SUPPORT_HT_MODE) || 1203 if (!conf->ht.enabled || !sta->ht_cap.ht_supported)
1205 !sta->ht_cap.ht_supported)
1206 return -1; 1204 return -1;
1207 1205
1208 IWL_DEBUG_RATE("LQ: try to switch to SISO\n"); 1206 IWL_DEBUG_RATE("LQ: try to switch to SISO\n");
@@ -2001,9 +1999,8 @@ lq_update:
2001 * stay with best antenna legacy modulation for a while 1999 * stay with best antenna legacy modulation for a while
2002 * before next round of mode comparisons. */ 2000 * before next round of mode comparisons. */
2003 tbl1 = &(lq_sta->lq_info[lq_sta->active_tbl]); 2001 tbl1 = &(lq_sta->lq_info[lq_sta->active_tbl]);
2004 if (is_legacy(tbl1->lq_type) && 2002 if (is_legacy(tbl1->lq_type) && !conf->ht.enabled &&
2005 (!(conf->flags & IEEE80211_CONF_SUPPORT_HT_MODE)) && 2003 lq_sta->action_counter >= 1) {
2006 (lq_sta->action_counter >= 1)) {
2007 lq_sta->action_counter = 0; 2004 lq_sta->action_counter = 0;
2008 IWL_DEBUG_RATE("LQ: STAY in legacy table\n"); 2005 IWL_DEBUG_RATE("LQ: STAY in legacy table\n");
2009 rs_set_stay_in_table(priv, 1, lq_sta); 2006 rs_set_stay_in_table(priv, 1, lq_sta);
@@ -2238,19 +2235,19 @@ static void rs_rate_init(void *priv_r, struct ieee80211_supported_band *sband,
2238 * active_siso_rate mask includes 9 MBits (bit 5), and CCK (bits 0-3), 2235 * active_siso_rate mask includes 9 MBits (bit 5), and CCK (bits 0-3),
2239 * supp_rates[] does not; shift to convert format, force 9 MBits off. 2236 * supp_rates[] does not; shift to convert format, force 9 MBits off.
2240 */ 2237 */
2241 lq_sta->active_siso_rate = conf->ht_cap.mcs.rx_mask[0] << 1; 2238 lq_sta->active_siso_rate = sta->ht_cap.mcs.rx_mask[0] << 1;
2242 lq_sta->active_siso_rate |= conf->ht_cap.mcs.rx_mask[0] & 0x1; 2239 lq_sta->active_siso_rate |= sta->ht_cap.mcs.rx_mask[0] & 0x1;
2243 lq_sta->active_siso_rate &= ~((u16)0x2); 2240 lq_sta->active_siso_rate &= ~((u16)0x2);
2244 lq_sta->active_siso_rate <<= IWL_FIRST_OFDM_RATE; 2241 lq_sta->active_siso_rate <<= IWL_FIRST_OFDM_RATE;
2245 2242
2246 /* Same here */ 2243 /* Same here */
2247 lq_sta->active_mimo2_rate = conf->ht_cap.mcs.rx_mask[1] << 1; 2244 lq_sta->active_mimo2_rate = sta->ht_cap.mcs.rx_mask[1] << 1;
2248 lq_sta->active_mimo2_rate |= conf->ht_cap.mcs.rx_mask[1] & 0x1; 2245 lq_sta->active_mimo2_rate |= sta->ht_cap.mcs.rx_mask[1] & 0x1;
2249 lq_sta->active_mimo2_rate &= ~((u16)0x2); 2246 lq_sta->active_mimo2_rate &= ~((u16)0x2);
2250 lq_sta->active_mimo2_rate <<= IWL_FIRST_OFDM_RATE; 2247 lq_sta->active_mimo2_rate <<= IWL_FIRST_OFDM_RATE;
2251 2248
2252 lq_sta->active_mimo3_rate = conf->ht_cap.mcs.rx_mask[2] << 1; 2249 lq_sta->active_mimo3_rate = sta->ht_cap.mcs.rx_mask[2] << 1;
2253 lq_sta->active_mimo3_rate |= conf->ht_cap.mcs.rx_mask[2] & 0x1; 2250 lq_sta->active_mimo3_rate |= sta->ht_cap.mcs.rx_mask[2] & 0x1;
2254 lq_sta->active_mimo3_rate &= ~((u16)0x2); 2251 lq_sta->active_mimo3_rate &= ~((u16)0x2);
2255 lq_sta->active_mimo3_rate <<= IWL_FIRST_OFDM_RATE; 2252 lq_sta->active_mimo3_rate <<= IWL_FIRST_OFDM_RATE;
2256 2253
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c
index 79a24410dd0a..7c3eb3d8f7e7 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn.c
@@ -552,17 +552,30 @@ static int iwl4965_send_beacon_cmd(struct iwl_priv *priv)
552static void iwl4965_ht_conf(struct iwl_priv *priv, 552static void iwl4965_ht_conf(struct iwl_priv *priv,
553 struct ieee80211_bss_conf *bss_conf) 553 struct ieee80211_bss_conf *bss_conf)
554{ 554{
555 struct ieee80211_sta_ht_cap *ht_conf = bss_conf->ht_cap; 555 struct ieee80211_sta_ht_cap *ht_conf;
556 struct ieee80211_ht_bss_info *ht_bss_conf = bss_conf->ht_bss_conf;
557 struct iwl_ht_info *iwl_conf = &priv->current_ht_config; 556 struct iwl_ht_info *iwl_conf = &priv->current_ht_config;
557 struct ieee80211_sta *sta;
558 558
559 IWL_DEBUG_MAC80211("enter: \n"); 559 IWL_DEBUG_MAC80211("enter: \n");
560 560
561 iwl_conf->is_ht = bss_conf->assoc_ht;
562
563 if (!iwl_conf->is_ht) 561 if (!iwl_conf->is_ht)
564 return; 562 return;
565 563
564
565 /*
566 * It is totally wrong to base global information on something
567 * that is valid only when associated, alas, this driver works
568 * that way and I don't know how to fix it.
569 */
570
571 rcu_read_lock();
572 sta = ieee80211_find_sta(priv->hw, priv->bssid);
573 if (!sta) {
574 rcu_read_unlock();
575 return;
576 }
577 ht_conf = &sta->ht_cap;
578
566 if (ht_conf->cap & IEEE80211_HT_CAP_SGI_20) 579 if (ht_conf->cap & IEEE80211_HT_CAP_SGI_20)
567 iwl_conf->sgf |= HT_SHORT_GI_20MHZ; 580 iwl_conf->sgf |= HT_SHORT_GI_20MHZ;
568 if (ht_conf->cap & IEEE80211_HT_CAP_SGI_40) 581 if (ht_conf->cap & IEEE80211_HT_CAP_SGI_40)
@@ -574,8 +587,8 @@ static void iwl4965_ht_conf(struct iwl_priv *priv,
574 587
575 iwl_conf->supported_chan_width = 588 iwl_conf->supported_chan_width =
576 !!(ht_conf->cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40); 589 !!(ht_conf->cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40);
577 iwl_conf->extension_chan_offset = 590
578 ht_bss_conf->bss_cap & IEEE80211_HT_PARAM_CHA_SEC_OFFSET; 591 iwl_conf->extension_chan_offset = bss_conf->ht.secondary_channel_offset;
579 /* If no above or below channel supplied disable FAT channel */ 592 /* If no above or below channel supplied disable FAT channel */
580 if (iwl_conf->extension_chan_offset != IEEE80211_HT_PARAM_CHA_SEC_ABOVE && 593 if (iwl_conf->extension_chan_offset != IEEE80211_HT_PARAM_CHA_SEC_ABOVE &&
581 iwl_conf->extension_chan_offset != IEEE80211_HT_PARAM_CHA_SEC_BELOW) { 594 iwl_conf->extension_chan_offset != IEEE80211_HT_PARAM_CHA_SEC_BELOW) {
@@ -587,15 +600,14 @@ static void iwl4965_ht_conf(struct iwl_priv *priv,
587 600
588 memcpy(&iwl_conf->mcs, &ht_conf->mcs, 16); 601 memcpy(&iwl_conf->mcs, &ht_conf->mcs, 16);
589 602
590 iwl_conf->control_channel = ht_bss_conf->primary_channel; 603 iwl_conf->tx_chan_width = bss_conf->ht.width_40_ok;
591 iwl_conf->tx_chan_width =
592 !!(ht_bss_conf->bss_cap & IEEE80211_HT_PARAM_CHAN_WIDTH_ANY);
593 iwl_conf->ht_protection = 604 iwl_conf->ht_protection =
594 ht_bss_conf->bss_op_mode & IEEE80211_HT_OP_MODE_PROTECTION; 605 bss_conf->ht.operation_mode & IEEE80211_HT_OP_MODE_PROTECTION;
595 iwl_conf->non_GF_STA_present = 606 iwl_conf->non_GF_STA_present =
596 !!(ht_bss_conf->bss_op_mode & IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT); 607 !!(bss_conf->ht.operation_mode & IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT);
608
609 rcu_read_unlock();
597 610
598 IWL_DEBUG_MAC80211("control channel %d\n", iwl_conf->control_channel);
599 IWL_DEBUG_MAC80211("leave\n"); 611 IWL_DEBUG_MAC80211("leave\n");
600} 612}
601 613
@@ -2746,6 +2758,8 @@ static int iwl4965_mac_config(struct ieee80211_hw *hw, u32 changed)
2746 mutex_lock(&priv->mutex); 2758 mutex_lock(&priv->mutex);
2747 IWL_DEBUG_MAC80211("enter to channel %d\n", conf->channel->hw_value); 2759 IWL_DEBUG_MAC80211("enter to channel %d\n", conf->channel->hw_value);
2748 2760
2761 priv->current_ht_config.is_ht = conf->ht.enabled;
2762
2749 if (conf->radio_enabled && iwl_radio_kill_sw_enable_radio(priv)) { 2763 if (conf->radio_enabled && iwl_radio_kill_sw_enable_radio(priv)) {
2750 IWL_DEBUG_MAC80211("leave - RF-KILL - waiting for uCode\n"); 2764 IWL_DEBUG_MAC80211("leave - RF-KILL - waiting for uCode\n");
2751 goto out; 2765 goto out;
@@ -3104,7 +3118,6 @@ static void iwl4965_bss_info_changed(struct ieee80211_hw *hw,
3104 } 3118 }
3105 3119
3106 if (changes & BSS_CHANGED_HT) { 3120 if (changes & BSS_CHANGED_HT) {
3107 IWL_DEBUG_MAC80211("HT %d\n", bss_conf->assoc_ht);
3108 iwl4965_ht_conf(priv, bss_conf); 3121 iwl4965_ht_conf(priv, bss_conf);
3109 iwl_set_rxon_chain(priv); 3122 iwl_set_rxon_chain(priv);
3110 } 3123 }
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c
index 4678da447ff6..10f5a0a233fe 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.c
+++ b/drivers/net/wireless/iwlwifi/iwl-core.c
@@ -637,8 +637,8 @@ u8 iwl_is_fat_tx_allowed(struct iwl_priv *priv,
637 } 637 }
638 638
639 return iwl_is_channel_extension(priv, priv->band, 639 return iwl_is_channel_extension(priv, priv->band,
640 iwl_ht_conf->control_channel, 640 le16_to_cpu(priv->staging_rxon.channel),
641 iwl_ht_conf->extension_chan_offset); 641 iwl_ht_conf->extension_chan_offset);
642} 642}
643EXPORT_SYMBOL(iwl_is_fat_tx_allowed); 643EXPORT_SYMBOL(iwl_is_fat_tx_allowed);
644 644
@@ -663,13 +663,6 @@ void iwl_set_rxon_ht(struct iwl_priv *priv, struct iwl_ht_info *ht_info)
663 rxon->flags &= ~(RXON_FLG_CHANNEL_MODE_MIXED_MSK | 663 rxon->flags &= ~(RXON_FLG_CHANNEL_MODE_MIXED_MSK |
664 RXON_FLG_CHANNEL_MODE_PURE_40_MSK); 664 RXON_FLG_CHANNEL_MODE_PURE_40_MSK);
665 665
666 if (le16_to_cpu(rxon->channel) != ht_info->control_channel) {
667 IWL_DEBUG_ASSOC("control diff than current %d %d\n",
668 le16_to_cpu(rxon->channel),
669 ht_info->control_channel);
670 return;
671 }
672
673 /* Note: control channel is opposite of extension channel */ 666 /* Note: control channel is opposite of extension channel */
674 switch (ht_info->extension_chan_offset) { 667 switch (ht_info->extension_chan_offset) {
675 case IEEE80211_HT_PARAM_CHA_SEC_ABOVE: 668 case IEEE80211_HT_PARAM_CHA_SEC_ABOVE:
@@ -692,14 +685,12 @@ void iwl_set_rxon_ht(struct iwl_priv *priv, struct iwl_ht_info *ht_info)
692 685
693 IWL_DEBUG_ASSOC("supported HT rate 0x%X 0x%X 0x%X " 686 IWL_DEBUG_ASSOC("supported HT rate 0x%X 0x%X 0x%X "
694 "rxon flags 0x%X operation mode :0x%X " 687 "rxon flags 0x%X operation mode :0x%X "
695 "extension channel offset 0x%x " 688 "extension channel offset 0x%x\n",
696 "control chan %d\n",
697 ht_info->mcs.rx_mask[0], 689 ht_info->mcs.rx_mask[0],
698 ht_info->mcs.rx_mask[1], 690 ht_info->mcs.rx_mask[1],
699 ht_info->mcs.rx_mask[2], 691 ht_info->mcs.rx_mask[2],
700 le32_to_cpu(rxon->flags), ht_info->ht_protection, 692 le32_to_cpu(rxon->flags), ht_info->ht_protection,
701 ht_info->extension_chan_offset, 693 ht_info->extension_chan_offset);
702 ht_info->control_channel);
703 return; 694 return;
704} 695}
705EXPORT_SYMBOL(iwl_set_rxon_ht); 696EXPORT_SYMBOL(iwl_set_rxon_ht);
diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h
index 572250ee9d58..2e9514933970 100644
--- a/drivers/net/wireless/iwlwifi/iwl-dev.h
+++ b/drivers/net/wireless/iwlwifi/iwl-dev.h
@@ -413,7 +413,6 @@ struct iwl_ht_info {
413 u8 mpdu_density; 413 u8 mpdu_density;
414 struct ieee80211_mcs_info mcs; 414 struct ieee80211_mcs_info mcs;
415 /* BSS related data */ 415 /* BSS related data */
416 u8 control_channel;
417 u8 extension_chan_offset; 416 u8 extension_chan_offset;
418 u8 tx_chan_width; 417 u8 tx_chan_width;
419 u8 ht_protection; 418 u8 ht_protection;
diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.c b/drivers/net/wireless/iwlwifi/iwl-sta.c
index b9b8554433a6..218483d096cc 100644
--- a/drivers/net/wireless/iwlwifi/iwl-sta.c
+++ b/drivers/net/wireless/iwlwifi/iwl-sta.c
@@ -890,20 +890,31 @@ static void iwl_sta_init_lq(struct iwl_priv *priv, const u8 *addr, int is_ap)
890 */ 890 */
891int iwl_rxon_add_station(struct iwl_priv *priv, const u8 *addr, int is_ap) 891int iwl_rxon_add_station(struct iwl_priv *priv, const u8 *addr, int is_ap)
892{ 892{
893 struct ieee80211_sta *sta;
894 struct ieee80211_sta_ht_cap ht_config;
895 struct ieee80211_sta_ht_cap *cur_ht_config = NULL;
893 u8 sta_id; 896 u8 sta_id;
894 897
895 /* Add station to device's station table */ 898 /* Add station to device's station table */
896 struct ieee80211_conf *conf = &priv->hw->conf; 899
897 struct ieee80211_sta_ht_cap *cur_ht_config = &conf->ht_cap; 900 /*
898 901 * XXX: This check is definitely not correct, if we're an AP
899 if ((is_ap) && 902 * it'll always be false which is not what we want, but
900 (conf->flags & IEEE80211_CONF_SUPPORT_HT_MODE) && 903 * it doesn't look like iwlagn is prepared to be an HT
901 (priv->iw_mode == NL80211_IFTYPE_STATION)) 904 * AP anyway.
902 sta_id = iwl_add_station_flags(priv, addr, is_ap, 905 */
903 0, cur_ht_config); 906 if (priv->current_ht_config.is_ht) {
904 else 907 rcu_read_lock();
905 sta_id = iwl_add_station_flags(priv, addr, is_ap, 908 sta = ieee80211_find_sta(priv->hw, addr);
906 0, NULL); 909 if (sta) {
910 memcpy(&ht_config, &sta->ht_cap, sizeof(ht_config));
911 cur_ht_config = &ht_config;
912 }
913 rcu_read_unlock();
914 }
915
916 sta_id = iwl_add_station_flags(priv, addr, is_ap,
917 0, cur_ht_config);
907 918
908 /* Set up default rate scaling table in device's station table */ 919 /* Set up default rate scaling table in device's station table */
909 iwl_sta_init_lq(priv, addr, is_ap); 920 iwl_sta_init_lq(priv, addr, is_ap);