[#3896] rtc in trunk kills board if irq fires after free_irq() happened

Document created by Aaronwu Employee on Aug 28, 2013
Version 1Show Document
  • View in full screen mode

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


Medium     Assignee:

Michael Hennerich


Closed     Fixed In Release:


Found In Release:

N/A     Release:


N/A     Board:



N/A     Silicon Revision:

Is this bug repeatable?:

Yes     Resolution:


Uboot version or rev.:

    Toolchain version or rev.:

App binary format:


Summary: rtc in trunk kills board if irq fires after free_irq() happened



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.





U-Boot 1.1.6-ga36a5315-svn1144 (ADI-2008R2-pre) (Feb  4 2008 - 23:49:11)






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







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)




    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.



--- Mike Frysinger                                           2008-02-15 13:58:27

thanks, things no longer fail for me












File Name     File Type     File Size     Posted By

rtctest.c    text/x-csrc    2541    Mike Frysinger