Thread (35 messages) flat view 35 messages, 7 authors, 2012-03-16

Re: [PATCH v4 3/3] Input: gpio_keys.c: Enable use with non-local GPIO chips.

From: David Jander <hidden>
Date: 2012-03-16 08:47:56

On Fri, 16 Mar 2012 01:32:01 -0700
Dmitry Torokhov [off-list ref] wrote:
On Fri, Mar 16, 2012 at 09:17:01AM +0100, David Jander wrote:
quoted
On Fri, 16 Mar 2012 00:20:04 -0700
Dmitry Torokhov [off-list ref] wrote:
quoted
Hi David,

On Tue, Jun 14, 2011 at 11:08:11AM +0200, David Jander wrote:
quoted
Use a threaded interrupt handler in order to permit the handler to use
a GPIO driver that causes things like I2C transactions being done inside
the handler context.
Also, gpio_keys_init needs to be declared as a late_initcall, to make sure
all needed GPIO drivers have been loaded if the drivers are built into the
kernel.
Don't want to resurrect the whole initcall discussion, but could you
tell me again why the interrup handler needs to be threaded? We do not
access hardware from it, hardware is accessed from workqueue context.
Here is the ISR in its entirety:
Sorry, the reason described is apparently not very clear. The real reason seems
to be that I would like this driver to work with I2C GPIO expanders, and its
the GPIO expanders "interrupt controller" which has itself a threaded handler
(due to I2C transfers done in it to ack an IRQ). So this is actually a nested
and threaded interrupt controller (because the IRQ line of the GPIO expander
is connected to a different GPIO acting itself also as interrupt line).
In irq/manage.c, function __setup_irq():

...
	/*
	 * Check whether the interrupt nests into another interrupt
	 * thread.
	 */
	nested = irq_settings_is_nested_thread(desc);
	if (nested) {
		if (!new->thread_fn) {
			ret = -EINVAL;
			goto out_mput;
		}
...

This is were requesting a non-threaded IRQ from this GPIO controller will fail.

I know this is not a trivial setup, but IMHO it is very useful (for
connecting keyboards), and a nice demonstration of the powerful features this
GPIO driver has :-)
Thanks for the explanation of your setup.
quoted
quoted
static irqreturn_t gpio_keys_isr(int irq, void *dev_id)
{
        struct gpio_button_data *bdata = dev_id;
        const struct gpio_keys_button *button = bdata->button;

        BUG_ON(irq != gpio_to_irq(button->gpio));

        if (bdata->timer_debounce)
                mod_timer(&bdata->timer,
                        jiffies + msecs_to_jiffies(bdata->timer_debounce));
        else
                schedule_work(&bdata->work);

        return IRQ_HANDLED;
}

It looks to me that non-threaded handler would work as well? Or
gpio_to_irq() can sleep with certain chips?
Not in my case. I just checked again. If I change request_threaded_irq() to
request_irq(), I get this:

...
[    6.409810] gpio-keys gpio_keys.0: Unable to claim irq 0; error -22
[    6.416106] gpio-keys: probe of gpio_keys.0 failed with error -22
...

This error -22 (-EINVAL) is returned from __setup_irq() (see above).
But the original code used request_any_context_irq() which should have
taken care of your nested IRQ setup:
Hmm. You are right. Apparently this change was introduced in 2.6.38, and I
must have missed it. Before 2.6.38, this place called request_irq(), which was
broken for my case.

I just checked, and indeed, using request_any_context_irq() seems to work fine
for me.

Best regards,

-- 
David Jander
Protonic Holland.
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help