aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/dma/mapping.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2018-10-22 13:16:03 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2018-10-22 13:16:03 -0400
commitcff229491af5df946781edfbeafd43e9cf66a3b4 (patch)
treedff787191eb78a69c054510a9ea74cc391330b73 /kernel/dma/mapping.c
parent13775dacca5c158a257320f4b47e1220b82e3b21 (diff)
parentb9fd04262a8abc366f40a9e97598e94591352c26 (diff)
Merge tag 'dma-mapping-4.20' of git://git.infradead.org/users/hch/dma-mapping
Pull dma mapping updates from Christoph Hellwig: "First batch of dma-mapping changes for 4.20. There will be a second PR as some big changes were only applied just before the end of the merge window, and I want to give them a few more days in linux-next. Summary: - mostly more consolidation of the direct mapping code, including converting over hexagon, and merging the coherent and non-coherent code into a single dma_map_ops instance (me) - cleanups for the dma_configure/dma_unconfigure callchains (me) - better handling of dma_masks in odd setups (me, Alexander Duyck) - better debugging of passing vmalloc address to the DMA API (Stephen Boyd) - CMA command line parsing fix (He Zhe)" * tag 'dma-mapping-4.20' of git://git.infradead.org/users/hch/dma-mapping: (27 commits) dma-direct: respect DMA_ATTR_NO_WARN dma-mapping: translate __GFP_NOFAIL to DMA_ATTR_NO_WARN dma-direct: document the zone selection logic dma-debug: Check for drivers mapping invalid addresses in dma_map_single() dma-direct: fix return value of dma_direct_supported dma-mapping: move dma_default_get_required_mask under ifdef dma-direct: always allow dma mask <= physiscal memory size dma-direct: implement complete bus_dma_mask handling dma-direct: refine dma_direct_alloc zone selection dma-direct: add an explicit dma_direct_get_required_mask dma-mapping: make the get_required_mask method available unconditionally unicore32: remove swiotlb support Revert "dma-mapping: clear dev->dma_ops in arch_teardown_dma_ops" dma-mapping: support non-coherent devices in dma_common_get_sgtable dma-mapping: consolidate the dma mmap implementations dma-mapping: merge direct and noncoherent ops dma-mapping: move the dma_coherent flag to struct device MIPS: don't select DMA_MAYBE_COHERENT from DMA_PERDEV_COHERENT dma-mapping: add the missing ARCH_HAS_SYNC_DMA_FOR_CPU_ALL declaration dma-mapping: fix panic caused by passing empty cma command line argument ...
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}