Re: [patch 1/6] hardirq: Make hardirq bits generic

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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
--
To unsubscribe from this list: send the line "unsubscribe linux-m68k" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html




[Index of Archives]     [Video for Linux]     [Yosemite News]     [Linux S/390]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux