aboutsummaryrefslogtreecommitdiff
path: root/arch/i386/kernel
diff options
context:
space:
mode:
authorEric W. Biederman <ebiederm@xmission.com>2006-10-04 02:16:43 -0700
committerLinus Torvalds <torvalds@g5.osdl.org>2006-10-04 07:55:28 -0700
commit2d3fcc1c54df2f49674e1f7c99d4800ed1d51902 (patch)
tree7cf478bc419f8f0c17be929b5ffdac6fc4236b70 /arch/i386/kernel
parent589e367f9b9117b3412da0d4e10ea6882db8da84 (diff)
[PATCH] genirq: i386 irq: Move msi message composition into io_apic.c
This removes the hardcoded assumption that irq == vector in the msi composition code, and it allows the msi message composition to setup logical mode, or lowest priorirty delivery mode as we do for other apic interrupts, and with the same selection criteria. Basically this moves the problem of what is in the msi message into the architecture irq management code where it belongs. Not in a generic layer that doesn't have enough information to compose msi messages properly. Signed-off-by: Eric W. Biederman <ebiederm@xmission.com> Cc: Ingo Molnar <mingo@elte.hu> Cc: Thomas Gleixner <tglx@linutronix.de> Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org> Cc: Rajesh Shah <rajesh.shah@intel.com> Cc: Andi Kleen <ak@muc.de> Cc: "Protasevich, Natalie" <Natalie.Protasevich@UNISYS.com> Cc: "Luck, Tony" <tony.luck@intel.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'arch/i386/kernel')
-rw-r--r--arch/i386/kernel/io_apic.c70
1 files changed, 70 insertions, 0 deletions
diff --git a/arch/i386/kernel/io_apic.c b/arch/i386/kernel/io_apic.c
index fca689cfb0c..85e7d5d465a 100644
--- a/arch/i386/kernel/io_apic.c
+++ b/arch/i386/kernel/io_apic.c
@@ -31,6 +31,7 @@
#include <linux/acpi.h>
#include <linux/module.h>
#include <linux/sysdev.h>
+#include <linux/pci.h>
#include <asm/io.h>
#include <asm/smp.h>
@@ -38,6 +39,7 @@
#include <asm/timer.h>
#include <asm/i8259.h>
#include <asm/nmi.h>
+#include <asm/msidef.h>
#include <mach_apic.h>
#include <mach_apicdef.h>
@@ -2531,6 +2533,74 @@ void destroy_irq(unsigned int irq)
}
#endif /* CONFIG_PCI_MSI */
+/*
+ * MSI mesage composition
+ */
+#ifdef CONFIG_PCI_MSI
+static int msi_msg_setup(struct pci_dev *pdev, unsigned int irq, struct msi_msg *msg)
+{
+ /* For now always this code always uses physical delivery
+ * mode.
+ */
+ int vector;
+ unsigned dest;
+
+ vector = assign_irq_vector(irq);
+ if (vector >= 0) {
+ dest = cpu_mask_to_apicid(TARGET_CPUS);
+
+ msg->address_hi = MSI_ADDR_BASE_HI;
+ msg->address_lo =
+ MSI_ADDR_BASE_LO |
+ ((INT_DEST_MODE == 0) ?
+ MSI_ADDR_DEST_MODE_PHYSICAL:
+ MSI_ADDR_DEST_MODE_LOGICAL) |
+ ((INT_DELIVERY_MODE != dest_LowestPrio) ?
+ MSI_ADDR_REDIRECTION_CPU:
+ MSI_ADDR_REDIRECTION_LOWPRI) |
+ MSI_ADDR_DEST_ID(dest);
+
+ msg->data =
+ MSI_DATA_TRIGGER_EDGE |
+ MSI_DATA_LEVEL_ASSERT |
+ ((INT_DELIVERY_MODE != dest_LowestPrio) ?
+ MSI_DATA_DELIVERY_FIXED:
+ MSI_DATA_DELIVERY_LOWPRI) |
+ MSI_DATA_VECTOR(vector);
+ }
+ return vector;
+}
+
+static void msi_msg_teardown(unsigned int irq)
+{
+ return;
+}
+
+static void msi_msg_set_affinity(unsigned int irq, cpumask_t mask, struct msi_msg *msg)
+{
+ int vector;
+ unsigned dest;
+
+ vector = assign_irq_vector(irq);
+ if (vector > 0) {
+ dest = cpu_mask_to_apicid(mask);
+
+ msg->data &= ~MSI_DATA_VECTOR_MASK;
+ msg->data |= MSI_DATA_VECTOR(vector);
+ msg->address_lo &= ~MSI_ADDR_DEST_ID_MASK;
+ msg->address_lo |= MSI_ADDR_DEST_ID(dest);
+ }
+}
+
+struct msi_ops arch_msi_ops = {
+ .needs_64bit_address = 0,
+ .setup = msi_msg_setup,
+ .teardown = msi_msg_teardown,
+ .target = msi_msg_set_affinity,
+};
+
+#endif /* CONFIG_PCI_MSI */
+
/* --------------------------------------------------------------------------
ACPI-based IOAPIC Configuration
-------------------------------------------------------------------------- */