All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] genirq: Check irq disabled & masked states in irq_shutdown
@ 2017-05-26 13:17 Jeffy Chen
  2017-05-26 13:20 ` Thomas Gleixner
  0 siblings, 1 reply; 8+ messages in thread
From: Jeffy Chen @ 2017-05-26 13:17 UTC (permalink / raw)
  To: linux-kernel; +Cc: briannorris, dianders, tfiga, Jeffy Chen, Thomas Gleixner

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

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* Re: [PATCH] genirq: Check irq disabled & masked states in irq_shutdown
  2017-05-26 13:17 [PATCH] genirq: Check irq disabled & masked states in irq_shutdown Jeffy Chen
@ 2017-05-26 13:20 ` Thomas Gleixner
  2017-05-27  4:52   ` jeffy
  0 siblings, 1 reply; 8+ messages in thread
From: Thomas Gleixner @ 2017-05-26 13:20 UTC (permalink / raw)
  To: Jeffy Chen; +Cc: linux-kernel, briannorris, dianders, tfiga

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

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH] genirq: Check irq disabled & masked states in irq_shutdown
  2017-05-26 13:20 ` Thomas Gleixner
@ 2017-05-27  4:52   ` jeffy
  2017-05-27  8:16     ` Thomas Gleixner
  0 siblings, 1 reply; 8+ messages in thread
From: jeffy @ 2017-05-27  4:52 UTC (permalink / raw)
  To: Thomas Gleixner; +Cc: linux-kernel, briannorris, dianders, tfiga

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
>
>
>

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH] genirq: Check irq disabled & masked states in irq_shutdown
  2017-05-27  4:52   ` jeffy
@ 2017-05-27  8:16     ` Thomas Gleixner
  2017-05-30 23:20       ` Brian Norris
  0 siblings, 1 reply; 8+ messages in thread
From: Thomas Gleixner @ 2017-05-27  8:16 UTC (permalink / raw)
  To: jeffy; +Cc: LKML, briannorris, dianders, tfiga, Johannes Berg

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

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH] genirq: Check irq disabled & masked states in irq_shutdown
  2017-05-27  8:16     ` Thomas Gleixner
@ 2017-05-30 23:20       ` Brian Norris
  2017-05-30 23:32         ` Brian Norris
  2017-05-31  9:22         ` Thomas Gleixner
  0 siblings, 2 replies; 8+ messages in thread
From: Brian Norris @ 2017-05-30 23:20 UTC (permalink / raw)
  To: Thomas Gleixner; +Cc: jeffy, LKML, dianders, tfiga, Johannes Berg

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.

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH] genirq: Check irq disabled & masked states in irq_shutdown
  2017-05-30 23:20       ` Brian Norris
@ 2017-05-30 23:32         ` Brian Norris
  2017-05-31  8:38           ` Thomas Gleixner
  2017-05-31  9:22         ` Thomas Gleixner
  1 sibling, 1 reply; 8+ messages in thread
From: Brian Norris @ 2017-05-30 23:32 UTC (permalink / raw)
  To: Thomas Gleixner; +Cc: jeffy, LKML, dianders, tfiga, Johannes Berg

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

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH] genirq: Check irq disabled & masked states in irq_shutdown
  2017-05-30 23:32         ` Brian Norris
@ 2017-05-31  8:38           ` Thomas Gleixner
  0 siblings, 0 replies; 8+ messages in thread
From: Thomas Gleixner @ 2017-05-31  8:38 UTC (permalink / raw)
  To: Brian Norris; +Cc: jeffy, LKML, dianders, tfiga, Johannes Berg

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

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH] genirq: Check irq disabled & masked states in irq_shutdown
  2017-05-30 23:20       ` Brian Norris
  2017-05-30 23:32         ` Brian Norris
@ 2017-05-31  9:22         ` Thomas Gleixner
  1 sibling, 0 replies; 8+ messages in thread
From: Thomas Gleixner @ 2017-05-31  9:22 UTC (permalink / raw)
  To: Brian Norris; +Cc: jeffy, LKML, dianders, tfiga, Johannes Berg

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

^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2017-05-31  9:22 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-05-26 13:17 [PATCH] genirq: Check irq disabled & masked states in irq_shutdown Jeffy Chen
2017-05-26 13:20 ` Thomas Gleixner
2017-05-27  4:52   ` jeffy
2017-05-27  8:16     ` Thomas Gleixner
2017-05-30 23:20       ` Brian Norris
2017-05-30 23:32         ` Brian Norris
2017-05-31  8:38           ` Thomas Gleixner
2017-05-31  9:22         ` Thomas Gleixner

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.