dmatest.c revision 851b7e16a07dfda6178d4e35fea9a9e3eb8954ae
14a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen/* 24a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen * DMA Engine test module 34a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen * 44a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen * Copyright (C) 2007 Atmel Corporation 5851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko * Copyright (C) 2013 Intel Corporation 64a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen * 74a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen * This program is free software; you can redistribute it and/or modify 84a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen * it under the terms of the GNU General Public License version 2 as 94a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen * published by the Free Software Foundation. 104a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen */ 114a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen#include <linux/delay.h> 12b7f080cfe223b3b7424872639d153695615a9255Alexey Dobriyan#include <linux/dma-mapping.h> 134a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen#include <linux/dmaengine.h> 14981ed70d8e4faf3689dbf3c48868a31d5b004d7aGuennadi Liakhovetski#include <linux/freezer.h> 154a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen#include <linux/init.h> 164a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen#include <linux/kthread.h> 174a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen#include <linux/module.h> 184a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen#include <linux/moduleparam.h> 194a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen#include <linux/random.h> 205a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h> 214a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen#include <linux/wait.h> 22851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko#include <linux/ctype.h> 23851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko#include <linux/debugfs.h> 24851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko#include <linux/uaccess.h> 25851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko#include <linux/seq_file.h> 264a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 274a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoenstatic unsigned int test_buf_size = 16384; 284a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoenmodule_param(test_buf_size, uint, S_IRUGO); 294a776f0aa922a552460192c07b56f4fe9cd82632Haavard SkinnemoenMODULE_PARM_DESC(test_buf_size, "Size of the memcpy test buffer"); 304a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 3106190d8415219d9eef7d8f04b52a109e34575a76Kay Sieversstatic char test_channel[20]; 324a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoenmodule_param_string(channel, test_channel, sizeof(test_channel), S_IRUGO); 334a776f0aa922a552460192c07b56f4fe9cd82632Haavard SkinnemoenMODULE_PARM_DESC(channel, "Bus ID of the channel to test (default: any)"); 344a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 3506190d8415219d9eef7d8f04b52a109e34575a76Kay Sieversstatic char test_device[20]; 364a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoenmodule_param_string(device, test_device, sizeof(test_device), S_IRUGO); 374a776f0aa922a552460192c07b56f4fe9cd82632Haavard SkinnemoenMODULE_PARM_DESC(device, "Bus ID of the DMA Engine to test (default: any)"); 384a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 394a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoenstatic unsigned int threads_per_chan = 1; 404a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoenmodule_param(threads_per_chan, uint, S_IRUGO); 414a776f0aa922a552460192c07b56f4fe9cd82632Haavard SkinnemoenMODULE_PARM_DESC(threads_per_chan, 424a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen "Number of threads to start per channel (default: 1)"); 434a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 444a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoenstatic unsigned int max_channels; 454a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoenmodule_param(max_channels, uint, S_IRUGO); 4633df8ca068123457db56c316946a3c0e4ef787d6Dan WilliamsMODULE_PARM_DESC(max_channels, 474a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen "Maximum number of channels to use (default: all)"); 484a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 490a2ff57d6fba92842272889b4bca447344cd9d36Nicolas Ferrestatic unsigned int iterations; 500a2ff57d6fba92842272889b4bca447344cd9d36Nicolas Ferremodule_param(iterations, uint, S_IRUGO); 510a2ff57d6fba92842272889b4bca447344cd9d36Nicolas FerreMODULE_PARM_DESC(iterations, 520a2ff57d6fba92842272889b4bca447344cd9d36Nicolas Ferre "Iterations before stopping test (default: infinite)"); 530a2ff57d6fba92842272889b4bca447344cd9d36Nicolas Ferre 54b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williamsstatic unsigned int xor_sources = 3; 55b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williamsmodule_param(xor_sources, uint, S_IRUGO); 56b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan WilliamsMODULE_PARM_DESC(xor_sources, 57b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams "Number of xor source buffers (default: 3)"); 58b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams 5958691d64c44ae41ddf098ecb31e9a994026e3cffDan Williamsstatic unsigned int pq_sources = 3; 6058691d64c44ae41ddf098ecb31e9a994026e3cffDan Williamsmodule_param(pq_sources, uint, S_IRUGO); 6158691d64c44ae41ddf098ecb31e9a994026e3cffDan WilliamsMODULE_PARM_DESC(pq_sources, 6258691d64c44ae41ddf098ecb31e9a994026e3cffDan Williams "Number of p+q source buffers (default: 3)"); 6358691d64c44ae41ddf098ecb31e9a994026e3cffDan Williams 64d42efe6bfb4eed8314c8ce3547f21954a4140399Viresh Kumarstatic int timeout = 3000; 65d42efe6bfb4eed8314c8ce3547f21954a4140399Viresh Kumarmodule_param(timeout, uint, S_IRUGO); 6685ee7a1d39d75d23d21f3871f6dc9b87d572747aJoe PerchesMODULE_PARM_DESC(timeout, "Transfer Timeout in msec (default: 3000), " 6785ee7a1d39d75d23d21f3871f6dc9b87d572747aJoe Perches "Pass -1 for infinite timeout"); 68d42efe6bfb4eed8314c8ce3547f21954a4140399Viresh Kumar 694a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen/* 704a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen * Initialization patterns. All bytes in the source buffer has bit 7 714a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen * set, all bytes in the destination buffer has bit 7 cleared. 724a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen * 734a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen * Bit 6 is set for all bytes which are to be copied by the DMA 744a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen * engine. Bit 5 is set for all bytes which are to be overwritten by 754a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen * the DMA engine. 764a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen * 774a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen * The remaining bits are the inverse of a counter which increments by 784a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen * one for each byte address. 794a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen */ 804a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen#define PATTERN_SRC 0x80 814a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen#define PATTERN_DST 0x00 824a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen#define PATTERN_COPY 0x40 834a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen#define PATTERN_OVERWRITE 0x20 844a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen#define PATTERN_COUNT_MASK 0x1f 854a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 86e03e93a976d0f0da63f02fd3384c4b99cac8d715Andy Shevchenkostruct dmatest_info; 87e03e93a976d0f0da63f02fd3384c4b99cac8d715Andy Shevchenko 884a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoenstruct dmatest_thread { 894a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen struct list_head node; 90e03e93a976d0f0da63f02fd3384c4b99cac8d715Andy Shevchenko struct dmatest_info *info; 914a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen struct task_struct *task; 924a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen struct dma_chan *chan; 93b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams u8 **srcs; 94b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams u8 **dsts; 95b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams enum dma_transaction_type type; 964a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen}; 974a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 984a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoenstruct dmatest_chan { 994a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen struct list_head node; 1004a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen struct dma_chan *chan; 1014a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen struct list_head threads; 1024a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen}; 1034a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 104e03e93a976d0f0da63f02fd3384c4b99cac8d715Andy Shevchenko/** 10515b8a8ea1a87313f1b46ea878c65942fd52147edAndy Shevchenko * struct dmatest_params - test parameters. 106e03e93a976d0f0da63f02fd3384c4b99cac8d715Andy Shevchenko * @buf_size: size of the memcpy test buffer 107e03e93a976d0f0da63f02fd3384c4b99cac8d715Andy Shevchenko * @channel: bus ID of the channel to test 108e03e93a976d0f0da63f02fd3384c4b99cac8d715Andy Shevchenko * @device: bus ID of the DMA Engine to test 109e03e93a976d0f0da63f02fd3384c4b99cac8d715Andy Shevchenko * @threads_per_chan: number of threads to start per channel 110e03e93a976d0f0da63f02fd3384c4b99cac8d715Andy Shevchenko * @max_channels: maximum number of channels to use 111e03e93a976d0f0da63f02fd3384c4b99cac8d715Andy Shevchenko * @iterations: iterations before stopping test 112e03e93a976d0f0da63f02fd3384c4b99cac8d715Andy Shevchenko * @xor_sources: number of xor source buffers 113e03e93a976d0f0da63f02fd3384c4b99cac8d715Andy Shevchenko * @pq_sources: number of p+q source buffers 114e03e93a976d0f0da63f02fd3384c4b99cac8d715Andy Shevchenko * @timeout: transfer timeout in msec, -1 for infinite timeout 115e03e93a976d0f0da63f02fd3384c4b99cac8d715Andy Shevchenko */ 11615b8a8ea1a87313f1b46ea878c65942fd52147edAndy Shevchenkostruct dmatest_params { 117e03e93a976d0f0da63f02fd3384c4b99cac8d715Andy Shevchenko unsigned int buf_size; 118e03e93a976d0f0da63f02fd3384c4b99cac8d715Andy Shevchenko char channel[20]; 119e03e93a976d0f0da63f02fd3384c4b99cac8d715Andy Shevchenko char device[20]; 120e03e93a976d0f0da63f02fd3384c4b99cac8d715Andy Shevchenko unsigned int threads_per_chan; 121e03e93a976d0f0da63f02fd3384c4b99cac8d715Andy Shevchenko unsigned int max_channels; 122e03e93a976d0f0da63f02fd3384c4b99cac8d715Andy Shevchenko unsigned int iterations; 123e03e93a976d0f0da63f02fd3384c4b99cac8d715Andy Shevchenko unsigned int xor_sources; 124e03e93a976d0f0da63f02fd3384c4b99cac8d715Andy Shevchenko unsigned int pq_sources; 125e03e93a976d0f0da63f02fd3384c4b99cac8d715Andy Shevchenko int timeout; 12615b8a8ea1a87313f1b46ea878c65942fd52147edAndy Shevchenko}; 12715b8a8ea1a87313f1b46ea878c65942fd52147edAndy Shevchenko 12815b8a8ea1a87313f1b46ea878c65942fd52147edAndy Shevchenko/** 12915b8a8ea1a87313f1b46ea878c65942fd52147edAndy Shevchenko * struct dmatest_info - test information. 13015b8a8ea1a87313f1b46ea878c65942fd52147edAndy Shevchenko * @params: test parameters 131851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko * @lock: access protection to the fields of this structure 13215b8a8ea1a87313f1b46ea878c65942fd52147edAndy Shevchenko */ 13315b8a8ea1a87313f1b46ea878c65942fd52147edAndy Shevchenkostruct dmatest_info { 13415b8a8ea1a87313f1b46ea878c65942fd52147edAndy Shevchenko /* Test parameters */ 13515b8a8ea1a87313f1b46ea878c65942fd52147edAndy Shevchenko struct dmatest_params params; 136838cc704ce5c8ab2a6d64d1324e37e040fcae3d8Andy Shevchenko 137838cc704ce5c8ab2a6d64d1324e37e040fcae3d8Andy Shevchenko /* Internal state */ 138838cc704ce5c8ab2a6d64d1324e37e040fcae3d8Andy Shevchenko struct list_head channels; 139838cc704ce5c8ab2a6d64d1324e37e040fcae3d8Andy Shevchenko unsigned int nr_channels; 140851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko struct mutex lock; 141851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko 142851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko /* debugfs related stuff */ 143851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko struct dentry *root; 144851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko struct dmatest_params dbgfs_params; 145e03e93a976d0f0da63f02fd3384c4b99cac8d715Andy Shevchenko}; 146e03e93a976d0f0da63f02fd3384c4b99cac8d715Andy Shevchenko 147e03e93a976d0f0da63f02fd3384c4b99cac8d715Andy Shevchenkostatic struct dmatest_info test_info; 148e03e93a976d0f0da63f02fd3384c4b99cac8d715Andy Shevchenko 14915b8a8ea1a87313f1b46ea878c65942fd52147edAndy Shevchenkostatic bool dmatest_match_channel(struct dmatest_params *params, 150e03e93a976d0f0da63f02fd3384c4b99cac8d715Andy Shevchenko struct dma_chan *chan) 1514a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen{ 15215b8a8ea1a87313f1b46ea878c65942fd52147edAndy Shevchenko if (params->channel[0] == '\0') 1534a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen return true; 15415b8a8ea1a87313f1b46ea878c65942fd52147edAndy Shevchenko return strcmp(dma_chan_name(chan), params->channel) == 0; 1554a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen} 1564a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 15715b8a8ea1a87313f1b46ea878c65942fd52147edAndy Shevchenkostatic bool dmatest_match_device(struct dmatest_params *params, 158e03e93a976d0f0da63f02fd3384c4b99cac8d715Andy Shevchenko struct dma_device *device) 1594a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen{ 16015b8a8ea1a87313f1b46ea878c65942fd52147edAndy Shevchenko if (params->device[0] == '\0') 1614a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen return true; 16215b8a8ea1a87313f1b46ea878c65942fd52147edAndy Shevchenko return strcmp(dev_name(device->dev), params->device) == 0; 1634a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen} 1644a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 1654a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoenstatic unsigned long dmatest_random(void) 1664a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen{ 1674a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen unsigned long buf; 1684a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 1694a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen get_random_bytes(&buf, sizeof(buf)); 1704a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen return buf; 1714a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen} 1724a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 173e03e93a976d0f0da63f02fd3384c4b99cac8d715Andy Shevchenkostatic void dmatest_init_srcs(u8 **bufs, unsigned int start, unsigned int len, 174e03e93a976d0f0da63f02fd3384c4b99cac8d715Andy Shevchenko unsigned int buf_size) 1754a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen{ 1764a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen unsigned int i; 177b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams u8 *buf; 178b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams 179b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams for (; (buf = *bufs); bufs++) { 180b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams for (i = 0; i < start; i++) 181b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams buf[i] = PATTERN_SRC | (~i & PATTERN_COUNT_MASK); 182b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams for ( ; i < start + len; i++) 183b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams buf[i] = PATTERN_SRC | PATTERN_COPY 184c019894efc9c9ba5939948caa78c133b1ec8ae63Joe Perches | (~i & PATTERN_COUNT_MASK); 185e03e93a976d0f0da63f02fd3384c4b99cac8d715Andy Shevchenko for ( ; i < buf_size; i++) 186b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams buf[i] = PATTERN_SRC | (~i & PATTERN_COUNT_MASK); 187b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams buf++; 188b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams } 1894a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen} 1904a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 191e03e93a976d0f0da63f02fd3384c4b99cac8d715Andy Shevchenkostatic void dmatest_init_dsts(u8 **bufs, unsigned int start, unsigned int len, 192e03e93a976d0f0da63f02fd3384c4b99cac8d715Andy Shevchenko unsigned int buf_size) 1934a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen{ 1944a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen unsigned int i; 195b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams u8 *buf; 196b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams 197b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams for (; (buf = *bufs); bufs++) { 198b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams for (i = 0; i < start; i++) 199b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams buf[i] = PATTERN_DST | (~i & PATTERN_COUNT_MASK); 200b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams for ( ; i < start + len; i++) 201b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams buf[i] = PATTERN_DST | PATTERN_OVERWRITE 202b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams | (~i & PATTERN_COUNT_MASK); 203e03e93a976d0f0da63f02fd3384c4b99cac8d715Andy Shevchenko for ( ; i < buf_size; i++) 204b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams buf[i] = PATTERN_DST | (~i & PATTERN_COUNT_MASK); 205b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams } 2064a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen} 2074a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 2084a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoenstatic void dmatest_mismatch(u8 actual, u8 pattern, unsigned int index, 2094a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen unsigned int counter, bool is_srcbuf) 2104a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen{ 2114a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen u8 diff = actual ^ pattern; 2124a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen u8 expected = pattern | (~counter & PATTERN_COUNT_MASK); 2134a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen const char *thread_name = current->comm; 2144a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 2154a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen if (is_srcbuf) 2164a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen pr_warning("%s: srcbuf[0x%x] overwritten!" 2174a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen " Expected %02x, got %02x\n", 2184a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen thread_name, index, expected, actual); 2194a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen else if ((pattern & PATTERN_COPY) 2204a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen && (diff & (PATTERN_COPY | PATTERN_OVERWRITE))) 2214a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen pr_warning("%s: dstbuf[0x%x] not copied!" 2224a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen " Expected %02x, got %02x\n", 2234a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen thread_name, index, expected, actual); 2244a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen else if (diff & PATTERN_SRC) 2254a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen pr_warning("%s: dstbuf[0x%x] was copied!" 2264a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen " Expected %02x, got %02x\n", 2274a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen thread_name, index, expected, actual); 2284a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen else 2294a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen pr_warning("%s: dstbuf[0x%x] mismatch!" 2304a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen " Expected %02x, got %02x\n", 2314a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen thread_name, index, expected, actual); 2324a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen} 2334a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 234b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williamsstatic unsigned int dmatest_verify(u8 **bufs, unsigned int start, 2354a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen unsigned int end, unsigned int counter, u8 pattern, 2364a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen bool is_srcbuf) 2374a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen{ 2384a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen unsigned int i; 2394a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen unsigned int error_count = 0; 2404a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen u8 actual; 241b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams u8 expected; 242b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams u8 *buf; 243b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams unsigned int counter_orig = counter; 244b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams 245b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams for (; (buf = *bufs); bufs++) { 246b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams counter = counter_orig; 247b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams for (i = start; i < end; i++) { 248b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams actual = buf[i]; 249b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams expected = pattern | (~counter & PATTERN_COUNT_MASK); 250b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams if (actual != expected) { 251b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams if (error_count < 32) 252b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams dmatest_mismatch(actual, pattern, i, 253b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams counter, is_srcbuf); 254b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams error_count++; 255b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams } 256b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams counter++; 2574a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen } 2584a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen } 2594a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 2604a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen if (error_count > 32) 2614a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen pr_warning("%s: %u errors suppressed\n", 2624a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen current->comm, error_count - 32); 2634a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 2644a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen return error_count; 2654a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen} 2664a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 267adfa543e7314b36ac55a40019977de6e47946dd7Tejun Heo/* poor man's completion - we want to use wait_event_freezable() on it */ 268adfa543e7314b36ac55a40019977de6e47946dd7Tejun Heostruct dmatest_done { 269adfa543e7314b36ac55a40019977de6e47946dd7Tejun Heo bool done; 270adfa543e7314b36ac55a40019977de6e47946dd7Tejun Heo wait_queue_head_t *wait; 271adfa543e7314b36ac55a40019977de6e47946dd7Tejun Heo}; 272adfa543e7314b36ac55a40019977de6e47946dd7Tejun Heo 273adfa543e7314b36ac55a40019977de6e47946dd7Tejun Heostatic void dmatest_callback(void *arg) 274e44e0aa3cfa97cddff01704751a4b25151830c72Dan Williams{ 275adfa543e7314b36ac55a40019977de6e47946dd7Tejun Heo struct dmatest_done *done = arg; 276adfa543e7314b36ac55a40019977de6e47946dd7Tejun Heo 277adfa543e7314b36ac55a40019977de6e47946dd7Tejun Heo done->done = true; 278adfa543e7314b36ac55a40019977de6e47946dd7Tejun Heo wake_up_all(done->wait); 279e44e0aa3cfa97cddff01704751a4b25151830c72Dan Williams} 280e44e0aa3cfa97cddff01704751a4b25151830c72Dan Williams 281632fd28326c0cc7be9c51ea0d76d8bec39a695e9Andy Shevchenkostatic inline void unmap_src(struct device *dev, dma_addr_t *addr, size_t len, 282632fd28326c0cc7be9c51ea0d76d8bec39a695e9Andy Shevchenko unsigned int count) 283632fd28326c0cc7be9c51ea0d76d8bec39a695e9Andy Shevchenko{ 284632fd28326c0cc7be9c51ea0d76d8bec39a695e9Andy Shevchenko while (count--) 285632fd28326c0cc7be9c51ea0d76d8bec39a695e9Andy Shevchenko dma_unmap_single(dev, addr[count], len, DMA_TO_DEVICE); 286632fd28326c0cc7be9c51ea0d76d8bec39a695e9Andy Shevchenko} 287632fd28326c0cc7be9c51ea0d76d8bec39a695e9Andy Shevchenko 288632fd28326c0cc7be9c51ea0d76d8bec39a695e9Andy Shevchenkostatic inline void unmap_dst(struct device *dev, dma_addr_t *addr, size_t len, 289632fd28326c0cc7be9c51ea0d76d8bec39a695e9Andy Shevchenko unsigned int count) 290632fd28326c0cc7be9c51ea0d76d8bec39a695e9Andy Shevchenko{ 291632fd28326c0cc7be9c51ea0d76d8bec39a695e9Andy Shevchenko while (count--) 292632fd28326c0cc7be9c51ea0d76d8bec39a695e9Andy Shevchenko dma_unmap_single(dev, addr[count], len, DMA_BIDIRECTIONAL); 293632fd28326c0cc7be9c51ea0d76d8bec39a695e9Andy Shevchenko} 294632fd28326c0cc7be9c51ea0d76d8bec39a695e9Andy Shevchenko 2958be9e32b310cd8c4302991c8ff6692689c7d9d76Akinobu Mitastatic unsigned int min_odd(unsigned int x, unsigned int y) 2968be9e32b310cd8c4302991c8ff6692689c7d9d76Akinobu Mita{ 2978be9e32b310cd8c4302991c8ff6692689c7d9d76Akinobu Mita unsigned int val = min(x, y); 2988be9e32b310cd8c4302991c8ff6692689c7d9d76Akinobu Mita 2998be9e32b310cd8c4302991c8ff6692689c7d9d76Akinobu Mita return val % 2 ? val : val - 1; 3008be9e32b310cd8c4302991c8ff6692689c7d9d76Akinobu Mita} 3018be9e32b310cd8c4302991c8ff6692689c7d9d76Akinobu Mita 3024a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen/* 3034a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen * This function repeatedly tests DMA transfers of various lengths and 304b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams * offsets for a given operation type until it is told to exit by 305b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams * kthread_stop(). There may be multiple threads running this function 306b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams * in parallel for a single channel, and there may be multiple channels 307b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams * being tested in parallel. 3084a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen * 3094a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen * Before each test, the source and destination buffer is initialized 3104a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen * with a known pattern. This pattern is different depending on 3114a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen * whether it's in an area which is supposed to be copied or 3124a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen * overwritten, and different in the source and destination buffers. 3134a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen * So if the DMA engine doesn't copy exactly what we tell it to copy, 3144a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen * we'll notice. 3154a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen */ 3164a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoenstatic int dmatest_func(void *data) 3174a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen{ 318adfa543e7314b36ac55a40019977de6e47946dd7Tejun Heo DECLARE_WAIT_QUEUE_HEAD_ONSTACK(done_wait); 3194a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen struct dmatest_thread *thread = data; 320adfa543e7314b36ac55a40019977de6e47946dd7Tejun Heo struct dmatest_done done = { .wait = &done_wait }; 321e03e93a976d0f0da63f02fd3384c4b99cac8d715Andy Shevchenko struct dmatest_info *info; 32215b8a8ea1a87313f1b46ea878c65942fd52147edAndy Shevchenko struct dmatest_params *params; 3234a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen struct dma_chan *chan; 3248be9e32b310cd8c4302991c8ff6692689c7d9d76Akinobu Mita struct dma_device *dev; 3254a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen const char *thread_name; 3264a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen unsigned int src_off, dst_off, len; 3274a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen unsigned int error_count; 3284a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen unsigned int failed_tests = 0; 3294a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen unsigned int total_tests = 0; 3304a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen dma_cookie_t cookie; 3314a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen enum dma_status status; 332b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams enum dma_ctrl_flags flags; 333945b5af3cedcdfed6d2d940e53cd19933bb57386Andy Shevchenko u8 *pq_coefs = NULL; 3344a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen int ret; 335b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams int src_cnt; 336b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams int dst_cnt; 337b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams int i; 3384a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 3394a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen thread_name = current->comm; 340adfa543e7314b36ac55a40019977de6e47946dd7Tejun Heo set_freezable(); 3414a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 3424a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen ret = -ENOMEM; 3434a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 3444a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen smp_rmb(); 345e03e93a976d0f0da63f02fd3384c4b99cac8d715Andy Shevchenko info = thread->info; 34615b8a8ea1a87313f1b46ea878c65942fd52147edAndy Shevchenko params = &info->params; 3474a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen chan = thread->chan; 3488be9e32b310cd8c4302991c8ff6692689c7d9d76Akinobu Mita dev = chan->device; 349b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams if (thread->type == DMA_MEMCPY) 350b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams src_cnt = dst_cnt = 1; 351b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams else if (thread->type == DMA_XOR) { 3528be9e32b310cd8c4302991c8ff6692689c7d9d76Akinobu Mita /* force odd to ensure dst = src */ 35315b8a8ea1a87313f1b46ea878c65942fd52147edAndy Shevchenko src_cnt = min_odd(params->xor_sources | 1, dev->max_xor); 354b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams dst_cnt = 1; 35558691d64c44ae41ddf098ecb31e9a994026e3cffDan Williams } else if (thread->type == DMA_PQ) { 3568be9e32b310cd8c4302991c8ff6692689c7d9d76Akinobu Mita /* force odd to ensure dst = src */ 35715b8a8ea1a87313f1b46ea878c65942fd52147edAndy Shevchenko src_cnt = min_odd(params->pq_sources | 1, dma_maxpq(dev, 0)); 35858691d64c44ae41ddf098ecb31e9a994026e3cffDan Williams dst_cnt = 2; 359945b5af3cedcdfed6d2d940e53cd19933bb57386Andy Shevchenko 36015b8a8ea1a87313f1b46ea878c65942fd52147edAndy Shevchenko pq_coefs = kmalloc(params->pq_sources+1, GFP_KERNEL); 361945b5af3cedcdfed6d2d940e53cd19933bb57386Andy Shevchenko if (!pq_coefs) 362945b5af3cedcdfed6d2d940e53cd19933bb57386Andy Shevchenko goto err_thread_type; 363945b5af3cedcdfed6d2d940e53cd19933bb57386Andy Shevchenko 36494de648d72c8bc833590523f22386d4babbea988Anatolij Gustschin for (i = 0; i < src_cnt; i++) 36558691d64c44ae41ddf098ecb31e9a994026e3cffDan Williams pq_coefs[i] = 1; 366b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams } else 367945b5af3cedcdfed6d2d940e53cd19933bb57386Andy Shevchenko goto err_thread_type; 368b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams 369b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams thread->srcs = kcalloc(src_cnt+1, sizeof(u8 *), GFP_KERNEL); 370b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams if (!thread->srcs) 371b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams goto err_srcs; 372b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams for (i = 0; i < src_cnt; i++) { 37315b8a8ea1a87313f1b46ea878c65942fd52147edAndy Shevchenko thread->srcs[i] = kmalloc(params->buf_size, GFP_KERNEL); 374b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams if (!thread->srcs[i]) 375b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams goto err_srcbuf; 376b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams } 377b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams thread->srcs[i] = NULL; 378b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams 379b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams thread->dsts = kcalloc(dst_cnt+1, sizeof(u8 *), GFP_KERNEL); 380b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams if (!thread->dsts) 381b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams goto err_dsts; 382b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams for (i = 0; i < dst_cnt; i++) { 38315b8a8ea1a87313f1b46ea878c65942fd52147edAndy Shevchenko thread->dsts[i] = kmalloc(params->buf_size, GFP_KERNEL); 384b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams if (!thread->dsts[i]) 385b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams goto err_dstbuf; 386b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams } 387b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams thread->dsts[i] = NULL; 388b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams 389e44e0aa3cfa97cddff01704751a4b25151830c72Dan Williams set_user_nice(current, 10); 390e44e0aa3cfa97cddff01704751a4b25151830c72Dan Williams 391b203bd3f6b9c3db3b1979c2ff79bb2b9be8f03a3Ira Snyder /* 392b203bd3f6b9c3db3b1979c2ff79bb2b9be8f03a3Ira Snyder * src buffers are freed by the DMAEngine code with dma_unmap_single() 393b203bd3f6b9c3db3b1979c2ff79bb2b9be8f03a3Ira Snyder * dst buffers are freed by ourselves below 394b203bd3f6b9c3db3b1979c2ff79bb2b9be8f03a3Ira Snyder */ 395b203bd3f6b9c3db3b1979c2ff79bb2b9be8f03a3Ira Snyder flags = DMA_CTRL_ACK | DMA_PREP_INTERRUPT 396b203bd3f6b9c3db3b1979c2ff79bb2b9be8f03a3Ira Snyder | DMA_COMPL_SKIP_DEST_UNMAP | DMA_COMPL_SRC_UNMAP_SINGLE; 3974a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 3980a2ff57d6fba92842272889b4bca447344cd9d36Nicolas Ferre while (!kthread_should_stop() 39915b8a8ea1a87313f1b46ea878c65942fd52147edAndy Shevchenko && !(params->iterations && total_tests >= params->iterations)) { 400b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams struct dma_async_tx_descriptor *tx = NULL; 401b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams dma_addr_t dma_srcs[src_cnt]; 402b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams dma_addr_t dma_dsts[dst_cnt]; 40383544ae9f3991bfc7d5e0fe9a3008cd05a8d57b7Dan Williams u8 align = 0; 404d86be86e9aab221089d72399072511f13fe2a771Atsushi Nemoto 4054a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen total_tests++; 4064a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 40783544ae9f3991bfc7d5e0fe9a3008cd05a8d57b7Dan Williams /* honor alignment restrictions */ 40883544ae9f3991bfc7d5e0fe9a3008cd05a8d57b7Dan Williams if (thread->type == DMA_MEMCPY) 40983544ae9f3991bfc7d5e0fe9a3008cd05a8d57b7Dan Williams align = dev->copy_align; 41083544ae9f3991bfc7d5e0fe9a3008cd05a8d57b7Dan Williams else if (thread->type == DMA_XOR) 41183544ae9f3991bfc7d5e0fe9a3008cd05a8d57b7Dan Williams align = dev->xor_align; 41283544ae9f3991bfc7d5e0fe9a3008cd05a8d57b7Dan Williams else if (thread->type == DMA_PQ) 41383544ae9f3991bfc7d5e0fe9a3008cd05a8d57b7Dan Williams align = dev->pq_align; 41483544ae9f3991bfc7d5e0fe9a3008cd05a8d57b7Dan Williams 41515b8a8ea1a87313f1b46ea878c65942fd52147edAndy Shevchenko if (1 << align > params->buf_size) { 416cfe4f2751ef1a5390b56c5d263f90b6ff138ba31Guennadi Liakhovetski pr_err("%u-byte buffer too small for %d-byte alignment\n", 41715b8a8ea1a87313f1b46ea878c65942fd52147edAndy Shevchenko params->buf_size, 1 << align); 418cfe4f2751ef1a5390b56c5d263f90b6ff138ba31Guennadi Liakhovetski break; 419cfe4f2751ef1a5390b56c5d263f90b6ff138ba31Guennadi Liakhovetski } 420cfe4f2751ef1a5390b56c5d263f90b6ff138ba31Guennadi Liakhovetski 42115b8a8ea1a87313f1b46ea878c65942fd52147edAndy Shevchenko len = dmatest_random() % params->buf_size + 1; 42283544ae9f3991bfc7d5e0fe9a3008cd05a8d57b7Dan Williams len = (len >> align) << align; 423cfe4f2751ef1a5390b56c5d263f90b6ff138ba31Guennadi Liakhovetski if (!len) 424cfe4f2751ef1a5390b56c5d263f90b6ff138ba31Guennadi Liakhovetski len = 1 << align; 42515b8a8ea1a87313f1b46ea878c65942fd52147edAndy Shevchenko src_off = dmatest_random() % (params->buf_size - len + 1); 42615b8a8ea1a87313f1b46ea878c65942fd52147edAndy Shevchenko dst_off = dmatest_random() % (params->buf_size - len + 1); 427cfe4f2751ef1a5390b56c5d263f90b6ff138ba31Guennadi Liakhovetski 42883544ae9f3991bfc7d5e0fe9a3008cd05a8d57b7Dan Williams src_off = (src_off >> align) << align; 42983544ae9f3991bfc7d5e0fe9a3008cd05a8d57b7Dan Williams dst_off = (dst_off >> align) << align; 43083544ae9f3991bfc7d5e0fe9a3008cd05a8d57b7Dan Williams 43115b8a8ea1a87313f1b46ea878c65942fd52147edAndy Shevchenko dmatest_init_srcs(thread->srcs, src_off, len, params->buf_size); 43215b8a8ea1a87313f1b46ea878c65942fd52147edAndy Shevchenko dmatest_init_dsts(thread->dsts, dst_off, len, params->buf_size); 4334a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 434b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams for (i = 0; i < src_cnt; i++) { 435b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams u8 *buf = thread->srcs[i] + src_off; 436b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams 437b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams dma_srcs[i] = dma_map_single(dev->dev, buf, len, 438b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams DMA_TO_DEVICE); 439afde3be121efcc658e26f8cc71ead04af96d38f9Andy Shevchenko ret = dma_mapping_error(dev->dev, dma_srcs[i]); 440afde3be121efcc658e26f8cc71ead04af96d38f9Andy Shevchenko if (ret) { 441afde3be121efcc658e26f8cc71ead04af96d38f9Andy Shevchenko unmap_src(dev->dev, dma_srcs, len, i); 442afde3be121efcc658e26f8cc71ead04af96d38f9Andy Shevchenko pr_warn("%s: #%u: mapping error %d with " 443afde3be121efcc658e26f8cc71ead04af96d38f9Andy Shevchenko "src_off=0x%x len=0x%x\n", 444afde3be121efcc658e26f8cc71ead04af96d38f9Andy Shevchenko thread_name, total_tests - 1, ret, 445afde3be121efcc658e26f8cc71ead04af96d38f9Andy Shevchenko src_off, len); 446afde3be121efcc658e26f8cc71ead04af96d38f9Andy Shevchenko failed_tests++; 447afde3be121efcc658e26f8cc71ead04af96d38f9Andy Shevchenko continue; 448afde3be121efcc658e26f8cc71ead04af96d38f9Andy Shevchenko } 449b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams } 450d86be86e9aab221089d72399072511f13fe2a771Atsushi Nemoto /* map with DMA_BIDIRECTIONAL to force writeback/invalidate */ 451b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams for (i = 0; i < dst_cnt; i++) { 452b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams dma_dsts[i] = dma_map_single(dev->dev, thread->dsts[i], 45315b8a8ea1a87313f1b46ea878c65942fd52147edAndy Shevchenko params->buf_size, 454b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams DMA_BIDIRECTIONAL); 455afde3be121efcc658e26f8cc71ead04af96d38f9Andy Shevchenko ret = dma_mapping_error(dev->dev, dma_dsts[i]); 456afde3be121efcc658e26f8cc71ead04af96d38f9Andy Shevchenko if (ret) { 457afde3be121efcc658e26f8cc71ead04af96d38f9Andy Shevchenko unmap_src(dev->dev, dma_srcs, len, src_cnt); 45815b8a8ea1a87313f1b46ea878c65942fd52147edAndy Shevchenko unmap_dst(dev->dev, dma_dsts, params->buf_size, 45915b8a8ea1a87313f1b46ea878c65942fd52147edAndy Shevchenko i); 460afde3be121efcc658e26f8cc71ead04af96d38f9Andy Shevchenko pr_warn("%s: #%u: mapping error %d with " 461afde3be121efcc658e26f8cc71ead04af96d38f9Andy Shevchenko "dst_off=0x%x len=0x%x\n", 462afde3be121efcc658e26f8cc71ead04af96d38f9Andy Shevchenko thread_name, total_tests - 1, ret, 46315b8a8ea1a87313f1b46ea878c65942fd52147edAndy Shevchenko dst_off, params->buf_size); 464afde3be121efcc658e26f8cc71ead04af96d38f9Andy Shevchenko failed_tests++; 465afde3be121efcc658e26f8cc71ead04af96d38f9Andy Shevchenko continue; 466afde3be121efcc658e26f8cc71ead04af96d38f9Andy Shevchenko } 467b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams } 468b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams 469b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams if (thread->type == DMA_MEMCPY) 470b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams tx = dev->device_prep_dma_memcpy(chan, 471b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams dma_dsts[0] + dst_off, 472b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams dma_srcs[0], len, 473b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams flags); 474b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams else if (thread->type == DMA_XOR) 475b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams tx = dev->device_prep_dma_xor(chan, 476b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams dma_dsts[0] + dst_off, 47767b9124f734b22b30d9adf18c39fe795e2901070Dan Williams dma_srcs, src_cnt, 478b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams len, flags); 47958691d64c44ae41ddf098ecb31e9a994026e3cffDan Williams else if (thread->type == DMA_PQ) { 48058691d64c44ae41ddf098ecb31e9a994026e3cffDan Williams dma_addr_t dma_pq[dst_cnt]; 48158691d64c44ae41ddf098ecb31e9a994026e3cffDan Williams 48258691d64c44ae41ddf098ecb31e9a994026e3cffDan Williams for (i = 0; i < dst_cnt; i++) 48358691d64c44ae41ddf098ecb31e9a994026e3cffDan Williams dma_pq[i] = dma_dsts[i] + dst_off; 48458691d64c44ae41ddf098ecb31e9a994026e3cffDan Williams tx = dev->device_prep_dma_pq(chan, dma_pq, dma_srcs, 48594de648d72c8bc833590523f22386d4babbea988Anatolij Gustschin src_cnt, pq_coefs, 48658691d64c44ae41ddf098ecb31e9a994026e3cffDan Williams len, flags); 48758691d64c44ae41ddf098ecb31e9a994026e3cffDan Williams } 488d86be86e9aab221089d72399072511f13fe2a771Atsushi Nemoto 489d86be86e9aab221089d72399072511f13fe2a771Atsushi Nemoto if (!tx) { 490632fd28326c0cc7be9c51ea0d76d8bec39a695e9Andy Shevchenko unmap_src(dev->dev, dma_srcs, len, src_cnt); 49115b8a8ea1a87313f1b46ea878c65942fd52147edAndy Shevchenko unmap_dst(dev->dev, dma_dsts, params->buf_size, 49215b8a8ea1a87313f1b46ea878c65942fd52147edAndy Shevchenko dst_cnt); 493d86be86e9aab221089d72399072511f13fe2a771Atsushi Nemoto pr_warning("%s: #%u: prep error with src_off=0x%x " 494d86be86e9aab221089d72399072511f13fe2a771Atsushi Nemoto "dst_off=0x%x len=0x%x\n", 495d86be86e9aab221089d72399072511f13fe2a771Atsushi Nemoto thread_name, total_tests - 1, 496d86be86e9aab221089d72399072511f13fe2a771Atsushi Nemoto src_off, dst_off, len); 497d86be86e9aab221089d72399072511f13fe2a771Atsushi Nemoto msleep(100); 498d86be86e9aab221089d72399072511f13fe2a771Atsushi Nemoto failed_tests++; 499d86be86e9aab221089d72399072511f13fe2a771Atsushi Nemoto continue; 500d86be86e9aab221089d72399072511f13fe2a771Atsushi Nemoto } 501e44e0aa3cfa97cddff01704751a4b25151830c72Dan Williams 502adfa543e7314b36ac55a40019977de6e47946dd7Tejun Heo done.done = false; 503e44e0aa3cfa97cddff01704751a4b25151830c72Dan Williams tx->callback = dmatest_callback; 504adfa543e7314b36ac55a40019977de6e47946dd7Tejun Heo tx->callback_param = &done; 505d86be86e9aab221089d72399072511f13fe2a771Atsushi Nemoto cookie = tx->tx_submit(tx); 506d86be86e9aab221089d72399072511f13fe2a771Atsushi Nemoto 5074a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen if (dma_submit_error(cookie)) { 5084a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen pr_warning("%s: #%u: submit error %d with src_off=0x%x " 5094a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen "dst_off=0x%x len=0x%x\n", 5104a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen thread_name, total_tests - 1, cookie, 5114a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen src_off, dst_off, len); 5124a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen msleep(100); 5134a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen failed_tests++; 5144a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen continue; 5154a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen } 516b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams dma_async_issue_pending(chan); 5174a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 51877101ce578bb365e44c2944d6c338c68206e6e10Andy Shevchenko wait_event_freezable_timeout(done_wait, 51977101ce578bb365e44c2944d6c338c68206e6e10Andy Shevchenko done.done || kthread_should_stop(), 52015b8a8ea1a87313f1b46ea878c65942fd52147edAndy Shevchenko msecs_to_jiffies(params->timeout)); 521981ed70d8e4faf3689dbf3c48868a31d5b004d7aGuennadi Liakhovetski 522e44e0aa3cfa97cddff01704751a4b25151830c72Dan Williams status = dma_async_is_tx_complete(chan, cookie, NULL, NULL); 5234a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 524adfa543e7314b36ac55a40019977de6e47946dd7Tejun Heo if (!done.done) { 525adfa543e7314b36ac55a40019977de6e47946dd7Tejun Heo /* 526adfa543e7314b36ac55a40019977de6e47946dd7Tejun Heo * We're leaving the timed out dma operation with 527adfa543e7314b36ac55a40019977de6e47946dd7Tejun Heo * dangling pointer to done_wait. To make this 528adfa543e7314b36ac55a40019977de6e47946dd7Tejun Heo * correct, we'll need to allocate wait_done for 529adfa543e7314b36ac55a40019977de6e47946dd7Tejun Heo * each test iteration and perform "who's gonna 530adfa543e7314b36ac55a40019977de6e47946dd7Tejun Heo * free it this time?" dancing. For now, just 531adfa543e7314b36ac55a40019977de6e47946dd7Tejun Heo * leave it dangling. 532adfa543e7314b36ac55a40019977de6e47946dd7Tejun Heo */ 533e44e0aa3cfa97cddff01704751a4b25151830c72Dan Williams pr_warning("%s: #%u: test timed out\n", 534e44e0aa3cfa97cddff01704751a4b25151830c72Dan Williams thread_name, total_tests - 1); 535e44e0aa3cfa97cddff01704751a4b25151830c72Dan Williams failed_tests++; 536e44e0aa3cfa97cddff01704751a4b25151830c72Dan Williams continue; 537e44e0aa3cfa97cddff01704751a4b25151830c72Dan Williams } else if (status != DMA_SUCCESS) { 538e44e0aa3cfa97cddff01704751a4b25151830c72Dan Williams pr_warning("%s: #%u: got completion callback," 539e44e0aa3cfa97cddff01704751a4b25151830c72Dan Williams " but status is \'%s\'\n", 540e44e0aa3cfa97cddff01704751a4b25151830c72Dan Williams thread_name, total_tests - 1, 541e44e0aa3cfa97cddff01704751a4b25151830c72Dan Williams status == DMA_ERROR ? "error" : "in progress"); 5424a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen failed_tests++; 5434a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen continue; 5444a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen } 545e44e0aa3cfa97cddff01704751a4b25151830c72Dan Williams 546d86be86e9aab221089d72399072511f13fe2a771Atsushi Nemoto /* Unmap by myself (see DMA_COMPL_SKIP_DEST_UNMAP above) */ 54715b8a8ea1a87313f1b46ea878c65942fd52147edAndy Shevchenko unmap_dst(dev->dev, dma_dsts, params->buf_size, dst_cnt); 5484a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 5494a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen error_count = 0; 5504a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 5514a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen pr_debug("%s: verifying source buffer...\n", thread_name); 552b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams error_count += dmatest_verify(thread->srcs, 0, src_off, 5534a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 0, PATTERN_SRC, true); 554b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams error_count += dmatest_verify(thread->srcs, src_off, 5554a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen src_off + len, src_off, 5564a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen PATTERN_SRC | PATTERN_COPY, true); 557b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams error_count += dmatest_verify(thread->srcs, src_off + len, 55815b8a8ea1a87313f1b46ea878c65942fd52147edAndy Shevchenko params->buf_size, src_off + len, 5594a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen PATTERN_SRC, true); 5604a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 5614a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen pr_debug("%s: verifying dest buffer...\n", 5624a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen thread->task->comm); 563b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams error_count += dmatest_verify(thread->dsts, 0, dst_off, 5644a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 0, PATTERN_DST, false); 565b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams error_count += dmatest_verify(thread->dsts, dst_off, 5664a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen dst_off + len, src_off, 5674a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen PATTERN_SRC | PATTERN_COPY, false); 568b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams error_count += dmatest_verify(thread->dsts, dst_off + len, 56915b8a8ea1a87313f1b46ea878c65942fd52147edAndy Shevchenko params->buf_size, dst_off + len, 5704a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen PATTERN_DST, false); 5714a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 5724a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen if (error_count) { 5734a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen pr_warning("%s: #%u: %u errors with " 5744a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen "src_off=0x%x dst_off=0x%x len=0x%x\n", 5754a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen thread_name, total_tests - 1, error_count, 5764a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen src_off, dst_off, len); 5774a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen failed_tests++; 5784a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen } else { 5794a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen pr_debug("%s: #%u: No errors with " 5804a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen "src_off=0x%x dst_off=0x%x len=0x%x\n", 5814a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen thread_name, total_tests - 1, 5824a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen src_off, dst_off, len); 5834a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen } 5844a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen } 5854a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 5864a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen ret = 0; 587b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams for (i = 0; thread->dsts[i]; i++) 588b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams kfree(thread->dsts[i]); 5894a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoenerr_dstbuf: 590b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams kfree(thread->dsts); 591b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williamserr_dsts: 592b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams for (i = 0; thread->srcs[i]; i++) 593b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams kfree(thread->srcs[i]); 5944a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoenerr_srcbuf: 595b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams kfree(thread->srcs); 596b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williamserr_srcs: 597945b5af3cedcdfed6d2d940e53cd19933bb57386Andy Shevchenko kfree(pq_coefs); 598945b5af3cedcdfed6d2d940e53cd19933bb57386Andy Shevchenkoerr_thread_type: 5994a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen pr_notice("%s: terminating after %u tests, %u failures (status %d)\n", 6004a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen thread_name, total_tests, failed_tests, ret); 6010a2ff57d6fba92842272889b4bca447344cd9d36Nicolas Ferre 6029704efaa52ab18eb3504c4e0bc421c1d01b7981aViresh Kumar /* terminate all transfers on specified channels */ 6035e034f7b659be9d94e64aaaa985ab530dd847fdbShiraz Hashim if (ret) 6045e034f7b659be9d94e64aaaa985ab530dd847fdbShiraz Hashim dmaengine_terminate_all(chan); 6055e034f7b659be9d94e64aaaa985ab530dd847fdbShiraz Hashim 60615b8a8ea1a87313f1b46ea878c65942fd52147edAndy Shevchenko if (params->iterations > 0) 6070a2ff57d6fba92842272889b4bca447344cd9d36Nicolas Ferre while (!kthread_should_stop()) { 608b953df7c70740cd7593072ebec77a8f658505630Yong Zhang DECLARE_WAIT_QUEUE_HEAD_ONSTACK(wait_dmatest_exit); 6090a2ff57d6fba92842272889b4bca447344cd9d36Nicolas Ferre interruptible_sleep_on(&wait_dmatest_exit); 6100a2ff57d6fba92842272889b4bca447344cd9d36Nicolas Ferre } 6110a2ff57d6fba92842272889b4bca447344cd9d36Nicolas Ferre 6124a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen return ret; 6134a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen} 6144a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 6154a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoenstatic void dmatest_cleanup_channel(struct dmatest_chan *dtc) 6164a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen{ 6174a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen struct dmatest_thread *thread; 6184a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen struct dmatest_thread *_thread; 6194a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen int ret; 6204a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 6214a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen list_for_each_entry_safe(thread, _thread, &dtc->threads, node) { 6224a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen ret = kthread_stop(thread->task); 6234a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen pr_debug("dmatest: thread %s exited with status %d\n", 6244a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen thread->task->comm, ret); 6254a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen list_del(&thread->node); 6264a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen kfree(thread); 6274a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen } 6289704efaa52ab18eb3504c4e0bc421c1d01b7981aViresh Kumar 6299704efaa52ab18eb3504c4e0bc421c1d01b7981aViresh Kumar /* terminate all transfers on specified channels */ 630944ea4dd38b8575e30a5699633c81945bff1864dJon Mason dmaengine_terminate_all(dtc->chan); 6319704efaa52ab18eb3504c4e0bc421c1d01b7981aViresh Kumar 6324a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen kfree(dtc); 6334a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen} 6344a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 635e03e93a976d0f0da63f02fd3384c4b99cac8d715Andy Shevchenkostatic int dmatest_add_threads(struct dmatest_info *info, 636e03e93a976d0f0da63f02fd3384c4b99cac8d715Andy Shevchenko struct dmatest_chan *dtc, enum dma_transaction_type type) 6374a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen{ 63815b8a8ea1a87313f1b46ea878c65942fd52147edAndy Shevchenko struct dmatest_params *params = &info->params; 639b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams struct dmatest_thread *thread; 640b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams struct dma_chan *chan = dtc->chan; 641b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams char *op; 642b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams unsigned int i; 6434a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 644b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams if (type == DMA_MEMCPY) 645b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams op = "copy"; 646b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams else if (type == DMA_XOR) 647b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams op = "xor"; 64858691d64c44ae41ddf098ecb31e9a994026e3cffDan Williams else if (type == DMA_PQ) 64958691d64c44ae41ddf098ecb31e9a994026e3cffDan Williams op = "pq"; 650b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams else 651b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams return -EINVAL; 6524a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 65315b8a8ea1a87313f1b46ea878c65942fd52147edAndy Shevchenko for (i = 0; i < params->threads_per_chan; i++) { 6544a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen thread = kzalloc(sizeof(struct dmatest_thread), GFP_KERNEL); 6554a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen if (!thread) { 656b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams pr_warning("dmatest: No memory for %s-%s%u\n", 657b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams dma_chan_name(chan), op, i); 658b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams 6594a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen break; 6604a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen } 661e03e93a976d0f0da63f02fd3384c4b99cac8d715Andy Shevchenko thread->info = info; 6624a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen thread->chan = dtc->chan; 663b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams thread->type = type; 6644a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen smp_wmb(); 665b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams thread->task = kthread_run(dmatest_func, thread, "%s-%s%u", 666b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams dma_chan_name(chan), op, i); 6674a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen if (IS_ERR(thread->task)) { 668b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams pr_warning("dmatest: Failed to run thread %s-%s%u\n", 669b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams dma_chan_name(chan), op, i); 6704a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen kfree(thread); 6714a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen break; 6724a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen } 6734a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 6744a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen /* srcbuf and dstbuf are allocated by the thread itself */ 6754a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 6764a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen list_add_tail(&thread->node, &dtc->threads); 6774a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen } 6784a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 679b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams return i; 680b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams} 681b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams 682e03e93a976d0f0da63f02fd3384c4b99cac8d715Andy Shevchenkostatic int dmatest_add_channel(struct dmatest_info *info, 683e03e93a976d0f0da63f02fd3384c4b99cac8d715Andy Shevchenko struct dma_chan *chan) 684b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams{ 685b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams struct dmatest_chan *dtc; 686b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams struct dma_device *dma_dev = chan->device; 687b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams unsigned int thread_count = 0; 688b9033e682e86f3c6a66763f9b6a3935c5c64e145Kulikov Vasiliy int cnt; 689b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams 690b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams dtc = kmalloc(sizeof(struct dmatest_chan), GFP_KERNEL); 691b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams if (!dtc) { 692b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams pr_warning("dmatest: No memory for %s\n", dma_chan_name(chan)); 693b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams return -ENOMEM; 694b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams } 695b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams 696b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams dtc->chan = chan; 697b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams INIT_LIST_HEAD(&dtc->threads); 698b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams 699b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams if (dma_has_cap(DMA_MEMCPY, dma_dev->cap_mask)) { 700e03e93a976d0f0da63f02fd3384c4b99cac8d715Andy Shevchenko cnt = dmatest_add_threads(info, dtc, DMA_MEMCPY); 701f1aef8b6e6abf32a3a269542f95a19e2cb319f6cNicolas Ferre thread_count += cnt > 0 ? cnt : 0; 702b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams } 703b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams if (dma_has_cap(DMA_XOR, dma_dev->cap_mask)) { 704e03e93a976d0f0da63f02fd3384c4b99cac8d715Andy Shevchenko cnt = dmatest_add_threads(info, dtc, DMA_XOR); 705f1aef8b6e6abf32a3a269542f95a19e2cb319f6cNicolas Ferre thread_count += cnt > 0 ? cnt : 0; 706b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams } 70758691d64c44ae41ddf098ecb31e9a994026e3cffDan Williams if (dma_has_cap(DMA_PQ, dma_dev->cap_mask)) { 708e03e93a976d0f0da63f02fd3384c4b99cac8d715Andy Shevchenko cnt = dmatest_add_threads(info, dtc, DMA_PQ); 709d07a74a546981a09ba490936645fbf0d1340b96cDr. David Alan Gilbert thread_count += cnt > 0 ? cnt : 0; 71058691d64c44ae41ddf098ecb31e9a994026e3cffDan Williams } 711b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams 712b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams pr_info("dmatest: Started %u threads using %s\n", 713b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams thread_count, dma_chan_name(chan)); 7144a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 715838cc704ce5c8ab2a6d64d1324e37e040fcae3d8Andy Shevchenko list_add_tail(&dtc->node, &info->channels); 716838cc704ce5c8ab2a6d64d1324e37e040fcae3d8Andy Shevchenko info->nr_channels++; 7174a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 71833df8ca068123457db56c316946a3c0e4ef787d6Dan Williams return 0; 7194a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen} 7204a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 7217dd602510128d7a64b11ff3b7d4f30ac8e3946ceDan Williamsstatic bool filter(struct dma_chan *chan, void *param) 7224a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen{ 72315b8a8ea1a87313f1b46ea878c65942fd52147edAndy Shevchenko struct dmatest_params *params = param; 724e03e93a976d0f0da63f02fd3384c4b99cac8d715Andy Shevchenko 72515b8a8ea1a87313f1b46ea878c65942fd52147edAndy Shevchenko if (!dmatest_match_channel(params, chan) || 72615b8a8ea1a87313f1b46ea878c65942fd52147edAndy Shevchenko !dmatest_match_device(params, chan->device)) 7277dd602510128d7a64b11ff3b7d4f30ac8e3946ceDan Williams return false; 72833df8ca068123457db56c316946a3c0e4ef787d6Dan Williams else 7297dd602510128d7a64b11ff3b7d4f30ac8e3946ceDan Williams return true; 7304a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen} 7314a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 732851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenkostatic int __run_threaded_test(struct dmatest_info *info) 7334a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen{ 73433df8ca068123457db56c316946a3c0e4ef787d6Dan Williams dma_cap_mask_t mask; 73533df8ca068123457db56c316946a3c0e4ef787d6Dan Williams struct dma_chan *chan; 73615b8a8ea1a87313f1b46ea878c65942fd52147edAndy Shevchenko struct dmatest_params *params = &info->params; 73733df8ca068123457db56c316946a3c0e4ef787d6Dan Williams int err = 0; 73833df8ca068123457db56c316946a3c0e4ef787d6Dan Williams 73933df8ca068123457db56c316946a3c0e4ef787d6Dan Williams dma_cap_zero(mask); 74033df8ca068123457db56c316946a3c0e4ef787d6Dan Williams dma_cap_set(DMA_MEMCPY, mask); 74133df8ca068123457db56c316946a3c0e4ef787d6Dan Williams for (;;) { 74215b8a8ea1a87313f1b46ea878c65942fd52147edAndy Shevchenko chan = dma_request_channel(mask, filter, params); 74333df8ca068123457db56c316946a3c0e4ef787d6Dan Williams if (chan) { 744e03e93a976d0f0da63f02fd3384c4b99cac8d715Andy Shevchenko err = dmatest_add_channel(info, chan); 745c56c81abe7e684bc6203632d807303eb765690dcDan Williams if (err) { 74633df8ca068123457db56c316946a3c0e4ef787d6Dan Williams dma_release_channel(chan); 74733df8ca068123457db56c316946a3c0e4ef787d6Dan Williams break; /* add_channel failed, punt */ 74833df8ca068123457db56c316946a3c0e4ef787d6Dan Williams } 74933df8ca068123457db56c316946a3c0e4ef787d6Dan Williams } else 75033df8ca068123457db56c316946a3c0e4ef787d6Dan Williams break; /* no more channels available */ 75115b8a8ea1a87313f1b46ea878c65942fd52147edAndy Shevchenko if (params->max_channels && 75215b8a8ea1a87313f1b46ea878c65942fd52147edAndy Shevchenko info->nr_channels >= params->max_channels) 75333df8ca068123457db56c316946a3c0e4ef787d6Dan Williams break; /* we have all we need */ 75433df8ca068123457db56c316946a3c0e4ef787d6Dan Williams } 75533df8ca068123457db56c316946a3c0e4ef787d6Dan Williams return err; 7564a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen} 7574a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 758851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko#ifndef MODULE 759851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenkostatic int run_threaded_test(struct dmatest_info *info) 760851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko{ 761851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko int ret; 762851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko 763851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko mutex_lock(&info->lock); 764851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko ret = __run_threaded_test(info); 765851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko mutex_unlock(&info->lock); 766851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko return ret; 767851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko} 768851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko#endif 769851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko 770851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenkostatic void __stop_threaded_test(struct dmatest_info *info) 7714a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen{ 77233df8ca068123457db56c316946a3c0e4ef787d6Dan Williams struct dmatest_chan *dtc, *_dtc; 7737cbd4877e5b167b56a3d6033b926a9f925186e12Dan Williams struct dma_chan *chan; 77433df8ca068123457db56c316946a3c0e4ef787d6Dan Williams 775838cc704ce5c8ab2a6d64d1324e37e040fcae3d8Andy Shevchenko list_for_each_entry_safe(dtc, _dtc, &info->channels, node) { 77633df8ca068123457db56c316946a3c0e4ef787d6Dan Williams list_del(&dtc->node); 7777cbd4877e5b167b56a3d6033b926a9f925186e12Dan Williams chan = dtc->chan; 77833df8ca068123457db56c316946a3c0e4ef787d6Dan Williams dmatest_cleanup_channel(dtc); 779838cc704ce5c8ab2a6d64d1324e37e040fcae3d8Andy Shevchenko pr_debug("dmatest: dropped channel %s\n", dma_chan_name(chan)); 7807cbd4877e5b167b56a3d6033b926a9f925186e12Dan Williams dma_release_channel(chan); 78133df8ca068123457db56c316946a3c0e4ef787d6Dan Williams } 782838cc704ce5c8ab2a6d64d1324e37e040fcae3d8Andy Shevchenko 783838cc704ce5c8ab2a6d64d1324e37e040fcae3d8Andy Shevchenko info->nr_channels = 0; 7844a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen} 785e03e93a976d0f0da63f02fd3384c4b99cac8d715Andy Shevchenko 786851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenkostatic void stop_threaded_test(struct dmatest_info *info) 787851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko{ 788851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko mutex_lock(&info->lock); 789851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko __stop_threaded_test(info); 790851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko mutex_unlock(&info->lock); 791851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko} 792851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko 793851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenkostatic int __restart_threaded_test(struct dmatest_info *info, bool run) 794851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko{ 795851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko struct dmatest_params *params = &info->params; 796851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko int ret; 797851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko 798851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko /* Stop any running test first */ 799851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko __stop_threaded_test(info); 800851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko 801851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko if (run == false) 802851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko return 0; 803851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko 804851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko /* Copy test parameters */ 805851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko memcpy(params, &info->dbgfs_params, sizeof(*params)); 806851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko 807851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko /* Run test with new parameters */ 808851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko ret = __run_threaded_test(info); 809851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko if (ret) { 810851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko __stop_threaded_test(info); 811851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko pr_err("dmatest: Can't run test\n"); 812851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko } 813851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko 814851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko return ret; 815851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko} 816851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko 817851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenkostatic ssize_t dtf_write_string(void *to, size_t available, loff_t *ppos, 818851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko const void __user *from, size_t count) 819851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko{ 820851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko char tmp[20]; 821851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko ssize_t len; 822851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko 823851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko len = simple_write_to_buffer(tmp, sizeof(tmp) - 1, ppos, from, count); 824851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko if (len >= 0) { 825851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko tmp[len] = '\0'; 826851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko strlcpy(to, strim(tmp), available); 827851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko } 828851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko 829851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko return len; 830851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko} 831851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko 832851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenkostatic ssize_t dtf_read_channel(struct file *file, char __user *buf, 833851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko size_t count, loff_t *ppos) 834851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko{ 835851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko struct dmatest_info *info = file->private_data; 836851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko return simple_read_from_buffer(buf, count, ppos, 837851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko info->dbgfs_params.channel, 838851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko strlen(info->dbgfs_params.channel)); 839851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko} 840851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko 841851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenkostatic ssize_t dtf_write_channel(struct file *file, const char __user *buf, 842851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko size_t size, loff_t *ppos) 843851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko{ 844851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko struct dmatest_info *info = file->private_data; 845851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko return dtf_write_string(info->dbgfs_params.channel, 846851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko sizeof(info->dbgfs_params.channel), 847851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko ppos, buf, size); 848851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko} 849851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko 850851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenkostatic const struct file_operations dtf_channel_fops = { 851851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko .read = dtf_read_channel, 852851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko .write = dtf_write_channel, 853851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko .open = simple_open, 854851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko .llseek = default_llseek, 855851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko}; 856851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko 857851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenkostatic ssize_t dtf_read_device(struct file *file, char __user *buf, 858851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko size_t count, loff_t *ppos) 859851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko{ 860851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko struct dmatest_info *info = file->private_data; 861851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko return simple_read_from_buffer(buf, count, ppos, 862851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko info->dbgfs_params.device, 863851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko strlen(info->dbgfs_params.device)); 864851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko} 865851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko 866851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenkostatic ssize_t dtf_write_device(struct file *file, const char __user *buf, 867851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko size_t size, loff_t *ppos) 868851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko{ 869851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko struct dmatest_info *info = file->private_data; 870851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko return dtf_write_string(info->dbgfs_params.device, 871851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko sizeof(info->dbgfs_params.device), 872851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko ppos, buf, size); 873851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko} 874851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko 875851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenkostatic const struct file_operations dtf_device_fops = { 876851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko .read = dtf_read_device, 877851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko .write = dtf_write_device, 878851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko .open = simple_open, 879851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko .llseek = default_llseek, 880851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko}; 881851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko 882851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenkostatic ssize_t dtf_read_run(struct file *file, char __user *user_buf, 883851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko size_t count, loff_t *ppos) 884851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko{ 885851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko struct dmatest_info *info = file->private_data; 886851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko char buf[3]; 887851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko 888851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko mutex_lock(&info->lock); 889851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko if (info->nr_channels) 890851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko buf[0] = 'Y'; 891851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko else 892851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko buf[0] = 'N'; 893851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko mutex_unlock(&info->lock); 894851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko buf[1] = '\n'; 895851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko buf[2] = 0x00; 896851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko return simple_read_from_buffer(user_buf, count, ppos, buf, 2); 897851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko} 898851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko 899851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenkostatic ssize_t dtf_write_run(struct file *file, const char __user *user_buf, 900851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko size_t count, loff_t *ppos) 901851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko{ 902851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko struct dmatest_info *info = file->private_data; 903851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko char buf[16]; 904851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko bool bv; 905851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko int ret = 0; 906851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko 907851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko if (copy_from_user(buf, user_buf, min(count, (sizeof(buf) - 1)))) 908851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko return -EFAULT; 909851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko 910851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko if (strtobool(buf, &bv) == 0) { 911851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko mutex_lock(&info->lock); 912851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko ret = __restart_threaded_test(info, bv); 913851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko mutex_unlock(&info->lock); 914851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko } 915851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko 916851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko return ret ? ret : count; 917851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko} 918851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko 919851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenkostatic const struct file_operations dtf_run_fops = { 920851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko .read = dtf_read_run, 921851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko .write = dtf_write_run, 922851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko .open = simple_open, 923851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko .llseek = default_llseek, 924851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko}; 925851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko 926851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenkostatic int dmatest_register_dbgfs(struct dmatest_info *info) 927851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko{ 928851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko struct dentry *d; 929851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko struct dmatest_params *params = &info->dbgfs_params; 930851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko int ret = -ENOMEM; 931851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko 932851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko d = debugfs_create_dir("dmatest", NULL); 933851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko if (IS_ERR(d)) 934851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko return PTR_ERR(d); 935851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko if (!d) 936851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko goto err_root; 937851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko 938851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko info->root = d; 939851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko 940851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko /* Copy initial values */ 941851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko memcpy(params, &info->params, sizeof(*params)); 942851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko 943851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko /* Test parameters */ 944851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko 945851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko d = debugfs_create_u32("test_buf_size", S_IWUSR | S_IRUGO, info->root, 946851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko (u32 *)¶ms->buf_size); 947851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko if (IS_ERR_OR_NULL(d)) 948851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko goto err_node; 949851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko 950851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko d = debugfs_create_file("channel", S_IRUGO | S_IWUSR, info->root, 951851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko info, &dtf_channel_fops); 952851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko if (IS_ERR_OR_NULL(d)) 953851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko goto err_node; 954851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko 955851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko d = debugfs_create_file("device", S_IRUGO | S_IWUSR, info->root, 956851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko info, &dtf_device_fops); 957851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko if (IS_ERR_OR_NULL(d)) 958851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko goto err_node; 959851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko 960851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko d = debugfs_create_u32("threads_per_chan", S_IWUSR | S_IRUGO, info->root, 961851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko (u32 *)¶ms->threads_per_chan); 962851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko if (IS_ERR_OR_NULL(d)) 963851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko goto err_node; 964851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko 965851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko d = debugfs_create_u32("max_channels", S_IWUSR | S_IRUGO, info->root, 966851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko (u32 *)¶ms->max_channels); 967851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko if (IS_ERR_OR_NULL(d)) 968851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko goto err_node; 969851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko 970851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko d = debugfs_create_u32("iterations", S_IWUSR | S_IRUGO, info->root, 971851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko (u32 *)¶ms->iterations); 972851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko if (IS_ERR_OR_NULL(d)) 973851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko goto err_node; 974851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko 975851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko d = debugfs_create_u32("xor_sources", S_IWUSR | S_IRUGO, info->root, 976851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko (u32 *)¶ms->xor_sources); 977851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko if (IS_ERR_OR_NULL(d)) 978851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko goto err_node; 979851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko 980851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko d = debugfs_create_u32("pq_sources", S_IWUSR | S_IRUGO, info->root, 981851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko (u32 *)¶ms->pq_sources); 982851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko if (IS_ERR_OR_NULL(d)) 983851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko goto err_node; 984851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko 985851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko d = debugfs_create_u32("timeout", S_IWUSR | S_IRUGO, info->root, 986851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko (u32 *)¶ms->timeout); 987851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko if (IS_ERR_OR_NULL(d)) 988851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko goto err_node; 989851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko 990851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko /* Run or stop threaded test */ 991851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko d = debugfs_create_file("run", S_IWUSR | S_IRUGO, info->root, 992851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko info, &dtf_run_fops); 993851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko if (IS_ERR_OR_NULL(d)) 994851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko goto err_node; 995851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko 996851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko return 0; 997851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko 998851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenkoerr_node: 999851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko debugfs_remove_recursive(info->root); 1000851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenkoerr_root: 1001851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko pr_err("dmatest: Failed to initialize debugfs\n"); 1002851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko return ret; 1003851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko} 1004851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko 1005e03e93a976d0f0da63f02fd3384c4b99cac8d715Andy Shevchenkostatic int __init dmatest_init(void) 1006e03e93a976d0f0da63f02fd3384c4b99cac8d715Andy Shevchenko{ 1007e03e93a976d0f0da63f02fd3384c4b99cac8d715Andy Shevchenko struct dmatest_info *info = &test_info; 100815b8a8ea1a87313f1b46ea878c65942fd52147edAndy Shevchenko struct dmatest_params *params = &info->params; 1009851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko int ret; 1010e03e93a976d0f0da63f02fd3384c4b99cac8d715Andy Shevchenko 1011e03e93a976d0f0da63f02fd3384c4b99cac8d715Andy Shevchenko memset(info, 0, sizeof(*info)); 1012e03e93a976d0f0da63f02fd3384c4b99cac8d715Andy Shevchenko 1013851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko mutex_init(&info->lock); 1014838cc704ce5c8ab2a6d64d1324e37e040fcae3d8Andy Shevchenko INIT_LIST_HEAD(&info->channels); 1015838cc704ce5c8ab2a6d64d1324e37e040fcae3d8Andy Shevchenko 1016838cc704ce5c8ab2a6d64d1324e37e040fcae3d8Andy Shevchenko /* Set default parameters */ 101715b8a8ea1a87313f1b46ea878c65942fd52147edAndy Shevchenko params->buf_size = test_buf_size; 101815b8a8ea1a87313f1b46ea878c65942fd52147edAndy Shevchenko strlcpy(params->channel, test_channel, sizeof(params->channel)); 101915b8a8ea1a87313f1b46ea878c65942fd52147edAndy Shevchenko strlcpy(params->device, test_device, sizeof(params->device)); 102015b8a8ea1a87313f1b46ea878c65942fd52147edAndy Shevchenko params->threads_per_chan = threads_per_chan; 102115b8a8ea1a87313f1b46ea878c65942fd52147edAndy Shevchenko params->max_channels = max_channels; 102215b8a8ea1a87313f1b46ea878c65942fd52147edAndy Shevchenko params->iterations = iterations; 102315b8a8ea1a87313f1b46ea878c65942fd52147edAndy Shevchenko params->xor_sources = xor_sources; 102415b8a8ea1a87313f1b46ea878c65942fd52147edAndy Shevchenko params->pq_sources = pq_sources; 102515b8a8ea1a87313f1b46ea878c65942fd52147edAndy Shevchenko params->timeout = timeout; 1026e03e93a976d0f0da63f02fd3384c4b99cac8d715Andy Shevchenko 1027851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko ret = dmatest_register_dbgfs(info); 1028851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko if (ret) 1029851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko return ret; 1030851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko 1031851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko#ifdef MODULE 1032851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko return 0; 1033851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko#else 1034e03e93a976d0f0da63f02fd3384c4b99cac8d715Andy Shevchenko return run_threaded_test(info); 1035851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko#endif 1036e03e93a976d0f0da63f02fd3384c4b99cac8d715Andy Shevchenko} 1037e03e93a976d0f0da63f02fd3384c4b99cac8d715Andy Shevchenko/* when compiled-in wait for drivers to load first */ 1038e03e93a976d0f0da63f02fd3384c4b99cac8d715Andy Shevchenkolate_initcall(dmatest_init); 1039e03e93a976d0f0da63f02fd3384c4b99cac8d715Andy Shevchenko 1040e03e93a976d0f0da63f02fd3384c4b99cac8d715Andy Shevchenkostatic void __exit dmatest_exit(void) 1041e03e93a976d0f0da63f02fd3384c4b99cac8d715Andy Shevchenko{ 1042e03e93a976d0f0da63f02fd3384c4b99cac8d715Andy Shevchenko struct dmatest_info *info = &test_info; 1043e03e93a976d0f0da63f02fd3384c4b99cac8d715Andy Shevchenko 1044851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko debugfs_remove_recursive(info->root); 1045e03e93a976d0f0da63f02fd3384c4b99cac8d715Andy Shevchenko stop_threaded_test(info); 1046e03e93a976d0f0da63f02fd3384c4b99cac8d715Andy Shevchenko} 10474a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoenmodule_exit(dmatest_exit); 10484a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 1049e05503ef1186ad33dfe56794407891eb1dd93ef6Jean DelvareMODULE_AUTHOR("Haavard Skinnemoen (Atmel)"); 10504a776f0aa922a552460192c07b56f4fe9cd82632Haavard SkinnemoenMODULE_LICENSE("GPL v2"); 1051