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

[MIPS] time: SMP/NUMA-proofing of IP27 HUB RT timer code.

Signed-off-by: Ralf Baechle <ralf@linux-mips.org>

+81 -73
+1 -1
arch/mips/sgi-ip27/ip27-init.c
··· 110 110 } 111 111 } 112 112 113 - void __init per_cpu_init(void) 113 + void __cpuinit per_cpu_init(void) 114 114 { 115 115 int cpu = smp_processor_id(); 116 116 int slice = LOCAL_HUB_L(PI_CPU_NUM);
+80 -72
arch/mips/sgi-ip27/ip27-timer.c
··· 111 111 return mktime(year, month, date, hour, min, sec); 112 112 } 113 113 114 - static int rt_set_next_event(unsigned long delta, 115 - struct clock_event_device *evt) 116 - { 117 - unsigned int cpu = smp_processor_id(); 118 - int slice = cputoslice(cpu) == 0; 119 - unsigned long cnt; 120 - 121 - cnt = LOCAL_HUB_L(PI_RT_COUNT); 122 - cnt += delta; 123 - LOCAL_HUB_S(slice ? PI_RT_COMPARE_A : PI_RT_COMPARE_B, cnt); 124 - 125 - return LOCAL_HUB_L(PI_RT_COUNT) >= cnt ? -ETIME : 0; 126 - } 127 - 128 - static void rt_set_mode(enum clock_event_mode mode, 129 - struct clock_event_device *evt) 130 - { 131 - switch (mode) { 132 - case CLOCK_EVT_MODE_PERIODIC: 133 - /* The only mode supported */ 134 - break; 135 - 136 - case CLOCK_EVT_MODE_UNUSED: 137 - case CLOCK_EVT_MODE_SHUTDOWN: 138 - case CLOCK_EVT_MODE_ONESHOT: 139 - case CLOCK_EVT_MODE_RESUME: 140 - /* Nothing to do */ 141 - break; 142 - } 143 - } 144 - 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 114 static void enable_rt_irq(unsigned int irq) 155 115 { 156 116 } ··· 128 168 .eoi = enable_rt_irq, 129 169 }; 130 170 171 + static int rt_next_event(unsigned long delta, struct clock_event_device *evt) 172 + { 173 + unsigned int cpu = smp_processor_id(); 174 + int slice = cputoslice(cpu) == 0; 175 + unsigned long cnt; 176 + 177 + cnt = LOCAL_HUB_L(PI_RT_COUNT); 178 + cnt += delta; 179 + LOCAL_HUB_S(slice ? PI_RT_COMPARE_A : PI_RT_COMPARE_B, cnt); 180 + 181 + return LOCAL_HUB_L(PI_RT_COUNT) >= cnt ? -ETIME : 0; 182 + } 183 + 184 + static void rt_set_mode(enum clock_event_mode mode, 185 + struct clock_event_device *evt) 186 + { 187 + switch (mode) { 188 + case CLOCK_EVT_MODE_ONESHOT: 189 + /* The only mode supported */ 190 + break; 191 + 192 + case CLOCK_EVT_MODE_PERIODIC: 193 + case CLOCK_EVT_MODE_UNUSED: 194 + case CLOCK_EVT_MODE_SHUTDOWN: 195 + case CLOCK_EVT_MODE_RESUME: 196 + /* Nothing to do */ 197 + break; 198 + } 199 + } 200 + 131 201 unsigned int rt_timer_irq; 132 202 133 - static irqreturn_t ip27_rt_timer_interrupt(int irq, void *dev_id) 203 + static irqreturn_t hub_rt_counter_handler(int irq, void *dev_id) 134 204 { 135 - struct clock_event_device *cd = &rt_clock_event_device; 205 + struct clock_event_device *cd = dev_id; 136 206 unsigned int cpu = smp_processor_id(); 137 207 int slice = cputoslice(cpu) == 0; 138 208 ··· 172 182 return IRQ_HANDLED; 173 183 } 174 184 175 - static struct irqaction rt_irqaction = { 176 - .handler = (irq_handler_t) ip27_rt_timer_interrupt, 177 - .flags = IRQF_DISABLED, 178 - .mask = CPU_MASK_NONE, 179 - .name = "timer" 185 + struct irqaction hub_rt_irqaction = { 186 + .handler = hub_rt_counter_handler, 187 + .flags = IRQF_DISABLED | IRQF_PERCPU, 188 + .name = "hub-rt", 180 189 }; 181 190 182 191 /* ··· 189 200 #define NSEC_PER_CYCLE 800 190 201 #define CYCLES_PER_SEC (NSEC_PER_SEC / NSEC_PER_CYCLE) 191 202 192 - static void __init ip27_rt_clock_event_init(void) 203 + static DEFINE_PER_CPU(struct clock_event_device, hub_rt_clockevent); 204 + static DEFINE_PER_CPU(char [11], hub_rt_name); 205 + 206 + static void __cpuinit hub_rt_clock_event_init(void) 193 207 { 194 - struct clock_event_device *cd = &rt_clock_event_device; 195 208 unsigned int cpu = smp_processor_id(); 196 - int irq = allocate_irqno(); 209 + struct clock_event_device *cd = &per_cpu(hub_rt_clockevent, cpu); 210 + unsigned char *name = per_cpu(hub_rt_name, cpu); 211 + int irq = rt_timer_irq; 197 212 198 - if (irq < 0) 199 - panic("Can't allocate interrupt number for timer interrupt"); 200 - 201 - rt_timer_irq = irq; 202 - 213 + sprintf(name, "hub-rt %d", cpu); 214 + cd->name = "HUB-RT", 215 + cd->features = CLOCK_EVT_FEAT_ONESHOT, 216 + clockevent_set_clock(cd, CYCLES_PER_SEC); 217 + cd->max_delta_ns = clockevent_delta2ns(0xfffffffffffff, cd); 218 + cd->min_delta_ns = clockevent_delta2ns(0x300, cd); 219 + cd->rating = 200, 203 220 cd->irq = irq, 204 221 cd->cpumask = cpumask_of_cpu(cpu), 205 - 206 - /* 207 - * Calculate the min / max delta 208 - */ 209 - cd->mult = 210 - div_sc((unsigned long) CYCLES_PER_SEC, NSEC_PER_SEC, 32); 211 - cd->shift = 32; 212 - cd->max_delta_ns = clockevent_delta2ns(0x7fffffff, cd); 213 - cd->min_delta_ns = clockevent_delta2ns(0x300, cd); 222 + cd->rating = 300, 223 + cd->set_next_event = rt_next_event, 224 + cd->set_mode = rt_set_mode, 214 225 clockevents_register_device(cd); 226 + } 227 + 228 + static void __init hub_rt_clock_event_global_init(void) 229 + { 230 + unsigned int irq; 231 + 232 + do { 233 + smp_wmb(); 234 + irq = rt_timer_irq; 235 + if (irq) 236 + break; 237 + 238 + irq = allocate_irqno(); 239 + if (irq < 0) 240 + panic("Allocation of irq number for timer failed"); 241 + } while (xchg(&rt_timer_irq, irq)); 215 242 216 243 set_irq_chip_and_handler(irq, &rt_irq_type, handle_percpu_irq); 217 - setup_irq(irq, &rt_irqaction); 244 + setup_irq(irq, &hub_rt_irqaction); 218 245 } 219 246 220 247 static cycle_t hub_rt_read(void) ··· 238 233 return REMOTE_HUB_L(cputonasid(0), PI_RT_COUNT); 239 234 } 240 235 241 - struct clocksource ht_rt_clocksource = { 236 + struct clocksource hub_rt_clocksource = { 242 237 .name = "HUB-RT", 243 238 .rating = 200, 244 239 .read = hub_rt_read, 245 240 .mask = CLOCKSOURCE_MASK(52), 246 - .shift = 32, 247 241 .flags = CLOCK_SOURCE_IS_CONTINUOUS, 248 242 }; 249 243 250 - static void __init ip27_rt_clocksource_init(void) 244 + static void __init hub_rt_clocksource_init(void) 251 245 { 252 - clocksource_register(&ht_rt_clocksource); 246 + struct clocksource *cs = &hub_rt_clocksource; 247 + 248 + clocksource_set_clock(cs, CYCLES_PER_SEC); 249 + clocksource_register(cs); 253 250 } 254 251 255 252 void __init plat_time_init(void) 256 253 { 257 - ip27_rt_clock_event_init(); 258 - ip27_rt_clocksource_init(); 254 + hub_rt_clocksource_init(); 255 + hub_rt_clock_event_global_init(); 259 256 } 260 257 261 - void __init cpu_time_init(void) 258 + void __cpuinit cpu_time_init(void) 262 259 { 263 260 lboard_t *board; 264 261 klcpu_t *cpu; ··· 278 271 279 272 printk("CPU %d clock is %dMHz.\n", smp_processor_id(), cpu->cpu_speed); 280 273 274 + hub_rt_clock_event_init(); 281 275 set_c0_status(SRB_TIMOCLK); 282 276 } 283 277