spi: loopback-test: add elapsed time check
authorAkinobu Mita <akinobu.mita@gmail.com>
Fri, 17 Mar 2017 18:17:30 +0000 (03:17 +0900)
committerMark Brown <broonie@kernel.org>
Fri, 17 Mar 2017 21:54:08 +0000 (21:54 +0000)
This adds checks whether the elapsed time is longer than the minimam
estimated time.  The estimated time is calculated with the total
transfer length per clock rate and optional spi_transfer.delay_usecs.

Signed-off-by: Akinobu Mita <akinobu.mita@gmail.com>
Signed-off-by: Mark Brown <broonie@kernel.org>
drivers/spi/spi-loopback-test.c
drivers/spi/spi-test.h

index 6df6ddd..66e8cfd 100644 (file)
@@ -20,6 +20,7 @@
 
 #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>
@@ -479,6 +480,35 @@ static int spi_check_rx_ranges(struct spi_device *spi,
        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 = 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 minimam 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)
@@ -817,12 +847,16 @@ int spi_test_execute_msg(struct spi_device *spi, struct spi_test *test,
 
        /* 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");
@@ -848,6 +882,10 @@ int spi_test_execute_msg(struct spi_device *spi, struct spi_test *test,
 
                /* 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) */
index 82fff4a..6ed7b89 100644 (file)
@@ -75,6 +75,7 @@
  * @fill_option:      define the way how tx_buf is filled
  * @fill_pattern:     fill pattern to apply to the tx_buf
  *                    (used in some of the @fill_options)
+ * @elapsed_time:     elapsed time in nanoseconds
  */
 
 struct spi_test {
@@ -108,6 +109,7 @@ struct spi_test {
 #define FILL_TRANSFER_BYTE_32 11 /* fill with the transfer byte - 32 bit */
 #define FILL_TRANSFER_NUM     16 /* fill with the transfer number */
        u32 fill_pattern;
+       unsigned long long elapsed_time;
 };
 
 /* default implementation for @spi_test.run_test */