xref: /dpdk/drivers/baseband/fpga_5gnr_fec/rte_fpga_5gnr_fec.c (revision 0f4e9909bc517d845e47da803f8b534691bbe5a3)
10b5927cbSNicolas Chautru /* SPDX-License-Identifier: BSD-3-Clause
20b5927cbSNicolas Chautru  * Copyright(c) 2020 Intel Corporation
30b5927cbSNicolas Chautru  */
40b5927cbSNicolas Chautru 
50b5927cbSNicolas Chautru #include <unistd.h>
60b5927cbSNicolas Chautru 
70b5927cbSNicolas Chautru #include <rte_common.h>
80b5927cbSNicolas Chautru #include <rte_log.h>
91acb7f54SDavid Marchand #include <dev_driver.h>
100b5927cbSNicolas Chautru #include <rte_malloc.h>
110b5927cbSNicolas Chautru #include <rte_mempool.h>
120b5927cbSNicolas Chautru #include <rte_errno.h>
130b5927cbSNicolas Chautru #include <rte_pci.h>
141f37cb2bSDavid Marchand #include <bus_pci_driver.h>
150b5927cbSNicolas Chautru #include <rte_byteorder.h>
1644dc6faaSNicolas Chautru #include <rte_cycles.h>
17dd329b2cSStephen Hemminger #include <rte_random.h>
180b5927cbSNicolas Chautru 
190b5927cbSNicolas Chautru #include <rte_bbdev.h>
200b5927cbSNicolas Chautru #include <rte_bbdev_pmd.h>
210b5927cbSNicolas Chautru 
222d430643SNicolas Chautru #include "rte_pmd_fpga_5gnr_fec.h"
239e3ffd38SHernan Vargas #include "fpga_5gnr_fec.h"
240b5927cbSNicolas Chautru 
259c99878aSJerin Jacob #ifdef RTE_LIBRTE_BBDEV_DEBUG
26eeded204SDavid Marchand RTE_LOG_REGISTER_DEFAULT(fpga_5gnr_fec_logtype, DEBUG);
279c99878aSJerin Jacob #else
28eeded204SDavid Marchand RTE_LOG_REGISTER_DEFAULT(fpga_5gnr_fec_logtype, NOTICE);
299c99878aSJerin Jacob #endif
300b5927cbSNicolas Chautru 
3111b0a112SNicolas Chautru #ifdef RTE_LIBRTE_BBDEV_DEBUG
3211b0a112SNicolas Chautru 
3311b0a112SNicolas Chautru /* Read Ring Control Register of FPGA 5GNR FEC device */
3411b0a112SNicolas Chautru static inline void
3511b0a112SNicolas Chautru print_ring_reg_debug_info(void *mmio_base, uint32_t offset)
3611b0a112SNicolas Chautru {
3711b0a112SNicolas Chautru 	rte_bbdev_log_debug(
3810829ff2SHernan Vargas 		"FPGA 5GNR MMIO base address @ %p | Ring Control Register @ offset = 0x%08"
3911b0a112SNicolas Chautru 		PRIx32, mmio_base, offset);
4011b0a112SNicolas Chautru 	rte_bbdev_log_debug(
4111b0a112SNicolas Chautru 		"RING_BASE_ADDR = 0x%016"PRIx64,
4210829ff2SHernan Vargas 		fpga_5gnr_reg_read_64(mmio_base, offset));
4311b0a112SNicolas Chautru 	rte_bbdev_log_debug(
4411b0a112SNicolas Chautru 		"RING_HEAD_ADDR = 0x%016"PRIx64,
4510829ff2SHernan Vargas 		fpga_5gnr_reg_read_64(mmio_base, offset +
4611b0a112SNicolas Chautru 				FPGA_5GNR_FEC_RING_HEAD_ADDR));
4711b0a112SNicolas Chautru 	rte_bbdev_log_debug(
4811b0a112SNicolas Chautru 		"RING_SIZE = 0x%04"PRIx16,
4910829ff2SHernan Vargas 		fpga_5gnr_reg_read_16(mmio_base, offset +
5011b0a112SNicolas Chautru 				FPGA_5GNR_FEC_RING_SIZE));
5111b0a112SNicolas Chautru 	rte_bbdev_log_debug(
5211b0a112SNicolas Chautru 		"RING_MISC = 0x%02"PRIx8,
5310829ff2SHernan Vargas 		fpga_5gnr_reg_read_8(mmio_base, offset +
5411b0a112SNicolas Chautru 				FPGA_5GNR_FEC_RING_MISC));
5511b0a112SNicolas Chautru 	rte_bbdev_log_debug(
5611b0a112SNicolas Chautru 		"RING_ENABLE = 0x%02"PRIx8,
5710829ff2SHernan Vargas 		fpga_5gnr_reg_read_8(mmio_base, offset +
5811b0a112SNicolas Chautru 				FPGA_5GNR_FEC_RING_ENABLE));
5911b0a112SNicolas Chautru 	rte_bbdev_log_debug(
6011b0a112SNicolas Chautru 		"RING_FLUSH_QUEUE_EN = 0x%02"PRIx8,
6110829ff2SHernan Vargas 		fpga_5gnr_reg_read_8(mmio_base, offset +
6211b0a112SNicolas Chautru 				FPGA_5GNR_FEC_RING_FLUSH_QUEUE_EN));
6311b0a112SNicolas Chautru 	rte_bbdev_log_debug(
6411b0a112SNicolas Chautru 		"RING_SHADOW_TAIL = 0x%04"PRIx16,
6510829ff2SHernan Vargas 		fpga_5gnr_reg_read_16(mmio_base, offset +
6611b0a112SNicolas Chautru 				FPGA_5GNR_FEC_RING_SHADOW_TAIL));
6711b0a112SNicolas Chautru 	rte_bbdev_log_debug(
6811b0a112SNicolas Chautru 		"RING_HEAD_POINT = 0x%04"PRIx16,
6910829ff2SHernan Vargas 		fpga_5gnr_reg_read_16(mmio_base, offset +
7011b0a112SNicolas Chautru 				FPGA_5GNR_FEC_RING_HEAD_POINT));
7111b0a112SNicolas Chautru }
7211b0a112SNicolas Chautru 
73c750d277SHernan Vargas /* Read Static Register of Vista Creek device. */
7411b0a112SNicolas Chautru static inline void
759e3ffd38SHernan Vargas print_static_reg_debug_info(void *mmio_base, uint8_t fpga_variant)
7611b0a112SNicolas Chautru {
779e3ffd38SHernan Vargas 	uint16_t config;
789e3ffd38SHernan Vargas 	uint8_t qmap_done = fpga_5gnr_reg_read_8(mmio_base, FPGA_5GNR_FEC_QUEUE_PF_VF_MAP_DONE);
799e3ffd38SHernan Vargas 	uint16_t lb_factor = fpga_5gnr_reg_read_16(mmio_base, FPGA_5GNR_FEC_LOAD_BALANCE_FACTOR);
809e3ffd38SHernan Vargas 	uint16_t ring_desc_len = fpga_5gnr_reg_read_16(mmio_base, FPGA_5GNR_FEC_RING_DESC_LEN);
819e3ffd38SHernan Vargas 	if (fpga_variant == VC_5GNR_FPGA_VARIANT)
829e3ffd38SHernan Vargas 		config = fpga_5gnr_reg_read_16(mmio_base, VC_5GNR_CONFIGURATION);
8311b0a112SNicolas Chautru 
849e3ffd38SHernan Vargas 	if (fpga_variant == VC_5GNR_FPGA_VARIANT)
8511b0a112SNicolas Chautru 		rte_bbdev_log_debug("UL.DL Weights = %u.%u",
8611b0a112SNicolas Chautru 				((uint8_t)config), ((uint8_t)(config >> 8)));
8711b0a112SNicolas Chautru 	rte_bbdev_log_debug("UL.DL Load Balance = %u.%u",
8811b0a112SNicolas Chautru 			((uint8_t)lb_factor), ((uint8_t)(lb_factor >> 8)));
8911b0a112SNicolas Chautru 	rte_bbdev_log_debug("Queue-PF/VF Mapping Table = %s",
9011b0a112SNicolas Chautru 			(qmap_done > 0) ? "READY" : "NOT-READY");
919e3ffd38SHernan Vargas 	if (fpga_variant == VC_5GNR_FPGA_VARIANT)
9211b0a112SNicolas Chautru 		rte_bbdev_log_debug("Ring Descriptor Size = %u bytes",
93c750d277SHernan Vargas 				ring_desc_len * VC_5GNR_RING_DESC_LEN_UNIT_BYTES);
949e3ffd38SHernan Vargas 	else
959e3ffd38SHernan Vargas 		rte_bbdev_log_debug("Ring Descriptor Size = %u bytes",
969e3ffd38SHernan Vargas 				ring_desc_len * AGX100_RING_DESC_LEN_UNIT_BYTES);
9711b0a112SNicolas Chautru }
9811b0a112SNicolas Chautru 
99c750d277SHernan Vargas /* Print decode DMA Descriptor of Vista Creek Decoder device. */
10011b0a112SNicolas Chautru static void
101c750d277SHernan Vargas vc_5gnr_print_dma_dec_desc_debug_info(union vc_5gnr_dma_desc *desc)
10211b0a112SNicolas Chautru {
1031af8b0b2SDavid Marchand 	rte_bbdev_log_debug("DMA response desc %p",
1041af8b0b2SDavid Marchand 			desc);
1051af8b0b2SDavid Marchand 	rte_bbdev_log_debug("\t-- done(%"PRIu32") | iter(%"PRIu32") | et_pass(%"PRIu32")"
1061af8b0b2SDavid Marchand 			" | crcb_pass (%"PRIu32") | error(%"PRIu32")",
10711b0a112SNicolas Chautru 			(uint32_t)desc->dec_req.done,
10811b0a112SNicolas Chautru 			(uint32_t)desc->dec_req.iter,
10911b0a112SNicolas Chautru 			(uint32_t)desc->dec_req.et_pass,
11011b0a112SNicolas Chautru 			(uint32_t)desc->dec_req.crcb_pass,
1111af8b0b2SDavid Marchand 			(uint32_t)desc->dec_req.error);
1121af8b0b2SDavid Marchand 	rte_bbdev_log_debug("\t-- qm_idx(%"PRIu32") | max_iter(%"PRIu32") | "
1131af8b0b2SDavid Marchand 			"bg_idx (%"PRIu32") | harqin_en(%"PRIu32") | zc(%"PRIu32")",
11411b0a112SNicolas Chautru 			(uint32_t)desc->dec_req.qm_idx,
11511b0a112SNicolas Chautru 			(uint32_t)desc->dec_req.max_iter,
11611b0a112SNicolas Chautru 			(uint32_t)desc->dec_req.bg_idx,
11711b0a112SNicolas Chautru 			(uint32_t)desc->dec_req.harqin_en,
1181af8b0b2SDavid Marchand 			(uint32_t)desc->dec_req.zc);
1191af8b0b2SDavid Marchand 	rte_bbdev_log_debug("\t-- hbstroe_offset(%"PRIu32") | num_null (%"PRIu32") "
1201af8b0b2SDavid Marchand 			"| irq_en(%"PRIu32")",
12111b0a112SNicolas Chautru 			(uint32_t)desc->dec_req.hbstroe_offset,
12211b0a112SNicolas Chautru 			(uint32_t)desc->dec_req.num_null,
1231af8b0b2SDavid Marchand 			(uint32_t)desc->dec_req.irq_en);
1241af8b0b2SDavid Marchand 	rte_bbdev_log_debug("\t-- ncb(%"PRIu32") | desc_idx (%"PRIu32") | "
1251af8b0b2SDavid Marchand 			"drop_crc24b(%"PRIu32") | RV (%"PRIu32")",
12611b0a112SNicolas Chautru 			(uint32_t)desc->dec_req.ncb,
12711b0a112SNicolas Chautru 			(uint32_t)desc->dec_req.desc_idx,
12811b0a112SNicolas Chautru 			(uint32_t)desc->dec_req.drop_crc24b,
1291af8b0b2SDavid Marchand 			(uint32_t)desc->dec_req.rv);
1301af8b0b2SDavid Marchand 	rte_bbdev_log_debug("\t-- crc24b_ind(%"PRIu32") | et_dis (%"PRIu32")",
13111b0a112SNicolas Chautru 			(uint32_t)desc->dec_req.crc24b_ind,
1321af8b0b2SDavid Marchand 			(uint32_t)desc->dec_req.et_dis);
1331af8b0b2SDavid Marchand 	rte_bbdev_log_debug("\t-- harq_input_length(%"PRIu32") | rm_e(%"PRIu32")",
13411b0a112SNicolas Chautru 			(uint32_t)desc->dec_req.harq_input_length,
1351af8b0b2SDavid Marchand 			(uint32_t)desc->dec_req.rm_e);
1361af8b0b2SDavid Marchand 	rte_bbdev_log_debug("\t-- cbs_in_op(%"PRIu32") | in_add (0x%08"PRIx32"%08"PRIx32")"
1371af8b0b2SDavid Marchand 			"| out_add (0x%08"PRIx32"%08"PRIx32")",
13811b0a112SNicolas Chautru 			(uint32_t)desc->dec_req.cbs_in_op,
13911b0a112SNicolas Chautru 			(uint32_t)desc->dec_req.in_addr_hi,
14011b0a112SNicolas Chautru 			(uint32_t)desc->dec_req.in_addr_lw,
14111b0a112SNicolas Chautru 			(uint32_t)desc->dec_req.out_addr_hi,
14211b0a112SNicolas Chautru 			(uint32_t)desc->dec_req.out_addr_lw);
14311b0a112SNicolas Chautru 	uint32_t *word = (uint32_t *) desc;
1441af8b0b2SDavid Marchand 	rte_bbdev_log_debug("%08"PRIx32", %08"PRIx32", %08"PRIx32", %08"PRIx32", "
1451af8b0b2SDavid Marchand 			"%08"PRIx32", %08"PRIx32", %08"PRIx32", %08"PRIx32,
14611b0a112SNicolas Chautru 			word[0], word[1], word[2], word[3],
14711b0a112SNicolas Chautru 			word[4], word[5], word[6], word[7]);
14811b0a112SNicolas Chautru }
14911b0a112SNicolas Chautru 
1509e3ffd38SHernan Vargas /* Print decode DMA Descriptor of AGX100 Decoder device. */
1519e3ffd38SHernan Vargas static void
1529e3ffd38SHernan Vargas agx100_print_dma_dec_desc_debug_info(union agx100_dma_desc *desc)
1539e3ffd38SHernan Vargas {
1541af8b0b2SDavid Marchand 	rte_bbdev_log_debug("DMA response desc %p",
1551af8b0b2SDavid Marchand 			desc);
1561af8b0b2SDavid Marchand 	rte_bbdev_log_debug("\t-- done(%"PRIu32") | tb_crc_pass(%"PRIu32") | cb_crc_all_pass(%"PRIu32")"
1579e3ffd38SHernan Vargas 			" | cb_all_et_pass(%"PRIu32") | max_iter_ret(%"PRIu32") |"
1589e3ffd38SHernan Vargas 			"cgb_crc_bitmap(%"PRIu32") | error_msg(%"PRIu32") | error_code(%"PRIu32") |"
1591af8b0b2SDavid Marchand 			"et_dis (%"PRIu32") | harq_in_en(%"PRIu32") | max_iter(%"PRIu32")",
1609e3ffd38SHernan Vargas 			(uint32_t)desc->dec_req.done,
1619e3ffd38SHernan Vargas 			(uint32_t)desc->dec_req.tb_crc_pass,
1629e3ffd38SHernan Vargas 			(uint32_t)desc->dec_req.cb_crc_all_pass,
1639e3ffd38SHernan Vargas 			(uint32_t)desc->dec_req.cb_all_et_pass,
1649e3ffd38SHernan Vargas 			(uint32_t)desc->dec_req.max_iter_ret,
1659e3ffd38SHernan Vargas 			(uint32_t)desc->dec_req.cgb_crc_bitmap,
1669e3ffd38SHernan Vargas 			(uint32_t)desc->dec_req.error_msg,
1679e3ffd38SHernan Vargas 			(uint32_t)desc->dec_req.error_code,
1689e3ffd38SHernan Vargas 			(uint32_t)desc->dec_req.et_dis,
1699e3ffd38SHernan Vargas 			(uint32_t)desc->dec_req.harq_in_en,
1701af8b0b2SDavid Marchand 			(uint32_t)desc->dec_req.max_iter);
1711af8b0b2SDavid Marchand 	rte_bbdev_log_debug("\t-- ncb(%"PRIu32") | bg_idx (%"PRIu32") | qm_idx (%"PRIu32")"
1721af8b0b2SDavid Marchand 			"| zc(%"PRIu32") | rv(%"PRIu32") | int_en(%"PRIu32")",
1739e3ffd38SHernan Vargas 			(uint32_t)desc->dec_req.ncb,
1749e3ffd38SHernan Vargas 			(uint32_t)desc->dec_req.bg_idx,
1759e3ffd38SHernan Vargas 			(uint32_t)desc->dec_req.qm_idx,
1769e3ffd38SHernan Vargas 			(uint32_t)desc->dec_req.zc,
1779e3ffd38SHernan Vargas 			(uint32_t)desc->dec_req.rv,
1781af8b0b2SDavid Marchand 			(uint32_t)desc->dec_req.int_en);
1791af8b0b2SDavid Marchand 	rte_bbdev_log_debug("\t-- max_cbg(%"PRIu32") | cbgti(%"PRIu32") | cbgfi(%"PRIu32") |"
1801af8b0b2SDavid Marchand 			"cbgs(%"PRIu32") | desc_idx(%"PRIu32")",
1819e3ffd38SHernan Vargas 			(uint32_t)desc->dec_req.max_cbg,
1829e3ffd38SHernan Vargas 			(uint32_t)desc->dec_req.cbgti,
1839e3ffd38SHernan Vargas 			(uint32_t)desc->dec_req.cbgfi,
1849e3ffd38SHernan Vargas 			(uint32_t)desc->dec_req.cbgs,
1851af8b0b2SDavid Marchand 			(uint32_t)desc->dec_req.desc_idx);
1861af8b0b2SDavid Marchand 	rte_bbdev_log_debug("\t-- ca(%"PRIu32") | c(%"PRIu32") | llr_pckg(%"PRIu32") |"
1871af8b0b2SDavid Marchand 			"syndrome_check_mode(%"PRIu32") | num_null(%"PRIu32")",
1889e3ffd38SHernan Vargas 			(uint32_t)desc->dec_req.ca,
1899e3ffd38SHernan Vargas 			(uint32_t)desc->dec_req.c,
1909e3ffd38SHernan Vargas 			(uint32_t)desc->dec_req.llr_pckg,
1919e3ffd38SHernan Vargas 			(uint32_t)desc->dec_req.syndrome_check_mode,
1921af8b0b2SDavid Marchand 			(uint32_t)desc->dec_req.num_null);
1931af8b0b2SDavid Marchand 	rte_bbdev_log_debug("\t-- ea(%"PRIu32") | eba(%"PRIu32")",
1949e3ffd38SHernan Vargas 			(uint32_t)desc->dec_req.ea,
1951af8b0b2SDavid Marchand 			(uint32_t)desc->dec_req.eba);
1961af8b0b2SDavid Marchand 	rte_bbdev_log_debug("\t-- hbstore_offset_out(%"PRIu32")",
1971af8b0b2SDavid Marchand 			(uint32_t)desc->dec_req.hbstore_offset_out);
1981af8b0b2SDavid Marchand 	rte_bbdev_log_debug("\t-- hbstore_offset_in(%"PRIu32") | en_slice_ts(%"PRIu32") |"
1991af8b0b2SDavid Marchand 			"en_host_ts(%"PRIu32") | en_cb_wr_status(%"PRIu32")"
2001af8b0b2SDavid Marchand 			" | en_output_sg(%"PRIu32") | en_input_sg(%"PRIu32") | tb_cb(%"PRIu32")"
2011af8b0b2SDavid Marchand 			" | crc24b_ind(%"PRIu32")| drop_crc24b(%"PRIu32")",
2029e3ffd38SHernan Vargas 			(uint32_t)desc->dec_req.hbstore_offset_in,
2039e3ffd38SHernan Vargas 			(uint32_t)desc->dec_req.en_slice_ts,
2049e3ffd38SHernan Vargas 			(uint32_t)desc->dec_req.en_host_ts,
2059e3ffd38SHernan Vargas 			(uint32_t)desc->dec_req.en_cb_wr_status,
2069e3ffd38SHernan Vargas 			(uint32_t)desc->dec_req.en_output_sg,
2079e3ffd38SHernan Vargas 			(uint32_t)desc->dec_req.en_input_sg,
2089e3ffd38SHernan Vargas 			(uint32_t)desc->dec_req.tb_cb,
2099e3ffd38SHernan Vargas 			(uint32_t)desc->dec_req.crc24b_ind,
2101af8b0b2SDavid Marchand 			(uint32_t)desc->dec_req.drop_crc24b);
2111af8b0b2SDavid Marchand 	rte_bbdev_log_debug("\t-- harq_input_length_a(%"PRIu32") | harq_input_length_b(%"PRIu32")",
2129e3ffd38SHernan Vargas 			(uint32_t)desc->dec_req.harq_input_length_a,
2131af8b0b2SDavid Marchand 			(uint32_t)desc->dec_req.harq_input_length_b);
2141af8b0b2SDavid Marchand 	rte_bbdev_log_debug("\t-- input_slice_table_addr_lo(%"PRIu32")"
2151af8b0b2SDavid Marchand 			" | input_start_addr_lo(%"PRIu32")",
2169e3ffd38SHernan Vargas 			(uint32_t)desc->dec_req.input_slice_table_addr_lo,
2171af8b0b2SDavid Marchand 			(uint32_t)desc->dec_req.input_start_addr_lo);
2181af8b0b2SDavid Marchand 	rte_bbdev_log_debug("\t-- input_slice_table_addr_hi(%"PRIu32")"
2191af8b0b2SDavid Marchand 			" | input_start_addr_hi(%"PRIu32")",
2209e3ffd38SHernan Vargas 			(uint32_t)desc->dec_req.input_slice_table_addr_hi,
2211af8b0b2SDavid Marchand 			(uint32_t)desc->dec_req.input_start_addr_hi);
2221af8b0b2SDavid Marchand 	rte_bbdev_log_debug("\t-- input_slice_num(%"PRIu32") | input_length(%"PRIu32")",
2239e3ffd38SHernan Vargas 			(uint32_t)desc->dec_req.input_slice_num,
2241af8b0b2SDavid Marchand 			(uint32_t)desc->dec_req.input_length);
2251af8b0b2SDavid Marchand 	rte_bbdev_log_debug("\t-- output_slice_table_addr_lo(%"PRIu32")"
2261af8b0b2SDavid Marchand 			" | output_start_addr_lo(%"PRIu32")",
2279e3ffd38SHernan Vargas 			(uint32_t)desc->dec_req.output_slice_table_addr_lo,
2281af8b0b2SDavid Marchand 			(uint32_t)desc->dec_req.output_start_addr_lo);
2291af8b0b2SDavid Marchand 	rte_bbdev_log_debug("\t-- output_slice_table_addr_hi(%"PRIu32")"
2301af8b0b2SDavid Marchand 			" | output_start_addr_hi(%"PRIu32")",
2319e3ffd38SHernan Vargas 			(uint32_t)desc->dec_req.output_slice_table_addr_hi,
2321af8b0b2SDavid Marchand 			(uint32_t)desc->dec_req.output_start_addr_hi);
2331af8b0b2SDavid Marchand 	rte_bbdev_log_debug("\t-- output_slice_num(%"PRIu32") | output_length(%"PRIu32")",
2349e3ffd38SHernan Vargas 			(uint32_t)desc->dec_req.output_slice_num,
2351af8b0b2SDavid Marchand 			(uint32_t)desc->dec_req.output_length);
2361af8b0b2SDavid Marchand 	rte_bbdev_log_debug("\t-- enqueue_timestamp(%"PRIu32")",
2371af8b0b2SDavid Marchand 			(uint32_t)desc->dec_req.enqueue_timestamp);
2381af8b0b2SDavid Marchand 	rte_bbdev_log_debug("\t-- completion_timestamp(%"PRIu32")",
2399e3ffd38SHernan Vargas 			(uint32_t)desc->dec_req.completion_timestamp);
2409e3ffd38SHernan Vargas 
2419e3ffd38SHernan Vargas 	uint32_t *word = (uint32_t *) desc;
2421af8b0b2SDavid Marchand 	rte_bbdev_log_debug("%08"PRIx32", %08"PRIx32", %08"PRIx32", %08"PRIx32", "
2431af8b0b2SDavid Marchand 			"%08"PRIx32", %08"PRIx32", %08"PRIx32", %08"PRIx32", "
2441af8b0b2SDavid Marchand 			"%08"PRIx32", %08"PRIx32", %08"PRIx32", %08"PRIx32", "
2451af8b0b2SDavid Marchand 			"%08"PRIx32", %08"PRIx32", %08"PRIx32", %08"PRIx32,
2469e3ffd38SHernan Vargas 			word[0], word[1], word[2], word[3],
2479e3ffd38SHernan Vargas 			word[4], word[5], word[6], word[7],
2489e3ffd38SHernan Vargas 			word[8], word[9], word[10], word[11],
2499e3ffd38SHernan Vargas 			word[12], word[13], word[14], word[15]);
2509e3ffd38SHernan Vargas }
2519e3ffd38SHernan Vargas 
252c750d277SHernan Vargas /* Print decode DMA Descriptor of Vista Creek encoder device. */
25311b0a112SNicolas Chautru static void
254c750d277SHernan Vargas vc_5gnr_print_dma_enc_desc_debug_info(union vc_5gnr_dma_desc *desc)
25511b0a112SNicolas Chautru {
2561af8b0b2SDavid Marchand 	rte_bbdev_log_debug("DMA response desc %p",
2571af8b0b2SDavid Marchand 			desc);
2581af8b0b2SDavid Marchand 	rte_bbdev_log_debug("%"PRIu32" %"PRIu32,
25911b0a112SNicolas Chautru 			(uint32_t)desc->enc_req.done,
2601af8b0b2SDavid Marchand 			(uint32_t)desc->enc_req.error);
2611af8b0b2SDavid Marchand 	rte_bbdev_log_debug("K' %"PRIu32" E %"PRIu32" desc %"PRIu32" Z %"PRIu32,
26211b0a112SNicolas Chautru 			(uint32_t)desc->enc_req.k_,
26311b0a112SNicolas Chautru 			(uint32_t)desc->enc_req.rm_e,
26411b0a112SNicolas Chautru 			(uint32_t)desc->enc_req.desc_idx,
2651af8b0b2SDavid Marchand 			(uint32_t)desc->enc_req.zc);
2661af8b0b2SDavid Marchand 	rte_bbdev_log_debug("BG %"PRIu32" Qm %"PRIu32" CRC %"PRIu32" IRQ %"PRIu32,
26711b0a112SNicolas Chautru 			(uint32_t)desc->enc_req.bg_idx,
26811b0a112SNicolas Chautru 			(uint32_t)desc->enc_req.qm_idx,
26911b0a112SNicolas Chautru 			(uint32_t)desc->enc_req.crc_en,
2701af8b0b2SDavid Marchand 			(uint32_t)desc->enc_req.irq_en);
2711af8b0b2SDavid Marchand 	rte_bbdev_log_debug("k0 %"PRIu32" Ncb %"PRIu32" F %"PRIu32,
27211b0a112SNicolas Chautru 			(uint32_t)desc->enc_req.k0,
27311b0a112SNicolas Chautru 			(uint32_t)desc->enc_req.ncb,
27411b0a112SNicolas Chautru 			(uint32_t)desc->enc_req.num_null);
27511b0a112SNicolas Chautru 	uint32_t *word = (uint32_t *) desc;
2761af8b0b2SDavid Marchand 	rte_bbdev_log_debug("%08"PRIx32", %08"PRIx32", %08"PRIx32", %08"PRIx32", "
2771af8b0b2SDavid Marchand 			"%08"PRIx32", %08"PRIx32", %08"PRIx32", %08"PRIx32,
27811b0a112SNicolas Chautru 			word[0], word[1], word[2], word[3],
27911b0a112SNicolas Chautru 			word[4], word[5], word[6], word[7]);
28011b0a112SNicolas Chautru }
28111b0a112SNicolas Chautru 
2829e3ffd38SHernan Vargas /* Print decode DMA Descriptor of AGX100 encoder device. */
2839e3ffd38SHernan Vargas static void
2849e3ffd38SHernan Vargas agx100_print_dma_enc_desc_debug_info(union agx100_dma_desc *desc)
2859e3ffd38SHernan Vargas {
2861af8b0b2SDavid Marchand 	rte_bbdev_log_debug("DMA response desc %p",
2871af8b0b2SDavid Marchand 			desc);
2881af8b0b2SDavid Marchand 	rte_bbdev_log_debug("\t-- done(%"PRIu32") | error_msg(%"PRIu32") | error_code(%"PRIu32")",
2899e3ffd38SHernan Vargas 			(uint32_t)desc->enc_req.done,
2909e3ffd38SHernan Vargas 			(uint32_t)desc->enc_req.error_msg,
2911af8b0b2SDavid Marchand 			(uint32_t)desc->enc_req.error_code);
2921af8b0b2SDavid Marchand 	rte_bbdev_log_debug("\t-- ncb(%"PRIu32") | bg_idx (%"PRIu32") | qm_idx (%"PRIu32")"
2931af8b0b2SDavid Marchand 			"| zc(%"PRIu32") | rv(%"PRIu32") | int_en(%"PRIu32")",
2949e3ffd38SHernan Vargas 			(uint32_t)desc->enc_req.ncb,
2959e3ffd38SHernan Vargas 			(uint32_t)desc->enc_req.bg_idx,
2969e3ffd38SHernan Vargas 			(uint32_t)desc->enc_req.qm_idx,
2979e3ffd38SHernan Vargas 			(uint32_t)desc->enc_req.zc,
2989e3ffd38SHernan Vargas 			(uint32_t)desc->enc_req.rv,
2991af8b0b2SDavid Marchand 			(uint32_t)desc->enc_req.int_en);
3001af8b0b2SDavid Marchand 	rte_bbdev_log_debug("\t-- max_cbg(%"PRIu32") | cbgti(%"PRIu32") | cbgs(%"PRIu32") | "
3011af8b0b2SDavid Marchand 			"desc_idx(%"PRIu32")",
3029e3ffd38SHernan Vargas 			(uint32_t)desc->enc_req.max_cbg,
3039e3ffd38SHernan Vargas 			(uint32_t)desc->enc_req.cbgti,
3049e3ffd38SHernan Vargas 			(uint32_t)desc->enc_req.cbgs,
3051af8b0b2SDavid Marchand 			(uint32_t)desc->enc_req.desc_idx);
3061af8b0b2SDavid Marchand 	rte_bbdev_log_debug("\t-- ca(%"PRIu32") | c(%"PRIu32") | num_null(%"PRIu32")",
3079e3ffd38SHernan Vargas 			(uint32_t)desc->enc_req.ca,
3089e3ffd38SHernan Vargas 			(uint32_t)desc->enc_req.c,
3091af8b0b2SDavid Marchand 			(uint32_t)desc->enc_req.num_null);
3101af8b0b2SDavid Marchand 	rte_bbdev_log_debug("\t-- ea(%"PRIu32")",
3111af8b0b2SDavid Marchand 			(uint32_t)desc->enc_req.ea);
3121af8b0b2SDavid Marchand 	rte_bbdev_log_debug("\t-- eb(%"PRIu32")",
3131af8b0b2SDavid Marchand 			(uint32_t)desc->enc_req.eb);
3141af8b0b2SDavid Marchand 	rte_bbdev_log_debug("\t-- k_(%"PRIu32") | en_slice_ts(%"PRIu32") | en_host_ts(%"PRIu32") | "
3151af8b0b2SDavid Marchand 			"en_cb_wr_status(%"PRIu32") | en_output_sg(%"PRIu32") | "
3161af8b0b2SDavid Marchand 			"en_input_sg(%"PRIu32") | tb_cb(%"PRIu32") | crc_en(%"PRIu32")",
3179e3ffd38SHernan Vargas 			(uint32_t)desc->enc_req.k_,
3189e3ffd38SHernan Vargas 			(uint32_t)desc->enc_req.en_slice_ts,
3199e3ffd38SHernan Vargas 			(uint32_t)desc->enc_req.en_host_ts,
3209e3ffd38SHernan Vargas 			(uint32_t)desc->enc_req.en_cb_wr_status,
3219e3ffd38SHernan Vargas 			(uint32_t)desc->enc_req.en_output_sg,
3229e3ffd38SHernan Vargas 			(uint32_t)desc->enc_req.en_input_sg,
3239e3ffd38SHernan Vargas 			(uint32_t)desc->enc_req.tb_cb,
3241af8b0b2SDavid Marchand 			(uint32_t)desc->enc_req.crc_en);
3251af8b0b2SDavid Marchand 	rte_bbdev_log_debug("\t-- input_slice_table_addr_lo(%"PRIu32")"
3261af8b0b2SDavid Marchand 			" | input_start_addr_lo(%"PRIu32")",
3279e3ffd38SHernan Vargas 			(uint32_t)desc->enc_req.input_slice_table_addr_lo,
3281af8b0b2SDavid Marchand 			(uint32_t)desc->enc_req.input_start_addr_lo);
3291af8b0b2SDavid Marchand 	rte_bbdev_log_debug("\t-- input_slice_table_addr_hi(%"PRIu32")"
3301af8b0b2SDavid Marchand 			" | input_start_addr_hi(%"PRIu32")",
3319e3ffd38SHernan Vargas 			(uint32_t)desc->enc_req.input_slice_table_addr_hi,
3321af8b0b2SDavid Marchand 			(uint32_t)desc->enc_req.input_start_addr_hi);
3331af8b0b2SDavid Marchand 	rte_bbdev_log_debug("\t-- input_slice_num(%"PRIu32") | input_length(%"PRIu32")",
3349e3ffd38SHernan Vargas 			(uint32_t)desc->enc_req.input_slice_num,
3351af8b0b2SDavid Marchand 			(uint32_t)desc->enc_req.input_length);
3361af8b0b2SDavid Marchand 	rte_bbdev_log_debug("\t-- output_slice_table_addr_lo(%"PRIu32")"
3371af8b0b2SDavid Marchand 			" | output_start_addr_lo(%"PRIu32")",
3389e3ffd38SHernan Vargas 			(uint32_t)desc->enc_req.output_slice_table_addr_lo,
3391af8b0b2SDavid Marchand 			(uint32_t)desc->enc_req.output_start_addr_lo);
3401af8b0b2SDavid Marchand 	rte_bbdev_log_debug("\t-- output_slice_table_addr_hi(%"PRIu32")"
3411af8b0b2SDavid Marchand 			" | output_start_addr_hi(%"PRIu32")",
3429e3ffd38SHernan Vargas 			(uint32_t)desc->enc_req.output_slice_table_addr_hi,
3431af8b0b2SDavid Marchand 			(uint32_t)desc->enc_req.output_start_addr_hi);
3441af8b0b2SDavid Marchand 	rte_bbdev_log_debug("\t-- output_slice_num(%"PRIu32") | output_length(%"PRIu32")",
3459e3ffd38SHernan Vargas 			(uint32_t)desc->enc_req.output_slice_num,
3461af8b0b2SDavid Marchand 			(uint32_t)desc->enc_req.output_length);
3471af8b0b2SDavid Marchand 	rte_bbdev_log_debug("\t-- enqueue_timestamp(%"PRIu32")",
3481af8b0b2SDavid Marchand 			(uint32_t)desc->enc_req.enqueue_timestamp);
3491af8b0b2SDavid Marchand 	rte_bbdev_log_debug("\t-- completion_timestamp(%"PRIu32")",
3509e3ffd38SHernan Vargas 			(uint32_t)desc->enc_req.completion_timestamp);
3519e3ffd38SHernan Vargas 
3529e3ffd38SHernan Vargas 	uint32_t *word = (uint32_t *) desc;
3531af8b0b2SDavid Marchand 	rte_bbdev_log_debug("%08"PRIx32", %08"PRIx32", %08"PRIx32", %08"PRIx32", "
3541af8b0b2SDavid Marchand 			"%08"PRIx32", %08"PRIx32", %08"PRIx32", %08"PRIx32", "
3551af8b0b2SDavid Marchand 			"%08"PRIx32", %08"PRIx32", %08"PRIx32", %08"PRIx32", "
3561af8b0b2SDavid Marchand 			"%08"PRIx32", %08"PRIx32", %08"PRIx32", %08"PRIx32,
3579e3ffd38SHernan Vargas 			word[0], word[1], word[2], word[3],
3589e3ffd38SHernan Vargas 			word[4], word[5], word[6], word[7],
3599e3ffd38SHernan Vargas 			word[8], word[9], word[10], word[11],
3609e3ffd38SHernan Vargas 			word[12], word[13], word[14], word[15]);
3619e3ffd38SHernan Vargas }
3629e3ffd38SHernan Vargas 
36311b0a112SNicolas Chautru #endif
36411b0a112SNicolas Chautru 
3659e3ffd38SHernan Vargas /**
3669e3ffd38SHernan Vargas  * Helper function that returns queue ID if queue is valid
3679e3ffd38SHernan Vargas  * or FPGA_5GNR_INVALID_HW_QUEUE_ID otherwise.
3689e3ffd38SHernan Vargas  */
3699e3ffd38SHernan Vargas static inline uint32_t
3709e3ffd38SHernan Vargas fpga_5gnr_get_queue_map(struct fpga_5gnr_fec_device *d, uint32_t q_id)
3719e3ffd38SHernan Vargas {
3729e3ffd38SHernan Vargas 	if (d->fpga_variant == VC_5GNR_FPGA_VARIANT)
3739e3ffd38SHernan Vargas 		return fpga_5gnr_reg_read_32(d->mmio_base, VC_5GNR_QUEUE_MAP + (q_id << 2));
3749e3ffd38SHernan Vargas 	else
3759e3ffd38SHernan Vargas 		return fpga_5gnr_reg_read_32(d->mmio_base, AGX100_QUEUE_MAP + (q_id << 2));
3769e3ffd38SHernan Vargas }
3779e3ffd38SHernan Vargas 
3780b5927cbSNicolas Chautru static int
37910829ff2SHernan Vargas fpga_5gnr_setup_queues(struct rte_bbdev *dev, uint16_t num_queues, int socket_id)
3800b5927cbSNicolas Chautru {
381c58109a8SNicolas Chautru 	/* Number of queues bound to a PF/VF */
382c58109a8SNicolas Chautru 	uint32_t hw_q_num = 0;
383c58109a8SNicolas Chautru 	uint32_t ring_size, payload, address, q_id, offset;
384c58109a8SNicolas Chautru 	rte_iova_t phys_addr;
38510829ff2SHernan Vargas 	struct fpga_5gnr_ring_ctrl_reg ring_reg;
38610829ff2SHernan Vargas 	struct fpga_5gnr_fec_device *d = dev->data->dev_private;
387c58109a8SNicolas Chautru 
388c58109a8SNicolas Chautru 	address = FPGA_5GNR_FEC_QUEUE_PF_VF_MAP_DONE;
38910829ff2SHernan Vargas 	if (!(fpga_5gnr_reg_read_32(d->mmio_base, address) & 0x1)) {
390c58109a8SNicolas Chautru 		rte_bbdev_log(ERR,
391c58109a8SNicolas Chautru 				"Queue-PF/VF mapping is not set! Was PF configured for device (%s) ?",
392c58109a8SNicolas Chautru 				dev->data->name);
393c58109a8SNicolas Chautru 		return -EPERM;
394c58109a8SNicolas Chautru 	}
395c58109a8SNicolas Chautru 
396c58109a8SNicolas Chautru 	/* Clear queue registers structure */
39710829ff2SHernan Vargas 	memset(&ring_reg, 0, sizeof(struct fpga_5gnr_ring_ctrl_reg));
398c58109a8SNicolas Chautru 
399c58109a8SNicolas Chautru 	/* Scan queue map.
400c58109a8SNicolas Chautru 	 * If a queue is valid and mapped to a calling PF/VF the read value is
401c58109a8SNicolas Chautru 	 * replaced with a queue ID and if it's not then
40210829ff2SHernan Vargas 	 * FPGA_5GNR_INVALID_HW_QUEUE_ID is returned.
403c58109a8SNicolas Chautru 	 */
40499f09224SHernan Vargas 	for (q_id = 0; q_id < d->total_num_queues; ++q_id) {
4059e3ffd38SHernan Vargas 		uint32_t hw_q_id = fpga_5gnr_get_queue_map(d, q_id);
406c58109a8SNicolas Chautru 
407c58109a8SNicolas Chautru 		rte_bbdev_log_debug("%s: queue ID: %u, registry queue ID: %u",
408c58109a8SNicolas Chautru 				dev->device->name, q_id, hw_q_id);
409c58109a8SNicolas Chautru 
41010829ff2SHernan Vargas 		if (hw_q_id != FPGA_5GNR_INVALID_HW_QUEUE_ID) {
41110829ff2SHernan Vargas 			d->q_bound_bit_map |= (1ULL << q_id);
412c58109a8SNicolas Chautru 			/* Clear queue register of found queue */
413c58109a8SNicolas Chautru 			offset = FPGA_5GNR_FEC_RING_CTRL_REGS +
41410829ff2SHernan Vargas 				(sizeof(struct fpga_5gnr_ring_ctrl_reg) * q_id);
415c750d277SHernan Vargas 			fpga_ring_reg_write(d->mmio_base, offset, ring_reg);
416c58109a8SNicolas Chautru 			++hw_q_num;
417c58109a8SNicolas Chautru 		}
418c58109a8SNicolas Chautru 	}
419c58109a8SNicolas Chautru 	if (hw_q_num == 0) {
420c58109a8SNicolas Chautru 		rte_bbdev_log(ERR,
421c58109a8SNicolas Chautru 			"No HW queues assigned to this device. Probably this is a VF configured for PF mode. Check device configuration!");
422c58109a8SNicolas Chautru 		return -ENODEV;
423c58109a8SNicolas Chautru 	}
424c58109a8SNicolas Chautru 
425c58109a8SNicolas Chautru 	if (num_queues > hw_q_num) {
426c58109a8SNicolas Chautru 		rte_bbdev_log(ERR,
427c58109a8SNicolas Chautru 			"Not enough queues for device %s! Requested: %u, available: %u",
428c58109a8SNicolas Chautru 			dev->device->name, num_queues, hw_q_num);
429c58109a8SNicolas Chautru 		return -EINVAL;
430c58109a8SNicolas Chautru 	}
4319e3ffd38SHernan Vargas 	if (d->fpga_variant == VC_5GNR_FPGA_VARIANT)
432c750d277SHernan Vargas 		ring_size = FPGA_5GNR_RING_MAX_SIZE * sizeof(struct vc_5gnr_dma_dec_desc);
4339e3ffd38SHernan Vargas 	else
4349e3ffd38SHernan Vargas 		ring_size = FPGA_5GNR_RING_MAX_SIZE * sizeof(struct agx100_dma_dec_desc);
435c58109a8SNicolas Chautru 
436c58109a8SNicolas Chautru 	/* Enforce 32 byte alignment */
437c58109a8SNicolas Chautru 	RTE_BUILD_BUG_ON((RTE_CACHE_LINE_SIZE % 32) != 0);
438c58109a8SNicolas Chautru 
439c58109a8SNicolas Chautru 	/* Allocate memory for SW descriptor rings */
44010829ff2SHernan Vargas 	d->sw_rings = rte_zmalloc_socket(dev->device->driver->name,
441c58109a8SNicolas Chautru 			num_queues * ring_size, RTE_CACHE_LINE_SIZE,
442c58109a8SNicolas Chautru 			socket_id);
44310829ff2SHernan Vargas 	if (d->sw_rings == NULL) {
444c58109a8SNicolas Chautru 		rte_bbdev_log(ERR,
445c58109a8SNicolas Chautru 				"Failed to allocate memory for %s:%u sw_rings",
446c58109a8SNicolas Chautru 				dev->device->driver->name, dev->data->dev_id);
447c58109a8SNicolas Chautru 		return -ENOMEM;
448c58109a8SNicolas Chautru 	}
449c58109a8SNicolas Chautru 
45010829ff2SHernan Vargas 	d->sw_rings_phys = rte_malloc_virt2iova(d->sw_rings);
45110829ff2SHernan Vargas 	d->sw_ring_size = ring_size;
45210829ff2SHernan Vargas 	d->sw_ring_max_depth = FPGA_5GNR_RING_MAX_SIZE;
453c58109a8SNicolas Chautru 
454c58109a8SNicolas Chautru 	/* Allocate memory for ring flush status */
45510829ff2SHernan Vargas 	d->flush_queue_status = rte_zmalloc_socket(NULL,
456c58109a8SNicolas Chautru 			sizeof(uint64_t), RTE_CACHE_LINE_SIZE, socket_id);
45710829ff2SHernan Vargas 	if (d->flush_queue_status == NULL) {
458c58109a8SNicolas Chautru 		rte_bbdev_log(ERR,
459c58109a8SNicolas Chautru 				"Failed to allocate memory for %s:%u flush_queue_status",
460c58109a8SNicolas Chautru 				dev->device->driver->name, dev->data->dev_id);
461c58109a8SNicolas Chautru 		return -ENOMEM;
462c58109a8SNicolas Chautru 	}
463c58109a8SNicolas Chautru 
464c58109a8SNicolas Chautru 	/* Set the flush status address registers */
46510829ff2SHernan Vargas 	phys_addr = rte_malloc_virt2iova(d->flush_queue_status);
466c58109a8SNicolas Chautru 
467c58109a8SNicolas Chautru 	address = FPGA_5GNR_FEC_VFQ_FLUSH_STATUS_LW;
468c58109a8SNicolas Chautru 	payload = (uint32_t)(phys_addr);
46910829ff2SHernan Vargas 	fpga_5gnr_reg_write_32(d->mmio_base, address, payload);
470c58109a8SNicolas Chautru 
471c58109a8SNicolas Chautru 	address = FPGA_5GNR_FEC_VFQ_FLUSH_STATUS_HI;
472c58109a8SNicolas Chautru 	payload = (uint32_t)(phys_addr >> 32);
47310829ff2SHernan Vargas 	fpga_5gnr_reg_write_32(d->mmio_base, address, payload);
474c58109a8SNicolas Chautru 
475c58109a8SNicolas Chautru 	return 0;
476c58109a8SNicolas Chautru }
477c58109a8SNicolas Chautru 
478c58109a8SNicolas Chautru static int
47910829ff2SHernan Vargas fpga_5gnr_dev_close(struct rte_bbdev *dev)
480c58109a8SNicolas Chautru {
48110829ff2SHernan Vargas 	struct fpga_5gnr_fec_device *fpga_5gnr_dev = dev->data->dev_private;
482c58109a8SNicolas Chautru 
48310829ff2SHernan Vargas 	rte_free(fpga_5gnr_dev->sw_rings);
48410829ff2SHernan Vargas 	rte_free(fpga_5gnr_dev->flush_queue_status);
485c58109a8SNicolas Chautru 
4860b5927cbSNicolas Chautru 	return 0;
4870b5927cbSNicolas Chautru }
4880b5927cbSNicolas Chautru 
48957936c36SNicolas Chautru static void
49010829ff2SHernan Vargas fpga_5gnr_dev_info_get(struct rte_bbdev *dev, struct rte_bbdev_driver_info *dev_info)
49157936c36SNicolas Chautru {
49257936c36SNicolas Chautru 	struct fpga_5gnr_fec_device *d = dev->data->dev_private;
49357936c36SNicolas Chautru 	uint32_t q_id = 0;
49457936c36SNicolas Chautru 
4959e3ffd38SHernan Vargas 	static const struct rte_bbdev_op_cap vc_5gnr_bbdev_capabilities[] = {
49644dc6faaSNicolas Chautru 		{
49744dc6faaSNicolas Chautru 			.type   = RTE_BBDEV_OP_LDPC_ENC,
49844dc6faaSNicolas Chautru 			.cap.ldpc_enc = {
49944dc6faaSNicolas Chautru 				.capability_flags =
50044dc6faaSNicolas Chautru 						RTE_BBDEV_LDPC_RATE_MATCH |
50144dc6faaSNicolas Chautru 						RTE_BBDEV_LDPC_ENC_INTERRUPTS |
50244dc6faaSNicolas Chautru 						RTE_BBDEV_LDPC_CRC_24B_ATTACH,
50344dc6faaSNicolas Chautru 				.num_buffers_src =
50444dc6faaSNicolas Chautru 						RTE_BBDEV_LDPC_MAX_CODE_BLOCKS,
50544dc6faaSNicolas Chautru 				.num_buffers_dst =
50644dc6faaSNicolas Chautru 						RTE_BBDEV_LDPC_MAX_CODE_BLOCKS,
50744dc6faaSNicolas Chautru 			}
50844dc6faaSNicolas Chautru 		},
50944dc6faaSNicolas Chautru 		{
51044dc6faaSNicolas Chautru 		.type   = RTE_BBDEV_OP_LDPC_DEC,
51144dc6faaSNicolas Chautru 		.cap.ldpc_dec = {
51244dc6faaSNicolas Chautru 			.capability_flags =
51344dc6faaSNicolas Chautru 				RTE_BBDEV_LDPC_CRC_TYPE_24B_CHECK |
51444dc6faaSNicolas Chautru 				RTE_BBDEV_LDPC_CRC_TYPE_24B_DROP |
51544dc6faaSNicolas Chautru 				RTE_BBDEV_LDPC_HQ_COMBINE_IN_ENABLE |
51644dc6faaSNicolas Chautru 				RTE_BBDEV_LDPC_HQ_COMBINE_OUT_ENABLE |
51744dc6faaSNicolas Chautru 				RTE_BBDEV_LDPC_ITERATION_STOP_ENABLE |
51844dc6faaSNicolas Chautru 				RTE_BBDEV_LDPC_INTERNAL_HARQ_MEMORY_IN_ENABLE |
51944dc6faaSNicolas Chautru 				RTE_BBDEV_LDPC_INTERNAL_HARQ_MEMORY_OUT_ENABLE |
5204d9199e3SNicolas Chautru 				RTE_BBDEV_LDPC_INTERNAL_HARQ_MEMORY_LOOPBACK |
521b7b1ba64SNicolas Chautru 				RTE_BBDEV_LDPC_DEC_INTERRUPTS |
52244dc6faaSNicolas Chautru 				RTE_BBDEV_LDPC_INTERNAL_HARQ_MEMORY_FILLERS,
52344dc6faaSNicolas Chautru 			.llr_size = 6,
52444dc6faaSNicolas Chautru 			.llr_decimals = 2,
52544dc6faaSNicolas Chautru 			.num_buffers_src =
52644dc6faaSNicolas Chautru 					RTE_BBDEV_LDPC_MAX_CODE_BLOCKS,
52744dc6faaSNicolas Chautru 			.num_buffers_hard_out =
52844dc6faaSNicolas Chautru 					RTE_BBDEV_LDPC_MAX_CODE_BLOCKS,
52944dc6faaSNicolas Chautru 			.num_buffers_soft_out = 0,
53044dc6faaSNicolas Chautru 		}
53144dc6faaSNicolas Chautru 		},
53257936c36SNicolas Chautru 		RTE_BBDEV_END_OF_CAPABILITIES_LIST()
53357936c36SNicolas Chautru 	};
53457936c36SNicolas Chautru 
5359e3ffd38SHernan Vargas 	static const struct rte_bbdev_op_cap agx100_bbdev_capabilities[] = {
5369e3ffd38SHernan Vargas 		{
5379e3ffd38SHernan Vargas 			.type   = RTE_BBDEV_OP_LDPC_ENC,
5389e3ffd38SHernan Vargas 			.cap.ldpc_enc = {
5399e3ffd38SHernan Vargas 				.capability_flags =
5409e3ffd38SHernan Vargas 						RTE_BBDEV_LDPC_RATE_MATCH |
5419e3ffd38SHernan Vargas 						RTE_BBDEV_LDPC_CRC_24B_ATTACH,
5429e3ffd38SHernan Vargas 				.num_buffers_src =
5439e3ffd38SHernan Vargas 						RTE_BBDEV_LDPC_MAX_CODE_BLOCKS,
5449e3ffd38SHernan Vargas 				.num_buffers_dst =
5459e3ffd38SHernan Vargas 						RTE_BBDEV_LDPC_MAX_CODE_BLOCKS,
5469e3ffd38SHernan Vargas 			}
5479e3ffd38SHernan Vargas 		},
5489e3ffd38SHernan Vargas 		{
5499e3ffd38SHernan Vargas 		.type   = RTE_BBDEV_OP_LDPC_DEC,
5509e3ffd38SHernan Vargas 		.cap.ldpc_dec = {
5519e3ffd38SHernan Vargas 			.capability_flags =
5529e3ffd38SHernan Vargas 					RTE_BBDEV_LDPC_CRC_TYPE_24B_CHECK |
5539e3ffd38SHernan Vargas 					RTE_BBDEV_LDPC_CRC_TYPE_24B_DROP |
5549e3ffd38SHernan Vargas 					RTE_BBDEV_LDPC_HQ_COMBINE_IN_ENABLE |
5559e3ffd38SHernan Vargas 					RTE_BBDEV_LDPC_HQ_COMBINE_OUT_ENABLE |
5569e3ffd38SHernan Vargas 					RTE_BBDEV_LDPC_ITERATION_STOP_ENABLE |
5579e3ffd38SHernan Vargas 					RTE_BBDEV_LDPC_INTERNAL_HARQ_MEMORY_IN_ENABLE |
5589e3ffd38SHernan Vargas 					RTE_BBDEV_LDPC_INTERNAL_HARQ_MEMORY_OUT_ENABLE |
5599e3ffd38SHernan Vargas 					RTE_BBDEV_LDPC_INTERNAL_HARQ_MEMORY_LOOPBACK |
5609e3ffd38SHernan Vargas 					RTE_BBDEV_LDPC_INTERNAL_HARQ_MEMORY_FILLERS,
5619e3ffd38SHernan Vargas 			.llr_size = 6,
5629e3ffd38SHernan Vargas 			.llr_decimals = 2,
5639e3ffd38SHernan Vargas 			.num_buffers_src =
5649e3ffd38SHernan Vargas 					RTE_BBDEV_LDPC_MAX_CODE_BLOCKS,
5659e3ffd38SHernan Vargas 			.num_buffers_hard_out =
5669e3ffd38SHernan Vargas 					RTE_BBDEV_LDPC_MAX_CODE_BLOCKS,
5679e3ffd38SHernan Vargas 			.num_buffers_soft_out = 0,
5689e3ffd38SHernan Vargas 		}
5699e3ffd38SHernan Vargas 		},
5709e3ffd38SHernan Vargas 		RTE_BBDEV_END_OF_CAPABILITIES_LIST()
5719e3ffd38SHernan Vargas 	};
5729e3ffd38SHernan Vargas 
57357936c36SNicolas Chautru 	/* Check the HARQ DDR size available */
57457936c36SNicolas Chautru 	uint8_t timeout_counter = 0;
57510829ff2SHernan Vargas 	uint32_t harq_buf_ready = fpga_5gnr_reg_read_32(d->mmio_base,
57657936c36SNicolas Chautru 			FPGA_5GNR_FEC_HARQ_BUF_SIZE_RDY_REGS);
57757936c36SNicolas Chautru 	while (harq_buf_ready != 1) {
57810829ff2SHernan Vargas 		usleep(FPGA_5GNR_TIMEOUT_CHECK_INTERVAL);
57957936c36SNicolas Chautru 		timeout_counter++;
58010829ff2SHernan Vargas 		harq_buf_ready = fpga_5gnr_reg_read_32(d->mmio_base,
58157936c36SNicolas Chautru 				FPGA_5GNR_FEC_HARQ_BUF_SIZE_RDY_REGS);
58210829ff2SHernan Vargas 		if (timeout_counter > FPGA_5GNR_HARQ_RDY_TIMEOUT) {
58310829ff2SHernan Vargas 			rte_bbdev_log(ERR, "HARQ Buffer not ready %d", harq_buf_ready);
58457936c36SNicolas Chautru 			harq_buf_ready = 1;
58557936c36SNicolas Chautru 		}
58657936c36SNicolas Chautru 	}
58710829ff2SHernan Vargas 	uint32_t harq_buf_size = fpga_5gnr_reg_read_32(d->mmio_base,
58857936c36SNicolas Chautru 			FPGA_5GNR_FEC_HARQ_BUF_SIZE_REGS);
58957936c36SNicolas Chautru 
59057936c36SNicolas Chautru 	static struct rte_bbdev_queue_conf default_queue_conf;
59157936c36SNicolas Chautru 	default_queue_conf.socket = dev->data->socket_id;
59210829ff2SHernan Vargas 	default_queue_conf.queue_size = FPGA_5GNR_RING_MAX_SIZE;
59357936c36SNicolas Chautru 
59457936c36SNicolas Chautru 	dev_info->driver_name = dev->device->driver->name;
59510829ff2SHernan Vargas 	dev_info->queue_size_lim = FPGA_5GNR_RING_MAX_SIZE;
59657936c36SNicolas Chautru 	dev_info->hardware_accelerated = true;
5979e3ffd38SHernan Vargas 	dev_info->min_alignment = 1;
5989e3ffd38SHernan Vargas 	if (d->fpga_variant == VC_5GNR_FPGA_VARIANT)
59957936c36SNicolas Chautru 		dev_info->harq_buffer_size = (harq_buf_size >> 10) + 1;
6009e3ffd38SHernan Vargas 	else
6019e3ffd38SHernan Vargas 		dev_info->harq_buffer_size = harq_buf_size << 10;
60257936c36SNicolas Chautru 	dev_info->default_queue_conf = default_queue_conf;
6039e3ffd38SHernan Vargas 	if (d->fpga_variant == VC_5GNR_FPGA_VARIANT)
6049e3ffd38SHernan Vargas 		dev_info->capabilities = vc_5gnr_bbdev_capabilities;
6059e3ffd38SHernan Vargas 	else
6069e3ffd38SHernan Vargas 		dev_info->capabilities = agx100_bbdev_capabilities;
60757936c36SNicolas Chautru 	dev_info->cpu_flag_reqs = NULL;
608ab4e1909SNicolas Chautru 	dev_info->data_endianness = RTE_LITTLE_ENDIAN;
6091be86f2eSNicolas Chautru 	dev_info->device_status = RTE_BBDEV_DEV_NOT_SUPPORTED;
61057936c36SNicolas Chautru 
61157936c36SNicolas Chautru 	/* Calculates number of queues assigned to device */
61257936c36SNicolas Chautru 	dev_info->max_num_queues = 0;
61399f09224SHernan Vargas 	for (q_id = 0; q_id < d->total_num_queues; ++q_id) {
6149e3ffd38SHernan Vargas 		uint32_t hw_q_id = fpga_5gnr_get_queue_map(d, q_id);
6159e3ffd38SHernan Vargas 
61610829ff2SHernan Vargas 		if (hw_q_id != FPGA_5GNR_INVALID_HW_QUEUE_ID)
61757936c36SNicolas Chautru 			dev_info->max_num_queues++;
61857936c36SNicolas Chautru 	}
61997332051SNicolas Chautru 	/* Expose number of queue per operation type */
62097332051SNicolas Chautru 	dev_info->num_queues[RTE_BBDEV_OP_NONE] = 0;
62197332051SNicolas Chautru 	dev_info->num_queues[RTE_BBDEV_OP_TURBO_DEC] = 0;
62297332051SNicolas Chautru 	dev_info->num_queues[RTE_BBDEV_OP_TURBO_ENC] = 0;
62397332051SNicolas Chautru 	dev_info->num_queues[RTE_BBDEV_OP_LDPC_DEC] = dev_info->max_num_queues / 2;
62497332051SNicolas Chautru 	dev_info->num_queues[RTE_BBDEV_OP_LDPC_ENC] = dev_info->max_num_queues / 2;
625*0f4e9909SHernan Vargas 	dev_info->num_queues[RTE_BBDEV_OP_FFT] = 0;
626*0f4e9909SHernan Vargas 	dev_info->num_queues[RTE_BBDEV_OP_MLDTS] = 0;
62797332051SNicolas Chautru 	dev_info->queue_priority[RTE_BBDEV_OP_LDPC_DEC] = 1;
62897332051SNicolas Chautru 	dev_info->queue_priority[RTE_BBDEV_OP_LDPC_ENC] = 1;
62957936c36SNicolas Chautru }
63057936c36SNicolas Chautru 
631c58109a8SNicolas Chautru /**
632c58109a8SNicolas Chautru  * Find index of queue bound to current PF/VF which is unassigned. Return -1
633c58109a8SNicolas Chautru  * when there is no available queue
634c58109a8SNicolas Chautru  */
635c58109a8SNicolas Chautru static inline int
63610829ff2SHernan Vargas fpga_5gnr_find_free_queue_idx(struct rte_bbdev *dev,
637c58109a8SNicolas Chautru 		const struct rte_bbdev_queue_conf *conf)
638c58109a8SNicolas Chautru {
639c58109a8SNicolas Chautru 	struct fpga_5gnr_fec_device *d = dev->data->dev_private;
640c58109a8SNicolas Chautru 	uint64_t q_idx;
641c58109a8SNicolas Chautru 	uint8_t i = 0;
64299f09224SHernan Vargas 	uint8_t range = d->total_num_queues >> 1;
643c58109a8SNicolas Chautru 
644c58109a8SNicolas Chautru 	if (conf->op_type == RTE_BBDEV_OP_LDPC_ENC) {
64599f09224SHernan Vargas 		i = d->total_num_queues >> 1;
64699f09224SHernan Vargas 		range = d->total_num_queues;
647c58109a8SNicolas Chautru 	}
648c58109a8SNicolas Chautru 
649c58109a8SNicolas Chautru 	for (; i < range; ++i) {
650c58109a8SNicolas Chautru 		q_idx = 1ULL << i;
651c58109a8SNicolas Chautru 		/* Check if index of queue is bound to current PF/VF */
652c58109a8SNicolas Chautru 		if (d->q_bound_bit_map & q_idx)
653c58109a8SNicolas Chautru 			/* Check if found queue was not already assigned */
654c58109a8SNicolas Chautru 			if (!(d->q_assigned_bit_map & q_idx)) {
655c58109a8SNicolas Chautru 				d->q_assigned_bit_map |= q_idx;
656c58109a8SNicolas Chautru 				return i;
657c58109a8SNicolas Chautru 			}
658c58109a8SNicolas Chautru 	}
659c58109a8SNicolas Chautru 
660c58109a8SNicolas Chautru 	rte_bbdev_log(INFO, "Failed to find free queue on %s", dev->data->name);
661c58109a8SNicolas Chautru 
662c58109a8SNicolas Chautru 	return -1;
663c58109a8SNicolas Chautru }
664c58109a8SNicolas Chautru 
665c58109a8SNicolas Chautru static int
66610829ff2SHernan Vargas fpga_5gnr_queue_setup(struct rte_bbdev *dev, uint16_t queue_id,
667c58109a8SNicolas Chautru 		const struct rte_bbdev_queue_conf *conf)
668c58109a8SNicolas Chautru {
669c58109a8SNicolas Chautru 	uint32_t address, ring_offset;
670c58109a8SNicolas Chautru 	struct fpga_5gnr_fec_device *d = dev->data->dev_private;
67110829ff2SHernan Vargas 	struct fpga_5gnr_queue *q;
672c58109a8SNicolas Chautru 	int8_t q_idx;
673c58109a8SNicolas Chautru 
674c58109a8SNicolas Chautru 	/* Check if there is a free queue to assign */
67510829ff2SHernan Vargas 	q_idx = fpga_5gnr_find_free_queue_idx(dev, conf);
676c58109a8SNicolas Chautru 	if (q_idx == -1)
677c58109a8SNicolas Chautru 		return -1;
678c58109a8SNicolas Chautru 
679c58109a8SNicolas Chautru 	/* Allocate the queue data structure. */
680c58109a8SNicolas Chautru 	q = rte_zmalloc_socket(dev->device->driver->name, sizeof(*q),
681c58109a8SNicolas Chautru 			RTE_CACHE_LINE_SIZE, conf->socket);
682c58109a8SNicolas Chautru 	if (q == NULL) {
683c58109a8SNicolas Chautru 		/* Mark queue as un-assigned */
684c58109a8SNicolas Chautru 		d->q_assigned_bit_map &= (0xFFFFFFFF - (1ULL << q_idx));
685c58109a8SNicolas Chautru 		rte_bbdev_log(ERR, "Failed to allocate queue memory");
686c58109a8SNicolas Chautru 		return -ENOMEM;
687c58109a8SNicolas Chautru 	}
688c58109a8SNicolas Chautru 
689c58109a8SNicolas Chautru 	q->d = d;
690c58109a8SNicolas Chautru 	q->q_idx = q_idx;
691c58109a8SNicolas Chautru 
692c58109a8SNicolas Chautru 	/* Set ring_base_addr */
6939e3ffd38SHernan Vargas 	if (d->fpga_variant == VC_5GNR_FPGA_VARIANT)
694c750d277SHernan Vargas 		q->vc_5gnr_ring_addr = RTE_PTR_ADD(d->sw_rings, (d->sw_ring_size * queue_id));
6959e3ffd38SHernan Vargas 	else
6969e3ffd38SHernan Vargas 		q->agx100_ring_addr = RTE_PTR_ADD(d->sw_rings, (d->sw_ring_size * queue_id));
6979e3ffd38SHernan Vargas 
69810829ff2SHernan Vargas 	q->ring_ctrl_reg.ring_base_addr = d->sw_rings_phys + (d->sw_ring_size * queue_id);
699c58109a8SNicolas Chautru 
700c58109a8SNicolas Chautru 	/* Allocate memory for Completion Head variable*/
701c58109a8SNicolas Chautru 	q->ring_head_addr = rte_zmalloc_socket(dev->device->driver->name,
702c58109a8SNicolas Chautru 			sizeof(uint64_t), RTE_CACHE_LINE_SIZE, conf->socket);
703c58109a8SNicolas Chautru 	if (q->ring_head_addr == NULL) {
704c58109a8SNicolas Chautru 		/* Mark queue as un-assigned */
705c58109a8SNicolas Chautru 		d->q_assigned_bit_map &= (0xFFFFFFFF - (1ULL << q_idx));
706c58109a8SNicolas Chautru 		rte_free(q);
707c58109a8SNicolas Chautru 		rte_bbdev_log(ERR,
708c58109a8SNicolas Chautru 				"Failed to allocate memory for %s:%u completion_head",
709c58109a8SNicolas Chautru 				dev->device->driver->name, dev->data->dev_id);
710c58109a8SNicolas Chautru 		return -ENOMEM;
711c58109a8SNicolas Chautru 	}
712c58109a8SNicolas Chautru 	/* Set ring_head_addr */
71310829ff2SHernan Vargas 	q->ring_ctrl_reg.ring_head_addr = rte_malloc_virt2iova(q->ring_head_addr);
714c58109a8SNicolas Chautru 
715c58109a8SNicolas Chautru 	/* Clear shadow_completion_head */
716c58109a8SNicolas Chautru 	q->shadow_completion_head = 0;
717c58109a8SNicolas Chautru 
718c58109a8SNicolas Chautru 	/* Set ring_size */
71910829ff2SHernan Vargas 	if (conf->queue_size > FPGA_5GNR_RING_MAX_SIZE) {
720c58109a8SNicolas Chautru 		/* Mark queue as un-assigned */
721c58109a8SNicolas Chautru 		d->q_assigned_bit_map &= (0xFFFFFFFF - (1ULL << q_idx));
722c58109a8SNicolas Chautru 		rte_free(q->ring_head_addr);
723c58109a8SNicolas Chautru 		rte_free(q);
724c58109a8SNicolas Chautru 		rte_bbdev_log(ERR,
725c58109a8SNicolas Chautru 				"Size of queue is too big %d (MAX: %d ) for %s:%u",
72610829ff2SHernan Vargas 				conf->queue_size, FPGA_5GNR_RING_MAX_SIZE,
727c58109a8SNicolas Chautru 				dev->device->driver->name, dev->data->dev_id);
728c58109a8SNicolas Chautru 		return -EINVAL;
729c58109a8SNicolas Chautru 	}
730c58109a8SNicolas Chautru 	q->ring_ctrl_reg.ring_size = conf->queue_size;
731c58109a8SNicolas Chautru 
73210829ff2SHernan Vargas 	/* Set Miscellaneous FPGA 5GNR register. */
733c58109a8SNicolas Chautru 	/* Max iteration number for TTI mitigation - todo */
734c58109a8SNicolas Chautru 	q->ring_ctrl_reg.max_ul_dec = 0;
735c58109a8SNicolas Chautru 	/* Enable max iteration number for TTI - todo */
736c58109a8SNicolas Chautru 	q->ring_ctrl_reg.max_ul_dec_en = 0;
737c58109a8SNicolas Chautru 
738c58109a8SNicolas Chautru 	/* Enable the ring */
739c58109a8SNicolas Chautru 	q->ring_ctrl_reg.enable = 1;
740c58109a8SNicolas Chautru 
74110829ff2SHernan Vargas 	/* Set FPGA 5GNR head_point and tail registers */
742c58109a8SNicolas Chautru 	q->ring_ctrl_reg.head_point = q->tail = 0;
743c58109a8SNicolas Chautru 
74410829ff2SHernan Vargas 	/* Set FPGA 5GNR shadow_tail register */
745c58109a8SNicolas Chautru 	q->ring_ctrl_reg.shadow_tail = q->tail;
746c58109a8SNicolas Chautru 
747c58109a8SNicolas Chautru 	/* Calculates the ring offset for found queue */
748c58109a8SNicolas Chautru 	ring_offset = FPGA_5GNR_FEC_RING_CTRL_REGS +
74910829ff2SHernan Vargas 			(sizeof(struct fpga_5gnr_ring_ctrl_reg) * q_idx);
750c58109a8SNicolas Chautru 
75110829ff2SHernan Vargas 	/* Set FPGA 5GNR Ring Control Registers */
752c58109a8SNicolas Chautru 	fpga_ring_reg_write(d->mmio_base, ring_offset, q->ring_ctrl_reg);
753c58109a8SNicolas Chautru 
754c58109a8SNicolas Chautru 	/* Store MMIO register of shadow_tail */
755c58109a8SNicolas Chautru 	address = ring_offset + FPGA_5GNR_FEC_RING_SHADOW_TAIL;
756c58109a8SNicolas Chautru 	q->shadow_tail_addr = RTE_PTR_ADD(d->mmio_base, address);
757c58109a8SNicolas Chautru 
758c58109a8SNicolas Chautru 	q->head_free_desc = q->tail;
759c58109a8SNicolas Chautru 
760c58109a8SNicolas Chautru 	/* Set wrap mask */
761c58109a8SNicolas Chautru 	q->sw_ring_wrap_mask = conf->queue_size - 1;
762c58109a8SNicolas Chautru 
763c58109a8SNicolas Chautru 	rte_bbdev_log_debug("Setup dev%u q%u: queue_idx=%u",
764c58109a8SNicolas Chautru 			dev->data->dev_id, queue_id, q->q_idx);
765c58109a8SNicolas Chautru 
766c58109a8SNicolas Chautru 	dev->data->queues[queue_id].queue_private = q;
767c58109a8SNicolas Chautru 
76810829ff2SHernan Vargas 	rte_bbdev_log_debug("BBDEV queue[%d] set up for FPGA 5GNR queue[%d]", queue_id, q_idx);
769c58109a8SNicolas Chautru 
77011b0a112SNicolas Chautru #ifdef RTE_LIBRTE_BBDEV_DEBUG
77111b0a112SNicolas Chautru 	/* Read FPGA Ring Control Registers after configuration*/
77211b0a112SNicolas Chautru 	print_ring_reg_debug_info(d->mmio_base, ring_offset);
77311b0a112SNicolas Chautru #endif
774c58109a8SNicolas Chautru 	return 0;
775c58109a8SNicolas Chautru }
776c58109a8SNicolas Chautru 
777c58109a8SNicolas Chautru static int
77810829ff2SHernan Vargas fpga_5gnr_queue_release(struct rte_bbdev *dev, uint16_t queue_id)
779c58109a8SNicolas Chautru {
780c58109a8SNicolas Chautru 	struct fpga_5gnr_fec_device *d = dev->data->dev_private;
78110829ff2SHernan Vargas 	struct fpga_5gnr_queue *q = dev->data->queues[queue_id].queue_private;
78210829ff2SHernan Vargas 	struct fpga_5gnr_ring_ctrl_reg ring_reg;
783c58109a8SNicolas Chautru 	uint32_t offset;
784c58109a8SNicolas Chautru 
78510829ff2SHernan Vargas 	rte_bbdev_log_debug("FPGA 5GNR Queue[%d] released", queue_id);
786c58109a8SNicolas Chautru 
787c58109a8SNicolas Chautru 	if (q != NULL) {
78810829ff2SHernan Vargas 		memset(&ring_reg, 0, sizeof(struct fpga_5gnr_ring_ctrl_reg));
789c58109a8SNicolas Chautru 		offset = FPGA_5GNR_FEC_RING_CTRL_REGS +
79010829ff2SHernan Vargas 			(sizeof(struct fpga_5gnr_ring_ctrl_reg) * q->q_idx);
791c58109a8SNicolas Chautru 		/* Disable queue */
79210829ff2SHernan Vargas 		fpga_5gnr_reg_write_8(d->mmio_base,
793c58109a8SNicolas Chautru 				offset + FPGA_5GNR_FEC_RING_ENABLE, 0x00);
794c58109a8SNicolas Chautru 		/* Clear queue registers */
795c58109a8SNicolas Chautru 		fpga_ring_reg_write(d->mmio_base, offset, ring_reg);
796c58109a8SNicolas Chautru 
797c58109a8SNicolas Chautru 		/* Mark the Queue as un-assigned */
798c58109a8SNicolas Chautru 		d->q_assigned_bit_map &= (0xFFFFFFFF - (1ULL << q->q_idx));
799c58109a8SNicolas Chautru 		rte_free(q->ring_head_addr);
800c58109a8SNicolas Chautru 		rte_free(q);
801c58109a8SNicolas Chautru 		dev->data->queues[queue_id].queue_private = NULL;
802c58109a8SNicolas Chautru 	}
803c58109a8SNicolas Chautru 
804c58109a8SNicolas Chautru 	return 0;
805c58109a8SNicolas Chautru }
806c58109a8SNicolas Chautru 
807c58109a8SNicolas Chautru /* Function starts a device queue. */
808c58109a8SNicolas Chautru static int
80910829ff2SHernan Vargas fpga_5gnr_queue_start(struct rte_bbdev *dev, uint16_t queue_id)
810c58109a8SNicolas Chautru {
811c58109a8SNicolas Chautru 	struct fpga_5gnr_fec_device *d = dev->data->dev_private;
81210829ff2SHernan Vargas 	struct fpga_5gnr_queue *q = dev->data->queues[queue_id].queue_private;
813490501e6SHernan Vargas 	uint32_t offset = FPGA_5GNR_FEC_RING_CTRL_REGS +
81410829ff2SHernan Vargas 			(sizeof(struct fpga_5gnr_ring_ctrl_reg) * q->q_idx);
815490501e6SHernan Vargas 	uint8_t enable = 0x01;
816490501e6SHernan Vargas 	uint16_t zero = 0x0000;
817c58109a8SNicolas Chautru #ifdef RTE_LIBRTE_BBDEV_DEBUG
818c58109a8SNicolas Chautru 	if (d == NULL) {
819c58109a8SNicolas Chautru 		rte_bbdev_log(ERR, "Invalid device pointer");
820c58109a8SNicolas Chautru 		return -1;
821c58109a8SNicolas Chautru 	}
822c58109a8SNicolas Chautru #endif
823490501e6SHernan Vargas 	if (dev->data->queues[queue_id].queue_private == NULL) {
824490501e6SHernan Vargas 		rte_bbdev_log(ERR, "Cannot start invalid queue %d", queue_id);
825490501e6SHernan Vargas 		return -1;
826490501e6SHernan Vargas 	}
827c58109a8SNicolas Chautru 
828c58109a8SNicolas Chautru 	/* Clear queue head and tail variables */
829c58109a8SNicolas Chautru 	q->tail = q->head_free_desc = 0;
830c58109a8SNicolas Chautru 
83110829ff2SHernan Vargas 	/* Clear FPGA 5GNR head_point and tail registers */
83210829ff2SHernan Vargas 	fpga_5gnr_reg_write_16(d->mmio_base, offset + FPGA_5GNR_FEC_RING_HEAD_POINT, zero);
83310829ff2SHernan Vargas 	fpga_5gnr_reg_write_16(d->mmio_base, offset + FPGA_5GNR_FEC_RING_SHADOW_TAIL, zero);
834c58109a8SNicolas Chautru 
835c58109a8SNicolas Chautru 	/* Enable queue */
83610829ff2SHernan Vargas 	fpga_5gnr_reg_write_8(d->mmio_base, offset + FPGA_5GNR_FEC_RING_ENABLE, enable);
837c58109a8SNicolas Chautru 
83810829ff2SHernan Vargas 	rte_bbdev_log_debug("FPGA 5GNR Queue[%d] started", queue_id);
839c58109a8SNicolas Chautru 	return 0;
840c58109a8SNicolas Chautru }
841c58109a8SNicolas Chautru 
842c58109a8SNicolas Chautru /* Function stops a device queue. */
843c58109a8SNicolas Chautru static int
84410829ff2SHernan Vargas fpga_5gnr_queue_stop(struct rte_bbdev *dev, uint16_t queue_id)
845c58109a8SNicolas Chautru {
846c58109a8SNicolas Chautru 	struct fpga_5gnr_fec_device *d = dev->data->dev_private;
847c58109a8SNicolas Chautru #ifdef RTE_LIBRTE_BBDEV_DEBUG
848c58109a8SNicolas Chautru 	if (d == NULL) {
849c58109a8SNicolas Chautru 		rte_bbdev_log(ERR, "Invalid device pointer");
850c58109a8SNicolas Chautru 		return -1;
851c58109a8SNicolas Chautru 	}
852c58109a8SNicolas Chautru #endif
85310829ff2SHernan Vargas 	struct fpga_5gnr_queue *q = dev->data->queues[queue_id].queue_private;
854c58109a8SNicolas Chautru 	uint32_t offset = FPGA_5GNR_FEC_RING_CTRL_REGS +
85510829ff2SHernan Vargas 			(sizeof(struct fpga_5gnr_ring_ctrl_reg) * q->q_idx);
856c58109a8SNicolas Chautru 	uint8_t payload = 0x01;
857c58109a8SNicolas Chautru 	uint8_t counter = 0;
85810829ff2SHernan Vargas 	uint8_t timeout = FPGA_5GNR_QUEUE_FLUSH_TIMEOUT_US / FPGA_5GNR_TIMEOUT_CHECK_INTERVAL;
859c58109a8SNicolas Chautru 
860c58109a8SNicolas Chautru 	/* Set flush_queue_en bit to trigger queue flushing */
86110829ff2SHernan Vargas 	fpga_5gnr_reg_write_8(d->mmio_base,
862c58109a8SNicolas Chautru 			offset + FPGA_5GNR_FEC_RING_FLUSH_QUEUE_EN, payload);
863c58109a8SNicolas Chautru 
864c58109a8SNicolas Chautru 	/** Check if queue flush is completed.
86510829ff2SHernan Vargas 	 * FPGA 5GNR will update the completion flag after queue flushing is
866c58109a8SNicolas Chautru 	 * completed. If completion flag is not updated within 1ms it is
867c58109a8SNicolas Chautru 	 * considered as a failure.
868c58109a8SNicolas Chautru 	 */
86910829ff2SHernan Vargas 	while (!(*((volatile uint8_t *)d->flush_queue_status + q->q_idx) & payload)) {
870c58109a8SNicolas Chautru 		if (counter > timeout) {
87110829ff2SHernan Vargas 			rte_bbdev_log(ERR, "FPGA 5GNR Queue Flush failed for queue %d", queue_id);
872c58109a8SNicolas Chautru 			return -1;
873c58109a8SNicolas Chautru 		}
87410829ff2SHernan Vargas 		usleep(FPGA_5GNR_TIMEOUT_CHECK_INTERVAL);
875c58109a8SNicolas Chautru 		counter++;
876c58109a8SNicolas Chautru 	}
877c58109a8SNicolas Chautru 
878c58109a8SNicolas Chautru 	/* Disable queue */
879c58109a8SNicolas Chautru 	payload = 0x00;
88010829ff2SHernan Vargas 	fpga_5gnr_reg_write_8(d->mmio_base, offset + FPGA_5GNR_FEC_RING_ENABLE, payload);
881c58109a8SNicolas Chautru 
88210829ff2SHernan Vargas 	rte_bbdev_log_debug("FPGA 5GNR Queue[%d] stopped", queue_id);
883c58109a8SNicolas Chautru 	return 0;
884c58109a8SNicolas Chautru }
885c58109a8SNicolas Chautru 
886b7b1ba64SNicolas Chautru static inline uint16_t
887b7b1ba64SNicolas Chautru get_queue_id(struct rte_bbdev_data *data, uint8_t q_idx)
888b7b1ba64SNicolas Chautru {
889b7b1ba64SNicolas Chautru 	uint16_t queue_id;
890b7b1ba64SNicolas Chautru 
891b7b1ba64SNicolas Chautru 	for (queue_id = 0; queue_id < data->num_queues; ++queue_id) {
89210829ff2SHernan Vargas 		struct fpga_5gnr_queue *q = data->queues[queue_id].queue_private;
893b7b1ba64SNicolas Chautru 		if (q != NULL && q->q_idx == q_idx)
894b7b1ba64SNicolas Chautru 			return queue_id;
895b7b1ba64SNicolas Chautru 	}
896b7b1ba64SNicolas Chautru 
897b7b1ba64SNicolas Chautru 	return -1;
898b7b1ba64SNicolas Chautru }
899b7b1ba64SNicolas Chautru 
90010829ff2SHernan Vargas /* Interrupt handler triggered by FPGA 5GNR dev for handling specific interrupt. */
901b7b1ba64SNicolas Chautru static void
90210829ff2SHernan Vargas fpga_5gnr_dev_interrupt_handler(void *cb_arg)
903b7b1ba64SNicolas Chautru {
904b7b1ba64SNicolas Chautru 	struct rte_bbdev *dev = cb_arg;
90510829ff2SHernan Vargas 	struct fpga_5gnr_fec_device *d = dev->data->dev_private;
90610829ff2SHernan Vargas 	struct fpga_5gnr_queue *q;
907b7b1ba64SNicolas Chautru 	uint64_t ring_head;
908b7b1ba64SNicolas Chautru 	uint64_t q_idx;
909b7b1ba64SNicolas Chautru 	uint16_t queue_id;
910b7b1ba64SNicolas Chautru 	uint8_t i;
911b7b1ba64SNicolas Chautru 
912b7b1ba64SNicolas Chautru 	/* Scan queue assigned to this device */
91399f09224SHernan Vargas 	for (i = 0; i < d->total_num_queues; ++i) {
914b7b1ba64SNicolas Chautru 		q_idx = 1ULL << i;
91510829ff2SHernan Vargas 		if (d->q_bound_bit_map & q_idx) {
916b7b1ba64SNicolas Chautru 			queue_id = get_queue_id(dev->data, i);
917b7b1ba64SNicolas Chautru 			if (queue_id == (uint16_t) -1)
918b7b1ba64SNicolas Chautru 				continue;
919b7b1ba64SNicolas Chautru 
920b7b1ba64SNicolas Chautru 			/* Check if completion head was changed */
921b7b1ba64SNicolas Chautru 			q = dev->data->queues[queue_id].queue_private;
922b7b1ba64SNicolas Chautru 			ring_head = *q->ring_head_addr;
923b7b1ba64SNicolas Chautru 			if (q->shadow_completion_head != ring_head &&
924b7b1ba64SNicolas Chautru 				q->irq_enable == 1) {
925b7b1ba64SNicolas Chautru 				q->shadow_completion_head = ring_head;
926b7b1ba64SNicolas Chautru 				rte_bbdev_pmd_callback_process(
927b7b1ba64SNicolas Chautru 						dev,
928b7b1ba64SNicolas Chautru 						RTE_BBDEV_EVENT_DEQUEUE,
929b7b1ba64SNicolas Chautru 						&queue_id);
930b7b1ba64SNicolas Chautru 			}
931b7b1ba64SNicolas Chautru 		}
932b7b1ba64SNicolas Chautru 	}
933b7b1ba64SNicolas Chautru }
934b7b1ba64SNicolas Chautru 
935b7b1ba64SNicolas Chautru static int
93610829ff2SHernan Vargas fpga_5gnr_queue_intr_enable(struct rte_bbdev *dev, uint16_t queue_id)
937b7b1ba64SNicolas Chautru {
93810829ff2SHernan Vargas 	struct fpga_5gnr_queue *q = dev->data->queues[queue_id].queue_private;
939b7b1ba64SNicolas Chautru 
940b7b1ba64SNicolas Chautru 	if (!rte_intr_cap_multiple(dev->intr_handle))
941b7b1ba64SNicolas Chautru 		return -ENOTSUP;
942b7b1ba64SNicolas Chautru 
943b7b1ba64SNicolas Chautru 	q->irq_enable = 1;
944b7b1ba64SNicolas Chautru 
945b7b1ba64SNicolas Chautru 	return 0;
946b7b1ba64SNicolas Chautru }
947b7b1ba64SNicolas Chautru 
948b7b1ba64SNicolas Chautru static int
94910829ff2SHernan Vargas fpga_5gnr_queue_intr_disable(struct rte_bbdev *dev, uint16_t queue_id)
950b7b1ba64SNicolas Chautru {
95110829ff2SHernan Vargas 	struct fpga_5gnr_queue *q = dev->data->queues[queue_id].queue_private;
952b7b1ba64SNicolas Chautru 	q->irq_enable = 0;
953b7b1ba64SNicolas Chautru 
954b7b1ba64SNicolas Chautru 	return 0;
955b7b1ba64SNicolas Chautru }
956b7b1ba64SNicolas Chautru 
957b7b1ba64SNicolas Chautru static int
95810829ff2SHernan Vargas fpga_5gnr_intr_enable(struct rte_bbdev *dev)
959b7b1ba64SNicolas Chautru {
960b7b1ba64SNicolas Chautru 	int ret;
961b7b1ba64SNicolas Chautru 	uint8_t i;
96299f09224SHernan Vargas 	struct fpga_5gnr_fec_device *d = dev->data->dev_private;
96399f09224SHernan Vargas 	uint8_t num_intr_vec;
964b7b1ba64SNicolas Chautru 
96599f09224SHernan Vargas 	num_intr_vec = d->total_num_queues - RTE_INTR_VEC_RXTX_OFFSET;
966b7b1ba64SNicolas Chautru 	if (!rte_intr_cap_multiple(dev->intr_handle)) {
967b7b1ba64SNicolas Chautru 		rte_bbdev_log(ERR, "Multiple intr vector is not supported by FPGA (%s)",
968b7b1ba64SNicolas Chautru 				dev->data->name);
969b7b1ba64SNicolas Chautru 		return -ENOTSUP;
970b7b1ba64SNicolas Chautru 	}
971b7b1ba64SNicolas Chautru 
97299f09224SHernan Vargas 	/* Create event file descriptors for each of the supported queues (Maximum 64).
97399f09224SHernan Vargas 	 * Event fds will be mapped to FPGA IRQs in rte_intr_enable().
97499f09224SHernan Vargas 	 * This is a 1:1 mapping where the IRQ number is a direct translation to the queue number.
975b7b1ba64SNicolas Chautru 	 *
97699f09224SHernan Vargas 	 * num_intr_vec event fds are created as rte_intr_enable()
977b7b1ba64SNicolas Chautru 	 * mapped the first IRQ to already created interrupt event file
978b7b1ba64SNicolas Chautru 	 * descriptor (intr_handle->fd).
979b7b1ba64SNicolas Chautru 	 */
98099f09224SHernan Vargas 	if (rte_intr_efd_enable(dev->intr_handle, num_intr_vec)) {
981c750d277SHernan Vargas 		rte_bbdev_log(ERR, "Failed to create fds for %u queues", dev->data->num_queues);
982b7b1ba64SNicolas Chautru 		return -1;
983b7b1ba64SNicolas Chautru 	}
984b7b1ba64SNicolas Chautru 
985b7b1ba64SNicolas Chautru 	/* TODO Each event file descriptor is overwritten by interrupt event
986b7b1ba64SNicolas Chautru 	 * file descriptor. That descriptor is added to epoll observed list.
987b7b1ba64SNicolas Chautru 	 * It ensures that callback function assigned to that descriptor will
988b7b1ba64SNicolas Chautru 	 * invoked when any FPGA queue issues interrupt.
989b7b1ba64SNicolas Chautru 	 */
99099f09224SHernan Vargas 	for (i = 0; i < num_intr_vec; ++i) {
991d61138d4SHarman Kalra 		if (rte_intr_efds_index_set(dev->intr_handle, i,
992d61138d4SHarman Kalra 				rte_intr_fd_get(dev->intr_handle)))
993d61138d4SHarman Kalra 			return -rte_errno;
994d61138d4SHarman Kalra 	}
995b7b1ba64SNicolas Chautru 
996c750d277SHernan Vargas 	if (rte_intr_vec_list_alloc(dev->intr_handle, "intr_vec", dev->data->num_queues)) {
997c750d277SHernan Vargas 		rte_bbdev_log(ERR, "Failed to allocate %u vectors", dev->data->num_queues);
998b7b1ba64SNicolas Chautru 		return -ENOMEM;
999b7b1ba64SNicolas Chautru 	}
1000b7b1ba64SNicolas Chautru 
1001b7b1ba64SNicolas Chautru 	ret = rte_intr_enable(dev->intr_handle);
1002b7b1ba64SNicolas Chautru 	if (ret < 0) {
1003b7b1ba64SNicolas Chautru 		rte_bbdev_log(ERR,
1004b7b1ba64SNicolas Chautru 				"Couldn't enable interrupts for device: %s",
1005b7b1ba64SNicolas Chautru 				dev->data->name);
1006b7b1ba64SNicolas Chautru 		return ret;
1007b7b1ba64SNicolas Chautru 	}
1008b7b1ba64SNicolas Chautru 
100910829ff2SHernan Vargas 	ret = rte_intr_callback_register(dev->intr_handle, fpga_5gnr_dev_interrupt_handler, dev);
1010b7b1ba64SNicolas Chautru 	if (ret < 0) {
1011b7b1ba64SNicolas Chautru 		rte_bbdev_log(ERR,
1012b7b1ba64SNicolas Chautru 				"Couldn't register interrupt callback for device: %s",
1013b7b1ba64SNicolas Chautru 				dev->data->name);
1014b7b1ba64SNicolas Chautru 		return ret;
1015b7b1ba64SNicolas Chautru 	}
1016b7b1ba64SNicolas Chautru 
1017b7b1ba64SNicolas Chautru 	return 0;
1018b7b1ba64SNicolas Chautru }
1019b7b1ba64SNicolas Chautru 
102010829ff2SHernan Vargas static const struct rte_bbdev_ops fpga_5gnr_ops = {
102110829ff2SHernan Vargas 	.setup_queues = fpga_5gnr_setup_queues,
102210829ff2SHernan Vargas 	.intr_enable = fpga_5gnr_intr_enable,
102310829ff2SHernan Vargas 	.close = fpga_5gnr_dev_close,
102410829ff2SHernan Vargas 	.info_get = fpga_5gnr_dev_info_get,
102510829ff2SHernan Vargas 	.queue_setup = fpga_5gnr_queue_setup,
102610829ff2SHernan Vargas 	.queue_stop = fpga_5gnr_queue_stop,
102710829ff2SHernan Vargas 	.queue_start = fpga_5gnr_queue_start,
102810829ff2SHernan Vargas 	.queue_release = fpga_5gnr_queue_release,
102910829ff2SHernan Vargas 	.queue_intr_enable = fpga_5gnr_queue_intr_enable,
103010829ff2SHernan Vargas 	.queue_intr_disable = fpga_5gnr_queue_intr_disable
10310b5927cbSNicolas Chautru };
103211b0a112SNicolas Chautru 
10339e3ffd38SHernan Vargas /* Provide the descriptor index on a given queue */
10349e3ffd38SHernan Vargas static inline uint16_t
10359e3ffd38SHernan Vargas fpga_5gnr_desc_idx(struct fpga_5gnr_queue *q, uint16_t offset)
10369e3ffd38SHernan Vargas {
10379e3ffd38SHernan Vargas 	return (q->head_free_desc + offset) & q->sw_ring_wrap_mask;
10389e3ffd38SHernan Vargas }
10399e3ffd38SHernan Vargas 
10409e3ffd38SHernan Vargas /* Provide the VC 5GNR descriptor pointer on a given queue */
10419e3ffd38SHernan Vargas static inline union vc_5gnr_dma_desc*
10429e3ffd38SHernan Vargas vc_5gnr_get_desc(struct fpga_5gnr_queue *q, uint16_t offset)
10439e3ffd38SHernan Vargas {
10449e3ffd38SHernan Vargas 	return q->vc_5gnr_ring_addr + fpga_5gnr_desc_idx(q, offset);
10459e3ffd38SHernan Vargas }
10469e3ffd38SHernan Vargas 
10479e3ffd38SHernan Vargas /* Provide the AGX100 descriptor pointer on a given queue */
10489e3ffd38SHernan Vargas static inline union agx100_dma_desc*
10499e3ffd38SHernan Vargas agx100_get_desc(struct fpga_5gnr_queue *q, uint16_t offset)
10509e3ffd38SHernan Vargas {
10519e3ffd38SHernan Vargas 	return q->agx100_ring_addr + fpga_5gnr_desc_idx(q, offset);
10529e3ffd38SHernan Vargas }
10539e3ffd38SHernan Vargas 
10549e3ffd38SHernan Vargas /* Provide the descriptor index for the tail of a given queue */
10559e3ffd38SHernan Vargas static inline uint16_t
10569e3ffd38SHernan Vargas fpga_5gnr_desc_idx_tail(struct fpga_5gnr_queue *q, uint16_t offset)
10579e3ffd38SHernan Vargas {
10589e3ffd38SHernan Vargas 	return (q->tail + offset) & q->sw_ring_wrap_mask;
10599e3ffd38SHernan Vargas }
10609e3ffd38SHernan Vargas 
10619e3ffd38SHernan Vargas /* Provide the descriptor tail pointer on a given queue */
10629e3ffd38SHernan Vargas static inline union vc_5gnr_dma_desc*
10639e3ffd38SHernan Vargas vc_5gnr_get_desc_tail(struct fpga_5gnr_queue *q, uint16_t offset)
10649e3ffd38SHernan Vargas {
10659e3ffd38SHernan Vargas 	return q->vc_5gnr_ring_addr + fpga_5gnr_desc_idx_tail(q, offset);
10669e3ffd38SHernan Vargas }
10679e3ffd38SHernan Vargas 
10689e3ffd38SHernan Vargas /* Provide the descriptor tail pointer on a given queue */
10699e3ffd38SHernan Vargas static inline union agx100_dma_desc*
10709e3ffd38SHernan Vargas agx100_get_desc_tail(struct fpga_5gnr_queue *q, uint16_t offset)
10719e3ffd38SHernan Vargas {
10729e3ffd38SHernan Vargas 	return q->agx100_ring_addr + fpga_5gnr_desc_idx_tail(q, offset);
10739e3ffd38SHernan Vargas }
10749e3ffd38SHernan Vargas 
107544dc6faaSNicolas Chautru static inline void
107610829ff2SHernan Vargas fpga_5gnr_dma_enqueue(struct fpga_5gnr_queue *q, uint16_t num_desc,
107744dc6faaSNicolas Chautru 		struct rte_bbdev_stats *queue_stats)
107844dc6faaSNicolas Chautru {
107944dc6faaSNicolas Chautru 	uint64_t start_time = 0;
108044dc6faaSNicolas Chautru 	queue_stats->acc_offload_cycles = 0;
108144dc6faaSNicolas Chautru 
108244dc6faaSNicolas Chautru 	/* Update tail and shadow_tail register */
10839e3ffd38SHernan Vargas 	q->tail = fpga_5gnr_desc_idx_tail(q, num_desc);
108444dc6faaSNicolas Chautru 
108544dc6faaSNicolas Chautru 	rte_wmb();
108644dc6faaSNicolas Chautru 
108744dc6faaSNicolas Chautru 	/* Start time measurement for enqueue function offload. */
108844dc6faaSNicolas Chautru 	start_time = rte_rdtsc_precise();
108944dc6faaSNicolas Chautru 	mmio_write_16(q->shadow_tail_addr, q->tail);
109044dc6faaSNicolas Chautru 
109144dc6faaSNicolas Chautru 	rte_wmb();
109244dc6faaSNicolas Chautru 	queue_stats->acc_offload_cycles += rte_rdtsc_precise() - start_time;
109344dc6faaSNicolas Chautru }
109444dc6faaSNicolas Chautru 
109544dc6faaSNicolas Chautru /* Read flag value 0/1/ from bitmap */
109644dc6faaSNicolas Chautru static inline bool
109744dc6faaSNicolas Chautru check_bit(uint32_t bitmap, uint32_t bitmask)
109844dc6faaSNicolas Chautru {
109944dc6faaSNicolas Chautru 	return bitmap & bitmask;
110044dc6faaSNicolas Chautru }
110144dc6faaSNicolas Chautru 
1102c750d277SHernan Vargas /* Vista Creek 5GNR FPGA descriptor errors.
1103c750d277SHernan Vargas  * Print an error if a descriptor error has occurred.
1104c750d277SHernan Vargas  * Return 0 on success, 1 on failure.
1105bee09be3SNicolas Chautru  */
1106bee09be3SNicolas Chautru static inline int
1107c750d277SHernan Vargas vc_5gnr_check_desc_error(uint32_t error_code) {
1108bee09be3SNicolas Chautru 	switch (error_code) {
1109c750d277SHernan Vargas 	case VC_5GNR_DESC_ERR_NO_ERR:
1110bee09be3SNicolas Chautru 		return 0;
1111c750d277SHernan Vargas 	case VC_5GNR_DESC_ERR_K_P_OUT_OF_RANGE:
1112bee09be3SNicolas Chautru 		rte_bbdev_log(ERR, "Encode block size K' is out of range");
1113bee09be3SNicolas Chautru 		break;
1114c750d277SHernan Vargas 	case VC_5GNR_DESC_ERR_Z_C_NOT_LEGAL:
1115bee09be3SNicolas Chautru 		rte_bbdev_log(ERR, "Zc is illegal");
1116bee09be3SNicolas Chautru 		break;
1117c750d277SHernan Vargas 	case VC_5GNR_DESC_ERR_DESC_OFFSET_ERR:
1118bee09be3SNicolas Chautru 		rte_bbdev_log(ERR,
1119bee09be3SNicolas Chautru 				"Queue offset does not meet the expectation in the FPGA"
1120bee09be3SNicolas Chautru 				);
1121bee09be3SNicolas Chautru 		break;
1122c750d277SHernan Vargas 	case VC_5GNR_DESC_ERR_DESC_READ_FAIL:
1123bee09be3SNicolas Chautru 		rte_bbdev_log(ERR, "Unsuccessful completion for descriptor read");
1124bee09be3SNicolas Chautru 		break;
1125c750d277SHernan Vargas 	case VC_5GNR_DESC_ERR_DESC_READ_TIMEOUT:
1126bee09be3SNicolas Chautru 		rte_bbdev_log(ERR, "Descriptor read time-out");
1127bee09be3SNicolas Chautru 		break;
1128c750d277SHernan Vargas 	case VC_5GNR_DESC_ERR_DESC_READ_TLP_POISONED:
1129bee09be3SNicolas Chautru 		rte_bbdev_log(ERR, "Descriptor read TLP poisoned");
1130bee09be3SNicolas Chautru 		break;
1131c750d277SHernan Vargas 	case VC_5GNR_DESC_ERR_HARQ_INPUT_LEN:
1132220c4708SHernan Vargas 		rte_bbdev_log(ERR, "HARQ input length is invalid");
1133220c4708SHernan Vargas 		break;
1134c750d277SHernan Vargas 	case VC_5GNR_DESC_ERR_CB_READ_FAIL:
1135bee09be3SNicolas Chautru 		rte_bbdev_log(ERR, "Unsuccessful completion for code block");
1136bee09be3SNicolas Chautru 		break;
1137c750d277SHernan Vargas 	case VC_5GNR_DESC_ERR_CB_READ_TIMEOUT:
1138bee09be3SNicolas Chautru 		rte_bbdev_log(ERR, "Code block read time-out");
1139bee09be3SNicolas Chautru 		break;
1140c750d277SHernan Vargas 	case VC_5GNR_DESC_ERR_CB_READ_TLP_POISONED:
1141bee09be3SNicolas Chautru 		rte_bbdev_log(ERR, "Code block read TLP poisoned");
1142bee09be3SNicolas Chautru 		break;
1143c750d277SHernan Vargas 	case VC_5GNR_DESC_ERR_HBSTORE_ERR:
1144bee09be3SNicolas Chautru 		rte_bbdev_log(ERR, "Hbstroe exceeds HARQ buffer size.");
1145bee09be3SNicolas Chautru 		break;
1146bee09be3SNicolas Chautru 	default:
1147c750d277SHernan Vargas 		rte_bbdev_log(ERR, "Descriptor error unknown error code %u", error_code);
1148bee09be3SNicolas Chautru 		break;
1149bee09be3SNicolas Chautru 	}
1150bee09be3SNicolas Chautru 	return 1;
1151bee09be3SNicolas Chautru }
1152bee09be3SNicolas Chautru 
11539e3ffd38SHernan Vargas /* AGX100 FPGA descriptor errors
11549e3ffd38SHernan Vargas  * Print an error if a descriptor error has occurred.
11559e3ffd38SHernan Vargas  * Return 0 on success, 1 on failure
11569e3ffd38SHernan Vargas  */
11579e3ffd38SHernan Vargas static inline int
11589e3ffd38SHernan Vargas agx100_check_desc_error(uint32_t error_code, uint32_t error_msg) {
11599e3ffd38SHernan Vargas 	uint8_t error = error_code << 4 | error_msg;
11609e3ffd38SHernan Vargas 	switch (error) {
11619e3ffd38SHernan Vargas 	case AGX100_DESC_ERR_NO_ERR:
11629e3ffd38SHernan Vargas 		return 0;
11639e3ffd38SHernan Vargas 	case AGX100_DESC_ERR_E_NOT_LEGAL:
11649e3ffd38SHernan Vargas 		rte_bbdev_log(ERR, "Invalid output length of rate matcher E");
11659e3ffd38SHernan Vargas 		break;
11669e3ffd38SHernan Vargas 	case AGX100_DESC_ERR_K_P_OUT_OF_RANGE:
11679e3ffd38SHernan Vargas 		rte_bbdev_log(ERR, "Encode block size K' is out of range");
11689e3ffd38SHernan Vargas 		break;
11699e3ffd38SHernan Vargas 	case AGX100_DESC_ERR_NCB_OUT_OF_RANGE:
11709e3ffd38SHernan Vargas 		rte_bbdev_log(ERR, "Ncb circular buffer size is out of range");
11719e3ffd38SHernan Vargas 		break;
11729e3ffd38SHernan Vargas 	case AGX100_DESC_ERR_Z_C_NOT_LEGAL:
11739e3ffd38SHernan Vargas 		rte_bbdev_log(ERR, "Zc is illegal");
11749e3ffd38SHernan Vargas 		break;
11759e3ffd38SHernan Vargas 	case AGX100_DESC_ERR_DESC_INDEX_ERR:
11769e3ffd38SHernan Vargas 		rte_bbdev_log(ERR,
11779e3ffd38SHernan Vargas 				"Desc_index received does not meet the expectation in the AGX100"
11789e3ffd38SHernan Vargas 				);
11799e3ffd38SHernan Vargas 		break;
11809e3ffd38SHernan Vargas 	case AGX100_DESC_ERR_HARQ_INPUT_LEN_A:
11819e3ffd38SHernan Vargas 		rte_bbdev_log(ERR, "HARQ input length A is invalid.");
11829e3ffd38SHernan Vargas 		break;
11839e3ffd38SHernan Vargas 	case AGX100_DESC_ERR_HARQ_INPUT_LEN_B:
11849e3ffd38SHernan Vargas 		rte_bbdev_log(ERR, "HARQ input length B is invalid.");
11859e3ffd38SHernan Vargas 		break;
11869e3ffd38SHernan Vargas 	case AGX100_DESC_ERR_HBSTORE_OFFSET_ERR:
11879e3ffd38SHernan Vargas 		rte_bbdev_log(ERR, "Hbstore exceeds HARQ buffer size.");
11889e3ffd38SHernan Vargas 		break;
11899e3ffd38SHernan Vargas 	case AGX100_DESC_ERR_TB_CBG_ERR:
11909e3ffd38SHernan Vargas 		rte_bbdev_log(ERR, "Total CB number C=0 or CB number with Ea Ca=0 or Ca>C.");
11919e3ffd38SHernan Vargas 		break;
11929e3ffd38SHernan Vargas 	case AGX100_DESC_ERR_CBG_OUT_OF_RANGE:
11939e3ffd38SHernan Vargas 		rte_bbdev_log(ERR, "Cbgti or max_cbg is out of range");
11949e3ffd38SHernan Vargas 		break;
11959e3ffd38SHernan Vargas 	case AGX100_DESC_ERR_CW_RM_NOT_LEGAL:
11969e3ffd38SHernan Vargas 		rte_bbdev_log(ERR, "Cw_rm is illegal");
11979e3ffd38SHernan Vargas 		break;
11989e3ffd38SHernan Vargas 	case AGX100_DESC_ERR_UNSUPPORTED_REQ:
11999e3ffd38SHernan Vargas 		rte_bbdev_log(ERR, "Unsupported request for descriptor");
12009e3ffd38SHernan Vargas 		break;
12019e3ffd38SHernan Vargas 	case AGX100_DESC_ERR_RESERVED:
12029e3ffd38SHernan Vargas 		rte_bbdev_log(ERR, "Reserved");
12039e3ffd38SHernan Vargas 		break;
12049e3ffd38SHernan Vargas 	case AGX100_DESC_ERR_DESC_ABORT:
12059e3ffd38SHernan Vargas 		rte_bbdev_log(ERR, "Completed abort for descriptor");
12069e3ffd38SHernan Vargas 		break;
12079e3ffd38SHernan Vargas 	case AGX100_DESC_ERR_DESC_READ_TLP_POISONED:
12089e3ffd38SHernan Vargas 		rte_bbdev_log(ERR, "Descriptor read TLP poisoned");
12099e3ffd38SHernan Vargas 		break;
12109e3ffd38SHernan Vargas 	default:
12119e3ffd38SHernan Vargas 		rte_bbdev_log(ERR,
12129e3ffd38SHernan Vargas 				"Descriptor error unknown error code %u error msg %u",
12139e3ffd38SHernan Vargas 				error_code, error_msg);
12149e3ffd38SHernan Vargas 		break;
12159e3ffd38SHernan Vargas 	}
12169e3ffd38SHernan Vargas 	return 1;
12179e3ffd38SHernan Vargas }
12189e3ffd38SHernan Vargas 
121944dc6faaSNicolas Chautru /* Compute value of k0.
122044dc6faaSNicolas Chautru  * Based on 3GPP 38.212 Table 5.4.2.1-2
122144dc6faaSNicolas Chautru  * Starting position of different redundancy versions, k0
122244dc6faaSNicolas Chautru  */
122344dc6faaSNicolas Chautru static inline uint16_t
122444dc6faaSNicolas Chautru get_k0(uint16_t n_cb, uint16_t z_c, uint8_t bg, uint8_t rv_index)
122544dc6faaSNicolas Chautru {
12268b087b96SHernan Vargas 	uint16_t n = (bg == 1 ? N_ZC_1 : N_ZC_2) * z_c;
122744dc6faaSNicolas Chautru 	if (rv_index == 0)
122844dc6faaSNicolas Chautru 		return 0;
12298b087b96SHernan Vargas 	if (z_c == 0)
12308b087b96SHernan Vargas 		return 0;
123144dc6faaSNicolas Chautru 	if (n_cb == n) {
123244dc6faaSNicolas Chautru 		if (rv_index == 1)
123344dc6faaSNicolas Chautru 			return (bg == 1 ? K0_1_1 : K0_1_2) * z_c;
123444dc6faaSNicolas Chautru 		else if (rv_index == 2)
123544dc6faaSNicolas Chautru 			return (bg == 1 ? K0_2_1 : K0_2_2) * z_c;
123644dc6faaSNicolas Chautru 		else
123744dc6faaSNicolas Chautru 			return (bg == 1 ? K0_3_1 : K0_3_2) * z_c;
123844dc6faaSNicolas Chautru 	}
123944dc6faaSNicolas Chautru 	/* LBRM case - includes a division by N */
124044dc6faaSNicolas Chautru 	if (rv_index == 1)
124144dc6faaSNicolas Chautru 		return (((bg == 1 ? K0_1_1 : K0_1_2) * n_cb)
124244dc6faaSNicolas Chautru 				/ n) * z_c;
124344dc6faaSNicolas Chautru 	else if (rv_index == 2)
124444dc6faaSNicolas Chautru 		return (((bg == 1 ? K0_2_1 : K0_2_2) * n_cb)
124544dc6faaSNicolas Chautru 				/ n) * z_c;
124644dc6faaSNicolas Chautru 	else
124744dc6faaSNicolas Chautru 		return (((bg == 1 ? K0_3_1 : K0_3_2) * n_cb)
124844dc6faaSNicolas Chautru 				/ n) * z_c;
124944dc6faaSNicolas Chautru }
125044dc6faaSNicolas Chautru 
125144dc6faaSNicolas Chautru /**
1252c750d277SHernan Vargas  * Vista Creek 5GNR FPGA
125344dc6faaSNicolas Chautru  * Set DMA descriptor for encode operation (1 Code Block)
125444dc6faaSNicolas Chautru  *
125544dc6faaSNicolas Chautru  * @param op
125644dc6faaSNicolas Chautru  *   Pointer to a single encode operation.
125744dc6faaSNicolas Chautru  * @param desc
125844dc6faaSNicolas Chautru  *   Pointer to DMA descriptor.
125944dc6faaSNicolas Chautru  * @param input
126044dc6faaSNicolas Chautru  *   Pointer to pointer to input data which will be decoded.
126144dc6faaSNicolas Chautru  * @param e
126244dc6faaSNicolas Chautru  *   E value (length of output in bits).
126344dc6faaSNicolas Chautru  * @param ncb
126444dc6faaSNicolas Chautru  *   Ncb value (size of the soft buffer).
126544dc6faaSNicolas Chautru  * @param out_length
126644dc6faaSNicolas Chautru  *   Length of output buffer
126744dc6faaSNicolas Chautru  * @param in_offset
126844dc6faaSNicolas Chautru  *   Input offset in rte_mbuf structure. It is used for calculating the point
126944dc6faaSNicolas Chautru  *   where data is starting.
127044dc6faaSNicolas Chautru  * @param out_offset
127144dc6faaSNicolas Chautru  *   Output offset in rte_mbuf structure. It is used for calculating the point
127244dc6faaSNicolas Chautru  *   where hard output data will be stored.
127344dc6faaSNicolas Chautru  * @param cbs_in_op
127444dc6faaSNicolas Chautru  *   Number of CBs contained in one operation.
127544dc6faaSNicolas Chautru  */
127644dc6faaSNicolas Chautru static inline int
1277c750d277SHernan Vargas vc_5gnr_dma_desc_te_fill(struct rte_bbdev_enc_op *op,
1278c750d277SHernan Vargas 		struct vc_5gnr_dma_enc_desc *desc, struct rte_mbuf *input,
127944dc6faaSNicolas Chautru 		struct rte_mbuf *output, uint16_t k_,  uint16_t e,
128044dc6faaSNicolas Chautru 		uint32_t in_offset, uint32_t out_offset, uint16_t desc_offset,
128144dc6faaSNicolas Chautru 		uint8_t cbs_in_op)
128244dc6faaSNicolas Chautru {
128344dc6faaSNicolas Chautru 	/* reset */
128444dc6faaSNicolas Chautru 	desc->done = 0;
128544dc6faaSNicolas Chautru 	desc->error = 0;
128644dc6faaSNicolas Chautru 	desc->k_ = k_;
128744dc6faaSNicolas Chautru 	desc->rm_e = e;
128844dc6faaSNicolas Chautru 	desc->desc_idx = desc_offset;
128944dc6faaSNicolas Chautru 	desc->zc = op->ldpc_enc.z_c;
129044dc6faaSNicolas Chautru 	desc->bg_idx = op->ldpc_enc.basegraph - 1;
129144dc6faaSNicolas Chautru 	desc->qm_idx = op->ldpc_enc.q_m / 2;
129244dc6faaSNicolas Chautru 	desc->crc_en = check_bit(op->ldpc_enc.op_flags,
129344dc6faaSNicolas Chautru 			RTE_BBDEV_LDPC_CRC_24B_ATTACH);
129444dc6faaSNicolas Chautru 	desc->irq_en = 0;
129544dc6faaSNicolas Chautru 	desc->k0 = get_k0(op->ldpc_enc.n_cb, op->ldpc_enc.z_c,
129644dc6faaSNicolas Chautru 			op->ldpc_enc.basegraph, op->ldpc_enc.rv_index);
129744dc6faaSNicolas Chautru 	desc->ncb = op->ldpc_enc.n_cb;
129844dc6faaSNicolas Chautru 	desc->num_null = op->ldpc_enc.n_filler;
129944dc6faaSNicolas Chautru 	/* Set inbound data buffer address */
130044dc6faaSNicolas Chautru 	desc->in_addr_hi = (uint32_t)(
1301ce627d63SThomas Monjalon 			rte_pktmbuf_iova_offset(input, in_offset) >> 32);
130244dc6faaSNicolas Chautru 	desc->in_addr_lw = (uint32_t)(
1303ce627d63SThomas Monjalon 			rte_pktmbuf_iova_offset(input, in_offset));
130444dc6faaSNicolas Chautru 
130544dc6faaSNicolas Chautru 	desc->out_addr_hi = (uint32_t)(
1306ce627d63SThomas Monjalon 			rte_pktmbuf_iova_offset(output, out_offset) >> 32);
130744dc6faaSNicolas Chautru 	desc->out_addr_lw = (uint32_t)(
1308ce627d63SThomas Monjalon 			rte_pktmbuf_iova_offset(output, out_offset));
130944dc6faaSNicolas Chautru 	/* Save software context needed for dequeue */
131044dc6faaSNicolas Chautru 	desc->op_addr = op;
131144dc6faaSNicolas Chautru 	/* Set total number of CBs in an op */
131244dc6faaSNicolas Chautru 	desc->cbs_in_op = cbs_in_op;
131344dc6faaSNicolas Chautru 	return 0;
131444dc6faaSNicolas Chautru }
131544dc6faaSNicolas Chautru 
131644dc6faaSNicolas Chautru /**
13179e3ffd38SHernan Vargas  * AGX100 FPGA
13189e3ffd38SHernan Vargas  * Set DMA descriptor for encode operation (1 Code Block)
13199e3ffd38SHernan Vargas  *
13209e3ffd38SHernan Vargas  * @param op
13219e3ffd38SHernan Vargas  *   Pointer to a single encode operation.
13229e3ffd38SHernan Vargas  * @param desc
13239e3ffd38SHernan Vargas  *   Pointer to DMA descriptor.
13249e3ffd38SHernan Vargas  * @param input
13259e3ffd38SHernan Vargas  *   Pointer to pointer to input data which will be decoded.
13269e3ffd38SHernan Vargas  * @param e
13279e3ffd38SHernan Vargas  *   E value (length of output in bits).
13289e3ffd38SHernan Vargas  * @param ncb
13299e3ffd38SHernan Vargas  *   Ncb value (size of the soft buffer).
13309e3ffd38SHernan Vargas  * @param out_length
13319e3ffd38SHernan Vargas  *   Length of output buffer
13329e3ffd38SHernan Vargas  * @param in_offset
13339e3ffd38SHernan Vargas  *   Input offset in rte_mbuf structure. It is used for calculating the point
13349e3ffd38SHernan Vargas  *   where data is starting.
13359e3ffd38SHernan Vargas  * @param out_offset
13369e3ffd38SHernan Vargas  *   Output offset in rte_mbuf structure. It is used for calculating the point
13379e3ffd38SHernan Vargas  *   where hard output data will be stored.
13389e3ffd38SHernan Vargas  * @param cbs_in_op
13399e3ffd38SHernan Vargas  *   Number of CBs contained in one operation.
13409e3ffd38SHernan Vargas  */
13419e3ffd38SHernan Vargas static inline int
13429e3ffd38SHernan Vargas agx100_dma_desc_le_fill(struct rte_bbdev_enc_op *op,
13439e3ffd38SHernan Vargas 		struct agx100_dma_enc_desc *desc, struct rte_mbuf *input,
13449e3ffd38SHernan Vargas 		struct rte_mbuf *output, uint16_t k_,  uint32_t e,
13459e3ffd38SHernan Vargas 		uint32_t in_offset, uint32_t out_offset, uint16_t desc_offset,
13469e3ffd38SHernan Vargas 		uint8_t cbs_in_op)
13479e3ffd38SHernan Vargas {
13489e3ffd38SHernan Vargas 	/* reset. */
13499e3ffd38SHernan Vargas 	desc->done = 0;
13509e3ffd38SHernan Vargas 	desc->error_msg = 0;
13519e3ffd38SHernan Vargas 	desc->error_code = 0;
13529e3ffd38SHernan Vargas 	desc->ncb = op->ldpc_enc.n_cb;
13539e3ffd38SHernan Vargas 	desc->bg_idx = op->ldpc_enc.basegraph - 1;
13549e3ffd38SHernan Vargas 	desc->qm_idx = op->ldpc_enc.q_m >> 1;
13559e3ffd38SHernan Vargas 	desc->zc = op->ldpc_enc.z_c;
13569e3ffd38SHernan Vargas 	desc->rv = op->ldpc_enc.rv_index;
13579e3ffd38SHernan Vargas 	desc->int_en = 0;	/**< Set by device externally. */
13589e3ffd38SHernan Vargas 	desc->max_cbg = 0;	/**< TODO: CBG specific. */
13599e3ffd38SHernan Vargas 	desc->cbgti = 0;	/**< TODO: CBG specific. */
13609e3ffd38SHernan Vargas 	desc->cbgs = 0;		/**< TODO: CBG specific. */
13619e3ffd38SHernan Vargas 	desc->desc_idx = desc_offset;
13629e3ffd38SHernan Vargas 	desc->ca = 0;	/**< TODO: CBG specific. */
13639e3ffd38SHernan Vargas 	desc->c = 0;	/**< TODO: CBG specific. */
13649e3ffd38SHernan Vargas 	desc->num_null = op->ldpc_enc.n_filler;
13659e3ffd38SHernan Vargas 	desc->ea = e;
13669e3ffd38SHernan Vargas 	desc->eb = e;	/**< TODO: TB/CBG specific. */
13679e3ffd38SHernan Vargas 	desc->k_ = k_;
13689e3ffd38SHernan Vargas 	desc->en_slice_ts = 0;	/**< TODO: Slice specific. */
13699e3ffd38SHernan Vargas 	desc->en_host_ts = 0;	/**< TODO: Slice specific. */
13709e3ffd38SHernan Vargas 	desc->en_cb_wr_status = 0;	/**< TODO: Event Queue specific. */
13719e3ffd38SHernan Vargas 	desc->en_output_sg = 0;	/**< TODO: Slice specific. */
13729e3ffd38SHernan Vargas 	desc->en_input_sg = 0;	/**< TODO: Slice specific. */
13739e3ffd38SHernan Vargas 	desc->tb_cb = 0;	/**< Descriptor for CB. TODO: Add TB and CBG logic. */
13749e3ffd38SHernan Vargas 	desc->crc_en = check_bit(op->ldpc_enc.op_flags,
13759e3ffd38SHernan Vargas 			RTE_BBDEV_LDPC_CRC_24B_ATTACH);
13769e3ffd38SHernan Vargas 
13779e3ffd38SHernan Vargas 	/* Set inbound/outbound data buffer address. */
13789e3ffd38SHernan Vargas 	/* TODO: add logic for input_slice. */
13799e3ffd38SHernan Vargas 	desc->output_start_addr_hi = (uint32_t)(
13809e3ffd38SHernan Vargas 			rte_pktmbuf_iova_offset(output, out_offset) >> 32);
13819e3ffd38SHernan Vargas 	desc->output_start_addr_lo = (uint32_t)(
13829e3ffd38SHernan Vargas 			rte_pktmbuf_iova_offset(output, out_offset));
13839e3ffd38SHernan Vargas 	desc->input_start_addr_hi = (uint32_t)(
13849e3ffd38SHernan Vargas 			rte_pktmbuf_iova_offset(input, in_offset) >> 32);
13859e3ffd38SHernan Vargas 	desc->input_start_addr_lo = (uint32_t)(
13869e3ffd38SHernan Vargas 			rte_pktmbuf_iova_offset(input, in_offset));
13879e3ffd38SHernan Vargas 	desc->output_length = (e + 7) >> 3; /* in bytes. */
13889e3ffd38SHernan Vargas 	desc->input_length = input->data_len;
13899e3ffd38SHernan Vargas 	desc->enqueue_timestamp = 0;
13909e3ffd38SHernan Vargas 	desc->completion_timestamp = 0;
13919e3ffd38SHernan Vargas 	/* Save software context needed for dequeue. */
13929e3ffd38SHernan Vargas 	desc->op_addr = op;
13939e3ffd38SHernan Vargas 	/* Set total number of CBs in an op. */
13949e3ffd38SHernan Vargas 	desc->cbs_in_op = cbs_in_op;
13959e3ffd38SHernan Vargas 	return 0;
13969e3ffd38SHernan Vargas }
13979e3ffd38SHernan Vargas 
13989e3ffd38SHernan Vargas /**
1399c750d277SHernan Vargas  * Vista Creek 5GNR FPGA
140044dc6faaSNicolas Chautru  * Set DMA descriptor for decode operation (1 Code Block)
140144dc6faaSNicolas Chautru  *
140244dc6faaSNicolas Chautru  * @param op
140344dc6faaSNicolas Chautru  *   Pointer to a single encode operation.
140444dc6faaSNicolas Chautru  * @param desc
140544dc6faaSNicolas Chautru  *   Pointer to DMA descriptor.
140644dc6faaSNicolas Chautru  * @param input
140744dc6faaSNicolas Chautru  *   Pointer to pointer to input data which will be decoded.
140844dc6faaSNicolas Chautru  * @param in_offset
140944dc6faaSNicolas Chautru  *   Input offset in rte_mbuf structure. It is used for calculating the point
141044dc6faaSNicolas Chautru  *   where data is starting.
141144dc6faaSNicolas Chautru  * @param out_offset
141244dc6faaSNicolas Chautru  *   Output offset in rte_mbuf structure. It is used for calculating the point
141344dc6faaSNicolas Chautru  *   where hard output data will be stored.
141444dc6faaSNicolas Chautru  * @param cbs_in_op
141544dc6faaSNicolas Chautru  *   Number of CBs contained in one operation.
141644dc6faaSNicolas Chautru  */
141744dc6faaSNicolas Chautru static inline int
1418c750d277SHernan Vargas vc_5gnr_dma_desc_ld_fill(struct rte_bbdev_dec_op *op,
1419c750d277SHernan Vargas 		struct vc_5gnr_dma_dec_desc *desc,
142044dc6faaSNicolas Chautru 		struct rte_mbuf *input,	struct rte_mbuf *output,
142144dc6faaSNicolas Chautru 		uint16_t harq_in_length,
142244dc6faaSNicolas Chautru 		uint32_t in_offset, uint32_t out_offset,
142344dc6faaSNicolas Chautru 		uint32_t harq_offset,
142444dc6faaSNicolas Chautru 		uint16_t desc_offset,
142544dc6faaSNicolas Chautru 		uint8_t cbs_in_op)
142644dc6faaSNicolas Chautru {
142744dc6faaSNicolas Chautru 	/* reset */
142844dc6faaSNicolas Chautru 	desc->done = 0;
142944dc6faaSNicolas Chautru 	desc->error = 0;
143044dc6faaSNicolas Chautru 	/* Set inbound data buffer address */
143144dc6faaSNicolas Chautru 	desc->in_addr_hi = (uint32_t)(
1432ce627d63SThomas Monjalon 			rte_pktmbuf_iova_offset(input, in_offset) >> 32);
143344dc6faaSNicolas Chautru 	desc->in_addr_lw = (uint32_t)(
1434ce627d63SThomas Monjalon 			rte_pktmbuf_iova_offset(input, in_offset));
143544dc6faaSNicolas Chautru 	desc->rm_e = op->ldpc_dec.cb_params.e;
143644dc6faaSNicolas Chautru 	desc->harq_input_length = harq_in_length;
143744dc6faaSNicolas Chautru 	desc->et_dis = !check_bit(op->ldpc_dec.op_flags,
143844dc6faaSNicolas Chautru 			RTE_BBDEV_LDPC_ITERATION_STOP_ENABLE);
143944dc6faaSNicolas Chautru 	desc->rv = op->ldpc_dec.rv_index;
144044dc6faaSNicolas Chautru 	desc->crc24b_ind = check_bit(op->ldpc_dec.op_flags,
144144dc6faaSNicolas Chautru 			RTE_BBDEV_LDPC_CRC_TYPE_24B_CHECK);
144244dc6faaSNicolas Chautru 	desc->drop_crc24b = check_bit(op->ldpc_dec.op_flags,
144344dc6faaSNicolas Chautru 			RTE_BBDEV_LDPC_CRC_TYPE_24B_DROP);
144444dc6faaSNicolas Chautru 	desc->desc_idx = desc_offset;
144544dc6faaSNicolas Chautru 	desc->ncb = op->ldpc_dec.n_cb;
144644dc6faaSNicolas Chautru 	desc->num_null = op->ldpc_dec.n_filler;
144744dc6faaSNicolas Chautru 	desc->hbstroe_offset = harq_offset >> 10;
144844dc6faaSNicolas Chautru 	desc->zc = op->ldpc_dec.z_c;
144944dc6faaSNicolas Chautru 	desc->harqin_en = check_bit(op->ldpc_dec.op_flags,
145044dc6faaSNicolas Chautru 			RTE_BBDEV_LDPC_HQ_COMBINE_IN_ENABLE);
145144dc6faaSNicolas Chautru 	desc->bg_idx = op->ldpc_dec.basegraph - 1;
145244dc6faaSNicolas Chautru 	desc->max_iter = op->ldpc_dec.iter_max;
145344dc6faaSNicolas Chautru 	desc->qm_idx = op->ldpc_dec.q_m / 2;
145444dc6faaSNicolas Chautru 	desc->out_addr_hi = (uint32_t)(
1455ce627d63SThomas Monjalon 			rte_pktmbuf_iova_offset(output, out_offset) >> 32);
145644dc6faaSNicolas Chautru 	desc->out_addr_lw = (uint32_t)(
1457ce627d63SThomas Monjalon 			rte_pktmbuf_iova_offset(output, out_offset));
145844dc6faaSNicolas Chautru 	/* Save software context needed for dequeue */
145944dc6faaSNicolas Chautru 	desc->op_addr = op;
146044dc6faaSNicolas Chautru 	/* Set total number of CBs in an op */
146144dc6faaSNicolas Chautru 	desc->cbs_in_op = cbs_in_op;
146244dc6faaSNicolas Chautru 
146344dc6faaSNicolas Chautru 	return 0;
146444dc6faaSNicolas Chautru }
146544dc6faaSNicolas Chautru 
14669e3ffd38SHernan Vargas /**
14679e3ffd38SHernan Vargas  * AGX100 FPGA
14689e3ffd38SHernan Vargas  * Set DMA descriptor for decode operation (1 Code Block)
14699e3ffd38SHernan Vargas  *
14709e3ffd38SHernan Vargas  * @param op
14719e3ffd38SHernan Vargas  *   Pointer to a single encode operation.
14729e3ffd38SHernan Vargas  * @param desc
14739e3ffd38SHernan Vargas  *   Pointer to DMA descriptor.
14749e3ffd38SHernan Vargas  * @param input
14759e3ffd38SHernan Vargas  *   Pointer to pointer to input data which will be decoded.
14769e3ffd38SHernan Vargas  * @param in_offset
14779e3ffd38SHernan Vargas  *   Input offset in rte_mbuf structure. It is used for calculating the point
14789e3ffd38SHernan Vargas  *   where data is starting.
14799e3ffd38SHernan Vargas  * @param out_offset
14809e3ffd38SHernan Vargas  *   Output offset in rte_mbuf structure. It is used for calculating the point
14819e3ffd38SHernan Vargas  *   where hard output data will be stored.
14829e3ffd38SHernan Vargas  * @param cbs_in_op
14839e3ffd38SHernan Vargas  *   Number of CBs contained in one operation.
14849e3ffd38SHernan Vargas  */
14859e3ffd38SHernan Vargas static inline int
14869e3ffd38SHernan Vargas agx100_dma_desc_ld_fill(struct rte_bbdev_dec_op *op,
14879e3ffd38SHernan Vargas 		struct agx100_dma_dec_desc *desc,
14889e3ffd38SHernan Vargas 		struct rte_mbuf *input,	struct rte_mbuf *output,
14899e3ffd38SHernan Vargas 		uint16_t harq_in_length,
14909e3ffd38SHernan Vargas 		uint32_t in_offset, uint32_t out_offset,
14919e3ffd38SHernan Vargas 		uint32_t harq_in_offset,
14929e3ffd38SHernan Vargas 		uint32_t harq_out_offset,
14939e3ffd38SHernan Vargas 		uint16_t desc_offset,
14949e3ffd38SHernan Vargas 		uint8_t cbs_in_op)
14959e3ffd38SHernan Vargas {
14969e3ffd38SHernan Vargas 	/* reset. */
14979e3ffd38SHernan Vargas 	desc->done = 0;
14989e3ffd38SHernan Vargas 	desc->tb_crc_pass = 0;
14999e3ffd38SHernan Vargas 	desc->cb_crc_all_pass = 0;
15009e3ffd38SHernan Vargas 	desc->cb_all_et_pass = 0;
15019e3ffd38SHernan Vargas 	desc->max_iter_ret = 0;
15029e3ffd38SHernan Vargas 	desc->cgb_crc_bitmap = 0;	/**< TODO: CBG specific. */
15039e3ffd38SHernan Vargas 	desc->error_msg = 0;
15049e3ffd38SHernan Vargas 	desc->error_code = 0;
15059e3ffd38SHernan Vargas 	desc->et_dis = !check_bit(op->ldpc_dec.op_flags,
15069e3ffd38SHernan Vargas 			RTE_BBDEV_LDPC_ITERATION_STOP_ENABLE);
15079e3ffd38SHernan Vargas 	desc->harq_in_en = check_bit(op->ldpc_dec.op_flags,
15089e3ffd38SHernan Vargas 			RTE_BBDEV_LDPC_HQ_COMBINE_IN_ENABLE);
15099e3ffd38SHernan Vargas 	desc->max_iter = op->ldpc_dec.iter_max;
15109e3ffd38SHernan Vargas 	desc->ncb = op->ldpc_dec.n_cb;
15119e3ffd38SHernan Vargas 	desc->bg_idx = op->ldpc_dec.basegraph - 1;
15129e3ffd38SHernan Vargas 	desc->qm_idx = op->ldpc_dec.q_m >> 1;
15139e3ffd38SHernan Vargas 	desc->zc = op->ldpc_dec.z_c;
15149e3ffd38SHernan Vargas 	desc->rv = op->ldpc_dec.rv_index;
15159e3ffd38SHernan Vargas 	desc->int_en = 0;	/**< Set by device externally. */
15169e3ffd38SHernan Vargas 	desc->max_cbg = 0;	/**< TODO: CBG specific. */
15179e3ffd38SHernan Vargas 	desc->cbgti = 0;	/**< TODO: CBG specific. */
15189e3ffd38SHernan Vargas 	desc->cbgfi = 0;	/**< TODO: CBG specific. */
15199e3ffd38SHernan Vargas 	desc->cbgs = 0;		/**< TODO: CBG specific. */
15209e3ffd38SHernan Vargas 	desc->desc_idx = desc_offset;
15219e3ffd38SHernan Vargas 	desc->ca = 0;	/**< TODO: CBG specific. */
15229e3ffd38SHernan Vargas 	desc->c = 0;		/**< TODO: CBG specific. */
15239e3ffd38SHernan Vargas 	desc->llr_pckg = 0;		/**< TODO: Not implemented yet. */
15249e3ffd38SHernan Vargas 	desc->syndrome_check_mode = 1;	/**< TODO: Make it configurable. */
15259e3ffd38SHernan Vargas 	desc->num_null = op->ldpc_dec.n_filler;
15269e3ffd38SHernan Vargas 	desc->ea = op->ldpc_dec.cb_params.e;	/**< TODO: TB/CBG specific. */
15279e3ffd38SHernan Vargas 	desc->eba = 0;	/**< TODO: TB/CBG specific. */
15289e3ffd38SHernan Vargas 	desc->hbstore_offset_out = harq_out_offset >> 10;
15299e3ffd38SHernan Vargas 	desc->hbstore_offset_in = harq_in_offset >> 10;
15309e3ffd38SHernan Vargas 	desc->en_slice_ts = 0;	/**< TODO: Slice specific. */
15319e3ffd38SHernan Vargas 	desc->en_host_ts = 0;	/**< TODO: Slice specific. */
15329e3ffd38SHernan Vargas 	desc->en_cb_wr_status = 0;	/**< TODO: Event Queue specific. */
15339e3ffd38SHernan Vargas 	desc->en_output_sg = 0;	/**< TODO: Slice specific. */
15349e3ffd38SHernan Vargas 	desc->en_input_sg = 0;	/**< TODO: Slice specific. */
15359e3ffd38SHernan Vargas 	desc->tb_cb = 0; /**< Descriptor for CB. TODO: Add TB and CBG logic. */
15369e3ffd38SHernan Vargas 	desc->crc24b_ind = check_bit(op->ldpc_dec.op_flags,
15379e3ffd38SHernan Vargas 			RTE_BBDEV_LDPC_CRC_TYPE_24B_CHECK);
15389e3ffd38SHernan Vargas 	desc->drop_crc24b = check_bit(op->ldpc_dec.op_flags,
15399e3ffd38SHernan Vargas 			RTE_BBDEV_LDPC_CRC_TYPE_24B_DROP);
15409e3ffd38SHernan Vargas 	desc->harq_input_length_a =
15419e3ffd38SHernan Vargas 			harq_in_length; /**< Descriptor for CB. TODO: Add TB and CBG logic. */
15429e3ffd38SHernan Vargas 	desc->harq_input_length_b = 0; /**< Descriptor for CB. TODO: Add TB and CBG logic. */
15439e3ffd38SHernan Vargas 	/* Set inbound/outbound data buffer address. */
15449e3ffd38SHernan Vargas 	/* TODO: add logic for input_slice. */
15459e3ffd38SHernan Vargas 	desc->output_start_addr_hi = (uint32_t)(
15469e3ffd38SHernan Vargas 			rte_pktmbuf_iova_offset(output, out_offset) >> 32);
15479e3ffd38SHernan Vargas 	desc->output_start_addr_lo = (uint32_t)(
15489e3ffd38SHernan Vargas 			rte_pktmbuf_iova_offset(output, out_offset));
15499e3ffd38SHernan Vargas 	desc->input_start_addr_hi = (uint32_t)(
15509e3ffd38SHernan Vargas 			rte_pktmbuf_iova_offset(input, in_offset) >> 32);
15519e3ffd38SHernan Vargas 	desc->input_start_addr_lo = (uint32_t)(
15529e3ffd38SHernan Vargas 			rte_pktmbuf_iova_offset(input, in_offset));
15539e3ffd38SHernan Vargas 	desc->output_length = (((op->ldpc_dec.basegraph == 1) ? 22 : 10) * op->ldpc_dec.z_c
15549e3ffd38SHernan Vargas 			- op->ldpc_dec.n_filler - desc->drop_crc24b * 24) >> 3;
15559e3ffd38SHernan Vargas 	desc->input_length = op->ldpc_dec.cb_params.e;	/**< TODO: TB/CBG specific. */
15569e3ffd38SHernan Vargas 	desc->enqueue_timestamp = 0;
15579e3ffd38SHernan Vargas 	desc->completion_timestamp = 0;
15589e3ffd38SHernan Vargas 	/* Save software context needed for dequeue. */
15599e3ffd38SHernan Vargas 	desc->op_addr = op;
15609e3ffd38SHernan Vargas 	/* Set total number of CBs in an op. */
15619e3ffd38SHernan Vargas 	desc->cbs_in_op = cbs_in_op;
15629e3ffd38SHernan Vargas 	return 0;
15639e3ffd38SHernan Vargas }
15649e3ffd38SHernan Vargas 
1565c750d277SHernan Vargas /* Validates LDPC encoder parameters for VC 5GNR FPGA. */
1566984b7306SHernan Vargas static inline int
1567c750d277SHernan Vargas vc_5gnr_validate_ldpc_enc_op(struct rte_bbdev_enc_op *op)
156811b0a112SNicolas Chautru {
156911b0a112SNicolas Chautru 	struct rte_bbdev_op_ldpc_enc *ldpc_enc = &op->ldpc_enc;
1570c750d277SHernan Vargas 	int z_c, n_filler, K, Kp, q_m, n_cb, N, k0, crc24;
1571c750d277SHernan Vargas 	int32_t L, Lcb, cw, cw_rm, e;
157211b0a112SNicolas Chautru 
157311b0a112SNicolas Chautru 	if (ldpc_enc->input.data == NULL) {
157411b0a112SNicolas Chautru 		rte_bbdev_log(ERR, "Invalid input pointer");
157511b0a112SNicolas Chautru 		return -1;
157611b0a112SNicolas Chautru 	}
157711b0a112SNicolas Chautru 	if (ldpc_enc->output.data == NULL) {
157811b0a112SNicolas Chautru 		rte_bbdev_log(ERR, "Invalid output pointer");
157911b0a112SNicolas Chautru 		return -1;
158011b0a112SNicolas Chautru 	}
1581984b7306SHernan Vargas 	if (ldpc_enc->input.length == 0) {
1582984b7306SHernan Vargas 		rte_bbdev_log(ERR, "CB size (%u) is null",
1583984b7306SHernan Vargas 				ldpc_enc->input.length);
1584984b7306SHernan Vargas 		return -1;
1585984b7306SHernan Vargas 	}
158611b0a112SNicolas Chautru 	if ((ldpc_enc->basegraph > 2) || (ldpc_enc->basegraph == 0)) {
158711b0a112SNicolas Chautru 		rte_bbdev_log(ERR,
1588984b7306SHernan Vargas 				"BG (%u) is out of range 1 <= value <= 2",
158911b0a112SNicolas Chautru 				ldpc_enc->basegraph);
159011b0a112SNicolas Chautru 		return -1;
159111b0a112SNicolas Chautru 	}
1592984b7306SHernan Vargas 	if (ldpc_enc->rv_index > 3) {
1593984b7306SHernan Vargas 		rte_bbdev_log(ERR,
1594984b7306SHernan Vargas 				"rv_index (%u) is out of range 0 <= value <= 3",
1595984b7306SHernan Vargas 				ldpc_enc->rv_index);
1596984b7306SHernan Vargas 		return -1;
1597984b7306SHernan Vargas 	}
159848fc315fSNicolas Chautru 	if (ldpc_enc->code_block_mode > RTE_BBDEV_CODE_BLOCK) {
159911b0a112SNicolas Chautru 		rte_bbdev_log(ERR,
1600984b7306SHernan Vargas 				"code_block_mode (%u) is out of range 0 <= value <= 1",
160111b0a112SNicolas Chautru 				ldpc_enc->code_block_mode);
160211b0a112SNicolas Chautru 		return -1;
160311b0a112SNicolas Chautru 	}
160411b0a112SNicolas Chautru 
1605984b7306SHernan Vargas 	if (ldpc_enc->input.length >
1606984b7306SHernan Vargas 		RTE_BBDEV_LDPC_MAX_CB_SIZE >> 3) {
1607984b7306SHernan Vargas 		rte_bbdev_log(ERR, "CB size (%u) is too big, max: %d",
1608984b7306SHernan Vargas 				ldpc_enc->input.length,
1609984b7306SHernan Vargas 				RTE_BBDEV_LDPC_MAX_CB_SIZE);
1610984b7306SHernan Vargas 		return -1;
1611984b7306SHernan Vargas 	}
1612c750d277SHernan Vargas 
1613c750d277SHernan Vargas 	z_c = ldpc_enc->z_c;
1614984b7306SHernan Vargas 	/* Check Zc is valid value */
1615984b7306SHernan Vargas 	if ((z_c > 384) || (z_c < 4)) {
1616984b7306SHernan Vargas 		rte_bbdev_log(ERR, "Zc (%u) is out of range", z_c);
1617984b7306SHernan Vargas 		return -1;
1618984b7306SHernan Vargas 	}
1619984b7306SHernan Vargas 	if (z_c > 256) {
1620984b7306SHernan Vargas 		if ((z_c % 32) != 0) {
1621984b7306SHernan Vargas 			rte_bbdev_log(ERR, "Invalid Zc %d", z_c);
1622984b7306SHernan Vargas 			return -1;
1623984b7306SHernan Vargas 		}
1624984b7306SHernan Vargas 	} else if (z_c > 128) {
1625984b7306SHernan Vargas 		if ((z_c % 16) != 0) {
1626984b7306SHernan Vargas 			rte_bbdev_log(ERR, "Invalid Zc %d", z_c);
1627984b7306SHernan Vargas 			return -1;
1628984b7306SHernan Vargas 		}
1629984b7306SHernan Vargas 	} else if (z_c > 64) {
1630984b7306SHernan Vargas 		if ((z_c % 8) != 0) {
1631984b7306SHernan Vargas 			rte_bbdev_log(ERR, "Invalid Zc %d", z_c);
1632984b7306SHernan Vargas 			return -1;
1633984b7306SHernan Vargas 		}
1634984b7306SHernan Vargas 	} else if (z_c > 32) {
1635984b7306SHernan Vargas 		if ((z_c % 4) != 0) {
1636984b7306SHernan Vargas 			rte_bbdev_log(ERR, "Invalid Zc %d", z_c);
1637984b7306SHernan Vargas 			return -1;
1638984b7306SHernan Vargas 		}
1639984b7306SHernan Vargas 	} else if (z_c > 16) {
1640984b7306SHernan Vargas 		if ((z_c % 2) != 0) {
1641984b7306SHernan Vargas 			rte_bbdev_log(ERR, "Invalid Zc %d", z_c);
1642984b7306SHernan Vargas 			return -1;
1643984b7306SHernan Vargas 		}
1644984b7306SHernan Vargas 	}
1645984b7306SHernan Vargas 
1646c750d277SHernan Vargas 	n_filler = ldpc_enc->n_filler;
1647c750d277SHernan Vargas 	K = (ldpc_enc->basegraph == 1 ? 22 : 10) * ldpc_enc->z_c;
1648c750d277SHernan Vargas 	Kp = K - n_filler;
1649c750d277SHernan Vargas 	q_m = ldpc_enc->q_m;
1650c750d277SHernan Vargas 	n_cb = ldpc_enc->n_cb;
1651c750d277SHernan Vargas 	N = (ldpc_enc->basegraph == 1 ? N_ZC_1 : N_ZC_2) * z_c;
1652c750d277SHernan Vargas 	k0 = get_k0(n_cb, z_c, ldpc_enc->basegraph, ldpc_enc->rv_index);
1653c750d277SHernan Vargas 	crc24 = 0;
1654c750d277SHernan Vargas 	e = ldpc_enc->cb_params.e;
1655c750d277SHernan Vargas 
1656c750d277SHernan Vargas 	if (check_bit(op->ldpc_enc.op_flags, RTE_BBDEV_LDPC_CRC_24B_ATTACH))
1657984b7306SHernan Vargas 		crc24 = 24;
1658984b7306SHernan Vargas 
1659984b7306SHernan Vargas 	if (K < (int) (ldpc_enc->input.length * 8 + n_filler) + crc24) {
1660984b7306SHernan Vargas 		rte_bbdev_log(ERR, "K and F not matching input size %u %u %u",
1661984b7306SHernan Vargas 				K, n_filler, ldpc_enc->input.length);
1662984b7306SHernan Vargas 		return -1;
1663984b7306SHernan Vargas 	}
166448fc315fSNicolas Chautru 	if (ldpc_enc->code_block_mode == RTE_BBDEV_TRANSPORT_BLOCK) {
1665984b7306SHernan Vargas 		rte_bbdev_log(ERR, "TB mode not supported");
1666984b7306SHernan Vargas 		return -1;
1667984b7306SHernan Vargas 
1668984b7306SHernan Vargas 	}
1669984b7306SHernan Vargas 
1670984b7306SHernan Vargas 	/* K' range check */
1671984b7306SHernan Vargas 	if (Kp % 8 > 0) {
1672984b7306SHernan Vargas 		rte_bbdev_log(ERR, "K' not byte aligned %u", Kp);
167311b0a112SNicolas Chautru 		return -1;
167411b0a112SNicolas Chautru 	}
1675984b7306SHernan Vargas 	if ((crc24 > 0) && (Kp < 292)) {
1676984b7306SHernan Vargas 		rte_bbdev_log(ERR, "Invalid CRC24 for small block %u", Kp);
167711b0a112SNicolas Chautru 		return -1;
167811b0a112SNicolas Chautru 	}
1679984b7306SHernan Vargas 	if (Kp < 24) {
1680984b7306SHernan Vargas 		rte_bbdev_log(ERR, "K' too small %u", Kp);
168111b0a112SNicolas Chautru 		return -1;
168211b0a112SNicolas Chautru 	}
1683984b7306SHernan Vargas 	if (n_filler >= (K - 2 * z_c)) {
1684984b7306SHernan Vargas 		rte_bbdev_log(ERR, "K - F invalid %u %u", K, n_filler);
168511b0a112SNicolas Chautru 		return -1;
168611b0a112SNicolas Chautru 	}
1687984b7306SHernan Vargas 	/* Ncb range check */
1688984b7306SHernan Vargas 	if ((n_cb > N) || (n_cb < 32) || (n_cb <= (Kp - crc24))) {
1689984b7306SHernan Vargas 		rte_bbdev_log(ERR, "Ncb (%u) is out of range K  %d N %d", n_cb, K, N);
169011b0a112SNicolas Chautru 		return -1;
169111b0a112SNicolas Chautru 	}
1692984b7306SHernan Vargas 	/* Qm range check */
1693984b7306SHernan Vargas 	if (!check_bit(op->ldpc_enc.op_flags, RTE_BBDEV_LDPC_INTERLEAVER_BYPASS) &&
1694984b7306SHernan Vargas 			((q_m == 0) || ((q_m > 2) && ((q_m % 2) == 1)) || (q_m > 8))) {
1695984b7306SHernan Vargas 		rte_bbdev_log(ERR, "Qm (%u) is out of range", q_m);
1696984b7306SHernan Vargas 		return -1;
1697984b7306SHernan Vargas 	}
1698984b7306SHernan Vargas 	/* K0 range check */
1699c750d277SHernan Vargas 	if (((k0 % z_c) > 0) || (k0 >= n_cb) || ((k0 >= (Kp - 2 * z_c)) && (k0 < (K - 2 * z_c)))) {
1700984b7306SHernan Vargas 		rte_bbdev_log(ERR, "K0 (%u) is out of range", k0);
1701984b7306SHernan Vargas 		return -1;
1702984b7306SHernan Vargas 	}
1703984b7306SHernan Vargas 	/* E range check */
1704984b7306SHernan Vargas 	if (e <= RTE_MAX(32, z_c)) {
1705984b7306SHernan Vargas 		rte_bbdev_log(ERR, "E is too small %"PRIu32"", e);
1706984b7306SHernan Vargas 		return -1;
1707984b7306SHernan Vargas 	}
1708984b7306SHernan Vargas 	if ((e > 0xFFFF)) {
1709984b7306SHernan Vargas 		rte_bbdev_log(ERR, "E is too large for N3000 %"PRIu32" > 64k", e);
1710984b7306SHernan Vargas 		return -1;
1711984b7306SHernan Vargas 	}
1712984b7306SHernan Vargas 	if (q_m > 0) {
1713984b7306SHernan Vargas 		if (e % q_m > 0) {
1714984b7306SHernan Vargas 			rte_bbdev_log(ERR, "E %"PRIu32" not multiple of qm %d", e, q_m);
1715984b7306SHernan Vargas 			return -1;
1716984b7306SHernan Vargas 		}
1717984b7306SHernan Vargas 	}
1718984b7306SHernan Vargas 	/* Code word in RM range check */
1719984b7306SHernan Vargas 	if (k0 > (Kp - 2 * z_c))
1720984b7306SHernan Vargas 		L = k0 + e;
1721984b7306SHernan Vargas 	else
1722984b7306SHernan Vargas 		L = k0 + e + n_filler;
1723984b7306SHernan Vargas 	Lcb = RTE_MIN(L, n_cb);
1724984b7306SHernan Vargas 	if (ldpc_enc->basegraph == 1) {
1725984b7306SHernan Vargas 		if (Lcb <= 25 * z_c)
1726984b7306SHernan Vargas 			cw = 25 * z_c;
1727984b7306SHernan Vargas 		else if (Lcb <= 27 * z_c)
1728984b7306SHernan Vargas 			cw = 27 * z_c;
1729984b7306SHernan Vargas 		else if (Lcb <= 30 * z_c)
1730984b7306SHernan Vargas 			cw = 30 * z_c;
1731984b7306SHernan Vargas 		else if (Lcb <= 33 * z_c)
1732984b7306SHernan Vargas 			cw = 33 * z_c;
1733984b7306SHernan Vargas 		else if (Lcb <= 44 * z_c)
1734984b7306SHernan Vargas 			cw = 44 * z_c;
1735984b7306SHernan Vargas 		else if (Lcb <= 55 * z_c)
1736984b7306SHernan Vargas 			cw = 55 * z_c;
1737984b7306SHernan Vargas 		else
1738984b7306SHernan Vargas 			cw = 66 * z_c;
173911b0a112SNicolas Chautru 	} else {
1740984b7306SHernan Vargas 		if (Lcb <= 15 * z_c)
1741984b7306SHernan Vargas 			cw = 15 * z_c;
1742984b7306SHernan Vargas 		else if (Lcb <= 20 * z_c)
1743984b7306SHernan Vargas 			cw = 20 * z_c;
1744984b7306SHernan Vargas 		else if (Lcb <= 25 * z_c)
1745984b7306SHernan Vargas 			cw = 25 * z_c;
1746984b7306SHernan Vargas 		else if (Lcb <= 30 * z_c)
1747984b7306SHernan Vargas 			cw = 30 * z_c;
1748984b7306SHernan Vargas 		else
1749984b7306SHernan Vargas 			cw = 50 * z_c;
175011b0a112SNicolas Chautru 	}
1751984b7306SHernan Vargas 	if (n_cb < Kp - 2 * z_c)
1752984b7306SHernan Vargas 		cw_rm = n_cb;
1753984b7306SHernan Vargas 	else if ((Kp - 2 * z_c <= n_cb) && (n_cb < K - 2 * z_c))
1754984b7306SHernan Vargas 		cw_rm = Kp - 2 * z_c;
1755984b7306SHernan Vargas 	else if ((K - 2 * z_c <= n_cb) && (n_cb < cw))
1756984b7306SHernan Vargas 		cw_rm = n_cb - n_filler;
1757984b7306SHernan Vargas 	else
1758984b7306SHernan Vargas 		cw_rm = cw - n_filler;
1759984b7306SHernan Vargas 	if (cw_rm <= 32) {
1760c750d277SHernan Vargas 		rte_bbdev_log(ERR, "Invalid Ratematching");
1761984b7306SHernan Vargas 		return -1;
176211b0a112SNicolas Chautru 	}
176311b0a112SNicolas Chautru 	return 0;
176411b0a112SNicolas Chautru }
1765984b7306SHernan Vargas 
1766c750d277SHernan Vargas /* Validates LDPC decoder parameters for VC 5GNR FPGA. */
1767984b7306SHernan Vargas static inline int
1768c750d277SHernan Vargas vc_5gnr_validate_ldpc_dec_op(struct rte_bbdev_dec_op *op)
1769984b7306SHernan Vargas {
1770984b7306SHernan Vargas 	struct rte_bbdev_op_ldpc_dec *ldpc_dec = &op->ldpc_dec;
1771c750d277SHernan Vargas 	int z_c, n_filler, K, Kp, q_m, n_cb, N, k0, crc24;
1772c750d277SHernan Vargas 	int32_t L, Lcb, cw, cw_rm, e;
1773c750d277SHernan Vargas 
1774c750d277SHernan Vargas 	if (check_bit(ldpc_dec->op_flags, RTE_BBDEV_LDPC_INTERNAL_HARQ_MEMORY_LOOPBACK))
1775984b7306SHernan Vargas 		return 0;
1776984b7306SHernan Vargas 	if (ldpc_dec->input.data == NULL) {
1777984b7306SHernan Vargas 		rte_bbdev_log(ERR, "Invalid input pointer");
1778984b7306SHernan Vargas 		return -1;
1779984b7306SHernan Vargas 	}
1780984b7306SHernan Vargas 	if (ldpc_dec->hard_output.data == NULL) {
1781984b7306SHernan Vargas 		rte_bbdev_log(ERR, "Invalid output pointer");
1782984b7306SHernan Vargas 		return -1;
1783984b7306SHernan Vargas 	}
1784984b7306SHernan Vargas 	if (ldpc_dec->input.length == 0) {
1785984b7306SHernan Vargas 		rte_bbdev_log(ERR, "input is null");
1786984b7306SHernan Vargas 		return -1;
1787984b7306SHernan Vargas 	}
1788984b7306SHernan Vargas 	if ((ldpc_dec->basegraph > 2) || (ldpc_dec->basegraph == 0)) {
1789984b7306SHernan Vargas 		rte_bbdev_log(ERR,
1790984b7306SHernan Vargas 				"BG (%u) is out of range 1 <= value <= 2",
1791984b7306SHernan Vargas 				ldpc_dec->basegraph);
1792984b7306SHernan Vargas 		return -1;
1793984b7306SHernan Vargas 	}
1794984b7306SHernan Vargas 	if (ldpc_dec->iter_max == 0) {
1795984b7306SHernan Vargas 		rte_bbdev_log(ERR,
1796984b7306SHernan Vargas 				"iter_max (%u) is equal to 0",
1797984b7306SHernan Vargas 				ldpc_dec->iter_max);
1798984b7306SHernan Vargas 		return -1;
1799984b7306SHernan Vargas 	}
1800984b7306SHernan Vargas 	if (ldpc_dec->rv_index > 3) {
1801984b7306SHernan Vargas 		rte_bbdev_log(ERR,
1802984b7306SHernan Vargas 				"rv_index (%u) is out of range 0 <= value <= 3",
1803984b7306SHernan Vargas 				ldpc_dec->rv_index);
1804984b7306SHernan Vargas 		return -1;
1805984b7306SHernan Vargas 	}
1806984b7306SHernan Vargas 	if (ldpc_dec->code_block_mode > RTE_BBDEV_CODE_BLOCK) {
1807984b7306SHernan Vargas 		rte_bbdev_log(ERR,
1808984b7306SHernan Vargas 				"code_block_mode (%u) is out of range 0 <= value <= 1",
1809984b7306SHernan Vargas 				ldpc_dec->code_block_mode);
1810984b7306SHernan Vargas 		return -1;
1811984b7306SHernan Vargas 	}
1812c750d277SHernan Vargas 	if (check_bit(op->ldpc_dec.op_flags, RTE_BBDEV_LDPC_DECODE_BYPASS)) {
1813984b7306SHernan Vargas 		rte_bbdev_log(ERR, "Avoid LDPC Decode bypass");
1814984b7306SHernan Vargas 		return -1;
1815984b7306SHernan Vargas 	}
1816c750d277SHernan Vargas 
1817c750d277SHernan Vargas 	z_c = ldpc_dec->z_c;
1818984b7306SHernan Vargas 	/* Check Zc is valid value */
1819984b7306SHernan Vargas 	if ((z_c > 384) || (z_c < 4)) {
1820c750d277SHernan Vargas 		rte_bbdev_log(ERR, "Zc (%u) is out of range", z_c);
1821984b7306SHernan Vargas 		return -1;
1822984b7306SHernan Vargas 	}
1823984b7306SHernan Vargas 	if (z_c > 256) {
1824984b7306SHernan Vargas 		if ((z_c % 32) != 0) {
1825984b7306SHernan Vargas 			rte_bbdev_log(ERR, "Invalid Zc %d", z_c);
1826984b7306SHernan Vargas 			return -1;
1827984b7306SHernan Vargas 		}
1828984b7306SHernan Vargas 	} else if (z_c > 128) {
1829984b7306SHernan Vargas 		if ((z_c % 16) != 0) {
1830984b7306SHernan Vargas 			rte_bbdev_log(ERR, "Invalid Zc %d", z_c);
1831984b7306SHernan Vargas 			return -1;
1832984b7306SHernan Vargas 		}
1833984b7306SHernan Vargas 	} else if (z_c > 64) {
1834984b7306SHernan Vargas 		if ((z_c % 8) != 0) {
1835984b7306SHernan Vargas 			rte_bbdev_log(ERR, "Invalid Zc %d", z_c);
1836984b7306SHernan Vargas 			return -1;
1837984b7306SHernan Vargas 		}
1838984b7306SHernan Vargas 	} else if (z_c > 32) {
1839984b7306SHernan Vargas 		if ((z_c % 4) != 0) {
1840984b7306SHernan Vargas 			rte_bbdev_log(ERR, "Invalid Zc %d", z_c);
1841984b7306SHernan Vargas 			return -1;
1842984b7306SHernan Vargas 		}
1843984b7306SHernan Vargas 	} else if (z_c > 16) {
1844984b7306SHernan Vargas 		if ((z_c % 2) != 0) {
1845984b7306SHernan Vargas 			rte_bbdev_log(ERR, "Invalid Zc %d", z_c);
1846984b7306SHernan Vargas 			return -1;
1847984b7306SHernan Vargas 		}
1848984b7306SHernan Vargas 	}
1849984b7306SHernan Vargas 
1850c750d277SHernan Vargas 	n_filler = ldpc_dec->n_filler;
1851c750d277SHernan Vargas 	K = (ldpc_dec->basegraph == 1 ? 22 : 10) * ldpc_dec->z_c;
1852c750d277SHernan Vargas 	Kp = K - n_filler;
1853c750d277SHernan Vargas 	q_m = ldpc_dec->q_m;
1854c750d277SHernan Vargas 	n_cb = ldpc_dec->n_cb;
1855c750d277SHernan Vargas 	N = (ldpc_dec->basegraph == 1 ? N_ZC_1 : N_ZC_2) * z_c;
1856c750d277SHernan Vargas 	k0 = get_k0(n_cb, z_c, ldpc_dec->basegraph, ldpc_dec->rv_index);
1857c750d277SHernan Vargas 	crc24 = 0;
1858c750d277SHernan Vargas 	e = ldpc_dec->cb_params.e;
1859c750d277SHernan Vargas 
1860c750d277SHernan Vargas 	if (check_bit(op->ldpc_dec.op_flags, RTE_BBDEV_LDPC_CRC_TYPE_24B_CHECK))
1861984b7306SHernan Vargas 		crc24 = 24;
1862984b7306SHernan Vargas 
1863984b7306SHernan Vargas 	if (ldpc_dec->code_block_mode == RTE_BBDEV_TRANSPORT_BLOCK) {
1864c750d277SHernan Vargas 		rte_bbdev_log(ERR, "TB mode not supported");
1865984b7306SHernan Vargas 		return -1;
1866984b7306SHernan Vargas 	}
1867984b7306SHernan Vargas 	/* Enforce HARQ input length */
1868984b7306SHernan Vargas 	ldpc_dec->harq_combined_input.length = RTE_MIN((uint32_t) n_cb,
1869984b7306SHernan Vargas 			ldpc_dec->harq_combined_input.length);
1870984b7306SHernan Vargas 	if ((ldpc_dec->harq_combined_input.length == 0) &&
1871984b7306SHernan Vargas 			check_bit(ldpc_dec->op_flags,
1872984b7306SHernan Vargas 			RTE_BBDEV_LDPC_HQ_COMBINE_IN_ENABLE)) {
1873984b7306SHernan Vargas 		rte_bbdev_log(ERR,
1874984b7306SHernan Vargas 				"HARQ input length (%u) should not be null",
1875984b7306SHernan Vargas 				ldpc_dec->harq_combined_input.length);
1876984b7306SHernan Vargas 		return -1;
1877984b7306SHernan Vargas 	}
1878984b7306SHernan Vargas 	if ((ldpc_dec->harq_combined_input.length > 0) &&
1879984b7306SHernan Vargas 			!check_bit(ldpc_dec->op_flags,
1880984b7306SHernan Vargas 			RTE_BBDEV_LDPC_HQ_COMBINE_IN_ENABLE)) {
1881984b7306SHernan Vargas 		ldpc_dec->harq_combined_input.length = 0;
1882984b7306SHernan Vargas 	}
1883984b7306SHernan Vargas 
1884984b7306SHernan Vargas 	/* K' range check */
1885984b7306SHernan Vargas 	if (Kp % 8 > 0) {
1886c750d277SHernan Vargas 		rte_bbdev_log(ERR, "K' not byte aligned %u", Kp);
1887984b7306SHernan Vargas 		return -1;
1888984b7306SHernan Vargas 	}
1889984b7306SHernan Vargas 	if ((crc24 > 0) && (Kp < 292)) {
1890c750d277SHernan Vargas 		rte_bbdev_log(ERR, "Invalid CRC24 for small block %u", Kp);
1891984b7306SHernan Vargas 		return -1;
1892984b7306SHernan Vargas 	}
1893984b7306SHernan Vargas 	if (Kp < 24) {
1894c750d277SHernan Vargas 		rte_bbdev_log(ERR, "K' too small %u", Kp);
1895984b7306SHernan Vargas 		return -1;
1896984b7306SHernan Vargas 	}
1897984b7306SHernan Vargas 	if (n_filler >= (K - 2 * z_c)) {
1898c750d277SHernan Vargas 		rte_bbdev_log(ERR, "K - F invalid %u %u", K, n_filler);
1899984b7306SHernan Vargas 		return -1;
1900984b7306SHernan Vargas 	}
1901984b7306SHernan Vargas 	/* Ncb range check */
1902984b7306SHernan Vargas 	if (n_cb != N) {
1903c750d277SHernan Vargas 		rte_bbdev_log(ERR, "Ncb (%u) is out of range K  %d N %d", n_cb, K, N);
1904984b7306SHernan Vargas 		return -1;
1905984b7306SHernan Vargas 	}
1906984b7306SHernan Vargas 	/* Qm range check */
1907984b7306SHernan Vargas 	if (!check_bit(op->ldpc_dec.op_flags,
1908984b7306SHernan Vargas 			RTE_BBDEV_LDPC_INTERLEAVER_BYPASS) &&
1909984b7306SHernan Vargas 			((q_m == 0) || ((q_m > 2) && ((q_m % 2) == 1))
1910984b7306SHernan Vargas 			|| (q_m > 8))) {
1911c750d277SHernan Vargas 		rte_bbdev_log(ERR, "Qm (%u) is out of range", q_m);
1912984b7306SHernan Vargas 		return -1;
1913984b7306SHernan Vargas 	}
1914984b7306SHernan Vargas 	/* K0 range check */
1915c750d277SHernan Vargas 	if (((k0 % z_c) > 0) || (k0 >= n_cb) || ((k0 >= (Kp - 2 * z_c)) && (k0 < (K - 2 * z_c)))) {
1916c750d277SHernan Vargas 		rte_bbdev_log(ERR, "K0 (%u) is out of range", k0);
1917984b7306SHernan Vargas 		return -1;
1918984b7306SHernan Vargas 	}
1919984b7306SHernan Vargas 	/* E range check */
1920984b7306SHernan Vargas 	if (e <= RTE_MAX(32, z_c)) {
1921c750d277SHernan Vargas 		rte_bbdev_log(ERR, "E is too small");
1922984b7306SHernan Vargas 		return -1;
1923984b7306SHernan Vargas 	}
1924984b7306SHernan Vargas 	if ((e > 0xFFFF)) {
1925c750d277SHernan Vargas 		rte_bbdev_log(ERR, "E is too large");
1926984b7306SHernan Vargas 		return -1;
1927984b7306SHernan Vargas 	}
1928984b7306SHernan Vargas 	if (q_m > 0) {
1929984b7306SHernan Vargas 		if (e % q_m > 0) {
1930c750d277SHernan Vargas 			rte_bbdev_log(ERR, "E not multiple of qm %d", q_m);
1931984b7306SHernan Vargas 			return -1;
1932984b7306SHernan Vargas 		}
1933984b7306SHernan Vargas 	}
1934984b7306SHernan Vargas 	/* Code word in RM range check */
1935984b7306SHernan Vargas 	if (k0 > (Kp - 2 * z_c))
1936984b7306SHernan Vargas 		L = k0 + e;
1937984b7306SHernan Vargas 	else
1938984b7306SHernan Vargas 		L = k0 + e + n_filler;
1939c750d277SHernan Vargas 
1940c750d277SHernan Vargas 	Lcb = RTE_MIN(n_cb, RTE_MAX(L, (int32_t) ldpc_dec->harq_combined_input.length));
1941984b7306SHernan Vargas 	if (ldpc_dec->basegraph == 1) {
1942984b7306SHernan Vargas 		if (Lcb <= 25 * z_c)
1943984b7306SHernan Vargas 			cw = 25 * z_c;
1944984b7306SHernan Vargas 		else if (Lcb <= 27 * z_c)
1945984b7306SHernan Vargas 			cw = 27 * z_c;
1946984b7306SHernan Vargas 		else if (Lcb <= 30 * z_c)
1947984b7306SHernan Vargas 			cw = 30 * z_c;
1948984b7306SHernan Vargas 		else if (Lcb <= 33 * z_c)
1949984b7306SHernan Vargas 			cw = 33 * z_c;
1950984b7306SHernan Vargas 		else if (Lcb <= 44 * z_c)
1951984b7306SHernan Vargas 			cw = 44 * z_c;
1952984b7306SHernan Vargas 		else if (Lcb <= 55 * z_c)
1953984b7306SHernan Vargas 			cw = 55 * z_c;
1954984b7306SHernan Vargas 		else
1955984b7306SHernan Vargas 			cw = 66 * z_c;
1956984b7306SHernan Vargas 	} else {
1957984b7306SHernan Vargas 		if (Lcb <= 15 * z_c)
1958984b7306SHernan Vargas 			cw = 15 * z_c;
1959984b7306SHernan Vargas 		else if (Lcb <= 20 * z_c)
1960984b7306SHernan Vargas 			cw = 20 * z_c;
1961984b7306SHernan Vargas 		else if (Lcb <= 25 * z_c)
1962984b7306SHernan Vargas 			cw = 25 * z_c;
1963984b7306SHernan Vargas 		else if (Lcb <= 30 * z_c)
1964984b7306SHernan Vargas 			cw = 30 * z_c;
1965984b7306SHernan Vargas 		else
1966984b7306SHernan Vargas 			cw = 50 * z_c;
1967984b7306SHernan Vargas 	}
1968984b7306SHernan Vargas 	cw_rm = cw - n_filler;
1969984b7306SHernan Vargas 	if (cw_rm <= 32) {
1970c750d277SHernan Vargas 		rte_bbdev_log(ERR, "Invalid Ratematching");
1971984b7306SHernan Vargas 		return -1;
1972984b7306SHernan Vargas 	}
1973984b7306SHernan Vargas 	return 0;
1974984b7306SHernan Vargas }
197511b0a112SNicolas Chautru 
197644dc6faaSNicolas Chautru static inline char *
197744dc6faaSNicolas Chautru mbuf_append(struct rte_mbuf *m_head, struct rte_mbuf *m, uint16_t len)
197844dc6faaSNicolas Chautru {
197944dc6faaSNicolas Chautru 	if (unlikely(len > rte_pktmbuf_tailroom(m)))
198044dc6faaSNicolas Chautru 		return NULL;
198144dc6faaSNicolas Chautru 
198244dc6faaSNicolas Chautru 	char *tail = (char *)m->buf_addr + m->data_off + m->data_len;
198344dc6faaSNicolas Chautru 	m->data_len = (uint16_t)(m->data_len + len);
198444dc6faaSNicolas Chautru 	m_head->pkt_len  = (m_head->pkt_len + len);
198544dc6faaSNicolas Chautru 	return tail;
198644dc6faaSNicolas Chautru }
198744dc6faaSNicolas Chautru 
1988b3d326e4SHernan Vargas static inline void
198910829ff2SHernan Vargas fpga_5gnr_mutex_acquisition(struct fpga_5gnr_queue *q)
1990b3d326e4SHernan Vargas {
1991b3d326e4SHernan Vargas 	uint32_t mutex_ctrl, mutex_read, cnt = 0;
1992b3d326e4SHernan Vargas 	/* Assign a unique id for the duration of the DDR access */
1993dd329b2cSStephen Hemminger 	q->ddr_mutex_uuid = rte_rand();
1994b3d326e4SHernan Vargas 	/* Request and wait for acquisition of the mutex */
1995b3d326e4SHernan Vargas 	mutex_ctrl = (q->ddr_mutex_uuid << 16) + 1;
1996b3d326e4SHernan Vargas 	do {
1997b3d326e4SHernan Vargas 		if (cnt > 0)
199810829ff2SHernan Vargas 			usleep(FPGA_5GNR_TIMEOUT_CHECK_INTERVAL);
1999f665790aSDavid Marchand 		rte_bbdev_log_debug("Acquiring Mutex for %x", q->ddr_mutex_uuid);
200010829ff2SHernan Vargas 		fpga_5gnr_reg_write_32(q->d->mmio_base, FPGA_5GNR_FEC_MUTEX, mutex_ctrl);
200110829ff2SHernan Vargas 		mutex_read = fpga_5gnr_reg_read_32(q->d->mmio_base, FPGA_5GNR_FEC_MUTEX);
2002f665790aSDavid Marchand 		rte_bbdev_log_debug("Mutex %x cnt %d owner %x",
2003b3d326e4SHernan Vargas 				mutex_read, cnt, q->ddr_mutex_uuid);
2004b3d326e4SHernan Vargas 		cnt++;
2005b3d326e4SHernan Vargas 	} while ((mutex_read >> 16) != q->ddr_mutex_uuid);
2006b3d326e4SHernan Vargas }
2007b3d326e4SHernan Vargas 
2008b3d326e4SHernan Vargas static inline void
200910829ff2SHernan Vargas fpga_5gnr_mutex_free(struct fpga_5gnr_queue *q)
2010b3d326e4SHernan Vargas {
2011b3d326e4SHernan Vargas 	uint32_t mutex_ctrl = q->ddr_mutex_uuid << 16;
201210829ff2SHernan Vargas 	fpga_5gnr_reg_write_32(q->d->mmio_base, FPGA_5GNR_FEC_MUTEX, mutex_ctrl);
2013b3d326e4SHernan Vargas }
2014b3d326e4SHernan Vargas 
201544dc6faaSNicolas Chautru static inline int
201610829ff2SHernan Vargas fpga_5gnr_harq_write_loopback(struct fpga_5gnr_queue *q,
20174d9199e3SNicolas Chautru 		struct rte_mbuf *harq_input, uint16_t harq_in_length,
20184d9199e3SNicolas Chautru 		uint32_t harq_in_offset, uint32_t harq_out_offset)
20194d9199e3SNicolas Chautru {
202010829ff2SHernan Vargas 	fpga_5gnr_mutex_acquisition(q);
20214d9199e3SNicolas Chautru 	uint32_t out_offset = harq_out_offset;
20224d9199e3SNicolas Chautru 	uint32_t in_offset = harq_in_offset;
20234d9199e3SNicolas Chautru 	uint32_t left_length = harq_in_length;
20244d9199e3SNicolas Chautru 	uint32_t reg_32, increment = 0;
20254d9199e3SNicolas Chautru 	uint64_t *input = NULL;
202610829ff2SHernan Vargas 	uint32_t last_transaction = left_length % FPGA_5GNR_DDR_WR_DATA_LEN_IN_BYTES;
20274d9199e3SNicolas Chautru 	uint64_t last_word;
20289e3ffd38SHernan Vargas 	struct fpga_5gnr_fec_device *d = q->d;
20294d9199e3SNicolas Chautru 
20304d9199e3SNicolas Chautru 	if (last_transaction > 0)
20314d9199e3SNicolas Chautru 		left_length -= last_transaction;
20329e3ffd38SHernan Vargas 	if (d->fpga_variant == VC_5GNR_FPGA_VARIANT) {
20334d9199e3SNicolas Chautru 		/*
20344d9199e3SNicolas Chautru 		 * Get HARQ buffer size for each VF/PF: When 0x00, there is no
20354d9199e3SNicolas Chautru 		 * available DDR space for the corresponding VF/PF.
20364d9199e3SNicolas Chautru 		 */
203710829ff2SHernan Vargas 		reg_32 = fpga_5gnr_reg_read_32(q->d->mmio_base, FPGA_5GNR_FEC_HARQ_BUF_SIZE_REGS);
20384d9199e3SNicolas Chautru 		if (reg_32 < harq_in_length) {
20394d9199e3SNicolas Chautru 			left_length = reg_32;
2040f665790aSDavid Marchand 			rte_bbdev_log(ERR, "HARQ in length > HARQ buffer size");
20414d9199e3SNicolas Chautru 		}
20429e3ffd38SHernan Vargas 	}
20434d9199e3SNicolas Chautru 
20443f9eab14SStephen Hemminger 	input = rte_pktmbuf_mtod_offset(harq_input, uint64_t *, in_offset);
20454d9199e3SNicolas Chautru 
20464d9199e3SNicolas Chautru 	while (left_length > 0) {
204710829ff2SHernan Vargas 		if (fpga_5gnr_reg_read_8(q->d->mmio_base, FPGA_5GNR_FEC_DDR4_ADDR_RDY_REGS) ==  1) {
20489e3ffd38SHernan Vargas 			if (d->fpga_variant == AGX100_FPGA_VARIANT) {
20499e3ffd38SHernan Vargas 				fpga_5gnr_reg_write_32(q->d->mmio_base,
20509e3ffd38SHernan Vargas 						FPGA_5GNR_FEC_DDR4_WR_ADDR_REGS,
20519e3ffd38SHernan Vargas 						out_offset >> 3);
20529e3ffd38SHernan Vargas 			} else {
205310829ff2SHernan Vargas 				fpga_5gnr_reg_write_32(q->d->mmio_base,
20544d9199e3SNicolas Chautru 						FPGA_5GNR_FEC_DDR4_WR_ADDR_REGS,
20554d9199e3SNicolas Chautru 						out_offset);
20569e3ffd38SHernan Vargas 			}
205710829ff2SHernan Vargas 			fpga_5gnr_reg_write_64(q->d->mmio_base,
20584d9199e3SNicolas Chautru 					FPGA_5GNR_FEC_DDR4_WR_DATA_REGS,
20594d9199e3SNicolas Chautru 					input[increment]);
206010829ff2SHernan Vargas 			left_length -= FPGA_5GNR_DDR_WR_DATA_LEN_IN_BYTES;
206110829ff2SHernan Vargas 			out_offset += FPGA_5GNR_DDR_WR_DATA_LEN_IN_BYTES;
20624d9199e3SNicolas Chautru 			increment++;
206310829ff2SHernan Vargas 			fpga_5gnr_reg_write_8(q->d->mmio_base, FPGA_5GNR_FEC_DDR4_WR_DONE_REGS, 1);
20644d9199e3SNicolas Chautru 		}
20654d9199e3SNicolas Chautru 	}
20664d9199e3SNicolas Chautru 	while (last_transaction > 0) {
206710829ff2SHernan Vargas 		if (fpga_5gnr_reg_read_8(q->d->mmio_base, FPGA_5GNR_FEC_DDR4_ADDR_RDY_REGS) ==  1) {
20689e3ffd38SHernan Vargas 			if (d->fpga_variant == AGX100_FPGA_VARIANT) {
20699e3ffd38SHernan Vargas 				fpga_5gnr_reg_write_32(q->d->mmio_base,
20709e3ffd38SHernan Vargas 						FPGA_5GNR_FEC_DDR4_WR_ADDR_REGS,
20719e3ffd38SHernan Vargas 						out_offset >> 3);
20729e3ffd38SHernan Vargas 			} else {
207310829ff2SHernan Vargas 				fpga_5gnr_reg_write_32(q->d->mmio_base,
20744d9199e3SNicolas Chautru 						FPGA_5GNR_FEC_DDR4_WR_ADDR_REGS,
20754d9199e3SNicolas Chautru 						out_offset);
20769e3ffd38SHernan Vargas 			}
20774d9199e3SNicolas Chautru 			last_word = input[increment];
20789e3ffd38SHernan Vargas 			last_word &= (uint64_t)(1ULL << (last_transaction * 4)) - 1;
207910829ff2SHernan Vargas 			fpga_5gnr_reg_write_64(q->d->mmio_base,
20804d9199e3SNicolas Chautru 					FPGA_5GNR_FEC_DDR4_WR_DATA_REGS,
20814d9199e3SNicolas Chautru 					last_word);
208210829ff2SHernan Vargas 			fpga_5gnr_reg_write_8(q->d->mmio_base, FPGA_5GNR_FEC_DDR4_WR_DONE_REGS, 1);
20834d9199e3SNicolas Chautru 			last_transaction = 0;
20844d9199e3SNicolas Chautru 		}
20854d9199e3SNicolas Chautru 	}
208610829ff2SHernan Vargas 	fpga_5gnr_mutex_free(q);
20874d9199e3SNicolas Chautru 	return 1;
20884d9199e3SNicolas Chautru }
20894d9199e3SNicolas Chautru 
20904d9199e3SNicolas Chautru static inline int
209110829ff2SHernan Vargas fpga_5gnr_harq_read_loopback(struct fpga_5gnr_queue *q,
20924d9199e3SNicolas Chautru 		struct rte_mbuf *harq_output, uint16_t harq_in_length,
20934d9199e3SNicolas Chautru 		uint32_t harq_in_offset, uint32_t harq_out_offset)
20944d9199e3SNicolas Chautru {
209510829ff2SHernan Vargas 	fpga_5gnr_mutex_acquisition(q);
20964d9199e3SNicolas Chautru 	uint32_t left_length, in_offset = harq_in_offset;
20974d9199e3SNicolas Chautru 	uint64_t reg;
20984d9199e3SNicolas Chautru 	uint32_t increment = 0;
20994d9199e3SNicolas Chautru 	uint64_t *input = NULL;
210010829ff2SHernan Vargas 	uint32_t last_transaction = harq_in_length % FPGA_5GNR_DDR_WR_DATA_LEN_IN_BYTES;
21019e3ffd38SHernan Vargas 	struct fpga_5gnr_fec_device *d = q->d;
21024d9199e3SNicolas Chautru 
21034d9199e3SNicolas Chautru 	if (last_transaction > 0)
21044d9199e3SNicolas Chautru 		harq_in_length += (8 - last_transaction);
21054d9199e3SNicolas Chautru 
21069e3ffd38SHernan Vargas 	if (d->fpga_variant == VC_5GNR_FPGA_VARIANT) {
210710829ff2SHernan Vargas 		reg = fpga_5gnr_reg_read_32(q->d->mmio_base, FPGA_5GNR_FEC_HARQ_BUF_SIZE_REGS);
21084d9199e3SNicolas Chautru 		if (reg < harq_in_length) {
21094d9199e3SNicolas Chautru 			harq_in_length = reg;
2110f665790aSDavid Marchand 			rte_bbdev_log(ERR, "HARQ in length > HARQ buffer size");
21114d9199e3SNicolas Chautru 		}
21129e3ffd38SHernan Vargas 	}
21134d9199e3SNicolas Chautru 
21144d9199e3SNicolas Chautru 	if (!mbuf_append(harq_output, harq_output, harq_in_length)) {
2115f665790aSDavid Marchand 		rte_bbdev_log(ERR, "HARQ output buffer warning %d %d",
211610829ff2SHernan Vargas 				harq_output->buf_len - rte_pktmbuf_headroom(harq_output),
21174d9199e3SNicolas Chautru 				harq_in_length);
211810829ff2SHernan Vargas 		harq_in_length = harq_output->buf_len - rte_pktmbuf_headroom(harq_output);
21194d9199e3SNicolas Chautru 		if (!mbuf_append(harq_output, harq_output, harq_in_length)) {
2120f665790aSDavid Marchand 			rte_bbdev_log(ERR, "HARQ output buffer issue %d %d",
21214d9199e3SNicolas Chautru 					harq_output->buf_len, harq_in_length);
21224d9199e3SNicolas Chautru 			return -1;
21234d9199e3SNicolas Chautru 		}
21244d9199e3SNicolas Chautru 	}
21254d9199e3SNicolas Chautru 	left_length = harq_in_length;
21264d9199e3SNicolas Chautru 
21273f9eab14SStephen Hemminger 	input = rte_pktmbuf_mtod_offset(harq_output, uint64_t *, harq_out_offset);
21284d9199e3SNicolas Chautru 
21294d9199e3SNicolas Chautru 	while (left_length > 0) {
21309e3ffd38SHernan Vargas 		if (d->fpga_variant == AGX100_FPGA_VARIANT) {
21319e3ffd38SHernan Vargas 			fpga_5gnr_reg_write_32(q->d->mmio_base,
21329e3ffd38SHernan Vargas 					FPGA_5GNR_FEC_DDR4_RD_ADDR_REGS,
21339e3ffd38SHernan Vargas 					in_offset >> 3);
21349e3ffd38SHernan Vargas 		} else {
213510829ff2SHernan Vargas 			fpga_5gnr_reg_write_32(q->d->mmio_base,
213610829ff2SHernan Vargas 					FPGA_5GNR_FEC_DDR4_RD_ADDR_REGS,
213710829ff2SHernan Vargas 					in_offset);
21389e3ffd38SHernan Vargas 		}
213910829ff2SHernan Vargas 		fpga_5gnr_reg_write_8(q->d->mmio_base, FPGA_5GNR_FEC_DDR4_RD_DONE_REGS, 1);
214010829ff2SHernan Vargas 		reg = fpga_5gnr_reg_read_8(q->d->mmio_base, FPGA_5GNR_FEC_DDR4_RD_RDY_REGS);
21414d9199e3SNicolas Chautru 		while (reg != 1) {
214210829ff2SHernan Vargas 			reg = fpga_5gnr_reg_read_8(q->d->mmio_base, FPGA_5GNR_FEC_DDR4_RD_RDY_REGS);
214310829ff2SHernan Vargas 			if (reg == FPGA_5GNR_DDR_OVERFLOW) {
2144f665790aSDavid Marchand 				rte_bbdev_log(ERR, "Read address is overflow!");
21454d9199e3SNicolas Chautru 				return -1;
21464d9199e3SNicolas Chautru 			}
21474d9199e3SNicolas Chautru 		}
214810829ff2SHernan Vargas 		input[increment] = fpga_5gnr_reg_read_64(q->d->mmio_base,
21494d9199e3SNicolas Chautru 			FPGA_5GNR_FEC_DDR4_RD_DATA_REGS);
215010829ff2SHernan Vargas 		left_length -= FPGA_5GNR_DDR_RD_DATA_LEN_IN_BYTES;
215110829ff2SHernan Vargas 		in_offset += FPGA_5GNR_DDR_WR_DATA_LEN_IN_BYTES;
21524d9199e3SNicolas Chautru 		increment++;
21539e3ffd38SHernan Vargas 		if (d->fpga_variant == AGX100_FPGA_VARIANT)
21549e3ffd38SHernan Vargas 			fpga_5gnr_reg_write_8(q->d->mmio_base, FPGA_5GNR_FEC_DDR4_RD_RDY_REGS, 0);
21559e3ffd38SHernan Vargas 		else
215610829ff2SHernan Vargas 			fpga_5gnr_reg_write_8(q->d->mmio_base, FPGA_5GNR_FEC_DDR4_RD_DONE_REGS, 0);
21574d9199e3SNicolas Chautru 	}
215810829ff2SHernan Vargas 	fpga_5gnr_mutex_free(q);
21594d9199e3SNicolas Chautru 	return 1;
21604d9199e3SNicolas Chautru }
21614d9199e3SNicolas Chautru 
21624d9199e3SNicolas Chautru static inline int
216310829ff2SHernan Vargas enqueue_ldpc_enc_one_op_cb(struct fpga_5gnr_queue *q, struct rte_bbdev_enc_op *op,
216444dc6faaSNicolas Chautru 		uint16_t desc_offset)
216544dc6faaSNicolas Chautru {
2166c750d277SHernan Vargas 	union vc_5gnr_dma_desc *vc_5gnr_desc;
21679e3ffd38SHernan Vargas 	union agx100_dma_desc *agx100_desc;
216844dc6faaSNicolas Chautru 	int ret;
216944dc6faaSNicolas Chautru 	uint8_t c, crc24_bits = 0;
217044dc6faaSNicolas Chautru 	struct rte_bbdev_op_ldpc_enc *enc = &op->ldpc_enc;
217144dc6faaSNicolas Chautru 	uint16_t in_offset = enc->input.offset;
217244dc6faaSNicolas Chautru 	uint16_t out_offset = enc->output.offset;
217344dc6faaSNicolas Chautru 	struct rte_mbuf *m_in = enc->input.data;
217444dc6faaSNicolas Chautru 	struct rte_mbuf *m_out = enc->output.data;
217544dc6faaSNicolas Chautru 	struct rte_mbuf *m_out_head = enc->output.data;
217644dc6faaSNicolas Chautru 	uint32_t in_length, out_length, e;
217744dc6faaSNicolas Chautru 	uint16_t total_left = enc->input.length;
217844dc6faaSNicolas Chautru 	uint16_t ring_offset;
217944dc6faaSNicolas Chautru 	uint16_t K, k_;
21809e3ffd38SHernan Vargas 	struct fpga_5gnr_fec_device *d = q->d;
218144dc6faaSNicolas Chautru 
21829e3ffd38SHernan Vargas 	if (d->fpga_variant == VC_5GNR_FPGA_VARIANT) {
2183c750d277SHernan Vargas 		if (vc_5gnr_validate_ldpc_enc_op(op) == -1) {
2184984b7306SHernan Vargas 			rte_bbdev_log(ERR, "LDPC encoder validation rejected");
218511b0a112SNicolas Chautru 			return -EINVAL;
218611b0a112SNicolas Chautru 		}
21879e3ffd38SHernan Vargas 	}
218811b0a112SNicolas Chautru 
218944dc6faaSNicolas Chautru 	/* Clear op status */
219044dc6faaSNicolas Chautru 	op->status = 0;
219144dc6faaSNicolas Chautru 
219244dc6faaSNicolas Chautru 	if (m_in == NULL || m_out == NULL) {
219344dc6faaSNicolas Chautru 		rte_bbdev_log(ERR, "Invalid mbuf pointer");
219444dc6faaSNicolas Chautru 		op->status = 1 << RTE_BBDEV_DATA_ERROR;
219544dc6faaSNicolas Chautru 		return -EINVAL;
219644dc6faaSNicolas Chautru 	}
219744dc6faaSNicolas Chautru 
219844dc6faaSNicolas Chautru 	if (enc->op_flags & RTE_BBDEV_LDPC_CRC_24B_ATTACH)
219944dc6faaSNicolas Chautru 		crc24_bits = 24;
220044dc6faaSNicolas Chautru 
220148fc315fSNicolas Chautru 	if (enc->code_block_mode == RTE_BBDEV_TRANSPORT_BLOCK) {
22029e3ffd38SHernan Vargas 		/* TODO: For Transport Block mode. */
22039e3ffd38SHernan Vargas 		rte_bbdev_log(ERR, "Transport Block not supported yet");
22049e3ffd38SHernan Vargas 		return -1;
22059e3ffd38SHernan Vargas 	}
22069e3ffd38SHernan Vargas 	/* For Code Block mode. */
220744dc6faaSNicolas Chautru 	c = 1;
220844dc6faaSNicolas Chautru 	e = enc->cb_params.e;
220944dc6faaSNicolas Chautru 
221044dc6faaSNicolas Chautru 	/* Update total_left */
221144dc6faaSNicolas Chautru 	K = (enc->basegraph == 1 ? 22 : 10) * enc->z_c;
221244dc6faaSNicolas Chautru 	k_ = K - enc->n_filler;
221344dc6faaSNicolas Chautru 	in_length = (k_ - crc24_bits) >> 3;
221444dc6faaSNicolas Chautru 	out_length = (e + 7) >> 3;
221544dc6faaSNicolas Chautru 
221644dc6faaSNicolas Chautru 	total_left = rte_pktmbuf_data_len(m_in) - in_offset;
221744dc6faaSNicolas Chautru 
221844dc6faaSNicolas Chautru 	/* Update offsets */
221944dc6faaSNicolas Chautru 	if (total_left != in_length) {
222044dc6faaSNicolas Chautru 		op->status |= 1 << RTE_BBDEV_DATA_ERROR;
222144dc6faaSNicolas Chautru 		rte_bbdev_log(ERR,
222244dc6faaSNicolas Chautru 				"Mismatch between mbuf length and included CBs sizes %d",
222344dc6faaSNicolas Chautru 				total_left);
222444dc6faaSNicolas Chautru 	}
222544dc6faaSNicolas Chautru 
222644dc6faaSNicolas Chautru 	mbuf_append(m_out_head, m_out, out_length);
222744dc6faaSNicolas Chautru 
22289e3ffd38SHernan Vargas 	/* Offset into the ring. */
22299e3ffd38SHernan Vargas 	ring_offset = fpga_5gnr_desc_idx_tail(q, desc_offset);
22309e3ffd38SHernan Vargas 
22319e3ffd38SHernan Vargas 	if (d->fpga_variant == VC_5GNR_FPGA_VARIANT) {
22329e3ffd38SHernan Vargas 		/* Setup DMA Descriptor. */
22339e3ffd38SHernan Vargas 		vc_5gnr_desc = vc_5gnr_get_desc_tail(q, desc_offset);
2234c750d277SHernan Vargas 		ret = vc_5gnr_dma_desc_te_fill(op, &vc_5gnr_desc->enc_req, m_in, m_out,
223544dc6faaSNicolas Chautru 				k_, e, in_offset, out_offset, ring_offset, c);
22369e3ffd38SHernan Vargas 	} else {
22379e3ffd38SHernan Vargas 		/* Setup DMA Descriptor. */
22389e3ffd38SHernan Vargas 		agx100_desc = agx100_get_desc_tail(q, desc_offset);
22399e3ffd38SHernan Vargas 		ret = agx100_dma_desc_le_fill(op, &agx100_desc->enc_req, m_in, m_out,
22409e3ffd38SHernan Vargas 				k_, e, in_offset, out_offset, ring_offset, c);
22419e3ffd38SHernan Vargas 	}
22429e3ffd38SHernan Vargas 
224344dc6faaSNicolas Chautru 	if (unlikely(ret < 0))
224444dc6faaSNicolas Chautru 		return ret;
224544dc6faaSNicolas Chautru 
224644dc6faaSNicolas Chautru 	/* Update lengths */
224744dc6faaSNicolas Chautru 	total_left -= in_length;
224844dc6faaSNicolas Chautru 	op->ldpc_enc.output.length += out_length;
224944dc6faaSNicolas Chautru 
225044dc6faaSNicolas Chautru 	if (total_left > 0) {
225144dc6faaSNicolas Chautru 		rte_bbdev_log(ERR,
225244dc6faaSNicolas Chautru 			"Mismatch between mbuf length and included CB sizes: mbuf len %u, cb len %u",
225344dc6faaSNicolas Chautru 				total_left, in_length);
225444dc6faaSNicolas Chautru 		return -1;
225544dc6faaSNicolas Chautru 	}
225644dc6faaSNicolas Chautru 
225711b0a112SNicolas Chautru #ifdef RTE_LIBRTE_BBDEV_DEBUG
22589e3ffd38SHernan Vargas 	if (d->fpga_variant == VC_5GNR_FPGA_VARIANT)
2259c750d277SHernan Vargas 		vc_5gnr_print_dma_enc_desc_debug_info(vc_5gnr_desc);
22609e3ffd38SHernan Vargas 	else
22619e3ffd38SHernan Vargas 		agx100_print_dma_enc_desc_debug_info(agx100_desc);
226211b0a112SNicolas Chautru #endif
226344dc6faaSNicolas Chautru 	return 1;
226444dc6faaSNicolas Chautru }
226544dc6faaSNicolas Chautru 
226644dc6faaSNicolas Chautru static inline int
2267c750d277SHernan Vargas vc_5gnr_enqueue_ldpc_dec_one_op_cb(struct fpga_5gnr_queue *q, struct rte_bbdev_dec_op *op,
226844dc6faaSNicolas Chautru 		uint16_t desc_offset)
226944dc6faaSNicolas Chautru {
2270c750d277SHernan Vargas 	union vc_5gnr_dma_desc *desc;
227144dc6faaSNicolas Chautru 	int ret;
227244dc6faaSNicolas Chautru 	uint16_t ring_offset;
227344dc6faaSNicolas Chautru 	uint8_t c;
227444dc6faaSNicolas Chautru 	uint16_t e, in_length, out_length, k0, l, seg_total_left, sys_cols;
227544dc6faaSNicolas Chautru 	uint16_t K, parity_offset, harq_in_length = 0, harq_out_length = 0;
227644dc6faaSNicolas Chautru 	uint16_t crc24_overlap = 0;
227744dc6faaSNicolas Chautru 	struct rte_bbdev_op_ldpc_dec *dec = &op->ldpc_dec;
227844dc6faaSNicolas Chautru 	struct rte_mbuf *m_in = dec->input.data;
227944dc6faaSNicolas Chautru 	struct rte_mbuf *m_out = dec->hard_output.data;
228044dc6faaSNicolas Chautru 	struct rte_mbuf *m_out_head = dec->hard_output.data;
228144dc6faaSNicolas Chautru 	uint16_t in_offset = dec->input.offset;
228244dc6faaSNicolas Chautru 	uint16_t out_offset = dec->hard_output.offset;
228344dc6faaSNicolas Chautru 	uint32_t harq_offset = 0;
228444dc6faaSNicolas Chautru 
2285c750d277SHernan Vargas 	if (vc_5gnr_validate_ldpc_dec_op(op) == -1) {
2286984b7306SHernan Vargas 		rte_bbdev_log(ERR, "LDPC decoder validation rejected");
228711b0a112SNicolas Chautru 		return -EINVAL;
228811b0a112SNicolas Chautru 	}
228911b0a112SNicolas Chautru 
229044dc6faaSNicolas Chautru 	/* Clear op status */
229144dc6faaSNicolas Chautru 	op->status = 0;
229244dc6faaSNicolas Chautru 
229344dc6faaSNicolas Chautru 	/* Setup DMA Descriptor */
22949e3ffd38SHernan Vargas 	ring_offset = fpga_5gnr_desc_idx_tail(q, desc_offset);
22959e3ffd38SHernan Vargas 	desc = vc_5gnr_get_desc_tail(q, desc_offset);
229644dc6faaSNicolas Chautru 
229710829ff2SHernan Vargas 	if (check_bit(dec->op_flags, RTE_BBDEV_LDPC_INTERNAL_HARQ_MEMORY_LOOPBACK)) {
22984d9199e3SNicolas Chautru 		struct rte_mbuf *harq_in = dec->harq_combined_input.data;
22994d9199e3SNicolas Chautru 		struct rte_mbuf *harq_out = dec->harq_combined_output.data;
23004d9199e3SNicolas Chautru 		harq_in_length = dec->harq_combined_input.length;
23014d9199e3SNicolas Chautru 		uint32_t harq_in_offset = dec->harq_combined_input.offset;
23024d9199e3SNicolas Chautru 		uint32_t harq_out_offset = dec->harq_combined_output.offset;
23034d9199e3SNicolas Chautru 
230410829ff2SHernan Vargas 		if (check_bit(dec->op_flags, RTE_BBDEV_LDPC_INTERNAL_HARQ_MEMORY_OUT_ENABLE)) {
230510829ff2SHernan Vargas 			ret = fpga_5gnr_harq_write_loopback(q, harq_in,
23064d9199e3SNicolas Chautru 					harq_in_length, harq_in_offset,
23074d9199e3SNicolas Chautru 					harq_out_offset);
23084d9199e3SNicolas Chautru 		} else if (check_bit(dec->op_flags,
23094d9199e3SNicolas Chautru 				RTE_BBDEV_LDPC_INTERNAL_HARQ_MEMORY_IN_ENABLE
23104d9199e3SNicolas Chautru 				)) {
231110829ff2SHernan Vargas 			ret = fpga_5gnr_harq_read_loopback(q, harq_out,
23124d9199e3SNicolas Chautru 				harq_in_length, harq_in_offset,
23134d9199e3SNicolas Chautru 				harq_out_offset);
23144d9199e3SNicolas Chautru 			dec->harq_combined_output.length = harq_in_length;
23154d9199e3SNicolas Chautru 		} else {
23164d9199e3SNicolas Chautru 			rte_bbdev_log(ERR, "OP flag Err!");
23174d9199e3SNicolas Chautru 			ret = -1;
23184d9199e3SNicolas Chautru 		}
231910829ff2SHernan Vargas 
23204d9199e3SNicolas Chautru 		/* Set descriptor for dequeue */
23214d9199e3SNicolas Chautru 		desc->dec_req.done = 1;
23224d9199e3SNicolas Chautru 		desc->dec_req.error = 0;
23234d9199e3SNicolas Chautru 		desc->dec_req.op_addr = op;
23244d9199e3SNicolas Chautru 		desc->dec_req.cbs_in_op = 1;
232510829ff2SHernan Vargas 
23264d9199e3SNicolas Chautru 		/* Mark this dummy descriptor to be dropped by HW */
232710829ff2SHernan Vargas 		desc->dec_req.desc_idx = (ring_offset + 1) & q->sw_ring_wrap_mask;
2328c750d277SHernan Vargas 
23294d9199e3SNicolas Chautru 		return ret; /* Error or number of CB */
23304d9199e3SNicolas Chautru 	}
23314d9199e3SNicolas Chautru 
233244dc6faaSNicolas Chautru 	if (m_in == NULL || m_out == NULL) {
233344dc6faaSNicolas Chautru 		rte_bbdev_log(ERR, "Invalid mbuf pointer");
233444dc6faaSNicolas Chautru 		op->status = 1 << RTE_BBDEV_DATA_ERROR;
233544dc6faaSNicolas Chautru 		return -1;
233644dc6faaSNicolas Chautru 	}
233744dc6faaSNicolas Chautru 
233844dc6faaSNicolas Chautru 	c = 1;
233944dc6faaSNicolas Chautru 	e = dec->cb_params.e;
234044dc6faaSNicolas Chautru 
234144dc6faaSNicolas Chautru 	if (check_bit(dec->op_flags, RTE_BBDEV_LDPC_CRC_TYPE_24B_DROP))
234244dc6faaSNicolas Chautru 		crc24_overlap = 24;
234344dc6faaSNicolas Chautru 
234444dc6faaSNicolas Chautru 	sys_cols = (dec->basegraph == 1) ? 22 : 10;
234544dc6faaSNicolas Chautru 	K = sys_cols * dec->z_c;
234644dc6faaSNicolas Chautru 	parity_offset = K - 2 * dec->z_c;
234744dc6faaSNicolas Chautru 
234844dc6faaSNicolas Chautru 	out_length = ((K - crc24_overlap - dec->n_filler) >> 3);
234944dc6faaSNicolas Chautru 	in_length = e;
235044dc6faaSNicolas Chautru 	seg_total_left = dec->input.length;
235144dc6faaSNicolas Chautru 
2352c750d277SHernan Vargas 	if (check_bit(dec->op_flags, RTE_BBDEV_LDPC_HQ_COMBINE_IN_ENABLE))
2353c750d277SHernan Vargas 		harq_in_length = RTE_MIN(dec->harq_combined_input.length, (uint32_t)dec->n_cb);
235444dc6faaSNicolas Chautru 
235544dc6faaSNicolas Chautru 	if (check_bit(dec->op_flags, RTE_BBDEV_LDPC_HQ_COMBINE_OUT_ENABLE)) {
2356c750d277SHernan Vargas 		k0 = get_k0(dec->n_cb, dec->z_c, dec->basegraph, dec->rv_index);
235744dc6faaSNicolas Chautru 		if (k0 > parity_offset)
235844dc6faaSNicolas Chautru 			l = k0 + e;
235944dc6faaSNicolas Chautru 		else
236044dc6faaSNicolas Chautru 			l = k0 + e + dec->n_filler;
2361c750d277SHernan Vargas 		harq_out_length = RTE_MIN(RTE_MAX(harq_in_length, l), dec->n_cb);
236244dc6faaSNicolas Chautru 		dec->harq_combined_output.length = harq_out_length;
236344dc6faaSNicolas Chautru 	}
236444dc6faaSNicolas Chautru 
236544dc6faaSNicolas Chautru 	mbuf_append(m_out_head, m_out, out_length);
2366c750d277SHernan Vargas 
236744dc6faaSNicolas Chautru 	if (check_bit(dec->op_flags, RTE_BBDEV_LDPC_HQ_COMBINE_IN_ENABLE))
236844dc6faaSNicolas Chautru 		harq_offset = dec->harq_combined_input.offset;
236944dc6faaSNicolas Chautru 	else if (check_bit(dec->op_flags, RTE_BBDEV_LDPC_HQ_COMBINE_OUT_ENABLE))
237044dc6faaSNicolas Chautru 		harq_offset = dec->harq_combined_output.offset;
237144dc6faaSNicolas Chautru 
237244dc6faaSNicolas Chautru 	if ((harq_offset & 0x3FF) > 0) {
237344dc6faaSNicolas Chautru 		rte_bbdev_log(ERR, "Invalid HARQ offset %d", harq_offset);
237444dc6faaSNicolas Chautru 		op->status = 1 << RTE_BBDEV_DATA_ERROR;
237544dc6faaSNicolas Chautru 		return -1;
237644dc6faaSNicolas Chautru 	}
237744dc6faaSNicolas Chautru 
2378c750d277SHernan Vargas 	ret = vc_5gnr_dma_desc_ld_fill(op, &desc->dec_req, m_in, m_out,
237944dc6faaSNicolas Chautru 		harq_in_length, in_offset, out_offset, harq_offset,
238044dc6faaSNicolas Chautru 		ring_offset, c);
2381c750d277SHernan Vargas 
238244dc6faaSNicolas Chautru 	if (unlikely(ret < 0))
238344dc6faaSNicolas Chautru 		return ret;
238444dc6faaSNicolas Chautru 	/* Update lengths */
238544dc6faaSNicolas Chautru 	seg_total_left -= in_length;
238644dc6faaSNicolas Chautru 	op->ldpc_dec.hard_output.length += out_length;
238744dc6faaSNicolas Chautru 	if (seg_total_left > 0) {
238844dc6faaSNicolas Chautru 		rte_bbdev_log(ERR,
238944dc6faaSNicolas Chautru 				"Mismatch between mbuf length and included CB sizes: mbuf len %u, cb len %u",
239044dc6faaSNicolas Chautru 				seg_total_left, in_length);
239144dc6faaSNicolas Chautru 		return -1;
239244dc6faaSNicolas Chautru 	}
239344dc6faaSNicolas Chautru 
239411b0a112SNicolas Chautru #ifdef RTE_LIBRTE_BBDEV_DEBUG
2395c750d277SHernan Vargas 	vc_5gnr_print_dma_dec_desc_debug_info(desc);
239611b0a112SNicolas Chautru #endif
239711b0a112SNicolas Chautru 
239844dc6faaSNicolas Chautru 	return 1;
239944dc6faaSNicolas Chautru }
240044dc6faaSNicolas Chautru 
24019e3ffd38SHernan Vargas static inline int
24029e3ffd38SHernan Vargas agx100_enqueue_ldpc_dec_one_op_cb(struct fpga_5gnr_queue *q, struct rte_bbdev_dec_op *op,
24039e3ffd38SHernan Vargas 		uint16_t desc_offset)
24049e3ffd38SHernan Vargas {
24059e3ffd38SHernan Vargas 	union agx100_dma_desc *desc;
24069e3ffd38SHernan Vargas 	int ret;
24079e3ffd38SHernan Vargas 	uint16_t ring_offset;
24089e3ffd38SHernan Vargas 	uint8_t c;
24099e3ffd38SHernan Vargas 	uint16_t e, in_length, out_length, k0, l, seg_total_left, sys_cols;
24109e3ffd38SHernan Vargas 	uint16_t K, parity_offset, harq_in_length = 0, harq_out_length = 0;
24119e3ffd38SHernan Vargas 	uint16_t crc24_overlap = 0;
24129e3ffd38SHernan Vargas 	struct rte_bbdev_op_ldpc_dec *dec = &op->ldpc_dec;
24139e3ffd38SHernan Vargas 	struct rte_mbuf *m_in = dec->input.data;
24149e3ffd38SHernan Vargas 	struct rte_mbuf *m_out = dec->hard_output.data;
24159e3ffd38SHernan Vargas 	struct rte_mbuf *m_out_head = dec->hard_output.data;
24169e3ffd38SHernan Vargas 	uint16_t in_offset = dec->input.offset;
24179e3ffd38SHernan Vargas 	uint16_t out_offset = dec->hard_output.offset;
24189e3ffd38SHernan Vargas 	uint32_t harq_in_offset = 0;
24199e3ffd38SHernan Vargas 	uint32_t harq_out_offset = 0;
24209e3ffd38SHernan Vargas 
24219e3ffd38SHernan Vargas 	/* Clear op status. */
24229e3ffd38SHernan Vargas 	op->status = 0;
24239e3ffd38SHernan Vargas 
24249e3ffd38SHernan Vargas 	/* Setup DMA Descriptor. */
24259e3ffd38SHernan Vargas 	ring_offset = fpga_5gnr_desc_idx_tail(q, desc_offset);
24269e3ffd38SHernan Vargas 	desc = agx100_get_desc_tail(q, desc_offset);
24279e3ffd38SHernan Vargas 
24289e3ffd38SHernan Vargas 	if (check_bit(dec->op_flags, RTE_BBDEV_LDPC_INTERNAL_HARQ_MEMORY_LOOPBACK)) {
24299e3ffd38SHernan Vargas 		struct rte_mbuf *harq_in = dec->harq_combined_input.data;
24309e3ffd38SHernan Vargas 		struct rte_mbuf *harq_out = dec->harq_combined_output.data;
24319e3ffd38SHernan Vargas 		harq_in_length = dec->harq_combined_input.length;
24329e3ffd38SHernan Vargas 		uint32_t harq_in_offset = dec->harq_combined_input.offset;
24339e3ffd38SHernan Vargas 		uint32_t harq_out_offset = dec->harq_combined_output.offset;
24349e3ffd38SHernan Vargas 
24359e3ffd38SHernan Vargas 		if (check_bit(dec->op_flags, RTE_BBDEV_LDPC_INTERNAL_HARQ_MEMORY_OUT_ENABLE)) {
24369e3ffd38SHernan Vargas 			ret = fpga_5gnr_harq_write_loopback(q, harq_in,
24379e3ffd38SHernan Vargas 					harq_in_length, harq_in_offset,
24389e3ffd38SHernan Vargas 					harq_out_offset);
24399e3ffd38SHernan Vargas 		} else if (check_bit(dec->op_flags,
24409e3ffd38SHernan Vargas 				RTE_BBDEV_LDPC_INTERNAL_HARQ_MEMORY_IN_ENABLE)) {
24419e3ffd38SHernan Vargas 			ret = fpga_5gnr_harq_read_loopback(q, harq_out,
24429e3ffd38SHernan Vargas 					harq_in_length, harq_in_offset,
24439e3ffd38SHernan Vargas 					harq_out_offset);
24449e3ffd38SHernan Vargas 			dec->harq_combined_output.length = harq_in_length;
24459e3ffd38SHernan Vargas 		} else {
24469e3ffd38SHernan Vargas 			rte_bbdev_log(ERR, "OP flag Err!");
24479e3ffd38SHernan Vargas 			ret = -1;
24489e3ffd38SHernan Vargas 		}
24499e3ffd38SHernan Vargas 
24509e3ffd38SHernan Vargas 		/* Set descriptor for dequeue. */
24519e3ffd38SHernan Vargas 		desc->dec_req.done = 1;
24529e3ffd38SHernan Vargas 		desc->dec_req.error_code = 0;
24539e3ffd38SHernan Vargas 		desc->dec_req.error_msg = 0;
24549e3ffd38SHernan Vargas 		desc->dec_req.op_addr = op;
24559e3ffd38SHernan Vargas 		desc->dec_req.cbs_in_op = 1;
24569e3ffd38SHernan Vargas 
24579e3ffd38SHernan Vargas 		/* Mark this dummy descriptor to be dropped by HW. */
24589e3ffd38SHernan Vargas 		desc->dec_req.desc_idx = (ring_offset + 1) & q->sw_ring_wrap_mask;
24599e3ffd38SHernan Vargas 
24609e3ffd38SHernan Vargas 		return ret; /* Error or number of CB. */
24619e3ffd38SHernan Vargas 	}
24629e3ffd38SHernan Vargas 
24639e3ffd38SHernan Vargas 	if (m_in == NULL || m_out == NULL) {
24649e3ffd38SHernan Vargas 		rte_bbdev_log(ERR, "Invalid mbuf pointer");
24659e3ffd38SHernan Vargas 		op->status = 1 << RTE_BBDEV_DATA_ERROR;
24669e3ffd38SHernan Vargas 		return -1;
24679e3ffd38SHernan Vargas 	}
24689e3ffd38SHernan Vargas 
24699e3ffd38SHernan Vargas 	c = 1;
24709e3ffd38SHernan Vargas 	e = dec->cb_params.e;
24719e3ffd38SHernan Vargas 
24729e3ffd38SHernan Vargas 	if (check_bit(dec->op_flags, RTE_BBDEV_LDPC_CRC_TYPE_24B_DROP))
24739e3ffd38SHernan Vargas 		crc24_overlap = 24;
24749e3ffd38SHernan Vargas 
24759e3ffd38SHernan Vargas 	sys_cols = (dec->basegraph == 1) ? 22 : 10;
24769e3ffd38SHernan Vargas 	K = sys_cols * dec->z_c;
24779e3ffd38SHernan Vargas 	parity_offset = K - 2 * dec->z_c;
24789e3ffd38SHernan Vargas 
24799e3ffd38SHernan Vargas 	out_length = ((K - crc24_overlap - dec->n_filler) >> 3);
24809e3ffd38SHernan Vargas 	in_length = e;
24819e3ffd38SHernan Vargas 	seg_total_left = dec->input.length;
24829e3ffd38SHernan Vargas 
24839e3ffd38SHernan Vargas 	if (check_bit(dec->op_flags, RTE_BBDEV_LDPC_HQ_COMBINE_IN_ENABLE))
24849e3ffd38SHernan Vargas 		harq_in_length = RTE_MIN(dec->harq_combined_input.length, (uint32_t)dec->n_cb);
24859e3ffd38SHernan Vargas 
24869e3ffd38SHernan Vargas 	if (check_bit(dec->op_flags, RTE_BBDEV_LDPC_HQ_COMBINE_OUT_ENABLE)) {
24879e3ffd38SHernan Vargas 		k0 = get_k0(dec->n_cb, dec->z_c, dec->basegraph, dec->rv_index);
24889e3ffd38SHernan Vargas 		if (k0 > parity_offset)
24899e3ffd38SHernan Vargas 			l = k0 + e;
24909e3ffd38SHernan Vargas 		else
24919e3ffd38SHernan Vargas 			l = k0 + e + dec->n_filler;
24929e3ffd38SHernan Vargas 		harq_out_length = RTE_MIN(RTE_MAX(harq_in_length, l), dec->n_cb);
24939e3ffd38SHernan Vargas 		dec->harq_combined_output.length = harq_out_length;
24949e3ffd38SHernan Vargas 	}
24959e3ffd38SHernan Vargas 
24969e3ffd38SHernan Vargas 	mbuf_append(m_out_head, m_out, out_length);
24979e3ffd38SHernan Vargas 	harq_in_offset = dec->harq_combined_input.offset;
24989e3ffd38SHernan Vargas 	harq_out_offset = dec->harq_combined_output.offset;
24999e3ffd38SHernan Vargas 
25009e3ffd38SHernan Vargas 	ret = agx100_dma_desc_ld_fill(op, &desc->dec_req, m_in, m_out,
25019e3ffd38SHernan Vargas 		harq_in_length, in_offset, out_offset, harq_in_offset,
25029e3ffd38SHernan Vargas 		harq_out_offset, ring_offset, c);
25039e3ffd38SHernan Vargas 
25049e3ffd38SHernan Vargas 	if (unlikely(ret < 0))
25059e3ffd38SHernan Vargas 		return ret;
25069e3ffd38SHernan Vargas 	/* Update lengths. */
25079e3ffd38SHernan Vargas 	seg_total_left -= in_length;
25089e3ffd38SHernan Vargas 	op->ldpc_dec.hard_output.length += out_length;
25099e3ffd38SHernan Vargas 	if (seg_total_left > 0) {
25109e3ffd38SHernan Vargas 		rte_bbdev_log(ERR,
25119e3ffd38SHernan Vargas 				"Mismatch between mbuf length and included CB sizes: mbuf len %u, cb len %u",
25129e3ffd38SHernan Vargas 				seg_total_left, in_length);
25139e3ffd38SHernan Vargas 		return -1;
25149e3ffd38SHernan Vargas 	}
25159e3ffd38SHernan Vargas 
25169e3ffd38SHernan Vargas #ifdef RTE_LIBRTE_BBDEV_DEBUG
25179e3ffd38SHernan Vargas 	agx100_print_dma_dec_desc_debug_info(desc);
25189e3ffd38SHernan Vargas #endif
25199e3ffd38SHernan Vargas 
25209e3ffd38SHernan Vargas 	return 1;
25219e3ffd38SHernan Vargas }
25229e3ffd38SHernan Vargas 
252344dc6faaSNicolas Chautru static uint16_t
252410829ff2SHernan Vargas fpga_5gnr_enqueue_ldpc_enc(struct rte_bbdev_queue_data *q_data,
252544dc6faaSNicolas Chautru 		struct rte_bbdev_enc_op **ops, uint16_t num)
252644dc6faaSNicolas Chautru {
252744dc6faaSNicolas Chautru 	uint16_t i, total_enqueued_cbs = 0;
252844dc6faaSNicolas Chautru 	int32_t avail;
252944dc6faaSNicolas Chautru 	int enqueued_cbs;
253010829ff2SHernan Vargas 	struct fpga_5gnr_queue *q = q_data->queue_private;
2531c750d277SHernan Vargas 	union vc_5gnr_dma_desc *vc_5gnr_desc;
25329e3ffd38SHernan Vargas 	union agx100_dma_desc *agx100_desc;
25339e3ffd38SHernan Vargas 	struct fpga_5gnr_fec_device *d = q->d;
253444dc6faaSNicolas Chautru 
253544dc6faaSNicolas Chautru 	/* Check if queue is not full */
25369e3ffd38SHernan Vargas 	if (unlikely((fpga_5gnr_desc_idx_tail(q, 1)) == q->head_free_desc))
253744dc6faaSNicolas Chautru 		return 0;
253844dc6faaSNicolas Chautru 
253944dc6faaSNicolas Chautru 	/* Calculates available space */
254044dc6faaSNicolas Chautru 	avail = (q->head_free_desc > q->tail) ?
254144dc6faaSNicolas Chautru 		q->head_free_desc - q->tail - 1 :
254244dc6faaSNicolas Chautru 		q->ring_ctrl_reg.ring_size + q->head_free_desc - q->tail - 1;
254344dc6faaSNicolas Chautru 
254444dc6faaSNicolas Chautru 	for (i = 0; i < num; ++i) {
254544dc6faaSNicolas Chautru 		/* Check if there is available space for further
254644dc6faaSNicolas Chautru 		 * processing
254744dc6faaSNicolas Chautru 		 */
254844dc6faaSNicolas Chautru 		if (unlikely(avail - 1 < 0))
254944dc6faaSNicolas Chautru 			break;
255044dc6faaSNicolas Chautru 		avail -= 1;
255110829ff2SHernan Vargas 		enqueued_cbs = enqueue_ldpc_enc_one_op_cb(q, ops[i], total_enqueued_cbs);
255244dc6faaSNicolas Chautru 
255344dc6faaSNicolas Chautru 		if (enqueued_cbs < 0)
255444dc6faaSNicolas Chautru 			break;
255544dc6faaSNicolas Chautru 
255644dc6faaSNicolas Chautru 		total_enqueued_cbs += enqueued_cbs;
255744dc6faaSNicolas Chautru 
255844dc6faaSNicolas Chautru 		rte_bbdev_log_debug("enqueuing enc ops [%d/%d] | head %d | tail %d",
255944dc6faaSNicolas Chautru 				total_enqueued_cbs, num,
256044dc6faaSNicolas Chautru 				q->head_free_desc, q->tail);
256144dc6faaSNicolas Chautru 	}
256244dc6faaSNicolas Chautru 
256344dc6faaSNicolas Chautru 	/* Set interrupt bit for last CB in enqueued ops. FPGA issues interrupt
256444dc6faaSNicolas Chautru 	 * only when all previous CBs were already processed.
256544dc6faaSNicolas Chautru 	 */
25669e3ffd38SHernan Vargas 	if (d->fpga_variant == VC_5GNR_FPGA_VARIANT) {
25679e3ffd38SHernan Vargas 		vc_5gnr_desc = vc_5gnr_get_desc_tail(q, total_enqueued_cbs - 1);
2568c750d277SHernan Vargas 		vc_5gnr_desc->enc_req.irq_en = q->irq_enable;
25699e3ffd38SHernan Vargas 	} else {
25709e3ffd38SHernan Vargas 		agx100_desc = agx100_get_desc_tail(q, total_enqueued_cbs - 1);
25719e3ffd38SHernan Vargas 		agx100_desc->enc_req.int_en = q->irq_enable;
25729e3ffd38SHernan Vargas 	}
257344dc6faaSNicolas Chautru 
257410829ff2SHernan Vargas 	fpga_5gnr_dma_enqueue(q, total_enqueued_cbs, &q_data->queue_stats);
257544dc6faaSNicolas Chautru 
257644dc6faaSNicolas Chautru 	/* Update stats */
257744dc6faaSNicolas Chautru 	q_data->queue_stats.enqueued_count += i;
257844dc6faaSNicolas Chautru 	q_data->queue_stats.enqueue_err_count += num - i;
257944dc6faaSNicolas Chautru 
258044dc6faaSNicolas Chautru 	return i;
258144dc6faaSNicolas Chautru }
258244dc6faaSNicolas Chautru 
258344dc6faaSNicolas Chautru static uint16_t
258410829ff2SHernan Vargas fpga_5gnr_enqueue_ldpc_dec(struct rte_bbdev_queue_data *q_data,
258544dc6faaSNicolas Chautru 		struct rte_bbdev_dec_op **ops, uint16_t num)
258644dc6faaSNicolas Chautru {
258744dc6faaSNicolas Chautru 	uint16_t i, total_enqueued_cbs = 0;
258844dc6faaSNicolas Chautru 	int32_t avail;
258944dc6faaSNicolas Chautru 	int enqueued_cbs;
259010829ff2SHernan Vargas 	struct fpga_5gnr_queue *q = q_data->queue_private;
2591c750d277SHernan Vargas 	union vc_5gnr_dma_desc *vc_5gnr_desc;
25929e3ffd38SHernan Vargas 	union agx100_dma_desc *agx100_desc;
25939e3ffd38SHernan Vargas 	struct fpga_5gnr_fec_device *d = q->d;
259444dc6faaSNicolas Chautru 
259544dc6faaSNicolas Chautru 	/* Check if queue is not full */
25969e3ffd38SHernan Vargas 	if (unlikely((fpga_5gnr_desc_idx_tail(q, 1)) == q->head_free_desc))
259744dc6faaSNicolas Chautru 		return 0;
259844dc6faaSNicolas Chautru 
259944dc6faaSNicolas Chautru 	/* Calculates available space */
260044dc6faaSNicolas Chautru 	avail = (q->head_free_desc > q->tail) ?
260144dc6faaSNicolas Chautru 		q->head_free_desc - q->tail - 1 :
260244dc6faaSNicolas Chautru 		q->ring_ctrl_reg.ring_size + q->head_free_desc - q->tail - 1;
260344dc6faaSNicolas Chautru 
260444dc6faaSNicolas Chautru 	for (i = 0; i < num; ++i) {
260544dc6faaSNicolas Chautru 
260644dc6faaSNicolas Chautru 		/* Check if there is available space for further
260744dc6faaSNicolas Chautru 		 * processing
260844dc6faaSNicolas Chautru 		 */
260944dc6faaSNicolas Chautru 		if (unlikely(avail - 1 < 0))
261044dc6faaSNicolas Chautru 			break;
261144dc6faaSNicolas Chautru 		avail -= 1;
26129e3ffd38SHernan Vargas 		if (q->d->fpga_variant == VC_5GNR_FPGA_VARIANT) {
2613c750d277SHernan Vargas 			enqueued_cbs = vc_5gnr_enqueue_ldpc_dec_one_op_cb(q, ops[i],
261444dc6faaSNicolas Chautru 					total_enqueued_cbs);
26159e3ffd38SHernan Vargas 		} else {
26169e3ffd38SHernan Vargas 			enqueued_cbs = agx100_enqueue_ldpc_dec_one_op_cb(q, ops[i],
26179e3ffd38SHernan Vargas 					total_enqueued_cbs);
26189e3ffd38SHernan Vargas 		}
261944dc6faaSNicolas Chautru 
262044dc6faaSNicolas Chautru 		if (enqueued_cbs < 0)
262144dc6faaSNicolas Chautru 			break;
262244dc6faaSNicolas Chautru 
262344dc6faaSNicolas Chautru 		total_enqueued_cbs += enqueued_cbs;
262444dc6faaSNicolas Chautru 
262544dc6faaSNicolas Chautru 		rte_bbdev_log_debug("enqueuing dec ops [%d/%d] | head %d | tail %d",
262644dc6faaSNicolas Chautru 				total_enqueued_cbs, num,
262744dc6faaSNicolas Chautru 				q->head_free_desc, q->tail);
262844dc6faaSNicolas Chautru 	}
262944dc6faaSNicolas Chautru 
263044dc6faaSNicolas Chautru 	/* Update stats */
263144dc6faaSNicolas Chautru 	q_data->queue_stats.enqueued_count += i;
263244dc6faaSNicolas Chautru 	q_data->queue_stats.enqueue_err_count += num - i;
263344dc6faaSNicolas Chautru 
263444dc6faaSNicolas Chautru 	/* Set interrupt bit for last CB in enqueued ops. FPGA issues interrupt
263544dc6faaSNicolas Chautru 	 * only when all previous CBs were already processed.
263644dc6faaSNicolas Chautru 	 */
26379e3ffd38SHernan Vargas 	if (d->fpga_variant == VC_5GNR_FPGA_VARIANT) {
26389e3ffd38SHernan Vargas 		vc_5gnr_desc = vc_5gnr_get_desc_tail(q, total_enqueued_cbs - 1);
2639c750d277SHernan Vargas 		vc_5gnr_desc->enc_req.irq_en = q->irq_enable;
26409e3ffd38SHernan Vargas 	} else {
26419e3ffd38SHernan Vargas 		agx100_desc = agx100_get_desc_tail(q, total_enqueued_cbs - 1);
26429e3ffd38SHernan Vargas 		agx100_desc->enc_req.int_en = q->irq_enable;
26439e3ffd38SHernan Vargas 	}
26449e3ffd38SHernan Vargas 
264510829ff2SHernan Vargas 	fpga_5gnr_dma_enqueue(q, total_enqueued_cbs, &q_data->queue_stats);
264644dc6faaSNicolas Chautru 	return i;
264744dc6faaSNicolas Chautru }
264844dc6faaSNicolas Chautru 
264944dc6faaSNicolas Chautru 
265044dc6faaSNicolas Chautru static inline int
2651c750d277SHernan Vargas vc_5gnr_dequeue_ldpc_enc_one_op_cb(struct fpga_5gnr_queue *q, struct rte_bbdev_enc_op **op,
265244dc6faaSNicolas Chautru 		uint16_t desc_offset)
265344dc6faaSNicolas Chautru {
2654c750d277SHernan Vargas 	union vc_5gnr_dma_desc *desc;
2655bee09be3SNicolas Chautru 	int desc_error;
265644dc6faaSNicolas Chautru 	/* Set current desc */
26579e3ffd38SHernan Vargas 	desc = vc_5gnr_get_desc(q, desc_offset);
265844dc6faaSNicolas Chautru 
265944dc6faaSNicolas Chautru 	/*check if done */
266044dc6faaSNicolas Chautru 	if (desc->enc_req.done == 0)
266144dc6faaSNicolas Chautru 		return -1;
266244dc6faaSNicolas Chautru 
266344dc6faaSNicolas Chautru 	/* make sure the response is read atomically */
266444dc6faaSNicolas Chautru 	rte_smp_rmb();
266544dc6faaSNicolas Chautru 
266644dc6faaSNicolas Chautru 	rte_bbdev_log_debug("DMA response desc %p", desc);
266744dc6faaSNicolas Chautru 
266811b0a112SNicolas Chautru #ifdef RTE_LIBRTE_BBDEV_DEBUG
2669c750d277SHernan Vargas 	vc_5gnr_print_dma_enc_desc_debug_info(desc);
267011b0a112SNicolas Chautru #endif
2671bee09be3SNicolas Chautru 	*op = desc->enc_req.op_addr;
2672bee09be3SNicolas Chautru 	/* Check the descriptor error field, return 1 on error */
2673c750d277SHernan Vargas 	desc_error = vc_5gnr_check_desc_error(desc->enc_req.error);
2674bee09be3SNicolas Chautru 	(*op)->status = desc_error << RTE_BBDEV_DATA_ERROR;
2675bee09be3SNicolas Chautru 
267644dc6faaSNicolas Chautru 	return 1;
267744dc6faaSNicolas Chautru }
267844dc6faaSNicolas Chautru 
26799e3ffd38SHernan Vargas static inline int
26809e3ffd38SHernan Vargas agx100_dequeue_ldpc_enc_one_op_cb(struct fpga_5gnr_queue *q, struct rte_bbdev_enc_op **op,
26819e3ffd38SHernan Vargas 		uint16_t desc_offset)
26829e3ffd38SHernan Vargas {
26839e3ffd38SHernan Vargas 	union agx100_dma_desc *desc;
26849e3ffd38SHernan Vargas 	int desc_error;
26859e3ffd38SHernan Vargas 
26869e3ffd38SHernan Vargas 	/* Set current desc. */
26879e3ffd38SHernan Vargas 	desc = agx100_get_desc(q, desc_offset);
26889e3ffd38SHernan Vargas 	/*check if done */
26899e3ffd38SHernan Vargas 	if (desc->enc_req.done == 0)
26909e3ffd38SHernan Vargas 		return -1;
26919e3ffd38SHernan Vargas 
26929e3ffd38SHernan Vargas 	/* make sure the response is read atomically. */
26939e3ffd38SHernan Vargas 	rte_smp_rmb();
26949e3ffd38SHernan Vargas 
26959e3ffd38SHernan Vargas 	rte_bbdev_log_debug("DMA response desc %p", desc);
26969e3ffd38SHernan Vargas 
26979e3ffd38SHernan Vargas #ifdef RTE_LIBRTE_BBDEV_DEBUG
26989e3ffd38SHernan Vargas 	agx100_print_dma_enc_desc_debug_info(desc);
26999e3ffd38SHernan Vargas #endif
27009e3ffd38SHernan Vargas 	*op = desc->enc_req.op_addr;
27019e3ffd38SHernan Vargas 	/* Check the descriptor error field, return 1 on error. */
27029e3ffd38SHernan Vargas 	desc_error = agx100_check_desc_error(desc->enc_req.error_code,
27039e3ffd38SHernan Vargas 			desc->enc_req.error_msg);
27049e3ffd38SHernan Vargas 
27059e3ffd38SHernan Vargas 	(*op)->status = desc_error << RTE_BBDEV_DATA_ERROR;
27069e3ffd38SHernan Vargas 
27079e3ffd38SHernan Vargas 	return 1;
27089e3ffd38SHernan Vargas }
270944dc6faaSNicolas Chautru 
271044dc6faaSNicolas Chautru static inline int
2711c750d277SHernan Vargas vc_5gnr_dequeue_ldpc_dec_one_op_cb(struct fpga_5gnr_queue *q, struct rte_bbdev_dec_op **op,
271244dc6faaSNicolas Chautru 		uint16_t desc_offset)
271344dc6faaSNicolas Chautru {
2714c750d277SHernan Vargas 	union vc_5gnr_dma_desc *desc;
2715bee09be3SNicolas Chautru 	int desc_error;
2716c750d277SHernan Vargas 
271744dc6faaSNicolas Chautru 	/* Set descriptor */
27189e3ffd38SHernan Vargas 	desc = vc_5gnr_get_desc(q, desc_offset);
271944dc6faaSNicolas Chautru 
272044dc6faaSNicolas Chautru 	/* Verify done bit is set */
272144dc6faaSNicolas Chautru 	if (desc->dec_req.done == 0)
272244dc6faaSNicolas Chautru 		return -1;
272344dc6faaSNicolas Chautru 
272444dc6faaSNicolas Chautru 	/* make sure the response is read atomically */
272544dc6faaSNicolas Chautru 	rte_smp_rmb();
272644dc6faaSNicolas Chautru 
272711b0a112SNicolas Chautru #ifdef RTE_LIBRTE_BBDEV_DEBUG
2728c750d277SHernan Vargas 	vc_5gnr_print_dma_dec_desc_debug_info(desc);
272911b0a112SNicolas Chautru #endif
273011b0a112SNicolas Chautru 
273144dc6faaSNicolas Chautru 	*op = desc->dec_req.op_addr;
273244dc6faaSNicolas Chautru 
273344dc6faaSNicolas Chautru 	if (check_bit((*op)->ldpc_dec.op_flags,
273444dc6faaSNicolas Chautru 			RTE_BBDEV_LDPC_INTERNAL_HARQ_MEMORY_LOOPBACK)) {
273544dc6faaSNicolas Chautru 		(*op)->status = 0;
273644dc6faaSNicolas Chautru 		return 1;
273744dc6faaSNicolas Chautru 	}
273844dc6faaSNicolas Chautru 
273944dc6faaSNicolas Chautru 	/* FPGA reports iterations based on round-up minus 1 */
274044dc6faaSNicolas Chautru 	(*op)->ldpc_dec.iter_count = desc->dec_req.iter + 1;
2741c750d277SHernan Vargas 
274244dc6faaSNicolas Chautru 	/* CRC Check criteria */
274344dc6faaSNicolas Chautru 	if (desc->dec_req.crc24b_ind && !(desc->dec_req.crcb_pass))
274444dc6faaSNicolas Chautru 		(*op)->status = 1 << RTE_BBDEV_CRC_ERROR;
2745c750d277SHernan Vargas 
274644dc6faaSNicolas Chautru 	/* et_pass = 0 when decoder fails */
274744dc6faaSNicolas Chautru 	(*op)->status |= !(desc->dec_req.et_pass) << RTE_BBDEV_SYNDROME_ERROR;
2748c750d277SHernan Vargas 
2749bee09be3SNicolas Chautru 	/* Check the descriptor error field, return 1 on error */
2750c750d277SHernan Vargas 	desc_error = vc_5gnr_check_desc_error(desc->dec_req.error);
2751c750d277SHernan Vargas 
2752bee09be3SNicolas Chautru 	(*op)->status |= desc_error << RTE_BBDEV_DATA_ERROR;
2753c750d277SHernan Vargas 
275444dc6faaSNicolas Chautru 	return 1;
275544dc6faaSNicolas Chautru }
275644dc6faaSNicolas Chautru 
27579e3ffd38SHernan Vargas static inline int
27589e3ffd38SHernan Vargas agx100_dequeue_ldpc_dec_one_op_cb(struct fpga_5gnr_queue *q, struct rte_bbdev_dec_op **op,
27599e3ffd38SHernan Vargas 		uint16_t desc_offset)
27609e3ffd38SHernan Vargas {
27619e3ffd38SHernan Vargas 	union agx100_dma_desc *desc;
27629e3ffd38SHernan Vargas 	int desc_error;
27639e3ffd38SHernan Vargas 
27649e3ffd38SHernan Vargas 	/* Set descriptor. */
27659e3ffd38SHernan Vargas 	desc = agx100_get_desc(q, desc_offset);
27669e3ffd38SHernan Vargas 	/* Verify done bit is set. */
27679e3ffd38SHernan Vargas 	if (desc->dec_req.done == 0)
27689e3ffd38SHernan Vargas 		return -1;
27699e3ffd38SHernan Vargas 
27709e3ffd38SHernan Vargas 	/* make sure the response is read atomically. */
27719e3ffd38SHernan Vargas 	rte_smp_rmb();
27729e3ffd38SHernan Vargas 
27739e3ffd38SHernan Vargas #ifdef RTE_LIBRTE_BBDEV_DEBUG
27749e3ffd38SHernan Vargas 	agx100_print_dma_dec_desc_debug_info(desc);
27759e3ffd38SHernan Vargas #endif
27769e3ffd38SHernan Vargas 
27779e3ffd38SHernan Vargas 	*op = desc->dec_req.op_addr;
27789e3ffd38SHernan Vargas 
27799e3ffd38SHernan Vargas 	if (check_bit((*op)->ldpc_dec.op_flags, RTE_BBDEV_LDPC_INTERNAL_HARQ_MEMORY_LOOPBACK)) {
27809e3ffd38SHernan Vargas 		(*op)->status = 0;
27819e3ffd38SHernan Vargas 		return 1;
27829e3ffd38SHernan Vargas 	}
27839e3ffd38SHernan Vargas 
27849e3ffd38SHernan Vargas 	/* FPGA reports iterations based on round-up minus 1. */
27859e3ffd38SHernan Vargas 	(*op)->ldpc_dec.iter_count = desc->dec_req.max_iter_ret + 1;
27869e3ffd38SHernan Vargas 
27879e3ffd38SHernan Vargas 	/* CRC Check criteria. */
27889e3ffd38SHernan Vargas 	if (desc->dec_req.crc24b_ind && !(desc->dec_req.cb_crc_all_pass))
27899e3ffd38SHernan Vargas 		(*op)->status = 1 << RTE_BBDEV_CRC_ERROR;
27909e3ffd38SHernan Vargas 
27919e3ffd38SHernan Vargas 	/* et_pass = 0 when decoder fails. */
27929e3ffd38SHernan Vargas 	(*op)->status |= !(desc->dec_req.cb_all_et_pass) << RTE_BBDEV_SYNDROME_ERROR;
27939e3ffd38SHernan Vargas 
27949e3ffd38SHernan Vargas 	/* Check the descriptor error field, return 1 on error. */
27959e3ffd38SHernan Vargas 	desc_error = agx100_check_desc_error(desc->dec_req.error_code,
27969e3ffd38SHernan Vargas 			desc->dec_req.error_msg);
27979e3ffd38SHernan Vargas 
27989e3ffd38SHernan Vargas 	(*op)->status |= desc_error << RTE_BBDEV_DATA_ERROR;
27999e3ffd38SHernan Vargas 	return 1;
28009e3ffd38SHernan Vargas }
28019e3ffd38SHernan Vargas 
280244dc6faaSNicolas Chautru static uint16_t
280310829ff2SHernan Vargas fpga_5gnr_dequeue_ldpc_enc(struct rte_bbdev_queue_data *q_data,
280444dc6faaSNicolas Chautru 		struct rte_bbdev_enc_op **ops, uint16_t num)
280544dc6faaSNicolas Chautru {
280610829ff2SHernan Vargas 	struct fpga_5gnr_queue *q = q_data->queue_private;
280744dc6faaSNicolas Chautru 	uint32_t avail = (q->tail - q->head_free_desc) & q->sw_ring_wrap_mask;
280844dc6faaSNicolas Chautru 	uint16_t i;
280944dc6faaSNicolas Chautru 	uint16_t dequeued_cbs = 0;
281044dc6faaSNicolas Chautru 	int ret;
281144dc6faaSNicolas Chautru 
281244dc6faaSNicolas Chautru 	for (i = 0; (i < num) && (dequeued_cbs < avail); ++i) {
28139e3ffd38SHernan Vargas 		if (q->d->fpga_variant == VC_5GNR_FPGA_VARIANT)
2814c750d277SHernan Vargas 			ret = vc_5gnr_dequeue_ldpc_enc_one_op_cb(q, &ops[i], dequeued_cbs);
28159e3ffd38SHernan Vargas 		else
28169e3ffd38SHernan Vargas 			ret = agx100_dequeue_ldpc_enc_one_op_cb(q, &ops[i], dequeued_cbs);
281744dc6faaSNicolas Chautru 
281844dc6faaSNicolas Chautru 		if (ret < 0)
281944dc6faaSNicolas Chautru 			break;
282044dc6faaSNicolas Chautru 
282144dc6faaSNicolas Chautru 		dequeued_cbs += ret;
282244dc6faaSNicolas Chautru 
282344dc6faaSNicolas Chautru 		rte_bbdev_log_debug("dequeuing enc ops [%d/%d] | head %d | tail %d",
282444dc6faaSNicolas Chautru 				dequeued_cbs, num, q->head_free_desc, q->tail);
282544dc6faaSNicolas Chautru 	}
282644dc6faaSNicolas Chautru 
282744dc6faaSNicolas Chautru 	/* Update head */
28289e3ffd38SHernan Vargas 	q->head_free_desc = fpga_5gnr_desc_idx(q, dequeued_cbs);
282944dc6faaSNicolas Chautru 
283044dc6faaSNicolas Chautru 	/* Update stats */
283144dc6faaSNicolas Chautru 	q_data->queue_stats.dequeued_count += i;
283244dc6faaSNicolas Chautru 
283344dc6faaSNicolas Chautru 	return i;
283444dc6faaSNicolas Chautru }
283544dc6faaSNicolas Chautru 
283644dc6faaSNicolas Chautru static uint16_t
283710829ff2SHernan Vargas fpga_5gnr_dequeue_ldpc_dec(struct rte_bbdev_queue_data *q_data,
283844dc6faaSNicolas Chautru 		struct rte_bbdev_dec_op **ops, uint16_t num)
283944dc6faaSNicolas Chautru {
284010829ff2SHernan Vargas 	struct fpga_5gnr_queue *q = q_data->queue_private;
284144dc6faaSNicolas Chautru 	uint32_t avail = (q->tail - q->head_free_desc) & q->sw_ring_wrap_mask;
284244dc6faaSNicolas Chautru 	uint16_t i;
284344dc6faaSNicolas Chautru 	uint16_t dequeued_cbs = 0;
284444dc6faaSNicolas Chautru 	int ret;
284544dc6faaSNicolas Chautru 
284644dc6faaSNicolas Chautru 	for (i = 0; (i < num) && (dequeued_cbs < avail); ++i) {
28479e3ffd38SHernan Vargas 		if (q->d->fpga_variant == VC_5GNR_FPGA_VARIANT)
2848c750d277SHernan Vargas 			ret = vc_5gnr_dequeue_ldpc_dec_one_op_cb(q, &ops[i], dequeued_cbs);
28499e3ffd38SHernan Vargas 		else
28509e3ffd38SHernan Vargas 			ret = agx100_dequeue_ldpc_dec_one_op_cb(q, &ops[i], dequeued_cbs);
285144dc6faaSNicolas Chautru 
285244dc6faaSNicolas Chautru 		if (ret < 0)
285344dc6faaSNicolas Chautru 			break;
285444dc6faaSNicolas Chautru 
285544dc6faaSNicolas Chautru 		dequeued_cbs += ret;
285644dc6faaSNicolas Chautru 
285744dc6faaSNicolas Chautru 		rte_bbdev_log_debug("dequeuing dec ops [%d/%d] | head %d | tail %d",
285844dc6faaSNicolas Chautru 				dequeued_cbs, num, q->head_free_desc, q->tail);
285944dc6faaSNicolas Chautru 	}
286044dc6faaSNicolas Chautru 
286144dc6faaSNicolas Chautru 	/* Update head */
28629e3ffd38SHernan Vargas 	q->head_free_desc = fpga_5gnr_desc_idx(q, dequeued_cbs);
286344dc6faaSNicolas Chautru 
286444dc6faaSNicolas Chautru 	/* Update stats */
286544dc6faaSNicolas Chautru 	q_data->queue_stats.dequeued_count += i;
286644dc6faaSNicolas Chautru 
286744dc6faaSNicolas Chautru 	return i;
286844dc6faaSNicolas Chautru }
286944dc6faaSNicolas Chautru 
28700b5927cbSNicolas Chautru 
28710b5927cbSNicolas Chautru /* Initialization Function */
28720b5927cbSNicolas Chautru static void
28730b5927cbSNicolas Chautru fpga_5gnr_fec_init(struct rte_bbdev *dev, struct rte_pci_driver *drv)
28740b5927cbSNicolas Chautru {
28750b5927cbSNicolas Chautru 	struct rte_pci_device *pci_dev = RTE_DEV_TO_PCI(dev->device);
28760b5927cbSNicolas Chautru 
287710829ff2SHernan Vargas 	dev->dev_ops = &fpga_5gnr_ops;
287810829ff2SHernan Vargas 	dev->enqueue_ldpc_enc_ops = fpga_5gnr_enqueue_ldpc_enc;
287910829ff2SHernan Vargas 	dev->enqueue_ldpc_dec_ops = fpga_5gnr_enqueue_ldpc_dec;
288010829ff2SHernan Vargas 	dev->dequeue_ldpc_enc_ops = fpga_5gnr_dequeue_ldpc_enc;
288110829ff2SHernan Vargas 	dev->dequeue_ldpc_dec_ops = fpga_5gnr_dequeue_ldpc_dec;
28820b5927cbSNicolas Chautru 
28839e3ffd38SHernan Vargas 	/* Device variant specific handling. */
28849e3ffd38SHernan Vargas 	if ((pci_dev->id.device_id == AGX100_PF_DEVICE_ID) ||
28859e3ffd38SHernan Vargas 			(pci_dev->id.device_id == AGX100_VF_DEVICE_ID)) {
28869e3ffd38SHernan Vargas 		((struct fpga_5gnr_fec_device *) dev->data->dev_private)->fpga_variant =
28879e3ffd38SHernan Vargas 				AGX100_FPGA_VARIANT;
28889e3ffd38SHernan Vargas 		((struct fpga_5gnr_fec_device *) dev->data->dev_private)->pf_device =
28899e3ffd38SHernan Vargas 				!strcmp(drv->driver.name, RTE_STR(FPGA_5GNR_FEC_PF_DRIVER_NAME));
28909e3ffd38SHernan Vargas 		((struct fpga_5gnr_fec_device *) dev->data->dev_private)->mmio_base =
28919e3ffd38SHernan Vargas 				pci_dev->mem_resource[0].addr;
28929e3ffd38SHernan Vargas 		/* Maximum number of queues possible for this device. */
28939e3ffd38SHernan Vargas 		((struct fpga_5gnr_fec_device *) dev->data->dev_private)->total_num_queues =
28949e3ffd38SHernan Vargas 				fpga_5gnr_reg_read_32(pci_dev->mem_resource[0].addr,
28959e3ffd38SHernan Vargas 				FPGA_5GNR_FEC_VERSION_ID) >> 24;
28969e3ffd38SHernan Vargas 	} else {
28979e3ffd38SHernan Vargas 		((struct fpga_5gnr_fec_device *) dev->data->dev_private)->fpga_variant =
28989e3ffd38SHernan Vargas 				VC_5GNR_FPGA_VARIANT;
28990b5927cbSNicolas Chautru 		((struct fpga_5gnr_fec_device *) dev->data->dev_private)->pf_device =
290010829ff2SHernan Vargas 				!strcmp(drv->driver.name, RTE_STR(FPGA_5GNR_FEC_PF_DRIVER_NAME));
29010b5927cbSNicolas Chautru 		((struct fpga_5gnr_fec_device *) dev->data->dev_private)->mmio_base =
29020b5927cbSNicolas Chautru 				pci_dev->mem_resource[0].addr;
290399f09224SHernan Vargas 		((struct fpga_5gnr_fec_device *) dev->data->dev_private)->total_num_queues =
290499f09224SHernan Vargas 				VC_5GNR_TOTAL_NUM_QUEUES;
29059e3ffd38SHernan Vargas 	}
29060b5927cbSNicolas Chautru 
29070b5927cbSNicolas Chautru 	rte_bbdev_log_debug(
29080b5927cbSNicolas Chautru 			"Init device %s [%s] @ virtaddr %p phyaddr %#"PRIx64,
2909e309e920SMaxime Coquelin 			drv->driver.name, dev->data->name,
29100b5927cbSNicolas Chautru 			(void *)pci_dev->mem_resource[0].addr,
29110b5927cbSNicolas Chautru 			pci_dev->mem_resource[0].phys_addr);
29120b5927cbSNicolas Chautru }
29130b5927cbSNicolas Chautru 
29140b5927cbSNicolas Chautru static int
29150b5927cbSNicolas Chautru fpga_5gnr_fec_probe(struct rte_pci_driver *pci_drv,
29160b5927cbSNicolas Chautru 	struct rte_pci_device *pci_dev)
29170b5927cbSNicolas Chautru {
29180b5927cbSNicolas Chautru 	struct rte_bbdev *bbdev = NULL;
29190b5927cbSNicolas Chautru 	char dev_name[RTE_BBDEV_NAME_MAX_LEN];
29209e3ffd38SHernan Vargas 	struct fpga_5gnr_fec_device *d;
29210b5927cbSNicolas Chautru 
29220b5927cbSNicolas Chautru 	if (pci_dev == NULL) {
29230b5927cbSNicolas Chautru 		rte_bbdev_log(ERR, "NULL PCI device");
29240b5927cbSNicolas Chautru 		return -EINVAL;
29250b5927cbSNicolas Chautru 	}
29260b5927cbSNicolas Chautru 
29270b5927cbSNicolas Chautru 	rte_pci_device_name(&pci_dev->addr, dev_name, sizeof(dev_name));
29280b5927cbSNicolas Chautru 
29290b5927cbSNicolas Chautru 	/* Allocate memory to be used privately by drivers */
29300b5927cbSNicolas Chautru 	bbdev = rte_bbdev_allocate(pci_dev->device.name);
29310b5927cbSNicolas Chautru 	if (bbdev == NULL)
29320b5927cbSNicolas Chautru 		return -ENODEV;
29330b5927cbSNicolas Chautru 
29340b5927cbSNicolas Chautru 	/* allocate device private memory */
29350b5927cbSNicolas Chautru 	bbdev->data->dev_private = rte_zmalloc_socket(dev_name,
29360b5927cbSNicolas Chautru 			sizeof(struct fpga_5gnr_fec_device),
29370b5927cbSNicolas Chautru 			RTE_CACHE_LINE_SIZE,
29380b5927cbSNicolas Chautru 			pci_dev->device.numa_node);
29390b5927cbSNicolas Chautru 
29400b5927cbSNicolas Chautru 	if (bbdev->data->dev_private == NULL) {
29410b5927cbSNicolas Chautru 		rte_bbdev_log(CRIT,
29420b5927cbSNicolas Chautru 				"Allocate of %zu bytes for device \"%s\" failed",
29430b5927cbSNicolas Chautru 				sizeof(struct fpga_5gnr_fec_device), dev_name);
29440b5927cbSNicolas Chautru 				rte_bbdev_release(bbdev);
29450b5927cbSNicolas Chautru 			return -ENOMEM;
29460b5927cbSNicolas Chautru 	}
29470b5927cbSNicolas Chautru 
29480b5927cbSNicolas Chautru 	/* Fill HW specific part of device structure */
29490b5927cbSNicolas Chautru 	bbdev->device = &pci_dev->device;
2950d61138d4SHarman Kalra 	bbdev->intr_handle = pci_dev->intr_handle;
29510b5927cbSNicolas Chautru 	bbdev->data->socket_id = pci_dev->device.numa_node;
29520b5927cbSNicolas Chautru 
295310829ff2SHernan Vargas 	/* Invoke FPGA 5GNR FEC device initialization function */
29540b5927cbSNicolas Chautru 	fpga_5gnr_fec_init(bbdev, pci_drv);
29550b5927cbSNicolas Chautru 
29560b5927cbSNicolas Chautru 	rte_bbdev_log_debug("bbdev id = %u [%s]",
29570b5927cbSNicolas Chautru 			bbdev->data->dev_id, dev_name);
29580b5927cbSNicolas Chautru 
29599e3ffd38SHernan Vargas 	d = bbdev->data->dev_private;
29609e3ffd38SHernan Vargas 	if (d->fpga_variant == VC_5GNR_FPGA_VARIANT) {
2961c750d277SHernan Vargas 		uint32_t version_id = fpga_5gnr_reg_read_32(d->mmio_base, FPGA_5GNR_FEC_VERSION_ID);
2962c750d277SHernan Vargas 		rte_bbdev_log(INFO, "Vista Creek FPGA RTL v%u.%u",
296311b0a112SNicolas Chautru 				((uint16_t)(version_id >> 16)), ((uint16_t)version_id));
29649e3ffd38SHernan Vargas 	} else {
29659e3ffd38SHernan Vargas 		uint32_t version_num_queues = fpga_5gnr_reg_read_32(d->mmio_base,
29669e3ffd38SHernan Vargas 				FPGA_5GNR_FEC_VERSION_ID);
29679e3ffd38SHernan Vargas 		uint8_t major_version_id = version_num_queues >> 16;
29689e3ffd38SHernan Vargas 		uint8_t minor_version_id = version_num_queues >> 8;
29699e3ffd38SHernan Vargas 		uint8_t patch_id = version_num_queues;
29709e3ffd38SHernan Vargas 
29719e3ffd38SHernan Vargas 		rte_bbdev_log(INFO, "AGX100 RTL v%u.%u.%u",
29729e3ffd38SHernan Vargas 				major_version_id, minor_version_id, patch_id);
29739e3ffd38SHernan Vargas 	}
297411b0a112SNicolas Chautru 
297511b0a112SNicolas Chautru #ifdef RTE_LIBRTE_BBDEV_DEBUG
29769e3ffd38SHernan Vargas 	print_static_reg_debug_info(d->mmio_base, d->fpga_variant);
297711b0a112SNicolas Chautru #endif
29780b5927cbSNicolas Chautru 	return 0;
29790b5927cbSNicolas Chautru }
29800b5927cbSNicolas Chautru 
29810b5927cbSNicolas Chautru static int
29820b5927cbSNicolas Chautru fpga_5gnr_fec_remove(struct rte_pci_device *pci_dev)
29830b5927cbSNicolas Chautru {
29840b5927cbSNicolas Chautru 	struct rte_bbdev *bbdev;
29850b5927cbSNicolas Chautru 	int ret;
29860b5927cbSNicolas Chautru 	uint8_t dev_id;
29870b5927cbSNicolas Chautru 
29880b5927cbSNicolas Chautru 	if (pci_dev == NULL)
29890b5927cbSNicolas Chautru 		return -EINVAL;
29900b5927cbSNicolas Chautru 
29910b5927cbSNicolas Chautru 	/* Find device */
29920b5927cbSNicolas Chautru 	bbdev = rte_bbdev_get_named_dev(pci_dev->device.name);
29930b5927cbSNicolas Chautru 	if (bbdev == NULL) {
29940b5927cbSNicolas Chautru 		rte_bbdev_log(CRIT,
29950b5927cbSNicolas Chautru 				"Couldn't find HW dev \"%s\" to uninitialise it",
29960b5927cbSNicolas Chautru 				pci_dev->device.name);
29970b5927cbSNicolas Chautru 		return -ENODEV;
29980b5927cbSNicolas Chautru 	}
29990b5927cbSNicolas Chautru 	dev_id = bbdev->data->dev_id;
30000b5927cbSNicolas Chautru 
30010b5927cbSNicolas Chautru 	/* free device private memory before close */
30020b5927cbSNicolas Chautru 	rte_free(bbdev->data->dev_private);
30030b5927cbSNicolas Chautru 
30040b5927cbSNicolas Chautru 	/* Close device */
30050b5927cbSNicolas Chautru 	ret = rte_bbdev_close(dev_id);
30060b5927cbSNicolas Chautru 	if (ret < 0)
30070b5927cbSNicolas Chautru 		rte_bbdev_log(ERR,
30080b5927cbSNicolas Chautru 				"Device %i failed to close during uninit: %i",
30090b5927cbSNicolas Chautru 				dev_id, ret);
30100b5927cbSNicolas Chautru 
30110b5927cbSNicolas Chautru 	/* release bbdev from library */
30120b5927cbSNicolas Chautru 	ret = rte_bbdev_release(bbdev);
30130b5927cbSNicolas Chautru 	if (ret)
301410829ff2SHernan Vargas 		rte_bbdev_log(ERR, "Device %i failed to uninit: %i", dev_id, ret);
30150b5927cbSNicolas Chautru 
30160b5927cbSNicolas Chautru 	rte_bbdev_log_debug("Destroyed bbdev = %u", dev_id);
30170b5927cbSNicolas Chautru 
30180b5927cbSNicolas Chautru 	return 0;
30190b5927cbSNicolas Chautru }
30200b5927cbSNicolas Chautru 
30212d430643SNicolas Chautru static inline void
302210829ff2SHernan Vargas fpga_5gnr_set_default_conf(struct rte_fpga_5gnr_fec_conf *def_conf)
30232d430643SNicolas Chautru {
30242d430643SNicolas Chautru 	/* clear default configuration before initialization */
30257adbb468SMaxime Coquelin 	memset(def_conf, 0, sizeof(struct rte_fpga_5gnr_fec_conf));
30262d430643SNicolas Chautru 	/* Set pf mode to true */
30272d430643SNicolas Chautru 	def_conf->pf_mode_en = true;
30282d430643SNicolas Chautru 
30292d430643SNicolas Chautru 	/* Set ratio between UL and DL to 1:1 (unit of weight is 3 CBs) */
30302d430643SNicolas Chautru 	def_conf->ul_bandwidth = 3;
30312d430643SNicolas Chautru 	def_conf->dl_bandwidth = 3;
30322d430643SNicolas Chautru 
30332d430643SNicolas Chautru 	/* Set Load Balance Factor to 64 */
30342d430643SNicolas Chautru 	def_conf->dl_load_balance = 64;
30352d430643SNicolas Chautru 	def_conf->ul_load_balance = 64;
30362d430643SNicolas Chautru }
30372d430643SNicolas Chautru 
3038c750d277SHernan Vargas /* Initial configuration of Vista Creek device. */
3039c750d277SHernan Vargas static int vc_5gnr_configure(const char *dev_name, const struct rte_fpga_5gnr_fec_conf *conf)
30402d430643SNicolas Chautru {
30412d430643SNicolas Chautru 	uint32_t payload_32, address;
30422d430643SNicolas Chautru 	uint16_t payload_16;
30432d430643SNicolas Chautru 	uint8_t payload_8;
30442d430643SNicolas Chautru 	uint16_t q_id, vf_id, total_q_id, total_ul_q_id, total_dl_q_id;
30452d430643SNicolas Chautru 	struct rte_bbdev *bbdev = rte_bbdev_get_named_dev(dev_name);
30467adbb468SMaxime Coquelin 	struct rte_fpga_5gnr_fec_conf def_conf;
30472d430643SNicolas Chautru 
30482d430643SNicolas Chautru 	if (bbdev == NULL) {
30492d430643SNicolas Chautru 		rte_bbdev_log(ERR,
30502d430643SNicolas Chautru 				"Invalid dev_name (%s), or device is not yet initialised",
30512d430643SNicolas Chautru 				dev_name);
30522d430643SNicolas Chautru 		return -ENODEV;
30532d430643SNicolas Chautru 	}
30542d430643SNicolas Chautru 
30552d430643SNicolas Chautru 	struct fpga_5gnr_fec_device *d = bbdev->data->dev_private;
30562d430643SNicolas Chautru 
30572d430643SNicolas Chautru 	if (conf == NULL) {
3058c750d277SHernan Vargas 		rte_bbdev_log(ERR, "VC FPGA Configuration was not provided.");
3059c750d277SHernan Vargas 		rte_bbdev_log(ERR, "Default configuration will be loaded.");
306010829ff2SHernan Vargas 		fpga_5gnr_set_default_conf(&def_conf);
30612d430643SNicolas Chautru 		conf = &def_conf;
30622d430643SNicolas Chautru 	}
30632d430643SNicolas Chautru 
30642d430643SNicolas Chautru 	/*
30652d430643SNicolas Chautru 	 * Configure UL:DL ratio.
30662d430643SNicolas Chautru 	 * [7:0]: UL weight
30672d430643SNicolas Chautru 	 * [15:8]: DL weight
30682d430643SNicolas Chautru 	 */
30692d430643SNicolas Chautru 	payload_16 = (conf->dl_bandwidth << 8) | conf->ul_bandwidth;
3070c750d277SHernan Vargas 	address = VC_5GNR_CONFIGURATION;
307110829ff2SHernan Vargas 	fpga_5gnr_reg_write_16(d->mmio_base, address, payload_16);
30722d430643SNicolas Chautru 
30732d430643SNicolas Chautru 	/* Clear all queues registers */
307410829ff2SHernan Vargas 	payload_32 = FPGA_5GNR_INVALID_HW_QUEUE_ID;
307599f09224SHernan Vargas 	for (q_id = 0; q_id < d->total_num_queues; ++q_id) {
3076c750d277SHernan Vargas 		address = (q_id << 2) + VC_5GNR_QUEUE_MAP;
307710829ff2SHernan Vargas 		fpga_5gnr_reg_write_32(d->mmio_base, address, payload_32);
30782d430643SNicolas Chautru 	}
30792d430643SNicolas Chautru 
30802d430643SNicolas Chautru 	/*
30812d430643SNicolas Chautru 	 * If PF mode is enabled allocate all queues for PF only.
30822d430643SNicolas Chautru 	 *
30832d430643SNicolas Chautru 	 * For VF mode each VF can have different number of UL and DL queues.
3084c750d277SHernan Vargas 	 * Total number of queues to configure cannot exceed VC FPGA
30852d430643SNicolas Chautru 	 * capabilities - 64 queues - 32 queues for UL and 32 queues for DL.
30862d430643SNicolas Chautru 	 * Queues mapping is done according to configuration:
30872d430643SNicolas Chautru 	 *
30882d430643SNicolas Chautru 	 * UL queues:
30892d430643SNicolas Chautru 	 * |                Q_ID              | VF_ID |
30902d430643SNicolas Chautru 	 * |                 0                |   0   |
30912d430643SNicolas Chautru 	 * |                ...               |   0   |
30922d430643SNicolas Chautru 	 * | conf->vf_dl_queues_number[0] - 1 |   0   |
30932d430643SNicolas Chautru 	 * | conf->vf_dl_queues_number[0]     |   1   |
30942d430643SNicolas Chautru 	 * |                ...               |   1   |
30952d430643SNicolas Chautru 	 * | conf->vf_dl_queues_number[1] - 1 |   1   |
30962d430643SNicolas Chautru 	 * |                ...               |  ...  |
30972d430643SNicolas Chautru 	 * | conf->vf_dl_queues_number[7] - 1 |   7   |
30982d430643SNicolas Chautru 	 *
30992d430643SNicolas Chautru 	 * DL queues:
31002d430643SNicolas Chautru 	 * |                Q_ID              | VF_ID |
31012d430643SNicolas Chautru 	 * |                 32               |   0   |
31022d430643SNicolas Chautru 	 * |                ...               |   0   |
31032d430643SNicolas Chautru 	 * | conf->vf_ul_queues_number[0] - 1 |   0   |
31042d430643SNicolas Chautru 	 * | conf->vf_ul_queues_number[0]     |   1   |
31052d430643SNicolas Chautru 	 * |                ...               |   1   |
31062d430643SNicolas Chautru 	 * | conf->vf_ul_queues_number[1] - 1 |   1   |
31072d430643SNicolas Chautru 	 * |                ...               |  ...  |
31082d430643SNicolas Chautru 	 * | conf->vf_ul_queues_number[7] - 1 |   7   |
31092d430643SNicolas Chautru 	 *
31102d430643SNicolas Chautru 	 * Example of configuration:
31112d430643SNicolas Chautru 	 * conf->vf_ul_queues_number[0] = 4;  -> 4 UL queues for VF0
31122d430643SNicolas Chautru 	 * conf->vf_dl_queues_number[0] = 4;  -> 4 DL queues for VF0
31132d430643SNicolas Chautru 	 * conf->vf_ul_queues_number[1] = 2;  -> 2 UL queues for VF1
31142d430643SNicolas Chautru 	 * conf->vf_dl_queues_number[1] = 2;  -> 2 DL queues for VF1
31152d430643SNicolas Chautru 	 *
31162d430643SNicolas Chautru 	 * UL:
31172d430643SNicolas Chautru 	 * | Q_ID | VF_ID |
31182d430643SNicolas Chautru 	 * |   0  |   0   |
31192d430643SNicolas Chautru 	 * |   1  |   0   |
31202d430643SNicolas Chautru 	 * |   2  |   0   |
31212d430643SNicolas Chautru 	 * |   3  |   0   |
31222d430643SNicolas Chautru 	 * |   4  |   1   |
31232d430643SNicolas Chautru 	 * |   5  |   1   |
31242d430643SNicolas Chautru 	 *
31252d430643SNicolas Chautru 	 * DL:
31262d430643SNicolas Chautru 	 * | Q_ID | VF_ID |
31272d430643SNicolas Chautru 	 * |  32  |   0   |
31282d430643SNicolas Chautru 	 * |  33  |   0   |
31292d430643SNicolas Chautru 	 * |  34  |   0   |
31302d430643SNicolas Chautru 	 * |  35  |   0   |
31312d430643SNicolas Chautru 	 * |  36  |   1   |
31322d430643SNicolas Chautru 	 * |  37  |   1   |
31332d430643SNicolas Chautru 	 */
31342d430643SNicolas Chautru 	if (conf->pf_mode_en) {
31352d430643SNicolas Chautru 		payload_32 = 0x1;
313699f09224SHernan Vargas 		for (q_id = 0; q_id < d->total_num_queues; ++q_id) {
3137c750d277SHernan Vargas 			address = (q_id << 2) + VC_5GNR_QUEUE_MAP;
313810829ff2SHernan Vargas 			fpga_5gnr_reg_write_32(d->mmio_base, address, payload_32);
31392d430643SNicolas Chautru 		}
31402d430643SNicolas Chautru 	} else {
31412d430643SNicolas Chautru 		/* Calculate total number of UL and DL queues to configure */
31422d430643SNicolas Chautru 		total_ul_q_id = total_dl_q_id = 0;
31432d430643SNicolas Chautru 		for (vf_id = 0; vf_id < FPGA_5GNR_FEC_NUM_VFS; ++vf_id) {
31442d430643SNicolas Chautru 			total_ul_q_id += conf->vf_ul_queues_number[vf_id];
31452d430643SNicolas Chautru 			total_dl_q_id += conf->vf_dl_queues_number[vf_id];
31462d430643SNicolas Chautru 		}
31472d430643SNicolas Chautru 		total_q_id = total_dl_q_id + total_ul_q_id;
31482d430643SNicolas Chautru 		/*
31492d430643SNicolas Chautru 		 * Check if total number of queues to configure does not exceed
31502d430643SNicolas Chautru 		 * FPGA capabilities (64 queues - 32 UL and 32 DL queues)
31512d430643SNicolas Chautru 		 */
3152c750d277SHernan Vargas 		if ((total_ul_q_id > VC_5GNR_NUM_UL_QUEUES) ||
3153c750d277SHernan Vargas 			(total_dl_q_id > VC_5GNR_NUM_DL_QUEUES) ||
315499f09224SHernan Vargas 			(total_q_id > d->total_num_queues)) {
31552d430643SNicolas Chautru 			rte_bbdev_log(ERR,
3156c750d277SHernan Vargas 					"VC 5GNR FPGA Configuration failed. Too many queues to configure: UL_Q %u, DL_Q %u, FPGA_Q %u",
31572d430643SNicolas Chautru 					total_ul_q_id, total_dl_q_id,
315899f09224SHernan Vargas 					d->total_num_queues);
31592d430643SNicolas Chautru 			return -EINVAL;
31602d430643SNicolas Chautru 		}
31612d430643SNicolas Chautru 		total_ul_q_id = 0;
31622d430643SNicolas Chautru 		for (vf_id = 0; vf_id < FPGA_5GNR_FEC_NUM_VFS; ++vf_id) {
31632d430643SNicolas Chautru 			for (q_id = 0; q_id < conf->vf_ul_queues_number[vf_id];
31642d430643SNicolas Chautru 					++q_id, ++total_ul_q_id) {
3165c750d277SHernan Vargas 				address = (total_ul_q_id << 2) + VC_5GNR_QUEUE_MAP;
31662d430643SNicolas Chautru 				payload_32 = ((0x80 + vf_id) << 16) | 0x1;
316710829ff2SHernan Vargas 				fpga_5gnr_reg_write_32(d->mmio_base, address,
31682d430643SNicolas Chautru 						payload_32);
31692d430643SNicolas Chautru 			}
31702d430643SNicolas Chautru 		}
31712d430643SNicolas Chautru 		total_dl_q_id = 0;
31722d430643SNicolas Chautru 		for (vf_id = 0; vf_id < FPGA_5GNR_FEC_NUM_VFS; ++vf_id) {
31732d430643SNicolas Chautru 			for (q_id = 0; q_id < conf->vf_dl_queues_number[vf_id];
31742d430643SNicolas Chautru 					++q_id, ++total_dl_q_id) {
3175c750d277SHernan Vargas 				address = ((total_dl_q_id + VC_5GNR_NUM_UL_QUEUES)
3176c750d277SHernan Vargas 						<< 2) + VC_5GNR_QUEUE_MAP;
31772d430643SNicolas Chautru 				payload_32 = ((0x80 + vf_id) << 16) | 0x1;
317810829ff2SHernan Vargas 				fpga_5gnr_reg_write_32(d->mmio_base, address,
31792d430643SNicolas Chautru 						payload_32);
31802d430643SNicolas Chautru 			}
31812d430643SNicolas Chautru 		}
31822d430643SNicolas Chautru 	}
31832d430643SNicolas Chautru 
31842d430643SNicolas Chautru 	/* Setting Load Balance Factor */
31852d430643SNicolas Chautru 	payload_16 = (conf->dl_load_balance << 8) | (conf->ul_load_balance);
31862d430643SNicolas Chautru 	address = FPGA_5GNR_FEC_LOAD_BALANCE_FACTOR;
318710829ff2SHernan Vargas 	fpga_5gnr_reg_write_16(d->mmio_base, address, payload_16);
31882d430643SNicolas Chautru 
31892d430643SNicolas Chautru 	/* Setting length of ring descriptor entry */
319010829ff2SHernan Vargas 	payload_16 = FPGA_5GNR_RING_DESC_ENTRY_LENGTH;
31912d430643SNicolas Chautru 	address = FPGA_5GNR_FEC_RING_DESC_LEN;
319210829ff2SHernan Vargas 	fpga_5gnr_reg_write_16(d->mmio_base, address, payload_16);
31932d430643SNicolas Chautru 
31942d430643SNicolas Chautru 	/* Queue PF/VF mapping table is ready */
31952d430643SNicolas Chautru 	payload_8 = 0x1;
31962d430643SNicolas Chautru 	address = FPGA_5GNR_FEC_QUEUE_PF_VF_MAP_DONE;
319710829ff2SHernan Vargas 	fpga_5gnr_reg_write_8(d->mmio_base, address, payload_8);
31982d430643SNicolas Chautru 
3199c750d277SHernan Vargas 	rte_bbdev_log_debug("PF Vista Creek 5GNR FPGA configuration complete for %s", dev_name);
32002d430643SNicolas Chautru 
32012d430643SNicolas Chautru #ifdef RTE_LIBRTE_BBDEV_DEBUG
32029e3ffd38SHernan Vargas 	print_static_reg_debug_info(d->mmio_base, d->fpga_variant);
32039e3ffd38SHernan Vargas #endif
32049e3ffd38SHernan Vargas 	return 0;
32059e3ffd38SHernan Vargas }
32069e3ffd38SHernan Vargas 
32079e3ffd38SHernan Vargas /* Initial configuration of AGX100 device. */
32089e3ffd38SHernan Vargas static int agx100_configure(const char *dev_name, const struct rte_fpga_5gnr_fec_conf *conf)
32099e3ffd38SHernan Vargas {
32109e3ffd38SHernan Vargas 	uint32_t payload_32, address;
32119e3ffd38SHernan Vargas 	uint16_t payload_16;
32129e3ffd38SHernan Vargas 	uint8_t payload_8;
32139e3ffd38SHernan Vargas 	uint16_t q_id, vf_id, total_q_id, total_ul_q_id, total_dl_q_id;
32149e3ffd38SHernan Vargas 	struct rte_bbdev *bbdev = rte_bbdev_get_named_dev(dev_name);
32159e3ffd38SHernan Vargas 	struct rte_fpga_5gnr_fec_conf def_conf;
32169e3ffd38SHernan Vargas 
32179e3ffd38SHernan Vargas 	if (bbdev == NULL) {
32189e3ffd38SHernan Vargas 		rte_bbdev_log(ERR,
32199e3ffd38SHernan Vargas 				"Invalid dev_name (%s), or device is not yet initialised",
32209e3ffd38SHernan Vargas 				dev_name);
32219e3ffd38SHernan Vargas 		return -ENODEV;
32229e3ffd38SHernan Vargas 	}
32239e3ffd38SHernan Vargas 
32249e3ffd38SHernan Vargas 	struct fpga_5gnr_fec_device *d = bbdev->data->dev_private;
32259e3ffd38SHernan Vargas 
32269e3ffd38SHernan Vargas 	if (conf == NULL) {
32279e3ffd38SHernan Vargas 		rte_bbdev_log(ERR, "AGX100 Configuration was not provided.");
32289e3ffd38SHernan Vargas 		rte_bbdev_log(ERR, "Default configuration will be loaded.");
32299e3ffd38SHernan Vargas 		fpga_5gnr_set_default_conf(&def_conf);
32309e3ffd38SHernan Vargas 		conf = &def_conf;
32319e3ffd38SHernan Vargas 	}
32329e3ffd38SHernan Vargas 
32339e3ffd38SHernan Vargas 	uint8_t total_num_queues = d->total_num_queues;
32349e3ffd38SHernan Vargas 	uint8_t num_ul_queues = total_num_queues >> 1;
32359e3ffd38SHernan Vargas 	uint8_t num_dl_queues = total_num_queues >> 1;
32369e3ffd38SHernan Vargas 
32379e3ffd38SHernan Vargas 	/* Clear all queues registers */
32389e3ffd38SHernan Vargas 	payload_32 = FPGA_5GNR_INVALID_HW_QUEUE_ID;
32399e3ffd38SHernan Vargas 	for (q_id = 0; q_id < total_num_queues; ++q_id) {
32409e3ffd38SHernan Vargas 		address = (q_id << 2) + AGX100_QUEUE_MAP;
32419e3ffd38SHernan Vargas 		fpga_5gnr_reg_write_32(d->mmio_base, address, payload_32);
32429e3ffd38SHernan Vargas 	}
32439e3ffd38SHernan Vargas 
32449e3ffd38SHernan Vargas 	/*
32459e3ffd38SHernan Vargas 	 * If PF mode is enabled allocate all queues for PF only.
32469e3ffd38SHernan Vargas 	 *
32479e3ffd38SHernan Vargas 	 * For VF mode each VF can have different number of UL and DL queues.
32489e3ffd38SHernan Vargas 	 * Total number of queues to configure cannot exceed AGX100
32499e3ffd38SHernan Vargas 	 * capabilities - 64 queues - 32 queues for UL and 32 queues for DL.
32509e3ffd38SHernan Vargas 	 * Queues mapping is done according to configuration:
32519e3ffd38SHernan Vargas 	 *
32529e3ffd38SHernan Vargas 	 * UL queues:
32539e3ffd38SHernan Vargas 	 * |                Q_ID              | VF_ID |
32549e3ffd38SHernan Vargas 	 * |                 0                |   0   |
32559e3ffd38SHernan Vargas 	 * |                ...               |   0   |
32569e3ffd38SHernan Vargas 	 * | conf->vf_dl_queues_number[0] - 1 |   0   |
32579e3ffd38SHernan Vargas 	 * | conf->vf_dl_queues_number[0]     |   1   |
32589e3ffd38SHernan Vargas 	 * |                ...               |   1   |
32599e3ffd38SHernan Vargas 	 * | conf->vf_dl_queues_number[1] - 1 |   1   |
32609e3ffd38SHernan Vargas 	 * |                ...               |  ...  |
32619e3ffd38SHernan Vargas 	 * | conf->vf_dl_queues_number[7] - 1 |   7   |
32629e3ffd38SHernan Vargas 	 *
32639e3ffd38SHernan Vargas 	 * DL queues:
32649e3ffd38SHernan Vargas 	 * |                Q_ID              | VF_ID |
32659e3ffd38SHernan Vargas 	 * |                 32               |   0   |
32669e3ffd38SHernan Vargas 	 * |                ...               |   0   |
32679e3ffd38SHernan Vargas 	 * | conf->vf_ul_queues_number[0] - 1 |   0   |
32689e3ffd38SHernan Vargas 	 * | conf->vf_ul_queues_number[0]     |   1   |
32699e3ffd38SHernan Vargas 	 * |                ...               |   1   |
32709e3ffd38SHernan Vargas 	 * | conf->vf_ul_queues_number[1] - 1 |   1   |
32719e3ffd38SHernan Vargas 	 * |                ...               |  ...  |
32729e3ffd38SHernan Vargas 	 * | conf->vf_ul_queues_number[7] - 1 |   7   |
32739e3ffd38SHernan Vargas 	 *
32749e3ffd38SHernan Vargas 	 * Example of configuration:
32759e3ffd38SHernan Vargas 	 * conf->vf_ul_queues_number[0] = 4;  -> 4 UL queues for VF0
32769e3ffd38SHernan Vargas 	 * conf->vf_dl_queues_number[0] = 4;  -> 4 DL queues for VF0
32779e3ffd38SHernan Vargas 	 * conf->vf_ul_queues_number[1] = 2;  -> 2 UL queues for VF1
32789e3ffd38SHernan Vargas 	 * conf->vf_dl_queues_number[1] = 2;  -> 2 DL queues for VF1
32799e3ffd38SHernan Vargas 	 *
32809e3ffd38SHernan Vargas 	 * UL:
32819e3ffd38SHernan Vargas 	 * | Q_ID | VF_ID |
32829e3ffd38SHernan Vargas 	 * |   0  |   0   |
32839e3ffd38SHernan Vargas 	 * |   1  |   0   |
32849e3ffd38SHernan Vargas 	 * |   2  |   0   |
32859e3ffd38SHernan Vargas 	 * |   3  |   0   |
32869e3ffd38SHernan Vargas 	 * |   4  |   1   |
32879e3ffd38SHernan Vargas 	 * |   5  |   1   |
32889e3ffd38SHernan Vargas 	 *
32899e3ffd38SHernan Vargas 	 * DL:
32909e3ffd38SHernan Vargas 	 * | Q_ID | VF_ID |
32919e3ffd38SHernan Vargas 	 * |  32  |   0   |
32929e3ffd38SHernan Vargas 	 * |  33  |   0   |
32939e3ffd38SHernan Vargas 	 * |  34  |   0   |
32949e3ffd38SHernan Vargas 	 * |  35  |   0   |
32959e3ffd38SHernan Vargas 	 * |  36  |   1   |
32969e3ffd38SHernan Vargas 	 * |  37  |   1   |
32979e3ffd38SHernan Vargas 	 */
32989e3ffd38SHernan Vargas 	if (conf->pf_mode_en) {
32999e3ffd38SHernan Vargas 		payload_32 = 0x1;
33009e3ffd38SHernan Vargas 		for (q_id = 0; q_id < total_num_queues; ++q_id) {
33019e3ffd38SHernan Vargas 			address = (q_id << 2) + AGX100_QUEUE_MAP;
33029e3ffd38SHernan Vargas 			fpga_5gnr_reg_write_32(d->mmio_base, address, payload_32);
33039e3ffd38SHernan Vargas 		}
33049e3ffd38SHernan Vargas 	} else {
33059e3ffd38SHernan Vargas 		/* Calculate total number of UL and DL queues to configure. */
33069e3ffd38SHernan Vargas 		total_ul_q_id = total_dl_q_id = 0;
33079e3ffd38SHernan Vargas 		for (vf_id = 0; vf_id < FPGA_5GNR_FEC_NUM_VFS; ++vf_id) {
33089e3ffd38SHernan Vargas 			total_ul_q_id += conf->vf_ul_queues_number[vf_id];
33099e3ffd38SHernan Vargas 			total_dl_q_id += conf->vf_dl_queues_number[vf_id];
33109e3ffd38SHernan Vargas 		}
33119e3ffd38SHernan Vargas 		total_q_id = total_dl_q_id + total_ul_q_id;
33129e3ffd38SHernan Vargas 		/*
33139e3ffd38SHernan Vargas 		 * Check if total number of queues to configure does not exceed
33149e3ffd38SHernan Vargas 		 * AGX100 capabilities (64 queues - 32 UL and 32 DL queues)
33159e3ffd38SHernan Vargas 		 */
33169e3ffd38SHernan Vargas 		if ((total_ul_q_id > num_ul_queues) ||
33179e3ffd38SHernan Vargas 				(total_dl_q_id > num_dl_queues) ||
33189e3ffd38SHernan Vargas 				(total_q_id > total_num_queues)) {
33199e3ffd38SHernan Vargas 			rte_bbdev_log(ERR,
33209e3ffd38SHernan Vargas 					"AGX100 Configuration failed. Too many queues to configure: UL_Q %u, DL_Q %u, AGX100_Q %u",
33219e3ffd38SHernan Vargas 					total_ul_q_id, total_dl_q_id,
33229e3ffd38SHernan Vargas 					total_num_queues);
33239e3ffd38SHernan Vargas 			return -EINVAL;
33249e3ffd38SHernan Vargas 		}
33259e3ffd38SHernan Vargas 		total_ul_q_id = 0;
33269e3ffd38SHernan Vargas 		for (vf_id = 0; vf_id < FPGA_5GNR_FEC_NUM_VFS; ++vf_id) {
33279e3ffd38SHernan Vargas 			for (q_id = 0; q_id < conf->vf_ul_queues_number[vf_id];
33289e3ffd38SHernan Vargas 					++q_id, ++total_ul_q_id) {
33299e3ffd38SHernan Vargas 				address = (total_ul_q_id << 2) + AGX100_QUEUE_MAP;
33309e3ffd38SHernan Vargas 				payload_32 = ((0x80 + vf_id) << 16) | 0x1;
33319e3ffd38SHernan Vargas 				fpga_5gnr_reg_write_32(d->mmio_base, address, payload_32);
33329e3ffd38SHernan Vargas 			}
33339e3ffd38SHernan Vargas 		}
33349e3ffd38SHernan Vargas 		total_dl_q_id = 0;
33359e3ffd38SHernan Vargas 		for (vf_id = 0; vf_id < FPGA_5GNR_FEC_NUM_VFS; ++vf_id) {
33369e3ffd38SHernan Vargas 			for (q_id = 0; q_id < conf->vf_dl_queues_number[vf_id];
33379e3ffd38SHernan Vargas 					++q_id, ++total_dl_q_id) {
33389e3ffd38SHernan Vargas 				address = ((total_dl_q_id + num_ul_queues)
33399e3ffd38SHernan Vargas 						<< 2) + AGX100_QUEUE_MAP;
33409e3ffd38SHernan Vargas 				payload_32 = ((0x80 + vf_id) << 16) | 0x1;
33419e3ffd38SHernan Vargas 				fpga_5gnr_reg_write_32(d->mmio_base, address, payload_32);
33429e3ffd38SHernan Vargas 			}
33439e3ffd38SHernan Vargas 		}
33449e3ffd38SHernan Vargas 	}
33459e3ffd38SHernan Vargas 
33469e3ffd38SHernan Vargas 	/* Setting Load Balance Factor. */
33479e3ffd38SHernan Vargas 	payload_16 = (conf->dl_load_balance << 8) | (conf->ul_load_balance);
33489e3ffd38SHernan Vargas 	address = FPGA_5GNR_FEC_LOAD_BALANCE_FACTOR;
33499e3ffd38SHernan Vargas 	fpga_5gnr_reg_write_16(d->mmio_base, address, payload_16);
33509e3ffd38SHernan Vargas 
33519e3ffd38SHernan Vargas 	/* Setting length of ring descriptor entry. */
33529e3ffd38SHernan Vargas 	payload_16 = FPGA_5GNR_RING_DESC_ENTRY_LENGTH;
33539e3ffd38SHernan Vargas 	address = FPGA_5GNR_FEC_RING_DESC_LEN;
33549e3ffd38SHernan Vargas 	fpga_5gnr_reg_write_16(d->mmio_base, address, payload_16);
33559e3ffd38SHernan Vargas 
33569e3ffd38SHernan Vargas 	/* Queue PF/VF mapping table is ready. */
33579e3ffd38SHernan Vargas 	payload_8 = 0x1;
33589e3ffd38SHernan Vargas 	address = FPGA_5GNR_FEC_QUEUE_PF_VF_MAP_DONE;
33599e3ffd38SHernan Vargas 	fpga_5gnr_reg_write_8(d->mmio_base, address, payload_8);
33609e3ffd38SHernan Vargas 
33619e3ffd38SHernan Vargas 	rte_bbdev_log_debug("PF AGX100 configuration complete for %s", dev_name);
33629e3ffd38SHernan Vargas 
33639e3ffd38SHernan Vargas #ifdef RTE_LIBRTE_BBDEV_DEBUG
33649e3ffd38SHernan Vargas 	print_static_reg_debug_info(d->mmio_base, d->fpga_variant);
33652d430643SNicolas Chautru #endif
33662d430643SNicolas Chautru 	return 0;
33672d430643SNicolas Chautru }
33682d430643SNicolas Chautru 
3369c750d277SHernan Vargas int rte_fpga_5gnr_fec_configure(const char *dev_name, const struct rte_fpga_5gnr_fec_conf *conf)
3370c750d277SHernan Vargas {
3371c750d277SHernan Vargas 	struct rte_bbdev *bbdev = rte_bbdev_get_named_dev(dev_name);
3372c750d277SHernan Vargas 	if (bbdev == NULL) {
3373c750d277SHernan Vargas 		rte_bbdev_log(ERR, "Invalid dev_name (%s), or device is not yet initialised",
3374c750d277SHernan Vargas 				dev_name);
3375c750d277SHernan Vargas 		return -ENODEV;
3376c750d277SHernan Vargas 	}
3377c750d277SHernan Vargas 	struct rte_pci_device *pci_dev = RTE_DEV_TO_PCI(bbdev->device);
3378f665790aSDavid Marchand 	rte_bbdev_log(INFO, "Configure dev id %x", pci_dev->id.device_id);
3379c750d277SHernan Vargas 	if (pci_dev->id.device_id == VC_5GNR_PF_DEVICE_ID)
3380c750d277SHernan Vargas 		return vc_5gnr_configure(dev_name, conf);
33819e3ffd38SHernan Vargas 	else if (pci_dev->id.device_id == AGX100_PF_DEVICE_ID)
33829e3ffd38SHernan Vargas 		return agx100_configure(dev_name, conf);
3383c750d277SHernan Vargas 
3384c750d277SHernan Vargas 	rte_bbdev_log(ERR, "Invalid device_id (%d)", pci_dev->id.device_id);
3385c750d277SHernan Vargas 	return -ENODEV;
3386c750d277SHernan Vargas }
3387c750d277SHernan Vargas 
33880b5927cbSNicolas Chautru /* FPGA 5GNR FEC PCI PF address map */
33890b5927cbSNicolas Chautru static struct rte_pci_id pci_id_fpga_5gnr_fec_pf_map[] = {
33900b5927cbSNicolas Chautru 	{
33919e3ffd38SHernan Vargas 		RTE_PCI_DEVICE(AGX100_VENDOR_ID, AGX100_PF_DEVICE_ID)
33929e3ffd38SHernan Vargas 	},
33939e3ffd38SHernan Vargas 	{
3394c750d277SHernan Vargas 		RTE_PCI_DEVICE(VC_5GNR_VENDOR_ID, VC_5GNR_PF_DEVICE_ID)
33950b5927cbSNicolas Chautru 	},
33960b5927cbSNicolas Chautru 	{.device_id = 0},
33970b5927cbSNicolas Chautru };
33980b5927cbSNicolas Chautru 
33990b5927cbSNicolas Chautru static struct rte_pci_driver fpga_5gnr_fec_pci_pf_driver = {
34000b5927cbSNicolas Chautru 	.probe = fpga_5gnr_fec_probe,
34010b5927cbSNicolas Chautru 	.remove = fpga_5gnr_fec_remove,
34020b5927cbSNicolas Chautru 	.id_table = pci_id_fpga_5gnr_fec_pf_map,
34030b5927cbSNicolas Chautru 	.drv_flags = RTE_PCI_DRV_NEED_MAPPING
34040b5927cbSNicolas Chautru };
34050b5927cbSNicolas Chautru 
34060b5927cbSNicolas Chautru /* FPGA 5GNR FEC PCI VF address map */
34070b5927cbSNicolas Chautru static struct rte_pci_id pci_id_fpga_5gnr_fec_vf_map[] = {
34080b5927cbSNicolas Chautru 	{
34099e3ffd38SHernan Vargas 		RTE_PCI_DEVICE(AGX100_VENDOR_ID, AGX100_VF_DEVICE_ID)
34109e3ffd38SHernan Vargas 	},
34119e3ffd38SHernan Vargas 	{
3412c750d277SHernan Vargas 		RTE_PCI_DEVICE(VC_5GNR_VENDOR_ID, VC_5GNR_VF_DEVICE_ID)
34130b5927cbSNicolas Chautru 	},
34140b5927cbSNicolas Chautru 	{.device_id = 0},
34150b5927cbSNicolas Chautru };
34160b5927cbSNicolas Chautru 
34170b5927cbSNicolas Chautru static struct rte_pci_driver fpga_5gnr_fec_pci_vf_driver = {
34180b5927cbSNicolas Chautru 	.probe = fpga_5gnr_fec_probe,
34190b5927cbSNicolas Chautru 	.remove = fpga_5gnr_fec_remove,
34200b5927cbSNicolas Chautru 	.id_table = pci_id_fpga_5gnr_fec_vf_map,
34210b5927cbSNicolas Chautru 	.drv_flags = RTE_PCI_DRV_NEED_MAPPING
34220b5927cbSNicolas Chautru };
34230b5927cbSNicolas Chautru 
34240b5927cbSNicolas Chautru 
34250b5927cbSNicolas Chautru RTE_PMD_REGISTER_PCI(FPGA_5GNR_FEC_PF_DRIVER_NAME, fpga_5gnr_fec_pci_pf_driver);
342610829ff2SHernan Vargas RTE_PMD_REGISTER_PCI_TABLE(FPGA_5GNR_FEC_PF_DRIVER_NAME, pci_id_fpga_5gnr_fec_pf_map);
34270b5927cbSNicolas Chautru RTE_PMD_REGISTER_PCI(FPGA_5GNR_FEC_VF_DRIVER_NAME, fpga_5gnr_fec_pci_vf_driver);
342810829ff2SHernan Vargas RTE_PMD_REGISTER_PCI_TABLE(FPGA_5GNR_FEC_VF_DRIVER_NAME, pci_id_fpga_5gnr_fec_vf_map);
3429