etherseeq: reset the card when it gets stuck (dma timeouts)
This commit is contained in:
parent
eff2a40c16
commit
2c9b1c6b53
1 changed files with 77 additions and 26 deletions
|
@ -133,14 +133,16 @@ enum {
|
|||
struct Ctlr
|
||||
{
|
||||
int attach;
|
||||
char* txerr;
|
||||
ulong txwdog;
|
||||
|
||||
Hio *io;
|
||||
Hio* io;
|
||||
|
||||
Ring rx;
|
||||
Ring tx;
|
||||
};
|
||||
|
||||
static ulong dummy;
|
||||
static int reset(Ether*);
|
||||
|
||||
static void
|
||||
txintr(Ctlr *ctlr)
|
||||
|
@ -153,17 +155,21 @@ txintr(Ctlr *ctlr)
|
|||
s = io->xstat;
|
||||
if((s & Xdma) != 0)
|
||||
return;
|
||||
p = IO(Desc, ctlr->tx.head->next);
|
||||
while((p->count & Busy) != 0){
|
||||
if((s & Xmaxtry) != 0)
|
||||
ctlr->txerr = "transmission failed";
|
||||
if((s & Xunder) != 0)
|
||||
ctlr->txerr = "transmitter underflowed";
|
||||
for(p = IO(Desc, ctlr->tx.head->next); (p->count & Busy) != 0; p = IO(Desc, p->next)){
|
||||
if((p->count & Done) == 0){
|
||||
io->nxbdp = PADDR(p);
|
||||
io->xstat = Xdma;
|
||||
ctlr->txwdog = MACHP(0)->ticks;
|
||||
break;
|
||||
}
|
||||
ctlr->tx.head = p;
|
||||
p->count = Eor|Eop;
|
||||
p = IO(Desc, p->next);
|
||||
ctlr->tx.head = p;
|
||||
ctlr->tx.free++;
|
||||
ctlr->txwdog = 0;
|
||||
}
|
||||
wakeup(&ctlr->tx);
|
||||
}
|
||||
|
@ -180,8 +186,10 @@ interrupt(Ureg *, void *arg)
|
|||
ctlr = edev->ctlr;
|
||||
io = ctlr->io;
|
||||
s = io->ctl;
|
||||
if(s & Cover)
|
||||
if(s & Cover){
|
||||
io->ctl = Cnormal | Cover;
|
||||
edev->overflows++;
|
||||
}
|
||||
if(s & Cint) {
|
||||
io->ctl = Cnormal | Cint;
|
||||
txintr(ctlr);
|
||||
|
@ -193,14 +201,31 @@ static int
|
|||
notempty(void *arg)
|
||||
{
|
||||
Ctlr *ctlr = arg;
|
||||
|
||||
return (IO(Desc, ctlr->rx.head->next)->count & Empty) == 0;
|
||||
}
|
||||
|
||||
static char*
|
||||
checkerr(Ctlr *ctlr)
|
||||
{
|
||||
ulong t;
|
||||
|
||||
if(ctlr->txerr != nil)
|
||||
return ctlr->txerr;
|
||||
t = ctlr->txwdog;
|
||||
if(t != 0 && TK2MS(MACHP(0)->ticks - t) > 1000)
|
||||
return "transmitter dma timeout";
|
||||
if((ctlr->io->rstat & Rdma) == 0)
|
||||
return "recevier dma stopped";
|
||||
return nil;
|
||||
}
|
||||
|
||||
static void
|
||||
rxproc(void *arg)
|
||||
{
|
||||
Ether *edev = arg;
|
||||
Ctlr *ctlr;
|
||||
char *err;
|
||||
Block *b;
|
||||
Desc *p;
|
||||
int n;
|
||||
|
@ -210,16 +235,22 @@ rxproc(void *arg)
|
|||
|
||||
ctlr = edev->ctlr;
|
||||
for(p = IO(Desc, ctlr->rx.head->next);; p = IO(Desc, p->next)){
|
||||
while((p->count & Empty) != 0)
|
||||
sleep(&ctlr->rx, notempty, ctlr);
|
||||
n = Rbsize - (p->count & 0x3fff)-3;
|
||||
if(n >= ETHERMINTU){
|
||||
if((p->base[n+2] & Rok) != 0){
|
||||
b = allocb(n);
|
||||
b->wp += n;
|
||||
memmove(b->rp, p->base+2, n);
|
||||
etheriq(edev, b, 1);
|
||||
while((p->count & Empty) != 0){
|
||||
err = checkerr(ctlr);
|
||||
if(err != nil){
|
||||
print("%s: %s; reseting\n", up->text, err);
|
||||
splhi();
|
||||
reset(edev);
|
||||
spllo();
|
||||
}
|
||||
tsleep(&ctlr->rx, notempty, ctlr, 500);
|
||||
}
|
||||
n = Rbsize - (p->count & 0x3fff)-3;
|
||||
if(n >= ETHERMINTU && (p->base[n+2] & Rok) != 0){
|
||||
b = allocb(n);
|
||||
b->wp += n;
|
||||
memmove(b->rp, p->base+2, n);
|
||||
etheriq(edev, b, 1);
|
||||
}
|
||||
p->addr = PADDR(p->base);
|
||||
p->count = Ioc|Empty|Rbsize;
|
||||
|
@ -250,7 +281,6 @@ txproc(void *arg)
|
|||
for(p = IO(Desc, ctlr->tx.tail->next); (b = qbread(edev->oq, 1000000)) != nil; p = IO(Desc, p->next)){
|
||||
while(ctlr->tx.free == 0)
|
||||
sleep(&ctlr->tx, notbusy, ctlr);
|
||||
ctlr->tx.free--;
|
||||
|
||||
n = BLEN(b);
|
||||
if(n > ETHERMAXTU)
|
||||
|
@ -264,6 +294,7 @@ txproc(void *arg)
|
|||
ctlr->tx.tail = p;
|
||||
|
||||
splhi();
|
||||
ctlr->tx.free--;
|
||||
txintr(ctlr);
|
||||
spllo();
|
||||
|
||||
|
@ -303,21 +334,20 @@ allocring(Ring *r, int n)
|
|||
}
|
||||
|
||||
static int
|
||||
init(Ether *edev)
|
||||
reset(Ether *edev)
|
||||
{
|
||||
Ctlr *ctlr;
|
||||
Desc *p;
|
||||
Hio *io;
|
||||
int i;
|
||||
|
||||
io = IO(Hio, edev->port);
|
||||
ctlr = edev->ctlr;
|
||||
ctlr->io = io;
|
||||
io = ctlr->io;
|
||||
|
||||
ctlr->txerr = nil;
|
||||
ctlr->txwdog = 0;
|
||||
|
||||
io->csx = Xreg0;
|
||||
allocring(&ctlr->rx, 256);
|
||||
allocring(&ctlr->tx, 64);
|
||||
|
||||
io->rstat = 0;
|
||||
io->xstat = 0;
|
||||
io->ctl = Cnormal | Creset | Cint;
|
||||
|
@ -336,15 +366,19 @@ init(Ether *edev)
|
|||
} while(p != ctlr->rx.head);
|
||||
io->crbdp = PADDR(p);
|
||||
io->nrbdp = p->next;
|
||||
ctlr->rx.tail = p;
|
||||
ctlr->rx.free = ctlr->rx.size;
|
||||
|
||||
p = ctlr->tx.tail;
|
||||
do {
|
||||
p->addr = 0;
|
||||
p->addr = PADDR(p->base);
|
||||
p->count = Eor|Eop;
|
||||
p = IO(Desc, p->next);
|
||||
} while(p != ctlr->tx.tail);
|
||||
io->cxbdp = PADDR(p);
|
||||
io->nxbdp = p->next;
|
||||
ctlr->tx.head = p;
|
||||
ctlr->tx.free = ctlr->tx.size;
|
||||
|
||||
for(i=0; i<6; i++)
|
||||
io->eaddr[i] = edev->ea[i];
|
||||
|
@ -354,7 +388,24 @@ init(Ether *edev)
|
|||
|
||||
io->rstat = Rdma;
|
||||
|
||||
wakeup(&ctlr->rx);
|
||||
wakeup(&ctlr->tx);
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
static int
|
||||
init(Ether *edev)
|
||||
{
|
||||
Ctlr *ctlr;
|
||||
|
||||
ctlr = edev->ctlr;
|
||||
ctlr->io = IO(Hio, edev->port);
|
||||
allocring(&ctlr->rx, 256);
|
||||
allocring(&ctlr->tx, 64);
|
||||
|
||||
return reset(edev);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -379,8 +430,8 @@ attach(Ether *edev)
|
|||
if(ctlr->attach)
|
||||
return;
|
||||
ctlr->attach = 1;
|
||||
kproc("#0rx", rxproc, edev);
|
||||
kproc("#0tx", txproc, edev);
|
||||
kproc("#l0rx", rxproc, edev);
|
||||
kproc("#l0tx", txproc, edev);
|
||||
}
|
||||
|
||||
static int
|
||||
|
|
Loading…
Reference in a new issue