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

Andriy Voskoboinyk avos at FreeBSD.org
Sun Nov 8 23:21:56 UTC 2015


Author: avos
Date: Sun Nov  8 23:21:54 2015
New Revision: 290564
URL: https://svnweb.freebsd.org/changeset/base/290564

Log:
  urtwn(4): improve RX filter.
  
  - Filter out unneeded frames in STA mode.
  - Implement ic_promisc() call.
  
  Tested with RTL8188EU, STA and MONITOR modes.
  
  Reviewed by:	kevlo
  Approved by:	adrian (mentor)
  Differential Revision:	https://reviews.freebsd.org/D3999

Modified:
  head/sys/dev/usb/wlan/if_urtwn.c
  head/sys/dev/usb/wlan/if_urtwnreg.h

Modified: head/sys/dev/usb/wlan/if_urtwn.c
==============================================================================
--- head/sys/dev/usb/wlan/if_urtwn.c	Sun Nov  8 23:06:40 2015	(r290563)
+++ head/sys/dev/usb/wlan/if_urtwn.c	Sun Nov  8 23:21:54 2015	(r290564)
@@ -269,6 +269,8 @@ static void		urtwn_set_gain(struct urtwn
 static void		urtwn_scan_start(struct ieee80211com *);
 static void		urtwn_scan_end(struct ieee80211com *);
 static void		urtwn_set_channel(struct ieee80211com *);
+static void		urtwn_set_promisc(struct urtwn_softc *);
+static void		urtwn_update_promisc(struct ieee80211com *);
 static void		urtwn_update_mcast(struct ieee80211com *);
 static void		urtwn_set_chan(struct urtwn_softc *,
 		    	    struct ieee80211_channel *,
@@ -457,6 +459,7 @@ urtwn_attach(device_t self)
 	ic->ic_parent = urtwn_parent;
 	ic->ic_vap_create = urtwn_vap_create;
 	ic->ic_vap_delete = urtwn_vap_delete;
+	ic->ic_update_promisc = urtwn_update_promisc;
 	ic->ic_update_mcast = urtwn_update_mcast;
 
 	ieee80211_radiotap_attach(ic, &sc->sc_txtap.wt_ihdr,
@@ -1574,22 +1577,6 @@ urtwn_newstate(struct ieee80211vap *vap,
 		break;
 	case IEEE80211_S_RUN:
 		if (vap->iv_opmode == IEEE80211_M_MONITOR) {
-			/* Enable Rx of data frames. */
-			urtwn_write_2(sc, R92C_RXFLTMAP2, 0xffff);
-
-			/* Enable Rx of ctrl frames. */
-			urtwn_write_2(sc, R92C_RXFLTMAP1, 0xffff);
-
-			/*
-			 * Accept data/control/management frames
-			 * from any BSSID.
-			 */
-			urtwn_write_4(sc, R92C_RCR,
-			    (urtwn_read_4(sc, R92C_RCR) & ~(R92C_RCR_APM |
-			    R92C_RCR_CBSSID_DATA | R92C_RCR_CBSSID_BCN)) |
-			    R92C_RCR_ADF | R92C_RCR_ACF | R92C_RCR_AMF |
-			    R92C_RCR_AAP);
-
 			/* Turn link LED on. */
 			urtwn_set_led(sc, URTWN_LED_LINK, 1);
 			break;
@@ -1618,9 +1605,11 @@ urtwn_newstate(struct ieee80211vap *vap,
 		urtwn_write_2(sc, R92C_BCN_INTERVAL, ni->ni_intval);
 
 		/* Allow Rx from our BSSID only. */
-		urtwn_write_4(sc, R92C_RCR,
-		    urtwn_read_4(sc, R92C_RCR) |
-		    R92C_RCR_CBSSID_DATA | R92C_RCR_CBSSID_BCN);
+		if (ic->ic_promisc == 0) {
+			urtwn_write_4(sc, R92C_RCR,
+			    urtwn_read_4(sc, R92C_RCR) |
+			    R92C_RCR_CBSSID_DATA | R92C_RCR_CBSSID_BCN);
+		}
 
 		/* Enable TSF synchronization. */
 		urtwn_tsf_sync_enable(sc);
@@ -2755,21 +2744,50 @@ urtwn_pa_bias_init(struct urtwn_softc *s
 static void
 urtwn_rxfilter_init(struct urtwn_softc *sc)
 {
-	/* Initialize Rx filter. */
-	/* TODO: use better filter for monitor mode. */
-	urtwn_write_4(sc, R92C_RCR,
-	    R92C_RCR_AAP | R92C_RCR_APM | R92C_RCR_AM | R92C_RCR_AB |
-	    R92C_RCR_APP_ICV | R92C_RCR_AMF | R92C_RCR_HTC_LOC_CTRL |
-	    R92C_RCR_APP_MIC | R92C_RCR_APP_PHYSTS);
+	struct ieee80211com *ic = &sc->sc_ic;
+	struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
+	uint32_t rcr;
+	uint16_t filter;
+
+	URTWN_ASSERT_LOCKED(sc);
+
 	/* Accept all multicast frames. */
 	urtwn_write_4(sc, R92C_MAR + 0, 0xffffffff);
 	urtwn_write_4(sc, R92C_MAR + 4, 0xffffffff);
-	/* Accept all management frames. */
-	urtwn_write_2(sc, R92C_RXFLTMAP0, 0xffff);
+
+	/* Filter for management frames. */
+	filter = 0x7f3f;
+	if (vap->iv_opmode == IEEE80211_M_STA) {
+		filter &= ~(
+		    R92C_RXFLTMAP_SUBTYPE(IEEE80211_FC0_SUBTYPE_ASSOC_REQ) |
+		    R92C_RXFLTMAP_SUBTYPE(IEEE80211_FC0_SUBTYPE_REASSOC_REQ) |
+		    R92C_RXFLTMAP_SUBTYPE(IEEE80211_FC0_SUBTYPE_PROBE_REQ));
+	}
+	urtwn_write_2(sc, R92C_RXFLTMAP0, filter);
+
 	/* Reject all control frames. */
 	urtwn_write_2(sc, R92C_RXFLTMAP1, 0x0000);
-	/* Accept all data frames. */
-	urtwn_write_2(sc, R92C_RXFLTMAP2, 0xffff);
+
+	/* Reject all data frames. */
+	urtwn_write_2(sc, R92C_RXFLTMAP2, 0x0000);
+
+	rcr = R92C_RCR_AM | R92C_RCR_AB | R92C_RCR_APM |
+	      R92C_RCR_HTC_LOC_CTRL | R92C_RCR_APP_PHYSTS |
+	      R92C_RCR_APP_ICV | R92C_RCR_APP_MIC;
+
+	if (vap->iv_opmode == IEEE80211_M_MONITOR) {
+		/* Accept all frames. */
+		rcr |= R92C_RCR_ACF | R92C_RCR_ADF | R92C_RCR_AMF |
+		       R92C_RCR_AAP;
+	}
+
+	/* Set Rx filter. */
+	urtwn_write_4(sc, R92C_RCR, rcr);
+
+	if (ic->ic_promisc != 0) {
+		/* Update Rx filter. */
+		urtwn_set_promisc(sc);
+	}
 }
 
 static void
@@ -3080,7 +3098,8 @@ urtwn_scan_end(struct ieee80211com *ic)
 
 	URTWN_LOCK(sc);
 	/* Restore limitations. */
-	urtwn_set_rx_bssid_all(sc, 0);
+	if (ic->ic_promisc == 0)
+		urtwn_set_rx_bssid_all(sc, 0);
 	/* Set gain under link. */
 	urtwn_set_gain(sc, 0x32);
 	URTWN_UNLOCK(sc);
@@ -3102,6 +3121,52 @@ urtwn_set_channel(struct ieee80211com *i
 }
 
 static void
+urtwn_set_promisc(struct urtwn_softc *sc)
+{
+	struct ieee80211com *ic = &sc->sc_ic;
+	struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
+	uint32_t rcr, mask1, mask2;
+
+	URTWN_ASSERT_LOCKED(sc);
+
+	if (vap->iv_opmode == IEEE80211_M_MONITOR)
+		return;
+
+	mask1 = R92C_RCR_ACF | R92C_RCR_ADF | R92C_RCR_AMF | R92C_RCR_AAP;
+	mask2 = R92C_RCR_APM;
+
+	if (vap->iv_state == IEEE80211_S_RUN) {
+		switch (vap->iv_opmode) {
+		case IEEE80211_M_STA:
+			mask2 |= R92C_RCR_CBSSID_BCN | R92C_RCR_CBSSID_DATA;
+			break;
+		default:
+			device_printf(sc->sc_dev, "%s: undefined opmode %d\n",
+			    __func__, vap->iv_opmode);
+			return;
+		}
+	}
+
+	rcr = urtwn_read_4(sc, R92C_RCR);
+	if (ic->ic_promisc == 0)
+		rcr = (rcr & ~mask1) | mask2;
+	else
+		rcr = (rcr & ~mask2) | mask1;
+	urtwn_write_4(sc, R92C_RCR, rcr);
+}
+
+static void
+urtwn_update_promisc(struct ieee80211com *ic)
+{
+	struct urtwn_softc *sc = ic->ic_softc;
+
+	URTWN_LOCK(sc);
+	if (sc->sc_flags & URTWN_RUNNING)
+		urtwn_set_promisc(sc);
+	URTWN_UNLOCK(sc);
+}
+
+static void
 urtwn_update_mcast(struct ieee80211com *ic)
 {
 	/* XXX do nothing?  */
@@ -3302,6 +3367,7 @@ urtwn_init(struct urtwn_softc *sc)
 	/* Set initial network type. */
 	urtwn_set_mode(sc, R92C_MSR_INFRA);
 
+	/* Initialize Rx filter. */
 	urtwn_rxfilter_init(sc);
 
 	/* Set response rate. */
@@ -3375,6 +3441,9 @@ urtwn_init(struct urtwn_softc *sc)
 	urtwn_bb_init(sc);
 	urtwn_rf_init(sc);
 
+	/* Reinitialize Rx filter (D3845 is not committed yet). */
+	urtwn_rxfilter_init(sc);
+
 	if (sc->chip & URTWN_CHIP_88E) {
 		urtwn_write_2(sc, R92C_CR,
 		    urtwn_read_2(sc, R92C_CR) | R92C_CR_MACTXEN |

Modified: head/sys/dev/usb/wlan/if_urtwnreg.h
==============================================================================
--- head/sys/dev/usb/wlan/if_urtwnreg.h	Sun Nov  8 23:06:40 2015	(r290563)
+++ head/sys/dev/usb/wlan/if_urtwnreg.h	Sun Nov  8 23:21:54 2015	(r290564)
@@ -535,6 +535,10 @@
 #define R92C_CAMCMD_CLR		0x40000000
 #define R92C_CAMCMD_POLLING	0x80000000
 
+/* Bits for R92C_RXFLTMAP*. */
+#define R92C_RXFLTMAP_SUBTYPE(subtype)	\
+	(1 << ((subtype) >> IEEE80211_FC0_SUBTYPE_SHIFT))
+
 
 /*
  * Baseband registers.


More information about the svn-src-all mailing list