ether8169: sometimes transmits got missed. kicking the poll bit on each transmit fixes the problem

This commit is contained in:
cinap_lenrek 2011-08-30 09:08:55 +02:00
parent 9a7e90d361
commit 962ec8cfb1

View file

@ -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)))