svn commit: r288414 - head/sys/dev/usb/wlan

Adrian Chadd adrian at FreeBSD.org
Wed Sep 30 05:19:17 UTC 2015


Author: adrian
Date: Wed Sep 30 05:19:16 2015
New Revision: 288414
URL: https://svnweb.freebsd.org/changeset/base/288414

Log:
  modify the rssi logic a bit to actually return a useful rssi.
  
  The fullmac firmware doesn't seem to populate a useful rssi indicator
  in the RX descriptor, so if one plotted said values, they'd basically
  look like garbage.
  
  The reference driver implements a "get current rssi" firmware command
  which I guess is really meant for station operation only (as hostap
  operation would need rssi per station, not a single firmware read.)
  
  So:
  
  * populate sc_currssi during each calibration run;
  * use this in the RX path instead of trying to reconstruct the RSSI
    value and passing it around as a pointer;
  * do up a quick hack to map the rssi hardware value to some useful
    signal level;
  * the survey results provide an RSSI value between 0..100, so just
    do another quick hack to map it into some usefulish signal level;
  * supply a faked noise floor - I haven't yet found how to pull it
    out of the firmware.
  
  The scan results and the station RSSI information is now more useful
  for indicating signal strength / distance.

Modified:
  head/sys/dev/usb/wlan/if_rsu.c
  head/sys/dev/usb/wlan/if_rsureg.h

Modified: head/sys/dev/usb/wlan/if_rsu.c
==============================================================================
--- head/sys/dev/usb/wlan/if_rsu.c	Wed Sep 30 04:48:56 2015	(r288413)
+++ head/sys/dev/usb/wlan/if_rsu.c	Wed Sep 30 05:19:16 2015	(r288414)
@@ -203,17 +203,18 @@ static void	rsu_delete_key(struct rsu_so
 static int	rsu_site_survey(struct rsu_softc *, struct ieee80211vap *);
 static int	rsu_join_bss(struct rsu_softc *, struct ieee80211_node *);
 static int	rsu_disconnect(struct rsu_softc *);
+static int	rsu_hwrssi_to_rssi(struct rsu_softc *, int hw_rssi);
 static void	rsu_event_survey(struct rsu_softc *, uint8_t *, int);
 static void	rsu_event_join_bss(struct rsu_softc *, uint8_t *, int);
 static void	rsu_rx_event(struct rsu_softc *, uint8_t, uint8_t *, int);
 static void	rsu_rx_multi_event(struct rsu_softc *, uint8_t *, int);
+#if 0
 static int8_t	rsu_get_rssi(struct rsu_softc *, int, void *);
+#endif
+static struct mbuf * rsu_rx_frame(struct rsu_softc *, uint8_t *, int);
+static struct mbuf * rsu_rx_multi_frame(struct rsu_softc *, uint8_t *, int);
 static struct mbuf *
-		rsu_rx_frame(struct rsu_softc *, uint8_t *, int, int *);
-static struct mbuf *
-		rsu_rx_multi_frame(struct rsu_softc *, uint8_t *, int, int *);
-static struct mbuf *
-		rsu_rxeof(struct usb_xfer *, struct rsu_data *, int *);
+		rsu_rxeof(struct usb_xfer *, struct rsu_data *);
 static void	rsu_txeof(struct usb_xfer *, struct rsu_data *);
 static int	rsu_raw_xmit(struct ieee80211_node *, struct mbuf *, 
 		    const struct ieee80211_bpf_params *);
@@ -1082,7 +1083,9 @@ static void
 rsu_calib_task(void *arg, int pending __unused)
 {
 	struct rsu_softc *sc = arg;
+#ifdef notyet
 	uint32_t reg;
+#endif
 
 	RSU_DPRINTF(sc, RSU_DEBUG_CALIB, "%s: running calibration task\n",
 	    __func__);
@@ -1100,9 +1103,10 @@ rsu_calib_task(void *arg, int pending __
 #endif
 	/* Read current signal level. */
 	if (rsu_fw_iocmd(sc, 0xf4000001) == 0) {
-		reg = rsu_read_4(sc, R92S_IOCMD_DATA);
-		RSU_DPRINTF(sc, RSU_DEBUG_CALIB, "%s: RSSI=%d%%\n",
-		    __func__, reg >> 4);
+		sc->sc_currssi = rsu_read_4(sc, R92S_IOCMD_DATA);
+		RSU_DPRINTF(sc, RSU_DEBUG_CALIB, "%s: RSSI=%d (%d)\n",
+		    __func__, sc->sc_currssi,
+		    rsu_hwrssi_to_rssi(sc, sc->sc_currssi));
 	}
 	if (sc->sc_calibrating)
 		taskqueue_enqueue_timeout(taskqueue_thread, &sc->calib_task, hz);
@@ -1433,6 +1437,24 @@ rsu_disconnect(struct rsu_softc *sc)
 	return (rsu_fw_cmd(sc, R92S_CMD_DISCONNECT, &zero, sizeof(zero)));
 }
 
+/*
+ * Map the hardware provided RSSI value to a signal level.
+ * For the most part it's just something we divide by and cap
+ * so it doesn't overflow the representation by net80211.
+ */
+static int
+rsu_hwrssi_to_rssi(struct rsu_softc *sc, int hw_rssi)
+{
+	int v;
+
+	if (hw_rssi == 0)
+		return (0);
+	v = hw_rssi >> 4;
+	if (v > 80)
+		v = 80;
+	return (v);
+}
+
 static void
 rsu_event_survey(struct rsu_softc *sc, uint8_t *buf, int len)
 {
@@ -1486,8 +1508,9 @@ rsu_event_survey(struct rsu_softc *sc, u
 	rxs.r_flags |= IEEE80211_R_NF | IEEE80211_R_RSSI;
 	rxs.c_ieee = le32toh(bss->config.dsconfig);
 	rxs.c_freq = ieee80211_ieee2mhz(rxs.c_ieee, IEEE80211_CHAN_2GHZ);
-	rxs.rssi = le32toh(bss->rssi);
-	rxs.nf = 0; /* XXX */
+	/* This is a number from 0..100; so let's just divide it down a bit */
+	rxs.rssi = le32toh(bss->rssi) / 2;
+	rxs.nf = -96;
 
 	/* XXX avoid a LOR */
 	RSU_UNLOCK(sc);
@@ -1557,7 +1580,7 @@ rsu_event_addba_req_report(struct rsu_so
 	if (vap == NULL)
 		return;
 
-	device_printf(sc->sc_dev, "%s: mac=%s, tid=%d, ssn=%d\n",
+	RSU_DPRINTF(sc, RSU_DEBUG_AMPDU, "%s: mac=%s, tid=%d, ssn=%d\n",
 	    __func__,
 	    ether_sprintf(ba->mac_addr),
 	    (int) ba->tid,
@@ -1670,6 +1693,7 @@ rsu_rx_multi_event(struct rsu_softc *sc,
 	}
 }
 
+#if 0
 static int8_t
 rsu_get_rssi(struct rsu_softc *sc, int rate, void *physt)
 {
@@ -1690,9 +1714,10 @@ rsu_get_rssi(struct rsu_softc *sc, int r
 	}
 	return (rssi);
 }
+#endif
 
 static struct mbuf *
-rsu_rx_frame(struct rsu_softc *sc, uint8_t *buf, int pktlen, int *rssi)
+rsu_rx_frame(struct rsu_softc *sc, uint8_t *buf, int pktlen)
 {
 	struct ieee80211com *ic = &sc->sc_ic;
 	struct ieee80211_frame *wh;
@@ -1718,16 +1743,17 @@ rsu_rx_frame(struct rsu_softc *sc, uint8
 	rate = MS(rxdw3, R92S_RXDW3_RATE);
 	infosz = MS(rxdw0, R92S_RXDW0_INFOSZ) * 8;
 
+#if 0
 	/* Get RSSI from PHY status descriptor if present. */
 	if (infosz != 0)
 		*rssi = rsu_get_rssi(sc, rate, &stat[1]);
 	else
 		*rssi = 0;
+#endif
 
 	RSU_DPRINTF(sc, RSU_DEBUG_RX,
-	    "%s: Rx frame len=%d rate=%d infosz=%d rssi=%d\n",
-	    __func__,
-	    pktlen, rate, infosz, *rssi);
+	    "%s: Rx frame len=%d rate=%d infosz=%d\n",
+	    __func__, pktlen, rate, infosz);
 
 	m = m_get2(pktlen, M_NOWAIT, MT_DATA, M_PKTHDR);
 	if (__predict_false(m == NULL)) {
@@ -1769,7 +1795,11 @@ rsu_rx_frame(struct rsu_softc *sc, uint8
 			/* Bit 7 set means HT MCS instead of rate. */
 			tap->wr_rate = 0x80 | (rate - 12);
 		}
+#if 0
 		tap->wr_dbm_antsignal = *rssi;
+#endif
+		/* XXX not nice */
+		tap->wr_dbm_antsignal = rsu_hwrssi_to_rssi(sc, sc->sc_currssi);
 		tap->wr_chan_freq = htole16(ic->ic_curchan->ic_freq);
 		tap->wr_chan_flags = htole16(ic->ic_curchan->ic_flags);
 	}
@@ -1778,7 +1808,7 @@ rsu_rx_frame(struct rsu_softc *sc, uint8
 }
 
 static struct mbuf *
-rsu_rx_multi_frame(struct rsu_softc *sc, uint8_t *buf, int len, int *rssi)
+rsu_rx_multi_frame(struct rsu_softc *sc, uint8_t *buf, int len)
 {
 	struct r92s_rx_stat *stat;
 	uint32_t rxdw0;
@@ -1810,7 +1840,7 @@ rsu_rx_multi_frame(struct rsu_softc *sc,
 			break;
 
 		/* Process 802.11 frame. */
-		m = rsu_rx_frame(sc, buf, pktlen, rssi);
+		m = rsu_rx_frame(sc, buf, pktlen);
 		if (m0 == NULL)
 			m0 = m;
 		if (prevm == NULL)
@@ -1829,7 +1859,7 @@ rsu_rx_multi_frame(struct rsu_softc *sc,
 }
 
 static struct mbuf *
-rsu_rxeof(struct usb_xfer *xfer, struct rsu_data *data, int *rssi)
+rsu_rxeof(struct usb_xfer *xfer, struct rsu_data *data)
 {
 	struct rsu_softc *sc = data->sc;
 	struct ieee80211com *ic = &sc->sc_ic;
@@ -1850,7 +1880,7 @@ rsu_rxeof(struct usb_xfer *xfer, struct 
 		/* No packets to process. */
 		return (NULL);
 	} else
-		return (rsu_rx_multi_frame(sc, data->buf, len, rssi));
+		return (rsu_rx_multi_frame(sc, data->buf, len));
 }
 
 static void
@@ -1862,7 +1892,6 @@ rsu_bulk_rx_callback(struct usb_xfer *xf
 	struct ieee80211_node *ni;
 	struct mbuf *m = NULL, *next;
 	struct rsu_data *data;
-	int rssi = 1;
 
 	RSU_ASSERT_LOCKED(sc);
 
@@ -1872,7 +1901,7 @@ rsu_bulk_rx_callback(struct usb_xfer *xf
 		if (data == NULL)
 			goto tr_setup;
 		STAILQ_REMOVE_HEAD(&sc->sc_rx_active, next);
-		m = rsu_rxeof(xfer, data, &rssi);
+		m = rsu_rxeof(xfer, data);
 		STAILQ_INSERT_TAIL(&sc->sc_rx_inactive, data, next);
 		/* FALLTHROUGH */
 	case USB_ST_SETUP:
@@ -1898,6 +1927,11 @@ tr_setup:
 		 */
 		RSU_UNLOCK(sc);
 		while (m != NULL) {
+			int rssi;
+
+			/* Cheat and get the last calibrated RSSI */
+			rssi = rsu_hwrssi_to_rssi(sc, sc->sc_currssi);
+
 			next = m->m_next;
 			m->m_next = NULL;
 			wh = mtod(m, struct ieee80211_frame *);
@@ -1906,10 +1940,10 @@ tr_setup:
 			if (ni != NULL) {
 				if (ni->ni_flags & IEEE80211_NODE_HT)
 					m->m_flags |= M_AMPDU;
-				(void)ieee80211_input(ni, m, rssi, 0);
+				(void)ieee80211_input(ni, m, rssi, -96);
 				ieee80211_free_node(ni);
 			} else
-				(void)ieee80211_input_all(ic, m, rssi, 0);
+				(void)ieee80211_input_all(ic, m, rssi, -96);
 			m = next;
 		}
 		RSU_LOCK(sc);
@@ -2003,6 +2037,12 @@ tr_setup:
 		}
 		break;
 	}
+
+	/*
+	 * XXX TODO: if the queue is low, flush out FF TX frames.
+	 * Remember to unlock the driver for now; net80211 doesn't
+	 * defer it for us.
+	 */
 }
 
 static void

Modified: head/sys/dev/usb/wlan/if_rsureg.h
==============================================================================
--- head/sys/dev/usb/wlan/if_rsureg.h	Wed Sep 30 04:48:56 2015	(r288413)
+++ head/sys/dev/usb/wlan/if_rsureg.h	Wed Sep 30 05:19:16 2015	(r288414)
@@ -764,6 +764,7 @@ struct rsu_softc {
 	int				sc_ht;
 	int				sc_nendpoints;
 	int				sc_curpwrstate;
+	int				sc_currssi;
 
 	u_int				sc_running:1,
 					sc_calibrating:1,


More information about the svn-src-head mailing list