[PATCH V1 XRT Alveo Infrastructure 8/9] fpga: xrt: xrt group device driver

From: Lizhi Hou
Date: Thu Nov 18 2021 - 16:05:38 EST


group driver that manages life cycle of a bunch of leaf driver instances.

Signed-off-by: Sonal Santan <sonal.santan@xxxxxxxxxx>
Signed-off-by: Max Zhen <max.zhen@xxxxxxxxxx>
Signed-off-by: Lizhi Hou <lizhi.hou@xxxxxxxxxx>
---
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 --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@xxxxxxxxxx>
+ */
+
+#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[];

--
2.27.0