dmatest.c 29.6 KB
Newer Older
1 2 3 4
/*
 * DMA Engine test module
 *
 * Copyright (C) 2007 Atmel Corporation
A
Andy Shevchenko 已提交
5
 * Copyright (C) 2013 Intel Corporation
6 7 8 9 10 11
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 */
#include <linux/delay.h>
12
#include <linux/dma-mapping.h>
13
#include <linux/dmaengine.h>
14
#include <linux/freezer.h>
15 16 17 18 19
#include <linux/init.h>
#include <linux/kthread.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/random.h>
20
#include <linux/slab.h>
21
#include <linux/wait.h>
A
Andy Shevchenko 已提交
22 23 24 25
#include <linux/ctype.h>
#include <linux/debugfs.h>
#include <linux/uaccess.h>
#include <linux/seq_file.h>
26 27

static unsigned int test_buf_size = 16384;
28
module_param(test_buf_size, uint, S_IRUGO | S_IWUSR);
29 30
MODULE_PARM_DESC(test_buf_size, "Size of the memcpy test buffer");

31
static char test_channel[20];
32 33
module_param_string(channel, test_channel, sizeof(test_channel),
		S_IRUGO | S_IWUSR);
34 35
MODULE_PARM_DESC(channel, "Bus ID of the channel to test (default: any)");

36
static char test_device[20];
37 38
module_param_string(device, test_device, sizeof(test_device),
		S_IRUGO | S_IWUSR);
39 40 41
MODULE_PARM_DESC(device, "Bus ID of the DMA Engine to test (default: any)");

static unsigned int threads_per_chan = 1;
42
module_param(threads_per_chan, uint, S_IRUGO | S_IWUSR);
43 44 45 46
MODULE_PARM_DESC(threads_per_chan,
		"Number of threads to start per channel (default: 1)");

static unsigned int max_channels;
47
module_param(max_channels, uint, S_IRUGO | S_IWUSR);
48
MODULE_PARM_DESC(max_channels,
49 50
		"Maximum number of channels to use (default: all)");

51
static unsigned int iterations;
52
module_param(iterations, uint, S_IRUGO | S_IWUSR);
53 54 55
MODULE_PARM_DESC(iterations,
		"Iterations before stopping test (default: infinite)");

D
Dan Williams 已提交
56
static unsigned int xor_sources = 3;
57
module_param(xor_sources, uint, S_IRUGO | S_IWUSR);
D
Dan Williams 已提交
58 59 60
MODULE_PARM_DESC(xor_sources,
		"Number of xor source buffers (default: 3)");

D
Dan Williams 已提交
61
static unsigned int pq_sources = 3;
62
module_param(pq_sources, uint, S_IRUGO | S_IWUSR);
D
Dan Williams 已提交
63 64 65
MODULE_PARM_DESC(pq_sources,
		"Number of p+q source buffers (default: 3)");

66
static int timeout = 3000;
67
module_param(timeout, uint, S_IRUGO | S_IWUSR);
68 69
MODULE_PARM_DESC(timeout, "Transfer Timeout in msec (default: 3000), "
		 "Pass -1 for infinite timeout");
70

71 72 73
/* Maximum amount of mismatched bytes in buffer to print */
#define MAX_ERROR_COUNT		32

74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90
/*
 * Initialization patterns. All bytes in the source buffer has bit 7
 * set, all bytes in the destination buffer has bit 7 cleared.
 *
 * Bit 6 is set for all bytes which are to be copied by the DMA
 * engine. Bit 5 is set for all bytes which are to be overwritten by
 * the DMA engine.
 *
 * The remaining bits are the inverse of a counter which increments by
 * one for each byte address.
 */
#define PATTERN_SRC		0x80
#define PATTERN_DST		0x00
#define PATTERN_COPY		0x40
#define PATTERN_OVERWRITE	0x20
#define PATTERN_COUNT_MASK	0x1f

91 92 93 94 95 96 97 98 99 100
enum dmatest_error_type {
	DMATEST_ET_OK,
	DMATEST_ET_MAP_SRC,
	DMATEST_ET_MAP_DST,
	DMATEST_ET_PREP,
	DMATEST_ET_SUBMIT,
	DMATEST_ET_TIMEOUT,
	DMATEST_ET_DMA_ERROR,
	DMATEST_ET_DMA_IN_PROGRESS,
	DMATEST_ET_VERIFY,
101 102 103 104 105 106 107 108 109 110 111 112 113 114
	DMATEST_ET_VERIFY_BUF,
};

struct dmatest_verify_buffer {
	unsigned int	index;
	u8		expected;
	u8		actual;
};

struct dmatest_verify_result {
	unsigned int			error_count;
	struct dmatest_verify_buffer	data[MAX_ERROR_COUNT];
	u8				pattern;
	bool				is_srcbuf;
115 116 117 118 119 120 121 122 123 124
};

struct dmatest_thread_result {
	struct list_head	node;
	unsigned int		n;
	unsigned int		src_off;
	unsigned int		dst_off;
	unsigned int		len;
	enum dmatest_error_type	type;
	union {
125 126 127 128 129
		unsigned long			data;
		dma_cookie_t			cookie;
		enum dma_status			status;
		int				error;
		struct dmatest_verify_result	*vr;
130 131 132 133 134 135 136 137 138
	};
};

struct dmatest_result {
	struct list_head	node;
	char			*name;
	struct list_head	results;
};

139 140
struct dmatest_info;

141 142
struct dmatest_thread {
	struct list_head	node;
143
	struct dmatest_info	*info;
144 145
	struct task_struct	*task;
	struct dma_chan		*chan;
D
Dan Williams 已提交
146 147 148
	u8			**srcs;
	u8			**dsts;
	enum dma_transaction_type type;
149
	bool			done;
150 151 152 153 154 155 156 157
};

struct dmatest_chan {
	struct list_head	node;
	struct dma_chan		*chan;
	struct list_head	threads;
};

158
/**
159
 * struct dmatest_params - test parameters.
160 161 162 163 164 165 166 167 168 169
 * @buf_size:		size of the memcpy test buffer
 * @channel:		bus ID of the channel to test
 * @device:		bus ID of the DMA Engine to test
 * @threads_per_chan:	number of threads to start per channel
 * @max_channels:	maximum number of channels to use
 * @iterations:		iterations before stopping test
 * @xor_sources:	number of xor source buffers
 * @pq_sources:		number of p+q source buffers
 * @timeout:		transfer timeout in msec, -1 for infinite timeout
 */
170
struct dmatest_params {
171 172 173 174 175 176 177 178 179
	unsigned int	buf_size;
	char		channel[20];
	char		device[20];
	unsigned int	threads_per_chan;
	unsigned int	max_channels;
	unsigned int	iterations;
	unsigned int	xor_sources;
	unsigned int	pq_sources;
	int		timeout;
180 181 182 183 184
};

/**
 * struct dmatest_info - test information.
 * @params:		test parameters
A
Andy Shevchenko 已提交
185
 * @lock:		access protection to the fields of this structure
186 187 188 189
 */
struct dmatest_info {
	/* Test parameters */
	struct dmatest_params	params;
190 191 192 193

	/* Internal state */
	struct list_head	channels;
	unsigned int		nr_channels;
A
Andy Shevchenko 已提交
194 195 196 197
	struct mutex		lock;

	/* debugfs related stuff */
	struct dentry		*root;
198 199 200 201

	/* Test results */
	struct list_head	results;
	struct mutex		results_lock;
202 203 204 205
};

static struct dmatest_info test_info;

206
static bool dmatest_match_channel(struct dmatest_params *params,
207
		struct dma_chan *chan)
208
{
209
	if (params->channel[0] == '\0')
210
		return true;
211
	return strcmp(dma_chan_name(chan), params->channel) == 0;
212 213
}

214
static bool dmatest_match_device(struct dmatest_params *params,
215
		struct dma_device *device)
216
{
217
	if (params->device[0] == '\0')
218
		return true;
219
	return strcmp(dev_name(device->dev), params->device) == 0;
220 221 222 223 224 225 226 227 228 229
}

static unsigned long dmatest_random(void)
{
	unsigned long buf;

	get_random_bytes(&buf, sizeof(buf));
	return buf;
}

230 231
static void dmatest_init_srcs(u8 **bufs, unsigned int start, unsigned int len,
		unsigned int buf_size)
232 233
{
	unsigned int i;
D
Dan Williams 已提交
234 235 236 237 238 239 240
	u8 *buf;

	for (; (buf = *bufs); bufs++) {
		for (i = 0; i < start; i++)
			buf[i] = PATTERN_SRC | (~i & PATTERN_COUNT_MASK);
		for ( ; i < start + len; i++)
			buf[i] = PATTERN_SRC | PATTERN_COPY
241
				| (~i & PATTERN_COUNT_MASK);
242
		for ( ; i < buf_size; i++)
D
Dan Williams 已提交
243 244 245
			buf[i] = PATTERN_SRC | (~i & PATTERN_COUNT_MASK);
		buf++;
	}
246 247
}

248 249
static void dmatest_init_dsts(u8 **bufs, unsigned int start, unsigned int len,
		unsigned int buf_size)
250 251
{
	unsigned int i;
D
Dan Williams 已提交
252 253 254 255 256 257 258 259
	u8 *buf;

	for (; (buf = *bufs); bufs++) {
		for (i = 0; i < start; i++)
			buf[i] = PATTERN_DST | (~i & PATTERN_COUNT_MASK);
		for ( ; i < start + len; i++)
			buf[i] = PATTERN_DST | PATTERN_OVERWRITE
				| (~i & PATTERN_COUNT_MASK);
260
		for ( ; i < buf_size; i++)
D
Dan Williams 已提交
261 262
			buf[i] = PATTERN_DST | (~i & PATTERN_COUNT_MASK);
	}
263 264
}

265 266 267
static unsigned int dmatest_verify(struct dmatest_verify_result *vr, u8 **bufs,
		unsigned int start, unsigned int end, unsigned int counter,
		u8 pattern, bool is_srcbuf)
268 269 270 271
{
	unsigned int i;
	unsigned int error_count = 0;
	u8 actual;
D
Dan Williams 已提交
272 273 274
	u8 expected;
	u8 *buf;
	unsigned int counter_orig = counter;
275
	struct dmatest_verify_buffer *vb;
D
Dan Williams 已提交
276 277 278 279 280 281 282

	for (; (buf = *bufs); bufs++) {
		counter = counter_orig;
		for (i = start; i < end; i++) {
			actual = buf[i];
			expected = pattern | (~counter & PATTERN_COUNT_MASK);
			if (actual != expected) {
283 284 285 286 287 288
				if (error_count < MAX_ERROR_COUNT && vr) {
					vb = &vr->data[error_count];
					vb->index = i;
					vb->expected = expected;
					vb->actual = actual;
				}
D
Dan Williams 已提交
289 290 291
				error_count++;
			}
			counter++;
292 293 294
		}
	}

295
	if (error_count > MAX_ERROR_COUNT)
296
		pr_warning("%s: %u errors suppressed\n",
297
			current->comm, error_count - MAX_ERROR_COUNT);
298 299 300 301

	return error_count;
}

302 303 304 305 306 307 308
/* poor man's completion - we want to use wait_event_freezable() on it */
struct dmatest_done {
	bool			done;
	wait_queue_head_t	*wait;
};

static void dmatest_callback(void *arg)
309
{
310 311 312 313
	struct dmatest_done *done = arg;

	done->done = true;
	wake_up_all(done->wait);
314 315
}

316 317 318 319 320 321 322 323 324 325 326 327 328 329
static inline void unmap_src(struct device *dev, dma_addr_t *addr, size_t len,
			     unsigned int count)
{
	while (count--)
		dma_unmap_single(dev, addr[count], len, DMA_TO_DEVICE);
}

static inline void unmap_dst(struct device *dev, dma_addr_t *addr, size_t len,
			     unsigned int count)
{
	while (count--)
		dma_unmap_single(dev, addr[count], len, DMA_BIDIRECTIONAL);
}

330 331 332 333 334 335 336
static unsigned int min_odd(unsigned int x, unsigned int y)
{
	unsigned int val = min(x, y);

	return val % 2 ? val : val - 1;
}

337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360
static char *verify_result_get_one(struct dmatest_verify_result *vr,
		unsigned int i)
{
	struct dmatest_verify_buffer *vb = &vr->data[i];
	u8 diff = vb->actual ^ vr->pattern;
	static char buf[512];
	char *msg;

	if (vr->is_srcbuf)
		msg = "srcbuf overwritten!";
	else if ((vr->pattern & PATTERN_COPY)
			&& (diff & (PATTERN_COPY | PATTERN_OVERWRITE)))
		msg = "dstbuf not copied!";
	else if (diff & PATTERN_SRC)
		msg = "dstbuf was copied!";
	else
		msg = "dstbuf mismatch!";

	snprintf(buf, sizeof(buf) - 1, "%s [0x%x] Expected %02x, got %02x", msg,
		 vb->index, vb->expected, vb->actual);

	return buf;
}

361 362 363 364 365 366 367 368 369 370 371 372 373 374 375
static char *thread_result_get(const char *name,
		struct dmatest_thread_result *tr)
{
	static const char * const messages[] = {
		[DMATEST_ET_OK]			= "No errors",
		[DMATEST_ET_MAP_SRC]		= "src mapping error",
		[DMATEST_ET_MAP_DST]		= "dst mapping error",
		[DMATEST_ET_PREP]		= "prep error",
		[DMATEST_ET_SUBMIT]		= "submit error",
		[DMATEST_ET_TIMEOUT]		= "test timed out",
		[DMATEST_ET_DMA_ERROR]		=
			"got completion callback (DMA_ERROR)",
		[DMATEST_ET_DMA_IN_PROGRESS]	=
			"got completion callback (DMA_IN_PROGRESS)",
		[DMATEST_ET_VERIFY]		= "errors",
376
		[DMATEST_ET_VERIFY_BUF]		= "verify errors",
377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413
	};
	static char buf[512];

	snprintf(buf, sizeof(buf) - 1,
		 "%s: #%u: %s with src_off=0x%x ""dst_off=0x%x len=0x%x (%lu)",
		 name, tr->n, messages[tr->type], tr->src_off, tr->dst_off,
		 tr->len, tr->data);

	return buf;
}

static int thread_result_add(struct dmatest_info *info,
		struct dmatest_result *r, enum dmatest_error_type type,
		unsigned int n, unsigned int src_off, unsigned int dst_off,
		unsigned int len, unsigned long data)
{
	struct dmatest_thread_result *tr;

	tr = kzalloc(sizeof(*tr), GFP_KERNEL);
	if (!tr)
		return -ENOMEM;

	tr->type = type;
	tr->n = n;
	tr->src_off = src_off;
	tr->dst_off = dst_off;
	tr->len = len;
	tr->data = data;

	mutex_lock(&info->results_lock);
	list_add_tail(&tr->node, &r->results);
	mutex_unlock(&info->results_lock);

	pr_warn("%s\n", thread_result_get(r->name, tr));
	return 0;
}

414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458
static unsigned int verify_result_add(struct dmatest_info *info,
		struct dmatest_result *r, unsigned int n,
		unsigned int src_off, unsigned int dst_off, unsigned int len,
		u8 **bufs, int whence, unsigned int counter, u8 pattern,
		bool is_srcbuf)
{
	struct dmatest_verify_result *vr;
	unsigned int error_count;
	unsigned int buf_off = is_srcbuf ? src_off : dst_off;
	unsigned int start, end;

	if (whence < 0) {
		start = 0;
		end = buf_off;
	} else if (whence > 0) {
		start = buf_off + len;
		end = info->params.buf_size;
	} else {
		start = buf_off;
		end = buf_off + len;
	}

	vr = kmalloc(sizeof(*vr), GFP_KERNEL);
	if (!vr) {
		pr_warn("dmatest: No memory to store verify result\n");
		return dmatest_verify(NULL, bufs, start, end, counter, pattern,
				      is_srcbuf);
	}

	vr->pattern = pattern;
	vr->is_srcbuf = is_srcbuf;

	error_count = dmatest_verify(vr, bufs, start, end, counter, pattern,
				     is_srcbuf);
	if (error_count) {
		vr->error_count = error_count;
		thread_result_add(info, r, DMATEST_ET_VERIFY_BUF, n, src_off,
				  dst_off, len, (unsigned long)vr);
		return error_count;
	}

	kfree(vr);
	return 0;
}

459 460 461 462 463 464 465 466 467 468 469 470
static void result_free(struct dmatest_info *info, const char *name)
{
	struct dmatest_result *r, *_r;

	mutex_lock(&info->results_lock);
	list_for_each_entry_safe(r, _r, &info->results, node) {
		struct dmatest_thread_result *tr, *_tr;

		if (name && strcmp(r->name, name))
			continue;

		list_for_each_entry_safe(tr, _tr, &r->results, node) {
471 472
			if (tr->type == DMATEST_ET_VERIFY_BUF)
				kfree(tr->vr);
473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500
			list_del(&tr->node);
			kfree(tr);
		}

		kfree(r->name);
		list_del(&r->node);
		kfree(r);
	}

	mutex_unlock(&info->results_lock);
}

static struct dmatest_result *result_init(struct dmatest_info *info,
		const char *name)
{
	struct dmatest_result *r;

	r = kzalloc(sizeof(*r), GFP_KERNEL);
	if (r) {
		r->name = kstrdup(name, GFP_KERNEL);
		INIT_LIST_HEAD(&r->results);
		mutex_lock(&info->results_lock);
		list_add_tail(&r->node, &info->results);
		mutex_unlock(&info->results_lock);
	}
	return r;
}

501 502
/*
 * This function repeatedly tests DMA transfers of various lengths and
D
Dan Williams 已提交
503 504 505 506
 * offsets for a given operation type until it is told to exit by
 * kthread_stop(). There may be multiple threads running this function
 * in parallel for a single channel, and there may be multiple channels
 * being tested in parallel.
507 508 509 510 511 512 513 514 515 516
 *
 * Before each test, the source and destination buffer is initialized
 * with a known pattern. This pattern is different depending on
 * whether it's in an area which is supposed to be copied or
 * overwritten, and different in the source and destination buffers.
 * So if the DMA engine doesn't copy exactly what we tell it to copy,
 * we'll notice.
 */
static int dmatest_func(void *data)
{
517
	DECLARE_WAIT_QUEUE_HEAD_ONSTACK(done_wait);
518
	struct dmatest_thread	*thread = data;
519
	struct dmatest_done	done = { .wait = &done_wait };
520
	struct dmatest_info	*info;
521
	struct dmatest_params	*params;
522
	struct dma_chan		*chan;
523
	struct dma_device	*dev;
524 525 526 527 528 529 530
	const char		*thread_name;
	unsigned int		src_off, dst_off, len;
	unsigned int		error_count;
	unsigned int		failed_tests = 0;
	unsigned int		total_tests = 0;
	dma_cookie_t		cookie;
	enum dma_status		status;
D
Dan Williams 已提交
531
	enum dma_ctrl_flags 	flags;
532
	u8			*pq_coefs = NULL;
533
	int			ret;
D
Dan Williams 已提交
534 535 536
	int			src_cnt;
	int			dst_cnt;
	int			i;
537
	struct dmatest_result	*result;
538 539

	thread_name = current->comm;
540
	set_freezable();
541 542 543 544

	ret = -ENOMEM;

	smp_rmb();
545
	info = thread->info;
546
	params = &info->params;
547
	chan = thread->chan;
548
	dev = chan->device;
D
Dan Williams 已提交
549 550 551
	if (thread->type == DMA_MEMCPY)
		src_cnt = dst_cnt = 1;
	else if (thread->type == DMA_XOR) {
552
		/* force odd to ensure dst = src */
553
		src_cnt = min_odd(params->xor_sources | 1, dev->max_xor);
D
Dan Williams 已提交
554
		dst_cnt = 1;
D
Dan Williams 已提交
555
	} else if (thread->type == DMA_PQ) {
556
		/* force odd to ensure dst = src */
557
		src_cnt = min_odd(params->pq_sources | 1, dma_maxpq(dev, 0));
D
Dan Williams 已提交
558
		dst_cnt = 2;
559

560
		pq_coefs = kmalloc(params->pq_sources+1, GFP_KERNEL);
561 562 563
		if (!pq_coefs)
			goto err_thread_type;

564
		for (i = 0; i < src_cnt; i++)
D
Dan Williams 已提交
565
			pq_coefs[i] = 1;
D
Dan Williams 已提交
566
	} else
567
		goto err_thread_type;
D
Dan Williams 已提交
568

569 570 571 572
	result = result_init(info, thread_name);
	if (!result)
		goto err_srcs;

D
Dan Williams 已提交
573 574 575 576
	thread->srcs = kcalloc(src_cnt+1, sizeof(u8 *), GFP_KERNEL);
	if (!thread->srcs)
		goto err_srcs;
	for (i = 0; i < src_cnt; i++) {
577
		thread->srcs[i] = kmalloc(params->buf_size, GFP_KERNEL);
D
Dan Williams 已提交
578 579 580 581 582 583 584 585 586
		if (!thread->srcs[i])
			goto err_srcbuf;
	}
	thread->srcs[i] = NULL;

	thread->dsts = kcalloc(dst_cnt+1, sizeof(u8 *), GFP_KERNEL);
	if (!thread->dsts)
		goto err_dsts;
	for (i = 0; i < dst_cnt; i++) {
587
		thread->dsts[i] = kmalloc(params->buf_size, GFP_KERNEL);
D
Dan Williams 已提交
588 589 590 591 592
		if (!thread->dsts[i])
			goto err_dstbuf;
	}
	thread->dsts[i] = NULL;

593 594
	set_user_nice(current, 10);

595 596 597 598 599 600
	/*
	 * src buffers are freed by the DMAEngine code with dma_unmap_single()
	 * dst buffers are freed by ourselves below
	 */
	flags = DMA_CTRL_ACK | DMA_PREP_INTERRUPT
	      | DMA_COMPL_SKIP_DEST_UNMAP | DMA_COMPL_SRC_UNMAP_SINGLE;
601

602
	while (!kthread_should_stop()
603
	       && !(params->iterations && total_tests >= params->iterations)) {
D
Dan Williams 已提交
604 605 606
		struct dma_async_tx_descriptor *tx = NULL;
		dma_addr_t dma_srcs[src_cnt];
		dma_addr_t dma_dsts[dst_cnt];
607
		u8 align = 0;
608

609 610
		total_tests++;

611 612 613 614 615 616 617 618
		/* honor alignment restrictions */
		if (thread->type == DMA_MEMCPY)
			align = dev->copy_align;
		else if (thread->type == DMA_XOR)
			align = dev->xor_align;
		else if (thread->type == DMA_PQ)
			align = dev->pq_align;

619
		if (1 << align > params->buf_size) {
620
			pr_err("%u-byte buffer too small for %d-byte alignment\n",
621
			       params->buf_size, 1 << align);
622 623 624
			break;
		}

625
		len = dmatest_random() % params->buf_size + 1;
626
		len = (len >> align) << align;
627 628
		if (!len)
			len = 1 << align;
629 630
		src_off = dmatest_random() % (params->buf_size - len + 1);
		dst_off = dmatest_random() % (params->buf_size - len + 1);
631

632 633 634
		src_off = (src_off >> align) << align;
		dst_off = (dst_off >> align) << align;

635 636
		dmatest_init_srcs(thread->srcs, src_off, len, params->buf_size);
		dmatest_init_dsts(thread->dsts, dst_off, len, params->buf_size);
637

D
Dan Williams 已提交
638 639 640 641 642
		for (i = 0; i < src_cnt; i++) {
			u8 *buf = thread->srcs[i] + src_off;

			dma_srcs[i] = dma_map_single(dev->dev, buf, len,
						     DMA_TO_DEVICE);
643 644 645
			ret = dma_mapping_error(dev->dev, dma_srcs[i]);
			if (ret) {
				unmap_src(dev->dev, dma_srcs, len, i);
646 647 648 649
				thread_result_add(info, result,
						  DMATEST_ET_MAP_SRC,
						  total_tests, src_off, dst_off,
						  len, ret);
650 651 652
				failed_tests++;
				continue;
			}
D
Dan Williams 已提交
653
		}
654
		/* map with DMA_BIDIRECTIONAL to force writeback/invalidate */
D
Dan Williams 已提交
655 656
		for (i = 0; i < dst_cnt; i++) {
			dma_dsts[i] = dma_map_single(dev->dev, thread->dsts[i],
657
						     params->buf_size,
D
Dan Williams 已提交
658
						     DMA_BIDIRECTIONAL);
659 660 661
			ret = dma_mapping_error(dev->dev, dma_dsts[i]);
			if (ret) {
				unmap_src(dev->dev, dma_srcs, len, src_cnt);
662 663
				unmap_dst(dev->dev, dma_dsts, params->buf_size,
					  i);
664 665 666 667
				thread_result_add(info, result,
						  DMATEST_ET_MAP_DST,
						  total_tests, src_off, dst_off,
						  len, ret);
668 669 670
				failed_tests++;
				continue;
			}
D
Dan Williams 已提交
671 672 673 674 675 676 677 678 679 680
		}

		if (thread->type == DMA_MEMCPY)
			tx = dev->device_prep_dma_memcpy(chan,
							 dma_dsts[0] + dst_off,
							 dma_srcs[0], len,
							 flags);
		else if (thread->type == DMA_XOR)
			tx = dev->device_prep_dma_xor(chan,
						      dma_dsts[0] + dst_off,
681
						      dma_srcs, src_cnt,
D
Dan Williams 已提交
682
						      len, flags);
D
Dan Williams 已提交
683 684 685 686 687 688
		else if (thread->type == DMA_PQ) {
			dma_addr_t dma_pq[dst_cnt];

			for (i = 0; i < dst_cnt; i++)
				dma_pq[i] = dma_dsts[i] + dst_off;
			tx = dev->device_prep_dma_pq(chan, dma_pq, dma_srcs,
689
						     src_cnt, pq_coefs,
D
Dan Williams 已提交
690 691
						     len, flags);
		}
692 693

		if (!tx) {
694
			unmap_src(dev->dev, dma_srcs, len, src_cnt);
695 696
			unmap_dst(dev->dev, dma_dsts, params->buf_size,
				  dst_cnt);
697 698 699
			thread_result_add(info, result, DMATEST_ET_PREP,
					  total_tests, src_off, dst_off,
					  len, 0);
700 701 702 703
			msleep(100);
			failed_tests++;
			continue;
		}
704

705
		done.done = false;
706
		tx->callback = dmatest_callback;
707
		tx->callback_param = &done;
708 709
		cookie = tx->tx_submit(tx);

710
		if (dma_submit_error(cookie)) {
711 712 713
			thread_result_add(info, result, DMATEST_ET_SUBMIT,
					  total_tests, src_off, dst_off,
					  len, cookie);
714 715 716 717
			msleep(100);
			failed_tests++;
			continue;
		}
D
Dan Williams 已提交
718
		dma_async_issue_pending(chan);
719

720
		wait_event_freezable_timeout(done_wait, done.done,
721
					     msecs_to_jiffies(params->timeout));
722

723
		status = dma_async_is_tx_complete(chan, cookie, NULL, NULL);
724

725 726 727 728 729 730 731 732 733
		if (!done.done) {
			/*
			 * We're leaving the timed out dma operation with
			 * dangling pointer to done_wait.  To make this
			 * correct, we'll need to allocate wait_done for
			 * each test iteration and perform "who's gonna
			 * free it this time?" dancing.  For now, just
			 * leave it dangling.
			 */
734 735 736
			thread_result_add(info, result, DMATEST_ET_TIMEOUT,
					  total_tests, src_off, dst_off,
					  len, 0);
737 738 739
			failed_tests++;
			continue;
		} else if (status != DMA_SUCCESS) {
740 741 742 743 744
			enum dmatest_error_type type = (status == DMA_ERROR) ?
				DMATEST_ET_DMA_ERROR : DMATEST_ET_DMA_IN_PROGRESS;
			thread_result_add(info, result, type,
					  total_tests, src_off, dst_off,
					  len, status);
745 746 747
			failed_tests++;
			continue;
		}
748

749
		/* Unmap by myself (see DMA_COMPL_SKIP_DEST_UNMAP above) */
750
		unmap_dst(dev->dev, dma_dsts, params->buf_size, dst_cnt);
751 752 753 754

		error_count = 0;

		pr_debug("%s: verifying source buffer...\n", thread_name);
755 756
		error_count += verify_result_add(info, result, total_tests,
				src_off, dst_off, len, thread->srcs, -1,
757
				0, PATTERN_SRC, true);
758 759 760 761 762 763 764 765 766 767
		error_count += verify_result_add(info, result, total_tests,
				src_off, dst_off, len, thread->srcs, 0,
				src_off, PATTERN_SRC | PATTERN_COPY, true);
		error_count += verify_result_add(info, result, total_tests,
				src_off, dst_off, len, thread->srcs, 1,
				src_off + len, PATTERN_SRC, true);

		pr_debug("%s: verifying dest buffer...\n", thread_name);
		error_count += verify_result_add(info, result, total_tests,
				src_off, dst_off, len, thread->dsts, -1,
768
				0, PATTERN_DST, false);
769 770 771 772 773 774
		error_count += verify_result_add(info, result, total_tests,
				src_off, dst_off, len, thread->dsts, 0,
				src_off, PATTERN_SRC | PATTERN_COPY, false);
		error_count += verify_result_add(info, result, total_tests,
				src_off, dst_off, len, thread->dsts, 1,
				dst_off + len, PATTERN_DST, false);
775 776

		if (error_count) {
777 778 779
			thread_result_add(info, result, DMATEST_ET_VERIFY,
					  total_tests, src_off, dst_off,
					  len, error_count);
780 781
			failed_tests++;
		} else {
782 783 784
			thread_result_add(info, result, DMATEST_ET_OK,
					  total_tests, src_off, dst_off,
					  len, 0);
785 786 787 788
		}
	}

	ret = 0;
D
Dan Williams 已提交
789 790
	for (i = 0; thread->dsts[i]; i++)
		kfree(thread->dsts[i]);
791
err_dstbuf:
D
Dan Williams 已提交
792 793 794 795
	kfree(thread->dsts);
err_dsts:
	for (i = 0; thread->srcs[i]; i++)
		kfree(thread->srcs[i]);
796
err_srcbuf:
D
Dan Williams 已提交
797 798
	kfree(thread->srcs);
err_srcs:
799 800
	kfree(pq_coefs);
err_thread_type:
801 802
	pr_notice("%s: terminating after %u tests, %u failures (status %d)\n",
			thread_name, total_tests, failed_tests, ret);
803

804
	/* terminate all transfers on specified channels */
805 806 807
	if (ret)
		dmaengine_terminate_all(chan);

808 809
	thread->done = true;

810
	if (params->iterations > 0)
811
		while (!kthread_should_stop()) {
812
			DECLARE_WAIT_QUEUE_HEAD_ONSTACK(wait_dmatest_exit);
813 814 815
			interruptible_sleep_on(&wait_dmatest_exit);
		}

816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831
	return ret;
}

static void dmatest_cleanup_channel(struct dmatest_chan *dtc)
{
	struct dmatest_thread	*thread;
	struct dmatest_thread	*_thread;
	int			ret;

	list_for_each_entry_safe(thread, _thread, &dtc->threads, node) {
		ret = kthread_stop(thread->task);
		pr_debug("dmatest: thread %s exited with status %d\n",
				thread->task->comm, ret);
		list_del(&thread->node);
		kfree(thread);
	}
832 833

	/* terminate all transfers on specified channels */
834
	dmaengine_terminate_all(dtc->chan);
835

836 837 838
	kfree(dtc);
}

839 840
static int dmatest_add_threads(struct dmatest_info *info,
		struct dmatest_chan *dtc, enum dma_transaction_type type)
841
{
842
	struct dmatest_params *params = &info->params;
D
Dan Williams 已提交
843 844 845 846
	struct dmatest_thread *thread;
	struct dma_chan *chan = dtc->chan;
	char *op;
	unsigned int i;
847

D
Dan Williams 已提交
848 849 850 851
	if (type == DMA_MEMCPY)
		op = "copy";
	else if (type == DMA_XOR)
		op = "xor";
D
Dan Williams 已提交
852 853
	else if (type == DMA_PQ)
		op = "pq";
D
Dan Williams 已提交
854 855
	else
		return -EINVAL;
856

857
	for (i = 0; i < params->threads_per_chan; i++) {
858 859
		thread = kzalloc(sizeof(struct dmatest_thread), GFP_KERNEL);
		if (!thread) {
D
Dan Williams 已提交
860 861 862
			pr_warning("dmatest: No memory for %s-%s%u\n",
				   dma_chan_name(chan), op, i);

863 864
			break;
		}
865
		thread->info = info;
866
		thread->chan = dtc->chan;
D
Dan Williams 已提交
867
		thread->type = type;
868
		smp_wmb();
D
Dan Williams 已提交
869 870
		thread->task = kthread_run(dmatest_func, thread, "%s-%s%u",
				dma_chan_name(chan), op, i);
871
		if (IS_ERR(thread->task)) {
D
Dan Williams 已提交
872 873
			pr_warning("dmatest: Failed to run thread %s-%s%u\n",
					dma_chan_name(chan), op, i);
874 875 876 877 878 879 880 881 882
			kfree(thread);
			break;
		}

		/* srcbuf and dstbuf are allocated by the thread itself */

		list_add_tail(&thread->node, &dtc->threads);
	}

D
Dan Williams 已提交
883 884 885
	return i;
}

886 887
static int dmatest_add_channel(struct dmatest_info *info,
		struct dma_chan *chan)
D
Dan Williams 已提交
888 889 890 891
{
	struct dmatest_chan	*dtc;
	struct dma_device	*dma_dev = chan->device;
	unsigned int		thread_count = 0;
892
	int cnt;
D
Dan Williams 已提交
893 894 895 896 897 898 899 900 901 902 903

	dtc = kmalloc(sizeof(struct dmatest_chan), GFP_KERNEL);
	if (!dtc) {
		pr_warning("dmatest: No memory for %s\n", dma_chan_name(chan));
		return -ENOMEM;
	}

	dtc->chan = chan;
	INIT_LIST_HEAD(&dtc->threads);

	if (dma_has_cap(DMA_MEMCPY, dma_dev->cap_mask)) {
904
		cnt = dmatest_add_threads(info, dtc, DMA_MEMCPY);
905
		thread_count += cnt > 0 ? cnt : 0;
D
Dan Williams 已提交
906 907
	}
	if (dma_has_cap(DMA_XOR, dma_dev->cap_mask)) {
908
		cnt = dmatest_add_threads(info, dtc, DMA_XOR);
909
		thread_count += cnt > 0 ? cnt : 0;
D
Dan Williams 已提交
910
	}
D
Dan Williams 已提交
911
	if (dma_has_cap(DMA_PQ, dma_dev->cap_mask)) {
912
		cnt = dmatest_add_threads(info, dtc, DMA_PQ);
913
		thread_count += cnt > 0 ? cnt : 0;
D
Dan Williams 已提交
914
	}
D
Dan Williams 已提交
915 916 917

	pr_info("dmatest: Started %u threads using %s\n",
		thread_count, dma_chan_name(chan));
918

919 920
	list_add_tail(&dtc->node, &info->channels);
	info->nr_channels++;
921

922
	return 0;
923 924
}

925
static bool filter(struct dma_chan *chan, void *param)
926
{
927
	struct dmatest_params *params = param;
928

929 930
	if (!dmatest_match_channel(params, chan) ||
	    !dmatest_match_device(params, chan->device))
931
		return false;
932
	else
933
		return true;
934 935
}

A
Andy Shevchenko 已提交
936
static int __run_threaded_test(struct dmatest_info *info)
937
{
938 939
	dma_cap_mask_t mask;
	struct dma_chan *chan;
940
	struct dmatest_params *params = &info->params;
941 942 943 944 945
	int err = 0;

	dma_cap_zero(mask);
	dma_cap_set(DMA_MEMCPY, mask);
	for (;;) {
946
		chan = dma_request_channel(mask, filter, params);
947
		if (chan) {
948
			err = dmatest_add_channel(info, chan);
949
			if (err) {
950 951 952 953 954
				dma_release_channel(chan);
				break; /* add_channel failed, punt */
			}
		} else
			break; /* no more channels available */
955 956
		if (params->max_channels &&
		    info->nr_channels >= params->max_channels)
957 958 959
			break; /* we have all we need */
	}
	return err;
960 961
}

A
Andy Shevchenko 已提交
962 963 964 965 966 967 968 969 970 971 972 973 974
#ifndef MODULE
static int run_threaded_test(struct dmatest_info *info)
{
	int ret;

	mutex_lock(&info->lock);
	ret = __run_threaded_test(info);
	mutex_unlock(&info->lock);
	return ret;
}
#endif

static void __stop_threaded_test(struct dmatest_info *info)
975
{
976
	struct dmatest_chan *dtc, *_dtc;
977
	struct dma_chan *chan;
978

979
	list_for_each_entry_safe(dtc, _dtc, &info->channels, node) {
980
		list_del(&dtc->node);
981
		chan = dtc->chan;
982
		dmatest_cleanup_channel(dtc);
983
		pr_debug("dmatest: dropped channel %s\n", dma_chan_name(chan));
984
		dma_release_channel(chan);
985
	}
986 987

	info->nr_channels = 0;
988
}
989

A
Andy Shevchenko 已提交
990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006
static void stop_threaded_test(struct dmatest_info *info)
{
	mutex_lock(&info->lock);
	__stop_threaded_test(info);
	mutex_unlock(&info->lock);
}

static int __restart_threaded_test(struct dmatest_info *info, bool run)
{
	struct dmatest_params *params = &info->params;

	/* Stop any running test first */
	__stop_threaded_test(info);

	if (run == false)
		return 0;

1007 1008 1009
	/* Clear results from previous run */
	result_free(info, NULL);

A
Andy Shevchenko 已提交
1010
	/* Copy test parameters */
1011 1012 1013 1014 1015 1016 1017 1018 1019
	params->buf_size = test_buf_size;
	strlcpy(params->channel, strim(test_channel), sizeof(params->channel));
	strlcpy(params->device, strim(test_device), sizeof(params->device));
	params->threads_per_chan = threads_per_chan;
	params->max_channels = max_channels;
	params->iterations = iterations;
	params->xor_sources = xor_sources;
	params->pq_sources = pq_sources;
	params->timeout = timeout;
A
Andy Shevchenko 已提交
1020 1021

	/* Run test with new parameters */
1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035
	return __run_threaded_test(info);
}

static bool __is_threaded_test_run(struct dmatest_info *info)
{
	struct dmatest_chan *dtc;

	list_for_each_entry(dtc, &info->channels, node) {
		struct dmatest_thread *thread;

		list_for_each_entry(thread, &dtc->threads, node) {
			if (!thread->done)
				return true;
		}
A
Andy Shevchenko 已提交
1036 1037
	}

1038
	return false;
A
Andy Shevchenko 已提交
1039 1040 1041 1042 1043 1044 1045 1046 1047
}

static ssize_t dtf_read_run(struct file *file, char __user *user_buf,
		size_t count, loff_t *ppos)
{
	struct dmatest_info *info = file->private_data;
	char buf[3];

	mutex_lock(&info->lock);
1048

1049
	if (__is_threaded_test_run(info)) {
A
Andy Shevchenko 已提交
1050
		buf[0] = 'Y';
1051 1052
	} else {
		__stop_threaded_test(info);
A
Andy Shevchenko 已提交
1053
		buf[0] = 'N';
1054 1055
	}

A
Andy Shevchenko 已提交
1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074
	mutex_unlock(&info->lock);
	buf[1] = '\n';
	buf[2] = 0x00;
	return simple_read_from_buffer(user_buf, count, ppos, buf, 2);
}

static ssize_t dtf_write_run(struct file *file, const char __user *user_buf,
		size_t count, loff_t *ppos)
{
	struct dmatest_info *info = file->private_data;
	char buf[16];
	bool bv;
	int ret = 0;

	if (copy_from_user(buf, user_buf, min(count, (sizeof(buf) - 1))))
		return -EFAULT;

	if (strtobool(buf, &bv) == 0) {
		mutex_lock(&info->lock);
1075 1076 1077 1078 1079 1080

		if (__is_threaded_test_run(info))
			ret = -EBUSY;
		else
			ret = __restart_threaded_test(info, bv);

A
Andy Shevchenko 已提交
1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093
		mutex_unlock(&info->lock);
	}

	return ret ? ret : count;
}

static const struct file_operations dtf_run_fops = {
	.read	= dtf_read_run,
	.write	= dtf_write_run,
	.open	= simple_open,
	.llseek	= default_llseek,
};

1094 1095 1096 1097 1098
static int dtf_results_show(struct seq_file *sf, void *data)
{
	struct dmatest_info *info = sf->private;
	struct dmatest_result *result;
	struct dmatest_thread_result *tr;
1099
	unsigned int i;
1100 1101 1102

	mutex_lock(&info->results_lock);
	list_for_each_entry(result, &info->results, node) {
1103
		list_for_each_entry(tr, &result->results, node) {
1104 1105
			seq_printf(sf, "%s\n",
				thread_result_get(result->name, tr));
1106 1107 1108 1109 1110 1111 1112
			if (tr->type == DMATEST_ET_VERIFY_BUF) {
				for (i = 0; i < tr->vr->error_count; i++) {
					seq_printf(sf, "\t%s\n",
						verify_result_get_one(tr->vr, i));
				}
			}
		}
1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130
	}

	mutex_unlock(&info->results_lock);
	return 0;
}

static int dtf_results_open(struct inode *inode, struct file *file)
{
	return single_open(file, dtf_results_show, inode->i_private);
}

static const struct file_operations dtf_results_fops = {
	.open		= dtf_results_open,
	.read		= seq_read,
	.llseek		= seq_lseek,
	.release	= single_release,
};

A
Andy Shevchenko 已提交
1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143
static int dmatest_register_dbgfs(struct dmatest_info *info)
{
	struct dentry *d;

	d = debugfs_create_dir("dmatest", NULL);
	if (IS_ERR(d))
		return PTR_ERR(d);
	if (!d)
		goto err_root;

	info->root = d;

	/* Run or stop threaded test */
1144 1145
	debugfs_create_file("run", S_IWUSR | S_IRUGO, info->root, info,
			    &dtf_run_fops);
A
Andy Shevchenko 已提交
1146

1147
	/* Results of test in progress */
1148 1149
	debugfs_create_file("results", S_IRUGO, info->root, info,
			    &dtf_results_fops);
1150

A
Andy Shevchenko 已提交
1151 1152 1153 1154
	return 0;

err_root:
	pr_err("dmatest: Failed to initialize debugfs\n");
1155
	return -ENOMEM;
A
Andy Shevchenko 已提交
1156 1157
}

1158 1159 1160
static int __init dmatest_init(void)
{
	struct dmatest_info *info = &test_info;
A
Andy Shevchenko 已提交
1161
	int ret;
1162 1163 1164

	memset(info, 0, sizeof(*info));

A
Andy Shevchenko 已提交
1165
	mutex_init(&info->lock);
1166 1167
	INIT_LIST_HEAD(&info->channels);

1168 1169 1170
	mutex_init(&info->results_lock);
	INIT_LIST_HEAD(&info->results);

A
Andy Shevchenko 已提交
1171 1172 1173 1174 1175 1176 1177
	ret = dmatest_register_dbgfs(info);
	if (ret)
		return ret;

#ifdef MODULE
	return 0;
#else
1178
	return run_threaded_test(info);
A
Andy Shevchenko 已提交
1179
#endif
1180 1181 1182 1183 1184 1185 1186 1187
}
/* when compiled-in wait for drivers to load first */
late_initcall(dmatest_init);

static void __exit dmatest_exit(void)
{
	struct dmatest_info *info = &test_info;

A
Andy Shevchenko 已提交
1188
	debugfs_remove_recursive(info->root);
1189
	stop_threaded_test(info);
1190
	result_free(info, NULL);
1191
}
1192 1193
module_exit(dmatest_exit);

J
Jean Delvare 已提交
1194
MODULE_AUTHOR("Haavard Skinnemoen (Atmel)");
1195
MODULE_LICENSE("GPL v2");