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

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

Attachments

    Outcomes