diff options
author | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2014-07-24 15:36:56 -0400 |
---|---|---|
committer | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2014-07-24 15:36:56 -0400 |
commit | b9f12a5d97f652c77ef6803dccd0d40d1290f5be (patch) | |
tree | 8f58c8620ffef0d350a5ec022feda492a96b179a /drivers/iommu | |
parent | 9d8dc3e529a19e427fd379118acd132520935c5d (diff) | |
parent | 9a3c4145af32125c5ee39c0272662b47307a8323 (diff) |
Merge tag 'v3.16-rc6' into next
Merge with mainline to bring in changes to MFD to allow merging
ipaq-micro-ts driver.
Diffstat (limited to 'drivers/iommu')
-rw-r--r-- | drivers/iommu/Kconfig | 26 | ||||
-rw-r--r-- | drivers/iommu/Makefile | 1 | ||||
-rw-r--r-- | drivers/iommu/amd_iommu.c | 10 | ||||
-rw-r--r-- | drivers/iommu/amd_iommu_init.c | 2 | ||||
-rw-r--r-- | drivers/iommu/amd_iommu_v2.c | 196 | ||||
-rw-r--r-- | drivers/iommu/arm-smmu.c | 4 | ||||
-rw-r--r-- | drivers/iommu/dmar.c | 8 | ||||
-rw-r--r-- | drivers/iommu/exynos-iommu.c | 1052 | ||||
-rw-r--r-- | drivers/iommu/fsl_pamu.c | 11 | ||||
-rw-r--r-- | drivers/iommu/fsl_pamu_domain.c | 18 | ||||
-rw-r--r-- | drivers/iommu/intel-iommu.c | 42 | ||||
-rw-r--r-- | drivers/iommu/ipmmu-vmsa.c | 1255 | ||||
-rw-r--r-- | drivers/iommu/irq_remapping.c | 12 | ||||
-rw-r--r-- | drivers/iommu/msm_iommu_dev.c | 38 | ||||
-rw-r--r-- | drivers/iommu/omap-iommu.c | 31 | ||||
-rw-r--r-- | drivers/iommu/omap-iopgtable.h | 3 | ||||
-rw-r--r-- | drivers/iommu/shmobile-ipmmu.c | 20 |
17 files changed, 2062 insertions, 667 deletions
diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig index df56e4c74a7e..d260605e6d5f 100644 --- a/drivers/iommu/Kconfig +++ b/drivers/iommu/Kconfig | |||
@@ -178,13 +178,13 @@ config TEGRA_IOMMU_SMMU | |||
178 | 178 | ||
179 | config EXYNOS_IOMMU | 179 | config EXYNOS_IOMMU |
180 | bool "Exynos IOMMU Support" | 180 | bool "Exynos IOMMU Support" |
181 | depends on ARCH_EXYNOS && EXYNOS_DEV_SYSMMU | 181 | depends on ARCH_EXYNOS |
182 | select IOMMU_API | 182 | select IOMMU_API |
183 | help | 183 | help |
184 | Support for the IOMMU(System MMU) of Samsung Exynos application | 184 | Support for the IOMMU (System MMU) of Samsung Exynos application |
185 | processor family. This enables H/W multimedia accellerators to see | 185 | processor family. This enables H/W multimedia accelerators to see |
186 | non-linear physical memory chunks as a linear memory in their | 186 | non-linear physical memory chunks as linear memory in their |
187 | address spaces | 187 | address space. |
188 | 188 | ||
189 | If unsure, say N here. | 189 | If unsure, say N here. |
190 | 190 | ||
@@ -193,9 +193,9 @@ config EXYNOS_IOMMU_DEBUG | |||
193 | depends on EXYNOS_IOMMU | 193 | depends on EXYNOS_IOMMU |
194 | help | 194 | help |
195 | Select this to see the detailed log message that shows what | 195 | Select this to see the detailed log message that shows what |
196 | happens in the IOMMU driver | 196 | happens in the IOMMU driver. |
197 | 197 | ||
198 | Say N unless you need kernel log message for IOMMU debugging | 198 | Say N unless you need kernel log message for IOMMU debugging. |
199 | 199 | ||
200 | config SHMOBILE_IPMMU | 200 | config SHMOBILE_IPMMU |
201 | bool | 201 | bool |
@@ -272,6 +272,18 @@ config SHMOBILE_IOMMU_L1SIZE | |||
272 | default 256 if SHMOBILE_IOMMU_ADDRSIZE_64MB | 272 | default 256 if SHMOBILE_IOMMU_ADDRSIZE_64MB |
273 | default 128 if SHMOBILE_IOMMU_ADDRSIZE_32MB | 273 | default 128 if SHMOBILE_IOMMU_ADDRSIZE_32MB |
274 | 274 | ||
275 | config IPMMU_VMSA | ||
276 | bool "Renesas VMSA-compatible IPMMU" | ||
277 | depends on ARM_LPAE | ||
278 | depends on ARCH_SHMOBILE || COMPILE_TEST | ||
279 | select IOMMU_API | ||
280 | select ARM_DMA_USE_IOMMU | ||
281 | help | ||
282 | Support for the Renesas VMSA-compatible IPMMU Renesas found in the | ||
283 | R-Mobile APE6 and R-Car H2/M2 SoCs. | ||
284 | |||
285 | If unsure, say N. | ||
286 | |||
275 | config SPAPR_TCE_IOMMU | 287 | config SPAPR_TCE_IOMMU |
276 | bool "sPAPR TCE IOMMU Support" | 288 | bool "sPAPR TCE IOMMU Support" |
277 | depends on PPC_POWERNV || PPC_PSERIES | 289 | depends on PPC_POWERNV || PPC_PSERIES |
diff --git a/drivers/iommu/Makefile b/drivers/iommu/Makefile index 5d58bf16e9e3..8893bad048e0 100644 --- a/drivers/iommu/Makefile +++ b/drivers/iommu/Makefile | |||
@@ -7,6 +7,7 @@ obj-$(CONFIG_AMD_IOMMU_V2) += amd_iommu_v2.o | |||
7 | obj-$(CONFIG_ARM_SMMU) += arm-smmu.o | 7 | obj-$(CONFIG_ARM_SMMU) += arm-smmu.o |
8 | obj-$(CONFIG_DMAR_TABLE) += dmar.o | 8 | obj-$(CONFIG_DMAR_TABLE) += dmar.o |
9 | obj-$(CONFIG_INTEL_IOMMU) += iova.o intel-iommu.o | 9 | obj-$(CONFIG_INTEL_IOMMU) += iova.o intel-iommu.o |
10 | obj-$(CONFIG_IPMMU_VMSA) += ipmmu-vmsa.o | ||
10 | obj-$(CONFIG_IRQ_REMAP) += intel_irq_remapping.o irq_remapping.o | 11 | obj-$(CONFIG_IRQ_REMAP) += intel_irq_remapping.o irq_remapping.o |
11 | obj-$(CONFIG_OMAP_IOMMU) += omap-iommu.o | 12 | obj-$(CONFIG_OMAP_IOMMU) += omap-iommu.o |
12 | obj-$(CONFIG_OMAP_IOMMU) += omap-iommu2.o | 13 | obj-$(CONFIG_OMAP_IOMMU) += omap-iommu2.o |
diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c index c949520bd196..4aec6a29e316 100644 --- a/drivers/iommu/amd_iommu.c +++ b/drivers/iommu/amd_iommu.c | |||
@@ -3499,8 +3499,6 @@ int __init amd_iommu_init_passthrough(void) | |||
3499 | { | 3499 | { |
3500 | struct iommu_dev_data *dev_data; | 3500 | struct iommu_dev_data *dev_data; |
3501 | struct pci_dev *dev = NULL; | 3501 | struct pci_dev *dev = NULL; |
3502 | struct amd_iommu *iommu; | ||
3503 | u16 devid; | ||
3504 | int ret; | 3502 | int ret; |
3505 | 3503 | ||
3506 | ret = alloc_passthrough_domain(); | 3504 | ret = alloc_passthrough_domain(); |
@@ -3514,12 +3512,6 @@ int __init amd_iommu_init_passthrough(void) | |||
3514 | dev_data = get_dev_data(&dev->dev); | 3512 | dev_data = get_dev_data(&dev->dev); |
3515 | dev_data->passthrough = true; | 3513 | dev_data->passthrough = true; |
3516 | 3514 | ||
3517 | devid = get_device_id(&dev->dev); | ||
3518 | |||
3519 | iommu = amd_iommu_rlookup_table[devid]; | ||
3520 | if (!iommu) | ||
3521 | continue; | ||
3522 | |||
3523 | attach_device(&dev->dev, pt_domain); | 3515 | attach_device(&dev->dev, pt_domain); |
3524 | } | 3516 | } |
3525 | 3517 | ||
@@ -3999,7 +3991,7 @@ static struct irq_remap_table *get_irq_table(u16 devid, bool ioapic) | |||
3999 | iommu_flush_dte(iommu, devid); | 3991 | iommu_flush_dte(iommu, devid); |
4000 | if (devid != alias) { | 3992 | if (devid != alias) { |
4001 | irq_lookup_table[alias] = table; | 3993 | irq_lookup_table[alias] = table; |
4002 | set_dte_irq_entry(devid, table); | 3994 | set_dte_irq_entry(alias, table); |
4003 | iommu_flush_dte(iommu, alias); | 3995 | iommu_flush_dte(iommu, alias); |
4004 | } | 3996 | } |
4005 | 3997 | ||
diff --git a/drivers/iommu/amd_iommu_init.c b/drivers/iommu/amd_iommu_init.c index b76c58dbe30c..0e08545d7298 100644 --- a/drivers/iommu/amd_iommu_init.c +++ b/drivers/iommu/amd_iommu_init.c | |||
@@ -788,7 +788,7 @@ static void __init set_device_exclusion_range(u16 devid, struct ivmd_header *m) | |||
788 | * per device. But we can enable the exclusion range per | 788 | * per device. But we can enable the exclusion range per |
789 | * device. This is done here | 789 | * device. This is done here |
790 | */ | 790 | */ |
791 | set_dev_entry_bit(m->devid, DEV_ENTRY_EX); | 791 | set_dev_entry_bit(devid, DEV_ENTRY_EX); |
792 | iommu->exclusion_start = m->range_start; | 792 | iommu->exclusion_start = m->range_start; |
793 | iommu->exclusion_length = m->range_length; | 793 | iommu->exclusion_length = m->range_length; |
794 | } | 794 | } |
diff --git a/drivers/iommu/amd_iommu_v2.c b/drivers/iommu/amd_iommu_v2.c index 5208828792e6..499b4366a98d 100644 --- a/drivers/iommu/amd_iommu_v2.c +++ b/drivers/iommu/amd_iommu_v2.c | |||
@@ -45,17 +45,22 @@ struct pri_queue { | |||
45 | struct pasid_state { | 45 | struct pasid_state { |
46 | struct list_head list; /* For global state-list */ | 46 | struct list_head list; /* For global state-list */ |
47 | atomic_t count; /* Reference count */ | 47 | atomic_t count; /* Reference count */ |
48 | unsigned mmu_notifier_count; /* Counting nested mmu_notifier | ||
49 | calls */ | ||
48 | struct task_struct *task; /* Task bound to this PASID */ | 50 | struct task_struct *task; /* Task bound to this PASID */ |
49 | struct mm_struct *mm; /* mm_struct for the faults */ | 51 | struct mm_struct *mm; /* mm_struct for the faults */ |
50 | struct mmu_notifier mn; /* mmu_otifier handle */ | 52 | struct mmu_notifier mn; /* mmu_otifier handle */ |
51 | struct pri_queue pri[PRI_QUEUE_SIZE]; /* PRI tag states */ | 53 | struct pri_queue pri[PRI_QUEUE_SIZE]; /* PRI tag states */ |
52 | struct device_state *device_state; /* Link to our device_state */ | 54 | struct device_state *device_state; /* Link to our device_state */ |
53 | int pasid; /* PASID index */ | 55 | int pasid; /* PASID index */ |
54 | spinlock_t lock; /* Protect pri_queues */ | 56 | spinlock_t lock; /* Protect pri_queues and |
57 | mmu_notifer_count */ | ||
55 | wait_queue_head_t wq; /* To wait for count == 0 */ | 58 | wait_queue_head_t wq; /* To wait for count == 0 */ |
56 | }; | 59 | }; |
57 | 60 | ||
58 | struct device_state { | 61 | struct device_state { |
62 | struct list_head list; | ||
63 | u16 devid; | ||
59 | atomic_t count; | 64 | atomic_t count; |
60 | struct pci_dev *pdev; | 65 | struct pci_dev *pdev; |
61 | struct pasid_state **states; | 66 | struct pasid_state **states; |
@@ -81,13 +86,9 @@ struct fault { | |||
81 | u16 flags; | 86 | u16 flags; |
82 | }; | 87 | }; |
83 | 88 | ||
84 | static struct device_state **state_table; | 89 | static LIST_HEAD(state_list); |
85 | static spinlock_t state_lock; | 90 | static spinlock_t state_lock; |
86 | 91 | ||
87 | /* List and lock for all pasid_states */ | ||
88 | static LIST_HEAD(pasid_state_list); | ||
89 | static DEFINE_SPINLOCK(ps_lock); | ||
90 | |||
91 | static struct workqueue_struct *iommu_wq; | 92 | static struct workqueue_struct *iommu_wq; |
92 | 93 | ||
93 | /* | 94 | /* |
@@ -99,7 +100,6 @@ static u64 *empty_page_table; | |||
99 | 100 | ||
100 | static void free_pasid_states(struct device_state *dev_state); | 101 | static void free_pasid_states(struct device_state *dev_state); |
101 | static void unbind_pasid(struct device_state *dev_state, int pasid); | 102 | static void unbind_pasid(struct device_state *dev_state, int pasid); |
102 | static int task_exit(struct notifier_block *nb, unsigned long e, void *data); | ||
103 | 103 | ||
104 | static u16 device_id(struct pci_dev *pdev) | 104 | static u16 device_id(struct pci_dev *pdev) |
105 | { | 105 | { |
@@ -111,13 +111,25 @@ static u16 device_id(struct pci_dev *pdev) | |||
111 | return devid; | 111 | return devid; |
112 | } | 112 | } |
113 | 113 | ||
114 | static struct device_state *__get_device_state(u16 devid) | ||
115 | { | ||
116 | struct device_state *dev_state; | ||
117 | |||
118 | list_for_each_entry(dev_state, &state_list, list) { | ||
119 | if (dev_state->devid == devid) | ||
120 | return dev_state; | ||
121 | } | ||
122 | |||
123 | return NULL; | ||
124 | } | ||
125 | |||
114 | static struct device_state *get_device_state(u16 devid) | 126 | static struct device_state *get_device_state(u16 devid) |
115 | { | 127 | { |
116 | struct device_state *dev_state; | 128 | struct device_state *dev_state; |
117 | unsigned long flags; | 129 | unsigned long flags; |
118 | 130 | ||
119 | spin_lock_irqsave(&state_lock, flags); | 131 | spin_lock_irqsave(&state_lock, flags); |
120 | dev_state = state_table[devid]; | 132 | dev_state = __get_device_state(devid); |
121 | if (dev_state != NULL) | 133 | if (dev_state != NULL) |
122 | atomic_inc(&dev_state->count); | 134 | atomic_inc(&dev_state->count); |
123 | spin_unlock_irqrestore(&state_lock, flags); | 135 | spin_unlock_irqrestore(&state_lock, flags); |
@@ -158,29 +170,6 @@ static void put_device_state_wait(struct device_state *dev_state) | |||
158 | free_device_state(dev_state); | 170 | free_device_state(dev_state); |
159 | } | 171 | } |
160 | 172 | ||
161 | static struct notifier_block profile_nb = { | ||
162 | .notifier_call = task_exit, | ||
163 | }; | ||
164 | |||
165 | static void link_pasid_state(struct pasid_state *pasid_state) | ||
166 | { | ||
167 | spin_lock(&ps_lock); | ||
168 | list_add_tail(&pasid_state->list, &pasid_state_list); | ||
169 | spin_unlock(&ps_lock); | ||
170 | } | ||
171 | |||
172 | static void __unlink_pasid_state(struct pasid_state *pasid_state) | ||
173 | { | ||
174 | list_del(&pasid_state->list); | ||
175 | } | ||
176 | |||
177 | static void unlink_pasid_state(struct pasid_state *pasid_state) | ||
178 | { | ||
179 | spin_lock(&ps_lock); | ||
180 | __unlink_pasid_state(pasid_state); | ||
181 | spin_unlock(&ps_lock); | ||
182 | } | ||
183 | |||
184 | /* Must be called under dev_state->lock */ | 173 | /* Must be called under dev_state->lock */ |
185 | static struct pasid_state **__get_pasid_state_ptr(struct device_state *dev_state, | 174 | static struct pasid_state **__get_pasid_state_ptr(struct device_state *dev_state, |
186 | int pasid, bool alloc) | 175 | int pasid, bool alloc) |
@@ -337,7 +326,6 @@ static void unbind_pasid(struct device_state *dev_state, int pasid) | |||
337 | if (pasid_state == NULL) | 326 | if (pasid_state == NULL) |
338 | return; | 327 | return; |
339 | 328 | ||
340 | unlink_pasid_state(pasid_state); | ||
341 | __unbind_pasid(pasid_state); | 329 | __unbind_pasid(pasid_state); |
342 | put_pasid_state_wait(pasid_state); /* Reference taken in this function */ | 330 | put_pasid_state_wait(pasid_state); /* Reference taken in this function */ |
343 | } | 331 | } |
@@ -379,7 +367,12 @@ static void free_pasid_states(struct device_state *dev_state) | |||
379 | continue; | 367 | continue; |
380 | 368 | ||
381 | put_pasid_state(pasid_state); | 369 | put_pasid_state(pasid_state); |
382 | unbind_pasid(dev_state, i); | 370 | |
371 | /* | ||
372 | * This will call the mn_release function and | ||
373 | * unbind the PASID | ||
374 | */ | ||
375 | mmu_notifier_unregister(&pasid_state->mn, pasid_state->mm); | ||
383 | } | 376 | } |
384 | 377 | ||
385 | if (dev_state->pasid_levels == 2) | 378 | if (dev_state->pasid_levels == 2) |
@@ -439,12 +432,19 @@ static void mn_invalidate_range_start(struct mmu_notifier *mn, | |||
439 | { | 432 | { |
440 | struct pasid_state *pasid_state; | 433 | struct pasid_state *pasid_state; |
441 | struct device_state *dev_state; | 434 | struct device_state *dev_state; |
435 | unsigned long flags; | ||
442 | 436 | ||
443 | pasid_state = mn_to_state(mn); | 437 | pasid_state = mn_to_state(mn); |
444 | dev_state = pasid_state->device_state; | 438 | dev_state = pasid_state->device_state; |
445 | 439 | ||
446 | amd_iommu_domain_set_gcr3(dev_state->domain, pasid_state->pasid, | 440 | spin_lock_irqsave(&pasid_state->lock, flags); |
447 | __pa(empty_page_table)); | 441 | if (pasid_state->mmu_notifier_count == 0) { |
442 | amd_iommu_domain_set_gcr3(dev_state->domain, | ||
443 | pasid_state->pasid, | ||
444 | __pa(empty_page_table)); | ||
445 | } | ||
446 | pasid_state->mmu_notifier_count += 1; | ||
447 | spin_unlock_irqrestore(&pasid_state->lock, flags); | ||
448 | } | 448 | } |
449 | 449 | ||
450 | static void mn_invalidate_range_end(struct mmu_notifier *mn, | 450 | static void mn_invalidate_range_end(struct mmu_notifier *mn, |
@@ -453,15 +453,39 @@ static void mn_invalidate_range_end(struct mmu_notifier *mn, | |||
453 | { | 453 | { |
454 | struct pasid_state *pasid_state; | 454 | struct pasid_state *pasid_state; |
455 | struct device_state *dev_state; | 455 | struct device_state *dev_state; |
456 | unsigned long flags; | ||
456 | 457 | ||
457 | pasid_state = mn_to_state(mn); | 458 | pasid_state = mn_to_state(mn); |
458 | dev_state = pasid_state->device_state; | 459 | dev_state = pasid_state->device_state; |
459 | 460 | ||
460 | amd_iommu_domain_set_gcr3(dev_state->domain, pasid_state->pasid, | 461 | spin_lock_irqsave(&pasid_state->lock, flags); |
461 | __pa(pasid_state->mm->pgd)); | 462 | pasid_state->mmu_notifier_count -= 1; |
463 | if (pasid_state->mmu_notifier_count == 0) { | ||
464 | amd_iommu_domain_set_gcr3(dev_state->domain, | ||
465 | pasid_state->pasid, | ||
466 | __pa(pasid_state->mm->pgd)); | ||
467 | } | ||
468 | spin_unlock_irqrestore(&pasid_state->lock, flags); | ||
469 | } | ||
470 | |||
471 | static void mn_release(struct mmu_notifier *mn, struct mm_struct *mm) | ||
472 | { | ||
473 | struct pasid_state *pasid_state; | ||
474 | struct device_state *dev_state; | ||
475 | |||
476 | might_sleep(); | ||
477 | |||
478 | pasid_state = mn_to_state(mn); | ||
479 | dev_state = pasid_state->device_state; | ||
480 | |||
481 | if (pasid_state->device_state->inv_ctx_cb) | ||
482 | dev_state->inv_ctx_cb(dev_state->pdev, pasid_state->pasid); | ||
483 | |||
484 | unbind_pasid(dev_state, pasid_state->pasid); | ||
462 | } | 485 | } |
463 | 486 | ||
464 | static struct mmu_notifier_ops iommu_mn = { | 487 | static struct mmu_notifier_ops iommu_mn = { |
488 | .release = mn_release, | ||
465 | .clear_flush_young = mn_clear_flush_young, | 489 | .clear_flush_young = mn_clear_flush_young, |
466 | .change_pte = mn_change_pte, | 490 | .change_pte = mn_change_pte, |
467 | .invalidate_page = mn_invalidate_page, | 491 | .invalidate_page = mn_invalidate_page, |
@@ -504,8 +528,10 @@ static void do_fault(struct work_struct *work) | |||
504 | 528 | ||
505 | write = !!(fault->flags & PPR_FAULT_WRITE); | 529 | write = !!(fault->flags & PPR_FAULT_WRITE); |
506 | 530 | ||
531 | down_read(&fault->state->mm->mmap_sem); | ||
507 | npages = get_user_pages(fault->state->task, fault->state->mm, | 532 | npages = get_user_pages(fault->state->task, fault->state->mm, |
508 | fault->address, 1, write, 0, &page, NULL); | 533 | fault->address, 1, write, 0, &page, NULL); |
534 | up_read(&fault->state->mm->mmap_sem); | ||
509 | 535 | ||
510 | if (npages == 1) { | 536 | if (npages == 1) { |
511 | put_page(page); | 537 | put_page(page); |
@@ -604,53 +630,6 @@ static struct notifier_block ppr_nb = { | |||
604 | .notifier_call = ppr_notifier, | 630 | .notifier_call = ppr_notifier, |
605 | }; | 631 | }; |
606 | 632 | ||
607 | static int task_exit(struct notifier_block *nb, unsigned long e, void *data) | ||
608 | { | ||
609 | struct pasid_state *pasid_state; | ||
610 | struct task_struct *task; | ||
611 | |||
612 | task = data; | ||
613 | |||
614 | /* | ||
615 | * Using this notifier is a hack - but there is no other choice | ||
616 | * at the moment. What I really want is a sleeping notifier that | ||
617 | * is called when an MM goes down. But such a notifier doesn't | ||
618 | * exist yet. The notifier needs to sleep because it has to make | ||
619 | * sure that the device does not use the PASID and the address | ||
620 | * space anymore before it is destroyed. This includes waiting | ||
621 | * for pending PRI requests to pass the workqueue. The | ||
622 | * MMU-Notifiers would be a good fit, but they use RCU and so | ||
623 | * they are not allowed to sleep. Lets see how we can solve this | ||
624 | * in a more intelligent way in the future. | ||
625 | */ | ||
626 | again: | ||
627 | spin_lock(&ps_lock); | ||
628 | list_for_each_entry(pasid_state, &pasid_state_list, list) { | ||
629 | struct device_state *dev_state; | ||
630 | int pasid; | ||
631 | |||
632 | if (pasid_state->task != task) | ||
633 | continue; | ||
634 | |||
635 | /* Drop Lock and unbind */ | ||
636 | spin_unlock(&ps_lock); | ||
637 | |||
638 | dev_state = pasid_state->device_state; | ||
639 | pasid = pasid_state->pasid; | ||
640 | |||
641 | if (pasid_state->device_state->inv_ctx_cb) | ||
642 | dev_state->inv_ctx_cb(dev_state->pdev, pasid); | ||
643 | |||
644 | unbind_pasid(dev_state, pasid); | ||
645 | |||
646 | /* Task may be in the list multiple times */ | ||
647 | goto again; | ||
648 | } | ||
649 | spin_unlock(&ps_lock); | ||
650 | |||
651 | return NOTIFY_OK; | ||
652 | } | ||
653 | |||
654 | int amd_iommu_bind_pasid(struct pci_dev *pdev, int pasid, | 633 | int amd_iommu_bind_pasid(struct pci_dev *pdev, int pasid, |
655 | struct task_struct *task) | 634 | struct task_struct *task) |
656 | { | 635 | { |
@@ -703,8 +682,6 @@ int amd_iommu_bind_pasid(struct pci_dev *pdev, int pasid, | |||
703 | if (ret) | 682 | if (ret) |
704 | goto out_clear_state; | 683 | goto out_clear_state; |
705 | 684 | ||
706 | link_pasid_state(pasid_state); | ||
707 | |||
708 | return 0; | 685 | return 0; |
709 | 686 | ||
710 | out_clear_state: | 687 | out_clear_state: |
@@ -725,6 +702,7 @@ EXPORT_SYMBOL(amd_iommu_bind_pasid); | |||
725 | 702 | ||
726 | void amd_iommu_unbind_pasid(struct pci_dev *pdev, int pasid) | 703 | void amd_iommu_unbind_pasid(struct pci_dev *pdev, int pasid) |
727 | { | 704 | { |
705 | struct pasid_state *pasid_state; | ||
728 | struct device_state *dev_state; | 706 | struct device_state *dev_state; |
729 | u16 devid; | 707 | u16 devid; |
730 | 708 | ||
@@ -741,7 +719,17 @@ void amd_iommu_unbind_pasid(struct pci_dev *pdev, int pasid) | |||
741 | if (pasid < 0 || pasid >= dev_state->max_pasids) | 719 | if (pasid < 0 || pasid >= dev_state->max_pasids) |
742 | goto out; | 720 | goto out; |
743 | 721 | ||
744 | unbind_pasid(dev_state, pasid); | 722 | pasid_state = get_pasid_state(dev_state, pasid); |
723 | if (pasid_state == NULL) | ||
724 | goto out; | ||
725 | /* | ||
726 | * Drop reference taken here. We are safe because we still hold | ||
727 | * the reference taken in the amd_iommu_bind_pasid function. | ||
728 | */ | ||
729 | put_pasid_state(pasid_state); | ||
730 | |||
731 | /* This will call the mn_release function and unbind the PASID */ | ||
732 | mmu_notifier_unregister(&pasid_state->mn, pasid_state->mm); | ||
745 | 733 | ||
746 | out: | 734 | out: |
747 | put_device_state(dev_state); | 735 | put_device_state(dev_state); |
@@ -771,7 +759,8 @@ int amd_iommu_init_device(struct pci_dev *pdev, int pasids) | |||
771 | 759 | ||
772 | spin_lock_init(&dev_state->lock); | 760 | spin_lock_init(&dev_state->lock); |
773 | init_waitqueue_head(&dev_state->wq); | 761 | init_waitqueue_head(&dev_state->wq); |
774 | dev_state->pdev = pdev; | 762 | dev_state->pdev = pdev; |
763 | dev_state->devid = devid; | ||
775 | 764 | ||
776 | tmp = pasids; | 765 | tmp = pasids; |
777 | for (dev_state->pasid_levels = 0; (tmp - 1) & ~0x1ff; tmp >>= 9) | 766 | for (dev_state->pasid_levels = 0; (tmp - 1) & ~0x1ff; tmp >>= 9) |
@@ -801,13 +790,13 @@ int amd_iommu_init_device(struct pci_dev *pdev, int pasids) | |||
801 | 790 | ||
802 | spin_lock_irqsave(&state_lock, flags); | 791 | spin_lock_irqsave(&state_lock, flags); |
803 | 792 | ||
804 | if (state_table[devid] != NULL) { | 793 | if (__get_device_state(devid) != NULL) { |
805 | spin_unlock_irqrestore(&state_lock, flags); | 794 | spin_unlock_irqrestore(&state_lock, flags); |
806 | ret = -EBUSY; | 795 | ret = -EBUSY; |
807 | goto out_free_domain; | 796 | goto out_free_domain; |
808 | } | 797 | } |
809 | 798 | ||
810 | state_table[devid] = dev_state; | 799 | list_add_tail(&dev_state->list, &state_list); |
811 | 800 | ||
812 | spin_unlock_irqrestore(&state_lock, flags); | 801 | spin_unlock_irqrestore(&state_lock, flags); |
813 | 802 | ||
@@ -839,13 +828,13 @@ void amd_iommu_free_device(struct pci_dev *pdev) | |||
839 | 828 | ||
840 | spin_lock_irqsave(&state_lock, flags); | 829 | spin_lock_irqsave(&state_lock, flags); |
841 | 830 | ||
842 | dev_state = state_table[devid]; | 831 | dev_state = __get_device_state(devid); |
843 | if (dev_state == NULL) { | 832 | if (dev_state == NULL) { |
844 | spin_unlock_irqrestore(&state_lock, flags); | 833 | spin_unlock_irqrestore(&state_lock, flags); |
845 | return; | 834 | return; |
846 | } | 835 | } |
847 | 836 | ||
848 | state_table[devid] = NULL; | 837 | list_del(&dev_state->list); |
849 | 838 | ||
850 | spin_unlock_irqrestore(&state_lock, flags); | 839 | spin_unlock_irqrestore(&state_lock, flags); |
851 | 840 | ||
@@ -872,7 +861,7 @@ int amd_iommu_set_invalid_ppr_cb(struct pci_dev *pdev, | |||
872 | spin_lock_irqsave(&state_lock, flags); | 861 | spin_lock_irqsave(&state_lock, flags); |
873 | 862 | ||
874 | ret = -EINVAL; | 863 | ret = -EINVAL; |
875 | dev_state = state_table[devid]; | 864 | dev_state = __get_device_state(devid); |
876 | if (dev_state == NULL) | 865 | if (dev_state == NULL) |
877 | goto out_unlock; | 866 | goto out_unlock; |
878 | 867 | ||
@@ -903,7 +892,7 @@ int amd_iommu_set_invalidate_ctx_cb(struct pci_dev *pdev, | |||
903 | spin_lock_irqsave(&state_lock, flags); | 892 | spin_lock_irqsave(&state_lock, flags); |
904 | 893 | ||
905 | ret = -EINVAL; | 894 | ret = -EINVAL; |
906 | dev_state = state_table[devid]; | 895 | dev_state = __get_device_state(devid); |
907 | if (dev_state == NULL) | 896 | if (dev_state == NULL) |
908 | goto out_unlock; | 897 | goto out_unlock; |
909 | 898 | ||
@@ -920,7 +909,6 @@ EXPORT_SYMBOL(amd_iommu_set_invalidate_ctx_cb); | |||
920 | 909 | ||
921 | static int __init amd_iommu_v2_init(void) | 910 | static int __init amd_iommu_v2_init(void) |
922 | { | 911 | { |
923 | size_t state_table_size; | ||
924 | int ret; | 912 | int ret; |
925 | 913 | ||
926 | pr_info("AMD IOMMUv2 driver by Joerg Roedel <joerg.roedel@amd.com>\n"); | 914 | pr_info("AMD IOMMUv2 driver by Joerg Roedel <joerg.roedel@amd.com>\n"); |
@@ -936,16 +924,10 @@ static int __init amd_iommu_v2_init(void) | |||
936 | 924 | ||
937 | spin_lock_init(&state_lock); | 925 | spin_lock_init(&state_lock); |
938 | 926 | ||
939 | state_table_size = MAX_DEVICES * sizeof(struct device_state *); | ||
940 | state_table = (void *)__get_free_pages(GFP_KERNEL | __GFP_ZERO, | ||
941 | get_order(state_table_size)); | ||
942 | if (state_table == NULL) | ||
943 | return -ENOMEM; | ||
944 | |||
945 | ret = -ENOMEM; | 927 | ret = -ENOMEM; |
946 | iommu_wq = create_workqueue("amd_iommu_v2"); | 928 | iommu_wq = create_workqueue("amd_iommu_v2"); |
947 | if (iommu_wq == NULL) | 929 | if (iommu_wq == NULL) |
948 | goto out_free; | 930 | goto out; |
949 | 931 | ||
950 | ret = -ENOMEM; | 932 | ret = -ENOMEM; |
951 | empty_page_table = (u64 *)get_zeroed_page(GFP_KERNEL); | 933 | empty_page_table = (u64 *)get_zeroed_page(GFP_KERNEL); |
@@ -953,29 +935,24 @@ static int __init amd_iommu_v2_init(void) | |||
953 | goto out_destroy_wq; | 935 | goto out_destroy_wq; |
954 | 936 | ||
955 | amd_iommu_register_ppr_notifier(&ppr_nb); | 937 | amd_iommu_register_ppr_notifier(&ppr_nb); |
956 | profile_event_register(PROFILE_TASK_EXIT, &profile_nb); | ||
957 | 938 | ||
958 | return 0; | 939 | return 0; |
959 | 940 | ||
960 | out_destroy_wq: | 941 | out_destroy_wq: |
961 | destroy_workqueue(iommu_wq); | 942 | destroy_workqueue(iommu_wq); |
962 | 943 | ||
963 | out_free: | 944 | out: |
964 | free_pages((unsigned long)state_table, get_order(state_table_size)); | ||
965 | |||
966 | return ret; | 945 | return ret; |
967 | } | 946 | } |
968 | 947 | ||
969 | static void __exit amd_iommu_v2_exit(void) | 948 | static void __exit amd_iommu_v2_exit(void) |
970 | { | 949 | { |
971 | struct device_state *dev_state; | 950 | struct device_state *dev_state; |
972 | size_t state_table_size; | ||
973 | int i; | 951 | int i; |
974 | 952 | ||
975 | if (!amd_iommu_v2_supported()) | 953 | if (!amd_iommu_v2_supported()) |
976 | return; | 954 | return; |
977 | 955 | ||
978 | profile_event_unregister(PROFILE_TASK_EXIT, &profile_nb); | ||
979 | amd_iommu_unregister_ppr_notifier(&ppr_nb); | 956 | amd_iommu_unregister_ppr_notifier(&ppr_nb); |
980 | 957 | ||
981 | flush_workqueue(iommu_wq); | 958 | flush_workqueue(iommu_wq); |
@@ -998,9 +975,6 @@ static void __exit amd_iommu_v2_exit(void) | |||
998 | 975 | ||
999 | destroy_workqueue(iommu_wq); | 976 | destroy_workqueue(iommu_wq); |
1000 | 977 | ||
1001 | state_table_size = MAX_DEVICES * sizeof(struct device_state *); | ||
1002 | free_pages((unsigned long)state_table, get_order(state_table_size)); | ||
1003 | |||
1004 | free_page((unsigned long)empty_page_table); | 978 | free_page((unsigned long)empty_page_table); |
1005 | } | 979 | } |
1006 | 980 | ||
diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c index 647c3c7fd742..1599354e974d 100644 --- a/drivers/iommu/arm-smmu.c +++ b/drivers/iommu/arm-smmu.c | |||
@@ -1167,7 +1167,7 @@ static int arm_smmu_domain_add_master(struct arm_smmu_domain *smmu_domain, | |||
1167 | for (i = 0; i < master->num_streamids; ++i) { | 1167 | for (i = 0; i < master->num_streamids; ++i) { |
1168 | u32 idx, s2cr; | 1168 | u32 idx, s2cr; |
1169 | idx = master->smrs ? master->smrs[i].idx : master->streamids[i]; | 1169 | idx = master->smrs ? master->smrs[i].idx : master->streamids[i]; |
1170 | s2cr = (S2CR_TYPE_TRANS << S2CR_TYPE_SHIFT) | | 1170 | s2cr = S2CR_TYPE_TRANS | |
1171 | (smmu_domain->root_cfg.cbndx << S2CR_CBNDX_SHIFT); | 1171 | (smmu_domain->root_cfg.cbndx << S2CR_CBNDX_SHIFT); |
1172 | writel_relaxed(s2cr, gr0_base + ARM_SMMU_GR0_S2CR(idx)); | 1172 | writel_relaxed(s2cr, gr0_base + ARM_SMMU_GR0_S2CR(idx)); |
1173 | } | 1173 | } |
@@ -1804,7 +1804,7 @@ static int arm_smmu_device_cfg_probe(struct arm_smmu_device *smmu) | |||
1804 | * allocation (PTRS_PER_PGD). | 1804 | * allocation (PTRS_PER_PGD). |
1805 | */ | 1805 | */ |
1806 | #ifdef CONFIG_64BIT | 1806 | #ifdef CONFIG_64BIT |
1807 | smmu->s1_output_size = min(39UL, size); | 1807 | smmu->s1_output_size = min((unsigned long)VA_BITS, size); |
1808 | #else | 1808 | #else |
1809 | smmu->s1_output_size = min(32UL, size); | 1809 | smmu->s1_output_size = min(32UL, size); |
1810 | #endif | 1810 | #endif |
diff --git a/drivers/iommu/dmar.c b/drivers/iommu/dmar.c index 39f8b717fe84..9a4f05e5b23f 100644 --- a/drivers/iommu/dmar.c +++ b/drivers/iommu/dmar.c | |||
@@ -994,7 +994,7 @@ static void free_iommu(struct intel_iommu *iommu) | |||
994 | if (iommu->irq) { | 994 | if (iommu->irq) { |
995 | free_irq(iommu->irq, iommu); | 995 | free_irq(iommu->irq, iommu); |
996 | irq_set_handler_data(iommu->irq, NULL); | 996 | irq_set_handler_data(iommu->irq, NULL); |
997 | destroy_irq(iommu->irq); | 997 | dmar_free_hwirq(iommu->irq); |
998 | } | 998 | } |
999 | 999 | ||
1000 | if (iommu->qi) { | 1000 | if (iommu->qi) { |
@@ -1550,8 +1550,8 @@ int dmar_set_interrupt(struct intel_iommu *iommu) | |||
1550 | if (iommu->irq) | 1550 | if (iommu->irq) |
1551 | return 0; | 1551 | return 0; |
1552 | 1552 | ||
1553 | irq = create_irq(); | 1553 | irq = dmar_alloc_hwirq(); |
1554 | if (!irq) { | 1554 | if (irq <= 0) { |
1555 | pr_err("IOMMU: no free vectors\n"); | 1555 | pr_err("IOMMU: no free vectors\n"); |
1556 | return -EINVAL; | 1556 | return -EINVAL; |
1557 | } | 1557 | } |
@@ -1563,7 +1563,7 @@ int dmar_set_interrupt(struct intel_iommu *iommu) | |||
1563 | if (ret) { | 1563 | if (ret) { |
1564 | irq_set_handler_data(irq, NULL); | 1564 | irq_set_handler_data(irq, NULL); |
1565 | iommu->irq = 0; | 1565 | iommu->irq = 0; |
1566 | destroy_irq(irq); | 1566 | dmar_free_hwirq(irq); |
1567 | return ret; | 1567 | return ret; |
1568 | } | 1568 | } |
1569 | 1569 | ||
diff --git a/drivers/iommu/exynos-iommu.c b/drivers/iommu/exynos-iommu.c index 074018979cdf..99054d2c040d 100644 --- a/drivers/iommu/exynos-iommu.c +++ b/drivers/iommu/exynos-iommu.c | |||
@@ -29,7 +29,8 @@ | |||
29 | #include <asm/cacheflush.h> | 29 | #include <asm/cacheflush.h> |
30 | #include <asm/pgtable.h> | 30 | #include <asm/pgtable.h> |
31 | 31 | ||
32 | #include <mach/sysmmu.h> | 32 | typedef u32 sysmmu_iova_t; |
33 | typedef u32 sysmmu_pte_t; | ||
33 | 34 | ||
34 | /* We does not consider super section mapping (16MB) */ | 35 | /* We does not consider super section mapping (16MB) */ |
35 | #define SECT_ORDER 20 | 36 | #define SECT_ORDER 20 |
@@ -44,28 +45,44 @@ | |||
44 | #define LPAGE_MASK (~(LPAGE_SIZE - 1)) | 45 | #define LPAGE_MASK (~(LPAGE_SIZE - 1)) |
45 | #define SPAGE_MASK (~(SPAGE_SIZE - 1)) | 46 | #define SPAGE_MASK (~(SPAGE_SIZE - 1)) |
46 | 47 | ||
47 | #define lv1ent_fault(sent) (((*(sent) & 3) == 0) || ((*(sent) & 3) == 3)) | 48 | #define lv1ent_fault(sent) ((*(sent) == ZERO_LV2LINK) || \ |
48 | #define lv1ent_page(sent) ((*(sent) & 3) == 1) | 49 | ((*(sent) & 3) == 0) || ((*(sent) & 3) == 3)) |
50 | #define lv1ent_zero(sent) (*(sent) == ZERO_LV2LINK) | ||
51 | #define lv1ent_page_zero(sent) ((*(sent) & 3) == 1) | ||
52 | #define lv1ent_page(sent) ((*(sent) != ZERO_LV2LINK) && \ | ||
53 | ((*(sent) & 3) == 1)) | ||
49 | #define lv1ent_section(sent) ((*(sent) & 3) == 2) | 54 | #define lv1ent_section(sent) ((*(sent) & 3) == 2) |
50 | 55 | ||
51 | #define lv2ent_fault(pent) ((*(pent) & 3) == 0) | 56 | #define lv2ent_fault(pent) ((*(pent) & 3) == 0) |
52 | #define lv2ent_small(pent) ((*(pent) & 2) == 2) | 57 | #define lv2ent_small(pent) ((*(pent) & 2) == 2) |
53 | #define lv2ent_large(pent) ((*(pent) & 3) == 1) | 58 | #define lv2ent_large(pent) ((*(pent) & 3) == 1) |
54 | 59 | ||
60 | static u32 sysmmu_page_offset(sysmmu_iova_t iova, u32 size) | ||
61 | { | ||
62 | return iova & (size - 1); | ||
63 | } | ||
64 | |||
55 | #define section_phys(sent) (*(sent) & SECT_MASK) | 65 | #define section_phys(sent) (*(sent) & SECT_MASK) |
56 | #define section_offs(iova) ((iova) & 0xFFFFF) | 66 | #define section_offs(iova) sysmmu_page_offset((iova), SECT_SIZE) |
57 | #define lpage_phys(pent) (*(pent) & LPAGE_MASK) | 67 | #define lpage_phys(pent) (*(pent) & LPAGE_MASK) |
58 | #define lpage_offs(iova) ((iova) & 0xFFFF) | 68 | #define lpage_offs(iova) sysmmu_page_offset((iova), LPAGE_SIZE) |
59 | #define spage_phys(pent) (*(pent) & SPAGE_MASK) | 69 | #define spage_phys(pent) (*(pent) & SPAGE_MASK) |
60 | #define spage_offs(iova) ((iova) & 0xFFF) | 70 | #define spage_offs(iova) sysmmu_page_offset((iova), SPAGE_SIZE) |
61 | |||
62 | #define lv1ent_offset(iova) ((iova) >> SECT_ORDER) | ||
63 | #define lv2ent_offset(iova) (((iova) & 0xFF000) >> SPAGE_ORDER) | ||
64 | 71 | ||
65 | #define NUM_LV1ENTRIES 4096 | 72 | #define NUM_LV1ENTRIES 4096 |
66 | #define NUM_LV2ENTRIES 256 | 73 | #define NUM_LV2ENTRIES (SECT_SIZE / SPAGE_SIZE) |
74 | |||
75 | static u32 lv1ent_offset(sysmmu_iova_t iova) | ||
76 | { | ||
77 | return iova >> SECT_ORDER; | ||
78 | } | ||
79 | |||
80 | static u32 lv2ent_offset(sysmmu_iova_t iova) | ||
81 | { | ||
82 | return (iova >> SPAGE_ORDER) & (NUM_LV2ENTRIES - 1); | ||
83 | } | ||
67 | 84 | ||
68 | #define LV2TABLE_SIZE (NUM_LV2ENTRIES * sizeof(long)) | 85 | #define LV2TABLE_SIZE (NUM_LV2ENTRIES * sizeof(sysmmu_pte_t)) |
69 | 86 | ||
70 | #define SPAGES_PER_LPAGE (LPAGE_SIZE / SPAGE_SIZE) | 87 | #define SPAGES_PER_LPAGE (LPAGE_SIZE / SPAGE_SIZE) |
71 | 88 | ||
@@ -80,6 +97,13 @@ | |||
80 | #define CTRL_BLOCK 0x7 | 97 | #define CTRL_BLOCK 0x7 |
81 | #define CTRL_DISABLE 0x0 | 98 | #define CTRL_DISABLE 0x0 |
82 | 99 | ||
100 | #define CFG_LRU 0x1 | ||
101 | #define CFG_QOS(n) ((n & 0xF) << 7) | ||
102 | #define CFG_MASK 0x0150FFFF /* Selecting bit 0-15, 20, 22 and 24 */ | ||
103 | #define CFG_ACGEN (1 << 24) /* System MMU 3.3 only */ | ||
104 | #define CFG_SYSSEL (1 << 22) /* System MMU 3.2 only */ | ||
105 | #define CFG_FLPDCACHE (1 << 20) /* System MMU 3.2+ only */ | ||
106 | |||
83 | #define REG_MMU_CTRL 0x000 | 107 | #define REG_MMU_CTRL 0x000 |
84 | #define REG_MMU_CFG 0x004 | 108 | #define REG_MMU_CFG 0x004 |
85 | #define REG_MMU_STATUS 0x008 | 109 | #define REG_MMU_STATUS 0x008 |
@@ -96,19 +120,32 @@ | |||
96 | 120 | ||
97 | #define REG_MMU_VERSION 0x034 | 121 | #define REG_MMU_VERSION 0x034 |
98 | 122 | ||
123 | #define MMU_MAJ_VER(val) ((val) >> 7) | ||
124 | #define MMU_MIN_VER(val) ((val) & 0x7F) | ||
125 | #define MMU_RAW_VER(reg) (((reg) >> 21) & ((1 << 11) - 1)) /* 11 bits */ | ||
126 | |||
127 | #define MAKE_MMU_VER(maj, min) ((((maj) & 0xF) << 7) | ((min) & 0x7F)) | ||
128 | |||
99 | #define REG_PB0_SADDR 0x04C | 129 | #define REG_PB0_SADDR 0x04C |
100 | #define REG_PB0_EADDR 0x050 | 130 | #define REG_PB0_EADDR 0x050 |
101 | #define REG_PB1_SADDR 0x054 | 131 | #define REG_PB1_SADDR 0x054 |
102 | #define REG_PB1_EADDR 0x058 | 132 | #define REG_PB1_EADDR 0x058 |
103 | 133 | ||
104 | static unsigned long *section_entry(unsigned long *pgtable, unsigned long iova) | 134 | #define has_sysmmu(dev) (dev->archdata.iommu != NULL) |
135 | |||
136 | static struct kmem_cache *lv2table_kmem_cache; | ||
137 | static sysmmu_pte_t *zero_lv2_table; | ||
138 | #define ZERO_LV2LINK mk_lv1ent_page(virt_to_phys(zero_lv2_table)) | ||
139 | |||
140 | static sysmmu_pte_t *section_entry(sysmmu_pte_t *pgtable, sysmmu_iova_t iova) | ||
105 | { | 141 | { |
106 | return pgtable + lv1ent_offset(iova); | 142 | return pgtable + lv1ent_offset(iova); |
107 | } | 143 | } |
108 | 144 | ||
109 | static unsigned long *page_entry(unsigned long *sent, unsigned long iova) | 145 | static sysmmu_pte_t *page_entry(sysmmu_pte_t *sent, sysmmu_iova_t iova) |
110 | { | 146 | { |
111 | return (unsigned long *)__va(lv2table_base(sent)) + lv2ent_offset(iova); | 147 | return (sysmmu_pte_t *)phys_to_virt( |
148 | lv2table_base(sent)) + lv2ent_offset(iova); | ||
112 | } | 149 | } |
113 | 150 | ||
114 | enum exynos_sysmmu_inttype { | 151 | enum exynos_sysmmu_inttype { |
@@ -124,16 +161,6 @@ enum exynos_sysmmu_inttype { | |||
124 | SYSMMU_FAULTS_NUM | 161 | SYSMMU_FAULTS_NUM |
125 | }; | 162 | }; |
126 | 163 | ||
127 | /* | ||
128 | * @itype: type of fault. | ||
129 | * @pgtable_base: the physical address of page table base. This is 0 if @itype | ||
130 | * is SYSMMU_BUSERROR. | ||
131 | * @fault_addr: the device (virtual) address that the System MMU tried to | ||
132 | * translated. This is 0 if @itype is SYSMMU_BUSERROR. | ||
133 | */ | ||
134 | typedef int (*sysmmu_fault_handler_t)(enum exynos_sysmmu_inttype itype, | ||
135 | unsigned long pgtable_base, unsigned long fault_addr); | ||
136 | |||
137 | static unsigned short fault_reg_offset[SYSMMU_FAULTS_NUM] = { | 164 | static unsigned short fault_reg_offset[SYSMMU_FAULTS_NUM] = { |
138 | REG_PAGE_FAULT_ADDR, | 165 | REG_PAGE_FAULT_ADDR, |
139 | REG_AR_FAULT_ADDR, | 166 | REG_AR_FAULT_ADDR, |
@@ -157,27 +184,34 @@ static char *sysmmu_fault_name[SYSMMU_FAULTS_NUM] = { | |||
157 | "UNKNOWN FAULT" | 184 | "UNKNOWN FAULT" |
158 | }; | 185 | }; |
159 | 186 | ||
187 | /* attached to dev.archdata.iommu of the master device */ | ||
188 | struct exynos_iommu_owner { | ||
189 | struct list_head client; /* entry of exynos_iommu_domain.clients */ | ||
190 | struct device *dev; | ||
191 | struct device *sysmmu; | ||
192 | struct iommu_domain *domain; | ||
193 | void *vmm_data; /* IO virtual memory manager's data */ | ||
194 | spinlock_t lock; /* Lock to preserve consistency of System MMU */ | ||
195 | }; | ||
196 | |||
160 | struct exynos_iommu_domain { | 197 | struct exynos_iommu_domain { |
161 | struct list_head clients; /* list of sysmmu_drvdata.node */ | 198 | struct list_head clients; /* list of sysmmu_drvdata.node */ |
162 | unsigned long *pgtable; /* lv1 page table, 16KB */ | 199 | sysmmu_pte_t *pgtable; /* lv1 page table, 16KB */ |
163 | short *lv2entcnt; /* free lv2 entry counter for each section */ | 200 | short *lv2entcnt; /* free lv2 entry counter for each section */ |
164 | spinlock_t lock; /* lock for this structure */ | 201 | spinlock_t lock; /* lock for this structure */ |
165 | spinlock_t pgtablelock; /* lock for modifying page table @ pgtable */ | 202 | spinlock_t pgtablelock; /* lock for modifying page table @ pgtable */ |
166 | }; | 203 | }; |
167 | 204 | ||
168 | struct sysmmu_drvdata { | 205 | struct sysmmu_drvdata { |
169 | struct list_head node; /* entry of exynos_iommu_domain.clients */ | ||
170 | struct device *sysmmu; /* System MMU's device descriptor */ | 206 | struct device *sysmmu; /* System MMU's device descriptor */ |
171 | struct device *dev; /* Owner of system MMU */ | 207 | struct device *master; /* Owner of system MMU */ |
172 | char *dbgname; | 208 | void __iomem *sfrbase; |
173 | int nsfrs; | 209 | struct clk *clk; |
174 | void __iomem **sfrbases; | 210 | struct clk *clk_master; |
175 | struct clk *clk[2]; | ||
176 | int activations; | 211 | int activations; |
177 | rwlock_t lock; | 212 | spinlock_t lock; |
178 | struct iommu_domain *domain; | 213 | struct iommu_domain *domain; |
179 | sysmmu_fault_handler_t fault_handler; | 214 | phys_addr_t pgtable; |
180 | unsigned long pgtable; | ||
181 | }; | 215 | }; |
182 | 216 | ||
183 | static bool set_sysmmu_active(struct sysmmu_drvdata *data) | 217 | static bool set_sysmmu_active(struct sysmmu_drvdata *data) |
@@ -204,6 +238,11 @@ static void sysmmu_unblock(void __iomem *sfrbase) | |||
204 | __raw_writel(CTRL_ENABLE, sfrbase + REG_MMU_CTRL); | 238 | __raw_writel(CTRL_ENABLE, sfrbase + REG_MMU_CTRL); |
205 | } | 239 | } |
206 | 240 | ||
241 | static unsigned int __raw_sysmmu_version(struct sysmmu_drvdata *data) | ||
242 | { | ||
243 | return MMU_RAW_VER(__raw_readl(data->sfrbase + REG_MMU_VERSION)); | ||
244 | } | ||
245 | |||
207 | static bool sysmmu_block(void __iomem *sfrbase) | 246 | static bool sysmmu_block(void __iomem *sfrbase) |
208 | { | 247 | { |
209 | int i = 120; | 248 | int i = 120; |
@@ -226,434 +265,428 @@ static void __sysmmu_tlb_invalidate(void __iomem *sfrbase) | |||
226 | } | 265 | } |
227 | 266 | ||
228 | static void __sysmmu_tlb_invalidate_entry(void __iomem *sfrbase, | 267 | static void __sysmmu_tlb_invalidate_entry(void __iomem *sfrbase, |
229 | unsigned long iova) | 268 | sysmmu_iova_t iova, unsigned int num_inv) |
230 | { | 269 | { |
231 | __raw_writel((iova & SPAGE_MASK) | 1, sfrbase + REG_MMU_FLUSH_ENTRY); | 270 | unsigned int i; |
271 | |||
272 | for (i = 0; i < num_inv; i++) { | ||
273 | __raw_writel((iova & SPAGE_MASK) | 1, | ||
274 | sfrbase + REG_MMU_FLUSH_ENTRY); | ||
275 | iova += SPAGE_SIZE; | ||
276 | } | ||
232 | } | 277 | } |
233 | 278 | ||
234 | static void __sysmmu_set_ptbase(void __iomem *sfrbase, | 279 | static void __sysmmu_set_ptbase(void __iomem *sfrbase, |
235 | unsigned long pgd) | 280 | phys_addr_t pgd) |
236 | { | 281 | { |
237 | __raw_writel(0x1, sfrbase + REG_MMU_CFG); /* 16KB LV1, LRU */ | ||
238 | __raw_writel(pgd, sfrbase + REG_PT_BASE_ADDR); | 282 | __raw_writel(pgd, sfrbase + REG_PT_BASE_ADDR); |
239 | 283 | ||
240 | __sysmmu_tlb_invalidate(sfrbase); | 284 | __sysmmu_tlb_invalidate(sfrbase); |
241 | } | 285 | } |
242 | 286 | ||
243 | static void __sysmmu_set_prefbuf(void __iomem *sfrbase, unsigned long base, | 287 | static void show_fault_information(const char *name, |
244 | unsigned long size, int idx) | 288 | enum exynos_sysmmu_inttype itype, |
245 | { | 289 | phys_addr_t pgtable_base, sysmmu_iova_t fault_addr) |
246 | __raw_writel(base, sfrbase + REG_PB0_SADDR + idx * 8); | ||
247 | __raw_writel(size - 1 + base, sfrbase + REG_PB0_EADDR + idx * 8); | ||
248 | } | ||
249 | |||
250 | static void __set_fault_handler(struct sysmmu_drvdata *data, | ||
251 | sysmmu_fault_handler_t handler) | ||
252 | { | ||
253 | unsigned long flags; | ||
254 | |||
255 | write_lock_irqsave(&data->lock, flags); | ||
256 | data->fault_handler = handler; | ||
257 | write_unlock_irqrestore(&data->lock, flags); | ||
258 | } | ||
259 | |||
260 | void exynos_sysmmu_set_fault_handler(struct device *dev, | ||
261 | sysmmu_fault_handler_t handler) | ||
262 | { | ||
263 | struct sysmmu_drvdata *data = dev_get_drvdata(dev->archdata.iommu); | ||
264 | |||
265 | __set_fault_handler(data, handler); | ||
266 | } | ||
267 | |||
268 | static int default_fault_handler(enum exynos_sysmmu_inttype itype, | ||
269 | unsigned long pgtable_base, unsigned long fault_addr) | ||
270 | { | 290 | { |
271 | unsigned long *ent; | 291 | sysmmu_pte_t *ent; |
272 | 292 | ||
273 | if ((itype >= SYSMMU_FAULTS_NUM) || (itype < SYSMMU_PAGEFAULT)) | 293 | if ((itype >= SYSMMU_FAULTS_NUM) || (itype < SYSMMU_PAGEFAULT)) |
274 | itype = SYSMMU_FAULT_UNKNOWN; | 294 | itype = SYSMMU_FAULT_UNKNOWN; |
275 | 295 | ||
276 | pr_err("%s occurred at 0x%lx(Page table base: 0x%lx)\n", | 296 | pr_err("%s occurred at %#x by %s(Page table base: %pa)\n", |
277 | sysmmu_fault_name[itype], fault_addr, pgtable_base); | 297 | sysmmu_fault_name[itype], fault_addr, name, &pgtable_base); |
278 | 298 | ||
279 | ent = section_entry(__va(pgtable_base), fault_addr); | 299 | ent = section_entry(phys_to_virt(pgtable_base), fault_addr); |
280 | pr_err("\tLv1 entry: 0x%lx\n", *ent); | 300 | pr_err("\tLv1 entry: %#x\n", *ent); |
281 | 301 | ||
282 | if (lv1ent_page(ent)) { | 302 | if (lv1ent_page(ent)) { |
283 | ent = page_entry(ent, fault_addr); | 303 | ent = page_entry(ent, fault_addr); |
284 | pr_err("\t Lv2 entry: 0x%lx\n", *ent); | 304 | pr_err("\t Lv2 entry: %#x\n", *ent); |
285 | } | 305 | } |
286 | |||
287 | pr_err("Generating Kernel OOPS... because it is unrecoverable.\n"); | ||
288 | |||
289 | BUG(); | ||
290 | |||
291 | return 0; | ||
292 | } | 306 | } |
293 | 307 | ||
294 | static irqreturn_t exynos_sysmmu_irq(int irq, void *dev_id) | 308 | static irqreturn_t exynos_sysmmu_irq(int irq, void *dev_id) |
295 | { | 309 | { |
296 | /* SYSMMU is in blocked when interrupt occurred. */ | 310 | /* SYSMMU is in blocked when interrupt occurred. */ |
297 | struct sysmmu_drvdata *data = dev_id; | 311 | struct sysmmu_drvdata *data = dev_id; |
298 | struct resource *irqres; | ||
299 | struct platform_device *pdev; | ||
300 | enum exynos_sysmmu_inttype itype; | 312 | enum exynos_sysmmu_inttype itype; |
301 | unsigned long addr = -1; | 313 | sysmmu_iova_t addr = -1; |
302 | 314 | int ret = -ENOSYS; | |
303 | int i, ret = -ENOSYS; | ||
304 | |||
305 | read_lock(&data->lock); | ||
306 | 315 | ||
307 | WARN_ON(!is_sysmmu_active(data)); | 316 | WARN_ON(!is_sysmmu_active(data)); |
308 | 317 | ||
309 | pdev = to_platform_device(data->sysmmu); | 318 | spin_lock(&data->lock); |
310 | for (i = 0; i < (pdev->num_resources / 2); i++) { | ||
311 | irqres = platform_get_resource(pdev, IORESOURCE_IRQ, i); | ||
312 | if (irqres && ((int)irqres->start == irq)) | ||
313 | break; | ||
314 | } | ||
315 | 319 | ||
316 | if (i == pdev->num_resources) { | 320 | if (!IS_ERR(data->clk_master)) |
321 | clk_enable(data->clk_master); | ||
322 | |||
323 | itype = (enum exynos_sysmmu_inttype) | ||
324 | __ffs(__raw_readl(data->sfrbase + REG_INT_STATUS)); | ||
325 | if (WARN_ON(!((itype >= 0) && (itype < SYSMMU_FAULT_UNKNOWN)))) | ||
317 | itype = SYSMMU_FAULT_UNKNOWN; | 326 | itype = SYSMMU_FAULT_UNKNOWN; |
327 | else | ||
328 | addr = __raw_readl(data->sfrbase + fault_reg_offset[itype]); | ||
329 | |||
330 | if (itype == SYSMMU_FAULT_UNKNOWN) { | ||
331 | pr_err("%s: Fault is not occurred by System MMU '%s'!\n", | ||
332 | __func__, dev_name(data->sysmmu)); | ||
333 | pr_err("%s: Please check if IRQ is correctly configured.\n", | ||
334 | __func__); | ||
335 | BUG(); | ||
318 | } else { | 336 | } else { |
319 | itype = (enum exynos_sysmmu_inttype) | 337 | unsigned int base = |
320 | __ffs(__raw_readl(data->sfrbases[i] + REG_INT_STATUS)); | 338 | __raw_readl(data->sfrbase + REG_PT_BASE_ADDR); |
321 | if (WARN_ON(!((itype >= 0) && (itype < SYSMMU_FAULT_UNKNOWN)))) | 339 | show_fault_information(dev_name(data->sysmmu), |
322 | itype = SYSMMU_FAULT_UNKNOWN; | 340 | itype, base, addr); |
323 | else | 341 | if (data->domain) |
324 | addr = __raw_readl( | 342 | ret = report_iommu_fault(data->domain, |
325 | data->sfrbases[i] + fault_reg_offset[itype]); | 343 | data->master, addr, itype); |
326 | } | 344 | } |
327 | 345 | ||
328 | if (data->domain) | 346 | /* fault is not recovered by fault handler */ |
329 | ret = report_iommu_fault(data->domain, data->dev, | 347 | BUG_ON(ret != 0); |
330 | addr, itype); | ||
331 | 348 | ||
332 | if ((ret == -ENOSYS) && data->fault_handler) { | 349 | __raw_writel(1 << itype, data->sfrbase + REG_INT_CLEAR); |
333 | unsigned long base = data->pgtable; | ||
334 | if (itype != SYSMMU_FAULT_UNKNOWN) | ||
335 | base = __raw_readl( | ||
336 | data->sfrbases[i] + REG_PT_BASE_ADDR); | ||
337 | ret = data->fault_handler(itype, base, addr); | ||
338 | } | ||
339 | 350 | ||
340 | if (!ret && (itype != SYSMMU_FAULT_UNKNOWN)) | 351 | sysmmu_unblock(data->sfrbase); |
341 | __raw_writel(1 << itype, data->sfrbases[i] + REG_INT_CLEAR); | ||
342 | else | ||
343 | dev_dbg(data->sysmmu, "(%s) %s is not handled.\n", | ||
344 | data->dbgname, sysmmu_fault_name[itype]); | ||
345 | 352 | ||
346 | if (itype != SYSMMU_FAULT_UNKNOWN) | 353 | if (!IS_ERR(data->clk_master)) |
347 | sysmmu_unblock(data->sfrbases[i]); | 354 | clk_disable(data->clk_master); |
348 | 355 | ||
349 | read_unlock(&data->lock); | 356 | spin_unlock(&data->lock); |
350 | 357 | ||
351 | return IRQ_HANDLED; | 358 | return IRQ_HANDLED; |
352 | } | 359 | } |
353 | 360 | ||
354 | static bool __exynos_sysmmu_disable(struct sysmmu_drvdata *data) | 361 | static void __sysmmu_disable_nocount(struct sysmmu_drvdata *data) |
355 | { | 362 | { |
363 | if (!IS_ERR(data->clk_master)) | ||
364 | clk_enable(data->clk_master); | ||
365 | |||
366 | __raw_writel(CTRL_DISABLE, data->sfrbase + REG_MMU_CTRL); | ||
367 | __raw_writel(0, data->sfrbase + REG_MMU_CFG); | ||
368 | |||
369 | clk_disable(data->clk); | ||
370 | if (!IS_ERR(data->clk_master)) | ||
371 | clk_disable(data->clk_master); | ||
372 | } | ||
373 | |||
374 | static bool __sysmmu_disable(struct sysmmu_drvdata *data) | ||
375 | { | ||
376 | bool disabled; | ||
356 | unsigned long flags; | 377 | unsigned long flags; |
357 | bool disabled = false; | ||
358 | int i; | ||
359 | 378 | ||
360 | write_lock_irqsave(&data->lock, flags); | 379 | spin_lock_irqsave(&data->lock, flags); |
361 | 380 | ||
362 | if (!set_sysmmu_inactive(data)) | 381 | disabled = set_sysmmu_inactive(data); |
363 | goto finish; | ||
364 | 382 | ||
365 | for (i = 0; i < data->nsfrs; i++) | 383 | if (disabled) { |
366 | __raw_writel(CTRL_DISABLE, data->sfrbases[i] + REG_MMU_CTRL); | 384 | data->pgtable = 0; |
385 | data->domain = NULL; | ||
367 | 386 | ||
368 | if (data->clk[1]) | 387 | __sysmmu_disable_nocount(data); |
369 | clk_disable(data->clk[1]); | ||
370 | if (data->clk[0]) | ||
371 | clk_disable(data->clk[0]); | ||
372 | 388 | ||
373 | disabled = true; | 389 | dev_dbg(data->sysmmu, "Disabled\n"); |
374 | data->pgtable = 0; | 390 | } else { |
375 | data->domain = NULL; | 391 | dev_dbg(data->sysmmu, "%d times left to disable\n", |
376 | finish: | 392 | data->activations); |
377 | write_unlock_irqrestore(&data->lock, flags); | 393 | } |
378 | 394 | ||
379 | if (disabled) | 395 | spin_unlock_irqrestore(&data->lock, flags); |
380 | dev_dbg(data->sysmmu, "(%s) Disabled\n", data->dbgname); | ||
381 | else | ||
382 | dev_dbg(data->sysmmu, "(%s) %d times left to be disabled\n", | ||
383 | data->dbgname, data->activations); | ||
384 | 396 | ||
385 | return disabled; | 397 | return disabled; |
386 | } | 398 | } |
387 | 399 | ||
388 | /* __exynos_sysmmu_enable: Enables System MMU | 400 | static void __sysmmu_init_config(struct sysmmu_drvdata *data) |
389 | * | ||
390 | * returns -error if an error occurred and System MMU is not enabled, | ||
391 | * 0 if the System MMU has been just enabled and 1 if System MMU was already | ||
392 | * enabled before. | ||
393 | */ | ||
394 | static int __exynos_sysmmu_enable(struct sysmmu_drvdata *data, | ||
395 | unsigned long pgtable, struct iommu_domain *domain) | ||
396 | { | 401 | { |
397 | int i, ret = 0; | 402 | unsigned int cfg = CFG_LRU | CFG_QOS(15); |
398 | unsigned long flags; | 403 | unsigned int ver; |
404 | |||
405 | ver = __raw_sysmmu_version(data); | ||
406 | if (MMU_MAJ_VER(ver) == 3) { | ||
407 | if (MMU_MIN_VER(ver) >= 2) { | ||
408 | cfg |= CFG_FLPDCACHE; | ||
409 | if (MMU_MIN_VER(ver) == 3) { | ||
410 | cfg |= CFG_ACGEN; | ||
411 | cfg &= ~CFG_LRU; | ||
412 | } else { | ||
413 | cfg |= CFG_SYSSEL; | ||
414 | } | ||
415 | } | ||
416 | } | ||
399 | 417 | ||
400 | write_lock_irqsave(&data->lock, flags); | 418 | __raw_writel(cfg, data->sfrbase + REG_MMU_CFG); |
419 | } | ||
401 | 420 | ||
402 | if (!set_sysmmu_active(data)) { | 421 | static void __sysmmu_enable_nocount(struct sysmmu_drvdata *data) |
403 | if (WARN_ON(pgtable != data->pgtable)) { | 422 | { |
404 | ret = -EBUSY; | 423 | if (!IS_ERR(data->clk_master)) |
405 | set_sysmmu_inactive(data); | 424 | clk_enable(data->clk_master); |
406 | } else { | 425 | clk_enable(data->clk); |
407 | ret = 1; | ||
408 | } | ||
409 | 426 | ||
410 | dev_dbg(data->sysmmu, "(%s) Already enabled\n", data->dbgname); | 427 | __raw_writel(CTRL_BLOCK, data->sfrbase + REG_MMU_CTRL); |
411 | goto finish; | ||
412 | } | ||
413 | 428 | ||
414 | if (data->clk[0]) | 429 | __sysmmu_init_config(data); |
415 | clk_enable(data->clk[0]); | ||
416 | if (data->clk[1]) | ||
417 | clk_enable(data->clk[1]); | ||
418 | 430 | ||
419 | data->pgtable = pgtable; | 431 | __sysmmu_set_ptbase(data->sfrbase, data->pgtable); |
420 | 432 | ||
421 | for (i = 0; i < data->nsfrs; i++) { | 433 | __raw_writel(CTRL_ENABLE, data->sfrbase + REG_MMU_CTRL); |
422 | __sysmmu_set_ptbase(data->sfrbases[i], pgtable); | ||
423 | 434 | ||
424 | if ((readl(data->sfrbases[i] + REG_MMU_VERSION) >> 28) == 3) { | 435 | if (!IS_ERR(data->clk_master)) |
425 | /* System MMU version is 3.x */ | 436 | clk_disable(data->clk_master); |
426 | __raw_writel((1 << 12) | (2 << 28), | 437 | } |
427 | data->sfrbases[i] + REG_MMU_CFG); | ||
428 | __sysmmu_set_prefbuf(data->sfrbases[i], 0, -1, 0); | ||
429 | __sysmmu_set_prefbuf(data->sfrbases[i], 0, -1, 1); | ||
430 | } | ||
431 | 438 | ||
432 | __raw_writel(CTRL_ENABLE, data->sfrbases[i] + REG_MMU_CTRL); | 439 | static int __sysmmu_enable(struct sysmmu_drvdata *data, |
440 | phys_addr_t pgtable, struct iommu_domain *domain) | ||
441 | { | ||
442 | int ret = 0; | ||
443 | unsigned long flags; | ||
444 | |||
445 | spin_lock_irqsave(&data->lock, flags); | ||
446 | if (set_sysmmu_active(data)) { | ||
447 | data->pgtable = pgtable; | ||
448 | data->domain = domain; | ||
449 | |||
450 | __sysmmu_enable_nocount(data); | ||
451 | |||
452 | dev_dbg(data->sysmmu, "Enabled\n"); | ||
453 | } else { | ||
454 | ret = (pgtable == data->pgtable) ? 1 : -EBUSY; | ||
455 | |||
456 | dev_dbg(data->sysmmu, "already enabled\n"); | ||
433 | } | 457 | } |
434 | 458 | ||
435 | data->domain = domain; | 459 | if (WARN_ON(ret < 0)) |
460 | set_sysmmu_inactive(data); /* decrement count */ | ||
436 | 461 | ||
437 | dev_dbg(data->sysmmu, "(%s) Enabled\n", data->dbgname); | 462 | spin_unlock_irqrestore(&data->lock, flags); |
438 | finish: | ||
439 | write_unlock_irqrestore(&data->lock, flags); | ||
440 | 463 | ||
441 | return ret; | 464 | return ret; |
442 | } | 465 | } |
443 | 466 | ||
444 | int exynos_sysmmu_enable(struct device *dev, unsigned long pgtable) | 467 | /* __exynos_sysmmu_enable: Enables System MMU |
468 | * | ||
469 | * returns -error if an error occurred and System MMU is not enabled, | ||
470 | * 0 if the System MMU has been just enabled and 1 if System MMU was already | ||
471 | * enabled before. | ||
472 | */ | ||
473 | static int __exynos_sysmmu_enable(struct device *dev, phys_addr_t pgtable, | ||
474 | struct iommu_domain *domain) | ||
445 | { | 475 | { |
446 | struct sysmmu_drvdata *data = dev_get_drvdata(dev->archdata.iommu); | 476 | int ret = 0; |
447 | int ret; | 477 | unsigned long flags; |
478 | struct exynos_iommu_owner *owner = dev->archdata.iommu; | ||
479 | struct sysmmu_drvdata *data; | ||
448 | 480 | ||
449 | BUG_ON(!memblock_is_memory(pgtable)); | 481 | BUG_ON(!has_sysmmu(dev)); |
450 | 482 | ||
451 | ret = pm_runtime_get_sync(data->sysmmu); | 483 | spin_lock_irqsave(&owner->lock, flags); |
452 | if (ret < 0) { | ||
453 | dev_dbg(data->sysmmu, "(%s) Failed to enable\n", data->dbgname); | ||
454 | return ret; | ||
455 | } | ||
456 | 484 | ||
457 | ret = __exynos_sysmmu_enable(data, pgtable, NULL); | 485 | data = dev_get_drvdata(owner->sysmmu); |
458 | if (WARN_ON(ret < 0)) { | 486 | |
459 | pm_runtime_put(data->sysmmu); | 487 | ret = __sysmmu_enable(data, pgtable, domain); |
460 | dev_err(data->sysmmu, | 488 | if (ret >= 0) |
461 | "(%s) Already enabled with page table %#lx\n", | 489 | data->master = dev; |
462 | data->dbgname, data->pgtable); | 490 | |
463 | } else { | 491 | spin_unlock_irqrestore(&owner->lock, flags); |
464 | data->dev = dev; | ||
465 | } | ||
466 | 492 | ||
467 | return ret; | 493 | return ret; |
468 | } | 494 | } |
469 | 495 | ||
496 | int exynos_sysmmu_enable(struct device *dev, phys_addr_t pgtable) | ||
497 | { | ||
498 | BUG_ON(!memblock_is_memory(pgtable)); | ||
499 | |||
500 | return __exynos_sysmmu_enable(dev, pgtable, NULL); | ||
501 | } | ||
502 | |||
470 | static bool exynos_sysmmu_disable(struct device *dev) | 503 | static bool exynos_sysmmu_disable(struct device *dev) |
471 | { | 504 | { |
472 | struct sysmmu_drvdata *data = dev_get_drvdata(dev->archdata.iommu); | 505 | unsigned long flags; |
473 | bool disabled; | 506 | bool disabled = true; |
507 | struct exynos_iommu_owner *owner = dev->archdata.iommu; | ||
508 | struct sysmmu_drvdata *data; | ||
509 | |||
510 | BUG_ON(!has_sysmmu(dev)); | ||
511 | |||
512 | spin_lock_irqsave(&owner->lock, flags); | ||
474 | 513 | ||
475 | disabled = __exynos_sysmmu_disable(data); | 514 | data = dev_get_drvdata(owner->sysmmu); |
476 | pm_runtime_put(data->sysmmu); | 515 | |
516 | disabled = __sysmmu_disable(data); | ||
517 | if (disabled) | ||
518 | data->master = NULL; | ||
519 | |||
520 | spin_unlock_irqrestore(&owner->lock, flags); | ||
477 | 521 | ||
478 | return disabled; | 522 | return disabled; |
479 | } | 523 | } |
480 | 524 | ||
481 | static void sysmmu_tlb_invalidate_entry(struct device *dev, unsigned long iova) | 525 | static void __sysmmu_tlb_invalidate_flpdcache(struct sysmmu_drvdata *data, |
526 | sysmmu_iova_t iova) | ||
527 | { | ||
528 | if (__raw_sysmmu_version(data) == MAKE_MMU_VER(3, 3)) | ||
529 | __raw_writel(iova | 0x1, data->sfrbase + REG_MMU_FLUSH_ENTRY); | ||
530 | } | ||
531 | |||
532 | static void sysmmu_tlb_invalidate_flpdcache(struct device *dev, | ||
533 | sysmmu_iova_t iova) | ||
534 | { | ||
535 | unsigned long flags; | ||
536 | struct exynos_iommu_owner *owner = dev->archdata.iommu; | ||
537 | struct sysmmu_drvdata *data = dev_get_drvdata(owner->sysmmu); | ||
538 | |||
539 | if (!IS_ERR(data->clk_master)) | ||
540 | clk_enable(data->clk_master); | ||
541 | |||
542 | spin_lock_irqsave(&data->lock, flags); | ||
543 | if (is_sysmmu_active(data)) | ||
544 | __sysmmu_tlb_invalidate_flpdcache(data, iova); | ||
545 | spin_unlock_irqrestore(&data->lock, flags); | ||
546 | |||
547 | if (!IS_ERR(data->clk_master)) | ||
548 | clk_disable(data->clk_master); | ||
549 | } | ||
550 | |||
551 | static void sysmmu_tlb_invalidate_entry(struct device *dev, sysmmu_iova_t iova, | ||
552 | size_t size) | ||
482 | { | 553 | { |
554 | struct exynos_iommu_owner *owner = dev->archdata.iommu; | ||
483 | unsigned long flags; | 555 | unsigned long flags; |
484 | struct sysmmu_drvdata *data = dev_get_drvdata(dev->archdata.iommu); | 556 | struct sysmmu_drvdata *data; |
485 | 557 | ||
486 | read_lock_irqsave(&data->lock, flags); | 558 | data = dev_get_drvdata(owner->sysmmu); |
487 | 559 | ||
560 | spin_lock_irqsave(&data->lock, flags); | ||
488 | if (is_sysmmu_active(data)) { | 561 | if (is_sysmmu_active(data)) { |
489 | int i; | 562 | unsigned int num_inv = 1; |
490 | for (i = 0; i < data->nsfrs; i++) { | 563 | |
491 | if (sysmmu_block(data->sfrbases[i])) { | 564 | if (!IS_ERR(data->clk_master)) |
492 | __sysmmu_tlb_invalidate_entry( | 565 | clk_enable(data->clk_master); |
493 | data->sfrbases[i], iova); | 566 | |
494 | sysmmu_unblock(data->sfrbases[i]); | 567 | /* |
495 | } | 568 | * L2TLB invalidation required |
569 | * 4KB page: 1 invalidation | ||
570 | * 64KB page: 16 invalidation | ||
571 | * 1MB page: 64 invalidation | ||
572 | * because it is set-associative TLB | ||
573 | * with 8-way and 64 sets. | ||
574 | * 1MB page can be cached in one of all sets. | ||
575 | * 64KB page can be one of 16 consecutive sets. | ||
576 | */ | ||
577 | if (MMU_MAJ_VER(__raw_sysmmu_version(data)) == 2) | ||
578 | num_inv = min_t(unsigned int, size / PAGE_SIZE, 64); | ||
579 | |||
580 | if (sysmmu_block(data->sfrbase)) { | ||
581 | __sysmmu_tlb_invalidate_entry( | ||
582 | data->sfrbase, iova, num_inv); | ||
583 | sysmmu_unblock(data->sfrbase); | ||
496 | } | 584 | } |
585 | if (!IS_ERR(data->clk_master)) | ||
586 | clk_disable(data->clk_master); | ||
497 | } else { | 587 | } else { |
498 | dev_dbg(data->sysmmu, | 588 | dev_dbg(dev, "disabled. Skipping TLB invalidation @ %#x\n", |
499 | "(%s) Disabled. Skipping invalidating TLB.\n", | 589 | iova); |
500 | data->dbgname); | ||
501 | } | 590 | } |
502 | 591 | spin_unlock_irqrestore(&data->lock, flags); | |
503 | read_unlock_irqrestore(&data->lock, flags); | ||
504 | } | 592 | } |
505 | 593 | ||
506 | void exynos_sysmmu_tlb_invalidate(struct device *dev) | 594 | void exynos_sysmmu_tlb_invalidate(struct device *dev) |
507 | { | 595 | { |
596 | struct exynos_iommu_owner *owner = dev->archdata.iommu; | ||
508 | unsigned long flags; | 597 | unsigned long flags; |
509 | struct sysmmu_drvdata *data = dev_get_drvdata(dev->archdata.iommu); | 598 | struct sysmmu_drvdata *data; |
510 | 599 | ||
511 | read_lock_irqsave(&data->lock, flags); | 600 | data = dev_get_drvdata(owner->sysmmu); |
512 | 601 | ||
602 | spin_lock_irqsave(&data->lock, flags); | ||
513 | if (is_sysmmu_active(data)) { | 603 | if (is_sysmmu_active(data)) { |
514 | int i; | 604 | if (!IS_ERR(data->clk_master)) |
515 | for (i = 0; i < data->nsfrs; i++) { | 605 | clk_enable(data->clk_master); |
516 | if (sysmmu_block(data->sfrbases[i])) { | 606 | if (sysmmu_block(data->sfrbase)) { |
517 | __sysmmu_tlb_invalidate(data->sfrbases[i]); | 607 | __sysmmu_tlb_invalidate(data->sfrbase); |
518 | sysmmu_unblock(data->sfrbases[i]); | 608 | sysmmu_unblock(data->sfrbase); |
519 | } | ||
520 | } | 609 | } |
610 | if (!IS_ERR(data->clk_master)) | ||
611 | clk_disable(data->clk_master); | ||
521 | } else { | 612 | } else { |
522 | dev_dbg(data->sysmmu, | 613 | dev_dbg(dev, "disabled. Skipping TLB invalidation\n"); |
523 | "(%s) Disabled. Skipping invalidating TLB.\n", | ||
524 | data->dbgname); | ||
525 | } | 614 | } |
526 | 615 | spin_unlock_irqrestore(&data->lock, flags); | |
527 | read_unlock_irqrestore(&data->lock, flags); | ||
528 | } | 616 | } |
529 | 617 | ||
530 | static int exynos_sysmmu_probe(struct platform_device *pdev) | 618 | static int __init exynos_sysmmu_probe(struct platform_device *pdev) |
531 | { | 619 | { |
532 | int i, ret; | 620 | int irq, ret; |
533 | struct device *dev; | 621 | struct device *dev = &pdev->dev; |
534 | struct sysmmu_drvdata *data; | 622 | struct sysmmu_drvdata *data; |
623 | struct resource *res; | ||
535 | 624 | ||
536 | dev = &pdev->dev; | 625 | data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL); |
626 | if (!data) | ||
627 | return -ENOMEM; | ||
537 | 628 | ||
538 | data = kzalloc(sizeof(*data), GFP_KERNEL); | 629 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
539 | if (!data) { | 630 | data->sfrbase = devm_ioremap_resource(dev, res); |
540 | dev_dbg(dev, "Not enough memory\n"); | 631 | if (IS_ERR(data->sfrbase)) |
541 | ret = -ENOMEM; | 632 | return PTR_ERR(data->sfrbase); |
542 | goto err_alloc; | ||
543 | } | ||
544 | 633 | ||
545 | ret = dev_set_drvdata(dev, data); | 634 | irq = platform_get_irq(pdev, 0); |
546 | if (ret) { | 635 | if (irq <= 0) { |
547 | dev_dbg(dev, "Unabled to initialize driver data\n"); | 636 | dev_err(dev, "Unable to find IRQ resource\n"); |
548 | goto err_init; | 637 | return irq; |
549 | } | 638 | } |
550 | 639 | ||
551 | data->nsfrs = pdev->num_resources / 2; | 640 | ret = devm_request_irq(dev, irq, exynos_sysmmu_irq, 0, |
552 | data->sfrbases = kmalloc(sizeof(*data->sfrbases) * data->nsfrs, | 641 | dev_name(dev), data); |
553 | GFP_KERNEL); | 642 | if (ret) { |
554 | if (data->sfrbases == NULL) { | 643 | dev_err(dev, "Unabled to register handler of irq %d\n", irq); |
555 | dev_dbg(dev, "Not enough memory\n"); | 644 | return ret; |
556 | ret = -ENOMEM; | ||
557 | goto err_init; | ||
558 | } | ||
559 | |||
560 | for (i = 0; i < data->nsfrs; i++) { | ||
561 | struct resource *res; | ||
562 | res = platform_get_resource(pdev, IORESOURCE_MEM, i); | ||
563 | if (!res) { | ||
564 | dev_dbg(dev, "Unable to find IOMEM region\n"); | ||
565 | ret = -ENOENT; | ||
566 | goto err_res; | ||
567 | } | ||
568 | |||
569 | data->sfrbases[i] = ioremap(res->start, resource_size(res)); | ||
570 | if (!data->sfrbases[i]) { | ||
571 | dev_dbg(dev, "Unable to map IOMEM @ PA:%#x\n", | ||
572 | res->start); | ||
573 | ret = -ENOENT; | ||
574 | goto err_res; | ||
575 | } | ||
576 | } | 645 | } |
577 | 646 | ||
578 | for (i = 0; i < data->nsfrs; i++) { | 647 | data->clk = devm_clk_get(dev, "sysmmu"); |
579 | ret = platform_get_irq(pdev, i); | 648 | if (IS_ERR(data->clk)) { |
580 | if (ret <= 0) { | 649 | dev_err(dev, "Failed to get clock!\n"); |
581 | dev_dbg(dev, "Unable to find IRQ resource\n"); | 650 | return PTR_ERR(data->clk); |
582 | goto err_irq; | 651 | } else { |
583 | } | 652 | ret = clk_prepare(data->clk); |
584 | |||
585 | ret = request_irq(ret, exynos_sysmmu_irq, 0, | ||
586 | dev_name(dev), data); | ||
587 | if (ret) { | 653 | if (ret) { |
588 | dev_dbg(dev, "Unabled to register interrupt handler\n"); | 654 | dev_err(dev, "Failed to prepare clk\n"); |
589 | goto err_irq; | 655 | return ret; |
590 | } | 656 | } |
591 | } | 657 | } |
592 | 658 | ||
593 | if (dev_get_platdata(dev)) { | 659 | data->clk_master = devm_clk_get(dev, "master"); |
594 | char *deli, *beg; | 660 | if (!IS_ERR(data->clk_master)) { |
595 | struct sysmmu_platform_data *platdata = dev_get_platdata(dev); | 661 | ret = clk_prepare(data->clk_master); |
596 | 662 | if (ret) { | |
597 | beg = platdata->clockname; | 663 | clk_unprepare(data->clk); |
598 | 664 | dev_err(dev, "Failed to prepare master's clk\n"); | |
599 | for (deli = beg; (*deli != '\0') && (*deli != ','); deli++) | 665 | return ret; |
600 | /* NOTHING */; | ||
601 | |||
602 | if (*deli == '\0') | ||
603 | deli = NULL; | ||
604 | else | ||
605 | *deli = '\0'; | ||
606 | |||
607 | data->clk[0] = clk_get(dev, beg); | ||
608 | if (IS_ERR(data->clk[0])) { | ||
609 | data->clk[0] = NULL; | ||
610 | dev_dbg(dev, "No clock descriptor registered\n"); | ||
611 | } | ||
612 | |||
613 | if (data->clk[0] && deli) { | ||
614 | *deli = ','; | ||
615 | data->clk[1] = clk_get(dev, deli + 1); | ||
616 | if (IS_ERR(data->clk[1])) | ||
617 | data->clk[1] = NULL; | ||
618 | } | 666 | } |
619 | |||
620 | data->dbgname = platdata->dbgname; | ||
621 | } | 667 | } |
622 | 668 | ||
623 | data->sysmmu = dev; | 669 | data->sysmmu = dev; |
624 | rwlock_init(&data->lock); | 670 | spin_lock_init(&data->lock); |
625 | INIT_LIST_HEAD(&data->node); | ||
626 | 671 | ||
627 | __set_fault_handler(data, &default_fault_handler); | 672 | platform_set_drvdata(pdev, data); |
628 | 673 | ||
629 | if (dev->parent) | 674 | pm_runtime_enable(dev); |
630 | pm_runtime_enable(dev); | ||
631 | 675 | ||
632 | dev_dbg(dev, "(%s) Initialized\n", data->dbgname); | ||
633 | return 0; | 676 | return 0; |
634 | err_irq: | ||
635 | while (i-- > 0) { | ||
636 | int irq; | ||
637 | |||
638 | irq = platform_get_irq(pdev, i); | ||
639 | free_irq(irq, data); | ||
640 | } | ||
641 | err_res: | ||
642 | while (data->nsfrs-- > 0) | ||
643 | iounmap(data->sfrbases[data->nsfrs]); | ||
644 | kfree(data->sfrbases); | ||
645 | err_init: | ||
646 | kfree(data); | ||
647 | err_alloc: | ||
648 | dev_err(dev, "Failed to initialize\n"); | ||
649 | return ret; | ||
650 | } | 677 | } |
651 | 678 | ||
652 | static struct platform_driver exynos_sysmmu_driver = { | 679 | static const struct of_device_id sysmmu_of_match[] __initconst = { |
653 | .probe = exynos_sysmmu_probe, | 680 | { .compatible = "samsung,exynos-sysmmu", }, |
654 | .driver = { | 681 | { }, |
682 | }; | ||
683 | |||
684 | static struct platform_driver exynos_sysmmu_driver __refdata = { | ||
685 | .probe = exynos_sysmmu_probe, | ||
686 | .driver = { | ||
655 | .owner = THIS_MODULE, | 687 | .owner = THIS_MODULE, |
656 | .name = "exynos-sysmmu", | 688 | .name = "exynos-sysmmu", |
689 | .of_match_table = sysmmu_of_match, | ||
657 | } | 690 | } |
658 | }; | 691 | }; |
659 | 692 | ||
@@ -667,21 +700,32 @@ static inline void pgtable_flush(void *vastart, void *vaend) | |||
667 | static int exynos_iommu_domain_init(struct iommu_domain *domain) | 700 | static int exynos_iommu_domain_init(struct iommu_domain *domain) |
668 | { | 701 | { |
669 | struct exynos_iommu_domain *priv; | 702 | struct exynos_iommu_domain *priv; |
703 | int i; | ||
670 | 704 | ||
671 | priv = kzalloc(sizeof(*priv), GFP_KERNEL); | 705 | priv = kzalloc(sizeof(*priv), GFP_KERNEL); |
672 | if (!priv) | 706 | if (!priv) |
673 | return -ENOMEM; | 707 | return -ENOMEM; |
674 | 708 | ||
675 | priv->pgtable = (unsigned long *)__get_free_pages( | 709 | priv->pgtable = (sysmmu_pte_t *)__get_free_pages(GFP_KERNEL, 2); |
676 | GFP_KERNEL | __GFP_ZERO, 2); | ||
677 | if (!priv->pgtable) | 710 | if (!priv->pgtable) |
678 | goto err_pgtable; | 711 | goto err_pgtable; |
679 | 712 | ||
680 | priv->lv2entcnt = (short *)__get_free_pages( | 713 | priv->lv2entcnt = (short *)__get_free_pages(GFP_KERNEL | __GFP_ZERO, 1); |
681 | GFP_KERNEL | __GFP_ZERO, 1); | ||
682 | if (!priv->lv2entcnt) | 714 | if (!priv->lv2entcnt) |
683 | goto err_counter; | 715 | goto err_counter; |
684 | 716 | ||
717 | /* w/a of System MMU v3.3 to prevent caching 1MiB mapping */ | ||
718 | for (i = 0; i < NUM_LV1ENTRIES; i += 8) { | ||
719 | priv->pgtable[i + 0] = ZERO_LV2LINK; | ||
720 | priv->pgtable[i + 1] = ZERO_LV2LINK; | ||
721 | priv->pgtable[i + 2] = ZERO_LV2LINK; | ||
722 | priv->pgtable[i + 3] = ZERO_LV2LINK; | ||
723 | priv->pgtable[i + 4] = ZERO_LV2LINK; | ||
724 | priv->pgtable[i + 5] = ZERO_LV2LINK; | ||
725 | priv->pgtable[i + 6] = ZERO_LV2LINK; | ||
726 | priv->pgtable[i + 7] = ZERO_LV2LINK; | ||
727 | } | ||
728 | |||
685 | pgtable_flush(priv->pgtable, priv->pgtable + NUM_LV1ENTRIES); | 729 | pgtable_flush(priv->pgtable, priv->pgtable + NUM_LV1ENTRIES); |
686 | 730 | ||
687 | spin_lock_init(&priv->lock); | 731 | spin_lock_init(&priv->lock); |
@@ -705,7 +749,7 @@ err_pgtable: | |||
705 | static void exynos_iommu_domain_destroy(struct iommu_domain *domain) | 749 | static void exynos_iommu_domain_destroy(struct iommu_domain *domain) |
706 | { | 750 | { |
707 | struct exynos_iommu_domain *priv = domain->priv; | 751 | struct exynos_iommu_domain *priv = domain->priv; |
708 | struct sysmmu_drvdata *data; | 752 | struct exynos_iommu_owner *owner; |
709 | unsigned long flags; | 753 | unsigned long flags; |
710 | int i; | 754 | int i; |
711 | 755 | ||
@@ -713,16 +757,20 @@ static void exynos_iommu_domain_destroy(struct iommu_domain *domain) | |||
713 | 757 | ||
714 | spin_lock_irqsave(&priv->lock, flags); | 758 | spin_lock_irqsave(&priv->lock, flags); |
715 | 759 | ||
716 | list_for_each_entry(data, &priv->clients, node) { | 760 | list_for_each_entry(owner, &priv->clients, client) { |
717 | while (!exynos_sysmmu_disable(data->dev)) | 761 | while (!exynos_sysmmu_disable(owner->dev)) |
718 | ; /* until System MMU is actually disabled */ | 762 | ; /* until System MMU is actually disabled */ |
719 | } | 763 | } |
720 | 764 | ||
765 | while (!list_empty(&priv->clients)) | ||
766 | list_del_init(priv->clients.next); | ||
767 | |||
721 | spin_unlock_irqrestore(&priv->lock, flags); | 768 | spin_unlock_irqrestore(&priv->lock, flags); |
722 | 769 | ||
723 | for (i = 0; i < NUM_LV1ENTRIES; i++) | 770 | for (i = 0; i < NUM_LV1ENTRIES; i++) |
724 | if (lv1ent_page(priv->pgtable + i)) | 771 | if (lv1ent_page(priv->pgtable + i)) |
725 | kfree(__va(lv2table_base(priv->pgtable + i))); | 772 | kmem_cache_free(lv2table_kmem_cache, |
773 | phys_to_virt(lv2table_base(priv->pgtable + i))); | ||
726 | 774 | ||
727 | free_pages((unsigned long)priv->pgtable, 2); | 775 | free_pages((unsigned long)priv->pgtable, 2); |
728 | free_pages((unsigned long)priv->lv2entcnt, 1); | 776 | free_pages((unsigned long)priv->lv2entcnt, 1); |
@@ -733,114 +781,134 @@ static void exynos_iommu_domain_destroy(struct iommu_domain *domain) | |||
733 | static int exynos_iommu_attach_device(struct iommu_domain *domain, | 781 | static int exynos_iommu_attach_device(struct iommu_domain *domain, |
734 | struct device *dev) | 782 | struct device *dev) |
735 | { | 783 | { |
736 | struct sysmmu_drvdata *data = dev_get_drvdata(dev->archdata.iommu); | 784 | struct exynos_iommu_owner *owner = dev->archdata.iommu; |
737 | struct exynos_iommu_domain *priv = domain->priv; | 785 | struct exynos_iommu_domain *priv = domain->priv; |
786 | phys_addr_t pagetable = virt_to_phys(priv->pgtable); | ||
738 | unsigned long flags; | 787 | unsigned long flags; |
739 | int ret; | 788 | int ret; |
740 | 789 | ||
741 | ret = pm_runtime_get_sync(data->sysmmu); | ||
742 | if (ret < 0) | ||
743 | return ret; | ||
744 | |||
745 | ret = 0; | ||
746 | |||
747 | spin_lock_irqsave(&priv->lock, flags); | 790 | spin_lock_irqsave(&priv->lock, flags); |
748 | 791 | ||
749 | ret = __exynos_sysmmu_enable(data, __pa(priv->pgtable), domain); | 792 | ret = __exynos_sysmmu_enable(dev, pagetable, domain); |
750 | |||
751 | if (ret == 0) { | 793 | if (ret == 0) { |
752 | /* 'data->node' must not be appeared in priv->clients */ | 794 | list_add_tail(&owner->client, &priv->clients); |
753 | BUG_ON(!list_empty(&data->node)); | 795 | owner->domain = domain; |
754 | data->dev = dev; | ||
755 | list_add_tail(&data->node, &priv->clients); | ||
756 | } | 796 | } |
757 | 797 | ||
758 | spin_unlock_irqrestore(&priv->lock, flags); | 798 | spin_unlock_irqrestore(&priv->lock, flags); |
759 | 799 | ||
760 | if (ret < 0) { | 800 | if (ret < 0) { |
761 | dev_err(dev, "%s: Failed to attach IOMMU with pgtable %#lx\n", | 801 | dev_err(dev, "%s: Failed to attach IOMMU with pgtable %pa\n", |
762 | __func__, __pa(priv->pgtable)); | 802 | __func__, &pagetable); |
763 | pm_runtime_put(data->sysmmu); | 803 | return ret; |
764 | } else if (ret > 0) { | ||
765 | dev_dbg(dev, "%s: IOMMU with pgtable 0x%lx already attached\n", | ||
766 | __func__, __pa(priv->pgtable)); | ||
767 | } else { | ||
768 | dev_dbg(dev, "%s: Attached new IOMMU with pgtable 0x%lx\n", | ||
769 | __func__, __pa(priv->pgtable)); | ||
770 | } | 804 | } |
771 | 805 | ||
806 | dev_dbg(dev, "%s: Attached IOMMU with pgtable %pa %s\n", | ||
807 | __func__, &pagetable, (ret == 0) ? "" : ", again"); | ||
808 | |||
772 | return ret; | 809 | return ret; |
773 | } | 810 | } |
774 | 811 | ||
775 | static void exynos_iommu_detach_device(struct iommu_domain *domain, | 812 | static void exynos_iommu_detach_device(struct iommu_domain *domain, |
776 | struct device *dev) | 813 | struct device *dev) |
777 | { | 814 | { |
778 | struct sysmmu_drvdata *data = dev_get_drvdata(dev->archdata.iommu); | 815 | struct exynos_iommu_owner *owner; |
779 | struct exynos_iommu_domain *priv = domain->priv; | 816 | struct exynos_iommu_domain *priv = domain->priv; |
780 | struct list_head *pos; | 817 | phys_addr_t pagetable = virt_to_phys(priv->pgtable); |
781 | unsigned long flags; | 818 | unsigned long flags; |
782 | bool found = false; | ||
783 | 819 | ||
784 | spin_lock_irqsave(&priv->lock, flags); | 820 | spin_lock_irqsave(&priv->lock, flags); |
785 | 821 | ||
786 | list_for_each(pos, &priv->clients) { | 822 | list_for_each_entry(owner, &priv->clients, client) { |
787 | if (list_entry(pos, struct sysmmu_drvdata, node) == data) { | 823 | if (owner == dev->archdata.iommu) { |
788 | found = true; | 824 | if (exynos_sysmmu_disable(dev)) { |
825 | list_del_init(&owner->client); | ||
826 | owner->domain = NULL; | ||
827 | } | ||
789 | break; | 828 | break; |
790 | } | 829 | } |
791 | } | 830 | } |
792 | 831 | ||
793 | if (!found) | ||
794 | goto finish; | ||
795 | |||
796 | if (__exynos_sysmmu_disable(data)) { | ||
797 | dev_dbg(dev, "%s: Detached IOMMU with pgtable %#lx\n", | ||
798 | __func__, __pa(priv->pgtable)); | ||
799 | list_del_init(&data->node); | ||
800 | |||
801 | } else { | ||
802 | dev_dbg(dev, "%s: Detaching IOMMU with pgtable %#lx delayed", | ||
803 | __func__, __pa(priv->pgtable)); | ||
804 | } | ||
805 | |||
806 | finish: | ||
807 | spin_unlock_irqrestore(&priv->lock, flags); | 832 | spin_unlock_irqrestore(&priv->lock, flags); |
808 | 833 | ||
809 | if (found) | 834 | if (owner == dev->archdata.iommu) |
810 | pm_runtime_put(data->sysmmu); | 835 | dev_dbg(dev, "%s: Detached IOMMU with pgtable %pa\n", |
836 | __func__, &pagetable); | ||
837 | else | ||
838 | dev_err(dev, "%s: No IOMMU is attached\n", __func__); | ||
811 | } | 839 | } |
812 | 840 | ||
813 | static unsigned long *alloc_lv2entry(unsigned long *sent, unsigned long iova, | 841 | static sysmmu_pte_t *alloc_lv2entry(struct exynos_iommu_domain *priv, |
814 | short *pgcounter) | 842 | sysmmu_pte_t *sent, sysmmu_iova_t iova, short *pgcounter) |
815 | { | 843 | { |
844 | if (lv1ent_section(sent)) { | ||
845 | WARN(1, "Trying mapping on %#08x mapped with 1MiB page", iova); | ||
846 | return ERR_PTR(-EADDRINUSE); | ||
847 | } | ||
848 | |||
816 | if (lv1ent_fault(sent)) { | 849 | if (lv1ent_fault(sent)) { |
817 | unsigned long *pent; | 850 | sysmmu_pte_t *pent; |
851 | bool need_flush_flpd_cache = lv1ent_zero(sent); | ||
818 | 852 | ||
819 | pent = kzalloc(LV2TABLE_SIZE, GFP_ATOMIC); | 853 | pent = kmem_cache_zalloc(lv2table_kmem_cache, GFP_ATOMIC); |
820 | BUG_ON((unsigned long)pent & (LV2TABLE_SIZE - 1)); | 854 | BUG_ON((unsigned int)pent & (LV2TABLE_SIZE - 1)); |
821 | if (!pent) | 855 | if (!pent) |
822 | return NULL; | 856 | return ERR_PTR(-ENOMEM); |
823 | 857 | ||
824 | *sent = mk_lv1ent_page(__pa(pent)); | 858 | *sent = mk_lv1ent_page(virt_to_phys(pent)); |
825 | *pgcounter = NUM_LV2ENTRIES; | 859 | *pgcounter = NUM_LV2ENTRIES; |
826 | pgtable_flush(pent, pent + NUM_LV2ENTRIES); | 860 | pgtable_flush(pent, pent + NUM_LV2ENTRIES); |
827 | pgtable_flush(sent, sent + 1); | 861 | pgtable_flush(sent, sent + 1); |
862 | |||
863 | /* | ||
864 | * If pretched SLPD is a fault SLPD in zero_l2_table, FLPD cache | ||
865 | * may caches the address of zero_l2_table. This function | ||
866 | * replaces the zero_l2_table with new L2 page table to write | ||
867 | * valid mappings. | ||
868 | * Accessing the valid area may cause page fault since FLPD | ||
869 | * cache may still caches zero_l2_table for the valid area | ||
870 | * instead of new L2 page table that have the mapping | ||
871 | * information of the valid area | ||
872 | * Thus any replacement of zero_l2_table with other valid L2 | ||
873 | * page table must involve FLPD cache invalidation for System | ||
874 | * MMU v3.3. | ||
875 | * FLPD cache invalidation is performed with TLB invalidation | ||
876 | * by VPN without blocking. It is safe to invalidate TLB without | ||
877 | * blocking because the target address of TLB invalidation is | ||
878 | * not currently mapped. | ||
879 | */ | ||
880 | if (need_flush_flpd_cache) { | ||
881 | struct exynos_iommu_owner *owner; | ||
882 | |||
883 | spin_lock(&priv->lock); | ||
884 | list_for_each_entry(owner, &priv->clients, client) | ||
885 | sysmmu_tlb_invalidate_flpdcache( | ||
886 | owner->dev, iova); | ||
887 | spin_unlock(&priv->lock); | ||
888 | } | ||
828 | } | 889 | } |
829 | 890 | ||
830 | return page_entry(sent, iova); | 891 | return page_entry(sent, iova); |
831 | } | 892 | } |
832 | 893 | ||
833 | static int lv1set_section(unsigned long *sent, phys_addr_t paddr, short *pgcnt) | 894 | static int lv1set_section(struct exynos_iommu_domain *priv, |
895 | sysmmu_pte_t *sent, sysmmu_iova_t iova, | ||
896 | phys_addr_t paddr, short *pgcnt) | ||
834 | { | 897 | { |
835 | if (lv1ent_section(sent)) | 898 | if (lv1ent_section(sent)) { |
899 | WARN(1, "Trying mapping on 1MiB@%#08x that is mapped", | ||
900 | iova); | ||
836 | return -EADDRINUSE; | 901 | return -EADDRINUSE; |
902 | } | ||
837 | 903 | ||
838 | if (lv1ent_page(sent)) { | 904 | if (lv1ent_page(sent)) { |
839 | if (*pgcnt != NUM_LV2ENTRIES) | 905 | if (*pgcnt != NUM_LV2ENTRIES) { |
906 | WARN(1, "Trying mapping on 1MiB@%#08x that is mapped", | ||
907 | iova); | ||
840 | return -EADDRINUSE; | 908 | return -EADDRINUSE; |
909 | } | ||
841 | 910 | ||
842 | kfree(page_entry(sent, 0)); | 911 | kmem_cache_free(lv2table_kmem_cache, page_entry(sent, 0)); |
843 | |||
844 | *pgcnt = 0; | 912 | *pgcnt = 0; |
845 | } | 913 | } |
846 | 914 | ||
@@ -848,14 +916,26 @@ static int lv1set_section(unsigned long *sent, phys_addr_t paddr, short *pgcnt) | |||
848 | 916 | ||
849 | pgtable_flush(sent, sent + 1); | 917 | pgtable_flush(sent, sent + 1); |
850 | 918 | ||
919 | spin_lock(&priv->lock); | ||
920 | if (lv1ent_page_zero(sent)) { | ||
921 | struct exynos_iommu_owner *owner; | ||
922 | /* | ||
923 | * Flushing FLPD cache in System MMU v3.3 that may cache a FLPD | ||
924 | * entry by speculative prefetch of SLPD which has no mapping. | ||
925 | */ | ||
926 | list_for_each_entry(owner, &priv->clients, client) | ||
927 | sysmmu_tlb_invalidate_flpdcache(owner->dev, iova); | ||
928 | } | ||
929 | spin_unlock(&priv->lock); | ||
930 | |||
851 | return 0; | 931 | return 0; |
852 | } | 932 | } |
853 | 933 | ||
854 | static int lv2set_page(unsigned long *pent, phys_addr_t paddr, size_t size, | 934 | static int lv2set_page(sysmmu_pte_t *pent, phys_addr_t paddr, size_t size, |
855 | short *pgcnt) | 935 | short *pgcnt) |
856 | { | 936 | { |
857 | if (size == SPAGE_SIZE) { | 937 | if (size == SPAGE_SIZE) { |
858 | if (!lv2ent_fault(pent)) | 938 | if (WARN_ON(!lv2ent_fault(pent))) |
859 | return -EADDRINUSE; | 939 | return -EADDRINUSE; |
860 | 940 | ||
861 | *pent = mk_lv2ent_spage(paddr); | 941 | *pent = mk_lv2ent_spage(paddr); |
@@ -863,9 +943,11 @@ static int lv2set_page(unsigned long *pent, phys_addr_t paddr, size_t size, | |||
863 | *pgcnt -= 1; | 943 | *pgcnt -= 1; |
864 | } else { /* size == LPAGE_SIZE */ | 944 | } else { /* size == LPAGE_SIZE */ |
865 | int i; | 945 | int i; |
946 | |||
866 | for (i = 0; i < SPAGES_PER_LPAGE; i++, pent++) { | 947 | for (i = 0; i < SPAGES_PER_LPAGE; i++, pent++) { |
867 | if (!lv2ent_fault(pent)) { | 948 | if (WARN_ON(!lv2ent_fault(pent))) { |
868 | memset(pent, 0, sizeof(*pent) * i); | 949 | if (i > 0) |
950 | memset(pent - i, 0, sizeof(*pent) * i); | ||
869 | return -EADDRINUSE; | 951 | return -EADDRINUSE; |
870 | } | 952 | } |
871 | 953 | ||
@@ -878,11 +960,38 @@ static int lv2set_page(unsigned long *pent, phys_addr_t paddr, size_t size, | |||
878 | return 0; | 960 | return 0; |
879 | } | 961 | } |
880 | 962 | ||
881 | static int exynos_iommu_map(struct iommu_domain *domain, unsigned long iova, | 963 | /* |
964 | * *CAUTION* to the I/O virtual memory managers that support exynos-iommu: | ||
965 | * | ||
966 | * System MMU v3.x have an advanced logic to improve address translation | ||
967 | * performance with caching more page table entries by a page table walk. | ||
968 | * However, the logic has a bug that caching fault page table entries and System | ||
969 | * MMU reports page fault if the cached fault entry is hit even though the fault | ||
970 | * entry is updated to a valid entry after the entry is cached. | ||
971 | * To prevent caching fault page table entries which may be updated to valid | ||
972 | * entries later, the virtual memory manager should care about the w/a about the | ||
973 | * problem. The followings describe w/a. | ||
974 | * | ||
975 | * Any two consecutive I/O virtual address regions must have a hole of 128KiB | ||
976 | * in maximum to prevent misbehavior of System MMU 3.x. (w/a of h/w bug) | ||
977 | * | ||
978 | * Precisely, any start address of I/O virtual region must be aligned by | ||
979 | * the following sizes for System MMU v3.1 and v3.2. | ||
980 | * System MMU v3.1: 128KiB | ||
981 | * System MMU v3.2: 256KiB | ||
982 | * | ||
983 | * Because System MMU v3.3 caches page table entries more aggressively, it needs | ||
984 | * more w/a. | ||
985 | * - Any two consecutive I/O virtual regions must be have a hole of larger size | ||
986 | * than or equal size to 128KiB. | ||
987 | * - Start address of an I/O virtual region must be aligned by 128KiB. | ||
988 | */ | ||
989 | static int exynos_iommu_map(struct iommu_domain *domain, unsigned long l_iova, | ||
882 | phys_addr_t paddr, size_t size, int prot) | 990 | phys_addr_t paddr, size_t size, int prot) |
883 | { | 991 | { |
884 | struct exynos_iommu_domain *priv = domain->priv; | 992 | struct exynos_iommu_domain *priv = domain->priv; |
885 | unsigned long *entry; | 993 | sysmmu_pte_t *entry; |
994 | sysmmu_iova_t iova = (sysmmu_iova_t)l_iova; | ||
886 | unsigned long flags; | 995 | unsigned long flags; |
887 | int ret = -ENOMEM; | 996 | int ret = -ENOMEM; |
888 | 997 | ||
@@ -893,38 +1002,52 @@ static int exynos_iommu_map(struct iommu_domain *domain, unsigned long iova, | |||
893 | entry = section_entry(priv->pgtable, iova); | 1002 | entry = section_entry(priv->pgtable, iova); |
894 | 1003 | ||
895 | if (size == SECT_SIZE) { | 1004 | if (size == SECT_SIZE) { |
896 | ret = lv1set_section(entry, paddr, | 1005 | ret = lv1set_section(priv, entry, iova, paddr, |
897 | &priv->lv2entcnt[lv1ent_offset(iova)]); | 1006 | &priv->lv2entcnt[lv1ent_offset(iova)]); |
898 | } else { | 1007 | } else { |
899 | unsigned long *pent; | 1008 | sysmmu_pte_t *pent; |
900 | 1009 | ||
901 | pent = alloc_lv2entry(entry, iova, | 1010 | pent = alloc_lv2entry(priv, entry, iova, |
902 | &priv->lv2entcnt[lv1ent_offset(iova)]); | 1011 | &priv->lv2entcnt[lv1ent_offset(iova)]); |
903 | 1012 | ||
904 | if (!pent) | 1013 | if (IS_ERR(pent)) |
905 | ret = -ENOMEM; | 1014 | ret = PTR_ERR(pent); |
906 | else | 1015 | else |
907 | ret = lv2set_page(pent, paddr, size, | 1016 | ret = lv2set_page(pent, paddr, size, |
908 | &priv->lv2entcnt[lv1ent_offset(iova)]); | 1017 | &priv->lv2entcnt[lv1ent_offset(iova)]); |
909 | } | 1018 | } |
910 | 1019 | ||
911 | if (ret) { | 1020 | if (ret) |
912 | pr_debug("%s: Failed to map iova 0x%lx/0x%x bytes\n", | 1021 | pr_err("%s: Failed(%d) to map %#zx bytes @ %#x\n", |
913 | __func__, iova, size); | 1022 | __func__, ret, size, iova); |
914 | } | ||
915 | 1023 | ||
916 | spin_unlock_irqrestore(&priv->pgtablelock, flags); | 1024 | spin_unlock_irqrestore(&priv->pgtablelock, flags); |
917 | 1025 | ||
918 | return ret; | 1026 | return ret; |
919 | } | 1027 | } |
920 | 1028 | ||
1029 | static void exynos_iommu_tlb_invalidate_entry(struct exynos_iommu_domain *priv, | ||
1030 | sysmmu_iova_t iova, size_t size) | ||
1031 | { | ||
1032 | struct exynos_iommu_owner *owner; | ||
1033 | unsigned long flags; | ||
1034 | |||
1035 | spin_lock_irqsave(&priv->lock, flags); | ||
1036 | |||
1037 | list_for_each_entry(owner, &priv->clients, client) | ||
1038 | sysmmu_tlb_invalidate_entry(owner->dev, iova, size); | ||
1039 | |||
1040 | spin_unlock_irqrestore(&priv->lock, flags); | ||
1041 | } | ||
1042 | |||
921 | static size_t exynos_iommu_unmap(struct iommu_domain *domain, | 1043 | static size_t exynos_iommu_unmap(struct iommu_domain *domain, |
922 | unsigned long iova, size_t size) | 1044 | unsigned long l_iova, size_t size) |
923 | { | 1045 | { |
924 | struct exynos_iommu_domain *priv = domain->priv; | 1046 | struct exynos_iommu_domain *priv = domain->priv; |
925 | struct sysmmu_drvdata *data; | 1047 | sysmmu_iova_t iova = (sysmmu_iova_t)l_iova; |
1048 | sysmmu_pte_t *ent; | ||
1049 | size_t err_pgsize; | ||
926 | unsigned long flags; | 1050 | unsigned long flags; |
927 | unsigned long *ent; | ||
928 | 1051 | ||
929 | BUG_ON(priv->pgtable == NULL); | 1052 | BUG_ON(priv->pgtable == NULL); |
930 | 1053 | ||
@@ -933,9 +1056,12 @@ static size_t exynos_iommu_unmap(struct iommu_domain *domain, | |||
933 | ent = section_entry(priv->pgtable, iova); | 1056 | ent = section_entry(priv->pgtable, iova); |
934 | 1057 | ||
935 | if (lv1ent_section(ent)) { | 1058 | if (lv1ent_section(ent)) { |
936 | BUG_ON(size < SECT_SIZE); | 1059 | if (WARN_ON(size < SECT_SIZE)) { |
1060 | err_pgsize = SECT_SIZE; | ||
1061 | goto err; | ||
1062 | } | ||
937 | 1063 | ||
938 | *ent = 0; | 1064 | *ent = ZERO_LV2LINK; /* w/a for h/w bug in Sysmem MMU v3.3 */ |
939 | pgtable_flush(ent, ent + 1); | 1065 | pgtable_flush(ent, ent + 1); |
940 | size = SECT_SIZE; | 1066 | size = SECT_SIZE; |
941 | goto done; | 1067 | goto done; |
@@ -959,34 +1085,42 @@ static size_t exynos_iommu_unmap(struct iommu_domain *domain, | |||
959 | if (lv2ent_small(ent)) { | 1085 | if (lv2ent_small(ent)) { |
960 | *ent = 0; | 1086 | *ent = 0; |
961 | size = SPAGE_SIZE; | 1087 | size = SPAGE_SIZE; |
1088 | pgtable_flush(ent, ent + 1); | ||
962 | priv->lv2entcnt[lv1ent_offset(iova)] += 1; | 1089 | priv->lv2entcnt[lv1ent_offset(iova)] += 1; |
963 | goto done; | 1090 | goto done; |
964 | } | 1091 | } |
965 | 1092 | ||
966 | /* lv1ent_large(ent) == true here */ | 1093 | /* lv1ent_large(ent) == true here */ |
967 | BUG_ON(size < LPAGE_SIZE); | 1094 | if (WARN_ON(size < LPAGE_SIZE)) { |
1095 | err_pgsize = LPAGE_SIZE; | ||
1096 | goto err; | ||
1097 | } | ||
968 | 1098 | ||
969 | memset(ent, 0, sizeof(*ent) * SPAGES_PER_LPAGE); | 1099 | memset(ent, 0, sizeof(*ent) * SPAGES_PER_LPAGE); |
1100 | pgtable_flush(ent, ent + SPAGES_PER_LPAGE); | ||
970 | 1101 | ||
971 | size = LPAGE_SIZE; | 1102 | size = LPAGE_SIZE; |
972 | priv->lv2entcnt[lv1ent_offset(iova)] += SPAGES_PER_LPAGE; | 1103 | priv->lv2entcnt[lv1ent_offset(iova)] += SPAGES_PER_LPAGE; |
973 | done: | 1104 | done: |
974 | spin_unlock_irqrestore(&priv->pgtablelock, flags); | 1105 | spin_unlock_irqrestore(&priv->pgtablelock, flags); |
975 | 1106 | ||
976 | spin_lock_irqsave(&priv->lock, flags); | 1107 | exynos_iommu_tlb_invalidate_entry(priv, iova, size); |
977 | list_for_each_entry(data, &priv->clients, node) | ||
978 | sysmmu_tlb_invalidate_entry(data->dev, iova); | ||
979 | spin_unlock_irqrestore(&priv->lock, flags); | ||
980 | |||
981 | 1108 | ||
982 | return size; | 1109 | return size; |
1110 | err: | ||
1111 | spin_unlock_irqrestore(&priv->pgtablelock, flags); | ||
1112 | |||
1113 | pr_err("%s: Failed: size(%#zx) @ %#x is smaller than page size %#zx\n", | ||
1114 | __func__, size, iova, err_pgsize); | ||
1115 | |||
1116 | return 0; | ||
983 | } | 1117 | } |
984 | 1118 | ||
985 | static phys_addr_t exynos_iommu_iova_to_phys(struct iommu_domain *domain, | 1119 | static phys_addr_t exynos_iommu_iova_to_phys(struct iommu_domain *domain, |
986 | dma_addr_t iova) | 1120 | dma_addr_t iova) |
987 | { | 1121 | { |
988 | struct exynos_iommu_domain *priv = domain->priv; | 1122 | struct exynos_iommu_domain *priv = domain->priv; |
989 | unsigned long *entry; | 1123 | sysmmu_pte_t *entry; |
990 | unsigned long flags; | 1124 | unsigned long flags; |
991 | phys_addr_t phys = 0; | 1125 | phys_addr_t phys = 0; |
992 | 1126 | ||
@@ -1010,14 +1144,42 @@ static phys_addr_t exynos_iommu_iova_to_phys(struct iommu_domain *domain, | |||
1010 | return phys; | 1144 | return phys; |
1011 | } | 1145 | } |
1012 | 1146 | ||
1147 | static int exynos_iommu_add_device(struct device *dev) | ||
1148 | { | ||
1149 | struct iommu_group *group; | ||
1150 | int ret; | ||
1151 | |||
1152 | group = iommu_group_get(dev); | ||
1153 | |||
1154 | if (!group) { | ||
1155 | group = iommu_group_alloc(); | ||
1156 | if (IS_ERR(group)) { | ||
1157 | dev_err(dev, "Failed to allocate IOMMU group\n"); | ||
1158 | return PTR_ERR(group); | ||
1159 | } | ||
1160 | } | ||
1161 | |||
1162 | ret = iommu_group_add_device(group, dev); | ||
1163 | iommu_group_put(group); | ||
1164 | |||
1165 | return ret; | ||
1166 | } | ||
1167 | |||
1168 | static void exynos_iommu_remove_device(struct device *dev) | ||
1169 | { | ||
1170 | iommu_group_remove_device(dev); | ||
1171 | } | ||
1172 | |||
1013 | static struct iommu_ops exynos_iommu_ops = { | 1173 | static struct iommu_ops exynos_iommu_ops = { |
1014 | .domain_init = &exynos_iommu_domain_init, | 1174 | .domain_init = exynos_iommu_domain_init, |
1015 | .domain_destroy = &exynos_iommu_domain_destroy, | 1175 | .domain_destroy = exynos_iommu_domain_destroy, |
1016 | .attach_dev = &exynos_iommu_attach_device, | 1176 | .attach_dev = exynos_iommu_attach_device, |
1017 | .detach_dev = &exynos_iommu_detach_device, | 1177 | .detach_dev = exynos_iommu_detach_device, |
1018 | .map = &exynos_iommu_map, | 1178 | .map = exynos_iommu_map, |
1019 | .unmap = &exynos_iommu_unmap, | 1179 | .unmap = exynos_iommu_unmap, |
1020 | .iova_to_phys = &exynos_iommu_iova_to_phys, | 1180 | .iova_to_phys = exynos_iommu_iova_to_phys, |
1181 | .add_device = exynos_iommu_add_device, | ||
1182 | .remove_device = exynos_iommu_remove_device, | ||
1021 | .pgsize_bitmap = SECT_SIZE | LPAGE_SIZE | SPAGE_SIZE, | 1183 | .pgsize_bitmap = SECT_SIZE | LPAGE_SIZE | SPAGE_SIZE, |
1022 | }; | 1184 | }; |
1023 | 1185 | ||
@@ -1025,11 +1187,41 @@ static int __init exynos_iommu_init(void) | |||
1025 | { | 1187 | { |
1026 | int ret; | 1188 | int ret; |
1027 | 1189 | ||
1190 | lv2table_kmem_cache = kmem_cache_create("exynos-iommu-lv2table", | ||
1191 | LV2TABLE_SIZE, LV2TABLE_SIZE, 0, NULL); | ||
1192 | if (!lv2table_kmem_cache) { | ||
1193 | pr_err("%s: Failed to create kmem cache\n", __func__); | ||
1194 | return -ENOMEM; | ||
1195 | } | ||
1196 | |||
1028 | ret = platform_driver_register(&exynos_sysmmu_driver); | 1197 | ret = platform_driver_register(&exynos_sysmmu_driver); |
1198 | if (ret) { | ||
1199 | pr_err("%s: Failed to register driver\n", __func__); | ||
1200 | goto err_reg_driver; | ||
1201 | } | ||
1029 | 1202 | ||
1030 | if (ret == 0) | 1203 | zero_lv2_table = kmem_cache_zalloc(lv2table_kmem_cache, GFP_KERNEL); |
1031 | bus_set_iommu(&platform_bus_type, &exynos_iommu_ops); | 1204 | if (zero_lv2_table == NULL) { |
1205 | pr_err("%s: Failed to allocate zero level2 page table\n", | ||
1206 | __func__); | ||
1207 | ret = -ENOMEM; | ||
1208 | goto err_zero_lv2; | ||
1209 | } | ||
1032 | 1210 | ||
1211 | ret = bus_set_iommu(&platform_bus_type, &exynos_iommu_ops); | ||
1212 | if (ret) { | ||
1213 | pr_err("%s: Failed to register exynos-iommu driver.\n", | ||
1214 | __func__); | ||
1215 | goto err_set_iommu; | ||
1216 | } | ||
1217 | |||
1218 | return 0; | ||
1219 | err_set_iommu: | ||
1220 | kmem_cache_free(lv2table_kmem_cache, zero_lv2_table); | ||
1221 | err_zero_lv2: | ||
1222 | platform_driver_unregister(&exynos_sysmmu_driver); | ||
1223 | err_reg_driver: | ||
1224 | kmem_cache_destroy(lv2table_kmem_cache); | ||
1033 | return ret; | 1225 | return ret; |
1034 | } | 1226 | } |
1035 | subsys_initcall(exynos_iommu_init); | 1227 | subsys_initcall(exynos_iommu_init); |
diff --git a/drivers/iommu/fsl_pamu.c b/drivers/iommu/fsl_pamu.c index cba0498eb011..bb446d742a2d 100644 --- a/drivers/iommu/fsl_pamu.c +++ b/drivers/iommu/fsl_pamu.c | |||
@@ -170,10 +170,10 @@ int pamu_disable_liodn(int liodn) | |||
170 | static unsigned int map_addrspace_size_to_wse(phys_addr_t addrspace_size) | 170 | static unsigned int map_addrspace_size_to_wse(phys_addr_t addrspace_size) |
171 | { | 171 | { |
172 | /* Bug if not a power of 2 */ | 172 | /* Bug if not a power of 2 */ |
173 | BUG_ON(!is_power_of_2(addrspace_size)); | 173 | BUG_ON((addrspace_size & (addrspace_size - 1))); |
174 | 174 | ||
175 | /* window size is 2^(WSE+1) bytes */ | 175 | /* window size is 2^(WSE+1) bytes */ |
176 | return __ffs(addrspace_size) - 1; | 176 | return fls64(addrspace_size) - 2; |
177 | } | 177 | } |
178 | 178 | ||
179 | /* Derive the PAACE window count encoding for the subwindow count */ | 179 | /* Derive the PAACE window count encoding for the subwindow count */ |
@@ -351,7 +351,7 @@ int pamu_config_ppaace(int liodn, phys_addr_t win_addr, phys_addr_t win_size, | |||
351 | struct paace *ppaace; | 351 | struct paace *ppaace; |
352 | unsigned long fspi; | 352 | unsigned long fspi; |
353 | 353 | ||
354 | if (!is_power_of_2(win_size) || win_size < PAMU_PAGE_SIZE) { | 354 | if ((win_size & (win_size - 1)) || win_size < PAMU_PAGE_SIZE) { |
355 | pr_debug("window size too small or not a power of two %llx\n", win_size); | 355 | pr_debug("window size too small or not a power of two %llx\n", win_size); |
356 | return -EINVAL; | 356 | return -EINVAL; |
357 | } | 357 | } |
@@ -464,7 +464,7 @@ int pamu_config_spaace(int liodn, u32 subwin_cnt, u32 subwin, | |||
464 | return -ENOENT; | 464 | return -ENOENT; |
465 | } | 465 | } |
466 | 466 | ||
467 | if (!is_power_of_2(subwin_size) || subwin_size < PAMU_PAGE_SIZE) { | 467 | if ((subwin_size & (subwin_size - 1)) || subwin_size < PAMU_PAGE_SIZE) { |
468 | pr_debug("subwindow size out of range, or not a power of 2\n"); | 468 | pr_debug("subwindow size out of range, or not a power of 2\n"); |
469 | return -EINVAL; | 469 | return -EINVAL; |
470 | } | 470 | } |
@@ -592,8 +592,7 @@ found_cpu_node: | |||
592 | /* advance to next node in cache hierarchy */ | 592 | /* advance to next node in cache hierarchy */ |
593 | node = of_find_node_by_phandle(*prop); | 593 | node = of_find_node_by_phandle(*prop); |
594 | if (!node) { | 594 | if (!node) { |
595 | pr_debug("Invalid node for cache hierarchy %s\n", | 595 | pr_debug("Invalid node for cache hierarchy\n"); |
596 | node->full_name); | ||
597 | return ~(u32)0; | 596 | return ~(u32)0; |
598 | } | 597 | } |
599 | } | 598 | } |
diff --git a/drivers/iommu/fsl_pamu_domain.c b/drivers/iommu/fsl_pamu_domain.c index 93072ba44b1d..af47648301a9 100644 --- a/drivers/iommu/fsl_pamu_domain.c +++ b/drivers/iommu/fsl_pamu_domain.c | |||
@@ -301,7 +301,7 @@ static int check_size(u64 size, dma_addr_t iova) | |||
301 | * Size must be a power of two and at least be equal | 301 | * Size must be a power of two and at least be equal |
302 | * to PAMU page size. | 302 | * to PAMU page size. |
303 | */ | 303 | */ |
304 | if (!is_power_of_2(size) || size < PAMU_PAGE_SIZE) { | 304 | if ((size & (size - 1)) || size < PAMU_PAGE_SIZE) { |
305 | pr_debug("%s: size too small or not a power of two\n", __func__); | 305 | pr_debug("%s: size too small or not a power of two\n", __func__); |
306 | return -EINVAL; | 306 | return -EINVAL; |
307 | } | 307 | } |
@@ -335,11 +335,6 @@ static struct fsl_dma_domain *iommu_alloc_dma_domain(void) | |||
335 | return domain; | 335 | return domain; |
336 | } | 336 | } |
337 | 337 | ||
338 | static inline struct device_domain_info *find_domain(struct device *dev) | ||
339 | { | ||
340 | return dev->archdata.iommu_domain; | ||
341 | } | ||
342 | |||
343 | static void remove_device_ref(struct device_domain_info *info, u32 win_cnt) | 338 | static void remove_device_ref(struct device_domain_info *info, u32 win_cnt) |
344 | { | 339 | { |
345 | unsigned long flags; | 340 | unsigned long flags; |
@@ -380,7 +375,7 @@ static void attach_device(struct fsl_dma_domain *dma_domain, int liodn, struct d | |||
380 | * Check here if the device is already attached to domain or not. | 375 | * Check here if the device is already attached to domain or not. |
381 | * If the device is already attached to a domain detach it. | 376 | * If the device is already attached to a domain detach it. |
382 | */ | 377 | */ |
383 | old_domain_info = find_domain(dev); | 378 | old_domain_info = dev->archdata.iommu_domain; |
384 | if (old_domain_info && old_domain_info->domain != dma_domain) { | 379 | if (old_domain_info && old_domain_info->domain != dma_domain) { |
385 | spin_unlock_irqrestore(&device_domain_lock, flags); | 380 | spin_unlock_irqrestore(&device_domain_lock, flags); |
386 | detach_device(dev, old_domain_info->domain); | 381 | detach_device(dev, old_domain_info->domain); |
@@ -399,7 +394,7 @@ static void attach_device(struct fsl_dma_domain *dma_domain, int liodn, struct d | |||
399 | * the info for the first LIODN as all | 394 | * the info for the first LIODN as all |
400 | * LIODNs share the same domain | 395 | * LIODNs share the same domain |
401 | */ | 396 | */ |
402 | if (!old_domain_info) | 397 | if (!dev->archdata.iommu_domain) |
403 | dev->archdata.iommu_domain = info; | 398 | dev->archdata.iommu_domain = info; |
404 | spin_unlock_irqrestore(&device_domain_lock, flags); | 399 | spin_unlock_irqrestore(&device_domain_lock, flags); |
405 | 400 | ||
@@ -1042,12 +1037,15 @@ root_bus: | |||
1042 | group = get_shared_pci_device_group(pdev); | 1037 | group = get_shared_pci_device_group(pdev); |
1043 | } | 1038 | } |
1044 | 1039 | ||
1040 | if (!group) | ||
1041 | group = ERR_PTR(-ENODEV); | ||
1042 | |||
1045 | return group; | 1043 | return group; |
1046 | } | 1044 | } |
1047 | 1045 | ||
1048 | static int fsl_pamu_add_device(struct device *dev) | 1046 | static int fsl_pamu_add_device(struct device *dev) |
1049 | { | 1047 | { |
1050 | struct iommu_group *group = NULL; | 1048 | struct iommu_group *group = ERR_PTR(-ENODEV); |
1051 | struct pci_dev *pdev; | 1049 | struct pci_dev *pdev; |
1052 | const u32 *prop; | 1050 | const u32 *prop; |
1053 | int ret, len; | 1051 | int ret, len; |
@@ -1070,7 +1068,7 @@ static int fsl_pamu_add_device(struct device *dev) | |||
1070 | group = get_device_iommu_group(dev); | 1068 | group = get_device_iommu_group(dev); |
1071 | } | 1069 | } |
1072 | 1070 | ||
1073 | if (!group || IS_ERR(group)) | 1071 | if (IS_ERR(group)) |
1074 | return PTR_ERR(group); | 1072 | return PTR_ERR(group); |
1075 | 1073 | ||
1076 | ret = iommu_group_add_device(group, dev); | 1074 | ret = iommu_group_add_device(group, dev); |
diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c index f256ffc02e29..51b6b77dc3e5 100644 --- a/drivers/iommu/intel-iommu.c +++ b/drivers/iommu/intel-iommu.c | |||
@@ -39,6 +39,7 @@ | |||
39 | #include <linux/dmi.h> | 39 | #include <linux/dmi.h> |
40 | #include <linux/pci-ats.h> | 40 | #include <linux/pci-ats.h> |
41 | #include <linux/memblock.h> | 41 | #include <linux/memblock.h> |
42 | #include <linux/dma-contiguous.h> | ||
42 | #include <asm/irq_remapping.h> | 43 | #include <asm/irq_remapping.h> |
43 | #include <asm/cacheflush.h> | 44 | #include <asm/cacheflush.h> |
44 | #include <asm/iommu.h> | 45 | #include <asm/iommu.h> |
@@ -3193,7 +3194,7 @@ static void *intel_alloc_coherent(struct device *dev, size_t size, | |||
3193 | dma_addr_t *dma_handle, gfp_t flags, | 3194 | dma_addr_t *dma_handle, gfp_t flags, |
3194 | struct dma_attrs *attrs) | 3195 | struct dma_attrs *attrs) |
3195 | { | 3196 | { |
3196 | void *vaddr; | 3197 | struct page *page = NULL; |
3197 | int order; | 3198 | int order; |
3198 | 3199 | ||
3199 | size = PAGE_ALIGN(size); | 3200 | size = PAGE_ALIGN(size); |
@@ -3208,17 +3209,31 @@ static void *intel_alloc_coherent(struct device *dev, size_t size, | |||
3208 | flags |= GFP_DMA32; | 3209 | flags |= GFP_DMA32; |
3209 | } | 3210 | } |
3210 | 3211 | ||
3211 | vaddr = (void *)__get_free_pages(flags, order); | 3212 | if (flags & __GFP_WAIT) { |
3212 | if (!vaddr) | 3213 | unsigned int count = size >> PAGE_SHIFT; |
3214 | |||
3215 | page = dma_alloc_from_contiguous(dev, count, order); | ||
3216 | if (page && iommu_no_mapping(dev) && | ||
3217 | page_to_phys(page) + size > dev->coherent_dma_mask) { | ||
3218 | dma_release_from_contiguous(dev, page, count); | ||
3219 | page = NULL; | ||
3220 | } | ||
3221 | } | ||
3222 | |||
3223 | if (!page) | ||
3224 | page = alloc_pages(flags, order); | ||
3225 | if (!page) | ||
3213 | return NULL; | 3226 | return NULL; |
3214 | memset(vaddr, 0, size); | 3227 | memset(page_address(page), 0, size); |
3215 | 3228 | ||
3216 | *dma_handle = __intel_map_single(dev, virt_to_bus(vaddr), size, | 3229 | *dma_handle = __intel_map_single(dev, page_to_phys(page), size, |
3217 | DMA_BIDIRECTIONAL, | 3230 | DMA_BIDIRECTIONAL, |
3218 | dev->coherent_dma_mask); | 3231 | dev->coherent_dma_mask); |
3219 | if (*dma_handle) | 3232 | if (*dma_handle) |
3220 | return vaddr; | 3233 | return page_address(page); |
3221 | free_pages((unsigned long)vaddr, order); | 3234 | if (!dma_release_from_contiguous(dev, page, size >> PAGE_SHIFT)) |
3235 | __free_pages(page, order); | ||
3236 | |||
3222 | return NULL; | 3237 | return NULL; |
3223 | } | 3238 | } |
3224 | 3239 | ||
@@ -3226,12 +3241,14 @@ static void intel_free_coherent(struct device *dev, size_t size, void *vaddr, | |||
3226 | dma_addr_t dma_handle, struct dma_attrs *attrs) | 3241 | dma_addr_t dma_handle, struct dma_attrs *attrs) |
3227 | { | 3242 | { |
3228 | int order; | 3243 | int order; |
3244 | struct page *page = virt_to_page(vaddr); | ||
3229 | 3245 | ||
3230 | size = PAGE_ALIGN(size); | 3246 | size = PAGE_ALIGN(size); |
3231 | order = get_order(size); | 3247 | order = get_order(size); |
3232 | 3248 | ||
3233 | intel_unmap_page(dev, dma_handle, size, DMA_BIDIRECTIONAL, NULL); | 3249 | intel_unmap_page(dev, dma_handle, size, DMA_BIDIRECTIONAL, NULL); |
3234 | free_pages((unsigned long)vaddr, order); | 3250 | if (!dma_release_from_contiguous(dev, page, size >> PAGE_SHIFT)) |
3251 | __free_pages(page, order); | ||
3235 | } | 3252 | } |
3236 | 3253 | ||
3237 | static void intel_unmap_sg(struct device *dev, struct scatterlist *sglist, | 3254 | static void intel_unmap_sg(struct device *dev, struct scatterlist *sglist, |
@@ -3799,14 +3816,11 @@ int dmar_iommu_notify_scope_dev(struct dmar_pci_notify_info *info) | |||
3799 | ((void *)rmrr) + rmrr->header.length, | 3816 | ((void *)rmrr) + rmrr->header.length, |
3800 | rmrr->segment, rmrru->devices, | 3817 | rmrr->segment, rmrru->devices, |
3801 | rmrru->devices_cnt); | 3818 | rmrru->devices_cnt); |
3802 | if (ret > 0) | 3819 | if(ret < 0) |
3803 | break; | ||
3804 | else if(ret < 0) | ||
3805 | return ret; | 3820 | return ret; |
3806 | } else if (info->event == BUS_NOTIFY_DEL_DEVICE) { | 3821 | } else if (info->event == BUS_NOTIFY_DEL_DEVICE) { |
3807 | if (dmar_remove_dev_scope(info, rmrr->segment, | 3822 | dmar_remove_dev_scope(info, rmrr->segment, |
3808 | rmrru->devices, rmrru->devices_cnt)) | 3823 | rmrru->devices, rmrru->devices_cnt); |
3809 | break; | ||
3810 | } | 3824 | } |
3811 | } | 3825 | } |
3812 | 3826 | ||
diff --git a/drivers/iommu/ipmmu-vmsa.c b/drivers/iommu/ipmmu-vmsa.c new file mode 100644 index 000000000000..53cde086e83b --- /dev/null +++ b/drivers/iommu/ipmmu-vmsa.c | |||
@@ -0,0 +1,1255 @@ | |||
1 | /* | ||
2 | * IPMMU VMSA | ||
3 | * | ||
4 | * Copyright (C) 2014 Renesas Electronics Corporation | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; version 2 of the License. | ||
9 | */ | ||
10 | |||
11 | #include <linux/delay.h> | ||
12 | #include <linux/dma-mapping.h> | ||
13 | #include <linux/err.h> | ||
14 | #include <linux/export.h> | ||
15 | #include <linux/interrupt.h> | ||
16 | #include <linux/io.h> | ||
17 | #include <linux/iommu.h> | ||
18 | #include <linux/module.h> | ||
19 | #include <linux/platform_data/ipmmu-vmsa.h> | ||
20 | #include <linux/platform_device.h> | ||
21 | #include <linux/sizes.h> | ||
22 | #include <linux/slab.h> | ||
23 | |||
24 | #include <asm/dma-iommu.h> | ||
25 | #include <asm/pgalloc.h> | ||
26 | |||
27 | struct ipmmu_vmsa_device { | ||
28 | struct device *dev; | ||
29 | void __iomem *base; | ||
30 | struct list_head list; | ||
31 | |||
32 | const struct ipmmu_vmsa_platform_data *pdata; | ||
33 | unsigned int num_utlbs; | ||
34 | |||
35 | struct dma_iommu_mapping *mapping; | ||
36 | }; | ||
37 | |||
38 | struct ipmmu_vmsa_domain { | ||
39 | struct ipmmu_vmsa_device *mmu; | ||
40 | struct iommu_domain *io_domain; | ||
41 | |||
42 | unsigned int context_id; | ||
43 | spinlock_t lock; /* Protects mappings */ | ||
44 | pgd_t *pgd; | ||
45 | }; | ||
46 | |||
47 | struct ipmmu_vmsa_archdata { | ||
48 | struct ipmmu_vmsa_device *mmu; | ||
49 | unsigned int utlb; | ||
50 | }; | ||
51 | |||
52 | static DEFINE_SPINLOCK(ipmmu_devices_lock); | ||
53 | static LIST_HEAD(ipmmu_devices); | ||
54 | |||
55 | #define TLB_LOOP_TIMEOUT 100 /* 100us */ | ||
56 | |||
57 | /* ----------------------------------------------------------------------------- | ||
58 | * Registers Definition | ||
59 | */ | ||
60 | |||
61 | #define IM_CTX_SIZE 0x40 | ||
62 | |||
63 | #define IMCTR 0x0000 | ||
64 | #define IMCTR_TRE (1 << 17) | ||
65 | #define IMCTR_AFE (1 << 16) | ||
66 | #define IMCTR_RTSEL_MASK (3 << 4) | ||
67 | #define IMCTR_RTSEL_SHIFT 4 | ||
68 | #define IMCTR_TREN (1 << 3) | ||
69 | #define IMCTR_INTEN (1 << 2) | ||
70 | #define IMCTR_FLUSH (1 << 1) | ||
71 | #define IMCTR_MMUEN (1 << 0) | ||
72 | |||
73 | #define IMCAAR 0x0004 | ||
74 | |||
75 | #define IMTTBCR 0x0008 | ||
76 | #define IMTTBCR_EAE (1 << 31) | ||
77 | #define IMTTBCR_PMB (1 << 30) | ||
78 | #define IMTTBCR_SH1_NON_SHAREABLE (0 << 28) | ||
79 | #define IMTTBCR_SH1_OUTER_SHAREABLE (2 << 28) | ||
80 | #define IMTTBCR_SH1_INNER_SHAREABLE (3 << 28) | ||
81 | #define IMTTBCR_SH1_MASK (3 << 28) | ||
82 | #define IMTTBCR_ORGN1_NC (0 << 26) | ||
83 | #define IMTTBCR_ORGN1_WB_WA (1 << 26) | ||
84 | #define IMTTBCR_ORGN1_WT (2 << 26) | ||
85 | #define IMTTBCR_ORGN1_WB (3 << 26) | ||
86 | #define IMTTBCR_ORGN1_MASK (3 << 26) | ||
87 | #define IMTTBCR_IRGN1_NC (0 << 24) | ||
88 | #define IMTTBCR_IRGN1_WB_WA (1 << 24) | ||
89 | #define IMTTBCR_IRGN1_WT (2 << 24) | ||
90 | #define IMTTBCR_IRGN1_WB (3 << 24) | ||
91 | #define IMTTBCR_IRGN1_MASK (3 << 24) | ||
92 | #define IMTTBCR_TSZ1_MASK (7 << 16) | ||
93 | #define IMTTBCR_TSZ1_SHIFT 16 | ||
94 | #define IMTTBCR_SH0_NON_SHAREABLE (0 << 12) | ||
95 | #define IMTTBCR_SH0_OUTER_SHAREABLE (2 << 12) | ||
96 | #define IMTTBCR_SH0_INNER_SHAREABLE (3 << 12) | ||
97 | #define IMTTBCR_SH0_MASK (3 << 12) | ||
98 | #define IMTTBCR_ORGN0_NC (0 << 10) | ||
99 | #define IMTTBCR_ORGN0_WB_WA (1 << 10) | ||
100 | #define IMTTBCR_ORGN0_WT (2 << 10) | ||
101 | #define IMTTBCR_ORGN0_WB (3 << 10) | ||
102 | #define IMTTBCR_ORGN0_MASK (3 << 10) | ||
103 | #define IMTTBCR_IRGN0_NC (0 << 8) | ||
104 | #define IMTTBCR_IRGN0_WB_WA (1 << 8) | ||
105 | #define IMTTBCR_IRGN0_WT (2 << 8) | ||
106 | #define IMTTBCR_IRGN0_WB (3 << 8) | ||
107 | #define IMTTBCR_IRGN0_MASK (3 << 8) | ||
108 | #define IMTTBCR_SL0_LVL_2 (0 << 4) | ||
109 | #define IMTTBCR_SL0_LVL_1 (1 << 4) | ||
110 | #define IMTTBCR_TSZ0_MASK (7 << 0) | ||
111 | #define IMTTBCR_TSZ0_SHIFT O | ||
112 | |||
113 | #define IMBUSCR 0x000c | ||
114 | #define IMBUSCR_DVM (1 << 2) | ||
115 | #define IMBUSCR_BUSSEL_SYS (0 << 0) | ||
116 | #define IMBUSCR_BUSSEL_CCI (1 << 0) | ||
117 | #define IMBUSCR_BUSSEL_IMCAAR (2 << 0) | ||
118 | #define IMBUSCR_BUSSEL_CCI_IMCAAR (3 << 0) | ||
119 | #define IMBUSCR_BUSSEL_MASK (3 << 0) | ||
120 | |||
121 | #define IMTTLBR0 0x0010 | ||
122 | #define IMTTUBR0 0x0014 | ||
123 | #define IMTTLBR1 0x0018 | ||
124 | #define IMTTUBR1 0x001c | ||
125 | |||
126 | #define IMSTR 0x0020 | ||
127 | #define IMSTR_ERRLVL_MASK (3 << 12) | ||
128 | #define IMSTR_ERRLVL_SHIFT 12 | ||
129 | #define IMSTR_ERRCODE_TLB_FORMAT (1 << 8) | ||
130 | #define IMSTR_ERRCODE_ACCESS_PERM (4 << 8) | ||
131 | #define IMSTR_ERRCODE_SECURE_ACCESS (5 << 8) | ||
132 | #define IMSTR_ERRCODE_MASK (7 << 8) | ||
133 | #define IMSTR_MHIT (1 << 4) | ||
134 | #define IMSTR_ABORT (1 << 2) | ||
135 | #define IMSTR_PF (1 << 1) | ||
136 | #define IMSTR_TF (1 << 0) | ||
137 | |||
138 | #define IMMAIR0 0x0028 | ||
139 | #define IMMAIR1 0x002c | ||
140 | #define IMMAIR_ATTR_MASK 0xff | ||
141 | #define IMMAIR_ATTR_DEVICE 0x04 | ||
142 | #define IMMAIR_ATTR_NC 0x44 | ||
143 | #define IMMAIR_ATTR_WBRWA 0xff | ||
144 | #define IMMAIR_ATTR_SHIFT(n) ((n) << 3) | ||
145 | #define IMMAIR_ATTR_IDX_NC 0 | ||
146 | #define IMMAIR_ATTR_IDX_WBRWA 1 | ||
147 | #define IMMAIR_ATTR_IDX_DEV 2 | ||
148 | |||
149 | #define IMEAR 0x0030 | ||
150 | |||
151 | #define IMPCTR 0x0200 | ||
152 | #define IMPSTR 0x0208 | ||
153 | #define IMPEAR 0x020c | ||
154 | #define IMPMBA(n) (0x0280 + ((n) * 4)) | ||
155 | #define IMPMBD(n) (0x02c0 + ((n) * 4)) | ||
156 | |||
157 | #define IMUCTR(n) (0x0300 + ((n) * 16)) | ||
158 | #define IMUCTR_FIXADDEN (1 << 31) | ||
159 | #define IMUCTR_FIXADD_MASK (0xff << 16) | ||
160 | #define IMUCTR_FIXADD_SHIFT 16 | ||
161 | #define IMUCTR_TTSEL_MMU(n) ((n) << 4) | ||
162 | #define IMUCTR_TTSEL_PMB (8 << 4) | ||
163 | #define IMUCTR_TTSEL_MASK (15 << 4) | ||
164 | #define IMUCTR_FLUSH (1 << 1) | ||
165 | #define IMUCTR_MMUEN (1 << 0) | ||
166 | |||
167 | #define IMUASID(n) (0x0308 + ((n) * 16)) | ||
168 | #define IMUASID_ASID8_MASK (0xff << 8) | ||
169 | #define IMUASID_ASID8_SHIFT 8 | ||
170 | #define IMUASID_ASID0_MASK (0xff << 0) | ||
171 | #define IMUASID_ASID0_SHIFT 0 | ||
172 | |||
173 | /* ----------------------------------------------------------------------------- | ||
174 | * Page Table Bits | ||
175 | */ | ||
176 | |||
177 | /* | ||
178 | * VMSA states in section B3.6.3 "Control of Secure or Non-secure memory access, | ||
179 | * Long-descriptor format" that the NStable bit being set in a table descriptor | ||
180 | * will result in the NStable and NS bits of all child entries being ignored and | ||
181 | * considered as being set. The IPMMU seems not to comply with this, as it | ||
182 | * generates a secure access page fault if any of the NStable and NS bits isn't | ||
183 | * set when running in non-secure mode. | ||
184 | */ | ||
185 | #ifndef PMD_NSTABLE | ||
186 | #define PMD_NSTABLE (_AT(pmdval_t, 1) << 63) | ||
187 | #endif | ||
188 | |||
189 | #define ARM_VMSA_PTE_XN (((pteval_t)3) << 53) | ||
190 | #define ARM_VMSA_PTE_CONT (((pteval_t)1) << 52) | ||
191 | #define ARM_VMSA_PTE_AF (((pteval_t)1) << 10) | ||
192 | #define ARM_VMSA_PTE_SH_NS (((pteval_t)0) << 8) | ||
193 | #define ARM_VMSA_PTE_SH_OS (((pteval_t)2) << 8) | ||
194 | #define ARM_VMSA_PTE_SH_IS (((pteval_t)3) << 8) | ||
195 | #define ARM_VMSA_PTE_SH_MASK (((pteval_t)3) << 8) | ||
196 | #define ARM_VMSA_PTE_NS (((pteval_t)1) << 5) | ||
197 | #define ARM_VMSA_PTE_PAGE (((pteval_t)3) << 0) | ||
198 | |||
199 | /* Stage-1 PTE */ | ||
200 | #define ARM_VMSA_PTE_nG (((pteval_t)1) << 11) | ||
201 | #define ARM_VMSA_PTE_AP_UNPRIV (((pteval_t)1) << 6) | ||
202 | #define ARM_VMSA_PTE_AP_RDONLY (((pteval_t)2) << 6) | ||
203 | #define ARM_VMSA_PTE_AP_MASK (((pteval_t)3) << 6) | ||
204 | #define ARM_VMSA_PTE_ATTRINDX_MASK (((pteval_t)3) << 2) | ||
205 | #define ARM_VMSA_PTE_ATTRINDX_SHIFT 2 | ||
206 | |||
207 | #define ARM_VMSA_PTE_ATTRS_MASK \ | ||
208 | (ARM_VMSA_PTE_XN | ARM_VMSA_PTE_CONT | ARM_VMSA_PTE_nG | \ | ||
209 | ARM_VMSA_PTE_AF | ARM_VMSA_PTE_SH_MASK | ARM_VMSA_PTE_AP_MASK | \ | ||
210 | ARM_VMSA_PTE_NS | ARM_VMSA_PTE_ATTRINDX_MASK) | ||
211 | |||
212 | #define ARM_VMSA_PTE_CONT_ENTRIES 16 | ||
213 | #define ARM_VMSA_PTE_CONT_SIZE (PAGE_SIZE * ARM_VMSA_PTE_CONT_ENTRIES) | ||
214 | |||
215 | #define IPMMU_PTRS_PER_PTE 512 | ||
216 | #define IPMMU_PTRS_PER_PMD 512 | ||
217 | #define IPMMU_PTRS_PER_PGD 4 | ||
218 | |||
219 | /* ----------------------------------------------------------------------------- | ||
220 | * Read/Write Access | ||
221 | */ | ||
222 | |||
223 | static u32 ipmmu_read(struct ipmmu_vmsa_device *mmu, unsigned int offset) | ||
224 | { | ||
225 | return ioread32(mmu->base + offset); | ||
226 | } | ||
227 | |||
228 | static void ipmmu_write(struct ipmmu_vmsa_device *mmu, unsigned int offset, | ||
229 | u32 data) | ||
230 | { | ||
231 | iowrite32(data, mmu->base + offset); | ||
232 | } | ||
233 | |||
234 | static u32 ipmmu_ctx_read(struct ipmmu_vmsa_domain *domain, unsigned int reg) | ||
235 | { | ||
236 | return ipmmu_read(domain->mmu, domain->context_id * IM_CTX_SIZE + reg); | ||
237 | } | ||
238 | |||
239 | static void ipmmu_ctx_write(struct ipmmu_vmsa_domain *domain, unsigned int reg, | ||
240 | u32 data) | ||
241 | { | ||
242 | ipmmu_write(domain->mmu, domain->context_id * IM_CTX_SIZE + reg, data); | ||
243 | } | ||
244 | |||
245 | /* ----------------------------------------------------------------------------- | ||
246 | * TLB and microTLB Management | ||
247 | */ | ||
248 | |||
249 | /* Wait for any pending TLB invalidations to complete */ | ||
250 | static void ipmmu_tlb_sync(struct ipmmu_vmsa_domain *domain) | ||
251 | { | ||
252 | unsigned int count = 0; | ||
253 | |||
254 | while (ipmmu_ctx_read(domain, IMCTR) & IMCTR_FLUSH) { | ||
255 | cpu_relax(); | ||
256 | if (++count == TLB_LOOP_TIMEOUT) { | ||
257 | dev_err_ratelimited(domain->mmu->dev, | ||
258 | "TLB sync timed out -- MMU may be deadlocked\n"); | ||
259 | return; | ||
260 | } | ||
261 | udelay(1); | ||
262 | } | ||
263 | } | ||
264 | |||
265 | static void ipmmu_tlb_invalidate(struct ipmmu_vmsa_domain *domain) | ||
266 | { | ||
267 | u32 reg; | ||
268 | |||
269 | reg = ipmmu_ctx_read(domain, IMCTR); | ||
270 | reg |= IMCTR_FLUSH; | ||
271 | ipmmu_ctx_write(domain, IMCTR, reg); | ||
272 | |||
273 | ipmmu_tlb_sync(domain); | ||
274 | } | ||
275 | |||
276 | /* | ||
277 | * Enable MMU translation for the microTLB. | ||
278 | */ | ||
279 | static void ipmmu_utlb_enable(struct ipmmu_vmsa_domain *domain, | ||
280 | unsigned int utlb) | ||
281 | { | ||
282 | struct ipmmu_vmsa_device *mmu = domain->mmu; | ||
283 | |||
284 | /* | ||
285 | * TODO: Reference-count the microTLB as several bus masters can be | ||
286 | * connected to the same microTLB. | ||
287 | */ | ||
288 | |||
289 | /* TODO: What should we set the ASID to ? */ | ||
290 | ipmmu_write(mmu, IMUASID(utlb), 0); | ||
291 | /* TODO: Do we need to flush the microTLB ? */ | ||
292 | ipmmu_write(mmu, IMUCTR(utlb), | ||
293 | IMUCTR_TTSEL_MMU(domain->context_id) | IMUCTR_FLUSH | | ||
294 | IMUCTR_MMUEN); | ||
295 | } | ||
296 | |||
297 | /* | ||
298 | * Disable MMU translation for the microTLB. | ||
299 | */ | ||
300 | static void ipmmu_utlb_disable(struct ipmmu_vmsa_domain *domain, | ||
301 | unsigned int utlb) | ||
302 | { | ||
303 | struct ipmmu_vmsa_device *mmu = domain->mmu; | ||
304 | |||
305 | ipmmu_write(mmu, IMUCTR(utlb), 0); | ||
306 | } | ||
307 | |||
308 | static void ipmmu_flush_pgtable(struct ipmmu_vmsa_device *mmu, void *addr, | ||
309 | size_t size) | ||
310 | { | ||
311 | unsigned long offset = (unsigned long)addr & ~PAGE_MASK; | ||
312 | |||
313 | /* | ||
314 | * TODO: Add support for coherent walk through CCI with DVM and remove | ||
315 | * cache handling. | ||
316 | */ | ||
317 | dma_map_page(mmu->dev, virt_to_page(addr), offset, size, DMA_TO_DEVICE); | ||
318 | } | ||
319 | |||
320 | /* ----------------------------------------------------------------------------- | ||
321 | * Domain/Context Management | ||
322 | */ | ||
323 | |||
324 | static int ipmmu_domain_init_context(struct ipmmu_vmsa_domain *domain) | ||
325 | { | ||
326 | phys_addr_t ttbr; | ||
327 | u32 reg; | ||
328 | |||
329 | /* | ||
330 | * TODO: When adding support for multiple contexts, find an unused | ||
331 | * context. | ||
332 | */ | ||
333 | domain->context_id = 0; | ||
334 | |||
335 | /* TTBR0 */ | ||
336 | ipmmu_flush_pgtable(domain->mmu, domain->pgd, | ||
337 | IPMMU_PTRS_PER_PGD * sizeof(*domain->pgd)); | ||
338 | ttbr = __pa(domain->pgd); | ||
339 | ipmmu_ctx_write(domain, IMTTLBR0, ttbr); | ||
340 | ipmmu_ctx_write(domain, IMTTUBR0, ttbr >> 32); | ||
341 | |||
342 | /* | ||
343 | * TTBCR | ||
344 | * We use long descriptors with inner-shareable WBWA tables and allocate | ||
345 | * the whole 32-bit VA space to TTBR0. | ||
346 | */ | ||
347 | ipmmu_ctx_write(domain, IMTTBCR, IMTTBCR_EAE | | ||
348 | IMTTBCR_SH0_INNER_SHAREABLE | IMTTBCR_ORGN0_WB_WA | | ||
349 | IMTTBCR_IRGN0_WB_WA | IMTTBCR_SL0_LVL_1); | ||
350 | |||
351 | /* | ||
352 | * MAIR0 | ||
353 | * We need three attributes only, non-cacheable, write-back read/write | ||
354 | * allocate and device memory. | ||
355 | */ | ||
356 | reg = (IMMAIR_ATTR_NC << IMMAIR_ATTR_SHIFT(IMMAIR_ATTR_IDX_NC)) | ||
357 | | (IMMAIR_ATTR_WBRWA << IMMAIR_ATTR_SHIFT(IMMAIR_ATTR_IDX_WBRWA)) | ||
358 | | (IMMAIR_ATTR_DEVICE << IMMAIR_ATTR_SHIFT(IMMAIR_ATTR_IDX_DEV)); | ||
359 | ipmmu_ctx_write(domain, IMMAIR0, reg); | ||
360 | |||
361 | /* IMBUSCR */ | ||
362 | ipmmu_ctx_write(domain, IMBUSCR, | ||
363 | ipmmu_ctx_read(domain, IMBUSCR) & | ||
364 | ~(IMBUSCR_DVM | IMBUSCR_BUSSEL_MASK)); | ||
365 | |||
366 | /* | ||
367 | * IMSTR | ||
368 | * Clear all interrupt flags. | ||
369 | */ | ||
370 | ipmmu_ctx_write(domain, IMSTR, ipmmu_ctx_read(domain, IMSTR)); | ||
371 | |||
372 | /* | ||
373 | * IMCTR | ||
374 | * Enable the MMU and interrupt generation. The long-descriptor | ||
375 | * translation table format doesn't use TEX remapping. Don't enable AF | ||
376 | * software management as we have no use for it. Flush the TLB as | ||
377 | * required when modifying the context registers. | ||
378 | */ | ||
379 | ipmmu_ctx_write(domain, IMCTR, IMCTR_INTEN | IMCTR_FLUSH | IMCTR_MMUEN); | ||
380 | |||
381 | return 0; | ||
382 | } | ||
383 | |||
384 | static void ipmmu_domain_destroy_context(struct ipmmu_vmsa_domain *domain) | ||
385 | { | ||
386 | /* | ||
387 | * Disable the context. Flush the TLB as required when modifying the | ||
388 | * context registers. | ||
389 | * | ||
390 | * TODO: Is TLB flush really needed ? | ||
391 | */ | ||
392 | ipmmu_ctx_write(domain, IMCTR, IMCTR_FLUSH); | ||
393 | ipmmu_tlb_sync(domain); | ||
394 | } | ||
395 | |||
396 | /* ----------------------------------------------------------------------------- | ||
397 | * Fault Handling | ||
398 | */ | ||
399 | |||
400 | static irqreturn_t ipmmu_domain_irq(struct ipmmu_vmsa_domain *domain) | ||
401 | { | ||
402 | const u32 err_mask = IMSTR_MHIT | IMSTR_ABORT | IMSTR_PF | IMSTR_TF; | ||
403 | struct ipmmu_vmsa_device *mmu = domain->mmu; | ||
404 | u32 status; | ||
405 | u32 iova; | ||
406 | |||
407 | status = ipmmu_ctx_read(domain, IMSTR); | ||
408 | if (!(status & err_mask)) | ||
409 | return IRQ_NONE; | ||
410 | |||
411 | iova = ipmmu_ctx_read(domain, IMEAR); | ||
412 | |||
413 | /* | ||
414 | * Clear the error status flags. Unlike traditional interrupt flag | ||
415 | * registers that must be cleared by writing 1, this status register | ||
416 | * seems to require 0. The error address register must be read before, | ||
417 | * otherwise its value will be 0. | ||
418 | */ | ||
419 | ipmmu_ctx_write(domain, IMSTR, 0); | ||
420 | |||
421 | /* Log fatal errors. */ | ||
422 | if (status & IMSTR_MHIT) | ||
423 | dev_err_ratelimited(mmu->dev, "Multiple TLB hits @0x%08x\n", | ||
424 | iova); | ||
425 | if (status & IMSTR_ABORT) | ||
426 | dev_err_ratelimited(mmu->dev, "Page Table Walk Abort @0x%08x\n", | ||
427 | iova); | ||
428 | |||
429 | if (!(status & (IMSTR_PF | IMSTR_TF))) | ||
430 | return IRQ_NONE; | ||
431 | |||
432 | /* | ||
433 | * Try to handle page faults and translation faults. | ||
434 | * | ||
435 | * TODO: We need to look up the faulty device based on the I/O VA. Use | ||
436 | * the IOMMU device for now. | ||
437 | */ | ||
438 | if (!report_iommu_fault(domain->io_domain, mmu->dev, iova, 0)) | ||
439 | return IRQ_HANDLED; | ||
440 | |||
441 | dev_err_ratelimited(mmu->dev, | ||
442 | "Unhandled fault: status 0x%08x iova 0x%08x\n", | ||
443 | status, iova); | ||
444 | |||
445 | return IRQ_HANDLED; | ||
446 | } | ||
447 | |||
448 | static irqreturn_t ipmmu_irq(int irq, void *dev) | ||
449 | { | ||
450 | struct ipmmu_vmsa_device *mmu = dev; | ||
451 | struct iommu_domain *io_domain; | ||
452 | struct ipmmu_vmsa_domain *domain; | ||
453 | |||
454 | if (!mmu->mapping) | ||
455 | return IRQ_NONE; | ||
456 | |||
457 | io_domain = mmu->mapping->domain; | ||
458 | domain = io_domain->priv; | ||
459 | |||
460 | return ipmmu_domain_irq(domain); | ||
461 | } | ||
462 | |||
463 | /* ----------------------------------------------------------------------------- | ||
464 | * Page Table Management | ||
465 | */ | ||
466 | |||
467 | #define pud_pgtable(pud) pfn_to_page(__phys_to_pfn(pud_val(pud) & PHYS_MASK)) | ||
468 | |||
469 | static void ipmmu_free_ptes(pmd_t *pmd) | ||
470 | { | ||
471 | pgtable_t table = pmd_pgtable(*pmd); | ||
472 | __free_page(table); | ||
473 | } | ||
474 | |||
475 | static void ipmmu_free_pmds(pud_t *pud) | ||
476 | { | ||
477 | pmd_t *pmd = pmd_offset(pud, 0); | ||
478 | pgtable_t table; | ||
479 | unsigned int i; | ||
480 | |||
481 | for (i = 0; i < IPMMU_PTRS_PER_PMD; ++i) { | ||
482 | if (!pmd_table(*pmd)) | ||
483 | continue; | ||
484 | |||
485 | ipmmu_free_ptes(pmd); | ||
486 | pmd++; | ||
487 | } | ||
488 | |||
489 | table = pud_pgtable(*pud); | ||
490 | __free_page(table); | ||
491 | } | ||
492 | |||
493 | static void ipmmu_free_pgtables(struct ipmmu_vmsa_domain *domain) | ||
494 | { | ||
495 | pgd_t *pgd, *pgd_base = domain->pgd; | ||
496 | unsigned int i; | ||
497 | |||
498 | /* | ||
499 | * Recursively free the page tables for this domain. We don't care about | ||
500 | * speculative TLB filling, because the TLB will be nuked next time this | ||
501 | * context bank is re-allocated and no devices currently map to these | ||
502 | * tables. | ||
503 | */ | ||
504 | pgd = pgd_base; | ||
505 | for (i = 0; i < IPMMU_PTRS_PER_PGD; ++i) { | ||
506 | if (pgd_none(*pgd)) | ||
507 | continue; | ||
508 | ipmmu_free_pmds((pud_t *)pgd); | ||
509 | pgd++; | ||
510 | } | ||
511 | |||
512 | kfree(pgd_base); | ||
513 | } | ||
514 | |||
515 | /* | ||
516 | * We can't use the (pgd|pud|pmd|pte)_populate or the set_(pgd|pud|pmd|pte) | ||
517 | * functions as they would flush the CPU TLB. | ||
518 | */ | ||
519 | |||
520 | static pte_t *ipmmu_alloc_pte(struct ipmmu_vmsa_device *mmu, pmd_t *pmd, | ||
521 | unsigned long iova) | ||
522 | { | ||
523 | pte_t *pte; | ||
524 | |||
525 | if (!pmd_none(*pmd)) | ||
526 | return pte_offset_kernel(pmd, iova); | ||
527 | |||
528 | pte = (pte_t *)get_zeroed_page(GFP_ATOMIC); | ||
529 | if (!pte) | ||
530 | return NULL; | ||
531 | |||
532 | ipmmu_flush_pgtable(mmu, pte, PAGE_SIZE); | ||
533 | *pmd = __pmd(__pa(pte) | PMD_NSTABLE | PMD_TYPE_TABLE); | ||
534 | ipmmu_flush_pgtable(mmu, pmd, sizeof(*pmd)); | ||
535 | |||
536 | return pte + pte_index(iova); | ||
537 | } | ||
538 | |||
539 | static pmd_t *ipmmu_alloc_pmd(struct ipmmu_vmsa_device *mmu, pgd_t *pgd, | ||
540 | unsigned long iova) | ||
541 | { | ||
542 | pud_t *pud = (pud_t *)pgd; | ||
543 | pmd_t *pmd; | ||
544 | |||
545 | if (!pud_none(*pud)) | ||
546 | return pmd_offset(pud, iova); | ||
547 | |||
548 | pmd = (pmd_t *)get_zeroed_page(GFP_ATOMIC); | ||
549 | if (!pmd) | ||
550 | return NULL; | ||
551 | |||
552 | ipmmu_flush_pgtable(mmu, pmd, PAGE_SIZE); | ||
553 | *pud = __pud(__pa(pmd) | PMD_NSTABLE | PMD_TYPE_TABLE); | ||
554 | ipmmu_flush_pgtable(mmu, pud, sizeof(*pud)); | ||
555 | |||
556 | return pmd + pmd_index(iova); | ||
557 | } | ||
558 | |||
559 | static u64 ipmmu_page_prot(unsigned int prot, u64 type) | ||
560 | { | ||
561 | u64 pgprot = ARM_VMSA_PTE_XN | ARM_VMSA_PTE_nG | ARM_VMSA_PTE_AF | ||
562 | | ARM_VMSA_PTE_SH_IS | ARM_VMSA_PTE_AP_UNPRIV | ||
563 | | ARM_VMSA_PTE_NS | type; | ||
564 | |||
565 | if (!(prot & IOMMU_WRITE) && (prot & IOMMU_READ)) | ||
566 | pgprot |= ARM_VMSA_PTE_AP_RDONLY; | ||
567 | |||
568 | if (prot & IOMMU_CACHE) | ||
569 | pgprot |= IMMAIR_ATTR_IDX_WBRWA << ARM_VMSA_PTE_ATTRINDX_SHIFT; | ||
570 | |||
571 | if (prot & IOMMU_EXEC) | ||
572 | pgprot &= ~ARM_VMSA_PTE_XN; | ||
573 | else if (!(prot & (IOMMU_READ | IOMMU_WRITE))) | ||
574 | /* If no access create a faulting entry to avoid TLB fills. */ | ||
575 | pgprot &= ~ARM_VMSA_PTE_PAGE; | ||
576 | |||
577 | return pgprot; | ||
578 | } | ||
579 | |||
580 | static int ipmmu_alloc_init_pte(struct ipmmu_vmsa_device *mmu, pmd_t *pmd, | ||
581 | unsigned long iova, unsigned long pfn, | ||
582 | size_t size, int prot) | ||
583 | { | ||
584 | pteval_t pteval = ipmmu_page_prot(prot, ARM_VMSA_PTE_PAGE); | ||
585 | unsigned int num_ptes = 1; | ||
586 | pte_t *pte, *start; | ||
587 | unsigned int i; | ||
588 | |||
589 | pte = ipmmu_alloc_pte(mmu, pmd, iova); | ||
590 | if (!pte) | ||
591 | return -ENOMEM; | ||
592 | |||
593 | start = pte; | ||
594 | |||
595 | /* | ||
596 | * Install the page table entries. We can be called both for a single | ||
597 | * page or for a block of 16 physically contiguous pages. In the latter | ||
598 | * case set the PTE contiguous hint. | ||
599 | */ | ||
600 | if (size == SZ_64K) { | ||
601 | pteval |= ARM_VMSA_PTE_CONT; | ||
602 | num_ptes = ARM_VMSA_PTE_CONT_ENTRIES; | ||
603 | } | ||
604 | |||
605 | for (i = num_ptes; i; --i) | ||
606 | *pte++ = pfn_pte(pfn++, __pgprot(pteval)); | ||
607 | |||
608 | ipmmu_flush_pgtable(mmu, start, sizeof(*pte) * num_ptes); | ||
609 | |||
610 | return 0; | ||
611 | } | ||
612 | |||
613 | static int ipmmu_alloc_init_pmd(struct ipmmu_vmsa_device *mmu, pmd_t *pmd, | ||
614 | unsigned long iova, unsigned long pfn, | ||
615 | int prot) | ||
616 | { | ||
617 | pmdval_t pmdval = ipmmu_page_prot(prot, PMD_TYPE_SECT); | ||
618 | |||
619 | *pmd = pfn_pmd(pfn, __pgprot(pmdval)); | ||
620 | ipmmu_flush_pgtable(mmu, pmd, sizeof(*pmd)); | ||
621 | |||
622 | return 0; | ||
623 | } | ||
624 | |||
625 | static int ipmmu_create_mapping(struct ipmmu_vmsa_domain *domain, | ||
626 | unsigned long iova, phys_addr_t paddr, | ||
627 | size_t size, int prot) | ||
628 | { | ||
629 | struct ipmmu_vmsa_device *mmu = domain->mmu; | ||
630 | pgd_t *pgd = domain->pgd; | ||
631 | unsigned long flags; | ||
632 | unsigned long pfn; | ||
633 | pmd_t *pmd; | ||
634 | int ret; | ||
635 | |||
636 | if (!pgd) | ||
637 | return -EINVAL; | ||
638 | |||
639 | if (size & ~PAGE_MASK) | ||
640 | return -EINVAL; | ||
641 | |||
642 | if (paddr & ~((1ULL << 40) - 1)) | ||
643 | return -ERANGE; | ||
644 | |||
645 | pfn = __phys_to_pfn(paddr); | ||
646 | pgd += pgd_index(iova); | ||
647 | |||
648 | /* Update the page tables. */ | ||
649 | spin_lock_irqsave(&domain->lock, flags); | ||
650 | |||
651 | pmd = ipmmu_alloc_pmd(mmu, pgd, iova); | ||
652 | if (!pmd) { | ||
653 | ret = -ENOMEM; | ||
654 | goto done; | ||
655 | } | ||
656 | |||
657 | switch (size) { | ||
658 | case SZ_2M: | ||
659 | ret = ipmmu_alloc_init_pmd(mmu, pmd, iova, pfn, prot); | ||
660 | break; | ||
661 | case SZ_64K: | ||
662 | case SZ_4K: | ||
663 | ret = ipmmu_alloc_init_pte(mmu, pmd, iova, pfn, size, prot); | ||
664 | break; | ||
665 | default: | ||
666 | ret = -EINVAL; | ||
667 | break; | ||
668 | } | ||
669 | |||
670 | done: | ||
671 | spin_unlock_irqrestore(&domain->lock, flags); | ||
672 | |||
673 | if (!ret) | ||
674 | ipmmu_tlb_invalidate(domain); | ||
675 | |||
676 | return ret; | ||
677 | } | ||
678 | |||
679 | static void ipmmu_clear_pud(struct ipmmu_vmsa_device *mmu, pud_t *pud) | ||
680 | { | ||
681 | /* Free the page table. */ | ||
682 | pgtable_t table = pud_pgtable(*pud); | ||
683 | __free_page(table); | ||
684 | |||
685 | /* Clear the PUD. */ | ||
686 | *pud = __pud(0); | ||
687 | ipmmu_flush_pgtable(mmu, pud, sizeof(*pud)); | ||
688 | } | ||
689 | |||
690 | static void ipmmu_clear_pmd(struct ipmmu_vmsa_device *mmu, pud_t *pud, | ||
691 | pmd_t *pmd) | ||
692 | { | ||
693 | unsigned int i; | ||
694 | |||
695 | /* Free the page table. */ | ||
696 | if (pmd_table(*pmd)) { | ||
697 | pgtable_t table = pmd_pgtable(*pmd); | ||
698 | __free_page(table); | ||
699 | } | ||
700 | |||
701 | /* Clear the PMD. */ | ||
702 | *pmd = __pmd(0); | ||
703 | ipmmu_flush_pgtable(mmu, pmd, sizeof(*pmd)); | ||
704 | |||
705 | /* Check whether the PUD is still needed. */ | ||
706 | pmd = pmd_offset(pud, 0); | ||
707 | for (i = 0; i < IPMMU_PTRS_PER_PMD; ++i) { | ||
708 | if (!pmd_none(pmd[i])) | ||
709 | return; | ||
710 | } | ||
711 | |||
712 | /* Clear the parent PUD. */ | ||
713 | ipmmu_clear_pud(mmu, pud); | ||
714 | } | ||
715 | |||
716 | static void ipmmu_clear_pte(struct ipmmu_vmsa_device *mmu, pud_t *pud, | ||
717 | pmd_t *pmd, pte_t *pte, unsigned int num_ptes) | ||
718 | { | ||
719 | unsigned int i; | ||
720 | |||
721 | /* Clear the PTE. */ | ||
722 | for (i = num_ptes; i; --i) | ||
723 | pte[i-1] = __pte(0); | ||
724 | |||
725 | ipmmu_flush_pgtable(mmu, pte, sizeof(*pte) * num_ptes); | ||
726 | |||
727 | /* Check whether the PMD is still needed. */ | ||
728 | pte = pte_offset_kernel(pmd, 0); | ||
729 | for (i = 0; i < IPMMU_PTRS_PER_PTE; ++i) { | ||
730 | if (!pte_none(pte[i])) | ||
731 | return; | ||
732 | } | ||
733 | |||
734 | /* Clear the parent PMD. */ | ||
735 | ipmmu_clear_pmd(mmu, pud, pmd); | ||
736 | } | ||
737 | |||
738 | static int ipmmu_split_pmd(struct ipmmu_vmsa_device *mmu, pmd_t *pmd) | ||
739 | { | ||
740 | pte_t *pte, *start; | ||
741 | pteval_t pteval; | ||
742 | unsigned long pfn; | ||
743 | unsigned int i; | ||
744 | |||
745 | pte = (pte_t *)get_zeroed_page(GFP_ATOMIC); | ||
746 | if (!pte) | ||
747 | return -ENOMEM; | ||
748 | |||
749 | /* Copy the PMD attributes. */ | ||
750 | pteval = (pmd_val(*pmd) & ARM_VMSA_PTE_ATTRS_MASK) | ||
751 | | ARM_VMSA_PTE_CONT | ARM_VMSA_PTE_PAGE; | ||
752 | |||
753 | pfn = pmd_pfn(*pmd); | ||
754 | start = pte; | ||
755 | |||
756 | for (i = IPMMU_PTRS_PER_PTE; i; --i) | ||
757 | *pte++ = pfn_pte(pfn++, __pgprot(pteval)); | ||
758 | |||
759 | ipmmu_flush_pgtable(mmu, start, PAGE_SIZE); | ||
760 | *pmd = __pmd(__pa(start) | PMD_NSTABLE | PMD_TYPE_TABLE); | ||
761 | ipmmu_flush_pgtable(mmu, pmd, sizeof(*pmd)); | ||
762 | |||
763 | return 0; | ||
764 | } | ||
765 | |||
766 | static void ipmmu_split_pte(struct ipmmu_vmsa_device *mmu, pte_t *pte) | ||
767 | { | ||
768 | unsigned int i; | ||
769 | |||
770 | for (i = ARM_VMSA_PTE_CONT_ENTRIES; i; --i) | ||
771 | pte[i-1] = __pte(pte_val(*pte) & ~ARM_VMSA_PTE_CONT); | ||
772 | |||
773 | ipmmu_flush_pgtable(mmu, pte, sizeof(*pte) * ARM_VMSA_PTE_CONT_ENTRIES); | ||
774 | } | ||
775 | |||
776 | static int ipmmu_clear_mapping(struct ipmmu_vmsa_domain *domain, | ||
777 | unsigned long iova, size_t size) | ||
778 | { | ||
779 | struct ipmmu_vmsa_device *mmu = domain->mmu; | ||
780 | unsigned long flags; | ||
781 | pgd_t *pgd = domain->pgd; | ||
782 | pud_t *pud; | ||
783 | pmd_t *pmd; | ||
784 | pte_t *pte; | ||
785 | int ret = 0; | ||
786 | |||
787 | if (!pgd) | ||
788 | return -EINVAL; | ||
789 | |||
790 | if (size & ~PAGE_MASK) | ||
791 | return -EINVAL; | ||
792 | |||
793 | pgd += pgd_index(iova); | ||
794 | pud = (pud_t *)pgd; | ||
795 | |||
796 | spin_lock_irqsave(&domain->lock, flags); | ||
797 | |||
798 | /* If there's no PUD or PMD we're done. */ | ||
799 | if (pud_none(*pud)) | ||
800 | goto done; | ||
801 | |||
802 | pmd = pmd_offset(pud, iova); | ||
803 | if (pmd_none(*pmd)) | ||
804 | goto done; | ||
805 | |||
806 | /* | ||
807 | * When freeing a 2MB block just clear the PMD. In the unlikely case the | ||
808 | * block is mapped as individual pages this will free the corresponding | ||
809 | * PTE page table. | ||
810 | */ | ||
811 | if (size == SZ_2M) { | ||
812 | ipmmu_clear_pmd(mmu, pud, pmd); | ||
813 | goto done; | ||
814 | } | ||
815 | |||
816 | /* | ||
817 | * If the PMD has been mapped as a section remap it as pages to allow | ||
818 | * freeing individual pages. | ||
819 | */ | ||
820 | if (pmd_sect(*pmd)) | ||
821 | ipmmu_split_pmd(mmu, pmd); | ||
822 | |||
823 | pte = pte_offset_kernel(pmd, iova); | ||
824 | |||
825 | /* | ||
826 | * When freeing a 64kB block just clear the PTE entries. We don't have | ||
827 | * to care about the contiguous hint of the surrounding entries. | ||
828 | */ | ||
829 | if (size == SZ_64K) { | ||
830 | ipmmu_clear_pte(mmu, pud, pmd, pte, ARM_VMSA_PTE_CONT_ENTRIES); | ||
831 | goto done; | ||
832 | } | ||
833 | |||
834 | /* | ||
835 | * If the PTE has been mapped with the contiguous hint set remap it and | ||
836 | * its surrounding PTEs to allow unmapping a single page. | ||
837 | */ | ||
838 | if (pte_val(*pte) & ARM_VMSA_PTE_CONT) | ||
839 | ipmmu_split_pte(mmu, pte); | ||
840 | |||
841 | /* Clear the PTE. */ | ||
842 | ipmmu_clear_pte(mmu, pud, pmd, pte, 1); | ||
843 | |||
844 | done: | ||
845 | spin_unlock_irqrestore(&domain->lock, flags); | ||
846 | |||
847 | if (ret) | ||
848 | ipmmu_tlb_invalidate(domain); | ||
849 | |||
850 | return 0; | ||
851 | } | ||
852 | |||
853 | /* ----------------------------------------------------------------------------- | ||
854 | * IOMMU Operations | ||
855 | */ | ||
856 | |||
857 | static int ipmmu_domain_init(struct iommu_domain *io_domain) | ||
858 | { | ||
859 | struct ipmmu_vmsa_domain *domain; | ||
860 | |||
861 | domain = kzalloc(sizeof(*domain), GFP_KERNEL); | ||
862 | if (!domain) | ||
863 | return -ENOMEM; | ||
864 | |||
865 | spin_lock_init(&domain->lock); | ||
866 | |||
867 | domain->pgd = kzalloc(IPMMU_PTRS_PER_PGD * sizeof(pgd_t), GFP_KERNEL); | ||
868 | if (!domain->pgd) { | ||
869 | kfree(domain); | ||
870 | return -ENOMEM; | ||
871 | } | ||
872 | |||
873 | io_domain->priv = domain; | ||
874 | domain->io_domain = io_domain; | ||
875 | |||
876 | return 0; | ||
877 | } | ||
878 | |||
879 | static void ipmmu_domain_destroy(struct iommu_domain *io_domain) | ||
880 | { | ||
881 | struct ipmmu_vmsa_domain *domain = io_domain->priv; | ||
882 | |||
883 | /* | ||
884 | * Free the domain resources. We assume that all devices have already | ||
885 | * been detached. | ||
886 | */ | ||
887 | ipmmu_domain_destroy_context(domain); | ||
888 | ipmmu_free_pgtables(domain); | ||
889 | kfree(domain); | ||
890 | } | ||
891 | |||
892 | static int ipmmu_attach_device(struct iommu_domain *io_domain, | ||
893 | struct device *dev) | ||
894 | { | ||
895 | struct ipmmu_vmsa_archdata *archdata = dev->archdata.iommu; | ||
896 | struct ipmmu_vmsa_device *mmu = archdata->mmu; | ||
897 | struct ipmmu_vmsa_domain *domain = io_domain->priv; | ||
898 | unsigned long flags; | ||
899 | int ret = 0; | ||
900 | |||
901 | if (!mmu) { | ||
902 | dev_err(dev, "Cannot attach to IPMMU\n"); | ||
903 | return -ENXIO; | ||
904 | } | ||
905 | |||
906 | spin_lock_irqsave(&domain->lock, flags); | ||
907 | |||
908 | if (!domain->mmu) { | ||
909 | /* The domain hasn't been used yet, initialize it. */ | ||
910 | domain->mmu = mmu; | ||
911 | ret = ipmmu_domain_init_context(domain); | ||
912 | } else if (domain->mmu != mmu) { | ||
913 | /* | ||
914 | * Something is wrong, we can't attach two devices using | ||
915 | * different IOMMUs to the same domain. | ||
916 | */ | ||
917 | dev_err(dev, "Can't attach IPMMU %s to domain on IPMMU %s\n", | ||
918 | dev_name(mmu->dev), dev_name(domain->mmu->dev)); | ||
919 | ret = -EINVAL; | ||
920 | } | ||
921 | |||
922 | spin_unlock_irqrestore(&domain->lock, flags); | ||
923 | |||
924 | if (ret < 0) | ||
925 | return ret; | ||
926 | |||
927 | ipmmu_utlb_enable(domain, archdata->utlb); | ||
928 | |||
929 | return 0; | ||
930 | } | ||
931 | |||
932 | static void ipmmu_detach_device(struct iommu_domain *io_domain, | ||
933 | struct device *dev) | ||
934 | { | ||
935 | struct ipmmu_vmsa_archdata *archdata = dev->archdata.iommu; | ||
936 | struct ipmmu_vmsa_domain *domain = io_domain->priv; | ||
937 | |||
938 | ipmmu_utlb_disable(domain, archdata->utlb); | ||
939 | |||
940 | /* | ||
941 | * TODO: Optimize by disabling the context when no device is attached. | ||
942 | */ | ||
943 | } | ||
944 | |||
945 | static int ipmmu_map(struct iommu_domain *io_domain, unsigned long iova, | ||
946 | phys_addr_t paddr, size_t size, int prot) | ||
947 | { | ||
948 | struct ipmmu_vmsa_domain *domain = io_domain->priv; | ||
949 | |||
950 | if (!domain) | ||
951 | return -ENODEV; | ||
952 | |||
953 | return ipmmu_create_mapping(domain, iova, paddr, size, prot); | ||
954 | } | ||
955 | |||
956 | static size_t ipmmu_unmap(struct iommu_domain *io_domain, unsigned long iova, | ||
957 | size_t size) | ||
958 | { | ||
959 | struct ipmmu_vmsa_domain *domain = io_domain->priv; | ||
960 | int ret; | ||
961 | |||
962 | ret = ipmmu_clear_mapping(domain, iova, size); | ||
963 | return ret ? 0 : size; | ||
964 | } | ||
965 | |||
966 | static phys_addr_t ipmmu_iova_to_phys(struct iommu_domain *io_domain, | ||
967 | dma_addr_t iova) | ||
968 | { | ||
969 | struct ipmmu_vmsa_domain *domain = io_domain->priv; | ||
970 | pgd_t pgd; | ||
971 | pud_t pud; | ||
972 | pmd_t pmd; | ||
973 | pte_t pte; | ||
974 | |||
975 | /* TODO: Is locking needed ? */ | ||
976 | |||
977 | if (!domain->pgd) | ||
978 | return 0; | ||
979 | |||
980 | pgd = *(domain->pgd + pgd_index(iova)); | ||
981 | if (pgd_none(pgd)) | ||
982 | return 0; | ||
983 | |||
984 | pud = *pud_offset(&pgd, iova); | ||
985 | if (pud_none(pud)) | ||
986 | return 0; | ||
987 | |||
988 | pmd = *pmd_offset(&pud, iova); | ||
989 | if (pmd_none(pmd)) | ||
990 | return 0; | ||
991 | |||
992 | if (pmd_sect(pmd)) | ||
993 | return __pfn_to_phys(pmd_pfn(pmd)) | (iova & ~PMD_MASK); | ||
994 | |||
995 | pte = *(pmd_page_vaddr(pmd) + pte_index(iova)); | ||
996 | if (pte_none(pte)) | ||
997 | return 0; | ||
998 | |||
999 | return __pfn_to_phys(pte_pfn(pte)) | (iova & ~PAGE_MASK); | ||
1000 | } | ||
1001 | |||
1002 | static int ipmmu_find_utlb(struct ipmmu_vmsa_device *mmu, struct device *dev) | ||
1003 | { | ||
1004 | const struct ipmmu_vmsa_master *master = mmu->pdata->masters; | ||
1005 | const char *devname = dev_name(dev); | ||
1006 | unsigned int i; | ||
1007 | |||
1008 | for (i = 0; i < mmu->pdata->num_masters; ++i, ++master) { | ||
1009 | if (strcmp(master->name, devname) == 0) | ||
1010 | return master->utlb; | ||
1011 | } | ||
1012 | |||
1013 | return -1; | ||
1014 | } | ||
1015 | |||
1016 | static int ipmmu_add_device(struct device *dev) | ||
1017 | { | ||
1018 | struct ipmmu_vmsa_archdata *archdata; | ||
1019 | struct ipmmu_vmsa_device *mmu; | ||
1020 | struct iommu_group *group; | ||
1021 | int utlb = -1; | ||
1022 | int ret; | ||
1023 | |||
1024 | if (dev->archdata.iommu) { | ||
1025 | dev_warn(dev, "IOMMU driver already assigned to device %s\n", | ||
1026 | dev_name(dev)); | ||
1027 | return -EINVAL; | ||
1028 | } | ||
1029 | |||
1030 | /* Find the master corresponding to the device. */ | ||
1031 | spin_lock(&ipmmu_devices_lock); | ||
1032 | |||
1033 | list_for_each_entry(mmu, &ipmmu_devices, list) { | ||
1034 | utlb = ipmmu_find_utlb(mmu, dev); | ||
1035 | if (utlb >= 0) { | ||
1036 | /* | ||
1037 | * TODO Take a reference to the MMU to protect | ||
1038 | * against device removal. | ||
1039 | */ | ||
1040 | break; | ||
1041 | } | ||
1042 | } | ||
1043 | |||
1044 | spin_unlock(&ipmmu_devices_lock); | ||
1045 | |||
1046 | if (utlb < 0) | ||
1047 | return -ENODEV; | ||
1048 | |||
1049 | if (utlb >= mmu->num_utlbs) | ||
1050 | return -EINVAL; | ||
1051 | |||
1052 | /* Create a device group and add the device to it. */ | ||
1053 | group = iommu_group_alloc(); | ||
1054 | if (IS_ERR(group)) { | ||
1055 | dev_err(dev, "Failed to allocate IOMMU group\n"); | ||
1056 | return PTR_ERR(group); | ||
1057 | } | ||
1058 | |||
1059 | ret = iommu_group_add_device(group, dev); | ||
1060 | iommu_group_put(group); | ||
1061 | |||
1062 | if (ret < 0) { | ||
1063 | dev_err(dev, "Failed to add device to IPMMU group\n"); | ||
1064 | return ret; | ||
1065 | } | ||
1066 | |||
1067 | archdata = kzalloc(sizeof(*archdata), GFP_KERNEL); | ||
1068 | if (!archdata) { | ||
1069 | ret = -ENOMEM; | ||
1070 | goto error; | ||
1071 | } | ||
1072 | |||
1073 | archdata->mmu = mmu; | ||
1074 | archdata->utlb = utlb; | ||
1075 | dev->archdata.iommu = archdata; | ||
1076 | |||
1077 | /* | ||
1078 | * Create the ARM mapping, used by the ARM DMA mapping core to allocate | ||
1079 | * VAs. This will allocate a corresponding IOMMU domain. | ||
1080 | * | ||
1081 | * TODO: | ||
1082 | * - Create one mapping per context (TLB). | ||
1083 | * - Make the mapping size configurable ? We currently use a 2GB mapping | ||
1084 | * at a 1GB offset to ensure that NULL VAs will fault. | ||
1085 | */ | ||
1086 | if (!mmu->mapping) { | ||
1087 | struct dma_iommu_mapping *mapping; | ||
1088 | |||
1089 | mapping = arm_iommu_create_mapping(&platform_bus_type, | ||
1090 | SZ_1G, SZ_2G); | ||
1091 | if (IS_ERR(mapping)) { | ||
1092 | dev_err(mmu->dev, "failed to create ARM IOMMU mapping\n"); | ||
1093 | return PTR_ERR(mapping); | ||
1094 | } | ||
1095 | |||
1096 | mmu->mapping = mapping; | ||
1097 | } | ||
1098 | |||
1099 | /* Attach the ARM VA mapping to the device. */ | ||
1100 | ret = arm_iommu_attach_device(dev, mmu->mapping); | ||
1101 | if (ret < 0) { | ||
1102 | dev_err(dev, "Failed to attach device to VA mapping\n"); | ||
1103 | goto error; | ||
1104 | } | ||
1105 | |||
1106 | return 0; | ||
1107 | |||
1108 | error: | ||
1109 | kfree(dev->archdata.iommu); | ||
1110 | dev->archdata.iommu = NULL; | ||
1111 | iommu_group_remove_device(dev); | ||
1112 | return ret; | ||
1113 | } | ||
1114 | |||
1115 | static void ipmmu_remove_device(struct device *dev) | ||
1116 | { | ||
1117 | arm_iommu_detach_device(dev); | ||
1118 | iommu_group_remove_device(dev); | ||
1119 | kfree(dev->archdata.iommu); | ||
1120 | dev->archdata.iommu = NULL; | ||
1121 | } | ||
1122 | |||
1123 | static struct iommu_ops ipmmu_ops = { | ||
1124 | .domain_init = ipmmu_domain_init, | ||
1125 | .domain_destroy = ipmmu_domain_destroy, | ||
1126 | .attach_dev = ipmmu_attach_device, | ||
1127 | .detach_dev = ipmmu_detach_device, | ||
1128 | .map = ipmmu_map, | ||
1129 | .unmap = ipmmu_unmap, | ||
1130 | .iova_to_phys = ipmmu_iova_to_phys, | ||
1131 | .add_device = ipmmu_add_device, | ||
1132 | .remove_device = ipmmu_remove_device, | ||
1133 | .pgsize_bitmap = SZ_2M | SZ_64K | SZ_4K, | ||
1134 | }; | ||
1135 | |||
1136 | /* ----------------------------------------------------------------------------- | ||
1137 | * Probe/remove and init | ||
1138 | */ | ||
1139 | |||
1140 | static void ipmmu_device_reset(struct ipmmu_vmsa_device *mmu) | ||
1141 | { | ||
1142 | unsigned int i; | ||
1143 | |||
1144 | /* Disable all contexts. */ | ||
1145 | for (i = 0; i < 4; ++i) | ||
1146 | ipmmu_write(mmu, i * IM_CTX_SIZE + IMCTR, 0); | ||
1147 | } | ||
1148 | |||
1149 | static int ipmmu_probe(struct platform_device *pdev) | ||
1150 | { | ||
1151 | struct ipmmu_vmsa_device *mmu; | ||
1152 | struct resource *res; | ||
1153 | int irq; | ||
1154 | int ret; | ||
1155 | |||
1156 | if (!pdev->dev.platform_data) { | ||
1157 | dev_err(&pdev->dev, "missing platform data\n"); | ||
1158 | return -EINVAL; | ||
1159 | } | ||
1160 | |||
1161 | mmu = devm_kzalloc(&pdev->dev, sizeof(*mmu), GFP_KERNEL); | ||
1162 | if (!mmu) { | ||
1163 | dev_err(&pdev->dev, "cannot allocate device data\n"); | ||
1164 | return -ENOMEM; | ||
1165 | } | ||
1166 | |||
1167 | mmu->dev = &pdev->dev; | ||
1168 | mmu->pdata = pdev->dev.platform_data; | ||
1169 | mmu->num_utlbs = 32; | ||
1170 | |||
1171 | /* Map I/O memory and request IRQ. */ | ||
1172 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
1173 | mmu->base = devm_ioremap_resource(&pdev->dev, res); | ||
1174 | if (IS_ERR(mmu->base)) | ||
1175 | return PTR_ERR(mmu->base); | ||
1176 | |||
1177 | irq = platform_get_irq(pdev, 0); | ||
1178 | if (irq < 0) { | ||
1179 | dev_err(&pdev->dev, "no IRQ found\n"); | ||
1180 | return irq; | ||
1181 | } | ||
1182 | |||
1183 | ret = devm_request_irq(&pdev->dev, irq, ipmmu_irq, 0, | ||
1184 | dev_name(&pdev->dev), mmu); | ||
1185 | if (ret < 0) { | ||
1186 | dev_err(&pdev->dev, "failed to request IRQ %d\n", irq); | ||
1187 | return irq; | ||
1188 | } | ||
1189 | |||
1190 | ipmmu_device_reset(mmu); | ||
1191 | |||
1192 | /* | ||
1193 | * We can't create the ARM mapping here as it requires the bus to have | ||
1194 | * an IOMMU, which only happens when bus_set_iommu() is called in | ||
1195 | * ipmmu_init() after the probe function returns. | ||
1196 | */ | ||
1197 | |||
1198 | spin_lock(&ipmmu_devices_lock); | ||
1199 | list_add(&mmu->list, &ipmmu_devices); | ||
1200 | spin_unlock(&ipmmu_devices_lock); | ||
1201 | |||
1202 | platform_set_drvdata(pdev, mmu); | ||
1203 | |||
1204 | return 0; | ||
1205 | } | ||
1206 | |||
1207 | static int ipmmu_remove(struct platform_device *pdev) | ||
1208 | { | ||
1209 | struct ipmmu_vmsa_device *mmu = platform_get_drvdata(pdev); | ||
1210 | |||
1211 | spin_lock(&ipmmu_devices_lock); | ||
1212 | list_del(&mmu->list); | ||
1213 | spin_unlock(&ipmmu_devices_lock); | ||
1214 | |||
1215 | arm_iommu_release_mapping(mmu->mapping); | ||
1216 | |||
1217 | ipmmu_device_reset(mmu); | ||
1218 | |||
1219 | return 0; | ||
1220 | } | ||
1221 | |||
1222 | static struct platform_driver ipmmu_driver = { | ||
1223 | .driver = { | ||
1224 | .owner = THIS_MODULE, | ||
1225 | .name = "ipmmu-vmsa", | ||
1226 | }, | ||
1227 | .probe = ipmmu_probe, | ||
1228 | .remove = ipmmu_remove, | ||
1229 | }; | ||
1230 | |||
1231 | static int __init ipmmu_init(void) | ||
1232 | { | ||
1233 | int ret; | ||
1234 | |||
1235 | ret = platform_driver_register(&ipmmu_driver); | ||
1236 | if (ret < 0) | ||
1237 | return ret; | ||
1238 | |||
1239 | if (!iommu_present(&platform_bus_type)) | ||
1240 | bus_set_iommu(&platform_bus_type, &ipmmu_ops); | ||
1241 | |||
1242 | return 0; | ||
1243 | } | ||
1244 | |||
1245 | static void __exit ipmmu_exit(void) | ||
1246 | { | ||
1247 | return platform_driver_unregister(&ipmmu_driver); | ||
1248 | } | ||
1249 | |||
1250 | subsys_initcall(ipmmu_init); | ||
1251 | module_exit(ipmmu_exit); | ||
1252 | |||
1253 | MODULE_DESCRIPTION("IOMMU API for Renesas VMSA-compatible IPMMU"); | ||
1254 | MODULE_AUTHOR("Laurent Pinchart <laurent.pinchart@ideasonboard.com>"); | ||
1255 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/iommu/irq_remapping.c b/drivers/iommu/irq_remapping.c index 228632c99adb..33c439524080 100644 --- a/drivers/iommu/irq_remapping.c +++ b/drivers/iommu/irq_remapping.c | |||
@@ -51,7 +51,7 @@ static void irq_remapping_disable_io_apic(void) | |||
51 | 51 | ||
52 | static int do_setup_msi_irqs(struct pci_dev *dev, int nvec) | 52 | static int do_setup_msi_irqs(struct pci_dev *dev, int nvec) |
53 | { | 53 | { |
54 | int node, ret, sub_handle, nvec_pow2, index = 0; | 54 | int ret, sub_handle, nvec_pow2, index = 0; |
55 | unsigned int irq; | 55 | unsigned int irq; |
56 | struct msi_desc *msidesc; | 56 | struct msi_desc *msidesc; |
57 | 57 | ||
@@ -61,8 +61,7 @@ static int do_setup_msi_irqs(struct pci_dev *dev, int nvec) | |||
61 | WARN_ON(msidesc->msi_attrib.multiple); | 61 | WARN_ON(msidesc->msi_attrib.multiple); |
62 | WARN_ON(msidesc->nvec_used); | 62 | WARN_ON(msidesc->nvec_used); |
63 | 63 | ||
64 | node = dev_to_node(&dev->dev); | 64 | irq = irq_alloc_hwirqs(nvec, dev_to_node(&dev->dev)); |
65 | irq = __create_irqs(get_nr_irqs_gsi(), nvec, node); | ||
66 | if (irq == 0) | 65 | if (irq == 0) |
67 | return -ENOSPC; | 66 | return -ENOSPC; |
68 | 67 | ||
@@ -89,7 +88,7 @@ static int do_setup_msi_irqs(struct pci_dev *dev, int nvec) | |||
89 | return 0; | 88 | return 0; |
90 | 89 | ||
91 | error: | 90 | error: |
92 | destroy_irqs(irq, nvec); | 91 | irq_free_hwirqs(irq, nvec); |
93 | 92 | ||
94 | /* | 93 | /* |
95 | * Restore altered MSI descriptor fields and prevent just destroyed | 94 | * Restore altered MSI descriptor fields and prevent just destroyed |
@@ -109,12 +108,11 @@ static int do_setup_msix_irqs(struct pci_dev *dev, int nvec) | |||
109 | unsigned int irq; | 108 | unsigned int irq; |
110 | 109 | ||
111 | node = dev_to_node(&dev->dev); | 110 | node = dev_to_node(&dev->dev); |
112 | irq = get_nr_irqs_gsi(); | ||
113 | sub_handle = 0; | 111 | sub_handle = 0; |
114 | 112 | ||
115 | list_for_each_entry(msidesc, &dev->msi_list, list) { | 113 | list_for_each_entry(msidesc, &dev->msi_list, list) { |
116 | 114 | ||
117 | irq = create_irq_nr(irq, node); | 115 | irq = irq_alloc_hwirq(node); |
118 | if (irq == 0) | 116 | if (irq == 0) |
119 | return -1; | 117 | return -1; |
120 | 118 | ||
@@ -137,7 +135,7 @@ static int do_setup_msix_irqs(struct pci_dev *dev, int nvec) | |||
137 | return 0; | 135 | return 0; |
138 | 136 | ||
139 | error: | 137 | error: |
140 | destroy_irq(irq); | 138 | irq_free_hwirq(irq); |
141 | return ret; | 139 | return ret; |
142 | } | 140 | } |
143 | 141 | ||
diff --git a/drivers/iommu/msm_iommu_dev.c b/drivers/iommu/msm_iommu_dev.c index 08ba4972da9d..61def7cb5263 100644 --- a/drivers/iommu/msm_iommu_dev.c +++ b/drivers/iommu/msm_iommu_dev.c | |||
@@ -127,13 +127,12 @@ static void msm_iommu_reset(void __iomem *base, int ncb) | |||
127 | 127 | ||
128 | static int msm_iommu_probe(struct platform_device *pdev) | 128 | static int msm_iommu_probe(struct platform_device *pdev) |
129 | { | 129 | { |
130 | struct resource *r, *r2; | 130 | struct resource *r; |
131 | struct clk *iommu_clk; | 131 | struct clk *iommu_clk; |
132 | struct clk *iommu_pclk; | 132 | struct clk *iommu_pclk; |
133 | struct msm_iommu_drvdata *drvdata; | 133 | struct msm_iommu_drvdata *drvdata; |
134 | struct msm_iommu_dev *iommu_dev = pdev->dev.platform_data; | 134 | struct msm_iommu_dev *iommu_dev = pdev->dev.platform_data; |
135 | void __iomem *regs_base; | 135 | void __iomem *regs_base; |
136 | resource_size_t len; | ||
137 | int ret, irq, par; | 136 | int ret, irq, par; |
138 | 137 | ||
139 | if (pdev->id == -1) { | 138 | if (pdev->id == -1) { |
@@ -178,35 +177,16 @@ static int msm_iommu_probe(struct platform_device *pdev) | |||
178 | iommu_clk = NULL; | 177 | iommu_clk = NULL; |
179 | 178 | ||
180 | r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "physbase"); | 179 | r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "physbase"); |
181 | 180 | regs_base = devm_ioremap_resource(&pdev->dev, r); | |
182 | if (!r) { | 181 | if (IS_ERR(regs_base)) { |
183 | ret = -ENODEV; | 182 | ret = PTR_ERR(regs_base); |
184 | goto fail_clk; | ||
185 | } | ||
186 | |||
187 | len = resource_size(r); | ||
188 | |||
189 | r2 = request_mem_region(r->start, len, r->name); | ||
190 | if (!r2) { | ||
191 | pr_err("Could not request memory region: start=%p, len=%d\n", | ||
192 | (void *) r->start, len); | ||
193 | ret = -EBUSY; | ||
194 | goto fail_clk; | 183 | goto fail_clk; |
195 | } | 184 | } |
196 | 185 | ||
197 | regs_base = ioremap(r2->start, len); | ||
198 | |||
199 | if (!regs_base) { | ||
200 | pr_err("Could not ioremap: start=%p, len=%d\n", | ||
201 | (void *) r2->start, len); | ||
202 | ret = -EBUSY; | ||
203 | goto fail_mem; | ||
204 | } | ||
205 | |||
206 | irq = platform_get_irq_byname(pdev, "secure_irq"); | 186 | irq = platform_get_irq_byname(pdev, "secure_irq"); |
207 | if (irq < 0) { | 187 | if (irq < 0) { |
208 | ret = -ENODEV; | 188 | ret = -ENODEV; |
209 | goto fail_io; | 189 | goto fail_clk; |
210 | } | 190 | } |
211 | 191 | ||
212 | msm_iommu_reset(regs_base, iommu_dev->ncb); | 192 | msm_iommu_reset(regs_base, iommu_dev->ncb); |
@@ -222,14 +202,14 @@ static int msm_iommu_probe(struct platform_device *pdev) | |||
222 | if (!par) { | 202 | if (!par) { |
223 | pr_err("%s: Invalid PAR value detected\n", iommu_dev->name); | 203 | pr_err("%s: Invalid PAR value detected\n", iommu_dev->name); |
224 | ret = -ENODEV; | 204 | ret = -ENODEV; |
225 | goto fail_io; | 205 | goto fail_clk; |
226 | } | 206 | } |
227 | 207 | ||
228 | ret = request_irq(irq, msm_iommu_fault_handler, 0, | 208 | ret = request_irq(irq, msm_iommu_fault_handler, 0, |
229 | "msm_iommu_secure_irpt_handler", drvdata); | 209 | "msm_iommu_secure_irpt_handler", drvdata); |
230 | if (ret) { | 210 | if (ret) { |
231 | pr_err("Request IRQ %d failed with ret=%d\n", irq, ret); | 211 | pr_err("Request IRQ %d failed with ret=%d\n", irq, ret); |
232 | goto fail_io; | 212 | goto fail_clk; |
233 | } | 213 | } |
234 | 214 | ||
235 | 215 | ||
@@ -250,10 +230,6 @@ static int msm_iommu_probe(struct platform_device *pdev) | |||
250 | clk_disable(iommu_pclk); | 230 | clk_disable(iommu_pclk); |
251 | 231 | ||
252 | return 0; | 232 | return 0; |
253 | fail_io: | ||
254 | iounmap(regs_base); | ||
255 | fail_mem: | ||
256 | release_mem_region(r->start, len); | ||
257 | fail_clk: | 233 | fail_clk: |
258 | if (iommu_clk) { | 234 | if (iommu_clk) { |
259 | clk_disable(iommu_clk); | 235 | clk_disable(iommu_clk); |
diff --git a/drivers/iommu/omap-iommu.c b/drivers/iommu/omap-iommu.c index 7fcbfc498fa9..895af06a667f 100644 --- a/drivers/iommu/omap-iommu.c +++ b/drivers/iommu/omap-iommu.c | |||
@@ -34,6 +34,9 @@ | |||
34 | #include "omap-iopgtable.h" | 34 | #include "omap-iopgtable.h" |
35 | #include "omap-iommu.h" | 35 | #include "omap-iommu.h" |
36 | 36 | ||
37 | #define to_iommu(dev) \ | ||
38 | ((struct omap_iommu *)platform_get_drvdata(to_platform_device(dev))) | ||
39 | |||
37 | #define for_each_iotlb_cr(obj, n, __i, cr) \ | 40 | #define for_each_iotlb_cr(obj, n, __i, cr) \ |
38 | for (__i = 0; \ | 41 | for (__i = 0; \ |
39 | (__i < (n)) && (cr = __iotlb_read_cr((obj), __i), true); \ | 42 | (__i < (n)) && (cr = __iotlb_read_cr((obj), __i), true); \ |
@@ -391,6 +394,7 @@ static void flush_iotlb_page(struct omap_iommu *obj, u32 da) | |||
391 | __func__, start, da, bytes); | 394 | __func__, start, da, bytes); |
392 | iotlb_load_cr(obj, &cr); | 395 | iotlb_load_cr(obj, &cr); |
393 | iommu_write_reg(obj, 1, MMU_FLUSH_ENTRY); | 396 | iommu_write_reg(obj, 1, MMU_FLUSH_ENTRY); |
397 | break; | ||
394 | } | 398 | } |
395 | } | 399 | } |
396 | pm_runtime_put_sync(obj->dev); | 400 | pm_runtime_put_sync(obj->dev); |
@@ -1037,19 +1041,18 @@ static void iopte_cachep_ctor(void *iopte) | |||
1037 | clean_dcache_area(iopte, IOPTE_TABLE_SIZE); | 1041 | clean_dcache_area(iopte, IOPTE_TABLE_SIZE); |
1038 | } | 1042 | } |
1039 | 1043 | ||
1040 | static u32 iotlb_init_entry(struct iotlb_entry *e, u32 da, u32 pa, | 1044 | static u32 iotlb_init_entry(struct iotlb_entry *e, u32 da, u32 pa, int pgsz) |
1041 | u32 flags) | ||
1042 | { | 1045 | { |
1043 | memset(e, 0, sizeof(*e)); | 1046 | memset(e, 0, sizeof(*e)); |
1044 | 1047 | ||
1045 | e->da = da; | 1048 | e->da = da; |
1046 | e->pa = pa; | 1049 | e->pa = pa; |
1047 | e->valid = 1; | 1050 | e->valid = MMU_CAM_V; |
1048 | /* FIXME: add OMAP1 support */ | 1051 | /* FIXME: add OMAP1 support */ |
1049 | e->pgsz = flags & MMU_CAM_PGSZ_MASK; | 1052 | e->pgsz = pgsz; |
1050 | e->endian = flags & MMU_RAM_ENDIAN_MASK; | 1053 | e->endian = MMU_RAM_ENDIAN_LITTLE; |
1051 | e->elsz = flags & MMU_RAM_ELSZ_MASK; | 1054 | e->elsz = MMU_RAM_ELSZ_8; |
1052 | e->mixed = flags & MMU_RAM_MIXED_MASK; | 1055 | e->mixed = 0; |
1053 | 1056 | ||
1054 | return iopgsz_to_bytes(e->pgsz); | 1057 | return iopgsz_to_bytes(e->pgsz); |
1055 | } | 1058 | } |
@@ -1062,9 +1065,8 @@ static int omap_iommu_map(struct iommu_domain *domain, unsigned long da, | |||
1062 | struct device *dev = oiommu->dev; | 1065 | struct device *dev = oiommu->dev; |
1063 | struct iotlb_entry e; | 1066 | struct iotlb_entry e; |
1064 | int omap_pgsz; | 1067 | int omap_pgsz; |
1065 | u32 ret, flags; | 1068 | u32 ret; |
1066 | 1069 | ||
1067 | /* we only support mapping a single iommu page for now */ | ||
1068 | omap_pgsz = bytes_to_iopgsz(bytes); | 1070 | omap_pgsz = bytes_to_iopgsz(bytes); |
1069 | if (omap_pgsz < 0) { | 1071 | if (omap_pgsz < 0) { |
1070 | dev_err(dev, "invalid size to map: %d\n", bytes); | 1072 | dev_err(dev, "invalid size to map: %d\n", bytes); |
@@ -1073,9 +1075,7 @@ static int omap_iommu_map(struct iommu_domain *domain, unsigned long da, | |||
1073 | 1075 | ||
1074 | dev_dbg(dev, "mapping da 0x%lx to pa 0x%x size 0x%x\n", da, pa, bytes); | 1076 | dev_dbg(dev, "mapping da 0x%lx to pa 0x%x size 0x%x\n", da, pa, bytes); |
1075 | 1077 | ||
1076 | flags = omap_pgsz | prot; | 1078 | iotlb_init_entry(&e, da, pa, omap_pgsz); |
1077 | |||
1078 | iotlb_init_entry(&e, da, pa, flags); | ||
1079 | 1079 | ||
1080 | ret = omap_iopgtable_store_entry(oiommu, &e); | 1080 | ret = omap_iopgtable_store_entry(oiommu, &e); |
1081 | if (ret) | 1081 | if (ret) |
@@ -1248,12 +1248,6 @@ static phys_addr_t omap_iommu_iova_to_phys(struct iommu_domain *domain, | |||
1248 | return ret; | 1248 | return ret; |
1249 | } | 1249 | } |
1250 | 1250 | ||
1251 | static int omap_iommu_domain_has_cap(struct iommu_domain *domain, | ||
1252 | unsigned long cap) | ||
1253 | { | ||
1254 | return 0; | ||
1255 | } | ||
1256 | |||
1257 | static int omap_iommu_add_device(struct device *dev) | 1251 | static int omap_iommu_add_device(struct device *dev) |
1258 | { | 1252 | { |
1259 | struct omap_iommu_arch_data *arch_data; | 1253 | struct omap_iommu_arch_data *arch_data; |
@@ -1305,7 +1299,6 @@ static struct iommu_ops omap_iommu_ops = { | |||
1305 | .map = omap_iommu_map, | 1299 | .map = omap_iommu_map, |
1306 | .unmap = omap_iommu_unmap, | 1300 | .unmap = omap_iommu_unmap, |
1307 | .iova_to_phys = omap_iommu_iova_to_phys, | 1301 | .iova_to_phys = omap_iommu_iova_to_phys, |
1308 | .domain_has_cap = omap_iommu_domain_has_cap, | ||
1309 | .add_device = omap_iommu_add_device, | 1302 | .add_device = omap_iommu_add_device, |
1310 | .remove_device = omap_iommu_remove_device, | 1303 | .remove_device = omap_iommu_remove_device, |
1311 | .pgsize_bitmap = OMAP_IOMMU_PGSIZES, | 1304 | .pgsize_bitmap = OMAP_IOMMU_PGSIZES, |
diff --git a/drivers/iommu/omap-iopgtable.h b/drivers/iommu/omap-iopgtable.h index b6f9a51746ca..f891683e3f05 100644 --- a/drivers/iommu/omap-iopgtable.h +++ b/drivers/iommu/omap-iopgtable.h | |||
@@ -93,6 +93,3 @@ static inline phys_addr_t omap_iommu_translate(u32 d, u32 va, u32 mask) | |||
93 | /* to find an entry in the second-level page table. */ | 93 | /* to find an entry in the second-level page table. */ |
94 | #define iopte_index(da) (((da) >> IOPTE_SHIFT) & (PTRS_PER_IOPTE - 1)) | 94 | #define iopte_index(da) (((da) >> IOPTE_SHIFT) & (PTRS_PER_IOPTE - 1)) |
95 | #define iopte_offset(iopgd, da) (iopgd_page_vaddr(iopgd) + iopte_index(da)) | 95 | #define iopte_offset(iopgd, da) (iopgd_page_vaddr(iopgd) + iopte_index(da)) |
96 | |||
97 | #define to_iommu(dev) \ | ||
98 | (platform_get_drvdata(to_platform_device(dev))) | ||
diff --git a/drivers/iommu/shmobile-ipmmu.c b/drivers/iommu/shmobile-ipmmu.c index e3bc2e19b6dd..bd97adecb1fd 100644 --- a/drivers/iommu/shmobile-ipmmu.c +++ b/drivers/iommu/shmobile-ipmmu.c | |||
@@ -94,11 +94,6 @@ static int ipmmu_probe(struct platform_device *pdev) | |||
94 | struct resource *res; | 94 | struct resource *res; |
95 | struct shmobile_ipmmu_platform_data *pdata = pdev->dev.platform_data; | 95 | struct shmobile_ipmmu_platform_data *pdata = pdev->dev.platform_data; |
96 | 96 | ||
97 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
98 | if (!res) { | ||
99 | dev_err(&pdev->dev, "cannot get platform resources\n"); | ||
100 | return -ENOENT; | ||
101 | } | ||
102 | ipmmu = devm_kzalloc(&pdev->dev, sizeof(*ipmmu), GFP_KERNEL); | 97 | ipmmu = devm_kzalloc(&pdev->dev, sizeof(*ipmmu), GFP_KERNEL); |
103 | if (!ipmmu) { | 98 | if (!ipmmu) { |
104 | dev_err(&pdev->dev, "cannot allocate device data\n"); | 99 | dev_err(&pdev->dev, "cannot allocate device data\n"); |
@@ -106,19 +101,18 @@ static int ipmmu_probe(struct platform_device *pdev) | |||
106 | } | 101 | } |
107 | spin_lock_init(&ipmmu->flush_lock); | 102 | spin_lock_init(&ipmmu->flush_lock); |
108 | ipmmu->dev = &pdev->dev; | 103 | ipmmu->dev = &pdev->dev; |
109 | ipmmu->ipmmu_base = devm_ioremap_nocache(&pdev->dev, res->start, | 104 | |
110 | resource_size(res)); | 105 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
111 | if (!ipmmu->ipmmu_base) { | 106 | ipmmu->ipmmu_base = devm_ioremap_resource(&pdev->dev, res); |
112 | dev_err(&pdev->dev, "ioremap_nocache failed\n"); | 107 | if (IS_ERR(ipmmu->ipmmu_base)) |
113 | return -ENOMEM; | 108 | return PTR_ERR(ipmmu->ipmmu_base); |
114 | } | 109 | |
115 | ipmmu->dev_names = pdata->dev_names; | 110 | ipmmu->dev_names = pdata->dev_names; |
116 | ipmmu->num_dev_names = pdata->num_dev_names; | 111 | ipmmu->num_dev_names = pdata->num_dev_names; |
117 | platform_set_drvdata(pdev, ipmmu); | 112 | platform_set_drvdata(pdev, ipmmu); |
118 | ipmmu_reg_write(ipmmu, IMCTR1, 0x0); /* disable TLB */ | 113 | ipmmu_reg_write(ipmmu, IMCTR1, 0x0); /* disable TLB */ |
119 | ipmmu_reg_write(ipmmu, IMCTR2, 0x0); /* disable PMB */ | 114 | ipmmu_reg_write(ipmmu, IMCTR2, 0x0); /* disable PMB */ |
120 | ipmmu_iommu_init(ipmmu); | 115 | return ipmmu_iommu_init(ipmmu); |
121 | return 0; | ||
122 | } | 116 | } |
123 | 117 | ||
124 | static struct platform_driver ipmmu_driver = { | 118 | static struct platform_driver ipmmu_driver = { |