1 /* 2 * DMA memory management for framework level HCD code (hc_driver) 3 * 4 * This implementation plugs in through generic "usb_bus" level methods, 5 * and should work with all USB controllers, regardles of bus type. 6 */ 7 8 #include <linux/config.h> 9 #include <linux/module.h> 10 #include <linux/kernel.h> 11 #include <linux/slab.h> 12 #include <linux/device.h> 13 #include <linux/mm.h> 14 #include <asm/io.h> 15 #include <asm/scatterlist.h> 16 #include <linux/dma-mapping.h> 17 #include <linux/dmapool.h> 18 19 20 #ifdef CONFIG_USB_DEBUG 21 #define DEBUG 22 #else 23 #undef DEBUG 24 #endif 25 26 #include <linux/usb.h> 27 #include "hcd.h" 28 29 30 /* 31 * DMA-Coherent Buffers 32 */ 33 34 /* FIXME tune these based on pool statistics ... */ 35 static const size_t pool_max [HCD_BUFFER_POOLS] = { 36 /* platforms without dma-friendly caches might need to 37 * prevent cacheline sharing... 38 */ 39 32, 40 128, 41 512, 42 PAGE_SIZE / 2 43 /* bigger --> allocate pages */ 44 }; 45 46 47 /* SETUP primitives */ 48 49 /** 50 * hcd_buffer_create - initialize buffer pools 51 * @hcd: the bus whose buffer pools are to be initialized 52 * Context: !in_interrupt() 53 * 54 * Call this as part of initializing a host controller that uses the dma 55 * memory allocators. It initializes some pools of dma-coherent memory that 56 * will be shared by all drivers using that controller, or returns a negative 57 * errno value on error. 58 * 59 * Call hcd_buffer_destroy() to clean up after using those pools. 60 */ 61 int hcd_buffer_create (struct usb_hcd *hcd) 62 { 63 char name [16]; 64 int i, size; 65 66 for (i = 0; i < HCD_BUFFER_POOLS; i++) { 67 if (!(size = pool_max [i])) 68 continue; 69 snprintf (name, sizeof name, "buffer-%d", size); 70 hcd->pool [i] = dma_pool_create (name, hcd->self.controller, 71 size, size, 0); 72 if (!hcd->pool [i]) { 73 hcd_buffer_destroy (hcd); 74 return -ENOMEM; 75 } 76 } 77 return 0; 78 } 79 80 81 /** 82 * hcd_buffer_destroy - deallocate buffer pools 83 * @hcd: the bus whose buffer pools are to be destroyed 84 * Context: !in_interrupt() 85 * 86 * This frees the buffer pools created by hcd_buffer_create(). 87 */ 88 void hcd_buffer_destroy (struct usb_hcd *hcd) 89 { 90 int i; 91 92 for (i = 0; i < HCD_BUFFER_POOLS; i++) { 93 struct dma_pool *pool = hcd->pool [i]; 94 if (pool) { 95 dma_pool_destroy (pool); 96 hcd->pool[i] = NULL; 97 } 98 } 99 } 100 101 102 /* sometimes alloc/free could use kmalloc with SLAB_DMA, for 103 * better sharing and to leverage mm/slab.c intelligence. 104 */ 105 106 void *hcd_buffer_alloc ( 107 struct usb_bus *bus, 108 size_t size, 109 int mem_flags, 110 dma_addr_t *dma 111 ) 112 { 113 struct usb_hcd *hcd = bus->hcpriv; 114 int i; 115 116 /* some USB hosts just use PIO */ 117 if (!bus->controller->dma_mask) { 118 *dma = ~(dma_addr_t) 0; 119 return kmalloc (size, mem_flags); 120 } 121 122 for (i = 0; i < HCD_BUFFER_POOLS; i++) { 123 if (size <= pool_max [i]) 124 return dma_pool_alloc (hcd->pool [i], mem_flags, dma); 125 } 126 return dma_alloc_coherent (hcd->self.controller, size, dma, 0); 127 } 128 129 void hcd_buffer_free ( 130 struct usb_bus *bus, 131 size_t size, 132 void *addr, 133 dma_addr_t dma 134 ) 135 { 136 struct usb_hcd *hcd = bus->hcpriv; 137 int i; 138 139 if (!addr) 140 return; 141 142 if (!bus->controller->dma_mask) { 143 kfree (addr); 144 return; 145 } 146 147 for (i = 0; i < HCD_BUFFER_POOLS; i++) { 148 if (size <= pool_max [i]) { 149 dma_pool_free (hcd->pool [i], addr, dma); 150 return; 151 } 152 } 153 dma_free_coherent (hcd->self.controller, size, addr, dma); 154 } 155