Commit 8f43640c authored by Linus Torvalds's avatar Linus Torvalds
Browse files

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

Pull gpio fixes from Bartosz Golaszewski:

 - fix resource handling in gpio-tegra186

 - fix wakeup source leaks in gpio-mpc8xxx and gpio-zynq

 - fix minor issues with some GPIO OF quirks

 - deprecate GPIOD_FLAGS_BIT_NONEXCLUSIVE and devm_gpiod_unhinge()
   symbols and add a TODO task to track replacing them with a better
   solution

* tag 'gpio-fixes-for-v6.15-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/brgl/linux:
  gpiolib: of: Move Atmel HSMCI quirk up out of the regulator comment
  gpiolib: of: Fix the choice for Ingenic NAND quirk
  gpio: zynq: Fix wakeup source leaks on device unbind
  gpio: mpc8xxx: Fix wakeup source leaks on device unbind
  gpio: TODO: track the removal of regulator-related workarounds
  MAINTAINERS: add more keywords for the GPIO subsystem entry
  gpio: deprecate devm_gpiod_unhinge()
  gpio: deprecate the GPIOD_FLAGS_BIT_NONEXCLUSIVE flag
  gpio: tegra186: fix resource handling in ACPI probe path
parents b4991c01 b8c7a1ac
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -10151,6 +10151,8 @@ F: include/linux/gpio.h
F:	include/linux/gpio/
F:	include/linux/of_gpio.h
K:	(devm_)?gpio_(request|free|direction|get|set)
K:	GPIOD_FLAGS_BIT_NONEXCLUSIVE
K:	devm_gpiod_unhinge
GPIO UAPI
M:	Bartosz Golaszewski <brgl@bgdev.pl>
+34 −0
Original line number Diff line number Diff line
@@ -186,3 +186,37 @@ their hardware offsets within the chip.

Encourage users to switch to using them and eventually remove the existing
global export/unexport attribues.

-------------------------------------------------------------------------------

Remove GPIOD_FLAGS_BIT_NONEXCLUSIVE

GPIOs in the linux kernel are meant to be an exclusive resource. This means
that the GPIO descriptors (the software representation of the hardware concept)
are not reference counted and - in general - only one user at a time can
request a GPIO line and control its settings. The consumer API is designed
around full control of the line's state as evidenced by the fact that, for
instance, gpiod_set_value() does indeed drive the line as requested, instead
of bumping an enable counter of some sort.

A problematic use-case for GPIOs is when two consumers want to use the same
descriptor independently. An example of such a user is the regulator subsystem
which may instantiate several struct regulator_dev instances containing
a struct device but using the same enable GPIO line.

A workaround was introduced in the form of the GPIOD_FLAGS_BIT_NONEXCLUSIVE
flag but its implementation is problematic: it does not provide any
synchronization of usage nor did it introduce any enable count meaning the
non-exclusive users of the same descriptor will in fact "fight" for the
control over it. This flag should be removed and replaced with a better
solution, possibly based on the new power sequencing subsystem.

-------------------------------------------------------------------------------

Remove devm_gpiod_unhinge()

devm_gpiod_unhinge() is provided as a way to transfer the ownership of managed
enable GPIOs to the regulator core. Rather than doing that however, we should
make it possible for the regulator subsystem to deal with GPIO resources the
lifetime of which it doesn't control as logically, a GPIO obtained by a caller
should also be freed by it.
+3 −1
Original line number Diff line number Diff line
@@ -410,7 +410,9 @@ static int mpc8xxx_probe(struct platform_device *pdev)
		goto err;
	}

	device_init_wakeup(dev, true);
	ret = devm_device_init_wakeup(dev);
	if (ret)
		return dev_err_probe(dev, ret, "Failed to init wakeup\n");

	return 0;
err:
+14 −13
Original line number Diff line number Diff line
@@ -823,6 +823,7 @@ static int tegra186_gpio_probe(struct platform_device *pdev)
	struct gpio_irq_chip *irq;
	struct tegra_gpio *gpio;
	struct device_node *np;
	struct resource *res;
	char **names;
	int err;

@@ -842,19 +843,19 @@ static int tegra186_gpio_probe(struct platform_device *pdev)
	gpio->num_banks++;

	/* get register apertures */
	gpio->secure = devm_platform_ioremap_resource_byname(pdev, "security");
	if (IS_ERR(gpio->secure)) {
		gpio->secure = devm_platform_ioremap_resource(pdev, 0);
	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "security");
	if (!res)
		res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	gpio->secure = devm_ioremap_resource(&pdev->dev, res);
	if (IS_ERR(gpio->secure))
		return PTR_ERR(gpio->secure);
	}

	gpio->base = devm_platform_ioremap_resource_byname(pdev, "gpio");
	if (IS_ERR(gpio->base)) {
		gpio->base = devm_platform_ioremap_resource(pdev, 1);
	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "gpio");
	if (!res)
		res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
	gpio->base = devm_ioremap_resource(&pdev->dev, res);
	if (IS_ERR(gpio->base))
		return PTR_ERR(gpio->base);
	}

	err = platform_irq_count(pdev);
	if (err < 0)
+1 −0
Original line number Diff line number Diff line
@@ -1011,6 +1011,7 @@ static void zynq_gpio_remove(struct platform_device *pdev)
	ret = pm_runtime_get_sync(&pdev->dev);
	if (ret < 0)
		dev_warn(&pdev->dev, "pm_runtime_get_sync() Failed\n");
	device_init_wakeup(&pdev->dev, 0);
	gpiochip_remove(&gpio->chip);
	device_set_wakeup_capable(&pdev->dev, 0);
	pm_runtime_disable(&pdev->dev);
Loading