diff mbox series

[1/3] gpio: pseudo: common helper functions for pseudo gpio devices

Message ID 20250217142758.540601-2-koichiro.den@canonical.com
State New
Headers show
Series Introduce gpio-pseudo, common utilities for pseudo GPIO devices | expand

Commit Message

Koichiro Den Feb. 17, 2025, 2:27 p.m. UTC
Both gpio-sim and gpio-virtuser share a mechanism to instantiate a
platform device and wait synchronously for probe completion.
With gpio-aggregator adopting the same approach in a later commit for
its configfs interface, it's time to factor out the common code.

Add gpio-pseudo.[ch] to house helper functions used by all the pseudo
GPIO device implementations.

No functional change.

Signed-off-by: Koichiro Den <koichiro.den@canonical.com>
---
 drivers/gpio/Kconfig       |  4 ++
 drivers/gpio/Makefile      |  1 +
 drivers/gpio/gpio-pseudo.c | 86 ++++++++++++++++++++++++++++++++++++++
 drivers/gpio/gpio-pseudo.h | 24 +++++++++++
 4 files changed, 115 insertions(+)
 create mode 100644 drivers/gpio/gpio-pseudo.c
 create mode 100644 drivers/gpio/gpio-pseudo.h

Comments

Bartosz Golaszewski Feb. 18, 2025, 8:57 a.m. UTC | #1
On Tue, Feb 18, 2025 at 6:01 AM Koichiro Den <koichiro.den@canonical.com> wrote:
>
> On Mon, Feb 17, 2025 at 06:29:27PM GMT, Bartosz Golaszewski wrote:
> > On Mon, Feb 17, 2025 at 5:21 PM Koichiro Den <koichiro.den@canonical.com> wrote:
> > >
> > > On Tue, Feb 18, 2025 at 01:12:17AM GMT, Koichiro Den wrote:
> > > > On Mon, Feb 17, 2025 at 04:46:30PM GMT, Bartosz Golaszewski wrote:
> > > > > On Mon, Feb 17, 2025 at 3:28 PM Koichiro Den <koichiro.den@canonical.com> wrote:
> > > > > >
> > > > > > Both gpio-sim and gpio-virtuser share a mechanism to instantiate a
> > > > > > platform device and wait synchronously for probe completion.
> > > > > > With gpio-aggregator adopting the same approach in a later commit for
> > > > > > its configfs interface, it's time to factor out the common code.
> > > > > >
> > > > > > Add gpio-pseudo.[ch] to house helper functions used by all the pseudo
> > > > > > GPIO device implementations.
> > > > > >
> > > > > > No functional change.
> > > > > >
> > > > > > Signed-off-by: Koichiro Den <koichiro.den@canonical.com>
> > > > > > ---
> > > > >
> > > >
> > > > Thanks for the review.
> > > >
> > > > > Looking at this patch now, I've realized that there is nothing
> > > > > GPIO-specific here. It's a mechanism for synchronous platform device
> > > > > probing. I don't think its place is in drivers/gpio/ if we're making
> > > > > it a set of library functions. Can I suggest moving it to lib/ and
> > > > > renaming the module as pdev_sync_probe or something else that's
> > > > > expressive enough to tell users what it does? You can make me the
> > > > > maintainer of that module if you wish (feel free to add yourself
> > > > > too!).
> > > >
> > > > I had vaguely envisioned that this might eventually contain some
> > > > GPIO-specific code for some reason, and also it's just a tiny utility to
> > > > reduce code duplication, which is why I placed it in the neighborhood,
> > > > drivers/gpio/. However, of course you’re right, there’s nothing
> > > > GPIO-specific here, so moving it to lib/ makes sense.
> > > >
> > > > I'm not really sure if this method for synchronous platform device probing
> > > > can be broadly accepted as a general solution, but I have no objections to
> > > > making the change. I'll move it as you suggested and send v2, setting you
> > > > as its maintainer.
> > >
> > > Regarding this series, I feel that it might make discussions smoother if
> > > you submit it directly. So if you're okay with it, please go ahead. In
> > > that case, there's even no need to mention me or CC me - I can track it on
> > > ML :)
> >
> > I'm not sure I'm following. Why would I submit it myself? You did most
> > of the work already. If you want the changes to gpio-aggregator
> > merged, then I think that it's time to refactor this code before we do
> > that because repeating it three times is just bad programming. I
> > probably wouldn't have done it otherwise at this point.
>
> As I mentioned earlier, I'm not really sure if this particular usage of
> platform devices will be generally acceptable. gpio-pseudo was intended
> solely to reduce code duplication in methods already accepted by the GPIO
> subsystem. Moving it to lib/ would shift the approach, effectively trying
> to promote this method as a standard solution.
>

Promote it as a solution for this specific use-case - the need to
probe "faux" platform devices synchonously.

> For example, if for any reason drivers_autoprobe is set to 0 on the
> platform bus, the synchronous mechanism might be blocked indefinitely.
> Moreover, in the first place, I'm not sure whether employing the platform
> bus in this way is appropriate.
>

It's sketchy, I know. Back in the day I was advised by Greg to use the
auxiliary bus but I realized very fast that if I want to support
device-tree too, then I would end up reimplementing all the code that
already exists for supporting the platform bus. He eventually agreed
that it's better to use the platform bus. We had the same issue with
PCI pwrctrl recently and also ended up using the platform bus.

> For drivers like gpio-virtuser, which we can define virtual GPIO consumers
> via DT, or for gpio-aggregator, which we can use as a generic GPIO driver,
> the expectation is to use the platform bus/device mechanism as usual. In
> those cases, adding a synchronous mechanism via the platform bus notifier
> to piggyback on the existing platform bus probe implementation is
> understandable and obviously has already been accepted in the GPIO
> subsystem. However, moving just the synchronous mechanism into lib/ can
> potentially be perceived as an abuse of the platform device concept?

That's actually a good point. I guess this code could be reworked to
work with any bus (that would be specified by the user).

>
> Incidentally, Greg K-H’s faux bus work was recently merged into mainline:
> commit 35fa2d88ca94 ("driver core: add a faux bus for use when a simple
> device/bus is needed").
>

Thanks for bringing this to my attention, I wasn't aware this existed.
However it's not useful here - I still want to support OF.

> Correct me where I'm wrong. And I'd appreciate if you could share your
> thoughts.
>

I don't want to block the aggregator work but I also don't want to
have code triplication under drivers/gpio/. Let's do the following: I
don't like the sound of the word "gpio-pseudo" in this context. Let's
keep it under drivers/gpio/ but rename the module already to
"dev-sync-probe.c" and use the
dev_sync_probe_init/register/unregister/data naming scheme. Stick to
supporting platform devices exclusively for now. I don't have the time
just yet but maybe in the next release cycle, I'll try to make it more
generic (work for all device types) and move it out of drivers/gpio/.
How does it sound?

Bartosz

> Koichiro
>
> >
> > The code looks good other than that, just put it under lib/, rename
> > functions to pdev_sync_probe_init/register/unregister() and send it to
> > the list as usual. With that it's good to go. Just make sure to
> > mention to Andrew Morton the need for this to go through the GPIO
> > tree, I don't think he'll mind.
> >
> > Bart
Koichiro Den Feb. 18, 2025, 12:58 p.m. UTC | #2
On Tue, Feb 18, 2025 at 09:57:05AM GMT, Bartosz Golaszewski wrote:
> On Tue, Feb 18, 2025 at 6:01 AM Koichiro Den <koichiro.den@canonical.com> wrote:
> >
> > On Mon, Feb 17, 2025 at 06:29:27PM GMT, Bartosz Golaszewski wrote:
> > > On Mon, Feb 17, 2025 at 5:21 PM Koichiro Den <koichiro.den@canonical.com> wrote:
> > > >
> > > > On Tue, Feb 18, 2025 at 01:12:17AM GMT, Koichiro Den wrote:
> > > > > On Mon, Feb 17, 2025 at 04:46:30PM GMT, Bartosz Golaszewski wrote:
> > > > > > On Mon, Feb 17, 2025 at 3:28 PM Koichiro Den <koichiro.den@canonical.com> wrote:
> > > > > > >
> > > > > > > Both gpio-sim and gpio-virtuser share a mechanism to instantiate a
> > > > > > > platform device and wait synchronously for probe completion.
> > > > > > > With gpio-aggregator adopting the same approach in a later commit for
> > > > > > > its configfs interface, it's time to factor out the common code.
> > > > > > >
> > > > > > > Add gpio-pseudo.[ch] to house helper functions used by all the pseudo
> > > > > > > GPIO device implementations.
> > > > > > >
> > > > > > > No functional change.
> > > > > > >
> > > > > > > Signed-off-by: Koichiro Den <koichiro.den@canonical.com>
> > > > > > > ---
> > > > > >
> > > > >
> > > > > Thanks for the review.
> > > > >
> > > > > > Looking at this patch now, I've realized that there is nothing
> > > > > > GPIO-specific here. It's a mechanism for synchronous platform device
> > > > > > probing. I don't think its place is in drivers/gpio/ if we're making
> > > > > > it a set of library functions. Can I suggest moving it to lib/ and
> > > > > > renaming the module as pdev_sync_probe or something else that's
> > > > > > expressive enough to tell users what it does? You can make me the
> > > > > > maintainer of that module if you wish (feel free to add yourself
> > > > > > too!).
> > > > >
> > > > > I had vaguely envisioned that this might eventually contain some
> > > > > GPIO-specific code for some reason, and also it's just a tiny utility to
> > > > > reduce code duplication, which is why I placed it in the neighborhood,
> > > > > drivers/gpio/. However, of course you’re right, there’s nothing
> > > > > GPIO-specific here, so moving it to lib/ makes sense.
> > > > >
> > > > > I'm not really sure if this method for synchronous platform device probing
> > > > > can be broadly accepted as a general solution, but I have no objections to
> > > > > making the change. I'll move it as you suggested and send v2, setting you
> > > > > as its maintainer.
> > > >
> > > > Regarding this series, I feel that it might make discussions smoother if
> > > > you submit it directly. So if you're okay with it, please go ahead. In
> > > > that case, there's even no need to mention me or CC me - I can track it on
> > > > ML :)
> > >
> > > I'm not sure I'm following. Why would I submit it myself? You did most
> > > of the work already. If you want the changes to gpio-aggregator
> > > merged, then I think that it's time to refactor this code before we do
> > > that because repeating it three times is just bad programming. I
> > > probably wouldn't have done it otherwise at this point.
> >
> > As I mentioned earlier, I'm not really sure if this particular usage of
> > platform devices will be generally acceptable. gpio-pseudo was intended
> > solely to reduce code duplication in methods already accepted by the GPIO
> > subsystem. Moving it to lib/ would shift the approach, effectively trying
> > to promote this method as a standard solution.
> >
> 
> Promote it as a solution for this specific use-case - the need to
> probe "faux" platform devices synchonously.

I think we're on the same page.

> 
> > For example, if for any reason drivers_autoprobe is set to 0 on the
> > platform bus, the synchronous mechanism might be blocked indefinitely.
> > Moreover, in the first place, I'm not sure whether employing the platform
> > bus in this way is appropriate.
> >
> 
> It's sketchy, I know. Back in the day I was advised by Greg to use the
> auxiliary bus but I realized very fast that if I want to support
> device-tree too, then I would end up reimplementing all the code that
> already exists for supporting the platform bus. He eventually agreed
> that it's better to use the platform bus. We had the same issue with
> PCI pwrctrl recently and also ended up using the platform bus.

Thanks for sharing the background history. My view/feeling remains unchanged.

> 
> > For drivers like gpio-virtuser, which we can define virtual GPIO consumers
> > via DT, or for gpio-aggregator, which we can use as a generic GPIO driver,
> > the expectation is to use the platform bus/device mechanism as usual. In
> > those cases, adding a synchronous mechanism via the platform bus notifier
> > to piggyback on the existing platform bus probe implementation is
> > understandable and obviously has already been accepted in the GPIO
> > subsystem. However, moving just the synchronous mechanism into lib/ can
> > potentially be perceived as an abuse of the platform device concept?
> 
> That's actually a good point. I guess this code could be reworked to
> work with any bus (that would be specified by the user).

Alright.

> 
> >
> > Incidentally, Greg K-H’s faux bus work was recently merged into mainline:
> > commit 35fa2d88ca94 ("driver core: add a faux bus for use when a simple
> > device/bus is needed").
> >
> 
> Thanks for bringing this to my attention, I wasn't aware this existed.
> However it's not useful here - I still want to support OF.

I have no intention of dropping the current OF support, as I wrote in my
last email like ".. understandable and obviously has already been accepted
..". In that sense, I think we're on the same page here as well.

> 
> > Correct me where I'm wrong. And I'd appreciate if you could share your
> > thoughts.
> >
> 
> I don't want to block the aggregator work but I also don't want to
> have code triplication under drivers/gpio/. Let's do the following: I
> don't like the sound of the word "gpio-pseudo" in this context. Let's
> keep it under drivers/gpio/ but rename the module already to
> "dev-sync-probe.c" and use the
> dev_sync_probe_init/register/unregister/data naming scheme. Stick to
> supporting platform devices exclusively for now. [...]

I totally agree with "dev-sync-probe" and the overall idea. Thanks for the
suggestion. I'll send v2 later.

> [...] I don't have the time
> just yet but maybe in the next release cycle, I'll try to make it more
> generic (work for all device types) and move it out of drivers/gpio/.
> How does it sound?

Although I'm not sure whether there are many justifiable demand for such
generic lib, probably that's just because I don't know relevant topics.

Thanks,

Koichiro

> 
> Bartosz
> 
> > Koichiro
> >
> > >
> > > The code looks good other than that, just put it under lib/, rename
> > > functions to pdev_sync_probe_init/register/unregister() and send it to
> > > the list as usual. With that it's good to go. Just make sure to
> > > mention to Andrew Morton the need for this to go through the GPIO
> > > tree, I don't think he'll mind.
> > >
> > > Bart
Geert Uytterhoeven Feb. 18, 2025, 1:24 p.m. UTC | #3
Hi Den-san,

On Mon, 17 Feb 2025 at 15:28, Koichiro Den <koichiro.den@canonical.com> wrote:
> Both gpio-sim and gpio-virtuser share a mechanism to instantiate a
> platform device and wait synchronously for probe completion.
> With gpio-aggregator adopting the same approach in a later commit for
> its configfs interface, it's time to factor out the common code.
>
> Add gpio-pseudo.[ch] to house helper functions used by all the pseudo
> GPIO device implementations.
>
> No functional change.
>
> Signed-off-by: Koichiro Den <koichiro.den@canonical.com>

Thanks for your patch!

> --- /dev/null
> +++ b/drivers/gpio/gpio-pseudo.c

> +int pseudo_gpio_register(struct pseudo_gpio_common *common,
> +                        struct platform_device_info *pdevinfo)
> +{
> +       struct platform_device *pdev;
> +       char *name;
> +
> +       name = kasprintf(GFP_KERNEL, "%s.%u", pdevinfo->name, pdevinfo->id);
> +       if (!name)
> +               return -ENOMEM;
> +
> +       common->driver_bound = false;
> +       common->name = name;
> +       reinit_completion(&common->probe_completion);
> +       bus_register_notifier(&platform_bus_type, &common->bus_notifier);
> +
> +       pdev = platform_device_register_full(pdevinfo);
> +       if (IS_ERR(pdev)) {
> +               bus_unregister_notifier(&platform_bus_type, &common->bus_notifier);
> +               kfree(common->name);

On arm32:
error: implicit declaration of function ‘kfree’

Adding #include <linux/slab.h> fixes that.
Probably you want to include a few more, to avoid relying on
implicit includes.


Gr{oetje,eeting}s,

                        Geert
Koichiro Den Feb. 18, 2025, 2:44 p.m. UTC | #4
On Tue, Feb 18, 2025 at 02:24:32PM GMT, Geert Uytterhoeven wrote:
> Hi Den-san,
> 
> On Mon, 17 Feb 2025 at 15:28, Koichiro Den <koichiro.den@canonical.com> wrote:
> > Both gpio-sim and gpio-virtuser share a mechanism to instantiate a
> > platform device and wait synchronously for probe completion.
> > With gpio-aggregator adopting the same approach in a later commit for
> > its configfs interface, it's time to factor out the common code.
> >
> > Add gpio-pseudo.[ch] to house helper functions used by all the pseudo
> > GPIO device implementations.
> >
> > No functional change.
> >
> > Signed-off-by: Koichiro Den <koichiro.den@canonical.com>
> 
> Thanks for your patch!
> 
> > --- /dev/null
> > +++ b/drivers/gpio/gpio-pseudo.c
> 
> > +int pseudo_gpio_register(struct pseudo_gpio_common *common,
> > +                        struct platform_device_info *pdevinfo)
> > +{
> > +       struct platform_device *pdev;
> > +       char *name;
> > +
> > +       name = kasprintf(GFP_KERNEL, "%s.%u", pdevinfo->name, pdevinfo->id);
> > +       if (!name)
> > +               return -ENOMEM;
> > +
> > +       common->driver_bound = false;
> > +       common->name = name;
> > +       reinit_completion(&common->probe_completion);
> > +       bus_register_notifier(&platform_bus_type, &common->bus_notifier);
> > +
> > +       pdev = platform_device_register_full(pdevinfo);
> > +       if (IS_ERR(pdev)) {
> > +               bus_unregister_notifier(&platform_bus_type, &common->bus_notifier);
> > +               kfree(common->name);
> 
> On arm32:
> error: implicit declaration of function ‘kfree’
> 
> Adding #include <linux/slab.h> fixes that.
> Probably you want to include a few more, to avoid relying on
> implicit includes.

Thank you for pointing that out!

Koichiro

> 
> 
> Gr{oetje,eeting}s,
> 
>                         Geert
> 
> -- 
> Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org
> 
> In personal conversations with technical people, I call myself a hacker. But
> when I'm talking to journalists I just say "programmer" or something like that.
>                                 -- Linus Torvalds
diff mbox series

Patch

diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index 56c1f30ac195..1e2c95e03a95 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -1863,6 +1863,10 @@  config GPIO_MPSSE
 
 endmenu
 
+# This symbol is selected by some pseudo gpio device implementations
+config GPIO_PSEUDO
+	bool
+
 menu "Virtual GPIO drivers"
 
 config GPIO_AGGREGATOR
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
index af3ba4d81b58..5eb54147a1ab 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -136,6 +136,7 @@  obj-$(CONFIG_GPIO_PISOSR)		+= gpio-pisosr.o
 obj-$(CONFIG_GPIO_PL061)		+= gpio-pl061.o
 obj-$(CONFIG_GPIO_PMIC_EIC_SPRD)	+= gpio-pmic-eic-sprd.o
 obj-$(CONFIG_GPIO_POLARFIRE_SOC)	+= gpio-mpfs.o
+obj-$(CONFIG_GPIO_PSEUDO)		+= gpio-pseudo.o
 obj-$(CONFIG_GPIO_PXA)			+= gpio-pxa.o
 obj-$(CONFIG_GPIO_RASPBERRYPI_EXP)	+= gpio-raspberrypi-exp.o
 obj-$(CONFIG_GPIO_RC5T583)		+= gpio-rc5t583.o
diff --git a/drivers/gpio/gpio-pseudo.c b/drivers/gpio/gpio-pseudo.c
new file mode 100644
index 000000000000..6e3da05440d8
--- /dev/null
+++ b/drivers/gpio/gpio-pseudo.c
@@ -0,0 +1,86 @@ 
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Helper functions for Pseudo GPIOs
+ *
+ * Copyright 2025 Canonical Ltd.
+ */
+
+#include "gpio-pseudo.h"
+
+static int pseudo_gpio_notifier_call(struct notifier_block *nb,
+				     unsigned long action,
+				     void *data)
+{
+	struct pseudo_gpio_common *common;
+	struct device *dev = data;
+
+	common = container_of(nb, struct pseudo_gpio_common, bus_notifier);
+	if (!device_match_name(dev, common->name))
+		return NOTIFY_DONE;
+
+	switch (action) {
+	case BUS_NOTIFY_BOUND_DRIVER:
+		common->driver_bound = true;
+		break;
+	case BUS_NOTIFY_DRIVER_NOT_BOUND:
+		common->driver_bound = false;
+		break;
+	default:
+		return NOTIFY_DONE;
+	}
+
+	complete(&common->probe_completion);
+	return NOTIFY_OK;
+}
+
+void pseudo_gpio_init(struct pseudo_gpio_common *common)
+{
+	memset(common, 0, sizeof(*common));
+	init_completion(&common->probe_completion);
+	common->bus_notifier.notifier_call = pseudo_gpio_notifier_call;
+}
+EXPORT_SYMBOL_GPL(pseudo_gpio_init);
+
+int pseudo_gpio_register(struct pseudo_gpio_common *common,
+			 struct platform_device_info *pdevinfo)
+{
+	struct platform_device *pdev;
+	char *name;
+
+	name = kasprintf(GFP_KERNEL, "%s.%u", pdevinfo->name, pdevinfo->id);
+	if (!name)
+		return -ENOMEM;
+
+	common->driver_bound = false;
+	common->name = name;
+	reinit_completion(&common->probe_completion);
+	bus_register_notifier(&platform_bus_type, &common->bus_notifier);
+
+	pdev = platform_device_register_full(pdevinfo);
+	if (IS_ERR(pdev)) {
+		bus_unregister_notifier(&platform_bus_type, &common->bus_notifier);
+		kfree(common->name);
+		return PTR_ERR(pdev);
+	}
+
+	wait_for_completion(&common->probe_completion);
+	bus_unregister_notifier(&platform_bus_type, &common->bus_notifier);
+
+	if (!common->driver_bound) {
+		platform_device_unregister(pdev);
+		kfree(common->name);
+		return -ENXIO;
+	}
+
+	common->pdev = pdev;
+	return 0;
+}
+EXPORT_SYMBOL_GPL(pseudo_gpio_register);
+
+void pseudo_gpio_unregister(struct pseudo_gpio_common *common)
+{
+	platform_device_unregister(common->pdev);
+	kfree(common->name);
+	common->pdev = NULL;
+}
+EXPORT_SYMBOL_GPL(pseudo_gpio_unregister);
diff --git a/drivers/gpio/gpio-pseudo.h b/drivers/gpio/gpio-pseudo.h
new file mode 100644
index 000000000000..093112b6cce5
--- /dev/null
+++ b/drivers/gpio/gpio-pseudo.h
@@ -0,0 +1,24 @@ 
+/* SPDX-License-Identifier: GPL-2.0 */
+
+#ifndef GPIO_PSEUDO_H
+#define GPIO_PSEUDO_H
+
+#include <linux/completion.h>
+#include <linux/platform_device.h>
+
+struct pseudo_gpio_common {
+	struct platform_device *pdev;
+	const char *name;
+
+	/* Synchronize with probe */
+	struct notifier_block bus_notifier;
+	struct completion probe_completion;
+	bool driver_bound;
+};
+
+void pseudo_gpio_init(struct pseudo_gpio_common *common);
+int pseudo_gpio_register(struct pseudo_gpio_common *common,
+			 struct platform_device_info *pdevinfo);
+void pseudo_gpio_unregister(struct pseudo_gpio_common *common);
+
+#endif /* GPIO_PSEUDO_H */