usbxhci: handle out of memory in controller initialization

This commit is contained in:
cinap_lenrek 2017-08-02 21:17:50 +02:00
parent 1ea109345b
commit 83b87729d9
2 changed files with 47 additions and 17 deletions

View file

@ -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; 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 @@ 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; i<hp->nports; 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; i<ctlr->nscratch; 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)
{

View file

@ -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<<hp->nports)-1;
n = hp->nports - numbits(hp->superspeed);