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