1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(c) 2021 HiSilicon Limited
3 * Copyright(c) 2021 Intel Corporation
8 #include <rte_dmadev.h>
10 #include <rte_pause.h>
11 #include <rte_cycles.h>
12 #include <rte_random.h>
13 #include <rte_bus_vdev.h>
14 #include <rte_dmadev_pmd.h>
17 #include "test_dmadev_api.h"
19 #define ERR_RETURN(...) do { print_err(__func__, __LINE__, __VA_ARGS__); return -1; } while (0)
23 static struct rte_mempool *pool;
24 static uint16_t id_count;
27 __rte_format_printf(3, 4)
28 print_err(const char *func, int lineno, const char *format, ...)
32 fprintf(stderr, "In %s:%d - ", func, lineno);
34 vfprintf(stderr, format, ap);
39 runtest(const char *printable, int (*test_fn)(int16_t dev_id, uint16_t vchan), int iterations,
40 int16_t dev_id, uint16_t vchan, bool check_err_stats)
42 struct rte_dma_stats stats;
45 rte_dma_stats_reset(dev_id, vchan);
46 printf("DMA Dev %d: Running %s Tests %s\n", dev_id, printable,
47 check_err_stats ? " " : "(errors expected)");
48 for (i = 0; i < iterations; i++) {
49 if (test_fn(dev_id, vchan) < 0)
52 rte_dma_stats_get(dev_id, 0, &stats);
53 printf("Ops submitted: %"PRIu64"\t", stats.submitted);
54 printf("Ops completed: %"PRIu64"\t", stats.completed);
55 printf("Errors: %"PRIu64"\r", stats.errors);
57 if (stats.completed != stats.submitted)
58 ERR_RETURN("\nError, not all submitted jobs are reported as completed\n");
59 if (check_err_stats && stats.errors != 0)
60 ERR_RETURN("\nErrors reported during op processing, aborting tests\n");
67 await_hw(int16_t dev_id, uint16_t vchan)
69 enum rte_dma_vchan_status st;
71 if (rte_dma_vchan_status(dev_id, vchan, &st) < 0) {
72 /* for drivers that don't support this op, just sleep for 1 millisecond */
73 rte_delay_us_sleep(1000);
77 /* for those that do, *max* end time is one second from now, but all should be faster */
78 const uint64_t end_cycles = rte_get_timer_cycles() + rte_get_timer_hz();
79 while (st == RTE_DMA_VCHAN_ACTIVE && rte_get_timer_cycles() < end_cycles) {
81 rte_dma_vchan_status(dev_id, vchan, &st);
86 test_enqueue_copies(int16_t dev_id, uint16_t vchan)
91 /* test doing a single copy */
93 struct rte_mbuf *src, *dst;
94 char *src_data, *dst_data;
96 src = rte_pktmbuf_alloc(pool);
97 dst = rte_pktmbuf_alloc(pool);
98 src_data = rte_pktmbuf_mtod(src, char *);
99 dst_data = rte_pktmbuf_mtod(dst, char *);
101 for (i = 0; i < COPY_LEN; i++)
102 src_data[i] = rte_rand() & 0xFF;
104 id = rte_dma_copy(dev_id, vchan, rte_pktmbuf_iova(src), rte_pktmbuf_iova(dst),
105 COPY_LEN, RTE_DMA_OP_FLAG_SUBMIT);
107 ERR_RETURN("Error with rte_dma_copy, got %u, expected %u\n",
110 /* give time for copy to finish, then check it was done */
111 await_hw(dev_id, vchan);
113 for (i = 0; i < COPY_LEN; i++)
114 if (dst_data[i] != src_data[i])
115 ERR_RETURN("Data mismatch at char %u [Got %02x not %02x]\n", i,
116 dst_data[i], src_data[i]);
118 /* now check completion works */
119 if (rte_dma_completed(dev_id, vchan, 1, &id, NULL) != 1)
120 ERR_RETURN("Error with rte_dma_completed\n");
123 ERR_RETURN("Error:incorrect job id received, %u [expected %u]\n",
126 rte_pktmbuf_free(src);
127 rte_pktmbuf_free(dst);
129 /* now check completion returns nothing more */
130 if (rte_dma_completed(dev_id, 0, 1, NULL, NULL) != 0)
131 ERR_RETURN("Error with rte_dma_completed in empty check\n");
137 /* test doing a multiple single copies */
139 const uint16_t max_ops = 4;
140 struct rte_mbuf *src, *dst;
141 char *src_data, *dst_data;
144 src = rte_pktmbuf_alloc(pool);
145 dst = rte_pktmbuf_alloc(pool);
146 src_data = rte_pktmbuf_mtod(src, char *);
147 dst_data = rte_pktmbuf_mtod(dst, char *);
149 for (i = 0; i < COPY_LEN; i++)
150 src_data[i] = rte_rand() & 0xFF;
152 /* perform the same copy <max_ops> times */
153 for (i = 0; i < max_ops; i++)
154 if (rte_dma_copy(dev_id, vchan,
155 rte_pktmbuf_iova(src),
156 rte_pktmbuf_iova(dst),
157 COPY_LEN, RTE_DMA_OP_FLAG_SUBMIT) != id_count++)
158 ERR_RETURN("Error with rte_dma_copy\n");
160 await_hw(dev_id, vchan);
162 count = rte_dma_completed(dev_id, vchan, max_ops * 2, &id, NULL);
163 if (count != max_ops)
164 ERR_RETURN("Error with rte_dma_completed, got %u not %u\n",
167 if (id != id_count - 1)
168 ERR_RETURN("Error, incorrect job id returned: got %u not %u\n",
171 for (i = 0; i < COPY_LEN; i++)
172 if (dst_data[i] != src_data[i])
173 ERR_RETURN("Data mismatch at char %u\n", i);
175 rte_pktmbuf_free(src);
176 rte_pktmbuf_free(dst);
183 test_dmadev_instance(int16_t dev_id)
185 #define TEST_RINGSIZE 512
186 #define CHECK_ERRS true
187 struct rte_dma_stats stats;
188 struct rte_dma_info info;
189 const struct rte_dma_conf conf = { .nb_vchans = 1};
190 const struct rte_dma_vchan_conf qconf = {
191 .direction = RTE_DMA_DIR_MEM_TO_MEM,
192 .nb_desc = TEST_RINGSIZE,
196 printf("\n### Test dmadev instance %u [%s]\n",
197 dev_id, rte_dma_devices[dev_id].data->dev_name);
199 rte_dma_info_get(dev_id, &info);
200 if (info.max_vchans < 1)
201 ERR_RETURN("Error, no channels available on device id %u\n", dev_id);
203 if (rte_dma_configure(dev_id, &conf) != 0)
204 ERR_RETURN("Error with rte_dma_configure()\n");
206 if (rte_dma_vchan_setup(dev_id, vchan, &qconf) < 0)
207 ERR_RETURN("Error with queue configuration\n");
209 rte_dma_info_get(dev_id, &info);
210 if (info.nb_vchans != 1)
211 ERR_RETURN("Error, no configured queues reported on device id %u\n", dev_id);
213 if (rte_dma_start(dev_id) != 0)
214 ERR_RETURN("Error with rte_dma_start()\n");
216 if (rte_dma_stats_get(dev_id, vchan, &stats) != 0)
217 ERR_RETURN("Error with rte_dma_stats_get()\n");
219 if (stats.completed != 0 || stats.submitted != 0 || stats.errors != 0)
220 ERR_RETURN("Error device stats are not all zero: completed = %"PRIu64", "
221 "submitted = %"PRIu64", errors = %"PRIu64"\n",
222 stats.completed, stats.submitted, stats.errors);
225 /* create a mempool for running tests */
226 pool = rte_pktmbuf_pool_create("TEST_DMADEV_POOL",
227 TEST_RINGSIZE * 2, /* n == num elements */
230 2048, /* data room size */
233 ERR_RETURN("Error with mempool creation\n");
235 /* run the test cases, use many iterations to ensure UINT16_MAX id wraparound */
236 if (runtest("copy", test_enqueue_copies, 640, dev_id, vchan, CHECK_ERRS) < 0)
239 rte_mempool_free(pool);
240 rte_dma_stop(dev_id);
241 rte_dma_stats_reset(dev_id, vchan);
245 rte_mempool_free(pool);
246 rte_dma_stop(dev_id);
253 const char *pmd = "dma_skeleton";
257 if (rte_vdev_init(pmd, NULL) < 0)
259 id = rte_dma_get_dev_id_by_name(pmd);
262 printf("\n### Test dmadev infrastructure using skeleton driver\n");
263 ret = test_dma_api(id);
264 rte_vdev_uninit(pmd);
274 /* basic sanity on dmadev infrastructure */
276 ERR_RETURN("Error performing API tests\n");
278 if (rte_dma_count_avail() == 0)
281 RTE_DMA_FOREACH_DEV(i)
282 if (test_dmadev_instance(i) < 0)
283 ERR_RETURN("Error, test failure for device %d\n", i);
288 REGISTER_TEST_COMMAND(dmadev_autotest, test_dma);