aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/iommu/intel-iommu.c
diff options
context:
space:
mode:
authorJiang Liu <jiang.liu@linux.intel.com>2014-02-19 01:07:33 -0500
committerJoerg Roedel <joro@8bytes.org>2014-03-04 11:51:05 -0500
commit3a5670e8ac932c10a3e50d9dc0ab1da4cc3041d7 (patch)
tree83a870c5951c2deafcf7eef4fc2212bb937f1b6e /drivers/iommu/intel-iommu.c
parentb683b230a244c3b2b3f6f3292e59d4a63298528b (diff)
iommu/vt-d: Introduce a rwsem to protect global data structures
Introduce a global rwsem dmar_global_lock, which will be used to protect DMAR related global data structures from DMAR/PCI/memory device hotplug operations in process context. DMA and interrupt remapping related data structures are read most, and only change when memory/PCI/DMAR hotplug event happens. So a global rwsem solution is adopted for balance between simplicity and performance. For interrupt remapping driver, function intel_irq_remapping_supported(), dmar_table_init(), intel_enable_irq_remapping(), disable_irq_remapping(), reenable_irq_remapping() and enable_drhd_fault_handling() etc are called during booting, suspending and resuming with interrupt disabled, so no need to take the global lock. For interrupt remapping entry allocation, the locking model is: down_read(&dmar_global_lock); /* Find corresponding iommu */ iommu = map_hpet_to_ir(id); if (iommu) /* * Allocate remapping entry and mark entry busy, * the IOMMU won't be hot-removed until the * allocated entry has been released. */ index = alloc_irte(iommu, irq, 1); up_read(&dmar_global_lock); For DMA remmaping driver, we only uses the dmar_global_lock rwsem to protect functions which are only called in process context. For any function which may be called in interrupt context, we will use RCU to protect them in following patches. Signed-off-by: Jiang Liu <jiang.liu@linux.intel.com> Signed-off-by: Joerg Roedel <joro@8bytes.org>
Diffstat (limited to 'drivers/iommu/intel-iommu.c')
-rw-r--r--drivers/iommu/intel-iommu.c22
1 files changed, 13 insertions, 9 deletions
diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c
index bb98e37f2cf7..50d639a2df88 100644
--- a/drivers/iommu/intel-iommu.c
+++ b/drivers/iommu/intel-iommu.c
@@ -3637,11 +3637,13 @@ static int device_notifier(struct notifier_block *nb,
3637 if (!domain) 3637 if (!domain)
3638 return 0; 3638 return 0;
3639 3639
3640 down_read(&dmar_global_lock);
3640 domain_remove_one_dev_info(domain, pdev); 3641 domain_remove_one_dev_info(domain, pdev);
3641 if (!(domain->flags & DOMAIN_FLAG_VIRTUAL_MACHINE) && 3642 if (!(domain->flags & DOMAIN_FLAG_VIRTUAL_MACHINE) &&
3642 !(domain->flags & DOMAIN_FLAG_STATIC_IDENTITY) && 3643 !(domain->flags & DOMAIN_FLAG_STATIC_IDENTITY) &&
3643 list_empty(&domain->devices)) 3644 list_empty(&domain->devices))
3644 domain_exit(domain); 3645 domain_exit(domain);
3646 up_read(&dmar_global_lock);
3645 3647
3646 return 0; 3648 return 0;
3647} 3649}
@@ -3659,6 +3661,13 @@ int __init intel_iommu_init(void)
3659 /* VT-d is required for a TXT/tboot launch, so enforce that */ 3661 /* VT-d is required for a TXT/tboot launch, so enforce that */
3660 force_on = tboot_force_iommu(); 3662 force_on = tboot_force_iommu();
3661 3663
3664 if (iommu_init_mempool()) {
3665 if (force_on)
3666 panic("tboot: Failed to initialize iommu memory\n");
3667 return -ENOMEM;
3668 }
3669
3670 down_write(&dmar_global_lock);
3662 if (dmar_table_init()) { 3671 if (dmar_table_init()) {
3663 if (force_on) 3672 if (force_on)
3664 panic("tboot: Failed to initialize DMAR table\n"); 3673 panic("tboot: Failed to initialize DMAR table\n");
@@ -3681,12 +3690,6 @@ int __init intel_iommu_init(void)
3681 if (no_iommu || dmar_disabled) 3690 if (no_iommu || dmar_disabled)
3682 goto out_free_dmar; 3691 goto out_free_dmar;
3683 3692
3684 if (iommu_init_mempool()) {
3685 if (force_on)
3686 panic("tboot: Failed to initialize iommu memory\n");
3687 goto out_free_dmar;
3688 }
3689
3690 if (list_empty(&dmar_rmrr_units)) 3693 if (list_empty(&dmar_rmrr_units))
3691 printk(KERN_INFO "DMAR: No RMRR found\n"); 3694 printk(KERN_INFO "DMAR: No RMRR found\n");
3692 3695
@@ -3696,7 +3699,7 @@ int __init intel_iommu_init(void)
3696 if (dmar_init_reserved_ranges()) { 3699 if (dmar_init_reserved_ranges()) {
3697 if (force_on) 3700 if (force_on)
3698 panic("tboot: Failed to reserve iommu ranges\n"); 3701 panic("tboot: Failed to reserve iommu ranges\n");
3699 goto out_free_mempool; 3702 goto out_free_reserved_range;
3700 } 3703 }
3701 3704
3702 init_no_remapping_devices(); 3705 init_no_remapping_devices();
@@ -3708,6 +3711,7 @@ int __init intel_iommu_init(void)
3708 printk(KERN_ERR "IOMMU: dmar init failed\n"); 3711 printk(KERN_ERR "IOMMU: dmar init failed\n");
3709 goto out_free_reserved_range; 3712 goto out_free_reserved_range;
3710 } 3713 }
3714 up_write(&dmar_global_lock);
3711 printk(KERN_INFO 3715 printk(KERN_INFO
3712 "PCI-DMA: Intel(R) Virtualization Technology for Directed I/O\n"); 3716 "PCI-DMA: Intel(R) Virtualization Technology for Directed I/O\n");
3713 3717
@@ -3729,10 +3733,10 @@ int __init intel_iommu_init(void)
3729 3733
3730out_free_reserved_range: 3734out_free_reserved_range:
3731 put_iova_domain(&reserved_iova_list); 3735 put_iova_domain(&reserved_iova_list);
3732out_free_mempool:
3733 iommu_exit_mempool();
3734out_free_dmar: 3736out_free_dmar:
3735 intel_iommu_free_dmars(); 3737 intel_iommu_free_dmars();
3738 up_write(&dmar_global_lock);
3739 iommu_exit_mempool();
3736 return ret; 3740 return ret;
3737} 3741}
3738 3742