xref: /dpdk/app/test-bbdev/test_bbdev_perf.c (revision 4b53e9802b6b6040ad5622b1414aaa93d9581d0c)
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2017 Intel Corporation
3  */
4 
5 #include <stdio.h>
6 #include <stdlib.h>
7 #include <inttypes.h>
8 #include <math.h>
9 
10 #include <rte_eal.h>
11 #include <rte_common.h>
12 #include <rte_dev.h>
13 #include <rte_launch.h>
14 #include <rte_bbdev.h>
15 #include <rte_cycles.h>
16 #include <rte_lcore.h>
17 #include <rte_malloc.h>
18 #include <rte_random.h>
19 #include <rte_hexdump.h>
20 #include <rte_interrupts.h>
21 
22 #include "main.h"
23 #include "test_bbdev_vector.h"
24 
25 #define GET_SOCKET(socket_id) (((socket_id) == SOCKET_ID_ANY) ? 0 : (socket_id))
26 
27 #define MAX_QUEUES RTE_MAX_LCORE
28 #define TEST_REPETITIONS 100
29 #define WAIT_OFFLOAD_US 1000
30 
31 #ifdef RTE_BASEBAND_FPGA_LTE_FEC
32 #include <fpga_lte_fec.h>
33 #define FPGA_LTE_PF_DRIVER_NAME ("intel_fpga_lte_fec_pf")
34 #define FPGA_LTE_VF_DRIVER_NAME ("intel_fpga_lte_fec_vf")
35 #define VF_UL_4G_QUEUE_VALUE 4
36 #define VF_DL_4G_QUEUE_VALUE 4
37 #define UL_4G_BANDWIDTH 3
38 #define DL_4G_BANDWIDTH 3
39 #define UL_4G_LOAD_BALANCE 128
40 #define DL_4G_LOAD_BALANCE 128
41 #define FLR_4G_TIMEOUT 610
42 #endif
43 
44 #ifdef RTE_BASEBAND_FPGA_5GNR_FEC
45 #include <rte_pmd_fpga_5gnr_fec.h>
46 #define FPGA_5GNR_PF_DRIVER_NAME ("intel_fpga_5gnr_fec_pf")
47 #define FPGA_5GNR_VF_DRIVER_NAME ("intel_fpga_5gnr_fec_vf")
48 #define VF_UL_5G_QUEUE_VALUE 4
49 #define VF_DL_5G_QUEUE_VALUE 4
50 #define UL_5G_BANDWIDTH 3
51 #define DL_5G_BANDWIDTH 3
52 #define UL_5G_LOAD_BALANCE 128
53 #define DL_5G_LOAD_BALANCE 128
54 #endif
55 
56 #ifdef RTE_BASEBAND_ACC
57 #include <rte_acc_cfg.h>
58 #define ACC100PF_DRIVER_NAME   ("intel_acc100_pf")
59 #define ACC100VF_DRIVER_NAME   ("intel_acc100_vf")
60 #define ACC100_QMGR_NUM_AQS 16
61 #define ACC100_QMGR_NUM_QGS 2
62 #define ACC100_QMGR_AQ_DEPTH 5
63 #define ACC100_QMGR_INVALID_IDX -1
64 #define ACC100_QMGR_RR 1
65 #define ACC100_QOS_GBR 0
66 #define ACC200PF_DRIVER_NAME   ("intel_acc200_pf")
67 #define ACC200VF_DRIVER_NAME   ("intel_acc200_vf")
68 #define ACC200_QMGR_NUM_AQS 16
69 #define ACC200_QMGR_NUM_QGS 2
70 #define ACC200_QMGR_AQ_DEPTH 5
71 #define ACC200_QMGR_INVALID_IDX -1
72 #define ACC200_QMGR_RR 1
73 #define ACC200_QOS_GBR 0
74 #endif
75 
76 #define OPS_CACHE_SIZE 256U
77 #define OPS_POOL_SIZE_MIN 511U /* 0.5K per queue */
78 
79 #define SYNC_WAIT 0
80 #define SYNC_START 1
81 #define INVALID_OPAQUE -1
82 
83 #define INVALID_QUEUE_ID -1
84 /* Increment for next code block in external HARQ memory */
85 #define HARQ_INCR 32768
86 /* Headroom for filler LLRs insertion in HARQ buffer */
87 #define FILLER_HEADROOM 1024
88 /* Constants from K0 computation from 3GPP 38.212 Table 5.4.2.1-2 */
89 #define N_ZC_1 66 /* N = 66 Zc for BG 1 */
90 #define N_ZC_2 50 /* N = 50 Zc for BG 2 */
91 #define K0_1_1 17 /* K0 fraction numerator for rv 1 and BG 1 */
92 #define K0_1_2 13 /* K0 fraction numerator for rv 1 and BG 2 */
93 #define K0_2_1 33 /* K0 fraction numerator for rv 2 and BG 1 */
94 #define K0_2_2 25 /* K0 fraction numerator for rv 2 and BG 2 */
95 #define K0_3_1 56 /* K0 fraction numerator for rv 3 and BG 1 */
96 #define K0_3_2 43 /* K0 fraction numerator for rv 3 and BG 2 */
97 
98 static struct test_bbdev_vector test_vector;
99 
100 /* Switch between PMD and Interrupt for throughput TC */
101 static bool intr_enabled;
102 
103 /* LLR arithmetic representation for numerical conversion */
104 static int ldpc_llr_decimals;
105 static int ldpc_llr_size;
106 /* Keep track of the LDPC decoder device capability flag */
107 static uint32_t ldpc_cap_flags;
108 
109 /* Represents tested active devices */
110 static struct active_device {
111 	const char *driver_name;
112 	uint8_t dev_id;
113 	uint16_t supported_ops;
114 	uint16_t queue_ids[MAX_QUEUES];
115 	uint16_t nb_queues;
116 	struct rte_mempool *ops_mempool;
117 	struct rte_mempool *in_mbuf_pool;
118 	struct rte_mempool *hard_out_mbuf_pool;
119 	struct rte_mempool *soft_out_mbuf_pool;
120 	struct rte_mempool *harq_in_mbuf_pool;
121 	struct rte_mempool *harq_out_mbuf_pool;
122 } active_devs[RTE_BBDEV_MAX_DEVS];
123 
124 static uint8_t nb_active_devs;
125 
126 /* Data buffers used by BBDEV ops */
127 struct test_buffers {
128 	struct rte_bbdev_op_data *inputs;
129 	struct rte_bbdev_op_data *hard_outputs;
130 	struct rte_bbdev_op_data *soft_outputs;
131 	struct rte_bbdev_op_data *harq_inputs;
132 	struct rte_bbdev_op_data *harq_outputs;
133 };
134 
135 /* Operation parameters specific for given test case */
136 struct test_op_params {
137 	struct rte_mempool *mp;
138 	struct rte_bbdev_dec_op *ref_dec_op;
139 	struct rte_bbdev_enc_op *ref_enc_op;
140 	struct rte_bbdev_fft_op *ref_fft_op;
141 	uint16_t burst_sz;
142 	uint16_t num_to_process;
143 	uint16_t num_lcores;
144 	int vector_mask;
145 	uint16_t sync;
146 	struct test_buffers q_bufs[RTE_MAX_NUMA_NODES][MAX_QUEUES];
147 };
148 
149 /* Contains per lcore params */
150 struct thread_params {
151 	uint8_t dev_id;
152 	uint16_t queue_id;
153 	uint32_t lcore_id;
154 	uint64_t start_time;
155 	double ops_per_sec;
156 	double mbps;
157 	uint8_t iter_count;
158 	double iter_average;
159 	double bler;
160 	uint16_t nb_dequeued;
161 	int16_t processing_status;
162 	uint16_t burst_sz;
163 	struct test_op_params *op_params;
164 	struct rte_bbdev_dec_op *dec_ops[MAX_BURST];
165 	struct rte_bbdev_enc_op *enc_ops[MAX_BURST];
166 	struct rte_bbdev_fft_op *fft_ops[MAX_BURST];
167 };
168 
169 #ifdef RTE_BBDEV_OFFLOAD_COST
170 /* Stores time statistics */
171 struct test_time_stats {
172 	/* Stores software enqueue total working time */
173 	uint64_t enq_sw_total_time;
174 	/* Stores minimum value of software enqueue working time */
175 	uint64_t enq_sw_min_time;
176 	/* Stores maximum value of software enqueue working time */
177 	uint64_t enq_sw_max_time;
178 	/* Stores turbo enqueue total working time */
179 	uint64_t enq_acc_total_time;
180 	/* Stores minimum value of accelerator enqueue working time */
181 	uint64_t enq_acc_min_time;
182 	/* Stores maximum value of accelerator enqueue working time */
183 	uint64_t enq_acc_max_time;
184 	/* Stores dequeue total working time */
185 	uint64_t deq_total_time;
186 	/* Stores minimum value of dequeue working time */
187 	uint64_t deq_min_time;
188 	/* Stores maximum value of dequeue working time */
189 	uint64_t deq_max_time;
190 };
191 #endif
192 
193 typedef int (test_case_function)(struct active_device *ad,
194 		struct test_op_params *op_params);
195 
196 static inline void
197 mbuf_reset(struct rte_mbuf *m)
198 {
199 	m->pkt_len = 0;
200 
201 	do {
202 		m->data_len = 0;
203 		m = m->next;
204 	} while (m != NULL);
205 }
206 
207 /* Read flag value 0/1 from bitmap */
208 static inline bool
209 check_bit(uint32_t bitmap, uint32_t bitmask)
210 {
211 	return bitmap & bitmask;
212 }
213 
214 static inline void
215 set_avail_op(struct active_device *ad, enum rte_bbdev_op_type op_type)
216 {
217 	ad->supported_ops |= (1 << op_type);
218 }
219 
220 static inline bool
221 is_avail_op(struct active_device *ad, enum rte_bbdev_op_type op_type)
222 {
223 	return ad->supported_ops & (1 << op_type);
224 }
225 
226 static inline bool
227 flags_match(uint32_t flags_req, uint32_t flags_present)
228 {
229 	return (flags_req & flags_present) == flags_req;
230 }
231 
232 static void
233 clear_soft_out_cap(uint32_t *op_flags)
234 {
235 	*op_flags &= ~RTE_BBDEV_TURBO_SOFT_OUTPUT;
236 	*op_flags &= ~RTE_BBDEV_TURBO_POS_LLR_1_BIT_SOFT_OUT;
237 	*op_flags &= ~RTE_BBDEV_TURBO_NEG_LLR_1_BIT_SOFT_OUT;
238 }
239 
240 /* This API is to convert all the test vector op data entries
241  * to big endian format. It is used when the device supports
242  * the input in the big endian format.
243  */
244 static inline void
245 convert_op_data_to_be(void)
246 {
247 	struct op_data_entries *op;
248 	enum op_data_type type;
249 	uint8_t nb_segs, *rem_data, temp;
250 	uint32_t *data, len;
251 	int complete, rem, i, j;
252 
253 	for (type = DATA_INPUT; type < DATA_NUM_TYPES; ++type) {
254 		nb_segs = test_vector.entries[type].nb_segments;
255 		op = &test_vector.entries[type];
256 
257 		/* Invert byte endianness for all the segments */
258 		for (i = 0; i < nb_segs; ++i) {
259 			len = op->segments[i].length;
260 			data = op->segments[i].addr;
261 
262 			/* Swap complete u32 bytes */
263 			complete = len / 4;
264 			for (j = 0; j < complete; j++)
265 				data[j] = rte_bswap32(data[j]);
266 
267 			/* Swap any remaining bytes */
268 			rem = len % 4;
269 			rem_data = (uint8_t *)&data[j];
270 			for (j = 0; j < rem/2; j++) {
271 				temp = rem_data[j];
272 				rem_data[j] = rem_data[rem - j - 1];
273 				rem_data[rem - j - 1] = temp;
274 			}
275 		}
276 	}
277 }
278 
279 static int
280 check_dev_cap(const struct rte_bbdev_info *dev_info)
281 {
282 	unsigned int i;
283 	unsigned int nb_inputs, nb_soft_outputs, nb_hard_outputs,
284 		nb_harq_inputs, nb_harq_outputs;
285 	const struct rte_bbdev_op_cap *op_cap = dev_info->drv.capabilities;
286 	uint8_t dev_data_endianness = dev_info->drv.data_endianness;
287 
288 	nb_inputs = test_vector.entries[DATA_INPUT].nb_segments;
289 	nb_soft_outputs = test_vector.entries[DATA_SOFT_OUTPUT].nb_segments;
290 	nb_hard_outputs = test_vector.entries[DATA_HARD_OUTPUT].nb_segments;
291 	nb_harq_inputs  = test_vector.entries[DATA_HARQ_INPUT].nb_segments;
292 	nb_harq_outputs = test_vector.entries[DATA_HARQ_OUTPUT].nb_segments;
293 
294 	for (i = 0; op_cap->type != RTE_BBDEV_OP_NONE; ++i, ++op_cap) {
295 		if (op_cap->type != test_vector.op_type)
296 			continue;
297 
298 		if (dev_data_endianness == RTE_BIG_ENDIAN)
299 			convert_op_data_to_be();
300 
301 		if (op_cap->type == RTE_BBDEV_OP_TURBO_DEC) {
302 			const struct rte_bbdev_op_cap_turbo_dec *cap =
303 					&op_cap->cap.turbo_dec;
304 			/* Ignore lack of soft output capability, just skip
305 			 * checking if soft output is valid.
306 			 */
307 			if ((test_vector.turbo_dec.op_flags &
308 					RTE_BBDEV_TURBO_SOFT_OUTPUT) &&
309 					!(cap->capability_flags &
310 					RTE_BBDEV_TURBO_SOFT_OUTPUT)) {
311 				printf(
312 					"INFO: Device \"%s\" does not support soft output - soft output flags will be ignored.\n",
313 					dev_info->dev_name);
314 				clear_soft_out_cap(
315 					&test_vector.turbo_dec.op_flags);
316 			}
317 
318 			if (!flags_match(test_vector.turbo_dec.op_flags,
319 					cap->capability_flags))
320 				return TEST_FAILED;
321 			if (nb_inputs > cap->num_buffers_src) {
322 				printf("Too many inputs defined: %u, max: %u\n",
323 					nb_inputs, cap->num_buffers_src);
324 				return TEST_FAILED;
325 			}
326 			if (nb_soft_outputs > cap->num_buffers_soft_out &&
327 					(test_vector.turbo_dec.op_flags &
328 					RTE_BBDEV_TURBO_SOFT_OUTPUT)) {
329 				printf(
330 					"Too many soft outputs defined: %u, max: %u\n",
331 						nb_soft_outputs,
332 						cap->num_buffers_soft_out);
333 				return TEST_FAILED;
334 			}
335 			if (nb_hard_outputs > cap->num_buffers_hard_out) {
336 				printf(
337 					"Too many hard outputs defined: %u, max: %u\n",
338 						nb_hard_outputs,
339 						cap->num_buffers_hard_out);
340 				return TEST_FAILED;
341 			}
342 			if (intr_enabled && !(cap->capability_flags &
343 					RTE_BBDEV_TURBO_DEC_INTERRUPTS)) {
344 				printf(
345 					"Dequeue interrupts are not supported!\n");
346 				return TEST_FAILED;
347 			}
348 
349 			return TEST_SUCCESS;
350 		} else if (op_cap->type == RTE_BBDEV_OP_TURBO_ENC) {
351 			const struct rte_bbdev_op_cap_turbo_enc *cap =
352 					&op_cap->cap.turbo_enc;
353 
354 			if (!flags_match(test_vector.turbo_enc.op_flags,
355 					cap->capability_flags))
356 				return TEST_FAILED;
357 			if (nb_inputs > cap->num_buffers_src) {
358 				printf("Too many inputs defined: %u, max: %u\n",
359 					nb_inputs, cap->num_buffers_src);
360 				return TEST_FAILED;
361 			}
362 			if (nb_hard_outputs > cap->num_buffers_dst) {
363 				printf(
364 					"Too many hard outputs defined: %u, max: %u\n",
365 					nb_hard_outputs, cap->num_buffers_dst);
366 				return TEST_FAILED;
367 			}
368 			if (intr_enabled && !(cap->capability_flags &
369 					RTE_BBDEV_TURBO_ENC_INTERRUPTS)) {
370 				printf(
371 					"Dequeue interrupts are not supported!\n");
372 				return TEST_FAILED;
373 			}
374 
375 			return TEST_SUCCESS;
376 		} else if (op_cap->type == RTE_BBDEV_OP_LDPC_ENC) {
377 			const struct rte_bbdev_op_cap_ldpc_enc *cap =
378 					&op_cap->cap.ldpc_enc;
379 
380 			if (!flags_match(test_vector.ldpc_enc.op_flags,
381 					cap->capability_flags)){
382 				printf("Flag Mismatch\n");
383 				return TEST_FAILED;
384 			}
385 			if (nb_inputs > cap->num_buffers_src) {
386 				printf("Too many inputs defined: %u, max: %u\n",
387 					nb_inputs, cap->num_buffers_src);
388 				return TEST_FAILED;
389 			}
390 			if (nb_hard_outputs > cap->num_buffers_dst) {
391 				printf(
392 					"Too many hard outputs defined: %u, max: %u\n",
393 					nb_hard_outputs, cap->num_buffers_dst);
394 				return TEST_FAILED;
395 			}
396 			if (intr_enabled && !(cap->capability_flags &
397 					RTE_BBDEV_LDPC_ENC_INTERRUPTS)) {
398 				printf(
399 					"Dequeue interrupts are not supported!\n");
400 				return TEST_FAILED;
401 			}
402 
403 			return TEST_SUCCESS;
404 		} else if (op_cap->type == RTE_BBDEV_OP_LDPC_DEC) {
405 			const struct rte_bbdev_op_cap_ldpc_dec *cap =
406 					&op_cap->cap.ldpc_dec;
407 
408 			if (!flags_match(test_vector.ldpc_dec.op_flags,
409 					cap->capability_flags)){
410 				printf("Flag Mismatch\n");
411 				return TEST_FAILED;
412 			}
413 			if (nb_inputs > cap->num_buffers_src) {
414 				printf("Too many inputs defined: %u, max: %u\n",
415 					nb_inputs, cap->num_buffers_src);
416 				return TEST_FAILED;
417 			}
418 			if (nb_hard_outputs > cap->num_buffers_hard_out) {
419 				printf(
420 					"Too many hard outputs defined: %u, max: %u\n",
421 					nb_hard_outputs,
422 					cap->num_buffers_hard_out);
423 				return TEST_FAILED;
424 			}
425 			if (nb_harq_inputs > cap->num_buffers_hard_out) {
426 				printf(
427 					"Too many HARQ inputs defined: %u, max: %u\n",
428 					nb_harq_inputs,
429 					cap->num_buffers_hard_out);
430 				return TEST_FAILED;
431 			}
432 			if (nb_harq_outputs > cap->num_buffers_hard_out) {
433 				printf(
434 					"Too many HARQ outputs defined: %u, max: %u\n",
435 					nb_harq_outputs,
436 					cap->num_buffers_hard_out);
437 				return TEST_FAILED;
438 			}
439 			if (intr_enabled && !(cap->capability_flags &
440 					RTE_BBDEV_LDPC_DEC_INTERRUPTS)) {
441 				printf(
442 					"Dequeue interrupts are not supported!\n");
443 				return TEST_FAILED;
444 			}
445 			if (intr_enabled && (test_vector.ldpc_dec.op_flags &
446 				(RTE_BBDEV_LDPC_HQ_COMBINE_IN_ENABLE |
447 				RTE_BBDEV_LDPC_HQ_COMBINE_OUT_ENABLE |
448 				RTE_BBDEV_LDPC_INTERNAL_HARQ_MEMORY_LOOPBACK
449 					))) {
450 				printf("Skip loop-back with interrupt\n");
451 				return TEST_FAILED;
452 			}
453 			return TEST_SUCCESS;
454 		} else if (op_cap->type == RTE_BBDEV_OP_FFT) {
455 			const struct rte_bbdev_op_cap_fft *cap = &op_cap->cap.fft;
456 
457 			if (!flags_match(test_vector.fft.op_flags, cap->capability_flags)) {
458 				printf("Flag Mismatch\n");
459 				return TEST_FAILED;
460 			}
461 			if (nb_inputs > cap->num_buffers_src) {
462 				printf("Too many inputs defined: %u, max: %u\n",
463 					nb_inputs, cap->num_buffers_src);
464 				return TEST_FAILED;
465 			}
466 			return TEST_SUCCESS;
467 		}
468 	}
469 
470 	if ((i == 0) && (test_vector.op_type == RTE_BBDEV_OP_NONE))
471 		return TEST_SUCCESS; /* Special case for NULL device */
472 
473 	return TEST_FAILED;
474 }
475 
476 /* calculates optimal mempool size not smaller than the val */
477 static unsigned int
478 optimal_mempool_size(unsigned int val)
479 {
480 	return rte_align32pow2(val + 1) - 1;
481 }
482 
483 /* allocates mbuf mempool for inputs and outputs */
484 static struct rte_mempool *
485 create_mbuf_pool(struct op_data_entries *entries, uint8_t dev_id,
486 		int socket_id, unsigned int mbuf_pool_size,
487 		const char *op_type_str)
488 {
489 	unsigned int i;
490 	uint32_t max_seg_sz = 0;
491 	char pool_name[RTE_MEMPOOL_NAMESIZE];
492 
493 	/* find max input segment size */
494 	for (i = 0; i < entries->nb_segments; ++i)
495 		if (entries->segments[i].length > max_seg_sz)
496 			max_seg_sz = entries->segments[i].length;
497 
498 	snprintf(pool_name, sizeof(pool_name), "%s_pool_%u", op_type_str,
499 			dev_id);
500 	return rte_pktmbuf_pool_create(pool_name, mbuf_pool_size, 0, 0,
501 			RTE_MAX(max_seg_sz + RTE_PKTMBUF_HEADROOM
502 					+ FILLER_HEADROOM,
503 			(unsigned int)RTE_MBUF_DEFAULT_BUF_SIZE), socket_id);
504 }
505 
506 static int
507 create_mempools(struct active_device *ad, int socket_id,
508 		enum rte_bbdev_op_type org_op_type, uint16_t num_ops)
509 {
510 	struct rte_mempool *mp;
511 	unsigned int ops_pool_size, mbuf_pool_size = 0;
512 	char pool_name[RTE_MEMPOOL_NAMESIZE];
513 	const char *op_type_str;
514 	enum rte_bbdev_op_type op_type = org_op_type;
515 
516 	struct op_data_entries *in = &test_vector.entries[DATA_INPUT];
517 	struct op_data_entries *hard_out =
518 			&test_vector.entries[DATA_HARD_OUTPUT];
519 	struct op_data_entries *soft_out =
520 			&test_vector.entries[DATA_SOFT_OUTPUT];
521 	struct op_data_entries *harq_in =
522 			&test_vector.entries[DATA_HARQ_INPUT];
523 	struct op_data_entries *harq_out =
524 			&test_vector.entries[DATA_HARQ_OUTPUT];
525 
526 	/* allocate ops mempool */
527 	ops_pool_size = optimal_mempool_size(RTE_MAX(
528 			/* Ops used plus 1 reference op */
529 			RTE_MAX((unsigned int)(ad->nb_queues * num_ops + 1),
530 			/* Minimal cache size plus 1 reference op */
531 			(unsigned int)(1.5 * rte_lcore_count() *
532 					OPS_CACHE_SIZE + 1)),
533 			OPS_POOL_SIZE_MIN));
534 
535 	if (org_op_type == RTE_BBDEV_OP_NONE)
536 		op_type = RTE_BBDEV_OP_TURBO_ENC;
537 
538 	op_type_str = rte_bbdev_op_type_str(op_type);
539 	TEST_ASSERT_NOT_NULL(op_type_str, "Invalid op type: %u", op_type);
540 
541 	snprintf(pool_name, sizeof(pool_name), "%s_pool_%u", op_type_str,
542 			ad->dev_id);
543 	mp = rte_bbdev_op_pool_create(pool_name, op_type,
544 			ops_pool_size, OPS_CACHE_SIZE, socket_id);
545 	TEST_ASSERT_NOT_NULL(mp,
546 			"ERROR Failed to create %u items ops pool for dev %u on socket %u.",
547 			ops_pool_size,
548 			ad->dev_id,
549 			socket_id);
550 	ad->ops_mempool = mp;
551 
552 	/* Do not create inputs and outputs mbufs for BaseBand Null Device */
553 	if (org_op_type == RTE_BBDEV_OP_NONE)
554 		return TEST_SUCCESS;
555 
556 	/* Inputs */
557 	if (in->nb_segments > 0) {
558 		mbuf_pool_size = optimal_mempool_size(ops_pool_size *
559 				in->nb_segments);
560 		mp = create_mbuf_pool(in, ad->dev_id, socket_id,
561 				mbuf_pool_size, "in");
562 		TEST_ASSERT_NOT_NULL(mp,
563 				"ERROR Failed to create %u items input pktmbuf pool for dev %u on socket %u.",
564 				mbuf_pool_size,
565 				ad->dev_id,
566 				socket_id);
567 		ad->in_mbuf_pool = mp;
568 	}
569 
570 	/* Hard outputs */
571 	if (hard_out->nb_segments > 0) {
572 		mbuf_pool_size = optimal_mempool_size(ops_pool_size *
573 				hard_out->nb_segments);
574 		mp = create_mbuf_pool(hard_out, ad->dev_id, socket_id,
575 				mbuf_pool_size,
576 				"hard_out");
577 		TEST_ASSERT_NOT_NULL(mp,
578 				"ERROR Failed to create %u items hard output pktmbuf pool for dev %u on socket %u.",
579 				mbuf_pool_size,
580 				ad->dev_id,
581 				socket_id);
582 		ad->hard_out_mbuf_pool = mp;
583 	}
584 
585 	/* Soft outputs */
586 	if (soft_out->nb_segments > 0) {
587 		mbuf_pool_size = optimal_mempool_size(ops_pool_size *
588 				soft_out->nb_segments);
589 		mp = create_mbuf_pool(soft_out, ad->dev_id, socket_id,
590 				mbuf_pool_size,
591 				"soft_out");
592 		TEST_ASSERT_NOT_NULL(mp,
593 				"ERROR Failed to create %uB soft output pktmbuf pool for dev %u on socket %u.",
594 				mbuf_pool_size,
595 				ad->dev_id,
596 				socket_id);
597 		ad->soft_out_mbuf_pool = mp;
598 	}
599 
600 	/* HARQ inputs */
601 	if (harq_in->nb_segments > 0) {
602 		mbuf_pool_size = optimal_mempool_size(ops_pool_size *
603 				harq_in->nb_segments);
604 		mp = create_mbuf_pool(harq_in, ad->dev_id, socket_id,
605 				mbuf_pool_size,
606 				"harq_in");
607 		TEST_ASSERT_NOT_NULL(mp,
608 				"ERROR Failed to create %uB harq input pktmbuf pool for dev %u on socket %u.",
609 				mbuf_pool_size,
610 				ad->dev_id,
611 				socket_id);
612 		ad->harq_in_mbuf_pool = mp;
613 	}
614 
615 	/* HARQ outputs */
616 	if (harq_out->nb_segments > 0) {
617 		mbuf_pool_size = optimal_mempool_size(ops_pool_size *
618 				harq_out->nb_segments);
619 		mp = create_mbuf_pool(harq_out, ad->dev_id, socket_id,
620 				mbuf_pool_size,
621 				"harq_out");
622 		TEST_ASSERT_NOT_NULL(mp,
623 				"ERROR Failed to create %uB harq output pktmbuf pool for dev %u on socket %u.",
624 				mbuf_pool_size,
625 				ad->dev_id,
626 				socket_id);
627 		ad->harq_out_mbuf_pool = mp;
628 	}
629 
630 	return TEST_SUCCESS;
631 }
632 
633 static int
634 add_bbdev_dev(uint8_t dev_id, struct rte_bbdev_info *info,
635 		struct test_bbdev_vector *vector)
636 {
637 	int ret;
638 	unsigned int queue_id;
639 	struct rte_bbdev_queue_conf qconf;
640 	struct active_device *ad = &active_devs[nb_active_devs];
641 	unsigned int nb_queues;
642 	enum rte_bbdev_op_type op_type = vector->op_type;
643 
644 /* Configure fpga lte fec with PF & VF values
645  * if '-i' flag is set and using fpga device
646  */
647 #ifdef RTE_BASEBAND_FPGA_LTE_FEC
648 	if ((get_init_device() == true) &&
649 		(!strcmp(info->drv.driver_name, FPGA_LTE_PF_DRIVER_NAME))) {
650 		struct rte_fpga_lte_fec_conf conf;
651 		unsigned int i;
652 
653 		printf("Configure FPGA LTE FEC Driver %s with default values\n",
654 				info->drv.driver_name);
655 
656 		/* clear default configuration before initialization */
657 		memset(&conf, 0, sizeof(struct rte_fpga_lte_fec_conf));
658 
659 		/* Set PF mode :
660 		 * true if PF is used for data plane
661 		 * false for VFs
662 		 */
663 		conf.pf_mode_en = true;
664 
665 		for (i = 0; i < FPGA_LTE_FEC_NUM_VFS; ++i) {
666 			/* Number of UL queues per VF (fpga supports 8 VFs) */
667 			conf.vf_ul_queues_number[i] = VF_UL_4G_QUEUE_VALUE;
668 			/* Number of DL queues per VF (fpga supports 8 VFs) */
669 			conf.vf_dl_queues_number[i] = VF_DL_4G_QUEUE_VALUE;
670 		}
671 
672 		/* UL bandwidth. Needed for schedule algorithm */
673 		conf.ul_bandwidth = UL_4G_BANDWIDTH;
674 		/* DL bandwidth */
675 		conf.dl_bandwidth = DL_4G_BANDWIDTH;
676 
677 		/* UL & DL load Balance Factor to 64 */
678 		conf.ul_load_balance = UL_4G_LOAD_BALANCE;
679 		conf.dl_load_balance = DL_4G_LOAD_BALANCE;
680 
681 		/**< FLR timeout value */
682 		conf.flr_time_out = FLR_4G_TIMEOUT;
683 
684 		/* setup FPGA PF with configuration information */
685 		ret = rte_fpga_lte_fec_configure(info->dev_name, &conf);
686 		TEST_ASSERT_SUCCESS(ret,
687 				"Failed to configure 4G FPGA PF for bbdev %s",
688 				info->dev_name);
689 	}
690 #endif
691 #ifdef RTE_BASEBAND_FPGA_5GNR_FEC
692 	if ((get_init_device() == true) &&
693 		(!strcmp(info->drv.driver_name, FPGA_5GNR_PF_DRIVER_NAME))) {
694 		struct rte_fpga_5gnr_fec_conf conf;
695 		unsigned int i;
696 
697 		printf("Configure FPGA 5GNR FEC Driver %s with default values\n",
698 				info->drv.driver_name);
699 
700 		/* clear default configuration before initialization */
701 		memset(&conf, 0, sizeof(struct rte_fpga_5gnr_fec_conf));
702 
703 		/* Set PF mode :
704 		 * true if PF is used for data plane
705 		 * false for VFs
706 		 */
707 		conf.pf_mode_en = true;
708 
709 		for (i = 0; i < FPGA_5GNR_FEC_NUM_VFS; ++i) {
710 			/* Number of UL queues per VF (fpga supports 8 VFs) */
711 			conf.vf_ul_queues_number[i] = VF_UL_5G_QUEUE_VALUE;
712 			/* Number of DL queues per VF (fpga supports 8 VFs) */
713 			conf.vf_dl_queues_number[i] = VF_DL_5G_QUEUE_VALUE;
714 		}
715 
716 		/* UL bandwidth. Needed for schedule algorithm */
717 		conf.ul_bandwidth = UL_5G_BANDWIDTH;
718 		/* DL bandwidth */
719 		conf.dl_bandwidth = DL_5G_BANDWIDTH;
720 
721 		/* UL & DL load Balance Factor to 64 */
722 		conf.ul_load_balance = UL_5G_LOAD_BALANCE;
723 		conf.dl_load_balance = DL_5G_LOAD_BALANCE;
724 
725 		/* setup FPGA PF with configuration information */
726 		ret = rte_fpga_5gnr_fec_configure(info->dev_name, &conf);
727 		TEST_ASSERT_SUCCESS(ret,
728 				"Failed to configure 5G FPGA PF for bbdev %s",
729 				info->dev_name);
730 	}
731 #endif
732 #ifdef RTE_BASEBAND_ACC
733 	if ((get_init_device() == true) &&
734 			(!strcmp(info->drv.driver_name, ACC100PF_DRIVER_NAME))) {
735 		struct rte_acc_conf conf;
736 		unsigned int i;
737 
738 		printf("Configure ACC100/ACC101 FEC Driver %s with default values\n",
739 				info->drv.driver_name);
740 
741 		/* clear default configuration before initialization */
742 		memset(&conf, 0, sizeof(struct rte_acc_conf));
743 
744 		/* Always set in PF mode for built-in configuration */
745 		conf.pf_mode_en = true;
746 		for (i = 0; i < RTE_ACC_NUM_VFS; ++i) {
747 			conf.arb_dl_4g[i].gbr_threshold1 = ACC100_QOS_GBR;
748 			conf.arb_dl_4g[i].gbr_threshold1 = ACC100_QOS_GBR;
749 			conf.arb_dl_4g[i].round_robin_weight = ACC100_QMGR_RR;
750 			conf.arb_ul_4g[i].gbr_threshold1 = ACC100_QOS_GBR;
751 			conf.arb_ul_4g[i].gbr_threshold1 = ACC100_QOS_GBR;
752 			conf.arb_ul_4g[i].round_robin_weight = ACC100_QMGR_RR;
753 			conf.arb_dl_5g[i].gbr_threshold1 = ACC100_QOS_GBR;
754 			conf.arb_dl_5g[i].gbr_threshold1 = ACC100_QOS_GBR;
755 			conf.arb_dl_5g[i].round_robin_weight = ACC100_QMGR_RR;
756 			conf.arb_ul_5g[i].gbr_threshold1 = ACC100_QOS_GBR;
757 			conf.arb_ul_5g[i].gbr_threshold1 = ACC100_QOS_GBR;
758 			conf.arb_ul_5g[i].round_robin_weight = ACC100_QMGR_RR;
759 		}
760 
761 		conf.input_pos_llr_1_bit = true;
762 		conf.output_pos_llr_1_bit = true;
763 		conf.num_vf_bundles = 1; /**< Number of VF bundles to setup */
764 
765 		conf.q_ul_4g.num_qgroups = ACC100_QMGR_NUM_QGS;
766 		conf.q_ul_4g.first_qgroup_index = ACC100_QMGR_INVALID_IDX;
767 		conf.q_ul_4g.num_aqs_per_groups = ACC100_QMGR_NUM_AQS;
768 		conf.q_ul_4g.aq_depth_log2 = ACC100_QMGR_AQ_DEPTH;
769 		conf.q_dl_4g.num_qgroups = ACC100_QMGR_NUM_QGS;
770 		conf.q_dl_4g.first_qgroup_index = ACC100_QMGR_INVALID_IDX;
771 		conf.q_dl_4g.num_aqs_per_groups = ACC100_QMGR_NUM_AQS;
772 		conf.q_dl_4g.aq_depth_log2 = ACC100_QMGR_AQ_DEPTH;
773 		conf.q_ul_5g.num_qgroups = ACC100_QMGR_NUM_QGS;
774 		conf.q_ul_5g.first_qgroup_index = ACC100_QMGR_INVALID_IDX;
775 		conf.q_ul_5g.num_aqs_per_groups = ACC100_QMGR_NUM_AQS;
776 		conf.q_ul_5g.aq_depth_log2 = ACC100_QMGR_AQ_DEPTH;
777 		conf.q_dl_5g.num_qgroups = ACC100_QMGR_NUM_QGS;
778 		conf.q_dl_5g.first_qgroup_index = ACC100_QMGR_INVALID_IDX;
779 		conf.q_dl_5g.num_aqs_per_groups = ACC100_QMGR_NUM_AQS;
780 		conf.q_dl_5g.aq_depth_log2 = ACC100_QMGR_AQ_DEPTH;
781 
782 		/* setup PF with configuration information */
783 		ret = rte_acc_configure(info->dev_name, &conf);
784 		TEST_ASSERT_SUCCESS(ret,
785 				"Failed to configure ACC100 PF for bbdev %s",
786 				info->dev_name);
787 	}
788 	if ((get_init_device() == true) &&
789 		(!strcmp(info->drv.driver_name, ACC200PF_DRIVER_NAME))) {
790 		struct rte_acc_conf conf;
791 		unsigned int i;
792 
793 		printf("Configure ACC200 FEC Driver %s with default values\n",
794 				info->drv.driver_name);
795 
796 		/* clear default configuration before initialization */
797 		memset(&conf, 0, sizeof(struct rte_acc_conf));
798 
799 		/* Always set in PF mode for built-in configuration */
800 		conf.pf_mode_en = true;
801 		for (i = 0; i < RTE_ACC_NUM_VFS; ++i) {
802 			conf.arb_dl_4g[i].gbr_threshold1 = ACC200_QOS_GBR;
803 			conf.arb_dl_4g[i].gbr_threshold1 = ACC200_QOS_GBR;
804 			conf.arb_dl_4g[i].round_robin_weight = ACC200_QMGR_RR;
805 			conf.arb_ul_4g[i].gbr_threshold1 = ACC200_QOS_GBR;
806 			conf.arb_ul_4g[i].gbr_threshold1 = ACC200_QOS_GBR;
807 			conf.arb_ul_4g[i].round_robin_weight = ACC200_QMGR_RR;
808 			conf.arb_dl_5g[i].gbr_threshold1 = ACC200_QOS_GBR;
809 			conf.arb_dl_5g[i].gbr_threshold1 = ACC200_QOS_GBR;
810 			conf.arb_dl_5g[i].round_robin_weight = ACC200_QMGR_RR;
811 			conf.arb_ul_5g[i].gbr_threshold1 = ACC200_QOS_GBR;
812 			conf.arb_ul_5g[i].gbr_threshold1 = ACC200_QOS_GBR;
813 			conf.arb_ul_5g[i].round_robin_weight = ACC200_QMGR_RR;
814 			conf.arb_fft[i].gbr_threshold1 = ACC200_QOS_GBR;
815 			conf.arb_fft[i].gbr_threshold1 = ACC200_QOS_GBR;
816 			conf.arb_fft[i].round_robin_weight = ACC200_QMGR_RR;
817 		}
818 
819 		conf.input_pos_llr_1_bit = true;
820 		conf.output_pos_llr_1_bit = true;
821 		conf.num_vf_bundles = 1; /**< Number of VF bundles to setup */
822 
823 		conf.q_ul_4g.num_qgroups = ACC200_QMGR_NUM_QGS;
824 		conf.q_ul_4g.first_qgroup_index = ACC200_QMGR_INVALID_IDX;
825 		conf.q_ul_4g.num_aqs_per_groups = ACC200_QMGR_NUM_AQS;
826 		conf.q_ul_4g.aq_depth_log2 = ACC200_QMGR_AQ_DEPTH;
827 		conf.q_dl_4g.num_qgroups = ACC200_QMGR_NUM_QGS;
828 		conf.q_dl_4g.first_qgroup_index = ACC200_QMGR_INVALID_IDX;
829 		conf.q_dl_4g.num_aqs_per_groups = ACC200_QMGR_NUM_AQS;
830 		conf.q_dl_4g.aq_depth_log2 = ACC200_QMGR_AQ_DEPTH;
831 		conf.q_ul_5g.num_qgroups = ACC200_QMGR_NUM_QGS;
832 		conf.q_ul_5g.first_qgroup_index = ACC200_QMGR_INVALID_IDX;
833 		conf.q_ul_5g.num_aqs_per_groups = ACC200_QMGR_NUM_AQS;
834 		conf.q_ul_5g.aq_depth_log2 = ACC200_QMGR_AQ_DEPTH;
835 		conf.q_dl_5g.num_qgroups = ACC200_QMGR_NUM_QGS;
836 		conf.q_dl_5g.first_qgroup_index = ACC200_QMGR_INVALID_IDX;
837 		conf.q_dl_5g.num_aqs_per_groups = ACC200_QMGR_NUM_AQS;
838 		conf.q_dl_5g.aq_depth_log2 = ACC200_QMGR_AQ_DEPTH;
839 		conf.q_fft.num_qgroups = ACC200_QMGR_NUM_QGS;
840 		conf.q_fft.first_qgroup_index = ACC200_QMGR_INVALID_IDX;
841 		conf.q_fft.num_aqs_per_groups = ACC200_QMGR_NUM_AQS;
842 		conf.q_fft.aq_depth_log2 = ACC200_QMGR_AQ_DEPTH;
843 
844 		/* setup PF with configuration information */
845 		ret = rte_acc_configure(info->dev_name, &conf);
846 		TEST_ASSERT_SUCCESS(ret,
847 				"Failed to configure ACC200 PF for bbdev %s",
848 				info->dev_name);
849 	}
850 #endif
851 	/* Let's refresh this now this is configured */
852 	rte_bbdev_info_get(dev_id, info);
853 	nb_queues = RTE_MIN(rte_lcore_count(), info->drv.max_num_queues);
854 	nb_queues = RTE_MIN(nb_queues, (unsigned int) MAX_QUEUES);
855 
856 	/* setup device */
857 	ret = rte_bbdev_setup_queues(dev_id, nb_queues, info->socket_id);
858 	if (ret < 0) {
859 		printf("rte_bbdev_setup_queues(%u, %u, %d) ret %i\n",
860 				dev_id, nb_queues, info->socket_id, ret);
861 		return TEST_FAILED;
862 	}
863 
864 	/* configure interrupts if needed */
865 	if (intr_enabled) {
866 		ret = rte_bbdev_intr_enable(dev_id);
867 		if (ret < 0) {
868 			printf("rte_bbdev_intr_enable(%u) ret %i\n", dev_id,
869 					ret);
870 			return TEST_FAILED;
871 		}
872 	}
873 
874 	/* setup device queues */
875 	qconf.socket = info->socket_id;
876 	qconf.queue_size = info->drv.default_queue_conf.queue_size;
877 	qconf.priority = 0;
878 	qconf.deferred_start = 0;
879 	qconf.op_type = op_type;
880 
881 	for (queue_id = 0; queue_id < nb_queues; ++queue_id) {
882 		ret = rte_bbdev_queue_configure(dev_id, queue_id, &qconf);
883 		if (ret != 0) {
884 			printf(
885 					"Allocated all queues (id=%u) at prio%u on dev%u\n",
886 					queue_id, qconf.priority, dev_id);
887 			qconf.priority++;
888 			ret = rte_bbdev_queue_configure(ad->dev_id, queue_id,
889 					&qconf);
890 		}
891 		if (ret != 0) {
892 			printf("All queues on dev %u allocated: %u\n",
893 					dev_id, queue_id);
894 			break;
895 		}
896 		ad->queue_ids[queue_id] = queue_id;
897 	}
898 	TEST_ASSERT(queue_id != 0,
899 			"ERROR Failed to configure any queues on dev %u",
900 			dev_id);
901 	ad->nb_queues = queue_id;
902 
903 	set_avail_op(ad, op_type);
904 
905 	return TEST_SUCCESS;
906 }
907 
908 static int
909 add_active_device(uint8_t dev_id, struct rte_bbdev_info *info,
910 		struct test_bbdev_vector *vector)
911 {
912 	int ret;
913 
914 	active_devs[nb_active_devs].driver_name = info->drv.driver_name;
915 	active_devs[nb_active_devs].dev_id = dev_id;
916 
917 	ret = add_bbdev_dev(dev_id, info, vector);
918 	if (ret == TEST_SUCCESS)
919 		++nb_active_devs;
920 	return ret;
921 }
922 
923 static uint8_t
924 populate_active_devices(void)
925 {
926 	int ret;
927 	uint8_t dev_id;
928 	uint8_t nb_devs_added = 0;
929 	struct rte_bbdev_info info;
930 
931 	RTE_BBDEV_FOREACH(dev_id) {
932 		rte_bbdev_info_get(dev_id, &info);
933 
934 		if (check_dev_cap(&info)) {
935 			printf(
936 				"Device %d (%s) does not support specified capabilities\n",
937 					dev_id, info.dev_name);
938 			continue;
939 		}
940 
941 		ret = add_active_device(dev_id, &info, &test_vector);
942 		if (ret != 0) {
943 			printf("Adding active bbdev %s skipped\n",
944 					info.dev_name);
945 			continue;
946 		}
947 		nb_devs_added++;
948 	}
949 
950 	return nb_devs_added;
951 }
952 
953 static int
954 read_test_vector(void)
955 {
956 	int ret;
957 
958 	memset(&test_vector, 0, sizeof(test_vector));
959 	printf("Test vector file = %s\n", get_vector_filename());
960 	ret = test_bbdev_vector_read(get_vector_filename(), &test_vector);
961 	TEST_ASSERT_SUCCESS(ret, "Failed to parse file %s\n",
962 			get_vector_filename());
963 
964 	return TEST_SUCCESS;
965 }
966 
967 static int
968 testsuite_setup(void)
969 {
970 	TEST_ASSERT_SUCCESS(read_test_vector(), "Test suite setup failed\n");
971 
972 	if (populate_active_devices() == 0) {
973 		printf("No suitable devices found!\n");
974 		return TEST_SKIPPED;
975 	}
976 
977 	return TEST_SUCCESS;
978 }
979 
980 static int
981 interrupt_testsuite_setup(void)
982 {
983 	TEST_ASSERT_SUCCESS(read_test_vector(), "Test suite setup failed\n");
984 
985 	/* Enable interrupts */
986 	intr_enabled = true;
987 
988 	/* Special case for NULL device (RTE_BBDEV_OP_NONE) */
989 	if (populate_active_devices() == 0 ||
990 			test_vector.op_type == RTE_BBDEV_OP_NONE) {
991 		intr_enabled = false;
992 		printf("No suitable devices found!\n");
993 		return TEST_SKIPPED;
994 	}
995 
996 	return TEST_SUCCESS;
997 }
998 
999 static void
1000 testsuite_teardown(void)
1001 {
1002 	uint8_t dev_id;
1003 
1004 	/* Unconfigure devices */
1005 	RTE_BBDEV_FOREACH(dev_id)
1006 		rte_bbdev_close(dev_id);
1007 
1008 	/* Clear active devices structs. */
1009 	memset(active_devs, 0, sizeof(active_devs));
1010 	nb_active_devs = 0;
1011 
1012 	/* Disable interrupts */
1013 	intr_enabled = false;
1014 }
1015 
1016 static int
1017 ut_setup(void)
1018 {
1019 	uint8_t i, dev_id;
1020 
1021 	for (i = 0; i < nb_active_devs; i++) {
1022 		dev_id = active_devs[i].dev_id;
1023 		/* reset bbdev stats */
1024 		TEST_ASSERT_SUCCESS(rte_bbdev_stats_reset(dev_id),
1025 				"Failed to reset stats of bbdev %u", dev_id);
1026 		/* start the device */
1027 		TEST_ASSERT_SUCCESS(rte_bbdev_start(dev_id),
1028 				"Failed to start bbdev %u", dev_id);
1029 	}
1030 
1031 	return TEST_SUCCESS;
1032 }
1033 
1034 static void
1035 ut_teardown(void)
1036 {
1037 	uint8_t i, dev_id;
1038 	struct rte_bbdev_stats stats;
1039 
1040 	for (i = 0; i < nb_active_devs; i++) {
1041 		dev_id = active_devs[i].dev_id;
1042 		/* read stats and print */
1043 		rte_bbdev_stats_get(dev_id, &stats);
1044 		/* Stop the device */
1045 		rte_bbdev_stop(dev_id);
1046 	}
1047 }
1048 
1049 static int
1050 init_op_data_objs(struct rte_bbdev_op_data *bufs,
1051 		struct op_data_entries *ref_entries,
1052 		struct rte_mempool *mbuf_pool, const uint16_t n,
1053 		enum op_data_type op_type, uint16_t min_alignment)
1054 {
1055 	int ret;
1056 	unsigned int i, j;
1057 	bool large_input = false;
1058 
1059 	for (i = 0; i < n; ++i) {
1060 		char *data;
1061 		struct op_data_buf *seg = &ref_entries->segments[0];
1062 		struct rte_mbuf *m_head = rte_pktmbuf_alloc(mbuf_pool);
1063 		TEST_ASSERT_NOT_NULL(m_head,
1064 				"Not enough mbufs in %d data type mbuf pool (needed %u, available %u)",
1065 				op_type, n * ref_entries->nb_segments,
1066 				mbuf_pool->size);
1067 
1068 		if ((seg->length + RTE_PKTMBUF_HEADROOM) > RTE_BBDEV_LDPC_E_MAX_MBUF) {
1069 			/*
1070 			 * Special case when DPDK mbuf cannot handle
1071 			 * the required input size
1072 			 */
1073 			printf("Warning: Larger input size than DPDK mbuf %d\n",
1074 					seg->length);
1075 			large_input = true;
1076 		}
1077 		bufs[i].data = m_head;
1078 		bufs[i].offset = 0;
1079 		bufs[i].length = 0;
1080 
1081 		if ((op_type == DATA_INPUT) || (op_type == DATA_HARQ_INPUT)) {
1082 			if (large_input) {
1083 				/* Allocate a fake overused mbuf */
1084 				data = rte_malloc(NULL, seg->length, 0);
1085 				TEST_ASSERT_NOT_NULL(data,
1086 					"rte malloc failed with %u bytes",
1087 					seg->length);
1088 				memcpy(data, seg->addr, seg->length);
1089 				m_head->buf_addr = data;
1090 				rte_mbuf_iova_set(m_head, rte_malloc_virt2iova(data));
1091 				m_head->data_off = 0;
1092 				m_head->data_len = seg->length;
1093 			} else {
1094 				data = rte_pktmbuf_append(m_head, seg->length);
1095 				TEST_ASSERT_NOT_NULL(data,
1096 					"Couldn't append %u bytes to mbuf from %d data type mbuf pool",
1097 					seg->length, op_type);
1098 
1099 				TEST_ASSERT(data == RTE_PTR_ALIGN(
1100 						data, min_alignment),
1101 					"Data addr in mbuf (%p) is not aligned to device min alignment (%u)",
1102 					data, min_alignment);
1103 				rte_memcpy(data, seg->addr, seg->length);
1104 			}
1105 
1106 			bufs[i].length += seg->length;
1107 
1108 			for (j = 1; j < ref_entries->nb_segments; ++j) {
1109 				struct rte_mbuf *m_tail =
1110 						rte_pktmbuf_alloc(mbuf_pool);
1111 				TEST_ASSERT_NOT_NULL(m_tail,
1112 						"Not enough mbufs in %d data type mbuf pool (needed %u, available %u)",
1113 						op_type,
1114 						n * ref_entries->nb_segments,
1115 						mbuf_pool->size);
1116 				seg += 1;
1117 
1118 				data = rte_pktmbuf_append(m_tail, seg->length);
1119 				TEST_ASSERT_NOT_NULL(data,
1120 						"Couldn't append %u bytes to mbuf from %d data type mbuf pool",
1121 						seg->length, op_type);
1122 
1123 				TEST_ASSERT(data == RTE_PTR_ALIGN(data,
1124 						min_alignment),
1125 						"Data addr in mbuf (%p) is not aligned to device min alignment (%u)",
1126 						data, min_alignment);
1127 				rte_memcpy(data, seg->addr, seg->length);
1128 				bufs[i].length += seg->length;
1129 
1130 				ret = rte_pktmbuf_chain(m_head, m_tail);
1131 				TEST_ASSERT_SUCCESS(ret,
1132 						"Couldn't chain mbufs from %d data type mbuf pool",
1133 						op_type);
1134 			}
1135 		} else {
1136 			if (((op_type == DATA_HARD_OUTPUT) || (op_type == DATA_SOFT_OUTPUT))
1137 					&& ((seg->length + RTE_PKTMBUF_HEADROOM)
1138 					> RTE_BBDEV_LDPC_E_MAX_MBUF)) {
1139 				/* Allocate a fake overused mbuf + margin */
1140 				data = rte_malloc(NULL, seg->length + 1024, 0);
1141 				TEST_ASSERT_NOT_NULL(data,
1142 					"rte malloc failed with %u bytes",
1143 					seg->length + 1024);
1144 				m_head->buf_addr = data;
1145 				m_head->buf_iova = rte_malloc_virt2iova(data);
1146 				m_head->data_off = 0;
1147 				m_head->data_len = seg->length;
1148 			} else {
1149 				/* allocate chained-mbuf for output buffer */
1150 				for (j = 1; j < ref_entries->nb_segments; ++j) {
1151 					struct rte_mbuf *m_tail =
1152 						rte_pktmbuf_alloc(mbuf_pool);
1153 					TEST_ASSERT_NOT_NULL(m_tail,
1154 						"Not enough mbufs in %d data type mbuf pool (needed %u, available %u)",
1155 						op_type,
1156 						n * ref_entries->nb_segments,
1157 						mbuf_pool->size);
1158 
1159 					ret = rte_pktmbuf_chain(m_head, m_tail);
1160 					TEST_ASSERT_SUCCESS(ret,
1161 						"Couldn't chain mbufs from %d data type mbuf pool",
1162 						op_type);
1163 				}
1164 			}
1165 			bufs[i].length += seg->length;
1166 		}
1167 	}
1168 
1169 	return 0;
1170 }
1171 
1172 static int
1173 allocate_buffers_on_socket(struct rte_bbdev_op_data **buffers, const int len,
1174 		const int socket)
1175 {
1176 	int i;
1177 
1178 	*buffers = rte_zmalloc_socket(NULL, len, 0, socket);
1179 	if (*buffers == NULL) {
1180 		printf("WARNING: Failed to allocate op_data on socket %d\n",
1181 				socket);
1182 		/* try to allocate memory on other detected sockets */
1183 		for (i = 0; i < socket; i++) {
1184 			*buffers = rte_zmalloc_socket(NULL, len, 0, i);
1185 			if (*buffers != NULL)
1186 				break;
1187 		}
1188 	}
1189 
1190 	return (*buffers == NULL) ? TEST_FAILED : TEST_SUCCESS;
1191 }
1192 
1193 static void
1194 limit_input_llr_val_range(struct rte_bbdev_op_data *input_ops,
1195 		const uint16_t n, const int8_t max_llr_modulus)
1196 {
1197 	uint16_t i, byte_idx;
1198 
1199 	for (i = 0; i < n; ++i) {
1200 		struct rte_mbuf *m = input_ops[i].data;
1201 		while (m != NULL) {
1202 			int8_t *llr = rte_pktmbuf_mtod_offset(m, int8_t *,
1203 					input_ops[i].offset);
1204 			for (byte_idx = 0; byte_idx < rte_pktmbuf_data_len(m);
1205 					++byte_idx)
1206 				llr[byte_idx] = round((double)max_llr_modulus *
1207 						llr[byte_idx] / INT8_MAX);
1208 
1209 			m = m->next;
1210 		}
1211 	}
1212 }
1213 
1214 /*
1215  * We may have to insert filler bits
1216  * when they are required by the HARQ assumption
1217  */
1218 static void
1219 ldpc_add_filler(struct rte_bbdev_op_data *input_ops,
1220 		const uint16_t n, struct test_op_params *op_params)
1221 {
1222 	struct rte_bbdev_op_ldpc_dec dec = op_params->ref_dec_op->ldpc_dec;
1223 
1224 	if (input_ops == NULL)
1225 		return;
1226 	/* No need to add filler if not required by device */
1227 	if (!(ldpc_cap_flags &
1228 			RTE_BBDEV_LDPC_INTERNAL_HARQ_MEMORY_FILLERS))
1229 		return;
1230 	/* No need to add filler for loopback operation */
1231 	if (dec.op_flags & RTE_BBDEV_LDPC_INTERNAL_HARQ_MEMORY_LOOPBACK)
1232 		return;
1233 
1234 	uint16_t i, j, parity_offset;
1235 	for (i = 0; i < n; ++i) {
1236 		struct rte_mbuf *m = input_ops[i].data;
1237 		int8_t *llr = rte_pktmbuf_mtod_offset(m, int8_t *,
1238 				input_ops[i].offset);
1239 		parity_offset = (dec.basegraph == 1 ? 20 : 8)
1240 				* dec.z_c - dec.n_filler;
1241 		uint16_t new_hin_size = input_ops[i].length + dec.n_filler;
1242 		m->data_len = new_hin_size;
1243 		input_ops[i].length = new_hin_size;
1244 		for (j = new_hin_size - 1; j >= parity_offset + dec.n_filler;
1245 				j--)
1246 			llr[j] = llr[j - dec.n_filler];
1247 		uint16_t llr_max_pre_scaling = (1 << (ldpc_llr_size - 1)) - 1;
1248 		for (j = 0; j < dec.n_filler; j++)
1249 			llr[parity_offset + j] = llr_max_pre_scaling;
1250 	}
1251 }
1252 
1253 static void
1254 ldpc_input_llr_scaling(struct rte_bbdev_op_data *input_ops,
1255 		const uint16_t n, const int8_t llr_size,
1256 		const int8_t llr_decimals)
1257 {
1258 	if (input_ops == NULL)
1259 		return;
1260 
1261 	uint16_t i, byte_idx;
1262 
1263 	int16_t llr_max, llr_min, llr_tmp;
1264 	llr_max = (1 << (llr_size - 1)) - 1;
1265 	llr_min = -llr_max;
1266 	for (i = 0; i < n; ++i) {
1267 		struct rte_mbuf *m = input_ops[i].data;
1268 		while (m != NULL) {
1269 			int8_t *llr = rte_pktmbuf_mtod_offset(m, int8_t *,
1270 					input_ops[i].offset);
1271 			for (byte_idx = 0; byte_idx < rte_pktmbuf_data_len(m);
1272 					++byte_idx) {
1273 
1274 				llr_tmp = llr[byte_idx];
1275 				if (llr_decimals == 4)
1276 					llr_tmp *= 8;
1277 				else if (llr_decimals == 2)
1278 					llr_tmp *= 2;
1279 				else if (llr_decimals == 0)
1280 					llr_tmp /= 2;
1281 				llr_tmp = RTE_MIN(llr_max,
1282 						RTE_MAX(llr_min, llr_tmp));
1283 				llr[byte_idx] = (int8_t) llr_tmp;
1284 			}
1285 
1286 			m = m->next;
1287 		}
1288 	}
1289 }
1290 
1291 
1292 
1293 static int
1294 fill_queue_buffers(struct test_op_params *op_params,
1295 		struct rte_mempool *in_mp, struct rte_mempool *hard_out_mp,
1296 		struct rte_mempool *soft_out_mp,
1297 		struct rte_mempool *harq_in_mp, struct rte_mempool *harq_out_mp,
1298 		uint16_t queue_id,
1299 		const struct rte_bbdev_op_cap *capabilities,
1300 		uint16_t min_alignment, const int socket_id)
1301 {
1302 	int ret;
1303 	enum op_data_type type;
1304 	const uint16_t n = op_params->num_to_process;
1305 
1306 	struct rte_mempool *mbuf_pools[DATA_NUM_TYPES] = {
1307 		in_mp,
1308 		soft_out_mp,
1309 		hard_out_mp,
1310 		harq_in_mp,
1311 		harq_out_mp,
1312 	};
1313 
1314 	struct rte_bbdev_op_data **queue_ops[DATA_NUM_TYPES] = {
1315 		&op_params->q_bufs[socket_id][queue_id].inputs,
1316 		&op_params->q_bufs[socket_id][queue_id].soft_outputs,
1317 		&op_params->q_bufs[socket_id][queue_id].hard_outputs,
1318 		&op_params->q_bufs[socket_id][queue_id].harq_inputs,
1319 		&op_params->q_bufs[socket_id][queue_id].harq_outputs,
1320 	};
1321 
1322 	for (type = DATA_INPUT; type < DATA_NUM_TYPES; ++type) {
1323 		struct op_data_entries *ref_entries =
1324 				&test_vector.entries[type];
1325 		if (ref_entries->nb_segments == 0)
1326 			continue;
1327 
1328 		ret = allocate_buffers_on_socket(queue_ops[type],
1329 				n * sizeof(struct rte_bbdev_op_data),
1330 				socket_id);
1331 		TEST_ASSERT_SUCCESS(ret,
1332 				"Couldn't allocate memory for rte_bbdev_op_data structs");
1333 
1334 		ret = init_op_data_objs(*queue_ops[type], ref_entries,
1335 				mbuf_pools[type], n, type, min_alignment);
1336 		TEST_ASSERT_SUCCESS(ret,
1337 				"Couldn't init rte_bbdev_op_data structs");
1338 	}
1339 
1340 	if (test_vector.op_type == RTE_BBDEV_OP_TURBO_DEC)
1341 		limit_input_llr_val_range(*queue_ops[DATA_INPUT], n,
1342 			capabilities->cap.turbo_dec.max_llr_modulus);
1343 
1344 	if (test_vector.op_type == RTE_BBDEV_OP_LDPC_DEC) {
1345 		bool loopback = op_params->ref_dec_op->ldpc_dec.op_flags &
1346 				RTE_BBDEV_LDPC_INTERNAL_HARQ_MEMORY_LOOPBACK;
1347 		bool llr_comp = op_params->ref_dec_op->ldpc_dec.op_flags &
1348 				RTE_BBDEV_LDPC_LLR_COMPRESSION;
1349 		bool harq_comp = op_params->ref_dec_op->ldpc_dec.op_flags &
1350 				RTE_BBDEV_LDPC_HARQ_6BIT_COMPRESSION;
1351 		ldpc_llr_decimals = capabilities->cap.ldpc_dec.llr_decimals;
1352 		ldpc_llr_size = capabilities->cap.ldpc_dec.llr_size;
1353 		ldpc_cap_flags = capabilities->cap.ldpc_dec.capability_flags;
1354 		if (!loopback && !llr_comp)
1355 			ldpc_input_llr_scaling(*queue_ops[DATA_INPUT], n,
1356 					ldpc_llr_size, ldpc_llr_decimals);
1357 		if (!loopback && !harq_comp)
1358 			ldpc_input_llr_scaling(*queue_ops[DATA_HARQ_INPUT], n,
1359 					ldpc_llr_size, ldpc_llr_decimals);
1360 		if (!loopback)
1361 			ldpc_add_filler(*queue_ops[DATA_HARQ_INPUT], n,
1362 					op_params);
1363 	}
1364 
1365 	return 0;
1366 }
1367 
1368 static void
1369 free_buffers(struct active_device *ad, struct test_op_params *op_params)
1370 {
1371 	unsigned int i, j;
1372 
1373 	rte_mempool_free(ad->ops_mempool);
1374 	rte_mempool_free(ad->in_mbuf_pool);
1375 	rte_mempool_free(ad->hard_out_mbuf_pool);
1376 	rte_mempool_free(ad->soft_out_mbuf_pool);
1377 	rte_mempool_free(ad->harq_in_mbuf_pool);
1378 	rte_mempool_free(ad->harq_out_mbuf_pool);
1379 
1380 	for (i = 0; i < rte_lcore_count(); ++i) {
1381 		for (j = 0; j < RTE_MAX_NUMA_NODES; ++j) {
1382 			rte_free(op_params->q_bufs[j][i].inputs);
1383 			rte_free(op_params->q_bufs[j][i].hard_outputs);
1384 			rte_free(op_params->q_bufs[j][i].soft_outputs);
1385 			rte_free(op_params->q_bufs[j][i].harq_inputs);
1386 			rte_free(op_params->q_bufs[j][i].harq_outputs);
1387 		}
1388 	}
1389 }
1390 
1391 static void
1392 copy_reference_dec_op(struct rte_bbdev_dec_op **ops, unsigned int n,
1393 		unsigned int start_idx,
1394 		struct rte_bbdev_op_data *inputs,
1395 		struct rte_bbdev_op_data *hard_outputs,
1396 		struct rte_bbdev_op_data *soft_outputs,
1397 		struct rte_bbdev_dec_op *ref_op)
1398 {
1399 	unsigned int i;
1400 	struct rte_bbdev_op_turbo_dec *turbo_dec = &ref_op->turbo_dec;
1401 
1402 	for (i = 0; i < n; ++i) {
1403 		if (turbo_dec->code_block_mode == RTE_BBDEV_TRANSPORT_BLOCK) {
1404 			ops[i]->turbo_dec.tb_params.ea =
1405 					turbo_dec->tb_params.ea;
1406 			ops[i]->turbo_dec.tb_params.eb =
1407 					turbo_dec->tb_params.eb;
1408 			ops[i]->turbo_dec.tb_params.k_pos =
1409 					turbo_dec->tb_params.k_pos;
1410 			ops[i]->turbo_dec.tb_params.k_neg =
1411 					turbo_dec->tb_params.k_neg;
1412 			ops[i]->turbo_dec.tb_params.c =
1413 					turbo_dec->tb_params.c;
1414 			ops[i]->turbo_dec.tb_params.c_neg =
1415 					turbo_dec->tb_params.c_neg;
1416 			ops[i]->turbo_dec.tb_params.cab =
1417 					turbo_dec->tb_params.cab;
1418 			ops[i]->turbo_dec.tb_params.r =
1419 					turbo_dec->tb_params.r;
1420 		} else {
1421 			ops[i]->turbo_dec.cb_params.e = turbo_dec->cb_params.e;
1422 			ops[i]->turbo_dec.cb_params.k = turbo_dec->cb_params.k;
1423 		}
1424 
1425 		ops[i]->turbo_dec.ext_scale = turbo_dec->ext_scale;
1426 		ops[i]->turbo_dec.iter_max = turbo_dec->iter_max;
1427 		ops[i]->turbo_dec.iter_min = turbo_dec->iter_min;
1428 		ops[i]->turbo_dec.op_flags = turbo_dec->op_flags;
1429 		ops[i]->turbo_dec.rv_index = turbo_dec->rv_index;
1430 		ops[i]->turbo_dec.num_maps = turbo_dec->num_maps;
1431 		ops[i]->turbo_dec.code_block_mode = turbo_dec->code_block_mode;
1432 
1433 		ops[i]->turbo_dec.hard_output = hard_outputs[start_idx + i];
1434 		ops[i]->turbo_dec.input = inputs[start_idx + i];
1435 		if (soft_outputs != NULL)
1436 			ops[i]->turbo_dec.soft_output =
1437 				soft_outputs[start_idx + i];
1438 	}
1439 }
1440 
1441 static void
1442 copy_reference_enc_op(struct rte_bbdev_enc_op **ops, unsigned int n,
1443 		unsigned int start_idx,
1444 		struct rte_bbdev_op_data *inputs,
1445 		struct rte_bbdev_op_data *outputs,
1446 		struct rte_bbdev_enc_op *ref_op)
1447 {
1448 	unsigned int i;
1449 	struct rte_bbdev_op_turbo_enc *turbo_enc = &ref_op->turbo_enc;
1450 	for (i = 0; i < n; ++i) {
1451 		if (turbo_enc->code_block_mode == RTE_BBDEV_TRANSPORT_BLOCK) {
1452 			ops[i]->turbo_enc.tb_params.ea =
1453 					turbo_enc->tb_params.ea;
1454 			ops[i]->turbo_enc.tb_params.eb =
1455 					turbo_enc->tb_params.eb;
1456 			ops[i]->turbo_enc.tb_params.k_pos =
1457 					turbo_enc->tb_params.k_pos;
1458 			ops[i]->turbo_enc.tb_params.k_neg =
1459 					turbo_enc->tb_params.k_neg;
1460 			ops[i]->turbo_enc.tb_params.c =
1461 					turbo_enc->tb_params.c;
1462 			ops[i]->turbo_enc.tb_params.c_neg =
1463 					turbo_enc->tb_params.c_neg;
1464 			ops[i]->turbo_enc.tb_params.cab =
1465 					turbo_enc->tb_params.cab;
1466 			ops[i]->turbo_enc.tb_params.ncb_pos =
1467 					turbo_enc->tb_params.ncb_pos;
1468 			ops[i]->turbo_enc.tb_params.ncb_neg =
1469 					turbo_enc->tb_params.ncb_neg;
1470 			ops[i]->turbo_enc.tb_params.r = turbo_enc->tb_params.r;
1471 		} else {
1472 			ops[i]->turbo_enc.cb_params.e = turbo_enc->cb_params.e;
1473 			ops[i]->turbo_enc.cb_params.k = turbo_enc->cb_params.k;
1474 			ops[i]->turbo_enc.cb_params.ncb =
1475 					turbo_enc->cb_params.ncb;
1476 		}
1477 		ops[i]->turbo_enc.rv_index = turbo_enc->rv_index;
1478 		ops[i]->turbo_enc.op_flags = turbo_enc->op_flags;
1479 		ops[i]->turbo_enc.code_block_mode = turbo_enc->code_block_mode;
1480 
1481 		ops[i]->turbo_enc.output = outputs[start_idx + i];
1482 		ops[i]->turbo_enc.input = inputs[start_idx + i];
1483 	}
1484 }
1485 
1486 
1487 /* Returns a random number drawn from a normal distribution
1488  * with mean of 0 and variance of 1
1489  * Marsaglia algorithm
1490  */
1491 static double
1492 randn(int n)
1493 {
1494 	double S, Z, U1, U2, u, v, fac;
1495 
1496 	do {
1497 		U1 = (double)rand() / RAND_MAX;
1498 		U2 = (double)rand() / RAND_MAX;
1499 		u = 2. * U1 - 1.;
1500 		v = 2. * U2 - 1.;
1501 		S = u * u + v * v;
1502 	} while (S >= 1 || S == 0);
1503 	fac = sqrt(-2. * log(S) / S);
1504 	Z = (n % 2) ? u * fac : v * fac;
1505 	return Z;
1506 }
1507 
1508 static inline double
1509 maxstar(double A, double B)
1510 {
1511 	if (fabs(A - B) > 5)
1512 		return RTE_MAX(A, B);
1513 	else
1514 		return RTE_MAX(A, B) + log1p(exp(-fabs(A - B)));
1515 }
1516 
1517 /*
1518  * Generate Qm LLRS for Qm==8
1519  * Modulation, AWGN and LLR estimation from max log development
1520  */
1521 static void
1522 gen_qm8_llr(int8_t *llrs, uint32_t i, double N0, double llr_max)
1523 {
1524 	int qm = 8;
1525 	int qam = 256;
1526 	int m, k;
1527 	double I, Q, p0, p1, llr_, b[qm], log_syml_prob[qam];
1528 	/* 5.1.4 of TS38.211 */
1529 	const double symbols_I[256] = {
1530 			5, 5, 7, 7, 5, 5, 7, 7, 3, 3, 1, 1, 3, 3, 1, 1, 5,
1531 			5, 7, 7, 5, 5, 7, 7, 3, 3, 1, 1, 3, 3, 1, 1, 11,
1532 			11, 9, 9, 11, 11, 9, 9, 13, 13, 15, 15, 13, 13,
1533 			15, 15, 11, 11, 9, 9, 11, 11, 9, 9, 13, 13, 15,
1534 			15, 13, 13, 15, 15, 5, 5, 7, 7, 5, 5, 7, 7, 3, 3,
1535 			1, 1, 3, 3, 1, 1, 5, 5, 7, 7, 5, 5, 7, 7, 3, 3, 1,
1536 			1, 3, 3, 1, 1, 11, 11, 9, 9, 11, 11, 9, 9, 13, 13,
1537 			15, 15, 13, 13, 15, 15, 11, 11, 9, 9, 11, 11, 9, 9,
1538 			13, 13, 15, 15, 13, 13, 15, 15, -5, -5, -7, -7, -5,
1539 			-5, -7, -7, -3, -3, -1, -1, -3, -3, -1, -1, -5, -5,
1540 			-7, -7, -5, -5, -7, -7, -3, -3, -1, -1, -3, -3,
1541 			-1, -1, -11, -11, -9, -9, -11, -11, -9, -9, -13,
1542 			-13, -15, -15, -13, -13, -15, -15, -11, -11, -9,
1543 			-9, -11, -11, -9, -9, -13, -13, -15, -15, -13,
1544 			-13, -15, -15, -5, -5, -7, -7, -5, -5, -7, -7, -3,
1545 			-3, -1, -1, -3, -3, -1, -1, -5, -5, -7, -7, -5, -5,
1546 			-7, -7, -3, -3, -1, -1, -3, -3, -1, -1, -11, -11,
1547 			-9, -9, -11, -11, -9, -9, -13, -13, -15, -15, -13,
1548 			-13, -15, -15, -11, -11, -9, -9, -11, -11, -9, -9,
1549 			-13, -13, -15, -15, -13, -13, -15, -15};
1550 	const double symbols_Q[256] = {
1551 			5, 7, 5, 7, 3, 1, 3, 1, 5, 7, 5, 7, 3, 1, 3, 1, 11,
1552 			9, 11, 9, 13, 15, 13, 15, 11, 9, 11, 9, 13, 15, 13,
1553 			15, 5, 7, 5, 7, 3, 1, 3, 1, 5, 7, 5, 7, 3, 1, 3, 1,
1554 			11, 9, 11, 9, 13, 15, 13, 15, 11, 9, 11, 9, 13,
1555 			15, 13, 15, -5, -7, -5, -7, -3, -1, -3, -1, -5,
1556 			-7, -5, -7, -3, -1, -3, -1, -11, -9, -11, -9, -13,
1557 			-15, -13, -15, -11, -9, -11, -9, -13, -15, -13,
1558 			-15, -5, -7, -5, -7, -3, -1, -3, -1, -5, -7, -5,
1559 			-7, -3, -1, -3, -1, -11, -9, -11, -9, -13, -15,
1560 			-13, -15, -11, -9, -11, -9, -13, -15, -13, -15, 5,
1561 			7, 5, 7, 3, 1, 3, 1, 5, 7, 5, 7, 3, 1, 3, 1, 11,
1562 			9, 11, 9, 13, 15, 13, 15, 11, 9, 11, 9, 13, 15,
1563 			13, 15, 5, 7, 5, 7, 3, 1, 3, 1, 5, 7, 5, 7, 3, 1,
1564 			3, 1, 11, 9, 11, 9, 13, 15, 13, 15, 11, 9, 11, 9,
1565 			13, 15, 13, 15, -5, -7, -5, -7, -3, -1, -3, -1,
1566 			-5, -7, -5, -7, -3, -1, -3, -1, -11, -9, -11, -9,
1567 			-13, -15, -13, -15, -11, -9, -11, -9, -13, -15,
1568 			-13, -15, -5, -7, -5, -7, -3, -1, -3, -1, -5, -7,
1569 			-5, -7, -3, -1, -3, -1, -11, -9, -11, -9, -13, -15,
1570 			-13, -15, -11, -9, -11, -9, -13, -15, -13, -15};
1571 	/* Average constellation point energy */
1572 	N0 *= 170.0;
1573 	for (k = 0; k < qm; k++)
1574 		b[k] = llrs[qm * i + k] < 0 ? 1.0 : 0.0;
1575 	/* 5.1.4 of TS38.211 */
1576 	I = (1 - 2 * b[0]) * (8 - (1 - 2 * b[2]) *
1577 			(4 - (1 - 2 * b[4]) * (2 - (1 - 2 * b[6]))));
1578 	Q = (1 - 2 * b[1]) * (8 - (1 - 2 * b[3]) *
1579 			(4 - (1 - 2 * b[5]) * (2 - (1 - 2 * b[7]))));
1580 	/* AWGN channel */
1581 	I += sqrt(N0 / 2) * randn(0);
1582 	Q += sqrt(N0 / 2) * randn(1);
1583 	/*
1584 	 * Calculate the log of the probability that each of
1585 	 * the constellation points was transmitted
1586 	 */
1587 	for (m = 0; m < qam; m++)
1588 		log_syml_prob[m] = -(pow(I - symbols_I[m], 2.0)
1589 				+ pow(Q - symbols_Q[m], 2.0)) / N0;
1590 	/* Calculate an LLR for each of the k_64QAM bits in the set */
1591 	for (k = 0; k < qm; k++) {
1592 		p0 = -999999;
1593 		p1 = -999999;
1594 		/* For each constellation point */
1595 		for (m = 0; m < qam; m++) {
1596 			if ((m >> (qm - k - 1)) & 1)
1597 				p1 = maxstar(p1, log_syml_prob[m]);
1598 			else
1599 				p0 = maxstar(p0, log_syml_prob[m]);
1600 		}
1601 		/* Calculate the LLR */
1602 		llr_ = p0 - p1;
1603 		llr_ *= (1 << ldpc_llr_decimals);
1604 		llr_ = round(llr_);
1605 		if (llr_ > llr_max)
1606 			llr_ = llr_max;
1607 		if (llr_ < -llr_max)
1608 			llr_ = -llr_max;
1609 		llrs[qm * i + k] = (int8_t) llr_;
1610 	}
1611 }
1612 
1613 
1614 /*
1615  * Generate Qm LLRS for Qm==6
1616  * Modulation, AWGN and LLR estimation from max log development
1617  */
1618 static void
1619 gen_qm6_llr(int8_t *llrs, uint32_t i, double N0, double llr_max)
1620 {
1621 	int qm = 6;
1622 	int qam = 64;
1623 	int m, k;
1624 	double I, Q, p0, p1, llr_, b[qm], log_syml_prob[qam];
1625 	/* 5.1.4 of TS38.211 */
1626 	const double symbols_I[64] = {
1627 			3, 3, 1, 1, 3, 3, 1, 1, 5, 5, 7, 7, 5, 5, 7, 7,
1628 			3, 3, 1, 1, 3, 3, 1, 1, 5, 5, 7, 7, 5, 5, 7, 7,
1629 			-3, -3, -1, -1, -3, -3, -1, -1, -5, -5, -7, -7,
1630 			-5, -5, -7, -7, -3, -3, -1, -1, -3, -3, -1, -1,
1631 			-5, -5, -7, -7, -5, -5, -7, -7};
1632 	const double symbols_Q[64] = {
1633 			3, 1, 3, 1, 5, 7, 5, 7, 3, 1, 3, 1, 5, 7, 5, 7,
1634 			-3, -1, -3, -1, -5, -7, -5, -7, -3, -1, -3, -1,
1635 			-5, -7, -5, -7, 3, 1, 3, 1, 5, 7, 5, 7, 3, 1, 3, 1,
1636 			5, 7, 5, 7, -3, -1, -3, -1, -5, -7, -5, -7,
1637 			-3, -1, -3, -1, -5, -7, -5, -7};
1638 	/* Average constellation point energy */
1639 	N0 *= 42.0;
1640 	for (k = 0; k < qm; k++)
1641 		b[k] = llrs[qm * i + k] < 0 ? 1.0 : 0.0;
1642 	/* 5.1.4 of TS38.211 */
1643 	I = (1 - 2 * b[0])*(4 - (1 - 2 * b[2]) * (2 - (1 - 2 * b[4])));
1644 	Q = (1 - 2 * b[1])*(4 - (1 - 2 * b[3]) * (2 - (1 - 2 * b[5])));
1645 	/* AWGN channel */
1646 	I += sqrt(N0 / 2) * randn(0);
1647 	Q += sqrt(N0 / 2) * randn(1);
1648 	/*
1649 	 * Calculate the log of the probability that each of
1650 	 * the constellation points was transmitted
1651 	 */
1652 	for (m = 0; m < qam; m++)
1653 		log_syml_prob[m] = -(pow(I - symbols_I[m], 2.0)
1654 				+ pow(Q - symbols_Q[m], 2.0)) / N0;
1655 	/* Calculate an LLR for each of the k_64QAM bits in the set */
1656 	for (k = 0; k < qm; k++) {
1657 		p0 = -999999;
1658 		p1 = -999999;
1659 		/* For each constellation point */
1660 		for (m = 0; m < qam; m++) {
1661 			if ((m >> (qm - k - 1)) & 1)
1662 				p1 = maxstar(p1, log_syml_prob[m]);
1663 			else
1664 				p0 = maxstar(p0, log_syml_prob[m]);
1665 		}
1666 		/* Calculate the LLR */
1667 		llr_ = p0 - p1;
1668 		llr_ *= (1 << ldpc_llr_decimals);
1669 		llr_ = round(llr_);
1670 		if (llr_ > llr_max)
1671 			llr_ = llr_max;
1672 		if (llr_ < -llr_max)
1673 			llr_ = -llr_max;
1674 		llrs[qm * i + k] = (int8_t) llr_;
1675 	}
1676 }
1677 
1678 /*
1679  * Generate Qm LLRS for Qm==4
1680  * Modulation, AWGN and LLR estimation from max log development
1681  */
1682 static void
1683 gen_qm4_llr(int8_t *llrs, uint32_t i, double N0, double llr_max)
1684 {
1685 	int qm = 4;
1686 	int qam = 16;
1687 	int m, k;
1688 	double I, Q, p0, p1, llr_, b[qm], log_syml_prob[qam];
1689 	/* 5.1.4 of TS38.211 */
1690 	const double symbols_I[16] = {1, 1, 3, 3, 1, 1, 3, 3,
1691 			-1, -1, -3, -3, -1, -1, -3, -3};
1692 	const double symbols_Q[16] = {1, 3, 1, 3, -1, -3, -1, -3,
1693 			1, 3, 1, 3, -1, -3, -1, -3};
1694 	/* Average constellation point energy */
1695 	N0 *= 10.0;
1696 	for (k = 0; k < qm; k++)
1697 		b[k] = llrs[qm * i + k] < 0 ? 1.0 : 0.0;
1698 	/* 5.1.4 of TS38.211 */
1699 	I = (1 - 2 * b[0]) * (2 - (1 - 2 * b[2]));
1700 	Q = (1 - 2 * b[1]) * (2 - (1 - 2 * b[3]));
1701 	/* AWGN channel */
1702 	I += sqrt(N0 / 2) * randn(0);
1703 	Q += sqrt(N0 / 2) * randn(1);
1704 	/*
1705 	 * Calculate the log of the probability that each of
1706 	 * the constellation points was transmitted
1707 	 */
1708 	for (m = 0; m < qam; m++)
1709 		log_syml_prob[m] = -(pow(I - symbols_I[m], 2.0)
1710 				+ pow(Q - symbols_Q[m], 2.0)) / N0;
1711 	/* Calculate an LLR for each of the k_64QAM bits in the set */
1712 	for (k = 0; k < qm; k++) {
1713 		p0 = -999999;
1714 		p1 = -999999;
1715 		/* For each constellation point */
1716 		for (m = 0; m < qam; m++) {
1717 			if ((m >> (qm - k - 1)) & 1)
1718 				p1 = maxstar(p1, log_syml_prob[m]);
1719 			else
1720 				p0 = maxstar(p0, log_syml_prob[m]);
1721 		}
1722 		/* Calculate the LLR */
1723 		llr_ = p0 - p1;
1724 		llr_ *= (1 << ldpc_llr_decimals);
1725 		llr_ = round(llr_);
1726 		if (llr_ > llr_max)
1727 			llr_ = llr_max;
1728 		if (llr_ < -llr_max)
1729 			llr_ = -llr_max;
1730 		llrs[qm * i + k] = (int8_t) llr_;
1731 	}
1732 }
1733 
1734 static void
1735 gen_qm2_llr(int8_t *llrs, uint32_t j, double N0, double llr_max)
1736 {
1737 	double b, b1, n;
1738 	double coeff = 2.0 * sqrt(N0);
1739 
1740 	/* Ignore in vectors rare quasi null LLRs not to be saturated */
1741 	if (llrs[j] < 8 && llrs[j] > -8)
1742 		return;
1743 
1744 	/* Note don't change sign here */
1745 	n = randn(j % 2);
1746 	b1 = ((llrs[j] > 0 ? 2.0 : -2.0)
1747 			+ coeff * n) / N0;
1748 	b = b1 * (1 << ldpc_llr_decimals);
1749 	b = round(b);
1750 	if (b > llr_max)
1751 		b = llr_max;
1752 	if (b < -llr_max)
1753 		b = -llr_max;
1754 	llrs[j] = (int8_t) b;
1755 }
1756 
1757 /* Generate LLR for a given SNR */
1758 static void
1759 generate_llr_input(uint16_t n, struct rte_bbdev_op_data *inputs,
1760 		struct rte_bbdev_dec_op *ref_op)
1761 {
1762 	struct rte_mbuf *m;
1763 	uint16_t qm;
1764 	uint32_t i, j, e, range;
1765 	double N0, llr_max;
1766 
1767 	e = ref_op->ldpc_dec.cb_params.e;
1768 	qm = ref_op->ldpc_dec.q_m;
1769 	llr_max = (1 << (ldpc_llr_size - 1)) - 1;
1770 	range = e / qm;
1771 	N0 = 1.0 / pow(10.0, get_snr() / 10.0);
1772 
1773 	for (i = 0; i < n; ++i) {
1774 		m = inputs[i].data;
1775 		int8_t *llrs = rte_pktmbuf_mtod_offset(m, int8_t *, 0);
1776 		if (qm == 8) {
1777 			for (j = 0; j < range; ++j)
1778 				gen_qm8_llr(llrs, j, N0, llr_max);
1779 		} else if (qm == 6) {
1780 			for (j = 0; j < range; ++j)
1781 				gen_qm6_llr(llrs, j, N0, llr_max);
1782 		} else if (qm == 4) {
1783 			for (j = 0; j < range; ++j)
1784 				gen_qm4_llr(llrs, j, N0, llr_max);
1785 		} else {
1786 			for (j = 0; j < e; ++j)
1787 				gen_qm2_llr(llrs, j, N0, llr_max);
1788 		}
1789 	}
1790 }
1791 
1792 static void
1793 copy_reference_ldpc_dec_op(struct rte_bbdev_dec_op **ops, unsigned int n,
1794 		unsigned int start_idx,
1795 		struct rte_bbdev_op_data *inputs,
1796 		struct rte_bbdev_op_data *hard_outputs,
1797 		struct rte_bbdev_op_data *soft_outputs,
1798 		struct rte_bbdev_op_data *harq_inputs,
1799 		struct rte_bbdev_op_data *harq_outputs,
1800 		struct rte_bbdev_dec_op *ref_op)
1801 {
1802 	unsigned int i;
1803 	struct rte_bbdev_op_ldpc_dec *ldpc_dec = &ref_op->ldpc_dec;
1804 
1805 	for (i = 0; i < n; ++i) {
1806 		if (ldpc_dec->code_block_mode == RTE_BBDEV_TRANSPORT_BLOCK) {
1807 			ops[i]->ldpc_dec.tb_params.ea =
1808 					ldpc_dec->tb_params.ea;
1809 			ops[i]->ldpc_dec.tb_params.eb =
1810 					ldpc_dec->tb_params.eb;
1811 			ops[i]->ldpc_dec.tb_params.c =
1812 					ldpc_dec->tb_params.c;
1813 			ops[i]->ldpc_dec.tb_params.cab =
1814 					ldpc_dec->tb_params.cab;
1815 			ops[i]->ldpc_dec.tb_params.r =
1816 					ldpc_dec->tb_params.r;
1817 		} else {
1818 			ops[i]->ldpc_dec.cb_params.e = ldpc_dec->cb_params.e;
1819 		}
1820 
1821 		ops[i]->ldpc_dec.basegraph = ldpc_dec->basegraph;
1822 		ops[i]->ldpc_dec.z_c = ldpc_dec->z_c;
1823 		ops[i]->ldpc_dec.q_m = ldpc_dec->q_m;
1824 		ops[i]->ldpc_dec.n_filler = ldpc_dec->n_filler;
1825 		ops[i]->ldpc_dec.n_cb = ldpc_dec->n_cb;
1826 		ops[i]->ldpc_dec.iter_max = ldpc_dec->iter_max;
1827 		ops[i]->ldpc_dec.rv_index = ldpc_dec->rv_index;
1828 		ops[i]->ldpc_dec.op_flags = ldpc_dec->op_flags;
1829 		ops[i]->ldpc_dec.code_block_mode = ldpc_dec->code_block_mode;
1830 
1831 		if (hard_outputs != NULL)
1832 			ops[i]->ldpc_dec.hard_output =
1833 					hard_outputs[start_idx + i];
1834 		if (inputs != NULL)
1835 			ops[i]->ldpc_dec.input =
1836 					inputs[start_idx + i];
1837 		if (soft_outputs != NULL)
1838 			ops[i]->ldpc_dec.soft_output =
1839 					soft_outputs[start_idx + i];
1840 		if (harq_inputs != NULL)
1841 			ops[i]->ldpc_dec.harq_combined_input =
1842 					harq_inputs[start_idx + i];
1843 		if (harq_outputs != NULL)
1844 			ops[i]->ldpc_dec.harq_combined_output =
1845 					harq_outputs[start_idx + i];
1846 	}
1847 }
1848 
1849 
1850 static void
1851 copy_reference_ldpc_enc_op(struct rte_bbdev_enc_op **ops, unsigned int n,
1852 		unsigned int start_idx,
1853 		struct rte_bbdev_op_data *inputs,
1854 		struct rte_bbdev_op_data *outputs,
1855 		struct rte_bbdev_enc_op *ref_op)
1856 {
1857 	unsigned int i;
1858 	struct rte_bbdev_op_ldpc_enc *ldpc_enc = &ref_op->ldpc_enc;
1859 	for (i = 0; i < n; ++i) {
1860 		if (ldpc_enc->code_block_mode == RTE_BBDEV_TRANSPORT_BLOCK) {
1861 			ops[i]->ldpc_enc.tb_params.ea = ldpc_enc->tb_params.ea;
1862 			ops[i]->ldpc_enc.tb_params.eb = ldpc_enc->tb_params.eb;
1863 			ops[i]->ldpc_enc.tb_params.cab =
1864 					ldpc_enc->tb_params.cab;
1865 			ops[i]->ldpc_enc.tb_params.c = ldpc_enc->tb_params.c;
1866 			ops[i]->ldpc_enc.tb_params.r = ldpc_enc->tb_params.r;
1867 		} else {
1868 			ops[i]->ldpc_enc.cb_params.e = ldpc_enc->cb_params.e;
1869 		}
1870 		ops[i]->ldpc_enc.basegraph = ldpc_enc->basegraph;
1871 		ops[i]->ldpc_enc.z_c = ldpc_enc->z_c;
1872 		ops[i]->ldpc_enc.q_m = ldpc_enc->q_m;
1873 		ops[i]->ldpc_enc.n_filler = ldpc_enc->n_filler;
1874 		ops[i]->ldpc_enc.n_cb = ldpc_enc->n_cb;
1875 		ops[i]->ldpc_enc.rv_index = ldpc_enc->rv_index;
1876 		ops[i]->ldpc_enc.op_flags = ldpc_enc->op_flags;
1877 		ops[i]->ldpc_enc.code_block_mode = ldpc_enc->code_block_mode;
1878 		ops[i]->ldpc_enc.output = outputs[start_idx + i];
1879 		ops[i]->ldpc_enc.input = inputs[start_idx + i];
1880 	}
1881 }
1882 
1883 static void
1884 copy_reference_fft_op(struct rte_bbdev_fft_op **ops, unsigned int n,
1885 		unsigned int start_idx, struct rte_bbdev_op_data *inputs,
1886 		struct rte_bbdev_op_data *outputs, struct rte_bbdev_op_data *pwrouts,
1887 		struct rte_bbdev_fft_op *ref_op)
1888 {
1889 	unsigned int i, j;
1890 	struct rte_bbdev_op_fft *fft = &ref_op->fft;
1891 	for (i = 0; i < n; i++) {
1892 		ops[i]->fft.input_sequence_size = fft->input_sequence_size;
1893 		ops[i]->fft.input_leading_padding = fft->input_leading_padding;
1894 		ops[i]->fft.output_sequence_size = fft->output_sequence_size;
1895 		ops[i]->fft.output_leading_depadding =
1896 				fft->output_leading_depadding;
1897 		for (j = 0; j < RTE_BBDEV_MAX_CS_2; j++)
1898 			ops[i]->fft.window_index[j] = fft->window_index[j];
1899 		ops[i]->fft.cs_bitmap = fft->cs_bitmap;
1900 		ops[i]->fft.num_antennas_log2 = fft->num_antennas_log2;
1901 		ops[i]->fft.idft_log2 = fft->idft_log2;
1902 		ops[i]->fft.dft_log2 = fft->dft_log2;
1903 		ops[i]->fft.cs_time_adjustment = fft->cs_time_adjustment;
1904 		ops[i]->fft.idft_shift = fft->idft_shift;
1905 		ops[i]->fft.dft_shift = fft->dft_shift;
1906 		ops[i]->fft.ncs_reciprocal = fft->ncs_reciprocal;
1907 		ops[i]->fft.power_shift = fft->power_shift;
1908 		ops[i]->fft.fp16_exp_adjust = fft->fp16_exp_adjust;
1909 		ops[i]->fft.base_output = outputs[start_idx + i];
1910 		ops[i]->fft.base_input = inputs[start_idx + i];
1911 		if (pwrouts != NULL)
1912 			ops[i]->fft.power_meas_output = pwrouts[start_idx + i];
1913 		ops[i]->fft.op_flags = fft->op_flags;
1914 	}
1915 }
1916 
1917 static int
1918 check_dec_status_and_ordering(struct rte_bbdev_dec_op *op,
1919 		unsigned int order_idx, const int expected_status)
1920 {
1921 	int status = op->status;
1922 	/* ignore parity mismatch false alarms for long iterations */
1923 	if (get_iter_max() >= 10) {
1924 		if (!(expected_status & (1 << RTE_BBDEV_SYNDROME_ERROR)) &&
1925 				(status & (1 << RTE_BBDEV_SYNDROME_ERROR))) {
1926 			printf("WARNING: Ignore Syndrome Check mismatch\n");
1927 			status -= (1 << RTE_BBDEV_SYNDROME_ERROR);
1928 		}
1929 		if ((expected_status & (1 << RTE_BBDEV_SYNDROME_ERROR)) &&
1930 				!(status & (1 << RTE_BBDEV_SYNDROME_ERROR))) {
1931 			printf("WARNING: Ignore Syndrome Check mismatch\n");
1932 			status += (1 << RTE_BBDEV_SYNDROME_ERROR);
1933 		}
1934 	}
1935 
1936 	TEST_ASSERT(status == expected_status,
1937 			"op_status (%d) != expected_status (%d)",
1938 			op->status, expected_status);
1939 
1940 	TEST_ASSERT((void *)(uintptr_t)order_idx == op->opaque_data,
1941 			"Ordering error, expected %p, got %p",
1942 			(void *)(uintptr_t)order_idx, op->opaque_data);
1943 
1944 	return TEST_SUCCESS;
1945 }
1946 
1947 static int
1948 check_enc_status_and_ordering(struct rte_bbdev_enc_op *op,
1949 		unsigned int order_idx, const int expected_status)
1950 {
1951 	TEST_ASSERT(op->status == expected_status,
1952 			"op_status (%d) != expected_status (%d)",
1953 			op->status, expected_status);
1954 
1955 	if (op->opaque_data != (void *)(uintptr_t)INVALID_OPAQUE)
1956 		TEST_ASSERT((void *)(uintptr_t)order_idx == op->opaque_data,
1957 				"Ordering error, expected %p, got %p",
1958 				(void *)(uintptr_t)order_idx, op->opaque_data);
1959 
1960 	return TEST_SUCCESS;
1961 }
1962 
1963 static int
1964 check_fft_status_and_ordering(struct rte_bbdev_fft_op *op,
1965 		unsigned int order_idx, const int expected_status)
1966 {
1967 	TEST_ASSERT(op->status == expected_status,
1968 			"op_status (%d) != expected_status (%d)",
1969 			op->status, expected_status);
1970 
1971 	TEST_ASSERT((void *)(uintptr_t)order_idx == op->opaque_data,
1972 			"Ordering error, expected %p, got %p",
1973 			(void *)(uintptr_t)order_idx, op->opaque_data);
1974 
1975 	return TEST_SUCCESS;
1976 }
1977 
1978 static inline int
1979 validate_op_chain(struct rte_bbdev_op_data *op,
1980 		struct op_data_entries *orig_op)
1981 {
1982 	uint8_t i;
1983 	struct rte_mbuf *m = op->data;
1984 	uint8_t nb_dst_segments = orig_op->nb_segments;
1985 	uint32_t total_data_size = 0;
1986 
1987 	TEST_ASSERT(nb_dst_segments == m->nb_segs,
1988 			"Number of segments differ in original (%u) and filled (%u) op",
1989 			nb_dst_segments, m->nb_segs);
1990 
1991 	/* Validate each mbuf segment length */
1992 	for (i = 0; i < nb_dst_segments; ++i) {
1993 		/* Apply offset to the first mbuf segment */
1994 		uint16_t offset = (i == 0) ? op->offset : 0;
1995 		uint16_t data_len = rte_pktmbuf_data_len(m) - offset;
1996 		total_data_size += orig_op->segments[i].length;
1997 
1998 		TEST_ASSERT(orig_op->segments[i].length == data_len,
1999 				"Length of segment differ in original (%u) and filled (%u) op",
2000 				orig_op->segments[i].length, data_len);
2001 		TEST_ASSERT_BUFFERS_ARE_EQUAL(orig_op->segments[i].addr,
2002 				rte_pktmbuf_mtod_offset(m, uint32_t *, offset),
2003 				data_len,
2004 				"Output buffers (CB=%u) are not equal", i);
2005 		m = m->next;
2006 	}
2007 
2008 	/* Validate total mbuf pkt length */
2009 	uint32_t pkt_len = rte_pktmbuf_pkt_len(op->data) - op->offset;
2010 	TEST_ASSERT(total_data_size == pkt_len,
2011 			"Length of data differ in original (%u) and filled (%u) op",
2012 			total_data_size, pkt_len);
2013 
2014 	return TEST_SUCCESS;
2015 }
2016 
2017 /*
2018  * Compute K0 for a given configuration for HARQ output length computation
2019  * As per definition in 3GPP 38.212 Table 5.4.2.1-2
2020  */
2021 static inline uint16_t
2022 get_k0(uint16_t n_cb, uint16_t z_c, uint8_t bg, uint8_t rv_index)
2023 {
2024 	if (rv_index == 0)
2025 		return 0;
2026 	uint16_t n = (bg == 1 ? N_ZC_1 : N_ZC_2) * z_c;
2027 	if (n_cb == n) {
2028 		if (rv_index == 1)
2029 			return (bg == 1 ? K0_1_1 : K0_1_2) * z_c;
2030 		else if (rv_index == 2)
2031 			return (bg == 1 ? K0_2_1 : K0_2_2) * z_c;
2032 		else
2033 			return (bg == 1 ? K0_3_1 : K0_3_2) * z_c;
2034 	}
2035 	/* LBRM case - includes a division by N */
2036 	if (rv_index == 1)
2037 		return (((bg == 1 ? K0_1_1 : K0_1_2) * n_cb)
2038 				/ n) * z_c;
2039 	else if (rv_index == 2)
2040 		return (((bg == 1 ? K0_2_1 : K0_2_2) * n_cb)
2041 				/ n) * z_c;
2042 	else
2043 		return (((bg == 1 ? K0_3_1 : K0_3_2) * n_cb)
2044 				/ n) * z_c;
2045 }
2046 
2047 /* HARQ output length including the Filler bits */
2048 static inline uint16_t
2049 compute_harq_len(struct rte_bbdev_op_ldpc_dec *ops_ld)
2050 {
2051 	uint16_t k0 = 0;
2052 	uint8_t max_rv = (ops_ld->rv_index == 1) ? 3 : ops_ld->rv_index;
2053 	k0 = get_k0(ops_ld->n_cb, ops_ld->z_c, ops_ld->basegraph, max_rv);
2054 	/* Compute RM out size and number of rows */
2055 	uint16_t parity_offset = (ops_ld->basegraph == 1 ? 20 : 8)
2056 			* ops_ld->z_c - ops_ld->n_filler;
2057 	uint16_t deRmOutSize = RTE_MIN(
2058 			k0 + ops_ld->cb_params.e +
2059 			((k0 > parity_offset) ?
2060 					0 : ops_ld->n_filler),
2061 					ops_ld->n_cb);
2062 	uint16_t numRows = ((deRmOutSize + ops_ld->z_c - 1)
2063 			/ ops_ld->z_c);
2064 	uint16_t harq_output_len = numRows * ops_ld->z_c;
2065 	return harq_output_len;
2066 }
2067 
2068 static inline int
2069 validate_op_harq_chain(struct rte_bbdev_op_data *op,
2070 		struct op_data_entries *orig_op,
2071 		struct rte_bbdev_op_ldpc_dec *ops_ld)
2072 {
2073 	uint8_t i;
2074 	uint32_t j, jj, k;
2075 	struct rte_mbuf *m = op->data;
2076 	uint8_t nb_dst_segments = orig_op->nb_segments;
2077 	uint32_t total_data_size = 0;
2078 	int8_t *harq_orig, *harq_out, abs_harq_origin;
2079 	uint32_t byte_error = 0, cum_error = 0, error;
2080 	int16_t llr_max = (1 << (ldpc_llr_size - ldpc_llr_decimals)) - 1;
2081 	int16_t llr_max_pre_scaling = (1 << (ldpc_llr_size - 1)) - 1;
2082 	uint16_t parity_offset;
2083 
2084 	TEST_ASSERT(nb_dst_segments == m->nb_segs,
2085 			"Number of segments differ in original (%u) and filled (%u) op",
2086 			nb_dst_segments, m->nb_segs);
2087 
2088 	/* Validate each mbuf segment length */
2089 	for (i = 0; i < nb_dst_segments; ++i) {
2090 		/* Apply offset to the first mbuf segment */
2091 		uint16_t offset = (i == 0) ? op->offset : 0;
2092 		uint16_t data_len = rte_pktmbuf_data_len(m) - offset;
2093 		total_data_size += orig_op->segments[i].length;
2094 
2095 		TEST_ASSERT(orig_op->segments[i].length <
2096 				(uint32_t)(data_len + 64),
2097 				"Length of segment differ in original (%u) and filled (%u) op",
2098 				orig_op->segments[i].length, data_len);
2099 		harq_orig = (int8_t *) orig_op->segments[i].addr;
2100 		harq_out = rte_pktmbuf_mtod_offset(m, int8_t *, offset);
2101 
2102 		if (!(ldpc_cap_flags &
2103 				RTE_BBDEV_LDPC_INTERNAL_HARQ_MEMORY_FILLERS
2104 				) || (ops_ld->op_flags &
2105 				RTE_BBDEV_LDPC_INTERNAL_HARQ_MEMORY_LOOPBACK)) {
2106 			data_len -= ops_ld->z_c;
2107 			parity_offset = data_len;
2108 		} else {
2109 			/* Compute RM out size and number of rows */
2110 			parity_offset = (ops_ld->basegraph == 1 ? 20 : 8)
2111 					* ops_ld->z_c - ops_ld->n_filler;
2112 			uint16_t deRmOutSize = compute_harq_len(ops_ld) -
2113 					ops_ld->n_filler;
2114 			if (data_len > deRmOutSize)
2115 				data_len = deRmOutSize;
2116 			if (data_len > orig_op->segments[i].length)
2117 				data_len = orig_op->segments[i].length;
2118 		}
2119 		/*
2120 		 * HARQ output can have minor differences
2121 		 * due to integer representation and related scaling
2122 		 */
2123 		for (j = 0, jj = 0; j < data_len; j++, jj++) {
2124 			if (j == parity_offset) {
2125 				/* Special Handling of the filler bits */
2126 				for (k = 0; k < ops_ld->n_filler; k++) {
2127 					if (harq_out[jj] !=
2128 							llr_max_pre_scaling) {
2129 						printf("HARQ Filler issue %d: %d %d\n",
2130 							jj, harq_out[jj],
2131 							llr_max);
2132 						byte_error++;
2133 					}
2134 					jj++;
2135 				}
2136 			}
2137 			if (!(ops_ld->op_flags &
2138 				RTE_BBDEV_LDPC_INTERNAL_HARQ_MEMORY_LOOPBACK)) {
2139 				if (ldpc_llr_decimals > 1)
2140 					harq_out[jj] = (harq_out[jj] + 1)
2141 						>> (ldpc_llr_decimals - 1);
2142 				/* Saturated to S7 */
2143 				if (harq_orig[j] > llr_max)
2144 					harq_orig[j] = llr_max;
2145 				if (harq_orig[j] < -llr_max)
2146 					harq_orig[j] = -llr_max;
2147 			}
2148 			if (harq_orig[j] != harq_out[jj]) {
2149 				error = (harq_orig[j] > harq_out[jj]) ?
2150 						harq_orig[j] - harq_out[jj] :
2151 						harq_out[jj] - harq_orig[j];
2152 				abs_harq_origin = harq_orig[j] > 0 ?
2153 							harq_orig[j] :
2154 							-harq_orig[j];
2155 				/* Residual quantization error */
2156 				if ((error > 8 && (abs_harq_origin <
2157 						(llr_max - 16))) ||
2158 						(error > 16)) {
2159 					printf("HARQ mismatch %d: exp %d act %d => %d\n",
2160 							j, harq_orig[j],
2161 							harq_out[jj], error);
2162 					byte_error++;
2163 					cum_error += error;
2164 				}
2165 			}
2166 		}
2167 		m = m->next;
2168 	}
2169 
2170 	if (byte_error)
2171 		TEST_ASSERT(byte_error <= 1,
2172 				"HARQ output mismatch (%d) %d",
2173 				byte_error, cum_error);
2174 
2175 	/* Validate total mbuf pkt length */
2176 	uint32_t pkt_len = rte_pktmbuf_pkt_len(op->data) - op->offset;
2177 	TEST_ASSERT(total_data_size < pkt_len + 64,
2178 			"Length of data differ in original (%u) and filled (%u) op",
2179 			total_data_size, pkt_len);
2180 
2181 	return TEST_SUCCESS;
2182 }
2183 
2184 
2185 static inline int
2186 validate_op_so_chain(struct rte_bbdev_op_data *op,
2187 		struct op_data_entries *orig_op)
2188 {
2189 	struct rte_mbuf *m = op->data;
2190 	uint8_t i, nb_dst_segments = orig_op->nb_segments;
2191 	uint32_t j, jj;
2192 	int8_t *so_orig, *so_out;
2193 	uint32_t byte_error = 0, error, margin_error = 0;
2194 
2195 	TEST_ASSERT(nb_dst_segments == m->nb_segs,
2196 			"Number of segments differ in original (%u) and filled (%u) op",
2197 			nb_dst_segments, m->nb_segs);
2198 
2199 	/* Validate each mbuf segment length. */
2200 	for (i = 0; i < nb_dst_segments; ++i) {
2201 		/* Apply offset to the first mbuf segment. */
2202 		uint16_t offset = (i == 0) ? op->offset : 0;
2203 		uint16_t data_len = rte_pktmbuf_data_len(m) - offset;
2204 
2205 		TEST_ASSERT(orig_op->segments[i].length == data_len,
2206 				"Length of segment differ in original (%u) and filled (%u) op",
2207 				orig_op->segments[i].length, data_len);
2208 		so_orig = (int8_t *) orig_op->segments[i].addr;
2209 		so_out = rte_pktmbuf_mtod_offset(m, int8_t *, offset);
2210 		margin_error += data_len / 8; /* Allow for few % errors. */
2211 
2212 		/* SO output can have minor differences due to algorithm variations. */
2213 		for (j = 0, jj = 0; j < data_len; j++, jj++) {
2214 			if (so_orig[j] != so_out[jj]) {
2215 				error = (so_orig[j] > so_out[jj]) ? so_orig[j] - so_out[jj] :
2216 						so_out[jj] - so_orig[j];
2217 				/* Residual quantization error. */
2218 				if (error > 32) {
2219 					printf("Warning: Soft mismatch %d: exp %d act %d => %d\n",
2220 							j, so_orig[j], so_out[jj], error);
2221 					byte_error++;
2222 				}
2223 			}
2224 		}
2225 		m = m->next;
2226 	}
2227 
2228 	if (byte_error > margin_error)
2229 		TEST_ASSERT(byte_error <= 1, "Soft output mismatch (%d) %d",
2230 				byte_error, margin_error);
2231 
2232 	return TEST_SUCCESS;
2233 }
2234 
2235 static int
2236 validate_dec_op(struct rte_bbdev_dec_op **ops, const uint16_t n,
2237 		struct rte_bbdev_dec_op *ref_op, const int vector_mask)
2238 {
2239 	unsigned int i;
2240 	int ret;
2241 	struct op_data_entries *hard_data_orig =
2242 			&test_vector.entries[DATA_HARD_OUTPUT];
2243 	struct op_data_entries *soft_data_orig =
2244 			&test_vector.entries[DATA_SOFT_OUTPUT];
2245 	struct rte_bbdev_op_turbo_dec *ops_td;
2246 	struct rte_bbdev_op_data *hard_output;
2247 	struct rte_bbdev_op_data *soft_output;
2248 	struct rte_bbdev_op_turbo_dec *ref_td = &ref_op->turbo_dec;
2249 
2250 	for (i = 0; i < n; ++i) {
2251 		ops_td = &ops[i]->turbo_dec;
2252 		hard_output = &ops_td->hard_output;
2253 		soft_output = &ops_td->soft_output;
2254 
2255 		if (vector_mask & TEST_BBDEV_VF_EXPECTED_ITER_COUNT)
2256 			TEST_ASSERT(ops_td->iter_count <= ref_td->iter_count,
2257 					"Returned iter_count (%d) > expected iter_count (%d)",
2258 					ops_td->iter_count, ref_td->iter_count);
2259 		ret = check_dec_status_and_ordering(ops[i], i, ref_op->status);
2260 		TEST_ASSERT_SUCCESS(ret,
2261 				"Checking status and ordering for decoder failed");
2262 
2263 		TEST_ASSERT_SUCCESS(validate_op_chain(hard_output,
2264 				hard_data_orig),
2265 				"Hard output buffers (CB=%u) are not equal",
2266 				i);
2267 
2268 		if (ref_op->turbo_dec.op_flags & RTE_BBDEV_TURBO_SOFT_OUTPUT)
2269 			TEST_ASSERT_SUCCESS(validate_op_so_chain(soft_output,
2270 					soft_data_orig),
2271 					"Soft output buffers (CB=%u) are not equal",
2272 					i);
2273 	}
2274 
2275 	return TEST_SUCCESS;
2276 }
2277 
2278 /* Check Number of code blocks errors */
2279 static int
2280 validate_ldpc_bler(struct rte_bbdev_dec_op **ops, const uint16_t n)
2281 {
2282 	unsigned int i;
2283 	struct op_data_entries *hard_data_orig =
2284 			&test_vector.entries[DATA_HARD_OUTPUT];
2285 	struct rte_bbdev_op_ldpc_dec *ops_td;
2286 	struct rte_bbdev_op_data *hard_output;
2287 	int errors = 0;
2288 	struct rte_mbuf *m;
2289 
2290 	for (i = 0; i < n; ++i) {
2291 		ops_td = &ops[i]->ldpc_dec;
2292 		hard_output = &ops_td->hard_output;
2293 		m = hard_output->data;
2294 		if (memcmp(rte_pktmbuf_mtod_offset(m, uint32_t *, 0),
2295 				hard_data_orig->segments[0].addr,
2296 				hard_data_orig->segments[0].length))
2297 			errors++;
2298 	}
2299 	return errors;
2300 }
2301 
2302 static int
2303 validate_ldpc_dec_op(struct rte_bbdev_dec_op **ops, const uint16_t n,
2304 		struct rte_bbdev_dec_op *ref_op, const int vector_mask)
2305 {
2306 	unsigned int i;
2307 	int ret;
2308 	struct op_data_entries *hard_data_orig =
2309 			&test_vector.entries[DATA_HARD_OUTPUT];
2310 	struct op_data_entries *soft_data_orig =
2311 			&test_vector.entries[DATA_SOFT_OUTPUT];
2312 	struct op_data_entries *harq_data_orig =
2313 				&test_vector.entries[DATA_HARQ_OUTPUT];
2314 	struct rte_bbdev_op_ldpc_dec *ops_td;
2315 	struct rte_bbdev_op_data *hard_output;
2316 	struct rte_bbdev_op_data *harq_output;
2317 	struct rte_bbdev_op_data *soft_output;
2318 	struct rte_bbdev_op_ldpc_dec *ref_td = &ref_op->ldpc_dec;
2319 
2320 	for (i = 0; i < n; ++i) {
2321 		ops_td = &ops[i]->ldpc_dec;
2322 		hard_output = &ops_td->hard_output;
2323 		harq_output = &ops_td->harq_combined_output;
2324 		soft_output = &ops_td->soft_output;
2325 
2326 		ret = check_dec_status_and_ordering(ops[i], i, ref_op->status);
2327 		TEST_ASSERT_SUCCESS(ret,
2328 				"Checking status and ordering for decoder failed");
2329 		if (vector_mask & TEST_BBDEV_VF_EXPECTED_ITER_COUNT)
2330 			TEST_ASSERT(ops_td->iter_count <= ref_td->iter_count,
2331 					"Returned iter_count (%d) > expected iter_count (%d)",
2332 					ops_td->iter_count, ref_td->iter_count);
2333 		/*
2334 		 * We can ignore output data when the decoding failed to
2335 		 * converge or for loop-back cases
2336 		 */
2337 		if (!check_bit(ops[i]->ldpc_dec.op_flags,
2338 				RTE_BBDEV_LDPC_INTERNAL_HARQ_MEMORY_LOOPBACK
2339 				) && (
2340 				ops[i]->status & (1 << RTE_BBDEV_SYNDROME_ERROR
2341 						)) == 0)
2342 			TEST_ASSERT_SUCCESS(validate_op_chain(hard_output,
2343 					hard_data_orig),
2344 					"Hard output buffers (CB=%u) are not equal",
2345 					i);
2346 
2347 		if (ref_op->ldpc_dec.op_flags & RTE_BBDEV_LDPC_SOFT_OUT_ENABLE)
2348 			TEST_ASSERT_SUCCESS(validate_op_chain(soft_output,
2349 					soft_data_orig),
2350 					"Soft output buffers (CB=%u) are not equal",
2351 					i);
2352 		if (ref_op->ldpc_dec.op_flags &
2353 				RTE_BBDEV_LDPC_HQ_COMBINE_OUT_ENABLE) {
2354 			TEST_ASSERT_SUCCESS(validate_op_harq_chain(harq_output,
2355 					harq_data_orig, ops_td),
2356 					"HARQ output buffers (CB=%u) are not equal",
2357 					i);
2358 		}
2359 		if (ref_op->ldpc_dec.op_flags &
2360 				RTE_BBDEV_LDPC_INTERNAL_HARQ_MEMORY_LOOPBACK)
2361 			TEST_ASSERT_SUCCESS(validate_op_harq_chain(harq_output,
2362 					harq_data_orig, ops_td),
2363 					"HARQ output buffers (CB=%u) are not equal",
2364 					i);
2365 
2366 	}
2367 
2368 	return TEST_SUCCESS;
2369 }
2370 
2371 
2372 static int
2373 validate_enc_op(struct rte_bbdev_enc_op **ops, const uint16_t n,
2374 		struct rte_bbdev_enc_op *ref_op)
2375 {
2376 	unsigned int i;
2377 	int ret;
2378 	struct op_data_entries *hard_data_orig =
2379 			&test_vector.entries[DATA_HARD_OUTPUT];
2380 
2381 	for (i = 0; i < n; ++i) {
2382 		ret = check_enc_status_and_ordering(ops[i], i, ref_op->status);
2383 		TEST_ASSERT_SUCCESS(ret,
2384 				"Checking status and ordering for encoder failed");
2385 		TEST_ASSERT_SUCCESS(validate_op_chain(
2386 				&ops[i]->turbo_enc.output,
2387 				hard_data_orig),
2388 				"Output buffers (CB=%u) are not equal",
2389 				i);
2390 	}
2391 
2392 	return TEST_SUCCESS;
2393 }
2394 
2395 static int
2396 validate_ldpc_enc_op(struct rte_bbdev_enc_op **ops, const uint16_t n,
2397 		struct rte_bbdev_enc_op *ref_op)
2398 {
2399 	unsigned int i;
2400 	int ret;
2401 	struct op_data_entries *hard_data_orig =
2402 			&test_vector.entries[DATA_HARD_OUTPUT];
2403 
2404 	for (i = 0; i < n; ++i) {
2405 		ret = check_enc_status_and_ordering(ops[i], i, ref_op->status);
2406 		TEST_ASSERT_SUCCESS(ret,
2407 				"Checking status and ordering for encoder failed");
2408 		TEST_ASSERT_SUCCESS(validate_op_chain(
2409 				&ops[i]->ldpc_enc.output,
2410 				hard_data_orig),
2411 				"Output buffers (CB=%u) are not equal",
2412 				i);
2413 	}
2414 
2415 	return TEST_SUCCESS;
2416 }
2417 
2418 
2419 static inline int
2420 validate_op_fft_chain(struct rte_bbdev_op_data *op, struct op_data_entries *orig_op)
2421 {
2422 	struct rte_mbuf *m = op->data;
2423 	uint8_t i, nb_dst_segments = orig_op->nb_segments;
2424 	int16_t delt, abs_delt, thres_hold = 3;
2425 	uint32_t j, data_len_iq, error_num;
2426 	int16_t *ref_out, *op_out;
2427 
2428 	TEST_ASSERT(nb_dst_segments == m->nb_segs,
2429 			"Number of segments differ in original (%u) and filled (%u) op fft",
2430 			nb_dst_segments, m->nb_segs);
2431 
2432 	/* Due to size limitation of mbuf, FFT doesn't use real mbuf. */
2433 	for (i = 0; i < nb_dst_segments; ++i) {
2434 		uint16_t offset = (i == 0) ? op->offset : 0;
2435 		uint32_t data_len = op->length;
2436 
2437 		TEST_ASSERT(orig_op->segments[i].length == data_len,
2438 				"Length of segment differ in original (%u) and filled (%u) op fft",
2439 				orig_op->segments[i].length, data_len);
2440 		/* Divided by 2 to get the number of 16bits data. */
2441 		data_len_iq = data_len >> 1;
2442 		ref_out = (int16_t *)(orig_op->segments[i].addr);
2443 		op_out = rte_pktmbuf_mtod_offset(m, int16_t *, offset);
2444 		error_num = 0;
2445 		for (j = 0; j < data_len_iq; j++) {
2446 			delt = ref_out[j] - op_out[j];
2447 			abs_delt = delt > 0 ? delt : -delt;
2448 			error_num += (abs_delt > thres_hold ? 1 : 0);
2449 		}
2450 		if (error_num > 0) {
2451 			rte_memdump(stdout, "Buffer A", ref_out, data_len);
2452 			rte_memdump(stdout, "Buffer B", op_out, data_len);
2453 			TEST_ASSERT(error_num == 0,
2454 				"FFT Output are not matched total (%u) errors (%u)",
2455 				data_len_iq, error_num);
2456 		}
2457 
2458 		m = m->next;
2459 	}
2460 
2461 	return TEST_SUCCESS;
2462 }
2463 
2464 static int
2465 validate_fft_op(struct rte_bbdev_fft_op **ops, const uint16_t n,
2466 		struct rte_bbdev_fft_op *ref_op)
2467 {
2468 	unsigned int i;
2469 	int ret;
2470 	struct op_data_entries *fft_data_orig = &test_vector.entries[DATA_HARD_OUTPUT];
2471 	struct op_data_entries *fft_pwr_orig = &test_vector.entries[DATA_SOFT_OUTPUT];
2472 
2473 	for (i = 0; i < n; ++i) {
2474 		ret = check_fft_status_and_ordering(ops[i], i, ref_op->status);
2475 		TEST_ASSERT_SUCCESS(ret, "Checking status and ordering for FFT failed");
2476 		TEST_ASSERT_SUCCESS(validate_op_fft_chain(
2477 				&ops[i]->fft.base_output, fft_data_orig),
2478 				"FFT Output buffers (op=%u) are not matched", i);
2479 		if (check_bit(ops[i]->fft.op_flags, RTE_BBDEV_FFT_POWER_MEAS))
2480 			TEST_ASSERT_SUCCESS(validate_op_fft_chain(
2481 				&ops[i]->fft.power_meas_output, fft_pwr_orig),
2482 				"FFT Power Output buffers (op=%u) are not matched", i);
2483 	}
2484 
2485 	return TEST_SUCCESS;
2486 }
2487 
2488 static void
2489 create_reference_dec_op(struct rte_bbdev_dec_op *op)
2490 {
2491 	unsigned int i;
2492 	struct op_data_entries *entry;
2493 
2494 	op->turbo_dec = test_vector.turbo_dec;
2495 	entry = &test_vector.entries[DATA_INPUT];
2496 	for (i = 0; i < entry->nb_segments; ++i)
2497 		op->turbo_dec.input.length +=
2498 				entry->segments[i].length;
2499 }
2500 
2501 static void
2502 create_reference_ldpc_dec_op(struct rte_bbdev_dec_op *op)
2503 {
2504 	unsigned int i;
2505 	struct op_data_entries *entry;
2506 
2507 	op->ldpc_dec = test_vector.ldpc_dec;
2508 	entry = &test_vector.entries[DATA_INPUT];
2509 	for (i = 0; i < entry->nb_segments; ++i)
2510 		op->ldpc_dec.input.length +=
2511 				entry->segments[i].length;
2512 	if (test_vector.ldpc_dec.op_flags &
2513 			RTE_BBDEV_LDPC_HQ_COMBINE_IN_ENABLE) {
2514 		entry = &test_vector.entries[DATA_HARQ_INPUT];
2515 		for (i = 0; i < entry->nb_segments; ++i)
2516 			op->ldpc_dec.harq_combined_input.length +=
2517 				entry->segments[i].length;
2518 	}
2519 }
2520 
2521 static void
2522 create_reference_fft_op(struct rte_bbdev_fft_op *op)
2523 {
2524 	unsigned int i;
2525 	struct op_data_entries *entry;
2526 	op->fft = test_vector.fft;
2527 	entry = &test_vector.entries[DATA_INPUT];
2528 	for (i = 0; i < entry->nb_segments; ++i)
2529 		op->fft.base_input.length += entry->segments[i].length;
2530 }
2531 
2532 static void
2533 create_reference_enc_op(struct rte_bbdev_enc_op *op)
2534 {
2535 	unsigned int i;
2536 	struct op_data_entries *entry;
2537 
2538 	op->turbo_enc = test_vector.turbo_enc;
2539 	entry = &test_vector.entries[DATA_INPUT];
2540 	for (i = 0; i < entry->nb_segments; ++i)
2541 		op->turbo_enc.input.length +=
2542 				entry->segments[i].length;
2543 }
2544 
2545 static void
2546 create_reference_ldpc_enc_op(struct rte_bbdev_enc_op *op)
2547 {
2548 	unsigned int i;
2549 	struct op_data_entries *entry;
2550 
2551 	op->ldpc_enc = test_vector.ldpc_enc;
2552 	entry = &test_vector.entries[DATA_INPUT];
2553 	for (i = 0; i < entry->nb_segments; ++i)
2554 		op->ldpc_enc.input.length +=
2555 				entry->segments[i].length;
2556 }
2557 
2558 static uint32_t
2559 calc_dec_TB_size(struct rte_bbdev_dec_op *op)
2560 {
2561 	uint8_t i;
2562 	uint32_t c, r, tb_size = 0;
2563 
2564 	if (op->turbo_dec.code_block_mode == RTE_BBDEV_CODE_BLOCK) {
2565 		tb_size = op->turbo_dec.tb_params.k_neg;
2566 	} else {
2567 		c = op->turbo_dec.tb_params.c;
2568 		r = op->turbo_dec.tb_params.r;
2569 		for (i = 0; i < c-r; i++)
2570 			tb_size += (r < op->turbo_dec.tb_params.c_neg) ?
2571 				op->turbo_dec.tb_params.k_neg :
2572 				op->turbo_dec.tb_params.k_pos;
2573 	}
2574 	return tb_size;
2575 }
2576 
2577 static uint32_t
2578 calc_ldpc_dec_TB_size(struct rte_bbdev_dec_op *op)
2579 {
2580 	uint8_t i;
2581 	uint32_t c, r, tb_size = 0;
2582 	uint16_t sys_cols = (op->ldpc_dec.basegraph == 1) ? 22 : 10;
2583 
2584 	if (op->ldpc_dec.code_block_mode == RTE_BBDEV_CODE_BLOCK) {
2585 		tb_size = sys_cols * op->ldpc_dec.z_c - op->ldpc_dec.n_filler;
2586 	} else {
2587 		c = op->ldpc_dec.tb_params.c;
2588 		r = op->ldpc_dec.tb_params.r;
2589 		for (i = 0; i < c-r; i++)
2590 			tb_size += sys_cols * op->ldpc_dec.z_c
2591 					- op->ldpc_dec.n_filler;
2592 	}
2593 	return tb_size;
2594 }
2595 
2596 static uint32_t
2597 calc_enc_TB_size(struct rte_bbdev_enc_op *op)
2598 {
2599 	uint8_t i;
2600 	uint32_t c, r, tb_size = 0;
2601 
2602 	if (op->turbo_enc.code_block_mode == RTE_BBDEV_CODE_BLOCK) {
2603 		tb_size = op->turbo_enc.tb_params.k_neg;
2604 	} else {
2605 		c = op->turbo_enc.tb_params.c;
2606 		r = op->turbo_enc.tb_params.r;
2607 		for (i = 0; i < c-r; i++)
2608 			tb_size += (r < op->turbo_enc.tb_params.c_neg) ?
2609 				op->turbo_enc.tb_params.k_neg :
2610 				op->turbo_enc.tb_params.k_pos;
2611 	}
2612 	return tb_size;
2613 }
2614 
2615 static uint32_t
2616 calc_ldpc_enc_TB_size(struct rte_bbdev_enc_op *op)
2617 {
2618 	uint8_t i;
2619 	uint32_t c, r, tb_size = 0;
2620 	uint16_t sys_cols = (op->ldpc_enc.basegraph == 1) ? 22 : 10;
2621 
2622 	if (op->ldpc_enc.code_block_mode == RTE_BBDEV_CODE_BLOCK) {
2623 		tb_size = sys_cols * op->ldpc_enc.z_c - op->ldpc_enc.n_filler;
2624 	} else {
2625 		c = op->turbo_enc.tb_params.c;
2626 		r = op->turbo_enc.tb_params.r;
2627 		for (i = 0; i < c-r; i++)
2628 			tb_size += sys_cols * op->ldpc_enc.z_c
2629 					- op->ldpc_enc.n_filler;
2630 	}
2631 	return tb_size;
2632 }
2633 
2634 static uint32_t
2635 calc_fft_size(struct rte_bbdev_fft_op *op)
2636 {
2637 	uint32_t output_size;
2638 	int num_cs = 0, i;
2639 	for (i = 0; i < 12; i++)
2640 		if (check_bit(op->fft.cs_bitmap, 1 << i))
2641 			num_cs++;
2642 	output_size = (num_cs * op->fft.output_sequence_size * 4) << op->fft.num_antennas_log2;
2643 	return output_size;
2644 }
2645 
2646 static int
2647 init_test_op_params(struct test_op_params *op_params,
2648 		enum rte_bbdev_op_type op_type, const int expected_status,
2649 		const int vector_mask, struct rte_mempool *ops_mp,
2650 		uint16_t burst_sz, uint16_t num_to_process, uint16_t num_lcores)
2651 {
2652 	int ret = 0;
2653 	if (op_type == RTE_BBDEV_OP_TURBO_DEC ||
2654 			op_type == RTE_BBDEV_OP_LDPC_DEC)
2655 		ret = rte_bbdev_dec_op_alloc_bulk(ops_mp,
2656 				&op_params->ref_dec_op, 1);
2657 	else if (op_type == RTE_BBDEV_OP_FFT)
2658 		ret = rte_bbdev_fft_op_alloc_bulk(ops_mp,
2659 				&op_params->ref_fft_op, 1);
2660 	else
2661 		ret = rte_bbdev_enc_op_alloc_bulk(ops_mp,
2662 				&op_params->ref_enc_op, 1);
2663 
2664 	TEST_ASSERT_SUCCESS(ret, "rte_bbdev_op_alloc_bulk() failed");
2665 
2666 	op_params->mp = ops_mp;
2667 	op_params->burst_sz = burst_sz;
2668 	op_params->num_to_process = num_to_process;
2669 	op_params->num_lcores = num_lcores;
2670 	op_params->vector_mask = vector_mask;
2671 	if (op_type == RTE_BBDEV_OP_TURBO_DEC ||
2672 			op_type == RTE_BBDEV_OP_LDPC_DEC)
2673 		op_params->ref_dec_op->status = expected_status;
2674 	else if (op_type == RTE_BBDEV_OP_TURBO_ENC
2675 			|| op_type == RTE_BBDEV_OP_LDPC_ENC)
2676 		op_params->ref_enc_op->status = expected_status;
2677 	else if (op_type == RTE_BBDEV_OP_FFT)
2678 		op_params->ref_fft_op->status = expected_status;
2679 	return 0;
2680 }
2681 
2682 static int
2683 run_test_case_on_device(test_case_function *test_case_func, uint8_t dev_id,
2684 		struct test_op_params *op_params)
2685 {
2686 	int t_ret, f_ret, socket_id = SOCKET_ID_ANY;
2687 	unsigned int i;
2688 	struct active_device *ad;
2689 	unsigned int burst_sz = get_burst_sz();
2690 	enum rte_bbdev_op_type op_type = test_vector.op_type;
2691 	const struct rte_bbdev_op_cap *capabilities = NULL;
2692 
2693 	ad = &active_devs[dev_id];
2694 
2695 	/* Check if device supports op_type */
2696 	if (!is_avail_op(ad, test_vector.op_type))
2697 		return TEST_SUCCESS;
2698 
2699 	struct rte_bbdev_info info;
2700 	rte_bbdev_info_get(ad->dev_id, &info);
2701 	socket_id = GET_SOCKET(info.socket_id);
2702 
2703 	f_ret = create_mempools(ad, socket_id, op_type,
2704 			get_num_ops());
2705 	if (f_ret != TEST_SUCCESS) {
2706 		printf("Couldn't create mempools");
2707 		goto fail;
2708 	}
2709 	if (op_type == RTE_BBDEV_OP_NONE)
2710 		op_type = RTE_BBDEV_OP_TURBO_ENC;
2711 
2712 	f_ret = init_test_op_params(op_params, test_vector.op_type,
2713 			test_vector.expected_status,
2714 			test_vector.mask,
2715 			ad->ops_mempool,
2716 			burst_sz,
2717 			get_num_ops(),
2718 			get_num_lcores());
2719 	if (f_ret != TEST_SUCCESS) {
2720 		printf("Couldn't init test op params");
2721 		goto fail;
2722 	}
2723 
2724 
2725 	/* Find capabilities */
2726 	const struct rte_bbdev_op_cap *cap = info.drv.capabilities;
2727 	do {
2728 		if (cap->type == test_vector.op_type) {
2729 			capabilities = cap;
2730 			break;
2731 		}
2732 		cap++;
2733 	} while (cap->type != RTE_BBDEV_OP_NONE);
2734 	TEST_ASSERT_NOT_NULL(capabilities,
2735 			"Couldn't find capabilities");
2736 
2737 	if (test_vector.op_type == RTE_BBDEV_OP_TURBO_DEC) {
2738 		create_reference_dec_op(op_params->ref_dec_op);
2739 	} else if (test_vector.op_type == RTE_BBDEV_OP_TURBO_ENC)
2740 		create_reference_enc_op(op_params->ref_enc_op);
2741 	else if (test_vector.op_type == RTE_BBDEV_OP_LDPC_ENC)
2742 		create_reference_ldpc_enc_op(op_params->ref_enc_op);
2743 	else if (test_vector.op_type == RTE_BBDEV_OP_LDPC_DEC)
2744 		create_reference_ldpc_dec_op(op_params->ref_dec_op);
2745 	else if (test_vector.op_type == RTE_BBDEV_OP_FFT)
2746 		create_reference_fft_op(op_params->ref_fft_op);
2747 
2748 	for (i = 0; i < ad->nb_queues; ++i) {
2749 		f_ret = fill_queue_buffers(op_params,
2750 				ad->in_mbuf_pool,
2751 				ad->hard_out_mbuf_pool,
2752 				ad->soft_out_mbuf_pool,
2753 				ad->harq_in_mbuf_pool,
2754 				ad->harq_out_mbuf_pool,
2755 				ad->queue_ids[i],
2756 				capabilities,
2757 				info.drv.min_alignment,
2758 				socket_id);
2759 		if (f_ret != TEST_SUCCESS) {
2760 			printf("Couldn't init queue buffers");
2761 			goto fail;
2762 		}
2763 	}
2764 
2765 	/* Run test case function */
2766 	t_ret = test_case_func(ad, op_params);
2767 
2768 	/* Free active device resources and return */
2769 	free_buffers(ad, op_params);
2770 	return t_ret;
2771 
2772 fail:
2773 	free_buffers(ad, op_params);
2774 	return TEST_FAILED;
2775 }
2776 
2777 /* Run given test function per active device per supported op type
2778  * per burst size.
2779  */
2780 static int
2781 run_test_case(test_case_function *test_case_func)
2782 {
2783 	int ret = 0;
2784 	uint8_t dev;
2785 
2786 	/* Alloc op_params */
2787 	struct test_op_params *op_params = rte_zmalloc(NULL,
2788 			sizeof(struct test_op_params), RTE_CACHE_LINE_SIZE);
2789 	TEST_ASSERT_NOT_NULL(op_params, "Failed to alloc %zuB for op_params",
2790 			RTE_ALIGN(sizeof(struct test_op_params),
2791 				RTE_CACHE_LINE_SIZE));
2792 
2793 	/* For each device run test case function */
2794 	for (dev = 0; dev < nb_active_devs; ++dev)
2795 		ret |= run_test_case_on_device(test_case_func, dev, op_params);
2796 
2797 	rte_free(op_params);
2798 
2799 	return ret;
2800 }
2801 
2802 
2803 /* Push back the HARQ output from DDR to host */
2804 static void
2805 retrieve_harq_ddr(uint16_t dev_id, uint16_t queue_id,
2806 		struct rte_bbdev_dec_op **ops,
2807 		const uint16_t n)
2808 {
2809 	uint16_t j;
2810 	int save_status, ret;
2811 	uint32_t harq_offset = (uint32_t) queue_id * HARQ_INCR * MAX_OPS;
2812 	struct rte_bbdev_dec_op *ops_deq[MAX_BURST];
2813 	uint32_t flags = ops[0]->ldpc_dec.op_flags;
2814 	bool loopback = flags & RTE_BBDEV_LDPC_INTERNAL_HARQ_MEMORY_LOOPBACK;
2815 	bool mem_out = flags & RTE_BBDEV_LDPC_INTERNAL_HARQ_MEMORY_OUT_ENABLE;
2816 	bool hc_out = flags & RTE_BBDEV_LDPC_HQ_COMBINE_OUT_ENABLE;
2817 	bool h_comp = flags & RTE_BBDEV_LDPC_HARQ_6BIT_COMPRESSION;
2818 	for (j = 0; j < n; ++j) {
2819 		if ((loopback && mem_out) || hc_out) {
2820 			save_status = ops[j]->status;
2821 			ops[j]->ldpc_dec.op_flags =
2822 				RTE_BBDEV_LDPC_INTERNAL_HARQ_MEMORY_LOOPBACK +
2823 				RTE_BBDEV_LDPC_INTERNAL_HARQ_MEMORY_IN_ENABLE;
2824 			if (h_comp)
2825 				ops[j]->ldpc_dec.op_flags +=
2826 					RTE_BBDEV_LDPC_HARQ_6BIT_COMPRESSION;
2827 			ops[j]->ldpc_dec.harq_combined_input.offset =
2828 					harq_offset;
2829 			ops[j]->ldpc_dec.harq_combined_output.offset = 0;
2830 			harq_offset += HARQ_INCR;
2831 			if (!loopback)
2832 				ops[j]->ldpc_dec.harq_combined_input.length =
2833 				ops[j]->ldpc_dec.harq_combined_output.length;
2834 			rte_bbdev_enqueue_ldpc_dec_ops(dev_id, queue_id,
2835 					&ops[j], 1);
2836 			ret = 0;
2837 			while (ret == 0)
2838 				ret = rte_bbdev_dequeue_ldpc_dec_ops(
2839 						dev_id, queue_id,
2840 						&ops_deq[j], 1);
2841 			ops[j]->ldpc_dec.op_flags = flags;
2842 			ops[j]->status = save_status;
2843 		}
2844 	}
2845 }
2846 
2847 /*
2848  * Push back the HARQ output from HW DDR to Host
2849  * Preload HARQ memory input and adjust HARQ offset
2850  */
2851 static void
2852 preload_harq_ddr(uint16_t dev_id, uint16_t queue_id,
2853 		struct rte_bbdev_dec_op **ops, const uint16_t n,
2854 		bool preload)
2855 {
2856 	uint16_t j;
2857 	int deq;
2858 	uint32_t harq_offset = (uint32_t) queue_id * HARQ_INCR * MAX_OPS;
2859 	struct rte_bbdev_op_data save_hc_in[MAX_OPS], save_hc_out[MAX_OPS];
2860 	struct rte_bbdev_dec_op *ops_deq[MAX_OPS];
2861 	uint32_t flags = ops[0]->ldpc_dec.op_flags;
2862 	bool mem_in = flags & RTE_BBDEV_LDPC_INTERNAL_HARQ_MEMORY_IN_ENABLE;
2863 	bool hc_in = flags & RTE_BBDEV_LDPC_HQ_COMBINE_IN_ENABLE;
2864 	bool mem_out = flags & RTE_BBDEV_LDPC_INTERNAL_HARQ_MEMORY_OUT_ENABLE;
2865 	bool hc_out = flags & RTE_BBDEV_LDPC_HQ_COMBINE_OUT_ENABLE;
2866 	bool h_comp = flags & RTE_BBDEV_LDPC_HARQ_6BIT_COMPRESSION;
2867 	if ((mem_in || hc_in) && preload) {
2868 		for (j = 0; j < n; ++j) {
2869 			save_hc_in[j] = ops[j]->ldpc_dec.harq_combined_input;
2870 			save_hc_out[j] = ops[j]->ldpc_dec.harq_combined_output;
2871 			ops[j]->ldpc_dec.op_flags =
2872 				RTE_BBDEV_LDPC_INTERNAL_HARQ_MEMORY_LOOPBACK +
2873 				RTE_BBDEV_LDPC_INTERNAL_HARQ_MEMORY_OUT_ENABLE;
2874 			if (h_comp)
2875 				ops[j]->ldpc_dec.op_flags +=
2876 					RTE_BBDEV_LDPC_HARQ_6BIT_COMPRESSION;
2877 			ops[j]->ldpc_dec.harq_combined_output.offset =
2878 					harq_offset;
2879 			ops[j]->ldpc_dec.harq_combined_input.offset = 0;
2880 			harq_offset += HARQ_INCR;
2881 		}
2882 		rte_bbdev_enqueue_ldpc_dec_ops(dev_id, queue_id, &ops[0], n);
2883 		deq = 0;
2884 		while (deq != n)
2885 			deq += rte_bbdev_dequeue_ldpc_dec_ops(
2886 					dev_id, queue_id, &ops_deq[deq],
2887 					n - deq);
2888 		/* Restore the operations */
2889 		for (j = 0; j < n; ++j) {
2890 			ops[j]->ldpc_dec.op_flags = flags;
2891 			ops[j]->ldpc_dec.harq_combined_input = save_hc_in[j];
2892 			ops[j]->ldpc_dec.harq_combined_output = save_hc_out[j];
2893 		}
2894 	}
2895 	harq_offset = (uint32_t) queue_id * HARQ_INCR * MAX_OPS;
2896 	for (j = 0; j < n; ++j) {
2897 		/* Adjust HARQ offset when we reach external DDR */
2898 		if (mem_in || hc_in)
2899 			ops[j]->ldpc_dec.harq_combined_input.offset
2900 				= harq_offset;
2901 		if (mem_out || hc_out)
2902 			ops[j]->ldpc_dec.harq_combined_output.offset
2903 				= harq_offset;
2904 		harq_offset += HARQ_INCR;
2905 	}
2906 }
2907 
2908 static void
2909 dequeue_event_callback(uint16_t dev_id,
2910 		enum rte_bbdev_event_type event, void *cb_arg,
2911 		void *ret_param)
2912 {
2913 	int ret;
2914 	uint16_t i;
2915 	uint64_t total_time;
2916 	uint16_t deq, burst_sz, num_ops;
2917 	uint16_t queue_id = *(uint16_t *) ret_param;
2918 	struct rte_bbdev_info info;
2919 	double tb_len_bits;
2920 	struct thread_params *tp = cb_arg;
2921 
2922 	/* Find matching thread params using queue_id */
2923 	for (i = 0; i < MAX_QUEUES; ++i, ++tp)
2924 		if (tp->queue_id == queue_id)
2925 			break;
2926 
2927 	if (i == MAX_QUEUES) {
2928 		printf("%s: Queue_id from interrupt details was not found!\n",
2929 				__func__);
2930 		return;
2931 	}
2932 
2933 	if (unlikely(event != RTE_BBDEV_EVENT_DEQUEUE)) {
2934 		__atomic_store_n(&tp->processing_status, TEST_FAILED, __ATOMIC_RELAXED);
2935 		printf(
2936 			"Dequeue interrupt handler called for incorrect event!\n");
2937 		return;
2938 	}
2939 
2940 	burst_sz = __atomic_load_n(&tp->burst_sz, __ATOMIC_RELAXED);
2941 	num_ops = tp->op_params->num_to_process;
2942 
2943 	if (test_vector.op_type == RTE_BBDEV_OP_TURBO_DEC)
2944 		deq = rte_bbdev_dequeue_dec_ops(dev_id, queue_id,
2945 				&tp->dec_ops[
2946 					__atomic_load_n(&tp->nb_dequeued, __ATOMIC_RELAXED)],
2947 				burst_sz);
2948 	else if (test_vector.op_type == RTE_BBDEV_OP_LDPC_DEC)
2949 		deq = rte_bbdev_dequeue_ldpc_dec_ops(dev_id, queue_id,
2950 				&tp->dec_ops[
2951 					__atomic_load_n(&tp->nb_dequeued, __ATOMIC_RELAXED)],
2952 				burst_sz);
2953 	else if (test_vector.op_type == RTE_BBDEV_OP_LDPC_ENC)
2954 		deq = rte_bbdev_dequeue_ldpc_enc_ops(dev_id, queue_id,
2955 				&tp->enc_ops[
2956 					__atomic_load_n(&tp->nb_dequeued, __ATOMIC_RELAXED)],
2957 				burst_sz);
2958 	else if (test_vector.op_type == RTE_BBDEV_OP_FFT)
2959 		deq = rte_bbdev_dequeue_fft_ops(dev_id, queue_id,
2960 				&tp->fft_ops[
2961 					__atomic_load_n(&tp->nb_dequeued, __ATOMIC_RELAXED)],
2962 				burst_sz);
2963 	else /*RTE_BBDEV_OP_TURBO_ENC*/
2964 		deq = rte_bbdev_dequeue_enc_ops(dev_id, queue_id,
2965 				&tp->enc_ops[
2966 					__atomic_load_n(&tp->nb_dequeued, __ATOMIC_RELAXED)],
2967 				burst_sz);
2968 
2969 	if (deq < burst_sz) {
2970 		printf(
2971 			"After receiving the interrupt all operations should be dequeued. Expected: %u, got: %u\n",
2972 			burst_sz, deq);
2973 		__atomic_store_n(&tp->processing_status, TEST_FAILED, __ATOMIC_RELAXED);
2974 		return;
2975 	}
2976 
2977 	if (__atomic_load_n(&tp->nb_dequeued, __ATOMIC_RELAXED) + deq < num_ops) {
2978 		__atomic_fetch_add(&tp->nb_dequeued, deq, __ATOMIC_RELAXED);
2979 		return;
2980 	}
2981 
2982 	total_time = rte_rdtsc_precise() - tp->start_time;
2983 
2984 	rte_bbdev_info_get(dev_id, &info);
2985 
2986 	ret = TEST_SUCCESS;
2987 
2988 	if (test_vector.op_type == RTE_BBDEV_OP_TURBO_DEC) {
2989 		struct rte_bbdev_dec_op *ref_op = tp->op_params->ref_dec_op;
2990 		ret = validate_dec_op(tp->dec_ops, num_ops, ref_op,
2991 				tp->op_params->vector_mask);
2992 		/* get the max of iter_count for all dequeued ops */
2993 		for (i = 0; i < num_ops; ++i)
2994 			tp->iter_count = RTE_MAX(
2995 					tp->dec_ops[i]->turbo_dec.iter_count,
2996 					tp->iter_count);
2997 		rte_bbdev_dec_op_free_bulk(tp->dec_ops, deq);
2998 	} else if (test_vector.op_type == RTE_BBDEV_OP_TURBO_ENC) {
2999 		struct rte_bbdev_enc_op *ref_op = tp->op_params->ref_enc_op;
3000 		ret = validate_enc_op(tp->enc_ops, num_ops, ref_op);
3001 		rte_bbdev_enc_op_free_bulk(tp->enc_ops, deq);
3002 	} else if (test_vector.op_type == RTE_BBDEV_OP_LDPC_ENC) {
3003 		struct rte_bbdev_enc_op *ref_op = tp->op_params->ref_enc_op;
3004 		ret = validate_ldpc_enc_op(tp->enc_ops, num_ops, ref_op);
3005 		rte_bbdev_enc_op_free_bulk(tp->enc_ops, deq);
3006 	} else if (test_vector.op_type == RTE_BBDEV_OP_FFT) {
3007 		struct rte_bbdev_fft_op *ref_op = tp->op_params->ref_fft_op;
3008 		ret = validate_fft_op(tp->fft_ops, num_ops, ref_op);
3009 		rte_bbdev_fft_op_free_bulk(tp->fft_ops, deq);
3010 	} else if (test_vector.op_type == RTE_BBDEV_OP_LDPC_DEC) {
3011 		struct rte_bbdev_dec_op *ref_op = tp->op_params->ref_dec_op;
3012 		ret = validate_ldpc_dec_op(tp->dec_ops, num_ops, ref_op,
3013 				tp->op_params->vector_mask);
3014 		rte_bbdev_dec_op_free_bulk(tp->dec_ops, deq);
3015 	}
3016 
3017 	if (ret) {
3018 		printf("Buffers validation failed\n");
3019 		__atomic_store_n(&tp->processing_status, TEST_FAILED, __ATOMIC_RELAXED);
3020 	}
3021 
3022 	switch (test_vector.op_type) {
3023 	case RTE_BBDEV_OP_TURBO_DEC:
3024 		tb_len_bits = calc_dec_TB_size(tp->op_params->ref_dec_op);
3025 		break;
3026 	case RTE_BBDEV_OP_TURBO_ENC:
3027 		tb_len_bits = calc_enc_TB_size(tp->op_params->ref_enc_op);
3028 		break;
3029 	case RTE_BBDEV_OP_LDPC_DEC:
3030 		tb_len_bits = calc_ldpc_dec_TB_size(tp->op_params->ref_dec_op);
3031 		break;
3032 	case RTE_BBDEV_OP_FFT:
3033 		tb_len_bits = calc_fft_size(tp->op_params->ref_fft_op);
3034 		break;
3035 	case RTE_BBDEV_OP_LDPC_ENC:
3036 		tb_len_bits = calc_ldpc_enc_TB_size(tp->op_params->ref_enc_op);
3037 		break;
3038 	case RTE_BBDEV_OP_NONE:
3039 		tb_len_bits = 0.0;
3040 		break;
3041 	default:
3042 		printf("Unknown op type: %d\n", test_vector.op_type);
3043 		__atomic_store_n(&tp->processing_status, TEST_FAILED, __ATOMIC_RELAXED);
3044 		return;
3045 	}
3046 
3047 	tp->ops_per_sec += ((double)num_ops) /
3048 			((double)total_time / (double)rte_get_tsc_hz());
3049 	tp->mbps += (((double)(num_ops * tb_len_bits)) / 1000000.0) /
3050 			((double)total_time / (double)rte_get_tsc_hz());
3051 
3052 	__atomic_fetch_add(&tp->nb_dequeued, deq, __ATOMIC_RELAXED);
3053 }
3054 
3055 static int
3056 throughput_intr_lcore_ldpc_dec(void *arg)
3057 {
3058 	struct thread_params *tp = arg;
3059 	unsigned int enqueued;
3060 	const uint16_t queue_id = tp->queue_id;
3061 	const uint16_t burst_sz = tp->op_params->burst_sz;
3062 	const uint16_t num_to_process = tp->op_params->num_to_process;
3063 	struct rte_bbdev_dec_op *ops[num_to_process];
3064 	struct test_buffers *bufs = NULL;
3065 	struct rte_bbdev_info info;
3066 	int ret, i, j;
3067 	struct rte_bbdev_dec_op *ref_op = tp->op_params->ref_dec_op;
3068 	uint16_t num_to_enq, enq;
3069 
3070 	bool loopback = check_bit(ref_op->ldpc_dec.op_flags,
3071 			RTE_BBDEV_LDPC_INTERNAL_HARQ_MEMORY_LOOPBACK);
3072 	bool hc_out = check_bit(ref_op->ldpc_dec.op_flags,
3073 			RTE_BBDEV_LDPC_HQ_COMBINE_OUT_ENABLE);
3074 
3075 	TEST_ASSERT_SUCCESS((burst_sz > MAX_BURST),
3076 			"BURST_SIZE should be <= %u", MAX_BURST);
3077 
3078 	TEST_ASSERT_SUCCESS(rte_bbdev_queue_intr_enable(tp->dev_id, queue_id),
3079 			"Failed to enable interrupts for dev: %u, queue_id: %u",
3080 			tp->dev_id, queue_id);
3081 
3082 	rte_bbdev_info_get(tp->dev_id, &info);
3083 
3084 	TEST_ASSERT_SUCCESS((num_to_process > info.drv.queue_size_lim),
3085 			"NUM_OPS cannot exceed %u for this device",
3086 			info.drv.queue_size_lim);
3087 
3088 	bufs = &tp->op_params->q_bufs[GET_SOCKET(info.socket_id)][queue_id];
3089 
3090 	__atomic_store_n(&tp->processing_status, 0, __ATOMIC_RELAXED);
3091 	__atomic_store_n(&tp->nb_dequeued, 0, __ATOMIC_RELAXED);
3092 
3093 	rte_wait_until_equal_16(&tp->op_params->sync, SYNC_START, __ATOMIC_RELAXED);
3094 
3095 	ret = rte_bbdev_dec_op_alloc_bulk(tp->op_params->mp, ops,
3096 				num_to_process);
3097 	TEST_ASSERT_SUCCESS(ret, "Allocation failed for %d ops",
3098 			num_to_process);
3099 	if (test_vector.op_type != RTE_BBDEV_OP_NONE)
3100 		copy_reference_ldpc_dec_op(ops, num_to_process, 0, bufs->inputs,
3101 				bufs->hard_outputs, bufs->soft_outputs,
3102 				bufs->harq_inputs, bufs->harq_outputs, ref_op);
3103 
3104 	/* Set counter to validate the ordering */
3105 	for (j = 0; j < num_to_process; ++j)
3106 		ops[j]->opaque_data = (void *)(uintptr_t)j;
3107 
3108 	for (j = 0; j < TEST_REPETITIONS; ++j) {
3109 		for (i = 0; i < num_to_process; ++i) {
3110 			if (!loopback)
3111 				rte_pktmbuf_reset(
3112 					ops[i]->ldpc_dec.hard_output.data);
3113 			if (hc_out || loopback)
3114 				mbuf_reset(
3115 				ops[i]->ldpc_dec.harq_combined_output.data);
3116 		}
3117 
3118 		tp->start_time = rte_rdtsc_precise();
3119 		for (enqueued = 0; enqueued < num_to_process;) {
3120 			num_to_enq = burst_sz;
3121 
3122 			if (unlikely(num_to_process - enqueued < num_to_enq))
3123 				num_to_enq = num_to_process - enqueued;
3124 
3125 			enq = 0;
3126 			do {
3127 				enq += rte_bbdev_enqueue_ldpc_dec_ops(
3128 						tp->dev_id,
3129 						queue_id, &ops[enqueued],
3130 						num_to_enq);
3131 			} while (unlikely(num_to_enq != enq));
3132 			enqueued += enq;
3133 
3134 			/* Write to thread burst_sz current number of enqueued
3135 			 * descriptors. It ensures that proper number of
3136 			 * descriptors will be dequeued in callback
3137 			 * function - needed for last batch in case where
3138 			 * the number of operations is not a multiple of
3139 			 * burst size.
3140 			 */
3141 			__atomic_store_n(&tp->burst_sz, num_to_enq, __ATOMIC_RELAXED);
3142 
3143 			/* Wait until processing of previous batch is
3144 			 * completed
3145 			 */
3146 			rte_wait_until_equal_16(&tp->nb_dequeued, enqueued, __ATOMIC_RELAXED);
3147 		}
3148 		if (j != TEST_REPETITIONS - 1)
3149 			__atomic_store_n(&tp->nb_dequeued, 0, __ATOMIC_RELAXED);
3150 	}
3151 
3152 	return TEST_SUCCESS;
3153 }
3154 
3155 static int
3156 throughput_intr_lcore_dec(void *arg)
3157 {
3158 	struct thread_params *tp = arg;
3159 	unsigned int enqueued;
3160 	const uint16_t queue_id = tp->queue_id;
3161 	const uint16_t burst_sz = tp->op_params->burst_sz;
3162 	const uint16_t num_to_process = tp->op_params->num_to_process;
3163 	struct rte_bbdev_dec_op *ops[num_to_process];
3164 	struct test_buffers *bufs = NULL;
3165 	struct rte_bbdev_info info;
3166 	struct rte_bbdev_dec_op *ref_op = tp->op_params->ref_dec_op;
3167 	int ret, i, j;
3168 	uint16_t num_to_enq, enq;
3169 
3170 	TEST_ASSERT_SUCCESS((burst_sz > MAX_BURST),
3171 			"BURST_SIZE should be <= %u", MAX_BURST);
3172 
3173 	TEST_ASSERT_SUCCESS(rte_bbdev_queue_intr_enable(tp->dev_id, queue_id),
3174 			"Failed to enable interrupts for dev: %u, queue_id: %u",
3175 			tp->dev_id, queue_id);
3176 
3177 	rte_bbdev_info_get(tp->dev_id, &info);
3178 
3179 	TEST_ASSERT_SUCCESS((num_to_process > info.drv.queue_size_lim),
3180 			"NUM_OPS cannot exceed %u for this device",
3181 			info.drv.queue_size_lim);
3182 
3183 	bufs = &tp->op_params->q_bufs[GET_SOCKET(info.socket_id)][queue_id];
3184 
3185 	__atomic_store_n(&tp->processing_status, 0, __ATOMIC_RELAXED);
3186 	__atomic_store_n(&tp->nb_dequeued, 0, __ATOMIC_RELAXED);
3187 
3188 	rte_wait_until_equal_16(&tp->op_params->sync, SYNC_START, __ATOMIC_RELAXED);
3189 
3190 	ret = rte_bbdev_dec_op_alloc_bulk(tp->op_params->mp, ops,
3191 				num_to_process);
3192 	TEST_ASSERT_SUCCESS(ret, "Allocation failed for %d ops", num_to_process);
3193 	ref_op->turbo_dec.iter_max = get_iter_max();
3194 	if (test_vector.op_type != RTE_BBDEV_OP_NONE)
3195 		copy_reference_dec_op(ops, num_to_process, 0, bufs->inputs,
3196 				bufs->hard_outputs, bufs->soft_outputs,
3197 				tp->op_params->ref_dec_op);
3198 
3199 	/* Set counter to validate the ordering. */
3200 	for (j = 0; j < num_to_process; ++j)
3201 		ops[j]->opaque_data = (void *)(uintptr_t)j;
3202 
3203 	for (j = 0; j < TEST_REPETITIONS; ++j) {
3204 		for (i = 0; i < num_to_process; ++i) {
3205 			rte_pktmbuf_reset(ops[i]->turbo_dec.hard_output.data);
3206 			if (ops[i]->turbo_dec.soft_output.data != NULL)
3207 				rte_pktmbuf_reset(ops[i]->turbo_dec.soft_output.data);
3208 		}
3209 
3210 
3211 		tp->start_time = rte_rdtsc_precise();
3212 		for (enqueued = 0; enqueued < num_to_process;) {
3213 			num_to_enq = burst_sz;
3214 
3215 			if (unlikely(num_to_process - enqueued < num_to_enq))
3216 				num_to_enq = num_to_process - enqueued;
3217 
3218 			enq = 0;
3219 			do {
3220 				enq += rte_bbdev_enqueue_dec_ops(tp->dev_id,
3221 						queue_id, &ops[enqueued],
3222 						num_to_enq);
3223 			} while (unlikely(num_to_enq != enq));
3224 			enqueued += enq;
3225 
3226 			/* Write to thread burst_sz current number of enqueued
3227 			 * descriptors. It ensures that proper number of
3228 			 * descriptors will be dequeued in callback
3229 			 * function - needed for last batch in case where
3230 			 * the number of operations is not a multiple of
3231 			 * burst size.
3232 			 */
3233 			__atomic_store_n(&tp->burst_sz, num_to_enq, __ATOMIC_RELAXED);
3234 
3235 			/* Wait until processing of previous batch is
3236 			 * completed
3237 			 */
3238 			rte_wait_until_equal_16(&tp->nb_dequeued, enqueued, __ATOMIC_RELAXED);
3239 		}
3240 		if (j != TEST_REPETITIONS - 1)
3241 			__atomic_store_n(&tp->nb_dequeued, 0, __ATOMIC_RELAXED);
3242 	}
3243 
3244 	return TEST_SUCCESS;
3245 }
3246 
3247 static int
3248 throughput_intr_lcore_enc(void *arg)
3249 {
3250 	struct thread_params *tp = arg;
3251 	unsigned int enqueued;
3252 	const uint16_t queue_id = tp->queue_id;
3253 	const uint16_t burst_sz = tp->op_params->burst_sz;
3254 	const uint16_t num_to_process = tp->op_params->num_to_process;
3255 	struct rte_bbdev_enc_op *ops[num_to_process];
3256 	struct test_buffers *bufs = NULL;
3257 	struct rte_bbdev_info info;
3258 	int ret, i, j;
3259 	uint16_t num_to_enq, enq;
3260 
3261 	TEST_ASSERT_SUCCESS((burst_sz > MAX_BURST),
3262 			"BURST_SIZE should be <= %u", MAX_BURST);
3263 
3264 	TEST_ASSERT_SUCCESS(rte_bbdev_queue_intr_enable(tp->dev_id, queue_id),
3265 			"Failed to enable interrupts for dev: %u, queue_id: %u",
3266 			tp->dev_id, queue_id);
3267 
3268 	rte_bbdev_info_get(tp->dev_id, &info);
3269 
3270 	TEST_ASSERT_SUCCESS((num_to_process > info.drv.queue_size_lim),
3271 			"NUM_OPS cannot exceed %u for this device",
3272 			info.drv.queue_size_lim);
3273 
3274 	bufs = &tp->op_params->q_bufs[GET_SOCKET(info.socket_id)][queue_id];
3275 
3276 	__atomic_store_n(&tp->processing_status, 0, __ATOMIC_RELAXED);
3277 	__atomic_store_n(&tp->nb_dequeued, 0, __ATOMIC_RELAXED);
3278 
3279 	rte_wait_until_equal_16(&tp->op_params->sync, SYNC_START, __ATOMIC_RELAXED);
3280 
3281 	ret = rte_bbdev_enc_op_alloc_bulk(tp->op_params->mp, ops,
3282 			num_to_process);
3283 	TEST_ASSERT_SUCCESS(ret, "Allocation failed for %d ops",
3284 			num_to_process);
3285 	if (test_vector.op_type != RTE_BBDEV_OP_NONE)
3286 		copy_reference_enc_op(ops, num_to_process, 0, bufs->inputs,
3287 				bufs->hard_outputs, tp->op_params->ref_enc_op);
3288 
3289 	/* Set counter to validate the ordering */
3290 	for (j = 0; j < num_to_process; ++j)
3291 		ops[j]->opaque_data = (void *)(uintptr_t)j;
3292 
3293 	for (j = 0; j < TEST_REPETITIONS; ++j) {
3294 		for (i = 0; i < num_to_process; ++i)
3295 			rte_pktmbuf_reset(ops[i]->turbo_enc.output.data);
3296 
3297 		tp->start_time = rte_rdtsc_precise();
3298 		for (enqueued = 0; enqueued < num_to_process;) {
3299 			num_to_enq = burst_sz;
3300 
3301 			if (unlikely(num_to_process - enqueued < num_to_enq))
3302 				num_to_enq = num_to_process - enqueued;
3303 
3304 			enq = 0;
3305 			do {
3306 				enq += rte_bbdev_enqueue_enc_ops(tp->dev_id,
3307 						queue_id, &ops[enqueued],
3308 						num_to_enq);
3309 			} while (unlikely(enq != num_to_enq));
3310 			enqueued += enq;
3311 
3312 			/* Write to thread burst_sz current number of enqueued
3313 			 * descriptors. It ensures that proper number of
3314 			 * descriptors will be dequeued in callback
3315 			 * function - needed for last batch in case where
3316 			 * the number of operations is not a multiple of
3317 			 * burst size.
3318 			 */
3319 			__atomic_store_n(&tp->burst_sz, num_to_enq, __ATOMIC_RELAXED);
3320 
3321 			/* Wait until processing of previous batch is
3322 			 * completed
3323 			 */
3324 			rte_wait_until_equal_16(&tp->nb_dequeued, enqueued, __ATOMIC_RELAXED);
3325 		}
3326 		if (j != TEST_REPETITIONS - 1)
3327 			__atomic_store_n(&tp->nb_dequeued, 0, __ATOMIC_RELAXED);
3328 	}
3329 
3330 	return TEST_SUCCESS;
3331 }
3332 
3333 
3334 static int
3335 throughput_intr_lcore_ldpc_enc(void *arg)
3336 {
3337 	struct thread_params *tp = arg;
3338 	unsigned int enqueued;
3339 	const uint16_t queue_id = tp->queue_id;
3340 	const uint16_t burst_sz = tp->op_params->burst_sz;
3341 	const uint16_t num_to_process = tp->op_params->num_to_process;
3342 	struct rte_bbdev_enc_op *ops[num_to_process];
3343 	struct test_buffers *bufs = NULL;
3344 	struct rte_bbdev_info info;
3345 	int ret, i, j;
3346 	uint16_t num_to_enq, enq;
3347 
3348 	TEST_ASSERT_SUCCESS((burst_sz > MAX_BURST),
3349 			"BURST_SIZE should be <= %u", MAX_BURST);
3350 
3351 	TEST_ASSERT_SUCCESS(rte_bbdev_queue_intr_enable(tp->dev_id, queue_id),
3352 			"Failed to enable interrupts for dev: %u, queue_id: %u",
3353 			tp->dev_id, queue_id);
3354 
3355 	rte_bbdev_info_get(tp->dev_id, &info);
3356 
3357 	TEST_ASSERT_SUCCESS((num_to_process > info.drv.queue_size_lim),
3358 			"NUM_OPS cannot exceed %u for this device",
3359 			info.drv.queue_size_lim);
3360 
3361 	bufs = &tp->op_params->q_bufs[GET_SOCKET(info.socket_id)][queue_id];
3362 
3363 	__atomic_store_n(&tp->processing_status, 0, __ATOMIC_RELAXED);
3364 	__atomic_store_n(&tp->nb_dequeued, 0, __ATOMIC_RELAXED);
3365 
3366 	rte_wait_until_equal_16(&tp->op_params->sync, SYNC_START, __ATOMIC_RELAXED);
3367 
3368 	ret = rte_bbdev_enc_op_alloc_bulk(tp->op_params->mp, ops,
3369 			num_to_process);
3370 	TEST_ASSERT_SUCCESS(ret, "Allocation failed for %d ops",
3371 			num_to_process);
3372 	if (test_vector.op_type != RTE_BBDEV_OP_NONE)
3373 		copy_reference_ldpc_enc_op(ops, num_to_process, 0,
3374 				bufs->inputs, bufs->hard_outputs,
3375 				tp->op_params->ref_enc_op);
3376 
3377 	/* Set counter to validate the ordering */
3378 	for (j = 0; j < num_to_process; ++j)
3379 		ops[j]->opaque_data = (void *)(uintptr_t)j;
3380 
3381 	for (j = 0; j < TEST_REPETITIONS; ++j) {
3382 		for (i = 0; i < num_to_process; ++i)
3383 			rte_pktmbuf_reset(ops[i]->turbo_enc.output.data);
3384 
3385 		tp->start_time = rte_rdtsc_precise();
3386 		for (enqueued = 0; enqueued < num_to_process;) {
3387 			num_to_enq = burst_sz;
3388 
3389 			if (unlikely(num_to_process - enqueued < num_to_enq))
3390 				num_to_enq = num_to_process - enqueued;
3391 
3392 			enq = 0;
3393 			do {
3394 				enq += rte_bbdev_enqueue_ldpc_enc_ops(
3395 						tp->dev_id,
3396 						queue_id, &ops[enqueued],
3397 						num_to_enq);
3398 			} while (unlikely(enq != num_to_enq));
3399 			enqueued += enq;
3400 
3401 			/* Write to thread burst_sz current number of enqueued
3402 			 * descriptors. It ensures that proper number of
3403 			 * descriptors will be dequeued in callback
3404 			 * function - needed for last batch in case where
3405 			 * the number of operations is not a multiple of
3406 			 * burst size.
3407 			 */
3408 			__atomic_store_n(&tp->burst_sz, num_to_enq, __ATOMIC_RELAXED);
3409 
3410 			/* Wait until processing of previous batch is
3411 			 * completed
3412 			 */
3413 			rte_wait_until_equal_16(&tp->nb_dequeued, enqueued, __ATOMIC_RELAXED);
3414 		}
3415 		if (j != TEST_REPETITIONS - 1)
3416 			__atomic_store_n(&tp->nb_dequeued, 0, __ATOMIC_RELAXED);
3417 	}
3418 
3419 	return TEST_SUCCESS;
3420 }
3421 
3422 
3423 static int
3424 throughput_intr_lcore_fft(void *arg)
3425 {
3426 	struct thread_params *tp = arg;
3427 	unsigned int enqueued;
3428 	const uint16_t queue_id = tp->queue_id;
3429 	const uint16_t burst_sz = tp->op_params->burst_sz;
3430 	const uint16_t num_to_process = tp->op_params->num_to_process;
3431 	struct rte_bbdev_fft_op *ops[num_to_process];
3432 	struct test_buffers *bufs = NULL;
3433 	struct rte_bbdev_info info;
3434 	int ret, i, j;
3435 	uint16_t num_to_enq, enq;
3436 
3437 	TEST_ASSERT_SUCCESS((burst_sz > MAX_BURST),
3438 			"BURST_SIZE should be <= %u", MAX_BURST);
3439 
3440 	TEST_ASSERT_SUCCESS(rte_bbdev_queue_intr_enable(tp->dev_id, queue_id),
3441 			"Failed to enable interrupts for dev: %u, queue_id: %u",
3442 			tp->dev_id, queue_id);
3443 
3444 	rte_bbdev_info_get(tp->dev_id, &info);
3445 
3446 	TEST_ASSERT_SUCCESS((num_to_process > info.drv.queue_size_lim),
3447 			"NUM_OPS cannot exceed %u for this device",
3448 			info.drv.queue_size_lim);
3449 
3450 	bufs = &tp->op_params->q_bufs[GET_SOCKET(info.socket_id)][queue_id];
3451 
3452 	__atomic_store_n(&tp->processing_status, 0, __ATOMIC_RELAXED);
3453 	__atomic_store_n(&tp->nb_dequeued, 0, __ATOMIC_RELAXED);
3454 
3455 	rte_wait_until_equal_16(&tp->op_params->sync, SYNC_START, __ATOMIC_RELAXED);
3456 
3457 	ret = rte_bbdev_fft_op_alloc_bulk(tp->op_params->mp, ops,
3458 			num_to_process);
3459 	TEST_ASSERT_SUCCESS(ret, "Allocation failed for %d ops",
3460 			num_to_process);
3461 	if (test_vector.op_type != RTE_BBDEV_OP_NONE)
3462 		copy_reference_fft_op(ops, num_to_process, 0, bufs->inputs,
3463 				bufs->hard_outputs, bufs->soft_outputs, tp->op_params->ref_fft_op);
3464 
3465 	/* Set counter to validate the ordering */
3466 	for (j = 0; j < num_to_process; ++j)
3467 		ops[j]->opaque_data = (void *)(uintptr_t)j;
3468 
3469 	for (j = 0; j < TEST_REPETITIONS; ++j) {
3470 		for (i = 0; i < num_to_process; ++i)
3471 			rte_pktmbuf_reset(ops[i]->fft.base_output.data);
3472 
3473 		tp->start_time = rte_rdtsc_precise();
3474 		for (enqueued = 0; enqueued < num_to_process;) {
3475 			num_to_enq = burst_sz;
3476 
3477 			if (unlikely(num_to_process - enqueued < num_to_enq))
3478 				num_to_enq = num_to_process - enqueued;
3479 
3480 			enq = 0;
3481 			do {
3482 				enq += rte_bbdev_enqueue_fft_ops(tp->dev_id,
3483 						queue_id, &ops[enqueued],
3484 						num_to_enq);
3485 			} while (unlikely(enq != num_to_enq));
3486 			enqueued += enq;
3487 
3488 			/* Write to thread burst_sz current number of enqueued
3489 			 * descriptors. It ensures that proper number of
3490 			 * descriptors will be dequeued in callback
3491 			 * function - needed for last batch in case where
3492 			 * the number of operations is not a multiple of
3493 			 * burst size.
3494 			 */
3495 			__atomic_store_n(&tp->burst_sz, num_to_enq, __ATOMIC_RELAXED);
3496 
3497 			/* Wait until processing of previous batch is
3498 			 * completed
3499 			 */
3500 			rte_wait_until_equal_16(&tp->nb_dequeued, enqueued, __ATOMIC_RELAXED);
3501 		}
3502 		if (j != TEST_REPETITIONS - 1)
3503 			__atomic_store_n(&tp->nb_dequeued, 0, __ATOMIC_RELAXED);
3504 	}
3505 
3506 	return TEST_SUCCESS;
3507 }
3508 
3509 static int
3510 throughput_pmd_lcore_dec(void *arg)
3511 {
3512 	struct thread_params *tp = arg;
3513 	uint16_t enq, deq;
3514 	uint64_t total_time = 0, start_time;
3515 	const uint16_t queue_id = tp->queue_id;
3516 	const uint16_t burst_sz = tp->op_params->burst_sz;
3517 	const uint16_t num_ops = tp->op_params->num_to_process;
3518 	struct rte_bbdev_dec_op *ops_enq[num_ops];
3519 	struct rte_bbdev_dec_op *ops_deq[num_ops];
3520 	struct rte_bbdev_dec_op *ref_op = tp->op_params->ref_dec_op;
3521 	struct test_buffers *bufs = NULL;
3522 	int i, j, ret;
3523 	struct rte_bbdev_info info;
3524 	uint16_t num_to_enq;
3525 	bool so_enable;
3526 
3527 	TEST_ASSERT_SUCCESS((burst_sz > MAX_BURST),
3528 			"BURST_SIZE should be <= %u", MAX_BURST);
3529 
3530 	rte_bbdev_info_get(tp->dev_id, &info);
3531 
3532 	TEST_ASSERT_SUCCESS((num_ops > info.drv.queue_size_lim),
3533 			"NUM_OPS cannot exceed %u for this device",
3534 			info.drv.queue_size_lim);
3535 
3536 	bufs = &tp->op_params->q_bufs[GET_SOCKET(info.socket_id)][queue_id];
3537 
3538 	rte_wait_until_equal_16(&tp->op_params->sync, SYNC_START, __ATOMIC_RELAXED);
3539 
3540 	ret = rte_bbdev_dec_op_alloc_bulk(tp->op_params->mp, ops_enq, num_ops);
3541 	TEST_ASSERT_SUCCESS(ret, "Allocation failed for %d ops", num_ops);
3542 	ref_op->turbo_dec.iter_max = get_iter_max();
3543 	if (test_vector.op_type != RTE_BBDEV_OP_NONE)
3544 		copy_reference_dec_op(ops_enq, num_ops, 0, bufs->inputs,
3545 				bufs->hard_outputs, bufs->soft_outputs, ref_op);
3546 
3547 	so_enable = check_bit(ops_enq[0]->turbo_dec.op_flags, RTE_BBDEV_TURBO_SOFT_OUTPUT);
3548 
3549 	/* Set counter to validate the ordering */
3550 	for (j = 0; j < num_ops; ++j)
3551 		ops_enq[j]->opaque_data = (void *)(uintptr_t)j;
3552 
3553 	for (i = 0; i < TEST_REPETITIONS; ++i) {
3554 
3555 		for (j = 0; j < num_ops; ++j)
3556 			mbuf_reset(ops_enq[j]->turbo_dec.hard_output.data);
3557 		if (so_enable)
3558 			for (j = 0; j < num_ops; ++j)
3559 				mbuf_reset(ops_enq[j]->turbo_dec.soft_output.data);
3560 
3561 		start_time = rte_rdtsc_precise();
3562 
3563 		for (enq = 0, deq = 0; enq < num_ops;) {
3564 			num_to_enq = burst_sz;
3565 
3566 			if (unlikely(num_ops - enq < num_to_enq))
3567 				num_to_enq = num_ops - enq;
3568 
3569 			enq += rte_bbdev_enqueue_dec_ops(tp->dev_id,
3570 					queue_id, &ops_enq[enq], num_to_enq);
3571 
3572 			deq += rte_bbdev_dequeue_dec_ops(tp->dev_id,
3573 					queue_id, &ops_deq[deq], enq - deq);
3574 		}
3575 
3576 		/* dequeue the remaining */
3577 		while (deq < enq) {
3578 			deq += rte_bbdev_dequeue_dec_ops(tp->dev_id,
3579 					queue_id, &ops_deq[deq], enq - deq);
3580 		}
3581 
3582 		total_time += rte_rdtsc_precise() - start_time;
3583 	}
3584 
3585 	tp->iter_count = 0;
3586 	/* get the max of iter_count for all dequeued ops */
3587 	for (i = 0; i < num_ops; ++i) {
3588 		tp->iter_count = RTE_MAX(ops_enq[i]->turbo_dec.iter_count,
3589 				tp->iter_count);
3590 	}
3591 
3592 	if (test_vector.op_type != RTE_BBDEV_OP_NONE) {
3593 		ret = validate_dec_op(ops_deq, num_ops, ref_op,
3594 				tp->op_params->vector_mask);
3595 		TEST_ASSERT_SUCCESS(ret, "Validation failed!");
3596 	}
3597 
3598 	rte_bbdev_dec_op_free_bulk(ops_enq, num_ops);
3599 
3600 	double tb_len_bits = calc_dec_TB_size(ref_op);
3601 
3602 	tp->ops_per_sec = ((double)num_ops * TEST_REPETITIONS) /
3603 			((double)total_time / (double)rte_get_tsc_hz());
3604 	tp->mbps = (((double)(num_ops * TEST_REPETITIONS * tb_len_bits)) /
3605 			1000000.0) / ((double)total_time /
3606 			(double)rte_get_tsc_hz());
3607 
3608 	return TEST_SUCCESS;
3609 }
3610 
3611 static int
3612 bler_pmd_lcore_ldpc_dec(void *arg)
3613 {
3614 	struct thread_params *tp = arg;
3615 	uint16_t enq, deq;
3616 	uint64_t total_time = 0, start_time;
3617 	const uint16_t queue_id = tp->queue_id;
3618 	const uint16_t burst_sz = tp->op_params->burst_sz;
3619 	const uint16_t num_ops = tp->op_params->num_to_process;
3620 	struct rte_bbdev_dec_op *ops_enq[num_ops];
3621 	struct rte_bbdev_dec_op *ops_deq[num_ops];
3622 	struct rte_bbdev_dec_op *ref_op = tp->op_params->ref_dec_op;
3623 	struct test_buffers *bufs = NULL;
3624 	int i, j, ret;
3625 	float parity_bler = 0;
3626 	struct rte_bbdev_info info;
3627 	uint16_t num_to_enq;
3628 	bool extDdr = check_bit(ldpc_cap_flags,
3629 			RTE_BBDEV_LDPC_INTERNAL_HARQ_MEMORY_OUT_ENABLE);
3630 	bool loopback = check_bit(ref_op->ldpc_dec.op_flags,
3631 			RTE_BBDEV_LDPC_INTERNAL_HARQ_MEMORY_LOOPBACK);
3632 	bool hc_out = check_bit(ref_op->ldpc_dec.op_flags,
3633 			RTE_BBDEV_LDPC_HQ_COMBINE_OUT_ENABLE);
3634 
3635 	TEST_ASSERT_SUCCESS((burst_sz > MAX_BURST),
3636 			"BURST_SIZE should be <= %u", MAX_BURST);
3637 
3638 	rte_bbdev_info_get(tp->dev_id, &info);
3639 
3640 	TEST_ASSERT_SUCCESS((num_ops > info.drv.queue_size_lim),
3641 			"NUM_OPS cannot exceed %u for this device",
3642 			info.drv.queue_size_lim);
3643 
3644 	bufs = &tp->op_params->q_bufs[GET_SOCKET(info.socket_id)][queue_id];
3645 
3646 	rte_wait_until_equal_16(&tp->op_params->sync, SYNC_START, __ATOMIC_RELAXED);
3647 
3648 	ret = rte_bbdev_dec_op_alloc_bulk(tp->op_params->mp, ops_enq, num_ops);
3649 	TEST_ASSERT_SUCCESS(ret, "Allocation failed for %d ops", num_ops);
3650 
3651 	/* For BLER tests we need to enable early termination */
3652 	if (!check_bit(ref_op->ldpc_dec.op_flags,
3653 			RTE_BBDEV_LDPC_ITERATION_STOP_ENABLE))
3654 		ref_op->ldpc_dec.op_flags +=
3655 				RTE_BBDEV_LDPC_ITERATION_STOP_ENABLE;
3656 	ref_op->ldpc_dec.iter_max = get_iter_max();
3657 	ref_op->ldpc_dec.iter_count = ref_op->ldpc_dec.iter_max;
3658 
3659 	if (test_vector.op_type != RTE_BBDEV_OP_NONE)
3660 		copy_reference_ldpc_dec_op(ops_enq, num_ops, 0, bufs->inputs,
3661 				bufs->hard_outputs, bufs->soft_outputs,
3662 				bufs->harq_inputs, bufs->harq_outputs, ref_op);
3663 	generate_llr_input(num_ops, bufs->inputs, ref_op);
3664 
3665 	/* Set counter to validate the ordering */
3666 	for (j = 0; j < num_ops; ++j)
3667 		ops_enq[j]->opaque_data = (void *)(uintptr_t)j;
3668 
3669 	for (i = 0; i < 1; ++i) { /* Could add more iterations */
3670 		for (j = 0; j < num_ops; ++j) {
3671 			if (!loopback)
3672 				mbuf_reset(
3673 				ops_enq[j]->ldpc_dec.hard_output.data);
3674 			if (hc_out || loopback)
3675 				mbuf_reset(ops_enq[j]->ldpc_dec.harq_combined_output.data);
3676 		}
3677 		if (extDdr)
3678 			preload_harq_ddr(tp->dev_id, queue_id, ops_enq,
3679 					num_ops, true);
3680 		start_time = rte_rdtsc_precise();
3681 
3682 		for (enq = 0, deq = 0; enq < num_ops;) {
3683 			num_to_enq = burst_sz;
3684 
3685 			if (unlikely(num_ops - enq < num_to_enq))
3686 				num_to_enq = num_ops - enq;
3687 
3688 			enq += rte_bbdev_enqueue_ldpc_dec_ops(tp->dev_id,
3689 					queue_id, &ops_enq[enq], num_to_enq);
3690 
3691 			deq += rte_bbdev_dequeue_ldpc_dec_ops(tp->dev_id,
3692 					queue_id, &ops_deq[deq], enq - deq);
3693 		}
3694 
3695 		/* dequeue the remaining */
3696 		while (deq < enq) {
3697 			deq += rte_bbdev_dequeue_ldpc_dec_ops(tp->dev_id,
3698 					queue_id, &ops_deq[deq], enq - deq);
3699 		}
3700 
3701 		total_time += rte_rdtsc_precise() - start_time;
3702 	}
3703 
3704 	tp->iter_count = 0;
3705 	tp->iter_average = 0;
3706 	/* get the max of iter_count for all dequeued ops */
3707 	for (i = 0; i < num_ops; ++i) {
3708 		tp->iter_count = RTE_MAX(ops_enq[i]->ldpc_dec.iter_count,
3709 				tp->iter_count);
3710 		tp->iter_average += (double) ops_enq[i]->ldpc_dec.iter_count;
3711 		if (ops_enq[i]->status & (1 << RTE_BBDEV_SYNDROME_ERROR))
3712 			parity_bler += 1.0;
3713 	}
3714 
3715 	parity_bler /= num_ops; /* This one is based on SYND */
3716 	tp->iter_average /= num_ops;
3717 	tp->bler = (double) validate_ldpc_bler(ops_deq, num_ops) / num_ops;
3718 
3719 	if (test_vector.op_type != RTE_BBDEV_OP_NONE
3720 			&& tp->bler == 0
3721 			&& parity_bler == 0
3722 			&& !hc_out) {
3723 		ret = validate_ldpc_dec_op(ops_deq, num_ops, ref_op,
3724 				tp->op_params->vector_mask);
3725 		TEST_ASSERT_SUCCESS(ret, "Validation failed!");
3726 	}
3727 
3728 	rte_bbdev_dec_op_free_bulk(ops_enq, num_ops);
3729 
3730 	double tb_len_bits = calc_ldpc_dec_TB_size(ref_op);
3731 	tp->ops_per_sec = ((double)num_ops * 1) /
3732 			((double)total_time / (double)rte_get_tsc_hz());
3733 	tp->mbps = (((double)(num_ops * 1 * tb_len_bits)) /
3734 			1000000.0) / ((double)total_time /
3735 			(double)rte_get_tsc_hz());
3736 
3737 	return TEST_SUCCESS;
3738 }
3739 
3740 static int
3741 throughput_pmd_lcore_ldpc_dec(void *arg)
3742 {
3743 	struct thread_params *tp = arg;
3744 	uint16_t enq, deq;
3745 	uint64_t total_time = 0, start_time;
3746 	const uint16_t queue_id = tp->queue_id;
3747 	const uint16_t burst_sz = tp->op_params->burst_sz;
3748 	const uint16_t num_ops = tp->op_params->num_to_process;
3749 	struct rte_bbdev_dec_op *ops_enq[num_ops];
3750 	struct rte_bbdev_dec_op *ops_deq[num_ops];
3751 	struct rte_bbdev_dec_op *ref_op = tp->op_params->ref_dec_op;
3752 	struct test_buffers *bufs = NULL;
3753 	int i, j, ret;
3754 	struct rte_bbdev_info info;
3755 	uint16_t num_to_enq;
3756 	bool extDdr = check_bit(ldpc_cap_flags,
3757 			RTE_BBDEV_LDPC_INTERNAL_HARQ_MEMORY_OUT_ENABLE);
3758 	bool loopback = check_bit(ref_op->ldpc_dec.op_flags,
3759 			RTE_BBDEV_LDPC_INTERNAL_HARQ_MEMORY_LOOPBACK);
3760 	bool hc_out = check_bit(ref_op->ldpc_dec.op_flags,
3761 			RTE_BBDEV_LDPC_HQ_COMBINE_OUT_ENABLE);
3762 
3763 	TEST_ASSERT_SUCCESS((burst_sz > MAX_BURST),
3764 			"BURST_SIZE should be <= %u", MAX_BURST);
3765 
3766 	rte_bbdev_info_get(tp->dev_id, &info);
3767 
3768 	TEST_ASSERT_SUCCESS((num_ops > info.drv.queue_size_lim),
3769 			"NUM_OPS cannot exceed %u for this device",
3770 			info.drv.queue_size_lim);
3771 
3772 	bufs = &tp->op_params->q_bufs[GET_SOCKET(info.socket_id)][queue_id];
3773 
3774 	rte_wait_until_equal_16(&tp->op_params->sync, SYNC_START, __ATOMIC_RELAXED);
3775 
3776 	ret = rte_bbdev_dec_op_alloc_bulk(tp->op_params->mp, ops_enq, num_ops);
3777 	TEST_ASSERT_SUCCESS(ret, "Allocation failed for %d ops", num_ops);
3778 
3779 	/* For throughput tests we need to disable early termination */
3780 	if (check_bit(ref_op->ldpc_dec.op_flags,
3781 			RTE_BBDEV_LDPC_ITERATION_STOP_ENABLE))
3782 		ref_op->ldpc_dec.op_flags -=
3783 				RTE_BBDEV_LDPC_ITERATION_STOP_ENABLE;
3784 	ref_op->ldpc_dec.iter_max = get_iter_max();
3785 	ref_op->ldpc_dec.iter_count = ref_op->ldpc_dec.iter_max;
3786 
3787 	if (test_vector.op_type != RTE_BBDEV_OP_NONE)
3788 		copy_reference_ldpc_dec_op(ops_enq, num_ops, 0, bufs->inputs,
3789 				bufs->hard_outputs, bufs->soft_outputs,
3790 				bufs->harq_inputs, bufs->harq_outputs, ref_op);
3791 
3792 	/* Set counter to validate the ordering */
3793 	for (j = 0; j < num_ops; ++j)
3794 		ops_enq[j]->opaque_data = (void *)(uintptr_t)j;
3795 
3796 	for (i = 0; i < TEST_REPETITIONS; ++i) {
3797 		for (j = 0; j < num_ops; ++j) {
3798 			if (!loopback)
3799 				mbuf_reset(
3800 				ops_enq[j]->ldpc_dec.hard_output.data);
3801 			if (hc_out || loopback)
3802 				mbuf_reset(
3803 				ops_enq[j]->ldpc_dec.harq_combined_output.data);
3804 		}
3805 		if (extDdr)
3806 			preload_harq_ddr(tp->dev_id, queue_id, ops_enq,
3807 					num_ops, true);
3808 		start_time = rte_rdtsc_precise();
3809 
3810 		for (enq = 0, deq = 0; enq < num_ops;) {
3811 			num_to_enq = burst_sz;
3812 
3813 			if (unlikely(num_ops - enq < num_to_enq))
3814 				num_to_enq = num_ops - enq;
3815 
3816 			enq += rte_bbdev_enqueue_ldpc_dec_ops(tp->dev_id,
3817 					queue_id, &ops_enq[enq], num_to_enq);
3818 
3819 			deq += rte_bbdev_dequeue_ldpc_dec_ops(tp->dev_id,
3820 					queue_id, &ops_deq[deq], enq - deq);
3821 		}
3822 
3823 		/* dequeue the remaining */
3824 		while (deq < enq) {
3825 			deq += rte_bbdev_dequeue_ldpc_dec_ops(tp->dev_id,
3826 					queue_id, &ops_deq[deq], enq - deq);
3827 		}
3828 
3829 		total_time += rte_rdtsc_precise() - start_time;
3830 	}
3831 
3832 	tp->iter_count = 0;
3833 	/* get the max of iter_count for all dequeued ops */
3834 	for (i = 0; i < num_ops; ++i) {
3835 		tp->iter_count = RTE_MAX(ops_enq[i]->ldpc_dec.iter_count,
3836 				tp->iter_count);
3837 	}
3838 	if (extDdr) {
3839 		/* Read loopback is not thread safe */
3840 		retrieve_harq_ddr(tp->dev_id, queue_id, ops_enq, num_ops);
3841 	}
3842 
3843 	if (test_vector.op_type != RTE_BBDEV_OP_NONE) {
3844 		ret = validate_ldpc_dec_op(ops_deq, num_ops, ref_op,
3845 				tp->op_params->vector_mask);
3846 		TEST_ASSERT_SUCCESS(ret, "Validation failed!");
3847 	}
3848 
3849 	rte_bbdev_dec_op_free_bulk(ops_enq, num_ops);
3850 
3851 	double tb_len_bits = calc_ldpc_dec_TB_size(ref_op);
3852 
3853 	tp->ops_per_sec = ((double)num_ops * TEST_REPETITIONS) /
3854 			((double)total_time / (double)rte_get_tsc_hz());
3855 	tp->mbps = (((double)(num_ops * TEST_REPETITIONS * tb_len_bits)) /
3856 			1000000.0) / ((double)total_time /
3857 			(double)rte_get_tsc_hz());
3858 
3859 	return TEST_SUCCESS;
3860 }
3861 
3862 static int
3863 throughput_pmd_lcore_enc(void *arg)
3864 {
3865 	struct thread_params *tp = arg;
3866 	uint16_t enq, deq;
3867 	uint64_t total_time = 0, start_time;
3868 	const uint16_t queue_id = tp->queue_id;
3869 	const uint16_t burst_sz = tp->op_params->burst_sz;
3870 	const uint16_t num_ops = tp->op_params->num_to_process;
3871 	struct rte_bbdev_enc_op *ops_enq[num_ops];
3872 	struct rte_bbdev_enc_op *ops_deq[num_ops];
3873 	struct rte_bbdev_enc_op *ref_op = tp->op_params->ref_enc_op;
3874 	struct test_buffers *bufs = NULL;
3875 	int i, j, ret;
3876 	struct rte_bbdev_info info;
3877 	uint16_t num_to_enq;
3878 
3879 	TEST_ASSERT_SUCCESS((burst_sz > MAX_BURST),
3880 			"BURST_SIZE should be <= %u", MAX_BURST);
3881 
3882 	rte_bbdev_info_get(tp->dev_id, &info);
3883 
3884 	TEST_ASSERT_SUCCESS((num_ops > info.drv.queue_size_lim),
3885 			"NUM_OPS cannot exceed %u for this device",
3886 			info.drv.queue_size_lim);
3887 
3888 	bufs = &tp->op_params->q_bufs[GET_SOCKET(info.socket_id)][queue_id];
3889 
3890 	rte_wait_until_equal_16(&tp->op_params->sync, SYNC_START, __ATOMIC_RELAXED);
3891 
3892 	ret = rte_bbdev_enc_op_alloc_bulk(tp->op_params->mp, ops_enq,
3893 			num_ops);
3894 	TEST_ASSERT_SUCCESS(ret, "Allocation failed for %d ops",
3895 			num_ops);
3896 	if (test_vector.op_type != RTE_BBDEV_OP_NONE)
3897 		copy_reference_enc_op(ops_enq, num_ops, 0, bufs->inputs,
3898 				bufs->hard_outputs, ref_op);
3899 
3900 	/* Set counter to validate the ordering */
3901 	for (j = 0; j < num_ops; ++j)
3902 		ops_enq[j]->opaque_data = (void *)(uintptr_t)j;
3903 
3904 	for (i = 0; i < TEST_REPETITIONS; ++i) {
3905 
3906 		if (test_vector.op_type != RTE_BBDEV_OP_NONE)
3907 			for (j = 0; j < num_ops; ++j)
3908 				mbuf_reset(ops_enq[j]->turbo_enc.output.data);
3909 
3910 		start_time = rte_rdtsc_precise();
3911 
3912 		for (enq = 0, deq = 0; enq < num_ops;) {
3913 			num_to_enq = burst_sz;
3914 
3915 			if (unlikely(num_ops - enq < num_to_enq))
3916 				num_to_enq = num_ops - enq;
3917 
3918 			enq += rte_bbdev_enqueue_enc_ops(tp->dev_id,
3919 					queue_id, &ops_enq[enq], num_to_enq);
3920 
3921 			deq += rte_bbdev_dequeue_enc_ops(tp->dev_id,
3922 					queue_id, &ops_deq[deq], enq - deq);
3923 		}
3924 
3925 		/* dequeue the remaining */
3926 		while (deq < enq) {
3927 			deq += rte_bbdev_dequeue_enc_ops(tp->dev_id,
3928 					queue_id, &ops_deq[deq], enq - deq);
3929 		}
3930 
3931 		total_time += rte_rdtsc_precise() - start_time;
3932 	}
3933 
3934 	if (test_vector.op_type != RTE_BBDEV_OP_NONE) {
3935 		ret = validate_enc_op(ops_deq, num_ops, ref_op);
3936 		TEST_ASSERT_SUCCESS(ret, "Validation failed!");
3937 	}
3938 
3939 	rte_bbdev_enc_op_free_bulk(ops_enq, num_ops);
3940 
3941 	double tb_len_bits = calc_enc_TB_size(ref_op);
3942 
3943 	tp->ops_per_sec = ((double)num_ops * TEST_REPETITIONS) /
3944 			((double)total_time / (double)rte_get_tsc_hz());
3945 	tp->mbps = (((double)(num_ops * TEST_REPETITIONS * tb_len_bits))
3946 			/ 1000000.0) / ((double)total_time /
3947 			(double)rte_get_tsc_hz());
3948 
3949 	return TEST_SUCCESS;
3950 }
3951 
3952 static int
3953 throughput_pmd_lcore_ldpc_enc(void *arg)
3954 {
3955 	struct thread_params *tp = arg;
3956 	uint16_t enq, deq;
3957 	uint64_t total_time = 0, start_time;
3958 	const uint16_t queue_id = tp->queue_id;
3959 	const uint16_t burst_sz = tp->op_params->burst_sz;
3960 	const uint16_t num_ops = tp->op_params->num_to_process;
3961 	struct rte_bbdev_enc_op *ops_enq[num_ops];
3962 	struct rte_bbdev_enc_op *ops_deq[num_ops];
3963 	struct rte_bbdev_enc_op *ref_op = tp->op_params->ref_enc_op;
3964 	struct test_buffers *bufs = NULL;
3965 	int i, j, ret;
3966 	struct rte_bbdev_info info;
3967 	uint16_t num_to_enq;
3968 
3969 	TEST_ASSERT_SUCCESS((burst_sz > MAX_BURST),
3970 			"BURST_SIZE should be <= %u", MAX_BURST);
3971 
3972 	rte_bbdev_info_get(tp->dev_id, &info);
3973 
3974 	TEST_ASSERT_SUCCESS((num_ops > info.drv.queue_size_lim),
3975 			"NUM_OPS cannot exceed %u for this device",
3976 			info.drv.queue_size_lim);
3977 
3978 	bufs = &tp->op_params->q_bufs[GET_SOCKET(info.socket_id)][queue_id];
3979 
3980 	rte_wait_until_equal_16(&tp->op_params->sync, SYNC_START, __ATOMIC_RELAXED);
3981 
3982 	ret = rte_bbdev_enc_op_alloc_bulk(tp->op_params->mp, ops_enq,
3983 			num_ops);
3984 	TEST_ASSERT_SUCCESS(ret, "Allocation failed for %d ops",
3985 			num_ops);
3986 	if (test_vector.op_type != RTE_BBDEV_OP_NONE)
3987 		copy_reference_ldpc_enc_op(ops_enq, num_ops, 0, bufs->inputs,
3988 				bufs->hard_outputs, ref_op);
3989 
3990 	/* Set counter to validate the ordering */
3991 	for (j = 0; j < num_ops; ++j)
3992 		ops_enq[j]->opaque_data = (void *)(uintptr_t)j;
3993 
3994 	for (i = 0; i < TEST_REPETITIONS; ++i) {
3995 
3996 		if (test_vector.op_type != RTE_BBDEV_OP_NONE)
3997 			for (j = 0; j < num_ops; ++j)
3998 				mbuf_reset(ops_enq[j]->turbo_enc.output.data);
3999 
4000 		start_time = rte_rdtsc_precise();
4001 
4002 		for (enq = 0, deq = 0; enq < num_ops;) {
4003 			num_to_enq = burst_sz;
4004 
4005 			if (unlikely(num_ops - enq < num_to_enq))
4006 				num_to_enq = num_ops - enq;
4007 
4008 			enq += rte_bbdev_enqueue_ldpc_enc_ops(tp->dev_id,
4009 					queue_id, &ops_enq[enq], num_to_enq);
4010 
4011 			deq += rte_bbdev_dequeue_ldpc_enc_ops(tp->dev_id,
4012 					queue_id, &ops_deq[deq], enq - deq);
4013 		}
4014 
4015 		/* dequeue the remaining */
4016 		while (deq < enq) {
4017 			deq += rte_bbdev_dequeue_ldpc_enc_ops(tp->dev_id,
4018 					queue_id, &ops_deq[deq], enq - deq);
4019 		}
4020 
4021 		total_time += rte_rdtsc_precise() - start_time;
4022 	}
4023 
4024 	if (test_vector.op_type != RTE_BBDEV_OP_NONE) {
4025 		ret = validate_ldpc_enc_op(ops_deq, num_ops, ref_op);
4026 		TEST_ASSERT_SUCCESS(ret, "Validation failed!");
4027 	}
4028 
4029 	rte_bbdev_enc_op_free_bulk(ops_enq, num_ops);
4030 
4031 	double tb_len_bits = calc_ldpc_enc_TB_size(ref_op);
4032 
4033 	tp->ops_per_sec = ((double)num_ops * TEST_REPETITIONS) /
4034 			((double)total_time / (double)rte_get_tsc_hz());
4035 	tp->mbps = (((double)(num_ops * TEST_REPETITIONS * tb_len_bits))
4036 			/ 1000000.0) / ((double)total_time /
4037 			(double)rte_get_tsc_hz());
4038 
4039 	return TEST_SUCCESS;
4040 }
4041 
4042 static int
4043 throughput_pmd_lcore_fft(void *arg)
4044 {
4045 	struct thread_params *tp = arg;
4046 	uint16_t enq, deq;
4047 	uint64_t total_time = 0, start_time;
4048 	const uint16_t queue_id = tp->queue_id;
4049 	const uint16_t burst_sz = tp->op_params->burst_sz;
4050 	const uint16_t num_ops = tp->op_params->num_to_process;
4051 	struct rte_bbdev_fft_op *ops_enq[num_ops];
4052 	struct rte_bbdev_fft_op *ops_deq[num_ops];
4053 	struct rte_bbdev_fft_op *ref_op = tp->op_params->ref_fft_op;
4054 	struct test_buffers *bufs = NULL;
4055 	int i, j, ret;
4056 	struct rte_bbdev_info info;
4057 	uint16_t num_to_enq;
4058 
4059 	TEST_ASSERT_SUCCESS((burst_sz > MAX_BURST),
4060 			"BURST_SIZE should be <= %u", MAX_BURST);
4061 
4062 	rte_bbdev_info_get(tp->dev_id, &info);
4063 
4064 	TEST_ASSERT_SUCCESS((num_ops > info.drv.queue_size_lim),
4065 			"NUM_OPS cannot exceed %u for this device",
4066 			info.drv.queue_size_lim);
4067 
4068 	bufs = &tp->op_params->q_bufs[GET_SOCKET(info.socket_id)][queue_id];
4069 
4070 	rte_wait_until_equal_16(&tp->op_params->sync, SYNC_START, __ATOMIC_RELAXED);
4071 
4072 	ret = rte_bbdev_fft_op_alloc_bulk(tp->op_params->mp, ops_enq, num_ops);
4073 	TEST_ASSERT_SUCCESS(ret, "Allocation failed for %d ops", num_ops);
4074 
4075 	if (test_vector.op_type != RTE_BBDEV_OP_NONE)
4076 		copy_reference_fft_op(ops_enq, num_ops, 0, bufs->inputs,
4077 				bufs->hard_outputs, bufs->soft_outputs, ref_op);
4078 
4079 	/* Set counter to validate the ordering */
4080 	for (j = 0; j < num_ops; ++j)
4081 		ops_enq[j]->opaque_data = (void *)(uintptr_t)j;
4082 
4083 	for (i = 0; i < TEST_REPETITIONS; ++i) {
4084 
4085 		for (j = 0; j < num_ops; ++j)
4086 			mbuf_reset(ops_enq[j]->fft.base_output.data);
4087 
4088 		start_time = rte_rdtsc_precise();
4089 
4090 		for (enq = 0, deq = 0; enq < num_ops;) {
4091 			num_to_enq = burst_sz;
4092 
4093 			if (unlikely(num_ops - enq < num_to_enq))
4094 				num_to_enq = num_ops - enq;
4095 
4096 			enq += rte_bbdev_enqueue_fft_ops(tp->dev_id,
4097 					queue_id, &ops_enq[enq], num_to_enq);
4098 
4099 			deq += rte_bbdev_dequeue_fft_ops(tp->dev_id,
4100 					queue_id, &ops_deq[deq], enq - deq);
4101 		}
4102 
4103 		/* dequeue the remaining */
4104 		while (deq < enq) {
4105 			deq += rte_bbdev_dequeue_fft_ops(tp->dev_id,
4106 					queue_id, &ops_deq[deq], enq - deq);
4107 		}
4108 
4109 		total_time += rte_rdtsc_precise() - start_time;
4110 	}
4111 
4112 	if (test_vector.op_type != RTE_BBDEV_OP_NONE) {
4113 		ret = validate_fft_op(ops_deq, num_ops, ref_op);
4114 		TEST_ASSERT_SUCCESS(ret, "Validation failed!");
4115 	}
4116 
4117 	rte_bbdev_fft_op_free_bulk(ops_enq, num_ops);
4118 
4119 	double tb_len_bits = calc_fft_size(ref_op);
4120 
4121 	tp->ops_per_sec = ((double)num_ops * TEST_REPETITIONS) /
4122 			((double)total_time / (double)rte_get_tsc_hz());
4123 	tp->mbps = (((double)(num_ops * TEST_REPETITIONS * tb_len_bits)) /
4124 			1000000.0) / ((double)total_time /
4125 			(double)rte_get_tsc_hz());
4126 
4127 	return TEST_SUCCESS;
4128 }
4129 
4130 static void
4131 print_enc_throughput(struct thread_params *t_params, unsigned int used_cores)
4132 {
4133 	unsigned int iter = 0;
4134 	double total_mops = 0, total_mbps = 0;
4135 
4136 	for (iter = 0; iter < used_cores; iter++) {
4137 		printf(
4138 			"Throughput for core (%u): %.8lg Ops/s, %.8lg Mbps\n",
4139 			t_params[iter].lcore_id, t_params[iter].ops_per_sec,
4140 			t_params[iter].mbps);
4141 		total_mops += t_params[iter].ops_per_sec;
4142 		total_mbps += t_params[iter].mbps;
4143 	}
4144 	printf(
4145 		"\nTotal throughput for %u cores: %.8lg MOPS, %.8lg Mbps\n",
4146 		used_cores, total_mops, total_mbps);
4147 }
4148 
4149 /* Aggregate the performance results over the number of cores used */
4150 static void
4151 print_dec_throughput(struct thread_params *t_params, unsigned int used_cores)
4152 {
4153 	unsigned int core_idx = 0;
4154 	double total_mops = 0, total_mbps = 0;
4155 	uint8_t iter_count = 0;
4156 
4157 	for (core_idx = 0; core_idx < used_cores; core_idx++) {
4158 		printf(
4159 			"Throughput for core (%u): %.8lg Ops/s, %.8lg Mbps @ max %u iterations\n",
4160 			t_params[core_idx].lcore_id,
4161 			t_params[core_idx].ops_per_sec,
4162 			t_params[core_idx].mbps,
4163 			t_params[core_idx].iter_count);
4164 		total_mops += t_params[core_idx].ops_per_sec;
4165 		total_mbps += t_params[core_idx].mbps;
4166 		iter_count = RTE_MAX(iter_count,
4167 				t_params[core_idx].iter_count);
4168 	}
4169 	printf(
4170 		"\nTotal throughput for %u cores: %.8lg MOPS, %.8lg Mbps @ max %u iterations\n",
4171 		used_cores, total_mops, total_mbps, iter_count);
4172 }
4173 
4174 /* Aggregate the performance results over the number of cores used */
4175 static void
4176 print_dec_bler(struct thread_params *t_params, unsigned int used_cores)
4177 {
4178 	unsigned int core_idx = 0;
4179 	double total_mbps = 0, total_bler = 0, total_iter = 0;
4180 	double snr = get_snr();
4181 
4182 	for (core_idx = 0; core_idx < used_cores; core_idx++) {
4183 		printf("Core%u BLER %.1f %% - Iters %.1f - Tp %.1f Mbps %s\n",
4184 				t_params[core_idx].lcore_id,
4185 				t_params[core_idx].bler * 100,
4186 				t_params[core_idx].iter_average,
4187 				t_params[core_idx].mbps,
4188 				get_vector_filename());
4189 		total_mbps += t_params[core_idx].mbps;
4190 		total_bler += t_params[core_idx].bler;
4191 		total_iter += t_params[core_idx].iter_average;
4192 	}
4193 	total_bler /= used_cores;
4194 	total_iter /= used_cores;
4195 
4196 	printf("SNR %.2f BLER %.1f %% - Iterations %.1f %d - Tp %.1f Mbps %s\n",
4197 			snr, total_bler * 100, total_iter, get_iter_max(),
4198 			total_mbps, get_vector_filename());
4199 }
4200 
4201 /*
4202  * Test function that determines BLER wireless performance
4203  */
4204 static int
4205 bler_test(struct active_device *ad,
4206 		struct test_op_params *op_params)
4207 {
4208 	int ret;
4209 	unsigned int lcore_id, used_cores = 0;
4210 	struct thread_params *t_params;
4211 	struct rte_bbdev_info info;
4212 	lcore_function_t *bler_function;
4213 	uint16_t num_lcores;
4214 	const char *op_type_str;
4215 
4216 	rte_bbdev_info_get(ad->dev_id, &info);
4217 
4218 	op_type_str = rte_bbdev_op_type_str(test_vector.op_type);
4219 	TEST_ASSERT_NOT_NULL(op_type_str, "Invalid op type: %u",
4220 			test_vector.op_type);
4221 
4222 	printf("+ ------------------------------------------------------- +\n");
4223 	printf("== test: bler\ndev: %s, nb_queues: %u, burst size: %u, num ops: %u, num_lcores: %u, op type: %s, itr mode: %s, GHz: %lg\n",
4224 			info.dev_name, ad->nb_queues, op_params->burst_sz,
4225 			op_params->num_to_process, op_params->num_lcores,
4226 			op_type_str,
4227 			intr_enabled ? "Interrupt mode" : "PMD mode",
4228 			(double)rte_get_tsc_hz() / 1000000000.0);
4229 
4230 	/* Set number of lcores */
4231 	num_lcores = (ad->nb_queues < (op_params->num_lcores))
4232 			? ad->nb_queues
4233 			: op_params->num_lcores;
4234 
4235 	/* Allocate memory for thread parameters structure */
4236 	t_params = rte_zmalloc(NULL, num_lcores * sizeof(struct thread_params),
4237 			RTE_CACHE_LINE_SIZE);
4238 	TEST_ASSERT_NOT_NULL(t_params, "Failed to alloc %zuB for t_params",
4239 			RTE_ALIGN(sizeof(struct thread_params) * num_lcores,
4240 				RTE_CACHE_LINE_SIZE));
4241 
4242 	if ((test_vector.op_type == RTE_BBDEV_OP_LDPC_DEC) &&
4243 			!check_bit(test_vector.ldpc_dec.op_flags,
4244 			RTE_BBDEV_LDPC_INTERNAL_HARQ_MEMORY_LOOPBACK)
4245 			&& !check_bit(test_vector.ldpc_dec.op_flags,
4246 			RTE_BBDEV_LDPC_LLR_COMPRESSION))
4247 		bler_function = bler_pmd_lcore_ldpc_dec;
4248 	else
4249 		return TEST_SKIPPED;
4250 
4251 	__atomic_store_n(&op_params->sync, SYNC_WAIT, __ATOMIC_RELAXED);
4252 
4253 	/* Main core is set at first entry */
4254 	t_params[0].dev_id = ad->dev_id;
4255 	t_params[0].lcore_id = rte_lcore_id();
4256 	t_params[0].op_params = op_params;
4257 	t_params[0].queue_id = ad->queue_ids[used_cores++];
4258 	t_params[0].iter_count = 0;
4259 
4260 	RTE_LCORE_FOREACH_WORKER(lcore_id) {
4261 		if (used_cores >= num_lcores)
4262 			break;
4263 
4264 		t_params[used_cores].dev_id = ad->dev_id;
4265 		t_params[used_cores].lcore_id = lcore_id;
4266 		t_params[used_cores].op_params = op_params;
4267 		t_params[used_cores].queue_id = ad->queue_ids[used_cores];
4268 		t_params[used_cores].iter_count = 0;
4269 
4270 		rte_eal_remote_launch(bler_function,
4271 				&t_params[used_cores++], lcore_id);
4272 	}
4273 
4274 	__atomic_store_n(&op_params->sync, SYNC_START, __ATOMIC_RELAXED);
4275 	ret = bler_function(&t_params[0]);
4276 
4277 	/* Main core is always used */
4278 	for (used_cores = 1; used_cores < num_lcores; used_cores++)
4279 		ret |= rte_eal_wait_lcore(t_params[used_cores].lcore_id);
4280 
4281 	print_dec_bler(t_params, num_lcores);
4282 
4283 	/* Return if test failed */
4284 	if (ret) {
4285 		rte_free(t_params);
4286 		return ret;
4287 	}
4288 
4289 	/* Function to print something  here*/
4290 	rte_free(t_params);
4291 	return ret;
4292 }
4293 
4294 /*
4295  * Test function that determines how long an enqueue + dequeue of a burst
4296  * takes on available lcores.
4297  */
4298 static int
4299 throughput_test(struct active_device *ad,
4300 		struct test_op_params *op_params)
4301 {
4302 	int ret;
4303 	unsigned int lcore_id, used_cores = 0;
4304 	struct thread_params *t_params, *tp;
4305 	struct rte_bbdev_info info;
4306 	lcore_function_t *throughput_function;
4307 	uint16_t num_lcores;
4308 	const char *op_type_str;
4309 
4310 	rte_bbdev_info_get(ad->dev_id, &info);
4311 
4312 	op_type_str = rte_bbdev_op_type_str(test_vector.op_type);
4313 	TEST_ASSERT_NOT_NULL(op_type_str, "Invalid op type: %u",
4314 			test_vector.op_type);
4315 
4316 	printf("+ ------------------------------------------------------- +\n");
4317 	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",
4318 			info.dev_name, ad->nb_queues, op_params->burst_sz,
4319 			op_params->num_to_process, op_params->num_lcores,
4320 			op_type_str,
4321 			intr_enabled ? "Interrupt mode" : "PMD mode",
4322 			(double)rte_get_tsc_hz() / 1000000000.0);
4323 
4324 	/* Set number of lcores */
4325 	num_lcores = (ad->nb_queues < (op_params->num_lcores))
4326 			? ad->nb_queues
4327 			: op_params->num_lcores;
4328 
4329 	/* Allocate memory for thread parameters structure */
4330 	t_params = rte_zmalloc(NULL, num_lcores * sizeof(struct thread_params),
4331 			RTE_CACHE_LINE_SIZE);
4332 	TEST_ASSERT_NOT_NULL(t_params, "Failed to alloc %zuB for t_params",
4333 			RTE_ALIGN(sizeof(struct thread_params) * num_lcores,
4334 				RTE_CACHE_LINE_SIZE));
4335 
4336 	if (intr_enabled) {
4337 		if (test_vector.op_type == RTE_BBDEV_OP_TURBO_DEC)
4338 			throughput_function = throughput_intr_lcore_dec;
4339 		else if (test_vector.op_type == RTE_BBDEV_OP_LDPC_DEC)
4340 			throughput_function = throughput_intr_lcore_ldpc_dec;
4341 		else if (test_vector.op_type == RTE_BBDEV_OP_TURBO_ENC)
4342 			throughput_function = throughput_intr_lcore_enc;
4343 		else if (test_vector.op_type == RTE_BBDEV_OP_LDPC_ENC)
4344 			throughput_function = throughput_intr_lcore_ldpc_enc;
4345 		else if (test_vector.op_type == RTE_BBDEV_OP_FFT)
4346 			throughput_function = throughput_intr_lcore_fft;
4347 		else
4348 			throughput_function = throughput_intr_lcore_enc;
4349 
4350 		/* Dequeue interrupt callback registration */
4351 		ret = rte_bbdev_callback_register(ad->dev_id,
4352 				RTE_BBDEV_EVENT_DEQUEUE, dequeue_event_callback,
4353 				t_params);
4354 		if (ret < 0) {
4355 			rte_free(t_params);
4356 			return ret;
4357 		}
4358 	} else {
4359 		if (test_vector.op_type == RTE_BBDEV_OP_TURBO_DEC)
4360 			throughput_function = throughput_pmd_lcore_dec;
4361 		else if (test_vector.op_type == RTE_BBDEV_OP_LDPC_DEC)
4362 			throughput_function = throughput_pmd_lcore_ldpc_dec;
4363 		else if (test_vector.op_type == RTE_BBDEV_OP_TURBO_ENC)
4364 			throughput_function = throughput_pmd_lcore_enc;
4365 		else if (test_vector.op_type == RTE_BBDEV_OP_LDPC_ENC)
4366 			throughput_function = throughput_pmd_lcore_ldpc_enc;
4367 		else if (test_vector.op_type == RTE_BBDEV_OP_FFT)
4368 			throughput_function = throughput_pmd_lcore_fft;
4369 		else
4370 			throughput_function = throughput_pmd_lcore_enc;
4371 	}
4372 
4373 	__atomic_store_n(&op_params->sync, SYNC_WAIT, __ATOMIC_RELAXED);
4374 
4375 	/* Main core is set at first entry */
4376 	t_params[0].dev_id = ad->dev_id;
4377 	t_params[0].lcore_id = rte_lcore_id();
4378 	t_params[0].op_params = op_params;
4379 	t_params[0].queue_id = ad->queue_ids[used_cores++];
4380 	t_params[0].iter_count = 0;
4381 
4382 	RTE_LCORE_FOREACH_WORKER(lcore_id) {
4383 		if (used_cores >= num_lcores)
4384 			break;
4385 
4386 		t_params[used_cores].dev_id = ad->dev_id;
4387 		t_params[used_cores].lcore_id = lcore_id;
4388 		t_params[used_cores].op_params = op_params;
4389 		t_params[used_cores].queue_id = ad->queue_ids[used_cores];
4390 		t_params[used_cores].iter_count = 0;
4391 
4392 		rte_eal_remote_launch(throughput_function,
4393 				&t_params[used_cores++], lcore_id);
4394 	}
4395 
4396 	__atomic_store_n(&op_params->sync, SYNC_START, __ATOMIC_RELAXED);
4397 	ret = throughput_function(&t_params[0]);
4398 
4399 	/* Main core is always used */
4400 	for (used_cores = 1; used_cores < num_lcores; used_cores++)
4401 		ret |= rte_eal_wait_lcore(t_params[used_cores].lcore_id);
4402 
4403 	/* Return if test failed */
4404 	if (ret) {
4405 		rte_free(t_params);
4406 		return ret;
4407 	}
4408 
4409 	/* Print throughput if interrupts are disabled and test passed */
4410 	if (!intr_enabled) {
4411 		if (test_vector.op_type == RTE_BBDEV_OP_TURBO_DEC ||
4412 				test_vector.op_type == RTE_BBDEV_OP_LDPC_DEC)
4413 			print_dec_throughput(t_params, num_lcores);
4414 		else
4415 			print_enc_throughput(t_params, num_lcores);
4416 		rte_free(t_params);
4417 		return ret;
4418 	}
4419 
4420 	/* In interrupt TC we need to wait for the interrupt callback to deqeue
4421 	 * all pending operations. Skip waiting for queues which reported an
4422 	 * error using processing_status variable.
4423 	 * Wait for main lcore operations.
4424 	 */
4425 	tp = &t_params[0];
4426 	while ((__atomic_load_n(&tp->nb_dequeued, __ATOMIC_RELAXED) <
4427 		op_params->num_to_process) &&
4428 		(__atomic_load_n(&tp->processing_status, __ATOMIC_RELAXED) !=
4429 		TEST_FAILED))
4430 		rte_pause();
4431 
4432 	tp->ops_per_sec /= TEST_REPETITIONS;
4433 	tp->mbps /= TEST_REPETITIONS;
4434 	ret |= (int)__atomic_load_n(&tp->processing_status, __ATOMIC_RELAXED);
4435 
4436 	/* Wait for worker lcores operations */
4437 	for (used_cores = 1; used_cores < num_lcores; used_cores++) {
4438 		tp = &t_params[used_cores];
4439 
4440 		while ((__atomic_load_n(&tp->nb_dequeued, __ATOMIC_RELAXED) <
4441 			op_params->num_to_process) &&
4442 			(__atomic_load_n(&tp->processing_status, __ATOMIC_RELAXED) !=
4443 			TEST_FAILED))
4444 			rte_pause();
4445 
4446 		tp->ops_per_sec /= TEST_REPETITIONS;
4447 		tp->mbps /= TEST_REPETITIONS;
4448 		ret |= (int)__atomic_load_n(&tp->processing_status, __ATOMIC_RELAXED);
4449 	}
4450 
4451 	/* Print throughput if test passed */
4452 	if (!ret) {
4453 		if (test_vector.op_type == RTE_BBDEV_OP_TURBO_DEC ||
4454 				test_vector.op_type == RTE_BBDEV_OP_LDPC_DEC)
4455 			print_dec_throughput(t_params, num_lcores);
4456 		else if (test_vector.op_type == RTE_BBDEV_OP_TURBO_ENC ||
4457 				test_vector.op_type == RTE_BBDEV_OP_LDPC_ENC)
4458 			print_enc_throughput(t_params, num_lcores);
4459 	}
4460 
4461 	rte_free(t_params);
4462 	return ret;
4463 }
4464 
4465 static int
4466 latency_test_dec(struct rte_mempool *mempool,
4467 		struct test_buffers *bufs, struct rte_bbdev_dec_op *ref_op,
4468 		int vector_mask, uint16_t dev_id, uint16_t queue_id,
4469 		const uint16_t num_to_process, uint16_t burst_sz,
4470 		uint64_t *total_time, uint64_t *min_time, uint64_t *max_time)
4471 {
4472 	int ret = TEST_SUCCESS;
4473 	uint16_t i, j, dequeued;
4474 	struct rte_bbdev_dec_op *ops_enq[MAX_BURST], *ops_deq[MAX_BURST];
4475 	uint64_t start_time = 0, last_time = 0;
4476 
4477 	for (i = 0, dequeued = 0; dequeued < num_to_process; ++i) {
4478 		uint16_t enq = 0, deq = 0;
4479 		bool first_time = true;
4480 		last_time = 0;
4481 
4482 		if (unlikely(num_to_process - dequeued < burst_sz))
4483 			burst_sz = num_to_process - dequeued;
4484 
4485 		ret = rte_bbdev_dec_op_alloc_bulk(mempool, ops_enq, burst_sz);
4486 		TEST_ASSERT_SUCCESS(ret,
4487 				"rte_bbdev_dec_op_alloc_bulk() failed");
4488 		if (test_vector.op_type != RTE_BBDEV_OP_NONE)
4489 			copy_reference_dec_op(ops_enq, burst_sz, dequeued,
4490 					bufs->inputs,
4491 					bufs->hard_outputs,
4492 					bufs->soft_outputs,
4493 					ref_op);
4494 
4495 		/* Set counter to validate the ordering */
4496 		for (j = 0; j < burst_sz; ++j)
4497 			ops_enq[j]->opaque_data = (void *)(uintptr_t)j;
4498 
4499 		start_time = rte_rdtsc_precise();
4500 
4501 		enq = rte_bbdev_enqueue_dec_ops(dev_id, queue_id, &ops_enq[enq],
4502 				burst_sz);
4503 		TEST_ASSERT(enq == burst_sz,
4504 				"Error enqueueing burst, expected %u, got %u",
4505 				burst_sz, enq);
4506 
4507 		/* Dequeue */
4508 		do {
4509 			deq += rte_bbdev_dequeue_dec_ops(dev_id, queue_id,
4510 					&ops_deq[deq], burst_sz - deq);
4511 			if (likely(first_time && (deq > 0))) {
4512 				last_time = rte_rdtsc_precise() - start_time;
4513 				first_time = false;
4514 			}
4515 		} while (unlikely(burst_sz != deq));
4516 
4517 		*max_time = RTE_MAX(*max_time, last_time);
4518 		*min_time = RTE_MIN(*min_time, last_time);
4519 		*total_time += last_time;
4520 
4521 		if (test_vector.op_type != RTE_BBDEV_OP_NONE) {
4522 			ret = validate_dec_op(ops_deq, burst_sz, ref_op,
4523 					vector_mask);
4524 			TEST_ASSERT_SUCCESS(ret, "Validation failed!");
4525 		}
4526 
4527 		rte_bbdev_dec_op_free_bulk(ops_enq, deq);
4528 		dequeued += deq;
4529 	}
4530 
4531 	return i;
4532 }
4533 
4534 /* Test case for latency/validation for LDPC Decoder */
4535 static int
4536 latency_test_ldpc_dec(struct rte_mempool *mempool,
4537 		struct test_buffers *bufs, struct rte_bbdev_dec_op *ref_op,
4538 		int vector_mask, uint16_t dev_id, uint16_t queue_id,
4539 		const uint16_t num_to_process, uint16_t burst_sz,
4540 		uint64_t *total_time, uint64_t *min_time, uint64_t *max_time,
4541 		bool disable_et)
4542 {
4543 	int ret = TEST_SUCCESS;
4544 	uint16_t i, j, dequeued;
4545 	struct rte_bbdev_dec_op *ops_enq[MAX_BURST], *ops_deq[MAX_BURST];
4546 	uint64_t start_time = 0, last_time = 0;
4547 	bool extDdr = ldpc_cap_flags &
4548 			RTE_BBDEV_LDPC_INTERNAL_HARQ_MEMORY_OUT_ENABLE;
4549 
4550 	for (i = 0, dequeued = 0; dequeued < num_to_process; ++i) {
4551 		uint16_t enq = 0, deq = 0;
4552 		bool first_time = true;
4553 		last_time = 0;
4554 
4555 		if (unlikely(num_to_process - dequeued < burst_sz))
4556 			burst_sz = num_to_process - dequeued;
4557 
4558 		ret = rte_bbdev_dec_op_alloc_bulk(mempool, ops_enq, burst_sz);
4559 		TEST_ASSERT_SUCCESS(ret,
4560 				"rte_bbdev_dec_op_alloc_bulk() failed");
4561 
4562 		/* For latency tests we need to disable early termination */
4563 		if (disable_et && check_bit(ref_op->ldpc_dec.op_flags,
4564 				RTE_BBDEV_LDPC_ITERATION_STOP_ENABLE))
4565 			ref_op->ldpc_dec.op_flags -=
4566 					RTE_BBDEV_LDPC_ITERATION_STOP_ENABLE;
4567 		ref_op->ldpc_dec.iter_max = get_iter_max();
4568 		ref_op->ldpc_dec.iter_count = ref_op->ldpc_dec.iter_max;
4569 
4570 		if (test_vector.op_type != RTE_BBDEV_OP_NONE)
4571 			copy_reference_ldpc_dec_op(ops_enq, burst_sz, dequeued,
4572 					bufs->inputs,
4573 					bufs->hard_outputs,
4574 					bufs->soft_outputs,
4575 					bufs->harq_inputs,
4576 					bufs->harq_outputs,
4577 					ref_op);
4578 
4579 		if (extDdr)
4580 			preload_harq_ddr(dev_id, queue_id, ops_enq,
4581 					burst_sz, true);
4582 
4583 		/* Set counter to validate the ordering */
4584 		for (j = 0; j < burst_sz; ++j)
4585 			ops_enq[j]->opaque_data = (void *)(uintptr_t)j;
4586 
4587 		start_time = rte_rdtsc_precise();
4588 
4589 		enq = rte_bbdev_enqueue_ldpc_dec_ops(dev_id, queue_id,
4590 				&ops_enq[enq], burst_sz);
4591 		TEST_ASSERT(enq == burst_sz,
4592 				"Error enqueueing burst, expected %u, got %u",
4593 				burst_sz, enq);
4594 
4595 		/* Dequeue */
4596 		do {
4597 			deq += rte_bbdev_dequeue_ldpc_dec_ops(dev_id, queue_id,
4598 					&ops_deq[deq], burst_sz - deq);
4599 			if (likely(first_time && (deq > 0))) {
4600 				last_time = rte_rdtsc_precise() - start_time;
4601 				first_time = false;
4602 			}
4603 		} while (unlikely(burst_sz != deq));
4604 
4605 		*max_time = RTE_MAX(*max_time, last_time);
4606 		*min_time = RTE_MIN(*min_time, last_time);
4607 		*total_time += last_time;
4608 
4609 		if (extDdr)
4610 			retrieve_harq_ddr(dev_id, queue_id, ops_enq, burst_sz);
4611 
4612 		if (test_vector.op_type != RTE_BBDEV_OP_NONE) {
4613 			ret = validate_ldpc_dec_op(ops_deq, burst_sz, ref_op,
4614 					vector_mask);
4615 			TEST_ASSERT_SUCCESS(ret, "Validation failed!");
4616 		}
4617 
4618 		rte_bbdev_dec_op_free_bulk(ops_enq, deq);
4619 		dequeued += deq;
4620 	}
4621 	return i;
4622 }
4623 
4624 static int
4625 latency_test_enc(struct rte_mempool *mempool,
4626 		struct test_buffers *bufs, struct rte_bbdev_enc_op *ref_op,
4627 		uint16_t dev_id, uint16_t queue_id,
4628 		const uint16_t num_to_process, uint16_t burst_sz,
4629 		uint64_t *total_time, uint64_t *min_time, uint64_t *max_time)
4630 {
4631 	int ret = TEST_SUCCESS;
4632 	uint16_t i, j, dequeued;
4633 	struct rte_bbdev_enc_op *ops_enq[MAX_BURST], *ops_deq[MAX_BURST];
4634 	uint64_t start_time = 0, last_time = 0;
4635 
4636 	for (i = 0, dequeued = 0; dequeued < num_to_process; ++i) {
4637 		uint16_t enq = 0, deq = 0;
4638 		bool first_time = true;
4639 		last_time = 0;
4640 
4641 		if (unlikely(num_to_process - dequeued < burst_sz))
4642 			burst_sz = num_to_process - dequeued;
4643 
4644 		ret = rte_bbdev_enc_op_alloc_bulk(mempool, ops_enq, burst_sz);
4645 		TEST_ASSERT_SUCCESS(ret,
4646 				"rte_bbdev_enc_op_alloc_bulk() failed");
4647 		if (test_vector.op_type != RTE_BBDEV_OP_NONE)
4648 			copy_reference_enc_op(ops_enq, burst_sz, dequeued,
4649 					bufs->inputs,
4650 					bufs->hard_outputs,
4651 					ref_op);
4652 
4653 		/* Set counter to validate the ordering */
4654 		for (j = 0; j < burst_sz; ++j)
4655 			ops_enq[j]->opaque_data = (void *)(uintptr_t)j;
4656 
4657 		start_time = rte_rdtsc_precise();
4658 
4659 		enq = rte_bbdev_enqueue_enc_ops(dev_id, queue_id, &ops_enq[enq],
4660 				burst_sz);
4661 		TEST_ASSERT(enq == burst_sz,
4662 				"Error enqueueing burst, expected %u, got %u",
4663 				burst_sz, enq);
4664 
4665 		/* Dequeue */
4666 		do {
4667 			deq += rte_bbdev_dequeue_enc_ops(dev_id, queue_id,
4668 					&ops_deq[deq], burst_sz - deq);
4669 			if (likely(first_time && (deq > 0))) {
4670 				last_time += rte_rdtsc_precise() - start_time;
4671 				first_time = false;
4672 			}
4673 		} while (unlikely(burst_sz != deq));
4674 
4675 		*max_time = RTE_MAX(*max_time, last_time);
4676 		*min_time = RTE_MIN(*min_time, last_time);
4677 		*total_time += last_time;
4678 
4679 		if (test_vector.op_type != RTE_BBDEV_OP_NONE) {
4680 			ret = validate_enc_op(ops_deq, burst_sz, ref_op);
4681 			TEST_ASSERT_SUCCESS(ret, "Validation failed!");
4682 		}
4683 
4684 		rte_bbdev_enc_op_free_bulk(ops_enq, deq);
4685 		dequeued += deq;
4686 	}
4687 
4688 	return i;
4689 }
4690 
4691 static int
4692 latency_test_ldpc_enc(struct rte_mempool *mempool,
4693 		struct test_buffers *bufs, struct rte_bbdev_enc_op *ref_op,
4694 		uint16_t dev_id, uint16_t queue_id,
4695 		const uint16_t num_to_process, uint16_t burst_sz,
4696 		uint64_t *total_time, uint64_t *min_time, uint64_t *max_time)
4697 {
4698 	int ret = TEST_SUCCESS;
4699 	uint16_t i, j, dequeued;
4700 	struct rte_bbdev_enc_op *ops_enq[MAX_BURST], *ops_deq[MAX_BURST];
4701 	uint64_t start_time = 0, last_time = 0;
4702 
4703 	for (i = 0, dequeued = 0; dequeued < num_to_process; ++i) {
4704 		uint16_t enq = 0, deq = 0;
4705 		bool first_time = true;
4706 		last_time = 0;
4707 
4708 		if (unlikely(num_to_process - dequeued < burst_sz))
4709 			burst_sz = num_to_process - dequeued;
4710 
4711 		ret = rte_bbdev_enc_op_alloc_bulk(mempool, ops_enq, burst_sz);
4712 		TEST_ASSERT_SUCCESS(ret,
4713 				"rte_bbdev_enc_op_alloc_bulk() failed");
4714 		if (test_vector.op_type != RTE_BBDEV_OP_NONE)
4715 			copy_reference_ldpc_enc_op(ops_enq, burst_sz, dequeued,
4716 					bufs->inputs,
4717 					bufs->hard_outputs,
4718 					ref_op);
4719 
4720 		/* Set counter to validate the ordering */
4721 		for (j = 0; j < burst_sz; ++j)
4722 			ops_enq[j]->opaque_data = (void *)(uintptr_t)j;
4723 
4724 		start_time = rte_rdtsc_precise();
4725 
4726 		enq = rte_bbdev_enqueue_ldpc_enc_ops(dev_id, queue_id,
4727 				&ops_enq[enq], burst_sz);
4728 		TEST_ASSERT(enq == burst_sz,
4729 				"Error enqueueing burst, expected %u, got %u",
4730 				burst_sz, enq);
4731 
4732 		/* Dequeue */
4733 		do {
4734 			deq += rte_bbdev_dequeue_ldpc_enc_ops(dev_id, queue_id,
4735 					&ops_deq[deq], burst_sz - deq);
4736 			if (likely(first_time && (deq > 0))) {
4737 				last_time += rte_rdtsc_precise() - start_time;
4738 				first_time = false;
4739 			}
4740 		} while (unlikely(burst_sz != deq));
4741 
4742 		*max_time = RTE_MAX(*max_time, last_time);
4743 		*min_time = RTE_MIN(*min_time, last_time);
4744 		*total_time += last_time;
4745 
4746 		if (test_vector.op_type != RTE_BBDEV_OP_NONE) {
4747 			ret = validate_enc_op(ops_deq, burst_sz, ref_op);
4748 			TEST_ASSERT_SUCCESS(ret, "Validation failed!");
4749 		}
4750 
4751 		rte_bbdev_enc_op_free_bulk(ops_enq, deq);
4752 		dequeued += deq;
4753 	}
4754 
4755 	return i;
4756 }
4757 
4758 
4759 static int
4760 latency_test_fft(struct rte_mempool *mempool,
4761 		struct test_buffers *bufs, struct rte_bbdev_fft_op *ref_op,
4762 		uint16_t dev_id, uint16_t queue_id,
4763 		const uint16_t num_to_process, uint16_t burst_sz,
4764 		uint64_t *total_time, uint64_t *min_time, uint64_t *max_time)
4765 {
4766 	int ret = TEST_SUCCESS;
4767 	uint16_t i, j, dequeued;
4768 	struct rte_bbdev_fft_op *ops_enq[MAX_BURST], *ops_deq[MAX_BURST];
4769 	uint64_t start_time = 0, last_time = 0;
4770 
4771 	for (i = 0, dequeued = 0; dequeued < num_to_process; ++i) {
4772 		uint16_t enq = 0, deq = 0;
4773 		bool first_time = true;
4774 		last_time = 0;
4775 
4776 		if (unlikely(num_to_process - dequeued < burst_sz))
4777 			burst_sz = num_to_process - dequeued;
4778 
4779 		ret = rte_bbdev_fft_op_alloc_bulk(mempool, ops_enq, burst_sz);
4780 		TEST_ASSERT_SUCCESS(ret,
4781 				"rte_bbdev_fft_op_alloc_bulk() failed");
4782 		if (test_vector.op_type != RTE_BBDEV_OP_NONE)
4783 			copy_reference_fft_op(ops_enq, burst_sz, dequeued,
4784 					bufs->inputs,
4785 					bufs->hard_outputs, bufs->soft_outputs,
4786 					ref_op);
4787 
4788 		/* Set counter to validate the ordering */
4789 		for (j = 0; j < burst_sz; ++j)
4790 			ops_enq[j]->opaque_data = (void *)(uintptr_t)j;
4791 
4792 		start_time = rte_rdtsc_precise();
4793 
4794 		enq = rte_bbdev_enqueue_fft_ops(dev_id, queue_id,
4795 				&ops_enq[enq], burst_sz);
4796 		TEST_ASSERT(enq == burst_sz,
4797 				"Error enqueueing burst, expected %u, got %u",
4798 				burst_sz, enq);
4799 
4800 		/* Dequeue */
4801 		do {
4802 			deq += rte_bbdev_dequeue_fft_ops(dev_id, queue_id,
4803 					&ops_deq[deq], burst_sz - deq);
4804 			if (likely(first_time && (deq > 0))) {
4805 				last_time += rte_rdtsc_precise() - start_time;
4806 				first_time = false;
4807 			}
4808 		} while (unlikely(burst_sz != deq));
4809 
4810 		*max_time = RTE_MAX(*max_time, last_time);
4811 		*min_time = RTE_MIN(*min_time, last_time);
4812 		*total_time += last_time;
4813 
4814 		if (test_vector.op_type != RTE_BBDEV_OP_NONE) {
4815 			ret = validate_fft_op(ops_deq, burst_sz, ref_op);
4816 			TEST_ASSERT_SUCCESS(ret, "Validation failed!");
4817 		}
4818 
4819 		rte_bbdev_fft_op_free_bulk(ops_enq, deq);
4820 		dequeued += deq;
4821 	}
4822 
4823 	return i;
4824 }
4825 
4826 /* Common function for running validation and latency test cases */
4827 static int
4828 validation_latency_test(struct active_device *ad,
4829 		struct test_op_params *op_params, bool latency_flag)
4830 {
4831 	int iter;
4832 	uint16_t burst_sz = op_params->burst_sz;
4833 	const uint16_t num_to_process = op_params->num_to_process;
4834 	const enum rte_bbdev_op_type op_type = test_vector.op_type;
4835 	const uint16_t queue_id = ad->queue_ids[0];
4836 	struct test_buffers *bufs = NULL;
4837 	struct rte_bbdev_info info;
4838 	uint64_t total_time, min_time, max_time;
4839 	const char *op_type_str;
4840 
4841 	total_time = max_time = 0;
4842 	min_time = UINT64_MAX;
4843 
4844 	TEST_ASSERT_SUCCESS((burst_sz > MAX_BURST),
4845 			"BURST_SIZE should be <= %u", MAX_BURST);
4846 
4847 	rte_bbdev_info_get(ad->dev_id, &info);
4848 	bufs = &op_params->q_bufs[GET_SOCKET(info.socket_id)][queue_id];
4849 
4850 	op_type_str = rte_bbdev_op_type_str(op_type);
4851 	TEST_ASSERT_NOT_NULL(op_type_str, "Invalid op type: %u", op_type);
4852 
4853 	printf("+ ------------------------------------------------------- +\n");
4854 	if (latency_flag)
4855 		printf("== test: latency\ndev:");
4856 	else
4857 		printf("== test: validation\ndev:");
4858 	printf("%s, burst size: %u, num ops: %u, op type: %s\n",
4859 			info.dev_name, burst_sz, num_to_process, op_type_str);
4860 
4861 	if (op_type == RTE_BBDEV_OP_TURBO_DEC)
4862 		iter = latency_test_dec(op_params->mp, bufs,
4863 				op_params->ref_dec_op, op_params->vector_mask,
4864 				ad->dev_id, queue_id, num_to_process,
4865 				burst_sz, &total_time, &min_time, &max_time);
4866 	else if (op_type == RTE_BBDEV_OP_LDPC_ENC)
4867 		iter = latency_test_ldpc_enc(op_params->mp, bufs,
4868 				op_params->ref_enc_op, ad->dev_id, queue_id,
4869 				num_to_process, burst_sz, &total_time,
4870 				&min_time, &max_time);
4871 	else if (op_type == RTE_BBDEV_OP_LDPC_DEC)
4872 		iter = latency_test_ldpc_dec(op_params->mp, bufs,
4873 				op_params->ref_dec_op, op_params->vector_mask,
4874 				ad->dev_id, queue_id, num_to_process,
4875 				burst_sz, &total_time, &min_time, &max_time,
4876 				latency_flag);
4877 	else if (op_type == RTE_BBDEV_OP_FFT)
4878 		iter = latency_test_fft(op_params->mp, bufs,
4879 				op_params->ref_fft_op,
4880 				ad->dev_id, queue_id,
4881 				num_to_process, burst_sz, &total_time,
4882 				&min_time, &max_time);
4883 	else /* RTE_BBDEV_OP_TURBO_ENC */
4884 		iter = latency_test_enc(op_params->mp, bufs,
4885 				op_params->ref_enc_op,
4886 				ad->dev_id, queue_id,
4887 				num_to_process, burst_sz, &total_time,
4888 				&min_time, &max_time);
4889 
4890 	if (iter <= 0)
4891 		return TEST_FAILED;
4892 
4893 	printf("Operation latency:\n"
4894 			"\tavg: %lg cycles, %lg us\n"
4895 			"\tmin: %lg cycles, %lg us\n"
4896 			"\tmax: %lg cycles, %lg us\n",
4897 			(double)total_time / (double)iter,
4898 			(double)(total_time * 1000000) / (double)iter /
4899 			(double)rte_get_tsc_hz(), (double)min_time,
4900 			(double)(min_time * 1000000) / (double)rte_get_tsc_hz(),
4901 			(double)max_time, (double)(max_time * 1000000) /
4902 			(double)rte_get_tsc_hz());
4903 
4904 	return TEST_SUCCESS;
4905 }
4906 
4907 static int
4908 latency_test(struct active_device *ad, struct test_op_params *op_params)
4909 {
4910 	return validation_latency_test(ad, op_params, true);
4911 }
4912 
4913 static int
4914 validation_test(struct active_device *ad, struct test_op_params *op_params)
4915 {
4916 	return validation_latency_test(ad, op_params, false);
4917 }
4918 
4919 #ifdef RTE_BBDEV_OFFLOAD_COST
4920 static int
4921 get_bbdev_queue_stats(uint16_t dev_id, uint16_t queue_id,
4922 		struct rte_bbdev_stats *stats)
4923 {
4924 	struct rte_bbdev *dev = &rte_bbdev_devices[dev_id];
4925 	struct rte_bbdev_stats *q_stats;
4926 
4927 	if (queue_id >= dev->data->num_queues)
4928 		return -1;
4929 
4930 	q_stats = &dev->data->queues[queue_id].queue_stats;
4931 
4932 	stats->enqueued_count = q_stats->enqueued_count;
4933 	stats->dequeued_count = q_stats->dequeued_count;
4934 	stats->enqueue_err_count = q_stats->enqueue_err_count;
4935 	stats->dequeue_err_count = q_stats->dequeue_err_count;
4936 	stats->enqueue_warning_count = q_stats->enqueue_warning_count;
4937 	stats->dequeue_warning_count = q_stats->dequeue_warning_count;
4938 	stats->acc_offload_cycles = q_stats->acc_offload_cycles;
4939 
4940 	return 0;
4941 }
4942 
4943 static int
4944 offload_latency_test_dec(struct rte_mempool *mempool, struct test_buffers *bufs,
4945 		struct rte_bbdev_dec_op *ref_op, uint16_t dev_id,
4946 		uint16_t queue_id, const uint16_t num_to_process,
4947 		uint16_t burst_sz, struct test_time_stats *time_st)
4948 {
4949 	int i, dequeued, ret;
4950 	struct rte_bbdev_dec_op *ops_enq[MAX_BURST], *ops_deq[MAX_BURST];
4951 	uint64_t enq_start_time, deq_start_time;
4952 	uint64_t enq_sw_last_time, deq_last_time;
4953 	struct rte_bbdev_stats stats;
4954 
4955 	for (i = 0, dequeued = 0; dequeued < num_to_process; ++i) {
4956 		uint16_t enq = 0, deq = 0;
4957 
4958 		if (unlikely(num_to_process - dequeued < burst_sz))
4959 			burst_sz = num_to_process - dequeued;
4960 
4961 		rte_bbdev_dec_op_alloc_bulk(mempool, ops_enq, burst_sz);
4962 		if (test_vector.op_type != RTE_BBDEV_OP_NONE)
4963 			copy_reference_dec_op(ops_enq, burst_sz, dequeued,
4964 					bufs->inputs,
4965 					bufs->hard_outputs,
4966 					bufs->soft_outputs,
4967 					ref_op);
4968 
4969 		/* Start time meas for enqueue function offload latency */
4970 		enq_start_time = rte_rdtsc_precise();
4971 		do {
4972 			enq += rte_bbdev_enqueue_dec_ops(dev_id, queue_id,
4973 					&ops_enq[enq], burst_sz - enq);
4974 		} while (unlikely(burst_sz != enq));
4975 
4976 		ret = get_bbdev_queue_stats(dev_id, queue_id, &stats);
4977 		TEST_ASSERT_SUCCESS(ret,
4978 				"Failed to get stats for queue (%u) of device (%u)",
4979 				queue_id, dev_id);
4980 
4981 		enq_sw_last_time = rte_rdtsc_precise() - enq_start_time -
4982 				stats.acc_offload_cycles;
4983 		time_st->enq_sw_max_time = RTE_MAX(time_st->enq_sw_max_time,
4984 				enq_sw_last_time);
4985 		time_st->enq_sw_min_time = RTE_MIN(time_st->enq_sw_min_time,
4986 				enq_sw_last_time);
4987 		time_st->enq_sw_total_time += enq_sw_last_time;
4988 
4989 		time_st->enq_acc_max_time = RTE_MAX(time_st->enq_acc_max_time,
4990 				stats.acc_offload_cycles);
4991 		time_st->enq_acc_min_time = RTE_MIN(time_st->enq_acc_min_time,
4992 				stats.acc_offload_cycles);
4993 		time_st->enq_acc_total_time += stats.acc_offload_cycles;
4994 
4995 		/* give time for device to process ops */
4996 		rte_delay_us(WAIT_OFFLOAD_US);
4997 
4998 		/* Start time meas for dequeue function offload latency */
4999 		deq_start_time = rte_rdtsc_precise();
5000 		/* Dequeue one operation */
5001 		do {
5002 			deq += rte_bbdev_dequeue_dec_ops(dev_id, queue_id,
5003 					&ops_deq[deq], enq);
5004 		} while (unlikely(deq == 0));
5005 
5006 		deq_last_time = rte_rdtsc_precise() - deq_start_time;
5007 		time_st->deq_max_time = RTE_MAX(time_st->deq_max_time,
5008 				deq_last_time);
5009 		time_st->deq_min_time = RTE_MIN(time_st->deq_min_time,
5010 				deq_last_time);
5011 		time_st->deq_total_time += deq_last_time;
5012 
5013 		/* Dequeue remaining operations if needed*/
5014 		while (burst_sz != deq)
5015 			deq += rte_bbdev_dequeue_dec_ops(dev_id, queue_id,
5016 					&ops_deq[deq], burst_sz - deq);
5017 
5018 		rte_bbdev_dec_op_free_bulk(ops_enq, deq);
5019 		dequeued += deq;
5020 	}
5021 
5022 	return i;
5023 }
5024 
5025 static int
5026 offload_latency_test_ldpc_dec(struct rte_mempool *mempool,
5027 		struct test_buffers *bufs,
5028 		struct rte_bbdev_dec_op *ref_op, uint16_t dev_id,
5029 		uint16_t queue_id, const uint16_t num_to_process,
5030 		uint16_t burst_sz, struct test_time_stats *time_st)
5031 {
5032 	int i, dequeued, ret;
5033 	struct rte_bbdev_dec_op *ops_enq[MAX_BURST], *ops_deq[MAX_BURST];
5034 	uint64_t enq_start_time, deq_start_time;
5035 	uint64_t enq_sw_last_time, deq_last_time;
5036 	struct rte_bbdev_stats stats;
5037 	bool extDdr = ldpc_cap_flags &
5038 			RTE_BBDEV_LDPC_INTERNAL_HARQ_MEMORY_OUT_ENABLE;
5039 
5040 	for (i = 0, dequeued = 0; dequeued < num_to_process; ++i) {
5041 		uint16_t enq = 0, deq = 0;
5042 
5043 		if (unlikely(num_to_process - dequeued < burst_sz))
5044 			burst_sz = num_to_process - dequeued;
5045 
5046 		rte_bbdev_dec_op_alloc_bulk(mempool, ops_enq, burst_sz);
5047 		if (test_vector.op_type != RTE_BBDEV_OP_NONE)
5048 			copy_reference_ldpc_dec_op(ops_enq, burst_sz, dequeued,
5049 					bufs->inputs,
5050 					bufs->hard_outputs,
5051 					bufs->soft_outputs,
5052 					bufs->harq_inputs,
5053 					bufs->harq_outputs,
5054 					ref_op);
5055 
5056 		if (extDdr)
5057 			preload_harq_ddr(dev_id, queue_id, ops_enq,
5058 					burst_sz, true);
5059 
5060 		/* Start time meas for enqueue function offload latency */
5061 		enq_start_time = rte_rdtsc_precise();
5062 		do {
5063 			enq += rte_bbdev_enqueue_ldpc_dec_ops(dev_id, queue_id,
5064 					&ops_enq[enq], burst_sz - enq);
5065 		} while (unlikely(burst_sz != enq));
5066 
5067 		enq_sw_last_time = rte_rdtsc_precise() - enq_start_time;
5068 		ret = get_bbdev_queue_stats(dev_id, queue_id, &stats);
5069 		TEST_ASSERT_SUCCESS(ret,
5070 				"Failed to get stats for queue (%u) of device (%u)",
5071 				queue_id, dev_id);
5072 
5073 		enq_sw_last_time -= stats.acc_offload_cycles;
5074 		time_st->enq_sw_max_time = RTE_MAX(time_st->enq_sw_max_time,
5075 				enq_sw_last_time);
5076 		time_st->enq_sw_min_time = RTE_MIN(time_st->enq_sw_min_time,
5077 				enq_sw_last_time);
5078 		time_st->enq_sw_total_time += enq_sw_last_time;
5079 
5080 		time_st->enq_acc_max_time = RTE_MAX(time_st->enq_acc_max_time,
5081 				stats.acc_offload_cycles);
5082 		time_st->enq_acc_min_time = RTE_MIN(time_st->enq_acc_min_time,
5083 				stats.acc_offload_cycles);
5084 		time_st->enq_acc_total_time += stats.acc_offload_cycles;
5085 
5086 		/* give time for device to process ops */
5087 		rte_delay_us(WAIT_OFFLOAD_US);
5088 
5089 		/* Start time meas for dequeue function offload latency */
5090 		deq_start_time = rte_rdtsc_precise();
5091 		/* Dequeue one operation */
5092 		do {
5093 			deq += rte_bbdev_dequeue_ldpc_dec_ops(dev_id, queue_id,
5094 					&ops_deq[deq], enq);
5095 		} while (unlikely(deq == 0));
5096 
5097 		deq_last_time = rte_rdtsc_precise() - deq_start_time;
5098 		time_st->deq_max_time = RTE_MAX(time_st->deq_max_time,
5099 				deq_last_time);
5100 		time_st->deq_min_time = RTE_MIN(time_st->deq_min_time,
5101 				deq_last_time);
5102 		time_st->deq_total_time += deq_last_time;
5103 
5104 		/* Dequeue remaining operations if needed*/
5105 		while (burst_sz != deq)
5106 			deq += rte_bbdev_dequeue_ldpc_dec_ops(dev_id, queue_id,
5107 					&ops_deq[deq], burst_sz - deq);
5108 
5109 		if (extDdr) {
5110 			/* Read loopback is not thread safe */
5111 			retrieve_harq_ddr(dev_id, queue_id, ops_enq, burst_sz);
5112 		}
5113 
5114 		rte_bbdev_dec_op_free_bulk(ops_enq, deq);
5115 		dequeued += deq;
5116 	}
5117 
5118 	return i;
5119 }
5120 
5121 static int
5122 offload_latency_test_enc(struct rte_mempool *mempool, struct test_buffers *bufs,
5123 		struct rte_bbdev_enc_op *ref_op, uint16_t dev_id,
5124 		uint16_t queue_id, const uint16_t num_to_process,
5125 		uint16_t burst_sz, struct test_time_stats *time_st)
5126 {
5127 	int i, dequeued, ret;
5128 	struct rte_bbdev_enc_op *ops_enq[MAX_BURST], *ops_deq[MAX_BURST];
5129 	uint64_t enq_start_time, deq_start_time;
5130 	uint64_t enq_sw_last_time, deq_last_time;
5131 	struct rte_bbdev_stats stats;
5132 
5133 	for (i = 0, dequeued = 0; dequeued < num_to_process; ++i) {
5134 		uint16_t enq = 0, deq = 0;
5135 
5136 		if (unlikely(num_to_process - dequeued < burst_sz))
5137 			burst_sz = num_to_process - dequeued;
5138 
5139 		ret = rte_bbdev_enc_op_alloc_bulk(mempool, ops_enq, burst_sz);
5140 		TEST_ASSERT_SUCCESS(ret,
5141 				"rte_bbdev_enc_op_alloc_bulk() failed");
5142 		if (test_vector.op_type != RTE_BBDEV_OP_NONE)
5143 			copy_reference_enc_op(ops_enq, burst_sz, dequeued,
5144 					bufs->inputs,
5145 					bufs->hard_outputs,
5146 					ref_op);
5147 
5148 		/* Start time meas for enqueue function offload latency */
5149 		enq_start_time = rte_rdtsc_precise();
5150 		do {
5151 			enq += rte_bbdev_enqueue_enc_ops(dev_id, queue_id,
5152 					&ops_enq[enq], burst_sz - enq);
5153 		} while (unlikely(burst_sz != enq));
5154 
5155 		enq_sw_last_time = rte_rdtsc_precise() - enq_start_time;
5156 
5157 		ret = get_bbdev_queue_stats(dev_id, queue_id, &stats);
5158 		TEST_ASSERT_SUCCESS(ret,
5159 				"Failed to get stats for queue (%u) of device (%u)",
5160 				queue_id, dev_id);
5161 		enq_sw_last_time -= stats.acc_offload_cycles;
5162 		time_st->enq_sw_max_time = RTE_MAX(time_st->enq_sw_max_time,
5163 				enq_sw_last_time);
5164 		time_st->enq_sw_min_time = RTE_MIN(time_st->enq_sw_min_time,
5165 				enq_sw_last_time);
5166 		time_st->enq_sw_total_time += enq_sw_last_time;
5167 
5168 		time_st->enq_acc_max_time = RTE_MAX(time_st->enq_acc_max_time,
5169 				stats.acc_offload_cycles);
5170 		time_st->enq_acc_min_time = RTE_MIN(time_st->enq_acc_min_time,
5171 				stats.acc_offload_cycles);
5172 		time_st->enq_acc_total_time += stats.acc_offload_cycles;
5173 
5174 		/* give time for device to process ops */
5175 		rte_delay_us(WAIT_OFFLOAD_US);
5176 
5177 		/* Start time meas for dequeue function offload latency */
5178 		deq_start_time = rte_rdtsc_precise();
5179 		/* Dequeue one operation */
5180 		do {
5181 			deq += rte_bbdev_dequeue_enc_ops(dev_id, queue_id,
5182 					&ops_deq[deq], enq);
5183 		} while (unlikely(deq == 0));
5184 
5185 		deq_last_time = rte_rdtsc_precise() - deq_start_time;
5186 		time_st->deq_max_time = RTE_MAX(time_st->deq_max_time,
5187 				deq_last_time);
5188 		time_st->deq_min_time = RTE_MIN(time_st->deq_min_time,
5189 				deq_last_time);
5190 		time_st->deq_total_time += deq_last_time;
5191 
5192 		while (burst_sz != deq)
5193 			deq += rte_bbdev_dequeue_enc_ops(dev_id, queue_id,
5194 					&ops_deq[deq], burst_sz - deq);
5195 
5196 		rte_bbdev_enc_op_free_bulk(ops_enq, deq);
5197 		dequeued += deq;
5198 	}
5199 
5200 	return i;
5201 }
5202 
5203 static int
5204 offload_latency_test_ldpc_enc(struct rte_mempool *mempool,
5205 		struct test_buffers *bufs,
5206 		struct rte_bbdev_enc_op *ref_op, uint16_t dev_id,
5207 		uint16_t queue_id, const uint16_t num_to_process,
5208 		uint16_t burst_sz, struct test_time_stats *time_st)
5209 {
5210 	int i, dequeued, ret;
5211 	struct rte_bbdev_enc_op *ops_enq[MAX_BURST], *ops_deq[MAX_BURST];
5212 	uint64_t enq_start_time, deq_start_time;
5213 	uint64_t enq_sw_last_time, deq_last_time;
5214 	struct rte_bbdev_stats stats;
5215 
5216 	for (i = 0, dequeued = 0; dequeued < num_to_process; ++i) {
5217 		uint16_t enq = 0, deq = 0;
5218 
5219 		if (unlikely(num_to_process - dequeued < burst_sz))
5220 			burst_sz = num_to_process - dequeued;
5221 
5222 		ret = rte_bbdev_enc_op_alloc_bulk(mempool, ops_enq, burst_sz);
5223 		TEST_ASSERT_SUCCESS(ret,
5224 				"rte_bbdev_enc_op_alloc_bulk() failed");
5225 		if (test_vector.op_type != RTE_BBDEV_OP_NONE)
5226 			copy_reference_ldpc_enc_op(ops_enq, burst_sz, dequeued,
5227 					bufs->inputs,
5228 					bufs->hard_outputs,
5229 					ref_op);
5230 
5231 		/* Start time meas for enqueue function offload latency */
5232 		enq_start_time = rte_rdtsc_precise();
5233 		do {
5234 			enq += rte_bbdev_enqueue_ldpc_enc_ops(dev_id, queue_id,
5235 					&ops_enq[enq], burst_sz - enq);
5236 		} while (unlikely(burst_sz != enq));
5237 
5238 		enq_sw_last_time = rte_rdtsc_precise() - enq_start_time;
5239 		ret = get_bbdev_queue_stats(dev_id, queue_id, &stats);
5240 		TEST_ASSERT_SUCCESS(ret,
5241 				"Failed to get stats for queue (%u) of device (%u)",
5242 				queue_id, dev_id);
5243 
5244 		enq_sw_last_time -= stats.acc_offload_cycles;
5245 		time_st->enq_sw_max_time = RTE_MAX(time_st->enq_sw_max_time,
5246 				enq_sw_last_time);
5247 		time_st->enq_sw_min_time = RTE_MIN(time_st->enq_sw_min_time,
5248 				enq_sw_last_time);
5249 		time_st->enq_sw_total_time += enq_sw_last_time;
5250 
5251 		time_st->enq_acc_max_time = RTE_MAX(time_st->enq_acc_max_time,
5252 				stats.acc_offload_cycles);
5253 		time_st->enq_acc_min_time = RTE_MIN(time_st->enq_acc_min_time,
5254 				stats.acc_offload_cycles);
5255 		time_st->enq_acc_total_time += stats.acc_offload_cycles;
5256 
5257 		/* give time for device to process ops */
5258 		rte_delay_us(WAIT_OFFLOAD_US);
5259 
5260 		/* Start time meas for dequeue function offload latency */
5261 		deq_start_time = rte_rdtsc_precise();
5262 		/* Dequeue one operation */
5263 		do {
5264 			deq += rte_bbdev_dequeue_ldpc_enc_ops(dev_id, queue_id,
5265 					&ops_deq[deq], enq);
5266 		} while (unlikely(deq == 0));
5267 
5268 		deq_last_time = rte_rdtsc_precise() - deq_start_time;
5269 		time_st->deq_max_time = RTE_MAX(time_st->deq_max_time,
5270 				deq_last_time);
5271 		time_st->deq_min_time = RTE_MIN(time_st->deq_min_time,
5272 				deq_last_time);
5273 		time_st->deq_total_time += deq_last_time;
5274 
5275 		while (burst_sz != deq)
5276 			deq += rte_bbdev_dequeue_ldpc_enc_ops(dev_id, queue_id,
5277 					&ops_deq[deq], burst_sz - deq);
5278 
5279 		rte_bbdev_enc_op_free_bulk(ops_enq, deq);
5280 		dequeued += deq;
5281 	}
5282 
5283 	return i;
5284 }
5285 #endif
5286 
5287 static int
5288 offload_cost_test(struct active_device *ad,
5289 		struct test_op_params *op_params)
5290 {
5291 #ifndef RTE_BBDEV_OFFLOAD_COST
5292 	RTE_SET_USED(ad);
5293 	RTE_SET_USED(op_params);
5294 	printf("Offload latency test is disabled.\n");
5295 	printf("Set RTE_BBDEV_OFFLOAD_COST to 'y' to turn the test on.\n");
5296 	return TEST_SKIPPED;
5297 #else
5298 	int iter;
5299 	uint16_t burst_sz = op_params->burst_sz;
5300 	const uint16_t num_to_process = op_params->num_to_process;
5301 	const enum rte_bbdev_op_type op_type = test_vector.op_type;
5302 	const uint16_t queue_id = ad->queue_ids[0];
5303 	struct test_buffers *bufs = NULL;
5304 	struct rte_bbdev_info info;
5305 	const char *op_type_str;
5306 	struct test_time_stats time_st;
5307 
5308 	memset(&time_st, 0, sizeof(struct test_time_stats));
5309 	time_st.enq_sw_min_time = UINT64_MAX;
5310 	time_st.enq_acc_min_time = UINT64_MAX;
5311 	time_st.deq_min_time = UINT64_MAX;
5312 
5313 	TEST_ASSERT_SUCCESS((burst_sz > MAX_BURST),
5314 			"BURST_SIZE should be <= %u", MAX_BURST);
5315 
5316 	rte_bbdev_info_get(ad->dev_id, &info);
5317 	bufs = &op_params->q_bufs[GET_SOCKET(info.socket_id)][queue_id];
5318 
5319 	op_type_str = rte_bbdev_op_type_str(op_type);
5320 	TEST_ASSERT_NOT_NULL(op_type_str, "Invalid op type: %u", op_type);
5321 
5322 	printf("+ ------------------------------------------------------- +\n");
5323 	printf("== test: offload latency test\ndev: %s, burst size: %u, num ops: %u, op type: %s\n",
5324 			info.dev_name, burst_sz, num_to_process, op_type_str);
5325 
5326 	if (op_type == RTE_BBDEV_OP_TURBO_DEC)
5327 		iter = offload_latency_test_dec(op_params->mp, bufs,
5328 				op_params->ref_dec_op, ad->dev_id, queue_id,
5329 				num_to_process, burst_sz, &time_st);
5330 	else if (op_type == RTE_BBDEV_OP_TURBO_ENC)
5331 		iter = offload_latency_test_enc(op_params->mp, bufs,
5332 				op_params->ref_enc_op, ad->dev_id, queue_id,
5333 				num_to_process, burst_sz, &time_st);
5334 	else if (op_type == RTE_BBDEV_OP_LDPC_ENC)
5335 		iter = offload_latency_test_ldpc_enc(op_params->mp, bufs,
5336 				op_params->ref_enc_op, ad->dev_id, queue_id,
5337 				num_to_process, burst_sz, &time_st);
5338 	else if (op_type == RTE_BBDEV_OP_LDPC_DEC)
5339 		iter = offload_latency_test_ldpc_dec(op_params->mp, bufs,
5340 			op_params->ref_dec_op, ad->dev_id, queue_id,
5341 			num_to_process, burst_sz, &time_st);
5342 	else if (op_type == RTE_BBDEV_OP_FFT)
5343 		iter = offload_latency_test_fft(op_params->mp, bufs,
5344 			op_params->ref_fft_op, ad->dev_id, queue_id,
5345 			num_to_process, burst_sz, &time_st);
5346 	else
5347 		iter = offload_latency_test_enc(op_params->mp, bufs,
5348 				op_params->ref_enc_op, ad->dev_id, queue_id,
5349 				num_to_process, burst_sz, &time_st);
5350 
5351 	if (iter <= 0)
5352 		return TEST_FAILED;
5353 
5354 	printf("Enqueue driver offload cost latency:\n"
5355 			"\tavg: %lg cycles, %lg us\n"
5356 			"\tmin: %lg cycles, %lg us\n"
5357 			"\tmax: %lg cycles, %lg us\n"
5358 			"Enqueue accelerator offload cost latency:\n"
5359 			"\tavg: %lg cycles, %lg us\n"
5360 			"\tmin: %lg cycles, %lg us\n"
5361 			"\tmax: %lg cycles, %lg us\n",
5362 			(double)time_st.enq_sw_total_time / (double)iter,
5363 			(double)(time_st.enq_sw_total_time * 1000000) /
5364 			(double)iter / (double)rte_get_tsc_hz(),
5365 			(double)time_st.enq_sw_min_time,
5366 			(double)(time_st.enq_sw_min_time * 1000000) /
5367 			rte_get_tsc_hz(), (double)time_st.enq_sw_max_time,
5368 			(double)(time_st.enq_sw_max_time * 1000000) /
5369 			rte_get_tsc_hz(), (double)time_st.enq_acc_total_time /
5370 			(double)iter,
5371 			(double)(time_st.enq_acc_total_time * 1000000) /
5372 			(double)iter / (double)rte_get_tsc_hz(),
5373 			(double)time_st.enq_acc_min_time,
5374 			(double)(time_st.enq_acc_min_time * 1000000) /
5375 			rte_get_tsc_hz(), (double)time_st.enq_acc_max_time,
5376 			(double)(time_st.enq_acc_max_time * 1000000) /
5377 			rte_get_tsc_hz());
5378 
5379 	printf("Dequeue offload cost latency - one op:\n"
5380 			"\tavg: %lg cycles, %lg us\n"
5381 			"\tmin: %lg cycles, %lg us\n"
5382 			"\tmax: %lg cycles, %lg us\n",
5383 			(double)time_st.deq_total_time / (double)iter,
5384 			(double)(time_st.deq_total_time * 1000000) /
5385 			(double)iter / (double)rte_get_tsc_hz(),
5386 			(double)time_st.deq_min_time,
5387 			(double)(time_st.deq_min_time * 1000000) /
5388 			rte_get_tsc_hz(), (double)time_st.deq_max_time,
5389 			(double)(time_st.deq_max_time * 1000000) /
5390 			rte_get_tsc_hz());
5391 
5392 	struct rte_bbdev_stats stats = {0};
5393 	get_bbdev_queue_stats(ad->dev_id, queue_id, &stats);
5394 	if (op_type != RTE_BBDEV_OP_LDPC_DEC) {
5395 		TEST_ASSERT_SUCCESS(stats.enqueued_count != num_to_process,
5396 				"Mismatch in enqueue count %10"PRIu64" %d",
5397 				stats.enqueued_count, num_to_process);
5398 		TEST_ASSERT_SUCCESS(stats.dequeued_count != num_to_process,
5399 				"Mismatch in dequeue count %10"PRIu64" %d",
5400 				stats.dequeued_count, num_to_process);
5401 	}
5402 	TEST_ASSERT_SUCCESS(stats.enqueue_err_count != 0,
5403 			"Enqueue count Error %10"PRIu64"",
5404 			stats.enqueue_err_count);
5405 	TEST_ASSERT_SUCCESS(stats.dequeue_err_count != 0,
5406 			"Dequeue count Error (%10"PRIu64"",
5407 			stats.dequeue_err_count);
5408 
5409 	return TEST_SUCCESS;
5410 #endif
5411 }
5412 
5413 #ifdef RTE_BBDEV_OFFLOAD_COST
5414 static int
5415 offload_latency_empty_q_test_dec(uint16_t dev_id, uint16_t queue_id,
5416 		const uint16_t num_to_process, uint16_t burst_sz,
5417 		uint64_t *deq_total_time, uint64_t *deq_min_time,
5418 		uint64_t *deq_max_time, const enum rte_bbdev_op_type op_type)
5419 {
5420 	int i, deq_total;
5421 	struct rte_bbdev_dec_op *ops[MAX_BURST];
5422 	uint64_t deq_start_time, deq_last_time;
5423 
5424 	/* Test deq offload latency from an empty queue */
5425 
5426 	for (i = 0, deq_total = 0; deq_total < num_to_process;
5427 			++i, deq_total += burst_sz) {
5428 		deq_start_time = rte_rdtsc_precise();
5429 
5430 		if (unlikely(num_to_process - deq_total < burst_sz))
5431 			burst_sz = num_to_process - deq_total;
5432 		if (op_type == RTE_BBDEV_OP_LDPC_DEC)
5433 			rte_bbdev_dequeue_ldpc_dec_ops(dev_id, queue_id, ops,
5434 					burst_sz);
5435 		else
5436 			rte_bbdev_dequeue_dec_ops(dev_id, queue_id, ops,
5437 					burst_sz);
5438 
5439 		deq_last_time = rte_rdtsc_precise() - deq_start_time;
5440 		*deq_max_time = RTE_MAX(*deq_max_time, deq_last_time);
5441 		*deq_min_time = RTE_MIN(*deq_min_time, deq_last_time);
5442 		*deq_total_time += deq_last_time;
5443 	}
5444 
5445 	return i;
5446 }
5447 
5448 static int
5449 offload_latency_empty_q_test_enc(uint16_t dev_id, uint16_t queue_id,
5450 		const uint16_t num_to_process, uint16_t burst_sz,
5451 		uint64_t *deq_total_time, uint64_t *deq_min_time,
5452 		uint64_t *deq_max_time, const enum rte_bbdev_op_type op_type)
5453 {
5454 	int i, deq_total;
5455 	struct rte_bbdev_enc_op *ops[MAX_BURST];
5456 	uint64_t deq_start_time, deq_last_time;
5457 
5458 	/* Test deq offload latency from an empty queue */
5459 	for (i = 0, deq_total = 0; deq_total < num_to_process;
5460 			++i, deq_total += burst_sz) {
5461 		deq_start_time = rte_rdtsc_precise();
5462 
5463 		if (unlikely(num_to_process - deq_total < burst_sz))
5464 			burst_sz = num_to_process - deq_total;
5465 		if (op_type == RTE_BBDEV_OP_LDPC_ENC)
5466 			rte_bbdev_dequeue_ldpc_enc_ops(dev_id, queue_id, ops,
5467 					burst_sz);
5468 		else
5469 			rte_bbdev_dequeue_enc_ops(dev_id, queue_id, ops,
5470 					burst_sz);
5471 
5472 		deq_last_time = rte_rdtsc_precise() - deq_start_time;
5473 		*deq_max_time = RTE_MAX(*deq_max_time, deq_last_time);
5474 		*deq_min_time = RTE_MIN(*deq_min_time, deq_last_time);
5475 		*deq_total_time += deq_last_time;
5476 	}
5477 
5478 	return i;
5479 }
5480 
5481 #endif
5482 
5483 static int
5484 offload_latency_empty_q_test(struct active_device *ad,
5485 		struct test_op_params *op_params)
5486 {
5487 #ifndef RTE_BBDEV_OFFLOAD_COST
5488 	RTE_SET_USED(ad);
5489 	RTE_SET_USED(op_params);
5490 	printf("Offload latency empty dequeue test is disabled.\n");
5491 	printf("Set RTE_BBDEV_OFFLOAD_COST to 'y' to turn the test on.\n");
5492 	return TEST_SKIPPED;
5493 #else
5494 	int iter;
5495 	uint64_t deq_total_time, deq_min_time, deq_max_time;
5496 	uint16_t burst_sz = op_params->burst_sz;
5497 	const uint16_t num_to_process = op_params->num_to_process;
5498 	const enum rte_bbdev_op_type op_type = test_vector.op_type;
5499 	const uint16_t queue_id = ad->queue_ids[0];
5500 	struct rte_bbdev_info info;
5501 	const char *op_type_str;
5502 
5503 	deq_total_time = deq_max_time = 0;
5504 	deq_min_time = UINT64_MAX;
5505 
5506 	TEST_ASSERT_SUCCESS((burst_sz > MAX_BURST),
5507 			"BURST_SIZE should be <= %u", MAX_BURST);
5508 
5509 	rte_bbdev_info_get(ad->dev_id, &info);
5510 
5511 	op_type_str = rte_bbdev_op_type_str(op_type);
5512 	TEST_ASSERT_NOT_NULL(op_type_str, "Invalid op type: %u", op_type);
5513 
5514 	printf("+ ------------------------------------------------------- +\n");
5515 	printf("== test: offload latency empty dequeue\ndev: %s, burst size: %u, num ops: %u, op type: %s\n",
5516 			info.dev_name, burst_sz, num_to_process, op_type_str);
5517 
5518 	if (op_type == RTE_BBDEV_OP_TURBO_DEC ||
5519 			op_type == RTE_BBDEV_OP_LDPC_DEC)
5520 		iter = offload_latency_empty_q_test_dec(ad->dev_id, queue_id,
5521 				num_to_process, burst_sz, &deq_total_time,
5522 				&deq_min_time, &deq_max_time, op_type);
5523 	else
5524 		iter = offload_latency_empty_q_test_enc(ad->dev_id, queue_id,
5525 				num_to_process, burst_sz, &deq_total_time,
5526 				&deq_min_time, &deq_max_time, op_type);
5527 
5528 	if (iter <= 0)
5529 		return TEST_FAILED;
5530 
5531 	printf("Empty dequeue offload:\n"
5532 			"\tavg: %lg cycles, %lg us\n"
5533 			"\tmin: %lg cycles, %lg us\n"
5534 			"\tmax: %lg cycles, %lg us\n",
5535 			(double)deq_total_time / (double)iter,
5536 			(double)(deq_total_time * 1000000) / (double)iter /
5537 			(double)rte_get_tsc_hz(), (double)deq_min_time,
5538 			(double)(deq_min_time * 1000000) / rte_get_tsc_hz(),
5539 			(double)deq_max_time, (double)(deq_max_time * 1000000) /
5540 			rte_get_tsc_hz());
5541 
5542 	return TEST_SUCCESS;
5543 #endif
5544 }
5545 
5546 static int
5547 bler_tc(void)
5548 {
5549 	return run_test_case(bler_test);
5550 }
5551 
5552 static int
5553 throughput_tc(void)
5554 {
5555 	return run_test_case(throughput_test);
5556 }
5557 
5558 static int
5559 offload_cost_tc(void)
5560 {
5561 	return run_test_case(offload_cost_test);
5562 }
5563 
5564 static int
5565 offload_latency_empty_q_tc(void)
5566 {
5567 	return run_test_case(offload_latency_empty_q_test);
5568 }
5569 
5570 static int
5571 latency_tc(void)
5572 {
5573 	return run_test_case(latency_test);
5574 }
5575 
5576 static int
5577 validation_tc(void)
5578 {
5579 	return run_test_case(validation_test);
5580 }
5581 
5582 static int
5583 interrupt_tc(void)
5584 {
5585 	return run_test_case(throughput_test);
5586 }
5587 
5588 static struct unit_test_suite bbdev_bler_testsuite = {
5589 	.suite_name = "BBdev BLER Tests",
5590 	.setup = testsuite_setup,
5591 	.teardown = testsuite_teardown,
5592 	.unit_test_cases = {
5593 		TEST_CASE_ST(ut_setup, ut_teardown, bler_tc),
5594 		TEST_CASES_END() /**< NULL terminate unit test array */
5595 	}
5596 };
5597 
5598 static struct unit_test_suite bbdev_throughput_testsuite = {
5599 	.suite_name = "BBdev Throughput Tests",
5600 	.setup = testsuite_setup,
5601 	.teardown = testsuite_teardown,
5602 	.unit_test_cases = {
5603 		TEST_CASE_ST(ut_setup, ut_teardown, throughput_tc),
5604 		TEST_CASES_END() /**< NULL terminate unit test array */
5605 	}
5606 };
5607 
5608 static struct unit_test_suite bbdev_validation_testsuite = {
5609 	.suite_name = "BBdev Validation Tests",
5610 	.setup = testsuite_setup,
5611 	.teardown = testsuite_teardown,
5612 	.unit_test_cases = {
5613 		TEST_CASE_ST(ut_setup, ut_teardown, validation_tc),
5614 		TEST_CASES_END() /**< NULL terminate unit test array */
5615 	}
5616 };
5617 
5618 static struct unit_test_suite bbdev_latency_testsuite = {
5619 	.suite_name = "BBdev Latency Tests",
5620 	.setup = testsuite_setup,
5621 	.teardown = testsuite_teardown,
5622 	.unit_test_cases = {
5623 		TEST_CASE_ST(ut_setup, ut_teardown, latency_tc),
5624 		TEST_CASES_END() /**< NULL terminate unit test array */
5625 	}
5626 };
5627 
5628 static struct unit_test_suite bbdev_offload_cost_testsuite = {
5629 	.suite_name = "BBdev Offload Cost Tests",
5630 	.setup = testsuite_setup,
5631 	.teardown = testsuite_teardown,
5632 	.unit_test_cases = {
5633 		TEST_CASE_ST(ut_setup, ut_teardown, offload_cost_tc),
5634 		TEST_CASE_ST(ut_setup, ut_teardown, offload_latency_empty_q_tc),
5635 		TEST_CASES_END() /**< NULL terminate unit test array */
5636 	}
5637 };
5638 
5639 static struct unit_test_suite bbdev_interrupt_testsuite = {
5640 	.suite_name = "BBdev Interrupt Tests",
5641 	.setup = interrupt_testsuite_setup,
5642 	.teardown = testsuite_teardown,
5643 	.unit_test_cases = {
5644 		TEST_CASE_ST(ut_setup, ut_teardown, interrupt_tc),
5645 		TEST_CASES_END() /**< NULL terminate unit test array */
5646 	}
5647 };
5648 
5649 REGISTER_TEST_COMMAND(bler, bbdev_bler_testsuite);
5650 REGISTER_TEST_COMMAND(throughput, bbdev_throughput_testsuite);
5651 REGISTER_TEST_COMMAND(validation, bbdev_validation_testsuite);
5652 REGISTER_TEST_COMMAND(latency, bbdev_latency_testsuite);
5653 REGISTER_TEST_COMMAND(offload, bbdev_offload_cost_testsuite);
5654 REGISTER_TEST_COMMAND(interrupt, bbdev_interrupt_testsuite);
5655