@@ -9,4 +9,5 @@
obj-$(CONFIG_FPGA_XRT_XMGMT) += xrt-mgmt.o
xrt-mgmt-objs := \
+ dt-test.dtb.o \
xmgmt-drv.o
new file mode 100644
@@ -0,0 +1,15 @@
+// SPDX-License-Identifier: GPL-2.0
+/dts-v1/;
+
+/ {
+ fragment@0 {
+ target-path="";
+ __overlay__ {
+ pr_isolate_ulp@0,41000 {
+ compatible = "xlnx,alveo-pr-isolation";
+ reg = <0x0 0x41000 0x0 0x1000>;
+ };
+ };
+ };
+};
+
new file mode 100644
@@ -0,0 +1,15 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2020-2022 Xilinx, Inc.
+ *
+ * Authors:
+ * Lizhi Hou <lizhih@xilinx.com>
+ */
+
+#ifndef _DT_TEST_H_
+#define _DT_TEST_H_
+
+extern u8 __dtb_dt_test_begin[];
+extern u8 __dtb_dt_test_end[];
+
+#endif /* _DT_TEST_H_ */
@@ -14,8 +14,11 @@
#include <linux/aer.h>
#include <linux/vmalloc.h>
#include <linux/delay.h>
+#include <linux/of.h>
#include <linux/of_pci.h>
+#include "dt-test.h"
+
#define XMGMT_MODULE_NAME "xrt-mgmt"
/* PCI Device IDs */
@@ -25,17 +28,53 @@ static const struct pci_device_id xmgmt_pci_ids[] = {
{ 0, }
};
+struct xmgmt {
+ int ovcs_id;
+};
+
static int xmgmt_probe(struct pci_dev *pdev, const struct pci_device_id *id)
{
- devm_of_pci_create_bus_endpoint(pdev);
+ struct device_node *dn;
+ struct xmgmt *xm;
+ int ret;
+
+ xm = devm_kzalloc(&pdev->dev, sizeof(*xm), GFP_KERNEL);
+ if (!xm)
+ return -ENOMEM;
+ pci_set_drvdata(pdev, xm);
+
+ ret = devm_of_pci_create_bus_endpoint(pdev);
+ if (ret)
+ return ret;
+
+ dn = of_pci_find_bus_endpoint(pdev);
+ if (!dn) {
+ dev_err(&pdev->dev, "does not find bus endpoint");
+ return -EINVAL;
+ }
+
+ ret = of_overlay_fdt_apply(__dtb_dt_test_begin,
+ (u32)(__dtb_dt_test_end - __dtb_dt_test_begin),
+ &xm->ovcs_id, dn);
+ of_node_put(dn);
+ if (ret)
+ return ret;
return 0;
}
+static void xmgmt_remove(struct pci_dev *pdev)
+{
+ struct xmgmt *xm = pci_get_drvdata(pdev);
+
+ of_overlay_remove(&xm->ovcs_id);
+}
+
static struct pci_driver xmgmt_driver = {
.name = XMGMT_MODULE_NAME,
.id_table = xmgmt_pci_ids,
.probe = xmgmt_probe,
+ .remove = xmgmt_remove,
};
static int __init xmgmt_init(void)
@@ -60,7 +60,7 @@ static int __init rcar_du_of_apply_overlay(const struct rcar_du_of_overlay *dtbs
ovcs_id = 0;
return of_overlay_fdt_apply(dtb->begin, dtb->end - dtb->begin,
- &ovcs_id);
+ &ovcs_id, NULL);
}
static int __init rcar_du_of_add_property(struct of_changeset *ocs,
@@ -686,9 +686,11 @@ static int build_changeset(struct overlay_changeset *ovcs)
* 1) "target" property containing the phandle of the target
* 2) "target-path" property containing the path of the target
*/
-static struct device_node *find_target(struct device_node *info_node)
+static struct device_node *find_target(struct device_node *info_node,
+ struct device_node *target_base)
{
struct device_node *node;
+ char *target_path;
const char *path;
u32 val;
int ret;
@@ -704,10 +706,23 @@ static struct device_node *find_target(struct device_node *info_node)
ret = of_property_read_string(info_node, "target-path", &path);
if (!ret) {
- node = of_find_node_by_path(path);
- if (!node)
- pr_err("find target, node: %pOF, path '%s' not found\n",
- info_node, path);
+ if (target_base) {
+ target_path = kasprintf(GFP_KERNEL, "%pOF%s", target_base, path);
+ if (!target_path)
+ return NULL;
+ node = of_find_node_by_path(target_path);
+ if (!node) {
+ pr_err("find target, node: %pOF, path '%s' not found\n",
+ info_node, target_path);
+ }
+ kfree(target_path);
+ } else {
+ node = of_find_node_by_path(path);
+ if (!node) {
+ pr_err("find target, node: %pOF, path '%s' not found\n",
+ info_node, path);
+ }
+ }
return node;
}
@@ -730,7 +745,7 @@ static struct device_node *find_target(struct device_node *info_node)
* detected in @tree, or -ENOSPC if idr_alloc() error.
*/
static int init_overlay_changeset(struct overlay_changeset *ovcs,
- const void *fdt, struct device_node *tree)
+ const void *fdt, struct device_node *tree, struct device_node *target_base)
{
struct device_node *node, *overlay_node;
struct fragment *fragment;
@@ -792,7 +807,7 @@ static int init_overlay_changeset(struct overlay_changeset *ovcs,
fragment = &fragments[cnt];
fragment->overlay = overlay_node;
- fragment->target = find_target(node);
+ fragment->target = find_target(node, target_base);
if (!fragment->target) {
of_node_put(fragment->overlay);
ret = -EINVAL;
@@ -914,7 +929,7 @@ static void free_overlay_changeset(struct overlay_changeset *ovcs)
*/
static int of_overlay_apply(const void *fdt, struct device_node *tree,
- int *ovcs_id)
+ int *ovcs_id, struct device_node *base)
{
struct overlay_changeset *ovcs;
int ret = 0, ret_revert, ret_tmp;
@@ -947,7 +962,7 @@ static int of_overlay_apply(const void *fdt, struct device_node *tree,
if (ret)
goto err_free_tree;
- ret = init_overlay_changeset(ovcs, fdt, tree);
+ ret = init_overlay_changeset(ovcs, fdt, tree, base);
if (ret)
goto err_free_tree;
@@ -1015,7 +1030,7 @@ static int of_overlay_apply(const void *fdt, struct device_node *tree,
}
int of_overlay_fdt_apply(const void *overlay_fdt, u32 overlay_fdt_size,
- int *ovcs_id)
+ int *ovcs_id, struct device_node *base)
{
void *new_fdt;
void *new_fdt_align;
@@ -1053,7 +1068,7 @@ int of_overlay_fdt_apply(const void *overlay_fdt, u32 overlay_fdt_size,
goto out_free_new_fdt;
}
- ret = of_overlay_apply(new_fdt, overlay_root, ovcs_id);
+ ret = of_overlay_apply(new_fdt, overlay_root, ovcs_id, base);
if (ret < 0) {
/*
* new_fdt and overlay_root now belong to the overlay
@@ -3010,7 +3010,7 @@ static int __init overlay_data_apply(const char *overlay_name, int *ovcs_id)
if (!size)
pr_err("no overlay data for %s\n", overlay_name);
- ret = of_overlay_fdt_apply(info->dtb_begin, size, &info->ovcs_id);
+ ret = of_overlay_fdt_apply(info->dtb_begin, size, &info->ovcs_id, NULL);
if (ovcs_id)
*ovcs_id = info->ovcs_id;
if (ret < 0)
@@ -1567,7 +1567,7 @@ struct of_overlay_notify_data {
#ifdef CONFIG_OF_OVERLAY
int of_overlay_fdt_apply(const void *overlay_fdt, u32 overlay_fdt_size,
- int *ovcs_id);
+ int *ovcs_id, struct device_node *target_base);
int of_overlay_remove(int *ovcs_id);
int of_overlay_remove_all(void);