dmatest.c revision b9033e682e86f3c6a66763f9b6a3935c5c64e145
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> 114a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen#include <linux/dmaengine.h> 124a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen#include <linux/init.h> 134a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen#include <linux/kthread.h> 144a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen#include <linux/module.h> 154a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen#include <linux/moduleparam.h> 164a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen#include <linux/random.h> 175a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h> 184a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen#include <linux/wait.h> 194a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 204a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoenstatic unsigned int test_buf_size = 16384; 214a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoenmodule_param(test_buf_size, uint, S_IRUGO); 224a776f0aa922a552460192c07b56f4fe9cd82632Haavard SkinnemoenMODULE_PARM_DESC(test_buf_size, "Size of the memcpy test buffer"); 234a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 2406190d8415219d9eef7d8f04b52a109e34575a76Kay Sieversstatic char test_channel[20]; 254a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoenmodule_param_string(channel, test_channel, sizeof(test_channel), S_IRUGO); 264a776f0aa922a552460192c07b56f4fe9cd82632Haavard SkinnemoenMODULE_PARM_DESC(channel, "Bus ID of the channel to test (default: any)"); 274a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 2806190d8415219d9eef7d8f04b52a109e34575a76Kay Sieversstatic char test_device[20]; 294a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoenmodule_param_string(device, test_device, sizeof(test_device), S_IRUGO); 304a776f0aa922a552460192c07b56f4fe9cd82632Haavard SkinnemoenMODULE_PARM_DESC(device, "Bus ID of the DMA Engine to test (default: any)"); 314a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 324a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoenstatic unsigned int threads_per_chan = 1; 334a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoenmodule_param(threads_per_chan, uint, S_IRUGO); 344a776f0aa922a552460192c07b56f4fe9cd82632Haavard SkinnemoenMODULE_PARM_DESC(threads_per_chan, 354a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen "Number of threads to start per channel (default: 1)"); 364a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 374a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoenstatic unsigned int max_channels; 384a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoenmodule_param(max_channels, uint, S_IRUGO); 3933df8ca068123457db56c316946a3c0e4ef787d6Dan WilliamsMODULE_PARM_DESC(max_channels, 404a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen "Maximum number of channels to use (default: all)"); 414a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 420a2ff57d6fba92842272889b4bca447344cd9d36Nicolas Ferrestatic unsigned int iterations; 430a2ff57d6fba92842272889b4bca447344cd9d36Nicolas Ferremodule_param(iterations, uint, S_IRUGO); 440a2ff57d6fba92842272889b4bca447344cd9d36Nicolas FerreMODULE_PARM_DESC(iterations, 450a2ff57d6fba92842272889b4bca447344cd9d36Nicolas Ferre "Iterations before stopping test (default: infinite)"); 460a2ff57d6fba92842272889b4bca447344cd9d36Nicolas Ferre 47b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williamsstatic unsigned int xor_sources = 3; 48b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williamsmodule_param(xor_sources, uint, S_IRUGO); 49b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan WilliamsMODULE_PARM_DESC(xor_sources, 50b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams "Number of xor source buffers (default: 3)"); 51b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams 5258691d64c44ae41ddf098ecb31e9a994026e3cffDan Williamsstatic unsigned int pq_sources = 3; 5358691d64c44ae41ddf098ecb31e9a994026e3cffDan Williamsmodule_param(pq_sources, uint, S_IRUGO); 5458691d64c44ae41ddf098ecb31e9a994026e3cffDan WilliamsMODULE_PARM_DESC(pq_sources, 5558691d64c44ae41ddf098ecb31e9a994026e3cffDan Williams "Number of p+q source buffers (default: 3)"); 5658691d64c44ae41ddf098ecb31e9a994026e3cffDan Williams 574a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen/* 584a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen * Initialization patterns. All bytes in the source buffer has bit 7 594a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen * set, all bytes in the destination buffer has bit 7 cleared. 604a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen * 614a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen * Bit 6 is set for all bytes which are to be copied by the DMA 624a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen * engine. Bit 5 is set for all bytes which are to be overwritten by 634a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen * the DMA engine. 644a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen * 654a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen * The remaining bits are the inverse of a counter which increments by 664a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen * one for each byte address. 674a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen */ 684a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen#define PATTERN_SRC 0x80 694a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen#define PATTERN_DST 0x00 704a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen#define PATTERN_COPY 0x40 714a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen#define PATTERN_OVERWRITE 0x20 724a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen#define PATTERN_COUNT_MASK 0x1f 734a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 744a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoenstruct dmatest_thread { 754a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen struct list_head node; 764a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen struct task_struct *task; 774a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen struct dma_chan *chan; 78b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams u8 **srcs; 79b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams u8 **dsts; 80b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams enum dma_transaction_type type; 814a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen}; 824a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 834a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoenstruct dmatest_chan { 844a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen struct list_head node; 854a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen struct dma_chan *chan; 864a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen struct list_head threads; 874a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen}; 884a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 894a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen/* 904a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen * These are protected by dma_list_mutex since they're only used by 9133df8ca068123457db56c316946a3c0e4ef787d6Dan Williams * the DMA filter function callback 924a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen */ 934a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoenstatic LIST_HEAD(dmatest_channels); 944a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoenstatic unsigned int nr_channels; 954a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 964a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoenstatic bool dmatest_match_channel(struct dma_chan *chan) 974a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen{ 984a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen if (test_channel[0] == '\0') 994a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen return true; 10041d5e59c1299f27983977bcfe3b360600996051cDan Williams return strcmp(dma_chan_name(chan), test_channel) == 0; 1014a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen} 1024a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 1034a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoenstatic bool dmatest_match_device(struct dma_device *device) 1044a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen{ 1054a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen if (test_device[0] == '\0') 1064a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen return true; 10706190d8415219d9eef7d8f04b52a109e34575a76Kay Sievers return strcmp(dev_name(device->dev), test_device) == 0; 1084a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen} 1094a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 1104a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoenstatic unsigned long dmatest_random(void) 1114a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen{ 1124a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen unsigned long buf; 1134a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 1144a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen get_random_bytes(&buf, sizeof(buf)); 1154a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen return buf; 1164a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen} 1174a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 118b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williamsstatic void dmatest_init_srcs(u8 **bufs, unsigned int start, unsigned int len) 1194a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen{ 1204a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen unsigned int i; 121b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams u8 *buf; 122b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams 123b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams for (; (buf = *bufs); bufs++) { 124b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams for (i = 0; i < start; i++) 125b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams buf[i] = PATTERN_SRC | (~i & PATTERN_COUNT_MASK); 126b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams for ( ; i < start + len; i++) 127b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams buf[i] = PATTERN_SRC | PATTERN_COPY 128c019894efc9c9ba5939948caa78c133b1ec8ae63Joe Perches | (~i & PATTERN_COUNT_MASK); 129b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams for ( ; i < test_buf_size; i++) 130b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams buf[i] = PATTERN_SRC | (~i & PATTERN_COUNT_MASK); 131b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams buf++; 132b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams } 1334a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen} 1344a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 135b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williamsstatic void dmatest_init_dsts(u8 **bufs, unsigned int start, unsigned int len) 1364a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen{ 1374a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen unsigned int i; 138b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams u8 *buf; 139b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams 140b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams for (; (buf = *bufs); bufs++) { 141b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams for (i = 0; i < start; i++) 142b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams buf[i] = PATTERN_DST | (~i & PATTERN_COUNT_MASK); 143b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams for ( ; i < start + len; i++) 144b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams buf[i] = PATTERN_DST | PATTERN_OVERWRITE 145b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams | (~i & PATTERN_COUNT_MASK); 146b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams for ( ; i < test_buf_size; i++) 147b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams buf[i] = PATTERN_DST | (~i & PATTERN_COUNT_MASK); 148b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams } 1494a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen} 1504a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 1514a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoenstatic void dmatest_mismatch(u8 actual, u8 pattern, unsigned int index, 1524a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen unsigned int counter, bool is_srcbuf) 1534a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen{ 1544a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen u8 diff = actual ^ pattern; 1554a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen u8 expected = pattern | (~counter & PATTERN_COUNT_MASK); 1564a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen const char *thread_name = current->comm; 1574a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 1584a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen if (is_srcbuf) 1594a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen pr_warning("%s: srcbuf[0x%x] overwritten!" 1604a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen " Expected %02x, got %02x\n", 1614a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen thread_name, index, expected, actual); 1624a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen else if ((pattern & PATTERN_COPY) 1634a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen && (diff & (PATTERN_COPY | PATTERN_OVERWRITE))) 1644a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen pr_warning("%s: dstbuf[0x%x] not copied!" 1654a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen " Expected %02x, got %02x\n", 1664a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen thread_name, index, expected, actual); 1674a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen else if (diff & PATTERN_SRC) 1684a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen pr_warning("%s: dstbuf[0x%x] was copied!" 1694a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen " Expected %02x, got %02x\n", 1704a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen thread_name, index, expected, actual); 1714a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen else 1724a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen pr_warning("%s: dstbuf[0x%x] mismatch!" 1734a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen " Expected %02x, got %02x\n", 1744a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen thread_name, index, expected, actual); 1754a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen} 1764a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 177b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williamsstatic unsigned int dmatest_verify(u8 **bufs, unsigned int start, 1784a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen unsigned int end, unsigned int counter, u8 pattern, 1794a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen bool is_srcbuf) 1804a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen{ 1814a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen unsigned int i; 1824a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen unsigned int error_count = 0; 1834a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen u8 actual; 184b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams u8 expected; 185b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams u8 *buf; 186b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams unsigned int counter_orig = counter; 187b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams 188b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams for (; (buf = *bufs); bufs++) { 189b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams counter = counter_orig; 190b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams for (i = start; i < end; i++) { 191b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams actual = buf[i]; 192b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams expected = pattern | (~counter & PATTERN_COUNT_MASK); 193b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams if (actual != expected) { 194b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams if (error_count < 32) 195b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams dmatest_mismatch(actual, pattern, i, 196b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams counter, is_srcbuf); 197b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams error_count++; 198b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams } 199b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams counter++; 2004a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen } 2014a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen } 2024a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 2034a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen if (error_count > 32) 2044a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen pr_warning("%s: %u errors suppressed\n", 2054a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen current->comm, error_count - 32); 2064a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 2074a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen return error_count; 2084a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen} 2094a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 210e44e0aa3cfa97cddff01704751a4b25151830c72Dan Williamsstatic void dmatest_callback(void *completion) 211e44e0aa3cfa97cddff01704751a4b25151830c72Dan Williams{ 212e44e0aa3cfa97cddff01704751a4b25151830c72Dan Williams complete(completion); 213e44e0aa3cfa97cddff01704751a4b25151830c72Dan Williams} 214e44e0aa3cfa97cddff01704751a4b25151830c72Dan Williams 2154a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen/* 2164a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen * This function repeatedly tests DMA transfers of various lengths and 217b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams * offsets for a given operation type until it is told to exit by 218b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams * kthread_stop(). There may be multiple threads running this function 219b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams * in parallel for a single channel, and there may be multiple channels 220b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams * being tested in parallel. 2214a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen * 2224a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen * Before each test, the source and destination buffer is initialized 2234a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen * with a known pattern. This pattern is different depending on 2244a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen * whether it's in an area which is supposed to be copied or 2254a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen * overwritten, and different in the source and destination buffers. 2264a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen * So if the DMA engine doesn't copy exactly what we tell it to copy, 2274a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen * we'll notice. 2284a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen */ 2294a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoenstatic int dmatest_func(void *data) 2304a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen{ 2314a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen struct dmatest_thread *thread = data; 2324a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen struct dma_chan *chan; 2334a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen const char *thread_name; 2344a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen unsigned int src_off, dst_off, len; 2354a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen unsigned int error_count; 2364a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen unsigned int failed_tests = 0; 2374a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen unsigned int total_tests = 0; 2384a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen dma_cookie_t cookie; 2394a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen enum dma_status status; 240b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams enum dma_ctrl_flags flags; 24194de648d72c8bc833590523f22386d4babbea988Anatolij Gustschin u8 pq_coefs[pq_sources + 1]; 2424a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen int ret; 243b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams int src_cnt; 244b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams int dst_cnt; 245b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams int i; 2464a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 2474a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen thread_name = current->comm; 2484a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 2494a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen ret = -ENOMEM; 2504a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 2514a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen smp_rmb(); 2524a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen chan = thread->chan; 253b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams if (thread->type == DMA_MEMCPY) 254b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams src_cnt = dst_cnt = 1; 255b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams else if (thread->type == DMA_XOR) { 256b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams src_cnt = xor_sources | 1; /* force odd to ensure dst = src */ 257b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams dst_cnt = 1; 25858691d64c44ae41ddf098ecb31e9a994026e3cffDan Williams } else if (thread->type == DMA_PQ) { 25958691d64c44ae41ddf098ecb31e9a994026e3cffDan Williams src_cnt = pq_sources | 1; /* force odd to ensure dst = src */ 26058691d64c44ae41ddf098ecb31e9a994026e3cffDan Williams dst_cnt = 2; 26194de648d72c8bc833590523f22386d4babbea988Anatolij Gustschin for (i = 0; i < src_cnt; i++) 26258691d64c44ae41ddf098ecb31e9a994026e3cffDan Williams pq_coefs[i] = 1; 263b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams } else 264b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams goto err_srcs; 265b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams 266b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams thread->srcs = kcalloc(src_cnt+1, sizeof(u8 *), GFP_KERNEL); 267b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams if (!thread->srcs) 268b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams goto err_srcs; 269b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams for (i = 0; i < src_cnt; i++) { 270b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams thread->srcs[i] = kmalloc(test_buf_size, GFP_KERNEL); 271b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams if (!thread->srcs[i]) 272b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams goto err_srcbuf; 273b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams } 274b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams thread->srcs[i] = NULL; 275b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams 276b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams thread->dsts = kcalloc(dst_cnt+1, sizeof(u8 *), GFP_KERNEL); 277b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams if (!thread->dsts) 278b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams goto err_dsts; 279b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams for (i = 0; i < dst_cnt; i++) { 280b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams thread->dsts[i] = kmalloc(test_buf_size, GFP_KERNEL); 281b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams if (!thread->dsts[i]) 282b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams goto err_dstbuf; 283b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams } 284b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams thread->dsts[i] = NULL; 285b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams 286e44e0aa3cfa97cddff01704751a4b25151830c72Dan Williams set_user_nice(current, 10); 287e44e0aa3cfa97cddff01704751a4b25151830c72Dan Williams 288e44e0aa3cfa97cddff01704751a4b25151830c72Dan Williams flags = DMA_CTRL_ACK | DMA_COMPL_SKIP_DEST_UNMAP | DMA_PREP_INTERRUPT; 2894a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 2900a2ff57d6fba92842272889b4bca447344cd9d36Nicolas Ferre while (!kthread_should_stop() 2910a2ff57d6fba92842272889b4bca447344cd9d36Nicolas Ferre && !(iterations && total_tests >= iterations)) { 292d86be86e9aab221089d72399072511f13fe2a771Atsushi Nemoto struct dma_device *dev = chan->device; 293b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams struct dma_async_tx_descriptor *tx = NULL; 294b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams dma_addr_t dma_srcs[src_cnt]; 295b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams dma_addr_t dma_dsts[dst_cnt]; 296e44e0aa3cfa97cddff01704751a4b25151830c72Dan Williams struct completion cmp; 297e44e0aa3cfa97cddff01704751a4b25151830c72Dan Williams unsigned long tmo = msecs_to_jiffies(3000); 29883544ae9f3991bfc7d5e0fe9a3008cd05a8d57b7Dan Williams u8 align = 0; 299d86be86e9aab221089d72399072511f13fe2a771Atsushi Nemoto 3004a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen total_tests++; 3014a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 30283544ae9f3991bfc7d5e0fe9a3008cd05a8d57b7Dan Williams /* honor alignment restrictions */ 30383544ae9f3991bfc7d5e0fe9a3008cd05a8d57b7Dan Williams if (thread->type == DMA_MEMCPY) 30483544ae9f3991bfc7d5e0fe9a3008cd05a8d57b7Dan Williams align = dev->copy_align; 30583544ae9f3991bfc7d5e0fe9a3008cd05a8d57b7Dan Williams else if (thread->type == DMA_XOR) 30683544ae9f3991bfc7d5e0fe9a3008cd05a8d57b7Dan Williams align = dev->xor_align; 30783544ae9f3991bfc7d5e0fe9a3008cd05a8d57b7Dan Williams else if (thread->type == DMA_PQ) 30883544ae9f3991bfc7d5e0fe9a3008cd05a8d57b7Dan Williams align = dev->pq_align; 30983544ae9f3991bfc7d5e0fe9a3008cd05a8d57b7Dan Williams 310cfe4f2751ef1a5390b56c5d263f90b6ff138ba31Guennadi Liakhovetski if (1 << align > test_buf_size) { 311cfe4f2751ef1a5390b56c5d263f90b6ff138ba31Guennadi Liakhovetski pr_err("%u-byte buffer too small for %d-byte alignment\n", 312cfe4f2751ef1a5390b56c5d263f90b6ff138ba31Guennadi Liakhovetski test_buf_size, 1 << align); 313cfe4f2751ef1a5390b56c5d263f90b6ff138ba31Guennadi Liakhovetski break; 314cfe4f2751ef1a5390b56c5d263f90b6ff138ba31Guennadi Liakhovetski } 315cfe4f2751ef1a5390b56c5d263f90b6ff138ba31Guennadi Liakhovetski 316cfe4f2751ef1a5390b56c5d263f90b6ff138ba31Guennadi Liakhovetski len = dmatest_random() % test_buf_size + 1; 31783544ae9f3991bfc7d5e0fe9a3008cd05a8d57b7Dan Williams len = (len >> align) << align; 318cfe4f2751ef1a5390b56c5d263f90b6ff138ba31Guennadi Liakhovetski if (!len) 319cfe4f2751ef1a5390b56c5d263f90b6ff138ba31Guennadi Liakhovetski len = 1 << align; 320cfe4f2751ef1a5390b56c5d263f90b6ff138ba31Guennadi Liakhovetski src_off = dmatest_random() % (test_buf_size - len + 1); 321cfe4f2751ef1a5390b56c5d263f90b6ff138ba31Guennadi Liakhovetski dst_off = dmatest_random() % (test_buf_size - len + 1); 322cfe4f2751ef1a5390b56c5d263f90b6ff138ba31Guennadi Liakhovetski 32383544ae9f3991bfc7d5e0fe9a3008cd05a8d57b7Dan Williams src_off = (src_off >> align) << align; 32483544ae9f3991bfc7d5e0fe9a3008cd05a8d57b7Dan Williams dst_off = (dst_off >> align) << align; 32583544ae9f3991bfc7d5e0fe9a3008cd05a8d57b7Dan Williams 326b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams dmatest_init_srcs(thread->srcs, src_off, len); 327b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams dmatest_init_dsts(thread->dsts, dst_off, len); 3284a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 329b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams for (i = 0; i < src_cnt; i++) { 330b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams u8 *buf = thread->srcs[i] + src_off; 331b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams 332b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams dma_srcs[i] = dma_map_single(dev->dev, buf, len, 333b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams DMA_TO_DEVICE); 334b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams } 335d86be86e9aab221089d72399072511f13fe2a771Atsushi Nemoto /* map with DMA_BIDIRECTIONAL to force writeback/invalidate */ 336b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams for (i = 0; i < dst_cnt; i++) { 337b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams dma_dsts[i] = dma_map_single(dev->dev, thread->dsts[i], 338b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams test_buf_size, 339b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams DMA_BIDIRECTIONAL); 340b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams } 341b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams 34283544ae9f3991bfc7d5e0fe9a3008cd05a8d57b7Dan Williams 343b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams if (thread->type == DMA_MEMCPY) 344b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams tx = dev->device_prep_dma_memcpy(chan, 345b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams dma_dsts[0] + dst_off, 346b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams dma_srcs[0], len, 347b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams flags); 348b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams else if (thread->type == DMA_XOR) 349b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams tx = dev->device_prep_dma_xor(chan, 350b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams dma_dsts[0] + dst_off, 35167b9124f734b22b30d9adf18c39fe795e2901070Dan Williams dma_srcs, src_cnt, 352b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams len, flags); 35358691d64c44ae41ddf098ecb31e9a994026e3cffDan Williams else if (thread->type == DMA_PQ) { 35458691d64c44ae41ddf098ecb31e9a994026e3cffDan Williams dma_addr_t dma_pq[dst_cnt]; 35558691d64c44ae41ddf098ecb31e9a994026e3cffDan Williams 35658691d64c44ae41ddf098ecb31e9a994026e3cffDan Williams for (i = 0; i < dst_cnt; i++) 35758691d64c44ae41ddf098ecb31e9a994026e3cffDan Williams dma_pq[i] = dma_dsts[i] + dst_off; 35858691d64c44ae41ddf098ecb31e9a994026e3cffDan Williams tx = dev->device_prep_dma_pq(chan, dma_pq, dma_srcs, 35994de648d72c8bc833590523f22386d4babbea988Anatolij Gustschin src_cnt, pq_coefs, 36058691d64c44ae41ddf098ecb31e9a994026e3cffDan Williams len, flags); 36158691d64c44ae41ddf098ecb31e9a994026e3cffDan Williams } 362d86be86e9aab221089d72399072511f13fe2a771Atsushi Nemoto 363d86be86e9aab221089d72399072511f13fe2a771Atsushi Nemoto if (!tx) { 364b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams for (i = 0; i < src_cnt; i++) 365b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams dma_unmap_single(dev->dev, dma_srcs[i], len, 366b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams DMA_TO_DEVICE); 367b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams for (i = 0; i < dst_cnt; i++) 368b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams dma_unmap_single(dev->dev, dma_dsts[i], 369b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams test_buf_size, 370b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams DMA_BIDIRECTIONAL); 371d86be86e9aab221089d72399072511f13fe2a771Atsushi Nemoto pr_warning("%s: #%u: prep error with src_off=0x%x " 372d86be86e9aab221089d72399072511f13fe2a771Atsushi Nemoto "dst_off=0x%x len=0x%x\n", 373d86be86e9aab221089d72399072511f13fe2a771Atsushi Nemoto thread_name, total_tests - 1, 374d86be86e9aab221089d72399072511f13fe2a771Atsushi Nemoto src_off, dst_off, len); 375d86be86e9aab221089d72399072511f13fe2a771Atsushi Nemoto msleep(100); 376d86be86e9aab221089d72399072511f13fe2a771Atsushi Nemoto failed_tests++; 377d86be86e9aab221089d72399072511f13fe2a771Atsushi Nemoto continue; 378d86be86e9aab221089d72399072511f13fe2a771Atsushi Nemoto } 379e44e0aa3cfa97cddff01704751a4b25151830c72Dan Williams 380e44e0aa3cfa97cddff01704751a4b25151830c72Dan Williams init_completion(&cmp); 381e44e0aa3cfa97cddff01704751a4b25151830c72Dan Williams tx->callback = dmatest_callback; 382e44e0aa3cfa97cddff01704751a4b25151830c72Dan Williams tx->callback_param = &cmp; 383d86be86e9aab221089d72399072511f13fe2a771Atsushi Nemoto cookie = tx->tx_submit(tx); 384d86be86e9aab221089d72399072511f13fe2a771Atsushi Nemoto 3854a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen if (dma_submit_error(cookie)) { 3864a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen pr_warning("%s: #%u: submit error %d with src_off=0x%x " 3874a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen "dst_off=0x%x len=0x%x\n", 3884a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen thread_name, total_tests - 1, cookie, 3894a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen src_off, dst_off, len); 3904a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen msleep(100); 3914a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen failed_tests++; 3924a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen continue; 3934a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen } 394b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams dma_async_issue_pending(chan); 3954a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 396e44e0aa3cfa97cddff01704751a4b25151830c72Dan Williams tmo = wait_for_completion_timeout(&cmp, tmo); 397e44e0aa3cfa97cddff01704751a4b25151830c72Dan Williams status = dma_async_is_tx_complete(chan, cookie, NULL, NULL); 3984a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 399e44e0aa3cfa97cddff01704751a4b25151830c72Dan Williams if (tmo == 0) { 400e44e0aa3cfa97cddff01704751a4b25151830c72Dan Williams pr_warning("%s: #%u: test timed out\n", 401e44e0aa3cfa97cddff01704751a4b25151830c72Dan Williams thread_name, total_tests - 1); 402e44e0aa3cfa97cddff01704751a4b25151830c72Dan Williams failed_tests++; 403e44e0aa3cfa97cddff01704751a4b25151830c72Dan Williams continue; 404e44e0aa3cfa97cddff01704751a4b25151830c72Dan Williams } else if (status != DMA_SUCCESS) { 405e44e0aa3cfa97cddff01704751a4b25151830c72Dan Williams pr_warning("%s: #%u: got completion callback," 406e44e0aa3cfa97cddff01704751a4b25151830c72Dan Williams " but status is \'%s\'\n", 407e44e0aa3cfa97cddff01704751a4b25151830c72Dan Williams thread_name, total_tests - 1, 408e44e0aa3cfa97cddff01704751a4b25151830c72Dan Williams status == DMA_ERROR ? "error" : "in progress"); 4094a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen failed_tests++; 4104a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen continue; 4114a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen } 412e44e0aa3cfa97cddff01704751a4b25151830c72Dan Williams 413d86be86e9aab221089d72399072511f13fe2a771Atsushi Nemoto /* Unmap by myself (see DMA_COMPL_SKIP_DEST_UNMAP above) */ 414b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams for (i = 0; i < dst_cnt; i++) 415b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams dma_unmap_single(dev->dev, dma_dsts[i], test_buf_size, 416b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams DMA_BIDIRECTIONAL); 4174a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 4184a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen error_count = 0; 4194a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 4204a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen pr_debug("%s: verifying source buffer...\n", thread_name); 421b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams error_count += dmatest_verify(thread->srcs, 0, src_off, 4224a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 0, PATTERN_SRC, true); 423b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams error_count += dmatest_verify(thread->srcs, src_off, 4244a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen src_off + len, src_off, 4254a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen PATTERN_SRC | PATTERN_COPY, true); 426b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams error_count += dmatest_verify(thread->srcs, src_off + len, 4274a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen test_buf_size, src_off + len, 4284a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen PATTERN_SRC, true); 4294a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 4304a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen pr_debug("%s: verifying dest buffer...\n", 4314a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen thread->task->comm); 432b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams error_count += dmatest_verify(thread->dsts, 0, dst_off, 4334a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 0, PATTERN_DST, false); 434b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams error_count += dmatest_verify(thread->dsts, dst_off, 4354a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen dst_off + len, src_off, 4364a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen PATTERN_SRC | PATTERN_COPY, false); 437b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams error_count += dmatest_verify(thread->dsts, dst_off + len, 4384a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen test_buf_size, dst_off + len, 4394a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen PATTERN_DST, false); 4404a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 4414a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen if (error_count) { 4424a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen pr_warning("%s: #%u: %u errors with " 4434a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen "src_off=0x%x dst_off=0x%x len=0x%x\n", 4444a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen thread_name, total_tests - 1, error_count, 4454a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen src_off, dst_off, len); 4464a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen failed_tests++; 4474a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen } else { 4484a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen pr_debug("%s: #%u: No errors with " 4494a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen "src_off=0x%x dst_off=0x%x len=0x%x\n", 4504a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen thread_name, total_tests - 1, 4514a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen src_off, dst_off, len); 4524a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen } 4534a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen } 4544a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 4554a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen ret = 0; 456b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams for (i = 0; thread->dsts[i]; i++) 457b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams kfree(thread->dsts[i]); 4584a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoenerr_dstbuf: 459b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams kfree(thread->dsts); 460b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williamserr_dsts: 461b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams for (i = 0; thread->srcs[i]; i++) 462b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams kfree(thread->srcs[i]); 4634a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoenerr_srcbuf: 464b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams kfree(thread->srcs); 465b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williamserr_srcs: 4664a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen pr_notice("%s: terminating after %u tests, %u failures (status %d)\n", 4674a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen thread_name, total_tests, failed_tests, ret); 4680a2ff57d6fba92842272889b4bca447344cd9d36Nicolas Ferre 4690a2ff57d6fba92842272889b4bca447344cd9d36Nicolas Ferre if (iterations > 0) 4700a2ff57d6fba92842272889b4bca447344cd9d36Nicolas Ferre while (!kthread_should_stop()) { 471b953df7c70740cd7593072ebec77a8f658505630Yong Zhang DECLARE_WAIT_QUEUE_HEAD_ONSTACK(wait_dmatest_exit); 4720a2ff57d6fba92842272889b4bca447344cd9d36Nicolas Ferre interruptible_sleep_on(&wait_dmatest_exit); 4730a2ff57d6fba92842272889b4bca447344cd9d36Nicolas Ferre } 4740a2ff57d6fba92842272889b4bca447344cd9d36Nicolas Ferre 4754a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen return ret; 4764a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen} 4774a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 4784a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoenstatic void dmatest_cleanup_channel(struct dmatest_chan *dtc) 4794a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen{ 4804a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen struct dmatest_thread *thread; 4814a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen struct dmatest_thread *_thread; 4824a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen int ret; 4834a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 4844a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen list_for_each_entry_safe(thread, _thread, &dtc->threads, node) { 4854a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen ret = kthread_stop(thread->task); 4864a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen pr_debug("dmatest: thread %s exited with status %d\n", 4874a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen thread->task->comm, ret); 4884a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen list_del(&thread->node); 4894a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen kfree(thread); 4904a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen } 4914a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen kfree(dtc); 4924a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen} 4934a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 494b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williamsstatic int dmatest_add_threads(struct dmatest_chan *dtc, enum dma_transaction_type type) 4954a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen{ 496b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams struct dmatest_thread *thread; 497b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams struct dma_chan *chan = dtc->chan; 498b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams char *op; 499b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams unsigned int i; 5004a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 501b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams if (type == DMA_MEMCPY) 502b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams op = "copy"; 503b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams else if (type == DMA_XOR) 504b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams op = "xor"; 50558691d64c44ae41ddf098ecb31e9a994026e3cffDan Williams else if (type == DMA_PQ) 50658691d64c44ae41ddf098ecb31e9a994026e3cffDan Williams op = "pq"; 507b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams else 508b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams return -EINVAL; 5094a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 5104a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen for (i = 0; i < threads_per_chan; i++) { 5114a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen thread = kzalloc(sizeof(struct dmatest_thread), GFP_KERNEL); 5124a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen if (!thread) { 513b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams pr_warning("dmatest: No memory for %s-%s%u\n", 514b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams dma_chan_name(chan), op, i); 515b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams 5164a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen break; 5174a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen } 5184a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen thread->chan = dtc->chan; 519b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams thread->type = type; 5204a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen smp_wmb(); 521b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams thread->task = kthread_run(dmatest_func, thread, "%s-%s%u", 522b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams dma_chan_name(chan), op, i); 5234a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen if (IS_ERR(thread->task)) { 524b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams pr_warning("dmatest: Failed to run thread %s-%s%u\n", 525b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams dma_chan_name(chan), op, i); 5264a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen kfree(thread); 5274a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen break; 5284a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen } 5294a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 5304a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen /* srcbuf and dstbuf are allocated by the thread itself */ 5314a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 5324a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen list_add_tail(&thread->node, &dtc->threads); 5334a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen } 5344a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 535b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams return i; 536b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams} 537b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams 538b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williamsstatic int dmatest_add_channel(struct dma_chan *chan) 539b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams{ 540b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams struct dmatest_chan *dtc; 541b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams struct dma_device *dma_dev = chan->device; 542b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams unsigned int thread_count = 0; 543b9033e682e86f3c6a66763f9b6a3935c5c64e145Kulikov Vasiliy int cnt; 544b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams 545b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams dtc = kmalloc(sizeof(struct dmatest_chan), GFP_KERNEL); 546b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams if (!dtc) { 547b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams pr_warning("dmatest: No memory for %s\n", dma_chan_name(chan)); 548b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams return -ENOMEM; 549b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams } 550b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams 551b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams dtc->chan = chan; 552b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams INIT_LIST_HEAD(&dtc->threads); 553b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams 554b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams if (dma_has_cap(DMA_MEMCPY, dma_dev->cap_mask)) { 555b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams cnt = dmatest_add_threads(dtc, DMA_MEMCPY); 556f1aef8b6e6abf32a3a269542f95a19e2cb319f6cNicolas Ferre thread_count += cnt > 0 ? cnt : 0; 557b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams } 558b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams if (dma_has_cap(DMA_XOR, dma_dev->cap_mask)) { 559b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams cnt = dmatest_add_threads(dtc, DMA_XOR); 560f1aef8b6e6abf32a3a269542f95a19e2cb319f6cNicolas Ferre thread_count += cnt > 0 ? cnt : 0; 561b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams } 56258691d64c44ae41ddf098ecb31e9a994026e3cffDan Williams if (dma_has_cap(DMA_PQ, dma_dev->cap_mask)) { 56358691d64c44ae41ddf098ecb31e9a994026e3cffDan Williams cnt = dmatest_add_threads(dtc, DMA_PQ); 56458691d64c44ae41ddf098ecb31e9a994026e3cffDan Williams thread_count += cnt > 0 ?: 0; 56558691d64c44ae41ddf098ecb31e9a994026e3cffDan Williams } 566b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams 567b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams pr_info("dmatest: Started %u threads using %s\n", 568b54d5cb9156868fb4f27ccd46a3afb0bf3ef8e0cDan Williams thread_count, dma_chan_name(chan)); 5694a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 5704a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen list_add_tail(&dtc->node, &dmatest_channels); 5714a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen nr_channels++; 5724a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 57333df8ca068123457db56c316946a3c0e4ef787d6Dan Williams return 0; 5744a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen} 5754a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 5767dd602510128d7a64b11ff3b7d4f30ac8e3946ceDan Williamsstatic bool filter(struct dma_chan *chan, void *param) 5774a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen{ 57833df8ca068123457db56c316946a3c0e4ef787d6Dan Williams if (!dmatest_match_channel(chan) || !dmatest_match_device(chan->device)) 5797dd602510128d7a64b11ff3b7d4f30ac8e3946ceDan Williams return false; 58033df8ca068123457db56c316946a3c0e4ef787d6Dan Williams else 5817dd602510128d7a64b11ff3b7d4f30ac8e3946ceDan Williams return true; 5824a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen} 5834a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 5844a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoenstatic int __init dmatest_init(void) 5854a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen{ 58633df8ca068123457db56c316946a3c0e4ef787d6Dan Williams dma_cap_mask_t mask; 58733df8ca068123457db56c316946a3c0e4ef787d6Dan Williams struct dma_chan *chan; 58833df8ca068123457db56c316946a3c0e4ef787d6Dan Williams int err = 0; 58933df8ca068123457db56c316946a3c0e4ef787d6Dan Williams 59033df8ca068123457db56c316946a3c0e4ef787d6Dan Williams dma_cap_zero(mask); 59133df8ca068123457db56c316946a3c0e4ef787d6Dan Williams dma_cap_set(DMA_MEMCPY, mask); 59233df8ca068123457db56c316946a3c0e4ef787d6Dan Williams for (;;) { 59333df8ca068123457db56c316946a3c0e4ef787d6Dan Williams chan = dma_request_channel(mask, filter, NULL); 59433df8ca068123457db56c316946a3c0e4ef787d6Dan Williams if (chan) { 59533df8ca068123457db56c316946a3c0e4ef787d6Dan Williams err = dmatest_add_channel(chan); 596c56c81abe7e684bc6203632d807303eb765690dcDan Williams if (err) { 59733df8ca068123457db56c316946a3c0e4ef787d6Dan Williams dma_release_channel(chan); 59833df8ca068123457db56c316946a3c0e4ef787d6Dan Williams break; /* add_channel failed, punt */ 59933df8ca068123457db56c316946a3c0e4ef787d6Dan Williams } 60033df8ca068123457db56c316946a3c0e4ef787d6Dan Williams } else 60133df8ca068123457db56c316946a3c0e4ef787d6Dan Williams break; /* no more channels available */ 60233df8ca068123457db56c316946a3c0e4ef787d6Dan Williams if (max_channels && nr_channels >= max_channels) 60333df8ca068123457db56c316946a3c0e4ef787d6Dan Williams break; /* we have all we need */ 60433df8ca068123457db56c316946a3c0e4ef787d6Dan Williams } 6054a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 60633df8ca068123457db56c316946a3c0e4ef787d6Dan Williams return err; 6074a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen} 60833df8ca068123457db56c316946a3c0e4ef787d6Dan Williams/* when compiled-in wait for drivers to load first */ 60933df8ca068123457db56c316946a3c0e4ef787d6Dan Williamslate_initcall(dmatest_init); 6104a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 6114a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoenstatic void __exit dmatest_exit(void) 6124a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen{ 61333df8ca068123457db56c316946a3c0e4ef787d6Dan Williams struct dmatest_chan *dtc, *_dtc; 6147cbd4877e5b167b56a3d6033b926a9f925186e12Dan Williams struct dma_chan *chan; 61533df8ca068123457db56c316946a3c0e4ef787d6Dan Williams 61633df8ca068123457db56c316946a3c0e4ef787d6Dan Williams list_for_each_entry_safe(dtc, _dtc, &dmatest_channels, node) { 61733df8ca068123457db56c316946a3c0e4ef787d6Dan Williams list_del(&dtc->node); 6187cbd4877e5b167b56a3d6033b926a9f925186e12Dan Williams chan = dtc->chan; 61933df8ca068123457db56c316946a3c0e4ef787d6Dan Williams dmatest_cleanup_channel(dtc); 62033df8ca068123457db56c316946a3c0e4ef787d6Dan Williams pr_debug("dmatest: dropped channel %s\n", 6217cbd4877e5b167b56a3d6033b926a9f925186e12Dan Williams dma_chan_name(chan)); 6227cbd4877e5b167b56a3d6033b926a9f925186e12Dan Williams dma_release_channel(chan); 62333df8ca068123457db56c316946a3c0e4ef787d6Dan Williams } 6244a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen} 6254a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoenmodule_exit(dmatest_exit); 6264a776f0aa922a552460192c07b56f4fe9cd82632Haavard Skinnemoen 6274a776f0aa922a552460192c07b56f4fe9cd82632Haavard SkinnemoenMODULE_AUTHOR("Haavard Skinnemoen <hskinnemoen@atmel.com>"); 6284a776f0aa922a552460192c07b56f4fe9cd82632Haavard SkinnemoenMODULE_LICENSE("GPL v2"); 629