aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/dma/dmatest.c109
1 files changed, 62 insertions, 47 deletions
diff --git a/drivers/dma/dmatest.c b/drivers/dma/dmatest.c
index 475a21ad6657..c6e5d8331c66 100644
--- a/drivers/dma/dmatest.c
+++ b/drivers/dma/dmatest.c
@@ -97,7 +97,7 @@ struct dmatest_chan {
97}; 97};
98 98
99/** 99/**
100 * struct dmatest_info - test information. 100 * struct dmatest_params - test parameters.
101 * @buf_size: size of the memcpy test buffer 101 * @buf_size: size of the memcpy test buffer
102 * @channel: bus ID of the channel to test 102 * @channel: bus ID of the channel to test
103 * @device: bus ID of the DMA Engine to test 103 * @device: bus ID of the DMA Engine to test
@@ -108,8 +108,7 @@ struct dmatest_chan {
108 * @pq_sources: number of p+q source buffers 108 * @pq_sources: number of p+q source buffers
109 * @timeout: transfer timeout in msec, -1 for infinite timeout 109 * @timeout: transfer timeout in msec, -1 for infinite timeout
110 */ 110 */
111struct dmatest_info { 111struct dmatest_params {
112 /* Test parameters */
113 unsigned int buf_size; 112 unsigned int buf_size;
114 char channel[20]; 113 char channel[20];
115 char device[20]; 114 char device[20];
@@ -119,6 +118,15 @@ struct dmatest_info {
119 unsigned int xor_sources; 118 unsigned int xor_sources;
120 unsigned int pq_sources; 119 unsigned int pq_sources;
121 int timeout; 120 int timeout;
121};
122
123/**
124 * struct dmatest_info - test information.
125 * @params: test parameters
126 */
127struct dmatest_info {
128 /* Test parameters */
129 struct dmatest_params params;
122 130
123 /* Internal state */ 131 /* Internal state */
124 struct list_head channels; 132 struct list_head channels;
@@ -127,20 +135,20 @@ struct dmatest_info {
127 135
128static struct dmatest_info test_info; 136static struct dmatest_info test_info;
129 137
130static bool dmatest_match_channel(struct dmatest_info *info, 138static bool dmatest_match_channel(struct dmatest_params *params,
131 struct dma_chan *chan) 139 struct dma_chan *chan)
132{ 140{
133 if (info->channel[0] == '\0') 141 if (params->channel[0] == '\0')
134 return true; 142 return true;
135 return strcmp(dma_chan_name(chan), info->channel) == 0; 143 return strcmp(dma_chan_name(chan), params->channel) == 0;
136} 144}
137 145
138static bool dmatest_match_device(struct dmatest_info *info, 146static bool dmatest_match_device(struct dmatest_params *params,
139 struct dma_device *device) 147 struct dma_device *device)
140{ 148{
141 if (info->device[0] == '\0') 149 if (params->device[0] == '\0')
142 return true; 150 return true;
143 return strcmp(dev_name(device->dev), info->device) == 0; 151 return strcmp(dev_name(device->dev), params->device) == 0;
144} 152}
145 153
146static unsigned long dmatest_random(void) 154static unsigned long dmatest_random(void)
@@ -300,6 +308,7 @@ static int dmatest_func(void *data)
300 struct dmatest_thread *thread = data; 308 struct dmatest_thread *thread = data;
301 struct dmatest_done done = { .wait = &done_wait }; 309 struct dmatest_done done = { .wait = &done_wait };
302 struct dmatest_info *info; 310 struct dmatest_info *info;
311 struct dmatest_params *params;
303 struct dma_chan *chan; 312 struct dma_chan *chan;
304 struct dma_device *dev; 313 struct dma_device *dev;
305 const char *thread_name; 314 const char *thread_name;
@@ -323,20 +332,21 @@ static int dmatest_func(void *data)
323 332
324 smp_rmb(); 333 smp_rmb();
325 info = thread->info; 334 info = thread->info;
335 params = &info->params;
326 chan = thread->chan; 336 chan = thread->chan;
327 dev = chan->device; 337 dev = chan->device;
328 if (thread->type == DMA_MEMCPY) 338 if (thread->type == DMA_MEMCPY)
329 src_cnt = dst_cnt = 1; 339 src_cnt = dst_cnt = 1;
330 else if (thread->type == DMA_XOR) { 340 else if (thread->type == DMA_XOR) {
331 /* force odd to ensure dst = src */ 341 /* force odd to ensure dst = src */
332 src_cnt = min_odd(info->xor_sources | 1, dev->max_xor); 342 src_cnt = min_odd(params->xor_sources | 1, dev->max_xor);
333 dst_cnt = 1; 343 dst_cnt = 1;
334 } else if (thread->type == DMA_PQ) { 344 } else if (thread->type == DMA_PQ) {
335 /* force odd to ensure dst = src */ 345 /* force odd to ensure dst = src */
336 src_cnt = min_odd(info->pq_sources | 1, dma_maxpq(dev, 0)); 346 src_cnt = min_odd(params->pq_sources | 1, dma_maxpq(dev, 0));
337 dst_cnt = 2; 347 dst_cnt = 2;
338 348
339 pq_coefs = kmalloc(info->pq_sources+1, GFP_KERNEL); 349 pq_coefs = kmalloc(params->pq_sources+1, GFP_KERNEL);
340 if (!pq_coefs) 350 if (!pq_coefs)
341 goto err_thread_type; 351 goto err_thread_type;
342 352
@@ -349,7 +359,7 @@ static int dmatest_func(void *data)
349 if (!thread->srcs) 359 if (!thread->srcs)
350 goto err_srcs; 360 goto err_srcs;
351 for (i = 0; i < src_cnt; i++) { 361 for (i = 0; i < src_cnt; i++) {
352 thread->srcs[i] = kmalloc(info->buf_size, GFP_KERNEL); 362 thread->srcs[i] = kmalloc(params->buf_size, GFP_KERNEL);
353 if (!thread->srcs[i]) 363 if (!thread->srcs[i])
354 goto err_srcbuf; 364 goto err_srcbuf;
355 } 365 }
@@ -359,7 +369,7 @@ static int dmatest_func(void *data)
359 if (!thread->dsts) 369 if (!thread->dsts)
360 goto err_dsts; 370 goto err_dsts;
361 for (i = 0; i < dst_cnt; i++) { 371 for (i = 0; i < dst_cnt; i++) {
362 thread->dsts[i] = kmalloc(info->buf_size, GFP_KERNEL); 372 thread->dsts[i] = kmalloc(params->buf_size, GFP_KERNEL);
363 if (!thread->dsts[i]) 373 if (!thread->dsts[i])
364 goto err_dstbuf; 374 goto err_dstbuf;
365 } 375 }
@@ -375,7 +385,7 @@ static int dmatest_func(void *data)
375 | DMA_COMPL_SKIP_DEST_UNMAP | DMA_COMPL_SRC_UNMAP_SINGLE; 385 | DMA_COMPL_SKIP_DEST_UNMAP | DMA_COMPL_SRC_UNMAP_SINGLE;
376 386
377 while (!kthread_should_stop() 387 while (!kthread_should_stop()
378 && !(info->iterations && total_tests >= info->iterations)) { 388 && !(params->iterations && total_tests >= params->iterations)) {
379 struct dma_async_tx_descriptor *tx = NULL; 389 struct dma_async_tx_descriptor *tx = NULL;
380 dma_addr_t dma_srcs[src_cnt]; 390 dma_addr_t dma_srcs[src_cnt];
381 dma_addr_t dma_dsts[dst_cnt]; 391 dma_addr_t dma_dsts[dst_cnt];
@@ -391,24 +401,24 @@ static int dmatest_func(void *data)
391 else if (thread->type == DMA_PQ) 401 else if (thread->type == DMA_PQ)
392 align = dev->pq_align; 402 align = dev->pq_align;
393 403
394 if (1 << align > info->buf_size) { 404 if (1 << align > params->buf_size) {
395 pr_err("%u-byte buffer too small for %d-byte alignment\n", 405 pr_err("%u-byte buffer too small for %d-byte alignment\n",
396 info->buf_size, 1 << align); 406 params->buf_size, 1 << align);
397 break; 407 break;
398 } 408 }
399 409
400 len = dmatest_random() % info->buf_size + 1; 410 len = dmatest_random() % params->buf_size + 1;
401 len = (len >> align) << align; 411 len = (len >> align) << align;
402 if (!len) 412 if (!len)
403 len = 1 << align; 413 len = 1 << align;
404 src_off = dmatest_random() % (info->buf_size - len + 1); 414 src_off = dmatest_random() % (params->buf_size - len + 1);
405 dst_off = dmatest_random() % (info->buf_size - len + 1); 415 dst_off = dmatest_random() % (params->buf_size - len + 1);
406 416
407 src_off = (src_off >> align) << align; 417 src_off = (src_off >> align) << align;
408 dst_off = (dst_off >> align) << align; 418 dst_off = (dst_off >> align) << align;
409 419
410 dmatest_init_srcs(thread->srcs, src_off, len, info->buf_size); 420 dmatest_init_srcs(thread->srcs, src_off, len, params->buf_size);
411 dmatest_init_dsts(thread->dsts, dst_off, len, info->buf_size); 421 dmatest_init_dsts(thread->dsts, dst_off, len, params->buf_size);
412 422
413 for (i = 0; i < src_cnt; i++) { 423 for (i = 0; i < src_cnt; i++) {
414 u8 *buf = thread->srcs[i] + src_off; 424 u8 *buf = thread->srcs[i] + src_off;
@@ -429,16 +439,17 @@ static int dmatest_func(void *data)
429 /* map with DMA_BIDIRECTIONAL to force writeback/invalidate */ 439 /* map with DMA_BIDIRECTIONAL to force writeback/invalidate */
430 for (i = 0; i < dst_cnt; i++) { 440 for (i = 0; i < dst_cnt; i++) {
431 dma_dsts[i] = dma_map_single(dev->dev, thread->dsts[i], 441 dma_dsts[i] = dma_map_single(dev->dev, thread->dsts[i],
432 info->buf_size, 442 params->buf_size,
433 DMA_BIDIRECTIONAL); 443 DMA_BIDIRECTIONAL);
434 ret = dma_mapping_error(dev->dev, dma_dsts[i]); 444 ret = dma_mapping_error(dev->dev, dma_dsts[i]);
435 if (ret) { 445 if (ret) {
436 unmap_src(dev->dev, dma_srcs, len, src_cnt); 446 unmap_src(dev->dev, dma_srcs, len, src_cnt);
437 unmap_dst(dev->dev, dma_dsts, info->buf_size, i); 447 unmap_dst(dev->dev, dma_dsts, params->buf_size,
448 i);
438 pr_warn("%s: #%u: mapping error %d with " 449 pr_warn("%s: #%u: mapping error %d with "
439 "dst_off=0x%x len=0x%x\n", 450 "dst_off=0x%x len=0x%x\n",
440 thread_name, total_tests - 1, ret, 451 thread_name, total_tests - 1, ret,
441 dst_off, info->buf_size); 452 dst_off, params->buf_size);
442 failed_tests++; 453 failed_tests++;
443 continue; 454 continue;
444 } 455 }
@@ -466,7 +477,8 @@ static int dmatest_func(void *data)
466 477
467 if (!tx) { 478 if (!tx) {
468 unmap_src(dev->dev, dma_srcs, len, src_cnt); 479 unmap_src(dev->dev, dma_srcs, len, src_cnt);
469 unmap_dst(dev->dev, dma_dsts, info->buf_size, dst_cnt); 480 unmap_dst(dev->dev, dma_dsts, params->buf_size,
481 dst_cnt);
470 pr_warning("%s: #%u: prep error with src_off=0x%x " 482 pr_warning("%s: #%u: prep error with src_off=0x%x "
471 "dst_off=0x%x len=0x%x\n", 483 "dst_off=0x%x len=0x%x\n",
472 thread_name, total_tests - 1, 484 thread_name, total_tests - 1,
@@ -494,7 +506,7 @@ static int dmatest_func(void *data)
494 506
495 wait_event_freezable_timeout(done_wait, 507 wait_event_freezable_timeout(done_wait,
496 done.done || kthread_should_stop(), 508 done.done || kthread_should_stop(),
497 msecs_to_jiffies(info->timeout)); 509 msecs_to_jiffies(params->timeout));
498 510
499 status = dma_async_is_tx_complete(chan, cookie, NULL, NULL); 511 status = dma_async_is_tx_complete(chan, cookie, NULL, NULL);
500 512
@@ -521,7 +533,7 @@ static int dmatest_func(void *data)
521 } 533 }
522 534
523 /* Unmap by myself (see DMA_COMPL_SKIP_DEST_UNMAP above) */ 535 /* Unmap by myself (see DMA_COMPL_SKIP_DEST_UNMAP above) */
524 unmap_dst(dev->dev, dma_dsts, info->buf_size, dst_cnt); 536 unmap_dst(dev->dev, dma_dsts, params->buf_size, dst_cnt);
525 537
526 error_count = 0; 538 error_count = 0;
527 539
@@ -532,7 +544,7 @@ static int dmatest_func(void *data)
532 src_off + len, src_off, 544 src_off + len, src_off,
533 PATTERN_SRC | PATTERN_COPY, true); 545 PATTERN_SRC | PATTERN_COPY, true);
534 error_count += dmatest_verify(thread->srcs, src_off + len, 546 error_count += dmatest_verify(thread->srcs, src_off + len,
535 info->buf_size, src_off + len, 547 params->buf_size, src_off + len,
536 PATTERN_SRC, true); 548 PATTERN_SRC, true);
537 549
538 pr_debug("%s: verifying dest buffer...\n", 550 pr_debug("%s: verifying dest buffer...\n",
@@ -543,7 +555,7 @@ static int dmatest_func(void *data)
543 dst_off + len, src_off, 555 dst_off + len, src_off,
544 PATTERN_SRC | PATTERN_COPY, false); 556 PATTERN_SRC | PATTERN_COPY, false);
545 error_count += dmatest_verify(thread->dsts, dst_off + len, 557 error_count += dmatest_verify(thread->dsts, dst_off + len,
546 info->buf_size, dst_off + len, 558 params->buf_size, dst_off + len,
547 PATTERN_DST, false); 559 PATTERN_DST, false);
548 560
549 if (error_count) { 561 if (error_count) {
@@ -580,7 +592,7 @@ err_thread_type:
580 if (ret) 592 if (ret)
581 dmaengine_terminate_all(chan); 593 dmaengine_terminate_all(chan);
582 594
583 if (info->iterations > 0) 595 if (params->iterations > 0)
584 while (!kthread_should_stop()) { 596 while (!kthread_should_stop()) {
585 DECLARE_WAIT_QUEUE_HEAD_ONSTACK(wait_dmatest_exit); 597 DECLARE_WAIT_QUEUE_HEAD_ONSTACK(wait_dmatest_exit);
586 interruptible_sleep_on(&wait_dmatest_exit); 598 interruptible_sleep_on(&wait_dmatest_exit);
@@ -612,6 +624,7 @@ static void dmatest_cleanup_channel(struct dmatest_chan *dtc)
612static int dmatest_add_threads(struct dmatest_info *info, 624static int dmatest_add_threads(struct dmatest_info *info,
613 struct dmatest_chan *dtc, enum dma_transaction_type type) 625 struct dmatest_chan *dtc, enum dma_transaction_type type)
614{ 626{
627 struct dmatest_params *params = &info->params;
615 struct dmatest_thread *thread; 628 struct dmatest_thread *thread;
616 struct dma_chan *chan = dtc->chan; 629 struct dma_chan *chan = dtc->chan;
617 char *op; 630 char *op;
@@ -626,7 +639,7 @@ static int dmatest_add_threads(struct dmatest_info *info,
626 else 639 else
627 return -EINVAL; 640 return -EINVAL;
628 641
629 for (i = 0; i < info->threads_per_chan; i++) { 642 for (i = 0; i < params->threads_per_chan; i++) {
630 thread = kzalloc(sizeof(struct dmatest_thread), GFP_KERNEL); 643 thread = kzalloc(sizeof(struct dmatest_thread), GFP_KERNEL);
631 if (!thread) { 644 if (!thread) {
632 pr_warning("dmatest: No memory for %s-%s%u\n", 645 pr_warning("dmatest: No memory for %s-%s%u\n",
@@ -696,10 +709,10 @@ static int dmatest_add_channel(struct dmatest_info *info,
696 709
697static bool filter(struct dma_chan *chan, void *param) 710static bool filter(struct dma_chan *chan, void *param)
698{ 711{
699 struct dmatest_info *info = param; 712 struct dmatest_params *params = param;
700 713
701 if (!dmatest_match_channel(info, chan) || 714 if (!dmatest_match_channel(params, chan) ||
702 !dmatest_match_device(info, chan->device)) 715 !dmatest_match_device(params, chan->device))
703 return false; 716 return false;
704 else 717 else
705 return true; 718 return true;
@@ -709,12 +722,13 @@ static int run_threaded_test(struct dmatest_info *info)
709{ 722{
710 dma_cap_mask_t mask; 723 dma_cap_mask_t mask;
711 struct dma_chan *chan; 724 struct dma_chan *chan;
725 struct dmatest_params *params = &info->params;
712 int err = 0; 726 int err = 0;
713 727
714 dma_cap_zero(mask); 728 dma_cap_zero(mask);
715 dma_cap_set(DMA_MEMCPY, mask); 729 dma_cap_set(DMA_MEMCPY, mask);
716 for (;;) { 730 for (;;) {
717 chan = dma_request_channel(mask, filter, info); 731 chan = dma_request_channel(mask, filter, params);
718 if (chan) { 732 if (chan) {
719 err = dmatest_add_channel(info, chan); 733 err = dmatest_add_channel(info, chan);
720 if (err) { 734 if (err) {
@@ -723,8 +737,8 @@ static int run_threaded_test(struct dmatest_info *info)
723 } 737 }
724 } else 738 } else
725 break; /* no more channels available */ 739 break; /* no more channels available */
726 if (info->max_channels && 740 if (params->max_channels &&
727 info->nr_channels >= info->max_channels) 741 info->nr_channels >= params->max_channels)
728 break; /* we have all we need */ 742 break; /* we have all we need */
729 } 743 }
730 return err; 744 return err;
@@ -749,21 +763,22 @@ static void stop_threaded_test(struct dmatest_info *info)
749static int __init dmatest_init(void) 763static int __init dmatest_init(void)
750{ 764{
751 struct dmatest_info *info = &test_info; 765 struct dmatest_info *info = &test_info;
766 struct dmatest_params *params = &info->params;
752 767
753 memset(info, 0, sizeof(*info)); 768 memset(info, 0, sizeof(*info));
754 769
755 INIT_LIST_HEAD(&info->channels); 770 INIT_LIST_HEAD(&info->channels);
756 771
757 /* Set default parameters */ 772 /* Set default parameters */
758 info->buf_size = test_buf_size; 773 params->buf_size = test_buf_size;
759 strlcpy(info->channel, test_channel, sizeof(info->channel)); 774 strlcpy(params->channel, test_channel, sizeof(params->channel));
760 strlcpy(info->device, test_device, sizeof(info->device)); 775 strlcpy(params->device, test_device, sizeof(params->device));
761 info->threads_per_chan = threads_per_chan; 776 params->threads_per_chan = threads_per_chan;
762 info->max_channels = max_channels; 777 params->max_channels = max_channels;
763 info->iterations = iterations; 778 params->iterations = iterations;
764 info->xor_sources = xor_sources; 779 params->xor_sources = xor_sources;
765 info->pq_sources = pq_sources; 780 params->pq_sources = pq_sources;
766 info->timeout = timeout; 781 params->timeout = timeout;
767 782
768 return run_threaded_test(info); 783 return run_threaded_test(info);
769} 784}