diff options
Diffstat (limited to 'arch/mips')
-rw-r--r-- | arch/mips/Kconfig | 14 | ||||
-rw-r--r-- | arch/mips/Makefile | 2 | ||||
-rw-r--r-- | arch/mips/dec/prom/memory.c | 2 | ||||
-rw-r--r-- | arch/mips/kernel/smtc.c | 64 | ||||
-rw-r--r-- | arch/mips/kernel/vpe.c | 9 | ||||
-rw-r--r-- | arch/mips/mips-boards/malta/Makefile | 3 | ||||
-rw-r--r-- | arch/mips/mips-boards/sim/sim_setup.c | 2 | ||||
-rw-r--r-- | arch/mips/mm/init.c | 3 | ||||
-rw-r--r-- | arch/mips/momentum/ocelot_g/prom.c | 4 | ||||
-rw-r--r-- | arch/mips/momentum/ocelot_g/setup.c | 4 | ||||
-rw-r--r-- | arch/mips/vr41xx/common/irq.c | 12 |
11 files changed, 80 insertions, 39 deletions
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index fd2ff0698a8..bbd386f572d 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -1568,6 +1568,20 @@ config MIPS_MT_FPAFF depends on MIPS_MT default y +config MIPS_MT_SMTC_INSTANT_REPLAY + bool "Low-latency Dispatch of Deferred SMTC IPIs" + depends on MIPS_MT_SMTC + default y + help + SMTC pseudo-interrupts between TCs are deferred and queued + if the target TC is interrupt-inhibited (IXMT). In the first + SMTC prototypes, these queued IPIs were serviced on return + to user mode, or on entry into the kernel idle loop. The + INSTANT_REPLAY option dispatches them as part of local_irq_restore() + processing, which adds runtime overhead (hence the option to turn + it off), but ensures that IPIs are handled promptly even under + heavy I/O interrupt load. + config MIPS_VPE_LOADER_TOM bool "Load VPE program into memory hidden from linux" depends on MIPS_VPE_LOADER diff --git a/arch/mips/Makefile b/arch/mips/Makefile index d1b026a0337..c68b5d3e5d1 100644 --- a/arch/mips/Makefile +++ b/arch/mips/Makefile @@ -623,7 +623,7 @@ LDFLAGS += -m $(ld-emul) ifdef CONFIG_MIPS CHECKFLAGS += $(shell $(CC) $(CFLAGS) -dM -E -xc /dev/null | \ - egrep -vw '__GNUC_(MAJOR|MINOR|PATCHLEVEL)__' | \ + egrep -vw '__GNUC_(|MINOR_|PATCHLEVEL_)_' | \ sed -e 's/^\#define /-D/' -e "s/ /='/" -e "s/$$/'/") ifdef CONFIG_64BIT CHECKFLAGS += -m64 diff --git a/arch/mips/dec/prom/memory.c b/arch/mips/dec/prom/memory.c index 3027ce78279..3aa01d268f2 100644 --- a/arch/mips/dec/prom/memory.c +++ b/arch/mips/dec/prom/memory.c @@ -122,7 +122,7 @@ unsigned long __init prom_free_prom_memory(void) addr += PAGE_SIZE; } - printk("Freeing unused PROM memory: %ldk freed\n", + printk("Freeing unused PROM memory: %ldkb freed\n", (end - PAGE_SIZE) >> 10); return end - PAGE_SIZE; diff --git a/arch/mips/kernel/smtc.c b/arch/mips/kernel/smtc.c index a8b387197d5..6a857bf030b 100644 --- a/arch/mips/kernel/smtc.c +++ b/arch/mips/kernel/smtc.c @@ -4,6 +4,7 @@ #include <linux/sched.h> #include <linux/cpumask.h> #include <linux/interrupt.h> +#include <linux/module.h> #include <asm/cpu.h> #include <asm/processor.h> @@ -270,9 +271,12 @@ void smtc_configure_tlb(void) * of their initialization in smtc_cpu_setup(). */ - tlbsiz = tlbsiz & 0x3f; /* MIPS32 limits TLB indices to 64 */ - cpu_data[0].tlbsize = tlbsiz; + /* MIPS32 limits TLB indices to 64 */ + if (tlbsiz > 64) + tlbsiz = 64; + cpu_data[0].tlbsize = current_cpu_data.tlbsize = tlbsiz; smtc_status |= SMTC_TLB_SHARED; + local_flush_tlb_all(); printk("TLB of %d entry pairs shared by %d VPEs\n", tlbsiz, vpes); @@ -1017,6 +1021,35 @@ void setup_cross_vpe_interrupts(void) * SMTC-specific hacks invoked from elsewhere in the kernel. */ +void smtc_ipi_replay(void) +{ + /* + * To the extent that we've ever turned interrupts off, + * we may have accumulated deferred IPIs. This is subtle. + * If we use the smtc_ipi_qdepth() macro, we'll get an + * exact number - but we'll also disable interrupts + * and create a window of failure where a new IPI gets + * queued after we test the depth but before we re-enable + * interrupts. So long as IXMT never gets set, however, + * we should be OK: If we pick up something and dispatch + * it here, that's great. If we see nothing, but concurrent + * with this operation, another TC sends us an IPI, IXMT + * is clear, and we'll handle it as a real pseudo-interrupt + * and not a pseudo-pseudo interrupt. + */ + if (IPIQ[smp_processor_id()].depth > 0) { + struct smtc_ipi *pipi; + extern void self_ipi(struct smtc_ipi *); + + while ((pipi = smtc_ipi_dq(&IPIQ[smp_processor_id()]))) { + self_ipi(pipi); + smtc_cpu_stats[smp_processor_id()].selfipis++; + } + } +} + +EXPORT_SYMBOL(smtc_ipi_replay); + void smtc_idle_loop_hook(void) { #ifdef SMTC_IDLE_HOOK_DEBUG @@ -1113,29 +1146,14 @@ void smtc_idle_loop_hook(void) if (pdb_msg != &id_ho_db_msg[0]) printk("CPU%d: %s", smp_processor_id(), id_ho_db_msg); #endif /* SMTC_IDLE_HOOK_DEBUG */ + /* - * To the extent that we've ever turned interrupts off, - * we may have accumulated deferred IPIs. This is subtle. - * If we use the smtc_ipi_qdepth() macro, we'll get an - * exact number - but we'll also disable interrupts - * and create a window of failure where a new IPI gets - * queued after we test the depth but before we re-enable - * interrupts. So long as IXMT never gets set, however, - * we should be OK: If we pick up something and dispatch - * it here, that's great. If we see nothing, but concurrent - * with this operation, another TC sends us an IPI, IXMT - * is clear, and we'll handle it as a real pseudo-interrupt - * and not a pseudo-pseudo interrupt. + * Replay any accumulated deferred IPIs. If "Instant Replay" + * is in use, there should never be any. */ - if (IPIQ[smp_processor_id()].depth > 0) { - struct smtc_ipi *pipi; - extern void self_ipi(struct smtc_ipi *); - - if ((pipi = smtc_ipi_dq(&IPIQ[smp_processor_id()])) != NULL) { - self_ipi(pipi); - smtc_cpu_stats[smp_processor_id()].selfipis++; - } - } +#ifndef CONFIG_MIPS_MT_SMTC_INSTANT_REPLAY + smtc_ipi_replay(); +#endif /* CONFIG_MIPS_MT_SMTC_INSTANT_REPLAY */ } void smtc_soft_dump(void) diff --git a/arch/mips/kernel/vpe.c b/arch/mips/kernel/vpe.c index 666bef484dc..458fccf87c5 100644 --- a/arch/mips/kernel/vpe.c +++ b/arch/mips/kernel/vpe.c @@ -139,13 +139,16 @@ struct tc { struct list_head list; }; -struct vpecontrol_ { +struct { /* Virtual processing elements */ struct list_head vpe_list; /* Thread contexts */ struct list_head tc_list; -} vpecontrol; +} vpecontrol = { + .vpe_list = LIST_HEAD_INIT(vpecontrol.vpe_list), + .tc_list = LIST_HEAD_INIT(vpecontrol.tc_list) +}; static void release_progmem(void *ptr); /* static __attribute_used__ void dump_vpe(struct vpe * v); */ @@ -1388,8 +1391,6 @@ static int __init vpe_module_init(void) /* dump_mtregs(); */ - INIT_LIST_HEAD(&vpecontrol.vpe_list); - INIT_LIST_HEAD(&vpecontrol.tc_list); val = read_c0_mvpconf0(); for (i = 0; i < ((val & MVPCONF0_PTC) + 1); i++) { diff --git a/arch/mips/mips-boards/malta/Makefile b/arch/mips/mips-boards/malta/Makefile index b662c75fb28..cb7f349b051 100644 --- a/arch/mips/mips-boards/malta/Makefile +++ b/arch/mips/mips-boards/malta/Makefile @@ -19,5 +19,6 @@ # under Linux. # -obj-y := malta_int.o malta_mtd.o malta_setup.o +obj-y := malta_int.o malta_setup.o +obj-$(CONFIG_MTD) += malta_mtd.o obj-$(CONFIG_SMP) += malta_smp.o diff --git a/arch/mips/mips-boards/sim/sim_setup.c b/arch/mips/mips-boards/sim/sim_setup.c index 2659c1c3b78..ea2066c3a1f 100644 --- a/arch/mips/mips-boards/sim/sim_setup.c +++ b/arch/mips/mips-boards/sim/sim_setup.c @@ -57,7 +57,7 @@ void __init plat_mem_setup(void) board_time_init = sim_time_init; prom_printf("Linux started...\n"); -#ifdef CONFIG_MT_SMP +#ifdef CONFIG_MIPS_MT_SMP sanitize_tlb_entries(); #endif } diff --git a/arch/mips/mm/init.c b/arch/mips/mm/init.c index 30245c09d02..49065c133eb 100644 --- a/arch/mips/mm/init.c +++ b/arch/mips/mm/init.c @@ -501,7 +501,8 @@ void free_initmem(void) freed = prom_free_prom_memory(); if (freed) - printk(KERN_INFO "Freeing firmware memory: %ldk freed\n",freed); + printk(KERN_INFO "Freeing firmware memory: %ldkb freed\n", + freed >> 10); free_init_pages("unused kernel memory", __pa_symbol(&__init_begin), diff --git a/arch/mips/momentum/ocelot_g/prom.c b/arch/mips/momentum/ocelot_g/prom.c index 6509a9c9863..2f75c6b91ec 100644 --- a/arch/mips/momentum/ocelot_g/prom.c +++ b/arch/mips/momentum/ocelot_g/prom.c @@ -28,7 +28,7 @@ struct callvectors* debug_vectors; extern unsigned long marvell_base; extern unsigned long bus_clock; -#ifdef CONFIG_GALILLEO_GT64240_ETH +#ifdef CONFIG_GALILEO_GT64240_ETH extern unsigned char prom_mac_addr_base[6]; #endif @@ -61,7 +61,7 @@ void __init prom_init(void) mips_machgroup = MACH_GROUP_MOMENCO; mips_machtype = MACH_MOMENCO_OCELOT_G; -#ifdef CONFIG_GALILLEO_GT64240_ETH +#ifdef CONFIG_GALILEO_GT64240_ETH /* get the base MAC address for on-board ethernet ports */ memcpy(prom_mac_addr_base, (void*)0xfc807cf2, 6); #endif diff --git a/arch/mips/momentum/ocelot_g/setup.c b/arch/mips/momentum/ocelot_g/setup.c index d288f7b0184..9db638a7982 100644 --- a/arch/mips/momentum/ocelot_g/setup.c +++ b/arch/mips/momentum/ocelot_g/setup.c @@ -64,7 +64,7 @@ #include "ocelot_pld.h" -#ifdef CONFIG_GALILLEO_GT64240_ETH +#ifdef CONFIG_GALILEO_GT64240_ETH extern unsigned char prom_mac_addr_base[6]; #endif @@ -185,7 +185,7 @@ void __init plat_mem_setup(void) /* do handoff reconfiguration */ PMON_v2_setup(); -#ifdef CONFIG_GALILLEO_GT64240_ETH +#ifdef CONFIG_GALILEO_GT64240_ETH /* get the mac addr */ memcpy(prom_mac_addr_base, (void*)0xfc807cf2, 6); #endif diff --git a/arch/mips/vr41xx/common/irq.c b/arch/mips/vr41xx/common/irq.c index 397ba94cd7e..16decf4ac2f 100644 --- a/arch/mips/vr41xx/common/irq.c +++ b/arch/mips/vr41xx/common/irq.c @@ -1,7 +1,7 @@ /* * Interrupt handing routines for NEC VR4100 series. * - * Copyright (C) 2005 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp> + * Copyright (C) 2005-2007 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp> * * 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 @@ -73,13 +73,19 @@ static void irq_dispatch(unsigned int irq) if (cascade->get_irq != NULL) { unsigned int source_irq = irq; desc = irq_desc + source_irq; - desc->chip->ack(source_irq); + if (desc->chip->mask_ack) + desc->chip->mask_ack(source_irq); + else { + desc->chip->mask(source_irq); + desc->chip->ack(source_irq); + } irq = cascade->get_irq(irq); if (irq < 0) atomic_inc(&irq_err_count); else irq_dispatch(irq); - desc->chip->end(source_irq); + if (!(desc->status & IRQ_DISABLED) && desc->chip->unmask) + desc->chip->unmask(source_irq); } else do_IRQ(irq); } |