All of lore.kernel.org
 help / color / mirror / Atom feed
From: Marco Pagani <marpagan@redhat.com>
To: Moritz Fischer <mdf@kernel.org>, Wu Hao <hao.wu@intel.com>,
	Xu Yilun <yilun.xu@intel.com>, Tom Rix <trix@redhat.com>
Cc: Marco Pagani <marpagan@redhat.com>,
	linux-kernel@vger.kernel.org, linux-fpga@vger.kernel.org
Subject: [RFC PATCH v5 3/4] fpga: add fake FPGA region
Date: Thu, 11 May 2023 16:19:21 +0200	[thread overview]
Message-ID: <20230511141922.437328-4-marpagan@redhat.com> (raw)
In-Reply-To: <20230511141922.437328-1-marpagan@redhat.com>

Add fake FPGA region platform driver with support functions. This module
is part of the KUnit tests for the FPGA subsystem.

Signed-off-by: Marco Pagani <marpagan@redhat.com>
---
 drivers/fpga/tests/fake-fpga-region.c | 245 ++++++++++++++++++++++++++
 drivers/fpga/tests/fake-fpga-region.h |  40 +++++
 2 files changed, 285 insertions(+)
 create mode 100644 drivers/fpga/tests/fake-fpga-region.c
 create mode 100644 drivers/fpga/tests/fake-fpga-region.h

diff --git a/drivers/fpga/tests/fake-fpga-region.c b/drivers/fpga/tests/fake-fpga-region.c
new file mode 100644
index 000000000000..020c3ad13812
--- /dev/null
+++ b/drivers/fpga/tests/fake-fpga-region.c
@@ -0,0 +1,245 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Driver for the fake FPGA region
+ *
+ * Copyright (C) 2023 Red Hat, Inc.
+ *
+ * Author: Marco Pagani <marpagan@redhat.com>
+ */
+
+#include <linux/device.h>
+#include <linux/list.h>
+#include <linux/platform_device.h>
+#include <linux/fpga/fpga-mgr.h>
+#include <linux/fpga/fpga-region.h>
+#include <linux/fpga/fpga-bridge.h>
+#include <kunit/test.h>
+
+#include "fake-fpga-region.h"
+
+#define FAKE_FPGA_REGION_DEV_NAME	"fake_fpga_region"
+
+struct fake_region_pdata {
+	struct kunit *test;
+	struct fpga_manager *mgr;
+};
+
+struct bridge_elem {
+	struct fpga_bridge *bridge;
+	struct list_head node;
+};
+
+struct fake_region_priv {
+	struct list_head bridge_list;
+	struct fake_region_pdata *pdata;
+};
+
+/**
+ * fake_fpga_region_register() - register a fake FPGA region.
+ * @mgr: associated FPGA manager.
+ * @parent: parent device.
+ * @test: KUnit test context object.
+ *
+ * Return: pointer to a new fake FPGA region on success, an ERR_PTR() encoded
+ * error code on failure.
+ */
+struct fake_fpga_region *
+fake_fpga_region_register(struct kunit *test, struct fpga_manager *mgr,
+			  struct device *parent)
+{
+	struct fake_fpga_region *region_ctx;
+	struct fake_region_pdata pdata;
+	int ret;
+
+	region_ctx = kunit_kzalloc(test, sizeof(*region_ctx), GFP_KERNEL);
+	if (!region_ctx) {
+		ret = -ENOMEM;
+		goto err_mem;
+	}
+
+	region_ctx->pdev = platform_device_alloc(FAKE_FPGA_REGION_DEV_NAME,
+						 PLATFORM_DEVID_AUTO);
+	if (!region_ctx->pdev) {
+		pr_err("Fake FPGA region device allocation failed\n");
+		ret = -ENOMEM;
+		goto err_mem;
+	}
+
+	pdata.mgr = mgr;
+	pdata.test = test;
+	platform_device_add_data(region_ctx->pdev, &pdata, sizeof(pdata));
+
+	region_ctx->pdev->dev.parent = parent;
+	ret = platform_device_add(region_ctx->pdev);
+	if (ret) {
+		pr_err("Fake FPGA region device add failed\n");
+		goto err_pdev;
+	}
+
+	region_ctx->region = platform_get_drvdata(region_ctx->pdev);
+
+	kunit_info(test, "Fake FPGA region %u: registered\n",
+		   region_ctx->region->dev.id);
+
+	return region_ctx;
+
+err_pdev:
+	platform_device_put(region_ctx->pdev);
+err_mem:
+	return ERR_PTR(ret);
+}
+EXPORT_SYMBOL_GPL(fake_fpga_region_register);
+
+/**
+ * fake_fpga_region_unregister() - unregister a fake FPGA region.
+ * @region_ctx: fake FPGA region context data structure.
+ */
+void fake_fpga_region_unregister(struct fake_fpga_region *region_ctx)
+{
+	struct fake_region_priv *priv;
+	struct kunit *test;
+	u32 id;
+
+	if (!region_ctx)
+		return;
+
+	id = region_ctx->region->dev.id;
+	priv = region_ctx->region->priv;
+	test = priv->pdata->test;
+
+	platform_device_unregister(region_ctx->pdev);
+
+	kunit_info(test, "Fake FPGA region %u: unregistered\n", id);
+}
+EXPORT_SYMBOL_GPL(fake_fpga_region_unregister);
+
+/**
+ * fake_fpga_region_add_bridge() - add a bridge to a fake FPGA region.
+ * @region_ctx: fake FPGA region context data structure.
+ * @bridge: FPGA bridge.
+ *
+ * Return: 0 if registration succeeded, an error code otherwise.
+ */
+int fake_fpga_region_add_bridge(struct fake_fpga_region *region_ctx,
+				struct fpga_bridge *bridge)
+{
+	struct fake_region_priv *priv;
+	struct bridge_elem *elem;
+
+	priv = region_ctx->region->priv;
+
+	elem = devm_kzalloc(&region_ctx->pdev->dev, sizeof(*elem), GFP_KERNEL);
+	if (!elem)
+		return -ENOMEM;
+
+	/* Add bridge to the list of bridges in the private context */
+	elem->bridge = bridge;
+	list_add(&elem->node, &priv->bridge_list);
+
+	kunit_info(priv->pdata->test, "Bridge: %u added to fake FPGA region: %u\n",
+		   bridge->dev.id, region_ctx->region->dev.id);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(fake_fpga_region_add_bridge);
+
+int fake_fpga_region_program(struct fake_fpga_region *region_ctx)
+{
+	int ret;
+
+	ret = fpga_region_program_fpga(region_ctx->region);
+
+	/* fpga_region_program_fpga() already puts the bridges in case of errors */
+	if (!ret)
+		fpga_bridges_put(&region_ctx->region->bridge_list);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(fake_fpga_region_program);
+
+static int fake_region_get_bridges(struct fpga_region *region)
+{
+	struct fake_region_priv *priv;
+	struct bridge_elem *elem;
+	int ret;
+
+	priv = region->priv;
+
+	/* Copy the list of bridges from the private context to the region */
+	list_for_each_entry(elem, &priv->bridge_list, node) {
+		ret = fpga_bridge_get_to_list(elem->bridge->dev.parent,
+					      region->info,
+					      &region->bridge_list);
+		if (ret)
+			break;
+	}
+
+	return ret;
+}
+
+static int fake_fpga_region_probe(struct platform_device *pdev)
+{
+	struct device *dev;
+	struct fpga_region *region;
+	struct fpga_manager *mgr;
+	struct fake_region_pdata *pdata;
+	struct fake_region_priv *priv;
+	struct fpga_region_info info;
+
+	dev = &pdev->dev;
+	pdata = dev_get_platdata(dev);
+
+	if (!pdata) {
+		dev_err(&pdev->dev, "Fake FPGA region probe: missing platform data\n");
+		return -EINVAL;
+	}
+
+	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+
+	mgr = fpga_mgr_get(pdata->mgr->dev.parent);
+	if (IS_ERR(mgr))
+		return PTR_ERR(mgr);
+
+	priv->pdata = pdata;
+	INIT_LIST_HEAD(&priv->bridge_list);
+
+	memset(&info, 0, sizeof(info));
+	info.priv = priv;
+	info.mgr = mgr;
+	info.get_bridges = fake_region_get_bridges;
+
+	region = fpga_region_register_full(dev, &info);
+	if (IS_ERR(region)) {
+		fpga_mgr_put(mgr);
+		return PTR_ERR(region);
+	}
+
+	platform_set_drvdata(pdev, region);
+
+	return 0;
+}
+
+static int fake_fpga_region_remove(struct platform_device *pdev)
+{
+	struct fpga_region *region = platform_get_drvdata(pdev);
+	struct fpga_manager *mgr = region->mgr;
+
+	fpga_mgr_put(mgr);
+	fpga_region_unregister(region);
+
+	return 0;
+}
+
+static struct platform_driver fake_fpga_region_drv = {
+	.driver = {
+		.name = FAKE_FPGA_REGION_DEV_NAME
+	},
+	.probe = fake_fpga_region_probe,
+	.remove = fake_fpga_region_remove,
+};
+
+module_platform_driver(fake_fpga_region_drv);
+
+MODULE_LICENSE("GPL");
diff --git a/drivers/fpga/tests/fake-fpga-region.h b/drivers/fpga/tests/fake-fpga-region.h
new file mode 100644
index 000000000000..c72992cbb218
--- /dev/null
+++ b/drivers/fpga/tests/fake-fpga-region.h
@@ -0,0 +1,40 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Header file for the fake FPGA region
+ *
+ * Copyright (C) 2023 Red Hat, Inc.
+ *
+ * Author: Marco Pagani <marpagan@redhat.com>
+ */
+
+#ifndef __FPGA_FAKE_RGN_H
+#define __FPGA_FAKE_RGN_H
+
+#include <linux/platform_device.h>
+#include <kunit/test.h>
+#include <linux/fpga/fpga-mgr.h>
+#include <linux/fpga/fpga-bridge.h>
+
+/**
+ * struct fake_fpga_region - fake FPGA region context data structure
+ *
+ * @region: FPGA region.
+ * @pdev: platform device of the FPGA region.
+ */
+struct fake_fpga_region {
+	struct fpga_region *region;
+	struct platform_device *pdev;
+};
+
+struct fake_fpga_region *
+fake_fpga_region_register(struct kunit *test, struct fpga_manager *mgr,
+			  struct device *parent);
+
+int fake_fpga_region_add_bridge(struct fake_fpga_region *region_ctx,
+				struct fpga_bridge *bridge);
+
+int fake_fpga_region_program(struct fake_fpga_region *region_ctx);
+
+void fake_fpga_region_unregister(struct fake_fpga_region *region_ctx);
+
+#endif /* __FPGA_FAKE_RGN_H */
-- 
2.40.1


  parent reply	other threads:[~2023-05-11 14:21 UTC|newest]

Thread overview: 12+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-05-11 14:19 [RFC PATCH v5 0/4] fpga: add initial KUnit tests for the subsystem Marco Pagani
2023-05-11 14:19 ` [RFC PATCH v5 1/4] fpga: add fake FPGA manager Marco Pagani
2023-05-13 15:44   ` Xu Yilun
2023-05-11 14:19 ` [RFC PATCH v5 2/4] fpga: add fake FPGA bridge Marco Pagani
2023-05-13 15:46   ` Xu Yilun
2023-05-11 14:19 ` Marco Pagani [this message]
2023-05-13 16:05   ` [RFC PATCH v5 3/4] fpga: add fake FPGA region Xu Yilun
2023-05-11 14:19 ` [RFC PATCH v5 4/4] fpga: add initial KUnit test suites Marco Pagani
2023-05-13 17:40   ` Xu Yilun
2023-05-15 17:24     ` Marco Pagani
2023-05-17 10:04       ` Xu Yilun
2023-05-18 12:43         ` Marco Pagani

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=20230511141922.437328-4-marpagan@redhat.com \
    --to=marpagan@redhat.com \
    --cc=hao.wu@intel.com \
    --cc=linux-fpga@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mdf@kernel.org \
    --cc=trix@redhat.com \
    --cc=yilun.xu@intel.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.