[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>
This commit is contained in:
@@ -127,6 +127,7 @@ static void sn_set_affinity_irq(unsigned int irq, cpumask_t mask)
|
|||||||
int local_widget, status;
|
int local_widget, status;
|
||||||
nasid_t local_nasid;
|
nasid_t local_nasid;
|
||||||
struct sn_irq_info *new_irq_info;
|
struct sn_irq_info *new_irq_info;
|
||||||
|
struct sn_pcibus_provider *pci_provider;
|
||||||
|
|
||||||
new_irq_info = kmalloc(sizeof(struct sn_irq_info), GFP_ATOMIC);
|
new_irq_info = kmalloc(sizeof(struct sn_irq_info), GFP_ATOMIC);
|
||||||
if (new_irq_info == NULL)
|
if (new_irq_info == NULL)
|
||||||
@@ -166,8 +167,9 @@ static void sn_set_affinity_irq(unsigned int irq, cpumask_t mask)
|
|||||||
new_irq_info->irq_cpuid = cpuid;
|
new_irq_info->irq_cpuid = cpuid;
|
||||||
register_intr_pda(new_irq_info);
|
register_intr_pda(new_irq_info);
|
||||||
|
|
||||||
if (IS_PCI_BRIDGE_ASIC(new_irq_info->irq_bridge_type))
|
pci_provider = sn_pci_provider[new_irq_info->irq_bridge_type];
|
||||||
pcibr_change_devices_irq(new_irq_info);
|
if (pci_provider && pci_provider->target_interrupt)
|
||||||
|
(pci_provider->target_interrupt)(new_irq_info);
|
||||||
|
|
||||||
spin_lock(&sn_irq_info_lock);
|
spin_lock(&sn_irq_info_lock);
|
||||||
list_replace_rcu(&sn_irq_info->list, &new_irq_info->list);
|
list_replace_rcu(&sn_irq_info->list, &new_irq_info->list);
|
||||||
|
@@ -198,7 +198,7 @@ void pcibr_force_interrupt(struct sn_irq_info *sn_irq_info)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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 pcidev_info *pcidev_info;
|
||||||
struct pcibus_info *pcibus_info;
|
struct pcibus_info *pcibus_info;
|
||||||
@@ -233,7 +233,8 @@ struct sn_pcibus_provider pcibr_provider = {
|
|||||||
.dma_map_consistent = pcibr_dma_map_consistent,
|
.dma_map_consistent = pcibr_dma_map_consistent,
|
||||||
.dma_unmap = pcibr_dma_unmap,
|
.dma_unmap = pcibr_dma_unmap,
|
||||||
.bus_fixup = pcibr_bus_fixup,
|
.bus_fixup = pcibr_bus_fixup,
|
||||||
.force_interrupt = pcibr_force_interrupt
|
.force_interrupt = pcibr_force_interrupt,
|
||||||
|
.target_interrupt = pcibr_target_interrupt
|
||||||
};
|
};
|
||||||
|
|
||||||
int
|
int
|
||||||
|
@@ -657,7 +657,8 @@ static struct sn_pcibus_provider tioca_pci_interfaces = {
|
|||||||
.dma_map_consistent = tioca_dma_map,
|
.dma_map_consistent = tioca_dma_map,
|
||||||
.dma_unmap = tioca_dma_unmap,
|
.dma_unmap = tioca_dma_unmap,
|
||||||
.bus_fixup = tioca_bus_fixup,
|
.bus_fixup = tioca_bus_fixup,
|
||||||
.force_interrupt = NULL
|
.force_interrupt = NULL,
|
||||||
|
.target_interrupt = NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -668,6 +668,43 @@ tioce_force_interrupt(struct sn_irq_info *sn_irq_info)
|
|||||||
ce_mmr->ce_adm_force_int = force_int_val;
|
ce_mmr->ce_adm_force_int = force_int_val;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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
|
* tioce_bus_fixup - perform final PCI fixup for a TIO CE bus
|
||||||
* @prom_bussoft: Common prom/kernel struct representing the bus
|
* @prom_bussoft: Common prom/kernel struct representing the bus
|
||||||
@@ -719,7 +756,8 @@ static struct sn_pcibus_provider tioce_pci_interfaces = {
|
|||||||
.dma_map_consistent = tioce_dma_consistent,
|
.dma_map_consistent = tioce_dma_consistent,
|
||||||
.dma_unmap = tioce_dma_unmap,
|
.dma_unmap = tioce_dma_unmap,
|
||||||
.bus_fixup = tioce_bus_fixup,
|
.bus_fixup = tioce_bus_fixup,
|
||||||
.force_interrupt = tioce_force_interrupt
|
.force_interrupt = tioce_force_interrupt,
|
||||||
|
.target_interrupt = tioce_target_interrupt
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -50,6 +50,7 @@ struct sn_pcibus_provider {
|
|||||||
void (*dma_unmap)(struct pci_dev *, dma_addr_t, int);
|
void (*dma_unmap)(struct pci_dev *, dma_addr_t, int);
|
||||||
void * (*bus_fixup)(struct pcibus_bussoft *, struct pci_controller *);
|
void * (*bus_fixup)(struct pcibus_bussoft *, struct pci_controller *);
|
||||||
void (*force_interrupt)(struct sn_irq_info *);
|
void (*force_interrupt)(struct sn_irq_info *);
|
||||||
|
void (*target_interrupt)(struct sn_irq_info *);
|
||||||
};
|
};
|
||||||
|
|
||||||
extern struct sn_pcibus_provider *sn_pci_provider[];
|
extern struct sn_pcibus_provider *sn_pci_provider[];
|
||||||
|
Reference in New Issue
Block a user