* [PATCH v4 0/9] spi: spidev_test: new features
@ 2026-09-18 15:22 Jonas Rebmann
2026-09-18 15:22 ` [PATCH v4 1/9] spi: spidev_test: include tools/include Jonas Rebmann
` (8 more replies)
0 siblings, 9 replies; 11+ messages in thread
From: Jonas Rebmann @ 2026-09-18 15:22 UTC (permalink / raw)
To: Mark Brown
Cc: linux-spi, linux-kernel, Marc Kleine-Budde, kernel, Jonas Rebmann
A collection of new features for spidev_test which have collected during
testing/development of spi drivers.
Patch 1 is a small preparatory commit to share macro definitions with
the rest of the tools tree instead of keeping local copies.
Patch 2 improves usage help.
Patches 3 to 8 add the following options:
-c, --compare Compare RX against TX without enabling controller
loopback mode; useful when TX is physically
bridged to RX.
-t, --no-tx Do not provide a TX buffer.
-r, --no-rx Do not provide an RX buffer.
-z, --nonzero Skip 0x00 and 0xff bytes in the generated
random TX pattern so that a stuck line (pulled
high or low) does not produce a false positive
in compare mode.
-P, --predictable Send a deterministic byte sequence instead of
random data, so that runs can be compared e.g.
on an oscilloscope.
-T, --transfers N Split the message into N SPI transfers inside a
single SPI_IOC_MESSAGE() ioctl, exercising the
controller's multi-transfer handling.
Patch 9 resolves out of bounds issues when parsing escape sequences in
the -i (--input) parameter.
Signed-off-by: Jonas Rebmann <jre@pengutronix.de>
---
Changes in v4:
- Add patch 2 to fix help text for --size
- Consistently use initial lower case for help texts
- 3/9: Only make -c, not -l conflict with -2/-4/-8 (sashiko)
- 4/9: Make all supported input data modes work with --no-rx (sashiko)
- 4/9: Make -S conflict with --no-tx (sashiko)
- 5/9: Make --nonzero depend on -S (sashiko)
- 7/9: Guard allocation (sashiko)
- 7/9: Fix double pointer indirection for tr (sashiko)
- Link to v3: https://patch.msgid.link/20260918-spi-sun4i-spidev_test-v3-0-d3ca218d9f76@pengutronix.de
Changes in v3:
- 1/8: Remove old obsolete comment (sashiko)
- 2/8: Fix conflict check introduced in v2 (sashiko)
- 3/8: Do not initialise statics to 0 (checkpatch)
- 4/8: Fix typo: "-r (--no-rx)" (not -t)
- 6/8: free() transfer-array heap-allocated since v2 (sashiko)
- 7/8: Insert blank line after declarations (checkpatch)
- Link to v2: https://patch.msgid.link/20260916-spi-sun4i-spidev_test-v2-0-e7d25bf96e4e@pengutronix.de
Changes in v2:
- Keep options sorted alphabetically in usage help (Thanks, Mark)
- Count mutually exclusive input choices during argparse to avoid
overwhelmingly cute construct during verification (Thanks, Mark)
- 3/7: Error on conflicting --no-rx --output <file> early (Thanks, Mark)
- 3/7: Make usage error message more clear
- 4/7: Braces for legibility (Thanks, Mark)
- 6/7: Heap-allocate transfer-array tr (Thanks, Mark)
- 6/7: Ensure --bpw is greater than zero, prevents division by zero (Thanks, Mark)
- 6/7: Use roundup instead of ALIGN so -T works when --bpw is no power of two (Thanks, Mark)
- 7/7: Limit hexdump to 256 characters (Thanks, Mark)
- 7/7: Preserve errno (Thanks, Mark)
- Add patch 8 to deal with a preexisting issue (sashiko)
- 2/7: Conflict -c with -2/-4/-8 (sashiko)
- Link to v1: https://patch.msgid.link/20260914-spi-sun4i-spidev_test-v1-0-72d6a3b38cee@pengutronix.de
---
Jonas Rebmann (3):
spi: spidev_test: include tools/include
spi: spidev_test: clarify help text for --size
spi: spidev_test: rewrite unescape() to stay in bounds
Marc Kleine-Budde (6):
spi: spidev_test: add compare mode
spi: spidev_test: allow disabling rx or tx buffers
spi: spidev_test: don't send 0x0 or 0xff
spi: spidev_test: send predictable data
spi: spidev_test: add option to split message into multiple transfers
spi: spidev_test: print TX on error
tools/spi/Makefile | 2 +-
tools/spi/spidev_test.c | 275 +++++++++++++++++++++++++++++++++---------------
2 files changed, 194 insertions(+), 83 deletions(-)
---
base-commit: 89a312991dc6e638a36adc43ccb91dbc25504c04
change-id: 20260910-spi-sun4i-spidev_test-881b33fdc3b4
Best regards,
--
Jonas Rebmann <jre@pengutronix.de>
^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH v4 1/9] spi: spidev_test: include tools/include
2026-09-18 15:22 [PATCH v4 0/9] spi: spidev_test: new features Jonas Rebmann
@ 2026-09-18 15:22 ` Jonas Rebmann
2026-09-18 15:22 ` [PATCH v4 2/9] spi: spidev_test: clarify help text for --size Jonas Rebmann
` (7 subsequent siblings)
8 siblings, 0 replies; 11+ messages in thread
From: Jonas Rebmann @ 2026-09-18 15:22 UTC (permalink / raw)
To: Mark Brown
Cc: linux-spi, linux-kernel, Marc Kleine-Budde, kernel, Jonas Rebmann
Add tools/include to include paths to allow using macro helpers.
Use ARRAY_SIZE() from tools/include/linux/kernel.h instead of
maintaining a copy.
Remove the obsolete comment with cross-compile instructions from the
header since spidev_test is integrated with the tools buildsystem since
commit f325b73dc4db ("spi: tools: move to tools buildsystem").
Signed-off-by: Jonas Rebmann <jre@pengutronix.de>
---
tools/spi/Makefile | 2 +-
tools/spi/spidev_test.c | 5 +----
2 files changed, 2 insertions(+), 5 deletions(-)
diff --git a/tools/spi/Makefile b/tools/spi/Makefile
index 7fccd245a535..8cf21ff8cd03 100644
--- a/tools/spi/Makefile
+++ b/tools/spi/Makefile
@@ -12,7 +12,7 @@ endif
# (this improves performance and avoids hard-to-debug behaviour);
MAKEFLAGS += -r
-CFLAGS += -O2 -Wall -g -D_GNU_SOURCE -I$(OUTPUT)include
+CFLAGS += -O2 -Wall -g -D_GNU_SOURCE -I$(OUTPUT)include -I$(srctree)/tools/include
ALL_TARGETS := spidev_test spidev_fdx
ALL_PROGRAMS := $(patsubst %,$(OUTPUT)%,$(ALL_TARGETS))
diff --git a/tools/spi/spidev_test.c b/tools/spi/spidev_test.c
index f2135d619a0b..bd5ee7a6ac82 100644
--- a/tools/spi/spidev_test.c
+++ b/tools/spi/spidev_test.c
@@ -4,8 +4,6 @@
*
* Copyright (c) 2007 MontaVista Software, Inc.
* Copyright (c) 2007 Anton Vorontsov <avorontsov@ru.mvista.com>
- *
- * Cross-compile with cross-gcc -I/path/to/cross-kernel/include
*/
#include <stdint.h>
@@ -22,8 +20,7 @@
#include <sys/stat.h>
#include <linux/types.h>
#include <linux/spi/spidev.h>
-
-#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
+#include <linux/kernel.h>
static void pabort(const char *s)
{
--
2.56.0.rc0.108.gf0ef1b96a0
^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH v4 2/9] spi: spidev_test: clarify help text for --size
2026-09-18 15:22 [PATCH v4 0/9] spi: spidev_test: new features Jonas Rebmann
2026-09-18 15:22 ` [PATCH v4 1/9] spi: spidev_test: include tools/include Jonas Rebmann
@ 2026-09-18 15:22 ` Jonas Rebmann
2026-09-18 15:22 ` [PATCH v4 3/9] spi: spidev_test: add compare mode Jonas Rebmann
` (6 subsequent siblings)
8 siblings, 0 replies; 11+ messages in thread
From: Jonas Rebmann @ 2026-09-18 15:22 UTC (permalink / raw)
To: Mark Brown
Cc: linux-spi, linux-kernel, Marc Kleine-Budde, kernel, Jonas Rebmann
It is slightly confusing that spidev_test by default transmits the
predetermined message default_tx but random bytes given the --size
parameter.
Clarify this in the help text.
While at it, make the -p help text consistently lowercase.
Signed-off-by: Jonas Rebmann <jre@pengutronix.de>
---
tools/spi/spidev_test.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/tools/spi/spidev_test.c b/tools/spi/spidev_test.c
index bd5ee7a6ac82..f5ab67236fac 100644
--- a/tools/spi/spidev_test.c
+++ b/tools/spi/spidev_test.c
@@ -191,8 +191,8 @@ static void print_usage(const char *prog)
"data:\n"
" -i --input input data from a file (e.g. \"test.bin\")\n"
" -o --output output data to a file (e.g. \"results.bin\")\n"
- " -p Send data (e.g. \"1234\\xde\\xad\")\n"
- " -S --size transfer size\n"
+ " -p send data (e.g. \"1234\\xde\\xad\")\n"
+ " -S --size transfer the given number of random bytes\n"
" -I --iter iterations\n"
"additional parameters:\n"
" -b --bpw bits per word\n"
--
2.56.0.rc0.108.gf0ef1b96a0
^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH v4 3/9] spi: spidev_test: add compare mode
2026-09-18 15:22 [PATCH v4 0/9] spi: spidev_test: new features Jonas Rebmann
2026-09-18 15:22 ` [PATCH v4 1/9] spi: spidev_test: include tools/include Jonas Rebmann
2026-09-18 15:22 ` [PATCH v4 2/9] spi: spidev_test: clarify help text for --size Jonas Rebmann
@ 2026-09-18 15:22 ` Jonas Rebmann
2026-09-18 15:22 ` [PATCH v4 4/9] spi: spidev_test: allow disabling rx or tx buffers Jonas Rebmann
` (5 subsequent siblings)
8 siblings, 0 replies; 11+ messages in thread
From: Jonas Rebmann @ 2026-09-18 15:22 UTC (permalink / raw)
To: Mark Brown
Cc: linux-spi, linux-kernel, Marc Kleine-Budde, kernel, Jonas Rebmann
From: Marc Kleine-Budde <mkl@pengutronix.de>
Check whether the received data correspond to the transferred data but
without enabling loopback mode in the controller.
This is for testing with TX physically bridged to RX which is useful if
a loopback mode is unavailable or insufficient.
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
Signed-off-by: Jonas Rebmann <jre@pengutronix.de>
---
tools/spi/spidev_test.c | 15 ++++++++++++---
1 file changed, 12 insertions(+), 3 deletions(-)
diff --git a/tools/spi/spidev_test.c b/tools/spi/spidev_test.c
index f5ab67236fac..7993eae88c44 100644
--- a/tools/spi/spidev_test.c
+++ b/tools/spi/spidev_test.c
@@ -44,6 +44,7 @@ static int verbose;
static int transfer_size;
static int iterations;
static int interval = 5; /* interval in seconds for showing transfer rate */
+static int compare;
static uint8_t default_tx[] = {
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
@@ -171,13 +172,14 @@ static void transfer(int fd, uint8_t const *tx, uint8_t const *rx, size_t len)
static void print_usage(const char *prog)
{
- printf("Usage: %s [-2348CDFHILMNORSZbdilopsvw]\n", prog);
+ printf("Usage: %s [-2348CDFHILMNORSZbcdilopsvw]\n", prog);
puts("general device settings:\n"
" -D --device device to use (default /dev/spidev1.1)\n"
" -s --speed max speed (Hz)\n"
" -d --delay delay (usec)\n"
" -w --word-delay word delay (usec)\n"
" -l --loop loopback\n"
+ " -c --compare compare RX'ed and TX'ed data\n"
"spi mode:\n"
" -H --cpha clock phase\n"
" -O --cpol clock polarity\n"
@@ -215,6 +217,7 @@ static void parse_opts(int argc, char *argv[])
{ "delay", 1, 0, 'd' },
{ "word-delay", 1, 0, 'w' },
{ "loop", 0, 0, 'l' },
+ { "compare", 0, 0, 'c' },
{ "cpha", 0, 0, 'H' },
{ "cpol", 0, 0, 'O' },
{ "rx-cpha-flip", 0, 0, 'F' },
@@ -238,7 +241,7 @@ static void parse_opts(int argc, char *argv[])
};
int c;
- c = getopt_long(argc, argv, "D:s:d:w:b:i:o:lHOLC3ZFMNR248p:vS:I:",
+ c = getopt_long(argc, argv, "D:s:d:w:b:i:o:lcHOLC3ZFMNR248p:vS:I:",
lopts, NULL);
if (c == -1)
@@ -269,6 +272,9 @@ static void parse_opts(int argc, char *argv[])
case 'l':
mode |= SPI_LOOP;
break;
+ case 'c':
+ compare = 1;
+ break;
case 'H':
mode |= SPI_CPHA;
break;
@@ -425,7 +431,7 @@ static void transfer_buf(int fd, int len)
_write_count += len;
_read_count += len;
- if (mode & SPI_LOOP) {
+ if (compare || mode & SPI_LOOP) {
if (memcmp(tx, rx, len)) {
fprintf(stderr, "transfer error !\n");
hex_dump(tx, len, 32, "TX");
@@ -449,6 +455,9 @@ int main(int argc, char *argv[])
if (input_tx && input_file)
pabort("only one of -p and --input may be selected");
+ if (compare && mode & (SPI_TX_OCTAL | SPI_TX_QUAD | SPI_TX_DUAL))
+ pabort("-c (--compare) conflicts with -2 (--dual), -4 (--quad) or -8 (--octal)");
+
fd = open(device, O_RDWR);
if (fd < 0)
pabort("can't open device");
--
2.56.0.rc0.108.gf0ef1b96a0
^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH v4 4/9] spi: spidev_test: allow disabling rx or tx buffers
2026-09-18 15:22 [PATCH v4 0/9] spi: spidev_test: new features Jonas Rebmann
` (2 preceding siblings ...)
2026-09-18 15:22 ` [PATCH v4 3/9] spi: spidev_test: add compare mode Jonas Rebmann
@ 2026-09-18 15:22 ` Jonas Rebmann
2026-09-18 15:22 ` [PATCH v4 5/9] spi: spidev_test: don't send 0x0 or 0xff Jonas Rebmann
` (4 subsequent siblings)
8 siblings, 0 replies; 11+ messages in thread
From: Jonas Rebmann @ 2026-09-18 15:22 UTC (permalink / raw)
To: Mark Brown
Cc: linux-spi, linux-kernel, Marc Kleine-Budde, kernel, Jonas Rebmann
From: Marc Kleine-Budde <mkl@pengutronix.de>
Allow not providing rx or tx buffers. This is useful to check if drivers
that don't use SPI_CONTROLLER_MUST_RX (or -TX respectively) handle their
operations correctly without a buffer.
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
Signed-off-by: Jonas Rebmann <jre@pengutronix.de>
---
tools/spi/spidev_test.c | 90 +++++++++++++++++++++++++++++++++----------------
1 file changed, 61 insertions(+), 29 deletions(-)
diff --git a/tools/spi/spidev_test.c b/tools/spi/spidev_test.c
index 7993eae88c44..906f9997b10a 100644
--- a/tools/spi/spidev_test.c
+++ b/tools/spi/spidev_test.c
@@ -45,6 +45,8 @@ static int transfer_size;
static int iterations;
static int interval = 5; /* interval in seconds for showing transfer rate */
static int compare;
+static int do_tx = 1, do_rx = 1;
+static int input_choices;
static uint8_t default_tx[] = {
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
@@ -151,7 +153,7 @@ static void transfer(int fd, uint8_t const *tx, uint8_t const *rx, size_t len)
if (ret < 1)
pabort("can't send spi message");
- if (verbose)
+ if (verbose && tx)
hex_dump(tx, len, 32, "TX");
if (output_file) {
@@ -166,13 +168,13 @@ static void transfer(int fd, uint8_t const *tx, uint8_t const *rx, size_t len)
close(out_fd);
}
- if (verbose)
+ if (verbose && rx)
hex_dump(rx, len, 32, "RX");
}
static void print_usage(const char *prog)
{
- printf("Usage: %s [-2348CDFHILMNORSZbcdilopsvw]\n", prog);
+ printf("Usage: %s [-2348CDFHILMNORSZbcdiloprstvw]\n", prog);
puts("general device settings:\n"
" -D --device device to use (default /dev/spidev1.1)\n"
" -s --speed max speed (Hz)\n"
@@ -180,6 +182,8 @@ static void print_usage(const char *prog)
" -w --word-delay word delay (usec)\n"
" -l --loop loopback\n"
" -c --compare compare RX'ed and TX'ed data\n"
+ " -t --no-tx don't send data\n"
+ " -r --no-rx don't receive data\n"
"spi mode:\n"
" -H --cpha clock phase\n"
" -O --cpol clock polarity\n"
@@ -218,6 +222,8 @@ static void parse_opts(int argc, char *argv[])
{ "word-delay", 1, 0, 'w' },
{ "loop", 0, 0, 'l' },
{ "compare", 0, 0, 'c' },
+ { "no-tx", 0, 0, 't' },
+ { "no-rx", 0, 0, 'r' },
{ "cpha", 0, 0, 'H' },
{ "cpol", 0, 0, 'O' },
{ "rx-cpha-flip", 0, 0, 'F' },
@@ -241,7 +247,7 @@ static void parse_opts(int argc, char *argv[])
};
int c;
- c = getopt_long(argc, argv, "D:s:d:w:b:i:o:lcHOLC3ZFMNR248p:vS:I:",
+ c = getopt_long(argc, argv, "D:s:d:w:b:i:o:lctrHOLC3ZFMNR248p:vS:I:",
lopts, NULL);
if (c == -1)
@@ -265,6 +271,7 @@ static void parse_opts(int argc, char *argv[])
break;
case 'i':
input_file = optarg;
+ input_choices++;
break;
case 'o':
output_file = optarg;
@@ -275,6 +282,13 @@ static void parse_opts(int argc, char *argv[])
case 'c':
compare = 1;
break;
+ case 't':
+ do_tx = 0;
+ input_choices++;
+ break;
+ case 'r':
+ do_rx = 0;
+ break;
case 'H':
mode |= SPI_CPHA;
break;
@@ -310,6 +324,7 @@ static void parse_opts(int argc, char *argv[])
break;
case 'p':
input_tx = optarg;
+ input_choices++;
break;
case '2':
mode |= SPI_TX_DUAL;
@@ -322,6 +337,7 @@ static void parse_opts(int argc, char *argv[])
break;
case 'S':
transfer_size = atoi(optarg);
+ input_choices++;
break;
case 'I':
iterations = atoi(optarg);
@@ -344,15 +360,17 @@ static void transfer_escaped_string(int fd, char *str)
{
size_t size = strlen(str);
uint8_t *tx;
- uint8_t *rx;
+ uint8_t *rx = NULL;
tx = malloc(size);
if (!tx)
pabort("can't allocate tx buffer");
- rx = malloc(size);
- if (!rx)
- pabort("can't allocate rx buffer");
+ if (do_rx) {
+ rx = malloc(size);
+ if (!rx)
+ pabort("can't allocate rx buffer");
+ }
size = unescape((char *)tx, str, size);
transfer(fd, tx, rx, size);
@@ -366,7 +384,7 @@ static void transfer_file(int fd, char *filename)
struct stat sb;
int tx_fd;
uint8_t *tx;
- uint8_t *rx;
+ uint8_t *rx = NULL;
if (stat(filename, &sb) == -1)
pabort("can't stat input file");
@@ -379,9 +397,12 @@ static void transfer_file(int fd, char *filename)
if (!tx)
pabort("can't allocate tx buffer");
- rx = malloc(sb.st_size);
- if (!rx)
- pabort("can't allocate rx buffer");
+
+ if (do_rx) {
+ rx = malloc(sb.st_size);
+ if (!rx)
+ pabort("can't allocate rx buffer");
+ }
bytes = read(tx_fd, tx, sb.st_size);
if (bytes != sb.st_size)
@@ -412,26 +433,31 @@ static void show_transfer_rate(void)
static void transfer_buf(int fd, int len)
{
- uint8_t *tx;
- uint8_t *rx;
+ uint8_t *tx = NULL;
+ uint8_t *rx = NULL;
int i;
- tx = malloc(len);
- if (!tx)
- pabort("can't allocate tx buffer");
- for (i = 0; i < len; i++)
- tx[i] = random();
+ if (do_tx) {
+ tx = malloc(len);
+ if (!tx)
+ pabort("can't allocate tx buffer");
+ for (i = 0; i < len; i++)
+ tx[i] = random();
+ }
- rx = malloc(len);
- if (!rx)
- pabort("can't allocate rx buffer");
+ if (do_rx) {
+ rx = malloc(len);
+ if (!rx)
+ pabort("can't allocate rx buffer");
+ }
transfer(fd, tx, rx, len);
+ if (do_tx)
+ _write_count += len;
+ if (do_rx)
+ _read_count += len;
- _write_count += len;
- _read_count += len;
-
- if (compare || mode & SPI_LOOP) {
+ if (tx && rx && (compare || mode & SPI_LOOP)) {
if (memcmp(tx, rx, len)) {
fprintf(stderr, "transfer error !\n");
hex_dump(tx, len, 32, "TX");
@@ -452,8 +478,14 @@ int main(int argc, char *argv[])
parse_opts(argc, argv);
- if (input_tx && input_file)
- pabort("only one of -p and --input may be selected");
+ if (input_choices > 1)
+ pabort("only one of -S (--size), -p, -i (--input), -t (--no-tx) may be selected");
+
+ if (compare && (!do_tx || !do_rx))
+ pabort("-c (--compare) conflicts with -t (--no-tx) or -r (--no-rx)");
+
+ if (!do_rx && output_file)
+ pabort("-r (--no-rx) conflicts with -o (--output)");
if (compare && mode & (SPI_TX_OCTAL | SPI_TX_QUAD | SPI_TX_DUAL))
pabort("-c (--compare) conflicts with -2 (--dual), -4 (--quad) or -8 (--octal)");
@@ -532,7 +564,7 @@ int main(int argc, char *argv[])
printf("total: tx %.1fKB, rx %.1fKB\n",
_write_count/1024.0, _read_count/1024.0);
} else
- transfer(fd, default_tx, default_rx, sizeof(default_tx));
+ transfer(fd, do_tx ? default_tx : NULL, do_rx ? default_rx : NULL, sizeof(default_tx));
close(fd);
--
2.56.0.rc0.108.gf0ef1b96a0
^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH v4 5/9] spi: spidev_test: don't send 0x0 or 0xff
2026-09-18 15:22 [PATCH v4 0/9] spi: spidev_test: new features Jonas Rebmann
` (3 preceding siblings ...)
2026-09-18 15:22 ` [PATCH v4 4/9] spi: spidev_test: allow disabling rx or tx buffers Jonas Rebmann
@ 2026-09-18 15:22 ` Jonas Rebmann
2026-09-18 15:22 ` [PATCH v4 6/9] spi: spidev_test: send predictable data Jonas Rebmann
` (3 subsequent siblings)
8 siblings, 0 replies; 11+ messages in thread
From: Jonas Rebmann @ 2026-09-18 15:22 UTC (permalink / raw)
To: Mark Brown
Cc: linux-spi, linux-kernel, Marc Kleine-Budde, kernel, Jonas Rebmann
From: Marc Kleine-Budde <mkl@pengutronix.de>
Particularly when using compare mode, if the controller fails to
transfer any data, asserting on a read of 0x00 or 0xff may lead a false
negative test, indicating a byte was successfully transferred when the
values simply originate from the pull-up or pull-down of RX.
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
Signed-off-by: Jonas Rebmann <jre@pengutronix.de>
---
tools/spi/spidev_test.c | 20 ++++++++++++++++----
1 file changed, 16 insertions(+), 4 deletions(-)
diff --git a/tools/spi/spidev_test.c b/tools/spi/spidev_test.c
index 906f9997b10a..c34601558646 100644
--- a/tools/spi/spidev_test.c
+++ b/tools/spi/spidev_test.c
@@ -45,6 +45,7 @@ static int transfer_size;
static int iterations;
static int interval = 5; /* interval in seconds for showing transfer rate */
static int compare;
+static int nonzero;
static int do_tx = 1, do_rx = 1;
static int input_choices;
@@ -174,7 +175,7 @@ static void transfer(int fd, uint8_t const *tx, uint8_t const *rx, size_t len)
static void print_usage(const char *prog)
{
- printf("Usage: %s [-2348CDFHILMNORSZbcdiloprstvw]\n", prog);
+ printf("Usage: %s [-2348CDFHILMNORSZbcdiloprstvwz]\n", prog);
puts("general device settings:\n"
" -D --device device to use (default /dev/spidev1.1)\n"
" -s --speed max speed (Hz)\n"
@@ -198,6 +199,7 @@ static void print_usage(const char *prog)
" -i --input input data from a file (e.g. \"test.bin\")\n"
" -o --output output data to a file (e.g. \"results.bin\")\n"
" -p send data (e.g. \"1234\\xde\\xad\")\n"
+ " -z --nonzero don't send 0x00 or 0xff bytes\n"
" -S --size transfer the given number of random bytes\n"
" -I --iter iterations\n"
"additional parameters:\n"
@@ -235,6 +237,7 @@ static void parse_opts(int argc, char *argv[])
{ "input", 1, 0, 'i' },
{ "output", 1, 0, 'o' },
{ "size", 1, 0, 'S' },
+ { "nonzero", 0, 0, 'z' },
{ "iter", 1, 0, 'I' },
{ "bpw", 1, 0, 'b' },
{ "lsb", 0, 0, 'L' },
@@ -247,7 +250,7 @@ static void parse_opts(int argc, char *argv[])
};
int c;
- c = getopt_long(argc, argv, "D:s:d:w:b:i:o:lctrHOLC3ZFMNR248p:vS:I:",
+ c = getopt_long(argc, argv, "D:s:d:w:b:i:o:lctrHOLC3ZFMNR248p:vS:zI:",
lopts, NULL);
if (c == -1)
@@ -339,6 +342,9 @@ static void parse_opts(int argc, char *argv[])
transfer_size = atoi(optarg);
input_choices++;
break;
+ case 'z':
+ nonzero = 1;
+ break;
case 'I':
iterations = atoi(optarg);
break;
@@ -441,8 +447,11 @@ static void transfer_buf(int fd, int len)
tx = malloc(len);
if (!tx)
pabort("can't allocate tx buffer");
- for (i = 0; i < len; i++)
- tx[i] = random();
+ for (i = 0; i < len; i++) {
+ do
+ tx[i] = random();
+ while (nonzero && (tx[i] == 0x0 || tx[i] == 0xff));
+ }
}
if (do_rx) {
@@ -481,6 +490,9 @@ int main(int argc, char *argv[])
if (input_choices > 1)
pabort("only one of -S (--size), -p, -i (--input), -t (--no-tx) may be selected");
+ if (nonzero && !transfer_size)
+ pabort("-z (--nonzero) is only implemented for -S (--size)");
+
if (compare && (!do_tx || !do_rx))
pabort("-c (--compare) conflicts with -t (--no-tx) or -r (--no-rx)");
--
2.56.0.rc0.108.gf0ef1b96a0
^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH v4 6/9] spi: spidev_test: send predictable data
2026-09-18 15:22 [PATCH v4 0/9] spi: spidev_test: new features Jonas Rebmann
` (4 preceding siblings ...)
2026-09-18 15:22 ` [PATCH v4 5/9] spi: spidev_test: don't send 0x0 or 0xff Jonas Rebmann
@ 2026-09-18 15:22 ` Jonas Rebmann
2026-09-22 11:57 ` Mark Brown
2026-09-18 15:22 ` [PATCH v4 7/9] spi: spidev_test: add option to split message into multiple transfers Jonas Rebmann
` (2 subsequent siblings)
8 siblings, 1 reply; 11+ messages in thread
From: Jonas Rebmann @ 2026-09-18 15:22 UTC (permalink / raw)
To: Mark Brown
Cc: linux-spi, linux-kernel, Marc Kleine-Budde, kernel, Jonas Rebmann
From: Marc Kleine-Budde <mkl@pengutronix.de>
Introduce a flag to test on a predictable byte sequence instead of
random bytes. This is useful when comparing multiple runs with the same
option set e.g. with an oscilloscope.
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
Signed-off-by: Jonas Rebmann <jre@pengutronix.de>
---
tools/spi/spidev_test.c | 23 +++++++++++++++++------
1 file changed, 17 insertions(+), 6 deletions(-)
diff --git a/tools/spi/spidev_test.c b/tools/spi/spidev_test.c
index c34601558646..21a631d346a4 100644
--- a/tools/spi/spidev_test.c
+++ b/tools/spi/spidev_test.c
@@ -47,6 +47,7 @@ static int interval = 5; /* interval in seconds for showing transfer rate */
static int compare;
static int nonzero;
static int do_tx = 1, do_rx = 1;
+static int predictable;
static int input_choices;
static uint8_t default_tx[] = {
@@ -175,7 +176,7 @@ static void transfer(int fd, uint8_t const *tx, uint8_t const *rx, size_t len)
static void print_usage(const char *prog)
{
- printf("Usage: %s [-2348CDFHILMNORSZbcdiloprstvwz]\n", prog);
+ printf("Usage: %s [-2348CDFHILMNOPRSZbcdiloprstvwz]\n", prog);
puts("general device settings:\n"
" -D --device device to use (default /dev/spidev1.1)\n"
" -s --speed max speed (Hz)\n"
@@ -200,6 +201,7 @@ static void print_usage(const char *prog)
" -o --output output data to a file (e.g. \"results.bin\")\n"
" -p send data (e.g. \"1234\\xde\\xad\")\n"
" -z --nonzero don't send 0x00 or 0xff bytes\n"
+ " -P --predictable send a predictable sequence instead of random numbers\n"
" -S --size transfer the given number of random bytes\n"
" -I --iter iterations\n"
"additional parameters:\n"
@@ -245,12 +247,13 @@ static void parse_opts(int argc, char *argv[])
{ "no-cs", 0, 0, 'N' },
{ "ready", 0, 0, 'R' },
{ "mosi-idle-low", 0, 0, 'M' },
+ { "predictable", 0, 0, 'P' },
{ "verbose", 0, 0, 'v' },
{ NULL, 0, 0, 0 },
};
int c;
- c = getopt_long(argc, argv, "D:s:d:w:b:i:o:lctrHOLC3ZFMNR248p:vS:zI:",
+ c = getopt_long(argc, argv, "D:s:d:w:b:i:o:lctrHOLC3ZFMNR248p:PvS:zI:",
lopts, NULL);
if (c == -1)
@@ -329,6 +332,10 @@ static void parse_opts(int argc, char *argv[])
input_tx = optarg;
input_choices++;
break;
+ case 'P':
+ predictable = 1;
+ input_choices++;
+ break;
case '2':
mode |= SPI_TX_DUAL;
break;
@@ -448,9 +455,13 @@ static void transfer_buf(int fd, int len)
if (!tx)
pabort("can't allocate tx buffer");
for (i = 0; i < len; i++) {
- do
- tx[i] = random();
- while (nonzero && (tx[i] == 0x0 || tx[i] == 0xff));
+ if (predictable) {
+ tx[i] = i - iterations;
+ } else {
+ do {
+ tx[i] = random();
+ } while (nonzero && (tx[i] == 0x0 || tx[i] == 0xff));
+ }
}
}
@@ -488,7 +499,7 @@ int main(int argc, char *argv[])
parse_opts(argc, argv);
if (input_choices > 1)
- pabort("only one of -S (--size), -p, -i (--input), -t (--no-tx) may be selected");
+ pabort("only one of -S (--size), -p, -i (--input), -t (--no-tx), -P (--predictable) may be selected");
if (nonzero && !transfer_size)
pabort("-z (--nonzero) is only implemented for -S (--size)");
--
2.56.0.rc0.108.gf0ef1b96a0
^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH v4 7/9] spi: spidev_test: add option to split message into multiple transfers
2026-09-18 15:22 [PATCH v4 0/9] spi: spidev_test: new features Jonas Rebmann
` (5 preceding siblings ...)
2026-09-18 15:22 ` [PATCH v4 6/9] spi: spidev_test: send predictable data Jonas Rebmann
@ 2026-09-18 15:22 ` Jonas Rebmann
2026-09-18 15:22 ` [PATCH v4 8/9] spi: spidev_test: print TX on error Jonas Rebmann
2026-09-18 15:22 ` [PATCH v4 9/9] spi: spidev_test: rewrite unescape() to stay in bounds Jonas Rebmann
8 siblings, 0 replies; 11+ messages in thread
From: Jonas Rebmann @ 2026-09-18 15:22 UTC (permalink / raw)
To: Mark Brown
Cc: linux-spi, linux-kernel, Marc Kleine-Budde, kernel, Jonas Rebmann
From: Marc Kleine-Budde <mkl@pengutronix.de>
SPI_IOC_MESSAGE() submits a single SPI message containing one or more
transfers. Introduce an option to allow splitting the message into
multiple transfers.
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
Signed-off-by: Jonas Rebmann <jre@pengutronix.de>
---
tools/spi/spidev_test.c | 98 +++++++++++++++++++++++++++++++++----------------
1 file changed, 67 insertions(+), 31 deletions(-)
diff --git a/tools/spi/spidev_test.c b/tools/spi/spidev_test.c
index 21a631d346a4..9aa1e0849a88 100644
--- a/tools/spi/spidev_test.c
+++ b/tools/spi/spidev_test.c
@@ -42,6 +42,7 @@ static uint16_t delay;
static uint16_t word_delay;
static int verbose;
static int transfer_size;
+static int transfers = 1;
static int iterations;
static int interval = 5; /* interval in seconds for showing transfer rate */
static int compare;
@@ -118,40 +119,64 @@ static int unescape(char *_dst, char *_src, size_t len)
return ret;
}
-static void transfer(int fd, uint8_t const *tx, uint8_t const *rx, size_t len)
+static void transfer(int fd, uint8_t const * const tx, uint8_t const * const rx, size_t len)
{
int ret;
int out_fd;
- struct spi_ioc_transfer tr = {
- .tx_buf = (unsigned long)tx,
- .rx_buf = (unsigned long)rx,
- .len = len,
- .delay_usecs = delay,
- .word_delay_usecs = word_delay,
- .speed_hz = speed,
- .bits_per_word = bits,
- };
-
- if (mode & SPI_TX_OCTAL)
- tr.tx_nbits = 8;
- else if (mode & SPI_TX_QUAD)
- tr.tx_nbits = 4;
- else if (mode & SPI_TX_DUAL)
- tr.tx_nbits = 2;
- if (mode & SPI_RX_OCTAL)
- tr.rx_nbits = 8;
- else if (mode & SPI_RX_QUAD)
- tr.rx_nbits = 4;
- else if (mode & SPI_RX_DUAL)
- tr.rx_nbits = 2;
- if (!(mode & SPI_LOOP)) {
- if (mode & (SPI_TX_OCTAL | SPI_TX_QUAD | SPI_TX_DUAL))
- tr.rx_buf = 0;
- else if (mode & (SPI_RX_OCTAL | SPI_RX_QUAD | SPI_RX_DUAL))
- tr.tx_buf = 0;
+ size_t bytes_per_word = DIV_ROUND_UP(bits, 8);
+ int effective_transfers = min_t(int, transfers, DIV_ROUND_UP(len, bytes_per_word));
+ struct spi_ioc_transfer *tr = calloc(effective_transfers, sizeof(*tr));
+ size_t len_per_transfer = roundup(DIV_ROUND_UP(len, effective_transfers), bytes_per_word);
+ const uint8_t *tx_buf = tx;
+ const uint8_t *rx_buf = rx;
+ size_t rem = len;
+
+ if (!tr)
+ pabort("can't allocate transfer array");
+
+ for (int i = 0; i < effective_transfers; i++) {
+ size_t n = min(rem, len_per_transfer);
+
+ tr[i] = (struct spi_ioc_transfer) {
+ .tx_buf = (unsigned long)tx_buf,
+ .rx_buf = (unsigned long)rx_buf,
+ .len = n,
+ .delay_usecs = delay,
+ .word_delay_usecs = word_delay,
+ .speed_hz = speed,
+ .bits_per_word = bits,
+ };
+
+ if (tx_buf)
+ tx_buf += n;
+
+ if (rx_buf)
+ rx_buf += n;
+
+ rem -= n;
+
+ if (mode & SPI_TX_OCTAL)
+ tr[i].tx_nbits = 8;
+ else if (mode & SPI_TX_QUAD)
+ tr[i].tx_nbits = 4;
+ else if (mode & SPI_TX_DUAL)
+ tr[i].tx_nbits = 2;
+ if (mode & SPI_RX_OCTAL)
+ tr[i].rx_nbits = 8;
+ else if (mode & SPI_RX_QUAD)
+ tr[i].rx_nbits = 4;
+ else if (mode & SPI_RX_DUAL)
+ tr[i].rx_nbits = 2;
+ if (!(mode & SPI_LOOP)) {
+ if (mode & (SPI_TX_OCTAL | SPI_TX_QUAD | SPI_TX_DUAL))
+ tr[i].rx_buf = 0;
+ else if (mode & (SPI_RX_OCTAL | SPI_RX_QUAD | SPI_RX_DUAL))
+ tr[i].tx_buf = 0;
+ }
}
- ret = ioctl(fd, SPI_IOC_MESSAGE(1), &tr);
+ ret = ioctl(fd, SPI_IOC_MESSAGE(effective_transfers), tr);
+ free(tr);
if (ret < 1)
pabort("can't send spi message");
@@ -176,7 +201,7 @@ static void transfer(int fd, uint8_t const *tx, uint8_t const *rx, size_t len)
static void print_usage(const char *prog)
{
- printf("Usage: %s [-2348CDFHILMNOPRSZbcdiloprstvwz]\n", prog);
+ printf("Usage: %s [-2348CDFHILMNOPRSTZbcdiloprstvwz]\n", prog);
puts("general device settings:\n"
" -D --device device to use (default /dev/spidev1.1)\n"
" -s --speed max speed (Hz)\n"
@@ -211,6 +236,7 @@ static void print_usage(const char *prog)
" -N --no-cs no chip select\n"
" -R --ready slave pulls low to pause\n"
" -M --mosi-idle-low leave mosi line low when idle\n"
+ " -T --transfers number of transfers\n"
"misc:\n"
" -v --verbose Verbose (show tx buffer)\n");
exit(1);
@@ -248,12 +274,13 @@ static void parse_opts(int argc, char *argv[])
{ "ready", 0, 0, 'R' },
{ "mosi-idle-low", 0, 0, 'M' },
{ "predictable", 0, 0, 'P' },
+ { "transfers", 1, 0, 'T' },
{ "verbose", 0, 0, 'v' },
{ NULL, 0, 0, 0 },
};
int c;
- c = getopt_long(argc, argv, "D:s:d:w:b:i:o:lctrHOLC3ZFMNR248p:PvS:zI:",
+ c = getopt_long(argc, argv, "D:s:d:w:b:i:o:lctrHOLC3ZFMNR248p:PT:vS:zI:",
lopts, NULL);
if (c == -1)
@@ -319,6 +346,9 @@ static void parse_opts(int argc, char *argv[])
case 'M':
mode |= SPI_MOSI_IDLE_LOW;
break;
+ case 'T':
+ transfers = atoi(optarg);
+ break;
case 'N':
mode |= SPI_NO_CS;
break;
@@ -513,6 +543,12 @@ int main(int argc, char *argv[])
if (compare && mode & (SPI_TX_OCTAL | SPI_TX_QUAD | SPI_TX_DUAL))
pabort("-c (--compare) conflicts with -2 (--dual), -4 (--quad) or -8 (--octal)");
+ if (transfers < 1)
+ pabort("-T (--transfers) must be 1 or above");
+
+ if (bits < 1)
+ pabort("-b (--bpw) must be 1 or above");
+
fd = open(device, O_RDWR);
if (fd < 0)
pabort("can't open device");
--
2.56.0.rc0.108.gf0ef1b96a0
^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH v4 8/9] spi: spidev_test: print TX on error
2026-09-18 15:22 [PATCH v4 0/9] spi: spidev_test: new features Jonas Rebmann
` (6 preceding siblings ...)
2026-09-18 15:22 ` [PATCH v4 7/9] spi: spidev_test: add option to split message into multiple transfers Jonas Rebmann
@ 2026-09-18 15:22 ` Jonas Rebmann
2026-09-18 15:22 ` [PATCH v4 9/9] spi: spidev_test: rewrite unescape() to stay in bounds Jonas Rebmann
8 siblings, 0 replies; 11+ messages in thread
From: Jonas Rebmann @ 2026-09-18 15:22 UTC (permalink / raw)
To: Mark Brown
Cc: linux-spi, linux-kernel, Marc Kleine-Budde, kernel, Jonas Rebmann
From: Marc Kleine-Budde <mkl@pengutronix.de>
If sending an spi message fails, dump its first up to 256 bytes to the
console.
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
Signed-off-by: Jonas Rebmann <jre@pengutronix.de>
---
tools/spi/spidev_test.c | 12 +++++++++++-
1 file changed, 11 insertions(+), 1 deletion(-)
diff --git a/tools/spi/spidev_test.c b/tools/spi/spidev_test.c
index 9aa1e0849a88..1910facdd3da 100644
--- a/tools/spi/spidev_test.c
+++ b/tools/spi/spidev_test.c
@@ -177,8 +177,18 @@ static void transfer(int fd, uint8_t const * const tx, uint8_t const * const rx,
ret = ioctl(fd, SPI_IOC_MESSAGE(effective_transfers), tr);
free(tr);
- if (ret < 1)
+ if (ret < 1) {
+ const size_t dump_len = min_t(size_t, len, 256);
+ int saved_errno = errno;
+
+ if (tx) {
+ hex_dump(tx, dump_len, 32, "TX");
+ if (len > dump_len)
+ printf("... (%zu more bytes)\n", len - dump_len);
+ }
+ errno = saved_errno;
pabort("can't send spi message");
+ }
if (verbose && tx)
hex_dump(tx, len, 32, "TX");
--
2.56.0.rc0.108.gf0ef1b96a0
^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH v4 9/9] spi: spidev_test: rewrite unescape() to stay in bounds
2026-09-18 15:22 [PATCH v4 0/9] spi: spidev_test: new features Jonas Rebmann
` (7 preceding siblings ...)
2026-09-18 15:22 ` [PATCH v4 8/9] spi: spidev_test: print TX on error Jonas Rebmann
@ 2026-09-18 15:22 ` Jonas Rebmann
8 siblings, 0 replies; 11+ messages in thread
From: Jonas Rebmann @ 2026-09-18 15:22 UTC (permalink / raw)
To: Mark Brown
Cc: linux-spi, linux-kernel, Marc Kleine-Budde, kernel, Jonas Rebmann
unescape() could read the source buffer out of bounds for inputs like
"\\x" and could write the destination buffer out of bounds due to lack
of checking against the len parameter.
For better readability and consistency, rewrite it as a simplified
version of unescape_string() in string_helpers.h. This includes
rearranging src and dst parameters.
Signed-off-by: Jonas Rebmann <jre@pengutronix.de>
---
tools/spi/spidev_test.c | 38 +++++++++++++++++++++-----------------
1 file changed, 21 insertions(+), 17 deletions(-)
diff --git a/tools/spi/spidev_test.c b/tools/spi/spidev_test.c
index 1910facdd3da..95d5d37788ba 100644
--- a/tools/spi/spidev_test.c
+++ b/tools/spi/spidev_test.c
@@ -11,6 +11,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <ctype.h>
#include <errno.h>
#include <getopt.h>
#include <fcntl.h>
@@ -95,28 +96,31 @@ static void hex_dump(const void *src, size_t length, size_t line_size,
* Unescape - process hexadecimal escape character
* converts shell input "\x23" -> 0x23
*/
-static int unescape(char *_dst, char *_src, size_t len)
+static int unescape(char *src, char *dst, size_t size)
{
- int ret = 0;
- int match;
- char *src = _src;
- char *dst = _dst;
+ char *out = dst;
unsigned int ch;
- while (*src) {
- if (*src == '\\' && *(src+1) == 'x') {
- match = sscanf(src + 2, "%2x", &ch);
- if (!match)
- pabort("malformed input string");
+ while (*src && size--) {
+ if (src[0] == '\\' && src[1] != '\0') {
+ src++;
+
+ if (src[0] == 'x' &&
+ isxdigit((unsigned char)src[1]) &&
+ isxdigit((unsigned char)src[2]) &&
+ sscanf(&src[1], "%2x", &ch)) {
+ *out++ = (unsigned char)ch;
+ src += 3;
+ continue;
+ }
- src += 4;
- *dst++ = (unsigned char)ch;
- } else {
- *dst++ = *src++;
+ *out++ = '\\';
+ if (!size--)
+ break;
}
- ret++;
+ *out++ = *src++;
}
- return ret;
+ return out - dst;
}
static void transfer(int fd, uint8_t const * const tx, uint8_t const * const rx, size_t len)
@@ -425,7 +429,7 @@ static void transfer_escaped_string(int fd, char *str)
pabort("can't allocate rx buffer");
}
- size = unescape((char *)tx, str, size);
+ size = unescape(str, (char *)tx, size);
transfer(fd, tx, rx, size);
free(rx);
free(tx);
--
2.56.0.rc0.108.gf0ef1b96a0
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH v4 6/9] spi: spidev_test: send predictable data
2026-09-18 15:22 ` [PATCH v4 6/9] spi: spidev_test: send predictable data Jonas Rebmann
@ 2026-09-22 11:57 ` Mark Brown
0 siblings, 0 replies; 11+ messages in thread
From: Mark Brown @ 2026-09-22 11:57 UTC (permalink / raw)
To: Jonas Rebmann; +Cc: linux-spi, linux-kernel, Marc Kleine-Budde, kernel
[-- Attachment #1: Type: text/plain, Size: 449 bytes --]
On Fri, Sep 18, 2026 at 05:22:52PM +0200, Jonas Rebmann wrote:
> From: Marc Kleine-Budde <mkl@pengutronix.de>
>
> Introduce a flag to test on a predictable byte sequence instead of
> random bytes. This is useful when comparing multiple runs with the same
> option set e.g. with an oscilloscope.
> + case 'P':
> + predictable = 1;
> + input_choices++;
> + break;
-z doesn't increment input_choices, seems one of them is wrong.
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]
^ permalink raw reply [flat|nested] 11+ messages in thread
end of thread, other threads:[~2026-09-22 11:57 UTC | newest]
Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-09-18 15:22 [PATCH v4 0/9] spi: spidev_test: new features Jonas Rebmann
2026-09-18 15:22 ` [PATCH v4 1/9] spi: spidev_test: include tools/include Jonas Rebmann
2026-09-18 15:22 ` [PATCH v4 2/9] spi: spidev_test: clarify help text for --size Jonas Rebmann
2026-09-18 15:22 ` [PATCH v4 3/9] spi: spidev_test: add compare mode Jonas Rebmann
2026-09-18 15:22 ` [PATCH v4 4/9] spi: spidev_test: allow disabling rx or tx buffers Jonas Rebmann
2026-09-18 15:22 ` [PATCH v4 5/9] spi: spidev_test: don't send 0x0 or 0xff Jonas Rebmann
2026-09-18 15:22 ` [PATCH v4 6/9] spi: spidev_test: send predictable data Jonas Rebmann
2026-09-22 11:57 ` Mark Brown
2026-09-18 15:22 ` [PATCH v4 7/9] spi: spidev_test: add option to split message into multiple transfers Jonas Rebmann
2026-09-18 15:22 ` [PATCH v4 8/9] spi: spidev_test: print TX on error Jonas Rebmann
2026-09-18 15:22 ` [PATCH v4 9/9] spi: spidev_test: rewrite unescape() to stay in bounds Jonas Rebmann
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®