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