[#3896] rtc in trunk kills board if irq fires after free_irq() happened
Submitted By: Mike Frysinger
Open Date
2008-02-14 13:16:15 Close Date
2008-02-15 11:49:03
Priority:
Medium Assignee:
Michael Hennerich
Status:
Closed Fixed In Release:
N/A
Found In Release:
N/A Release:
Category:
N/A Board:
N/A
Processor:
N/A Silicon Revision:
Is this bug repeatable?:
Yes Resolution:
Fixed
Uboot version or rev.:
Toolchain version or rev.:
App binary format:
N/A
Summary: rtc in trunk kills board if irq fires after free_irq() happened
Details:
if you set an rtc alarm (RTC_AIE_ON), after it fires, the board hangs a few seconds later and the watchdog kicks it
root:/> /rtctest
Current RTC date/time is 1-1-1970, 23:28:26.
Alarm time now set to 23:28:29.
Waiting 5 seconds for alarm... okay. Alarm rang.
root:/>
root:/>
root:/>
U-Boot 1.1.6-ga36a5315-svn1144 (ADI-2008R2-pre) (Feb 4 2008 - 23:49:11)
........
Follow-ups
--- Mike Frysinger 2008-02-15 02:14:52
ive fixed the immediate issue (the rtc driver was not disabling the write
complete interrupt while shutting down and before free-ing the RTC IRQ), but i
think there's a bigger problem here
if the IRQ fired (and it does) after freeing the RTC IRQ, it should not cause
the board to hang ... i think that means something is going wrong in our core
irq handling code
Michael: to reproduce the issue on trunk, edit the rtc-bfin.c driver and change
the release function like so:
- bfin_rtc_reset(dev, 0);
+ bfin_rtc_reset(dev, RTC_ISTAT_WRITE_COMPLETE);
then once you've booted the system, simply do:
cat /dev/rtc0
then hit CTRL+C to kill it
after like 2 or 3 seconds, the system should go into a soft hang and eventually
the watchdog will kick the system
--- Michael Hennerich 2008-02-15 08:29:28
This is a pretty interesting kernel Bug, which may affects all archs.
free_irq() does not disable/mask the irq.
According to linux/irq.h
shutdown should default to disable if left blank in struct irq_chip.
However irq_chip_set_defaults initializes it with disable which points to
default_disable() a empty function.
if (!desc->action) {
desc->status |= IRQ_DISABLED;
if (desc->chip->shutdown)
desc->chip->shutdown(irq);
else
desc->chip->disable(irq);
}
Will always be true and it will execute the empty function.
/**
* struct irq_chip - hardware interrupt chip descriptor
*
* @name: name for /proc/interrupts
* @startup: start up the interrupt (defaults to ->enable if NULL)
* @shutdown: shut down the interrupt (defaults to ->disable if NULL)
* @enable: enable the interrupt (defaults to chip->unmask if NULL)
* @disable: disable the interrupt (defaults to chip->mask if NULL)
* @ack: start of a new interrupt
* @mask: mask an interrupt source
* @mask_ack: ack and mask an interrupt source
* @unmask: unmask an interrupt source
* @eoi: end of interrupt - chip level
* @end: end of interrupt - flow level
* @set_affinity: set the CPU affinity on SMP machines
* @retrigger: resend an IRQ to the CPU
* @set_type: set the flow type (IRQ_TYPE_LEVEL/etc.) of an IRQ
* @set_wake: enable/disable power-management wake-on of an IRQ
*
* @release: release function solely used by UML
* @typename: obsoleted by name, kept as migration helper
*/
/*
* default disable function
*/
static void default_disable(unsigned int irq)
{
}
/*
* default startup function
*/
static unsigned int default_startup(unsigned int irq)
{
irq_desc[irq].chip->enable(irq);
return 0;
}
/*
* Fixup enable/disable function pointers
*/
void irq_chip_set_defaults(struct irq_chip *chip)
{
if (!chip->enable)
chip->enable = default_enable;
if (!chip->disable)
chip->disable = default_disable;
if (!chip->startup)
chip->startup = default_startup;
if (!chip->shutdown)
chip->shutdown = chip->disable;
if (!chip->name)
chip->name = chip->typename;
if (!chip->end)
chip->end = dummy_irq_chip.end;
}
--- Michael Hennerich 2008-02-15 09:59:31
should be fixed now.
I sent a patch to lkml.
-Michael
--- Mike Frysinger 2008-02-15 13:58:27
thanks, things no longer fail for me
Files
Changes
Commits
Dependencies
Duplicates
Associations
Tags
File Name File Type File Size Posted By
rtctest.c text/x-csrc 2541 Mike Frysinger