| .. | .. |
|---|
| 16 | 16 | #include <linux/io.h> |
|---|
| 17 | 17 | #include <linux/dma-mapping.h> |
|---|
| 18 | 18 | #include <linux/dmapool.h> |
|---|
| 19 | +#include <linux/genalloc.h> |
|---|
| 19 | 20 | #include <linux/usb.h> |
|---|
| 20 | 21 | #include <linux/usb/hcd.h> |
|---|
| 21 | 22 | |
|---|
| .. | .. |
|---|
| 65 | 66 | char name[16]; |
|---|
| 66 | 67 | int i, size; |
|---|
| 67 | 68 | |
|---|
| 68 | | - if (!IS_ENABLED(CONFIG_HAS_DMA) || |
|---|
| 69 | | - (!is_device_dma_capable(hcd->self.sysdev) && |
|---|
| 70 | | - !(hcd->driver->flags & HCD_LOCAL_MEM))) |
|---|
| 69 | + if (hcd->localmem_pool || !hcd_uses_dma(hcd)) |
|---|
| 71 | 70 | return 0; |
|---|
| 72 | 71 | |
|---|
| 73 | 72 | for (i = 0; i < HCD_BUFFER_POOLS; i++) { |
|---|
| .. | .. |
|---|
| 101 | 100 | return; |
|---|
| 102 | 101 | |
|---|
| 103 | 102 | for (i = 0; i < HCD_BUFFER_POOLS; i++) { |
|---|
| 104 | | - struct dma_pool *pool = hcd->pool[i]; |
|---|
| 105 | | - |
|---|
| 106 | | - if (pool) { |
|---|
| 107 | | - dma_pool_destroy(pool); |
|---|
| 108 | | - hcd->pool[i] = NULL; |
|---|
| 109 | | - } |
|---|
| 103 | + dma_pool_destroy(hcd->pool[i]); |
|---|
| 104 | + hcd->pool[i] = NULL; |
|---|
| 110 | 105 | } |
|---|
| 111 | 106 | } |
|---|
| 112 | 107 | |
|---|
| .. | .. |
|---|
| 128 | 123 | if (size == 0) |
|---|
| 129 | 124 | return NULL; |
|---|
| 130 | 125 | |
|---|
| 126 | + if (hcd->localmem_pool) |
|---|
| 127 | + return gen_pool_dma_alloc(hcd->localmem_pool, size, dma); |
|---|
| 128 | + |
|---|
| 131 | 129 | /* some USB hosts just use PIO */ |
|---|
| 132 | | - if (!IS_ENABLED(CONFIG_HAS_DMA) || |
|---|
| 133 | | - (!is_device_dma_capable(bus->sysdev) && |
|---|
| 134 | | - !(hcd->driver->flags & HCD_LOCAL_MEM))) { |
|---|
| 130 | + if (!hcd_uses_dma(hcd)) { |
|---|
| 135 | 131 | *dma = ~(dma_addr_t) 0; |
|---|
| 136 | 132 | return kmalloc(size, mem_flags); |
|---|
| 137 | 133 | } |
|---|
| .. | .. |
|---|
| 156 | 152 | if (!addr) |
|---|
| 157 | 153 | return; |
|---|
| 158 | 154 | |
|---|
| 159 | | - if (!IS_ENABLED(CONFIG_HAS_DMA) || |
|---|
| 160 | | - (!is_device_dma_capable(bus->sysdev) && |
|---|
| 161 | | - !(hcd->driver->flags & HCD_LOCAL_MEM))) { |
|---|
| 155 | + if (hcd->localmem_pool) { |
|---|
| 156 | + gen_pool_free(hcd->localmem_pool, (unsigned long)addr, size); |
|---|
| 157 | + return; |
|---|
| 158 | + } |
|---|
| 159 | + |
|---|
| 160 | + if (!hcd_uses_dma(hcd)) { |
|---|
| 162 | 161 | kfree(addr); |
|---|
| 163 | 162 | return; |
|---|
| 164 | 163 | } |
|---|
| .. | .. |
|---|
| 171 | 170 | } |
|---|
| 172 | 171 | dma_free_coherent(hcd->self.sysdev, size, addr, dma); |
|---|
| 173 | 172 | } |
|---|
| 173 | + |
|---|
| 174 | +void *hcd_buffer_alloc_pages(struct usb_hcd *hcd, |
|---|
| 175 | + size_t size, gfp_t mem_flags, dma_addr_t *dma) |
|---|
| 176 | +{ |
|---|
| 177 | + if (size == 0) |
|---|
| 178 | + return NULL; |
|---|
| 179 | + |
|---|
| 180 | + if (hcd->localmem_pool) |
|---|
| 181 | + return gen_pool_dma_alloc_align(hcd->localmem_pool, |
|---|
| 182 | + size, dma, PAGE_SIZE); |
|---|
| 183 | + |
|---|
| 184 | + /* some USB hosts just use PIO */ |
|---|
| 185 | + if (!hcd_uses_dma(hcd)) { |
|---|
| 186 | + *dma = DMA_MAPPING_ERROR; |
|---|
| 187 | + return (void *)__get_free_pages(mem_flags, |
|---|
| 188 | + get_order(size)); |
|---|
| 189 | + } |
|---|
| 190 | + |
|---|
| 191 | + return dma_alloc_coherent(hcd->self.sysdev, |
|---|
| 192 | + size, dma, mem_flags); |
|---|
| 193 | +} |
|---|
| 194 | + |
|---|
| 195 | +void hcd_buffer_free_pages(struct usb_hcd *hcd, |
|---|
| 196 | + size_t size, void *addr, dma_addr_t dma) |
|---|
| 197 | +{ |
|---|
| 198 | + if (!addr) |
|---|
| 199 | + return; |
|---|
| 200 | + |
|---|
| 201 | + if (hcd->localmem_pool) { |
|---|
| 202 | + gen_pool_free(hcd->localmem_pool, |
|---|
| 203 | + (unsigned long)addr, size); |
|---|
| 204 | + return; |
|---|
| 205 | + } |
|---|
| 206 | + |
|---|
| 207 | + if (!hcd_uses_dma(hcd)) { |
|---|
| 208 | + free_pages((unsigned long)addr, get_order(size)); |
|---|
| 209 | + return; |
|---|
| 210 | + } |
|---|
| 211 | + |
|---|
| 212 | + dma_free_coherent(hcd->self.sysdev, size, addr, dma); |
|---|
| 213 | +} |
|---|