From 83b87729d94850396c7183376320e16dbb80ecc5 Mon Sep 17 00:00:00 2001 From: cinap_lenrek Date: Wed, 2 Aug 2017 21:17:50 +0200 Subject: [PATCH] usbxhci: handle out of memory in controller initialization --- sys/src/9/pc/usbxhci.c | 56 +++++++++++++++++++++++++++++------------ sys/src/9/port/devusb.c | 8 +++++- 2 files changed, 47 insertions(+), 17 deletions(-) diff --git a/sys/src/9/pc/usbxhci.c b/sys/src/9/pc/usbxhci.c index a9f99fae8..bda0d849b 100644 --- a/sys/src/9/pc/usbxhci.c +++ b/sys/src/9/pc/usbxhci.c @@ -303,8 +303,7 @@ freering(Ring *r) { if(r == nil) return; - if(r->base != nil) - free(r->base); + free(r->base); memset(r, 0, sizeof(*r)); } @@ -394,6 +393,19 @@ handoff(Ctlr *ctlr) r[0] &= ~(1<<16); /* in case of timeout */ } +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) { @@ -423,6 +435,22 @@ init(Hci *hp) 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; ier); 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 @@ init(Hci *hp) 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; inports; i++) ctlr->port[i].reg = &ctlr->opr[0x400/4 + i*4]; @@ -459,9 +489,13 @@ init(Hci *hp) 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; inscratch; i++, p += ctlr->pagesize){ memset(p, 0, ctlr->pagesize); ctlr->sba[i] = PADDR(p); @@ -491,6 +525,8 @@ init(Hci *hp) /* 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 @@ init(Hci *hp) irs[IMAN] = 3; irs[IMOD] = 0; - } + } + poperror(); ctlr->µframe = 0; ctlr->opr[USBCMD] = RUNSTOP|INTE|HSEE|EWE; @@ -829,19 +866,6 @@ allocslot(Ctlr *ctlr, Udev *dev) 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 setdebug(Hci *, int) { diff --git a/sys/src/9/port/devusb.c b/sys/src/9/port/devusb.c index 4ecd08c28..7e713c7a9 100644 --- a/sys/src/9/port/devusb.c +++ b/sys/src/9/port/devusb.c @@ -769,8 +769,14 @@ usbinit(void) 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<nports)-1; n = hp->nports - numbits(hp->superspeed);