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