aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTony Lindgren <tony@atomide.com>2010-05-20 14:14:28 -0400
committerTony Lindgren <tony@atomide.com>2010-05-20 14:14:28 -0400
commitad57c39482a91cc7e377b0356d130810a78167fd (patch)
tree39a75269663e29b1e7ecba580bc07e07f0cd226d
parent0581b52e898f3f5472820940537d91d80895db5a (diff)
parent4abb761749abfb4ec403e4054f9dae2ee604e54f (diff)
Merge branch 'v2.6.34-rc7.iommu' of git://gitorious.org/~doyu/lk/mainline into omap-for-linus
-rw-r--r--arch/arm/mach-omap2/Makefile5
-rw-r--r--arch/arm/mach-omap2/iommu2.c6
-rw-r--r--arch/arm/mach-omap2/omap-iommu.c157
-rw-r--r--arch/arm/mach-omap2/omap3-iommu.c105
-rw-r--r--arch/arm/plat-omap/Kconfig9
-rw-r--r--arch/arm/plat-omap/include/plat/omap44xx.h3
-rw-r--r--arch/arm/plat-omap/iommu.c101
-rw-r--r--arch/arm/plat-omap/iovmm.c9
8 files changed, 244 insertions, 151 deletions
diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile
index 4b9fc57770db..7d2cf0f714c0 100644
--- a/arch/arm/mach-omap2/Makefile
+++ b/arch/arm/mach-omap2/Makefile
@@ -89,10 +89,7 @@ obj-$(CONFIG_OMAP3_EMU) += emu.o
89obj-$(CONFIG_OMAP_MBOX_FWK) += mailbox_mach.o 89obj-$(CONFIG_OMAP_MBOX_FWK) += mailbox_mach.o
90mailbox_mach-objs := mailbox.o 90mailbox_mach-objs := mailbox.o
91 91
92iommu-y += iommu2.o 92obj-$(CONFIG_OMAP_IOMMU) := iommu2.o omap-iommu.o
93iommu-$(CONFIG_ARCH_OMAP3) += omap3-iommu.o
94
95obj-$(CONFIG_OMAP_IOMMU) += $(iommu-y)
96 93
97i2c-omap-$(CONFIG_I2C_OMAP) := i2c.o 94i2c-omap-$(CONFIG_I2C_OMAP) := i2c.o
98obj-y += $(i2c-omap-m) $(i2c-omap-y) 95obj-y += $(i2c-omap-m) $(i2c-omap-y)
diff --git a/arch/arm/mach-omap2/iommu2.c b/arch/arm/mach-omap2/iommu2.c
index 4f63dc6859a4..e82da680d908 100644
--- a/arch/arm/mach-omap2/iommu2.c
+++ b/arch/arm/mach-omap2/iommu2.c
@@ -147,6 +147,7 @@ static u32 omap2_iommu_fault_isr(struct iommu *obj, u32 *ra)
147 printk("\n"); 147 printk("\n");
148 148
149 iommu_write_reg(obj, stat, MMU_IRQSTATUS); 149 iommu_write_reg(obj, stat, MMU_IRQSTATUS);
150 omap2_iommu_disable(obj);
150 return stat; 151 return stat;
151} 152}
152 153
@@ -184,7 +185,7 @@ static struct cr_regs *omap2_alloc_cr(struct iommu *obj, struct iotlb_entry *e)
184 if (!cr) 185 if (!cr)
185 return ERR_PTR(-ENOMEM); 186 return ERR_PTR(-ENOMEM);
186 187
187 cr->cam = (e->da & MMU_CAM_VATAG_MASK) | e->prsvd | e->pgsz; 188 cr->cam = (e->da & MMU_CAM_VATAG_MASK) | e->prsvd | e->pgsz | e->valid;
188 cr->ram = e->pa | e->endian | e->elsz | e->mixed; 189 cr->ram = e->pa | e->endian | e->elsz | e->mixed;
189 190
190 return cr; 191 return cr;
@@ -212,7 +213,8 @@ static ssize_t omap2_dump_cr(struct iommu *obj, struct cr_regs *cr, char *buf)
212 char *p = buf; 213 char *p = buf;
213 214
214 /* FIXME: Need more detail analysis of cam/ram */ 215 /* FIXME: Need more detail analysis of cam/ram */
215 p += sprintf(p, "%08x %08x\n", cr->cam, cr->ram); 216 p += sprintf(p, "%08x %08x %01x\n", cr->cam, cr->ram,
217 (cr->cam & MMU_CAM_P) ? 1 : 0);
216 218
217 return p - buf; 219 return p - buf;
218} 220}
diff --git a/arch/arm/mach-omap2/omap-iommu.c b/arch/arm/mach-omap2/omap-iommu.c
new file mode 100644
index 000000000000..eb9bee73e0cb
--- /dev/null
+++ b/arch/arm/mach-omap2/omap-iommu.c
@@ -0,0 +1,157 @@
1/*
2 * omap iommu: omap device registration
3 *
4 * Copyright (C) 2008-2009 Nokia Corporation
5 *
6 * Written by Hiroshi DOYU <Hiroshi.DOYU@nokia.com>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11 */
12
13#include <linux/platform_device.h>
14
15#include <plat/iommu.h>
16#include <plat/irqs.h>
17
18struct iommu_device {
19 resource_size_t base;
20 int irq;
21 struct iommu_platform_data pdata;
22 struct resource res[2];
23};
24static struct iommu_device *devices;
25static int num_iommu_devices;
26
27#ifdef CONFIG_ARCH_OMAP3
28static struct iommu_device omap3_devices[] = {
29 {
30 .base = 0x480bd400,
31 .irq = 24,
32 .pdata = {
33 .name = "isp",
34 .nr_tlb_entries = 8,
35 .clk_name = "cam_ick",
36 },
37 },
38#if defined(CONFIG_MPU_BRIDGE_IOMMU)
39 {
40 .base = 0x5d000000,
41 .irq = 28,
42 .pdata = {
43 .name = "iva2",
44 .nr_tlb_entries = 32,
45 .clk_name = "iva2_ck",
46 },
47 },
48#endif
49};
50#define NR_OMAP3_IOMMU_DEVICES ARRAY_SIZE(omap3_devices)
51static struct platform_device *omap3_iommu_pdev[NR_OMAP3_IOMMU_DEVICES];
52#else
53#define omap3_devices NULL
54#define NR_OMAP3_IOMMU_DEVICES 0
55#define omap3_iommu_pdev NULL
56#endif
57
58#ifdef CONFIG_ARCH_OMAP4
59static struct iommu_device omap4_devices[] = {
60 {
61 .base = OMAP4_MMU1_BASE,
62 .irq = INT_44XX_DUCATI_MMU_IRQ,
63 .pdata = {
64 .name = "ducati",
65 .nr_tlb_entries = 32,
66 .clk_name = "ducati_ick",
67 },
68 },
69#if defined(CONFIG_MPU_TESLA_IOMMU)
70 {
71 .base = OMAP4_MMU2_BASE,
72 .irq = INT_44XX_DSP_MMU,
73 .pdata = {
74 .name = "tesla",
75 .nr_tlb_entries = 32,
76 .clk_name = "tesla_ick",
77 },
78 },
79#endif
80};
81#define NR_OMAP4_IOMMU_DEVICES ARRAY_SIZE(omap4_devices)
82static struct platform_device *omap4_iommu_pdev[NR_OMAP4_IOMMU_DEVICES];
83#else
84#define omap4_devices NULL
85#define NR_OMAP4_IOMMU_DEVICES 0
86#define omap4_iommu_pdev NULL
87#endif
88
89static struct platform_device **omap_iommu_pdev;
90
91static int __init omap_iommu_init(void)
92{
93 int i, err;
94 struct resource res[] = {
95 { .flags = IORESOURCE_MEM },
96 { .flags = IORESOURCE_IRQ },
97 };
98
99 if (cpu_is_omap34xx()) {
100 devices = omap3_devices;
101 omap_iommu_pdev = omap3_iommu_pdev;
102 num_iommu_devices = NR_OMAP3_IOMMU_DEVICES;
103 } else if (cpu_is_omap44xx()) {
104 devices = omap4_devices;
105 omap_iommu_pdev = omap4_iommu_pdev;
106 num_iommu_devices = NR_OMAP4_IOMMU_DEVICES;
107 } else
108 return -ENODEV;
109
110 for (i = 0; i < num_iommu_devices; i++) {
111 struct platform_device *pdev;
112 const struct iommu_device *d = &devices[i];
113
114 pdev = platform_device_alloc("omap-iommu", i);
115 if (!pdev) {
116 err = -ENOMEM;
117 goto err_out;
118 }
119
120 res[0].start = d->base;
121 res[0].end = d->base + MMU_REG_SIZE - 1;
122 res[1].start = res[1].end = d->irq;
123
124 err = platform_device_add_resources(pdev, res,
125 ARRAY_SIZE(res));
126 if (err)
127 goto err_out;
128 err = platform_device_add_data(pdev, &d->pdata,
129 sizeof(d->pdata));
130 if (err)
131 goto err_out;
132 err = platform_device_add(pdev);
133 if (err)
134 goto err_out;
135 omap_iommu_pdev[i] = pdev;
136 }
137 return 0;
138
139err_out:
140 while (i--)
141 platform_device_put(omap_iommu_pdev[i]);
142 return err;
143}
144module_init(omap_iommu_init);
145
146static void __exit omap_iommu_exit(void)
147{
148 int i;
149
150 for (i = 0; i < num_iommu_devices; i++)
151 platform_device_unregister(omap_iommu_pdev[i]);
152}
153module_exit(omap_iommu_exit);
154
155MODULE_AUTHOR("Hiroshi DOYU");
156MODULE_DESCRIPTION("omap iommu: omap device registration");
157MODULE_LICENSE("GPL v2");
diff --git a/arch/arm/mach-omap2/omap3-iommu.c b/arch/arm/mach-omap2/omap3-iommu.c
deleted file mode 100644
index fbbcb5c83367..000000000000
--- a/arch/arm/mach-omap2/omap3-iommu.c
+++ /dev/null
@@ -1,105 +0,0 @@
1/*
2 * omap iommu: omap3 device registration
3 *
4 * Copyright (C) 2008-2009 Nokia Corporation
5 *
6 * Written by Hiroshi DOYU <Hiroshi.DOYU@nokia.com>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11 */
12
13#include <linux/platform_device.h>
14
15#include <plat/iommu.h>
16
17struct iommu_device {
18 resource_size_t base;
19 int irq;
20 struct iommu_platform_data pdata;
21 struct resource res[2];
22};
23
24static struct iommu_device devices[] = {
25 {
26 .base = 0x480bd400,
27 .irq = 24,
28 .pdata = {
29 .name = "isp",
30 .nr_tlb_entries = 8,
31 .clk_name = "cam_ick",
32 },
33 },
34#if defined(CONFIG_MPU_BRIDGE_IOMMU)
35 {
36 .base = 0x5d000000,
37 .irq = 28,
38 .pdata = {
39 .name = "iva2",
40 .nr_tlb_entries = 32,
41 .clk_name = "iva2_ck",
42 },
43 },
44#endif
45};
46#define NR_IOMMU_DEVICES ARRAY_SIZE(devices)
47
48static struct platform_device *omap3_iommu_pdev[NR_IOMMU_DEVICES];
49
50static int __init omap3_iommu_init(void)
51{
52 int i, err;
53 struct resource res[] = {
54 { .flags = IORESOURCE_MEM },
55 { .flags = IORESOURCE_IRQ },
56 };
57
58 for (i = 0; i < NR_IOMMU_DEVICES; i++) {
59 struct platform_device *pdev;
60 const struct iommu_device *d = &devices[i];
61
62 pdev = platform_device_alloc("omap-iommu", i);
63 if (!pdev) {
64 err = -ENOMEM;
65 goto err_out;
66 }
67
68 res[0].start = d->base;
69 res[0].end = d->base + MMU_REG_SIZE - 1;
70 res[1].start = res[1].end = d->irq;
71
72 err = platform_device_add_resources(pdev, res,
73 ARRAY_SIZE(res));
74 if (err)
75 goto err_out;
76 err = platform_device_add_data(pdev, &d->pdata,
77 sizeof(d->pdata));
78 if (err)
79 goto err_out;
80 err = platform_device_add(pdev);
81 if (err)
82 goto err_out;
83 omap3_iommu_pdev[i] = pdev;
84 }
85 return 0;
86
87err_out:
88 while (i--)
89 platform_device_put(omap3_iommu_pdev[i]);
90 return err;
91}
92module_init(omap3_iommu_init);
93
94static void __exit omap3_iommu_exit(void)
95{
96 int i;
97
98 for (i = 0; i < NR_IOMMU_DEVICES; i++)
99 platform_device_unregister(omap3_iommu_pdev[i]);
100}
101module_exit(omap3_iommu_exit);
102
103MODULE_AUTHOR("Hiroshi DOYU");
104MODULE_DESCRIPTION("omap iommu: omap3 device registration");
105MODULE_LICENSE("GPL v2");
diff --git a/arch/arm/plat-omap/Kconfig b/arch/arm/plat-omap/Kconfig
index 6da796ef82bd..78b49a626d06 100644
--- a/arch/arm/plat-omap/Kconfig
+++ b/arch/arm/plat-omap/Kconfig
@@ -110,8 +110,13 @@ config OMAP_IOMMU
110 tristate 110 tristate
111 111
112config OMAP_IOMMU_DEBUG 112config OMAP_IOMMU_DEBUG
113 depends on OMAP_IOMMU 113 tristate "Export OMAP IOMMU internals in DebugFS"
114 tristate 114 depends on OMAP_IOMMU && DEBUG_FS
115 help
116 Select this to see extensive information about
117 the internal state of OMAP IOMMU in debugfs.
118
119 Say N unless you know you need this.
115 120
116choice 121choice
117 prompt "System timer" 122 prompt "System timer"
diff --git a/arch/arm/plat-omap/include/plat/omap44xx.h b/arch/arm/plat-omap/include/plat/omap44xx.h
index b3ef1a7f53cc..bb94a0baee8a 100644
--- a/arch/arm/plat-omap/include/plat/omap44xx.h
+++ b/arch/arm/plat-omap/include/plat/omap44xx.h
@@ -48,5 +48,8 @@
48#define OMAP44XX_MAILBOX_BASE (L4_44XX_BASE + 0xF4000) 48#define OMAP44XX_MAILBOX_BASE (L4_44XX_BASE + 0xF4000)
49#define OMAP44XX_HSUSB_OTG_BASE (L4_44XX_BASE + 0xAB000) 49#define OMAP44XX_HSUSB_OTG_BASE (L4_44XX_BASE + 0xAB000)
50 50
51#define OMAP4_MMU1_BASE 0x55082000
52#define OMAP4_MMU2_BASE 0x4A066000
53
51#endif /* __ASM_ARCH_OMAP44XX_H */ 54#endif /* __ASM_ARCH_OMAP44XX_H */
52 55
diff --git a/arch/arm/plat-omap/iommu.c b/arch/arm/plat-omap/iommu.c
index 0e137663349c..bc094dbacee6 100644
--- a/arch/arm/plat-omap/iommu.c
+++ b/arch/arm/plat-omap/iommu.c
@@ -25,6 +25,11 @@
25 25
26#include "iopgtable.h" 26#include "iopgtable.h"
27 27
28#define for_each_iotlb_cr(obj, n, __i, cr) \
29 for (__i = 0; \
30 (__i < (n)) && (cr = __iotlb_read_cr((obj), __i), true); \
31 __i++)
32
28/* accommodate the difference between omap1 and omap2/3 */ 33/* accommodate the difference between omap1 and omap2/3 */
29static const struct iommu_functions *arch_iommu; 34static const struct iommu_functions *arch_iommu;
30 35
@@ -172,15 +177,12 @@ static void iotlb_lock_get(struct iommu *obj, struct iotlb_lock *l)
172 l->base = MMU_LOCK_BASE(val); 177 l->base = MMU_LOCK_BASE(val);
173 l->vict = MMU_LOCK_VICT(val); 178 l->vict = MMU_LOCK_VICT(val);
174 179
175 BUG_ON(l->base != 0); /* Currently no preservation is used */
176} 180}
177 181
178static void iotlb_lock_set(struct iommu *obj, struct iotlb_lock *l) 182static void iotlb_lock_set(struct iommu *obj, struct iotlb_lock *l)
179{ 183{
180 u32 val; 184 u32 val;
181 185
182 BUG_ON(l->base != 0); /* Currently no preservation is used */
183
184 val = (l->base << MMU_LOCK_BASE_SHIFT); 186 val = (l->base << MMU_LOCK_BASE_SHIFT);
185 val |= (l->vict << MMU_LOCK_VICT_SHIFT); 187 val |= (l->vict << MMU_LOCK_VICT_SHIFT);
186 188
@@ -214,6 +216,20 @@ static inline ssize_t iotlb_dump_cr(struct iommu *obj, struct cr_regs *cr,
214 return arch_iommu->dump_cr(obj, cr, buf); 216 return arch_iommu->dump_cr(obj, cr, buf);
215} 217}
216 218
219/* only used in iotlb iteration for-loop */
220static struct cr_regs __iotlb_read_cr(struct iommu *obj, int n)
221{
222 struct cr_regs cr;
223 struct iotlb_lock l;
224
225 iotlb_lock_get(obj, &l);
226 l.vict = n;
227 iotlb_lock_set(obj, &l);
228 iotlb_read_cr(obj, &cr);
229
230 return cr;
231}
232
217/** 233/**
218 * load_iotlb_entry - Set an iommu tlb entry 234 * load_iotlb_entry - Set an iommu tlb entry
219 * @obj: target iommu 235 * @obj: target iommu
@@ -221,7 +237,6 @@ static inline ssize_t iotlb_dump_cr(struct iommu *obj, struct cr_regs *cr,
221 **/ 237 **/
222int load_iotlb_entry(struct iommu *obj, struct iotlb_entry *e) 238int load_iotlb_entry(struct iommu *obj, struct iotlb_entry *e)
223{ 239{
224 int i;
225 int err = 0; 240 int err = 0;
226 struct iotlb_lock l; 241 struct iotlb_lock l;
227 struct cr_regs *cr; 242 struct cr_regs *cr;
@@ -231,21 +246,30 @@ int load_iotlb_entry(struct iommu *obj, struct iotlb_entry *e)
231 246
232 clk_enable(obj->clk); 247 clk_enable(obj->clk);
233 248
234 for (i = 0; i < obj->nr_tlb_entries; i++) { 249 iotlb_lock_get(obj, &l);
250 if (l.base == obj->nr_tlb_entries) {
251 dev_warn(obj->dev, "%s: preserve entries full\n", __func__);
252 err = -EBUSY;
253 goto out;
254 }
255 if (!e->prsvd) {
256 int i;
235 struct cr_regs tmp; 257 struct cr_regs tmp;
236 258
259 for_each_iotlb_cr(obj, obj->nr_tlb_entries, i, tmp)
260 if (!iotlb_cr_valid(&tmp))
261 break;
262
263 if (i == obj->nr_tlb_entries) {
264 dev_dbg(obj->dev, "%s: full: no entry\n", __func__);
265 err = -EBUSY;
266 goto out;
267 }
268
237 iotlb_lock_get(obj, &l); 269 iotlb_lock_get(obj, &l);
238 l.vict = i; 270 } else {
271 l.vict = l.base;
239 iotlb_lock_set(obj, &l); 272 iotlb_lock_set(obj, &l);
240 iotlb_read_cr(obj, &tmp);
241 if (!iotlb_cr_valid(&tmp))
242 break;
243 }
244
245 if (i == obj->nr_tlb_entries) {
246 dev_dbg(obj->dev, "%s: full: no entry\n", __func__);
247 err = -EBUSY;
248 goto out;
249 } 273 }
250 274
251 cr = iotlb_alloc_cr(obj, e); 275 cr = iotlb_alloc_cr(obj, e);
@@ -257,9 +281,11 @@ int load_iotlb_entry(struct iommu *obj, struct iotlb_entry *e)
257 iotlb_load_cr(obj, cr); 281 iotlb_load_cr(obj, cr);
258 kfree(cr); 282 kfree(cr);
259 283
284 if (e->prsvd)
285 l.base++;
260 /* increment victim for next tlb load */ 286 /* increment victim for next tlb load */
261 if (++l.vict == obj->nr_tlb_entries) 287 if (++l.vict == obj->nr_tlb_entries)
262 l.vict = 0; 288 l.vict = l.base;
263 iotlb_lock_set(obj, &l); 289 iotlb_lock_set(obj, &l);
264out: 290out:
265 clk_disable(obj->clk); 291 clk_disable(obj->clk);
@@ -276,20 +302,15 @@ EXPORT_SYMBOL_GPL(load_iotlb_entry);
276 **/ 302 **/
277void flush_iotlb_page(struct iommu *obj, u32 da) 303void flush_iotlb_page(struct iommu *obj, u32 da)
278{ 304{
279 struct iotlb_lock l;
280 int i; 305 int i;
306 struct cr_regs cr;
281 307
282 clk_enable(obj->clk); 308 clk_enable(obj->clk);
283 309
284 for (i = 0; i < obj->nr_tlb_entries; i++) { 310 for_each_iotlb_cr(obj, obj->nr_tlb_entries, i, cr) {
285 struct cr_regs cr;
286 u32 start; 311 u32 start;
287 size_t bytes; 312 size_t bytes;
288 313
289 iotlb_lock_get(obj, &l);
290 l.vict = i;
291 iotlb_lock_set(obj, &l);
292 iotlb_read_cr(obj, &cr);
293 if (!iotlb_cr_valid(&cr)) 314 if (!iotlb_cr_valid(&cr))
294 continue; 315 continue;
295 316
@@ -299,7 +320,6 @@ void flush_iotlb_page(struct iommu *obj, u32 da)
299 if ((start <= da) && (da < start + bytes)) { 320 if ((start <= da) && (da < start + bytes)) {
300 dev_dbg(obj->dev, "%s: %08x<=%08x(%x)\n", 321 dev_dbg(obj->dev, "%s: %08x<=%08x(%x)\n",
301 __func__, start, da, bytes); 322 __func__, start, da, bytes);
302 iotlb_load_cr(obj, &cr);
303 iommu_write_reg(obj, 1, MMU_FLUSH_ENTRY); 323 iommu_write_reg(obj, 1, MMU_FLUSH_ENTRY);
304 } 324 }
305 } 325 }
@@ -370,26 +390,19 @@ EXPORT_SYMBOL_GPL(iommu_dump_ctx);
370static int __dump_tlb_entries(struct iommu *obj, struct cr_regs *crs, int num) 390static int __dump_tlb_entries(struct iommu *obj, struct cr_regs *crs, int num)
371{ 391{
372 int i; 392 int i;
373 struct iotlb_lock saved, l; 393 struct iotlb_lock saved;
394 struct cr_regs tmp;
374 struct cr_regs *p = crs; 395 struct cr_regs *p = crs;
375 396
376 clk_enable(obj->clk); 397 clk_enable(obj->clk);
377
378 iotlb_lock_get(obj, &saved); 398 iotlb_lock_get(obj, &saved);
379 memcpy(&l, &saved, sizeof(saved));
380 399
381 for (i = 0; i < num; i++) { 400 for_each_iotlb_cr(obj, num, i, tmp) {
382 struct cr_regs tmp;
383
384 iotlb_lock_get(obj, &l);
385 l.vict = i;
386 iotlb_lock_set(obj, &l);
387 iotlb_read_cr(obj, &tmp);
388 if (!iotlb_cr_valid(&tmp)) 401 if (!iotlb_cr_valid(&tmp))
389 continue; 402 continue;
390
391 *p++ = tmp; 403 *p++ = tmp;
392 } 404 }
405
393 iotlb_lock_set(obj, &saved); 406 iotlb_lock_set(obj, &saved);
394 clk_disable(obj->clk); 407 clk_disable(obj->clk);
395 408
@@ -503,6 +516,12 @@ static int iopgd_alloc_section(struct iommu *obj, u32 da, u32 pa, u32 prot)
503{ 516{
504 u32 *iopgd = iopgd_offset(obj, da); 517 u32 *iopgd = iopgd_offset(obj, da);
505 518
519 if ((da | pa) & ~IOSECTION_MASK) {
520 dev_err(obj->dev, "%s: %08x:%08x should aligned on %08lx\n",
521 __func__, da, pa, IOSECTION_SIZE);
522 return -EINVAL;
523 }
524
506 *iopgd = (pa & IOSECTION_MASK) | prot | IOPGD_SECTION; 525 *iopgd = (pa & IOSECTION_MASK) | prot | IOPGD_SECTION;
507 flush_iopgd_range(iopgd, iopgd); 526 flush_iopgd_range(iopgd, iopgd);
508 return 0; 527 return 0;
@@ -513,6 +532,12 @@ static int iopgd_alloc_super(struct iommu *obj, u32 da, u32 pa, u32 prot)
513 u32 *iopgd = iopgd_offset(obj, da); 532 u32 *iopgd = iopgd_offset(obj, da);
514 int i; 533 int i;
515 534
535 if ((da | pa) & ~IOSUPER_MASK) {
536 dev_err(obj->dev, "%s: %08x:%08x should aligned on %08lx\n",
537 __func__, da, pa, IOSUPER_SIZE);
538 return -EINVAL;
539 }
540
516 for (i = 0; i < 16; i++) 541 for (i = 0; i < 16; i++)
517 *(iopgd + i) = (pa & IOSUPER_MASK) | prot | IOPGD_SUPER; 542 *(iopgd + i) = (pa & IOSUPER_MASK) | prot | IOPGD_SUPER;
518 flush_iopgd_range(iopgd, iopgd + 15); 543 flush_iopgd_range(iopgd, iopgd + 15);
@@ -542,6 +567,12 @@ static int iopte_alloc_large(struct iommu *obj, u32 da, u32 pa, u32 prot)
542 u32 *iopte = iopte_alloc(obj, iopgd, da); 567 u32 *iopte = iopte_alloc(obj, iopgd, da);
543 int i; 568 int i;
544 569
570 if ((da | pa) & ~IOLARGE_MASK) {
571 dev_err(obj->dev, "%s: %08x:%08x should aligned on %08lx\n",
572 __func__, da, pa, IOLARGE_SIZE);
573 return -EINVAL;
574 }
575
545 if (IS_ERR(iopte)) 576 if (IS_ERR(iopte))
546 return PTR_ERR(iopte); 577 return PTR_ERR(iopte);
547 578
diff --git a/arch/arm/plat-omap/iovmm.c b/arch/arm/plat-omap/iovmm.c
index 65c6d1ff7237..e43983ba59c5 100644
--- a/arch/arm/plat-omap/iovmm.c
+++ b/arch/arm/plat-omap/iovmm.c
@@ -287,16 +287,19 @@ static struct iovm_struct *alloc_iovm_area(struct iommu *obj, u32 da,
287 prev_end = 0; 287 prev_end = 0;
288 list_for_each_entry(tmp, &obj->mmap, list) { 288 list_for_each_entry(tmp, &obj->mmap, list) {
289 289
290 if ((prev_end <= start) && (start + bytes < tmp->da_start)) 290 if (prev_end >= start)
291 break;
292
293 if (start + bytes < tmp->da_start)
291 goto found; 294 goto found;
292 295
293 if (flags & IOVMF_DA_ANON) 296 if (flags & IOVMF_DA_ANON)
294 start = roundup(tmp->da_end, alignement); 297 start = roundup(tmp->da_end + 1, alignement);
295 298
296 prev_end = tmp->da_end; 299 prev_end = tmp->da_end;
297 } 300 }
298 301
299 if ((start >= prev_end) && (ULONG_MAX - start >= bytes)) 302 if ((start > prev_end) && (ULONG_MAX - start >= bytes))
300 goto found; 303 goto found;
301 304
302 dev_dbg(obj->dev, "%s: no space to fit %08x(%x) flags: %08x\n", 305 dev_dbg(obj->dev, "%s: no space to fit %08x(%x) flags: %08x\n",