summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinus Walleij <linus.walleij@linaro.org>2019-08-20 11:05:27 +0300
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2019-09-10 12:35:25 +0300
commit44dfa46aaf7cf594ac89bc1a0c0e56c498b31269 (patch)
tree41ef3017f4804ab3994c9885f35727dbd7103c1f
parent157ec0a3f834ba449a2fa1c1c9075862a614ed52 (diff)
downloadlinux-44dfa46aaf7cf594ac89bc1a0c0e56c498b31269.tar.xz
gpio: Fix irqchip initialization order
[ Upstream commit 48057ed1840fde9239b1e000bea1a0a1f07c5e99 ] The new API for registering a gpio_irq_chip along with a gpio_chip has a different semantic ordering than the old API which added the irqchip explicitly after registering the gpio_chip. Move the calls to add the gpio_irq_chip *last* in the function, so that the different hooks setting up OF and ACPI and machine gpio_chips are called *before* we try to register the interrupts, preserving the elder semantic order. This cropped up in the PL061 driver which used to work fine with no special ACPI quirks, but started to misbehave using the new API. Fixes: e0d897289813 ("gpio: Implement tighter IRQ chip integration") Cc: Thierry Reding <treding@nvidia.com> Cc: Grygorii Strashko <grygorii.strashko@ti.com> Cc: Andy Shevchenko <andy.shevchenko@gmail.com> Reported-by: Wei Xu <xuwei5@hisilicon.com> Tested-by: Wei Xu <xuwei5@hisilicon.com> Reported-by: Andy Shevchenko <andy.shevchenko@gmail.com> Signed-off-by: Linus Walleij <linus.walleij@linaro.org> Link: https://lore.kernel.org/r/20190820080527.11796-1-linus.walleij@linaro.org Signed-off-by: Sasha Levin <sashal@kernel.org>
-rw-r--r--drivers/gpio/gpiolib.c30
1 files changed, 15 insertions, 15 deletions
diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
index 7f9f75201138..f272b5143997 100644
--- a/drivers/gpio/gpiolib.c
+++ b/drivers/gpio/gpiolib.c
@@ -1373,21 +1373,13 @@ int gpiochip_add_data_with_key(struct gpio_chip *chip, void *data,
if (status)
goto err_remove_from_list;
- status = gpiochip_irqchip_init_valid_mask(chip);
- if (status)
- goto err_remove_from_list;
-
status = gpiochip_alloc_valid_mask(chip);
if (status)
- goto err_remove_irqchip_mask;
-
- status = gpiochip_add_irqchip(chip, lock_key, request_key);
- if (status)
- goto err_free_gpiochip_mask;
+ goto err_remove_from_list;
status = of_gpiochip_add(chip);
if (status)
- goto err_remove_chip;
+ goto err_free_gpiochip_mask;
status = gpiochip_init_valid_mask(chip);
if (status)
@@ -1413,6 +1405,14 @@ int gpiochip_add_data_with_key(struct gpio_chip *chip, void *data,
machine_gpiochip_add(chip);
+ status = gpiochip_irqchip_init_valid_mask(chip);
+ if (status)
+ goto err_remove_acpi_chip;
+
+ status = gpiochip_add_irqchip(chip, lock_key, request_key);
+ if (status)
+ goto err_remove_irqchip_mask;
+
/*
* By first adding the chardev, and then adding the device,
* we get a device node entry in sysfs under
@@ -1424,21 +1424,21 @@ int gpiochip_add_data_with_key(struct gpio_chip *chip, void *data,
if (gpiolib_initialized) {
status = gpiochip_setup_dev(gdev);
if (status)
- goto err_remove_acpi_chip;
+ goto err_remove_irqchip;
}
return 0;
+err_remove_irqchip:
+ gpiochip_irqchip_remove(chip);
+err_remove_irqchip_mask:
+ gpiochip_irqchip_free_valid_mask(chip);
err_remove_acpi_chip:
acpi_gpiochip_remove(chip);
err_remove_of_chip:
gpiochip_free_hogs(chip);
of_gpiochip_remove(chip);
-err_remove_chip:
- gpiochip_irqchip_remove(chip);
err_free_gpiochip_mask:
gpiochip_free_valid_mask(chip);
-err_remove_irqchip_mask:
- gpiochip_irqchip_free_valid_mask(chip);
err_remove_from_list:
spin_lock_irqsave(&gpio_lock, flags);
list_del(&gdev->list);