Merge remote-tracking branches 'spi/topic/spidev', 'spi/topic/spidev-test', 'spi...
authorMark Brown <broonie@kernel.org>
Wed, 26 Apr 2017 14:58:16 +0000 (15:58 +0100)
committerMark Brown <broonie@kernel.org>
Wed, 26 Apr 2017 14:58:16 +0000 (15:58 +0100)
1  2  3  4  5  6 
drivers/spi/spi-loopback-test.c

      
      #include <linux/delay.h>
      #include <linux/kernel.h>
+++++ #include <linux/ktime.h>
      #include <linux/list.h>
      #include <linux/list_sort.h>
      #include <linux/module.h>
      #include <linux/of_device.h>
      #include <linux/printk.h>
 +++++#include <linux/vmalloc.h>
      #include <linux/spi/spi.h>
      
      #include "spi-test.h"
@@@@@@@ -56,18 -55,6 -55,6 -55,6 -55,6 -56,6 +57,18 @@@@@@@ module_param(run_only_test, int, 0)
      MODULE_PARM_DESC(run_only_test,
                 "only run the test with this number (0-based !)");
      
 +++++/* use vmalloc'ed buffers */
 +++++int use_vmalloc;
 +++++module_param(use_vmalloc, int, 0644);
 +++++MODULE_PARM_DESC(use_vmalloc,
 +++++           "use vmalloc'ed buffers instead of kmalloc'ed");
 +++++
 +++++/* check rx ranges */
 +++++int check_ranges = 1;
 +++++module_param(check_ranges, int, 0644);
 +++++MODULE_PARM_DESC(check_ranges,
 +++++           "checks rx_buffer pattern are valid");
 +++++
      /* the actual tests to execute */
      static struct spi_test spi_tests[] = {
        {
                .iterate_len    = { ITERATE_MAX_LEN },
                .iterate_tx_align = ITERATE_ALIGN,
                .iterate_rx_align = ITERATE_ALIGN,
+++++           .transfer_count = 1,
                .transfers              = {
                        {
-----                           .len = 1,
                                .tx_buf = TX(0),
                                .rx_buf = RX(0),
                        },
                .iterate_len    = { ITERATE_MAX_LEN },
                .iterate_tx_align = ITERATE_ALIGN,
                .iterate_rx_align = ITERATE_ALIGN,
+++++           .transfer_count = 1,
                .transfers              = {
                        {
-----                           .len = 1,
                                .tx_buf = TX(PAGE_SIZE - 4),
                                .rx_buf = RX(PAGE_SIZE - 4),
                        },
                .fill_option    = FILL_COUNT_8,
                .iterate_len    = { ITERATE_MAX_LEN },
                .iterate_tx_align = ITERATE_ALIGN,
+++++           .transfer_count = 1,
                .transfers              = {
                        {
-----                           .len = 1,
                                .tx_buf = TX(0),
                        },
                },
                .fill_option    = FILL_COUNT_8,
                .iterate_len    = { ITERATE_MAX_LEN },
                .iterate_rx_align = ITERATE_ALIGN,
+++++           .transfer_count = 1,
                .transfers              = {
                        {
-----                           .len = 1,
                                .rx_buf = RX(0),
                        },
                },
                .iterate_len    = { ITERATE_LEN },
                .iterate_tx_align = ITERATE_ALIGN,
                .iterate_transfer_mask = BIT(0) | BIT(1),
+++++           .transfer_count = 2,
                .transfers              = {
                        {
-----                           .len = 1,
                                .tx_buf = TX(0),
                        },
                        {
-----                           .len = 1,
                                /* this is why we cant use ITERATE_MAX_LEN */
                                .tx_buf = TX(SPI_TEST_MAX_SIZE_HALF),
                        },
                .fill_option    = FILL_COUNT_8,
                .iterate_len    = { ITERATE_MAX_LEN },
                .iterate_tx_align = ITERATE_ALIGN,
-----           .iterate_transfer_mask = BIT(1),
+++++           .iterate_transfer_mask = BIT(0),
+++++           .transfer_count = 2,
                .transfers              = {
                        {
-----                           .len = 1,
                                .tx_buf = TX(64),
                        },
                        {
                .fill_option    = FILL_COUNT_8,
                .iterate_len    = { ITERATE_MAX_LEN },
                .iterate_tx_align = ITERATE_ALIGN,
-----           .iterate_transfer_mask = BIT(0),
+++++           .iterate_transfer_mask = BIT(1),
+++++           .transfer_count = 2,
                .transfers              = {
                        {
                                .len = 16,
                                .tx_buf = TX(0),
                        },
                        {
-----                           .len = 1,
                                .tx_buf = TX(64),
                        },
                },
                .iterate_len    = { ITERATE_MAX_LEN },
                .iterate_tx_align = ITERATE_ALIGN,
                .iterate_transfer_mask = BIT(0) | BIT(1),
+++++           .transfer_count = 2,
                .transfers              = {
                        {
-----                           .len = 1,
                                .tx_buf = TX(0),
                        },
                        {
-----                           .len = 1,
                                .rx_buf = RX(0),
                        },
                },
                .iterate_len    = { ITERATE_MAX_LEN },
                .iterate_tx_align = ITERATE_ALIGN,
                .iterate_transfer_mask = BIT(0),
+++++           .transfer_count = 2,
                .transfers              = {
                        {
-----                           .len = 1,
                                .tx_buf = TX(0),
                        },
                        {
                .iterate_len    = { ITERATE_MAX_LEN },
                .iterate_tx_align = ITERATE_ALIGN,
                .iterate_transfer_mask = BIT(1),
+++++           .transfer_count = 2,
                .transfers              = {
                        {
                                .len = 1,
                                .tx_buf = TX(0),
                        },
                        {
-----                           .len = 1,
                                .rx_buf = RX(0),
                        },
                },
                .iterate_len    = { ITERATE_LEN },
                .iterate_tx_align = ITERATE_ALIGN,
                .iterate_transfer_mask = BIT(0) | BIT(1),
+++++           .transfer_count = 2,
                .transfers              = {
                        {
-----                           .len = 1,
                                .tx_buf = TX(0),
                                .rx_buf = RX(0),
                        },
                        {
-----                           .len = 1,
                                /* making sure we align without overwrite
                                 * the reason we can not use ITERATE_MAX_LEN
                                 */
                .iterate_len    = { ITERATE_MAX_LEN },
                .iterate_tx_align = ITERATE_ALIGN,
                .iterate_transfer_mask = BIT(0),
+++++           .transfer_count = 2,
                .transfers              = {
                        {
-----                           .len = 1,
                                /* making sure we align without overwrite */
                                .tx_buf = TX(1024),
                                .rx_buf = RX(1024),
                .iterate_len    = { ITERATE_MAX_LEN },
                .iterate_tx_align = ITERATE_ALIGN,
                .iterate_transfer_mask = BIT(1),
+++++           .transfer_count = 2,
                .transfers              = {
                        {
                                .len = 1,
                                .rx_buf = RX(0),
                        },
                        {
-----                           .len = 1,
                                /* making sure we align without overwrite */
                                .tx_buf = TX(1024),
                                .rx_buf = RX(1024),
                        },
                },
        },
+++++   {
+++++           .description    = "two tx+rx transfers - delay after transfer",
+++++           .fill_option    = FILL_COUNT_8,
+++++           .iterate_len    = { ITERATE_MAX_LEN },
+++++           .iterate_transfer_mask = BIT(0) | BIT(1),
+++++           .transfer_count = 2,
+++++           .transfers              = {
+++++                   {
+++++                           .tx_buf = TX(0),
+++++                           .rx_buf = RX(0),
+++++                           .delay_usecs = 1000,
+++++                   },
+++++                   {
+++++                           .tx_buf = TX(0),
+++++                           .rx_buf = RX(0),
+++++                           .delay_usecs = 1000,
+++++                   },
+++++           },
+++++   },
      
        { /* end of tests sequence */ }
      };
@@@@@@@ -495,6 -482,6 -482,6 -482,6 -482,6 -499,36 +512,36 @@@@@@@ static int spi_check_rx_ranges(struct s
        return ret;
      }
      
+++++ static int spi_test_check_elapsed_time(struct spi_device *spi,
+++++                                  struct spi_test *test)
+++++ {
+++++   int i;
+++++   unsigned long long estimated_time = 0;
+++++   unsigned long long delay_usecs = 0;
+++++ 
+++++   for (i = 0; i < test->transfer_count; i++) {
+++++           struct spi_transfer *xfer = test->transfers + i;
+++++           unsigned long long nbits = (unsigned long long)BITS_PER_BYTE *
+++++                                      xfer->len;
+++++ 
+++++           delay_usecs += xfer->delay_usecs;
+++++           if (!xfer->speed_hz)
+++++                   continue;
+++++           estimated_time += div_u64(nbits * NSEC_PER_SEC, xfer->speed_hz);
+++++   }
+++++ 
+++++   estimated_time += delay_usecs * NSEC_PER_USEC;
+++++   if (test->elapsed_time < estimated_time) {
+++++           dev_err(&spi->dev,
+++++                   "elapsed time %lld ns is shorter than minimum estimated time %lld ns\n",
+++++                   test->elapsed_time, estimated_time);
+++++ 
+++++           return -EINVAL;
+++++   }
+++++ 
+++++   return 0;
+++++ }
+++++ 
      static int spi_test_check_loopback_result(struct spi_device *spi,
                                          struct spi_message *msg,
                                          void *tx, void *rx)
        int ret;
      
        /* checks rx_buffer pattern are valid with loopback or without */
 -----  ret = spi_check_rx_ranges(spi, msg, rx);
 -----  if (ret)
 -----          return ret;
 +++++  if (check_ranges) {
 +++++          ret = spi_check_rx_ranges(spi, msg, rx);
 +++++          if (ret)
 +++++                  return ret;
 +++++  }
      
        /* if we run without loopback, then return now */
        if (!loopback)
        /* if applicable to transfer check that rx_buf is equal to tx_buf */
        list_for_each_entry(xfer, &msg->transfers, transfer_list) {
                /* if there is no rx, then no check is needed */
-----           if (!xfer->rx_buf)
+++++           if (!xfer->len || !xfer->rx_buf)
                        continue;
                /* so depending on tx_buf we need to handle things */
                if (xfer->tx_buf) {
-----                   for (i = 1; i < xfer->len; i++) {
+++++                   for (i = 0; i < xfer->len; i++) {
                                txb = ((u8 *)xfer->tx_buf)[i];
                                rxb = ((u8 *)xfer->rx_buf)[i];
                                if (txb != rxb)
@@@@@@@ -760,15 -745,15 -745,15 -745,15 -745,15 -792,6 +807,6 @@@@@@@ static int spi_test_run_iter(struct spi
        /* copy the test template to test */
        memcpy(&test, testtemplate, sizeof(test));
      
-----   /* set up test->transfers to the correct count */
-----   if (!test.transfer_count) {
-----           for (i = 0;
-----               (i < SPI_TEST_MAX_TRANSFERS) && test.transfers[i].len;
-----               i++) {
-----                   test.transfer_count++;
-----           }
-----   }
----- 
        /* if iterate_transfer_mask is not set,
         * then set it to first transfer only
         */
                /* only when bit in transfer mask is set */
                if (!(test.iterate_transfer_mask & BIT(i)))
                        continue;
-----           if (len)
-----                   test.transfers[i].len = len;
+++++           test.transfers[i].len = len;
                if (test.transfers[i].tx_buf)
                        test.transfers[i].tx_buf += tx_off;
                if (test.transfers[i].tx_buf)
@@@@@@@ -845,12 -830,12 -830,12 -830,12 -830,12 -867,16 +882,16 @@@@@@@ int spi_test_execute_msg(struct spi_dev
      
        /* only if we do not simulate */
        if (!simulate_only) {
+++++           ktime_t start;
+++++ 
                /* dump the complete message before and after the transfer */
                if (dump_messages == 3)
                        spi_test_dump_message(spi, msg, true);
      
+++++           start = ktime_get();
                /* run spi message */
                ret = spi_sync(spi, msg);
+++++           test->elapsed_time = ktime_to_ns(ktime_sub(ktime_get(), start));
                if (ret == -ETIMEDOUT) {
                        dev_info(&spi->dev,
                                 "spi-message timed out - reruning...\n");
      
                /* run rx-buffer tests */
                ret = spi_test_check_loopback_result(spi, msg, tx, rx);
+++++           if (ret)
+++++                   goto exit;
+++++ 
+++++           ret = spi_test_check_elapsed_time(spi, test);
        }
      
        /* if requested or on error dump message (including data) */
@@@@@@@ -925,15 -910,15 -910,15 -910,15 -910,15 -955,6 +970,6 @@@@@@@ int spi_test_run_test(struct spi_devic
        /* iterate over all the iterable values using macros
         * (to make it a bit more readable...
         */
----- #define FOR_EACH_ITERATE(var, defaultvalue)                               \
-----   for (idx_##var = -1, var = defaultvalue;                        \
-----        ((idx_##var < 0) ||                                        \
-----                (                                                  \
-----                        (idx_##var < SPI_TEST_MAX_ITERATE) &&      \
-----                        (var = test->iterate_##var[idx_##var])     \
-----                )                                                  \
-----        );                                                         \
-----        idx_##var++)
      #define FOR_EACH_ALIGNMENT(var)                                           \
        for (var = 0;                                                   \
            var < (test->iterate_##var ?                                \
                        1);                                             \
            var++)
      
-----   FOR_EACH_ITERATE(len, 0) {
+++++   for (idx_len = 0; idx_len < SPI_TEST_MAX_ITERATE &&
+++++        (len = test->iterate_len[idx_len]) != -1; idx_len++) {
                FOR_EACH_ALIGNMENT(tx_align) {
                        FOR_EACH_ALIGNMENT(rx_align) {
                                /* and run the iteration */
@@@@@@@ -980,19 -965,13 -965,13 -965,13 -965,13 -1002,13 +1017,19 @@@@@@@ int spi_test_run_tests(struct spi_devic
        /* allocate rx/tx buffers of 128kB size without devm
         * in the hope that is on a page boundary
         */
 -----  rx = kzalloc(SPI_TEST_MAX_SIZE_PLUS, GFP_KERNEL);
 +++++  if (use_vmalloc)
 +++++          rx = vmalloc(SPI_TEST_MAX_SIZE_PLUS);
 +++++  else
 +++++          rx = kzalloc(SPI_TEST_MAX_SIZE_PLUS, GFP_KERNEL);
        if (!rx) {
                ret = -ENOMEM;
                goto out;
        }
      
 -----  tx = kzalloc(SPI_TEST_MAX_SIZE_PLUS, GFP_KERNEL);
 +++++  if (use_vmalloc)
 +++++          tx = vmalloc(SPI_TEST_MAX_SIZE_PLUS);
 +++++  else
 +++++          tx = kzalloc(SPI_TEST_MAX_SIZE_PLUS, GFP_KERNEL);
        if (!tx) {
                ret = -ENOMEM;
                goto out;
        }
      
      out:
 -----  kfree(rx);
 -----  kfree(tx);
 +++++  kvfree(rx);
 +++++  kvfree(tx);
        return ret;
      }
      EXPORT_SYMBOL_GPL(spi_test_run_tests);