aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEric W. Biederman <ebiederm@xmission.com>2006-10-04 05:16:59 -0400
committerLinus Torvalds <torvalds@g5.osdl.org>2006-10-04 10:55:29 -0400
commit3b7d1921f4cdd6d6ddb7899ae7a8d413991c5cf4 (patch)
tree5f809e0c4310f60dfa6f65d54fbaf9f01e2ebff9
parent277bc33bc2479707e88b0b2ae6fe56e8e4aabe81 (diff)
[PATCH] msi: refactor and move the msi irq_chip into the arch code
It turns out msi_ops was simply not enough to abstract the architecture specific details of msi. So I have moved the resposibility of constructing the struct irq_chip to the architectures, and have two architecture specific functions arch_setup_msi_irq, and arch_teardown_msi_irq. For simple architectures those functions can do all of the work. For architectures with platform dependencies they can call into the appropriate platform code. With this msi.c is finally free of assuming you have an apic, and this actually takes less code. The helpers for the architecture specific code are declared in the linux/msi.h to keep them separate from the msi functions used by drivers in linux/pci.h Signed-off-by: Eric W. Biederman <ebiederm@xmission.com> Cc: Ingo Molnar <mingo@elte.hu> Cc: Tony Luck <tony.luck@intel.com> Cc: Andi Kleen <ak@suse.de> Cc: Thomas Gleixner <tglx@linutronix.de> Cc: Greg KH <greg@kroah.com> Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-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