]> err.no Git - linux-2.6/blobdiff - arch/x86/kernel/io_apic_64.c
x86: printk kernel version in WARN_ON and other dump_stack users
[linux-2.6] / arch / x86 / kernel / io_apic_64.c
index 966fa10624911c93fd042e37440f9d101e10693f..953328b55a30503c58f2f8b3ed0f30939ff4047c 100644 (file)
@@ -31,6 +31,7 @@
 #include <linux/sysdev.h>
 #include <linux/msi.h>
 #include <linux/htirq.h>
+#include <linux/dmar.h>
 #ifdef CONFIG_ACPI
 #include <acpi/acpi_bus.h>
 #endif
@@ -875,6 +876,10 @@ static void __init setup_IO_APIC_irqs(void)
                                apic_printk(APIC_VERBOSE, ", %d-%d", mp_ioapics[apic].mpc_apicid, pin);
                        continue;
                }
+               if (!first_notcon) {
+                       apic_printk(APIC_VERBOSE, " not connected.\n");
+                       first_notcon = 1;
+               }
 
                irq = pin_2_irq(idx, apic, pin);
                add_pin_to_irq(irq, apic, pin);
@@ -885,7 +890,7 @@ static void __init setup_IO_APIC_irqs(void)
        }
 
        if (!first_notcon)
-               apic_printk(APIC_VERBOSE," not connected.\n");
+               apic_printk(APIC_VERBOSE, " not connected.\n");
 }
 
 /*
@@ -1766,7 +1771,7 @@ __setup("no_timer_check", notimercheck);
 
 /*
  *
- * IRQ's that are handled by the PIC in the MPS IOAPIC case.
+ * IRQs that are handled by the PIC in the MPS IOAPIC case.
  * - IRQ2 is the cascade IRQ, and cannot be a io-apic IRQ.
  *   Linux doesn't really care, as it's not actually used
  *   for any interrupt handling anyway.
@@ -1845,7 +1850,7 @@ static struct sysdev_class ioapic_sysdev_class = {
 static int __init ioapic_init_sysfs(void)
 {
        struct sys_device * dev;
-       int i, size, error = 0;
+       int i, size, error;
 
        error = sysdev_class_register(&ioapic_sysdev_class);
        if (error)
@@ -1854,12 +1859,11 @@ static int __init ioapic_init_sysfs(void)
        for (i = 0; i < nr_ioapics; i++ ) {
                size = sizeof(struct sys_device) + nr_ioapic_registers[i]
                        * sizeof(struct IO_APIC_route_entry);
-               mp_ioapic_data[i] = kmalloc(size, GFP_KERNEL);
+               mp_ioapic_data[i] = kzalloc(size, GFP_KERNEL);
                if (!mp_ioapic_data[i]) {
                        printk(KERN_ERR "Can't suspend/resume IOAPIC %d\n", i);
                        continue;
                }
-               memset(mp_ioapic_data[i], 0, size);
                dev = &mp_ioapic_data[i]->dev;
                dev->id = i;
                dev->cls = &ioapic_sysdev_class;
@@ -1918,7 +1922,7 @@ void destroy_irq(unsigned int irq)
 }
 
 /*
- * MSI mesage composition
+ * MSI message composition
  */
 #ifdef CONFIG_PCI_MSI
 static int msi_compose_msg(struct pci_dev *pdev, unsigned int irq, struct msi_msg *msg)
@@ -2028,8 +2032,64 @@ void arch_teardown_msi_irq(unsigned int irq)
        destroy_irq(irq);
 }
 
-#endif /* CONFIG_PCI_MSI */
+#ifdef CONFIG_DMAR
+#ifdef CONFIG_SMP
+static void dmar_msi_set_affinity(unsigned int irq, cpumask_t mask)
+{
+       struct irq_cfg *cfg = irq_cfg + irq;
+       struct msi_msg msg;
+       unsigned int dest;
+       cpumask_t tmp;
 
+       cpus_and(tmp, mask, cpu_online_map);
+       if (cpus_empty(tmp))
+               return;
+
+       if (assign_irq_vector(irq, mask))
+               return;
+
+       cpus_and(tmp, cfg->domain, mask);
+       dest = cpu_mask_to_apicid(tmp);
+
+       dmar_msi_read(irq, &msg);
+
+       msg.data &= ~MSI_DATA_VECTOR_MASK;
+       msg.data |= MSI_DATA_VECTOR(cfg->vector);
+       msg.address_lo &= ~MSI_ADDR_DEST_ID_MASK;
+       msg.address_lo |= MSI_ADDR_DEST_ID(dest);
+
+       dmar_msi_write(irq, &msg);
+       irq_desc[irq].affinity = mask;
+}
+#endif /* CONFIG_SMP */
+
+struct irq_chip dmar_msi_type = {
+       .name = "DMAR_MSI",
+       .unmask = dmar_msi_unmask,
+       .mask = dmar_msi_mask,
+       .ack = ack_apic_edge,
+#ifdef CONFIG_SMP
+       .set_affinity = dmar_msi_set_affinity,
+#endif
+       .retrigger = ioapic_retrigger_irq,
+};
+
+int arch_setup_dmar_msi(unsigned int irq)
+{
+       int ret;
+       struct msi_msg msg;
+
+       ret = msi_compose_msg(NULL, irq, &msg);
+       if (ret < 0)
+               return ret;
+       dmar_msi_write(irq, &msg);
+       set_irq_chip_and_handler_name(irq, &dmar_msi_type, handle_edge_irq,
+               "edge");
+       return 0;
+}
+#endif
+
+#endif /* CONFIG_PCI_MSI */
 /*
  * Hypertransport interrupt support
  */