shithub: riscv

Download patch

ref: f86cc3e912e1598ff0df63b053dcb49b24e7f758
parent: d38dbf6415cbff7a43997f80f1be9492b496665e
author: cinap_lenrek <cinap_lenrek@felloff.net>
date: Sun Dec 15 16:27:00 EST 2024

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.

--- a/sys/src/9/port/usbxhci.c
+++ b/sys/src/9/port/usbxhci.c
@@ -43,6 +43,7 @@
 		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,10 +55,12 @@
 		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 */
@@ -64,12 +67,12 @@
 		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 @@
 
 	/* 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 @@
 	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 @@
 	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 @@
 	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 @@
 	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 @@
 		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 @@
 		;
 	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 @@
 	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 @@
 
 	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 @@
 				(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 @@
 		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 @@
 
 	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;
--