All of lore.kernel.org
 help / color / mirror / Atom feed
From: Lizhi Hou <lizhi.hou@xilinx.com>
To: <linux-kernel@vger.kernel.org>
Cc: Lizhi Hou <lizhih@xilinx.com>, <linux-fpga@vger.kernel.org>,
	<maxz@xilinx.com>, <sonal.santan@xilinx.com>,
	<michal.simek@xilinx.com>, <stefanos@xilinx.com>,
	<devicetree@vger.kernel.org>, <trix@redhat.com>, <mdf@kernel.org>,
	<robh@kernel.org>, Max Zhen <max.zhen@xilinx.com>
Subject: [PATCH V3 XRT Alveo 09/18] fpga: xrt: fpga-mgr and region implementation for xclbin download
Date: Wed, 17 Feb 2021 22:40:10 -0800	[thread overview]
Message-ID: <20210218064019.29189-10-lizhih@xilinx.com> (raw)
In-Reply-To: <20210218064019.29189-1-lizhih@xilinx.com>

fpga-mgr and region implementation for xclbin download which will be
called from main platform driver

Signed-off-by: Sonal Santan <sonal.santan@xilinx.com>
Signed-off-by: Max Zhen <max.zhen@xilinx.com>
Signed-off-by: Lizhi Hou <lizhih@xilinx.com>
---
 drivers/fpga/xrt/mgmt/fmgr-drv.c    | 187 +++++++++++
 drivers/fpga/xrt/mgmt/fmgr.h        |  28 ++
 drivers/fpga/xrt/mgmt/main-region.c | 471 ++++++++++++++++++++++++++++
 3 files changed, 686 insertions(+)
 create mode 100644 drivers/fpga/xrt/mgmt/fmgr-drv.c
 create mode 100644 drivers/fpga/xrt/mgmt/fmgr.h
 create mode 100644 drivers/fpga/xrt/mgmt/main-region.c

diff --git a/drivers/fpga/xrt/mgmt/fmgr-drv.c b/drivers/fpga/xrt/mgmt/fmgr-drv.c
new file mode 100644
index 000000000000..a44d35ecdb60
--- /dev/null
+++ b/drivers/fpga/xrt/mgmt/fmgr-drv.c
@@ -0,0 +1,187 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * FPGA Manager Support for Xilinx Alveo Management Function Driver
+ *
+ * Copyright (C) 2020-2021 Xilinx, Inc.
+ *
+ * Authors: Sonal.Santan@xilinx.com
+ */
+
+#include <linux/cred.h>
+#include <linux/efi.h>
+#include <linux/fpga/fpga-mgr.h>
+#include <linux/platform_device.h>
+#include <linux/module.h>
+#include <linux/vmalloc.h>
+
+#include "xclbin-helper.h"
+#include "xleaf.h"
+#include "fmgr.h"
+#include "xleaf/axigate.h"
+#include "xleaf/icap.h"
+#include "main-impl.h"
+
+struct xfpga_class {
+	const struct platform_device *pdev;
+	char                          name[64];
+};
+
+/*
+ * xclbin download plumbing -- find the download subsystem, ICAP and
+ * pass the xclbin for heavy lifting
+ */
+static int xmgmt_download_bitstream(struct platform_device *pdev,
+				    const struct axlf *xclbin)
+
+{
+	struct hw_icap_bit_header bit_header = { 0 };
+	struct platform_device *icap_leaf = NULL;
+	struct xrt_icap_ioctl_wr arg;
+	char *bitstream = NULL;
+	u64 bit_len;
+	int ret;
+
+	ret = xrt_xclbin_get_section(xclbin, BITSTREAM, (void **)&bitstream, &bit_len);
+	if (ret || !bitstream) {
+		xrt_err(pdev, "bitstream not found");
+		return -ENOENT;
+	}
+	ret = xrt_xclbin_parse_bitstream_header(bitstream,
+						DMA_HWICAP_BITFILE_BUFFER_SIZE,
+						&bit_header);
+	if (ret) {
+		ret = -EINVAL;
+		xrt_err(pdev, "invalid bitstream header");
+		goto done;
+	}
+	if (bit_header.header_length + bit_header.bitstream_length > bit_len) {
+		ret = -EINVAL;
+		xrt_err(pdev, "invalid bitstream length. header %d, bitstream %d, section len %lld",
+			bit_header.header_length, bit_header.bitstream_length, bit_len);
+		goto done;
+	}
+
+	icap_leaf = xleaf_get_leaf_by_id(pdev, XRT_SUBDEV_ICAP, PLATFORM_DEVID_NONE);
+	if (!icap_leaf) {
+		ret = -ENODEV;
+		xrt_err(pdev, "icap does not exist");
+		xrt_xclbin_free_header(&bit_header);
+		goto done;
+	}
+	arg.xiiw_bit_data = bitstream + bit_header.header_length;
+	arg.xiiw_data_len = bit_header.bitstream_length;
+	ret = xleaf_ioctl(icap_leaf, XRT_ICAP_WRITE, &arg);
+	if (ret)
+		xrt_err(pdev, "write bitstream failed, ret = %d", ret);
+
+	xrt_xclbin_free_header(&bit_header);
+done:
+	if (icap_leaf)
+		xleaf_put_leaf(pdev, icap_leaf);
+	vfree(bitstream);
+
+	return ret;
+}
+
+/*
+ * There is no HW prep work we do here since we need the full
+ * xclbin for its sanity check.
+ */
+static int xmgmt_pr_write_init(struct fpga_manager *mgr,
+			       struct fpga_image_info *info,
+			       const char *buf, size_t count)
+{
+	const struct axlf *bin = (const struct axlf *)buf;
+	struct xfpga_class *obj = mgr->priv;
+
+	if (!(info->flags & FPGA_MGR_PARTIAL_RECONFIG)) {
+		xrt_info(obj->pdev, "%s only supports partial reconfiguration\n", obj->name);
+		return -EINVAL;
+	}
+
+	if (count < sizeof(struct axlf))
+		return -EINVAL;
+
+	if (count > bin->m_header.m_length)
+		return -EINVAL;
+
+	xrt_info(obj->pdev, "Prepare download of xclbin %pUb of length %lld B",
+		 &bin->m_header.uuid, bin->m_header.m_length);
+
+	return 0;
+}
+
+/*
+ * The implementation requries full xclbin image before we can start
+ * programming the hardware via ICAP subsystem. Full image is required
+ * for checking the validity of xclbin and walking the sections to
+ * discover the bitstream.
+ */
+static int xmgmt_pr_write(struct fpga_manager *mgr,
+			  const char *buf, size_t count)
+{
+	const struct axlf *bin = (const struct axlf *)buf;
+	struct xfpga_class *obj = mgr->priv;
+
+	if (bin->m_header.m_length != count)
+		return -EINVAL;
+
+	return xmgmt_download_bitstream((void *)obj->pdev, bin);
+}
+
+static int xmgmt_pr_write_complete(struct fpga_manager *mgr,
+				   struct fpga_image_info *info)
+{
+	const struct axlf *bin = (const struct axlf *)info->buf;
+	struct xfpga_class *obj = mgr->priv;
+
+	xrt_info(obj->pdev, "Finished download of xclbin %pUb",
+		 &bin->m_header.uuid);
+	return 0;
+}
+
+static enum fpga_mgr_states xmgmt_pr_state(struct fpga_manager *mgr)
+{
+	return FPGA_MGR_STATE_UNKNOWN;
+}
+
+static const struct fpga_manager_ops xmgmt_pr_ops = {
+	.initial_header_size = sizeof(struct axlf),
+	.write_init = xmgmt_pr_write_init,
+	.write = xmgmt_pr_write,
+	.write_complete = xmgmt_pr_write_complete,
+	.state = xmgmt_pr_state,
+};
+
+struct fpga_manager *xmgmt_fmgr_probe(struct platform_device *pdev)
+{
+	struct xfpga_class *obj = devm_kzalloc(DEV(pdev), sizeof(struct xfpga_class),
+					       GFP_KERNEL);
+	struct fpga_manager *fmgr = NULL;
+	int ret = 0;
+
+	if (!obj)
+		return ERR_PTR(-ENOMEM);
+
+	snprintf(obj->name, sizeof(obj->name), "Xilinx Alveo FPGA Manager");
+	obj->pdev = pdev;
+	fmgr = fpga_mgr_create(&pdev->dev,
+			       obj->name,
+			       &xmgmt_pr_ops,
+			       obj);
+	if (!fmgr)
+		return ERR_PTR(-ENOMEM);
+
+	ret = fpga_mgr_register(fmgr);
+	if (ret) {
+		fpga_mgr_free(fmgr);
+		return ERR_PTR(ret);
+	}
+	return fmgr;
+}
+
+int xmgmt_fmgr_remove(struct fpga_manager *fmgr)
+{
+	fpga_mgr_unregister(fmgr);
+	return 0;
+}
diff --git a/drivers/fpga/xrt/mgmt/fmgr.h b/drivers/fpga/xrt/mgmt/fmgr.h
new file mode 100644
index 000000000000..e1fc033e2542
--- /dev/null
+++ b/drivers/fpga/xrt/mgmt/fmgr.h
@@ -0,0 +1,28 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Header file for Xilinx Alveo Management Function Driver
+ *
+ * Copyright (C) 2020-2021 Xilinx, Inc.
+ *
+ * Authors: Sonal.Santan@xilinx.com
+ */
+
+#ifndef _XMGMT_FMGR_H_
+#define _XMGMT_FMGR_H_
+
+#include <linux/fpga/fpga-mgr.h>
+#include <linux/mutex.h>
+
+#include <linux/xrt/xclbin.h>
+
+enum xfpga_sec_level {
+	XFPGA_SEC_NONE = 0,
+	XFPGA_SEC_DEDICATE,
+	XFPGA_SEC_SYSTEM,
+	XFPGA_SEC_MAX = XFPGA_SEC_SYSTEM,
+};
+
+struct fpga_manager *xmgmt_fmgr_probe(struct platform_device *pdev);
+int xmgmt_fmgr_remove(struct fpga_manager *fmgr);
+
+#endif
diff --git a/drivers/fpga/xrt/mgmt/main-region.c b/drivers/fpga/xrt/mgmt/main-region.c
new file mode 100644
index 000000000000..9779693fe7ae
--- /dev/null
+++ b/drivers/fpga/xrt/mgmt/main-region.c
@@ -0,0 +1,471 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * FPGA Region Support for Xilinx Alveo Management Function Driver
+ *
+ * Copyright (C) 2020-2021 Xilinx, Inc.
+ * Bulk of the code borrowed from XRT mgmt driver file, fmgr.c
+ *
+ * Authors: Lizhi.Hou@xilinx.com
+ */
+
+#include <linux/uuid.h>
+#include <linux/fpga/fpga-bridge.h>
+#include <linux/fpga/fpga-region.h>
+#include "metadata.h"
+#include "xleaf.h"
+#include "xleaf/axigate.h"
+#include "xclbin-helper.h"
+#include "main-impl.h"
+
+struct xmgmt_bridge {
+	struct platform_device *pdev;
+	const char *axigate_name;
+};
+
+struct xmgmt_region {
+	struct platform_device *pdev;
+	struct fpga_region *fregion;
+	uuid_t intf_uuid;
+	struct fpga_bridge *fbridge;
+	int grp_inst;
+	uuid_t dep_uuid;
+	struct list_head list;
+};
+
+struct xmgmt_region_match_arg {
+	struct platform_device *pdev;
+	uuid_t *uuids;
+	u32 uuid_num;
+};
+
+static int xmgmt_br_enable_set(struct fpga_bridge *bridge, bool enable)
+{
+	struct xmgmt_bridge *br_data = (struct xmgmt_bridge *)bridge->priv;
+	struct platform_device *axigate_leaf;
+	int rc;
+
+	axigate_leaf = xleaf_get_leaf_by_epname(br_data->pdev, br_data->axigate_name);
+	if (!axigate_leaf) {
+		xrt_err(br_data->pdev, "failed to get leaf %s",
+			br_data->axigate_name);
+		return -ENOENT;
+	}
+
+	if (enable)
+		rc = xleaf_ioctl(axigate_leaf, XRT_AXIGATE_FREE, NULL);
+	else
+		rc = xleaf_ioctl(axigate_leaf, XRT_AXIGATE_FREEZE, NULL);
+
+	if (rc) {
+		xrt_err(br_data->pdev, "failed to %s gate %s, rc %d",
+			(enable ? "free" : "freeze"), br_data->axigate_name,
+			rc);
+	}
+
+	xleaf_put_leaf(br_data->pdev, axigate_leaf);
+
+	return rc;
+}
+
+const struct fpga_bridge_ops xmgmt_bridge_ops = {
+	.enable_set = xmgmt_br_enable_set
+};
+
+static void xmgmt_destroy_bridge(struct fpga_bridge *br)
+{
+	struct xmgmt_bridge *br_data = br->priv;
+
+	if (!br_data)
+		return;
+
+	xrt_info(br_data->pdev, "destroy fpga bridge %s", br_data->axigate_name);
+	fpga_bridge_unregister(br);
+
+	devm_kfree(DEV(br_data->pdev), br_data);
+
+	fpga_bridge_free(br);
+}
+
+static struct fpga_bridge *xmgmt_create_bridge(struct platform_device *pdev,
+					       char *dtb)
+{
+	struct xmgmt_bridge *br_data;
+	struct fpga_bridge *br = NULL;
+	const char *gate;
+	int rc;
+
+	br_data = devm_kzalloc(DEV(pdev), sizeof(*br_data), GFP_KERNEL);
+	if (!br_data)
+		return NULL;
+	br_data->pdev = pdev;
+
+	br_data->axigate_name = XRT_MD_NODE_GATE_ULP;
+	rc = xrt_md_find_endpoint(&pdev->dev, dtb, XRT_MD_NODE_GATE_ULP,
+				  NULL, &gate);
+	if (rc) {
+		br_data->axigate_name = XRT_MD_NODE_GATE_PLP;
+		rc = xrt_md_find_endpoint(&pdev->dev, dtb, XRT_MD_NODE_GATE_PLP,
+					  NULL, &gate);
+	}
+	if (rc) {
+		xrt_err(pdev, "failed to get axigate, rc %d", rc);
+		goto failed;
+	}
+
+	br = fpga_bridge_create(DEV(pdev), br_data->axigate_name,
+				&xmgmt_bridge_ops, br_data);
+	if (!br) {
+		xrt_err(pdev, "failed to create bridge");
+		goto failed;
+	}
+
+	rc = fpga_bridge_register(br);
+	if (rc) {
+		xrt_err(pdev, "failed to register bridge, rc %d", rc);
+		goto failed;
+	}
+
+	xrt_info(pdev, "created fpga bridge %s", br_data->axigate_name);
+
+	return br;
+
+failed:
+	if (br)
+		fpga_bridge_free(br);
+	if (br_data)
+		devm_kfree(DEV(pdev), br_data);
+
+	return NULL;
+}
+
+static void xmgmt_destroy_region(struct fpga_region *re)
+{
+	struct xmgmt_region *r_data = re->priv;
+
+	xrt_info(r_data->pdev, "destroy fpga region %llx%llx",
+		 re->compat_id->id_l, re->compat_id->id_h);
+
+	fpga_region_unregister(re);
+
+	if (r_data->grp_inst > 0)
+		xleaf_destroy_group(r_data->pdev, r_data->grp_inst);
+
+	if (r_data->fbridge)
+		xmgmt_destroy_bridge(r_data->fbridge);
+
+	if (r_data->fregion->info) {
+		fpga_image_info_free(r_data->fregion->info);
+		r_data->fregion->info = NULL;
+	}
+
+	fpga_region_free(re);
+
+	devm_kfree(DEV(r_data->pdev), r_data);
+}
+
+static int xmgmt_region_match(struct device *dev, const void *data)
+{
+	const struct xmgmt_region_match_arg *arg = data;
+	const struct fpga_region *match_re;
+	int i;
+
+	if (dev->parent != &arg->pdev->dev)
+		return false;
+
+	match_re = to_fpga_region(dev);
+	/*
+	 * The device tree provides both parent and child uuids for an
+	 * xclbin in one array. Here we try both uuids to see if it matches
+	 * with target region's compat_id. Strictly speaking we should
+	 * only match xclbin's parent uuid with target region's compat_id
+	 * but given the uuids by design are unique comparing with both
+	 * does not hurt.
+	 */
+	for (i = 0; i < arg->uuid_num; i++) {
+		if (!memcmp(match_re->compat_id, &arg->uuids[i],
+			    sizeof(*match_re->compat_id)))
+			return true;
+	}
+
+	return false;
+}
+
+static int xmgmt_region_match_base(struct device *dev, const void *data)
+{
+	const struct xmgmt_region_match_arg *arg = data;
+	const struct fpga_region *match_re;
+	const struct xmgmt_region *r_data;
+
+	if (dev->parent != &arg->pdev->dev)
+		return false;
+
+	match_re = to_fpga_region(dev);
+	r_data = match_re->priv;
+	if (uuid_is_null(&r_data->dep_uuid))
+		return true;
+
+	return false;
+}
+
+static int xmgmt_region_match_by_depuuid(struct device *dev, const void *data)
+{
+	const struct xmgmt_region_match_arg *arg = data;
+	const struct fpga_region *match_re;
+	const struct xmgmt_region *r_data;
+
+	if (dev->parent != &arg->pdev->dev)
+		return false;
+
+	match_re = to_fpga_region(dev);
+	r_data = match_re->priv;
+	if (!memcmp(&r_data->dep_uuid, arg->uuids, sizeof(uuid_t)))
+		return true;
+
+	return false;
+}
+
+static void xmgmt_region_cleanup(struct fpga_region *re)
+{
+	struct xmgmt_region *r_data = re->priv, *temp;
+	struct platform_device *pdev = r_data->pdev;
+	struct fpga_region *match_re = NULL;
+	struct device *start_dev = NULL;
+	struct xmgmt_region_match_arg arg;
+	LIST_HEAD(free_list);
+
+	list_add_tail(&r_data->list, &free_list);
+	arg.pdev = pdev;
+	arg.uuid_num = 1;
+
+	while (!r_data) {
+		arg.uuids = (uuid_t *)r_data->fregion->compat_id;
+		match_re = fpga_region_class_find(start_dev, &arg,
+						  xmgmt_region_match_by_depuuid);
+		if (match_re) {
+			r_data = match_re->priv;
+			list_add_tail(&r_data->list, &free_list);
+			start_dev = &match_re->dev;
+			put_device(&match_re->dev);
+			continue;
+		}
+
+		r_data = list_is_last(&r_data->list, &free_list) ? NULL :
+			list_next_entry(r_data, list);
+		start_dev = NULL;
+	}
+
+	list_for_each_entry_safe_reverse(r_data, temp, &free_list, list) {
+		if (list_is_first(&r_data->list, &free_list)) {
+			if (r_data->grp_inst > 0) {
+				xleaf_destroy_group(pdev, r_data->grp_inst);
+				r_data->grp_inst = -1;
+			}
+			if (r_data->fregion->info) {
+				fpga_image_info_free(r_data->fregion->info);
+				r_data->fregion->info = NULL;
+			}
+			continue;
+		}
+		xmgmt_destroy_region(r_data->fregion);
+	}
+}
+
+void xmgmt_region_cleanup_all(struct platform_device *pdev)
+{
+	struct fpga_region *base_re;
+	struct xmgmt_region_match_arg arg;
+
+	arg.pdev = pdev;
+
+	for (base_re = fpga_region_class_find(NULL, &arg, xmgmt_region_match_base);
+	    base_re;
+	    base_re = fpga_region_class_find(NULL, &arg, xmgmt_region_match_base)) {
+		put_device(&base_re->dev);
+
+		xmgmt_region_cleanup(base_re);
+		xmgmt_destroy_region(base_re);
+	}
+}
+
+/*
+ * Program a given region with given xclbin image. Bring up the subdevs and the
+ * group object to contain the subdevs.
+ */
+static int xmgmt_region_program(struct fpga_region *re, const void *xclbin, char *dtb)
+{
+	struct xmgmt_region *r_data = re->priv;
+	struct platform_device *pdev = r_data->pdev;
+	struct fpga_image_info *info;
+	const struct axlf *xclbin_obj = xclbin;
+	int rc;
+
+	info = fpga_image_info_alloc(&pdev->dev);
+	if (!info)
+		return -ENOMEM;
+
+	info->buf = xclbin;
+	info->count = xclbin_obj->m_header.m_length;
+	info->flags |= FPGA_MGR_PARTIAL_RECONFIG;
+	re->info = info;
+	rc = fpga_region_program_fpga(re);
+	if (rc) {
+		xrt_err(pdev, "programming xclbin failed, rc %d", rc);
+		return rc;
+	}
+
+	/* free bridges to allow reprogram */
+	if (re->get_bridges)
+		fpga_bridges_put(&re->bridge_list);
+
+	/*
+	 * Next bringup the subdevs for this region which will be managed by
+	 * its own group object.
+	 */
+	r_data->grp_inst = xleaf_create_group(pdev, dtb);
+	if (r_data->grp_inst < 0) {
+		xrt_err(pdev, "failed to create group, rc %d",
+			r_data->grp_inst);
+		rc = r_data->grp_inst;
+		return rc;
+	}
+
+	rc = xleaf_wait_for_group_bringup(pdev);
+	if (rc)
+		xrt_err(pdev, "group bringup failed, rc %d", rc);
+	return rc;
+}
+
+static int xmgmt_get_bridges(struct fpga_region *re)
+{
+	struct xmgmt_region *r_data = re->priv;
+	struct device *dev = &r_data->pdev->dev;
+
+	return fpga_bridge_get_to_list(dev, re->info, &re->bridge_list);
+}
+
+/*
+ * Program/create FPGA regions based on input xclbin file. This is key function
+ * stitching the flow together:
+ * 1. Identify a matching existing region for this xclbin
+ * 2. Tear down any previous objects for the found region
+ * 3. Program this region with input xclbin
+ * 4. Iterate over this region's interface uuids to determine if it defines any
+ *    child region. Create fpga_region for the child region.
+ */
+int xmgmt_process_xclbin(struct platform_device *pdev,
+			 struct fpga_manager *fmgr,
+			 const struct axlf *xclbin,
+			 enum provider_kind kind)
+{
+	struct fpga_region *re, *compat_re = NULL;
+	struct xmgmt_region_match_arg arg;
+	struct xmgmt_region *r_data;
+	char *dtb = NULL;
+	int rc, i;
+
+	rc = xrt_xclbin_get_metadata(DEV(pdev), xclbin, &dtb);
+	if (rc) {
+		xrt_err(pdev, "failed to get dtb: %d", rc);
+		goto failed;
+	}
+
+	xrt_md_get_intf_uuids(DEV(pdev), dtb, &arg.uuid_num, NULL);
+	if (arg.uuid_num == 0) {
+		xrt_err(pdev, "failed to get intf uuid");
+		rc = -EINVAL;
+		goto failed;
+	}
+	arg.uuids = vzalloc(sizeof(uuid_t) * arg.uuid_num);
+	if (!arg.uuids) {
+		rc = -ENOMEM;
+		goto failed;
+	}
+	arg.pdev = pdev;
+
+	xrt_md_get_intf_uuids(DEV(pdev), dtb, &arg.uuid_num, arg.uuids);
+
+	/* if this is not base firmware, search for a compatible region */
+	if (kind != XMGMT_BLP) {
+		compat_re = fpga_region_class_find(NULL, &arg,
+						   xmgmt_region_match);
+		if (!compat_re) {
+			xrt_err(pdev, "failed to get compatible region");
+			rc = -ENOENT;
+			goto failed;
+		}
+
+		xmgmt_region_cleanup(compat_re);
+
+		rc = xmgmt_region_program(compat_re, xclbin, dtb);
+		if (rc) {
+			xrt_err(pdev, "failed to program region");
+			goto failed;
+		}
+	}
+
+	/* create all the new regions contained in this xclbin */
+	for (i = 0; i < arg.uuid_num; i++) {
+		if (compat_re && !memcmp(compat_re->compat_id, &arg.uuids[i],
+					 sizeof(*compat_re->compat_id)))
+			/* region for this interface already exists */
+			continue;
+		re = fpga_region_create(DEV(pdev), fmgr, xmgmt_get_bridges);
+		if (!re) {
+			xrt_err(pdev, "failed to create fpga region");
+			rc = -EFAULT;
+			goto failed;
+		}
+		r_data = devm_kzalloc(DEV(pdev), sizeof(*r_data), GFP_KERNEL);
+		if (!r_data) {
+			rc = -ENOMEM;
+			fpga_region_free(re);
+			goto failed;
+		}
+		r_data->pdev = pdev;
+		r_data->fregion = re;
+		r_data->grp_inst = -1;
+		memcpy(&r_data->intf_uuid, &arg.uuids[i],
+		       sizeof(r_data->intf_uuid));
+		if (compat_re) {
+			memcpy(&r_data->dep_uuid, compat_re->compat_id,
+			       sizeof(r_data->intf_uuid));
+		}
+		r_data->fbridge = xmgmt_create_bridge(pdev, dtb);
+		if (!r_data->fbridge) {
+			xrt_err(pdev, "failed to create fpga bridge");
+			rc = -EFAULT;
+			devm_kfree(DEV(pdev), r_data);
+			fpga_region_free(re);
+			goto failed;
+		}
+
+		re->compat_id = (struct fpga_compat_id *)&r_data->intf_uuid;
+		re->priv = r_data;
+
+		rc = fpga_region_register(re);
+		if (rc) {
+			xrt_err(pdev, "failed to register fpga region");
+			xmgmt_destroy_bridge(r_data->fbridge);
+			fpga_region_free(re);
+			devm_kfree(DEV(pdev), r_data);
+			goto failed;
+		}
+
+		xrt_info(pdev, "created fpga region %llx%llx",
+			 re->compat_id->id_l, re->compat_id->id_h);
+	}
+
+failed:
+	if (compat_re)
+		put_device(&compat_re->dev);
+
+	if (rc) {
+		if (compat_re)
+			xmgmt_region_cleanup(compat_re);
+	}
+
+	if (dtb)
+		vfree(dtb);
+
+	return rc;
+}
-- 
2.18.4


  parent reply	other threads:[~2021-02-18  7:19 UTC|newest]

Thread overview: 89+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-02-18  6:40 [PATCH V3 XRT Alveo 00/18] XRT Alveo driver overview Lizhi Hou
2021-02-18  6:40 ` [PATCH V3 XRT Alveo 01/18] Documentation: fpga: Add a document describing XRT Alveo drivers Lizhi Hou
2021-02-19 22:26   ` Tom Rix
2021-03-01  6:48     ` Sonal Santan
2021-03-06 17:19       ` Moritz Fischer
2021-03-08 20:12         ` Sonal Santan
2021-02-18  6:40 ` [PATCH V3 XRT Alveo 02/18] fpga: xrt: driver metadata helper functions Lizhi Hou
2021-02-20 17:07   ` Tom Rix
2021-02-23  6:05     ` Lizhi Hou
2021-02-23  1:23   ` Fernando Pacheco
2021-02-25 20:27     ` Lizhi Hou
2021-02-18  6:40 ` [PATCH V3 XRT Alveo 03/18] fpga: xrt: xclbin file " Lizhi Hou
2021-02-21 17:12   ` Tom Rix
2021-02-21 18:33     ` Moritz Fischer
2021-03-06  1:13       ` Lizhi Hou
2021-02-26 21:23     ` Lizhi Hou
2021-02-28 16:54       ` Tom Rix
2021-03-02  0:25         ` Lizhi Hou
2021-03-02 15:14           ` Moritz Fischer
2021-03-04 18:53             ` Lizhi Hou
2021-02-18  6:40 ` [PATCH V3 XRT Alveo 04/18] fpga: xrt: xrt-lib platform driver manager Lizhi Hou
2021-02-21 20:39   ` Moritz Fischer
2021-03-01 20:34     ` Max Zhen
2021-02-22 15:05   ` Tom Rix
2021-02-23  3:35     ` Moritz Fischer
2021-03-03 17:20     ` Max Zhen
2021-02-18  6:40 ` [PATCH V3 XRT Alveo 05/18] fpga: xrt: group platform driver Lizhi Hou
2021-02-22 18:50   ` Tom Rix
2021-02-26 21:57     ` Max Zhen
2021-02-18  6:40 ` [PATCH V3 XRT Alveo 06/18] fpga: xrt: platform driver infrastructure Lizhi Hou
2021-02-25 21:59   ` Tom Rix
     [not found]     ` <13e9a311-2d04-ba65-3ed2-f9f1834c37de@xilinx.com>
2021-03-08 20:36       ` Max Zhen
2021-02-18  6:40 ` [PATCH V3 XRT Alveo 07/18] fpga: xrt: management physical function driver (root) Lizhi Hou
2021-02-26 15:01   ` Tom Rix
2021-02-26 17:56     ` Moritz Fischer
2021-03-16 20:29     ` Max Zhen
2021-03-17 21:08       ` Tom Rix
2021-03-18  0:44         ` Max Zhen
2021-02-18  6:40 ` [PATCH V3 XRT Alveo 08/18] fpga: xrt: main platform driver for management function device Lizhi Hou
2021-02-26 17:22   ` Tom Rix
2021-03-16 21:23     ` Lizhi Hou
2021-03-17 21:12       ` Tom Rix
2021-02-18  6:40 ` Lizhi Hou [this message]
2021-02-28 16:36   ` [PATCH V3 XRT Alveo 09/18] fpga: xrt: fpga-mgr and region implementation for xclbin download Tom Rix
2021-03-04 17:50     ` Lizhi Hou
2021-02-18  6:40 ` [PATCH V3 XRT Alveo 10/18] fpga: xrt: VSEC platform driver Lizhi Hou
2021-03-01 19:01   ` Tom Rix
2021-03-05 19:58     ` Lizhi Hou
2021-02-18  6:40 ` [PATCH V3 XRT Alveo 11/18] fpga: xrt: UCS " Lizhi Hou
2021-03-02 16:09   ` Tom Rix
2021-03-10 20:24     ` Lizhi Hou
2021-02-18  6:40 ` [PATCH V3 XRT Alveo 12/18] fpga: xrt: ICAP " Lizhi Hou
2021-02-21 20:24   ` Moritz Fischer
2021-03-02 18:26     ` Lizhi Hou
2021-03-03 15:12   ` Tom Rix
2021-03-17 20:56     ` Lizhi Hou
2021-02-18  6:40 ` [PATCH V3 XRT Alveo 13/18] fpga: xrt: devctl " Lizhi Hou
2021-03-04 13:39   ` Tom Rix
2021-03-16 23:54     ` Lizhi Hou
2021-03-17 21:16       ` Tom Rix
2021-02-18  6:40 ` [PATCH V3 XRT Alveo 14/18] fpga: xrt: clock " Lizhi Hou
2021-03-05 15:23   ` Tom Rix
2021-03-11  0:12     ` Lizhi Hou
2021-02-18  6:40 ` [PATCH V3 XRT Alveo 15/18] fpga: xrt: clock frequence counter " Lizhi Hou
2021-03-06 15:25   ` Tom Rix
2021-03-12 23:43     ` Lizhi Hou
2021-02-18  6:40 ` [PATCH V3 XRT Alveo 16/18] fpga: xrt: DDR calibration " Lizhi Hou
2021-02-21 20:21   ` Moritz Fischer
2021-03-06 15:34   ` Tom Rix
2021-03-13  0:45     ` Lizhi Hou
2021-02-18  6:40 ` [PATCH V3 XRT Alveo 17/18] fpga: xrt: partition isolation " Lizhi Hou
2021-02-21 20:36   ` Moritz Fischer
2021-03-16 20:38     ` Lizhi Hou
2021-03-06 15:54   ` Tom Rix
2021-03-13  6:53     ` Lizhi Hou
2021-02-18  6:40 ` [PATCH V3 XRT Alveo 18/18] fpga: xrt: Kconfig and Makefile updates for XRT drivers Lizhi Hou
2021-02-18  9:02   ` kernel test robot
2021-02-18  9:02     ` kernel test robot
2021-02-18 19:50   ` kernel test robot
2021-02-18 19:50     ` kernel test robot
2021-02-21 14:57   ` Tom Rix
2021-02-21 18:39     ` Moritz Fischer
2021-02-28 20:52       ` Sonal Santan
2021-02-18 13:52 ` [PATCH V3 XRT Alveo 00/18] XRT Alveo driver overview Tom Rix
2021-02-19  5:15   ` Lizhi Hou
2021-02-21 20:43 ` Moritz Fischer
2021-03-01 18:29   ` Lizhi Hou
2021-03-03  6:49   ` Joe Perches
2021-03-03 23:15     ` Moritz Fischer

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20210218064019.29189-10-lizhih@xilinx.com \
    --to=lizhi.hou@xilinx.com \
    --cc=devicetree@vger.kernel.org \
    --cc=linux-fpga@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=lizhih@xilinx.com \
    --cc=max.zhen@xilinx.com \
    --cc=maxz@xilinx.com \
    --cc=mdf@kernel.org \
    --cc=michal.simek@xilinx.com \
    --cc=robh@kernel.org \
    --cc=sonal.santan@xilinx.com \
    --cc=stefanos@xilinx.com \
    --cc=trix@redhat.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.