aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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 */