enable msi-x, and clean up interrupt locking. since wakeup/register reads should be slow in comparison to locking, take the imlock twice if necessary. it will usually be necessary due to the link interrupt, but measurements show latency to be about 5000 cycles lower (20%) for maximum bandwidth tcp transmit. Reference: /n/atom/patch/applied/82563msix Date: Sun Sep 6 20:41:35 CES 2015 Signed-off-by: quanstro@quanstro.net --- /sys/src/nix/k10/ether82563.c Sun Sep 6 20:37:59 2015 +++ /sys/src/nix/k10/ether82563.c Sun Sep 6 20:38:01 2015 @@ -554,8 +554,6 @@ int radv; /* receive interrupt absolute delay timer */ Rendez trendez; - QLock tlock; - int tbusy; Td *tdba; /* transmit descriptor base address */ Block **tb; /* transmit buffers */ int tdh; /* transmit descriptor head */ @@ -1595,10 +1593,11 @@ ctlr = edev->ctlr; ilock(&ctlr->imlock); - csr32w(ctlr, Imc, ~0); im = ctlr->im; + ctlr->im = 0; + iunlock(&ctlr->imlock); - while(icr = csr32r(ctlr, Icr) & ctlr->im){ + if(icr = csr32r(ctlr, Icr) & im){ if(icr & (Lsc | Omed)){ im &= ~(Lsc | Omed); ctlr->lim = icr & (Lsc | Omed); @@ -1613,14 +1612,17 @@ } if(icr & Txdw){ im &= ~Txdw; - ctlr->tintr++; wakeup(&ctlr->trendez); + ctlr->tintr++; } } - ctlr->im = im; - csr32w(ctlr, Ims, im); - iunlock(&ctlr->imlock); + if(im){ + ilock(&ctlr->imlock); + ctlr->im |= im; + csr32w(ctlr, Ims, ctlr->im); + iunlock(&ctlr->imlock); + } } static int @@ -1853,6 +1855,8 @@ csr32w(ctlr, Fcrth, ctlr->fcrth); if(cttab[ctlr->type].flag & F75) csr32w(ctlr, Eitr, 128<<2); /* 128 ΒΌ microsecond intervals */ + csr32w(ctlr, Ctrlext, csr32r(ctlr, Ctrlext) | Iame); + csr32w(ctlr, Iam, Lsc|Omed|Rxt0|Rxo|Rxdmt0|Rxseq|Ack|Txdw); return 0; } @@ -2079,6 +2083,7 @@ } pcisetbme(p); if(i82563reset(ctlr)){ + pciclrbme(ctlr->pcidev); vunmap(ctlr->nic, p->mem[0].size); return -1; } @@ -2089,6 +2094,7 @@ pnp(Ether *edev, int type) { Ctlr *ctlr; + Vctl *v; static int done; if(!done) { @@ -2114,6 +2120,16 @@ break; } } + + v = malloc(sizeof(Vctl)); + vctlinit(v); + v->irq = ctlr->pcidev->intl; + v->f = i82563interrupt; + v->tbdf = ctlr->pcidev->tbdf; + v->a = edev; + if(ctlr->type == i210) + v->flag |= Vmsix; + edev->vector = v; edev->ctlr = ctlr; edev->port = ctlr->port;