diff options
-rw-r--r-- | arch/x86_64/kernel/io_apic.c | 74 | ||||
-rw-r--r-- | include/asm-x86_64/msi.h | 7 | ||||
-rw-r--r-- | include/asm-x86_64/msidef.h | 47 |
3 files changed, 123 insertions, 5 deletions
diff --git a/arch/x86_64/kernel/io_apic.c b/arch/x86_64/kernel/io_apic.c index fd52fcb6fa16..437b6f96cc80 100644 --- a/arch/x86_64/kernel/io_apic.c +++ b/arch/x86_64/kernel/io_apic.c | |||
@@ -26,6 +26,7 @@ | |||
26 | #include <linux/delay.h> | 26 | #include <linux/delay.h> |
27 | #include <linux/sched.h> | 27 | #include <linux/sched.h> |
28 | #include <linux/smp_lock.h> | 28 | #include <linux/smp_lock.h> |
29 | #include <linux/pci.h> | ||
29 | #include <linux/mc146818rtc.h> | 30 | #include <linux/mc146818rtc.h> |
30 | #include <linux/acpi.h> | 31 | #include <linux/acpi.h> |
31 | #include <linux/sysdev.h> | 32 | #include <linux/sysdev.h> |
@@ -41,6 +42,7 @@ | |||
41 | #include <asm/acpi.h> | 42 | #include <asm/acpi.h> |
42 | #include <asm/dma.h> | 43 | #include <asm/dma.h> |
43 | #include <asm/nmi.h> | 44 | #include <asm/nmi.h> |
45 | #include <asm/msidef.h> | ||
44 | 46 | ||
45 | #define __apicdebuginit __init | 47 | #define __apicdebuginit __init |
46 | 48 | ||
@@ -1739,6 +1741,78 @@ void destroy_irq(unsigned int irq) | |||
1739 | } | 1741 | } |
1740 | #endif | 1742 | #endif |
1741 | 1743 | ||
1744 | /* | ||
1745 | * MSI mesage composition | ||
1746 | */ | ||
1747 | #ifdef CONFIG_PCI_MSI | ||
1748 | static int msi_msg_setup(struct pci_dev *pdev, unsigned int irq, struct msi_msg *msg) | ||
1749 | { | ||
1750 | /* For now always this code always uses physical delivery | ||
1751 | * mode. | ||
1752 | */ | ||
1753 | int vector; | ||
1754 | unsigned dest; | ||
1755 | |||
1756 | vector = assign_irq_vector(irq); | ||
1757 | if (vector >= 0) { | ||
1758 | cpumask_t tmp; | ||
1759 | |||
1760 | cpus_clear(tmp); | ||
1761 | cpu_set(first_cpu(cpu_online_map), tmp); | ||
1762 | dest = cpu_mask_to_apicid(tmp); | ||
1763 | |||
1764 | msg->address_hi = MSI_ADDR_BASE_HI; | ||
1765 | msg->address_lo = | ||
1766 | MSI_ADDR_BASE_LO | | ||
1767 | ((INT_DEST_MODE == 0) ? | ||
1768 | MSI_ADDR_DEST_MODE_PHYSICAL: | ||
1769 | MSI_ADDR_DEST_MODE_LOGICAL) | | ||
1770 | ((INT_DELIVERY_MODE != dest_LowestPrio) ? | ||
1771 | MSI_ADDR_REDIRECTION_CPU: | ||
1772 | MSI_ADDR_REDIRECTION_LOWPRI) | | ||
1773 | MSI_ADDR_DEST_ID(dest); | ||
1774 | |||
1775 | msg->data = | ||
1776 | MSI_DATA_TRIGGER_EDGE | | ||
1777 | MSI_DATA_LEVEL_ASSERT | | ||
1778 | ((INT_DELIVERY_MODE != dest_LowestPrio) ? | ||
1779 | MSI_DATA_DELIVERY_FIXED: | ||
1780 | MSI_DATA_DELIVERY_LOWPRI) | | ||
1781 | MSI_DATA_VECTOR(vector); | ||
1782 | } | ||
1783 | return vector; | ||
1784 | } | ||
1785 | |||
1786 | static void msi_msg_teardown(unsigned int irq) | ||
1787 | { | ||
1788 | return; | ||
1789 | } | ||
1790 | |||
1791 | static void msi_msg_set_affinity(unsigned int irq, cpumask_t mask, struct msi_msg *msg) | ||
1792 | { | ||
1793 | int vector; | ||
1794 | unsigned dest; | ||
1795 | |||
1796 | vector = assign_irq_vector(irq); | ||
1797 | if (vector > 0) { | ||
1798 | dest = cpu_mask_to_apicid(mask); | ||
1799 | |||
1800 | msg->data &= ~MSI_DATA_VECTOR_MASK; | ||
1801 | msg->data |= MSI_DATA_VECTOR(vector); | ||
1802 | msg->address_lo &= ~MSI_ADDR_DEST_ID_MASK; | ||
1803 | msg->address_lo |= MSI_ADDR_DEST_ID(dest); | ||
1804 | } | ||
1805 | } | ||
1806 | |||
1807 | struct msi_ops arch_msi_ops = { | ||
1808 | .needs_64bit_address = 0, | ||
1809 | .setup = msi_msg_setup, | ||
1810 | .teardown = msi_msg_teardown, | ||
1811 | .target = msi_msg_set_affinity, | ||
1812 | }; | ||
1813 | |||
1814 | #endif | ||
1815 | |||
1742 | /* -------------------------------------------------------------------------- | 1816 | /* -------------------------------------------------------------------------- |
1743 | ACPI-based IOAPIC Configuration | 1817 | ACPI-based IOAPIC Configuration |
1744 | -------------------------------------------------------------------------- */ | 1818 | -------------------------------------------------------------------------- */ |
diff --git a/include/asm-x86_64/msi.h b/include/asm-x86_64/msi.h index 3ad2346624b2..1876fda52ae3 100644 --- a/include/asm-x86_64/msi.h +++ b/include/asm-x86_64/msi.h | |||
@@ -10,14 +10,11 @@ | |||
10 | #include <asm/mach_apic.h> | 10 | #include <asm/mach_apic.h> |
11 | #include <asm/smp.h> | 11 | #include <asm/smp.h> |
12 | 12 | ||
13 | #define LAST_DEVICE_VECTOR (FIRST_SYSTEM_VECTOR - 1) | 13 | extern struct msi_ops arch_msi_ops; |
14 | #define MSI_TARGET_CPU_SHIFT 12 | ||
15 | |||
16 | extern struct msi_ops msi_apic_ops; | ||
17 | 14 | ||
18 | static inline int msi_arch_init(void) | 15 | static inline int msi_arch_init(void) |
19 | { | 16 | { |
20 | msi_register(&msi_apic_ops); | 17 | msi_register(&arch_msi_ops); |
21 | return 0; | 18 | return 0; |
22 | } | 19 | } |
23 | 20 | ||
diff --git a/include/asm-x86_64/msidef.h b/include/asm-x86_64/msidef.h new file mode 100644 index 000000000000..5b8acddb70fb --- /dev/null +++ b/include/asm-x86_64/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 */ | ||