diff options
Diffstat (limited to 'drivers/spi/spi-loopback-test.c')
| -rw-r--r-- | drivers/spi/spi-loopback-test.c | 118 |
1 files changed, 78 insertions, 40 deletions
diff --git a/drivers/spi/spi-loopback-test.c b/drivers/spi/spi-loopback-test.c index bed7403bb6b3..e0b131aa29b6 100644 --- a/drivers/spi/spi-loopback-test.c +++ b/drivers/spi/spi-loopback-test.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0-or-later /* * linux/drivers/spi/spi-loopback-test.c * @@ -6,16 +7,6 @@ * Loopback test driver to test several typical spi_message conditions * that a spi_master driver may encounter * this can also get used for regression testing - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. */ #include <linux/delay.h> @@ -23,8 +14,8 @@ #include <linux/ktime.h> #include <linux/list.h> #include <linux/list_sort.h> +#include <linux/mod_devicetable.h> #include <linux/module.h> -#include <linux/of_device.h> #include <linux/printk.h> #include <linux/vmalloc.h> #include <linux/spi/spi.h> @@ -62,6 +53,12 @@ module_param(no_cs, int, 0); MODULE_PARM_DESC(no_cs, "if set Chip Select (CS) will not be used"); +/* run tests only for a specific length */ +static int run_only_iter_len = -1; +module_param(run_only_iter_len, int, 0); +MODULE_PARM_DESC(run_only_iter_len, + "only run tests for a length of this number in iterate_len list"); + /* run only a specific test */ static int run_only_test = -1; module_param(run_only_test, int, 0); @@ -80,6 +77,11 @@ module_param(check_ranges, int, 0644); MODULE_PARM_DESC(check_ranges, "checks rx_buffer pattern are valid"); +static unsigned int delay_ms = 100; +module_param(delay_ms, uint, 0644); +MODULE_PARM_DESC(delay_ms, + "delay between tests, in milliseconds (default: 100)"); + /* the actual tests to execute */ static struct spi_test spi_tests[] = { { @@ -99,7 +101,7 @@ static struct spi_test spi_tests[] = { { .description = "tx/rx-transfer - crossing PAGE_SIZE", .fill_option = FILL_COUNT_8, - .iterate_len = { ITERATE_MAX_LEN }, + .iterate_len = { ITERATE_LEN }, .iterate_tx_align = ITERATE_ALIGN, .iterate_rx_align = ITERATE_ALIGN, .transfer_count = 1, @@ -307,12 +309,45 @@ static struct spi_test spi_tests[] = { { .tx_buf = TX(0), .rx_buf = RX(0), - .delay_usecs = 1000, + .delay = { + .value = 1000, + .unit = SPI_DELAY_UNIT_USECS, + }, }, { .tx_buf = TX(0), .rx_buf = RX(0), - .delay_usecs = 1000, + .delay = { + .value = 1000, + .unit = SPI_DELAY_UNIT_USECS, + }, + }, + }, + }, + { + .description = "three tx+rx transfers with overlapping cache lines", + .fill_option = FILL_COUNT_8, + /* + * This should be large enough for the controller driver to + * choose to transfer it with DMA. + */ + .iterate_len = { 512, -1 }, + .iterate_transfer_mask = BIT(1), + .transfer_count = 3, + .transfers = { + { + .len = 1, + .tx_buf = TX(0), + .rx_buf = RX(0), + }, + { + .tx_buf = TX(1), + .rx_buf = RX(1), + }, + { + .len = 1, + .tx_buf = TX(513), + .rx_buf = RX(513), }, }, }, @@ -361,7 +396,6 @@ MODULE_DEVICE_TABLE(of, spi_loopback_test_of_match); static struct spi_driver spi_loopback_test_driver = { .driver = { .name = "spi-loopback-test", - .owner = THIS_MODULE, .of_match_table = spi_loopback_test_of_match, }, .probe = spi_loopback_test_probe, @@ -386,7 +420,7 @@ MODULE_LICENSE("GPL"); static void spi_test_print_hex_dump(char *pre, const void *ptr, size_t len) { /* limit the hex_dump */ - if (len < 1024) { + if (len <= 1024) { print_hex_dump(KERN_INFO, pre, DUMP_PREFIX_OFFSET, 16, 1, ptr, len, 0); @@ -412,7 +446,7 @@ static void spi_test_dump_message(struct spi_device *spi, int i; u8 b; - dev_info(&spi->dev, " spi_msg@%pK\n", msg); + dev_info(&spi->dev, " spi_msg@%p\n", msg); if (msg->status) dev_info(&spi->dev, " status: %i\n", msg->status); @@ -422,15 +456,15 @@ static void spi_test_dump_message(struct spi_device *spi, msg->actual_length); list_for_each_entry(xfer, &msg->transfers, transfer_list) { - dev_info(&spi->dev, " spi_transfer@%pK\n", xfer); + dev_info(&spi->dev, " spi_transfer@%p\n", xfer); dev_info(&spi->dev, " len: %i\n", xfer->len); - dev_info(&spi->dev, " tx_buf: %pK\n", xfer->tx_buf); + dev_info(&spi->dev, " tx_buf: %p\n", xfer->tx_buf); if (dump_data && xfer->tx_buf) spi_test_print_hex_dump(" TX: ", xfer->tx_buf, xfer->len); - dev_info(&spi->dev, " rx_buf: %pK\n", xfer->rx_buf); + dev_info(&spi->dev, " rx_buf: %p\n", xfer->rx_buf); if (dump_data && xfer->rx_buf) spi_test_print_hex_dump(" RX: ", xfer->rx_buf, @@ -457,10 +491,11 @@ struct rx_ranges { u8 *end; }; -static int rx_ranges_cmp(void *priv, struct list_head *a, struct list_head *b) +static int rx_ranges_cmp(void *priv, const struct list_head *a, + const struct list_head *b) { - struct rx_ranges *rx_a = list_entry(a, struct rx_ranges, list); - struct rx_ranges *rx_b = list_entry(b, struct rx_ranges, list); + const struct rx_ranges *rx_a = list_entry(a, struct rx_ranges, list); + const struct rx_ranges *rx_b = list_entry(b, struct rx_ranges, list); if (rx_a->start > rx_b->start) return 1; @@ -523,7 +558,7 @@ static int spi_check_rx_ranges(struct spi_device *spi, /* if still not found then something has modified too much */ /* we could list the "closest" transfer here... */ dev_err(&spi->dev, - "loopback strangeness - rx changed outside of allowed range at: %pK\n", + "loopback strangeness - rx changed outside of allowed range at: %p\n", addr); /* do not return, only set ret, * so that we list all addresses @@ -546,7 +581,7 @@ static int spi_test_check_elapsed_time(struct spi_device *spi, unsigned long long nbits = (unsigned long long)BITS_PER_BYTE * xfer->len; - delay_usecs += xfer->delay_usecs; + delay_usecs += xfer->delay.value; if (!xfer->speed_hz) continue; estimated_time += div_u64(nbits * NSEC_PER_SEC, xfer->speed_hz); @@ -600,8 +635,8 @@ static int spi_test_check_loopback_result(struct spi_device *spi, } else { /* first byte received */ txb = ((u8 *)xfer->rx_buf)[0]; - /* first byte may be 0 or xff */ - if (!((txb == 0) || (txb == 0xff))) { + /* first byte may be 0 or 0xff */ + if (txb != 0 && txb != 0xff) { dev_err(&spi->dev, "loopback strangeness - we expect 0x00 or 0xff, but not 0x%02x\n", txb); @@ -661,7 +696,7 @@ static int spi_test_translate(struct spi_device *spi, } dev_err(&spi->dev, - "PointerRange [%pK:%pK[ not in range [%pK:%pK[ or [%pK:%pK[\n", + "PointerRange [%p:%p[ not in range [%p:%p[ or [%p:%p[\n", *ptr, *ptr + len, RX(0), RX(SPI_TEST_MAX_SIZE), TX(0), TX(SPI_TEST_MAX_SIZE)); @@ -877,7 +912,7 @@ static int spi_test_run_iter(struct spi_device *spi, test.transfers[i].len = len; if (test.transfers[i].tx_buf) test.transfers[i].tx_buf += tx_off; - if (test.transfers[i].tx_buf) + if (test.transfers[i].rx_buf) test.transfers[i].rx_buf += rx_off; } @@ -888,10 +923,10 @@ static int spi_test_run_iter(struct spi_device *spi, /** * spi_test_execute_msg - default implementation to run a test * - * spi: @spi_device on which to run the @spi_message - * test: the test to execute, which already contains @msg - * tx: the tx buffer allocated for the test sequence - * rx: the rx buffer allocated for the test sequence + * @spi: @spi_device on which to run the @spi_message + * @test: the test to execute, which already contains @msg + * @tx: the tx buffer allocated for the test sequence + * @rx: the rx buffer allocated for the test sequence * * Returns: error code of spi_sync as well as basic error checking */ @@ -960,10 +995,10 @@ EXPORT_SYMBOL_GPL(spi_test_execute_msg); * including all the relevant iterations on: * length and buffer alignment * - * spi: the spi_device to send the messages to - * test: the test which we need to execute - * tx: the tx buffer allocated for the test sequence - * rx: the rx buffer allocated for the test sequence + * @spi: the spi_device to send the messages to + * @test: the test which we need to execute + * @tx: the tx buffer allocated for the test sequence + * @rx: the rx buffer allocated for the test sequence * * Returns: status code of spi_sync or other failures */ @@ -995,14 +1030,16 @@ int spi_test_run_test(struct spi_device *spi, const struct spi_test *test, #define FOR_EACH_ALIGNMENT(var) \ for (var = 0; \ var < (test->iterate_##var ? \ - (spi->master->dma_alignment ? \ - spi->master->dma_alignment : \ + (spi->controller->dma_alignment ? \ + spi->controller->dma_alignment : \ test->iterate_##var) : \ 1); \ var++) for (idx_len = 0; idx_len < SPI_TEST_MAX_ITERATE && (len = test->iterate_len[idx_len]) != -1; idx_len++) { + if ((run_only_iter_len > -1) && len != run_only_iter_len) + continue; FOR_EACH_ALIGNMENT(tx_align) { FOR_EACH_ALIGNMENT(rx_align) { /* and run the iteration */ @@ -1073,7 +1110,8 @@ int spi_test_run_tests(struct spi_device *spi, * detect the individual tests when using a logic analyzer * we also add scheduling to avoid potential spi_timeouts... */ - mdelay(100); + if (delay_ms) + mdelay(delay_ms); schedule(); } |
