summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGary King <gking@nvidia.com>2010-06-22 09:41:49 -0700
committerGary King <gking@nvidia.com>2010-06-22 15:02:20 -0700
commit972c0096a9c6b35872110fa482fb4d2194a35ca8 (patch)
tree158d3bd0be7df637e5f86c22f0d58169c785daa6
parentf977a657fc6552a20d9ca0205f8b75239bda2d78 (diff)
[ARM] dmabounce: add support for low bitmasks in dmabounce
some systems have devices which require DMA bounce buffers due to alignment restrictions rather than address window restrictions. detect when a device's DMA mask has low bits set to zero and treat this as an alignment for DMA pool allocations, but ignore the low bits for DMA valid window comparisons. Change-Id: I1cdce4ff8f928d90af4b92ff3822996599c47bdc Reviewed-on: http://git-master.nvidia.com/r/3004 Reviewed-by: Michael Hsu <mhsu@nvidia.com> Tested-by: Michael Hsu <mhsu@nvidia.com> Reviewed-by: Gary King <gking@nvidia.com>
-rw-r--r--arch/arm/common/dmabounce.c12
-rw-r--r--arch/arm/mm/dma-mapping.c1
2 files changed, 11 insertions, 2 deletions
diff --git a/arch/arm/common/dmabounce.c b/arch/arm/common/dmabounce.c
index bdd6f3f50221..bd8348017da1 100644
--- a/arch/arm/common/dmabounce.c
+++ b/arch/arm/common/dmabounce.c
@@ -235,6 +235,7 @@ static inline dma_addr_t map_single(struct device *dev, void *ptr, size_t size,
unsigned long mask = *dev->dma_mask;
unsigned long limit;
+ mask = (mask - 1) | mask;
limit = (mask + 1) & ~mask;
if (limit && size > limit) {
dev_err(dev, "DMA mapping too big (requested %#x "
@@ -455,10 +456,17 @@ EXPORT_SYMBOL(dmabounce_sync_for_device);
static int dmabounce_init_pool(struct dmabounce_pool *pool, struct device *dev,
const char *name, unsigned long size)
{
+ unsigned int align = 0;
+ if (!(*dev->dma_mask & 0x1))
+ align = 1 << ffs(*dev->dma_mask);
+
+ if (align & (align-1)) {
+ dev_warn(dev, "invalid DMA mask %#llx\n", *dev->dma_mask);
+ return -ENOMEM;
+ }
pool->size = size;
DO_STATS(pool->allocs = 0);
- pool->pool = dma_pool_create(name, dev, size,
- 0 /* byte alignment */,
+ pool->pool = dma_pool_create(name, dev, size, align,
0 /* no page-crossing issues */);
return pool->pool ? 0 : -ENOMEM;
diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c
index daefd01d3e4c..afa797ff4393 100644
--- a/arch/arm/mm/dma-mapping.c
+++ b/arch/arm/mm/dma-mapping.c
@@ -42,6 +42,7 @@ static u64 get_coherent_dma_mask(struct device *dev)
if (dev) {
mask = dev->coherent_dma_mask;
+ mask = (mask - 1) | mask;
/*
* Sanity check the DMA mask - it must be non-zero, and