aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEric W. Biederman <ebiederm@xmission.com>2006-10-04 05:16:43 -0400
committerLinus Torvalds <torvalds@g5.osdl.org>2006-10-04 10:55:28 -0400
commit2d3fcc1c54df2f49674e1f7c99d4800ed1d51902 (patch)
tree7cf478bc419f8f0c17be929b5ffdac6fc4236b70
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>
-rw-r--r--arch/i386/kernel/io_apic.c70
-rw-r--r--include/asm-i386/msi.h7
-rw-r--r--include/asm-i386/msidef.h47
3 files changed, 119 insertions, 5 deletions
diff --git a/arch/i386/kernel/io_apic.c b/arch/i386/kernel/io_apic.c
index fca689cfb0c9..85e7d5d465a2 100644
--- a/arch/i386/kernel/io_apic.c
+++ b/arch/i386/kernel/io_apic.c
@@ -31,6 +31,7 @@
31#include <linux/acpi.h> 31#include <linux/acpi.h>
32#include <linux/module.h> 32#include <linux/module.h>
33#include <linux/sysdev.h> 33#include <linux/sysdev.h>
34#include <linux/pci.h>
34 35
35#include <asm/io.h> 36#include <asm/io.h>
36#include <asm/smp.h> 37#include <asm/smp.h>
@@ -38,6 +39,7 @@
38#include <asm/timer.h> 39#include <asm/timer.h>
39#include <asm/i8259.h> 40#include <asm/i8259.h>
40#include <asm/nmi.h> 41#include <asm/nmi.h>
42#include <asm/msidef.h>
41 43
42#include <mach_apic.h> 44#include <mach_apic.h>
43#include <mach_apicdef.h> 45#include <mach_apicdef.h>
@@ -2531,6 +2533,74 @@ void destroy_irq(unsigned int irq)
2531} 2533}
2532#endif /* CONFIG_PCI_MSI */ 2534#endif /* CONFIG_PCI_MSI */
2533 2535
2536/*
2537 * MSI mesage composition
2538 */
2539#ifdef CONFIG_PCI_MSI
2540static int msi_msg_setup(struct pci_dev *pdev, unsigned int irq, struct msi_msg *msg)
2541{
2542 /* For now always this code always uses physical delivery
2543 * mode.
2544 */
2545 int vector;
2546 unsigned dest;
2547
2548 vector = assign_irq_vector(irq);
2549 if (vector >= 0) {
2550 dest = cpu_mask_to_apicid(TARGET_CPUS);
2551
2552 msg->address_hi = MSI_ADDR_BASE_HI;
2553 msg->address_lo =
2554 MSI_ADDR_BASE_LO |
2555 ((INT_DEST_MODE == 0) ?
2556 MSI_ADDR_DEST_MODE_PHYSICAL:
2557 MSI_ADDR_DEST_MODE_LOGICAL) |
2558 ((INT_DELIVERY_MODE != dest_LowestPrio) ?
2559 MSI_ADDR_REDIRECTION_CPU:
2560 MSI_ADDR_REDIRECTION_LOWPRI) |
2561 MSI_ADDR_DEST_ID(dest);
2562
2563 msg->data =
2564 MSI_DATA_TRIGGER_EDGE |
2565 MSI_DATA_LEVEL_ASSERT |
2566 ((INT_DELIVERY_MODE != dest_LowestPrio) ?
2567 MSI_DATA_DELIVERY_FIXED:
2568 MSI_DATA_DELIVERY_LOWPRI) |
2569 MSI_DATA_VECTOR(vector);
2570 }
2571 return vector;
2572}
2573
2574static void msi_msg_teardown(unsigned int irq)
2575{
2576 return;
2577}
2578
2579static void msi_msg_set_affinity(unsigned int irq, cpumask_t mask, struct msi_msg *msg)
2580{
2581 int vector;
2582 unsigned dest;
2583
2584 vector = assign_irq_vector(irq);
2585 if (vector > 0) {
2586 dest = cpu_mask_to_apicid(mask);
2587
2588 msg->data &= ~MSI_DATA_VECTOR_MASK;
2589 msg->data |= MSI_DATA_VECTOR(vector);
2590 msg->address_lo &= ~MSI_ADDR_DEST_ID_MASK;
2591 msg->address_lo |= MSI_ADDR_DEST_ID(dest);
2592 }
2593}
2594
2595struct msi_ops arch_msi_ops = {
2596 .needs_64bit_address = 0,
2597 .setup = msi_msg_setup,
2598 .teardown = msi_msg_teardown,
2599 .target = msi_msg_set_affinity,
2600};
2601
2602#endif /* CONFIG_PCI_MSI */
2603
2534/* -------------------------------------------------------------------------- 2604/* --------------------------------------------------------------------------
2535 ACPI-based IOAPIC Configuration 2605 ACPI-based IOAPIC Configuration
2536 -------------------------------------------------------------------------- */ 2606 -------------------------------------------------------------------------- */
diff --git a/include/asm-i386/msi.h b/include/asm-i386/msi.h
index b11c4b7dfaef..7368a89a0f42 100644
--- a/include/asm-i386/msi.h
+++ b/include/asm-i386/msi.h
@@ -9,14 +9,11 @@
9#include <asm/desc.h> 9#include <asm/desc.h>
10#include <mach_apic.h> 10#include <mach_apic.h>
11 11
12#define LAST_DEVICE_VECTOR (FIRST_SYSTEM_VECTOR - 1) 12extern struct msi_ops arch_msi_ops;
13#define MSI_TARGET_CPU_SHIFT 12
14
15extern struct msi_ops msi_apic_ops;
16 13
17static inline int msi_arch_init(void) 14static inline int msi_arch_init(void)
18{ 15{
19 msi_register(&msi_apic_ops); 16 msi_register(&arch_msi_ops);
20 return 0; 17 return 0;
21} 18}
22 19
diff --git a/include/asm-i386/msidef.h b/include/asm-i386/msidef.h
new file mode 100644
index 000000000000..5b8acddb70fb
--- /dev/null
+++ b/include/asm-i386/msidef.h
@@ -0,0 +1,47 @@
1#ifndef ASM_MSIDEF_H
2#define ASM_MSIDEF_H
3
4/*
5 * Constants for Intel APIC based MSI messages.
6 */
7
8/*
9 * Shifts for MSI data
10 */
11
12#define MSI_DATA_VECTOR_SHIFT 0
13#define MSI_DATA_VECTOR_MASK 0x000000ff
14#define MSI_DATA_VECTOR(v) (((v) << MSI_DATA_VECTOR_SHIFT) & MSI_DATA_VECTOR_MASK)
15
16#define MSI_DATA_DELIVERY_MODE_SHIFT 8
17#define MSI_DATA_DELIVERY_FIXED (0 << MSI_DATA_DELIVERY_MODE_SHIFT)
18#define MSI_DATA_DELIVERY_LOWPRI (1 << MSI_DATA_DELIVERY_MODE_SHIFT)
19
20#define MSI_DATA_LEVEL_SHIFT 14
21#define MSI_DATA_LEVEL_DEASSERT (0 << MSI_DATA_LEVEL_SHIFT)
22#define MSI_DATA_LEVEL_ASSERT (1 << MSI_DATA_LEVEL_SHIFT)
23
24#define MSI_DATA_TRIGGER_SHIFT 15
25#define MSI_DATA_TRIGGER_EDGE (0 << MSI_DATA_TRIGGER_SHIFT)
26#define MSI_DATA_TRIGGER_LEVEL (1 << MSI_DATA_TRIGGER_SHIFT)
27
28/*
29 * Shift/mask fields for msi address
30 */
31
32#define MSI_ADDR_BASE_HI 0
33#define MSI_ADDR_BASE_LO 0xfee00000
34
35#define MSI_ADDR_DEST_MODE_SHIFT 2
36#define MSI_ADDR_DEST_MODE_PHYSICAL (0 << MSI_ADDR_DEST_MODE_SHIFT)
37#define MSI_ADDR_DEST_MODE_LOGICAL (1 << MSI_ADDR_DEST_MODE_SHIFT)
38
39#define MSI_ADDR_REDIRECTION_SHIFT 3
40#define MSI_ADDR_REDIRECTION_CPU (0 << MSI_ADDR_REDIRECTION_SHIFT) /* dedicated cpu */
41#define MSI_ADDR_REDIRECTION_LOWPRI (1 << MSI_ADDR_REDIRECTION_SHIFT) /* lowest priority */
42
43#define MSI_ADDR_DEST_ID_SHIFT 12
44#define MSI_ADDR_DEST_ID_MASK 0x00ffff0
45#define MSI_ADDR_DEST_ID(dest) (((dest) << MSI_ADDR_DEST_ID_SHIFT) & MSI_ADDR_DEST_ID_MASK)
46
47#endif /* ASM_MSIDEF_H */