Commit 48057ed1 authored by Linus Walleij's avatar Linus Walleij

gpio: Fix irqchip initialization order

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: e0d89728 ("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: default avatarWei Xu <xuwei5@hisilicon.com>
Tested-by: default avatarWei Xu <xuwei5@hisilicon.com>
Reported-by: default avatarAndy Shevchenko <andy.shevchenko@gmail.com>
Signed-off-by: default avatarLinus Walleij <linus.walleij@linaro.org>
Link: https://lore.kernel.org/r/20190820080527.11796-1-linus.walleij@linaro.org
parent df451f83
...@@ -1373,21 +1373,13 @@ int gpiochip_add_data_with_key(struct gpio_chip *chip, void *data, ...@@ -1373,21 +1373,13 @@ int gpiochip_add_data_with_key(struct gpio_chip *chip, void *data,
if (status) if (status)
goto err_remove_from_list; 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); status = gpiochip_alloc_valid_mask(chip);
if (status) if (status)
goto err_remove_irqchip_mask; goto err_remove_from_list;
status = gpiochip_add_irqchip(chip, lock_key, request_key);
if (status)
goto err_free_gpiochip_mask;
status = of_gpiochip_add(chip); status = of_gpiochip_add(chip);
if (status) if (status)
goto err_remove_chip; goto err_free_gpiochip_mask;
status = gpiochip_init_valid_mask(chip); status = gpiochip_init_valid_mask(chip);
if (status) if (status)
...@@ -1413,6 +1405,14 @@ int gpiochip_add_data_with_key(struct gpio_chip *chip, void *data, ...@@ -1413,6 +1405,14 @@ int gpiochip_add_data_with_key(struct gpio_chip *chip, void *data,
machine_gpiochip_add(chip); 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, * By first adding the chardev, and then adding the device,
* we get a device node entry in sysfs under * 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, ...@@ -1424,21 +1424,21 @@ int gpiochip_add_data_with_key(struct gpio_chip *chip, void *data,
if (gpiolib_initialized) { if (gpiolib_initialized) {
status = gpiochip_setup_dev(gdev); status = gpiochip_setup_dev(gdev);
if (status) if (status)
goto err_remove_acpi_chip; goto err_remove_irqchip;
} }
return 0; return 0;
err_remove_irqchip:
gpiochip_irqchip_remove(chip);
err_remove_irqchip_mask:
gpiochip_irqchip_free_valid_mask(chip);
err_remove_acpi_chip: err_remove_acpi_chip:
acpi_gpiochip_remove(chip); acpi_gpiochip_remove(chip);
err_remove_of_chip: err_remove_of_chip:
gpiochip_free_hogs(chip); gpiochip_free_hogs(chip);
of_gpiochip_remove(chip); of_gpiochip_remove(chip);
err_remove_chip:
gpiochip_irqchip_remove(chip);
err_free_gpiochip_mask: err_free_gpiochip_mask:
gpiochip_free_valid_mask(chip); gpiochip_free_valid_mask(chip);
err_remove_irqchip_mask:
gpiochip_irqchip_free_valid_mask(chip);
err_remove_from_list: err_remove_from_list:
spin_lock_irqsave(&gpio_lock, flags); spin_lock_irqsave(&gpio_lock, flags);
list_del(&gdev->list); list_del(&gdev->list);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment