diff mbox series

[V3,XRT,Alveo,Infrastructure,7/8] fpga: xrt: xrt group device driver

Message ID 20211204003957.1448567-8-lizhi.hou@xilinx.com (mailing list archive)
State New
Headers show
Series XRT Alveo driver infrastructure overview | expand

Commit Message

Lizhi Hou Dec. 4, 2021, 12:39 a.m. UTC
group driver that manages life cycle of a bunch of leaf driver instances.

Signed-off-by: Sonal Santan <sonal.santan@xilinx.com>
Signed-off-by: Max Zhen <max.zhen@xilinx.com>
Signed-off-by: Lizhi Hou <lizhi.hou@xilinx.com>
---
 drivers/fpga/xrt/lib/Makefile  |  1 +
 drivers/fpga/xrt/lib/group.c   | 94 ++++++++++++++++++++++++++++++++++
 drivers/fpga/xrt/lib/lib-drv.c | 18 ++++++-
 drivers/fpga/xrt/lib/lib-drv.h | 13 +++++
 4 files changed, 125 insertions(+), 1 deletion(-)
 create mode 100644 drivers/fpga/xrt/lib/group.c
diff mbox series

Patch

diff --git a/drivers/fpga/xrt/lib/Makefile b/drivers/fpga/xrt/lib/Makefile
index fd2af2cbd1da..abf7d5341a69 100644
--- a/drivers/fpga/xrt/lib/Makefile
+++ b/drivers/fpga/xrt/lib/Makefile
@@ -12,6 +12,7 @@  obj-$(CONFIG_FPGA_XRT_LIB) += xrt-lib.o
 xrt-lib-objs :=			\
 	lib-drv.o		\
 	xroot.o			\
+	group.o			\
 	xrt-bus.dtb.o
 
 ccflags-y := -I$(FULL_XRT_PATH)/include
diff --git a/drivers/fpga/xrt/lib/group.c b/drivers/fpga/xrt/lib/group.c
new file mode 100644
index 000000000000..feafc45ddb52
--- /dev/null
+++ b/drivers/fpga/xrt/lib/group.c
@@ -0,0 +1,94 @@ 
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Xilinx Alveo FPGA Group Driver
+ *
+ * Copyright (C) 2020-2021 Xilinx, Inc.
+ *
+ * Authors:
+ *	Cheng Zhen <maxz@xilinx.com>
+ */
+
+#include <linux/kmod.h>
+#include <linux/slab.h>
+#include <linux/of.h>
+#include <linux/xrt/xdevice.h>
+#include "lib-drv.h"
+#include "xroot.h"
+
+#define XRT_GRP "xrt_group"
+
+struct xgroup_leaf {
+	struct list_head node;
+	struct xrt_device *leaf_dev;
+};
+
+struct xgroup {
+	struct xrt_device *xdev;
+	struct list_head leaves;
+};
+
+static int xrt_grp_probe(struct xrt_device *xdev)
+{
+	struct xgroup_leaf *leaf;
+	struct xgroup *xg = NULL;
+	struct device_node *dn;
+
+	dev_info(&xdev->dev, "probing\n");
+
+	xg = devm_kzalloc(&xdev->dev, sizeof(*xg), GFP_KERNEL);
+	if (!xg)
+		return -ENOMEM;
+
+	xg->xdev = xdev;
+	INIT_LIST_HEAD(&xg->leaves);
+	xrt_set_drvdata(xdev, xg);
+
+	for_each_child_of_node(xdev->dev.of_node, dn) {
+		leaf = kmalloc(sizeof(*leaf), GFP_KERNEL);
+		if (!leaf)
+			break;
+
+		leaf->leaf_dev = xrt_device_register(&xdev->dev, dn, NULL, 0, NULL, 0);
+		if (!leaf->leaf_dev) {
+			kfree(leaf);
+			continue;
+		}
+		list_add(&leaf->node, &xg->leaves);
+	}
+
+	return 0;
+}
+
+static void xrt_grp_remove(struct xrt_device *xdev)
+{
+	struct xgroup *xg = xrt_get_drvdata(xdev);
+	struct xgroup_leaf *leaf, *tmp;
+
+	list_for_each_entry_safe(leaf, tmp, &xg->leaves, node) {
+		list_del(&leaf->node);
+		xrt_device_unregister(leaf->leaf_dev);
+		kfree(leaf);
+	}
+}
+
+static int xrt_grp_leaf_call(struct xrt_device *xdev, u32 cmd, void *arg)
+{
+	return 0;
+}
+
+static const struct of_device_id group_match[] = {
+	{ .compatible = "xlnx,xrt-group" },
+	{ }
+};
+
+static struct xrt_driver xrt_group_driver = {
+	.driver	= {
+		.name = XRT_GRP,
+		.of_match_table = group_match,
+	},
+	.probe = xrt_grp_probe,
+	.remove = xrt_grp_remove,
+	.leaf_call = xrt_grp_leaf_call,
+};
+
+XRT_LEAF_INIT_FINI_FUNC(group);
diff --git a/drivers/fpga/xrt/lib/lib-drv.c b/drivers/fpga/xrt/lib/lib-drv.c
index 3ad02a7c2aac..c9c654f692d4 100644
--- a/drivers/fpga/xrt/lib/lib-drv.c
+++ b/drivers/fpga/xrt/lib/lib-drv.c
@@ -200,9 +200,17 @@  xrt_device_register(struct device *parent, struct device_node *dn,
 	return NULL;
 }
 
+/*
+ * Leaf driver's module init/fini callbacks. This is not a open infrastructure for dynamic
+ * plugging in drivers. All drivers should be statically added.
+ */
+static void (*leaf_init_fini_cbs[])(bool) = {
+	group_leaf_init_fini,
+};
+
 static __init int xrt_lib_init(void)
 {
-	int ret;
+	int ret, i;
 
 	ret = of_overlay_fdt_apply(__dtb_xrt_bus_begin,
 				   __dtb_xrt_bus_end - __dtb_xrt_bus_begin,
@@ -216,11 +224,19 @@  static __init int xrt_lib_init(void)
 		return ret;
 	}
 
+	for (i = 0; i < ARRAY_SIZE(leaf_init_fini_cbs); i++)
+		leaf_init_fini_cbs[i](true);
+
 	return 0;
 }
 
 static __exit void xrt_lib_fini(void)
 {
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(leaf_init_fini_cbs); i++)
+		leaf_init_fini_cbs[i](false);
+
 	bus_unregister(&xrt_bus_type);
 	of_overlay_remove(&xrt_bus_ovcs_id);
 }
diff --git a/drivers/fpga/xrt/lib/lib-drv.h b/drivers/fpga/xrt/lib/lib-drv.h
index 4bf8a32c7ec5..02d9b3731351 100644
--- a/drivers/fpga/xrt/lib/lib-drv.h
+++ b/drivers/fpga/xrt/lib/lib-drv.h
@@ -9,6 +9,19 @@ 
 #ifndef _LIB_DRV_H_
 #define _LIB_DRV_H_
 
+/* Module's init/fini routines for leaf driver in xrt-lib module */
+#define XRT_LEAF_INIT_FINI_FUNC(name)					\
+void name##_leaf_init_fini(bool init)					\
+{									\
+	if (init)							\
+		xrt_register_driver(&xrt_##name##_driver);		\
+	else								\
+		xrt_unregister_driver(&xrt_##name##_driver);		\
+}
+
+/* Module's init/fini routines for leaf driver in xrt-lib module */
+void group_leaf_init_fini(bool init);
+
 extern u8 __dtb_xrt_bus_begin[];
 extern u8 __dtb_xrt_bus_end[];