Skip to content

Commit

Permalink
gpio: Allow per-parent interrupt data
Browse files Browse the repository at this point in the history
The core gpiolib code is able to deal with multiple interrupt parents
for a single gpio irqchip. It however only allows a single piece
of data to be conveyed to all flow handlers (either the gpio_chip
or some other, driver-specific data).

This means that drivers have to go through some interesting dance
to find the correct context, something that isn't great in interrupt
context (see aebdc8a for a prime
example).

Instead, offer an optional way for a pinctrl/gpio driver to provide
an array of pointers which gets used to provide the correct context
to the flow handler.

Signed-off-by: Marc Zyngier <maz@kernel.org>
Signed-off-by: Joey Gouly <joey.gouly@arm.com>
Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
Link: https://lore.kernel.org/r/20211026175815.52703-2-joey.gouly@arm.com
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
  • Loading branch information
Marc Zyngier authored and Linus Walleij committed Oct 26, 2021
1 parent 6880fa6 commit cfe6807
Show file tree
Hide file tree
Showing 2 changed files with 24 additions and 4 deletions.
9 changes: 7 additions & 2 deletions drivers/gpio/gpiolib.c
Original file line number Diff line number Diff line change
Expand Up @@ -1534,9 +1534,14 @@ static int gpiochip_add_irqchip(struct gpio_chip *gc,
}

if (gc->irq.parent_handler) {
void *data = gc->irq.parent_handler_data ?: gc;

for (i = 0; i < gc->irq.num_parents; i++) {
void *data;

if (gc->irq.per_parent_data)
data = gc->irq.parent_handler_data_array[i];
else
data = gc->irq.parent_handler_data ?: gc;

/*
* The parent IRQ chip is already using the chip_data
* for this IRQ chip, so our callbacks simply use the
Expand Down
19 changes: 17 additions & 2 deletions include/linux/gpio/driver.h
Original file line number Diff line number Diff line change
Expand Up @@ -168,11 +168,18 @@ struct gpio_irq_chip {

/**
* @parent_handler_data:
* @parent_handler_data_array:
*
* Data associated, and passed to, the handler for the parent
* interrupt.
* interrupt. Can either be a single pointer if @per_parent_data
* is false, or an array of @num_parents pointers otherwise. If
* @per_parent_data is true, @parent_handler_data_array cannot be
* NULL.
*/
void *parent_handler_data;
union {
void *parent_handler_data;
void **parent_handler_data_array;
};

/**
* @num_parents:
Expand Down Expand Up @@ -203,6 +210,14 @@ struct gpio_irq_chip {
*/
bool threaded;

/**
* @per_parent_data:
*
* True if parent_handler_data_array describes a @num_parents
* sized array to be used as parent data.
*/
bool per_parent_data;

/**
* @init_hw: optional routine to initialize hardware before
* an IRQ chip will be added. This is quite useful when
Expand Down

0 comments on commit cfe6807

Please sign in to comment.