aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authoroftedal <oftedal@gmail.com>2011-06-01 06:43:50 -0400
committerDavid S. Miller <davem@davemloft.net>2011-06-07 19:06:32 -0400
commit5fba17084e5d1b00bf24e17b2b580cfa7705e7be (patch)
tree522a070938752ceb822ce9b6b270df6bf7e6cfde /arch
parent8c47f8d07e16034dfbf736bb4478809aba8a53f1 (diff)
Restructure sun4d_build_device_irq so that timer interrupts can be allocated
sun4d_build_device_irq was called without a valid platform_device when the system timer was initialized on sun4d systems. This caused a NULL pointer crash. Josip Rodin suggested that the current sun4d_build_device_irq should be split into two functions. So that the timer initialization could skip the slot and sbus interface detection code in sun4d_build_device_irq, as this does not make sence due to the timer interrupts not being generated from a device located on sbus. Signed-off-by: Kjetil Oftedal <oftedal@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'arch')
-rw-r--r--arch/sparc/kernel/sun4d_irq.c78
1 files changed, 54 insertions, 24 deletions
diff --git a/arch/sparc/kernel/sun4d_irq.c b/arch/sparc/kernel/sun4d_irq.c
index a9ea60eb2c10..487c1bb374f5 100644
--- a/arch/sparc/kernel/sun4d_irq.c
+++ b/arch/sparc/kernel/sun4d_irq.c
@@ -299,19 +299,53 @@ static void __init sun4d_load_profile_irqs(void)
299 } 299 }
300} 300}
301 301
302unsigned int _sun4d_build_device_irq(unsigned int real_irq,
303 unsigned int pil,
304 unsigned int board)
305{
306 struct sun4d_handler_data *handler_data;
307 unsigned int irq;
308
309 irq = irq_alloc(real_irq, pil);
310 if (irq == 0) {
311 prom_printf("IRQ: allocate for %d %d %d failed\n",
312 real_irq, pil, board);
313 goto err_out;
314 }
315
316 handler_data = irq_get_handler_data(irq);
317 if (unlikely(handler_data))
318 goto err_out;
319
320 handler_data = kzalloc(sizeof(struct sun4d_handler_data), GFP_ATOMIC);
321 if (unlikely(!handler_data)) {
322 prom_printf("IRQ: kzalloc(sun4d_handler_data) failed.\n");
323 prom_halt();
324 }
325 handler_data->cpuid = board_to_cpu[board];
326 handler_data->real_irq = real_irq;
327 irq_set_chip_and_handler_name(irq, &sun4d_irq,
328 handle_level_irq, "level");
329 irq_set_handler_data(irq, handler_data);
330
331err_out:
332 return irq;
333}
334
335
336
302unsigned int sun4d_build_device_irq(struct platform_device *op, 337unsigned int sun4d_build_device_irq(struct platform_device *op,
303 unsigned int real_irq) 338 unsigned int real_irq)
304{ 339{
305 struct device_node *dp = op->dev.of_node; 340 struct device_node *dp = op->dev.of_node;
306 struct device_node *io_unit, *sbi = dp->parent; 341 struct device_node *io_unit, *sbi = dp->parent;
307 const struct linux_prom_registers *regs; 342 const struct linux_prom_registers *regs;
308 struct sun4d_handler_data *handler_data;
309 unsigned int pil; 343 unsigned int pil;
310 unsigned int irq; 344 unsigned int irq;
311 int board, slot; 345 int board, slot;
312 int sbusl; 346 int sbusl;
313 347
314 irq = 0; 348 irq = real_irq;
315 while (sbi) { 349 while (sbi) {
316 if (!strcmp(sbi->name, "sbi")) 350 if (!strcmp(sbi->name, "sbi"))
317 break; 351 break;
@@ -348,29 +382,17 @@ unsigned int sun4d_build_device_irq(struct platform_device *op,
348 else 382 else
349 pil = real_irq; 383 pil = real_irq;
350 384
351 irq = irq_alloc(real_irq, pil); 385 irq = _sun4d_build_device_irq(real_irq, pil, board);
352 if (irq == 0)
353 goto err_out;
354
355 handler_data = irq_get_handler_data(irq);
356 if (unlikely(handler_data))
357 goto err_out;
358
359 handler_data = kzalloc(sizeof(struct sun4d_handler_data), GFP_ATOMIC);
360 if (unlikely(!handler_data)) {
361 prom_printf("IRQ: kzalloc(sun4d_handler_data) failed.\n");
362 prom_halt();
363 }
364 handler_data->cpuid = board_to_cpu[board];
365 handler_data->real_irq = real_irq;
366 irq_set_chip_and_handler_name(irq, &sun4d_irq,
367 handle_level_irq, "level");
368 irq_set_handler_data(irq, handler_data);
369
370err_out: 386err_out:
371 return real_irq; 387 return irq;
372} 388}
373 389
390unsigned int sun4d_build_timer_irq(unsigned int board, unsigned int real_irq)
391{
392 return _sun4d_build_device_irq(real_irq, real_irq, board);
393}
394
395
374static void __init sun4d_fixup_trap_table(void) 396static void __init sun4d_fixup_trap_table(void)
375{ 397{
376#ifdef CONFIG_SMP 398#ifdef CONFIG_SMP
@@ -402,6 +424,7 @@ static void __init sun4d_init_timers(irq_handler_t counter_fn)
402 unsigned int irq; 424 unsigned int irq;
403 const u32 *reg; 425 const u32 *reg;
404 int err; 426 int err;
427 int board;
405 428
406 dp = of_find_node_by_name(NULL, "cpu-unit"); 429 dp = of_find_node_by_name(NULL, "cpu-unit");
407 if (!dp) { 430 if (!dp) {
@@ -414,12 +437,19 @@ static void __init sun4d_init_timers(irq_handler_t counter_fn)
414 * bootbus. 437 * bootbus.
415 */ 438 */
416 reg = of_get_property(dp, "reg", NULL); 439 reg = of_get_property(dp, "reg", NULL);
417 of_node_put(dp);
418 if (!reg) { 440 if (!reg) {
419 prom_printf("sun4d_init_timers: No reg property\n"); 441 prom_printf("sun4d_init_timers: No reg property\n");
420 prom_halt(); 442 prom_halt();
421 } 443 }
422 444
445 board = of_getintprop_default(dp, "board#", -1);
446 if (board == -1) {
447 prom_printf("sun4d_init_timers: No board# property on cpu-unit\n");
448 prom_halt();
449 }
450
451 of_node_put(dp);
452
423 res.start = reg[1]; 453 res.start = reg[1];
424 res.end = reg[2] - 1; 454 res.end = reg[2] - 1;
425 res.flags = reg[0] & 0xff; 455 res.flags = reg[0] & 0xff;
@@ -434,7 +464,7 @@ static void __init sun4d_init_timers(irq_handler_t counter_fn)
434 464
435 master_l10_counter = &sun4d_timers->l10_cur_count; 465 master_l10_counter = &sun4d_timers->l10_cur_count;
436 466
437 irq = sun4d_build_device_irq(NULL, SUN4D_TIMER_IRQ); 467 irq = sun4d_build_timer_irq(board, SUN4D_TIMER_IRQ);
438 err = request_irq(irq, counter_fn, IRQF_TIMER, "timer", NULL); 468 err = request_irq(irq, counter_fn, IRQF_TIMER, "timer", NULL);
439 if (err) { 469 if (err) {
440 prom_printf("sun4d_init_timers: request_irq() failed with %d\n", 470 prom_printf("sun4d_init_timers: request_irq() failed with %d\n",