]> Git Repo - linux.git/commitdiff
iommu/vt-d: Allocate DMAR fault interrupts locally
authorDimitri Sivanich <[email protected]>
Wed, 24 Apr 2024 07:16:29 +0000 (15:16 +0800)
committerJoerg Roedel <[email protected]>
Fri, 26 Apr 2024 09:57:36 +0000 (11:57 +0200)
The Intel IOMMU code currently tries to allocate all DMAR fault interrupt
vectors on the boot cpu.  On large systems with high DMAR counts this
results in vector exhaustion, and most of the vectors are not initially
allocated socket local.

Instead, have a cpu on each node do the vector allocation for the DMARs on
that node.  The boot cpu still does the allocation for its node during its
boot sequence.

Signed-off-by: Dimitri Sivanich <[email protected]>
Reviewed-by: Kevin Tian <[email protected]>
Link: https://lore.kernel.org/r/[email protected]
Signed-off-by: Lu Baolu <[email protected]>
Signed-off-by: Joerg Roedel <[email protected]>
drivers/iommu/amd/amd_iommu.h
drivers/iommu/amd/init.c
drivers/iommu/intel/dmar.c
drivers/iommu/irq_remapping.c
drivers/iommu/irq_remapping.h
include/linux/dmar.h

index f482aab420f7873bb12da67684c5cc23a0cda05a..410c360e7e245880e06faaf0f844d300a0020949 100644 (file)
@@ -33,7 +33,7 @@ int amd_iommu_prepare(void);
 int amd_iommu_enable(void);
 void amd_iommu_disable(void);
 int amd_iommu_reenable(int mode);
-int amd_iommu_enable_faulting(void);
+int amd_iommu_enable_faulting(unsigned int cpu);
 extern int amd_iommu_guest_ir;
 extern enum io_pgtable_fmt amd_iommu_pgtable;
 extern int amd_iommu_gpt_level;
index ac6754a85f3507ee88bd3847359a53292a14dc9f..8085e13e0100d76f2b7cf1012964e5c01e09b8a9 100644 (file)
@@ -3392,7 +3392,7 @@ int amd_iommu_reenable(int mode)
        return 0;
 }
 
-int __init amd_iommu_enable_faulting(void)
+int __init amd_iommu_enable_faulting(unsigned int cpu)
 {
        /* We enable MSI later when PCI is initialized */
        return 0;
index 351be945521468fdc583bcff03ce606cde1e839c..932e0c10c0fe17339bd4f4ec247796f86bc5ed98 100644 (file)
@@ -2121,7 +2121,7 @@ int dmar_set_interrupt(struct intel_iommu *iommu)
        return ret;
 }
 
-int __init enable_drhd_fault_handling(void)
+int enable_drhd_fault_handling(unsigned int cpu)
 {
        struct dmar_drhd_unit *drhd;
        struct intel_iommu *iommu;
@@ -2131,7 +2131,12 @@ int __init enable_drhd_fault_handling(void)
         */
        for_each_iommu(iommu, drhd) {
                u32 fault_status;
-               int ret = dmar_set_interrupt(iommu);
+               int ret;
+
+               if (iommu->irq || iommu->node != cpu_to_node(cpu))
+                       continue;
+
+               ret = dmar_set_interrupt(iommu);
 
                if (ret) {
                        pr_err("DRHD %Lx: failed to enable fault, interrupt, ret %d\n",
index ee59647c20501ec29792a19b381b0d133313cac8..2f7281ccc05f64778a7f70309dd054192bb1ae74 100644 (file)
@@ -151,7 +151,10 @@ int __init irq_remap_enable_fault_handling(void)
        if (!remap_ops->enable_faulting)
                return -ENODEV;
 
-       return remap_ops->enable_faulting();
+       cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "dmar:enable_fault_handling",
+                         remap_ops->enable_faulting, NULL);
+
+       return remap_ops->enable_faulting(smp_processor_id());
 }
 
 void panic_if_irq_remap(const char *msg)
index 8c89cb947cdb29e072f8218afa26601c8ee3ef7c..0d6f140b5e0148c06452de0dcd916eb39a5589ef 100644 (file)
@@ -41,7 +41,7 @@ struct irq_remap_ops {
        int  (*reenable)(int);
 
        /* Enable fault handling */
-       int  (*enable_faulting)(void);
+       int  (*enable_faulting)(unsigned int);
 };
 
 extern struct irq_remap_ops intel_irq_remap_ops;
index e34b601b71fd25c4b68c6e6c44075fea16275cd0..499bb2c634832311c4edfe7441baa0fa25f2c00d 100644 (file)
@@ -117,7 +117,7 @@ extern int dmar_remove_dev_scope(struct dmar_pci_notify_info *info,
                                 int count);
 /* Intel IOMMU detection */
 void detect_intel_iommu(void);
-extern int enable_drhd_fault_handling(void);
+extern int enable_drhd_fault_handling(unsigned int cpu);
 extern int dmar_device_add(acpi_handle handle);
 extern int dmar_device_remove(acpi_handle handle);
 
This page took 0.099403 seconds and 4 git commands to generate.