dmatest.c revision e3b9c347316fe243bea6abd08681050c43ca22ee
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 */ 11872f05c6e9a37e9358fd58eb54deee7337863496Dan Williams#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 12872f05c6e9a37e9358fd58eb54deee7337863496Dan Williams 134a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen#include <linux/delay.h> 14b7f080cfe223b3b7424872639d153695615a9255Alexey Dobriyan#include <linux/dma-mapping.h> 154a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen#include <linux/dmaengine.h> 16981ed70d8e4faf3689dbf3c48868a31d5b004d7aGuennadi Liakhovetski#include <linux/freezer.h> 174a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen#include <linux/init.h> 184a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen#include <linux/kthread.h> 194a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen#include <linux/module.h> 204a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen#include <linux/moduleparam.h> 214a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen#include <linux/random.h> 225a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h> 234a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen#include <linux/wait.h> 244a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 254a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoenstatic unsigned int test_buf_size = 16384; 26a6c268d033b1f363e0d76c0483a0f99266542820Andy Shevchenkomodule_param(test_buf_size, uint, S_IRUGO | S_IWUSR); 274a776f0aa922a552460192c07b56f4fe9cd82632Haavard SkinnemoenMODULE_PARM_DESC(test_buf_size, "Size of the memcpy test buffer"); 284a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 2906190d8415219d9eef7d8f04b52a109e34575a76Kay Sieversstatic char test_channel[20]; 30a6c268d033b1f363e0d76c0483a0f99266542820Andy Shevchenkomodule_param_string(channel, test_channel, sizeof(test_channel), 31a6c268d033b1f363e0d76c0483a0f99266542820Andy Shevchenko S_IRUGO | S_IWUSR); 324a776f0aa922a552460192c07b56f4fe9cd82632Haavard SkinnemoenMODULE_PARM_DESC(channel, "Bus ID of the channel to test (default: any)"); 334a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 3406190d8415219d9eef7d8f04b52a109e34575a76Kay Sieversstatic char test_device[20]; 35a6c268d033b1f363e0d76c0483a0f99266542820Andy Shevchenkomodule_param_string(device, test_device, sizeof(test_device), 36a6c268d033b1f363e0d76c0483a0f99266542820Andy Shevchenko S_IRUGO | S_IWUSR); 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; 40a6c268d033b1f363e0d76c0483a0f99266542820Andy Shevchenkomodule_param(threads_per_chan, uint, S_IRUGO | S_IWUSR); 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; 45a6c268d033b1f363e0d76c0483a0f99266542820Andy Shevchenkomodule_param(max_channels, uint, S_IRUGO | S_IWUSR); 4633df8ca068123457db56c316946a3c0e4ef787d6Dan WilliamsMODULE_PARM_DESC(max_channels, 474a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen "Maximum number of channels to use (default: all)"); 484a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 490a2ff57d6fba92842272889b4bca447344cd9d36Nicolas Ferrestatic unsigned int iterations; 50a6c268d033b1f363e0d76c0483a0f99266542820Andy Shevchenkomodule_param(iterations, uint, S_IRUGO | S_IWUSR); 510a2ff57d6fba92842272889b4bca447344cd9d36Nicolas FerreMODULE_PARM_DESC(iterations, 520a2ff57d6fba92842272889b4bca447344cd9d36Nicolas Ferre "Iterations before stopping test (default: infinite)"); 530a2ff57d6fba92842272889b4bca447344cd9d36Nicolas Ferre 54b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williamsstatic unsigned int xor_sources = 3; 55a6c268d033b1f363e0d76c0483a0f99266542820Andy Shevchenkomodule_param(xor_sources, uint, S_IRUGO | S_IWUSR); 56b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan WilliamsMODULE_PARM_DESC(xor_sources, 57b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams "Number of xor source buffers (default: 3)"); 58b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams 5958691d64c44ae41ddf098ecb31e9a994026e3cffDan Williamsstatic unsigned int pq_sources = 3; 60a6c268d033b1f363e0d76c0483a0f99266542820Andy Shevchenkomodule_param(pq_sources, uint, S_IRUGO | S_IWUSR); 6158691d64c44ae41ddf098ecb31e9a994026e3cffDan WilliamsMODULE_PARM_DESC(pq_sources, 6258691d64c44ae41ddf098ecb31e9a994026e3cffDan Williams "Number of p+q source buffers (default: 3)"); 6358691d64c44ae41ddf098ecb31e9a994026e3cffDan Williams 64d42efe6bfb4eed8314c8ce3547f21954a4140399Viresh Kumarstatic int timeout = 3000; 65a6c268d033b1f363e0d76c0483a0f99266542820Andy Shevchenkomodule_param(timeout, uint, S_IRUGO | S_IWUSR); 6685ee7a1d39d75d23d21f3871f6dc9b87d572747aJoe PerchesMODULE_PARM_DESC(timeout, "Transfer Timeout in msec (default: 3000), " 6785ee7a1d39d75d23d21f3871f6dc9b87d572747aJoe Perches "Pass -1 for infinite timeout"); 68d42efe6bfb4eed8314c8ce3547f21954a4140399Viresh Kumar 69e3b9c347316fe243bea6abd08681050c43ca22eeDan Williamsstatic bool noverify; 70e3b9c347316fe243bea6abd08681050c43ca22eeDan Williamsmodule_param(noverify, bool, S_IRUGO | S_IWUSR); 71e3b9c347316fe243bea6abd08681050c43ca22eeDan WilliamsMODULE_PARM_DESC(noverify, "Disable random data setup and verification"); 72e3b9c347316fe243bea6abd08681050c43ca22eeDan Williams 73e03e93a976d0f0da63f02fd3384c4b99cac8d715Andy Shevchenko/** 7415b8a8ea1a87313f1b46ea878c65942fd52147edAndy Shevchenko * struct dmatest_params - test parameters. 75e03e93a976d0f0da63f02fd3384c4b99cac8d715Andy Shevchenko * @buf_size: size of the memcpy test buffer 76e03e93a976d0f0da63f02fd3384c4b99cac8d715Andy Shevchenko * @channel: bus ID of the channel to test 77e03e93a976d0f0da63f02fd3384c4b99cac8d715Andy Shevchenko * @device: bus ID of the DMA Engine to test 78e03e93a976d0f0da63f02fd3384c4b99cac8d715Andy Shevchenko * @threads_per_chan: number of threads to start per channel 79e03e93a976d0f0da63f02fd3384c4b99cac8d715Andy Shevchenko * @max_channels: maximum number of channels to use 80e03e93a976d0f0da63f02fd3384c4b99cac8d715Andy Shevchenko * @iterations: iterations before stopping test 81e03e93a976d0f0da63f02fd3384c4b99cac8d715Andy Shevchenko * @xor_sources: number of xor source buffers 82e03e93a976d0f0da63f02fd3384c4b99cac8d715Andy Shevchenko * @pq_sources: number of p+q source buffers 83e03e93a976d0f0da63f02fd3384c4b99cac8d715Andy Shevchenko * @timeout: transfer timeout in msec, -1 for infinite timeout 84e03e93a976d0f0da63f02fd3384c4b99cac8d715Andy Shevchenko */ 8515b8a8ea1a87313f1b46ea878c65942fd52147edAndy Shevchenkostruct dmatest_params { 86e03e93a976d0f0da63f02fd3384c4b99cac8d715Andy Shevchenko unsigned int buf_size; 87e03e93a976d0f0da63f02fd3384c4b99cac8d715Andy Shevchenko char channel[20]; 88e03e93a976d0f0da63f02fd3384c4b99cac8d715Andy Shevchenko char device[20]; 89e03e93a976d0f0da63f02fd3384c4b99cac8d715Andy Shevchenko unsigned int threads_per_chan; 90e03e93a976d0f0da63f02fd3384c4b99cac8d715Andy Shevchenko unsigned int max_channels; 91e03e93a976d0f0da63f02fd3384c4b99cac8d715Andy Shevchenko unsigned int iterations; 92e03e93a976d0f0da63f02fd3384c4b99cac8d715Andy Shevchenko unsigned int xor_sources; 93e03e93a976d0f0da63f02fd3384c4b99cac8d715Andy Shevchenko unsigned int pq_sources; 94e03e93a976d0f0da63f02fd3384c4b99cac8d715Andy Shevchenko int timeout; 95e3b9c347316fe243bea6abd08681050c43ca22eeDan Williams bool noverify; 9615b8a8ea1a87313f1b46ea878c65942fd52147edAndy Shevchenko}; 9715b8a8ea1a87313f1b46ea878c65942fd52147edAndy Shevchenko 9815b8a8ea1a87313f1b46ea878c65942fd52147edAndy Shevchenko/** 9915b8a8ea1a87313f1b46ea878c65942fd52147edAndy Shevchenko * struct dmatest_info - test information. 10015b8a8ea1a87313f1b46ea878c65942fd52147edAndy Shevchenko * @params: test parameters 101851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko * @lock: access protection to the fields of this structure 10215b8a8ea1a87313f1b46ea878c65942fd52147edAndy Shevchenko */ 103a310d037b8d06755c62bb4878c00d19490af5550Dan Williamsstatic struct dmatest_info { 10415b8a8ea1a87313f1b46ea878c65942fd52147edAndy Shevchenko /* Test parameters */ 10515b8a8ea1a87313f1b46ea878c65942fd52147edAndy Shevchenko struct dmatest_params params; 106838cc704ce5c8ab2a6d64d1324e37e040fcae3d8Andy Shevchenko 107838cc704ce5c8ab2a6d64d1324e37e040fcae3d8Andy Shevchenko /* Internal state */ 108838cc704ce5c8ab2a6d64d1324e37e040fcae3d8Andy Shevchenko struct list_head channels; 109838cc704ce5c8ab2a6d64d1324e37e040fcae3d8Andy Shevchenko unsigned int nr_channels; 110851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko struct mutex lock; 111a310d037b8d06755c62bb4878c00d19490af5550Dan Williams bool did_init; 112a310d037b8d06755c62bb4878c00d19490af5550Dan Williams} test_info = { 113a310d037b8d06755c62bb4878c00d19490af5550Dan Williams .channels = LIST_HEAD_INIT(test_info.channels), 114a310d037b8d06755c62bb4878c00d19490af5550Dan Williams .lock = __MUTEX_INITIALIZER(test_info.lock), 115a310d037b8d06755c62bb4878c00d19490af5550Dan Williams}; 116851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko 117a310d037b8d06755c62bb4878c00d19490af5550Dan Williamsstatic int dmatest_run_set(const char *val, const struct kernel_param *kp); 118a310d037b8d06755c62bb4878c00d19490af5550Dan Williamsstatic int dmatest_run_get(char *val, const struct kernel_param *kp); 119a310d037b8d06755c62bb4878c00d19490af5550Dan Williamsstatic struct kernel_param_ops run_ops = { 120a310d037b8d06755c62bb4878c00d19490af5550Dan Williams .set = dmatest_run_set, 121a310d037b8d06755c62bb4878c00d19490af5550Dan Williams .get = dmatest_run_get, 122e03e93a976d0f0da63f02fd3384c4b99cac8d715Andy Shevchenko}; 123a310d037b8d06755c62bb4878c00d19490af5550Dan Williamsstatic bool dmatest_run; 124a310d037b8d06755c62bb4878c00d19490af5550Dan Williamsmodule_param_cb(run, &run_ops, &dmatest_run, S_IRUGO | S_IWUSR); 125a310d037b8d06755c62bb4878c00d19490af5550Dan WilliamsMODULE_PARM_DESC(run, "Run the test (default: false)"); 126e03e93a976d0f0da63f02fd3384c4b99cac8d715Andy Shevchenko 127a310d037b8d06755c62bb4878c00d19490af5550Dan Williams/* Maximum amount of mismatched bytes in buffer to print */ 128a310d037b8d06755c62bb4878c00d19490af5550Dan Williams#define MAX_ERROR_COUNT 32 129a310d037b8d06755c62bb4878c00d19490af5550Dan Williams 130a310d037b8d06755c62bb4878c00d19490af5550Dan Williams/* 131a310d037b8d06755c62bb4878c00d19490af5550Dan Williams * Initialization patterns. All bytes in the source buffer has bit 7 132a310d037b8d06755c62bb4878c00d19490af5550Dan Williams * set, all bytes in the destination buffer has bit 7 cleared. 133a310d037b8d06755c62bb4878c00d19490af5550Dan Williams * 134a310d037b8d06755c62bb4878c00d19490af5550Dan Williams * Bit 6 is set for all bytes which are to be copied by the DMA 135a310d037b8d06755c62bb4878c00d19490af5550Dan Williams * engine. Bit 5 is set for all bytes which are to be overwritten by 136a310d037b8d06755c62bb4878c00d19490af5550Dan Williams * the DMA engine. 137a310d037b8d06755c62bb4878c00d19490af5550Dan Williams * 138a310d037b8d06755c62bb4878c00d19490af5550Dan Williams * The remaining bits are the inverse of a counter which increments by 139a310d037b8d06755c62bb4878c00d19490af5550Dan Williams * one for each byte address. 140a310d037b8d06755c62bb4878c00d19490af5550Dan Williams */ 141a310d037b8d06755c62bb4878c00d19490af5550Dan Williams#define PATTERN_SRC 0x80 142a310d037b8d06755c62bb4878c00d19490af5550Dan Williams#define PATTERN_DST 0x00 143a310d037b8d06755c62bb4878c00d19490af5550Dan Williams#define PATTERN_COPY 0x40 144a310d037b8d06755c62bb4878c00d19490af5550Dan Williams#define PATTERN_OVERWRITE 0x20 145a310d037b8d06755c62bb4878c00d19490af5550Dan Williams#define PATTERN_COUNT_MASK 0x1f 146a310d037b8d06755c62bb4878c00d19490af5550Dan Williams 147a310d037b8d06755c62bb4878c00d19490af5550Dan Williamsstruct dmatest_thread { 148a310d037b8d06755c62bb4878c00d19490af5550Dan Williams struct list_head node; 149a310d037b8d06755c62bb4878c00d19490af5550Dan Williams struct dmatest_info *info; 150a310d037b8d06755c62bb4878c00d19490af5550Dan Williams struct task_struct *task; 151a310d037b8d06755c62bb4878c00d19490af5550Dan Williams struct dma_chan *chan; 152a310d037b8d06755c62bb4878c00d19490af5550Dan Williams u8 **srcs; 153a310d037b8d06755c62bb4878c00d19490af5550Dan Williams u8 **dsts; 154a310d037b8d06755c62bb4878c00d19490af5550Dan Williams enum dma_transaction_type type; 155a310d037b8d06755c62bb4878c00d19490af5550Dan Williams bool done; 156a310d037b8d06755c62bb4878c00d19490af5550Dan Williams}; 157a310d037b8d06755c62bb4878c00d19490af5550Dan Williams 158a310d037b8d06755c62bb4878c00d19490af5550Dan Williamsstruct dmatest_chan { 159a310d037b8d06755c62bb4878c00d19490af5550Dan Williams struct list_head node; 160a310d037b8d06755c62bb4878c00d19490af5550Dan Williams struct dma_chan *chan; 161a310d037b8d06755c62bb4878c00d19490af5550Dan Williams struct list_head threads; 162a310d037b8d06755c62bb4878c00d19490af5550Dan Williams}; 163e03e93a976d0f0da63f02fd3384c4b99cac8d715Andy Shevchenko 16415b8a8ea1a87313f1b46ea878c65942fd52147edAndy Shevchenkostatic bool dmatest_match_channel(struct dmatest_params *params, 165e03e93a976d0f0da63f02fd3384c4b99cac8d715Andy Shevchenko struct dma_chan *chan) 1664a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen{ 16715b8a8ea1a87313f1b46ea878c65942fd52147edAndy Shevchenko if (params->channel[0] == '\0') 1684a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen return true; 16915b8a8ea1a87313f1b46ea878c65942fd52147edAndy Shevchenko return strcmp(dma_chan_name(chan), params->channel) == 0; 1704a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen} 1714a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 17215b8a8ea1a87313f1b46ea878c65942fd52147edAndy Shevchenkostatic bool dmatest_match_device(struct dmatest_params *params, 173e03e93a976d0f0da63f02fd3384c4b99cac8d715Andy Shevchenko struct dma_device *device) 1744a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen{ 17515b8a8ea1a87313f1b46ea878c65942fd52147edAndy Shevchenko if (params->device[0] == '\0') 1764a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen return true; 17715b8a8ea1a87313f1b46ea878c65942fd52147edAndy Shevchenko return strcmp(dev_name(device->dev), params->device) == 0; 1784a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen} 1794a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 1804a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoenstatic unsigned long dmatest_random(void) 1814a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen{ 1824a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen unsigned long buf; 1834a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 184be9fa5a43641103bf13cd1bb8101a1453da03616Dan Williams prandom_bytes(&buf, sizeof(buf)); 1854a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen return buf; 1864a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen} 1874a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 188e03e93a976d0f0da63f02fd3384c4b99cac8d715Andy Shevchenkostatic void dmatest_init_srcs(u8 **bufs, unsigned int start, unsigned int len, 189e03e93a976d0f0da63f02fd3384c4b99cac8d715Andy Shevchenko unsigned int buf_size) 1904a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen{ 1914a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen unsigned int i; 192b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams u8 *buf; 193b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams 194b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams for (; (buf = *bufs); bufs++) { 195b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams for (i = 0; i < start; i++) 196b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams buf[i] = PATTERN_SRC | (~i & PATTERN_COUNT_MASK); 197b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams for ( ; i < start + len; i++) 198b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams buf[i] = PATTERN_SRC | PATTERN_COPY 199c019894efc9c9ba5939948caa78c133b1ec8ae63Joe Perches | (~i & PATTERN_COUNT_MASK); 200e03e93a976d0f0da63f02fd3384c4b99cac8d715Andy Shevchenko for ( ; i < buf_size; i++) 201b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams buf[i] = PATTERN_SRC | (~i & PATTERN_COUNT_MASK); 202b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams buf++; 203b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams } 2044a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen} 2054a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 206e03e93a976d0f0da63f02fd3384c4b99cac8d715Andy Shevchenkostatic void dmatest_init_dsts(u8 **bufs, unsigned int start, unsigned int len, 207e03e93a976d0f0da63f02fd3384c4b99cac8d715Andy Shevchenko unsigned int buf_size) 2084a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen{ 2094a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen unsigned int i; 210b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams u8 *buf; 211b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams 212b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams for (; (buf = *bufs); bufs++) { 213b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams for (i = 0; i < start; i++) 214b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams buf[i] = PATTERN_DST | (~i & PATTERN_COUNT_MASK); 215b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams for ( ; i < start + len; i++) 216b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams buf[i] = PATTERN_DST | PATTERN_OVERWRITE 217b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams | (~i & PATTERN_COUNT_MASK); 218e03e93a976d0f0da63f02fd3384c4b99cac8d715Andy Shevchenko for ( ; i < buf_size; i++) 219b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams buf[i] = PATTERN_DST | (~i & PATTERN_COUNT_MASK); 220b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams } 2214a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen} 2224a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 2237b61017822cdff9c18ae70005cf52d84e8dafe5dDan Williamsstatic void dmatest_mismatch(u8 actual, u8 pattern, unsigned int index, 2247b61017822cdff9c18ae70005cf52d84e8dafe5dDan Williams unsigned int counter, bool is_srcbuf) 2257b61017822cdff9c18ae70005cf52d84e8dafe5dDan Williams{ 2267b61017822cdff9c18ae70005cf52d84e8dafe5dDan Williams u8 diff = actual ^ pattern; 2277b61017822cdff9c18ae70005cf52d84e8dafe5dDan Williams u8 expected = pattern | (~counter & PATTERN_COUNT_MASK); 2287b61017822cdff9c18ae70005cf52d84e8dafe5dDan Williams const char *thread_name = current->comm; 2297b61017822cdff9c18ae70005cf52d84e8dafe5dDan Williams 2307b61017822cdff9c18ae70005cf52d84e8dafe5dDan Williams if (is_srcbuf) 2317b61017822cdff9c18ae70005cf52d84e8dafe5dDan Williams pr_warn("%s: srcbuf[0x%x] overwritten! Expected %02x, got %02x\n", 2327b61017822cdff9c18ae70005cf52d84e8dafe5dDan Williams thread_name, index, expected, actual); 2337b61017822cdff9c18ae70005cf52d84e8dafe5dDan Williams else if ((pattern & PATTERN_COPY) 2347b61017822cdff9c18ae70005cf52d84e8dafe5dDan Williams && (diff & (PATTERN_COPY | PATTERN_OVERWRITE))) 2357b61017822cdff9c18ae70005cf52d84e8dafe5dDan Williams pr_warn("%s: dstbuf[0x%x] not copied! Expected %02x, got %02x\n", 2367b61017822cdff9c18ae70005cf52d84e8dafe5dDan Williams thread_name, index, expected, actual); 2377b61017822cdff9c18ae70005cf52d84e8dafe5dDan Williams else if (diff & PATTERN_SRC) 2387b61017822cdff9c18ae70005cf52d84e8dafe5dDan Williams pr_warn("%s: dstbuf[0x%x] was copied! Expected %02x, got %02x\n", 2397b61017822cdff9c18ae70005cf52d84e8dafe5dDan Williams thread_name, index, expected, actual); 2407b61017822cdff9c18ae70005cf52d84e8dafe5dDan Williams else 2417b61017822cdff9c18ae70005cf52d84e8dafe5dDan Williams pr_warn("%s: dstbuf[0x%x] mismatch! Expected %02x, got %02x\n", 2427b61017822cdff9c18ae70005cf52d84e8dafe5dDan Williams thread_name, index, expected, actual); 2437b61017822cdff9c18ae70005cf52d84e8dafe5dDan Williams} 2447b61017822cdff9c18ae70005cf52d84e8dafe5dDan Williams 2457b61017822cdff9c18ae70005cf52d84e8dafe5dDan Williamsstatic unsigned int dmatest_verify(u8 **bufs, unsigned int start, 2467b61017822cdff9c18ae70005cf52d84e8dafe5dDan Williams unsigned int end, unsigned int counter, u8 pattern, 2477b61017822cdff9c18ae70005cf52d84e8dafe5dDan Williams bool is_srcbuf) 2484a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen{ 2494a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen unsigned int i; 2504a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen unsigned int error_count = 0; 2514a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen u8 actual; 252b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams u8 expected; 253b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams u8 *buf; 254b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams unsigned int counter_orig = counter; 255b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams 256b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams for (; (buf = *bufs); bufs++) { 257b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams counter = counter_orig; 258b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams for (i = start; i < end; i++) { 259b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams actual = buf[i]; 260b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams expected = pattern | (~counter & PATTERN_COUNT_MASK); 261b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams if (actual != expected) { 2627b61017822cdff9c18ae70005cf52d84e8dafe5dDan Williams if (error_count < MAX_ERROR_COUNT) 2637b61017822cdff9c18ae70005cf52d84e8dafe5dDan Williams dmatest_mismatch(actual, pattern, i, 2647b61017822cdff9c18ae70005cf52d84e8dafe5dDan Williams counter, is_srcbuf); 265b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams error_count++; 266b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams } 267b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams counter++; 2684a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen } 2694a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen } 2704a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 27174b5c07a515b2986c9bdfe649213b8e358d32ad2Andy Shevchenko if (error_count > MAX_ERROR_COUNT) 2727b61017822cdff9c18ae70005cf52d84e8dafe5dDan Williams pr_warn("%s: %u errors suppressed\n", 27374b5c07a515b2986c9bdfe649213b8e358d32ad2Andy Shevchenko current->comm, error_count - MAX_ERROR_COUNT); 2744a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 2754a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen return error_count; 2764a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen} 2774a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 278adfa543e7314b36ac55a40019977de6e47946dd7Tejun Heo/* poor man's completion - we want to use wait_event_freezable() on it */ 279adfa543e7314b36ac55a40019977de6e47946dd7Tejun Heostruct dmatest_done { 280adfa543e7314b36ac55a40019977de6e47946dd7Tejun Heo bool done; 281adfa543e7314b36ac55a40019977de6e47946dd7Tejun Heo wait_queue_head_t *wait; 282adfa543e7314b36ac55a40019977de6e47946dd7Tejun Heo}; 283adfa543e7314b36ac55a40019977de6e47946dd7Tejun Heo 284adfa543e7314b36ac55a40019977de6e47946dd7Tejun Heostatic void dmatest_callback(void *arg) 285e44e0aa3cfa97cddff01704751a4b25151830c72Dan Williams{ 286adfa543e7314b36ac55a40019977de6e47946dd7Tejun Heo struct dmatest_done *done = arg; 287adfa543e7314b36ac55a40019977de6e47946dd7Tejun Heo 288adfa543e7314b36ac55a40019977de6e47946dd7Tejun Heo done->done = true; 289adfa543e7314b36ac55a40019977de6e47946dd7Tejun Heo wake_up_all(done->wait); 290e44e0aa3cfa97cddff01704751a4b25151830c72Dan Williams} 291e44e0aa3cfa97cddff01704751a4b25151830c72Dan Williams 292632fd28326c0cc7be9c51ea0d76d8bec39a695e9Andy Shevchenkostatic inline void unmap_src(struct device *dev, dma_addr_t *addr, size_t len, 293632fd28326c0cc7be9c51ea0d76d8bec39a695e9Andy Shevchenko unsigned int count) 294632fd28326c0cc7be9c51ea0d76d8bec39a695e9Andy Shevchenko{ 295632fd28326c0cc7be9c51ea0d76d8bec39a695e9Andy Shevchenko while (count--) 296632fd28326c0cc7be9c51ea0d76d8bec39a695e9Andy Shevchenko dma_unmap_single(dev, addr[count], len, DMA_TO_DEVICE); 297632fd28326c0cc7be9c51ea0d76d8bec39a695e9Andy Shevchenko} 298632fd28326c0cc7be9c51ea0d76d8bec39a695e9Andy Shevchenko 299632fd28326c0cc7be9c51ea0d76d8bec39a695e9Andy Shevchenkostatic inline void unmap_dst(struct device *dev, dma_addr_t *addr, size_t len, 300632fd28326c0cc7be9c51ea0d76d8bec39a695e9Andy Shevchenko unsigned int count) 301632fd28326c0cc7be9c51ea0d76d8bec39a695e9Andy Shevchenko{ 302632fd28326c0cc7be9c51ea0d76d8bec39a695e9Andy Shevchenko while (count--) 303632fd28326c0cc7be9c51ea0d76d8bec39a695e9Andy Shevchenko dma_unmap_single(dev, addr[count], len, DMA_BIDIRECTIONAL); 304632fd28326c0cc7be9c51ea0d76d8bec39a695e9Andy Shevchenko} 305632fd28326c0cc7be9c51ea0d76d8bec39a695e9Andy Shevchenko 3068be9e32b310cd8c4302991c8ff6692689c7d9d76Akinobu Mitastatic unsigned int min_odd(unsigned int x, unsigned int y) 3078be9e32b310cd8c4302991c8ff6692689c7d9d76Akinobu Mita{ 3088be9e32b310cd8c4302991c8ff6692689c7d9d76Akinobu Mita unsigned int val = min(x, y); 3098be9e32b310cd8c4302991c8ff6692689c7d9d76Akinobu Mita 3108be9e32b310cd8c4302991c8ff6692689c7d9d76Akinobu Mita return val % 2 ? val : val - 1; 3118be9e32b310cd8c4302991c8ff6692689c7d9d76Akinobu Mita} 3128be9e32b310cd8c4302991c8ff6692689c7d9d76Akinobu Mita 313872f05c6e9a37e9358fd58eb54deee7337863496Dan Williamsstatic void result(const char *err, unsigned int n, unsigned int src_off, 314872f05c6e9a37e9358fd58eb54deee7337863496Dan Williams unsigned int dst_off, unsigned int len, unsigned long data) 31595019c8c5af947f64e4a62e08a4a275bc36148eeAndy Shevchenko{ 316872f05c6e9a37e9358fd58eb54deee7337863496Dan Williams pr_info("%s: result #%u: '%s' with src_off=0x%x ""dst_off=0x%x len=0x%x (%lu)", 317872f05c6e9a37e9358fd58eb54deee7337863496Dan Williams current->comm, n, err, src_off, dst_off, len, data); 31895019c8c5af947f64e4a62e08a4a275bc36148eeAndy Shevchenko} 31995019c8c5af947f64e4a62e08a4a275bc36148eeAndy Shevchenko 320872f05c6e9a37e9358fd58eb54deee7337863496Dan Williamsstatic void dbg_result(const char *err, unsigned int n, unsigned int src_off, 321872f05c6e9a37e9358fd58eb54deee7337863496Dan Williams unsigned int dst_off, unsigned int len, 322872f05c6e9a37e9358fd58eb54deee7337863496Dan Williams unsigned long data) 32395019c8c5af947f64e4a62e08a4a275bc36148eeAndy Shevchenko{ 324872f05c6e9a37e9358fd58eb54deee7337863496Dan Williams pr_debug("%s: result #%u: '%s' with src_off=0x%x ""dst_off=0x%x len=0x%x (%lu)", 325872f05c6e9a37e9358fd58eb54deee7337863496Dan Williams current->comm, n, err, src_off, dst_off, len, data); 32695019c8c5af947f64e4a62e08a4a275bc36148eeAndy Shevchenko} 32795019c8c5af947f64e4a62e08a4a275bc36148eeAndy Shevchenko 3284a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen/* 3294a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen * This function repeatedly tests DMA transfers of various lengths and 330b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams * offsets for a given operation type until it is told to exit by 331b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams * kthread_stop(). There may be multiple threads running this function 332b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams * in parallel for a single channel, and there may be multiple channels 333b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams * being tested in parallel. 3344a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen * 3354a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen * Before each test, the source and destination buffer is initialized 3364a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen * with a known pattern. This pattern is different depending on 3374a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen * whether it's in an area which is supposed to be copied or 3384a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen * overwritten, and different in the source and destination buffers. 3394a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen * So if the DMA engine doesn't copy exactly what we tell it to copy, 3404a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen * we'll notice. 3414a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen */ 3424a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoenstatic int dmatest_func(void *data) 3434a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen{ 344adfa543e7314b36ac55a40019977de6e47946dd7Tejun Heo DECLARE_WAIT_QUEUE_HEAD_ONSTACK(done_wait); 3454a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen struct dmatest_thread *thread = data; 346adfa543e7314b36ac55a40019977de6e47946dd7Tejun Heo struct dmatest_done done = { .wait = &done_wait }; 347e03e93a976d0f0da63f02fd3384c4b99cac8d715Andy Shevchenko struct dmatest_info *info; 34815b8a8ea1a87313f1b46ea878c65942fd52147edAndy Shevchenko struct dmatest_params *params; 3494a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen struct dma_chan *chan; 3508be9e32b310cd8c4302991c8ff6692689c7d9d76Akinobu Mita struct dma_device *dev; 3514a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen unsigned int src_off, dst_off, len; 3524a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen unsigned int error_count; 3534a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen unsigned int failed_tests = 0; 3544a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen unsigned int total_tests = 0; 3554a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen dma_cookie_t cookie; 3564a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen enum dma_status status; 357b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams enum dma_ctrl_flags flags; 358945b5af3cedcdfed6d2d940e53cd19933bb57386Andy Shevchenko u8 *pq_coefs = NULL; 3594a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen int ret; 360b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams int src_cnt; 361b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams int dst_cnt; 362b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams int i; 3634a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 364adfa543e7314b36ac55a40019977de6e47946dd7Tejun Heo set_freezable(); 3654a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 3664a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen ret = -ENOMEM; 3674a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 3684a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen smp_rmb(); 369e03e93a976d0f0da63f02fd3384c4b99cac8d715Andy Shevchenko info = thread->info; 37015b8a8ea1a87313f1b46ea878c65942fd52147edAndy Shevchenko params = &info->params; 3714a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen chan = thread->chan; 3728be9e32b310cd8c4302991c8ff6692689c7d9d76Akinobu Mita dev = chan->device; 373b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams if (thread->type == DMA_MEMCPY) 374b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams src_cnt = dst_cnt = 1; 375b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams else if (thread->type == DMA_XOR) { 3768be9e32b310cd8c4302991c8ff6692689c7d9d76Akinobu Mita /* force odd to ensure dst = src */ 37715b8a8ea1a87313f1b46ea878c65942fd52147edAndy Shevchenko src_cnt = min_odd(params->xor_sources | 1, dev->max_xor); 378b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams dst_cnt = 1; 37958691d64c44ae41ddf098ecb31e9a994026e3cffDan Williams } else if (thread->type == DMA_PQ) { 3808be9e32b310cd8c4302991c8ff6692689c7d9d76Akinobu Mita /* force odd to ensure dst = src */ 38115b8a8ea1a87313f1b46ea878c65942fd52147edAndy Shevchenko src_cnt = min_odd(params->pq_sources | 1, dma_maxpq(dev, 0)); 38258691d64c44ae41ddf098ecb31e9a994026e3cffDan Williams dst_cnt = 2; 383945b5af3cedcdfed6d2d940e53cd19933bb57386Andy Shevchenko 38415b8a8ea1a87313f1b46ea878c65942fd52147edAndy Shevchenko pq_coefs = kmalloc(params->pq_sources+1, GFP_KERNEL); 385945b5af3cedcdfed6d2d940e53cd19933bb57386Andy Shevchenko if (!pq_coefs) 386945b5af3cedcdfed6d2d940e53cd19933bb57386Andy Shevchenko goto err_thread_type; 387945b5af3cedcdfed6d2d940e53cd19933bb57386Andy Shevchenko 38894de648d72c8bc833590523f22386d4babbea988Anatolij Gustschin for (i = 0; i < src_cnt; i++) 38958691d64c44ae41ddf098ecb31e9a994026e3cffDan Williams pq_coefs[i] = 1; 390b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams } else 391945b5af3cedcdfed6d2d940e53cd19933bb57386Andy Shevchenko goto err_thread_type; 392b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams 393b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams thread->srcs = kcalloc(src_cnt+1, sizeof(u8 *), GFP_KERNEL); 394b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams if (!thread->srcs) 395b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams goto err_srcs; 396b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams for (i = 0; i < src_cnt; i++) { 39715b8a8ea1a87313f1b46ea878c65942fd52147edAndy Shevchenko thread->srcs[i] = kmalloc(params->buf_size, GFP_KERNEL); 398b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams if (!thread->srcs[i]) 399b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams goto err_srcbuf; 400b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams } 401b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams thread->srcs[i] = NULL; 402b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams 403b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams thread->dsts = kcalloc(dst_cnt+1, sizeof(u8 *), GFP_KERNEL); 404b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams if (!thread->dsts) 405b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams goto err_dsts; 406b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams for (i = 0; i < dst_cnt; i++) { 40715b8a8ea1a87313f1b46ea878c65942fd52147edAndy Shevchenko thread->dsts[i] = kmalloc(params->buf_size, GFP_KERNEL); 408b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams if (!thread->dsts[i]) 409b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams goto err_dstbuf; 410b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams } 411b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams thread->dsts[i] = NULL; 412b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams 413e44e0aa3cfa97cddff01704751a4b25151830c72Dan Williams set_user_nice(current, 10); 414e44e0aa3cfa97cddff01704751a4b25151830c72Dan Williams 415b203bd3f6b9c3db3b1979c2ff79bb2b9be8f03a3Ira Snyder /* 416d1cab34c039584ebe76b04d2f2109e0d87d344e1Bartlomiej Zolnierkiewicz * src and dst buffers are freed by ourselves below 417b203bd3f6b9c3db3b1979c2ff79bb2b9be8f03a3Ira Snyder */ 4180776ae7b89782124ddd72eafe0b1e0fdcdabe32eBartlomiej Zolnierkiewicz flags = DMA_CTRL_ACK | DMA_PREP_INTERRUPT; 4194a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 4200a2ff57d6fba92842272889b4bca447344cd9d36Nicolas Ferre while (!kthread_should_stop() 42115b8a8ea1a87313f1b46ea878c65942fd52147edAndy Shevchenko && !(params->iterations && total_tests >= params->iterations)) { 422b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams struct dma_async_tx_descriptor *tx = NULL; 423b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams dma_addr_t dma_srcs[src_cnt]; 424b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams dma_addr_t dma_dsts[dst_cnt]; 42583544ae9f3991bfc7d5e0fe9a3008cd05a8d57b7Dan Williams u8 align = 0; 426d86be86e9aab221089d72399072511f13fe2a771Atsushi Nemoto 4274a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen total_tests++; 4284a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 42983544ae9f3991bfc7d5e0fe9a3008cd05a8d57b7Dan Williams /* honor alignment restrictions */ 43083544ae9f3991bfc7d5e0fe9a3008cd05a8d57b7Dan Williams if (thread->type == DMA_MEMCPY) 43183544ae9f3991bfc7d5e0fe9a3008cd05a8d57b7Dan Williams align = dev->copy_align; 43283544ae9f3991bfc7d5e0fe9a3008cd05a8d57b7Dan Williams else if (thread->type == DMA_XOR) 43383544ae9f3991bfc7d5e0fe9a3008cd05a8d57b7Dan Williams align = dev->xor_align; 43483544ae9f3991bfc7d5e0fe9a3008cd05a8d57b7Dan Williams else if (thread->type == DMA_PQ) 43583544ae9f3991bfc7d5e0fe9a3008cd05a8d57b7Dan Williams align = dev->pq_align; 43683544ae9f3991bfc7d5e0fe9a3008cd05a8d57b7Dan Williams 43715b8a8ea1a87313f1b46ea878c65942fd52147edAndy Shevchenko if (1 << align > params->buf_size) { 438cfe4f2751ef1a5390b56c5d263f90b6ff138ba31Guennadi Liakhovetski pr_err("%u-byte buffer too small for %d-byte alignment\n", 43915b8a8ea1a87313f1b46ea878c65942fd52147edAndy Shevchenko params->buf_size, 1 << align); 440cfe4f2751ef1a5390b56c5d263f90b6ff138ba31Guennadi Liakhovetski break; 441cfe4f2751ef1a5390b56c5d263f90b6ff138ba31Guennadi Liakhovetski } 442cfe4f2751ef1a5390b56c5d263f90b6ff138ba31Guennadi Liakhovetski 443e3b9c347316fe243bea6abd08681050c43ca22eeDan Williams if (params->noverify) { 444e3b9c347316fe243bea6abd08681050c43ca22eeDan Williams len = params->buf_size; 445e3b9c347316fe243bea6abd08681050c43ca22eeDan Williams src_off = 0; 446e3b9c347316fe243bea6abd08681050c43ca22eeDan Williams dst_off = 0; 447e3b9c347316fe243bea6abd08681050c43ca22eeDan Williams } else { 448e3b9c347316fe243bea6abd08681050c43ca22eeDan Williams len = dmatest_random() % params->buf_size + 1; 449e3b9c347316fe243bea6abd08681050c43ca22eeDan Williams len = (len >> align) << align; 450e3b9c347316fe243bea6abd08681050c43ca22eeDan Williams if (!len) 451e3b9c347316fe243bea6abd08681050c43ca22eeDan Williams len = 1 << align; 452e3b9c347316fe243bea6abd08681050c43ca22eeDan Williams src_off = dmatest_random() % (params->buf_size - len + 1); 453e3b9c347316fe243bea6abd08681050c43ca22eeDan Williams dst_off = dmatest_random() % (params->buf_size - len + 1); 454e3b9c347316fe243bea6abd08681050c43ca22eeDan Williams 455e3b9c347316fe243bea6abd08681050c43ca22eeDan Williams src_off = (src_off >> align) << align; 456e3b9c347316fe243bea6abd08681050c43ca22eeDan Williams dst_off = (dst_off >> align) << align; 457e3b9c347316fe243bea6abd08681050c43ca22eeDan Williams 458e3b9c347316fe243bea6abd08681050c43ca22eeDan Williams dmatest_init_srcs(thread->srcs, src_off, len, 459e3b9c347316fe243bea6abd08681050c43ca22eeDan Williams params->buf_size); 460e3b9c347316fe243bea6abd08681050c43ca22eeDan Williams dmatest_init_dsts(thread->dsts, dst_off, len, 461e3b9c347316fe243bea6abd08681050c43ca22eeDan Williams params->buf_size); 462e3b9c347316fe243bea6abd08681050c43ca22eeDan Williams } 463e3b9c347316fe243bea6abd08681050c43ca22eeDan Williams 46483544ae9f3991bfc7d5e0fe9a3008cd05a8d57b7Dan Williams len = (len >> align) << align; 465cfe4f2751ef1a5390b56c5d263f90b6ff138ba31Guennadi Liakhovetski if (!len) 466cfe4f2751ef1a5390b56c5d263f90b6ff138ba31Guennadi Liakhovetski len = 1 << align; 4674a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 468b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams for (i = 0; i < src_cnt; i++) { 469b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams u8 *buf = thread->srcs[i] + src_off; 470b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams 471b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams dma_srcs[i] = dma_map_single(dev->dev, buf, len, 472b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams DMA_TO_DEVICE); 473afde3be121efcc658e26f8cc71ead04af96d38f9Andy Shevchenko ret = dma_mapping_error(dev->dev, dma_srcs[i]); 474afde3be121efcc658e26f8cc71ead04af96d38f9Andy Shevchenko if (ret) { 475afde3be121efcc658e26f8cc71ead04af96d38f9Andy Shevchenko unmap_src(dev->dev, dma_srcs, len, i); 476872f05c6e9a37e9358fd58eb54deee7337863496Dan Williams result("src mapping error", total_tests, 477872f05c6e9a37e9358fd58eb54deee7337863496Dan Williams src_off, dst_off, len, ret); 478afde3be121efcc658e26f8cc71ead04af96d38f9Andy Shevchenko failed_tests++; 479afde3be121efcc658e26f8cc71ead04af96d38f9Andy Shevchenko continue; 480afde3be121efcc658e26f8cc71ead04af96d38f9Andy Shevchenko } 481b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams } 482d86be86e9aab221089d72399072511f13fe2a771Atsushi Nemoto /* map with DMA_BIDIRECTIONAL to force writeback/invalidate */ 483b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams for (i = 0; i < dst_cnt; i++) { 484b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams dma_dsts[i] = dma_map_single(dev->dev, thread->dsts[i], 48515b8a8ea1a87313f1b46ea878c65942fd52147edAndy Shevchenko params->buf_size, 486b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams DMA_BIDIRECTIONAL); 487afde3be121efcc658e26f8cc71ead04af96d38f9Andy Shevchenko ret = dma_mapping_error(dev->dev, dma_dsts[i]); 488afde3be121efcc658e26f8cc71ead04af96d38f9Andy Shevchenko if (ret) { 489afde3be121efcc658e26f8cc71ead04af96d38f9Andy Shevchenko unmap_src(dev->dev, dma_srcs, len, src_cnt); 49015b8a8ea1a87313f1b46ea878c65942fd52147edAndy Shevchenko unmap_dst(dev->dev, dma_dsts, params->buf_size, 49115b8a8ea1a87313f1b46ea878c65942fd52147edAndy Shevchenko i); 492872f05c6e9a37e9358fd58eb54deee7337863496Dan Williams result("dst mapping error", total_tests, 493872f05c6e9a37e9358fd58eb54deee7337863496Dan Williams src_off, dst_off, len, ret); 494afde3be121efcc658e26f8cc71ead04af96d38f9Andy Shevchenko failed_tests++; 495afde3be121efcc658e26f8cc71ead04af96d38f9Andy Shevchenko continue; 496afde3be121efcc658e26f8cc71ead04af96d38f9Andy Shevchenko } 497b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams } 498b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams 499b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams if (thread->type == DMA_MEMCPY) 500b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams tx = dev->device_prep_dma_memcpy(chan, 501b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams dma_dsts[0] + dst_off, 502b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams dma_srcs[0], len, 503b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams flags); 504b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams else if (thread->type == DMA_XOR) 505b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams tx = dev->device_prep_dma_xor(chan, 506b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams dma_dsts[0] + dst_off, 50767b9124f734b22b30d9adf18c39fe795e2901070Dan Williams dma_srcs, src_cnt, 508b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams len, flags); 50958691d64c44ae41ddf098ecb31e9a994026e3cffDan Williams else if (thread->type == DMA_PQ) { 51058691d64c44ae41ddf098ecb31e9a994026e3cffDan Williams dma_addr_t dma_pq[dst_cnt]; 51158691d64c44ae41ddf098ecb31e9a994026e3cffDan Williams 51258691d64c44ae41ddf098ecb31e9a994026e3cffDan Williams for (i = 0; i < dst_cnt; i++) 51358691d64c44ae41ddf098ecb31e9a994026e3cffDan Williams dma_pq[i] = dma_dsts[i] + dst_off; 51458691d64c44ae41ddf098ecb31e9a994026e3cffDan Williams tx = dev->device_prep_dma_pq(chan, dma_pq, dma_srcs, 51594de648d72c8bc833590523f22386d4babbea988Anatolij Gustschin src_cnt, pq_coefs, 51658691d64c44ae41ddf098ecb31e9a994026e3cffDan Williams len, flags); 51758691d64c44ae41ddf098ecb31e9a994026e3cffDan Williams } 518d86be86e9aab221089d72399072511f13fe2a771Atsushi Nemoto 519d86be86e9aab221089d72399072511f13fe2a771Atsushi Nemoto if (!tx) { 520632fd28326c0cc7be9c51ea0d76d8bec39a695e9Andy Shevchenko unmap_src(dev->dev, dma_srcs, len, src_cnt); 52115b8a8ea1a87313f1b46ea878c65942fd52147edAndy Shevchenko unmap_dst(dev->dev, dma_dsts, params->buf_size, 52215b8a8ea1a87313f1b46ea878c65942fd52147edAndy Shevchenko dst_cnt); 523872f05c6e9a37e9358fd58eb54deee7337863496Dan Williams result("prep error", total_tests, src_off, 524872f05c6e9a37e9358fd58eb54deee7337863496Dan Williams dst_off, len, ret); 525d86be86e9aab221089d72399072511f13fe2a771Atsushi Nemoto msleep(100); 526d86be86e9aab221089d72399072511f13fe2a771Atsushi Nemoto failed_tests++; 527d86be86e9aab221089d72399072511f13fe2a771Atsushi Nemoto continue; 528d86be86e9aab221089d72399072511f13fe2a771Atsushi Nemoto } 529e44e0aa3cfa97cddff01704751a4b25151830c72Dan Williams 530adfa543e7314b36ac55a40019977de6e47946dd7Tejun Heo done.done = false; 531e44e0aa3cfa97cddff01704751a4b25151830c72Dan Williams tx->callback = dmatest_callback; 532adfa543e7314b36ac55a40019977de6e47946dd7Tejun Heo tx->callback_param = &done; 533d86be86e9aab221089d72399072511f13fe2a771Atsushi Nemoto cookie = tx->tx_submit(tx); 534d86be86e9aab221089d72399072511f13fe2a771Atsushi Nemoto 5354a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen if (dma_submit_error(cookie)) { 536872f05c6e9a37e9358fd58eb54deee7337863496Dan Williams result("submit error", total_tests, src_off, 537872f05c6e9a37e9358fd58eb54deee7337863496Dan Williams dst_off, len, ret); 5384a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen msleep(100); 5394a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen failed_tests++; 5404a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen continue; 5414a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen } 542b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams dma_async_issue_pending(chan); 5434a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 544bcc567e3115055a9cc256183d72864f01286be22Andy Shevchenko wait_event_freezable_timeout(done_wait, done.done, 54515b8a8ea1a87313f1b46ea878c65942fd52147edAndy Shevchenko msecs_to_jiffies(params->timeout)); 546981ed70d8e4faf3689dbf3c48868a31d5b004d7aGuennadi Liakhovetski 547e44e0aa3cfa97cddff01704751a4b25151830c72Dan Williams status = dma_async_is_tx_complete(chan, cookie, NULL, NULL); 5484a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 549adfa543e7314b36ac55a40019977de6e47946dd7Tejun Heo if (!done.done) { 550adfa543e7314b36ac55a40019977de6e47946dd7Tejun Heo /* 551adfa543e7314b36ac55a40019977de6e47946dd7Tejun Heo * We're leaving the timed out dma operation with 552adfa543e7314b36ac55a40019977de6e47946dd7Tejun Heo * dangling pointer to done_wait. To make this 553adfa543e7314b36ac55a40019977de6e47946dd7Tejun Heo * correct, we'll need to allocate wait_done for 554adfa543e7314b36ac55a40019977de6e47946dd7Tejun Heo * each test iteration and perform "who's gonna 555adfa543e7314b36ac55a40019977de6e47946dd7Tejun Heo * free it this time?" dancing. For now, just 556adfa543e7314b36ac55a40019977de6e47946dd7Tejun Heo * leave it dangling. 557adfa543e7314b36ac55a40019977de6e47946dd7Tejun Heo */ 558872f05c6e9a37e9358fd58eb54deee7337863496Dan Williams result("test timed out", total_tests, src_off, dst_off, 559872f05c6e9a37e9358fd58eb54deee7337863496Dan Williams len, 0); 560e44e0aa3cfa97cddff01704751a4b25151830c72Dan Williams failed_tests++; 561e44e0aa3cfa97cddff01704751a4b25151830c72Dan Williams continue; 562e44e0aa3cfa97cddff01704751a4b25151830c72Dan Williams } else if (status != DMA_SUCCESS) { 563872f05c6e9a37e9358fd58eb54deee7337863496Dan Williams result(status == DMA_ERROR ? 564872f05c6e9a37e9358fd58eb54deee7337863496Dan Williams "completion error status" : 565872f05c6e9a37e9358fd58eb54deee7337863496Dan Williams "completion busy status", total_tests, src_off, 566872f05c6e9a37e9358fd58eb54deee7337863496Dan Williams dst_off, len, ret); 5674a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen failed_tests++; 5684a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen continue; 5694a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen } 570e44e0aa3cfa97cddff01704751a4b25151830c72Dan Williams 571d1cab34c039584ebe76b04d2f2109e0d87d344e1Bartlomiej Zolnierkiewicz /* Unmap by myself */ 572d1cab34c039584ebe76b04d2f2109e0d87d344e1Bartlomiej Zolnierkiewicz unmap_src(dev->dev, dma_srcs, len, src_cnt); 57315b8a8ea1a87313f1b46ea878c65942fd52147edAndy Shevchenko unmap_dst(dev->dev, dma_dsts, params->buf_size, dst_cnt); 5744a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 575e3b9c347316fe243bea6abd08681050c43ca22eeDan Williams if (params->noverify) { 576e3b9c347316fe243bea6abd08681050c43ca22eeDan Williams dbg_result("test passed", total_tests, src_off, dst_off, 577e3b9c347316fe243bea6abd08681050c43ca22eeDan Williams len, 0); 578e3b9c347316fe243bea6abd08681050c43ca22eeDan Williams continue; 579e3b9c347316fe243bea6abd08681050c43ca22eeDan Williams } 5804a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 581872f05c6e9a37e9358fd58eb54deee7337863496Dan Williams pr_debug("%s: verifying source buffer...\n", current->comm); 582e3b9c347316fe243bea6abd08681050c43ca22eeDan Williams error_count = dmatest_verify(thread->srcs, 0, src_off, 5834a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 0, PATTERN_SRC, true); 5847b61017822cdff9c18ae70005cf52d84e8dafe5dDan Williams error_count += dmatest_verify(thread->srcs, src_off, 5857b61017822cdff9c18ae70005cf52d84e8dafe5dDan Williams src_off + len, src_off, 5867b61017822cdff9c18ae70005cf52d84e8dafe5dDan Williams PATTERN_SRC | PATTERN_COPY, true); 5877b61017822cdff9c18ae70005cf52d84e8dafe5dDan Williams error_count += dmatest_verify(thread->srcs, src_off + len, 5887b61017822cdff9c18ae70005cf52d84e8dafe5dDan Williams params->buf_size, src_off + len, 5897b61017822cdff9c18ae70005cf52d84e8dafe5dDan Williams PATTERN_SRC, true); 5907b61017822cdff9c18ae70005cf52d84e8dafe5dDan Williams 591872f05c6e9a37e9358fd58eb54deee7337863496Dan Williams pr_debug("%s: verifying dest buffer...\n", current->comm); 5927b61017822cdff9c18ae70005cf52d84e8dafe5dDan Williams error_count += dmatest_verify(thread->dsts, 0, dst_off, 5934a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 0, PATTERN_DST, false); 5947b61017822cdff9c18ae70005cf52d84e8dafe5dDan Williams error_count += dmatest_verify(thread->dsts, dst_off, 5957b61017822cdff9c18ae70005cf52d84e8dafe5dDan Williams dst_off + len, src_off, 5967b61017822cdff9c18ae70005cf52d84e8dafe5dDan Williams PATTERN_SRC | PATTERN_COPY, false); 5977b61017822cdff9c18ae70005cf52d84e8dafe5dDan Williams error_count += dmatest_verify(thread->dsts, dst_off + len, 5987b61017822cdff9c18ae70005cf52d84e8dafe5dDan Williams params->buf_size, dst_off + len, 5997b61017822cdff9c18ae70005cf52d84e8dafe5dDan Williams PATTERN_DST, false); 6004a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 6014a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen if (error_count) { 602872f05c6e9a37e9358fd58eb54deee7337863496Dan Williams result("data error", total_tests, src_off, dst_off, 603872f05c6e9a37e9358fd58eb54deee7337863496Dan Williams len, error_count); 6044a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen failed_tests++; 6054a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen } else { 606872f05c6e9a37e9358fd58eb54deee7337863496Dan Williams dbg_result("test passed", total_tests, src_off, dst_off, 607872f05c6e9a37e9358fd58eb54deee7337863496Dan Williams len, 0); 6084a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen } 6094a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen } 6104a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 6114a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen ret = 0; 612b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams for (i = 0; thread->dsts[i]; i++) 613b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams kfree(thread->dsts[i]); 6144a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoenerr_dstbuf: 615b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams kfree(thread->dsts); 616b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williamserr_dsts: 617b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams for (i = 0; thread->srcs[i]; i++) 618b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams kfree(thread->srcs[i]); 6194a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoenerr_srcbuf: 620b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams kfree(thread->srcs); 621b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williamserr_srcs: 622945b5af3cedcdfed6d2d940e53cd19933bb57386Andy Shevchenko kfree(pq_coefs); 623945b5af3cedcdfed6d2d940e53cd19933bb57386Andy Shevchenkoerr_thread_type: 624872f05c6e9a37e9358fd58eb54deee7337863496Dan Williams pr_info("%s: terminating after %u tests, %u failures (status %d)\n", 625872f05c6e9a37e9358fd58eb54deee7337863496Dan Williams current->comm, total_tests, failed_tests, ret); 6260a2ff57d6fba92842272889b4bca447344cd9d36Nicolas Ferre 6279704efaa52ab18eb3504c4e0bc421c1d01b7981aViresh Kumar /* terminate all transfers on specified channels */ 6285e034f7b659be9d94e64aaaa985ab530dd847fdbShiraz Hashim if (ret) 6295e034f7b659be9d94e64aaaa985ab530dd847fdbShiraz Hashim dmaengine_terminate_all(chan); 6305e034f7b659be9d94e64aaaa985ab530dd847fdbShiraz Hashim 6313e5ccd866fdf3a1e1d4d2c08c81f861ad6798d32Andy Shevchenko thread->done = true; 6323e5ccd866fdf3a1e1d4d2c08c81f861ad6798d32Andy Shevchenko 63315b8a8ea1a87313f1b46ea878c65942fd52147edAndy Shevchenko if (params->iterations > 0) 6340a2ff57d6fba92842272889b4bca447344cd9d36Nicolas Ferre while (!kthread_should_stop()) { 635b953df7c70740cd7593072ebec77a8f658505630Yong Zhang DECLARE_WAIT_QUEUE_HEAD_ONSTACK(wait_dmatest_exit); 6360a2ff57d6fba92842272889b4bca447344cd9d36Nicolas Ferre interruptible_sleep_on(&wait_dmatest_exit); 6370a2ff57d6fba92842272889b4bca447344cd9d36Nicolas Ferre } 6380a2ff57d6fba92842272889b4bca447344cd9d36Nicolas Ferre 6394a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen return ret; 6404a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen} 6414a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 6424a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoenstatic void dmatest_cleanup_channel(struct dmatest_chan *dtc) 6434a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen{ 6444a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen struct dmatest_thread *thread; 6454a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen struct dmatest_thread *_thread; 6464a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen int ret; 6474a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 6484a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen list_for_each_entry_safe(thread, _thread, &dtc->threads, node) { 6494a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen ret = kthread_stop(thread->task); 6500adff800662f52d0ffc3e420db231769cb3fff13Dan Williams pr_debug("thread %s exited with status %d\n", 6510adff800662f52d0ffc3e420db231769cb3fff13Dan Williams thread->task->comm, ret); 6524a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen list_del(&thread->node); 6534a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen kfree(thread); 6544a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen } 6559704efaa52ab18eb3504c4e0bc421c1d01b7981aViresh Kumar 6569704efaa52ab18eb3504c4e0bc421c1d01b7981aViresh Kumar /* terminate all transfers on specified channels */ 657944ea4dd38b8575e30a5699633c81945bff1864dJon Mason dmaengine_terminate_all(dtc->chan); 6589704efaa52ab18eb3504c4e0bc421c1d01b7981aViresh Kumar 6594a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen kfree(dtc); 6604a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen} 6614a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 662e03e93a976d0f0da63f02fd3384c4b99cac8d715Andy Shevchenkostatic int dmatest_add_threads(struct dmatest_info *info, 663e03e93a976d0f0da63f02fd3384c4b99cac8d715Andy Shevchenko struct dmatest_chan *dtc, enum dma_transaction_type type) 6644a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen{ 66515b8a8ea1a87313f1b46ea878c65942fd52147edAndy Shevchenko struct dmatest_params *params = &info->params; 666b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams struct dmatest_thread *thread; 667b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams struct dma_chan *chan = dtc->chan; 668b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams char *op; 669b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams unsigned int i; 6704a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 671b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams if (type == DMA_MEMCPY) 672b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams op = "copy"; 673b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams else if (type == DMA_XOR) 674b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams op = "xor"; 67558691d64c44ae41ddf098ecb31e9a994026e3cffDan Williams else if (type == DMA_PQ) 67658691d64c44ae41ddf098ecb31e9a994026e3cffDan Williams op = "pq"; 677b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams else 678b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams return -EINVAL; 6794a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 68015b8a8ea1a87313f1b46ea878c65942fd52147edAndy Shevchenko for (i = 0; i < params->threads_per_chan; i++) { 6814a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen thread = kzalloc(sizeof(struct dmatest_thread), GFP_KERNEL); 6824a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen if (!thread) { 6830adff800662f52d0ffc3e420db231769cb3fff13Dan Williams pr_warn("No memory for %s-%s%u\n", 6840adff800662f52d0ffc3e420db231769cb3fff13Dan Williams dma_chan_name(chan), op, i); 6854a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen break; 6864a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen } 687e03e93a976d0f0da63f02fd3384c4b99cac8d715Andy Shevchenko thread->info = info; 6884a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen thread->chan = dtc->chan; 689b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams thread->type = type; 6904a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen smp_wmb(); 691b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams thread->task = kthread_run(dmatest_func, thread, "%s-%s%u", 692b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams dma_chan_name(chan), op, i); 6934a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen if (IS_ERR(thread->task)) { 6940adff800662f52d0ffc3e420db231769cb3fff13Dan Williams pr_warn("Failed to run thread %s-%s%u\n", 6950adff800662f52d0ffc3e420db231769cb3fff13Dan Williams dma_chan_name(chan), op, i); 6964a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen kfree(thread); 6974a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen break; 6984a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen } 6994a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 7004a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen /* srcbuf and dstbuf are allocated by the thread itself */ 7014a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 7024a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen list_add_tail(&thread->node, &dtc->threads); 7034a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen } 7044a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 705b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams return i; 706b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams} 707b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams 708e03e93a976d0f0da63f02fd3384c4b99cac8d715Andy Shevchenkostatic int dmatest_add_channel(struct dmatest_info *info, 709e03e93a976d0f0da63f02fd3384c4b99cac8d715Andy Shevchenko struct dma_chan *chan) 710b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams{ 711b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams struct dmatest_chan *dtc; 712b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams struct dma_device *dma_dev = chan->device; 713b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams unsigned int thread_count = 0; 714b9033e682e86f3c6a66763f9b6a3935c5c64e145Kulikov Vasiliy int cnt; 715b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams 716b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams dtc = kmalloc(sizeof(struct dmatest_chan), GFP_KERNEL); 717b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams if (!dtc) { 7180adff800662f52d0ffc3e420db231769cb3fff13Dan Williams pr_warn("No memory for %s\n", dma_chan_name(chan)); 719b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams return -ENOMEM; 720b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams } 721b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams 722b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams dtc->chan = chan; 723b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams INIT_LIST_HEAD(&dtc->threads); 724b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams 725b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams if (dma_has_cap(DMA_MEMCPY, dma_dev->cap_mask)) { 726e03e93a976d0f0da63f02fd3384c4b99cac8d715Andy Shevchenko cnt = dmatest_add_threads(info, dtc, DMA_MEMCPY); 727f1aef8b6e6abf32a3a269542f95a19e2cb319f6cNicolas Ferre thread_count += cnt > 0 ? cnt : 0; 728b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams } 729b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams if (dma_has_cap(DMA_XOR, dma_dev->cap_mask)) { 730e03e93a976d0f0da63f02fd3384c4b99cac8d715Andy Shevchenko cnt = dmatest_add_threads(info, dtc, DMA_XOR); 731f1aef8b6e6abf32a3a269542f95a19e2cb319f6cNicolas Ferre thread_count += cnt > 0 ? cnt : 0; 732b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams } 73358691d64c44ae41ddf098ecb31e9a994026e3cffDan Williams if (dma_has_cap(DMA_PQ, dma_dev->cap_mask)) { 734e03e93a976d0f0da63f02fd3384c4b99cac8d715Andy Shevchenko cnt = dmatest_add_threads(info, dtc, DMA_PQ); 735d07a74a546981a09ba490936645fbf0d1340b96cDr. David Alan Gilbert thread_count += cnt > 0 ? cnt : 0; 73658691d64c44ae41ddf098ecb31e9a994026e3cffDan Williams } 737b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams 7380adff800662f52d0ffc3e420db231769cb3fff13Dan Williams pr_info("Started %u threads using %s\n", 739b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams thread_count, dma_chan_name(chan)); 7404a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 741838cc704ce5c8ab2a6d64d1324e37e040fcae3d8Andy Shevchenko list_add_tail(&dtc->node, &info->channels); 742838cc704ce5c8ab2a6d64d1324e37e040fcae3d8Andy Shevchenko info->nr_channels++; 7434a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 74433df8ca068123457db56c316946a3c0e4ef787d6Dan Williams return 0; 7454a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen} 7464a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 7477dd602510128d7a64b11ff3b7d4f30ac8e3946ceDan Williamsstatic bool filter(struct dma_chan *chan, void *param) 7484a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen{ 74915b8a8ea1a87313f1b46ea878c65942fd52147edAndy Shevchenko struct dmatest_params *params = param; 750e03e93a976d0f0da63f02fd3384c4b99cac8d715Andy Shevchenko 75115b8a8ea1a87313f1b46ea878c65942fd52147edAndy Shevchenko if (!dmatest_match_channel(params, chan) || 75215b8a8ea1a87313f1b46ea878c65942fd52147edAndy Shevchenko !dmatest_match_device(params, chan->device)) 7537dd602510128d7a64b11ff3b7d4f30ac8e3946ceDan Williams return false; 75433df8ca068123457db56c316946a3c0e4ef787d6Dan Williams else 7557dd602510128d7a64b11ff3b7d4f30ac8e3946ceDan Williams return true; 7564a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen} 7574a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 758a9e554957de406d6adc581731f571b8a1503f6b0Dan Williamsstatic void request_channels(struct dmatest_info *info, 759a9e554957de406d6adc581731f571b8a1503f6b0Dan Williams enum dma_transaction_type type) 7604a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen{ 76133df8ca068123457db56c316946a3c0e4ef787d6Dan Williams dma_cap_mask_t mask; 762a310d037b8d06755c62bb4878c00d19490af5550Dan Williams 76333df8ca068123457db56c316946a3c0e4ef787d6Dan Williams dma_cap_zero(mask); 764a9e554957de406d6adc581731f571b8a1503f6b0Dan Williams dma_cap_set(type, mask); 76533df8ca068123457db56c316946a3c0e4ef787d6Dan Williams for (;;) { 766a9e554957de406d6adc581731f571b8a1503f6b0Dan Williams struct dmatest_params *params = &info->params; 767a9e554957de406d6adc581731f571b8a1503f6b0Dan Williams struct dma_chan *chan; 768a9e554957de406d6adc581731f571b8a1503f6b0Dan Williams 76915b8a8ea1a87313f1b46ea878c65942fd52147edAndy Shevchenko chan = dma_request_channel(mask, filter, params); 77033df8ca068123457db56c316946a3c0e4ef787d6Dan Williams if (chan) { 771a9e554957de406d6adc581731f571b8a1503f6b0Dan Williams if (dmatest_add_channel(info, chan)) { 77233df8ca068123457db56c316946a3c0e4ef787d6Dan Williams dma_release_channel(chan); 77333df8ca068123457db56c316946a3c0e4ef787d6Dan Williams break; /* add_channel failed, punt */ 77433df8ca068123457db56c316946a3c0e4ef787d6Dan Williams } 77533df8ca068123457db56c316946a3c0e4ef787d6Dan Williams } else 77633df8ca068123457db56c316946a3c0e4ef787d6Dan Williams break; /* no more channels available */ 77715b8a8ea1a87313f1b46ea878c65942fd52147edAndy Shevchenko if (params->max_channels && 77815b8a8ea1a87313f1b46ea878c65942fd52147edAndy Shevchenko info->nr_channels >= params->max_channels) 77933df8ca068123457db56c316946a3c0e4ef787d6Dan Williams break; /* we have all we need */ 78033df8ca068123457db56c316946a3c0e4ef787d6Dan Williams } 7814a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen} 7824a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 783a9e554957de406d6adc581731f571b8a1503f6b0Dan Williamsstatic void run_threaded_test(struct dmatest_info *info) 784a9e554957de406d6adc581731f571b8a1503f6b0Dan Williams{ 785a9e554957de406d6adc581731f571b8a1503f6b0Dan Williams struct dmatest_params *params = &info->params; 786a9e554957de406d6adc581731f571b8a1503f6b0Dan Williams 787a9e554957de406d6adc581731f571b8a1503f6b0Dan Williams /* Copy test parameters */ 788a9e554957de406d6adc581731f571b8a1503f6b0Dan Williams params->buf_size = test_buf_size; 789a9e554957de406d6adc581731f571b8a1503f6b0Dan Williams strlcpy(params->channel, strim(test_channel), sizeof(params->channel)); 790a9e554957de406d6adc581731f571b8a1503f6b0Dan Williams strlcpy(params->device, strim(test_device), sizeof(params->device)); 791a9e554957de406d6adc581731f571b8a1503f6b0Dan Williams params->threads_per_chan = threads_per_chan; 792a9e554957de406d6adc581731f571b8a1503f6b0Dan Williams params->max_channels = max_channels; 793a9e554957de406d6adc581731f571b8a1503f6b0Dan Williams params->iterations = iterations; 794a9e554957de406d6adc581731f571b8a1503f6b0Dan Williams params->xor_sources = xor_sources; 795a9e554957de406d6adc581731f571b8a1503f6b0Dan Williams params->pq_sources = pq_sources; 796a9e554957de406d6adc581731f571b8a1503f6b0Dan Williams params->timeout = timeout; 797e3b9c347316fe243bea6abd08681050c43ca22eeDan Williams params->noverify = noverify; 798a9e554957de406d6adc581731f571b8a1503f6b0Dan Williams 799a9e554957de406d6adc581731f571b8a1503f6b0Dan Williams request_channels(info, DMA_MEMCPY); 800a9e554957de406d6adc581731f571b8a1503f6b0Dan Williams request_channels(info, DMA_XOR); 801a9e554957de406d6adc581731f571b8a1503f6b0Dan Williams request_channels(info, DMA_PQ); 802a9e554957de406d6adc581731f571b8a1503f6b0Dan Williams} 803851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko 804a310d037b8d06755c62bb4878c00d19490af5550Dan Williamsstatic void stop_threaded_test(struct dmatest_info *info) 8054a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen{ 80633df8ca068123457db56c316946a3c0e4ef787d6Dan Williams struct dmatest_chan *dtc, *_dtc; 8077cbd4877e5b167b56a3d6033b926a9f925186e12Dan Williams struct dma_chan *chan; 80833df8ca068123457db56c316946a3c0e4ef787d6Dan Williams 809838cc704ce5c8ab2a6d64d1324e37e040fcae3d8Andy Shevchenko list_for_each_entry_safe(dtc, _dtc, &info->channels, node) { 81033df8ca068123457db56c316946a3c0e4ef787d6Dan Williams list_del(&dtc->node); 8117cbd4877e5b167b56a3d6033b926a9f925186e12Dan Williams chan = dtc->chan; 81233df8ca068123457db56c316946a3c0e4ef787d6Dan Williams dmatest_cleanup_channel(dtc); 8130adff800662f52d0ffc3e420db231769cb3fff13Dan Williams pr_debug("dropped channel %s\n", dma_chan_name(chan)); 8147cbd4877e5b167b56a3d6033b926a9f925186e12Dan Williams dma_release_channel(chan); 81533df8ca068123457db56c316946a3c0e4ef787d6Dan Williams } 816838cc704ce5c8ab2a6d64d1324e37e040fcae3d8Andy Shevchenko 817838cc704ce5c8ab2a6d64d1324e37e040fcae3d8Andy Shevchenko info->nr_channels = 0; 8184a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen} 819e03e93a976d0f0da63f02fd3384c4b99cac8d715Andy Shevchenko 820a9e554957de406d6adc581731f571b8a1503f6b0Dan Williamsstatic void restart_threaded_test(struct dmatest_info *info, bool run) 821851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko{ 822a310d037b8d06755c62bb4878c00d19490af5550Dan Williams /* we might be called early to set run=, defer running until all 823a310d037b8d06755c62bb4878c00d19490af5550Dan Williams * parameters have been evaluated 824a310d037b8d06755c62bb4878c00d19490af5550Dan Williams */ 825a310d037b8d06755c62bb4878c00d19490af5550Dan Williams if (!info->did_init) 826a9e554957de406d6adc581731f571b8a1503f6b0Dan Williams return; 827851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko 828a310d037b8d06755c62bb4878c00d19490af5550Dan Williams /* Stop any running test first */ 829a310d037b8d06755c62bb4878c00d19490af5550Dan Williams stop_threaded_test(info); 830851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko 831851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko /* Run test with new parameters */ 832a9e554957de406d6adc581731f571b8a1503f6b0Dan Williams run_threaded_test(info); 833bcc567e3115055a9cc256183d72864f01286be22Andy Shevchenko} 834bcc567e3115055a9cc256183d72864f01286be22Andy Shevchenko 835a310d037b8d06755c62bb4878c00d19490af5550Dan Williamsstatic bool is_threaded_test_run(struct dmatest_info *info) 836bcc567e3115055a9cc256183d72864f01286be22Andy Shevchenko{ 837bcc567e3115055a9cc256183d72864f01286be22Andy Shevchenko struct dmatest_chan *dtc; 838bcc567e3115055a9cc256183d72864f01286be22Andy Shevchenko 839bcc567e3115055a9cc256183d72864f01286be22Andy Shevchenko list_for_each_entry(dtc, &info->channels, node) { 840bcc567e3115055a9cc256183d72864f01286be22Andy Shevchenko struct dmatest_thread *thread; 841bcc567e3115055a9cc256183d72864f01286be22Andy Shevchenko 842bcc567e3115055a9cc256183d72864f01286be22Andy Shevchenko list_for_each_entry(thread, &dtc->threads, node) { 843bcc567e3115055a9cc256183d72864f01286be22Andy Shevchenko if (!thread->done) 844bcc567e3115055a9cc256183d72864f01286be22Andy Shevchenko return true; 845bcc567e3115055a9cc256183d72864f01286be22Andy Shevchenko } 846851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko } 847851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko 848bcc567e3115055a9cc256183d72864f01286be22Andy Shevchenko return false; 849851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko} 850851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko 851a310d037b8d06755c62bb4878c00d19490af5550Dan Williamsstatic int dmatest_run_get(char *val, const struct kernel_param *kp) 852851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko{ 853a310d037b8d06755c62bb4878c00d19490af5550Dan Williams struct dmatest_info *info = &test_info; 854851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko 855851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko mutex_lock(&info->lock); 856a310d037b8d06755c62bb4878c00d19490af5550Dan Williams if (is_threaded_test_run(info)) { 857a310d037b8d06755c62bb4878c00d19490af5550Dan Williams dmatest_run = true; 8583e5ccd866fdf3a1e1d4d2c08c81f861ad6798d32Andy Shevchenko } else { 859a310d037b8d06755c62bb4878c00d19490af5550Dan Williams stop_threaded_test(info); 860a310d037b8d06755c62bb4878c00d19490af5550Dan Williams dmatest_run = false; 8613e5ccd866fdf3a1e1d4d2c08c81f861ad6798d32Andy Shevchenko } 862851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko mutex_unlock(&info->lock); 863a310d037b8d06755c62bb4878c00d19490af5550Dan Williams 864a310d037b8d06755c62bb4878c00d19490af5550Dan Williams return param_get_bool(val, kp); 865851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko} 866851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko 867a310d037b8d06755c62bb4878c00d19490af5550Dan Williamsstatic int dmatest_run_set(const char *val, const struct kernel_param *kp) 868851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko{ 869a310d037b8d06755c62bb4878c00d19490af5550Dan Williams struct dmatest_info *info = &test_info; 870a310d037b8d06755c62bb4878c00d19490af5550Dan Williams int ret; 871bcc567e3115055a9cc256183d72864f01286be22Andy Shevchenko 872a310d037b8d06755c62bb4878c00d19490af5550Dan Williams mutex_lock(&info->lock); 873a310d037b8d06755c62bb4878c00d19490af5550Dan Williams ret = param_set_bool(val, kp); 874a310d037b8d06755c62bb4878c00d19490af5550Dan Williams if (ret) { 875851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko mutex_unlock(&info->lock); 876a310d037b8d06755c62bb4878c00d19490af5550Dan Williams return ret; 877851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko } 878851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko 879a310d037b8d06755c62bb4878c00d19490af5550Dan Williams if (is_threaded_test_run(info)) 880a310d037b8d06755c62bb4878c00d19490af5550Dan Williams ret = -EBUSY; 881a310d037b8d06755c62bb4878c00d19490af5550Dan Williams else if (dmatest_run) 882a9e554957de406d6adc581731f571b8a1503f6b0Dan Williams restart_threaded_test(info, dmatest_run); 883851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko 884a310d037b8d06755c62bb4878c00d19490af5550Dan Williams mutex_unlock(&info->lock); 885851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko 886a310d037b8d06755c62bb4878c00d19490af5550Dan Williams return ret; 887851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko} 888851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko 889e03e93a976d0f0da63f02fd3384c4b99cac8d715Andy Shevchenkostatic int __init dmatest_init(void) 890e03e93a976d0f0da63f02fd3384c4b99cac8d715Andy Shevchenko{ 891e03e93a976d0f0da63f02fd3384c4b99cac8d715Andy Shevchenko struct dmatest_info *info = &test_info; 892e03e93a976d0f0da63f02fd3384c4b99cac8d715Andy Shevchenko 893a310d037b8d06755c62bb4878c00d19490af5550Dan Williams if (dmatest_run) { 894a310d037b8d06755c62bb4878c00d19490af5550Dan Williams mutex_lock(&info->lock); 895a9e554957de406d6adc581731f571b8a1503f6b0Dan Williams run_threaded_test(info); 896a310d037b8d06755c62bb4878c00d19490af5550Dan Williams mutex_unlock(&info->lock); 897a310d037b8d06755c62bb4878c00d19490af5550Dan Williams } 898838cc704ce5c8ab2a6d64d1324e37e040fcae3d8Andy Shevchenko 899a310d037b8d06755c62bb4878c00d19490af5550Dan Williams /* module parameters are stable, inittime tests are started, 900a310d037b8d06755c62bb4878c00d19490af5550Dan Williams * let userspace take over 'run' control 901a310d037b8d06755c62bb4878c00d19490af5550Dan Williams */ 902a310d037b8d06755c62bb4878c00d19490af5550Dan Williams info->did_init = true; 903851b7e16a07dfda6178d4e35fea9a9e3eb8954aeAndy Shevchenko 904a9e554957de406d6adc581731f571b8a1503f6b0Dan Williams return 0; 905e03e93a976d0f0da63f02fd3384c4b99cac8d715Andy Shevchenko} 906e03e93a976d0f0da63f02fd3384c4b99cac8d715Andy Shevchenko/* when compiled-in wait for drivers to load first */ 907e03e93a976d0f0da63f02fd3384c4b99cac8d715Andy Shevchenkolate_initcall(dmatest_init); 908e03e93a976d0f0da63f02fd3384c4b99cac8d715Andy Shevchenko 909e03e93a976d0f0da63f02fd3384c4b99cac8d715Andy Shevchenkostatic void __exit dmatest_exit(void) 910e03e93a976d0f0da63f02fd3384c4b99cac8d715Andy Shevchenko{ 911e03e93a976d0f0da63f02fd3384c4b99cac8d715Andy Shevchenko struct dmatest_info *info = &test_info; 912e03e93a976d0f0da63f02fd3384c4b99cac8d715Andy Shevchenko 913a310d037b8d06755c62bb4878c00d19490af5550Dan Williams mutex_lock(&info->lock); 914e03e93a976d0f0da63f02fd3384c4b99cac8d715Andy Shevchenko stop_threaded_test(info); 915a310d037b8d06755c62bb4878c00d19490af5550Dan Williams mutex_unlock(&info->lock); 916e03e93a976d0f0da63f02fd3384c4b99cac8d715Andy Shevchenko} 9174a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoenmodule_exit(dmatest_exit); 9184a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 919e05503ef1186ad33dfe56794407891eb1dd93ef6Jean DelvareMODULE_AUTHOR("Haavard Skinnemoen (Atmel)"); 9204a776f0aa922a552460192c07b56f4fe9cd82632Haavard SkinnemoenMODULE_LICENSE("GPL v2"); 921