| Submitter | Yong Zhang |
|---|---|
| Date | 2009-11-03 14:58:54 |
| Message ID | <2674af740911030658m76b702cfxb67723984286c4bb@mail.gmail.com> |
| Download | mbox | patch |
| Permalink | /patch/57320/ |
| State | New |
| Headers | show |
Comments
Yong Zhang wrote: >> This happens because the &desc->lock is taken with spin_lock_irqsave and >> just a spin_lock. In the try_one_irq(), this lock really should be a >> spin_lock_irqsave(). >> >> > > Cc'ed Ingo and Thomas. > > The reason is that try_one_irq() is called both from hardirq context and softirq > context. And by default the timer handler poll_all_shared_irqs() is > called with irq enabled. > Then the two usage will cause inconsistent. > > So I think the following patch is also workable to you. > Ah, okay. I will retest and get back to you ... P. -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
On Tue, 3 Nov 2009, Yong Zhang wrote: > > This happens because the &desc->lock is taken with spin_lock_irqsave and > > just a spin_lock. In the try_one_irq(), this lock really should be a > > spin_lock_irqsave(). > > > > Cc'ed Ingo and Thomas. > > The reason is that try_one_irq() is called both from hardirq context and softirq > context. And by default the timer handler poll_all_shared_irqs() is > called with irq enabled. > Then the two usage will cause inconsistent. > > So I think the following patch is also workable to you. Yes, that's sufficient. > diff --git a/kernel/irq/spurious.c b/kernel/irq/spurious.c > index 114e704..11affbc 100644 > --- a/kernel/irq/spurious.c > +++ b/kernel/irq/spurious.c > @@ -111,6 +111,7 @@ static void poll_all_shared_irqs(void) > > for_each_irq_desc(i, desc) { > unsigned int status; > + unsigned long flags; > > if (!i) > continue; > @@ -121,7 +122,9 @@ static void poll_all_shared_irqs(void) > if (!(status & IRQ_SPURIOUS_DISABLED)) > continue; > > + local_irq_save(flags); > try_one_irq(i, desc); > + local_irq_restore(flags); You can even use local_irq_en/disable() here. Thanks, tglx
On Wed, Nov 4, 2009 at 5:18 PM, Thomas Gleixner <tglx@linutronix.de> wrote: > On Tue, 3 Nov 2009, Yong Zhang wrote: > >> > This happens because the &desc->lock is taken with spin_lock_irqsave and >> > just a spin_lock. In the try_one_irq(), this lock really should be a >> > spin_lock_irqsave(). >> > >> So I think the following patch is also workable to you. > > Yes, that's sufficient. > >> diff --git a/kernel/irq/spurious.c b/kernel/irq/spurious.c >> index 114e704..11affbc 100644 >> --- a/kernel/irq/spurious.c >> +++ b/kernel/irq/spurious.c >> @@ -111,6 +111,7 @@ static void poll_all_shared_irqs(void) >> >> for_each_irq_desc(i, desc) { >> unsigned int status; >> + unsigned long flags; >> >> if (!i) >> continue; >> @@ -121,7 +122,9 @@ static void poll_all_shared_irqs(void) >> if (!(status & IRQ_SPURIOUS_DISABLED)) >> continue; >> >> + local_irq_save(flags); >> try_one_irq(i, desc); >> + local_irq_restore(flags); > > You can even use local_irq_en/disable() here. Yup, I will resend the patch later. Thanks, Yong > > Thanks, > > tglx -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Patch
diff --git a/kernel/irq/spurious.c b/kernel/irq/spurious.c index 114e704..11affbc 100644 --- a/kernel/irq/spurious.c +++ b/kernel/irq/spurious.c @@ -111,6 +111,7 @@ static void poll_all_shared_irqs(void) for_each_irq_desc(i, desc) { unsigned int status; + unsigned long flags; if (!i) continue; @@ -121,7 +122,9 @@ static void poll_all_shared_irqs(void) if (!(status & IRQ_SPURIOUS_DISABLED)) continue; + local_irq_save(flags); try_one_irq(i, desc); + local_irq_restore(flags); } }