aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2012-11-09 09:07:02 -0500
committerJohannes Berg <johannes.berg@intel.com>2012-11-26 06:42:59 -0500
commit5614618ec498320e3b686fea246e50b833865c34 (patch)
treea319fd5575bc7ee090136e6e7829200a152886cf /net/mac80211
parentdb9c64cf8d9d3fcbc34b09d037f266d1fc9f928c (diff)
mac80211: support drivers reporting VHT RX
Add support to mac80211 for having drivers report received VHT MCS information. Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Diffstat (limited to 'net/mac80211')
-rw-r--r--net/mac80211/cfg.c26
-rw-r--r--net/mac80211/rx.c20
-rw-r--r--net/mac80211/sta_info.h4
-rw-r--r--net/mac80211/util.c14
4 files changed, 55 insertions, 9 deletions
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index b9702d16d608..0b9de4fa54a6 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -374,7 +374,8 @@ static void rate_idx_to_bitrate(struct rate_info *rate, struct sta_info *sta, in
374{ 374{
375 enum ieee80211_band band = ieee80211_get_sdata_band(sta->sdata); 375 enum ieee80211_band band = ieee80211_get_sdata_band(sta->sdata);
376 376
377 if (!(rate->flags & RATE_INFO_FLAGS_MCS)) { 377 if (!(rate->flags & RATE_INFO_FLAGS_MCS) &&
378 !(rate->flags & RATE_INFO_FLAGS_VHT_MCS)) {
378 struct ieee80211_supported_band *sband; 379 struct ieee80211_supported_band *sband;
379 sband = sta->local->hw.wiphy->bands[band]; 380 sband = sta->local->hw.wiphy->bands[band];
380 rate->legacy = sband->bitrates[idx].bitrate; 381 rate->legacy = sband->bitrates[idx].bitrate;
@@ -444,13 +445,32 @@ static void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo)
444 sta_set_rate_info_tx(sta, &sta->last_tx_rate, &sinfo->txrate); 445 sta_set_rate_info_tx(sta, &sta->last_tx_rate, &sinfo->txrate);
445 446
446 sinfo->rxrate.flags = 0; 447 sinfo->rxrate.flags = 0;
447 if (sta->last_rx_rate_flag & RX_FLAG_HT) 448 if (sta->last_rx_rate_flag & RX_FLAG_HT) {
448 sinfo->rxrate.flags |= RATE_INFO_FLAGS_MCS; 449 sinfo->rxrate.flags |= RATE_INFO_FLAGS_MCS;
450 sinfo->rxrate.mcs = sta->last_rx_rate_idx;
451 } else if (sta->last_rx_rate_flag & RX_FLAG_VHT) {
452 sinfo->rxrate.flags |= RATE_INFO_FLAGS_VHT_MCS;
453 sinfo->rxrate.nss = sta->last_rx_rate_vht_nss;
454 sinfo->rxrate.mcs = sta->last_rx_rate_idx;
455 } else {
456 struct ieee80211_supported_band *sband;
457
458 sband = sta->local->hw.wiphy->bands[
459 ieee80211_get_sdata_band(sta->sdata)];
460 sinfo->rxrate.legacy =
461 sband->bitrates[sta->last_rx_rate_idx].bitrate;
462 }
463
449 if (sta->last_rx_rate_flag & RX_FLAG_40MHZ) 464 if (sta->last_rx_rate_flag & RX_FLAG_40MHZ)
450 sinfo->rxrate.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH; 465 sinfo->rxrate.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
451 if (sta->last_rx_rate_flag & RX_FLAG_SHORT_GI) 466 if (sta->last_rx_rate_flag & RX_FLAG_SHORT_GI)
452 sinfo->rxrate.flags |= RATE_INFO_FLAGS_SHORT_GI; 467 sinfo->rxrate.flags |= RATE_INFO_FLAGS_SHORT_GI;
453 rate_idx_to_bitrate(&sinfo->rxrate, sta, sta->last_rx_rate_idx); 468 if (sta->last_rx_rate_flag & RX_FLAG_80MHZ)
469 sinfo->rxrate.flags |= RATE_INFO_FLAGS_80_MHZ_WIDTH;
470 if (sta->last_rx_rate_flag & RX_FLAG_80P80MHZ)
471 sinfo->rxrate.flags |= RATE_INFO_FLAGS_80P80_MHZ_WIDTH;
472 if (sta->last_rx_rate_flag & RX_FLAG_160MHZ)
473 sinfo->rxrate.flags |= RATE_INFO_FLAGS_160_MHZ_WIDTH;
454 474
455 if (ieee80211_vif_is_mesh(&sdata->vif)) { 475 if (ieee80211_vif_is_mesh(&sdata->vif)) {
456#ifdef CONFIG_MAC80211_MESH 476#ifdef CONFIG_MAC80211_MESH
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index b2ae2baefc9a..825f33cf7bbc 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -193,7 +193,7 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local,
193 pos++; 193 pos++;
194 194
195 /* IEEE80211_RADIOTAP_RATE */ 195 /* IEEE80211_RADIOTAP_RATE */
196 if (!rate || status->flag & RX_FLAG_HT) { 196 if (!rate || status->flag & (RX_FLAG_HT | RX_FLAG_VHT)) {
197 /* 197 /*
198 * Without rate information don't add it. If we have, 198 * Without rate information don't add it. If we have,
199 * MCS information is a separate field in radiotap, 199 * MCS information is a separate field in radiotap,
@@ -213,7 +213,7 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local,
213 if (status->band == IEEE80211_BAND_5GHZ) 213 if (status->band == IEEE80211_BAND_5GHZ)
214 put_unaligned_le16(IEEE80211_CHAN_OFDM | IEEE80211_CHAN_5GHZ, 214 put_unaligned_le16(IEEE80211_CHAN_OFDM | IEEE80211_CHAN_5GHZ,
215 pos); 215 pos);
216 else if (status->flag & RX_FLAG_HT) 216 else if (status->flag & (RX_FLAG_HT | RX_FLAG_VHT))
217 put_unaligned_le16(IEEE80211_CHAN_DYN | IEEE80211_CHAN_2GHZ, 217 put_unaligned_le16(IEEE80211_CHAN_DYN | IEEE80211_CHAN_2GHZ,
218 pos); 218 pos);
219 else if (rate && rate->flags & IEEE80211_RATE_ERP_G) 219 else if (rate && rate->flags & IEEE80211_RATE_ERP_G)
@@ -1356,6 +1356,7 @@ ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx)
1356 if (ieee80211_is_data(hdr->frame_control)) { 1356 if (ieee80211_is_data(hdr->frame_control)) {
1357 sta->last_rx_rate_idx = status->rate_idx; 1357 sta->last_rx_rate_idx = status->rate_idx;
1358 sta->last_rx_rate_flag = status->flag; 1358 sta->last_rx_rate_flag = status->flag;
1359 sta->last_rx_rate_vht_nss = status->vht_nss;
1359 } 1360 }
1360 } 1361 }
1361 } else if (!is_multicast_ether_addr(hdr->addr1)) { 1362 } else if (!is_multicast_ether_addr(hdr->addr1)) {
@@ -1367,6 +1368,7 @@ ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx)
1367 if (ieee80211_is_data(hdr->frame_control)) { 1368 if (ieee80211_is_data(hdr->frame_control)) {
1368 sta->last_rx_rate_idx = status->rate_idx; 1369 sta->last_rx_rate_idx = status->rate_idx;
1369 sta->last_rx_rate_flag = status->flag; 1370 sta->last_rx_rate_flag = status->flag;
1371 sta->last_rx_rate_vht_nss = status->vht_nss;
1370 } 1372 }
1371 } 1373 }
1372 1374
@@ -2710,7 +2712,8 @@ static void ieee80211_rx_handlers_result(struct ieee80211_rx_data *rx,
2710 status = IEEE80211_SKB_RXCB((rx->skb)); 2712 status = IEEE80211_SKB_RXCB((rx->skb));
2711 2713
2712 sband = rx->local->hw.wiphy->bands[status->band]; 2714 sband = rx->local->hw.wiphy->bands[status->band];
2713 if (!(status->flag & RX_FLAG_HT)) 2715 if (!(status->flag & RX_FLAG_HT) &&
2716 !(status->flag & RX_FLAG_VHT))
2714 rate = &sband->bitrates[status->rate_idx]; 2717 rate = &sband->bitrates[status->rate_idx];
2715 2718
2716 ieee80211_rx_cooked_monitor(rx, rate); 2719 ieee80211_rx_cooked_monitor(rx, rate);
@@ -2877,8 +2880,8 @@ static int prepare_for_handlers(struct ieee80211_rx_data *rx,
2877 status->rx_flags &= ~IEEE80211_RX_RA_MATCH; 2880 status->rx_flags &= ~IEEE80211_RX_RA_MATCH;
2878 } else if (!rx->sta) { 2881 } else if (!rx->sta) {
2879 int rate_idx; 2882 int rate_idx;
2880 if (status->flag & RX_FLAG_HT) 2883 if (status->flag & (RX_FLAG_HT | RX_FLAG_VHT))
2881 rate_idx = 0; /* TODO: HT rates */ 2884 rate_idx = 0; /* TODO: HT/VHT rates */
2882 else 2885 else
2883 rate_idx = status->rate_idx; 2886 rate_idx = status->rate_idx;
2884 ieee80211_ibss_rx_no_sta(sdata, bssid, hdr->addr2, 2887 ieee80211_ibss_rx_no_sta(sdata, bssid, hdr->addr2,
@@ -3154,6 +3157,13 @@ void ieee80211_rx(struct ieee80211_hw *hw, struct sk_buff *skb)
3154 status->rate_idx, 3157 status->rate_idx,
3155 status->rate_idx)) 3158 status->rate_idx))
3156 goto drop; 3159 goto drop;
3160 } else if (status->flag & RX_FLAG_VHT) {
3161 if (WARN_ONCE(status->rate_idx > 9 ||
3162 !status->vht_nss ||
3163 status->vht_nss > 8,
3164 "Rate marked as a VHT rate but data is invalid: MCS: %d, NSS: %d\n",
3165 status->rate_idx, status->vht_nss))
3166 goto drop;
3157 } else { 3167 } else {
3158 if (WARN_ON(status->rate_idx >= sband->n_bitrates)) 3168 if (WARN_ON(status->rate_idx >= sband->n_bitrates))
3159 goto drop; 3169 goto drop;
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h
index 2b2d5aac2bb1..6835cea4e402 100644
--- a/net/mac80211/sta_info.h
+++ b/net/mac80211/sta_info.h
@@ -227,6 +227,7 @@ struct sta_ampdu_mlme {
227 * "the" transmit rate 227 * "the" transmit rate
228 * @last_rx_rate_idx: rx status rate index of the last data packet 228 * @last_rx_rate_idx: rx status rate index of the last data packet
229 * @last_rx_rate_flag: rx status flag of the last data packet 229 * @last_rx_rate_flag: rx status flag of the last data packet
230 * @last_rx_rate_vht_nss: rx status nss of last data packet
230 * @lock: used for locking all fields that require locking, see comments 231 * @lock: used for locking all fields that require locking, see comments
231 * in the header file. 232 * in the header file.
232 * @drv_unblock_wk: used for driver PS unblocking 233 * @drv_unblock_wk: used for driver PS unblocking
@@ -343,7 +344,8 @@ struct sta_info {
343 unsigned long tx_fragments; 344 unsigned long tx_fragments;
344 struct ieee80211_tx_rate last_tx_rate; 345 struct ieee80211_tx_rate last_tx_rate;
345 int last_rx_rate_idx; 346 int last_rx_rate_idx;
346 int last_rx_rate_flag; 347 u32 last_rx_rate_flag;
348 u8 last_rx_rate_vht_nss;
347 u16 tid_seq[IEEE80211_QOS_CTL_TID_MASK + 1]; 349 u16 tid_seq[IEEE80211_QOS_CTL_TID_MASK + 1];
348 350
349 /* 351 /*
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index 3b3dd32f121f..dc7f6b264593 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -2069,6 +2069,20 @@ u64 ieee80211_calculate_rx_timestamp(struct ieee80211_local *local,
2069 ri.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH; 2069 ri.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
2070 if (status->flag & RX_FLAG_SHORT_GI) 2070 if (status->flag & RX_FLAG_SHORT_GI)
2071 ri.flags |= RATE_INFO_FLAGS_SHORT_GI; 2071 ri.flags |= RATE_INFO_FLAGS_SHORT_GI;
2072 } else if (status->flag & RX_FLAG_VHT) {
2073 ri.flags |= RATE_INFO_FLAGS_VHT_MCS;
2074 ri.mcs = status->rate_idx;
2075 ri.nss = status->vht_nss;
2076 if (status->flag & RX_FLAG_40MHZ)
2077 ri.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
2078 if (status->flag & RX_FLAG_80MHZ)
2079 ri.flags |= RATE_INFO_FLAGS_80_MHZ_WIDTH;
2080 if (status->flag & RX_FLAG_80P80MHZ)
2081 ri.flags |= RATE_INFO_FLAGS_80P80_MHZ_WIDTH;
2082 if (status->flag & RX_FLAG_160MHZ)
2083 ri.flags |= RATE_INFO_FLAGS_160_MHZ_WIDTH;
2084 if (status->flag & RX_FLAG_SHORT_GI)
2085 ri.flags |= RATE_INFO_FLAGS_SHORT_GI;
2072 } else { 2086 } else {
2073 struct ieee80211_supported_band *sband; 2087 struct ieee80211_supported_band *sband;
2074 2088