Author: avos
Date: Sat Nov  5 23:21:30 2016
New Revision: 308356
URL: https://svnweb.freebsd.org/changeset/base/308356

Log:
  rtwn: fix Rx filter setup for some multi-vap configuratons.
  
  - Correctly refresh Rx filter when AP (IBSS) vap is created after STA vap.
  - Block any RCR updates during TSF correction (IBSS mode).
  - Set CBSSID* bits during vap creation, not when it was started / stopped.
  - Cache current state to prevent unnecessary register reads.
  
  Tested with RTL8188CE, STA + AP mode.

Modified:
  head/sys/dev/rtwn/if_rtwn.c
  head/sys/dev/rtwn/if_rtwn_rx.c
  head/sys/dev/rtwn/if_rtwn_rx.h
  head/sys/dev/rtwn/if_rtwnvar.h
  head/sys/dev/rtwn/rtl8812a/r12a_caps.c

Modified: head/sys/dev/rtwn/if_rtwn.c
==============================================================================
--- head/sys/dev/rtwn/if_rtwn.c Sat Nov  5 22:47:09 2016        (r308355)
+++ head/sys/dev/rtwn/if_rtwn.c Sat Nov  5 23:21:30 2016        (r308356)
@@ -917,6 +917,9 @@ rtwn_tsf_sync_adhoc_task(void *arg, int 
        /* Accept beacons with the same BSSID. */
        rtwn_set_rx_bssid_all(sc, 0);
 
+       /* Deny RCR updates. */
+       sc->sc_flags |= RTWN_RCR_LOCKED;
+
        /* Enable synchronization. */
        rtwn_setbits_1(sc, R92C_BCN_CTRL(uvp->id),
            R92C_BCN_CTRL_DIS_TSF_UDT0, 0);
@@ -929,6 +932,7 @@ rtwn_tsf_sync_adhoc_task(void *arg, int 
            0, R92C_BCN_CTRL_DIS_TSF_UDT0);
 
        /* Accept all beacons. */
+       sc->sc_flags &= ~RTWN_RCR_LOCKED;
        rtwn_set_rx_bssid_all(sc, 1);
 
        /* Schedule next TSF synchronization. */
@@ -1193,7 +1197,6 @@ rtwn_run(struct rtwn_softc *sc, struct i
        struct ieee80211com *ic = vap->iv_ic;
        struct rtwn_vap *uvp = RTWN_VAP(vap);
        struct ieee80211_node *ni;
-       uint32_t reg;
        uint8_t mode;
        int error;
 
@@ -1246,18 +1249,6 @@ rtwn_run(struct rtwn_softc *sc, struct i
                rtwn_write_1(sc, R92C_TXPAUSE, 0);
        }
 
-       /* Allow Rx from our BSSID only. */
-       if (ic->ic_promisc == 0) {
-               reg = rtwn_read_4(sc, R92C_RCR);
-
-               if (sc->bcn_vaps == 0)
-                       reg |= R92C_RCR_CBSSID_BCN;
-               if (sc->ap_vaps == 0)
-                       reg |= R92C_RCR_CBSSID_DATA;
-
-               rtwn_write_4(sc, R92C_RCR, reg);
-       }
-
 #ifndef RTWN_WITHOUT_UCODE
        /* Upload (QoS) Null Data frame to firmware. */
        /* Note: do this for port 0 only. */

Modified: head/sys/dev/rtwn/if_rtwn_rx.c
==============================================================================
--- head/sys/dev/rtwn/if_rtwn_rx.c      Sat Nov  5 22:47:09 2016        
(r308355)
+++ head/sys/dev/rtwn/if_rtwn_rx.c      Sat Nov  5 23:21:30 2016        
(r308356)
@@ -362,7 +362,7 @@ rtwn_rxfilter_update_mgt(struct rtwn_sof
 {
        uint16_t filter;
 
-       filter = 0x7f3f;
+       filter = 0x7f7f;
        if (sc->bcn_vaps == 0) {        /* STA and/or MONITOR mode vaps */
                filter &= ~(
                    R92C_RXFLTMAP_SUBTYPE(IEEE80211_FC0_SUBTYPE_ASSOC_REQ) |
@@ -393,7 +393,6 @@ rtwn_rxfilter_update(struct rtwn_softc *
 void
 rtwn_rxfilter_init(struct rtwn_softc *sc)
 {
-       uint32_t rcr;
 
        RTWN_ASSERT_LOCKED(sc);
 
@@ -406,47 +405,60 @@ rtwn_rxfilter_init(struct rtwn_softc *sc
        /* Reject all data frames. */
        rtwn_write_2(sc, R92C_RXFLTMAP2, 0x0000);
 
-       rcr = sc->rcr;
-       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;
-
-       /* Set Rx filter. */
-       rtwn_write_4(sc, R92C_RCR, rcr);
+       /* Append generic Rx filter bits. */
+       sc->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;
 
        /* Update dynamic Rx filter parts. */
        rtwn_rxfilter_update(sc);
 }
 
 void
+rtwn_rxfilter_set(struct rtwn_softc *sc)
+{
+       if (!(sc->sc_flags & RTWN_RCR_LOCKED))
+               rtwn_write_4(sc, R92C_RCR, sc->rcr);
+}
+
+void
 rtwn_set_rx_bssid_all(struct rtwn_softc *sc, int enable)
 {
+
        if (enable)
-               rtwn_setbits_4(sc, R92C_RCR, R92C_RCR_CBSSID_BCN, 0);
+               sc->rcr &= ~R92C_RCR_CBSSID_BCN;
        else
-               rtwn_setbits_4(sc, R92C_RCR, 0, R92C_RCR_CBSSID_BCN);
+               sc->rcr |= R92C_RCR_CBSSID_BCN;
+       rtwn_rxfilter_set(sc);
 }
 
 void
 rtwn_set_promisc(struct rtwn_softc *sc)
 {
        struct ieee80211com *ic = &sc->sc_ic;
-       uint32_t mask1, mask2;
+       uint32_t mask_all, mask_min;
 
        RTWN_ASSERT_LOCKED(sc);
 
-       mask1 = R92C_RCR_ACF | R92C_RCR_ADF | R92C_RCR_AMF | R92C_RCR_AAP;
-       mask2 = R92C_RCR_APM;
+       mask_all = R92C_RCR_ACF | R92C_RCR_ADF | R92C_RCR_AMF | R92C_RCR_AAP;
+       mask_min = R92C_RCR_APM;
 
-       if (sc->vaps_running != 0) {
-               if (sc->bcn_vaps == 0)
-                       mask2 |= R92C_RCR_CBSSID_BCN;
-               if (sc->ap_vaps == 0)
-                       mask2 |= R92C_RCR_CBSSID_DATA;
+       if (sc->bcn_vaps == 0)
+               mask_min |= R92C_RCR_CBSSID_BCN;
+       if (sc->ap_vaps == 0)
+               mask_min |= R92C_RCR_CBSSID_DATA;
+
+       if (ic->ic_promisc == 0 && sc->mon_vaps == 0) {
+               if (sc->bcn_vaps != 0)
+                       mask_all |= R92C_RCR_CBSSID_BCN;
+               if (sc->ap_vaps != 0)   /* for Null data frames */
+                       mask_all |= R92C_RCR_CBSSID_DATA;
+
+               sc->rcr &= ~mask_all;
+               sc->rcr |= mask_min;
+       } else {
+               sc->rcr &= ~mask_min;
+               sc->rcr |= mask_all;
        }
-
-       if (ic->ic_promisc == 0 && sc->mon_vaps == 0)
-               rtwn_setbits_4(sc, R92C_RCR, mask1, mask2);
-       else
-               rtwn_setbits_4(sc, R92C_RCR, mask2, mask1);
+       rtwn_rxfilter_set(sc);
 }

Modified: head/sys/dev/rtwn/if_rtwn_rx.h
==============================================================================
--- head/sys/dev/rtwn/if_rtwn_rx.h      Sat Nov  5 22:47:09 2016        
(r308355)
+++ head/sys/dev/rtwn/if_rtwn_rx.h      Sat Nov  5 23:21:30 2016        
(r308356)
@@ -32,6 +32,7 @@ void  rtwn_adhoc_recv_mgmt(struct ieee802
 void   rtwn_set_multi(struct rtwn_softc *);
 void   rtwn_rxfilter_update(struct rtwn_softc *);
 void   rtwn_rxfilter_init(struct rtwn_softc *);
+void   rtwn_rxfilter_set(struct rtwn_softc *);
 void   rtwn_set_rx_bssid_all(struct rtwn_softc *, int);
 void   rtwn_set_promisc(struct rtwn_softc *);
 

Modified: head/sys/dev/rtwn/if_rtwnvar.h
==============================================================================
--- head/sys/dev/rtwn/if_rtwnvar.h      Sat Nov  5 22:47:09 2016        
(r308355)
+++ head/sys/dev/rtwn/if_rtwnvar.h      Sat Nov  5 23:21:30 2016        
(r308356)
@@ -186,6 +186,7 @@ struct rtwn_softc {
 #define RTWN_RUNNING           0x10
 #define RTWN_FW_LOADED         0x20
 #define RTWN_TEMP_MEASURED     0x40
+#define RTWN_RCR_LOCKED                0x80
 
 #define RTWN_CHIP_HAS_BCNQ1(_sc)       \
        ((_sc)->bcn_status_reg[0] != (_sc)->bcn_status_reg[1])

Modified: head/sys/dev/rtwn/rtl8812a/r12a_caps.c
==============================================================================
--- head/sys/dev/rtwn/rtl8812a/r12a_caps.c      Sat Nov  5 22:47:09 2016        
(r308355)
+++ head/sys/dev/rtwn/rtl8812a/r12a_caps.c      Sat Nov  5 23:21:30 2016        
(r308356)
@@ -53,6 +53,7 @@ __FBSDID("$FreeBSD$");
 #include <net80211/ieee80211_radiotap.h>
 
 #include <dev/rtwn/if_rtwnvar.h>
+#include <dev/rtwn/if_rtwn_rx.h>
 
 #include <dev/rtwn/rtl8812a/r12a.h>
 #include <dev/rtwn/rtl8812a/r12a_reg.h>
@@ -89,19 +90,13 @@ r12a_ioctl_net(struct ieee80211com *ic, 
                        changed = 1;
                }
                if (changed) {
-                       if (rxmask == 0) {
+                       if (rxmask == 0)
                                sc->rcr &= ~R12A_RCR_TCP_OFFLD_EN;
-                               if (sc->sc_flags & RTWN_RUNNING) {
-                                       rtwn_setbits_4(sc, R92C_RCR,
-                                           R12A_RCR_TCP_OFFLD_EN, 0);
-                               }
-                       } else {
+                       else
                                sc->rcr |= R12A_RCR_TCP_OFFLD_EN;
-                               if (sc->sc_flags & RTWN_RUNNING) {
-                                       rtwn_setbits_4(sc, R92C_RCR,
-                                           0, R12A_RCR_TCP_OFFLD_EN);
-                               }
-                       }
+
+                       if (sc->sc_flags & RTWN_RUNNING)
+                               rtwn_rxfilter_set(sc);
                }
                RTWN_UNLOCK(sc);
 
_______________________________________________
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to