···15681568 depends on MIPS_MT15691569 default y1570157015711571+config MIPS_MT_SMTC_INSTANT_REPLAY15721572+ bool "Low-latency Dispatch of Deferred SMTC IPIs"15731573+ depends on MIPS_MT_SMTC15741574+ default y15751575+ help15761576+ SMTC pseudo-interrupts between TCs are deferred and queued15771577+ if the target TC is interrupt-inhibited (IXMT). In the first15781578+ SMTC prototypes, these queued IPIs were serviced on return15791579+ to user mode, or on entry into the kernel idle loop. The15801580+ INSTANT_REPLAY option dispatches them as part of local_irq_restore()15811581+ processing, which adds runtime overhead (hence the option to turn15821582+ it off), but ensures that IPIs are handled promptly even under15831583+ heavy I/O interrupt load.15841584+15711585config MIPS_VPE_LOADER_TOM15721586 bool "Load VPE program into memory hidden from linux"15731587 depends on MIPS_VPE_LOADER
+34-22
arch/mips/kernel/smtc.c
···10171017 * SMTC-specific hacks invoked from elsewhere in the kernel.10181018 */1019101910201020+void smtc_ipi_replay(void)10211021+{10221022+ /*10231023+ * To the extent that we've ever turned interrupts off,10241024+ * we may have accumulated deferred IPIs. This is subtle.10251025+ * If we use the smtc_ipi_qdepth() macro, we'll get an10261026+ * exact number - but we'll also disable interrupts10271027+ * and create a window of failure where a new IPI gets10281028+ * queued after we test the depth but before we re-enable10291029+ * interrupts. So long as IXMT never gets set, however,10301030+ * we should be OK: If we pick up something and dispatch10311031+ * it here, that's great. If we see nothing, but concurrent10321032+ * with this operation, another TC sends us an IPI, IXMT10331033+ * is clear, and we'll handle it as a real pseudo-interrupt10341034+ * and not a pseudo-pseudo interrupt.10351035+ */10361036+ if (IPIQ[smp_processor_id()].depth > 0) {10371037+ struct smtc_ipi *pipi;10381038+ extern void self_ipi(struct smtc_ipi *);10391039+10401040+ while ((pipi = smtc_ipi_dq(&IPIQ[smp_processor_id()]))) {10411041+ self_ipi(pipi);10421042+ smtc_cpu_stats[smp_processor_id()].selfipis++;10431043+ }10441044+ }10451045+}10461046+10201047void smtc_idle_loop_hook(void)10211048{10221049#ifdef SMTC_IDLE_HOOK_DEBUG···11401113 if (pdb_msg != &id_ho_db_msg[0])11411114 printk("CPU%d: %s", smp_processor_id(), id_ho_db_msg);11421115#endif /* SMTC_IDLE_HOOK_DEBUG */11431143- /*11441144- * To the extent that we've ever turned interrupts off,11451145- * we may have accumulated deferred IPIs. This is subtle.11461146- * If we use the smtc_ipi_qdepth() macro, we'll get an11471147- * exact number - but we'll also disable interrupts11481148- * and create a window of failure where a new IPI gets11491149- * queued after we test the depth but before we re-enable11501150- * interrupts. So long as IXMT never gets set, however,11511151- * we should be OK: If we pick up something and dispatch11521152- * it here, that's great. If we see nothing, but concurrent11531153- * with this operation, another TC sends us an IPI, IXMT11541154- * is clear, and we'll handle it as a real pseudo-interrupt11551155- * and not a pseudo-pseudo interrupt.11561156- */11571157- if (IPIQ[smp_processor_id()].depth > 0) {11581158- struct smtc_ipi *pipi;11591159- extern void self_ipi(struct smtc_ipi *);1160111611611161- if ((pipi = smtc_ipi_dq(&IPIQ[smp_processor_id()])) != NULL) {11621162- self_ipi(pipi);11631163- smtc_cpu_stats[smp_processor_id()].selfipis++;11641164- }11651165- }11171117+ /*11181118+ * Replay any accumulated deferred IPIs. If "Instant Replay"11191119+ * is in use, there should never be any.11201120+ */11211121+#ifndef CONFIG_MIPS_MT_SMTC_INSTANT_REPLAY11221122+ smtc_ipi_replay();11231123+#endif /* CONFIG_MIPS_MT_SMTC_INSTANT_REPLAY */11661124}1167112511681126void smtc_soft_dump(void)
+9-3
arch/mips/vr41xx/common/irq.c
···11/*22 * Interrupt handing routines for NEC VR4100 series.33 *44- * Copyright (C) 2005 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>44+ * Copyright (C) 2005-2007 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>55 *66 * This program is free software; you can redistribute it and/or modify77 * it under the terms of the GNU General Public License as published by···7373 if (cascade->get_irq != NULL) {7474 unsigned int source_irq = irq;7575 desc = irq_desc + source_irq;7676- desc->chip->ack(source_irq);7676+ if (desc->chip->mask_ack)7777+ desc->chip->mask_ack(source_irq);7878+ else {7979+ desc->chip->mask(source_irq);8080+ desc->chip->ack(source_irq);8181+ }7782 irq = cascade->get_irq(irq);7883 if (irq < 0)7984 atomic_inc(&irq_err_count);8085 else8186 irq_dispatch(irq);8282- desc->chip->end(source_irq);8787+ if (!(desc->status & IRQ_DISABLED) && desc->chip->unmask)8888+ desc->chip->unmask(source_irq);8389 } else8490 do_IRQ(irq);8591}
+52-62
drivers/char/vr41xx_giu.c
···33 *44 * Copyright (C) 2002 MontaVista Software Inc.55 * Author: Yoichi Yuasa <yyuasa@mvista.com or source@mvista.com>66- * Copyright (C) 2003-2005 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>66+ * Copyright (C) 2003-2007 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>77 *88 * This program is free software; you can redistribute it and/or modify99 * it under the terms of the GNU General Public License as published by···125125 return data;126126}127127128128-static unsigned int startup_giuint_low_irq(unsigned int irq)128128+static void ack_giuint_low(unsigned int irq)129129{130130- unsigned int pin;131131-132132- pin = GPIO_PIN_OF_IRQ(irq);133133- giu_write(GIUINTSTATL, 1 << pin);134134- giu_set(GIUINTENL, 1 << pin);135135-136136- return 0;130130+ giu_write(GIUINTSTATL, 1 << GPIO_PIN_OF_IRQ(irq));137131}138132139139-static void shutdown_giuint_low_irq(unsigned int irq)133133+static void mask_giuint_low(unsigned int irq)140134{141135 giu_clear(GIUINTENL, 1 << GPIO_PIN_OF_IRQ(irq));142136}143137144144-static void enable_giuint_low_irq(unsigned int irq)145145-{146146- giu_set(GIUINTENL, 1 << GPIO_PIN_OF_IRQ(irq));147147-}148148-149149-#define disable_giuint_low_irq shutdown_giuint_low_irq150150-151151-static void ack_giuint_low_irq(unsigned int irq)138138+static void mask_ack_giuint_low(unsigned int irq)152139{153140 unsigned int pin;154141···144157 giu_write(GIUINTSTATL, 1 << pin);145158}146159147147-static void end_giuint_low_irq(unsigned int irq)160160+static void unmask_giuint_low(unsigned int irq)148161{149149- if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS)))150150- giu_set(GIUINTENL, 1 << GPIO_PIN_OF_IRQ(irq));162162+ giu_set(GIUINTENL, 1 << GPIO_PIN_OF_IRQ(irq));151163}152164153153-static struct hw_interrupt_type giuint_low_irq_type = {154154- .typename = "GIUINTL",155155- .startup = startup_giuint_low_irq,156156- .shutdown = shutdown_giuint_low_irq,157157- .enable = enable_giuint_low_irq,158158- .disable = disable_giuint_low_irq,159159- .ack = ack_giuint_low_irq,160160- .end = end_giuint_low_irq,165165+static struct irq_chip giuint_low_irq_chip = {166166+ .name = "GIUINTL",167167+ .ack = ack_giuint_low,168168+ .mask = mask_giuint_low,169169+ .mask_ack = mask_ack_giuint_low,170170+ .unmask = unmask_giuint_low,161171};162172163163-static unsigned int startup_giuint_high_irq(unsigned int irq)173173+static void ack_giuint_high(unsigned int irq)164174{165165- unsigned int pin;166166-167167- pin = GPIO_PIN_OF_IRQ(irq) - GIUINT_HIGH_OFFSET;168168- giu_write(GIUINTSTATH, 1 << pin);169169- giu_set(GIUINTENH, 1 << pin);170170-171171- return 0;175175+ giu_write(GIUINTSTATH, 1 << (GPIO_PIN_OF_IRQ(irq) - GIUINT_HIGH_OFFSET));172176}173177174174-static void shutdown_giuint_high_irq(unsigned int irq)178178+static void mask_giuint_high(unsigned int irq)175179{176180 giu_clear(GIUINTENH, 1 << (GPIO_PIN_OF_IRQ(irq) - GIUINT_HIGH_OFFSET));177181}178182179179-static void enable_giuint_high_irq(unsigned int irq)180180-{181181- giu_set(GIUINTENH, 1 << (GPIO_PIN_OF_IRQ(irq) - GIUINT_HIGH_OFFSET));182182-}183183-184184-#define disable_giuint_high_irq shutdown_giuint_high_irq185185-186186-static void ack_giuint_high_irq(unsigned int irq)183183+static void mask_ack_giuint_high(unsigned int irq)187184{188185 unsigned int pin;189186···176205 giu_write(GIUINTSTATH, 1 << pin);177206}178207179179-static void end_giuint_high_irq(unsigned int irq)208208+static void unmask_giuint_high(unsigned int irq)180209{181181- if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS)))182182- giu_set(GIUINTENH, 1 << (GPIO_PIN_OF_IRQ(irq) - GIUINT_HIGH_OFFSET));210210+ giu_set(GIUINTENH, 1 << (GPIO_PIN_OF_IRQ(irq) - GIUINT_HIGH_OFFSET));183211}184212185185-static struct hw_interrupt_type giuint_high_irq_type = {186186- .typename = "GIUINTH",187187- .startup = startup_giuint_high_irq,188188- .shutdown = shutdown_giuint_high_irq,189189- .enable = enable_giuint_high_irq,190190- .disable = disable_giuint_high_irq,191191- .ack = ack_giuint_high_irq,192192- .end = end_giuint_high_irq,213213+static struct irq_chip giuint_high_irq_chip = {214214+ .name = "GIUINTH",215215+ .ack = ack_giuint_high,216216+ .mask = mask_giuint_high,217217+ .mask_ack = mask_ack_giuint_high,218218+ .unmask = unmask_giuint_high,193219};194220195221static int giu_get_irq(unsigned int irq)···250282 break;251283 }252284 }285285+ set_irq_chip_and_handler(GIU_IRQ(pin),286286+ &giuint_low_irq_chip,287287+ handle_edge_irq);253288 } else {254289 giu_clear(GIUINTTYPL, mask);255290 giu_clear(GIUINTHTSELL, mask);291291+ set_irq_chip_and_handler(GIU_IRQ(pin),292292+ &giuint_low_irq_chip,293293+ handle_level_irq);256294 }257295 giu_write(GIUINTSTATL, mask);258296 } else if (pin < GIUINT_HIGH_MAX) {···285311 break;286312 }287313 }314314+ set_irq_chip_and_handler(GIU_IRQ(pin),315315+ &giuint_high_irq_chip,316316+ handle_edge_irq);288317 } else {289318 giu_clear(GIUINTTYPH, mask);290319 giu_clear(GIUINTHTSELH, mask);320320+ set_irq_chip_and_handler(GIU_IRQ(pin),321321+ &giuint_high_irq_chip,322322+ handle_level_irq);291323 }292324 giu_write(GIUINTSTATH, mask);293325 }···597617static int __devinit giu_probe(struct platform_device *dev)598618{599619 unsigned long start, size, flags = 0;600600- unsigned int nr_pins = 0;620620+ unsigned int nr_pins = 0, trigger, i, pin;601621 struct resource *res1, *res2 = NULL;602622 void *base;603603- int retval, i;623623+ struct irq_chip *chip;624624+ int retval;604625605626 switch (current_cpu_data.cputype) {606627 case CPU_VR4111:···669688 giu_write(GIUINTENL, 0);670689 giu_write(GIUINTENH, 0);671690691691+ trigger = giu_read(GIUINTTYPH) << 16;692692+ trigger |= giu_read(GIUINTTYPL);672693 for (i = GIU_IRQ_BASE; i <= GIU_IRQ_LAST; i++) {673673- if (i < GIU_IRQ(GIUINT_HIGH_OFFSET))674674- irq_desc[i].chip = &giuint_low_irq_type;694694+ pin = GPIO_PIN_OF_IRQ(i);695695+ if (pin < GIUINT_HIGH_OFFSET)696696+ chip = &giuint_low_irq_chip;675697 else676676- irq_desc[i].chip = &giuint_high_irq_type;698698+ chip = &giuint_high_irq_chip;699699+700700+ if (trigger & (1 << pin))701701+ set_irq_chip_and_handler(i, chip, handle_edge_irq);702702+ else703703+ set_irq_chip_and_handler(i, chip, handle_level_irq);704704+677705 }678706679707 return cascade_irq(GIUINT_IRQ, giu_get_irq);
+22
include/asm-mips/irqflags.h
···15151616#include <asm/hazards.h>17171818+/*1919+ * CONFIG_MIPS_MT_SMTC_INSTANT_REPLAY does prompt replay of deferred IPIs,2020+ * at the cost of branch and call overhead on each local_irq_restore()2121+ */2222+2323+#ifdef CONFIG_MIPS_MT_SMTC_INSTANT_REPLAY2424+2525+extern void smtc_ipi_replay(void);2626+2727+#define irq_restore_epilog(flags) \2828+do { \2929+ if (!(flags & 0x0400)) \3030+ smtc_ipi_replay(); \3131+} while (0)3232+3333+#else3434+3535+#define irq_restore_epilog(ignore) do { } while (0)3636+3737+#endif /* CONFIG_MIPS_MT_SMTC_INSTANT_REPLAY */3838+1839__asm__ (1940 " .macro raw_local_irq_enable \n"2041 " .set push \n"···214193 : "=r" (__tmp1) \215194 : "0" (flags) \216195 : "memory"); \196196+ irq_restore_epilog(flags); \217197} while(0)218198219199static inline int raw_irqs_disabled_flags(unsigned long flags)