ref: d80cdf26e535edc0ceaa6ee8b0d5df8e1f98b5a7
parent: 5d58d1f595274389d81ab4ef7f1e5840d372db19
author: cinap_lenrek <cinap_lenrek@centraldogma>
date: Tue Aug 30 13:19:22 EDT 2011
ether8169: reset on fifo overflow error
--- a/sys/src/9/pc/ether8169.c
+++ b/sys/src/9/pc/ether8169.c
@@ -260,6 +260,7 @@
QLock alock; /* attach */
Lock ilock; /* init */
int init; /* */
+ Rendez reset;
int pciv; /* */
int macv; /* MAC version */
@@ -306,7 +307,6 @@
uint rer;
uint rdu;
uint punlc;
- uint fovw;
uint mcast;
uint frag; /* partial packets; rb was too small */
} Ctlr;
@@ -556,7 +556,6 @@
l += snprint(p+l, READSTR-l, "rer: %ud\n", ctlr->rer);
l += snprint(p+l, READSTR-l, "rdu: %ud\n", ctlr->rdu);
l += snprint(p+l, READSTR-l, "punlc: %ud\n", ctlr->punlc);
- l += snprint(p+l, READSTR-l, "fovw: %ud\n", ctlr->fovw);
l += snprint(p+l, READSTR-l, "tcr: %#8.8ux\n", ctlr->tcr);
l += snprint(p+l, READSTR-l, "rcr: %#8.8ux\n", ctlr->rcr);
@@ -810,12 +809,33 @@
iunlock(&ctlr->ilock);
-// rtl8169mii(ctlr);
-
return 0;
}
static void
+rtl8169reseter(void *arg)
+{+ Ether *edev;
+ Ctlr *ctlr;
+
+ edev = arg;
+ ctlr = edev->ctlr;
+
+ for(;;){+ print("rtl8169: reset\n");+ rtl8169init(edev);
+ qunlock(&ctlr->alock);
+
+ while(waserror())
+ ;
+ sleep(&ctlr->reset, return0, nil);
+ poperror();
+
+ qlock(&ctlr->alock);
+ }
+}
+
+static void
rtl8169attach(Ether* edev)
{int timeo;
@@ -834,8 +854,10 @@
ctlr->rb = malloc(Nrd*sizeof(Block*));
ctlr->nrd = Nrd;
ctlr->dtcc = mallocalign(sizeof(Dtcc), 64, 0, 0);
- rtl8169init(edev);
ctlr->init = 1;
+
+ kproc("rtl8169", rtl8169reseter, edev);+ qlock(&ctlr->alock); /* reset proc unlocks when finished */
}
qunlock(&ctlr->alock);
@@ -1010,6 +1032,25 @@
}
static void
+rtl8169restart(Ctlr *ctlr)
+{+ ilock(&ctlr->ilock);
+
+ /* disable interrupts */
+ ctlr->imr = 0;
+ csr16w(ctlr, Imr, ctlr->imr);
+ csr16w(ctlr, Isr, 0xFFFF);
+
+ /* software reset */
+ csr8w(ctlr, Cr, Rst);
+ csr8r(ctlr, Cr);
+
+ wakeup(&ctlr->reset);
+
+ iunlock(&ctlr->ilock);
+}
+
+static void
rtl8169interrupt(Ureg*, void* arg)
{Ctlr *ctlr;
@@ -1024,7 +1065,12 @@
if((isr & ctlr->imr) == 0)
break;
- if(isr & (Fovw|Punlc|Rdu|Rer|Rok)){+ if(isr & Fovw){+ rtl8169restart(ctlr);
+ break;
+ }
+
+ if(isr & (Punlc|Rdu|Rer|Rok)){rtl8169receive(edev);
if(!(isr & (Punlc|Rok)))
ctlr->ierrs++;
@@ -1034,9 +1080,7 @@
ctlr->rdu++;
if(isr & Punlc)
ctlr->punlc++;
- if(isr & Fovw)
- ctlr->fovw++;
- isr &= ~(Fovw|Rdu|Rer|Rok);
+ isr &= ~(Rdu|Rer|Rok);
}
if(isr & (Tdu|Ter|Tok)){--
⑨