From 7f8e33546d17c7d8849be3a6623c3b6b3c9b588b Mon Sep 17 00:00:00 2001 From: Russell King Date: Tue, 6 Feb 2007 17:29:53 +0000 Subject: [ARM] Don't call consistent_sync() for DMA coherent memory Memory allocated by the coherent memory allocators will be marked uncacheable, which means it's pointless calling consistent_sync() to perform cache maintainence on this memory; it's just a waste of CPU cycles. Moreover, with the (subsequent) merge of outer cache support, it actually breaks things to call consistent_sync() on anything but direct-mapped memory. Signed-off-by: Russell King --- arch/arm/common/dmabounce.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) (limited to 'arch/arm/common/dmabounce.c') diff --git a/arch/arm/common/dmabounce.c b/arch/arm/common/dmabounce.c index 2e635b814c14..272702accd8b 100644 --- a/arch/arm/common/dmabounce.c +++ b/arch/arm/common/dmabounce.c @@ -281,10 +281,14 @@ map_single(struct device *dev, void *ptr, size_t size, ptr = buf->safe; dma_addr = buf->safe_dma_addr; + } else { + /* + * We don't need to sync the DMA buffer since + * it was allocated via the coherent allocators. + */ + consistent_sync(ptr, size, dir); } - consistent_sync(ptr, size, dir); - return dma_addr; } @@ -397,7 +401,10 @@ sync_single(struct device *dev, dma_addr_t dma_addr, size_t size, default: BUG(); } - consistent_sync(buf->safe, size, dir); + /* + * No need to sync the safe buffer - it was allocated + * via the coherent allocators. + */ } else { consistent_sync(dma_to_virt(dev, dma_addr), size, dir); } -- cgit From 953233dc9958ba2b29753d0f24e37a33a076a5f6 Mon Sep 17 00:00:00 2001 From: Catalin Marinas Date: Mon, 5 Feb 2007 14:48:08 +0100 Subject: [ARM] 4134/1: Add generic support for outer caches The outer cache can be L2 as on RealView/EB MPCore platform or even L3 or further on ARMv7 cores. This patch adds the generic support for flushing the outer cache in the DMA operations. Signed-off-by: Catalin Marinas Signed-off-by: Russell King --- arch/arm/common/dmabounce.c | 1 + 1 file changed, 1 insertion(+) (limited to 'arch/arm/common/dmabounce.c') diff --git a/arch/arm/common/dmabounce.c b/arch/arm/common/dmabounce.c index 272702accd8b..b4748e3171c6 100644 --- a/arch/arm/common/dmabounce.c +++ b/arch/arm/common/dmabounce.c @@ -338,6 +338,7 @@ unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size, */ ptr = (unsigned long)buf->ptr; dmac_clean_range(ptr, ptr + size); + outer_clean_range(__pa(ptr), __pa(ptr) + size); } free_safe_buffer(device_info, buf); } -- cgit From 7ae5a761d2ffc4cf7d3248e09f4d3da234434f30 Mon Sep 17 00:00:00 2001 From: Russell King Date: Tue, 6 Feb 2007 17:39:31 +0000 Subject: [ARM] Convert DMA cache handling to take const void * args The DMA cache handling functions take virtual addresses, but in the form of unsigned long arguments. This leads to a little confusion about what exactly they take. So, convert them to take const void * instead. Signed-off-by: Russell King --- arch/arm/common/dmabounce.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'arch/arm/common/dmabounce.c') diff --git a/arch/arm/common/dmabounce.c b/arch/arm/common/dmabounce.c index b4748e3171c6..2362c498f52e 100644 --- a/arch/arm/common/dmabounce.c +++ b/arch/arm/common/dmabounce.c @@ -321,12 +321,12 @@ unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size, DO_STATS ( device_info->bounce_count++ ); if (dir == DMA_FROM_DEVICE || dir == DMA_BIDIRECTIONAL) { - unsigned long ptr; + void *ptr = buf->ptr; dev_dbg(dev, "%s: copy back safe %p to unsafe %p size %d\n", - __func__, buf->safe, buf->ptr, size); - memcpy(buf->ptr, buf->safe, size); + __func__, buf->safe, ptr, size); + memcpy(ptr, buf->safe, size); /* * DMA buffers must have the same cache properties @@ -336,7 +336,6 @@ unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size, * bidirectional case because we know the cache * lines will be coherent with the data written. */ - ptr = (unsigned long)buf->ptr; dmac_clean_range(ptr, ptr + size); outer_clean_range(__pa(ptr), __pa(ptr) + size); } -- cgit From ab2c21529df6ee0f06787773882a1abc6bc2d665 Mon Sep 17 00:00:00 2001 From: Russell King Date: Mon, 12 Feb 2007 10:28:24 +0000 Subject: [ARM] Add a reference from struct device to the dma bounce info dmabounce keeps a per-device structure, and finds the correct structure by walking a list. Since architectures can now add fields to struct device, we can attach this structure direct to the struct device, thereby eliminating the code to search the list. Signed-off-by: Russell King --- arch/arm/common/dmabounce.c | 31 +++++++------------------------ 1 file changed, 7 insertions(+), 24 deletions(-) (limited to 'arch/arm/common/dmabounce.c') diff --git a/arch/arm/common/dmabounce.c b/arch/arm/common/dmabounce.c index 2e635b814c14..490e1fe286d5 100644 --- a/arch/arm/common/dmabounce.c +++ b/arch/arm/common/dmabounce.c @@ -66,8 +66,6 @@ struct dmabounce_pool { }; struct dmabounce_device_info { - struct list_head node; - struct device *dev; struct list_head safe_buffers; #ifdef STATS @@ -81,8 +79,6 @@ struct dmabounce_device_info { rwlock_t lock; }; -static LIST_HEAD(dmabounce_devs); - #ifdef STATS static void print_alloc_stats(struct dmabounce_device_info *device_info) { @@ -96,19 +92,6 @@ static void print_alloc_stats(struct dmabounce_device_info *device_info) } #endif -/* find the given device in the dmabounce device list */ -static inline struct dmabounce_device_info * -find_dmabounce_dev(struct device *dev) -{ - struct dmabounce_device_info *d; - - list_for_each_entry(d, &dmabounce_devs, node) - if (d->dev == dev) - return d; - - return NULL; -} - /* allocate a 'safe' buffer and keep track of it */ static inline struct safe_buffer * @@ -231,7 +214,7 @@ 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 = find_dmabounce_dev(dev); + struct dmabounce_device_info *device_info = dev->archdata.dmabounce; dma_addr_t dma_addr; int needs_bounce = 0; @@ -292,7 +275,7 @@ static inline void unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size, enum dma_data_direction dir) { - struct dmabounce_device_info *device_info = find_dmabounce_dev(dev); + struct dmabounce_device_info *device_info = dev->archdata.dmabounce; struct safe_buffer *buf = NULL; /* @@ -343,7 +326,7 @@ static inline void sync_single(struct device *dev, dma_addr_t dma_addr, size_t size, enum dma_data_direction dir) { - struct dmabounce_device_info *device_info = find_dmabounce_dev(dev); + struct dmabounce_device_info *device_info = dev->archdata.dmabounce; struct safe_buffer *buf = NULL; if (device_info) @@ -606,7 +589,7 @@ dmabounce_register_dev(struct device *dev, unsigned long small_buffer_size, device_info->bounce_count = 0; #endif - list_add(&device_info->node, &dmabounce_devs); + dev->archdata.dmabounce = device_info; printk(KERN_INFO "dmabounce: registered device %s on %s bus\n", dev->bus_id, dev->bus->name); @@ -623,7 +606,9 @@ dmabounce_register_dev(struct device *dev, unsigned long small_buffer_size, void dmabounce_unregister_dev(struct device *dev) { - struct dmabounce_device_info *device_info = find_dmabounce_dev(dev); + struct dmabounce_device_info *device_info = dev->archdata.dmabounce; + + dev->archdata.dmabounce = NULL; if (!device_info) { printk(KERN_WARNING @@ -649,8 +634,6 @@ dmabounce_unregister_dev(struct device *dev) print_map_stats(device_info); #endif - list_del(&device_info->node); - kfree(device_info); printk(KERN_INFO "dmabounce: device %s on %s bus unregistered\n", -- cgit From 017cc022b6f0a0619cc3b0bba43e1c3247b06779 Mon Sep 17 00:00:00 2001 From: Russell King Date: Mon, 12 Feb 2007 10:53:50 +0000 Subject: [ARM] Convert dmabounce statistics to use a device attribute Rather than printk'ing the dmabounce statistics occasionally to the kernel log, provide a sysfs file to allow this information to be periodically read. Signed-off-by: Russell King --- arch/arm/common/dmabounce.c | 35 +++++++++++++++-------------------- 1 file changed, 15 insertions(+), 20 deletions(-) (limited to 'arch/arm/common/dmabounce.c') diff --git a/arch/arm/common/dmabounce.c b/arch/arm/common/dmabounce.c index 490e1fe286d5..4d5b031ac745 100644 --- a/arch/arm/common/dmabounce.c +++ b/arch/arm/common/dmabounce.c @@ -32,7 +32,6 @@ #include -#undef DEBUG #undef STATS #ifdef STATS @@ -72,6 +71,7 @@ struct dmabounce_device_info { unsigned long total_allocs; unsigned long map_op_count; unsigned long bounce_count; + int attr_res; #endif struct dmabounce_pool small; struct dmabounce_pool large; @@ -80,16 +80,21 @@ struct dmabounce_device_info { }; #ifdef STATS -static void print_alloc_stats(struct dmabounce_device_info *device_info) +static ssize_t dmabounce_show(struct device *dev, struct device_attribute *attr, + char *buf) { - printk(KERN_INFO - "%s: dmabounce: sbp: %lu, lbp: %lu, other: %lu, total: %lu\n", - device_info->dev->bus_id, - device_info->small.allocs, device_info->large.allocs, + struct dmabounce_device_info *device_info = dev->archdata.dmabounce; + return sprintf(buf, "%lu %lu %lu %lu %lu %lu\n", + device_info->small.allocs, + device_info->large.allocs, device_info->total_allocs - device_info->small.allocs - device_info->large.allocs, - device_info->total_allocs); + device_info->total_allocs, + device_info->map_op_count, + device_info->bounce_count); } + +static DEVICE_ATTR(dmabounce_stats, 0400, dmabounce_show, NULL); #endif @@ -145,8 +150,6 @@ alloc_safe_buffer(struct dmabounce_device_info *device_info, void *ptr, if (pool) pool->allocs++; device_info->total_allocs++; - if (device_info->total_allocs % 1000 == 0) - print_alloc_stats(device_info); #endif write_lock_irqsave(&device_info->lock, flags); @@ -201,15 +204,6 @@ free_safe_buffer(struct dmabounce_device_info *device_info, struct safe_buffer * /* ************************************************** */ -#ifdef STATS -static void print_map_stats(struct dmabounce_device_info *device_info) -{ - dev_info(device_info->dev, - "dmabounce: map_op_count=%lu, bounce_count=%lu\n", - device_info->map_op_count, device_info->bounce_count); -} -#endif - static inline dma_addr_t map_single(struct device *dev, void *ptr, size_t size, enum dma_data_direction dir) @@ -587,6 +581,7 @@ dmabounce_register_dev(struct device *dev, unsigned long small_buffer_size, device_info->total_allocs = 0; device_info->map_op_count = 0; device_info->bounce_count = 0; + device_info->attr_res = device_create_file(dev, &dev_attr_dmabounce_stats); #endif dev->archdata.dmabounce = device_info; @@ -630,8 +625,8 @@ dmabounce_unregister_dev(struct device *dev) dma_pool_destroy(device_info->large.pool); #ifdef STATS - print_alloc_stats(device_info); - print_map_stats(device_info); + if (device_info->attr_res == 0) + device_remove_file(dev, &dev_attr_dmabounce_stats); #endif kfree(device_info); -- cgit