rtl8xxxu: Enable monitor mode by handling filters
authorBruno Randolf <br1@einfach.org>
Wed, 3 Feb 2016 18:39:51 +0000 (13:39 -0500)
committerKalle Valo <kvalo@codeaurora.org>
Thu, 25 Feb 2016 09:55:35 +0000 (11:55 +0200)
Monitor mode is enabled by handling the filter flags we get from mac80211 in
rtl8xxxu_configure_filter() and writing them to the RCR register.

By handling the filters, we can also stop setting the BSSID filters in the
association event.

Signed-off-by: Bruno Randolf <br1@einfach.org>
Signed-off-by: Jes Sorensen <Jes.Sorensen@redhat.com>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.c

index ac4c211184df5d040eb98988a6a01f615f2ac446..b58a60f8ceb1d936fda927c90dd6c546dee5a169 100644 (file)
@@ -4199,7 +4199,6 @@ static int rtl8xxxu_init_device(struct ieee80211_hw *hw)
         * Configure initial WMAC settings
         */
        val32 = RCR_ACCEPT_PHYS_MATCH | RCR_ACCEPT_MCAST | RCR_ACCEPT_BCAST |
-               /* RCR_CHECK_BSSID_MATCH | RCR_CHECK_BSSID_BEACON | */
                RCR_ACCEPT_MGMT_FRAME | RCR_HTC_LOC_CTRL |
                RCR_APPEND_PHYSTAT | RCR_APPEND_ICV | RCR_APPEND_MIC;
        rtl8xxxu_write32(priv, REG_RCR, val32);
@@ -4522,10 +4521,6 @@ rtl8xxxu_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
 
                        rtl8xxxu_update_rate_mask(priv, ramask, sgi);
 
-                       val32 = rtl8xxxu_read32(priv, REG_RCR);
-                       val32 |= RCR_CHECK_BSSID_MATCH | RCR_CHECK_BSSID_BEACON;
-                       rtl8xxxu_write32(priv, REG_RCR, val32);
-
                        /* Enable RX of data frames */
                        rtl8xxxu_write16(priv, REG_RXFLTMAP2, 0xffff);
 
@@ -4539,11 +4534,6 @@ rtl8xxxu_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
 
                        h2c.joinbss.data = H2C_JOIN_BSS_CONNECT;
                } else {
-                       val32 = rtl8xxxu_read32(priv, REG_RCR);
-                       val32 &= ~(RCR_CHECK_BSSID_MATCH |
-                                  RCR_CHECK_BSSID_BEACON);
-                       rtl8xxxu_write32(priv, REG_RCR, val32);
-
                        val8 = rtl8xxxu_read8(priv, REG_BEACON_CTRL);
                        val8 |= BEACON_DISABLE_TSF_UPDATE;
                        rtl8xxxu_write8(priv, REG_BEACON_CTRL, val8);
@@ -5318,11 +5308,55 @@ static void rtl8xxxu_configure_filter(struct ieee80211_hw *hw,
                                      unsigned int *total_flags, u64 multicast)
 {
        struct rtl8xxxu_priv *priv = hw->priv;
+       u32 rcr = rtl8xxxu_read32(priv, REG_RCR);
 
        dev_dbg(&priv->udev->dev, "%s: changed_flags %08x, total_flags %08x\n",
                __func__, changed_flags, *total_flags);
 
-       *total_flags &= (FIF_ALLMULTI | FIF_CONTROL | FIF_BCN_PRBRESP_PROMISC);
+       /*
+        * FIF_ALLMULTI ignored as all multicast frames are accepted (REG_MAR)
+        */
+
+       if (*total_flags & FIF_FCSFAIL)
+               rcr |= RCR_ACCEPT_CRC32;
+       else
+               rcr &= ~RCR_ACCEPT_CRC32;
+
+       /*
+        * FIF_PLCPFAIL not supported?
+        */
+
+       if (*total_flags & FIF_BCN_PRBRESP_PROMISC)
+               rcr &= ~RCR_CHECK_BSSID_BEACON;
+       else
+               rcr |= RCR_CHECK_BSSID_BEACON;
+
+       if (*total_flags & FIF_CONTROL)
+               rcr |= RCR_ACCEPT_CTRL_FRAME;
+       else
+               rcr &= ~RCR_ACCEPT_CTRL_FRAME;
+
+       if (*total_flags & FIF_OTHER_BSS) {
+               rcr |= RCR_ACCEPT_AP;
+               rcr &= ~RCR_CHECK_BSSID_MATCH;
+       } else {
+               rcr &= ~RCR_ACCEPT_AP;
+               rcr |= RCR_CHECK_BSSID_MATCH;
+       }
+
+       if (*total_flags & FIF_PSPOLL)
+               rcr |= RCR_ACCEPT_PM;
+       else
+               rcr &= ~RCR_ACCEPT_PM;
+
+       /*
+        * FIF_PROBE_REQ ignored as probe requests always seem to be accepted
+        */
+
+       rtl8xxxu_write32(priv, REG_RCR, rcr);
+
+       *total_flags &= (FIF_ALLMULTI | FIF_FCSFAIL | FIF_BCN_PRBRESP_PROMISC | \
+                        FIF_CONTROL | FIF_OTHER_BSS | FIF_PSPOLL | FIF_PROBE_REQ);
 }
 
 static int rtl8xxxu_set_rts_threshold(struct ieee80211_hw *hw, u32 rts)