diff options
author | Gary King <gking@nvidia.com> | 2010-06-22 09:41:49 -0700 |
---|---|---|
committer | Gary King <gking@nvidia.com> | 2010-06-22 15:02:20 -0700 |
commit | 972c0096a9c6b35872110fa482fb4d2194a35ca8 (patch) | |
tree | 158d3bd0be7df637e5f86c22f0d58169c785daa6 | |
parent | f977a657fc6552a20d9ca0205f8b75239bda2d78 (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.c | 12 | ||||
-rw-r--r-- | arch/arm/mm/dma-mapping.c | 1 |
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 |