Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

MIPS: SGI-IP27: rework HUB interrupts

This commit rearranges the HUB interrupt code by using MIPS_IRQ_CPU
interrupt handling code and modern Linux IRQ framework features to get
rid of global arrays. It also adds support for irq affinity setting.

Signed-off-by: Thomas Bogendoerfer <tbogendoerfer@suse.de>
Signed-off-by: Paul Burton <paul.burton@mips.com>
Cc: Ralf Baechle <ralf@linux-mips.org>
Cc: James Hogan <jhogan@kernel.org>
Cc: linux-mips@vger.kernel.org
Cc: linux-kernel@vger.kernel.org

authored by

Thomas Bogendoerfer and committed by
Paul Burton
69a07a41 2c865620

+265 -536
+1
arch/mips/Kconfig
··· 675 675 select DEFAULT_SGI_PARTITION 676 676 select SYS_HAS_EARLY_PRINTK 677 677 select HAVE_PCI 678 + select IRQ_MIPS_CPU 678 679 select NR_CPUS_DEFAULT_64 679 680 select SYS_HAS_CPU_R10000 680 681 select SYS_SUPPORTS_64BIT_KERNEL
+7 -5
arch/mips/include/asm/mach-ip27/irq.h
··· 10 10 #ifndef __ASM_MACH_IP27_IRQ_H 11 11 #define __ASM_MACH_IP27_IRQ_H 12 12 13 - /* 14 - * A hardwired interrupt number is completely stupid for this system - a 15 - * large configuration might have thousands if not tenthousands of 16 - * interrupts. 17 - */ 18 13 #define NR_IRQS 256 19 14 20 15 #include_next <irq.h> 16 + 17 + #define IP27_HUB_PEND0_IRQ (MIPS_CPU_IRQ_BASE + 2) 18 + #define IP27_HUB_PEND1_IRQ (MIPS_CPU_IRQ_BASE + 3) 19 + #define IP27_RT_TIMER_IRQ (MIPS_CPU_IRQ_BASE + 4) 20 + 21 + #define IP27_HUB_IRQ_BASE (MIPS_CPU_IRQ_BASE + 8) 22 + #define IP27_HUB_IRQ_COUNT 128 21 23 22 24 #endif /* __ASM_MACH_IP27_IRQ_H */
-9
arch/mips/include/asm/mach-ip27/mmzone.h
··· 8 8 9 9 #define pa_to_nid(addr) NASID_TO_COMPACT_NODEID(NASID_GET(addr)) 10 10 11 - #define LEVELS_PER_SLICE 128 12 - 13 - struct slice_data { 14 - unsigned long irq_enable_mask[2]; 15 - int level_to_irq[LEVELS_PER_SLICE]; 16 - }; 17 - 18 11 struct hub_data { 19 12 kern_vars_t kern_vars; 20 13 DECLARE_BITMAP(h_bigwin_used, HUB_NUM_BIG_WINDOW); 21 14 cpumask_t h_cpus; 22 15 unsigned long slice_map; 23 - unsigned long irq_alloc_mask[2]; 24 - struct slice_data slice[2]; 25 16 }; 26 17 27 18 struct node_data {
+1 -3
arch/mips/include/asm/pci/bridge.h
··· 808 808 struct bridge_regs *base; 809 809 nasid_t nasid; 810 810 unsigned int widget_id; 811 - unsigned int irq_cpu; 812 811 u64 baddr; 813 812 unsigned int pci_int[8]; 814 813 }; ··· 822 823 #define bridge_clr(bc, reg, val) \ 823 824 __raw_writel(__raw_readl(&bc->base->reg) & ~(val), &bc->base->reg) 824 825 825 - extern void register_bridge_irq(unsigned int irq); 826 - extern int request_bridge_irq(struct bridge_controller *bc); 826 + extern int request_bridge_irq(struct bridge_controller *bc, int pin); 827 827 828 828 extern struct pci_ops bridge_pci_ops; 829 829
+1 -17
arch/mips/pci/pci-ip27.c
··· 24 24 #define MAX_PCI_BUSSES 40 25 25 26 26 /* 27 - * Max #PCI devices (like scsi controllers) we handle on a bus. 28 - */ 29 - #define MAX_DEVICES_PER_PCIBUS 8 30 - 31 - /* 32 27 * XXX: No kmalloc available when we do our crosstalk scan, 33 28 * we should try to move it later in the boot process. 34 29 */ 35 30 static struct bridge_controller bridges[MAX_PCI_BUSSES]; 36 - 37 - /* 38 - * Translate from irq to software PCI bus number and PCI slot. 39 - */ 40 - struct bridge_controller *irq_to_bridge[MAX_PCI_BUSSES * MAX_DEVICES_PER_PCIBUS]; 41 - int irq_to_slot[MAX_PCI_BUSSES * MAX_DEVICES_PER_PCIBUS]; 42 31 43 32 extern struct pci_ops bridge_pci_ops; 44 33 ··· 66 77 bc->io.end = ~0UL; 67 78 bc->io.flags = IORESOURCE_IO; 68 79 69 - bc->irq_cpu = smp_processor_id(); 70 80 bc->widget_id = widget_id; 71 81 bc->nasid = nasid; 72 82 ··· 153 165 154 166 irq = bc->pci_int[slot]; 155 167 if (irq == -1) { 156 - irq = request_bridge_irq(bc); 168 + irq = request_bridge_irq(bc, slot); 157 169 if (irq < 0) 158 170 return irq; 159 171 160 172 bc->pci_int[slot] = irq; 161 173 } 162 - 163 - irq_to_bridge[irq] = bc; 164 - irq_to_slot[irq] = slot; 165 - 166 174 dev->irq = irq; 167 175 168 176 return 0;
+1 -2
arch/mips/sgi-ip27/Makefile
··· 3 3 # Makefile for the IP27 specific kernel interface routines under Linux. 4 4 # 5 5 6 - obj-y := ip27-berr.o ip27-irq.o ip27-irqno.o ip27-init.o ip27-klconfig.o \ 6 + obj-y := ip27-berr.o ip27-irq.o ip27-init.o ip27-klconfig.o \ 7 7 ip27-klnuma.o ip27-memory.o ip27-nmi.o ip27-reset.o ip27-timer.o \ 8 8 ip27-hubio.o ip27-xtalk.o 9 9 10 10 obj-$(CONFIG_EARLY_PRINTK) += ip27-console.o 11 - obj-$(CONFIG_PCI) += ip27-irq-pci.o 12 11 obj-$(CONFIG_SMP) += ip27-smp.o
+2 -31
arch/mips/sgi-ip27/ip27-init.c
··· 56 56 { 57 57 struct hub_data *hub = hub_data(cnode); 58 58 nasid_t nasid = COMPACT_TO_NASID_NODEID(cnode); 59 - int i; 60 59 61 60 cpumask_set_cpu(smp_processor_id(), &hub->h_cpus); 62 61 ··· 86 87 __flush_cache_all(); 87 88 } 88 89 #endif 89 - 90 - /* 91 - * Some interrupts are reserved by hardware or by software convention. 92 - * Mark these as reserved right away so they won't be used accidentally 93 - * later. 94 - */ 95 - for (i = 0; i <= BASE_PCI_IRQ; i++) { 96 - __set_bit(i, hub->irq_alloc_mask); 97 - LOCAL_HUB_CLR_INTR(INT_PEND0_BASELVL + i); 98 - } 99 - 100 - __set_bit(IP_PEND0_6_63, hub->irq_alloc_mask); 101 - LOCAL_HUB_S(PI_INT_PEND_MOD, IP_PEND0_6_63); 102 - 103 - for (i = NI_BRDCAST_ERR_A; i <= MSC_PANIC_INTR; i++) { 104 - __set_bit(i, hub->irq_alloc_mask); 105 - LOCAL_HUB_CLR_INTR(INT_PEND1_BASELVL + i); 106 - } 107 90 } 108 91 109 92 void per_cpu_init(void) ··· 94 113 int slice = LOCAL_HUB_L(PI_CPU_NUM); 95 114 cnodeid_t cnode = get_compact_nodeid(); 96 115 struct hub_data *hub = hub_data(cnode); 97 - struct slice_data *si = hub->slice + slice; 98 - int i; 99 116 100 117 if (test_and_set_bit(slice, &hub->slice_map)) 101 118 return; ··· 102 123 103 124 per_hub_init(cnode); 104 125 105 - for (i = 0; i < LEVELS_PER_SLICE; i++) 106 - si->level_to_irq[i] = -1; 107 - 108 - /* 109 - * We use this so we can find the local hub's data as fast as only 110 - * possible. 111 - */ 112 - cpu_data[cpu].data = si; 113 - 114 126 cpu_time_init(); 115 127 install_ipi(); 116 128 117 129 /* Install our NMI handler if symmon hasn't installed one. */ 118 130 install_cpu_nmi_handler(cputoslice(cpu)); 119 131 120 - set_c0_status(SRB_DEV0 | SRB_DEV1); 132 + enable_percpu_irq(IP27_HUB_PEND0_IRQ, IRQ_TYPE_NONE); 133 + enable_percpu_irq(IP27_HUB_PEND1_IRQ, IRQ_TYPE_NONE); 121 134 } 122 135 123 136 /*
-264
arch/mips/sgi-ip27/ip27-irq-pci.c
··· 1 - // SPDX-License-Identifier: GPL-2.0 2 - /* 3 - * ip27-irq.c: Highlevel interrupt handling for IP27 architecture. 4 - * 5 - * Copyright (C) 1999, 2000 Ralf Baechle (ralf@gnu.org) 6 - * Copyright (C) 1999, 2000 Silicon Graphics, Inc. 7 - * Copyright (C) 1999 - 2001 Kanoj Sarcar 8 - */ 9 - 10 - #undef DEBUG 11 - 12 - #include <linux/irq.h> 13 - #include <linux/errno.h> 14 - #include <linux/signal.h> 15 - #include <linux/sched.h> 16 - #include <linux/types.h> 17 - #include <linux/interrupt.h> 18 - #include <linux/ioport.h> 19 - #include <linux/timex.h> 20 - #include <linux/smp.h> 21 - #include <linux/random.h> 22 - #include <linux/kernel.h> 23 - #include <linux/kernel_stat.h> 24 - #include <linux/delay.h> 25 - #include <linux/bitops.h> 26 - 27 - #include <asm/bootinfo.h> 28 - #include <asm/io.h> 29 - #include <asm/mipsregs.h> 30 - 31 - #include <asm/processor.h> 32 - #include <asm/pci/bridge.h> 33 - #include <asm/sn/addrs.h> 34 - #include <asm/sn/agent.h> 35 - #include <asm/sn/arch.h> 36 - #include <asm/sn/hub.h> 37 - #include <asm/sn/intr.h> 38 - 39 - /* 40 - * Linux has a controller-independent x86 interrupt architecture. 41 - * every controller has a 'controller-template', that is used 42 - * by the main code to do the right thing. Each driver-visible 43 - * interrupt source is transparently wired to the appropriate 44 - * controller. Thus drivers need not be aware of the 45 - * interrupt-controller. 46 - * 47 - * Various interrupt controllers we handle: 8259 PIC, SMP IO-APIC, 48 - * PIIX4's internal 8259 PIC and SGI's Visual Workstation Cobalt (IO-)APIC. 49 - * (IO-APICs assumed to be messaging to Pentium local-APICs) 50 - * 51 - * the code is designed to be easily extended with new/different 52 - * interrupt controllers, without having to do assembly magic. 53 - */ 54 - 55 - extern struct bridge_controller *irq_to_bridge[]; 56 - extern int irq_to_slot[]; 57 - 58 - /* 59 - * use these macros to get the encoded nasid and widget id 60 - * from the irq value 61 - */ 62 - #define IRQ_TO_BRIDGE(i) irq_to_bridge[(i)] 63 - #define SLOT_FROM_PCI_IRQ(i) irq_to_slot[i] 64 - 65 - static inline int alloc_level(int cpu, int irq) 66 - { 67 - struct hub_data *hub = hub_data(cpu_to_node(cpu)); 68 - struct slice_data *si = cpu_data[cpu].data; 69 - int level; 70 - 71 - level = find_first_zero_bit(hub->irq_alloc_mask, LEVELS_PER_SLICE); 72 - if (level >= LEVELS_PER_SLICE) 73 - panic("Cpu %d flooded with devices", cpu); 74 - 75 - __set_bit(level, hub->irq_alloc_mask); 76 - si->level_to_irq[level] = irq; 77 - 78 - return level; 79 - } 80 - 81 - static inline int find_level(cpuid_t *cpunum, int irq) 82 - { 83 - int cpu, i; 84 - 85 - for_each_online_cpu(cpu) { 86 - struct slice_data *si = cpu_data[cpu].data; 87 - 88 - for (i = BASE_PCI_IRQ; i < LEVELS_PER_SLICE; i++) 89 - if (si->level_to_irq[i] == irq) { 90 - *cpunum = cpu; 91 - 92 - return i; 93 - } 94 - } 95 - 96 - panic("Could not identify cpu/level for irq %d", irq); 97 - } 98 - 99 - static int intr_connect_level(int cpu, int bit) 100 - { 101 - nasid_t nasid = COMPACT_TO_NASID_NODEID(cpu_to_node(cpu)); 102 - struct slice_data *si = cpu_data[cpu].data; 103 - 104 - set_bit(bit, si->irq_enable_mask); 105 - 106 - if (!cputoslice(cpu)) { 107 - REMOTE_HUB_S(nasid, PI_INT_MASK0_A, si->irq_enable_mask[0]); 108 - REMOTE_HUB_S(nasid, PI_INT_MASK1_A, si->irq_enable_mask[1]); 109 - } else { 110 - REMOTE_HUB_S(nasid, PI_INT_MASK0_B, si->irq_enable_mask[0]); 111 - REMOTE_HUB_S(nasid, PI_INT_MASK1_B, si->irq_enable_mask[1]); 112 - } 113 - 114 - return 0; 115 - } 116 - 117 - static int intr_disconnect_level(int cpu, int bit) 118 - { 119 - nasid_t nasid = COMPACT_TO_NASID_NODEID(cpu_to_node(cpu)); 120 - struct slice_data *si = cpu_data[cpu].data; 121 - 122 - clear_bit(bit, si->irq_enable_mask); 123 - 124 - if (!cputoslice(cpu)) { 125 - REMOTE_HUB_S(nasid, PI_INT_MASK0_A, si->irq_enable_mask[0]); 126 - REMOTE_HUB_S(nasid, PI_INT_MASK1_A, si->irq_enable_mask[1]); 127 - } else { 128 - REMOTE_HUB_S(nasid, PI_INT_MASK0_B, si->irq_enable_mask[0]); 129 - REMOTE_HUB_S(nasid, PI_INT_MASK1_B, si->irq_enable_mask[1]); 130 - } 131 - 132 - return 0; 133 - } 134 - 135 - /* Startup one of the (PCI ...) IRQs routes over a bridge. */ 136 - static unsigned int startup_bridge_irq(struct irq_data *d) 137 - { 138 - struct bridge_controller *bc; 139 - int pin, swlevel; 140 - cpuid_t cpu; 141 - u64 device; 142 - 143 - pin = SLOT_FROM_PCI_IRQ(d->irq); 144 - bc = IRQ_TO_BRIDGE(d->irq); 145 - 146 - pr_debug("bridge_startup(): irq= 0x%x pin=%d\n", d->irq, pin); 147 - /* 148 - * "map" irq to a swlevel greater than 6 since the first 6 bits 149 - * of INT_PEND0 are taken 150 - */ 151 - swlevel = find_level(&cpu, d->irq); 152 - bridge_write(bc, b_int_addr[pin].addr, 153 - (0x20000 | swlevel | (bc->nasid << 8))); 154 - bridge_set(bc, b_int_enable, (1 << pin)); 155 - bridge_set(bc, b_int_enable, 0x7ffffe00); /* more stuff in int_enable */ 156 - 157 - /* 158 - * Enable sending of an interrupt clear packt to the hub on a high to 159 - * low transition of the interrupt pin. 160 - * 161 - * IRIX sets additional bits in the address which are documented as 162 - * reserved in the bridge docs. 163 - */ 164 - bridge_set(bc, b_int_mode, (1UL << pin)); 165 - 166 - /* 167 - * We assume the bridge to have a 1:1 mapping between devices 168 - * (slots) and intr pins. 169 - */ 170 - device = bridge_read(bc, b_int_device); 171 - device &= ~(7 << (pin*3)); 172 - device |= (pin << (pin*3)); 173 - bridge_write(bc, b_int_device, device); 174 - 175 - bridge_read(bc, b_wid_tflush); 176 - 177 - intr_connect_level(cpu, swlevel); 178 - 179 - return 0; /* Never anything pending. */ 180 - } 181 - 182 - /* Shutdown one of the (PCI ...) IRQs routes over a bridge. */ 183 - static void shutdown_bridge_irq(struct irq_data *d) 184 - { 185 - struct bridge_controller *bc = IRQ_TO_BRIDGE(d->irq); 186 - int pin, swlevel; 187 - cpuid_t cpu; 188 - 189 - pr_debug("bridge_shutdown: irq 0x%x\n", d->irq); 190 - pin = SLOT_FROM_PCI_IRQ(d->irq); 191 - 192 - /* 193 - * map irq to a swlevel greater than 6 since the first 6 bits 194 - * of INT_PEND0 are taken 195 - */ 196 - swlevel = find_level(&cpu, d->irq); 197 - intr_disconnect_level(cpu, swlevel); 198 - 199 - bridge_clr(bc, b_int_enable, (1 << pin)); 200 - bridge_read(bc, b_wid_tflush); 201 - } 202 - 203 - static inline void enable_bridge_irq(struct irq_data *d) 204 - { 205 - cpuid_t cpu; 206 - int swlevel; 207 - 208 - swlevel = find_level(&cpu, d->irq); /* Criminal offence */ 209 - intr_connect_level(cpu, swlevel); 210 - } 211 - 212 - static inline void disable_bridge_irq(struct irq_data *d) 213 - { 214 - cpuid_t cpu; 215 - int swlevel; 216 - 217 - swlevel = find_level(&cpu, d->irq); /* Criminal offence */ 218 - intr_disconnect_level(cpu, swlevel); 219 - } 220 - 221 - static struct irq_chip bridge_irq_type = { 222 - .name = "bridge", 223 - .irq_startup = startup_bridge_irq, 224 - .irq_shutdown = shutdown_bridge_irq, 225 - .irq_mask = disable_bridge_irq, 226 - .irq_unmask = enable_bridge_irq, 227 - }; 228 - 229 - void register_bridge_irq(unsigned int irq) 230 - { 231 - irq_set_chip_and_handler(irq, &bridge_irq_type, handle_level_irq); 232 - } 233 - 234 - int request_bridge_irq(struct bridge_controller *bc) 235 - { 236 - int irq = allocate_irqno(); 237 - int swlevel, cpu; 238 - nasid_t nasid; 239 - 240 - if (irq < 0) 241 - return irq; 242 - 243 - /* 244 - * "map" irq to a swlevel greater than 6 since the first 6 bits 245 - * of INT_PEND0 are taken 246 - */ 247 - cpu = bc->irq_cpu; 248 - swlevel = alloc_level(cpu, irq); 249 - if (unlikely(swlevel < 0)) { 250 - free_irqno(irq); 251 - 252 - return -EAGAIN; 253 - } 254 - 255 - /* Make sure it's not already pending when we connect it. */ 256 - nasid = COMPACT_TO_NASID_NODEID(cpu_to_node(cpu)); 257 - REMOTE_HUB_CLR_INTR(nasid, swlevel); 258 - 259 - intr_connect_level(cpu, swlevel); 260 - 261 - register_bridge_irq(irq); 262 - 263 - return irq; 264 - }
+245 -122
arch/mips/sgi-ip27/ip27-irq.c
··· 7 7 * Copyright (C) 1999 - 2001 Kanoj Sarcar 8 8 */ 9 9 10 - #undef DEBUG 11 - 12 - #include <linux/init.h> 13 - #include <linux/irq.h> 14 - #include <linux/errno.h> 15 - #include <linux/signal.h> 16 - #include <linux/sched.h> 17 - #include <linux/types.h> 18 10 #include <linux/interrupt.h> 11 + #include <linux/irq.h> 19 12 #include <linux/ioport.h> 20 - #include <linux/timex.h> 21 - #include <linux/smp.h> 22 - #include <linux/random.h> 23 13 #include <linux/kernel.h> 24 - #include <linux/kernel_stat.h> 25 - #include <linux/delay.h> 26 14 #include <linux/bitops.h> 27 15 28 - #include <asm/bootinfo.h> 29 16 #include <asm/io.h> 30 - #include <asm/mipsregs.h> 31 - 32 - #include <asm/processor.h> 17 + #include <asm/irq_cpu.h> 18 + #include <asm/pci/bridge.h> 33 19 #include <asm/sn/addrs.h> 34 20 #include <asm/sn/agent.h> 35 21 #include <asm/sn/arch.h> 36 22 #include <asm/sn/hub.h> 37 23 #include <asm/sn/intr.h> 38 24 39 - /* 40 - * Linux has a controller-independent x86 interrupt architecture. 41 - * every controller has a 'controller-template', that is used 42 - * by the main code to do the right thing. Each driver-visible 43 - * interrupt source is transparently wired to the appropriate 44 - * controller. Thus drivers need not be aware of the 45 - * interrupt-controller. 46 - * 47 - * Various interrupt controllers we handle: 8259 PIC, SMP IO-APIC, 48 - * PIIX4's internal 8259 PIC and SGI's Visual Workstation Cobalt (IO-)APIC. 49 - * (IO-APICs assumed to be messaging to Pentium local-APICs) 50 - * 51 - * the code is designed to be easily extended with new/different 52 - * interrupt controllers, without having to do assembly magic. 53 - */ 25 + struct hub_irq_data { 26 + struct bridge_controller *bc; 27 + u64 *irq_mask[2]; 28 + cpuid_t cpu; 29 + int bit; 30 + int pin; 31 + }; 54 32 55 - extern asmlinkage void ip27_irq(void); 33 + static DECLARE_BITMAP(hub_irq_map, IP27_HUB_IRQ_COUNT); 56 34 57 - /* 58 - * Find first bit set 59 - */ 60 - static int ms1bit(unsigned long x) 35 + static DEFINE_PER_CPU(unsigned long [2], irq_enable_mask); 36 + 37 + static inline int alloc_level(void) 61 38 { 62 - int b = 0, s; 39 + int level; 63 40 64 - s = 16; if (x >> 16 == 0) s = 0; b += s; x >>= s; 65 - s = 8; if (x >> 8 == 0) s = 0; b += s; x >>= s; 66 - s = 4; if (x >> 4 == 0) s = 0; b += s; x >>= s; 67 - s = 2; if (x >> 2 == 0) s = 0; b += s; x >>= s; 68 - s = 1; if (x >> 1 == 0) s = 0; b += s; 41 + again: 42 + level = find_first_zero_bit(hub_irq_map, IP27_HUB_IRQ_COUNT); 43 + if (level >= IP27_HUB_IRQ_COUNT) 44 + return -ENOSPC; 69 45 70 - return b; 46 + if (test_and_set_bit(level, hub_irq_map)) 47 + goto again; 48 + 49 + return level; 50 + } 51 + 52 + static void enable_hub_irq(struct irq_data *d) 53 + { 54 + struct hub_irq_data *hd = irq_data_get_irq_chip_data(d); 55 + unsigned long *mask = per_cpu(irq_enable_mask, hd->cpu); 56 + 57 + set_bit(hd->bit, mask); 58 + __raw_writeq(mask[0], hd->irq_mask[0]); 59 + __raw_writeq(mask[1], hd->irq_mask[1]); 60 + } 61 + 62 + static void disable_hub_irq(struct irq_data *d) 63 + { 64 + struct hub_irq_data *hd = irq_data_get_irq_chip_data(d); 65 + unsigned long *mask = per_cpu(irq_enable_mask, hd->cpu); 66 + 67 + clear_bit(hd->bit, mask); 68 + __raw_writeq(mask[0], hd->irq_mask[0]); 69 + __raw_writeq(mask[1], hd->irq_mask[1]); 70 + } 71 + 72 + static unsigned int startup_bridge_irq(struct irq_data *d) 73 + { 74 + struct hub_irq_data *hd = irq_data_get_irq_chip_data(d); 75 + struct bridge_controller *bc; 76 + nasid_t nasid; 77 + u32 device; 78 + int pin; 79 + 80 + if (!hd) 81 + return -EINVAL; 82 + 83 + pin = hd->pin; 84 + bc = hd->bc; 85 + 86 + nasid = COMPACT_TO_NASID_NODEID(cpu_to_node(hd->cpu)); 87 + bridge_write(bc, b_int_addr[pin].addr, 88 + (0x20000 | hd->bit | (nasid << 8))); 89 + bridge_set(bc, b_int_enable, (1 << pin)); 90 + bridge_set(bc, b_int_enable, 0x7ffffe00); /* more stuff in int_enable */ 91 + 92 + /* 93 + * Enable sending of an interrupt clear packt to the hub on a high to 94 + * low transition of the interrupt pin. 95 + * 96 + * IRIX sets additional bits in the address which are documented as 97 + * reserved in the bridge docs. 98 + */ 99 + bridge_set(bc, b_int_mode, (1UL << pin)); 100 + 101 + /* 102 + * We assume the bridge to have a 1:1 mapping between devices 103 + * (slots) and intr pins. 104 + */ 105 + device = bridge_read(bc, b_int_device); 106 + device &= ~(7 << (pin*3)); 107 + device |= (pin << (pin*3)); 108 + bridge_write(bc, b_int_device, device); 109 + 110 + bridge_read(bc, b_wid_tflush); 111 + 112 + enable_hub_irq(d); 113 + 114 + return 0; /* Never anything pending. */ 115 + } 116 + 117 + static void shutdown_bridge_irq(struct irq_data *d) 118 + { 119 + struct hub_irq_data *hd = irq_data_get_irq_chip_data(d); 120 + struct bridge_controller *bc; 121 + int pin = hd->pin; 122 + 123 + if (!hd) 124 + return; 125 + 126 + disable_hub_irq(d); 127 + 128 + bc = hd->bc; 129 + bridge_clr(bc, b_int_enable, (1 << pin)); 130 + bridge_read(bc, b_wid_tflush); 131 + } 132 + 133 + static void setup_hub_mask(struct hub_irq_data *hd, const struct cpumask *mask) 134 + { 135 + nasid_t nasid; 136 + int cpu; 137 + 138 + cpu = cpumask_first_and(mask, cpu_online_mask); 139 + nasid = COMPACT_TO_NASID_NODEID(cpu_to_node(cpu)); 140 + hd->cpu = cpu; 141 + if (!cputoslice(cpu)) { 142 + hd->irq_mask[0] = REMOTE_HUB_PTR(nasid, PI_INT_MASK0_A); 143 + hd->irq_mask[1] = REMOTE_HUB_PTR(nasid, PI_INT_MASK1_A); 144 + } else { 145 + hd->irq_mask[0] = REMOTE_HUB_PTR(nasid, PI_INT_MASK0_B); 146 + hd->irq_mask[1] = REMOTE_HUB_PTR(nasid, PI_INT_MASK1_B); 147 + } 148 + 149 + /* Make sure it's not already pending when we connect it. */ 150 + REMOTE_HUB_CLR_INTR(nasid, hd->bit); 151 + } 152 + 153 + static int set_affinity_hub_irq(struct irq_data *d, const struct cpumask *mask, 154 + bool force) 155 + { 156 + struct hub_irq_data *hd = irq_data_get_irq_chip_data(d); 157 + 158 + if (!hd) 159 + return -EINVAL; 160 + 161 + if (irqd_is_started(d)) 162 + disable_hub_irq(d); 163 + 164 + setup_hub_mask(hd, mask); 165 + 166 + if (irqd_is_started(d)) 167 + startup_bridge_irq(d); 168 + 169 + irq_data_update_effective_affinity(d, cpumask_of(hd->cpu)); 170 + 171 + return 0; 172 + } 173 + 174 + static struct irq_chip hub_irq_type = { 175 + .name = "HUB", 176 + .irq_startup = startup_bridge_irq, 177 + .irq_shutdown = shutdown_bridge_irq, 178 + .irq_mask = disable_hub_irq, 179 + .irq_unmask = enable_hub_irq, 180 + .irq_set_affinity = set_affinity_hub_irq, 181 + }; 182 + 183 + int request_bridge_irq(struct bridge_controller *bc, int pin) 184 + { 185 + struct hub_irq_data *hd; 186 + struct hub_data *hub; 187 + struct irq_desc *desc; 188 + int swlevel; 189 + int irq; 190 + 191 + hd = kzalloc(sizeof(*hd), GFP_KERNEL); 192 + if (!hd) 193 + return -ENOMEM; 194 + 195 + swlevel = alloc_level(); 196 + if (unlikely(swlevel < 0)) { 197 + kfree(hd); 198 + return -EAGAIN; 199 + } 200 + irq = swlevel + IP27_HUB_IRQ_BASE; 201 + 202 + hd->bc = bc; 203 + hd->bit = swlevel; 204 + hd->pin = pin; 205 + irq_set_chip_data(irq, hd); 206 + 207 + /* use CPU connected to nearest hub */ 208 + hub = hub_data(NASID_TO_COMPACT_NODEID(bc->nasid)); 209 + setup_hub_mask(hd, &hub->h_cpus); 210 + 211 + desc = irq_to_desc(irq); 212 + desc->irq_common_data.node = bc->nasid; 213 + cpumask_copy(desc->irq_common_data.affinity, &hub->h_cpus); 214 + 215 + return irq; 216 + } 217 + 218 + void ip27_hub_irq_init(void) 219 + { 220 + int i; 221 + 222 + for (i = IP27_HUB_IRQ_BASE; 223 + i < (IP27_HUB_IRQ_BASE + IP27_HUB_IRQ_COUNT); i++) 224 + irq_set_chip_and_handler(i, &hub_irq_type, handle_level_irq); 225 + 226 + /* 227 + * Some interrupts are reserved by hardware or by software convention. 228 + * Mark these as reserved right away so they won't be used accidentally 229 + * later. 230 + */ 231 + for (i = 0; i <= BASE_PCI_IRQ; i++) 232 + set_bit(i, hub_irq_map); 233 + 234 + set_bit(IP_PEND0_6_63, hub_irq_map); 235 + 236 + for (i = NI_BRDCAST_ERR_A; i <= MSC_PANIC_INTR; i++) 237 + set_bit(i, hub_irq_map); 71 238 } 72 239 73 240 /* ··· 249 82 * Kanoj 05.13.00 250 83 */ 251 84 252 - static void ip27_do_irq_mask0(void) 85 + static void ip27_do_irq_mask0(struct irq_desc *desc) 253 86 { 254 - int irq, swlevel; 255 - u64 pend0, mask0; 256 87 cpuid_t cpu = smp_processor_id(); 257 - int pi_int_mask0 = 258 - (cputoslice(cpu) == 0) ? PI_INT_MASK0_A : PI_INT_MASK0_B; 88 + unsigned long *mask = per_cpu(irq_enable_mask, cpu); 89 + u64 pend0; 259 90 260 91 /* copied from Irix intpend0() */ 261 92 pend0 = LOCAL_HUB_L(PI_INT_PEND0); 262 - mask0 = LOCAL_HUB_L(pi_int_mask0); 263 93 264 - pend0 &= mask0; /* Pick intrs we should look at */ 94 + pend0 &= mask[0]; /* Pick intrs we should look at */ 265 95 if (!pend0) 266 96 return; 267 97 268 - swlevel = ms1bit(pend0); 269 98 #ifdef CONFIG_SMP 270 99 if (pend0 & (1UL << CPU_RESCHED_A_IRQ)) { 271 100 LOCAL_HUB_CLR_INTR(CPU_RESCHED_A_IRQ); ··· 271 108 scheduler_ipi(); 272 109 } else if (pend0 & (1UL << CPU_CALL_A_IRQ)) { 273 110 LOCAL_HUB_CLR_INTR(CPU_CALL_A_IRQ); 274 - irq_enter(); 275 111 generic_smp_call_function_interrupt(); 276 - irq_exit(); 277 112 } else if (pend0 & (1UL << CPU_CALL_B_IRQ)) { 278 113 LOCAL_HUB_CLR_INTR(CPU_CALL_B_IRQ); 279 - irq_enter(); 280 114 generic_smp_call_function_interrupt(); 281 - irq_exit(); 282 115 } else 283 116 #endif 284 - { 285 - /* "map" swlevel to irq */ 286 - struct slice_data *si = cpu_data[cpu].data; 287 - 288 - irq = si->level_to_irq[swlevel]; 289 - do_IRQ(irq); 290 - } 117 + generic_handle_irq(__ffs(pend0) + IP27_HUB_IRQ_BASE); 291 118 292 119 LOCAL_HUB_L(PI_INT_PEND0); 293 120 } 294 121 295 - static void ip27_do_irq_mask1(void) 122 + static void ip27_do_irq_mask1(struct irq_desc *desc) 296 123 { 297 - int irq, swlevel; 298 - u64 pend1, mask1; 299 124 cpuid_t cpu = smp_processor_id(); 300 - int pi_int_mask1 = (cputoslice(cpu) == 0) ? PI_INT_MASK1_A : PI_INT_MASK1_B; 301 - struct slice_data *si = cpu_data[cpu].data; 125 + unsigned long *mask = per_cpu(irq_enable_mask, cpu); 126 + u64 pend1; 302 127 303 128 /* copied from Irix intpend0() */ 304 129 pend1 = LOCAL_HUB_L(PI_INT_PEND1); 305 - mask1 = LOCAL_HUB_L(pi_int_mask1); 306 130 307 - pend1 &= mask1; /* Pick intrs we should look at */ 131 + pend1 &= mask[1]; /* Pick intrs we should look at */ 308 132 if (!pend1) 309 133 return; 310 134 311 - swlevel = ms1bit(pend1); 312 - /* "map" swlevel to irq */ 313 - irq = si->level_to_irq[swlevel]; 314 - LOCAL_HUB_CLR_INTR(swlevel); 315 - do_IRQ(irq); 135 + generic_handle_irq(__ffs(pend1) + IP27_HUB_IRQ_BASE + 64); 316 136 317 137 LOCAL_HUB_L(PI_INT_PEND1); 318 138 } 319 139 320 - static void ip27_prof_timer(void) 140 + void install_ipi(void) 321 141 { 322 - panic("CPU %d got a profiling interrupt", smp_processor_id()); 323 - } 142 + int cpu = smp_processor_id(); 143 + unsigned long *mask = per_cpu(irq_enable_mask, cpu); 144 + int slice = LOCAL_HUB_L(PI_CPU_NUM); 145 + int resched, call; 324 146 325 - static void ip27_hub_error(void) 326 - { 327 - panic("CPU %d got a hub error interrupt", smp_processor_id()); 328 - } 147 + resched = CPU_RESCHED_A_IRQ + slice; 148 + set_bit(resched, mask); 149 + LOCAL_HUB_CLR_INTR(resched); 329 150 330 - asmlinkage void plat_irq_dispatch(void) 331 - { 332 - unsigned long pending = read_c0_cause() & read_c0_status(); 333 - extern unsigned int rt_timer_irq; 151 + call = CPU_CALL_A_IRQ + slice; 152 + set_bit(call, mask); 153 + LOCAL_HUB_CLR_INTR(call); 334 154 335 - if (pending & CAUSEF_IP4) 336 - do_IRQ(rt_timer_irq); 337 - else if (pending & CAUSEF_IP2) /* PI_INT_PEND_0 or CC_PEND_{A|B} */ 338 - ip27_do_irq_mask0(); 339 - else if (pending & CAUSEF_IP3) /* PI_INT_PEND_1 */ 340 - ip27_do_irq_mask1(); 341 - else if (pending & CAUSEF_IP5) 342 - ip27_prof_timer(); 343 - else if (pending & CAUSEF_IP6) 344 - ip27_hub_error(); 155 + if (slice == 0) { 156 + LOCAL_HUB_S(PI_INT_MASK0_A, mask[0]); 157 + LOCAL_HUB_S(PI_INT_MASK1_A, mask[1]); 158 + } else { 159 + LOCAL_HUB_S(PI_INT_MASK0_B, mask[0]); 160 + LOCAL_HUB_S(PI_INT_MASK1_B, mask[1]); 161 + } 345 162 } 346 163 347 164 void __init arch_init_irq(void) 348 165 { 349 - } 166 + mips_cpu_irq_init(); 167 + ip27_hub_irq_init(); 350 168 351 - void install_ipi(void) 352 - { 353 - int slice = LOCAL_HUB_L(PI_CPU_NUM); 354 - int cpu = smp_processor_id(); 355 - struct slice_data *si = cpu_data[cpu].data; 356 - struct hub_data *hub = hub_data(cpu_to_node(cpu)); 357 - int resched, call; 358 - 359 - resched = CPU_RESCHED_A_IRQ + slice; 360 - __set_bit(resched, hub->irq_alloc_mask); 361 - __set_bit(resched, si->irq_enable_mask); 362 - LOCAL_HUB_CLR_INTR(resched); 363 - 364 - call = CPU_CALL_A_IRQ + slice; 365 - __set_bit(call, hub->irq_alloc_mask); 366 - __set_bit(call, si->irq_enable_mask); 367 - LOCAL_HUB_CLR_INTR(call); 368 - 369 - if (slice == 0) { 370 - LOCAL_HUB_S(PI_INT_MASK0_A, si->irq_enable_mask[0]); 371 - LOCAL_HUB_S(PI_INT_MASK1_A, si->irq_enable_mask[1]); 372 - } else { 373 - LOCAL_HUB_S(PI_INT_MASK0_B, si->irq_enable_mask[0]); 374 - LOCAL_HUB_S(PI_INT_MASK1_B, si->irq_enable_mask[1]); 375 - } 169 + irq_set_percpu_devid(IP27_HUB_PEND0_IRQ); 170 + irq_set_chained_handler(IP27_HUB_PEND0_IRQ, ip27_do_irq_mask0); 171 + irq_set_percpu_devid(IP27_HUB_PEND1_IRQ); 172 + irq_set_chained_handler(IP27_HUB_PEND1_IRQ, ip27_do_irq_mask1); 376 173 }
-48
arch/mips/sgi-ip27/ip27-irqno.c
··· 1 - /* 2 - * This file is subject to the terms and conditions of the GNU General Public 3 - * License. See the file "COPYING" in the main directory of this archive 4 - * for more details. 5 - */ 6 - #include <linux/init.h> 7 - #include <linux/irq.h> 8 - #include <linux/types.h> 9 - 10 - #include <asm/barrier.h> 11 - 12 - static DECLARE_BITMAP(irq_map, NR_IRQS); 13 - 14 - int allocate_irqno(void) 15 - { 16 - int irq; 17 - 18 - again: 19 - irq = find_first_zero_bit(irq_map, NR_IRQS); 20 - 21 - if (irq >= NR_IRQS) 22 - return -ENOSPC; 23 - 24 - if (test_and_set_bit(irq, irq_map)) 25 - goto again; 26 - 27 - return irq; 28 - } 29 - 30 - /* 31 - * Allocate the 16 legacy interrupts for i8259 devices. This happens early 32 - * in the kernel initialization so treating allocation failure as BUG() is 33 - * ok. 34 - */ 35 - void __init alloc_legacy_irqno(void) 36 - { 37 - int i; 38 - 39 - for (i = 0; i <= 16; i++) 40 - BUG_ON(test_and_set_bit(i, irq_map)); 41 - } 42 - 43 - void free_irqno(unsigned int irq) 44 - { 45 - smp_mb__before_atomic(); 46 - clear_bit(irq, irq_map); 47 - smp_mb__after_atomic(); 48 - }
+7 -35
arch/mips/sgi-ip27/ip27-timer.c
··· 38 38 #include <asm/sn/sn0/hubio.h> 39 39 #include <asm/pci/bridge.h> 40 40 41 - static void enable_rt_irq(struct irq_data *d) 42 - { 43 - } 44 - 45 - static void disable_rt_irq(struct irq_data *d) 46 - { 47 - } 48 - 49 - static struct irq_chip rt_irq_type = { 50 - .name = "SN HUB RT timer", 51 - .irq_mask = disable_rt_irq, 52 - .irq_unmask = enable_rt_irq, 53 - }; 54 - 55 41 static int rt_next_event(unsigned long delta, struct clock_event_device *evt) 56 42 { 57 43 unsigned int cpu = smp_processor_id(); ··· 50 64 51 65 return LOCAL_HUB_L(PI_RT_COUNT) >= cnt ? -ETIME : 0; 52 66 } 53 - 54 - unsigned int rt_timer_irq; 55 67 56 68 static DEFINE_PER_CPU(struct clock_event_device, hub_rt_clockevent); 57 69 static DEFINE_PER_CPU(char [11], hub_rt_name); ··· 71 87 72 88 struct irqaction hub_rt_irqaction = { 73 89 .handler = hub_rt_counter_handler, 90 + .percpu_dev_id = &hub_rt_clockevent, 74 91 .flags = IRQF_PERCPU | IRQF_TIMER, 75 92 .name = "hub-rt", 76 93 }; ··· 92 107 unsigned int cpu = smp_processor_id(); 93 108 struct clock_event_device *cd = &per_cpu(hub_rt_clockevent, cpu); 94 109 unsigned char *name = per_cpu(hub_rt_name, cpu); 95 - int irq = rt_timer_irq; 96 110 97 111 sprintf(name, "hub-rt %d", cpu); 98 112 cd->name = name; ··· 102 118 cd->min_delta_ns = clockevent_delta2ns(0x300, cd); 103 119 cd->min_delta_ticks = 0x300; 104 120 cd->rating = 200; 105 - cd->irq = irq; 121 + cd->irq = IP27_RT_TIMER_IRQ; 106 122 cd->cpumask = cpumask_of(cpu); 107 123 cd->set_next_event = rt_next_event; 108 124 clockevents_register_device(cd); 125 + 126 + enable_percpu_irq(IP27_RT_TIMER_IRQ, IRQ_TYPE_NONE); 109 127 } 110 128 111 129 static void __init hub_rt_clock_event_global_init(void) 112 130 { 113 - int irq; 114 - 115 - do { 116 - smp_wmb(); 117 - irq = rt_timer_irq; 118 - if (irq) 119 - break; 120 - 121 - irq = allocate_irqno(); 122 - if (irq < 0) 123 - panic("Allocation of irq number for timer failed"); 124 - } while (xchg(&rt_timer_irq, irq)); 125 - 126 - irq_set_chip_and_handler(irq, &rt_irq_type, handle_percpu_irq); 127 - setup_irq(irq, &hub_rt_irqaction); 131 + irq_set_handler(IP27_RT_TIMER_IRQ, handle_percpu_devid_irq); 132 + irq_set_percpu_devid(IP27_RT_TIMER_IRQ); 133 + setup_percpu_irq(IP27_RT_TIMER_IRQ, &hub_rt_irqaction); 128 134 } 129 135 130 136 static u64 hub_rt_read(struct clocksource *cs) ··· 168 194 panic("No information about myself?"); 169 195 170 196 printk("CPU %d clock is %dMHz.\n", smp_processor_id(), cpu->cpu_speed); 171 - 172 - set_c0_status(SRB_TIMOCLK); 173 197 } 174 198 175 199 void hub_rtc_init(cnodeid_t cnode)