#ifdef CONFIG_INTEL_IOMMU_SVM
                if (pasid_supported(iommu) && ecap_prs(iommu->ecap)) {
+                       /*
+                        * Call dmar_alloc_hwirq() with dmar_global_lock held,
+                        * could cause possible lock race condition.
+                        */
+                       up_write(&dmar_global_lock);
                        ret = intel_svm_enable_prq(iommu);
+                       down_write(&dmar_global_lock);
                        if (ret)
                                goto free_iommu;
                }
        force_on = (!intel_iommu_tboot_noforce && tboot_force_iommu()) ||
                    platform_optin_force_iommu();
 
+       down_write(&dmar_global_lock);
        if (dmar_table_init()) {
                if (force_on)
                        panic("tboot: Failed to initialize DMAR table\n");
                goto out_free_dmar;
        }
 
+       up_write(&dmar_global_lock);
+
+       /*
+        * The bus notifier takes the dmar_global_lock, so lockdep will
+        * complain later when we register it under the lock.
+        */
+       dmar_register_bus_notifier();
+
+       down_write(&dmar_global_lock);
+
        if (!no_iommu)
                intel_iommu_debugfs_init();
 
                pr_err("Initialization failed\n");
                goto out_free_dmar;
        }
+       up_write(&dmar_global_lock);
 
        init_iommu_pm_ops();
 
+       down_read(&dmar_global_lock);
        for_each_active_iommu(iommu, drhd) {
                /*
                 * The flush queue implementation does not perform
                                       "%s", iommu->name);
                iommu_device_register(&iommu->iommu, &intel_iommu_ops, NULL);
        }
+       up_read(&dmar_global_lock);
 
        bus_set_iommu(&pci_bus_type, &intel_iommu_ops);
        if (si_domain && !hw_pass_through)
                register_memory_notifier(&intel_iommu_memory_nb);
 
+       down_read(&dmar_global_lock);
        if (probe_acpi_namespace_devices())
                pr_warn("ACPI name space devices didn't probe correctly\n");
 
 
                iommu_disable_protect_mem_regions(iommu);
        }
+       up_read(&dmar_global_lock);
 
-       intel_iommu_enabled = 1;
-       dmar_register_bus_notifier();
        pr_info("Intel(R) Virtualization Technology for Directed I/O\n");
 
+       intel_iommu_enabled = 1;
+
        return 0;
 
 out_free_dmar:
        intel_iommu_free_dmars();
+       up_write(&dmar_global_lock);
        return ret;
 }
 
 
 
 extern struct rw_semaphore dmar_global_lock;
 extern struct list_head dmar_drhd_units;
-extern int intel_iommu_enabled;
 
 #define for_each_drhd_unit(drhd)                                       \
        list_for_each_entry_rcu(drhd, &dmar_drhd_units, list,           \
 static inline bool dmar_rcu_check(void)
 {
        return rwsem_is_locked(&dmar_global_lock) ||
-              system_state == SYSTEM_BOOTING ||
-              (IS_ENABLED(CONFIG_INTEL_IOMMU) && !intel_iommu_enabled);
+              system_state == SYSTEM_BOOTING;
 }
 
 #define        dmar_rcu_dereference(p) rcu_dereference_check((p), dmar_rcu_check())