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