aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAdrian Chadd <adrian@FreeBSD.org>2024-11-27 00:59:15 +0000
committerAdrian Chadd <adrian@FreeBSD.org>2024-12-05 07:27:03 +0000
commitd76247e801dec95600a068fa1bb09f4f57e00031 (patch)
tree83f7c40c227861f61b24c1eeb8ba296f3232c77f
parent4fa68495f04ff3906c6d93d7c296fea5bc0311d3 (diff)
rtwn: enable FCS in the recive config to work around truncated frames
I noticed that on RTL8812AU/RTL8821AU receiving VHT frames that I'd occasionally see frames missing the last 4 bytes. I can easily reproduce it with a ping sweep and fast (10ms) between frames. There's also a report of an earlier NIC (RTL8188EU) doing the same thing with HT frames but not with OFDM (11g) frames. After a bunch of poking, it turns out a driver where things DID work properly for the other report kept FCS enabled, and trimmed it from the frame before pushing it up to the network layer. I did the same and it also worked fine. The other solution was to disable PHYSTATUS notifications, but then we'd get no per packet RX notifications (RX rate, RSSI, etc.) Locally tested: * RTL8192EU, STA mode (HT) * RTL8812AU, STA mode (HT, VHT) * RTL8821AU, STA mode (HT, VHT) Differential Revision: https://reviews.freebsd.org/D47775
-rw-r--r--sys/dev/rtwn/if_rtwn_rx.c15
1 files changed, 14 insertions, 1 deletions
diff --git a/sys/dev/rtwn/if_rtwn_rx.c b/sys/dev/rtwn/if_rtwn_rx.c
index 762472eca440..ebfb8e67ec6d 100644
--- a/sys/dev/rtwn/if_rtwn_rx.c
+++ b/sys/dev/rtwn/if_rtwn_rx.c
@@ -318,6 +318,10 @@ rtwn_rx_common(struct rtwn_softc *sc, struct mbuf *m, void *desc)
/* Drop PHY descriptor. */
m_adj(m, infosz + shift);
+ /* If APPFCS, drop FCS */
+ if (sc->rcr & R92C_RCR_APPFCS)
+ m_adj(m, -IEEE80211_CRC_LEN);
+
return (ni);
}
@@ -456,6 +460,15 @@ rtwn_rxfilter_init(struct rtwn_softc *sc)
R92C_RCR_HTC_LOC_CTRL | R92C_RCR_APP_PHYSTS |
R92C_RCR_APP_ICV | R92C_RCR_APP_MIC;
+ /*
+ * Add FCS, to work around occasional 4 byte truncation
+ * with some frames. This is more problematic on RTL8812/
+ * RTL8821 because they're also doing L3/L4 checksum offload
+ * and hardware encryption, so both are tagged as "passed"
+ * before the frame is truncated.
+ */
+ sc->rcr |= R92C_RCR_APPFCS;
+
/* Update dynamic Rx filter parts. */
rtwn_rxfilter_update(sc);
}
@@ -487,7 +500,7 @@ rtwn_set_promisc(struct rtwn_softc *sc)
RTWN_ASSERT_LOCKED(sc);
mask_all = R92C_RCR_ACF | R92C_RCR_ADF | R92C_RCR_AMF | R92C_RCR_AAP;
- mask_min = R92C_RCR_APM;
+ mask_min = R92C_RCR_APM | R92C_RCR_APPFCS;
if (sc->bcn_vaps == 0)
mask_min |= R92C_RCR_CBSSID_BCN;