[#4202] GPIO interrupts not disabled; edge sensitive interrupt hang system
Submitted By: Michael McTernan
Open Date
2008-06-26 05:08:25 Close Date
2008-07-10 10:24:09
Priority:
Medium Assignee:
Michael Hennerich
Status:
Closed Fixed In Release:
N/A
Found In Release:
2008R1-RC8 Release:
2008R1
Category:
Kernel Functions Board:
Custom
Processor:
ALL Silicon Revision:
Is this bug repeatable?:
Yes Resolution:
Fixed
Uboot version or rev.:
Toolchain version or rev.:
App binary format:
N/A
Summary: GPIO interrupts not disabled; edge sensitive interrupt hang system
Details:
Hi,
In arch/blackfin/mach-common/ints-priority.c bfin_gpio_irqchip does not define .enable and .disable. This means that the GPIOs remain in the MASKA register after disabling, causing possible further interrupts.
This can be overlooked for edge sensitive interrupts as the kernel sets IRQ_DISABLED on the interrupt descriptors when disable_irq() is called, preventing unexpected handler execution.
For level sensitive interrupts the situation may not be so good. Calling disable_irq_nosync() in the interrupt handler marks the interrupt as IRQ_DISABLE but leaves the source active. If the GPIO is not rapidly cleared the system can stall while the GPO further interrupts the processor but does nothing due to IRQ_DISABLED having been set. (For background, my driver uses a level sensitive interrupt from the device, and merely calls disable_irq_nosync() in the interrupt in the handler, leaving the actual device access and eventual interrupt source clearing to some deferred processing as it is quite complex and involved).
The fix is to add entries for .disable and .enable into the two bfin_gpio_irqchip structures (one is for !CONFIG_BF54x, one is for the #else case):
static struct irq_chip bfin_gpio_irqchip = {
.ack = bfin_gpio_ack_irq,
.mask = bfin_gpio_mask_irq,
.mask_ack = bfin_gpio_mask_ack_irq,
.unmask = bfin_gpio_unmask_irq,
.disable = bfin_gpio_mask_irq, /* fix for level sensitive */
.enable = bfin_gpio_unmask_irq, /* fix for level sensitive */
.set_type = bfin_gpio_irq_type,
.startup = bfin_gpio_irq_startup,
.shutdown = bfin_gpio_irq_shutdown,
#ifdef CONFIG_PM
.set_wake = bfin_gpio_set_wake,
#endif
};
This drops the GPIO source from MASKA when disabled, adding it when re-enabled, and prevents actual interrupt events being generated for disabled GPOs. This makes level sensitive interrupts easier to use, and removes any performance hit from interrupting the processor for disabled irqs.
A patch is attached.
Kind Regards,
Mike
Follow-ups
--- Michael McTernan 2008-06-26 06:44:03
Correction: title should read "level sensitive interrupts hang
system".
--- Michael Hennerich 2008-06-26 06:44:46
Assign to me.
I fixed a similar issue some time ago for internal irqs.
blackfin.uclinux.org/gf/project/linux-kernel/scmsvn/?action=browse&path=%2F&view=rev&revision=4299
At that point I thought it wouldn't be an issue for GPIO irqs.
-Michael
--- Michael Hennerich 2008-06-26 07:02:19
Fixed on 2008R1 and on trunk.
Thanks for pointing this out.
IIRC the code used to call mask instead, in case disable is not implemented.
But this must have changed in the meanwhile. For enable I think this is still
the case.
-Michael
--- Michael Hennerich 2008-07-10 10:24:09
close it.
-Michael
Files
Changes
Commits
Dependencies
Duplicates
Associations
Tags
File Name File Type File Size Posted By
gpio-enabledisable.patch application/octet-stream 790 Michael McTernan