1 From d48a09b301d9a460d5ce027433e8cb8872e7b5c3 Mon Sep 17 00:00:00 2001
2 From: Ian Molton <spyro@f2s.com>
3 Date: Fri, 4 Jan 2008 18:26:38 +0000
4 Subject: [PATCH 01/64] Allow runtime registration of regions of memory that require dma bouncing.
7 arch/arm/common/Kconfig | 4 ++
8 arch/arm/common/dmabounce.c | 82 ++++++++++++++++++++++++++++++++++++-
9 arch/arm/common/sa1111.c | 2 +-
10 arch/arm/mach-ixp4xx/Kconfig | 1 +
11 arch/arm/mach-ixp4xx/common-pci.c | 2 +-
12 5 files changed, 87 insertions(+), 4 deletions(-)
14 diff --git a/arch/arm/common/Kconfig b/arch/arm/common/Kconfig
15 index 3e07346..5f357fb 100644
16 --- a/arch/arm/common/Kconfig
17 +++ b/arch/arm/common/Kconfig
18 @@ -13,10 +13,14 @@ config ICST307
22 + select PLATFORM_DMABOUNCE
27 +config PLATFORM_DMABOUNCE
33 diff --git a/arch/arm/common/dmabounce.c b/arch/arm/common/dmabounce.c
34 index 52fc6a8..ed80abe 100644
35 --- a/arch/arm/common/dmabounce.c
36 +++ b/arch/arm/common/dmabounce.c
39 * Copyright (C) 2002 Hewlett Packard Company.
40 * Copyright (C) 2004 MontaVista Software, Inc.
41 + * Copyright (C) 2007 Dmitry Baryshkov <dbaryshkov@gmail.com>
43 * This program is free software; you can redistribute it and/or
44 * modify it under the terms of the GNU General Public License
47 #include <linux/module.h>
48 #include <linux/init.h>
49 +#include <linux/rwsem.h>
50 #include <linux/slab.h>
51 #include <linux/device.h>
52 #include <linux/dma-mapping.h>
53 @@ -80,6 +82,80 @@ struct dmabounce_device_info {
57 +struct dmabounce_check_entry {
58 + struct list_head list;
59 + dmabounce_check checker;
63 +static struct list_head checkers = LIST_HEAD_INIT(checkers);
64 +static rwlock_t checkers_lock = RW_LOCK_UNLOCKED;
67 +dmabounce_register_checker(dmabounce_check function, void *data)
69 + unsigned long flags;
70 + struct dmabounce_check_entry *entry =
71 + kzalloc(sizeof(struct dmabounce_check_entry), GFP_ATOMIC);
76 + INIT_LIST_HEAD(&entry->list);
77 + entry->checker = function;
80 + write_lock_irqsave(&checkers_lock, flags);
81 + list_add(&entry->list, &checkers);
82 + write_unlock_irqrestore(&checkers_lock, flags);
88 +dmabounce_remove_checker(dmabounce_check function, void *data)
90 + unsigned long flags;
91 + struct list_head *pos;
93 + write_lock_irqsave(&checkers_lock, flags);
94 + __list_for_each(pos, &checkers) {
95 + struct dmabounce_check_entry *entry = container_of(pos,
96 + struct dmabounce_check_entry, list);
97 + if (entry->checker == function && entry->data == data) {
99 + write_unlock_irqrestore(&checkers_lock, flags);
105 + write_unlock_irqrestore(&checkers_lock, flags);
106 + printk(KERN_WARNING "dmabounce checker not found: %p\n", function);
109 +static int dma_needs_bounce(struct device *dev, dma_addr_t dma, size_t size)
111 + unsigned long flags;
112 + struct list_head *pos;
114 + read_lock_irqsave(&checkers_lock, flags);
115 + __list_for_each(pos, &checkers) {
116 + struct dmabounce_check_entry *entry = container_of(pos,
117 + struct dmabounce_check_entry, list);
118 + if (entry->checker(dev, dma, size, entry->data)) {
119 + read_unlock_irqrestore(&checkers_lock, flags);
124 + read_unlock_irqrestore(&checkers_lock, flags);
125 +#ifdef CONFIG_PLATFORM_DMABOUNCE
126 + return platform_dma_needs_bounce(dev, dma, size);
132 static ssize_t dmabounce_show(struct device *dev, struct device_attribute *attr,
134 @@ -239,7 +315,7 @@ map_single(struct device *dev, void *ptr, size_t size,
135 struct safe_buffer *buf;
137 buf = alloc_safe_buffer(device_info, ptr, size, dir);
140 dev_err(dev, "%s: unable to map unsafe buffer %p!\n",
143 @@ -643,7 +719,6 @@ dmabounce_unregister_dev(struct device *dev)
144 dev->bus_id, dev->bus->name);
148 EXPORT_SYMBOL(dma_map_single);
149 EXPORT_SYMBOL(dma_unmap_single);
150 EXPORT_SYMBOL(dma_map_sg);
151 @@ -653,6 +728,9 @@ EXPORT_SYMBOL(dma_sync_single_for_device);
152 EXPORT_SYMBOL(dma_sync_sg);
153 EXPORT_SYMBOL(dmabounce_register_dev);
154 EXPORT_SYMBOL(dmabounce_unregister_dev);
155 +EXPORT_SYMBOL(dmabounce_register_checker);
156 +EXPORT_SYMBOL(dmabounce_remove_checker);
159 MODULE_AUTHOR("Christopher Hoover <ch@hpl.hp.com>, Deepak Saxena <dsaxena@plexity.net>");
160 MODULE_DESCRIPTION("Special dma_{map/unmap/dma_sync}_* routines for systems with limited DMA windows");
161 diff --git a/arch/arm/common/sa1111.c b/arch/arm/common/sa1111.c
162 index eb06d0b..3b8fbdd 100644
163 --- a/arch/arm/common/sa1111.c
164 +++ b/arch/arm/common/sa1111.c
165 @@ -778,7 +778,7 @@ static void __sa1111_remove(struct sa1111 *sachip)
166 * This should only get called for sa1111_device types due to the
167 * way we configure our device dma_masks.
169 -int dma_needs_bounce(struct device *dev, dma_addr_t addr, size_t size)
170 +int platform_dma_needs_bounce(struct device *dev, dma_addr_t addr, size_t size)
173 * Section 4.6 of the "Intel StrongARM SA-1111 Development Module
174 diff --git a/arch/arm/mach-ixp4xx/Kconfig b/arch/arm/mach-ixp4xx/Kconfig
175 index 61b2dfc..5870371 100644
176 --- a/arch/arm/mach-ixp4xx/Kconfig
177 +++ b/arch/arm/mach-ixp4xx/Kconfig
178 @@ -161,6 +161,7 @@ comment "IXP4xx Options"
182 + select PLATFORM_DMABOUNCE
185 config IXP4XX_INDIRECT_PCI
186 diff --git a/arch/arm/mach-ixp4xx/common-pci.c b/arch/arm/mach-ixp4xx/common-pci.c
187 index bf04121..ac46492 100644
188 --- a/arch/arm/mach-ixp4xx/common-pci.c
189 +++ b/arch/arm/mach-ixp4xx/common-pci.c
190 @@ -336,7 +336,7 @@ static int ixp4xx_pci_platform_notify_remove(struct device *dev)
194 -int dma_needs_bounce(struct device *dev, dma_addr_t dma_addr, size_t size)
195 +int platform_dma_needs_bounce(struct device *dev, dma_addr_t dma_addr, size_t size)
197 return (dev->bus == &pci_bus_type ) && ((dma_addr + size) >= SZ_64M);