baseband/turbo_sw: scale likelihood ratio input
[dpdk.git] / app / test-bbdev / test_bbdev_perf.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2017 Intel Corporation
3  */
4
5 #include <stdio.h>
6 #include <inttypes.h>
7 #include <math.h>
8
9 #include <rte_eal.h>
10 #include <rte_common.h>
11 #include <rte_dev.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>
19
20 #include "main.h"
21 #include "test_bbdev_vector.h"
22
23 #define GET_SOCKET(socket_id) (((socket_id) == SOCKET_ID_ANY) ? 0 : (socket_id))
24
25 #define MAX_QUEUES RTE_MAX_LCORE
26
27 #define OPS_CACHE_SIZE 256U
28 #define OPS_POOL_SIZE_MIN 511U /* 0.5K per queue */
29
30 #define SYNC_WAIT 0
31 #define SYNC_START 1
32
33 #define INVALID_QUEUE_ID -1
34
35 static struct test_bbdev_vector test_vector;
36
37 /* Switch between PMD and Interrupt for throughput TC */
38 static bool intr_enabled;
39
40 /* Represents tested active devices */
41 static struct active_device {
42         const char *driver_name;
43         uint8_t dev_id;
44         uint16_t supported_ops;
45         uint16_t queue_ids[MAX_QUEUES];
46         uint16_t nb_queues;
47         struct rte_mempool *ops_mempool;
48         struct rte_mempool *in_mbuf_pool;
49         struct rte_mempool *hard_out_mbuf_pool;
50         struct rte_mempool *soft_out_mbuf_pool;
51 } active_devs[RTE_BBDEV_MAX_DEVS];
52
53 static uint8_t nb_active_devs;
54
55 /* Data buffers used by BBDEV ops */
56 struct test_buffers {
57         struct rte_bbdev_op_data *inputs;
58         struct rte_bbdev_op_data *hard_outputs;
59         struct rte_bbdev_op_data *soft_outputs;
60 };
61
62 /* Operation parameters specific for given test case */
63 struct test_op_params {
64         struct rte_mempool *mp;
65         struct rte_bbdev_dec_op *ref_dec_op;
66         struct rte_bbdev_enc_op *ref_enc_op;
67         uint16_t burst_sz;
68         uint16_t num_to_process;
69         uint16_t num_lcores;
70         int vector_mask;
71         rte_atomic16_t sync;
72         struct test_buffers q_bufs[RTE_MAX_NUMA_NODES][MAX_QUEUES];
73 };
74
75 /* Contains per lcore params */
76 struct thread_params {
77         uint8_t dev_id;
78         uint16_t queue_id;
79         uint64_t start_time;
80         double mops;
81         double mbps;
82         rte_atomic16_t nb_dequeued;
83         rte_atomic16_t processing_status;
84         struct test_op_params *op_params;
85 };
86
87 typedef int (test_case_function)(struct active_device *ad,
88                 struct test_op_params *op_params);
89
90 static inline void
91 set_avail_op(struct active_device *ad, enum rte_bbdev_op_type op_type)
92 {
93         ad->supported_ops |= (1 << op_type);
94 }
95
96 static inline bool
97 is_avail_op(struct active_device *ad, enum rte_bbdev_op_type op_type)
98 {
99         return ad->supported_ops & (1 << op_type);
100 }
101
102 static inline bool
103 flags_match(uint32_t flags_req, uint32_t flags_present)
104 {
105         return (flags_req & flags_present) == flags_req;
106 }
107
108 static void
109 clear_soft_out_cap(uint32_t *op_flags)
110 {
111         *op_flags &= ~RTE_BBDEV_TURBO_SOFT_OUTPUT;
112         *op_flags &= ~RTE_BBDEV_TURBO_POS_LLR_1_BIT_SOFT_OUT;
113         *op_flags &= ~RTE_BBDEV_TURBO_NEG_LLR_1_BIT_SOFT_OUT;
114 }
115
116 static int
117 check_dev_cap(const struct rte_bbdev_info *dev_info)
118 {
119         unsigned int i;
120         unsigned int nb_inputs, nb_soft_outputs, nb_hard_outputs;
121         const struct rte_bbdev_op_cap *op_cap = dev_info->drv.capabilities;
122
123         nb_inputs = test_vector.entries[DATA_INPUT].nb_segments;
124         nb_soft_outputs = test_vector.entries[DATA_SOFT_OUTPUT].nb_segments;
125         nb_hard_outputs = test_vector.entries[DATA_HARD_OUTPUT].nb_segments;
126
127         for (i = 0; op_cap->type != RTE_BBDEV_OP_NONE; ++i, ++op_cap) {
128                 if (op_cap->type != test_vector.op_type)
129                         continue;
130
131                 if (op_cap->type == RTE_BBDEV_OP_TURBO_DEC) {
132                         const struct rte_bbdev_op_cap_turbo_dec *cap =
133                                         &op_cap->cap.turbo_dec;
134                         /* Ignore lack of soft output capability, just skip
135                          * checking if soft output is valid.
136                          */
137                         if ((test_vector.turbo_dec.op_flags &
138                                         RTE_BBDEV_TURBO_SOFT_OUTPUT) &&
139                                         !(cap->capability_flags &
140                                         RTE_BBDEV_TURBO_SOFT_OUTPUT)) {
141                                 printf(
142                                         "WARNING: Device \"%s\" does not support soft output - soft output flags will be ignored.\n",
143                                         dev_info->dev_name);
144                                 clear_soft_out_cap(
145                                         &test_vector.turbo_dec.op_flags);
146                         }
147
148                         if (!flags_match(test_vector.turbo_dec.op_flags,
149                                         cap->capability_flags))
150                                 return TEST_FAILED;
151                         if (nb_inputs > cap->num_buffers_src) {
152                                 printf("Too many inputs defined: %u, max: %u\n",
153                                         nb_inputs, cap->num_buffers_src);
154                                 return TEST_FAILED;
155                         }
156                         if (nb_soft_outputs > cap->num_buffers_soft_out &&
157                                         (test_vector.turbo_dec.op_flags &
158                                         RTE_BBDEV_TURBO_SOFT_OUTPUT)) {
159                                 printf(
160                                         "Too many soft outputs defined: %u, max: %u\n",
161                                                 nb_soft_outputs,
162                                                 cap->num_buffers_soft_out);
163                                 return TEST_FAILED;
164                         }
165                         if (nb_hard_outputs > cap->num_buffers_hard_out) {
166                                 printf(
167                                         "Too many hard outputs defined: %u, max: %u\n",
168                                                 nb_hard_outputs,
169                                                 cap->num_buffers_hard_out);
170                                 return TEST_FAILED;
171                         }
172                         if (intr_enabled && !(cap->capability_flags &
173                                         RTE_BBDEV_TURBO_DEC_INTERRUPTS)) {
174                                 printf(
175                                         "Dequeue interrupts are not supported!\n");
176                                 return TEST_FAILED;
177                         }
178
179                         return TEST_SUCCESS;
180                 } else if (op_cap->type == RTE_BBDEV_OP_TURBO_ENC) {
181                         const struct rte_bbdev_op_cap_turbo_enc *cap =
182                                         &op_cap->cap.turbo_enc;
183
184                         if (!flags_match(test_vector.turbo_enc.op_flags,
185                                         cap->capability_flags))
186                                 return TEST_FAILED;
187                         if (nb_inputs > cap->num_buffers_src) {
188                                 printf("Too many inputs defined: %u, max: %u\n",
189                                         nb_inputs, cap->num_buffers_src);
190                                 return TEST_FAILED;
191                         }
192                         if (nb_hard_outputs > cap->num_buffers_dst) {
193                                 printf(
194                                         "Too many hard outputs defined: %u, max: %u\n",
195                                         nb_hard_outputs, cap->num_buffers_src);
196                                 return TEST_FAILED;
197                         }
198                         if (intr_enabled && !(cap->capability_flags &
199                                         RTE_BBDEV_TURBO_ENC_INTERRUPTS)) {
200                                 printf(
201                                         "Dequeue interrupts are not supported!\n");
202                                 return TEST_FAILED;
203                         }
204
205                         return TEST_SUCCESS;
206                 }
207         }
208
209         if ((i == 0) && (test_vector.op_type == RTE_BBDEV_OP_NONE))
210                 return TEST_SUCCESS; /* Special case for NULL device */
211
212         return TEST_FAILED;
213 }
214
215 /* calculates optimal mempool size not smaller than the val */
216 static unsigned int
217 optimal_mempool_size(unsigned int val)
218 {
219         return rte_align32pow2(val + 1) - 1;
220 }
221
222 /* allocates mbuf mempool for inputs and outputs */
223 static struct rte_mempool *
224 create_mbuf_pool(struct op_data_entries *entries, uint8_t dev_id,
225                 int socket_id, unsigned int mbuf_pool_size,
226                 const char *op_type_str)
227 {
228         unsigned int i;
229         uint32_t max_seg_sz = 0;
230         char pool_name[RTE_MEMPOOL_NAMESIZE];
231
232         /* find max input segment size */
233         for (i = 0; i < entries->nb_segments; ++i)
234                 if (entries->segments[i].length > max_seg_sz)
235                         max_seg_sz = entries->segments[i].length;
236
237         snprintf(pool_name, sizeof(pool_name), "%s_pool_%u", op_type_str,
238                         dev_id);
239         return rte_pktmbuf_pool_create(pool_name, mbuf_pool_size, 0, 0,
240                         RTE_MAX(max_seg_sz + RTE_PKTMBUF_HEADROOM,
241                         (unsigned int)RTE_MBUF_DEFAULT_BUF_SIZE), socket_id);
242 }
243
244 static int
245 create_mempools(struct active_device *ad, int socket_id,
246                 enum rte_bbdev_op_type op_type, uint16_t num_ops)
247 {
248         struct rte_mempool *mp;
249         unsigned int ops_pool_size, mbuf_pool_size = 0;
250         char pool_name[RTE_MEMPOOL_NAMESIZE];
251         const char *op_type_str;
252
253         struct op_data_entries *in = &test_vector.entries[DATA_INPUT];
254         struct op_data_entries *hard_out =
255                         &test_vector.entries[DATA_HARD_OUTPUT];
256         struct op_data_entries *soft_out =
257                         &test_vector.entries[DATA_SOFT_OUTPUT];
258
259         /* allocate ops mempool */
260         ops_pool_size = optimal_mempool_size(RTE_MAX(
261                         /* Ops used plus 1 reference op */
262                         RTE_MAX((unsigned int)(ad->nb_queues * num_ops + 1),
263                         /* Minimal cache size plus 1 reference op */
264                         (unsigned int)(1.5 * rte_lcore_count() *
265                                         OPS_CACHE_SIZE + 1)),
266                         OPS_POOL_SIZE_MIN));
267
268         op_type_str = rte_bbdev_op_type_str(op_type);
269         TEST_ASSERT_NOT_NULL(op_type_str, "Invalid op type: %u", op_type);
270
271         snprintf(pool_name, sizeof(pool_name), "%s_pool_%u", op_type_str,
272                         ad->dev_id);
273         mp = rte_bbdev_op_pool_create(pool_name, op_type,
274                         ops_pool_size, OPS_CACHE_SIZE, socket_id);
275         TEST_ASSERT_NOT_NULL(mp,
276                         "ERROR Failed to create %u items ops pool for dev %u on socket %u.",
277                         ops_pool_size,
278                         ad->dev_id,
279                         socket_id);
280         ad->ops_mempool = mp;
281
282         /* Inputs */
283         mbuf_pool_size = optimal_mempool_size(ops_pool_size * in->nb_segments);
284         mp = create_mbuf_pool(in, ad->dev_id, socket_id, mbuf_pool_size, "in");
285         TEST_ASSERT_NOT_NULL(mp,
286                         "ERROR Failed to create %u items input pktmbuf pool for dev %u on socket %u.",
287                         mbuf_pool_size,
288                         ad->dev_id,
289                         socket_id);
290         ad->in_mbuf_pool = mp;
291
292         /* Hard outputs */
293         mbuf_pool_size = optimal_mempool_size(ops_pool_size *
294                         hard_out->nb_segments);
295         mp = create_mbuf_pool(hard_out, ad->dev_id, socket_id, mbuf_pool_size,
296                         "hard_out");
297         TEST_ASSERT_NOT_NULL(mp,
298                         "ERROR Failed to create %u items hard output pktmbuf pool for dev %u on socket %u.",
299                         mbuf_pool_size,
300                         ad->dev_id,
301                         socket_id);
302         ad->hard_out_mbuf_pool = mp;
303
304         if (soft_out->nb_segments == 0)
305                 return TEST_SUCCESS;
306
307         /* Soft outputs */
308         mbuf_pool_size = optimal_mempool_size(ops_pool_size *
309                         soft_out->nb_segments);
310         mp = create_mbuf_pool(soft_out, ad->dev_id, socket_id, mbuf_pool_size,
311                         "soft_out");
312         TEST_ASSERT_NOT_NULL(mp,
313                         "ERROR Failed to create %uB soft output pktmbuf pool for dev %u on socket %u.",
314                         mbuf_pool_size,
315                         ad->dev_id,
316                         socket_id);
317         ad->soft_out_mbuf_pool = mp;
318
319         return 0;
320 }
321
322 static int
323 add_bbdev_dev(uint8_t dev_id, struct rte_bbdev_info *info,
324                 struct test_bbdev_vector *vector)
325 {
326         int ret;
327         unsigned int queue_id;
328         struct rte_bbdev_queue_conf qconf;
329         struct active_device *ad = &active_devs[nb_active_devs];
330         unsigned int nb_queues;
331         enum rte_bbdev_op_type op_type = vector->op_type;
332
333         nb_queues = RTE_MIN(rte_lcore_count(), info->drv.max_num_queues);
334         /* setup device */
335         ret = rte_bbdev_setup_queues(dev_id, nb_queues, info->socket_id);
336         if (ret < 0) {
337                 printf("rte_bbdev_setup_queues(%u, %u, %d) ret %i\n",
338                                 dev_id, nb_queues, info->socket_id, ret);
339                 return TEST_FAILED;
340         }
341
342         /* configure interrupts if needed */
343         if (intr_enabled) {
344                 ret = rte_bbdev_intr_enable(dev_id);
345                 if (ret < 0) {
346                         printf("rte_bbdev_intr_enable(%u) ret %i\n", dev_id,
347                                         ret);
348                         return TEST_FAILED;
349                 }
350         }
351
352         /* setup device queues */
353         qconf.socket = info->socket_id;
354         qconf.queue_size = info->drv.default_queue_conf.queue_size;
355         qconf.priority = 0;
356         qconf.deferred_start = 0;
357         qconf.op_type = op_type;
358
359         for (queue_id = 0; queue_id < nb_queues; ++queue_id) {
360                 ret = rte_bbdev_queue_configure(dev_id, queue_id, &qconf);
361                 if (ret != 0) {
362                         printf(
363                                         "Allocated all queues (id=%u) at prio%u on dev%u\n",
364                                         queue_id, qconf.priority, dev_id);
365                         qconf.priority++;
366                         ret = rte_bbdev_queue_configure(ad->dev_id, queue_id,
367                                         &qconf);
368                 }
369                 if (ret != 0) {
370                         printf("All queues on dev %u allocated: %u\n",
371                                         dev_id, queue_id);
372                         break;
373                 }
374                 ad->queue_ids[queue_id] = queue_id;
375         }
376         TEST_ASSERT(queue_id != 0,
377                         "ERROR Failed to configure any queues on dev %u",
378                         dev_id);
379         ad->nb_queues = queue_id;
380
381         set_avail_op(ad, op_type);
382
383         return TEST_SUCCESS;
384 }
385
386 static int
387 add_active_device(uint8_t dev_id, struct rte_bbdev_info *info,
388                 struct test_bbdev_vector *vector)
389 {
390         int ret;
391
392         active_devs[nb_active_devs].driver_name = info->drv.driver_name;
393         active_devs[nb_active_devs].dev_id = dev_id;
394
395         ret = add_bbdev_dev(dev_id, info, vector);
396         if (ret == TEST_SUCCESS)
397                 ++nb_active_devs;
398         return ret;
399 }
400
401 static uint8_t
402 populate_active_devices(void)
403 {
404         int ret;
405         uint8_t dev_id;
406         uint8_t nb_devs_added = 0;
407         struct rte_bbdev_info info;
408
409         RTE_BBDEV_FOREACH(dev_id) {
410                 rte_bbdev_info_get(dev_id, &info);
411
412                 if (check_dev_cap(&info)) {
413                         printf(
414                                 "Device %d (%s) does not support specified capabilities\n",
415                                         dev_id, info.dev_name);
416                         continue;
417                 }
418
419                 ret = add_active_device(dev_id, &info, &test_vector);
420                 if (ret != 0) {
421                         printf("Adding active bbdev %s skipped\n",
422                                         info.dev_name);
423                         continue;
424                 }
425                 nb_devs_added++;
426         }
427
428         return nb_devs_added;
429 }
430
431 static int
432 read_test_vector(void)
433 {
434         int ret;
435
436         memset(&test_vector, 0, sizeof(test_vector));
437         printf("Test vector file = %s\n", get_vector_filename());
438         ret = test_bbdev_vector_read(get_vector_filename(), &test_vector);
439         TEST_ASSERT_SUCCESS(ret, "Failed to parse file %s\n",
440                         get_vector_filename());
441
442         return TEST_SUCCESS;
443 }
444
445 static int
446 testsuite_setup(void)
447 {
448         TEST_ASSERT_SUCCESS(read_test_vector(), "Test suite setup failed\n");
449
450         if (populate_active_devices() == 0) {
451                 printf("No suitable devices found!\n");
452                 return TEST_SKIPPED;
453         }
454
455         return TEST_SUCCESS;
456 }
457
458 static int
459 interrupt_testsuite_setup(void)
460 {
461         TEST_ASSERT_SUCCESS(read_test_vector(), "Test suite setup failed\n");
462
463         /* Enable interrupts */
464         intr_enabled = true;
465
466         /* Special case for NULL device (RTE_BBDEV_OP_NONE) */
467         if (populate_active_devices() == 0 ||
468                         test_vector.op_type == RTE_BBDEV_OP_NONE) {
469                 intr_enabled = false;
470                 printf("No suitable devices found!\n");
471                 return TEST_SKIPPED;
472         }
473
474         return TEST_SUCCESS;
475 }
476
477 static void
478 testsuite_teardown(void)
479 {
480         uint8_t dev_id;
481
482         /* Unconfigure devices */
483         RTE_BBDEV_FOREACH(dev_id)
484                 rte_bbdev_close(dev_id);
485
486         /* Clear active devices structs. */
487         memset(active_devs, 0, sizeof(active_devs));
488         nb_active_devs = 0;
489 }
490
491 static int
492 ut_setup(void)
493 {
494         uint8_t i, dev_id;
495
496         for (i = 0; i < nb_active_devs; i++) {
497                 dev_id = active_devs[i].dev_id;
498                 /* reset bbdev stats */
499                 TEST_ASSERT_SUCCESS(rte_bbdev_stats_reset(dev_id),
500                                 "Failed to reset stats of bbdev %u", dev_id);
501                 /* start the device */
502                 TEST_ASSERT_SUCCESS(rte_bbdev_start(dev_id),
503                                 "Failed to start bbdev %u", dev_id);
504         }
505
506         return TEST_SUCCESS;
507 }
508
509 static void
510 ut_teardown(void)
511 {
512         uint8_t i, dev_id;
513         struct rte_bbdev_stats stats;
514
515         for (i = 0; i < nb_active_devs; i++) {
516                 dev_id = active_devs[i].dev_id;
517                 /* read stats and print */
518                 rte_bbdev_stats_get(dev_id, &stats);
519                 /* Stop the device */
520                 rte_bbdev_stop(dev_id);
521         }
522 }
523
524 static int
525 init_op_data_objs(struct rte_bbdev_op_data *bufs,
526                 struct op_data_entries *ref_entries,
527                 struct rte_mempool *mbuf_pool, const uint16_t n,
528                 enum op_data_type op_type, uint16_t min_alignment)
529 {
530         int ret;
531         unsigned int i, j;
532
533         for (i = 0; i < n; ++i) {
534                 char *data;
535                 struct op_data_buf *seg = &ref_entries->segments[0];
536                 struct rte_mbuf *m_head = rte_pktmbuf_alloc(mbuf_pool);
537                 TEST_ASSERT_NOT_NULL(m_head,
538                                 "Not enough mbufs in %d data type mbuf pool (needed %u, available %u)",
539                                 op_type, n * ref_entries->nb_segments,
540                                 mbuf_pool->size);
541
542                 bufs[i].data = m_head;
543                 bufs[i].offset = 0;
544                 bufs[i].length = 0;
545
546                 if (op_type == DATA_INPUT) {
547                         data = rte_pktmbuf_append(m_head, seg->length);
548                         TEST_ASSERT_NOT_NULL(data,
549                                         "Couldn't append %u bytes to mbuf from %d data type mbuf pool",
550                                         seg->length, op_type);
551
552                         TEST_ASSERT(data == RTE_PTR_ALIGN(data, min_alignment),
553                                         "Data addr in mbuf (%p) is not aligned to device min alignment (%u)",
554                                         data, min_alignment);
555                         rte_memcpy(data, seg->addr, seg->length);
556                         bufs[i].length += seg->length;
557
558
559                         for (j = 1; j < ref_entries->nb_segments; ++j) {
560                                 struct rte_mbuf *m_tail =
561                                                 rte_pktmbuf_alloc(mbuf_pool);
562                                 TEST_ASSERT_NOT_NULL(m_tail,
563                                                 "Not enough mbufs in %d data type mbuf pool (needed %u, available %u)",
564                                                 op_type,
565                                                 n * ref_entries->nb_segments,
566                                                 mbuf_pool->size);
567                                 seg += 1;
568
569                                 data = rte_pktmbuf_append(m_tail, seg->length);
570                                 TEST_ASSERT_NOT_NULL(data,
571                                                 "Couldn't append %u bytes to mbuf from %d data type mbuf pool",
572                                                 seg->length, op_type);
573
574                                 TEST_ASSERT(data == RTE_PTR_ALIGN(data,
575                                                 min_alignment),
576                                                 "Data addr in mbuf (%p) is not aligned to device min alignment (%u)",
577                                                 data, min_alignment);
578                                 rte_memcpy(data, seg->addr, seg->length);
579                                 bufs[i].length += seg->length;
580
581                                 ret = rte_pktmbuf_chain(m_head, m_tail);
582                                 TEST_ASSERT_SUCCESS(ret,
583                                                 "Couldn't chain mbufs from %d data type mbuf pool",
584                                                 op_type);
585                         }
586                 }
587         }
588
589         return 0;
590 }
591
592 static int
593 allocate_buffers_on_socket(struct rte_bbdev_op_data **buffers, const int len,
594                 const int socket)
595 {
596         int i;
597
598         *buffers = rte_zmalloc_socket(NULL, len, 0, socket);
599         if (*buffers == NULL) {
600                 printf("WARNING: Failed to allocate op_data on socket %d\n",
601                                 socket);
602                 /* try to allocate memory on other detected sockets */
603                 for (i = 0; i < socket; i++) {
604                         *buffers = rte_zmalloc_socket(NULL, len, 0, i);
605                         if (*buffers != NULL)
606                                 break;
607                 }
608         }
609
610         return (*buffers == NULL) ? TEST_FAILED : TEST_SUCCESS;
611 }
612
613 static void
614 limit_input_llr_val_range(struct rte_bbdev_op_data *input_ops,
615                 uint16_t n, int8_t max_llr_modulus)
616 {
617         uint16_t i, byte_idx;
618
619         for (i = 0; i < n; ++i) {
620                 struct rte_mbuf *m = input_ops[i].data;
621                 while (m != NULL) {
622                         int8_t *llr = rte_pktmbuf_mtod_offset(m, int8_t *,
623                                         input_ops[i].offset);
624                         for (byte_idx = 0; byte_idx < input_ops[i].length;
625                                         ++byte_idx)
626                                 llr[byte_idx] = round((double)max_llr_modulus *
627                                                 llr[byte_idx] / INT8_MAX);
628
629                         m = m->next;
630                 }
631         }
632 }
633
634 static int
635 fill_queue_buffers(struct test_op_params *op_params,
636                 struct rte_mempool *in_mp, struct rte_mempool *hard_out_mp,
637                 struct rte_mempool *soft_out_mp, uint16_t queue_id,
638                 const struct rte_bbdev_op_cap *capabilities,
639                 uint16_t min_alignment, const int socket_id)
640 {
641         int ret;
642         enum op_data_type type;
643         const uint16_t n = op_params->num_to_process;
644
645         struct rte_mempool *mbuf_pools[DATA_NUM_TYPES] = {
646                 in_mp,
647                 soft_out_mp,
648                 hard_out_mp,
649         };
650
651         struct rte_bbdev_op_data **queue_ops[DATA_NUM_TYPES] = {
652                 &op_params->q_bufs[socket_id][queue_id].inputs,
653                 &op_params->q_bufs[socket_id][queue_id].soft_outputs,
654                 &op_params->q_bufs[socket_id][queue_id].hard_outputs,
655         };
656
657         for (type = DATA_INPUT; type < DATA_NUM_TYPES; ++type) {
658                 struct op_data_entries *ref_entries =
659                                 &test_vector.entries[type];
660                 if (ref_entries->nb_segments == 0)
661                         continue;
662
663                 ret = allocate_buffers_on_socket(queue_ops[type],
664                                 n * sizeof(struct rte_bbdev_op_data),
665                                 socket_id);
666                 TEST_ASSERT_SUCCESS(ret,
667                                 "Couldn't allocate memory for rte_bbdev_op_data structs");
668
669                 ret = init_op_data_objs(*queue_ops[type], ref_entries,
670                                 mbuf_pools[type], n, type, min_alignment);
671                 TEST_ASSERT_SUCCESS(ret,
672                                 "Couldn't init rte_bbdev_op_data structs");
673         }
674
675         if (test_vector.op_type == RTE_BBDEV_OP_TURBO_DEC)
676                 limit_input_llr_val_range(*queue_ops[DATA_INPUT], n,
677                         capabilities->cap.turbo_dec.max_llr_modulus);
678
679         return 0;
680 }
681
682 static void
683 free_buffers(struct active_device *ad, struct test_op_params *op_params)
684 {
685         unsigned int i, j;
686
687         rte_mempool_free(ad->ops_mempool);
688         rte_mempool_free(ad->in_mbuf_pool);
689         rte_mempool_free(ad->hard_out_mbuf_pool);
690         rte_mempool_free(ad->soft_out_mbuf_pool);
691
692         for (i = 0; i < rte_lcore_count(); ++i) {
693                 for (j = 0; j < RTE_MAX_NUMA_NODES; ++j) {
694                         rte_free(op_params->q_bufs[j][i].inputs);
695                         rte_free(op_params->q_bufs[j][i].hard_outputs);
696                         rte_free(op_params->q_bufs[j][i].soft_outputs);
697                 }
698         }
699 }
700
701 static void
702 copy_reference_dec_op(struct rte_bbdev_dec_op **ops, unsigned int n,
703                 unsigned int start_idx,
704                 struct rte_bbdev_op_data *inputs,
705                 struct rte_bbdev_op_data *hard_outputs,
706                 struct rte_bbdev_op_data *soft_outputs,
707                 struct rte_bbdev_dec_op *ref_op)
708 {
709         unsigned int i;
710         struct rte_bbdev_op_turbo_dec *turbo_dec = &ref_op->turbo_dec;
711
712         for (i = 0; i < n; ++i) {
713                 if (turbo_dec->code_block_mode == 0) {
714                         ops[i]->turbo_dec.tb_params.ea =
715                                         turbo_dec->tb_params.ea;
716                         ops[i]->turbo_dec.tb_params.eb =
717                                         turbo_dec->tb_params.eb;
718                         ops[i]->turbo_dec.tb_params.k_pos =
719                                         turbo_dec->tb_params.k_pos;
720                         ops[i]->turbo_dec.tb_params.k_neg =
721                                         turbo_dec->tb_params.k_neg;
722                         ops[i]->turbo_dec.tb_params.c =
723                                         turbo_dec->tb_params.c;
724                         ops[i]->turbo_dec.tb_params.c_neg =
725                                         turbo_dec->tb_params.c_neg;
726                         ops[i]->turbo_dec.tb_params.cab =
727                                         turbo_dec->tb_params.cab;
728                 } else {
729                         ops[i]->turbo_dec.cb_params.e = turbo_dec->cb_params.e;
730                         ops[i]->turbo_dec.cb_params.k = turbo_dec->cb_params.k;
731                 }
732
733                 ops[i]->turbo_dec.ext_scale = turbo_dec->ext_scale;
734                 ops[i]->turbo_dec.iter_max = turbo_dec->iter_max;
735                 ops[i]->turbo_dec.iter_min = turbo_dec->iter_min;
736                 ops[i]->turbo_dec.op_flags = turbo_dec->op_flags;
737                 ops[i]->turbo_dec.rv_index = turbo_dec->rv_index;
738                 ops[i]->turbo_dec.num_maps = turbo_dec->num_maps;
739                 ops[i]->turbo_dec.code_block_mode = turbo_dec->code_block_mode;
740
741                 ops[i]->turbo_dec.hard_output = hard_outputs[start_idx + i];
742                 ops[i]->turbo_dec.input = inputs[start_idx + i];
743                 if (soft_outputs != NULL)
744                         ops[i]->turbo_dec.soft_output =
745                                 soft_outputs[start_idx + i];
746         }
747 }
748
749 static void
750 copy_reference_enc_op(struct rte_bbdev_enc_op **ops, unsigned int n,
751                 unsigned int start_idx,
752                 struct rte_bbdev_op_data *inputs,
753                 struct rte_bbdev_op_data *outputs,
754                 struct rte_bbdev_enc_op *ref_op)
755 {
756         unsigned int i;
757         struct rte_bbdev_op_turbo_enc *turbo_enc = &ref_op->turbo_enc;
758         for (i = 0; i < n; ++i) {
759                 if (turbo_enc->code_block_mode == 0) {
760                         ops[i]->turbo_enc.tb_params.ea =
761                                         turbo_enc->tb_params.ea;
762                         ops[i]->turbo_enc.tb_params.eb =
763                                         turbo_enc->tb_params.eb;
764                         ops[i]->turbo_enc.tb_params.k_pos =
765                                         turbo_enc->tb_params.k_pos;
766                         ops[i]->turbo_enc.tb_params.k_neg =
767                                         turbo_enc->tb_params.k_neg;
768                         ops[i]->turbo_enc.tb_params.c =
769                                         turbo_enc->tb_params.c;
770                         ops[i]->turbo_enc.tb_params.c_neg =
771                                         turbo_enc->tb_params.c_neg;
772                         ops[i]->turbo_enc.tb_params.cab =
773                                         turbo_enc->tb_params.cab;
774                         ops[i]->turbo_enc.tb_params.ncb_pos =
775                                         turbo_enc->tb_params.ncb_pos;
776                         ops[i]->turbo_enc.tb_params.ncb_neg =
777                                         turbo_enc->tb_params.ncb_neg;
778                         ops[i]->turbo_enc.tb_params.r = turbo_enc->tb_params.r;
779                 } else {
780                         ops[i]->turbo_enc.cb_params.e = turbo_enc->cb_params.e;
781                         ops[i]->turbo_enc.cb_params.k = turbo_enc->cb_params.k;
782                         ops[i]->turbo_enc.cb_params.ncb =
783                                         turbo_enc->cb_params.ncb;
784                 }
785                 ops[i]->turbo_enc.rv_index = turbo_enc->rv_index;
786                 ops[i]->turbo_enc.op_flags = turbo_enc->op_flags;
787                 ops[i]->turbo_enc.code_block_mode = turbo_enc->code_block_mode;
788
789                 ops[i]->turbo_enc.output = outputs[start_idx + i];
790                 ops[i]->turbo_enc.input = inputs[start_idx + i];
791         }
792 }
793
794 static int
795 check_dec_status_and_ordering(struct rte_bbdev_dec_op *op,
796                 unsigned int order_idx, const int expected_status)
797 {
798         TEST_ASSERT(op->status == expected_status,
799                         "op_status (%d) != expected_status (%d)",
800                         op->status, expected_status);
801
802         TEST_ASSERT((void *)(uintptr_t)order_idx == op->opaque_data,
803                         "Ordering error, expected %p, got %p",
804                         (void *)(uintptr_t)order_idx, op->opaque_data);
805
806         return TEST_SUCCESS;
807 }
808
809 static int
810 check_enc_status_and_ordering(struct rte_bbdev_enc_op *op,
811                 unsigned int order_idx, const int expected_status)
812 {
813         TEST_ASSERT(op->status == expected_status,
814                         "op_status (%d) != expected_status (%d)",
815                         op->status, expected_status);
816
817         TEST_ASSERT((void *)(uintptr_t)order_idx == op->opaque_data,
818                         "Ordering error, expected %p, got %p",
819                         (void *)(uintptr_t)order_idx, op->opaque_data);
820
821         return TEST_SUCCESS;
822 }
823
824 static inline int
825 validate_op_chain(struct rte_bbdev_op_data *op,
826                 struct op_data_entries *orig_op)
827 {
828         uint8_t i;
829         struct rte_mbuf *m = op->data;
830         uint8_t nb_dst_segments = orig_op->nb_segments;
831
832         TEST_ASSERT(nb_dst_segments == m->nb_segs,
833                         "Number of segments differ in original (%u) and filled (%u) op",
834                         nb_dst_segments, m->nb_segs);
835
836         for (i = 0; i < nb_dst_segments; ++i) {
837                 /* Apply offset to the first mbuf segment */
838                 uint16_t offset = (i == 0) ? op->offset : 0;
839                 uint16_t data_len = m->data_len - offset;
840
841                 TEST_ASSERT(orig_op->segments[i].length == data_len,
842                                 "Length of segment differ in original (%u) and filled (%u) op",
843                                 orig_op->segments[i].length, data_len);
844                 TEST_ASSERT_BUFFERS_ARE_EQUAL(orig_op->segments[i].addr,
845                                 rte_pktmbuf_mtod_offset(m, uint32_t *, offset),
846                                 data_len,
847                                 "Output buffers (CB=%u) are not equal", i);
848                 m = m->next;
849         }
850
851         return TEST_SUCCESS;
852 }
853
854 static int
855 validate_dec_buffers(struct rte_bbdev_dec_op *ref_op, struct test_buffers *bufs,
856                 const uint16_t num_to_process)
857 {
858         int i;
859
860         struct op_data_entries *hard_data_orig =
861                         &test_vector.entries[DATA_HARD_OUTPUT];
862         struct op_data_entries *soft_data_orig =
863                         &test_vector.entries[DATA_SOFT_OUTPUT];
864
865         for (i = 0; i < num_to_process; i++) {
866                 TEST_ASSERT_SUCCESS(validate_op_chain(&bufs->hard_outputs[i],
867                                 hard_data_orig),
868                                 "Hard output buffers are not equal");
869                 if (ref_op->turbo_dec.op_flags &
870                                 RTE_BBDEV_TURBO_SOFT_OUTPUT)
871                         TEST_ASSERT_SUCCESS(validate_op_chain(
872                                         &bufs->soft_outputs[i],
873                                         soft_data_orig),
874                                         "Soft output buffers are not equal");
875         }
876
877         return TEST_SUCCESS;
878 }
879
880 static int
881 validate_enc_buffers(struct test_buffers *bufs, const uint16_t num_to_process)
882 {
883         int i;
884
885         struct op_data_entries *hard_data_orig =
886                         &test_vector.entries[DATA_HARD_OUTPUT];
887
888         for (i = 0; i < num_to_process; i++)
889                 TEST_ASSERT_SUCCESS(validate_op_chain(&bufs->hard_outputs[i],
890                                 hard_data_orig), "");
891
892         return TEST_SUCCESS;
893 }
894
895 static int
896 validate_dec_op(struct rte_bbdev_dec_op **ops, const uint16_t n,
897                 struct rte_bbdev_dec_op *ref_op, const int vector_mask)
898 {
899         unsigned int i;
900         int ret;
901         struct op_data_entries *hard_data_orig =
902                         &test_vector.entries[DATA_HARD_OUTPUT];
903         struct op_data_entries *soft_data_orig =
904                         &test_vector.entries[DATA_SOFT_OUTPUT];
905         struct rte_bbdev_op_turbo_dec *ops_td;
906         struct rte_bbdev_op_data *hard_output;
907         struct rte_bbdev_op_data *soft_output;
908         struct rte_bbdev_op_turbo_dec *ref_td = &ref_op->turbo_dec;
909
910         for (i = 0; i < n; ++i) {
911                 ops_td = &ops[i]->turbo_dec;
912                 hard_output = &ops_td->hard_output;
913                 soft_output = &ops_td->soft_output;
914
915                 if (vector_mask & TEST_BBDEV_VF_EXPECTED_ITER_COUNT)
916                         TEST_ASSERT(ops_td->iter_count <= ref_td->iter_count,
917                                         "Returned iter_count (%d) > expected iter_count (%d)",
918                                         ops_td->iter_count, ref_td->iter_count);
919                 ret = check_dec_status_and_ordering(ops[i], i, ref_op->status);
920                 TEST_ASSERT_SUCCESS(ret,
921                                 "Checking status and ordering for decoder failed");
922
923                 TEST_ASSERT_SUCCESS(validate_op_chain(hard_output,
924                                 hard_data_orig),
925                                 "Hard output buffers (CB=%u) are not equal",
926                                 i);
927
928                 if (ref_op->turbo_dec.op_flags & RTE_BBDEV_TURBO_SOFT_OUTPUT)
929                         TEST_ASSERT_SUCCESS(validate_op_chain(soft_output,
930                                         soft_data_orig),
931                                         "Soft output buffers (CB=%u) are not equal",
932                                         i);
933         }
934
935         return TEST_SUCCESS;
936 }
937
938 static int
939 validate_enc_op(struct rte_bbdev_enc_op **ops, const uint16_t n,
940                 struct rte_bbdev_enc_op *ref_op)
941 {
942         unsigned int i;
943         int ret;
944         struct op_data_entries *hard_data_orig =
945                         &test_vector.entries[DATA_HARD_OUTPUT];
946
947         for (i = 0; i < n; ++i) {
948                 ret = check_enc_status_and_ordering(ops[i], i, ref_op->status);
949                 TEST_ASSERT_SUCCESS(ret,
950                                 "Checking status and ordering for encoder failed");
951                 TEST_ASSERT_SUCCESS(validate_op_chain(
952                                 &ops[i]->turbo_enc.output,
953                                 hard_data_orig),
954                                 "Output buffers (CB=%u) are not equal",
955                                 i);
956         }
957
958         return TEST_SUCCESS;
959 }
960
961 static void
962 create_reference_dec_op(struct rte_bbdev_dec_op *op)
963 {
964         unsigned int i;
965         struct op_data_entries *entry;
966
967         op->turbo_dec = test_vector.turbo_dec;
968         entry = &test_vector.entries[DATA_INPUT];
969         for (i = 0; i < entry->nb_segments; ++i)
970                 op->turbo_dec.input.length +=
971                                 entry->segments[i].length;
972 }
973
974 static void
975 create_reference_enc_op(struct rte_bbdev_enc_op *op)
976 {
977         unsigned int i;
978         struct op_data_entries *entry;
979
980         op->turbo_enc = test_vector.turbo_enc;
981         entry = &test_vector.entries[DATA_INPUT];
982         for (i = 0; i < entry->nb_segments; ++i)
983                 op->turbo_enc.input.length +=
984                                 entry->segments[i].length;
985 }
986
987 static int
988 init_test_op_params(struct test_op_params *op_params,
989                 enum rte_bbdev_op_type op_type, const int expected_status,
990                 const int vector_mask, struct rte_mempool *ops_mp,
991                 uint16_t burst_sz, uint16_t num_to_process, uint16_t num_lcores)
992 {
993         int ret = 0;
994         if (op_type == RTE_BBDEV_OP_TURBO_DEC)
995                 ret = rte_bbdev_dec_op_alloc_bulk(ops_mp,
996                                 &op_params->ref_dec_op, 1);
997         else
998                 ret = rte_bbdev_enc_op_alloc_bulk(ops_mp,
999                                 &op_params->ref_enc_op, 1);
1000
1001         TEST_ASSERT_SUCCESS(ret, "rte_bbdev_op_alloc_bulk() failed");
1002
1003         op_params->mp = ops_mp;
1004         op_params->burst_sz = burst_sz;
1005         op_params->num_to_process = num_to_process;
1006         op_params->num_lcores = num_lcores;
1007         op_params->vector_mask = vector_mask;
1008         if (op_type == RTE_BBDEV_OP_TURBO_DEC)
1009                 op_params->ref_dec_op->status = expected_status;
1010         else if (op_type == RTE_BBDEV_OP_TURBO_ENC)
1011                 op_params->ref_enc_op->status = expected_status;
1012
1013         return 0;
1014 }
1015
1016 static int
1017 run_test_case_on_device(test_case_function *test_case_func, uint8_t dev_id,
1018                 struct test_op_params *op_params)
1019 {
1020         int t_ret, f_ret, socket_id = SOCKET_ID_ANY;
1021         unsigned int i;
1022         struct active_device *ad;
1023         unsigned int burst_sz = get_burst_sz();
1024         enum rte_bbdev_op_type op_type = test_vector.op_type;
1025         const struct rte_bbdev_op_cap *capabilities = NULL;
1026
1027         ad = &active_devs[dev_id];
1028
1029         /* Check if device supports op_type */
1030         if (!is_avail_op(ad, test_vector.op_type))
1031                 return TEST_SUCCESS;
1032
1033         struct rte_bbdev_info info;
1034         rte_bbdev_info_get(ad->dev_id, &info);
1035         socket_id = GET_SOCKET(info.socket_id);
1036
1037         if (op_type == RTE_BBDEV_OP_NONE)
1038                 op_type = RTE_BBDEV_OP_TURBO_ENC;
1039         f_ret = create_mempools(ad, socket_id, op_type,
1040                         get_num_ops());
1041         if (f_ret != TEST_SUCCESS) {
1042                 printf("Couldn't create mempools");
1043                 goto fail;
1044         }
1045
1046         f_ret = init_test_op_params(op_params, test_vector.op_type,
1047                         test_vector.expected_status,
1048                         test_vector.mask,
1049                         ad->ops_mempool,
1050                         burst_sz,
1051                         get_num_ops(),
1052                         get_num_lcores());
1053         if (f_ret != TEST_SUCCESS) {
1054                 printf("Couldn't init test op params");
1055                 goto fail;
1056         }
1057
1058         if (test_vector.op_type == RTE_BBDEV_OP_TURBO_DEC) {
1059                 /* Find Decoder capabilities */
1060                 const struct rte_bbdev_op_cap *cap = info.drv.capabilities;
1061                 while (cap->type != RTE_BBDEV_OP_NONE) {
1062                         if (cap->type == RTE_BBDEV_OP_TURBO_DEC) {
1063                                 capabilities = cap;
1064                                 break;
1065                         }
1066                 }
1067                 TEST_ASSERT_NOT_NULL(capabilities,
1068                                 "Couldn't find Decoder capabilities");
1069
1070                 create_reference_dec_op(op_params->ref_dec_op);
1071         } else if (test_vector.op_type == RTE_BBDEV_OP_TURBO_ENC)
1072                 create_reference_enc_op(op_params->ref_enc_op);
1073
1074         for (i = 0; i < ad->nb_queues; ++i) {
1075                 f_ret = fill_queue_buffers(op_params,
1076                                 ad->in_mbuf_pool,
1077                                 ad->hard_out_mbuf_pool,
1078                                 ad->soft_out_mbuf_pool,
1079                                 ad->queue_ids[i],
1080                                 capabilities,
1081                                 info.drv.min_alignment,
1082                                 socket_id);
1083                 if (f_ret != TEST_SUCCESS) {
1084                         printf("Couldn't init queue buffers");
1085                         goto fail;
1086                 }
1087         }
1088
1089         /* Run test case function */
1090         t_ret = test_case_func(ad, op_params);
1091
1092         /* Free active device resources and return */
1093         free_buffers(ad, op_params);
1094         return t_ret;
1095
1096 fail:
1097         free_buffers(ad, op_params);
1098         return TEST_FAILED;
1099 }
1100
1101 /* Run given test function per active device per supported op type
1102  * per burst size.
1103  */
1104 static int
1105 run_test_case(test_case_function *test_case_func)
1106 {
1107         int ret = 0;
1108         uint8_t dev;
1109
1110         /* Alloc op_params */
1111         struct test_op_params *op_params = rte_zmalloc(NULL,
1112                         sizeof(struct test_op_params), RTE_CACHE_LINE_SIZE);
1113         TEST_ASSERT_NOT_NULL(op_params, "Failed to alloc %zuB for op_params",
1114                         RTE_ALIGN(sizeof(struct test_op_params),
1115                                 RTE_CACHE_LINE_SIZE));
1116
1117         /* For each device run test case function */
1118         for (dev = 0; dev < nb_active_devs; ++dev)
1119                 ret |= run_test_case_on_device(test_case_func, dev, op_params);
1120
1121         rte_free(op_params);
1122
1123         return ret;
1124 }
1125
1126 static void
1127 dequeue_event_callback(uint16_t dev_id,
1128                 enum rte_bbdev_event_type event, void *cb_arg,
1129                 void *ret_param)
1130 {
1131         int ret;
1132         uint16_t i;
1133         uint64_t total_time;
1134         uint16_t deq, burst_sz, num_to_process;
1135         uint16_t queue_id = INVALID_QUEUE_ID;
1136         struct rte_bbdev_dec_op *dec_ops[MAX_BURST];
1137         struct rte_bbdev_enc_op *enc_ops[MAX_BURST];
1138         struct test_buffers *bufs;
1139         struct rte_bbdev_info info;
1140
1141         /* Input length in bytes, million operations per second,
1142          * million bits per second.
1143          */
1144         double in_len;
1145
1146         struct thread_params *tp = cb_arg;
1147
1148         RTE_SET_USED(ret_param);
1149         queue_id = tp->queue_id;
1150
1151         /* Find matching thread params using queue_id */
1152         for (i = 0; i < MAX_QUEUES; ++i, ++tp)
1153                 if (tp->queue_id == queue_id)
1154                         break;
1155
1156         if (i == MAX_QUEUES) {
1157                 printf("%s: Queue_id from interrupt details was not found!\n",
1158                                 __func__);
1159                 return;
1160         }
1161
1162         if (unlikely(event != RTE_BBDEV_EVENT_DEQUEUE)) {
1163                 rte_atomic16_set(&tp->processing_status, TEST_FAILED);
1164                 printf(
1165                         "Dequeue interrupt handler called for incorrect event!\n");
1166                 return;
1167         }
1168
1169         burst_sz = tp->op_params->burst_sz;
1170         num_to_process = tp->op_params->num_to_process;
1171
1172         if (test_vector.op_type == RTE_BBDEV_OP_TURBO_DEC)
1173                 deq = rte_bbdev_dequeue_dec_ops(dev_id, queue_id, dec_ops,
1174                                 burst_sz);
1175         else
1176                 deq = rte_bbdev_dequeue_enc_ops(dev_id, queue_id, enc_ops,
1177                                 burst_sz);
1178
1179         if (deq < burst_sz) {
1180                 printf(
1181                         "After receiving the interrupt all operations should be dequeued. Expected: %u, got: %u\n",
1182                         burst_sz, deq);
1183                 rte_atomic16_set(&tp->processing_status, TEST_FAILED);
1184                 return;
1185         }
1186
1187         if (rte_atomic16_read(&tp->nb_dequeued) + deq < num_to_process) {
1188                 rte_atomic16_add(&tp->nb_dequeued, deq);
1189                 return;
1190         }
1191
1192         total_time = rte_rdtsc_precise() - tp->start_time;
1193
1194         rte_bbdev_info_get(dev_id, &info);
1195
1196         bufs = &tp->op_params->q_bufs[GET_SOCKET(info.socket_id)][queue_id];
1197
1198         ret = TEST_SUCCESS;
1199         if (test_vector.op_type == RTE_BBDEV_OP_TURBO_DEC)
1200                 ret = validate_dec_buffers(tp->op_params->ref_dec_op, bufs,
1201                                 num_to_process);
1202         else if (test_vector.op_type == RTE_BBDEV_OP_TURBO_ENC)
1203                 ret = validate_enc_buffers(bufs, num_to_process);
1204
1205         if (ret) {
1206                 printf("Buffers validation failed\n");
1207                 rte_atomic16_set(&tp->processing_status, TEST_FAILED);
1208         }
1209
1210         switch (test_vector.op_type) {
1211         case RTE_BBDEV_OP_TURBO_DEC:
1212                 in_len = tp->op_params->ref_dec_op->turbo_dec.input.length;
1213                 break;
1214         case RTE_BBDEV_OP_TURBO_ENC:
1215                 in_len = tp->op_params->ref_enc_op->turbo_enc.input.length;
1216                 break;
1217         case RTE_BBDEV_OP_NONE:
1218                 in_len = 0.0;
1219                 break;
1220         default:
1221                 printf("Unknown op type: %d\n", test_vector.op_type);
1222                 rte_atomic16_set(&tp->processing_status, TEST_FAILED);
1223                 return;
1224         }
1225
1226         tp->mops = ((double)num_to_process / 1000000.0) /
1227                         ((double)total_time / (double)rte_get_tsc_hz());
1228         tp->mbps = ((double)num_to_process * in_len * 8 / 1000000.0) /
1229                         ((double)total_time / (double)rte_get_tsc_hz());
1230
1231         rte_atomic16_add(&tp->nb_dequeued, deq);
1232 }
1233
1234 static int
1235 throughput_intr_lcore_dec(void *arg)
1236 {
1237         struct thread_params *tp = arg;
1238         unsigned int enqueued;
1239         struct rte_bbdev_dec_op *ops[MAX_BURST];
1240         const uint16_t queue_id = tp->queue_id;
1241         const uint16_t burst_sz = tp->op_params->burst_sz;
1242         const uint16_t num_to_process = tp->op_params->num_to_process;
1243         struct test_buffers *bufs = NULL;
1244         unsigned int allocs_failed = 0;
1245         struct rte_bbdev_info info;
1246         int ret;
1247
1248         TEST_ASSERT_SUCCESS((burst_sz > MAX_BURST),
1249                         "BURST_SIZE should be <= %u", MAX_BURST);
1250
1251         TEST_ASSERT_SUCCESS(rte_bbdev_queue_intr_enable(tp->dev_id, queue_id),
1252                         "Failed to enable interrupts for dev: %u, queue_id: %u",
1253                         tp->dev_id, queue_id);
1254
1255         rte_bbdev_info_get(tp->dev_id, &info);
1256         bufs = &tp->op_params->q_bufs[GET_SOCKET(info.socket_id)][queue_id];
1257
1258         rte_atomic16_clear(&tp->processing_status);
1259         rte_atomic16_clear(&tp->nb_dequeued);
1260
1261         while (rte_atomic16_read(&tp->op_params->sync) == SYNC_WAIT)
1262                 rte_pause();
1263
1264         tp->start_time = rte_rdtsc_precise();
1265         for (enqueued = 0; enqueued < num_to_process;) {
1266
1267                 uint16_t num_to_enq = burst_sz;
1268
1269                 if (unlikely(num_to_process - enqueued < num_to_enq))
1270                         num_to_enq = num_to_process - enqueued;
1271
1272                 ret = rte_bbdev_dec_op_alloc_bulk(tp->op_params->mp, ops,
1273                                 num_to_enq);
1274                 if (ret != 0) {
1275                         allocs_failed++;
1276                         continue;
1277                 }
1278
1279                 if (test_vector.op_type != RTE_BBDEV_OP_NONE)
1280                         copy_reference_dec_op(ops, num_to_enq, enqueued,
1281                                         bufs->inputs,
1282                                         bufs->hard_outputs,
1283                                         bufs->soft_outputs,
1284                                         tp->op_params->ref_dec_op);
1285
1286                 enqueued += rte_bbdev_enqueue_dec_ops(tp->dev_id, queue_id, ops,
1287                                 num_to_enq);
1288
1289                 rte_bbdev_dec_op_free_bulk(ops, num_to_enq);
1290         }
1291
1292         if (allocs_failed > 0)
1293                 printf("WARNING: op allocations failed: %u times\n",
1294                                 allocs_failed);
1295
1296         return TEST_SUCCESS;
1297 }
1298
1299 static int
1300 throughput_intr_lcore_enc(void *arg)
1301 {
1302         struct thread_params *tp = arg;
1303         unsigned int enqueued;
1304         struct rte_bbdev_enc_op *ops[MAX_BURST];
1305         const uint16_t queue_id = tp->queue_id;
1306         const uint16_t burst_sz = tp->op_params->burst_sz;
1307         const uint16_t num_to_process = tp->op_params->num_to_process;
1308         struct test_buffers *bufs = NULL;
1309         unsigned int allocs_failed = 0;
1310         struct rte_bbdev_info info;
1311         int ret;
1312
1313         TEST_ASSERT_SUCCESS((burst_sz > MAX_BURST),
1314                         "BURST_SIZE should be <= %u", MAX_BURST);
1315
1316         TEST_ASSERT_SUCCESS(rte_bbdev_queue_intr_enable(tp->dev_id, queue_id),
1317                         "Failed to enable interrupts for dev: %u, queue_id: %u",
1318                         tp->dev_id, queue_id);
1319
1320         rte_bbdev_info_get(tp->dev_id, &info);
1321         bufs = &tp->op_params->q_bufs[GET_SOCKET(info.socket_id)][queue_id];
1322
1323         rte_atomic16_clear(&tp->processing_status);
1324         rte_atomic16_clear(&tp->nb_dequeued);
1325
1326         while (rte_atomic16_read(&tp->op_params->sync) == SYNC_WAIT)
1327                 rte_pause();
1328
1329         tp->start_time = rte_rdtsc_precise();
1330         for (enqueued = 0; enqueued < num_to_process;) {
1331
1332                 uint16_t num_to_enq = burst_sz;
1333
1334                 if (unlikely(num_to_process - enqueued < num_to_enq))
1335                         num_to_enq = num_to_process - enqueued;
1336
1337                 ret = rte_bbdev_enc_op_alloc_bulk(tp->op_params->mp, ops,
1338                                 num_to_enq);
1339                 if (ret != 0) {
1340                         allocs_failed++;
1341                         continue;
1342                 }
1343
1344                 if (test_vector.op_type != RTE_BBDEV_OP_NONE)
1345                         copy_reference_enc_op(ops, num_to_enq, enqueued,
1346                                         bufs->inputs,
1347                                         bufs->hard_outputs,
1348                                         tp->op_params->ref_enc_op);
1349
1350                 enqueued += rte_bbdev_enqueue_enc_ops(tp->dev_id, queue_id, ops,
1351                                 num_to_enq);
1352
1353                 rte_bbdev_enc_op_free_bulk(ops, num_to_enq);
1354         }
1355
1356         if (allocs_failed > 0)
1357                 printf("WARNING: op allocations failed: %u times\n",
1358                                 allocs_failed);
1359
1360         return TEST_SUCCESS;
1361 }
1362
1363 static int
1364 throughput_pmd_lcore_dec(void *arg)
1365 {
1366         struct thread_params *tp = arg;
1367         unsigned int enqueued, dequeued;
1368         struct rte_bbdev_dec_op *ops_enq[MAX_BURST], *ops_deq[MAX_BURST];
1369         uint64_t total_time, start_time;
1370         const uint16_t queue_id = tp->queue_id;
1371         const uint16_t burst_sz = tp->op_params->burst_sz;
1372         const uint16_t num_to_process = tp->op_params->num_to_process;
1373         struct rte_bbdev_dec_op *ref_op = tp->op_params->ref_dec_op;
1374         struct test_buffers *bufs = NULL;
1375         unsigned int allocs_failed = 0;
1376         int ret;
1377         struct rte_bbdev_info info;
1378
1379         /* Input length in bytes, million operations per second, million bits
1380          * per second.
1381          */
1382         double in_len;
1383
1384         TEST_ASSERT_SUCCESS((burst_sz > MAX_BURST),
1385                         "BURST_SIZE should be <= %u", MAX_BURST);
1386
1387         rte_bbdev_info_get(tp->dev_id, &info);
1388         bufs = &tp->op_params->q_bufs[GET_SOCKET(info.socket_id)][queue_id];
1389
1390         while (rte_atomic16_read(&tp->op_params->sync) == SYNC_WAIT)
1391                 rte_pause();
1392
1393         start_time = rte_rdtsc_precise();
1394         for (enqueued = 0, dequeued = 0; dequeued < num_to_process;) {
1395                 uint16_t deq;
1396
1397                 if (likely(enqueued < num_to_process)) {
1398
1399                         uint16_t num_to_enq = burst_sz;
1400
1401                         if (unlikely(num_to_process - enqueued < num_to_enq))
1402                                 num_to_enq = num_to_process - enqueued;
1403
1404                         ret = rte_bbdev_dec_op_alloc_bulk(tp->op_params->mp,
1405                                         ops_enq, num_to_enq);
1406                         if (ret != 0) {
1407                                 allocs_failed++;
1408                                 goto do_dequeue;
1409                         }
1410
1411                         if (test_vector.op_type != RTE_BBDEV_OP_NONE)
1412                                 copy_reference_dec_op(ops_enq, num_to_enq,
1413                                                 enqueued,
1414                                                 bufs->inputs,
1415                                                 bufs->hard_outputs,
1416                                                 bufs->soft_outputs,
1417                                                 ref_op);
1418
1419                         enqueued += rte_bbdev_enqueue_dec_ops(tp->dev_id,
1420                                         queue_id, ops_enq, num_to_enq);
1421                 }
1422 do_dequeue:
1423                 deq = rte_bbdev_dequeue_dec_ops(tp->dev_id, queue_id, ops_deq,
1424                                 burst_sz);
1425                 dequeued += deq;
1426                 rte_bbdev_dec_op_free_bulk(ops_enq, deq);
1427         }
1428         total_time = rte_rdtsc_precise() - start_time;
1429
1430         if (allocs_failed > 0)
1431                 printf("WARNING: op allocations failed: %u times\n",
1432                                 allocs_failed);
1433
1434         TEST_ASSERT(enqueued == dequeued, "enqueued (%u) != dequeued (%u)",
1435                         enqueued, dequeued);
1436
1437         if (test_vector.op_type != RTE_BBDEV_OP_NONE) {
1438                 ret = validate_dec_buffers(ref_op, bufs, num_to_process);
1439                 TEST_ASSERT_SUCCESS(ret, "Buffers validation failed");
1440         }
1441
1442         in_len = ref_op->turbo_dec.input.length;
1443         tp->mops = ((double)num_to_process / 1000000.0) /
1444                         ((double)total_time / (double)rte_get_tsc_hz());
1445         tp->mbps = ((double)num_to_process * in_len * 8 / 1000000.0) /
1446                         ((double)total_time / (double)rte_get_tsc_hz());
1447
1448         return TEST_SUCCESS;
1449 }
1450
1451 static int
1452 throughput_pmd_lcore_enc(void *arg)
1453 {
1454         struct thread_params *tp = arg;
1455         unsigned int enqueued, dequeued;
1456         struct rte_bbdev_enc_op *ops_enq[MAX_BURST], *ops_deq[MAX_BURST];
1457         uint64_t total_time, start_time;
1458         const uint16_t queue_id = tp->queue_id;
1459         const uint16_t burst_sz = tp->op_params->burst_sz;
1460         const uint16_t num_to_process = tp->op_params->num_to_process;
1461         struct rte_bbdev_enc_op *ref_op = tp->op_params->ref_enc_op;
1462         struct test_buffers *bufs = NULL;
1463         unsigned int allocs_failed = 0;
1464         int ret;
1465         struct rte_bbdev_info info;
1466
1467         /* Input length in bytes, million operations per second, million bits
1468          * per second.
1469          */
1470         double in_len;
1471
1472         TEST_ASSERT_SUCCESS((burst_sz > MAX_BURST),
1473                         "BURST_SIZE should be <= %u", MAX_BURST);
1474
1475         rte_bbdev_info_get(tp->dev_id, &info);
1476         bufs = &tp->op_params->q_bufs[GET_SOCKET(info.socket_id)][queue_id];
1477
1478         while (rte_atomic16_read(&tp->op_params->sync) == SYNC_WAIT)
1479                 rte_pause();
1480
1481         start_time = rte_rdtsc_precise();
1482         for (enqueued = 0, dequeued = 0; dequeued < num_to_process;) {
1483                 uint16_t deq;
1484
1485                 if (likely(enqueued < num_to_process)) {
1486
1487                         uint16_t num_to_enq = burst_sz;
1488
1489                         if (unlikely(num_to_process - enqueued < num_to_enq))
1490                                 num_to_enq = num_to_process - enqueued;
1491
1492                         ret = rte_bbdev_enc_op_alloc_bulk(tp->op_params->mp,
1493                                         ops_enq, num_to_enq);
1494                         if (ret != 0) {
1495                                 allocs_failed++;
1496                                 goto do_dequeue;
1497                         }
1498
1499                         if (test_vector.op_type != RTE_BBDEV_OP_NONE)
1500                                 copy_reference_enc_op(ops_enq, num_to_enq,
1501                                                 enqueued,
1502                                                 bufs->inputs,
1503                                                 bufs->hard_outputs,
1504                                                 ref_op);
1505
1506                         enqueued += rte_bbdev_enqueue_enc_ops(tp->dev_id,
1507                                         queue_id, ops_enq, num_to_enq);
1508                 }
1509 do_dequeue:
1510                 deq = rte_bbdev_dequeue_enc_ops(tp->dev_id, queue_id, ops_deq,
1511                                 burst_sz);
1512                 dequeued += deq;
1513                 rte_bbdev_enc_op_free_bulk(ops_enq, deq);
1514         }
1515         total_time = rte_rdtsc_precise() - start_time;
1516
1517         if (allocs_failed > 0)
1518                 printf("WARNING: op allocations failed: %u times\n",
1519                                 allocs_failed);
1520
1521         TEST_ASSERT(enqueued == dequeued, "enqueued (%u) != dequeued (%u)",
1522                         enqueued, dequeued);
1523
1524         if (test_vector.op_type != RTE_BBDEV_OP_NONE) {
1525                 ret = validate_enc_buffers(bufs, num_to_process);
1526                 TEST_ASSERT_SUCCESS(ret, "Buffers validation failed");
1527         }
1528
1529         in_len = ref_op->turbo_enc.input.length;
1530
1531         tp->mops = ((double)num_to_process / 1000000.0) /
1532                         ((double)total_time / (double)rte_get_tsc_hz());
1533         tp->mbps = ((double)num_to_process * in_len * 8 / 1000000.0) /
1534                         ((double)total_time / (double)rte_get_tsc_hz());
1535
1536         return TEST_SUCCESS;
1537 }
1538 static void
1539 print_throughput(struct thread_params *t_params, unsigned int used_cores)
1540 {
1541         unsigned int lcore_id, iter = 0;
1542         double total_mops = 0, total_mbps = 0;
1543
1544         RTE_LCORE_FOREACH(lcore_id) {
1545                 if (iter++ >= used_cores)
1546                         break;
1547                 printf("\tlcore_id: %u, throughput: %.8lg MOPS, %.8lg Mbps\n",
1548                 lcore_id, t_params[lcore_id].mops, t_params[lcore_id].mbps);
1549                 total_mops += t_params[lcore_id].mops;
1550                 total_mbps += t_params[lcore_id].mbps;
1551         }
1552         printf(
1553                 "\n\tTotal stats for %u cores: throughput: %.8lg MOPS, %.8lg Mbps\n",
1554                 used_cores, total_mops, total_mbps);
1555 }
1556
1557 /*
1558  * Test function that determines how long an enqueue + dequeue of a burst
1559  * takes on available lcores.
1560  */
1561 static int
1562 throughput_test(struct active_device *ad,
1563                 struct test_op_params *op_params)
1564 {
1565         int ret;
1566         unsigned int lcore_id, used_cores = 0;
1567         struct thread_params t_params[MAX_QUEUES];
1568         struct rte_bbdev_info info;
1569         lcore_function_t *throughput_function;
1570         struct thread_params *tp;
1571         uint16_t num_lcores;
1572         const char *op_type_str;
1573
1574         rte_bbdev_info_get(ad->dev_id, &info);
1575
1576         op_type_str = rte_bbdev_op_type_str(test_vector.op_type);
1577         TEST_ASSERT_NOT_NULL(op_type_str, "Invalid op type: %u",
1578                         test_vector.op_type);
1579
1580         printf(
1581                 "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",
1582                         info.dev_name, ad->nb_queues, op_params->burst_sz,
1583                         op_params->num_to_process, op_params->num_lcores,
1584                         op_type_str,
1585                         intr_enabled ? "Interrupt mode" : "PMD mode",
1586                         (double)rte_get_tsc_hz() / 1000000000.0);
1587
1588         /* Set number of lcores */
1589         num_lcores = (ad->nb_queues < (op_params->num_lcores))
1590                         ? ad->nb_queues
1591                         : op_params->num_lcores;
1592
1593         if (intr_enabled) {
1594                 if (test_vector.op_type == RTE_BBDEV_OP_TURBO_DEC)
1595                         throughput_function = throughput_intr_lcore_dec;
1596                 else
1597                         throughput_function = throughput_intr_lcore_enc;
1598
1599                 /* Dequeue interrupt callback registration */
1600                 ret = rte_bbdev_callback_register(ad->dev_id,
1601                                 RTE_BBDEV_EVENT_DEQUEUE, dequeue_event_callback,
1602                                 &t_params);
1603                 if (ret < 0)
1604                         return ret;
1605         } else {
1606                 if (test_vector.op_type == RTE_BBDEV_OP_TURBO_DEC)
1607                         throughput_function = throughput_pmd_lcore_dec;
1608                 else
1609                         throughput_function = throughput_pmd_lcore_enc;
1610         }
1611
1612         rte_atomic16_set(&op_params->sync, SYNC_WAIT);
1613
1614         t_params[rte_lcore_id()].dev_id = ad->dev_id;
1615         t_params[rte_lcore_id()].op_params = op_params;
1616         t_params[rte_lcore_id()].queue_id =
1617                         ad->queue_ids[used_cores++];
1618
1619         RTE_LCORE_FOREACH_SLAVE(lcore_id) {
1620                 if (used_cores >= num_lcores)
1621                         break;
1622
1623                 t_params[lcore_id].dev_id = ad->dev_id;
1624                 t_params[lcore_id].op_params = op_params;
1625                 t_params[lcore_id].queue_id = ad->queue_ids[used_cores++];
1626
1627                 rte_eal_remote_launch(throughput_function, &t_params[lcore_id],
1628                                 lcore_id);
1629         }
1630
1631         rte_atomic16_set(&op_params->sync, SYNC_START);
1632         ret = throughput_function(&t_params[rte_lcore_id()]);
1633
1634         /* Master core is always used */
1635         used_cores = 1;
1636         RTE_LCORE_FOREACH_SLAVE(lcore_id) {
1637                 if (used_cores++ >= num_lcores)
1638                         break;
1639
1640                 ret |= rte_eal_wait_lcore(lcore_id);
1641         }
1642
1643         /* Return if test failed */
1644         if (ret)
1645                 return ret;
1646
1647         /* Print throughput if interrupts are disabled and test passed */
1648         if (!intr_enabled) {
1649                 if (test_vector.op_type != RTE_BBDEV_OP_NONE)
1650                         print_throughput(t_params, num_lcores);
1651                 return ret;
1652         }
1653
1654         /* In interrupt TC we need to wait for the interrupt callback to deqeue
1655          * all pending operations. Skip waiting for queues which reported an
1656          * error using processing_status variable.
1657          * Wait for master lcore operations.
1658          */
1659         tp = &t_params[rte_lcore_id()];
1660         while ((rte_atomic16_read(&tp->nb_dequeued) <
1661                         op_params->num_to_process) &&
1662                         (rte_atomic16_read(&tp->processing_status) !=
1663                         TEST_FAILED))
1664                 rte_pause();
1665
1666         ret |= rte_atomic16_read(&tp->processing_status);
1667
1668         /* Wait for slave lcores operations */
1669         used_cores = 1;
1670         RTE_LCORE_FOREACH_SLAVE(lcore_id) {
1671                 tp = &t_params[lcore_id];
1672                 if (used_cores++ >= num_lcores)
1673                         break;
1674
1675                 while ((rte_atomic16_read(&tp->nb_dequeued) <
1676                                 op_params->num_to_process) &&
1677                                 (rte_atomic16_read(&tp->processing_status) !=
1678                                 TEST_FAILED))
1679                         rte_pause();
1680
1681                 ret |= rte_atomic16_read(&tp->processing_status);
1682         }
1683
1684         /* Print throughput if test passed */
1685         if (!ret && test_vector.op_type != RTE_BBDEV_OP_NONE)
1686                 print_throughput(t_params, num_lcores);
1687
1688         return ret;
1689 }
1690
1691 static int
1692 operation_latency_test_dec(struct rte_mempool *mempool,
1693                 struct test_buffers *bufs, struct rte_bbdev_dec_op *ref_op,
1694                 int vector_mask, uint16_t dev_id, uint16_t queue_id,
1695                 const uint16_t num_to_process, uint16_t burst_sz,
1696                 uint64_t *total_time)
1697 {
1698         int ret = TEST_SUCCESS;
1699         uint16_t i, j, dequeued;
1700         struct rte_bbdev_dec_op *ops_enq[MAX_BURST], *ops_deq[MAX_BURST];
1701         uint64_t start_time = 0;
1702
1703         for (i = 0, dequeued = 0; dequeued < num_to_process; ++i) {
1704                 uint16_t enq = 0, deq = 0;
1705                 bool first_time = true;
1706
1707                 if (unlikely(num_to_process - dequeued < burst_sz))
1708                         burst_sz = num_to_process - dequeued;
1709
1710                 rte_bbdev_dec_op_alloc_bulk(mempool, ops_enq, burst_sz);
1711                 if (test_vector.op_type != RTE_BBDEV_OP_NONE)
1712                         copy_reference_dec_op(ops_enq, burst_sz, dequeued,
1713                                         bufs->inputs,
1714                                         bufs->hard_outputs,
1715                                         bufs->soft_outputs,
1716                                         ref_op);
1717
1718                 /* Set counter to validate the ordering */
1719                 for (j = 0; j < burst_sz; ++j)
1720                         ops_enq[j]->opaque_data = (void *)(uintptr_t)j;
1721
1722                 start_time = rte_rdtsc_precise();
1723
1724                 enq = rte_bbdev_enqueue_dec_ops(dev_id, queue_id, &ops_enq[enq],
1725                                 burst_sz);
1726                 TEST_ASSERT(enq == burst_sz,
1727                                 "Error enqueueing burst, expected %u, got %u",
1728                                 burst_sz, enq);
1729
1730                 /* Dequeue */
1731                 do {
1732                         deq += rte_bbdev_dequeue_dec_ops(dev_id, queue_id,
1733                                         &ops_deq[deq], burst_sz - deq);
1734                         if (likely(first_time && (deq > 0))) {
1735                                 *total_time += rte_rdtsc_precise() - start_time;
1736                                 first_time = false;
1737                         }
1738                 } while (unlikely(burst_sz != deq));
1739
1740                 if (test_vector.op_type != RTE_BBDEV_OP_NONE) {
1741                         ret = validate_dec_op(ops_deq, burst_sz, ref_op,
1742                                         vector_mask);
1743                         TEST_ASSERT_SUCCESS(ret, "Validation failed!");
1744                 }
1745
1746                 rte_bbdev_dec_op_free_bulk(ops_enq, deq);
1747                 dequeued += deq;
1748         }
1749
1750         return i;
1751 }
1752
1753 static int
1754 operation_latency_test_enc(struct rte_mempool *mempool,
1755                 struct test_buffers *bufs, struct rte_bbdev_enc_op *ref_op,
1756                 uint16_t dev_id, uint16_t queue_id,
1757                 const uint16_t num_to_process, uint16_t burst_sz,
1758                 uint64_t *total_time)
1759 {
1760         int ret = TEST_SUCCESS;
1761         uint16_t i, j, dequeued;
1762         struct rte_bbdev_enc_op *ops_enq[MAX_BURST], *ops_deq[MAX_BURST];
1763         uint64_t start_time = 0;
1764
1765         for (i = 0, dequeued = 0; dequeued < num_to_process; ++i) {
1766                 uint16_t enq = 0, deq = 0;
1767                 bool first_time = true;
1768
1769                 if (unlikely(num_to_process - dequeued < burst_sz))
1770                         burst_sz = num_to_process - dequeued;
1771
1772                 rte_bbdev_enc_op_alloc_bulk(mempool, ops_enq, burst_sz);
1773                 if (test_vector.op_type != RTE_BBDEV_OP_NONE)
1774                         copy_reference_enc_op(ops_enq, burst_sz, dequeued,
1775                                         bufs->inputs,
1776                                         bufs->hard_outputs,
1777                                         ref_op);
1778
1779                 /* Set counter to validate the ordering */
1780                 for (j = 0; j < burst_sz; ++j)
1781                         ops_enq[j]->opaque_data = (void *)(uintptr_t)j;
1782
1783                 start_time = rte_rdtsc_precise();
1784
1785                 enq = rte_bbdev_enqueue_enc_ops(dev_id, queue_id, &ops_enq[enq],
1786                                 burst_sz);
1787                 TEST_ASSERT(enq == burst_sz,
1788                                 "Error enqueueing burst, expected %u, got %u",
1789                                 burst_sz, enq);
1790
1791                 /* Dequeue */
1792                 do {
1793                         deq += rte_bbdev_dequeue_enc_ops(dev_id, queue_id,
1794                                         &ops_deq[deq], burst_sz - deq);
1795                         if (likely(first_time && (deq > 0))) {
1796                                 *total_time += rte_rdtsc_precise() - start_time;
1797                                 first_time = false;
1798                         }
1799                 } while (unlikely(burst_sz != deq));
1800
1801                 if (test_vector.op_type != RTE_BBDEV_OP_NONE) {
1802                         ret = validate_enc_op(ops_deq, burst_sz, ref_op);
1803                         TEST_ASSERT_SUCCESS(ret, "Validation failed!");
1804                 }
1805
1806                 rte_bbdev_enc_op_free_bulk(ops_enq, deq);
1807                 dequeued += deq;
1808         }
1809
1810         return i;
1811 }
1812
1813 static int
1814 operation_latency_test(struct active_device *ad,
1815                 struct test_op_params *op_params)
1816 {
1817         int iter;
1818         uint16_t burst_sz = op_params->burst_sz;
1819         const uint16_t num_to_process = op_params->num_to_process;
1820         const enum rte_bbdev_op_type op_type = test_vector.op_type;
1821         const uint16_t queue_id = ad->queue_ids[0];
1822         struct test_buffers *bufs = NULL;
1823         struct rte_bbdev_info info;
1824         uint64_t total_time = 0;
1825         const char *op_type_str;
1826
1827         TEST_ASSERT_SUCCESS((burst_sz > MAX_BURST),
1828                         "BURST_SIZE should be <= %u", MAX_BURST);
1829
1830         rte_bbdev_info_get(ad->dev_id, &info);
1831         bufs = &op_params->q_bufs[GET_SOCKET(info.socket_id)][queue_id];
1832
1833         op_type_str = rte_bbdev_op_type_str(op_type);
1834         TEST_ASSERT_NOT_NULL(op_type_str, "Invalid op type: %u", op_type);
1835
1836         printf(
1837                 "Validation/Latency test: dev: %s, burst size: %u, num ops: %u, op type: %s\n",
1838                         info.dev_name, burst_sz, num_to_process, op_type_str);
1839
1840         if (op_type == RTE_BBDEV_OP_TURBO_DEC)
1841                 iter = operation_latency_test_dec(op_params->mp, bufs,
1842                                 op_params->ref_dec_op, op_params->vector_mask,
1843                                 ad->dev_id, queue_id, num_to_process,
1844                                 burst_sz, &total_time);
1845         else
1846                 iter = operation_latency_test_enc(op_params->mp, bufs,
1847                                 op_params->ref_enc_op, ad->dev_id, queue_id,
1848                                 num_to_process, burst_sz, &total_time);
1849
1850         if (iter <= 0)
1851                 return TEST_FAILED;
1852
1853         printf("\toperation avg. latency: %lg cycles, %lg us\n",
1854                         (double)total_time / (double)iter,
1855                         (double)(total_time * 1000000) / (double)iter /
1856                         (double)rte_get_tsc_hz());
1857
1858         return TEST_SUCCESS;
1859 }
1860
1861 static int
1862 offload_latency_test_dec(struct rte_mempool *mempool, struct test_buffers *bufs,
1863                 struct rte_bbdev_dec_op *ref_op, uint16_t dev_id,
1864                 uint16_t queue_id, const uint16_t num_to_process,
1865                 uint16_t burst_sz, uint64_t *enq_total_time,
1866                 uint64_t *deq_total_time)
1867 {
1868         int i, dequeued;
1869         struct rte_bbdev_dec_op *ops_enq[MAX_BURST], *ops_deq[MAX_BURST];
1870         uint64_t enq_start_time, deq_start_time;
1871
1872         for (i = 0, dequeued = 0; dequeued < num_to_process; ++i) {
1873                 uint16_t enq = 0, deq = 0;
1874
1875                 if (unlikely(num_to_process - dequeued < burst_sz))
1876                         burst_sz = num_to_process - dequeued;
1877
1878                 rte_bbdev_dec_op_alloc_bulk(mempool, ops_enq, burst_sz);
1879                 if (test_vector.op_type != RTE_BBDEV_OP_NONE)
1880                         copy_reference_dec_op(ops_enq, burst_sz, dequeued,
1881                                         bufs->inputs,
1882                                         bufs->hard_outputs,
1883                                         bufs->soft_outputs,
1884                                         ref_op);
1885
1886                 /* Start time measurment for enqueue function offload latency */
1887                 enq_start_time = rte_rdtsc();
1888                 do {
1889                         enq += rte_bbdev_enqueue_dec_ops(dev_id, queue_id,
1890                                         &ops_enq[enq], burst_sz - enq);
1891                 } while (unlikely(burst_sz != enq));
1892                 *enq_total_time += rte_rdtsc() - enq_start_time;
1893
1894                 /* ensure enqueue has been completed */
1895                 rte_delay_ms(10);
1896
1897                 /* Start time measurment for dequeue function offload latency */
1898                 deq_start_time = rte_rdtsc();
1899                 do {
1900                         deq += rte_bbdev_dequeue_dec_ops(dev_id, queue_id,
1901                                         &ops_deq[deq], burst_sz - deq);
1902                 } while (unlikely(burst_sz != deq));
1903                 *deq_total_time += rte_rdtsc() - deq_start_time;
1904
1905                 rte_bbdev_dec_op_free_bulk(ops_enq, deq);
1906                 dequeued += deq;
1907         }
1908
1909         return i;
1910 }
1911
1912 static int
1913 offload_latency_test_enc(struct rte_mempool *mempool, struct test_buffers *bufs,
1914                 struct rte_bbdev_enc_op *ref_op, uint16_t dev_id,
1915                 uint16_t queue_id, const uint16_t num_to_process,
1916                 uint16_t burst_sz, uint64_t *enq_total_time,
1917                 uint64_t *deq_total_time)
1918 {
1919         int i, dequeued;
1920         struct rte_bbdev_enc_op *ops_enq[MAX_BURST], *ops_deq[MAX_BURST];
1921         uint64_t enq_start_time, deq_start_time;
1922
1923         for (i = 0, dequeued = 0; dequeued < num_to_process; ++i) {
1924                 uint16_t enq = 0, deq = 0;
1925
1926                 if (unlikely(num_to_process - dequeued < burst_sz))
1927                         burst_sz = num_to_process - dequeued;
1928
1929                 rte_bbdev_enc_op_alloc_bulk(mempool, ops_enq, burst_sz);
1930                 if (test_vector.op_type != RTE_BBDEV_OP_NONE)
1931                         copy_reference_enc_op(ops_enq, burst_sz, dequeued,
1932                                         bufs->inputs,
1933                                         bufs->hard_outputs,
1934                                         ref_op);
1935
1936                 /* Start time measurment for enqueue function offload latency */
1937                 enq_start_time = rte_rdtsc();
1938                 do {
1939                         enq += rte_bbdev_enqueue_enc_ops(dev_id, queue_id,
1940                                         &ops_enq[enq], burst_sz - enq);
1941                 } while (unlikely(burst_sz != enq));
1942                 *enq_total_time += rte_rdtsc() - enq_start_time;
1943
1944                 /* ensure enqueue has been completed */
1945                 rte_delay_ms(10);
1946
1947                 /* Start time measurment for dequeue function offload latency */
1948                 deq_start_time = rte_rdtsc();
1949                 do {
1950                         deq += rte_bbdev_dequeue_enc_ops(dev_id, queue_id,
1951                                         &ops_deq[deq], burst_sz - deq);
1952                 } while (unlikely(burst_sz != deq));
1953                 *deq_total_time += rte_rdtsc() - deq_start_time;
1954
1955                 rte_bbdev_enc_op_free_bulk(ops_enq, deq);
1956                 dequeued += deq;
1957         }
1958
1959         return i;
1960 }
1961
1962 static int
1963 offload_latency_test(struct active_device *ad,
1964                 struct test_op_params *op_params)
1965 {
1966         int iter;
1967         uint64_t enq_total_time = 0, deq_total_time = 0;
1968         uint16_t burst_sz = op_params->burst_sz;
1969         const uint16_t num_to_process = op_params->num_to_process;
1970         const enum rte_bbdev_op_type op_type = test_vector.op_type;
1971         const uint16_t queue_id = ad->queue_ids[0];
1972         struct test_buffers *bufs = NULL;
1973         struct rte_bbdev_info info;
1974         const char *op_type_str;
1975
1976         TEST_ASSERT_SUCCESS((burst_sz > MAX_BURST),
1977                         "BURST_SIZE should be <= %u", MAX_BURST);
1978
1979         rte_bbdev_info_get(ad->dev_id, &info);
1980         bufs = &op_params->q_bufs[GET_SOCKET(info.socket_id)][queue_id];
1981
1982         op_type_str = rte_bbdev_op_type_str(op_type);
1983         TEST_ASSERT_NOT_NULL(op_type_str, "Invalid op type: %u", op_type);
1984
1985         printf(
1986                 "Offload latency test: dev: %s, burst size: %u, num ops: %u, op type: %s\n",
1987                         info.dev_name, burst_sz, num_to_process, op_type_str);
1988
1989         if (op_type == RTE_BBDEV_OP_TURBO_DEC)
1990                 iter = offload_latency_test_dec(op_params->mp, bufs,
1991                                 op_params->ref_dec_op, ad->dev_id, queue_id,
1992                                 num_to_process, burst_sz, &enq_total_time,
1993                                 &deq_total_time);
1994         else
1995                 iter = offload_latency_test_enc(op_params->mp, bufs,
1996                                 op_params->ref_enc_op, ad->dev_id, queue_id,
1997                                 num_to_process, burst_sz, &enq_total_time,
1998                                 &deq_total_time);
1999
2000         if (iter <= 0)
2001                 return TEST_FAILED;
2002
2003         printf("\tenq offload avg. latency: %lg cycles, %lg us\n",
2004                         (double)enq_total_time / (double)iter,
2005                         (double)(enq_total_time * 1000000) / (double)iter /
2006                         (double)rte_get_tsc_hz());
2007
2008         printf("\tdeq offload avg. latency: %lg cycles, %lg us\n",
2009                         (double)deq_total_time / (double)iter,
2010                         (double)(deq_total_time * 1000000) / (double)iter /
2011                         (double)rte_get_tsc_hz());
2012
2013         return TEST_SUCCESS;
2014 }
2015
2016 static int
2017 offload_latency_empty_q_test_dec(uint16_t dev_id, uint16_t queue_id,
2018                 const uint16_t num_to_process, uint16_t burst_sz,
2019                 uint64_t *deq_total_time)
2020 {
2021         int i, deq_total;
2022         struct rte_bbdev_dec_op *ops[MAX_BURST];
2023         uint64_t deq_start_time;
2024
2025         /* Test deq offload latency from an empty queue */
2026         deq_start_time = rte_rdtsc_precise();
2027         for (i = 0, deq_total = 0; deq_total < num_to_process;
2028                         ++i, deq_total += burst_sz) {
2029                 if (unlikely(num_to_process - deq_total < burst_sz))
2030                         burst_sz = num_to_process - deq_total;
2031                 rte_bbdev_dequeue_dec_ops(dev_id, queue_id, ops, burst_sz);
2032         }
2033         *deq_total_time = rte_rdtsc_precise() - deq_start_time;
2034
2035         return i;
2036 }
2037
2038 static int
2039 offload_latency_empty_q_test_enc(uint16_t dev_id, uint16_t queue_id,
2040                 const uint16_t num_to_process, uint16_t burst_sz,
2041                 uint64_t *deq_total_time)
2042 {
2043         int i, deq_total;
2044         struct rte_bbdev_enc_op *ops[MAX_BURST];
2045         uint64_t deq_start_time;
2046
2047         /* Test deq offload latency from an empty queue */
2048         deq_start_time = rte_rdtsc_precise();
2049         for (i = 0, deq_total = 0; deq_total < num_to_process;
2050                         ++i, deq_total += burst_sz) {
2051                 if (unlikely(num_to_process - deq_total < burst_sz))
2052                         burst_sz = num_to_process - deq_total;
2053                 rte_bbdev_dequeue_enc_ops(dev_id, queue_id, ops, burst_sz);
2054         }
2055         *deq_total_time = rte_rdtsc_precise() - deq_start_time;
2056
2057         return i;
2058 }
2059
2060 static int
2061 offload_latency_empty_q_test(struct active_device *ad,
2062                 struct test_op_params *op_params)
2063 {
2064         int iter;
2065         uint64_t deq_total_time = 0;
2066         uint16_t burst_sz = op_params->burst_sz;
2067         const uint16_t num_to_process = op_params->num_to_process;
2068         const enum rte_bbdev_op_type op_type = test_vector.op_type;
2069         const uint16_t queue_id = ad->queue_ids[0];
2070         struct rte_bbdev_info info;
2071         const char *op_type_str;
2072
2073         TEST_ASSERT_SUCCESS((burst_sz > MAX_BURST),
2074                         "BURST_SIZE should be <= %u", MAX_BURST);
2075
2076         rte_bbdev_info_get(ad->dev_id, &info);
2077
2078         op_type_str = rte_bbdev_op_type_str(op_type);
2079         TEST_ASSERT_NOT_NULL(op_type_str, "Invalid op type: %u", op_type);
2080
2081         printf(
2082                 "Offload latency empty dequeue test: dev: %s, burst size: %u, num ops: %u, op type: %s\n",
2083                         info.dev_name, burst_sz, num_to_process, op_type_str);
2084
2085         if (op_type == RTE_BBDEV_OP_TURBO_DEC)
2086                 iter = offload_latency_empty_q_test_dec(ad->dev_id, queue_id,
2087                                 num_to_process, burst_sz, &deq_total_time);
2088         else
2089                 iter = offload_latency_empty_q_test_enc(ad->dev_id, queue_id,
2090                                 num_to_process, burst_sz, &deq_total_time);
2091
2092         if (iter <= 0)
2093                 return TEST_FAILED;
2094
2095         printf("\tempty deq offload avg. latency: %lg cycles, %lg us\n",
2096                         (double)deq_total_time / (double)iter,
2097                         (double)(deq_total_time * 1000000) / (double)iter /
2098                         (double)rte_get_tsc_hz());
2099
2100         return TEST_SUCCESS;
2101 }
2102
2103 static int
2104 throughput_tc(void)
2105 {
2106         return run_test_case(throughput_test);
2107 }
2108
2109 static int
2110 offload_latency_tc(void)
2111 {
2112         return run_test_case(offload_latency_test);
2113 }
2114
2115 static int
2116 offload_latency_empty_q_tc(void)
2117 {
2118         return run_test_case(offload_latency_empty_q_test);
2119 }
2120
2121 static int
2122 operation_latency_tc(void)
2123 {
2124         return run_test_case(operation_latency_test);
2125 }
2126
2127 static int
2128 interrupt_tc(void)
2129 {
2130         return run_test_case(throughput_test);
2131 }
2132
2133 static struct unit_test_suite bbdev_throughput_testsuite = {
2134         .suite_name = "BBdev Throughput Tests",
2135         .setup = testsuite_setup,
2136         .teardown = testsuite_teardown,
2137         .unit_test_cases = {
2138                 TEST_CASE_ST(ut_setup, ut_teardown, throughput_tc),
2139                 TEST_CASES_END() /**< NULL terminate unit test array */
2140         }
2141 };
2142
2143 static struct unit_test_suite bbdev_validation_testsuite = {
2144         .suite_name = "BBdev Validation Tests",
2145         .setup = testsuite_setup,
2146         .teardown = testsuite_teardown,
2147         .unit_test_cases = {
2148                 TEST_CASE_ST(ut_setup, ut_teardown, operation_latency_tc),
2149                 TEST_CASES_END() /**< NULL terminate unit test array */
2150         }
2151 };
2152
2153 static struct unit_test_suite bbdev_latency_testsuite = {
2154         .suite_name = "BBdev Latency Tests",
2155         .setup = testsuite_setup,
2156         .teardown = testsuite_teardown,
2157         .unit_test_cases = {
2158                 TEST_CASE_ST(ut_setup, ut_teardown, offload_latency_tc),
2159                 TEST_CASE_ST(ut_setup, ut_teardown, offload_latency_empty_q_tc),
2160                 TEST_CASE_ST(ut_setup, ut_teardown, operation_latency_tc),
2161                 TEST_CASES_END() /**< NULL terminate unit test array */
2162         }
2163 };
2164
2165 static struct unit_test_suite bbdev_interrupt_testsuite = {
2166         .suite_name = "BBdev Interrupt Tests",
2167         .setup = interrupt_testsuite_setup,
2168         .teardown = testsuite_teardown,
2169         .unit_test_cases = {
2170                 TEST_CASE_ST(ut_setup, ut_teardown, interrupt_tc),
2171                 TEST_CASES_END() /**< NULL terminate unit test array */
2172         }
2173 };
2174
2175 REGISTER_TEST_COMMAND(throughput, bbdev_throughput_testsuite);
2176 REGISTER_TEST_COMMAND(validation, bbdev_validation_testsuite);
2177 REGISTER_TEST_COMMAND(latency, bbdev_latency_testsuite);
2178 REGISTER_TEST_COMMAND(interrupt, bbdev_interrupt_testsuite);