projects/linux·commit ff7a1790

gpiolib: Fix irq_domain resource tracking for gpiochip_irqchip_add_domain()

ff7a1790 · Michael Walle <[email protected]> · 2023-06-19 10:56:07 +02:00

Up until commit 6a45b0e2589f ("gpiolib: Introduce
gpiochip_irqchip_add_domain()") all irq_domains were allocated
by gpiolib itself and thus gpiolib also takes care of freeing it.

With gpiochip_irqchip_add_domain() a user of gpiolib can associate an
irq_domain with the gpio_chip. This irq_domain is not managed by
gpiolib and therefore must not be freed by gpiolib.

Fixes: 6a45b0e2589f ("gpiolib: Introduce gpiochip_irqchip_add_domain()")
Reported-by: Jiawen Wu <[email protected]>
Signed-off-by: Michael Walle <[email protected]>
Reviewed-by: Linus Walleij <[email protected]>
Reviewed-by: Andy Shevchenko <[email protected]>
Signed-off-by: Bartosz Golaszewski <[email protected]>
Commit
ff7a1790fbf92f1bdd0966d3f0da3ea808ede876
Parents
c1bcb976

Changes

2 files changed · +10 −1

FileStatusAddDelContent
drivers/gpio/gpiolib.cmodified+2−1View file
include/linux/gpio/driver.hmodified+8−0View file

drivers/gpio/gpiolib.c

View file
diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
index 9ecf93c..5be8ad6 100644
--- a/drivers/gpio/gpiolib.c
+++ b/drivers/gpio/gpiolib.c
@@ -1745,7 +1745,7 @@ static void gpiochip_irqchip_remove(struct gpio_chip *gc)
}
/* Remove all IRQ mappings and delete the domain */
- if (gc->irq.domain) {
+ if (!gc->irq.domain_is_allocated_externally && gc->irq.domain) {
unsigned int irq;
for (offset = 0; offset < gc->ngpio; offset++) {
@@ -1791,6 +1791,7 @@ int gpiochip_irqchip_add_domain(struct gpio_chip *gc,
gc->to_irq = gpiochip_to_irq;
gc->irq.domain = domain;
+ gc->irq.domain_is_allocated_externally = true;
/*
* Using barrier() here to prevent compiler from reordering

include/linux/gpio/driver.h

View file
diff --git a/include/linux/gpio/driver.h b/include/linux/gpio/driver.h
index 5c6db55..67b8774 100644
--- a/include/linux/gpio/driver.h
+++ b/include/linux/gpio/driver.h
@@ -252,6 +252,14 @@ struct gpio_irq_chip {
bool initialized;
/**
+ * @domain_is_allocated_externally:
+ *
+ * True it the irq_domain was allocated outside of gpiolib, in which
+ * case gpiolib won't free the irq_domain itself.
+ */
+ bool domain_is_allocated_externally;
+
+ /**
* @init_hw: optional routine to initialize hardware before
* an IRQ chip will be added. This is quite useful when
* a particular driver wants to clear IRQ related registers