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

Configure Feed

Select the types of activity you want to include in your feed.

Merge branch 'upstream' of git://ftp.linux-mips.org/pub/scm/upstream-linus

* 'upstream' of git://ftp.linux-mips.org/pub/scm/upstream-linus:
[MIPS] Vr41xx: Fix after GENERIC_HARDIRQS_NO__DO_IRQ change
[MIPS] SMTC: Instant IPI replay.

+131 -87
+14
arch/mips/Kconfig
··· 1568 1568 depends on MIPS_MT 1569 1569 default y 1570 1570 1571 + config MIPS_MT_SMTC_INSTANT_REPLAY 1572 + bool "Low-latency Dispatch of Deferred SMTC IPIs" 1573 + depends on MIPS_MT_SMTC 1574 + default y 1575 + help 1576 + SMTC pseudo-interrupts between TCs are deferred and queued 1577 + if the target TC is interrupt-inhibited (IXMT). In the first 1578 + SMTC prototypes, these queued IPIs were serviced on return 1579 + to user mode, or on entry into the kernel idle loop. The 1580 + INSTANT_REPLAY option dispatches them as part of local_irq_restore() 1581 + processing, which adds runtime overhead (hence the option to turn 1582 + it off), but ensures that IPIs are handled promptly even under 1583 + heavy I/O interrupt load. 1584 + 1571 1585 config MIPS_VPE_LOADER_TOM 1572 1586 bool "Load VPE program into memory hidden from linux" 1573 1587 depends on MIPS_VPE_LOADER
+34 -22
arch/mips/kernel/smtc.c
··· 1017 1017 * SMTC-specific hacks invoked from elsewhere in the kernel. 1018 1018 */ 1019 1019 1020 + void smtc_ipi_replay(void) 1021 + { 1022 + /* 1023 + * To the extent that we've ever turned interrupts off, 1024 + * we may have accumulated deferred IPIs. This is subtle. 1025 + * If we use the smtc_ipi_qdepth() macro, we'll get an 1026 + * exact number - but we'll also disable interrupts 1027 + * and create a window of failure where a new IPI gets 1028 + * queued after we test the depth but before we re-enable 1029 + * interrupts. So long as IXMT never gets set, however, 1030 + * we should be OK: If we pick up something and dispatch 1031 + * it here, that's great. If we see nothing, but concurrent 1032 + * with this operation, another TC sends us an IPI, IXMT 1033 + * is clear, and we'll handle it as a real pseudo-interrupt 1034 + * and not a pseudo-pseudo interrupt. 1035 + */ 1036 + if (IPIQ[smp_processor_id()].depth > 0) { 1037 + struct smtc_ipi *pipi; 1038 + extern void self_ipi(struct smtc_ipi *); 1039 + 1040 + while ((pipi = smtc_ipi_dq(&IPIQ[smp_processor_id()]))) { 1041 + self_ipi(pipi); 1042 + smtc_cpu_stats[smp_processor_id()].selfipis++; 1043 + } 1044 + } 1045 + } 1046 + 1020 1047 void smtc_idle_loop_hook(void) 1021 1048 { 1022 1049 #ifdef SMTC_IDLE_HOOK_DEBUG ··· 1140 1113 if (pdb_msg != &id_ho_db_msg[0]) 1141 1114 printk("CPU%d: %s", smp_processor_id(), id_ho_db_msg); 1142 1115 #endif /* SMTC_IDLE_HOOK_DEBUG */ 1143 - /* 1144 - * To the extent that we've ever turned interrupts off, 1145 - * we may have accumulated deferred IPIs. This is subtle. 1146 - * If we use the smtc_ipi_qdepth() macro, we'll get an 1147 - * exact number - but we'll also disable interrupts 1148 - * and create a window of failure where a new IPI gets 1149 - * queued after we test the depth but before we re-enable 1150 - * interrupts. So long as IXMT never gets set, however, 1151 - * we should be OK: If we pick up something and dispatch 1152 - * it here, that's great. If we see nothing, but concurrent 1153 - * with this operation, another TC sends us an IPI, IXMT 1154 - * is clear, and we'll handle it as a real pseudo-interrupt 1155 - * and not a pseudo-pseudo interrupt. 1156 - */ 1157 - if (IPIQ[smp_processor_id()].depth > 0) { 1158 - struct smtc_ipi *pipi; 1159 - extern void self_ipi(struct smtc_ipi *); 1160 1116 1161 - if ((pipi = smtc_ipi_dq(&IPIQ[smp_processor_id()])) != NULL) { 1162 - self_ipi(pipi); 1163 - smtc_cpu_stats[smp_processor_id()].selfipis++; 1164 - } 1165 - } 1117 + /* 1118 + * Replay any accumulated deferred IPIs. If "Instant Replay" 1119 + * is in use, there should never be any. 1120 + */ 1121 + #ifndef CONFIG_MIPS_MT_SMTC_INSTANT_REPLAY 1122 + smtc_ipi_replay(); 1123 + #endif /* CONFIG_MIPS_MT_SMTC_INSTANT_REPLAY */ 1166 1124 } 1167 1125 1168 1126 void smtc_soft_dump(void)
+9 -3
arch/mips/vr41xx/common/irq.c
··· 1 1 /* 2 2 * Interrupt handing routines for NEC VR4100 series. 3 3 * 4 - * Copyright (C) 2005 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp> 4 + * Copyright (C) 2005-2007 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp> 5 5 * 6 6 * This program is free software; you can redistribute it and/or modify 7 7 * it under the terms of the GNU General Public License as published by ··· 73 73 if (cascade->get_irq != NULL) { 74 74 unsigned int source_irq = irq; 75 75 desc = irq_desc + source_irq; 76 - desc->chip->ack(source_irq); 76 + if (desc->chip->mask_ack) 77 + desc->chip->mask_ack(source_irq); 78 + else { 79 + desc->chip->mask(source_irq); 80 + desc->chip->ack(source_irq); 81 + } 77 82 irq = cascade->get_irq(irq); 78 83 if (irq < 0) 79 84 atomic_inc(&irq_err_count); 80 85 else 81 86 irq_dispatch(irq); 82 - desc->chip->end(source_irq); 87 + if (!(desc->status & IRQ_DISABLED) && desc->chip->unmask) 88 + desc->chip->unmask(source_irq); 83 89 } else 84 90 do_IRQ(irq); 85 91 }
+52 -62
drivers/char/vr41xx_giu.c
··· 3 3 * 4 4 * Copyright (C) 2002 MontaVista Software Inc. 5 5 * Author: Yoichi Yuasa <yyuasa@mvista.com or source@mvista.com> 6 - * Copyright (C) 2003-2005 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp> 6 + * Copyright (C) 2003-2007 Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp> 7 7 * 8 8 * This program is free software; you can redistribute it and/or modify 9 9 * it under the terms of the GNU General Public License as published by ··· 125 125 return data; 126 126 } 127 127 128 - static unsigned int startup_giuint_low_irq(unsigned int irq) 128 + static void ack_giuint_low(unsigned int irq) 129 129 { 130 - unsigned int pin; 131 - 132 - pin = GPIO_PIN_OF_IRQ(irq); 133 - giu_write(GIUINTSTATL, 1 << pin); 134 - giu_set(GIUINTENL, 1 << pin); 135 - 136 - return 0; 130 + giu_write(GIUINTSTATL, 1 << GPIO_PIN_OF_IRQ(irq)); 137 131 } 138 132 139 - static void shutdown_giuint_low_irq(unsigned int irq) 133 + static void mask_giuint_low(unsigned int irq) 140 134 { 141 135 giu_clear(GIUINTENL, 1 << GPIO_PIN_OF_IRQ(irq)); 142 136 } 143 137 144 - static void enable_giuint_low_irq(unsigned int irq) 145 - { 146 - giu_set(GIUINTENL, 1 << GPIO_PIN_OF_IRQ(irq)); 147 - } 148 - 149 - #define disable_giuint_low_irq shutdown_giuint_low_irq 150 - 151 - static void ack_giuint_low_irq(unsigned int irq) 138 + static void mask_ack_giuint_low(unsigned int irq) 152 139 { 153 140 unsigned int pin; 154 141 ··· 144 157 giu_write(GIUINTSTATL, 1 << pin); 145 158 } 146 159 147 - static void end_giuint_low_irq(unsigned int irq) 160 + static void unmask_giuint_low(unsigned int irq) 148 161 { 149 - if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) 150 - giu_set(GIUINTENL, 1 << GPIO_PIN_OF_IRQ(irq)); 162 + giu_set(GIUINTENL, 1 << GPIO_PIN_OF_IRQ(irq)); 151 163 } 152 164 153 - static struct hw_interrupt_type giuint_low_irq_type = { 154 - .typename = "GIUINTL", 155 - .startup = startup_giuint_low_irq, 156 - .shutdown = shutdown_giuint_low_irq, 157 - .enable = enable_giuint_low_irq, 158 - .disable = disable_giuint_low_irq, 159 - .ack = ack_giuint_low_irq, 160 - .end = end_giuint_low_irq, 165 + static struct irq_chip giuint_low_irq_chip = { 166 + .name = "GIUINTL", 167 + .ack = ack_giuint_low, 168 + .mask = mask_giuint_low, 169 + .mask_ack = mask_ack_giuint_low, 170 + .unmask = unmask_giuint_low, 161 171 }; 162 172 163 - static unsigned int startup_giuint_high_irq(unsigned int irq) 173 + static void ack_giuint_high(unsigned int irq) 164 174 { 165 - unsigned int pin; 166 - 167 - pin = GPIO_PIN_OF_IRQ(irq) - GIUINT_HIGH_OFFSET; 168 - giu_write(GIUINTSTATH, 1 << pin); 169 - giu_set(GIUINTENH, 1 << pin); 170 - 171 - return 0; 175 + giu_write(GIUINTSTATH, 1 << (GPIO_PIN_OF_IRQ(irq) - GIUINT_HIGH_OFFSET)); 172 176 } 173 177 174 - static void shutdown_giuint_high_irq(unsigned int irq) 178 + static void mask_giuint_high(unsigned int irq) 175 179 { 176 180 giu_clear(GIUINTENH, 1 << (GPIO_PIN_OF_IRQ(irq) - GIUINT_HIGH_OFFSET)); 177 181 } 178 182 179 - static void enable_giuint_high_irq(unsigned int irq) 180 - { 181 - giu_set(GIUINTENH, 1 << (GPIO_PIN_OF_IRQ(irq) - GIUINT_HIGH_OFFSET)); 182 - } 183 - 184 - #define disable_giuint_high_irq shutdown_giuint_high_irq 185 - 186 - static void ack_giuint_high_irq(unsigned int irq) 183 + static void mask_ack_giuint_high(unsigned int irq) 187 184 { 188 185 unsigned int pin; 189 186 ··· 176 205 giu_write(GIUINTSTATH, 1 << pin); 177 206 } 178 207 179 - static void end_giuint_high_irq(unsigned int irq) 208 + static void unmask_giuint_high(unsigned int irq) 180 209 { 181 - if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) 182 - giu_set(GIUINTENH, 1 << (GPIO_PIN_OF_IRQ(irq) - GIUINT_HIGH_OFFSET)); 210 + giu_set(GIUINTENH, 1 << (GPIO_PIN_OF_IRQ(irq) - GIUINT_HIGH_OFFSET)); 183 211 } 184 212 185 - static struct hw_interrupt_type giuint_high_irq_type = { 186 - .typename = "GIUINTH", 187 - .startup = startup_giuint_high_irq, 188 - .shutdown = shutdown_giuint_high_irq, 189 - .enable = enable_giuint_high_irq, 190 - .disable = disable_giuint_high_irq, 191 - .ack = ack_giuint_high_irq, 192 - .end = end_giuint_high_irq, 213 + static struct irq_chip giuint_high_irq_chip = { 214 + .name = "GIUINTH", 215 + .ack = ack_giuint_high, 216 + .mask = mask_giuint_high, 217 + .mask_ack = mask_ack_giuint_high, 218 + .unmask = unmask_giuint_high, 193 219 }; 194 220 195 221 static int giu_get_irq(unsigned int irq) ··· 250 282 break; 251 283 } 252 284 } 285 + set_irq_chip_and_handler(GIU_IRQ(pin), 286 + &giuint_low_irq_chip, 287 + handle_edge_irq); 253 288 } else { 254 289 giu_clear(GIUINTTYPL, mask); 255 290 giu_clear(GIUINTHTSELL, mask); 291 + set_irq_chip_and_handler(GIU_IRQ(pin), 292 + &giuint_low_irq_chip, 293 + handle_level_irq); 256 294 } 257 295 giu_write(GIUINTSTATL, mask); 258 296 } else if (pin < GIUINT_HIGH_MAX) { ··· 285 311 break; 286 312 } 287 313 } 314 + set_irq_chip_and_handler(GIU_IRQ(pin), 315 + &giuint_high_irq_chip, 316 + handle_edge_irq); 288 317 } else { 289 318 giu_clear(GIUINTTYPH, mask); 290 319 giu_clear(GIUINTHTSELH, mask); 320 + set_irq_chip_and_handler(GIU_IRQ(pin), 321 + &giuint_high_irq_chip, 322 + handle_level_irq); 291 323 } 292 324 giu_write(GIUINTSTATH, mask); 293 325 } ··· 597 617 static int __devinit giu_probe(struct platform_device *dev) 598 618 { 599 619 unsigned long start, size, flags = 0; 600 - unsigned int nr_pins = 0; 620 + unsigned int nr_pins = 0, trigger, i, pin; 601 621 struct resource *res1, *res2 = NULL; 602 622 void *base; 603 - int retval, i; 623 + struct irq_chip *chip; 624 + int retval; 604 625 605 626 switch (current_cpu_data.cputype) { 606 627 case CPU_VR4111: ··· 669 688 giu_write(GIUINTENL, 0); 670 689 giu_write(GIUINTENH, 0); 671 690 691 + trigger = giu_read(GIUINTTYPH) << 16; 692 + trigger |= giu_read(GIUINTTYPL); 672 693 for (i = GIU_IRQ_BASE; i <= GIU_IRQ_LAST; i++) { 673 - if (i < GIU_IRQ(GIUINT_HIGH_OFFSET)) 674 - irq_desc[i].chip = &giuint_low_irq_type; 694 + pin = GPIO_PIN_OF_IRQ(i); 695 + if (pin < GIUINT_HIGH_OFFSET) 696 + chip = &giuint_low_irq_chip; 675 697 else 676 - irq_desc[i].chip = &giuint_high_irq_type; 698 + chip = &giuint_high_irq_chip; 699 + 700 + if (trigger & (1 << pin)) 701 + set_irq_chip_and_handler(i, chip, handle_edge_irq); 702 + else 703 + set_irq_chip_and_handler(i, chip, handle_level_irq); 704 + 677 705 } 678 706 679 707 return cascade_irq(GIUINT_IRQ, giu_get_irq);
+22
include/asm-mips/irqflags.h
··· 15 15 16 16 #include <asm/hazards.h> 17 17 18 + /* 19 + * CONFIG_MIPS_MT_SMTC_INSTANT_REPLAY does prompt replay of deferred IPIs, 20 + * at the cost of branch and call overhead on each local_irq_restore() 21 + */ 22 + 23 + #ifdef CONFIG_MIPS_MT_SMTC_INSTANT_REPLAY 24 + 25 + extern void smtc_ipi_replay(void); 26 + 27 + #define irq_restore_epilog(flags) \ 28 + do { \ 29 + if (!(flags & 0x0400)) \ 30 + smtc_ipi_replay(); \ 31 + } while (0) 32 + 33 + #else 34 + 35 + #define irq_restore_epilog(ignore) do { } while (0) 36 + 37 + #endif /* CONFIG_MIPS_MT_SMTC_INSTANT_REPLAY */ 38 + 18 39 __asm__ ( 19 40 " .macro raw_local_irq_enable \n" 20 41 " .set push \n" ··· 214 193 : "=r" (__tmp1) \ 215 194 : "0" (flags) \ 216 195 : "memory"); \ 196 + irq_restore_epilog(flags); \ 217 197 } while(0) 218 198 219 199 static inline int raw_irqs_disabled_flags(unsigned long flags)