On Sun, Sep 11, 2016 at 01:24:23PM +0200, Mark Kettenis wrote: > Hardware has two transmit FIFOs, and the idea is to alternate between > the two. The code that decides which FIFO to use is busted. It keeps > a count of the number of FIFOs in use. That means that if the count > is one, we don't actually know which if the FIFOs is currently in use. > If we pick the wrong FIFO for the next packet, the interface hangs and > we get a watchdog timeout. > > Diff below fixes this by using a bitmask to keep track of the FIFOs > that are in use. > > ok?
I can't test it myself, but makes sense to me. ok mglocker > Index: arch/armv7/sunxi/sxie.c > =================================================================== > RCS file: /cvs/src/sys/arch/armv7/sunxi/sxie.c,v > retrieving revision 1.21 > diff -u -p -r1.21 sxie.c > --- arch/armv7/sunxi/sxie.c 22 Aug 2016 19:38:42 -0000 1.21 > +++ arch/armv7/sunxi/sxie.c 11 Sep 2016 11:18:24 -0000 > @@ -101,6 +101,9 @@ > #define SXIE_INTR_DISABLE 0x0000 > #define SXIE_INTR_CLEAR 0x0000 > > +#define SXIE_TX_FIFO0 0x0001 > +#define SXIE_TX_FIFO1 0x0002 > + > #define SXIE_RX_ENABLE 0x0004 > #define SXIE_TX_ENABLE 0x0003 > #define SXIE_RXTX_ENABLE 0x0007 > @@ -436,16 +439,13 @@ sxie_intr(void *arg) > sxie_recv(sc); > } > > - pending &= 3; > - > - if (pending) { > + if (pending & (SXIE_TX_FIFO0 | SXIE_TX_FIFO1)) { > ifq_clr_oactive(&ifp->if_snd); > - sc->txf_inuse--; > - ifp->if_opackets++; > - if (pending == 3) { /* 2 packets got sent */ > - sc->txf_inuse--; > + if (pending & SXIE_TX_FIFO0) > + ifp->if_opackets++; > + if (pending & SXIE_TX_FIFO1) > ifp->if_opackets++; > - } > + sc->txf_inuse &= ~pending; > if (sc->txf_inuse == 0) > ifp->if_timer = 0; > else > @@ -473,7 +473,7 @@ sxie_start(struct ifnet *ifp) > uint32_t fifo; > uint32_t txbuf[SXIE_MAX_PKT_SIZE / sizeof(uint32_t)]; /* XXX !!! */ > > - if (sc->txf_inuse > 1) > + if (sc->txf_inuse == (SXIE_TX_FIFO0 | SXIE_TX_FIFO1)) > ifq_set_oactive(&ifp->if_snd); > > if (!(ifp->if_flags & IFF_RUNNING) || ifq_is_oactive(&ifp->if_snd)) > @@ -494,7 +494,7 @@ trynext: > return; > } > > - if (sc->txf_inuse > 1) { > + if (sc->txf_inuse == (SXIE_TX_FIFO0 | SXIE_TX_FIFO1)) { > ifq_deq_rollback(&ifp->if_snd, m); > printf("sxie_start: tx fifos in use.\n"); > ifq_set_oactive(&ifp->if_snd); > @@ -502,10 +502,14 @@ trynext: > } > > /* select fifo */ > - fifo = sc->txf_inuse; > + if (sc->txf_inuse & SXIE_TX_FIFO0) { > + sc->txf_inuse |= SXIE_TX_FIFO1; > + fifo = 1; > + } else { > + sc->txf_inuse |= SXIE_TX_FIFO0; > + fifo = 0; > + } > SXIWRITE4(sc, SXIE_TXINS, fifo); > - > - sc->txf_inuse++; > > /* set packet length */ > SXIWRITE4(sc, SXIE_TXPKTLEN0 + (fifo * 4), m->m_pkthdr.len);