diff options
Diffstat (limited to 'drivers/iommu/amd_iommu_v2.c')
-rw-r--r-- | drivers/iommu/amd_iommu_v2.c | 61 |
1 files changed, 9 insertions, 52 deletions
diff --git a/drivers/iommu/amd_iommu_v2.c b/drivers/iommu/amd_iommu_v2.c index bea878f8e7d3..90f70d0e1141 100644 --- a/drivers/iommu/amd_iommu_v2.c +++ b/drivers/iommu/amd_iommu_v2.c | |||
@@ -92,13 +92,6 @@ static spinlock_t state_lock; | |||
92 | 92 | ||
93 | static struct workqueue_struct *iommu_wq; | 93 | static struct workqueue_struct *iommu_wq; |
94 | 94 | ||
95 | /* | ||
96 | * Empty page table - Used between | ||
97 | * mmu_notifier_invalidate_range_start and | ||
98 | * mmu_notifier_invalidate_range_end | ||
99 | */ | ||
100 | static u64 *empty_page_table; | ||
101 | |||
102 | static void free_pasid_states(struct device_state *dev_state); | 95 | static void free_pasid_states(struct device_state *dev_state); |
103 | 96 | ||
104 | static u16 device_id(struct pci_dev *pdev) | 97 | static u16 device_id(struct pci_dev *pdev) |
@@ -414,46 +407,21 @@ static void mn_invalidate_page(struct mmu_notifier *mn, | |||
414 | __mn_flush_page(mn, address); | 407 | __mn_flush_page(mn, address); |
415 | } | 408 | } |
416 | 409 | ||
417 | static void mn_invalidate_range_start(struct mmu_notifier *mn, | 410 | static void mn_invalidate_range(struct mmu_notifier *mn, |
418 | struct mm_struct *mm, | 411 | struct mm_struct *mm, |
419 | unsigned long start, unsigned long end) | 412 | unsigned long start, unsigned long end) |
420 | { | ||
421 | struct pasid_state *pasid_state; | ||
422 | struct device_state *dev_state; | ||
423 | unsigned long flags; | ||
424 | |||
425 | pasid_state = mn_to_state(mn); | ||
426 | dev_state = pasid_state->device_state; | ||
427 | |||
428 | spin_lock_irqsave(&pasid_state->lock, flags); | ||
429 | if (pasid_state->mmu_notifier_count == 0) { | ||
430 | amd_iommu_domain_set_gcr3(dev_state->domain, | ||
431 | pasid_state->pasid, | ||
432 | __pa(empty_page_table)); | ||
433 | } | ||
434 | pasid_state->mmu_notifier_count += 1; | ||
435 | spin_unlock_irqrestore(&pasid_state->lock, flags); | ||
436 | } | ||
437 | |||
438 | static void mn_invalidate_range_end(struct mmu_notifier *mn, | ||
439 | struct mm_struct *mm, | ||
440 | unsigned long start, unsigned long end) | ||
441 | { | 413 | { |
442 | struct pasid_state *pasid_state; | 414 | struct pasid_state *pasid_state; |
443 | struct device_state *dev_state; | 415 | struct device_state *dev_state; |
444 | unsigned long flags; | ||
445 | 416 | ||
446 | pasid_state = mn_to_state(mn); | 417 | pasid_state = mn_to_state(mn); |
447 | dev_state = pasid_state->device_state; | 418 | dev_state = pasid_state->device_state; |
448 | 419 | ||
449 | spin_lock_irqsave(&pasid_state->lock, flags); | 420 | if ((start ^ (end - 1)) < PAGE_SIZE) |
450 | pasid_state->mmu_notifier_count -= 1; | 421 | amd_iommu_flush_page(dev_state->domain, pasid_state->pasid, |
451 | if (pasid_state->mmu_notifier_count == 0) { | 422 | start); |
452 | amd_iommu_domain_set_gcr3(dev_state->domain, | 423 | else |
453 | pasid_state->pasid, | 424 | amd_iommu_flush_tlb(dev_state->domain, pasid_state->pasid); |
454 | __pa(pasid_state->mm->pgd)); | ||
455 | } | ||
456 | spin_unlock_irqrestore(&pasid_state->lock, flags); | ||
457 | } | 425 | } |
458 | 426 | ||
459 | static void mn_release(struct mmu_notifier *mn, struct mm_struct *mm) | 427 | static void mn_release(struct mmu_notifier *mn, struct mm_struct *mm) |
@@ -478,8 +446,7 @@ static struct mmu_notifier_ops iommu_mn = { | |||
478 | .release = mn_release, | 446 | .release = mn_release, |
479 | .clear_flush_young = mn_clear_flush_young, | 447 | .clear_flush_young = mn_clear_flush_young, |
480 | .invalidate_page = mn_invalidate_page, | 448 | .invalidate_page = mn_invalidate_page, |
481 | .invalidate_range_start = mn_invalidate_range_start, | 449 | .invalidate_range = mn_invalidate_range, |
482 | .invalidate_range_end = mn_invalidate_range_end, | ||
483 | }; | 450 | }; |
484 | 451 | ||
485 | static void set_pri_tag_status(struct pasid_state *pasid_state, | 452 | static void set_pri_tag_status(struct pasid_state *pasid_state, |
@@ -972,18 +939,10 @@ static int __init amd_iommu_v2_init(void) | |||
972 | if (iommu_wq == NULL) | 939 | if (iommu_wq == NULL) |
973 | goto out; | 940 | goto out; |
974 | 941 | ||
975 | ret = -ENOMEM; | ||
976 | empty_page_table = (u64 *)get_zeroed_page(GFP_KERNEL); | ||
977 | if (empty_page_table == NULL) | ||
978 | goto out_destroy_wq; | ||
979 | |||
980 | amd_iommu_register_ppr_notifier(&ppr_nb); | 942 | amd_iommu_register_ppr_notifier(&ppr_nb); |
981 | 943 | ||
982 | return 0; | 944 | return 0; |
983 | 945 | ||
984 | out_destroy_wq: | ||
985 | destroy_workqueue(iommu_wq); | ||
986 | |||
987 | out: | 946 | out: |
988 | return ret; | 947 | return ret; |
989 | } | 948 | } |
@@ -1017,8 +976,6 @@ static void __exit amd_iommu_v2_exit(void) | |||
1017 | } | 976 | } |
1018 | 977 | ||
1019 | destroy_workqueue(iommu_wq); | 978 | destroy_workqueue(iommu_wq); |
1020 | |||
1021 | free_page((unsigned long)empty_page_table); | ||
1022 | } | 979 | } |
1023 | 980 | ||
1024 | module_init(amd_iommu_v2_init); | 981 | module_init(amd_iommu_v2_init); |