Commit 2b889c52 authored by Andrew Morton's avatar Andrew Morton Committed by Linus Torvalds

[PATCH] sn: Code changes for interrupt redirect

From: Pat Gefre <pfg@sgi.com>

Code changes for interrupt redirect
parent 439ab81e
...@@ -81,7 +81,7 @@ void intr_init_vecblk(cnodeid_t node) ...@@ -81,7 +81,7 @@ void intr_init_vecblk(cnodeid_t node)
/* Config and enable UART interrupt, all nodes. */ /* Config and enable UART interrupt, all nodes. */
local5_config.sh_local_int5_config_regval = 0; local5_config.sh_local_int5_config_regval = 0;
local5_config.sh_local_int5_config_s.idx = SGI_UART_VECTOR; local5_config.sh_local_int5_config_s.idx = SGI_UART_VECTOR;
local5_config.sh_local_int5_config_s.pid = cpu0; local5_config.sh_local_int5_config_s.pid = cpu;
HUB_S((unsigned long *)GLOBAL_MMR_ADDR(nasid, SH_LOCAL_INT5_CONFIG), HUB_S((unsigned long *)GLOBAL_MMR_ADDR(nasid, SH_LOCAL_INT5_CONFIG),
local5_config.sh_local_int5_config_regval); local5_config.sh_local_int5_config_regval);
...@@ -222,7 +222,7 @@ static cpuid_t intr_cpu_choose_from_node(cnodeid_t cnode) ...@@ -222,7 +222,7 @@ static cpuid_t intr_cpu_choose_from_node(cnodeid_t cnode)
int intrs; int intrs;
cpu = cnode_slice_to_cpuid(cnode, slice); cpu = cnode_slice_to_cpuid(cnode, slice);
if (cpu == num_online_cpus()) if (cpu == NR_CPUS)
continue; continue;
if (!cpu_online(cpu)) if (!cpu_online(cpu))
continue; continue;
......
...@@ -9,5 +9,8 @@ ...@@ -9,5 +9,8 @@
# Makefile for the sn2 specific pci bridge routines. # Makefile for the sn2 specific pci bridge routines.
# #
obj-y += pcibr_ate.o pcibr_config.o pcibr_dvr.o pcibr_hints.o pcibr_intr.o pcibr_rrb.o \ obj-y += pcibr_ate.o pcibr_config.o \
pcibr_slot.o pcibr_error.o pcibr_dvr.o pcibr_hints.o \
pcibr_intr.o pcibr_rrb.o \
pcibr_slot.o pcibr_error.o \
pcibr_reg.o
...@@ -25,10 +25,8 @@ ...@@ -25,10 +25,8 @@
#include <asm/sn/klconfig.h> #include <asm/sn/klconfig.h>
#include <asm/sn/sn2/shub_mmr.h> #include <asm/sn/sn2/shub_mmr.h>
#include <asm/sn/sn_cpuid.h> #include <asm/sn/sn_cpuid.h>
#include <asm/sn/pci/pcibr.h>
#include <asm/sn/pci/pcibr_private.h>
typedef void pci_bridge_t;
/* ARGSUSED */ /* ARGSUSED */
void void
...@@ -39,11 +37,15 @@ hub_intr_init(vertex_hdl_t hubv) ...@@ -39,11 +37,15 @@ hub_intr_init(vertex_hdl_t hubv)
xwidgetnum_t xwidgetnum_t
hub_widget_id(nasid_t nasid) hub_widget_id(nasid_t nasid)
{ {
hubii_wcr_t ii_wcr; /* the control status register */
if (!(nasid & 1)) {
hubii_wcr_t ii_wcr; /* the control status register */
ii_wcr.wcr_reg_value = REMOTE_HUB_L(nasid,IIO_WCR); ii_wcr.wcr_reg_value = REMOTE_HUB_L(nasid,IIO_WCR);
return ii_wcr.wcr_fields_s.wcr_widget_id; return ii_wcr.wcr_fields_s.wcr_widget_id;
} else {
/* ICE does not have widget id. */
return(-1);
}
} }
static hub_intr_t static hub_intr_t
...@@ -52,7 +54,7 @@ do_hub_intr_alloc(vertex_hdl_t dev, ...@@ -52,7 +54,7 @@ do_hub_intr_alloc(vertex_hdl_t dev,
vertex_hdl_t owner_dev, vertex_hdl_t owner_dev,
int uncond_nothread) int uncond_nothread)
{ {
cpuid_t cpu = 0; cpuid_t cpu;
int vector; int vector;
hub_intr_t intr_hdl; hub_intr_t intr_hdl;
cnodeid_t cnode; cnodeid_t cnode;
...@@ -97,7 +99,7 @@ do_hub_intr_alloc(vertex_hdl_t dev, ...@@ -97,7 +99,7 @@ do_hub_intr_alloc(vertex_hdl_t dev,
intr_hdl->i_bit = vector; intr_hdl->i_bit = vector;
intr_hdl->i_flags |= HUB_INTR_IS_ALLOCED; intr_hdl->i_flags |= HUB_INTR_IS_ALLOCED;
return(intr_hdl); return intr_hdl;
} }
hub_intr_t hub_intr_t
...@@ -187,3 +189,73 @@ hub_intr_disconnect(hub_intr_t intr_hdl) ...@@ -187,3 +189,73 @@ hub_intr_disconnect(hub_intr_t intr_hdl)
ASSERT(rv == 0); ASSERT(rv == 0);
intr_hdl->i_flags &= ~HUB_INTR_IS_CONNECTED; intr_hdl->i_flags &= ~HUB_INTR_IS_CONNECTED;
} }
/*
* Redirect an interrupt to another cpu.
*/
void
sn_shub_redirect_intr(pcibr_intr_t intr, unsigned long cpu)
{
unsigned long bit;
int cpuphys, slice;
nasid_t nasid;
unsigned long xtalk_addr;
void *bridge = intr->bi_soft->bs_base;
int irq;
int i;
int old_cpu;
int new_cpu;
cpuphys = cpu_physical_id(cpu);
slice = cpu_physical_id_to_slice(cpuphys);
nasid = cpu_physical_id_to_nasid(cpuphys);
for (i = CPUS_PER_NODE - 1; i >= 0; i--) {
new_cpu = nasid_slice_to_cpuid(nasid, i);
if (new_cpu == NR_CPUS) {
continue;
}
if (!cpu_online(new_cpu)) {
continue;
}
break;
}
if (enable_shub_wars_1_1() && slice != i) {
printk("smp_affinity WARNING: SHUB 1.1 present: cannot target cpu %d, targeting cpu %d instead.\n",(int)cpu, new_cpu);
cpu = new_cpu;
slice = i;
}
if (slice) {
xtalk_addr = SH_II_INT1 | ((unsigned long)nasid << 36) | (1UL << 47);
} else {
xtalk_addr = SH_II_INT0 | ((unsigned long)nasid << 36) | (1UL << 47);
}
for (bit = 0; bit < 8; bit++) {
if (intr->bi_ibits & (1 << bit) ) {
/* Disable interrupts. */
pcireg_intr_enable_bit_clr(bridge, bit);
/* Reset Host address (Interrupt destination) */
pcireg_intr_addr_addr_set(bridge, bit, xtalk_addr);
/* Enable interrupt */
pcireg_intr_enable_bit_set(bridge, bit);
/* Force an interrupt, just in case. */
pcireg_force_intr_set(bridge, bit);
}
}
irq = intr->bi_irq;
old_cpu = intr->bi_cpu;
if (pdacpu(cpu)->sn_first_irq == 0 || pdacpu(cpu)->sn_first_irq > irq) {
pdacpu(cpu)->sn_first_irq = irq;
}
if (pdacpu(cpu)->sn_last_irq < irq) {
pdacpu(cpu)->sn_last_irq = irq;
}
pdacpu(old_cpu)->sn_num_irqs--;
pdacpu(cpu)->sn_num_irqs++;
intr->bi_cpu = (int)cpu;
}
...@@ -121,6 +121,7 @@ sn_set_affinity_irq(unsigned int irq, cpumask_t mask) ...@@ -121,6 +121,7 @@ sn_set_affinity_irq(unsigned int irq, cpumask_t mask)
pcibr_intr_list_t p = pcibr_intr_list[irq]; pcibr_intr_list_t p = pcibr_intr_list[irq];
pcibr_intr_t intr; pcibr_intr_t intr;
int cpu; int cpu;
extern void sn_shub_redirect_intr(pcibr_intr_t intr, unsigned long cpu);
extern void sn_tio_redirect_intr(pcibr_intr_t intr, unsigned long cpu); extern void sn_tio_redirect_intr(pcibr_intr_t intr, unsigned long cpu);
if (p == NULL) if (p == NULL)
...@@ -132,6 +133,11 @@ sn_set_affinity_irq(unsigned int irq, cpumask_t mask) ...@@ -132,6 +133,11 @@ sn_set_affinity_irq(unsigned int irq, cpumask_t mask)
return; return;
cpu = first_cpu(mask); cpu = first_cpu(mask);
if (IS_PIC_SOFT(intr->bi_soft) ) {
sn_shub_redirect_intr(intr, cpu);
} else {
return;
}
(void) set_irq_affinity_info(irq, cpu_physical_id(intr->bi_cpu), redir); (void) set_irq_affinity_info(irq, cpu_physical_id(intr->bi_cpu), redir);
#endif /* CONFIG_SMP */ #endif /* CONFIG_SMP */
} }
......
...@@ -58,6 +58,7 @@ extern void bte_init_node (nodepda_t *, cnodeid_t); ...@@ -58,6 +58,7 @@ extern void bte_init_node (nodepda_t *, cnodeid_t);
extern void bte_init_cpu (void); extern void bte_init_cpu (void);
extern void sn_timer_init(void); extern void sn_timer_init(void);
extern unsigned long last_time_offset; extern unsigned long last_time_offset;
extern void init_platform_hubinfo(nodepda_t **nodepdaindr);
extern void (*ia64_mark_idle)(int); extern void (*ia64_mark_idle)(int);
extern void snidle(int); extern void snidle(int);
...@@ -220,6 +221,8 @@ sn_setup(char **cmdline_p) ...@@ -220,6 +221,8 @@ sn_setup(char **cmdline_p)
int major = sn_sal_rev_major(), minor = sn_sal_rev_minor(); int major = sn_sal_rev_major(), minor = sn_sal_rev_minor();
extern nasid_t snia_get_master_baseio_nasid(void); extern nasid_t snia_get_master_baseio_nasid(void);
extern void sn_cpu_init(void); extern void sn_cpu_init(void);
extern nasid_t snia_get_console_nasid(void);
MAX_DMA_ADDRESS = PAGE_OFFSET + MAX_PHYS_MEMORY; MAX_DMA_ADDRESS = PAGE_OFFSET + MAX_PHYS_MEMORY;
......
...@@ -43,6 +43,10 @@ cfg_p pcibr_slot_config_addr(bridge_t *, pciio_slot_t, int); ...@@ -43,6 +43,10 @@ cfg_p pcibr_slot_config_addr(bridge_t *, pciio_slot_t, int);
cfg_p pcibr_func_config_addr(bridge_t *, pciio_bus_t bus, pciio_slot_t, pciio_function_t, int); cfg_p pcibr_func_config_addr(bridge_t *, pciio_bus_t bus, pciio_slot_t, pciio_function_t, int);
unsigned pcibr_slot_config_get(bridge_t *, pciio_slot_t, int); unsigned pcibr_slot_config_get(bridge_t *, pciio_slot_t, int);
unsigned pcibr_func_config_get(bridge_t *, pciio_slot_t, pciio_function_t, int); unsigned pcibr_func_config_get(bridge_t *, pciio_slot_t, pciio_function_t, int);
extern void pcireg_intr_enable_bit_clr(void *, uint64_t);
extern void pcireg_intr_enable_bit_set(void *, uint64_t);
extern void pcireg_intr_addr_addr_set(void *, int, uint64_t);
extern void pcireg_force_intr_set(void *, int);
void pcibr_debug(uint32_t, vertex_hdl_t, char *, ...); void pcibr_debug(uint32_t, vertex_hdl_t, char *, ...);
void pcibr_slot_config_set(bridge_t *, pciio_slot_t, int, unsigned); void pcibr_slot_config_set(bridge_t *, pciio_slot_t, int, unsigned);
void pcibr_func_config_set(bridge_t *, pciio_slot_t, pciio_function_t, int, void pcibr_func_config_set(bridge_t *, pciio_slot_t, pciio_function_t, int,
...@@ -304,6 +308,9 @@ struct pcibr_intr_wrap_s { ...@@ -304,6 +308,9 @@ struct pcibr_intr_wrap_s {
#define PV862253 (1 << 1) /* PIC: don't enable write req RAM parity checking */ #define PV862253 (1 << 1) /* PIC: don't enable write req RAM parity checking */
#define PV867308 (3 << 1) /* PIC: make LLP error interrupts FATAL for PIC */ #define PV867308 (3 << 1) /* PIC: make LLP error interrupts FATAL for PIC */
/* Bridgetype macros given a pcibr_soft structure */
#define IS_PIC_SOFT(ps) (ps->bs_bridge_type == PCIBR_BRIDGETYPE_PIC)
/* defines for pcibr_soft_s->bs_bridge_mode */ /* defines for pcibr_soft_s->bs_bridge_mode */
#define PCIBR_BRIDGEMODE_PCI_33 0x0 #define PCIBR_BRIDGEMODE_PCI_33 0x0
......
This diff is collapsed.
...@@ -60,6 +60,7 @@ typedef struct pda_s { ...@@ -60,6 +60,7 @@ typedef struct pda_s {
int sn_lb_int_war_ticks; int sn_lb_int_war_ticks;
int sn_last_irq; int sn_last_irq;
int sn_first_irq; int sn_first_irq;
int sn_num_irqs; /* number of irqs targeted for this cpu */
} pda_t; } pda_t;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment