diff options
author | Ralf Baechle <ralf@linux-mips.org> | 2007-10-22 05:34:13 -0400 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2007-10-22 17:09:00 -0400 |
commit | 06d428d719dece96c01532b62df4140f4e69a308 (patch) | |
tree | 2e10ca921862366b515404697206f1d0ca68dd56 /arch/mips | |
parent | 508a775a3c9c6c3f952338f6722ea8bc92899962 (diff) |
[MIPS] time: SMP/NUMA-proofing of IP27 HUB RT timer code.
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
Diffstat (limited to 'arch/mips')
-rw-r--r-- | arch/mips/sgi-ip27/ip27-init.c | 2 | ||||
-rw-r--r-- | arch/mips/sgi-ip27/ip27-timer.c | 134 |
2 files changed, 72 insertions, 64 deletions
diff --git a/arch/mips/sgi-ip27/ip27-init.c b/arch/mips/sgi-ip27/ip27-init.c index 681b593071cb..3305fa9ae66d 100644 --- a/arch/mips/sgi-ip27/ip27-init.c +++ b/arch/mips/sgi-ip27/ip27-init.c | |||
@@ -110,7 +110,7 @@ static void __init per_hub_init(cnodeid_t cnode) | |||
110 | } | 110 | } |
111 | } | 111 | } |
112 | 112 | ||
113 | void __init per_cpu_init(void) | 113 | void __cpuinit per_cpu_init(void) |
114 | { | 114 | { |
115 | int cpu = smp_processor_id(); | 115 | int cpu = smp_processor_id(); |
116 | int slice = LOCAL_HUB_L(PI_CPU_NUM); | 116 | int slice = LOCAL_HUB_L(PI_CPU_NUM); |
diff --git a/arch/mips/sgi-ip27/ip27-timer.c b/arch/mips/sgi-ip27/ip27-timer.c index d467bf4f6c3f..f5dccf01da11 100644 --- a/arch/mips/sgi-ip27/ip27-timer.c +++ b/arch/mips/sgi-ip27/ip27-timer.c | |||
@@ -111,8 +111,24 @@ unsigned long read_persistent_clock(void) | |||
111 | return mktime(year, month, date, hour, min, sec); | 111 | return mktime(year, month, date, hour, min, sec); |
112 | } | 112 | } |
113 | 113 | ||
114 | static int rt_set_next_event(unsigned long delta, | 114 | static void enable_rt_irq(unsigned int irq) |
115 | struct clock_event_device *evt) | 115 | { |
116 | } | ||
117 | |||
118 | static void disable_rt_irq(unsigned int irq) | ||
119 | { | ||
120 | } | ||
121 | |||
122 | static struct irq_chip rt_irq_type = { | ||
123 | .name = "SN HUB RT timer", | ||
124 | .ack = disable_rt_irq, | ||
125 | .mask = disable_rt_irq, | ||
126 | .mask_ack = disable_rt_irq, | ||
127 | .unmask = enable_rt_irq, | ||
128 | .eoi = enable_rt_irq, | ||
129 | }; | ||
130 | |||
131 | static int rt_next_event(unsigned long delta, struct clock_event_device *evt) | ||
116 | { | 132 | { |
117 | unsigned int cpu = smp_processor_id(); | 133 | unsigned int cpu = smp_processor_id(); |
118 | int slice = cputoslice(cpu) == 0; | 134 | int slice = cputoslice(cpu) == 0; |
@@ -129,50 +145,24 @@ static void rt_set_mode(enum clock_event_mode mode, | |||
129 | struct clock_event_device *evt) | 145 | struct clock_event_device *evt) |
130 | { | 146 | { |
131 | switch (mode) { | 147 | switch (mode) { |
132 | case CLOCK_EVT_MODE_PERIODIC: | 148 | case CLOCK_EVT_MODE_ONESHOT: |
133 | /* The only mode supported */ | 149 | /* The only mode supported */ |
134 | break; | 150 | break; |
135 | 151 | ||
152 | case CLOCK_EVT_MODE_PERIODIC: | ||
136 | case CLOCK_EVT_MODE_UNUSED: | 153 | case CLOCK_EVT_MODE_UNUSED: |
137 | case CLOCK_EVT_MODE_SHUTDOWN: | 154 | case CLOCK_EVT_MODE_SHUTDOWN: |
138 | case CLOCK_EVT_MODE_ONESHOT: | ||
139 | case CLOCK_EVT_MODE_RESUME: | 155 | case CLOCK_EVT_MODE_RESUME: |
140 | /* Nothing to do */ | 156 | /* Nothing to do */ |
141 | break; | 157 | break; |
142 | } | 158 | } |
143 | } | 159 | } |
144 | 160 | ||
145 | struct clock_event_device rt_clock_event_device = { | ||
146 | .name = "HUB-RT", | ||
147 | .features = CLOCK_EVT_FEAT_ONESHOT, | ||
148 | |||
149 | .rating = 300, | ||
150 | .set_next_event = rt_set_next_event, | ||
151 | .set_mode = rt_set_mode, | ||
152 | }; | ||
153 | |||
154 | static void enable_rt_irq(unsigned int irq) | ||
155 | { | ||
156 | } | ||
157 | |||
158 | static void disable_rt_irq(unsigned int irq) | ||
159 | { | ||
160 | } | ||
161 | |||
162 | static struct irq_chip rt_irq_type = { | ||
163 | .name = "SN HUB RT timer", | ||
164 | .ack = disable_rt_irq, | ||
165 | .mask = disable_rt_irq, | ||
166 | .mask_ack = disable_rt_irq, | ||
167 | .unmask = enable_rt_irq, | ||
168 | .eoi = enable_rt_irq, | ||
169 | }; | ||
170 | |||
171 | unsigned int rt_timer_irq; | 161 | unsigned int rt_timer_irq; |
172 | 162 | ||
173 | static irqreturn_t ip27_rt_timer_interrupt(int irq, void *dev_id) | 163 | static irqreturn_t hub_rt_counter_handler(int irq, void *dev_id) |
174 | { | 164 | { |
175 | struct clock_event_device *cd = &rt_clock_event_device; | 165 | struct clock_event_device *cd = dev_id; |
176 | unsigned int cpu = smp_processor_id(); | 166 | unsigned int cpu = smp_processor_id(); |
177 | int slice = cputoslice(cpu) == 0; | 167 | int slice = cputoslice(cpu) == 0; |
178 | 168 | ||
@@ -182,11 +172,10 @@ static irqreturn_t ip27_rt_timer_interrupt(int irq, void *dev_id) | |||
182 | return IRQ_HANDLED; | 172 | return IRQ_HANDLED; |
183 | } | 173 | } |
184 | 174 | ||
185 | static struct irqaction rt_irqaction = { | 175 | struct irqaction hub_rt_irqaction = { |
186 | .handler = (irq_handler_t) ip27_rt_timer_interrupt, | 176 | .handler = hub_rt_counter_handler, |
187 | .flags = IRQF_DISABLED, | 177 | .flags = IRQF_DISABLED | IRQF_PERCPU, |
188 | .mask = CPU_MASK_NONE, | 178 | .name = "hub-rt", |
189 | .name = "timer" | ||
190 | }; | 179 | }; |
191 | 180 | ||
192 | /* | 181 | /* |
@@ -200,32 +189,48 @@ static struct irqaction rt_irqaction = { | |||
200 | #define NSEC_PER_CYCLE 800 | 189 | #define NSEC_PER_CYCLE 800 |
201 | #define CYCLES_PER_SEC (NSEC_PER_SEC / NSEC_PER_CYCLE) | 190 | #define CYCLES_PER_SEC (NSEC_PER_SEC / NSEC_PER_CYCLE) |
202 | 191 | ||
203 | static void __init ip27_rt_clock_event_init(void) | 192 | static DEFINE_PER_CPU(struct clock_event_device, hub_rt_clockevent); |
193 | static DEFINE_PER_CPU(char [11], hub_rt_name); | ||
194 | |||
195 | static void __cpuinit hub_rt_clock_event_init(void) | ||
204 | { | 196 | { |
205 | struct clock_event_device *cd = &rt_clock_event_device; | ||
206 | unsigned int cpu = smp_processor_id(); | 197 | unsigned int cpu = smp_processor_id(); |
207 | int irq = allocate_irqno(); | 198 | struct clock_event_device *cd = &per_cpu(hub_rt_clockevent, cpu); |
208 | 199 | unsigned char *name = per_cpu(hub_rt_name, cpu); | |
209 | if (irq < 0) | 200 | int irq = rt_timer_irq; |
210 | panic("Can't allocate interrupt number for timer interrupt"); | 201 | |
211 | 202 | sprintf(name, "hub-rt %d", cpu); | |
212 | rt_timer_irq = irq; | 203 | cd->name = "HUB-RT", |
213 | 204 | cd->features = CLOCK_EVT_FEAT_ONESHOT, | |
205 | clockevent_set_clock(cd, CYCLES_PER_SEC); | ||
206 | cd->max_delta_ns = clockevent_delta2ns(0xfffffffffffff, cd); | ||
207 | cd->min_delta_ns = clockevent_delta2ns(0x300, cd); | ||
208 | cd->rating = 200, | ||
214 | cd->irq = irq, | 209 | cd->irq = irq, |
215 | cd->cpumask = cpumask_of_cpu(cpu), | 210 | cd->cpumask = cpumask_of_cpu(cpu), |
216 | 211 | cd->rating = 300, | |
217 | /* | 212 | cd->set_next_event = rt_next_event, |
218 | * Calculate the min / max delta | 213 | cd->set_mode = rt_set_mode, |
219 | */ | ||
220 | cd->mult = | ||
221 | div_sc((unsigned long) CYCLES_PER_SEC, NSEC_PER_SEC, 32); | ||
222 | cd->shift = 32; | ||
223 | cd->max_delta_ns = clockevent_delta2ns(0x7fffffff, cd); | ||
224 | cd->min_delta_ns = clockevent_delta2ns(0x300, cd); | ||
225 | clockevents_register_device(cd); | 214 | clockevents_register_device(cd); |
215 | } | ||
216 | |||
217 | static void __init hub_rt_clock_event_global_init(void) | ||
218 | { | ||
219 | unsigned int irq; | ||
220 | |||
221 | do { | ||
222 | smp_wmb(); | ||
223 | irq = rt_timer_irq; | ||
224 | if (irq) | ||
225 | break; | ||
226 | |||
227 | irq = allocate_irqno(); | ||
228 | if (irq < 0) | ||
229 | panic("Allocation of irq number for timer failed"); | ||
230 | } while (xchg(&rt_timer_irq, irq)); | ||
226 | 231 | ||
227 | set_irq_chip_and_handler(irq, &rt_irq_type, handle_percpu_irq); | 232 | set_irq_chip_and_handler(irq, &rt_irq_type, handle_percpu_irq); |
228 | setup_irq(irq, &rt_irqaction); | 233 | setup_irq(irq, &hub_rt_irqaction); |
229 | } | 234 | } |
230 | 235 | ||
231 | static cycle_t hub_rt_read(void) | 236 | static cycle_t hub_rt_read(void) |
@@ -233,27 +238,29 @@ static cycle_t hub_rt_read(void) | |||
233 | return REMOTE_HUB_L(cputonasid(0), PI_RT_COUNT); | 238 | return REMOTE_HUB_L(cputonasid(0), PI_RT_COUNT); |
234 | } | 239 | } |
235 | 240 | ||
236 | struct clocksource ht_rt_clocksource = { | 241 | struct clocksource hub_rt_clocksource = { |
237 | .name = "HUB-RT", | 242 | .name = "HUB-RT", |
238 | .rating = 200, | 243 | .rating = 200, |
239 | .read = hub_rt_read, | 244 | .read = hub_rt_read, |
240 | .mask = CLOCKSOURCE_MASK(52), | 245 | .mask = CLOCKSOURCE_MASK(52), |
241 | .shift = 32, | ||
242 | .flags = CLOCK_SOURCE_IS_CONTINUOUS, | 246 | .flags = CLOCK_SOURCE_IS_CONTINUOUS, |
243 | }; | 247 | }; |
244 | 248 | ||
245 | static void __init ip27_rt_clocksource_init(void) | 249 | static void __init hub_rt_clocksource_init(void) |
246 | { | 250 | { |
247 | clocksource_register(&ht_rt_clocksource); | 251 | struct clocksource *cs = &hub_rt_clocksource; |
252 | |||
253 | clocksource_set_clock(cs, CYCLES_PER_SEC); | ||
254 | clocksource_register(cs); | ||
248 | } | 255 | } |
249 | 256 | ||
250 | void __init plat_time_init(void) | 257 | void __init plat_time_init(void) |
251 | { | 258 | { |
252 | ip27_rt_clock_event_init(); | 259 | hub_rt_clocksource_init(); |
253 | ip27_rt_clocksource_init(); | 260 | hub_rt_clock_event_global_init(); |
254 | } | 261 | } |
255 | 262 | ||
256 | void __init cpu_time_init(void) | 263 | void __cpuinit cpu_time_init(void) |
257 | { | 264 | { |
258 | lboard_t *board; | 265 | lboard_t *board; |
259 | klcpu_t *cpu; | 266 | klcpu_t *cpu; |
@@ -271,6 +278,7 @@ void __init cpu_time_init(void) | |||
271 | 278 | ||
272 | printk("CPU %d clock is %dMHz.\n", smp_processor_id(), cpu->cpu_speed); | 279 | printk("CPU %d clock is %dMHz.\n", smp_processor_id(), cpu->cpu_speed); |
273 | 280 | ||
281 | hub_rt_clock_event_init(); | ||
274 | set_c0_status(SRB_TIMOCLK); | 282 | set_c0_status(SRB_TIMOCLK); |
275 | } | 283 | } |
276 | 284 | ||