dmatest.c revision 944ea4dd38b8575e30a5699633c81945bff1864d
14a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen/* 24a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen * DMA Engine test module 34a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen * 44a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen * Copyright (C) 2007 Atmel Corporation 54a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen * 64a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen * This program is free software; you can redistribute it and/or modify 74a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen * it under the terms of the GNU General Public License version 2 as 84a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen * published by the Free Software Foundation. 94a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen */ 104a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen#include <linux/delay.h> 11b7f080cfe223b3b7424872639d153695615a9255Alexey Dobriyan#include <linux/dma-mapping.h> 124a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen#include <linux/dmaengine.h> 13981ed70d8e4faf3689dbf3c48868a31d5b004d7aGuennadi Liakhovetski#include <linux/freezer.h> 144a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen#include <linux/init.h> 154a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen#include <linux/kthread.h> 164a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen#include <linux/module.h> 174a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen#include <linux/moduleparam.h> 184a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen#include <linux/random.h> 195a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h> 204a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen#include <linux/wait.h> 214a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 224a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoenstatic unsigned int test_buf_size = 16384; 234a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoenmodule_param(test_buf_size, uint, S_IRUGO); 244a776f0aa922a552460192c07b56f4fe9cd82632Haavard SkinnemoenMODULE_PARM_DESC(test_buf_size, "Size of the memcpy test buffer"); 254a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 2606190d8415219d9eef7d8f04b52a109e34575a76Kay Sieversstatic char test_channel[20]; 274a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoenmodule_param_string(channel, test_channel, sizeof(test_channel), S_IRUGO); 284a776f0aa922a552460192c07b56f4fe9cd82632Haavard SkinnemoenMODULE_PARM_DESC(channel, "Bus ID of the channel to test (default: any)"); 294a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 3006190d8415219d9eef7d8f04b52a109e34575a76Kay Sieversstatic char test_device[20]; 314a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoenmodule_param_string(device, test_device, sizeof(test_device), S_IRUGO); 324a776f0aa922a552460192c07b56f4fe9cd82632Haavard SkinnemoenMODULE_PARM_DESC(device, "Bus ID of the DMA Engine to test (default: any)"); 334a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 344a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoenstatic unsigned int threads_per_chan = 1; 354a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoenmodule_param(threads_per_chan, uint, S_IRUGO); 364a776f0aa922a552460192c07b56f4fe9cd82632Haavard SkinnemoenMODULE_PARM_DESC(threads_per_chan, 374a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen "Number of threads to start per channel (default: 1)"); 384a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 394a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoenstatic unsigned int max_channels; 404a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoenmodule_param(max_channels, uint, S_IRUGO); 4133df8ca068123457db56c316946a3c0e4ef787d6Dan WilliamsMODULE_PARM_DESC(max_channels, 424a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen "Maximum number of channels to use (default: all)"); 434a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 440a2ff57d6fba92842272889b4bca447344cd9d36Nicolas Ferrestatic unsigned int iterations; 450a2ff57d6fba92842272889b4bca447344cd9d36Nicolas Ferremodule_param(iterations, uint, S_IRUGO); 460a2ff57d6fba92842272889b4bca447344cd9d36Nicolas FerreMODULE_PARM_DESC(iterations, 470a2ff57d6fba92842272889b4bca447344cd9d36Nicolas Ferre "Iterations before stopping test (default: infinite)"); 480a2ff57d6fba92842272889b4bca447344cd9d36Nicolas Ferre 49b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williamsstatic unsigned int xor_sources = 3; 50b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williamsmodule_param(xor_sources, uint, S_IRUGO); 51b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan WilliamsMODULE_PARM_DESC(xor_sources, 52b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams "Number of xor source buffers (default: 3)"); 53b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams 5458691d64c44ae41ddf098ecb31e9a994026e3cffDan Williamsstatic unsigned int pq_sources = 3; 5558691d64c44ae41ddf098ecb31e9a994026e3cffDan Williamsmodule_param(pq_sources, uint, S_IRUGO); 5658691d64c44ae41ddf098ecb31e9a994026e3cffDan WilliamsMODULE_PARM_DESC(pq_sources, 5758691d64c44ae41ddf098ecb31e9a994026e3cffDan Williams "Number of p+q source buffers (default: 3)"); 5858691d64c44ae41ddf098ecb31e9a994026e3cffDan Williams 59d42efe6bfb4eed8314c8ce3547f21954a4140399Viresh Kumarstatic int timeout = 3000; 60d42efe6bfb4eed8314c8ce3547f21954a4140399Viresh Kumarmodule_param(timeout, uint, S_IRUGO); 6185ee7a1d39d75d23d21f3871f6dc9b87d572747aJoe PerchesMODULE_PARM_DESC(timeout, "Transfer Timeout in msec (default: 3000), " 6285ee7a1d39d75d23d21f3871f6dc9b87d572747aJoe Perches "Pass -1 for infinite timeout"); 63d42efe6bfb4eed8314c8ce3547f21954a4140399Viresh Kumar 644a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen/* 654a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen * Initialization patterns. All bytes in the source buffer has bit 7 664a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen * set, all bytes in the destination buffer has bit 7 cleared. 674a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen * 684a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen * Bit 6 is set for all bytes which are to be copied by the DMA 694a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen * engine. Bit 5 is set for all bytes which are to be overwritten by 704a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen * the DMA engine. 714a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen * 724a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen * The remaining bits are the inverse of a counter which increments by 734a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen * one for each byte address. 744a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen */ 754a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen#define PATTERN_SRC 0x80 764a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen#define PATTERN_DST 0x00 774a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen#define PATTERN_COPY 0x40 784a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen#define PATTERN_OVERWRITE 0x20 794a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen#define PATTERN_COUNT_MASK 0x1f 804a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 814a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoenstruct dmatest_thread { 824a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen struct list_head node; 834a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen struct task_struct *task; 844a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen struct dma_chan *chan; 85b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams u8 **srcs; 86b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams u8 **dsts; 87b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams enum dma_transaction_type type; 884a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen}; 894a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 904a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoenstruct dmatest_chan { 914a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen struct list_head node; 924a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen struct dma_chan *chan; 934a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen struct list_head threads; 944a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen}; 954a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 964a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen/* 974a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen * These are protected by dma_list_mutex since they're only used by 9833df8ca068123457db56c316946a3c0e4ef787d6Dan Williams * the DMA filter function callback 994a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen */ 1004a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoenstatic LIST_HEAD(dmatest_channels); 1014a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoenstatic unsigned int nr_channels; 1024a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 1034a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoenstatic bool dmatest_match_channel(struct dma_chan *chan) 1044a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen{ 1054a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen if (test_channel[0] == '\0') 1064a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen return true; 10741d5e59c1299f27983977bcfe3b360600996051cDan Williams return strcmp(dma_chan_name(chan), test_channel) == 0; 1084a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen} 1094a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 1104a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoenstatic bool dmatest_match_device(struct dma_device *device) 1114a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen{ 1124a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen if (test_device[0] == '\0') 1134a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen return true; 11406190d8415219d9eef7d8f04b52a109e34575a76Kay Sievers return strcmp(dev_name(device->dev), test_device) == 0; 1154a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen} 1164a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 1174a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoenstatic unsigned long dmatest_random(void) 1184a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen{ 1194a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen unsigned long buf; 1204a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 1214a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen get_random_bytes(&buf, sizeof(buf)); 1224a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen return buf; 1234a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen} 1244a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 125b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williamsstatic void dmatest_init_srcs(u8 **bufs, unsigned int start, unsigned int len) 1264a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen{ 1274a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen unsigned int i; 128b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams u8 *buf; 129b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams 130b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams for (; (buf = *bufs); bufs++) { 131b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams for (i = 0; i < start; i++) 132b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams buf[i] = PATTERN_SRC | (~i & PATTERN_COUNT_MASK); 133b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams for ( ; i < start + len; i++) 134b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams buf[i] = PATTERN_SRC | PATTERN_COPY 135c019894efc9c9ba5939948caa78c133b1ec8ae63Joe Perches | (~i & PATTERN_COUNT_MASK); 136b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams for ( ; i < test_buf_size; i++) 137b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams buf[i] = PATTERN_SRC | (~i & PATTERN_COUNT_MASK); 138b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams buf++; 139b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams } 1404a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen} 1414a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 142b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williamsstatic void dmatest_init_dsts(u8 **bufs, unsigned int start, unsigned int len) 1434a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen{ 1444a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen unsigned int i; 145b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams u8 *buf; 146b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams 147b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams for (; (buf = *bufs); bufs++) { 148b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams for (i = 0; i < start; i++) 149b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams buf[i] = PATTERN_DST | (~i & PATTERN_COUNT_MASK); 150b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams for ( ; i < start + len; i++) 151b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams buf[i] = PATTERN_DST | PATTERN_OVERWRITE 152b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams | (~i & PATTERN_COUNT_MASK); 153b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams for ( ; i < test_buf_size; i++) 154b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams buf[i] = PATTERN_DST | (~i & PATTERN_COUNT_MASK); 155b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams } 1564a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen} 1574a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 1584a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoenstatic void dmatest_mismatch(u8 actual, u8 pattern, unsigned int index, 1594a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen unsigned int counter, bool is_srcbuf) 1604a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen{ 1614a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen u8 diff = actual ^ pattern; 1624a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen u8 expected = pattern | (~counter & PATTERN_COUNT_MASK); 1634a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen const char *thread_name = current->comm; 1644a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 1654a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen if (is_srcbuf) 1664a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen pr_warning("%s: srcbuf[0x%x] overwritten!" 1674a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen " Expected %02x, got %02x\n", 1684a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen thread_name, index, expected, actual); 1694a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen else if ((pattern & PATTERN_COPY) 1704a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen && (diff & (PATTERN_COPY | PATTERN_OVERWRITE))) 1714a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen pr_warning("%s: dstbuf[0x%x] not copied!" 1724a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen " Expected %02x, got %02x\n", 1734a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen thread_name, index, expected, actual); 1744a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen else if (diff & PATTERN_SRC) 1754a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen pr_warning("%s: dstbuf[0x%x] was copied!" 1764a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen " Expected %02x, got %02x\n", 1774a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen thread_name, index, expected, actual); 1784a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen else 1794a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen pr_warning("%s: dstbuf[0x%x] mismatch!" 1804a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen " Expected %02x, got %02x\n", 1814a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen thread_name, index, expected, actual); 1824a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen} 1834a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 184b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williamsstatic unsigned int dmatest_verify(u8 **bufs, unsigned int start, 1854a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen unsigned int end, unsigned int counter, u8 pattern, 1864a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen bool is_srcbuf) 1874a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen{ 1884a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen unsigned int i; 1894a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen unsigned int error_count = 0; 1904a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen u8 actual; 191b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams u8 expected; 192b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams u8 *buf; 193b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams unsigned int counter_orig = counter; 194b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams 195b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams for (; (buf = *bufs); bufs++) { 196b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams counter = counter_orig; 197b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams for (i = start; i < end; i++) { 198b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams actual = buf[i]; 199b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams expected = pattern | (~counter & PATTERN_COUNT_MASK); 200b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams if (actual != expected) { 201b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams if (error_count < 32) 202b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams dmatest_mismatch(actual, pattern, i, 203b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams counter, is_srcbuf); 204b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams error_count++; 205b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams } 206b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams counter++; 2074a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen } 2084a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen } 2094a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 2104a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen if (error_count > 32) 2114a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen pr_warning("%s: %u errors suppressed\n", 2124a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen current->comm, error_count - 32); 2134a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 2144a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen return error_count; 2154a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen} 2164a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 217adfa543e7314b36ac55a40019977de6e47946dd7Tejun Heo/* poor man's completion - we want to use wait_event_freezable() on it */ 218adfa543e7314b36ac55a40019977de6e47946dd7Tejun Heostruct dmatest_done { 219adfa543e7314b36ac55a40019977de6e47946dd7Tejun Heo bool done; 220adfa543e7314b36ac55a40019977de6e47946dd7Tejun Heo wait_queue_head_t *wait; 221adfa543e7314b36ac55a40019977de6e47946dd7Tejun Heo}; 222adfa543e7314b36ac55a40019977de6e47946dd7Tejun Heo 223adfa543e7314b36ac55a40019977de6e47946dd7Tejun Heostatic void dmatest_callback(void *arg) 224e44e0aa3cfa97cddff01704751a4b25151830c72Dan Williams{ 225adfa543e7314b36ac55a40019977de6e47946dd7Tejun Heo struct dmatest_done *done = arg; 226adfa543e7314b36ac55a40019977de6e47946dd7Tejun Heo 227adfa543e7314b36ac55a40019977de6e47946dd7Tejun Heo done->done = true; 228adfa543e7314b36ac55a40019977de6e47946dd7Tejun Heo wake_up_all(done->wait); 229e44e0aa3cfa97cddff01704751a4b25151830c72Dan Williams} 230e44e0aa3cfa97cddff01704751a4b25151830c72Dan Williams 231632fd28326c0cc7be9c51ea0d76d8bec39a695e9Andy Shevchenkostatic inline void unmap_src(struct device *dev, dma_addr_t *addr, size_t len, 232632fd28326c0cc7be9c51ea0d76d8bec39a695e9Andy Shevchenko unsigned int count) 233632fd28326c0cc7be9c51ea0d76d8bec39a695e9Andy Shevchenko{ 234632fd28326c0cc7be9c51ea0d76d8bec39a695e9Andy Shevchenko while (count--) 235632fd28326c0cc7be9c51ea0d76d8bec39a695e9Andy Shevchenko dma_unmap_single(dev, addr[count], len, DMA_TO_DEVICE); 236632fd28326c0cc7be9c51ea0d76d8bec39a695e9Andy Shevchenko} 237632fd28326c0cc7be9c51ea0d76d8bec39a695e9Andy Shevchenko 238632fd28326c0cc7be9c51ea0d76d8bec39a695e9Andy Shevchenkostatic inline void unmap_dst(struct device *dev, dma_addr_t *addr, size_t len, 239632fd28326c0cc7be9c51ea0d76d8bec39a695e9Andy Shevchenko unsigned int count) 240632fd28326c0cc7be9c51ea0d76d8bec39a695e9Andy Shevchenko{ 241632fd28326c0cc7be9c51ea0d76d8bec39a695e9Andy Shevchenko while (count--) 242632fd28326c0cc7be9c51ea0d76d8bec39a695e9Andy Shevchenko dma_unmap_single(dev, addr[count], len, DMA_BIDIRECTIONAL); 243632fd28326c0cc7be9c51ea0d76d8bec39a695e9Andy Shevchenko} 244632fd28326c0cc7be9c51ea0d76d8bec39a695e9Andy Shevchenko 2458be9e32b310cd8c4302991c8ff6692689c7d9d76Akinobu Mitastatic unsigned int min_odd(unsigned int x, unsigned int y) 2468be9e32b310cd8c4302991c8ff6692689c7d9d76Akinobu Mita{ 2478be9e32b310cd8c4302991c8ff6692689c7d9d76Akinobu Mita unsigned int val = min(x, y); 2488be9e32b310cd8c4302991c8ff6692689c7d9d76Akinobu Mita 2498be9e32b310cd8c4302991c8ff6692689c7d9d76Akinobu Mita return val % 2 ? val : val - 1; 2508be9e32b310cd8c4302991c8ff6692689c7d9d76Akinobu Mita} 2518be9e32b310cd8c4302991c8ff6692689c7d9d76Akinobu Mita 2524a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen/* 2534a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen * This function repeatedly tests DMA transfers of various lengths and 254b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams * offsets for a given operation type until it is told to exit by 255b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams * kthread_stop(). There may be multiple threads running this function 256b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams * in parallel for a single channel, and there may be multiple channels 257b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams * being tested in parallel. 2584a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen * 2594a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen * Before each test, the source and destination buffer is initialized 2604a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen * with a known pattern. This pattern is different depending on 2614a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen * whether it's in an area which is supposed to be copied or 2624a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen * overwritten, and different in the source and destination buffers. 2634a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen * So if the DMA engine doesn't copy exactly what we tell it to copy, 2644a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen * we'll notice. 2654a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen */ 2664a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoenstatic int dmatest_func(void *data) 2674a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen{ 268adfa543e7314b36ac55a40019977de6e47946dd7Tejun Heo DECLARE_WAIT_QUEUE_HEAD_ONSTACK(done_wait); 2694a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen struct dmatest_thread *thread = data; 270adfa543e7314b36ac55a40019977de6e47946dd7Tejun Heo struct dmatest_done done = { .wait = &done_wait }; 2714a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen struct dma_chan *chan; 2728be9e32b310cd8c4302991c8ff6692689c7d9d76Akinobu Mita struct dma_device *dev; 2734a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen const char *thread_name; 2744a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen unsigned int src_off, dst_off, len; 2754a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen unsigned int error_count; 2764a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen unsigned int failed_tests = 0; 2774a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen unsigned int total_tests = 0; 2784a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen dma_cookie_t cookie; 2794a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen enum dma_status status; 280b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams enum dma_ctrl_flags flags; 28194de648d72c8bc833590523f22386d4babbea988Anatolij Gustschin u8 pq_coefs[pq_sources + 1]; 2824a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen int ret; 283b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams int src_cnt; 284b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams int dst_cnt; 285b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams int i; 2864a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 2874a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen thread_name = current->comm; 288adfa543e7314b36ac55a40019977de6e47946dd7Tejun Heo set_freezable(); 2894a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 2904a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen ret = -ENOMEM; 2914a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 2924a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen smp_rmb(); 2934a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen chan = thread->chan; 2948be9e32b310cd8c4302991c8ff6692689c7d9d76Akinobu Mita dev = chan->device; 295b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams if (thread->type == DMA_MEMCPY) 296b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams src_cnt = dst_cnt = 1; 297b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams else if (thread->type == DMA_XOR) { 2988be9e32b310cd8c4302991c8ff6692689c7d9d76Akinobu Mita /* force odd to ensure dst = src */ 2998be9e32b310cd8c4302991c8ff6692689c7d9d76Akinobu Mita src_cnt = min_odd(xor_sources | 1, dev->max_xor); 300b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams dst_cnt = 1; 30158691d64c44ae41ddf098ecb31e9a994026e3cffDan Williams } else if (thread->type == DMA_PQ) { 3028be9e32b310cd8c4302991c8ff6692689c7d9d76Akinobu Mita /* force odd to ensure dst = src */ 3038be9e32b310cd8c4302991c8ff6692689c7d9d76Akinobu Mita src_cnt = min_odd(pq_sources | 1, dma_maxpq(dev, 0)); 30458691d64c44ae41ddf098ecb31e9a994026e3cffDan Williams dst_cnt = 2; 30594de648d72c8bc833590523f22386d4babbea988Anatolij Gustschin for (i = 0; i < src_cnt; i++) 30658691d64c44ae41ddf098ecb31e9a994026e3cffDan Williams pq_coefs[i] = 1; 307b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams } else 308b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams goto err_srcs; 309b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams 310b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams thread->srcs = kcalloc(src_cnt+1, sizeof(u8 *), GFP_KERNEL); 311b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams if (!thread->srcs) 312b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams goto err_srcs; 313b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams for (i = 0; i < src_cnt; i++) { 314b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams thread->srcs[i] = kmalloc(test_buf_size, GFP_KERNEL); 315b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams if (!thread->srcs[i]) 316b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams goto err_srcbuf; 317b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams } 318b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams thread->srcs[i] = NULL; 319b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams 320b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams thread->dsts = kcalloc(dst_cnt+1, sizeof(u8 *), GFP_KERNEL); 321b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams if (!thread->dsts) 322b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams goto err_dsts; 323b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams for (i = 0; i < dst_cnt; i++) { 324b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams thread->dsts[i] = kmalloc(test_buf_size, GFP_KERNEL); 325b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams if (!thread->dsts[i]) 326b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams goto err_dstbuf; 327b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams } 328b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams thread->dsts[i] = NULL; 329b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams 330e44e0aa3cfa97cddff01704751a4b25151830c72Dan Williams set_user_nice(current, 10); 331e44e0aa3cfa97cddff01704751a4b25151830c72Dan Williams 332b203bd3f6b9c3db3b1979c2ff79bb2b9be8f03a3Ira Snyder /* 333b203bd3f6b9c3db3b1979c2ff79bb2b9be8f03a3Ira Snyder * src buffers are freed by the DMAEngine code with dma_unmap_single() 334b203bd3f6b9c3db3b1979c2ff79bb2b9be8f03a3Ira Snyder * dst buffers are freed by ourselves below 335b203bd3f6b9c3db3b1979c2ff79bb2b9be8f03a3Ira Snyder */ 336b203bd3f6b9c3db3b1979c2ff79bb2b9be8f03a3Ira Snyder flags = DMA_CTRL_ACK | DMA_PREP_INTERRUPT 337b203bd3f6b9c3db3b1979c2ff79bb2b9be8f03a3Ira Snyder | DMA_COMPL_SKIP_DEST_UNMAP | DMA_COMPL_SRC_UNMAP_SINGLE; 3384a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 3390a2ff57d6fba92842272889b4bca447344cd9d36Nicolas Ferre while (!kthread_should_stop() 3400a2ff57d6fba92842272889b4bca447344cd9d36Nicolas Ferre && !(iterations && total_tests >= iterations)) { 341b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams struct dma_async_tx_descriptor *tx = NULL; 342b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams dma_addr_t dma_srcs[src_cnt]; 343b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams dma_addr_t dma_dsts[dst_cnt]; 34483544ae9f3991bfc7d5e0fe9a3008cd05a8d57b7Dan Williams u8 align = 0; 345d86be86e9aab221089d72399072511f13fe2a771Atsushi Nemoto 3464a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen total_tests++; 3474a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 34883544ae9f3991bfc7d5e0fe9a3008cd05a8d57b7Dan Williams /* honor alignment restrictions */ 34983544ae9f3991bfc7d5e0fe9a3008cd05a8d57b7Dan Williams if (thread->type == DMA_MEMCPY) 35083544ae9f3991bfc7d5e0fe9a3008cd05a8d57b7Dan Williams align = dev->copy_align; 35183544ae9f3991bfc7d5e0fe9a3008cd05a8d57b7Dan Williams else if (thread->type == DMA_XOR) 35283544ae9f3991bfc7d5e0fe9a3008cd05a8d57b7Dan Williams align = dev->xor_align; 35383544ae9f3991bfc7d5e0fe9a3008cd05a8d57b7Dan Williams else if (thread->type == DMA_PQ) 35483544ae9f3991bfc7d5e0fe9a3008cd05a8d57b7Dan Williams align = dev->pq_align; 35583544ae9f3991bfc7d5e0fe9a3008cd05a8d57b7Dan Williams 356cfe4f2751ef1a5390b56c5d263f90b6ff138ba31Guennadi Liakhovetski if (1 << align > test_buf_size) { 357cfe4f2751ef1a5390b56c5d263f90b6ff138ba31Guennadi Liakhovetski pr_err("%u-byte buffer too small for %d-byte alignment\n", 358cfe4f2751ef1a5390b56c5d263f90b6ff138ba31Guennadi Liakhovetski test_buf_size, 1 << align); 359cfe4f2751ef1a5390b56c5d263f90b6ff138ba31Guennadi Liakhovetski break; 360cfe4f2751ef1a5390b56c5d263f90b6ff138ba31Guennadi Liakhovetski } 361cfe4f2751ef1a5390b56c5d263f90b6ff138ba31Guennadi Liakhovetski 362cfe4f2751ef1a5390b56c5d263f90b6ff138ba31Guennadi Liakhovetski len = dmatest_random() % test_buf_size + 1; 36383544ae9f3991bfc7d5e0fe9a3008cd05a8d57b7Dan Williams len = (len >> align) << align; 364cfe4f2751ef1a5390b56c5d263f90b6ff138ba31Guennadi Liakhovetski if (!len) 365cfe4f2751ef1a5390b56c5d263f90b6ff138ba31Guennadi Liakhovetski len = 1 << align; 366cfe4f2751ef1a5390b56c5d263f90b6ff138ba31Guennadi Liakhovetski src_off = dmatest_random() % (test_buf_size - len + 1); 367cfe4f2751ef1a5390b56c5d263f90b6ff138ba31Guennadi Liakhovetski dst_off = dmatest_random() % (test_buf_size - len + 1); 368cfe4f2751ef1a5390b56c5d263f90b6ff138ba31Guennadi Liakhovetski 36983544ae9f3991bfc7d5e0fe9a3008cd05a8d57b7Dan Williams src_off = (src_off >> align) << align; 37083544ae9f3991bfc7d5e0fe9a3008cd05a8d57b7Dan Williams dst_off = (dst_off >> align) << align; 37183544ae9f3991bfc7d5e0fe9a3008cd05a8d57b7Dan Williams 372b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams dmatest_init_srcs(thread->srcs, src_off, len); 373b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams dmatest_init_dsts(thread->dsts, dst_off, len); 3744a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 375b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams for (i = 0; i < src_cnt; i++) { 376b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams u8 *buf = thread->srcs[i] + src_off; 377b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams 378b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams dma_srcs[i] = dma_map_single(dev->dev, buf, len, 379b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams DMA_TO_DEVICE); 380afde3be121efcc658e26f8cc71ead04af96d38f9Andy Shevchenko ret = dma_mapping_error(dev->dev, dma_srcs[i]); 381afde3be121efcc658e26f8cc71ead04af96d38f9Andy Shevchenko if (ret) { 382afde3be121efcc658e26f8cc71ead04af96d38f9Andy Shevchenko unmap_src(dev->dev, dma_srcs, len, i); 383afde3be121efcc658e26f8cc71ead04af96d38f9Andy Shevchenko pr_warn("%s: #%u: mapping error %d with " 384afde3be121efcc658e26f8cc71ead04af96d38f9Andy Shevchenko "src_off=0x%x len=0x%x\n", 385afde3be121efcc658e26f8cc71ead04af96d38f9Andy Shevchenko thread_name, total_tests - 1, ret, 386afde3be121efcc658e26f8cc71ead04af96d38f9Andy Shevchenko src_off, len); 387afde3be121efcc658e26f8cc71ead04af96d38f9Andy Shevchenko failed_tests++; 388afde3be121efcc658e26f8cc71ead04af96d38f9Andy Shevchenko continue; 389afde3be121efcc658e26f8cc71ead04af96d38f9Andy Shevchenko } 390b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams } 391d86be86e9aab221089d72399072511f13fe2a771Atsushi Nemoto /* map with DMA_BIDIRECTIONAL to force writeback/invalidate */ 392b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams for (i = 0; i < dst_cnt; i++) { 393b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams dma_dsts[i] = dma_map_single(dev->dev, thread->dsts[i], 394b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams test_buf_size, 395b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams DMA_BIDIRECTIONAL); 396afde3be121efcc658e26f8cc71ead04af96d38f9Andy Shevchenko ret = dma_mapping_error(dev->dev, dma_dsts[i]); 397afde3be121efcc658e26f8cc71ead04af96d38f9Andy Shevchenko if (ret) { 398afde3be121efcc658e26f8cc71ead04af96d38f9Andy Shevchenko unmap_src(dev->dev, dma_srcs, len, src_cnt); 399afde3be121efcc658e26f8cc71ead04af96d38f9Andy Shevchenko unmap_dst(dev->dev, dma_dsts, test_buf_size, i); 400afde3be121efcc658e26f8cc71ead04af96d38f9Andy Shevchenko pr_warn("%s: #%u: mapping error %d with " 401afde3be121efcc658e26f8cc71ead04af96d38f9Andy Shevchenko "dst_off=0x%x len=0x%x\n", 402afde3be121efcc658e26f8cc71ead04af96d38f9Andy Shevchenko thread_name, total_tests - 1, ret, 403afde3be121efcc658e26f8cc71ead04af96d38f9Andy Shevchenko dst_off, test_buf_size); 404afde3be121efcc658e26f8cc71ead04af96d38f9Andy Shevchenko failed_tests++; 405afde3be121efcc658e26f8cc71ead04af96d38f9Andy Shevchenko continue; 406afde3be121efcc658e26f8cc71ead04af96d38f9Andy Shevchenko } 407b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams } 408b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams 409b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams if (thread->type == DMA_MEMCPY) 410b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams tx = dev->device_prep_dma_memcpy(chan, 411b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams dma_dsts[0] + dst_off, 412b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams dma_srcs[0], len, 413b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams flags); 414b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams else if (thread->type == DMA_XOR) 415b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams tx = dev->device_prep_dma_xor(chan, 416b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams dma_dsts[0] + dst_off, 41767b9124f734b22b30d9adf18c39fe795e2901070Dan Williams dma_srcs, src_cnt, 418b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams len, flags); 41958691d64c44ae41ddf098ecb31e9a994026e3cffDan Williams else if (thread->type == DMA_PQ) { 42058691d64c44ae41ddf098ecb31e9a994026e3cffDan Williams dma_addr_t dma_pq[dst_cnt]; 42158691d64c44ae41ddf098ecb31e9a994026e3cffDan Williams 42258691d64c44ae41ddf098ecb31e9a994026e3cffDan Williams for (i = 0; i < dst_cnt; i++) 42358691d64c44ae41ddf098ecb31e9a994026e3cffDan Williams dma_pq[i] = dma_dsts[i] + dst_off; 42458691d64c44ae41ddf098ecb31e9a994026e3cffDan Williams tx = dev->device_prep_dma_pq(chan, dma_pq, dma_srcs, 42594de648d72c8bc833590523f22386d4babbea988Anatolij Gustschin src_cnt, pq_coefs, 42658691d64c44ae41ddf098ecb31e9a994026e3cffDan Williams len, flags); 42758691d64c44ae41ddf098ecb31e9a994026e3cffDan Williams } 428d86be86e9aab221089d72399072511f13fe2a771Atsushi Nemoto 429d86be86e9aab221089d72399072511f13fe2a771Atsushi Nemoto if (!tx) { 430632fd28326c0cc7be9c51ea0d76d8bec39a695e9Andy Shevchenko unmap_src(dev->dev, dma_srcs, len, src_cnt); 431632fd28326c0cc7be9c51ea0d76d8bec39a695e9Andy Shevchenko unmap_dst(dev->dev, dma_dsts, test_buf_size, dst_cnt); 432d86be86e9aab221089d72399072511f13fe2a771Atsushi Nemoto pr_warning("%s: #%u: prep error with src_off=0x%x " 433d86be86e9aab221089d72399072511f13fe2a771Atsushi Nemoto "dst_off=0x%x len=0x%x\n", 434d86be86e9aab221089d72399072511f13fe2a771Atsushi Nemoto thread_name, total_tests - 1, 435d86be86e9aab221089d72399072511f13fe2a771Atsushi Nemoto src_off, dst_off, len); 436d86be86e9aab221089d72399072511f13fe2a771Atsushi Nemoto msleep(100); 437d86be86e9aab221089d72399072511f13fe2a771Atsushi Nemoto failed_tests++; 438d86be86e9aab221089d72399072511f13fe2a771Atsushi Nemoto continue; 439d86be86e9aab221089d72399072511f13fe2a771Atsushi Nemoto } 440e44e0aa3cfa97cddff01704751a4b25151830c72Dan Williams 441adfa543e7314b36ac55a40019977de6e47946dd7Tejun Heo done.done = false; 442e44e0aa3cfa97cddff01704751a4b25151830c72Dan Williams tx->callback = dmatest_callback; 443adfa543e7314b36ac55a40019977de6e47946dd7Tejun Heo tx->callback_param = &done; 444d86be86e9aab221089d72399072511f13fe2a771Atsushi Nemoto cookie = tx->tx_submit(tx); 445d86be86e9aab221089d72399072511f13fe2a771Atsushi Nemoto 4464a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen if (dma_submit_error(cookie)) { 4474a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen pr_warning("%s: #%u: submit error %d with src_off=0x%x " 4484a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen "dst_off=0x%x len=0x%x\n", 4494a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen thread_name, total_tests - 1, cookie, 4504a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen src_off, dst_off, len); 4514a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen msleep(100); 4524a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen failed_tests++; 4534a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen continue; 4544a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen } 455b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams dma_async_issue_pending(chan); 4564a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 457adfa543e7314b36ac55a40019977de6e47946dd7Tejun Heo wait_event_freezable_timeout(done_wait, done.done, 458adfa543e7314b36ac55a40019977de6e47946dd7Tejun Heo msecs_to_jiffies(timeout)); 459981ed70d8e4faf3689dbf3c48868a31d5b004d7aGuennadi Liakhovetski 460e44e0aa3cfa97cddff01704751a4b25151830c72Dan Williams status = dma_async_is_tx_complete(chan, cookie, NULL, NULL); 4614a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 462adfa543e7314b36ac55a40019977de6e47946dd7Tejun Heo if (!done.done) { 463adfa543e7314b36ac55a40019977de6e47946dd7Tejun Heo /* 464adfa543e7314b36ac55a40019977de6e47946dd7Tejun Heo * We're leaving the timed out dma operation with 465adfa543e7314b36ac55a40019977de6e47946dd7Tejun Heo * dangling pointer to done_wait. To make this 466adfa543e7314b36ac55a40019977de6e47946dd7Tejun Heo * correct, we'll need to allocate wait_done for 467adfa543e7314b36ac55a40019977de6e47946dd7Tejun Heo * each test iteration and perform "who's gonna 468adfa543e7314b36ac55a40019977de6e47946dd7Tejun Heo * free it this time?" dancing. For now, just 469adfa543e7314b36ac55a40019977de6e47946dd7Tejun Heo * leave it dangling. 470adfa543e7314b36ac55a40019977de6e47946dd7Tejun Heo */ 471e44e0aa3cfa97cddff01704751a4b25151830c72Dan Williams pr_warning("%s: #%u: test timed out\n", 472e44e0aa3cfa97cddff01704751a4b25151830c72Dan Williams thread_name, total_tests - 1); 473e44e0aa3cfa97cddff01704751a4b25151830c72Dan Williams failed_tests++; 474e44e0aa3cfa97cddff01704751a4b25151830c72Dan Williams continue; 475e44e0aa3cfa97cddff01704751a4b25151830c72Dan Williams } else if (status != DMA_SUCCESS) { 476e44e0aa3cfa97cddff01704751a4b25151830c72Dan Williams pr_warning("%s: #%u: got completion callback," 477e44e0aa3cfa97cddff01704751a4b25151830c72Dan Williams " but status is \'%s\'\n", 478e44e0aa3cfa97cddff01704751a4b25151830c72Dan Williams thread_name, total_tests - 1, 479e44e0aa3cfa97cddff01704751a4b25151830c72Dan Williams status == DMA_ERROR ? "error" : "in progress"); 4804a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen failed_tests++; 4814a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen continue; 4824a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen } 483e44e0aa3cfa97cddff01704751a4b25151830c72Dan Williams 484d86be86e9aab221089d72399072511f13fe2a771Atsushi Nemoto /* Unmap by myself (see DMA_COMPL_SKIP_DEST_UNMAP above) */ 485632fd28326c0cc7be9c51ea0d76d8bec39a695e9Andy Shevchenko unmap_dst(dev->dev, dma_dsts, test_buf_size, dst_cnt); 4864a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 4874a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen error_count = 0; 4884a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 4894a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen pr_debug("%s: verifying source buffer...\n", thread_name); 490b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams error_count += dmatest_verify(thread->srcs, 0, src_off, 4914a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 0, PATTERN_SRC, true); 492b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams error_count += dmatest_verify(thread->srcs, src_off, 4934a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen src_off + len, src_off, 4944a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen PATTERN_SRC | PATTERN_COPY, true); 495b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams error_count += dmatest_verify(thread->srcs, src_off + len, 4964a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen test_buf_size, src_off + len, 4974a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen PATTERN_SRC, true); 4984a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 4994a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen pr_debug("%s: verifying dest buffer...\n", 5004a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen thread->task->comm); 501b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams error_count += dmatest_verify(thread->dsts, 0, dst_off, 5024a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 0, PATTERN_DST, false); 503b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams error_count += dmatest_verify(thread->dsts, dst_off, 5044a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen dst_off + len, src_off, 5054a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen PATTERN_SRC | PATTERN_COPY, false); 506b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams error_count += dmatest_verify(thread->dsts, dst_off + len, 5074a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen test_buf_size, dst_off + len, 5084a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen PATTERN_DST, false); 5094a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 5104a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen if (error_count) { 5114a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen pr_warning("%s: #%u: %u errors with " 5124a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen "src_off=0x%x dst_off=0x%x len=0x%x\n", 5134a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen thread_name, total_tests - 1, error_count, 5144a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen src_off, dst_off, len); 5154a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen failed_tests++; 5164a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen } else { 5174a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen pr_debug("%s: #%u: No errors with " 5184a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen "src_off=0x%x dst_off=0x%x len=0x%x\n", 5194a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen thread_name, total_tests - 1, 5204a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen src_off, dst_off, len); 5214a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen } 5224a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen } 5234a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 5244a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen ret = 0; 525b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams for (i = 0; thread->dsts[i]; i++) 526b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams kfree(thread->dsts[i]); 5274a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoenerr_dstbuf: 528b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams kfree(thread->dsts); 529b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williamserr_dsts: 530b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams for (i = 0; thread->srcs[i]; i++) 531b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams kfree(thread->srcs[i]); 5324a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoenerr_srcbuf: 533b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams kfree(thread->srcs); 534b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williamserr_srcs: 5354a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen pr_notice("%s: terminating after %u tests, %u failures (status %d)\n", 5364a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen thread_name, total_tests, failed_tests, ret); 5370a2ff57d6fba92842272889b4bca447344cd9d36Nicolas Ferre 5389704efaa52ab18eb3504c4e0bc421c1d01b7981aViresh Kumar /* terminate all transfers on specified channels */ 539944ea4dd38b8575e30a5699633c81945bff1864dJon Mason dmaengine_terminate_all(chan); 5400a2ff57d6fba92842272889b4bca447344cd9d36Nicolas Ferre if (iterations > 0) 5410a2ff57d6fba92842272889b4bca447344cd9d36Nicolas Ferre while (!kthread_should_stop()) { 542b953df7c70740cd7593072ebec77a8f658505630Yong Zhang DECLARE_WAIT_QUEUE_HEAD_ONSTACK(wait_dmatest_exit); 5430a2ff57d6fba92842272889b4bca447344cd9d36Nicolas Ferre interruptible_sleep_on(&wait_dmatest_exit); 5440a2ff57d6fba92842272889b4bca447344cd9d36Nicolas Ferre } 5450a2ff57d6fba92842272889b4bca447344cd9d36Nicolas Ferre 5464a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen return ret; 5474a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen} 5484a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 5494a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoenstatic void dmatest_cleanup_channel(struct dmatest_chan *dtc) 5504a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen{ 5514a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen struct dmatest_thread *thread; 5524a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen struct dmatest_thread *_thread; 5534a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen int ret; 5544a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 5554a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen list_for_each_entry_safe(thread, _thread, &dtc->threads, node) { 5564a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen ret = kthread_stop(thread->task); 5574a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen pr_debug("dmatest: thread %s exited with status %d\n", 5584a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen thread->task->comm, ret); 5594a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen list_del(&thread->node); 5604a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen kfree(thread); 5614a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen } 5629704efaa52ab18eb3504c4e0bc421c1d01b7981aViresh Kumar 5639704efaa52ab18eb3504c4e0bc421c1d01b7981aViresh Kumar /* terminate all transfers on specified channels */ 564944ea4dd38b8575e30a5699633c81945bff1864dJon Mason dmaengine_terminate_all(dtc->chan); 5659704efaa52ab18eb3504c4e0bc421c1d01b7981aViresh Kumar 5664a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen kfree(dtc); 5674a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen} 5684a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 569b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williamsstatic int dmatest_add_threads(struct dmatest_chan *dtc, enum dma_transaction_type type) 5704a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen{ 571b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams struct dmatest_thread *thread; 572b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams struct dma_chan *chan = dtc->chan; 573b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams char *op; 574b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams unsigned int i; 5754a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 576b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams if (type == DMA_MEMCPY) 577b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams op = "copy"; 578b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams else if (type == DMA_XOR) 579b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams op = "xor"; 58058691d64c44ae41ddf098ecb31e9a994026e3cffDan Williams else if (type == DMA_PQ) 58158691d64c44ae41ddf098ecb31e9a994026e3cffDan Williams op = "pq"; 582b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams else 583b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams return -EINVAL; 5844a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 5854a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen for (i = 0; i < threads_per_chan; i++) { 5864a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen thread = kzalloc(sizeof(struct dmatest_thread), GFP_KERNEL); 5874a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen if (!thread) { 588b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams pr_warning("dmatest: No memory for %s-%s%u\n", 589b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams dma_chan_name(chan), op, i); 590b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams 5914a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen break; 5924a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen } 5934a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen thread->chan = dtc->chan; 594b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams thread->type = type; 5954a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen smp_wmb(); 596b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams thread->task = kthread_run(dmatest_func, thread, "%s-%s%u", 597b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams dma_chan_name(chan), op, i); 5984a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen if (IS_ERR(thread->task)) { 599b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams pr_warning("dmatest: Failed to run thread %s-%s%u\n", 600b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams dma_chan_name(chan), op, i); 6014a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen kfree(thread); 6024a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen break; 6034a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen } 6044a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 6054a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen /* srcbuf and dstbuf are allocated by the thread itself */ 6064a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 6074a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen list_add_tail(&thread->node, &dtc->threads); 6084a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen } 6094a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 610b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams return i; 611b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams} 612b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams 613b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williamsstatic int dmatest_add_channel(struct dma_chan *chan) 614b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams{ 615b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams struct dmatest_chan *dtc; 616b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams struct dma_device *dma_dev = chan->device; 617b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams unsigned int thread_count = 0; 618b9033e682e86f3c6a66763f9b6a3935c5c64e145Kulikov Vasiliy int cnt; 619b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams 620b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams dtc = kmalloc(sizeof(struct dmatest_chan), GFP_KERNEL); 621b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams if (!dtc) { 622b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams pr_warning("dmatest: No memory for %s\n", dma_chan_name(chan)); 623b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams return -ENOMEM; 624b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams } 625b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams 626b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams dtc->chan = chan; 627b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams INIT_LIST_HEAD(&dtc->threads); 628b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams 629b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams if (dma_has_cap(DMA_MEMCPY, dma_dev->cap_mask)) { 630b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams cnt = dmatest_add_threads(dtc, DMA_MEMCPY); 631f1aef8b6e6abf32a3a269542f95a19e2cb319f6cNicolas Ferre thread_count += cnt > 0 ? cnt : 0; 632b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams } 633b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams if (dma_has_cap(DMA_XOR, dma_dev->cap_mask)) { 634b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams cnt = dmatest_add_threads(dtc, DMA_XOR); 635f1aef8b6e6abf32a3a269542f95a19e2cb319f6cNicolas Ferre thread_count += cnt > 0 ? cnt : 0; 636b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams } 63758691d64c44ae41ddf098ecb31e9a994026e3cffDan Williams if (dma_has_cap(DMA_PQ, dma_dev->cap_mask)) { 63858691d64c44ae41ddf098ecb31e9a994026e3cffDan Williams cnt = dmatest_add_threads(dtc, DMA_PQ); 639d07a74a546981a09ba490936645fbf0d1340b96cDr. David Alan Gilbert thread_count += cnt > 0 ? cnt : 0; 64058691d64c44ae41ddf098ecb31e9a994026e3cffDan Williams } 641b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams 642b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams pr_info("dmatest: Started %u threads using %s\n", 643b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams thread_count, dma_chan_name(chan)); 6444a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 6454a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen list_add_tail(&dtc->node, &dmatest_channels); 6464a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen nr_channels++; 6474a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 64833df8ca068123457db56c316946a3c0e4ef787d6Dan Williams return 0; 6494a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen} 6504a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 6517dd602510128d7a64b11ff3b7d4f30ac8e3946ceDan Williamsstatic bool filter(struct dma_chan *chan, void *param) 6524a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen{ 65333df8ca068123457db56c316946a3c0e4ef787d6Dan Williams if (!dmatest_match_channel(chan) || !dmatest_match_device(chan->device)) 6547dd602510128d7a64b11ff3b7d4f30ac8e3946ceDan Williams return false; 65533df8ca068123457db56c316946a3c0e4ef787d6Dan Williams else 6567dd602510128d7a64b11ff3b7d4f30ac8e3946ceDan Williams return true; 6574a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen} 6584a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 6594a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoenstatic int __init dmatest_init(void) 6604a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen{ 66133df8ca068123457db56c316946a3c0e4ef787d6Dan Williams dma_cap_mask_t mask; 66233df8ca068123457db56c316946a3c0e4ef787d6Dan Williams struct dma_chan *chan; 66333df8ca068123457db56c316946a3c0e4ef787d6Dan Williams int err = 0; 66433df8ca068123457db56c316946a3c0e4ef787d6Dan Williams 66533df8ca068123457db56c316946a3c0e4ef787d6Dan Williams dma_cap_zero(mask); 66633df8ca068123457db56c316946a3c0e4ef787d6Dan Williams dma_cap_set(DMA_MEMCPY, mask); 66733df8ca068123457db56c316946a3c0e4ef787d6Dan Williams for (;;) { 66833df8ca068123457db56c316946a3c0e4ef787d6Dan Williams chan = dma_request_channel(mask, filter, NULL); 66933df8ca068123457db56c316946a3c0e4ef787d6Dan Williams if (chan) { 67033df8ca068123457db56c316946a3c0e4ef787d6Dan Williams err = dmatest_add_channel(chan); 671c56c81abe7e684bc6203632d807303eb765690dcDan Williams if (err) { 67233df8ca068123457db56c316946a3c0e4ef787d6Dan Williams dma_release_channel(chan); 67333df8ca068123457db56c316946a3c0e4ef787d6Dan Williams break; /* add_channel failed, punt */ 67433df8ca068123457db56c316946a3c0e4ef787d6Dan Williams } 67533df8ca068123457db56c316946a3c0e4ef787d6Dan Williams } else 67633df8ca068123457db56c316946a3c0e4ef787d6Dan Williams break; /* no more channels available */ 67733df8ca068123457db56c316946a3c0e4ef787d6Dan Williams if (max_channels && nr_channels >= max_channels) 67833df8ca068123457db56c316946a3c0e4ef787d6Dan Williams break; /* we have all we need */ 67933df8ca068123457db56c316946a3c0e4ef787d6Dan Williams } 6804a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 68133df8ca068123457db56c316946a3c0e4ef787d6Dan Williams return err; 6824a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen} 68333df8ca068123457db56c316946a3c0e4ef787d6Dan Williams/* when compiled-in wait for drivers to load first */ 68433df8ca068123457db56c316946a3c0e4ef787d6Dan Williamslate_initcall(dmatest_init); 6854a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 6864a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoenstatic void __exit dmatest_exit(void) 6874a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen{ 68833df8ca068123457db56c316946a3c0e4ef787d6Dan Williams struct dmatest_chan *dtc, *_dtc; 6897cbd4877e5b167b56a3d6033b926a9f925186e12Dan Williams struct dma_chan *chan; 69033df8ca068123457db56c316946a3c0e4ef787d6Dan Williams 69133df8ca068123457db56c316946a3c0e4ef787d6Dan Williams list_for_each_entry_safe(dtc, _dtc, &dmatest_channels, node) { 69233df8ca068123457db56c316946a3c0e4ef787d6Dan Williams list_del(&dtc->node); 6937cbd4877e5b167b56a3d6033b926a9f925186e12Dan Williams chan = dtc->chan; 69433df8ca068123457db56c316946a3c0e4ef787d6Dan Williams dmatest_cleanup_channel(dtc); 69533df8ca068123457db56c316946a3c0e4ef787d6Dan Williams pr_debug("dmatest: dropped channel %s\n", 6967cbd4877e5b167b56a3d6033b926a9f925186e12Dan Williams dma_chan_name(chan)); 6977cbd4877e5b167b56a3d6033b926a9f925186e12Dan Williams dma_release_channel(chan); 69833df8ca068123457db56c316946a3c0e4ef787d6Dan Williams } 6994a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen} 7004a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoenmodule_exit(dmatest_exit); 7014a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 702e05503ef1186ad33dfe56794407891eb1dd93ef6Jean DelvareMODULE_AUTHOR("Haavard Skinnemoen (Atmel)"); 7034a776f0aa922a552460192c07b56f4fe9cd82632Haavard SkinnemoenMODULE_LICENSE("GPL v2"); 704