Module Name: src Committed By: tsutsui Date: Fri May 27 19:04:24 UTC 2011
Modified Files: src/sys/dev/usb: ehci.c ohci.c ohcivar.h uhci.c Log Message: Apply patch in PR kern/44907 (crash due to race in ehci.c): - make sure to remove abort_task in ehci_freex - always initialize abort_task in ehci_allocx, not in ehci_timeout just before adding the task Also apply similar fixes to ohci and uhci. XXX: should we also call abort_task handler before removing it from queue if *hci_freex() is called for usbd_xfer_handle with queued abort_task? To generate a diff of this commit: cvs rdiff -u -r1.175 -r1.176 src/sys/dev/usb/ehci.c cvs rdiff -u -r1.212 -r1.213 src/sys/dev/usb/ohci.c cvs rdiff -u -r1.49 -r1.50 src/sys/dev/usb/ohcivar.h cvs rdiff -u -r1.236 -r1.237 src/sys/dev/usb/uhci.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/dev/usb/ehci.c diff -u src/sys/dev/usb/ehci.c:1.175 src/sys/dev/usb/ehci.c:1.176 --- src/sys/dev/usb/ehci.c:1.175 Fri May 27 17:19:18 2011 +++ src/sys/dev/usb/ehci.c Fri May 27 19:04:24 2011 @@ -1,4 +1,4 @@ -/* $NetBSD: ehci.c,v 1.175 2011/05/27 17:19:18 drochner Exp $ */ +/* $NetBSD: ehci.c,v 1.176 2011/05/27 19:04:24 tsutsui Exp $ */ /* * Copyright (c) 2004-2008 The NetBSD Foundation, Inc. @@ -52,7 +52,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: ehci.c,v 1.175 2011/05/27 17:19:18 drochner Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ehci.c,v 1.176 2011/05/27 19:04:24 tsutsui Exp $"); #include "ohci.h" #include "uhci.h" @@ -1284,6 +1284,7 @@ { struct ehci_softc *sc = bus->hci_private; usbd_xfer_handle xfer; + struct ehci_xfer *exfer; xfer = SIMPLEQ_FIRST(&sc->sc_free_xfers); if (xfer != NULL) { @@ -1295,12 +1296,14 @@ } #endif } else { - xfer = malloc(sizeof(struct ehci_xfer), M_USB, M_NOWAIT); + xfer = malloc(sizeof(*exfer), M_USB, M_NOWAIT); } if (xfer != NULL) { - memset(xfer, 0, sizeof(struct ehci_xfer)); + exfer = EXFER(xfer); + memset(exfer, 0, sizeof(*exfer)); + usb_init_task(&exfer->abort_task, ehci_timeout_task, exfer); #ifdef DIAGNOSTIC - EXFER(xfer)->isdone = 1; + exfer->isdone = 1; xfer->busy_free = XFER_BUSY; #endif } @@ -1311,6 +1314,7 @@ ehci_freex(struct usbd_bus *bus, usbd_xfer_handle xfer) { struct ehci_softc *sc = bus->hci_private; + struct ehci_xfer *exfer = EXFER(xfer); #ifdef DIAGNOSTIC if (xfer->busy_free != XFER_BUSY) { @@ -1318,10 +1322,11 @@ xfer->busy_free); } xfer->busy_free = XFER_FREE; - if (!EXFER(xfer)->isdone) { + if (!exfer->isdone) { printf("ehci_freex: !isdone\n"); } #endif + usb_rem_task(xfer->pipe->device, &exfer->abort_task); SIMPLEQ_INSERT_HEAD(&sc->sc_free_xfers, xfer, next); } @@ -3150,7 +3155,6 @@ } /* Execute the abort in a process context. */ - usb_init_task(&exfer->abort_task, ehci_timeout_task, addr); usb_add_task(exfer->xfer.pipe->device, &exfer->abort_task, USB_TASKQ_HC); } Index: src/sys/dev/usb/ohci.c diff -u src/sys/dev/usb/ohci.c:1.212 src/sys/dev/usb/ohci.c:1.213 --- src/sys/dev/usb/ohci.c:1.212 Wed Dec 22 01:34:19 2010 +++ src/sys/dev/usb/ohci.c Fri May 27 19:04:24 2011 @@ -1,4 +1,4 @@ -/* $NetBSD: ohci.c,v 1.212 2010/12/22 01:34:19 macallan Exp $ */ +/* $NetBSD: ohci.c,v 1.213 2011/05/27 19:04:24 tsutsui Exp $ */ /* $FreeBSD: src/sys/dev/usb/ohci.c,v 1.22 1999/11/17 22:33:40 n_hibma Exp $ */ /* @@ -41,7 +41,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: ohci.c,v 1.212 2010/12/22 01:34:19 macallan Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ohci.c,v 1.213 2011/05/27 19:04:24 tsutsui Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -945,6 +945,7 @@ { struct ohci_softc *sc = bus->hci_private; usbd_xfer_handle xfer; + struct ohci_xfer *oxfer; xfer = SIMPLEQ_FIRST(&sc->sc_free_xfers); if (xfer != NULL) { @@ -956,10 +957,12 @@ } #endif } else { - xfer = malloc(sizeof(struct ohci_xfer), M_USB, M_NOWAIT); + xfer = malloc(sizeof(*oxfer), M_USB, M_NOWAIT); } if (xfer != NULL) { - memset(xfer, 0, sizeof (struct ohci_xfer)); + oxfer = OXFER(xfer); + memset(oxfer, 0, sizeof(*oxfer)); + usb_init_task(&oxfer->abort_task, ohci_timeout_task, oxfer); #ifdef DIAGNOSTIC xfer->busy_free = XFER_BUSY; #endif @@ -971,6 +974,7 @@ ohci_freex(struct usbd_bus *bus, usbd_xfer_handle xfer) { struct ohci_softc *sc = bus->hci_private; + struct ohci_xfer *oxfer = OXFER(xfer); #ifdef DIAGNOSTIC if (xfer->busy_free != XFER_BUSY) { @@ -979,6 +983,7 @@ } xfer->busy_free = XFER_FREE; #endif + usb_rem_task(xfer->pipe->device, &oxfer->abort_task); SIMPLEQ_INSERT_HEAD(&sc->sc_free_xfers, xfer, next); } @@ -1948,7 +1953,6 @@ } /* Execute the abort in a process context. */ - usb_init_task(&oxfer->abort_task, ohci_timeout_task, addr); usb_add_task(oxfer->xfer.pipe->device, &oxfer->abort_task, USB_TASKQ_HC); } Index: src/sys/dev/usb/ohcivar.h diff -u src/sys/dev/usb/ohcivar.h:1.49 src/sys/dev/usb/ohcivar.h:1.50 --- src/sys/dev/usb/ohcivar.h:1.49 Wed Nov 3 22:34:23 2010 +++ src/sys/dev/usb/ohcivar.h Fri May 27 19:04:24 2011 @@ -1,4 +1,4 @@ -/* $NetBSD: ohcivar.h,v 1.49 2010/11/03 22:34:23 dyoung Exp $ */ +/* $NetBSD: ohcivar.h,v 1.50 2011/05/27 19:04:24 tsutsui Exp $ */ /* $FreeBSD: src/sys/dev/usb/ohcivar.h,v 1.13 1999/11/17 22:33:41 n_hibma Exp $ */ /* @@ -140,6 +140,7 @@ struct usbd_xfer xfer; struct usb_task abort_task; }; +#define OXFER(xfer) ((struct ohci_xfer *)(xfer)) usbd_status ohci_init(ohci_softc_t *); int ohci_intr(void *); Index: src/sys/dev/usb/uhci.c diff -u src/sys/dev/usb/uhci.c:1.236 src/sys/dev/usb/uhci.c:1.237 --- src/sys/dev/usb/uhci.c:1.236 Fri May 27 17:19:18 2011 +++ src/sys/dev/usb/uhci.c Fri May 27 19:04:24 2011 @@ -1,4 +1,4 @@ -/* $NetBSD: uhci.c,v 1.236 2011/05/27 17:19:18 drochner Exp $ */ +/* $NetBSD: uhci.c,v 1.237 2011/05/27 19:04:24 tsutsui Exp $ */ /* $FreeBSD: src/sys/dev/usb/uhci.c,v 1.33 1999/11/17 22:33:41 n_hibma Exp $ */ /* @@ -42,7 +42,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: uhci.c,v 1.236 2011/05/27 17:19:18 drochner Exp $"); +__KERNEL_RCSID(0, "$NetBSD: uhci.c,v 1.237 2011/05/27 19:04:24 tsutsui Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -640,6 +640,7 @@ { struct uhci_softc *sc = bus->hci_private; usbd_xfer_handle xfer; + struct uhci_xfer *uxfer; xfer = SIMPLEQ_FIRST(&sc->sc_free_xfers); if (xfer != NULL) { @@ -651,13 +652,15 @@ } #endif } else { - xfer = malloc(sizeof(struct uhci_xfer), M_USB, M_NOWAIT); + xfer = malloc(sizeof(*uxfer), M_USB, M_NOWAIT); } if (xfer != NULL) { - memset(xfer, 0, sizeof (struct uhci_xfer)); - UXFER(xfer)->iinfo.sc = sc; + uxfer = UXFER(xfer); + memset(uxfer, 0, sizeof(*uxfer)); + uxfer->iinfo.sc = sc; + usb_init_task(&uxfer->abort_task, uhci_timeout_task, uxfer); #ifdef DIAGNOSTIC - UXFER(xfer)->iinfo.isdone = 1; + uxfer->iinfo.isdone = 1; xfer->busy_free = XFER_BUSY; #endif } @@ -668,6 +671,7 @@ uhci_freex(struct usbd_bus *bus, usbd_xfer_handle xfer) { struct uhci_softc *sc = bus->hci_private; + struct uhci_xfer *uxfer = UXFER(xfer); #ifdef DIAGNOSTIC if (xfer->busy_free != XFER_BUSY) { @@ -675,10 +679,11 @@ xfer->busy_free); } xfer->busy_free = XFER_FREE; - if (!UXFER(xfer)->iinfo.isdone) { + if (!uxfer->iinfo.isdone) { printf("uhci_freex: !isdone\n"); } #endif + usb_rem_task(xfer->pipe->device, &uxfer->abort_task); SIMPLEQ_INSERT_HEAD(&sc->sc_free_xfers, xfer, next); } @@ -1619,7 +1624,6 @@ } /* Execute the abort in a process context. */ - usb_init_task(&uxfer->abort_task, uhci_timeout_task, ii->xfer); usb_add_task(uxfer->xfer.pipe->device, &uxfer->abort_task, USB_TASKQ_HC); }