ba79b4a47021a41103aee996a7f53ae70794f97a
[openembedded.git] /
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.
5
6 ---
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(-)
13
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
19  config SA1111
20         bool
21         select DMABOUNCE
22 +       select PLATFORM_DMABOUNCE
23  
24  config DMABOUNCE
25         bool
26  
27 +config PLATFORM_DMABOUNCE
28 +       bool
29 +
30  config TIMER_ACORN
31         bool
32  
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
37 @@ -16,6 +16,7 @@
38   *
39   *  Copyright (C) 2002 Hewlett Packard Company.
40   *  Copyright (C) 2004 MontaVista Software, Inc.
41 + *  Copyright (C) 2007 Dmitry Baryshkov <dbaryshkov@gmail.com>
42   *
43   *  This program is free software; you can redistribute it and/or
44   *  modify it under the terms of the GNU General Public License
45 @@ -24,6 +25,7 @@
46  
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 {
54         rwlock_t lock;
55  };
56  
57 +struct dmabounce_check_entry {
58 +       struct list_head        list;
59 +       dmabounce_check         checker;
60 +       void                    *data;
61 +};
62 +
63 +static struct list_head checkers = LIST_HEAD_INIT(checkers);
64 +static rwlock_t checkers_lock = RW_LOCK_UNLOCKED;
65 +
66 +int
67 +dmabounce_register_checker(dmabounce_check function, void *data)
68 +{
69 +       unsigned long flags;
70 +       struct dmabounce_check_entry *entry =
71 +               kzalloc(sizeof(struct dmabounce_check_entry), GFP_ATOMIC);
72 +
73 +       if (!entry)
74 +               return ENOMEM;
75 +
76 +       INIT_LIST_HEAD(&entry->list);
77 +       entry->checker = function;
78 +       entry->data = data;
79 +
80 +       write_lock_irqsave(&checkers_lock, flags);
81 +       list_add(&entry->list, &checkers);
82 +       write_unlock_irqrestore(&checkers_lock, flags);
83 +
84 +       return 0;
85 +}
86 +
87 +void
88 +dmabounce_remove_checker(dmabounce_check function, void *data)
89 +{
90 +       unsigned long flags;
91 +       struct list_head *pos;
92 +
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) {
98 +                       list_del(pos);
99 +                       write_unlock_irqrestore(&checkers_lock, flags);
100 +                       kfree(entry);
101 +                       return;
102 +               }
103 +       }
104 +
105 +       write_unlock_irqrestore(&checkers_lock, flags);
106 +       printk(KERN_WARNING "dmabounce checker not found: %p\n", function);
107 +}
108 +
109 +static int dma_needs_bounce(struct device *dev, dma_addr_t dma, size_t size)
110 +{
111 +       unsigned long flags;
112 +       struct list_head *pos;
113 +
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);
120 +                       return 1;
121 +               }
122 +       }
123 +
124 +       read_unlock_irqrestore(&checkers_lock, flags);
125 +#ifdef CONFIG_PLATFORM_DMABOUNCE
126 +       return platform_dma_needs_bounce(dev, dma, size);
127 +#else
128 +       return 0;
129 +#endif
130 +}
131  #ifdef STATS
132  static ssize_t dmabounce_show(struct device *dev, struct device_attribute *attr,
133                               char *buf)
134 @@ -239,7 +315,7 @@ map_single(struct device *dev, void *ptr, size_t size,
135                 struct safe_buffer *buf;
136  
137                 buf = alloc_safe_buffer(device_info, ptr, size, dir);
138 -               if (buf == 0) {
139 +               if (buf == NULL) {
140                         dev_err(dev, "%s: unable to map unsafe buffer %p!\n",
141                                __func__, ptr);
142                         return 0;
143 @@ -643,7 +719,6 @@ dmabounce_unregister_dev(struct device *dev)
144                 dev->bus_id, dev->bus->name);
145  }
146  
147 -
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);
157 +
158  
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.
168   */
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)
171  {
172         /*
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"
179  config DMABOUNCE
180         bool
181         default y
182 +       select PLATFORM_DMABOUNCE
183         depends on PCI
184  
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)
191         return 0;
192  }
193  
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)
196  {
197         return (dev->bus == &pci_bus_type ) && ((dma_addr + size) >= SZ_64M);
198  }
199 -- 
200 1.5.3.8
201