Commit 34551358 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge tag 'gpio-fixes-for-v6.8-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/brgl/linux

Pull gpio fixes from Bartosz Golaszewski:
 "Apart from some regular driver fixes there's a relatively big revert
  of the locking changes that were introduced to GPIOLIB in this merge
  window.

  This is because it turned out that some legacy GPIO interfaces - that
  need to translate a number from the global GPIO numberspace to the
  address of the relevant descriptor, thus running a GPIO device lookup
  and taking the GPIO device list lock - are still used in old code from
  atomic context resulting in "scheduling while atomic" errors.

  I'll try to make the read-only part of the list access entirely
  lockless using SRCU but this will take some time so let's go back to
  the old global spinlock for now.

  Summary:

   - revert the changes aiming to use a read-write semaphore to protect
     the list of GPIO devices due to calls to legacy API taking that
     lock from atomic context in old code

   - fix inverted logic in DEFINE_FREE() for GPIO device references

   - check the return value of bgpio_init() in gpio-mlxbf3

   - fix node address in the DT bindings example for gpio-xilinx

   - fix signedness bug in gpio-rtd

   - fix kernel-doc warnings in gpio-en7523"

* tag 'gpio-fixes-for-v6.8-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/brgl/linux:
  gpiolib: revert the attempt to protect the GPIO device list with an rwsem
  gpio: EN7523: fix kernel-doc warnings
  gpiolib: Fix scope-based gpio_device refcounting
  gpio: mlxbf3: add an error code check in mlxbf3_gpio_probe
  dt-bindings: gpio: xilinx: Fix node address in gpio
  gpio: rtd: Fix signedness bug in probe
parents 5c935069 efb8235b
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -126,7 +126,7 @@ examples:
  - |
    #include <dt-bindings/interrupt-controller/arm-gic.h>

        gpio@e000a000 {
        gpio@a0020000 {
            compatible = "xlnx,xps-gpio-1.00.a";
            reg = <0xa0020000 0x10000>;
            #gpio-cells = <2>;
+3 −3
Original line number Diff line number Diff line
@@ -12,11 +12,11 @@
#define AIROHA_GPIO_MAX		32

/**
 * airoha_gpio_ctrl - Airoha GPIO driver data
 * struct airoha_gpio_ctrl - Airoha GPIO driver data
 * @gc: Associated gpio_chip instance.
 * @data: The data register.
 * @dir0: The direction register for the lower 16 pins.
 * @dir1: The direction register for the higher 16 pins.
 * @dir: [0] The direction register for the lower 16 pins.
 * [1]: The direction register for the higher 16 pins.
 * @output: The output enable register.
 */
struct airoha_gpio_ctrl {
+2 −0
Original line number Diff line number Diff line
@@ -215,6 +215,8 @@ static int mlxbf3_gpio_probe(struct platform_device *pdev)
			gs->gpio_clr_io + MLXBF_GPIO_FW_DATA_OUT_CLEAR,
			gs->gpio_set_io + MLXBF_GPIO_FW_OUTPUT_ENABLE_SET,
			gs->gpio_clr_io + MLXBF_GPIO_FW_OUTPUT_ENABLE_CLEAR, 0);
	if (ret)
		return dev_err_probe(dev, ret, "%s: bgpio_init() failed", __func__);

	gc->request = gpiochip_generic_request;
	gc->free = gpiochip_generic_free;
+9 −6
Original line number Diff line number Diff line
@@ -525,18 +525,21 @@ static int rtd_gpio_probe(struct platform_device *pdev)
	struct device *dev = &pdev->dev;
	struct gpio_irq_chip *irq_chip;
	struct rtd_gpio *data;
	int ret;

	data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
	if (!data)
		return -ENOMEM;

	data->irqs[0] = platform_get_irq(pdev, 0);
	if (data->irqs[0] < 0)
		return data->irqs[0];
	ret = platform_get_irq(pdev, 0);
	if (ret < 0)
		return ret;
	data->irqs[0] = ret;

	data->irqs[1] = platform_get_irq(pdev, 1);
	if (data->irqs[1] < 0)
		return data->irqs[1];
	ret = platform_get_irq(pdev, 1);
	if (ret < 0)
		return ret;
	data->irqs[1] = ret;

	data->info = device_get_match_data(dev);
	if (!data->info)
+24 −21
Original line number Diff line number Diff line
@@ -768,25 +768,6 @@ int gpiochip_sysfs_register(struct gpio_device *gdev)
	return 0;
}

int gpiochip_sysfs_register_all(void)
{
	struct gpio_device *gdev;
	int ret;

	guard(rwsem_read)(&gpio_devices_sem);

	list_for_each_entry(gdev, &gpio_devices, list) {
		if (gdev->mockdev)
			continue;

		ret = gpiochip_sysfs_register(gdev);
		if (ret)
			return ret;
	}

	return 0;
}

void gpiochip_sysfs_unregister(struct gpio_device *gdev)
{
	struct gpio_desc *desc;
@@ -812,6 +793,8 @@ void gpiochip_sysfs_unregister(struct gpio_device *gdev)
static int __init gpiolib_sysfs_init(void)
{
	int		status;
	unsigned long	flags;
	struct gpio_device *gdev;

	status = class_register(&gpio_class);
	if (status < 0)
@@ -823,6 +806,26 @@ static int __init gpiolib_sysfs_init(void)
	 * We run before arch_initcall() so chip->dev nodes can have
	 * registered, and so arch_initcall() can always gpiod_export().
	 */
	return gpiochip_sysfs_register_all();
	spin_lock_irqsave(&gpio_lock, flags);
	list_for_each_entry(gdev, &gpio_devices, list) {
		if (gdev->mockdev)
			continue;

		/*
		 * TODO we yield gpio_lock here because
		 * gpiochip_sysfs_register() acquires a mutex. This is unsafe
		 * and needs to be fixed.
		 *
		 * Also it would be nice to use gpio_device_find() here so we
		 * can keep gpio_chips local to gpiolib.c, but the yield of
		 * gpio_lock prevents us from doing this.
		 */
		spin_unlock_irqrestore(&gpio_lock, flags);
		status = gpiochip_sysfs_register(gdev);
		spin_lock_irqsave(&gpio_lock, flags);
	}
	spin_unlock_irqrestore(&gpio_lock, flags);

	return status;
}
postcore_initcall(gpiolib_sysfs_init);
Loading