aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/iommu
diff options
context:
space:
mode:
authorJoerg Roedel <jroedel@suse.de>2014-07-08 08:15:45 -0400
committerJoerg Roedel <jroedel@suse.de>2014-07-10 09:36:27 -0400
commitc5db16ad6cc15c261639c0105cfff72df4122790 (patch)
treecbca9e6f752c2aeb193076c21352c818f9318d86 /drivers/iommu
parentcaf8a518d73e71c4073ef1bd5c369e80d27ebf2c (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>
Diffstat (limited to 'drivers/iommu')
-rw-r--r--drivers/iommu/amd_iommu_v2.c10
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
319static void unbind_pasid(struct device_state *dev_state, int pasid) 317static 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
331static void free_pasid_states_level1(struct pasid_state **tbl) 329static 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
692out_free: 693out_free:
694 mmput(pasid_state->mm);
693 free_pasid_state(pasid_state); 695 free_pasid_state(pasid_state);
694 696
695out: 697out:
@@ -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 */
733out: 737out:
734 put_device_state(dev_state); 738 put_device_state(dev_state);
735} 739}