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