aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sparc64/kernel/irq.c
diff options
context:
space:
mode:
authorDavid S. Miller <davem@sunset.davemloft.net>2007-08-31 01:33:25 -0400
committerDavid S. Miller <davem@sunset.davemloft.net>2007-10-14 00:53:09 -0400
commit9bb3c227c47b23280eb50fac0872d96ef3e160a7 (patch)
treec519fa5e544bc1df018eafecb3563c7ce1b3c43b /arch/sparc64/kernel/irq.c
parentf9c97e5d7cd9ff5e51e16d5db08d7e54fa4cb6bb (diff)
[SPARC64]: Enable MSI on sun4u Fire PCI-E controllers.
The support code is identical to the hypervisor sun4v stuff, just replacing the hypervisor calls with register reads and writes in the Fire controller. Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'arch/sparc64/kernel/irq.c')
-rw-r--r--arch/sparc64/kernel/irq.c71
1 files changed, 71 insertions, 0 deletions
diff --git a/arch/sparc64/kernel/irq.c b/arch/sparc64/kernel/irq.c
index 23956096b3bf..7f5a4c77e3e4 100644
--- a/arch/sparc64/kernel/irq.c
+++ b/arch/sparc64/kernel/irq.c
@@ -406,6 +406,18 @@ static void sun4v_irq_disable(unsigned int virt_irq)
406} 406}
407 407
408#ifdef CONFIG_PCI_MSI 408#ifdef CONFIG_PCI_MSI
409static void sun4u_msi_enable(unsigned int virt_irq)
410{
411 sun4u_irq_enable(virt_irq);
412 unmask_msi_irq(virt_irq);
413}
414
415static void sun4u_msi_disable(unsigned int virt_irq)
416{
417 mask_msi_irq(virt_irq);
418 sun4u_irq_disable(virt_irq);
419}
420
409static void sun4v_msi_enable(unsigned int virt_irq) 421static void sun4v_msi_enable(unsigned int virt_irq)
410{ 422{
411 sun4v_irq_enable(virt_irq); 423 sun4v_irq_enable(virt_irq);
@@ -583,6 +595,17 @@ static struct irq_chip sun4v_irq_ack = {
583}; 595};
584 596
585#ifdef CONFIG_PCI_MSI 597#ifdef CONFIG_PCI_MSI
598static struct irq_chip sun4u_msi = {
599 .typename = "sun4u+msi",
600 .mask = mask_msi_irq,
601 .unmask = unmask_msi_irq,
602 .enable = sun4u_msi_enable,
603 .disable = sun4u_msi_disable,
604 .ack = run_pre_handler,
605 .end = sun4u_irq_end,
606 .set_affinity = sun4u_set_affinity,
607};
608
586static struct irq_chip sun4v_msi = { 609static struct irq_chip sun4v_msi = {
587 .typename = "sun4v+msi", 610 .typename = "sun4v+msi",
588 .mask = mask_msi_irq, 611 .mask = mask_msi_irq,
@@ -628,6 +651,7 @@ void irq_install_pre_handler(int virt_irq,
628 chip == &sun4v_irq_ack || 651 chip == &sun4v_irq_ack ||
629 chip == &sun4v_virq_ack 652 chip == &sun4v_virq_ack
630#ifdef CONFIG_PCI_MSI 653#ifdef CONFIG_PCI_MSI
654 || chip == &sun4u_msi
631 || chip == &sun4v_msi 655 || chip == &sun4v_msi
632#endif 656#endif
633 ) 657 )
@@ -789,6 +813,53 @@ void sun4v_destroy_msi(unsigned int virt_irq)
789{ 813{
790 virt_irq_free(virt_irq); 814 virt_irq_free(virt_irq);
791} 815}
816
817unsigned int sun4u_build_msi(u32 portid, unsigned int *virt_irq_p,
818 unsigned int msi_start, unsigned int msi_end,
819 unsigned long imap_base, unsigned long iclr_base)
820{
821 struct ino_bucket *bucket;
822 struct irq_handler_data *data;
823 unsigned long sysino;
824 unsigned int devino;
825
826 /* Find a free devino in the given range. */
827 for (devino = msi_start; devino < msi_end; devino++) {
828 sysino = (portid << 6) | devino;
829 bucket = &ivector_table[sysino];
830 if (!bucket->virt_irq)
831 break;
832 }
833 if (devino >= msi_end)
834 return -ENOSPC;
835
836 sysino = (portid << 6) | devino;
837 bucket = &ivector_table[sysino];
838 bucket->virt_irq = virt_irq_alloc(__irq(bucket));
839 *virt_irq_p = bucket->virt_irq;
840 set_irq_chip(bucket->virt_irq, &sun4u_msi);
841
842 data = get_irq_chip_data(bucket->virt_irq);
843 if (unlikely(data))
844 return devino;
845
846 data = kzalloc(sizeof(struct irq_handler_data), GFP_ATOMIC);
847 if (unlikely(!data)) {
848 virt_irq_free(*virt_irq_p);
849 return -ENOMEM;
850 }
851 set_irq_chip_data(bucket->virt_irq, data);
852
853 data->imap = (imap_base + (devino * 0x8UL));
854 data->iclr = (iclr_base + (devino * 0x8UL));
855
856 return devino;
857}
858
859void sun4u_destroy_msi(unsigned int virt_irq)
860{
861 virt_irq_free(virt_irq);
862}
792#endif 863#endif
793 864
794void ack_bad_irq(unsigned int virt_irq) 865void ack_bad_irq(unsigned int virt_irq)