linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] gpio: Add device link support
@ 2019-06-21 15:23 Thierry Reding
  2019-06-24 22:34 ` Linus Walleij
  0 siblings, 1 reply; 2+ messages in thread
From: Thierry Reding @ 2019-06-21 15:23 UTC (permalink / raw)
  To: Linus Walleij, Bartosz Golaszewski; +Cc: linux-gpio, linux-kernel

From: Thierry Reding <treding@nvidia.com>

Create a device link between a GPIO consumer and the GPIO supplier (i.e.
the GPIO chip's parent). This makes the driver core aware of the
dependency between the two devices so that it can properly order the
suspend/resume sequence.

As a side-effect the GPIO consumer will be force unloaded when the GPIO
supplier goes away, which prevents the consumer from accessing dangling
GPIOs.

Signed-off-by: Thierry Reding <treding@nvidia.com>
---
 drivers/gpio/gpiolib-devres.c |  4 ++++
 drivers/gpio/gpiolib.c        | 20 +++++++++++++++++++-
 drivers/gpio/gpiolib.h        |  2 ++
 3 files changed, 25 insertions(+), 1 deletion(-)

diff --git a/drivers/gpio/gpiolib-devres.c b/drivers/gpio/gpiolib-devres.c
index 0acc2cc6e868..0092feec9a5a 100644
--- a/drivers/gpio/gpiolib-devres.c
+++ b/drivers/gpio/gpiolib-devres.c
@@ -177,6 +177,8 @@ struct gpio_desc *devm_gpiod_get_from_of_node(struct device *dev,
 		return ERR_PTR(-ENOMEM);
 	}
 
+	gpiod_add_device_link(desc, dev);
+
 	*dr = desc;
 	devres_add(dev, dr);
 
@@ -234,6 +236,8 @@ struct gpio_desc *devm_fwnode_get_index_gpiod_from_child(struct device *dev,
 		return desc;
 	}
 
+	gpiod_add_device_link(desc, dev);
+
 	*dr = desc;
 	devres_add(dev, dr);
 
diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
index 71cd685ed6c4..bd793038ba36 100644
--- a/drivers/gpio/gpiolib.c
+++ b/drivers/gpio/gpiolib.c
@@ -4160,6 +4160,20 @@ int gpiod_configure_flags(struct gpio_desc *desc, const char *con_id,
 	return status;
 }
 
+void gpiod_add_device_link(struct gpio_desc *desc, struct device *consumer)
+{
+	struct device_link *link;
+
+	link = device_link_add(consumer, desc->gdev->dev.parent,
+			       DL_FLAG_AUTOREMOVE_CONSUMER);
+	if (!link) {
+		dev_err(consumer, "failed to create device link to %s\n",
+			dev_name(desc->gdev->dev.parent));
+	} else {
+		desc->consumer = consumer;
+	}
+}
+
 /**
  * gpiod_get_index - obtain a GPIO from a multi-index GPIO function
  * @dev:	GPIO consumer, can be NULL for system-global GPIOs
@@ -4242,6 +4256,8 @@ struct gpio_desc *__must_check gpiod_get_index(struct device *dev,
 		return ERR_PTR(status);
 	}
 
+	gpiod_add_device_link(desc, dev);
+
 	return desc;
 }
 EXPORT_SYMBOL_GPL(gpiod_get_index);
@@ -4625,8 +4641,10 @@ EXPORT_SYMBOL_GPL(gpiod_get_array_optional);
  */
 void gpiod_put(struct gpio_desc *desc)
 {
-	if (desc)
+	if (desc) {
+		device_link_remove(desc->consumer, desc->gdev->dev.parent);
 		gpiod_free(desc);
+	}
 }
 EXPORT_SYMBOL_GPL(gpiod_put);
 
diff --git a/drivers/gpio/gpiolib.h b/drivers/gpio/gpiolib.h
index 7a65dad43932..ed1488aedce0 100644
--- a/drivers/gpio/gpiolib.h
+++ b/drivers/gpio/gpiolib.h
@@ -215,6 +215,7 @@ extern struct list_head gpio_devices;
 
 struct gpio_desc {
 	struct gpio_device	*gdev;
+	struct device		*consumer;
 	unsigned long		flags;
 /* flag symbols are bit numbers */
 #define FLAG_REQUESTED	0
@@ -241,6 +242,7 @@ int gpiod_request(struct gpio_desc *desc, const char *label);
 void gpiod_free(struct gpio_desc *desc);
 int gpiod_configure_flags(struct gpio_desc *desc, const char *con_id,
 		unsigned long lflags, enum gpiod_flags dflags);
+void gpiod_add_device_link(struct gpio_desc *desc, struct device *consumer);
 int gpiod_hog(struct gpio_desc *desc, const char *name,
 		unsigned long lflags, enum gpiod_flags dflags);
 
-- 
2.21.0


^ permalink raw reply related	[flat|nested] 2+ messages in thread

* Re: [PATCH] gpio: Add device link support
  2019-06-21 15:23 [PATCH] gpio: Add device link support Thierry Reding
@ 2019-06-24 22:34 ` Linus Walleij
  0 siblings, 0 replies; 2+ messages in thread
From: Linus Walleij @ 2019-06-24 22:34 UTC (permalink / raw)
  To: Thierry Reding
  Cc: Bartosz Golaszewski, open list:GPIO SUBSYSTEM, linux-kernel

On Fri, Jun 21, 2019 at 5:23 PM Thierry Reding <thierry.reding@gmail.com> wrote:

> From: Thierry Reding <treding@nvidia.com>
>
> Create a device link between a GPIO consumer and the GPIO supplier (i.e.
> the GPIO chip's parent). This makes the driver core aware of the
> dependency between the two devices so that it can properly order the
> suspend/resume sequence.
>
> As a side-effect the GPIO consumer will be force unloaded when the GPIO
> supplier goes away, which prevents the consumer from accessing dangling
> GPIOs.
>
> Signed-off-by: Thierry Reding <treding@nvidia.com>

I was thinking we were gonna see this soon :D

> +void gpiod_add_device_link(struct gpio_desc *desc, struct device *consumer)
> +{
> +       struct device_link *link;
> +
> +       link = device_link_add(consumer, desc->gdev->dev.parent,
> +                              DL_FLAG_AUTOREMOVE_CONSUMER);

I think this needs a NULL check.

Some GPIO chips still have NULL as parent here, they just
register a gpio_chip right out of boardfile code without any
corresponding device. MIPS does this for example IIRC.

> +               device_link_remove(desc->consumer, desc->gdev->dev.parent);

And same on remove.

But why not use desc->gdev->dev as link, simply?
That device has the same lifetime as the gpio_chip, sometimes
even longer I think, if e.g. there is userspace holding the
GPIOs.

Yours,
Linus Walleij

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2019-06-24 22:34 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-06-21 15:23 [PATCH] gpio: Add device link support Thierry Reding
2019-06-24 22:34 ` Linus Walleij

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).