Compare commits

...

7 commits

Author SHA1 Message Date
cinap_lenrek
837c596bdf usbdwc: preserve Prtpwr bit for portstatus, turn off power by default, handle channel timeout
preserve the Prtpwr bit in portstatus instead of
unconditionally setting it.

turn off port powert on init. (let usbd will turn it on).

make chanio() halt the channel and error out
when interrupt status is 0 after timout.

this happens when the port is powered off.
2024-12-16 05:14:45 +00:00
cinap_lenrek
5028b882da usbehci: implement portpower control for rootports 2024-12-16 01:52:12 +00:00
Ori Bernstein
eff4b93652 acme/Mail: correct message line number for partially hidden threads 2024-12-15 21:56:54 +00:00
cinap_lenrek
f86cc3e912 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.
2024-12-15 21:27:00 +00:00
cinap_lenrek
d38dbf6415 nusb/usbd: use longer reset delay for rootports
Make reset delays more conservative:

The usb spec says root ports need 50ms reset minimum, use 100ms.
The usb spec says hub ports need 20ms minimum, use 50ms.
2024-12-15 21:19:57 +00:00
Ori Bernstein
2f685dd96b git/branch: stop emitting incorrect 'merge failed' messages 2024-12-14 05:32:05 +00:00
cinap_lenrek
473ebd0f9e ndb/dns: don't refuse queries when delegated subareas
We used to always provide soa and ns hints when
we where not authoritative.

This changed with the last commit, where we
would instead return refused error.

But this breaks when we want to explicitely
delegate to another nameserver, so add parameter
to inmyarea() to get the delegated soa out,
and provide delegated nameservers when we have one.
2024-12-14 01:49:55 +00:00
14 changed files with 119 additions and 61 deletions

View file

@ -234,14 +234,20 @@ chanwait(Ep *ep, Ctlr *ctlr, Hostchan *hc, int mask)
int intr, ointr, chan;
ulong start, now;
if(waserror()){
chanhalt(ep, hc);
nexterror();
}
chan = hc - ctlr->regs->hchan;
for(;;){
restart:
tsleep(&ctlr->chanintr[chan], chandone, hc, 1000);
if((intr = hc->hcint) == 0)
goto restart;
if(intr & Chhltd)
error("channel timeout");
if(intr & Chhltd){
poperror();
return intr;
}
ointr = intr;
now = start = fastticks(0);
do{
@ -252,6 +258,7 @@ restart:
(now - start) > 60)
dprint("ep%d.%d await %x after %ldµs %x -> %x\n",
ep->dev->nb, ep->nb, mask, now - start, ointr, intr);
poperror();
return intr;
}
if((intr & mask) == 0){
@ -686,7 +693,7 @@ init(Hci *hp)
dprint("usbdwc: FIFO depth %d sizes rx/nptx/ptx %8.8ux %8.8ux %8.8ux\n",
n, r->grxfsiz, r->gnptxfsiz, r->hptxfsiz);
r->hport0 = Prtpwr|Prtconndet|Prtenchng|Prtovrcurrchng;
r->hport0 = Prtconndet|Prtenchng|Prtovrcurrchng;
r->gintsts = ~0;
r->gintmsk = Hcintr;
r->gahbcfg |= Glblintrmsk;
@ -982,7 +989,7 @@ portstatus(Hci *hp, int)
s = r->hport0;
b = s & (Prtconndet|Prtenchng|Prtovrcurrchng);
if(b != 0)
r->hport0 = Prtpwr | b;
r->hport0 = (s & Prtpwr) | b;
b = 0;
if(s & Prtconnsts)
b |= HPpresent;

View file

@ -1639,7 +1639,7 @@ static void
portlend(Ctlr *ctlr, int port, char *ss)
{
Eopio *opio;
ulong s;
int s;
opio = ctlr->opio;
dprint("ehci %#p port %d: %s speed device: no longer owned\n",
@ -1648,6 +1648,27 @@ portlend(Ctlr *ctlr, int port, char *ss)
opio->portsc[port-1] = s | Psowner;
}
static void
portpower(Hci *hp, int port, int on)
{
Ctlr *ctlr;
Eopio *opio;
int s;
ctlr = hp->aux;
opio = ctlr->opio;
eqlock(&ctlr->portlck);
ilock(ctlr);
s = opio->portsc[port-1] & ~(Pschange|Psstatuschg);
if(on)
s |= Pspower;
else
s &= ~Pspower;
opio->portsc[port-1] = s;
iunlock(ctlr);
qunlock(&ctlr->portlck);
}
static void
portenable(Hci *hp, int port, int on)
{
@ -3221,7 +3242,6 @@ init(Hci *hp)
{
Ctlr *ctlr;
Eopio *opio;
int i;
hp->highspeed = 1;
ctlr = hp->aux;
@ -3243,10 +3263,6 @@ init(Hci *hp)
/* route all ports to us */
opio->config = Callmine;
coherence();
for (i = 0; i < hp->nports; i++)
opio->portsc[i] = Pspower;
iunlock(ctlr);
if(ehcidebug > 1)
dump(hp);
@ -3263,8 +3279,9 @@ ehcilinkage(Hci *hp)
hp->epread = epread;
hp->epwrite = epwrite;
hp->seprintep = seprintep;
hp->portenable = portenable;
hp->portpower = portpower;
hp->portreset = portreset;
hp->portenable = portenable;
hp->portstatus = portstatus;
hp->type = "ehci";
}

View file

@ -43,6 +43,7 @@ enum {
CRS = 1<<9, /* Controller Restore State - RW */
EWE = 1<<10, /* Enable Wrap Event - RW */
EU3S = 1<<11, /* Enable U3 MFINDEX Stop - RW */
USBCMD_PRES =0xfffff030,/* Reserved - RsvdP */
USBSTS = 0x04/4, /* USB Status Register */
HCH = 1<<0, /* HCHalted - RO */
@ -54,22 +55,24 @@ enum {
SRE = 1<<10, /* Save/Restore Error - RW1C */
CNR = 1<<11, /* Controller Not Ready - RO */
HCE = 1<<12, /* Host Controller Error - RO */
USBSTS_PRES =0xffffe002,/* Reserved - RsvdP */
PAGESIZE = 0x08/4, /* Page Size - RO */
DNCTRL = 0x14/4, /* Device Notification Control Register - RW */
DNCTL_PRES =0xffff0000, /* Reserved - RsvdP */
CRCR = 0x18/4, /* Command Ring Control Register - RW */
RCS = 1<<0, /* Ring Cycle State - RW */
CS = 1<<1, /* Command Stop - RW1S */
CA = 1<<2, /* Command Abort - RW1S */
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]) */
U3E = 1<<8,
CIE = 1<<9,
CONFIG_PRES =0xffffff00,/* Reserved - RsvdP */
/* Port Register Set */
PORTSC = 0x00/4, /* Port status and Control Register */
@ -105,10 +108,16 @@ enum {
/* Interrupter Registers */
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 */
ERSTSZ = 0x08/4, /* Event Ring Segment Table Size */
ERSTSZ_PRES =0xffff0000,/* Reserved - RsvdP */
ERSTBA = 0x10/4, /* Event Ring Segment Table Base Address */
ERSTBA_PRES =0x3f, /* Reserved - RsvdP */
ERDP = 0x18/4, /* Event Ring Dequeue Pointer */
EHB = 1<<3, /* Event Handler Busy - RW1C */
/* TRB flags */
TR_ENT = 1<<1,
@ -420,7 +429,7 @@ xhcishutdown(Hci *hp)
Ctlr *ctlr = hp->aux;
int i;
ctlr->opr[USBCMD] = 0;
ctlr->opr[USBCMD] &= USBCMD_PRES;
for(i=0; (ctlr->opr[USBSTS] & HCH) == 0 && i < 10; i++)
delay(10);
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++)
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 */
tsleep(&up->sleep, return0, nil, 1);
@ -544,7 +553,8 @@ xhciinit(Hci *hp)
for(i=1; i<=ctlr->nslots; i++)
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]));
setrptr(&ctlr->opr[DCBAAP], (*ctlr->dmaaddr)(ctlr->dcba));
@ -552,16 +562,18 @@ xhciinit(Hci *hp)
initring(ctlr, ctlr->cr, 8); /* 256 entries */
ctlr->cr->id = 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++){
u32int *irs = &ctlr->rts[IR0 + i*8];
if(i >= nelem(ctlr->er)){
irs[ERSTSZ] = 0; /* disable ring */
irs[IMAN] = 1;
/* disable ring */
irs[ERSTSZ] = 0 | (irs[ERSTSZ] & ERSTSZ_PRES);
irs[IMAN] = irs[IMAN] & (IP | IMAN_PRES);
irs[IMOD] = 0;
setrptr(&irs[ERSTBA], 0);
setrptr(&irs[ERSTBA], irs[ERSTBA] & ERSTBA_PRES);
setrptr(&irs[ERDP], 0);
continue;
}
@ -576,19 +588,22 @@ xhciinit(Hci *hp)
ctlr->erst[i][3] = 0;
dmaflush(1, ctlr->erst[i], 4*4);
irs[ERSTSZ] = 1; /* just one segment */
irs[IMAN] = 3;
/* just one segment */
irs[ERSTSZ] = 1 | (irs[ERSTSZ] & ERSTSZ_PRES);
irs[IMAN] = IE | (irs[IMAN] & (IP | IMAN_PRES));
irs[IMOD] = 0;
setrptr(&irs[ERSTBA], (*ctlr->dmaaddr)(ctlr->erst[i]));
setrptr(&irs[ERDP], (*ctlr->dmaaddr)(ctlr->er[i].base) | (1<<3));
setrptr(&irs[ERSTBA], (*ctlr->dmaaddr)(ctlr->erst[i]) |
(irs[ERSTBA] & ERSTBA_PRES));
setrptr(&irs[ERDP], (*ctlr->dmaaddr)(ctlr->er[i].base) | EHB);
}
poperror();
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();
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++)
tsleep(&up->sleep, return0, nil, 10);
@ -613,6 +628,10 @@ recover(void *arg)
;
while(!needrecover(ctlr))
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);
/*
@ -654,12 +673,11 @@ recover(void *arg)
qlock(&ctlr->cmdlock);
release(ctlr);
if(waserror()) {
print("xhci recovery failed: %s\n", up->errstr);
print("usbxhci %llux: recovery failed: %s\n", ctlr->base, up->errstr);
} else {
(*hp->init)(hp);
poperror();
}
qunlock(&ctlr->cmdlock);
qunlock(&ctlr->slotlock);
@ -881,7 +899,7 @@ interrupt(Ureg*, void *arg)
irs = &ctlr->rts[IR0];
x = irs[IMAN];
if(x & 1) irs[IMAN] = x & 3;
if(x & IP) irs[IMAN] = x;
for(x = ring->rp;; x=++ring->rp){
td = ring->base + 4*(x & ring->mask);
@ -908,8 +926,8 @@ interrupt(Ureg*, void *arg)
(ctlr->µframe+(1<<14) & ~((1<<14)-1));
break;
case ER_HCE:
iprint("xhci: host controller error: %ux %ux %ux %ux\n",
td[0], td[1], td[2], td[3]);
iprint("usbxhci %llux: host controller error: %ux %ux %ux %ux\n",
ctlr->base, td[0], td[1], td[2], td[3]);
ctlr->er->stopped = 1;
wakeup(&ctlr->recover);
return;
@ -919,12 +937,12 @@ interrupt(Ureg*, void *arg)
case ER_DOORBELL:
case ER_DEVNOTE:
default:
iprint("xhci: event %ud: %ux %ux %ux %ux\n",
x, td[0], td[1], td[2], td[3]);
iprint("usbxhci %llux: event %ud: %ux %ux %ux %ux\n",
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
@ -1855,7 +1873,7 @@ xhcialloc(u32int *mmio, u64int base, u64int size)
ctlr = malloc(sizeof(Ctlr));
if(ctlr == nil){
print("usbxhci: no memory for controller\n");
print("usbxhci %llux: no memory for controller\n", base);
return nil;
}
ctlr->mmio = mmio;

View file

@ -114,8 +114,9 @@ for(m in $cleanpaths){
for(ours in $dirtypaths){
common=$gitfs/object/$orig/tree/$ours
theirs=$gitfs/object/$base/tree/$ours
merge1 $ours $ours $common $theirs || st=$status
if(! ~ $#st 1)
merge1 $ours $ours $common $theirs
st=$status
if(! ~ $st '')
>[1=2] echo merge failed $ours: $st
}
if(~ $new */*)

View file

@ -164,7 +164,7 @@ out:
* don't call it non-existent if it's not ours
* (unless we're a resolver).
*/
if(err == Rname && (!inmyarea(dp->name) || cfg.resolver))
if(err == Rname && (!inmyarea(dp->name, nil) || cfg.resolver))
err = Rserver;
dp->respcode = err;
}
@ -848,7 +848,7 @@ baddelegation(RR *rp, RR *nsrp, uchar *addr)
for(nt = mydoms; nt != nil; nt = nt->entry)
if(rp->host && cistrcmp(rp->host->name, nt->val) == 0)
break;
if(nt == nil || inmyarea(rp->owner->name))
if(nt == nil || inmyarea(rp->owner->name, nil))
return 0;
dnslog("bad delegation %R from %I/%s; "
"no further logging of them",

View file

@ -526,7 +526,7 @@ dnauthdb(void)
for(i = 0; i < HTLEN; i++)
for(dp = ht[i]; dp; dp = dp->next){
area = inmyarea(dp->name);
area = inmyarea(dp->name, nil);
l = &dp->rr;
for(rp = *l; rp; rp = *l){
if(rp->db){
@ -539,7 +539,7 @@ dnauthdb(void)
if(rp->ttl < minttl)
rp->ttl = minttl;
rp->auth = 1;
} else if(rp->type == Tns && inmyarea(rp->host->name))
} else if(rp->type == Tns && inmyarea(rp->host->name, nil))
rp->auth = 1;
} else if(area){
/* no outside spoofing */
@ -707,7 +707,7 @@ rrattach(RR *rp, int auth)
next = rp->next;
rp->next = nil;
if(rp->type == Tall || rp->type == Topt || !rrsupported(rp->type)
|| cfg.cachedb && !rp->db && inmyarea(rp->owner->name))
|| cfg.cachedb && !rp->db && inmyarea(rp->owner->name, nil))
rrfree(rp);
else
rrattach1(rp, auth);

View file

@ -26,17 +26,22 @@ nameinarea(char *name, Area *s)
* true if a name is in our area
*/
Area*
inmyarea(char *name)
inmyarea(char *name, Area **delegation)
{
Area *s, *d;
s = nameinarea(name, owned);
if(s == nil)
if(s == nil){
if(delegation)
*delegation = nil;
return nil;
}
d = nameinarea(name, delegated);
if(d && d->len > s->len)
if(delegation)
*delegation = d;
if(d != nil && d->len > s->len)
return nil;
return s; /* name is in owned area `s' and not in a delegated subarea */
return s; /* name is in owned area `s' and not in a delegated subarea `d' */
}
/*

View file

@ -26,7 +26,7 @@ dnnotify(DNSmsg *reqp, DNSmsg *repp, Request *req)
return;
/* is it something we care about? */
a = inmyarea(repp->qd->owner->name);
a = inmyarea(repp->qd->owner->name, nil);
if(a == nil)
return;

View file

@ -403,7 +403,7 @@ dnresolve1(char *name, int class, int type, Request *req, int depth, int recurse
* if the domain name is within an area of ours,
* we should have found its data in memory by now.
*/
area = inmyarea(dp->name);
area = inmyarea(dp->name, nil);
if (area || strncmp(dp->name, "local#", 6) == 0)
return nil;

View file

@ -489,7 +489,7 @@ extern Area *delegated;
extern Area *owned;
void addarea(RR *rp, Ndbtuple *t);
void freeareas(Area**);
Area* inmyarea(char*);
Area* inmyarea(char*, Area**);
/* dblookup.c */
int baddelegation(RR*, RR*, uchar*);

View file

@ -14,7 +14,7 @@ dnserver(DNSmsg *reqp, DNSmsg *repp, Request *req, uchar *srcip, int rcode)
{
char tname[32], *cp;
DN *nsdp;
Area *myarea;
Area *myarea, *delegation;
RR *rp, *neg;
repp->id = reqp->id;
@ -49,7 +49,7 @@ dnserver(DNSmsg *reqp, DNSmsg *repp, Request *req, uchar *srcip, int rcode)
return;
}
myarea = inmyarea(repp->qd->owner->name);
myarea = inmyarea(repp->qd->owner->name, &delegation);
if(myarea){
if(repp->qd->type == Tixfr || repp->qd->type == Taxfr){
if(debug)
@ -64,9 +64,15 @@ dnserver(DNSmsg *reqp, DNSmsg *repp, Request *req, uchar *srcip, int rcode)
} else {
if(cfg.nonrecursive
|| cfg.localrecursive && !localip(srcip)){
/* we don't recurse and we're not authoritative */
if(delegation == nil){
/*
* we don't recurse and we're not authoritative
* nor lies the domain in a delegated sub area.
*/
setercode(repp, Rrefused);
return;
}
neg = nil;
} else {
repp->flags |= Fcanrec;
if(reqp->flags & Frecurse){

View file

@ -56,8 +56,9 @@ enum
Pconfigured,
/* Delays, timeouts (ms) */
Resetdelay = 20, /* how much to wait after a reset */
Resumedelay = 20, /* how much to wait after a resume */
Rootresetdelay = 100, /* how much to wait after a root port reset (50ms by standard) */
Portresetdelay = 50, /* how much to wait after a hub port reset (20ms by standard) */
Resumedelay = 50, /* how much to wait after a resume (20ms by standard) */
Powerdelay = 100, /* after powering up ports */
Pollms = 250, /* port poll interval */

View file

@ -452,7 +452,7 @@ portattach(Hub *h, int p)
dprint(2, "%s: %s: port %d: set reset: %r\n", argv0, d->dir, p);
return -1;
}
sleep(Resetdelay);
sleep(d->depth<0? Rootresetdelay: Portresetdelay);
if((sts = portstatus(h, p)) == -1)
return -1;
sp = "full";

View file

@ -159,8 +159,9 @@ nsub(Mesg *m)
n = 0;
for(i = 0; i < m->nchild; i++){
c = m->child[i];
n += nsub(c);
if(!(c->state & (Sdummy|Shide)))
n += nsub(c)+1;
n++;
}
return n;
}
@ -183,7 +184,9 @@ mesglineno(Mesg *msg, int *depth)
for(i = 0; i < p->nchild; i++){
if(p->child[i] == m)
break;
o += nsub(p->child[i]) + 1;
o += nsub(p->child[i]);
if(!(p->state & (Sdummy|Shide)))
o++;
}
if(!(p->state & (Sdummy|Shide))){
o++;