summaryrefslogtreecommitdiffstats
path: root/sys/dev/usb/usb_transfer.c
diff options
context:
space:
mode:
authorhselasky <hselasky@FreeBSD.org>2015-02-02 11:32:15 +0000
committerhselasky <hselasky@FreeBSD.org>2015-02-02 11:32:15 +0000
commit47e0756aa20f117b6512e683161d62cb894bd3da (patch)
tree425e8d5c94ce17973a934b832d751ced35e2b497 /sys/dev/usb/usb_transfer.c
parent9ebeef8fb0f5c752ab311f6c3260afa5cb5e1984 (diff)
downloadFreeBSD-src-47e0756aa20f117b6512e683161d62cb894bd3da.zip
FreeBSD-src-47e0756aa20f117b6512e683161d62cb894bd3da.tar.gz
Optimise allocation of USB DMA structures. By default don't double map
allocations if only one element should be allocated per page cache. Make one allocation per element compile time configurable. Fix a comment while at it. Suggested by: ian @ MFC after: 1 week
Diffstat (limited to 'sys/dev/usb/usb_transfer.c')
-rw-r--r--sys/dev/usb/usb_transfer.c31
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;
OpenPOWER on IntegriCloud