2  * DMA memory management for framework level HCD code (hc_driver)
 
   4  * This implementation plugs in through generic "usb_bus" level methods,
 
   5  * and should work with all USB controllers, regardles of bus type.
 
   8 #include <linux/module.h>
 
   9 #include <linux/kernel.h>
 
  10 #include <linux/slab.h>
 
  11 #include <linux/device.h>
 
  14 #include <linux/dma-mapping.h>
 
  15 #include <linux/dmapool.h>
 
  16 #include <linux/usb.h>
 
  21  * DMA-Coherent Buffers
 
  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...
 
  33         /* bigger --> allocate pages */
 
  37 /* SETUP primitives */
 
  40  * hcd_buffer_create - initialize buffer pools
 
  41  * @hcd: the bus whose buffer pools are to be initialized
 
  42  * Context: !in_interrupt()
 
  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.
 
  49  * Call hcd_buffer_destroy() to clean up after using those pools.
 
  51 int hcd_buffer_create(struct usb_hcd *hcd)
 
  56         if (!hcd->self.controller->dma_mask &&
 
  57             !(hcd->driver->flags & HCD_LOCAL_MEM))
 
  60         for (i = 0; i < HCD_BUFFER_POOLS; i++) {
 
  64                 snprintf(name, sizeof name, "buffer-%d", size);
 
  65                 hcd->pool[i] = dma_pool_create(name, hcd->self.controller,
 
  68                         hcd_buffer_destroy(hcd);
 
  77  * hcd_buffer_destroy - deallocate buffer pools
 
  78  * @hcd: the bus whose buffer pools are to be destroyed
 
  79  * Context: !in_interrupt()
 
  81  * This frees the buffer pools created by hcd_buffer_create().
 
  83 void hcd_buffer_destroy(struct usb_hcd *hcd)
 
  87         for (i = 0; i < HCD_BUFFER_POOLS; i++) {
 
  88                 struct dma_pool *pool = hcd->pool[i];
 
  90                         dma_pool_destroy(pool);
 
  97 /* sometimes alloc/free could use kmalloc with GFP_DMA, for
 
  98  * better sharing and to leverage mm/slab.c intelligence.
 
 101 void *hcd_buffer_alloc(
 
 108         struct usb_hcd          *hcd = bus_to_hcd(bus);
 
 111         /* some USB hosts just use PIO */
 
 112         if (!bus->controller->dma_mask &&
 
 113             !(hcd->driver->flags & HCD_LOCAL_MEM)) {
 
 114                 *dma = ~(dma_addr_t) 0;
 
 115                 return kmalloc(size, mem_flags);
 
 118         for (i = 0; i < HCD_BUFFER_POOLS; i++) {
 
 119                 if (size <= pool_max [i])
 
 120                         return dma_pool_alloc(hcd->pool [i], mem_flags, dma);
 
 122         return dma_alloc_coherent(hcd->self.controller, size, dma, 0);
 
 125 void hcd_buffer_free(
 
 132         struct usb_hcd          *hcd = bus_to_hcd(bus);
 
 138         if (!bus->controller->dma_mask &&
 
 139             !(hcd->driver->flags & HCD_LOCAL_MEM)) {
 
 144         for (i = 0; i < HCD_BUFFER_POOLS; i++) {
 
 145                 if (size <= pool_max [i]) {
 
 146                         dma_pool_free(hcd->pool [i], addr, dma);
 
 150         dma_free_coherent(hcd->self.controller, size, addr, dma);