* [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(®s_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(®s_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).