2011-06-12 18:53:49

by Manuel Lauss

[permalink] [raw]
Subject: chained irq handler problems

Hello Thomas,

I've been struggling to get an external IRQ multiplexer to work with the
chained handler infrastructure, and I was wondering whether you could shed
some light on it:

The code below is the one that works: in the ->irq_startup callback it
installs a "traditional" irq handler for the multiplexer cascade, and
the handler then reads the external status register and dispatches all
pending external irqs at once.

Now, when I register the cascade handler with irq_set_chained_handler() and
remove the irq_startup callback the system is overrun with an irq storm from
the external mux, which starts when userspace is booting (i.e. after
"Freeing unused kernel memory: xx" appears), rendering it effectively dead.

My question is: what are the differences in interrupt handling between the
"traditional" handler and the cascade handler case?
I also noticed that the cascade irq (the muxer irq line to the cpu) is not
disabled when the interrupt is serviced. Is this by design?

Thank you!
Manuel Lauss


static irqreturn_t db1300_csc_handler(int irq, void *dev_id)
{
unsigned short bisr = __raw_readw(__bcsr_virt + BCSR_REG_INTSTAT);

for ( ; bisr; bisr &= bisr - 1)
generic_handle_irq(__cscfirst + __ffs(bisr));

return IRQ_HANDLED;
}

// mask/unmask/maskack for external ints come here

static unsigned int db1300_csc_startup(struct irq_data *d)
{
int retval = 0;

mutex_lock(&__cscmtx);
if ((++__cscusecnt) == 1)
retval = request_irq(__cscirq, &db1300_csc_handler,
IRQF_TRIGGER_HIGH, "csc", 0);
mutex_unlock(&__cscmtx);

db1300_csc_unmask(d);

return retval;
}

static void db1300_csc_shutdown(struct irq_data *d)
{
db1300_csc_mask(d);

mutex_lock(&__cscmtx);
if ((--__cscusecnt) == 0)
free_irq(__cscirq, &db1300_csc_handler);
mutex_unlock(&__cscmtx);
}

static struct irq_chip db1300_csc_irq_type = {
[...]
.irq_startup = db1300_csc_startup,
.irq_shutdown = db1300_csc_shutdown,
};

// external int initialization:
[...]
for (irq = first; irq <= last; irq++)
irq_set_chip_and_handler_name(irq, &db1300_csc_irq_type,
handle_level_irq, "level");
[...]


2011-06-14 10:05:53

by Thomas Gleixner

[permalink] [raw]
Subject: Re: chained irq handler problems

On Sun, 12 Jun 2011, Manuel Lauss wrote:
> My question is: what are the differences in interrupt handling between the
> "traditional" handler and the cascade handler case?
> I also noticed that the cascade irq (the muxer irq line to the cpu) is not
> disabled when the interrupt is serviced. Is this by design?

The normal handler, which should btw never ever be setup from an
startup callback, deals with the irq chip functions (mask, ack, eoi)
which are assigned to that irq line. The chained handler is called
directly from the low level entry code and bypasses the standard
handling mechanism. That means no chip functions are called. If your
irq chip of the primary line requires e.g. an ack, then this needs to
be done explicitely in the chained handler itself.

Thanks,

tglx

2011-06-14 11:17:12

by Manuel Lauss

[permalink] [raw]
Subject: Re: chained irq handler problems

On Tue, Jun 14, 2011 at 12:05 PM, Thomas Gleixner <[email protected]> wrote:
> On Sun, 12 Jun 2011, Manuel Lauss wrote:
>> My question is: what are the differences in interrupt handling between the
>> "traditional" handler and the cascade handler case?
>> I also noticed that the cascade irq (the muxer irq line to the cpu) is not
>> disabled when the interrupt is serviced. Is this by design?
>
> The normal handler, which should btw never ever be setup from an
> startup callback, deals with the irq chip functions (mask, ack, eoi)
> which are assigned to that irq line. The chained handler is called
> directly from the low level entry code and bypasses the standard
> handling mechanism. That means no chip functions are called. If your
> irq chip of the primary line requires e.g. an ack, then this needs to
> be done explicitely in the chained handler itself.

I added calls to disable/enable the cascade around the call
to generic_handle_irq() and now it works (no ack necessary since
the cascade is set up as level-triggered).

Thanks!
Manuel Lauss