From owner-svn-src-all@FreeBSD.ORG Fri Apr 8 09:20:46 2011 Return-Path: Delivered-To: svn-src-all@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 4432E106566C; Fri, 8 Apr 2011 09:20:46 +0000 (UTC) (envelope-from adrian@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 28E148FC12; Fri, 8 Apr 2011 09:20:46 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id p389Kkm1070212; Fri, 8 Apr 2011 09:20:46 GMT (envelope-from adrian@svn.freebsd.org) Received: (from adrian@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id p389KjUY070206; Fri, 8 Apr 2011 09:20:45 GMT (envelope-from adrian@svn.freebsd.org) Message-Id: <201104080920.p389KjUY070206@svn.freebsd.org> From: Adrian Chadd Date: Fri, 8 Apr 2011 09:20:45 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r220445 - head/sys/net80211 X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 08 Apr 2011 09:20:46 -0000 Author: adrian Date: Fri Apr 8 09:20:45 2011 New Revision: 220445 URL: http://svn.freebsd.org/changeset/base/220445 Log: Add initial support for MIMO statistics to net80211. This introduces struct ieee80211_rx_stats - which stores the various kinds of RX statistics which a MIMO and non-MIMO 802.11 device can export. It also fleshes out the mimo export to userland (node_getmimoinfo()). It assumes that MIMO radios (for now) export both ctl and ext channels. Non-11n MIMO radios are possible (and I believe Atheros made at least one), so if that chipset support is added, extra flags to the struct ieee80211_rx_stats can be added to extend this support. Two new input functions have been added - ieee80211_input_mimo() and ieee80211_input_mimo_all() - which MIMO-aware devices can call with MIMO specific statistics. 802.11 devices calling the non-MIMO input functions will still function. Modified: head/sys/net80211/_ieee80211.h head/sys/net80211/ieee80211_input.c head/sys/net80211/ieee80211_node.c head/sys/net80211/ieee80211_node.h head/sys/net80211/ieee80211_proto.h Modified: head/sys/net80211/_ieee80211.h ============================================================================== --- head/sys/net80211/_ieee80211.h Fri Apr 8 08:49:50 2011 (r220444) +++ head/sys/net80211/_ieee80211.h Fri Apr 8 09:20:45 2011 (r220445) @@ -387,10 +387,16 @@ struct ieee80211_regdomain { /* * MIMO antenna/radio state. */ + +#define IEEE80211_MAX_CHAINS 3 +#define IEEE80211_MAX_EVM_PILOTS 6 + +/* + * XXX This doesn't yet export both ctl/ext chain details + */ struct ieee80211_mimo_info { - int8_t rssi[3]; /* per-antenna rssi */ - int8_t noise[3]; /* per-antenna noise floor */ - uint8_t pad[2]; + int8_t rssi[IEEE80211_MAX_CHAINS]; /* per-antenna rssi */ + int8_t noise[IEEE80211_MAX_CHAINS]; /* per-antenna noise floor */ uint32_t evm[3]; /* EVM data */ }; #endif /* _NET80211__IEEE80211_H_ */ Modified: head/sys/net80211/ieee80211_input.c ============================================================================== --- head/sys/net80211/ieee80211_input.c Fri Apr 8 08:49:50 2011 (r220444) +++ head/sys/net80211/ieee80211_input.c Fri Apr 8 09:20:45 2011 (r220445) @@ -57,9 +57,54 @@ __FBSDID("$FreeBSD$"); #include #endif +static void +ieee80211_process_mimo(struct ieee80211_node *ni, struct ieee80211_rx_stats *rx) +{ + int i; + + /* Verify the required MIMO bits are set */ + if ((rx->r_flags & (IEEE80211_R_C_CHAIN | IEEE80211_R_C_NF | IEEE80211_R_C_RSSI)) != + (IEEE80211_R_C_CHAIN | IEEE80211_R_C_NF | IEEE80211_R_C_RSSI)) + return; + + /* XXX This assumes the MIMO radios have both ctl and ext chains */ + for (i = 0; i < MIN(rx->c_chain, IEEE80211_MAX_CHAINS); i++) { + IEEE80211_RSSI_LPF(ni->ni_mimo_rssi_ctl[i], rx->c_rssi_ctl[i]); + IEEE80211_RSSI_LPF(ni->ni_mimo_rssi_ext[i], rx->c_rssi_ext[i]); + } + + /* XXX This also assumes the MIMO radios have both ctl and ext chains */ + for(i = 0; i < MIN(rx->c_chain, IEEE80211_MAX_CHAINS); i++) { + ni->ni_mimo_noise_ctl[i] = rx->c_nf_ctl[i]; + ni->ni_mimo_noise_ext[i] = rx->c_nf_ext[i]; + } + ni->ni_mimo_chains = rx->c_chain; +} + +int +ieee80211_input_mimo(struct ieee80211_node *ni, struct mbuf *m, + struct ieee80211_rx_stats *rx) +{ + /* XXX should assert IEEE80211_R_NF and IEEE80211_R_RSSI are set */ + ieee80211_process_mimo(ni, rx); + return ieee80211_input(ni, m, rx->rssi, rx->nf); +} + int ieee80211_input_all(struct ieee80211com *ic, struct mbuf *m, int rssi, int nf) { + struct ieee80211_rx_stats rx; + + rx.r_flags = IEEE80211_R_NF | IEEE80211_R_RSSI; + rx.nf = nf; + rx.rssi = rssi; + return ieee80211_input_mimo_all(ic, m, &rx); +} + +int +ieee80211_input_mimo_all(struct ieee80211com *ic, struct mbuf *m, + struct ieee80211_rx_stats *rx) +{ struct ieee80211vap *vap; int type = -1; @@ -96,7 +141,7 @@ ieee80211_input_all(struct ieee80211com m = NULL; } ni = ieee80211_ref_node(vap->iv_bss); - type = ieee80211_input(ni, mcopy, rssi, nf); + type = ieee80211_input_mimo(ni, mcopy, rx); ieee80211_free_node(ni); } if (m != NULL) /* no vaps, reclaim mbuf */ Modified: head/sys/net80211/ieee80211_node.c ============================================================================== --- head/sys/net80211/ieee80211_node.c Fri Apr 8 08:49:50 2011 (r220444) +++ head/sys/net80211/ieee80211_node.c Fri Apr 8 09:20:45 2011 (r220445) @@ -1085,7 +1085,26 @@ static void node_getmimoinfo(const struct ieee80211_node *ni, struct ieee80211_mimo_info *info) { - /* XXX zero data? */ + int i; + uint32_t avgrssi; + int32_t rssi; + + bzero(info, sizeof(*info)); + + for (i = 0; i < ni->ni_mimo_chains; i++) { + avgrssi = ni->ni_mimo_rssi_ctl[i]; + if (avgrssi == IEEE80211_RSSI_DUMMY_MARKER) { + info->rssi[i] = 0; + } else { + rssi = IEEE80211_RSSI_GET(avgrssi); + info->rssi[i] = rssi < 0 ? 0 : rssi > 127 ? 127 : rssi; + } + info->noise[i] = ni->ni_mimo_noise_ctl[i]; + } + + /* XXX ext radios? */ + + /* XXX EVM? */ } struct ieee80211_node * Modified: head/sys/net80211/ieee80211_node.h ============================================================================== --- head/sys/net80211/ieee80211_node.h Fri Apr 8 08:49:50 2011 (r220444) +++ head/sys/net80211/ieee80211_node.h Fri Apr 8 09:20:45 2011 (r220445) @@ -166,6 +166,13 @@ struct ieee80211_node { uint32_t ni_avgrssi; /* recv ssi state */ int8_t ni_noise; /* noise floor */ + /* mimo statistics */ + uint32_t ni_mimo_rssi_ctl[IEEE80211_MAX_CHAINS]; + uint32_t ni_mimo_rssi_ext[IEEE80211_MAX_CHAINS]; + uint8_t ni_mimo_noise_ctl[IEEE80211_MAX_CHAINS]; + uint8_t ni_mimo_noise_ext[IEEE80211_MAX_CHAINS]; + uint8_t ni_mimo_chains; + /* header */ uint8_t ni_macaddr[IEEE80211_ADDR_LEN]; uint8_t ni_bssid[IEEE80211_ADDR_LEN]; Modified: head/sys/net80211/ieee80211_proto.h ============================================================================== --- head/sys/net80211/ieee80211_proto.h Fri Apr 8 08:49:50 2011 (r220444) +++ head/sys/net80211/ieee80211_proto.h Fri Apr 8 09:20:45 2011 (r220445) @@ -61,9 +61,36 @@ void ieee80211_syncflag(struct ieee80211 void ieee80211_syncflag_ht(struct ieee80211vap *, int flag); void ieee80211_syncflag_ext(struct ieee80211vap *, int flag); +#define IEEE80211_R_NF 0x0000001 /* global NF value valid */ +#define IEEE80211_R_RSSI 0x0000002 /* global RSSI value valid */ +#define IEEE80211_R_C_CHAIN 0x0000004 /* RX chain count valid */ +#define IEEE80211_R_C_NF 0x0000008 /* per-chain NF value valid */ +#define IEEE80211_R_C_RSSI 0x0000010 /* per-chain RSSI value valid */ +#define IEEE80211_R_C_EVM 0x0000020 /* per-chain EVM valid */ +#define IEEE80211_R_C_HT40 0x0000040 /* RX'ed packet is 40mhz, pilots 4,5 valid */ + +struct ieee80211_rx_stats { + uint32_t r_flags; /* IEEE80211_R_* flags */ + uint8_t c_chain; /* number of RX chains involved */ + int16_t c_nf_ctl[IEEE80211_MAX_CHAINS]; /* per-chain NF */ + int16_t c_nf_ext[IEEE80211_MAX_CHAINS]; /* per-chain NF */ + int16_t c_rssi_ctl[IEEE80211_MAX_CHAINS]; /* per-chain RSSI */ + int16_t c_rssi_ext[IEEE80211_MAX_CHAINS]; /* per-chain RSSI */ + uint8_t nf; /* global NF */ + uint8_t rssi; /* global RSSI */ + uint8_t evm[IEEE80211_MAX_CHAINS][IEEE80211_MAX_EVM_PILOTS]; + /* per-chain, per-pilot EVM values */ +}; + #define ieee80211_input(ni, m, rssi, nf) \ ((ni)->ni_vap->iv_input(ni, m, rssi, nf)) int ieee80211_input_all(struct ieee80211com *, struct mbuf *, int, int); + +int ieee80211_input_mimo(struct ieee80211_node *, struct mbuf *, + struct ieee80211_rx_stats *); +int ieee80211_input_mimo_all(struct ieee80211com *, struct mbuf *, + struct ieee80211_rx_stats *); + struct ieee80211_bpf_params; int ieee80211_mgmt_output(struct ieee80211_node *, struct mbuf *, int, struct ieee80211_bpf_params *);