diff options
-rw-r--r-- | arch/i386/kernel/io_apic.c | 70 | ||||
-rw-r--r-- | include/asm-i386/msi.h | 7 | ||||
-rw-r--r-- | include/asm-i386/msidef.h | 47 |
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 | ||
2540 | static 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 | |||
2574 | static void msi_msg_teardown(unsigned int irq) | ||
2575 | { | ||
2576 | return; | ||
2577 | } | ||
2578 | |||
2579 | static 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 | |||
2595 | struct 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) | 12 | extern struct msi_ops arch_msi_ops; |
13 | #define MSI_TARGET_CPU_SHIFT 12 | ||
14 | |||
15 | extern struct msi_ops msi_apic_ops; | ||
16 | 13 | ||
17 | static inline int msi_arch_init(void) | 14 | static 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 */ | ||