paper over very bad queue behavior when recv(queue, 0) and recv(queue, 1) contend over the same queue by disabling the transmit proc for ethernet devices that would like to do their own receive. Reference: /n/atom/patch/applied2013/fsamd64ether Date: Tue Aug 27 23:23:45 CES 2013 Signed-off-by: quanstro@quanstro.net --- /sys/src/fs/amd64/ether82563.c Tue Aug 27 23:22:45 2013 +++ /sys/src/fs/amd64/ether82563.c Tue Aug 27 23:22:45 2013 @@ -926,7 +926,6 @@ td->control = Ide|Rs|Ifcs|Teop|BLEN(bp); ctlr->tb[tdt] = bp; tdt = Next(tdt, m); -extern void sfence(void); sfence(); csr32w(ctlr, Tdt, tdt); } @@ -1729,7 +1728,8 @@ */ edev->attach = i82563attach; edev->interrupt = i82563interrupt; - edev->transmit = i82563transmit; +// edev->transmit = i82563transmit; + edev->transmit = nil; // edev->arg = edev; --- /sys/src/fs/amd64/fns.h Tue Aug 27 23:22:45 2013 +++ /sys/src/fs/amd64/fns.h Tue Aug 27 23:22:45 2013 @@ -1,19 +1,10 @@ #include "../port/portfns.h" -/* junk */ -void waveprint(char*, ...); -void wave(int); -#pragma varargck argpos waveprint 1 - -void vunmap(void*, usize); -#define machcolor(m) -1 void acpiinit(int); - int adec(int*); int ainc(int*); void apmmuinit(void); int archmmu(void); -#define BIOSSEG(a) KADDR(((uint)(a))<<4) void cgaputc(int); void cgaputs(char*, int); void cmd_e820(int, char**); @@ -48,6 +39,7 @@ int kbdgetc(void); void kbdinit(void); int kbdintr0(void); +#define machcolor(m) -1 void mfence(void); void microdelay(int); void mmuinit(void); @@ -72,6 +64,7 @@ void puttr(u64int); u64int rdmsr(int); vlong rdtsc(void); +void sfence(void); void sipi(void); Mpl splhi(void); Mpl spllo(void); @@ -89,12 +82,16 @@ int vmapsync(uintptr); void* vmap(uintmem, usize); void vsvminit(int); +void vunmap(void*, usize); +void wave(int); +void waveprint(char*, ...); void wrmsr(int, vlong); +#define BIOSSEG(a) KADDR(((uint)(a))<<4) + +#pragma varargck argpos waveprint 1 #define PTR2UINT(p) ((uintptr)(p)) #define UINT2PTR(i) ((void*)(i)) - -//#define PCIWADDR(a) PADDR(a) /* pata */ void ideinit(Device*); --- /sys/src/fs/amd64/etherif.c Tue Aug 27 23:22:45 2013 +++ /sys/src/fs/amd64/etherif.c Tue Aug 27 23:22:45 2013 @@ -81,70 +81,6 @@ } } -#ifdef no -static void -ethero(void) -{ - Ether *ether; - Ifc *ifc; - Msgbuf *mb; - int len; - - ether = u->arg; - ifc = ðer->ifc; - print("ether%do: %E %I\n", ether->ctlrno, ifc->ea, ifc->ipa); - - for(;;) { - mb = recv(ifc->reply, 1); - if(mb == nil) - continue; - - len = mb->count; - if(len > ether->ifc.maxmtu){ - print("ether%do: pkt too big - %d\n", ether->ctlrno, len); - mbfree(mb); - continue; - } - if(len < ETHERMINTU) { - memset(mb->data+len, 0, ETHERMINTU-len); - mb->count = len = ETHERMINTU; - } - memmove(((Enpkt*)(mb->data))->s, ifc->ea, sizeof(ifc->ea)); - - ilock(ðer->tqlock); - if(ether->tqhead) - ether->tqtail->next = mb; - else - ether->tqhead = mb; - ether->tqtail = mb; - mb->next = 0; - iunlock(ðer->tqlock); - - ether->transmit(ether); - - ifc->work.count++; - ifc->rate.count += len; - ifc->txpkt++; - } -} - -Msgbuf* -etheroq(Ether* ether) -{ - Msgbuf *mb; - - mb = nil; - ilock(ðer->tqlock); - if(ether->tqhead){ - mb = ether->tqhead; - ether->tqhead = mb->next; - } - iunlock(ðer->tqlock); - - return mb; -} -#endif - /* * look, ma. no extra queue. */ @@ -155,6 +91,13 @@ e = u->arg; print("ether%do: %E %I\n", e->ctlrno, e->ifc.ea, e->ifc.ipa); + + /* should not be necessary; scheduling sucks */ + if(e->transmit == nil){ + static Rendez r[MaxEther]; + for(;;) + tsleep(r + e->ctlrno, no, 0, 10000); + } for(;;){ recv(e->ifc.reply, 0); // wait for something to do.