dmatest.c revision b7f080cfe223b3b7424872639d153695615a9255
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> 134a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen#include <linux/init.h> 144a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen#include <linux/kthread.h> 154a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen#include <linux/module.h> 164a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen#include <linux/moduleparam.h> 174a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen#include <linux/random.h> 185a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h> 194a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen#include <linux/wait.h> 204a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 214a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoenstatic unsigned int test_buf_size = 16384; 224a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoenmodule_param(test_buf_size, uint, S_IRUGO); 234a776f0aa922a552460192c07b56f4fe9cd82632Haavard SkinnemoenMODULE_PARM_DESC(test_buf_size, "Size of the memcpy test buffer"); 244a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 2506190d8415219d9eef7d8f04b52a109e34575a76Kay Sieversstatic char test_channel[20]; 264a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoenmodule_param_string(channel, test_channel, sizeof(test_channel), S_IRUGO); 274a776f0aa922a552460192c07b56f4fe9cd82632Haavard SkinnemoenMODULE_PARM_DESC(channel, "Bus ID of the channel to test (default: any)"); 284a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 2906190d8415219d9eef7d8f04b52a109e34575a76Kay Sieversstatic char test_device[20]; 304a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoenmodule_param_string(device, test_device, sizeof(test_device), S_IRUGO); 314a776f0aa922a552460192c07b56f4fe9cd82632Haavard SkinnemoenMODULE_PARM_DESC(device, "Bus ID of the DMA Engine to test (default: any)"); 324a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 334a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoenstatic unsigned int threads_per_chan = 1; 344a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoenmodule_param(threads_per_chan, uint, S_IRUGO); 354a776f0aa922a552460192c07b56f4fe9cd82632Haavard SkinnemoenMODULE_PARM_DESC(threads_per_chan, 364a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen "Number of threads to start per channel (default: 1)"); 374a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 384a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoenstatic unsigned int max_channels; 394a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoenmodule_param(max_channels, uint, S_IRUGO); 4033df8ca068123457db56c316946a3c0e4ef787d6Dan WilliamsMODULE_PARM_DESC(max_channels, 414a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen "Maximum number of channels to use (default: all)"); 424a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 430a2ff57d6fba92842272889b4bca447344cd9d36Nicolas Ferrestatic unsigned int iterations; 440a2ff57d6fba92842272889b4bca447344cd9d36Nicolas Ferremodule_param(iterations, uint, S_IRUGO); 450a2ff57d6fba92842272889b4bca447344cd9d36Nicolas FerreMODULE_PARM_DESC(iterations, 460a2ff57d6fba92842272889b4bca447344cd9d36Nicolas Ferre "Iterations before stopping test (default: infinite)"); 470a2ff57d6fba92842272889b4bca447344cd9d36Nicolas Ferre 48b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williamsstatic unsigned int xor_sources = 3; 49b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williamsmodule_param(xor_sources, uint, S_IRUGO); 50b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan WilliamsMODULE_PARM_DESC(xor_sources, 51b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams "Number of xor source buffers (default: 3)"); 52b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams 5358691d64c44ae41ddf098ecb31e9a994026e3cffDan Williamsstatic unsigned int pq_sources = 3; 5458691d64c44ae41ddf098ecb31e9a994026e3cffDan Williamsmodule_param(pq_sources, uint, S_IRUGO); 5558691d64c44ae41ddf098ecb31e9a994026e3cffDan WilliamsMODULE_PARM_DESC(pq_sources, 5658691d64c44ae41ddf098ecb31e9a994026e3cffDan Williams "Number of p+q source buffers (default: 3)"); 5758691d64c44ae41ddf098ecb31e9a994026e3cffDan Williams 58d42efe6bfb4eed8314c8ce3547f21954a4140399Viresh Kumarstatic int timeout = 3000; 59d42efe6bfb4eed8314c8ce3547f21954a4140399Viresh Kumarmodule_param(timeout, uint, S_IRUGO); 6085ee7a1d39d75d23d21f3871f6dc9b87d572747aJoe PerchesMODULE_PARM_DESC(timeout, "Transfer Timeout in msec (default: 3000), " 6185ee7a1d39d75d23d21f3871f6dc9b87d572747aJoe Perches "Pass -1 for infinite timeout"); 62d42efe6bfb4eed8314c8ce3547f21954a4140399Viresh Kumar 634a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen/* 644a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen * Initialization patterns. All bytes in the source buffer has bit 7 654a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen * set, all bytes in the destination buffer has bit 7 cleared. 664a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen * 674a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen * Bit 6 is set for all bytes which are to be copied by the DMA 684a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen * engine. Bit 5 is set for all bytes which are to be overwritten by 694a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen * the DMA engine. 704a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen * 714a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen * The remaining bits are the inverse of a counter which increments by 724a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen * one for each byte address. 734a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen */ 744a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen#define PATTERN_SRC 0x80 754a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen#define PATTERN_DST 0x00 764a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen#define PATTERN_COPY 0x40 774a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen#define PATTERN_OVERWRITE 0x20 784a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen#define PATTERN_COUNT_MASK 0x1f 794a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 804a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoenstruct dmatest_thread { 814a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen struct list_head node; 824a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen struct task_struct *task; 834a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen struct dma_chan *chan; 84b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams u8 **srcs; 85b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams u8 **dsts; 86b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams enum dma_transaction_type type; 874a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen}; 884a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 894a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoenstruct dmatest_chan { 904a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen struct list_head node; 914a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen struct dma_chan *chan; 924a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen struct list_head threads; 934a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen}; 944a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 954a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen/* 964a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen * These are protected by dma_list_mutex since they're only used by 9733df8ca068123457db56c316946a3c0e4ef787d6Dan Williams * the DMA filter function callback 984a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen */ 994a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoenstatic LIST_HEAD(dmatest_channels); 1004a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoenstatic unsigned int nr_channels; 1014a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 1024a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoenstatic bool dmatest_match_channel(struct dma_chan *chan) 1034a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen{ 1044a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen if (test_channel[0] == '\0') 1054a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen return true; 10641d5e59c1299f27983977bcfe3b360600996051cDan Williams return strcmp(dma_chan_name(chan), test_channel) == 0; 1074a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen} 1084a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 1094a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoenstatic bool dmatest_match_device(struct dma_device *device) 1104a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen{ 1114a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen if (test_device[0] == '\0') 1124a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen return true; 11306190d8415219d9eef7d8f04b52a109e34575a76Kay Sievers return strcmp(dev_name(device->dev), test_device) == 0; 1144a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen} 1154a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 1164a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoenstatic unsigned long dmatest_random(void) 1174a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen{ 1184a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen unsigned long buf; 1194a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 1204a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen get_random_bytes(&buf, sizeof(buf)); 1214a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen return buf; 1224a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen} 1234a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 124b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williamsstatic void dmatest_init_srcs(u8 **bufs, unsigned int start, unsigned int len) 1254a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen{ 1264a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen unsigned int i; 127b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams u8 *buf; 128b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams 129b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams for (; (buf = *bufs); bufs++) { 130b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams for (i = 0; i < start; i++) 131b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams buf[i] = PATTERN_SRC | (~i & PATTERN_COUNT_MASK); 132b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams for ( ; i < start + len; i++) 133b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams buf[i] = PATTERN_SRC | PATTERN_COPY 134c019894efc9c9ba5939948caa78c133b1ec8ae63Joe Perches | (~i & PATTERN_COUNT_MASK); 135b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams for ( ; i < test_buf_size; i++) 136b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams buf[i] = PATTERN_SRC | (~i & PATTERN_COUNT_MASK); 137b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams buf++; 138b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams } 1394a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen} 1404a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 141b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williamsstatic void dmatest_init_dsts(u8 **bufs, unsigned int start, unsigned int len) 1424a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen{ 1434a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen unsigned int i; 144b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams u8 *buf; 145b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams 146b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams for (; (buf = *bufs); bufs++) { 147b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams for (i = 0; i < start; i++) 148b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams buf[i] = PATTERN_DST | (~i & PATTERN_COUNT_MASK); 149b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams for ( ; i < start + len; i++) 150b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams buf[i] = PATTERN_DST | PATTERN_OVERWRITE 151b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams | (~i & PATTERN_COUNT_MASK); 152b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams for ( ; i < test_buf_size; i++) 153b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams buf[i] = PATTERN_DST | (~i & PATTERN_COUNT_MASK); 154b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams } 1554a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen} 1564a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 1574a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoenstatic void dmatest_mismatch(u8 actual, u8 pattern, unsigned int index, 1584a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen unsigned int counter, bool is_srcbuf) 1594a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen{ 1604a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen u8 diff = actual ^ pattern; 1614a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen u8 expected = pattern | (~counter & PATTERN_COUNT_MASK); 1624a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen const char *thread_name = current->comm; 1634a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 1644a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen if (is_srcbuf) 1654a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen pr_warning("%s: srcbuf[0x%x] overwritten!" 1664a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen " Expected %02x, got %02x\n", 1674a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen thread_name, index, expected, actual); 1684a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen else if ((pattern & PATTERN_COPY) 1694a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen && (diff & (PATTERN_COPY | PATTERN_OVERWRITE))) 1704a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen pr_warning("%s: dstbuf[0x%x] not copied!" 1714a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen " Expected %02x, got %02x\n", 1724a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen thread_name, index, expected, actual); 1734a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen else if (diff & PATTERN_SRC) 1744a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen pr_warning("%s: dstbuf[0x%x] was copied!" 1754a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen " Expected %02x, got %02x\n", 1764a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen thread_name, index, expected, actual); 1774a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen else 1784a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen pr_warning("%s: dstbuf[0x%x] mismatch!" 1794a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen " Expected %02x, got %02x\n", 1804a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen thread_name, index, expected, actual); 1814a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen} 1824a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 183b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williamsstatic unsigned int dmatest_verify(u8 **bufs, unsigned int start, 1844a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen unsigned int end, unsigned int counter, u8 pattern, 1854a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen bool is_srcbuf) 1864a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen{ 1874a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen unsigned int i; 1884a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen unsigned int error_count = 0; 1894a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen u8 actual; 190b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams u8 expected; 191b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams u8 *buf; 192b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams unsigned int counter_orig = counter; 193b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams 194b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams for (; (buf = *bufs); bufs++) { 195b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams counter = counter_orig; 196b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams for (i = start; i < end; i++) { 197b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams actual = buf[i]; 198b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams expected = pattern | (~counter & PATTERN_COUNT_MASK); 199b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams if (actual != expected) { 200b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams if (error_count < 32) 201b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams dmatest_mismatch(actual, pattern, i, 202b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams counter, is_srcbuf); 203b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams error_count++; 204b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams } 205b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams counter++; 2064a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen } 2074a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen } 2084a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 2094a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen if (error_count > 32) 2104a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen pr_warning("%s: %u errors suppressed\n", 2114a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen current->comm, error_count - 32); 2124a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 2134a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen return error_count; 2144a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen} 2154a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 216e44e0aa3cfa97cddff01704751a4b25151830c72Dan Williamsstatic void dmatest_callback(void *completion) 217e44e0aa3cfa97cddff01704751a4b25151830c72Dan Williams{ 218e44e0aa3cfa97cddff01704751a4b25151830c72Dan Williams complete(completion); 219e44e0aa3cfa97cddff01704751a4b25151830c72Dan Williams} 220e44e0aa3cfa97cddff01704751a4b25151830c72Dan Williams 2214a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen/* 2224a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen * This function repeatedly tests DMA transfers of various lengths and 223b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams * offsets for a given operation type until it is told to exit by 224b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams * kthread_stop(). There may be multiple threads running this function 225b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams * in parallel for a single channel, and there may be multiple channels 226b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams * being tested in parallel. 2274a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen * 2284a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen * Before each test, the source and destination buffer is initialized 2294a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen * with a known pattern. This pattern is different depending on 2304a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen * whether it's in an area which is supposed to be copied or 2314a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen * overwritten, and different in the source and destination buffers. 2324a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen * So if the DMA engine doesn't copy exactly what we tell it to copy, 2334a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen * we'll notice. 2344a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen */ 2354a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoenstatic int dmatest_func(void *data) 2364a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen{ 2374a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen struct dmatest_thread *thread = data; 2384a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen struct dma_chan *chan; 2394a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen const char *thread_name; 2404a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen unsigned int src_off, dst_off, len; 2414a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen unsigned int error_count; 2424a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen unsigned int failed_tests = 0; 2434a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen unsigned int total_tests = 0; 2444a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen dma_cookie_t cookie; 2454a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen enum dma_status status; 246b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams enum dma_ctrl_flags flags; 24794de648d72c8bc833590523f22386d4babbea988Anatolij Gustschin u8 pq_coefs[pq_sources + 1]; 2484a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen int ret; 249b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams int src_cnt; 250b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams int dst_cnt; 251b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams int i; 2524a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 2534a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen thread_name = current->comm; 2544a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 2554a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen ret = -ENOMEM; 2564a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 2574a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen smp_rmb(); 2584a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen chan = thread->chan; 259b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams if (thread->type == DMA_MEMCPY) 260b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams src_cnt = dst_cnt = 1; 261b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams else if (thread->type == DMA_XOR) { 262b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams src_cnt = xor_sources | 1; /* force odd to ensure dst = src */ 263b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams dst_cnt = 1; 26458691d64c44ae41ddf098ecb31e9a994026e3cffDan Williams } else if (thread->type == DMA_PQ) { 26558691d64c44ae41ddf098ecb31e9a994026e3cffDan Williams src_cnt = pq_sources | 1; /* force odd to ensure dst = src */ 26658691d64c44ae41ddf098ecb31e9a994026e3cffDan Williams dst_cnt = 2; 26794de648d72c8bc833590523f22386d4babbea988Anatolij Gustschin for (i = 0; i < src_cnt; i++) 26858691d64c44ae41ddf098ecb31e9a994026e3cffDan Williams pq_coefs[i] = 1; 269b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams } else 270b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams goto err_srcs; 271b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams 272b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams thread->srcs = kcalloc(src_cnt+1, sizeof(u8 *), GFP_KERNEL); 273b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams if (!thread->srcs) 274b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams goto err_srcs; 275b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams for (i = 0; i < src_cnt; i++) { 276b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams thread->srcs[i] = kmalloc(test_buf_size, GFP_KERNEL); 277b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams if (!thread->srcs[i]) 278b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams goto err_srcbuf; 279b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams } 280b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams thread->srcs[i] = NULL; 281b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams 282b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams thread->dsts = kcalloc(dst_cnt+1, sizeof(u8 *), GFP_KERNEL); 283b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams if (!thread->dsts) 284b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams goto err_dsts; 285b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams for (i = 0; i < dst_cnt; i++) { 286b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams thread->dsts[i] = kmalloc(test_buf_size, GFP_KERNEL); 287b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams if (!thread->dsts[i]) 288b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams goto err_dstbuf; 289b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams } 290b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams thread->dsts[i] = NULL; 291b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams 292e44e0aa3cfa97cddff01704751a4b25151830c72Dan Williams set_user_nice(current, 10); 293e44e0aa3cfa97cddff01704751a4b25151830c72Dan Williams 294b203bd3f6b9c3db3b1979c2ff79bb2b9be8f03a3Ira Snyder /* 295b203bd3f6b9c3db3b1979c2ff79bb2b9be8f03a3Ira Snyder * src buffers are freed by the DMAEngine code with dma_unmap_single() 296b203bd3f6b9c3db3b1979c2ff79bb2b9be8f03a3Ira Snyder * dst buffers are freed by ourselves below 297b203bd3f6b9c3db3b1979c2ff79bb2b9be8f03a3Ira Snyder */ 298b203bd3f6b9c3db3b1979c2ff79bb2b9be8f03a3Ira Snyder flags = DMA_CTRL_ACK | DMA_PREP_INTERRUPT 299b203bd3f6b9c3db3b1979c2ff79bb2b9be8f03a3Ira Snyder | DMA_COMPL_SKIP_DEST_UNMAP | DMA_COMPL_SRC_UNMAP_SINGLE; 3004a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 3010a2ff57d6fba92842272889b4bca447344cd9d36Nicolas Ferre while (!kthread_should_stop() 3020a2ff57d6fba92842272889b4bca447344cd9d36Nicolas Ferre && !(iterations && total_tests >= iterations)) { 303d86be86e9aab221089d72399072511f13fe2a771Atsushi Nemoto struct dma_device *dev = chan->device; 304b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams struct dma_async_tx_descriptor *tx = NULL; 305b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams dma_addr_t dma_srcs[src_cnt]; 306b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams dma_addr_t dma_dsts[dst_cnt]; 307e44e0aa3cfa97cddff01704751a4b25151830c72Dan Williams struct completion cmp; 308d42efe6bfb4eed8314c8ce3547f21954a4140399Viresh Kumar unsigned long tmo = msecs_to_jiffies(timeout); 30983544ae9f3991bfc7d5e0fe9a3008cd05a8d57b7Dan Williams u8 align = 0; 310d86be86e9aab221089d72399072511f13fe2a771Atsushi Nemoto 3114a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen total_tests++; 3124a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 31383544ae9f3991bfc7d5e0fe9a3008cd05a8d57b7Dan Williams /* honor alignment restrictions */ 31483544ae9f3991bfc7d5e0fe9a3008cd05a8d57b7Dan Williams if (thread->type == DMA_MEMCPY) 31583544ae9f3991bfc7d5e0fe9a3008cd05a8d57b7Dan Williams align = dev->copy_align; 31683544ae9f3991bfc7d5e0fe9a3008cd05a8d57b7Dan Williams else if (thread->type == DMA_XOR) 31783544ae9f3991bfc7d5e0fe9a3008cd05a8d57b7Dan Williams align = dev->xor_align; 31883544ae9f3991bfc7d5e0fe9a3008cd05a8d57b7Dan Williams else if (thread->type == DMA_PQ) 31983544ae9f3991bfc7d5e0fe9a3008cd05a8d57b7Dan Williams align = dev->pq_align; 32083544ae9f3991bfc7d5e0fe9a3008cd05a8d57b7Dan Williams 321cfe4f2751ef1a5390b56c5d263f90b6ff138ba31Guennadi Liakhovetski if (1 << align > test_buf_size) { 322cfe4f2751ef1a5390b56c5d263f90b6ff138ba31Guennadi Liakhovetski pr_err("%u-byte buffer too small for %d-byte alignment\n", 323cfe4f2751ef1a5390b56c5d263f90b6ff138ba31Guennadi Liakhovetski test_buf_size, 1 << align); 324cfe4f2751ef1a5390b56c5d263f90b6ff138ba31Guennadi Liakhovetski break; 325cfe4f2751ef1a5390b56c5d263f90b6ff138ba31Guennadi Liakhovetski } 326cfe4f2751ef1a5390b56c5d263f90b6ff138ba31Guennadi Liakhovetski 327cfe4f2751ef1a5390b56c5d263f90b6ff138ba31Guennadi Liakhovetski len = dmatest_random() % test_buf_size + 1; 32883544ae9f3991bfc7d5e0fe9a3008cd05a8d57b7Dan Williams len = (len >> align) << align; 329cfe4f2751ef1a5390b56c5d263f90b6ff138ba31Guennadi Liakhovetski if (!len) 330cfe4f2751ef1a5390b56c5d263f90b6ff138ba31Guennadi Liakhovetski len = 1 << align; 331cfe4f2751ef1a5390b56c5d263f90b6ff138ba31Guennadi Liakhovetski src_off = dmatest_random() % (test_buf_size - len + 1); 332cfe4f2751ef1a5390b56c5d263f90b6ff138ba31Guennadi Liakhovetski dst_off = dmatest_random() % (test_buf_size - len + 1); 333cfe4f2751ef1a5390b56c5d263f90b6ff138ba31Guennadi Liakhovetski 33483544ae9f3991bfc7d5e0fe9a3008cd05a8d57b7Dan Williams src_off = (src_off >> align) << align; 33583544ae9f3991bfc7d5e0fe9a3008cd05a8d57b7Dan Williams dst_off = (dst_off >> align) << align; 33683544ae9f3991bfc7d5e0fe9a3008cd05a8d57b7Dan Williams 337b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams dmatest_init_srcs(thread->srcs, src_off, len); 338b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams dmatest_init_dsts(thread->dsts, dst_off, len); 3394a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 340b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams for (i = 0; i < src_cnt; i++) { 341b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams u8 *buf = thread->srcs[i] + src_off; 342b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams 343b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams dma_srcs[i] = dma_map_single(dev->dev, buf, len, 344b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams DMA_TO_DEVICE); 345b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams } 346d86be86e9aab221089d72399072511f13fe2a771Atsushi Nemoto /* map with DMA_BIDIRECTIONAL to force writeback/invalidate */ 347b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams for (i = 0; i < dst_cnt; i++) { 348b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams dma_dsts[i] = dma_map_single(dev->dev, thread->dsts[i], 349b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams test_buf_size, 350b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams DMA_BIDIRECTIONAL); 351b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams } 352b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams 35383544ae9f3991bfc7d5e0fe9a3008cd05a8d57b7Dan Williams 354b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams if (thread->type == DMA_MEMCPY) 355b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams tx = dev->device_prep_dma_memcpy(chan, 356b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams dma_dsts[0] + dst_off, 357b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams dma_srcs[0], len, 358b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams flags); 359b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams else if (thread->type == DMA_XOR) 360b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams tx = dev->device_prep_dma_xor(chan, 361b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams dma_dsts[0] + dst_off, 36267b9124f734b22b30d9adf18c39fe795e2901070Dan Williams dma_srcs, src_cnt, 363b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams len, flags); 36458691d64c44ae41ddf098ecb31e9a994026e3cffDan Williams else if (thread->type == DMA_PQ) { 36558691d64c44ae41ddf098ecb31e9a994026e3cffDan Williams dma_addr_t dma_pq[dst_cnt]; 36658691d64c44ae41ddf098ecb31e9a994026e3cffDan Williams 36758691d64c44ae41ddf098ecb31e9a994026e3cffDan Williams for (i = 0; i < dst_cnt; i++) 36858691d64c44ae41ddf098ecb31e9a994026e3cffDan Williams dma_pq[i] = dma_dsts[i] + dst_off; 36958691d64c44ae41ddf098ecb31e9a994026e3cffDan Williams tx = dev->device_prep_dma_pq(chan, dma_pq, dma_srcs, 37094de648d72c8bc833590523f22386d4babbea988Anatolij Gustschin src_cnt, pq_coefs, 37158691d64c44ae41ddf098ecb31e9a994026e3cffDan Williams len, flags); 37258691d64c44ae41ddf098ecb31e9a994026e3cffDan Williams } 373d86be86e9aab221089d72399072511f13fe2a771Atsushi Nemoto 374d86be86e9aab221089d72399072511f13fe2a771Atsushi Nemoto if (!tx) { 375b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams for (i = 0; i < src_cnt; i++) 376b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams dma_unmap_single(dev->dev, dma_srcs[i], len, 377b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams DMA_TO_DEVICE); 378b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams for (i = 0; i < dst_cnt; i++) 379b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams dma_unmap_single(dev->dev, dma_dsts[i], 380b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams test_buf_size, 381b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams DMA_BIDIRECTIONAL); 382d86be86e9aab221089d72399072511f13fe2a771Atsushi Nemoto pr_warning("%s: #%u: prep error with src_off=0x%x " 383d86be86e9aab221089d72399072511f13fe2a771Atsushi Nemoto "dst_off=0x%x len=0x%x\n", 384d86be86e9aab221089d72399072511f13fe2a771Atsushi Nemoto thread_name, total_tests - 1, 385d86be86e9aab221089d72399072511f13fe2a771Atsushi Nemoto src_off, dst_off, len); 386d86be86e9aab221089d72399072511f13fe2a771Atsushi Nemoto msleep(100); 387d86be86e9aab221089d72399072511f13fe2a771Atsushi Nemoto failed_tests++; 388d86be86e9aab221089d72399072511f13fe2a771Atsushi Nemoto continue; 389d86be86e9aab221089d72399072511f13fe2a771Atsushi Nemoto } 390e44e0aa3cfa97cddff01704751a4b25151830c72Dan Williams 391e44e0aa3cfa97cddff01704751a4b25151830c72Dan Williams init_completion(&cmp); 392e44e0aa3cfa97cddff01704751a4b25151830c72Dan Williams tx->callback = dmatest_callback; 393e44e0aa3cfa97cddff01704751a4b25151830c72Dan Williams tx->callback_param = &cmp; 394d86be86e9aab221089d72399072511f13fe2a771Atsushi Nemoto cookie = tx->tx_submit(tx); 395d86be86e9aab221089d72399072511f13fe2a771Atsushi Nemoto 3964a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen if (dma_submit_error(cookie)) { 3974a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen pr_warning("%s: #%u: submit error %d with src_off=0x%x " 3984a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen "dst_off=0x%x len=0x%x\n", 3994a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen thread_name, total_tests - 1, cookie, 4004a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen src_off, dst_off, len); 4014a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen msleep(100); 4024a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen failed_tests++; 4034a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen continue; 4044a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen } 405b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams dma_async_issue_pending(chan); 4064a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 407e44e0aa3cfa97cddff01704751a4b25151830c72Dan Williams tmo = wait_for_completion_timeout(&cmp, tmo); 408e44e0aa3cfa97cddff01704751a4b25151830c72Dan Williams status = dma_async_is_tx_complete(chan, cookie, NULL, NULL); 4094a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 410e44e0aa3cfa97cddff01704751a4b25151830c72Dan Williams if (tmo == 0) { 411e44e0aa3cfa97cddff01704751a4b25151830c72Dan Williams pr_warning("%s: #%u: test timed out\n", 412e44e0aa3cfa97cddff01704751a4b25151830c72Dan Williams thread_name, total_tests - 1); 413e44e0aa3cfa97cddff01704751a4b25151830c72Dan Williams failed_tests++; 414e44e0aa3cfa97cddff01704751a4b25151830c72Dan Williams continue; 415e44e0aa3cfa97cddff01704751a4b25151830c72Dan Williams } else if (status != DMA_SUCCESS) { 416e44e0aa3cfa97cddff01704751a4b25151830c72Dan Williams pr_warning("%s: #%u: got completion callback," 417e44e0aa3cfa97cddff01704751a4b25151830c72Dan Williams " but status is \'%s\'\n", 418e44e0aa3cfa97cddff01704751a4b25151830c72Dan Williams thread_name, total_tests - 1, 419e44e0aa3cfa97cddff01704751a4b25151830c72Dan Williams status == DMA_ERROR ? "error" : "in progress"); 4204a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen failed_tests++; 4214a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen continue; 4224a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen } 423e44e0aa3cfa97cddff01704751a4b25151830c72Dan Williams 424d86be86e9aab221089d72399072511f13fe2a771Atsushi Nemoto /* Unmap by myself (see DMA_COMPL_SKIP_DEST_UNMAP above) */ 425b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams for (i = 0; i < dst_cnt; i++) 426b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams dma_unmap_single(dev->dev, dma_dsts[i], test_buf_size, 427b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams DMA_BIDIRECTIONAL); 4284a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 4294a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen error_count = 0; 4304a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 4314a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen pr_debug("%s: verifying source buffer...\n", thread_name); 432b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams error_count += dmatest_verify(thread->srcs, 0, src_off, 4334a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 0, PATTERN_SRC, true); 434b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams error_count += dmatest_verify(thread->srcs, src_off, 4354a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen src_off + len, src_off, 4364a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen PATTERN_SRC | PATTERN_COPY, true); 437b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams error_count += dmatest_verify(thread->srcs, src_off + len, 4384a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen test_buf_size, src_off + len, 4394a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen PATTERN_SRC, true); 4404a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 4414a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen pr_debug("%s: verifying dest buffer...\n", 4424a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen thread->task->comm); 443b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams error_count += dmatest_verify(thread->dsts, 0, dst_off, 4444a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 0, PATTERN_DST, false); 445b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams error_count += dmatest_verify(thread->dsts, dst_off, 4464a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen dst_off + len, src_off, 4474a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen PATTERN_SRC | PATTERN_COPY, false); 448b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams error_count += dmatest_verify(thread->dsts, dst_off + len, 4494a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen test_buf_size, dst_off + len, 4504a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen PATTERN_DST, false); 4514a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 4524a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen if (error_count) { 4534a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen pr_warning("%s: #%u: %u errors with " 4544a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen "src_off=0x%x dst_off=0x%x len=0x%x\n", 4554a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen thread_name, total_tests - 1, error_count, 4564a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen src_off, dst_off, len); 4574a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen failed_tests++; 4584a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen } else { 4594a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen pr_debug("%s: #%u: No errors with " 4604a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen "src_off=0x%x dst_off=0x%x len=0x%x\n", 4614a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen thread_name, total_tests - 1, 4624a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen src_off, dst_off, len); 4634a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen } 4644a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen } 4654a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 4664a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen ret = 0; 467b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams for (i = 0; thread->dsts[i]; i++) 468b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams kfree(thread->dsts[i]); 4694a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoenerr_dstbuf: 470b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams kfree(thread->dsts); 471b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williamserr_dsts: 472b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams for (i = 0; thread->srcs[i]; i++) 473b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams kfree(thread->srcs[i]); 4744a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoenerr_srcbuf: 475b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams kfree(thread->srcs); 476b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williamserr_srcs: 4774a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen pr_notice("%s: terminating after %u tests, %u failures (status %d)\n", 4784a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen thread_name, total_tests, failed_tests, ret); 4790a2ff57d6fba92842272889b4bca447344cd9d36Nicolas Ferre 4800a2ff57d6fba92842272889b4bca447344cd9d36Nicolas Ferre if (iterations > 0) 4810a2ff57d6fba92842272889b4bca447344cd9d36Nicolas Ferre while (!kthread_should_stop()) { 482b953df7c70740cd7593072ebec77a8f658505630Yong Zhang DECLARE_WAIT_QUEUE_HEAD_ONSTACK(wait_dmatest_exit); 4830a2ff57d6fba92842272889b4bca447344cd9d36Nicolas Ferre interruptible_sleep_on(&wait_dmatest_exit); 4840a2ff57d6fba92842272889b4bca447344cd9d36Nicolas Ferre } 4850a2ff57d6fba92842272889b4bca447344cd9d36Nicolas Ferre 4864a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen return ret; 4874a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen} 4884a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 4894a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoenstatic void dmatest_cleanup_channel(struct dmatest_chan *dtc) 4904a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen{ 4914a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen struct dmatest_thread *thread; 4924a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen struct dmatest_thread *_thread; 4934a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen int ret; 4944a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 4954a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen list_for_each_entry_safe(thread, _thread, &dtc->threads, node) { 4964a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen ret = kthread_stop(thread->task); 4974a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen pr_debug("dmatest: thread %s exited with status %d\n", 4984a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen thread->task->comm, ret); 4994a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen list_del(&thread->node); 5004a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen kfree(thread); 5014a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen } 5024a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen kfree(dtc); 5034a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen} 5044a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 505b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williamsstatic int dmatest_add_threads(struct dmatest_chan *dtc, enum dma_transaction_type type) 5064a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen{ 507b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams struct dmatest_thread *thread; 508b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams struct dma_chan *chan = dtc->chan; 509b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams char *op; 510b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams unsigned int i; 5114a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 512b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams if (type == DMA_MEMCPY) 513b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams op = "copy"; 514b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams else if (type == DMA_XOR) 515b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams op = "xor"; 51658691d64c44ae41ddf098ecb31e9a994026e3cffDan Williams else if (type == DMA_PQ) 51758691d64c44ae41ddf098ecb31e9a994026e3cffDan Williams op = "pq"; 518b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams else 519b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams return -EINVAL; 5204a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 5214a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen for (i = 0; i < threads_per_chan; i++) { 5224a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen thread = kzalloc(sizeof(struct dmatest_thread), GFP_KERNEL); 5234a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen if (!thread) { 524b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams pr_warning("dmatest: No memory for %s-%s%u\n", 525b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams dma_chan_name(chan), op, i); 526b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams 5274a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen break; 5284a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen } 5294a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen thread->chan = dtc->chan; 530b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams thread->type = type; 5314a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen smp_wmb(); 532b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams thread->task = kthread_run(dmatest_func, thread, "%s-%s%u", 533b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams dma_chan_name(chan), op, i); 5344a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen if (IS_ERR(thread->task)) { 535b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams pr_warning("dmatest: Failed to run thread %s-%s%u\n", 536b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams dma_chan_name(chan), op, i); 5374a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen kfree(thread); 5384a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen break; 5394a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen } 5404a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 5414a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen /* srcbuf and dstbuf are allocated by the thread itself */ 5424a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 5434a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen list_add_tail(&thread->node, &dtc->threads); 5444a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen } 5454a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 546b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams return i; 547b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams} 548b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams 549b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williamsstatic int dmatest_add_channel(struct dma_chan *chan) 550b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams{ 551b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams struct dmatest_chan *dtc; 552b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams struct dma_device *dma_dev = chan->device; 553b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams unsigned int thread_count = 0; 554b9033e682e86f3c6a66763f9b6a3935c5c64e145Kulikov Vasiliy int cnt; 555b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams 556b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams dtc = kmalloc(sizeof(struct dmatest_chan), GFP_KERNEL); 557b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams if (!dtc) { 558b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams pr_warning("dmatest: No memory for %s\n", dma_chan_name(chan)); 559b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams return -ENOMEM; 560b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams } 561b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams 562b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams dtc->chan = chan; 563b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams INIT_LIST_HEAD(&dtc->threads); 564b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams 565b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams if (dma_has_cap(DMA_MEMCPY, dma_dev->cap_mask)) { 566b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams cnt = dmatest_add_threads(dtc, DMA_MEMCPY); 567f1aef8b6e6abf32a3a269542f95a19e2cb319f6cNicolas Ferre thread_count += cnt > 0 ? cnt : 0; 568b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams } 569b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams if (dma_has_cap(DMA_XOR, dma_dev->cap_mask)) { 570b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams cnt = dmatest_add_threads(dtc, DMA_XOR); 571f1aef8b6e6abf32a3a269542f95a19e2cb319f6cNicolas Ferre thread_count += cnt > 0 ? cnt : 0; 572b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams } 57358691d64c44ae41ddf098ecb31e9a994026e3cffDan Williams if (dma_has_cap(DMA_PQ, dma_dev->cap_mask)) { 57458691d64c44ae41ddf098ecb31e9a994026e3cffDan Williams cnt = dmatest_add_threads(dtc, DMA_PQ); 57558691d64c44ae41ddf098ecb31e9a994026e3cffDan Williams thread_count += cnt > 0 ?: 0; 57658691d64c44ae41ddf098ecb31e9a994026e3cffDan Williams } 577b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams 578b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams pr_info("dmatest: Started %u threads using %s\n", 579b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams thread_count, dma_chan_name(chan)); 5804a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 5814a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen list_add_tail(&dtc->node, &dmatest_channels); 5824a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen nr_channels++; 5834a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 58433df8ca068123457db56c316946a3c0e4ef787d6Dan Williams return 0; 5854a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen} 5864a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 5877dd602510128d7a64b11ff3b7d4f30ac8e3946ceDan Williamsstatic bool filter(struct dma_chan *chan, void *param) 5884a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen{ 58933df8ca068123457db56c316946a3c0e4ef787d6Dan Williams if (!dmatest_match_channel(chan) || !dmatest_match_device(chan->device)) 5907dd602510128d7a64b11ff3b7d4f30ac8e3946ceDan Williams return false; 59133df8ca068123457db56c316946a3c0e4ef787d6Dan Williams else 5927dd602510128d7a64b11ff3b7d4f30ac8e3946ceDan Williams return true; 5934a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen} 5944a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 5954a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoenstatic int __init dmatest_init(void) 5964a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen{ 59733df8ca068123457db56c316946a3c0e4ef787d6Dan Williams dma_cap_mask_t mask; 59833df8ca068123457db56c316946a3c0e4ef787d6Dan Williams struct dma_chan *chan; 59933df8ca068123457db56c316946a3c0e4ef787d6Dan Williams int err = 0; 60033df8ca068123457db56c316946a3c0e4ef787d6Dan Williams 60133df8ca068123457db56c316946a3c0e4ef787d6Dan Williams dma_cap_zero(mask); 60233df8ca068123457db56c316946a3c0e4ef787d6Dan Williams dma_cap_set(DMA_MEMCPY, mask); 60333df8ca068123457db56c316946a3c0e4ef787d6Dan Williams for (;;) { 60433df8ca068123457db56c316946a3c0e4ef787d6Dan Williams chan = dma_request_channel(mask, filter, NULL); 60533df8ca068123457db56c316946a3c0e4ef787d6Dan Williams if (chan) { 60633df8ca068123457db56c316946a3c0e4ef787d6Dan Williams err = dmatest_add_channel(chan); 607c56c81abe7e684bc6203632d807303eb765690dcDan Williams if (err) { 60833df8ca068123457db56c316946a3c0e4ef787d6Dan Williams dma_release_channel(chan); 60933df8ca068123457db56c316946a3c0e4ef787d6Dan Williams break; /* add_channel failed, punt */ 61033df8ca068123457db56c316946a3c0e4ef787d6Dan Williams } 61133df8ca068123457db56c316946a3c0e4ef787d6Dan Williams } else 61233df8ca068123457db56c316946a3c0e4ef787d6Dan Williams break; /* no more channels available */ 61333df8ca068123457db56c316946a3c0e4ef787d6Dan Williams if (max_channels && nr_channels >= max_channels) 61433df8ca068123457db56c316946a3c0e4ef787d6Dan Williams break; /* we have all we need */ 61533df8ca068123457db56c316946a3c0e4ef787d6Dan Williams } 6164a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 61733df8ca068123457db56c316946a3c0e4ef787d6Dan Williams return err; 6184a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen} 61933df8ca068123457db56c316946a3c0e4ef787d6Dan Williams/* when compiled-in wait for drivers to load first */ 62033df8ca068123457db56c316946a3c0e4ef787d6Dan Williamslate_initcall(dmatest_init); 6214a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 6224a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoenstatic void __exit dmatest_exit(void) 6234a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen{ 62433df8ca068123457db56c316946a3c0e4ef787d6Dan Williams struct dmatest_chan *dtc, *_dtc; 6257cbd4877e5b167b56a3d6033b926a9f925186e12Dan Williams struct dma_chan *chan; 62633df8ca068123457db56c316946a3c0e4ef787d6Dan Williams 62733df8ca068123457db56c316946a3c0e4ef787d6Dan Williams list_for_each_entry_safe(dtc, _dtc, &dmatest_channels, node) { 62833df8ca068123457db56c316946a3c0e4ef787d6Dan Williams list_del(&dtc->node); 6297cbd4877e5b167b56a3d6033b926a9f925186e12Dan Williams chan = dtc->chan; 63033df8ca068123457db56c316946a3c0e4ef787d6Dan Williams dmatest_cleanup_channel(dtc); 63133df8ca068123457db56c316946a3c0e4ef787d6Dan Williams pr_debug("dmatest: dropped channel %s\n", 6327cbd4877e5b167b56a3d6033b926a9f925186e12Dan Williams dma_chan_name(chan)); 6337cbd4877e5b167b56a3d6033b926a9f925186e12Dan Williams dma_release_channel(chan); 63433df8ca068123457db56c316946a3c0e4ef787d6Dan Williams } 6354a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen} 6364a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoenmodule_exit(dmatest_exit); 6374a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 638e05503ef1186ad33dfe56794407891eb1dd93ef6Jean DelvareMODULE_AUTHOR("Haavard Skinnemoen (Atmel)"); 6394a776f0aa922a552460192c07b56f4fe9cd82632Haavard SkinnemoenMODULE_LICENSE("GPL v2"); 640