diff options
Diffstat (limited to 'arch/mips/sgi-ip27')
| -rw-r--r-- | arch/mips/sgi-ip27/Kconfig | 7 | ||||
| -rw-r--r-- | arch/mips/sgi-ip27/Makefile | 4 | ||||
| -rw-r--r-- | arch/mips/sgi-ip27/Platform | 19 | ||||
| -rw-r--r-- | arch/mips/sgi-ip27/TODO | 2 | ||||
| -rw-r--r-- | arch/mips/sgi-ip27/ip27-berr.c | 6 | ||||
| -rw-r--r-- | arch/mips/sgi-ip27/ip27-console.c | 4 | ||||
| -rw-r--r-- | arch/mips/sgi-ip27/ip27-dbgio.c | 60 | ||||
| -rw-r--r-- | arch/mips/sgi-ip27/ip27-hubio.c | 17 | ||||
| -rw-r--r-- | arch/mips/sgi-ip27/ip27-init.c | 31 | ||||
| -rw-r--r-- | arch/mips/sgi-ip27/ip27-irq-pci.c | 265 | ||||
| -rw-r--r-- | arch/mips/sgi-ip27/ip27-irq.c | 225 | ||||
| -rw-r--r-- | arch/mips/sgi-ip27/ip27-klconfig.c | 9 | ||||
| -rw-r--r-- | arch/mips/sgi-ip27/ip27-klnuma.c | 7 | ||||
| -rw-r--r-- | arch/mips/sgi-ip27/ip27-memory.c | 184 | ||||
| -rw-r--r-- | arch/mips/sgi-ip27/ip27-nmi.c | 31 | ||||
| -rw-r--r-- | arch/mips/sgi-ip27/ip27-reset.c | 3 | ||||
| -rw-r--r-- | arch/mips/sgi-ip27/ip27-smp.c | 26 | ||||
| -rw-r--r-- | arch/mips/sgi-ip27/ip27-timer.c | 172 | ||||
| -rw-r--r-- | arch/mips/sgi-ip27/ip27-xtalk.c | 24 |
19 files changed, 445 insertions, 651 deletions
diff --git a/arch/mips/sgi-ip27/Kconfig b/arch/mips/sgi-ip27/Kconfig index 5e960ae9735..4d8705a65e4 100644 --- a/arch/mips/sgi-ip27/Kconfig +++ b/arch/mips/sgi-ip27/Kconfig @@ -1,9 +1,3 @@ -#config SGI_SN0_XXL -# bool "IP27 XXL" -# depends on SGI_IP27 -# This options adds support for userspace processes upto 16TB size. -# Normally the limit is just .5TB. - choice prompt "Node addressing mode" depends on SGI_IP27 @@ -19,7 +13,6 @@ config SGI_SN_M_MODE config SGI_SN_N_MODE bool "IP27 N-Mode" - depends on EXPERIMENTAL help The nodes of Origin, Onyx, Fuel and Tezro systems can be configured in either N-Modes which allows for more nodes or M-Mode which allows diff --git a/arch/mips/sgi-ip27/Makefile b/arch/mips/sgi-ip27/Makefile index e0a6871d56e..da8f6816d34 100644 --- a/arch/mips/sgi-ip27/Makefile +++ b/arch/mips/sgi-ip27/Makefile @@ -7,7 +7,5 @@ obj-y := ip27-berr.o ip27-irq.o ip27-init.o ip27-klconfig.o ip27-klnuma.o \ ip27-xtalk.o obj-$(CONFIG_EARLY_PRINTK) += ip27-console.o -obj-$(CONFIG_KGDB) += ip27-dbgio.o +obj-$(CONFIG_PCI) += ip27-irq-pci.o obj-$(CONFIG_SMP) += ip27-smp.o - -EXTRA_CFLAGS += -Werror diff --git a/arch/mips/sgi-ip27/Platform b/arch/mips/sgi-ip27/Platform new file mode 100644 index 00000000000..1fb9c2ea7c8 --- /dev/null +++ b/arch/mips/sgi-ip27/Platform @@ -0,0 +1,19 @@ +# +# SGI-IP27 (Origin200/2000) +# +# Set the load address to >= 0xc000000000300000 if you want to leave space for +# symmon, 0xc00000000001c000 for production kernels. Note that the value must +# be 16kb aligned or the handling of the current variable will break. +# +ifdef CONFIG_SGI_IP27 +platform-$(CONFIG_SGI_IP27) += sgi-ip27/ +cflags-$(CONFIG_SGI_IP27) += -I$(srctree)/arch/mips/include/asm/mach-ip27 +ifdef CONFIG_MAPPED_KERNEL +load-$(CONFIG_SGI_IP27) += 0xc00000004001c000 +OBJCOPYFLAGS := --change-addresses=0x3fffffff80000000 +dataoffset-$(CONFIG_SGI_IP27) += 0x01000000 +else +load-$(CONFIG_SGI_IP27) += 0xa80000000001c000 +OBJCOPYFLAGS := --change-addresses=0x57ffffff80000000 +endif +endif diff --git a/arch/mips/sgi-ip27/TODO b/arch/mips/sgi-ip27/TODO index 19f1512c8f2..160857ff148 100644 --- a/arch/mips/sgi-ip27/TODO +++ b/arch/mips/sgi-ip27/TODO @@ -13,7 +13,7 @@ being invoked on all nodes in ip27-memory.c. 9. start_thread must turn off UX64 ... and define tlb_refill_debug. 10. Need a bad pmd table, bad pte table. __bad_pmd_table/__bad_pagetable does not agree with pgd_bad/pmd_bad. -11. All intrs (ip27_do_irq handlers) are targetted at cpu A on the node. +11. All intrs (ip27_do_irq handlers) are targeted at cpu A on the node. This might need to change later. Only the timer intr is set up to be received on both Cpu A and B. (ip27_do_irq()/bridge_startup()) 13. Cache flushing (specially the SMP version) has to be investigated. diff --git a/arch/mips/sgi-ip27/ip27-berr.c b/arch/mips/sgi-ip27/ip27-berr.c index 7d05e68fdc7..692778da9e7 100644 --- a/arch/mips/sgi-ip27/ip27-berr.c +++ b/arch/mips/sgi-ip27/ip27-berr.c @@ -39,7 +39,7 @@ static void dump_hub_information(unsigned long errst0, unsigned long errst1) printk("Hub has valid error information:\n"); if (errst0 & PI_ERR_ST0_OVERRUN_MASK) - printk("Overrun is set. Error stack may contain additional " + printk("Overrun is set. Error stack may contain additional " "information.\n"); printk("Hub error address is %08lx\n", (errst0 & PI_ERR_ST0_ADDR_MASK) >> (PI_ERR_ST0_ADDR_SHFT - 3)); @@ -66,7 +66,7 @@ int ip27_be_handler(struct pt_regs *regs, int is_fixup) printk("Slice %c got %cbe at 0x%lx\n", 'A' + cpu, data ? 'd' : 'i', regs->cp0_epc); printk("Hub information:\n"); - printk("ERR_INT_PEND = 0x%06lx\n", LOCAL_HUB_L(PI_ERR_INT_PEND)); + printk("ERR_INT_PEND = 0x%06llx\n", LOCAL_HUB_L(PI_ERR_INT_PEND)); errst0 = LOCAL_HUB_L(cpu ? PI_ERR_STATUS0_B : PI_ERR_STATUS0_A); errst1 = LOCAL_HUB_L(cpu ? PI_ERR_STATUS1_B : PI_ERR_STATUS1_A); dump_hub_information(errst0, errst1); @@ -85,7 +85,7 @@ void __init ip27_be_init(void) board_be_handler = ip27_be_handler; LOCAL_HUB_S(PI_ERR_INT_PEND, - cpu ? PI_ERR_CLEAR_ALL_B : PI_ERR_CLEAR_ALL_A); + cpu ? PI_ERR_CLEAR_ALL_B : PI_ERR_CLEAR_ALL_A); LOCAL_HUB_S(PI_ERR_INT_MASK_A + cpuoff, 0); LOCAL_HUB_S(PI_ERR_STACK_ADDR_A + cpuoff, 0); LOCAL_HUB_S(PI_ERR_STACK_SIZE, 0); /* Disable error stack */ diff --git a/arch/mips/sgi-ip27/ip27-console.c b/arch/mips/sgi-ip27/ip27-console.c index 3ba830651c5..45fdfbcbd4c 100644 --- a/arch/mips/sgi-ip27/ip27-console.c +++ b/arch/mips/sgi-ip27/ip27-console.c @@ -5,10 +5,8 @@ * * Copyright (C) 2001, 2002 Ralf Baechle */ -#include <linux/init.h> #include <asm/page.h> -#include <asm/semaphore.h> #include <asm/sn/addrs.h> #include <asm/sn/sn0/hub.h> #include <asm/sn/klconfig.h> @@ -32,7 +30,7 @@ static inline struct ioc3_uartregs *console_uart(void) return &ioc3->sregs.uarta; } -void __init prom_putchar(char c) +void prom_putchar(char c) { struct ioc3_uartregs *uart = console_uart(); diff --git a/arch/mips/sgi-ip27/ip27-dbgio.c b/arch/mips/sgi-ip27/ip27-dbgio.c deleted file mode 100644 index 08fd88b36f8..00000000000 --- a/arch/mips/sgi-ip27/ip27-dbgio.c +++ /dev/null @@ -1,60 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN - * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 675 Mass Ave, Cambridge, MA 02139, USA. - * - * Copyright 2004 Ralf Baechle <ralf@linux-mips.org> - */ -#include <asm/sn/addrs.h> -#include <asm/sn/sn0/hub.h> -#include <asm/sn/klconfig.h> -#include <asm/sn/ioc3.h> -#include <asm/sn/sn_private.h> - -#include <linux/serial.h> -#include <linux/serial_core.h> -#include <linux/serial_reg.h> - -#define IOC3_CLK (22000000 / 3) -#define IOC3_FLAGS (0) - -static inline struct ioc3_uartregs *console_uart(void) -{ - struct ioc3 *ioc3; - - ioc3 = (struct ioc3 *)KL_CONFIG_CH_CONS_INFO(get_nasid())->memory_base; - - return &ioc3->sregs.uarta; -} - -unsigned char getDebugChar(void) -{ - struct ioc3_uartregs *uart = console_uart(); - - while ((uart->iu_lsr & UART_LSR_DR) == 0); - return uart->iu_rbr; -} - -void putDebugChar(unsigned char c) -{ - struct ioc3_uartregs *uart = console_uart(); - - while ((uart->iu_lsr & UART_LSR_THRE) == 0); - uart->iu_thr = c; -} diff --git a/arch/mips/sgi-ip27/ip27-hubio.c b/arch/mips/sgi-ip27/ip27-hubio.c index a1fa4abb3f6..328ceb3c86e 100644 --- a/arch/mips/sgi-ip27/ip27-hubio.c +++ b/arch/mips/sgi-ip27/ip27-hubio.c @@ -17,11 +17,11 @@ static int force_fire_and_forget = 1; /** - * hub_pio_map - establish a HUB PIO mapping + * hub_pio_map - establish a HUB PIO mapping * * @hub: hub to perform PIO mapping on * @widget: widget ID to perform PIO mapping for - * @xtalk_addr: xtalk_address that needs to be mapped + * @xtalk_addr: xtalk_address that needs to be mapped * @size: size of the PIO mapping * **/ @@ -29,7 +29,6 @@ unsigned long hub_pio_map(cnodeid_t cnode, xwidgetnum_t widget, unsigned long xtalk_addr, size_t size) { nasid_t nasid = COMPACT_TO_NASID_NODEID(cnode); - volatile hubreg_t junk; unsigned i; /* use small-window mapping if possible */ @@ -64,7 +63,7 @@ unsigned long hub_pio_map(cnodeid_t cnode, xwidgetnum_t widget, * after we write it. */ IIO_ITTE_PUT(nasid, i, HUB_PIO_MAP_TO_MEM, widget, xtalk_addr); - junk = HUB_L(IIO_ITTE_GET(nasid, i)); + (void) HUB_L(IIO_ITTE_GET(nasid, i)); return NODE_BWIN_BASE(nasid, widget) + (xtalk_addr % BWIN_SIZE); } @@ -79,8 +78,8 @@ unsigned long hub_pio_map(cnodeid_t cnode, xwidgetnum_t widget, /* * hub_setup_prb(nasid, prbnum, credits, conveyor) * - * Put a PRB into fire-and-forget mode if conveyor isn't set. Otherwise, - * put it into conveyor belt mode with the specified number of credits. + * Put a PRB into fire-and-forget mode if conveyor isn't set. Otherwise, + * put it into conveyor belt mode with the specified number of credits. */ static void hub_setup_prb(nasid_t nasid, int prbnum, int credits) { @@ -126,12 +125,12 @@ static void hub_setup_prb(nasid_t nasid, int prbnum, int credits) * so we turn off access to all widgets for the duration of the function. * * XXX - This code should really check what kind of widget we're talking - * to. Bridges can only handle three requests, but XG will do more. + * to. Bridges can only handle three requests, but XG will do more. * How many can crossbow handle to widget 0? We're assuming 1. * * XXX - There is a bug in the crossbow that link reset PIOs do not * return write responses. The easiest solution to this problem is to - * leave widget 0 (xbow) in fire-and-forget mode at all times. This + * leave widget 0 (xbow) in fire-and-forget mode at all times. This * only affects pio's to xbow registers, which should be rare. **/ static void hub_set_piomode(nasid_t nasid) @@ -168,7 +167,7 @@ static void hub_set_piomode(nasid_t nasid) } /* - * hub_pio_init - PIO-related hub initialization + * hub_pio_init - PIO-related hub initialization * * @hub: hubinfo structure for our hub */ diff --git a/arch/mips/sgi-ip27/ip27-init.c b/arch/mips/sgi-ip27/ip27-init.c index 7093e7c573a..ee736bd103f 100644 --- a/arch/mips/sgi-ip27/ip27-init.c +++ b/arch/mips/sgi-ip27/ip27-init.c @@ -9,6 +9,7 @@ #include <linux/kernel.h> #include <linux/init.h> #include <linux/sched.h> +#include <linux/smp.h> #include <linux/mm.h> #include <linux/module.h> #include <linux/cpumask.h> @@ -53,7 +54,7 @@ extern void pcibr_setup(cnodeid_t); extern void xtalk_probe_node(cnodeid_t nid); -static void __cpuinit per_hub_init(cnodeid_t cnode) +static void per_hub_init(cnodeid_t cnode) { struct hub_data *hub = hub_data(cnode); nasid_t nasid = COMPACT_TO_NASID_NODEID(cnode); @@ -92,7 +93,7 @@ static void __cpuinit per_hub_init(cnodeid_t cnode) /* * Some interrupts are reserved by hardware or by software convention. - * Mark these as reserved right away so they won't be used accidently + * Mark these as reserved right away so they won't be used accidentally * later. */ for (i = 0; i <= BASE_PCI_IRQ; i++) { @@ -109,7 +110,7 @@ static void __cpuinit per_hub_init(cnodeid_t cnode) } } -void __cpuinit per_cpu_init(void) +void per_cpu_init(void) { int cpu = smp_processor_id(); int slice = LOCAL_HUB_L(PI_CPU_NUM); @@ -150,7 +151,7 @@ nasid_t get_nasid(void) { return (nasid_t)((LOCAL_HUB_L(NI_STATUS_REV_ID) & NSRI_NODEID_MASK) - >> NSRI_NODEID_SHFT); + >> NSRI_NODEID_SHFT); } /* @@ -161,27 +162,6 @@ cnodeid_t get_compact_nodeid(void) return NASID_TO_COMPACT_NODEID(get_nasid()); } -/* Extracted from the IOC3 meta driver. FIXME. */ -static inline void ioc3_sio_init(void) -{ - struct ioc3 *ioc3; - nasid_t nid; - long loops; - - nid = get_nasid(); - ioc3 = (struct ioc3 *) KL_CONFIG_CH_CONS_INFO(nid)->memory_base; - - ioc3->sscr_a = 0; /* PIO mode for uarta. */ - ioc3->sscr_b = 0; /* PIO mode for uartb. */ - ioc3->sio_iec = ~0; - ioc3->sio_ies = (SIO_IR_SA_INT | SIO_IR_SB_INT); - - loops=1000000; while(loops--); - ioc3->sregs.uarta.iu_fcr = 0; - ioc3->sregs.uartb.iu_fcr = 0; - loops=1000000; while(loops--); -} - static inline void ioc3_eth_init(void) { struct ioc3 *ioc3; @@ -234,7 +214,6 @@ void __init plat_mem_setup(void) panic("Kernel compiled for N mode."); #endif - ioc3_sio_init(); ioc3_eth_init(); per_cpu_init(); diff --git a/arch/mips/sgi-ip27/ip27-irq-pci.c b/arch/mips/sgi-ip27/ip27-irq-pci.c new file mode 100644 index 00000000000..2a1c40784bd --- /dev/null +++ b/arch/mips/sgi-ip27/ip27-irq-pci.c @@ -0,0 +1,265 @@ +/* + * ip27-irq.c: Highlevel interrupt handling for IP27 architecture. + * + * Copyright (C) 1999, 2000 Ralf Baechle (ralf@gnu.org) + * Copyright (C) 1999, 2000 Silicon Graphics, Inc. + * Copyright (C) 1999 - 2001 Kanoj Sarcar + */ + +#undef DEBUG + +#include <linux/irq.h> +#include <linux/errno.h> +#include <linux/signal.h> +#include <linux/sched.h> +#include <linux/types.h> +#include <linux/interrupt.h> +#include <linux/ioport.h> +#include <linux/timex.h> +#include <linux/smp.h> +#include <linux/random.h> +#include <linux/kernel.h> +#include <linux/kernel_stat.h> +#include <linux/delay.h> +#include <linux/bitops.h> + +#include <asm/bootinfo.h> +#include <asm/io.h> +#include <asm/mipsregs.h> + +#include <asm/processor.h> +#include <asm/pci/bridge.h> +#include <asm/sn/addrs.h> +#include <asm/sn/agent.h> +#include <asm/sn/arch.h> +#include <asm/sn/hub.h> +#include <asm/sn/intr.h> + +/* + * Linux has a controller-independent x86 interrupt architecture. + * every controller has a 'controller-template', that is used + * by the main code to do the right thing. Each driver-visible + * interrupt source is transparently wired to the appropriate + * controller. Thus drivers need not be aware of the + * interrupt-controller. + * + * Various interrupt controllers we handle: 8259 PIC, SMP IO-APIC, + * PIIX4's internal 8259 PIC and SGI's Visual Workstation Cobalt (IO-)APIC. + * (IO-APICs assumed to be messaging to Pentium local-APICs) + * + * the code is designed to be easily extended with new/different + * interrupt controllers, without having to do assembly magic. + */ + +extern struct bridge_controller *irq_to_bridge[]; +extern int irq_to_slot[]; + +/* + * use these macros to get the encoded nasid and widget id + * from the irq value + */ +#define IRQ_TO_BRIDGE(i) irq_to_bridge[(i)] +#define SLOT_FROM_PCI_IRQ(i) irq_to_slot[i] + +static inline int alloc_level(int cpu, int irq) +{ + struct hub_data *hub = hub_data(cpu_to_node(cpu)); + struct slice_data *si = cpu_data[cpu].data; + int level; + + level = find_first_zero_bit(hub->irq_alloc_mask, LEVELS_PER_SLICE); + if (level >= LEVELS_PER_SLICE) + panic("Cpu %d flooded with devices", cpu); + + __set_bit(level, hub->irq_alloc_mask); + si->level_to_irq[level] = irq; + + return level; +} + +static inline int find_level(cpuid_t *cpunum, int irq) +{ + int cpu, i; + + for_each_online_cpu(cpu) { + struct slice_data *si = cpu_data[cpu].data; + + for (i = BASE_PCI_IRQ; i < LEVELS_PER_SLICE; i++) + if (si->level_to_irq[i] == irq) { + *cpunum = cpu; + + return i; + } + } + + panic("Could not identify cpu/level for irq %d", irq); +} + +static int intr_connect_level(int cpu, int bit) +{ + nasid_t nasid = COMPACT_TO_NASID_NODEID(cpu_to_node(cpu)); + struct slice_data *si = cpu_data[cpu].data; + + set_bit(bit, si->irq_enable_mask); + + if (!cputoslice(cpu)) { + REMOTE_HUB_S(nasid, PI_INT_MASK0_A, si->irq_enable_mask[0]); + REMOTE_HUB_S(nasid, PI_INT_MASK1_A, si->irq_enable_mask[1]); + } else { + REMOTE_HUB_S(nasid, PI_INT_MASK0_B, si->irq_enable_mask[0]); + REMOTE_HUB_S(nasid, PI_INT_MASK1_B, si->irq_enable_mask[1]); + } + + return 0; +} + +static int intr_disconnect_level(int cpu, int bit) +{ + nasid_t nasid = COMPACT_TO_NASID_NODEID(cpu_to_node(cpu)); + struct slice_data *si = cpu_data[cpu].data; + + clear_bit(bit, si->irq_enable_mask); + + if (!cputoslice(cpu)) { + REMOTE_HUB_S(nasid, PI_INT_MASK0_A, si->irq_enable_mask[0]); + REMOTE_HUB_S(nasid, PI_INT_MASK1_A, si->irq_enable_mask[1]); + } else { + REMOTE_HUB_S(nasid, PI_INT_MASK0_B, si->irq_enable_mask[0]); + REMOTE_HUB_S(nasid, PI_INT_MASK1_B, si->irq_enable_mask[1]); + } + + return 0; +} + +/* Startup one of the (PCI ...) IRQs routes over a bridge. */ +static unsigned int startup_bridge_irq(struct irq_data *d) +{ + struct bridge_controller *bc; + bridgereg_t device; + bridge_t *bridge; + int pin, swlevel; + cpuid_t cpu; + + pin = SLOT_FROM_PCI_IRQ(d->irq); + bc = IRQ_TO_BRIDGE(d->irq); + bridge = bc->base; + + pr_debug("bridge_startup(): irq= 0x%x pin=%d\n", d->irq, pin); + /* + * "map" irq to a swlevel greater than 6 since the first 6 bits + * of INT_PEND0 are taken + */ + swlevel = find_level(&cpu, d->irq); + bridge->b_int_addr[pin].addr = (0x20000 | swlevel | (bc->nasid << 8)); + bridge->b_int_enable |= (1 << pin); + bridge->b_int_enable |= 0x7ffffe00; /* more stuff in int_enable */ + + /* + * Enable sending of an interrupt clear packt to the hub on a high to + * low transition of the interrupt pin. + * + * IRIX sets additional bits in the address which are documented as + * reserved in the bridge docs. + */ + bridge->b_int_mode |= (1UL << pin); + + /* + * We assume the bridge to have a 1:1 mapping between devices + * (slots) and intr pins. + */ + device = bridge->b_int_device; + device &= ~(7 << (pin*3)); + device |= (pin << (pin*3)); + bridge->b_int_device = device; + + bridge->b_wid_tflush; + + intr_connect_level(cpu, swlevel); + + return 0; /* Never anything pending. */ +} + +/* Shutdown one of the (PCI ...) IRQs routes over a bridge. */ +static void shutdown_bridge_irq(struct irq_data *d) +{ + struct bridge_controller *bc = IRQ_TO_BRIDGE(d->irq); + bridge_t *bridge = bc->base; + int pin, swlevel; + cpuid_t cpu; + + pr_debug("bridge_shutdown: irq 0x%x\n", d->irq); + pin = SLOT_FROM_PCI_IRQ(d->irq); + + /* + * map irq to a swlevel greater than 6 since the first 6 bits + * of INT_PEND0 are taken + */ + swlevel = find_level(&cpu, d->irq); + intr_disconnect_level(cpu, swlevel); + + bridge->b_int_enable &= ~(1 << pin); + bridge->b_wid_tflush; +} + +static inline void enable_bridge_irq(struct irq_data *d) +{ + cpuid_t cpu; + int swlevel; + + swlevel = find_level(&cpu, d->irq); /* Criminal offence */ + intr_connect_level(cpu, swlevel); +} + +static inline void disable_bridge_irq(struct irq_data *d) +{ + cpuid_t cpu; + int swlevel; + + swlevel = find_level(&cpu, d->irq); /* Criminal offence */ + intr_disconnect_level(cpu, swlevel); +} + +static struct irq_chip bridge_irq_type = { + .name = "bridge", + .irq_startup = startup_bridge_irq, + .irq_shutdown = shutdown_bridge_irq, + .irq_mask = disable_bridge_irq, + .irq_unmask = enable_bridge_irq, +}; + +void register_bridge_irq(unsigned int irq) +{ + irq_set_chip_and_handler(irq, &bridge_irq_type, handle_level_irq); +} + +int request_bridge_irq(struct bridge_controller *bc) +{ + int irq = allocate_irqno(); + int swlevel, cpu; + nasid_t nasid; + + if (irq < 0) + return irq; + + /* + * "map" irq to a swlevel greater than 6 since the first 6 bits + * of INT_PEND0 are taken + */ + cpu = bc->irq_cpu; + swlevel = alloc_level(cpu, irq); + if (unlikely(swlevel < 0)) { + free_irqno(irq); + + return -EAGAIN; + } + + /* Make sure it's not already pending when we connect it. */ + nasid = COMPACT_TO_NASID_NODEID(cpu_to_node(cpu)); + REMOTE_HUB_CLR_INTR(nasid, swlevel); + + intr_connect_level(cpu, swlevel); + + register_bridge_irq(irq); + + return irq; +} diff --git a/arch/mips/sgi-ip27/ip27-irq.c b/arch/mips/sgi-ip27/ip27-irq.c index 1bb692a3b31..3fbaef97a1b 100644 --- a/arch/mips/sgi-ip27/ip27-irq.c +++ b/arch/mips/sgi-ip27/ip27-irq.c @@ -17,7 +17,7 @@ #include <linux/interrupt.h> #include <linux/ioport.h> #include <linux/timex.h> -#include <linux/slab.h> +#include <linux/smp.h> #include <linux/random.h> #include <linux/kernel.h> #include <linux/kernel_stat.h> @@ -27,10 +27,8 @@ #include <asm/bootinfo.h> #include <asm/io.h> #include <asm/mipsregs.h> -#include <asm/system.h> #include <asm/processor.h> -#include <asm/pci/bridge.h> #include <asm/sn/addrs.h> #include <asm/sn/agent.h> #include <asm/sn/arch.h> @@ -41,7 +39,7 @@ * Linux has a controller-independent x86 interrupt architecture. * every controller has a 'controller-template', that is used * by the main code to do the right thing. Each driver-visible - * interrupt source is transparently wired to the apropriate + * interrupt source is transparently wired to the appropriate * controller. Thus drivers need not be aware of the * interrupt-controller. * @@ -55,50 +53,6 @@ extern asmlinkage void ip27_irq(void); -extern struct bridge_controller *irq_to_bridge[]; -extern int irq_to_slot[]; - -/* - * use these macros to get the encoded nasid and widget id - * from the irq value - */ -#define IRQ_TO_BRIDGE(i) irq_to_bridge[(i)] -#define SLOT_FROM_PCI_IRQ(i) irq_to_slot[i] - -static inline int alloc_level(int cpu, int irq) -{ - struct hub_data *hub = hub_data(cpu_to_node(cpu)); - struct slice_data *si = cpu_data[cpu].data; - int level; - - level = find_first_zero_bit(hub->irq_alloc_mask, LEVELS_PER_SLICE); - if (level >= LEVELS_PER_SLICE) - panic("Cpu %d flooded with devices\n", cpu); - - __set_bit(level, hub->irq_alloc_mask); - si->level_to_irq[level] = irq; - - return level; -} - -static inline int find_level(cpuid_t *cpunum, int irq) -{ - int cpu, i; - - for_each_online_cpu(cpu) { - struct slice_data *si = cpu_data[cpu].data; - - for (i = BASE_PCI_IRQ; i < LEVELS_PER_SLICE; i++) - if (si->level_to_irq[i] == irq) { - *cpunum = cpu; - - return i; - } - } - - panic("Could not identify cpu/level for irq %d\n", irq); -} - /* * Find first bit set */ @@ -116,7 +70,7 @@ static int ms1bit(unsigned long x) } /* - * This code is unnecessarily complex, because we do IRQF_DISABLED + * This code is unnecessarily complex, because we do * intr enabling. Basically, once we grab the set of intrs we need * to service, we must mask _all_ these interrupts; firstly, to make * sure the same intr does not intr again, causing recursion that @@ -147,8 +101,10 @@ static void ip27_do_irq_mask0(void) #ifdef CONFIG_SMP if (pend0 & (1UL << CPU_RESCHED_A_IRQ)) { LOCAL_HUB_CLR_INTR(CPU_RESCHED_A_IRQ); + scheduler_ipi(); } else if (pend0 & (1UL << CPU_RESCHED_B_IRQ)) { LOCAL_HUB_CLR_INTR(CPU_RESCHED_B_IRQ); + scheduler_ipi(); } else if (pend0 & (1UL << CPU_CALL_A_IRQ)) { LOCAL_HUB_CLR_INTR(CPU_CALL_A_IRQ); smp_call_function_interrupt(); @@ -203,177 +159,6 @@ static void ip27_hub_error(void) panic("CPU %d got a hub error interrupt", smp_processor_id()); } -static int intr_connect_level(int cpu, int bit) -{ - nasid_t nasid = COMPACT_TO_NASID_NODEID(cpu_to_node(cpu)); - struct slice_data *si = cpu_data[cpu].data; - - set_bit(bit, si->irq_enable_mask); - - if (!cputoslice(cpu)) { - REMOTE_HUB_S(nasid, PI_INT_MASK0_A, si->irq_enable_mask[0]); - REMOTE_HUB_S(nasid, PI_INT_MASK1_A, si->irq_enable_mask[1]); - } else { - REMOTE_HUB_S(nasid, PI_INT_MASK0_B, si->irq_enable_mask[0]); - REMOTE_HUB_S(nasid, PI_INT_MASK1_B, si->irq_enable_mask[1]); - } - - return 0; -} - -static int intr_disconnect_level(int cpu, int bit) -{ - nasid_t nasid = COMPACT_TO_NASID_NODEID(cpu_to_node(cpu)); - struct slice_data *si = cpu_data[cpu].data; - - clear_bit(bit, si->irq_enable_mask); - - if (!cputoslice(cpu)) { - REMOTE_HUB_S(nasid, PI_INT_MASK0_A, si->irq_enable_mask[0]); - REMOTE_HUB_S(nasid, PI_INT_MASK1_A, si->irq_enable_mask[1]); - } else { - REMOTE_HUB_S(nasid, PI_INT_MASK0_B, si->irq_enable_mask[0]); - REMOTE_HUB_S(nasid, PI_INT_MASK1_B, si->irq_enable_mask[1]); - } - - return 0; -} - -/* Startup one of the (PCI ...) IRQs routes over a bridge. */ -static unsigned int startup_bridge_irq(unsigned int irq) -{ - struct bridge_controller *bc; - bridgereg_t device; - bridge_t *bridge; - int pin, swlevel; - cpuid_t cpu; - - pin = SLOT_FROM_PCI_IRQ(irq); - bc = IRQ_TO_BRIDGE(irq); - bridge = bc->base; - - pr_debug("bridge_startup(): irq= 0x%x pin=%d\n", irq, pin); - /* - * "map" irq to a swlevel greater than 6 since the first 6 bits - * of INT_PEND0 are taken - */ - swlevel = find_level(&cpu, irq); - bridge->b_int_addr[pin].addr = (0x20000 | swlevel | (bc->nasid << 8)); - bridge->b_int_enable |= (1 << pin); - bridge->b_int_enable |= 0x7ffffe00; /* more stuff in int_enable */ - - /* - * Enable sending of an interrupt clear packt to the hub on a high to - * low transition of the interrupt pin. - * - * IRIX sets additional bits in the address which are documented as - * reserved in the bridge docs. - */ - bridge->b_int_mode |= (1UL << pin); - - /* - * We assume the bridge to have a 1:1 mapping between devices - * (slots) and intr pins. - */ - device = bridge->b_int_device; - device &= ~(7 << (pin*3)); - device |= (pin << (pin*3)); - bridge->b_int_device = device; - - bridge->b_wid_tflush; - - intr_connect_level(cpu, swlevel); - - return 0; /* Never anything pending. */ -} - -/* Shutdown one of the (PCI ...) IRQs routes over a bridge. */ -static void shutdown_bridge_irq(unsigned int irq) -{ - struct bridge_controller *bc = IRQ_TO_BRIDGE(irq); - bridge_t *bridge = bc->base; - int pin, swlevel; - cpuid_t cpu; - - pr_debug("bridge_shutdown: irq 0x%x\n", irq); - pin = SLOT_FROM_PCI_IRQ(irq); - - /* - * map irq to a swlevel greater than 6 since the first 6 bits - * of INT_PEND0 are taken - */ - swlevel = find_level(&cpu, irq); - intr_disconnect_level(cpu, swlevel); - - bridge->b_int_enable &= ~(1 << pin); - bridge->b_wid_tflush; -} - -static inline void enable_bridge_irq(unsigned int irq) -{ - cpuid_t cpu; - int swlevel; - - swlevel = find_level(&cpu, irq); /* Criminal offence */ - intr_connect_level(cpu, swlevel); -} - -static inline void disable_bridge_irq(unsigned int irq) -{ - cpuid_t cpu; - int swlevel; - - swlevel = find_level(&cpu, irq); /* Criminal offence */ - intr_disconnect_level(cpu, swlevel); -} - -static struct irq_chip bridge_irq_type = { - .name = "bridge", - .startup = startup_bridge_irq, - .shutdown = shutdown_bridge_irq, - .ack = disable_bridge_irq, - .mask = disable_bridge_irq, - .mask_ack = disable_bridge_irq, - .unmask = enable_bridge_irq, -}; - -void __devinit register_bridge_irq(unsigned int irq) -{ - set_irq_chip_and_handler(irq, &bridge_irq_type, handle_level_irq); -} - -int __devinit request_bridge_irq(struct bridge_controller *bc) -{ - int irq = allocate_irqno(); - int swlevel, cpu; - nasid_t nasid; - - if (irq < 0) - return irq; - - /* - * "map" irq to a swlevel greater than 6 since the first 6 bits - * of INT_PEND0 are taken - */ - cpu = bc->irq_cpu; - swlevel = alloc_level(cpu, irq); - if (unlikely(swlevel < 0)) { - free_irqno(irq); - - return -EAGAIN; - } - - /* Make sure it's not already pending when we connect it. */ - nasid = COMPACT_TO_NASID_NODEID(cpu_to_node(cpu)); - REMOTE_HUB_CLR_INTR(nasid, swlevel); - - intr_connect_level(cpu, swlevel); - - register_bridge_irq(irq); - - return irq; -} - asmlinkage void plat_irq_dispatch(void) { unsigned long pending = read_c0_cause() & read_c0_status(); diff --git a/arch/mips/sgi-ip27/ip27-klconfig.c b/arch/mips/sgi-ip27/ip27-klconfig.c index dd830b3670d..c873d62ff08 100644 --- a/arch/mips/sgi-ip27/ip27-klconfig.c +++ b/arch/mips/sgi-ip27/ip27-klconfig.c @@ -2,7 +2,6 @@ * Copyright (C) 1999, 2000 Ralf Baechle (ralf@gnu.org) * Copyright (C) 1999, 2000 Silicon Graphics, Inc. */ -#include <linux/init.h> #include <linux/kernel.h> #include <linux/sched.h> #include <linux/interrupt.h> @@ -48,7 +47,7 @@ klinfo_t *find_first_component(lboard_t *brd, unsigned char struct_type) return find_component(brd, (klinfo_t *)NULL, struct_type); } -lboard_t * find_lboard(lboard_t *start, unsigned char brd_type) +lboard_t *find_lboard(lboard_t *start, unsigned char brd_type) { /* Search all boards stored on this node. */ while (start) { @@ -60,7 +59,7 @@ lboard_t * find_lboard(lboard_t *start, unsigned char brd_type) return (lboard_t *)NULL; } -lboard_t * find_lboard_class(lboard_t *start, unsigned char brd_type) +lboard_t *find_lboard_class(lboard_t *start, unsigned char brd_type) { /* Search all boards stored on this node. */ while (start) { @@ -78,7 +77,7 @@ cnodeid_t get_cpu_cnode(cpuid_t cpu) return CPUID_TO_COMPACT_NODEID(cpu); } -klcpu_t * nasid_slice_to_cpuinfo(nasid_t nasid, int slice) +klcpu_t *nasid_slice_to_cpuinfo(nasid_t nasid, int slice) { lboard_t *brd; klcpu_t *acpu; @@ -97,7 +96,7 @@ klcpu_t * nasid_slice_to_cpuinfo(nasid_t nasid, int slice) return (klcpu_t *)NULL; } -klcpu_t * sn_get_cpuinfo(cpuid_t cpu) +klcpu_t *sn_get_cpuinfo(cpuid_t cpu) { nasid_t nasid; int slice; diff --git a/arch/mips/sgi-ip27/ip27-klnuma.c b/arch/mips/sgi-ip27/ip27-klnuma.c index 48932ce1d73..7a53b1e28a9 100644 --- a/arch/mips/sgi-ip27/ip27-klnuma.c +++ b/arch/mips/sgi-ip27/ip27-klnuma.c @@ -4,6 +4,7 @@ * Copyright 2000 - 2001 Kanoj Sarcar (kanoj@sgi.com) */ #include <linux/init.h> +#include <linux/mm.h> #include <linux/mmzone.h> #include <linux/kernel.h> #include <linux/nodemask.h> @@ -53,11 +54,8 @@ void __init setup_replication_mask(void) static __init void set_ktext_source(nasid_t client_nasid, nasid_t server_nasid) { - cnodeid_t client_cnode; kern_vars_t *kvp; - client_cnode = NASID_TO_COMPACT_NODEID(client_nasid); - kvp = &hub_data(client_nasid)->kern_vars; KERN_VARS_ADDR(client_nasid) = (unsigned long)kvp; @@ -116,7 +114,7 @@ void __init replicate_kernel_text() * data structures on the first couple of pages of the first slot of each * node. If this is the case, getfirstfree(node) > getslotstart(node, 0). */ -pfn_t node_getfirstfree(cnodeid_t cnode) +unsigned long node_getfirstfree(cnodeid_t cnode) { unsigned long loadbase = REP_BASE; nasid_t nasid = COMPACT_TO_NASID_NODEID(cnode); @@ -132,4 +130,3 @@ pfn_t node_getfirstfree(cnodeid_t cnode) return (KDM_TO_PHYS(PAGE_ALIGN(SYMMON_STK_ADDR(nasid, 0))) >> PAGE_SHIFT); } - diff --git a/arch/mips/sgi-ip27/ip27-memory.c b/arch/mips/sgi-ip27/ip27-memory.c index bf438d02366..a95c00f5fb9 100644 --- a/arch/mips/sgi-ip27/ip27-memory.c +++ b/arch/mips/sgi-ip27/ip27-memory.c @@ -12,6 +12,7 @@ */ #include <linux/init.h> #include <linux/kernel.h> +#include <linux/memblock.h> #include <linux/mm.h> #include <linux/mmzone.h> #include <linux/module.h> @@ -30,14 +31,8 @@ #include <asm/sn/sn_private.h> -#define SLOT_PFNSHIFT (SLOT_SHIFT - PAGE_SHIFT) -#define PFN_NASIDSHFT (NASID_SHFT - PAGE_SHIFT) - -#define SLOT_IGNORED 0xffff - -static short __initdata slot_lastfilled_cache[MAX_COMPACT_NODES]; -static unsigned short __initdata slot_psize_cache[MAX_COMPACT_NODES][MAX_MEM_SLOTS]; -static struct bootmem_data __initdata plat_node_bdata[MAX_COMPACT_NODES]; +#define SLOT_PFNSHIFT (SLOT_SHIFT - PAGE_SHIFT) +#define PFN_NASIDSHFT (NASID_SHFT - PAGE_SHIFT) struct node_data *__node_data[MAX_COMPACT_NODES]; @@ -48,7 +43,7 @@ static int fine_mode; static int is_fine_dirmode(void) { return (((LOCAL_HUB_L(NI_STATUS_REV_ID) & NSRI_REGIONSIZE_MASK) - >> NSRI_REGIONSIZE_SHFT) & REGIONSIZE_FINE); + >> NSRI_REGIONSIZE_SHFT) & REGIONSIZE_FINE); } static hubreg_t get_region(cnodeid_t cnode) @@ -71,7 +66,7 @@ static void gen_region_mask(hubreg_t *region_mask) } } -#define rou_rflag rou_flags +#define rou_rflag rou_flags static int router_distance; @@ -260,59 +255,14 @@ static void __init dump_topology(void) } } -static pfn_t __init slot_getbasepfn(cnodeid_t cnode, int slot) +static unsigned long __init slot_getbasepfn(cnodeid_t cnode, int slot) { nasid_t nasid = COMPACT_TO_NASID_NODEID(cnode); - return ((pfn_t)nasid << PFN_NASIDSHFT) | (slot << SLOT_PFNSHIFT); -} - -/* - * Return the number of pages of memory provided by the given slot - * on the specified node. - */ -static pfn_t __init slot_getsize(cnodeid_t node, int slot) -{ - return (pfn_t) slot_psize_cache[node][slot]; -} - -/* - * Return highest slot filled - */ -static int __init node_getlastslot(cnodeid_t node) -{ - return (int) slot_lastfilled_cache[node]; -} - -/* - * Return the pfn of the last free page of memory on a node. - */ -static pfn_t __init node_getmaxclick(cnodeid_t node) -{ - pfn_t slot_psize; - int slot; - - /* - * Start at the top slot. When we find a slot with memory in it, - * that's the winner. - */ - for (slot = (MAX_MEM_SLOTS - 1); slot >= 0; slot--) { - if ((slot_psize = slot_getsize(node, slot))) { - if (slot_psize == SLOT_IGNORED) - continue; - /* Return the basepfn + the slot size, minus 1. */ - return slot_getbasepfn(node, slot) + slot_psize - 1; - } - } - - /* - * If there's no memory on the node, return 0. This is likely - * to cause problems. - */ - return 0; + return ((unsigned long)nasid << PFN_NASIDSHFT) | (slot << SLOT_PFNSHIFT); } -static pfn_t __init slot_psize_compute(cnodeid_t node, int slot) +static unsigned long __init slot_psize_compute(cnodeid_t node, int slot) { nasid_t nasid; lboard_t *brd; @@ -403,14 +353,12 @@ static void __init mlreset(void) static void __init szmem(void) { - pfn_t slot_psize, slot0sz = 0, nodebytes; /* Hack to detect problem configs */ - int slot, ignore; + unsigned long slot_psize, slot0sz = 0, nodebytes; /* Hack to detect problem configs */ + int slot; cnodeid_t node; - num_physpages = 0; - for_each_online_node(node) { - ignore = nodebytes = 0; + nodebytes = 0; for (slot = 0; slot < MAX_MEM_SLOTS; slot++) { slot_psize = slot_psize_compute(node, slot); if (slot == 0) @@ -420,58 +368,59 @@ static void __init szmem(void) * kernel text. */ nodebytes += (1LL << SLOT_SHIFT); + + if (!slot_psize) + continue; + if ((nodebytes >> PAGE_SHIFT) * (sizeof(struct page)) > - (slot0sz << PAGE_SHIFT)) - ignore = 1; - if (ignore && slot_psize) { + (slot0sz << PAGE_SHIFT)) { printk("Ignoring slot %d onwards on node %d\n", slot, node); - slot_psize_cache[node][slot] = SLOT_IGNORED; slot = MAX_MEM_SLOTS; continue; } - num_physpages += slot_psize; - slot_psize_cache[node][slot] = - (unsigned short) slot_psize; - if (slot_psize) - slot_lastfilled_cache[node] = slot; + memblock_add_node(PFN_PHYS(slot_getbasepfn(node, slot)), + PFN_PHYS(slot_psize), node); } } } static void __init node_mem_init(cnodeid_t node) { - pfn_t slot_firstpfn = slot_getbasepfn(node, 0); - pfn_t slot_lastpfn = slot_firstpfn + slot_getsize(node, 0); - pfn_t slot_freepfn = node_getfirstfree(node); - struct pglist_data *pd; + unsigned long slot_firstpfn = slot_getbasepfn(node, 0); + unsigned long slot_freepfn = node_getfirstfree(node); unsigned long bootmap_size; + unsigned long start_pfn, end_pfn; + + get_pfn_range_for_nid(node, &start_pfn, &end_pfn); /* * Allocate the node data structures on the node first. */ __node_data[node] = __va(slot_freepfn << PAGE_SHIFT); + memset(__node_data[node], 0, PAGE_SIZE); - pd = NODE_DATA(node); - pd->bdata = &plat_node_bdata[node]; + NODE_DATA(node)->bdata = &bootmem_node_data[node]; + NODE_DATA(node)->node_start_pfn = start_pfn; + NODE_DATA(node)->node_spanned_pages = end_pfn - start_pfn; cpus_clear(hub_data(node)->h_cpus); slot_freepfn += PFN_UP(sizeof(struct pglist_data) + sizeof(struct hub_data)); - bootmap_size = init_bootmem_node(NODE_DATA(node), slot_freepfn, - slot_firstpfn, slot_lastpfn); - free_bootmem_node(NODE_DATA(node), slot_firstpfn << PAGE_SHIFT, - (slot_lastpfn - slot_firstpfn) << PAGE_SHIFT); + bootmap_size = init_bootmem_node(NODE_DATA(node), slot_freepfn, + start_pfn, end_pfn); + free_bootmem_with_active_regions(node, end_pfn); reserve_bootmem_node(NODE_DATA(node), slot_firstpfn << PAGE_SHIFT, ((slot_freepfn - slot_firstpfn) << PAGE_SHIFT) + bootmap_size, BOOTMEM_DEFAULT); + sparse_memory_present_with_active_regions(node); } /* - * A node with nothing. We use it to avoid any special casing in - * node_to_cpumask + * A node with nothing. We use it to avoid any special casing in + * cpumask_of_node */ static struct node_data null_node = { .hub = { @@ -505,7 +454,7 @@ void __init prom_free_prom_memory(void) /* We got nothing to free here ... */ } -extern unsigned long setup_zero_pages(void); +extern void setup_zero_pages(void); void __init paging_init(void) { @@ -515,70 +464,21 @@ void __init paging_init(void) pagetable_init(); for_each_online_node(node) { - pfn_t start_pfn = slot_getbasepfn(node, 0); - pfn_t end_pfn = node_getmaxclick(node) + 1; + unsigned long start_pfn, end_pfn; - zones_size[ZONE_NORMAL] = end_pfn - start_pfn; - free_area_init_node(node, NODE_DATA(node), - zones_size, start_pfn, NULL); + get_pfn_range_for_nid(node, &start_pfn, &end_pfn); if (end_pfn > max_low_pfn) max_low_pfn = end_pfn; } + zones_size[ZONE_NORMAL] = max_low_pfn; + free_area_init_nodes(zones_size); } void __init mem_init(void) { - unsigned long codesize, datasize, initsize, tmp; - unsigned node; - - high_memory = (void *) __va(num_physpages << PAGE_SHIFT); - - for_each_online_node(node) { - unsigned slot, numslots; - struct page *end, *p; - - /* - * This will free up the bootmem, ie, slot 0 memory. - */ - totalram_pages += free_all_bootmem_node(NODE_DATA(node)); - - /* - * We need to manually do the other slots. - */ - numslots = node_getlastslot(node); - for (slot = 1; slot <= numslots; slot++) { - p = nid_page_nr(node, slot_getbasepfn(node, slot) - - slot_getbasepfn(node, 0)); - - /* - * Free valid memory in current slot. - */ - for (end = p + slot_getsize(node, slot); p < end; p++) { - /* if (!page_is_ram(pgnr)) continue; */ - /* commented out until page_is_ram works */ - ClearPageReserved(p); - init_page_count(p); - __free_page(p); - totalram_pages++; - } - } - } - - totalram_pages -= setup_zero_pages(); /* This comes from node 0 */ - - codesize = (unsigned long) &_etext - (unsigned long) &_text; - datasize = (unsigned long) &_edata - (unsigned long) &_etext; - initsize = (unsigned long) &__init_end - (unsigned long) &__init_begin; - - tmp = nr_free_pages(); - printk(KERN_INFO "Memory: %luk/%luk available (%ldk kernel code, " - "%ldk reserved, %ldk data, %ldk init, %ldk highmem)\n", - tmp << (PAGE_SHIFT-10), - num_physpages << (PAGE_SHIFT-10), - codesize >> 10, - (num_physpages - tmp) << (PAGE_SHIFT-10), - datasize >> 10, - initsize >> 10, - (unsigned long) (totalhigh_pages << (PAGE_SHIFT-10))); + high_memory = (void *) __va(get_num_physpages() << PAGE_SHIFT); + free_all_bootmem(); + setup_zero_pages(); /* This comes from node 0 */ + mem_init_print_info(NULL); } diff --git a/arch/mips/sgi-ip27/ip27-nmi.c b/arch/mips/sgi-ip27/ip27-nmi.c index b0a25e1ee8b..a2358b44420 100644 --- a/arch/mips/sgi-ip27/ip27-nmi.c +++ b/arch/mips/sgi-ip27/ip27-nmi.c @@ -1,10 +1,9 @@ -#include <linux/kallsyms.h> #include <linux/kernel.h> #include <linux/mmzone.h> #include <linux/nodemask.h> #include <linux/spinlock.h> #include <linux/smp.h> -#include <asm/atomic.h> +#include <linux/atomic.h> #include <asm/sn/types.h> #include <asm/sn/addrs.h> #include <asm/sn/nmi.h> @@ -18,11 +17,10 @@ #endif #define CNODEID_NONE (cnodeid_t)-1 -#define enter_panic_mode() spin_lock(&nmi_lock) typedef unsigned long machreg_t; -DEFINE_SPINLOCK(nmi_lock); +static arch_spinlock_t nmi_lock = __ARCH_SPIN_LOCK_UNLOCKED; /* * Lets see what else we need to do here. Set up sp, gp? @@ -56,7 +54,7 @@ void install_cpu_nmi_handler(int slice) void nmi_cpu_eframe_save(nasid_t nasid, int slice) { struct reg_struct *nr; - int i; + int i; /* Get the pointer to the current cpu's register set. */ nr = (struct reg_struct *) @@ -84,19 +82,16 @@ void nmi_cpu_eframe_save(nasid_t nasid, int slice) /* * Saved cp0 registers */ - printk("epc : %016lx ", nr->epc); - print_symbol("%s ", nr->epc); + printk("epc : %016lx %pS\n", nr->epc, (void *) nr->epc); printk("%s\n", print_tainted()); - printk("ErrEPC: %016lx ", nr->error_epc); - print_symbol("%s\n", nr->error_epc); - printk("ra : %016lx ", nr->gpr[31]); - print_symbol("%s\n", nr->gpr[31]); - printk("Status: %08lx ", nr->sr); + printk("ErrEPC: %016lx %pS\n", nr->error_epc, (void *) nr->error_epc); + printk("ra : %016lx %pS\n", nr->gpr[31], (void *) nr->gpr[31]); + printk("Status: %08lx ", nr->sr); if (nr->sr & ST0_KX) printk("KX "); if (nr->sr & ST0_SX) - printk("SX "); + printk("SX "); if (nr->sr & ST0_UX) printk("UX "); @@ -147,8 +142,8 @@ void nmi_dump_hub_irq(nasid_t nasid, int slice) pend0 = REMOTE_HUB_L(nasid, PI_INT_PEND0); pend1 = REMOTE_HUB_L(nasid, PI_INT_PEND1); - printk("PI_INT_MASK0: %16lx PI_INT_MASK1: %16lx\n", mask0, mask1); - printk("PI_INT_PEND0: %16lx PI_INT_PEND1: %16lx\n", pend0, pend1); + printk("PI_INT_MASK0: %16Lx PI_INT_MASK1: %16Lx\n", mask0, mask1); + printk("PI_INT_PEND0: %16Lx PI_INT_PEND1: %16Lx\n", pend0, pend1); printk("\n\n"); } @@ -197,9 +192,9 @@ cont_nmi_dump(void) atomic_inc(&nmied_cpus); #endif /* - * Use enter_panic_mode to allow only 1 cpu to proceed + * Only allow 1 cpu to proceed */ - enter_panic_mode(); + arch_spin_lock(&nmi_lock); #ifdef REAL_NMI_SIGNAL /* @@ -223,7 +218,7 @@ cont_nmi_dump(void) if (i == 1000) { for_each_online_node(node) if (NODEPDA(node)->dump_count == 0) { - cpu = node_to_first_cpu(node); + cpu = cpumask_first(cpumask_of_node(node)); for (n=0; n < CNODE_NUM_CPUS(node); cpu++, n++) { CPUMASK_SETB(nmied_cpus, cpu); /* diff --git a/arch/mips/sgi-ip27/ip27-reset.c b/arch/mips/sgi-ip27/ip27-reset.c index c17076108d4..ac37e54b3d5 100644 --- a/arch/mips/sgi-ip27/ip27-reset.c +++ b/arch/mips/sgi-ip27/ip27-reset.c @@ -19,7 +19,6 @@ #include <asm/io.h> #include <asm/irq.h> #include <asm/reboot.h> -#include <asm/system.h> #include <asm/sgialib.h> #include <asm/sn/addrs.h> #include <asm/sn/arch.h> @@ -30,7 +29,7 @@ void machine_restart(char *command) __attribute__((noreturn)); void machine_halt(void) __attribute__((noreturn)); void machine_power_off(void) __attribute__((noreturn)); -#define noreturn while(1); /* Silence gcc. */ +#define noreturn while(1); /* Silence gcc. */ /* XXX How to pass the reboot command to the firmware??? */ static void ip27_machine_restart(char *command) diff --git a/arch/mips/sgi-ip27/ip27-smp.c b/arch/mips/sgi-ip27/ip27-smp.c index f15fc93d6b3..f9ae6a8fa7c 100644 --- a/arch/mips/sgi-ip27/ip27-smp.c +++ b/arch/mips/sgi-ip27/ip27-smp.c @@ -76,7 +76,7 @@ static int do_cpumask(cnodeid_t cnode, nasid_t nasid, int highest) /* Only let it join in if it's marked enabled */ if ((acpu->cpu_info.flags & KLINFO_ENABLE) && (tot_cpus_found != NR_CPUS)) { - cpu_set(cpuid, phys_cpu_present_map); + set_cpu_possible(cpuid, true); alloc_cpupda(cpuid, tot_cpus_found); cpus_found++; tot_cpus_found++; @@ -165,34 +165,33 @@ static void ip27_send_ipi_single(int destid, unsigned int action) REMOTE_HUB_SEND_INTR(COMPACT_TO_NASID_NODEID(cpu_to_node(destid)), irq); } -static void ip27_send_ipi_mask(cpumask_t mask, unsigned int action) +static void ip27_send_ipi_mask(const struct cpumask *mask, unsigned int action) { unsigned int i; - for_each_cpu_mask(i, mask) + for_each_cpu(i, mask) ip27_send_ipi_single(i, action); } -static void __cpuinit ip27_init_secondary(void) +static void ip27_init_secondary(void) { per_cpu_init(); - local_irq_enable(); } -static void __cpuinit ip27_smp_finish(void) +static void ip27_smp_finish(void) { -} + extern void hub_rt_clock_event_init(void); -static void __init ip27_cpus_done(void) -{ + hub_rt_clock_event_init(); + local_irq_enable(); } /* - * Launch a slave into smp_bootstrap(). It doesn't take an argument, and we + * Launch a slave into smp_bootstrap(). It doesn't take an argument, and we * set sp to the kernel stack of the newly created idle process, gp to the proc * struct so that current_thread_info() will work. */ -static void __cpuinit ip27_boot_secondary(int cpu, struct task_struct *idle) +static void ip27_boot_secondary(int cpu, struct task_struct *idle) { unsigned long gp = (unsigned long)task_thread_info(idle); unsigned long sp = __KSTK_TOS(idle); @@ -216,9 +215,9 @@ static void __init ip27_smp_setup(void) /* * Assumption to be fixed: we're always booted on logical / physical - * processor 0. While we're always running on logical processor 0 + * processor 0. While we're always running on logical processor 0 * this still means this is physical processor zero; it might for - * example be disabled in the firwware. + * example be disabled in the firmware. */ alloc_cpupda(0, 0); } @@ -233,7 +232,6 @@ struct plat_smp_ops ip27_smp_ops = { .send_ipi_mask = ip27_send_ipi_mask, .init_secondary = ip27_init_secondary, .smp_finish = ip27_smp_finish, - .cpus_done = ip27_cpus_done, .boot_secondary = ip27_boot_secondary, .smp_setup = ip27_smp_setup, .prepare_cpus = ip27_prepare_cpus, diff --git a/arch/mips/sgi-ip27/ip27-timer.c b/arch/mips/sgi-ip27/ip27-timer.c index 25d3baf0ebc..1d97eaba0c5 100644 --- a/arch/mips/sgi-ip27/ip27-timer.c +++ b/arch/mips/sgi-ip27/ip27-timer.c @@ -10,15 +10,16 @@ #include <linux/interrupt.h> #include <linux/kernel_stat.h> #include <linux/param.h> +#include <linux/smp.h> #include <linux/time.h> #include <linux/timex.h> #include <linux/mm.h> +#include <linux/platform_device.h> #include <asm/time.h> #include <asm/pgtable.h> #include <asm/sgialib.h> #include <asm/sn/ioc3.h> -#include <asm/m48t35.h> #include <asm/sn/klconfig.h> #include <asm/sn/arch.h> #include <asm/sn/addrs.h> @@ -28,51 +29,6 @@ #define TICK_SIZE (tick_nsec / 1000) -#if 0 -static int set_rtc_mmss(unsigned long nowtime) -{ - int retval = 0; - int real_seconds, real_minutes, cmos_minutes; - struct m48t35_rtc *rtc; - nasid_t nid; - - nid = get_nasid(); - rtc = (struct m48t35_rtc *)(KL_CONFIG_CH_CONS_INFO(nid)->memory_base + - IOC3_BYTEBUS_DEV0); - - rtc->control |= M48T35_RTC_READ; - cmos_minutes = BCD2BIN(rtc->min); - rtc->control &= ~M48T35_RTC_READ; - - /* - * Since we're only adjusting minutes and seconds, don't interfere with - * hour overflow. This avoids messing with unknown time zones but - * requires your RTC not to be off by more than 15 minutes - */ - real_seconds = nowtime % 60; - real_minutes = nowtime / 60; - if (((abs(real_minutes - cmos_minutes) + 15)/30) & 1) - real_minutes += 30; /* correct for half hour time zone */ - real_minutes %= 60; - - if (abs(real_minutes - cmos_minutes) < 30) { - real_seconds = BIN2BCD(real_seconds); - real_minutes = BIN2BCD(real_minutes); - rtc->control |= M48T35_RTC_SET; - rtc->sec = real_seconds; - rtc->min = real_minutes; - rtc->control &= ~M48T35_RTC_SET; - } else { - printk(KERN_WARNING - "set_rtc_mmss: can't update from %d to %d\n", - cmos_minutes, real_minutes); - retval = -1; - } - - return retval; -} -#endif - /* Includes for ioc3_init(). */ #include <asm/sn/types.h> #include <asm/sn/sn0/addrs.h> @@ -80,52 +36,18 @@ static int set_rtc_mmss(unsigned long nowtime) #include <asm/sn/sn0/hubio.h> #include <asm/pci/bridge.h> -unsigned long read_persistent_clock(void) -{ - unsigned int year, month, date, hour, min, sec; - struct m48t35_rtc *rtc; - nasid_t nid; - - nid = get_nasid(); - rtc = (struct m48t35_rtc *)(KL_CONFIG_CH_CONS_INFO(nid)->memory_base + - IOC3_BYTEBUS_DEV0); - - rtc->control |= M48T35_RTC_READ; - sec = rtc->sec; - min = rtc->min; - hour = rtc->hour; - date = rtc->date; - month = rtc->month; - year = rtc->year; - rtc->control &= ~M48T35_RTC_READ; - - sec = BCD2BIN(sec); - min = BCD2BIN(min); - hour = BCD2BIN(hour); - date = BCD2BIN(date); - month = BCD2BIN(month); - year = BCD2BIN(year); - - year += 1970; - - return mktime(year, month, date, hour, min, sec); -} - -static void enable_rt_irq(unsigned int irq) +static void enable_rt_irq(struct irq_data *d) { } -static void disable_rt_irq(unsigned int irq) +static void disable_rt_irq(struct irq_data *d) { } static struct irq_chip rt_irq_type = { .name = "SN HUB RT timer", - .ack = disable_rt_irq, - .mask = disable_rt_irq, - .mask_ack = disable_rt_irq, - .unmask = enable_rt_irq, - .eoi = enable_rt_irq, + .irq_mask = disable_rt_irq, + .irq_unmask = enable_rt_irq, }; static int rt_next_event(unsigned long delta, struct clock_event_device *evt) @@ -144,26 +66,18 @@ static int rt_next_event(unsigned long delta, struct clock_event_device *evt) static void rt_set_mode(enum clock_event_mode mode, struct clock_event_device *evt) { - switch (mode) { - case CLOCK_EVT_MODE_ONESHOT: - /* The only mode supported */ - break; - - case CLOCK_EVT_MODE_PERIODIC: - case CLOCK_EVT_MODE_UNUSED: - case CLOCK_EVT_MODE_SHUTDOWN: - case CLOCK_EVT_MODE_RESUME: - /* Nothing to do */ - break; - } + /* Nothing to do ... */ } unsigned int rt_timer_irq; +static DEFINE_PER_CPU(struct clock_event_device, hub_rt_clockevent); +static DEFINE_PER_CPU(char [11], hub_rt_name); + static irqreturn_t hub_rt_counter_handler(int irq, void *dev_id) { - struct clock_event_device *cd = dev_id; unsigned int cpu = smp_processor_id(); + struct clock_event_device *cd = &per_cpu(hub_rt_clockevent, cpu); int slice = cputoslice(cpu); /* @@ -177,7 +91,7 @@ static irqreturn_t hub_rt_counter_handler(int irq, void *dev_id) struct irqaction hub_rt_irqaction = { .handler = hub_rt_counter_handler, - .flags = IRQF_DISABLED | IRQF_PERCPU, + .flags = IRQF_PERCPU | IRQF_TIMER, .name = "hub-rt", }; @@ -192,10 +106,7 @@ struct irqaction hub_rt_irqaction = { #define NSEC_PER_CYCLE 800 #define CYCLES_PER_SEC (NSEC_PER_SEC / NSEC_PER_CYCLE) -static DEFINE_PER_CPU(struct clock_event_device, hub_rt_clockevent); -static DEFINE_PER_CPU(char [11], hub_rt_name); - -static void __cpuinit hub_rt_clock_event_init(void) +void hub_rt_clock_event_init(void) { unsigned int cpu = smp_processor_id(); struct clock_event_device *cd = &per_cpu(hub_rt_clockevent, cpu); @@ -203,23 +114,22 @@ static void __cpuinit hub_rt_clock_event_init(void) int irq = rt_timer_irq; sprintf(name, "hub-rt %d", cpu); - cd->name = "HUB-RT", - cd->features = CLOCK_EVT_FEAT_ONESHOT, + cd->name = name; + cd->features = CLOCK_EVT_FEAT_ONESHOT; clockevent_set_clock(cd, CYCLES_PER_SEC); - cd->max_delta_ns = clockevent_delta2ns(0xfffffffffffff, cd); - cd->min_delta_ns = clockevent_delta2ns(0x300, cd); - cd->rating = 200, - cd->irq = irq, - cd->cpumask = cpumask_of_cpu(cpu), - cd->rating = 300, - cd->set_next_event = rt_next_event, - cd->set_mode = rt_set_mode, + cd->max_delta_ns = clockevent_delta2ns(0xfffffffffffff, cd); + cd->min_delta_ns = clockevent_delta2ns(0x300, cd); + cd->rating = 200; + cd->irq = irq; + cd->cpumask = cpumask_of(cpu); + cd->set_next_event = rt_next_event; + cd->set_mode = rt_set_mode; clockevents_register_device(cd); } static void __init hub_rt_clock_event_global_init(void) { - unsigned int irq; + int irq; do { smp_wmb(); @@ -232,18 +142,18 @@ static void __init hub_rt_clock_event_global_init(void) panic("Allocation of irq number for timer failed"); } while (xchg(&rt_timer_irq, irq)); - set_irq_chip_and_handler(irq, &rt_irq_type, handle_percpu_irq); + irq_set_chip_and_handler(irq, &rt_irq_type, handle_percpu_irq); setup_irq(irq, &hub_rt_irqaction); } -static cycle_t hub_rt_read(void) +static cycle_t hub_rt_read(struct clocksource *cs) { return REMOTE_HUB_L(cputonasid(0), PI_RT_COUNT); } struct clocksource hub_rt_clocksource = { .name = "HUB-RT", - .rating = 200, + .rating = 200, .read = hub_rt_read, .mask = CLOCKSOURCE_MASK(52), .flags = CLOCK_SOURCE_IS_CONTINUOUS, @@ -253,17 +163,17 @@ static void __init hub_rt_clocksource_init(void) { struct clocksource *cs = &hub_rt_clocksource; - clocksource_set_clock(cs, CYCLES_PER_SEC); - clocksource_register(cs); + clocksource_register_hz(cs, CYCLES_PER_SEC); } void __init plat_time_init(void) { hub_rt_clocksource_init(); hub_rt_clock_event_global_init(); + hub_rt_clock_event_init(); } -void __cpuinit cpu_time_init(void) +void cpu_time_init(void) { lboard_t *board; klcpu_t *cpu; @@ -281,12 +191,12 @@ void __cpuinit cpu_time_init(void) printk("CPU %d clock is %dMHz.\n", smp_processor_id(), cpu->cpu_speed); - hub_rt_clock_event_init(); set_c0_status(SRB_TIMOCLK); } -void __cpuinit hub_rtc_init(cnodeid_t cnode) +void hub_rtc_init(cnodeid_t cnode) { + /* * We only need to initialize the current node. * If this is not the current node then it is a cpuless @@ -302,3 +212,23 @@ void __cpuinit hub_rtc_init(cnodeid_t cnode) LOCAL_HUB_S(PI_RT_PEND_B, 0); } } + +static int __init sgi_ip27_rtc_devinit(void) +{ + struct resource res; + + memset(&res, 0, sizeof(res)); + res.start = XPHYSADDR(KL_CONFIG_CH_CONS_INFO(master_nasid)->memory_base + + IOC3_BYTEBUS_DEV0); + res.end = res.start + 32767; + res.flags = IORESOURCE_MEM; + + return IS_ERR(platform_device_register_simple("rtc-m48t35", -1, + &res, 1)); +} + +/* + * kludge make this a device_initcall after ioc3 resource conflicts + * are resolved + */ +late_initcall(sgi_ip27_rtc_devinit); diff --git a/arch/mips/sgi-ip27/ip27-xtalk.c b/arch/mips/sgi-ip27/ip27-xtalk.c index 6ae64e8dfc4..20f582a2137 100644 --- a/arch/mips/sgi-ip27/ip27-xtalk.c +++ b/arch/mips/sgi-ip27/ip27-xtalk.c @@ -7,8 +7,8 @@ * Generic XTALK initialization code */ -#include <linux/init.h> #include <linux/kernel.h> +#include <linux/smp.h> #include <asm/sn/types.h> #include <asm/sn/klconfig.h> #include <asm/sn/hub.h> @@ -16,15 +16,15 @@ #include <asm/xtalk/xtalk.h> -#define XBOW_WIDGET_PART_NUM 0x0 -#define XXBOW_WIDGET_PART_NUM 0xd000 /* Xbow in Xbridge */ -#define BASE_XBOW_PORT 8 /* Lowest external port */ +#define XBOW_WIDGET_PART_NUM 0x0 +#define XXBOW_WIDGET_PART_NUM 0xd000 /* Xbow in Xbridge */ +#define BASE_XBOW_PORT 8 /* Lowest external port */ extern int bridge_probe(nasid_t nasid, int widget, int masterwid); -static int __cpuinit probe_one_port(nasid_t nasid, int widget, int masterwid) +static int probe_one_port(nasid_t nasid, int widget, int masterwid) { - widgetreg_t widget_id; + widgetreg_t widget_id; xwidget_part_num_t partnum; widget_id = *(volatile widgetreg_t *) @@ -46,7 +46,7 @@ static int __cpuinit probe_one_port(nasid_t nasid, int widget, int masterwid) return 0; } -static int __cpuinit xbow_probe(nasid_t nasid) +static int xbow_probe(nasid_t nasid) { lboard_t *brd; klxbow_t *xbow_p; @@ -99,12 +99,12 @@ static int __cpuinit xbow_probe(nasid_t nasid) return 0; } -void __cpuinit xtalk_probe_node(cnodeid_t nid) +void xtalk_probe_node(cnodeid_t nid) { - volatile u64 hubreg; - nasid_t nasid; + volatile u64 hubreg; + nasid_t nasid; xwidget_part_num_t partnum; - widgetreg_t widget_id; + widgetreg_t widget_id; nasid = COMPACT_TO_NASID_NODEID(nid); hubreg = REMOTE_HUB_L(nasid, IIO_LLP_CSR); @@ -114,7 +114,7 @@ void __cpuinit xtalk_probe_node(cnodeid_t nid) return; widget_id = *(volatile widgetreg_t *) - (RAW_NODE_SWIN_BASE(nasid, 0x0) + WIDGET_ID); + (RAW_NODE_SWIN_BASE(nasid, 0x0) + WIDGET_ID); partnum = XWIDGET_PART_NUM(widget_id); printk(KERN_INFO "Cpu %d, Nasid 0x%x: partnum 0x%x is ", |
