22 * DMA Engine test module
33 *
44 * Copyright (C) 2007 Atmel Corporation
5+ * Copyright (C) 2013 Intel Corporation
56 *
67 * This program is free software; you can redistribute it and/or modify
78 * it under the terms of the GNU General Public License version 2 as
1819#include <linux/random.h>
1920#include <linux/slab.h>
2021#include <linux/wait.h>
22+ #include <linux/ctype.h>
23+ #include <linux/debugfs.h>
24+ #include <linux/uaccess.h>
25+ #include <linux/seq_file.h>
2126
2227static unsigned int test_buf_size = 16384 ;
2328module_param (test_buf_size , uint , S_IRUGO );
@@ -123,6 +128,7 @@ struct dmatest_params {
123128/**
124129 * struct dmatest_info - test information.
125130 * @params: test parameters
131+ * @lock: access protection to the fields of this structure
126132 */
127133struct dmatest_info {
128134 /* Test parameters */
@@ -131,6 +137,11 @@ struct dmatest_info {
131137 /* Internal state */
132138 struct list_head channels ;
133139 unsigned int nr_channels ;
140+ struct mutex lock ;
141+
142+ /* debugfs related stuff */
143+ struct dentry * root ;
144+ struct dmatest_params dbgfs_params ;
134145};
135146
136147static struct dmatest_info test_info ;
@@ -718,7 +729,7 @@ static bool filter(struct dma_chan *chan, void *param)
718729 return true;
719730}
720731
721- static int run_threaded_test (struct dmatest_info * info )
732+ static int __run_threaded_test (struct dmatest_info * info )
722733{
723734 dma_cap_mask_t mask ;
724735 struct dma_chan * chan ;
@@ -744,7 +755,19 @@ static int run_threaded_test(struct dmatest_info *info)
744755 return err ;
745756}
746757
747- static void stop_threaded_test (struct dmatest_info * info )
758+ #ifndef MODULE
759+ static int run_threaded_test (struct dmatest_info * info )
760+ {
761+ int ret ;
762+
763+ mutex_lock (& info -> lock );
764+ ret = __run_threaded_test (info );
765+ mutex_unlock (& info -> lock );
766+ return ret ;
767+ }
768+ #endif
769+
770+ static void __stop_threaded_test (struct dmatest_info * info )
748771{
749772 struct dmatest_chan * dtc , * _dtc ;
750773 struct dma_chan * chan ;
@@ -760,13 +783,234 @@ static void stop_threaded_test(struct dmatest_info *info)
760783 info -> nr_channels = 0 ;
761784}
762785
786+ static void stop_threaded_test (struct dmatest_info * info )
787+ {
788+ mutex_lock (& info -> lock );
789+ __stop_threaded_test (info );
790+ mutex_unlock (& info -> lock );
791+ }
792+
793+ static int __restart_threaded_test (struct dmatest_info * info , bool run )
794+ {
795+ struct dmatest_params * params = & info -> params ;
796+ int ret ;
797+
798+ /* Stop any running test first */
799+ __stop_threaded_test (info );
800+
801+ if (run == false)
802+ return 0 ;
803+
804+ /* Copy test parameters */
805+ memcpy (params , & info -> dbgfs_params , sizeof (* params ));
806+
807+ /* Run test with new parameters */
808+ ret = __run_threaded_test (info );
809+ if (ret ) {
810+ __stop_threaded_test (info );
811+ pr_err ("dmatest: Can't run test\n" );
812+ }
813+
814+ return ret ;
815+ }
816+
817+ static ssize_t dtf_write_string (void * to , size_t available , loff_t * ppos ,
818+ const void __user * from , size_t count )
819+ {
820+ char tmp [20 ];
821+ ssize_t len ;
822+
823+ len = simple_write_to_buffer (tmp , sizeof (tmp ) - 1 , ppos , from , count );
824+ if (len >= 0 ) {
825+ tmp [len ] = '\0' ;
826+ strlcpy (to , strim (tmp ), available );
827+ }
828+
829+ return len ;
830+ }
831+
832+ static ssize_t dtf_read_channel (struct file * file , char __user * buf ,
833+ size_t count , loff_t * ppos )
834+ {
835+ struct dmatest_info * info = file -> private_data ;
836+ return simple_read_from_buffer (buf , count , ppos ,
837+ info -> dbgfs_params .channel ,
838+ strlen (info -> dbgfs_params .channel ));
839+ }
840+
841+ static ssize_t dtf_write_channel (struct file * file , const char __user * buf ,
842+ size_t size , loff_t * ppos )
843+ {
844+ struct dmatest_info * info = file -> private_data ;
845+ return dtf_write_string (info -> dbgfs_params .channel ,
846+ sizeof (info -> dbgfs_params .channel ),
847+ ppos , buf , size );
848+ }
849+
850+ static const struct file_operations dtf_channel_fops = {
851+ .read = dtf_read_channel ,
852+ .write = dtf_write_channel ,
853+ .open = simple_open ,
854+ .llseek = default_llseek ,
855+ };
856+
857+ static ssize_t dtf_read_device (struct file * file , char __user * buf ,
858+ size_t count , loff_t * ppos )
859+ {
860+ struct dmatest_info * info = file -> private_data ;
861+ return simple_read_from_buffer (buf , count , ppos ,
862+ info -> dbgfs_params .device ,
863+ strlen (info -> dbgfs_params .device ));
864+ }
865+
866+ static ssize_t dtf_write_device (struct file * file , const char __user * buf ,
867+ size_t size , loff_t * ppos )
868+ {
869+ struct dmatest_info * info = file -> private_data ;
870+ return dtf_write_string (info -> dbgfs_params .device ,
871+ sizeof (info -> dbgfs_params .device ),
872+ ppos , buf , size );
873+ }
874+
875+ static const struct file_operations dtf_device_fops = {
876+ .read = dtf_read_device ,
877+ .write = dtf_write_device ,
878+ .open = simple_open ,
879+ .llseek = default_llseek ,
880+ };
881+
882+ static ssize_t dtf_read_run (struct file * file , char __user * user_buf ,
883+ size_t count , loff_t * ppos )
884+ {
885+ struct dmatest_info * info = file -> private_data ;
886+ char buf [3 ];
887+
888+ mutex_lock (& info -> lock );
889+ if (info -> nr_channels )
890+ buf [0 ] = 'Y' ;
891+ else
892+ buf [0 ] = 'N' ;
893+ mutex_unlock (& info -> lock );
894+ buf [1 ] = '\n' ;
895+ buf [2 ] = 0x00 ;
896+ return simple_read_from_buffer (user_buf , count , ppos , buf , 2 );
897+ }
898+
899+ static ssize_t dtf_write_run (struct file * file , const char __user * user_buf ,
900+ size_t count , loff_t * ppos )
901+ {
902+ struct dmatest_info * info = file -> private_data ;
903+ char buf [16 ];
904+ bool bv ;
905+ int ret = 0 ;
906+
907+ if (copy_from_user (buf , user_buf , min (count , (sizeof (buf ) - 1 ))))
908+ return - EFAULT ;
909+
910+ if (strtobool (buf , & bv ) == 0 ) {
911+ mutex_lock (& info -> lock );
912+ ret = __restart_threaded_test (info , bv );
913+ mutex_unlock (& info -> lock );
914+ }
915+
916+ return ret ? ret : count ;
917+ }
918+
919+ static const struct file_operations dtf_run_fops = {
920+ .read = dtf_read_run ,
921+ .write = dtf_write_run ,
922+ .open = simple_open ,
923+ .llseek = default_llseek ,
924+ };
925+
926+ static int dmatest_register_dbgfs (struct dmatest_info * info )
927+ {
928+ struct dentry * d ;
929+ struct dmatest_params * params = & info -> dbgfs_params ;
930+ int ret = - ENOMEM ;
931+
932+ d = debugfs_create_dir ("dmatest" , NULL );
933+ if (IS_ERR (d ))
934+ return PTR_ERR (d );
935+ if (!d )
936+ goto err_root ;
937+
938+ info -> root = d ;
939+
940+ /* Copy initial values */
941+ memcpy (params , & info -> params , sizeof (* params ));
942+
943+ /* Test parameters */
944+
945+ d = debugfs_create_u32 ("test_buf_size" , S_IWUSR | S_IRUGO , info -> root ,
946+ (u32 * )& params -> buf_size );
947+ if (IS_ERR_OR_NULL (d ))
948+ goto err_node ;
949+
950+ d = debugfs_create_file ("channel" , S_IRUGO | S_IWUSR , info -> root ,
951+ info , & dtf_channel_fops );
952+ if (IS_ERR_OR_NULL (d ))
953+ goto err_node ;
954+
955+ d = debugfs_create_file ("device" , S_IRUGO | S_IWUSR , info -> root ,
956+ info , & dtf_device_fops );
957+ if (IS_ERR_OR_NULL (d ))
958+ goto err_node ;
959+
960+ d = debugfs_create_u32 ("threads_per_chan" , S_IWUSR | S_IRUGO , info -> root ,
961+ (u32 * )& params -> threads_per_chan );
962+ if (IS_ERR_OR_NULL (d ))
963+ goto err_node ;
964+
965+ d = debugfs_create_u32 ("max_channels" , S_IWUSR | S_IRUGO , info -> root ,
966+ (u32 * )& params -> max_channels );
967+ if (IS_ERR_OR_NULL (d ))
968+ goto err_node ;
969+
970+ d = debugfs_create_u32 ("iterations" , S_IWUSR | S_IRUGO , info -> root ,
971+ (u32 * )& params -> iterations );
972+ if (IS_ERR_OR_NULL (d ))
973+ goto err_node ;
974+
975+ d = debugfs_create_u32 ("xor_sources" , S_IWUSR | S_IRUGO , info -> root ,
976+ (u32 * )& params -> xor_sources );
977+ if (IS_ERR_OR_NULL (d ))
978+ goto err_node ;
979+
980+ d = debugfs_create_u32 ("pq_sources" , S_IWUSR | S_IRUGO , info -> root ,
981+ (u32 * )& params -> pq_sources );
982+ if (IS_ERR_OR_NULL (d ))
983+ goto err_node ;
984+
985+ d = debugfs_create_u32 ("timeout" , S_IWUSR | S_IRUGO , info -> root ,
986+ (u32 * )& params -> timeout );
987+ if (IS_ERR_OR_NULL (d ))
988+ goto err_node ;
989+
990+ /* Run or stop threaded test */
991+ d = debugfs_create_file ("run" , S_IWUSR | S_IRUGO , info -> root ,
992+ info , & dtf_run_fops );
993+ if (IS_ERR_OR_NULL (d ))
994+ goto err_node ;
995+
996+ return 0 ;
997+
998+ err_node :
999+ debugfs_remove_recursive (info -> root );
1000+ err_root :
1001+ pr_err ("dmatest: Failed to initialize debugfs\n" );
1002+ return ret ;
1003+ }
1004+
7631005static int __init dmatest_init (void )
7641006{
7651007 struct dmatest_info * info = & test_info ;
7661008 struct dmatest_params * params = & info -> params ;
1009+ int ret ;
7671010
7681011 memset (info , 0 , sizeof (* info ));
7691012
1013+ mutex_init (& info -> lock );
7701014 INIT_LIST_HEAD (& info -> channels );
7711015
7721016 /* Set default parameters */
@@ -780,7 +1024,15 @@ static int __init dmatest_init(void)
7801024 params -> pq_sources = pq_sources ;
7811025 params -> timeout = timeout ;
7821026
1027+ ret = dmatest_register_dbgfs (info );
1028+ if (ret )
1029+ return ret ;
1030+
1031+ #ifdef MODULE
1032+ return 0 ;
1033+ #else
7831034 return run_threaded_test (info );
1035+ #endif
7841036}
7851037/* when compiled-in wait for drivers to load first */
7861038late_initcall (dmatest_init );
@@ -789,6 +1041,7 @@ static void __exit dmatest_exit(void)
7891041{
7901042 struct dmatest_info * info = & test_info ;
7911043
1044+ debugfs_remove_recursive (info -> root );
7921045 stop_threaded_test (info );
7931046}
7941047module_exit (dmatest_exit );
0 commit comments