mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Thierry Reding <thierry.reding@gmail.com>
To: Linus Walleij <linus.walleij@linaro.org>,
	Bartosz Golaszewski <bgolaszewski@baylibre.com>
Cc: linux-gpio@vger.kernel.org, linux-kernel@vger.kernel.org
Subject: [PATCH] gpio: Add device link support
Date: Fri, 21 Jun 2019 17:23:29 +0200	[thread overview]
Message-ID: <20190621152329.21072-1-thierry.reding@gmail.com> (raw)

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


             reply	other threads:[~2019-06-21 15:23 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-06-21 15:23 Thierry Reding [this message]
2019-06-24 22:34 ` Linus Walleij

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20190621152329.21072-1-thierry.reding@gmail.com \
    --to=thierry.reding@gmail.com \
    --cc=bgolaszewski@baylibre.com \
    --cc=linus.walleij@linaro.org \
    --cc=linux-gpio@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®