From owner-p4-projects@FreeBSD.ORG Sat Jun 6 04:33:11 2009 Return-Path: Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id C94741065674; Sat, 6 Jun 2009 04:33:10 +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 88FE3106564A for ; Sat, 6 Jun 2009 04:33:10 +0000 (UTC) (envelope-from thompsa@freebsd.org) Received: from repoman.freebsd.org (repoman.freebsd.org [IPv6:2001:4f8:fff6::29]) by mx1.freebsd.org (Postfix) with ESMTP id 7592B8FC17 for ; Sat, 6 Jun 2009 04:33:10 +0000 (UTC) (envelope-from thompsa@freebsd.org) Received: from repoman.freebsd.org (localhost [127.0.0.1]) by repoman.freebsd.org (8.14.3/8.14.3) with ESMTP id n564XAJE028570 for ; Sat, 6 Jun 2009 04:33:10 GMT (envelope-from thompsa@freebsd.org) Received: (from perforce@localhost) by repoman.freebsd.org (8.14.3/8.14.3/Submit) id n564XA1A028568 for perforce@freebsd.org; Sat, 6 Jun 2009 04:33:10 GMT (envelope-from thompsa@freebsd.org) Date: Sat, 6 Jun 2009 04:33:10 GMT Message-Id: <200906060433.n564XA1A028568@repoman.freebsd.org> X-Authentication-Warning: repoman.freebsd.org: perforce set sender to thompsa@freebsd.org using -f From: Andrew Thompson To: Perforce Change Reviews Cc: Subject: PERFORCE change 163628 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: Sat, 06 Jun 2009 04:33:11 -0000 http://perforce.freebsd.org/chv.cgi?CH=163628 Change 163628 by thompsa@thompsa_burger on 2009/06/06 04:32:19 - Allocate multiple urbs - Add urb list functions Affected files ... .. //depot/projects/usb_buf/src/sys/dev/usb/usb_transfer.c#14 edit .. //depot/projects/usb_buf/src/sys/dev/usb/usbdi.h#5 edit Differences ... ==== //depot/projects/usb_buf/src/sys/dev/usb/usb_transfer.c#14 (text+ko) ==== @@ -61,6 +61,11 @@ #include #include +enum { + REQ_SIZE = 8, + MIN_PKT = 8, +}; + struct usb2_std_packet_size { struct { uint16_t min; /* inclusive */ @@ -114,6 +119,9 @@ static void usb2_get_std_packet_size(struct usb2_std_packet_size *ptr, uint8_t type, enum usb_dev_speed speed); static void usb_submit_urb_flags(struct usb_urb *, int); +static struct usb_urb *urb_alloc(struct usb_pipe *, struct usb_setup_params *, + uint8_t, usb_frcount_t, usb_frcount_t); +static void urb_free(struct usb_urb *); /*------------------------------------------------------------------------* @@ -297,6 +305,101 @@ } #endif +static struct usb_urb * +urb_alloc(struct usb_pipe *pipe, struct usb_setup_params *parm, + uint8_t type, usb_frcount_t n_frlengths, usb_frcount_t n_frbuffers) +{ + const struct usb_config *setup = parm->curr_setup; + struct usb_urb *urb; + usb_frlength_t bufsiz; + usb_frcount_t x; + + bufsiz = setup->flags.ext_buffer == 1 ? 0 : parm->bufsize; + + urb = malloc(sizeof(struct usb_urb) + bufsiz, M_USB, + M_WAITOK | M_ZERO); + urb->ub_pipe = pipe; + urb->ub_buflen = bufsiz; + urb->local_buffer = urb + 1; + + urb->frlengths = malloc(sizeof(usb_frlength_t) * n_frlengths, + M_USB, M_WAITOK | M_ZERO); + urb->frbuffers = malloc(sizeof(struct usb_page_cache) * n_frbuffers, + M_USB, M_WAITOK | M_ZERO); + +#if USB_HAVE_BUSDMA + if (pipe->flags_int.bdma_enable) { + /* + * Setup "dma_page_ptr". + * + * Proof for formula below: + * + * Assume there are three USB frames having length "a", + * "b" and "c". These USB frames will at maximum need + * "z" "usb_page" structures. "z" is given by: + * + * z = ((a / USB_PAGE_SIZE) + 2) + + * ((b / USB_PAGE_SIZE) + 2) + + * ((c / USB_PAGE_SIZE) + 2); + * + * Constraining "a", "b" and "c" like this: + * + * (a + b + c) <= parm->bufsize + * + * We know that: + * + * z <= ((parm->bufsize / USB_PAGE_SIZE) + (3*2)); + * + * Here is the general formula: + */ + urb->dma_page_ptr = malloc(sizeof(struct usb_page) * + ((2 * n_frbuffers) + (parm->bufsize / USB_PAGE_SIZE)), + M_USB, M_WAITOK | M_ZERO); + } +#endif + /* initialize frame buffers */ + for (x = 0; x < n_frbuffers; x++) { + urb->frbuffers[x].tag_parent = + &pipe->xroot->dma_parent_tag; +#if USB_HAVE_BUSDMA + if (pipe->flags_int.bdma_enable && + (parm->bufsize_max > 0)) { + + if (usb2_pc_dmamap_create( + urb->frbuffers + x, + parm->bufsize_max)) { + goto error; + } + } +#endif + } + + if (bufsiz > 0) { + usb2_set_frame_offset(urb, 0, 0); + if ((type == UE_CONTROL) && (n_frbuffers > 1)) + usb2_set_frame_offset(urb, REQ_SIZE, 1); + } + /* initialize max frame count */ + urb->max_frame_count = pipe->nframes; + urb->nframes = pipe->nframes; + + return (urb); + +error: + urb_free(urb); + return (NULL); +} + +static void +urb_free(struct usb_urb *urb) +{ + + free(urb->dma_page_ptr, M_USB); + free(urb->frbuffers, M_USB); + free(urb->frlengths, M_USB); + free(urb, M_USB); +} + /*------------------------------------------------------------------------* * usb2_transfer_setup_sub - transfer setup subroutine * @@ -309,10 +412,6 @@ void usb2_transfer_setup_sub(struct usb_setup_params *parm) { - enum { - REQ_SIZE = 8, - MIN_PKT = 8, - }; struct usb_pipe *pipe = parm->curr_pipe; const struct usb_config *setup = parm->curr_setup; struct usb_endpoint_descriptor *edesc; @@ -320,9 +419,9 @@ struct usb_urb *urb; usb_frcount_t n_frlengths; usb_frcount_t n_frbuffers; - usb_frcount_t x; uint8_t type; uint8_t zmps; + int i; /* * Sanity check. The following parameters must be initialized before @@ -338,15 +437,9 @@ type = (edesc->bmAttributes & UE_XFERTYPE); - /* XXX */ TAILQ_INIT(&pipe->urb_hc_q); TAILQ_INIT(&pipe->urb_pending_q); TAILQ_INIT(&pipe->urb_free_q); - urb = &pipe->urb0; - urb->ub_pipe = pipe; - TAILQ_INSERT_TAIL(&pipe->urb_free_q, urb, ub_next); - pipe->urb_nfree = 1; - pipe->urb_nurb = 1; pipe->flags = setup->flags; pipe->nframes = setup->frames; @@ -602,80 +695,30 @@ } pipe->max_data_length -= REQ_SIZE; } - /* setup "frlengths" */ - - pipe->urb0.frlengths = parm->xfer_length_ptr; - parm->xfer_length_ptr += n_frlengths; - - /* setup "frbuffers" */ - - pipe->urb0.frbuffers = parm->xfer_page_cache_ptr; - - parm->xfer_page_cache_ptr += n_frbuffers; - /* - * check if we need to setup - * a local buffer: + * Compute maximum buffer size */ - if (!pipe->flags.ext_buffer) { + if (parm->bufsize_max < parm->bufsize) { + parm->bufsize_max = parm->bufsize; + } - /* align data */ - parm->size[0] += ((-parm->size[0]) & (USB_HOST_ALIGN - 1)); - - if (parm->buf) { - - pipe->urb0.local_buffer = - USB_ADD_BYTES(parm->buf, parm->size[0]); - - usb2_set_frame_offset(pipe, 0, 0); - - if ((type == UE_CONTROL) && (n_frbuffers > 1)) { - usb2_set_frame_offset(pipe, REQ_SIZE, 1); + /* Allocate the URBs */ + if (parm->buf) { + pipe->urb_nurb = setup->urb_count ? setup->urb_count : 1; + for (i = 0; i < pipe->urb_nurb; i++) { + urb = urb_alloc(pipe, parm, type, n_frlengths, + n_frbuffers); + if (urb == NULL) { + parm->err = USB_ERR_NOMEM; + goto done; } + TAILQ_INSERT_TAIL(&pipe->urb_free_q, urb, ub_next); + pipe->urb_nfree++; } - parm->size[0] += parm->bufsize; - - /* align data again */ - parm->size[0] += ((-parm->size[0]) & (USB_HOST_ALIGN - 1)); } - /* - * Compute maximum buffer size - */ - if (parm->bufsize_max < parm->bufsize) { - parm->bufsize_max = parm->bufsize; - } -#if USB_HAVE_BUSDMA - if (pipe->flags_int.bdma_enable) { - /* - * Setup "dma_page_ptr". - * - * Proof for formula below: - * - * Assume there are three USB frames having length "a", "b" and - * "c". These USB frames will at maximum need "z" - * "usb_page" structures. "z" is given by: - * - * z = ((a / USB_PAGE_SIZE) + 2) + ((b / USB_PAGE_SIZE) + 2) + - * ((c / USB_PAGE_SIZE) + 2); - * - * Constraining "a", "b" and "c" like this: - * - * (a + b + c) <= parm->bufsize - * - * We know that: - * - * z <= ((parm->bufsize / USB_PAGE_SIZE) + (3*2)); - * - * Here is the general formula: - */ - pipe->urb0.dma_page_ptr = parm->dma_page_ptr; - parm->dma_page_ptr += (2 * n_frbuffers); - parm->dma_page_ptr += (parm->bufsize / USB_PAGE_SIZE); - } -#endif if (zmps) { /* correct maximum data length */ pipe->max_data_length = 0; @@ -690,31 +733,7 @@ parm->err = USB_ERR_INVAL; goto done; } - /* initialize max frame count */ - pipe->urb0.max_frame_count = pipe->nframes; - - /* initialize frame buffers */ - - if (parm->buf) { - for (x = 0; x != n_frbuffers; x++) { - pipe->urb0.frbuffers[x].tag_parent = - &pipe->xroot->dma_parent_tag; -#if USB_HAVE_BUSDMA - if (pipe->flags_int.bdma_enable && - (parm->bufsize_max > 0)) { - - if (usb2_pc_dmamap_create( - pipe->urb0.frbuffers + x, - parm->bufsize_max)) { - parm->err = USB_ERR_NOMEM; - goto done; - } - } -#endif - } - } - pipe->urb0.nframes = pipe->nframes; done: if (parm->err) { /* @@ -724,8 +743,6 @@ pipe->max_frame_size = 1; pipe->max_packet_size = 1; pipe->max_data_length = 0; - pipe->urb0.nframes = 0; - pipe->urb0.max_frame_count = 0; } } @@ -783,6 +800,10 @@ parm.err = USB_ERR_BAD_BUFSIZE; DPRINTF("invalid bufsize\n"); } + if (setup->urb_count > 4) { + parm.err = USB_ERR_BAD_BUFSIZE; + DPRINTF("too many urbs requested\n"); + } if (setup->callback == NULL) { parm.err = USB_ERR_NO_CALLBACK; DPRINTF("no callback\n"); @@ -1128,6 +1149,7 @@ usb_pipe_close(struct usb_pipe **pxfer, int n_setup) { struct usb_pipe *pipe; + struct usb_urb *urb; struct usb_xfer_root *info; uint8_t needs_delay = 0; @@ -1171,6 +1193,11 @@ KASSERT (pipe->urb_nfree == pipe->urb_nurb, ("leaked %d urbs", pipe->urb_nurb - pipe->urb_nfree)); + while ((urb = TAILQ_FIRST(&pipe->urb_free_q)) != NULL) { + TAILQ_REMOVE(&pipe->urb_free_q, urb, ub_next); + urb_free(urb); + } + #if USB_HAVE_BUSDMA if (pipe->flags_int.bdma_enable) needs_delay = 1; @@ -1421,8 +1448,6 @@ printf("pipe halted, queuing %p\n", urb); TAILQ_INSERT_TAIL(&pipe->urb_pending_q, urb, ub_next); return; - } else { - KASSERT(TAILQ_FIRST(&pipe->urb_pending_q) == NULL, ("odd")); } /* Only open the USB transfer once! */ @@ -1657,6 +1682,10 @@ usb_pipe_halt(struct usb_pipe *pipe) { + if (pipe == NULL) { + printf("%s: null pipe!!?!\n", __func__); + return; + } USB_PIPE_LOCK(pipe); pipe->flags_int.halted = 1; @@ -1742,10 +1771,10 @@ * than zero gives undefined results! *------------------------------------------------------------------------*/ void -usb2_set_frame_data(struct usb_pipe *pipe, void *ptr, usb_frcount_t frindex) +usb2_set_frame_data(struct usb_urb *urb, void *ptr, usb_frcount_t frindex) { /* set virtual address to load and length */ - (&pipe->urb0)->frbuffers[frindex].buffer = ptr; + urb->frbuffers[frindex].buffer = ptr; } /*------------------------------------------------------------------------* @@ -1755,15 +1784,19 @@ * of the USB DMA buffer allocated for this USB transfer. *------------------------------------------------------------------------*/ void -usb2_set_frame_offset(struct usb_pipe *pipe, usb_frlength_t offset, +usb2_set_frame_offset(struct usb_urb *urb, usb_frlength_t offset, usb_frcount_t frindex) { + struct usb_pipe *pipe = urb->ub_pipe; + USB_ASSERT(!pipe->flags.ext_buffer, ("Cannot offset data frame " "when the USB buffer is external!\n")); + /* USB_ASSERT(offset < urb->ub_buflen, + ("frame overflow %d > %d", offset, urb->ub_buflen)); */ /* set virtual address to load */ - (&pipe->urb0)->frbuffers[frindex].buffer = - USB_ADD_BYTES((&pipe->urb0)->local_buffer, offset); + urb->frbuffers[frindex].buffer = + USB_ADD_BYTES(urb->local_buffer, offset); } /*------------------------------------------------------------------------* @@ -2743,15 +2776,14 @@ USB_PIPE_LOCK(pipe); urb = TAILQ_FIRST(&pipe->urb_free_q); - if (urb == NULL) - panic("out of urbs"); + if (urb != NULL) { + TAILQ_REMOVE(&pipe->urb_free_q, urb, ub_next); + pipe->urb_nfree--; + KASSERT(pipe->urb_nfree >= 0, ("negative count")); - TAILQ_REMOVE(&pipe->urb_free_q, urb, ub_next); - pipe->urb_nfree--; - KASSERT(pipe->urb_nfree >= 0, ("negative count")); + usb_init_urb(urb); + } USB_PIPE_UNLOCK(pipe); - - usb_init_urb(urb); return (urb); } @@ -2808,7 +2840,7 @@ if (ptr != NULL) *ptr = urb->frbuffers->buffer; if (len != NULL) - *len = urb->sumlen; + *len = urb->ub_pipe->max_data_length; if (alen != NULL) *alen = urb->actlen; if (err != NULL) @@ -2816,8 +2848,52 @@ } void -urb_set_framelen(struct usb_urb *urb, int frame, int len) +urb_set_framelen(struct usb_urb *urb, usb_frcount_t frame, usb_frlength_t len) { - /* XXX checking */ + KASSERT(len <= urb->ub_pipe->max_data_length, + ("%s: urb buffer overflow", __func__)); urb->frlengths[frame] = len; } + +void +urb_list_init(usb_urb_list *list) +{ + + TAILQ_INIT(&list->head); + list->count = 0; +} + +void +urb_list_insert(usb_urb_list *list, struct usb_urb *urb) +{ + + KASSERT(urb->on_queue == 0, ("urb already qeueued")); + TAILQ_INSERT_TAIL(&list->head, urb, ub_next); + list->count++; + urb->on_queue = 1; +} + +void +urb_list_remove(usb_urb_list *list, struct usb_urb *urb) +{ + + KASSERT(urb->on_queue == 1, ("urb not on qeueue")); + KASSERT(list->count > 0, ("list count corrupt")); + TAILQ_REMOVE(&list->head, urb, ub_next); + list->count--; + urb->on_queue = 0; +} + +struct usb_urb * +urb_list_dequeue(usb_urb_list *list) +{ + struct usb_urb *urb; + + urb = TAILQ_FIRST(&list->head); + if (urb != NULL) + urb_list_remove(list, urb); + + KASSERT(urb != NULL || list->count == 0, ("list count corrupt")); + + return (urb); +} ==== //depot/projects/usb_buf/src/sys/dev/usb/usbdi.h#5 (text+ko) ==== @@ -93,6 +93,11 @@ typedef usb_error_t (usb_handle_req_t)(struct usb_device *, struct usb_device_request *, const void **, uint16_t *); +typedef struct { + TAILQ_HEAD(, usb_urb) head; + int count; +} usb_urb_list; + /* * The following structure defines a set of USB transfer flags. */ @@ -132,6 +137,7 @@ uint8_t direction; /* pipe direction */ uint8_t ep_index; /* pipe index match to use */ uint8_t if_index; /* "ifaces" index to use */ + uint8_t urb_count; /* number if urbs avaialble */ }; /* @@ -300,7 +306,13 @@ void *urb_get_softc(struct usb_urb *urb); void *urb_get_priv(struct usb_urb *urb); void urb_set_priv(struct usb_urb *urb, void *); -void urb_set_framelen(struct usb_urb *urb, int frame, int len); +void urb_set_framelen(struct usb_urb *urb, usb_frcount_t frame, + usb_frlength_t len); + +void urb_list_init(usb_urb_list *); +void urb_list_insert(usb_urb_list *, struct usb_urb *); +void urb_list_remove(usb_urb_list *, struct usb_urb *); +struct usb_urb *urb_list_dequeue(usb_urb_list *); void device_set_usb_desc(device_t dev); void usb_pause_mtx(struct mtx *mtx, int _ticks);