Add code implementing managed version of serdev_device_open() for
serdev device drivers that "open" the device during driver's lifecycle
only once (e.g. opened in .probe() and closed in .remove()).

Cc: linux-kernel@vger.kernel.org
Cc: linux-ser...@vger.kernel.org
Cc: Rob Herring <r...@kernel.org>
Cc: cphe...@gmail.com
Cc: Guenter Roeck <li...@roeck-us.net>
Cc: Lucas Stach <l.st...@pengutronix.de>
Cc: Nikita Yushchenko <nikita.yo...@cogentembedded.com>
Cc: Lee Jones <lee.jo...@linaro.org>
Cc: Greg Kroah-Hartman <gre...@linuxfoundation.org>
Cc: Pavel Machek <pa...@ucw.cz>
Cc: Andy Shevchenko <andy.shevche...@gmail.com>
Cc: Johan Hovold <jo...@kernel.org>
Cc: Sebastian Reichel <sebastian.reic...@collabora.co.uk>
Acked-by: Rob Herring <r...@kernel.org>
Reviewed-by: Sebastian Reichel <sebastian.reic...@collabora.co.uk>
Reviewed-by: Guenter Roeck <li...@roeck-us.net>
Signed-off-by: Andrey Smirnov <andrew.smir...@gmail.com>
---
 Documentation/driver-model/devres.txt |  3 +++
 drivers/tty/serdev/core.c             | 27 +++++++++++++++++++++++++++
 include/linux/serdev.h                |  1 +
 3 files changed, 31 insertions(+)

diff --git a/Documentation/driver-model/devres.txt 
b/Documentation/driver-model/devres.txt
index c180045eb43b..7c1bb3d0c222 100644
--- a/Documentation/driver-model/devres.txt
+++ b/Documentation/driver-model/devres.txt
@@ -384,6 +384,9 @@ RESET
   devm_reset_control_get()
   devm_reset_controller_register()
 
+SERDEV
+  devm_serdev_device_open()
+
 SLAVE DMA ENGINE
   devm_acpi_dma_controller_register()
 
diff --git a/drivers/tty/serdev/core.c b/drivers/tty/serdev/core.c
index 34050b439c1f..28133dbd2808 100644
--- a/drivers/tty/serdev/core.c
+++ b/drivers/tty/serdev/core.c
@@ -132,6 +132,33 @@ void serdev_device_close(struct serdev_device *serdev)
 }
 EXPORT_SYMBOL_GPL(serdev_device_close);
 
+static void devm_serdev_device_release(struct device *dev, void *dr)
+{
+       serdev_device_close(*(struct serdev_device **)dr);
+}
+
+int devm_serdev_device_open(struct device *dev, struct serdev_device *serdev)
+{
+       struct serdev_device **dr;
+       int ret;
+
+       dr = devres_alloc(devm_serdev_device_release, sizeof(*dr), GFP_KERNEL);
+       if (!dr)
+               return -ENOMEM;
+
+       ret = serdev_device_open(serdev);
+       if (ret) {
+               devres_free(dr);
+               return ret;
+       }
+
+       *dr = serdev;
+       devres_add(dev, dr);
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(devm_serdev_device_open);
+
 void serdev_device_write_wakeup(struct serdev_device *serdev)
 {
        complete(&serdev->write_comp);
diff --git a/include/linux/serdev.h b/include/linux/serdev.h
index e69402d4a8ae..9929063bd45d 100644
--- a/include/linux/serdev.h
+++ b/include/linux/serdev.h
@@ -193,6 +193,7 @@ static inline int serdev_controller_receive_buf(struct 
serdev_controller *ctrl,
 
 int serdev_device_open(struct serdev_device *);
 void serdev_device_close(struct serdev_device *);
+int devm_serdev_device_open(struct device *, struct serdev_device *);
 unsigned int serdev_device_set_baudrate(struct serdev_device *, unsigned int);
 void serdev_device_set_flow_control(struct serdev_device *, bool);
 int serdev_device_write_buf(struct serdev_device *, const unsigned char *, 
size_t);
-- 
2.14.3

Reply via email to