tree 7783a2e701b7ae866be858e9121ec70f91fe4fa9
parent 5b9021bc5800796e23e4994f8cf2dc61536be0a7
author Mark Maule <[EMAIL PROTECTED]> Fri, 26 Aug 2005 01:45:00 -0700
committer Tony Luck <[EMAIL PROTECTED]> Sat, 27 Aug 2005 02:09:01 -0700

[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 <[EMAIL PROTECTED]>
Signed-off-by: Tony Luck <[EMAIL PROTECTED]>

 arch/ia64/sn/kernel/irq.c                  |    6 ++--
 arch/ia64/sn/pci/pcibr/pcibr_provider.c    |    5 ++-
 arch/ia64/sn/pci/tioca_provider.c          |    3 +-
 arch/ia64/sn/pci/tioce_provider.c          |   40 ++++++++++++++++++++++++++++-
 include/asm-ia64/sn/pcibus_provider_defs.h |    1 
 5 files changed, 49 insertions(+), 6 deletions(-)

diff --git a/arch/ia64/sn/kernel/irq.c b/arch/ia64/sn/kernel/irq.c
--- 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 local_widget, status;
                nasid_t local_nasid;
                struct sn_irq_info *new_irq_info;
+               struct sn_pcibus_provider *pci_provider;
 
                new_irq_info = kmalloc(sizeof(struct sn_irq_info), GFP_ATOMIC);
                if (new_irq_info == NULL)
@@ -166,8 +167,9 @@ static void sn_set_affinity_irq(unsigned
                new_irq_info->irq_cpuid = cpuid;
                register_intr_pda(new_irq_info);
 
-               if (IS_PCI_BRIDGE_ASIC(new_irq_info->irq_bridge_type))
-                       pcibr_change_devices_irq(new_irq_info);
+               pci_provider = sn_pci_provider[new_irq_info->irq_bridge_type];
+               if (pci_provider && pci_provider->target_interrupt)
+                       (pci_provider->target_interrupt)(new_irq_info);
 
                spin_lock(&sn_irq_info_lock);
                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
--- 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
        }
 }
 
-void pcibr_change_devices_irq(struct sn_irq_info *sn_irq_info)
+void pcibr_target_interrupt(struct sn_irq_info *sn_irq_info)
 {
        struct pcidev_info *pcidev_info;
        struct pcibus_info *pcibus_info;
@@ -233,7 +233,8 @@ struct sn_pcibus_provider pcibr_provider
        .dma_map_consistent = pcibr_dma_map_consistent,
        .dma_unmap = pcibr_dma_unmap,
        .bus_fixup = pcibr_bus_fixup,
-       .force_interrupt = pcibr_force_interrupt
+       .force_interrupt = pcibr_force_interrupt,
+       .target_interrupt = pcibr_target_interrupt
 };
 
 int
diff --git a/arch/ia64/sn/pci/tioca_provider.c 
b/arch/ia64/sn/pci/tioca_provider.c
--- 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_p
        .dma_map_consistent = tioca_dma_map,
        .dma_unmap = tioca_dma_unmap,
        .bus_fixup = tioca_bus_fixup,
-       .force_interrupt = NULL
+       .force_interrupt = NULL,
+       .target_interrupt = NULL
 };
 
 /**
diff --git a/arch/ia64/sn/pci/tioce_provider.c 
b/arch/ia64/sn/pci/tioce_provider.c
--- 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
 }
 
 /**
+ * tioce_target_interrupt - implement set_irq_affinity for tioce resident
+ * functions.  Note:  only applies to line interrupts, not MSI's.
+ *
+ * @sn_irq_info: SN IRQ context
+ *
+ * Given an sn_irq_info, set the associated CE device's interrupt destination
+ * register.  Since the interrupt destination registers are on a per-ce-slot
+ * basis, this will retarget line interrupts for all functions downstream of
+ * the slot.
+ */
+static void
+tioce_target_interrupt(struct sn_irq_info *sn_irq_info)
+{
+       struct pcidev_info *pcidev_info;
+       struct tioce_common *ce_common;
+       struct tioce *ce_mmr;
+       int bit;
+
+       pcidev_info = (struct pcidev_info *)sn_irq_info->irq_pciioinfo;
+       if (!pcidev_info)
+               return;
+
+       ce_common = (struct tioce_common *)pcidev_info->pdi_pcibus_info;
+       ce_mmr = (struct tioce *)ce_common->ce_pcibus.bs_base;
+
+       bit = sn_irq_info->irq_int_bit;
+
+       ce_mmr->ce_adm_int_mask |= (1UL << bit);
+       ce_mmr->ce_adm_int_dest[bit] =
+               ((uint64_t)sn_irq_info->irq_irq << INTR_VECTOR_SHFT) |
+                          sn_irq_info->irq_xtalkaddr;
+       ce_mmr->ce_adm_int_mask &= ~(1UL << bit);
+
+       tioce_force_interrupt(sn_irq_info);
+}
+
+/**
  * tioce_bus_fixup - perform final PCI fixup for a TIO CE bus
  * @prom_bussoft: Common prom/kernel struct representing the bus
  *
@@ -719,7 +756,8 @@ static struct sn_pcibus_provider tioce_p
        .dma_map_consistent = tioce_dma_consistent,
        .dma_unmap = tioce_dma_unmap,
        .bus_fixup = tioce_bus_fixup,
-       .force_interrupt = tioce_force_interrupt
+       .force_interrupt = tioce_force_interrupt,
+       .target_interrupt = tioce_target_interrupt
 };
 
 /**
diff --git a/include/asm-ia64/sn/pcibus_provider_defs.h 
b/include/asm-ia64/sn/pcibus_provider_defs.h
--- 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 {
        void            (*dma_unmap)(struct pci_dev *, dma_addr_t, int);
        void *          (*bus_fixup)(struct pcibus_bussoft *, struct 
pci_controller *);
        void            (*force_interrupt)(struct sn_irq_info *);
+       void            (*target_interrupt)(struct sn_irq_info *);
 };
 
 extern struct sn_pcibus_provider *sn_pci_provider[];
-
To unsubscribe from this list: send the line "unsubscribe git-commits-head" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to