mirror of
https://git.FreeBSD.org/src.git
synced 2024-12-20 11:11:24 +00:00
Drain the mbuf queue upon rsu_stop().
Correctly (I hope!) remove net80211 references before doing so. Just doing a dumb mbufq drain isn't enough. If enough traffic occurs and the mbuf queue fills up then transmit stalls (which I'm not fixing in this commit!) but then the mbuf queue stays full until the driver is removed. There's also the net80211 node refcounting leak. This just ensures that during rsu_stop and detach the mbuf queue is purged (and references!) so the queue-full situation can be recovered from.
This commit is contained in:
parent
ea8b18848f
commit
829e0b0b84
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=288051
@ -508,6 +508,8 @@ rsu_detach(device_t self)
|
||||
rsu_stop(sc);
|
||||
RSU_UNLOCK(sc);
|
||||
usbd_transfer_unsetup(sc->sc_xfer, RSU_N_TRANSFER);
|
||||
|
||||
/* Frames are freed; detach from net80211 */
|
||||
ieee80211_ifdetach(ic);
|
||||
|
||||
taskqueue_drain_timeout(taskqueue_thread, &sc->calib_task);
|
||||
@ -516,7 +518,6 @@ rsu_detach(device_t self)
|
||||
rsu_free_tx_list(sc);
|
||||
rsu_free_rx_list(sc);
|
||||
|
||||
mbufq_drain(&sc->sc_snd);
|
||||
mtx_destroy(&sc->sc_mtx);
|
||||
|
||||
return (0);
|
||||
@ -759,6 +760,9 @@ rsu_getbuf(struct rsu_softc *sc)
|
||||
RSU_ASSERT_LOCKED(sc);
|
||||
|
||||
bf = _rsu_getbuf(sc);
|
||||
if (bf == NULL) {
|
||||
RSU_DPRINTF(sc, RSU_DEBUG_TX, "%s: no buffers\n", __func__);
|
||||
}
|
||||
return (bf);
|
||||
}
|
||||
|
||||
@ -1997,6 +2001,10 @@ rsu_transmit(struct ieee80211com *ic, struct mbuf *m)
|
||||
}
|
||||
error = mbufq_enqueue(&sc->sc_snd, m);
|
||||
if (error) {
|
||||
RSU_DPRINTF(sc, RSU_DEBUG_TX,
|
||||
"%s: mbufq_enable: failed (%d)\n",
|
||||
__func__,
|
||||
error);
|
||||
RSU_UNLOCK(sc);
|
||||
return (error);
|
||||
}
|
||||
@ -2006,6 +2014,21 @@ rsu_transmit(struct ieee80211com *ic, struct mbuf *m)
|
||||
return (0);
|
||||
}
|
||||
|
||||
static void
|
||||
rsu_drain_mbufq(struct rsu_softc *sc)
|
||||
{
|
||||
struct mbuf *m;
|
||||
struct ieee80211_node *ni;
|
||||
|
||||
RSU_ASSERT_LOCKED(sc);
|
||||
while ((m = mbufq_dequeue(&sc->sc_snd)) != NULL) {
|
||||
ni = (struct ieee80211_node *)m->m_pkthdr.rcvif;
|
||||
m->m_pkthdr.rcvif = NULL;
|
||||
ieee80211_free_node(ni);
|
||||
m_freem(m);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
rsu_start(struct rsu_softc *sc)
|
||||
{
|
||||
@ -2018,6 +2041,8 @@ rsu_start(struct rsu_softc *sc)
|
||||
while ((m = mbufq_dequeue(&sc->sc_snd)) != NULL) {
|
||||
bf = rsu_getbuf(sc);
|
||||
if (bf == NULL) {
|
||||
RSU_DPRINTF(sc, RSU_DEBUG_TX,
|
||||
"%s: failed to get buffer\n", __func__);
|
||||
mbufq_prepend(&sc->sc_snd, m);
|
||||
break;
|
||||
}
|
||||
@ -2026,6 +2051,8 @@ rsu_start(struct rsu_softc *sc)
|
||||
m->m_pkthdr.rcvif = NULL;
|
||||
|
||||
if (rsu_tx_start(sc, ni, m, bf) != 0) {
|
||||
RSU_DPRINTF(sc, RSU_DEBUG_TX,
|
||||
"%s: failed to transmit\n", __func__);
|
||||
if_inc_counter(ni->ni_vap->iv_ifp,
|
||||
IFCOUNTER_OERRORS, 1);
|
||||
rsu_freebuf(sc, bf);
|
||||
@ -2551,6 +2578,9 @@ rsu_init(struct rsu_softc *sc)
|
||||
|
||||
RSU_ASSERT_LOCKED(sc);
|
||||
|
||||
/* Ensure the mbuf queue is drained */
|
||||
rsu_drain_mbufq(sc);
|
||||
|
||||
/* Init host async commands ring. */
|
||||
sc->cmdq.cur = sc->cmdq.next = sc->cmdq.queued = 0;
|
||||
|
||||
@ -2660,6 +2690,9 @@ rsu_stop(struct rsu_softc *sc)
|
||||
|
||||
for (i = 0; i < RSU_N_TRANSFER; i++)
|
||||
usbd_transfer_stop(sc->sc_xfer[i]);
|
||||
|
||||
/* Ensure the mbuf queue is drained */
|
||||
rsu_drain_mbufq(sc);
|
||||
}
|
||||
|
||||
/*
|
||||
|
Loading…
Reference in New Issue
Block a user