@@ -86,6 +86,39 @@ MODULE_PARM_DESC(timeout, "Transfer Timeout in msec (default: 3000), "
86
86
#define PATTERN_OVERWRITE 0x20
87
87
#define PATTERN_COUNT_MASK 0x1f
88
88
89
+ enum dmatest_error_type {
90
+ DMATEST_ET_OK ,
91
+ DMATEST_ET_MAP_SRC ,
92
+ DMATEST_ET_MAP_DST ,
93
+ DMATEST_ET_PREP ,
94
+ DMATEST_ET_SUBMIT ,
95
+ DMATEST_ET_TIMEOUT ,
96
+ DMATEST_ET_DMA_ERROR ,
97
+ DMATEST_ET_DMA_IN_PROGRESS ,
98
+ DMATEST_ET_VERIFY ,
99
+ };
100
+
101
+ struct dmatest_thread_result {
102
+ struct list_head node ;
103
+ unsigned int n ;
104
+ unsigned int src_off ;
105
+ unsigned int dst_off ;
106
+ unsigned int len ;
107
+ enum dmatest_error_type type ;
108
+ union {
109
+ unsigned long data ;
110
+ dma_cookie_t cookie ;
111
+ enum dma_status status ;
112
+ int error ;
113
+ };
114
+ };
115
+
116
+ struct dmatest_result {
117
+ struct list_head node ;
118
+ char * name ;
119
+ struct list_head results ;
120
+ };
121
+
89
122
struct dmatest_info ;
90
123
91
124
struct dmatest_thread {
@@ -146,6 +179,10 @@ struct dmatest_info {
146
179
/* debugfs related stuff */
147
180
struct dentry * root ;
148
181
struct dmatest_params dbgfs_params ;
182
+
183
+ /* Test results */
184
+ struct list_head results ;
185
+ struct mutex results_lock ;
149
186
};
150
187
151
188
static struct dmatest_info test_info ;
@@ -303,6 +340,98 @@ static unsigned int min_odd(unsigned int x, unsigned int y)
303
340
return val % 2 ? val : val - 1 ;
304
341
}
305
342
343
+ static char * thread_result_get (const char * name ,
344
+ struct dmatest_thread_result * tr )
345
+ {
346
+ static const char * const messages [] = {
347
+ [DMATEST_ET_OK ] = "No errors" ,
348
+ [DMATEST_ET_MAP_SRC ] = "src mapping error" ,
349
+ [DMATEST_ET_MAP_DST ] = "dst mapping error" ,
350
+ [DMATEST_ET_PREP ] = "prep error" ,
351
+ [DMATEST_ET_SUBMIT ] = "submit error" ,
352
+ [DMATEST_ET_TIMEOUT ] = "test timed out" ,
353
+ [DMATEST_ET_DMA_ERROR ] =
354
+ "got completion callback (DMA_ERROR)" ,
355
+ [DMATEST_ET_DMA_IN_PROGRESS ] =
356
+ "got completion callback (DMA_IN_PROGRESS)" ,
357
+ [DMATEST_ET_VERIFY ] = "errors" ,
358
+ };
359
+ static char buf [512 ];
360
+
361
+ snprintf (buf , sizeof (buf ) - 1 ,
362
+ "%s: #%u: %s with src_off=0x%x " "dst_off=0x%x len=0x%x (%lu)" ,
363
+ name , tr -> n , messages [tr -> type ], tr -> src_off , tr -> dst_off ,
364
+ tr -> len , tr -> data );
365
+
366
+ return buf ;
367
+ }
368
+
369
+ static int thread_result_add (struct dmatest_info * info ,
370
+ struct dmatest_result * r , enum dmatest_error_type type ,
371
+ unsigned int n , unsigned int src_off , unsigned int dst_off ,
372
+ unsigned int len , unsigned long data )
373
+ {
374
+ struct dmatest_thread_result * tr ;
375
+
376
+ tr = kzalloc (sizeof (* tr ), GFP_KERNEL );
377
+ if (!tr )
378
+ return - ENOMEM ;
379
+
380
+ tr -> type = type ;
381
+ tr -> n = n ;
382
+ tr -> src_off = src_off ;
383
+ tr -> dst_off = dst_off ;
384
+ tr -> len = len ;
385
+ tr -> data = data ;
386
+
387
+ mutex_lock (& info -> results_lock );
388
+ list_add_tail (& tr -> node , & r -> results );
389
+ mutex_unlock (& info -> results_lock );
390
+
391
+ pr_warn ("%s\n" , thread_result_get (r -> name , tr ));
392
+ return 0 ;
393
+ }
394
+
395
+ static void result_free (struct dmatest_info * info , const char * name )
396
+ {
397
+ struct dmatest_result * r , * _r ;
398
+
399
+ mutex_lock (& info -> results_lock );
400
+ list_for_each_entry_safe (r , _r , & info -> results , node ) {
401
+ struct dmatest_thread_result * tr , * _tr ;
402
+
403
+ if (name && strcmp (r -> name , name ))
404
+ continue ;
405
+
406
+ list_for_each_entry_safe (tr , _tr , & r -> results , node ) {
407
+ list_del (& tr -> node );
408
+ kfree (tr );
409
+ }
410
+
411
+ kfree (r -> name );
412
+ list_del (& r -> node );
413
+ kfree (r );
414
+ }
415
+
416
+ mutex_unlock (& info -> results_lock );
417
+ }
418
+
419
+ static struct dmatest_result * result_init (struct dmatest_info * info ,
420
+ const char * name )
421
+ {
422
+ struct dmatest_result * r ;
423
+
424
+ r = kzalloc (sizeof (* r ), GFP_KERNEL );
425
+ if (r ) {
426
+ r -> name = kstrdup (name , GFP_KERNEL );
427
+ INIT_LIST_HEAD (& r -> results );
428
+ mutex_lock (& info -> results_lock );
429
+ list_add_tail (& r -> node , & info -> results );
430
+ mutex_unlock (& info -> results_lock );
431
+ }
432
+ return r ;
433
+ }
434
+
306
435
/*
307
436
* This function repeatedly tests DMA transfers of various lengths and
308
437
* offsets for a given operation type until it is told to exit by
@@ -339,6 +468,7 @@ static int dmatest_func(void *data)
339
468
int src_cnt ;
340
469
int dst_cnt ;
341
470
int i ;
471
+ struct dmatest_result * result ;
342
472
343
473
thread_name = current -> comm ;
344
474
set_freezable ();
@@ -370,6 +500,10 @@ static int dmatest_func(void *data)
370
500
} else
371
501
goto err_thread_type ;
372
502
503
+ result = result_init (info , thread_name );
504
+ if (!result )
505
+ goto err_srcs ;
506
+
373
507
thread -> srcs = kcalloc (src_cnt + 1 , sizeof (u8 * ), GFP_KERNEL );
374
508
if (!thread -> srcs )
375
509
goto err_srcs ;
@@ -443,10 +577,10 @@ static int dmatest_func(void *data)
443
577
ret = dma_mapping_error (dev -> dev , dma_srcs [i ]);
444
578
if (ret ) {
445
579
unmap_src (dev -> dev , dma_srcs , len , i );
446
- pr_warn ( "%s: #%u: mapping error %d with "
447
- "src_off=0x%x len=0x%x\n" ,
448
- thread_name , total_tests - 1 , ret ,
449
- src_off , len );
580
+ thread_result_add ( info , result ,
581
+ DMATEST_ET_MAP_SRC ,
582
+ total_tests , src_off , dst_off ,
583
+ len , ret );
450
584
failed_tests ++ ;
451
585
continue ;
452
586
}
@@ -461,10 +595,10 @@ static int dmatest_func(void *data)
461
595
unmap_src (dev -> dev , dma_srcs , len , src_cnt );
462
596
unmap_dst (dev -> dev , dma_dsts , params -> buf_size ,
463
597
i );
464
- pr_warn ( "%s: #%u: mapping error %d with "
465
- "dst_off=0x%x len=0x%x\n" ,
466
- thread_name , total_tests - 1 , ret ,
467
- dst_off , params -> buf_size );
598
+ thread_result_add ( info , result ,
599
+ DMATEST_ET_MAP_DST ,
600
+ total_tests , src_off , dst_off ,
601
+ len , ret );
468
602
failed_tests ++ ;
469
603
continue ;
470
604
}
@@ -494,10 +628,9 @@ static int dmatest_func(void *data)
494
628
unmap_src (dev -> dev , dma_srcs , len , src_cnt );
495
629
unmap_dst (dev -> dev , dma_dsts , params -> buf_size ,
496
630
dst_cnt );
497
- pr_warning ("%s: #%u: prep error with src_off=0x%x "
498
- "dst_off=0x%x len=0x%x\n" ,
499
- thread_name , total_tests - 1 ,
500
- src_off , dst_off , len );
631
+ thread_result_add (info , result , DMATEST_ET_PREP ,
632
+ total_tests , src_off , dst_off ,
633
+ len , 0 );
501
634
msleep (100 );
502
635
failed_tests ++ ;
503
636
continue ;
@@ -509,10 +642,9 @@ static int dmatest_func(void *data)
509
642
cookie = tx -> tx_submit (tx );
510
643
511
644
if (dma_submit_error (cookie )) {
512
- pr_warning ("%s: #%u: submit error %d with src_off=0x%x "
513
- "dst_off=0x%x len=0x%x\n" ,
514
- thread_name , total_tests - 1 , cookie ,
515
- src_off , dst_off , len );
645
+ thread_result_add (info , result , DMATEST_ET_SUBMIT ,
646
+ total_tests , src_off , dst_off ,
647
+ len , cookie );
516
648
msleep (100 );
517
649
failed_tests ++ ;
518
650
continue ;
@@ -534,15 +666,17 @@ static int dmatest_func(void *data)
534
666
* free it this time?" dancing. For now, just
535
667
* leave it dangling.
536
668
*/
537
- pr_warning ("%s: #%u: test timed out\n" ,
538
- thread_name , total_tests - 1 );
669
+ thread_result_add (info , result , DMATEST_ET_TIMEOUT ,
670
+ total_tests , src_off , dst_off ,
671
+ len , 0 );
539
672
failed_tests ++ ;
540
673
continue ;
541
674
} else if (status != DMA_SUCCESS ) {
542
- pr_warning ("%s: #%u: got completion callback,"
543
- " but status is \'%s\'\n" ,
544
- thread_name , total_tests - 1 ,
545
- status == DMA_ERROR ? "error" : "in progress" );
675
+ enum dmatest_error_type type = (status == DMA_ERROR ) ?
676
+ DMATEST_ET_DMA_ERROR : DMATEST_ET_DMA_IN_PROGRESS ;
677
+ thread_result_add (info , result , type ,
678
+ total_tests , src_off , dst_off ,
679
+ len , status );
546
680
failed_tests ++ ;
547
681
continue ;
548
682
}
@@ -574,16 +708,14 @@ static int dmatest_func(void *data)
574
708
PATTERN_DST , false);
575
709
576
710
if (error_count ) {
577
- pr_warning ("%s: #%u: %u errors with "
578
- "src_off=0x%x dst_off=0x%x len=0x%x\n" ,
579
- thread_name , total_tests - 1 , error_count ,
580
- src_off , dst_off , len );
711
+ thread_result_add (info , result , DMATEST_ET_VERIFY ,
712
+ total_tests , src_off , dst_off ,
713
+ len , error_count );
581
714
failed_tests ++ ;
582
715
} else {
583
- pr_debug ("%s: #%u: No errors with "
584
- "src_off=0x%x dst_off=0x%x len=0x%x\n" ,
585
- thread_name , total_tests - 1 ,
586
- src_off , dst_off , len );
716
+ thread_result_add (info , result , DMATEST_ET_OK ,
717
+ total_tests , src_off , dst_off ,
718
+ len , 0 );
587
719
}
588
720
}
589
721
@@ -807,6 +939,9 @@ static int __restart_threaded_test(struct dmatest_info *info, bool run)
807
939
if (run == false)
808
940
return 0 ;
809
941
942
+ /* Clear results from previous run */
943
+ result_free (info , NULL );
944
+
810
945
/* Copy test parameters */
811
946
memcpy (params , & info -> dbgfs_params , sizeof (* params ));
812
947
@@ -945,6 +1080,35 @@ static const struct file_operations dtf_run_fops = {
945
1080
.llseek = default_llseek ,
946
1081
};
947
1082
1083
+ static int dtf_results_show (struct seq_file * sf , void * data )
1084
+ {
1085
+ struct dmatest_info * info = sf -> private ;
1086
+ struct dmatest_result * result ;
1087
+ struct dmatest_thread_result * tr ;
1088
+
1089
+ mutex_lock (& info -> results_lock );
1090
+ list_for_each_entry (result , & info -> results , node ) {
1091
+ list_for_each_entry (tr , & result -> results , node )
1092
+ seq_printf (sf , "%s\n" ,
1093
+ thread_result_get (result -> name , tr ));
1094
+ }
1095
+
1096
+ mutex_unlock (& info -> results_lock );
1097
+ return 0 ;
1098
+ }
1099
+
1100
+ static int dtf_results_open (struct inode * inode , struct file * file )
1101
+ {
1102
+ return single_open (file , dtf_results_show , inode -> i_private );
1103
+ }
1104
+
1105
+ static const struct file_operations dtf_results_fops = {
1106
+ .open = dtf_results_open ,
1107
+ .read = seq_read ,
1108
+ .llseek = seq_lseek ,
1109
+ .release = single_release ,
1110
+ };
1111
+
948
1112
static int dmatest_register_dbgfs (struct dmatest_info * info )
949
1113
{
950
1114
struct dentry * d ;
@@ -1015,6 +1179,12 @@ static int dmatest_register_dbgfs(struct dmatest_info *info)
1015
1179
if (IS_ERR_OR_NULL (d ))
1016
1180
goto err_node ;
1017
1181
1182
+ /* Results of test in progress */
1183
+ d = debugfs_create_file ("results" , S_IRUGO , info -> root , info ,
1184
+ & dtf_results_fops );
1185
+ if (IS_ERR_OR_NULL (d ))
1186
+ goto err_node ;
1187
+
1018
1188
return 0 ;
1019
1189
1020
1190
err_node :
@@ -1035,6 +1205,9 @@ static int __init dmatest_init(void)
1035
1205
mutex_init (& info -> lock );
1036
1206
INIT_LIST_HEAD (& info -> channels );
1037
1207
1208
+ mutex_init (& info -> results_lock );
1209
+ INIT_LIST_HEAD (& info -> results );
1210
+
1038
1211
/* Set default parameters */
1039
1212
params -> buf_size = test_buf_size ;
1040
1213
strlcpy (params -> channel , test_channel , sizeof (params -> channel ));
@@ -1065,6 +1238,7 @@ static void __exit dmatest_exit(void)
1065
1238
1066
1239
debugfs_remove_recursive (info -> root );
1067
1240
stop_threaded_test (info );
1241
+ result_free (info , NULL );
1068
1242
}
1069
1243
module_exit (dmatest_exit );
1070
1244
0 commit comments