greybus: gpio: fix interrupt protocol
authorJohan Hovold <johan@hovoldconsulting.com>
Tue, 26 May 2015 13:29:25 +0000 (15:29 +0200)
committerGreg Kroah-Hartman <gregkh@google.com>
Tue, 26 May 2015 22:27:39 +0000 (15:27 -0700)
The current interrupt implementation uses the simple irq-flow handler,
which means that the interrupt subsystem makes no irq-chip callbacks
when handling an interrupt. Specifically, no end-of-interrupt message is
sent when the threaded handler has run. This means that we may currently
re-enable an interrupt before it has been serviced (i.e. the irq-event
operation may complete before the threaded handler has run).

The simple flow handler also silently drops a second interrupt arriving
while a handler is running. This means that we may lose a second edge
interrupt with the current firmware.

Switch to a new one-shot interrupt protocol, where the primary handler
(firmware) always masks and acks an interrupt before sending an event to
the AP. The AP is responsible for unmasking the interrupt when it has
been handled. By having the firmware ack an edge interrupt before
sending the event, a second edge interrupt will no longer get lost.

This one-shot protocol can be implemented in the kernel by using the
level irq-flow handler, one-shot interrupts with threaded handlers and
bus-lock synchronisation for slow buses. Note that the same flow handler
is used for both edge and level interrupts.

Signed-off-by: Johan Hovold <johan@hovoldconsulting.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
drivers/staging/greybus/gpio.c
drivers/staging/greybus/greybus_protocols.h

index 6cf3bb1..8dad9e5 100644 (file)
@@ -672,7 +672,7 @@ static int gb_gpio_connection_init(struct gb_connection *connection)
        }
 
        ret = gb_gpio_irqchip_add(gpio, irqc, 0,
-                                  handle_simple_irq, IRQ_TYPE_NONE);
+                                  handle_level_irq, IRQ_TYPE_NONE);
        if (ret) {
                dev_err(&connection->dev, "failed to add irq chip: %d\n", ret);
                goto irqchip_err;
index 0fd42bc..81ec3b2 100644 (file)
@@ -206,7 +206,7 @@ struct gb_gpio_irq_unmask_request {
 struct gb_gpio_irq_event_request {
        __u8    which;
 };
-/* irq event response has no payload */
+/* irq event has no response */
 
 
 /* PWM */