shithub: riscv

Download patch

ref: 83b87729d94850396c7183376320e16dbb80ecc5
parent: 1ea109345b8654110239d9c2695ae15486aa6810
author: cinap_lenrek <[email protected]>
date: Wed Aug 2 17:17:50 EDT 2017

usbxhci: handle out of memory in controller initialization

--- a/sys/src/9/pc/usbxhci.c
+++ b/sys/src/9/pc/usbxhci.c
@@ -303,8 +303,7 @@
 {
 	if(r == nil)
 		return;
-	if(r->base != nil)
-		free(r->base);
+	free(r->base);
 	memset(r, 0, sizeof(*r));
 }
 
@@ -395,6 +394,19 @@
 }
 
 static void
+shutdown(Hci *hp)
+{
+	Ctlr *ctlr = hp->aux;
+	int i;
+
+	ctlr->opr[USBCMD] = 0;
+	for(i=0; (ctlr->opr[USBSTS] & HCH) == 0 && i < 10; i++)
+		delay(10);
+	intrdisable(ctlr->pcidev->intl, hp->interrupt, hp, ctlr->pcidev->tbdf, hp->type);
+	pciclrbme(ctlr->pcidev);
+}
+
+static void
 init(Hci *hp)
 {
 	Ctlr *ctlr;
@@ -423,6 +435,22 @@
 	pcisetpms(ctlr->pcidev, 0);
 	intrenable(ctlr->pcidev->intl, hp->interrupt, hp, ctlr->pcidev->tbdf, hp->type);
 
+	if(waserror()){
+		shutdown(hp);
+		freering(ctlr->cr);
+		for(i=0; i<nelem(ctlr->er); i++){
+			freering(&ctlr->er[i]);
+			free(ctlr->erst[i]);
+			ctlr->erst[i] = nil;
+		}
+		free(ctlr->port), ctlr->port = nil;
+		free(ctlr->slot), ctlr->slot = nil;
+		free(ctlr->dcba), ctlr->dcba = nil;
+		free(ctlr->sba), ctlr->sba = nil;
+		free(ctlr->sbp), ctlr->sbp = nil;
+		nexterror();
+	}
+
 	ctlr->csz = (ctlr->hccparams & CSZ) != 0;
 	if(ctlr->hccparams & AC64)
 		ctlr->setrptr = setrptr64;
@@ -438,6 +466,8 @@
 	hp->superspeed = 0;
 	hp->nports = (ctlr->mmio[HCSPARAMS1] >> 24) & 0xFF;
 	ctlr->port = malloc(hp->nports * sizeof(Port));
+	if(ctlr->port == nil)
+		error(Enomem);
 	for(i=0; i<hp->nports; i++)
 		ctlr->port[i].reg = &ctlr->opr[0x400/4 + i*4];
 
@@ -459,9 +489,13 @@
 
 	ctlr->slot = malloc((1+ctlr->nslots)*sizeof(ctlr->slot[0]));
 	ctlr->dcba = mallocalign((1+ctlr->nslots)*8, 64, 0, ctlr->pagesize);
+	if(ctlr->slot == nil || ctlr->dcba == nil)
+		error(Enomem);
 	if(ctlr->nscratch != 0){
 		ctlr->sba = mallocalign(ctlr->nscratch*8, 64, 0, ctlr->pagesize);
 		ctlr->sbp = mallocalign(ctlr->nscratch*ctlr->pagesize, ctlr->pagesize, 0, 0);
+		if(ctlr->sba == nil || ctlr->sbp == nil)
+			error(Enomem);
 		for(i=0, p = ctlr->sbp; i<ctlr->nscratch; i++, p += ctlr->pagesize){
 			memset(p, 0, ctlr->pagesize);
 			ctlr->sba[i] = PADDR(p);
@@ -491,6 +525,8 @@
 		/* allocate and link into event ring segment table */
 		initring(&ctlr->er[i], 8);	/* 256 entries */
 		ctlr->erst[i] = mallocalign(16, 64, 0, 0);
+		if(ctlr->erst[i] == nil)
+			error(Enomem);
 		*((u64int*)ctlr->erst[i]) = PADDR(ctlr->er[i].base);
 		ctlr->erst[i][2] = ctlr->er[i].mask+1;
 		ctlr->erst[i][3] = 0;
@@ -501,7 +537,8 @@
 
 		irs[IMAN] = 3;
 		irs[IMOD] = 0;
-	}	
+	}
+	poperror();
 
 	ctlr->µframe = 0;
 	ctlr->opr[USBCMD] = RUNSTOP|INTE|HSEE|EWE;
@@ -827,19 +864,6 @@
 	dev->free = freeslot;
 
 	return slot;
-}
-
-static void
-shutdown(Hci *hp)
-{
-	Ctlr *ctlr = hp->aux;
-	int i;
-
-	ctlr->opr[USBCMD] = 0;
-	for(i=0; (ctlr->opr[USBSTS] & HCH) == 0 && i < 10; i++)
-		delay(10);
-	intrdisable(ctlr->pcidev->intl, hp->interrupt, hp, ctlr->pcidev->tbdf, hp->type);
-	pciclrbme(ctlr->pcidev);
 }
 
 static void
--- a/sys/src/9/port/devusb.c
+++ b/sys/src/9/port/devusb.c
@@ -769,8 +769,14 @@
 		if(hp != nil){
 			int n;
 
-			if(hp->init != nil)
+			if(hp->init != nil){
+				if(waserror()){
+					print("usbinit: %s: %s\n", hp->type, up->errstr);
+					continue;
+				}
 				hp->init(hp);
+				poperror();
+			}
 
 			hp->superspeed &= (1<<hp->nports)-1;
 			n = hp->nports - numbits(hp->superspeed);