xref: /dpdk/app/test/test_dmadev.c (revision 2aba4f16cd4e112b1c252f5244e4442ad38ca720)
19942ebb9SChengwen Feng /* SPDX-License-Identifier: BSD-3-Clause
29942ebb9SChengwen Feng  * Copyright(c) 2021 HiSilicon Limited
39942ebb9SChengwen Feng  * Copyright(c) 2021 Intel Corporation
49942ebb9SChengwen Feng  */
59942ebb9SChengwen Feng 
6718f7804SBruce Richardson #include <inttypes.h>
7718f7804SBruce Richardson 
89942ebb9SChengwen Feng #include <rte_dmadev.h>
98febcbe1SBruce Richardson #include <rte_mbuf.h>
108febcbe1SBruce Richardson #include <rte_pause.h>
118febcbe1SBruce Richardson #include <rte_cycles.h>
128febcbe1SBruce Richardson #include <rte_random.h>
139942ebb9SChengwen Feng #include <rte_bus_vdev.h>
14718f7804SBruce Richardson #include <rte_dmadev_pmd.h>
159942ebb9SChengwen Feng 
169942ebb9SChengwen Feng #include "test.h"
179942ebb9SChengwen Feng #include "test_dmadev_api.h"
189942ebb9SChengwen Feng 
19718f7804SBruce Richardson #define ERR_RETURN(...) do { print_err(__func__, __LINE__, __VA_ARGS__); return -1; } while (0)
20718f7804SBruce Richardson 
2114b477edSGowrishankar Muthukrishnan #define TEST_NAME_MAX_LEN 80
22877cb3e3SAmit Prakash Shukla #define TEST_RINGSIZE 512
23*2aba4f16SGowrishankar Muthukrishnan #define COPY_LEN 2048
248febcbe1SBruce Richardson 
2514b477edSGowrishankar Muthukrishnan static struct rte_dma_info info;
268febcbe1SBruce Richardson static struct rte_mempool *pool;
2714b477edSGowrishankar Muthukrishnan static bool check_err_stats;
2814b477edSGowrishankar Muthukrishnan static int16_t test_dev_id;
298febcbe1SBruce Richardson static uint16_t id_count;
3014b477edSGowrishankar Muthukrishnan static uint16_t vchan;
318febcbe1SBruce Richardson 
32877cb3e3SAmit Prakash Shukla enum {
33877cb3e3SAmit Prakash Shukla 	TEST_PARAM_REMOTE_ADDR = 0,
34877cb3e3SAmit Prakash Shukla 	TEST_PARAM_MAX,
35877cb3e3SAmit Prakash Shukla };
36877cb3e3SAmit Prakash Shukla 
37877cb3e3SAmit Prakash Shukla static const char * const dma_test_param[] = {
38877cb3e3SAmit Prakash Shukla 	[TEST_PARAM_REMOTE_ADDR] = "remote_addr",
39877cb3e3SAmit Prakash Shukla };
40877cb3e3SAmit Prakash Shukla 
41877cb3e3SAmit Prakash Shukla static uint64_t env_test_param[TEST_PARAM_MAX];
42877cb3e3SAmit Prakash Shukla 
43877cb3e3SAmit Prakash Shukla enum {
44877cb3e3SAmit Prakash Shukla 	TEST_M2D_AUTO_FREE = 0,
45877cb3e3SAmit Prakash Shukla 	TEST_MAX,
46877cb3e3SAmit Prakash Shukla };
47877cb3e3SAmit Prakash Shukla 
48877cb3e3SAmit Prakash Shukla struct dma_add_test {
49877cb3e3SAmit Prakash Shukla 	const char *name;
50877cb3e3SAmit Prakash Shukla 	bool enabled;
51877cb3e3SAmit Prakash Shukla };
52877cb3e3SAmit Prakash Shukla 
53877cb3e3SAmit Prakash Shukla struct dma_add_test dma_add_test[] = {
54877cb3e3SAmit Prakash Shukla 	[TEST_M2D_AUTO_FREE] = {.name = "m2d_auto_free", .enabled = false},
55877cb3e3SAmit Prakash Shukla };
56877cb3e3SAmit Prakash Shukla 
57718f7804SBruce Richardson static void
58718f7804SBruce Richardson __rte_format_printf(3, 4)
print_err(const char * func,int lineno,const char * format,...)59718f7804SBruce Richardson print_err(const char *func, int lineno, const char *format, ...)
60718f7804SBruce Richardson {
61718f7804SBruce Richardson 	va_list ap;
62718f7804SBruce Richardson 
63718f7804SBruce Richardson 	fprintf(stderr, "In %s:%d - ", func, lineno);
64718f7804SBruce Richardson 	va_start(ap, format);
65718f7804SBruce Richardson 	vfprintf(stderr, format, ap);
66718f7804SBruce Richardson 	va_end(ap);
67718f7804SBruce Richardson }
68718f7804SBruce Richardson 
6914b477edSGowrishankar Muthukrishnan struct runtest_param {
7014b477edSGowrishankar Muthukrishnan 	const char name[TEST_NAME_MAX_LEN];
7114b477edSGowrishankar Muthukrishnan 	int (*test_fn)(int16_t dev_id, uint16_t vchan);
7214b477edSGowrishankar Muthukrishnan 	int iterations;
7314b477edSGowrishankar Muthukrishnan };
7414b477edSGowrishankar Muthukrishnan 
75718f7804SBruce Richardson static int
runtest(const void * args)7614b477edSGowrishankar Muthukrishnan runtest(const void *args)
778febcbe1SBruce Richardson {
7814b477edSGowrishankar Muthukrishnan 	int (*test_fn)(int16_t dev_id, uint16_t vchan);
7914b477edSGowrishankar Muthukrishnan 	const struct runtest_param *param = args;
808febcbe1SBruce Richardson 	struct rte_dma_stats stats;
8114b477edSGowrishankar Muthukrishnan 	const char *printable;
8214b477edSGowrishankar Muthukrishnan 	int iterations;
8314b477edSGowrishankar Muthukrishnan 	int16_t dev_id;
848febcbe1SBruce Richardson 	int i;
858febcbe1SBruce Richardson 
8614b477edSGowrishankar Muthukrishnan 	printable = param->name;
8714b477edSGowrishankar Muthukrishnan 	iterations = param->iterations;
8814b477edSGowrishankar Muthukrishnan 	test_fn = param->test_fn;
8914b477edSGowrishankar Muthukrishnan 	dev_id = test_dev_id;
9014b477edSGowrishankar Muthukrishnan 
918febcbe1SBruce Richardson 	rte_dma_stats_reset(dev_id, vchan);
928febcbe1SBruce Richardson 	printf("DMA Dev %d: Running %s Tests %s\n", dev_id, printable,
938febcbe1SBruce Richardson 			check_err_stats ? " " : "(errors expected)");
948febcbe1SBruce Richardson 	for (i = 0; i < iterations; i++) {
958febcbe1SBruce Richardson 		if (test_fn(dev_id, vchan) < 0)
968febcbe1SBruce Richardson 			return -1;
978febcbe1SBruce Richardson 
988febcbe1SBruce Richardson 		rte_dma_stats_get(dev_id, 0, &stats);
998febcbe1SBruce Richardson 		printf("Ops submitted: %"PRIu64"\t", stats.submitted);
1008febcbe1SBruce Richardson 		printf("Ops completed: %"PRIu64"\t", stats.completed);
1018febcbe1SBruce Richardson 		printf("Errors: %"PRIu64"\r", stats.errors);
1028febcbe1SBruce Richardson 
1038febcbe1SBruce Richardson 		if (stats.completed != stats.submitted)
1048febcbe1SBruce Richardson 			ERR_RETURN("\nError, not all submitted jobs are reported as completed\n");
1058febcbe1SBruce Richardson 		if (check_err_stats && stats.errors != 0)
1068febcbe1SBruce Richardson 			ERR_RETURN("\nErrors reported during op processing, aborting tests\n");
1078febcbe1SBruce Richardson 	}
1088febcbe1SBruce Richardson 	printf("\n");
1098febcbe1SBruce Richardson 	return 0;
1108febcbe1SBruce Richardson }
1118febcbe1SBruce Richardson 
1128febcbe1SBruce Richardson static void
await_hw(int16_t dev_id,uint16_t vchan)1138febcbe1SBruce Richardson await_hw(int16_t dev_id, uint16_t vchan)
1148febcbe1SBruce Richardson {
1158febcbe1SBruce Richardson 	enum rte_dma_vchan_status st;
1168febcbe1SBruce Richardson 
1178febcbe1SBruce Richardson 	if (rte_dma_vchan_status(dev_id, vchan, &st) < 0) {
1188febcbe1SBruce Richardson 		/* for drivers that don't support this op, just sleep for 1 millisecond */
1198febcbe1SBruce Richardson 		rte_delay_us_sleep(1000);
1208febcbe1SBruce Richardson 		return;
1218febcbe1SBruce Richardson 	}
1228febcbe1SBruce Richardson 
1238febcbe1SBruce Richardson 	/* for those that do, *max* end time is one second from now, but all should be faster */
1248febcbe1SBruce Richardson 	const uint64_t end_cycles = rte_get_timer_cycles() + rte_get_timer_hz();
1258febcbe1SBruce Richardson 	while (st == RTE_DMA_VCHAN_ACTIVE && rte_get_timer_cycles() < end_cycles) {
1268febcbe1SBruce Richardson 		rte_pause();
1278febcbe1SBruce Richardson 		rte_dma_vchan_status(dev_id, vchan, &st);
1288febcbe1SBruce Richardson 	}
1298febcbe1SBruce Richardson }
1308febcbe1SBruce Richardson 
1311b86a66aSBruce Richardson /* run a series of copy tests just using some different options for enqueues and completions */
1321b86a66aSBruce Richardson static int
do_multi_copies(int16_t dev_id,uint16_t vchan,int split_batches,int split_completions,int use_completed_status)1331b86a66aSBruce Richardson do_multi_copies(int16_t dev_id, uint16_t vchan,
1341b86a66aSBruce Richardson 		int split_batches,     /* submit 2 x 16 or 1 x 32 burst */
1351b86a66aSBruce Richardson 		int split_completions, /* gather 2 x 16 or 1 x 32 completions */
1361b86a66aSBruce Richardson 		int use_completed_status) /* use completed or completed_status function */
1371b86a66aSBruce Richardson {
1381b86a66aSBruce Richardson 	struct rte_mbuf *srcs[32], *dsts[32];
1391b86a66aSBruce Richardson 	enum rte_dma_status_code sc[32];
1401b86a66aSBruce Richardson 	unsigned int i, j;
1411b86a66aSBruce Richardson 	bool dma_err = false;
1421b86a66aSBruce Richardson 
1431b86a66aSBruce Richardson 	/* Enqueue burst of copies and hit doorbell */
1441b86a66aSBruce Richardson 	for (i = 0; i < RTE_DIM(srcs); i++) {
1451b86a66aSBruce Richardson 		uint64_t *src_data;
1461b86a66aSBruce Richardson 
1471b86a66aSBruce Richardson 		if (split_batches && i == RTE_DIM(srcs) / 2)
1481b86a66aSBruce Richardson 			rte_dma_submit(dev_id, vchan);
1491b86a66aSBruce Richardson 
1501b86a66aSBruce Richardson 		srcs[i] = rte_pktmbuf_alloc(pool);
1511b86a66aSBruce Richardson 		dsts[i] = rte_pktmbuf_alloc(pool);
1521b86a66aSBruce Richardson 		if (srcs[i] == NULL || dsts[i] == NULL)
1531b86a66aSBruce Richardson 			ERR_RETURN("Error allocating buffers\n");
1541b86a66aSBruce Richardson 
1551b86a66aSBruce Richardson 		src_data = rte_pktmbuf_mtod(srcs[i], uint64_t *);
1561b86a66aSBruce Richardson 		for (j = 0; j < COPY_LEN/sizeof(uint64_t); j++)
1571b86a66aSBruce Richardson 			src_data[j] = rte_rand();
1581b86a66aSBruce Richardson 
15939683912SShijith Thotton 		if (rte_dma_copy(dev_id, vchan, rte_mbuf_data_iova(srcs[i]),
16039683912SShijith Thotton 				 rte_mbuf_data_iova(dsts[i]), COPY_LEN, 0) != id_count++)
1611b86a66aSBruce Richardson 			ERR_RETURN("Error with rte_dma_copy for buffer %u\n", i);
1621b86a66aSBruce Richardson 	}
1631b86a66aSBruce Richardson 	rte_dma_submit(dev_id, vchan);
1641b86a66aSBruce Richardson 
1651b86a66aSBruce Richardson 	await_hw(dev_id, vchan);
1661b86a66aSBruce Richardson 
1671b86a66aSBruce Richardson 	if (split_completions) {
1681b86a66aSBruce Richardson 		/* gather completions in two halves */
1691b86a66aSBruce Richardson 		uint16_t half_len = RTE_DIM(srcs) / 2;
1701b86a66aSBruce Richardson 		int ret = rte_dma_completed(dev_id, vchan, half_len, NULL, &dma_err);
1711b86a66aSBruce Richardson 		if (ret != half_len || dma_err)
1721b86a66aSBruce Richardson 			ERR_RETURN("Error with rte_dma_completed - first half. ret = %d, expected ret = %u, dma_err = %d\n",
1731b86a66aSBruce Richardson 					ret, half_len, dma_err);
1741b86a66aSBruce Richardson 
1751b86a66aSBruce Richardson 		ret = rte_dma_completed(dev_id, vchan, half_len, NULL, &dma_err);
1761b86a66aSBruce Richardson 		if (ret != half_len || dma_err)
1771b86a66aSBruce Richardson 			ERR_RETURN("Error with rte_dma_completed - second half. ret = %d, expected ret = %u, dma_err = %d\n",
1781b86a66aSBruce Richardson 					ret, half_len, dma_err);
1791b86a66aSBruce Richardson 	} else {
1801b86a66aSBruce Richardson 		/* gather all completions in one go, using either
1811b86a66aSBruce Richardson 		 * completed or completed_status fns
1821b86a66aSBruce Richardson 		 */
1831b86a66aSBruce Richardson 		if (!use_completed_status) {
1841b86a66aSBruce Richardson 			int n = rte_dma_completed(dev_id, vchan, RTE_DIM(srcs), NULL, &dma_err);
1851b86a66aSBruce Richardson 			if (n != RTE_DIM(srcs) || dma_err)
1861b86a66aSBruce Richardson 				ERR_RETURN("Error with rte_dma_completed, %u [expected: %zu], dma_err = %d\n",
1871b86a66aSBruce Richardson 						n, RTE_DIM(srcs), dma_err);
1881b86a66aSBruce Richardson 		} else {
1891b86a66aSBruce Richardson 			int n = rte_dma_completed_status(dev_id, vchan, RTE_DIM(srcs), NULL, sc);
1901b86a66aSBruce Richardson 			if (n != RTE_DIM(srcs))
1911b86a66aSBruce Richardson 				ERR_RETURN("Error with rte_dma_completed_status, %u [expected: %zu]\n",
1921b86a66aSBruce Richardson 						n, RTE_DIM(srcs));
1931b86a66aSBruce Richardson 
1941b86a66aSBruce Richardson 			for (j = 0; j < (uint16_t)n; j++)
1951b86a66aSBruce Richardson 				if (sc[j] != RTE_DMA_STATUS_SUCCESSFUL)
1961b86a66aSBruce Richardson 					ERR_RETURN("Error with rte_dma_completed_status, job %u reports failure [code %u]\n",
1971b86a66aSBruce Richardson 							j, sc[j]);
1981b86a66aSBruce Richardson 		}
1991b86a66aSBruce Richardson 	}
2001b86a66aSBruce Richardson 
2011b86a66aSBruce Richardson 	/* check for empty */
2021b86a66aSBruce Richardson 	int ret = use_completed_status ?
2031b86a66aSBruce Richardson 			rte_dma_completed_status(dev_id, vchan, RTE_DIM(srcs), NULL, sc) :
2041b86a66aSBruce Richardson 			rte_dma_completed(dev_id, vchan, RTE_DIM(srcs), NULL, &dma_err);
2051b86a66aSBruce Richardson 	if (ret != 0)
2061b86a66aSBruce Richardson 		ERR_RETURN("Error with completion check - ops unexpectedly returned\n");
2071b86a66aSBruce Richardson 
2081b86a66aSBruce Richardson 	for (i = 0; i < RTE_DIM(srcs); i++) {
2091b86a66aSBruce Richardson 		char *src_data, *dst_data;
2101b86a66aSBruce Richardson 
2111b86a66aSBruce Richardson 		src_data = rte_pktmbuf_mtod(srcs[i], char *);
2121b86a66aSBruce Richardson 		dst_data = rte_pktmbuf_mtod(dsts[i], char *);
2131b86a66aSBruce Richardson 		for (j = 0; j < COPY_LEN; j++)
2141b86a66aSBruce Richardson 			if (src_data[j] != dst_data[j])
2151b86a66aSBruce Richardson 				ERR_RETURN("Error with copy of packet %u, byte %u\n", i, j);
2161b86a66aSBruce Richardson 
2171b86a66aSBruce Richardson 		rte_pktmbuf_free(srcs[i]);
2181b86a66aSBruce Richardson 		rte_pktmbuf_free(dsts[i]);
2191b86a66aSBruce Richardson 	}
2201b86a66aSBruce Richardson 	return 0;
2211b86a66aSBruce Richardson }
2221b86a66aSBruce Richardson 
2238febcbe1SBruce Richardson static int
test_single_copy(int16_t dev_id,uint16_t vchan)2248037bdc6SBruce Richardson test_single_copy(int16_t dev_id, uint16_t vchan)
2258febcbe1SBruce Richardson {
2268037bdc6SBruce Richardson 	uint16_t i;
2278febcbe1SBruce Richardson 	uint16_t id;
2288037bdc6SBruce Richardson 	enum rte_dma_status_code status;
2298febcbe1SBruce Richardson 	struct rte_mbuf *src, *dst;
2308febcbe1SBruce Richardson 	char *src_data, *dst_data;
2318febcbe1SBruce Richardson 
2328febcbe1SBruce Richardson 	src = rte_pktmbuf_alloc(pool);
2338febcbe1SBruce Richardson 	dst = rte_pktmbuf_alloc(pool);
2348febcbe1SBruce Richardson 	src_data = rte_pktmbuf_mtod(src, char *);
2358febcbe1SBruce Richardson 	dst_data = rte_pktmbuf_mtod(dst, char *);
2368febcbe1SBruce Richardson 
2378febcbe1SBruce Richardson 	for (i = 0; i < COPY_LEN; i++)
2388febcbe1SBruce Richardson 		src_data[i] = rte_rand() & 0xFF;
2398febcbe1SBruce Richardson 
2408febcbe1SBruce Richardson 	id = rte_dma_copy(dev_id, vchan, rte_pktmbuf_iova(src), rte_pktmbuf_iova(dst),
2418febcbe1SBruce Richardson 			COPY_LEN, RTE_DMA_OP_FLAG_SUBMIT);
2428febcbe1SBruce Richardson 	if (id != id_count)
2438febcbe1SBruce Richardson 		ERR_RETURN("Error with rte_dma_copy, got %u, expected %u\n",
2448febcbe1SBruce Richardson 				id, id_count);
2458febcbe1SBruce Richardson 
2468febcbe1SBruce Richardson 	/* give time for copy to finish, then check it was done */
2478febcbe1SBruce Richardson 	await_hw(dev_id, vchan);
2488febcbe1SBruce Richardson 
2498febcbe1SBruce Richardson 	for (i = 0; i < COPY_LEN; i++)
2508febcbe1SBruce Richardson 		if (dst_data[i] != src_data[i])
2518febcbe1SBruce Richardson 			ERR_RETURN("Data mismatch at char %u [Got %02x not %02x]\n", i,
2528febcbe1SBruce Richardson 					dst_data[i], src_data[i]);
2538febcbe1SBruce Richardson 
2548febcbe1SBruce Richardson 	/* now check completion works */
2551c549cddSChengwen Feng 	id = ~id;
2568febcbe1SBruce Richardson 	if (rte_dma_completed(dev_id, vchan, 1, &id, NULL) != 1)
2578febcbe1SBruce Richardson 		ERR_RETURN("Error with rte_dma_completed\n");
2588febcbe1SBruce Richardson 
2598febcbe1SBruce Richardson 	if (id != id_count)
2608febcbe1SBruce Richardson 		ERR_RETURN("Error:incorrect job id received, %u [expected %u]\n",
2618febcbe1SBruce Richardson 				id, id_count);
2628febcbe1SBruce Richardson 
263f25265f0SChengwen Feng 	/* check for completed and id when no job done */
2641c549cddSChengwen Feng 	id = ~id;
265f25265f0SChengwen Feng 	if (rte_dma_completed(dev_id, vchan, 1, &id, NULL) != 0)
266f25265f0SChengwen Feng 		ERR_RETURN("Error with rte_dma_completed when no job done\n");
267f25265f0SChengwen Feng 	if (id != id_count)
268f25265f0SChengwen Feng 		ERR_RETURN("Error:incorrect job id received when no job done, %u [expected %u]\n",
269f25265f0SChengwen Feng 				id, id_count);
270f25265f0SChengwen Feng 
271f25265f0SChengwen Feng 	/* check for completed_status and id when no job done */
2721c549cddSChengwen Feng 	id = ~id;
273f25265f0SChengwen Feng 	if (rte_dma_completed_status(dev_id, vchan, 1, &id, &status) != 0)
274f25265f0SChengwen Feng 		ERR_RETURN("Error with rte_dma_completed_status when no job done\n");
275f25265f0SChengwen Feng 	if (id != id_count)
276f25265f0SChengwen Feng 		ERR_RETURN("Error:incorrect job id received when no job done, %u [expected %u]\n",
277f25265f0SChengwen Feng 				id, id_count);
278f25265f0SChengwen Feng 
2798febcbe1SBruce Richardson 	rte_pktmbuf_free(src);
2808febcbe1SBruce Richardson 	rte_pktmbuf_free(dst);
2818febcbe1SBruce Richardson 
2828febcbe1SBruce Richardson 	/* now check completion returns nothing more */
2838febcbe1SBruce Richardson 	if (rte_dma_completed(dev_id, 0, 1, NULL, NULL) != 0)
2848febcbe1SBruce Richardson 		ERR_RETURN("Error with rte_dma_completed in empty check\n");
2858febcbe1SBruce Richardson 
2868febcbe1SBruce Richardson 	id_count++;
2878febcbe1SBruce Richardson 
2888037bdc6SBruce Richardson 	return 0;
2898037bdc6SBruce Richardson }
2908037bdc6SBruce Richardson 
2918037bdc6SBruce Richardson static int
test_enqueue_copies(int16_t dev_id,uint16_t vchan)2928037bdc6SBruce Richardson test_enqueue_copies(int16_t dev_id, uint16_t vchan)
2938037bdc6SBruce Richardson {
2948037bdc6SBruce Richardson 	unsigned int i;
2958037bdc6SBruce Richardson 
2968037bdc6SBruce Richardson 	/* test doing a single copy */
2978037bdc6SBruce Richardson 	if (test_single_copy(dev_id, vchan) < 0)
2988037bdc6SBruce Richardson 		return -1;
2998febcbe1SBruce Richardson 
3008febcbe1SBruce Richardson 	/* test doing a multiple single copies */
3018febcbe1SBruce Richardson 	do {
3028037bdc6SBruce Richardson 		uint16_t id;
3038febcbe1SBruce Richardson 		const uint16_t max_ops = 4;
3048febcbe1SBruce Richardson 		struct rte_mbuf *src, *dst;
3058febcbe1SBruce Richardson 		char *src_data, *dst_data;
3068febcbe1SBruce Richardson 		uint16_t count;
3078febcbe1SBruce Richardson 
3088febcbe1SBruce Richardson 		src = rte_pktmbuf_alloc(pool);
3098febcbe1SBruce Richardson 		dst = rte_pktmbuf_alloc(pool);
3108febcbe1SBruce Richardson 		src_data = rte_pktmbuf_mtod(src, char *);
3118febcbe1SBruce Richardson 		dst_data = rte_pktmbuf_mtod(dst, char *);
3128febcbe1SBruce Richardson 
3138febcbe1SBruce Richardson 		for (i = 0; i < COPY_LEN; i++)
3148febcbe1SBruce Richardson 			src_data[i] = rte_rand() & 0xFF;
3158febcbe1SBruce Richardson 
3168febcbe1SBruce Richardson 		/* perform the same copy <max_ops> times */
3178febcbe1SBruce Richardson 		for (i = 0; i < max_ops; i++)
3188febcbe1SBruce Richardson 			if (rte_dma_copy(dev_id, vchan,
3198febcbe1SBruce Richardson 					rte_pktmbuf_iova(src),
3208febcbe1SBruce Richardson 					rte_pktmbuf_iova(dst),
3218febcbe1SBruce Richardson 					COPY_LEN, RTE_DMA_OP_FLAG_SUBMIT) != id_count++)
3228febcbe1SBruce Richardson 				ERR_RETURN("Error with rte_dma_copy\n");
3238febcbe1SBruce Richardson 
3248febcbe1SBruce Richardson 		await_hw(dev_id, vchan);
3258febcbe1SBruce Richardson 
3268febcbe1SBruce Richardson 		count = rte_dma_completed(dev_id, vchan, max_ops * 2, &id, NULL);
3278febcbe1SBruce Richardson 		if (count != max_ops)
3288febcbe1SBruce Richardson 			ERR_RETURN("Error with rte_dma_completed, got %u not %u\n",
3298febcbe1SBruce Richardson 					count, max_ops);
3308febcbe1SBruce Richardson 
3318febcbe1SBruce Richardson 		if (id != id_count - 1)
3328febcbe1SBruce Richardson 			ERR_RETURN("Error, incorrect job id returned: got %u not %u\n",
3338febcbe1SBruce Richardson 					id, id_count - 1);
3348febcbe1SBruce Richardson 
3358febcbe1SBruce Richardson 		for (i = 0; i < COPY_LEN; i++)
3368febcbe1SBruce Richardson 			if (dst_data[i] != src_data[i])
3378febcbe1SBruce Richardson 				ERR_RETURN("Data mismatch at char %u\n", i);
3388febcbe1SBruce Richardson 
3398febcbe1SBruce Richardson 		rte_pktmbuf_free(src);
3408febcbe1SBruce Richardson 		rte_pktmbuf_free(dst);
3418febcbe1SBruce Richardson 	} while (0);
3428febcbe1SBruce Richardson 
3431b86a66aSBruce Richardson 	/* test doing multiple copies */
3441b86a66aSBruce Richardson 	return do_multi_copies(dev_id, vchan, 0, 0, 0) /* enqueue and complete 1 batch at a time */
3451b86a66aSBruce Richardson 			/* enqueue 2 batches and then complete both */
3461b86a66aSBruce Richardson 			|| do_multi_copies(dev_id, vchan, 1, 0, 0)
3471b86a66aSBruce Richardson 			/* enqueue 1 batch, then complete in two halves */
3481b86a66aSBruce Richardson 			|| do_multi_copies(dev_id, vchan, 0, 1, 0)
3491b86a66aSBruce Richardson 			/* test using completed_status in place of regular completed API */
3501b86a66aSBruce Richardson 			|| do_multi_copies(dev_id, vchan, 0, 0, 1);
3518febcbe1SBruce Richardson }
3528febcbe1SBruce Richardson 
3536a9bc8c8SBruce Richardson static int
test_stop_start(int16_t dev_id,uint16_t vchan)3546a9bc8c8SBruce Richardson test_stop_start(int16_t dev_id, uint16_t vchan)
3556a9bc8c8SBruce Richardson {
3566a9bc8c8SBruce Richardson 	/* device is already started on input, should be (re)started on output */
3576a9bc8c8SBruce Richardson 
3586a9bc8c8SBruce Richardson 	uint16_t id = 0;
3596a9bc8c8SBruce Richardson 	enum rte_dma_status_code status = RTE_DMA_STATUS_SUCCESSFUL;
3606a9bc8c8SBruce Richardson 
3616a9bc8c8SBruce Richardson 	/* - test stopping a device works ok,
3626a9bc8c8SBruce Richardson 	 * - then do a start-stop without doing a copy
3636a9bc8c8SBruce Richardson 	 * - finally restart the device
3646a9bc8c8SBruce Richardson 	 * checking for errors at each stage, and validating we can still copy at the end.
3656a9bc8c8SBruce Richardson 	 */
3666a9bc8c8SBruce Richardson 	if (rte_dma_stop(dev_id) < 0)
3676a9bc8c8SBruce Richardson 		ERR_RETURN("Error stopping device\n");
3686a9bc8c8SBruce Richardson 
3696a9bc8c8SBruce Richardson 	if (rte_dma_start(dev_id) < 0)
3706a9bc8c8SBruce Richardson 		ERR_RETURN("Error restarting device\n");
3716a9bc8c8SBruce Richardson 	if (rte_dma_stop(dev_id) < 0)
3726a9bc8c8SBruce Richardson 		ERR_RETURN("Error stopping device after restart (no jobs executed)\n");
3736a9bc8c8SBruce Richardson 
3746a9bc8c8SBruce Richardson 	if (rte_dma_start(dev_id) < 0)
3756a9bc8c8SBruce Richardson 		ERR_RETURN("Error restarting device after multiple stop-starts\n");
3766a9bc8c8SBruce Richardson 
3776a9bc8c8SBruce Richardson 	/* before doing a copy, we need to know what the next id will be it should
3786a9bc8c8SBruce Richardson 	 * either be:
3796a9bc8c8SBruce Richardson 	 * - the last completed job before start if driver does not reset id on stop
3806a9bc8c8SBruce Richardson 	 * - or -1 i.e. next job is 0, if driver does reset the job ids on stop
3816a9bc8c8SBruce Richardson 	 */
3826a9bc8c8SBruce Richardson 	if (rte_dma_completed_status(dev_id, vchan, 1, &id, &status) != 0)
3836a9bc8c8SBruce Richardson 		ERR_RETURN("Error with rte_dma_completed_status when no job done\n");
3846a9bc8c8SBruce Richardson 	id += 1; /* id_count is next job id */
3856a9bc8c8SBruce Richardson 	if (id != id_count && id != 0)
3866a9bc8c8SBruce Richardson 		ERR_RETURN("Unexpected next id from device after stop-start. Got %u, expected %u or 0\n",
3876a9bc8c8SBruce Richardson 				id, id_count);
3886a9bc8c8SBruce Richardson 
3896a9bc8c8SBruce Richardson 	id_count = id;
3906a9bc8c8SBruce Richardson 	if (test_single_copy(dev_id, vchan) < 0)
3916a9bc8c8SBruce Richardson 		ERR_RETURN("Error performing copy after device restart\n");
3926a9bc8c8SBruce Richardson 	return 0;
3936a9bc8c8SBruce Richardson }
3946a9bc8c8SBruce Richardson 
395*2aba4f16SGowrishankar Muthukrishnan static int
test_enqueue_sg_copies(int16_t dev_id,uint16_t vchan)396*2aba4f16SGowrishankar Muthukrishnan test_enqueue_sg_copies(int16_t dev_id, uint16_t vchan)
397*2aba4f16SGowrishankar Muthukrishnan {
398*2aba4f16SGowrishankar Muthukrishnan 	unsigned int src_len, dst_len, n_sge, len, i, j, k;
399*2aba4f16SGowrishankar Muthukrishnan 	char orig_src[COPY_LEN], orig_dst[COPY_LEN];
400*2aba4f16SGowrishankar Muthukrishnan 	struct rte_dma_info info = { 0 };
401*2aba4f16SGowrishankar Muthukrishnan 	enum rte_dma_status_code status;
402*2aba4f16SGowrishankar Muthukrishnan 	uint16_t id, n_src, n_dst;
403*2aba4f16SGowrishankar Muthukrishnan 
404*2aba4f16SGowrishankar Muthukrishnan 	if (rte_dma_info_get(dev_id, &info) < 0)
405*2aba4f16SGowrishankar Muthukrishnan 		ERR_RETURN("Failed to get dev info");
406*2aba4f16SGowrishankar Muthukrishnan 
407*2aba4f16SGowrishankar Muthukrishnan 	if (info.max_sges < 2)
408*2aba4f16SGowrishankar Muthukrishnan 		ERR_RETURN("Test needs minimum 2 SG pointers");
409*2aba4f16SGowrishankar Muthukrishnan 
410*2aba4f16SGowrishankar Muthukrishnan 	n_sge = info.max_sges;
411*2aba4f16SGowrishankar Muthukrishnan 
412*2aba4f16SGowrishankar Muthukrishnan 	for (n_src = 1; n_src <= n_sge; n_src++) {
413*2aba4f16SGowrishankar Muthukrishnan 		for (n_dst = 1; n_dst <= n_sge; n_dst++) {
414*2aba4f16SGowrishankar Muthukrishnan 			/* Normalize SG buffer lengths */
415*2aba4f16SGowrishankar Muthukrishnan 			len = COPY_LEN;
416*2aba4f16SGowrishankar Muthukrishnan 			len -= (len % (n_src * n_dst));
417*2aba4f16SGowrishankar Muthukrishnan 			dst_len = len / n_dst;
418*2aba4f16SGowrishankar Muthukrishnan 			src_len = len / n_src;
419*2aba4f16SGowrishankar Muthukrishnan 
420*2aba4f16SGowrishankar Muthukrishnan 			struct rte_dma_sge sg_src[n_sge], sg_dst[n_sge];
421*2aba4f16SGowrishankar Muthukrishnan 			struct rte_mbuf *src[n_sge], *dst[n_sge];
422*2aba4f16SGowrishankar Muthukrishnan 			char *src_data[n_sge], *dst_data[n_sge];
423*2aba4f16SGowrishankar Muthukrishnan 
424*2aba4f16SGowrishankar Muthukrishnan 			for (i = 0 ; i < len; i++)
425*2aba4f16SGowrishankar Muthukrishnan 				orig_src[i] = rte_rand() & 0xFF;
426*2aba4f16SGowrishankar Muthukrishnan 
427*2aba4f16SGowrishankar Muthukrishnan 			memset(orig_dst, 0, len);
428*2aba4f16SGowrishankar Muthukrishnan 
429*2aba4f16SGowrishankar Muthukrishnan 			for (i = 0; i < n_src; i++) {
430*2aba4f16SGowrishankar Muthukrishnan 				src[i] = rte_pktmbuf_alloc(pool);
431*2aba4f16SGowrishankar Muthukrishnan 				RTE_ASSERT(src[i] != NULL);
432*2aba4f16SGowrishankar Muthukrishnan 				sg_src[i].addr = rte_pktmbuf_iova(src[i]);
433*2aba4f16SGowrishankar Muthukrishnan 				sg_src[i].length = src_len;
434*2aba4f16SGowrishankar Muthukrishnan 				src_data[i] = rte_pktmbuf_mtod(src[i], char *);
435*2aba4f16SGowrishankar Muthukrishnan 			}
436*2aba4f16SGowrishankar Muthukrishnan 
437*2aba4f16SGowrishankar Muthukrishnan 			for (k = 0; k < n_dst; k++) {
438*2aba4f16SGowrishankar Muthukrishnan 				dst[k] = rte_pktmbuf_alloc(pool);
439*2aba4f16SGowrishankar Muthukrishnan 				RTE_ASSERT(dst[k] != NULL);
440*2aba4f16SGowrishankar Muthukrishnan 				sg_dst[k].addr = rte_pktmbuf_iova(dst[k]);
441*2aba4f16SGowrishankar Muthukrishnan 				sg_dst[k].length = dst_len;
442*2aba4f16SGowrishankar Muthukrishnan 				dst_data[k] = rte_pktmbuf_mtod(dst[k], char *);
443*2aba4f16SGowrishankar Muthukrishnan 			}
444*2aba4f16SGowrishankar Muthukrishnan 
445*2aba4f16SGowrishankar Muthukrishnan 			for (i = 0; i < n_src; i++) {
446*2aba4f16SGowrishankar Muthukrishnan 				for (j = 0; j < src_len; j++)
447*2aba4f16SGowrishankar Muthukrishnan 					src_data[i][j] = orig_src[i * src_len + j];
448*2aba4f16SGowrishankar Muthukrishnan 			}
449*2aba4f16SGowrishankar Muthukrishnan 
450*2aba4f16SGowrishankar Muthukrishnan 			for (k = 0; k < n_dst; k++)
451*2aba4f16SGowrishankar Muthukrishnan 				memset(dst_data[k], 0, dst_len);
452*2aba4f16SGowrishankar Muthukrishnan 
453*2aba4f16SGowrishankar Muthukrishnan 			printf("\tsrc segs: %2d [seg len: %4d] - dst segs: %2d [seg len : %4d]\n",
454*2aba4f16SGowrishankar Muthukrishnan 				n_src, src_len, n_dst, dst_len);
455*2aba4f16SGowrishankar Muthukrishnan 
456*2aba4f16SGowrishankar Muthukrishnan 			id = rte_dma_copy_sg(dev_id, vchan, sg_src, sg_dst, n_src, n_dst,
457*2aba4f16SGowrishankar Muthukrishnan 					     RTE_DMA_OP_FLAG_SUBMIT);
458*2aba4f16SGowrishankar Muthukrishnan 
459*2aba4f16SGowrishankar Muthukrishnan 			if (id != id_count)
460*2aba4f16SGowrishankar Muthukrishnan 				ERR_RETURN("Error with rte_dma_copy_sg, got %u, expected %u\n",
461*2aba4f16SGowrishankar Muthukrishnan 					id, id_count);
462*2aba4f16SGowrishankar Muthukrishnan 
463*2aba4f16SGowrishankar Muthukrishnan 			/* Give time for copy to finish, then check it was done */
464*2aba4f16SGowrishankar Muthukrishnan 			await_hw(dev_id, vchan);
465*2aba4f16SGowrishankar Muthukrishnan 
466*2aba4f16SGowrishankar Muthukrishnan 			for (k = 0; k < n_dst; k++)
467*2aba4f16SGowrishankar Muthukrishnan 				memcpy((&orig_dst[0] + k * dst_len), dst_data[k], dst_len);
468*2aba4f16SGowrishankar Muthukrishnan 
469*2aba4f16SGowrishankar Muthukrishnan 			if (memcmp(orig_src, orig_dst, COPY_LEN))
470*2aba4f16SGowrishankar Muthukrishnan 				ERR_RETURN("Data mismatch");
471*2aba4f16SGowrishankar Muthukrishnan 
472*2aba4f16SGowrishankar Muthukrishnan 			/* Verify completion */
473*2aba4f16SGowrishankar Muthukrishnan 			id = ~id;
474*2aba4f16SGowrishankar Muthukrishnan 			if (rte_dma_completed(dev_id, vchan, 1, &id, NULL) != 1)
475*2aba4f16SGowrishankar Muthukrishnan 				ERR_RETURN("Error with rte_dma_completed\n");
476*2aba4f16SGowrishankar Muthukrishnan 
477*2aba4f16SGowrishankar Muthukrishnan 			/* Verify expected index(id_count) */
478*2aba4f16SGowrishankar Muthukrishnan 			if (id != id_count)
479*2aba4f16SGowrishankar Muthukrishnan 				ERR_RETURN("Error:incorrect job id received, %u [expected %u]\n",
480*2aba4f16SGowrishankar Muthukrishnan 						id, id_count);
481*2aba4f16SGowrishankar Muthukrishnan 
482*2aba4f16SGowrishankar Muthukrishnan 			/* Check for completed and id when no job done */
483*2aba4f16SGowrishankar Muthukrishnan 			id = ~id;
484*2aba4f16SGowrishankar Muthukrishnan 			if (rte_dma_completed(dev_id, vchan, 1, &id, NULL) != 0)
485*2aba4f16SGowrishankar Muthukrishnan 				ERR_RETURN("Error with rte_dma_completed when no job done\n");
486*2aba4f16SGowrishankar Muthukrishnan 
487*2aba4f16SGowrishankar Muthukrishnan 			if (id != id_count)
488*2aba4f16SGowrishankar Muthukrishnan 				ERR_RETURN("Error:incorrect job id received when no job done, %u [expected %u]\n",
489*2aba4f16SGowrishankar Muthukrishnan 					   id, id_count);
490*2aba4f16SGowrishankar Muthukrishnan 
491*2aba4f16SGowrishankar Muthukrishnan 			/* Check for completed_status and id when no job done */
492*2aba4f16SGowrishankar Muthukrishnan 			id = ~id;
493*2aba4f16SGowrishankar Muthukrishnan 			if (rte_dma_completed_status(dev_id, vchan, 1, &id, &status) != 0)
494*2aba4f16SGowrishankar Muthukrishnan 				ERR_RETURN("Error with rte_dma_completed_status when no job done\n");
495*2aba4f16SGowrishankar Muthukrishnan 			if (id != id_count)
496*2aba4f16SGowrishankar Muthukrishnan 				ERR_RETURN("Error:incorrect job id received when no job done, %u [expected %u]\n",
497*2aba4f16SGowrishankar Muthukrishnan 						id, 0);
498*2aba4f16SGowrishankar Muthukrishnan 
499*2aba4f16SGowrishankar Muthukrishnan 			for (i = 0; i < n_src; i++)
500*2aba4f16SGowrishankar Muthukrishnan 				rte_pktmbuf_free(src[i]);
501*2aba4f16SGowrishankar Muthukrishnan 			for (i = 0; i < n_dst; i++)
502*2aba4f16SGowrishankar Muthukrishnan 				rte_pktmbuf_free(dst[i]);
503*2aba4f16SGowrishankar Muthukrishnan 
504*2aba4f16SGowrishankar Muthukrishnan 			/* Verify that completion returns nothing more */
505*2aba4f16SGowrishankar Muthukrishnan 			if (rte_dma_completed(dev_id, 0, 1, NULL, NULL) != 0)
506*2aba4f16SGowrishankar Muthukrishnan 				ERR_RETURN("Error with rte_dma_completed in empty check\n");
507*2aba4f16SGowrishankar Muthukrishnan 
508*2aba4f16SGowrishankar Muthukrishnan 			id_count++;
509*2aba4f16SGowrishankar Muthukrishnan 		}
510*2aba4f16SGowrishankar Muthukrishnan 	}
511*2aba4f16SGowrishankar Muthukrishnan 	return 0;
512*2aba4f16SGowrishankar Muthukrishnan }
513*2aba4f16SGowrishankar Muthukrishnan 
51499d7ec4bSBruce Richardson /* Failure handling test cases - global macros and variables for those tests*/
51599d7ec4bSBruce Richardson #define COMP_BURST_SZ	16
51699d7ec4bSBruce Richardson #define OPT_FENCE(idx) ((fence && idx == 8) ? RTE_DMA_OP_FLAG_FENCE : 0)
51799d7ec4bSBruce Richardson 
51899d7ec4bSBruce Richardson static int
test_failure_in_full_burst(int16_t dev_id,uint16_t vchan,bool fence,struct rte_mbuf ** srcs,struct rte_mbuf ** dsts,unsigned int fail_idx)51999d7ec4bSBruce Richardson test_failure_in_full_burst(int16_t dev_id, uint16_t vchan, bool fence,
52099d7ec4bSBruce Richardson 		struct rte_mbuf **srcs, struct rte_mbuf **dsts, unsigned int fail_idx)
52199d7ec4bSBruce Richardson {
52299d7ec4bSBruce Richardson 	/* Test single full batch statuses with failures */
52399d7ec4bSBruce Richardson 	enum rte_dma_status_code status[COMP_BURST_SZ];
52499d7ec4bSBruce Richardson 	struct rte_dma_stats baseline, stats;
52599d7ec4bSBruce Richardson 	uint16_t invalid_addr_id = 0;
52699d7ec4bSBruce Richardson 	uint16_t idx;
52799d7ec4bSBruce Richardson 	uint16_t count, status_count;
52899d7ec4bSBruce Richardson 	unsigned int i;
52999d7ec4bSBruce Richardson 	bool error = false;
53099d7ec4bSBruce Richardson 	int err_count = 0;
53199d7ec4bSBruce Richardson 
53299d7ec4bSBruce Richardson 	rte_dma_stats_get(dev_id, vchan, &baseline); /* get a baseline set of stats */
53399d7ec4bSBruce Richardson 	for (i = 0; i < COMP_BURST_SZ; i++) {
53499d7ec4bSBruce Richardson 		int id = rte_dma_copy(dev_id, vchan,
53539683912SShijith Thotton 				      (i == fail_idx ? 0 : rte_mbuf_data_iova(srcs[i])),
53639683912SShijith Thotton 				      rte_mbuf_data_iova(dsts[i]), COPY_LEN, OPT_FENCE(i));
53799d7ec4bSBruce Richardson 		if (id < 0)
53899d7ec4bSBruce Richardson 			ERR_RETURN("Error with rte_dma_copy for buffer %u\n", i);
53999d7ec4bSBruce Richardson 		if (i == fail_idx)
54099d7ec4bSBruce Richardson 			invalid_addr_id = id;
54199d7ec4bSBruce Richardson 	}
54299d7ec4bSBruce Richardson 	rte_dma_submit(dev_id, vchan);
54399d7ec4bSBruce Richardson 	rte_dma_stats_get(dev_id, vchan, &stats);
54499d7ec4bSBruce Richardson 	if (stats.submitted != baseline.submitted + COMP_BURST_SZ)
54599d7ec4bSBruce Richardson 		ERR_RETURN("Submitted stats value not as expected, %"PRIu64" not %"PRIu64"\n",
54699d7ec4bSBruce Richardson 				stats.submitted, baseline.submitted + COMP_BURST_SZ);
54799d7ec4bSBruce Richardson 
54899d7ec4bSBruce Richardson 	await_hw(dev_id, vchan);
54999d7ec4bSBruce Richardson 
55099d7ec4bSBruce Richardson 	count = rte_dma_completed(dev_id, vchan, COMP_BURST_SZ, &idx, &error);
55199d7ec4bSBruce Richardson 	if (count != fail_idx)
55299d7ec4bSBruce Richardson 		ERR_RETURN("Error with rte_dma_completed for failure test. Got returned %u not %u.\n",
55399d7ec4bSBruce Richardson 				count, fail_idx);
55499d7ec4bSBruce Richardson 	if (!error)
55599d7ec4bSBruce Richardson 		ERR_RETURN("Error, missing expected failed copy, %u. has_error is not set\n",
55699d7ec4bSBruce Richardson 				fail_idx);
55799d7ec4bSBruce Richardson 	if (idx != invalid_addr_id - 1)
55899d7ec4bSBruce Richardson 		ERR_RETURN("Error, missing expected failed copy, %u. Got last idx %u, not %u\n",
55999d7ec4bSBruce Richardson 				fail_idx, idx, invalid_addr_id - 1);
56099d7ec4bSBruce Richardson 
56199d7ec4bSBruce Richardson 	/* all checks ok, now verify calling completed() again always returns 0 */
56299d7ec4bSBruce Richardson 	for (i = 0; i < 10; i++)
56399d7ec4bSBruce Richardson 		if (rte_dma_completed(dev_id, vchan, COMP_BURST_SZ, &idx, &error) != 0
56499d7ec4bSBruce Richardson 				|| error == false || idx != (invalid_addr_id - 1))
56599d7ec4bSBruce Richardson 			ERR_RETURN("Error with follow-up completed calls for fail idx %u\n",
56699d7ec4bSBruce Richardson 					fail_idx);
56799d7ec4bSBruce Richardson 
56899d7ec4bSBruce Richardson 	status_count = rte_dma_completed_status(dev_id, vchan, COMP_BURST_SZ,
56999d7ec4bSBruce Richardson 			&idx, status);
57099d7ec4bSBruce Richardson 	/* some HW may stop on error and be restarted after getting error status for single value
57199d7ec4bSBruce Richardson 	 * To handle this case, if we get just one error back, wait for more completions and get
57299d7ec4bSBruce Richardson 	 * status for rest of the burst
57399d7ec4bSBruce Richardson 	 */
57499d7ec4bSBruce Richardson 	if (status_count == 1) {
57599d7ec4bSBruce Richardson 		await_hw(dev_id, vchan);
57699d7ec4bSBruce Richardson 		status_count += rte_dma_completed_status(dev_id, vchan, COMP_BURST_SZ - 1,
57799d7ec4bSBruce Richardson 					&idx, &status[1]);
57899d7ec4bSBruce Richardson 	}
57999d7ec4bSBruce Richardson 	/* check that at this point we have all status values */
58099d7ec4bSBruce Richardson 	if (status_count != COMP_BURST_SZ - count)
58199d7ec4bSBruce Richardson 		ERR_RETURN("Error with completed_status calls for fail idx %u. Got %u not %u\n",
58299d7ec4bSBruce Richardson 				fail_idx, status_count, COMP_BURST_SZ - count);
58399d7ec4bSBruce Richardson 	/* now verify just one failure followed by multiple successful or skipped entries */
58499d7ec4bSBruce Richardson 	if (status[0] == RTE_DMA_STATUS_SUCCESSFUL)
58599d7ec4bSBruce Richardson 		ERR_RETURN("Error with status returned for fail idx %u. First status was not failure\n",
58699d7ec4bSBruce Richardson 				fail_idx);
58799d7ec4bSBruce Richardson 	for (i = 1; i < status_count; i++)
58899d7ec4bSBruce Richardson 		/* after a failure in a burst, depending on ordering/fencing,
58999d7ec4bSBruce Richardson 		 * operations may be successful or skipped because of previous error.
59099d7ec4bSBruce Richardson 		 */
59199d7ec4bSBruce Richardson 		if (status[i] != RTE_DMA_STATUS_SUCCESSFUL
59299d7ec4bSBruce Richardson 				&& status[i] != RTE_DMA_STATUS_NOT_ATTEMPTED)
59399d7ec4bSBruce Richardson 			ERR_RETURN("Error with status calls for fail idx %u. Status for job %u (of %u) is not successful\n",
59499d7ec4bSBruce Richardson 					fail_idx, count + i, COMP_BURST_SZ);
59599d7ec4bSBruce Richardson 
59699d7ec4bSBruce Richardson 	/* check the completed + errors stats are as expected */
59799d7ec4bSBruce Richardson 	rte_dma_stats_get(dev_id, vchan, &stats);
59899d7ec4bSBruce Richardson 	if (stats.completed != baseline.completed + COMP_BURST_SZ)
59999d7ec4bSBruce Richardson 		ERR_RETURN("Completed stats value not as expected, %"PRIu64" not %"PRIu64"\n",
60099d7ec4bSBruce Richardson 				stats.completed, baseline.completed + COMP_BURST_SZ);
60199d7ec4bSBruce Richardson 	for (i = 0; i < status_count; i++)
60299d7ec4bSBruce Richardson 		err_count += (status[i] != RTE_DMA_STATUS_SUCCESSFUL);
60399d7ec4bSBruce Richardson 	if (stats.errors != baseline.errors + err_count)
60499d7ec4bSBruce Richardson 		ERR_RETURN("'Errors' stats value not as expected, %"PRIu64" not %"PRIu64"\n",
60599d7ec4bSBruce Richardson 				stats.errors, baseline.errors + err_count);
60699d7ec4bSBruce Richardson 
60799d7ec4bSBruce Richardson 	return 0;
60899d7ec4bSBruce Richardson }
60999d7ec4bSBruce Richardson 
61099d7ec4bSBruce Richardson static int
test_individual_status_query_with_failure(int16_t dev_id,uint16_t vchan,bool fence,struct rte_mbuf ** srcs,struct rte_mbuf ** dsts,unsigned int fail_idx)61199d7ec4bSBruce Richardson test_individual_status_query_with_failure(int16_t dev_id, uint16_t vchan, bool fence,
61299d7ec4bSBruce Richardson 		struct rte_mbuf **srcs, struct rte_mbuf **dsts, unsigned int fail_idx)
61399d7ec4bSBruce Richardson {
61499d7ec4bSBruce Richardson 	/* Test gathering batch statuses one at a time */
61599d7ec4bSBruce Richardson 	enum rte_dma_status_code status[COMP_BURST_SZ];
61699d7ec4bSBruce Richardson 	uint16_t invalid_addr_id = 0;
61799d7ec4bSBruce Richardson 	uint16_t idx;
61899d7ec4bSBruce Richardson 	uint16_t count = 0, status_count = 0;
61999d7ec4bSBruce Richardson 	unsigned int j;
62099d7ec4bSBruce Richardson 	bool error = false;
62199d7ec4bSBruce Richardson 
62299d7ec4bSBruce Richardson 	for (j = 0; j < COMP_BURST_SZ; j++) {
62399d7ec4bSBruce Richardson 		int id = rte_dma_copy(dev_id, vchan,
62439683912SShijith Thotton 				      (j == fail_idx ? 0 : rte_mbuf_data_iova(srcs[j])),
62539683912SShijith Thotton 				      rte_mbuf_data_iova(dsts[j]), COPY_LEN, OPT_FENCE(j));
62699d7ec4bSBruce Richardson 		if (id < 0)
62799d7ec4bSBruce Richardson 			ERR_RETURN("Error with rte_dma_copy for buffer %u\n", j);
62899d7ec4bSBruce Richardson 		if (j == fail_idx)
62999d7ec4bSBruce Richardson 			invalid_addr_id = id;
63099d7ec4bSBruce Richardson 	}
63199d7ec4bSBruce Richardson 	rte_dma_submit(dev_id, vchan);
63299d7ec4bSBruce Richardson 	await_hw(dev_id, vchan);
63399d7ec4bSBruce Richardson 
63499d7ec4bSBruce Richardson 	/* use regular "completed" until we hit error */
63599d7ec4bSBruce Richardson 	while (!error) {
63699d7ec4bSBruce Richardson 		uint16_t n = rte_dma_completed(dev_id, vchan, 1, &idx, &error);
63799d7ec4bSBruce Richardson 		count += n;
63899d7ec4bSBruce Richardson 		if (n > 1 || count >= COMP_BURST_SZ)
63999d7ec4bSBruce Richardson 			ERR_RETURN("Error - too many completions got\n");
64099d7ec4bSBruce Richardson 		if (n == 0 && !error)
64199d7ec4bSBruce Richardson 			ERR_RETURN("Error, unexpectedly got zero completions after %u completed\n",
64299d7ec4bSBruce Richardson 					count);
64399d7ec4bSBruce Richardson 	}
64499d7ec4bSBruce Richardson 	if (idx != invalid_addr_id - 1)
64599d7ec4bSBruce Richardson 		ERR_RETURN("Error, last successful index not as expected, got %u, expected %u\n",
64699d7ec4bSBruce Richardson 				idx, invalid_addr_id - 1);
64799d7ec4bSBruce Richardson 
64899d7ec4bSBruce Richardson 	/* use completed_status until we hit end of burst */
64999d7ec4bSBruce Richardson 	while (count + status_count < COMP_BURST_SZ) {
65099d7ec4bSBruce Richardson 		uint16_t n = rte_dma_completed_status(dev_id, vchan, 1, &idx,
65199d7ec4bSBruce Richardson 				&status[status_count]);
65299d7ec4bSBruce Richardson 		await_hw(dev_id, vchan); /* allow delay to ensure jobs are completed */
65399d7ec4bSBruce Richardson 		status_count += n;
65499d7ec4bSBruce Richardson 		if (n != 1)
65599d7ec4bSBruce Richardson 			ERR_RETURN("Error: unexpected number of completions received, %u, not 1\n",
65699d7ec4bSBruce Richardson 					n);
65799d7ec4bSBruce Richardson 	}
65899d7ec4bSBruce Richardson 
65999d7ec4bSBruce Richardson 	/* check for single failure */
66099d7ec4bSBruce Richardson 	if (status[0] == RTE_DMA_STATUS_SUCCESSFUL)
66199d7ec4bSBruce Richardson 		ERR_RETURN("Error, unexpected successful DMA transaction\n");
66299d7ec4bSBruce Richardson 	for (j = 1; j < status_count; j++)
66399d7ec4bSBruce Richardson 		if (status[j] != RTE_DMA_STATUS_SUCCESSFUL
66499d7ec4bSBruce Richardson 				&& status[j] != RTE_DMA_STATUS_NOT_ATTEMPTED)
66599d7ec4bSBruce Richardson 			ERR_RETURN("Error, unexpected DMA error reported\n");
66699d7ec4bSBruce Richardson 
66799d7ec4bSBruce Richardson 	return 0;
66899d7ec4bSBruce Richardson }
66999d7ec4bSBruce Richardson 
67099d7ec4bSBruce Richardson static int
test_single_item_status_query_with_failure(int16_t dev_id,uint16_t vchan,struct rte_mbuf ** srcs,struct rte_mbuf ** dsts,unsigned int fail_idx)67199d7ec4bSBruce Richardson test_single_item_status_query_with_failure(int16_t dev_id, uint16_t vchan,
67299d7ec4bSBruce Richardson 		struct rte_mbuf **srcs, struct rte_mbuf **dsts, unsigned int fail_idx)
67399d7ec4bSBruce Richardson {
67499d7ec4bSBruce Richardson 	/* When error occurs just collect a single error using "completed_status()"
67599d7ec4bSBruce Richardson 	 * before going to back to completed() calls
67699d7ec4bSBruce Richardson 	 */
67799d7ec4bSBruce Richardson 	enum rte_dma_status_code status;
67899d7ec4bSBruce Richardson 	uint16_t invalid_addr_id = 0;
67999d7ec4bSBruce Richardson 	uint16_t idx;
68099d7ec4bSBruce Richardson 	uint16_t count, status_count, count2;
68199d7ec4bSBruce Richardson 	unsigned int j;
68299d7ec4bSBruce Richardson 	bool error = false;
68399d7ec4bSBruce Richardson 
68499d7ec4bSBruce Richardson 	for (j = 0; j < COMP_BURST_SZ; j++) {
68599d7ec4bSBruce Richardson 		int id = rte_dma_copy(dev_id, vchan,
68639683912SShijith Thotton 				      (j == fail_idx ? 0 : rte_mbuf_data_iova(srcs[j])),
68739683912SShijith Thotton 				      rte_mbuf_data_iova(dsts[j]), COPY_LEN, 0);
68899d7ec4bSBruce Richardson 		if (id < 0)
68999d7ec4bSBruce Richardson 			ERR_RETURN("Error with rte_dma_copy for buffer %u\n", j);
69099d7ec4bSBruce Richardson 		if (j == fail_idx)
69199d7ec4bSBruce Richardson 			invalid_addr_id = id;
69299d7ec4bSBruce Richardson 	}
69399d7ec4bSBruce Richardson 	rte_dma_submit(dev_id, vchan);
69499d7ec4bSBruce Richardson 	await_hw(dev_id, vchan);
69599d7ec4bSBruce Richardson 
69699d7ec4bSBruce Richardson 	/* get up to the error point */
69799d7ec4bSBruce Richardson 	count = rte_dma_completed(dev_id, vchan, COMP_BURST_SZ, &idx, &error);
69899d7ec4bSBruce Richardson 	if (count != fail_idx)
69999d7ec4bSBruce Richardson 		ERR_RETURN("Error with rte_dma_completed for failure test. Got returned %u not %u.\n",
70099d7ec4bSBruce Richardson 				count, fail_idx);
70199d7ec4bSBruce Richardson 	if (!error)
70299d7ec4bSBruce Richardson 		ERR_RETURN("Error, missing expected failed copy, %u. has_error is not set\n",
70399d7ec4bSBruce Richardson 				fail_idx);
70499d7ec4bSBruce Richardson 	if (idx != invalid_addr_id - 1)
70599d7ec4bSBruce Richardson 		ERR_RETURN("Error, missing expected failed copy, %u. Got last idx %u, not %u\n",
70699d7ec4bSBruce Richardson 				fail_idx, idx, invalid_addr_id - 1);
70799d7ec4bSBruce Richardson 
70899d7ec4bSBruce Richardson 	/* get the error code */
70999d7ec4bSBruce Richardson 	status_count = rte_dma_completed_status(dev_id, vchan, 1, &idx, &status);
71099d7ec4bSBruce Richardson 	if (status_count != 1)
71199d7ec4bSBruce Richardson 		ERR_RETURN("Error with completed_status calls for fail idx %u. Got %u not %u\n",
71299d7ec4bSBruce Richardson 				fail_idx, status_count, COMP_BURST_SZ - count);
71399d7ec4bSBruce Richardson 	if (status == RTE_DMA_STATUS_SUCCESSFUL)
71499d7ec4bSBruce Richardson 		ERR_RETURN("Error with status returned for fail idx %u. First status was not failure\n",
71599d7ec4bSBruce Richardson 				fail_idx);
71699d7ec4bSBruce Richardson 
71799d7ec4bSBruce Richardson 	/* delay in case time needed after err handled to complete other jobs */
71899d7ec4bSBruce Richardson 	await_hw(dev_id, vchan);
71999d7ec4bSBruce Richardson 
72099d7ec4bSBruce Richardson 	/* get the rest of the completions without status */
72199d7ec4bSBruce Richardson 	count2 = rte_dma_completed(dev_id, vchan, COMP_BURST_SZ, &idx, &error);
72299d7ec4bSBruce Richardson 	if (error == true)
72399d7ec4bSBruce Richardson 		ERR_RETURN("Error, got further errors post completed_status() call, for failure case %u.\n",
72499d7ec4bSBruce Richardson 				fail_idx);
72599d7ec4bSBruce Richardson 	if (count + status_count + count2 != COMP_BURST_SZ)
72699d7ec4bSBruce Richardson 		ERR_RETURN("Error, incorrect number of completions received, got %u not %u\n",
72799d7ec4bSBruce Richardson 				count + status_count + count2, COMP_BURST_SZ);
72899d7ec4bSBruce Richardson 
72999d7ec4bSBruce Richardson 	return 0;
73099d7ec4bSBruce Richardson }
73199d7ec4bSBruce Richardson 
73299d7ec4bSBruce Richardson static int
test_multi_failure(int16_t dev_id,uint16_t vchan,struct rte_mbuf ** srcs,struct rte_mbuf ** dsts,const unsigned int * fail,size_t num_fail)73399d7ec4bSBruce Richardson test_multi_failure(int16_t dev_id, uint16_t vchan, struct rte_mbuf **srcs, struct rte_mbuf **dsts,
73499d7ec4bSBruce Richardson 		const unsigned int *fail, size_t num_fail)
73599d7ec4bSBruce Richardson {
73699d7ec4bSBruce Richardson 	/* test having multiple errors in one go */
73799d7ec4bSBruce Richardson 	enum rte_dma_status_code status[COMP_BURST_SZ];
73899d7ec4bSBruce Richardson 	unsigned int i, j;
73999d7ec4bSBruce Richardson 	uint16_t count, err_count = 0;
74099d7ec4bSBruce Richardson 	bool error = false;
74199d7ec4bSBruce Richardson 
74299d7ec4bSBruce Richardson 	/* enqueue and gather completions in one go */
74399d7ec4bSBruce Richardson 	for (j = 0; j < COMP_BURST_SZ; j++) {
74439683912SShijith Thotton 		uintptr_t src = rte_mbuf_data_iova(srcs[j]);
74599d7ec4bSBruce Richardson 		/* set up for failure if the current index is anywhere is the fails array */
74699d7ec4bSBruce Richardson 		for (i = 0; i < num_fail; i++)
74799d7ec4bSBruce Richardson 			if (j == fail[i])
74899d7ec4bSBruce Richardson 				src = 0;
74999d7ec4bSBruce Richardson 
75039683912SShijith Thotton 		int id = rte_dma_copy(dev_id, vchan, src, rte_mbuf_data_iova(dsts[j]),
75199d7ec4bSBruce Richardson 				      COPY_LEN, 0);
75299d7ec4bSBruce Richardson 		if (id < 0)
75399d7ec4bSBruce Richardson 			ERR_RETURN("Error with rte_dma_copy for buffer %u\n", j);
75499d7ec4bSBruce Richardson 	}
75599d7ec4bSBruce Richardson 	rte_dma_submit(dev_id, vchan);
75699d7ec4bSBruce Richardson 	await_hw(dev_id, vchan);
75799d7ec4bSBruce Richardson 
75899d7ec4bSBruce Richardson 	count = rte_dma_completed_status(dev_id, vchan, COMP_BURST_SZ, NULL, status);
75999d7ec4bSBruce Richardson 	while (count < COMP_BURST_SZ) {
76099d7ec4bSBruce Richardson 		await_hw(dev_id, vchan);
76199d7ec4bSBruce Richardson 
76299d7ec4bSBruce Richardson 		uint16_t ret = rte_dma_completed_status(dev_id, vchan, COMP_BURST_SZ - count,
76399d7ec4bSBruce Richardson 				NULL, &status[count]);
76499d7ec4bSBruce Richardson 		if (ret == 0)
76599d7ec4bSBruce Richardson 			ERR_RETURN("Error getting all completions for jobs. Got %u of %u\n",
76699d7ec4bSBruce Richardson 					count, COMP_BURST_SZ);
76799d7ec4bSBruce Richardson 		count += ret;
76899d7ec4bSBruce Richardson 	}
76999d7ec4bSBruce Richardson 	for (i = 0; i < count; i++)
77099d7ec4bSBruce Richardson 		if (status[i] != RTE_DMA_STATUS_SUCCESSFUL)
77199d7ec4bSBruce Richardson 			err_count++;
77299d7ec4bSBruce Richardson 
77399d7ec4bSBruce Richardson 	if (err_count != num_fail)
77499d7ec4bSBruce Richardson 		ERR_RETURN("Error: Invalid number of failed completions returned, %u; expected %zu\n",
77599d7ec4bSBruce Richardson 			err_count, num_fail);
77699d7ec4bSBruce Richardson 
77799d7ec4bSBruce Richardson 	/* enqueue and gather completions in bursts, but getting errors one at a time */
77899d7ec4bSBruce Richardson 	for (j = 0; j < COMP_BURST_SZ; j++) {
77939683912SShijith Thotton 		uintptr_t src = rte_mbuf_data_iova(srcs[j]);
78099d7ec4bSBruce Richardson 		/* set up for failure if the current index is anywhere is the fails array */
78199d7ec4bSBruce Richardson 		for (i = 0; i < num_fail; i++)
78299d7ec4bSBruce Richardson 			if (j == fail[i])
78399d7ec4bSBruce Richardson 				src = 0;
78499d7ec4bSBruce Richardson 
78539683912SShijith Thotton 		int id = rte_dma_copy(dev_id, vchan, src, rte_mbuf_data_iova(dsts[j]),
78699d7ec4bSBruce Richardson 				      COPY_LEN, 0);
78799d7ec4bSBruce Richardson 		if (id < 0)
78899d7ec4bSBruce Richardson 			ERR_RETURN("Error with rte_dma_copy for buffer %u\n", j);
78999d7ec4bSBruce Richardson 	}
79099d7ec4bSBruce Richardson 	rte_dma_submit(dev_id, vchan);
79199d7ec4bSBruce Richardson 	await_hw(dev_id, vchan);
79299d7ec4bSBruce Richardson 
79399d7ec4bSBruce Richardson 	count = 0;
79499d7ec4bSBruce Richardson 	err_count = 0;
79599d7ec4bSBruce Richardson 	while (count + err_count < COMP_BURST_SZ) {
79699d7ec4bSBruce Richardson 		count += rte_dma_completed(dev_id, vchan, COMP_BURST_SZ, NULL, &error);
79799d7ec4bSBruce Richardson 		if (error) {
79899d7ec4bSBruce Richardson 			uint16_t ret = rte_dma_completed_status(dev_id, vchan, 1,
79999d7ec4bSBruce Richardson 					NULL, status);
80099d7ec4bSBruce Richardson 			if (ret != 1)
80199d7ec4bSBruce Richardson 				ERR_RETURN("Error getting error-status for completions\n");
80299d7ec4bSBruce Richardson 			err_count += ret;
80399d7ec4bSBruce Richardson 			await_hw(dev_id, vchan);
80499d7ec4bSBruce Richardson 		}
80599d7ec4bSBruce Richardson 	}
80699d7ec4bSBruce Richardson 	if (err_count != num_fail)
80799d7ec4bSBruce Richardson 		ERR_RETURN("Error: Incorrect number of failed completions received, got %u not %zu\n",
80899d7ec4bSBruce Richardson 				err_count, num_fail);
80999d7ec4bSBruce Richardson 
81099d7ec4bSBruce Richardson 	return 0;
81199d7ec4bSBruce Richardson }
81299d7ec4bSBruce Richardson 
81399d7ec4bSBruce Richardson static int
test_completion_status(int16_t dev_id,uint16_t vchan,bool fence)81499d7ec4bSBruce Richardson test_completion_status(int16_t dev_id, uint16_t vchan, bool fence)
81599d7ec4bSBruce Richardson {
81699d7ec4bSBruce Richardson 	const unsigned int fail[] = {0, 7, 14, 15};
81799d7ec4bSBruce Richardson 	struct rte_mbuf *srcs[COMP_BURST_SZ], *dsts[COMP_BURST_SZ];
81899d7ec4bSBruce Richardson 	unsigned int i;
81999d7ec4bSBruce Richardson 
82099d7ec4bSBruce Richardson 	for (i = 0; i < COMP_BURST_SZ; i++) {
82199d7ec4bSBruce Richardson 		srcs[i] = rte_pktmbuf_alloc(pool);
82299d7ec4bSBruce Richardson 		dsts[i] = rte_pktmbuf_alloc(pool);
82399d7ec4bSBruce Richardson 	}
82499d7ec4bSBruce Richardson 
82599d7ec4bSBruce Richardson 	for (i = 0; i < RTE_DIM(fail); i++) {
82699d7ec4bSBruce Richardson 		if (test_failure_in_full_burst(dev_id, vchan, fence, srcs, dsts, fail[i]) < 0)
82799d7ec4bSBruce Richardson 			return -1;
82899d7ec4bSBruce Richardson 
82999d7ec4bSBruce Richardson 		if (test_individual_status_query_with_failure(dev_id, vchan, fence,
83099d7ec4bSBruce Richardson 				srcs, dsts, fail[i]) < 0)
83199d7ec4bSBruce Richardson 			return -1;
83299d7ec4bSBruce Richardson 
83399d7ec4bSBruce Richardson 		/* test is run the same fenced, or unfenced, but no harm in running it twice */
83499d7ec4bSBruce Richardson 		if (test_single_item_status_query_with_failure(dev_id, vchan,
83599d7ec4bSBruce Richardson 				srcs, dsts, fail[i]) < 0)
83699d7ec4bSBruce Richardson 			return -1;
83799d7ec4bSBruce Richardson 	}
83899d7ec4bSBruce Richardson 
83999d7ec4bSBruce Richardson 	if (test_multi_failure(dev_id, vchan, srcs, dsts, fail, RTE_DIM(fail)) < 0)
84099d7ec4bSBruce Richardson 		return -1;
84199d7ec4bSBruce Richardson 
84299d7ec4bSBruce Richardson 	for (i = 0; i < COMP_BURST_SZ; i++) {
84399d7ec4bSBruce Richardson 		rte_pktmbuf_free(srcs[i]);
84499d7ec4bSBruce Richardson 		rte_pktmbuf_free(dsts[i]);
84599d7ec4bSBruce Richardson 	}
84699d7ec4bSBruce Richardson 	return 0;
84799d7ec4bSBruce Richardson }
84899d7ec4bSBruce Richardson 
84999d7ec4bSBruce Richardson static int
test_completion_handling(int16_t dev_id,uint16_t vchan)85099d7ec4bSBruce Richardson test_completion_handling(int16_t dev_id, uint16_t vchan)
85199d7ec4bSBruce Richardson {
85299d7ec4bSBruce Richardson 	return test_completion_status(dev_id, vchan, false)              /* without fences */
85399d7ec4bSBruce Richardson 			|| test_completion_status(dev_id, vchan, true);  /* with fences */
854e00fcb0fSKevin Laatz }
85599d7ec4bSBruce Richardson 
856e00fcb0fSKevin Laatz static int
test_enqueue_fill(int16_t dev_id,uint16_t vchan)857e00fcb0fSKevin Laatz test_enqueue_fill(int16_t dev_id, uint16_t vchan)
858e00fcb0fSKevin Laatz {
859e00fcb0fSKevin Laatz 	const unsigned int lengths[] = {8, 64, 1024, 50, 100, 89};
860e00fcb0fSKevin Laatz 	struct rte_mbuf *dst;
861e00fcb0fSKevin Laatz 	char *dst_data;
862e00fcb0fSKevin Laatz 	uint64_t pattern = 0xfedcba9876543210;
863e00fcb0fSKevin Laatz 	unsigned int i, j;
864e00fcb0fSKevin Laatz 
865e00fcb0fSKevin Laatz 	dst = rte_pktmbuf_alloc(pool);
866e00fcb0fSKevin Laatz 	if (dst == NULL)
867e00fcb0fSKevin Laatz 		ERR_RETURN("Failed to allocate mbuf\n");
868e00fcb0fSKevin Laatz 	dst_data = rte_pktmbuf_mtod(dst, char *);
869e00fcb0fSKevin Laatz 
870e00fcb0fSKevin Laatz 	for (i = 0; i < RTE_DIM(lengths); i++) {
871e00fcb0fSKevin Laatz 		/* reset dst_data */
872e00fcb0fSKevin Laatz 		memset(dst_data, 0, rte_pktmbuf_data_len(dst));
873e00fcb0fSKevin Laatz 
874e00fcb0fSKevin Laatz 		/* perform the fill operation */
875e00fcb0fSKevin Laatz 		int id = rte_dma_fill(dev_id, vchan, pattern,
876e00fcb0fSKevin Laatz 				rte_pktmbuf_iova(dst), lengths[i], RTE_DMA_OP_FLAG_SUBMIT);
877e00fcb0fSKevin Laatz 		if (id < 0)
878e00fcb0fSKevin Laatz 			ERR_RETURN("Error with rte_dma_fill\n");
879e00fcb0fSKevin Laatz 		await_hw(dev_id, vchan);
880e00fcb0fSKevin Laatz 
881e00fcb0fSKevin Laatz 		if (rte_dma_completed(dev_id, vchan, 1, NULL, NULL) != 1)
882e00fcb0fSKevin Laatz 			ERR_RETURN("Error: fill operation failed (length: %u)\n", lengths[i]);
883e00fcb0fSKevin Laatz 		/* check the data from the fill operation is correct */
884e00fcb0fSKevin Laatz 		for (j = 0; j < lengths[i]; j++) {
885e00fcb0fSKevin Laatz 			char pat_byte = ((char *)&pattern)[j % 8];
886e00fcb0fSKevin Laatz 			if (dst_data[j] != pat_byte)
887e00fcb0fSKevin Laatz 				ERR_RETURN("Error with fill operation (lengths = %u): got (%x), not (%x)\n",
888e00fcb0fSKevin Laatz 						lengths[i], dst_data[j], pat_byte);
889e00fcb0fSKevin Laatz 		}
890e00fcb0fSKevin Laatz 		/* check that the data after the fill operation was not written to */
891e00fcb0fSKevin Laatz 		for (; j < rte_pktmbuf_data_len(dst); j++)
892e00fcb0fSKevin Laatz 			if (dst_data[j] != 0)
893e00fcb0fSKevin Laatz 				ERR_RETURN("Error, fill operation wrote too far (lengths = %u): got (%x), not (%x)\n",
894e00fcb0fSKevin Laatz 						lengths[i], dst_data[j], 0);
895e00fcb0fSKevin Laatz 	}
896e00fcb0fSKevin Laatz 
897e00fcb0fSKevin Laatz 	rte_pktmbuf_free(dst);
898e00fcb0fSKevin Laatz 	return 0;
89999d7ec4bSBruce Richardson }
90099d7ec4bSBruce Richardson 
9018febcbe1SBruce Richardson static int
test_burst_capacity(int16_t dev_id,uint16_t vchan)9028fa5d268SKevin Laatz test_burst_capacity(int16_t dev_id, uint16_t vchan)
9038fa5d268SKevin Laatz {
9048fa5d268SKevin Laatz #define CAP_TEST_BURST_SIZE	64
9058fa5d268SKevin Laatz 	const int ring_space = rte_dma_burst_capacity(dev_id, vchan);
9068fa5d268SKevin Laatz 	struct rte_mbuf *src, *dst;
9078fa5d268SKevin Laatz 	int i, j, iter;
9088fa5d268SKevin Laatz 	int cap, ret;
9098fa5d268SKevin Laatz 	bool dma_err;
9108fa5d268SKevin Laatz 
9118fa5d268SKevin Laatz 	src = rte_pktmbuf_alloc(pool);
9128fa5d268SKevin Laatz 	dst = rte_pktmbuf_alloc(pool);
9138fa5d268SKevin Laatz 
9148fa5d268SKevin Laatz 	/* to test capacity, we enqueue elements and check capacity is reduced
9158fa5d268SKevin Laatz 	 * by one each time - rebaselining the expected value after each burst
9168fa5d268SKevin Laatz 	 * as the capacity is only for a burst. We enqueue multiple bursts to
91798a54d0aSBruce Richardson 	 * fill up half the ring, before emptying it again. We do this multiple
91898a54d0aSBruce Richardson 	 * times to ensure that we get to test scenarios where we get ring
91998a54d0aSBruce Richardson 	 * wrap-around and wrap-around of the ids returned (at UINT16_MAX).
9208fa5d268SKevin Laatz 	 */
92198a54d0aSBruce Richardson 	for (iter = 0; iter < 2 * (((int)UINT16_MAX + 1) / ring_space); iter++) {
9228fa5d268SKevin Laatz 		for (i = 0; i < (ring_space / (2 * CAP_TEST_BURST_SIZE)) + 1; i++) {
9238fa5d268SKevin Laatz 			cap = rte_dma_burst_capacity(dev_id, vchan);
9248fa5d268SKevin Laatz 
9258fa5d268SKevin Laatz 			for (j = 0; j < CAP_TEST_BURST_SIZE; j++) {
9268fa5d268SKevin Laatz 				ret = rte_dma_copy(dev_id, vchan, rte_pktmbuf_iova(src),
9278fa5d268SKevin Laatz 						rte_pktmbuf_iova(dst), COPY_LEN, 0);
9288fa5d268SKevin Laatz 				if (ret < 0)
9298fa5d268SKevin Laatz 					ERR_RETURN("Error with rte_dmadev_copy\n");
9308fa5d268SKevin Laatz 
9318fa5d268SKevin Laatz 				if (rte_dma_burst_capacity(dev_id, vchan) != cap - (j + 1))
9328fa5d268SKevin Laatz 					ERR_RETURN("Error, ring capacity did not change as expected\n");
9338fa5d268SKevin Laatz 			}
9348fa5d268SKevin Laatz 			if (rte_dma_submit(dev_id, vchan) < 0)
9358fa5d268SKevin Laatz 				ERR_RETURN("Error, failed to submit burst\n");
9368fa5d268SKevin Laatz 
9378fa5d268SKevin Laatz 			if (cap < rte_dma_burst_capacity(dev_id, vchan))
9388fa5d268SKevin Laatz 				ERR_RETURN("Error, avail ring capacity has gone up, not down\n");
9398fa5d268SKevin Laatz 		}
9408fa5d268SKevin Laatz 		await_hw(dev_id, vchan);
9418fa5d268SKevin Laatz 
9428fa5d268SKevin Laatz 		for (i = 0; i < (ring_space / (2 * CAP_TEST_BURST_SIZE)) + 1; i++) {
9438fa5d268SKevin Laatz 			ret = rte_dma_completed(dev_id, vchan,
9448fa5d268SKevin Laatz 					CAP_TEST_BURST_SIZE, NULL, &dma_err);
9458fa5d268SKevin Laatz 			if (ret != CAP_TEST_BURST_SIZE || dma_err) {
9468fa5d268SKevin Laatz 				enum rte_dma_status_code status;
9478fa5d268SKevin Laatz 
9488fa5d268SKevin Laatz 				rte_dma_completed_status(dev_id, vchan, 1, NULL, &status);
9498fa5d268SKevin Laatz 				ERR_RETURN("Error with rte_dmadev_completed, %u [expected: %u], dma_err = %d, i = %u, iter = %u, status = %u\n",
9508fa5d268SKevin Laatz 						ret, CAP_TEST_BURST_SIZE, dma_err, i, iter, status);
9518fa5d268SKevin Laatz 			}
9528fa5d268SKevin Laatz 		}
9538fa5d268SKevin Laatz 		cap = rte_dma_burst_capacity(dev_id, vchan);
9548fa5d268SKevin Laatz 		if (cap != ring_space)
9558fa5d268SKevin Laatz 			ERR_RETURN("Error, ring capacity has not reset to original value, got %u, expected %u\n",
9568fa5d268SKevin Laatz 					cap, ring_space);
9578fa5d268SKevin Laatz 	}
9588fa5d268SKevin Laatz 
9598fa5d268SKevin Laatz 	rte_pktmbuf_free(src);
9608fa5d268SKevin Laatz 	rte_pktmbuf_free(dst);
9618fa5d268SKevin Laatz 
9628fa5d268SKevin Laatz 	return 0;
9638fa5d268SKevin Laatz }
9648fa5d268SKevin Laatz 
9658fa5d268SKevin Laatz static int
test_m2d_auto_free(int16_t dev_id,uint16_t vchan)966877cb3e3SAmit Prakash Shukla test_m2d_auto_free(int16_t dev_id, uint16_t vchan)
967877cb3e3SAmit Prakash Shukla {
968877cb3e3SAmit Prakash Shukla #define NR_MBUF 256
9694dc8a18fSAmit Prakash Shukla 	struct rte_mempool_cache *cache;
9704dc8a18fSAmit Prakash Shukla 	struct rte_mbuf *src[NR_MBUF];
971877cb3e3SAmit Prakash Shukla 	uint32_t buf_cnt1, buf_cnt2;
972877cb3e3SAmit Prakash Shukla 	struct rte_mempool_ops *ops;
973877cb3e3SAmit Prakash Shukla 	uint16_t nb_done = 0;
974877cb3e3SAmit Prakash Shukla 	bool dma_err = false;
975877cb3e3SAmit Prakash Shukla 	int retry = 100;
976877cb3e3SAmit Prakash Shukla 	int i, ret = 0;
9774dc8a18fSAmit Prakash Shukla 	rte_iova_t dst;
978877cb3e3SAmit Prakash Shukla 
9794dc8a18fSAmit Prakash Shukla 	dst = (rte_iova_t)env_test_param[TEST_PARAM_REMOTE_ADDR];
980877cb3e3SAmit Prakash Shukla 
981877cb3e3SAmit Prakash Shukla 	/* Capture buffer count before allocating source buffer. */
9824dc8a18fSAmit Prakash Shukla 	cache = rte_mempool_default_cache(pool, rte_lcore_id());
983877cb3e3SAmit Prakash Shukla 	ops = rte_mempool_get_ops(pool->ops_index);
9844dc8a18fSAmit Prakash Shukla 	buf_cnt1 = ops->get_count(pool) + cache->len;
985877cb3e3SAmit Prakash Shukla 
9864dc8a18fSAmit Prakash Shukla 	if (rte_pktmbuf_alloc_bulk(pool, src, NR_MBUF) != 0)
9874dc8a18fSAmit Prakash Shukla 		ERR_RETURN("alloc src mbufs failed.\n");
988877cb3e3SAmit Prakash Shukla 
9894dc8a18fSAmit Prakash Shukla 	if ((buf_cnt1 - NR_MBUF) != (ops->get_count(pool) + cache->len)) {
990877cb3e3SAmit Prakash Shukla 		printf("Buffer count check failed.\n");
991877cb3e3SAmit Prakash Shukla 		ret = -1;
992877cb3e3SAmit Prakash Shukla 		goto done;
993877cb3e3SAmit Prakash Shukla 	}
994877cb3e3SAmit Prakash Shukla 
995877cb3e3SAmit Prakash Shukla 	for (i = 0; i < NR_MBUF; i++) {
9964dc8a18fSAmit Prakash Shukla 		ret = rte_dma_copy(dev_id, vchan, rte_mbuf_data_iova(src[i]), dst,
9974dc8a18fSAmit Prakash Shukla 				   COPY_LEN, RTE_DMA_OP_FLAG_AUTO_FREE);
998877cb3e3SAmit Prakash Shukla 
999877cb3e3SAmit Prakash Shukla 		if (ret < 0) {
1000877cb3e3SAmit Prakash Shukla 			printf("rte_dma_copy returned error.\n");
1001877cb3e3SAmit Prakash Shukla 			goto done;
1002877cb3e3SAmit Prakash Shukla 		}
1003877cb3e3SAmit Prakash Shukla 	}
1004877cb3e3SAmit Prakash Shukla 
1005877cb3e3SAmit Prakash Shukla 	rte_dma_submit(dev_id, vchan);
1006877cb3e3SAmit Prakash Shukla 	do {
1007877cb3e3SAmit Prakash Shukla 		nb_done += rte_dma_completed(dev_id, vchan, (NR_MBUF - nb_done), NULL, &dma_err);
1008877cb3e3SAmit Prakash Shukla 		if (dma_err)
1009877cb3e3SAmit Prakash Shukla 			break;
1010877cb3e3SAmit Prakash Shukla 		/* Sleep for 1 millisecond */
1011877cb3e3SAmit Prakash Shukla 		rte_delay_us_sleep(1000);
1012877cb3e3SAmit Prakash Shukla 	} while (retry-- && (nb_done < NR_MBUF));
1013877cb3e3SAmit Prakash Shukla 
10144dc8a18fSAmit Prakash Shukla 	buf_cnt2 = ops->get_count(pool) + cache->len;
1015877cb3e3SAmit Prakash Shukla 	if ((buf_cnt1 != buf_cnt2) || dma_err) {
1016877cb3e3SAmit Prakash Shukla 		printf("Free mem to dev buffer test failed.\n");
1017877cb3e3SAmit Prakash Shukla 		ret = -1;
1018877cb3e3SAmit Prakash Shukla 	}
1019877cb3e3SAmit Prakash Shukla 
1020877cb3e3SAmit Prakash Shukla done:
1021877cb3e3SAmit Prakash Shukla 	/* If the test passes source buffer will be freed in hardware. */
1022877cb3e3SAmit Prakash Shukla 	if (ret < 0)
1023877cb3e3SAmit Prakash Shukla 		rte_pktmbuf_free_bulk(&src[nb_done], (NR_MBUF - nb_done));
1024877cb3e3SAmit Prakash Shukla 
1025877cb3e3SAmit Prakash Shukla 	return ret;
1026877cb3e3SAmit Prakash Shukla }
1027877cb3e3SAmit Prakash Shukla 
1028877cb3e3SAmit Prakash Shukla static int
prepare_m2d_auto_free(int16_t dev_id,uint16_t vchan)10294dc8a18fSAmit Prakash Shukla prepare_m2d_auto_free(int16_t dev_id, uint16_t vchan)
10304dc8a18fSAmit Prakash Shukla {
10314dc8a18fSAmit Prakash Shukla 	const struct rte_dma_vchan_conf qconf = {
10324dc8a18fSAmit Prakash Shukla 		.direction = RTE_DMA_DIR_MEM_TO_DEV,
10334dc8a18fSAmit Prakash Shukla 		.nb_desc = TEST_RINGSIZE,
10344dc8a18fSAmit Prakash Shukla 		.auto_free.m2d.pool = pool,
10354dc8a18fSAmit Prakash Shukla 		.dst_port.port_type = RTE_DMA_PORT_PCIE,
10364dc8a18fSAmit Prakash Shukla 		.dst_port.pcie.coreid = 0,
10374dc8a18fSAmit Prakash Shukla 	};
10384dc8a18fSAmit Prakash Shukla 
10394dc8a18fSAmit Prakash Shukla 	/* Stop the device to reconfigure vchan. */
10404dc8a18fSAmit Prakash Shukla 	if (rte_dma_stop(dev_id) < 0)
10414dc8a18fSAmit Prakash Shukla 		ERR_RETURN("Error stopping device %u\n", dev_id);
10424dc8a18fSAmit Prakash Shukla 
10434dc8a18fSAmit Prakash Shukla 	if (rte_dma_vchan_setup(dev_id, vchan, &qconf) < 0)
10444dc8a18fSAmit Prakash Shukla 		ERR_RETURN("Error with queue configuration\n");
10454dc8a18fSAmit Prakash Shukla 
10464dc8a18fSAmit Prakash Shukla 	if (rte_dma_start(dev_id) != 0)
10474dc8a18fSAmit Prakash Shukla 		ERR_RETURN("Error with rte_dma_start()\n");
10484dc8a18fSAmit Prakash Shukla 
10494dc8a18fSAmit Prakash Shukla 	return 0;
10504dc8a18fSAmit Prakash Shukla }
10514dc8a18fSAmit Prakash Shukla 
10524dc8a18fSAmit Prakash Shukla static int
test_dmadev_sg_copy_setup(void)1053*2aba4f16SGowrishankar Muthukrishnan test_dmadev_sg_copy_setup(void)
1054*2aba4f16SGowrishankar Muthukrishnan {
1055*2aba4f16SGowrishankar Muthukrishnan 	int ret = TEST_SUCCESS;
1056*2aba4f16SGowrishankar Muthukrishnan 
1057*2aba4f16SGowrishankar Muthukrishnan 	if ((info.dev_capa & RTE_DMA_CAPA_OPS_COPY_SG) == 0)
1058*2aba4f16SGowrishankar Muthukrishnan 		return TEST_SKIPPED;
1059*2aba4f16SGowrishankar Muthukrishnan 
1060*2aba4f16SGowrishankar Muthukrishnan 	return ret;
1061*2aba4f16SGowrishankar Muthukrishnan }
1062*2aba4f16SGowrishankar Muthukrishnan 
1063*2aba4f16SGowrishankar Muthukrishnan static int
test_dmadev_burst_setup(void)106414b477edSGowrishankar Muthukrishnan test_dmadev_burst_setup(void)
1065718f7804SBruce Richardson {
106614b477edSGowrishankar Muthukrishnan 	if (rte_dma_burst_capacity(test_dev_id, vchan) < 64) {
106714b477edSGowrishankar Muthukrishnan 		RTE_LOG(ERR, USER1,
106814b477edSGowrishankar Muthukrishnan 			"DMA Dev %u: insufficient burst capacity (64 required), skipping tests\n",
106914b477edSGowrishankar Muthukrishnan 			test_dev_id);
107014b477edSGowrishankar Muthukrishnan 		return TEST_SKIPPED;
107114b477edSGowrishankar Muthukrishnan 	}
107214b477edSGowrishankar Muthukrishnan 
107314b477edSGowrishankar Muthukrishnan 	return TEST_SUCCESS;
107414b477edSGowrishankar Muthukrishnan }
107514b477edSGowrishankar Muthukrishnan 
107614b477edSGowrishankar Muthukrishnan static int
test_dmadev_err_handling_setup(void)107714b477edSGowrishankar Muthukrishnan test_dmadev_err_handling_setup(void)
107814b477edSGowrishankar Muthukrishnan {
107914b477edSGowrishankar Muthukrishnan 	int ret = TEST_SKIPPED;
108014b477edSGowrishankar Muthukrishnan 
108114b477edSGowrishankar Muthukrishnan 	/* to test error handling we can provide null pointers for source or dest in copies. This
108214b477edSGowrishankar Muthukrishnan 	 * requires VA mode in DPDK, since NULL(0) is a valid physical address.
108314b477edSGowrishankar Muthukrishnan 	 * We also need hardware that can report errors back.
108414b477edSGowrishankar Muthukrishnan 	 */
108514b477edSGowrishankar Muthukrishnan 	if (rte_eal_iova_mode() != RTE_IOVA_VA)
108614b477edSGowrishankar Muthukrishnan 		RTE_LOG(ERR, USER1,
108714b477edSGowrishankar Muthukrishnan 			"DMA Dev %u: DPDK not in VA mode, skipping error handling tests\n",
108814b477edSGowrishankar Muthukrishnan 			test_dev_id);
108914b477edSGowrishankar Muthukrishnan 	else if ((info.dev_capa & RTE_DMA_CAPA_HANDLES_ERRORS) == 0)
109014b477edSGowrishankar Muthukrishnan 		RTE_LOG(ERR, USER1,
109114b477edSGowrishankar Muthukrishnan 			"DMA Dev %u: device does not report errors, skipping error handling tests\n",
109214b477edSGowrishankar Muthukrishnan 			test_dev_id);
109314b477edSGowrishankar Muthukrishnan 	else
109414b477edSGowrishankar Muthukrishnan 		ret = TEST_SUCCESS;
109514b477edSGowrishankar Muthukrishnan 
109614b477edSGowrishankar Muthukrishnan 	return ret;
109714b477edSGowrishankar Muthukrishnan }
109814b477edSGowrishankar Muthukrishnan 
109914b477edSGowrishankar Muthukrishnan static int
test_dmadev_fill_setup(void)110014b477edSGowrishankar Muthukrishnan test_dmadev_fill_setup(void)
110114b477edSGowrishankar Muthukrishnan {
110214b477edSGowrishankar Muthukrishnan 	int ret = TEST_SUCCESS;
110314b477edSGowrishankar Muthukrishnan 
110414b477edSGowrishankar Muthukrishnan 	if ((info.dev_capa & RTE_DMA_CAPA_OPS_FILL) == 0) {
110514b477edSGowrishankar Muthukrishnan 		RTE_LOG(ERR, USER1,
110614b477edSGowrishankar Muthukrishnan 			"DMA Dev %u: No device fill support, skipping fill tests\n", test_dev_id);
110714b477edSGowrishankar Muthukrishnan 		ret = TEST_SKIPPED;
110814b477edSGowrishankar Muthukrishnan 	}
110914b477edSGowrishankar Muthukrishnan 
111014b477edSGowrishankar Muthukrishnan 	return ret;
111114b477edSGowrishankar Muthukrishnan }
111214b477edSGowrishankar Muthukrishnan 
111314b477edSGowrishankar Muthukrishnan static int
test_dmadev_autofree_setup(void)111414b477edSGowrishankar Muthukrishnan test_dmadev_autofree_setup(void)
111514b477edSGowrishankar Muthukrishnan {
111614b477edSGowrishankar Muthukrishnan 	int ret = TEST_SKIPPED;
111714b477edSGowrishankar Muthukrishnan 
111814b477edSGowrishankar Muthukrishnan 	if ((info.dev_capa & RTE_DMA_CAPA_M2D_AUTO_FREE) &&
111914b477edSGowrishankar Muthukrishnan 	    dma_add_test[TEST_M2D_AUTO_FREE].enabled == true) {
112014b477edSGowrishankar Muthukrishnan 		if (prepare_m2d_auto_free(test_dev_id, vchan) != 0)
112114b477edSGowrishankar Muthukrishnan 			return ret;
112214b477edSGowrishankar Muthukrishnan 
112314b477edSGowrishankar Muthukrishnan 		ret = TEST_SUCCESS;
112414b477edSGowrishankar Muthukrishnan 	}
112514b477edSGowrishankar Muthukrishnan 
112614b477edSGowrishankar Muthukrishnan 	return ret;
112714b477edSGowrishankar Muthukrishnan }
112814b477edSGowrishankar Muthukrishnan 
112914b477edSGowrishankar Muthukrishnan static int
test_dmadev_setup(void)113014b477edSGowrishankar Muthukrishnan test_dmadev_setup(void)
113114b477edSGowrishankar Muthukrishnan {
113214b477edSGowrishankar Muthukrishnan 	int16_t dev_id = test_dev_id;
1133718f7804SBruce Richardson 	struct rte_dma_stats stats;
1134718f7804SBruce Richardson 	const struct rte_dma_conf conf = { .nb_vchans = 1};
1135718f7804SBruce Richardson 	const struct rte_dma_vchan_conf qconf = {
1136718f7804SBruce Richardson 			.direction = RTE_DMA_DIR_MEM_TO_MEM,
1137718f7804SBruce Richardson 			.nb_desc = TEST_RINGSIZE,
1138718f7804SBruce Richardson 	};
1139b916b1a9SChengwen Feng 	int ret;
1140718f7804SBruce Richardson 
1141b916b1a9SChengwen Feng 	ret = rte_dma_info_get(dev_id, &info);
1142b916b1a9SChengwen Feng 	if (ret != 0)
1143b916b1a9SChengwen Feng 		ERR_RETURN("Error with rte_dma_info_get()\n");
1144c61c8282SDavid Marchand 
1145718f7804SBruce Richardson 	if (info.max_vchans < 1)
1146718f7804SBruce Richardson 		ERR_RETURN("Error, no channels available on device id %u\n", dev_id);
1147718f7804SBruce Richardson 
1148718f7804SBruce Richardson 	if (rte_dma_configure(dev_id, &conf) != 0)
1149718f7804SBruce Richardson 		ERR_RETURN("Error with rte_dma_configure()\n");
1150718f7804SBruce Richardson 
1151718f7804SBruce Richardson 	if (rte_dma_vchan_setup(dev_id, vchan, &qconf) < 0)
1152718f7804SBruce Richardson 		ERR_RETURN("Error with queue configuration\n");
1153718f7804SBruce Richardson 
1154b916b1a9SChengwen Feng 	ret = rte_dma_info_get(dev_id, &info);
1155b916b1a9SChengwen Feng 	if (ret != 0 || info.nb_vchans != 1)
1156718f7804SBruce Richardson 		ERR_RETURN("Error, no configured queues reported on device id %u\n", dev_id);
1157718f7804SBruce Richardson 
1158718f7804SBruce Richardson 	if (rte_dma_start(dev_id) != 0)
1159718f7804SBruce Richardson 		ERR_RETURN("Error with rte_dma_start()\n");
1160718f7804SBruce Richardson 
1161718f7804SBruce Richardson 	if (rte_dma_stats_get(dev_id, vchan, &stats) != 0)
1162718f7804SBruce Richardson 		ERR_RETURN("Error with rte_dma_stats_get()\n");
1163718f7804SBruce Richardson 
1164727e6b78SBruce Richardson 	if (rte_dma_burst_capacity(dev_id, vchan) < 32)
1165727e6b78SBruce Richardson 		ERR_RETURN("Error: Device does not have sufficient burst capacity to run tests");
1166727e6b78SBruce Richardson 
1167718f7804SBruce Richardson 	if (stats.completed != 0 || stats.submitted != 0 || stats.errors != 0)
1168718f7804SBruce Richardson 		ERR_RETURN("Error device stats are not all zero: completed = %"PRIu64", "
1169718f7804SBruce Richardson 				"submitted = %"PRIu64", errors = %"PRIu64"\n",
1170718f7804SBruce Richardson 				stats.completed, stats.submitted, stats.errors);
11718febcbe1SBruce Richardson 	id_count = 0;
1172718f7804SBruce Richardson 
11738febcbe1SBruce Richardson 	/* create a mempool for running tests */
11748febcbe1SBruce Richardson 	pool = rte_pktmbuf_pool_create("TEST_DMADEV_POOL",
11758febcbe1SBruce Richardson 			TEST_RINGSIZE * 2, /* n == num elements */
11768febcbe1SBruce Richardson 			32,  /* cache size */
11778febcbe1SBruce Richardson 			0,   /* priv size */
1178*2aba4f16SGowrishankar Muthukrishnan 			COPY_LEN + RTE_PKTMBUF_HEADROOM, /* data room size */
11798febcbe1SBruce Richardson 			info.numa_node);
11808febcbe1SBruce Richardson 	if (pool == NULL)
11818febcbe1SBruce Richardson 		ERR_RETURN("Error with mempool creation\n");
11828febcbe1SBruce Richardson 
118314b477edSGowrishankar Muthukrishnan 	check_err_stats = false;
118414b477edSGowrishankar Muthukrishnan 	vchan = 0;
11858febcbe1SBruce Richardson 
118614b477edSGowrishankar Muthukrishnan 	return 0;
1187877cb3e3SAmit Prakash Shukla }
1188877cb3e3SAmit Prakash Shukla 
118914b477edSGowrishankar Muthukrishnan static void
test_dmadev_teardown(void)119014b477edSGowrishankar Muthukrishnan test_dmadev_teardown(void)
119114b477edSGowrishankar Muthukrishnan {
11928febcbe1SBruce Richardson 	rte_mempool_free(pool);
119314b477edSGowrishankar Muthukrishnan 	rte_dma_stop(test_dev_id);
119414b477edSGowrishankar Muthukrishnan 	rte_dma_stats_reset(test_dev_id, vchan);
119514b477edSGowrishankar Muthukrishnan 	test_dev_id = -EINVAL;
1196718f7804SBruce Richardson }
1197718f7804SBruce Richardson 
11989942ebb9SChengwen Feng static int
test_dmadev_instance(int16_t dev_id)119914b477edSGowrishankar Muthukrishnan test_dmadev_instance(int16_t dev_id)
12009942ebb9SChengwen Feng {
120114b477edSGowrishankar Muthukrishnan 	struct rte_dma_info dev_info;
120214b477edSGowrishankar Muthukrishnan 	enum {
120314b477edSGowrishankar Muthukrishnan 		  TEST_COPY = 0,
1204*2aba4f16SGowrishankar Muthukrishnan 		  TEST_COPY_SG,
120514b477edSGowrishankar Muthukrishnan 		  TEST_START,
120614b477edSGowrishankar Muthukrishnan 		  TEST_BURST,
120714b477edSGowrishankar Muthukrishnan 		  TEST_ERR,
120814b477edSGowrishankar Muthukrishnan 		  TEST_FILL,
120914b477edSGowrishankar Muthukrishnan 		  TEST_M2D,
121014b477edSGowrishankar Muthukrishnan 		  TEST_END
121114b477edSGowrishankar Muthukrishnan 	};
121214b477edSGowrishankar Muthukrishnan 
121314b477edSGowrishankar Muthukrishnan 	static struct runtest_param param[] = {
121414b477edSGowrishankar Muthukrishnan 		{"copy", test_enqueue_copies, 640},
1215*2aba4f16SGowrishankar Muthukrishnan 		{"sg_copy", test_enqueue_sg_copies, 1},
121614b477edSGowrishankar Muthukrishnan 		{"stop_start", test_stop_start, 1},
121714b477edSGowrishankar Muthukrishnan 		{"burst_capacity", test_burst_capacity, 1},
121814b477edSGowrishankar Muthukrishnan 		{"error_handling", test_completion_handling, 1},
121914b477edSGowrishankar Muthukrishnan 		{"fill", test_enqueue_fill, 1},
122014b477edSGowrishankar Muthukrishnan 		{"m2d_auto_free", test_m2d_auto_free, 128},
122114b477edSGowrishankar Muthukrishnan 	};
122214b477edSGowrishankar Muthukrishnan 
122314b477edSGowrishankar Muthukrishnan 	static struct unit_test_suite ts = {
122414b477edSGowrishankar Muthukrishnan 		.suite_name = "DMA dev instance testsuite",
122514b477edSGowrishankar Muthukrishnan 		.setup = test_dmadev_setup,
122614b477edSGowrishankar Muthukrishnan 		.teardown = test_dmadev_teardown,
122714b477edSGowrishankar Muthukrishnan 		.unit_test_cases = {
122814b477edSGowrishankar Muthukrishnan 			TEST_CASE_NAMED_WITH_DATA("copy",
122914b477edSGowrishankar Muthukrishnan 				NULL, NULL,
123014b477edSGowrishankar Muthukrishnan 				runtest, &param[TEST_COPY]),
1231*2aba4f16SGowrishankar Muthukrishnan 			TEST_CASE_NAMED_WITH_DATA("sg_copy",
1232*2aba4f16SGowrishankar Muthukrishnan 				test_dmadev_sg_copy_setup, NULL,
1233*2aba4f16SGowrishankar Muthukrishnan 				runtest, &param[TEST_COPY_SG]),
123414b477edSGowrishankar Muthukrishnan 			TEST_CASE_NAMED_WITH_DATA("stop_start",
123514b477edSGowrishankar Muthukrishnan 				NULL, NULL,
123614b477edSGowrishankar Muthukrishnan 				runtest, &param[TEST_START]),
123714b477edSGowrishankar Muthukrishnan 			TEST_CASE_NAMED_WITH_DATA("burst_capacity",
123814b477edSGowrishankar Muthukrishnan 				test_dmadev_burst_setup, NULL,
123914b477edSGowrishankar Muthukrishnan 				runtest, &param[TEST_BURST]),
124014b477edSGowrishankar Muthukrishnan 			TEST_CASE_NAMED_WITH_DATA("error_handling",
124114b477edSGowrishankar Muthukrishnan 				test_dmadev_err_handling_setup, NULL,
124214b477edSGowrishankar Muthukrishnan 				runtest, &param[TEST_ERR]),
124314b477edSGowrishankar Muthukrishnan 			TEST_CASE_NAMED_WITH_DATA("fill",
124414b477edSGowrishankar Muthukrishnan 				test_dmadev_fill_setup, NULL,
124514b477edSGowrishankar Muthukrishnan 				runtest, &param[TEST_FILL]),
124614b477edSGowrishankar Muthukrishnan 			TEST_CASE_NAMED_WITH_DATA("m2d_autofree",
124714b477edSGowrishankar Muthukrishnan 				test_dmadev_autofree_setup, NULL,
124814b477edSGowrishankar Muthukrishnan 				runtest, &param[TEST_M2D]),
124914b477edSGowrishankar Muthukrishnan 			TEST_CASES_END()
125014b477edSGowrishankar Muthukrishnan 		}
125114b477edSGowrishankar Muthukrishnan 	};
125214b477edSGowrishankar Muthukrishnan 
12539942ebb9SChengwen Feng 	int ret;
12549942ebb9SChengwen Feng 
125514b477edSGowrishankar Muthukrishnan 	if (rte_dma_info_get(dev_id, &dev_info) < 0)
12569942ebb9SChengwen Feng 		return TEST_SKIPPED;
125714b477edSGowrishankar Muthukrishnan 
125814b477edSGowrishankar Muthukrishnan 	test_dev_id = dev_id;
125914b477edSGowrishankar Muthukrishnan 	printf("\n### Test dmadev instance %u [%s]\n",
126014b477edSGowrishankar Muthukrishnan 		   test_dev_id, dev_info.dev_name);
126114b477edSGowrishankar Muthukrishnan 
126214b477edSGowrishankar Muthukrishnan 	ret = unit_test_suite_runner(&ts);
126314b477edSGowrishankar Muthukrishnan 	test_dev_id = -EINVAL;
12649942ebb9SChengwen Feng 
12659942ebb9SChengwen Feng 	return ret;
12669942ebb9SChengwen Feng }
12679942ebb9SChengwen Feng 
1268877cb3e3SAmit Prakash Shukla static void
parse_dma_env_var(void)1269877cb3e3SAmit Prakash Shukla parse_dma_env_var(void)
1270877cb3e3SAmit Prakash Shukla {
1271877cb3e3SAmit Prakash Shukla 	char *dma_env_param_str = getenv("DPDK_ADD_DMA_TEST_PARAM");
1272877cb3e3SAmit Prakash Shukla 	char *dma_env_test_str = getenv("DPDK_ADD_DMA_TEST");
1273877cb3e3SAmit Prakash Shukla 	char *params[32] = {0};
1274877cb3e3SAmit Prakash Shukla 	char *tests[32] = {0};
1275877cb3e3SAmit Prakash Shukla 	char *var[2] = {0};
1276877cb3e3SAmit Prakash Shukla 	int n_var = 0;
1277877cb3e3SAmit Prakash Shukla 	int i, j;
1278877cb3e3SAmit Prakash Shukla 
1279877cb3e3SAmit Prakash Shukla 	/* Additional test from commandline. */
1280877cb3e3SAmit Prakash Shukla 	if (dma_env_test_str && strlen(dma_env_test_str) > 0) {
1281877cb3e3SAmit Prakash Shukla 		n_var = rte_strsplit(dma_env_test_str, strlen(dma_env_test_str), tests,
1282877cb3e3SAmit Prakash Shukla 				RTE_DIM(tests), ',');
1283877cb3e3SAmit Prakash Shukla 		for (i = 0; i < n_var; i++) {
1284877cb3e3SAmit Prakash Shukla 			for (j = 0; j < TEST_MAX; j++) {
1285877cb3e3SAmit Prakash Shukla 				if (!strcmp(tests[i], dma_add_test[j].name))
1286877cb3e3SAmit Prakash Shukla 					dma_add_test[j].enabled = true;
1287877cb3e3SAmit Prakash Shukla 			}
1288877cb3e3SAmit Prakash Shukla 		}
1289877cb3e3SAmit Prakash Shukla 	}
1290877cb3e3SAmit Prakash Shukla 
1291877cb3e3SAmit Prakash Shukla 	/* Commandline variables for test */
1292877cb3e3SAmit Prakash Shukla 	if (dma_env_param_str && strlen(dma_env_param_str) > 0) {
1293877cb3e3SAmit Prakash Shukla 		n_var = rte_strsplit(dma_env_param_str, strlen(dma_env_param_str), params,
1294877cb3e3SAmit Prakash Shukla 				       RTE_DIM(params), ',');
1295877cb3e3SAmit Prakash Shukla 		for (i = 0; i < n_var; i++) {
1296877cb3e3SAmit Prakash Shukla 			rte_strsplit(params[i], strlen(params[i]), var,	RTE_DIM(var), '=');
1297877cb3e3SAmit Prakash Shukla 			for (j = 0; j < TEST_PARAM_MAX; j++) {
1298877cb3e3SAmit Prakash Shukla 				if (!strcmp(var[0], dma_test_param[j]))
1299877cb3e3SAmit Prakash Shukla 					env_test_param[j] = strtoul(var[1], NULL, 16);
1300877cb3e3SAmit Prakash Shukla 			}
1301877cb3e3SAmit Prakash Shukla 		}
1302877cb3e3SAmit Prakash Shukla 	}
1303877cb3e3SAmit Prakash Shukla }
1304877cb3e3SAmit Prakash Shukla 
13059942ebb9SChengwen Feng static int
test_dma(void)13069942ebb9SChengwen Feng test_dma(void)
13079942ebb9SChengwen Feng {
130814b477edSGowrishankar Muthukrishnan 	const char *pmd = "dma_skeleton";
1309718f7804SBruce Richardson 	int i;
1310718f7804SBruce Richardson 
1311877cb3e3SAmit Prakash Shukla 	parse_dma_env_var();
1312877cb3e3SAmit Prakash Shukla 
131314b477edSGowrishankar Muthukrishnan 	/* attempt to create skeleton instance - ignore errors due to one being already present*/
131414b477edSGowrishankar Muthukrishnan 	rte_vdev_init(pmd, NULL);
1315718f7804SBruce Richardson 
1316718f7804SBruce Richardson 	if (rte_dma_count_avail() == 0)
1317718f7804SBruce Richardson 		return TEST_SKIPPED;
1318718f7804SBruce Richardson 
131914b477edSGowrishankar Muthukrishnan 	RTE_DMA_FOREACH_DEV(i) {
132014b477edSGowrishankar Muthukrishnan 		if (test_dma_api(i) < 0)
132114b477edSGowrishankar Muthukrishnan 			ERR_RETURN("Error performing API tests\n");
132214b477edSGowrishankar Muthukrishnan 
1323718f7804SBruce Richardson 		if (test_dmadev_instance(i) < 0)
1324718f7804SBruce Richardson 			ERR_RETURN("Error, test failure for device %d\n", i);
132514b477edSGowrishankar Muthukrishnan 	}
13269942ebb9SChengwen Feng 
13279942ebb9SChengwen Feng 	return 0;
13289942ebb9SChengwen Feng }
13299942ebb9SChengwen Feng 
1330e0a8442cSBruce Richardson REGISTER_DRIVER_TEST(dmadev_autotest, test_dma);
1331