aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMark Maule <maule@sgi.com>2005-08-25 14:45:00 -0400
committerTony Luck <tony.luck@intel.com>2005-08-26 15:09:01 -0400
commit8409668b561fbe464f7a392e8dc77eca225d27ac (patch)
tree7783a2e701b7ae866be858e9121ec70f91fe4fa9
parent5b9021bc5800796e23e4994f8cf2dc61536be0a7 (diff)
[IA64] altix: Abstract irq_affinity at the sn pci provider
Altix patch to abstract irq_affinity down to the pci provider level since different SGI hardware implements this in different ways. Signed-off-by: Mark Maule <maule@sgi.com> Signed-off-by: Tony Luck <tony.luck@intel.com>
-rw-r--r--arch/ia64/sn/kernel/irq.c6
-rw-r--r--arch/ia64/sn/pci/pcibr/pcibr_provider.c5
-rw-r--r--arch/ia64/sn/pci/tioca_provider.c3
-rw-r--r--arch/ia64/sn/pci/tioce_provider.c40
-rw-r--r--include/asm-ia64/sn/pcibus_provider_defs.h1
5 files changed, 49 insertions, 6 deletions
diff --git a/arch/ia64/sn/kernel/irq.c b/arch/ia64/sn/kernel/irq.c
index 607938c288b..9fc74631ba8 100644
--- a/arch/ia64/sn/kernel/irq.c
+++ b/arch/ia64/sn/kernel/irq.c
@@ -127,6 +127,7 @@ static void sn_set_affinity_irq(unsigned int irq, cpumask_t mask)
127 int local_widget, status; 127 int local_widget, status;
128 nasid_t local_nasid; 128 nasid_t local_nasid;
129 struct sn_irq_info *new_irq_info; 129 struct sn_irq_info *new_irq_info;
130 struct sn_pcibus_provider *pci_provider;
130 131
131 new_irq_info = kmalloc(sizeof(struct sn_irq_info), GFP_ATOMIC); 132 new_irq_info = kmalloc(sizeof(struct sn_irq_info), GFP_ATOMIC);
132 if (new_irq_info == NULL) 133 if (new_irq_info == NULL)
@@ -166,8 +167,9 @@ static void sn_set_affinity_irq(unsigned int irq, cpumask_t mask)
166 new_irq_info->irq_cpuid = cpuid; 167 new_irq_info->irq_cpuid = cpuid;
167 register_intr_pda(new_irq_info); 168 register_intr_pda(new_irq_info);
168 169
169 if (IS_PCI_BRIDGE_ASIC(new_irq_info->irq_bridge_type)) 170 pci_provider = sn_pci_provider[new_irq_info->irq_bridge_type];
170 pcibr_change_devices_irq(new_irq_info); 171 if (pci_provider && pci_provider->target_interrupt)
172 (pci_provider->target_interrupt)(new_irq_info);
171 173
172 spin_lock(&sn_irq_info_lock); 174 spin_lock(&sn_irq_info_lock);
173 list_replace_rcu(&sn_irq_info->list, &new_irq_info->list); 175 list_replace_rcu(&sn_irq_info->list, &new_irq_info->list);
diff --git a/arch/ia64/sn/pci/pcibr/pcibr_provider.c b/arch/ia64/sn/pci/pcibr/pcibr_provider.c
index 5862a709adf..7b03b8084ff 100644
--- a/arch/ia64/sn/pci/pcibr/pcibr_provider.c
+++ b/arch/ia64/sn/pci/pcibr/pcibr_provider.c
@@ -198,7 +198,7 @@ void pcibr_force_interrupt(struct sn_irq_info *sn_irq_info)
198 } 198 }
199} 199}
200 200
201void pcibr_change_devices_irq(struct sn_irq_info *sn_irq_info) 201void pcibr_target_interrupt(struct sn_irq_info *sn_irq_info)
202{ 202{
203 struct pcidev_info *pcidev_info; 203 struct pcidev_info *pcidev_info;
204 struct pcibus_info *pcibus_info; 204 struct pcibus_info *pcibus_info;
@@ -233,7 +233,8 @@ struct sn_pcibus_provider pcibr_provider = {
233 .dma_map_consistent = pcibr_dma_map_consistent, 233 .dma_map_consistent = pcibr_dma_map_consistent,
234 .dma_unmap = pcibr_dma_unmap, 234 .dma_unmap = pcibr_dma_unmap,
235 .bus_fixup = pcibr_bus_fixup, 235 .bus_fixup = pcibr_bus_fixup,
236 .force_interrupt = pcibr_force_interrupt 236 .force_interrupt = pcibr_force_interrupt,
237 .target_interrupt = pcibr_target_interrupt
237}; 238};
238 239
239int 240int
diff --git a/arch/ia64/sn/pci/tioca_provider.c b/arch/ia64/sn/pci/tioca_provider.c
index 4ea04cfa30f..ea09c12f025 100644
--- a/arch/ia64/sn/pci/tioca_provider.c
+++ b/arch/ia64/sn/pci/tioca_provider.c
@@ -657,7 +657,8 @@ static struct sn_pcibus_provider tioca_pci_interfaces = {
657 .dma_map_consistent = tioca_dma_map, 657 .dma_map_consistent = tioca_dma_map,
658 .dma_unmap = tioca_dma_unmap, 658 .dma_unmap = tioca_dma_unmap,
659 .bus_fixup = tioca_bus_fixup, 659 .bus_fixup = tioca_bus_fixup,
660 .force_interrupt = NULL 660 .force_interrupt = NULL,
661 .target_interrupt = NULL
661}; 662};
662 663
663/** 664/**
diff --git a/arch/ia64/sn/pci/tioce_provider.c b/arch/ia64/sn/pci/tioce_provider.c
index d9081369cf9..8e75db2b825 100644
--- a/arch/ia64/sn/pci/tioce_provider.c
+++ b/arch/ia64/sn/pci/tioce_provider.c
@@ -669,6 +669,43 @@ tioce_force_interrupt(struct sn_irq_info *sn_irq_info)
669} 669}
670 670
671/** 671/**
672 * tioce_target_interrupt - implement set_irq_affinity for tioce resident
673 * functions. Note: only applies to line interrupts, not MSI's.
674 *
675 * @sn_irq_info: SN IRQ context
676 *
677 * Given an sn_irq_info, set the associated CE device's interrupt destination
678 * register. Since the interrupt destination registers are on a per-ce-slot
679 * basis, this will retarget line interrupts for all functions downstream of
680 * the slot.
681 */
682static void
683tioce_target_interrupt(struct sn_irq_info *sn_irq_info)
684{
685 struct pcidev_info *pcidev_info;
686 struct tioce_common *ce_common;
687 struct tioce *ce_mmr;
688 int bit;
689
690 pcidev_info = (struct pcidev_info *)sn_irq_info->irq_pciioinfo;
691 if (!pcidev_info)
692 return;
693
694 ce_common = (struct tioce_common *)pcidev_info->pdi_pcibus_info;
695 ce_mmr = (struct tioce *)ce_common->ce_pcibus.bs_base;
696
697 bit = sn_irq_info->irq_int_bit;
698
699 ce_mmr->ce_adm_int_mask |= (1UL << bit);
700 ce_mmr->ce_adm_int_dest[bit] =
701 ((uint64_t)sn_irq_info->irq_irq << INTR_VECTOR_SHFT) |
702 sn_irq_info->irq_xtalkaddr;
703 ce_mmr->ce_adm_int_mask &= ~(1UL << bit);
704
705 tioce_force_interrupt(sn_irq_info);
706}
707
708/**
672 * tioce_bus_fixup - perform final PCI fixup for a TIO CE bus 709 * tioce_bus_fixup - perform final PCI fixup for a TIO CE bus
673 * @prom_bussoft: Common prom/kernel struct representing the bus 710 * @prom_bussoft: Common prom/kernel struct representing the bus
674 * 711 *
@@ -719,7 +756,8 @@ static struct sn_pcibus_provider tioce_pci_interfaces = {
719 .dma_map_consistent = tioce_dma_consistent, 756 .dma_map_consistent = tioce_dma_consistent,
720 .dma_unmap = tioce_dma_unmap, 757 .dma_unmap = tioce_dma_unmap,
721 .bus_fixup = tioce_bus_fixup, 758 .bus_fixup = tioce_bus_fixup,
722 .force_interrupt = tioce_force_interrupt 759 .force_interrupt = tioce_force_interrupt,
760 .target_interrupt = tioce_target_interrupt
723}; 761};
724 762
725/** 763/**
diff --git a/include/asm-ia64/sn/pcibus_provider_defs.h b/include/asm-ia64/sn/pcibus_provider_defs.h
index 5a92f5149a9..ad0e8e8ae53 100644
--- a/include/asm-ia64/sn/pcibus_provider_defs.h
+++ b/include/asm-ia64/sn/pcibus_provider_defs.h
@@ -50,6 +50,7 @@ struct sn_pcibus_provider {
50 void (*dma_unmap)(struct pci_dev *, dma_addr_t, int); 50 void (*dma_unmap)(struct pci_dev *, dma_addr_t, int);
51 void * (*bus_fixup)(struct pcibus_bussoft *, struct pci_controller *); 51 void * (*bus_fixup)(struct pcibus_bussoft *, struct pci_controller *);
52 void (*force_interrupt)(struct sn_irq_info *); 52 void (*force_interrupt)(struct sn_irq_info *);
53 void (*target_interrupt)(struct sn_irq_info *);
53}; 54};
54 55
55extern struct sn_pcibus_provider *sn_pci_provider[]; 56extern struct sn_pcibus_provider *sn_pci_provider[];