Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

dmatest: add a 'wait' parameter

Allows for scripting test runs by module load / unload. Prevent module
load from returning until 'iterations' (finite) tests have completed, or
cause reads of the 'wait' parameter in sysfs to pause until the tests
are done.

Also killed the local waitqueue since we can just let the thread exit
naturally as long as we hold a reference.

Cc: Nicolas Ferre <nicolas.ferre@atmel.com>
Signed-off-by: Dan Williams <dan.j.williams@intel.com>

+64 -35
+17 -10
Documentation/dmatest.txt
··· 39 39 40 40 Note that running a new test will not stop any in progress test. 41 41 42 - The following command should return actual state of the test. 43 - % cat /sys/kernel/debug/dmatest/run 42 + The following command returns the state of the test. 43 + % cat /sys/module/dmatest/parameters/run 44 44 45 - To wait for test done the user may perform a busy loop that checks the state. 45 + To wait for test completion userpace can poll 'run' until it is false, or use 46 + the wait parameter. Specifying 'wait=1' when loading the module causes module 47 + initialization to pause until a test run has completed, while reading 48 + /sys/module/dmatest/parameters/wait waits for any running test to complete 49 + before returning. For example, the following scripts wait for 42 tests 50 + to complete before exiting. Note that if 'iterations' is set to 'infinite' then 51 + waiting is disabled. 46 52 47 - % while [ $(cat /sys/module/dmatest/parameters/run) = "Y" ] 48 - > do 49 - > echo -n "." 50 - > sleep 1 51 - > done 52 - > echo 53 + Example: 54 + % modprobe dmatest run=1 iterations=42 wait=1 55 + % modprobe -r dmatest 56 + ...or: 57 + % modprobe dmatest run=1 iterations=42 58 + % cat /sys/module/dmatest/parameters/wait 59 + % modprobe -r dmatest 53 60 54 61 Part 3 - When built-in in the kernel... 55 62 ··· 86 79 87 80 Example: 88 81 % dmesg | tail -n 1 89 - dmatest: dma3chan0-copy0: summary 400000 tests, 0 failures iops: 61524 KB/s 246098 (0) 82 + dmatest: dma0chan0-copy0: summary 1 test, 0 failures 1000 iops 100000 KB/s (0) 90 83 91 84 The details of a data miscompare error are also emitted, but do not follow the 92 85 above format.
+47 -25
drivers/dma/dmatest.c
··· 161 161 struct list_head threads; 162 162 }; 163 163 164 + static DECLARE_WAIT_QUEUE_HEAD(thread_wait); 165 + static bool wait; 166 + 167 + static bool is_threaded_test_run(struct dmatest_info *info) 168 + { 169 + struct dmatest_chan *dtc; 170 + 171 + list_for_each_entry(dtc, &info->channels, node) { 172 + struct dmatest_thread *thread; 173 + 174 + list_for_each_entry(thread, &dtc->threads, node) { 175 + if (!thread->done) 176 + return true; 177 + } 178 + } 179 + 180 + return false; 181 + } 182 + 183 + static int dmatest_wait_get(char *val, const struct kernel_param *kp) 184 + { 185 + struct dmatest_info *info = &test_info; 186 + struct dmatest_params *params = &info->params; 187 + 188 + if (params->iterations) 189 + wait_event(thread_wait, !is_threaded_test_run(info)); 190 + wait = true; 191 + return param_get_bool(val, kp); 192 + } 193 + 194 + static struct kernel_param_ops wait_ops = { 195 + .get = dmatest_wait_get, 196 + .set = param_set_bool, 197 + }; 198 + module_param_cb(wait, &wait_ops, &wait, S_IRUGO); 199 + MODULE_PARM_DESC(wait, "Wait for tests to complete (default: false)"); 200 + 164 201 static bool dmatest_match_channel(struct dmatest_params *params, 165 202 struct dma_chan *chan) 166 203 { ··· 697 660 dmaengine_terminate_all(chan); 698 661 699 662 thread->done = true; 700 - 701 - if (params->iterations > 0) 702 - while (!kthread_should_stop()) { 703 - DECLARE_WAIT_QUEUE_HEAD_ONSTACK(wait_dmatest_exit); 704 - interruptible_sleep_on(&wait_dmatest_exit); 705 - } 663 + wake_up(&thread_wait); 706 664 707 665 return ret; 708 666 } ··· 713 681 pr_debug("thread %s exited with status %d\n", 714 682 thread->task->comm, ret); 715 683 list_del(&thread->node); 684 + put_task_struct(thread->task); 716 685 kfree(thread); 717 686 } 718 687 ··· 752 719 thread->chan = dtc->chan; 753 720 thread->type = type; 754 721 smp_wmb(); 755 - thread->task = kthread_run(dmatest_func, thread, "%s-%s%u", 722 + thread->task = kthread_create(dmatest_func, thread, "%s-%s%u", 756 723 dma_chan_name(chan), op, i); 757 724 if (IS_ERR(thread->task)) { 758 - pr_warn("Failed to run thread %s-%s%u\n", 725 + pr_warn("Failed to create thread %s-%s%u\n", 759 726 dma_chan_name(chan), op, i); 760 727 kfree(thread); 761 728 break; 762 729 } 763 730 764 731 /* srcbuf and dstbuf are allocated by the thread itself */ 765 - 732 + get_task_struct(thread->task); 766 733 list_add_tail(&thread->node, &dtc->threads); 734 + wake_up_process(thread->task); 767 735 } 768 736 769 737 return i; ··· 897 863 run_threaded_test(info); 898 864 } 899 865 900 - static bool is_threaded_test_run(struct dmatest_info *info) 901 - { 902 - struct dmatest_chan *dtc; 903 - 904 - list_for_each_entry(dtc, &info->channels, node) { 905 - struct dmatest_thread *thread; 906 - 907 - list_for_each_entry(thread, &dtc->threads, node) { 908 - if (!thread->done) 909 - return true; 910 - } 911 - } 912 - 913 - return false; 914 - } 915 - 916 866 static int dmatest_run_get(char *val, const struct kernel_param *kp) 917 867 { 918 868 struct dmatest_info *info = &test_info; ··· 938 920 static int __init dmatest_init(void) 939 921 { 940 922 struct dmatest_info *info = &test_info; 923 + struct dmatest_params *params = &info->params; 941 924 942 925 if (dmatest_run) { 943 926 mutex_lock(&info->lock); 944 927 run_threaded_test(info); 945 928 mutex_unlock(&info->lock); 946 929 } 930 + 931 + if (params->iterations && wait) 932 + wait_event(thread_wait, !is_threaded_test_run(info)); 947 933 948 934 /* module parameters are stable, inittime tests are started, 949 935 * let userspace take over 'run' control