diff options
author | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-01-23 14:19:32 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-01-23 14:19:32 -0500 |
commit | d227e87e6c939c6071def92bc7691ad774c733ff (patch) | |
tree | 31fbc74974da765322b26de321e0b33f2f7e1478 /arch | |
parent | f66d45e99eb7ca91822c3e3f6d7a98843c9626cb (diff) | |
parent | 364ca8a897eadb2f0e76b7f0ffe94168f6d83d66 (diff) |
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.
Diffstat (limited to 'arch')
-rw-r--r-- | arch/mips/Kconfig | 14 | ||||
-rw-r--r-- | arch/mips/kernel/smtc.c | 54 | ||||
-rw-r--r-- | arch/mips/vr41xx/common/irq.c | 12 |
3 files changed, 56 insertions, 24 deletions
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index fd2ff0698a85..bbd386f572d9 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig | |||
@@ -1568,6 +1568,20 @@ config MIPS_MT_FPAFF | |||
1568 | depends on MIPS_MT | 1568 | depends on MIPS_MT |
1569 | default y | 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 | config MIPS_VPE_LOADER_TOM | 1585 | config MIPS_VPE_LOADER_TOM |
1572 | bool "Load VPE program into memory hidden from linux" | 1586 | bool "Load VPE program into memory hidden from linux" |
1573 | depends on MIPS_VPE_LOADER | 1587 | depends on MIPS_VPE_LOADER |
diff --git a/arch/mips/kernel/smtc.c b/arch/mips/kernel/smtc.c index a8b387197d5b..44238ab2fc99 100644 --- a/arch/mips/kernel/smtc.c +++ b/arch/mips/kernel/smtc.c | |||
@@ -1017,6 +1017,33 @@ void setup_cross_vpe_interrupts(void) | |||
1017 | * SMTC-specific hacks invoked from elsewhere in the kernel. | 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 | void smtc_idle_loop_hook(void) | 1047 | void smtc_idle_loop_hook(void) |
1021 | { | 1048 | { |
1022 | #ifdef SMTC_IDLE_HOOK_DEBUG | 1049 | #ifdef SMTC_IDLE_HOOK_DEBUG |
@@ -1113,29 +1140,14 @@ void smtc_idle_loop_hook(void) | |||
1113 | if (pdb_msg != &id_ho_db_msg[0]) | 1140 | if (pdb_msg != &id_ho_db_msg[0]) |
1114 | printk("CPU%d: %s", smp_processor_id(), id_ho_db_msg); | 1141 | printk("CPU%d: %s", smp_processor_id(), id_ho_db_msg); |
1115 | #endif /* SMTC_IDLE_HOOK_DEBUG */ | 1142 | #endif /* SMTC_IDLE_HOOK_DEBUG */ |
1143 | |||
1116 | /* | 1144 | /* |
1117 | * To the extent that we've ever turned interrupts off, | 1145 | * Replay any accumulated deferred IPIs. If "Instant Replay" |
1118 | * we may have accumulated deferred IPIs. This is subtle. | 1146 | * is in use, there should never be any. |
1119 | * If we use the smtc_ipi_qdepth() macro, we'll get an | ||
1120 | * exact number - but we'll also disable interrupts | ||
1121 | * and create a window of failure where a new IPI gets | ||
1122 | * queued after we test the depth but before we re-enable | ||
1123 | * interrupts. So long as IXMT never gets set, however, | ||
1124 | * we should be OK: If we pick up something and dispatch | ||
1125 | * it here, that's great. If we see nothing, but concurrent | ||
1126 | * with this operation, another TC sends us an IPI, IXMT | ||
1127 | * is clear, and we'll handle it as a real pseudo-interrupt | ||
1128 | * and not a pseudo-pseudo interrupt. | ||
1129 | */ | 1147 | */ |
1130 | if (IPIQ[smp_processor_id()].depth > 0) { | 1148 | #ifndef CONFIG_MIPS_MT_SMTC_INSTANT_REPLAY |
1131 | struct smtc_ipi *pipi; | 1149 | smtc_ipi_replay(); |
1132 | extern void self_ipi(struct smtc_ipi *); | 1150 | #endif /* CONFIG_MIPS_MT_SMTC_INSTANT_REPLAY */ |
1133 | |||
1134 | if ((pipi = smtc_ipi_dq(&IPIQ[smp_processor_id()])) != NULL) { | ||
1135 | self_ipi(pipi); | ||
1136 | smtc_cpu_stats[smp_processor_id()].selfipis++; | ||
1137 | } | ||
1138 | } | ||
1139 | } | 1151 | } |
1140 | 1152 | ||
1141 | void smtc_soft_dump(void) | 1153 | void smtc_soft_dump(void) |
diff --git a/arch/mips/vr41xx/common/irq.c b/arch/mips/vr41xx/common/irq.c index 397ba94cd7ec..16decf4ac2f4 100644 --- a/arch/mips/vr41xx/common/irq.c +++ b/arch/mips/vr41xx/common/irq.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * Interrupt handing routines for NEC VR4100 series. | 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 | * This program is free software; you can redistribute it and/or modify | 6 | * This program is free software; you can redistribute it and/or modify |
7 | * it under the terms of the GNU General Public License as published by | 7 | * it under the terms of the GNU General Public License as published by |
@@ -73,13 +73,19 @@ static void irq_dispatch(unsigned int irq) | |||
73 | if (cascade->get_irq != NULL) { | 73 | if (cascade->get_irq != NULL) { |
74 | unsigned int source_irq = irq; | 74 | unsigned int source_irq = irq; |
75 | desc = irq_desc + source_irq; | 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 | irq = cascade->get_irq(irq); | 82 | irq = cascade->get_irq(irq); |
78 | if (irq < 0) | 83 | if (irq < 0) |
79 | atomic_inc(&irq_err_count); | 84 | atomic_inc(&irq_err_count); |
80 | else | 85 | else |
81 | irq_dispatch(irq); | 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 | } else | 89 | } else |
84 | do_IRQ(irq); | 90 | do_IRQ(irq); |
85 | } | 91 | } |