.. | .. |
---|
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 | +} |
---|