1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(c) 2017 Intel Corporation
10 #include <rte_common.h>
12 #include <rte_launch.h>
13 #include <rte_bbdev.h>
14 #include <rte_cycles.h>
15 #include <rte_lcore.h>
16 #include <rte_malloc.h>
17 #include <rte_random.h>
18 #include <rte_hexdump.h>
21 #include "test_bbdev_vector.h"
23 #define GET_SOCKET(socket_id) (((socket_id) == SOCKET_ID_ANY) ? 0 : (socket_id))
25 #define MAX_QUEUES RTE_MAX_LCORE
26 #define TEST_REPETITIONS 1000
28 #define OPS_CACHE_SIZE 256U
29 #define OPS_POOL_SIZE_MIN 511U /* 0.5K per queue */
34 #define INVALID_QUEUE_ID -1
36 static struct test_bbdev_vector test_vector;
38 /* Switch between PMD and Interrupt for throughput TC */
39 static bool intr_enabled;
41 /* Represents tested active devices */
42 static struct active_device {
43 const char *driver_name;
45 uint16_t supported_ops;
46 uint16_t queue_ids[MAX_QUEUES];
48 struct rte_mempool *ops_mempool;
49 struct rte_mempool *in_mbuf_pool;
50 struct rte_mempool *hard_out_mbuf_pool;
51 struct rte_mempool *soft_out_mbuf_pool;
52 } active_devs[RTE_BBDEV_MAX_DEVS];
54 static uint8_t nb_active_devs;
56 /* Data buffers used by BBDEV ops */
58 struct rte_bbdev_op_data *inputs;
59 struct rte_bbdev_op_data *hard_outputs;
60 struct rte_bbdev_op_data *soft_outputs;
63 /* Operation parameters specific for given test case */
64 struct test_op_params {
65 struct rte_mempool *mp;
66 struct rte_bbdev_dec_op *ref_dec_op;
67 struct rte_bbdev_enc_op *ref_enc_op;
69 uint16_t num_to_process;
73 struct test_buffers q_bufs[RTE_MAX_NUMA_NODES][MAX_QUEUES];
76 /* Contains per lcore params */
77 struct thread_params {
84 rte_atomic16_t nb_dequeued;
85 rte_atomic16_t processing_status;
86 struct test_op_params *op_params;
89 #ifdef RTE_BBDEV_OFFLOAD_COST
90 /* Stores time statistics */
91 struct test_time_stats {
92 /* Stores software enqueue total working time */
93 uint64_t enq_sw_total_time;
94 /* Stores minimum value of software enqueue working time */
95 uint64_t enq_sw_min_time;
96 /* Stores maximum value of software enqueue working time */
97 uint64_t enq_sw_max_time;
98 /* Stores turbo enqueue total working time */
99 uint64_t enq_acc_total_time;
100 /* Stores minimum value of accelerator enqueue working time */
101 uint64_t enq_acc_min_time;
102 /* Stores maximum value of accelerator enqueue working time */
103 uint64_t enq_acc_max_time;
104 /* Stores dequeue total working time */
105 uint64_t deq_total_time;
106 /* Stores minimum value of dequeue working time */
107 uint64_t deq_min_time;
108 /* Stores maximum value of dequeue working time */
109 uint64_t deq_max_time;
113 typedef int (test_case_function)(struct active_device *ad,
114 struct test_op_params *op_params);
117 set_avail_op(struct active_device *ad, enum rte_bbdev_op_type op_type)
119 ad->supported_ops |= (1 << op_type);
123 is_avail_op(struct active_device *ad, enum rte_bbdev_op_type op_type)
125 return ad->supported_ops & (1 << op_type);
129 flags_match(uint32_t flags_req, uint32_t flags_present)
131 return (flags_req & flags_present) == flags_req;
135 clear_soft_out_cap(uint32_t *op_flags)
137 *op_flags &= ~RTE_BBDEV_TURBO_SOFT_OUTPUT;
138 *op_flags &= ~RTE_BBDEV_TURBO_POS_LLR_1_BIT_SOFT_OUT;
139 *op_flags &= ~RTE_BBDEV_TURBO_NEG_LLR_1_BIT_SOFT_OUT;
143 check_dev_cap(const struct rte_bbdev_info *dev_info)
146 unsigned int nb_inputs, nb_soft_outputs, nb_hard_outputs;
147 const struct rte_bbdev_op_cap *op_cap = dev_info->drv.capabilities;
149 nb_inputs = test_vector.entries[DATA_INPUT].nb_segments;
150 nb_soft_outputs = test_vector.entries[DATA_SOFT_OUTPUT].nb_segments;
151 nb_hard_outputs = test_vector.entries[DATA_HARD_OUTPUT].nb_segments;
153 for (i = 0; op_cap->type != RTE_BBDEV_OP_NONE; ++i, ++op_cap) {
154 if (op_cap->type != test_vector.op_type)
157 if (op_cap->type == RTE_BBDEV_OP_TURBO_DEC) {
158 const struct rte_bbdev_op_cap_turbo_dec *cap =
159 &op_cap->cap.turbo_dec;
160 /* Ignore lack of soft output capability, just skip
161 * checking if soft output is valid.
163 if ((test_vector.turbo_dec.op_flags &
164 RTE_BBDEV_TURBO_SOFT_OUTPUT) &&
165 !(cap->capability_flags &
166 RTE_BBDEV_TURBO_SOFT_OUTPUT)) {
168 "WARNING: Device \"%s\" does not support soft output - soft output flags will be ignored.\n",
171 &test_vector.turbo_dec.op_flags);
174 if (!flags_match(test_vector.turbo_dec.op_flags,
175 cap->capability_flags))
177 if (nb_inputs > cap->num_buffers_src) {
178 printf("Too many inputs defined: %u, max: %u\n",
179 nb_inputs, cap->num_buffers_src);
182 if (nb_soft_outputs > cap->num_buffers_soft_out &&
183 (test_vector.turbo_dec.op_flags &
184 RTE_BBDEV_TURBO_SOFT_OUTPUT)) {
186 "Too many soft outputs defined: %u, max: %u\n",
188 cap->num_buffers_soft_out);
191 if (nb_hard_outputs > cap->num_buffers_hard_out) {
193 "Too many hard outputs defined: %u, max: %u\n",
195 cap->num_buffers_hard_out);
198 if (intr_enabled && !(cap->capability_flags &
199 RTE_BBDEV_TURBO_DEC_INTERRUPTS)) {
201 "Dequeue interrupts are not supported!\n");
206 } else if (op_cap->type == RTE_BBDEV_OP_TURBO_ENC) {
207 const struct rte_bbdev_op_cap_turbo_enc *cap =
208 &op_cap->cap.turbo_enc;
210 if (!flags_match(test_vector.turbo_enc.op_flags,
211 cap->capability_flags))
213 if (nb_inputs > cap->num_buffers_src) {
214 printf("Too many inputs defined: %u, max: %u\n",
215 nb_inputs, cap->num_buffers_src);
218 if (nb_hard_outputs > cap->num_buffers_dst) {
220 "Too many hard outputs defined: %u, max: %u\n",
221 nb_hard_outputs, cap->num_buffers_src);
224 if (intr_enabled && !(cap->capability_flags &
225 RTE_BBDEV_TURBO_ENC_INTERRUPTS)) {
227 "Dequeue interrupts are not supported!\n");
235 if ((i == 0) && (test_vector.op_type == RTE_BBDEV_OP_NONE))
236 return TEST_SUCCESS; /* Special case for NULL device */
241 /* calculates optimal mempool size not smaller than the val */
243 optimal_mempool_size(unsigned int val)
245 return rte_align32pow2(val + 1) - 1;
248 /* allocates mbuf mempool for inputs and outputs */
249 static struct rte_mempool *
250 create_mbuf_pool(struct op_data_entries *entries, uint8_t dev_id,
251 int socket_id, unsigned int mbuf_pool_size,
252 const char *op_type_str)
255 uint32_t max_seg_sz = 0;
256 char pool_name[RTE_MEMPOOL_NAMESIZE];
258 /* find max input segment size */
259 for (i = 0; i < entries->nb_segments; ++i)
260 if (entries->segments[i].length > max_seg_sz)
261 max_seg_sz = entries->segments[i].length;
263 snprintf(pool_name, sizeof(pool_name), "%s_pool_%u", op_type_str,
265 return rte_pktmbuf_pool_create(pool_name, mbuf_pool_size, 0, 0,
266 RTE_MAX(max_seg_sz + RTE_PKTMBUF_HEADROOM,
267 (unsigned int)RTE_MBUF_DEFAULT_BUF_SIZE), socket_id);
271 create_mempools(struct active_device *ad, int socket_id,
272 enum rte_bbdev_op_type org_op_type, uint16_t num_ops)
274 struct rte_mempool *mp;
275 unsigned int ops_pool_size, mbuf_pool_size = 0;
276 char pool_name[RTE_MEMPOOL_NAMESIZE];
277 const char *op_type_str;
278 enum rte_bbdev_op_type op_type = org_op_type;
280 struct op_data_entries *in = &test_vector.entries[DATA_INPUT];
281 struct op_data_entries *hard_out =
282 &test_vector.entries[DATA_HARD_OUTPUT];
283 struct op_data_entries *soft_out =
284 &test_vector.entries[DATA_SOFT_OUTPUT];
286 /* allocate ops mempool */
287 ops_pool_size = optimal_mempool_size(RTE_MAX(
288 /* Ops used plus 1 reference op */
289 RTE_MAX((unsigned int)(ad->nb_queues * num_ops + 1),
290 /* Minimal cache size plus 1 reference op */
291 (unsigned int)(1.5 * rte_lcore_count() *
292 OPS_CACHE_SIZE + 1)),
295 if (org_op_type == RTE_BBDEV_OP_NONE)
296 op_type = RTE_BBDEV_OP_TURBO_ENC;
298 op_type_str = rte_bbdev_op_type_str(op_type);
299 TEST_ASSERT_NOT_NULL(op_type_str, "Invalid op type: %u", op_type);
301 snprintf(pool_name, sizeof(pool_name), "%s_pool_%u", op_type_str,
303 mp = rte_bbdev_op_pool_create(pool_name, op_type,
304 ops_pool_size, OPS_CACHE_SIZE, socket_id);
305 TEST_ASSERT_NOT_NULL(mp,
306 "ERROR Failed to create %u items ops pool for dev %u on socket %u.",
310 ad->ops_mempool = mp;
312 /* Do not create inputs and outputs mbufs for BaseBand Null Device */
313 if (org_op_type == RTE_BBDEV_OP_NONE)
317 mbuf_pool_size = optimal_mempool_size(ops_pool_size * in->nb_segments);
318 mp = create_mbuf_pool(in, ad->dev_id, socket_id, mbuf_pool_size, "in");
319 TEST_ASSERT_NOT_NULL(mp,
320 "ERROR Failed to create %u items input pktmbuf pool for dev %u on socket %u.",
324 ad->in_mbuf_pool = mp;
327 mbuf_pool_size = optimal_mempool_size(ops_pool_size *
328 hard_out->nb_segments);
329 mp = create_mbuf_pool(hard_out, ad->dev_id, socket_id, mbuf_pool_size,
331 TEST_ASSERT_NOT_NULL(mp,
332 "ERROR Failed to create %u items hard output pktmbuf pool for dev %u on socket %u.",
336 ad->hard_out_mbuf_pool = mp;
338 if (soft_out->nb_segments == 0)
342 mbuf_pool_size = optimal_mempool_size(ops_pool_size *
343 soft_out->nb_segments);
344 mp = create_mbuf_pool(soft_out, ad->dev_id, socket_id, mbuf_pool_size,
346 TEST_ASSERT_NOT_NULL(mp,
347 "ERROR Failed to create %uB soft output pktmbuf pool for dev %u on socket %u.",
351 ad->soft_out_mbuf_pool = mp;
357 add_bbdev_dev(uint8_t dev_id, struct rte_bbdev_info *info,
358 struct test_bbdev_vector *vector)
361 unsigned int queue_id;
362 struct rte_bbdev_queue_conf qconf;
363 struct active_device *ad = &active_devs[nb_active_devs];
364 unsigned int nb_queues;
365 enum rte_bbdev_op_type op_type = vector->op_type;
367 nb_queues = RTE_MIN(rte_lcore_count(), info->drv.max_num_queues);
369 ret = rte_bbdev_setup_queues(dev_id, nb_queues, info->socket_id);
371 printf("rte_bbdev_setup_queues(%u, %u, %d) ret %i\n",
372 dev_id, nb_queues, info->socket_id, ret);
376 /* configure interrupts if needed */
378 ret = rte_bbdev_intr_enable(dev_id);
380 printf("rte_bbdev_intr_enable(%u) ret %i\n", dev_id,
386 /* setup device queues */
387 qconf.socket = info->socket_id;
388 qconf.queue_size = info->drv.default_queue_conf.queue_size;
390 qconf.deferred_start = 0;
391 qconf.op_type = op_type;
393 for (queue_id = 0; queue_id < nb_queues; ++queue_id) {
394 ret = rte_bbdev_queue_configure(dev_id, queue_id, &qconf);
397 "Allocated all queues (id=%u) at prio%u on dev%u\n",
398 queue_id, qconf.priority, dev_id);
400 ret = rte_bbdev_queue_configure(ad->dev_id, queue_id,
404 printf("All queues on dev %u allocated: %u\n",
408 ad->queue_ids[queue_id] = queue_id;
410 TEST_ASSERT(queue_id != 0,
411 "ERROR Failed to configure any queues on dev %u",
413 ad->nb_queues = queue_id;
415 set_avail_op(ad, op_type);
421 add_active_device(uint8_t dev_id, struct rte_bbdev_info *info,
422 struct test_bbdev_vector *vector)
426 active_devs[nb_active_devs].driver_name = info->drv.driver_name;
427 active_devs[nb_active_devs].dev_id = dev_id;
429 ret = add_bbdev_dev(dev_id, info, vector);
430 if (ret == TEST_SUCCESS)
436 populate_active_devices(void)
440 uint8_t nb_devs_added = 0;
441 struct rte_bbdev_info info;
443 RTE_BBDEV_FOREACH(dev_id) {
444 rte_bbdev_info_get(dev_id, &info);
446 if (check_dev_cap(&info)) {
448 "Device %d (%s) does not support specified capabilities\n",
449 dev_id, info.dev_name);
453 ret = add_active_device(dev_id, &info, &test_vector);
455 printf("Adding active bbdev %s skipped\n",
462 return nb_devs_added;
466 read_test_vector(void)
470 memset(&test_vector, 0, sizeof(test_vector));
471 printf("Test vector file = %s\n", get_vector_filename());
472 ret = test_bbdev_vector_read(get_vector_filename(), &test_vector);
473 TEST_ASSERT_SUCCESS(ret, "Failed to parse file %s\n",
474 get_vector_filename());
480 testsuite_setup(void)
482 TEST_ASSERT_SUCCESS(read_test_vector(), "Test suite setup failed\n");
484 if (populate_active_devices() == 0) {
485 printf("No suitable devices found!\n");
493 interrupt_testsuite_setup(void)
495 TEST_ASSERT_SUCCESS(read_test_vector(), "Test suite setup failed\n");
497 /* Enable interrupts */
500 /* Special case for NULL device (RTE_BBDEV_OP_NONE) */
501 if (populate_active_devices() == 0 ||
502 test_vector.op_type == RTE_BBDEV_OP_NONE) {
503 intr_enabled = false;
504 printf("No suitable devices found!\n");
512 testsuite_teardown(void)
516 /* Unconfigure devices */
517 RTE_BBDEV_FOREACH(dev_id)
518 rte_bbdev_close(dev_id);
520 /* Clear active devices structs. */
521 memset(active_devs, 0, sizeof(active_devs));
530 for (i = 0; i < nb_active_devs; i++) {
531 dev_id = active_devs[i].dev_id;
532 /* reset bbdev stats */
533 TEST_ASSERT_SUCCESS(rte_bbdev_stats_reset(dev_id),
534 "Failed to reset stats of bbdev %u", dev_id);
535 /* start the device */
536 TEST_ASSERT_SUCCESS(rte_bbdev_start(dev_id),
537 "Failed to start bbdev %u", dev_id);
547 struct rte_bbdev_stats stats;
549 for (i = 0; i < nb_active_devs; i++) {
550 dev_id = active_devs[i].dev_id;
551 /* read stats and print */
552 rte_bbdev_stats_get(dev_id, &stats);
553 /* Stop the device */
554 rte_bbdev_stop(dev_id);
559 init_op_data_objs(struct rte_bbdev_op_data *bufs,
560 struct op_data_entries *ref_entries,
561 struct rte_mempool *mbuf_pool, const uint16_t n,
562 enum op_data_type op_type, uint16_t min_alignment)
567 for (i = 0; i < n; ++i) {
569 struct op_data_buf *seg = &ref_entries->segments[0];
570 struct rte_mbuf *m_head = rte_pktmbuf_alloc(mbuf_pool);
571 TEST_ASSERT_NOT_NULL(m_head,
572 "Not enough mbufs in %d data type mbuf pool (needed %u, available %u)",
573 op_type, n * ref_entries->nb_segments,
576 bufs[i].data = m_head;
580 if (op_type == DATA_INPUT) {
581 data = rte_pktmbuf_append(m_head, seg->length);
582 TEST_ASSERT_NOT_NULL(data,
583 "Couldn't append %u bytes to mbuf from %d data type mbuf pool",
584 seg->length, op_type);
586 TEST_ASSERT(data == RTE_PTR_ALIGN(data, min_alignment),
587 "Data addr in mbuf (%p) is not aligned to device min alignment (%u)",
588 data, min_alignment);
589 rte_memcpy(data, seg->addr, seg->length);
590 bufs[i].length += seg->length;
593 for (j = 1; j < ref_entries->nb_segments; ++j) {
594 struct rte_mbuf *m_tail =
595 rte_pktmbuf_alloc(mbuf_pool);
596 TEST_ASSERT_NOT_NULL(m_tail,
597 "Not enough mbufs in %d data type mbuf pool (needed %u, available %u)",
599 n * ref_entries->nb_segments,
603 data = rte_pktmbuf_append(m_tail, seg->length);
604 TEST_ASSERT_NOT_NULL(data,
605 "Couldn't append %u bytes to mbuf from %d data type mbuf pool",
606 seg->length, op_type);
608 TEST_ASSERT(data == RTE_PTR_ALIGN(data,
610 "Data addr in mbuf (%p) is not aligned to device min alignment (%u)",
611 data, min_alignment);
612 rte_memcpy(data, seg->addr, seg->length);
613 bufs[i].length += seg->length;
615 ret = rte_pktmbuf_chain(m_head, m_tail);
616 TEST_ASSERT_SUCCESS(ret,
617 "Couldn't chain mbufs from %d data type mbuf pool",
627 allocate_buffers_on_socket(struct rte_bbdev_op_data **buffers, const int len,
632 *buffers = rte_zmalloc_socket(NULL, len, 0, socket);
633 if (*buffers == NULL) {
634 printf("WARNING: Failed to allocate op_data on socket %d\n",
636 /* try to allocate memory on other detected sockets */
637 for (i = 0; i < socket; i++) {
638 *buffers = rte_zmalloc_socket(NULL, len, 0, i);
639 if (*buffers != NULL)
644 return (*buffers == NULL) ? TEST_FAILED : TEST_SUCCESS;
648 limit_input_llr_val_range(struct rte_bbdev_op_data *input_ops,
649 uint16_t n, int8_t max_llr_modulus)
651 uint16_t i, byte_idx;
653 for (i = 0; i < n; ++i) {
654 struct rte_mbuf *m = input_ops[i].data;
656 int8_t *llr = rte_pktmbuf_mtod_offset(m, int8_t *,
657 input_ops[i].offset);
658 for (byte_idx = 0; byte_idx < input_ops[i].length;
660 llr[byte_idx] = round((double)max_llr_modulus *
661 llr[byte_idx] / INT8_MAX);
669 fill_queue_buffers(struct test_op_params *op_params,
670 struct rte_mempool *in_mp, struct rte_mempool *hard_out_mp,
671 struct rte_mempool *soft_out_mp, uint16_t queue_id,
672 const struct rte_bbdev_op_cap *capabilities,
673 uint16_t min_alignment, const int socket_id)
676 enum op_data_type type;
677 const uint16_t n = op_params->num_to_process;
679 struct rte_mempool *mbuf_pools[DATA_NUM_TYPES] = {
685 struct rte_bbdev_op_data **queue_ops[DATA_NUM_TYPES] = {
686 &op_params->q_bufs[socket_id][queue_id].inputs,
687 &op_params->q_bufs[socket_id][queue_id].soft_outputs,
688 &op_params->q_bufs[socket_id][queue_id].hard_outputs,
691 for (type = DATA_INPUT; type < DATA_NUM_TYPES; ++type) {
692 struct op_data_entries *ref_entries =
693 &test_vector.entries[type];
694 if (ref_entries->nb_segments == 0)
697 ret = allocate_buffers_on_socket(queue_ops[type],
698 n * sizeof(struct rte_bbdev_op_data),
700 TEST_ASSERT_SUCCESS(ret,
701 "Couldn't allocate memory for rte_bbdev_op_data structs");
703 ret = init_op_data_objs(*queue_ops[type], ref_entries,
704 mbuf_pools[type], n, type, min_alignment);
705 TEST_ASSERT_SUCCESS(ret,
706 "Couldn't init rte_bbdev_op_data structs");
709 if (test_vector.op_type == RTE_BBDEV_OP_TURBO_DEC)
710 limit_input_llr_val_range(*queue_ops[DATA_INPUT], n,
711 capabilities->cap.turbo_dec.max_llr_modulus);
717 free_buffers(struct active_device *ad, struct test_op_params *op_params)
721 rte_mempool_free(ad->ops_mempool);
722 rte_mempool_free(ad->in_mbuf_pool);
723 rte_mempool_free(ad->hard_out_mbuf_pool);
724 rte_mempool_free(ad->soft_out_mbuf_pool);
726 for (i = 0; i < rte_lcore_count(); ++i) {
727 for (j = 0; j < RTE_MAX_NUMA_NODES; ++j) {
728 rte_free(op_params->q_bufs[j][i].inputs);
729 rte_free(op_params->q_bufs[j][i].hard_outputs);
730 rte_free(op_params->q_bufs[j][i].soft_outputs);
736 copy_reference_dec_op(struct rte_bbdev_dec_op **ops, unsigned int n,
737 unsigned int start_idx,
738 struct rte_bbdev_op_data *inputs,
739 struct rte_bbdev_op_data *hard_outputs,
740 struct rte_bbdev_op_data *soft_outputs,
741 struct rte_bbdev_dec_op *ref_op)
744 struct rte_bbdev_op_turbo_dec *turbo_dec = &ref_op->turbo_dec;
746 for (i = 0; i < n; ++i) {
747 if (turbo_dec->code_block_mode == 0) {
748 ops[i]->turbo_dec.tb_params.ea =
749 turbo_dec->tb_params.ea;
750 ops[i]->turbo_dec.tb_params.eb =
751 turbo_dec->tb_params.eb;
752 ops[i]->turbo_dec.tb_params.k_pos =
753 turbo_dec->tb_params.k_pos;
754 ops[i]->turbo_dec.tb_params.k_neg =
755 turbo_dec->tb_params.k_neg;
756 ops[i]->turbo_dec.tb_params.c =
757 turbo_dec->tb_params.c;
758 ops[i]->turbo_dec.tb_params.c_neg =
759 turbo_dec->tb_params.c_neg;
760 ops[i]->turbo_dec.tb_params.cab =
761 turbo_dec->tb_params.cab;
762 ops[i]->turbo_dec.tb_params.r =
763 turbo_dec->tb_params.r;
765 ops[i]->turbo_dec.cb_params.e = turbo_dec->cb_params.e;
766 ops[i]->turbo_dec.cb_params.k = turbo_dec->cb_params.k;
769 ops[i]->turbo_dec.ext_scale = turbo_dec->ext_scale;
770 ops[i]->turbo_dec.iter_max = turbo_dec->iter_max;
771 ops[i]->turbo_dec.iter_min = turbo_dec->iter_min;
772 ops[i]->turbo_dec.op_flags = turbo_dec->op_flags;
773 ops[i]->turbo_dec.rv_index = turbo_dec->rv_index;
774 ops[i]->turbo_dec.num_maps = turbo_dec->num_maps;
775 ops[i]->turbo_dec.code_block_mode = turbo_dec->code_block_mode;
777 ops[i]->turbo_dec.hard_output = hard_outputs[start_idx + i];
778 ops[i]->turbo_dec.input = inputs[start_idx + i];
779 if (soft_outputs != NULL)
780 ops[i]->turbo_dec.soft_output =
781 soft_outputs[start_idx + i];
786 copy_reference_enc_op(struct rte_bbdev_enc_op **ops, unsigned int n,
787 unsigned int start_idx,
788 struct rte_bbdev_op_data *inputs,
789 struct rte_bbdev_op_data *outputs,
790 struct rte_bbdev_enc_op *ref_op)
793 struct rte_bbdev_op_turbo_enc *turbo_enc = &ref_op->turbo_enc;
794 for (i = 0; i < n; ++i) {
795 if (turbo_enc->code_block_mode == 0) {
796 ops[i]->turbo_enc.tb_params.ea =
797 turbo_enc->tb_params.ea;
798 ops[i]->turbo_enc.tb_params.eb =
799 turbo_enc->tb_params.eb;
800 ops[i]->turbo_enc.tb_params.k_pos =
801 turbo_enc->tb_params.k_pos;
802 ops[i]->turbo_enc.tb_params.k_neg =
803 turbo_enc->tb_params.k_neg;
804 ops[i]->turbo_enc.tb_params.c =
805 turbo_enc->tb_params.c;
806 ops[i]->turbo_enc.tb_params.c_neg =
807 turbo_enc->tb_params.c_neg;
808 ops[i]->turbo_enc.tb_params.cab =
809 turbo_enc->tb_params.cab;
810 ops[i]->turbo_enc.tb_params.ncb_pos =
811 turbo_enc->tb_params.ncb_pos;
812 ops[i]->turbo_enc.tb_params.ncb_neg =
813 turbo_enc->tb_params.ncb_neg;
814 ops[i]->turbo_enc.tb_params.r = turbo_enc->tb_params.r;
816 ops[i]->turbo_enc.cb_params.e = turbo_enc->cb_params.e;
817 ops[i]->turbo_enc.cb_params.k = turbo_enc->cb_params.k;
818 ops[i]->turbo_enc.cb_params.ncb =
819 turbo_enc->cb_params.ncb;
821 ops[i]->turbo_enc.rv_index = turbo_enc->rv_index;
822 ops[i]->turbo_enc.op_flags = turbo_enc->op_flags;
823 ops[i]->turbo_enc.code_block_mode = turbo_enc->code_block_mode;
825 ops[i]->turbo_enc.output = outputs[start_idx + i];
826 ops[i]->turbo_enc.input = inputs[start_idx + i];
831 check_dec_status_and_ordering(struct rte_bbdev_dec_op *op,
832 unsigned int order_idx, const int expected_status)
834 TEST_ASSERT(op->status == expected_status,
835 "op_status (%d) != expected_status (%d)",
836 op->status, expected_status);
838 TEST_ASSERT((void *)(uintptr_t)order_idx == op->opaque_data,
839 "Ordering error, expected %p, got %p",
840 (void *)(uintptr_t)order_idx, op->opaque_data);
846 check_enc_status_and_ordering(struct rte_bbdev_enc_op *op,
847 unsigned int order_idx, const int expected_status)
849 TEST_ASSERT(op->status == expected_status,
850 "op_status (%d) != expected_status (%d)",
851 op->status, expected_status);
853 TEST_ASSERT((void *)(uintptr_t)order_idx == op->opaque_data,
854 "Ordering error, expected %p, got %p",
855 (void *)(uintptr_t)order_idx, op->opaque_data);
861 validate_op_chain(struct rte_bbdev_op_data *op,
862 struct op_data_entries *orig_op)
865 struct rte_mbuf *m = op->data;
866 uint8_t nb_dst_segments = orig_op->nb_segments;
868 TEST_ASSERT(nb_dst_segments == m->nb_segs,
869 "Number of segments differ in original (%u) and filled (%u) op",
870 nb_dst_segments, m->nb_segs);
872 for (i = 0; i < nb_dst_segments; ++i) {
873 /* Apply offset to the first mbuf segment */
874 uint16_t offset = (i == 0) ? op->offset : 0;
875 uint16_t data_len = m->data_len - offset;
877 TEST_ASSERT(orig_op->segments[i].length == data_len,
878 "Length of segment differ in original (%u) and filled (%u) op",
879 orig_op->segments[i].length, data_len);
880 TEST_ASSERT_BUFFERS_ARE_EQUAL(orig_op->segments[i].addr,
881 rte_pktmbuf_mtod_offset(m, uint32_t *, offset),
883 "Output buffers (CB=%u) are not equal", i);
891 validate_dec_op(struct rte_bbdev_dec_op **ops, const uint16_t n,
892 struct rte_bbdev_dec_op *ref_op, const int vector_mask)
896 struct op_data_entries *hard_data_orig =
897 &test_vector.entries[DATA_HARD_OUTPUT];
898 struct op_data_entries *soft_data_orig =
899 &test_vector.entries[DATA_SOFT_OUTPUT];
900 struct rte_bbdev_op_turbo_dec *ops_td;
901 struct rte_bbdev_op_data *hard_output;
902 struct rte_bbdev_op_data *soft_output;
903 struct rte_bbdev_op_turbo_dec *ref_td = &ref_op->turbo_dec;
905 for (i = 0; i < n; ++i) {
906 ops_td = &ops[i]->turbo_dec;
907 hard_output = &ops_td->hard_output;
908 soft_output = &ops_td->soft_output;
910 if (vector_mask & TEST_BBDEV_VF_EXPECTED_ITER_COUNT)
911 TEST_ASSERT(ops_td->iter_count <= ref_td->iter_count,
912 "Returned iter_count (%d) > expected iter_count (%d)",
913 ops_td->iter_count, ref_td->iter_count);
914 ret = check_dec_status_and_ordering(ops[i], i, ref_op->status);
915 TEST_ASSERT_SUCCESS(ret,
916 "Checking status and ordering for decoder failed");
918 TEST_ASSERT_SUCCESS(validate_op_chain(hard_output,
920 "Hard output buffers (CB=%u) are not equal",
923 if (ref_op->turbo_dec.op_flags & RTE_BBDEV_TURBO_SOFT_OUTPUT)
924 TEST_ASSERT_SUCCESS(validate_op_chain(soft_output,
926 "Soft output buffers (CB=%u) are not equal",
934 validate_enc_op(struct rte_bbdev_enc_op **ops, const uint16_t n,
935 struct rte_bbdev_enc_op *ref_op)
939 struct op_data_entries *hard_data_orig =
940 &test_vector.entries[DATA_HARD_OUTPUT];
942 for (i = 0; i < n; ++i) {
943 ret = check_enc_status_and_ordering(ops[i], i, ref_op->status);
944 TEST_ASSERT_SUCCESS(ret,
945 "Checking status and ordering for encoder failed");
946 TEST_ASSERT_SUCCESS(validate_op_chain(
947 &ops[i]->turbo_enc.output,
949 "Output buffers (CB=%u) are not equal",
957 create_reference_dec_op(struct rte_bbdev_dec_op *op)
960 struct op_data_entries *entry;
962 op->turbo_dec = test_vector.turbo_dec;
963 entry = &test_vector.entries[DATA_INPUT];
964 for (i = 0; i < entry->nb_segments; ++i)
965 op->turbo_dec.input.length +=
966 entry->segments[i].length;
970 create_reference_enc_op(struct rte_bbdev_enc_op *op)
973 struct op_data_entries *entry;
975 op->turbo_enc = test_vector.turbo_enc;
976 entry = &test_vector.entries[DATA_INPUT];
977 for (i = 0; i < entry->nb_segments; ++i)
978 op->turbo_enc.input.length +=
979 entry->segments[i].length;
983 calc_dec_TB_size(struct rte_bbdev_dec_op *op)
986 uint32_t c, r, tb_size = 0;
988 if (op->turbo_dec.code_block_mode) {
989 tb_size = op->turbo_dec.tb_params.k_neg;
991 c = op->turbo_dec.tb_params.c;
992 r = op->turbo_dec.tb_params.r;
993 for (i = 0; i < c-r; i++)
994 tb_size += (r < op->turbo_dec.tb_params.c_neg) ?
995 op->turbo_dec.tb_params.k_neg :
996 op->turbo_dec.tb_params.k_pos;
1002 calc_enc_TB_size(struct rte_bbdev_enc_op *op)
1005 uint32_t c, r, tb_size = 0;
1007 if (op->turbo_enc.code_block_mode) {
1008 tb_size = op->turbo_enc.tb_params.k_neg;
1010 c = op->turbo_enc.tb_params.c;
1011 r = op->turbo_enc.tb_params.r;
1012 for (i = 0; i < c-r; i++)
1013 tb_size += (r < op->turbo_enc.tb_params.c_neg) ?
1014 op->turbo_enc.tb_params.k_neg :
1015 op->turbo_enc.tb_params.k_pos;
1021 init_test_op_params(struct test_op_params *op_params,
1022 enum rte_bbdev_op_type op_type, const int expected_status,
1023 const int vector_mask, struct rte_mempool *ops_mp,
1024 uint16_t burst_sz, uint16_t num_to_process, uint16_t num_lcores)
1027 if (op_type == RTE_BBDEV_OP_TURBO_DEC)
1028 ret = rte_bbdev_dec_op_alloc_bulk(ops_mp,
1029 &op_params->ref_dec_op, 1);
1031 ret = rte_bbdev_enc_op_alloc_bulk(ops_mp,
1032 &op_params->ref_enc_op, 1);
1034 TEST_ASSERT_SUCCESS(ret, "rte_bbdev_op_alloc_bulk() failed");
1036 op_params->mp = ops_mp;
1037 op_params->burst_sz = burst_sz;
1038 op_params->num_to_process = num_to_process;
1039 op_params->num_lcores = num_lcores;
1040 op_params->vector_mask = vector_mask;
1041 if (op_type == RTE_BBDEV_OP_TURBO_DEC)
1042 op_params->ref_dec_op->status = expected_status;
1043 else if (op_type == RTE_BBDEV_OP_TURBO_ENC)
1044 op_params->ref_enc_op->status = expected_status;
1050 run_test_case_on_device(test_case_function *test_case_func, uint8_t dev_id,
1051 struct test_op_params *op_params)
1053 int t_ret, f_ret, socket_id = SOCKET_ID_ANY;
1055 struct active_device *ad;
1056 unsigned int burst_sz = get_burst_sz();
1057 enum rte_bbdev_op_type op_type = test_vector.op_type;
1058 const struct rte_bbdev_op_cap *capabilities = NULL;
1060 ad = &active_devs[dev_id];
1062 /* Check if device supports op_type */
1063 if (!is_avail_op(ad, test_vector.op_type))
1064 return TEST_SUCCESS;
1066 struct rte_bbdev_info info;
1067 rte_bbdev_info_get(ad->dev_id, &info);
1068 socket_id = GET_SOCKET(info.socket_id);
1070 f_ret = create_mempools(ad, socket_id, op_type,
1072 if (f_ret != TEST_SUCCESS) {
1073 printf("Couldn't create mempools");
1076 if (op_type == RTE_BBDEV_OP_NONE)
1077 op_type = RTE_BBDEV_OP_TURBO_ENC;
1079 f_ret = init_test_op_params(op_params, test_vector.op_type,
1080 test_vector.expected_status,
1086 if (f_ret != TEST_SUCCESS) {
1087 printf("Couldn't init test op params");
1091 if (test_vector.op_type == RTE_BBDEV_OP_TURBO_DEC) {
1092 /* Find Decoder capabilities */
1093 const struct rte_bbdev_op_cap *cap = info.drv.capabilities;
1094 while (cap->type != RTE_BBDEV_OP_NONE) {
1095 if (cap->type == RTE_BBDEV_OP_TURBO_DEC) {
1100 TEST_ASSERT_NOT_NULL(capabilities,
1101 "Couldn't find Decoder capabilities");
1103 create_reference_dec_op(op_params->ref_dec_op);
1104 } else if (test_vector.op_type == RTE_BBDEV_OP_TURBO_ENC)
1105 create_reference_enc_op(op_params->ref_enc_op);
1107 for (i = 0; i < ad->nb_queues; ++i) {
1108 f_ret = fill_queue_buffers(op_params,
1110 ad->hard_out_mbuf_pool,
1111 ad->soft_out_mbuf_pool,
1114 info.drv.min_alignment,
1116 if (f_ret != TEST_SUCCESS) {
1117 printf("Couldn't init queue buffers");
1122 /* Run test case function */
1123 t_ret = test_case_func(ad, op_params);
1125 /* Free active device resources and return */
1126 free_buffers(ad, op_params);
1130 free_buffers(ad, op_params);
1134 /* Run given test function per active device per supported op type
1138 run_test_case(test_case_function *test_case_func)
1143 /* Alloc op_params */
1144 struct test_op_params *op_params = rte_zmalloc(NULL,
1145 sizeof(struct test_op_params), RTE_CACHE_LINE_SIZE);
1146 TEST_ASSERT_NOT_NULL(op_params, "Failed to alloc %zuB for op_params",
1147 RTE_ALIGN(sizeof(struct test_op_params),
1148 RTE_CACHE_LINE_SIZE));
1150 /* For each device run test case function */
1151 for (dev = 0; dev < nb_active_devs; ++dev)
1152 ret |= run_test_case_on_device(test_case_func, dev, op_params);
1154 rte_free(op_params);
1160 dequeue_event_callback(uint16_t dev_id,
1161 enum rte_bbdev_event_type event, void *cb_arg,
1166 uint64_t total_time;
1167 uint16_t deq, burst_sz, num_ops;
1168 uint16_t queue_id = INVALID_QUEUE_ID;
1169 struct rte_bbdev_dec_op *dec_ops[MAX_BURST];
1170 struct rte_bbdev_enc_op *enc_ops[MAX_BURST];
1171 struct rte_bbdev_info info;
1175 struct thread_params *tp = cb_arg;
1176 RTE_SET_USED(ret_param);
1177 queue_id = tp->queue_id;
1179 /* Find matching thread params using queue_id */
1180 for (i = 0; i < MAX_QUEUES; ++i, ++tp)
1181 if (tp->queue_id == queue_id)
1184 if (i == MAX_QUEUES) {
1185 printf("%s: Queue_id from interrupt details was not found!\n",
1190 if (unlikely(event != RTE_BBDEV_EVENT_DEQUEUE)) {
1191 rte_atomic16_set(&tp->processing_status, TEST_FAILED);
1193 "Dequeue interrupt handler called for incorrect event!\n");
1197 burst_sz = tp->op_params->burst_sz;
1198 num_ops = tp->op_params->num_to_process;
1200 if (test_vector.op_type == RTE_BBDEV_OP_TURBO_DEC) {
1201 deq = rte_bbdev_dequeue_dec_ops(dev_id, queue_id, dec_ops,
1203 rte_bbdev_dec_op_free_bulk(dec_ops, deq);
1205 deq = rte_bbdev_dequeue_enc_ops(dev_id, queue_id, enc_ops,
1207 rte_bbdev_enc_op_free_bulk(enc_ops, deq);
1210 if (deq < burst_sz) {
1212 "After receiving the interrupt all operations should be dequeued. Expected: %u, got: %u\n",
1214 rte_atomic16_set(&tp->processing_status, TEST_FAILED);
1218 if (rte_atomic16_read(&tp->nb_dequeued) + deq < num_ops) {
1219 rte_atomic16_add(&tp->nb_dequeued, deq);
1223 total_time = rte_rdtsc_precise() - tp->start_time;
1225 rte_bbdev_info_get(dev_id, &info);
1229 if (test_vector.op_type == RTE_BBDEV_OP_TURBO_DEC) {
1230 struct rte_bbdev_dec_op *ref_op = tp->op_params->ref_dec_op;
1231 ret = validate_dec_op(dec_ops, num_ops, ref_op,
1232 tp->op_params->vector_mask);
1233 rte_bbdev_dec_op_free_bulk(dec_ops, deq);
1234 } else if (test_vector.op_type == RTE_BBDEV_OP_TURBO_ENC) {
1235 struct rte_bbdev_enc_op *ref_op = tp->op_params->ref_enc_op;
1236 ret = validate_enc_op(enc_ops, num_ops, ref_op);
1237 rte_bbdev_enc_op_free_bulk(enc_ops, deq);
1241 printf("Buffers validation failed\n");
1242 rte_atomic16_set(&tp->processing_status, TEST_FAILED);
1245 switch (test_vector.op_type) {
1246 case RTE_BBDEV_OP_TURBO_DEC:
1247 tb_len_bits = calc_dec_TB_size(tp->op_params->ref_dec_op);
1249 case RTE_BBDEV_OP_TURBO_ENC:
1250 tb_len_bits = calc_enc_TB_size(tp->op_params->ref_enc_op);
1252 case RTE_BBDEV_OP_NONE:
1256 printf("Unknown op type: %d\n", test_vector.op_type);
1257 rte_atomic16_set(&tp->processing_status, TEST_FAILED);
1261 tp->ops_per_sec = ((double)num_ops) /
1262 ((double)total_time / (double)rte_get_tsc_hz());
1263 tp->mbps = (((double)(num_ops * tb_len_bits)) / 1000000.0) /
1264 ((double)total_time / (double)rte_get_tsc_hz());
1266 rte_atomic16_add(&tp->nb_dequeued, deq);
1270 throughput_intr_lcore_dec(void *arg)
1272 struct thread_params *tp = arg;
1273 unsigned int enqueued;
1274 const uint16_t queue_id = tp->queue_id;
1275 const uint16_t burst_sz = tp->op_params->burst_sz;
1276 const uint16_t num_to_process = tp->op_params->num_to_process;
1277 struct rte_bbdev_dec_op *ops[num_to_process];
1278 struct test_buffers *bufs = NULL;
1279 struct rte_bbdev_info info;
1281 uint16_t num_to_enq;
1283 TEST_ASSERT_SUCCESS((burst_sz > MAX_BURST),
1284 "BURST_SIZE should be <= %u", MAX_BURST);
1286 TEST_ASSERT_SUCCESS(rte_bbdev_queue_intr_enable(tp->dev_id, queue_id),
1287 "Failed to enable interrupts for dev: %u, queue_id: %u",
1288 tp->dev_id, queue_id);
1290 rte_bbdev_info_get(tp->dev_id, &info);
1292 TEST_ASSERT_SUCCESS((num_to_process > info.drv.queue_size_lim),
1293 "NUM_OPS cannot exceed %u for this device",
1294 info.drv.queue_size_lim);
1296 bufs = &tp->op_params->q_bufs[GET_SOCKET(info.socket_id)][queue_id];
1298 rte_atomic16_clear(&tp->processing_status);
1299 rte_atomic16_clear(&tp->nb_dequeued);
1301 while (rte_atomic16_read(&tp->op_params->sync) == SYNC_WAIT)
1304 ret = rte_bbdev_dec_op_alloc_bulk(tp->op_params->mp, ops,
1306 TEST_ASSERT_SUCCESS(ret, "Allocation failed for %d ops",
1308 if (test_vector.op_type != RTE_BBDEV_OP_NONE)
1309 copy_reference_dec_op(ops, num_to_process, 0, bufs->inputs,
1310 bufs->hard_outputs, bufs->soft_outputs,
1311 tp->op_params->ref_dec_op);
1313 tp->start_time = rte_rdtsc_precise();
1314 for (enqueued = 0; enqueued < num_to_process;) {
1316 num_to_enq = burst_sz;
1318 if (unlikely(num_to_process - enqueued < num_to_enq))
1319 num_to_enq = num_to_process - enqueued;
1321 enqueued += rte_bbdev_enqueue_dec_ops(tp->dev_id, queue_id,
1322 &ops[enqueued], num_to_enq);
1325 return TEST_SUCCESS;
1329 throughput_intr_lcore_enc(void *arg)
1331 struct thread_params *tp = arg;
1332 unsigned int enqueued;
1333 const uint16_t queue_id = tp->queue_id;
1334 const uint16_t burst_sz = tp->op_params->burst_sz;
1335 const uint16_t num_to_process = tp->op_params->num_to_process;
1336 struct rte_bbdev_enc_op *ops[num_to_process];
1337 struct test_buffers *bufs = NULL;
1338 struct rte_bbdev_info info;
1340 uint16_t num_to_enq;
1342 TEST_ASSERT_SUCCESS((burst_sz > MAX_BURST),
1343 "BURST_SIZE should be <= %u", MAX_BURST);
1345 TEST_ASSERT_SUCCESS(rte_bbdev_queue_intr_enable(tp->dev_id, queue_id),
1346 "Failed to enable interrupts for dev: %u, queue_id: %u",
1347 tp->dev_id, queue_id);
1349 rte_bbdev_info_get(tp->dev_id, &info);
1351 TEST_ASSERT_SUCCESS((num_to_process > info.drv.queue_size_lim),
1352 "NUM_OPS cannot exceed %u for this device",
1353 info.drv.queue_size_lim);
1355 bufs = &tp->op_params->q_bufs[GET_SOCKET(info.socket_id)][queue_id];
1357 rte_atomic16_clear(&tp->processing_status);
1358 rte_atomic16_clear(&tp->nb_dequeued);
1360 while (rte_atomic16_read(&tp->op_params->sync) == SYNC_WAIT)
1363 ret = rte_bbdev_enc_op_alloc_bulk(tp->op_params->mp, ops,
1365 TEST_ASSERT_SUCCESS(ret, "Allocation failed for %d ops",
1367 if (test_vector.op_type != RTE_BBDEV_OP_NONE)
1368 copy_reference_enc_op(ops, num_to_process, 0, bufs->inputs,
1369 bufs->hard_outputs, tp->op_params->ref_enc_op);
1371 tp->start_time = rte_rdtsc_precise();
1372 for (enqueued = 0; enqueued < num_to_process;) {
1374 num_to_enq = burst_sz;
1376 if (unlikely(num_to_process - enqueued < num_to_enq))
1377 num_to_enq = num_to_process - enqueued;
1379 enqueued += rte_bbdev_enqueue_enc_ops(tp->dev_id, queue_id,
1380 &ops[enqueued], num_to_enq);
1383 return TEST_SUCCESS;
1387 throughput_pmd_lcore_dec(void *arg)
1389 struct thread_params *tp = arg;
1391 uint64_t total_time = 0, start_time;
1392 const uint16_t queue_id = tp->queue_id;
1393 const uint16_t burst_sz = tp->op_params->burst_sz;
1394 const uint16_t num_ops = tp->op_params->num_to_process;
1395 struct rte_bbdev_dec_op *ops_enq[num_ops];
1396 struct rte_bbdev_dec_op *ops_deq[num_ops];
1397 struct rte_bbdev_dec_op *ref_op = tp->op_params->ref_dec_op;
1398 struct test_buffers *bufs = NULL;
1400 struct rte_bbdev_info info;
1401 uint16_t num_to_enq;
1403 TEST_ASSERT_SUCCESS((burst_sz > MAX_BURST),
1404 "BURST_SIZE should be <= %u", MAX_BURST);
1406 rte_bbdev_info_get(tp->dev_id, &info);
1408 TEST_ASSERT_SUCCESS((num_ops > info.drv.queue_size_lim),
1409 "NUM_OPS cannot exceed %u for this device",
1410 info.drv.queue_size_lim);
1412 bufs = &tp->op_params->q_bufs[GET_SOCKET(info.socket_id)][queue_id];
1414 while (rte_atomic16_read(&tp->op_params->sync) == SYNC_WAIT)
1417 ret = rte_bbdev_dec_op_alloc_bulk(tp->op_params->mp, ops_enq, num_ops);
1418 TEST_ASSERT_SUCCESS(ret, "Allocation failed for %d ops", num_ops);
1420 if (test_vector.op_type != RTE_BBDEV_OP_NONE)
1421 copy_reference_dec_op(ops_enq, num_ops, 0, bufs->inputs,
1422 bufs->hard_outputs, bufs->soft_outputs, ref_op);
1424 /* Set counter to validate the ordering */
1425 for (j = 0; j < num_ops; ++j)
1426 ops_enq[j]->opaque_data = (void *)(uintptr_t)j;
1428 for (i = 0; i < TEST_REPETITIONS; ++i) {
1430 for (j = 0; j < num_ops; ++j) {
1431 struct rte_bbdev_dec_op *op = ops_enq[j];
1432 rte_pktmbuf_reset(op->turbo_dec.hard_output.data);
1435 start_time = rte_rdtsc_precise();
1437 for (enq = 0, deq = 0; enq < num_ops;) {
1438 num_to_enq = burst_sz;
1440 if (unlikely(num_ops - enq < num_to_enq))
1441 num_to_enq = num_ops - enq;
1443 enq += rte_bbdev_enqueue_dec_ops(tp->dev_id,
1444 queue_id, &ops_enq[enq], num_to_enq);
1446 deq += rte_bbdev_dequeue_dec_ops(tp->dev_id,
1447 queue_id, &ops_deq[deq], enq - deq);
1450 /* dequeue the remaining */
1452 deq += rte_bbdev_dequeue_dec_ops(tp->dev_id,
1453 queue_id, &ops_deq[deq], enq - deq);
1456 total_time += rte_rdtsc_precise() - start_time;
1460 /* get the max of iter_count for all dequeued ops */
1461 for (i = 0; i < num_ops; ++i) {
1462 tp->iter_count = RTE_MAX(ops_enq[i]->turbo_dec.iter_count,
1466 if (test_vector.op_type != RTE_BBDEV_OP_NONE) {
1467 ret = validate_dec_op(ops_deq, num_ops, ref_op,
1468 tp->op_params->vector_mask);
1469 TEST_ASSERT_SUCCESS(ret, "Validation failed!");
1472 rte_bbdev_dec_op_free_bulk(ops_enq, num_ops);
1474 double tb_len_bits = calc_dec_TB_size(ref_op);
1476 tp->ops_per_sec = ((double)num_ops * TEST_REPETITIONS) /
1477 ((double)total_time / (double)rte_get_tsc_hz());
1478 tp->mbps = (((double)(num_ops * TEST_REPETITIONS * tb_len_bits)) /
1479 1000000.0) / ((double)total_time /
1480 (double)rte_get_tsc_hz());
1482 return TEST_SUCCESS;
1486 throughput_pmd_lcore_enc(void *arg)
1488 struct thread_params *tp = arg;
1490 uint64_t total_time = 0, start_time;
1491 const uint16_t queue_id = tp->queue_id;
1492 const uint16_t burst_sz = tp->op_params->burst_sz;
1493 const uint16_t num_ops = tp->op_params->num_to_process;
1494 struct rte_bbdev_enc_op *ops_enq[num_ops];
1495 struct rte_bbdev_enc_op *ops_deq[num_ops];
1496 struct rte_bbdev_enc_op *ref_op = tp->op_params->ref_enc_op;
1497 struct test_buffers *bufs = NULL;
1499 struct rte_bbdev_info info;
1500 uint16_t num_to_enq;
1502 TEST_ASSERT_SUCCESS((burst_sz > MAX_BURST),
1503 "BURST_SIZE should be <= %u", MAX_BURST);
1505 rte_bbdev_info_get(tp->dev_id, &info);
1507 TEST_ASSERT_SUCCESS((num_ops > info.drv.queue_size_lim),
1508 "NUM_OPS cannot exceed %u for this device",
1509 info.drv.queue_size_lim);
1511 bufs = &tp->op_params->q_bufs[GET_SOCKET(info.socket_id)][queue_id];
1513 while (rte_atomic16_read(&tp->op_params->sync) == SYNC_WAIT)
1516 ret = rte_bbdev_enc_op_alloc_bulk(tp->op_params->mp, ops_enq,
1518 TEST_ASSERT_SUCCESS(ret, "Allocation failed for %d ops",
1520 if (test_vector.op_type != RTE_BBDEV_OP_NONE)
1521 copy_reference_enc_op(ops_enq, num_ops, 0, bufs->inputs,
1522 bufs->hard_outputs, ref_op);
1524 /* Set counter to validate the ordering */
1525 for (j = 0; j < num_ops; ++j)
1526 ops_enq[j]->opaque_data = (void *)(uintptr_t)j;
1528 for (i = 0; i < TEST_REPETITIONS; ++i) {
1530 if (test_vector.op_type != RTE_BBDEV_OP_NONE)
1531 for (j = 0; j < num_ops; ++j)
1533 ops_enq[j]->turbo_enc.output.data);
1535 start_time = rte_rdtsc_precise();
1537 for (enq = 0, deq = 0; enq < num_ops;) {
1538 num_to_enq = burst_sz;
1540 if (unlikely(num_ops - enq < num_to_enq))
1541 num_to_enq = num_ops - enq;
1543 enq += rte_bbdev_enqueue_enc_ops(tp->dev_id,
1544 queue_id, &ops_enq[enq], num_to_enq);
1546 deq += rte_bbdev_dequeue_enc_ops(tp->dev_id,
1547 queue_id, &ops_deq[deq], enq - deq);
1550 /* dequeue the remaining */
1552 deq += rte_bbdev_dequeue_enc_ops(tp->dev_id,
1553 queue_id, &ops_deq[deq], enq - deq);
1556 total_time += rte_rdtsc_precise() - start_time;
1559 if (test_vector.op_type != RTE_BBDEV_OP_NONE) {
1560 ret = validate_enc_op(ops_deq, num_ops, ref_op);
1561 TEST_ASSERT_SUCCESS(ret, "Validation failed!");
1564 double tb_len_bits = calc_enc_TB_size(ref_op);
1566 tp->ops_per_sec = ((double)num_ops * TEST_REPETITIONS) /
1567 ((double)total_time / (double)rte_get_tsc_hz());
1568 tp->mbps = (((double)(num_ops * TEST_REPETITIONS * tb_len_bits))
1569 / 1000000.0) / ((double)total_time /
1570 (double)rte_get_tsc_hz());
1572 return TEST_SUCCESS;
1576 print_enc_throughput(struct thread_params *t_params, unsigned int used_cores)
1578 unsigned int lcore_id, iter = 0;
1579 double total_mops = 0, total_mbps = 0;
1581 RTE_LCORE_FOREACH(lcore_id) {
1582 if (iter++ >= used_cores)
1585 "Throughput for core (%u): %.8lg Ops/s, %.8lg Mbps\n",
1586 lcore_id, t_params[lcore_id].ops_per_sec,
1587 t_params[lcore_id].mbps);
1588 total_mops += t_params[lcore_id].ops_per_sec;
1589 total_mbps += t_params[lcore_id].mbps;
1592 "\nTotal throughput for %u cores: %.8lg MOPS, %.8lg Mbps\n",
1593 used_cores, total_mops, total_mbps);
1597 print_dec_throughput(struct thread_params *t_params, unsigned int used_cores)
1599 unsigned int lcore_id, iter = 0;
1600 double total_mops = 0, total_mbps = 0;
1601 uint8_t iter_count = 0;
1603 RTE_LCORE_FOREACH(lcore_id) {
1604 if (iter++ >= used_cores)
1607 "Throughput for core (%u): %.8lg Ops/s, %.8lg Mbps @ max %u iterations\n",
1608 lcore_id, t_params[lcore_id].ops_per_sec,
1609 t_params[lcore_id].mbps,
1610 t_params[lcore_id].iter_count);
1611 total_mops += t_params[lcore_id].ops_per_sec;
1612 total_mbps += t_params[lcore_id].mbps;
1613 iter_count = RTE_MAX(iter_count, t_params[lcore_id].iter_count);
1616 "\nTotal throughput for %u cores: %.8lg MOPS, %.8lg Mbps @ max %u iterations\n",
1617 used_cores, total_mops, total_mbps, iter_count);
1621 * Test function that determines how long an enqueue + dequeue of a burst
1622 * takes on available lcores.
1625 throughput_test(struct active_device *ad,
1626 struct test_op_params *op_params)
1629 unsigned int lcore_id, used_cores = 0;
1630 struct thread_params t_params[MAX_QUEUES];
1631 struct rte_bbdev_info info;
1632 lcore_function_t *throughput_function;
1633 struct thread_params *tp;
1634 uint16_t num_lcores;
1635 const char *op_type_str;
1637 rte_bbdev_info_get(ad->dev_id, &info);
1639 op_type_str = rte_bbdev_op_type_str(test_vector.op_type);
1640 TEST_ASSERT_NOT_NULL(op_type_str, "Invalid op type: %u",
1641 test_vector.op_type);
1644 "Throughput test: dev: %s, nb_queues: %u, burst size: %u, num ops: %u, num_lcores: %u, op type: %s, int mode: %s, GHz: %lg\n",
1645 info.dev_name, ad->nb_queues, op_params->burst_sz,
1646 op_params->num_to_process, op_params->num_lcores,
1648 intr_enabled ? "Interrupt mode" : "PMD mode",
1649 (double)rte_get_tsc_hz() / 1000000000.0);
1651 /* Set number of lcores */
1652 num_lcores = (ad->nb_queues < (op_params->num_lcores))
1654 : op_params->num_lcores;
1657 if (test_vector.op_type == RTE_BBDEV_OP_TURBO_DEC)
1658 throughput_function = throughput_intr_lcore_dec;
1660 throughput_function = throughput_intr_lcore_enc;
1662 /* Dequeue interrupt callback registration */
1663 ret = rte_bbdev_callback_register(ad->dev_id,
1664 RTE_BBDEV_EVENT_DEQUEUE, dequeue_event_callback,
1669 if (test_vector.op_type == RTE_BBDEV_OP_TURBO_DEC)
1670 throughput_function = throughput_pmd_lcore_dec;
1672 throughput_function = throughput_pmd_lcore_enc;
1675 rte_atomic16_set(&op_params->sync, SYNC_WAIT);
1677 t_params[rte_lcore_id()].dev_id = ad->dev_id;
1678 t_params[rte_lcore_id()].op_params = op_params;
1679 t_params[rte_lcore_id()].queue_id =
1680 ad->queue_ids[used_cores++];
1682 RTE_LCORE_FOREACH_SLAVE(lcore_id) {
1683 if (used_cores >= num_lcores)
1686 t_params[lcore_id].dev_id = ad->dev_id;
1687 t_params[lcore_id].op_params = op_params;
1688 t_params[lcore_id].queue_id = ad->queue_ids[used_cores++];
1690 rte_eal_remote_launch(throughput_function, &t_params[lcore_id],
1694 rte_atomic16_set(&op_params->sync, SYNC_START);
1695 ret = throughput_function(&t_params[rte_lcore_id()]);
1697 /* Master core is always used */
1699 RTE_LCORE_FOREACH_SLAVE(lcore_id) {
1700 if (used_cores++ >= num_lcores)
1703 ret |= rte_eal_wait_lcore(lcore_id);
1706 /* Return if test failed */
1710 /* Print throughput if interrupts are disabled and test passed */
1711 if (!intr_enabled) {
1712 if (test_vector.op_type == RTE_BBDEV_OP_TURBO_DEC)
1713 print_dec_throughput(t_params, num_lcores);
1715 print_enc_throughput(t_params, num_lcores);
1719 /* In interrupt TC we need to wait for the interrupt callback to deqeue
1720 * all pending operations. Skip waiting for queues which reported an
1721 * error using processing_status variable.
1722 * Wait for master lcore operations.
1724 tp = &t_params[rte_lcore_id()];
1725 while ((rte_atomic16_read(&tp->nb_dequeued) <
1726 op_params->num_to_process) &&
1727 (rte_atomic16_read(&tp->processing_status) !=
1731 ret |= rte_atomic16_read(&tp->processing_status);
1733 /* Wait for slave lcores operations */
1735 RTE_LCORE_FOREACH_SLAVE(lcore_id) {
1736 tp = &t_params[lcore_id];
1737 if (used_cores++ >= num_lcores)
1740 while ((rte_atomic16_read(&tp->nb_dequeued) <
1741 op_params->num_to_process) &&
1742 (rte_atomic16_read(&tp->processing_status) !=
1746 ret |= rte_atomic16_read(&tp->processing_status);
1749 /* Print throughput if test passed */
1751 if (test_vector.op_type == RTE_BBDEV_OP_TURBO_DEC)
1752 print_dec_throughput(t_params, num_lcores);
1753 else if (test_vector.op_type == RTE_BBDEV_OP_TURBO_ENC)
1754 print_enc_throughput(t_params, num_lcores);
1760 latency_test_dec(struct rte_mempool *mempool,
1761 struct test_buffers *bufs, struct rte_bbdev_dec_op *ref_op,
1762 int vector_mask, uint16_t dev_id, uint16_t queue_id,
1763 const uint16_t num_to_process, uint16_t burst_sz,
1764 uint64_t *total_time, uint64_t *min_time, uint64_t *max_time)
1766 int ret = TEST_SUCCESS;
1767 uint16_t i, j, dequeued;
1768 struct rte_bbdev_dec_op *ops_enq[MAX_BURST], *ops_deq[MAX_BURST];
1769 uint64_t start_time = 0, last_time = 0;
1771 for (i = 0, dequeued = 0; dequeued < num_to_process; ++i) {
1772 uint16_t enq = 0, deq = 0;
1773 bool first_time = true;
1776 if (unlikely(num_to_process - dequeued < burst_sz))
1777 burst_sz = num_to_process - dequeued;
1779 ret = rte_bbdev_dec_op_alloc_bulk(mempool, ops_enq, burst_sz);
1780 TEST_ASSERT_SUCCESS(ret,
1781 "rte_bbdev_dec_op_alloc_bulk() failed");
1782 if (test_vector.op_type != RTE_BBDEV_OP_NONE)
1783 copy_reference_dec_op(ops_enq, burst_sz, dequeued,
1789 /* Set counter to validate the ordering */
1790 for (j = 0; j < burst_sz; ++j)
1791 ops_enq[j]->opaque_data = (void *)(uintptr_t)j;
1793 start_time = rte_rdtsc_precise();
1795 enq = rte_bbdev_enqueue_dec_ops(dev_id, queue_id, &ops_enq[enq],
1797 TEST_ASSERT(enq == burst_sz,
1798 "Error enqueueing burst, expected %u, got %u",
1803 deq += rte_bbdev_dequeue_dec_ops(dev_id, queue_id,
1804 &ops_deq[deq], burst_sz - deq);
1805 if (likely(first_time && (deq > 0))) {
1806 last_time = rte_rdtsc_precise() - start_time;
1809 } while (unlikely(burst_sz != deq));
1811 *max_time = RTE_MAX(*max_time, last_time);
1812 *min_time = RTE_MIN(*min_time, last_time);
1813 *total_time += last_time;
1815 if (test_vector.op_type != RTE_BBDEV_OP_NONE) {
1816 ret = validate_dec_op(ops_deq, burst_sz, ref_op,
1818 TEST_ASSERT_SUCCESS(ret, "Validation failed!");
1821 rte_bbdev_dec_op_free_bulk(ops_enq, deq);
1829 latency_test_enc(struct rte_mempool *mempool,
1830 struct test_buffers *bufs, struct rte_bbdev_enc_op *ref_op,
1831 uint16_t dev_id, uint16_t queue_id,
1832 const uint16_t num_to_process, uint16_t burst_sz,
1833 uint64_t *total_time, uint64_t *min_time, uint64_t *max_time)
1835 int ret = TEST_SUCCESS;
1836 uint16_t i, j, dequeued;
1837 struct rte_bbdev_enc_op *ops_enq[MAX_BURST], *ops_deq[MAX_BURST];
1838 uint64_t start_time = 0, last_time = 0;
1840 for (i = 0, dequeued = 0; dequeued < num_to_process; ++i) {
1841 uint16_t enq = 0, deq = 0;
1842 bool first_time = true;
1845 if (unlikely(num_to_process - dequeued < burst_sz))
1846 burst_sz = num_to_process - dequeued;
1848 ret = rte_bbdev_enc_op_alloc_bulk(mempool, ops_enq, burst_sz);
1849 TEST_ASSERT_SUCCESS(ret,
1850 "rte_bbdev_enc_op_alloc_bulk() failed");
1851 if (test_vector.op_type != RTE_BBDEV_OP_NONE)
1852 copy_reference_enc_op(ops_enq, burst_sz, dequeued,
1857 /* Set counter to validate the ordering */
1858 for (j = 0; j < burst_sz; ++j)
1859 ops_enq[j]->opaque_data = (void *)(uintptr_t)j;
1861 start_time = rte_rdtsc_precise();
1863 enq = rte_bbdev_enqueue_enc_ops(dev_id, queue_id, &ops_enq[enq],
1865 TEST_ASSERT(enq == burst_sz,
1866 "Error enqueueing burst, expected %u, got %u",
1871 deq += rte_bbdev_dequeue_enc_ops(dev_id, queue_id,
1872 &ops_deq[deq], burst_sz - deq);
1873 if (likely(first_time && (deq > 0))) {
1874 last_time += rte_rdtsc_precise() - start_time;
1877 } while (unlikely(burst_sz != deq));
1879 *max_time = RTE_MAX(*max_time, last_time);
1880 *min_time = RTE_MIN(*min_time, last_time);
1881 *total_time += last_time;
1883 if (test_vector.op_type != RTE_BBDEV_OP_NONE) {
1884 ret = validate_enc_op(ops_deq, burst_sz, ref_op);
1885 TEST_ASSERT_SUCCESS(ret, "Validation failed!");
1888 rte_bbdev_enc_op_free_bulk(ops_enq, deq);
1896 latency_test(struct active_device *ad,
1897 struct test_op_params *op_params)
1900 uint16_t burst_sz = op_params->burst_sz;
1901 const uint16_t num_to_process = op_params->num_to_process;
1902 const enum rte_bbdev_op_type op_type = test_vector.op_type;
1903 const uint16_t queue_id = ad->queue_ids[0];
1904 struct test_buffers *bufs = NULL;
1905 struct rte_bbdev_info info;
1906 uint64_t total_time, min_time, max_time;
1907 const char *op_type_str;
1909 total_time = max_time = 0;
1910 min_time = UINT64_MAX;
1912 TEST_ASSERT_SUCCESS((burst_sz > MAX_BURST),
1913 "BURST_SIZE should be <= %u", MAX_BURST);
1915 rte_bbdev_info_get(ad->dev_id, &info);
1916 bufs = &op_params->q_bufs[GET_SOCKET(info.socket_id)][queue_id];
1918 op_type_str = rte_bbdev_op_type_str(op_type);
1919 TEST_ASSERT_NOT_NULL(op_type_str, "Invalid op type: %u", op_type);
1922 "\nValidation/Latency test: dev: %s, burst size: %u, num ops: %u, op type: %s\n",
1923 info.dev_name, burst_sz, num_to_process, op_type_str);
1925 if (op_type == RTE_BBDEV_OP_TURBO_DEC)
1926 iter = latency_test_dec(op_params->mp, bufs,
1927 op_params->ref_dec_op, op_params->vector_mask,
1928 ad->dev_id, queue_id, num_to_process,
1929 burst_sz, &total_time, &min_time, &max_time);
1931 iter = latency_test_enc(op_params->mp, bufs,
1932 op_params->ref_enc_op, ad->dev_id, queue_id,
1933 num_to_process, burst_sz, &total_time,
1934 &min_time, &max_time);
1939 printf("Operation latency:\n"
1940 "\tavg latency: %lg cycles, %lg us\n"
1941 "\tmin latency: %lg cycles, %lg us\n"
1942 "\tmax latency: %lg cycles, %lg us\n",
1943 (double)total_time / (double)iter,
1944 (double)(total_time * 1000000) / (double)iter /
1945 (double)rte_get_tsc_hz(), (double)min_time,
1946 (double)(min_time * 1000000) / (double)rte_get_tsc_hz(),
1947 (double)max_time, (double)(max_time * 1000000) /
1948 (double)rte_get_tsc_hz());
1950 return TEST_SUCCESS;
1953 #ifdef RTE_BBDEV_OFFLOAD_COST
1955 get_bbdev_queue_stats(uint16_t dev_id, uint16_t queue_id,
1956 struct rte_bbdev_stats *stats)
1958 struct rte_bbdev *dev = &rte_bbdev_devices[dev_id];
1959 struct rte_bbdev_stats *q_stats;
1961 if (queue_id >= dev->data->num_queues)
1964 q_stats = &dev->data->queues[queue_id].queue_stats;
1966 stats->enqueued_count = q_stats->enqueued_count;
1967 stats->dequeued_count = q_stats->dequeued_count;
1968 stats->enqueue_err_count = q_stats->enqueue_err_count;
1969 stats->dequeue_err_count = q_stats->dequeue_err_count;
1970 stats->acc_offload_cycles = q_stats->acc_offload_cycles;
1976 offload_latency_test_dec(struct rte_mempool *mempool, struct test_buffers *bufs,
1977 struct rte_bbdev_dec_op *ref_op, uint16_t dev_id,
1978 uint16_t queue_id, const uint16_t num_to_process,
1979 uint16_t burst_sz, struct test_time_stats *time_st)
1981 int i, dequeued, ret;
1982 struct rte_bbdev_dec_op *ops_enq[MAX_BURST], *ops_deq[MAX_BURST];
1983 uint64_t enq_start_time, deq_start_time;
1984 uint64_t enq_sw_last_time, deq_last_time;
1985 struct rte_bbdev_stats stats;
1987 for (i = 0, dequeued = 0; dequeued < num_to_process; ++i) {
1988 uint16_t enq = 0, deq = 0;
1990 if (unlikely(num_to_process - dequeued < burst_sz))
1991 burst_sz = num_to_process - dequeued;
1993 rte_bbdev_dec_op_alloc_bulk(mempool, ops_enq, burst_sz);
1994 if (test_vector.op_type != RTE_BBDEV_OP_NONE)
1995 copy_reference_dec_op(ops_enq, burst_sz, dequeued,
2001 /* Start time meas for enqueue function offload latency */
2002 enq_start_time = rte_rdtsc_precise();
2004 enq += rte_bbdev_enqueue_dec_ops(dev_id, queue_id,
2005 &ops_enq[enq], burst_sz - enq);
2006 } while (unlikely(burst_sz != enq));
2008 ret = get_bbdev_queue_stats(dev_id, queue_id, &stats);
2009 TEST_ASSERT_SUCCESS(ret,
2010 "Failed to get stats for queue (%u) of device (%u)",
2013 enq_sw_last_time = rte_rdtsc_precise() - enq_start_time -
2014 stats.acc_offload_cycles;
2015 time_st->enq_sw_max_time = RTE_MAX(time_st->enq_sw_max_time,
2017 time_st->enq_sw_min_time = RTE_MIN(time_st->enq_sw_min_time,
2019 time_st->enq_sw_total_time += enq_sw_last_time;
2021 time_st->enq_acc_max_time = RTE_MAX(time_st->enq_acc_max_time,
2022 stats.acc_offload_cycles);
2023 time_st->enq_acc_min_time = RTE_MIN(time_st->enq_acc_min_time,
2024 stats.acc_offload_cycles);
2025 time_st->enq_acc_total_time += stats.acc_offload_cycles;
2027 /* ensure enqueue has been completed */
2030 /* Start time meas for dequeue function offload latency */
2031 deq_start_time = rte_rdtsc_precise();
2032 /* Dequeue one operation */
2034 deq += rte_bbdev_dequeue_dec_ops(dev_id, queue_id,
2036 } while (unlikely(deq != 1));
2038 deq_last_time = rte_rdtsc_precise() - deq_start_time;
2039 time_st->deq_max_time = RTE_MAX(time_st->deq_max_time,
2041 time_st->deq_min_time = RTE_MIN(time_st->deq_min_time,
2043 time_st->deq_total_time += deq_last_time;
2045 /* Dequeue remaining operations if needed*/
2046 while (burst_sz != deq)
2047 deq += rte_bbdev_dequeue_dec_ops(dev_id, queue_id,
2048 &ops_deq[deq], burst_sz - deq);
2050 rte_bbdev_dec_op_free_bulk(ops_enq, deq);
2058 offload_latency_test_enc(struct rte_mempool *mempool, struct test_buffers *bufs,
2059 struct rte_bbdev_enc_op *ref_op, uint16_t dev_id,
2060 uint16_t queue_id, const uint16_t num_to_process,
2061 uint16_t burst_sz, struct test_time_stats *time_st)
2063 int i, dequeued, ret;
2064 struct rte_bbdev_enc_op *ops_enq[MAX_BURST], *ops_deq[MAX_BURST];
2065 uint64_t enq_start_time, deq_start_time;
2066 uint64_t enq_sw_last_time, deq_last_time;
2067 struct rte_bbdev_stats stats;
2069 for (i = 0, dequeued = 0; dequeued < num_to_process; ++i) {
2070 uint16_t enq = 0, deq = 0;
2072 if (unlikely(num_to_process - dequeued < burst_sz))
2073 burst_sz = num_to_process - dequeued;
2075 rte_bbdev_enc_op_alloc_bulk(mempool, ops_enq, burst_sz);
2076 if (test_vector.op_type != RTE_BBDEV_OP_NONE)
2077 copy_reference_enc_op(ops_enq, burst_sz, dequeued,
2082 /* Start time meas for enqueue function offload latency */
2083 enq_start_time = rte_rdtsc_precise();
2085 enq += rte_bbdev_enqueue_enc_ops(dev_id, queue_id,
2086 &ops_enq[enq], burst_sz - enq);
2087 } while (unlikely(burst_sz != enq));
2089 ret = get_bbdev_queue_stats(dev_id, queue_id, &stats);
2090 TEST_ASSERT_SUCCESS(ret,
2091 "Failed to get stats for queue (%u) of device (%u)",
2094 enq_sw_last_time = rte_rdtsc_precise() - enq_start_time -
2095 stats.acc_offload_cycles;
2096 time_st->enq_sw_max_time = RTE_MAX(time_st->enq_sw_max_time,
2098 time_st->enq_sw_min_time = RTE_MIN(time_st->enq_sw_min_time,
2100 time_st->enq_sw_total_time += enq_sw_last_time;
2102 time_st->enq_acc_max_time = RTE_MAX(time_st->enq_acc_max_time,
2103 stats.acc_offload_cycles);
2104 time_st->enq_acc_min_time = RTE_MIN(time_st->enq_acc_min_time,
2105 stats.acc_offload_cycles);
2106 time_st->enq_acc_total_time += stats.acc_offload_cycles;
2108 /* ensure enqueue has been completed */
2111 /* Start time meas for dequeue function offload latency */
2112 deq_start_time = rte_rdtsc_precise();
2113 /* Dequeue one operation */
2115 deq += rte_bbdev_dequeue_enc_ops(dev_id, queue_id,
2117 } while (unlikely(deq != 1));
2119 deq_last_time = rte_rdtsc_precise() - deq_start_time;
2120 time_st->deq_max_time = RTE_MAX(time_st->deq_max_time,
2122 time_st->deq_min_time = RTE_MIN(time_st->deq_min_time,
2124 time_st->deq_total_time += deq_last_time;
2126 while (burst_sz != deq)
2127 deq += rte_bbdev_dequeue_enc_ops(dev_id, queue_id,
2128 &ops_deq[deq], burst_sz - deq);
2130 rte_bbdev_enc_op_free_bulk(ops_enq, deq);
2139 offload_cost_test(struct active_device *ad,
2140 struct test_op_params *op_params)
2142 #ifndef RTE_BBDEV_OFFLOAD_COST
2144 RTE_SET_USED(op_params);
2145 printf("Offload latency test is disabled.\n");
2146 printf("Set RTE_BBDEV_OFFLOAD_COST to 'y' to turn the test on.\n");
2147 return TEST_SKIPPED;
2150 uint16_t burst_sz = op_params->burst_sz;
2151 const uint16_t num_to_process = op_params->num_to_process;
2152 const enum rte_bbdev_op_type op_type = test_vector.op_type;
2153 const uint16_t queue_id = ad->queue_ids[0];
2154 struct test_buffers *bufs = NULL;
2155 struct rte_bbdev_info info;
2156 const char *op_type_str;
2157 struct test_time_stats time_st;
2159 memset(&time_st, 0, sizeof(struct test_time_stats));
2160 time_st.enq_sw_min_time = UINT64_MAX;
2161 time_st.enq_acc_min_time = UINT64_MAX;
2162 time_st.deq_min_time = UINT64_MAX;
2164 TEST_ASSERT_SUCCESS((burst_sz > MAX_BURST),
2165 "BURST_SIZE should be <= %u", MAX_BURST);
2167 rte_bbdev_info_get(ad->dev_id, &info);
2168 bufs = &op_params->q_bufs[GET_SOCKET(info.socket_id)][queue_id];
2170 op_type_str = rte_bbdev_op_type_str(op_type);
2171 TEST_ASSERT_NOT_NULL(op_type_str, "Invalid op type: %u", op_type);
2174 "\nOffload latency test: dev: %s, burst size: %u, num ops: %u, op type: %s\n",
2175 info.dev_name, burst_sz, num_to_process, op_type_str);
2177 if (op_type == RTE_BBDEV_OP_TURBO_DEC)
2178 iter = offload_latency_test_dec(op_params->mp, bufs,
2179 op_params->ref_dec_op, ad->dev_id, queue_id,
2180 num_to_process, burst_sz, &time_st);
2182 iter = offload_latency_test_enc(op_params->mp, bufs,
2183 op_params->ref_enc_op, ad->dev_id, queue_id,
2184 num_to_process, burst_sz, &time_st);
2189 printf("Enqueue offload cost latency:\n"
2190 "\tDriver offload avg %lg cycles, %lg us\n"
2191 "\tDriver offload min %lg cycles, %lg us\n"
2192 "\tDriver offload max %lg cycles, %lg us\n"
2193 "\tAccelerator offload avg %lg cycles, %lg us\n"
2194 "\tAccelerator offload min %lg cycles, %lg us\n"
2195 "\tAccelerator offload max %lg cycles, %lg us\n",
2196 (double)time_st.enq_sw_total_time / (double)iter,
2197 (double)(time_st.enq_sw_total_time * 1000000) /
2198 (double)iter / (double)rte_get_tsc_hz(),
2199 (double)time_st.enq_sw_min_time,
2200 (double)(time_st.enq_sw_min_time * 1000000) /
2201 rte_get_tsc_hz(), (double)time_st.enq_sw_max_time,
2202 (double)(time_st.enq_sw_max_time * 1000000) /
2203 rte_get_tsc_hz(), (double)time_st.enq_acc_total_time /
2205 (double)(time_st.enq_acc_total_time * 1000000) /
2206 (double)iter / (double)rte_get_tsc_hz(),
2207 (double)time_st.enq_acc_min_time,
2208 (double)(time_st.enq_acc_min_time * 1000000) /
2209 rte_get_tsc_hz(), (double)time_st.enq_acc_max_time,
2210 (double)(time_st.enq_acc_max_time * 1000000) /
2213 printf("Dequeue offload cost latency - one op:\n"
2214 "\tavg %lg cycles, %lg us\n"
2215 "\tmin %lg cycles, %lg us\n"
2216 "\tmax %lg cycles, %lg us\n",
2217 (double)time_st.deq_total_time / (double)iter,
2218 (double)(time_st.deq_total_time * 1000000) /
2219 (double)iter / (double)rte_get_tsc_hz(),
2220 (double)time_st.deq_min_time,
2221 (double)(time_st.deq_min_time * 1000000) /
2222 rte_get_tsc_hz(), (double)time_st.deq_max_time,
2223 (double)(time_st.deq_max_time * 1000000) /
2226 return TEST_SUCCESS;
2230 #ifdef RTE_BBDEV_OFFLOAD_COST
2232 offload_latency_empty_q_test_dec(uint16_t dev_id, uint16_t queue_id,
2233 const uint16_t num_to_process, uint16_t burst_sz,
2234 uint64_t *deq_total_time, uint64_t *deq_min_time,
2235 uint64_t *deq_max_time)
2238 struct rte_bbdev_dec_op *ops[MAX_BURST];
2239 uint64_t deq_start_time, deq_last_time;
2241 /* Test deq offload latency from an empty queue */
2243 for (i = 0, deq_total = 0; deq_total < num_to_process;
2244 ++i, deq_total += burst_sz) {
2245 deq_start_time = rte_rdtsc_precise();
2247 if (unlikely(num_to_process - deq_total < burst_sz))
2248 burst_sz = num_to_process - deq_total;
2249 rte_bbdev_dequeue_dec_ops(dev_id, queue_id, ops, burst_sz);
2251 deq_last_time = rte_rdtsc_precise() - deq_start_time;
2252 *deq_max_time = RTE_MAX(*deq_max_time, deq_last_time);
2253 *deq_min_time = RTE_MIN(*deq_min_time, deq_last_time);
2254 *deq_total_time += deq_last_time;
2261 offload_latency_empty_q_test_enc(uint16_t dev_id, uint16_t queue_id,
2262 const uint16_t num_to_process, uint16_t burst_sz,
2263 uint64_t *deq_total_time, uint64_t *deq_min_time,
2264 uint64_t *deq_max_time)
2267 struct rte_bbdev_enc_op *ops[MAX_BURST];
2268 uint64_t deq_start_time, deq_last_time;
2270 /* Test deq offload latency from an empty queue */
2271 for (i = 0, deq_total = 0; deq_total < num_to_process;
2272 ++i, deq_total += burst_sz) {
2273 deq_start_time = rte_rdtsc_precise();
2275 if (unlikely(num_to_process - deq_total < burst_sz))
2276 burst_sz = num_to_process - deq_total;
2277 rte_bbdev_dequeue_enc_ops(dev_id, queue_id, ops, burst_sz);
2279 deq_last_time = rte_rdtsc_precise() - deq_start_time;
2280 *deq_max_time = RTE_MAX(*deq_max_time, deq_last_time);
2281 *deq_min_time = RTE_MIN(*deq_min_time, deq_last_time);
2282 *deq_total_time += deq_last_time;
2290 offload_latency_empty_q_test(struct active_device *ad,
2291 struct test_op_params *op_params)
2293 #ifndef RTE_BBDEV_OFFLOAD_COST
2295 RTE_SET_USED(op_params);
2296 printf("Offload latency empty dequeue test is disabled.\n");
2297 printf("Set RTE_BBDEV_OFFLOAD_COST to 'y' to turn the test on.\n");
2298 return TEST_SKIPPED;
2301 uint64_t deq_total_time, deq_min_time, deq_max_time;
2302 uint16_t burst_sz = op_params->burst_sz;
2303 const uint16_t num_to_process = op_params->num_to_process;
2304 const enum rte_bbdev_op_type op_type = test_vector.op_type;
2305 const uint16_t queue_id = ad->queue_ids[0];
2306 struct rte_bbdev_info info;
2307 const char *op_type_str;
2309 deq_total_time = deq_max_time = 0;
2310 deq_min_time = UINT64_MAX;
2312 TEST_ASSERT_SUCCESS((burst_sz > MAX_BURST),
2313 "BURST_SIZE should be <= %u", MAX_BURST);
2315 rte_bbdev_info_get(ad->dev_id, &info);
2317 op_type_str = rte_bbdev_op_type_str(op_type);
2318 TEST_ASSERT_NOT_NULL(op_type_str, "Invalid op type: %u", op_type);
2321 "\nOffload latency empty dequeue test: dev: %s, burst size: %u, num ops: %u, op type: %s\n",
2322 info.dev_name, burst_sz, num_to_process, op_type_str);
2324 if (op_type == RTE_BBDEV_OP_TURBO_DEC)
2325 iter = offload_latency_empty_q_test_dec(ad->dev_id, queue_id,
2326 num_to_process, burst_sz, &deq_total_time,
2327 &deq_min_time, &deq_max_time);
2329 iter = offload_latency_empty_q_test_enc(ad->dev_id, queue_id,
2330 num_to_process, burst_sz, &deq_total_time,
2331 &deq_min_time, &deq_max_time);
2336 printf("Empty dequeue offload\n"
2337 "\tavg. latency: %lg cycles, %lg us\n"
2338 "\tmin. latency: %lg cycles, %lg us\n"
2339 "\tmax. latency: %lg cycles, %lg us\n",
2340 (double)deq_total_time / (double)iter,
2341 (double)(deq_total_time * 1000000) / (double)iter /
2342 (double)rte_get_tsc_hz(), (double)deq_min_time,
2343 (double)(deq_min_time * 1000000) / rte_get_tsc_hz(),
2344 (double)deq_max_time, (double)(deq_max_time * 1000000) /
2347 return TEST_SUCCESS;
2354 return run_test_case(throughput_test);
2358 offload_cost_tc(void)
2360 return run_test_case(offload_cost_test);
2364 offload_latency_empty_q_tc(void)
2366 return run_test_case(offload_latency_empty_q_test);
2372 return run_test_case(latency_test);
2378 return run_test_case(throughput_test);
2381 static struct unit_test_suite bbdev_throughput_testsuite = {
2382 .suite_name = "BBdev Throughput Tests",
2383 .setup = testsuite_setup,
2384 .teardown = testsuite_teardown,
2385 .unit_test_cases = {
2386 TEST_CASE_ST(ut_setup, ut_teardown, throughput_tc),
2387 TEST_CASES_END() /**< NULL terminate unit test array */
2391 static struct unit_test_suite bbdev_validation_testsuite = {
2392 .suite_name = "BBdev Validation Tests",
2393 .setup = testsuite_setup,
2394 .teardown = testsuite_teardown,
2395 .unit_test_cases = {
2396 TEST_CASE_ST(ut_setup, ut_teardown, latency_tc),
2397 TEST_CASES_END() /**< NULL terminate unit test array */
2401 static struct unit_test_suite bbdev_latency_testsuite = {
2402 .suite_name = "BBdev Latency Tests",
2403 .setup = testsuite_setup,
2404 .teardown = testsuite_teardown,
2405 .unit_test_cases = {
2406 TEST_CASE_ST(ut_setup, ut_teardown, latency_tc),
2407 TEST_CASES_END() /**< NULL terminate unit test array */
2411 static struct unit_test_suite bbdev_offload_cost_testsuite = {
2412 .suite_name = "BBdev Offload Cost Tests",
2413 .setup = testsuite_setup,
2414 .teardown = testsuite_teardown,
2415 .unit_test_cases = {
2416 TEST_CASE_ST(ut_setup, ut_teardown, offload_cost_tc),
2417 TEST_CASE_ST(ut_setup, ut_teardown, offload_latency_empty_q_tc),
2418 TEST_CASES_END() /**< NULL terminate unit test array */
2422 static struct unit_test_suite bbdev_interrupt_testsuite = {
2423 .suite_name = "BBdev Interrupt Tests",
2424 .setup = interrupt_testsuite_setup,
2425 .teardown = testsuite_teardown,
2426 .unit_test_cases = {
2427 TEST_CASE_ST(ut_setup, ut_teardown, interrupt_tc),
2428 TEST_CASES_END() /**< NULL terminate unit test array */
2432 REGISTER_TEST_COMMAND(throughput, bbdev_throughput_testsuite);
2433 REGISTER_TEST_COMMAND(validation, bbdev_validation_testsuite);
2434 REGISTER_TEST_COMMAND(latency, bbdev_latency_testsuite);
2435 REGISTER_TEST_COMMAND(offload, bbdev_offload_cost_testsuite);
2436 REGISTER_TEST_COMMAND(interrupt, bbdev_interrupt_testsuite);