app/bbdev: rename FPGA LTE macros to be more explicit
[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 #include <rte_interrupts.h>
20
21 #include "main.h"
22 #include "test_bbdev_vector.h"
23
24 #define GET_SOCKET(socket_id) (((socket_id) == SOCKET_ID_ANY) ? 0 : (socket_id))
25
26 #define MAX_QUEUES RTE_MAX_LCORE
27 #define TEST_REPETITIONS 1000
28
29 #ifdef RTE_LIBRTE_PMD_BBDEV_FPGA_LTE_FEC
30 #include <fpga_lte_fec.h>
31 #define FPGA_LTE_PF_DRIVER_NAME ("intel_fpga_lte_fec_pf")
32 #define FPGA_LTE_VF_DRIVER_NAME ("intel_fpga_lte_fec_vf")
33 #define VF_UL_4G_QUEUE_VALUE 4
34 #define VF_DL_4G_QUEUE_VALUE 4
35 #define UL_4G_BANDWIDTH 3
36 #define DL_4G_BANDWIDTH 3
37 #define UL_4G_LOAD_BALANCE 128
38 #define DL_4G_LOAD_BALANCE 128
39 #define FLR_4G_TIMEOUT 610
40 #endif
41
42 #define OPS_CACHE_SIZE 256U
43 #define OPS_POOL_SIZE_MIN 511U /* 0.5K per queue */
44
45 #define SYNC_WAIT 0
46 #define SYNC_START 1
47
48 #define INVALID_QUEUE_ID -1
49
50 static struct test_bbdev_vector test_vector;
51
52 /* Switch between PMD and Interrupt for throughput TC */
53 static bool intr_enabled;
54
55 /* Represents tested active devices */
56 static struct active_device {
57         const char *driver_name;
58         uint8_t dev_id;
59         uint16_t supported_ops;
60         uint16_t queue_ids[MAX_QUEUES];
61         uint16_t nb_queues;
62         struct rte_mempool *ops_mempool;
63         struct rte_mempool *in_mbuf_pool;
64         struct rte_mempool *hard_out_mbuf_pool;
65         struct rte_mempool *soft_out_mbuf_pool;
66         struct rte_mempool *harq_in_mbuf_pool;
67         struct rte_mempool *harq_out_mbuf_pool;
68 } active_devs[RTE_BBDEV_MAX_DEVS];
69
70 static uint8_t nb_active_devs;
71
72 /* Data buffers used by BBDEV ops */
73 struct test_buffers {
74         struct rte_bbdev_op_data *inputs;
75         struct rte_bbdev_op_data *hard_outputs;
76         struct rte_bbdev_op_data *soft_outputs;
77         struct rte_bbdev_op_data *harq_inputs;
78         struct rte_bbdev_op_data *harq_outputs;
79 };
80
81 /* Operation parameters specific for given test case */
82 struct test_op_params {
83         struct rte_mempool *mp;
84         struct rte_bbdev_dec_op *ref_dec_op;
85         struct rte_bbdev_enc_op *ref_enc_op;
86         uint16_t burst_sz;
87         uint16_t num_to_process;
88         uint16_t num_lcores;
89         int vector_mask;
90         rte_atomic16_t sync;
91         struct test_buffers q_bufs[RTE_MAX_NUMA_NODES][MAX_QUEUES];
92 };
93
94 /* Contains per lcore params */
95 struct thread_params {
96         uint8_t dev_id;
97         uint16_t queue_id;
98         uint32_t lcore_id;
99         uint64_t start_time;
100         double ops_per_sec;
101         double mbps;
102         uint8_t iter_count;
103         rte_atomic16_t nb_dequeued;
104         rte_atomic16_t processing_status;
105         rte_atomic16_t burst_sz;
106         struct test_op_params *op_params;
107         struct rte_bbdev_dec_op *dec_ops[MAX_BURST];
108         struct rte_bbdev_enc_op *enc_ops[MAX_BURST];
109 };
110
111 #ifdef RTE_BBDEV_OFFLOAD_COST
112 /* Stores time statistics */
113 struct test_time_stats {
114         /* Stores software enqueue total working time */
115         uint64_t enq_sw_total_time;
116         /* Stores minimum value of software enqueue working time */
117         uint64_t enq_sw_min_time;
118         /* Stores maximum value of software enqueue working time */
119         uint64_t enq_sw_max_time;
120         /* Stores turbo enqueue total working time */
121         uint64_t enq_acc_total_time;
122         /* Stores minimum value of accelerator enqueue working time */
123         uint64_t enq_acc_min_time;
124         /* Stores maximum value of accelerator enqueue working time */
125         uint64_t enq_acc_max_time;
126         /* Stores dequeue total working time */
127         uint64_t deq_total_time;
128         /* Stores minimum value of dequeue working time */
129         uint64_t deq_min_time;
130         /* Stores maximum value of dequeue working time */
131         uint64_t deq_max_time;
132 };
133 #endif
134
135 typedef int (test_case_function)(struct active_device *ad,
136                 struct test_op_params *op_params);
137
138 static inline void
139 mbuf_reset(struct rte_mbuf *m)
140 {
141         m->pkt_len = 0;
142
143         do {
144                 m->data_len = 0;
145                 m = m->next;
146         } while (m != NULL);
147 }
148
149 /* Read flag value 0/1 from bitmap */
150 static inline bool
151 check_bit(uint32_t bitmap, uint32_t bitmask)
152 {
153         return bitmap & bitmask;
154 }
155
156 static inline void
157 set_avail_op(struct active_device *ad, enum rte_bbdev_op_type op_type)
158 {
159         ad->supported_ops |= (1 << op_type);
160 }
161
162 static inline bool
163 is_avail_op(struct active_device *ad, enum rte_bbdev_op_type op_type)
164 {
165         return ad->supported_ops & (1 << op_type);
166 }
167
168 static inline bool
169 flags_match(uint32_t flags_req, uint32_t flags_present)
170 {
171         return (flags_req & flags_present) == flags_req;
172 }
173
174 static void
175 clear_soft_out_cap(uint32_t *op_flags)
176 {
177         *op_flags &= ~RTE_BBDEV_TURBO_SOFT_OUTPUT;
178         *op_flags &= ~RTE_BBDEV_TURBO_POS_LLR_1_BIT_SOFT_OUT;
179         *op_flags &= ~RTE_BBDEV_TURBO_NEG_LLR_1_BIT_SOFT_OUT;
180 }
181
182 static int
183 check_dev_cap(const struct rte_bbdev_info *dev_info)
184 {
185         unsigned int i;
186         unsigned int nb_inputs, nb_soft_outputs, nb_hard_outputs,
187                 nb_harq_inputs, nb_harq_outputs;
188         const struct rte_bbdev_op_cap *op_cap = dev_info->drv.capabilities;
189
190         nb_inputs = test_vector.entries[DATA_INPUT].nb_segments;
191         nb_soft_outputs = test_vector.entries[DATA_SOFT_OUTPUT].nb_segments;
192         nb_hard_outputs = test_vector.entries[DATA_HARD_OUTPUT].nb_segments;
193         nb_harq_inputs  = test_vector.entries[DATA_HARQ_INPUT].nb_segments;
194         nb_harq_outputs = test_vector.entries[DATA_HARQ_OUTPUT].nb_segments;
195
196         for (i = 0; op_cap->type != RTE_BBDEV_OP_NONE; ++i, ++op_cap) {
197                 if (op_cap->type != test_vector.op_type)
198                         continue;
199
200                 if (op_cap->type == RTE_BBDEV_OP_TURBO_DEC) {
201                         const struct rte_bbdev_op_cap_turbo_dec *cap =
202                                         &op_cap->cap.turbo_dec;
203                         /* Ignore lack of soft output capability, just skip
204                          * checking if soft output is valid.
205                          */
206                         if ((test_vector.turbo_dec.op_flags &
207                                         RTE_BBDEV_TURBO_SOFT_OUTPUT) &&
208                                         !(cap->capability_flags &
209                                         RTE_BBDEV_TURBO_SOFT_OUTPUT)) {
210                                 printf(
211                                         "INFO: Device \"%s\" does not support soft output - soft output flags will be ignored.\n",
212                                         dev_info->dev_name);
213                                 clear_soft_out_cap(
214                                         &test_vector.turbo_dec.op_flags);
215                         }
216
217                         if (!flags_match(test_vector.turbo_dec.op_flags,
218                                         cap->capability_flags))
219                                 return TEST_FAILED;
220                         if (nb_inputs > cap->num_buffers_src) {
221                                 printf("Too many inputs defined: %u, max: %u\n",
222                                         nb_inputs, cap->num_buffers_src);
223                                 return TEST_FAILED;
224                         }
225                         if (nb_soft_outputs > cap->num_buffers_soft_out &&
226                                         (test_vector.turbo_dec.op_flags &
227                                         RTE_BBDEV_TURBO_SOFT_OUTPUT)) {
228                                 printf(
229                                         "Too many soft outputs defined: %u, max: %u\n",
230                                                 nb_soft_outputs,
231                                                 cap->num_buffers_soft_out);
232                                 return TEST_FAILED;
233                         }
234                         if (nb_hard_outputs > cap->num_buffers_hard_out) {
235                                 printf(
236                                         "Too many hard outputs defined: %u, max: %u\n",
237                                                 nb_hard_outputs,
238                                                 cap->num_buffers_hard_out);
239                                 return TEST_FAILED;
240                         }
241                         if (intr_enabled && !(cap->capability_flags &
242                                         RTE_BBDEV_TURBO_DEC_INTERRUPTS)) {
243                                 printf(
244                                         "Dequeue interrupts are not supported!\n");
245                                 return TEST_FAILED;
246                         }
247
248                         return TEST_SUCCESS;
249                 } else if (op_cap->type == RTE_BBDEV_OP_TURBO_ENC) {
250                         const struct rte_bbdev_op_cap_turbo_enc *cap =
251                                         &op_cap->cap.turbo_enc;
252
253                         if (!flags_match(test_vector.turbo_enc.op_flags,
254                                         cap->capability_flags))
255                                 return TEST_FAILED;
256                         if (nb_inputs > cap->num_buffers_src) {
257                                 printf("Too many inputs defined: %u, max: %u\n",
258                                         nb_inputs, cap->num_buffers_src);
259                                 return TEST_FAILED;
260                         }
261                         if (nb_hard_outputs > cap->num_buffers_dst) {
262                                 printf(
263                                         "Too many hard outputs defined: %u, max: %u\n",
264                                         nb_hard_outputs, cap->num_buffers_dst);
265                                 return TEST_FAILED;
266                         }
267                         if (intr_enabled && !(cap->capability_flags &
268                                         RTE_BBDEV_TURBO_ENC_INTERRUPTS)) {
269                                 printf(
270                                         "Dequeue interrupts are not supported!\n");
271                                 return TEST_FAILED;
272                         }
273
274                         return TEST_SUCCESS;
275                 } else if (op_cap->type == RTE_BBDEV_OP_LDPC_ENC) {
276                         const struct rte_bbdev_op_cap_ldpc_enc *cap =
277                                         &op_cap->cap.ldpc_enc;
278
279                         if (!flags_match(test_vector.ldpc_enc.op_flags,
280                                         cap->capability_flags)){
281                                 printf("Flag Mismatch\n");
282                                 return TEST_FAILED;
283                         }
284                         if (nb_inputs > cap->num_buffers_src) {
285                                 printf("Too many inputs defined: %u, max: %u\n",
286                                         nb_inputs, cap->num_buffers_src);
287                                 return TEST_FAILED;
288                         }
289                         if (nb_hard_outputs > cap->num_buffers_dst) {
290                                 printf(
291                                         "Too many hard outputs defined: %u, max: %u\n",
292                                         nb_hard_outputs, cap->num_buffers_dst);
293                                 return TEST_FAILED;
294                         }
295                         if (intr_enabled && !(cap->capability_flags &
296                                         RTE_BBDEV_TURBO_ENC_INTERRUPTS)) {
297                                 printf(
298                                         "Dequeue interrupts are not supported!\n");
299                                 return TEST_FAILED;
300                         }
301
302                         return TEST_SUCCESS;
303                 } else if (op_cap->type == RTE_BBDEV_OP_LDPC_DEC) {
304                         const struct rte_bbdev_op_cap_ldpc_dec *cap =
305                                         &op_cap->cap.ldpc_dec;
306
307                         if (!flags_match(test_vector.ldpc_dec.op_flags,
308                                         cap->capability_flags)){
309                                 printf("Flag Mismatch\n");
310                                 return TEST_FAILED;
311                         }
312                         if (nb_inputs > cap->num_buffers_src) {
313                                 printf("Too many inputs defined: %u, max: %u\n",
314                                         nb_inputs, cap->num_buffers_src);
315                                 return TEST_FAILED;
316                         }
317                         if (nb_hard_outputs > cap->num_buffers_hard_out) {
318                                 printf(
319                                         "Too many hard outputs defined: %u, max: %u\n",
320                                         nb_hard_outputs,
321                                         cap->num_buffers_hard_out);
322                                 return TEST_FAILED;
323                         }
324                         if (nb_harq_inputs > cap->num_buffers_hard_out) {
325                                 printf(
326                                         "Too many HARQ inputs defined: %u, max: %u\n",
327                                         nb_hard_outputs,
328                                         cap->num_buffers_hard_out);
329                                 return TEST_FAILED;
330                         }
331                         if (nb_harq_outputs > cap->num_buffers_hard_out) {
332                                 printf(
333                                         "Too many HARQ outputs defined: %u, max: %u\n",
334                                         nb_hard_outputs,
335                                         cap->num_buffers_hard_out);
336                                 return TEST_FAILED;
337                         }
338                         if (intr_enabled && !(cap->capability_flags &
339                                         RTE_BBDEV_TURBO_DEC_INTERRUPTS)) {
340                                 printf(
341                                         "Dequeue interrupts are not supported!\n");
342                                 return TEST_FAILED;
343                         }
344
345                         return TEST_SUCCESS;
346                 }
347         }
348
349         if ((i == 0) && (test_vector.op_type == RTE_BBDEV_OP_NONE))
350                 return TEST_SUCCESS; /* Special case for NULL device */
351
352         return TEST_FAILED;
353 }
354
355 /* calculates optimal mempool size not smaller than the val */
356 static unsigned int
357 optimal_mempool_size(unsigned int val)
358 {
359         return rte_align32pow2(val + 1) - 1;
360 }
361
362 /* allocates mbuf mempool for inputs and outputs */
363 static struct rte_mempool *
364 create_mbuf_pool(struct op_data_entries *entries, uint8_t dev_id,
365                 int socket_id, unsigned int mbuf_pool_size,
366                 const char *op_type_str)
367 {
368         unsigned int i;
369         uint32_t max_seg_sz = 0;
370         char pool_name[RTE_MEMPOOL_NAMESIZE];
371
372         /* find max input segment size */
373         for (i = 0; i < entries->nb_segments; ++i)
374                 if (entries->segments[i].length > max_seg_sz)
375                         max_seg_sz = entries->segments[i].length;
376
377         snprintf(pool_name, sizeof(pool_name), "%s_pool_%u", op_type_str,
378                         dev_id);
379         return rte_pktmbuf_pool_create(pool_name, mbuf_pool_size, 0, 0,
380                         RTE_MAX(max_seg_sz + RTE_PKTMBUF_HEADROOM,
381                         (unsigned int)RTE_MBUF_DEFAULT_BUF_SIZE), socket_id);
382 }
383
384 static int
385 create_mempools(struct active_device *ad, int socket_id,
386                 enum rte_bbdev_op_type org_op_type, uint16_t num_ops)
387 {
388         struct rte_mempool *mp;
389         unsigned int ops_pool_size, mbuf_pool_size = 0;
390         char pool_name[RTE_MEMPOOL_NAMESIZE];
391         const char *op_type_str;
392         enum rte_bbdev_op_type op_type = org_op_type;
393
394         struct op_data_entries *in = &test_vector.entries[DATA_INPUT];
395         struct op_data_entries *hard_out =
396                         &test_vector.entries[DATA_HARD_OUTPUT];
397         struct op_data_entries *soft_out =
398                         &test_vector.entries[DATA_SOFT_OUTPUT];
399         struct op_data_entries *harq_in =
400                         &test_vector.entries[DATA_HARQ_INPUT];
401         struct op_data_entries *harq_out =
402                         &test_vector.entries[DATA_HARQ_OUTPUT];
403
404         /* allocate ops mempool */
405         ops_pool_size = optimal_mempool_size(RTE_MAX(
406                         /* Ops used plus 1 reference op */
407                         RTE_MAX((unsigned int)(ad->nb_queues * num_ops + 1),
408                         /* Minimal cache size plus 1 reference op */
409                         (unsigned int)(1.5 * rte_lcore_count() *
410                                         OPS_CACHE_SIZE + 1)),
411                         OPS_POOL_SIZE_MIN));
412
413         if (org_op_type == RTE_BBDEV_OP_NONE)
414                 op_type = RTE_BBDEV_OP_TURBO_ENC;
415
416         op_type_str = rte_bbdev_op_type_str(op_type);
417         TEST_ASSERT_NOT_NULL(op_type_str, "Invalid op type: %u", op_type);
418
419         snprintf(pool_name, sizeof(pool_name), "%s_pool_%u", op_type_str,
420                         ad->dev_id);
421         mp = rte_bbdev_op_pool_create(pool_name, op_type,
422                         ops_pool_size, OPS_CACHE_SIZE, socket_id);
423         TEST_ASSERT_NOT_NULL(mp,
424                         "ERROR Failed to create %u items ops pool for dev %u on socket %u.",
425                         ops_pool_size,
426                         ad->dev_id,
427                         socket_id);
428         ad->ops_mempool = mp;
429
430         /* Do not create inputs and outputs mbufs for BaseBand Null Device */
431         if (org_op_type == RTE_BBDEV_OP_NONE)
432                 return TEST_SUCCESS;
433
434         /* Inputs */
435         mbuf_pool_size = optimal_mempool_size(ops_pool_size * in->nb_segments);
436         mp = create_mbuf_pool(in, ad->dev_id, socket_id, mbuf_pool_size, "in");
437         TEST_ASSERT_NOT_NULL(mp,
438                         "ERROR Failed to create %u items input pktmbuf pool for dev %u on socket %u.",
439                         mbuf_pool_size,
440                         ad->dev_id,
441                         socket_id);
442         ad->in_mbuf_pool = mp;
443
444         /* Hard outputs */
445         mbuf_pool_size = optimal_mempool_size(ops_pool_size *
446                         hard_out->nb_segments);
447         mp = create_mbuf_pool(hard_out, ad->dev_id, socket_id, mbuf_pool_size,
448                         "hard_out");
449         TEST_ASSERT_NOT_NULL(mp,
450                         "ERROR Failed to create %u items hard output pktmbuf pool for dev %u on socket %u.",
451                         mbuf_pool_size,
452                         ad->dev_id,
453                         socket_id);
454         ad->hard_out_mbuf_pool = mp;
455
456
457         /* Soft outputs */
458         if (soft_out->nb_segments > 0) {
459                 mbuf_pool_size = optimal_mempool_size(ops_pool_size *
460                                 soft_out->nb_segments);
461                 mp = create_mbuf_pool(soft_out, ad->dev_id, socket_id,
462                                 mbuf_pool_size,
463                                 "soft_out");
464                 TEST_ASSERT_NOT_NULL(mp,
465                                 "ERROR Failed to create %uB soft output pktmbuf pool for dev %u on socket %u.",
466                                 mbuf_pool_size,
467                                 ad->dev_id,
468                                 socket_id);
469                 ad->soft_out_mbuf_pool = mp;
470         }
471
472         /* HARQ inputs */
473         if (harq_in->nb_segments > 0) {
474                 mbuf_pool_size = optimal_mempool_size(ops_pool_size *
475                                 harq_in->nb_segments);
476                 mp = create_mbuf_pool(harq_in, ad->dev_id, socket_id,
477                                 mbuf_pool_size,
478                                 "harq_in");
479                 TEST_ASSERT_NOT_NULL(mp,
480                                 "ERROR Failed to create %uB harq input pktmbuf pool for dev %u on socket %u.",
481                                 mbuf_pool_size,
482                                 ad->dev_id,
483                                 socket_id);
484                 ad->harq_in_mbuf_pool = mp;
485         }
486
487         /* HARQ outputs */
488         if (harq_out->nb_segments > 0) {
489                 mbuf_pool_size = optimal_mempool_size(ops_pool_size *
490                                 harq_out->nb_segments);
491                 mp = create_mbuf_pool(harq_out, ad->dev_id, socket_id,
492                                 mbuf_pool_size,
493                                 "harq_out");
494                 TEST_ASSERT_NOT_NULL(mp,
495                                 "ERROR Failed to create %uB harq output pktmbuf pool for dev %u on socket %u.",
496                                 mbuf_pool_size,
497                                 ad->dev_id,
498                                 socket_id);
499                 ad->harq_out_mbuf_pool = mp;
500         }
501
502         return TEST_SUCCESS;
503 }
504
505 static int
506 add_bbdev_dev(uint8_t dev_id, struct rte_bbdev_info *info,
507                 struct test_bbdev_vector *vector)
508 {
509         int ret;
510         unsigned int queue_id;
511         struct rte_bbdev_queue_conf qconf;
512         struct active_device *ad = &active_devs[nb_active_devs];
513         unsigned int nb_queues;
514         enum rte_bbdev_op_type op_type = vector->op_type;
515
516 /* Configure fpga lte fec with PF & VF values
517  * if '-i' flag is set and using fpga device
518  */
519 #ifdef RTE_LIBRTE_PMD_BBDEV_FPGA_LTE_FEC
520         if ((get_init_device() == true) &&
521                 (!strcmp(info->drv.driver_name, FPGA_LTE_PF_DRIVER_NAME))) {
522                 struct fpga_lte_fec_conf conf;
523                 unsigned int i;
524
525                 printf("Configure FPGA LTE FEC Driver %s with default values\n",
526                                 info->drv.driver_name);
527
528                 /* clear default configuration before initialization */
529                 memset(&conf, 0, sizeof(struct fpga_lte_fec_conf));
530
531                 /* Set PF mode :
532                  * true if PF is used for data plane
533                  * false for VFs
534                  */
535                 conf.pf_mode_en = true;
536
537                 for (i = 0; i < FPGA_LTE_FEC_NUM_VFS; ++i) {
538                         /* Number of UL queues per VF (fpga supports 8 VFs) */
539                         conf.vf_ul_queues_number[i] = VF_UL_4G_QUEUE_VALUE;
540                         /* Number of DL queues per VF (fpga supports 8 VFs) */
541                         conf.vf_dl_queues_number[i] = VF_DL_4G_QUEUE_VALUE;
542                 }
543
544                 /* UL bandwidth. Needed for schedule algorithm */
545                 conf.ul_bandwidth = UL_4G_BANDWIDTH;
546                 /* DL bandwidth */
547                 conf.dl_bandwidth = DL_4G_BANDWIDTH;
548
549                 /* UL & DL load Balance Factor to 64 */
550                 conf.ul_load_balance = UL_4G_LOAD_BALANCE;
551                 conf.dl_load_balance = DL_4G_LOAD_BALANCE;
552
553                 /**< FLR timeout value */
554                 conf.flr_time_out = FLR_4G_TIMEOUT;
555
556                 /* setup FPGA PF with configuration information */
557                 ret = fpga_lte_fec_configure(info->dev_name, &conf);
558                 TEST_ASSERT_SUCCESS(ret,
559                                 "Failed to configure 4G FPGA PF for bbdev %s",
560                                 info->dev_name);
561         }
562 #endif
563         nb_queues = RTE_MIN(rte_lcore_count(), info->drv.max_num_queues);
564         nb_queues = RTE_MIN(nb_queues, (unsigned int) MAX_QUEUES);
565
566         /* setup device */
567         ret = rte_bbdev_setup_queues(dev_id, nb_queues, info->socket_id);
568         if (ret < 0) {
569                 printf("rte_bbdev_setup_queues(%u, %u, %d) ret %i\n",
570                                 dev_id, nb_queues, info->socket_id, ret);
571                 return TEST_FAILED;
572         }
573
574         /* configure interrupts if needed */
575         if (intr_enabled) {
576                 ret = rte_bbdev_intr_enable(dev_id);
577                 if (ret < 0) {
578                         printf("rte_bbdev_intr_enable(%u) ret %i\n", dev_id,
579                                         ret);
580                         return TEST_FAILED;
581                 }
582         }
583
584         /* setup device queues */
585         qconf.socket = info->socket_id;
586         qconf.queue_size = info->drv.default_queue_conf.queue_size;
587         qconf.priority = 0;
588         qconf.deferred_start = 0;
589         qconf.op_type = op_type;
590
591         for (queue_id = 0; queue_id < nb_queues; ++queue_id) {
592                 ret = rte_bbdev_queue_configure(dev_id, queue_id, &qconf);
593                 if (ret != 0) {
594                         printf(
595                                         "Allocated all queues (id=%u) at prio%u on dev%u\n",
596                                         queue_id, qconf.priority, dev_id);
597                         qconf.priority++;
598                         ret = rte_bbdev_queue_configure(ad->dev_id, queue_id,
599                                         &qconf);
600                 }
601                 if (ret != 0) {
602                         printf("All queues on dev %u allocated: %u\n",
603                                         dev_id, queue_id);
604                         break;
605                 }
606                 ad->queue_ids[queue_id] = queue_id;
607         }
608         TEST_ASSERT(queue_id != 0,
609                         "ERROR Failed to configure any queues on dev %u",
610                         dev_id);
611         ad->nb_queues = queue_id;
612
613         set_avail_op(ad, op_type);
614
615         return TEST_SUCCESS;
616 }
617
618 static int
619 add_active_device(uint8_t dev_id, struct rte_bbdev_info *info,
620                 struct test_bbdev_vector *vector)
621 {
622         int ret;
623
624         active_devs[nb_active_devs].driver_name = info->drv.driver_name;
625         active_devs[nb_active_devs].dev_id = dev_id;
626
627         ret = add_bbdev_dev(dev_id, info, vector);
628         if (ret == TEST_SUCCESS)
629                 ++nb_active_devs;
630         return ret;
631 }
632
633 static uint8_t
634 populate_active_devices(void)
635 {
636         int ret;
637         uint8_t dev_id;
638         uint8_t nb_devs_added = 0;
639         struct rte_bbdev_info info;
640
641         RTE_BBDEV_FOREACH(dev_id) {
642                 rte_bbdev_info_get(dev_id, &info);
643
644                 if (check_dev_cap(&info)) {
645                         printf(
646                                 "Device %d (%s) does not support specified capabilities\n",
647                                         dev_id, info.dev_name);
648                         continue;
649                 }
650
651                 ret = add_active_device(dev_id, &info, &test_vector);
652                 if (ret != 0) {
653                         printf("Adding active bbdev %s skipped\n",
654                                         info.dev_name);
655                         continue;
656                 }
657                 nb_devs_added++;
658         }
659
660         return nb_devs_added;
661 }
662
663 static int
664 read_test_vector(void)
665 {
666         int ret;
667
668         memset(&test_vector, 0, sizeof(test_vector));
669         printf("Test vector file = %s\n", get_vector_filename());
670         ret = test_bbdev_vector_read(get_vector_filename(), &test_vector);
671         TEST_ASSERT_SUCCESS(ret, "Failed to parse file %s\n",
672                         get_vector_filename());
673
674         return TEST_SUCCESS;
675 }
676
677 static int
678 testsuite_setup(void)
679 {
680         TEST_ASSERT_SUCCESS(read_test_vector(), "Test suite setup failed\n");
681
682         if (populate_active_devices() == 0) {
683                 printf("No suitable devices found!\n");
684                 return TEST_SKIPPED;
685         }
686
687         return TEST_SUCCESS;
688 }
689
690 static int
691 interrupt_testsuite_setup(void)
692 {
693         TEST_ASSERT_SUCCESS(read_test_vector(), "Test suite setup failed\n");
694
695         /* Enable interrupts */
696         intr_enabled = true;
697
698         /* Special case for NULL device (RTE_BBDEV_OP_NONE) */
699         if (populate_active_devices() == 0 ||
700                         test_vector.op_type == RTE_BBDEV_OP_NONE) {
701                 intr_enabled = false;
702                 printf("No suitable devices found!\n");
703                 return TEST_SKIPPED;
704         }
705
706         return TEST_SUCCESS;
707 }
708
709 static void
710 testsuite_teardown(void)
711 {
712         uint8_t dev_id;
713
714         /* Unconfigure devices */
715         RTE_BBDEV_FOREACH(dev_id)
716                 rte_bbdev_close(dev_id);
717
718         /* Clear active devices structs. */
719         memset(active_devs, 0, sizeof(active_devs));
720         nb_active_devs = 0;
721 }
722
723 static int
724 ut_setup(void)
725 {
726         uint8_t i, dev_id;
727
728         for (i = 0; i < nb_active_devs; i++) {
729                 dev_id = active_devs[i].dev_id;
730                 /* reset bbdev stats */
731                 TEST_ASSERT_SUCCESS(rte_bbdev_stats_reset(dev_id),
732                                 "Failed to reset stats of bbdev %u", dev_id);
733                 /* start the device */
734                 TEST_ASSERT_SUCCESS(rte_bbdev_start(dev_id),
735                                 "Failed to start bbdev %u", dev_id);
736         }
737
738         return TEST_SUCCESS;
739 }
740
741 static void
742 ut_teardown(void)
743 {
744         uint8_t i, dev_id;
745         struct rte_bbdev_stats stats;
746
747         for (i = 0; i < nb_active_devs; i++) {
748                 dev_id = active_devs[i].dev_id;
749                 /* read stats and print */
750                 rte_bbdev_stats_get(dev_id, &stats);
751                 /* Stop the device */
752                 rte_bbdev_stop(dev_id);
753         }
754 }
755
756 static int
757 init_op_data_objs(struct rte_bbdev_op_data *bufs,
758                 struct op_data_entries *ref_entries,
759                 struct rte_mempool *mbuf_pool, const uint16_t n,
760                 enum op_data_type op_type, uint16_t min_alignment)
761 {
762         int ret;
763         unsigned int i, j;
764         bool large_input = false;
765
766         for (i = 0; i < n; ++i) {
767                 char *data;
768                 struct op_data_buf *seg = &ref_entries->segments[0];
769                 struct rte_mbuf *m_head = rte_pktmbuf_alloc(mbuf_pool);
770                 TEST_ASSERT_NOT_NULL(m_head,
771                                 "Not enough mbufs in %d data type mbuf pool (needed %u, available %u)",
772                                 op_type, n * ref_entries->nb_segments,
773                                 mbuf_pool->size);
774
775                 if (seg->length > RTE_BBDEV_LDPC_E_MAX_MBUF) {
776                         /*
777                          * Special case when DPDK mbuf cannot handle
778                          * the required input size
779                          */
780                         printf("Warning: Larger input size than DPDK mbuf %d\n",
781                                         seg->length);
782                         large_input = true;
783                 }
784                 bufs[i].data = m_head;
785                 bufs[i].offset = 0;
786                 bufs[i].length = 0;
787
788                 if ((op_type == DATA_INPUT) || (op_type == DATA_HARQ_INPUT)) {
789                         if ((op_type == DATA_INPUT) && large_input) {
790                                 /* Allocate a fake overused mbuf */
791                                 data = rte_malloc(NULL, seg->length, 0);
792                                 memcpy(data, seg->addr, seg->length);
793                                 m_head->buf_addr = data;
794                                 m_head->buf_iova = rte_malloc_virt2iova(data);
795                                 m_head->data_off = 0;
796                                 m_head->data_len = seg->length;
797                         } else {
798                                 data = rte_pktmbuf_append(m_head, seg->length);
799                                 TEST_ASSERT_NOT_NULL(data,
800                                         "Couldn't append %u bytes to mbuf from %d data type mbuf pool",
801                                         seg->length, op_type);
802
803                                 TEST_ASSERT(data == RTE_PTR_ALIGN(
804                                                 data, min_alignment),
805                                         "Data addr in mbuf (%p) is not aligned to device min alignment (%u)",
806                                         data, min_alignment);
807                                 rte_memcpy(data, seg->addr, seg->length);
808                         }
809
810                         bufs[i].length += seg->length;
811
812                         for (j = 1; j < ref_entries->nb_segments; ++j) {
813                                 struct rte_mbuf *m_tail =
814                                                 rte_pktmbuf_alloc(mbuf_pool);
815                                 TEST_ASSERT_NOT_NULL(m_tail,
816                                                 "Not enough mbufs in %d data type mbuf pool (needed %u, available %u)",
817                                                 op_type,
818                                                 n * ref_entries->nb_segments,
819                                                 mbuf_pool->size);
820                                 seg += 1;
821
822                                 data = rte_pktmbuf_append(m_tail, seg->length);
823                                 TEST_ASSERT_NOT_NULL(data,
824                                                 "Couldn't append %u bytes to mbuf from %d data type mbuf pool",
825                                                 seg->length, op_type);
826
827                                 TEST_ASSERT(data == RTE_PTR_ALIGN(data,
828                                                 min_alignment),
829                                                 "Data addr in mbuf (%p) is not aligned to device min alignment (%u)",
830                                                 data, min_alignment);
831                                 rte_memcpy(data, seg->addr, seg->length);
832                                 bufs[i].length += seg->length;
833
834                                 ret = rte_pktmbuf_chain(m_head, m_tail);
835                                 TEST_ASSERT_SUCCESS(ret,
836                                                 "Couldn't chain mbufs from %d data type mbuf pool",
837                                                 op_type);
838                         }
839                 } else {
840
841                         /* allocate chained-mbuf for output buffer */
842                         for (j = 1; j < ref_entries->nb_segments; ++j) {
843                                 struct rte_mbuf *m_tail =
844                                                 rte_pktmbuf_alloc(mbuf_pool);
845                                 TEST_ASSERT_NOT_NULL(m_tail,
846                                                 "Not enough mbufs in %d data type mbuf pool (needed %u, available %u)",
847                                                 op_type,
848                                                 n * ref_entries->nb_segments,
849                                                 mbuf_pool->size);
850
851                                 ret = rte_pktmbuf_chain(m_head, m_tail);
852                                 TEST_ASSERT_SUCCESS(ret,
853                                                 "Couldn't chain mbufs from %d data type mbuf pool",
854                                                 op_type);
855                         }
856                 }
857         }
858
859         return 0;
860 }
861
862 static int
863 allocate_buffers_on_socket(struct rte_bbdev_op_data **buffers, const int len,
864                 const int socket)
865 {
866         int i;
867
868         *buffers = rte_zmalloc_socket(NULL, len, 0, socket);
869         if (*buffers == NULL) {
870                 printf("WARNING: Failed to allocate op_data on socket %d\n",
871                                 socket);
872                 /* try to allocate memory on other detected sockets */
873                 for (i = 0; i < socket; i++) {
874                         *buffers = rte_zmalloc_socket(NULL, len, 0, i);
875                         if (*buffers != NULL)
876                                 break;
877                 }
878         }
879
880         return (*buffers == NULL) ? TEST_FAILED : TEST_SUCCESS;
881 }
882
883 static void
884 limit_input_llr_val_range(struct rte_bbdev_op_data *input_ops,
885                 const uint16_t n, const int8_t max_llr_modulus)
886 {
887         uint16_t i, byte_idx;
888
889         for (i = 0; i < n; ++i) {
890                 struct rte_mbuf *m = input_ops[i].data;
891                 while (m != NULL) {
892                         int8_t *llr = rte_pktmbuf_mtod_offset(m, int8_t *,
893                                         input_ops[i].offset);
894                         for (byte_idx = 0; byte_idx < rte_pktmbuf_data_len(m);
895                                         ++byte_idx)
896                                 llr[byte_idx] = round((double)max_llr_modulus *
897                                                 llr[byte_idx] / INT8_MAX);
898
899                         m = m->next;
900                 }
901         }
902 }
903
904 static void
905 ldpc_input_llr_scaling(struct rte_bbdev_op_data *input_ops,
906                 const uint16_t n, const int8_t llr_size,
907                 const int8_t llr_decimals)
908 {
909         if (input_ops == NULL)
910                 return;
911
912         uint16_t i, byte_idx;
913
914         int16_t llr_max, llr_min, llr_tmp;
915         llr_max = (1 << (llr_size - 1)) - 1;
916         llr_min = -llr_max;
917         for (i = 0; i < n; ++i) {
918                 struct rte_mbuf *m = input_ops[i].data;
919                 while (m != NULL) {
920                         int8_t *llr = rte_pktmbuf_mtod_offset(m, int8_t *,
921                                         input_ops[i].offset);
922                         for (byte_idx = 0; byte_idx < rte_pktmbuf_data_len(m);
923                                         ++byte_idx) {
924
925                                 llr_tmp = llr[byte_idx];
926                                 if (llr_decimals == 2)
927                                         llr_tmp *= 2;
928                                 else if (llr_decimals == 0)
929                                         llr_tmp /= 2;
930                                 llr_tmp = RTE_MIN(llr_max,
931                                                 RTE_MAX(llr_min, llr_tmp));
932                                 llr[byte_idx] = (int8_t) llr_tmp;
933                         }
934
935                         m = m->next;
936                 }
937         }
938 }
939
940
941
942 static int
943 fill_queue_buffers(struct test_op_params *op_params,
944                 struct rte_mempool *in_mp, struct rte_mempool *hard_out_mp,
945                 struct rte_mempool *soft_out_mp,
946                 struct rte_mempool *harq_in_mp, struct rte_mempool *harq_out_mp,
947                 uint16_t queue_id,
948                 const struct rte_bbdev_op_cap *capabilities,
949                 uint16_t min_alignment, const int socket_id)
950 {
951         int ret;
952         enum op_data_type type;
953         const uint16_t n = op_params->num_to_process;
954
955         struct rte_mempool *mbuf_pools[DATA_NUM_TYPES] = {
956                 in_mp,
957                 soft_out_mp,
958                 hard_out_mp,
959                 harq_in_mp,
960                 harq_out_mp,
961         };
962
963         struct rte_bbdev_op_data **queue_ops[DATA_NUM_TYPES] = {
964                 &op_params->q_bufs[socket_id][queue_id].inputs,
965                 &op_params->q_bufs[socket_id][queue_id].soft_outputs,
966                 &op_params->q_bufs[socket_id][queue_id].hard_outputs,
967                 &op_params->q_bufs[socket_id][queue_id].harq_inputs,
968                 &op_params->q_bufs[socket_id][queue_id].harq_outputs,
969         };
970
971         for (type = DATA_INPUT; type < DATA_NUM_TYPES; ++type) {
972                 struct op_data_entries *ref_entries =
973                                 &test_vector.entries[type];
974                 if (ref_entries->nb_segments == 0)
975                         continue;
976
977                 ret = allocate_buffers_on_socket(queue_ops[type],
978                                 n * sizeof(struct rte_bbdev_op_data),
979                                 socket_id);
980                 TEST_ASSERT_SUCCESS(ret,
981                                 "Couldn't allocate memory for rte_bbdev_op_data structs");
982
983                 ret = init_op_data_objs(*queue_ops[type], ref_entries,
984                                 mbuf_pools[type], n, type, min_alignment);
985                 TEST_ASSERT_SUCCESS(ret,
986                                 "Couldn't init rte_bbdev_op_data structs");
987         }
988
989         if (test_vector.op_type == RTE_BBDEV_OP_TURBO_DEC)
990                 limit_input_llr_val_range(*queue_ops[DATA_INPUT], n,
991                         capabilities->cap.turbo_dec.max_llr_modulus);
992
993         if (test_vector.op_type == RTE_BBDEV_OP_LDPC_DEC) {
994                 ldpc_input_llr_scaling(*queue_ops[DATA_INPUT], n,
995                         capabilities->cap.ldpc_dec.llr_size,
996                         capabilities->cap.ldpc_dec.llr_decimals);
997                 ldpc_input_llr_scaling(*queue_ops[DATA_HARQ_INPUT], n,
998                                 capabilities->cap.ldpc_dec.llr_size,
999                                 capabilities->cap.ldpc_dec.llr_decimals);
1000         }
1001
1002         return 0;
1003 }
1004
1005 static void
1006 free_buffers(struct active_device *ad, struct test_op_params *op_params)
1007 {
1008         unsigned int i, j;
1009
1010         rte_mempool_free(ad->ops_mempool);
1011         rte_mempool_free(ad->in_mbuf_pool);
1012         rte_mempool_free(ad->hard_out_mbuf_pool);
1013         rte_mempool_free(ad->soft_out_mbuf_pool);
1014         rte_mempool_free(ad->harq_in_mbuf_pool);
1015         rte_mempool_free(ad->harq_out_mbuf_pool);
1016
1017         for (i = 0; i < rte_lcore_count(); ++i) {
1018                 for (j = 0; j < RTE_MAX_NUMA_NODES; ++j) {
1019                         rte_free(op_params->q_bufs[j][i].inputs);
1020                         rte_free(op_params->q_bufs[j][i].hard_outputs);
1021                         rte_free(op_params->q_bufs[j][i].soft_outputs);
1022                         rte_free(op_params->q_bufs[j][i].harq_inputs);
1023                         rte_free(op_params->q_bufs[j][i].harq_outputs);
1024                 }
1025         }
1026 }
1027
1028 static void
1029 copy_reference_dec_op(struct rte_bbdev_dec_op **ops, unsigned int n,
1030                 unsigned int start_idx,
1031                 struct rte_bbdev_op_data *inputs,
1032                 struct rte_bbdev_op_data *hard_outputs,
1033                 struct rte_bbdev_op_data *soft_outputs,
1034                 struct rte_bbdev_dec_op *ref_op)
1035 {
1036         unsigned int i;
1037         struct rte_bbdev_op_turbo_dec *turbo_dec = &ref_op->turbo_dec;
1038
1039         for (i = 0; i < n; ++i) {
1040                 if (turbo_dec->code_block_mode == 0) {
1041                         ops[i]->turbo_dec.tb_params.ea =
1042                                         turbo_dec->tb_params.ea;
1043                         ops[i]->turbo_dec.tb_params.eb =
1044                                         turbo_dec->tb_params.eb;
1045                         ops[i]->turbo_dec.tb_params.k_pos =
1046                                         turbo_dec->tb_params.k_pos;
1047                         ops[i]->turbo_dec.tb_params.k_neg =
1048                                         turbo_dec->tb_params.k_neg;
1049                         ops[i]->turbo_dec.tb_params.c =
1050                                         turbo_dec->tb_params.c;
1051                         ops[i]->turbo_dec.tb_params.c_neg =
1052                                         turbo_dec->tb_params.c_neg;
1053                         ops[i]->turbo_dec.tb_params.cab =
1054                                         turbo_dec->tb_params.cab;
1055                         ops[i]->turbo_dec.tb_params.r =
1056                                         turbo_dec->tb_params.r;
1057                 } else {
1058                         ops[i]->turbo_dec.cb_params.e = turbo_dec->cb_params.e;
1059                         ops[i]->turbo_dec.cb_params.k = turbo_dec->cb_params.k;
1060                 }
1061
1062                 ops[i]->turbo_dec.ext_scale = turbo_dec->ext_scale;
1063                 ops[i]->turbo_dec.iter_max = turbo_dec->iter_max;
1064                 ops[i]->turbo_dec.iter_min = turbo_dec->iter_min;
1065                 ops[i]->turbo_dec.op_flags = turbo_dec->op_flags;
1066                 ops[i]->turbo_dec.rv_index = turbo_dec->rv_index;
1067                 ops[i]->turbo_dec.num_maps = turbo_dec->num_maps;
1068                 ops[i]->turbo_dec.code_block_mode = turbo_dec->code_block_mode;
1069
1070                 ops[i]->turbo_dec.hard_output = hard_outputs[start_idx + i];
1071                 ops[i]->turbo_dec.input = inputs[start_idx + i];
1072                 if (soft_outputs != NULL)
1073                         ops[i]->turbo_dec.soft_output =
1074                                 soft_outputs[start_idx + i];
1075         }
1076 }
1077
1078 static void
1079 copy_reference_enc_op(struct rte_bbdev_enc_op **ops, unsigned int n,
1080                 unsigned int start_idx,
1081                 struct rte_bbdev_op_data *inputs,
1082                 struct rte_bbdev_op_data *outputs,
1083                 struct rte_bbdev_enc_op *ref_op)
1084 {
1085         unsigned int i;
1086         struct rte_bbdev_op_turbo_enc *turbo_enc = &ref_op->turbo_enc;
1087         for (i = 0; i < n; ++i) {
1088                 if (turbo_enc->code_block_mode == 0) {
1089                         ops[i]->turbo_enc.tb_params.ea =
1090                                         turbo_enc->tb_params.ea;
1091                         ops[i]->turbo_enc.tb_params.eb =
1092                                         turbo_enc->tb_params.eb;
1093                         ops[i]->turbo_enc.tb_params.k_pos =
1094                                         turbo_enc->tb_params.k_pos;
1095                         ops[i]->turbo_enc.tb_params.k_neg =
1096                                         turbo_enc->tb_params.k_neg;
1097                         ops[i]->turbo_enc.tb_params.c =
1098                                         turbo_enc->tb_params.c;
1099                         ops[i]->turbo_enc.tb_params.c_neg =
1100                                         turbo_enc->tb_params.c_neg;
1101                         ops[i]->turbo_enc.tb_params.cab =
1102                                         turbo_enc->tb_params.cab;
1103                         ops[i]->turbo_enc.tb_params.ncb_pos =
1104                                         turbo_enc->tb_params.ncb_pos;
1105                         ops[i]->turbo_enc.tb_params.ncb_neg =
1106                                         turbo_enc->tb_params.ncb_neg;
1107                         ops[i]->turbo_enc.tb_params.r = turbo_enc->tb_params.r;
1108                 } else {
1109                         ops[i]->turbo_enc.cb_params.e = turbo_enc->cb_params.e;
1110                         ops[i]->turbo_enc.cb_params.k = turbo_enc->cb_params.k;
1111                         ops[i]->turbo_enc.cb_params.ncb =
1112                                         turbo_enc->cb_params.ncb;
1113                 }
1114                 ops[i]->turbo_enc.rv_index = turbo_enc->rv_index;
1115                 ops[i]->turbo_enc.op_flags = turbo_enc->op_flags;
1116                 ops[i]->turbo_enc.code_block_mode = turbo_enc->code_block_mode;
1117
1118                 ops[i]->turbo_enc.output = outputs[start_idx + i];
1119                 ops[i]->turbo_enc.input = inputs[start_idx + i];
1120         }
1121 }
1122
1123 static void
1124 copy_reference_ldpc_dec_op(struct rte_bbdev_dec_op **ops, unsigned int n,
1125                 unsigned int start_idx,
1126                 struct rte_bbdev_op_data *inputs,
1127                 struct rte_bbdev_op_data *hard_outputs,
1128                 struct rte_bbdev_op_data *soft_outputs,
1129                 struct rte_bbdev_op_data *harq_inputs,
1130                 struct rte_bbdev_op_data *harq_outputs,
1131                 struct rte_bbdev_dec_op *ref_op)
1132 {
1133         unsigned int i;
1134         struct rte_bbdev_op_ldpc_dec *ldpc_dec = &ref_op->ldpc_dec;
1135
1136         for (i = 0; i < n; ++i) {
1137                 if (ldpc_dec->code_block_mode == 0) {
1138                         ops[i]->ldpc_dec.tb_params.ea =
1139                                         ldpc_dec->tb_params.ea;
1140                         ops[i]->ldpc_dec.tb_params.eb =
1141                                         ldpc_dec->tb_params.eb;
1142                         ops[i]->ldpc_dec.tb_params.c =
1143                                         ldpc_dec->tb_params.c;
1144                         ops[i]->ldpc_dec.tb_params.cab =
1145                                         ldpc_dec->tb_params.cab;
1146                         ops[i]->ldpc_dec.tb_params.r =
1147                                         ldpc_dec->tb_params.r;
1148                 } else {
1149                         ops[i]->ldpc_dec.cb_params.e = ldpc_dec->cb_params.e;
1150                 }
1151
1152                 ops[i]->ldpc_dec.basegraph = ldpc_dec->basegraph;
1153                 ops[i]->ldpc_dec.z_c = ldpc_dec->z_c;
1154                 ops[i]->ldpc_dec.q_m = ldpc_dec->q_m;
1155                 ops[i]->ldpc_dec.n_filler = ldpc_dec->n_filler;
1156                 ops[i]->ldpc_dec.n_cb = ldpc_dec->n_cb;
1157                 ops[i]->ldpc_dec.iter_max = ldpc_dec->iter_max;
1158                 ops[i]->ldpc_dec.rv_index = ldpc_dec->rv_index;
1159                 ops[i]->ldpc_dec.op_flags = ldpc_dec->op_flags;
1160                 ops[i]->ldpc_dec.code_block_mode = ldpc_dec->code_block_mode;
1161
1162                 ops[i]->ldpc_dec.hard_output = hard_outputs[start_idx + i];
1163                 ops[i]->ldpc_dec.input = inputs[start_idx + i];
1164                 if (soft_outputs != NULL)
1165                         ops[i]->ldpc_dec.soft_output =
1166                                 soft_outputs[start_idx + i];
1167                 if (harq_inputs != NULL)
1168                         ops[i]->ldpc_dec.harq_combined_input =
1169                                         harq_inputs[start_idx + i];
1170                 if (harq_outputs != NULL)
1171                         ops[i]->ldpc_dec.harq_combined_output =
1172                                 harq_outputs[start_idx + i];
1173         }
1174 }
1175
1176
1177 static void
1178 copy_reference_ldpc_enc_op(struct rte_bbdev_enc_op **ops, unsigned int n,
1179                 unsigned int start_idx,
1180                 struct rte_bbdev_op_data *inputs,
1181                 struct rte_bbdev_op_data *outputs,
1182                 struct rte_bbdev_enc_op *ref_op)
1183 {
1184         unsigned int i;
1185         struct rte_bbdev_op_ldpc_enc *ldpc_enc = &ref_op->ldpc_enc;
1186         for (i = 0; i < n; ++i) {
1187                 if (ldpc_enc->code_block_mode == 0) {
1188                         ops[i]->ldpc_enc.tb_params.ea = ldpc_enc->tb_params.ea;
1189                         ops[i]->ldpc_enc.tb_params.eb = ldpc_enc->tb_params.eb;
1190                         ops[i]->ldpc_enc.tb_params.cab =
1191                                         ldpc_enc->tb_params.cab;
1192                         ops[i]->ldpc_enc.tb_params.c = ldpc_enc->tb_params.c;
1193                         ops[i]->ldpc_enc.tb_params.r = ldpc_enc->tb_params.r;
1194                 } else {
1195                         ops[i]->ldpc_enc.cb_params.e = ldpc_enc->cb_params.e;
1196                 }
1197                 ops[i]->ldpc_enc.basegraph = ldpc_enc->basegraph;
1198                 ops[i]->ldpc_enc.z_c = ldpc_enc->z_c;
1199                 ops[i]->ldpc_enc.q_m = ldpc_enc->q_m;
1200                 ops[i]->ldpc_enc.n_filler = ldpc_enc->n_filler;
1201                 ops[i]->ldpc_enc.n_cb = ldpc_enc->n_cb;
1202                 ops[i]->ldpc_enc.rv_index = ldpc_enc->rv_index;
1203                 ops[i]->ldpc_enc.op_flags = ldpc_enc->op_flags;
1204                 ops[i]->ldpc_enc.code_block_mode = ldpc_enc->code_block_mode;
1205                 ops[i]->ldpc_enc.output = outputs[start_idx + i];
1206                 ops[i]->ldpc_enc.input = inputs[start_idx + i];
1207         }
1208 }
1209
1210 static int
1211 check_dec_status_and_ordering(struct rte_bbdev_dec_op *op,
1212                 unsigned int order_idx, const int expected_status)
1213 {
1214         TEST_ASSERT(op->status == expected_status,
1215                         "op_status (%d) != expected_status (%d)",
1216                         op->status, expected_status);
1217
1218         TEST_ASSERT((void *)(uintptr_t)order_idx == op->opaque_data,
1219                         "Ordering error, expected %p, got %p",
1220                         (void *)(uintptr_t)order_idx, op->opaque_data);
1221
1222         return TEST_SUCCESS;
1223 }
1224
1225 static int
1226 check_enc_status_and_ordering(struct rte_bbdev_enc_op *op,
1227                 unsigned int order_idx, const int expected_status)
1228 {
1229         TEST_ASSERT(op->status == expected_status,
1230                         "op_status (%d) != expected_status (%d)",
1231                         op->status, expected_status);
1232
1233         TEST_ASSERT((void *)(uintptr_t)order_idx == op->opaque_data,
1234                         "Ordering error, expected %p, got %p",
1235                         (void *)(uintptr_t)order_idx, op->opaque_data);
1236
1237         return TEST_SUCCESS;
1238 }
1239
1240 static inline int
1241 validate_op_chain(struct rte_bbdev_op_data *op,
1242                 struct op_data_entries *orig_op)
1243 {
1244         uint8_t i;
1245         struct rte_mbuf *m = op->data;
1246         uint8_t nb_dst_segments = orig_op->nb_segments;
1247         uint32_t total_data_size = 0;
1248
1249         TEST_ASSERT(nb_dst_segments == m->nb_segs,
1250                         "Number of segments differ in original (%u) and filled (%u) op",
1251                         nb_dst_segments, m->nb_segs);
1252
1253         /* Validate each mbuf segment length */
1254         for (i = 0; i < nb_dst_segments; ++i) {
1255                 /* Apply offset to the first mbuf segment */
1256                 uint16_t offset = (i == 0) ? op->offset : 0;
1257                 uint16_t data_len = rte_pktmbuf_data_len(m) - offset;
1258                 total_data_size += orig_op->segments[i].length;
1259
1260                 TEST_ASSERT(orig_op->segments[i].length == data_len,
1261                                 "Length of segment differ in original (%u) and filled (%u) op",
1262                                 orig_op->segments[i].length, data_len);
1263                 TEST_ASSERT_BUFFERS_ARE_EQUAL(orig_op->segments[i].addr,
1264                                 rte_pktmbuf_mtod_offset(m, uint32_t *, offset),
1265                                 data_len,
1266                                 "Output buffers (CB=%u) are not equal", i);
1267                 m = m->next;
1268         }
1269
1270         /* Validate total mbuf pkt length */
1271         uint32_t pkt_len = rte_pktmbuf_pkt_len(op->data) - op->offset;
1272         TEST_ASSERT(total_data_size == pkt_len,
1273                         "Length of data differ in original (%u) and filled (%u) op",
1274                         total_data_size, pkt_len);
1275
1276         return TEST_SUCCESS;
1277 }
1278
1279 static int
1280 validate_dec_op(struct rte_bbdev_dec_op **ops, const uint16_t n,
1281                 struct rte_bbdev_dec_op *ref_op, const int vector_mask)
1282 {
1283         unsigned int i;
1284         int ret;
1285         struct op_data_entries *hard_data_orig =
1286                         &test_vector.entries[DATA_HARD_OUTPUT];
1287         struct op_data_entries *soft_data_orig =
1288                         &test_vector.entries[DATA_SOFT_OUTPUT];
1289         struct rte_bbdev_op_turbo_dec *ops_td;
1290         struct rte_bbdev_op_data *hard_output;
1291         struct rte_bbdev_op_data *soft_output;
1292         struct rte_bbdev_op_turbo_dec *ref_td = &ref_op->turbo_dec;
1293
1294         for (i = 0; i < n; ++i) {
1295                 ops_td = &ops[i]->turbo_dec;
1296                 hard_output = &ops_td->hard_output;
1297                 soft_output = &ops_td->soft_output;
1298
1299                 if (vector_mask & TEST_BBDEV_VF_EXPECTED_ITER_COUNT)
1300                         TEST_ASSERT(ops_td->iter_count <= ref_td->iter_count,
1301                                         "Returned iter_count (%d) > expected iter_count (%d)",
1302                                         ops_td->iter_count, ref_td->iter_count);
1303                 ret = check_dec_status_and_ordering(ops[i], i, ref_op->status);
1304                 TEST_ASSERT_SUCCESS(ret,
1305                                 "Checking status and ordering for decoder failed");
1306
1307                 TEST_ASSERT_SUCCESS(validate_op_chain(hard_output,
1308                                 hard_data_orig),
1309                                 "Hard output buffers (CB=%u) are not equal",
1310                                 i);
1311
1312                 if (ref_op->turbo_dec.op_flags & RTE_BBDEV_TURBO_SOFT_OUTPUT)
1313                         TEST_ASSERT_SUCCESS(validate_op_chain(soft_output,
1314                                         soft_data_orig),
1315                                         "Soft output buffers (CB=%u) are not equal",
1316                                         i);
1317         }
1318
1319         return TEST_SUCCESS;
1320 }
1321
1322
1323 static int
1324 validate_ldpc_dec_op(struct rte_bbdev_dec_op **ops, const uint16_t n,
1325                 struct rte_bbdev_dec_op *ref_op, const int vector_mask)
1326 {
1327         unsigned int i;
1328         int ret;
1329         struct op_data_entries *hard_data_orig =
1330                         &test_vector.entries[DATA_HARD_OUTPUT];
1331         struct op_data_entries *soft_data_orig =
1332                         &test_vector.entries[DATA_SOFT_OUTPUT];
1333         struct op_data_entries *harq_data_orig =
1334                                 &test_vector.entries[DATA_HARQ_OUTPUT];
1335         struct rte_bbdev_op_ldpc_dec *ops_td;
1336         struct rte_bbdev_op_data *hard_output;
1337         struct rte_bbdev_op_data *harq_output;
1338         struct rte_bbdev_op_data *soft_output;
1339         struct rte_bbdev_op_ldpc_dec *ref_td = &ref_op->ldpc_dec;
1340
1341         for (i = 0; i < n; ++i) {
1342                 ops_td = &ops[i]->ldpc_dec;
1343                 hard_output = &ops_td->hard_output;
1344                 harq_output = &ops_td->harq_combined_output;
1345                 soft_output = &ops_td->soft_output;
1346
1347                 ret = check_dec_status_and_ordering(ops[i], i, ref_op->status);
1348                 TEST_ASSERT_SUCCESS(ret,
1349                                 "Checking status and ordering for decoder failed");
1350                 if (vector_mask & TEST_BBDEV_VF_EXPECTED_ITER_COUNT)
1351                         TEST_ASSERT(ops_td->iter_count <= ref_td->iter_count,
1352                                         "Returned iter_count (%d) > expected iter_count (%d)",
1353                                         ops_td->iter_count, ref_td->iter_count);
1354                 /* We can ignore data when the decoding failed to converge */
1355                 if ((ops[i]->status &  (1 << RTE_BBDEV_SYNDROME_ERROR)) == 0)
1356                         TEST_ASSERT_SUCCESS(validate_op_chain(hard_output,
1357                                         hard_data_orig),
1358                                         "Hard output buffers (CB=%u) are not equal",
1359                                         i);
1360
1361                 if (ref_op->ldpc_dec.op_flags & RTE_BBDEV_LDPC_SOFT_OUT_ENABLE)
1362                         TEST_ASSERT_SUCCESS(validate_op_chain(soft_output,
1363                                         soft_data_orig),
1364                                         "Soft output buffers (CB=%u) are not equal",
1365                                         i);
1366                 if (ref_op->ldpc_dec.op_flags &
1367                                 RTE_BBDEV_LDPC_HQ_COMBINE_OUT_ENABLE) {
1368                         ldpc_input_llr_scaling(harq_output, 1, 8, 0);
1369                         TEST_ASSERT_SUCCESS(validate_op_chain(harq_output,
1370                                         harq_data_orig),
1371                                         "HARQ output buffers (CB=%u) are not equal",
1372                                         i);
1373                 }
1374         }
1375
1376         return TEST_SUCCESS;
1377 }
1378
1379
1380 static int
1381 validate_enc_op(struct rte_bbdev_enc_op **ops, const uint16_t n,
1382                 struct rte_bbdev_enc_op *ref_op)
1383 {
1384         unsigned int i;
1385         int ret;
1386         struct op_data_entries *hard_data_orig =
1387                         &test_vector.entries[DATA_HARD_OUTPUT];
1388
1389         for (i = 0; i < n; ++i) {
1390                 ret = check_enc_status_and_ordering(ops[i], i, ref_op->status);
1391                 TEST_ASSERT_SUCCESS(ret,
1392                                 "Checking status and ordering for encoder failed");
1393                 TEST_ASSERT_SUCCESS(validate_op_chain(
1394                                 &ops[i]->turbo_enc.output,
1395                                 hard_data_orig),
1396                                 "Output buffers (CB=%u) are not equal",
1397                                 i);
1398         }
1399
1400         return TEST_SUCCESS;
1401 }
1402
1403 static int
1404 validate_ldpc_enc_op(struct rte_bbdev_enc_op **ops, const uint16_t n,
1405                 struct rte_bbdev_enc_op *ref_op)
1406 {
1407         unsigned int i;
1408         int ret;
1409         struct op_data_entries *hard_data_orig =
1410                         &test_vector.entries[DATA_HARD_OUTPUT];
1411
1412         for (i = 0; i < n; ++i) {
1413                 ret = check_enc_status_and_ordering(ops[i], i, ref_op->status);
1414                 TEST_ASSERT_SUCCESS(ret,
1415                                 "Checking status and ordering for encoder failed");
1416                 TEST_ASSERT_SUCCESS(validate_op_chain(
1417                                 &ops[i]->ldpc_enc.output,
1418                                 hard_data_orig),
1419                                 "Output buffers (CB=%u) are not equal",
1420                                 i);
1421         }
1422
1423         return TEST_SUCCESS;
1424 }
1425
1426 static void
1427 create_reference_dec_op(struct rte_bbdev_dec_op *op)
1428 {
1429         unsigned int i;
1430         struct op_data_entries *entry;
1431
1432         op->turbo_dec = test_vector.turbo_dec;
1433         entry = &test_vector.entries[DATA_INPUT];
1434         for (i = 0; i < entry->nb_segments; ++i)
1435                 op->turbo_dec.input.length +=
1436                                 entry->segments[i].length;
1437 }
1438
1439 static void
1440 create_reference_ldpc_dec_op(struct rte_bbdev_dec_op *op)
1441 {
1442         unsigned int i;
1443         struct op_data_entries *entry;
1444
1445         op->ldpc_dec = test_vector.ldpc_dec;
1446         entry = &test_vector.entries[DATA_INPUT];
1447         for (i = 0; i < entry->nb_segments; ++i)
1448                 op->ldpc_dec.input.length +=
1449                                 entry->segments[i].length;
1450         if (test_vector.ldpc_dec.op_flags &
1451                         RTE_BBDEV_LDPC_HQ_COMBINE_IN_ENABLE) {
1452                 entry = &test_vector.entries[DATA_HARQ_INPUT];
1453                 for (i = 0; i < entry->nb_segments; ++i)
1454                         op->ldpc_dec.harq_combined_input.length +=
1455                                 entry->segments[i].length;
1456         }
1457 }
1458
1459
1460 static void
1461 create_reference_enc_op(struct rte_bbdev_enc_op *op)
1462 {
1463         unsigned int i;
1464         struct op_data_entries *entry;
1465
1466         op->turbo_enc = test_vector.turbo_enc;
1467         entry = &test_vector.entries[DATA_INPUT];
1468         for (i = 0; i < entry->nb_segments; ++i)
1469                 op->turbo_enc.input.length +=
1470                                 entry->segments[i].length;
1471 }
1472
1473 static void
1474 create_reference_ldpc_enc_op(struct rte_bbdev_enc_op *op)
1475 {
1476         unsigned int i;
1477         struct op_data_entries *entry;
1478
1479         op->ldpc_enc = test_vector.ldpc_enc;
1480         entry = &test_vector.entries[DATA_INPUT];
1481         for (i = 0; i < entry->nb_segments; ++i)
1482                 op->ldpc_enc.input.length +=
1483                                 entry->segments[i].length;
1484 }
1485
1486 static uint32_t
1487 calc_dec_TB_size(struct rte_bbdev_dec_op *op)
1488 {
1489         uint8_t i;
1490         uint32_t c, r, tb_size = 0;
1491
1492         if (op->turbo_dec.code_block_mode) {
1493                 tb_size = op->turbo_dec.tb_params.k_neg;
1494         } else {
1495                 c = op->turbo_dec.tb_params.c;
1496                 r = op->turbo_dec.tb_params.r;
1497                 for (i = 0; i < c-r; i++)
1498                         tb_size += (r < op->turbo_dec.tb_params.c_neg) ?
1499                                 op->turbo_dec.tb_params.k_neg :
1500                                 op->turbo_dec.tb_params.k_pos;
1501         }
1502         return tb_size;
1503 }
1504
1505 static uint32_t
1506 calc_ldpc_dec_TB_size(struct rte_bbdev_dec_op *op)
1507 {
1508         uint8_t i;
1509         uint32_t c, r, tb_size = 0;
1510         uint16_t sys_cols = (op->ldpc_dec.basegraph == 1) ? 22 : 10;
1511
1512         if (op->ldpc_dec.code_block_mode) {
1513                 tb_size = sys_cols * op->ldpc_dec.z_c - op->ldpc_dec.n_filler;
1514         } else {
1515                 c = op->ldpc_dec.tb_params.c;
1516                 r = op->ldpc_dec.tb_params.r;
1517                 for (i = 0; i < c-r; i++)
1518                         tb_size += sys_cols * op->ldpc_dec.z_c
1519                                         - op->ldpc_dec.n_filler;
1520         }
1521         return tb_size;
1522 }
1523
1524 static uint32_t
1525 calc_enc_TB_size(struct rte_bbdev_enc_op *op)
1526 {
1527         uint8_t i;
1528         uint32_t c, r, tb_size = 0;
1529
1530         if (op->turbo_enc.code_block_mode) {
1531                 tb_size = op->turbo_enc.tb_params.k_neg;
1532         } else {
1533                 c = op->turbo_enc.tb_params.c;
1534                 r = op->turbo_enc.tb_params.r;
1535                 for (i = 0; i < c-r; i++)
1536                         tb_size += (r < op->turbo_enc.tb_params.c_neg) ?
1537                                 op->turbo_enc.tb_params.k_neg :
1538                                 op->turbo_enc.tb_params.k_pos;
1539         }
1540         return tb_size;
1541 }
1542
1543 static uint32_t
1544 calc_ldpc_enc_TB_size(struct rte_bbdev_enc_op *op)
1545 {
1546         uint8_t i;
1547         uint32_t c, r, tb_size = 0;
1548         uint16_t sys_cols = (op->ldpc_enc.basegraph == 1) ? 22 : 10;
1549
1550         if (op->turbo_enc.code_block_mode) {
1551                 tb_size = sys_cols * op->ldpc_enc.z_c - op->ldpc_enc.n_filler;
1552         } else {
1553                 c = op->turbo_enc.tb_params.c;
1554                 r = op->turbo_enc.tb_params.r;
1555                 for (i = 0; i < c-r; i++)
1556                         tb_size += sys_cols * op->ldpc_enc.z_c
1557                                         - op->ldpc_enc.n_filler;
1558         }
1559         return tb_size;
1560 }
1561
1562
1563 static int
1564 init_test_op_params(struct test_op_params *op_params,
1565                 enum rte_bbdev_op_type op_type, const int expected_status,
1566                 const int vector_mask, struct rte_mempool *ops_mp,
1567                 uint16_t burst_sz, uint16_t num_to_process, uint16_t num_lcores)
1568 {
1569         int ret = 0;
1570         if (op_type == RTE_BBDEV_OP_TURBO_DEC ||
1571                         op_type == RTE_BBDEV_OP_LDPC_DEC)
1572                 ret = rte_bbdev_dec_op_alloc_bulk(ops_mp,
1573                                 &op_params->ref_dec_op, 1);
1574         else
1575                 ret = rte_bbdev_enc_op_alloc_bulk(ops_mp,
1576                                 &op_params->ref_enc_op, 1);
1577
1578         TEST_ASSERT_SUCCESS(ret, "rte_bbdev_op_alloc_bulk() failed");
1579
1580         op_params->mp = ops_mp;
1581         op_params->burst_sz = burst_sz;
1582         op_params->num_to_process = num_to_process;
1583         op_params->num_lcores = num_lcores;
1584         op_params->vector_mask = vector_mask;
1585         if (op_type == RTE_BBDEV_OP_TURBO_DEC ||
1586                         op_type == RTE_BBDEV_OP_LDPC_DEC)
1587                 op_params->ref_dec_op->status = expected_status;
1588         else if (op_type == RTE_BBDEV_OP_TURBO_ENC
1589                         || op_type == RTE_BBDEV_OP_LDPC_ENC)
1590                 op_params->ref_enc_op->status = expected_status;
1591         return 0;
1592 }
1593
1594 static int
1595 run_test_case_on_device(test_case_function *test_case_func, uint8_t dev_id,
1596                 struct test_op_params *op_params)
1597 {
1598         int t_ret, f_ret, socket_id = SOCKET_ID_ANY;
1599         unsigned int i;
1600         struct active_device *ad;
1601         unsigned int burst_sz = get_burst_sz();
1602         enum rte_bbdev_op_type op_type = test_vector.op_type;
1603         const struct rte_bbdev_op_cap *capabilities = NULL;
1604
1605         ad = &active_devs[dev_id];
1606
1607         /* Check if device supports op_type */
1608         if (!is_avail_op(ad, test_vector.op_type))
1609                 return TEST_SUCCESS;
1610
1611         struct rte_bbdev_info info;
1612         rte_bbdev_info_get(ad->dev_id, &info);
1613         socket_id = GET_SOCKET(info.socket_id);
1614
1615         f_ret = create_mempools(ad, socket_id, op_type,
1616                         get_num_ops());
1617         if (f_ret != TEST_SUCCESS) {
1618                 printf("Couldn't create mempools");
1619                 goto fail;
1620         }
1621         if (op_type == RTE_BBDEV_OP_NONE)
1622                 op_type = RTE_BBDEV_OP_TURBO_ENC;
1623
1624         f_ret = init_test_op_params(op_params, test_vector.op_type,
1625                         test_vector.expected_status,
1626                         test_vector.mask,
1627                         ad->ops_mempool,
1628                         burst_sz,
1629                         get_num_ops(),
1630                         get_num_lcores());
1631         if (f_ret != TEST_SUCCESS) {
1632                 printf("Couldn't init test op params");
1633                 goto fail;
1634         }
1635
1636
1637         /* Find capabilities */
1638         const struct rte_bbdev_op_cap *cap = info.drv.capabilities;
1639         for (i = 0; i < RTE_BBDEV_OP_TYPE_COUNT; i++) {
1640                 if (cap->type == test_vector.op_type) {
1641                         capabilities = cap;
1642                         break;
1643                 }
1644                 cap++;
1645         }
1646         TEST_ASSERT_NOT_NULL(capabilities,
1647                         "Couldn't find capabilities");
1648
1649         if (test_vector.op_type == RTE_BBDEV_OP_TURBO_DEC) {
1650                 create_reference_dec_op(op_params->ref_dec_op);
1651         } else if (test_vector.op_type == RTE_BBDEV_OP_TURBO_ENC)
1652                 create_reference_enc_op(op_params->ref_enc_op);
1653         else if (test_vector.op_type == RTE_BBDEV_OP_LDPC_ENC)
1654                 create_reference_ldpc_enc_op(op_params->ref_enc_op);
1655         else if (test_vector.op_type == RTE_BBDEV_OP_LDPC_DEC)
1656                 create_reference_ldpc_dec_op(op_params->ref_dec_op);
1657
1658         for (i = 0; i < ad->nb_queues; ++i) {
1659                 f_ret = fill_queue_buffers(op_params,
1660                                 ad->in_mbuf_pool,
1661                                 ad->hard_out_mbuf_pool,
1662                                 ad->soft_out_mbuf_pool,
1663                                 ad->harq_in_mbuf_pool,
1664                                 ad->harq_out_mbuf_pool,
1665                                 ad->queue_ids[i],
1666                                 capabilities,
1667                                 info.drv.min_alignment,
1668                                 socket_id);
1669                 if (f_ret != TEST_SUCCESS) {
1670                         printf("Couldn't init queue buffers");
1671                         goto fail;
1672                 }
1673         }
1674
1675         /* Run test case function */
1676         t_ret = test_case_func(ad, op_params);
1677
1678         /* Free active device resources and return */
1679         free_buffers(ad, op_params);
1680         return t_ret;
1681
1682 fail:
1683         free_buffers(ad, op_params);
1684         return TEST_FAILED;
1685 }
1686
1687 /* Run given test function per active device per supported op type
1688  * per burst size.
1689  */
1690 static int
1691 run_test_case(test_case_function *test_case_func)
1692 {
1693         int ret = 0;
1694         uint8_t dev;
1695
1696         /* Alloc op_params */
1697         struct test_op_params *op_params = rte_zmalloc(NULL,
1698                         sizeof(struct test_op_params), RTE_CACHE_LINE_SIZE);
1699         TEST_ASSERT_NOT_NULL(op_params, "Failed to alloc %zuB for op_params",
1700                         RTE_ALIGN(sizeof(struct test_op_params),
1701                                 RTE_CACHE_LINE_SIZE));
1702
1703         /* For each device run test case function */
1704         for (dev = 0; dev < nb_active_devs; ++dev)
1705                 ret |= run_test_case_on_device(test_case_func, dev, op_params);
1706
1707         rte_free(op_params);
1708
1709         return ret;
1710 }
1711
1712 static void
1713 dequeue_event_callback(uint16_t dev_id,
1714                 enum rte_bbdev_event_type event, void *cb_arg,
1715                 void *ret_param)
1716 {
1717         int ret;
1718         uint16_t i;
1719         uint64_t total_time;
1720         uint16_t deq, burst_sz, num_ops;
1721         uint16_t queue_id = *(uint16_t *) ret_param;
1722         struct rte_bbdev_info info;
1723         double tb_len_bits;
1724         struct thread_params *tp = cb_arg;
1725
1726         /* Find matching thread params using queue_id */
1727         for (i = 0; i < MAX_QUEUES; ++i, ++tp)
1728                 if (tp->queue_id == queue_id)
1729                         break;
1730
1731         if (i == MAX_QUEUES) {
1732                 printf("%s: Queue_id from interrupt details was not found!\n",
1733                                 __func__);
1734                 return;
1735         }
1736
1737         if (unlikely(event != RTE_BBDEV_EVENT_DEQUEUE)) {
1738                 rte_atomic16_set(&tp->processing_status, TEST_FAILED);
1739                 printf(
1740                         "Dequeue interrupt handler called for incorrect event!\n");
1741                 return;
1742         }
1743
1744         burst_sz = rte_atomic16_read(&tp->burst_sz);
1745         num_ops = tp->op_params->num_to_process;
1746
1747         if (test_vector.op_type == RTE_BBDEV_OP_TURBO_DEC ||
1748                         test_vector.op_type == RTE_BBDEV_OP_LDPC_DEC)
1749                 deq = rte_bbdev_dequeue_dec_ops(dev_id, queue_id,
1750                                 &tp->dec_ops[
1751                                         rte_atomic16_read(&tp->nb_dequeued)],
1752                                 burst_sz);
1753         else
1754                 deq = rte_bbdev_dequeue_enc_ops(dev_id, queue_id,
1755                                 &tp->enc_ops[
1756                                         rte_atomic16_read(&tp->nb_dequeued)],
1757                                 burst_sz);
1758
1759         if (deq < burst_sz) {
1760                 printf(
1761                         "After receiving the interrupt all operations should be dequeued. Expected: %u, got: %u\n",
1762                         burst_sz, deq);
1763                 rte_atomic16_set(&tp->processing_status, TEST_FAILED);
1764                 return;
1765         }
1766
1767         if (rte_atomic16_read(&tp->nb_dequeued) + deq < num_ops) {
1768                 rte_atomic16_add(&tp->nb_dequeued, deq);
1769                 return;
1770         }
1771
1772         total_time = rte_rdtsc_precise() - tp->start_time;
1773
1774         rte_bbdev_info_get(dev_id, &info);
1775
1776         ret = TEST_SUCCESS;
1777
1778         if (test_vector.op_type == RTE_BBDEV_OP_TURBO_DEC) {
1779                 struct rte_bbdev_dec_op *ref_op = tp->op_params->ref_dec_op;
1780                 ret = validate_dec_op(tp->dec_ops, num_ops, ref_op,
1781                                 tp->op_params->vector_mask);
1782                 /* get the max of iter_count for all dequeued ops */
1783                 for (i = 0; i < num_ops; ++i)
1784                         tp->iter_count = RTE_MAX(
1785                                         tp->dec_ops[i]->turbo_dec.iter_count,
1786                                         tp->iter_count);
1787                 rte_bbdev_dec_op_free_bulk(tp->dec_ops, deq);
1788         } else if (test_vector.op_type == RTE_BBDEV_OP_TURBO_ENC) {
1789                 struct rte_bbdev_enc_op *ref_op = tp->op_params->ref_enc_op;
1790                 ret = validate_enc_op(tp->enc_ops, num_ops, ref_op);
1791                 rte_bbdev_enc_op_free_bulk(tp->enc_ops, deq);
1792         } else if (test_vector.op_type == RTE_BBDEV_OP_LDPC_ENC) {
1793                 struct rte_bbdev_enc_op *ref_op = tp->op_params->ref_enc_op;
1794                 ret = validate_ldpc_enc_op(tp->enc_ops, num_ops, ref_op);
1795                 rte_bbdev_enc_op_free_bulk(tp->enc_ops, deq);
1796         } else if (test_vector.op_type == RTE_BBDEV_OP_LDPC_DEC) {
1797                 struct rte_bbdev_dec_op *ref_op = tp->op_params->ref_dec_op;
1798                 ret = validate_ldpc_dec_op(tp->dec_ops, num_ops, ref_op,
1799                                 tp->op_params->vector_mask);
1800                 rte_bbdev_dec_op_free_bulk(tp->dec_ops, deq);
1801         }
1802
1803         if (ret) {
1804                 printf("Buffers validation failed\n");
1805                 rte_atomic16_set(&tp->processing_status, TEST_FAILED);
1806         }
1807
1808         switch (test_vector.op_type) {
1809         case RTE_BBDEV_OP_TURBO_DEC:
1810                 tb_len_bits = calc_dec_TB_size(tp->op_params->ref_dec_op);
1811                 break;
1812         case RTE_BBDEV_OP_TURBO_ENC:
1813                 tb_len_bits = calc_enc_TB_size(tp->op_params->ref_enc_op);
1814                 break;
1815         case RTE_BBDEV_OP_LDPC_DEC:
1816                 tb_len_bits = calc_ldpc_dec_TB_size(tp->op_params->ref_dec_op);
1817                 break;
1818         case RTE_BBDEV_OP_LDPC_ENC:
1819                 tb_len_bits = calc_ldpc_enc_TB_size(tp->op_params->ref_enc_op);
1820                 break;
1821         case RTE_BBDEV_OP_NONE:
1822                 tb_len_bits = 0.0;
1823                 break;
1824         default:
1825                 printf("Unknown op type: %d\n", test_vector.op_type);
1826                 rte_atomic16_set(&tp->processing_status, TEST_FAILED);
1827                 return;
1828         }
1829
1830         tp->ops_per_sec += ((double)num_ops) /
1831                         ((double)total_time / (double)rte_get_tsc_hz());
1832         tp->mbps += (((double)(num_ops * tb_len_bits)) / 1000000.0) /
1833                         ((double)total_time / (double)rte_get_tsc_hz());
1834
1835         rte_atomic16_add(&tp->nb_dequeued, deq);
1836 }
1837
1838 static int
1839 throughput_intr_lcore_dec(void *arg)
1840 {
1841         struct thread_params *tp = arg;
1842         unsigned int enqueued;
1843         const uint16_t queue_id = tp->queue_id;
1844         const uint16_t burst_sz = tp->op_params->burst_sz;
1845         const uint16_t num_to_process = tp->op_params->num_to_process;
1846         struct rte_bbdev_dec_op *ops[num_to_process];
1847         struct test_buffers *bufs = NULL;
1848         struct rte_bbdev_info info;
1849         int ret, i, j;
1850         uint16_t num_to_enq, enq;
1851
1852         TEST_ASSERT_SUCCESS((burst_sz > MAX_BURST),
1853                         "BURST_SIZE should be <= %u", MAX_BURST);
1854
1855         TEST_ASSERT_SUCCESS(rte_bbdev_queue_intr_enable(tp->dev_id, queue_id),
1856                         "Failed to enable interrupts for dev: %u, queue_id: %u",
1857                         tp->dev_id, queue_id);
1858
1859         rte_bbdev_info_get(tp->dev_id, &info);
1860
1861         TEST_ASSERT_SUCCESS((num_to_process > info.drv.queue_size_lim),
1862                         "NUM_OPS cannot exceed %u for this device",
1863                         info.drv.queue_size_lim);
1864
1865         bufs = &tp->op_params->q_bufs[GET_SOCKET(info.socket_id)][queue_id];
1866
1867         rte_atomic16_clear(&tp->processing_status);
1868         rte_atomic16_clear(&tp->nb_dequeued);
1869
1870         while (rte_atomic16_read(&tp->op_params->sync) == SYNC_WAIT)
1871                 rte_pause();
1872
1873         ret = rte_bbdev_dec_op_alloc_bulk(tp->op_params->mp, ops,
1874                                 num_to_process);
1875         TEST_ASSERT_SUCCESS(ret, "Allocation failed for %d ops",
1876                         num_to_process);
1877         if (test_vector.op_type != RTE_BBDEV_OP_NONE)
1878                 copy_reference_dec_op(ops, num_to_process, 0, bufs->inputs,
1879                                 bufs->hard_outputs, bufs->soft_outputs,
1880                                 tp->op_params->ref_dec_op);
1881
1882         /* Set counter to validate the ordering */
1883         for (j = 0; j < num_to_process; ++j)
1884                 ops[j]->opaque_data = (void *)(uintptr_t)j;
1885
1886         for (j = 0; j < TEST_REPETITIONS; ++j) {
1887                 for (i = 0; i < num_to_process; ++i)
1888                         rte_pktmbuf_reset(ops[i]->turbo_dec.hard_output.data);
1889
1890                 tp->start_time = rte_rdtsc_precise();
1891                 for (enqueued = 0; enqueued < num_to_process;) {
1892                         num_to_enq = burst_sz;
1893
1894                         if (unlikely(num_to_process - enqueued < num_to_enq))
1895                                 num_to_enq = num_to_process - enqueued;
1896
1897                         enq = 0;
1898                         do {
1899                                 enq += rte_bbdev_enqueue_dec_ops(tp->dev_id,
1900                                                 queue_id, &ops[enqueued],
1901                                                 num_to_enq);
1902                         } while (unlikely(num_to_enq != enq));
1903                         enqueued += enq;
1904
1905                         /* Write to thread burst_sz current number of enqueued
1906                          * descriptors. It ensures that proper number of
1907                          * descriptors will be dequeued in callback
1908                          * function - needed for last batch in case where
1909                          * the number of operations is not a multiple of
1910                          * burst size.
1911                          */
1912                         rte_atomic16_set(&tp->burst_sz, num_to_enq);
1913
1914                         /* Wait until processing of previous batch is
1915                          * completed
1916                          */
1917                         while (rte_atomic16_read(&tp->nb_dequeued) !=
1918                                         (int16_t) enqueued)
1919                                 rte_pause();
1920                 }
1921                 if (j != TEST_REPETITIONS - 1)
1922                         rte_atomic16_clear(&tp->nb_dequeued);
1923         }
1924
1925         return TEST_SUCCESS;
1926 }
1927
1928 static int
1929 throughput_intr_lcore_enc(void *arg)
1930 {
1931         struct thread_params *tp = arg;
1932         unsigned int enqueued;
1933         const uint16_t queue_id = tp->queue_id;
1934         const uint16_t burst_sz = tp->op_params->burst_sz;
1935         const uint16_t num_to_process = tp->op_params->num_to_process;
1936         struct rte_bbdev_enc_op *ops[num_to_process];
1937         struct test_buffers *bufs = NULL;
1938         struct rte_bbdev_info info;
1939         int ret, i, j;
1940         uint16_t num_to_enq, enq;
1941
1942         TEST_ASSERT_SUCCESS((burst_sz > MAX_BURST),
1943                         "BURST_SIZE should be <= %u", MAX_BURST);
1944
1945         TEST_ASSERT_SUCCESS(rte_bbdev_queue_intr_enable(tp->dev_id, queue_id),
1946                         "Failed to enable interrupts for dev: %u, queue_id: %u",
1947                         tp->dev_id, queue_id);
1948
1949         rte_bbdev_info_get(tp->dev_id, &info);
1950
1951         TEST_ASSERT_SUCCESS((num_to_process > info.drv.queue_size_lim),
1952                         "NUM_OPS cannot exceed %u for this device",
1953                         info.drv.queue_size_lim);
1954
1955         bufs = &tp->op_params->q_bufs[GET_SOCKET(info.socket_id)][queue_id];
1956
1957         rte_atomic16_clear(&tp->processing_status);
1958         rte_atomic16_clear(&tp->nb_dequeued);
1959
1960         while (rte_atomic16_read(&tp->op_params->sync) == SYNC_WAIT)
1961                 rte_pause();
1962
1963         ret = rte_bbdev_enc_op_alloc_bulk(tp->op_params->mp, ops,
1964                         num_to_process);
1965         TEST_ASSERT_SUCCESS(ret, "Allocation failed for %d ops",
1966                         num_to_process);
1967         if (test_vector.op_type != RTE_BBDEV_OP_NONE)
1968                 copy_reference_enc_op(ops, num_to_process, 0, bufs->inputs,
1969                                 bufs->hard_outputs, tp->op_params->ref_enc_op);
1970
1971         /* Set counter to validate the ordering */
1972         for (j = 0; j < num_to_process; ++j)
1973                 ops[j]->opaque_data = (void *)(uintptr_t)j;
1974
1975         for (j = 0; j < TEST_REPETITIONS; ++j) {
1976                 for (i = 0; i < num_to_process; ++i)
1977                         rte_pktmbuf_reset(ops[i]->turbo_enc.output.data);
1978
1979                 tp->start_time = rte_rdtsc_precise();
1980                 for (enqueued = 0; enqueued < num_to_process;) {
1981                         num_to_enq = burst_sz;
1982
1983                         if (unlikely(num_to_process - enqueued < num_to_enq))
1984                                 num_to_enq = num_to_process - enqueued;
1985
1986                         enq = 0;
1987                         do {
1988                                 enq += rte_bbdev_enqueue_enc_ops(tp->dev_id,
1989                                                 queue_id, &ops[enqueued],
1990                                                 num_to_enq);
1991                         } while (unlikely(enq != num_to_enq));
1992                         enqueued += enq;
1993
1994                         /* Write to thread burst_sz current number of enqueued
1995                          * descriptors. It ensures that proper number of
1996                          * descriptors will be dequeued in callback
1997                          * function - needed for last batch in case where
1998                          * the number of operations is not a multiple of
1999                          * burst size.
2000                          */
2001                         rte_atomic16_set(&tp->burst_sz, num_to_enq);
2002
2003                         /* Wait until processing of previous batch is
2004                          * completed
2005                          */
2006                         while (rte_atomic16_read(&tp->nb_dequeued) !=
2007                                         (int16_t) enqueued)
2008                                 rte_pause();
2009                 }
2010                 if (j != TEST_REPETITIONS - 1)
2011                         rte_atomic16_clear(&tp->nb_dequeued);
2012         }
2013
2014         return TEST_SUCCESS;
2015 }
2016
2017 static int
2018 throughput_pmd_lcore_dec(void *arg)
2019 {
2020         struct thread_params *tp = arg;
2021         uint16_t enq, deq;
2022         uint64_t total_time = 0, start_time;
2023         const uint16_t queue_id = tp->queue_id;
2024         const uint16_t burst_sz = tp->op_params->burst_sz;
2025         const uint16_t num_ops = tp->op_params->num_to_process;
2026         struct rte_bbdev_dec_op *ops_enq[num_ops];
2027         struct rte_bbdev_dec_op *ops_deq[num_ops];
2028         struct rte_bbdev_dec_op *ref_op = tp->op_params->ref_dec_op;
2029         struct test_buffers *bufs = NULL;
2030         int i, j, ret;
2031         struct rte_bbdev_info info;
2032         uint16_t num_to_enq;
2033
2034         TEST_ASSERT_SUCCESS((burst_sz > MAX_BURST),
2035                         "BURST_SIZE should be <= %u", MAX_BURST);
2036
2037         rte_bbdev_info_get(tp->dev_id, &info);
2038
2039         TEST_ASSERT_SUCCESS((num_ops > info.drv.queue_size_lim),
2040                         "NUM_OPS cannot exceed %u for this device",
2041                         info.drv.queue_size_lim);
2042
2043         bufs = &tp->op_params->q_bufs[GET_SOCKET(info.socket_id)][queue_id];
2044
2045         while (rte_atomic16_read(&tp->op_params->sync) == SYNC_WAIT)
2046                 rte_pause();
2047
2048         ret = rte_bbdev_dec_op_alloc_bulk(tp->op_params->mp, ops_enq, num_ops);
2049         TEST_ASSERT_SUCCESS(ret, "Allocation failed for %d ops", num_ops);
2050
2051         if (test_vector.op_type != RTE_BBDEV_OP_NONE)
2052                 copy_reference_dec_op(ops_enq, num_ops, 0, bufs->inputs,
2053                                 bufs->hard_outputs, bufs->soft_outputs, ref_op);
2054
2055         /* Set counter to validate the ordering */
2056         for (j = 0; j < num_ops; ++j)
2057                 ops_enq[j]->opaque_data = (void *)(uintptr_t)j;
2058
2059         for (i = 0; i < TEST_REPETITIONS; ++i) {
2060
2061                 for (j = 0; j < num_ops; ++j)
2062                         mbuf_reset(ops_enq[j]->turbo_dec.hard_output.data);
2063
2064                 start_time = rte_rdtsc_precise();
2065
2066                 for (enq = 0, deq = 0; enq < num_ops;) {
2067                         num_to_enq = burst_sz;
2068
2069                         if (unlikely(num_ops - enq < num_to_enq))
2070                                 num_to_enq = num_ops - enq;
2071
2072                         enq += rte_bbdev_enqueue_dec_ops(tp->dev_id,
2073                                         queue_id, &ops_enq[enq], num_to_enq);
2074
2075                         deq += rte_bbdev_dequeue_dec_ops(tp->dev_id,
2076                                         queue_id, &ops_deq[deq], enq - deq);
2077                 }
2078
2079                 /* dequeue the remaining */
2080                 while (deq < enq) {
2081                         deq += rte_bbdev_dequeue_dec_ops(tp->dev_id,
2082                                         queue_id, &ops_deq[deq], enq - deq);
2083                 }
2084
2085                 total_time += rte_rdtsc_precise() - start_time;
2086         }
2087
2088         tp->iter_count = 0;
2089         /* get the max of iter_count for all dequeued ops */
2090         for (i = 0; i < num_ops; ++i) {
2091                 tp->iter_count = RTE_MAX(ops_enq[i]->turbo_dec.iter_count,
2092                                 tp->iter_count);
2093         }
2094
2095         if (test_vector.op_type != RTE_BBDEV_OP_NONE) {
2096                 ret = validate_dec_op(ops_deq, num_ops, ref_op,
2097                                 tp->op_params->vector_mask);
2098                 TEST_ASSERT_SUCCESS(ret, "Validation failed!");
2099         }
2100
2101         rte_bbdev_dec_op_free_bulk(ops_enq, num_ops);
2102
2103         double tb_len_bits = calc_dec_TB_size(ref_op);
2104
2105         tp->ops_per_sec = ((double)num_ops * TEST_REPETITIONS) /
2106                         ((double)total_time / (double)rte_get_tsc_hz());
2107         tp->mbps = (((double)(num_ops * TEST_REPETITIONS * tb_len_bits)) /
2108                         1000000.0) / ((double)total_time /
2109                         (double)rte_get_tsc_hz());
2110
2111         return TEST_SUCCESS;
2112 }
2113
2114 static int
2115 throughput_pmd_lcore_ldpc_dec(void *arg)
2116 {
2117         struct thread_params *tp = arg;
2118         uint16_t enq, deq;
2119         uint64_t total_time = 0, start_time;
2120         const uint16_t queue_id = tp->queue_id;
2121         const uint16_t burst_sz = tp->op_params->burst_sz;
2122         const uint16_t num_ops = tp->op_params->num_to_process;
2123         struct rte_bbdev_dec_op *ops_enq[num_ops];
2124         struct rte_bbdev_dec_op *ops_deq[num_ops];
2125         struct rte_bbdev_dec_op *ref_op = tp->op_params->ref_dec_op;
2126         struct test_buffers *bufs = NULL;
2127         int i, j, ret;
2128         struct rte_bbdev_info info;
2129         uint16_t num_to_enq;
2130
2131         TEST_ASSERT_SUCCESS((burst_sz > MAX_BURST),
2132                         "BURST_SIZE should be <= %u", MAX_BURST);
2133
2134         rte_bbdev_info_get(tp->dev_id, &info);
2135
2136         TEST_ASSERT_SUCCESS((num_ops > info.drv.queue_size_lim),
2137                         "NUM_OPS cannot exceed %u for this device",
2138                         info.drv.queue_size_lim);
2139
2140         bufs = &tp->op_params->q_bufs[GET_SOCKET(info.socket_id)][queue_id];
2141
2142         while (rte_atomic16_read(&tp->op_params->sync) == SYNC_WAIT)
2143                 rte_pause();
2144
2145         ret = rte_bbdev_dec_op_alloc_bulk(tp->op_params->mp, ops_enq, num_ops);
2146         TEST_ASSERT_SUCCESS(ret, "Allocation failed for %d ops", num_ops);
2147
2148         /* For throughput tests we need to disable early termination */
2149         if (check_bit(ref_op->ldpc_dec.op_flags,
2150                         RTE_BBDEV_LDPC_ITERATION_STOP_ENABLE))
2151                 ref_op->ldpc_dec.op_flags -=
2152                                 RTE_BBDEV_LDPC_ITERATION_STOP_ENABLE;
2153         ref_op->ldpc_dec.iter_max = 6;
2154         ref_op->ldpc_dec.iter_count = ref_op->ldpc_dec.iter_max;
2155
2156         if (test_vector.op_type != RTE_BBDEV_OP_NONE)
2157                 copy_reference_ldpc_dec_op(ops_enq, num_ops, 0, bufs->inputs,
2158                                 bufs->hard_outputs, bufs->soft_outputs,
2159                                 bufs->harq_inputs, bufs->harq_outputs, ref_op);
2160
2161         /* Set counter to validate the ordering */
2162         for (j = 0; j < num_ops; ++j)
2163                 ops_enq[j]->opaque_data = (void *)(uintptr_t)j;
2164
2165         for (i = 0; i < TEST_REPETITIONS; ++i) {
2166                 for (j = 0; j < num_ops; ++j) {
2167                         mbuf_reset(ops_enq[j]->ldpc_dec.hard_output.data);
2168                         if (check_bit(ref_op->ldpc_dec.op_flags,
2169                                         RTE_BBDEV_LDPC_HQ_COMBINE_OUT_ENABLE))
2170                                 mbuf_reset(
2171                                 ops_enq[j]->ldpc_dec.harq_combined_output.data);
2172                 }
2173
2174                 start_time = rte_rdtsc_precise();
2175
2176                 for (enq = 0, deq = 0; enq < num_ops;) {
2177                         num_to_enq = burst_sz;
2178
2179                         if (unlikely(num_ops - enq < num_to_enq))
2180                                 num_to_enq = num_ops - enq;
2181
2182                         enq += rte_bbdev_enqueue_ldpc_dec_ops(tp->dev_id,
2183                                         queue_id, &ops_enq[enq], num_to_enq);
2184
2185                         deq += rte_bbdev_dequeue_ldpc_dec_ops(tp->dev_id,
2186                                         queue_id, &ops_deq[deq], enq - deq);
2187                 }
2188
2189                 /* dequeue the remaining */
2190                 while (deq < enq) {
2191                         deq += rte_bbdev_dequeue_ldpc_dec_ops(tp->dev_id,
2192                                         queue_id, &ops_deq[deq], enq - deq);
2193                 }
2194
2195                 total_time += rte_rdtsc_precise() - start_time;
2196         }
2197
2198         tp->iter_count = 0;
2199         /* get the max of iter_count for all dequeued ops */
2200         for (i = 0; i < num_ops; ++i) {
2201                 tp->iter_count = RTE_MAX(ops_enq[i]->ldpc_dec.iter_count,
2202                                 tp->iter_count);
2203         }
2204
2205         if (test_vector.op_type != RTE_BBDEV_OP_NONE) {
2206                 ret = validate_ldpc_dec_op(ops_deq, num_ops, ref_op,
2207                                 tp->op_params->vector_mask);
2208                 TEST_ASSERT_SUCCESS(ret, "Validation failed!");
2209         }
2210
2211         rte_bbdev_dec_op_free_bulk(ops_enq, num_ops);
2212
2213         double tb_len_bits = calc_ldpc_dec_TB_size(ref_op);
2214
2215         tp->ops_per_sec = ((double)num_ops * TEST_REPETITIONS) /
2216                         ((double)total_time / (double)rte_get_tsc_hz());
2217         tp->mbps = (((double)(num_ops * TEST_REPETITIONS * tb_len_bits)) /
2218                         1000000.0) / ((double)total_time /
2219                         (double)rte_get_tsc_hz());
2220
2221         return TEST_SUCCESS;
2222 }
2223
2224 static int
2225 throughput_pmd_lcore_enc(void *arg)
2226 {
2227         struct thread_params *tp = arg;
2228         uint16_t enq, deq;
2229         uint64_t total_time = 0, start_time;
2230         const uint16_t queue_id = tp->queue_id;
2231         const uint16_t burst_sz = tp->op_params->burst_sz;
2232         const uint16_t num_ops = tp->op_params->num_to_process;
2233         struct rte_bbdev_enc_op *ops_enq[num_ops];
2234         struct rte_bbdev_enc_op *ops_deq[num_ops];
2235         struct rte_bbdev_enc_op *ref_op = tp->op_params->ref_enc_op;
2236         struct test_buffers *bufs = NULL;
2237         int i, j, ret;
2238         struct rte_bbdev_info info;
2239         uint16_t num_to_enq;
2240
2241         TEST_ASSERT_SUCCESS((burst_sz > MAX_BURST),
2242                         "BURST_SIZE should be <= %u", MAX_BURST);
2243
2244         rte_bbdev_info_get(tp->dev_id, &info);
2245
2246         TEST_ASSERT_SUCCESS((num_ops > info.drv.queue_size_lim),
2247                         "NUM_OPS cannot exceed %u for this device",
2248                         info.drv.queue_size_lim);
2249
2250         bufs = &tp->op_params->q_bufs[GET_SOCKET(info.socket_id)][queue_id];
2251
2252         while (rte_atomic16_read(&tp->op_params->sync) == SYNC_WAIT)
2253                 rte_pause();
2254
2255         ret = rte_bbdev_enc_op_alloc_bulk(tp->op_params->mp, ops_enq,
2256                         num_ops);
2257         TEST_ASSERT_SUCCESS(ret, "Allocation failed for %d ops",
2258                         num_ops);
2259         if (test_vector.op_type != RTE_BBDEV_OP_NONE)
2260                 copy_reference_enc_op(ops_enq, num_ops, 0, bufs->inputs,
2261                                 bufs->hard_outputs, ref_op);
2262
2263         /* Set counter to validate the ordering */
2264         for (j = 0; j < num_ops; ++j)
2265                 ops_enq[j]->opaque_data = (void *)(uintptr_t)j;
2266
2267         for (i = 0; i < TEST_REPETITIONS; ++i) {
2268
2269                 if (test_vector.op_type != RTE_BBDEV_OP_NONE)
2270                         for (j = 0; j < num_ops; ++j)
2271                                 mbuf_reset(ops_enq[j]->turbo_enc.output.data);
2272
2273                 start_time = rte_rdtsc_precise();
2274
2275                 for (enq = 0, deq = 0; enq < num_ops;) {
2276                         num_to_enq = burst_sz;
2277
2278                         if (unlikely(num_ops - enq < num_to_enq))
2279                                 num_to_enq = num_ops - enq;
2280
2281                         enq += rte_bbdev_enqueue_enc_ops(tp->dev_id,
2282                                         queue_id, &ops_enq[enq], num_to_enq);
2283
2284                         deq += rte_bbdev_dequeue_enc_ops(tp->dev_id,
2285                                         queue_id, &ops_deq[deq], enq - deq);
2286                 }
2287
2288                 /* dequeue the remaining */
2289                 while (deq < enq) {
2290                         deq += rte_bbdev_dequeue_enc_ops(tp->dev_id,
2291                                         queue_id, &ops_deq[deq], enq - deq);
2292                 }
2293
2294                 total_time += rte_rdtsc_precise() - start_time;
2295         }
2296
2297         if (test_vector.op_type != RTE_BBDEV_OP_NONE) {
2298                 ret = validate_enc_op(ops_deq, num_ops, ref_op);
2299                 TEST_ASSERT_SUCCESS(ret, "Validation failed!");
2300         }
2301
2302         rte_bbdev_enc_op_free_bulk(ops_enq, num_ops);
2303
2304         double tb_len_bits = calc_enc_TB_size(ref_op);
2305
2306         tp->ops_per_sec = ((double)num_ops * TEST_REPETITIONS) /
2307                         ((double)total_time / (double)rte_get_tsc_hz());
2308         tp->mbps = (((double)(num_ops * TEST_REPETITIONS * tb_len_bits))
2309                         / 1000000.0) / ((double)total_time /
2310                         (double)rte_get_tsc_hz());
2311
2312         return TEST_SUCCESS;
2313 }
2314
2315 static int
2316 throughput_pmd_lcore_ldpc_enc(void *arg)
2317 {
2318         struct thread_params *tp = arg;
2319         uint16_t enq, deq;
2320         uint64_t total_time = 0, start_time;
2321         const uint16_t queue_id = tp->queue_id;
2322         const uint16_t burst_sz = tp->op_params->burst_sz;
2323         const uint16_t num_ops = tp->op_params->num_to_process;
2324         struct rte_bbdev_enc_op *ops_enq[num_ops];
2325         struct rte_bbdev_enc_op *ops_deq[num_ops];
2326         struct rte_bbdev_enc_op *ref_op = tp->op_params->ref_enc_op;
2327         struct test_buffers *bufs = NULL;
2328         int i, j, ret;
2329         struct rte_bbdev_info info;
2330         uint16_t num_to_enq;
2331
2332         TEST_ASSERT_SUCCESS((burst_sz > MAX_BURST),
2333                         "BURST_SIZE should be <= %u", MAX_BURST);
2334
2335         rte_bbdev_info_get(tp->dev_id, &info);
2336
2337         TEST_ASSERT_SUCCESS((num_ops > info.drv.queue_size_lim),
2338                         "NUM_OPS cannot exceed %u for this device",
2339                         info.drv.queue_size_lim);
2340
2341         bufs = &tp->op_params->q_bufs[GET_SOCKET(info.socket_id)][queue_id];
2342
2343         while (rte_atomic16_read(&tp->op_params->sync) == SYNC_WAIT)
2344                 rte_pause();
2345
2346         ret = rte_bbdev_enc_op_alloc_bulk(tp->op_params->mp, ops_enq,
2347                         num_ops);
2348         TEST_ASSERT_SUCCESS(ret, "Allocation failed for %d ops",
2349                         num_ops);
2350         if (test_vector.op_type != RTE_BBDEV_OP_NONE)
2351                 copy_reference_ldpc_enc_op(ops_enq, num_ops, 0, bufs->inputs,
2352                                 bufs->hard_outputs, ref_op);
2353
2354         /* Set counter to validate the ordering */
2355         for (j = 0; j < num_ops; ++j)
2356                 ops_enq[j]->opaque_data = (void *)(uintptr_t)j;
2357
2358         for (i = 0; i < TEST_REPETITIONS; ++i) {
2359
2360                 if (test_vector.op_type != RTE_BBDEV_OP_NONE)
2361                         for (j = 0; j < num_ops; ++j)
2362                                 mbuf_reset(ops_enq[j]->turbo_enc.output.data);
2363
2364                 start_time = rte_rdtsc_precise();
2365
2366                 for (enq = 0, deq = 0; enq < num_ops;) {
2367                         num_to_enq = burst_sz;
2368
2369                         if (unlikely(num_ops - enq < num_to_enq))
2370                                 num_to_enq = num_ops - enq;
2371
2372                         enq += rte_bbdev_enqueue_ldpc_enc_ops(tp->dev_id,
2373                                         queue_id, &ops_enq[enq], num_to_enq);
2374
2375                         deq += rte_bbdev_dequeue_ldpc_enc_ops(tp->dev_id,
2376                                         queue_id, &ops_deq[deq], enq - deq);
2377                 }
2378
2379                 /* dequeue the remaining */
2380                 while (deq < enq) {
2381                         deq += rte_bbdev_dequeue_ldpc_enc_ops(tp->dev_id,
2382                                         queue_id, &ops_deq[deq], enq - deq);
2383                 }
2384
2385                 total_time += rte_rdtsc_precise() - start_time;
2386         }
2387
2388         if (test_vector.op_type != RTE_BBDEV_OP_NONE) {
2389                 ret = validate_ldpc_enc_op(ops_deq, num_ops, ref_op);
2390                 TEST_ASSERT_SUCCESS(ret, "Validation failed!");
2391         }
2392
2393         rte_bbdev_enc_op_free_bulk(ops_enq, num_ops);
2394
2395         double tb_len_bits = calc_ldpc_enc_TB_size(ref_op);
2396
2397         tp->ops_per_sec = ((double)num_ops * TEST_REPETITIONS) /
2398                         ((double)total_time / (double)rte_get_tsc_hz());
2399         tp->mbps = (((double)(num_ops * TEST_REPETITIONS * tb_len_bits))
2400                         / 1000000.0) / ((double)total_time /
2401                         (double)rte_get_tsc_hz());
2402
2403         return TEST_SUCCESS;
2404 }
2405
2406 static void
2407 print_enc_throughput(struct thread_params *t_params, unsigned int used_cores)
2408 {
2409         unsigned int iter = 0;
2410         double total_mops = 0, total_mbps = 0;
2411
2412         for (iter = 0; iter < used_cores; iter++) {
2413                 printf(
2414                         "Throughput for core (%u): %.8lg Ops/s, %.8lg Mbps\n",
2415                         t_params[iter].lcore_id, t_params[iter].ops_per_sec,
2416                         t_params[iter].mbps);
2417                 total_mops += t_params[iter].ops_per_sec;
2418                 total_mbps += t_params[iter].mbps;
2419         }
2420         printf(
2421                 "\nTotal throughput for %u cores: %.8lg MOPS, %.8lg Mbps\n",
2422                 used_cores, total_mops, total_mbps);
2423 }
2424
2425 static void
2426 print_dec_throughput(struct thread_params *t_params, unsigned int used_cores)
2427 {
2428         unsigned int iter = 0;
2429         double total_mops = 0, total_mbps = 0;
2430         uint8_t iter_count = 0;
2431
2432         for (iter = 0; iter < used_cores; iter++) {
2433                 printf(
2434                         "Throughput for core (%u): %.8lg Ops/s, %.8lg Mbps @ max %u iterations\n",
2435                         t_params[iter].lcore_id, t_params[iter].ops_per_sec,
2436                         t_params[iter].mbps, t_params[iter].iter_count);
2437                 total_mops += t_params[iter].ops_per_sec;
2438                 total_mbps += t_params[iter].mbps;
2439                 iter_count = RTE_MAX(iter_count, t_params[iter].iter_count);
2440         }
2441         printf(
2442                 "\nTotal throughput for %u cores: %.8lg MOPS, %.8lg Mbps @ max %u iterations\n",
2443                 used_cores, total_mops, total_mbps, iter_count);
2444 }
2445
2446 /*
2447  * Test function that determines how long an enqueue + dequeue of a burst
2448  * takes on available lcores.
2449  */
2450 static int
2451 throughput_test(struct active_device *ad,
2452                 struct test_op_params *op_params)
2453 {
2454         int ret;
2455         unsigned int lcore_id, used_cores = 0;
2456         struct thread_params *t_params, *tp;
2457         struct rte_bbdev_info info;
2458         lcore_function_t *throughput_function;
2459         uint16_t num_lcores;
2460         const char *op_type_str;
2461
2462         rte_bbdev_info_get(ad->dev_id, &info);
2463
2464         op_type_str = rte_bbdev_op_type_str(test_vector.op_type);
2465         TEST_ASSERT_NOT_NULL(op_type_str, "Invalid op type: %u",
2466                         test_vector.op_type);
2467
2468         printf("+ ------------------------------------------------------- +\n");
2469         printf("== test: throughput\ndev: %s, nb_queues: %u, burst size: %u, num ops: %u, num_lcores: %u, op type: %s, itr mode: %s, GHz: %lg\n",
2470                         info.dev_name, ad->nb_queues, op_params->burst_sz,
2471                         op_params->num_to_process, op_params->num_lcores,
2472                         op_type_str,
2473                         intr_enabled ? "Interrupt mode" : "PMD mode",
2474                         (double)rte_get_tsc_hz() / 1000000000.0);
2475
2476         /* Set number of lcores */
2477         num_lcores = (ad->nb_queues < (op_params->num_lcores))
2478                         ? ad->nb_queues
2479                         : op_params->num_lcores;
2480
2481         /* Allocate memory for thread parameters structure */
2482         t_params = rte_zmalloc(NULL, num_lcores * sizeof(struct thread_params),
2483                         RTE_CACHE_LINE_SIZE);
2484         TEST_ASSERT_NOT_NULL(t_params, "Failed to alloc %zuB for t_params",
2485                         RTE_ALIGN(sizeof(struct thread_params) * num_lcores,
2486                                 RTE_CACHE_LINE_SIZE));
2487
2488         if (intr_enabled) {
2489                 if (test_vector.op_type == RTE_BBDEV_OP_TURBO_DEC)
2490                         throughput_function = throughput_intr_lcore_dec;
2491                 else if (test_vector.op_type == RTE_BBDEV_OP_LDPC_DEC)
2492                         throughput_function = throughput_intr_lcore_dec;
2493                 else if (test_vector.op_type == RTE_BBDEV_OP_TURBO_ENC)
2494                         throughput_function = throughput_intr_lcore_enc;
2495                 else if (test_vector.op_type == RTE_BBDEV_OP_LDPC_ENC)
2496                         throughput_function = throughput_intr_lcore_enc;
2497                 else
2498                         throughput_function = throughput_intr_lcore_enc;
2499
2500                 /* Dequeue interrupt callback registration */
2501                 ret = rte_bbdev_callback_register(ad->dev_id,
2502                                 RTE_BBDEV_EVENT_DEQUEUE, dequeue_event_callback,
2503                                 t_params);
2504                 if (ret < 0) {
2505                         rte_free(t_params);
2506                         return ret;
2507                 }
2508         } else {
2509                 if (test_vector.op_type == RTE_BBDEV_OP_TURBO_DEC)
2510                         throughput_function = throughput_pmd_lcore_dec;
2511                 else if (test_vector.op_type == RTE_BBDEV_OP_LDPC_DEC)
2512                         throughput_function = throughput_pmd_lcore_ldpc_dec;
2513                 else if (test_vector.op_type == RTE_BBDEV_OP_TURBO_ENC)
2514                         throughput_function = throughput_pmd_lcore_enc;
2515                 else if (test_vector.op_type == RTE_BBDEV_OP_LDPC_ENC)
2516                         throughput_function = throughput_pmd_lcore_ldpc_enc;
2517                 else
2518                         throughput_function = throughput_pmd_lcore_enc;
2519         }
2520
2521         rte_atomic16_set(&op_params->sync, SYNC_WAIT);
2522
2523         /* Master core is set at first entry */
2524         t_params[0].dev_id = ad->dev_id;
2525         t_params[0].lcore_id = rte_lcore_id();
2526         t_params[0].op_params = op_params;
2527         t_params[0].queue_id = ad->queue_ids[used_cores++];
2528         t_params[0].iter_count = 0;
2529
2530         RTE_LCORE_FOREACH_SLAVE(lcore_id) {
2531                 if (used_cores >= num_lcores)
2532                         break;
2533
2534                 t_params[used_cores].dev_id = ad->dev_id;
2535                 t_params[used_cores].lcore_id = lcore_id;
2536                 t_params[used_cores].op_params = op_params;
2537                 t_params[used_cores].queue_id = ad->queue_ids[used_cores];
2538                 t_params[used_cores].iter_count = 0;
2539
2540                 rte_eal_remote_launch(throughput_function,
2541                                 &t_params[used_cores++], lcore_id);
2542         }
2543
2544         rte_atomic16_set(&op_params->sync, SYNC_START);
2545         ret = throughput_function(&t_params[0]);
2546
2547         /* Master core is always used */
2548         for (used_cores = 1; used_cores < num_lcores; used_cores++)
2549                 ret |= rte_eal_wait_lcore(t_params[used_cores].lcore_id);
2550
2551         /* Return if test failed */
2552         if (ret) {
2553                 rte_free(t_params);
2554                 return ret;
2555         }
2556
2557         /* Print throughput if interrupts are disabled and test passed */
2558         if (!intr_enabled) {
2559                 if (test_vector.op_type == RTE_BBDEV_OP_TURBO_DEC ||
2560                                 test_vector.op_type == RTE_BBDEV_OP_LDPC_DEC)
2561                         print_dec_throughput(t_params, num_lcores);
2562                 else
2563                         print_enc_throughput(t_params, num_lcores);
2564                 rte_free(t_params);
2565                 return ret;
2566         }
2567
2568         /* In interrupt TC we need to wait for the interrupt callback to deqeue
2569          * all pending operations. Skip waiting for queues which reported an
2570          * error using processing_status variable.
2571          * Wait for master lcore operations.
2572          */
2573         tp = &t_params[0];
2574         while ((rte_atomic16_read(&tp->nb_dequeued) <
2575                         op_params->num_to_process) &&
2576                         (rte_atomic16_read(&tp->processing_status) !=
2577                         TEST_FAILED))
2578                 rte_pause();
2579
2580         tp->ops_per_sec /= TEST_REPETITIONS;
2581         tp->mbps /= TEST_REPETITIONS;
2582         ret |= (int)rte_atomic16_read(&tp->processing_status);
2583
2584         /* Wait for slave lcores operations */
2585         for (used_cores = 1; used_cores < num_lcores; used_cores++) {
2586                 tp = &t_params[used_cores];
2587
2588                 while ((rte_atomic16_read(&tp->nb_dequeued) <
2589                                 op_params->num_to_process) &&
2590                                 (rte_atomic16_read(&tp->processing_status) !=
2591                                 TEST_FAILED))
2592                         rte_pause();
2593
2594                 tp->ops_per_sec /= TEST_REPETITIONS;
2595                 tp->mbps /= TEST_REPETITIONS;
2596                 ret |= (int)rte_atomic16_read(&tp->processing_status);
2597         }
2598
2599         /* Print throughput if test passed */
2600         if (!ret) {
2601                 if (test_vector.op_type == RTE_BBDEV_OP_TURBO_DEC ||
2602                                 test_vector.op_type == RTE_BBDEV_OP_LDPC_DEC)
2603                         print_dec_throughput(t_params, num_lcores);
2604                 else if (test_vector.op_type == RTE_BBDEV_OP_TURBO_ENC ||
2605                                 test_vector.op_type == RTE_BBDEV_OP_LDPC_ENC)
2606                         print_enc_throughput(t_params, num_lcores);
2607         }
2608
2609         rte_free(t_params);
2610         return ret;
2611 }
2612
2613 static int
2614 latency_test_dec(struct rte_mempool *mempool,
2615                 struct test_buffers *bufs, struct rte_bbdev_dec_op *ref_op,
2616                 int vector_mask, uint16_t dev_id, uint16_t queue_id,
2617                 const uint16_t num_to_process, uint16_t burst_sz,
2618                 uint64_t *total_time, uint64_t *min_time, uint64_t *max_time)
2619 {
2620         int ret = TEST_SUCCESS;
2621         uint16_t i, j, dequeued;
2622         struct rte_bbdev_dec_op *ops_enq[MAX_BURST], *ops_deq[MAX_BURST];
2623         uint64_t start_time = 0, last_time = 0;
2624
2625         for (i = 0, dequeued = 0; dequeued < num_to_process; ++i) {
2626                 uint16_t enq = 0, deq = 0;
2627                 bool first_time = true;
2628                 last_time = 0;
2629
2630                 if (unlikely(num_to_process - dequeued < burst_sz))
2631                         burst_sz = num_to_process - dequeued;
2632
2633                 ret = rte_bbdev_dec_op_alloc_bulk(mempool, ops_enq, burst_sz);
2634                 TEST_ASSERT_SUCCESS(ret,
2635                                 "rte_bbdev_dec_op_alloc_bulk() failed");
2636                 if (test_vector.op_type != RTE_BBDEV_OP_NONE)
2637                         copy_reference_dec_op(ops_enq, burst_sz, dequeued,
2638                                         bufs->inputs,
2639                                         bufs->hard_outputs,
2640                                         bufs->soft_outputs,
2641                                         ref_op);
2642
2643                 /* Set counter to validate the ordering */
2644                 for (j = 0; j < burst_sz; ++j)
2645                         ops_enq[j]->opaque_data = (void *)(uintptr_t)j;
2646
2647                 start_time = rte_rdtsc_precise();
2648
2649                 enq = rte_bbdev_enqueue_dec_ops(dev_id, queue_id, &ops_enq[enq],
2650                                 burst_sz);
2651                 TEST_ASSERT(enq == burst_sz,
2652                                 "Error enqueueing burst, expected %u, got %u",
2653                                 burst_sz, enq);
2654
2655                 /* Dequeue */
2656                 do {
2657                         deq += rte_bbdev_dequeue_dec_ops(dev_id, queue_id,
2658                                         &ops_deq[deq], burst_sz - deq);
2659                         if (likely(first_time && (deq > 0))) {
2660                                 last_time = rte_rdtsc_precise() - start_time;
2661                                 first_time = false;
2662                         }
2663                 } while (unlikely(burst_sz != deq));
2664
2665                 *max_time = RTE_MAX(*max_time, last_time);
2666                 *min_time = RTE_MIN(*min_time, last_time);
2667                 *total_time += last_time;
2668
2669                 if (test_vector.op_type != RTE_BBDEV_OP_NONE) {
2670                         ret = validate_dec_op(ops_deq, burst_sz, ref_op,
2671                                         vector_mask);
2672                         TEST_ASSERT_SUCCESS(ret, "Validation failed!");
2673                 }
2674
2675                 rte_bbdev_dec_op_free_bulk(ops_enq, deq);
2676                 dequeued += deq;
2677         }
2678
2679         return i;
2680 }
2681
2682 static int
2683 latency_test_ldpc_dec(struct rte_mempool *mempool,
2684                 struct test_buffers *bufs, struct rte_bbdev_dec_op *ref_op,
2685                 int vector_mask, uint16_t dev_id, uint16_t queue_id,
2686                 const uint16_t num_to_process, uint16_t burst_sz,
2687                 uint64_t *total_time, uint64_t *min_time, uint64_t *max_time)
2688 {
2689         int ret = TEST_SUCCESS;
2690         uint16_t i, j, dequeued;
2691         struct rte_bbdev_dec_op *ops_enq[MAX_BURST], *ops_deq[MAX_BURST];
2692         uint64_t start_time = 0, last_time = 0;
2693
2694         for (i = 0, dequeued = 0; dequeued < num_to_process; ++i) {
2695                 uint16_t enq = 0, deq = 0;
2696                 bool first_time = true;
2697                 last_time = 0;
2698
2699                 if (unlikely(num_to_process - dequeued < burst_sz))
2700                         burst_sz = num_to_process - dequeued;
2701
2702                 ret = rte_bbdev_dec_op_alloc_bulk(mempool, ops_enq, burst_sz);
2703                 TEST_ASSERT_SUCCESS(ret,
2704                                 "rte_bbdev_dec_op_alloc_bulk() failed");
2705                 if (test_vector.op_type != RTE_BBDEV_OP_NONE)
2706                         copy_reference_ldpc_dec_op(ops_enq, burst_sz, dequeued,
2707                                         bufs->inputs,
2708                                         bufs->hard_outputs,
2709                                         bufs->soft_outputs,
2710                                         bufs->harq_inputs,
2711                                         bufs->harq_outputs,
2712                                         ref_op);
2713
2714                 /* Set counter to validate the ordering */
2715                 for (j = 0; j < burst_sz; ++j)
2716                         ops_enq[j]->opaque_data = (void *)(uintptr_t)j;
2717
2718                 start_time = rte_rdtsc_precise();
2719
2720                 enq = rte_bbdev_enqueue_ldpc_dec_ops(dev_id, queue_id,
2721                                 &ops_enq[enq], burst_sz);
2722                 TEST_ASSERT(enq == burst_sz,
2723                                 "Error enqueueing burst, expected %u, got %u",
2724                                 burst_sz, enq);
2725
2726                 /* Dequeue */
2727                 do {
2728                         deq += rte_bbdev_dequeue_ldpc_dec_ops(dev_id, queue_id,
2729                                         &ops_deq[deq], burst_sz - deq);
2730                         if (likely(first_time && (deq > 0))) {
2731                                 last_time = rte_rdtsc_precise() - start_time;
2732                                 first_time = false;
2733                         }
2734                 } while (unlikely(burst_sz != deq));
2735
2736                 *max_time = RTE_MAX(*max_time, last_time);
2737                 *min_time = RTE_MIN(*min_time, last_time);
2738                 *total_time += last_time;
2739
2740                 if (test_vector.op_type != RTE_BBDEV_OP_NONE) {
2741                         ret = validate_ldpc_dec_op(ops_deq, burst_sz, ref_op,
2742                                         vector_mask);
2743                         TEST_ASSERT_SUCCESS(ret, "Validation failed!");
2744                 }
2745
2746                 rte_bbdev_dec_op_free_bulk(ops_enq, deq);
2747                 dequeued += deq;
2748         }
2749
2750         return i;
2751 }
2752
2753 static int
2754 latency_test_enc(struct rte_mempool *mempool,
2755                 struct test_buffers *bufs, struct rte_bbdev_enc_op *ref_op,
2756                 uint16_t dev_id, uint16_t queue_id,
2757                 const uint16_t num_to_process, uint16_t burst_sz,
2758                 uint64_t *total_time, uint64_t *min_time, uint64_t *max_time)
2759 {
2760         int ret = TEST_SUCCESS;
2761         uint16_t i, j, dequeued;
2762         struct rte_bbdev_enc_op *ops_enq[MAX_BURST], *ops_deq[MAX_BURST];
2763         uint64_t start_time = 0, last_time = 0;
2764
2765         for (i = 0, dequeued = 0; dequeued < num_to_process; ++i) {
2766                 uint16_t enq = 0, deq = 0;
2767                 bool first_time = true;
2768                 last_time = 0;
2769
2770                 if (unlikely(num_to_process - dequeued < burst_sz))
2771                         burst_sz = num_to_process - dequeued;
2772
2773                 ret = rte_bbdev_enc_op_alloc_bulk(mempool, ops_enq, burst_sz);
2774                 TEST_ASSERT_SUCCESS(ret,
2775                                 "rte_bbdev_enc_op_alloc_bulk() failed");
2776                 if (test_vector.op_type != RTE_BBDEV_OP_NONE)
2777                         copy_reference_enc_op(ops_enq, burst_sz, dequeued,
2778                                         bufs->inputs,
2779                                         bufs->hard_outputs,
2780                                         ref_op);
2781
2782                 /* Set counter to validate the ordering */
2783                 for (j = 0; j < burst_sz; ++j)
2784                         ops_enq[j]->opaque_data = (void *)(uintptr_t)j;
2785
2786                 start_time = rte_rdtsc_precise();
2787
2788                 enq = rte_bbdev_enqueue_enc_ops(dev_id, queue_id, &ops_enq[enq],
2789                                 burst_sz);
2790                 TEST_ASSERT(enq == burst_sz,
2791                                 "Error enqueueing burst, expected %u, got %u",
2792                                 burst_sz, enq);
2793
2794                 /* Dequeue */
2795                 do {
2796                         deq += rte_bbdev_dequeue_enc_ops(dev_id, queue_id,
2797                                         &ops_deq[deq], burst_sz - deq);
2798                         if (likely(first_time && (deq > 0))) {
2799                                 last_time += rte_rdtsc_precise() - start_time;
2800                                 first_time = false;
2801                         }
2802                 } while (unlikely(burst_sz != deq));
2803
2804                 *max_time = RTE_MAX(*max_time, last_time);
2805                 *min_time = RTE_MIN(*min_time, last_time);
2806                 *total_time += last_time;
2807
2808                 if (test_vector.op_type != RTE_BBDEV_OP_NONE) {
2809                         ret = validate_enc_op(ops_deq, burst_sz, ref_op);
2810                         TEST_ASSERT_SUCCESS(ret, "Validation failed!");
2811                 }
2812
2813                 rte_bbdev_enc_op_free_bulk(ops_enq, deq);
2814                 dequeued += deq;
2815         }
2816
2817         return i;
2818 }
2819
2820 static int
2821 latency_test_ldpc_enc(struct rte_mempool *mempool,
2822                 struct test_buffers *bufs, struct rte_bbdev_enc_op *ref_op,
2823                 uint16_t dev_id, uint16_t queue_id,
2824                 const uint16_t num_to_process, uint16_t burst_sz,
2825                 uint64_t *total_time, uint64_t *min_time, uint64_t *max_time)
2826 {
2827         int ret = TEST_SUCCESS;
2828         uint16_t i, j, dequeued;
2829         struct rte_bbdev_enc_op *ops_enq[MAX_BURST], *ops_deq[MAX_BURST];
2830         uint64_t start_time = 0, last_time = 0;
2831
2832         for (i = 0, dequeued = 0; dequeued < num_to_process; ++i) {
2833                 uint16_t enq = 0, deq = 0;
2834                 bool first_time = true;
2835                 last_time = 0;
2836
2837                 if (unlikely(num_to_process - dequeued < burst_sz))
2838                         burst_sz = num_to_process - dequeued;
2839
2840                 ret = rte_bbdev_enc_op_alloc_bulk(mempool, ops_enq, burst_sz);
2841
2842                 TEST_ASSERT_SUCCESS(ret,
2843                                 "rte_bbdev_enc_op_alloc_bulk() failed");
2844                 if (test_vector.op_type != RTE_BBDEV_OP_NONE)
2845                         copy_reference_ldpc_enc_op(ops_enq, burst_sz, dequeued,
2846                                         bufs->inputs,
2847                                         bufs->hard_outputs,
2848                                         ref_op);
2849
2850                 /* Set counter to validate the ordering */
2851                 for (j = 0; j < burst_sz; ++j)
2852                         ops_enq[j]->opaque_data = (void *)(uintptr_t)j;
2853
2854                 start_time = rte_rdtsc_precise();
2855
2856                 enq = rte_bbdev_enqueue_ldpc_enc_ops(dev_id, queue_id,
2857                                 &ops_enq[enq], burst_sz);
2858                 TEST_ASSERT(enq == burst_sz,
2859                                 "Error enqueueing burst, expected %u, got %u",
2860                                 burst_sz, enq);
2861
2862                 /* Dequeue */
2863                 do {
2864                         deq += rte_bbdev_dequeue_ldpc_enc_ops(dev_id, queue_id,
2865                                         &ops_deq[deq], burst_sz - deq);
2866                         if (likely(first_time && (deq > 0))) {
2867                                 last_time += rte_rdtsc_precise() - start_time;
2868                                 first_time = false;
2869                         }
2870                 } while (unlikely(burst_sz != deq));
2871
2872                 *max_time = RTE_MAX(*max_time, last_time);
2873                 *min_time = RTE_MIN(*min_time, last_time);
2874                 *total_time += last_time;
2875
2876                 if (test_vector.op_type != RTE_BBDEV_OP_NONE) {
2877                         ret = validate_enc_op(ops_deq, burst_sz, ref_op);
2878                         TEST_ASSERT_SUCCESS(ret, "Validation failed!");
2879                 }
2880
2881                 rte_bbdev_enc_op_free_bulk(ops_enq, deq);
2882                 dequeued += deq;
2883         }
2884
2885         return i;
2886 }
2887
2888 static int
2889 latency_test(struct active_device *ad,
2890                 struct test_op_params *op_params)
2891 {
2892         int iter;
2893         uint16_t burst_sz = op_params->burst_sz;
2894         const uint16_t num_to_process = op_params->num_to_process;
2895         const enum rte_bbdev_op_type op_type = test_vector.op_type;
2896         const uint16_t queue_id = ad->queue_ids[0];
2897         struct test_buffers *bufs = NULL;
2898         struct rte_bbdev_info info;
2899         uint64_t total_time, min_time, max_time;
2900         const char *op_type_str;
2901
2902         total_time = max_time = 0;
2903         min_time = UINT64_MAX;
2904
2905         TEST_ASSERT_SUCCESS((burst_sz > MAX_BURST),
2906                         "BURST_SIZE should be <= %u", MAX_BURST);
2907
2908         rte_bbdev_info_get(ad->dev_id, &info);
2909         bufs = &op_params->q_bufs[GET_SOCKET(info.socket_id)][queue_id];
2910
2911         op_type_str = rte_bbdev_op_type_str(op_type);
2912         TEST_ASSERT_NOT_NULL(op_type_str, "Invalid op type: %u", op_type);
2913
2914         printf("+ ------------------------------------------------------- +\n");
2915         printf("== test: validation/latency\ndev: %s, burst size: %u, num ops: %u, op type: %s\n",
2916                         info.dev_name, burst_sz, num_to_process, op_type_str);
2917
2918         if (op_type == RTE_BBDEV_OP_TURBO_DEC)
2919                 iter = latency_test_dec(op_params->mp, bufs,
2920                                 op_params->ref_dec_op, op_params->vector_mask,
2921                                 ad->dev_id, queue_id, num_to_process,
2922                                 burst_sz, &total_time, &min_time, &max_time);
2923         else if (op_type == RTE_BBDEV_OP_TURBO_ENC)
2924                 iter = latency_test_enc(op_params->mp, bufs,
2925                                 op_params->ref_enc_op, ad->dev_id, queue_id,
2926                                 num_to_process, burst_sz, &total_time,
2927                                 &min_time, &max_time);
2928         else if (op_type == RTE_BBDEV_OP_LDPC_ENC)
2929                 iter = latency_test_ldpc_enc(op_params->mp, bufs,
2930                                 op_params->ref_enc_op, ad->dev_id, queue_id,
2931                                 num_to_process, burst_sz, &total_time,
2932                                 &min_time, &max_time);
2933         else if (op_type == RTE_BBDEV_OP_LDPC_DEC)
2934                 iter = latency_test_ldpc_dec(op_params->mp, bufs,
2935                                 op_params->ref_dec_op, op_params->vector_mask,
2936                                 ad->dev_id, queue_id, num_to_process,
2937                                 burst_sz, &total_time, &min_time, &max_time);
2938         else
2939                 iter = latency_test_enc(op_params->mp, bufs,
2940                                         op_params->ref_enc_op,
2941                                         ad->dev_id, queue_id,
2942                                         num_to_process, burst_sz, &total_time,
2943                                         &min_time, &max_time);
2944
2945         if (iter <= 0)
2946                 return TEST_FAILED;
2947
2948         printf("Operation latency:\n"
2949                         "\tavg: %lg cycles, %lg us\n"
2950                         "\tmin: %lg cycles, %lg us\n"
2951                         "\tmax: %lg cycles, %lg us\n",
2952                         (double)total_time / (double)iter,
2953                         (double)(total_time * 1000000) / (double)iter /
2954                         (double)rte_get_tsc_hz(), (double)min_time,
2955                         (double)(min_time * 1000000) / (double)rte_get_tsc_hz(),
2956                         (double)max_time, (double)(max_time * 1000000) /
2957                         (double)rte_get_tsc_hz());
2958
2959         return TEST_SUCCESS;
2960 }
2961
2962 #ifdef RTE_BBDEV_OFFLOAD_COST
2963 static int
2964 get_bbdev_queue_stats(uint16_t dev_id, uint16_t queue_id,
2965                 struct rte_bbdev_stats *stats)
2966 {
2967         struct rte_bbdev *dev = &rte_bbdev_devices[dev_id];
2968         struct rte_bbdev_stats *q_stats;
2969
2970         if (queue_id >= dev->data->num_queues)
2971                 return -1;
2972
2973         q_stats = &dev->data->queues[queue_id].queue_stats;
2974
2975         stats->enqueued_count = q_stats->enqueued_count;
2976         stats->dequeued_count = q_stats->dequeued_count;
2977         stats->enqueue_err_count = q_stats->enqueue_err_count;
2978         stats->dequeue_err_count = q_stats->dequeue_err_count;
2979         stats->acc_offload_cycles = q_stats->acc_offload_cycles;
2980
2981         return 0;
2982 }
2983
2984 static int
2985 offload_latency_test_dec(struct rte_mempool *mempool, struct test_buffers *bufs,
2986                 struct rte_bbdev_dec_op *ref_op, uint16_t dev_id,
2987                 uint16_t queue_id, const uint16_t num_to_process,
2988                 uint16_t burst_sz, struct test_time_stats *time_st)
2989 {
2990         int i, dequeued, ret;
2991         struct rte_bbdev_dec_op *ops_enq[MAX_BURST], *ops_deq[MAX_BURST];
2992         uint64_t enq_start_time, deq_start_time;
2993         uint64_t enq_sw_last_time, deq_last_time;
2994         struct rte_bbdev_stats stats;
2995
2996         for (i = 0, dequeued = 0; dequeued < num_to_process; ++i) {
2997                 uint16_t enq = 0, deq = 0;
2998
2999                 if (unlikely(num_to_process - dequeued < burst_sz))
3000                         burst_sz = num_to_process - dequeued;
3001
3002                 rte_bbdev_dec_op_alloc_bulk(mempool, ops_enq, burst_sz);
3003                 if (test_vector.op_type != RTE_BBDEV_OP_NONE)
3004                         copy_reference_dec_op(ops_enq, burst_sz, dequeued,
3005                                         bufs->inputs,
3006                                         bufs->hard_outputs,
3007                                         bufs->soft_outputs,
3008                                         ref_op);
3009
3010                 /* Start time meas for enqueue function offload latency */
3011                 enq_start_time = rte_rdtsc_precise();
3012                 do {
3013                         enq += rte_bbdev_enqueue_dec_ops(dev_id, queue_id,
3014                                         &ops_enq[enq], burst_sz - enq);
3015                 } while (unlikely(burst_sz != enq));
3016
3017                 ret = get_bbdev_queue_stats(dev_id, queue_id, &stats);
3018                 TEST_ASSERT_SUCCESS(ret,
3019                                 "Failed to get stats for queue (%u) of device (%u)",
3020                                 queue_id, dev_id);
3021
3022                 enq_sw_last_time = rte_rdtsc_precise() - enq_start_time -
3023                                 stats.acc_offload_cycles;
3024                 time_st->enq_sw_max_time = RTE_MAX(time_st->enq_sw_max_time,
3025                                 enq_sw_last_time);
3026                 time_st->enq_sw_min_time = RTE_MIN(time_st->enq_sw_min_time,
3027                                 enq_sw_last_time);
3028                 time_st->enq_sw_total_time += enq_sw_last_time;
3029
3030                 time_st->enq_acc_max_time = RTE_MAX(time_st->enq_acc_max_time,
3031                                 stats.acc_offload_cycles);
3032                 time_st->enq_acc_min_time = RTE_MIN(time_st->enq_acc_min_time,
3033                                 stats.acc_offload_cycles);
3034                 time_st->enq_acc_total_time += stats.acc_offload_cycles;
3035
3036                 /* give time for device to process ops */
3037                 rte_delay_us(200);
3038
3039                 /* Start time meas for dequeue function offload latency */
3040                 deq_start_time = rte_rdtsc_precise();
3041                 /* Dequeue one operation */
3042                 do {
3043                         deq += rte_bbdev_dequeue_dec_ops(dev_id, queue_id,
3044                                         &ops_deq[deq], 1);
3045                 } while (unlikely(deq != 1));
3046
3047                 deq_last_time = rte_rdtsc_precise() - deq_start_time;
3048                 time_st->deq_max_time = RTE_MAX(time_st->deq_max_time,
3049                                 deq_last_time);
3050                 time_st->deq_min_time = RTE_MIN(time_st->deq_min_time,
3051                                 deq_last_time);
3052                 time_st->deq_total_time += deq_last_time;
3053
3054                 /* Dequeue remaining operations if needed*/
3055                 while (burst_sz != deq)
3056                         deq += rte_bbdev_dequeue_dec_ops(dev_id, queue_id,
3057                                         &ops_deq[deq], burst_sz - deq);
3058
3059                 rte_bbdev_dec_op_free_bulk(ops_enq, deq);
3060                 dequeued += deq;
3061         }
3062
3063         return i;
3064 }
3065
3066 static int
3067 offload_latency_test_ldpc_dec(struct rte_mempool *mempool,
3068                 struct test_buffers *bufs,
3069                 struct rte_bbdev_dec_op *ref_op, uint16_t dev_id,
3070                 uint16_t queue_id, const uint16_t num_to_process,
3071                 uint16_t burst_sz, struct test_time_stats *time_st)
3072 {
3073         int i, dequeued, ret;
3074         struct rte_bbdev_dec_op *ops_enq[MAX_BURST], *ops_deq[MAX_BURST];
3075         uint64_t enq_start_time, deq_start_time;
3076         uint64_t enq_sw_last_time, deq_last_time;
3077         struct rte_bbdev_stats stats;
3078
3079         for (i = 0, dequeued = 0; dequeued < num_to_process; ++i) {
3080                 uint16_t enq = 0, deq = 0;
3081
3082                 if (unlikely(num_to_process - dequeued < burst_sz))
3083                         burst_sz = num_to_process - dequeued;
3084
3085                 rte_bbdev_dec_op_alloc_bulk(mempool, ops_enq, burst_sz);
3086                 if (test_vector.op_type != RTE_BBDEV_OP_NONE)
3087                         copy_reference_ldpc_dec_op(ops_enq, burst_sz, dequeued,
3088                                         bufs->inputs,
3089                                         bufs->hard_outputs,
3090                                         bufs->soft_outputs,
3091                                         bufs->harq_inputs,
3092                                         bufs->harq_outputs,
3093                                         ref_op);
3094
3095                 /* Start time meas for enqueue function offload latency */
3096                 enq_start_time = rte_rdtsc_precise();
3097                 do {
3098                         enq += rte_bbdev_enqueue_ldpc_dec_ops(dev_id, queue_id,
3099                                         &ops_enq[enq], burst_sz - enq);
3100                 } while (unlikely(burst_sz != enq));
3101
3102                 ret = get_bbdev_queue_stats(dev_id, queue_id, &stats);
3103                 TEST_ASSERT_SUCCESS(ret,
3104                                 "Failed to get stats for queue (%u) of device (%u)",
3105                                 queue_id, dev_id);
3106
3107                 enq_sw_last_time = rte_rdtsc_precise() - enq_start_time -
3108                                 stats.acc_offload_cycles;
3109                 time_st->enq_sw_max_time = RTE_MAX(time_st->enq_sw_max_time,
3110                                 enq_sw_last_time);
3111                 time_st->enq_sw_min_time = RTE_MIN(time_st->enq_sw_min_time,
3112                                 enq_sw_last_time);
3113                 time_st->enq_sw_total_time += enq_sw_last_time;
3114
3115                 time_st->enq_acc_max_time = RTE_MAX(time_st->enq_acc_max_time,
3116                                 stats.acc_offload_cycles);
3117                 time_st->enq_acc_min_time = RTE_MIN(time_st->enq_acc_min_time,
3118                                 stats.acc_offload_cycles);
3119                 time_st->enq_acc_total_time += stats.acc_offload_cycles;
3120
3121                 /* give time for device to process ops */
3122                 rte_delay_us(200);
3123
3124                 /* Start time meas for dequeue function offload latency */
3125                 deq_start_time = rte_rdtsc_precise();
3126                 /* Dequeue one operation */
3127                 do {
3128                         deq += rte_bbdev_dequeue_ldpc_dec_ops(dev_id, queue_id,
3129                                         &ops_deq[deq], 1);
3130                 } while (unlikely(deq != 1));
3131
3132                 deq_last_time = rte_rdtsc_precise() - deq_start_time;
3133                 time_st->deq_max_time = RTE_MAX(time_st->deq_max_time,
3134                                 deq_last_time);
3135                 time_st->deq_min_time = RTE_MIN(time_st->deq_min_time,
3136                                 deq_last_time);
3137                 time_st->deq_total_time += deq_last_time;
3138
3139                 /* Dequeue remaining operations if needed*/
3140                 while (burst_sz != deq)
3141                         deq += rte_bbdev_dequeue_dec_ops(dev_id, queue_id,
3142                                         &ops_deq[deq], burst_sz - deq);
3143
3144                 rte_bbdev_dec_op_free_bulk(ops_enq, deq);
3145                 dequeued += deq;
3146         }
3147
3148         return i;
3149 }
3150
3151 static int
3152 offload_latency_test_enc(struct rte_mempool *mempool, struct test_buffers *bufs,
3153                 struct rte_bbdev_enc_op *ref_op, uint16_t dev_id,
3154                 uint16_t queue_id, const uint16_t num_to_process,
3155                 uint16_t burst_sz, struct test_time_stats *time_st)
3156 {
3157         int i, dequeued, ret;
3158         struct rte_bbdev_enc_op *ops_enq[MAX_BURST], *ops_deq[MAX_BURST];
3159         uint64_t enq_start_time, deq_start_time;
3160         uint64_t enq_sw_last_time, deq_last_time;
3161         struct rte_bbdev_stats stats;
3162
3163         for (i = 0, dequeued = 0; dequeued < num_to_process; ++i) {
3164                 uint16_t enq = 0, deq = 0;
3165
3166                 if (unlikely(num_to_process - dequeued < burst_sz))
3167                         burst_sz = num_to_process - dequeued;
3168
3169                 ret = rte_bbdev_enc_op_alloc_bulk(mempool, ops_enq, burst_sz);
3170                 TEST_ASSERT_SUCCESS(ret, "rte_bbdev_op_alloc_bulk() failed");
3171                 if (test_vector.op_type != RTE_BBDEV_OP_NONE)
3172                         copy_reference_enc_op(ops_enq, burst_sz, dequeued,
3173                                         bufs->inputs,
3174                                         bufs->hard_outputs,
3175                                         ref_op);
3176
3177                 /* Start time meas for enqueue function offload latency */
3178                 enq_start_time = rte_rdtsc_precise();
3179                 do {
3180                         enq += rte_bbdev_enqueue_enc_ops(dev_id, queue_id,
3181                                         &ops_enq[enq], burst_sz - enq);
3182                 } while (unlikely(burst_sz != enq));
3183
3184                 ret = get_bbdev_queue_stats(dev_id, queue_id, &stats);
3185                 TEST_ASSERT_SUCCESS(ret,
3186                                 "Failed to get stats for queue (%u) of device (%u)",
3187                                 queue_id, dev_id);
3188
3189                 enq_sw_last_time = rte_rdtsc_precise() - enq_start_time -
3190                                 stats.acc_offload_cycles;
3191                 time_st->enq_sw_max_time = RTE_MAX(time_st->enq_sw_max_time,
3192                                 enq_sw_last_time);
3193                 time_st->enq_sw_min_time = RTE_MIN(time_st->enq_sw_min_time,
3194                                 enq_sw_last_time);
3195                 time_st->enq_sw_total_time += enq_sw_last_time;
3196
3197                 time_st->enq_acc_max_time = RTE_MAX(time_st->enq_acc_max_time,
3198                                 stats.acc_offload_cycles);
3199                 time_st->enq_acc_min_time = RTE_MIN(time_st->enq_acc_min_time,
3200                                 stats.acc_offload_cycles);
3201                 time_st->enq_acc_total_time += stats.acc_offload_cycles;
3202
3203                 /* give time for device to process ops */
3204                 rte_delay_us(200);
3205
3206                 /* Start time meas for dequeue function offload latency */
3207                 deq_start_time = rte_rdtsc_precise();
3208                 /* Dequeue one operation */
3209                 do {
3210                         deq += rte_bbdev_dequeue_enc_ops(dev_id, queue_id,
3211                                         &ops_deq[deq], 1);
3212                 } while (unlikely(deq != 1));
3213
3214                 deq_last_time = rte_rdtsc_precise() - deq_start_time;
3215                 time_st->deq_max_time = RTE_MAX(time_st->deq_max_time,
3216                                 deq_last_time);
3217                 time_st->deq_min_time = RTE_MIN(time_st->deq_min_time,
3218                                 deq_last_time);
3219                 time_st->deq_total_time += deq_last_time;
3220
3221                 while (burst_sz != deq)
3222                         deq += rte_bbdev_dequeue_enc_ops(dev_id, queue_id,
3223                                         &ops_deq[deq], burst_sz - deq);
3224
3225                 rte_bbdev_enc_op_free_bulk(ops_enq, deq);
3226                 dequeued += deq;
3227         }
3228
3229         return i;
3230 }
3231
3232 static int
3233 offload_latency_test_ldpc_enc(struct rte_mempool *mempool,
3234                 struct test_buffers *bufs,
3235                 struct rte_bbdev_enc_op *ref_op, uint16_t dev_id,
3236                 uint16_t queue_id, const uint16_t num_to_process,
3237                 uint16_t burst_sz, struct test_time_stats *time_st)
3238 {
3239         int i, dequeued, ret;
3240         struct rte_bbdev_enc_op *ops_enq[MAX_BURST], *ops_deq[MAX_BURST];
3241         uint64_t enq_start_time, deq_start_time;
3242         uint64_t enq_sw_last_time, deq_last_time;
3243         struct rte_bbdev_stats stats;
3244
3245         for (i = 0, dequeued = 0; dequeued < num_to_process; ++i) {
3246                 uint16_t enq = 0, deq = 0;
3247
3248                 if (unlikely(num_to_process - dequeued < burst_sz))
3249                         burst_sz = num_to_process - dequeued;
3250
3251                 ret = rte_bbdev_enc_op_alloc_bulk(mempool, ops_enq, burst_sz);
3252                 TEST_ASSERT_SUCCESS(ret, "rte_bbdev_op_alloc_bulk() failed");
3253                 if (test_vector.op_type != RTE_BBDEV_OP_NONE)
3254                         copy_reference_ldpc_enc_op(ops_enq, burst_sz, dequeued,
3255                                         bufs->inputs,
3256                                         bufs->hard_outputs,
3257                                         ref_op);
3258
3259                 /* Start time meas for enqueue function offload latency */
3260                 enq_start_time = rte_rdtsc_precise();
3261                 do {
3262                         enq += rte_bbdev_enqueue_ldpc_enc_ops(dev_id, queue_id,
3263                                         &ops_enq[enq], burst_sz - enq);
3264                 } while (unlikely(burst_sz != enq));
3265
3266                 ret = get_bbdev_queue_stats(dev_id, queue_id, &stats);
3267                 TEST_ASSERT_SUCCESS(ret,
3268                                 "Failed to get stats for queue (%u) of device (%u)",
3269                                 queue_id, dev_id);
3270
3271                 enq_sw_last_time = rte_rdtsc_precise() - enq_start_time -
3272                                 stats.acc_offload_cycles;
3273                 time_st->enq_sw_max_time = RTE_MAX(time_st->enq_sw_max_time,
3274                                 enq_sw_last_time);
3275                 time_st->enq_sw_min_time = RTE_MIN(time_st->enq_sw_min_time,
3276                                 enq_sw_last_time);
3277                 time_st->enq_sw_total_time += enq_sw_last_time;
3278
3279                 time_st->enq_acc_max_time = RTE_MAX(time_st->enq_acc_max_time,
3280                                 stats.acc_offload_cycles);
3281                 time_st->enq_acc_min_time = RTE_MIN(time_st->enq_acc_min_time,
3282                                 stats.acc_offload_cycles);
3283                 time_st->enq_acc_total_time += stats.acc_offload_cycles;
3284
3285                 /* give time for device to process ops */
3286                 rte_delay_us(200);
3287
3288                 /* Start time meas for dequeue function offload latency */
3289                 deq_start_time = rte_rdtsc_precise();
3290                 /* Dequeue one operation */
3291                 do {
3292                         deq += rte_bbdev_dequeue_ldpc_enc_ops(dev_id, queue_id,
3293                                         &ops_deq[deq], 1);
3294                 } while (unlikely(deq != 1));
3295
3296                 deq_last_time = rte_rdtsc_precise() - deq_start_time;
3297                 time_st->deq_max_time = RTE_MAX(time_st->deq_max_time,
3298                                 deq_last_time);
3299                 time_st->deq_min_time = RTE_MIN(time_st->deq_min_time,
3300                                 deq_last_time);
3301                 time_st->deq_total_time += deq_last_time;
3302
3303                 while (burst_sz != deq)
3304                         deq += rte_bbdev_dequeue_ldpc_enc_ops(dev_id, queue_id,
3305                                         &ops_deq[deq], burst_sz - deq);
3306
3307                 rte_bbdev_enc_op_free_bulk(ops_enq, deq);
3308                 dequeued += deq;
3309         }
3310
3311         return i;
3312 }
3313 #endif
3314
3315 static int
3316 offload_cost_test(struct active_device *ad,
3317                 struct test_op_params *op_params)
3318 {
3319 #ifndef RTE_BBDEV_OFFLOAD_COST
3320         RTE_SET_USED(ad);
3321         RTE_SET_USED(op_params);
3322         printf("Offload latency test is disabled.\n");
3323         printf("Set RTE_BBDEV_OFFLOAD_COST to 'y' to turn the test on.\n");
3324         return TEST_SKIPPED;
3325 #else
3326         int iter;
3327         uint16_t burst_sz = op_params->burst_sz;
3328         const uint16_t num_to_process = op_params->num_to_process;
3329         const enum rte_bbdev_op_type op_type = test_vector.op_type;
3330         const uint16_t queue_id = ad->queue_ids[0];
3331         struct test_buffers *bufs = NULL;
3332         struct rte_bbdev_info info;
3333         const char *op_type_str;
3334         struct test_time_stats time_st;
3335
3336         memset(&time_st, 0, sizeof(struct test_time_stats));
3337         time_st.enq_sw_min_time = UINT64_MAX;
3338         time_st.enq_acc_min_time = UINT64_MAX;
3339         time_st.deq_min_time = UINT64_MAX;
3340
3341         TEST_ASSERT_SUCCESS((burst_sz > MAX_BURST),
3342                         "BURST_SIZE should be <= %u", MAX_BURST);
3343
3344         rte_bbdev_info_get(ad->dev_id, &info);
3345         bufs = &op_params->q_bufs[GET_SOCKET(info.socket_id)][queue_id];
3346
3347         op_type_str = rte_bbdev_op_type_str(op_type);
3348         TEST_ASSERT_NOT_NULL(op_type_str, "Invalid op type: %u", op_type);
3349
3350         printf("+ ------------------------------------------------------- +\n");
3351         printf("== test: offload latency test\ndev: %s, burst size: %u, num ops: %u, op type: %s\n",
3352                         info.dev_name, burst_sz, num_to_process, op_type_str);
3353
3354         if (op_type == RTE_BBDEV_OP_TURBO_DEC)
3355                 iter = offload_latency_test_dec(op_params->mp, bufs,
3356                                 op_params->ref_dec_op, ad->dev_id, queue_id,
3357                                 num_to_process, burst_sz, &time_st);
3358         else if (op_type == RTE_BBDEV_OP_TURBO_ENC)
3359                 iter = offload_latency_test_enc(op_params->mp, bufs,
3360                                 op_params->ref_enc_op, ad->dev_id, queue_id,
3361                                 num_to_process, burst_sz, &time_st);
3362         else if (op_type == RTE_BBDEV_OP_LDPC_ENC)
3363                 iter = offload_latency_test_ldpc_enc(op_params->mp, bufs,
3364                                 op_params->ref_enc_op, ad->dev_id, queue_id,
3365                                 num_to_process, burst_sz, &time_st);
3366         else if (op_type == RTE_BBDEV_OP_LDPC_DEC)
3367                 iter = offload_latency_test_ldpc_dec(op_params->mp, bufs,
3368                         op_params->ref_dec_op, ad->dev_id, queue_id,
3369                         num_to_process, burst_sz, &time_st);
3370         else
3371                 iter = offload_latency_test_enc(op_params->mp, bufs,
3372                                 op_params->ref_enc_op, ad->dev_id, queue_id,
3373                                 num_to_process, burst_sz, &time_st);
3374
3375         if (iter <= 0)
3376                 return TEST_FAILED;
3377
3378         printf("Enqueue driver offload cost latency:\n"
3379                         "\tavg: %lg cycles, %lg us\n"
3380                         "\tmin: %lg cycles, %lg us\n"
3381                         "\tmax: %lg cycles, %lg us\n"
3382                         "Enqueue accelerator offload cost latency:\n"
3383                         "\tavg: %lg cycles, %lg us\n"
3384                         "\tmin: %lg cycles, %lg us\n"
3385                         "\tmax: %lg cycles, %lg us\n",
3386                         (double)time_st.enq_sw_total_time / (double)iter,
3387                         (double)(time_st.enq_sw_total_time * 1000000) /
3388                         (double)iter / (double)rte_get_tsc_hz(),
3389                         (double)time_st.enq_sw_min_time,
3390                         (double)(time_st.enq_sw_min_time * 1000000) /
3391                         rte_get_tsc_hz(), (double)time_st.enq_sw_max_time,
3392                         (double)(time_st.enq_sw_max_time * 1000000) /
3393                         rte_get_tsc_hz(), (double)time_st.enq_acc_total_time /
3394                         (double)iter,
3395                         (double)(time_st.enq_acc_total_time * 1000000) /
3396                         (double)iter / (double)rte_get_tsc_hz(),
3397                         (double)time_st.enq_acc_min_time,
3398                         (double)(time_st.enq_acc_min_time * 1000000) /
3399                         rte_get_tsc_hz(), (double)time_st.enq_acc_max_time,
3400                         (double)(time_st.enq_acc_max_time * 1000000) /
3401                         rte_get_tsc_hz());
3402
3403         printf("Dequeue offload cost latency - one op:\n"
3404                         "\tavg: %lg cycles, %lg us\n"
3405                         "\tmin: %lg cycles, %lg us\n"
3406                         "\tmax: %lg cycles, %lg us\n",
3407                         (double)time_st.deq_total_time / (double)iter,
3408                         (double)(time_st.deq_total_time * 1000000) /
3409                         (double)iter / (double)rte_get_tsc_hz(),
3410                         (double)time_st.deq_min_time,
3411                         (double)(time_st.deq_min_time * 1000000) /
3412                         rte_get_tsc_hz(), (double)time_st.deq_max_time,
3413                         (double)(time_st.deq_max_time * 1000000) /
3414                         rte_get_tsc_hz());
3415
3416         return TEST_SUCCESS;
3417 #endif
3418 }
3419
3420 #ifdef RTE_BBDEV_OFFLOAD_COST
3421 static int
3422 offload_latency_empty_q_test_dec(uint16_t dev_id, uint16_t queue_id,
3423                 const uint16_t num_to_process, uint16_t burst_sz,
3424                 uint64_t *deq_total_time, uint64_t *deq_min_time,
3425                 uint64_t *deq_max_time)
3426 {
3427         int i, deq_total;
3428         struct rte_bbdev_dec_op *ops[MAX_BURST];
3429         uint64_t deq_start_time, deq_last_time;
3430
3431         /* Test deq offload latency from an empty queue */
3432
3433         for (i = 0, deq_total = 0; deq_total < num_to_process;
3434                         ++i, deq_total += burst_sz) {
3435                 deq_start_time = rte_rdtsc_precise();
3436
3437                 if (unlikely(num_to_process - deq_total < burst_sz))
3438                         burst_sz = num_to_process - deq_total;
3439                 rte_bbdev_dequeue_dec_ops(dev_id, queue_id, ops, burst_sz);
3440
3441                 deq_last_time = rte_rdtsc_precise() - deq_start_time;
3442                 *deq_max_time = RTE_MAX(*deq_max_time, deq_last_time);
3443                 *deq_min_time = RTE_MIN(*deq_min_time, deq_last_time);
3444                 *deq_total_time += deq_last_time;
3445         }
3446
3447         return i;
3448 }
3449
3450 static int
3451 offload_latency_empty_q_test_enc(uint16_t dev_id, uint16_t queue_id,
3452                 const uint16_t num_to_process, uint16_t burst_sz,
3453                 uint64_t *deq_total_time, uint64_t *deq_min_time,
3454                 uint64_t *deq_max_time)
3455 {
3456         int i, deq_total;
3457         struct rte_bbdev_enc_op *ops[MAX_BURST];
3458         uint64_t deq_start_time, deq_last_time;
3459
3460         /* Test deq offload latency from an empty queue */
3461         for (i = 0, deq_total = 0; deq_total < num_to_process;
3462                         ++i, deq_total += burst_sz) {
3463                 deq_start_time = rte_rdtsc_precise();
3464
3465                 if (unlikely(num_to_process - deq_total < burst_sz))
3466                         burst_sz = num_to_process - deq_total;
3467                 rte_bbdev_dequeue_enc_ops(dev_id, queue_id, ops, burst_sz);
3468
3469                 deq_last_time = rte_rdtsc_precise() - deq_start_time;
3470                 *deq_max_time = RTE_MAX(*deq_max_time, deq_last_time);
3471                 *deq_min_time = RTE_MIN(*deq_min_time, deq_last_time);
3472                 *deq_total_time += deq_last_time;
3473         }
3474
3475         return i;
3476 }
3477 #endif
3478
3479 static int
3480 offload_latency_empty_q_test(struct active_device *ad,
3481                 struct test_op_params *op_params)
3482 {
3483 #ifndef RTE_BBDEV_OFFLOAD_COST
3484         RTE_SET_USED(ad);
3485         RTE_SET_USED(op_params);
3486         printf("Offload latency empty dequeue test is disabled.\n");
3487         printf("Set RTE_BBDEV_OFFLOAD_COST to 'y' to turn the test on.\n");
3488         return TEST_SKIPPED;
3489 #else
3490         int iter;
3491         uint64_t deq_total_time, deq_min_time, deq_max_time;
3492         uint16_t burst_sz = op_params->burst_sz;
3493         const uint16_t num_to_process = op_params->num_to_process;
3494         const enum rte_bbdev_op_type op_type = test_vector.op_type;
3495         const uint16_t queue_id = ad->queue_ids[0];
3496         struct rte_bbdev_info info;
3497         const char *op_type_str;
3498
3499         deq_total_time = deq_max_time = 0;
3500         deq_min_time = UINT64_MAX;
3501
3502         TEST_ASSERT_SUCCESS((burst_sz > MAX_BURST),
3503                         "BURST_SIZE should be <= %u", MAX_BURST);
3504
3505         rte_bbdev_info_get(ad->dev_id, &info);
3506
3507         op_type_str = rte_bbdev_op_type_str(op_type);
3508         TEST_ASSERT_NOT_NULL(op_type_str, "Invalid op type: %u", op_type);
3509
3510         printf("+ ------------------------------------------------------- +\n");
3511         printf("== test: offload latency empty dequeue\ndev: %s, burst size: %u, num ops: %u, op type: %s\n",
3512                         info.dev_name, burst_sz, num_to_process, op_type_str);
3513
3514         if (op_type == RTE_BBDEV_OP_TURBO_DEC)
3515                 iter = offload_latency_empty_q_test_dec(ad->dev_id, queue_id,
3516                                 num_to_process, burst_sz, &deq_total_time,
3517                                 &deq_min_time, &deq_max_time);
3518         else
3519                 iter = offload_latency_empty_q_test_enc(ad->dev_id, queue_id,
3520                                 num_to_process, burst_sz, &deq_total_time,
3521                                 &deq_min_time, &deq_max_time);
3522
3523         if (iter <= 0)
3524                 return TEST_FAILED;
3525
3526         printf("Empty dequeue offload:\n"
3527                         "\tavg: %lg cycles, %lg us\n"
3528                         "\tmin: %lg cycles, %lg us\n"
3529                         "\tmax: %lg cycles, %lg us\n",
3530                         (double)deq_total_time / (double)iter,
3531                         (double)(deq_total_time * 1000000) / (double)iter /
3532                         (double)rte_get_tsc_hz(), (double)deq_min_time,
3533                         (double)(deq_min_time * 1000000) / rte_get_tsc_hz(),
3534                         (double)deq_max_time, (double)(deq_max_time * 1000000) /
3535                         rte_get_tsc_hz());
3536
3537         return TEST_SUCCESS;
3538 #endif
3539 }
3540
3541 static int
3542 throughput_tc(void)
3543 {
3544         return run_test_case(throughput_test);
3545 }
3546
3547 static int
3548 offload_cost_tc(void)
3549 {
3550         return run_test_case(offload_cost_test);
3551 }
3552
3553 static int
3554 offload_latency_empty_q_tc(void)
3555 {
3556         return run_test_case(offload_latency_empty_q_test);
3557 }
3558
3559 static int
3560 latency_tc(void)
3561 {
3562         return run_test_case(latency_test);
3563 }
3564
3565 static int
3566 interrupt_tc(void)
3567 {
3568         return run_test_case(throughput_test);
3569 }
3570
3571 static struct unit_test_suite bbdev_throughput_testsuite = {
3572         .suite_name = "BBdev Throughput Tests",
3573         .setup = testsuite_setup,
3574         .teardown = testsuite_teardown,
3575         .unit_test_cases = {
3576                 TEST_CASE_ST(ut_setup, ut_teardown, throughput_tc),
3577                 TEST_CASES_END() /**< NULL terminate unit test array */
3578         }
3579 };
3580
3581 static struct unit_test_suite bbdev_validation_testsuite = {
3582         .suite_name = "BBdev Validation Tests",
3583         .setup = testsuite_setup,
3584         .teardown = testsuite_teardown,
3585         .unit_test_cases = {
3586                 TEST_CASE_ST(ut_setup, ut_teardown, latency_tc),
3587                 TEST_CASES_END() /**< NULL terminate unit test array */
3588         }
3589 };
3590
3591 static struct unit_test_suite bbdev_latency_testsuite = {
3592         .suite_name = "BBdev Latency Tests",
3593         .setup = testsuite_setup,
3594         .teardown = testsuite_teardown,
3595         .unit_test_cases = {
3596                 TEST_CASE_ST(ut_setup, ut_teardown, latency_tc),
3597                 TEST_CASES_END() /**< NULL terminate unit test array */
3598         }
3599 };
3600
3601 static struct unit_test_suite bbdev_offload_cost_testsuite = {
3602         .suite_name = "BBdev Offload Cost Tests",
3603         .setup = testsuite_setup,
3604         .teardown = testsuite_teardown,
3605         .unit_test_cases = {
3606                 TEST_CASE_ST(ut_setup, ut_teardown, offload_cost_tc),
3607                 TEST_CASE_ST(ut_setup, ut_teardown, offload_latency_empty_q_tc),
3608                 TEST_CASES_END() /**< NULL terminate unit test array */
3609         }
3610 };
3611
3612 static struct unit_test_suite bbdev_interrupt_testsuite = {
3613         .suite_name = "BBdev Interrupt Tests",
3614         .setup = interrupt_testsuite_setup,
3615         .teardown = testsuite_teardown,
3616         .unit_test_cases = {
3617                 TEST_CASE_ST(ut_setup, ut_teardown, interrupt_tc),
3618                 TEST_CASES_END() /**< NULL terminate unit test array */
3619         }
3620 };
3621
3622 REGISTER_TEST_COMMAND(throughput, bbdev_throughput_testsuite);
3623 REGISTER_TEST_COMMAND(validation, bbdev_validation_testsuite);
3624 REGISTER_TEST_COMMAND(latency, bbdev_latency_testsuite);
3625 REGISTER_TEST_COMMAND(offload, bbdev_offload_cost_testsuite);
3626 REGISTER_TEST_COMMAND(interrupt, bbdev_interrupt_testsuite);