gpio: Allow per-parent interrupt data
[ Upstream commit cfe6807d82e97e81c3209dca9448f091e1448a57 ]
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 aebdc8abc9
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>
Stable-dep-of: 8c00914e5438 ("gpiolib: Fix GPIO chip IRQ initialization restriction")
Signed-off-by: Sasha Levin <sashal@kernel.org>
This commit is contained in:
parent
bc75968b49
commit
304802e5b0
@ -1595,9 +1595,14 @@ static int gpiochip_add_irqchip(struct gpio_chip *gc,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (gc->irq.parent_handler) {
|
if (gc->irq.parent_handler) {
|
||||||
void *data = gc->irq.parent_handler_data ?: gc;
|
|
||||||
|
|
||||||
for (i = 0; i < gc->irq.num_parents; i++) {
|
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
|
* The parent IRQ chip is already using the chip_data
|
||||||
* for this IRQ chip, so our callbacks simply use the
|
* for this IRQ chip, so our callbacks simply use the
|
||||||
|
@ -168,11 +168,18 @@ struct gpio_irq_chip {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @parent_handler_data:
|
* @parent_handler_data:
|
||||||
|
* @parent_handler_data_array:
|
||||||
*
|
*
|
||||||
* Data associated, and passed to, the handler for the parent
|
* 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:
|
* @num_parents:
|
||||||
@ -203,6 +210,14 @@ struct gpio_irq_chip {
|
|||||||
*/
|
*/
|
||||||
bool threaded;
|
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
|
* @init_hw: optional routine to initialize hardware before
|
||||||
* an IRQ chip will be added. This is quite useful when
|
* an IRQ chip will be added. This is quite useful when
|
||||||
|
Loading…
Reference in New Issue
Block a user