mirror of
git://git.9front.org/plan9front/plan9front
synced 2025-01-12 11:10:06 +00:00
usbxhci: preserve RsvdP bits in registers, print recovery reason, print base address.
Preserve reserved "RsvdP" bits in registers according to 2019 xhci specification 1.2. Print the USBSTS register and event-ring stopped flag on recovery. Add the controller base address in prints, so it can be identified what errors belong to what controller.
This commit is contained in:
parent
d38dbf6415
commit
f86cc3e912
1 changed files with 43 additions and 25 deletions
|
@ -43,6 +43,7 @@ enum {
|
||||||
CRS = 1<<9, /* Controller Restore State - RW */
|
CRS = 1<<9, /* Controller Restore State - RW */
|
||||||
EWE = 1<<10, /* Enable Wrap Event - RW */
|
EWE = 1<<10, /* Enable Wrap Event - RW */
|
||||||
EU3S = 1<<11, /* Enable U3 MFINDEX Stop - RW */
|
EU3S = 1<<11, /* Enable U3 MFINDEX Stop - RW */
|
||||||
|
USBCMD_PRES =0xfffff030,/* Reserved - RsvdP */
|
||||||
|
|
||||||
USBSTS = 0x04/4, /* USB Status Register */
|
USBSTS = 0x04/4, /* USB Status Register */
|
||||||
HCH = 1<<0, /* HCHalted - RO */
|
HCH = 1<<0, /* HCHalted - RO */
|
||||||
|
@ -54,22 +55,24 @@ enum {
|
||||||
SRE = 1<<10, /* Save/Restore Error - RW1C */
|
SRE = 1<<10, /* Save/Restore Error - RW1C */
|
||||||
CNR = 1<<11, /* Controller Not Ready - RO */
|
CNR = 1<<11, /* Controller Not Ready - RO */
|
||||||
HCE = 1<<12, /* Host Controller Error - RO */
|
HCE = 1<<12, /* Host Controller Error - RO */
|
||||||
|
USBSTS_PRES =0xffffe002,/* Reserved - RsvdP */
|
||||||
|
|
||||||
PAGESIZE = 0x08/4, /* Page Size - RO */
|
PAGESIZE = 0x08/4, /* Page Size - RO */
|
||||||
|
|
||||||
DNCTRL = 0x14/4, /* Device Notification Control Register - RW */
|
DNCTRL = 0x14/4, /* Device Notification Control Register - RW */
|
||||||
|
DNCTL_PRES =0xffff0000, /* Reserved - RsvdP */
|
||||||
|
|
||||||
CRCR = 0x18/4, /* Command Ring Control Register - RW */
|
CRCR = 0x18/4, /* Command Ring Control Register - RW */
|
||||||
RCS = 1<<0, /* Ring Cycle State - RW */
|
RCS = 1<<0, /* Ring Cycle State - RW */
|
||||||
CS = 1<<1, /* Command Stop - RW1S */
|
CS = 1<<1, /* Command Stop - RW1S */
|
||||||
CA = 1<<2, /* Command Abort - RW1S */
|
CA = 1<<2, /* Command Abort - RW1S */
|
||||||
CRR = 1<<3, /* Command Ring Running - RO */
|
CRR = 1<<3, /* Command Ring Running - RO */
|
||||||
|
CRCR_PRES = 3<<4, /* Reserved - RsvdP */
|
||||||
|
|
||||||
DCBAAP = 0x30/4, // 8
|
DCBAAP = 0x30/4, /* 64-bit */
|
||||||
|
|
||||||
CONFIG = 0x38/4, /* Configure Register (MaxSlotEn[7:0]) */
|
CONFIG = 0x38/4, /* Configure Register (MaxSlotEn[7:0]) */
|
||||||
U3E = 1<<8,
|
CONFIG_PRES =0xffffff00,/* Reserved - RsvdP */
|
||||||
CIE = 1<<9,
|
|
||||||
|
|
||||||
/* Port Register Set */
|
/* Port Register Set */
|
||||||
PORTSC = 0x00/4, /* Port status and Control Register */
|
PORTSC = 0x00/4, /* Port status and Control Register */
|
||||||
|
@ -105,10 +108,16 @@ enum {
|
||||||
|
|
||||||
/* Interrupter Registers */
|
/* Interrupter Registers */
|
||||||
IMAN = 0x00/4, /* Interrupter Management */
|
IMAN = 0x00/4, /* Interrupter Management */
|
||||||
|
IP = 1<<0, /* Interrupt pending - RW1C */
|
||||||
|
IE = 1<<1, /* interrupt enable - RW */
|
||||||
|
IMAN_PRES = 0xfffffffc, /* Reserved - RsvdP */
|
||||||
IMOD = 0x04/4, /* Interrupter Moderation */
|
IMOD = 0x04/4, /* Interrupter Moderation */
|
||||||
ERSTSZ = 0x08/4, /* Event Ring Segment Table Size */
|
ERSTSZ = 0x08/4, /* Event Ring Segment Table Size */
|
||||||
|
ERSTSZ_PRES =0xffff0000,/* Reserved - RsvdP */
|
||||||
ERSTBA = 0x10/4, /* Event Ring Segment Table Base Address */
|
ERSTBA = 0x10/4, /* Event Ring Segment Table Base Address */
|
||||||
|
ERSTBA_PRES =0x3f, /* Reserved - RsvdP */
|
||||||
ERDP = 0x18/4, /* Event Ring Dequeue Pointer */
|
ERDP = 0x18/4, /* Event Ring Dequeue Pointer */
|
||||||
|
EHB = 1<<3, /* Event Handler Busy - RW1C */
|
||||||
|
|
||||||
/* TRB flags */
|
/* TRB flags */
|
||||||
TR_ENT = 1<<1,
|
TR_ENT = 1<<1,
|
||||||
|
@ -420,7 +429,7 @@ xhcishutdown(Hci *hp)
|
||||||
Ctlr *ctlr = hp->aux;
|
Ctlr *ctlr = hp->aux;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
ctlr->opr[USBCMD] = 0;
|
ctlr->opr[USBCMD] &= USBCMD_PRES;
|
||||||
for(i=0; (ctlr->opr[USBSTS] & HCH) == 0 && i < 10; i++)
|
for(i=0; (ctlr->opr[USBSTS] & HCH) == 0 && i < 10; i++)
|
||||||
delay(10);
|
delay(10);
|
||||||
intrdisable(hp->irq, hp->interrupt, hp, hp->tbdf, hp->type);
|
intrdisable(hp->irq, hp->interrupt, hp, hp->tbdf, hp->type);
|
||||||
|
@ -470,7 +479,7 @@ xhciinit(Hci *hp)
|
||||||
for(i=0; (ctlr->opr[USBSTS] & CNR) != 0 && i<100; i++)
|
for(i=0; (ctlr->opr[USBSTS] & CNR) != 0 && i<100; i++)
|
||||||
tsleep(&up->sleep, return0, nil, 10);
|
tsleep(&up->sleep, return0, nil, 10);
|
||||||
|
|
||||||
ctlr->opr[USBCMD] = HCRST;
|
ctlr->opr[USBCMD] = HCRST | (ctlr->opr[USBCMD] & USBCMD_PRES);
|
||||||
|
|
||||||
/* some intel controllers require 1ms delay after reset */
|
/* some intel controllers require 1ms delay after reset */
|
||||||
tsleep(&up->sleep, return0, nil, 1);
|
tsleep(&up->sleep, return0, nil, 1);
|
||||||
|
@ -544,7 +553,8 @@ xhciinit(Hci *hp)
|
||||||
for(i=1; i<=ctlr->nslots; i++)
|
for(i=1; i<=ctlr->nslots; i++)
|
||||||
ctlr->dcba[i] = 0;
|
ctlr->dcba[i] = 0;
|
||||||
|
|
||||||
ctlr->opr[CONFIG] = (ctlr->opr[CONFIG] & ~(CIE|U3E|0xFF)) | ctlr->nslots; /* MaxSlotsEn */
|
/* MaxSlotsEn */
|
||||||
|
ctlr->opr[CONFIG] = ctlr->nslots | (ctlr->opr[CONFIG] & CONFIG_PRES);
|
||||||
|
|
||||||
dmaflush(1, ctlr->dcba, (1+ctlr->nslots)*sizeof(ctlr->dcba[0]));
|
dmaflush(1, ctlr->dcba, (1+ctlr->nslots)*sizeof(ctlr->dcba[0]));
|
||||||
setrptr(&ctlr->opr[DCBAAP], (*ctlr->dmaaddr)(ctlr->dcba));
|
setrptr(&ctlr->opr[DCBAAP], (*ctlr->dmaaddr)(ctlr->dcba));
|
||||||
|
@ -552,16 +562,18 @@ xhciinit(Hci *hp)
|
||||||
initring(ctlr, ctlr->cr, 8); /* 256 entries */
|
initring(ctlr, ctlr->cr, 8); /* 256 entries */
|
||||||
ctlr->cr->id = 0;
|
ctlr->cr->id = 0;
|
||||||
ctlr->cr->doorbell = &ctlr->dba[0];
|
ctlr->cr->doorbell = &ctlr->dba[0];
|
||||||
setrptr(&ctlr->opr[CRCR], resetring(ctlr->cr));
|
setrptr(&ctlr->opr[CRCR], resetring(ctlr->cr) |
|
||||||
|
(ctlr->opr[CRCR] & CRCR_PRES));
|
||||||
|
|
||||||
for(i=0; i<ctlr->nintrs; i++){
|
for(i=0; i<ctlr->nintrs; i++){
|
||||||
u32int *irs = &ctlr->rts[IR0 + i*8];
|
u32int *irs = &ctlr->rts[IR0 + i*8];
|
||||||
|
|
||||||
if(i >= nelem(ctlr->er)){
|
if(i >= nelem(ctlr->er)){
|
||||||
irs[ERSTSZ] = 0; /* disable ring */
|
/* disable ring */
|
||||||
irs[IMAN] = 1;
|
irs[ERSTSZ] = 0 | (irs[ERSTSZ] & ERSTSZ_PRES);
|
||||||
|
irs[IMAN] = irs[IMAN] & (IP | IMAN_PRES);
|
||||||
irs[IMOD] = 0;
|
irs[IMOD] = 0;
|
||||||
setrptr(&irs[ERSTBA], 0);
|
setrptr(&irs[ERSTBA], irs[ERSTBA] & ERSTBA_PRES);
|
||||||
setrptr(&irs[ERDP], 0);
|
setrptr(&irs[ERDP], 0);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -576,19 +588,22 @@ xhciinit(Hci *hp)
|
||||||
ctlr->erst[i][3] = 0;
|
ctlr->erst[i][3] = 0;
|
||||||
dmaflush(1, ctlr->erst[i], 4*4);
|
dmaflush(1, ctlr->erst[i], 4*4);
|
||||||
|
|
||||||
irs[ERSTSZ] = 1; /* just one segment */
|
/* just one segment */
|
||||||
irs[IMAN] = 3;
|
irs[ERSTSZ] = 1 | (irs[ERSTSZ] & ERSTSZ_PRES);
|
||||||
|
irs[IMAN] = IE | (irs[IMAN] & (IP | IMAN_PRES));
|
||||||
irs[IMOD] = 0;
|
irs[IMOD] = 0;
|
||||||
setrptr(&irs[ERSTBA], (*ctlr->dmaaddr)(ctlr->erst[i]));
|
setrptr(&irs[ERSTBA], (*ctlr->dmaaddr)(ctlr->erst[i]) |
|
||||||
setrptr(&irs[ERDP], (*ctlr->dmaaddr)(ctlr->er[i].base) | (1<<3));
|
(irs[ERSTBA] & ERSTBA_PRES));
|
||||||
|
|
||||||
|
setrptr(&irs[ERDP], (*ctlr->dmaaddr)(ctlr->er[i].base) | EHB);
|
||||||
}
|
}
|
||||||
poperror();
|
poperror();
|
||||||
|
|
||||||
ctlr->µframe = 0;
|
ctlr->µframe = 0;
|
||||||
ctlr->opr[USBSTS] = ctlr->opr[USBSTS] & (HSE|EINT|PCD|SRE);
|
ctlr->opr[USBSTS] = ctlr->opr[USBSTS] & (HSE|EINT|PCD|SRE | USBSTS_PRES);
|
||||||
coherence();
|
coherence();
|
||||||
|
|
||||||
ctlr->opr[USBCMD] = RUNSTOP|INTE|HSEE|EWE;
|
ctlr->opr[USBCMD] = RUNSTOP|INTE|HSEE|EWE | (ctlr->opr[USBCMD] & USBCMD_PRES);
|
||||||
for(i=0; (ctlr->opr[USBSTS] & (CNR|HCH)) != 0 && i<100; i++)
|
for(i=0; (ctlr->opr[USBSTS] & (CNR|HCH)) != 0 && i<100; i++)
|
||||||
tsleep(&up->sleep, return0, nil, 10);
|
tsleep(&up->sleep, return0, nil, 10);
|
||||||
|
|
||||||
|
@ -613,6 +628,10 @@ recover(void *arg)
|
||||||
;
|
;
|
||||||
while(!needrecover(ctlr))
|
while(!needrecover(ctlr))
|
||||||
tsleep(&ctlr->recover, needrecover, ctlr, 1000);
|
tsleep(&ctlr->recover, needrecover, ctlr, 1000);
|
||||||
|
|
||||||
|
print("usbxhci %llux: need recover: USBSTS=%ux, er stopped=%d\n",
|
||||||
|
ctlr->base, ctlr->opr[USBSTS], ctlr->er->stopped);
|
||||||
|
|
||||||
(*hp->shutdown)(hp);
|
(*hp->shutdown)(hp);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -654,12 +673,11 @@ recover(void *arg)
|
||||||
qlock(&ctlr->cmdlock);
|
qlock(&ctlr->cmdlock);
|
||||||
release(ctlr);
|
release(ctlr);
|
||||||
if(waserror()) {
|
if(waserror()) {
|
||||||
print("xhci recovery failed: %s\n", up->errstr);
|
print("usbxhci %llux: recovery failed: %s\n", ctlr->base, up->errstr);
|
||||||
} else {
|
} else {
|
||||||
(*hp->init)(hp);
|
(*hp->init)(hp);
|
||||||
poperror();
|
poperror();
|
||||||
}
|
}
|
||||||
|
|
||||||
qunlock(&ctlr->cmdlock);
|
qunlock(&ctlr->cmdlock);
|
||||||
qunlock(&ctlr->slotlock);
|
qunlock(&ctlr->slotlock);
|
||||||
|
|
||||||
|
@ -881,7 +899,7 @@ interrupt(Ureg*, void *arg)
|
||||||
|
|
||||||
irs = &ctlr->rts[IR0];
|
irs = &ctlr->rts[IR0];
|
||||||
x = irs[IMAN];
|
x = irs[IMAN];
|
||||||
if(x & 1) irs[IMAN] = x & 3;
|
if(x & IP) irs[IMAN] = x;
|
||||||
|
|
||||||
for(x = ring->rp;; x=++ring->rp){
|
for(x = ring->rp;; x=++ring->rp){
|
||||||
td = ring->base + 4*(x & ring->mask);
|
td = ring->base + 4*(x & ring->mask);
|
||||||
|
@ -908,8 +926,8 @@ interrupt(Ureg*, void *arg)
|
||||||
(ctlr->µframe+(1<<14) & ~((1<<14)-1));
|
(ctlr->µframe+(1<<14) & ~((1<<14)-1));
|
||||||
break;
|
break;
|
||||||
case ER_HCE:
|
case ER_HCE:
|
||||||
iprint("xhci: host controller error: %ux %ux %ux %ux\n",
|
iprint("usbxhci %llux: host controller error: %ux %ux %ux %ux\n",
|
||||||
td[0], td[1], td[2], td[3]);
|
ctlr->base, td[0], td[1], td[2], td[3]);
|
||||||
ctlr->er->stopped = 1;
|
ctlr->er->stopped = 1;
|
||||||
wakeup(&ctlr->recover);
|
wakeup(&ctlr->recover);
|
||||||
return;
|
return;
|
||||||
|
@ -919,12 +937,12 @@ interrupt(Ureg*, void *arg)
|
||||||
case ER_DOORBELL:
|
case ER_DOORBELL:
|
||||||
case ER_DEVNOTE:
|
case ER_DEVNOTE:
|
||||||
default:
|
default:
|
||||||
iprint("xhci: event %ud: %ux %ux %ux %ux\n",
|
iprint("usbxhci %llux: event %ud: %ux %ux %ux %ux\n",
|
||||||
x, td[0], td[1], td[2], td[3]);
|
ctlr->base, x, td[0], td[1], td[2], td[3]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
setrptr(&irs[ERDP], (*ctlr->dmaaddr)(td) | (1<<3));
|
setrptr(&irs[ERDP], (*ctlr->dmaaddr)(td) | EHB);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -1855,7 +1873,7 @@ xhcialloc(u32int *mmio, u64int base, u64int size)
|
||||||
|
|
||||||
ctlr = malloc(sizeof(Ctlr));
|
ctlr = malloc(sizeof(Ctlr));
|
||||||
if(ctlr == nil){
|
if(ctlr == nil){
|
||||||
print("usbxhci: no memory for controller\n");
|
print("usbxhci %llux: no memory for controller\n", base);
|
||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
ctlr->mmio = mmio;
|
ctlr->mmio = mmio;
|
||||||
|
|
Loading…
Reference in a new issue