diff options
| author | Joerg Roedel <jroedel@suse.de> | 2014-07-08 08:15:45 -0400 |
|---|---|---|
| committer | Joerg Roedel <jroedel@suse.de> | 2014-07-10 09:36:27 -0400 |
| commit | c5db16ad6cc15c261639c0105cfff72df4122790 (patch) | |
| tree | cbca9e6f752c2aeb193076c21352c818f9318d86 | |
| parent | caf8a518d73e71c4073ef1bd5c369e80d27ebf2c (diff) | |
iommu/amd: Don't free pasid_state in mn_release path
The mmu_notifier state is part of pasid_state so it can't be
freed in the mn_release path. Free the pasid_state after
mmu_notifer_unregister has completed.
Signed-off-by: Joerg Roedel <jroedel@suse.de>
Tested-by: Oded Gabbay <Oded.Gabbay@amd.com>
| -rw-r--r-- | drivers/iommu/amd_iommu_v2.c | 10 |
1 files changed, 7 insertions, 3 deletions
diff --git a/drivers/iommu/amd_iommu_v2.c b/drivers/iommu/amd_iommu_v2.c index 1fdd22c3bc04..a621552e715d 100644 --- a/drivers/iommu/amd_iommu_v2.c +++ b/drivers/iommu/amd_iommu_v2.c | |||
| @@ -312,8 +312,6 @@ static void __unbind_pasid(struct pasid_state *pasid_state) | |||
| 312 | 312 | ||
| 313 | /* Make sure no more pending faults are in the queue */ | 313 | /* Make sure no more pending faults are in the queue */ |
| 314 | flush_workqueue(iommu_wq); | 314 | flush_workqueue(iommu_wq); |
| 315 | |||
| 316 | put_pasid_state(pasid_state); /* Reference taken in bind() function */ | ||
| 317 | } | 315 | } |
| 318 | 316 | ||
| 319 | static void unbind_pasid(struct device_state *dev_state, int pasid) | 317 | static void unbind_pasid(struct device_state *dev_state, int pasid) |
| @@ -325,7 +323,7 @@ static void unbind_pasid(struct device_state *dev_state, int pasid) | |||
| 325 | return; | 323 | return; |
| 326 | 324 | ||
| 327 | __unbind_pasid(pasid_state); | 325 | __unbind_pasid(pasid_state); |
| 328 | put_pasid_state_wait(pasid_state); /* Reference taken in this function */ | 326 | put_pasid_state(pasid_state); /* Reference taken in this function */ |
| 329 | } | 327 | } |
| 330 | 328 | ||
| 331 | static void free_pasid_states_level1(struct pasid_state **tbl) | 329 | static void free_pasid_states_level1(struct pasid_state **tbl) |
| @@ -371,6 +369,9 @@ static void free_pasid_states(struct device_state *dev_state) | |||
| 371 | * unbind the PASID | 369 | * unbind the PASID |
| 372 | */ | 370 | */ |
| 373 | mmu_notifier_unregister(&pasid_state->mn, pasid_state->mm); | 371 | mmu_notifier_unregister(&pasid_state->mn, pasid_state->mm); |
| 372 | |||
| 373 | put_pasid_state_wait(pasid_state); /* Reference taken in | ||
| 374 | amd_iommu_pasid_bind */ | ||
| 374 | } | 375 | } |
| 375 | 376 | ||
| 376 | if (dev_state->pasid_levels == 2) | 377 | if (dev_state->pasid_levels == 2) |
| @@ -690,6 +691,7 @@ out_unregister: | |||
| 690 | mmu_notifier_unregister(&pasid_state->mn, pasid_state->mm); | 691 | mmu_notifier_unregister(&pasid_state->mn, pasid_state->mm); |
| 691 | 692 | ||
| 692 | out_free: | 693 | out_free: |
| 694 | mmput(pasid_state->mm); | ||
| 693 | free_pasid_state(pasid_state); | 695 | free_pasid_state(pasid_state); |
| 694 | 696 | ||
| 695 | out: | 697 | out: |
| @@ -730,6 +732,8 @@ void amd_iommu_unbind_pasid(struct pci_dev *pdev, int pasid) | |||
| 730 | /* This will call the mn_release function and unbind the PASID */ | 732 | /* This will call the mn_release function and unbind the PASID */ |
| 731 | mmu_notifier_unregister(&pasid_state->mn, pasid_state->mm); | 733 | mmu_notifier_unregister(&pasid_state->mn, pasid_state->mm); |
| 732 | 734 | ||
| 735 | put_pasid_state_wait(pasid_state); /* Reference taken in | ||
| 736 | amd_iommu_pasid_bind */ | ||
| 733 | out: | 737 | out: |
| 734 | put_device_state(dev_state); | 738 | put_device_state(dev_state); |
| 735 | } | 739 | } |
