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