static int __init intel_prepare_irq_remapping(void) { struct dmar_drhd_unit *drhd; struct intel_iommu *iommu; if (irq_remap_broken) { printk(KERN_WARNING "This system BIOS has enabled interrupt remapping\n" "on a chipset that contains an erratum making that\n" "feature unstable. To maintain system stability\n" "interrupt remapping is being disabled. Please\n" "contact your BIOS vendor for an update\n"); add_taint(TAINT_FIRMWARE_WORKAROUND, LOCKDEP_STILL_OK); return -ENODEV; } if (dmar_table_init() < 0) return -ENODEV; if (!dmar_ir_support()) return -ENODEV; if (parse_ioapics_under_ir() != 1) { printk(KERN_INFO "Not enabling interrupt remapping\n"); goto error; } /* First make sure all IOMMUs support IRQ remapping */ for_each_iommu(iommu, drhd) if (!ecap_ir_support(iommu->ecap)) goto error; /* Do the allocations early */ for_each_iommu(iommu, drhd) if (intel_setup_irq_remapping(iommu)) goto error; return 0; error: intel_cleanup_irq_remapping(); return -ENODEV; }
static int __init intel_prepare_irq_remapping(void) { struct dmar_drhd_unit *drhd; struct intel_iommu *iommu; int eim = 0; if (irq_remap_broken) { pr_warn("This system BIOS has enabled interrupt remapping\n" "on a chipset that contains an erratum making that\n" "feature unstable. To maintain system stability\n" "interrupt remapping is being disabled. Please\n" "contact your BIOS vendor for an update\n"); add_taint(TAINT_FIRMWARE_WORKAROUND, LOCKDEP_STILL_OK); return -ENODEV; } if (dmar_table_init() < 0) return -ENODEV; if (!dmar_ir_support()) return -ENODEV; if (parse_ioapics_under_ir()) { pr_info("Not enabling interrupt remapping\n"); goto error; } /* First make sure all IOMMUs support IRQ remapping */ for_each_iommu(iommu, drhd) if (!ecap_ir_support(iommu->ecap)) goto error; /* Detect remapping mode: lapic or x2apic */ if (x2apic_supported()) { eim = !dmar_x2apic_optout(); if (!eim) { pr_info("x2apic is disabled because BIOS sets x2apic opt out bit."); pr_info("Use 'intremap=no_x2apic_optout' to override the BIOS setting.\n"); } } for_each_iommu(iommu, drhd) { if (eim && !ecap_eim_support(iommu->ecap)) { pr_info("%s does not support EIM\n", iommu->name); eim = 0; } } eim_mode = eim; if (eim) pr_info("Queued invalidation will be enabled to support x2apic and Intr-remapping.\n"); /* Do the initializations early */ for_each_iommu(iommu, drhd) { if (intel_setup_irq_remapping(iommu)) { pr_err("Failed to setup irq remapping for %s\n", iommu->name); goto error; } } return 0; error: intel_cleanup_irq_remapping(); return -ENODEV; }
void __init enable_IR_x2apic(void) { unsigned long flags; struct IO_APIC_route_entry **ioapic_entries = NULL; int ret, x2apic_enabled = 0; int dmar_table_init_ret = 0; #ifdef CONFIG_INTR_REMAP dmar_table_init_ret = dmar_table_init(); if (dmar_table_init_ret) pr_debug("dmar_table_init() failed with %d:\n", dmar_table_init_ret); #endif ioapic_entries = alloc_ioapic_entries(); if (!ioapic_entries) { pr_err("Allocate ioapic_entries failed\n"); goto out; } ret = save_IO_APIC_setup(ioapic_entries); if (ret) { pr_info("Saving IO-APIC state failed: %d\n", ret); goto out; } local_irq_save(flags); mask_8259A(); mask_IO_APIC_setup(ioapic_entries); if (dmar_table_init_ret) ret = 0; else ret = enable_IR(); if (!ret) { if (max_physical_apicid > 255 || !kvm_para_available()) goto nox2apic; x2apic_force_phys(); } x2apic_enabled = 1; if (x2apic_supported() && !x2apic_mode) { x2apic_mode = 1; enable_x2apic(); pr_info("Enabled x2apic\n"); } nox2apic: if (!ret) restore_IO_APIC_setup(ioapic_entries); unmask_8259A(); local_irq_restore(flags); out: if (ioapic_entries) free_ioapic_entries(ioapic_entries); if (x2apic_enabled) return; if (x2apic_preenabled) panic("x2apic: enabled by BIOS but kernel init failed."); else if (cpu_has_x2apic) pr_info("Not enabling x2apic, Intr-remapping init failed.\n"); }