aboutsummaryrefslogtreecommitdiffstats
path: root/arch/mips
diff options
context:
space:
mode:
Diffstat (limited to 'arch/mips')
-rw-r--r--arch/mips/mips-boards/generic/time.c57
1 files changed, 36 insertions, 21 deletions
diff --git a/arch/mips/mips-boards/generic/time.c b/arch/mips/mips-boards/generic/time.c
index 557bf961f36..de5798e1e01 100644
--- a/arch/mips/mips-boards/generic/time.c
+++ b/arch/mips/mips-boards/generic/time.c
@@ -92,10 +92,9 @@ extern int (*perf_irq)(struct pt_regs *regs);
92irqreturn_t mips_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) 92irqreturn_t mips_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
93{ 93{
94 int cpu = smp_processor_id(); 94 int cpu = smp_processor_id();
95 int r2 = cpu_has_mips_r2;
96 95
97#ifdef CONFIG_MIPS_MT_SMTC 96#ifdef CONFIG_MIPS_MT_SMTC
98 /* 97 /*
99 * In an SMTC system, one Count/Compare set exists per VPE. 98 * In an SMTC system, one Count/Compare set exists per VPE.
100 * Which TC within a VPE gets the interrupt is essentially 99 * Which TC within a VPE gets the interrupt is essentially
101 * random - we only know that it shouldn't be one with 100 * random - we only know that it shouldn't be one with
@@ -108,29 +107,46 @@ irqreturn_t mips_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
108 * the general MIPS timer_interrupt routine. 107 * the general MIPS timer_interrupt routine.
109 */ 108 */
110 109
110 int vpflags;
111
111 /* 112 /*
112 * DVPE is necessary so long as cross-VPE interrupts 113 * We could be here due to timer interrupt,
113 * are done via read-modify-write of Cause register. 114 * perf counter overflow, or both.
114 */ 115 */
115 int vpflags = dvpe(); 116 if (read_c0_cause() & (1 << 26))
116 write_c0_compare (read_c0_count() - 1); 117 perf_irq(regs);
117 clear_c0_cause(CPUCTR_IMASKBIT);
118 evpe(vpflags);
119
120 if (cpu_data[cpu].vpe_id == 0) {
121 timer_interrupt(irq, dev_id, regs);
122 scroll_display_message();
123 } else
124 write_c0_compare (read_c0_count() + ( mips_hpt_frequency/HZ));
125 smtc_timer_broadcast(cpu_data[cpu].vpe_id);
126 118
127 if (cpu != 0) 119 if (read_c0_cause() & (1 << 30)) {
120 /* If timer interrupt, make it de-assert */
121 write_c0_compare (read_c0_count() - 1);
128 /* 122 /*
129 * Other CPUs should do profiling and process accounting 123 * DVPE is necessary so long as cross-VPE interrupts
124 * are done via read-modify-write of Cause register.
130 */ 125 */
131 local_timer_interrupt(irq, dev_id, regs); 126 vpflags = dvpe();
132 127 clear_c0_cause(CPUCTR_IMASKBIT);
128 evpe(vpflags);
129 /*
130 * There are things we only want to do once per tick
131 * in an "MP" system. One TC of each VPE will take
132 * the actual timer interrupt. The others will get
133 * timer broadcast IPIs. We use whoever it is that takes
134 * the tick on VPE 0 to run the full timer_interrupt().
135 */
136 if (cpu_data[cpu].vpe_id == 0) {
137 timer_interrupt(irq, NULL, regs);
138 smtc_timer_broadcast(cpu_data[cpu].vpe_id);
139 scroll_display_message();
140 } else {
141 write_c0_compare(read_c0_count() +
142 (mips_hpt_frequency/HZ));
143 local_timer_interrupt(irq, dev_id, regs);
144 smtc_timer_broadcast(cpu_data[cpu].vpe_id);
145 }
146 }
133#else /* CONFIG_MIPS_MT_SMTC */ 147#else /* CONFIG_MIPS_MT_SMTC */
148 int r2 = cpu_has_mips_r2;
149
134 if (cpu == 0) { 150 if (cpu == 0) {
135 /* 151 /*
136 * CPU 0 handles the global timer interrupt job and process 152 * CPU 0 handles the global timer interrupt job and process
@@ -161,9 +177,8 @@ irqreturn_t mips_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
161 */ 177 */
162 local_timer_interrupt(irq, dev_id, regs); 178 local_timer_interrupt(irq, dev_id, regs);
163 } 179 }
164#endif /* CONFIG_MIPS_MT_SMTC */
165
166out: 180out:
181#endif /* CONFIG_MIPS_MT_SMTC */
167 return IRQ_HANDLED; 182 return IRQ_HANDLED;
168} 183}
169 184