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)
/* Config and enable UART interrupt, all nodes. */
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.pid = cpu0;
local5_config.sh_local_int5_config_s.pid = cpu;
HUB_S((unsigned long *)GLOBAL_MMR_ADDR(nasid, SH_LOCAL_INT5_CONFIG),
local5_config.sh_local_int5_config_regval);
......@@ -222,7 +222,7 @@ static cpuid_t intr_cpu_choose_from_node(cnodeid_t cnode)
int intrs;
cpu = cnode_slice_to_cpuid(cnode, slice);
if (cpu == num_online_cpus())
if (cpu == NR_CPUS)
continue;
if (!cpu_online(cpu))
continue;
......
......@@ -9,5 +9,8 @@
# 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 \
pcibr_slot.o pcibr_error.o
obj-y += pcibr_ate.o pcibr_config.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 @@
#include <asm/sn/klconfig.h>
#include <asm/sn/sn2/shub_mmr.h>
#include <asm/sn/sn_cpuid.h>
typedef void pci_bridge_t;
#include <asm/sn/pci/pcibr.h>
#include <asm/sn/pci/pcibr_private.h>
/* ARGSUSED */
void
......@@ -39,11 +37,15 @@ hub_intr_init(vertex_hdl_t hubv)
xwidgetnum_t
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);
return ii_wcr.wcr_fields_s.wcr_widget_id;
} else {
/* ICE does not have widget id. */
return(-1);
}
}
static hub_intr_t
......@@ -52,7 +54,7 @@ do_hub_intr_alloc(vertex_hdl_t dev,
vertex_hdl_t owner_dev,
int uncond_nothread)
{
cpuid_t cpu = 0;
cpuid_t cpu;
int vector;
hub_intr_t intr_hdl;
cnodeid_t cnode;
......@@ -97,7 +99,7 @@ do_hub_intr_alloc(vertex_hdl_t dev,
intr_hdl->i_bit = vector;
intr_hdl->i_flags |= HUB_INTR_IS_ALLOCED;
return(intr_hdl);
return intr_hdl;
}
hub_intr_t
......@@ -187,3 +189,73 @@ hub_intr_disconnect(hub_intr_t intr_hdl)
ASSERT(rv == 0);
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)
pcibr_intr_list_t p = pcibr_intr_list[irq];
pcibr_intr_t intr;
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);
if (p == NULL)
......@@ -132,6 +133,11 @@ sn_set_affinity_irq(unsigned int irq, cpumask_t mask)
return;
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);
#endif /* CONFIG_SMP */
}
......
......@@ -58,6 +58,7 @@ extern void bte_init_node (nodepda_t *, cnodeid_t);
extern void bte_init_cpu (void);
extern void sn_timer_init(void);
extern unsigned long last_time_offset;
extern void init_platform_hubinfo(nodepda_t **nodepdaindr);
extern void (*ia64_mark_idle)(int);
extern void snidle(int);
......@@ -220,6 +221,8 @@ sn_setup(char **cmdline_p)
int major = sn_sal_rev_major(), minor = sn_sal_rev_minor();
extern nasid_t snia_get_master_baseio_nasid(void);
extern void sn_cpu_init(void);
extern nasid_t snia_get_console_nasid(void);
MAX_DMA_ADDRESS = PAGE_OFFSET + MAX_PHYS_MEMORY;
......
......@@ -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);
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);
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_slot_config_set(bridge_t *, pciio_slot_t, int, unsigned);
void pcibr_func_config_set(bridge_t *, pciio_slot_t, pciio_function_t, int,
......@@ -304,6 +308,9 @@ struct pcibr_intr_wrap_s {
#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 */
/* 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 */
#define PCIBR_BRIDGEMODE_PCI_33 0x0
......
This diff is collapsed.
......@@ -60,6 +60,7 @@ typedef struct pda_s {
int sn_lb_int_war_ticks;
int sn_last_irq;
int sn_first_irq;
int sn_num_irqs; /* number of irqs targeted for this cpu */
} 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