Skip to contentSkip to conversation

kernel/irq: __setup_irq/__free_irq disable-depth asymmetry?

PATCH New Shmulik Ladkani 1 participant 2 messages Jan 11, 2010 – Jan 12, 2010 IRQ

lore
Share & tools
lore
#0 lore raw

Hi,

For discussion simplicity, lets assume our IRQ is not IRQF_SHARED, also IRQ_NOAUTOEN is not set.

Normally, when the system is initialized, the initial value of irq_desc[i].depth is 1, representing disable-depth of 1, as the line is indeed initially disabeled.

When __setup_irq is called (as a result of request_irq call), the line gets enabled via desc->chip->startup(irq), and desc->depth is set to 0 (meaning: there's no disable-depth).

When __free_irq is called (assuming last handler unregistering), the line gets masked by desc->chip->shutdown(irq), however the desc->depth is not modified.
In that case, desc->depth is still 0 ("no disable-depth") but the line is actually disabled.

Now suppose someone calls disable_irq() and then enable_irq(). The overall result will be the line getting enabled by the latter call, although there's no registered ISR.
(disable_irq increments depth to 1, enabled_irq decrements it to 0 and thus calls desc->chip->enable).

Yes, I agree, calling disable_irq/enable_irq when there's no registered ISR is bizzare... however bizzare things might happen to you too ;)

What bothers me is that the overall result is not identical when running the following sequence: system initlialization, disable_irq, enable_irq (without any __setup_irq/__free_irq calls).
In that case, the overall result is that the line is kept masked. (upon initialization depth is 1, disable_irq increments it to 2, enable_irq decrements it to back 1. no desc->chip->xxx calls whatsoever).

The cause for this behaviour is the assymetrical treatment to the 'depth' field in __free_irq; it should have reverted what was done in __setup_irq.

So, I suggest resetting desc->depth to 1 within __free_irq (at the same place desc->chip->shutdown is called).

Your thoughts appreciated.

Signature · 1 line
Shmulik Ladkani
#1 lore raw

PATCH 1/1 kernel/irq: Reset IRQ desc->depth to 1 when __free_irq disables the line

Reset irq_desc's depth field to 1, indicating IRQ line is disabled, when __free_irq disables/shuts-down the line (i.e. upon unregistration of last interrupt handler).

---

kernel/irq/manage.c +1 -0
index eb6078c..642a98c 100644
@@ -877,6 +877,7 @@ static struct irqaction *__free_irq(unsigned int irq, void *dev_id)
 
 	/* If this was the last handler, shut down the IRQ line: */
 	if (!desc->action) {
+		desc->depth = 1;
 		desc->status |= IRQ_DISABLED;
 		if (desc->chip->shutdown)
 			desc->chip->shutdown(irq);
Signature · 1 line
Shmulik Ladkani