prevent rb ether from locking up due to queue full conditions Reference: /n/atom/patch/applied2013/rbetherhangup Date: Sat Sep 21 21:08:39 CES 2013 Signed-off-by: quanstro@quanstro.net --- /sys/src/9/rb/devether.c Sat Sep 21 21:08:39 2013 +++ /sys/src/9/rb/devether.c Sat Sep 21 21:08:39 2013 @@ -231,7 +231,7 @@ Dmatxunderrun = 1 << 1, Dmatxpktsent = 1 << 0, /* we don't really need most tx interrupts */ - Dmaall = Dmarxbuserr | Dmarxovflo | Dmarxpktrcvd | Dmatxbuserr, + Dmaall = Dmarxbuserr | /* Dmarxovflo |*/ Dmarxpktrcvd | Dmatxbuserr, Spictlremapdisable = 1 << 6, Spictlclkdividermask = MASK(6), @@ -702,7 +702,7 @@ Desc *rd; if (ctlr->rd[i] != nil) - return; + panic("rxnewbuf: overflow"); //return; ctlr->rd[i] = bp = athrballoc(); if(bp == nil) panic("#l%d: can't allocate receive buffer", @@ -741,12 +741,12 @@ arge = ctlr->regs; ilock(ctlr); sts = arge->dmaintrsts; - if (sts & Dmarxpktrcvd) { + if (sts & (Dmarxpktrcvd | Dmarxovflo)) { arge->dmaintr &= ~Dmarxpktrcvd; ctlr->pktstoread = 1; wakeup(&ctlr->rrendez); ctlr->rintr++; - sts &= ~Dmarxpktrcvd; + sts &= ~(Dmarxpktrcvd | Dmarxovflo); } if (sts & (Dmatxpktsent | Dmatxunderrun)) { arge->dmaintr &= ~(Dmatxpktsent | Dmatxunderrun); @@ -755,6 +755,7 @@ ctlr->tintr++; sts &= ~(Dmatxpktsent | Dmatxunderrun); } + iunlock(ctlr); if (sts) iprint("#l%d: sts %#ux\n", ether->ctlrno, sts); @@ -771,7 +772,7 @@ static void rproc(void* arg) { - uint rdh, sz; + uint rdh, sz, n; Arge *arge; Block *bp; Ctlr *ctlr; @@ -782,9 +783,12 @@ ctlr = edev->ctlr; arge = ctlr->regs; for(;;){ + rxreclaim(edev->ctlr); + /* wait for next interrupt */ ilock(ctlr); arge->dmaintr |= Dmarxpktrcvd; +arge->rxctl = Dmarxctlen; iunlock(ctlr); sleep(&ctlr->rrendez, pktstoread, ctlr); @@ -792,6 +796,7 @@ rxreclaim(ctlr); rdh = ctlr->rdh; + n = 0; for (rd = &ctlr->rdba[rdh]; !(rd->ctl & Descempty); rd = &ctlr->rdba[rdh]){ bp = ctlr->rd[rdh]; @@ -802,17 +807,17 @@ sz = DMASIZE(rd->ctl) - 4; assert(sz > 0 && sz <= Rbsz); bp->wp = bp->rp + sz; - bp = etheriq(edev, bp, 1); - assert(bp == nil); /* Block was consumed */ + etheriq(edev, bp, 1); arge->rxsts = Rxpktrcvd; ctlr->nrdfree--; rdh = NEXT(rdh, Nrd); - if(ctlr->nrdfree < Nrd/2) { + if(++n >= 8) { /* rxreclaim reads ctlr->rdh */ ctlr->rdh = rdh; rxreclaim(edev->ctlr); + n = 0; } } ctlr->rdh = rdh; @@ -842,12 +847,12 @@ ctlr = edev->ctlr; arge = ctlr->regs; for(;;){ + txreclaim(ctlr); + /* wait for next free buffer and output queue block */ sleep(&ctlr->trendez, pktstosend, edev); ctlr->pktstosend = 0; - txreclaim(ctlr); - /* copy as much of my output q as possible into output ring */ added = 0; tdt = ctlr->tdt; @@ -890,7 +895,6 @@ else if (ctlr->ntq > 0) arge->dmaintr |= Dmatxunderrun; iunlock(ctlr); - txreclaim(ctlr); } }