baseband/fpga_5gnr_fec: add HARQ loopback capability
authorNicolas Chautru <nicolas.chautru@intel.com>
Sat, 18 Apr 2020 22:46:46 +0000 (15:46 -0700)
committerAkhil Goyal <akhil.goyal@nxp.com>
Sun, 19 Apr 2020 20:34:26 +0000 (22:34 +0200)
Adding optional capability to support loopback preloading
and check of the extern HARQ memory.
This function is required to run the HARQ bit exact test successfully.

Signed-off-by: Nicolas Chautru <nicolas.chautru@intel.com>
Acked-by: Dave Burley <dave.burley@accelercomm.com>
Acked-by: Niall Power <niall.power@intel.com>
Acked-by: Akhil Goyal <akhil.goyal@nxp.com>
drivers/baseband/fpga_5gnr_fec/fpga_5gnr_fec.h
drivers/baseband/fpga_5gnr_fec/rte_fpga_5gnr_fec.c

index fde3b30..e72c95e 100644 (file)
@@ -366,6 +366,8 @@ fpga_reg_read_16(void *mmio_base, uint32_t offset)
        return rte_le_to_cpu_16(ret);
 }
 
+#endif
+
 /* Read a register of FPGA 5GNR FEC device */
 static inline uint8_t
 fpga_reg_read_8(void *mmio_base, uint32_t offset)
@@ -383,6 +385,4 @@ fpga_reg_read_64(void *mmio_base, uint32_t offset)
        return rte_le_to_cpu_64(ret);
 }
 
-#endif
-
 #endif /* _FPGA_5GNR_FEC_H_ */
index d9c1883..63d11ad 100644 (file)
@@ -324,6 +324,7 @@ fpga_dev_info_get(struct rte_bbdev *dev,
                                RTE_BBDEV_LDPC_ITERATION_STOP_ENABLE |
                                RTE_BBDEV_LDPC_INTERNAL_HARQ_MEMORY_IN_ENABLE |
                                RTE_BBDEV_LDPC_INTERNAL_HARQ_MEMORY_OUT_ENABLE |
+                               RTE_BBDEV_LDPC_INTERNAL_HARQ_MEMORY_LOOPBACK |
                                RTE_BBDEV_LDPC_INTERNAL_HARQ_MEMORY_FILLERS,
                        .llr_size = 6,
                        .llr_decimals = 2,
@@ -1054,6 +1055,140 @@ validate_dec_op(struct rte_bbdev_dec_op *op __rte_unused)
 }
 #endif
 
+static inline int
+fpga_harq_write_loopback(struct fpga_5gnr_fec_device *fpga_dev,
+               struct rte_mbuf *harq_input, uint16_t harq_in_length,
+               uint32_t harq_in_offset, uint32_t harq_out_offset)
+{
+       uint32_t out_offset = harq_out_offset;
+       uint32_t in_offset = harq_in_offset;
+       uint32_t left_length = harq_in_length;
+       uint32_t reg_32, increment = 0;
+       uint64_t *input = NULL;
+       uint32_t last_transaction = left_length
+                       % FPGA_5GNR_FEC_DDR_WR_DATA_LEN_IN_BYTES;
+       uint64_t last_word;
+
+       if (last_transaction > 0)
+               left_length -= last_transaction;
+
+       /*
+        * Get HARQ buffer size for each VF/PF: When 0x00, there is no
+        * available DDR space for the corresponding VF/PF.
+        */
+       reg_32 = fpga_reg_read_32(fpga_dev->mmio_base,
+                       FPGA_5GNR_FEC_HARQ_BUF_SIZE_REGS);
+       if (reg_32 < harq_in_length) {
+               left_length = reg_32;
+               rte_bbdev_log(ERR, "HARQ in length > HARQ buffer size\n");
+       }
+
+       input = (uint64_t *)rte_pktmbuf_mtod_offset(harq_input,
+                       uint8_t *, in_offset);
+
+       while (left_length > 0) {
+               if (fpga_reg_read_8(fpga_dev->mmio_base,
+                               FPGA_5GNR_FEC_DDR4_ADDR_RDY_REGS) ==  1) {
+                       fpga_reg_write_32(fpga_dev->mmio_base,
+                                       FPGA_5GNR_FEC_DDR4_WR_ADDR_REGS,
+                                       out_offset);
+                       fpga_reg_write_64(fpga_dev->mmio_base,
+                                       FPGA_5GNR_FEC_DDR4_WR_DATA_REGS,
+                                       input[increment]);
+                       left_length -= FPGA_5GNR_FEC_DDR_WR_DATA_LEN_IN_BYTES;
+                       out_offset += FPGA_5GNR_FEC_DDR_WR_DATA_LEN_IN_BYTES;
+                       increment++;
+                       fpga_reg_write_8(fpga_dev->mmio_base,
+                                       FPGA_5GNR_FEC_DDR4_WR_DONE_REGS, 1);
+               }
+       }
+       while (last_transaction > 0) {
+               if (fpga_reg_read_8(fpga_dev->mmio_base,
+                               FPGA_5GNR_FEC_DDR4_ADDR_RDY_REGS) ==  1) {
+                       fpga_reg_write_32(fpga_dev->mmio_base,
+                                       FPGA_5GNR_FEC_DDR4_WR_ADDR_REGS,
+                                       out_offset);
+                       last_word = input[increment];
+                       last_word &= (uint64_t)(1 << (last_transaction * 4))
+                                       - 1;
+                       fpga_reg_write_64(fpga_dev->mmio_base,
+                                       FPGA_5GNR_FEC_DDR4_WR_DATA_REGS,
+                                       last_word);
+                       fpga_reg_write_8(fpga_dev->mmio_base,
+                                       FPGA_5GNR_FEC_DDR4_WR_DONE_REGS, 1);
+                       last_transaction = 0;
+               }
+       }
+       return 1;
+}
+
+static inline int
+fpga_harq_read_loopback(struct fpga_5gnr_fec_device *fpga_dev,
+               struct rte_mbuf *harq_output, uint16_t harq_in_length,
+               uint32_t harq_in_offset, uint32_t harq_out_offset)
+{
+       uint32_t left_length, in_offset = harq_in_offset;
+       uint64_t reg;
+       uint32_t increment = 0;
+       uint64_t *input = NULL;
+       uint32_t last_transaction = harq_in_length
+                       % FPGA_5GNR_FEC_DDR_WR_DATA_LEN_IN_BYTES;
+
+       if (last_transaction > 0)
+               harq_in_length += (8 - last_transaction);
+
+       reg = fpga_reg_read_32(fpga_dev->mmio_base,
+                       FPGA_5GNR_FEC_HARQ_BUF_SIZE_REGS);
+       if (reg < harq_in_length) {
+               harq_in_length = reg;
+               rte_bbdev_log(ERR, "HARQ in length > HARQ buffer size\n");
+       }
+
+       if (!mbuf_append(harq_output, harq_output, harq_in_length)) {
+               rte_bbdev_log(ERR, "HARQ output buffer warning %d %d\n",
+                               harq_output->buf_len -
+                               rte_pktmbuf_headroom(harq_output),
+                               harq_in_length);
+               harq_in_length = harq_output->buf_len -
+                               rte_pktmbuf_headroom(harq_output);
+               if (!mbuf_append(harq_output, harq_output, harq_in_length)) {
+                       rte_bbdev_log(ERR, "HARQ output buffer issue %d %d\n",
+                                       harq_output->buf_len, harq_in_length);
+                       return -1;
+               }
+       }
+       left_length = harq_in_length;
+
+       input = (uint64_t *)rte_pktmbuf_mtod_offset(harq_output,
+                       uint8_t *, harq_out_offset);
+
+       while (left_length > 0) {
+               fpga_reg_write_32(fpga_dev->mmio_base,
+                       FPGA_5GNR_FEC_DDR4_RD_ADDR_REGS, in_offset);
+               fpga_reg_write_8(fpga_dev->mmio_base,
+                               FPGA_5GNR_FEC_DDR4_RD_DONE_REGS, 1);
+               reg = fpga_reg_read_8(fpga_dev->mmio_base,
+                       FPGA_5GNR_FEC_DDR4_RD_RDY_REGS);
+               while (reg != 1) {
+                       reg = fpga_reg_read_8(fpga_dev->mmio_base,
+                               FPGA_5GNR_FEC_DDR4_RD_RDY_REGS);
+                       if (reg == FPGA_DDR_OVERFLOW) {
+                               rte_bbdev_log(ERR,
+                                               "Read address is overflow!\n");
+                               return -1;
+                       }
+               }
+               input[increment] = fpga_reg_read_64(fpga_dev->mmio_base,
+                       FPGA_5GNR_FEC_DDR4_RD_DATA_REGS);
+               left_length -= FPGA_5GNR_FEC_DDR_RD_DATA_LEN_IN_BYTES;
+               in_offset += FPGA_5GNR_FEC_DDR_WR_DATA_LEN_IN_BYTES;
+               increment++;
+               fpga_reg_write_8(fpga_dev->mmio_base,
+                               FPGA_5GNR_FEC_DDR4_RD_DONE_REGS, 0);
+       }
+       return 1;
+}
+
 static inline int
 enqueue_ldpc_enc_one_op_cb(struct fpga_queue *q, struct rte_bbdev_enc_op *op,
                uint16_t desc_offset)
@@ -1182,6 +1317,42 @@ enqueue_ldpc_dec_one_op_cb(struct fpga_queue *q, struct rte_bbdev_dec_op *op,
        ring_offset = ((q->tail + desc_offset) & q->sw_ring_wrap_mask);
        desc = q->ring_addr + ring_offset;
 
+       if (check_bit(dec->op_flags,
+                       RTE_BBDEV_LDPC_INTERNAL_HARQ_MEMORY_LOOPBACK)) {
+               struct rte_mbuf *harq_in = dec->harq_combined_input.data;
+               struct rte_mbuf *harq_out = dec->harq_combined_output.data;
+               harq_in_length = dec->harq_combined_input.length;
+               uint32_t harq_in_offset = dec->harq_combined_input.offset;
+               uint32_t harq_out_offset = dec->harq_combined_output.offset;
+
+               if (check_bit(dec->op_flags,
+                               RTE_BBDEV_LDPC_INTERNAL_HARQ_MEMORY_OUT_ENABLE
+                               )) {
+                       ret = fpga_harq_write_loopback(q->d, harq_in,
+                                       harq_in_length, harq_in_offset,
+                                       harq_out_offset);
+               } else if (check_bit(dec->op_flags,
+                               RTE_BBDEV_LDPC_INTERNAL_HARQ_MEMORY_IN_ENABLE
+                               )) {
+                       ret = fpga_harq_read_loopback(q->d, harq_out,
+                               harq_in_length, harq_in_offset,
+                               harq_out_offset);
+                       dec->harq_combined_output.length = harq_in_length;
+               } else {
+                       rte_bbdev_log(ERR, "OP flag Err!");
+                       ret = -1;
+               }
+               /* Set descriptor for dequeue */
+               desc->dec_req.done = 1;
+               desc->dec_req.error = 0;
+               desc->dec_req.op_addr = op;
+               desc->dec_req.cbs_in_op = 1;
+               /* Mark this dummy descriptor to be dropped by HW */
+               desc->dec_req.desc_idx = (ring_offset + 1)
+                               & q->sw_ring_wrap_mask;
+               return ret; /* Error or number of CB */
+       }
+
        if (m_in == NULL || m_out == NULL) {
                rte_bbdev_log(ERR, "Invalid mbuf pointer");
                op->status = 1 << RTE_BBDEV_DATA_ERROR;