aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/dma/mapping.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/dma/mapping.c')
-rw-r--r--kernel/dma/mapping.c71
1 files changed, 37 insertions, 34 deletions
diff --git a/kernel/dma/mapping.c b/kernel/dma/mapping.c
index d2a92ddaac4d..58dec7a92b7b 100644
--- a/kernel/dma/mapping.c
+++ b/kernel/dma/mapping.c
@@ -7,7 +7,7 @@
7 */ 7 */
8 8
9#include <linux/acpi.h> 9#include <linux/acpi.h>
10#include <linux/dma-mapping.h> 10#include <linux/dma-noncoherent.h>
11#include <linux/export.h> 11#include <linux/export.h>
12#include <linux/gfp.h> 12#include <linux/gfp.h>
13#include <linux/of_device.h> 13#include <linux/of_device.h>
@@ -202,17 +202,26 @@ EXPORT_SYMBOL(dmam_release_declared_memory);
202 * Create scatter-list for the already allocated DMA buffer. 202 * Create scatter-list for the already allocated DMA buffer.
203 */ 203 */
204int dma_common_get_sgtable(struct device *dev, struct sg_table *sgt, 204int dma_common_get_sgtable(struct device *dev, struct sg_table *sgt,
205 void *cpu_addr, dma_addr_t handle, size_t size) 205 void *cpu_addr, dma_addr_t dma_addr, size_t size,
206 unsigned long attrs)
206{ 207{
207 struct page *page = virt_to_page(cpu_addr); 208 struct page *page;
208 int ret; 209 int ret;
209 210
210 ret = sg_alloc_table(sgt, 1, GFP_KERNEL); 211 if (!dev_is_dma_coherent(dev)) {
211 if (unlikely(ret)) 212 if (!IS_ENABLED(CONFIG_ARCH_HAS_DMA_COHERENT_TO_PFN))
212 return ret; 213 return -ENXIO;
213 214
214 sg_set_page(sgt->sgl, page, PAGE_ALIGN(size), 0); 215 page = pfn_to_page(arch_dma_coherent_to_pfn(dev, cpu_addr,
215 return 0; 216 dma_addr));
217 } else {
218 page = virt_to_page(cpu_addr);
219 }
220
221 ret = sg_alloc_table(sgt, 1, GFP_KERNEL);
222 if (!ret)
223 sg_set_page(sgt->sgl, page, PAGE_ALIGN(size), 0);
224 return ret;
216} 225}
217EXPORT_SYMBOL(dma_common_get_sgtable); 226EXPORT_SYMBOL(dma_common_get_sgtable);
218 227
@@ -220,27 +229,37 @@ EXPORT_SYMBOL(dma_common_get_sgtable);
220 * Create userspace mapping for the DMA-coherent memory. 229 * Create userspace mapping for the DMA-coherent memory.
221 */ 230 */
222int dma_common_mmap(struct device *dev, struct vm_area_struct *vma, 231int dma_common_mmap(struct device *dev, struct vm_area_struct *vma,
223 void *cpu_addr, dma_addr_t dma_addr, size_t size) 232 void *cpu_addr, dma_addr_t dma_addr, size_t size,
233 unsigned long attrs)
224{ 234{
225 int ret = -ENXIO;
226#ifndef CONFIG_ARCH_NO_COHERENT_DMA_MMAP 235#ifndef CONFIG_ARCH_NO_COHERENT_DMA_MMAP
227 unsigned long user_count = vma_pages(vma); 236 unsigned long user_count = vma_pages(vma);
228 unsigned long count = PAGE_ALIGN(size) >> PAGE_SHIFT; 237 unsigned long count = PAGE_ALIGN(size) >> PAGE_SHIFT;
229 unsigned long off = vma->vm_pgoff; 238 unsigned long off = vma->vm_pgoff;
239 unsigned long pfn;
240 int ret = -ENXIO;
230 241
231 vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); 242 vma->vm_page_prot = arch_dma_mmap_pgprot(dev, vma->vm_page_prot, attrs);
232 243
233 if (dma_mmap_from_dev_coherent(dev, vma, cpu_addr, size, &ret)) 244 if (dma_mmap_from_dev_coherent(dev, vma, cpu_addr, size, &ret))
234 return ret; 245 return ret;
235 246
236 if (off < count && user_count <= (count - off)) 247 if (off >= count || user_count > count - off)
237 ret = remap_pfn_range(vma, vma->vm_start, 248 return -ENXIO;
238 page_to_pfn(virt_to_page(cpu_addr)) + off,
239 user_count << PAGE_SHIFT,
240 vma->vm_page_prot);
241#endif /* !CONFIG_ARCH_NO_COHERENT_DMA_MMAP */
242 249
243 return ret; 250 if (!dev_is_dma_coherent(dev)) {
251 if (!IS_ENABLED(CONFIG_ARCH_HAS_DMA_COHERENT_TO_PFN))
252 return -ENXIO;
253 pfn = arch_dma_coherent_to_pfn(dev, cpu_addr, dma_addr);
254 } else {
255 pfn = page_to_pfn(virt_to_page(cpu_addr));
256 }
257
258 return remap_pfn_range(vma, vma->vm_start, pfn + vma->vm_pgoff,
259 user_count << PAGE_SHIFT, vma->vm_page_prot);
260#else
261 return -ENXIO;
262#endif /* !CONFIG_ARCH_NO_COHERENT_DMA_MMAP */
244} 263}
245EXPORT_SYMBOL(dma_common_mmap); 264EXPORT_SYMBOL(dma_common_mmap);
246 265
@@ -327,19 +346,3 @@ void dma_common_free_remap(void *cpu_addr, size_t size, unsigned long vm_flags)
327 vunmap(cpu_addr); 346 vunmap(cpu_addr);
328} 347}
329#endif 348#endif
330
331/*
332 * enables DMA API use for a device
333 */
334int dma_configure(struct device *dev)
335{
336 if (dev->bus->dma_configure)
337 return dev->bus->dma_configure(dev);
338 return 0;
339}
340
341void dma_deconfigure(struct device *dev)
342{
343 of_dma_deconfigure(dev);
344 acpi_dma_deconfigure(dev);
345}