]> git.itanic.dy.fi Git - linux-stable/commitdiff
Revert "iommu/vt-d: Fix possible recursive locking in intel_iommu_init()"
authorLu Baolu <baolu.lu@linux.intel.com>
Wed, 21 Sep 2022 02:40:53 +0000 (10:40 +0800)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 23 Sep 2022 12:14:06 +0000 (14:14 +0200)
commit 7ebb5f8e001037efbdf18afabbbebf71bd98825e upstream.

This reverts commit 9cd4f1434479f1ac25c440c421fbf52069079914.

Some issues were reported on the original commit. Some thunderbolt devices
don't work anymore due to the following DMA fault.

DMAR: DRHD: handling fault status reg 2
DMAR: [INTR-REMAP] Request device [09:00.0] fault index 0x8080
      [fault reason 0x25]
      Blocked a compatibility format interrupt request

Bring it back for now to avoid functional regression.

Fixes: 9cd4f1434479f ("iommu/vt-d: Fix possible recursive locking in intel_iommu_init()")
Link: https://lore.kernel.org/linux-iommu/485A6EA5-6D58-42EA-B298-8571E97422DE@getmailspring.com/
Link: https://bugzilla.kernel.org/show_bug.cgi?id=216497
Cc: Mika Westerberg <mika.westerberg@linux.intel.com>
Cc: <stable@vger.kernel.org> # 5.19.x
Reported-and-tested-by: George Hilliard <thirtythreeforty@gmail.com>
Signed-off-by: Lu Baolu <baolu.lu@linux.intel.com>
Link: https://lore.kernel.org/r/20220920081701.3453504-1-baolu.lu@linux.intel.com
Signed-off-by: Joerg Roedel <jroedel@suse.de>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/iommu/intel/dmar.c
drivers/iommu/intel/iommu.c
include/linux/dmar.h

index fc8c1420c0b696e7b4a854412214b377da7a3827..64b14ac4c7b02aa37de001eccd6e8d270533010a 100644 (file)
@@ -2368,13 +2368,6 @@ static int dmar_device_hotplug(acpi_handle handle, bool insert)
        if (!dmar_in_use())
                return 0;
 
-       /*
-        * It's unlikely that any I/O board is hot added before the IOMMU
-        * subsystem is initialized.
-        */
-       if (IS_ENABLED(CONFIG_INTEL_IOMMU) && !intel_iommu_enabled)
-               return -EOPNOTSUPP;
-
        if (dmar_detect_dsm(handle, DMAR_DSM_FUNC_DRHD)) {
                tmp = handle;
        } else {
index c0464959cbcdbea37592acad0d1e453273dfbc59..861a239d905a42461102e3173573abf9f8316767 100644 (file)
@@ -3133,7 +3133,13 @@ static int __init init_dmars(void)
 
 #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;
                }
@@ -4039,6 +4045,7 @@ int __init intel_iommu_init(void)
        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");
@@ -4051,6 +4058,16 @@ int __init intel_iommu_init(void)
                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();
 
@@ -4098,9 +4115,11 @@ int __init intel_iommu_init(void)
                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
@@ -4118,11 +4137,13 @@ int __init intel_iommu_init(void)
                                       "%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");
 
@@ -4133,15 +4154,17 @@ int __init intel_iommu_init(void)
 
                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;
 }
 
index f3a3d95df5325996d7ef596456be36f8747c3f9e..cbd714a198a0a3664d96c119b9f486e56b81151a 100644 (file)
@@ -69,7 +69,6 @@ struct dmar_pci_notify_info {
 
 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,           \
@@ -93,8 +92,7 @@ extern int intel_iommu_enabled;
 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())