Commit 11a5aa32 authored by Russell King's avatar Russell King

ARM: dma-mapping: check DMA mask against available memory

Some buses have negative offsets, which causes the DMA mask checks to
falsely fail.  Fix this by using the actual amount of memory fitted in
the system.
Signed-off-by: default avatarRussell King <rmk+kernel@arm.linux.org.uk>
parent 6ce4eac1
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
* *
* DMA uncached mapping support. * DMA uncached mapping support.
*/ */
#include <linux/bootmem.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/mm.h> #include <linux/mm.h>
#include <linux/gfp.h> #include <linux/gfp.h>
...@@ -162,6 +163,8 @@ static u64 get_coherent_dma_mask(struct device *dev) ...@@ -162,6 +163,8 @@ static u64 get_coherent_dma_mask(struct device *dev)
u64 mask = (u64)DMA_BIT_MASK(32); u64 mask = (u64)DMA_BIT_MASK(32);
if (dev) { if (dev) {
unsigned long max_dma_pfn;
mask = dev->coherent_dma_mask; mask = dev->coherent_dma_mask;
/* /*
...@@ -173,6 +176,8 @@ static u64 get_coherent_dma_mask(struct device *dev) ...@@ -173,6 +176,8 @@ static u64 get_coherent_dma_mask(struct device *dev)
return 0; return 0;
} }
max_dma_pfn = min(max_pfn, arm_dma_pfn_limit);
/* /*
* If the mask allows for more memory than we can address, * If the mask allows for more memory than we can address,
* and we actually have that much memory, then fail the * and we actually have that much memory, then fail the
...@@ -180,7 +185,7 @@ static u64 get_coherent_dma_mask(struct device *dev) ...@@ -180,7 +185,7 @@ static u64 get_coherent_dma_mask(struct device *dev)
*/ */
if (sizeof(mask) != sizeof(dma_addr_t) && if (sizeof(mask) != sizeof(dma_addr_t) &&
mask > (dma_addr_t)~0 && mask > (dma_addr_t)~0 &&
dma_to_pfn(dev, ~0) > arm_dma_pfn_limit) { dma_to_pfn(dev, ~0) > max_dma_pfn) {
dev_warn(dev, "Coherent DMA mask %#llx is larger than dma_addr_t allows\n", dev_warn(dev, "Coherent DMA mask %#llx is larger than dma_addr_t allows\n",
mask); mask);
dev_warn(dev, "Driver did not use or check the return value from dma_set_coherent_mask()?\n"); dev_warn(dev, "Driver did not use or check the return value from dma_set_coherent_mask()?\n");
...@@ -192,7 +197,7 @@ static u64 get_coherent_dma_mask(struct device *dev) ...@@ -192,7 +197,7 @@ static u64 get_coherent_dma_mask(struct device *dev)
* fits within the allowable addresses which we can * fits within the allowable addresses which we can
* allocate. * allocate.
*/ */
if (dma_to_pfn(dev, mask) < arm_dma_pfn_limit) { if (dma_to_pfn(dev, mask) < max_dma_pfn) {
dev_warn(dev, "Coherent DMA mask %#llx (pfn %#lx-%#lx) covers a smaller range of system memory than the DMA zone pfn 0x0-%#lx\n", dev_warn(dev, "Coherent DMA mask %#llx (pfn %#lx-%#lx) covers a smaller range of system memory than the DMA zone pfn 0x0-%#lx\n",
mask, mask,
dma_to_pfn(dev, 0), dma_to_pfn(dev, mask) + 1, dma_to_pfn(dev, 0), dma_to_pfn(dev, mask) + 1,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment