linux-spi.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v4 -next 0/4] spi: Introduce BPF based SPI mockup controller
@ 2023-11-18 10:44 Zhang Xiaoxu
  2023-11-18 10:44 ` [PATCH v4 -next 1/4] spi: mockup: Add SPI controller testing driver Zhang Xiaoxu
                   ` (3 more replies)
  0 siblings, 4 replies; 6+ messages in thread
From: Zhang Xiaoxu @ 2023-11-18 10:44 UTC (permalink / raw)
  To: zhangxiaoxu5, weiyongjun1, linux-kernel, broonie, rostedt, mingo,
	frowand.list, linux-spi

From: Zhang Xiaoxu <zhangxiaoxu@huawe.com>

v3->v4:
  Use configfs to register the controller and target
  Modify with the comments from Mark Brown

v2->v3:
  Add configfs to configure and register the device;
  Fix some misspelling.

v1->v2:
  Use the new _controller() API
  P1. Move the license identifier to the entrie comment
  P2. Inherit tx_nbits/rx_nbits/cs_off/cs_change from the
      spi_transfer to the tracepoint
  P3. Removed.
  P4. Update the Document.

Zhang Xiaoxu (4):
  spi: mockup: Add SPI controller testing driver
  spi: mockup: Add register spi device support
  spi: mockup: Add writeable tracepoint for spi transfer
  spi: mockup: Add documentation

 Documentation/spi/index.rst       |   1 +
 Documentation/spi/spi-mockup.rst  | 198 +++++++++++
 drivers/spi/Kconfig               |  12 +
 drivers/spi/Makefile              |   1 +
 drivers/spi/spi-mockup.c          | 562 ++++++++++++++++++++++++++++++
 include/linux/spi/spi-mockup.h    |  17 +
 include/trace/events/spi_mockup.h |  31 ++
 7 files changed, 822 insertions(+)
 create mode 100644 Documentation/spi/spi-mockup.rst
 create mode 100644 drivers/spi/spi-mockup.c
 create mode 100644 include/linux/spi/spi-mockup.h
 create mode 100644 include/trace/events/spi_mockup.h

-- 
2.34.1


^ permalink raw reply	[flat|nested] 6+ messages in thread

* [PATCH v4 -next 1/4] spi: mockup: Add SPI controller testing driver
  2023-11-18 10:44 [PATCH v4 -next 0/4] spi: Introduce BPF based SPI mockup controller Zhang Xiaoxu
@ 2023-11-18 10:44 ` Zhang Xiaoxu
  2023-11-18 10:44 ` [PATCH v4 -next 2/4] spi: mockup: Add register spi device support Zhang Xiaoxu
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 6+ messages in thread
From: Zhang Xiaoxu @ 2023-11-18 10:44 UTC (permalink / raw)
  To: zhangxiaoxu5, weiyongjun1, linux-kernel, broonie, rostedt, mingo,
	frowand.list, linux-spi

From: Zhang Xiaoxu <zhangxiaoxu5@huawei.com>

This enables SPI controller testing driver, which provides a
way to test SPI subsystem. Its controlled by configfs and can
by use as below:

Create the controller by executing the following command:

  $ mkdir /config/spi-mockup/spi0

Configure it by:

  $ echo 40000 > /config/spi-mockup/spi0/min_speed
  $ echo 25000000 > /config/spi-mockup/spi0/max_speed
  $ echo 0 > /config/spi-mockup/spi0/flags
  $ echo 8 > /config/spi-mockup/spi0/num_cs

Enable:  $ echo 1 > /config/spi-mockup/spi0/live
Disable: $ echo 0 > /config/spi-mockup/spi0/live
Remove:  $ rmdir /config/spi-mockup/spi0

Signed-off-by: Wei Yongjun <weiyongjun1@huawei.com>
Signed-off-by: Zhang Xiaoxu <zhangxiaoxu5@huawei.com>
---
 drivers/spi/Kconfig      |  11 ++
 drivers/spi/Makefile     |   1 +
 drivers/spi/spi-mockup.c | 305 +++++++++++++++++++++++++++++++++++++++
 3 files changed, 317 insertions(+)
 create mode 100644 drivers/spi/spi-mockup.c

diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index 35dbfacecf1c..6524735a4936 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -1230,6 +1230,17 @@ config SPI_TLE62X0
 	  sysfs interface, with each line presented as a kind of GPIO
 	  exposing both switch control and diagnostic feedback.
 
+config SPI_MOCKUP
+	tristate "SPI controller Testing Driver"
+	help
+	  This enables SPI controller testing driver, which provides a way to
+	  test SPI subsystem.
+
+	  If you do build this module, be sure to read the notes and warnings
+	  in <file:Documentation/spi/spi-mockup.rst>.
+
+	  If you don't know what to do here, definitely say N.
+
 #
 # Add new SPI protocol masters in alphabetical order above this line
 #
diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
index 4ff8d725ba5e..ab5a1a12b5ac 100644
--- a/drivers/spi/Makefile
+++ b/drivers/spi/Makefile
@@ -12,6 +12,7 @@ obj-$(CONFIG_SPI_MEM)			+= spi-mem.o
 obj-$(CONFIG_SPI_MUX)			+= spi-mux.o
 obj-$(CONFIG_SPI_SPIDEV)		+= spidev.o
 obj-$(CONFIG_SPI_LOOPBACK_TEST)		+= spi-loopback-test.o
+obj-$(CONFIG_SPI_MOCKUP)		+= spi-mockup.o
 
 # SPI master controller drivers (bus)
 obj-$(CONFIG_SPI_ALTERA)		+= spi-altera-platform.o
diff --git a/drivers/spi/spi-mockup.c b/drivers/spi/spi-mockup.c
new file mode 100644
index 000000000000..acb502c14676
--- /dev/null
+++ b/drivers/spi/spi-mockup.c
@@ -0,0 +1,305 @@
+/*
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ *
+ * SPI controller Testing Driver
+ *
+ * Copyright(c) 2022 Huawei Technologies Co., Ltd.
+ */
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+#include <linux/platform_device.h>
+#include <linux/spi/spi.h>
+#include <linux/configfs.h>
+
+#define MOCKUP_CHIPSELECT_MAX	U16_MAX
+
+struct spi_mockup_host {
+	struct config_group group;
+
+	struct mutex lock;
+
+	unsigned int bus_nr;
+	u32 min_speed;
+	u32 max_speed;
+	u16 flags;
+	u16 num_cs;
+
+	struct platform_device *pdev;
+	struct spi_controller *ctrl;
+};
+
+static struct spi_mockup_host *to_spi_mockup_host(struct config_item *item)
+{
+	struct config_group *group = to_config_group(item);
+
+	return container_of(group, struct spi_mockup_host, group);
+}
+
+static ssize_t __host_online(struct spi_mockup_host *host)
+{
+	int ret;
+	struct platform_device_info pdevinfo = {0};
+
+	if (host->pdev)
+		return -EEXIST;
+
+	pdevinfo.name = "spi-mockup";
+	pdevinfo.id = host->bus_nr;
+
+	/* Use the pointer of host as the data, then probe
+	 * can init the host->ctrl */
+	pdevinfo.data = &host;
+	pdevinfo.size_data = sizeof(&host);
+
+	host->pdev = platform_device_register_full(&pdevinfo);
+	if (IS_ERR(host->pdev)) {
+		ret = PTR_ERR(host->pdev);
+		host->pdev = NULL;
+		return ret;
+	}
+
+	return 0;
+}
+
+static ssize_t __host_offline(struct spi_mockup_host *host)
+{
+	if (!host->pdev)
+		return -ENODEV;
+
+	platform_device_unregister(host->pdev);
+	host->pdev = NULL;
+	host->ctrl = NULL;
+
+	return 0;
+}
+
+static ssize_t
+spi_mockup_live_store(struct config_item *item, const char *buf, size_t len)
+{
+	struct spi_mockup_host *host = to_spi_mockup_host(item);
+	int ret;
+	bool res;
+
+	ret = kstrtobool(buf, &res);
+	if (ret)
+		return ret;
+
+	mutex_lock(&host->lock);
+	if (res)
+		ret = __host_online(host);
+	else
+		ret = __host_offline(host);
+	mutex_unlock(&host->lock);
+
+	return ret ? ret : len;
+}
+
+static ssize_t
+spi_mockup_live_show(struct config_item *item, char *buf)
+{
+	struct spi_mockup_host *host = to_spi_mockup_host(item);
+
+	return sprintf(buf, "%s", (host->pdev) ? "true" : "false");
+}
+CONFIGFS_ATTR(spi_mockup_, live);
+
+
+#define SPI_MOCKUP_ATTR(type, name)					  \
+static ssize_t spi_mockup_ ## name ## _store(struct config_item *item,	  \
+					     const char *buf, size_t len) \
+{									  \
+	int ret;							  \
+	type val;							  \
+	struct spi_mockup_host *host = to_spi_mockup_host(item);	  \
+									  \
+	mutex_lock(&host->lock);					  \
+	if (host->pdev) {						  \
+		ret = -EBUSY;						  \
+		goto out;						  \
+	}								  \
+									  \
+	ret = kstrto ## type(buf, 0, &val);				  \
+	if (ret)							  \
+		goto out;						  \
+									  \
+	host->name = val;						  \
+out:									  \
+	mutex_unlock(&host->lock);					  \
+	return ret ? ret : len;						  \
+}									  \
+static ssize_t spi_mockup_ ## name ## _show(struct config_item *item,	  \
+					    char *buf)			  \
+{									  \
+	struct spi_mockup_host *host = to_spi_mockup_host(item);	  \
+	return sprintf(buf, "%u", host->name);                            \
+}                                                                         \
+CONFIGFS_ATTR(spi_mockup_, name)					  \
+
+SPI_MOCKUP_ATTR(u32, min_speed);
+SPI_MOCKUP_ATTR(u32, max_speed);
+SPI_MOCKUP_ATTR(u16, flags);
+SPI_MOCKUP_ATTR(u16, num_cs);
+
+static struct configfs_attribute *spi_mockup_host_attrs[] = {
+	&spi_mockup_attr_live,
+	&spi_mockup_attr_min_speed,
+	&spi_mockup_attr_max_speed,
+	&spi_mockup_attr_flags,
+	&spi_mockup_attr_num_cs,
+	NULL,
+};
+
+static void spi_mockup_host_release(struct config_item *item)
+{
+	struct spi_mockup_host *host = to_spi_mockup_host(item);
+
+	__host_offline(host);
+	kfree(host);
+}
+
+static struct configfs_item_operations spi_mockup_host_item_ops = {
+	.release = spi_mockup_host_release,
+};
+
+static const struct config_item_type spi_mockup_host_config_group_type = {
+	.ct_owner	= THIS_MODULE,
+	.ct_attrs	= spi_mockup_host_attrs,
+	.ct_item_ops	= &spi_mockup_host_item_ops,
+};
+
+static struct config_group *
+spi_mockup_host_make_group(struct config_group *group, const char *name)
+{
+	int ret, nchar;
+	unsigned int nr;
+	struct spi_mockup_host *host;
+
+	ret = sscanf(name, "spi%u%n", &nr, &nchar);
+	if (ret != 1 || nchar != strlen(name))
+		return ERR_PTR(-EINVAL);
+
+	host = kzalloc(sizeof(*host), GFP_KERNEL);
+	if (!host)
+		return ERR_PTR(-ENOMEM);
+
+	host->bus_nr = nr;
+	host->num_cs = MOCKUP_CHIPSELECT_MAX;
+	mutex_init(&host->lock);
+
+	config_group_init_type_name(&host->group, name,
+				    &spi_mockup_host_config_group_type);
+
+	return &host->group;
+}
+
+static struct configfs_group_operations spi_mockup_host_group_ops = {
+	.make_group = spi_mockup_host_make_group,
+};
+
+static const struct config_item_type spi_mockup_host_type = {
+	.ct_owner	= THIS_MODULE,
+	.ct_group_ops	= &spi_mockup_host_group_ops,
+};
+
+static struct configfs_subsystem spi_mockup_config_subsys = {
+	.su_group = {
+		.cg_item = {
+			.ci_namebuf = "spi-mockup",
+			.ci_type = &spi_mockup_host_type,
+		}
+	}
+};
+
+static int
+spi_mockup_transfer(struct spi_controller *ctrl, struct spi_message *msg)
+{
+	msg->status = 0;
+	spi_finalize_current_message(ctrl);
+
+	return 0;
+}
+
+static int
+spi_mockup_probe(struct platform_device *pdev)
+{
+	int ret;
+	struct spi_controller *ctrl;
+	struct spi_mockup_host **host;
+
+	host = dev_get_platdata(&pdev->dev);
+	if (!host || !(*host))
+		return -EINVAL;
+
+	ctrl = spi_alloc_host(&pdev->dev, 0);
+	if (!ctrl) {
+		pr_err("failed to alloc spi controller\n");
+		return -ENOMEM;
+	}
+
+	platform_set_drvdata(pdev, ctrl);
+
+	ctrl->bus_num = pdev->id;
+	ctrl->mode_bits = SPI_MODE_USER_MASK;
+	ctrl->dev.of_node = pdev->dev.of_node;
+	ctrl->transfer_one_message = spi_mockup_transfer;
+	ctrl->min_speed_hz = (*host)->min_speed;
+	ctrl->max_speed_hz = (*host)->max_speed;
+	ctrl->num_chipselect = (*host)->num_cs;
+	ctrl->flags = (*host)->flags;
+
+	ret = devm_spi_register_controller(&pdev->dev, ctrl);
+	if (ret) {
+		spi_controller_put(ctrl);
+		return ret;
+	}
+
+	(*host)->ctrl = ctrl;
+
+	return 0;
+}
+
+static struct platform_driver spi_mockup_driver = {
+	.probe = spi_mockup_probe,
+	.driver = {
+		.name = "spi-mockup",
+	},
+};
+
+static int __init spi_mockup_init(void)
+{
+	int ret;
+
+	ret = platform_driver_register(&spi_mockup_driver);
+	if (ret) {
+		pr_err("spi mockup driver registering failed with %d\n", ret);
+		return ret;
+	}
+
+	config_group_init(&spi_mockup_config_subsys.su_group);
+	mutex_init(&spi_mockup_config_subsys.su_mutex);
+	ret = configfs_register_subsystem(&spi_mockup_config_subsys);
+	if (ret) {
+		pr_err("spi mockup configfs registering failed with %d\n", ret);
+		mutex_destroy(&spi_mockup_config_subsys.su_mutex);
+		platform_driver_unregister(&spi_mockup_driver);
+		return ret;
+	}
+
+	return ret;
+}
+module_init(spi_mockup_init);
+
+static void __exit spi_mockup_exit(void)
+{
+	configfs_unregister_subsystem(&spi_mockup_config_subsys);
+	mutex_destroy(&spi_mockup_config_subsys.su_mutex);
+	return platform_driver_unregister(&spi_mockup_driver);
+}
+module_exit(spi_mockup_exit);
+
+MODULE_AUTHOR("Wei Yongjun <weiyongjun1@huawei.com>");
+MODULE_DESCRIPTION("SPI controller Testing Driver");
+MODULE_LICENSE("GPL");
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH v4 -next 2/4] spi: mockup: Add register spi device support
  2023-11-18 10:44 [PATCH v4 -next 0/4] spi: Introduce BPF based SPI mockup controller Zhang Xiaoxu
  2023-11-18 10:44 ` [PATCH v4 -next 1/4] spi: mockup: Add SPI controller testing driver Zhang Xiaoxu
@ 2023-11-18 10:44 ` Zhang Xiaoxu
  2023-11-19 17:04   ` kernel test robot
  2023-11-18 10:44 ` [PATCH v4 -next 3/4] spi: mockup: Add writeable tracepoint for spi transfer Zhang Xiaoxu
  2023-11-18 10:44 ` [PATCH v4 -next 4/4] spi: mockup: Add documentation Zhang Xiaoxu
  3 siblings, 1 reply; 6+ messages in thread
From: Zhang Xiaoxu @ 2023-11-18 10:44 UTC (permalink / raw)
  To: zhangxiaoxu5, weiyongjun1, linux-kernel, broonie, rostedt, mingo,
	frowand.list, linux-spi

From: Zhang Xiaoxu <zhangxiaoxu5@huawei.com>

This enable register the spi device to mockup host, it depends
configfs. After enable the mockup host, register the device by
executing the following command:

  $ mkdir /config/spi-mockup/spi0/max31722
  $ echo -n max31722 > /config/spi-mockup/spi0/max31722/device_id
  $ echo 1 > /config/spi-mockup/spi0/max31722/live

Unregister by:

  $ echo 0 > /config/spi-mockup/spi0/max31722/live
  $ rmdir /config/spi-mockup/spi0/max31722

Signed-off-by: Zhang Xiaoxu <zhangxiaoxu@huawei.com>
---
 drivers/spi/spi-mockup.c | 208 +++++++++++++++++++++++++++++++++++++++
 1 file changed, 208 insertions(+)

diff --git a/drivers/spi/spi-mockup.c b/drivers/spi/spi-mockup.c
index acb502c14676..f053579cc37f 100644
--- a/drivers/spi/spi-mockup.c
+++ b/drivers/spi/spi-mockup.c
@@ -18,6 +18,7 @@
 
 struct spi_mockup_host {
 	struct config_group group;
+	struct config_group targets_group;
 
 	struct mutex lock;
 
@@ -29,6 +30,7 @@ struct spi_mockup_host {
 
 	struct platform_device *pdev;
 	struct spi_controller *ctrl;
+	unsigned long bitmap[BITS_TO_LONGS(MOCKUP_CHIPSELECT_MAX)];
 };
 
 static struct spi_mockup_host *to_spi_mockup_host(struct config_item *item)
@@ -38,6 +40,205 @@ static struct spi_mockup_host *to_spi_mockup_host(struct config_item *item)
 	return container_of(group, struct spi_mockup_host, group);
 }
 
+static struct spi_mockup_host *
+to_spi_mockup_host_from_targets(struct config_group *targets_group)
+{
+	return container_of(targets_group,
+			    struct spi_mockup_host, targets_group);
+}
+
+struct spi_mockup_target {
+	struct config_group group;
+	unsigned short chip;
+	char device_id[SPI_NAME_SIZE];
+	struct spi_device *spi;
+	struct spi_mockup_host *host;
+};
+
+static struct spi_mockup_target *to_spi_mockup_target(struct config_item *item)
+{
+	struct config_group *group = to_config_group(item);
+
+	return container_of(group, struct spi_mockup_target, group);
+}
+
+static ssize_t
+spi_mockup_target_device_id_show(struct config_item *item, char *buf)
+{
+	struct spi_mockup_target *target = to_spi_mockup_target(item);
+
+	return sprintf(buf, "%s\n", target->device_id);
+}
+
+static ssize_t
+spi_mockup_target_device_id_store(struct config_item *item,
+				  const char *buf, size_t len)
+{
+	struct spi_mockup_target *target = to_spi_mockup_target(item);
+
+	if (len > SPI_NAME_SIZE)
+		return -EINVAL;
+
+	memcpy(target->device_id, buf, len);
+
+	return len;
+}
+CONFIGFS_ATTR(spi_mockup_target_, device_id);
+
+static int __target_online(struct spi_mockup_target *target)
+{
+	struct spi_board_info info = {0};
+	struct device *dev;
+
+	if (target->spi)
+		return -EBUSY;
+
+	if (!target->host->pdev)
+		return -ENODEV;
+
+	target->chip = find_first_zero_bit(target->host->bitmap,
+					   MOCKUP_CHIPSELECT_MAX);
+	if (target->chip < 0)
+		return target->chip;
+
+	if (target->chip > target->host->num_cs)
+		return -EBUSY;
+
+	info.chip_select = target->chip;
+	strncpy(info.modalias, target->device_id,
+		strlen(target->device_id));
+
+	target->spi = spi_new_device(target->host->ctrl, &info);
+	if (!target->spi)
+		return -ENOMEM;
+
+	bitmap_set(target->host->bitmap, target->chip, 1);
+
+	dev = &target->host->ctrl->dev;
+	dev_info(dev, "Instantiated device %s at 0x%02x\n",
+		 info.modalias, info.chip_select);
+
+	return 0;
+}
+
+static int __target_offline(struct spi_mockup_target *target)
+{
+	struct device *dev;
+
+	if (!target->spi)
+		return -ENODEV;
+
+	dev = &target->host->ctrl->dev;
+	dev_info(dev, "Deleting device %s at 0x%02hx\n",
+		 dev_name(&target->spi->dev), target->chip);
+
+	spi_unregister_device(target->spi);
+	target->spi = NULL;
+
+	bitmap_clear(target->host->bitmap, target->chip, 1);
+
+
+	return 0;
+}
+
+static ssize_t
+spi_mockup_target_live_store(struct config_item *item,
+			     const char *buf, size_t len)
+{
+	struct spi_mockup_target *target = to_spi_mockup_target(item);
+	int ret;
+	bool res;
+
+	ret = kstrtobool(buf, &res);
+	if (ret)
+		return -EINVAL;
+
+	if (!strlen(target->device_id))
+		return -EINVAL;
+
+	mutex_lock(&target->host->lock);
+	if (res)
+		ret = __target_online(target);
+	else
+		ret = __target_offline(target);
+	mutex_unlock(&target->host->lock);
+
+	return ret ? ret : len;
+}
+
+static ssize_t
+spi_mockup_target_live_show(struct config_item *item, char *buf)
+{
+	struct spi_mockup_target *target = to_spi_mockup_target(item);
+
+	return sprintf(buf, "%s\n", (target->spi) ? "true" : "false");
+}
+CONFIGFS_ATTR(spi_mockup_target_, live);
+
+
+static struct configfs_attribute *spi_mockup_target_attrs[] = {
+	&spi_mockup_target_attr_device_id,
+	&spi_mockup_target_attr_live,
+	NULL,
+};
+
+static void spi_mockup_target_release(struct config_item *item)
+{
+	struct spi_mockup_target *target = to_spi_mockup_target(item);
+
+	__target_offline(target);
+	kfree(target);
+}
+
+static struct configfs_item_operations spi_mockup_target_item_ops = {
+	.release = spi_mockup_target_release,
+};
+
+static const struct config_item_type spi_mockup_target_item_type = {
+	.ct_owner	= THIS_MODULE,
+	.ct_attrs	= spi_mockup_target_attrs,
+	.ct_item_ops    = &spi_mockup_target_item_ops,
+};
+
+static struct config_group *
+spi_mockup_target_make_group(struct config_group *group, const char *name)
+{
+	struct spi_mockup_target *target;
+	struct spi_mockup_host *host = to_spi_mockup_host_from_targets(group);
+
+	target = kzalloc(sizeof(*target), GFP_KERNEL);
+	if (!target)
+		return ERR_PTR(-ENOMEM);
+
+	target->host = host;
+
+	config_group_init_type_name(&target->group, name,
+				    &spi_mockup_target_item_type);
+
+	return &target->group;
+}
+
+static struct configfs_group_operations spi_mockup_targets_group_ops = {
+	.make_group = spi_mockup_target_make_group,
+};
+
+static void spi_mockup_targets_group_release(struct config_item *item)
+{
+	struct spi_mockup_target *target = to_spi_mockup_target(item);
+
+	kfree(target);
+}
+
+static struct configfs_item_operations spi_mockup_targets_group_item_ops = {
+	.release = spi_mockup_targets_group_release,
+};
+
+static const struct config_item_type spi_mockup_target_type = {
+	.ct_owner     = THIS_MODULE,
+	.ct_group_ops = &spi_mockup_targets_group_ops,
+	.ct_item_ops  = &spi_mockup_targets_group_item_ops,
+};
+
 static ssize_t __host_online(struct spi_mockup_host *host)
 {
 	int ret;
@@ -69,6 +270,9 @@ static ssize_t __host_offline(struct spi_mockup_host *host)
 	if (!host->pdev)
 		return -ENODEV;
 
+	if (!bitmap_empty(host->bitmap, host->num_cs))
+		return -EBUSY;
+
 	platform_device_unregister(host->pdev);
 	host->pdev = NULL;
 	host->ctrl = NULL;
@@ -192,6 +396,10 @@ spi_mockup_host_make_group(struct config_group *group, const char *name)
 	config_group_init_type_name(&host->group, name,
 				    &spi_mockup_host_config_group_type);
 
+	config_group_init_type_name(&host->targets_group, "targets",
+				    &spi_mockup_target_type);
+	configfs_add_default_group(&host->targets_group, &host->group);
+
 	return &host->group;
 }
 
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH v4 -next 3/4] spi: mockup: Add writeable tracepoint for spi transfer
  2023-11-18 10:44 [PATCH v4 -next 0/4] spi: Introduce BPF based SPI mockup controller Zhang Xiaoxu
  2023-11-18 10:44 ` [PATCH v4 -next 1/4] spi: mockup: Add SPI controller testing driver Zhang Xiaoxu
  2023-11-18 10:44 ` [PATCH v4 -next 2/4] spi: mockup: Add register spi device support Zhang Xiaoxu
@ 2023-11-18 10:44 ` Zhang Xiaoxu
  2023-11-18 10:44 ` [PATCH v4 -next 4/4] spi: mockup: Add documentation Zhang Xiaoxu
  3 siblings, 0 replies; 6+ messages in thread
From: Zhang Xiaoxu @ 2023-11-18 10:44 UTC (permalink / raw)
  To: zhangxiaoxu5, weiyongjun1, linux-kernel, broonie, rostedt, mingo,
	frowand.list, linux-spi

From: Zhang Xiaoxu <zhangxiaoxu5@huawei.com>

Add writeable tracepoint for transfer_one_message(), then bpf program
can be used to control read and write data from spi host, as mockup
chip's expectation.

For example:

  #include "vmlinux.h"
  #include <bpf/bpf_helpers.h>
  #include <bpf/bpf_tracing.h>

  SEC("raw_tp.w/spi_transfer_writeable")
  int BPF_PROG(spi_transfer_writeable_test, struct spi_msg_ctx *msg,
               u8 chip, unsigned int len)
  {
      if (msg->tx_nbits)
          msg->data[0] = 0x20;

      return 0;
  }

  char LICENSE[] SEC("license") = "GPL";

This will be useful for writing spi device mockup backend.

Signed-off-by: Wei Yongjun <weiyongjun1@huawei.com>
Signed-off-by: Zhang Xiaoxu <zhangxiaoxu5@huawei.com>
---
 drivers/spi/Kconfig               |  1 +
 drivers/spi/spi-mockup.c          | 53 +++++++++++++++++++++++++++++--
 include/linux/spi/spi-mockup.h    | 17 ++++++++++
 include/trace/events/spi_mockup.h | 31 ++++++++++++++++++
 4 files changed, 100 insertions(+), 2 deletions(-)
 create mode 100644 include/linux/spi/spi-mockup.h
 create mode 100644 include/trace/events/spi_mockup.h

diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index 6524735a4936..aee2dfcc9e54 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -1232,6 +1232,7 @@ config SPI_TLE62X0
 
 config SPI_MOCKUP
 	tristate "SPI controller Testing Driver"
+	select BPF_EVENTS
 	help
 	  This enables SPI controller testing driver, which provides a way to
 	  test SPI subsystem.
diff --git a/drivers/spi/spi-mockup.c b/drivers/spi/spi-mockup.c
index f053579cc37f..a86bd6c7bd2e 100644
--- a/drivers/spi/spi-mockup.c
+++ b/drivers/spi/spi-mockup.c
@@ -14,6 +14,9 @@
 #include <linux/spi/spi.h>
 #include <linux/configfs.h>
 
+#define CREATE_TRACE_POINTS
+#include <trace/events/spi_mockup.h>
+
 #define MOCKUP_CHIPSELECT_MAX	U16_MAX
 
 struct spi_mockup_host {
@@ -421,13 +424,59 @@ static struct configfs_subsystem spi_mockup_config_subsys = {
 	}
 };
 
+static int
+spi_mockup_transfer_writeable(struct spi_message *msg)
+{
+	struct spi_msg_ctx *ctx;
+	struct spi_transfer *t;
+	int ret = 0;
+
+	ctx = kmalloc(sizeof(*ctx), GFP_ATOMIC);
+	if (!ctx)
+		return -ENOMEM;
+
+	list_for_each_entry(t, &msg->transfers, transfer_list) {
+		if (t->len > SPI_BUFSIZ_MAX)
+			return -E2BIG;
+
+		memset(ctx, 0, sizeof(*ctx));
+		ctx->cs_off = t->cs_off;
+		ctx->cs_change = t->cs_change;
+		ctx->tx_nbits = t->tx_nbits;
+		ctx->rx_nbits = t->rx_nbits;
+
+		if (t->tx_nbits)
+			memcpy(ctx->data, t->tx_buf, t->len);
+
+		trace_spi_transfer_writeable(ctx, msg->spi->chip_select, t->len);
+
+		if (ctx->ret) {
+			ret = ctx->ret;
+			break;
+		}
+
+		if (t->rx_nbits)
+			memcpy(t->rx_buf, ctx->data, t->len);
+		msg->actual_length += t->len;
+	}
+
+	kfree(ctx);
+
+	return ret;
+}
+
 static int
 spi_mockup_transfer(struct spi_controller *ctrl, struct spi_message *msg)
 {
-	msg->status = 0;
+	int ret = 0;
+
+	if (trace_spi_transfer_writeable_enabled())
+		ret = spi_mockup_transfer_writeable(msg);
+
+	msg->status = ret;
 	spi_finalize_current_message(ctrl);
 
-	return 0;
+	return ret;
 }
 
 static int
diff --git a/include/linux/spi/spi-mockup.h b/include/linux/spi/spi-mockup.h
new file mode 100644
index 000000000000..224894b416fb
--- /dev/null
+++ b/include/linux/spi/spi-mockup.h
@@ -0,0 +1,17 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+#ifndef __LINUX_SPI_MOCKUP_H
+#define __LINUX_SPI_MOCKUP_H
+
+#define SPI_BUFSIZ_MAX		0x1000
+
+struct spi_msg_ctx {
+	int ret;
+	unsigned cs_off:1;
+	unsigned cs_change:1;
+	unsigned tx_nbits:3;
+	unsigned rx_nbits:3;
+	__u8 data[SPI_BUFSIZ_MAX];
+};
+
+#endif
diff --git a/include/trace/events/spi_mockup.h b/include/trace/events/spi_mockup.h
new file mode 100644
index 000000000000..46debf26a5e3
--- /dev/null
+++ b/include/trace/events/spi_mockup.h
@@ -0,0 +1,31 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * SPI mockup controller transfer writeable tracepoint
+ *
+ * Copyright(c) 2022 Huawei Technologies Co., Ltd.
+ */
+
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM spi_mockup
+
+#if !defined(_TRACE_SPI_MOCKUP_H) || defined(TRACE_HEADER_MULTI_READ)
+#define _TRACE_SPI_MOCKUP_H
+
+#include <linux/tracepoint.h>
+#include <linux/spi/spi-mockup.h>
+
+#ifndef DECLARE_TRACE_WRITABLE
+#define DECLARE_TRACE_WRITABLE(call, proto, args, size) \
+	DECLARE_TRACE(call, PARAMS(proto), PARAMS(args))
+#endif
+
+DECLARE_TRACE_WRITABLE(spi_transfer_writeable,
+	TP_PROTO(struct spi_msg_ctx *msg, u8 chip_select, unsigned int len),
+	TP_ARGS(msg, chip_select, len),
+	sizeof(struct spi_msg_ctx)
+);
+
+#endif /* _TRACE_SPI_MOCKUP_H */
+
+/* This part must be outside protection */
+#include <trace/define_trace.h>
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH v4 -next 4/4] spi: mockup: Add documentation
  2023-11-18 10:44 [PATCH v4 -next 0/4] spi: Introduce BPF based SPI mockup controller Zhang Xiaoxu
                   ` (2 preceding siblings ...)
  2023-11-18 10:44 ` [PATCH v4 -next 3/4] spi: mockup: Add writeable tracepoint for spi transfer Zhang Xiaoxu
@ 2023-11-18 10:44 ` Zhang Xiaoxu
  3 siblings, 0 replies; 6+ messages in thread
From: Zhang Xiaoxu @ 2023-11-18 10:44 UTC (permalink / raw)
  To: zhangxiaoxu5, weiyongjun1, linux-kernel, broonie, rostedt, mingo,
	frowand.list, linux-spi

From: Zhang Xiaoxu <zhangxiaoxu5@huawei.com>

Add documentation for the SPI mockup controller driver.
This include the tutorial for how to mockup a spi device.

Signed-off-by: Wei Yongjun <weiyongjun1@huawei.com>
Signed-off-by: Zhang Xiaoxu <zhangxiaoxu5@huawei.com>
---
 Documentation/spi/index.rst      |   1 +
 Documentation/spi/spi-mockup.rst | 198 +++++++++++++++++++++++++++++++
 2 files changed, 199 insertions(+)
 create mode 100644 Documentation/spi/spi-mockup.rst

diff --git a/Documentation/spi/index.rst b/Documentation/spi/index.rst
index 06c34ea11bcf..a8f4f5cd0f09 100644
--- a/Documentation/spi/index.rst
+++ b/Documentation/spi/index.rst
@@ -13,6 +13,7 @@ Serial Peripheral Interface (SPI)
    pxa2xx
    spi-lm70llp
    spi-sc18is602
+   spi-mockup
 
 .. only::  subproject and html
 
diff --git a/Documentation/spi/spi-mockup.rst b/Documentation/spi/spi-mockup.rst
new file mode 100644
index 000000000000..a5b69ce83ad9
--- /dev/null
+++ b/Documentation/spi/spi-mockup.rst
@@ -0,0 +1,198 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+==========
+spi-mockup
+==========
+
+Description
+===========
+
+This module is a very simple fake SPI controller driver. It implements
+a BPF based interface to mockup SPI device.
+
+No hardware is needed nor associated with this module. It will respond
+spi message by BPF program attached to spi_transfer_writeable tracepoint
+by reading from or writing BPF maps.
+
+The typical use-case is like this:
+        1. create the spi mockup controller;
+        2. load EBPF program as device's backend;
+        3. create target chip device to the spi mockup controller.
+
+Example
+=======
+
+This example show how to mock a MTD device by using spi-mockup driver.
+
+Compile your copy of the kernel source. Make sure to configure the spi-mockup
+and the target chip driver as a module.
+
+Register the spi mockup controller.
+
+::
+
+  $ mkdir /sys/kernel/config/spi-mockup/spi0
+
+  # configure the spi mockup controller attribute
+  $ echo 40000 > /sys/kernel/config/spi-mockup/spi0/min_speed
+  $ echo 25000000 > /sys/kernel/config/spi-mockup/spi0/max_speed
+  $ echo 0 > /sys/kernel/config/spi-mockup/spi0/flags
+  $ echo 8 > /sys/kernel/config/spi-mockup/spi0/num_cs
+
+  # enable the spi mockup controller
+  $ echo 1 > /sys/kernel/config/spi-mockup/spi0/live
+
+Write a BPF program as device's backup.
+
+::
+
+  #define MCHP23K256_CMD_WRITE_STATUS   0x01
+  #define MCHP23K256_CMD_WRITE          0x02
+  #define MCHP23K256_CMD_READ           0x03
+
+  #define CHIP_REGS_SIZE		0x20000
+
+  #define MAX_CMD_SIZE		        4
+
+  struct {
+	__uint(type, BPF_MAP_TYPE_ARRAY);
+	__uint(max_entries, CHIP_REGS_SIZE);
+	__type(key, __u32);
+	__type(value, __u8);
+  } regs_mchp23k256 SEC(".maps");
+
+  static unsigned int chip_reg = 0;
+
+  static int spi_transfer_read(struct spi_msg_ctx *msg, unsigned int len)
+  {
+	int i, key;
+	u8 *reg;
+
+	for (i = 0; i < len && i < sizeof(msg->data); i++) {
+		key = i + chip_reg;
+
+		reg = bpf_map_lookup_elem(&regs_mchp23k256, &key);
+		if (!reg) {
+			bpf_printk("key %d not exists", key);
+			return -EINVAL;
+		}
+
+		msg->data[i] = *reg;
+	}
+
+	return 0;
+  }
+
+  static int spi_transfer_write(struct spi_msg_ctx *msg, unsigned int len)
+  {
+	u8 opcode = msg->data[0], value;
+	int i, key;
+
+	switch (opcode) {
+	case MCHP23K256_CMD_READ:
+	case MCHP23K256_CMD_WRITE:
+		if (len < 2)
+			return -EINVAL;
+
+		chip_reg = 0;
+		for (i = 0; i < MAX_CMD_SIZE && i < len - 1; i++)
+			chip_reg = (chip_reg << 8) + msg->data[1 + i];
+
+		return 0;
+	case MCHP23K256_CMD_WRITE_STATUS:
+		// ignore write status
+		return 0;
+	default:
+		break;
+	}
+
+	for (i = 0; i < len && i < sizeof(msg->data); i++) {
+		value = msg->data[i];
+		key = chip_reg + i;
+
+		if (bpf_map_update_elem(&regs_mchp23k256, &key, &value,
+					BPF_EXIST)) {
+			bpf_printk("key %d not exists", key);
+			return -EINVAL;
+		}
+	}
+
+	return 0;
+  }
+
+  SEC("raw_tp.w/spi_transfer_writeable")
+  int BPF_PROG(mtd_mchp23k256, struct spi_msg_ctx *msg, u8 chip, unsigned int len)
+  {
+	int ret = 0;
+
+	if (msg->tx_nbits)
+		ret = spi_transfer_write(msg, len);
+	else if (msg->rx_nbits)
+		ret = spi_transfer_read(msg, len);
+
+	return ret;
+  }
+
+  char LICENSE[] SEC("license") = "GPL";
+
+Use bpftool to load the BPF program.
+
+::
+
+  $ bpftool prog load mtd-mchp23k256.o /sys/fs/bpf/mtd_mchp23k256 autoattach
+
+Create the mchp23k256 device, this is accomplished by executing the
+following command:
+
+::
+
+  $ mkdir /sys/kernel/config/spi-mockup/spi0/targets/mchp23k256
+  $ echo -n mchp23k256 > /sys/kernel/config/spi-mockup/spi0/targets/mchp23k256/device_id
+  $ echo 1 > /sys/kernel/config/spi-mockup/spi0/targets/mchp23k256/live
+
+
+Now, the mchp23k256 MTD device named /dev/mtd0 has been created successfully.
+
+::
+
+  $ ls /sys/bus/spi/devices/spi0.0/mtd/
+  mtd0  mtd0ro
+
+  $ cat /sys/class/mtd/mtd0/name
+  spi0.0
+
+  $ hexdump /dev/mtd0
+  0000000 0000 0000 0000 0000 0000 0000 0000 0000
+  *
+  0008000
+
+  $ echo aaaa > /dev/mtd0
+
+  $ hexdump /dev/mtd0
+  00000000  61 61 61 61 0a 00 00 00  00 00 00 00 00 00 00 00  |aaaa............|
+  00000010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
+  *
+  00008000
+
+  $ bpftool map update name regs_mchp23k256 key 0 0 0 0 value 0
+
+  $ hexdump /dev/mtd0
+  00000000  00 61 61 61 0a 00 00 00  00 00 00 00 00 00 00 00  |.aaa............|
+  00000010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
+  *
+  00008000
+
+
+Remove the mchp23k256 device by executing the following command:
+
+::
+
+  $ echo 0 > /sys/kernel/config/spi-mockup/spi0/targets/mchp23k256/live
+  $ rmdir /sys/kernel/config/spi-mockup/spi0/targets/mchp23k256
+
+Remove the spi mockup controller by executing the following command:
+
+::
+
+  $ echo 0 > /sys/kernel/config/spi-mockup/spi0/live
+  $ rmdir /sys/kernel/config/spi-mockup/spi0
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* Re: [PATCH v4 -next 2/4] spi: mockup: Add register spi device support
  2023-11-18 10:44 ` [PATCH v4 -next 2/4] spi: mockup: Add register spi device support Zhang Xiaoxu
@ 2023-11-19 17:04   ` kernel test robot
  0 siblings, 0 replies; 6+ messages in thread
From: kernel test robot @ 2023-11-19 17:04 UTC (permalink / raw)
  To: Zhang Xiaoxu, zhangxiaoxu5, weiyongjun1, linux-kernel, broonie,
	rostedt, mingo, frowand.list, linux-spi
  Cc: oe-kbuild-all

Hi Zhang,

kernel test robot noticed the following build warnings:

[auto build test WARNING on next-20231117]

url:    https://github.com/intel-lab-lkp/linux/commits/Zhang-Xiaoxu/spi-mockup-Add-SPI-controller-testing-driver/20231118-184747
base:   next-20231117
patch link:    https://lore.kernel.org/r/20231118104442.861759-3-zhangxiaoxu%40huawecloud.com
patch subject: [PATCH v4 -next 2/4] spi: mockup: Add register spi device support
config: openrisc-allmodconfig (https://download.01.org/0day-ci/archive/20231120/202311200018.xB4hEnZx-lkp@intel.com/config)
compiler: or1k-linux-gcc (GCC) 13.2.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20231120/202311200018.xB4hEnZx-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202311200018.xB4hEnZx-lkp@intel.com/

All warnings (new ones prefixed by >>):

   In function '__target_online',
       inlined from 'spi_mockup_target_live_store' at drivers/spi/spi-mockup.c:161:9:
>> drivers/spi/spi-mockup.c:108:9: warning: 'strncpy' specified bound depends on the length of the source argument [-Wstringop-truncation]
     108 |         strncpy(info.modalias, target->device_id,
         |         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     109 |                 strlen(target->device_id));
         |                 ~~~~~~~~~~~~~~~~~~~~~~~~~~
   drivers/spi/spi-mockup.c:108:9: note: length computed here
     108 |         strncpy(info.modalias, target->device_id,
         |         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     109 |                 strlen(target->device_id));
         |                 ~~~~~~~~~~~~~~~~~~~~~~~~~~


vim +/strncpy +108 drivers/spi/spi-mockup.c

    87	
    88	static int __target_online(struct spi_mockup_target *target)
    89	{
    90		struct spi_board_info info = {0};
    91		struct device *dev;
    92	
    93		if (target->spi)
    94			return -EBUSY;
    95	
    96		if (!target->host->pdev)
    97			return -ENODEV;
    98	
    99		target->chip = find_first_zero_bit(target->host->bitmap,
   100						   MOCKUP_CHIPSELECT_MAX);
   101		if (target->chip < 0)
   102			return target->chip;
   103	
   104		if (target->chip > target->host->num_cs)
   105			return -EBUSY;
   106	
   107		info.chip_select = target->chip;
 > 108		strncpy(info.modalias, target->device_id,
   109			strlen(target->device_id));
   110	
   111		target->spi = spi_new_device(target->host->ctrl, &info);
   112		if (!target->spi)
   113			return -ENOMEM;
   114	
   115		bitmap_set(target->host->bitmap, target->chip, 1);
   116	
   117		dev = &target->host->ctrl->dev;
   118		dev_info(dev, "Instantiated device %s at 0x%02x\n",
   119			 info.modalias, info.chip_select);
   120	
   121		return 0;
   122	}
   123	
   124	static int __target_offline(struct spi_mockup_target *target)
   125	{
   126		struct device *dev;
   127	
   128		if (!target->spi)
   129			return -ENODEV;
   130	
   131		dev = &target->host->ctrl->dev;
   132		dev_info(dev, "Deleting device %s at 0x%02hx\n",
   133			 dev_name(&target->spi->dev), target->chip);
   134	
   135		spi_unregister_device(target->spi);
   136		target->spi = NULL;
   137	
   138		bitmap_clear(target->host->bitmap, target->chip, 1);
   139	
   140	
   141		return 0;
   142	}
   143	
   144	static ssize_t
   145	spi_mockup_target_live_store(struct config_item *item,
   146				     const char *buf, size_t len)
   147	{
   148		struct spi_mockup_target *target = to_spi_mockup_target(item);
   149		int ret;
   150		bool res;
   151	
   152		ret = kstrtobool(buf, &res);
   153		if (ret)
   154			return -EINVAL;
   155	
   156		if (!strlen(target->device_id))
   157			return -EINVAL;
   158	
   159		mutex_lock(&target->host->lock);
   160		if (res)
 > 161			ret = __target_online(target);
   162		else
   163			ret = __target_offline(target);
   164		mutex_unlock(&target->host->lock);
   165	
   166		return ret ? ret : len;
   167	}
   168	

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2023-11-19 17:05 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-11-18 10:44 [PATCH v4 -next 0/4] spi: Introduce BPF based SPI mockup controller Zhang Xiaoxu
2023-11-18 10:44 ` [PATCH v4 -next 1/4] spi: mockup: Add SPI controller testing driver Zhang Xiaoxu
2023-11-18 10:44 ` [PATCH v4 -next 2/4] spi: mockup: Add register spi device support Zhang Xiaoxu
2023-11-19 17:04   ` kernel test robot
2023-11-18 10:44 ` [PATCH v4 -next 3/4] spi: mockup: Add writeable tracepoint for spi transfer Zhang Xiaoxu
2023-11-18 10:44 ` [PATCH v4 -next 4/4] spi: mockup: Add documentation Zhang Xiaoxu

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).