summaryrefslogtreecommitdiff
path: root/net/mac80211
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2012-12-27 21:26:42 +0400
committerJohannes Berg <johannes.berg@intel.com>2013-02-15 12:41:31 +0400
commit8921d04e8df7475d733d853564bdb001e83bf33f (patch)
tree44961c6570025b439e7f6b905819d6e54e2d6b43 /net/mac80211
parent7bf9b9a0f0372d45b581f00173505fb76a9c5d23 (diff)
downloadlinux-8921d04e8df7475d733d853564bdb001e83bf33f.tar.xz
mac80211: track number of spatial streams
With VHT, a station can change the number of spatial streams it can receive on the fly, not unlike spatial multiplexing in HT. Prepare for that by tracking the maximum number of spatial streams it can receive when the connection is established. Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Diffstat (limited to 'net/mac80211')
-rw-r--r--net/mac80211/ieee80211_i.h1
-rw-r--r--net/mac80211/rate.h2
-rw-r--r--net/mac80211/vht.c41
3 files changed, 44 insertions, 0 deletions
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 6b41d7787a5a..3b13af4e6c49 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -1432,6 +1432,7 @@ void ieee80211_vht_cap_ie_to_sta_vht_cap(struct ieee80211_sub_if_data *sdata,
struct ieee80211_vht_cap *vht_cap_ie,
struct sta_info *sta);
enum ieee80211_sta_rx_bandwidth ieee80211_sta_cur_vht_bw(struct sta_info *sta);
+void ieee80211_sta_set_rx_nss(struct sta_info *sta);
/* Spectrum management */
void ieee80211_process_measurement_req(struct ieee80211_sub_if_data *sdata,
diff --git a/net/mac80211/rate.h b/net/mac80211/rate.h
index 301386dabf88..d35a5dd3fb13 100644
--- a/net/mac80211/rate.h
+++ b/net/mac80211/rate.h
@@ -68,6 +68,8 @@ static inline void rate_control_rate_init(struct sta_info *sta)
sband = local->hw.wiphy->bands[chanctx_conf->def.chan->band];
rcu_read_unlock();
+ ieee80211_sta_set_rx_nss(sta);
+
ref->ops->rate_init(ref->priv, sband, ista, priv_sta);
set_sta_flag(sta, WLAN_STA_RATE_CONTROL);
}
diff --git a/net/mac80211/vht.c b/net/mac80211/vht.c
index 0fc9a2fb8d53..67436e3efbbd 100644
--- a/net/mac80211/vht.c
+++ b/net/mac80211/vht.c
@@ -74,3 +74,44 @@ enum ieee80211_sta_rx_bandwidth ieee80211_sta_cur_vht_bw(struct sta_info *sta)
return IEEE80211_STA_RX_BW_80;
}
}
+
+void ieee80211_sta_set_rx_nss(struct sta_info *sta)
+{
+ u8 ht_rx_nss = 0, vht_rx_nss = 0;
+
+ /* if we received a notification already don't overwrite it */
+ if (sta->sta.rx_nss)
+ return;
+
+ if (sta->sta.ht_cap.ht_supported) {
+ if (sta->sta.ht_cap.mcs.rx_mask[0])
+ ht_rx_nss++;
+ if (sta->sta.ht_cap.mcs.rx_mask[1])
+ ht_rx_nss++;
+ if (sta->sta.ht_cap.mcs.rx_mask[2])
+ ht_rx_nss++;
+ if (sta->sta.ht_cap.mcs.rx_mask[3])
+ ht_rx_nss++;
+ /* FIXME: consider rx_highest? */
+ }
+
+ if (sta->sta.vht_cap.vht_supported) {
+ int i;
+ u16 rx_mcs_map;
+
+ rx_mcs_map = le16_to_cpu(sta->sta.vht_cap.vht_mcs.rx_mcs_map);
+
+ for (i = 7; i >= 0; i--) {
+ u8 mcs = (rx_mcs_map >> (2 * i)) & 3;
+
+ if (mcs != IEEE80211_VHT_MCS_NOT_SUPPORTED) {
+ vht_rx_nss = i + 1;
+ break;
+ }
+ }
+ /* FIXME: consider rx_highest? */
+ }
+
+ ht_rx_nss = max(ht_rx_nss, vht_rx_nss);
+ sta->sta.rx_nss = max_t(u8, 1, ht_rx_nss);
+}