diff options
author | Eric W. Biederman <ebiederm@xmission.com> | 2006-10-04 05:16:59 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-10-04 10:55:29 -0400 |
commit | 3b7d1921f4cdd6d6ddb7899ae7a8d413991c5cf4 (patch) | |
tree | 5f809e0c4310f60dfa6f65d54fbaf9f01e2ebff9 /drivers/pci/msi-altix.c | |
parent | 277bc33bc2479707e88b0b2ae6fe56e8e4aabe81 (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>
Diffstat (limited to 'drivers/pci/msi-altix.c')
-rw-r--r-- | drivers/pci/msi-altix.c | 81 |
1 files changed, 50 insertions, 31 deletions
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 | |||
21 | struct sn_msi_info { | 21 | struct 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 | ||
26 | static struct sn_msi_info *sn_msi_info; | 26 | static struct sn_msi_info sn_msi_info[NR_IRQS]; |
27 | |||
28 | static struct irq_chip sn_msi_chip; | ||
27 | 29 | ||
28 | static void | 30 | void sn_teardown_msi_irq(unsigned int irq) |
29 | sn_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 | ||
64 | int | 65 | int sn_setup_msi_irq(unsigned int irq, struct pci_dev *pdev) |
65 | sn_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 | ||
140 | static void | 149 | #ifdef CONFIG_SMP |
141 | sn_msi_target(unsigned int irq, cpumask_t cpu_mask, struct msi_msg *msg) | 150 | static 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 | ||
192 | struct msi_ops sn_msi_ops = { | 207 | static 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 | ||
201 | int | 213 | static int sn_msi_retrigger_irq(unsigned int irq) |
202 | sn_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 | |||
221 | static 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 | }; | ||