ether8169: sometimes transmits got missed. kicking the poll bit on each transmit fixes the problem
This commit is contained in:
parent
9a7e90d361
commit
962ec8cfb1
1 changed files with 13 additions and 18 deletions
|
@ -670,7 +670,7 @@ rtl8169init(Ether* edev)
|
||||||
* Transmitter.
|
* Transmitter.
|
||||||
*/
|
*/
|
||||||
memset(ctlr->td, 0, sizeof(D)*ctlr->ntd);
|
memset(ctlr->td, 0, sizeof(D)*ctlr->ntd);
|
||||||
ctlr->tdh = ctlr->tdt = 0;
|
ctlr->tdh = ctlr->tdt = ctlr->ntq = 0;
|
||||||
ctlr->td[ctlr->ntd-1].control = Eor;
|
ctlr->td[ctlr->ntd-1].control = Eor;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -759,12 +759,9 @@ rtl8169init(Ether* edev)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Interrupts.
|
* Interrupts.
|
||||||
* Disable Tdu|Tok for now, the transmit routine will tidy.
|
|
||||||
* Tdu means the NIC ran out of descriptors to send, so it
|
|
||||||
* doesn't really need to ever be on.
|
|
||||||
*/
|
*/
|
||||||
csr32w(ctlr, Timerint, 0);
|
csr32w(ctlr, Timerint, 0);
|
||||||
ctlr->imr = Serr|Timeout|Fovw|Punlc|Rdu|Ter|Rer|Rok;
|
ctlr->imr = Serr|Timeout|Fovw|Punlc|Rdu|Ter|Rer|Rok|Tdu;
|
||||||
csr16w(ctlr, Imr, ctlr->imr);
|
csr16w(ctlr, Imr, ctlr->imr);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -890,21 +887,16 @@ rtl8169transmit(Ether* edev)
|
||||||
D *d;
|
D *d;
|
||||||
Block *bp;
|
Block *bp;
|
||||||
Ctlr *ctlr;
|
Ctlr *ctlr;
|
||||||
int control, x;
|
int x;
|
||||||
|
|
||||||
ctlr = edev->ctlr;
|
ctlr = edev->ctlr;
|
||||||
|
|
||||||
ilock(&ctlr->tlock);
|
ilock(&ctlr->tlock);
|
||||||
for(x = ctlr->tdh; ctlr->ntq > 0; x = NEXT(x, ctlr->ntd)){
|
for(x = ctlr->tdh; ctlr->ntq > 0; x = NEXT(x, ctlr->ntd)){
|
||||||
d = &ctlr->td[x];
|
d = &ctlr->td[x];
|
||||||
if((control = d->control) & Own)
|
if(d->control & Own)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/*
|
|
||||||
* Check errors and log here.
|
|
||||||
*/
|
|
||||||
USED(control);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Free it up.
|
* Free it up.
|
||||||
* Need to clean the descriptor here? Not really.
|
* Need to clean the descriptor here? Not really.
|
||||||
|
@ -913,7 +905,6 @@ rtl8169transmit(Ether* edev)
|
||||||
*/
|
*/
|
||||||
freeb(ctlr->tb[x]);
|
freeb(ctlr->tb[x]);
|
||||||
ctlr->tb[x] = nil;
|
ctlr->tb[x] = nil;
|
||||||
d->control &= Eor;
|
|
||||||
|
|
||||||
ctlr->ntq--;
|
ctlr->ntq--;
|
||||||
}
|
}
|
||||||
|
@ -927,20 +918,23 @@ rtl8169transmit(Ether* edev)
|
||||||
d = &ctlr->td[x];
|
d = &ctlr->td[x];
|
||||||
d->addrlo = PCIWADDR(bp->rp);
|
d->addrlo = PCIWADDR(bp->rp);
|
||||||
d->addrhi = 0;
|
d->addrhi = 0;
|
||||||
ctlr->tb[x] = bp;
|
|
||||||
coherence();
|
coherence();
|
||||||
d->control |= Own | Fs | Ls | BLEN(bp);
|
ctlr->tb[x] = bp;
|
||||||
|
d->control = (d->control & Eor) | Own | Fs | Ls | BLEN(bp);
|
||||||
|
|
||||||
x = NEXT(x, ctlr->ntd);
|
x = NEXT(x, ctlr->ntd);
|
||||||
ctlr->ntq++;
|
ctlr->ntq++;
|
||||||
}
|
}
|
||||||
if(x != ctlr->tdt){
|
if(x != ctlr->tdt)
|
||||||
ctlr->tdt = x;
|
ctlr->tdt = x;
|
||||||
csr8w(ctlr, Tppoll, Npq);
|
|
||||||
}
|
|
||||||
else if(ctlr->ntq >= (ctlr->ntd-1))
|
else if(ctlr->ntq >= (ctlr->ntd-1))
|
||||||
ctlr->txdu++;
|
ctlr->txdu++;
|
||||||
|
|
||||||
|
if(ctlr->ntq > 0){
|
||||||
|
coherence();
|
||||||
|
csr8w(ctlr, Tppoll, Npq);
|
||||||
|
}
|
||||||
|
|
||||||
iunlock(&ctlr->tlock);
|
iunlock(&ctlr->tlock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1029,6 +1023,7 @@ rtl8169interrupt(Ureg*, void* arg)
|
||||||
csr16w(ctlr, Isr, isr);
|
csr16w(ctlr, Isr, isr);
|
||||||
if((isr & ctlr->imr) == 0)
|
if((isr & ctlr->imr) == 0)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if(isr & (Fovw|Punlc|Rdu|Rer|Rok)){
|
if(isr & (Fovw|Punlc|Rdu|Rer|Rok)){
|
||||||
rtl8169receive(edev);
|
rtl8169receive(edev);
|
||||||
if(!(isr & (Punlc|Rok)))
|
if(!(isr & (Punlc|Rok)))
|
||||||
|
|
Loading…
Reference in a new issue