aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kernel/io_apic_64.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/x86/kernel/io_apic_64.c')
-rw-r--r--arch/x86/kernel/io_apic_64.c59
1 files changed, 58 insertions, 1 deletions
diff --git a/arch/x86/kernel/io_apic_64.c b/arch/x86/kernel/io_apic_64.c
index b3c2d268d708..953328b55a30 100644
--- a/arch/x86/kernel/io_apic_64.c
+++ b/arch/x86/kernel/io_apic_64.c
@@ -31,6 +31,7 @@
31#include <linux/sysdev.h> 31#include <linux/sysdev.h>
32#include <linux/msi.h> 32#include <linux/msi.h>
33#include <linux/htirq.h> 33#include <linux/htirq.h>
34#include <linux/dmar.h>
34#ifdef CONFIG_ACPI 35#ifdef CONFIG_ACPI
35#include <acpi/acpi_bus.h> 36#include <acpi/acpi_bus.h>
36#endif 37#endif
@@ -2031,8 +2032,64 @@ void arch_teardown_msi_irq(unsigned int irq)
2031 destroy_irq(irq); 2032 destroy_irq(irq);
2032} 2033}
2033 2034
2034#endif /* CONFIG_PCI_MSI */ 2035#ifdef CONFIG_DMAR
2036#ifdef CONFIG_SMP
2037static void dmar_msi_set_affinity(unsigned int irq, cpumask_t mask)
2038{
2039 struct irq_cfg *cfg = irq_cfg + irq;
2040 struct msi_msg msg;
2041 unsigned int dest;
2042 cpumask_t tmp;
2043
2044 cpus_and(tmp, mask, cpu_online_map);
2045 if (cpus_empty(tmp))
2046 return;
2047
2048 if (assign_irq_vector(irq, mask))
2049 return;
2050
2051 cpus_and(tmp, cfg->domain, mask);
2052 dest = cpu_mask_to_apicid(tmp);
2053
2054 dmar_msi_read(irq, &msg);
2055
2056 msg.data &= ~MSI_DATA_VECTOR_MASK;
2057 msg.data |= MSI_DATA_VECTOR(cfg->vector);
2058 msg.address_lo &= ~MSI_ADDR_DEST_ID_MASK;
2059 msg.address_lo |= MSI_ADDR_DEST_ID(dest);
2060
2061 dmar_msi_write(irq, &msg);
2062 irq_desc[irq].affinity = mask;
2063}
2064#endif /* CONFIG_SMP */
2065
2066struct irq_chip dmar_msi_type = {
2067 .name = "DMAR_MSI",
2068 .unmask = dmar_msi_unmask,
2069 .mask = dmar_msi_mask,
2070 .ack = ack_apic_edge,
2071#ifdef CONFIG_SMP
2072 .set_affinity = dmar_msi_set_affinity,
2073#endif
2074 .retrigger = ioapic_retrigger_irq,
2075};
2076
2077int arch_setup_dmar_msi(unsigned int irq)
2078{
2079 int ret;
2080 struct msi_msg msg;
2081
2082 ret = msi_compose_msg(NULL, irq, &msg);
2083 if (ret < 0)
2084 return ret;
2085 dmar_msi_write(irq, &msg);
2086 set_irq_chip_and_handler_name(irq, &dmar_msi_type, handle_edge_irq,
2087 "edge");
2088 return 0;
2089}
2090#endif
2035 2091
2092#endif /* CONFIG_PCI_MSI */
2036/* 2093/*
2037 * Hypertransport interrupt support 2094 * Hypertransport interrupt support
2038 */ 2095 */