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 <net/ethernet.h>
 #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 *);
_______________________________________________
svn-src-head@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to