aboutsummaryrefslogtreecommitdiffstats
path: root/include/asm-sparc64
diff options
context:
space:
mode:
authorDavid S. Miller <davem@sunset.davemloft.net>2007-02-10 20:41:02 -0500
committerDavid S. Miller <davem@sunset.davemloft.net>2007-02-11 02:50:37 -0500
commit35a17eb6a87c9ceb0d35dcb51f464fe6faf584ab (patch)
tree7f56095a56e9f62dca7514cdfe781739548011f5 /include/asm-sparc64
parent68c921869491c119142612fa5796c9f8b4e9970b (diff)
[SPARC64]: Add PCI MSI support on Niagara.
This is kind of hokey, we could use the hardware provided facilities much better. MSIs are assosciated with MSI Queues. MSI Queues generate interrupts when any MSI assosciated with it is signalled. This suggests a two-tiered IRQ dispatch scheme: MSI Queue interrupt --> queue interrupt handler MSI dispatch --> driver interrupt handler But we just get one-level under Linux currently. What I'd like to do is possibly stick the IRQ actions into a per-MSI-Queue data structure, and dispatch them form there, but the generic IRQ layer doesn't provide a way to do that right now. So, the current kludge is to "ACK" the interrupt by processing the MSI Queue data structures and ACK'ing them, then we run the actual handler like normal. We are wasting a lot of useful information, for example the MSI data and address are provided with ever MSI, as well as a system tick if available. If we could pass this into the IRQ handler it could help with certain things, in particular for PCI-Express error messages. The MSI entries on sparc64 also tell you exactly which bus/device/fn sent the MSI, which would be great for error handling when no registered IRQ handler can service the interrupt. We override the disable/enable IRQ chip methods in sun4v_msi, so we have to call {mask,unmask}_msi_irq() directly from there. This is another ugly wart. Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'include/asm-sparc64')
-rw-r--r--include/asm-sparc64/irq.h4
-rw-r--r--include/asm-sparc64/pbm.h28
2 files changed, 32 insertions, 0 deletions
diff --git a/include/asm-sparc64/irq.h b/include/asm-sparc64/irq.h
index 905e59b4a737..5d233b42fe13 100644
--- a/include/asm-sparc64/irq.h
+++ b/include/asm-sparc64/irq.h
@@ -46,6 +46,10 @@ extern void irq_install_pre_handler(int virt_irq,
46#define irq_canonicalize(irq) (irq) 46#define irq_canonicalize(irq) (irq)
47extern unsigned int build_irq(int inofixup, unsigned long iclr, unsigned long imap); 47extern unsigned int build_irq(int inofixup, unsigned long iclr, unsigned long imap);
48extern unsigned int sun4v_build_irq(u32 devhandle, unsigned int devino); 48extern unsigned int sun4v_build_irq(u32 devhandle, unsigned int devino);
49extern unsigned int sun4v_build_msi(u32 devhandle, unsigned int *virt_irq_p,
50 unsigned int msi_devino_start,
51 unsigned int msi_devino_end);
52extern void sun4v_destroy_msi(unsigned int virt_irq);
49extern unsigned int sbus_build_irq(void *sbus, unsigned int ino); 53extern unsigned int sbus_build_irq(void *sbus, unsigned int ino);
50 54
51static __inline__ void set_softint(unsigned long bits) 55static __inline__ void set_softint(unsigned long bits)
diff --git a/include/asm-sparc64/pbm.h b/include/asm-sparc64/pbm.h
index dcfa7629358c..7a246d8a1828 100644
--- a/include/asm-sparc64/pbm.h
+++ b/include/asm-sparc64/pbm.h
@@ -11,6 +11,7 @@
11#include <linux/pci.h> 11#include <linux/pci.h>
12#include <linux/ioport.h> 12#include <linux/ioport.h>
13#include <linux/spinlock.h> 13#include <linux/spinlock.h>
14#include <linux/msi.h>
14 15
15#include <asm/io.h> 16#include <asm/io.h>
16#include <asm/page.h> 17#include <asm/page.h>
@@ -177,6 +178,24 @@ struct pci_pbm_info {
177 int is_66mhz_capable; 178 int is_66mhz_capable;
178 int all_devs_66mhz; 179 int all_devs_66mhz;
179 180
181#ifdef CONFIG_PCI_MSI
182 /* MSI info. */
183 u32 msiq_num;
184 u32 msiq_ent_count;
185 u32 msiq_first;
186 u32 msiq_first_devino;
187 u32 msi_num;
188 u32 msi_first;
189 u32 msi_data_mask;
190 u32 msix_data_width;
191 u64 msi32_start;
192 u64 msi64_start;
193 u32 msi32_len;
194 u32 msi64_len;
195 void *msi_queues;
196 unsigned long *msi_bitmap;
197#endif /* !(CONFIG_PCI_MSI) */
198
180 /* This PBM's streaming buffer. */ 199 /* This PBM's streaming buffer. */
181 struct pci_strbuf stc; 200 struct pci_strbuf stc;
182 201
@@ -213,6 +232,12 @@ struct pci_controller_info {
213 void (*base_address_update)(struct pci_dev *, int); 232 void (*base_address_update)(struct pci_dev *, int);
214 void (*resource_adjust)(struct pci_dev *, struct resource *, struct resource *); 233 void (*resource_adjust)(struct pci_dev *, struct resource *, struct resource *);
215 234
235#ifdef CONFIG_PCI_MSI
236 int (*setup_msi_irq)(unsigned int *virt_irq_p, struct pci_dev *pdev,
237 struct msi_desc *entry);
238 void (*teardown_msi_irq)(unsigned int virt_irq, struct pci_dev *pdev);
239#endif
240
216 /* Now things for the actual PCI bus probes. */ 241 /* Now things for the actual PCI bus probes. */
217 struct pci_ops *pci_ops; 242 struct pci_ops *pci_ops;
218 unsigned int pci_first_busno; 243 unsigned int pci_first_busno;
@@ -231,6 +256,9 @@ struct pcidev_cookie {
231 int num_prom_regs; 256 int num_prom_regs;
232 struct linux_prom_pci_registers prom_assignments[PROMREG_MAX]; 257 struct linux_prom_pci_registers prom_assignments[PROMREG_MAX];
233 int num_prom_assignments; 258 int num_prom_assignments;
259#ifdef CONFIG_PCI_MSI
260 unsigned int msi_num;
261#endif
234}; 262};
235 263
236/* Currently these are the same across all PCI controllers 264/* Currently these are the same across all PCI controllers