aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2012-11-22 23:00:18 +0100
committerJohannes Berg <johannes.berg@intel.com>2012-11-27 11:56:18 +0100
commit5164892184d1b9ce19e45e97e9ca405ea8b9ceb2 (patch)
tree011ba3d92ccf3b10f34ffff9c0ea09d339521a49 /net/mac80211
parentf2d9d270c15ae0139b54a7e7466d738327e97e03 (diff)
downloadkernel_goldelico_gta04-5164892184d1b9ce19e45e97e9ca405ea8b9ceb2.zip
kernel_goldelico_gta04-5164892184d1b9ce19e45e97e9ca405ea8b9ceb2.tar.gz
kernel_goldelico_gta04-5164892184d1b9ce19e45e97e9ca405ea8b9ceb2.tar.bz2
mac80211: support (partial) VHT radiotap information
Add some information that we have about VHT to radiotap. This at least lets one see the MCS and NSS information. Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Diffstat (limited to 'net/mac80211')
-rw-r--r--net/mac80211/main.c2
-rw-r--r--net/mac80211/rx.c40
2 files changed, 42 insertions, 0 deletions
diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index 6e93340..c4ed83b 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -638,6 +638,8 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len,
local->hw.radiotap_mcs_details = IEEE80211_RADIOTAP_MCS_HAVE_MCS |
IEEE80211_RADIOTAP_MCS_HAVE_GI |
IEEE80211_RADIOTAP_MCS_HAVE_BW;
+ local->hw.radiotap_vht_details = IEEE80211_RADIOTAP_VHT_KNOWN_GI |
+ IEEE80211_RADIOTAP_VHT_KNOWN_BANDWIDTH;
local->user_power_level = IEEE80211_UNSET_POWER_LEVEL;
wiphy->ht_capa_mod_mask = &mac80211_ht_capa_mod_mask;
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index 825f33c..9b13b8b 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -111,6 +111,11 @@ ieee80211_rx_radiotap_space(struct ieee80211_local *local,
len += 8;
}
+ if (status->flag & RX_FLAG_VHT) {
+ len = ALIGN(len, 2);
+ len += 12;
+ }
+
if (status->vendor_radiotap_len) {
if (WARN_ON_ONCE(status->vendor_radiotap_align == 0))
status->vendor_radiotap_align = 1;
@@ -297,6 +302,41 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local,
*pos++ = 0;
}
+ if (status->flag & RX_FLAG_VHT) {
+ u16 known = local->hw.radiotap_vht_details;
+
+ rthdr->it_present |= cpu_to_le32(1 << IEEE80211_RADIOTAP_VHT);
+ /* known field - how to handle 80+80? */
+ if (status->flag & RX_FLAG_80P80MHZ)
+ known &= ~IEEE80211_RADIOTAP_VHT_KNOWN_BANDWIDTH;
+ put_unaligned_le16(known, pos);
+ pos += 2;
+ /* flags */
+ if (status->flag & RX_FLAG_SHORT_GI)
+ *pos |= IEEE80211_RADIOTAP_VHT_FLAG_SGI;
+ pos++;
+ /* bandwidth */
+ if (status->flag & RX_FLAG_80MHZ)
+ *pos++ = 4;
+ else if (status->flag & RX_FLAG_80P80MHZ)
+ *pos++ = 0; /* marked not known above */
+ else if (status->flag & RX_FLAG_160MHZ)
+ *pos++ = 11;
+ else if (status->flag & RX_FLAG_40MHZ)
+ *pos++ = 1;
+ else /* 20 MHz */
+ *pos++ = 0;
+ /* MCS/NSS */
+ *pos = (status->rate_idx << 4) | status->vht_nss;
+ pos += 4;
+ /* coding field */
+ pos++;
+ /* group ID */
+ pos++;
+ /* partial_aid */
+ pos += 2;
+ }
+
if (status->vendor_radiotap_len) {
/* ensure 2 byte alignment for the vendor field as required */
if ((pos - (u8 *)rthdr) & 1)