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: e0d8972898 ("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
This commit is contained in:
Linus Walleij 2019-08-20 10:05:27 +02:00
parent df451f83e1
commit 48057ed184
1 changed files with 15 additions and 15 deletions

View File

@ -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);
status = gpiochip_alloc_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;
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);