On Mon, May 23, 2011 at 02:59:49PM -0400, daniel@xxxxxxxxxxx wrote: > First of all you're right calling will NULL just can't be good. The > LEON genirq build_device_irq has been split into two separate parts, > one that takes a platofrm device and one that works with "real_irq" > just because of this reason. Even though the OpenBoot PROM shuold > deliver all information, I think we should be able to bypass it when > needed, like in this case. > > Secondly, the return value from sun4d_build_device_irq() is a > real_irq, and that is what causes the problem I guess. Try make it > return the virtual IRQ instead, and give that VIRQ to request_irq > instead. Yeah, something like this (completely untested): diff --git a/arch/sparc/kernel/sun4d_irq.c b/arch/sparc/kernel/sun4d_irq.c index a9ea60e..c18c5f2 100644 --- a/arch/sparc/kernel/sun4d_irq.c +++ b/arch/sparc/kernel/sun4d_irq.c @@ -305,7 +305,6 @@ unsigned int sun4d_build_device_irq(struct platform_device *op, struct device_node *dp = op->dev.of_node; struct device_node *io_unit, *sbi = dp->parent; const struct linux_prom_registers *regs; - struct sun4d_handler_data *handler_data; unsigned int pil; unsigned int irq; int board, slot; @@ -348,6 +347,19 @@ unsigned int sun4d_build_device_irq(struct platform_device *op, else pil = real_irq; + return _sun4d_build_device_irq(real_irq, pil, board); + +err_out: + return irq; +} + +unsigned int _sun4d_build_device_irq(unsigned int real_irq, + unsigned int pil, + unsigned int board) +{ + struct sun4d_handler_data *handler_data; + unsigned int irq; + irq = irq_alloc(real_irq, pil); if (irq == 0) goto err_out; @@ -368,7 +380,12 @@ unsigned int sun4d_build_device_irq(struct platform_device *op, irq_set_handler_data(irq, handler_data); err_out: - return real_irq; + return irq; +} + +unsigned int sun4d_build_timer_irq(unsigned int board, unsigned int real_irq) +{ + return _sun4d_build_device_irq(real_irq, real_irq, board); } static void __init sun4d_fixup_trap_table(void) @@ -402,6 +419,7 @@ static void __init sun4d_init_timers(irq_handler_t counter_fn) unsigned int irq; const u32 *reg; int err; + int board; dp = of_find_node_by_name(NULL, "cpu-unit"); if (!dp) { @@ -414,12 +432,19 @@ static void __init sun4d_init_timers(irq_handler_t counter_fn) * bootbus. */ reg = of_get_property(dp, "reg", NULL); - of_node_put(dp); if (!reg) { prom_printf("sun4d_init_timers: No reg property\n"); prom_halt(); } + board = of_getintprop_default(dp, "board#", 0); + if (!board) { + prom_printf("sun4d_init_timers: No board# property on cpu-unit\n"); + prom_halt(); + } + + of_node_put(dp); + res.start = reg[1]; res.end = reg[2] - 1; res.flags = reg[0] & 0xff; @@ -434,7 +459,7 @@ static void __init sun4d_init_timers(irq_handler_t counter_fn) master_l10_counter = &sun4d_timers->l10_cur_count; - irq = sun4d_build_device_irq(NULL, SUN4D_TIMER_IRQ); + irq = sun4d_build_timer_irq(board, SUN4D_TIMER_IRQ); err = request_irq(irq, counter_fn, IRQF_TIMER, "timer", NULL); if (err) { prom_printf("sun4d_init_timers: request_irq() failed with %d\n", Passing around the 'board' property of 'cpu-unit' looks like it should be done because the same thing is used to seed board_to_cpu[]. http://git.kernel.org/?p=linux/kernel/git/davem/prtconfs.git;a=blob;f=ss1000;h=f420dc005d6939b837134d146741316c024d5932;hb=HEAD says both cpu-units have the same, zeroth board, but it might not hurt to check just in case some other machine happens to use a different index. -- 2. That which causes joy or happiness. -- To unsubscribe from this list: send the line "unsubscribe sparclinux" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html