From owner-p4-projects@FreeBSD.ORG Fri Dec 14 22:14:52 2007 Return-Path: Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id 6307116A476; Fri, 14 Dec 2007 22:14:52 +0000 (UTC) Delivered-To: perforce@FreeBSD.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 081BA16A419 for ; Fri, 14 Dec 2007 22:14:52 +0000 (UTC) (envelope-from hselasky@FreeBSD.org) Received: from repoman.freebsd.org (repoman.freebsd.org [IPv6:2001:4f8:fff6::29]) by mx1.freebsd.org (Postfix) with ESMTP id D8F2813C45A for ; Fri, 14 Dec 2007 22:14:51 +0000 (UTC) (envelope-from hselasky@FreeBSD.org) Received: from repoman.freebsd.org (localhost [127.0.0.1]) by repoman.freebsd.org (8.14.1/8.14.1) with ESMTP id lBEMEpbY035361 for ; Fri, 14 Dec 2007 22:14:51 GMT (envelope-from hselasky@FreeBSD.org) Received: (from perforce@localhost) by repoman.freebsd.org (8.14.1/8.14.1/Submit) id lBEMEpTL035358 for perforce@freebsd.org; Fri, 14 Dec 2007 22:14:51 GMT (envelope-from hselasky@FreeBSD.org) Date: Fri, 14 Dec 2007 22:14:51 GMT Message-Id: <200712142214.lBEMEpTL035358@repoman.freebsd.org> X-Authentication-Warning: repoman.freebsd.org: perforce set sender to hselasky@FreeBSD.org using -f From: Hans Petter Selasky To: Perforce Change Reviews Cc: Subject: PERFORCE change 130895 for review X-BeenThere: p4-projects@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: p4 projects tree changes List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 14 Dec 2007 22:14:52 -0000 http://perforce.freebsd.org/chv.cgi?CH=130895 Change 130895 by hselasky@hselasky_laptop001 on 2007/12/14 22:13:56 This commit is device side related, but also affects the host side. Create one interrupt thread per "struct usbd_memory_info" that will handle USB callbacks outside the main interrupt thread. This should also increase parallellism. Affected files ... .. //depot/projects/usb/src/sys/dev/usb/usb_subr.h#74 edit .. //depot/projects/usb/src/sys/dev/usb/usb_transfer.c#69 edit Differences ... ==== //depot/projects/usb/src/sys/dev/usb/usb_subr.h#74 (text+ko) ==== @@ -68,6 +68,7 @@ m(USBD_DMA_LOAD_FAILED,)\ m(USBD_BAD_CONTEXT,)\ m(USBD_NO_ROOT_HUB,)\ +m(USBD_NO_INTR_THREAD,)\ /**/ MAKE_ENUM(USBD_STATUS, @@ -565,7 +566,10 @@ struct usbd_memory_info { LIST_HEAD(, usbd_xfer) dma_head; + LIST_HEAD(, usbd_xfer) done_head; + struct mtx done_mtx; /* mutex protecting "done_head" */ + void *done_cookie; /* software interrupt thread cookie */ void *memory_base; struct mtx *priv_mtx; struct mtx *usb_mtx; ==== //depot/projects/usb/src/sys/dev/usb/usb_transfer.c#69 (text+ko) ==== @@ -43,6 +43,8 @@ #include #include #include +#include +#include #include #include @@ -61,6 +63,8 @@ static void usbd_bdma_cancel_event(struct usbd_xfer *xfer); static void usbd_callback_wrapper(struct usbd_xfer *xfer, uint8_t context); static usbd_status_t usbd_handle_request(struct usbd_xfer *xfer); +static driver_intr_t usbd_callback_intr_td; +static void usbd_transfer_unsetup_sub(struct usbd_memory_info *info); #ifdef USB_DEBUG void @@ -763,8 +767,10 @@ struct usbd_xfer *xfer; void *buf = NULL; uint16_t n; + uint16_t refcount; parm.err = 0; + refcount = 0; WITNESS_WARN(WARN_GIANTOK | WARN_SLEEPOK, NULL, "usbd_transfer_setup can sleep!"); @@ -827,6 +833,19 @@ info->dma_tag_p = parm.dma_tag_p; info->dma_tag_max = parm.dma_tag_max; + LIST_INIT(&(info->done_head)); + + /* initialize mutex */ + mtx_init(&(info->done_mtx), "USB done queue lock", + NULL, MTX_DEF); + + /* create our interrupt thread */ + if (swi_add(NULL, "usbcb", &usbd_callback_intr_td, + info, SWI_CAMBIO, INTR_MPSAFE, &(info->done_cookie))) { + info->done_cookie = NULL; + parm.err = USBD_NO_INTR_THREAD; + goto done; + } } else { info = NULL; } @@ -882,6 +901,7 @@ /* dummy xfer */ xfer = &dummy; bzero(&dummy, sizeof(dummy)); + refcount++; } parm.size[0] += sizeof(xfer[0]); @@ -904,6 +924,10 @@ if (buf || parm.err) { goto done; } + if (refcount == 0) { + /* no transfers - nothing to do ! */ + goto done; + } /* align data to 8 byte boundary */ parm.size[0] += ((-parm.size[0]) & (USB_HOST_ALIGN - 1)); @@ -983,6 +1007,12 @@ } done: + if (buf) { + if (info->setup_refcount == 0) { + /* something went wrong */ + usbd_transfer_unsetup_sub(info); + } + } if (parm.err) { usbd_transfer_unsetup(ppxfer, n_setup); } @@ -1011,6 +1041,62 @@ return; } +static void +usbd_transfer_unsetup_sub(struct usbd_memory_info *info) +{ + struct usbd_page_cache *pc; + int error; + + /* + * wait for any USB callbacks to + * return + */ + + while (info->memory_refcount > 0) { + error = mtx_sleep(info, info->usb_mtx, 0, + "usb_mem_wait", 0); + } + + mtx_unlock(info->usb_mtx); + + /* free DMA'able memory, if any */ + pc = info->dma_page_cache_start; + while (pc != info->dma_page_cache_end) { + usbd_pc_free_mem(pc); + pc++; + } + + /* + * free DMA maps in all + * "xfer->frbuffers" + */ + pc = info->xfer_page_cache_start; + while (pc != info->xfer_page_cache_end) { + usbd_pc_dmamap_destroy(pc); + pc++; + } + + /* free all DMA tags */ + usbd_dma_tag_unsetup(info->dma_tag_p, + info->dma_tag_max); + + /* teardown the interrupt thread, if any */ + if (info->done_cookie) { + swi_remove(info->done_cookie); + } + /* destroy done queue mutex */ + mtx_destroy(&(info->done_mtx)); + + /* + * free the "memory_base" last, + * hence the "info" structure is + * contained within the + * "memory_base"! + */ + free(info->memory_base, M_USB); + return; +} + /*------------------------------------------------------------------------* * usbd_transfer_unsetup - unsetup/free an array of USB transfers * @@ -1023,8 +1109,6 @@ { struct usbd_xfer *xfer; struct usbd_memory_info *info; - struct usbd_page_cache *pc; - int error; WITNESS_WARN(WARN_GIANTOK | WARN_SLEEPOK, NULL, "usbd_transfer_unsetup can sleep!"); @@ -1092,48 +1176,7 @@ info->setup_refcount--; if (info->setup_refcount == 0) { - - /* - * wait for any USB callbacks to - * return - */ - - while (info->memory_refcount > 0) { - error = mtx_sleep(info, info->usb_mtx, 0, - "usb_mem_wait", 0); - } - - mtx_unlock(info->usb_mtx); - - /* free DMA'able memory, if any */ - pc = info->dma_page_cache_start; - while (pc != info->dma_page_cache_end) { - usbd_pc_free_mem(pc); - pc++; - } - - /* - * free DMA maps in all - * "xfer->frbuffers" - */ - pc = info->xfer_page_cache_start; - while (pc != info->xfer_page_cache_end) { - usbd_pc_dmamap_destroy(pc); - pc++; - } - - /* free all DMA tags */ - usbd_dma_tag_unsetup(info->dma_tag_p, - info->dma_tag_max); - - /* - * free the "memory_base" last, - * hence the "info" structure is - * contained within the - * "memory_base"! - */ - free(info->memory_base, M_USB); - + usbd_transfer_unsetup_sub(info); } else { mtx_unlock(info->usb_mtx); } @@ -1443,6 +1486,23 @@ return (1); } +/*------------------------------------------------------------------------* + * usbd_callback_intr_td + * + * This is the USB callback interrupt thread. Every time a callback + * cannot be called directly we go through the callback interrupt + * thread. + *------------------------------------------------------------------------*/ +static void +usbd_callback_intr_td(void *arg) +{ +#if 0 + struct usbd_memory_info *info = arg; + +#endif + return; +} + static void usbd_premature_callback(struct usbd_xfer *xfer, usbd_status_t error) {