rtwn: narrow the epoch area

Rather than placing the epoch around the entire receive loop which
might call into rtwn_rx_frame() and USB and sleep, split the loop
into two[1] and leave us with one unlock/lock cycle as well.

PR:		249925
Reported by:	thj, (rkoberman gmail.com)
Tested by:	thj
Suggested by:	adrian [1]
Reviewed by:	adrian
MFC after:	3 days
Sponsored by:	The FreeBSD Foundation (initially, paniced my iwl lab host)
Differential Revision:	https://reviews.freebsd.org/D26554
This commit is contained in:
Bjoern A. Zeeb 2020-09-29 20:46:25 +00:00
parent 6186bfbd18
commit 3917c9ba65

View File

@ -368,7 +368,7 @@ rtwn_bulk_rx_callback(struct usb_xfer *xfer, usb_error_t error)
struct rtwn_softc *sc = &uc->uc_sc;
struct ieee80211com *ic = &sc->sc_ic;
struct ieee80211_node *ni;
struct mbuf *m = NULL, *next;
struct mbuf *m0, *m = NULL, *next;
struct rtwn_data *data;
RTWN_ASSERT_LOCKED(sc);
@ -400,24 +400,30 @@ rtwn_bulk_rx_callback(struct usb_xfer *xfer, usb_error_t error)
* ieee80211_input() because here is at the end of a USB
* callback and safe to unlock.
*/
m0 = m;
while (m != NULL) {
M_ASSERTPKTHDR(m);
m->m_pkthdr.PH_loc.ptr = rtwn_rx_frame(sc, m);
m = m->m_nextpkt;
}
NET_EPOCH_ENTER(et);
RTWN_UNLOCK(sc);
m = m0;
while (m != NULL) {
next = m->m_nextpkt;
m->m_nextpkt = NULL;
ni = rtwn_rx_frame(sc, m);
RTWN_UNLOCK(sc);
ni = m->m_pkthdr.PH_loc.ptr;
m->m_pkthdr.PH_loc.ptr = NULL;
if (ni != NULL) {
(void)ieee80211_input_mimo(ni, m);
ieee80211_free_node(ni);
} else {
(void)ieee80211_input_mimo_all(ic, m);
}
RTWN_LOCK(sc);
m = next;
}
RTWN_LOCK(sc);
NET_EPOCH_EXIT(et);
break;
default: