1efd45369SNicolas Chautru /* SPDX-License-Identifier: BSD-3-Clause 2efd45369SNicolas Chautru * Copyright(c) 2019 Intel Corporation 3efd45369SNicolas Chautru */ 4efd45369SNicolas Chautru 5efd45369SNicolas Chautru #include <unistd.h> 6efd45369SNicolas Chautru 7efd45369SNicolas Chautru #include <rte_common.h> 8efd45369SNicolas Chautru #include <rte_log.h> 91acb7f54SDavid Marchand #include <dev_driver.h> 10efd45369SNicolas Chautru #include <rte_malloc.h> 11efd45369SNicolas Chautru #include <rte_mempool.h> 12efd45369SNicolas Chautru #include <rte_errno.h> 13efd45369SNicolas Chautru #include <rte_pci.h> 141f37cb2bSDavid Marchand #include <bus_pci_driver.h> 15efd45369SNicolas Chautru #include <rte_byteorder.h> 16efd45369SNicolas Chautru #include <rte_cycles.h> 17efd45369SNicolas Chautru 18efd45369SNicolas Chautru #include <rte_bbdev.h> 19efd45369SNicolas Chautru #include <rte_bbdev_pmd.h> 20efd45369SNicolas Chautru 21efd45369SNicolas Chautru #include "fpga_lte_fec.h" 22efd45369SNicolas Chautru 239c99878aSJerin Jacob #ifdef RTE_LIBRTE_BBDEV_DEBUG 24eeded204SDavid Marchand RTE_LOG_REGISTER_DEFAULT(fpga_lte_fec_logtype, DEBUG); 259c99878aSJerin Jacob #else 26eeded204SDavid Marchand RTE_LOG_REGISTER_DEFAULT(fpga_lte_fec_logtype, NOTICE); 279c99878aSJerin Jacob #endif 282b843cacSDavid Marchand #define RTE_LOGTYPE_FPGA_LTE_FEC fpga_lte_fec_logtype 29efd45369SNicolas Chautru 30efd45369SNicolas Chautru /* Helper macro for logging */ 312b843cacSDavid Marchand #define rte_bbdev_log(level, ...) \ 322b843cacSDavid Marchand RTE_LOG_LINE(level, FPGA_LTE_FEC, __VA_ARGS__) 33efd45369SNicolas Chautru 34efd45369SNicolas Chautru #ifdef RTE_LIBRTE_BBDEV_DEBUG 352b843cacSDavid Marchand #define rte_bbdev_log_debug(...) \ 362b843cacSDavid Marchand rte_bbdev_log(DEBUG, __VA_ARGS__) 37efd45369SNicolas Chautru #else 382b843cacSDavid Marchand #define rte_bbdev_log_debug(...) 39efd45369SNicolas Chautru #endif 40efd45369SNicolas Chautru 41efd45369SNicolas Chautru /* FPGA LTE FEC driver names */ 42efd45369SNicolas Chautru #define FPGA_LTE_FEC_PF_DRIVER_NAME intel_fpga_lte_fec_pf 43efd45369SNicolas Chautru #define FPGA_LTE_FEC_VF_DRIVER_NAME intel_fpga_lte_fec_vf 44efd45369SNicolas Chautru 45efd45369SNicolas Chautru /* FPGA LTE FEC PCI vendor & device IDs */ 46efd45369SNicolas Chautru #define FPGA_LTE_FEC_VENDOR_ID (0x1172) 47efd45369SNicolas Chautru #define FPGA_LTE_FEC_PF_DEVICE_ID (0x5052) 48efd45369SNicolas Chautru #define FPGA_LTE_FEC_VF_DEVICE_ID (0x5050) 49efd45369SNicolas Chautru 50efd45369SNicolas Chautru /* Align DMA descriptors to 256 bytes - cache-aligned */ 51efd45369SNicolas Chautru #define FPGA_RING_DESC_ENTRY_LENGTH (8) 52efd45369SNicolas Chautru /* Ring size is in 256 bits (32 bytes) units */ 53efd45369SNicolas Chautru #define FPGA_RING_DESC_LEN_UNIT_BYTES (32) 54efd45369SNicolas Chautru /* Maximum size of queue */ 55efd45369SNicolas Chautru #define FPGA_RING_MAX_SIZE (1024) 56efd45369SNicolas Chautru #define FPGA_FLR_TIMEOUT_UNIT (16.384) 57efd45369SNicolas Chautru 58efd45369SNicolas Chautru #define FPGA_NUM_UL_QUEUES (32) 59efd45369SNicolas Chautru #define FPGA_NUM_DL_QUEUES (32) 60efd45369SNicolas Chautru #define FPGA_TOTAL_NUM_QUEUES (FPGA_NUM_UL_QUEUES + FPGA_NUM_DL_QUEUES) 61efd45369SNicolas Chautru #define FPGA_NUM_INTR_VEC (FPGA_TOTAL_NUM_QUEUES - RTE_INTR_VEC_RXTX_OFFSET) 62efd45369SNicolas Chautru 63efd45369SNicolas Chautru #define FPGA_INVALID_HW_QUEUE_ID (0xFFFFFFFF) 64efd45369SNicolas Chautru 65efd45369SNicolas Chautru #define FPGA_QUEUE_FLUSH_TIMEOUT_US (1000) 66efd45369SNicolas Chautru #define FPGA_TIMEOUT_CHECK_INTERVAL (5) 67efd45369SNicolas Chautru 68efd45369SNicolas Chautru /* FPGA LTE FEC Register mapping on BAR0 */ 69efd45369SNicolas Chautru enum { 70efd45369SNicolas Chautru FPGA_LTE_FEC_VERSION_ID = 0x00000000, /* len: 4B */ 71efd45369SNicolas Chautru FPGA_LTE_FEC_CONFIGURATION = 0x00000004, /* len: 2B */ 72efd45369SNicolas Chautru FPGA_LTE_FEC_QUEUE_PF_VF_MAP_DONE = 0x00000008, /* len: 1B */ 73efd45369SNicolas Chautru FPGA_LTE_FEC_LOAD_BALANCE_FACTOR = 0x0000000a, /* len: 2B */ 74efd45369SNicolas Chautru FPGA_LTE_FEC_RING_DESC_LEN = 0x0000000c, /* len: 2B */ 75efd45369SNicolas Chautru FPGA_LTE_FEC_FLR_TIME_OUT = 0x0000000e, /* len: 2B */ 76efd45369SNicolas Chautru FPGA_LTE_FEC_VFQ_FLUSH_STATUS_LW = 0x00000018, /* len: 4B */ 77efd45369SNicolas Chautru FPGA_LTE_FEC_VFQ_FLUSH_STATUS_HI = 0x0000001c, /* len: 4B */ 78efd45369SNicolas Chautru FPGA_LTE_FEC_VF0_DEBUG = 0x00000020, /* len: 4B */ 79efd45369SNicolas Chautru FPGA_LTE_FEC_VF1_DEBUG = 0x00000024, /* len: 4B */ 80efd45369SNicolas Chautru FPGA_LTE_FEC_VF2_DEBUG = 0x00000028, /* len: 4B */ 81efd45369SNicolas Chautru FPGA_LTE_FEC_VF3_DEBUG = 0x0000002c, /* len: 4B */ 82efd45369SNicolas Chautru FPGA_LTE_FEC_VF4_DEBUG = 0x00000030, /* len: 4B */ 83efd45369SNicolas Chautru FPGA_LTE_FEC_VF5_DEBUG = 0x00000034, /* len: 4B */ 84efd45369SNicolas Chautru FPGA_LTE_FEC_VF6_DEBUG = 0x00000038, /* len: 4B */ 85efd45369SNicolas Chautru FPGA_LTE_FEC_VF7_DEBUG = 0x0000003c, /* len: 4B */ 86efd45369SNicolas Chautru FPGA_LTE_FEC_QUEUE_MAP = 0x00000040, /* len: 256B */ 87efd45369SNicolas Chautru FPGA_LTE_FEC_RING_CTRL_REGS = 0x00000200 /* len: 2048B */ 88efd45369SNicolas Chautru }; 89efd45369SNicolas Chautru 90efd45369SNicolas Chautru /* FPGA LTE FEC Ring Control Registers */ 91efd45369SNicolas Chautru enum { 92efd45369SNicolas Chautru FPGA_LTE_FEC_RING_HEAD_ADDR = 0x00000008, 93efd45369SNicolas Chautru FPGA_LTE_FEC_RING_SIZE = 0x00000010, 94efd45369SNicolas Chautru FPGA_LTE_FEC_RING_MISC = 0x00000014, 95efd45369SNicolas Chautru FPGA_LTE_FEC_RING_ENABLE = 0x00000015, 96efd45369SNicolas Chautru FPGA_LTE_FEC_RING_FLUSH_QUEUE_EN = 0x00000016, 97efd45369SNicolas Chautru FPGA_LTE_FEC_RING_SHADOW_TAIL = 0x00000018, 98efd45369SNicolas Chautru FPGA_LTE_FEC_RING_HEAD_POINT = 0x0000001C 99efd45369SNicolas Chautru }; 100efd45369SNicolas Chautru 101efd45369SNicolas Chautru /* FPGA LTE FEC DESCRIPTOR ERROR */ 102efd45369SNicolas Chautru enum { 103efd45369SNicolas Chautru DESC_ERR_NO_ERR = 0x0, 104efd45369SNicolas Chautru DESC_ERR_K_OUT_OF_RANGE = 0x1, 105efd45369SNicolas Chautru DESC_ERR_K_NOT_NORMAL = 0x2, 106efd45369SNicolas Chautru DESC_ERR_KPAI_NOT_NORMAL = 0x3, 107efd45369SNicolas Chautru DESC_ERR_DESC_OFFSET_ERR = 0x4, 108efd45369SNicolas Chautru DESC_ERR_DESC_READ_FAIL = 0x8, 109efd45369SNicolas Chautru DESC_ERR_DESC_READ_TIMEOUT = 0x9, 110efd45369SNicolas Chautru DESC_ERR_DESC_READ_TLP_POISONED = 0xA, 111efd45369SNicolas Chautru DESC_ERR_CB_READ_FAIL = 0xC, 112efd45369SNicolas Chautru DESC_ERR_CB_READ_TIMEOUT = 0xD, 113efd45369SNicolas Chautru DESC_ERR_CB_READ_TLP_POISONED = 0xE 114efd45369SNicolas Chautru }; 115efd45369SNicolas Chautru 116efd45369SNicolas Chautru /* FPGA LTE FEC DMA Encoding Request Descriptor */ 117*e7750639SAndre Muezerie struct __rte_packed_begin fpga_dma_enc_desc { 118efd45369SNicolas Chautru uint32_t done:1, 119efd45369SNicolas Chautru rsrvd0:11, 120efd45369SNicolas Chautru error:4, 121efd45369SNicolas Chautru rsrvd1:16; 122efd45369SNicolas Chautru uint32_t ncb:16, 123efd45369SNicolas Chautru rsrvd2:14, 124efd45369SNicolas Chautru rv:2; 125efd45369SNicolas Chautru uint32_t bypass_rm:1, 126efd45369SNicolas Chautru irq_en:1, 127efd45369SNicolas Chautru crc_en:1, 128efd45369SNicolas Chautru rsrvd3:13, 129efd45369SNicolas Chautru offset:10, 130efd45369SNicolas Chautru rsrvd4:6; 131efd45369SNicolas Chautru uint16_t e; 132efd45369SNicolas Chautru uint16_t k; 133efd45369SNicolas Chautru uint32_t out_addr_lw; 134efd45369SNicolas Chautru uint32_t out_addr_hi; 135efd45369SNicolas Chautru uint32_t in_addr_lw; 136efd45369SNicolas Chautru uint32_t in_addr_hi; 137efd45369SNicolas Chautru 138efd45369SNicolas Chautru union { 139efd45369SNicolas Chautru struct { 140efd45369SNicolas Chautru /* Virtual addresses used to retrieve SW context info */ 141efd45369SNicolas Chautru void *op_addr; 142efd45369SNicolas Chautru /* Stores information about total number of Code Blocks 143efd45369SNicolas Chautru * in currently processed Transport Block 144efd45369SNicolas Chautru */ 145efd45369SNicolas Chautru uint64_t cbs_in_op; 146efd45369SNicolas Chautru }; 147efd45369SNicolas Chautru 148efd45369SNicolas Chautru uint8_t sw_ctxt[FPGA_RING_DESC_LEN_UNIT_BYTES * 149efd45369SNicolas Chautru (FPGA_RING_DESC_ENTRY_LENGTH - 1)]; 150efd45369SNicolas Chautru }; 151*e7750639SAndre Muezerie } __rte_packed_end; 152efd45369SNicolas Chautru 153efd45369SNicolas Chautru /* FPGA LTE FEC DMA Decoding Request Descriptor */ 154*e7750639SAndre Muezerie struct __rte_packed_begin fpga_dma_dec_desc { 155efd45369SNicolas Chautru uint32_t done:1, 156efd45369SNicolas Chautru iter:5, 157efd45369SNicolas Chautru rsrvd0:2, 158efd45369SNicolas Chautru crc_pass:1, 159efd45369SNicolas Chautru rsrvd1:3, 160efd45369SNicolas Chautru error:4, 161efd45369SNicolas Chautru crc_type:1, 162efd45369SNicolas Chautru rsrvd2:7, 163efd45369SNicolas Chautru max_iter:5, 164efd45369SNicolas Chautru rsrvd3:3; 165efd45369SNicolas Chautru uint32_t rsrvd4; 166efd45369SNicolas Chautru uint32_t bypass_rm:1, 167efd45369SNicolas Chautru irq_en:1, 168efd45369SNicolas Chautru drop_crc:1, 169efd45369SNicolas Chautru rsrvd5:13, 170efd45369SNicolas Chautru offset:10, 171efd45369SNicolas Chautru rsrvd6:6; 172efd45369SNicolas Chautru uint16_t k; 173efd45369SNicolas Chautru uint16_t in_len; 174efd45369SNicolas Chautru uint32_t out_addr_lw; 175efd45369SNicolas Chautru uint32_t out_addr_hi; 176efd45369SNicolas Chautru uint32_t in_addr_lw; 177efd45369SNicolas Chautru uint32_t in_addr_hi; 178efd45369SNicolas Chautru 179efd45369SNicolas Chautru union { 180efd45369SNicolas Chautru struct { 181efd45369SNicolas Chautru /* Virtual addresses used to retrieve SW context info */ 182efd45369SNicolas Chautru void *op_addr; 183efd45369SNicolas Chautru /* Stores information about total number of Code Blocks 184efd45369SNicolas Chautru * in currently processed Transport Block 185efd45369SNicolas Chautru */ 186efd45369SNicolas Chautru uint8_t cbs_in_op; 187efd45369SNicolas Chautru }; 188efd45369SNicolas Chautru 189efd45369SNicolas Chautru uint32_t sw_ctxt[8 * (FPGA_RING_DESC_ENTRY_LENGTH - 1)]; 190efd45369SNicolas Chautru }; 191*e7750639SAndre Muezerie } __rte_packed_end; 192efd45369SNicolas Chautru 193efd45369SNicolas Chautru /* FPGA LTE DMA Descriptor */ 194efd45369SNicolas Chautru union fpga_dma_desc { 195efd45369SNicolas Chautru struct fpga_dma_enc_desc enc_req; 196efd45369SNicolas Chautru struct fpga_dma_dec_desc dec_req; 197efd45369SNicolas Chautru }; 198efd45369SNicolas Chautru 199efd45369SNicolas Chautru /* FPGA LTE FEC Ring Control Register */ 200*e7750639SAndre Muezerie struct __rte_packed_begin fpga_ring_ctrl_reg { 201efd45369SNicolas Chautru uint64_t ring_base_addr; 202efd45369SNicolas Chautru uint64_t ring_head_addr; 203efd45369SNicolas Chautru uint16_t ring_size:11; 204efd45369SNicolas Chautru uint16_t rsrvd0; 205efd45369SNicolas Chautru union { /* Miscellaneous register */ 206efd45369SNicolas Chautru uint8_t misc; 207efd45369SNicolas Chautru uint8_t max_ul_dec:5, 208efd45369SNicolas Chautru max_ul_dec_en:1, 209efd45369SNicolas Chautru rsrvd1:2; 210efd45369SNicolas Chautru }; 211efd45369SNicolas Chautru uint8_t enable; 212efd45369SNicolas Chautru uint8_t flush_queue_en; 213efd45369SNicolas Chautru uint8_t rsrvd2; 214efd45369SNicolas Chautru uint16_t shadow_tail; 215efd45369SNicolas Chautru uint16_t rsrvd3; 216efd45369SNicolas Chautru uint16_t head_point; 217efd45369SNicolas Chautru uint16_t rsrvd4; 218efd45369SNicolas Chautru 219*e7750639SAndre Muezerie } __rte_packed_end; 220efd45369SNicolas Chautru 221efd45369SNicolas Chautru /* Private data structure for each FPGA FEC device */ 222efd45369SNicolas Chautru struct fpga_lte_fec_device { 223efd45369SNicolas Chautru /** Base address of MMIO registers (BAR0) */ 224efd45369SNicolas Chautru void *mmio_base; 225efd45369SNicolas Chautru /** Base address of memory for sw rings */ 226efd45369SNicolas Chautru void *sw_rings; 227efd45369SNicolas Chautru /** Physical address of sw_rings */ 228efd45369SNicolas Chautru rte_iova_t sw_rings_phys; 229efd45369SNicolas Chautru /** Number of bytes available for each queue in device. */ 230efd45369SNicolas Chautru uint32_t sw_ring_size; 231efd45369SNicolas Chautru /** Max number of entries available for each queue in device */ 232efd45369SNicolas Chautru uint32_t sw_ring_max_depth; 233efd45369SNicolas Chautru /** Base address of response tail pointer buffer */ 234efd45369SNicolas Chautru uint32_t *tail_ptrs; 235efd45369SNicolas Chautru /** Physical address of tail pointers */ 236efd45369SNicolas Chautru rte_iova_t tail_ptr_phys; 237efd45369SNicolas Chautru /** Queues flush completion flag */ 238efd45369SNicolas Chautru uint64_t *flush_queue_status; 239efd45369SNicolas Chautru /* Bitmap capturing which Queues are bound to the PF/VF */ 240efd45369SNicolas Chautru uint64_t q_bound_bit_map; 241efd45369SNicolas Chautru /* Bitmap capturing which Queues have already been assigned */ 242efd45369SNicolas Chautru uint64_t q_assigned_bit_map; 243efd45369SNicolas Chautru /** True if this is a PF FPGA FEC device */ 244efd45369SNicolas Chautru bool pf_device; 245efd45369SNicolas Chautru }; 246efd45369SNicolas Chautru 247efd45369SNicolas Chautru /* Structure associated with each queue. */ 248efd45369SNicolas Chautru struct __rte_cache_aligned fpga_queue { 249efd45369SNicolas Chautru struct fpga_ring_ctrl_reg ring_ctrl_reg; /* Ring Control Register */ 250efd45369SNicolas Chautru union fpga_dma_desc *ring_addr; /* Virtual address of software ring */ 251efd45369SNicolas Chautru uint64_t *ring_head_addr; /* Virtual address of completion_head */ 252efd45369SNicolas Chautru uint64_t shadow_completion_head; /* Shadow completion head value */ 253efd45369SNicolas Chautru uint16_t head_free_desc; /* Ring head */ 254efd45369SNicolas Chautru uint16_t tail; /* Ring tail */ 255efd45369SNicolas Chautru /* Mask used to wrap enqueued descriptors on the sw ring */ 256efd45369SNicolas Chautru uint32_t sw_ring_wrap_mask; 257efd45369SNicolas Chautru uint32_t irq_enable; /* Enable ops dequeue interrupts if set to 1 */ 258efd45369SNicolas Chautru uint8_t q_idx; /* Queue index */ 259efd45369SNicolas Chautru struct fpga_lte_fec_device *d; 260efd45369SNicolas Chautru /* MMIO register of shadow_tail used to enqueue descriptors */ 261efd45369SNicolas Chautru void *shadow_tail_addr; 262efd45369SNicolas Chautru }; 263efd45369SNicolas Chautru 264efd45369SNicolas Chautru /* Write to 16 bit MMIO register address */ 265efd45369SNicolas Chautru static inline void 266efd45369SNicolas Chautru mmio_write_16(void *addr, uint16_t value) 267efd45369SNicolas Chautru { 268efd45369SNicolas Chautru *((volatile uint16_t *)(addr)) = rte_cpu_to_le_16(value); 269efd45369SNicolas Chautru } 270efd45369SNicolas Chautru 271efd45369SNicolas Chautru /* Write to 32 bit MMIO register address */ 272efd45369SNicolas Chautru static inline void 273efd45369SNicolas Chautru mmio_write_32(void *addr, uint32_t value) 274efd45369SNicolas Chautru { 275efd45369SNicolas Chautru *((volatile uint32_t *)(addr)) = rte_cpu_to_le_32(value); 276efd45369SNicolas Chautru } 277efd45369SNicolas Chautru 278efd45369SNicolas Chautru /* Write to 64 bit MMIO register address */ 279efd45369SNicolas Chautru static inline void 280efd45369SNicolas Chautru mmio_write_64(void *addr, uint64_t value) 281efd45369SNicolas Chautru { 282efd45369SNicolas Chautru *((volatile uint64_t *)(addr)) = rte_cpu_to_le_64(value); 283efd45369SNicolas Chautru } 284efd45369SNicolas Chautru 285efd45369SNicolas Chautru /* Write a 8 bit register of a FPGA LTE FEC device */ 286efd45369SNicolas Chautru static inline void 287efd45369SNicolas Chautru fpga_reg_write_8(void *mmio_base, uint32_t offset, uint8_t payload) 288efd45369SNicolas Chautru { 289efd45369SNicolas Chautru void *reg_addr = RTE_PTR_ADD(mmio_base, offset); 290efd45369SNicolas Chautru *((volatile uint8_t *)(reg_addr)) = payload; 291efd45369SNicolas Chautru } 292efd45369SNicolas Chautru 293efd45369SNicolas Chautru /* Write a 16 bit register of a FPGA LTE FEC device */ 294efd45369SNicolas Chautru static inline void 295efd45369SNicolas Chautru fpga_reg_write_16(void *mmio_base, uint32_t offset, uint16_t payload) 296efd45369SNicolas Chautru { 297efd45369SNicolas Chautru void *reg_addr = RTE_PTR_ADD(mmio_base, offset); 298efd45369SNicolas Chautru mmio_write_16(reg_addr, payload); 299efd45369SNicolas Chautru } 300efd45369SNicolas Chautru 301efd45369SNicolas Chautru /* Write a 32 bit register of a FPGA LTE FEC device */ 302efd45369SNicolas Chautru static inline void 303efd45369SNicolas Chautru fpga_reg_write_32(void *mmio_base, uint32_t offset, uint32_t payload) 304efd45369SNicolas Chautru { 305efd45369SNicolas Chautru void *reg_addr = RTE_PTR_ADD(mmio_base, offset); 306efd45369SNicolas Chautru mmio_write_32(reg_addr, payload); 307efd45369SNicolas Chautru } 308efd45369SNicolas Chautru 309efd45369SNicolas Chautru /* Write a 64 bit register of a FPGA LTE FEC device */ 310efd45369SNicolas Chautru static inline void 311efd45369SNicolas Chautru fpga_reg_write_64(void *mmio_base, uint32_t offset, uint64_t payload) 312efd45369SNicolas Chautru { 313efd45369SNicolas Chautru void *reg_addr = RTE_PTR_ADD(mmio_base, offset); 314efd45369SNicolas Chautru mmio_write_64(reg_addr, payload); 315efd45369SNicolas Chautru } 316efd45369SNicolas Chautru 317efd45369SNicolas Chautru /* Write a ring control register of a FPGA LTE FEC device */ 318efd45369SNicolas Chautru static inline void 319efd45369SNicolas Chautru fpga_ring_reg_write(void *mmio_base, uint32_t offset, 320efd45369SNicolas Chautru struct fpga_ring_ctrl_reg payload) 321efd45369SNicolas Chautru { 322efd45369SNicolas Chautru fpga_reg_write_64(mmio_base, offset, payload.ring_base_addr); 323efd45369SNicolas Chautru fpga_reg_write_64(mmio_base, offset + FPGA_LTE_FEC_RING_HEAD_ADDR, 324efd45369SNicolas Chautru payload.ring_head_addr); 325efd45369SNicolas Chautru fpga_reg_write_16(mmio_base, offset + FPGA_LTE_FEC_RING_SIZE, 326efd45369SNicolas Chautru payload.ring_size); 327efd45369SNicolas Chautru fpga_reg_write_16(mmio_base, offset + FPGA_LTE_FEC_RING_HEAD_POINT, 328efd45369SNicolas Chautru payload.head_point); 329efd45369SNicolas Chautru fpga_reg_write_8(mmio_base, offset + FPGA_LTE_FEC_RING_FLUSH_QUEUE_EN, 330efd45369SNicolas Chautru payload.flush_queue_en); 331efd45369SNicolas Chautru fpga_reg_write_16(mmio_base, offset + FPGA_LTE_FEC_RING_SHADOW_TAIL, 332efd45369SNicolas Chautru payload.shadow_tail); 333efd45369SNicolas Chautru fpga_reg_write_8(mmio_base, offset + FPGA_LTE_FEC_RING_MISC, 334efd45369SNicolas Chautru payload.misc); 335efd45369SNicolas Chautru fpga_reg_write_8(mmio_base, offset + FPGA_LTE_FEC_RING_ENABLE, 336efd45369SNicolas Chautru payload.enable); 337efd45369SNicolas Chautru } 338efd45369SNicolas Chautru 339efd45369SNicolas Chautru /* Read a register of FPGA LTE FEC device */ 340efd45369SNicolas Chautru static uint32_t 341efd45369SNicolas Chautru fpga_reg_read_32(void *mmio_base, uint32_t offset) 342efd45369SNicolas Chautru { 343efd45369SNicolas Chautru void *reg_addr = RTE_PTR_ADD(mmio_base, offset); 344efd45369SNicolas Chautru uint32_t ret = *((volatile uint32_t *)(reg_addr)); 345efd45369SNicolas Chautru return rte_le_to_cpu_32(ret); 346efd45369SNicolas Chautru } 347efd45369SNicolas Chautru 348efd45369SNicolas Chautru #ifdef RTE_LIBRTE_BBDEV_DEBUG 349efd45369SNicolas Chautru /* Read a register of FPGA LTE FEC device */ 350efd45369SNicolas Chautru static uint8_t 351efd45369SNicolas Chautru fpga_reg_read_8(void *mmio_base, uint32_t offset) 352efd45369SNicolas Chautru { 353efd45369SNicolas Chautru void *reg_addr = RTE_PTR_ADD(mmio_base, offset); 354efd45369SNicolas Chautru return *((volatile uint8_t *)(reg_addr)); 355efd45369SNicolas Chautru } 356efd45369SNicolas Chautru 357efd45369SNicolas Chautru /* Read a register of FPGA LTE FEC device */ 358efd45369SNicolas Chautru static uint16_t 359efd45369SNicolas Chautru fpga_reg_read_16(void *mmio_base, uint32_t offset) 360efd45369SNicolas Chautru { 361efd45369SNicolas Chautru void *reg_addr = RTE_PTR_ADD(mmio_base, offset); 362efd45369SNicolas Chautru uint16_t ret = *((volatile uint16_t *)(reg_addr)); 363efd45369SNicolas Chautru return rte_le_to_cpu_16(ret); 364efd45369SNicolas Chautru } 365efd45369SNicolas Chautru 366efd45369SNicolas Chautru /* Read a register of FPGA LTE FEC device */ 367efd45369SNicolas Chautru static uint64_t 368efd45369SNicolas Chautru fpga_reg_read_64(void *mmio_base, uint32_t offset) 369efd45369SNicolas Chautru { 370efd45369SNicolas Chautru void *reg_addr = RTE_PTR_ADD(mmio_base, offset); 371efd45369SNicolas Chautru uint64_t ret = *((volatile uint64_t *)(reg_addr)); 372efd45369SNicolas Chautru return rte_le_to_cpu_64(ret); 373efd45369SNicolas Chautru } 374efd45369SNicolas Chautru 375efd45369SNicolas Chautru /* Read Ring Control Register of FPGA LTE FEC device */ 376efd45369SNicolas Chautru static inline void 377efd45369SNicolas Chautru print_ring_reg_debug_info(void *mmio_base, uint32_t offset) 378efd45369SNicolas Chautru { 379efd45369SNicolas Chautru rte_bbdev_log_debug( 380efd45369SNicolas Chautru "FPGA MMIO base address @ %p | Ring Control Register @ offset = 0x%08" 381efd45369SNicolas Chautru PRIx32, mmio_base, offset); 382efd45369SNicolas Chautru rte_bbdev_log_debug( 383efd45369SNicolas Chautru "RING_BASE_ADDR = 0x%016"PRIx64, 384efd45369SNicolas Chautru fpga_reg_read_64(mmio_base, offset)); 385efd45369SNicolas Chautru rte_bbdev_log_debug( 386efd45369SNicolas Chautru "RING_HEAD_ADDR = 0x%016"PRIx64, 387efd45369SNicolas Chautru fpga_reg_read_64(mmio_base, offset + 388efd45369SNicolas Chautru FPGA_LTE_FEC_RING_HEAD_ADDR)); 389efd45369SNicolas Chautru rte_bbdev_log_debug( 390efd45369SNicolas Chautru "RING_SIZE = 0x%04"PRIx16, 391efd45369SNicolas Chautru fpga_reg_read_16(mmio_base, offset + 392efd45369SNicolas Chautru FPGA_LTE_FEC_RING_SIZE)); 393efd45369SNicolas Chautru rte_bbdev_log_debug( 394efd45369SNicolas Chautru "RING_MISC = 0x%02"PRIx8, 395efd45369SNicolas Chautru fpga_reg_read_8(mmio_base, offset + 396efd45369SNicolas Chautru FPGA_LTE_FEC_RING_MISC)); 397efd45369SNicolas Chautru rte_bbdev_log_debug( 398efd45369SNicolas Chautru "RING_ENABLE = 0x%02"PRIx8, 399efd45369SNicolas Chautru fpga_reg_read_8(mmio_base, offset + 400efd45369SNicolas Chautru FPGA_LTE_FEC_RING_ENABLE)); 401efd45369SNicolas Chautru rte_bbdev_log_debug( 402efd45369SNicolas Chautru "RING_FLUSH_QUEUE_EN = 0x%02"PRIx8, 403efd45369SNicolas Chautru fpga_reg_read_8(mmio_base, offset + 404efd45369SNicolas Chautru FPGA_LTE_FEC_RING_FLUSH_QUEUE_EN)); 405efd45369SNicolas Chautru rte_bbdev_log_debug( 406efd45369SNicolas Chautru "RING_SHADOW_TAIL = 0x%04"PRIx16, 407efd45369SNicolas Chautru fpga_reg_read_16(mmio_base, offset + 408efd45369SNicolas Chautru FPGA_LTE_FEC_RING_SHADOW_TAIL)); 409efd45369SNicolas Chautru rte_bbdev_log_debug( 410efd45369SNicolas Chautru "RING_HEAD_POINT = 0x%04"PRIx16, 411efd45369SNicolas Chautru fpga_reg_read_16(mmio_base, offset + 412efd45369SNicolas Chautru FPGA_LTE_FEC_RING_HEAD_POINT)); 413efd45369SNicolas Chautru } 414efd45369SNicolas Chautru 415efd45369SNicolas Chautru /* Read Static Register of FPGA LTE FEC device */ 416efd45369SNicolas Chautru static inline void 417efd45369SNicolas Chautru print_static_reg_debug_info(void *mmio_base) 418efd45369SNicolas Chautru { 419efd45369SNicolas Chautru uint16_t config = fpga_reg_read_16(mmio_base, 420efd45369SNicolas Chautru FPGA_LTE_FEC_CONFIGURATION); 421efd45369SNicolas Chautru uint8_t qmap_done = fpga_reg_read_8(mmio_base, 422efd45369SNicolas Chautru FPGA_LTE_FEC_QUEUE_PF_VF_MAP_DONE); 423efd45369SNicolas Chautru uint16_t lb_factor = fpga_reg_read_16(mmio_base, 424efd45369SNicolas Chautru FPGA_LTE_FEC_LOAD_BALANCE_FACTOR); 425efd45369SNicolas Chautru uint16_t ring_desc_len = fpga_reg_read_16(mmio_base, 426efd45369SNicolas Chautru FPGA_LTE_FEC_RING_DESC_LEN); 427efd45369SNicolas Chautru uint16_t flr_time_out = fpga_reg_read_16(mmio_base, 428efd45369SNicolas Chautru FPGA_LTE_FEC_FLR_TIME_OUT); 429efd45369SNicolas Chautru 430efd45369SNicolas Chautru rte_bbdev_log_debug("UL.DL Weights = %u.%u", 431efd45369SNicolas Chautru ((uint8_t)config), ((uint8_t)(config >> 8))); 432efd45369SNicolas Chautru rte_bbdev_log_debug("UL.DL Load Balance = %u.%u", 433efd45369SNicolas Chautru ((uint8_t)lb_factor), ((uint8_t)(lb_factor >> 8))); 434efd45369SNicolas Chautru rte_bbdev_log_debug("Queue-PF/VF Mapping Table = %s", 435efd45369SNicolas Chautru (qmap_done > 0) ? "READY" : "NOT-READY"); 436efd45369SNicolas Chautru rte_bbdev_log_debug("Ring Descriptor Size = %u bytes", 437efd45369SNicolas Chautru ring_desc_len*FPGA_RING_DESC_LEN_UNIT_BYTES); 438efd45369SNicolas Chautru rte_bbdev_log_debug("FLR Timeout = %f usec", 439efd45369SNicolas Chautru (float)flr_time_out*FPGA_FLR_TIMEOUT_UNIT); 440efd45369SNicolas Chautru } 441efd45369SNicolas Chautru 442efd45369SNicolas Chautru /* Print decode DMA Descriptor of FPGA LTE FEC device */ 443efd45369SNicolas Chautru static void 444efd45369SNicolas Chautru print_dma_dec_desc_debug_info(union fpga_dma_desc *desc) 445efd45369SNicolas Chautru { 4461af8b0b2SDavid Marchand rte_bbdev_log_debug("DMA response desc %p", 4471af8b0b2SDavid Marchand desc); 4481af8b0b2SDavid Marchand rte_bbdev_log_debug("\t-- done(%"PRIu32") | iter(%"PRIu32") | crc_pass(%"PRIu32")" 4491af8b0b2SDavid Marchand " | error (%"PRIu32") | crc_type(%"PRIu32")", 450efd45369SNicolas Chautru (uint32_t)desc->dec_req.done, 451efd45369SNicolas Chautru (uint32_t)desc->dec_req.iter, 452efd45369SNicolas Chautru (uint32_t)desc->dec_req.crc_pass, 453efd45369SNicolas Chautru (uint32_t)desc->dec_req.error, 4541af8b0b2SDavid Marchand (uint32_t)desc->dec_req.crc_type); 4551af8b0b2SDavid Marchand rte_bbdev_log_debug("\t-- max_iter(%"PRIu32") | bypass_rm(%"PRIu32") | " 4561af8b0b2SDavid Marchand "irq_en (%"PRIu32") | drop_crc(%"PRIu32") | offset(%"PRIu32")", 457efd45369SNicolas Chautru (uint32_t)desc->dec_req.max_iter, 458efd45369SNicolas Chautru (uint32_t)desc->dec_req.bypass_rm, 459efd45369SNicolas Chautru (uint32_t)desc->dec_req.irq_en, 460efd45369SNicolas Chautru (uint32_t)desc->dec_req.drop_crc, 4611af8b0b2SDavid Marchand (uint32_t)desc->dec_req.offset); 4621af8b0b2SDavid Marchand rte_bbdev_log_debug("\t-- k(%"PRIu32") | in_len (%"PRIu16") | op_add(%p)", 463efd45369SNicolas Chautru (uint32_t)desc->dec_req.k, 464efd45369SNicolas Chautru (uint16_t)desc->dec_req.in_len, 4651af8b0b2SDavid Marchand desc->dec_req.op_addr); 4661af8b0b2SDavid Marchand rte_bbdev_log_debug("\t-- cbs_in_op(%"PRIu32") | in_add (0x%08"PRIx32"%08"PRIx32") | " 4671af8b0b2SDavid Marchand "out_add (0x%08"PRIx32"%08"PRIx32")", 468efd45369SNicolas Chautru (uint32_t)desc->dec_req.cbs_in_op, 469efd45369SNicolas Chautru (uint32_t)desc->dec_req.in_addr_hi, 470efd45369SNicolas Chautru (uint32_t)desc->dec_req.in_addr_lw, 471efd45369SNicolas Chautru (uint32_t)desc->dec_req.out_addr_hi, 472efd45369SNicolas Chautru (uint32_t)desc->dec_req.out_addr_lw); 473efd45369SNicolas Chautru } 474efd45369SNicolas Chautru #endif 475efd45369SNicolas Chautru 476efd45369SNicolas Chautru static int 477efd45369SNicolas Chautru fpga_setup_queues(struct rte_bbdev *dev, uint16_t num_queues, int socket_id) 478efd45369SNicolas Chautru { 479efd45369SNicolas Chautru /* Number of queues bound to a PF/VF */ 480efd45369SNicolas Chautru uint32_t hw_q_num = 0; 481efd45369SNicolas Chautru uint32_t ring_size, payload, address, q_id, offset; 482efd45369SNicolas Chautru rte_iova_t phys_addr; 483efd45369SNicolas Chautru struct fpga_ring_ctrl_reg ring_reg; 484efd45369SNicolas Chautru struct fpga_lte_fec_device *fpga_dev = dev->data->dev_private; 485efd45369SNicolas Chautru 486efd45369SNicolas Chautru address = FPGA_LTE_FEC_QUEUE_PF_VF_MAP_DONE; 487efd45369SNicolas Chautru if (!(fpga_reg_read_32(fpga_dev->mmio_base, address) & 0x1)) { 488efd45369SNicolas Chautru rte_bbdev_log(ERR, 489efd45369SNicolas Chautru "Queue-PF/VF mapping is not set! Was PF configured for device (%s) ?", 490efd45369SNicolas Chautru dev->data->name); 491efd45369SNicolas Chautru return -EPERM; 492efd45369SNicolas Chautru } 493efd45369SNicolas Chautru 494efd45369SNicolas Chautru /* Clear queue registers structure */ 495efd45369SNicolas Chautru memset(&ring_reg, 0, sizeof(struct fpga_ring_ctrl_reg)); 496efd45369SNicolas Chautru 497efd45369SNicolas Chautru /* Scan queue map. 498efd45369SNicolas Chautru * If a queue is valid and mapped to a calling PF/VF the read value is 499efd45369SNicolas Chautru * replaced with a queue ID and if it's not then 500efd45369SNicolas Chautru * FPGA_INVALID_HW_QUEUE_ID is returned. 501efd45369SNicolas Chautru */ 502efd45369SNicolas Chautru for (q_id = 0; q_id < FPGA_TOTAL_NUM_QUEUES; ++q_id) { 503efd45369SNicolas Chautru uint32_t hw_q_id = fpga_reg_read_32(fpga_dev->mmio_base, 504efd45369SNicolas Chautru FPGA_LTE_FEC_QUEUE_MAP + (q_id << 2)); 505efd45369SNicolas Chautru 506efd45369SNicolas Chautru rte_bbdev_log_debug("%s: queue ID: %u, registry queue ID: %u", 507efd45369SNicolas Chautru dev->device->name, q_id, hw_q_id); 508efd45369SNicolas Chautru 509efd45369SNicolas Chautru if (hw_q_id != FPGA_INVALID_HW_QUEUE_ID) { 510efd45369SNicolas Chautru fpga_dev->q_bound_bit_map |= (1ULL << q_id); 511efd45369SNicolas Chautru /* Clear queue register of found queue */ 512efd45369SNicolas Chautru offset = FPGA_LTE_FEC_RING_CTRL_REGS + 513efd45369SNicolas Chautru (sizeof(struct fpga_ring_ctrl_reg) * q_id); 514efd45369SNicolas Chautru fpga_ring_reg_write(fpga_dev->mmio_base, 515efd45369SNicolas Chautru offset, ring_reg); 516efd45369SNicolas Chautru ++hw_q_num; 517efd45369SNicolas Chautru } 518efd45369SNicolas Chautru } 519efd45369SNicolas Chautru if (hw_q_num == 0) { 520efd45369SNicolas Chautru rte_bbdev_log(ERR, 521efd45369SNicolas Chautru "No HW queues assigned to this device. Probably this is a VF configured for PF mode. Check device configuration!"); 522efd45369SNicolas Chautru return -ENODEV; 523efd45369SNicolas Chautru } 524efd45369SNicolas Chautru 525efd45369SNicolas Chautru if (num_queues > hw_q_num) { 526efd45369SNicolas Chautru rte_bbdev_log(ERR, 527efd45369SNicolas Chautru "Not enough queues for device %s! Requested: %u, available: %u", 528efd45369SNicolas Chautru dev->device->name, num_queues, hw_q_num); 529efd45369SNicolas Chautru return -EINVAL; 530efd45369SNicolas Chautru } 531efd45369SNicolas Chautru 532efd45369SNicolas Chautru ring_size = FPGA_RING_MAX_SIZE * sizeof(struct fpga_dma_dec_desc); 533efd45369SNicolas Chautru 534efd45369SNicolas Chautru /* Enforce 32 byte alignment */ 535efd45369SNicolas Chautru RTE_BUILD_BUG_ON((RTE_CACHE_LINE_SIZE % 32) != 0); 536efd45369SNicolas Chautru 537efd45369SNicolas Chautru /* Allocate memory for SW descriptor rings */ 538efd45369SNicolas Chautru fpga_dev->sw_rings = rte_zmalloc_socket(dev->device->driver->name, 539efd45369SNicolas Chautru num_queues * ring_size, RTE_CACHE_LINE_SIZE, 540efd45369SNicolas Chautru socket_id); 541efd45369SNicolas Chautru if (fpga_dev->sw_rings == NULL) { 542efd45369SNicolas Chautru rte_bbdev_log(ERR, 543efd45369SNicolas Chautru "Failed to allocate memory for %s:%u sw_rings", 544efd45369SNicolas Chautru dev->device->driver->name, dev->data->dev_id); 545efd45369SNicolas Chautru return -ENOMEM; 546efd45369SNicolas Chautru } 547efd45369SNicolas Chautru 548efd45369SNicolas Chautru fpga_dev->sw_rings_phys = rte_malloc_virt2iova(fpga_dev->sw_rings); 549efd45369SNicolas Chautru fpga_dev->sw_ring_size = ring_size; 550efd45369SNicolas Chautru fpga_dev->sw_ring_max_depth = FPGA_RING_MAX_SIZE; 551efd45369SNicolas Chautru 552efd45369SNicolas Chautru /* Allocate memory for ring flush status */ 553efd45369SNicolas Chautru fpga_dev->flush_queue_status = rte_zmalloc_socket(NULL, 554efd45369SNicolas Chautru sizeof(uint64_t), RTE_CACHE_LINE_SIZE, socket_id); 555efd45369SNicolas Chautru if (fpga_dev->flush_queue_status == NULL) { 556efd45369SNicolas Chautru rte_bbdev_log(ERR, 557efd45369SNicolas Chautru "Failed to allocate memory for %s:%u flush_queue_status", 558efd45369SNicolas Chautru dev->device->driver->name, dev->data->dev_id); 559efd45369SNicolas Chautru return -ENOMEM; 560efd45369SNicolas Chautru } 561efd45369SNicolas Chautru 562efd45369SNicolas Chautru /* Set the flush status address registers */ 563efd45369SNicolas Chautru phys_addr = rte_malloc_virt2iova(fpga_dev->flush_queue_status); 564efd45369SNicolas Chautru 565efd45369SNicolas Chautru address = FPGA_LTE_FEC_VFQ_FLUSH_STATUS_LW; 566efd45369SNicolas Chautru payload = (uint32_t)(phys_addr); 567efd45369SNicolas Chautru fpga_reg_write_32(fpga_dev->mmio_base, address, payload); 568efd45369SNicolas Chautru 569efd45369SNicolas Chautru address = FPGA_LTE_FEC_VFQ_FLUSH_STATUS_HI; 570efd45369SNicolas Chautru payload = (uint32_t)(phys_addr >> 32); 571efd45369SNicolas Chautru fpga_reg_write_32(fpga_dev->mmio_base, address, payload); 572efd45369SNicolas Chautru 573efd45369SNicolas Chautru return 0; 574efd45369SNicolas Chautru } 575efd45369SNicolas Chautru 576efd45369SNicolas Chautru static int 577efd45369SNicolas Chautru fpga_dev_close(struct rte_bbdev *dev) 578efd45369SNicolas Chautru { 579efd45369SNicolas Chautru struct fpga_lte_fec_device *fpga_dev = dev->data->dev_private; 580efd45369SNicolas Chautru 581efd45369SNicolas Chautru rte_free(fpga_dev->sw_rings); 582efd45369SNicolas Chautru rte_free(fpga_dev->flush_queue_status); 583efd45369SNicolas Chautru 584efd45369SNicolas Chautru return 0; 585efd45369SNicolas Chautru } 586efd45369SNicolas Chautru 587efd45369SNicolas Chautru static void 588efd45369SNicolas Chautru fpga_dev_info_get(struct rte_bbdev *dev, 589efd45369SNicolas Chautru struct rte_bbdev_driver_info *dev_info) 590efd45369SNicolas Chautru { 591efd45369SNicolas Chautru struct fpga_lte_fec_device *d = dev->data->dev_private; 592efd45369SNicolas Chautru uint32_t q_id = 0; 593efd45369SNicolas Chautru 594efd45369SNicolas Chautru /* TODO RTE_BBDEV_TURBO_NEG_LLR_1_BIT_IN and numbers of buffers are set 595efd45369SNicolas Chautru * to temporary values as they are required by test application while 596efd45369SNicolas Chautru * validation phase. 597efd45369SNicolas Chautru */ 598efd45369SNicolas Chautru static const struct rte_bbdev_op_cap bbdev_capabilities[] = { 599efd45369SNicolas Chautru { 600efd45369SNicolas Chautru .type = RTE_BBDEV_OP_TURBO_DEC, 601efd45369SNicolas Chautru .cap.turbo_dec = { 602efd45369SNicolas Chautru .capability_flags = 603efd45369SNicolas Chautru RTE_BBDEV_TURBO_CRC_TYPE_24B | 604efd45369SNicolas Chautru RTE_BBDEV_TURBO_SUBBLOCK_DEINTERLEAVE | 605efd45369SNicolas Chautru RTE_BBDEV_TURBO_DEC_INTERRUPTS | 606efd45369SNicolas Chautru RTE_BBDEV_TURBO_NEG_LLR_1_BIT_IN | 607efd45369SNicolas Chautru RTE_BBDEV_TURBO_DEC_TB_CRC_24B_KEEP, 608efd45369SNicolas Chautru .max_llr_modulus = INT8_MAX, 609efd45369SNicolas Chautru .num_buffers_src = 610c4b0d663SNicolas Chautru RTE_BBDEV_TURBO_MAX_CODE_BLOCKS, 611efd45369SNicolas Chautru .num_buffers_hard_out = 612c4b0d663SNicolas Chautru RTE_BBDEV_TURBO_MAX_CODE_BLOCKS, 613efd45369SNicolas Chautru .num_buffers_soft_out = 0 614efd45369SNicolas Chautru } 615efd45369SNicolas Chautru }, 616efd45369SNicolas Chautru { 617efd45369SNicolas Chautru .type = RTE_BBDEV_OP_TURBO_ENC, 618efd45369SNicolas Chautru .cap.turbo_enc = { 619efd45369SNicolas Chautru .capability_flags = 620efd45369SNicolas Chautru RTE_BBDEV_TURBO_CRC_24B_ATTACH | 621efd45369SNicolas Chautru RTE_BBDEV_TURBO_RATE_MATCH | 622efd45369SNicolas Chautru RTE_BBDEV_TURBO_ENC_INTERRUPTS, 623efd45369SNicolas Chautru .num_buffers_src = 624c4b0d663SNicolas Chautru RTE_BBDEV_TURBO_MAX_CODE_BLOCKS, 625efd45369SNicolas Chautru .num_buffers_dst = 626c4b0d663SNicolas Chautru RTE_BBDEV_TURBO_MAX_CODE_BLOCKS 627efd45369SNicolas Chautru } 628efd45369SNicolas Chautru }, 629efd45369SNicolas Chautru RTE_BBDEV_END_OF_CAPABILITIES_LIST() 630efd45369SNicolas Chautru }; 631efd45369SNicolas Chautru 632efd45369SNicolas Chautru static struct rte_bbdev_queue_conf default_queue_conf; 633efd45369SNicolas Chautru default_queue_conf.socket = dev->data->socket_id; 634efd45369SNicolas Chautru default_queue_conf.queue_size = FPGA_RING_MAX_SIZE; 635efd45369SNicolas Chautru 636efd45369SNicolas Chautru 637efd45369SNicolas Chautru dev_info->driver_name = dev->device->driver->name; 638efd45369SNicolas Chautru dev_info->queue_size_lim = FPGA_RING_MAX_SIZE; 639efd45369SNicolas Chautru dev_info->hardware_accelerated = true; 640efd45369SNicolas Chautru dev_info->min_alignment = 64; 641efd45369SNicolas Chautru dev_info->default_queue_conf = default_queue_conf; 642efd45369SNicolas Chautru dev_info->capabilities = bbdev_capabilities; 643efd45369SNicolas Chautru dev_info->cpu_flag_reqs = NULL; 644ab4e1909SNicolas Chautru dev_info->data_endianness = RTE_LITTLE_ENDIAN; 6451be86f2eSNicolas Chautru dev_info->device_status = RTE_BBDEV_DEV_NOT_SUPPORTED; 646efd45369SNicolas Chautru 647efd45369SNicolas Chautru /* Calculates number of queues assigned to device */ 648efd45369SNicolas Chautru dev_info->max_num_queues = 0; 649efd45369SNicolas Chautru for (q_id = 0; q_id < FPGA_TOTAL_NUM_QUEUES; ++q_id) { 650efd45369SNicolas Chautru uint32_t hw_q_id = fpga_reg_read_32(d->mmio_base, 651efd45369SNicolas Chautru FPGA_LTE_FEC_QUEUE_MAP + (q_id << 2)); 652efd45369SNicolas Chautru if (hw_q_id != FPGA_INVALID_HW_QUEUE_ID) 653efd45369SNicolas Chautru dev_info->max_num_queues++; 654efd45369SNicolas Chautru } 65597332051SNicolas Chautru /* Expose number of queue per operation type */ 65697332051SNicolas Chautru dev_info->num_queues[RTE_BBDEV_OP_NONE] = 0; 65797332051SNicolas Chautru dev_info->num_queues[RTE_BBDEV_OP_TURBO_DEC] = dev_info->max_num_queues / 2; 65897332051SNicolas Chautru dev_info->num_queues[RTE_BBDEV_OP_TURBO_ENC] = dev_info->max_num_queues / 2; 65997332051SNicolas Chautru dev_info->num_queues[RTE_BBDEV_OP_LDPC_DEC] = 0; 66097332051SNicolas Chautru dev_info->num_queues[RTE_BBDEV_OP_LDPC_ENC] = 0; 6610f4e9909SHernan Vargas dev_info->num_queues[RTE_BBDEV_OP_FFT] = 0; 6620f4e9909SHernan Vargas dev_info->num_queues[RTE_BBDEV_OP_MLDTS] = 0; 66397332051SNicolas Chautru dev_info->queue_priority[RTE_BBDEV_OP_TURBO_DEC] = 1; 66497332051SNicolas Chautru dev_info->queue_priority[RTE_BBDEV_OP_TURBO_ENC] = 1; 665efd45369SNicolas Chautru } 666efd45369SNicolas Chautru 667efd45369SNicolas Chautru /** 668efd45369SNicolas Chautru * Find index of queue bound to current PF/VF which is unassigned. Return -1 669efd45369SNicolas Chautru * when there is no available queue 670efd45369SNicolas Chautru */ 671efd45369SNicolas Chautru static int 672efd45369SNicolas Chautru fpga_find_free_queue_idx(struct rte_bbdev *dev, 673efd45369SNicolas Chautru const struct rte_bbdev_queue_conf *conf) 674efd45369SNicolas Chautru { 675efd45369SNicolas Chautru struct fpga_lte_fec_device *d = dev->data->dev_private; 676efd45369SNicolas Chautru uint64_t q_idx; 677efd45369SNicolas Chautru uint8_t i = 0; 678efd45369SNicolas Chautru uint8_t range = FPGA_TOTAL_NUM_QUEUES >> 1; 679efd45369SNicolas Chautru 680efd45369SNicolas Chautru if (conf->op_type == RTE_BBDEV_OP_TURBO_ENC) { 681efd45369SNicolas Chautru i = FPGA_NUM_DL_QUEUES; 682efd45369SNicolas Chautru range = FPGA_TOTAL_NUM_QUEUES; 683efd45369SNicolas Chautru } 684efd45369SNicolas Chautru 685efd45369SNicolas Chautru for (; i < range; ++i) { 686efd45369SNicolas Chautru q_idx = 1ULL << i; 687efd45369SNicolas Chautru /* Check if index of queue is bound to current PF/VF */ 688efd45369SNicolas Chautru if (d->q_bound_bit_map & q_idx) 689efd45369SNicolas Chautru /* Check if found queue was not already assigned */ 690efd45369SNicolas Chautru if (!(d->q_assigned_bit_map & q_idx)) { 691efd45369SNicolas Chautru d->q_assigned_bit_map |= q_idx; 692efd45369SNicolas Chautru return i; 693efd45369SNicolas Chautru } 694efd45369SNicolas Chautru } 695efd45369SNicolas Chautru 696efd45369SNicolas Chautru rte_bbdev_log(INFO, "Failed to find free queue on %s", dev->data->name); 697efd45369SNicolas Chautru 698efd45369SNicolas Chautru return -1; 699efd45369SNicolas Chautru } 700efd45369SNicolas Chautru 701efd45369SNicolas Chautru static int 702efd45369SNicolas Chautru fpga_queue_setup(struct rte_bbdev *dev, uint16_t queue_id, 703efd45369SNicolas Chautru const struct rte_bbdev_queue_conf *conf) 704efd45369SNicolas Chautru { 705efd45369SNicolas Chautru uint32_t address, ring_offset; 706efd45369SNicolas Chautru struct fpga_lte_fec_device *d = dev->data->dev_private; 707efd45369SNicolas Chautru struct fpga_queue *q; 708efd45369SNicolas Chautru int8_t q_idx; 709efd45369SNicolas Chautru 710efd45369SNicolas Chautru /* Check if there is a free queue to assign */ 711efd45369SNicolas Chautru q_idx = fpga_find_free_queue_idx(dev, conf); 712efd45369SNicolas Chautru if (q_idx == -1) 713efd45369SNicolas Chautru return -1; 714efd45369SNicolas Chautru 715efd45369SNicolas Chautru /* Allocate the queue data structure. */ 716efd45369SNicolas Chautru q = rte_zmalloc_socket(dev->device->driver->name, sizeof(*q), 717efd45369SNicolas Chautru RTE_CACHE_LINE_SIZE, conf->socket); 718efd45369SNicolas Chautru if (q == NULL) { 719efd45369SNicolas Chautru /* Mark queue as un-assigned */ 720efd45369SNicolas Chautru d->q_assigned_bit_map &= (0xFFFFFFFF - (1ULL << q_idx)); 721efd45369SNicolas Chautru rte_bbdev_log(ERR, "Failed to allocate queue memory"); 722efd45369SNicolas Chautru return -ENOMEM; 723efd45369SNicolas Chautru } 724efd45369SNicolas Chautru 725efd45369SNicolas Chautru q->d = d; 726efd45369SNicolas Chautru q->q_idx = q_idx; 727efd45369SNicolas Chautru 728efd45369SNicolas Chautru /* Set ring_base_addr */ 729efd45369SNicolas Chautru q->ring_addr = RTE_PTR_ADD(d->sw_rings, (d->sw_ring_size * queue_id)); 730efd45369SNicolas Chautru q->ring_ctrl_reg.ring_base_addr = d->sw_rings_phys + 731efd45369SNicolas Chautru (d->sw_ring_size * queue_id); 732efd45369SNicolas Chautru 733efd45369SNicolas Chautru /* Allocate memory for Completion Head variable*/ 734efd45369SNicolas Chautru q->ring_head_addr = rte_zmalloc_socket(dev->device->driver->name, 735efd45369SNicolas Chautru sizeof(uint64_t), RTE_CACHE_LINE_SIZE, conf->socket); 736efd45369SNicolas Chautru if (q->ring_head_addr == NULL) { 737efd45369SNicolas Chautru /* Mark queue as un-assigned */ 738efd45369SNicolas Chautru d->q_assigned_bit_map &= (0xFFFFFFFF - (1ULL << q_idx)); 739efd45369SNicolas Chautru rte_free(q); 740efd45369SNicolas Chautru rte_bbdev_log(ERR, 741efd45369SNicolas Chautru "Failed to allocate memory for %s:%u completion_head", 742efd45369SNicolas Chautru dev->device->driver->name, dev->data->dev_id); 743efd45369SNicolas Chautru return -ENOMEM; 744efd45369SNicolas Chautru } 745efd45369SNicolas Chautru /* Set ring_head_addr */ 746efd45369SNicolas Chautru q->ring_ctrl_reg.ring_head_addr = 747efd45369SNicolas Chautru rte_malloc_virt2iova(q->ring_head_addr); 748efd45369SNicolas Chautru 749efd45369SNicolas Chautru /* Clear shadow_completion_head */ 750efd45369SNicolas Chautru q->shadow_completion_head = 0; 751efd45369SNicolas Chautru 752efd45369SNicolas Chautru /* Set ring_size */ 753efd45369SNicolas Chautru if (conf->queue_size > FPGA_RING_MAX_SIZE) { 754efd45369SNicolas Chautru /* Mark queue as un-assigned */ 755efd45369SNicolas Chautru d->q_assigned_bit_map &= (0xFFFFFFFF - (1ULL << q_idx)); 756efd45369SNicolas Chautru rte_free(q->ring_head_addr); 757efd45369SNicolas Chautru rte_free(q); 758efd45369SNicolas Chautru rte_bbdev_log(ERR, 759efd45369SNicolas Chautru "Size of queue is too big %d (MAX: %d ) for %s:%u", 760efd45369SNicolas Chautru conf->queue_size, FPGA_RING_MAX_SIZE, 761efd45369SNicolas Chautru dev->device->driver->name, dev->data->dev_id); 762efd45369SNicolas Chautru return -EINVAL; 763efd45369SNicolas Chautru } 764efd45369SNicolas Chautru q->ring_ctrl_reg.ring_size = conf->queue_size; 765efd45369SNicolas Chautru 766efd45369SNicolas Chautru /* Set Miscellaneous FPGA register*/ 767efd45369SNicolas Chautru /* Max iteration number for TTI mitigation - todo */ 768efd45369SNicolas Chautru q->ring_ctrl_reg.max_ul_dec = 0; 769efd45369SNicolas Chautru /* Enable max iteration number for TTI - todo */ 770efd45369SNicolas Chautru q->ring_ctrl_reg.max_ul_dec_en = 0; 771efd45369SNicolas Chautru 772efd45369SNicolas Chautru /* Enable the ring */ 773efd45369SNicolas Chautru q->ring_ctrl_reg.enable = 1; 774efd45369SNicolas Chautru 775efd45369SNicolas Chautru /* Set FPGA head_point and tail registers */ 776efd45369SNicolas Chautru q->ring_ctrl_reg.head_point = q->tail = 0; 777efd45369SNicolas Chautru 778efd45369SNicolas Chautru /* Set FPGA shadow_tail register */ 779efd45369SNicolas Chautru q->ring_ctrl_reg.shadow_tail = q->tail; 780efd45369SNicolas Chautru 781efd45369SNicolas Chautru /* Calculates the ring offset for found queue */ 782efd45369SNicolas Chautru ring_offset = FPGA_LTE_FEC_RING_CTRL_REGS + 783efd45369SNicolas Chautru (sizeof(struct fpga_ring_ctrl_reg) * q_idx); 784efd45369SNicolas Chautru 785efd45369SNicolas Chautru /* Set FPGA Ring Control Registers */ 786efd45369SNicolas Chautru fpga_ring_reg_write(d->mmio_base, ring_offset, q->ring_ctrl_reg); 787efd45369SNicolas Chautru 788efd45369SNicolas Chautru /* Store MMIO register of shadow_tail */ 789efd45369SNicolas Chautru address = ring_offset + FPGA_LTE_FEC_RING_SHADOW_TAIL; 790efd45369SNicolas Chautru q->shadow_tail_addr = RTE_PTR_ADD(d->mmio_base, address); 791efd45369SNicolas Chautru 792efd45369SNicolas Chautru q->head_free_desc = q->tail; 793efd45369SNicolas Chautru 794efd45369SNicolas Chautru /* Set wrap mask */ 795efd45369SNicolas Chautru q->sw_ring_wrap_mask = conf->queue_size - 1; 796efd45369SNicolas Chautru 797efd45369SNicolas Chautru rte_bbdev_log_debug("Setup dev%u q%u: queue_idx=%u", 798efd45369SNicolas Chautru dev->data->dev_id, queue_id, q->q_idx); 799efd45369SNicolas Chautru 800efd45369SNicolas Chautru dev->data->queues[queue_id].queue_private = q; 801efd45369SNicolas Chautru 802efd45369SNicolas Chautru rte_bbdev_log_debug("BBDEV queue[%d] set up for FPGA queue[%d]", 803efd45369SNicolas Chautru queue_id, q_idx); 804efd45369SNicolas Chautru 805efd45369SNicolas Chautru #ifdef RTE_LIBRTE_BBDEV_DEBUG 806efd45369SNicolas Chautru /* Read FPGA Ring Control Registers after configuration*/ 807efd45369SNicolas Chautru print_ring_reg_debug_info(d->mmio_base, ring_offset); 808efd45369SNicolas Chautru #endif 809efd45369SNicolas Chautru return 0; 810efd45369SNicolas Chautru } 811efd45369SNicolas Chautru 812efd45369SNicolas Chautru static int 813efd45369SNicolas Chautru fpga_queue_release(struct rte_bbdev *dev, uint16_t queue_id) 814efd45369SNicolas Chautru { 815efd45369SNicolas Chautru struct fpga_lte_fec_device *d = dev->data->dev_private; 816efd45369SNicolas Chautru struct fpga_queue *q = dev->data->queues[queue_id].queue_private; 817efd45369SNicolas Chautru struct fpga_ring_ctrl_reg ring_reg; 818efd45369SNicolas Chautru uint32_t offset; 819efd45369SNicolas Chautru 820efd45369SNicolas Chautru rte_bbdev_log_debug("FPGA Queue[%d] released", queue_id); 821efd45369SNicolas Chautru 822efd45369SNicolas Chautru if (q != NULL) { 823efd45369SNicolas Chautru memset(&ring_reg, 0, sizeof(struct fpga_ring_ctrl_reg)); 824efd45369SNicolas Chautru offset = FPGA_LTE_FEC_RING_CTRL_REGS + 825efd45369SNicolas Chautru (sizeof(struct fpga_ring_ctrl_reg) * q->q_idx); 826efd45369SNicolas Chautru /* Disable queue */ 827efd45369SNicolas Chautru fpga_reg_write_8(d->mmio_base, 828efd45369SNicolas Chautru offset + FPGA_LTE_FEC_RING_ENABLE, 0x00); 829efd45369SNicolas Chautru /* Clear queue registers */ 830efd45369SNicolas Chautru fpga_ring_reg_write(d->mmio_base, offset, ring_reg); 831efd45369SNicolas Chautru 832efd45369SNicolas Chautru /* Mark the Queue as un-assigned */ 833efd45369SNicolas Chautru d->q_assigned_bit_map &= (0xFFFFFFFF - (1ULL << q->q_idx)); 834efd45369SNicolas Chautru rte_free(q->ring_head_addr); 835efd45369SNicolas Chautru rte_free(q); 836efd45369SNicolas Chautru dev->data->queues[queue_id].queue_private = NULL; 837efd45369SNicolas Chautru } 838efd45369SNicolas Chautru 839efd45369SNicolas Chautru return 0; 840efd45369SNicolas Chautru } 841efd45369SNicolas Chautru 842efd45369SNicolas Chautru /* Function starts a device queue. */ 843efd45369SNicolas Chautru static int 844efd45369SNicolas Chautru fpga_queue_start(struct rte_bbdev *dev, uint16_t queue_id) 845efd45369SNicolas Chautru { 846efd45369SNicolas Chautru struct fpga_lte_fec_device *d = dev->data->dev_private; 847efd45369SNicolas Chautru #ifdef RTE_LIBRTE_BBDEV_DEBUG 848efd45369SNicolas Chautru if (d == NULL) { 849efd45369SNicolas Chautru rte_bbdev_log(ERR, "Invalid device pointer"); 850efd45369SNicolas Chautru return -1; 851efd45369SNicolas Chautru } 852efd45369SNicolas Chautru #endif 853efd45369SNicolas Chautru struct fpga_queue *q = dev->data->queues[queue_id].queue_private; 854efd45369SNicolas Chautru uint32_t offset = FPGA_LTE_FEC_RING_CTRL_REGS + 855efd45369SNicolas Chautru (sizeof(struct fpga_ring_ctrl_reg) * q->q_idx); 856efd45369SNicolas Chautru uint8_t enable = 0x01; 857efd45369SNicolas Chautru uint16_t zero = 0x0000; 858efd45369SNicolas Chautru 859efd45369SNicolas Chautru /* Clear queue head and tail variables */ 860efd45369SNicolas Chautru q->tail = q->head_free_desc = 0; 861efd45369SNicolas Chautru 862efd45369SNicolas Chautru /* Clear FPGA head_point and tail registers */ 863efd45369SNicolas Chautru fpga_reg_write_16(d->mmio_base, offset + FPGA_LTE_FEC_RING_HEAD_POINT, 864efd45369SNicolas Chautru zero); 865efd45369SNicolas Chautru fpga_reg_write_16(d->mmio_base, offset + FPGA_LTE_FEC_RING_SHADOW_TAIL, 866efd45369SNicolas Chautru zero); 867efd45369SNicolas Chautru 868efd45369SNicolas Chautru /* Enable queue */ 869efd45369SNicolas Chautru fpga_reg_write_8(d->mmio_base, offset + FPGA_LTE_FEC_RING_ENABLE, 870efd45369SNicolas Chautru enable); 871efd45369SNicolas Chautru 872efd45369SNicolas Chautru rte_bbdev_log_debug("FPGA Queue[%d] started", queue_id); 873efd45369SNicolas Chautru return 0; 874efd45369SNicolas Chautru } 875efd45369SNicolas Chautru 876efd45369SNicolas Chautru /* Function stops a device queue. */ 877efd45369SNicolas Chautru static int 878efd45369SNicolas Chautru fpga_queue_stop(struct rte_bbdev *dev, uint16_t queue_id) 879efd45369SNicolas Chautru { 880efd45369SNicolas Chautru struct fpga_lte_fec_device *d = dev->data->dev_private; 881efd45369SNicolas Chautru #ifdef RTE_LIBRTE_BBDEV_DEBUG 882efd45369SNicolas Chautru if (d == NULL) { 883efd45369SNicolas Chautru rte_bbdev_log(ERR, "Invalid device pointer"); 884efd45369SNicolas Chautru return -1; 885efd45369SNicolas Chautru } 886efd45369SNicolas Chautru #endif 887efd45369SNicolas Chautru struct fpga_queue *q = dev->data->queues[queue_id].queue_private; 888efd45369SNicolas Chautru uint32_t offset = FPGA_LTE_FEC_RING_CTRL_REGS + 889efd45369SNicolas Chautru (sizeof(struct fpga_ring_ctrl_reg) * q->q_idx); 890efd45369SNicolas Chautru uint8_t payload = 0x01; 891efd45369SNicolas Chautru uint8_t counter = 0; 892efd45369SNicolas Chautru uint8_t timeout = FPGA_QUEUE_FLUSH_TIMEOUT_US / 893efd45369SNicolas Chautru FPGA_TIMEOUT_CHECK_INTERVAL; 894efd45369SNicolas Chautru 895efd45369SNicolas Chautru /* Set flush_queue_en bit to trigger queue flushing */ 896efd45369SNicolas Chautru fpga_reg_write_8(d->mmio_base, 897efd45369SNicolas Chautru offset + FPGA_LTE_FEC_RING_FLUSH_QUEUE_EN, payload); 898efd45369SNicolas Chautru 899efd45369SNicolas Chautru /** Check if queue flush is completed. 900efd45369SNicolas Chautru * FPGA will update the completion flag after queue flushing is 901efd45369SNicolas Chautru * completed. If completion flag is not updated within 1ms it is 902efd45369SNicolas Chautru * considered as a failure. 903efd45369SNicolas Chautru */ 904e12aabceSNicolas Chautru while (!(*((volatile uint8_t *)d->flush_queue_status + q->q_idx) & payload)) { 905efd45369SNicolas Chautru if (counter > timeout) { 906efd45369SNicolas Chautru rte_bbdev_log(ERR, "FPGA Queue Flush failed for queue %d", 907efd45369SNicolas Chautru queue_id); 908efd45369SNicolas Chautru return -1; 909efd45369SNicolas Chautru } 910efd45369SNicolas Chautru usleep(FPGA_TIMEOUT_CHECK_INTERVAL); 911efd45369SNicolas Chautru counter++; 912efd45369SNicolas Chautru } 913efd45369SNicolas Chautru 914efd45369SNicolas Chautru /* Disable queue */ 915efd45369SNicolas Chautru payload = 0x00; 916efd45369SNicolas Chautru fpga_reg_write_8(d->mmio_base, offset + FPGA_LTE_FEC_RING_ENABLE, 917efd45369SNicolas Chautru payload); 918efd45369SNicolas Chautru 919efd45369SNicolas Chautru rte_bbdev_log_debug("FPGA Queue[%d] stopped", queue_id); 920efd45369SNicolas Chautru return 0; 921efd45369SNicolas Chautru } 922efd45369SNicolas Chautru 923efd45369SNicolas Chautru static inline uint16_t 924efd45369SNicolas Chautru get_queue_id(struct rte_bbdev_data *data, uint8_t q_idx) 925efd45369SNicolas Chautru { 926efd45369SNicolas Chautru uint16_t queue_id; 927efd45369SNicolas Chautru 928efd45369SNicolas Chautru for (queue_id = 0; queue_id < data->num_queues; ++queue_id) { 929efd45369SNicolas Chautru struct fpga_queue *q = data->queues[queue_id].queue_private; 930efd45369SNicolas Chautru if (q != NULL && q->q_idx == q_idx) 931efd45369SNicolas Chautru return queue_id; 932efd45369SNicolas Chautru } 933efd45369SNicolas Chautru 934efd45369SNicolas Chautru return -1; 935efd45369SNicolas Chautru } 936efd45369SNicolas Chautru 937efd45369SNicolas Chautru /* Interrupt handler triggered by FPGA dev for handling specific interrupt */ 938efd45369SNicolas Chautru static void 939efd45369SNicolas Chautru fpga_dev_interrupt_handler(void *cb_arg) 940efd45369SNicolas Chautru { 941efd45369SNicolas Chautru struct rte_bbdev *dev = cb_arg; 942efd45369SNicolas Chautru struct fpga_lte_fec_device *fpga_dev = dev->data->dev_private; 943efd45369SNicolas Chautru struct fpga_queue *q; 944efd45369SNicolas Chautru uint64_t ring_head; 945efd45369SNicolas Chautru uint64_t q_idx; 946efd45369SNicolas Chautru uint16_t queue_id; 947efd45369SNicolas Chautru uint8_t i; 948efd45369SNicolas Chautru 949efd45369SNicolas Chautru /* Scan queue assigned to this device */ 950efd45369SNicolas Chautru for (i = 0; i < FPGA_TOTAL_NUM_QUEUES; ++i) { 951efd45369SNicolas Chautru q_idx = 1ULL << i; 952efd45369SNicolas Chautru if (fpga_dev->q_bound_bit_map & q_idx) { 953efd45369SNicolas Chautru queue_id = get_queue_id(dev->data, i); 954efd45369SNicolas Chautru if (queue_id == (uint16_t) -1) 955efd45369SNicolas Chautru continue; 956efd45369SNicolas Chautru 957efd45369SNicolas Chautru /* Check if completion head was changed */ 958efd45369SNicolas Chautru q = dev->data->queues[queue_id].queue_private; 959efd45369SNicolas Chautru ring_head = *q->ring_head_addr; 960efd45369SNicolas Chautru if (q->shadow_completion_head != ring_head && 961efd45369SNicolas Chautru q->irq_enable == 1) { 962efd45369SNicolas Chautru q->shadow_completion_head = ring_head; 963efd45369SNicolas Chautru rte_bbdev_pmd_callback_process( 964efd45369SNicolas Chautru dev, 965efd45369SNicolas Chautru RTE_BBDEV_EVENT_DEQUEUE, 966efd45369SNicolas Chautru &queue_id); 967efd45369SNicolas Chautru } 968efd45369SNicolas Chautru } 969efd45369SNicolas Chautru } 970efd45369SNicolas Chautru } 971efd45369SNicolas Chautru 972efd45369SNicolas Chautru static int 973efd45369SNicolas Chautru fpga_queue_intr_enable(struct rte_bbdev *dev, uint16_t queue_id) 974efd45369SNicolas Chautru { 975efd45369SNicolas Chautru struct fpga_queue *q = dev->data->queues[queue_id].queue_private; 976efd45369SNicolas Chautru 977efd45369SNicolas Chautru if (!rte_intr_cap_multiple(dev->intr_handle)) 978efd45369SNicolas Chautru return -ENOTSUP; 979efd45369SNicolas Chautru 980efd45369SNicolas Chautru q->irq_enable = 1; 981efd45369SNicolas Chautru 982efd45369SNicolas Chautru return 0; 983efd45369SNicolas Chautru } 984efd45369SNicolas Chautru 985efd45369SNicolas Chautru static int 986efd45369SNicolas Chautru fpga_queue_intr_disable(struct rte_bbdev *dev, uint16_t queue_id) 987efd45369SNicolas Chautru { 988efd45369SNicolas Chautru struct fpga_queue *q = dev->data->queues[queue_id].queue_private; 989efd45369SNicolas Chautru q->irq_enable = 0; 990efd45369SNicolas Chautru 991efd45369SNicolas Chautru return 0; 992efd45369SNicolas Chautru } 993efd45369SNicolas Chautru 994efd45369SNicolas Chautru static int 995efd45369SNicolas Chautru fpga_intr_enable(struct rte_bbdev *dev) 996efd45369SNicolas Chautru { 997efd45369SNicolas Chautru int ret; 998efd45369SNicolas Chautru uint8_t i; 999efd45369SNicolas Chautru 1000efd45369SNicolas Chautru if (!rte_intr_cap_multiple(dev->intr_handle)) { 1001efd45369SNicolas Chautru rte_bbdev_log(ERR, "Multiple intr vector is not supported by FPGA (%s)", 1002efd45369SNicolas Chautru dev->data->name); 1003efd45369SNicolas Chautru return -ENOTSUP; 1004efd45369SNicolas Chautru } 1005efd45369SNicolas Chautru 1006efd45369SNicolas Chautru /* Create event file descriptors for each of 64 queue. Event fds will be 1007efd45369SNicolas Chautru * mapped to FPGA IRQs in rte_intr_enable(). This is a 1:1 mapping where 1008efd45369SNicolas Chautru * the IRQ number is a direct translation to the queue number. 1009efd45369SNicolas Chautru * 1010efd45369SNicolas Chautru * 63 (FPGA_NUM_INTR_VEC) event fds are created as rte_intr_enable() 1011efd45369SNicolas Chautru * mapped the first IRQ to already created interrupt event file 1012efd45369SNicolas Chautru * descriptor (intr_handle->fd). 1013efd45369SNicolas Chautru */ 1014efd45369SNicolas Chautru if (rte_intr_efd_enable(dev->intr_handle, FPGA_NUM_INTR_VEC)) { 1015efd45369SNicolas Chautru rte_bbdev_log(ERR, "Failed to create fds for %u queues", 1016efd45369SNicolas Chautru dev->data->num_queues); 1017efd45369SNicolas Chautru return -1; 1018efd45369SNicolas Chautru } 1019efd45369SNicolas Chautru 1020efd45369SNicolas Chautru /* TODO Each event file descriptor is overwritten by interrupt event 1021efd45369SNicolas Chautru * file descriptor. That descriptor is added to epoll observed list. 1022efd45369SNicolas Chautru * It ensures that callback function assigned to that descriptor will 1023efd45369SNicolas Chautru * invoked when any FPGA queue issues interrupt. 1024efd45369SNicolas Chautru */ 1025d61138d4SHarman Kalra for (i = 0; i < FPGA_NUM_INTR_VEC; ++i) { 1026d61138d4SHarman Kalra if (rte_intr_efds_index_set(dev->intr_handle, i, 1027d61138d4SHarman Kalra rte_intr_fd_get(dev->intr_handle))) 1028d61138d4SHarman Kalra return -rte_errno; 1029d61138d4SHarman Kalra } 1030efd45369SNicolas Chautru 1031d61138d4SHarman Kalra if (rte_intr_vec_list_alloc(dev->intr_handle, "intr_vec", 1032d61138d4SHarman Kalra dev->data->num_queues)) { 1033efd45369SNicolas Chautru rte_bbdev_log(ERR, "Failed to allocate %u vectors", 1034efd45369SNicolas Chautru dev->data->num_queues); 1035efd45369SNicolas Chautru return -ENOMEM; 1036efd45369SNicolas Chautru } 1037efd45369SNicolas Chautru 1038efd45369SNicolas Chautru ret = rte_intr_enable(dev->intr_handle); 1039efd45369SNicolas Chautru if (ret < 0) { 1040efd45369SNicolas Chautru rte_bbdev_log(ERR, 1041efd45369SNicolas Chautru "Couldn't enable interrupts for device: %s", 1042efd45369SNicolas Chautru dev->data->name); 1043efd45369SNicolas Chautru return ret; 1044efd45369SNicolas Chautru } 1045efd45369SNicolas Chautru 1046efd45369SNicolas Chautru ret = rte_intr_callback_register(dev->intr_handle, 1047efd45369SNicolas Chautru fpga_dev_interrupt_handler, dev); 1048efd45369SNicolas Chautru if (ret < 0) { 1049efd45369SNicolas Chautru rte_bbdev_log(ERR, 1050efd45369SNicolas Chautru "Couldn't register interrupt callback for device: %s", 1051efd45369SNicolas Chautru dev->data->name); 1052efd45369SNicolas Chautru return ret; 1053efd45369SNicolas Chautru } 1054efd45369SNicolas Chautru 1055efd45369SNicolas Chautru return 0; 1056efd45369SNicolas Chautru } 1057efd45369SNicolas Chautru 1058efd45369SNicolas Chautru static const struct rte_bbdev_ops fpga_ops = { 1059efd45369SNicolas Chautru .setup_queues = fpga_setup_queues, 1060efd45369SNicolas Chautru .intr_enable = fpga_intr_enable, 1061efd45369SNicolas Chautru .close = fpga_dev_close, 1062efd45369SNicolas Chautru .info_get = fpga_dev_info_get, 1063efd45369SNicolas Chautru .queue_setup = fpga_queue_setup, 1064efd45369SNicolas Chautru .queue_stop = fpga_queue_stop, 1065efd45369SNicolas Chautru .queue_start = fpga_queue_start, 1066efd45369SNicolas Chautru .queue_release = fpga_queue_release, 1067efd45369SNicolas Chautru .queue_intr_enable = fpga_queue_intr_enable, 1068efd45369SNicolas Chautru .queue_intr_disable = fpga_queue_intr_disable 1069efd45369SNicolas Chautru }; 1070efd45369SNicolas Chautru 1071efd45369SNicolas Chautru static inline void 1072efd45369SNicolas Chautru fpga_dma_enqueue(struct fpga_queue *q, uint16_t num_desc, 1073efd45369SNicolas Chautru struct rte_bbdev_stats *queue_stats) 1074efd45369SNicolas Chautru { 1075efd45369SNicolas Chautru uint64_t start_time = 0; 1076efd45369SNicolas Chautru queue_stats->acc_offload_cycles = 0; 1077efd45369SNicolas Chautru 1078efd45369SNicolas Chautru /* Update tail and shadow_tail register */ 1079efd45369SNicolas Chautru q->tail = (q->tail + num_desc) & q->sw_ring_wrap_mask; 1080efd45369SNicolas Chautru 1081efd45369SNicolas Chautru rte_wmb(); 1082efd45369SNicolas Chautru 1083efd45369SNicolas Chautru /* Start time measurement for enqueue function offload. */ 1084efd45369SNicolas Chautru start_time = rte_rdtsc_precise(); 1085efd45369SNicolas Chautru mmio_write_16(q->shadow_tail_addr, q->tail); 1086efd45369SNicolas Chautru 1087efd45369SNicolas Chautru rte_wmb(); 1088efd45369SNicolas Chautru queue_stats->acc_offload_cycles += rte_rdtsc_precise() - start_time; 1089efd45369SNicolas Chautru } 1090efd45369SNicolas Chautru 1091efd45369SNicolas Chautru /* Calculates number of CBs in processed encoder TB based on 'r' and input 1092efd45369SNicolas Chautru * length. 1093efd45369SNicolas Chautru */ 1094efd45369SNicolas Chautru static inline uint8_t 1095efd45369SNicolas Chautru get_num_cbs_in_op_enc(struct rte_bbdev_op_turbo_enc *turbo_enc) 1096efd45369SNicolas Chautru { 1097efd45369SNicolas Chautru uint8_t c, c_neg, r, crc24_bits = 0; 1098efd45369SNicolas Chautru uint16_t k, k_neg, k_pos; 1099efd45369SNicolas Chautru uint8_t cbs_in_op = 0; 1100efd45369SNicolas Chautru int32_t length; 1101efd45369SNicolas Chautru 1102efd45369SNicolas Chautru length = turbo_enc->input.length; 1103efd45369SNicolas Chautru r = turbo_enc->tb_params.r; 1104efd45369SNicolas Chautru c = turbo_enc->tb_params.c; 1105efd45369SNicolas Chautru c_neg = turbo_enc->tb_params.c_neg; 1106efd45369SNicolas Chautru k_neg = turbo_enc->tb_params.k_neg; 1107efd45369SNicolas Chautru k_pos = turbo_enc->tb_params.k_pos; 1108efd45369SNicolas Chautru crc24_bits = 24; 1109efd45369SNicolas Chautru while (length > 0 && r < c) { 1110efd45369SNicolas Chautru k = (r < c_neg) ? k_neg : k_pos; 1111efd45369SNicolas Chautru length -= (k - crc24_bits) >> 3; 1112efd45369SNicolas Chautru r++; 1113efd45369SNicolas Chautru cbs_in_op++; 1114efd45369SNicolas Chautru } 1115efd45369SNicolas Chautru 1116efd45369SNicolas Chautru return cbs_in_op; 1117efd45369SNicolas Chautru } 1118efd45369SNicolas Chautru 1119efd45369SNicolas Chautru /* Calculates number of CBs in processed decoder TB based on 'r' and input 1120efd45369SNicolas Chautru * length. 1121efd45369SNicolas Chautru */ 1122efd45369SNicolas Chautru static inline uint16_t 1123efd45369SNicolas Chautru get_num_cbs_in_op_dec(struct rte_bbdev_op_turbo_dec *turbo_dec) 1124efd45369SNicolas Chautru { 1125efd45369SNicolas Chautru uint8_t c, c_neg, r = 0; 1126efd45369SNicolas Chautru uint16_t kw, k, k_neg, k_pos, cbs_in_op = 0; 1127efd45369SNicolas Chautru int32_t length; 1128efd45369SNicolas Chautru 1129efd45369SNicolas Chautru length = turbo_dec->input.length; 1130efd45369SNicolas Chautru r = turbo_dec->tb_params.r; 1131efd45369SNicolas Chautru c = turbo_dec->tb_params.c; 1132efd45369SNicolas Chautru c_neg = turbo_dec->tb_params.c_neg; 1133efd45369SNicolas Chautru k_neg = turbo_dec->tb_params.k_neg; 1134efd45369SNicolas Chautru k_pos = turbo_dec->tb_params.k_pos; 1135efd45369SNicolas Chautru while (length > 0 && r < c) { 1136efd45369SNicolas Chautru k = (r < c_neg) ? k_neg : k_pos; 1137efd45369SNicolas Chautru kw = RTE_ALIGN_CEIL(k + 4, 32) * 3; 1138efd45369SNicolas Chautru length -= kw; 1139efd45369SNicolas Chautru r++; 1140efd45369SNicolas Chautru cbs_in_op++; 1141efd45369SNicolas Chautru } 1142efd45369SNicolas Chautru 1143efd45369SNicolas Chautru return cbs_in_op; 1144efd45369SNicolas Chautru } 1145efd45369SNicolas Chautru 1146efd45369SNicolas Chautru /* Read flag value 0/1/ from bitmap */ 1147efd45369SNicolas Chautru static inline bool 1148efd45369SNicolas Chautru check_bit(uint32_t bitmap, uint32_t bitmask) 1149efd45369SNicolas Chautru { 1150efd45369SNicolas Chautru return bitmap & bitmask; 1151efd45369SNicolas Chautru } 1152efd45369SNicolas Chautru 1153efd45369SNicolas Chautru /* Print an error if a descriptor error has occurred. 1154efd45369SNicolas Chautru * Return 0 on success, 1 on failure 1155efd45369SNicolas Chautru */ 1156efd45369SNicolas Chautru static inline int 1157efd45369SNicolas Chautru check_desc_error(uint32_t error_code) { 1158efd45369SNicolas Chautru switch (error_code) { 1159efd45369SNicolas Chautru case DESC_ERR_NO_ERR: 1160efd45369SNicolas Chautru return 0; 1161efd45369SNicolas Chautru case DESC_ERR_K_OUT_OF_RANGE: 1162efd45369SNicolas Chautru rte_bbdev_log(ERR, "Block_size_k is out of range (k<40 or k>6144)"); 1163efd45369SNicolas Chautru break; 1164efd45369SNicolas Chautru case DESC_ERR_K_NOT_NORMAL: 1165efd45369SNicolas Chautru rte_bbdev_log(ERR, "Block_size_k is not a normal value within normal range"); 1166efd45369SNicolas Chautru break; 1167efd45369SNicolas Chautru case DESC_ERR_KPAI_NOT_NORMAL: 1168efd45369SNicolas Chautru rte_bbdev_log(ERR, "Three_kpai is not a normal value for UL only"); 1169efd45369SNicolas Chautru break; 1170efd45369SNicolas Chautru case DESC_ERR_DESC_OFFSET_ERR: 1171efd45369SNicolas Chautru rte_bbdev_log(ERR, "Queue offset does not meet the expectation in the FPGA"); 1172efd45369SNicolas Chautru break; 1173efd45369SNicolas Chautru case (DESC_ERR_K_OUT_OF_RANGE | DESC_ERR_DESC_OFFSET_ERR): 1174efd45369SNicolas Chautru rte_bbdev_log(ERR, "Block_size_k is out of range (k<40 or k>6144) and queue offset error"); 1175efd45369SNicolas Chautru break; 1176efd45369SNicolas Chautru case (DESC_ERR_K_NOT_NORMAL | DESC_ERR_DESC_OFFSET_ERR): 1177efd45369SNicolas Chautru rte_bbdev_log(ERR, "Block_size_k is not a normal value within normal range and queue offset error"); 1178efd45369SNicolas Chautru break; 1179efd45369SNicolas Chautru case (DESC_ERR_KPAI_NOT_NORMAL | DESC_ERR_DESC_OFFSET_ERR): 1180efd45369SNicolas Chautru rte_bbdev_log(ERR, "Three_kpai is not a normal value for UL only and queue offset error"); 1181efd45369SNicolas Chautru break; 1182efd45369SNicolas Chautru case DESC_ERR_DESC_READ_FAIL: 1183efd45369SNicolas Chautru rte_bbdev_log(ERR, "Unsuccessful completion for descriptor read"); 1184efd45369SNicolas Chautru break; 1185efd45369SNicolas Chautru case DESC_ERR_DESC_READ_TIMEOUT: 1186efd45369SNicolas Chautru rte_bbdev_log(ERR, "Descriptor read time-out"); 1187efd45369SNicolas Chautru break; 1188efd45369SNicolas Chautru case DESC_ERR_DESC_READ_TLP_POISONED: 1189efd45369SNicolas Chautru rte_bbdev_log(ERR, "Descriptor read TLP poisoned"); 1190efd45369SNicolas Chautru break; 1191efd45369SNicolas Chautru case DESC_ERR_CB_READ_FAIL: 1192efd45369SNicolas Chautru rte_bbdev_log(ERR, "Unsuccessful completion for code block"); 1193efd45369SNicolas Chautru break; 1194efd45369SNicolas Chautru case DESC_ERR_CB_READ_TIMEOUT: 1195efd45369SNicolas Chautru rte_bbdev_log(ERR, "Code block read time-out"); 1196efd45369SNicolas Chautru break; 1197efd45369SNicolas Chautru case DESC_ERR_CB_READ_TLP_POISONED: 1198efd45369SNicolas Chautru rte_bbdev_log(ERR, "Code block read TLP poisoned"); 1199efd45369SNicolas Chautru break; 1200efd45369SNicolas Chautru default: 1201efd45369SNicolas Chautru rte_bbdev_log(ERR, "Descriptor error unknown error code %u", 1202efd45369SNicolas Chautru error_code); 1203efd45369SNicolas Chautru break; 1204efd45369SNicolas Chautru } 1205efd45369SNicolas Chautru return 1; 1206efd45369SNicolas Chautru } 1207efd45369SNicolas Chautru 1208efd45369SNicolas Chautru /** 1209efd45369SNicolas Chautru * Set DMA descriptor for encode operation (1 Code Block) 1210efd45369SNicolas Chautru * 1211efd45369SNicolas Chautru * @param op 1212efd45369SNicolas Chautru * Pointer to a single encode operation. 1213efd45369SNicolas Chautru * @param desc 1214efd45369SNicolas Chautru * Pointer to DMA descriptor. 1215efd45369SNicolas Chautru * @param input 1216efd45369SNicolas Chautru * Pointer to pointer to input data which will be decoded. 1217efd45369SNicolas Chautru * @param k 1218efd45369SNicolas Chautru * K value (length of input in bits). 1219efd45369SNicolas Chautru * @param e 1220efd45369SNicolas Chautru * E value (length of output in bits). 1221efd45369SNicolas Chautru * @param ncb 1222efd45369SNicolas Chautru * Ncb value (size of the soft buffer). 1223efd45369SNicolas Chautru * @param out_length 1224efd45369SNicolas Chautru * Length of output buffer 1225efd45369SNicolas Chautru * @param in_offset 1226efd45369SNicolas Chautru * Input offset in rte_mbuf structure. It is used for calculating the point 1227efd45369SNicolas Chautru * where data is starting. 1228efd45369SNicolas Chautru * @param out_offset 1229efd45369SNicolas Chautru * Output offset in rte_mbuf structure. It is used for calculating the point 1230efd45369SNicolas Chautru * where hard output data will be stored. 1231efd45369SNicolas Chautru * @param cbs_in_op 1232efd45369SNicolas Chautru * Number of CBs contained in one operation. 1233efd45369SNicolas Chautru */ 1234efd45369SNicolas Chautru static inline int 1235efd45369SNicolas Chautru fpga_dma_desc_te_fill(struct rte_bbdev_enc_op *op, 1236efd45369SNicolas Chautru struct fpga_dma_enc_desc *desc, struct rte_mbuf *input, 1237efd45369SNicolas Chautru struct rte_mbuf *output, uint16_t k, uint16_t e, uint16_t ncb, 1238efd45369SNicolas Chautru uint32_t in_offset, uint32_t out_offset, uint16_t desc_offset, 1239efd45369SNicolas Chautru uint8_t cbs_in_op) 1240efd45369SNicolas Chautru 1241efd45369SNicolas Chautru { 1242efd45369SNicolas Chautru /* reset */ 1243efd45369SNicolas Chautru desc->done = 0; 1244efd45369SNicolas Chautru desc->crc_en = check_bit(op->turbo_enc.op_flags, 1245efd45369SNicolas Chautru RTE_BBDEV_TURBO_CRC_24B_ATTACH); 1246efd45369SNicolas Chautru desc->bypass_rm = !check_bit(op->turbo_enc.op_flags, 1247efd45369SNicolas Chautru RTE_BBDEV_TURBO_RATE_MATCH); 1248efd45369SNicolas Chautru desc->k = k; 1249efd45369SNicolas Chautru desc->e = e; 1250efd45369SNicolas Chautru desc->ncb = ncb; 1251efd45369SNicolas Chautru desc->rv = op->turbo_enc.rv_index; 1252efd45369SNicolas Chautru desc->offset = desc_offset; 1253efd45369SNicolas Chautru /* Set inbound data buffer address */ 1254efd45369SNicolas Chautru desc->in_addr_hi = (uint32_t)( 1255ce627d63SThomas Monjalon rte_pktmbuf_iova_offset(input, in_offset) >> 32); 1256efd45369SNicolas Chautru desc->in_addr_lw = (uint32_t)( 1257ce627d63SThomas Monjalon rte_pktmbuf_iova_offset(input, in_offset)); 1258efd45369SNicolas Chautru 1259efd45369SNicolas Chautru desc->out_addr_hi = (uint32_t)( 1260ce627d63SThomas Monjalon rte_pktmbuf_iova_offset(output, out_offset) >> 32); 1261efd45369SNicolas Chautru desc->out_addr_lw = (uint32_t)( 1262ce627d63SThomas Monjalon rte_pktmbuf_iova_offset(output, out_offset)); 1263efd45369SNicolas Chautru 1264efd45369SNicolas Chautru /* Save software context needed for dequeue */ 1265efd45369SNicolas Chautru desc->op_addr = op; 1266efd45369SNicolas Chautru 1267efd45369SNicolas Chautru /* Set total number of CBs in an op */ 1268efd45369SNicolas Chautru desc->cbs_in_op = cbs_in_op; 1269efd45369SNicolas Chautru 1270efd45369SNicolas Chautru return 0; 1271efd45369SNicolas Chautru } 1272efd45369SNicolas Chautru 1273efd45369SNicolas Chautru /** 1274efd45369SNicolas Chautru * Set DMA descriptor for encode operation (1 Code Block) 1275efd45369SNicolas Chautru * 1276efd45369SNicolas Chautru * @param op 1277efd45369SNicolas Chautru * Pointer to a single encode operation. 1278efd45369SNicolas Chautru * @param desc 1279efd45369SNicolas Chautru * Pointer to DMA descriptor. 1280efd45369SNicolas Chautru * @param input 1281efd45369SNicolas Chautru * Pointer to pointer to input data which will be decoded. 1282efd45369SNicolas Chautru * @param in_length 1283efd45369SNicolas Chautru * Length of an input. 1284efd45369SNicolas Chautru * @param k 1285efd45369SNicolas Chautru * K value (length of an output in bits). 1286efd45369SNicolas Chautru * @param in_offset 1287efd45369SNicolas Chautru * Input offset in rte_mbuf structure. It is used for calculating the point 1288efd45369SNicolas Chautru * where data is starting. 1289efd45369SNicolas Chautru * @param out_offset 1290efd45369SNicolas Chautru * Output offset in rte_mbuf structure. It is used for calculating the point 1291efd45369SNicolas Chautru * where hard output data will be stored. 1292efd45369SNicolas Chautru * @param cbs_in_op 1293efd45369SNicolas Chautru * Number of CBs contained in one operation. 1294efd45369SNicolas Chautru */ 1295efd45369SNicolas Chautru static inline int 1296efd45369SNicolas Chautru fpga_dma_desc_td_fill(struct rte_bbdev_dec_op *op, 1297efd45369SNicolas Chautru struct fpga_dma_dec_desc *desc, struct rte_mbuf *input, 1298efd45369SNicolas Chautru struct rte_mbuf *output, uint16_t in_length, uint16_t k, 1299efd45369SNicolas Chautru uint32_t in_offset, uint32_t out_offset, uint16_t desc_offset, 1300efd45369SNicolas Chautru uint8_t cbs_in_op) 1301efd45369SNicolas Chautru { 1302efd45369SNicolas Chautru /* reset */ 1303efd45369SNicolas Chautru desc->done = 0; 1304efd45369SNicolas Chautru /* Set inbound data buffer address */ 1305efd45369SNicolas Chautru desc->in_addr_hi = (uint32_t)( 1306ce627d63SThomas Monjalon rte_pktmbuf_iova_offset(input, in_offset) >> 32); 1307efd45369SNicolas Chautru desc->in_addr_lw = (uint32_t)( 1308ce627d63SThomas Monjalon rte_pktmbuf_iova_offset(input, in_offset)); 1309efd45369SNicolas Chautru desc->in_len = in_length; 1310efd45369SNicolas Chautru desc->k = k; 1311efd45369SNicolas Chautru desc->crc_type = !check_bit(op->turbo_dec.op_flags, 1312efd45369SNicolas Chautru RTE_BBDEV_TURBO_CRC_TYPE_24B); 131348fc315fSNicolas Chautru if ((op->turbo_dec.code_block_mode == RTE_BBDEV_TRANSPORT_BLOCK) 1314efd45369SNicolas Chautru && !check_bit(op->turbo_dec.op_flags, 1315efd45369SNicolas Chautru RTE_BBDEV_TURBO_DEC_TB_CRC_24B_KEEP)) 1316efd45369SNicolas Chautru desc->drop_crc = 1; 1317efd45369SNicolas Chautru desc->max_iter = op->turbo_dec.iter_max * 2; 1318efd45369SNicolas Chautru desc->offset = desc_offset; 1319efd45369SNicolas Chautru desc->out_addr_hi = (uint32_t)( 1320ce627d63SThomas Monjalon rte_pktmbuf_iova_offset(output, out_offset) >> 32); 1321efd45369SNicolas Chautru desc->out_addr_lw = (uint32_t)( 1322ce627d63SThomas Monjalon rte_pktmbuf_iova_offset(output, out_offset)); 1323efd45369SNicolas Chautru 1324efd45369SNicolas Chautru /* Save software context needed for dequeue */ 1325efd45369SNicolas Chautru desc->op_addr = op; 1326efd45369SNicolas Chautru 1327efd45369SNicolas Chautru /* Set total number of CBs in an op */ 1328efd45369SNicolas Chautru desc->cbs_in_op = cbs_in_op; 1329efd45369SNicolas Chautru 1330efd45369SNicolas Chautru return 0; 1331efd45369SNicolas Chautru } 1332efd45369SNicolas Chautru 1333efd45369SNicolas Chautru #ifdef RTE_LIBRTE_BBDEV_DEBUG 1334efd45369SNicolas Chautru /* Validates turbo encoder parameters */ 1335efd45369SNicolas Chautru static int 1336efd45369SNicolas Chautru validate_enc_op(struct rte_bbdev_enc_op *op) 1337efd45369SNicolas Chautru { 1338efd45369SNicolas Chautru struct rte_bbdev_op_turbo_enc *turbo_enc = &op->turbo_enc; 1339c4b0d663SNicolas Chautru struct rte_bbdev_op_enc_turbo_cb_params *cb = NULL; 1340c4b0d663SNicolas Chautru struct rte_bbdev_op_enc_turbo_tb_params *tb = NULL; 1341efd45369SNicolas Chautru uint16_t kw, kw_neg, kw_pos; 1342efd45369SNicolas Chautru 1343efd45369SNicolas Chautru if (turbo_enc->input.length > 1344c4b0d663SNicolas Chautru RTE_BBDEV_TURBO_MAX_TB_SIZE >> 3) { 1345efd45369SNicolas Chautru rte_bbdev_log(ERR, "TB size (%u) is too big, max: %d", 1346c4b0d663SNicolas Chautru turbo_enc->input.length, 1347c4b0d663SNicolas Chautru RTE_BBDEV_TURBO_MAX_TB_SIZE); 1348efd45369SNicolas Chautru op->status = 1 << RTE_BBDEV_DATA_ERROR; 1349efd45369SNicolas Chautru return -1; 1350efd45369SNicolas Chautru } 1351efd45369SNicolas Chautru 1352efd45369SNicolas Chautru if (op->mempool == NULL) { 1353efd45369SNicolas Chautru rte_bbdev_log(ERR, "Invalid mempool pointer"); 1354efd45369SNicolas Chautru return -1; 1355efd45369SNicolas Chautru } 1356efd45369SNicolas Chautru if (turbo_enc->input.data == NULL) { 1357efd45369SNicolas Chautru rte_bbdev_log(ERR, "Invalid input pointer"); 1358efd45369SNicolas Chautru return -1; 1359efd45369SNicolas Chautru } 1360efd45369SNicolas Chautru if (turbo_enc->output.data == NULL) { 1361efd45369SNicolas Chautru rte_bbdev_log(ERR, "Invalid output pointer"); 1362efd45369SNicolas Chautru return -1; 1363efd45369SNicolas Chautru } 1364efd45369SNicolas Chautru if (turbo_enc->rv_index > 3) { 1365efd45369SNicolas Chautru rte_bbdev_log(ERR, 1366efd45369SNicolas Chautru "rv_index (%u) is out of range 0 <= value <= 3", 1367efd45369SNicolas Chautru turbo_enc->rv_index); 1368efd45369SNicolas Chautru return -1; 1369efd45369SNicolas Chautru } 137048fc315fSNicolas Chautru if (turbo_enc->code_block_mode != RTE_BBDEV_TRANSPORT_BLOCK && 137148fc315fSNicolas Chautru turbo_enc->code_block_mode != RTE_BBDEV_CODE_BLOCK) { 1372efd45369SNicolas Chautru rte_bbdev_log(ERR, 1373efd45369SNicolas Chautru "code_block_mode (%u) is out of range 0 <= value <= 1", 1374efd45369SNicolas Chautru turbo_enc->code_block_mode); 1375efd45369SNicolas Chautru return -1; 1376efd45369SNicolas Chautru } 1377efd45369SNicolas Chautru 137848fc315fSNicolas Chautru if (turbo_enc->code_block_mode == RTE_BBDEV_TRANSPORT_BLOCK) { 1379efd45369SNicolas Chautru tb = &turbo_enc->tb_params; 1380c4b0d663SNicolas Chautru if ((tb->k_neg < RTE_BBDEV_TURBO_MIN_CB_SIZE 1381c4b0d663SNicolas Chautru || tb->k_neg > RTE_BBDEV_TURBO_MAX_CB_SIZE) 1382efd45369SNicolas Chautru && tb->c_neg > 0) { 1383efd45369SNicolas Chautru rte_bbdev_log(ERR, 1384efd45369SNicolas Chautru "k_neg (%u) is out of range %u <= value <= %u", 1385c4b0d663SNicolas Chautru tb->k_neg, RTE_BBDEV_TURBO_MIN_CB_SIZE, 1386c4b0d663SNicolas Chautru RTE_BBDEV_TURBO_MAX_CB_SIZE); 1387efd45369SNicolas Chautru return -1; 1388efd45369SNicolas Chautru } 1389c4b0d663SNicolas Chautru if (tb->k_pos < RTE_BBDEV_TURBO_MIN_CB_SIZE 1390c4b0d663SNicolas Chautru || tb->k_pos > RTE_BBDEV_TURBO_MAX_CB_SIZE) { 1391efd45369SNicolas Chautru rte_bbdev_log(ERR, 1392efd45369SNicolas Chautru "k_pos (%u) is out of range %u <= value <= %u", 1393c4b0d663SNicolas Chautru tb->k_pos, RTE_BBDEV_TURBO_MIN_CB_SIZE, 1394c4b0d663SNicolas Chautru RTE_BBDEV_TURBO_MAX_CB_SIZE); 1395efd45369SNicolas Chautru return -1; 1396efd45369SNicolas Chautru } 1397c4b0d663SNicolas Chautru if (tb->c_neg > (RTE_BBDEV_TURBO_MAX_CODE_BLOCKS - 1)) 1398efd45369SNicolas Chautru rte_bbdev_log(ERR, 1399efd45369SNicolas Chautru "c_neg (%u) is out of range 0 <= value <= %u", 1400efd45369SNicolas Chautru tb->c_neg, 1401c4b0d663SNicolas Chautru RTE_BBDEV_TURBO_MAX_CODE_BLOCKS - 1); 1402c4b0d663SNicolas Chautru if (tb->c < 1 || tb->c > RTE_BBDEV_TURBO_MAX_CODE_BLOCKS) { 1403efd45369SNicolas Chautru rte_bbdev_log(ERR, 1404efd45369SNicolas Chautru "c (%u) is out of range 1 <= value <= %u", 1405c4b0d663SNicolas Chautru tb->c, RTE_BBDEV_TURBO_MAX_CODE_BLOCKS); 1406efd45369SNicolas Chautru return -1; 1407efd45369SNicolas Chautru } 1408efd45369SNicolas Chautru if (tb->cab > tb->c) { 1409efd45369SNicolas Chautru rte_bbdev_log(ERR, 1410efd45369SNicolas Chautru "cab (%u) is greater than c (%u)", 1411efd45369SNicolas Chautru tb->cab, tb->c); 1412efd45369SNicolas Chautru return -1; 1413efd45369SNicolas Chautru } 1414c4b0d663SNicolas Chautru if ((tb->ea < RTE_BBDEV_TURBO_MIN_CB_SIZE || (tb->ea % 2)) 1415efd45369SNicolas Chautru && tb->r < tb->cab) { 1416efd45369SNicolas Chautru rte_bbdev_log(ERR, 1417efd45369SNicolas Chautru "ea (%u) is less than %u or it is not even", 1418c4b0d663SNicolas Chautru tb->ea, RTE_BBDEV_TURBO_MIN_CB_SIZE); 1419efd45369SNicolas Chautru return -1; 1420efd45369SNicolas Chautru } 1421c4b0d663SNicolas Chautru if ((tb->eb < RTE_BBDEV_TURBO_MIN_CB_SIZE || (tb->eb % 2)) 1422efd45369SNicolas Chautru && tb->c > tb->cab) { 1423efd45369SNicolas Chautru rte_bbdev_log(ERR, 1424efd45369SNicolas Chautru "eb (%u) is less than %u or it is not even", 1425c4b0d663SNicolas Chautru tb->eb, RTE_BBDEV_TURBO_MIN_CB_SIZE); 1426efd45369SNicolas Chautru return -1; 1427efd45369SNicolas Chautru } 1428efd45369SNicolas Chautru 1429efd45369SNicolas Chautru kw_neg = 3 * RTE_ALIGN_CEIL(tb->k_neg + 4, 1430c4b0d663SNicolas Chautru RTE_BBDEV_TURBO_C_SUBBLOCK); 1431efd45369SNicolas Chautru if (tb->ncb_neg < tb->k_neg || tb->ncb_neg > kw_neg) { 1432efd45369SNicolas Chautru rte_bbdev_log(ERR, 1433efd45369SNicolas Chautru "ncb_neg (%u) is out of range (%u) k_neg <= value <= (%u) kw_neg", 1434efd45369SNicolas Chautru tb->ncb_neg, tb->k_neg, kw_neg); 1435efd45369SNicolas Chautru return -1; 1436efd45369SNicolas Chautru } 1437efd45369SNicolas Chautru 1438efd45369SNicolas Chautru kw_pos = 3 * RTE_ALIGN_CEIL(tb->k_pos + 4, 1439c4b0d663SNicolas Chautru RTE_BBDEV_TURBO_C_SUBBLOCK); 1440efd45369SNicolas Chautru if (tb->ncb_pos < tb->k_pos || tb->ncb_pos > kw_pos) { 1441efd45369SNicolas Chautru rte_bbdev_log(ERR, 1442efd45369SNicolas Chautru "ncb_pos (%u) is out of range (%u) k_pos <= value <= (%u) kw_pos", 1443efd45369SNicolas Chautru tb->ncb_pos, tb->k_pos, kw_pos); 1444efd45369SNicolas Chautru return -1; 1445efd45369SNicolas Chautru } 1446efd45369SNicolas Chautru if (tb->r > (tb->c - 1)) { 1447efd45369SNicolas Chautru rte_bbdev_log(ERR, 1448efd45369SNicolas Chautru "r (%u) is greater than c - 1 (%u)", 1449efd45369SNicolas Chautru tb->r, tb->c - 1); 1450efd45369SNicolas Chautru return -1; 1451efd45369SNicolas Chautru } 1452efd45369SNicolas Chautru } else { 1453efd45369SNicolas Chautru cb = &turbo_enc->cb_params; 1454c4b0d663SNicolas Chautru if (cb->k < RTE_BBDEV_TURBO_MIN_CB_SIZE 1455c4b0d663SNicolas Chautru || cb->k > RTE_BBDEV_TURBO_MAX_CB_SIZE) { 1456efd45369SNicolas Chautru rte_bbdev_log(ERR, 1457efd45369SNicolas Chautru "k (%u) is out of range %u <= value <= %u", 1458c4b0d663SNicolas Chautru cb->k, RTE_BBDEV_TURBO_MIN_CB_SIZE, 1459c4b0d663SNicolas Chautru RTE_BBDEV_TURBO_MAX_CB_SIZE); 1460efd45369SNicolas Chautru return -1; 1461efd45369SNicolas Chautru } 1462efd45369SNicolas Chautru 1463c4b0d663SNicolas Chautru if (cb->e < RTE_BBDEV_TURBO_MIN_CB_SIZE || (cb->e % 2)) { 1464efd45369SNicolas Chautru rte_bbdev_log(ERR, 1465efd45369SNicolas Chautru "e (%u) is less than %u or it is not even", 1466c4b0d663SNicolas Chautru cb->e, RTE_BBDEV_TURBO_MIN_CB_SIZE); 1467efd45369SNicolas Chautru return -1; 1468efd45369SNicolas Chautru } 1469efd45369SNicolas Chautru 1470c4b0d663SNicolas Chautru kw = RTE_ALIGN_CEIL(cb->k + 4, RTE_BBDEV_TURBO_C_SUBBLOCK) * 3; 1471efd45369SNicolas Chautru if (cb->ncb < cb->k || cb->ncb > kw) { 1472efd45369SNicolas Chautru rte_bbdev_log(ERR, 1473efd45369SNicolas Chautru "ncb (%u) is out of range (%u) k <= value <= (%u) kw", 1474efd45369SNicolas Chautru cb->ncb, cb->k, kw); 1475efd45369SNicolas Chautru return -1; 1476efd45369SNicolas Chautru } 1477efd45369SNicolas Chautru } 1478efd45369SNicolas Chautru 1479efd45369SNicolas Chautru return 0; 1480efd45369SNicolas Chautru } 1481efd45369SNicolas Chautru #endif 1482efd45369SNicolas Chautru 1483efd45369SNicolas Chautru static inline char * 1484efd45369SNicolas Chautru mbuf_append(struct rte_mbuf *m_head, struct rte_mbuf *m, uint16_t len) 1485efd45369SNicolas Chautru { 1486efd45369SNicolas Chautru if (unlikely(len > rte_pktmbuf_tailroom(m))) 1487efd45369SNicolas Chautru return NULL; 1488efd45369SNicolas Chautru 1489efd45369SNicolas Chautru char *tail = (char *)m->buf_addr + m->data_off + m->data_len; 1490efd45369SNicolas Chautru m->data_len = (uint16_t)(m->data_len + len); 1491efd45369SNicolas Chautru m_head->pkt_len = (m_head->pkt_len + len); 1492efd45369SNicolas Chautru return tail; 1493efd45369SNicolas Chautru } 1494efd45369SNicolas Chautru 1495efd45369SNicolas Chautru static inline int 1496efd45369SNicolas Chautru enqueue_enc_one_op_cb(struct fpga_queue *q, struct rte_bbdev_enc_op *op, 1497efd45369SNicolas Chautru uint16_t desc_offset) 1498efd45369SNicolas Chautru { 1499efd45369SNicolas Chautru union fpga_dma_desc *desc; 1500efd45369SNicolas Chautru struct rte_mbuf *input; 1501efd45369SNicolas Chautru struct rte_mbuf *output; 1502efd45369SNicolas Chautru int ret; 1503efd45369SNicolas Chautru uint16_t k, e, ncb, ring_offset; 1504efd45369SNicolas Chautru uint32_t total_left, in_length, out_length, in_offset, out_offset; 1505efd45369SNicolas Chautru 1506efd45369SNicolas Chautru #ifdef RTE_LIBRTE_BBDEV_DEBUG 1507efd45369SNicolas Chautru /* Validate op structure */ 1508efd45369SNicolas Chautru if (validate_enc_op(op) == -1) { 1509efd45369SNicolas Chautru rte_bbdev_log(ERR, "Turbo encoder validation failed"); 1510efd45369SNicolas Chautru return -EINVAL; 1511efd45369SNicolas Chautru } 1512efd45369SNicolas Chautru #endif 1513efd45369SNicolas Chautru 1514efd45369SNicolas Chautru input = op->turbo_enc.input.data; 1515efd45369SNicolas Chautru output = op->turbo_enc.output.data; 1516efd45369SNicolas Chautru in_offset = op->turbo_enc.input.offset; 1517efd45369SNicolas Chautru out_offset = op->turbo_enc.output.offset; 1518efd45369SNicolas Chautru total_left = op->turbo_enc.input.length; 1519efd45369SNicolas Chautru k = op->turbo_enc.cb_params.k; 1520efd45369SNicolas Chautru e = op->turbo_enc.cb_params.e; 1521efd45369SNicolas Chautru ncb = op->turbo_enc.cb_params.ncb; 1522efd45369SNicolas Chautru 1523efd45369SNicolas Chautru if (check_bit(op->turbo_enc.op_flags, RTE_BBDEV_TURBO_CRC_24B_ATTACH)) 1524efd45369SNicolas Chautru in_length = ((k - 24) >> 3); 1525efd45369SNicolas Chautru else 1526efd45369SNicolas Chautru in_length = k >> 3; 1527efd45369SNicolas Chautru 1528efd45369SNicolas Chautru if (check_bit(op->turbo_enc.op_flags, RTE_BBDEV_TURBO_RATE_MATCH)) 1529efd45369SNicolas Chautru out_length = (e + 7) >> 3; 1530efd45369SNicolas Chautru else 1531efd45369SNicolas Chautru out_length = (k >> 3) * 3 + 2; 1532efd45369SNicolas Chautru 1533efd45369SNicolas Chautru mbuf_append(output, output, out_length); 1534efd45369SNicolas Chautru 1535efd45369SNicolas Chautru /* Offset into the ring */ 1536efd45369SNicolas Chautru ring_offset = ((q->tail + desc_offset) & q->sw_ring_wrap_mask); 1537efd45369SNicolas Chautru /* Setup DMA Descriptor */ 1538efd45369SNicolas Chautru desc = q->ring_addr + ring_offset; 1539efd45369SNicolas Chautru 1540efd45369SNicolas Chautru ret = fpga_dma_desc_te_fill(op, &desc->enc_req, input, output, k, e, 1541efd45369SNicolas Chautru ncb, in_offset, out_offset, ring_offset, 1); 1542efd45369SNicolas Chautru if (unlikely(ret < 0)) 1543efd45369SNicolas Chautru return ret; 1544efd45369SNicolas Chautru 1545efd45369SNicolas Chautru /* Update lengths */ 1546efd45369SNicolas Chautru total_left -= in_length; 1547efd45369SNicolas Chautru op->turbo_enc.output.length += out_length; 1548efd45369SNicolas Chautru 1549efd45369SNicolas Chautru if (total_left > 0) { 1550efd45369SNicolas Chautru rte_bbdev_log(ERR, 1551efd45369SNicolas Chautru "Mismatch between mbuf length and included CB sizes: mbuf len %u, cb len %u", 1552efd45369SNicolas Chautru total_left, in_length); 1553efd45369SNicolas Chautru return -1; 1554efd45369SNicolas Chautru } 1555efd45369SNicolas Chautru 1556efd45369SNicolas Chautru return 1; 1557efd45369SNicolas Chautru } 1558efd45369SNicolas Chautru 1559efd45369SNicolas Chautru static inline int 1560efd45369SNicolas Chautru enqueue_enc_one_op_tb(struct fpga_queue *q, struct rte_bbdev_enc_op *op, 1561efd45369SNicolas Chautru uint16_t desc_offset, uint8_t cbs_in_op) 1562efd45369SNicolas Chautru { 1563efd45369SNicolas Chautru union fpga_dma_desc *desc; 1564efd45369SNicolas Chautru struct rte_mbuf *input, *output_head, *output; 1565efd45369SNicolas Chautru int ret; 1566efd45369SNicolas Chautru uint8_t r, c, crc24_bits = 0; 1567efd45369SNicolas Chautru uint16_t k, e, ncb, ring_offset; 1568efd45369SNicolas Chautru uint32_t mbuf_total_left, in_length, out_length, in_offset, out_offset; 1569efd45369SNicolas Chautru uint32_t seg_total_left; 1570efd45369SNicolas Chautru uint16_t current_enqueued_cbs = 0; 1571efd45369SNicolas Chautru 1572efd45369SNicolas Chautru #ifdef RTE_LIBRTE_BBDEV_DEBUG 1573efd45369SNicolas Chautru /* Validate op structure */ 1574efd45369SNicolas Chautru if (validate_enc_op(op) == -1) { 1575efd45369SNicolas Chautru rte_bbdev_log(ERR, "Turbo encoder validation failed"); 1576efd45369SNicolas Chautru return -EINVAL; 1577efd45369SNicolas Chautru } 1578efd45369SNicolas Chautru #endif 1579efd45369SNicolas Chautru 1580efd45369SNicolas Chautru input = op->turbo_enc.input.data; 1581efd45369SNicolas Chautru output_head = output = op->turbo_enc.output.data; 1582efd45369SNicolas Chautru in_offset = op->turbo_enc.input.offset; 1583efd45369SNicolas Chautru out_offset = op->turbo_enc.output.offset; 1584efd45369SNicolas Chautru mbuf_total_left = op->turbo_enc.input.length; 1585efd45369SNicolas Chautru 1586efd45369SNicolas Chautru c = op->turbo_enc.tb_params.c; 1587efd45369SNicolas Chautru r = op->turbo_enc.tb_params.r; 1588efd45369SNicolas Chautru 1589efd45369SNicolas Chautru if (check_bit(op->turbo_enc.op_flags, RTE_BBDEV_TURBO_CRC_24B_ATTACH)) 1590efd45369SNicolas Chautru crc24_bits = 24; 1591efd45369SNicolas Chautru 1592efd45369SNicolas Chautru while (mbuf_total_left > 0 && r < c && input != NULL) { 1593efd45369SNicolas Chautru seg_total_left = rte_pktmbuf_data_len(input) - in_offset; 1594efd45369SNicolas Chautru 1595efd45369SNicolas Chautru e = (r < op->turbo_enc.tb_params.cab) ? 1596efd45369SNicolas Chautru op->turbo_enc.tb_params.ea : 1597efd45369SNicolas Chautru op->turbo_enc.tb_params.eb; 1598efd45369SNicolas Chautru k = (r < op->turbo_enc.tb_params.c_neg) ? 1599efd45369SNicolas Chautru op->turbo_enc.tb_params.k_neg : 1600efd45369SNicolas Chautru op->turbo_enc.tb_params.k_pos; 1601efd45369SNicolas Chautru ncb = (r < op->turbo_enc.tb_params.c_neg) ? 1602efd45369SNicolas Chautru op->turbo_enc.tb_params.ncb_neg : 1603efd45369SNicolas Chautru op->turbo_enc.tb_params.ncb_pos; 1604efd45369SNicolas Chautru 1605efd45369SNicolas Chautru in_length = ((k - crc24_bits) >> 3); 1606efd45369SNicolas Chautru 1607efd45369SNicolas Chautru if (check_bit(op->turbo_enc.op_flags, 1608efd45369SNicolas Chautru RTE_BBDEV_TURBO_RATE_MATCH)) 1609efd45369SNicolas Chautru out_length = (e + 7) >> 3; 1610efd45369SNicolas Chautru else 1611efd45369SNicolas Chautru out_length = (k >> 3) * 3 + 2; 1612efd45369SNicolas Chautru 1613efd45369SNicolas Chautru mbuf_append(output_head, output, out_length); 1614efd45369SNicolas Chautru 1615efd45369SNicolas Chautru /* Setup DMA Descriptor */ 1616efd45369SNicolas Chautru ring_offset = ((q->tail + desc_offset) & q->sw_ring_wrap_mask); 1617efd45369SNicolas Chautru desc = q->ring_addr + ring_offset; 1618efd45369SNicolas Chautru ret = fpga_dma_desc_te_fill(op, &desc->enc_req, input, output, 1619efd45369SNicolas Chautru k, e, ncb, in_offset, out_offset, ring_offset, 1620efd45369SNicolas Chautru cbs_in_op); 1621efd45369SNicolas Chautru if (unlikely(ret < 0)) 1622efd45369SNicolas Chautru return ret; 1623efd45369SNicolas Chautru 1624efd45369SNicolas Chautru rte_bbdev_log_debug("DMA request desc %p", desc); 1625efd45369SNicolas Chautru 1626efd45369SNicolas Chautru /* Update lengths */ 1627efd45369SNicolas Chautru op->turbo_enc.output.length += out_length; 1628efd45369SNicolas Chautru mbuf_total_left -= in_length; 1629efd45369SNicolas Chautru 1630efd45369SNicolas Chautru /* Update offsets */ 1631efd45369SNicolas Chautru if (seg_total_left == in_length) { 1632efd45369SNicolas Chautru /* Go to the next mbuf */ 1633efd45369SNicolas Chautru input = input->next; 1634efd45369SNicolas Chautru output = output->next; 1635efd45369SNicolas Chautru in_offset = 0; 1636efd45369SNicolas Chautru out_offset = 0; 1637efd45369SNicolas Chautru } else { 1638efd45369SNicolas Chautru in_offset += in_length; 1639efd45369SNicolas Chautru out_offset += out_length; 1640efd45369SNicolas Chautru } 1641efd45369SNicolas Chautru 1642efd45369SNicolas Chautru r++; 1643efd45369SNicolas Chautru desc_offset++; 1644efd45369SNicolas Chautru current_enqueued_cbs++; 1645efd45369SNicolas Chautru } 1646efd45369SNicolas Chautru 1647efd45369SNicolas Chautru if (mbuf_total_left > 0) { 1648efd45369SNicolas Chautru rte_bbdev_log(ERR, 1649efd45369SNicolas Chautru "Some date still left for processing: mbuf_total_left = %u", 1650efd45369SNicolas Chautru mbuf_total_left); 1651efd45369SNicolas Chautru return -1; 1652efd45369SNicolas Chautru } 1653efd45369SNicolas Chautru 1654efd45369SNicolas Chautru return current_enqueued_cbs; 1655efd45369SNicolas Chautru } 1656efd45369SNicolas Chautru 1657efd45369SNicolas Chautru #ifdef RTE_LIBRTE_BBDEV_DEBUG 1658efd45369SNicolas Chautru /* Validates turbo decoder parameters */ 1659efd45369SNicolas Chautru static int 1660efd45369SNicolas Chautru validate_dec_op(struct rte_bbdev_dec_op *op) 1661efd45369SNicolas Chautru { 1662efd45369SNicolas Chautru struct rte_bbdev_op_turbo_dec *turbo_dec = &op->turbo_dec; 1663b443f318SNicolas Chautru struct rte_bbdev_op_dec_turbo_cb_params *cb = NULL; 1664b443f318SNicolas Chautru struct rte_bbdev_op_dec_turbo_tb_params *tb = NULL; 1665efd45369SNicolas Chautru 1666efd45369SNicolas Chautru if (op->mempool == NULL) { 1667efd45369SNicolas Chautru rte_bbdev_log(ERR, "Invalid mempool pointer"); 1668efd45369SNicolas Chautru return -1; 1669efd45369SNicolas Chautru } 1670efd45369SNicolas Chautru if (turbo_dec->input.data == NULL) { 1671efd45369SNicolas Chautru rte_bbdev_log(ERR, "Invalid input pointer"); 1672efd45369SNicolas Chautru return -1; 1673efd45369SNicolas Chautru } 1674efd45369SNicolas Chautru if (turbo_dec->hard_output.data == NULL) { 1675efd45369SNicolas Chautru rte_bbdev_log(ERR, "Invalid hard_output pointer"); 1676efd45369SNicolas Chautru return -1; 1677efd45369SNicolas Chautru } 1678efd45369SNicolas Chautru if (turbo_dec->rv_index > 3) { 1679efd45369SNicolas Chautru rte_bbdev_log(ERR, 1680efd45369SNicolas Chautru "rv_index (%u) is out of range 0 <= value <= 3", 1681efd45369SNicolas Chautru turbo_dec->rv_index); 1682efd45369SNicolas Chautru return -1; 1683efd45369SNicolas Chautru } 1684efd45369SNicolas Chautru if (turbo_dec->iter_min < 1) { 1685efd45369SNicolas Chautru rte_bbdev_log(ERR, 1686efd45369SNicolas Chautru "iter_min (%u) is less than 1", 1687efd45369SNicolas Chautru turbo_dec->iter_min); 1688efd45369SNicolas Chautru return -1; 1689efd45369SNicolas Chautru } 1690efd45369SNicolas Chautru if (turbo_dec->iter_max <= 2) { 1691efd45369SNicolas Chautru rte_bbdev_log(ERR, 1692efd45369SNicolas Chautru "iter_max (%u) is less than or equal to 2", 1693efd45369SNicolas Chautru turbo_dec->iter_max); 1694efd45369SNicolas Chautru return -1; 1695efd45369SNicolas Chautru } 1696efd45369SNicolas Chautru if (turbo_dec->iter_min > turbo_dec->iter_max) { 1697efd45369SNicolas Chautru rte_bbdev_log(ERR, 1698efd45369SNicolas Chautru "iter_min (%u) is greater than iter_max (%u)", 1699efd45369SNicolas Chautru turbo_dec->iter_min, turbo_dec->iter_max); 1700efd45369SNicolas Chautru return -1; 1701efd45369SNicolas Chautru } 170248fc315fSNicolas Chautru if (turbo_dec->code_block_mode != RTE_BBDEV_TRANSPORT_BLOCK && 170348fc315fSNicolas Chautru turbo_dec->code_block_mode != RTE_BBDEV_CODE_BLOCK) { 1704efd45369SNicolas Chautru rte_bbdev_log(ERR, 1705efd45369SNicolas Chautru "code_block_mode (%u) is out of range 0 <= value <= 1", 1706efd45369SNicolas Chautru turbo_dec->code_block_mode); 1707efd45369SNicolas Chautru return -1; 1708efd45369SNicolas Chautru } 1709efd45369SNicolas Chautru 171048fc315fSNicolas Chautru if (turbo_dec->code_block_mode == RTE_BBDEV_TRANSPORT_BLOCK) { 1711efd45369SNicolas Chautru 1712efd45369SNicolas Chautru if ((turbo_dec->op_flags & 1713efd45369SNicolas Chautru RTE_BBDEV_TURBO_DEC_TB_CRC_24B_KEEP) && 1714efd45369SNicolas Chautru !(turbo_dec->op_flags & RTE_BBDEV_TURBO_CRC_TYPE_24B)) { 1715efd45369SNicolas Chautru rte_bbdev_log(ERR, 1716efd45369SNicolas Chautru "RTE_BBDEV_TURBO_DEC_TB_CRC_24B_KEEP should accompany RTE_BBDEV_TURBO_CRC_TYPE_24B"); 1717efd45369SNicolas Chautru return -1; 1718efd45369SNicolas Chautru } 1719efd45369SNicolas Chautru 1720efd45369SNicolas Chautru tb = &turbo_dec->tb_params; 1721c4b0d663SNicolas Chautru if ((tb->k_neg < RTE_BBDEV_TURBO_MIN_CB_SIZE 1722c4b0d663SNicolas Chautru || tb->k_neg > RTE_BBDEV_TURBO_MAX_CB_SIZE) 1723efd45369SNicolas Chautru && tb->c_neg > 0) { 1724efd45369SNicolas Chautru rte_bbdev_log(ERR, 1725efd45369SNicolas Chautru "k_neg (%u) is out of range %u <= value <= %u", 1726c4b0d663SNicolas Chautru tb->k_neg, RTE_BBDEV_TURBO_MIN_CB_SIZE, 1727c4b0d663SNicolas Chautru RTE_BBDEV_TURBO_MAX_CB_SIZE); 1728efd45369SNicolas Chautru return -1; 1729efd45369SNicolas Chautru } 1730c4b0d663SNicolas Chautru if ((tb->k_pos < RTE_BBDEV_TURBO_MIN_CB_SIZE 1731c4b0d663SNicolas Chautru || tb->k_pos > RTE_BBDEV_TURBO_MAX_CB_SIZE) 1732efd45369SNicolas Chautru && tb->c > tb->c_neg) { 1733efd45369SNicolas Chautru rte_bbdev_log(ERR, 1734efd45369SNicolas Chautru "k_pos (%u) is out of range %u <= value <= %u", 1735c4b0d663SNicolas Chautru tb->k_pos, RTE_BBDEV_TURBO_MIN_CB_SIZE, 1736c4b0d663SNicolas Chautru RTE_BBDEV_TURBO_MAX_CB_SIZE); 1737efd45369SNicolas Chautru return -1; 1738efd45369SNicolas Chautru } 1739c4b0d663SNicolas Chautru if (tb->c_neg > (RTE_BBDEV_TURBO_MAX_CODE_BLOCKS - 1)) 1740efd45369SNicolas Chautru rte_bbdev_log(ERR, 1741efd45369SNicolas Chautru "c_neg (%u) is out of range 0 <= value <= %u", 1742efd45369SNicolas Chautru tb->c_neg, 1743c4b0d663SNicolas Chautru RTE_BBDEV_TURBO_MAX_CODE_BLOCKS - 1); 1744c4b0d663SNicolas Chautru if (tb->c < 1 || tb->c > RTE_BBDEV_TURBO_MAX_CODE_BLOCKS) { 1745efd45369SNicolas Chautru rte_bbdev_log(ERR, 1746efd45369SNicolas Chautru "c (%u) is out of range 1 <= value <= %u", 1747c4b0d663SNicolas Chautru tb->c, RTE_BBDEV_TURBO_MAX_CODE_BLOCKS); 1748efd45369SNicolas Chautru return -1; 1749efd45369SNicolas Chautru } 1750efd45369SNicolas Chautru if (tb->cab > tb->c) { 1751efd45369SNicolas Chautru rte_bbdev_log(ERR, 1752efd45369SNicolas Chautru "cab (%u) is greater than c (%u)", 1753efd45369SNicolas Chautru tb->cab, tb->c); 1754efd45369SNicolas Chautru return -1; 1755efd45369SNicolas Chautru } 1756efd45369SNicolas Chautru } else { 1757efd45369SNicolas Chautru 1758efd45369SNicolas Chautru if (turbo_dec->op_flags & RTE_BBDEV_TURBO_DEC_TB_CRC_24B_KEEP) { 1759efd45369SNicolas Chautru rte_bbdev_log(ERR, 1760efd45369SNicolas Chautru "RTE_BBDEV_TURBO_DEC_TB_CRC_24B_KEEP is invalid in CB-mode"); 1761efd45369SNicolas Chautru return -1; 1762efd45369SNicolas Chautru } 1763efd45369SNicolas Chautru 1764efd45369SNicolas Chautru cb = &turbo_dec->cb_params; 1765c4b0d663SNicolas Chautru if (cb->k < RTE_BBDEV_TURBO_MIN_CB_SIZE 1766c4b0d663SNicolas Chautru || cb->k > RTE_BBDEV_TURBO_MAX_CB_SIZE) { 1767efd45369SNicolas Chautru rte_bbdev_log(ERR, 1768efd45369SNicolas Chautru "k (%u) is out of range %u <= value <= %u", 1769c4b0d663SNicolas Chautru cb->k, RTE_BBDEV_TURBO_MIN_CB_SIZE, 1770c4b0d663SNicolas Chautru RTE_BBDEV_TURBO_MAX_CB_SIZE); 1771efd45369SNicolas Chautru return -1; 1772efd45369SNicolas Chautru } 1773efd45369SNicolas Chautru } 1774efd45369SNicolas Chautru 1775efd45369SNicolas Chautru return 0; 1776efd45369SNicolas Chautru } 1777efd45369SNicolas Chautru #endif 1778efd45369SNicolas Chautru 1779efd45369SNicolas Chautru static inline int 1780efd45369SNicolas Chautru enqueue_dec_one_op_cb(struct fpga_queue *q, struct rte_bbdev_dec_op *op, 1781efd45369SNicolas Chautru uint16_t desc_offset) 1782efd45369SNicolas Chautru { 1783efd45369SNicolas Chautru union fpga_dma_desc *desc; 1784efd45369SNicolas Chautru struct rte_mbuf *input; 1785efd45369SNicolas Chautru struct rte_mbuf *output; 1786efd45369SNicolas Chautru int ret; 1787efd45369SNicolas Chautru uint16_t k, kw, ring_offset; 1788efd45369SNicolas Chautru uint32_t total_left, in_length, out_length, in_offset, out_offset; 1789efd45369SNicolas Chautru 1790efd45369SNicolas Chautru #ifdef RTE_LIBRTE_BBDEV_DEBUG 1791efd45369SNicolas Chautru /* Validate op structure */ 1792efd45369SNicolas Chautru if (validate_dec_op(op) == -1) { 1793efd45369SNicolas Chautru rte_bbdev_log(ERR, "Turbo decoder validation failed"); 1794efd45369SNicolas Chautru return -EINVAL; 1795efd45369SNicolas Chautru } 1796efd45369SNicolas Chautru #endif 1797efd45369SNicolas Chautru 1798efd45369SNicolas Chautru input = op->turbo_dec.input.data; 1799efd45369SNicolas Chautru output = op->turbo_dec.hard_output.data; 1800efd45369SNicolas Chautru total_left = op->turbo_dec.input.length; 1801efd45369SNicolas Chautru in_offset = op->turbo_dec.input.offset; 1802efd45369SNicolas Chautru out_offset = op->turbo_dec.hard_output.offset; 1803efd45369SNicolas Chautru 1804efd45369SNicolas Chautru k = op->turbo_dec.cb_params.k; 1805efd45369SNicolas Chautru kw = RTE_ALIGN_CEIL(k + 4, 32) * 3; 1806efd45369SNicolas Chautru in_length = kw; 1807efd45369SNicolas Chautru out_length = k >> 3; 1808efd45369SNicolas Chautru 1809efd45369SNicolas Chautru mbuf_append(output, output, out_length); 1810efd45369SNicolas Chautru 1811efd45369SNicolas Chautru /* Setup DMA Descriptor */ 1812efd45369SNicolas Chautru ring_offset = ((q->tail + desc_offset) & q->sw_ring_wrap_mask); 1813efd45369SNicolas Chautru desc = q->ring_addr + ring_offset; 1814efd45369SNicolas Chautru ret = fpga_dma_desc_td_fill(op, &desc->dec_req, input, output, 1815efd45369SNicolas Chautru in_length, k, in_offset, out_offset, ring_offset, 1); 1816efd45369SNicolas Chautru if (unlikely(ret < 0)) 1817efd45369SNicolas Chautru return ret; 1818efd45369SNicolas Chautru 1819efd45369SNicolas Chautru #ifdef RTE_LIBRTE_BBDEV_DEBUG 1820efd45369SNicolas Chautru print_dma_dec_desc_debug_info(desc); 1821efd45369SNicolas Chautru #endif 1822efd45369SNicolas Chautru 1823efd45369SNicolas Chautru /* Update lengths */ 1824efd45369SNicolas Chautru total_left -= in_length; 1825efd45369SNicolas Chautru op->turbo_dec.hard_output.length += out_length; 1826efd45369SNicolas Chautru 1827efd45369SNicolas Chautru if (total_left > 0) { 1828efd45369SNicolas Chautru rte_bbdev_log(ERR, 1829efd45369SNicolas Chautru "Mismatch between mbuf length and included CB sizes: mbuf len %u, cb len %u", 1830efd45369SNicolas Chautru total_left, in_length); 1831efd45369SNicolas Chautru return -1; 1832efd45369SNicolas Chautru } 1833efd45369SNicolas Chautru 1834efd45369SNicolas Chautru return 1; 1835efd45369SNicolas Chautru } 1836efd45369SNicolas Chautru 1837efd45369SNicolas Chautru 1838efd45369SNicolas Chautru static inline int 1839efd45369SNicolas Chautru enqueue_dec_one_op_tb(struct fpga_queue *q, struct rte_bbdev_dec_op *op, 1840efd45369SNicolas Chautru uint16_t desc_offset, uint8_t cbs_in_op) 1841efd45369SNicolas Chautru { 1842efd45369SNicolas Chautru union fpga_dma_desc *desc; 1843efd45369SNicolas Chautru struct rte_mbuf *input, *output_head, *output; 1844efd45369SNicolas Chautru int ret; 1845efd45369SNicolas Chautru uint8_t r, c; 1846efd45369SNicolas Chautru uint16_t k, kw, in_length, out_length, ring_offset; 1847efd45369SNicolas Chautru uint32_t mbuf_total_left, seg_total_left, in_offset, out_offset; 1848efd45369SNicolas Chautru uint16_t current_enqueued_cbs = 0; 1849efd45369SNicolas Chautru uint16_t crc24_overlap = 0; 1850efd45369SNicolas Chautru 1851efd45369SNicolas Chautru #ifdef RTE_LIBRTE_BBDEV_DEBUG 1852efd45369SNicolas Chautru /* Validate op structure */ 1853efd45369SNicolas Chautru if (validate_dec_op(op) == -1) { 1854efd45369SNicolas Chautru rte_bbdev_log(ERR, "Turbo decoder validation failed"); 1855efd45369SNicolas Chautru return -EINVAL; 1856efd45369SNicolas Chautru } 1857efd45369SNicolas Chautru #endif 1858efd45369SNicolas Chautru 1859efd45369SNicolas Chautru input = op->turbo_dec.input.data; 1860efd45369SNicolas Chautru output_head = output = op->turbo_dec.hard_output.data; 1861efd45369SNicolas Chautru mbuf_total_left = op->turbo_dec.input.length; 1862efd45369SNicolas Chautru in_offset = op->turbo_dec.input.offset; 1863efd45369SNicolas Chautru out_offset = op->turbo_dec.hard_output.offset; 1864efd45369SNicolas Chautru 1865efd45369SNicolas Chautru if (!check_bit(op->turbo_dec.op_flags, 1866efd45369SNicolas Chautru RTE_BBDEV_TURBO_DEC_TB_CRC_24B_KEEP)) 1867efd45369SNicolas Chautru crc24_overlap = 24; 1868efd45369SNicolas Chautru 1869efd45369SNicolas Chautru c = op->turbo_dec.tb_params.c; 1870efd45369SNicolas Chautru r = op->turbo_dec.tb_params.r; 1871efd45369SNicolas Chautru 1872efd45369SNicolas Chautru while (mbuf_total_left > 0 && r < c && input != NULL) { 1873efd45369SNicolas Chautru seg_total_left = rte_pktmbuf_data_len(input) - in_offset; 1874efd45369SNicolas Chautru k = (r < op->turbo_dec.tb_params.c_neg) ? 1875efd45369SNicolas Chautru op->turbo_dec.tb_params.k_neg : 1876efd45369SNicolas Chautru op->turbo_dec.tb_params.k_pos; 1877efd45369SNicolas Chautru kw = RTE_ALIGN_CEIL(k + 4, 32) * 3; 1878efd45369SNicolas Chautru 1879efd45369SNicolas Chautru in_length = kw; 1880efd45369SNicolas Chautru out_length = (k - crc24_overlap) >> 3; 1881efd45369SNicolas Chautru 1882efd45369SNicolas Chautru mbuf_append(output_head, output, out_length); 1883efd45369SNicolas Chautru 1884efd45369SNicolas Chautru if (seg_total_left < in_length) { 1885efd45369SNicolas Chautru rte_bbdev_log(ERR, 1886efd45369SNicolas Chautru "Partial CB found in a TB. FPGA Driver doesn't support scatter-gather operations!"); 1887efd45369SNicolas Chautru return -1; 1888efd45369SNicolas Chautru } 1889efd45369SNicolas Chautru 1890efd45369SNicolas Chautru /* Setup DMA Descriptor */ 1891efd45369SNicolas Chautru ring_offset = ((q->tail + desc_offset) & q->sw_ring_wrap_mask); 1892efd45369SNicolas Chautru desc = q->ring_addr + ring_offset; 1893efd45369SNicolas Chautru ret = fpga_dma_desc_td_fill(op, &desc->dec_req, input, output, 1894efd45369SNicolas Chautru in_length, k, in_offset, out_offset, 1895efd45369SNicolas Chautru ring_offset, cbs_in_op); 1896efd45369SNicolas Chautru if (unlikely(ret < 0)) 1897efd45369SNicolas Chautru return ret; 1898efd45369SNicolas Chautru 1899efd45369SNicolas Chautru /* Update lengths */ 1900efd45369SNicolas Chautru ret = rte_pktmbuf_trim(op->turbo_dec.hard_output.data, 1901efd45369SNicolas Chautru (crc24_overlap >> 3)); 1902efd45369SNicolas Chautru #ifdef RTE_LIBRTE_BBDEV_DEBUG 1903efd45369SNicolas Chautru if (ret < 0) { 1904efd45369SNicolas Chautru rte_bbdev_log(ERR, 1905efd45369SNicolas Chautru "The length to remove is greater than the length of the last segment"); 1906efd45369SNicolas Chautru return -EINVAL; 1907efd45369SNicolas Chautru } 1908efd45369SNicolas Chautru #endif 1909efd45369SNicolas Chautru op->turbo_dec.hard_output.length += out_length; 1910efd45369SNicolas Chautru mbuf_total_left -= in_length; 1911efd45369SNicolas Chautru 1912efd45369SNicolas Chautru /* Update offsets */ 1913efd45369SNicolas Chautru if (seg_total_left == in_length) { 1914efd45369SNicolas Chautru /* Go to the next mbuf */ 1915efd45369SNicolas Chautru input = input->next; 1916efd45369SNicolas Chautru output = output->next; 1917efd45369SNicolas Chautru in_offset = 0; 1918efd45369SNicolas Chautru out_offset = 0; 1919efd45369SNicolas Chautru } else { 1920efd45369SNicolas Chautru in_offset += in_length; 1921efd45369SNicolas Chautru out_offset += out_length; 1922efd45369SNicolas Chautru } 1923efd45369SNicolas Chautru 1924efd45369SNicolas Chautru r++; 1925efd45369SNicolas Chautru desc_offset++; 1926efd45369SNicolas Chautru current_enqueued_cbs++; 1927efd45369SNicolas Chautru } 1928efd45369SNicolas Chautru 1929efd45369SNicolas Chautru if (mbuf_total_left > 0) { 1930efd45369SNicolas Chautru rte_bbdev_log(ERR, 1931efd45369SNicolas Chautru "Some date still left for processing: mbuf_total_left = %u", 1932efd45369SNicolas Chautru mbuf_total_left); 1933efd45369SNicolas Chautru return -1; 1934efd45369SNicolas Chautru } 1935efd45369SNicolas Chautru 1936efd45369SNicolas Chautru return current_enqueued_cbs; 1937efd45369SNicolas Chautru } 1938efd45369SNicolas Chautru 1939efd45369SNicolas Chautru static uint16_t 1940efd45369SNicolas Chautru fpga_enqueue_enc(struct rte_bbdev_queue_data *q_data, 1941efd45369SNicolas Chautru struct rte_bbdev_enc_op **ops, uint16_t num) 1942efd45369SNicolas Chautru { 1943efd45369SNicolas Chautru uint8_t cbs_in_op; 1944efd45369SNicolas Chautru uint16_t i, total_enqueued_cbs = 0; 1945efd45369SNicolas Chautru int32_t avail; 1946efd45369SNicolas Chautru int enqueued_cbs; 1947efd45369SNicolas Chautru struct fpga_queue *q = q_data->queue_private; 1948efd45369SNicolas Chautru union fpga_dma_desc *desc; 1949efd45369SNicolas Chautru 1950efd45369SNicolas Chautru /* Check if queue is not full */ 1951efd45369SNicolas Chautru if (unlikely(((q->tail + 1) & q->sw_ring_wrap_mask) == 1952efd45369SNicolas Chautru q->head_free_desc)) 1953efd45369SNicolas Chautru return 0; 1954efd45369SNicolas Chautru 1955efd45369SNicolas Chautru /* Calculates available space */ 1956efd45369SNicolas Chautru avail = (q->head_free_desc > q->tail) ? 1957efd45369SNicolas Chautru q->head_free_desc - q->tail - 1 : 1958efd45369SNicolas Chautru q->ring_ctrl_reg.ring_size + q->head_free_desc - q->tail - 1; 1959efd45369SNicolas Chautru 1960efd45369SNicolas Chautru for (i = 0; i < num; ++i) { 196148fc315fSNicolas Chautru if (ops[i]->turbo_enc.code_block_mode == 196248fc315fSNicolas Chautru RTE_BBDEV_TRANSPORT_BLOCK) { 1963efd45369SNicolas Chautru cbs_in_op = get_num_cbs_in_op_enc(&ops[i]->turbo_enc); 1964efd45369SNicolas Chautru /* Check if there is available space for further 1965efd45369SNicolas Chautru * processing 1966efd45369SNicolas Chautru */ 1967efd45369SNicolas Chautru if (unlikely(avail - cbs_in_op < 0)) 1968efd45369SNicolas Chautru break; 1969efd45369SNicolas Chautru avail -= cbs_in_op; 1970efd45369SNicolas Chautru enqueued_cbs = enqueue_enc_one_op_tb(q, ops[i], 1971efd45369SNicolas Chautru total_enqueued_cbs, cbs_in_op); 1972efd45369SNicolas Chautru } else { 1973efd45369SNicolas Chautru /* Check if there is available space for further 1974efd45369SNicolas Chautru * processing 1975efd45369SNicolas Chautru */ 1976efd45369SNicolas Chautru if (unlikely(avail - 1 < 0)) 1977efd45369SNicolas Chautru break; 1978efd45369SNicolas Chautru avail -= 1; 1979efd45369SNicolas Chautru enqueued_cbs = enqueue_enc_one_op_cb(q, ops[i], 1980efd45369SNicolas Chautru total_enqueued_cbs); 1981efd45369SNicolas Chautru } 1982efd45369SNicolas Chautru 1983efd45369SNicolas Chautru if (enqueued_cbs < 0) 1984efd45369SNicolas Chautru break; 1985efd45369SNicolas Chautru 1986efd45369SNicolas Chautru total_enqueued_cbs += enqueued_cbs; 1987efd45369SNicolas Chautru 1988efd45369SNicolas Chautru rte_bbdev_log_debug("enqueuing enc ops [%d/%d] | head %d | tail %d", 1989efd45369SNicolas Chautru total_enqueued_cbs, num, 1990efd45369SNicolas Chautru q->head_free_desc, q->tail); 1991efd45369SNicolas Chautru } 1992efd45369SNicolas Chautru 1993efd45369SNicolas Chautru /* Set interrupt bit for last CB in enqueued ops. FPGA issues interrupt 1994efd45369SNicolas Chautru * only when all previous CBs were already processed. 1995efd45369SNicolas Chautru */ 1996efd45369SNicolas Chautru desc = q->ring_addr + ((q->tail + total_enqueued_cbs - 1) 1997efd45369SNicolas Chautru & q->sw_ring_wrap_mask); 1998efd45369SNicolas Chautru desc->enc_req.irq_en = q->irq_enable; 1999efd45369SNicolas Chautru 2000efd45369SNicolas Chautru fpga_dma_enqueue(q, total_enqueued_cbs, &q_data->queue_stats); 2001efd45369SNicolas Chautru 2002efd45369SNicolas Chautru /* Update stats */ 2003efd45369SNicolas Chautru q_data->queue_stats.enqueued_count += i; 2004efd45369SNicolas Chautru q_data->queue_stats.enqueue_err_count += num - i; 2005efd45369SNicolas Chautru 2006efd45369SNicolas Chautru return i; 2007efd45369SNicolas Chautru } 2008efd45369SNicolas Chautru 2009efd45369SNicolas Chautru static uint16_t 2010efd45369SNicolas Chautru fpga_enqueue_dec(struct rte_bbdev_queue_data *q_data, 2011efd45369SNicolas Chautru struct rte_bbdev_dec_op **ops, uint16_t num) 2012efd45369SNicolas Chautru { 2013efd45369SNicolas Chautru uint8_t cbs_in_op; 2014efd45369SNicolas Chautru uint16_t i, total_enqueued_cbs = 0; 2015efd45369SNicolas Chautru int32_t avail; 2016efd45369SNicolas Chautru int enqueued_cbs; 2017efd45369SNicolas Chautru struct fpga_queue *q = q_data->queue_private; 2018efd45369SNicolas Chautru union fpga_dma_desc *desc; 2019efd45369SNicolas Chautru 2020efd45369SNicolas Chautru /* Check if queue is not full */ 2021efd45369SNicolas Chautru if (unlikely(((q->tail + 1) & q->sw_ring_wrap_mask) == 2022efd45369SNicolas Chautru q->head_free_desc)) 2023efd45369SNicolas Chautru return 0; 2024efd45369SNicolas Chautru 2025efd45369SNicolas Chautru /* Calculates available space */ 2026efd45369SNicolas Chautru avail = (q->head_free_desc > q->tail) ? 2027efd45369SNicolas Chautru q->head_free_desc - q->tail - 1 : 2028efd45369SNicolas Chautru q->ring_ctrl_reg.ring_size + q->head_free_desc - q->tail - 1; 2029efd45369SNicolas Chautru 2030efd45369SNicolas Chautru for (i = 0; i < num; ++i) { 203148fc315fSNicolas Chautru if (ops[i]->turbo_dec.code_block_mode == 203248fc315fSNicolas Chautru RTE_BBDEV_TRANSPORT_BLOCK) { 2033efd45369SNicolas Chautru cbs_in_op = get_num_cbs_in_op_dec(&ops[i]->turbo_dec); 2034efd45369SNicolas Chautru /* Check if there is available space for further 2035efd45369SNicolas Chautru * processing 2036efd45369SNicolas Chautru */ 2037efd45369SNicolas Chautru if (unlikely(avail - cbs_in_op < 0)) 2038efd45369SNicolas Chautru break; 2039efd45369SNicolas Chautru avail -= cbs_in_op; 2040efd45369SNicolas Chautru enqueued_cbs = enqueue_dec_one_op_tb(q, ops[i], 2041efd45369SNicolas Chautru total_enqueued_cbs, cbs_in_op); 2042efd45369SNicolas Chautru } else { 2043efd45369SNicolas Chautru /* Check if there is available space for further 2044efd45369SNicolas Chautru * processing 2045efd45369SNicolas Chautru */ 2046efd45369SNicolas Chautru if (unlikely(avail - 1 < 0)) 2047efd45369SNicolas Chautru break; 2048efd45369SNicolas Chautru avail -= 1; 2049efd45369SNicolas Chautru enqueued_cbs = enqueue_dec_one_op_cb(q, ops[i], 2050efd45369SNicolas Chautru total_enqueued_cbs); 2051efd45369SNicolas Chautru } 2052efd45369SNicolas Chautru 2053efd45369SNicolas Chautru if (enqueued_cbs < 0) 2054efd45369SNicolas Chautru break; 2055efd45369SNicolas Chautru 2056efd45369SNicolas Chautru total_enqueued_cbs += enqueued_cbs; 2057efd45369SNicolas Chautru 2058efd45369SNicolas Chautru rte_bbdev_log_debug("enqueuing dec ops [%d/%d] | head %d | tail %d", 2059efd45369SNicolas Chautru total_enqueued_cbs, num, 2060efd45369SNicolas Chautru q->head_free_desc, q->tail); 2061efd45369SNicolas Chautru } 2062efd45369SNicolas Chautru 2063efd45369SNicolas Chautru /* Set interrupt bit for last CB in enqueued ops. FPGA issues interrupt 2064efd45369SNicolas Chautru * only when all previous CBs were already processed. 2065efd45369SNicolas Chautru */ 2066efd45369SNicolas Chautru desc = q->ring_addr + ((q->tail + total_enqueued_cbs - 1) 2067efd45369SNicolas Chautru & q->sw_ring_wrap_mask); 2068efd45369SNicolas Chautru desc->dec_req.irq_en = q->irq_enable; 2069efd45369SNicolas Chautru 2070efd45369SNicolas Chautru fpga_dma_enqueue(q, total_enqueued_cbs, &q_data->queue_stats); 2071efd45369SNicolas Chautru 2072efd45369SNicolas Chautru /* Update stats */ 2073efd45369SNicolas Chautru q_data->queue_stats.enqueued_count += i; 2074efd45369SNicolas Chautru q_data->queue_stats.enqueue_err_count += num - i; 2075efd45369SNicolas Chautru 2076efd45369SNicolas Chautru return i; 2077efd45369SNicolas Chautru } 2078efd45369SNicolas Chautru 2079efd45369SNicolas Chautru static inline int 2080efd45369SNicolas Chautru dequeue_enc_one_op_cb(struct fpga_queue *q, struct rte_bbdev_enc_op **op, 2081efd45369SNicolas Chautru uint16_t desc_offset) 2082efd45369SNicolas Chautru { 2083efd45369SNicolas Chautru union fpga_dma_desc *desc; 2084efd45369SNicolas Chautru int desc_error = 0; 2085efd45369SNicolas Chautru 2086efd45369SNicolas Chautru /* Set current desc */ 2087efd45369SNicolas Chautru desc = q->ring_addr + ((q->head_free_desc + desc_offset) 2088efd45369SNicolas Chautru & q->sw_ring_wrap_mask); 2089efd45369SNicolas Chautru 2090efd45369SNicolas Chautru /*check if done */ 2091efd45369SNicolas Chautru if (desc->enc_req.done == 0) 2092efd45369SNicolas Chautru return -1; 2093efd45369SNicolas Chautru 2094efd45369SNicolas Chautru /* make sure the response is read atomically */ 2095efd45369SNicolas Chautru rte_smp_rmb(); 2096efd45369SNicolas Chautru 2097efd45369SNicolas Chautru rte_bbdev_log_debug("DMA response desc %p", desc); 2098efd45369SNicolas Chautru 2099efd45369SNicolas Chautru *op = desc->enc_req.op_addr; 21007be78d02SJosh Soref /* Check the descriptor error field, return 1 on error */ 2101efd45369SNicolas Chautru desc_error = check_desc_error(desc->enc_req.error); 2102efd45369SNicolas Chautru (*op)->status = desc_error << RTE_BBDEV_DATA_ERROR; 2103efd45369SNicolas Chautru 2104efd45369SNicolas Chautru return 1; 2105efd45369SNicolas Chautru } 2106efd45369SNicolas Chautru 2107efd45369SNicolas Chautru static inline int 2108efd45369SNicolas Chautru dequeue_enc_one_op_tb(struct fpga_queue *q, struct rte_bbdev_enc_op **op, 2109efd45369SNicolas Chautru uint16_t desc_offset) 2110efd45369SNicolas Chautru { 2111efd45369SNicolas Chautru union fpga_dma_desc *desc; 2112efd45369SNicolas Chautru uint8_t cbs_in_op, cb_idx; 2113efd45369SNicolas Chautru int desc_error = 0; 2114efd45369SNicolas Chautru int status = 0; 2115efd45369SNicolas Chautru 2116efd45369SNicolas Chautru /* Set descriptor */ 2117efd45369SNicolas Chautru desc = q->ring_addr + ((q->head_free_desc + desc_offset) 2118efd45369SNicolas Chautru & q->sw_ring_wrap_mask); 2119efd45369SNicolas Chautru 2120efd45369SNicolas Chautru /* Verify if done bit is set */ 2121efd45369SNicolas Chautru if (desc->enc_req.done == 0) 2122efd45369SNicolas Chautru return -1; 2123efd45369SNicolas Chautru 2124efd45369SNicolas Chautru /* Make sure the response is read atomically */ 2125efd45369SNicolas Chautru rte_smp_rmb(); 2126efd45369SNicolas Chautru 2127efd45369SNicolas Chautru /* Verify if done bit in all CBs is set */ 2128efd45369SNicolas Chautru cbs_in_op = desc->enc_req.cbs_in_op; 2129efd45369SNicolas Chautru for (cb_idx = 1; cb_idx < cbs_in_op; ++cb_idx) { 2130efd45369SNicolas Chautru desc = q->ring_addr + ((q->head_free_desc + desc_offset + 2131efd45369SNicolas Chautru cb_idx) & q->sw_ring_wrap_mask); 2132efd45369SNicolas Chautru if (desc->enc_req.done == 0) 2133efd45369SNicolas Chautru return -1; 2134efd45369SNicolas Chautru } 2135efd45369SNicolas Chautru 2136efd45369SNicolas Chautru /* Make sure the response is read atomically */ 2137efd45369SNicolas Chautru rte_smp_rmb(); 2138efd45369SNicolas Chautru 2139efd45369SNicolas Chautru for (cb_idx = 0; cb_idx < cbs_in_op; ++cb_idx) { 2140efd45369SNicolas Chautru desc = q->ring_addr + ((q->head_free_desc + desc_offset + 2141efd45369SNicolas Chautru cb_idx) & q->sw_ring_wrap_mask); 21427be78d02SJosh Soref /* Check the descriptor error field, return 1 on error */ 2143efd45369SNicolas Chautru desc_error = check_desc_error(desc->enc_req.error); 2144efd45369SNicolas Chautru status |= desc_error << RTE_BBDEV_DATA_ERROR; 2145efd45369SNicolas Chautru rte_bbdev_log_debug("DMA response desc %p", desc); 2146efd45369SNicolas Chautru } 2147efd45369SNicolas Chautru 2148efd45369SNicolas Chautru *op = desc->enc_req.op_addr; 2149efd45369SNicolas Chautru (*op)->status = status; 2150efd45369SNicolas Chautru return cbs_in_op; 2151efd45369SNicolas Chautru } 2152efd45369SNicolas Chautru 2153efd45369SNicolas Chautru static inline int 2154efd45369SNicolas Chautru dequeue_dec_one_op_cb(struct fpga_queue *q, struct rte_bbdev_dec_op **op, 2155efd45369SNicolas Chautru uint16_t desc_offset) 2156efd45369SNicolas Chautru { 2157efd45369SNicolas Chautru union fpga_dma_desc *desc; 2158efd45369SNicolas Chautru int desc_error = 0; 2159efd45369SNicolas Chautru /* Set descriptor */ 2160efd45369SNicolas Chautru desc = q->ring_addr + ((q->head_free_desc + desc_offset) 2161efd45369SNicolas Chautru & q->sw_ring_wrap_mask); 2162efd45369SNicolas Chautru 2163efd45369SNicolas Chautru /* Verify done bit is set */ 2164efd45369SNicolas Chautru if (desc->dec_req.done == 0) 2165efd45369SNicolas Chautru return -1; 2166efd45369SNicolas Chautru 2167efd45369SNicolas Chautru /* make sure the response is read atomically */ 2168efd45369SNicolas Chautru rte_smp_rmb(); 2169efd45369SNicolas Chautru 2170efd45369SNicolas Chautru #ifdef RTE_LIBRTE_BBDEV_DEBUG 2171efd45369SNicolas Chautru print_dma_dec_desc_debug_info(desc); 2172efd45369SNicolas Chautru 2173efd45369SNicolas Chautru #endif 2174efd45369SNicolas Chautru 2175efd45369SNicolas Chautru *op = desc->dec_req.op_addr; 2176efd45369SNicolas Chautru /* FPGA reports in half-iterations, from 0 to 31. get ceiling */ 2177efd45369SNicolas Chautru (*op)->turbo_dec.iter_count = (desc->dec_req.iter + 2) >> 1; 2178efd45369SNicolas Chautru /* crc_pass = 0 when decoder fails */ 2179efd45369SNicolas Chautru (*op)->status = !(desc->dec_req.crc_pass) << RTE_BBDEV_CRC_ERROR; 21807be78d02SJosh Soref /* Check the descriptor error field, return 1 on error */ 2181efd45369SNicolas Chautru desc_error = check_desc_error(desc->enc_req.error); 2182efd45369SNicolas Chautru (*op)->status |= desc_error << RTE_BBDEV_DATA_ERROR; 2183efd45369SNicolas Chautru return 1; 2184efd45369SNicolas Chautru } 2185efd45369SNicolas Chautru 2186efd45369SNicolas Chautru static inline int 2187efd45369SNicolas Chautru dequeue_dec_one_op_tb(struct fpga_queue *q, struct rte_bbdev_dec_op **op, 2188efd45369SNicolas Chautru uint16_t desc_offset) 2189efd45369SNicolas Chautru { 2190efd45369SNicolas Chautru union fpga_dma_desc *desc; 2191efd45369SNicolas Chautru uint8_t cbs_in_op, cb_idx, iter_count = 0; 2192efd45369SNicolas Chautru int status = 0; 2193efd45369SNicolas Chautru int desc_error = 0; 2194efd45369SNicolas Chautru /* Set descriptor */ 2195efd45369SNicolas Chautru desc = q->ring_addr + ((q->head_free_desc + desc_offset) 2196efd45369SNicolas Chautru & q->sw_ring_wrap_mask); 2197efd45369SNicolas Chautru 2198efd45369SNicolas Chautru /* Verify if done bit is set */ 2199efd45369SNicolas Chautru if (desc->dec_req.done == 0) 2200efd45369SNicolas Chautru return -1; 2201efd45369SNicolas Chautru 2202efd45369SNicolas Chautru /* Make sure the response is read atomically */ 2203efd45369SNicolas Chautru rte_smp_rmb(); 2204efd45369SNicolas Chautru 2205efd45369SNicolas Chautru /* Verify if done bit in all CBs is set */ 2206efd45369SNicolas Chautru cbs_in_op = desc->dec_req.cbs_in_op; 2207efd45369SNicolas Chautru for (cb_idx = 1; cb_idx < cbs_in_op; ++cb_idx) { 2208efd45369SNicolas Chautru desc = q->ring_addr + ((q->head_free_desc + desc_offset + 2209efd45369SNicolas Chautru cb_idx) & q->sw_ring_wrap_mask); 2210efd45369SNicolas Chautru if (desc->dec_req.done == 0) 2211efd45369SNicolas Chautru return -1; 2212efd45369SNicolas Chautru } 2213efd45369SNicolas Chautru 2214efd45369SNicolas Chautru /* Make sure the response is read atomically */ 2215efd45369SNicolas Chautru rte_smp_rmb(); 2216efd45369SNicolas Chautru 2217efd45369SNicolas Chautru for (cb_idx = 0; cb_idx < cbs_in_op; ++cb_idx) { 2218efd45369SNicolas Chautru desc = q->ring_addr + ((q->head_free_desc + desc_offset + 2219efd45369SNicolas Chautru cb_idx) & q->sw_ring_wrap_mask); 2220efd45369SNicolas Chautru /* get max iter_count for all CBs in op */ 2221efd45369SNicolas Chautru iter_count = RTE_MAX(iter_count, (uint8_t) desc->dec_req.iter); 2222efd45369SNicolas Chautru /* crc_pass = 0 when decoder fails, one fails all */ 2223efd45369SNicolas Chautru status |= !(desc->dec_req.crc_pass) << RTE_BBDEV_CRC_ERROR; 22247be78d02SJosh Soref /* Check the descriptor error field, return 1 on error */ 2225efd45369SNicolas Chautru desc_error = check_desc_error(desc->enc_req.error); 2226efd45369SNicolas Chautru status |= desc_error << RTE_BBDEV_DATA_ERROR; 2227efd45369SNicolas Chautru rte_bbdev_log_debug("DMA response desc %p", desc); 2228efd45369SNicolas Chautru } 2229efd45369SNicolas Chautru 2230efd45369SNicolas Chautru *op = desc->dec_req.op_addr; 2231efd45369SNicolas Chautru 2232efd45369SNicolas Chautru /* FPGA reports in half-iterations, get ceiling */ 2233efd45369SNicolas Chautru (*op)->turbo_dec.iter_count = (iter_count + 2) >> 1; 2234efd45369SNicolas Chautru (*op)->status = status; 2235efd45369SNicolas Chautru return cbs_in_op; 2236efd45369SNicolas Chautru } 2237efd45369SNicolas Chautru 2238efd45369SNicolas Chautru static uint16_t 2239efd45369SNicolas Chautru fpga_dequeue_enc(struct rte_bbdev_queue_data *q_data, 2240efd45369SNicolas Chautru struct rte_bbdev_enc_op **ops, uint16_t num) 2241efd45369SNicolas Chautru { 2242efd45369SNicolas Chautru struct fpga_queue *q = q_data->queue_private; 2243efd45369SNicolas Chautru uint32_t avail = (q->tail - q->head_free_desc) & q->sw_ring_wrap_mask; 2244efd45369SNicolas Chautru uint16_t i; 2245efd45369SNicolas Chautru uint16_t dequeued_cbs = 0; 2246efd45369SNicolas Chautru struct rte_bbdev_enc_op *op; 2247efd45369SNicolas Chautru int ret; 2248efd45369SNicolas Chautru 2249efd45369SNicolas Chautru for (i = 0; (i < num) && (dequeued_cbs < avail); ++i) { 2250efd45369SNicolas Chautru op = (q->ring_addr + ((q->head_free_desc + dequeued_cbs) 2251efd45369SNicolas Chautru & q->sw_ring_wrap_mask))->enc_req.op_addr; 225248fc315fSNicolas Chautru if (op->turbo_enc.code_block_mode == RTE_BBDEV_TRANSPORT_BLOCK) 2253efd45369SNicolas Chautru ret = dequeue_enc_one_op_tb(q, &ops[i], dequeued_cbs); 2254efd45369SNicolas Chautru else 2255efd45369SNicolas Chautru ret = dequeue_enc_one_op_cb(q, &ops[i], dequeued_cbs); 2256efd45369SNicolas Chautru 2257efd45369SNicolas Chautru if (ret < 0) 2258efd45369SNicolas Chautru break; 2259efd45369SNicolas Chautru 2260efd45369SNicolas Chautru dequeued_cbs += ret; 2261efd45369SNicolas Chautru 2262efd45369SNicolas Chautru rte_bbdev_log_debug("dequeuing enc ops [%d/%d] | head %d | tail %d", 2263efd45369SNicolas Chautru dequeued_cbs, num, q->head_free_desc, q->tail); 2264efd45369SNicolas Chautru } 2265efd45369SNicolas Chautru 2266efd45369SNicolas Chautru /* Update head */ 2267efd45369SNicolas Chautru q->head_free_desc = (q->head_free_desc + dequeued_cbs) & 2268efd45369SNicolas Chautru q->sw_ring_wrap_mask; 2269efd45369SNicolas Chautru 2270efd45369SNicolas Chautru /* Update stats */ 2271efd45369SNicolas Chautru q_data->queue_stats.dequeued_count += i; 2272efd45369SNicolas Chautru 2273efd45369SNicolas Chautru return i; 2274efd45369SNicolas Chautru } 2275efd45369SNicolas Chautru 2276efd45369SNicolas Chautru static uint16_t 2277efd45369SNicolas Chautru fpga_dequeue_dec(struct rte_bbdev_queue_data *q_data, 2278efd45369SNicolas Chautru struct rte_bbdev_dec_op **ops, uint16_t num) 2279efd45369SNicolas Chautru { 2280efd45369SNicolas Chautru struct fpga_queue *q = q_data->queue_private; 2281efd45369SNicolas Chautru uint32_t avail = (q->tail - q->head_free_desc) & q->sw_ring_wrap_mask; 2282efd45369SNicolas Chautru uint16_t i; 2283efd45369SNicolas Chautru uint16_t dequeued_cbs = 0; 2284efd45369SNicolas Chautru struct rte_bbdev_dec_op *op; 2285efd45369SNicolas Chautru int ret; 2286efd45369SNicolas Chautru 2287efd45369SNicolas Chautru for (i = 0; (i < num) && (dequeued_cbs < avail); ++i) { 2288efd45369SNicolas Chautru op = (q->ring_addr + ((q->head_free_desc + dequeued_cbs) 2289efd45369SNicolas Chautru & q->sw_ring_wrap_mask))->dec_req.op_addr; 229048fc315fSNicolas Chautru if (op->turbo_dec.code_block_mode == RTE_BBDEV_TRANSPORT_BLOCK) 2291efd45369SNicolas Chautru ret = dequeue_dec_one_op_tb(q, &ops[i], dequeued_cbs); 2292efd45369SNicolas Chautru else 2293efd45369SNicolas Chautru ret = dequeue_dec_one_op_cb(q, &ops[i], dequeued_cbs); 2294efd45369SNicolas Chautru 2295efd45369SNicolas Chautru if (ret < 0) 2296efd45369SNicolas Chautru break; 2297efd45369SNicolas Chautru 2298efd45369SNicolas Chautru dequeued_cbs += ret; 2299efd45369SNicolas Chautru 2300efd45369SNicolas Chautru rte_bbdev_log_debug("dequeuing dec ops [%d/%d] | head %d | tail %d", 2301efd45369SNicolas Chautru dequeued_cbs, num, q->head_free_desc, q->tail); 2302efd45369SNicolas Chautru } 2303efd45369SNicolas Chautru 2304efd45369SNicolas Chautru /* Update head */ 2305efd45369SNicolas Chautru q->head_free_desc = (q->head_free_desc + dequeued_cbs) & 2306efd45369SNicolas Chautru q->sw_ring_wrap_mask; 2307efd45369SNicolas Chautru 2308efd45369SNicolas Chautru /* Update stats */ 2309efd45369SNicolas Chautru q_data->queue_stats.dequeued_count += i; 2310efd45369SNicolas Chautru 2311efd45369SNicolas Chautru return i; 2312efd45369SNicolas Chautru } 2313efd45369SNicolas Chautru 2314efd45369SNicolas Chautru /* Initialization Function */ 2315efd45369SNicolas Chautru static void 23166d608a6cSNicolas Chautru fpga_lte_fec_init(struct rte_bbdev *dev, struct rte_pci_driver *drv) 2317efd45369SNicolas Chautru { 2318efd45369SNicolas Chautru struct rte_pci_device *pci_dev = RTE_DEV_TO_PCI(dev->device); 2319efd45369SNicolas Chautru 2320efd45369SNicolas Chautru dev->dev_ops = &fpga_ops; 2321efd45369SNicolas Chautru dev->enqueue_enc_ops = fpga_enqueue_enc; 2322efd45369SNicolas Chautru dev->enqueue_dec_ops = fpga_enqueue_dec; 2323efd45369SNicolas Chautru dev->dequeue_enc_ops = fpga_dequeue_enc; 2324efd45369SNicolas Chautru dev->dequeue_dec_ops = fpga_dequeue_dec; 2325efd45369SNicolas Chautru 2326efd45369SNicolas Chautru ((struct fpga_lte_fec_device *) dev->data->dev_private)->pf_device = 23276d608a6cSNicolas Chautru !strcmp(drv->driver.name, 2328efd45369SNicolas Chautru RTE_STR(FPGA_LTE_FEC_PF_DRIVER_NAME)); 2329efd45369SNicolas Chautru ((struct fpga_lte_fec_device *) dev->data->dev_private)->mmio_base = 2330efd45369SNicolas Chautru pci_dev->mem_resource[0].addr; 2331efd45369SNicolas Chautru 2332efd45369SNicolas Chautru rte_bbdev_log_debug( 2333efd45369SNicolas Chautru "Init device %s [%s] @ virtaddr %p phyaddr %#"PRIx64, 2334755fb088SMaxime Coquelin drv->driver.name, dev->data->name, 2335efd45369SNicolas Chautru (void *)pci_dev->mem_resource[0].addr, 2336efd45369SNicolas Chautru pci_dev->mem_resource[0].phys_addr); 2337efd45369SNicolas Chautru } 2338efd45369SNicolas Chautru 2339efd45369SNicolas Chautru static int 23406d608a6cSNicolas Chautru fpga_lte_fec_probe(struct rte_pci_driver *pci_drv, 2341efd45369SNicolas Chautru struct rte_pci_device *pci_dev) 2342efd45369SNicolas Chautru { 2343efd45369SNicolas Chautru struct rte_bbdev *bbdev = NULL; 2344efd45369SNicolas Chautru char dev_name[RTE_BBDEV_NAME_MAX_LEN]; 2345efd45369SNicolas Chautru 2346efd45369SNicolas Chautru if (pci_dev == NULL) { 2347efd45369SNicolas Chautru rte_bbdev_log(ERR, "NULL PCI device"); 2348efd45369SNicolas Chautru return -EINVAL; 2349efd45369SNicolas Chautru } 2350efd45369SNicolas Chautru 2351efd45369SNicolas Chautru rte_pci_device_name(&pci_dev->addr, dev_name, sizeof(dev_name)); 2352efd45369SNicolas Chautru 2353efd45369SNicolas Chautru /* Allocate memory to be used privately by drivers */ 2354efd45369SNicolas Chautru bbdev = rte_bbdev_allocate(pci_dev->device.name); 2355efd45369SNicolas Chautru if (bbdev == NULL) 2356efd45369SNicolas Chautru return -ENODEV; 2357efd45369SNicolas Chautru 2358efd45369SNicolas Chautru /* allocate device private memory */ 2359efd45369SNicolas Chautru bbdev->data->dev_private = rte_zmalloc_socket(dev_name, 2360efd45369SNicolas Chautru sizeof(struct fpga_lte_fec_device), RTE_CACHE_LINE_SIZE, 2361efd45369SNicolas Chautru pci_dev->device.numa_node); 2362efd45369SNicolas Chautru 2363efd45369SNicolas Chautru if (bbdev->data->dev_private == NULL) { 2364efd45369SNicolas Chautru rte_bbdev_log(CRIT, 2365efd45369SNicolas Chautru "Allocate of %zu bytes for device \"%s\" failed", 2366efd45369SNicolas Chautru sizeof(struct fpga_lte_fec_device), dev_name); 2367efd45369SNicolas Chautru rte_bbdev_release(bbdev); 2368efd45369SNicolas Chautru return -ENOMEM; 2369efd45369SNicolas Chautru } 2370efd45369SNicolas Chautru 2371efd45369SNicolas Chautru /* Fill HW specific part of device structure */ 2372efd45369SNicolas Chautru bbdev->device = &pci_dev->device; 2373d61138d4SHarman Kalra bbdev->intr_handle = pci_dev->intr_handle; 2374efd45369SNicolas Chautru bbdev->data->socket_id = pci_dev->device.numa_node; 2375efd45369SNicolas Chautru 2376efd45369SNicolas Chautru /* Invoke FEC FPGA device initialization function */ 23776d608a6cSNicolas Chautru fpga_lte_fec_init(bbdev, pci_drv); 2378efd45369SNicolas Chautru 2379efd45369SNicolas Chautru rte_bbdev_log_debug("bbdev id = %u [%s]", 2380efd45369SNicolas Chautru bbdev->data->dev_id, dev_name); 2381efd45369SNicolas Chautru 2382efd45369SNicolas Chautru struct fpga_lte_fec_device *d = bbdev->data->dev_private; 2383efd45369SNicolas Chautru uint32_t version_id = fpga_reg_read_32(d->mmio_base, 2384efd45369SNicolas Chautru FPGA_LTE_FEC_VERSION_ID); 2385efd45369SNicolas Chautru rte_bbdev_log(INFO, "FEC FPGA RTL v%u.%u", 2386efd45369SNicolas Chautru ((uint16_t)(version_id >> 16)), ((uint16_t)version_id)); 2387efd45369SNicolas Chautru 2388efd45369SNicolas Chautru #ifdef RTE_LIBRTE_BBDEV_DEBUG 2389755fb088SMaxime Coquelin if (!strcmp(pci_drv->driver.name, 2390efd45369SNicolas Chautru RTE_STR(FPGA_LTE_FEC_PF_DRIVER_NAME))) 2391efd45369SNicolas Chautru print_static_reg_debug_info(d->mmio_base); 2392efd45369SNicolas Chautru #endif 2393efd45369SNicolas Chautru return 0; 2394efd45369SNicolas Chautru } 2395efd45369SNicolas Chautru 2396efd45369SNicolas Chautru static int 2397efd45369SNicolas Chautru fpga_lte_fec_remove(struct rte_pci_device *pci_dev) 2398efd45369SNicolas Chautru { 2399efd45369SNicolas Chautru struct rte_bbdev *bbdev; 2400efd45369SNicolas Chautru int ret; 2401efd45369SNicolas Chautru uint8_t dev_id; 2402efd45369SNicolas Chautru 2403efd45369SNicolas Chautru if (pci_dev == NULL) 2404efd45369SNicolas Chautru return -EINVAL; 2405efd45369SNicolas Chautru 2406efd45369SNicolas Chautru /* Find device */ 2407efd45369SNicolas Chautru bbdev = rte_bbdev_get_named_dev(pci_dev->device.name); 2408efd45369SNicolas Chautru if (bbdev == NULL) { 2409efd45369SNicolas Chautru rte_bbdev_log(CRIT, 2410efd45369SNicolas Chautru "Couldn't find HW dev \"%s\" to uninitialise it", 2411efd45369SNicolas Chautru pci_dev->device.name); 2412efd45369SNicolas Chautru return -ENODEV; 2413efd45369SNicolas Chautru } 2414efd45369SNicolas Chautru dev_id = bbdev->data->dev_id; 2415efd45369SNicolas Chautru 2416efd45369SNicolas Chautru /* free device private memory before close */ 2417efd45369SNicolas Chautru rte_free(bbdev->data->dev_private); 2418efd45369SNicolas Chautru 2419efd45369SNicolas Chautru /* Close device */ 2420efd45369SNicolas Chautru ret = rte_bbdev_close(dev_id); 2421efd45369SNicolas Chautru if (ret < 0) 2422efd45369SNicolas Chautru rte_bbdev_log(ERR, 2423efd45369SNicolas Chautru "Device %i failed to close during uninit: %i", 2424efd45369SNicolas Chautru dev_id, ret); 2425efd45369SNicolas Chautru 2426efd45369SNicolas Chautru /* release bbdev from library */ 2427efd45369SNicolas Chautru ret = rte_bbdev_release(bbdev); 2428efd45369SNicolas Chautru if (ret) 2429efd45369SNicolas Chautru rte_bbdev_log(ERR, "Device %i failed to uninit: %i", dev_id, 2430efd45369SNicolas Chautru ret); 2431efd45369SNicolas Chautru 2432efd45369SNicolas Chautru rte_bbdev_log_debug("Destroyed bbdev = %u", dev_id); 2433efd45369SNicolas Chautru 2434efd45369SNicolas Chautru return 0; 2435efd45369SNicolas Chautru } 2436efd45369SNicolas Chautru 2437efd45369SNicolas Chautru static inline void 2438e6925585SMaxime Coquelin set_default_fpga_conf(struct rte_fpga_lte_fec_conf *def_conf) 2439efd45369SNicolas Chautru { 2440efd45369SNicolas Chautru /* clear default configuration before initialization */ 2441e6925585SMaxime Coquelin memset(def_conf, 0, sizeof(struct rte_fpga_lte_fec_conf)); 2442efd45369SNicolas Chautru /* Set pf mode to true */ 2443efd45369SNicolas Chautru def_conf->pf_mode_en = true; 2444efd45369SNicolas Chautru 2445efd45369SNicolas Chautru /* Set ratio between UL and DL to 1:1 (unit of weight is 3 CBs) */ 2446efd45369SNicolas Chautru def_conf->ul_bandwidth = 3; 2447efd45369SNicolas Chautru def_conf->dl_bandwidth = 3; 2448efd45369SNicolas Chautru 2449efd45369SNicolas Chautru /* Set Load Balance Factor to 64 */ 2450efd45369SNicolas Chautru def_conf->dl_load_balance = 64; 2451efd45369SNicolas Chautru def_conf->ul_load_balance = 64; 2452efd45369SNicolas Chautru } 2453efd45369SNicolas Chautru 2454efd45369SNicolas Chautru /* Initial configuration of FPGA LTE FEC device */ 2455efd45369SNicolas Chautru int 2456e6925585SMaxime Coquelin rte_fpga_lte_fec_configure(const char *dev_name, 2457e6925585SMaxime Coquelin const struct rte_fpga_lte_fec_conf *conf) 2458efd45369SNicolas Chautru { 2459efd45369SNicolas Chautru uint32_t payload_32, address; 2460efd45369SNicolas Chautru uint16_t payload_16; 2461efd45369SNicolas Chautru uint8_t payload_8; 2462efd45369SNicolas Chautru uint16_t q_id, vf_id, total_q_id, total_ul_q_id, total_dl_q_id; 2463efd45369SNicolas Chautru struct rte_bbdev *bbdev = rte_bbdev_get_named_dev(dev_name); 2464e6925585SMaxime Coquelin struct rte_fpga_lte_fec_conf def_conf; 2465efd45369SNicolas Chautru 2466efd45369SNicolas Chautru if (bbdev == NULL) { 2467efd45369SNicolas Chautru rte_bbdev_log(ERR, 2468efd45369SNicolas Chautru "Invalid dev_name (%s), or device is not yet initialised", 2469efd45369SNicolas Chautru dev_name); 2470efd45369SNicolas Chautru return -ENODEV; 2471efd45369SNicolas Chautru } 2472efd45369SNicolas Chautru 2473efd45369SNicolas Chautru struct fpga_lte_fec_device *d = bbdev->data->dev_private; 2474efd45369SNicolas Chautru 2475efd45369SNicolas Chautru if (conf == NULL) { 2476efd45369SNicolas Chautru rte_bbdev_log(ERR, 2477efd45369SNicolas Chautru "FPGA Configuration was not provided. Default configuration will be loaded."); 2478efd45369SNicolas Chautru set_default_fpga_conf(&def_conf); 2479efd45369SNicolas Chautru conf = &def_conf; 2480efd45369SNicolas Chautru } 2481efd45369SNicolas Chautru 2482efd45369SNicolas Chautru /* 2483efd45369SNicolas Chautru * Configure UL:DL ratio. 2484efd45369SNicolas Chautru * [7:0]: UL weight 2485efd45369SNicolas Chautru * [15:8]: DL weight 2486efd45369SNicolas Chautru */ 2487efd45369SNicolas Chautru payload_16 = (conf->dl_bandwidth << 8) | conf->ul_bandwidth; 2488efd45369SNicolas Chautru address = FPGA_LTE_FEC_CONFIGURATION; 2489efd45369SNicolas Chautru fpga_reg_write_16(d->mmio_base, address, payload_16); 2490efd45369SNicolas Chautru 2491efd45369SNicolas Chautru /* Clear all queues registers */ 2492efd45369SNicolas Chautru payload_32 = FPGA_INVALID_HW_QUEUE_ID; 2493efd45369SNicolas Chautru for (q_id = 0; q_id < FPGA_TOTAL_NUM_QUEUES; ++q_id) { 2494efd45369SNicolas Chautru address = (q_id << 2) + FPGA_LTE_FEC_QUEUE_MAP; 2495efd45369SNicolas Chautru fpga_reg_write_32(d->mmio_base, address, payload_32); 2496efd45369SNicolas Chautru } 2497efd45369SNicolas Chautru 2498efd45369SNicolas Chautru /* 2499efd45369SNicolas Chautru * If PF mode is enabled allocate all queues for PF only. 2500efd45369SNicolas Chautru * 2501efd45369SNicolas Chautru * For VF mode each VF can have different number of UL and DL queues. 2502efd45369SNicolas Chautru * Total number of queues to configure cannot exceed FPGA 2503efd45369SNicolas Chautru * capabilities - 64 queues - 32 queues for UL and 32 queues for DL. 2504efd45369SNicolas Chautru * Queues mapping is done according to configuration: 2505efd45369SNicolas Chautru * 2506efd45369SNicolas Chautru * UL queues: 2507efd45369SNicolas Chautru * | Q_ID | VF_ID | 2508efd45369SNicolas Chautru * | 0 | 0 | 2509efd45369SNicolas Chautru * | ... | 0 | 2510efd45369SNicolas Chautru * | conf->vf_dl_queues_number[0] - 1 | 0 | 2511efd45369SNicolas Chautru * | conf->vf_dl_queues_number[0] | 1 | 2512efd45369SNicolas Chautru * | ... | 1 | 2513efd45369SNicolas Chautru * | conf->vf_dl_queues_number[1] - 1 | 1 | 2514efd45369SNicolas Chautru * | ... | ... | 2515efd45369SNicolas Chautru * | conf->vf_dl_queues_number[7] - 1 | 7 | 2516efd45369SNicolas Chautru * 2517efd45369SNicolas Chautru * DL queues: 2518efd45369SNicolas Chautru * | Q_ID | VF_ID | 2519efd45369SNicolas Chautru * | 32 | 0 | 2520efd45369SNicolas Chautru * | ... | 0 | 2521efd45369SNicolas Chautru * | conf->vf_ul_queues_number[0] - 1 | 0 | 2522efd45369SNicolas Chautru * | conf->vf_ul_queues_number[0] | 1 | 2523efd45369SNicolas Chautru * | ... | 1 | 2524efd45369SNicolas Chautru * | conf->vf_ul_queues_number[1] - 1 | 1 | 2525efd45369SNicolas Chautru * | ... | ... | 2526efd45369SNicolas Chautru * | conf->vf_ul_queues_number[7] - 1 | 7 | 2527efd45369SNicolas Chautru * 2528efd45369SNicolas Chautru * Example of configuration: 2529efd45369SNicolas Chautru * conf->vf_ul_queues_number[0] = 4; -> 4 UL queues for VF0 2530efd45369SNicolas Chautru * conf->vf_dl_queues_number[0] = 4; -> 4 DL queues for VF0 2531efd45369SNicolas Chautru * conf->vf_ul_queues_number[1] = 2; -> 2 UL queues for VF1 2532efd45369SNicolas Chautru * conf->vf_dl_queues_number[1] = 2; -> 2 DL queues for VF1 2533efd45369SNicolas Chautru * 2534efd45369SNicolas Chautru * UL: 2535efd45369SNicolas Chautru * | Q_ID | VF_ID | 2536efd45369SNicolas Chautru * | 0 | 0 | 2537efd45369SNicolas Chautru * | 1 | 0 | 2538efd45369SNicolas Chautru * | 2 | 0 | 2539efd45369SNicolas Chautru * | 3 | 0 | 2540efd45369SNicolas Chautru * | 4 | 1 | 2541efd45369SNicolas Chautru * | 5 | 1 | 2542efd45369SNicolas Chautru * 2543efd45369SNicolas Chautru * DL: 2544efd45369SNicolas Chautru * | Q_ID | VF_ID | 2545efd45369SNicolas Chautru * | 32 | 0 | 2546efd45369SNicolas Chautru * | 33 | 0 | 2547efd45369SNicolas Chautru * | 34 | 0 | 2548efd45369SNicolas Chautru * | 35 | 0 | 2549efd45369SNicolas Chautru * | 36 | 1 | 2550efd45369SNicolas Chautru * | 37 | 1 | 2551efd45369SNicolas Chautru */ 2552efd45369SNicolas Chautru if (conf->pf_mode_en) { 2553efd45369SNicolas Chautru payload_32 = 0x1; 2554efd45369SNicolas Chautru for (q_id = 0; q_id < FPGA_TOTAL_NUM_QUEUES; ++q_id) { 2555efd45369SNicolas Chautru address = (q_id << 2) + FPGA_LTE_FEC_QUEUE_MAP; 2556efd45369SNicolas Chautru fpga_reg_write_32(d->mmio_base, address, payload_32); 2557efd45369SNicolas Chautru } 2558efd45369SNicolas Chautru } else { 2559efd45369SNicolas Chautru /* Calculate total number of UL and DL queues to configure */ 2560efd45369SNicolas Chautru total_ul_q_id = total_dl_q_id = 0; 2561efd45369SNicolas Chautru for (vf_id = 0; vf_id < FPGA_LTE_FEC_NUM_VFS; ++vf_id) { 2562efd45369SNicolas Chautru total_ul_q_id += conf->vf_ul_queues_number[vf_id]; 2563efd45369SNicolas Chautru total_dl_q_id += conf->vf_dl_queues_number[vf_id]; 2564efd45369SNicolas Chautru } 2565efd45369SNicolas Chautru total_q_id = total_dl_q_id + total_ul_q_id; 2566efd45369SNicolas Chautru /* 2567efd45369SNicolas Chautru * Check if total number of queues to configure does not exceed 2568efd45369SNicolas Chautru * FPGA capabilities (64 queues - 32 UL and 32 DL queues) 2569efd45369SNicolas Chautru */ 2570efd45369SNicolas Chautru if ((total_ul_q_id > FPGA_NUM_UL_QUEUES) || 2571efd45369SNicolas Chautru (total_dl_q_id > FPGA_NUM_DL_QUEUES) || 2572efd45369SNicolas Chautru (total_q_id > FPGA_TOTAL_NUM_QUEUES)) { 2573efd45369SNicolas Chautru rte_bbdev_log(ERR, 2574efd45369SNicolas Chautru "FPGA Configuration failed. Too many queues to configure: UL_Q %u, DL_Q %u, FPGA_Q %u", 2575efd45369SNicolas Chautru total_ul_q_id, total_dl_q_id, 2576efd45369SNicolas Chautru FPGA_TOTAL_NUM_QUEUES); 2577efd45369SNicolas Chautru return -EINVAL; 2578efd45369SNicolas Chautru } 2579efd45369SNicolas Chautru total_ul_q_id = 0; 2580efd45369SNicolas Chautru for (vf_id = 0; vf_id < FPGA_LTE_FEC_NUM_VFS; ++vf_id) { 2581efd45369SNicolas Chautru for (q_id = 0; q_id < conf->vf_ul_queues_number[vf_id]; 2582efd45369SNicolas Chautru ++q_id, ++total_ul_q_id) { 2583efd45369SNicolas Chautru address = (total_ul_q_id << 2) + 2584efd45369SNicolas Chautru FPGA_LTE_FEC_QUEUE_MAP; 2585efd45369SNicolas Chautru payload_32 = ((0x80 + vf_id) << 16) | 0x1; 2586efd45369SNicolas Chautru fpga_reg_write_32(d->mmio_base, address, 2587efd45369SNicolas Chautru payload_32); 2588efd45369SNicolas Chautru } 2589efd45369SNicolas Chautru } 2590efd45369SNicolas Chautru total_dl_q_id = 0; 2591efd45369SNicolas Chautru for (vf_id = 0; vf_id < FPGA_LTE_FEC_NUM_VFS; ++vf_id) { 2592efd45369SNicolas Chautru for (q_id = 0; q_id < conf->vf_dl_queues_number[vf_id]; 2593efd45369SNicolas Chautru ++q_id, ++total_dl_q_id) { 2594efd45369SNicolas Chautru address = ((total_dl_q_id + FPGA_NUM_UL_QUEUES) 2595efd45369SNicolas Chautru << 2) + FPGA_LTE_FEC_QUEUE_MAP; 2596efd45369SNicolas Chautru payload_32 = ((0x80 + vf_id) << 16) | 0x1; 2597efd45369SNicolas Chautru fpga_reg_write_32(d->mmio_base, address, 2598efd45369SNicolas Chautru payload_32); 2599efd45369SNicolas Chautru } 2600efd45369SNicolas Chautru } 2601efd45369SNicolas Chautru } 2602efd45369SNicolas Chautru 2603efd45369SNicolas Chautru /* Setting Load Balance Factor */ 2604efd45369SNicolas Chautru payload_16 = (conf->dl_load_balance << 8) | (conf->ul_load_balance); 2605efd45369SNicolas Chautru address = FPGA_LTE_FEC_LOAD_BALANCE_FACTOR; 2606efd45369SNicolas Chautru fpga_reg_write_16(d->mmio_base, address, payload_16); 2607efd45369SNicolas Chautru 2608efd45369SNicolas Chautru /* Setting length of ring descriptor entry */ 2609efd45369SNicolas Chautru payload_16 = FPGA_RING_DESC_ENTRY_LENGTH; 2610efd45369SNicolas Chautru address = FPGA_LTE_FEC_RING_DESC_LEN; 2611efd45369SNicolas Chautru fpga_reg_write_16(d->mmio_base, address, payload_16); 2612efd45369SNicolas Chautru 2613efd45369SNicolas Chautru /* Setting FLR timeout value */ 2614efd45369SNicolas Chautru payload_16 = conf->flr_time_out; 2615efd45369SNicolas Chautru address = FPGA_LTE_FEC_FLR_TIME_OUT; 2616efd45369SNicolas Chautru fpga_reg_write_16(d->mmio_base, address, payload_16); 2617efd45369SNicolas Chautru 2618efd45369SNicolas Chautru /* Queue PF/VF mapping table is ready */ 2619efd45369SNicolas Chautru payload_8 = 0x1; 2620efd45369SNicolas Chautru address = FPGA_LTE_FEC_QUEUE_PF_VF_MAP_DONE; 2621efd45369SNicolas Chautru fpga_reg_write_8(d->mmio_base, address, payload_8); 2622efd45369SNicolas Chautru 2623efd45369SNicolas Chautru rte_bbdev_log_debug("PF FPGA LTE FEC configuration complete for %s", 2624efd45369SNicolas Chautru dev_name); 2625efd45369SNicolas Chautru 2626efd45369SNicolas Chautru #ifdef RTE_LIBRTE_BBDEV_DEBUG 2627efd45369SNicolas Chautru print_static_reg_debug_info(d->mmio_base); 2628efd45369SNicolas Chautru #endif 2629efd45369SNicolas Chautru return 0; 2630efd45369SNicolas Chautru } 2631efd45369SNicolas Chautru 2632efd45369SNicolas Chautru /* FPGA LTE FEC PCI PF address map */ 2633efd45369SNicolas Chautru static struct rte_pci_id pci_id_fpga_lte_fec_pf_map[] = { 2634efd45369SNicolas Chautru { 2635efd45369SNicolas Chautru RTE_PCI_DEVICE(FPGA_LTE_FEC_VENDOR_ID, 2636efd45369SNicolas Chautru FPGA_LTE_FEC_PF_DEVICE_ID) 2637efd45369SNicolas Chautru }, 2638efd45369SNicolas Chautru {.device_id = 0}, 2639efd45369SNicolas Chautru }; 2640efd45369SNicolas Chautru 2641efd45369SNicolas Chautru static struct rte_pci_driver fpga_lte_fec_pci_pf_driver = { 2642efd45369SNicolas Chautru .probe = fpga_lte_fec_probe, 2643efd45369SNicolas Chautru .remove = fpga_lte_fec_remove, 2644efd45369SNicolas Chautru .id_table = pci_id_fpga_lte_fec_pf_map, 2645efd45369SNicolas Chautru .drv_flags = RTE_PCI_DRV_NEED_MAPPING 2646efd45369SNicolas Chautru }; 2647efd45369SNicolas Chautru 2648efd45369SNicolas Chautru /* FPGA LTE FEC PCI VF address map */ 2649efd45369SNicolas Chautru static struct rte_pci_id pci_id_fpga_lte_fec_vf_map[] = { 2650efd45369SNicolas Chautru { 2651efd45369SNicolas Chautru RTE_PCI_DEVICE(FPGA_LTE_FEC_VENDOR_ID, 2652efd45369SNicolas Chautru FPGA_LTE_FEC_VF_DEVICE_ID) 2653efd45369SNicolas Chautru }, 2654efd45369SNicolas Chautru {.device_id = 0}, 2655efd45369SNicolas Chautru }; 2656efd45369SNicolas Chautru 2657efd45369SNicolas Chautru static struct rte_pci_driver fpga_lte_fec_pci_vf_driver = { 2658efd45369SNicolas Chautru .probe = fpga_lte_fec_probe, 2659efd45369SNicolas Chautru .remove = fpga_lte_fec_remove, 2660efd45369SNicolas Chautru .id_table = pci_id_fpga_lte_fec_vf_map, 2661efd45369SNicolas Chautru .drv_flags = RTE_PCI_DRV_NEED_MAPPING 2662efd45369SNicolas Chautru }; 2663efd45369SNicolas Chautru 2664efd45369SNicolas Chautru 2665efd45369SNicolas Chautru RTE_PMD_REGISTER_PCI(FPGA_LTE_FEC_PF_DRIVER_NAME, fpga_lte_fec_pci_pf_driver); 2666efd45369SNicolas Chautru RTE_PMD_REGISTER_PCI_TABLE(FPGA_LTE_FEC_PF_DRIVER_NAME, 2667efd45369SNicolas Chautru pci_id_fpga_lte_fec_pf_map); 2668efd45369SNicolas Chautru RTE_PMD_REGISTER_PCI(FPGA_LTE_FEC_VF_DRIVER_NAME, fpga_lte_fec_pci_vf_driver); 2669efd45369SNicolas Chautru RTE_PMD_REGISTER_PCI_TABLE(FPGA_LTE_FEC_VF_DRIVER_NAME, 2670efd45369SNicolas Chautru pci_id_fpga_lte_fec_vf_map); 2671