* [PATCH 00/10] dmabounce cleanups
@ 2011-07-04 8:47 Russell King - ARM Linux
2011-07-04 8:47 ` [PATCH 01/10] ARM: dmabounce: fix map_single() error return value Russell King - ARM Linux
` (9 more replies)
0 siblings, 10 replies; 11+ messages in thread
From: Russell King - ARM Linux @ 2011-07-04 8:47 UTC (permalink / raw)
To: linux-arm-kernel
This patch series cleans up the DMA bounce code with the following in mind:
1. Fix the map_single failure case to return the correct dma_addr_t
indicating failure.
2. Allow __dma_map_page() to work for non-bounced highmem pages.
3. Get rid of the global dma_needs_bounce function, passing it at
registration time.
Without this patch set, enabling DMA bounce support causes the DMA API to
fail all attempts to map highmem pages whether or not they will be using
the DMA bounce API. We address that in this patch set, but DMA bounce
itself will still not permit highmem pages.
The first patch in the series fixing the failure return value will be
queued for -rc and stable trees.
^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH 01/10] ARM: dmabounce: fix map_single() error return value
2011-07-04 8:47 [PATCH 00/10] dmabounce cleanups Russell King - ARM Linux
@ 2011-07-04 8:47 ` Russell King - ARM Linux
2011-07-04 8:48 ` [PATCH 02/10] ARM: dma-mapping: define dma_(un)?map_single in terms of dma_(un)?map_page Russell King - ARM Linux
` (8 subsequent siblings)
9 siblings, 0 replies; 11+ messages in thread
From: Russell King - ARM Linux @ 2011-07-04 8:47 UTC (permalink / raw)
To: linux-arm-kernel
When map_single() is unable to obtain a safe buffer, we must return
the dma_addr_t error value, which is ~0 rather than 0.
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
---
arch/arm/common/dmabounce.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/arch/arm/common/dmabounce.c b/arch/arm/common/dmabounce.c
index e568163..841df7d 100644
--- a/arch/arm/common/dmabounce.c
+++ b/arch/arm/common/dmabounce.c
@@ -255,7 +255,7 @@ static inline dma_addr_t map_single(struct device *dev, void *ptr, size_t size,
if (buf == 0) {
dev_err(dev, "%s: unable to map unsafe buffer %p!\n",
__func__, ptr);
- return 0;
+ return ~0;
}
dev_dbg(dev,
--
1.7.4.4
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH 02/10] ARM: dma-mapping: define dma_(un)?map_single in terms of dma_(un)?map_page
2011-07-04 8:47 [PATCH 00/10] dmabounce cleanups Russell King - ARM Linux
2011-07-04 8:47 ` [PATCH 01/10] ARM: dmabounce: fix map_single() error return value Russell King - ARM Linux
@ 2011-07-04 8:48 ` Russell King - ARM Linux
2011-07-04 8:48 ` [PATCH 03/10] ARM: dmabounce: avoid needless valid_dma_direction() check Russell King - ARM Linux
` (7 subsequent siblings)
9 siblings, 0 replies; 11+ messages in thread
From: Russell King - ARM Linux @ 2011-07-04 8:48 UTC (permalink / raw)
To: linux-arm-kernel
Use dma_map_page()/dma_unmap_page() internals to handle dma_map_single()
and dma_unmap_single().
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
---
arch/arm/common/dmabounce.c | 28 ----------------------------
arch/arm/include/asm/dma-mapping.h | 31 +++++++++----------------------
2 files changed, 9 insertions(+), 50 deletions(-)
diff --git a/arch/arm/common/dmabounce.c b/arch/arm/common/dmabounce.c
index 841df7d..8a0588b 100644
--- a/arch/arm/common/dmabounce.c
+++ b/arch/arm/common/dmabounce.c
@@ -328,34 +328,6 @@ static inline void unmap_single(struct device *dev, dma_addr_t dma_addr,
* substitute the safe buffer for the unsafe one.
* (basically move the buffer from an unsafe area to a safe one)
*/
-dma_addr_t __dma_map_single(struct device *dev, void *ptr, size_t size,
- enum dma_data_direction dir)
-{
- dev_dbg(dev, "%s(ptr=%p,size=%d,dir=%x)\n",
- __func__, ptr, size, dir);
-
- BUG_ON(!valid_dma_direction(dir));
-
- return map_single(dev, ptr, size, dir);
-}
-EXPORT_SYMBOL(__dma_map_single);
-
-/*
- * see if a mapped address was really a "safe" buffer and if so, copy
- * the data from the safe buffer back to the unsafe buffer and free up
- * the safe buffer. (basically return things back to the way they
- * should be)
- */
-void __dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size,
- enum dma_data_direction dir)
-{
- dev_dbg(dev, "%s(ptr=%p,size=%d,dir=%x)\n",
- __func__, (void *) dma_addr, size, dir);
-
- unmap_single(dev, dma_addr, size, dir);
-}
-EXPORT_SYMBOL(__dma_unmap_single);
-
dma_addr_t __dma_map_page(struct device *dev, struct page *page,
unsigned long offset, size_t size, enum dma_data_direction dir)
{
diff --git a/arch/arm/include/asm/dma-mapping.h b/arch/arm/include/asm/dma-mapping.h
index 4fff837..d2903d0 100644
--- a/arch/arm/include/asm/dma-mapping.h
+++ b/arch/arm/include/asm/dma-mapping.h
@@ -298,10 +298,6 @@ extern int dma_needs_bounce(struct device*, dma_addr_t, size_t);
/*
* The DMA API, implemented by dmabounce.c. See below for descriptions.
*/
-extern dma_addr_t __dma_map_single(struct device *, void *, size_t,
- enum dma_data_direction);
-extern void __dma_unmap_single(struct device *, dma_addr_t, size_t,
- enum dma_data_direction);
extern dma_addr_t __dma_map_page(struct device *, struct page *,
unsigned long, size_t, enum dma_data_direction);
extern void __dma_unmap_page(struct device *, dma_addr_t, size_t,
@@ -328,13 +324,6 @@ static inline int dmabounce_sync_for_device(struct device *d, dma_addr_t addr,
}
-static inline dma_addr_t __dma_map_single(struct device *dev, void *cpu_addr,
- size_t size, enum dma_data_direction dir)
-{
- __dma_single_cpu_to_dev(cpu_addr, size, dir);
- return virt_to_dma(dev, cpu_addr);
-}
-
static inline dma_addr_t __dma_map_page(struct device *dev, struct page *page,
unsigned long offset, size_t size, enum dma_data_direction dir)
{
@@ -342,12 +331,6 @@ static inline dma_addr_t __dma_map_page(struct device *dev, struct page *page,
return pfn_to_dma(dev, page_to_pfn(page)) + offset;
}
-static inline void __dma_unmap_single(struct device *dev, dma_addr_t handle,
- size_t size, enum dma_data_direction dir)
-{
- __dma_single_dev_to_cpu(dma_to_virt(dev, handle), size, dir);
-}
-
static inline void __dma_unmap_page(struct device *dev, dma_addr_t handle,
size_t size, enum dma_data_direction dir)
{
@@ -373,14 +356,18 @@ static inline void __dma_unmap_page(struct device *dev, dma_addr_t handle,
static inline dma_addr_t dma_map_single(struct device *dev, void *cpu_addr,
size_t size, enum dma_data_direction dir)
{
+ unsigned long offset;
+ struct page *page;
dma_addr_t addr;
+ BUG_ON(!virt_addr_valid(cpu_addr));
+ BUG_ON(!virt_addr_valid(cpu_addr + size - 1));
BUG_ON(!valid_dma_direction(dir));
- addr = __dma_map_single(dev, cpu_addr, size, dir);
- debug_dma_map_page(dev, virt_to_page(cpu_addr),
- (unsigned long)cpu_addr & ~PAGE_MASK, size,
- dir, addr, true);
+ page = virt_to_page(cpu_addr);
+ offset = (unsigned long)cpu_addr & ~PAGE_MASK;
+ addr = __dma_map_page(dev, page, offset, size, dir);
+ debug_dma_map_page(dev, page, offset, size, dir, addr, true);
return addr;
}
@@ -430,7 +417,7 @@ static inline void dma_unmap_single(struct device *dev, dma_addr_t handle,
size_t size, enum dma_data_direction dir)
{
debug_dma_unmap_page(dev, handle, size, dir, true);
- __dma_unmap_single(dev, handle, size, dir);
+ __dma_unmap_page(dev, handle, size, dir);
}
/**
--
1.7.4.4
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH 03/10] ARM: dmabounce: avoid needless valid_dma_direction() check
2011-07-04 8:47 [PATCH 00/10] dmabounce cleanups Russell King - ARM Linux
2011-07-04 8:47 ` [PATCH 01/10] ARM: dmabounce: fix map_single() error return value Russell King - ARM Linux
2011-07-04 8:48 ` [PATCH 02/10] ARM: dma-mapping: define dma_(un)?map_single in terms of dma_(un)?map_page Russell King - ARM Linux
@ 2011-07-04 8:48 ` Russell King - ARM Linux
2011-07-04 8:48 ` [PATCH 04/10] ARM: dmabounce: separate out decision to bounce Russell King - ARM Linux
` (6 subsequent siblings)
9 siblings, 0 replies; 11+ messages in thread
From: Russell King - ARM Linux @ 2011-07-04 8:48 UTC (permalink / raw)
To: linux-arm-kernel
This check is done at the DMA API level, so there's no point repeating
it here.
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
---
arch/arm/common/dmabounce.c | 2 --
1 files changed, 0 insertions(+), 2 deletions(-)
diff --git a/arch/arm/common/dmabounce.c b/arch/arm/common/dmabounce.c
index 8a0588b..3e0fa15 100644
--- a/arch/arm/common/dmabounce.c
+++ b/arch/arm/common/dmabounce.c
@@ -334,8 +334,6 @@ dma_addr_t __dma_map_page(struct device *dev, struct page *page,
dev_dbg(dev, "%s(page=%p,off=%#lx,size=%zx,dir=%x)\n",
__func__, page, offset, size, dir);
- BUG_ON(!valid_dma_direction(dir));
-
if (PageHighMem(page)) {
dev_err(dev, "DMA buffer bouncing of HIGHMEM pages "
"is not supported\n");
--
1.7.4.4
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH 04/10] ARM: dmabounce: separate out decision to bounce
2011-07-04 8:47 [PATCH 00/10] dmabounce cleanups Russell King - ARM Linux
` (2 preceding siblings ...)
2011-07-04 8:48 ` [PATCH 03/10] ARM: dmabounce: avoid needless valid_dma_direction() check Russell King - ARM Linux
@ 2011-07-04 8:48 ` Russell King - ARM Linux
2011-07-04 8:49 ` [PATCH 05/10] ARM: dmabounce: move decision for bouncing into __dma_map_page() Russell King - ARM Linux
` (5 subsequent siblings)
9 siblings, 0 replies; 11+ messages in thread
From: Russell King - ARM Linux @ 2011-07-04 8:48 UTC (permalink / raw)
To: linux-arm-kernel
Move the decision to perform DMA bouncing out of map_single() into its
own stand-alone function.
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
---
arch/arm/common/dmabounce.c | 46 ++++++++++++++++++++++++++----------------
1 files changed, 28 insertions(+), 18 deletions(-)
diff --git a/arch/arm/common/dmabounce.c b/arch/arm/common/dmabounce.c
index 3e0fa15..643e1d6 100644
--- a/arch/arm/common/dmabounce.c
+++ b/arch/arm/common/dmabounce.c
@@ -219,36 +219,46 @@ static struct safe_buffer *find_safe_buffer_dev(struct device *dev,
return find_safe_buffer(dev->archdata.dmabounce, dma_addr);
}
-static inline dma_addr_t map_single(struct device *dev, void *ptr, size_t size,
- enum dma_data_direction dir)
+static int needs_bounce(struct device *dev, dma_addr_t dma_addr, size_t size)
{
- struct dmabounce_device_info *device_info = dev->archdata.dmabounce;
- dma_addr_t dma_addr;
- int needs_bounce = 0;
-
- if (device_info)
- DO_STATS ( device_info->map_op_count++ );
-
- dma_addr = virt_to_dma(dev, ptr);
+ if (!dev || !dev->archdata.dmabounce)
+ return 0;
if (dev->dma_mask) {
- unsigned long mask = *dev->dma_mask;
- unsigned long limit;
+ unsigned long limit, mask = *dev->dma_mask;
limit = (mask + 1) & ~mask;
if (limit && size > limit) {
dev_err(dev, "DMA mapping too big (requested %#x "
"mask %#Lx)\n", size, *dev->dma_mask);
- return ~0;
+ return -E2BIG;
}
- /*
- * Figure out if we need to bounce from the DMA mask.
- */
- needs_bounce = (dma_addr | (dma_addr + size - 1)) & ~mask;
+ /* Figure out if we need to bounce from the DMA mask. */
+ if ((dma_addr | (dma_addr + size - 1)) & ~mask)
+ return 1;
}
- if (device_info && (needs_bounce || dma_needs_bounce(dev, dma_addr, size))) {
+ return dma_needs_bounce(dev, dma_addr, size) ? 1 : 0;
+}
+
+static inline dma_addr_t map_single(struct device *dev, void *ptr, size_t size,
+ enum dma_data_direction dir)
+{
+ struct dmabounce_device_info *device_info = dev->archdata.dmabounce;
+ dma_addr_t dma_addr;
+ int ret;
+
+ if (device_info)
+ DO_STATS ( device_info->map_op_count++ );
+
+ dma_addr = virt_to_dma(dev, ptr);
+
+ ret = needs_bounce(dev, dma_addr, size);
+ if (ret < 0)
+ return ~0;
+
+ if (ret > 0) {
struct safe_buffer *buf;
buf = alloc_safe_buffer(device_info, ptr, size, dir);
--
1.7.4.4
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH 05/10] ARM: dmabounce: move decision for bouncing into __dma_map_page()
2011-07-04 8:47 [PATCH 00/10] dmabounce cleanups Russell King - ARM Linux
` (3 preceding siblings ...)
2011-07-04 8:48 ` [PATCH 04/10] ARM: dmabounce: separate out decision to bounce Russell King - ARM Linux
@ 2011-07-04 8:49 ` Russell King - ARM Linux
2011-07-04 8:49 ` [PATCH 06/10] ARM: dmabounce: remove useless pr_err Russell King - ARM Linux
` (4 subsequent siblings)
9 siblings, 0 replies; 11+ messages in thread
From: Russell King - ARM Linux @ 2011-07-04 8:49 UTC (permalink / raw)
To: linux-arm-kernel
Move the decision whether to bounce into __dma_map_page(), before
the check for high pages. This avoids triggering the high page
check for devices which aren't using dmabounce. Fix the unmap path
to cope too.
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
---
arch/arm/common/dmabounce.c | 124 ++++++++++++++++++++-----------------------
1 files changed, 58 insertions(+), 66 deletions(-)
diff --git a/arch/arm/common/dmabounce.c b/arch/arm/common/dmabounce.c
index 643e1d6..6ae292c 100644
--- a/arch/arm/common/dmabounce.c
+++ b/arch/arm/common/dmabounce.c
@@ -246,88 +246,58 @@ static inline dma_addr_t map_single(struct device *dev, void *ptr, size_t size,
enum dma_data_direction dir)
{
struct dmabounce_device_info *device_info = dev->archdata.dmabounce;
- dma_addr_t dma_addr;
- int ret;
+ struct safe_buffer *buf;
if (device_info)
DO_STATS ( device_info->map_op_count++ );
- dma_addr = virt_to_dma(dev, ptr);
-
- ret = needs_bounce(dev, dma_addr, size);
- if (ret < 0)
+ buf = alloc_safe_buffer(device_info, ptr, size, dir);
+ if (buf == 0) {
+ dev_err(dev, "%s: unable to map unsafe buffer %p!\n",
+ __func__, ptr);
return ~0;
+ }
- if (ret > 0) {
- struct safe_buffer *buf;
-
- buf = alloc_safe_buffer(device_info, ptr, size, dir);
- if (buf == 0) {
- dev_err(dev, "%s: unable to map unsafe buffer %p!\n",
- __func__, ptr);
- return ~0;
- }
-
- dev_dbg(dev,
- "%s: unsafe buffer %p (dma=%#x) mapped to %p (dma=%#x)\n",
- __func__, buf->ptr, virt_to_dma(dev, buf->ptr),
- buf->safe, buf->safe_dma_addr);
-
- if ((dir == DMA_TO_DEVICE) ||
- (dir == DMA_BIDIRECTIONAL)) {
- dev_dbg(dev, "%s: copy unsafe %p to safe %p, size %d\n",
- __func__, ptr, buf->safe, size);
- memcpy(buf->safe, ptr, size);
- }
- ptr = buf->safe;
+ dev_dbg(dev, "%s: unsafe buffer %p (dma=%#x) mapped to %p (dma=%#x)\n",
+ __func__, buf->ptr, virt_to_dma(dev, buf->ptr),
+ buf->safe, buf->safe_dma_addr);
- dma_addr = buf->safe_dma_addr;
- } else {
- /*
- * We don't need to sync the DMA buffer since
- * it was allocated via the coherent allocators.
- */
- __dma_single_cpu_to_dev(ptr, size, dir);
+ if (dir == DMA_TO_DEVICE || dir == DMA_BIDIRECTIONAL) {
+ dev_dbg(dev, "%s: copy unsafe %p to safe %p, size %d\n",
+ __func__, ptr, buf->safe, size);
+ memcpy(buf->safe, ptr, size);
}
- return dma_addr;
+ return buf->safe_dma_addr;
}
-static inline void unmap_single(struct device *dev, dma_addr_t dma_addr,
+static inline void unmap_single(struct device *dev, struct safe_buffer *buf,
size_t size, enum dma_data_direction dir)
{
- struct safe_buffer *buf = find_safe_buffer_dev(dev, dma_addr, "unmap");
-
- if (buf) {
- BUG_ON(buf->size != size);
- BUG_ON(buf->direction != dir);
+ BUG_ON(buf->size != size);
+ BUG_ON(buf->direction != dir);
- dev_dbg(dev,
- "%s: unsafe buffer %p (dma=%#x) mapped to %p (dma=%#x)\n",
- __func__, buf->ptr, virt_to_dma(dev, buf->ptr),
- buf->safe, buf->safe_dma_addr);
+ dev_dbg(dev, "%s: unsafe buffer %p (dma=%#x) mapped to %p (dma=%#x)\n",
+ __func__, buf->ptr, virt_to_dma(dev, buf->ptr),
+ buf->safe, buf->safe_dma_addr);
- DO_STATS(dev->archdata.dmabounce->bounce_count++);
+ DO_STATS(dev->archdata.dmabounce->bounce_count++);
- if (dir == DMA_FROM_DEVICE || dir == DMA_BIDIRECTIONAL) {
- void *ptr = buf->ptr;
+ if (dir == DMA_FROM_DEVICE || dir == DMA_BIDIRECTIONAL) {
+ void *ptr = buf->ptr;
- dev_dbg(dev,
- "%s: copy back safe %p to unsafe %p size %d\n",
- __func__, buf->safe, ptr, size);
- memcpy(ptr, buf->safe, size);
+ dev_dbg(dev, "%s: copy back safe %p to unsafe %p size %d\n",
+ __func__, buf->safe, ptr, size);
+ memcpy(ptr, buf->safe, size);
- /*
- * Since we may have written to a page cache page,
- * we need to ensure that the data will be coherent
- * with user mappings.
- */
- __cpuc_flush_dcache_area(ptr, size);
- }
- free_safe_buffer(dev->archdata.dmabounce, buf);
- } else {
- __dma_single_dev_to_cpu(dma_to_virt(dev, dma_addr), size, dir);
+ /*
+ * Since we may have written to a page cache page,
+ * we need to ensure that the data will be coherent
+ * with user mappings.
+ */
+ __cpuc_flush_dcache_area(ptr, size);
}
+ free_safe_buffer(dev->archdata.dmabounce, buf);
}
/* ************************************************** */
@@ -341,12 +311,25 @@ static inline void unmap_single(struct device *dev, dma_addr_t dma_addr,
dma_addr_t __dma_map_page(struct device *dev, struct page *page,
unsigned long offset, size_t size, enum dma_data_direction dir)
{
+ dma_addr_t dma_addr;
+ int ret;
+
dev_dbg(dev, "%s(page=%p,off=%#lx,size=%zx,dir=%x)\n",
__func__, page, offset, size, dir);
+ dma_addr = pfn_to_dma(dev, page_to_pfn(page)) + offset;
+
+ ret = needs_bounce(dev, dma_addr, size);
+ if (ret < 0)
+ return ~0;
+
+ if (ret == 0) {
+ __dma_page_cpu_to_dev(page, offset, size, dir);
+ return dma_addr;
+ }
+
if (PageHighMem(page)) {
- dev_err(dev, "DMA buffer bouncing of HIGHMEM pages "
- "is not supported\n");
+ dev_err(dev, "DMA buffer bouncing of HIGHMEM pages is not supported\n");
return ~0;
}
@@ -363,10 +346,19 @@ EXPORT_SYMBOL(__dma_map_page);
void __dma_unmap_page(struct device *dev, dma_addr_t dma_addr, size_t size,
enum dma_data_direction dir)
{
+ struct safe_buffer *buf;
+
dev_dbg(dev, "%s(ptr=%p,size=%d,dir=%x)\n",
__func__, (void *) dma_addr, size, dir);
- unmap_single(dev, dma_addr, size, dir);
+ buf = find_safe_buffer_dev(dev, dma_addr, __func__);
+ if (!buf) {
+ __dma_page_dev_to_cpu(pfn_to_page(dma_to_pfn(dev, dma_addr)),
+ dma_addr & ~PAGE_MASK, size, dir);
+ return;
+ }
+
+ unmap_single(dev, buf, size, dir);
}
EXPORT_SYMBOL(__dma_unmap_page);
--
1.7.4.4
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH 06/10] ARM: dmabounce: remove useless pr_err
2011-07-04 8:47 [PATCH 00/10] dmabounce cleanups Russell King - ARM Linux
` (4 preceding siblings ...)
2011-07-04 8:49 ` [PATCH 05/10] ARM: dmabounce: move decision for bouncing into __dma_map_page() Russell King - ARM Linux
@ 2011-07-04 8:49 ` Russell King - ARM Linux
2011-07-04 8:49 ` [PATCH 07/10] ARM: dmabounce: check pointer against NULL not 0 Russell King - ARM Linux
` (3 subsequent siblings)
9 siblings, 0 replies; 11+ messages in thread
From: Russell King - ARM Linux @ 2011-07-04 8:49 UTC (permalink / raw)
To: linux-arm-kernel
We already check that dev != NULL, so this won't be reached.
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
---
arch/arm/common/dmabounce.c | 5 +----
1 files changed, 1 insertions(+), 4 deletions(-)
diff --git a/arch/arm/common/dmabounce.c b/arch/arm/common/dmabounce.c
index 6ae292c..0077c1b 100644
--- a/arch/arm/common/dmabounce.c
+++ b/arch/arm/common/dmabounce.c
@@ -210,10 +210,7 @@ static struct safe_buffer *find_safe_buffer_dev(struct device *dev,
if (!dev || !dev->archdata.dmabounce)
return NULL;
if (dma_mapping_error(dev, dma_addr)) {
- if (dev)
- dev_err(dev, "Trying to %s invalid mapping\n", where);
- else
- pr_err("unknown device: Trying to %s invalid mapping\n", where);
+ dev_err(dev, "Trying to %s invalid mapping\n", where);
return NULL;
}
return find_safe_buffer(dev->archdata.dmabounce, dma_addr);
--
1.7.4.4
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH 07/10] ARM: dmabounce: check pointer against NULL not 0
2011-07-04 8:47 [PATCH 00/10] dmabounce cleanups Russell King - ARM Linux
` (5 preceding siblings ...)
2011-07-04 8:49 ` [PATCH 06/10] ARM: dmabounce: remove useless pr_err Russell King - ARM Linux
@ 2011-07-04 8:49 ` Russell King - ARM Linux
2011-07-04 8:50 ` [PATCH 08/10] ARM: dmabounce: correct unmap_single dev_dbg Russell King - ARM Linux
` (2 subsequent siblings)
9 siblings, 0 replies; 11+ messages in thread
From: Russell King - ARM Linux @ 2011-07-04 8:49 UTC (permalink / raw)
To: linux-arm-kernel
Pointers should be checked against NULL rather than 0, otherwise we
get sparse warnings.
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
---
arch/arm/common/dmabounce.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/arch/arm/common/dmabounce.c b/arch/arm/common/dmabounce.c
index 0077c1b..b4a8759 100644
--- a/arch/arm/common/dmabounce.c
+++ b/arch/arm/common/dmabounce.c
@@ -249,7 +249,7 @@ static inline dma_addr_t map_single(struct device *dev, void *ptr, size_t size,
DO_STATS ( device_info->map_op_count++ );
buf = alloc_safe_buffer(device_info, ptr, size, dir);
- if (buf == 0) {
+ if (buf == NULL) {
dev_err(dev, "%s: unable to map unsafe buffer %p!\n",
__func__, ptr);
return ~0;
--
1.7.4.4
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH 08/10] ARM: dmabounce: correct unmap_single dev_dbg
2011-07-04 8:47 [PATCH 00/10] dmabounce cleanups Russell King - ARM Linux
` (6 preceding siblings ...)
2011-07-04 8:49 ` [PATCH 07/10] ARM: dmabounce: check pointer against NULL not 0 Russell King - ARM Linux
@ 2011-07-04 8:50 ` Russell King - ARM Linux
2011-07-04 8:50 ` [PATCH 09/10] ARM: dmabounce: get rid of dma_needs_bounce global function Russell King - ARM Linux
2011-07-04 8:50 ` [PATCH 10/10] ARM: dmabounce: no need to check dev->bus type in needs_bounce function Russell King - ARM Linux
9 siblings, 0 replies; 11+ messages in thread
From: Russell King - ARM Linux @ 2011-07-04 8:50 UTC (permalink / raw)
To: linux-arm-kernel
DMA addresses should not be casted to void * for printing. Fix
that to be consistent with the rest of the file.
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
---
arch/arm/common/dmabounce.c | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/arch/arm/common/dmabounce.c b/arch/arm/common/dmabounce.c
index b4a8759..4f13505 100644
--- a/arch/arm/common/dmabounce.c
+++ b/arch/arm/common/dmabounce.c
@@ -345,8 +345,8 @@ void __dma_unmap_page(struct device *dev, dma_addr_t dma_addr, size_t size,
{
struct safe_buffer *buf;
- dev_dbg(dev, "%s(ptr=%p,size=%d,dir=%x)\n",
- __func__, (void *) dma_addr, size, dir);
+ dev_dbg(dev, "%s(dma=%#x,size=%d,dir=%x)\n",
+ __func__, dma_addr, size, dir);
buf = find_safe_buffer_dev(dev, dma_addr, __func__);
if (!buf) {
--
1.7.4.4
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH 09/10] ARM: dmabounce: get rid of dma_needs_bounce global function
2011-07-04 8:47 [PATCH 00/10] dmabounce cleanups Russell King - ARM Linux
` (7 preceding siblings ...)
2011-07-04 8:50 ` [PATCH 08/10] ARM: dmabounce: correct unmap_single dev_dbg Russell King - ARM Linux
@ 2011-07-04 8:50 ` Russell King - ARM Linux
2011-07-04 8:50 ` [PATCH 10/10] ARM: dmabounce: no need to check dev->bus type in needs_bounce function Russell King - ARM Linux
9 siblings, 0 replies; 11+ messages in thread
From: Russell King - ARM Linux @ 2011-07-04 8:50 UTC (permalink / raw)
To: linux-arm-kernel
Pass the device type specific needs_bounce function in at dmabounce
register time, avoiding the need for a platform specific global
function to do this.
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
---
arch/arm/common/dmabounce.c | 8 +++-
arch/arm/common/it8152.c | 17 +++++-----
arch/arm/common/sa1111.c | 60 ++++++++++++++++++-----------------
arch/arm/include/asm/dma-mapping.h | 22 +------------
arch/arm/mach-ixp4xx/common-pci.c | 12 +++---
5 files changed, 53 insertions(+), 66 deletions(-)
diff --git a/arch/arm/common/dmabounce.c b/arch/arm/common/dmabounce.c
index 4f13505..595ecd2 100644
--- a/arch/arm/common/dmabounce.c
+++ b/arch/arm/common/dmabounce.c
@@ -79,6 +79,8 @@ struct dmabounce_device_info {
struct dmabounce_pool large;
rwlock_t lock;
+
+ int (*needs_bounce)(struct device *, dma_addr_t, size_t);
};
#ifdef STATS
@@ -236,7 +238,7 @@ static int needs_bounce(struct device *dev, dma_addr_t dma_addr, size_t size)
return 1;
}
- return dma_needs_bounce(dev, dma_addr, size) ? 1 : 0;
+ return !!dev->archdata.dmabounce->needs_bounce(dev, dma_addr, size);
}
static inline dma_addr_t map_single(struct device *dev, void *ptr, size_t size,
@@ -430,7 +432,8 @@ static int dmabounce_init_pool(struct dmabounce_pool *pool, struct device *dev,
}
int dmabounce_register_dev(struct device *dev, unsigned long small_buffer_size,
- unsigned long large_buffer_size)
+ unsigned long large_buffer_size,
+ int (*needs_bounce_fn)(struct device *, dma_addr_t, size_t))
{
struct dmabounce_device_info *device_info;
int ret;
@@ -466,6 +469,7 @@ int dmabounce_register_dev(struct device *dev, unsigned long small_buffer_size,
device_info->dev = dev;
INIT_LIST_HEAD(&device_info->safe_buffers);
rwlock_init(&device_info->lock);
+ device_info->needs_bounce = needs_bounce_fn;
#ifdef STATS
device_info->total_allocs = 0;
diff --git a/arch/arm/common/it8152.c b/arch/arm/common/it8152.c
index 7a21927..80b49e1 100644
--- a/arch/arm/common/it8152.c
+++ b/arch/arm/common/it8152.c
@@ -243,6 +243,13 @@ static struct resource it8152_mem = {
* ITE8152 chip can address up to 64MByte, so all the devices
* connected to ITE8152 (PCI and USB) should have limited DMA window
*/
+static int it8152_needs_bounce(struct device *dev, dma_addr_t dma_addr, size_t size)
+{
+ dev_dbg(dev, "%s: dma_addr %08x, size %08x\n",
+ __func__, dma_addr, size);
+ return dev->bus == &pci_bus_type &&
+ (dma_addr + size - PHYS_OFFSET) >= SZ_64M;
+}
/*
* Setup DMA mask to 64MB on devices connected to ITE8152. Ignore all
@@ -254,7 +261,7 @@ static int it8152_pci_platform_notify(struct device *dev)
if (dev->dma_mask)
*dev->dma_mask = (SZ_64M - 1) | PHYS_OFFSET;
dev->coherent_dma_mask = (SZ_64M - 1) | PHYS_OFFSET;
- dmabounce_register_dev(dev, 2048, 4096);
+ dmabounce_register_dev(dev, 2048, 4096, it8152_needs_bounce);
}
return 0;
}
@@ -267,14 +274,6 @@ static int it8152_pci_platform_notify_remove(struct device *dev)
return 0;
}
-int dma_needs_bounce(struct device *dev, dma_addr_t dma_addr, size_t size)
-{
- dev_dbg(dev, "%s: dma_addr %08x, size %08x\n",
- __func__, dma_addr, size);
- return (dev->bus == &pci_bus_type) &&
- ((dma_addr + size - PHYS_OFFSET) >= SZ_64M);
-}
-
int dma_set_coherent_mask(struct device *dev, u64 mask)
{
if (mask >= PHYS_OFFSET + SZ_64M - 1)
diff --git a/arch/arm/common/sa1111.c b/arch/arm/common/sa1111.c
index 9c49a46..0569de6 100644
--- a/arch/arm/common/sa1111.c
+++ b/arch/arm/common/sa1111.c
@@ -579,7 +579,36 @@ sa1111_configure_smc(struct sa1111 *sachip, int sdram, unsigned int drac,
sachip->dev->coherent_dma_mask &= sa1111_dma_mask[drac >> 2];
}
+#endif
+#ifdef CONFIG_DMABOUNCE
+/*
+ * According to the "Intel StrongARM SA-1111 Microprocessor Companion
+ * Chip Specification Update" (June 2000), erratum #7, there is a
+ * significant bug in the SA1111 SDRAM shared memory controller. If
+ * an access to a region of memory above 1MB relative to the bank base,
+ * it is important that address bit 10 _NOT_ be asserted. Depending
+ * on the configuration of the RAM, bit 10 may correspond to one
+ * of several different (processor-relative) address bits.
+ *
+ * This routine only identifies whether or not a given DMA address
+ * is susceptible to the bug.
+ *
+ * This should only get called for sa1111_device types due to the
+ * way we configure our device dma_masks.
+ */
+static int sa1111_needs_bounce(struct device *dev, dma_addr_t addr, size_t size)
+{
+ /*
+ * Section 4.6 of the "Intel StrongARM SA-1111 Development Module
+ * User's Guide" mentions that jumpers R51 and R52 control the
+ * target of SA-1111 DMA (either SDRAM bank 0 on Assabet, or
+ * SDRAM bank 1 on Neponset). The default configuration selects
+ * Assabet, so any address in bank 1 is necessarily invalid.
+ */
+ return (machine_is_assabet() || machine_is_pfs168()) &&
+ (addr >= 0xc8000000 || (addr + size) >= 0xc8000000);
+}
#endif
static void sa1111_dev_release(struct device *_dev)
@@ -644,7 +673,8 @@ sa1111_init_one_child(struct sa1111 *sachip, struct resource *parent,
dev->dev.dma_mask = &dev->dma_mask;
if (dev->dma_mask != 0xffffffffUL) {
- ret = dmabounce_register_dev(&dev->dev, 1024, 4096);
+ ret = dmabounce_register_dev(&dev->dev, 1024, 4096,
+ sa1111_needs_bounce);
if (ret) {
dev_err(&dev->dev, "SA1111: Failed to register"
" with dmabounce\n");
@@ -818,34 +848,6 @@ static void __sa1111_remove(struct sa1111 *sachip)
kfree(sachip);
}
-/*
- * According to the "Intel StrongARM SA-1111 Microprocessor Companion
- * Chip Specification Update" (June 2000), erratum #7, there is a
- * significant bug in the SA1111 SDRAM shared memory controller. If
- * an access to a region of memory above 1MB relative to the bank base,
- * it is important that address bit 10 _NOT_ be asserted. Depending
- * on the configuration of the RAM, bit 10 may correspond to one
- * of several different (processor-relative) address bits.
- *
- * This routine only identifies whether or not a given DMA address
- * is susceptible to the bug.
- *
- * This should only get called for sa1111_device types due to the
- * way we configure our device dma_masks.
- */
-int dma_needs_bounce(struct device *dev, dma_addr_t addr, size_t size)
-{
- /*
- * Section 4.6 of the "Intel StrongARM SA-1111 Development Module
- * User's Guide" mentions that jumpers R51 and R52 control the
- * target of SA-1111 DMA (either SDRAM bank 0 on Assabet, or
- * SDRAM bank 1 on Neponset). The default configuration selects
- * Assabet, so any address in bank 1 is necessarily invalid.
- */
- return ((machine_is_assabet() || machine_is_pfs168()) &&
- (addr >= 0xc8000000 || (addr + size) >= 0xc8000000));
-}
-
struct sa1111_save_data {
unsigned int skcr;
unsigned int skpcr;
diff --git a/arch/arm/include/asm/dma-mapping.h b/arch/arm/include/asm/dma-mapping.h
index d2903d0..4ad2533 100644
--- a/arch/arm/include/asm/dma-mapping.h
+++ b/arch/arm/include/asm/dma-mapping.h
@@ -256,14 +256,14 @@ int dma_mmap_writecombine(struct device *, struct vm_area_struct *,
* @dev: valid struct device pointer
* @small_buf_size: size of buffers to use with small buffer pool
* @large_buf_size: size of buffers to use with large buffer pool (can be 0)
+ * @needs_bounce_fn: called to determine whether buffer needs bouncing
*
* This function should be called by low-level platform code to register
* a device as requireing DMA buffer bouncing. The function will allocate
* appropriate DMA pools for the device.
- *
*/
extern int dmabounce_register_dev(struct device *, unsigned long,
- unsigned long);
+ unsigned long, int (*)(struct device *, dma_addr_t, size_t));
/**
* dmabounce_unregister_dev
@@ -277,24 +277,6 @@ extern int dmabounce_register_dev(struct device *, unsigned long,
*/
extern void dmabounce_unregister_dev(struct device *);
-/**
- * dma_needs_bounce
- *
- * @dev: valid struct device pointer
- * @dma_handle: dma_handle of unbounced buffer
- * @size: size of region being mapped
- *
- * Platforms that utilize the dmabounce mechanism must implement
- * this function.
- *
- * The dmabounce routines call this function whenever a dma-mapping
- * is requested to determine whether a given buffer needs to be bounced
- * or not. The function must return 0 if the buffer is OK for
- * DMA access and 1 if the buffer needs to be bounced.
- *
- */
-extern int dma_needs_bounce(struct device*, dma_addr_t, size_t);
-
/*
* The DMA API, implemented by dmabounce.c. See below for descriptions.
*/
diff --git a/arch/arm/mach-ixp4xx/common-pci.c b/arch/arm/mach-ixp4xx/common-pci.c
index e9a5893..d7db10c 100644
--- a/arch/arm/mach-ixp4xx/common-pci.c
+++ b/arch/arm/mach-ixp4xx/common-pci.c
@@ -316,6 +316,11 @@ static int abort_handler(unsigned long addr, unsigned int fsr, struct pt_regs *r
}
+static int ixp4xx_needs_bounce(struct device *dev, dma_addr_t dma_addr, size_t size)
+{
+ return dev->bus == &pci_bus_type && (dma_addr + size) >= SZ_64M;
+}
+
/*
* Setup DMA mask to 64MB on PCI devices. Ignore all other devices.
*/
@@ -324,7 +329,7 @@ static int ixp4xx_pci_platform_notify(struct device *dev)
if(dev->bus == &pci_bus_type) {
*dev->dma_mask = SZ_64M - 1;
dev->coherent_dma_mask = SZ_64M - 1;
- dmabounce_register_dev(dev, 2048, 4096);
+ dmabounce_register_dev(dev, 2048, 4096, ixp4xx_needs_bounce);
}
return 0;
}
@@ -337,11 +342,6 @@ static int ixp4xx_pci_platform_notify_remove(struct device *dev)
return 0;
}
-int dma_needs_bounce(struct device *dev, dma_addr_t dma_addr, size_t size)
-{
- return (dev->bus == &pci_bus_type ) && ((dma_addr + size) >= SZ_64M);
-}
-
void __init ixp4xx_pci_preinit(void)
{
unsigned long cpuid = read_cpuid_id();
--
1.7.4.4
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH 10/10] ARM: dmabounce: no need to check dev->bus type in needs_bounce function
2011-07-04 8:47 [PATCH 00/10] dmabounce cleanups Russell King - ARM Linux
` (8 preceding siblings ...)
2011-07-04 8:50 ` [PATCH 09/10] ARM: dmabounce: get rid of dma_needs_bounce global function Russell King - ARM Linux
@ 2011-07-04 8:50 ` Russell King - ARM Linux
9 siblings, 0 replies; 11+ messages in thread
From: Russell King - ARM Linux @ 2011-07-04 8:50 UTC (permalink / raw)
To: linux-arm-kernel
As the needs_bounce function is passed at DMA bounce register time,
we already know what the device bus type is, so we don't need to check
it each time the needs_bounce function is called.
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
---
arch/arm/common/it8152.c | 3 +--
arch/arm/mach-ixp4xx/common-pci.c | 2 +-
2 files changed, 2 insertions(+), 3 deletions(-)
diff --git a/arch/arm/common/it8152.c b/arch/arm/common/it8152.c
index 80b49e1..14ad62e 100644
--- a/arch/arm/common/it8152.c
+++ b/arch/arm/common/it8152.c
@@ -247,8 +247,7 @@ static int it8152_needs_bounce(struct device *dev, dma_addr_t dma_addr, size_t s
{
dev_dbg(dev, "%s: dma_addr %08x, size %08x\n",
__func__, dma_addr, size);
- return dev->bus == &pci_bus_type &&
- (dma_addr + size - PHYS_OFFSET) >= SZ_64M;
+ return (dma_addr + size - PHYS_OFFSET) >= SZ_64M;
}
/*
diff --git a/arch/arm/mach-ixp4xx/common-pci.c b/arch/arm/mach-ixp4xx/common-pci.c
index d7db10c..e2e98bb 100644
--- a/arch/arm/mach-ixp4xx/common-pci.c
+++ b/arch/arm/mach-ixp4xx/common-pci.c
@@ -318,7 +318,7 @@ static int abort_handler(unsigned long addr, unsigned int fsr, struct pt_regs *r
static int ixp4xx_needs_bounce(struct device *dev, dma_addr_t dma_addr, size_t size)
{
- return dev->bus == &pci_bus_type && (dma_addr + size) >= SZ_64M;
+ return (dma_addr + size) >= SZ_64M;
}
/*
--
1.7.4.4
^ permalink raw reply related [flat|nested] 11+ messages in thread
end of thread, other threads:[~2011-07-04 8:50 UTC | newest]
Thread overview: 11+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2011-07-04 8:47 [PATCH 00/10] dmabounce cleanups Russell King - ARM Linux
2011-07-04 8:47 ` [PATCH 01/10] ARM: dmabounce: fix map_single() error return value Russell King - ARM Linux
2011-07-04 8:48 ` [PATCH 02/10] ARM: dma-mapping: define dma_(un)?map_single in terms of dma_(un)?map_page Russell King - ARM Linux
2011-07-04 8:48 ` [PATCH 03/10] ARM: dmabounce: avoid needless valid_dma_direction() check Russell King - ARM Linux
2011-07-04 8:48 ` [PATCH 04/10] ARM: dmabounce: separate out decision to bounce Russell King - ARM Linux
2011-07-04 8:49 ` [PATCH 05/10] ARM: dmabounce: move decision for bouncing into __dma_map_page() Russell King - ARM Linux
2011-07-04 8:49 ` [PATCH 06/10] ARM: dmabounce: remove useless pr_err Russell King - ARM Linux
2011-07-04 8:49 ` [PATCH 07/10] ARM: dmabounce: check pointer against NULL not 0 Russell King - ARM Linux
2011-07-04 8:50 ` [PATCH 08/10] ARM: dmabounce: correct unmap_single dev_dbg Russell King - ARM Linux
2011-07-04 8:50 ` [PATCH 09/10] ARM: dmabounce: get rid of dma_needs_bounce global function Russell King - ARM Linux
2011-07-04 8:50 ` [PATCH 10/10] ARM: dmabounce: no need to check dev->bus type in needs_bounce function Russell King - ARM Linux
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).