This commit is contained in:
cinap_lenrek 2020-11-21 22:04:15 +01:00
commit 59308f15dd
5 changed files with 130 additions and 97 deletions

View file

@ -383,16 +383,16 @@ rtl8169miimiw(Mii* mii, int pa, int ra, int data)
return 0; return 0;
} }
static int static void
rtl8169mii(Ctlr* ctlr) rtl8169mii(Ether *edev)
{ {
Ctlr *ctlr = edev->ctlr;
MiiPhy *phy; MiiPhy *phy;
/* /*
* Link management. * Link management.
*/ */
if((ctlr->mii = malloc(sizeof(Mii))) == nil) ctlr->mii = smalloc(sizeof(Mii));
return -1;
ctlr->mii->mir = rtl8169miimir; ctlr->mii->mir = rtl8169miimir;
ctlr->mii->miw = rtl8169miimiw; ctlr->mii->miw = rtl8169miimiw;
ctlr->mii->ctlr = ctlr; ctlr->mii->ctlr = ctlr;
@ -420,22 +420,20 @@ rtl8169mii(Ctlr* ctlr)
csr8w(ctlr, Ldps, 1); /* magic */ csr8w(ctlr, Ldps, 1); /* magic */
rtl8169miimiw(ctlr->mii, 1, 0x0B, 0x0000); /* magic */ rtl8169miimiw(ctlr->mii, 1, 0x0B, 0x0000); /* magic */
} }
if(mii(ctlr->mii, (1<<1)) == 0 || (phy = ctlr->mii->curphy) == nil){ if(mii(ctlr->mii, (1<<1)) == 0 || (phy = ctlr->mii->curphy) == nil){
free(ctlr->mii); error("no phy");
ctlr->mii = nil; return;
return -1;
} }
print("rtl8169: oui %#ux phyno %d, macv = %#8.8ux phyv = %#4.4ux\n",
phy->oui, phy->phyno, ctlr->macv, ctlr->phyv); print("#l%d: rtl8169: oui %#ux phyno %d, macv = %#8.8ux phyv = %#4.4ux\n",
edev->ctlrno, phy->oui, phy->phyno, ctlr->macv, ctlr->phyv);
miireset(ctlr->mii); miireset(ctlr->mii);
microdelay(100); microdelay(100);
miiane(ctlr->mii, ~0, ~0, ~0); miiane(ctlr->mii, ~0, ~0, ~0);
return 0;
} }
static void static void
@ -615,6 +613,8 @@ static void
rtl8169halt(Ctlr* ctlr) rtl8169halt(Ctlr* ctlr)
{ {
csr8w(ctlr, Cr, 0); csr8w(ctlr, Cr, 0);
ctlr->imr = 0;
csr16w(ctlr, Imr, 0); csr16w(ctlr, Imr, 0);
csr16w(ctlr, Isr, ~0); csr16w(ctlr, Isr, ~0);
} }
@ -648,6 +648,7 @@ rtl8169replenish(Ctlr* ctlr)
D *d; D *d;
int x; int x;
Block *bp; Block *bp;
u64int pa;
x = ctlr->rdt; x = ctlr->rdt;
while(NEXT(x, ctlr->nrd) != ctlr->rdh){ while(NEXT(x, ctlr->nrd) != ctlr->rdh){
@ -658,9 +659,10 @@ rtl8169replenish(Ctlr* ctlr)
} }
ctlr->rb[x] = bp; ctlr->rb[x] = bp;
ctlr->nrq++; ctlr->nrq++;
pa = PCIWADDR(bp->rp);
d = &ctlr->rd[x]; d = &ctlr->rd[x];
d->addrlo = PCIWADDR(bp->rp); d->addrlo = pa;
d->addrhi = 0; d->addrhi = pa >> 32;
coherence(); coherence();
d->control = (d->control & Eor) | Own | BALLOC(bp); d->control = (d->control & Eor) | Own | BALLOC(bp);
x = NEXT(x, ctlr->nrd); x = NEXT(x, ctlr->nrd);
@ -668,19 +670,22 @@ rtl8169replenish(Ctlr* ctlr)
} }
} }
static int static void
rtl8169init(Ether* edev) rtl8169init(Ether* edev)
{ {
int i; int i;
u32int r; u32int r;
Block *bp; Block *bp;
Ctlr *ctlr; Ctlr *ctlr;
u64int pa;
u16int cplusc; u16int cplusc;
ctlr = edev->ctlr; ctlr = edev->ctlr;
ilock(ctlr); ilock(ctlr);
if(rtl8169reset(ctlr) < 0){
rtl8169reset(ctlr); iunlock(ctlr);
error("reset failed");
}
memset(ctlr->td, 0, sizeof(D)*ctlr->ntd); memset(ctlr->td, 0, sizeof(D)*ctlr->ntd);
ctlr->tdh = ctlr->tdt = ctlr->ntq = 0; ctlr->tdh = ctlr->tdt = ctlr->ntq = 0;
@ -716,10 +721,13 @@ rtl8169init(Ether* edev)
} }
csr16w(ctlr, Cplusc, cplusc); csr16w(ctlr, Cplusc, cplusc);
csr32w(ctlr, Tnpds+4, 0); pa = PCIWADDR(ctlr->td);
csr32w(ctlr, Tnpds, PCIWADDR(ctlr->td)); csr32w(ctlr, Tnpds+4, pa>>32);
csr32w(ctlr, Rdsar+4, 0); csr32w(ctlr, Tnpds, pa);
csr32w(ctlr, Rdsar, PCIWADDR(ctlr->rd));
pa = PCIWADDR(ctlr->rd);
csr32w(ctlr, Rdsar+4, pa>>32);
csr32w(ctlr, Rdsar, pa);
csr8w(ctlr, Cr, Te|Re); csr8w(ctlr, Cr, Te|Re);
@ -755,8 +763,6 @@ rtl8169init(Ether* edev)
csr32w(ctlr, Mpc, 0); csr32w(ctlr, Mpc, 0);
iunlock(ctlr); iunlock(ctlr);
return 0;
} }
static void static void
@ -766,69 +772,80 @@ rtl8169reseter(void *arg)
Ctlr *ctlr; Ctlr *ctlr;
edev = arg; edev = arg;
while(waserror())
;
for(;;){ for(;;){
rtl8169init(edev);
ctlr = edev->ctlr; ctlr = edev->ctlr;
qunlock(&ctlr->alock);
while(waserror())
;
sleep(&ctlr->reset, return0, nil); sleep(&ctlr->reset, return0, nil);
poperror(); rtl8169init(edev);
qlock(&ctlr->alock);
} }
} }
static void rtl8169interrupt(Ureg*, void* arg);
static void static void
rtl8169attach(Ether* edev) rtl8169attach(Ether* edev)
{ {
int timeo;
Ctlr *ctlr; Ctlr *ctlr;
ctlr = edev->ctlr; ctlr = edev->ctlr;
qlock(&ctlr->alock); qlock(&ctlr->alock);
if(!ctlr->init){ if(ctlr->init){
ctlr->ntd = Ntd; qunlock(&ctlr->alock);
ctlr->nrd = Nrd; return;
ctlr->tb = malloc(ctlr->ntd*sizeof(Block*));
ctlr->rb = malloc(ctlr->nrd*sizeof(Block*));
ctlr->td = mallocalign(sizeof(D)*ctlr->ntd, 256, 0, 0);
ctlr->rd = mallocalign(sizeof(D)*ctlr->nrd, 256, 0, 0);
ctlr->dtcc = mallocalign(sizeof(Dtcc), 64, 0, 0);
if(ctlr->rb == nil || ctlr->rb == nil ||
ctlr->rd == nil || ctlr->rd == nil || ctlr->dtcc == nil){
free(ctlr->tb);
ctlr->tb = nil;
free(ctlr->rb);
ctlr->rb = nil;
free(ctlr->td);
ctlr->td = nil;
free(ctlr->rd);
ctlr->rd = nil;
free(ctlr->dtcc);
ctlr->dtcc = nil;
qunlock(&ctlr->alock);
error(Enomem);
}
ctlr->init = 1;
kproc("rtl8169", rtl8169reseter, edev);
/* rtl8169reseter() does qunlock(&ctlr->alock) when complete */
qlock(&ctlr->alock);
} }
if(waserror()){
print("#l%d: rtl8169: %s\n", edev->ctlrno, up->errstr);
qunlock(&ctlr->alock);
nexterror();
}
ctlr->ntd = Ntd;
ctlr->nrd = Nrd;
ctlr->tb = malloc(ctlr->ntd*sizeof(Block*));
ctlr->rb = malloc(ctlr->nrd*sizeof(Block*));
ctlr->td = mallocalign(sizeof(D)*ctlr->ntd, 256, 0, 0);
ctlr->rd = mallocalign(sizeof(D)*ctlr->nrd, 256, 0, 0);
ctlr->dtcc = mallocalign(sizeof(Dtcc), 64, 0, 0);
if(waserror()){
free(ctlr->tb);
ctlr->tb = nil;
free(ctlr->rb);
ctlr->rb = nil;
free(ctlr->td);
ctlr->td = nil;
free(ctlr->rd);
ctlr->rd = nil;
free(ctlr->dtcc);
ctlr->dtcc = nil;
nexterror();
}
if(ctlr->tb == nil || ctlr->rb == nil
|| ctlr->td == nil || ctlr->rd == nil
|| ctlr->dtcc == nil)
error(Enomem);
pcisetbme(ctlr->pcidev);
intrenable(edev->irq, rtl8169interrupt, edev, edev->tbdf, edev->name);
if(waserror()){
rtl8169halt(ctlr);
pciclrbme(ctlr->pcidev);
intrdisable(edev->irq, rtl8169interrupt, edev, edev->tbdf, edev->name);
nexterror();
}
rtl8169init(edev);
rtl8169mii(edev);
ctlr->init = 1;
poperror();
poperror();
kproc("rtl8169", rtl8169reseter, edev);
qunlock(&ctlr->alock); qunlock(&ctlr->alock);
poperror();
/*
* Wait for link to be ready.
*/
for(timeo = 0; timeo < 35; timeo++){
if(miistatus(ctlr->mii) == 0)
break;
delay(100); /* print fewer miistatus messages */
}
} }
static void static void
@ -866,6 +883,7 @@ rtl8169transmit(Ether* edev)
D *d; D *d;
Block *bp; Block *bp;
Ctlr *ctlr; Ctlr *ctlr;
u64int pa;
int x; int x;
ctlr = edev->ctlr; ctlr = edev->ctlr;
@ -894,9 +912,10 @@ rtl8169transmit(Ether* edev)
if((bp = qget(edev->oq)) == nil) if((bp = qget(edev->oq)) == nil)
break; break;
pa = PCIWADDR(bp->rp);
d = &ctlr->td[x]; d = &ctlr->td[x];
d->addrlo = PCIWADDR(bp->rp); d->addrlo = pa;
d->addrhi = 0; d->addrhi = pa >> 32;
coherence(); coherence();
d->control = (d->control & Eor) | Own | Fs | Ls | BLEN(bp); d->control = (d->control & Eor) | Own | Fs | Ls | BLEN(bp);
@ -990,7 +1009,6 @@ rtl8169receive(Ether* edev)
static void static void
rtl8169restart(Ctlr *ctlr) rtl8169restart(Ctlr *ctlr)
{ {
ctlr->imr = 0;
rtl8169halt(ctlr); rtl8169halt(ctlr);
wakeup(&ctlr->reset); wakeup(&ctlr->reset);
} }
@ -1037,6 +1055,14 @@ rtl8169interrupt(Ureg*, void* arg)
} }
} }
static void
rtl8169shutdown(Ether *edev)
{
Ctlr *ctlr = edev->ctlr;
rtl8169halt(ctlr);
}
int int
vetmacv(Ctlr *ctlr, uint *macv) vetmacv(Ctlr *ctlr, uint *macv)
{ {
@ -1103,11 +1129,14 @@ rtl8169pci(void)
break; break;
} }
if(p->mem[0].size == 0 || (p->mem[0].bar & 1) == 0)
continue;
port = p->mem[0].bar & ~3; port = p->mem[0].bar & ~3;
if(ioalloc(port, p->mem[0].size, 0, "rtl8169") < 0){ if(ioalloc(port, p->mem[0].size, 0, "rtl8169") < 0){
print("rtl8169: port %#ux in use\n", port); print("rtl8169: port %#ux in use\n", port);
continue; continue;
} }
ctlr = malloc(sizeof(Ctlr)); ctlr = malloc(sizeof(Ctlr));
if(ctlr == nil){ if(ctlr == nil){
print("rtl8169: can't allocate memory\n"); print("rtl8169: can't allocate memory\n");
@ -1121,31 +1150,19 @@ rtl8169pci(void)
pcienable(p); pcienable(p);
if(vetmacv(ctlr, &macv) == -1){ if(vetmacv(ctlr, &macv) == -1){
print("rtl8169: %T: unknown mac %.4ux %.8ux\n", p->tbdf, p->did, macv);
pcidisable(p); pcidisable(p);
iofree(port); iofree(port);
free(ctlr); free(ctlr);
print("rtl8169: unknown mac %.4ux %.8ux\n", p->did, macv);
continue;
}
if(rtl8169reset(ctlr)){
pcidisable(p);
iofree(port);
free(ctlr);
print("rtl8169: reset failed\n");
continue; continue;
} }
rtl8169halt(ctlr);
/* /*
* Extract the chip hardware version, * Extract the chip hardware version,
* needed to configure each properly. * needed to configure each properly.
*/ */
ctlr->macv = macv; ctlr->macv = macv;
rtl8169mii(ctlr);
pcisetbme(p);
if(rtl8169ctlrhead != nil) if(rtl8169ctlrhead != nil)
rtl8169ctlrtail->next = ctlr; rtl8169ctlrtail->next = ctlr;
else else
@ -1208,6 +1225,7 @@ rtl8169pnp(Ether* edev)
edev->attach = rtl8169attach; edev->attach = rtl8169attach;
edev->transmit = rtl8169transmit; edev->transmit = rtl8169transmit;
edev->ifstat = rtl8169ifstat; edev->ifstat = rtl8169ifstat;
edev->shutdown = rtl8169shutdown;
edev->arg = edev; edev->arg = edev;
edev->promiscuous = rtl8169promiscuous; edev->promiscuous = rtl8169promiscuous;
@ -1215,8 +1233,6 @@ rtl8169pnp(Ether* edev)
rtl8169link(edev); rtl8169link(edev);
intrenable(edev->irq, rtl8169interrupt, edev, edev->tbdf, edev->name);
return 0; return 0;
} }

View file

@ -48,15 +48,19 @@ enum {
typedef struct Vctl { typedef struct Vctl {
Vctl* next; /* handlers on this vector */ Vctl* next; /* handlers on this vector */
char name[KNAMELEN]; /* of driver */ void (*f)(Ureg*, void*); /* handler to call */
void* a; /* argument to call it with */
int isintr; /* interrupt or fault/trap */ int isintr; /* interrupt or fault/trap */
int irq;
int tbdf;
int (*isr)(int); /* get isr bit for this irq */ int (*isr)(int); /* get isr bit for this irq */
int (*eoi)(int); /* eoi */ int (*eoi)(int); /* eoi */
void (*f)(Ureg*, void*); /* handler to call */ void (*disable)(Vctl*);
void* a; /* argument to call it with */ int irq;
int tbdf;
char name[KNAMELEN]; /* of driver */
} Vctl; } Vctl;
enum { enum {

View file

@ -469,6 +469,15 @@ htmsienable(Pcidev *pdev)
return -1; return -1;
} }
static void
msiintrdisable(Vctl *v)
{
Pcidev *pci;
if((pci = pcimatchtbdf(v->tbdf)) != nil)
pcimsidisable(pci);
}
static int static int
msiintrenable(Vctl *v) msiintrenable(Vctl *v)
{ {
@ -493,6 +502,7 @@ msiintrenable(Vctl *v)
cpu = mpintrcpu(); cpu = mpintrcpu();
if(pcimsienable(pci, 0xFEE00000ULL | (cpu << 12), vno | (1<<14)) < 0) if(pcimsienable(pci, 0xFEE00000ULL | (cpu << 12), vno | (1<<14)) < 0)
return -1; return -1;
v->disable = msiintrdisable;
v->isr = lapicisr; v->isr = lapicisr;
v->eoi = lapiceoi; v->eoi = lapiceoi;
return vno; return vno;

View file

@ -89,8 +89,7 @@ intrdisable(int irq, void (*f)(Ureg *, void *), void *a, int tbdf, char *name)
irq = 9; irq = 9;
if(arch->intrvecno == nil || (tbdf != BUSUNKNOWN && (irq == 0xff || irq == 0))){ if(arch->intrvecno == nil || (tbdf != BUSUNKNOWN && (irq == 0xff || irq == 0))){
/* /*
* on APIC machine, irq is pretty meaningless * on APIC machine, irq is pretty meaningless.
* and disabling a the vector is not implemented.
* however, we still want to remove the matching * however, we still want to remove the matching
* Vctl entry to prevent calling Vctl.f() with a * Vctl entry to prevent calling Vctl.f() with a
* stale Vctl.a pointer. * stale Vctl.a pointer.
@ -109,6 +108,8 @@ intrdisable(int irq, void (*f)(Ureg *, void *), void *a, int tbdf, char *name)
break; break;
} }
if(v != nil){ if(v != nil){
if(v->disable != nil)
(*v->disable)(v);
*pv = v->next; *pv = v->next;
xfree(v); xfree(v);

View file

@ -111,6 +111,8 @@ intrdisable(int irq, void (*f)(Ureg *, void *), void *a, int tbdf, char *name)
break; break;
} }
if(v != nil){ if(v != nil){
if(v->disable != nil)
(*v->disable)(v);
*pv = v->next; *pv = v->next;
xfree(v); xfree(v);