mac80211: fix peer HT capabilities
authorJohannes Berg <johannes@sipsolutions.net>
Thu, 17 Dec 2009 12:55:48 +0000 (13:55 +0100)
committerJohn W. Linville <linville@tuxdriver.com>
Mon, 21 Dec 2009 16:32:27 +0000 (11:32 -0500)
I noticed yesterday, because Jeff had noticed
a speed regression, cf. bug
http://bugzilla.intellinuxwireless.org/show_bug.cgi?id=2138
that the SM PS settings for peers were wrong.
Instead of overwriting the SM PS settings with
the local bits, we need to keep the remote bits.

The bug was part of the original HT code from
over two years ago, but unfortunately nobody
noticed that it makes no sense -- we shouldn't
be overwriting the peer's setting with our own
but rather keep it intact when masking the peer
capabilities with our own.

While fixing that, I noticed that the masking of
capabilities is completely useless for most of
the bits, so also fix those other bits.

Finally, I also noticed that PSMP_SUPPORT no
longer exists in the final 802.11n version, so
also remove that.

Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
drivers/net/wireless/rt2x00/rt2800lib.c
include/linux/ieee80211.h
net/mac80211/ht.c

index 6bf6c0f..27bf887 100644 (file)
@@ -2080,8 +2080,7 @@ int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
            IEEE80211_HT_CAP_SGI_20 |
            IEEE80211_HT_CAP_SGI_40 |
            IEEE80211_HT_CAP_TX_STBC |
-           IEEE80211_HT_CAP_RX_STBC |
-           IEEE80211_HT_CAP_PSMP_SUPPORT;
+           IEEE80211_HT_CAP_RX_STBC;
        spec->ht.ampdu_factor = 3;
        spec->ht.ampdu_density = 4;
        spec->ht.mcs.tx_params =
index d9724a2..163c840 100644 (file)
@@ -832,7 +832,7 @@ struct ieee80211_ht_cap {
 #define IEEE80211_HT_CAP_DELAY_BA              0x0400
 #define IEEE80211_HT_CAP_MAX_AMSDU             0x0800
 #define IEEE80211_HT_CAP_DSSSCCK40             0x1000
-#define IEEE80211_HT_CAP_PSMP_SUPPORT          0x2000
+#define IEEE80211_HT_CAP_RESERVED              0x2000
 #define IEEE80211_HT_CAP_40MHZ_INTOLERANT      0x4000
 #define IEEE80211_HT_CAP_LSIG_TXOP_PROT                0x8000
 
index 3787455..d7dcee6 100644 (file)
@@ -34,9 +34,28 @@ void ieee80211_ht_cap_ie_to_sta_ht_cap(struct ieee80211_supported_band *sband,
 
        ht_cap->ht_supported = true;
 
-       ht_cap->cap = le16_to_cpu(ht_cap_ie->cap_info) & sband->ht_cap.cap;
-       ht_cap->cap &= ~IEEE80211_HT_CAP_SM_PS;
-       ht_cap->cap |= sband->ht_cap.cap & IEEE80211_HT_CAP_SM_PS;
+       /*
+        * The bits listed in this expression should be
+        * the same for the peer and us, if the station
+        * advertises more then we can't use those thus
+        * we mask them out.
+        */
+       ht_cap->cap = le16_to_cpu(ht_cap_ie->cap_info) &
+               (sband->ht_cap.cap |
+                ~(IEEE80211_HT_CAP_LDPC_CODING |
+                  IEEE80211_HT_CAP_SUP_WIDTH_20_40 |
+                  IEEE80211_HT_CAP_GRN_FLD |
+                  IEEE80211_HT_CAP_SGI_20 |
+                  IEEE80211_HT_CAP_SGI_40 |
+                  IEEE80211_HT_CAP_DSSSCCK40));
+       /*
+        * The STBC bits are asymmetric -- if we don't have
+        * TX then mask out the peer's RX and vice versa.
+        */
+       if (!(sband->ht_cap.cap & IEEE80211_HT_CAP_TX_STBC))
+               ht_cap->cap &= ~IEEE80211_HT_CAP_RX_STBC;
+       if (!(sband->ht_cap.cap & IEEE80211_HT_CAP_RX_STBC))
+               ht_cap->cap &= ~IEEE80211_HT_CAP_TX_STBC;
 
        ampdu_info = ht_cap_ie->ampdu_params_info;
        ht_cap->ampdu_factor =