Commit 52176d0d authored by Johan Hovold's avatar Johan Hovold Committed by Linus Walleij

gpio: sysfs: fix redundant lock-as-irq handling

Drivers should call gpiochip_lock_as_irq (which prevents the pin
direction from being changed) in their irq_request_resources callbacks
but some drivers currently fail to do so.

Instead a second, explicit and often redundant call to lock-as-irq is
made by the sysfs-interface implementation after an irq has been
requested.

Move the explicit call before the irq-request to match the unlock done
after the irq is later released. Note that this also fixes an irq leak,
should the explicit call ever have failed.

Also add a comment about removing the redundant call once the broken
drivers have been fixed.
Signed-off-by: default avatarJohan Hovold <johan@kernel.org>
Reviewed-by: default avatarAlexandre Courbot <acourbot@nvidia.com>
Signed-off-by: default avatarLinus Walleij <linus.walleij@linaro.org>
parent fab28b89
...@@ -195,20 +195,28 @@ static int gpio_setup_irq(struct gpio_desc *desc, struct device *dev, ...@@ -195,20 +195,28 @@ static int gpio_setup_irq(struct gpio_desc *desc, struct device *dev,
} }
} }
ret = request_any_context_irq(irq, gpio_sysfs_irq, irq_flags, /*
"gpiolib", value_sd); * FIXME: This should be done in the irq_request_resources callback
* when the irq is requested, but a few drivers currently fail
* to do so.
*
* Remove this redundant call (along with the corresponding
* unlock) when those drivers have been fixed.
*/
ret = gpiochip_lock_as_irq(desc->chip, gpio_chip_hwgpio(desc));
if (ret < 0) if (ret < 0)
goto free_id; goto free_id;
ret = gpiochip_lock_as_irq(desc->chip, gpio_chip_hwgpio(desc)); ret = request_any_context_irq(irq, gpio_sysfs_irq, irq_flags,
if (ret < 0) { "gpiolib", value_sd);
gpiod_warn(desc, "failed to flag the GPIO for IRQ\n"); if (ret < 0)
goto free_id; goto err_unlock;
}
desc->flags |= gpio_flags; desc->flags |= gpio_flags;
return 0; return 0;
err_unlock:
gpiochip_unlock_as_irq(desc->chip, gpio_chip_hwgpio(desc));
free_id: free_id:
idr_remove(&dirent_idr, id); idr_remove(&dirent_idr, id);
desc->flags &= GPIO_FLAGS_MASK; desc->flags &= GPIO_FLAGS_MASK;
......
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