aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/i386/kernel/io_apic.c81
-rw-r--r--arch/x86_64/kernel/io_apic.c89
-rw-r--r--drivers/pci/msi-altix.c81
-rw-r--r--drivers/pci/msi-apic.c86
-rw-r--r--drivers/pci/msi.c150
-rw-r--r--drivers/pci/msi.h27
-rw-r--r--include/asm-i386/msi.h20
-rw-r--r--include/asm-ia64/machvec.h21
-rw-r--r--include/asm-ia64/machvec_sn2.h9
-rw-r--r--include/asm-ia64/msi.h29
-rw-r--r--include/asm-x86_64/msi.h21
-rw-r--r--include/linux/msi.h49
-rw-r--r--include/linux/pci.h67
13 files changed, 335 insertions, 395 deletions
diff --git a/arch/i386/kernel/io_apic.c b/arch/i386/kernel/io_apic.c
index 100406b453b8..5a1252753dbb 100644
--- a/arch/i386/kernel/io_apic.c
+++ b/arch/i386/kernel/io_apic.c
@@ -32,6 +32,7 @@
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#include <linux/pci.h>
35#include <linux/msi.h>
35 36
36#include <asm/io.h> 37#include <asm/io.h>
37#include <asm/smp.h> 38#include <asm/smp.h>
@@ -2455,11 +2456,8 @@ void destroy_irq(unsigned int irq)
2455 * MSI mesage composition 2456 * MSI mesage composition
2456 */ 2457 */
2457#ifdef CONFIG_PCI_MSI 2458#ifdef CONFIG_PCI_MSI
2458static int msi_msg_setup(struct pci_dev *pdev, unsigned int irq, struct msi_msg *msg) 2459static int msi_compose_msg(struct pci_dev *pdev, unsigned int irq, struct msi_msg *msg)
2459{ 2460{
2460 /* For now always this code always uses physical delivery
2461 * mode.
2462 */
2463 int vector; 2461 int vector;
2464 unsigned dest; 2462 unsigned dest;
2465 2463
@@ -2489,34 +2487,71 @@ static int msi_msg_setup(struct pci_dev *pdev, unsigned int irq, struct msi_msg
2489 return vector; 2487 return vector;
2490} 2488}
2491 2489
2492static void msi_msg_teardown(unsigned int irq) 2490#ifdef CONFIG_SMP
2493{ 2491static void set_msi_irq_affinity(unsigned int irq, cpumask_t mask)
2494 return;
2495}
2496
2497static void msi_msg_set_affinity(unsigned int irq, cpumask_t mask, struct msi_msg *msg)
2498{ 2492{
2493 struct msi_msg msg;
2494 unsigned int dest;
2495 cpumask_t tmp;
2499 int vector; 2496 int vector;
2500 unsigned dest; 2497
2498 cpus_and(tmp, mask, cpu_online_map);
2499 if (cpus_empty(tmp))
2500 tmp = TARGET_CPUS;
2501 2501
2502 vector = assign_irq_vector(irq); 2502 vector = assign_irq_vector(irq);
2503 if (vector > 0) { 2503 if (vector < 0)
2504 dest = cpu_mask_to_apicid(mask); 2504 return;
2505 2505
2506 msg->data &= ~MSI_DATA_VECTOR_MASK; 2506 dest = cpu_mask_to_apicid(mask);
2507 msg->data |= MSI_DATA_VECTOR(vector); 2507
2508 msg->address_lo &= ~MSI_ADDR_DEST_ID_MASK; 2508 read_msi_msg(irq, &msg);
2509 msg->address_lo |= MSI_ADDR_DEST_ID(dest); 2509
2510 } 2510 msg.data &= ~MSI_DATA_VECTOR_MASK;
2511 msg.data |= MSI_DATA_VECTOR(vector);
2512 msg.address_lo &= ~MSI_ADDR_DEST_ID_MASK;
2513 msg.address_lo |= MSI_ADDR_DEST_ID(dest);
2514
2515 write_msi_msg(irq, &msg);
2516 set_native_irq_info(irq, mask);
2511} 2517}
2518#endif /* CONFIG_SMP */
2512 2519
2513struct msi_ops arch_msi_ops = { 2520/*
2514 .needs_64bit_address = 0, 2521 * IRQ Chip for MSI PCI/PCI-X/PCI-Express Devices,
2515 .setup = msi_msg_setup, 2522 * which implement the MSI or MSI-X Capability Structure.
2516 .teardown = msi_msg_teardown, 2523 */
2517 .target = msi_msg_set_affinity, 2524static struct irq_chip msi_chip = {
2525 .name = "PCI-MSI",
2526 .unmask = unmask_msi_irq,
2527 .mask = mask_msi_irq,
2528 .ack = ack_ioapic_irq,
2529#ifdef CONFIG_SMP
2530 .set_affinity = set_msi_irq_affinity,
2531#endif
2532 .retrigger = ioapic_retrigger_irq,
2518}; 2533};
2519 2534
2535int arch_setup_msi_irq(unsigned int irq, struct pci_dev *dev)
2536{
2537 struct msi_msg msg;
2538 int ret;
2539 ret = msi_compose_msg(dev, irq, &msg);
2540 if (ret < 0)
2541 return ret;
2542
2543 write_msi_msg(irq, &msg);
2544
2545 set_irq_chip_and_handler(irq, &msi_chip, handle_edge_irq);
2546
2547 return 0;
2548}
2549
2550void arch_teardown_msi_irq(unsigned int irq)
2551{
2552 return;
2553}
2554
2520#endif /* CONFIG_PCI_MSI */ 2555#endif /* CONFIG_PCI_MSI */
2521 2556
2522/* 2557/*
diff --git a/arch/x86_64/kernel/io_apic.c b/arch/x86_64/kernel/io_apic.c
index 31c270fee337..e55028fba942 100644
--- a/arch/x86_64/kernel/io_apic.c
+++ b/arch/x86_64/kernel/io_apic.c
@@ -30,6 +30,7 @@
30#include <linux/mc146818rtc.h> 30#include <linux/mc146818rtc.h>
31#include <linux/acpi.h> 31#include <linux/acpi.h>
32#include <linux/sysdev.h> 32#include <linux/sysdev.h>
33#include <linux/msi.h>
33#ifdef CONFIG_ACPI 34#ifdef CONFIG_ACPI
34#include <acpi/acpi_bus.h> 35#include <acpi/acpi_bus.h>
35#endif 36#endif
@@ -1701,11 +1702,8 @@ void destroy_irq(unsigned int irq)
1701 * MSI mesage composition 1702 * MSI mesage composition
1702 */ 1703 */
1703#ifdef CONFIG_PCI_MSI 1704#ifdef CONFIG_PCI_MSI
1704static int msi_msg_setup(struct pci_dev *pdev, unsigned int irq, struct msi_msg *msg) 1705static int msi_compose_msg(struct pci_dev *pdev, unsigned int irq, struct msi_msg *msg)
1705{ 1706{
1706 /* For now always this code always uses physical delivery
1707 * mode.
1708 */
1709 int vector; 1707 int vector;
1710 unsigned dest; 1708 unsigned dest;
1711 1709
@@ -1739,39 +1737,76 @@ static int msi_msg_setup(struct pci_dev *pdev, unsigned int irq, struct msi_msg
1739 return vector; 1737 return vector;
1740} 1738}
1741 1739
1742static void msi_msg_teardown(unsigned int irq) 1740#ifdef CONFIG_SMP
1743{ 1741static void set_msi_irq_affinity(unsigned int irq, cpumask_t mask)
1744 return;
1745}
1746
1747static void msi_msg_set_affinity(unsigned int irq, cpumask_t mask, struct msi_msg *msg)
1748{ 1742{
1743 struct msi_msg msg;
1744 unsigned int dest;
1745 cpumask_t tmp;
1749 int vector; 1746 int vector;
1750 unsigned dest; 1747
1748 cpus_and(tmp, mask, cpu_online_map);
1749 if (cpus_empty(tmp))
1750 tmp = TARGET_CPUS;
1751
1752 cpus_and(mask, tmp, CPU_MASK_ALL);
1751 1753
1752 vector = assign_irq_vector(irq, mask); 1754 vector = assign_irq_vector(irq, mask);
1753 if (vector > 0) { 1755 if (vector < 0)
1754 cpumask_t tmp; 1756 return;
1755 1757
1756 cpus_clear(tmp); 1758 cpus_clear(tmp);
1757 cpu_set(vector >> 8, tmp); 1759 cpu_set(vector >> 8, tmp);
1758 dest = cpu_mask_to_apicid(tmp); 1760 dest = cpu_mask_to_apicid(tmp);
1759 1761
1760 msg->data &= ~MSI_DATA_VECTOR_MASK; 1762 read_msi_msg(irq, &msg);
1761 msg->data |= MSI_DATA_VECTOR(vector); 1763
1762 msg->address_lo &= ~MSI_ADDR_DEST_ID_MASK; 1764 msg.data &= ~MSI_DATA_VECTOR_MASK;
1763 msg->address_lo |= MSI_ADDR_DEST_ID(dest); 1765 msg.data |= MSI_DATA_VECTOR(vector);
1764 } 1766 msg.address_lo &= ~MSI_ADDR_DEST_ID_MASK;
1767 msg.address_lo |= MSI_ADDR_DEST_ID(dest);
1768
1769 write_msi_msg(irq, &msg);
1770 set_native_irq_info(irq, mask);
1765} 1771}
1772#endif /* CONFIG_SMP */
1766 1773
1767struct msi_ops arch_msi_ops = { 1774/*
1768 .needs_64bit_address = 0, 1775 * IRQ Chip for MSI PCI/PCI-X/PCI-Express Devices,
1769 .setup = msi_msg_setup, 1776 * which implement the MSI or MSI-X Capability Structure.
1770 .teardown = msi_msg_teardown, 1777 */
1771 .target = msi_msg_set_affinity, 1778static struct irq_chip msi_chip = {
1779 .name = "PCI-MSI",
1780 .unmask = unmask_msi_irq,
1781 .mask = mask_msi_irq,
1782 .ack = ack_apic_edge,
1783#ifdef CONFIG_SMP
1784 .set_affinity = set_msi_irq_affinity,
1785#endif
1786 .retrigger = ioapic_retrigger_irq,
1772}; 1787};
1773 1788
1774#endif 1789int arch_setup_msi_irq(unsigned int irq, struct pci_dev *dev)
1790{
1791 struct msi_msg msg;
1792 int ret;
1793 ret = msi_compose_msg(dev, irq, &msg);
1794 if (ret < 0)
1795 return ret;
1796
1797 write_msi_msg(irq, &msg);
1798
1799 set_irq_chip_and_handler(irq, &msi_chip, handle_edge_irq);
1800
1801 return 0;
1802}
1803
1804void arch_teardown_msi_irq(unsigned int irq)
1805{
1806 return;
1807}
1808
1809#endif /* CONFIG_PCI_MSI */
1775 1810
1776/* 1811/*
1777 * Hypertransport interrupt support 1812 * Hypertransport interrupt support
diff --git a/drivers/pci/msi-altix.c b/drivers/pci/msi-altix.c
index 7aedc2ac8c28..6ffd1f850d41 100644
--- a/drivers/pci/msi-altix.c
+++ b/drivers/pci/msi-altix.c
@@ -7,8 +7,10 @@
7 */ 7 */
8 8
9#include <linux/types.h> 9#include <linux/types.h>
10#include <linux/irq.h>
10#include <linux/pci.h> 11#include <linux/pci.h>
11#include <linux/cpumask.h> 12#include <linux/cpumask.h>
13#include <linux/msi.h>
12 14
13#include <asm/sn/addrs.h> 15#include <asm/sn/addrs.h>
14#include <asm/sn/intr.h> 16#include <asm/sn/intr.h>
@@ -16,17 +18,16 @@
16#include <asm/sn/pcidev.h> 18#include <asm/sn/pcidev.h>
17#include <asm/sn/nodepda.h> 19#include <asm/sn/nodepda.h>
18 20
19#include "msi.h"
20
21struct sn_msi_info { 21struct sn_msi_info {
22 u64 pci_addr; 22 u64 pci_addr;
23 struct sn_irq_info *sn_irq_info; 23 struct sn_irq_info *sn_irq_info;
24}; 24};
25 25
26static struct sn_msi_info *sn_msi_info; 26static struct sn_msi_info sn_msi_info[NR_IRQS];
27
28static struct irq_chip sn_msi_chip;
27 29
28static void 30void sn_teardown_msi_irq(unsigned int irq)
29sn_msi_teardown(unsigned int irq)
30{ 31{
31 nasid_t nasid; 32 nasid_t nasid;
32 int widget; 33 int widget;
@@ -61,9 +62,10 @@ sn_msi_teardown(unsigned int irq)
61 return; 62 return;
62} 63}
63 64
64int 65int sn_setup_msi_irq(unsigned int irq, struct pci_dev *pdev)
65sn_msi_setup(struct pci_dev *pdev, unsigned int irq, struct msi_msg *msg)
66{ 66{
67 struct msi_msg msg;
68 struct msi_desc *entry;
67 int widget; 69 int widget;
68 int status; 70 int status;
69 nasid_t nasid; 71 nasid_t nasid;
@@ -72,6 +74,10 @@ sn_msi_setup(struct pci_dev *pdev, unsigned int irq, struct msi_msg *msg)
72 struct pcibus_bussoft *bussoft = SN_PCIDEV_BUSSOFT(pdev); 74 struct pcibus_bussoft *bussoft = SN_PCIDEV_BUSSOFT(pdev);
73 struct sn_pcibus_provider *provider = SN_PCIDEV_BUSPROVIDER(pdev); 75 struct sn_pcibus_provider *provider = SN_PCIDEV_BUSPROVIDER(pdev);
74 76
77 entry = get_irq_data(irq);
78 if (!entry->msi_attrib.is_64)
79 return -EINVAL;
80
75 if (bussoft == NULL) 81 if (bussoft == NULL)
76 return -EINVAL; 82 return -EINVAL;
77 83
@@ -121,25 +127,29 @@ sn_msi_setup(struct pci_dev *pdev, unsigned int irq, struct msi_msg *msg)
121 sn_msi_info[irq].sn_irq_info = sn_irq_info; 127 sn_msi_info[irq].sn_irq_info = sn_irq_info;
122 sn_msi_info[irq].pci_addr = bus_addr; 128 sn_msi_info[irq].pci_addr = bus_addr;
123 129
124 msg->address_hi = (u32)(bus_addr >> 32); 130 msg.address_hi = (u32)(bus_addr >> 32);
125 msg->address_lo = (u32)(bus_addr & 0x00000000ffffffff); 131 msg.address_lo = (u32)(bus_addr & 0x00000000ffffffff);
126 132
127 /* 133 /*
128 * In the SN platform, bit 16 is a "send vector" bit which 134 * In the SN platform, bit 16 is a "send vector" bit which
129 * must be present in order to move the vector through the system. 135 * must be present in order to move the vector through the system.
130 */ 136 */
131 msg->data = 0x100 + irq; 137 msg.data = 0x100 + irq;
132 138
133#ifdef CONFIG_SMP 139#ifdef CONFIG_SMP
134 set_irq_affinity_info(irq, sn_irq_info->irq_cpuid, 0); 140 set_irq_affinity_info(irq, sn_irq_info->irq_cpuid, 0);
135#endif 141#endif
136 142
143 write_msi_msg(irq, &msg);
144 set_irq_chip_and_handler(irq, &sn_msi_chip, handle_edge_irq);
145
137 return 0; 146 return 0;
138} 147}
139 148
140static void 149#ifdef CONFIG_SMP
141sn_msi_target(unsigned int irq, cpumask_t cpu_mask, struct msi_msg *msg) 150static void sn_set_msi_irq_affinity(unsigned int irq, cpumask_t cpu_mask)
142{ 151{
152 struct msi_msg msg;
143 int slice; 153 int slice;
144 nasid_t nasid; 154 nasid_t nasid;
145 u64 bus_addr; 155 u64 bus_addr;
@@ -159,11 +169,12 @@ sn_msi_target(unsigned int irq, cpumask_t cpu_mask, struct msi_msg *msg)
159 * Release XIO resources for the old MSI PCI address 169 * Release XIO resources for the old MSI PCI address
160 */ 170 */
161 171
172 read_msi_msg(irq, &msg);
162 sn_pdev = (struct pcidev_info *)sn_irq_info->irq_pciioinfo; 173 sn_pdev = (struct pcidev_info *)sn_irq_info->irq_pciioinfo;
163 pdev = sn_pdev->pdi_linux_pcidev; 174 pdev = sn_pdev->pdi_linux_pcidev;
164 provider = SN_PCIDEV_BUSPROVIDER(pdev); 175 provider = SN_PCIDEV_BUSPROVIDER(pdev);
165 176
166 bus_addr = (u64)(msg->address_hi) << 32 | (u64)(msg->address_lo); 177 bus_addr = (u64)(msg.address_hi) << 32 | (u64)(msg.address_lo);
167 (*provider->dma_unmap)(pdev, bus_addr, PCI_DMA_FROMDEVICE); 178 (*provider->dma_unmap)(pdev, bus_addr, PCI_DMA_FROMDEVICE);
168 sn_msi_info[irq].pci_addr = 0; 179 sn_msi_info[irq].pci_addr = 0;
169 180
@@ -185,27 +196,35 @@ sn_msi_target(unsigned int irq, cpumask_t cpu_mask, struct msi_msg *msg)
185 SN_DMA_MSI|SN_DMA_ADDR_XIO); 196 SN_DMA_MSI|SN_DMA_ADDR_XIO);
186 197
187 sn_msi_info[irq].pci_addr = bus_addr; 198 sn_msi_info[irq].pci_addr = bus_addr;
188 msg->address_hi = (u32)(bus_addr >> 32); 199 msg.address_hi = (u32)(bus_addr >> 32);
189 msg->address_lo = (u32)(bus_addr & 0x00000000ffffffff); 200 msg.address_lo = (u32)(bus_addr & 0x00000000ffffffff);
201
202 write_msi_msg(irq, &msg);
203 set_native_irq_info(irq, cpu_mask);
190} 204}
205#endif /* CONFIG_SMP */
191 206
192struct msi_ops sn_msi_ops = { 207static void sn_ack_msi_irq(unsigned int irq)
193 .needs_64bit_address = 1, 208{
194 .setup = sn_msi_setup, 209 move_native_irq(irq);
195 .teardown = sn_msi_teardown, 210 ia64_eoi();
196#ifdef CONFIG_SMP 211}
197 .target = sn_msi_target,
198#endif
199};
200 212
201int 213static int sn_msi_retrigger_irq(unsigned int irq)
202sn_msi_init(void)
203{ 214{
204 sn_msi_info = 215 unsigned int vector = irq;
205 kzalloc(sizeof(struct sn_msi_info) * NR_IRQS, GFP_KERNEL); 216 ia64_resend_irq(vector);
206 if (! sn_msi_info)
207 return -ENOMEM;
208 217
209 msi_register(&sn_msi_ops); 218 return 1;
210 return 0;
211} 219}
220
221static struct irq_chip sn_msi_chip = {
222 .name = "PCI-MSI",
223 .mask = mask_msi_irq,
224 .unmask = unmask_msi_irq,
225 .ack = sn_ack_msi_irq,
226#ifdef CONFIG_SMP
227 .set_affinity = sn_set_msi_irq_affinity,
228#endif
229 .retrigger = sn_msi_retrigger_irq,
230};
diff --git a/drivers/pci/msi-apic.c b/drivers/pci/msi-apic.c
index afc0ed13aa89..822e59a1b822 100644
--- a/drivers/pci/msi-apic.c
+++ b/drivers/pci/msi-apic.c
@@ -4,10 +4,9 @@
4 4
5#include <linux/pci.h> 5#include <linux/pci.h>
6#include <linux/irq.h> 6#include <linux/irq.h>
7#include <linux/msi.h>
7#include <asm/smp.h> 8#include <asm/smp.h>
8 9
9#include "msi.h"
10
11/* 10/*
12 * Shifts for APIC-based data 11 * Shifts for APIC-based data
13 */ 12 */
@@ -31,6 +30,7 @@
31 * Shift/mask fields for APIC-based bus address 30 * Shift/mask fields for APIC-based bus address
32 */ 31 */
33 32
33#define MSI_TARGET_CPU_SHIFT 4
34#define MSI_ADDR_HEADER 0xfee00000 34#define MSI_ADDR_HEADER 0xfee00000
35 35
36#define MSI_ADDR_DESTID_MASK 0xfff0000f 36#define MSI_ADDR_DESTID_MASK 0xfff0000f
@@ -44,58 +44,100 @@
44#define MSI_ADDR_REDIRECTION_CPU (0 << MSI_ADDR_REDIRECTION_SHIFT) 44#define MSI_ADDR_REDIRECTION_CPU (0 << MSI_ADDR_REDIRECTION_SHIFT)
45#define MSI_ADDR_REDIRECTION_LOWPRI (1 << MSI_ADDR_REDIRECTION_SHIFT) 45#define MSI_ADDR_REDIRECTION_LOWPRI (1 << MSI_ADDR_REDIRECTION_SHIFT)
46 46
47static struct irq_chip ia64_msi_chip;
47 48
48static void 49#ifdef CONFIG_SMP
49msi_target_apic(unsigned int irq, cpumask_t cpu_mask, struct msi_msg *msg) 50static void ia64_set_msi_irq_affinity(unsigned int irq, cpumask_t cpu_mask)
50{ 51{
51 u32 addr = msg->address_lo; 52 struct msi_msg msg;
53 u32 addr;
54
55 read_msi_msg(irq, &msg);
52 56
57 addr = msg.address_lo;
53 addr &= MSI_ADDR_DESTID_MASK; 58 addr &= MSI_ADDR_DESTID_MASK;
54 addr |= MSI_ADDR_DESTID_CPU(cpu_physical_id(first_cpu(cpu_mask))); 59 addr |= MSI_ADDR_DESTID_CPU(cpu_physical_id(first_cpu(cpu_mask)));
60 msg.address_lo = addr;
55 61
56 msg->address_lo = addr; 62 write_msi_msg(irq, &msg);
63 set_native_irq_info(irq, cpu_mask);
57} 64}
65#endif /* CONFIG_SMP */
58 66
59static int 67int ia64_setup_msi_irq(unsigned int irq, struct pci_dev *pdev)
60msi_setup_apic(struct pci_dev *pdev, /* unused in generic */
61 unsigned int irq,
62 struct msi_msg *msg)
63{ 68{
69 struct msi_msg msg;
64 unsigned long dest_phys_id; 70 unsigned long dest_phys_id;
65 unsigned int vector; 71 unsigned int vector;
66 72
67 dest_phys_id = cpu_physical_id(first_cpu(cpu_online_map)); 73 dest_phys_id = cpu_physical_id(first_cpu(cpu_online_map));
68 vector = irq; 74 vector = irq;
69 75
70 msg->address_hi = 0; 76 msg.address_hi = 0;
71 msg->address_lo = 77 msg.address_lo =
72 MSI_ADDR_HEADER | 78 MSI_ADDR_HEADER |
73 MSI_ADDR_DESTMODE_PHYS | 79 MSI_ADDR_DESTMODE_PHYS |
74 MSI_ADDR_REDIRECTION_CPU | 80 MSI_ADDR_REDIRECTION_CPU |
75 MSI_ADDR_DESTID_CPU(dest_phys_id); 81 MSI_ADDR_DESTID_CPU(dest_phys_id);
76 82
77 msg->data = 83 msg.data =
78 MSI_DATA_TRIGGER_EDGE | 84 MSI_DATA_TRIGGER_EDGE |
79 MSI_DATA_LEVEL_ASSERT | 85 MSI_DATA_LEVEL_ASSERT |
80 MSI_DATA_DELIVERY_FIXED | 86 MSI_DATA_DELIVERY_FIXED |
81 MSI_DATA_VECTOR(vector); 87 MSI_DATA_VECTOR(vector);
82 88
89 write_msi_msg(irq, &msg);
90 set_irq_chip_and_handler(irq, &ia64_msi_chip, handle_edge_irq);
91
83 return 0; 92 return 0;
84} 93}
85 94
86static void 95void ia64_teardown_msi_irq(unsigned int irq)
87msi_teardown_apic(unsigned int irq)
88{ 96{
89 return; /* no-op */ 97 return; /* no-op */
90} 98}
91 99
100static void ia64_ack_msi_irq(unsigned int irq)
101{
102 move_native_irq(irq);
103 ia64_eoi();
104}
105
106static int ia64_msi_retrigger_irq(unsigned int irq)
107{
108 unsigned int vector = irq;
109 ia64_resend_irq(vector);
110
111 return 1;
112}
113
92/* 114/*
93 * Generic ops used on most IA archs/platforms. Set with msi_register() 115 * Generic ops used on most IA64 platforms.
94 */ 116 */
95 117static struct irq_chip ia64_msi_chip = {
96struct msi_ops msi_apic_ops = { 118 .name = "PCI-MSI",
97 .needs_64bit_address = 0, 119 .mask = mask_msi_irq,
98 .setup = msi_setup_apic, 120 .unmask = unmask_msi_irq,
99 .teardown = msi_teardown_apic, 121 .ack = ia64_ack_msi_irq,
100 .target = msi_target_apic, 122#ifdef CONFIG_SMP
123 .set_affinity = ia64_set_msi_irq_affinity,
124#endif
125 .retrigger = ia64_msi_retrigger_irq,
101}; 126};
127
128
129int arch_setup_msi_irq(unsigned int irq, struct pci_dev *pdev)
130{
131 if (platform_setup_msi_irq)
132 return platform_setup_msi_irq(irq, pdev);
133
134 return ia64_setup_msi_irq(irq, pdev);
135}
136
137void arch_teardown_msi_irq(unsigned int irq)
138{
139 if (platform_teardown_msi_irq)
140 return platform_teardown_msi_irq(irq);
141
142 return ia64_teardown_msi_irq(irq);
143}
diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c
index fc7dd2a239dd..f9fdc54473c4 100644
--- a/drivers/pci/msi.c
+++ b/drivers/pci/msi.c
@@ -15,6 +15,7 @@
15#include <linux/smp_lock.h> 15#include <linux/smp_lock.h>
16#include <linux/pci.h> 16#include <linux/pci.h>
17#include <linux/proc_fs.h> 17#include <linux/proc_fs.h>
18#include <linux/msi.h>
18 19
19#include <asm/errno.h> 20#include <asm/errno.h>
20#include <asm/io.h> 21#include <asm/io.h>
@@ -29,15 +30,6 @@ static kmem_cache_t* msi_cachep;
29 30
30static int pci_msi_enable = 1; 31static int pci_msi_enable = 1;
31 32
32static struct msi_ops *msi_ops;
33
34int
35msi_register(struct msi_ops *ops)
36{
37 msi_ops = ops;
38 return 0;
39}
40
41static int msi_cache_init(void) 33static int msi_cache_init(void)
42{ 34{
43 msi_cachep = kmem_cache_create("msi_cache", sizeof(struct msi_desc), 35 msi_cachep = kmem_cache_create("msi_cache", sizeof(struct msi_desc),
@@ -80,8 +72,9 @@ static void msi_set_mask_bit(unsigned int irq, int flag)
80 } 72 }
81} 73}
82 74
83static void read_msi_msg(struct msi_desc *entry, struct msi_msg *msg) 75void read_msi_msg(unsigned int irq, struct msi_msg *msg)
84{ 76{
77 struct msi_desc *entry = get_irq_data(irq);
85 switch(entry->msi_attrib.type) { 78 switch(entry->msi_attrib.type) {
86 case PCI_CAP_ID_MSI: 79 case PCI_CAP_ID_MSI:
87 { 80 {
@@ -118,8 +111,9 @@ static void read_msi_msg(struct msi_desc *entry, struct msi_msg *msg)
118 } 111 }
119} 112}
120 113
121static void write_msi_msg(struct msi_desc *entry, struct msi_msg *msg) 114void write_msi_msg(unsigned int irq, struct msi_msg *msg)
122{ 115{
116 struct msi_desc *entry = get_irq_data(irq);
123 switch (entry->msi_attrib.type) { 117 switch (entry->msi_attrib.type) {
124 case PCI_CAP_ID_MSI: 118 case PCI_CAP_ID_MSI:
125 { 119 {
@@ -157,53 +151,16 @@ static void write_msi_msg(struct msi_desc *entry, struct msi_msg *msg)
157 } 151 }
158} 152}
159 153
160#ifdef CONFIG_SMP 154void mask_msi_irq(unsigned int irq)
161static void set_msi_affinity(unsigned int irq, cpumask_t cpu_mask)
162{
163 struct msi_desc *entry;
164 struct msi_msg msg;
165
166 entry = msi_desc[irq];
167 if (!entry || !entry->dev)
168 return;
169
170 read_msi_msg(entry, &msg);
171 msi_ops->target(irq, cpu_mask, &msg);
172 write_msi_msg(entry, &msg);
173 set_native_irq_info(irq, cpu_mask);
174}
175#else
176#define set_msi_affinity NULL
177#endif /* CONFIG_SMP */
178
179static void mask_MSI_irq(unsigned int irq)
180{ 155{
181 msi_set_mask_bit(irq, 1); 156 msi_set_mask_bit(irq, 1);
182} 157}
183 158
184static void unmask_MSI_irq(unsigned int irq) 159void unmask_msi_irq(unsigned int irq)
185{ 160{
186 msi_set_mask_bit(irq, 0); 161 msi_set_mask_bit(irq, 0);
187} 162}
188 163
189static void ack_msi_irq(unsigned int irq)
190{
191 move_native_irq(irq);
192 ack_APIC_irq();
193}
194
195/*
196 * IRQ Chip for MSI PCI/PCI-X/PCI-Express Devices,
197 * which implement the MSI or MSI-X Capability Structure.
198 */
199static struct irq_chip msi_chip = {
200 .name = "PCI-MSI",
201 .unmask = unmask_MSI_irq,
202 .mask = mask_MSI_irq,
203 .ack = ack_msi_irq,
204 .set_affinity = set_msi_affinity
205};
206
207static int msi_free_irq(struct pci_dev* dev, int irq); 164static int msi_free_irq(struct pci_dev* dev, int irq);
208static int msi_init(void) 165static int msi_init(void)
209{ 166{
@@ -219,22 +176,6 @@ static int msi_init(void)
219 return status; 176 return status;
220 } 177 }
221 178
222 status = msi_arch_init();
223 if (status < 0) {
224 pci_msi_enable = 0;
225 printk(KERN_WARNING
226 "PCI: MSI arch init failed. MSI disabled.\n");
227 return status;
228 }
229
230 if (! msi_ops) {
231 pci_msi_enable = 0;
232 printk(KERN_WARNING
233 "PCI: MSI ops not registered. MSI disabled.\n");
234 status = -EINVAL;
235 return status;
236 }
237
238 status = msi_cache_init(); 179 status = msi_cache_init();
239 if (status < 0) { 180 if (status < 0) {
240 pci_msi_enable = 0; 181 pci_msi_enable = 0;
@@ -268,7 +209,7 @@ static void attach_msi_entry(struct msi_desc *entry, int irq)
268 spin_unlock_irqrestore(&msi_lock, flags); 209 spin_unlock_irqrestore(&msi_lock, flags);
269} 210}
270 211
271static int create_msi_irq(struct irq_chip *chip) 212static int create_msi_irq(void)
272{ 213{
273 struct msi_desc *entry; 214 struct msi_desc *entry;
274 int irq; 215 int irq;
@@ -283,7 +224,6 @@ static int create_msi_irq(struct irq_chip *chip)
283 return -EBUSY; 224 return -EBUSY;
284 } 225 }
285 226
286 set_irq_chip_and_handler(irq, chip, handle_edge_irq);
287 set_irq_data(irq, entry); 227 set_irq_data(irq, entry);
288 228
289 return irq; 229 return irq;
@@ -473,7 +413,7 @@ int pci_save_msix_state(struct pci_dev *dev)
473 struct msi_desc *entry; 413 struct msi_desc *entry;
474 414
475 entry = msi_desc[irq]; 415 entry = msi_desc[irq];
476 read_msi_msg(entry, &entry->msg_save); 416 read_msi_msg(irq, &entry->msg_save);
477 417
478 tail = msi_desc[irq]->link.tail; 418 tail = msi_desc[irq]->link.tail;
479 irq = tail; 419 irq = tail;
@@ -512,7 +452,7 @@ void pci_restore_msix_state(struct pci_dev *dev)
512 irq = head = dev->irq; 452 irq = head = dev->irq;
513 while (head != tail) { 453 while (head != tail) {
514 entry = msi_desc[irq]; 454 entry = msi_desc[irq];
515 write_msi_msg(entry, &entry->msg_save); 455 write_msi_msg(irq, &entry->msg_save);
516 456
517 tail = msi_desc[irq]->link.tail; 457 tail = msi_desc[irq]->link.tail;
518 irq = tail; 458 irq = tail;
@@ -524,39 +464,6 @@ void pci_restore_msix_state(struct pci_dev *dev)
524} 464}
525#endif 465#endif
526 466
527static int msi_register_init(struct pci_dev *dev, struct msi_desc *entry)
528{
529 int status;
530 struct msi_msg msg;
531 int pos;
532 u16 control;
533
534 pos = entry->msi_attrib.pos;
535 pci_read_config_word(dev, msi_control_reg(pos), &control);
536
537 /* Configure MSI capability structure */
538 status = msi_ops->setup(dev, dev->irq, &msg);
539 if (status < 0)
540 return status;
541
542 write_msi_msg(entry, &msg);
543 if (entry->msi_attrib.maskbit) {
544 unsigned int maskbits, temp;
545 /* All MSIs are unmasked by default, Mask them all */
546 pci_read_config_dword(dev,
547 msi_mask_bits_reg(pos, is_64bit_address(control)),
548 &maskbits);
549 temp = (1 << multi_msi_capable(control));
550 temp = ((temp - 1) & ~temp);
551 maskbits |= temp;
552 pci_write_config_dword(dev,
553 msi_mask_bits_reg(pos, is_64bit_address(control)),
554 maskbits);
555 }
556
557 return 0;
558}
559
560/** 467/**
561 * msi_capability_init - configure device's MSI capability structure 468 * msi_capability_init - configure device's MSI capability structure
562 * @dev: pointer to the pci_dev data structure of MSI device function 469 * @dev: pointer to the pci_dev data structure of MSI device function
@@ -576,7 +483,7 @@ static int msi_capability_init(struct pci_dev *dev)
576 pos = pci_find_capability(dev, PCI_CAP_ID_MSI); 483 pos = pci_find_capability(dev, PCI_CAP_ID_MSI);
577 pci_read_config_word(dev, msi_control_reg(pos), &control); 484 pci_read_config_word(dev, msi_control_reg(pos), &control);
578 /* MSI Entry Initialization */ 485 /* MSI Entry Initialization */
579 irq = create_msi_irq(&msi_chip); 486 irq = create_msi_irq();
580 if (irq < 0) 487 if (irq < 0)
581 return irq; 488 return irq;
582 489
@@ -589,16 +496,27 @@ static int msi_capability_init(struct pci_dev *dev)
589 entry->msi_attrib.maskbit = is_mask_bit_support(control); 496 entry->msi_attrib.maskbit = is_mask_bit_support(control);
590 entry->msi_attrib.default_irq = dev->irq; /* Save IOAPIC IRQ */ 497 entry->msi_attrib.default_irq = dev->irq; /* Save IOAPIC IRQ */
591 entry->msi_attrib.pos = pos; 498 entry->msi_attrib.pos = pos;
592 dev->irq = irq;
593 entry->dev = dev;
594 if (is_mask_bit_support(control)) { 499 if (is_mask_bit_support(control)) {
595 entry->mask_base = (void __iomem *)(long)msi_mask_bits_reg(pos, 500 entry->mask_base = (void __iomem *)(long)msi_mask_bits_reg(pos,
596 is_64bit_address(control)); 501 is_64bit_address(control));
597 } 502 }
503 entry->dev = dev;
504 if (entry->msi_attrib.maskbit) {
505 unsigned int maskbits, temp;
506 /* All MSIs are unmasked by default, Mask them all */
507 pci_read_config_dword(dev,
508 msi_mask_bits_reg(pos, is_64bit_address(control)),
509 &maskbits);
510 temp = (1 << multi_msi_capable(control));
511 temp = ((temp - 1) & ~temp);
512 maskbits |= temp;
513 pci_write_config_dword(dev,
514 msi_mask_bits_reg(pos, is_64bit_address(control)),
515 maskbits);
516 }
598 /* Configure MSI capability structure */ 517 /* Configure MSI capability structure */
599 status = msi_register_init(dev, entry); 518 status = arch_setup_msi_irq(irq, dev);
600 if (status != 0) { 519 if (status < 0) {
601 dev->irq = entry->msi_attrib.default_irq;
602 destroy_msi_irq(irq); 520 destroy_msi_irq(irq);
603 return status; 521 return status;
604 } 522 }
@@ -607,6 +525,7 @@ static int msi_capability_init(struct pci_dev *dev)
607 /* Set MSI enabled bits */ 525 /* Set MSI enabled bits */
608 enable_msi_mode(dev, pos, PCI_CAP_ID_MSI); 526 enable_msi_mode(dev, pos, PCI_CAP_ID_MSI);
609 527
528 dev->irq = irq;
610 return 0; 529 return 0;
611} 530}
612 531
@@ -624,7 +543,6 @@ static int msix_capability_init(struct pci_dev *dev,
624 struct msix_entry *entries, int nvec) 543 struct msix_entry *entries, int nvec)
625{ 544{
626 struct msi_desc *head = NULL, *tail = NULL, *entry = NULL; 545 struct msi_desc *head = NULL, *tail = NULL, *entry = NULL;
627 struct msi_msg msg;
628 int status; 546 int status;
629 int irq, pos, i, j, nr_entries, temp = 0; 547 int irq, pos, i, j, nr_entries, temp = 0;
630 unsigned long phys_addr; 548 unsigned long phys_addr;
@@ -648,7 +566,7 @@ static int msix_capability_init(struct pci_dev *dev,
648 566
649 /* MSI-X Table Initialization */ 567 /* MSI-X Table Initialization */
650 for (i = 0; i < nvec; i++) { 568 for (i = 0; i < nvec; i++) {
651 irq = create_msi_irq(&msi_chip); 569 irq = create_msi_irq();
652 if (irq < 0) 570 if (irq < 0)
653 break; 571 break;
654 572
@@ -676,13 +594,12 @@ static int msix_capability_init(struct pci_dev *dev,
676 temp = irq; 594 temp = irq;
677 tail = entry; 595 tail = entry;
678 /* Configure MSI-X capability structure */ 596 /* Configure MSI-X capability structure */
679 status = msi_ops->setup(dev, irq, &msg); 597 status = arch_setup_msi_irq(irq, dev);
680 if (status < 0) { 598 if (status < 0) {
681 destroy_msi_irq(irq); 599 destroy_msi_irq(irq);
682 break; 600 break;
683 } 601 }
684 602
685 write_msi_msg(entry, &msg);
686 attach_msi_entry(entry, irq); 603 attach_msi_entry(entry, irq);
687 } 604 }
688 if (i != nvec) { 605 if (i != nvec) {
@@ -746,7 +663,6 @@ int pci_msi_supported(struct pci_dev * dev)
746int pci_enable_msi(struct pci_dev* dev) 663int pci_enable_msi(struct pci_dev* dev)
747{ 664{
748 int pos, temp, status; 665 int pos, temp, status;
749 u16 control;
750 666
751 if (pci_msi_supported(dev) < 0) 667 if (pci_msi_supported(dev) < 0)
752 return -EINVAL; 668 return -EINVAL;
@@ -761,10 +677,6 @@ int pci_enable_msi(struct pci_dev* dev)
761 if (!pos) 677 if (!pos)
762 return -EINVAL; 678 return -EINVAL;
763 679
764 pci_read_config_word(dev, msi_control_reg(pos), &control);
765 if (!is_64bit_address(control) && msi_ops->needs_64bit_address)
766 return -EINVAL;
767
768 WARN_ON(!msi_lookup_irq(dev, PCI_CAP_ID_MSI)); 680 WARN_ON(!msi_lookup_irq(dev, PCI_CAP_ID_MSI));
769 681
770 /* Check whether driver already requested for MSI-X irqs */ 682 /* Check whether driver already requested for MSI-X irqs */
@@ -831,7 +743,7 @@ static int msi_free_irq(struct pci_dev* dev, int irq)
831 void __iomem *base; 743 void __iomem *base;
832 unsigned long flags; 744 unsigned long flags;
833 745
834 msi_ops->teardown(irq); 746 arch_teardown_msi_irq(irq);
835 747
836 spin_lock_irqsave(&msi_lock, flags); 748 spin_lock_irqsave(&msi_lock, flags);
837 entry = msi_desc[irq]; 749 entry = msi_desc[irq];
diff --git a/drivers/pci/msi.h b/drivers/pci/msi.h
index 77823bfed5c1..f0cca1772f9c 100644
--- a/drivers/pci/msi.h
+++ b/drivers/pci/msi.h
@@ -6,8 +6,6 @@
6#ifndef MSI_H 6#ifndef MSI_H
7#define MSI_H 7#define MSI_H
8 8
9#include <asm/msi.h>
10
11/* 9/*
12 * MSI-X Address Register 10 * MSI-X Address Register
13 */ 11 */
@@ -49,29 +47,4 @@
49#define msix_mask(address) (address | PCI_MSIX_FLAGS_BITMASK) 47#define msix_mask(address) (address | PCI_MSIX_FLAGS_BITMASK)
50#define msix_is_pending(address) (address & PCI_MSIX_FLAGS_PENDMASK) 48#define msix_is_pending(address) (address & PCI_MSIX_FLAGS_PENDMASK)
51 49
52struct msi_desc {
53 struct {
54 __u8 type : 5; /* {0: unused, 5h:MSI, 11h:MSI-X} */
55 __u8 maskbit : 1; /* mask-pending bit supported ? */
56 __u8 unused : 1;
57 __u8 is_64 : 1; /* Address size: 0=32bit 1=64bit */
58 __u8 pos; /* Location of the msi capability */
59 __u16 entry_nr; /* specific enabled entry */
60 unsigned default_irq; /* default pre-assigned irq */
61 }msi_attrib;
62
63 struct {
64 __u16 head;
65 __u16 tail;
66 }link;
67
68 void __iomem *mask_base;
69 struct pci_dev *dev;
70
71#ifdef CONFIG_PM
72 /* PM save area for MSIX address/data */
73 struct msi_msg msg_save;
74#endif
75};
76
77#endif /* MSI_H */ 50#endif /* MSI_H */
diff --git a/include/asm-i386/msi.h b/include/asm-i386/msi.h
deleted file mode 100644
index 7368a89a0f42..000000000000
--- a/include/asm-i386/msi.h
+++ /dev/null
@@ -1,20 +0,0 @@
1/*
2 * Copyright (C) 2003-2004 Intel
3 * Copyright (C) Tom Long Nguyen (tom.l.nguyen@intel.com)
4 */
5
6#ifndef ASM_MSI_H
7#define ASM_MSI_H
8
9#include <asm/desc.h>
10#include <mach_apic.h>
11
12extern struct msi_ops arch_msi_ops;
13
14static inline int msi_arch_init(void)
15{
16 msi_register(&arch_msi_ops);
17 return 0;
18}
19
20#endif /* ASM_MSI_H */
diff --git a/include/asm-ia64/machvec.h b/include/asm-ia64/machvec.h
index 15b545a897a4..90cba967df35 100644
--- a/include/asm-ia64/machvec.h
+++ b/include/asm-ia64/machvec.h
@@ -20,6 +20,7 @@ struct page;
20struct mm_struct; 20struct mm_struct;
21struct pci_bus; 21struct pci_bus;
22struct task_struct; 22struct task_struct;
23struct pci_dev;
23 24
24typedef void ia64_mv_setup_t (char **); 25typedef void ia64_mv_setup_t (char **);
25typedef void ia64_mv_cpu_init_t (void); 26typedef void ia64_mv_cpu_init_t (void);
@@ -75,7 +76,9 @@ typedef unsigned char ia64_mv_readb_relaxed_t (const volatile void __iomem *);
75typedef unsigned short ia64_mv_readw_relaxed_t (const volatile void __iomem *); 76typedef unsigned short ia64_mv_readw_relaxed_t (const volatile void __iomem *);
76typedef unsigned int ia64_mv_readl_relaxed_t (const volatile void __iomem *); 77typedef unsigned int ia64_mv_readl_relaxed_t (const volatile void __iomem *);
77typedef unsigned long ia64_mv_readq_relaxed_t (const volatile void __iomem *); 78typedef unsigned long ia64_mv_readq_relaxed_t (const volatile void __iomem *);
78typedef int ia64_mv_msi_init_t (void); 79
80typedef int ia64_mv_setup_msi_irq_t (unsigned int irq, struct pci_dev *pdev);
81typedef void ia64_mv_teardown_msi_irq_t (unsigned int irq);
79 82
80static inline void 83static inline void
81machvec_noop (void) 84machvec_noop (void)
@@ -154,7 +157,8 @@ extern void machvec_tlb_migrate_finish (struct mm_struct *);
154# define platform_readl_relaxed ia64_mv.readl_relaxed 157# define platform_readl_relaxed ia64_mv.readl_relaxed
155# define platform_readq_relaxed ia64_mv.readq_relaxed 158# define platform_readq_relaxed ia64_mv.readq_relaxed
156# define platform_migrate ia64_mv.migrate 159# define platform_migrate ia64_mv.migrate
157# define platform_msi_init ia64_mv.msi_init 160# define platform_setup_msi_irq ia64_mv.setup_msi_irq
161# define platform_teardown_msi_irq ia64_mv.teardown_msi_irq
158# endif 162# endif
159 163
160/* __attribute__((__aligned__(16))) is required to make size of the 164/* __attribute__((__aligned__(16))) is required to make size of the
@@ -204,7 +208,8 @@ struct ia64_machine_vector {
204 ia64_mv_readl_relaxed_t *readl_relaxed; 208 ia64_mv_readl_relaxed_t *readl_relaxed;
205 ia64_mv_readq_relaxed_t *readq_relaxed; 209 ia64_mv_readq_relaxed_t *readq_relaxed;
206 ia64_mv_migrate_t *migrate; 210 ia64_mv_migrate_t *migrate;
207 ia64_mv_msi_init_t *msi_init; 211 ia64_mv_setup_msi_irq_t *setup_msi_irq;
212 ia64_mv_teardown_msi_irq_t *teardown_msi_irq;
208} __attribute__((__aligned__(16))); /* align attrib? see above comment */ 213} __attribute__((__aligned__(16))); /* align attrib? see above comment */
209 214
210#define MACHVEC_INIT(name) \ 215#define MACHVEC_INIT(name) \
@@ -250,7 +255,8 @@ struct ia64_machine_vector {
250 platform_readl_relaxed, \ 255 platform_readl_relaxed, \
251 platform_readq_relaxed, \ 256 platform_readq_relaxed, \
252 platform_migrate, \ 257 platform_migrate, \
253 platform_msi_init, \ 258 platform_setup_msi_irq, \
259 platform_teardown_msi_irq, \
254} 260}
255 261
256extern struct ia64_machine_vector ia64_mv; 262extern struct ia64_machine_vector ia64_mv;
@@ -404,8 +410,11 @@ extern int ia64_pci_legacy_write(struct pci_bus *bus, u16 port, u32 val, u8 size
404#ifndef platform_migrate 410#ifndef platform_migrate
405# define platform_migrate machvec_noop_task 411# define platform_migrate machvec_noop_task
406#endif 412#endif
407#ifndef platform_msi_init 413#ifndef platform_setup_msi_irq
408# define platform_msi_init ((ia64_mv_msi_init_t*)NULL) 414# define platform_setup_msi_irq ((ia64_mv_setup_msi_irq_t*)NULL)
415#endif
416#ifndef platform_teardown_msi_irq
417# define platform_teardown_msi_irq ((ia64_mv_teardown_msi_irq_t*)NULL)
409#endif 418#endif
410 419
411#endif /* _ASM_IA64_MACHVEC_H */ 420#endif /* _ASM_IA64_MACHVEC_H */
diff --git a/include/asm-ia64/machvec_sn2.h b/include/asm-ia64/machvec_sn2.h
index cf724dc79d8c..c54b165b1c17 100644
--- a/include/asm-ia64/machvec_sn2.h
+++ b/include/asm-ia64/machvec_sn2.h
@@ -67,7 +67,8 @@ extern ia64_mv_dma_sync_sg_for_device sn_dma_sync_sg_for_device;
67extern ia64_mv_dma_mapping_error sn_dma_mapping_error; 67extern ia64_mv_dma_mapping_error sn_dma_mapping_error;
68extern ia64_mv_dma_supported sn_dma_supported; 68extern ia64_mv_dma_supported sn_dma_supported;
69extern ia64_mv_migrate_t sn_migrate; 69extern ia64_mv_migrate_t sn_migrate;
70extern ia64_mv_msi_init_t sn_msi_init; 70extern ia64_mv_setup_msi_irq_t sn_setup_msi_irq;
71extern ia64_mv_teardown_msi_irq_t sn_teardown_msi_irq;
71 72
72 73
73/* 74/*
@@ -120,9 +121,11 @@ extern ia64_mv_msi_init_t sn_msi_init;
120#define platform_dma_supported sn_dma_supported 121#define platform_dma_supported sn_dma_supported
121#define platform_migrate sn_migrate 122#define platform_migrate sn_migrate
122#ifdef CONFIG_PCI_MSI 123#ifdef CONFIG_PCI_MSI
123#define platform_msi_init sn_msi_init 124#define platform_setup_msi_irq sn_setup_msi_irq
125#define platform_teardown_msi_irq sn_teardown_msi_irq
124#else 126#else
125#define platform_msi_init ((ia64_mv_msi_init_t*)NULL) 127#define platform_setup_msi_irq ((ia64_mv_setup_msi_irq_t*)NULL)
128#define platform_teardown_msi_irq ((ia64_mv_teardown_msi_irq_t*)NULL)
126#endif 129#endif
127 130
128#include <asm/sn/io.h> 131#include <asm/sn/io.h>
diff --git a/include/asm-ia64/msi.h b/include/asm-ia64/msi.h
deleted file mode 100644
index bb92b0dbde2f..000000000000
--- a/include/asm-ia64/msi.h
+++ /dev/null
@@ -1,29 +0,0 @@
1/*
2 * Copyright (C) 2003-2004 Intel
3 * Copyright (C) Tom Long Nguyen (tom.l.nguyen@intel.com)
4 */
5
6#ifndef ASM_MSI_H
7#define ASM_MSI_H
8
9#define NR_VECTORS NR_IRQS
10#define FIRST_DEVICE_VECTOR IA64_FIRST_DEVICE_VECTOR
11#define LAST_DEVICE_VECTOR IA64_LAST_DEVICE_VECTOR
12static inline void set_intr_gate (int nr, void *func) {}
13#define IO_APIC_VECTOR(irq) (irq)
14#define ack_APIC_irq ia64_eoi
15#define MSI_TARGET_CPU_SHIFT 4
16
17extern struct msi_ops msi_apic_ops;
18
19static inline int msi_arch_init(void)
20{
21 if (platform_msi_init)
22 return platform_msi_init();
23
24 /* default ops for most ia64 platforms */
25 msi_register(&msi_apic_ops);
26 return 0;
27}
28
29#endif /* ASM_MSI_H */
diff --git a/include/asm-x86_64/msi.h b/include/asm-x86_64/msi.h
deleted file mode 100644
index 1876fda52ae3..000000000000
--- a/include/asm-x86_64/msi.h
+++ /dev/null
@@ -1,21 +0,0 @@
1/*
2 * Copyright (C) 2003-2004 Intel
3 * Copyright (C) Tom Long Nguyen (tom.l.nguyen@intel.com)
4 */
5
6#ifndef ASM_MSI_H
7#define ASM_MSI_H
8
9#include <asm/desc.h>
10#include <asm/mach_apic.h>
11#include <asm/smp.h>
12
13extern struct msi_ops arch_msi_ops;
14
15static inline int msi_arch_init(void)
16{
17 msi_register(&arch_msi_ops);
18 return 0;
19}
20
21#endif /* ASM_MSI_H */
diff --git a/include/linux/msi.h b/include/linux/msi.h
new file mode 100644
index 000000000000..c7ef94343673
--- /dev/null
+++ b/include/linux/msi.h
@@ -0,0 +1,49 @@
1#ifndef LINUX_MSI_H
2#define LINUX_MSI_H
3
4struct msi_msg {
5 u32 address_lo; /* low 32 bits of msi message address */
6 u32 address_hi; /* high 32 bits of msi message address */
7 u32 data; /* 16 bits of msi message data */
8};
9
10/* Heper functions */
11extern void mask_msi_irq(unsigned int irq);
12extern void unmask_msi_irq(unsigned int irq);
13extern void read_msi_msg(unsigned int irq, struct msi_msg *msg);
14
15extern void write_msi_msg(unsigned int irq, struct msi_msg *msg);
16
17struct msi_desc {
18 struct {
19 __u8 type : 5; /* {0: unused, 5h:MSI, 11h:MSI-X} */
20 __u8 maskbit : 1; /* mask-pending bit supported ? */
21 __u8 unused : 1;
22 __u8 is_64 : 1; /* Address size: 0=32bit 1=64bit */
23 __u8 pos; /* Location of the msi capability */
24 __u16 entry_nr; /* specific enabled entry */
25 unsigned default_irq; /* default pre-assigned irq */
26 }msi_attrib;
27
28 struct {
29 __u16 head;
30 __u16 tail;
31 }link;
32
33 void __iomem *mask_base;
34 struct pci_dev *dev;
35
36#ifdef CONFIG_PM
37 /* PM save area for MSIX address/data */
38 struct msi_msg msg_save;
39#endif
40};
41
42/*
43 * The arch hook for setup up msi irqs
44 */
45int arch_setup_msi_irq(unsigned int irq, struct pci_dev *dev);
46void arch_teardown_msi_irq(unsigned int irq);
47
48
49#endif /* LINUX_MSI_H */
diff --git a/include/linux/pci.h b/include/linux/pci.h
index 9b34bc8f34e4..0da5a4a8940f 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -595,11 +595,6 @@ struct msix_entry {
595 u16 entry; /* driver uses to specify entry, OS writes */ 595 u16 entry; /* driver uses to specify entry, OS writes */
596}; 596};
597 597
598struct msi_msg {
599 u32 address_lo; /* low 32 bits of msi message address */
600 u32 address_hi; /* high 32 bits of msi message address */
601 u32 data; /* 16 bits of msi message data */
602};
603 598
604#ifndef CONFIG_PCI_MSI 599#ifndef CONFIG_PCI_MSI
605static inline void pci_scan_msi_device(struct pci_dev *dev) {} 600static inline void pci_scan_msi_device(struct pci_dev *dev) {}
@@ -617,68 +612,6 @@ extern int pci_enable_msix(struct pci_dev* dev,
617 struct msix_entry *entries, int nvec); 612 struct msix_entry *entries, int nvec);
618extern void pci_disable_msix(struct pci_dev *dev); 613extern void pci_disable_msix(struct pci_dev *dev);
619extern void msi_remove_pci_irq_vectors(struct pci_dev *dev); 614extern void msi_remove_pci_irq_vectors(struct pci_dev *dev);
620
621/*
622 * MSI operation vector. Used by the msi core code (drivers/pci/msi.c)
623 * to abstract platform-specific tasks relating to MSI address generation
624 * and resource management.
625 */
626struct msi_ops {
627 int needs_64bit_address;
628 /**
629 * setup - generate an MSI bus address and data for a given vector
630 * @pdev: PCI device context (in)
631 * @irq: irq allocated by the msi core (in)
632 * @msg: PCI bus address and data for msi message (out)
633 *
634 * Description: The setup op is used to generate a PCI bus addres and
635 * data which the msi core will program into the card MSI capability
636 * registers. The setup routine is responsible for picking an initial
637 * cpu to target the MSI at. The setup routine is responsible for
638 * examining pdev to determine the MSI capabilities of the card and
639 * generating a suitable address/data. The setup routine is
640 * responsible for allocating and tracking any system resources it
641 * needs to route the MSI to the cpu it picks, and for associating
642 * those resources with the passed in vector.
643 *
644 * Returns 0 if the MSI address/data was successfully setup.
645 **/
646
647 int (*setup) (struct pci_dev *pdev, unsigned int irq,
648 struct msi_msg *msg);
649
650 /**
651 * teardown - release resources allocated by setup
652 * @vector: vector context for resources (in)
653 *
654 * Description: The teardown op is used to release any resources
655 * that were allocated in the setup routine associated with the passed
656 * in vector.
657 **/
658
659 void (*teardown) (unsigned int irq);
660
661 /**
662 * target - retarget an MSI at a different cpu
663 * @vector: vector context for resources (in)
664 * @cpu: new cpu to direct vector at (in)
665 * @addr_hi: new value of PCI bus upper 32 bits (in/out)
666 * @addr_lo: new value of PCI bus lower 32 bits (in/out)
667 *
668 * Description: The target op is used to redirect an MSI vector
669 * at a different cpu. addr_hi/addr_lo coming in are the existing
670 * values that the MSI core has programmed into the card. The
671 * target code is responsible for freeing any resources (if any)
672 * associated with the old address, and generating a new PCI bus
673 * addr_hi/addr_lo that will redirect the vector at the indicated cpu.
674 **/
675
676 void (*target) (unsigned int irq, cpumask_t cpumask,
677 struct msi_msg *msg);
678};
679
680extern int msi_register(struct msi_ops *ops);
681
682#endif 615#endif
683 616
684#ifdef CONFIG_HT_IRQ 617#ifdef CONFIG_HT_IRQ