Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright(c) 2023 Intel Corporation
3 : : */
4 : :
5 : : #include <inttypes.h>
6 : : #include <stdio.h>
7 : : #include <stdlib.h>
8 : : #include <unistd.h>
9 : :
10 : : #include <rte_time.h>
11 : : #include <rte_mbuf.h>
12 : : #include <rte_dmadev.h>
13 : : #include <rte_malloc.h>
14 : : #include <rte_lcore.h>
15 : : #include <rte_random.h>
16 : :
17 : : #include "main.h"
18 : :
19 : : #define MAX_DMA_CPL_NB 255
20 : :
21 : : #define TEST_WAIT_U_SECOND 10000
22 : : #define POLL_MAX 1000
23 : :
24 : : #define CSV_LINE_DMA_FMT "Scenario %u,%u,%s,%u,%u,%u,%u,%.2lf,%" PRIu64 ",%.3lf,%.3lf\n"
25 : : #define CSV_LINE_CPU_FMT "Scenario %u,%u,NA,NA,NA,%u,%u,%.2lf,%" PRIu64 ",%.3lf,%.3lf\n"
26 : :
27 : : #define CSV_TOTAL_LINE_FMT "Scenario %u Summary, , , , , ,%u,%.2lf,%.1lf,%.3lf,%.3lf\n"
28 : :
29 : : struct worker_info {
30 : : bool ready_flag;
31 : : bool start_flag;
32 : : bool stop_flag;
33 : : uint32_t total_cpl;
34 : : uint32_t test_cpl;
35 : : };
36 : :
37 : : struct sge_info {
38 : : struct rte_dma_sge *srcs;
39 : : struct rte_dma_sge *dsts;
40 : : uint8_t nb_srcs;
41 : : uint8_t nb_dsts;
42 : : };
43 : :
44 : : struct lcore_params {
45 : : uint8_t scenario_id;
46 : : unsigned int lcore_id;
47 : : char *dma_name;
48 : : uint16_t worker_id;
49 : : uint16_t dev_id;
50 : : uint32_t nr_buf;
51 : : uint16_t kick_batch;
52 : : uint32_t buf_size;
53 : : uint16_t test_secs;
54 : : struct rte_mbuf **srcs;
55 : : struct rte_mbuf **dsts;
56 : : struct sge_info sge;
57 : : struct rte_dma_op **dma_ops;
58 : : volatile struct worker_info worker_info;
59 : : };
60 : :
61 : : static struct rte_mempool *src_pool;
62 : : static struct rte_mempool *dst_pool;
63 : :
64 : : static struct lcore_params *lcores[MAX_WORKER_NB];
65 : :
66 : : #define PRINT_ERR(...) print_err(__func__, __LINE__, __VA_ARGS__)
67 : :
68 : : static inline int
69 : : __rte_format_printf(3, 4)
70 : 0 : print_err(const char *func, int lineno, const char *format, ...)
71 : : {
72 : : va_list ap;
73 : : int ret;
74 : :
75 : 0 : ret = fprintf(stderr, "In %s:%d - ", func, lineno);
76 : 0 : va_start(ap, format);
77 : 0 : ret += vfprintf(stderr, format, ap);
78 : 0 : va_end(ap);
79 : :
80 : 0 : return ret;
81 : : }
82 : :
83 : : static inline void
84 : 0 : calc_result(uint32_t buf_size, uint32_t nr_buf, uint16_t nb_workers, uint16_t test_secs,
85 : : uint32_t total_cnt, float *memory, uint32_t *ave_cycle,
86 : : float *bandwidth, float *mops)
87 : : {
88 : : float ops;
89 : :
90 : 0 : *memory = (float)(buf_size * (nr_buf / nb_workers) * 2) / (1024 * 1024);
91 : 0 : *ave_cycle = test_secs * rte_get_timer_hz() / total_cnt;
92 : 0 : ops = (float)total_cnt / test_secs;
93 : 0 : *mops = ops / (1000 * 1000);
94 : 0 : *bandwidth = (ops * buf_size * 8) / (1000 * 1000 * 1000);
95 : 0 : }
96 : :
97 : : static void
98 : 0 : output_result(struct test_configure *cfg, struct lcore_params *para,
99 : : uint16_t kick_batch, uint64_t ave_cycle, uint32_t buf_size,
100 : : uint32_t nr_buf, float memory, float bandwidth, float mops)
101 : : {
102 : 0 : uint16_t ring_size = cfg->ring_size.cur;
103 : 0 : uint8_t scenario_id = cfg->scenario_id;
104 : 0 : uint32_t lcore_id = para->lcore_id;
105 : 0 : char *dma_name = para->dma_name;
106 : :
107 : 0 : if (cfg->is_dma) {
108 : 0 : printf("lcore %u, DMA %s, DMA Ring Size: %u, Kick Batch Size: %u", lcore_id,
109 : : dma_name, ring_size, kick_batch);
110 : 0 : if (cfg->is_sg)
111 : 0 : printf(" DMA src sges: %u, dst sges: %u",
112 : 0 : para->sge.nb_srcs, para->sge.nb_dsts);
113 : : printf(".\n");
114 : : } else {
115 : : printf("lcore %u\n", lcore_id);
116 : : }
117 : :
118 : 0 : printf("Average Cycles/op: %" PRIu64 ", Buffer Size: %u B, Buffer Number: %u, Memory: %.2lf MB, Frequency: %.3lf Ghz.\n",
119 : : ave_cycle, buf_size, nr_buf, memory, rte_get_timer_hz()/1000000000.0);
120 : 0 : printf("Average Bandwidth: %.3lf Gbps, MOps: %.3lf\n", bandwidth, mops);
121 : :
122 : 0 : if (cfg->is_dma)
123 : 0 : snprintf(output_str[lcore_id], MAX_OUTPUT_STR_LEN, CSV_LINE_DMA_FMT,
124 : : scenario_id, lcore_id, dma_name, ring_size, kick_batch, buf_size,
125 : : nr_buf, memory, ave_cycle, bandwidth, mops);
126 : : else
127 : 0 : snprintf(output_str[lcore_id], MAX_OUTPUT_STR_LEN, CSV_LINE_CPU_FMT,
128 : : scenario_id, lcore_id, buf_size,
129 : : nr_buf, memory, ave_cycle, bandwidth, mops);
130 : 0 : }
131 : :
132 : : static inline void
133 : : cache_flush_buf(__rte_unused struct rte_mbuf **array,
134 : : __rte_unused uint32_t buf_size,
135 : : __rte_unused uint32_t nr_buf)
136 : : {
137 : : #ifdef RTE_ARCH_X86_64
138 : : char *data;
139 : : struct rte_mbuf **srcs = array;
140 : : uint32_t i, offset;
141 : :
142 : 0 : for (i = 0; i < nr_buf; i++) {
143 : 0 : data = rte_pktmbuf_mtod(srcs[i], char *);
144 : 0 : for (offset = 0; offset < buf_size; offset += 64)
145 : 0 : __builtin_ia32_clflush(data + offset);
146 : : }
147 : : #endif
148 : : }
149 : :
150 : : static int
151 : 0 : vchan_data_populate(uint32_t dev_id, struct rte_dma_vchan_conf *qconf,
152 : : struct test_configure *cfg, uint16_t dev_num)
153 : : {
154 : : struct vchan_dev_config *vchan_dconfig;
155 : : struct rte_dma_info info;
156 : :
157 : 0 : vchan_dconfig = &cfg->dma_config[dev_num].vchan_dev;
158 : 0 : qconf->direction = vchan_dconfig->tdir;
159 : :
160 : 0 : rte_dma_info_get(dev_id, &info);
161 : 0 : if (!(RTE_BIT64(qconf->direction) & info.dev_capa))
162 : : return -1;
163 : :
164 : 0 : qconf->nb_desc = cfg->ring_size.cur;
165 : :
166 : 0 : switch (qconf->direction) {
167 : 0 : case RTE_DMA_DIR_MEM_TO_DEV:
168 : 0 : qconf->dst_port.pcie.vfen = 1;
169 : 0 : qconf->dst_port.port_type = RTE_DMA_PORT_PCIE;
170 : 0 : qconf->dst_port.pcie.coreid = vchan_dconfig->port.pcie.coreid;
171 : 0 : qconf->dst_port.pcie.vfid = vchan_dconfig->port.pcie.vfid;
172 : 0 : qconf->dst_port.pcie.pfid = vchan_dconfig->port.pcie.pfid;
173 : 0 : break;
174 : 0 : case RTE_DMA_DIR_DEV_TO_MEM:
175 : 0 : qconf->src_port.pcie.vfen = 1;
176 : 0 : qconf->src_port.port_type = RTE_DMA_PORT_PCIE;
177 : 0 : qconf->src_port.pcie.coreid = vchan_dconfig->port.pcie.coreid;
178 : 0 : qconf->src_port.pcie.vfid = vchan_dconfig->port.pcie.vfid;
179 : 0 : qconf->src_port.pcie.pfid = vchan_dconfig->port.pcie.pfid;
180 : 0 : break;
181 : : case RTE_DMA_DIR_MEM_TO_MEM:
182 : : case RTE_DMA_DIR_DEV_TO_DEV:
183 : : break;
184 : : }
185 : :
186 : : return 0;
187 : : }
188 : :
189 : : /* Configuration of device. */
190 : : static void
191 : 0 : configure_dmadev_queue(uint32_t dev_id, struct test_configure *cfg, uint8_t sges_max,
192 : : uint16_t dev_num)
193 : : {
194 : : uint16_t vchan = 0;
195 : : struct rte_dma_info info;
196 : 0 : struct rte_dma_conf dev_config = { .nb_vchans = 1 };
197 : 0 : struct rte_dma_vchan_conf qconf = { 0 };
198 : :
199 : 0 : if (vchan_data_populate(dev_id, &qconf, cfg, dev_num) != 0)
200 : 0 : rte_exit(EXIT_FAILURE, "Error with vchan data populate.\n");
201 : :
202 : 0 : if (rte_dma_info_get(dev_id, &info) != 0)
203 : 0 : rte_exit(EXIT_FAILURE, "Error with getting device info.\n");
204 : :
205 : 0 : if (cfg->use_ops && !(info.dev_capa & RTE_DMA_CAPA_OPS_ENQ_DEQ))
206 : 0 : rte_exit(EXIT_FAILURE, "Error with device %s not support enq_deq ops.\n",
207 : : info.dev_name);
208 : :
209 : 0 : if (cfg->use_ops)
210 : 0 : dev_config.flags = RTE_DMA_CFG_FLAG_ENQ_DEQ;
211 : :
212 : 0 : if (rte_dma_configure(dev_id, &dev_config) != 0)
213 : 0 : rte_exit(EXIT_FAILURE, "Error with dma configure.\n");
214 : :
215 : 0 : if (rte_dma_vchan_setup(dev_id, vchan, &qconf) != 0)
216 : 0 : rte_exit(EXIT_FAILURE, "Error with queue configuration.\n");
217 : :
218 : 0 : if (rte_dma_info_get(dev_id, &info) != 0)
219 : 0 : rte_exit(EXIT_FAILURE, "Error with getting device info.\n");
220 : :
221 : 0 : if (info.nb_vchans != 1)
222 : 0 : rte_exit(EXIT_FAILURE, "Error, no configured queues reported on device id. %u\n",
223 : : dev_id);
224 : :
225 : 0 : if (info.max_sges < sges_max)
226 : 0 : rte_exit(EXIT_FAILURE, "Error with unsupported max_sges on device id %u.\n",
227 : : dev_id);
228 : :
229 : 0 : if (rte_dma_start(dev_id) != 0)
230 : 0 : rte_exit(EXIT_FAILURE, "Error with dma start.\n");
231 : 0 : }
232 : :
233 : : static int
234 : 0 : config_dmadevs(struct test_configure *cfg)
235 : : {
236 : 0 : uint32_t nb_workers = cfg->num_worker;
237 : : struct lcore_dma_map_t *ldm;
238 : : uint32_t i;
239 : : int dev_id;
240 : : uint16_t nb_dmadevs = 0;
241 : : uint8_t nb_sges = 0;
242 : : char *dma_name;
243 : :
244 : 0 : if (cfg->is_sg)
245 : 0 : nb_sges = RTE_MAX(cfg->nb_src_sges, cfg->nb_dst_sges);
246 : :
247 : 0 : for (i = 0; i < nb_workers; i++) {
248 : : ldm = &cfg->dma_config[i].lcore_dma_map;
249 : 0 : dma_name = ldm->dma_names;
250 : 0 : dev_id = rte_dma_get_dev_id_by_name(dma_name);
251 : 0 : if (dev_id < 0) {
252 : 0 : fprintf(stderr, "Error: Fail to find DMA %s.\n", dma_name);
253 : 0 : goto end;
254 : : }
255 : :
256 : 0 : ldm->dma_id = dev_id;
257 : 0 : configure_dmadev_queue(dev_id, cfg, nb_sges, nb_dmadevs);
258 : 0 : ++nb_dmadevs;
259 : : }
260 : :
261 : 0 : end:
262 : 0 : if (nb_dmadevs < nb_workers) {
263 : 0 : printf("Not enough dmadevs (%u) for all workers (%u).\n", nb_dmadevs, nb_workers);
264 : 0 : return -1;
265 : : }
266 : :
267 : 0 : printf("Number of used dmadevs: %u.\n", nb_dmadevs);
268 : :
269 : 0 : return 0;
270 : : }
271 : :
272 : : static void
273 : 0 : error_exit(int dev_id)
274 : : {
275 : 0 : rte_dma_stop(dev_id);
276 : 0 : rte_dma_close(dev_id);
277 : 0 : rte_exit(EXIT_FAILURE, "DMA error\n");
278 : : }
279 : :
280 : : static inline void
281 : 0 : do_dma_submit_and_poll(uint16_t dev_id, uint64_t *async_cnt,
282 : : volatile struct worker_info *worker_info)
283 : : {
284 : : int ret;
285 : : uint16_t nr_cpl;
286 : :
287 : 0 : ret = rte_dma_submit(dev_id, 0);
288 : 0 : if (ret < 0)
289 : 0 : error_exit(dev_id);
290 : :
291 : : nr_cpl = rte_dma_completed(dev_id, 0, MAX_DMA_CPL_NB, NULL, NULL);
292 : 0 : *async_cnt -= nr_cpl;
293 : 0 : worker_info->total_cpl += nr_cpl;
294 : 0 : }
295 : :
296 : : static inline int
297 : 0 : do_dma_plain_mem_copy(void *p)
298 : : {
299 : : struct lcore_params *para = (struct lcore_params *)p;
300 : 0 : volatile struct worker_info *worker_info = &(para->worker_info);
301 : 0 : const uint16_t dev_id = para->dev_id;
302 : 0 : const uint32_t nr_buf = para->nr_buf;
303 : 0 : const uint16_t kick_batch = para->kick_batch;
304 : 0 : const uint32_t buf_size = para->buf_size;
305 : 0 : struct rte_mbuf **srcs = para->srcs;
306 : 0 : struct rte_mbuf **dsts = para->dsts;
307 : : uint16_t nr_cpl;
308 : 0 : uint64_t async_cnt = 0;
309 : : uint32_t i;
310 : : uint32_t poll_cnt = 0;
311 : : int ret;
312 : :
313 : 0 : worker_info->stop_flag = false;
314 : 0 : worker_info->ready_flag = true;
315 : :
316 : 0 : while (!worker_info->start_flag)
317 : : ;
318 : :
319 : : while (1) {
320 : 0 : for (i = 0; i < nr_buf; i++) {
321 : 0 : dma_copy:
322 : 0 : ret = rte_dma_copy(dev_id, 0, rte_mbuf_data_iova(srcs[i]),
323 : 0 : rte_mbuf_data_iova(dsts[i]), buf_size, 0);
324 : 0 : if (unlikely(ret < 0)) {
325 : 0 : if (ret == -ENOSPC) {
326 : 0 : do_dma_submit_and_poll(dev_id, &async_cnt, worker_info);
327 : 0 : goto dma_copy;
328 : : } else
329 : 0 : error_exit(dev_id);
330 : : }
331 : 0 : async_cnt++;
332 : :
333 : 0 : if ((async_cnt % kick_batch) == 0)
334 : 0 : do_dma_submit_and_poll(dev_id, &async_cnt, worker_info);
335 : : }
336 : :
337 : 0 : if (worker_info->stop_flag)
338 : : break;
339 : : }
340 : :
341 : 0 : rte_dma_submit(dev_id, 0);
342 : 0 : while ((async_cnt > 0) && (poll_cnt++ < POLL_MAX)) {
343 : : nr_cpl = rte_dma_completed(dev_id, 0, MAX_DMA_CPL_NB, NULL, NULL);
344 : 0 : async_cnt -= nr_cpl;
345 : : }
346 : :
347 : 0 : return 0;
348 : : }
349 : :
350 : : static inline int
351 : 0 : do_dma_sg_mem_copy(void *p)
352 : : {
353 : : struct lcore_params *para = (struct lcore_params *)p;
354 : 0 : volatile struct worker_info *worker_info = &(para->worker_info);
355 : 0 : struct rte_dma_sge *src_sges = para->sge.srcs;
356 : 0 : struct rte_dma_sge *dst_sges = para->sge.dsts;
357 : 0 : const uint8_t nb_src_sges = para->sge.nb_srcs;
358 : 0 : const uint8_t nb_dst_sges = para->sge.nb_dsts;
359 : 0 : const uint16_t kick_batch = para->kick_batch;
360 : 0 : const uint16_t dev_id = para->dev_id;
361 : 0 : uint32_t nr_buf = para->nr_buf;
362 : 0 : uint64_t async_cnt = 0;
363 : : uint32_t poll_cnt = 0;
364 : : uint16_t nr_cpl;
365 : : uint32_t i, j;
366 : : int ret;
367 : :
368 : 0 : nr_buf /= RTE_MAX(nb_src_sges, nb_dst_sges);
369 : 0 : worker_info->stop_flag = false;
370 : 0 : worker_info->ready_flag = true;
371 : :
372 : 0 : while (!worker_info->start_flag)
373 : : ;
374 : :
375 : : while (1) {
376 : : j = 0;
377 : 0 : for (i = 0; i < nr_buf; i++) {
378 : 0 : dma_copy:
379 : 0 : ret = rte_dma_copy_sg(dev_id, 0,
380 : 0 : &src_sges[i * nb_src_sges], &dst_sges[j * nb_dst_sges],
381 : : nb_src_sges, nb_dst_sges, 0);
382 : 0 : if (unlikely(ret < 0)) {
383 : 0 : if (ret == -ENOSPC) {
384 : 0 : do_dma_submit_and_poll(dev_id, &async_cnt, worker_info);
385 : 0 : goto dma_copy;
386 : : } else
387 : 0 : error_exit(dev_id);
388 : : }
389 : 0 : async_cnt++;
390 : 0 : j++;
391 : :
392 : 0 : if ((async_cnt % kick_batch) == 0)
393 : 0 : do_dma_submit_and_poll(dev_id, &async_cnt, worker_info);
394 : : }
395 : :
396 : 0 : if (worker_info->stop_flag)
397 : : break;
398 : : }
399 : :
400 : 0 : rte_dma_submit(dev_id, 0);
401 : 0 : while ((async_cnt > 0) && (poll_cnt++ < POLL_MAX)) {
402 : : nr_cpl = rte_dma_completed(dev_id, 0, MAX_DMA_CPL_NB, NULL, NULL);
403 : 0 : async_cnt -= nr_cpl;
404 : : }
405 : :
406 : 0 : return 0;
407 : : }
408 : :
409 : : static inline int
410 : 0 : do_dma_enq_deq_mem_copy(void *p)
411 : : {
412 : : #define DEQ_SZ 64
413 : : struct lcore_params *para = (struct lcore_params *)p;
414 : : volatile struct worker_info *worker_info = &(para->worker_info);
415 : 0 : struct rte_dma_op **dma_ops = para->dma_ops;
416 : 0 : uint16_t kick_batch = para->kick_batch, sz;
417 : : uint16_t enq, deq, poll_cnt;
418 : : uint64_t tenq, tdeq;
419 : 0 : const uint16_t dev_id = para->dev_id;
420 : 0 : uint32_t nr_buf = para->nr_buf;
421 : : struct rte_dma_op *op[DEQ_SZ];
422 : : uint32_t i;
423 : :
424 : 0 : worker_info->stop_flag = false;
425 : 0 : worker_info->ready_flag = true;
426 : :
427 : 0 : while (!worker_info->start_flag)
428 : : ;
429 : :
430 : 0 : if (kick_batch > nr_buf)
431 : 0 : kick_batch = nr_buf;
432 : :
433 : : tenq = 0;
434 : : tdeq = 0;
435 : : while (1) {
436 : 0 : for (i = 0; i < nr_buf; i += kick_batch) {
437 : 0 : sz = RTE_MIN(nr_buf - i, kick_batch);
438 : 0 : enq = rte_dma_enqueue_ops(dev_id, 0, &dma_ops[i], sz);
439 : 0 : while (enq < sz) {
440 : : do {
441 : : deq = rte_dma_dequeue_ops(dev_id, 0, op, DEQ_SZ);
442 : 0 : tdeq += deq;
443 : 0 : } while (deq);
444 : 0 : enq += rte_dma_enqueue_ops(dev_id, 0, &dma_ops[i + enq], sz - enq);
445 : 0 : if (worker_info->stop_flag)
446 : : break;
447 : : }
448 : 0 : tenq += enq;
449 : :
450 : 0 : worker_info->total_cpl += enq;
451 : : }
452 : :
453 : 0 : if (worker_info->stop_flag)
454 : : break;
455 : : }
456 : :
457 : : poll_cnt = 0;
458 : 0 : while ((tenq != tdeq) && (poll_cnt++ < POLL_MAX))
459 : 0 : tdeq += rte_dma_dequeue_ops(dev_id, 0, op, DEQ_SZ);
460 : :
461 : 0 : return 0;
462 : : }
463 : :
464 : : static inline int
465 : 0 : do_cpu_mem_copy(void *p)
466 : : {
467 : : struct lcore_params *para = (struct lcore_params *)p;
468 : : volatile struct worker_info *worker_info = &(para->worker_info);
469 : 0 : const uint32_t nr_buf = para->nr_buf;
470 : 0 : const uint32_t buf_size = para->buf_size;
471 : 0 : struct rte_mbuf **srcs = para->srcs;
472 : 0 : struct rte_mbuf **dsts = para->dsts;
473 : : uint32_t i;
474 : :
475 : 0 : worker_info->stop_flag = false;
476 : 0 : worker_info->ready_flag = true;
477 : :
478 : 0 : while (!worker_info->start_flag)
479 : : ;
480 : :
481 : : while (1) {
482 : 0 : for (i = 0; i < nr_buf; i++) {
483 : 0 : const void *src = rte_pktmbuf_mtod(dsts[i], void *);
484 : 0 : void *dst = rte_pktmbuf_mtod(srcs[i], void *);
485 : :
486 : : /* copy buffer form src to dst */
487 : 0 : rte_memcpy(dst, src, (size_t)buf_size);
488 : 0 : worker_info->total_cpl++;
489 : : }
490 : 0 : if (worker_info->stop_flag)
491 : : break;
492 : : }
493 : :
494 : 0 : return 0;
495 : : }
496 : :
497 : : static void
498 : 0 : dummy_free_ext_buf(void *addr, void *opaque)
499 : : {
500 : : RTE_SET_USED(addr);
501 : : RTE_SET_USED(opaque);
502 : 0 : }
503 : :
504 : : static int
505 : 0 : setup_memory_env(struct test_configure *cfg, struct rte_mbuf ***srcs, struct rte_mbuf ***dsts,
506 : : struct rte_dma_sge **src_sges, struct rte_dma_sge **dst_sges,
507 : : struct rte_dma_op ***dma_ops)
508 : : {
509 : 0 : unsigned int cur_buf_size = cfg->buf_size.cur;
510 : 0 : unsigned int buf_size = cur_buf_size + RTE_PKTMBUF_HEADROOM;
511 : : bool is_src_numa_incorrect, is_dst_numa_incorrect;
512 : 0 : uint32_t nr_buf = cfg->nr_buf;
513 : : unsigned int nr_sockets;
514 : : uintptr_t ops;
515 : : uint32_t i;
516 : :
517 : 0 : nr_sockets = rte_socket_count();
518 : 0 : is_src_numa_incorrect = (cfg->src_numa_node >= nr_sockets);
519 : 0 : is_dst_numa_incorrect = (cfg->dst_numa_node >= nr_sockets);
520 : :
521 : 0 : if (is_src_numa_incorrect || is_dst_numa_incorrect) {
522 : 0 : PRINT_ERR("Error: Incorrect NUMA config for %s.\n",
523 : : (is_src_numa_incorrect && is_dst_numa_incorrect) ? "source & destination" :
524 : : (is_src_numa_incorrect) ? "source" : "destination");
525 : 0 : return -1;
526 : : }
527 : :
528 : 0 : src_pool = rte_pktmbuf_pool_create("Benchmark_DMA_SRC",
529 : : nr_buf,
530 : : 0,
531 : : 0,
532 : : buf_size,
533 : : cfg->src_numa_node);
534 : 0 : if (src_pool == NULL) {
535 : 0 : PRINT_ERR("Error with source mempool creation.\n");
536 : 0 : return -1;
537 : : }
538 : :
539 : 0 : dst_pool = rte_pktmbuf_pool_create("Benchmark_DMA_DST",
540 : : nr_buf,
541 : : 0,
542 : : 0,
543 : : buf_size,
544 : 0 : cfg->dst_numa_node);
545 : 0 : if (dst_pool == NULL) {
546 : 0 : PRINT_ERR("Error with destination mempool creation.\n");
547 : 0 : return -1;
548 : : }
549 : :
550 : 0 : *srcs = rte_malloc(NULL, nr_buf * sizeof(struct rte_mbuf *), 0);
551 : 0 : if (*srcs == NULL) {
552 : : printf("Error: srcs malloc failed.\n");
553 : 0 : return -1;
554 : : }
555 : :
556 : 0 : *dsts = rte_malloc(NULL, nr_buf * sizeof(struct rte_mbuf *), 0);
557 : 0 : if (*dsts == NULL) {
558 : : printf("Error: dsts malloc failed.\n");
559 : 0 : return -1;
560 : : }
561 : :
562 : 0 : if (rte_pktmbuf_alloc_bulk(src_pool, *srcs, nr_buf) != 0) {
563 : : printf("alloc src mbufs failed.\n");
564 : 0 : return -1;
565 : : }
566 : :
567 : 0 : if (rte_pktmbuf_alloc_bulk(dst_pool, *dsts, nr_buf) != 0) {
568 : : printf("alloc dst mbufs failed.\n");
569 : 0 : return -1;
570 : : }
571 : :
572 : 0 : for (i = 0; i < nr_buf; i++) {
573 : 0 : memset(rte_pktmbuf_mtod((*srcs)[i], void *), rte_rand(), cur_buf_size);
574 : 0 : memset(rte_pktmbuf_mtod((*dsts)[i], void *), 0, cur_buf_size);
575 : : }
576 : :
577 : 0 : if (cfg->is_sg) {
578 : 0 : uint8_t nb_src_sges = cfg->nb_src_sges;
579 : 0 : uint8_t nb_dst_sges = cfg->nb_dst_sges;
580 : : uint32_t sglen_src, sglen_dst;
581 : :
582 : 0 : *src_sges = rte_zmalloc(NULL, nr_buf * sizeof(struct rte_dma_sge),
583 : : RTE_CACHE_LINE_SIZE);
584 : 0 : if (*src_sges == NULL) {
585 : : printf("Error: src_sges array malloc failed.\n");
586 : 0 : return -1;
587 : : }
588 : :
589 : 0 : *dst_sges = rte_zmalloc(NULL, nr_buf * sizeof(struct rte_dma_sge),
590 : : RTE_CACHE_LINE_SIZE);
591 : 0 : if (*dst_sges == NULL) {
592 : : printf("Error: dst_sges array malloc failed.\n");
593 : 0 : return -1;
594 : : }
595 : :
596 : 0 : sglen_src = cur_buf_size / nb_src_sges;
597 : 0 : sglen_dst = cur_buf_size / nb_dst_sges;
598 : :
599 : 0 : for (i = 0; i < nr_buf; i++) {
600 : 0 : (*src_sges)[i].addr = rte_pktmbuf_iova((*srcs)[i]);
601 : 0 : (*src_sges)[i].length = sglen_src;
602 : 0 : if (!((i+1) % nb_src_sges))
603 : 0 : (*src_sges)[i].length += (cur_buf_size % nb_src_sges);
604 : :
605 : 0 : (*dst_sges)[i].addr = rte_pktmbuf_iova((*dsts)[i]);
606 : 0 : (*dst_sges)[i].length = sglen_dst;
607 : 0 : if (!((i+1) % nb_dst_sges))
608 : 0 : (*dst_sges)[i].length += (cur_buf_size % nb_dst_sges);
609 : : }
610 : :
611 : 0 : if (cfg->use_ops) {
612 : :
613 : 0 : nr_buf /= RTE_MAX(nb_src_sges, nb_dst_sges);
614 : 0 : *dma_ops = rte_zmalloc(NULL, nr_buf * (sizeof(struct rte_dma_op *)),
615 : : RTE_CACHE_LINE_SIZE);
616 : 0 : if (*dma_ops == NULL) {
617 : : printf("Error: dma_ops container malloc failed.\n");
618 : 0 : return -1;
619 : : }
620 : :
621 : 0 : ops = (uintptr_t)rte_zmalloc(
622 : : NULL,
623 : 0 : nr_buf * (sizeof(struct rte_dma_op) + ((nb_src_sges + nb_dst_sges) *
624 : : sizeof(struct rte_dma_sge))),
625 : : RTE_CACHE_LINE_SIZE);
626 : 0 : if (ops == 0) {
627 : : printf("Error: dma_ops malloc failed.\n");
628 : 0 : return -1;
629 : : }
630 : :
631 : 0 : for (i = 0; i < nr_buf; i++)
632 : 0 : (*dma_ops)[i] =
633 : 0 : (struct rte_dma_op *)(ops +
634 : 0 : (i * (sizeof(struct rte_dma_op) +
635 : : ((nb_src_sges + nb_dst_sges) *
636 : : sizeof(struct rte_dma_sge)))));
637 : : }
638 : : }
639 : :
640 : : return 0;
641 : : }
642 : :
643 : : static uint32_t
644 : 0 : align_buffer_count(struct test_configure *cfg, uint32_t *nr_sgsrc, uint32_t *nr_sgdst)
645 : : {
646 : 0 : uint16_t nb_workers = cfg->num_worker;
647 : : uint32_t nr_buf;
648 : :
649 : 0 : nr_buf = (cfg->mem_size.cur * 1024 * 1024) / (cfg->buf_size.cur * 2);
650 : 0 : nr_buf -= (nr_buf % nb_workers);
651 : :
652 : 0 : if (nr_sgsrc == NULL || nr_sgdst == NULL)
653 : : return nr_buf;
654 : :
655 : 0 : if (cfg->is_sg) {
656 : 0 : nr_buf /= nb_workers;
657 : 0 : nr_buf -= nr_buf % (cfg->nb_src_sges * cfg->nb_dst_sges);
658 : 0 : nr_buf *= nb_workers;
659 : :
660 : 0 : if (cfg->nb_dst_sges > cfg->nb_src_sges) {
661 : 0 : *nr_sgsrc = (nr_buf / cfg->nb_dst_sges * cfg->nb_src_sges);
662 : 0 : *nr_sgdst = nr_buf;
663 : : } else {
664 : 0 : *nr_sgsrc = nr_buf;
665 : 0 : *nr_sgdst = (nr_buf / cfg->nb_src_sges * cfg->nb_dst_sges);
666 : : }
667 : : }
668 : :
669 : : return nr_buf;
670 : : }
671 : :
672 : : static lcore_function_t *
673 : : get_work_function(struct test_configure *cfg)
674 : : {
675 : : lcore_function_t *fn;
676 : :
677 : 0 : if (cfg->is_dma) {
678 : 0 : if (!cfg->is_sg)
679 : : fn = do_dma_plain_mem_copy;
680 : : else {
681 : 0 : if (cfg->use_ops)
682 : : fn = do_dma_enq_deq_mem_copy;
683 : : else
684 : : fn = do_dma_sg_mem_copy;
685 : : }
686 : : } else {
687 : : fn = do_cpu_mem_copy;
688 : : }
689 : :
690 : : return fn;
691 : : }
692 : :
693 : : static int
694 : 0 : attach_ext_buffer(struct vchan_dev_config *vchan_dev, struct lcore_params *lcore, bool is_sg,
695 : : uint32_t nr_sgsrc, uint32_t nr_sgdst)
696 : : {
697 : : static struct rte_mbuf_ext_shared_info *ext_buf_info;
698 : : struct rte_dma_sge **src_sges, **dst_sges;
699 : : struct rte_mbuf **srcs, **dsts;
700 : : unsigned int cur_buf_size;
701 : : unsigned int buf_size;
702 : : uint32_t nr_buf;
703 : : uint32_t i;
704 : :
705 : 0 : cur_buf_size = lcore->buf_size;
706 : 0 : buf_size = cur_buf_size + RTE_PKTMBUF_HEADROOM;
707 : 0 : nr_buf = lcore->nr_buf;
708 : 0 : srcs = lcore->srcs;
709 : 0 : dsts = lcore->dsts;
710 : :
711 : 0 : ext_buf_info = rte_malloc(NULL, sizeof(struct rte_mbuf_ext_shared_info), 0);
712 : 0 : if (ext_buf_info == NULL) {
713 : : printf("Error: ext_buf_info malloc failed.\n");
714 : 0 : return -1;
715 : : }
716 : 0 : ext_buf_info->free_cb = dummy_free_ext_buf;
717 : 0 : ext_buf_info->fcb_opaque = NULL;
718 : :
719 : 0 : if (vchan_dev->tdir == RTE_DMA_DIR_DEV_TO_MEM) {
720 : 0 : for (i = 0; i < nr_buf; i++) {
721 : : /* Using mbuf structure to hold remote iova address. */
722 : 0 : rte_pktmbuf_attach_extbuf(srcs[i],
723 : : (void *)(vchan_dev->raddr + (i * buf_size)),
724 : 0 : (rte_iova_t)(vchan_dev->raddr + (i * buf_size)), 0, ext_buf_info);
725 : 0 : rte_mbuf_ext_refcnt_update(ext_buf_info, 1);
726 : : }
727 : : }
728 : :
729 : 0 : if (vchan_dev->tdir == RTE_DMA_DIR_MEM_TO_DEV) {
730 : 0 : for (i = 0; i < nr_buf; i++) {
731 : : /* Using mbuf structure to hold remote iova address. */
732 : 0 : rte_pktmbuf_attach_extbuf(dsts[i],
733 : : (void *)(vchan_dev->raddr + (i * buf_size)),
734 : 0 : (rte_iova_t)(vchan_dev->raddr + (i * buf_size)), 0, ext_buf_info);
735 : 0 : rte_mbuf_ext_refcnt_update(ext_buf_info, 1);
736 : : }
737 : : }
738 : :
739 : 0 : if (is_sg) {
740 : 0 : uint8_t nb_src_sges = lcore->sge.nb_srcs;
741 : 0 : uint8_t nb_dst_sges = lcore->sge.nb_dsts;
742 : : uint32_t sglen_src, sglen_dst;
743 : :
744 : : src_sges = &lcore->sge.srcs;
745 : : dst_sges = &lcore->sge.dsts;
746 : :
747 : 0 : sglen_src = cur_buf_size / nb_src_sges;
748 : 0 : sglen_dst = cur_buf_size / nb_dst_sges;
749 : :
750 : 0 : if (vchan_dev->tdir == RTE_DMA_DIR_DEV_TO_MEM) {
751 : 0 : for (i = 0; i < nr_sgsrc; i++) {
752 : 0 : (*src_sges)[i].addr = rte_pktmbuf_iova(srcs[i]);
753 : 0 : (*src_sges)[i].length = sglen_src;
754 : 0 : if (!((i+1) % nb_src_sges))
755 : 0 : (*src_sges)[i].length += (cur_buf_size % nb_src_sges);
756 : : }
757 : : }
758 : :
759 : 0 : if (vchan_dev->tdir == RTE_DMA_DIR_MEM_TO_DEV) {
760 : 0 : for (i = 0; i < nr_sgdst; i++) {
761 : 0 : (*dst_sges)[i].addr = rte_pktmbuf_iova(dsts[i]);
762 : 0 : (*dst_sges)[i].length = sglen_dst;
763 : 0 : if (!((i+1) % nb_dst_sges))
764 : 0 : (*dst_sges)[i].length += (cur_buf_size % nb_dst_sges);
765 : : }
766 : : }
767 : : }
768 : :
769 : : return 0;
770 : : }
771 : :
772 : : int
773 : 0 : mem_copy_benchmark(struct test_configure *cfg)
774 : : {
775 : : uint32_t i, j, k;
776 : : uint32_t offset;
777 : : unsigned int lcore_id = 0;
778 : 0 : struct rte_mbuf **srcs = NULL, **dsts = NULL, **m = NULL;
779 : 0 : struct rte_dma_sge *src_sges = NULL, *dst_sges = NULL;
780 : : struct vchan_dev_config *vchan_dev = NULL;
781 : : struct lcore_dma_map_t *lcore_dma_map = NULL;
782 : 0 : struct rte_dma_op **dma_ops = NULL;
783 : 0 : unsigned int buf_size = cfg->buf_size.cur;
784 : 0 : uint16_t kick_batch = cfg->kick_batch.cur;
785 : 0 : uint16_t nb_workers = cfg->num_worker;
786 : 0 : uint16_t test_secs = cfg->test_secs;
787 : 0 : float memory = 0;
788 : 0 : uint32_t avg_cycles = 0;
789 : : uint32_t avg_cycles_total;
790 : : float mops, mops_total;
791 : : float bandwidth, bandwidth_total;
792 : 0 : uint32_t nr_sgsrc = 0, nr_sgdst = 0;
793 : : uint32_t nr_buf, nr_ops;
794 : : int ret = 0;
795 : :
796 : 0 : nr_buf = align_buffer_count(cfg, &nr_sgsrc, &nr_sgdst);
797 : 0 : cfg->nr_buf = nr_buf;
798 : :
799 : 0 : if (setup_memory_env(cfg, &srcs, &dsts, &src_sges, &dst_sges, &dma_ops) < 0)
800 : 0 : goto out;
801 : :
802 : 0 : if (cfg->is_dma)
803 : 0 : if (config_dmadevs(cfg) < 0)
804 : 0 : goto out;
805 : :
806 : 0 : if (cfg->cache_flush == 1) {
807 : 0 : cache_flush_buf(srcs, buf_size, nr_buf);
808 : 0 : cache_flush_buf(dsts, buf_size, nr_buf);
809 : : rte_mb();
810 : : }
811 : :
812 : : printf("Start testing....\n");
813 : :
814 : 0 : for (i = 0; i < nb_workers; i++) {
815 : : lcore_dma_map = &cfg->dma_config[i].lcore_dma_map;
816 : 0 : vchan_dev = &cfg->dma_config[i].vchan_dev;
817 : :
818 : 0 : lcore_id = lcore_dma_map->lcore;
819 : 0 : offset = nr_buf / nb_workers * i;
820 : 0 : lcores[i] = rte_malloc(NULL, sizeof(struct lcore_params), 0);
821 : 0 : if (lcores[i] == NULL) {
822 : : printf("lcore parameters malloc failure for lcore %d\n", lcore_id);
823 : : break;
824 : : }
825 : 0 : if (cfg->is_dma) {
826 : 0 : lcores[i]->dma_name = lcore_dma_map->dma_names;
827 : 0 : lcores[i]->dev_id = lcore_dma_map->dma_id;
828 : 0 : lcores[i]->kick_batch = kick_batch;
829 : : }
830 : :
831 : 0 : lcores[i]->worker_id = i;
832 : 0 : lcores[i]->nr_buf = (uint32_t)(nr_buf / nb_workers);
833 : 0 : lcores[i]->buf_size = buf_size;
834 : 0 : lcores[i]->test_secs = test_secs;
835 : 0 : lcores[i]->srcs = srcs + offset;
836 : 0 : lcores[i]->dsts = dsts + offset;
837 : 0 : lcores[i]->scenario_id = cfg->scenario_id;
838 : 0 : lcores[i]->lcore_id = lcore_id;
839 : :
840 : 0 : if (cfg->is_sg) {
841 : 0 : lcores[i]->sge.nb_srcs = cfg->nb_src_sges;
842 : 0 : lcores[i]->sge.nb_dsts = cfg->nb_dst_sges;
843 : 0 : lcores[i]->sge.srcs = src_sges + (nr_sgsrc / nb_workers * i);
844 : 0 : lcores[i]->sge.dsts = dst_sges + (nr_sgdst / nb_workers * i);
845 : : }
846 : :
847 : 0 : if (vchan_dev->tdir == RTE_DMA_DIR_DEV_TO_MEM ||
848 : : vchan_dev->tdir == RTE_DMA_DIR_MEM_TO_DEV) {
849 : 0 : if (attach_ext_buffer(vchan_dev, lcores[i], cfg->is_sg,
850 : : (nr_sgsrc/nb_workers), (nr_sgdst/nb_workers)) < 0)
851 : 0 : goto out;
852 : : }
853 : :
854 : 0 : if (cfg->is_sg && cfg->use_ops) {
855 : 0 : nr_ops = nr_buf / RTE_MAX(cfg->nb_src_sges, cfg->nb_dst_sges);
856 : 0 : lcores[i]->nr_buf = nr_ops / nb_workers;
857 : 0 : lcores[i]->dma_ops = dma_ops + (nr_ops / nb_workers * i);
858 : 0 : for (j = 0; j < (nr_ops / nb_workers); j++) {
859 : 0 : for (k = 0; k < cfg->nb_src_sges; k++)
860 : 0 : lcores[i]->dma_ops[j]->src_dst_seg[k] =
861 : 0 : lcores[i]->sge.srcs[(j * cfg->nb_src_sges) + k];
862 : :
863 : 0 : for (k = 0; k < cfg->nb_dst_sges; k++)
864 : 0 : lcores[i]->dma_ops[j]->src_dst_seg[k + cfg->nb_src_sges] =
865 : 0 : lcores[i]->sge.dsts[(j * cfg->nb_dst_sges) + k];
866 : :
867 : 0 : lcores[i]->dma_ops[j]->nb_src = cfg->nb_src_sges;
868 : 0 : lcores[i]->dma_ops[j]->nb_dst = cfg->nb_dst_sges;
869 : 0 : lcores[i]->dma_ops[j]->vchan = 0;
870 : : }
871 : : }
872 : :
873 : 0 : rte_eal_remote_launch(get_work_function(cfg), (void *)(lcores[i]), lcore_id);
874 : : }
875 : :
876 : : while (1) {
877 : : bool ready = true;
878 : 0 : for (i = 0; i < nb_workers; i++) {
879 : 0 : if (lcores[i]->worker_info.ready_flag == false) {
880 : : ready = 0;
881 : : break;
882 : : }
883 : : }
884 : 0 : if (ready)
885 : : break;
886 : : }
887 : :
888 : 0 : for (i = 0; i < nb_workers; i++)
889 : 0 : lcores[i]->worker_info.start_flag = true;
890 : :
891 : 0 : usleep(TEST_WAIT_U_SECOND);
892 : 0 : for (i = 0; i < nb_workers; i++)
893 : 0 : lcores[i]->worker_info.test_cpl = lcores[i]->worker_info.total_cpl;
894 : :
895 : 0 : usleep(test_secs * 1000 * 1000);
896 : 0 : for (i = 0; i < nb_workers; i++)
897 : 0 : lcores[i]->worker_info.test_cpl = lcores[i]->worker_info.total_cpl -
898 : 0 : lcores[i]->worker_info.test_cpl;
899 : :
900 : 0 : for (i = 0; i < nb_workers; i++)
901 : 0 : lcores[i]->worker_info.stop_flag = true;
902 : :
903 : 0 : rte_eal_mp_wait_lcore();
904 : :
905 : 0 : for (k = 0; k < nb_workers; k++) {
906 : : struct rte_mbuf **src_buf = NULL, **dst_buf = NULL;
907 : 0 : uint32_t nr_buf_pt = nr_buf / nb_workers;
908 : : vchan_dev = &cfg->dma_config[k].vchan_dev;
909 : 0 : offset = nr_buf / nb_workers * k;
910 : 0 : src_buf = srcs + offset;
911 : 0 : dst_buf = dsts + offset;
912 : :
913 : 0 : if (vchan_dev->tdir == RTE_DMA_DIR_MEM_TO_MEM && !cfg->is_sg) {
914 : 0 : for (i = 0; i < nr_buf_pt; i++) {
915 : 0 : if (memcmp(rte_pktmbuf_mtod(src_buf[i], void *),
916 : 0 : rte_pktmbuf_mtod(dst_buf[i], void *),
917 : 0 : cfg->buf_size.cur) != 0) {
918 : : printf("Copy validation fails for buffer number %d\n", i);
919 : : ret = -1;
920 : 0 : goto out;
921 : : }
922 : : }
923 : 0 : } else if (vchan_dev->tdir == RTE_DMA_DIR_MEM_TO_MEM && cfg->is_sg) {
924 : 0 : size_t src_remsz = buf_size % cfg->nb_src_sges;
925 : 0 : size_t dst_remsz = buf_size % cfg->nb_dst_sges;
926 : 0 : size_t src_sz = buf_size / cfg->nb_src_sges;
927 : 0 : size_t dst_sz = buf_size / cfg->nb_dst_sges;
928 : 0 : uint8_t src[buf_size], dst[buf_size];
929 : : uint8_t *sbuf, *dbuf, *ptr;
930 : :
931 : 0 : for (i = 0; i < (nr_buf_pt / RTE_MAX(cfg->nb_src_sges, cfg->nb_dst_sges));
932 : 0 : i++) {
933 : : sbuf = src;
934 : : dbuf = dst;
935 : : ptr = NULL;
936 : :
937 : 0 : for (j = 0; j < cfg->nb_src_sges; j++) {
938 : 0 : ptr = rte_pktmbuf_mtod(src_buf[i * cfg->nb_src_sges + j],
939 : : uint8_t *);
940 : : memcpy(sbuf, ptr, src_sz);
941 : 0 : sbuf += src_sz;
942 : : }
943 : :
944 : 0 : if (src_remsz)
945 : 0 : memcpy(sbuf, ptr + src_sz, src_remsz);
946 : :
947 : 0 : for (j = 0; j < cfg->nb_dst_sges; j++) {
948 : 0 : ptr = rte_pktmbuf_mtod(dst_buf[i * cfg->nb_dst_sges + j],
949 : : uint8_t *);
950 : : memcpy(dbuf, ptr, dst_sz);
951 : 0 : dbuf += dst_sz;
952 : : }
953 : :
954 : 0 : if (dst_remsz)
955 : 0 : memcpy(dbuf, ptr + dst_sz, dst_remsz);
956 : :
957 : 0 : if (memcmp(src, dst, buf_size) != 0) {
958 : 0 : printf("SG Copy validation fails for buffer number %d\n",
959 : : i * cfg->nb_src_sges);
960 : : ret = -1;
961 : 0 : goto out;
962 : : }
963 : : }
964 : : }
965 : : }
966 : :
967 : : mops_total = 0;
968 : : bandwidth_total = 0;
969 : : avg_cycles_total = 0;
970 : 0 : for (i = 0; i < nb_workers; i++) {
971 : : vchan_dev = &cfg->dma_config[i].vchan_dev;
972 : 0 : calc_result(buf_size, nr_buf, nb_workers, test_secs,
973 : 0 : lcores[i]->worker_info.test_cpl,
974 : : &memory, &avg_cycles, &bandwidth, &mops);
975 : 0 : printf("Direction: %s\n", vchan_dev->tdir == 0 ? "mem2mem" :
976 : 0 : vchan_dev->tdir == 1 ? "mem2dev" : "dev2mem");
977 : 0 : output_result(cfg, lcores[i], kick_batch, avg_cycles, buf_size,
978 : : nr_buf / nb_workers, memory, bandwidth, mops);
979 : 0 : mops_total += mops;
980 : 0 : bandwidth_total += bandwidth;
981 : 0 : avg_cycles_total += avg_cycles;
982 : : }
983 : 0 : printf("\nAverage Cycles/op per worker: %.1lf, Total Bandwidth: %.3lf Gbps, Total MOps: %.3lf\n",
984 : 0 : (avg_cycles_total * (float) 1.0) / nb_workers, bandwidth_total, mops_total);
985 : 0 : snprintf(output_str[MAX_WORKER_NB], MAX_OUTPUT_STR_LEN, CSV_TOTAL_LINE_FMT,
986 : 0 : cfg->scenario_id, nr_buf, memory * nb_workers,
987 : : (avg_cycles_total * (float) 1.0) / nb_workers, bandwidth_total, mops_total);
988 : :
989 : 0 : out:
990 : :
991 : 0 : for (k = 0; k < nb_workers; k++) {
992 : : struct rte_mbuf **sbuf = NULL, **dbuf = NULL;
993 : : vchan_dev = &cfg->dma_config[k].vchan_dev;
994 : 0 : offset = nr_buf / nb_workers * k;
995 : : m = NULL;
996 : 0 : if (vchan_dev->tdir == RTE_DMA_DIR_DEV_TO_MEM) {
997 : 0 : sbuf = srcs + offset;
998 : : m = sbuf;
999 : 0 : } else if (vchan_dev->tdir == RTE_DMA_DIR_MEM_TO_DEV) {
1000 : 0 : dbuf = dsts + offset;
1001 : : m = dbuf;
1002 : : }
1003 : :
1004 : 0 : if (m) {
1005 : 0 : for (i = 0; i < (nr_buf / nb_workers); i++)
1006 : 0 : rte_pktmbuf_detach_extbuf(m[i]);
1007 : :
1008 : 0 : if (m[0]->shinfo && rte_mbuf_ext_refcnt_read(m[0]->shinfo) == 0)
1009 : 0 : rte_free(m[0]->shinfo);
1010 : : }
1011 : : }
1012 : :
1013 : : /* free mbufs used in the test */
1014 : 0 : if (srcs != NULL)
1015 : 0 : rte_pktmbuf_free_bulk(srcs, nr_buf);
1016 : 0 : if (dsts != NULL)
1017 : 0 : rte_pktmbuf_free_bulk(dsts, nr_buf);
1018 : :
1019 : : /* free the points for the mbufs */
1020 : 0 : rte_free(srcs);
1021 : 0 : srcs = NULL;
1022 : 0 : rte_free(dsts);
1023 : 0 : dsts = NULL;
1024 : :
1025 : 0 : rte_mempool_free(src_pool);
1026 : 0 : src_pool = NULL;
1027 : :
1028 : 0 : rte_mempool_free(dst_pool);
1029 : 0 : dst_pool = NULL;
1030 : :
1031 : : /* free sges for mbufs */
1032 : 0 : rte_free(src_sges);
1033 : 0 : src_sges = NULL;
1034 : :
1035 : 0 : rte_free(dst_sges);
1036 : 0 : dst_sges = NULL;
1037 : :
1038 : : /* free the worker parameters */
1039 : 0 : for (i = 0; i < nb_workers; i++) {
1040 : 0 : rte_free(lcores[i]);
1041 : 0 : lcores[i] = NULL;
1042 : : }
1043 : :
1044 : 0 : if (cfg->is_dma) {
1045 : 0 : for (i = 0; i < nb_workers; i++) {
1046 : : lcore_dma_map = &cfg->dma_config[i].lcore_dma_map;
1047 : 0 : printf("Stopping dmadev %d\n", lcore_dma_map->dma_id);
1048 : 0 : rte_dma_stop(lcore_dma_map->dma_id);
1049 : : }
1050 : : }
1051 : :
1052 : 0 : return ret;
1053 : : }
|