hc
2024-02-20 102a0743326a03cd1a1202ceda21e175b7d3575c
kernel/drivers/dma/dmatest.c
....@@ -1,15 +1,13 @@
1
+// SPDX-License-Identifier: GPL-2.0-only
12 /*
23 * DMA Engine test module
34 *
45 * Copyright (C) 2007 Atmel Corporation
56 * Copyright (C) 2013 Intel Corporation
6
- *
7
- * This program is free software; you can redistribute it and/or modify
8
- * it under the terms of the GNU General Public License version 2 as
9
- * published by the Free Software Foundation.
107 */
118 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
129
10
+#include <linux/err.h>
1311 #include <linux/delay.h>
1412 #include <linux/dma-mapping.h>
1513 #include <linux/dmaengine.h>
....@@ -26,11 +24,6 @@
2624 static unsigned int test_buf_size = 16384;
2725 module_param(test_buf_size, uint, S_IRUGO | S_IWUSR);
2826 MODULE_PARM_DESC(test_buf_size, "Size of the memcpy test buffer");
29
-
30
-static char test_channel[20];
31
-module_param_string(channel, test_channel, sizeof(test_channel),
32
- S_IRUGO | S_IWUSR);
33
-MODULE_PARM_DESC(channel, "Bus ID of the channel to test (default: any)");
3427
3528 static char test_device[32];
3629 module_param_string(device, test_device, sizeof(test_device),
....@@ -68,7 +61,7 @@
6861 "Number of p+q source buffers (default: 3)");
6962
7063 static int timeout = 3000;
71
-module_param(timeout, uint, S_IRUGO | S_IWUSR);
64
+module_param(timeout, int, S_IRUGO | S_IWUSR);
7265 MODULE_PARM_DESC(timeout, "Transfer Timeout in msec (default: 3000), "
7366 "Pass -1 for infinite timeout");
7467
....@@ -84,6 +77,18 @@
8477 module_param(verbose, bool, S_IRUGO | S_IWUSR);
8578 MODULE_PARM_DESC(verbose, "Enable \"success\" result messages (default: off)");
8679
80
+static int alignment = -1;
81
+module_param(alignment, int, 0644);
82
+MODULE_PARM_DESC(alignment, "Custom data address alignment taken as 2^(alignment) (default: not used (-1))");
83
+
84
+static unsigned int transfer_size;
85
+module_param(transfer_size, uint, 0644);
86
+MODULE_PARM_DESC(transfer_size, "Optional custom transfer size in bytes (default: not used (0))");
87
+
88
+static bool polled;
89
+module_param(polled, bool, S_IRUGO | S_IWUSR);
90
+MODULE_PARM_DESC(polled, "Use polling for completion instead of interrupts");
91
+
8792 /**
8893 * struct dmatest_params - test parameters.
8994 * @buf_size: size of the memcpy test buffer
....@@ -95,6 +100,11 @@
95100 * @xor_sources: number of xor source buffers
96101 * @pq_sources: number of p+q source buffers
97102 * @timeout: transfer timeout in msec, -1 for infinite timeout
103
+ * @noverify: disable data verification
104
+ * @norandom: disable random offset setup
105
+ * @alignment: custom data address alignment taken as 2^alignment
106
+ * @transfer_size: custom transfer size in bytes
107
+ * @polled: use polling for completion instead of interrupts
98108 */
99109 struct dmatest_params {
100110 unsigned int buf_size;
....@@ -108,12 +118,19 @@
108118 int timeout;
109119 bool noverify;
110120 bool norandom;
121
+ int alignment;
122
+ unsigned int transfer_size;
123
+ bool polled;
111124 };
112125
113126 /**
114127 * struct dmatest_info - test information.
115128 * @params: test parameters
129
+ * @channels: channels under test
130
+ * @nr_channels: number of channels under test
116131 * @lock: access protection to the fields of this structure
132
+ * @did_init: module has been initialized completely
133
+ * @last_error: test has faced configuration issues
117134 */
118135 static struct dmatest_info {
119136 /* Test parameters */
....@@ -122,6 +139,7 @@
122139 /* Internal state */
123140 struct list_head channels;
124141 unsigned int nr_channels;
142
+ int last_error;
125143 struct mutex lock;
126144 bool did_init;
127145 } test_info = {
....@@ -138,6 +156,28 @@
138156 static bool dmatest_run;
139157 module_param_cb(run, &run_ops, &dmatest_run, S_IRUGO | S_IWUSR);
140158 MODULE_PARM_DESC(run, "Run the test (default: false)");
159
+
160
+static int dmatest_chan_set(const char *val, const struct kernel_param *kp);
161
+static int dmatest_chan_get(char *val, const struct kernel_param *kp);
162
+static const struct kernel_param_ops multi_chan_ops = {
163
+ .set = dmatest_chan_set,
164
+ .get = dmatest_chan_get,
165
+};
166
+
167
+static char test_channel[20];
168
+static struct kparam_string newchan_kps = {
169
+ .string = test_channel,
170
+ .maxlen = 20,
171
+};
172
+module_param_cb(channel, &multi_chan_ops, &newchan_kps, 0644);
173
+MODULE_PARM_DESC(channel, "Bus ID of the channel to test (default: any)");
174
+
175
+static int dmatest_test_list_get(char *val, const struct kernel_param *kp);
176
+static const struct kernel_param_ops test_list_ops = {
177
+ .get = dmatest_test_list_get,
178
+};
179
+module_param_cb(test_list, &test_list_ops, NULL, 0444);
180
+MODULE_PARM_DESC(test_list, "Print current test list");
141181
142182 /* Maximum amount of mismatched bytes in buffer to print */
143183 #define MAX_ERROR_COUNT 32
....@@ -160,10 +200,24 @@
160200 #define PATTERN_COUNT_MASK 0x1f
161201 #define PATTERN_MEMSET_IDX 0x01
162202
203
+/* Fixed point arithmetic ops */
204
+#define FIXPT_SHIFT 8
205
+#define FIXPNT_MASK 0xFF
206
+#define FIXPT_TO_INT(a) ((a) >> FIXPT_SHIFT)
207
+#define INT_TO_FIXPT(a) ((a) << FIXPT_SHIFT)
208
+#define FIXPT_GET_FRAC(a) ((((a) & FIXPNT_MASK) * 100) >> FIXPT_SHIFT)
209
+
163210 /* poor man's completion - we want to use wait_event_freezable() on it */
164211 struct dmatest_done {
165212 bool done;
166213 wait_queue_head_t *wait;
214
+};
215
+
216
+struct dmatest_data {
217
+ u8 **raw;
218
+ u8 **aligned;
219
+ unsigned int cnt;
220
+ unsigned int off;
167221 };
168222
169223 struct dmatest_thread {
....@@ -171,14 +225,13 @@
171225 struct dmatest_info *info;
172226 struct task_struct *task;
173227 struct dma_chan *chan;
174
- u8 **srcs;
175
- u8 **usrcs;
176
- u8 **dsts;
177
- u8 **udsts;
228
+ struct dmatest_data src;
229
+ struct dmatest_data dst;
178230 enum dma_transaction_type type;
179231 wait_queue_head_t done_wait;
180232 struct dmatest_done test_done;
181233 bool done;
234
+ bool pending;
182235 };
183236
184237 struct dmatest_chan {
....@@ -198,7 +251,23 @@
198251 struct dmatest_thread *thread;
199252
200253 list_for_each_entry(thread, &dtc->threads, node) {
201
- if (!thread->done)
254
+ if (!thread->done && !thread->pending)
255
+ return true;
256
+ }
257
+ }
258
+
259
+ return false;
260
+}
261
+
262
+static bool is_threaded_test_pending(struct dmatest_info *info)
263
+{
264
+ struct dmatest_chan *dtc;
265
+
266
+ list_for_each_entry(dtc, &info->channels, node) {
267
+ struct dmatest_thread *thread;
268
+
269
+ list_for_each_entry(thread, &dtc->threads, node) {
270
+ if (thread->pending)
202271 return true;
203272 }
204273 }
....@@ -386,8 +455,13 @@
386455 static void result(const char *err, unsigned int n, unsigned int src_off,
387456 unsigned int dst_off, unsigned int len, unsigned long data)
388457 {
389
- pr_info("%s: result #%u: '%s' with src_off=0x%x dst_off=0x%x len=0x%x (%lu)\n",
390
- current->comm, n, err, src_off, dst_off, len, data);
458
+ if (IS_ERR_VALUE(data)) {
459
+ pr_info("%s: result #%u: '%s' with src_off=0x%x dst_off=0x%x len=0x%x (%ld)\n",
460
+ current->comm, n, err, src_off, dst_off, len, data);
461
+ } else {
462
+ pr_info("%s: result #%u: '%s' with src_off=0x%x dst_off=0x%x len=0x%x (%lu)\n",
463
+ current->comm, n, err, src_off, dst_off, len, data);
464
+ }
391465 }
392466
393467 static void dbg_result(const char *err, unsigned int n, unsigned int src_off,
....@@ -419,13 +493,62 @@
419493 }
420494
421495 per_sec *= val;
496
+ per_sec = INT_TO_FIXPT(per_sec);
422497 do_div(per_sec, runtime);
498
+
423499 return per_sec;
424500 }
425501
426502 static unsigned long long dmatest_KBs(s64 runtime, unsigned long long len)
427503 {
428
- return dmatest_persec(runtime, len >> 10);
504
+ return FIXPT_TO_INT(dmatest_persec(runtime, len >> 10));
505
+}
506
+
507
+static void __dmatest_free_test_data(struct dmatest_data *d, unsigned int cnt)
508
+{
509
+ unsigned int i;
510
+
511
+ for (i = 0; i < cnt; i++)
512
+ kfree(d->raw[i]);
513
+
514
+ kfree(d->aligned);
515
+ kfree(d->raw);
516
+}
517
+
518
+static void dmatest_free_test_data(struct dmatest_data *d)
519
+{
520
+ __dmatest_free_test_data(d, d->cnt);
521
+}
522
+
523
+static int dmatest_alloc_test_data(struct dmatest_data *d,
524
+ unsigned int buf_size, u8 align)
525
+{
526
+ unsigned int i = 0;
527
+
528
+ d->raw = kcalloc(d->cnt + 1, sizeof(u8 *), GFP_KERNEL);
529
+ if (!d->raw)
530
+ return -ENOMEM;
531
+
532
+ d->aligned = kcalloc(d->cnt + 1, sizeof(u8 *), GFP_KERNEL);
533
+ if (!d->aligned)
534
+ goto err;
535
+
536
+ for (i = 0; i < d->cnt; i++) {
537
+ d->raw[i] = kmalloc(buf_size + align, GFP_KERNEL);
538
+ if (!d->raw[i])
539
+ goto err;
540
+
541
+ /* align to alignment restriction */
542
+ if (align)
543
+ d->aligned[i] = PTR_ALIGN(d->raw[i], align);
544
+ else
545
+ d->aligned[i] = d->raw[i];
546
+ }
547
+
548
+ return 0;
549
+err:
550
+ __dmatest_free_test_data(d, i);
551
+ return -ENOMEM;
429552 }
430553
431554 /*
....@@ -458,14 +581,16 @@
458581 enum dma_ctrl_flags flags;
459582 u8 *pq_coefs = NULL;
460583 int ret;
461
- int src_cnt;
462
- int dst_cnt;
584
+ unsigned int buf_size;
585
+ struct dmatest_data *src;
586
+ struct dmatest_data *dst;
463587 int i;
464588 ktime_t ktime, start, diff;
465589 ktime_t filltime = 0;
466590 ktime_t comparetime = 0;
467591 s64 runtime = 0;
468592 unsigned long long total_len = 0;
593
+ unsigned long long iops = 0;
469594 u8 align = 0;
470595 bool is_memset = false;
471596 dma_addr_t *srcs;
....@@ -476,95 +601,81 @@
476601 ret = -ENOMEM;
477602
478603 smp_rmb();
604
+ thread->pending = false;
479605 info = thread->info;
480606 params = &info->params;
481607 chan = thread->chan;
482608 dev = chan->device;
609
+ src = &thread->src;
610
+ dst = &thread->dst;
483611 if (thread->type == DMA_MEMCPY) {
484
- align = dev->copy_align;
485
- src_cnt = dst_cnt = 1;
612
+ align = params->alignment < 0 ? dev->copy_align :
613
+ params->alignment;
614
+ src->cnt = dst->cnt = 1;
486615 } else if (thread->type == DMA_MEMSET) {
487
- align = dev->fill_align;
488
- src_cnt = dst_cnt = 1;
616
+ align = params->alignment < 0 ? dev->fill_align :
617
+ params->alignment;
618
+ src->cnt = dst->cnt = 1;
489619 is_memset = true;
490620 } else if (thread->type == DMA_XOR) {
491621 /* force odd to ensure dst = src */
492
- src_cnt = min_odd(params->xor_sources | 1, dev->max_xor);
493
- dst_cnt = 1;
494
- align = dev->xor_align;
622
+ src->cnt = min_odd(params->xor_sources | 1, dev->max_xor);
623
+ dst->cnt = 1;
624
+ align = params->alignment < 0 ? dev->xor_align :
625
+ params->alignment;
495626 } else if (thread->type == DMA_PQ) {
496627 /* force odd to ensure dst = src */
497
- src_cnt = min_odd(params->pq_sources | 1, dma_maxpq(dev, 0));
498
- dst_cnt = 2;
499
- align = dev->pq_align;
628
+ src->cnt = min_odd(params->pq_sources | 1, dma_maxpq(dev, 0));
629
+ dst->cnt = 2;
630
+ align = params->alignment < 0 ? dev->pq_align :
631
+ params->alignment;
500632
501633 pq_coefs = kmalloc(params->pq_sources + 1, GFP_KERNEL);
502634 if (!pq_coefs)
503635 goto err_thread_type;
504636
505
- for (i = 0; i < src_cnt; i++)
637
+ for (i = 0; i < src->cnt; i++)
506638 pq_coefs[i] = 1;
507639 } else
508640 goto err_thread_type;
509641
510
- thread->srcs = kcalloc(src_cnt + 1, sizeof(u8 *), GFP_KERNEL);
511
- if (!thread->srcs)
512
- goto err_srcs;
513
-
514
- thread->usrcs = kcalloc(src_cnt + 1, sizeof(u8 *), GFP_KERNEL);
515
- if (!thread->usrcs)
516
- goto err_usrcs;
517
-
518
- for (i = 0; i < src_cnt; i++) {
519
- thread->usrcs[i] = kmalloc(params->buf_size + align,
520
- GFP_KERNEL);
521
- if (!thread->usrcs[i])
522
- goto err_srcbuf;
523
-
524
- /* align srcs to alignment restriction */
525
- if (align)
526
- thread->srcs[i] = PTR_ALIGN(thread->usrcs[i], align);
527
- else
528
- thread->srcs[i] = thread->usrcs[i];
642
+ /* Check if buffer count fits into map count variable (u8) */
643
+ if ((src->cnt + dst->cnt) >= 255) {
644
+ pr_err("too many buffers (%d of 255 supported)\n",
645
+ src->cnt + dst->cnt);
646
+ goto err_free_coefs;
529647 }
530
- thread->srcs[i] = NULL;
531648
532
- thread->dsts = kcalloc(dst_cnt + 1, sizeof(u8 *), GFP_KERNEL);
533
- if (!thread->dsts)
534
- goto err_dsts;
535
-
536
- thread->udsts = kcalloc(dst_cnt + 1, sizeof(u8 *), GFP_KERNEL);
537
- if (!thread->udsts)
538
- goto err_udsts;
539
-
540
- for (i = 0; i < dst_cnt; i++) {
541
- thread->udsts[i] = kmalloc(params->buf_size + align,
542
- GFP_KERNEL);
543
- if (!thread->udsts[i])
544
- goto err_dstbuf;
545
-
546
- /* align dsts to alignment restriction */
547
- if (align)
548
- thread->dsts[i] = PTR_ALIGN(thread->udsts[i], align);
549
- else
550
- thread->dsts[i] = thread->udsts[i];
649
+ buf_size = params->buf_size;
650
+ if (1 << align > buf_size) {
651
+ pr_err("%u-byte buffer too small for %d-byte alignment\n",
652
+ buf_size, 1 << align);
653
+ goto err_free_coefs;
551654 }
552
- thread->dsts[i] = NULL;
655
+
656
+ if (dmatest_alloc_test_data(src, buf_size, align) < 0)
657
+ goto err_free_coefs;
658
+
659
+ if (dmatest_alloc_test_data(dst, buf_size, align) < 0)
660
+ goto err_src;
553661
554662 set_user_nice(current, 10);
555663
556
- srcs = kcalloc(src_cnt, sizeof(dma_addr_t), GFP_KERNEL);
664
+ srcs = kcalloc(src->cnt, sizeof(dma_addr_t), GFP_KERNEL);
557665 if (!srcs)
558
- goto err_dstbuf;
666
+ goto err_dst;
559667
560
- dma_pq = kcalloc(dst_cnt, sizeof(dma_addr_t), GFP_KERNEL);
668
+ dma_pq = kcalloc(dst->cnt, sizeof(dma_addr_t), GFP_KERNEL);
561669 if (!dma_pq)
562670 goto err_srcs_array;
563671
564672 /*
565673 * src and dst buffers are freed by ourselves below
566674 */
567
- flags = DMA_CTRL_ACK | DMA_PREP_INTERRUPT;
675
+ if (params->polled)
676
+ flags = DMA_CTRL_ACK;
677
+ else
678
+ flags = DMA_CTRL_ACK | DMA_PREP_INTERRUPT;
568679
569680 ktime = ktime_get();
570681 while (!(kthread_should_stop() ||
....@@ -572,86 +683,83 @@
572683 struct dma_async_tx_descriptor *tx = NULL;
573684 struct dmaengine_unmap_data *um;
574685 dma_addr_t *dsts;
575
- unsigned int src_off, dst_off, len;
686
+ unsigned int len;
576687
577688 total_tests++;
578689
579
- /* Check if buffer count fits into map count variable (u8) */
580
- if ((src_cnt + dst_cnt) >= 255) {
581
- pr_err("too many buffers (%d of 255 supported)\n",
582
- src_cnt + dst_cnt);
583
- break;
690
+ if (params->transfer_size) {
691
+ if (params->transfer_size >= buf_size) {
692
+ pr_err("%u-byte transfer size must be lower than %u-buffer size\n",
693
+ params->transfer_size, buf_size);
694
+ break;
695
+ }
696
+ len = params->transfer_size;
697
+ } else if (params->norandom) {
698
+ len = buf_size;
699
+ } else {
700
+ len = dmatest_random() % buf_size + 1;
584701 }
585702
586
- if (1 << align > params->buf_size) {
587
- pr_err("%u-byte buffer too small for %d-byte alignment\n",
588
- params->buf_size, 1 << align);
589
- break;
703
+ /* Do not alter transfer size explicitly defined by user */
704
+ if (!params->transfer_size) {
705
+ len = (len >> align) << align;
706
+ if (!len)
707
+ len = 1 << align;
590708 }
591
-
592
- if (params->norandom)
593
- len = params->buf_size;
594
- else
595
- len = dmatest_random() % params->buf_size + 1;
596
-
597
- len = (len >> align) << align;
598
- if (!len)
599
- len = 1 << align;
600
-
601709 total_len += len;
602710
603711 if (params->norandom) {
604
- src_off = 0;
605
- dst_off = 0;
712
+ src->off = 0;
713
+ dst->off = 0;
606714 } else {
607
- src_off = dmatest_random() % (params->buf_size - len + 1);
608
- dst_off = dmatest_random() % (params->buf_size - len + 1);
715
+ src->off = dmatest_random() % (buf_size - len + 1);
716
+ dst->off = dmatest_random() % (buf_size - len + 1);
609717
610
- src_off = (src_off >> align) << align;
611
- dst_off = (dst_off >> align) << align;
718
+ src->off = (src->off >> align) << align;
719
+ dst->off = (dst->off >> align) << align;
612720 }
613721
614722 if (!params->noverify) {
615723 start = ktime_get();
616
- dmatest_init_srcs(thread->srcs, src_off, len,
617
- params->buf_size, is_memset);
618
- dmatest_init_dsts(thread->dsts, dst_off, len,
619
- params->buf_size, is_memset);
724
+ dmatest_init_srcs(src->aligned, src->off, len,
725
+ buf_size, is_memset);
726
+ dmatest_init_dsts(dst->aligned, dst->off, len,
727
+ buf_size, is_memset);
620728
621729 diff = ktime_sub(ktime_get(), start);
622730 filltime = ktime_add(filltime, diff);
623731 }
624732
625
- um = dmaengine_get_unmap_data(dev->dev, src_cnt + dst_cnt,
733
+ um = dmaengine_get_unmap_data(dev->dev, src->cnt + dst->cnt,
626734 GFP_KERNEL);
627735 if (!um) {
628736 failed_tests++;
629737 result("unmap data NULL", total_tests,
630
- src_off, dst_off, len, ret);
738
+ src->off, dst->off, len, ret);
631739 continue;
632740 }
633741
634
- um->len = params->buf_size;
635
- for (i = 0; i < src_cnt; i++) {
636
- void *buf = thread->srcs[i];
742
+ um->len = buf_size;
743
+ for (i = 0; i < src->cnt; i++) {
744
+ void *buf = src->aligned[i];
637745 struct page *pg = virt_to_page(buf);
638746 unsigned long pg_off = offset_in_page(buf);
639747
640748 um->addr[i] = dma_map_page(dev->dev, pg, pg_off,
641749 um->len, DMA_TO_DEVICE);
642
- srcs[i] = um->addr[i] + src_off;
750
+ srcs[i] = um->addr[i] + src->off;
643751 ret = dma_mapping_error(dev->dev, um->addr[i]);
644752 if (ret) {
645753 result("src mapping error", total_tests,
646
- src_off, dst_off, len, ret);
754
+ src->off, dst->off, len, ret);
647755 goto error_unmap_continue;
648756 }
649757 um->to_cnt++;
650758 }
651759 /* map with DMA_BIDIRECTIONAL to force writeback/invalidate */
652
- dsts = &um->addr[src_cnt];
653
- for (i = 0; i < dst_cnt; i++) {
654
- void *buf = thread->dsts[i];
760
+ dsts = &um->addr[src->cnt];
761
+ for (i = 0; i < dst->cnt; i++) {
762
+ void *buf = dst->aligned[i];
655763 struct page *pg = virt_to_page(buf);
656764 unsigned long pg_off = offset_in_page(buf);
657765
....@@ -660,7 +768,7 @@
660768 ret = dma_mapping_error(dev->dev, dsts[i]);
661769 if (ret) {
662770 result("dst mapping error", total_tests,
663
- src_off, dst_off, len, ret);
771
+ src->off, dst->off, len, ret);
664772 goto error_unmap_continue;
665773 }
666774 um->bidi_cnt++;
....@@ -668,106 +776,119 @@
668776
669777 if (thread->type == DMA_MEMCPY)
670778 tx = dev->device_prep_dma_memcpy(chan,
671
- dsts[0] + dst_off,
779
+ dsts[0] + dst->off,
672780 srcs[0], len, flags);
673781 else if (thread->type == DMA_MEMSET)
674782 tx = dev->device_prep_dma_memset(chan,
675
- dsts[0] + dst_off,
676
- *(thread->srcs[0] + src_off),
783
+ dsts[0] + dst->off,
784
+ *(src->aligned[0] + src->off),
677785 len, flags);
678786 else if (thread->type == DMA_XOR)
679787 tx = dev->device_prep_dma_xor(chan,
680
- dsts[0] + dst_off,
681
- srcs, src_cnt,
788
+ dsts[0] + dst->off,
789
+ srcs, src->cnt,
682790 len, flags);
683791 else if (thread->type == DMA_PQ) {
684
- for (i = 0; i < dst_cnt; i++)
685
- dma_pq[i] = dsts[i] + dst_off;
792
+ for (i = 0; i < dst->cnt; i++)
793
+ dma_pq[i] = dsts[i] + dst->off;
686794 tx = dev->device_prep_dma_pq(chan, dma_pq, srcs,
687
- src_cnt, pq_coefs,
795
+ src->cnt, pq_coefs,
688796 len, flags);
689797 }
690798
691799 if (!tx) {
692
- result("prep error", total_tests, src_off,
693
- dst_off, len, ret);
800
+ result("prep error", total_tests, src->off,
801
+ dst->off, len, ret);
694802 msleep(100);
695803 goto error_unmap_continue;
696804 }
697805
698806 done->done = false;
699
- tx->callback = dmatest_callback;
700
- tx->callback_param = done;
807
+ if (!params->polled) {
808
+ tx->callback = dmatest_callback;
809
+ tx->callback_param = done;
810
+ }
701811 cookie = tx->tx_submit(tx);
702812
703813 if (dma_submit_error(cookie)) {
704
- result("submit error", total_tests, src_off,
705
- dst_off, len, ret);
814
+ result("submit error", total_tests, src->off,
815
+ dst->off, len, ret);
706816 msleep(100);
707817 goto error_unmap_continue;
708818 }
709
- dma_async_issue_pending(chan);
710819
711
- wait_event_freezable_timeout(thread->done_wait, done->done,
712
- msecs_to_jiffies(params->timeout));
820
+ if (params->polled) {
821
+ status = dma_sync_wait(chan, cookie);
822
+ dmaengine_terminate_sync(chan);
823
+ if (status == DMA_COMPLETE)
824
+ done->done = true;
825
+ } else {
826
+ dma_async_issue_pending(chan);
713827
714
- status = dma_async_is_tx_complete(chan, cookie, NULL, NULL);
828
+ wait_event_freezable_timeout(thread->done_wait,
829
+ done->done,
830
+ msecs_to_jiffies(params->timeout));
831
+
832
+ status = dma_async_is_tx_complete(chan, cookie, NULL,
833
+ NULL);
834
+ }
715835
716836 if (!done->done) {
717
- dmaengine_unmap_put(um);
718
- result("test timed out", total_tests, src_off, dst_off,
837
+ result("test timed out", total_tests, src->off, dst->off,
719838 len, 0);
720839 goto error_unmap_continue;
721
- } else if (status != DMA_COMPLETE) {
722
- dmaengine_unmap_put(um);
840
+ } else if (status != DMA_COMPLETE &&
841
+ !(dma_has_cap(DMA_COMPLETION_NO_ORDER,
842
+ dev->cap_mask) &&
843
+ status == DMA_OUT_OF_ORDER)) {
723844 result(status == DMA_ERROR ?
724845 "completion error status" :
725
- "completion busy status", total_tests, src_off,
726
- dst_off, len, ret);
846
+ "completion busy status", total_tests, src->off,
847
+ dst->off, len, ret);
727848 goto error_unmap_continue;
728849 }
729850
730851 dmaengine_unmap_put(um);
731852
732853 if (params->noverify) {
733
- verbose_result("test passed", total_tests, src_off,
734
- dst_off, len, 0);
854
+ verbose_result("test passed", total_tests, src->off,
855
+ dst->off, len, 0);
735856 continue;
736857 }
737858
738859 start = ktime_get();
739860 pr_debug("%s: verifying source buffer...\n", current->comm);
740
- error_count = dmatest_verify(thread->srcs, 0, src_off,
861
+ error_count = dmatest_verify(src->aligned, 0, src->off,
741862 0, PATTERN_SRC, true, is_memset);
742
- error_count += dmatest_verify(thread->srcs, src_off,
743
- src_off + len, src_off,
863
+ error_count += dmatest_verify(src->aligned, src->off,
864
+ src->off + len, src->off,
744865 PATTERN_SRC | PATTERN_COPY, true, is_memset);
745
- error_count += dmatest_verify(thread->srcs, src_off + len,
746
- params->buf_size, src_off + len,
866
+ error_count += dmatest_verify(src->aligned, src->off + len,
867
+ buf_size, src->off + len,
747868 PATTERN_SRC, true, is_memset);
748869
749870 pr_debug("%s: verifying dest buffer...\n", current->comm);
750
- error_count += dmatest_verify(thread->dsts, 0, dst_off,
871
+ error_count += dmatest_verify(dst->aligned, 0, dst->off,
751872 0, PATTERN_DST, false, is_memset);
752873
753
- error_count += dmatest_verify(thread->dsts, dst_off,
754
- dst_off + len, src_off,
874
+ error_count += dmatest_verify(dst->aligned, dst->off,
875
+ dst->off + len, src->off,
755876 PATTERN_SRC | PATTERN_COPY, false, is_memset);
756877
757
- error_count += dmatest_verify(thread->dsts, dst_off + len,
758
- params->buf_size, dst_off + len,
878
+ error_count += dmatest_verify(dst->aligned, dst->off + len,
879
+ buf_size, dst->off + len,
759880 PATTERN_DST, false, is_memset);
760881
761882 diff = ktime_sub(ktime_get(), start);
762883 comparetime = ktime_add(comparetime, diff);
763884
764885 if (error_count) {
765
- result("data error", total_tests, src_off, dst_off,
886
+ result("data error", total_tests, src->off, dst->off,
766887 len, error_count);
767888 failed_tests++;
768889 } else {
769
- verbose_result("test passed", total_tests, src_off,
770
- dst_off, len, 0);
890
+ verbose_result("test passed", total_tests, src->off,
891
+ dst->off, len, 0);
771892 }
772893
773894 continue;
....@@ -785,30 +906,22 @@
785906 kfree(dma_pq);
786907 err_srcs_array:
787908 kfree(srcs);
788
-err_dstbuf:
789
- for (i = 0; thread->udsts[i]; i++)
790
- kfree(thread->udsts[i]);
791
- kfree(thread->udsts);
792
-err_udsts:
793
- kfree(thread->dsts);
794
-err_dsts:
795
-err_srcbuf:
796
- for (i = 0; thread->usrcs[i]; i++)
797
- kfree(thread->usrcs[i]);
798
- kfree(thread->usrcs);
799
-err_usrcs:
800
- kfree(thread->srcs);
801
-err_srcs:
909
+err_dst:
910
+ dmatest_free_test_data(dst);
911
+err_src:
912
+ dmatest_free_test_data(src);
913
+err_free_coefs:
802914 kfree(pq_coefs);
803915 err_thread_type:
804
- pr_info("%s: summary %u tests, %u failures %llu iops %llu KB/s (%d)\n",
916
+ iops = dmatest_persec(runtime, total_tests);
917
+ pr_info("%s: summary %u tests, %u failures %llu.%02llu iops %llu KB/s (%d)\n",
805918 current->comm, total_tests, failed_tests,
806
- dmatest_persec(runtime, total_tests),
919
+ FIXPT_TO_INT(iops), FIXPT_GET_FRAC(iops),
807920 dmatest_KBs(runtime, total_len), ret);
808921
809922 /* terminate all transfers on specified channels */
810923 if (ret || failed_tests)
811
- dmaengine_terminate_all(chan);
924
+ dmaengine_terminate_sync(chan);
812925
813926 thread->done = true;
814927 wake_up(&thread_wait);
....@@ -832,7 +945,7 @@
832945 }
833946
834947 /* terminate all transfers on specified channels */
835
- dmaengine_terminate_all(dtc->chan);
948
+ dmaengine_terminate_sync(dtc->chan);
836949
837950 kfree(dtc);
838951 }
....@@ -882,7 +995,7 @@
882995 /* srcbuf and dstbuf are allocated by the thread itself */
883996 get_task_struct(thread->task);
884997 list_add_tail(&thread->node, &dtc->threads);
885
- wake_up_process(thread->task);
998
+ thread->pending = true;
886999 }
8871000
8881001 return i;
....@@ -904,6 +1017,12 @@
9041017
9051018 dtc->chan = chan;
9061019 INIT_LIST_HEAD(&dtc->threads);
1020
+
1021
+ if (dma_has_cap(DMA_COMPLETION_NO_ORDER, dma_dev->cap_mask) &&
1022
+ info->params.polled) {
1023
+ info->params.polled = false;
1024
+ pr_warn("DMA_COMPLETION_NO_ORDER, polled disabled\n");
1025
+ }
9071026
9081027 if (dma_has_cap(DMA_MEMCPY, dma_dev->cap_mask)) {
9091028 if (dmatest == 0) {
....@@ -928,7 +1047,7 @@
9281047 thread_count += cnt > 0 ? cnt : 0;
9291048 }
9301049
931
- pr_info("Started %u threads using %s\n",
1050
+ pr_info("Added %u threads using %s\n",
9321051 thread_count, dma_chan_name(chan));
9331052
9341053 list_add_tail(&dtc->node, &info->channels);
....@@ -939,13 +1058,7 @@
9391058
9401059 static bool filter(struct dma_chan *chan, void *param)
9411060 {
942
- struct dmatest_params *params = param;
943
-
944
- if (!dmatest_match_channel(params, chan) ||
945
- !dmatest_match_device(params, chan->device))
946
- return false;
947
- else
948
- return true;
1061
+ return dmatest_match_channel(param, chan) && dmatest_match_device(param, chan->device);
9491062 }
9501063
9511064 static void request_channels(struct dmatest_info *info,
....@@ -973,7 +1086,7 @@
9731086 }
9741087 }
9751088
976
-static void run_threaded_test(struct dmatest_info *info)
1089
+static void add_threaded_test(struct dmatest_info *info)
9771090 {
9781091 struct dmatest_params *params = &info->params;
9791092
....@@ -989,11 +1102,32 @@
9891102 params->timeout = timeout;
9901103 params->noverify = noverify;
9911104 params->norandom = norandom;
1105
+ params->alignment = alignment;
1106
+ params->transfer_size = transfer_size;
1107
+ params->polled = polled;
9921108
9931109 request_channels(info, DMA_MEMCPY);
9941110 request_channels(info, DMA_MEMSET);
9951111 request_channels(info, DMA_XOR);
9961112 request_channels(info, DMA_PQ);
1113
+}
1114
+
1115
+static void run_pending_tests(struct dmatest_info *info)
1116
+{
1117
+ struct dmatest_chan *dtc;
1118
+ unsigned int thread_count = 0;
1119
+
1120
+ list_for_each_entry(dtc, &info->channels, node) {
1121
+ struct dmatest_thread *thread;
1122
+
1123
+ thread_count = 0;
1124
+ list_for_each_entry(thread, &dtc->threads, node) {
1125
+ wake_up_process(thread->task);
1126
+ thread_count++;
1127
+ }
1128
+ pr_info("Started %u threads using %s\n",
1129
+ thread_count, dma_chan_name(dtc->chan));
1130
+ }
9971131 }
9981132
9991133 static void stop_threaded_test(struct dmatest_info *info)
....@@ -1012,7 +1146,7 @@
10121146 info->nr_channels = 0;
10131147 }
10141148
1015
-static void restart_threaded_test(struct dmatest_info *info, bool run)
1149
+static void start_threaded_tests(struct dmatest_info *info)
10161150 {
10171151 /* we might be called early to set run=, defer running until all
10181152 * parameters have been evaluated
....@@ -1020,11 +1154,7 @@
10201154 if (!info->did_init)
10211155 return;
10221156
1023
- /* Stop any running test first */
1024
- stop_threaded_test(info);
1025
-
1026
- /* Run test with new parameters */
1027
- run_threaded_test(info);
1157
+ run_pending_tests(info);
10281158 }
10291159
10301160 static int dmatest_run_get(char *val, const struct kernel_param *kp)
....@@ -1035,7 +1165,8 @@
10351165 if (is_threaded_test_run(info)) {
10361166 dmatest_run = true;
10371167 } else {
1038
- stop_threaded_test(info);
1168
+ if (!is_threaded_test_pending(info))
1169
+ stop_threaded_test(info);
10391170 dmatest_run = false;
10401171 }
10411172 mutex_unlock(&info->lock);
....@@ -1053,16 +1184,139 @@
10531184 if (ret) {
10541185 mutex_unlock(&info->lock);
10551186 return ret;
1187
+ } else if (dmatest_run) {
1188
+ if (!is_threaded_test_pending(info)) {
1189
+ /*
1190
+ * We have nothing to run. This can be due to:
1191
+ */
1192
+ ret = info->last_error;
1193
+ if (ret) {
1194
+ /* 1) Misconfiguration */
1195
+ pr_err("Channel misconfigured, can't continue\n");
1196
+ mutex_unlock(&info->lock);
1197
+ return ret;
1198
+ } else {
1199
+ /* 2) We rely on defaults */
1200
+ pr_info("No channels configured, continue with any\n");
1201
+ if (!is_threaded_test_run(info))
1202
+ stop_threaded_test(info);
1203
+ add_threaded_test(info);
1204
+ }
1205
+ }
1206
+ start_threaded_tests(info);
1207
+ } else {
1208
+ stop_threaded_test(info);
10561209 }
1057
-
1058
- if (is_threaded_test_run(info))
1059
- ret = -EBUSY;
1060
- else if (dmatest_run)
1061
- restart_threaded_test(info, dmatest_run);
10621210
10631211 mutex_unlock(&info->lock);
10641212
10651213 return ret;
1214
+}
1215
+
1216
+static int dmatest_chan_set(const char *val, const struct kernel_param *kp)
1217
+{
1218
+ struct dmatest_info *info = &test_info;
1219
+ struct dmatest_chan *dtc;
1220
+ char chan_reset_val[20];
1221
+ int ret;
1222
+
1223
+ mutex_lock(&info->lock);
1224
+ ret = param_set_copystring(val, kp);
1225
+ if (ret) {
1226
+ mutex_unlock(&info->lock);
1227
+ return ret;
1228
+ }
1229
+ /*Clear any previously run threads */
1230
+ if (!is_threaded_test_run(info) && !is_threaded_test_pending(info))
1231
+ stop_threaded_test(info);
1232
+ /* Reject channels that are already registered */
1233
+ if (is_threaded_test_pending(info)) {
1234
+ list_for_each_entry(dtc, &info->channels, node) {
1235
+ if (strcmp(dma_chan_name(dtc->chan),
1236
+ strim(test_channel)) == 0) {
1237
+ dtc = list_last_entry(&info->channels,
1238
+ struct dmatest_chan,
1239
+ node);
1240
+ strlcpy(chan_reset_val,
1241
+ dma_chan_name(dtc->chan),
1242
+ sizeof(chan_reset_val));
1243
+ ret = -EBUSY;
1244
+ goto add_chan_err;
1245
+ }
1246
+ }
1247
+ }
1248
+
1249
+ add_threaded_test(info);
1250
+
1251
+ /* Check if channel was added successfully */
1252
+ if (!list_empty(&info->channels)) {
1253
+ /*
1254
+ * if new channel was not successfully added, revert the
1255
+ * "test_channel" string to the name of the last successfully
1256
+ * added channel. exception for when users issues empty string
1257
+ * to channel parameter.
1258
+ */
1259
+ dtc = list_last_entry(&info->channels, struct dmatest_chan, node);
1260
+ if ((strcmp(dma_chan_name(dtc->chan), strim(test_channel)) != 0)
1261
+ && (strcmp("", strim(test_channel)) != 0)) {
1262
+ ret = -EINVAL;
1263
+ strlcpy(chan_reset_val, dma_chan_name(dtc->chan),
1264
+ sizeof(chan_reset_val));
1265
+ goto add_chan_err;
1266
+ }
1267
+
1268
+ } else {
1269
+ /* Clear test_channel if no channels were added successfully */
1270
+ strlcpy(chan_reset_val, "", sizeof(chan_reset_val));
1271
+ ret = -EBUSY;
1272
+ goto add_chan_err;
1273
+ }
1274
+
1275
+ info->last_error = ret;
1276
+ mutex_unlock(&info->lock);
1277
+
1278
+ return ret;
1279
+
1280
+add_chan_err:
1281
+ param_set_copystring(chan_reset_val, kp);
1282
+ info->last_error = ret;
1283
+ mutex_unlock(&info->lock);
1284
+
1285
+ return ret;
1286
+}
1287
+
1288
+static int dmatest_chan_get(char *val, const struct kernel_param *kp)
1289
+{
1290
+ struct dmatest_info *info = &test_info;
1291
+
1292
+ mutex_lock(&info->lock);
1293
+ if (!is_threaded_test_run(info) && !is_threaded_test_pending(info)) {
1294
+ stop_threaded_test(info);
1295
+ strlcpy(test_channel, "", sizeof(test_channel));
1296
+ }
1297
+ mutex_unlock(&info->lock);
1298
+
1299
+ return param_get_string(val, kp);
1300
+}
1301
+
1302
+static int dmatest_test_list_get(char *val, const struct kernel_param *kp)
1303
+{
1304
+ struct dmatest_info *info = &test_info;
1305
+ struct dmatest_chan *dtc;
1306
+ unsigned int thread_count = 0;
1307
+
1308
+ list_for_each_entry(dtc, &info->channels, node) {
1309
+ struct dmatest_thread *thread;
1310
+
1311
+ thread_count = 0;
1312
+ list_for_each_entry(thread, &dtc->threads, node) {
1313
+ thread_count++;
1314
+ }
1315
+ pr_info("%u threads using %s\n",
1316
+ thread_count, dma_chan_name(dtc->chan));
1317
+ }
1318
+
1319
+ return 0;
10661320 }
10671321
10681322 static int __init dmatest_init(void)
....@@ -1072,7 +1326,8 @@
10721326
10731327 if (dmatest_run) {
10741328 mutex_lock(&info->lock);
1075
- run_threaded_test(info);
1329
+ add_threaded_test(info);
1330
+ run_pending_tests(info);
10761331 mutex_unlock(&info->lock);
10771332 }
10781333