diff --git a/drivers/gpio/gpiolib-acpi.c b/drivers/gpio/gpiolib-acpi.c index c758b4daf92b..8c7c65540b7c 100644 --- a/drivers/gpio/gpiolib-acpi.c +++ b/drivers/gpio/gpiolib-acpi.c @@ -207,7 +207,7 @@ fail_free_desc: /** * acpi_gpiochip_request_interrupts() - Register isr for gpio chip ACPI events - * @acpi_gpio: ACPI GPIO chip + * @chip: GPIO chip * * ACPI5 platforms can use GPIO signaled ACPI events. These GPIO interrupts are * handled by ACPI event methods which need to be called from the GPIO @@ -215,11 +215,21 @@ fail_free_desc: * gpio pins have acpi event methods and assigns interrupt handlers that calls * the acpi event methods for those pins. */ -static void acpi_gpiochip_request_interrupts(struct acpi_gpio_chip *acpi_gpio) +void acpi_gpiochip_request_interrupts(struct gpio_chip *chip) { - struct gpio_chip *chip = acpi_gpio->chip; + struct acpi_gpio_chip *acpi_gpio; + acpi_handle handle; + acpi_status status; - if (!chip->to_irq) + if (!chip->dev || !chip->to_irq) + return; + + handle = ACPI_HANDLE(chip->dev); + if (!handle) + return; + + status = acpi_get_data(handle, acpi_gpio_chip_dh, (void **)&acpi_gpio); + if (ACPI_FAILURE(status)) return; INIT_LIST_HEAD(&acpi_gpio->events); @@ -229,17 +239,27 @@ static void acpi_gpiochip_request_interrupts(struct acpi_gpio_chip *acpi_gpio) /** * acpi_gpiochip_free_interrupts() - Free GPIO ACPI event interrupts. - * @acpi_gpio: ACPI GPIO chip + * @chip: GPIO chip * * Free interrupts associated with GPIO ACPI event method for the given * GPIO chip. */ -static void acpi_gpiochip_free_interrupts(struct acpi_gpio_chip *acpi_gpio) +void acpi_gpiochip_free_interrupts(struct gpio_chip *chip) { + struct acpi_gpio_chip *acpi_gpio; struct acpi_gpio_event *event, *ep; - struct gpio_chip *chip = acpi_gpio->chip; + acpi_handle handle; + acpi_status status; - if (!chip->to_irq) + if (!chip->dev || !chip->to_irq) + return; + + handle = ACPI_HANDLE(chip->dev); + if (!handle) + return; + + status = acpi_get_data(handle, acpi_gpio_chip_dh, (void **)&acpi_gpio); + if (ACPI_FAILURE(status)) return; list_for_each_entry_safe_reverse(event, ep, &acpi_gpio->events, node) { diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index d5c14744c127..2017734affaa 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -1474,6 +1474,8 @@ static void gpiochip_irqchip_remove(struct gpio_chip *gpiochip) { unsigned int offset; + acpi_gpiochip_free_interrupts(gpiochip); + /* Remove all IRQ mappings and delete the domain */ if (gpiochip->irqdomain) { for (offset = 0; offset < gpiochip->ngpio; offset++) @@ -1567,6 +1569,8 @@ int gpiochip_irqchip_add(struct gpio_chip *gpiochip, gpiochip->irq_base = irq_base; } + acpi_gpiochip_request_interrupts(gpiochip); + return 0; } EXPORT_SYMBOL_GPL(gpiochip_irqchip_add); diff --git a/drivers/gpio/gpiolib.h b/drivers/gpio/gpiolib.h index cf092941a9fd..3b9ac1ed038c 100644 --- a/drivers/gpio/gpiolib.h +++ b/drivers/gpio/gpiolib.h @@ -29,12 +29,21 @@ struct acpi_gpio_info { void acpi_gpiochip_add(struct gpio_chip *chip); void acpi_gpiochip_remove(struct gpio_chip *chip); +void acpi_gpiochip_request_interrupts(struct gpio_chip *chip); +void acpi_gpiochip_free_interrupts(struct gpio_chip *chip); + struct gpio_desc *acpi_get_gpiod_by_index(struct device *dev, int index, struct acpi_gpio_info *info); #else static inline void acpi_gpiochip_add(struct gpio_chip *chip) { } static inline void acpi_gpiochip_remove(struct gpio_chip *chip) { } +static inline void +acpi_gpiochip_request_interrupts(struct gpio_chip *chip) { } + +static inline void +acpi_gpiochip_free_interrupts(struct gpio_chip *chip) { } + static inline struct gpio_desc * acpi_get_gpiod_by_index(struct device *dev, int index, struct acpi_gpio_info *info)