diff options
Diffstat (limited to 'drivers/iommu/fsl_pamu_domain.c')
-rw-r--r-- | drivers/iommu/fsl_pamu_domain.c | 173 |
1 files changed, 74 insertions, 99 deletions
diff --git a/drivers/iommu/fsl_pamu_domain.c b/drivers/iommu/fsl_pamu_domain.c index c828f80d48b0..ceebd287b660 100644 --- a/drivers/iommu/fsl_pamu_domain.c +++ b/drivers/iommu/fsl_pamu_domain.c | |||
@@ -19,26 +19,10 @@ | |||
19 | 19 | ||
20 | #define pr_fmt(fmt) "fsl-pamu-domain: %s: " fmt, __func__ | 20 | #define pr_fmt(fmt) "fsl-pamu-domain: %s: " fmt, __func__ |
21 | 21 | ||
22 | #include <linux/init.h> | ||
23 | #include <linux/iommu.h> | ||
24 | #include <linux/notifier.h> | ||
25 | #include <linux/slab.h> | ||
26 | #include <linux/module.h> | ||
27 | #include <linux/types.h> | ||
28 | #include <linux/mm.h> | ||
29 | #include <linux/interrupt.h> | ||
30 | #include <linux/device.h> | ||
31 | #include <linux/of_platform.h> | ||
32 | #include <linux/bootmem.h> | ||
33 | #include <linux/err.h> | ||
34 | #include <asm/io.h> | ||
35 | #include <asm/bitops.h> | ||
36 | |||
37 | #include <asm/pci-bridge.h> | ||
38 | #include <sysdev/fsl_pci.h> | ||
39 | |||
40 | #include "fsl_pamu_domain.h" | 22 | #include "fsl_pamu_domain.h" |
41 | 23 | ||
24 | #include <sysdev/fsl_pci.h> | ||
25 | |||
42 | /* | 26 | /* |
43 | * Global spinlock that needs to be held while | 27 | * Global spinlock that needs to be held while |
44 | * configuring PAMU. | 28 | * configuring PAMU. |
@@ -51,23 +35,21 @@ static DEFINE_SPINLOCK(device_domain_lock); | |||
51 | 35 | ||
52 | static int __init iommu_init_mempool(void) | 36 | static int __init iommu_init_mempool(void) |
53 | { | 37 | { |
54 | |||
55 | fsl_pamu_domain_cache = kmem_cache_create("fsl_pamu_domain", | 38 | fsl_pamu_domain_cache = kmem_cache_create("fsl_pamu_domain", |
56 | sizeof(struct fsl_dma_domain), | 39 | sizeof(struct fsl_dma_domain), |
57 | 0, | 40 | 0, |
58 | SLAB_HWCACHE_ALIGN, | 41 | SLAB_HWCACHE_ALIGN, |
59 | 42 | NULL); | |
60 | NULL); | ||
61 | if (!fsl_pamu_domain_cache) { | 43 | if (!fsl_pamu_domain_cache) { |
62 | pr_debug("Couldn't create fsl iommu_domain cache\n"); | 44 | pr_debug("Couldn't create fsl iommu_domain cache\n"); |
63 | return -ENOMEM; | 45 | return -ENOMEM; |
64 | } | 46 | } |
65 | 47 | ||
66 | iommu_devinfo_cache = kmem_cache_create("iommu_devinfo", | 48 | iommu_devinfo_cache = kmem_cache_create("iommu_devinfo", |
67 | sizeof(struct device_domain_info), | 49 | sizeof(struct device_domain_info), |
68 | 0, | 50 | 0, |
69 | SLAB_HWCACHE_ALIGN, | 51 | SLAB_HWCACHE_ALIGN, |
70 | NULL); | 52 | NULL); |
71 | if (!iommu_devinfo_cache) { | 53 | if (!iommu_devinfo_cache) { |
72 | pr_debug("Couldn't create devinfo cache\n"); | 54 | pr_debug("Couldn't create devinfo cache\n"); |
73 | kmem_cache_destroy(fsl_pamu_domain_cache); | 55 | kmem_cache_destroy(fsl_pamu_domain_cache); |
@@ -80,8 +62,7 @@ static int __init iommu_init_mempool(void) | |||
80 | static phys_addr_t get_phys_addr(struct fsl_dma_domain *dma_domain, dma_addr_t iova) | 62 | static phys_addr_t get_phys_addr(struct fsl_dma_domain *dma_domain, dma_addr_t iova) |
81 | { | 63 | { |
82 | u32 win_cnt = dma_domain->win_cnt; | 64 | u32 win_cnt = dma_domain->win_cnt; |
83 | struct dma_window *win_ptr = | 65 | struct dma_window *win_ptr = &dma_domain->win_arr[0]; |
84 | &dma_domain->win_arr[0]; | ||
85 | struct iommu_domain_geometry *geom; | 66 | struct iommu_domain_geometry *geom; |
86 | 67 | ||
87 | geom = &dma_domain->iommu_domain->geometry; | 68 | geom = &dma_domain->iommu_domain->geometry; |
@@ -103,22 +84,20 @@ static phys_addr_t get_phys_addr(struct fsl_dma_domain *dma_domain, dma_addr_t i | |||
103 | } | 84 | } |
104 | 85 | ||
105 | if (win_ptr->valid) | 86 | if (win_ptr->valid) |
106 | return (win_ptr->paddr + (iova & (win_ptr->size - 1))); | 87 | return win_ptr->paddr + (iova & (win_ptr->size - 1)); |
107 | 88 | ||
108 | return 0; | 89 | return 0; |
109 | } | 90 | } |
110 | 91 | ||
111 | static int map_subwins(int liodn, struct fsl_dma_domain *dma_domain) | 92 | static int map_subwins(int liodn, struct fsl_dma_domain *dma_domain) |
112 | { | 93 | { |
113 | struct dma_window *sub_win_ptr = | 94 | struct dma_window *sub_win_ptr = &dma_domain->win_arr[0]; |
114 | &dma_domain->win_arr[0]; | ||
115 | int i, ret; | 95 | int i, ret; |
116 | unsigned long rpn, flags; | 96 | unsigned long rpn, flags; |
117 | 97 | ||
118 | for (i = 0; i < dma_domain->win_cnt; i++) { | 98 | for (i = 0; i < dma_domain->win_cnt; i++) { |
119 | if (sub_win_ptr[i].valid) { | 99 | if (sub_win_ptr[i].valid) { |
120 | rpn = sub_win_ptr[i].paddr >> | 100 | rpn = sub_win_ptr[i].paddr >> PAMU_PAGE_SHIFT; |
121 | PAMU_PAGE_SHIFT; | ||
122 | spin_lock_irqsave(&iommu_lock, flags); | 101 | spin_lock_irqsave(&iommu_lock, flags); |
123 | ret = pamu_config_spaace(liodn, dma_domain->win_cnt, i, | 102 | ret = pamu_config_spaace(liodn, dma_domain->win_cnt, i, |
124 | sub_win_ptr[i].size, | 103 | sub_win_ptr[i].size, |
@@ -130,7 +109,7 @@ static int map_subwins(int liodn, struct fsl_dma_domain *dma_domain) | |||
130 | sub_win_ptr[i].prot); | 109 | sub_win_ptr[i].prot); |
131 | spin_unlock_irqrestore(&iommu_lock, flags); | 110 | spin_unlock_irqrestore(&iommu_lock, flags); |
132 | if (ret) { | 111 | if (ret) { |
133 | pr_debug("PAMU SPAACE configuration failed for liodn %d\n", | 112 | pr_debug("SPAACE configuration failed for liodn %d\n", |
134 | liodn); | 113 | liodn); |
135 | return ret; | 114 | return ret; |
136 | } | 115 | } |
@@ -156,8 +135,7 @@ static int map_win(int liodn, struct fsl_dma_domain *dma_domain) | |||
156 | 0, wnd->prot); | 135 | 0, wnd->prot); |
157 | spin_unlock_irqrestore(&iommu_lock, flags); | 136 | spin_unlock_irqrestore(&iommu_lock, flags); |
158 | if (ret) | 137 | if (ret) |
159 | pr_debug("PAMU PAACE configuration failed for liodn %d\n", | 138 | pr_debug("PAACE configuration failed for liodn %d\n", liodn); |
160 | liodn); | ||
161 | 139 | ||
162 | return ret; | 140 | return ret; |
163 | } | 141 | } |
@@ -169,7 +147,6 @@ static int map_liodn(int liodn, struct fsl_dma_domain *dma_domain) | |||
169 | return map_subwins(liodn, dma_domain); | 147 | return map_subwins(liodn, dma_domain); |
170 | else | 148 | else |
171 | return map_win(liodn, dma_domain); | 149 | return map_win(liodn, dma_domain); |
172 | |||
173 | } | 150 | } |
174 | 151 | ||
175 | /* Update window/subwindow mapping for the LIODN */ | 152 | /* Update window/subwindow mapping for the LIODN */ |
@@ -190,7 +167,8 @@ static int update_liodn(int liodn, struct fsl_dma_domain *dma_domain, u32 wnd_nr | |||
190 | (wnd_nr > 0) ? 1 : 0, | 167 | (wnd_nr > 0) ? 1 : 0, |
191 | wnd->prot); | 168 | wnd->prot); |
192 | if (ret) | 169 | if (ret) |
193 | pr_debug("Subwindow reconfiguration failed for liodn %d\n", liodn); | 170 | pr_debug("Subwindow reconfiguration failed for liodn %d\n", |
171 | liodn); | ||
194 | } else { | 172 | } else { |
195 | phys_addr_t wnd_addr; | 173 | phys_addr_t wnd_addr; |
196 | 174 | ||
@@ -200,10 +178,11 @@ static int update_liodn(int liodn, struct fsl_dma_domain *dma_domain, u32 wnd_nr | |||
200 | wnd->size, | 178 | wnd->size, |
201 | ~(u32)0, | 179 | ~(u32)0, |
202 | wnd->paddr >> PAMU_PAGE_SHIFT, | 180 | wnd->paddr >> PAMU_PAGE_SHIFT, |
203 | dma_domain->snoop_id, dma_domain->stash_id, | 181 | dma_domain->snoop_id, dma_domain->stash_id, |
204 | 0, wnd->prot); | 182 | 0, wnd->prot); |
205 | if (ret) | 183 | if (ret) |
206 | pr_debug("Window reconfiguration failed for liodn %d\n", liodn); | 184 | pr_debug("Window reconfiguration failed for liodn %d\n", |
185 | liodn); | ||
207 | } | 186 | } |
208 | 187 | ||
209 | spin_unlock_irqrestore(&iommu_lock, flags); | 188 | spin_unlock_irqrestore(&iommu_lock, flags); |
@@ -212,14 +191,15 @@ static int update_liodn(int liodn, struct fsl_dma_domain *dma_domain, u32 wnd_nr | |||
212 | } | 191 | } |
213 | 192 | ||
214 | static int update_liodn_stash(int liodn, struct fsl_dma_domain *dma_domain, | 193 | static int update_liodn_stash(int liodn, struct fsl_dma_domain *dma_domain, |
215 | u32 val) | 194 | u32 val) |
216 | { | 195 | { |
217 | int ret = 0, i; | 196 | int ret = 0, i; |
218 | unsigned long flags; | 197 | unsigned long flags; |
219 | 198 | ||
220 | spin_lock_irqsave(&iommu_lock, flags); | 199 | spin_lock_irqsave(&iommu_lock, flags); |
221 | if (!dma_domain->win_arr) { | 200 | if (!dma_domain->win_arr) { |
222 | pr_debug("Windows not configured, stash destination update failed for liodn %d\n", liodn); | 201 | pr_debug("Windows not configured, stash destination update failed for liodn %d\n", |
202 | liodn); | ||
223 | spin_unlock_irqrestore(&iommu_lock, flags); | 203 | spin_unlock_irqrestore(&iommu_lock, flags); |
224 | return -EINVAL; | 204 | return -EINVAL; |
225 | } | 205 | } |
@@ -227,7 +207,8 @@ static int update_liodn_stash(int liodn, struct fsl_dma_domain *dma_domain, | |||
227 | for (i = 0; i < dma_domain->win_cnt; i++) { | 207 | for (i = 0; i < dma_domain->win_cnt; i++) { |
228 | ret = pamu_update_paace_stash(liodn, i, val); | 208 | ret = pamu_update_paace_stash(liodn, i, val); |
229 | if (ret) { | 209 | if (ret) { |
230 | pr_debug("Failed to update SPAACE %d field for liodn %d\n ", i, liodn); | 210 | pr_debug("Failed to update SPAACE %d field for liodn %d\n ", |
211 | i, liodn); | ||
231 | spin_unlock_irqrestore(&iommu_lock, flags); | 212 | spin_unlock_irqrestore(&iommu_lock, flags); |
232 | return ret; | 213 | return ret; |
233 | } | 214 | } |
@@ -240,9 +221,9 @@ static int update_liodn_stash(int liodn, struct fsl_dma_domain *dma_domain, | |||
240 | 221 | ||
241 | /* Set the geometry parameters for a LIODN */ | 222 | /* Set the geometry parameters for a LIODN */ |
242 | static int pamu_set_liodn(int liodn, struct device *dev, | 223 | static int pamu_set_liodn(int liodn, struct device *dev, |
243 | struct fsl_dma_domain *dma_domain, | 224 | struct fsl_dma_domain *dma_domain, |
244 | struct iommu_domain_geometry *geom_attr, | 225 | struct iommu_domain_geometry *geom_attr, |
245 | u32 win_cnt) | 226 | u32 win_cnt) |
246 | { | 227 | { |
247 | phys_addr_t window_addr, window_size; | 228 | phys_addr_t window_addr, window_size; |
248 | phys_addr_t subwin_size; | 229 | phys_addr_t subwin_size; |
@@ -268,7 +249,8 @@ static int pamu_set_liodn(int liodn, struct device *dev, | |||
268 | dma_domain->stash_id, win_cnt, 0); | 249 | dma_domain->stash_id, win_cnt, 0); |
269 | spin_unlock_irqrestore(&iommu_lock, flags); | 250 | spin_unlock_irqrestore(&iommu_lock, flags); |
270 | if (ret) { | 251 | if (ret) { |
271 | pr_debug("PAMU PAACE configuration failed for liodn %d, win_cnt =%d\n", liodn, win_cnt); | 252 | pr_debug("PAACE configuration failed for liodn %d, win_cnt =%d\n", |
253 | liodn, win_cnt); | ||
272 | return ret; | 254 | return ret; |
273 | } | 255 | } |
274 | 256 | ||
@@ -285,7 +267,8 @@ static int pamu_set_liodn(int liodn, struct device *dev, | |||
285 | 0, 0); | 267 | 0, 0); |
286 | spin_unlock_irqrestore(&iommu_lock, flags); | 268 | spin_unlock_irqrestore(&iommu_lock, flags); |
287 | if (ret) { | 269 | if (ret) { |
288 | pr_debug("PAMU SPAACE configuration failed for liodn %d\n", liodn); | 270 | pr_debug("SPAACE configuration failed for liodn %d\n", |
271 | liodn); | ||
289 | return ret; | 272 | return ret; |
290 | } | 273 | } |
291 | } | 274 | } |
@@ -301,13 +284,13 @@ static int check_size(u64 size, dma_addr_t iova) | |||
301 | * to PAMU page size. | 284 | * to PAMU page size. |
302 | */ | 285 | */ |
303 | if ((size & (size - 1)) || size < PAMU_PAGE_SIZE) { | 286 | if ((size & (size - 1)) || size < PAMU_PAGE_SIZE) { |
304 | pr_debug("%s: size too small or not a power of two\n", __func__); | 287 | pr_debug("Size too small or not a power of two\n"); |
305 | return -EINVAL; | 288 | return -EINVAL; |
306 | } | 289 | } |
307 | 290 | ||
308 | /* iova must be page size aligned*/ | 291 | /* iova must be page size aligned */ |
309 | if (iova & (size - 1)) { | 292 | if (iova & (size - 1)) { |
310 | pr_debug("%s: address is not aligned with window size\n", __func__); | 293 | pr_debug("Address is not aligned with window size\n"); |
311 | return -EINVAL; | 294 | return -EINVAL; |
312 | } | 295 | } |
313 | 296 | ||
@@ -396,16 +379,15 @@ static void attach_device(struct fsl_dma_domain *dma_domain, int liodn, struct d | |||
396 | if (!dev->archdata.iommu_domain) | 379 | if (!dev->archdata.iommu_domain) |
397 | dev->archdata.iommu_domain = info; | 380 | dev->archdata.iommu_domain = info; |
398 | spin_unlock_irqrestore(&device_domain_lock, flags); | 381 | spin_unlock_irqrestore(&device_domain_lock, flags); |
399 | |||
400 | } | 382 | } |
401 | 383 | ||
402 | static phys_addr_t fsl_pamu_iova_to_phys(struct iommu_domain *domain, | 384 | static phys_addr_t fsl_pamu_iova_to_phys(struct iommu_domain *domain, |
403 | dma_addr_t iova) | 385 | dma_addr_t iova) |
404 | { | 386 | { |
405 | struct fsl_dma_domain *dma_domain = domain->priv; | 387 | struct fsl_dma_domain *dma_domain = domain->priv; |
406 | 388 | ||
407 | if ((iova < domain->geometry.aperture_start) || | 389 | if (iova < domain->geometry.aperture_start || |
408 | iova > (domain->geometry.aperture_end)) | 390 | iova > domain->geometry.aperture_end) |
409 | return 0; | 391 | return 0; |
410 | 392 | ||
411 | return get_phys_addr(dma_domain, iova); | 393 | return get_phys_addr(dma_domain, iova); |
@@ -460,7 +442,7 @@ static int pamu_set_domain_geometry(struct fsl_dma_domain *dma_domain, | |||
460 | 442 | ||
461 | list_for_each_entry(info, &dma_domain->devices, link) { | 443 | list_for_each_entry(info, &dma_domain->devices, link) { |
462 | ret = pamu_set_liodn(info->liodn, info->dev, dma_domain, | 444 | ret = pamu_set_liodn(info->liodn, info->dev, dma_domain, |
463 | geom_attr, win_cnt); | 445 | geom_attr, win_cnt); |
464 | if (ret) | 446 | if (ret) |
465 | break; | 447 | break; |
466 | } | 448 | } |
@@ -543,7 +525,6 @@ static void fsl_pamu_window_disable(struct iommu_domain *domain, u32 wnd_nr) | |||
543 | } | 525 | } |
544 | 526 | ||
545 | spin_unlock_irqrestore(&dma_domain->domain_lock, flags); | 527 | spin_unlock_irqrestore(&dma_domain->domain_lock, flags); |
546 | |||
547 | } | 528 | } |
548 | 529 | ||
549 | static int fsl_pamu_window_enable(struct iommu_domain *domain, u32 wnd_nr, | 530 | static int fsl_pamu_window_enable(struct iommu_domain *domain, u32 wnd_nr, |
@@ -576,7 +557,7 @@ static int fsl_pamu_window_enable(struct iommu_domain *domain, u32 wnd_nr, | |||
576 | 557 | ||
577 | win_size = dma_domain->geom_size >> ilog2(dma_domain->win_cnt); | 558 | win_size = dma_domain->geom_size >> ilog2(dma_domain->win_cnt); |
578 | if (size > win_size) { | 559 | if (size > win_size) { |
579 | pr_debug("Invalid window size \n"); | 560 | pr_debug("Invalid window size\n"); |
580 | spin_unlock_irqrestore(&dma_domain->domain_lock, flags); | 561 | spin_unlock_irqrestore(&dma_domain->domain_lock, flags); |
581 | return -EINVAL; | 562 | return -EINVAL; |
582 | } | 563 | } |
@@ -622,8 +603,8 @@ static int fsl_pamu_window_enable(struct iommu_domain *domain, u32 wnd_nr, | |||
622 | * and window mappings. | 603 | * and window mappings. |
623 | */ | 604 | */ |
624 | static int handle_attach_device(struct fsl_dma_domain *dma_domain, | 605 | static int handle_attach_device(struct fsl_dma_domain *dma_domain, |
625 | struct device *dev, const u32 *liodn, | 606 | struct device *dev, const u32 *liodn, |
626 | int num) | 607 | int num) |
627 | { | 608 | { |
628 | unsigned long flags; | 609 | unsigned long flags; |
629 | struct iommu_domain *domain = dma_domain->iommu_domain; | 610 | struct iommu_domain *domain = dma_domain->iommu_domain; |
@@ -632,11 +613,10 @@ static int handle_attach_device(struct fsl_dma_domain *dma_domain, | |||
632 | 613 | ||
633 | spin_lock_irqsave(&dma_domain->domain_lock, flags); | 614 | spin_lock_irqsave(&dma_domain->domain_lock, flags); |
634 | for (i = 0; i < num; i++) { | 615 | for (i = 0; i < num; i++) { |
635 | |||
636 | /* Ensure that LIODN value is valid */ | 616 | /* Ensure that LIODN value is valid */ |
637 | if (liodn[i] >= PAACE_NUMBER_ENTRIES) { | 617 | if (liodn[i] >= PAACE_NUMBER_ENTRIES) { |
638 | pr_debug("Invalid liodn %d, attach device failed for %s\n", | 618 | pr_debug("Invalid liodn %d, attach device failed for %s\n", |
639 | liodn[i], dev->of_node->full_name); | 619 | liodn[i], dev->of_node->full_name); |
640 | ret = -EINVAL; | 620 | ret = -EINVAL; |
641 | break; | 621 | break; |
642 | } | 622 | } |
@@ -649,9 +629,9 @@ static int handle_attach_device(struct fsl_dma_domain *dma_domain, | |||
649 | */ | 629 | */ |
650 | if (dma_domain->win_arr) { | 630 | if (dma_domain->win_arr) { |
651 | u32 win_cnt = dma_domain->win_cnt > 1 ? dma_domain->win_cnt : 0; | 631 | u32 win_cnt = dma_domain->win_cnt > 1 ? dma_domain->win_cnt : 0; |
632 | |||
652 | ret = pamu_set_liodn(liodn[i], dev, dma_domain, | 633 | ret = pamu_set_liodn(liodn[i], dev, dma_domain, |
653 | &domain->geometry, | 634 | &domain->geometry, win_cnt); |
654 | win_cnt); | ||
655 | if (ret) | 635 | if (ret) |
656 | break; | 636 | break; |
657 | if (dma_domain->mapped) { | 637 | if (dma_domain->mapped) { |
@@ -698,19 +678,18 @@ static int fsl_pamu_attach_device(struct iommu_domain *domain, | |||
698 | liodn = of_get_property(dev->of_node, "fsl,liodn", &len); | 678 | liodn = of_get_property(dev->of_node, "fsl,liodn", &len); |
699 | if (liodn) { | 679 | if (liodn) { |
700 | liodn_cnt = len / sizeof(u32); | 680 | liodn_cnt = len / sizeof(u32); |
701 | ret = handle_attach_device(dma_domain, dev, | 681 | ret = handle_attach_device(dma_domain, dev, liodn, liodn_cnt); |
702 | liodn, liodn_cnt); | ||
703 | } else { | 682 | } else { |
704 | pr_debug("missing fsl,liodn property at %s\n", | 683 | pr_debug("missing fsl,liodn property at %s\n", |
705 | dev->of_node->full_name); | 684 | dev->of_node->full_name); |
706 | ret = -EINVAL; | 685 | ret = -EINVAL; |
707 | } | 686 | } |
708 | 687 | ||
709 | return ret; | 688 | return ret; |
710 | } | 689 | } |
711 | 690 | ||
712 | static void fsl_pamu_detach_device(struct iommu_domain *domain, | 691 | static void fsl_pamu_detach_device(struct iommu_domain *domain, |
713 | struct device *dev) | 692 | struct device *dev) |
714 | { | 693 | { |
715 | struct fsl_dma_domain *dma_domain = domain->priv; | 694 | struct fsl_dma_domain *dma_domain = domain->priv; |
716 | const u32 *prop; | 695 | const u32 *prop; |
@@ -738,7 +717,7 @@ static void fsl_pamu_detach_device(struct iommu_domain *domain, | |||
738 | detach_device(dev, dma_domain); | 717 | detach_device(dev, dma_domain); |
739 | else | 718 | else |
740 | pr_debug("missing fsl,liodn property at %s\n", | 719 | pr_debug("missing fsl,liodn property at %s\n", |
741 | dev->of_node->full_name); | 720 | dev->of_node->full_name); |
742 | } | 721 | } |
743 | 722 | ||
744 | static int configure_domain_geometry(struct iommu_domain *domain, void *data) | 723 | static int configure_domain_geometry(struct iommu_domain *domain, void *data) |
@@ -754,10 +733,10 @@ static int configure_domain_geometry(struct iommu_domain *domain, void *data) | |||
754 | * DMA outside of the geometry. | 733 | * DMA outside of the geometry. |
755 | */ | 734 | */ |
756 | if (check_size(geom_size, geom_attr->aperture_start) || | 735 | if (check_size(geom_size, geom_attr->aperture_start) || |
757 | !geom_attr->force_aperture) { | 736 | !geom_attr->force_aperture) { |
758 | pr_debug("Invalid PAMU geometry attributes\n"); | 737 | pr_debug("Invalid PAMU geometry attributes\n"); |
759 | return -EINVAL; | 738 | return -EINVAL; |
760 | } | 739 | } |
761 | 740 | ||
762 | spin_lock_irqsave(&dma_domain->domain_lock, flags); | 741 | spin_lock_irqsave(&dma_domain->domain_lock, flags); |
763 | if (dma_domain->enabled) { | 742 | if (dma_domain->enabled) { |
@@ -786,7 +765,7 @@ static int configure_domain_stash(struct fsl_dma_domain *dma_domain, void *data) | |||
786 | spin_lock_irqsave(&dma_domain->domain_lock, flags); | 765 | spin_lock_irqsave(&dma_domain->domain_lock, flags); |
787 | 766 | ||
788 | memcpy(&dma_domain->dma_stash, stash_attr, | 767 | memcpy(&dma_domain->dma_stash, stash_attr, |
789 | sizeof(struct pamu_stash_attribute)); | 768 | sizeof(struct pamu_stash_attribute)); |
790 | 769 | ||
791 | dma_domain->stash_id = get_stash_id(stash_attr->cache, | 770 | dma_domain->stash_id = get_stash_id(stash_attr->cache, |
792 | stash_attr->cpu); | 771 | stash_attr->cpu); |
@@ -803,7 +782,7 @@ static int configure_domain_stash(struct fsl_dma_domain *dma_domain, void *data) | |||
803 | return ret; | 782 | return ret; |
804 | } | 783 | } |
805 | 784 | ||
806 | /* Configure domain dma state i.e. enable/disable DMA*/ | 785 | /* Configure domain dma state i.e. enable/disable DMA */ |
807 | static int configure_domain_dma_state(struct fsl_dma_domain *dma_domain, bool enable) | 786 | static int configure_domain_dma_state(struct fsl_dma_domain *dma_domain, bool enable) |
808 | { | 787 | { |
809 | struct device_domain_info *info; | 788 | struct device_domain_info *info; |
@@ -819,8 +798,7 @@ static int configure_domain_dma_state(struct fsl_dma_domain *dma_domain, bool en | |||
819 | } | 798 | } |
820 | 799 | ||
821 | dma_domain->enabled = enable; | 800 | dma_domain->enabled = enable; |
822 | list_for_each_entry(info, &dma_domain->devices, | 801 | list_for_each_entry(info, &dma_domain->devices, link) { |
823 | link) { | ||
824 | ret = (enable) ? pamu_enable_liodn(info->liodn) : | 802 | ret = (enable) ? pamu_enable_liodn(info->liodn) : |
825 | pamu_disable_liodn(info->liodn); | 803 | pamu_disable_liodn(info->liodn); |
826 | if (ret) | 804 | if (ret) |
@@ -833,12 +811,11 @@ static int configure_domain_dma_state(struct fsl_dma_domain *dma_domain, bool en | |||
833 | } | 811 | } |
834 | 812 | ||
835 | static int fsl_pamu_set_domain_attr(struct iommu_domain *domain, | 813 | static int fsl_pamu_set_domain_attr(struct iommu_domain *domain, |
836 | enum iommu_attr attr_type, void *data) | 814 | enum iommu_attr attr_type, void *data) |
837 | { | 815 | { |
838 | struct fsl_dma_domain *dma_domain = domain->priv; | 816 | struct fsl_dma_domain *dma_domain = domain->priv; |
839 | int ret = 0; | 817 | int ret = 0; |
840 | 818 | ||
841 | |||
842 | switch (attr_type) { | 819 | switch (attr_type) { |
843 | case DOMAIN_ATTR_GEOMETRY: | 820 | case DOMAIN_ATTR_GEOMETRY: |
844 | ret = configure_domain_geometry(domain, data); | 821 | ret = configure_domain_geometry(domain, data); |
@@ -853,22 +830,21 @@ static int fsl_pamu_set_domain_attr(struct iommu_domain *domain, | |||
853 | pr_debug("Unsupported attribute type\n"); | 830 | pr_debug("Unsupported attribute type\n"); |
854 | ret = -EINVAL; | 831 | ret = -EINVAL; |
855 | break; | 832 | break; |
856 | }; | 833 | } |
857 | 834 | ||
858 | return ret; | 835 | return ret; |
859 | } | 836 | } |
860 | 837 | ||
861 | static int fsl_pamu_get_domain_attr(struct iommu_domain *domain, | 838 | static int fsl_pamu_get_domain_attr(struct iommu_domain *domain, |
862 | enum iommu_attr attr_type, void *data) | 839 | enum iommu_attr attr_type, void *data) |
863 | { | 840 | { |
864 | struct fsl_dma_domain *dma_domain = domain->priv; | 841 | struct fsl_dma_domain *dma_domain = domain->priv; |
865 | int ret = 0; | 842 | int ret = 0; |
866 | 843 | ||
867 | |||
868 | switch (attr_type) { | 844 | switch (attr_type) { |
869 | case DOMAIN_ATTR_FSL_PAMU_STASH: | 845 | case DOMAIN_ATTR_FSL_PAMU_STASH: |
870 | memcpy((struct pamu_stash_attribute *) data, &dma_domain->dma_stash, | 846 | memcpy(data, &dma_domain->dma_stash, |
871 | sizeof(struct pamu_stash_attribute)); | 847 | sizeof(struct pamu_stash_attribute)); |
872 | break; | 848 | break; |
873 | case DOMAIN_ATTR_FSL_PAMU_ENABLE: | 849 | case DOMAIN_ATTR_FSL_PAMU_ENABLE: |
874 | *(int *)data = dma_domain->enabled; | 850 | *(int *)data = dma_domain->enabled; |
@@ -880,7 +856,7 @@ static int fsl_pamu_get_domain_attr(struct iommu_domain *domain, | |||
880 | pr_debug("Unsupported attribute type\n"); | 856 | pr_debug("Unsupported attribute type\n"); |
881 | ret = -EINVAL; | 857 | ret = -EINVAL; |
882 | break; | 858 | break; |
883 | }; | 859 | } |
884 | 860 | ||
885 | return ret; | 861 | return ret; |
886 | } | 862 | } |
@@ -903,11 +879,8 @@ static bool check_pci_ctl_endpt_part(struct pci_controller *pci_ctl) | |||
903 | /* Check the PCI controller version number by readding BRR1 register */ | 879 | /* Check the PCI controller version number by readding BRR1 register */ |
904 | version = in_be32(pci_ctl->cfg_addr + (PCI_FSL_BRR1 >> 2)); | 880 | version = in_be32(pci_ctl->cfg_addr + (PCI_FSL_BRR1 >> 2)); |
905 | version &= PCI_FSL_BRR1_VER; | 881 | version &= PCI_FSL_BRR1_VER; |
906 | /* If PCI controller version is >= 0x204 we can partition endpoints*/ | 882 | /* If PCI controller version is >= 0x204 we can partition endpoints */ |
907 | if (version >= 0x204) | 883 | return version >= 0x204; |
908 | return 1; | ||
909 | |||
910 | return 0; | ||
911 | } | 884 | } |
912 | 885 | ||
913 | /* Get iommu group information from peer devices or devices on the parent bus */ | 886 | /* Get iommu group information from peer devices or devices on the parent bus */ |
@@ -968,8 +941,9 @@ static struct iommu_group *get_pci_device_group(struct pci_dev *pdev) | |||
968 | if (pci_ctl->parent->iommu_group) { | 941 | if (pci_ctl->parent->iommu_group) { |
969 | group = get_device_iommu_group(pci_ctl->parent); | 942 | group = get_device_iommu_group(pci_ctl->parent); |
970 | iommu_group_remove_device(pci_ctl->parent); | 943 | iommu_group_remove_device(pci_ctl->parent); |
971 | } else | 944 | } else { |
972 | group = get_shared_pci_device_group(pdev); | 945 | group = get_shared_pci_device_group(pdev); |
946 | } | ||
973 | } | 947 | } |
974 | 948 | ||
975 | if (!group) | 949 | if (!group) |
@@ -1055,11 +1029,12 @@ static int fsl_pamu_set_windows(struct iommu_domain *domain, u32 w_count) | |||
1055 | } | 1029 | } |
1056 | 1030 | ||
1057 | ret = pamu_set_domain_geometry(dma_domain, &domain->geometry, | 1031 | ret = pamu_set_domain_geometry(dma_domain, &domain->geometry, |
1058 | ((w_count > 1) ? w_count : 0)); | 1032 | w_count > 1 ? w_count : 0); |
1059 | if (!ret) { | 1033 | if (!ret) { |
1060 | kfree(dma_domain->win_arr); | 1034 | kfree(dma_domain->win_arr); |
1061 | dma_domain->win_arr = kzalloc(sizeof(struct dma_window) * | 1035 | dma_domain->win_arr = kcalloc(w_count, |
1062 | w_count, GFP_ATOMIC); | 1036 | sizeof(*dma_domain->win_arr), |
1037 | GFP_ATOMIC); | ||
1063 | if (!dma_domain->win_arr) { | 1038 | if (!dma_domain->win_arr) { |
1064 | spin_unlock_irqrestore(&dma_domain->domain_lock, flags); | 1039 | spin_unlock_irqrestore(&dma_domain->domain_lock, flags); |
1065 | return -ENOMEM; | 1040 | return -ENOMEM; |
@@ -1095,7 +1070,7 @@ static const struct iommu_ops fsl_pamu_ops = { | |||
1095 | .remove_device = fsl_pamu_remove_device, | 1070 | .remove_device = fsl_pamu_remove_device, |
1096 | }; | 1071 | }; |
1097 | 1072 | ||
1098 | int pamu_domain_init(void) | 1073 | int __init pamu_domain_init(void) |
1099 | { | 1074 | { |
1100 | int ret = 0; | 1075 | int ret = 0; |
1101 | 1076 | ||