Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > linux.kernel > #1651383 > unrolled thread

[PATCH] genirq: Check irq disabled & masked states in irq_shutdown

Started byJeffy Chen <jeffy.chen@rock-chips.com>
First post2017-05-26 15:20 +0200
Last post2017-05-31 11:30 +0200
Articles 8 — 4 participants

Back to article view | Back to linux.kernel


Contents

  [PATCH] genirq: Check irq disabled & masked states in irq_shutdown Jeffy Chen <jeffy.chen@rock-chips.com> - 2017-05-26 15:20 +0200
    Re: [PATCH] genirq: Check irq disabled & masked states in  irq_shutdown Thomas Gleixner <tglx@linutronix.de> - 2017-05-26 15:30 +0200
      Re: [PATCH] genirq: Check irq disabled & masked states in irq_shutdown jeffy <jeffy.chen@rock-chips.com> - 2017-05-27 07:00 +0200
        Re: [PATCH] genirq: Check irq disabled & masked states in  irq_shutdown Thomas Gleixner <tglx@linutronix.de> - 2017-05-27 10:20 +0200
          Re: [PATCH] genirq: Check irq disabled & masked states in  irq_shutdown Brian Norris <briannorris@chromium.org> - 2017-05-31 01:30 +0200
            Re: [PATCH] genirq: Check irq disabled & masked states in  irq_shutdown Brian Norris <briannorris@chromium.org> - 2017-05-31 01:40 +0200
              Re: [PATCH] genirq: Check irq disabled & masked states in  irq_shutdown Thomas Gleixner <tglx@linutronix.de> - 2017-05-31 10:40 +0200
            Re: [PATCH] genirq: Check irq disabled & masked states in  irq_shutdown Thomas Gleixner <tglx@linutronix.de> - 2017-05-31 11:30 +0200

#1651383 — [PATCH] genirq: Check irq disabled & masked states in irq_shutdown

FromJeffy Chen <jeffy.chen@rock-chips.com>
Date2017-05-26 15:20 +0200
Subject[PATCH] genirq: Check irq disabled & masked states in irq_shutdown
Message-ID<tLnjP-6mu-3@gated-at.bofh.it>
If irq is already disabled and masked, we would hit a unbalanced irq
shutdown/disable/mask when freeing it.

Add a state check in irq_shutdown to prevent this.

Signed-off-by: Jeffy Chen <jeffy.chen@rock-chips.com>
---

 kernel/irq/chip.c | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/kernel/irq/chip.c b/kernel/irq/chip.c
index 686be4b..816da03 100644
--- a/kernel/irq/chip.c
+++ b/kernel/irq/chip.c
@@ -206,14 +206,20 @@ int irq_startup(struct irq_desc *desc, bool resend)
 
 void irq_shutdown(struct irq_desc *desc)
 {
-	irq_state_set_disabled(desc);
 	desc->depth = 1;
+
+	if (unlikely(irqd_irq_disabled(&desc->irq_data) &&
+		irqd_irq_masked(&desc->irq_data)))
+		goto out;
+
+	irq_state_set_disabled(desc);
 	if (desc->irq_data.chip->irq_shutdown)
 		desc->irq_data.chip->irq_shutdown(&desc->irq_data);
 	else if (desc->irq_data.chip->irq_disable)
 		desc->irq_data.chip->irq_disable(&desc->irq_data);
 	else
 		desc->irq_data.chip->irq_mask(&desc->irq_data);
+out:
 	irq_domain_deactivate_irq(&desc->irq_data);
 	irq_state_set_masked(desc);
 }
-- 
2.1.4

[toc] | [next] | [standalone]


#1651392 — Re: [PATCH] genirq: Check irq disabled & masked states in irq_shutdown

FromThomas Gleixner <tglx@linutronix.de>
Date2017-05-26 15:30 +0200
SubjectRe: [PATCH] genirq: Check irq disabled & masked states in irq_shutdown
Message-ID<tLntw-6pE-11@gated-at.bofh.it>
In reply to#1651383
On Fri, 26 May 2017, Jeffy Chen wrote:

> If irq is already disabled and masked, we would hit a unbalanced irq
> shutdown/disable/mask when freeing it.

Errr? What exactly is unbalanced? None of the called functions has any
counter or whatever.

Can you please explain what you are trying to fix?

Thanks,

	tglx

[toc] | [prev] | [next] | [standalone]


#1651755

Fromjeffy <jeffy.chen@rock-chips.com>
Date2017-05-27 07:00 +0200
Message-ID<tLBZv-70X-1@gated-at.bofh.it>
In reply to#1651392
Hi Thomas,

On 05/26/2017 09:20 PM, Thomas Gleixner wrote:
> On Fri, 26 May 2017, Jeffy Chen wrote:
>
>> If irq is already disabled and masked, we would hit a unbalanced irq
>> shutdown/disable/mask when freeing it.
>
> Errr? What exactly is unbalanced? None of the called functions has any
> counter or whatever.
>
> Can you please explain what you are trying to fix?

sorry, i'll try to rewrite the commit message.

for example when a driver(drivers/net/wireless/marvell/mwifiex/main.c) 
try to do these:

devm_request_irq->irq_startup->irq_enable
disable_irq                                     <-- disabled and masked
devm_free_irq->irq_shutdown                     <-- disable it again

and the pinctrl-rockchip driver would enable/disable gpio clk in 
irq_enable/irq_disable, so it would try to disable a disabled clk(due to 
unbalanced irq disable)


>
> Thanks,
>
> 	tglx
>
>
>

[toc] | [prev] | [next] | [standalone]


#1651802 — Re: [PATCH] genirq: Check irq disabled & masked states in irq_shutdown

FromThomas Gleixner <tglx@linutronix.de>
Date2017-05-27 10:20 +0200
SubjectRe: [PATCH] genirq: Check irq disabled & masked states in irq_shutdown
Message-ID<tLF74-H2-15@gated-at.bofh.it>
In reply to#1651755
On Sat, 27 May 2017, jeffy wrote:
> On 05/26/2017 09:20 PM, Thomas Gleixner wrote:
> > On Fri, 26 May 2017, Jeffy Chen wrote:
> > 
> > > If irq is already disabled and masked, we would hit a unbalanced irq
> > > shutdown/disable/mask when freeing it.
> > 
> > Errr? What exactly is unbalanced? None of the called functions has any
> > counter or whatever.
> > 
> > Can you please explain what you are trying to fix?
> 
> sorry, i'll try to rewrite the commit message.
> 
> for example when a driver(drivers/net/wireless/marvell/mwifiex/main.c) try to
> do these:
> 
> devm_request_irq->irq_startup->irq_enable
> disable_irq                                     <-- disabled and masked
> devm_free_irq->irq_shutdown                     <-- disable it again

This driver is broken as hell. It requests the interrupt _BEFORE_ the whole
thing is initialized. If there is a pending interrupt on that line, it will
explode nicely before it is able to disable the irq. But that's a different
problem.

Thanks,

	tglx

[toc] | [prev] | [next] | [standalone]


#1653714 — Re: [PATCH] genirq: Check irq disabled & masked states in irq_shutdown

FromBrian Norris <briannorris@chromium.org>
Date2017-05-31 01:30 +0200
SubjectRe: [PATCH] genirq: Check irq disabled & masked states in irq_shutdown
Message-ID<tMYKl-5hj-1@gated-at.bofh.it>
In reply to#1651802
Hi,

To address a tangent brought up here:

On Sat, May 27, 2017 at 10:16:37AM +0200, Thomas Gleixner wrote:
> On Sat, 27 May 2017, jeffy wrote:
> > for example when a driver(drivers/net/wireless/marvell/mwifiex/main.c) try to
> > do these:
> > 
> > devm_request_irq->irq_startup->irq_enable
> > disable_irq                                     <-- disabled and masked
> > devm_free_irq->irq_shutdown                     <-- disable it again
> 
> This driver is broken as hell.

No argument on the general statement :)

> It requests the interrupt _BEFORE_ the whole
> thing is initialized. If there is a pending interrupt on that line, it will
> explode nicely before it is able to disable the irq. But that's a different
> problem.

For that particular interrupt, it's mostly an informational interrupt
regarding wakeups. We don't do anything that could blow up there, except
report a (spurious) wakeup event. (And this spurious wakeup event only
occurs because the Wifi firmware may toggle its "wake" pin even when the
system is already awake. A weird behavior...)

So yes, the pattern isn't great, but no, it's not going to blow up,
AFAIK.

However, if you were to look at the same driver's .../mwifiex/pcie.c,
you would see a similar problem, and you *would* be right if you claimed
that things could blow up badly there! mwifiex_pcie_request_irq() is
called much too early, and if an interrupt gets queued up at the wrong
time, we won't handle it very nicely.

Anyway, I just thought I'd mention it, in case someone else following
this thread is curious. Coincidentally, I'm already working on patching
this on linux-wireless@.

Side note: for issues like the first problem above, I wonder why there
isn't a flag that once could pass to request_irq() that suggests the IRQ
should be initially disabled? I know this wouldn't work for shared
interrupts (but request_irq() could reject that combination, no?), but
it seems like there are plenty of cases where it might be useful. Some
devices simply don't have a device-level interrupt mask, and always
expect to have a dedicated interrupt. With the status quo, a driver for
such a device has to defer their request_irq() until
sometimes-inconvient times [1], or else accept some subpar behavior (see
above "spurious wakeup reporting").

Regards,
Brian

[1] Note that, for one, request_irq() can fail, whereas enable_irq()
    cannot.

[toc] | [prev] | [next] | [standalone]


#1653718 — Re: [PATCH] genirq: Check irq disabled & masked states in irq_shutdown

FromBrian Norris <briannorris@chromium.org>
Date2017-05-31 01:40 +0200
SubjectRe: [PATCH] genirq: Check irq disabled & masked states in irq_shutdown
Message-ID<tMYU1-5kF-1@gated-at.bofh.it>
In reply to#1653714
Sorry to respond to myself. Thomas, your reply to another mail in this
series helped me to notice:

On Tue, May 30, 2017 at 04:19:58PM -0700, Brian Norris wrote:
> Side note: for issues like the first problem above, I wonder why there
> isn't a flag that once could pass to request_irq() that suggests the IRQ
> should be initially disabled?

Is that what IRQ_NOAUTOEN is for?

> I know this wouldn't work for shared
> interrupts (but request_irq() could reject that combination, no?)

Hehe, but then I see this, for example, when grepping around:

drivers/usb/dwc3/dwc3-omap.c:

        irq_set_status_flags(omap->irq, IRQ_NOAUTOEN);
        ret = devm_request_threaded_irq(dev, omap->irq, dwc3_omap_interrupt,
                                        dwc3_omap_interrupt_thread, IRQF_SHARED,
                                        "dwc3-omap", omap);

IIUC, that's quite broken, no?

Brian

[toc] | [prev] | [next] | [standalone]


#1653998 — Re: [PATCH] genirq: Check irq disabled & masked states in irq_shutdown

FromThomas Gleixner <tglx@linutronix.de>
Date2017-05-31 10:40 +0200
SubjectRe: [PATCH] genirq: Check irq disabled & masked states in irq_shutdown
Message-ID<tN7kB-2mN-7@gated-at.bofh.it>
In reply to#1653718
On Tue, 30 May 2017, Brian Norris wrote:
> Sorry to respond to myself. Thomas, your reply to another mail in this
> series helped me to notice:
> 
> On Tue, May 30, 2017 at 04:19:58PM -0700, Brian Norris wrote:
> > Side note: for issues like the first problem above, I wonder why there
> > isn't a flag that once could pass to request_irq() that suggests the IRQ
> > should be initially disabled?
> 
> Is that what IRQ_NOAUTOEN is for?

Yes.

> > I know this wouldn't work for shared
> > interrupts (but request_irq() could reject that combination, no?)
> 
> Hehe, but then I see this, for example, when grepping around:
> 
> drivers/usb/dwc3/dwc3-omap.c:
> 
>         irq_set_status_flags(omap->irq, IRQ_NOAUTOEN);
>         ret = devm_request_threaded_irq(dev, omap->irq, dwc3_omap_interrupt,
>                                         dwc3_omap_interrupt_thread, IRQF_SHARED,
>                                         "dwc3-omap", omap);
> 
> IIUC, that's quite broken, no?

Indeed. Because the interrupt could have been requested by some other
driver already. In that case IRQ_NOAUTOEN has no effect at all.

We probably should check that in __setup_irq() and yell at people.

Thanks,

	tglx

[toc] | [prev] | [next] | [standalone]


#1654054 — Re: [PATCH] genirq: Check irq disabled & masked states in irq_shutdown

FromThomas Gleixner <tglx@linutronix.de>
Date2017-05-31 11:30 +0200
SubjectRe: [PATCH] genirq: Check irq disabled & masked states in irq_shutdown
Message-ID<tN870-2UY-27@gated-at.bofh.it>
In reply to#1653714
On Tue, 30 May 2017, Brian Norris wrote:
> On Sat, May 27, 2017 at 10:16:37AM +0200, Thomas Gleixner wrote:
> > On Sat, 27 May 2017, jeffy wrote:
> > > for example when a driver(drivers/net/wireless/marvell/mwifiex/main.c) try to
> > > do these:
> > > 
> > > devm_request_irq->irq_startup->irq_enable
> > > disable_irq                                     <-- disabled and masked
> > > devm_free_irq->irq_shutdown                     <-- disable it again
> > 
> > This driver is broken as hell.
> 
> No argument on the general statement :)
> 
> > It requests the interrupt _BEFORE_ the whole
> > thing is initialized. If there is a pending interrupt on that line, it will
> > explode nicely before it is able to disable the irq. But that's a different
> > problem.
> 
> For that particular interrupt, it's mostly an informational interrupt
> regarding wakeups. We don't do anything that could blow up there, except
> report a (spurious) wakeup event. (And this spurious wakeup event only
> occurs because the Wifi firmware may toggle its "wake" pin even when the
> system is already awake. A weird behavior...)
> 
> So yes, the pattern isn't great, but no, it's not going to blow up,
> AFAIK.

Fair enough.

Thanks,

	tglx

[toc] | [prev] | [standalone]


Back to top | Article view | linux.kernel


csiph-web