aboutsummaryrefslogtreecommitdiff
path: root/sys/dev/iwn
diff options
context:
space:
mode:
authorAndriy Voskoboinyk <avos@FreeBSD.org>2017-03-01 00:42:38 +0000
committerAndriy Voskoboinyk <avos@FreeBSD.org>2017-03-01 00:42:38 +0000
commit7ab1926316902a74784b4224b3f91107b8c8f4d6 (patch)
tree048d4219a43e9f213fed444148a236cc680da09f /sys/dev/iwn
parent4b6c378be3fb98948d7f451e5b78d18e029e3c52 (diff)
downloadsrc-7ab1926316902a74784b4224b3f91107b8c8f4d6.tar.gz
src-7ab1926316902a74784b4224b3f91107b8c8f4d6.zip
iwn: fix data rate parsing for Rx radiotap header.
Tested with Intel 6205, MONITOR mode + RTL8188EU, STA mode.
Notes
Notes: svn path=/head/; revision=314443
Diffstat (limited to 'sys/dev/iwn')
-rw-r--r--sys/dev/iwn/if_iwn.c44
-rw-r--r--sys/dev/iwn/if_iwnreg.h4
2 files changed, 30 insertions, 18 deletions
diff --git a/sys/dev/iwn/if_iwn.c b/sys/dev/iwn/if_iwn.c
index f430127e0aa2..c1e7f8a422c4 100644
--- a/sys/dev/iwn/if_iwn.c
+++ b/sys/dev/iwn/if_iwn.c
@@ -2667,6 +2667,26 @@ rate2plcp(int rate)
return 0;
}
+static __inline uint8_t
+plcp2rate(const uint8_t rate_plcp)
+{
+ switch (rate_plcp) {
+ case 0xd: return 12;
+ case 0xf: return 18;
+ case 0x5: return 24;
+ case 0x7: return 36;
+ case 0x9: return 48;
+ case 0xb: return 72;
+ case 0x1: return 96;
+ case 0x3: return 108;
+ case 10: return 2;
+ case 20: return 4;
+ case 55: return 11;
+ case 110: return 22;
+ default: return 0;
+ }
+}
+
static int
iwn_get_1stream_tx_antmask(struct iwn_softc *sc)
{
@@ -3078,6 +3098,7 @@ iwn_rx_done(struct iwn_softc *sc, struct iwn_rx_desc *desc,
if (ieee80211_radiotap_active(ic)) {
struct iwn_rx_radiotap_header *tap = &sc->sc_rxtap;
+ uint32_t rate = le32toh(stat->rate);
tap->wr_flags = 0;
if (stat->flags & htole16(IWN_STAT_FLAG_SHPREAMBLE))
@@ -3085,24 +3106,11 @@ iwn_rx_done(struct iwn_softc *sc, struct iwn_rx_desc *desc,
tap->wr_dbm_antsignal = (int8_t)rssi;
tap->wr_dbm_antnoise = (int8_t)nf;
tap->wr_tsft = stat->tstamp;
- switch (stat->rate) {
- /* CCK rates. */
- case 10: tap->wr_rate = 2; break;
- case 20: tap->wr_rate = 4; break;
- case 55: tap->wr_rate = 11; break;
- case 110: tap->wr_rate = 22; break;
- /* OFDM rates. */
- case 0xd: tap->wr_rate = 12; break;
- case 0xf: tap->wr_rate = 18; break;
- case 0x5: tap->wr_rate = 24; break;
- case 0x7: tap->wr_rate = 36; break;
- case 0x9: tap->wr_rate = 48; break;
- case 0xb: tap->wr_rate = 72; break;
- case 0x1: tap->wr_rate = 96; break;
- case 0x3: tap->wr_rate = 108; break;
- /* Unknown rate: should not happen. */
- default: tap->wr_rate = 0;
- }
+ if (rate & IWN_RFLAG_MCS) {
+ tap->wr_rate = rate & IWN_RFLAG_RATE_MCS;
+ tap->wr_rate |= IEEE80211_RATE_MCS;
+ } else
+ tap->wr_rate = plcp2rate(rate & IWN_RFLAG_RATE);
}
/*
diff --git a/sys/dev/iwn/if_iwnreg.h b/sys/dev/iwn/if_iwnreg.h
index 05ababf39204..2ea469737a43 100644
--- a/sys/dev/iwn/if_iwnreg.h
+++ b/sys/dev/iwn/if_iwnreg.h
@@ -736,6 +736,10 @@ struct iwn4965_node_info {
uint32_t reserved7;
} __packed;
+#define IWN_RFLAG_RATE 0xff
+#define IWN_RFLAG_RATE_MCS 0x1f
+#define IWN_RFLAG_HT40_DUP 0x20
+
#define IWN_RFLAG_MCS (1 << 8)
#define IWN_RFLAG_CCK (1 << 9)
#define IWN_RFLAG_GREENFIELD (1 << 10)