The rt2560 part of the ral driver uses a prio queue for management frames and a tx queue for data frames.
Both queues currently use a shared flag to tell the network stack that they are full (IFF_OACTIVE). It seems that IFF_OACTIVE can get cleared by the interrupt handler for one queue while the other queue is still loaded, so the network layer might try to push more frames down while we can't actually handle them. With the diff below we reset IFF_OACTIVE only if both prio and tx queues have been drained. Also, don't reset the tx watchdog counter if the tx/prio queues still have frames queued when we exit the frame-processing loop in either interrupt handler. Else, it seems the watchdog might fail to run rt2560_init() even though we failed to transmit some frames. Both changes from sephe@dragonfly [[[ commit b77254ce33366a140b2dc273fa7b4439aac4b07c Author: Sepherosa Ziehau <se...@dragonflybsd.org> Date: Fri Jan 25 14:43:10 2008 +0000 There are actually two TX queues for 2560 parts, so add two softc private flags which are used to mark that the TX queues are "over active". Clear IFF_OACTIVE iff all of the private OACT flags are off. commit c22d69a1955e146448ea0708347dbcaa72c3647f Author: Sepherosa Ziehau <se...@dragonflybsd.org> Date: Fri Jan 25 14:26:14 2008 +0000 Don't reset watchdog timeout value, if there are still TX descs pending on either data queue or prio(management) queue. ]]] This diff survived tcpbench traffic to ral hostap in an x60s thinkpad over night, with flags=<..,OACTIVE,...> showing up very often in ifconfig output. A concurrent ping from AP to STA resulted in: 42744 packets transmitted, 42698 packets received, 0.1% packet loss I'm not sure yet if this fixes the bug where ral gets stuck with OACTIVE on soekris and requires "ifconfig ral0 down up" to unwedge. Tests on soekris or similarly slow hardware are very welcome. Index: rt2560.c =================================================================== RCS file: /cvs/src/sys/dev/ic/rt2560.c,v retrieving revision 1.58 diff -u -p -r1.58 rt2560.c --- rt2560.c 22 Feb 2011 20:05:03 -0000 1.58 +++ rt2560.c 8 Jul 2012 07:48:08 -0000 @@ -995,9 +995,14 @@ rt2560_tx_intr(struct rt2560_softc *sc) sc->txq.next = (sc->txq.next + 1) % RT2560_TX_RING_COUNT; } - sc->sc_tx_timer = 0; - ifp->if_flags &= ~IFF_OACTIVE; - rt2560_start(ifp); + if (sc->txq.queued == 0 && sc->prioq.queued == 0) + sc->sc_tx_timer = 0; + if (sc->txq.queued < RT2560_TX_RING_COUNT - 1) { + sc->sc_flags &= ~RT2560_DATA_OACTIVE; + if (!(sc->sc_flags & (RT2560_DATA_OACTIVE|RT2560_PRIO_OACTIVE))) + ifp->if_flags &= ~IFF_OACTIVE; + rt2560_start(ifp); + } } void @@ -1061,9 +1066,14 @@ rt2560_prio_intr(struct rt2560_softc *sc sc->prioq.next = (sc->prioq.next + 1) % RT2560_PRIO_RING_COUNT; } - sc->sc_tx_timer = 0; - ifp->if_flags &= ~IFF_OACTIVE; - rt2560_start(ifp); + if (sc->txq.queued == 0 && sc->prioq.queued == 0) + sc->sc_tx_timer = 0; + if (sc->prioq.queued < RT2560_PRIO_RING_COUNT) { + sc->sc_flags &= ~RT2560_PRIO_OACTIVE; + if (!(sc->sc_flags & (RT2560_DATA_OACTIVE|RT2560_PRIO_OACTIVE))) + ifp->if_flags &= ~IFF_OACTIVE; + rt2560_start(ifp); + } } /* @@ -1931,6 +1941,7 @@ rt2560_start(struct ifnet *ifp) if (m0 != NULL) { if (sc->prioq.queued >= RT2560_PRIO_RING_COUNT) { ifp->if_flags |= IFF_OACTIVE; + sc->sc_flags |= RT2560_PRIO_OACTIVE; break; } IF_DEQUEUE(&ic->ic_mgtq, m0); @@ -1952,6 +1963,7 @@ rt2560_start(struct ifnet *ifp) break; if (sc->txq.queued >= RT2560_TX_RING_COUNT - 1) { ifp->if_flags |= IFF_OACTIVE; + sc->sc_flags |= RT2560_DATA_OACTIVE; break; } IFQ_DEQUEUE(&ifp->if_snd, m0); @@ -2685,6 +2697,7 @@ rt2560_stop(struct ifnet *ifp, int disab struct ieee80211com *ic = &sc->sc_ic; sc->sc_tx_timer = 0; + sc->sc_flags &= ~(RT2560_PRIO_OACTIVE|RT2560_DATA_OACTIVE); ifp->if_timer = 0; ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE); Index: rt2560var.h =================================================================== RCS file: /cvs/src/sys/dev/ic/rt2560var.h,v retrieving revision 1.9 diff -u -p -r1.9 rt2560var.h --- rt2560var.h 7 Sep 2010 16:21:42 -0000 1.9 +++ rt2560var.h 7 Jul 2012 15:58:58 -0000 @@ -116,6 +116,8 @@ struct rt2560_softc { #define RT2560_ENABLED (1 << 0) #define RT2560_UPDATE_SLOT (1 << 1) #define RT2560_SET_SLOTTIME (1 << 2) +#define RT2560_PRIO_OACTIVE (1 << 3) +#define RT2560_DATA_OACTIVE (1 << 4) int sc_tx_timer;