diff options
Diffstat (limited to 'sys/dev/usb/usb_transfer.c')
-rw-r--r-- | sys/dev/usb/usb_transfer.c | 31 |
1 files changed, 27 insertions, 4 deletions
diff --git a/sys/dev/usb/usb_transfer.c b/sys/dev/usb/usb_transfer.c index 0f02fc8..5650790 100644 --- a/sys/dev/usb/usb_transfer.c +++ b/sys/dev/usb/usb_transfer.c @@ -237,7 +237,11 @@ usbd_transfer_setup_sub_malloc(struct usb_setup_params *parm, n_obj = 1; } else { /* compute number of objects per page */ +#ifdef USB_DMA_SINGLE_ALLOC + n_obj = 1; +#else n_obj = (USB_PAGE_SIZE / size); +#endif /* * Compute number of DMA chunks, rounded up * to nearest one: @@ -273,15 +277,33 @@ usbd_transfer_setup_sub_malloc(struct usb_setup_params *parm, &parm->curr_xfer->xroot->dma_parent_tag; } - if (ppc) { - *ppc = parm->xfer_page_cache_ptr; + if (ppc != NULL) { + if (n_obj != 1) + *ppc = parm->xfer_page_cache_ptr; + else + *ppc = parm->dma_page_cache_ptr; } r = count; /* set remainder count */ z = n_obj * size; /* set allocation size */ pc = parm->xfer_page_cache_ptr; pg = parm->dma_page_ptr; - for (x = 0; x != n_dma_pc; x++) { + if (n_obj == 1) { + /* + * Avoid mapping memory twice if only a single object + * should be allocated per page cache: + */ + for (x = 0; x != n_dma_pc; x++) { + if (usb_pc_alloc_mem(parm->dma_page_cache_ptr, + pg, z, align)) { + return (1); /* failure */ + } + /* Make room for one DMA page cache and "n_dma_pg" pages */ + parm->dma_page_cache_ptr++; + pg += n_dma_pg; + } + } else { + for (x = 0; x != n_dma_pc; x++) { if (r < n_obj) { /* compute last remainder */ @@ -294,7 +316,7 @@ usbd_transfer_setup_sub_malloc(struct usb_setup_params *parm, } /* Set beginning of current buffer */ buf = parm->dma_page_cache_ptr->buffer; - /* Make room for one DMA page cache and one page */ + /* Make room for one DMA page cache and "n_dma_pg" pages */ parm->dma_page_cache_ptr++; pg += n_dma_pg; @@ -314,6 +336,7 @@ usbd_transfer_setup_sub_malloc(struct usb_setup_params *parm, } mtx_unlock(pc->tag_parent->mtx); } + } } parm->xfer_page_cache_ptr = pc; |