[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <db30127ab4741d4e71b768881197f4791174f545.1666786471.git.matthias.schiffer@ew.tq-group.com>
Date: Wed, 26 Oct 2022 15:15:30 +0200
From: Matthias Schiffer <matthias.schiffer@...tq-group.com>
To: Arnd Bergmann <arnd@...db.de>,
Greg Kroah-Hartman <gregkh@...uxfoundation.org>,
Rob Herring <robh+dt@...nel.org>,
Krzysztof Kozlowski <krzysztof.kozlowski+dt@...aro.org>
Cc: Marcel Holtmann <marcel@...tmann.org>,
Johan Hedberg <johan.hedberg@...il.com>,
Luiz Augusto von Dentz <luiz.dentz@...il.com>,
Amitkumar Karwar <amitkarwar@...il.com>,
Ganapathi Bhat <ganapathi017@...il.com>,
Sharvari Harisangam <sharvari.harisangam@....com>,
Xinming Hu <huxinming820@...il.com>,
Kalle Valo <kvalo@...nel.org>,
"David S. Miller" <davem@...emloft.net>,
Eric Dumazet <edumazet@...gle.com>,
Jakub Kicinski <kuba@...nel.org>,
Paolo Abeni <pabeni@...hat.com>, linux-kernel@...r.kernel.org,
linux-bluetooth@...r.kernel.org, linux-wireless@...r.kernel.org,
netdev@...r.kernel.org, devicetree@...r.kernel.org,
linux@...tq-group.com,
Matthias Schiffer <matthias.schiffer@...tq-group.com>
Subject: [RFC 1/5] misc: introduce notify-device driver
A notify-device is a synchronization facility that allows to query
"readiness" across drivers, without creating a direct dependency between
the driver modules. The notify-device can also be used to trigger deferred
probes.
Signed-off-by: Matthias Schiffer <matthias.schiffer@...tq-group.com>
---
drivers/misc/Kconfig | 4 ++
drivers/misc/Makefile | 1 +
drivers/misc/notify-device.c | 109 ++++++++++++++++++++++++++++++++++
include/linux/notify-device.h | 33 ++++++++++
4 files changed, 147 insertions(+)
create mode 100644 drivers/misc/notify-device.c
create mode 100644 include/linux/notify-device.h
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index 358ad56f6524..63559e9f854c 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -496,6 +496,10 @@ config VCPU_STALL_DETECTOR
If you do not intend to run this kernel as a guest, say N.
+config NOTIFY_DEVICE
+ tristate "Notify device"
+ depends on OF
+
source "drivers/misc/c2port/Kconfig"
source "drivers/misc/eeprom/Kconfig"
source "drivers/misc/cb710/Kconfig"
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index ac9b3e757ba1..1e8012112b43 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -62,3 +62,4 @@ obj-$(CONFIG_HI6421V600_IRQ) += hi6421v600-irq.o
obj-$(CONFIG_OPEN_DICE) += open-dice.o
obj-$(CONFIG_GP_PCI1XXXX) += mchp_pci1xxxx/
obj-$(CONFIG_VCPU_STALL_DETECTOR) += vcpu_stall_detector.o
+obj-$(CONFIG_NOTIFY_DEVICE) += notify-device.o
diff --git a/drivers/misc/notify-device.c b/drivers/misc/notify-device.c
new file mode 100644
index 000000000000..42e0980394ea
--- /dev/null
+++ b/drivers/misc/notify-device.c
@@ -0,0 +1,109 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include <linux/device/class.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/notify-device.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+
+static void notify_device_release(struct device *dev)
+{
+ of_node_put(dev->of_node);
+ kfree(dev);
+}
+
+static struct class notify_device_class = {
+ .name = "notify-device",
+ .owner = THIS_MODULE,
+ .dev_release = notify_device_release,
+};
+
+static struct platform_driver notify_device_driver = {
+ .driver = {
+ .name = "notify-device",
+ },
+};
+
+struct device *notify_device_create(struct device *parent, const char *child)
+{
+ struct device_node *node;
+ struct device *dev;
+ int err;
+
+ if (!parent->of_node)
+ return ERR_PTR(-EINVAL);
+
+ node = of_get_child_by_name(parent->of_node, child);
+ if (!node)
+ return NULL;
+
+ dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+ if (!dev) {
+ of_node_put(node);
+ return ERR_PTR(-ENOMEM);
+ }
+
+ dev_set_name(dev, "%s:%s", dev_name(parent), child);
+ dev->class = ¬ify_device_class;
+ dev->parent = parent;
+ dev->of_node = node;
+ err = device_register(dev);
+ if (err) {
+ put_device(dev);
+ return ERR_PTR(err);
+ }
+
+ dev->driver = ¬ify_device_driver.driver;
+ err = device_bind_driver(dev);
+ if (err) {
+ device_unregister(dev);
+ return ERR_PTR(err);
+ }
+
+ return dev;
+}
+EXPORT_SYMBOL_GPL(notify_device_create);
+
+void notify_device_destroy(struct device *dev)
+{
+ if (!dev)
+ return;
+
+ device_release_driver(dev);
+ device_unregister(dev);
+}
+EXPORT_SYMBOL_GPL(notify_device_destroy);
+
+struct device *notify_device_find_by_of_node(struct device_node *node)
+{
+ return class_find_device_by_of_node(¬ify_device_class, node);
+}
+EXPORT_SYMBOL_GPL(notify_device_find_by_of_node);
+
+static int __init notify_device_init(void)
+{
+ int err;
+
+ err = class_register(¬ify_device_class);
+ if (err)
+ return err;
+
+ err = platform_driver_register(¬ify_device_driver);
+ if (err) {
+ class_unregister(¬ify_device_class);
+ return err;
+ }
+
+ return 0;
+}
+
+static void __exit notify_device_exit(void)
+{
+ platform_driver_unregister(¬ify_device_driver);
+ class_unregister(¬ify_device_class);
+}
+
+module_init(notify_device_init);
+module_exit(notify_device_exit);
+MODULE_LICENSE("GPL");
diff --git a/include/linux/notify-device.h b/include/linux/notify-device.h
new file mode 100644
index 000000000000..f8c3e15d3b8f
--- /dev/null
+++ b/include/linux/notify-device.h
@@ -0,0 +1,33 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+#ifndef _LINUX_NOTIFY_DEVICE_H
+#define _LINUX_NOTIFY_DEVICE_H
+#include <linux/device.h>
+#include <linux/of.h>
+
+#ifdef CONFIG_NOTIFY_DEVICE
+
+struct device *notify_device_create(struct device *parent, const char *child);
+void notify_device_destroy(struct device *dev);
+struct device *notify_device_find_by_of_node(struct device_node *node);
+
+#else
+
+static inline struct device *notify_device_create(struct device *parent,
+ const char *child)
+{
+ return NULL;
+}
+
+static inline void notify_device_destroy(struct device *dev)
+{
+}
+
+static inline struct device *notify_device_find_by_of_node(struct device_node *node)
+{
+ return NULL;
+}
+
+#endif
+
+#endif /* _LINUX_NOTIFY_DEVICE_H */
--
2.25.1
Powered by blists - more mailing lists