Messages in this thread | | | Date | Wed, 6 Nov 2013 18:23:21 +0100 (CET) | From | Thomas Gleixner <> | Subject | Re: [patch 1/6] hardirq: Make hardirq bits generic |
| |
Geert,
On Mon, 4 Nov 2013, Geert Uytterhoeven wrote: > But only if you look at "[m68k] IRQ: add handle_polled_irq() for timer > based soft interrupt" (http://www.spinics.net/lists/linux-m68k/msg05889.html) > first ;-)
Done. Thanks for the reminder!
> Below is a patch with some fixups, on top of your two patches. > > Unfortunately it still hangs somewhere after mounting the root filesystem. > > Using this debug code for do_IRQ(): > > diff --git a/arch/m68k/kernel/irq.c b/arch/m68k/kernel/irq.c > index aaf7b15fad41..da9687803d98 100644 > --- a/arch/m68k/kernel/irq.c > +++ b/arch/m68k/kernel/irq.c > @@ -22,11 +22,21 @@ asmlinkage int do_IRQ(int irq, struct pt_regs *regs) > struct pt_regs *oldregs = set_irq_regs(regs); > int nested = regs->sr & ~ALLOWINT; > > +static int nesting; > +const char prefix[] = " "; > +unsigned long flags; > +local_irq_save(flags); > +nesting++; > +printk("# %sirq %d nested %d\n", &prefix[16-2*nesting], irq, nested); > +local_irq_restore(flags); > irq_enter(); > generic_handle_irq(irq); > irq_exit_nested(nested); > > set_irq_regs(oldregs); > +local_irq_save(flags); > +nesting--; > +local_irq_restore(flags); > return nested; > } > > I get output like > > # irq 15 nested 0 > # irq 15 nested 1024 > > irq 15 while irq 15 in progress??
Huch, that's odd.
> With similar debug code on the old working do_IRQ(), I get > - slightly less deep nesting, > - do_IRQ() is never re-entered with the same irq number. > > Also note that the value of "nested" doesn't match the indentation level, > which depends on my own bookkeeping using "nesting".
Well, nested is just an indicator. It's not the nest level.
nested = pt->sr & ~ALLOWINT; i.e.: nested = pt->sr & 0x0700;
So in the case above nested is 0x400
> Anyone with an idea where it's going wrong?
The original code does:
add_preempt_count(HARDIRQ_OFFSET);
do_IRQ() irq_enter(); add_preempt_count(HARDIRQ_OFFSET);
handle_irq();
irq_exit(); local_irq_disable(); sub_preempt_count(HARDIRQ_OFFSET);
sub_preempt_count(HARDIRQ_OFFSET);
/* Check for nested irq */ if (in_hardirq()) reti();
/* Check for nested irq again */ if (pt->sr & ~ALLOWINT != 0) reti();
do_softirq(); .... ret_from_exception();
With the patches in place it looks like this:
do_IRQ() nested = pt->sr & ~ALLOWINT;
irq_enter(); add_preempt_count(HARDIRQ_OFFSET);
handle_irq();
irq_exit_nested(nested); local_irq_disable(); sub_preempt_count(HARDIRQ_OFFSET); if (!nested && !in_hardirq()) do_softirq() return nested;
if (nested) reti();
ret_from_exception();
So all it does essentially is to move the softirq invocation in the non nested case a tad earlier. I'm really puzzled as I can't spot the point where this change makes a real difference.
Thanks,
tglx
| |