On Tue, Jul 10, 2012 at 05:56:29PM +0200, Stefan Sperling wrote:
> Updated version that includes similar fixes for the rt2661 variants.
>
> This seems to help soekris-based ral APs that get stuck with the OACTIVE
> flag set (see the flags line in "ifconfig ral0" output when the AP stops
> responding) and then require "ifconfig ral0 down up" to recover.
>
> It would be great to get some more testing. Thanks!
Anyone want to OK this?
We've been testing this with edd's soekris (rt2661 minipci)
and two rt2560/rt2661 ralink cardbus cards.
>
> 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 10 Jul 2012 15:34:21 -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;
>
> Index: rt2661.c
> ===================================================================
> RCS file: /cvs/src/sys/dev/ic/rt2661.c,v
> retrieving revision 1.65
> diff -u -p -r1.65 rt2661.c
> --- rt2661.c 18 Mar 2011 06:05:21 -0000 1.65
> +++ rt2661.c 10 Jul 2012 15:38:03 -0000
> @@ -986,9 +986,18 @@ rt2661_tx_intr(struct rt2661_softc *sc)
> txq->stat = 0;
> }
>
> - sc->sc_tx_timer = 0;
> - ifp->if_flags &= ~IFF_OACTIVE;
> - rt2661_start(ifp);
> + if (sc->mgtq.queued == 0 && sc->txq[0].queued == 0)
> + sc->sc_tx_timer = 0;
> + if (sc->mgtq.queued < RT2661_MGT_RING_COUNT &&
> + sc->txq[0].queued < RT2661_TX_RING_COUNT - 1) {
> + if (sc->mgtq.queued < RT2661_MGT_RING_COUNT)
> + sc->sc_flags &= ~RT2661_MGT_OACTIVE;
> + if (sc->txq[0].queued < RT2661_TX_RING_COUNT - 1)
> + sc->sc_flags &= ~RT2661_DATA_OACTIVE;
> + if (!(sc->sc_flags & (RT2661_MGT_OACTIVE|RT2661_DATA_OACTIVE)))
> + ifp->if_flags &= ~IFF_OACTIVE;
> + rt2661_start(ifp);
> + }
> }
>
> void
> @@ -1805,6 +1814,7 @@ rt2661_start(struct ifnet *ifp)
> if (m0 != NULL) {
> if (sc->mgtq.queued >= RT2661_MGT_RING_COUNT) {
> ifp->if_flags |= IFF_OACTIVE;
> + sc->sc_flags |= RT2661_MGT_OACTIVE;
> break;
> }
> IF_DEQUEUE(&ic->ic_mgtq, m0);
> @@ -1827,6 +1837,7 @@ rt2661_start(struct ifnet *ifp)
> if (sc->txq[0].queued >= RT2661_TX_RING_COUNT - 1) {
> /* there is no place left in this ring */
> ifp->if_flags |= IFF_OACTIVE;
> + sc->sc_flags |= RT2661_DATA_OACTIVE;
> break;
> }
> IFQ_DEQUEUE(&ifp->if_snd, m0);
> @@ -2602,6 +2613,7 @@ rt2661_stop(struct ifnet *ifp, int disab
> int ac;
>
> sc->sc_tx_timer = 0;
> + sc->sc_flags &= ~(RT2661_MGT_OACTIVE|RT2661_DATA_OACTIVE);
> ifp->if_timer = 0;
> ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
>
> Index: rt2661var.h
> ===================================================================
> RCS file: /cvs/src/sys/dev/ic/rt2661var.h,v
> retrieving revision 1.14
> diff -u -p -r1.14 rt2661var.h
> --- rt2661var.h 18 Mar 2011 06:05:21 -0000 1.14
> +++ rt2661var.h 10 Jul 2012 13:17:30 -0000
> @@ -111,6 +111,8 @@ struct rt2661_softc {
> #define RT2661_UPDATE_SLOT (1 << 1)
> #define RT2661_SET_SLOTTIME (1 << 2)
> #define RT2661_FWLOADED (1 << 3)
> +#define RT2661_MGT_OACTIVE (1 << 4)
> +#define RT2661_DATA_OACTIVE (1 << 5)
>
> int sc_tx_timer;