diff options
author | Matthew Dempsky <matthew@cvs.openbsd.org> | 2010-11-21 01:29:08 +0000 |
---|---|---|
committer | Matthew Dempsky <matthew@cvs.openbsd.org> | 2010-11-21 01:29:08 +0000 |
commit | 8faebe9544a4fc6611d79806140e1a2f47b55e6a (patch) | |
tree | 288104e2aa01ac2387ee5621b97de84b21d877b3 | |
parent | d920e81f8b61240b4c4500a543ed992904bd455f (diff) |
Properly handle when uhci_alloc_sqh() fails to allocate memory in
uhci_device_setintr().
ok jakemsr@
-rw-r--r-- | sys/dev/usb/uhci.c | 22 |
1 files changed, 15 insertions, 7 deletions
diff --git a/sys/dev/usb/uhci.c b/sys/dev/usb/uhci.c index c2b64ae79d9..f8de2d13c7d 100644 --- a/sys/dev/usb/uhci.c +++ b/sys/dev/usb/uhci.c @@ -1,4 +1,4 @@ -/* $OpenBSD: uhci.c,v 1.85 2010/11/19 18:42:27 miod Exp $ */ +/* $OpenBSD: uhci.c,v 1.86 2010/11/21 01:29:07 matthew Exp $ */ /* $NetBSD: uhci.c,v 1.172 2003/02/23 04:19:26 simonb Exp $ */ /* $FreeBSD: src/sys/dev/usb/uhci.c,v 1.33 1999/11/17 22:33:41 n_hibma Exp $ */ @@ -2740,7 +2740,7 @@ uhci_remove_intr(uhci_softc_t *sc, uhci_soft_qh_t *sqh) usbd_status uhci_device_setintr(uhci_softc_t *sc, struct uhci_pipe *upipe, int ival) { - uhci_soft_qh_t *sqh; + uhci_soft_qh_t *sqh, **qhs; int i, npoll, s; u_int bestbw, bw, bestoffs, offs; @@ -2755,10 +2755,8 @@ uhci_device_setintr(uhci_softc_t *sc, struct uhci_pipe *upipe, int ival) npoll = (UHCI_VFRAMELIST_COUNT + ival - 1) / ival; DPRINTFN(2, ("uhci_device_setintr: ival=%d npoll=%d\n", ival, npoll)); - upipe->u.intr.npoll = npoll; - upipe->u.intr.qhs = - malloc(npoll * sizeof(uhci_soft_qh_t *), M_USBHC, M_NOWAIT); - if (upipe->u.intr.qhs == NULL) + qhs = malloc(npoll * sizeof(uhci_soft_qh_t *), M_USBHC, M_NOWAIT); + if (qhs == NULL) return (USBD_NOMEM); /* @@ -2777,13 +2775,23 @@ uhci_device_setintr(uhci_softc_t *sc, struct uhci_pipe *upipe, int ival) DPRINTFN(1, ("uhci_device_setintr: bw=%d offs=%d\n", bestbw, bestoffs)); for(i = 0; i < npoll; i++) { - upipe->u.intr.qhs[i] = sqh = uhci_alloc_sqh(sc); + sqh = uhci_alloc_sqh(sc); + if (sqh == NULL) { + while (i > 0) + uhci_free_sqh(sc, qhs[--i]); + free(qhs, M_USBHC); + return (USBD_NOMEM); + } sqh->elink = NULL; sqh->qh.qh_elink = htole32(UHCI_PTR_T); sqh->pos = MOD(i * ival + bestoffs); + qhs[i] = sqh; } #undef MOD + upipe->u.intr.npoll = npoll; + upipe->u.intr.qhs = qhs; + s = splusb(); /* Enter QHs into the controller data structures. */ for(i = 0; i < npoll; i++) |