浏览代码

Merge tag 'dma-mapping-4.14' of git://git.infradead.org/users/hch/dma-mapping

Pull dma-mapping updates from Christoph Hellwig:

 - removal of the old dma_alloc_noncoherent interface

 - remove unused flags to dma_declare_coherent_memory

 - restrict OF DMA configuration to specific physical busses

 - use the iommu mailing list for dma-mapping questions and patches

* tag 'dma-mapping-4.14' of git://git.infradead.org/users/hch/dma-mapping:
  dma-coherent: fix dma_declare_coherent_memory() logic error
  ARM: imx: mx31moboard: Remove unused 'dma' variable
  dma-coherent: remove an unused variable
  MAINTAINERS: use the iommu list for the dma-mapping subsystem
  dma-coherent: remove the DMA_MEMORY_MAP and DMA_MEMORY_IO flags
  dma-coherent: remove the DMA_MEMORY_INCLUDES_CHILDREN flag
  of: restrict DMA configuration
  dma-mapping: remove dma_alloc_noncoherent and dma_free_noncoherent
  i825xx: switch to switch to dma_alloc_attrs
  au1000_eth: switch to dma_alloc_attrs
  sgiseeq: switch to dma_alloc_attrs
  dma-mapping: reduce dma_mapping_error inline bloat
Linus Torvalds 8 年之前
父节点
当前提交
52269718dc

+ 17 - 38
Documentation/DMA-API.txt

@@ -515,14 +515,15 @@ API at all.
 ::
 ::
 
 
 	void *
 	void *
-	dma_alloc_noncoherent(struct device *dev, size_t size,
-			      dma_addr_t *dma_handle, gfp_t flag)
+	dma_alloc_attrs(struct device *dev, size_t size, dma_addr_t *dma_handle,
+			gfp_t flag, unsigned long attrs)
 
 
-Identical to dma_alloc_coherent() except that the platform will
-choose to return either consistent or non-consistent memory as it sees
-fit.  By using this API, you are guaranteeing to the platform that you
-have all the correct and necessary sync points for this memory in the
-driver should it choose to return non-consistent memory.
+Identical to dma_alloc_coherent() except that when the
+DMA_ATTR_NON_CONSISTENT flags is passed in the attrs argument, the
+platform will choose to return either consistent or non-consistent memory
+as it sees fit.  By using this API, you are guaranteeing to the platform
+that you have all the correct and necessary sync points for this memory
+in the driver should it choose to return non-consistent memory.
 
 
 Note: where the platform can return consistent memory, it will
 Note: where the platform can return consistent memory, it will
 guarantee that the sync points become nops.
 guarantee that the sync points become nops.
@@ -535,12 +536,13 @@ that simply cannot make consistent memory.
 ::
 ::
 
 
 	void
 	void
-	dma_free_noncoherent(struct device *dev, size_t size, void *cpu_addr,
-			     dma_addr_t dma_handle)
+	dma_free_attrs(struct device *dev, size_t size, void *cpu_addr,
+		       dma_addr_t dma_handle, unsigned long attrs)
 
 
-Free memory allocated by the nonconsistent API.  All parameters must
-be identical to those passed in (and returned by
-dma_alloc_noncoherent()).
+Free memory allocated by the dma_alloc_attrs().  All parameters common
+parameters must identical to those otherwise passed to dma_fre_coherent,
+and the attrs argument must be identical to the attrs passed to
+dma_alloc_attrs().
 
 
 ::
 ::
 
 
@@ -564,8 +566,8 @@ memory or doing partial flushes.
 	dma_cache_sync(struct device *dev, void *vaddr, size_t size,
 	dma_cache_sync(struct device *dev, void *vaddr, size_t size,
 		       enum dma_data_direction direction)
 		       enum dma_data_direction direction)
 
 
-Do a partial sync of memory that was allocated by
-dma_alloc_noncoherent(), starting at virtual address vaddr and
+Do a partial sync of memory that was allocated by dma_alloc_attrs() with
+the DMA_ATTR_NON_CONSISTENT flag starting at virtual address vaddr and
 continuing on for size.  Again, you *must* observe the cache line
 continuing on for size.  Again, you *must* observe the cache line
 boundaries when doing this.
 boundaries when doing this.
 
 
@@ -590,34 +592,11 @@ size is the size of the area (must be multiples of PAGE_SIZE).
 
 
 flags can be ORed together and are:
 flags can be ORed together and are:
 
 
-- DMA_MEMORY_MAP - request that the memory returned from
-  dma_alloc_coherent() be directly writable.
-
-- DMA_MEMORY_IO - request that the memory returned from
-  dma_alloc_coherent() be addressable using read()/write()/memcpy_toio() etc.
-
-One or both of these flags must be present.
-
-- DMA_MEMORY_INCLUDES_CHILDREN - make the declared memory be allocated by
-  dma_alloc_coherent of any child devices of this one (for memory residing
-  on a bridge).
-
 - DMA_MEMORY_EXCLUSIVE - only allocate memory from the declared regions.
 - DMA_MEMORY_EXCLUSIVE - only allocate memory from the declared regions.
   Do not allow dma_alloc_coherent() to fall back to system memory when
   Do not allow dma_alloc_coherent() to fall back to system memory when
   it's out of memory in the declared region.
   it's out of memory in the declared region.
 
 
-The return value will be either DMA_MEMORY_MAP or DMA_MEMORY_IO and
-must correspond to a passed in flag (i.e. no returning DMA_MEMORY_IO
-if only DMA_MEMORY_MAP were passed in) for success or zero for
-failure.
-
-Note, for DMA_MEMORY_IO returns, all subsequent memory returned by
-dma_alloc_coherent() may no longer be accessed directly, but instead
-must be accessed using the correct bus functions.  If your driver
-isn't prepared to handle this contingency, it should not specify
-DMA_MEMORY_IO in the input flags.
-
-As a simplification for the platforms, only **one** such region of
+As a simplification for the platforms, only *one* such region of
 memory may be declared per device.
 memory may be declared per device.
 
 
 For reasons of efficiency, most platforms choose to track the declared
 For reasons of efficiency, most platforms choose to track the declared

+ 1 - 1
MAINTAINERS

@@ -4219,7 +4219,7 @@ DMA MAPPING HELPERS
 M:	Christoph Hellwig <hch@lst.de>
 M:	Christoph Hellwig <hch@lst.de>
 M:	Marek Szyprowski <m.szyprowski@samsung.com>
 M:	Marek Szyprowski <m.szyprowski@samsung.com>
 R:	Robin Murphy <robin.murphy@arm.com>
 R:	Robin Murphy <robin.murphy@arm.com>
-L:	linux-kernel@vger.kernel.org
+L:	iommu@lists.linux-foundation.org
 T:	git git://git.infradead.org/users/hch/dma-mapping.git
 T:	git git://git.infradead.org/users/hch/dma-mapping.git
 W:	http://git.infradead.org/users/hch/dma-mapping.git
 W:	http://git.infradead.org/users/hch/dma-mapping.git
 S:	Supported
 S:	Supported

+ 17 - 27
arch/arm/mach-imx/mach-imx27_visstrim_m10.c

@@ -245,7 +245,6 @@ static phys_addr_t mx2_camera_base __initdata;
 static void __init visstrim_analog_camera_init(void)
 static void __init visstrim_analog_camera_init(void)
 {
 {
 	struct platform_device *pdev;
 	struct platform_device *pdev;
-	int dma;
 
 
 	gpio_set_value(TVP5150_PWDN, 1);
 	gpio_set_value(TVP5150_PWDN, 1);
 	ndelay(1);
 	ndelay(1);
@@ -258,12 +257,9 @@ static void __init visstrim_analog_camera_init(void)
 	if (IS_ERR(pdev))
 	if (IS_ERR(pdev))
 		return;
 		return;
 
 
-	dma = dma_declare_coherent_memory(&pdev->dev,
-				mx2_camera_base, mx2_camera_base,
-				MX2_CAMERA_BUF_SIZE,
-				DMA_MEMORY_MAP | DMA_MEMORY_EXCLUSIVE);
-	if (!(dma & DMA_MEMORY_MAP))
-		return;
+	dma_declare_coherent_memory(&pdev->dev, mx2_camera_base,
+				    mx2_camera_base, MX2_CAMERA_BUF_SIZE,
+				    DMA_MEMORY_EXCLUSIVE);
 }
 }
 
 
 static void __init visstrim_reserve(void)
 static void __init visstrim_reserve(void)
@@ -444,16 +440,13 @@ static const struct imx_ssi_platform_data visstrim_m10_ssi_pdata __initconst = {
 static void __init visstrim_coda_init(void)
 static void __init visstrim_coda_init(void)
 {
 {
 	struct platform_device *pdev;
 	struct platform_device *pdev;
-	int dma;
 
 
 	pdev = imx27_add_coda();
 	pdev = imx27_add_coda();
-	dma = dma_declare_coherent_memory(&pdev->dev,
-					  mx2_camera_base + MX2_CAMERA_BUF_SIZE,
-					  mx2_camera_base + MX2_CAMERA_BUF_SIZE,
-					  MX2_CAMERA_BUF_SIZE,
-					  DMA_MEMORY_MAP | DMA_MEMORY_EXCLUSIVE);
-	if (!(dma & DMA_MEMORY_MAP))
-		return;
+	dma_declare_coherent_memory(&pdev->dev,
+				    mx2_camera_base + MX2_CAMERA_BUF_SIZE,
+				    mx2_camera_base + MX2_CAMERA_BUF_SIZE,
+				    MX2_CAMERA_BUF_SIZE,
+				    DMA_MEMORY_EXCLUSIVE);
 }
 }
 
 
 /* DMA deinterlace */
 /* DMA deinterlace */
@@ -466,24 +459,21 @@ static void __init visstrim_deinterlace_init(void)
 {
 {
 	int ret = -ENOMEM;
 	int ret = -ENOMEM;
 	struct platform_device *pdev = &visstrim_deinterlace;
 	struct platform_device *pdev = &visstrim_deinterlace;
-	int dma;
 
 
 	ret = platform_device_register(pdev);
 	ret = platform_device_register(pdev);
 
 
-	dma = dma_declare_coherent_memory(&pdev->dev,
-					  mx2_camera_base + 2 * MX2_CAMERA_BUF_SIZE,
-					  mx2_camera_base + 2 * MX2_CAMERA_BUF_SIZE,
-					  MX2_CAMERA_BUF_SIZE,
-					  DMA_MEMORY_MAP | DMA_MEMORY_EXCLUSIVE);
-	if (!(dma & DMA_MEMORY_MAP))
-		return;
+	dma_declare_coherent_memory(&pdev->dev,
+				    mx2_camera_base + 2 * MX2_CAMERA_BUF_SIZE,
+				    mx2_camera_base + 2 * MX2_CAMERA_BUF_SIZE,
+				    MX2_CAMERA_BUF_SIZE,
+				    DMA_MEMORY_EXCLUSIVE);
 }
 }
 
 
 /* Emma-PrP for format conversion */
 /* Emma-PrP for format conversion */
 static void __init visstrim_emmaprp_init(void)
 static void __init visstrim_emmaprp_init(void)
 {
 {
 	struct platform_device *pdev;
 	struct platform_device *pdev;
-	int dma;
+	int ret;
 
 
 	pdev = imx27_add_mx2_emmaprp();
 	pdev = imx27_add_mx2_emmaprp();
 	if (IS_ERR(pdev))
 	if (IS_ERR(pdev))
@@ -493,11 +483,11 @@ static void __init visstrim_emmaprp_init(void)
 	 * Use the same memory area as the analog camera since both
 	 * Use the same memory area as the analog camera since both
 	 * devices are, by nature, exclusive.
 	 * devices are, by nature, exclusive.
 	 */
 	 */
-	dma = dma_declare_coherent_memory(&pdev->dev,
+	ret = dma_declare_coherent_memory(&pdev->dev,
 				mx2_camera_base, mx2_camera_base,
 				mx2_camera_base, mx2_camera_base,
 				MX2_CAMERA_BUF_SIZE,
 				MX2_CAMERA_BUF_SIZE,
-				DMA_MEMORY_MAP | DMA_MEMORY_EXCLUSIVE);
-	if (!(dma & DMA_MEMORY_MAP))
+				DMA_MEMORY_EXCLUSIVE);
+	if (ret)
 		pr_err("Failed to declare memory for emmaprp\n");
 		pr_err("Failed to declare memory for emmaprp\n");
 }
 }
 
 

+ 6 - 6
arch/arm/mach-imx/mach-mx31moboard.c

@@ -475,7 +475,7 @@ static phys_addr_t mx3_camera_base __initdata;
 
 
 static int __init mx31moboard_init_cam(void)
 static int __init mx31moboard_init_cam(void)
 {
 {
-	int dma, ret = -ENOMEM;
+	int ret;
 	struct platform_device *pdev;
 	struct platform_device *pdev;
 
 
 	imx31_add_ipu_core();
 	imx31_add_ipu_core();
@@ -484,11 +484,11 @@ static int __init mx31moboard_init_cam(void)
 	if (IS_ERR(pdev))
 	if (IS_ERR(pdev))
 		return PTR_ERR(pdev);
 		return PTR_ERR(pdev);
 
 
-	dma = dma_declare_coherent_memory(&pdev->dev,
-					mx3_camera_base, mx3_camera_base,
-					MX3_CAMERA_BUF_SIZE,
-					DMA_MEMORY_MAP | DMA_MEMORY_EXCLUSIVE);
-	if (!(dma & DMA_MEMORY_MAP))
+	ret = dma_declare_coherent_memory(&pdev->dev,
+					  mx3_camera_base, mx3_camera_base,
+					  MX3_CAMERA_BUF_SIZE,
+					  DMA_MEMORY_EXCLUSIVE);
+	if (ret)
 		goto err;
 		goto err;
 
 
 	ret = platform_device_add(pdev);
 	ret = platform_device_add(pdev);

+ 1 - 1
arch/metag/include/asm/dma-mapping.h

@@ -9,7 +9,7 @@ static inline const struct dma_map_ops *get_arch_dma_ops(struct bus_type *bus)
 }
 }
 
 
 /*
 /*
- * dma_alloc_noncoherent() returns non-cacheable memory, so there's no need to
+ * dma_alloc_attrs() always returns non-cacheable memory, so there's no need to
  * do any flushing here.
  * do any flushing here.
  */
  */
 static inline void
 static inline void

+ 1 - 1
arch/nios2/include/asm/dma-mapping.h

@@ -18,7 +18,7 @@ static inline const struct dma_map_ops *get_arch_dma_ops(struct bus_type *bus)
 }
 }
 
 
 /*
 /*
- * dma_alloc_noncoherent() returns non-cacheable memory, so there's no need to
+ * dma_alloc_attrs() always returns non-cacheable memory, so there's no need to
  * do any flushing here.
  * do any flushing here.
  */
  */
 static inline void dma_cache_sync(struct device *dev, void *vaddr, size_t size,
 static inline void dma_cache_sync(struct device *dev, void *vaddr, size_t size,

+ 1 - 2
arch/sh/drivers/pci/fixups-dreamcast.c

@@ -63,11 +63,10 @@ static void gapspci_fixup_resources(struct pci_dev *dev)
 		res.end = GAPSPCI_DMA_BASE + GAPSPCI_DMA_SIZE - 1;
 		res.end = GAPSPCI_DMA_BASE + GAPSPCI_DMA_SIZE - 1;
 		res.flags = IORESOURCE_MEM;
 		res.flags = IORESOURCE_MEM;
 		pcibios_resource_to_bus(dev->bus, &region, &res);
 		pcibios_resource_to_bus(dev->bus, &region, &res);
-		BUG_ON(!dma_declare_coherent_memory(&dev->dev,
+		BUG_ON(dma_declare_coherent_memory(&dev->dev,
 						res.start,
 						res.start,
 						region.start,
 						region.start,
 						resource_size(&res),
 						resource_size(&res),
-						DMA_MEMORY_MAP |
 						DMA_MEMORY_EXCLUSIVE));
 						DMA_MEMORY_EXCLUSIVE));
 		break;
 		break;
 	default:
 	default:

+ 2 - 2
arch/tile/include/asm/dma-mapping.h

@@ -68,8 +68,8 @@ static inline bool dma_capable(struct device *dev, dma_addr_t addr, size_t size)
 int dma_set_mask(struct device *dev, u64 mask);
 int dma_set_mask(struct device *dev, u64 mask);
 
 
 /*
 /*
- * dma_alloc_noncoherent() is #defined to return coherent memory,
- * so there's no need to do any flushing here.
+ * dma_alloc_attrs() always returns non-cacheable memory, so there's no need to
+ * do any flushing here.
  */
  */
 static inline void dma_cache_sync(struct device *dev, void *vaddr, size_t size,
 static inline void dma_cache_sync(struct device *dev, void *vaddr, size_t size,
 				  enum dma_data_direction direction)
 				  enum dma_data_direction direction)

+ 38 - 47
drivers/base/dma-coherent.c

@@ -37,7 +37,7 @@ static inline dma_addr_t dma_get_device_base(struct device *dev,
 		return mem->device_base;
 		return mem->device_base;
 }
 }
 
 
-static bool dma_init_coherent_memory(
+static int dma_init_coherent_memory(
 	phys_addr_t phys_addr, dma_addr_t device_addr, size_t size, int flags,
 	phys_addr_t phys_addr, dma_addr_t device_addr, size_t size, int flags,
 	struct dma_coherent_mem **mem)
 	struct dma_coherent_mem **mem)
 {
 {
@@ -45,25 +45,28 @@ static bool dma_init_coherent_memory(
 	void __iomem *mem_base = NULL;
 	void __iomem *mem_base = NULL;
 	int pages = size >> PAGE_SHIFT;
 	int pages = size >> PAGE_SHIFT;
 	int bitmap_size = BITS_TO_LONGS(pages) * sizeof(long);
 	int bitmap_size = BITS_TO_LONGS(pages) * sizeof(long);
+	int ret;
 
 
-	if ((flags & (DMA_MEMORY_MAP | DMA_MEMORY_IO)) == 0)
-		goto out;
-	if (!size)
+	if (!size) {
+		ret = -EINVAL;
 		goto out;
 		goto out;
+	}
 
 
-	if (flags & DMA_MEMORY_MAP)
-		mem_base = memremap(phys_addr, size, MEMREMAP_WC);
-	else
-		mem_base = ioremap(phys_addr, size);
-	if (!mem_base)
+	mem_base = memremap(phys_addr, size, MEMREMAP_WC);
+	if (!mem_base) {
+		ret = -EINVAL;
 		goto out;
 		goto out;
-
+	}
 	dma_mem = kzalloc(sizeof(struct dma_coherent_mem), GFP_KERNEL);
 	dma_mem = kzalloc(sizeof(struct dma_coherent_mem), GFP_KERNEL);
-	if (!dma_mem)
+	if (!dma_mem) {
+		ret = -ENOMEM;
 		goto out;
 		goto out;
+	}
 	dma_mem->bitmap = kzalloc(bitmap_size, GFP_KERNEL);
 	dma_mem->bitmap = kzalloc(bitmap_size, GFP_KERNEL);
-	if (!dma_mem->bitmap)
+	if (!dma_mem->bitmap) {
+		ret = -ENOMEM;
 		goto out;
 		goto out;
+	}
 
 
 	dma_mem->virt_base = mem_base;
 	dma_mem->virt_base = mem_base;
 	dma_mem->device_base = device_addr;
 	dma_mem->device_base = device_addr;
@@ -73,17 +76,13 @@ static bool dma_init_coherent_memory(
 	spin_lock_init(&dma_mem->spinlock);
 	spin_lock_init(&dma_mem->spinlock);
 
 
 	*mem = dma_mem;
 	*mem = dma_mem;
-	return true;
+	return 0;
 
 
 out:
 out:
 	kfree(dma_mem);
 	kfree(dma_mem);
-	if (mem_base) {
-		if (flags & DMA_MEMORY_MAP)
-			memunmap(mem_base);
-		else
-			iounmap(mem_base);
-	}
-	return false;
+	if (mem_base)
+		memunmap(mem_base);
+	return ret;
 }
 }
 
 
 static void dma_release_coherent_memory(struct dma_coherent_mem *mem)
 static void dma_release_coherent_memory(struct dma_coherent_mem *mem)
@@ -91,10 +90,7 @@ static void dma_release_coherent_memory(struct dma_coherent_mem *mem)
 	if (!mem)
 	if (!mem)
 		return;
 		return;
 
 
-	if (mem->flags & DMA_MEMORY_MAP)
-		memunmap(mem->virt_base);
-	else
-		iounmap(mem->virt_base);
+	memunmap(mem->virt_base);
 	kfree(mem->bitmap);
 	kfree(mem->bitmap);
 	kfree(mem);
 	kfree(mem);
 }
 }
@@ -109,8 +105,6 @@ static int dma_assign_coherent_memory(struct device *dev,
 		return -EBUSY;
 		return -EBUSY;
 
 
 	dev->dma_mem = mem;
 	dev->dma_mem = mem;
-	/* FIXME: this routine just ignores DMA_MEMORY_INCLUDES_CHILDREN */
-
 	return 0;
 	return 0;
 }
 }
 
 
@@ -118,16 +112,16 @@ int dma_declare_coherent_memory(struct device *dev, phys_addr_t phys_addr,
 				dma_addr_t device_addr, size_t size, int flags)
 				dma_addr_t device_addr, size_t size, int flags)
 {
 {
 	struct dma_coherent_mem *mem;
 	struct dma_coherent_mem *mem;
+	int ret;
 
 
-	if (!dma_init_coherent_memory(phys_addr, device_addr, size, flags,
-				      &mem))
-		return 0;
-
-	if (dma_assign_coherent_memory(dev, mem) == 0)
-		return flags & DMA_MEMORY_MAP ? DMA_MEMORY_MAP : DMA_MEMORY_IO;
+	ret = dma_init_coherent_memory(phys_addr, device_addr, size, flags, &mem);
+	if (ret)
+		return ret;
 
 
-	dma_release_coherent_memory(mem);
-	return 0;
+	ret = dma_assign_coherent_memory(dev, mem);
+	if (ret)
+		dma_release_coherent_memory(mem);
+	return ret;
 }
 }
 EXPORT_SYMBOL(dma_declare_coherent_memory);
 EXPORT_SYMBOL(dma_declare_coherent_memory);
 
 
@@ -171,7 +165,6 @@ static void *__dma_alloc_from_coherent(struct dma_coherent_mem *mem,
 	int order = get_order(size);
 	int order = get_order(size);
 	unsigned long flags;
 	unsigned long flags;
 	int pageno;
 	int pageno;
-	int dma_memory_map;
 	void *ret;
 	void *ret;
 
 
 	spin_lock_irqsave(&mem->spinlock, flags);
 	spin_lock_irqsave(&mem->spinlock, flags);
@@ -188,15 +181,9 @@ static void *__dma_alloc_from_coherent(struct dma_coherent_mem *mem,
 	 */
 	 */
 	*dma_handle = mem->device_base + (pageno << PAGE_SHIFT);
 	*dma_handle = mem->device_base + (pageno << PAGE_SHIFT);
 	ret = mem->virt_base + (pageno << PAGE_SHIFT);
 	ret = mem->virt_base + (pageno << PAGE_SHIFT);
-	dma_memory_map = (mem->flags & DMA_MEMORY_MAP);
 	spin_unlock_irqrestore(&mem->spinlock, flags);
 	spin_unlock_irqrestore(&mem->spinlock, flags);
-	if (dma_memory_map)
-		memset(ret, 0, size);
-	else
-		memset_io(ret, 0, size);
-
+	memset(ret, 0, size);
 	return ret;
 	return ret;
-
 err:
 err:
 	spin_unlock_irqrestore(&mem->spinlock, flags);
 	spin_unlock_irqrestore(&mem->spinlock, flags);
 	return NULL;
 	return NULL;
@@ -359,14 +346,18 @@ static struct reserved_mem *dma_reserved_default_memory __initdata;
 static int rmem_dma_device_init(struct reserved_mem *rmem, struct device *dev)
 static int rmem_dma_device_init(struct reserved_mem *rmem, struct device *dev)
 {
 {
 	struct dma_coherent_mem *mem = rmem->priv;
 	struct dma_coherent_mem *mem = rmem->priv;
+	int ret;
 
 
-	if (!mem &&
-	    !dma_init_coherent_memory(rmem->base, rmem->base, rmem->size,
-				      DMA_MEMORY_MAP | DMA_MEMORY_EXCLUSIVE,
-				      &mem)) {
+	if (!mem)
+		return -ENODEV;
+
+	ret = dma_init_coherent_memory(rmem->base, rmem->base, rmem->size,
+				       DMA_MEMORY_EXCLUSIVE, &mem);
+
+	if (ret) {
 		pr_err("Reserved memory: failed to init DMA memory pool at %pa, size %ld MiB\n",
 		pr_err("Reserved memory: failed to init DMA memory pool at %pa, size %ld MiB\n",
 			&rmem->base, (unsigned long)rmem->size / SZ_1M);
 			&rmem->base, (unsigned long)rmem->size / SZ_1M);
-		return -ENODEV;
+		return ret;
 	}
 	}
 	mem->use_dev_dma_pfn_offset = true;
 	mem->use_dev_dma_pfn_offset = true;
 	rmem->priv = mem;
 	rmem->priv = mem;

+ 2 - 5
drivers/base/dma-mapping.c

@@ -176,13 +176,10 @@ int dmam_declare_coherent_memory(struct device *dev, phys_addr_t phys_addr,
 
 
 	rc = dma_declare_coherent_memory(dev, phys_addr, device_addr, size,
 	rc = dma_declare_coherent_memory(dev, phys_addr, device_addr, size,
 					 flags);
 					 flags);
-	if (rc) {
+	if (!rc)
 		devres_add(dev, res);
 		devres_add(dev, res);
-		rc = 0;
-	} else {
+	else
 		devres_free(res);
 		devres_free(res);
-		rc = -ENOMEM;
-	}
 
 
 	return rc;
 	return rc;
 }
 }

+ 0 - 3
drivers/char/virtio_console.c

@@ -451,9 +451,6 @@ static struct port_buffer *alloc_buf(struct virtqueue *vq, size_t buf_size,
 		 * device is created by remoteproc, the DMA memory is
 		 * device is created by remoteproc, the DMA memory is
 		 * associated with the grandparent device:
 		 * associated with the grandparent device:
 		 * vdev => rproc => platform-dev.
 		 * vdev => rproc => platform-dev.
-		 * The code here would have been less quirky if
-		 * DMA_MEMORY_INCLUDES_CHILDREN had been supported
-		 * in dma-coherent.c
 		 */
 		 */
 		if (!vq->vdev->dev.parent || !vq->vdev->dev.parent->parent)
 		if (!vq->vdev->dev.parent || !vq->vdev->dev.parent->parent)
 			goto free_buf;
 			goto free_buf;

+ 2 - 3
drivers/media/platform/soc_camera/sh_mobile_ceu_camera.c

@@ -1708,11 +1708,10 @@ static int sh_mobile_ceu_probe(struct platform_device *pdev)
 		err = dma_declare_coherent_memory(&pdev->dev, res->start,
 		err = dma_declare_coherent_memory(&pdev->dev, res->start,
 						  res->start,
 						  res->start,
 						  resource_size(res),
 						  resource_size(res),
-						  DMA_MEMORY_MAP |
 						  DMA_MEMORY_EXCLUSIVE);
 						  DMA_MEMORY_EXCLUSIVE);
-		if (!err) {
+		if (err) {
 			dev_err(&pdev->dev, "Unable to declare CEU memory.\n");
 			dev_err(&pdev->dev, "Unable to declare CEU memory.\n");
-			return -ENXIO;
+			return err;
 		}
 		}
 
 
 		pcdev->video_limit = resource_size(res);
 		pcdev->video_limit = resource_size(res);

+ 10 - 8
drivers/net/ethernet/amd/au1000_eth.c

@@ -1180,9 +1180,10 @@ static int au1000_probe(struct platform_device *pdev)
 	/* Allocate the data buffers
 	/* Allocate the data buffers
 	 * Snooping works fine with eth on all au1xxx
 	 * Snooping works fine with eth on all au1xxx
 	 */
 	 */
-	aup->vaddr = (u32)dma_alloc_noncoherent(NULL, MAX_BUF_SIZE *
-						(NUM_TX_BUFFS + NUM_RX_BUFFS),
-						&aup->dma_addr,	0);
+	aup->vaddr = (u32)dma_alloc_attrs(NULL, MAX_BUF_SIZE *
+					  (NUM_TX_BUFFS + NUM_RX_BUFFS),
+					  &aup->dma_addr, 0,
+					  DMA_ATTR_NON_CONSISTENT);
 	if (!aup->vaddr) {
 	if (!aup->vaddr) {
 		dev_err(&pdev->dev, "failed to allocate data buffers\n");
 		dev_err(&pdev->dev, "failed to allocate data buffers\n");
 		err = -ENOMEM;
 		err = -ENOMEM;
@@ -1361,8 +1362,9 @@ err_remap3:
 err_remap2:
 err_remap2:
 	iounmap(aup->mac);
 	iounmap(aup->mac);
 err_remap1:
 err_remap1:
-	dma_free_noncoherent(NULL, MAX_BUF_SIZE * (NUM_TX_BUFFS + NUM_RX_BUFFS),
-			     (void *)aup->vaddr, aup->dma_addr);
+	dma_free_attrs(NULL, MAX_BUF_SIZE * (NUM_TX_BUFFS + NUM_RX_BUFFS),
+			(void *)aup->vaddr, aup->dma_addr,
+			DMA_ATTR_NON_CONSISTENT);
 err_vaddr:
 err_vaddr:
 	free_netdev(dev);
 	free_netdev(dev);
 err_alloc:
 err_alloc:
@@ -1394,9 +1396,9 @@ static int au1000_remove(struct platform_device *pdev)
 		if (aup->tx_db_inuse[i])
 		if (aup->tx_db_inuse[i])
 			au1000_ReleaseDB(aup, aup->tx_db_inuse[i]);
 			au1000_ReleaseDB(aup, aup->tx_db_inuse[i]);
 
 
-	dma_free_noncoherent(NULL, MAX_BUF_SIZE *
-			(NUM_TX_BUFFS + NUM_RX_BUFFS),
-			(void *)aup->vaddr, aup->dma_addr);
+	dma_free_attrs(NULL, MAX_BUF_SIZE * (NUM_TX_BUFFS + NUM_RX_BUFFS),
+			(void *)aup->vaddr, aup->dma_addr,
+			DMA_ATTR_NON_CONSISTENT);
 
 
 	iounmap(aup->macdma);
 	iounmap(aup->macdma);
 	iounmap(aup->mac);
 	iounmap(aup->mac);

+ 2 - 4
drivers/net/ethernet/i825xx/lasi_82596.c

@@ -96,8 +96,6 @@
 
 
 #define OPT_SWAP_PORT	0x0001	/* Need to wordswp on the MPU port */
 #define OPT_SWAP_PORT	0x0001	/* Need to wordswp on the MPU port */
 
 
-#define DMA_ALLOC                        dma_alloc_noncoherent
-#define DMA_FREE                         dma_free_noncoherent
 #define DMA_WBACK(ndev, addr, len) \
 #define DMA_WBACK(ndev, addr, len) \
 	do { dma_cache_sync((ndev)->dev.parent, (void *)addr, len, DMA_TO_DEVICE); } while (0)
 	do { dma_cache_sync((ndev)->dev.parent, (void *)addr, len, DMA_TO_DEVICE); } while (0)
 
 
@@ -200,8 +198,8 @@ static int __exit lan_remove_chip(struct parisc_device *pdev)
 	struct i596_private *lp = netdev_priv(dev);
 	struct i596_private *lp = netdev_priv(dev);
 
 
 	unregister_netdev (dev);
 	unregister_netdev (dev);
-	DMA_FREE(&pdev->dev, sizeof(struct i596_private),
-		 (void *)lp->dma, lp->dma_addr);
+	dma_free_attrs(&pdev->dev, sizeof(struct i596_private), lp->dma,
+		       lp->dma_addr, DMA_ATTR_NON_CONSISTENT);
 	free_netdev (dev);
 	free_netdev (dev);
 	return 0;
 	return 0;
 }
 }

+ 5 - 4
drivers/net/ethernet/i825xx/lib82596.c

@@ -1063,8 +1063,9 @@ static int i82596_probe(struct net_device *dev)
 	if (!dev->base_addr || !dev->irq)
 	if (!dev->base_addr || !dev->irq)
 		return -ENODEV;
 		return -ENODEV;
 
 
-	dma = (struct i596_dma *) DMA_ALLOC(dev->dev.parent,
-		sizeof(struct i596_dma), &lp->dma_addr, GFP_KERNEL);
+	dma = dma_alloc_attrs(dev->dev.parent, sizeof(struct i596_dma),
+			      &lp->dma_addr, GFP_KERNEL,
+			      DMA_ATTR_NON_CONSISTENT);
 	if (!dma) {
 	if (!dma) {
 		printk(KERN_ERR "%s: Couldn't get shared memory\n", __FILE__);
 		printk(KERN_ERR "%s: Couldn't get shared memory\n", __FILE__);
 		return -ENOMEM;
 		return -ENOMEM;
@@ -1085,8 +1086,8 @@ static int i82596_probe(struct net_device *dev)
 
 
 	i = register_netdev(dev);
 	i = register_netdev(dev);
 	if (i) {
 	if (i) {
-		DMA_FREE(dev->dev.parent, sizeof(struct i596_dma),
-				    (void *)dma, lp->dma_addr);
+		dma_free_attrs(dev->dev.parent, sizeof(struct i596_dma),
+			       dma, lp->dma_addr, DMA_ATTR_NON_CONSISTENT);
 		return i;
 		return i;
 	}
 	}
 
 

+ 2 - 4
drivers/net/ethernet/i825xx/sni_82596.c

@@ -23,8 +23,6 @@
 
 
 static const char sni_82596_string[] = "snirm_82596";
 static const char sni_82596_string[] = "snirm_82596";
 
 
-#define DMA_ALLOC                      dma_alloc_coherent
-#define DMA_FREE                       dma_free_coherent
 #define DMA_WBACK(priv, addr, len)     do { } while (0)
 #define DMA_WBACK(priv, addr, len)     do { } while (0)
 #define DMA_INV(priv, addr, len)       do { } while (0)
 #define DMA_INV(priv, addr, len)       do { } while (0)
 #define DMA_WBACK_INV(priv, addr, len) do { } while (0)
 #define DMA_WBACK_INV(priv, addr, len) do { } while (0)
@@ -152,8 +150,8 @@ static int sni_82596_driver_remove(struct platform_device *pdev)
 	struct i596_private *lp = netdev_priv(dev);
 	struct i596_private *lp = netdev_priv(dev);
 
 
 	unregister_netdev(dev);
 	unregister_netdev(dev);
-	DMA_FREE(dev->dev.parent, sizeof(struct i596_private),
-		 lp->dma, lp->dma_addr);
+	dma_free_attrs(dev->dev.parent, sizeof(struct i596_private), lp->dma,
+		       lp->dma_addr, DMA_ATTR_NON_CONSISTENT);
 	iounmap(lp->ca);
 	iounmap(lp->ca);
 	iounmap(lp->mpu_port);
 	iounmap(lp->mpu_port);
 	free_netdev (dev);
 	free_netdev (dev);

+ 4 - 4
drivers/net/ethernet/seeq/sgiseeq.c

@@ -737,8 +737,8 @@ static int sgiseeq_probe(struct platform_device *pdev)
 	sp = netdev_priv(dev);
 	sp = netdev_priv(dev);
 
 
 	/* Make private data page aligned */
 	/* Make private data page aligned */
-	sr = dma_alloc_noncoherent(&pdev->dev, sizeof(*sp->srings),
-				&sp->srings_dma, GFP_KERNEL);
+	sr = dma_alloc_attrs(&pdev->dev, sizeof(*sp->srings), &sp->srings_dma,
+			     GFP_KERNEL, DMA_ATTR_NON_CONSISTENT);
 	if (!sr) {
 	if (!sr) {
 		printk(KERN_ERR "Sgiseeq: Page alloc failed, aborting.\n");
 		printk(KERN_ERR "Sgiseeq: Page alloc failed, aborting.\n");
 		err = -ENOMEM;
 		err = -ENOMEM;
@@ -813,8 +813,8 @@ static int sgiseeq_remove(struct platform_device *pdev)
 	struct sgiseeq_private *sp = netdev_priv(dev);
 	struct sgiseeq_private *sp = netdev_priv(dev);
 
 
 	unregister_netdev(dev);
 	unregister_netdev(dev);
-	dma_free_noncoherent(&pdev->dev, sizeof(*sp->srings), sp->srings,
-			     sp->srings_dma);
+	dma_free_attrs(&pdev->dev, sizeof(*sp->srings), sp->srings,
+		       sp->srings_dma, DMA_ATTR_NON_CONSISTENT);
 	free_netdev(dev);
 	free_netdev(dev);
 
 
 	return 0;
 	return 0;

+ 32 - 16
drivers/of/device.c

@@ -9,6 +9,9 @@
 #include <linux/module.h>
 #include <linux/module.h>
 #include <linux/mod_devicetable.h>
 #include <linux/mod_devicetable.h>
 #include <linux/slab.h>
 #include <linux/slab.h>
+#include <linux/pci.h>
+#include <linux/platform_device.h>
+#include <linux/amba/bus.h>
 
 
 #include <asm/errno.h>
 #include <asm/errno.h>
 #include "of_private.h"
 #include "of_private.h"
@@ -84,31 +87,28 @@ int of_device_add(struct platform_device *ofdev)
  */
  */
 int of_dma_configure(struct device *dev, struct device_node *np)
 int of_dma_configure(struct device *dev, struct device_node *np)
 {
 {
-	u64 dma_addr, paddr, size;
+	u64 dma_addr, paddr, size = 0;
 	int ret;
 	int ret;
 	bool coherent;
 	bool coherent;
 	unsigned long offset;
 	unsigned long offset;
 	const struct iommu_ops *iommu;
 	const struct iommu_ops *iommu;
 	u64 mask;
 	u64 mask;
 
 
-	/*
-	 * Set default coherent_dma_mask to 32 bit.  Drivers are expected to
-	 * setup the correct supported mask.
-	 */
-	if (!dev->coherent_dma_mask)
-		dev->coherent_dma_mask = DMA_BIT_MASK(32);
-
-	/*
-	 * Set it to coherent_dma_mask by default if the architecture
-	 * code has not set it.
-	 */
-	if (!dev->dma_mask)
-		dev->dma_mask = &dev->coherent_dma_mask;
-
 	ret = of_dma_get_range(np, &dma_addr, &paddr, &size);
 	ret = of_dma_get_range(np, &dma_addr, &paddr, &size);
 	if (ret < 0) {
 	if (ret < 0) {
+		/*
+		 * For legacy reasons, we have to assume some devices need
+		 * DMA configuration regardless of whether "dma-ranges" is
+		 * correctly specified or not.
+		 */
+		if (!dev_is_pci(dev) &&
+#ifdef CONFIG_ARM_AMBA
+		    dev->bus != &amba_bustype &&
+#endif
+		    dev->bus != &platform_bus_type)
+			return ret == -ENODEV ? 0 : ret;
+
 		dma_addr = offset = 0;
 		dma_addr = offset = 0;
-		size = max(dev->coherent_dma_mask, dev->coherent_dma_mask + 1);
 	} else {
 	} else {
 		offset = PFN_DOWN(paddr - dma_addr);
 		offset = PFN_DOWN(paddr - dma_addr);
 
 
@@ -129,6 +129,22 @@ int of_dma_configure(struct device *dev, struct device_node *np)
 		dev_dbg(dev, "dma_pfn_offset(%#08lx)\n", offset);
 		dev_dbg(dev, "dma_pfn_offset(%#08lx)\n", offset);
 	}
 	}
 
 
+	/*
+	 * Set default coherent_dma_mask to 32 bit.  Drivers are expected to
+	 * setup the correct supported mask.
+	 */
+	if (!dev->coherent_dma_mask)
+		dev->coherent_dma_mask = DMA_BIT_MASK(32);
+	/*
+	 * Set it to coherent_dma_mask by default if the architecture
+	 * code has not set it.
+	 */
+	if (!dev->dma_mask)
+		dev->dma_mask = &dev->coherent_dma_mask;
+
+	if (!size)
+		size = max(dev->coherent_dma_mask, dev->coherent_dma_mask + 1);
+
 	dev->dma_pfn_offset = offset;
 	dev->dma_pfn_offset = offset;
 
 
 	/*
 	/*

+ 1 - 2
drivers/scsi/NCR_Q720.c

@@ -217,8 +217,7 @@ NCR_Q720_probe(struct device *dev)
 	}
 	}
 	
 	
 	if (dma_declare_coherent_memory(dev, base_addr, base_addr,
 	if (dma_declare_coherent_memory(dev, base_addr, base_addr,
-					mem_size, DMA_MEMORY_MAP)
-	    != DMA_MEMORY_MAP) {
+					mem_size, 0)) {
 		printk(KERN_ERR "NCR_Q720: DMA declare memory failed\n");
 		printk(KERN_ERR "NCR_Q720: DMA declare memory failed\n");
 		goto out_release_region;
 		goto out_release_region;
 	}
 	}

+ 3 - 4
drivers/usb/host/ohci-sm501.c

@@ -123,13 +123,12 @@ static int ohci_hcd_sm501_drv_probe(struct platform_device *pdev)
 	 * regular memory. The HCD_LOCAL_MEM flag does just that.
 	 * regular memory. The HCD_LOCAL_MEM flag does just that.
 	 */
 	 */
 
 
-	if (!dma_declare_coherent_memory(dev, mem->start,
+	retval = dma_declare_coherent_memory(dev, mem->start,
 					 mem->start - mem->parent->start,
 					 mem->start - mem->parent->start,
 					 resource_size(mem),
 					 resource_size(mem),
-					 DMA_MEMORY_MAP |
-					 DMA_MEMORY_EXCLUSIVE)) {
+					 DMA_MEMORY_EXCLUSIVE);
+	if (retval) {
 		dev_err(dev, "cannot declare coherent memory\n");
 		dev_err(dev, "cannot declare coherent memory\n");
-		retval = -ENXIO;
 		goto err1;
 		goto err1;
 	}
 	}
 
 

+ 3 - 6
drivers/usb/host/ohci-tmio.c

@@ -227,13 +227,10 @@ static int ohci_hcd_tmio_drv_probe(struct platform_device *dev)
 		goto err_ioremap_regs;
 		goto err_ioremap_regs;
 	}
 	}
 
 
-	if (!dma_declare_coherent_memory(&dev->dev, sram->start,
-				sram->start,
-				resource_size(sram),
-				DMA_MEMORY_MAP | DMA_MEMORY_EXCLUSIVE)) {
-		ret = -EBUSY;
+	ret = dma_declare_coherent_memory(&dev->dev, sram->start, sram->start,
+				resource_size(sram), DMA_MEMORY_EXCLUSIVE);
+	if (ret)
 		goto err_dma_declare;
 		goto err_dma_declare;
-	}
 
 
 	if (cell->enable) {
 	if (cell->enable) {
 		ret = cell->enable(dev);
 		ret = cell->enable(dev);

+ 6 - 22
include/linux/dma-mapping.h

@@ -550,26 +550,13 @@ static inline void dma_free_coherent(struct device *dev, size_t size,
 	return dma_free_attrs(dev, size, cpu_addr, dma_handle, 0);
 	return dma_free_attrs(dev, size, cpu_addr, dma_handle, 0);
 }
 }
 
 
-static inline void *dma_alloc_noncoherent(struct device *dev, size_t size,
-		dma_addr_t *dma_handle, gfp_t gfp)
-{
-	return dma_alloc_attrs(dev, size, dma_handle, gfp,
-			       DMA_ATTR_NON_CONSISTENT);
-}
-
-static inline void dma_free_noncoherent(struct device *dev, size_t size,
-		void *cpu_addr, dma_addr_t dma_handle)
-{
-	dma_free_attrs(dev, size, cpu_addr, dma_handle,
-		       DMA_ATTR_NON_CONSISTENT);
-}
-
 static inline int dma_mapping_error(struct device *dev, dma_addr_t dma_addr)
 static inline int dma_mapping_error(struct device *dev, dma_addr_t dma_addr)
 {
 {
-	debug_dma_mapping_error(dev, dma_addr);
+	const struct dma_map_ops *ops = get_dma_ops(dev);
 
 
-	if (get_dma_ops(dev)->mapping_error)
-		return get_dma_ops(dev)->mapping_error(dev, dma_addr);
+	debug_dma_mapping_error(dev, dma_addr);
+	if (ops->mapping_error)
+		return ops->mapping_error(dev, dma_addr);
 	return 0;
 	return 0;
 }
 }
 
 
@@ -720,10 +707,7 @@ static inline int dma_get_cache_alignment(void)
 #endif
 #endif
 
 
 /* flags for the coherent memory api */
 /* flags for the coherent memory api */
-#define	DMA_MEMORY_MAP			0x01
-#define DMA_MEMORY_IO			0x02
-#define DMA_MEMORY_INCLUDES_CHILDREN	0x04
-#define DMA_MEMORY_EXCLUSIVE		0x08
+#define DMA_MEMORY_EXCLUSIVE		0x01
 
 
 #ifdef CONFIG_HAVE_GENERIC_DMA_COHERENT
 #ifdef CONFIG_HAVE_GENERIC_DMA_COHERENT
 int dma_declare_coherent_memory(struct device *dev, phys_addr_t phys_addr,
 int dma_declare_coherent_memory(struct device *dev, phys_addr_t phys_addr,
@@ -736,7 +720,7 @@ static inline int
 dma_declare_coherent_memory(struct device *dev, phys_addr_t phys_addr,
 dma_declare_coherent_memory(struct device *dev, phys_addr_t phys_addr,
 			    dma_addr_t device_addr, size_t size, int flags)
 			    dma_addr_t device_addr, size_t size, int flags)
 {
 {
-	return 0;
+	return -ENOSYS;
 }
 }
 
 
 static inline void
 static inline void