Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright(c) 2020 Intel Corporation
3 : : */
4 : :
5 : : #include <unistd.h>
6 : :
7 : : #include <rte_common.h>
8 : : #include <rte_log.h>
9 : : #include <dev_driver.h>
10 : : #include <rte_malloc.h>
11 : : #include <rte_mempool.h>
12 : : #include <rte_errno.h>
13 : : #include <rte_pci.h>
14 : : #include <bus_pci_driver.h>
15 : : #include <rte_byteorder.h>
16 : : #include <rte_cycles.h>
17 : : #include <rte_random.h>
18 : :
19 : : #include <rte_bbdev.h>
20 : : #include <rte_bbdev_pmd.h>
21 : :
22 : : #include "rte_pmd_fpga_5gnr_fec.h"
23 : : #include "fpga_5gnr_fec.h"
24 : :
25 : : #ifdef RTE_LIBRTE_BBDEV_DEBUG
26 : : RTE_LOG_REGISTER_DEFAULT(fpga_5gnr_fec_logtype, DEBUG);
27 : : #else
28 [ - + ]: 238 : RTE_LOG_REGISTER_DEFAULT(fpga_5gnr_fec_logtype, NOTICE);
29 : : #endif
30 : :
31 : : #ifdef RTE_LIBRTE_BBDEV_DEBUG
32 : :
33 : : /* Read Ring Control Register of FPGA 5GNR FEC device */
34 : : static inline void
35 : : print_ring_reg_debug_info(void *mmio_base, uint32_t offset)
36 : : {
37 : : rte_bbdev_log_debug(
38 : : "FPGA 5GNR MMIO base address @ %p | Ring Control Register @ offset = 0x%08"
39 : : PRIx32, mmio_base, offset);
40 : : rte_bbdev_log_debug(
41 : : "RING_BASE_ADDR = 0x%016"PRIx64,
42 : : fpga_5gnr_reg_read_64(mmio_base, offset));
43 : : rte_bbdev_log_debug(
44 : : "RING_HEAD_ADDR = 0x%016"PRIx64,
45 : : fpga_5gnr_reg_read_64(mmio_base, offset +
46 : : FPGA_5GNR_FEC_RING_HEAD_ADDR));
47 : : rte_bbdev_log_debug(
48 : : "RING_SIZE = 0x%04"PRIx16,
49 : : fpga_5gnr_reg_read_16(mmio_base, offset +
50 : : FPGA_5GNR_FEC_RING_SIZE));
51 : : rte_bbdev_log_debug(
52 : : "RING_MISC = 0x%02"PRIx8,
53 : : fpga_5gnr_reg_read_8(mmio_base, offset +
54 : : FPGA_5GNR_FEC_RING_MISC));
55 : : rte_bbdev_log_debug(
56 : : "RING_ENABLE = 0x%02"PRIx8,
57 : : fpga_5gnr_reg_read_8(mmio_base, offset +
58 : : FPGA_5GNR_FEC_RING_ENABLE));
59 : : rte_bbdev_log_debug(
60 : : "RING_FLUSH_QUEUE_EN = 0x%02"PRIx8,
61 : : fpga_5gnr_reg_read_8(mmio_base, offset +
62 : : FPGA_5GNR_FEC_RING_FLUSH_QUEUE_EN));
63 : : rte_bbdev_log_debug(
64 : : "RING_SHADOW_TAIL = 0x%04"PRIx16,
65 : : fpga_5gnr_reg_read_16(mmio_base, offset +
66 : : FPGA_5GNR_FEC_RING_SHADOW_TAIL));
67 : : rte_bbdev_log_debug(
68 : : "RING_HEAD_POINT = 0x%04"PRIx16,
69 : : fpga_5gnr_reg_read_16(mmio_base, offset +
70 : : FPGA_5GNR_FEC_RING_HEAD_POINT));
71 : : }
72 : :
73 : : /* Read Static Register of Vista Creek device. */
74 : : static inline void
75 : : print_static_reg_debug_info(void *mmio_base, uint8_t fpga_variant)
76 : : {
77 : : uint16_t config;
78 : : uint8_t qmap_done = fpga_5gnr_reg_read_8(mmio_base, FPGA_5GNR_FEC_QUEUE_PF_VF_MAP_DONE);
79 : : uint16_t lb_factor = fpga_5gnr_reg_read_16(mmio_base, FPGA_5GNR_FEC_LOAD_BALANCE_FACTOR);
80 : : uint16_t ring_desc_len = fpga_5gnr_reg_read_16(mmio_base, FPGA_5GNR_FEC_RING_DESC_LEN);
81 : : if (fpga_variant == VC_5GNR_FPGA_VARIANT)
82 : : config = fpga_5gnr_reg_read_16(mmio_base, VC_5GNR_CONFIGURATION);
83 : :
84 : : if (fpga_variant == VC_5GNR_FPGA_VARIANT)
85 : : rte_bbdev_log_debug("UL.DL Weights = %u.%u",
86 : : ((uint8_t)config), ((uint8_t)(config >> 8)));
87 : : rte_bbdev_log_debug("UL.DL Load Balance = %u.%u",
88 : : ((uint8_t)lb_factor), ((uint8_t)(lb_factor >> 8)));
89 : : rte_bbdev_log_debug("Queue-PF/VF Mapping Table = %s",
90 : : (qmap_done > 0) ? "READY" : "NOT-READY");
91 : : if (fpga_variant == VC_5GNR_FPGA_VARIANT)
92 : : rte_bbdev_log_debug("Ring Descriptor Size = %u bytes",
93 : : ring_desc_len * VC_5GNR_RING_DESC_LEN_UNIT_BYTES);
94 : : else
95 : : rte_bbdev_log_debug("Ring Descriptor Size = %u bytes",
96 : : ring_desc_len * AGX100_RING_DESC_LEN_UNIT_BYTES);
97 : : }
98 : :
99 : : /* Print decode DMA Descriptor of Vista Creek Decoder device. */
100 : : static void
101 : : vc_5gnr_print_dma_dec_desc_debug_info(union vc_5gnr_dma_desc *desc)
102 : : {
103 : : rte_bbdev_log_debug("DMA response desc %p\n"
104 : : "\t-- done(%"PRIu32") | iter(%"PRIu32") | et_pass(%"PRIu32")"
105 : : " | crcb_pass (%"PRIu32") | error(%"PRIu32")\n"
106 : : "\t-- qm_idx(%"PRIu32") | max_iter(%"PRIu32") | "
107 : : "bg_idx (%"PRIu32") | harqin_en(%"PRIu32") | zc(%"PRIu32")\n"
108 : : "\t-- hbstroe_offset(%"PRIu32") | num_null (%"PRIu32") "
109 : : "| irq_en(%"PRIu32")\n"
110 : : "\t-- ncb(%"PRIu32") | desc_idx (%"PRIu32") | "
111 : : "drop_crc24b(%"PRIu32") | RV (%"PRIu32")\n"
112 : : "\t-- crc24b_ind(%"PRIu32") | et_dis (%"PRIu32")\n"
113 : : "\t-- harq_input_length(%"PRIu32") | rm_e(%"PRIu32")\n"
114 : : "\t-- cbs_in_op(%"PRIu32") | in_add (0x%08"PRIx32"%08"PRIx32")"
115 : : "| out_add (0x%08"PRIx32"%08"PRIx32")",
116 : : desc,
117 : : (uint32_t)desc->dec_req.done,
118 : : (uint32_t)desc->dec_req.iter,
119 : : (uint32_t)desc->dec_req.et_pass,
120 : : (uint32_t)desc->dec_req.crcb_pass,
121 : : (uint32_t)desc->dec_req.error,
122 : : (uint32_t)desc->dec_req.qm_idx,
123 : : (uint32_t)desc->dec_req.max_iter,
124 : : (uint32_t)desc->dec_req.bg_idx,
125 : : (uint32_t)desc->dec_req.harqin_en,
126 : : (uint32_t)desc->dec_req.zc,
127 : : (uint32_t)desc->dec_req.hbstroe_offset,
128 : : (uint32_t)desc->dec_req.num_null,
129 : : (uint32_t)desc->dec_req.irq_en,
130 : : (uint32_t)desc->dec_req.ncb,
131 : : (uint32_t)desc->dec_req.desc_idx,
132 : : (uint32_t)desc->dec_req.drop_crc24b,
133 : : (uint32_t)desc->dec_req.rv,
134 : : (uint32_t)desc->dec_req.crc24b_ind,
135 : : (uint32_t)desc->dec_req.et_dis,
136 : : (uint32_t)desc->dec_req.harq_input_length,
137 : : (uint32_t)desc->dec_req.rm_e,
138 : : (uint32_t)desc->dec_req.cbs_in_op,
139 : : (uint32_t)desc->dec_req.in_addr_hi,
140 : : (uint32_t)desc->dec_req.in_addr_lw,
141 : : (uint32_t)desc->dec_req.out_addr_hi,
142 : : (uint32_t)desc->dec_req.out_addr_lw);
143 : : uint32_t *word = (uint32_t *) desc;
144 : : rte_bbdev_log_debug("%08"PRIx32"\n%08"PRIx32"\n%08"PRIx32"\n%08"PRIx32"\n"
145 : : "%08"PRIx32"\n%08"PRIx32"\n%08"PRIx32"\n%08"PRIx32"\n",
146 : : word[0], word[1], word[2], word[3],
147 : : word[4], word[5], word[6], word[7]);
148 : : }
149 : :
150 : : /* Print decode DMA Descriptor of AGX100 Decoder device. */
151 : : static void
152 : : agx100_print_dma_dec_desc_debug_info(union agx100_dma_desc *desc)
153 : : {
154 : : rte_bbdev_log_debug("DMA response desc %p\n"
155 : : "\t-- done(%"PRIu32") | tb_crc_pass(%"PRIu32") | cb_crc_all_pass(%"PRIu32")"
156 : : " | cb_all_et_pass(%"PRIu32") | max_iter_ret(%"PRIu32") |"
157 : : "cgb_crc_bitmap(%"PRIu32") | error_msg(%"PRIu32") | error_code(%"PRIu32") |"
158 : : "et_dis (%"PRIu32") | harq_in_en(%"PRIu32") | max_iter(%"PRIu32")\n"
159 : : "\t-- ncb(%"PRIu32") | bg_idx (%"PRIu32") | qm_idx (%"PRIu32")"
160 : : "| zc(%"PRIu32") | rv(%"PRIu32") | int_en(%"PRIu32")\n"
161 : : "\t-- max_cbg(%"PRIu32") | cbgti(%"PRIu32") | cbgfi(%"PRIu32") |"
162 : : "cbgs(%"PRIu32") | desc_idx(%"PRIu32")\n"
163 : : "\t-- ca(%"PRIu32") | c(%"PRIu32") | llr_pckg(%"PRIu32") |"
164 : : "syndrome_check_mode(%"PRIu32") | num_null(%"PRIu32")\n"
165 : : "\t-- ea(%"PRIu32") | eba(%"PRIu32")\n"
166 : : "\t-- hbstore_offset_out(%"PRIu32")\n"
167 : : "\t-- hbstore_offset_in(%"PRIu32") | en_slice_ts(%"PRIu32") |"
168 : : "en_host_ts(%"PRIu32") | en_cb_wr_status(%"PRIu32")"
169 : : " | en_output_sg(%"PRIu32") | en_input_sg(%"PRIu32") | tb_cb(%"PRIu32")"
170 : : " | crc24b_ind(%"PRIu32")| drop_crc24b(%"PRIu32")\n"
171 : : "\t-- harq_input_length_a(%"PRIu32") | harq_input_length_b(%"PRIu32")\n"
172 : : "\t-- input_slice_table_addr_lo(%"PRIu32")"
173 : : " | input_start_addr_lo(%"PRIu32")\n"
174 : : "\t-- input_slice_table_addr_hi(%"PRIu32")"
175 : : " | input_start_addr_hi(%"PRIu32")\n"
176 : : "\t-- input_slice_num(%"PRIu32") | input_length(%"PRIu32")\n"
177 : : "\t-- output_slice_table_addr_lo(%"PRIu32")"
178 : : " | output_start_addr_lo(%"PRIu32")\n"
179 : : "\t-- output_slice_table_addr_hi(%"PRIu32")"
180 : : " | output_start_addr_hi(%"PRIu32")\n"
181 : : "\t-- output_slice_num(%"PRIu32") | output_length(%"PRIu32")\n"
182 : : "\t-- enqueue_timestamp(%"PRIu32")\n"
183 : : "\t-- completion_timestamp(%"PRIu32")\n",
184 : : desc,
185 : : (uint32_t)desc->dec_req.done,
186 : : (uint32_t)desc->dec_req.tb_crc_pass,
187 : : (uint32_t)desc->dec_req.cb_crc_all_pass,
188 : : (uint32_t)desc->dec_req.cb_all_et_pass,
189 : : (uint32_t)desc->dec_req.max_iter_ret,
190 : : (uint32_t)desc->dec_req.cgb_crc_bitmap,
191 : : (uint32_t)desc->dec_req.error_msg,
192 : : (uint32_t)desc->dec_req.error_code,
193 : : (uint32_t)desc->dec_req.et_dis,
194 : : (uint32_t)desc->dec_req.harq_in_en,
195 : : (uint32_t)desc->dec_req.max_iter,
196 : : (uint32_t)desc->dec_req.ncb,
197 : : (uint32_t)desc->dec_req.bg_idx,
198 : : (uint32_t)desc->dec_req.qm_idx,
199 : : (uint32_t)desc->dec_req.zc,
200 : : (uint32_t)desc->dec_req.rv,
201 : : (uint32_t)desc->dec_req.int_en,
202 : : (uint32_t)desc->dec_req.max_cbg,
203 : : (uint32_t)desc->dec_req.cbgti,
204 : : (uint32_t)desc->dec_req.cbgfi,
205 : : (uint32_t)desc->dec_req.cbgs,
206 : : (uint32_t)desc->dec_req.desc_idx,
207 : : (uint32_t)desc->dec_req.ca,
208 : : (uint32_t)desc->dec_req.c,
209 : : (uint32_t)desc->dec_req.llr_pckg,
210 : : (uint32_t)desc->dec_req.syndrome_check_mode,
211 : : (uint32_t)desc->dec_req.num_null,
212 : : (uint32_t)desc->dec_req.ea,
213 : : (uint32_t)desc->dec_req.eba,
214 : : (uint32_t)desc->dec_req.hbstore_offset_out,
215 : : (uint32_t)desc->dec_req.hbstore_offset_in,
216 : : (uint32_t)desc->dec_req.en_slice_ts,
217 : : (uint32_t)desc->dec_req.en_host_ts,
218 : : (uint32_t)desc->dec_req.en_cb_wr_status,
219 : : (uint32_t)desc->dec_req.en_output_sg,
220 : : (uint32_t)desc->dec_req.en_input_sg,
221 : : (uint32_t)desc->dec_req.tb_cb,
222 : : (uint32_t)desc->dec_req.crc24b_ind,
223 : : (uint32_t)desc->dec_req.drop_crc24b,
224 : : (uint32_t)desc->dec_req.harq_input_length_a,
225 : : (uint32_t)desc->dec_req.harq_input_length_b,
226 : : (uint32_t)desc->dec_req.input_slice_table_addr_lo,
227 : : (uint32_t)desc->dec_req.input_start_addr_lo,
228 : : (uint32_t)desc->dec_req.input_slice_table_addr_hi,
229 : : (uint32_t)desc->dec_req.input_start_addr_hi,
230 : : (uint32_t)desc->dec_req.input_slice_num,
231 : : (uint32_t)desc->dec_req.input_length,
232 : : (uint32_t)desc->dec_req.output_slice_table_addr_lo,
233 : : (uint32_t)desc->dec_req.output_start_addr_lo,
234 : : (uint32_t)desc->dec_req.output_slice_table_addr_hi,
235 : : (uint32_t)desc->dec_req.output_start_addr_hi,
236 : : (uint32_t)desc->dec_req.output_slice_num,
237 : : (uint32_t)desc->dec_req.output_length,
238 : : (uint32_t)desc->dec_req.enqueue_timestamp,
239 : : (uint32_t)desc->dec_req.completion_timestamp);
240 : :
241 : : uint32_t *word = (uint32_t *) desc;
242 : : rte_bbdev_log_debug("%08"PRIx32"\n%08"PRIx32"\n%08"PRIx32"\n%08"PRIx32"\n"
243 : : "%08"PRIx32"\n%08"PRIx32"\n%08"PRIx32"\n%08"PRIx32"\n"
244 : : "%08"PRIx32"\n%08"PRIx32"\n%08"PRIx32"\n%08"PRIx32"\n"
245 : : "%08"PRIx32"\n%08"PRIx32"\n%08"PRIx32"\n%08"PRIx32"\n",
246 : : word[0], word[1], word[2], word[3],
247 : : word[4], word[5], word[6], word[7],
248 : : word[8], word[9], word[10], word[11],
249 : : word[12], word[13], word[14], word[15]);
250 : : }
251 : :
252 : : /* Print decode DMA Descriptor of Vista Creek encoder device. */
253 : : static void
254 : : vc_5gnr_print_dma_enc_desc_debug_info(union vc_5gnr_dma_desc *desc)
255 : : {
256 : : rte_bbdev_log_debug("DMA response desc %p\n"
257 : : "%"PRIu32" %"PRIu32"\n"
258 : : "K' %"PRIu32" E %"PRIu32" desc %"PRIu32" Z %"PRIu32"\n"
259 : : "BG %"PRIu32" Qm %"PRIu32" CRC %"PRIu32" IRQ %"PRIu32"\n"
260 : : "k0 %"PRIu32" Ncb %"PRIu32" F %"PRIu32"\n",
261 : : desc,
262 : : (uint32_t)desc->enc_req.done,
263 : : (uint32_t)desc->enc_req.error,
264 : :
265 : : (uint32_t)desc->enc_req.k_,
266 : : (uint32_t)desc->enc_req.rm_e,
267 : : (uint32_t)desc->enc_req.desc_idx,
268 : : (uint32_t)desc->enc_req.zc,
269 : :
270 : : (uint32_t)desc->enc_req.bg_idx,
271 : : (uint32_t)desc->enc_req.qm_idx,
272 : : (uint32_t)desc->enc_req.crc_en,
273 : : (uint32_t)desc->enc_req.irq_en,
274 : :
275 : : (uint32_t)desc->enc_req.k0,
276 : : (uint32_t)desc->enc_req.ncb,
277 : : (uint32_t)desc->enc_req.num_null);
278 : : uint32_t *word = (uint32_t *) desc;
279 : : rte_bbdev_log_debug("%08"PRIx32"\n%08"PRIx32"\n%08"PRIx32"\n%08"PRIx32"\n"
280 : : "%08"PRIx32"\n%08"PRIx32"\n%08"PRIx32"\n%08"PRIx32"\n",
281 : : word[0], word[1], word[2], word[3],
282 : : word[4], word[5], word[6], word[7]);
283 : : }
284 : :
285 : : /* Print decode DMA Descriptor of AGX100 encoder device. */
286 : : static void
287 : : agx100_print_dma_enc_desc_debug_info(union agx100_dma_desc *desc)
288 : : {
289 : : rte_bbdev_log_debug("DMA response desc %p\n"
290 : : "\t-- done(%"PRIu32") | error_msg(%"PRIu32") | error_code(%"PRIu32")\n"
291 : : "\t-- ncb(%"PRIu32") | bg_idx (%"PRIu32") | qm_idx (%"PRIu32")"
292 : : "| zc(%"PRIu32") | rv(%"PRIu32") | int_en(%"PRIu32")\n"
293 : : "\t-- max_cbg(%"PRIu32") | cbgti(%"PRIu32") | cbgs(%"PRIu32") | "
294 : : "desc_idx(%"PRIu32")\n"
295 : : "\t-- ca(%"PRIu32") | c(%"PRIu32") | num_null(%"PRIu32")\n"
296 : : "\t-- ea(%"PRIu32")\n"
297 : : "\t-- eb(%"PRIu32")\n"
298 : : "\t-- k_(%"PRIu32") | en_slice_ts(%"PRIu32") | en_host_ts(%"PRIu32") | "
299 : : "en_cb_wr_status(%"PRIu32") | en_output_sg(%"PRIu32") | "
300 : : "en_input_sg(%"PRIu32") | tb_cb(%"PRIu32") | crc_en(%"PRIu32")\n"
301 : : "\t-- input_slice_table_addr_lo(%"PRIu32")"
302 : : " | input_start_addr_lo(%"PRIu32")\n"
303 : : "\t-- input_slice_table_addr_hi(%"PRIu32")"
304 : : " | input_start_addr_hi(%"PRIu32")\n"
305 : : "\t-- input_slice_num(%"PRIu32") | input_length(%"PRIu32")\n"
306 : : "\t-- output_slice_table_addr_lo(%"PRIu32")"
307 : : " | output_start_addr_lo(%"PRIu32")\n"
308 : : "\t-- output_slice_table_addr_hi(%"PRIu32")"
309 : : " | output_start_addr_hi(%"PRIu32")\n"
310 : : "\t-- output_slice_num(%"PRIu32") | output_length(%"PRIu32")\n"
311 : : "\t-- enqueue_timestamp(%"PRIu32")\n"
312 : : "\t-- completion_timestamp(%"PRIu32")\n",
313 : : desc,
314 : : (uint32_t)desc->enc_req.done,
315 : : (uint32_t)desc->enc_req.error_msg,
316 : : (uint32_t)desc->enc_req.error_code,
317 : : (uint32_t)desc->enc_req.ncb,
318 : : (uint32_t)desc->enc_req.bg_idx,
319 : : (uint32_t)desc->enc_req.qm_idx,
320 : : (uint32_t)desc->enc_req.zc,
321 : : (uint32_t)desc->enc_req.rv,
322 : : (uint32_t)desc->enc_req.int_en,
323 : : (uint32_t)desc->enc_req.max_cbg,
324 : : (uint32_t)desc->enc_req.cbgti,
325 : : (uint32_t)desc->enc_req.cbgs,
326 : : (uint32_t)desc->enc_req.desc_idx,
327 : : (uint32_t)desc->enc_req.ca,
328 : : (uint32_t)desc->enc_req.c,
329 : : (uint32_t)desc->enc_req.num_null,
330 : : (uint32_t)desc->enc_req.ea,
331 : : (uint32_t)desc->enc_req.eb,
332 : : (uint32_t)desc->enc_req.k_,
333 : : (uint32_t)desc->enc_req.en_slice_ts,
334 : : (uint32_t)desc->enc_req.en_host_ts,
335 : : (uint32_t)desc->enc_req.en_cb_wr_status,
336 : : (uint32_t)desc->enc_req.en_output_sg,
337 : : (uint32_t)desc->enc_req.en_input_sg,
338 : : (uint32_t)desc->enc_req.tb_cb,
339 : : (uint32_t)desc->enc_req.crc_en,
340 : : (uint32_t)desc->enc_req.input_slice_table_addr_lo,
341 : : (uint32_t)desc->enc_req.input_start_addr_lo,
342 : : (uint32_t)desc->enc_req.input_slice_table_addr_hi,
343 : : (uint32_t)desc->enc_req.input_start_addr_hi,
344 : : (uint32_t)desc->enc_req.input_slice_num,
345 : : (uint32_t)desc->enc_req.input_length,
346 : : (uint32_t)desc->enc_req.output_slice_table_addr_lo,
347 : : (uint32_t)desc->enc_req.output_start_addr_lo,
348 : : (uint32_t)desc->enc_req.output_slice_table_addr_hi,
349 : : (uint32_t)desc->enc_req.output_start_addr_hi,
350 : : (uint32_t)desc->enc_req.output_slice_num,
351 : : (uint32_t)desc->enc_req.output_length,
352 : : (uint32_t)desc->enc_req.enqueue_timestamp,
353 : : (uint32_t)desc->enc_req.completion_timestamp);
354 : :
355 : : uint32_t *word = (uint32_t *) desc;
356 : : rte_bbdev_log_debug("%08"PRIx32"\n%08"PRIx32"\n%08"PRIx32"\n%08"PRIx32"\n"
357 : : "%08"PRIx32"\n%08"PRIx32"\n%08"PRIx32"\n%08"PRIx32"\n"
358 : : "%08"PRIx32"\n%08"PRIx32"\n%08"PRIx32"\n%08"PRIx32"\n"
359 : : "%08"PRIx32"\n%08"PRIx32"\n%08"PRIx32"\n%08"PRIx32"\n",
360 : : word[0], word[1], word[2], word[3],
361 : : word[4], word[5], word[6], word[7],
362 : : word[8], word[9], word[10], word[11],
363 : : word[12], word[13], word[14], word[15]);
364 : : }
365 : :
366 : : #endif
367 : :
368 : : /**
369 : : * Helper function that returns queue ID if queue is valid
370 : : * or FPGA_5GNR_INVALID_HW_QUEUE_ID otherwise.
371 : : */
372 : : static inline uint32_t
373 : : fpga_5gnr_get_queue_map(struct fpga_5gnr_fec_device *d, uint32_t q_id)
374 : : {
375 [ # # # # ]: 0 : if (d->fpga_variant == VC_5GNR_FPGA_VARIANT)
376 : 0 : return fpga_5gnr_reg_read_32(d->mmio_base, VC_5GNR_QUEUE_MAP + (q_id << 2));
377 : : else
378 : 0 : return fpga_5gnr_reg_read_32(d->mmio_base, AGX100_QUEUE_MAP + (q_id << 2));
379 : : }
380 : :
381 : : static int
382 : 0 : fpga_5gnr_setup_queues(struct rte_bbdev *dev, uint16_t num_queues, int socket_id)
383 : : {
384 : : /* Number of queues bound to a PF/VF */
385 : : uint32_t hw_q_num = 0;
386 : : uint32_t ring_size, payload, address, q_id, offset;
387 : : rte_iova_t phys_addr;
388 : : struct fpga_5gnr_ring_ctrl_reg ring_reg;
389 : 0 : struct fpga_5gnr_fec_device *d = dev->data->dev_private;
390 : :
391 : : address = FPGA_5GNR_FEC_QUEUE_PF_VF_MAP_DONE;
392 [ # # ]: 0 : if (!(fpga_5gnr_reg_read_32(d->mmio_base, address) & 0x1)) {
393 : 0 : rte_bbdev_log(ERR,
394 : : "Queue-PF/VF mapping is not set! Was PF configured for device (%s) ?",
395 : : dev->data->name);
396 : 0 : return -EPERM;
397 : : }
398 : :
399 : : /* Clear queue registers structure */
400 : : memset(&ring_reg, 0, sizeof(struct fpga_5gnr_ring_ctrl_reg));
401 : :
402 : : /* Scan queue map.
403 : : * If a queue is valid and mapped to a calling PF/VF the read value is
404 : : * replaced with a queue ID and if it's not then
405 : : * FPGA_5GNR_INVALID_HW_QUEUE_ID is returned.
406 : : */
407 [ # # ]: 0 : for (q_id = 0; q_id < d->total_num_queues; ++q_id) {
408 : : uint32_t hw_q_id = fpga_5gnr_get_queue_map(d, q_id);
409 : :
410 : : rte_bbdev_log_debug("%s: queue ID: %u, registry queue ID: %u",
411 : : dev->device->name, q_id, hw_q_id);
412 : :
413 [ # # ]: 0 : if (hw_q_id != FPGA_5GNR_INVALID_HW_QUEUE_ID) {
414 : 0 : d->q_bound_bit_map |= (1ULL << q_id);
415 : : /* Clear queue register of found queue */
416 : 0 : offset = FPGA_5GNR_FEC_RING_CTRL_REGS +
417 : : (sizeof(struct fpga_5gnr_ring_ctrl_reg) * q_id);
418 : 0 : fpga_ring_reg_write(d->mmio_base, offset, ring_reg);
419 : 0 : ++hw_q_num;
420 : : }
421 : : }
422 [ # # ]: 0 : if (hw_q_num == 0) {
423 : 0 : rte_bbdev_log(ERR,
424 : : "No HW queues assigned to this device. Probably this is a VF configured for PF mode. Check device configuration!");
425 : 0 : return -ENODEV;
426 : : }
427 : :
428 [ # # ]: 0 : if (num_queues > hw_q_num) {
429 : 0 : rte_bbdev_log(ERR,
430 : : "Not enough queues for device %s! Requested: %u, available: %u",
431 : : dev->device->name, num_queues, hw_q_num);
432 : 0 : return -EINVAL;
433 : : }
434 [ # # ]: 0 : if (d->fpga_variant == VC_5GNR_FPGA_VARIANT)
435 : : ring_size = FPGA_5GNR_RING_MAX_SIZE * sizeof(struct vc_5gnr_dma_dec_desc);
436 : : else
437 : : ring_size = FPGA_5GNR_RING_MAX_SIZE * sizeof(struct agx100_dma_dec_desc);
438 : :
439 : : /* Enforce 32 byte alignment */
440 : : RTE_BUILD_BUG_ON((RTE_CACHE_LINE_SIZE % 32) != 0);
441 : :
442 : : /* Allocate memory for SW descriptor rings */
443 : 0 : d->sw_rings = rte_zmalloc_socket(dev->device->driver->name,
444 : 0 : num_queues * ring_size, RTE_CACHE_LINE_SIZE,
445 : : socket_id);
446 [ # # ]: 0 : if (d->sw_rings == NULL) {
447 : 0 : rte_bbdev_log(ERR,
448 : : "Failed to allocate memory for %s:%u sw_rings",
449 : : dev->device->driver->name, dev->data->dev_id);
450 : 0 : return -ENOMEM;
451 : : }
452 : :
453 : 0 : d->sw_rings_phys = rte_malloc_virt2iova(d->sw_rings);
454 : 0 : d->sw_ring_size = ring_size;
455 : 0 : d->sw_ring_max_depth = FPGA_5GNR_RING_MAX_SIZE;
456 : :
457 : : /* Allocate memory for ring flush status */
458 : 0 : d->flush_queue_status = rte_zmalloc_socket(NULL,
459 : : sizeof(uint64_t), RTE_CACHE_LINE_SIZE, socket_id);
460 [ # # ]: 0 : if (d->flush_queue_status == NULL) {
461 : 0 : rte_bbdev_log(ERR,
462 : : "Failed to allocate memory for %s:%u flush_queue_status",
463 : : dev->device->driver->name, dev->data->dev_id);
464 : 0 : return -ENOMEM;
465 : : }
466 : :
467 : : /* Set the flush status address registers */
468 : 0 : phys_addr = rte_malloc_virt2iova(d->flush_queue_status);
469 : :
470 : : address = FPGA_5GNR_FEC_VFQ_FLUSH_STATUS_LW;
471 : 0 : payload = (uint32_t)(phys_addr);
472 : 0 : fpga_5gnr_reg_write_32(d->mmio_base, address, payload);
473 : :
474 : : address = FPGA_5GNR_FEC_VFQ_FLUSH_STATUS_HI;
475 : 0 : payload = (uint32_t)(phys_addr >> 32);
476 : : fpga_5gnr_reg_write_32(d->mmio_base, address, payload);
477 : :
478 : 0 : return 0;
479 : : }
480 : :
481 : : static int
482 : 0 : fpga_5gnr_dev_close(struct rte_bbdev *dev)
483 : : {
484 : 0 : struct fpga_5gnr_fec_device *fpga_5gnr_dev = dev->data->dev_private;
485 : :
486 : 0 : rte_free(fpga_5gnr_dev->sw_rings);
487 : 0 : rte_free(fpga_5gnr_dev->flush_queue_status);
488 : :
489 : 0 : return 0;
490 : : }
491 : :
492 : : static void
493 : 0 : fpga_5gnr_dev_info_get(struct rte_bbdev *dev, struct rte_bbdev_driver_info *dev_info)
494 : : {
495 : 0 : struct fpga_5gnr_fec_device *d = dev->data->dev_private;
496 : : uint32_t q_id = 0;
497 : :
498 : : static const struct rte_bbdev_op_cap vc_5gnr_bbdev_capabilities[] = {
499 : : {
500 : : .type = RTE_BBDEV_OP_LDPC_ENC,
501 : : .cap.ldpc_enc = {
502 : : .capability_flags =
503 : : RTE_BBDEV_LDPC_RATE_MATCH |
504 : : RTE_BBDEV_LDPC_ENC_INTERRUPTS |
505 : : RTE_BBDEV_LDPC_CRC_24B_ATTACH,
506 : : .num_buffers_src =
507 : : RTE_BBDEV_LDPC_MAX_CODE_BLOCKS,
508 : : .num_buffers_dst =
509 : : RTE_BBDEV_LDPC_MAX_CODE_BLOCKS,
510 : : }
511 : : },
512 : : {
513 : : .type = RTE_BBDEV_OP_LDPC_DEC,
514 : : .cap.ldpc_dec = {
515 : : .capability_flags =
516 : : RTE_BBDEV_LDPC_CRC_TYPE_24B_CHECK |
517 : : RTE_BBDEV_LDPC_CRC_TYPE_24B_DROP |
518 : : RTE_BBDEV_LDPC_HQ_COMBINE_IN_ENABLE |
519 : : RTE_BBDEV_LDPC_HQ_COMBINE_OUT_ENABLE |
520 : : RTE_BBDEV_LDPC_ITERATION_STOP_ENABLE |
521 : : RTE_BBDEV_LDPC_INTERNAL_HARQ_MEMORY_IN_ENABLE |
522 : : RTE_BBDEV_LDPC_INTERNAL_HARQ_MEMORY_OUT_ENABLE |
523 : : RTE_BBDEV_LDPC_INTERNAL_HARQ_MEMORY_LOOPBACK |
524 : : RTE_BBDEV_LDPC_DEC_INTERRUPTS |
525 : : RTE_BBDEV_LDPC_INTERNAL_HARQ_MEMORY_FILLERS,
526 : : .llr_size = 6,
527 : : .llr_decimals = 2,
528 : : .num_buffers_src =
529 : : RTE_BBDEV_LDPC_MAX_CODE_BLOCKS,
530 : : .num_buffers_hard_out =
531 : : RTE_BBDEV_LDPC_MAX_CODE_BLOCKS,
532 : : .num_buffers_soft_out = 0,
533 : : }
534 : : },
535 : : RTE_BBDEV_END_OF_CAPABILITIES_LIST()
536 : : };
537 : :
538 : : static const struct rte_bbdev_op_cap agx100_bbdev_capabilities[] = {
539 : : {
540 : : .type = RTE_BBDEV_OP_LDPC_ENC,
541 : : .cap.ldpc_enc = {
542 : : .capability_flags =
543 : : RTE_BBDEV_LDPC_RATE_MATCH |
544 : : RTE_BBDEV_LDPC_CRC_24B_ATTACH,
545 : : .num_buffers_src =
546 : : RTE_BBDEV_LDPC_MAX_CODE_BLOCKS,
547 : : .num_buffers_dst =
548 : : RTE_BBDEV_LDPC_MAX_CODE_BLOCKS,
549 : : }
550 : : },
551 : : {
552 : : .type = RTE_BBDEV_OP_LDPC_DEC,
553 : : .cap.ldpc_dec = {
554 : : .capability_flags =
555 : : RTE_BBDEV_LDPC_CRC_TYPE_24B_CHECK |
556 : : RTE_BBDEV_LDPC_CRC_TYPE_24B_DROP |
557 : : RTE_BBDEV_LDPC_HQ_COMBINE_IN_ENABLE |
558 : : RTE_BBDEV_LDPC_HQ_COMBINE_OUT_ENABLE |
559 : : RTE_BBDEV_LDPC_ITERATION_STOP_ENABLE |
560 : : RTE_BBDEV_LDPC_INTERNAL_HARQ_MEMORY_IN_ENABLE |
561 : : RTE_BBDEV_LDPC_INTERNAL_HARQ_MEMORY_OUT_ENABLE |
562 : : RTE_BBDEV_LDPC_INTERNAL_HARQ_MEMORY_LOOPBACK |
563 : : RTE_BBDEV_LDPC_INTERNAL_HARQ_MEMORY_FILLERS,
564 : : .llr_size = 6,
565 : : .llr_decimals = 2,
566 : : .num_buffers_src =
567 : : RTE_BBDEV_LDPC_MAX_CODE_BLOCKS,
568 : : .num_buffers_hard_out =
569 : : RTE_BBDEV_LDPC_MAX_CODE_BLOCKS,
570 : : .num_buffers_soft_out = 0,
571 : : }
572 : : },
573 : : RTE_BBDEV_END_OF_CAPABILITIES_LIST()
574 : : };
575 : :
576 : : /* Check the HARQ DDR size available */
577 : : uint8_t timeout_counter = 0;
578 : 0 : uint32_t harq_buf_ready = fpga_5gnr_reg_read_32(d->mmio_base,
579 : : FPGA_5GNR_FEC_HARQ_BUF_SIZE_RDY_REGS);
580 [ # # ]: 0 : while (harq_buf_ready != 1) {
581 : 0 : usleep(FPGA_5GNR_TIMEOUT_CHECK_INTERVAL);
582 : 0 : timeout_counter++;
583 [ # # ]: 0 : harq_buf_ready = fpga_5gnr_reg_read_32(d->mmio_base,
584 : : FPGA_5GNR_FEC_HARQ_BUF_SIZE_RDY_REGS);
585 [ # # ]: 0 : if (timeout_counter > FPGA_5GNR_HARQ_RDY_TIMEOUT) {
586 : 0 : rte_bbdev_log(ERR, "HARQ Buffer not ready %d", harq_buf_ready);
587 : : harq_buf_ready = 1;
588 : : }
589 : : }
590 [ # # ]: 0 : uint32_t harq_buf_size = fpga_5gnr_reg_read_32(d->mmio_base,
591 : : FPGA_5GNR_FEC_HARQ_BUF_SIZE_REGS);
592 : :
593 : : static struct rte_bbdev_queue_conf default_queue_conf;
594 : 0 : default_queue_conf.socket = dev->data->socket_id;
595 : 0 : default_queue_conf.queue_size = FPGA_5GNR_RING_MAX_SIZE;
596 : :
597 : 0 : dev_info->driver_name = dev->device->driver->name;
598 : 0 : dev_info->queue_size_lim = FPGA_5GNR_RING_MAX_SIZE;
599 : 0 : dev_info->hardware_accelerated = true;
600 : 0 : dev_info->min_alignment = 1;
601 [ # # ]: 0 : if (d->fpga_variant == VC_5GNR_FPGA_VARIANT)
602 : 0 : dev_info->harq_buffer_size = (harq_buf_size >> 10) + 1;
603 : : else
604 : 0 : dev_info->harq_buffer_size = harq_buf_size << 10;
605 : 0 : dev_info->default_queue_conf = default_queue_conf;
606 [ # # ]: 0 : if (d->fpga_variant == VC_5GNR_FPGA_VARIANT)
607 : 0 : dev_info->capabilities = vc_5gnr_bbdev_capabilities;
608 : : else
609 : 0 : dev_info->capabilities = agx100_bbdev_capabilities;
610 : 0 : dev_info->cpu_flag_reqs = NULL;
611 : 0 : dev_info->data_endianness = RTE_LITTLE_ENDIAN;
612 : 0 : dev_info->device_status = RTE_BBDEV_DEV_NOT_SUPPORTED;
613 : :
614 : : /* Calculates number of queues assigned to device */
615 : 0 : dev_info->max_num_queues = 0;
616 [ # # ]: 0 : for (q_id = 0; q_id < d->total_num_queues; ++q_id) {
617 : : uint32_t hw_q_id = fpga_5gnr_get_queue_map(d, q_id);
618 : :
619 [ # # ]: 0 : if (hw_q_id != FPGA_5GNR_INVALID_HW_QUEUE_ID)
620 : 0 : dev_info->max_num_queues++;
621 : : }
622 : : /* Expose number of queue per operation type */
623 : 0 : dev_info->num_queues[RTE_BBDEV_OP_NONE] = 0;
624 : 0 : dev_info->num_queues[RTE_BBDEV_OP_TURBO_DEC] = 0;
625 : 0 : dev_info->num_queues[RTE_BBDEV_OP_TURBO_ENC] = 0;
626 : 0 : dev_info->num_queues[RTE_BBDEV_OP_LDPC_DEC] = dev_info->max_num_queues / 2;
627 : 0 : dev_info->num_queues[RTE_BBDEV_OP_LDPC_ENC] = dev_info->max_num_queues / 2;
628 : 0 : dev_info->queue_priority[RTE_BBDEV_OP_LDPC_DEC] = 1;
629 : 0 : dev_info->queue_priority[RTE_BBDEV_OP_LDPC_ENC] = 1;
630 : 0 : }
631 : :
632 : : /**
633 : : * Find index of queue bound to current PF/VF which is unassigned. Return -1
634 : : * when there is no available queue
635 : : */
636 : : static inline int
637 : 0 : fpga_5gnr_find_free_queue_idx(struct rte_bbdev *dev,
638 : : const struct rte_bbdev_queue_conf *conf)
639 : : {
640 : 0 : struct fpga_5gnr_fec_device *d = dev->data->dev_private;
641 : : uint64_t q_idx;
642 : : uint8_t i = 0;
643 : 0 : uint8_t range = d->total_num_queues >> 1;
644 : :
645 [ # # ]: 0 : if (conf->op_type == RTE_BBDEV_OP_LDPC_ENC) {
646 : : i = d->total_num_queues >> 1;
647 : : range = d->total_num_queues;
648 : : }
649 : :
650 [ # # ]: 0 : for (; i < range; ++i) {
651 : 0 : q_idx = 1ULL << i;
652 : : /* Check if index of queue is bound to current PF/VF */
653 [ # # ]: 0 : if (d->q_bound_bit_map & q_idx)
654 : : /* Check if found queue was not already assigned */
655 [ # # ]: 0 : if (!(d->q_assigned_bit_map & q_idx)) {
656 : 0 : d->q_assigned_bit_map |= q_idx;
657 : 0 : return i;
658 : : }
659 : : }
660 : :
661 : 0 : rte_bbdev_log(INFO, "Failed to find free queue on %s", dev->data->name);
662 : :
663 : 0 : return -1;
664 : : }
665 : :
666 : : static int
667 : 0 : fpga_5gnr_queue_setup(struct rte_bbdev *dev, uint16_t queue_id,
668 : : const struct rte_bbdev_queue_conf *conf)
669 : : {
670 : : uint32_t address, ring_offset;
671 : 0 : struct fpga_5gnr_fec_device *d = dev->data->dev_private;
672 : : struct fpga_5gnr_queue *q;
673 : : int8_t q_idx;
674 : :
675 : : /* Check if there is a free queue to assign */
676 : 0 : q_idx = fpga_5gnr_find_free_queue_idx(dev, conf);
677 [ # # ]: 0 : if (q_idx == -1)
678 : : return -1;
679 : :
680 : : /* Allocate the queue data structure. */
681 : 0 : q = rte_zmalloc_socket(dev->device->driver->name, sizeof(*q),
682 : 0 : RTE_CACHE_LINE_SIZE, conf->socket);
683 [ # # ]: 0 : if (q == NULL) {
684 : : /* Mark queue as un-assigned */
685 : 0 : d->q_assigned_bit_map &= (0xFFFFFFFF - (1ULL << q_idx));
686 : 0 : rte_bbdev_log(ERR, "Failed to allocate queue memory");
687 : 0 : return -ENOMEM;
688 : : }
689 : :
690 : 0 : q->d = d;
691 : 0 : q->q_idx = q_idx;
692 : :
693 : : /* Set ring_base_addr */
694 [ # # ]: 0 : if (d->fpga_variant == VC_5GNR_FPGA_VARIANT)
695 : 0 : q->vc_5gnr_ring_addr = RTE_PTR_ADD(d->sw_rings, (d->sw_ring_size * queue_id));
696 : : else
697 : 0 : q->agx100_ring_addr = RTE_PTR_ADD(d->sw_rings, (d->sw_ring_size * queue_id));
698 : :
699 : 0 : q->ring_ctrl_reg.ring_base_addr = d->sw_rings_phys + (d->sw_ring_size * queue_id);
700 : :
701 : : /* Allocate memory for Completion Head variable*/
702 : 0 : q->ring_head_addr = rte_zmalloc_socket(dev->device->driver->name,
703 : 0 : sizeof(uint64_t), RTE_CACHE_LINE_SIZE, conf->socket);
704 [ # # ]: 0 : if (q->ring_head_addr == NULL) {
705 : : /* Mark queue as un-assigned */
706 : 0 : d->q_assigned_bit_map &= (0xFFFFFFFF - (1ULL << q_idx));
707 : 0 : rte_free(q);
708 : 0 : rte_bbdev_log(ERR,
709 : : "Failed to allocate memory for %s:%u completion_head",
710 : : dev->device->driver->name, dev->data->dev_id);
711 : 0 : return -ENOMEM;
712 : : }
713 : : /* Set ring_head_addr */
714 : 0 : q->ring_ctrl_reg.ring_head_addr = rte_malloc_virt2iova(q->ring_head_addr);
715 : :
716 : : /* Clear shadow_completion_head */
717 : 0 : q->shadow_completion_head = 0;
718 : :
719 : : /* Set ring_size */
720 [ # # ]: 0 : if (conf->queue_size > FPGA_5GNR_RING_MAX_SIZE) {
721 : : /* Mark queue as un-assigned */
722 : 0 : d->q_assigned_bit_map &= (0xFFFFFFFF - (1ULL << q_idx));
723 : 0 : rte_free(q->ring_head_addr);
724 : 0 : rte_free(q);
725 : 0 : rte_bbdev_log(ERR,
726 : : "Size of queue is too big %d (MAX: %d ) for %s:%u",
727 : : conf->queue_size, FPGA_5GNR_RING_MAX_SIZE,
728 : : dev->device->driver->name, dev->data->dev_id);
729 : 0 : return -EINVAL;
730 : : }
731 : 0 : q->ring_ctrl_reg.ring_size = conf->queue_size;
732 : :
733 : : /* Set Miscellaneous FPGA 5GNR register. */
734 : : /* Max iteration number for TTI mitigation - todo */
735 : 0 : q->ring_ctrl_reg.max_ul_dec = 0;
736 : : /* Enable max iteration number for TTI - todo */
737 : : q->ring_ctrl_reg.max_ul_dec_en = 0;
738 : :
739 : : /* Enable the ring */
740 : 0 : q->ring_ctrl_reg.enable = 1;
741 : :
742 : : /* Set FPGA 5GNR head_point and tail registers */
743 : 0 : q->ring_ctrl_reg.head_point = q->tail = 0;
744 : :
745 : : /* Set FPGA 5GNR shadow_tail register */
746 : 0 : q->ring_ctrl_reg.shadow_tail = q->tail;
747 : :
748 : : /* Calculates the ring offset for found queue */
749 : 0 : ring_offset = FPGA_5GNR_FEC_RING_CTRL_REGS +
750 : : (sizeof(struct fpga_5gnr_ring_ctrl_reg) * q_idx);
751 : :
752 : : /* Set FPGA 5GNR Ring Control Registers */
753 : 0 : fpga_ring_reg_write(d->mmio_base, ring_offset, q->ring_ctrl_reg);
754 : :
755 : : /* Store MMIO register of shadow_tail */
756 : 0 : address = ring_offset + FPGA_5GNR_FEC_RING_SHADOW_TAIL;
757 : 0 : q->shadow_tail_addr = RTE_PTR_ADD(d->mmio_base, address);
758 : :
759 : 0 : q->head_free_desc = q->tail;
760 : :
761 : : /* Set wrap mask */
762 : 0 : q->sw_ring_wrap_mask = conf->queue_size - 1;
763 : :
764 : : rte_bbdev_log_debug("Setup dev%u q%u: queue_idx=%u",
765 : : dev->data->dev_id, queue_id, q->q_idx);
766 : :
767 : 0 : dev->data->queues[queue_id].queue_private = q;
768 : :
769 : : rte_bbdev_log_debug("BBDEV queue[%d] set up for FPGA 5GNR queue[%d]", queue_id, q_idx);
770 : :
771 : : #ifdef RTE_LIBRTE_BBDEV_DEBUG
772 : : /* Read FPGA Ring Control Registers after configuration*/
773 : : print_ring_reg_debug_info(d->mmio_base, ring_offset);
774 : : #endif
775 : 0 : return 0;
776 : : }
777 : :
778 : : static int
779 : 0 : fpga_5gnr_queue_release(struct rte_bbdev *dev, uint16_t queue_id)
780 : : {
781 : 0 : struct fpga_5gnr_fec_device *d = dev->data->dev_private;
782 : 0 : struct fpga_5gnr_queue *q = dev->data->queues[queue_id].queue_private;
783 : : struct fpga_5gnr_ring_ctrl_reg ring_reg;
784 : : uint32_t offset;
785 : :
786 : : rte_bbdev_log_debug("FPGA 5GNR Queue[%d] released", queue_id);
787 : :
788 [ # # ]: 0 : if (q != NULL) {
789 : : memset(&ring_reg, 0, sizeof(struct fpga_5gnr_ring_ctrl_reg));
790 : 0 : offset = FPGA_5GNR_FEC_RING_CTRL_REGS +
791 : 0 : (sizeof(struct fpga_5gnr_ring_ctrl_reg) * q->q_idx);
792 : : /* Disable queue */
793 : 0 : fpga_5gnr_reg_write_8(d->mmio_base,
794 : : offset + FPGA_5GNR_FEC_RING_ENABLE, 0x00);
795 : : /* Clear queue registers */
796 : 0 : fpga_ring_reg_write(d->mmio_base, offset, ring_reg);
797 : :
798 : : /* Mark the Queue as un-assigned */
799 : 0 : d->q_assigned_bit_map &= (0xFFFFFFFF - (1ULL << q->q_idx));
800 : 0 : rte_free(q->ring_head_addr);
801 : 0 : rte_free(q);
802 : 0 : dev->data->queues[queue_id].queue_private = NULL;
803 : : }
804 : :
805 : 0 : return 0;
806 : : }
807 : :
808 : : /* Function starts a device queue. */
809 : : static int
810 : 0 : fpga_5gnr_queue_start(struct rte_bbdev *dev, uint16_t queue_id)
811 : : {
812 : 0 : struct fpga_5gnr_fec_device *d = dev->data->dev_private;
813 : 0 : struct fpga_5gnr_queue *q = dev->data->queues[queue_id].queue_private;
814 : 0 : uint32_t offset = FPGA_5GNR_FEC_RING_CTRL_REGS +
815 : 0 : (sizeof(struct fpga_5gnr_ring_ctrl_reg) * q->q_idx);
816 : : uint8_t enable = 0x01;
817 : : uint16_t zero = 0x0000;
818 : : #ifdef RTE_LIBRTE_BBDEV_DEBUG
819 : : if (d == NULL) {
820 : : rte_bbdev_log(ERR, "Invalid device pointer");
821 : : return -1;
822 : : }
823 : : #endif
824 : : if (dev->data->queues[queue_id].queue_private == NULL) {
825 : : rte_bbdev_log(ERR, "Cannot start invalid queue %d", queue_id);
826 : : return -1;
827 : : }
828 : :
829 : : /* Clear queue head and tail variables */
830 : 0 : q->tail = q->head_free_desc = 0;
831 : :
832 : : /* Clear FPGA 5GNR head_point and tail registers */
833 : 0 : fpga_5gnr_reg_write_16(d->mmio_base, offset + FPGA_5GNR_FEC_RING_HEAD_POINT, zero);
834 : 0 : fpga_5gnr_reg_write_16(d->mmio_base, offset + FPGA_5GNR_FEC_RING_SHADOW_TAIL, zero);
835 : :
836 : : /* Enable queue */
837 : 0 : fpga_5gnr_reg_write_8(d->mmio_base, offset + FPGA_5GNR_FEC_RING_ENABLE, enable);
838 : :
839 : : rte_bbdev_log_debug("FPGA 5GNR Queue[%d] started", queue_id);
840 : : return 0;
841 : : }
842 : :
843 : : /* Function stops a device queue. */
844 : : static int
845 : 0 : fpga_5gnr_queue_stop(struct rte_bbdev *dev, uint16_t queue_id)
846 : : {
847 : 0 : struct fpga_5gnr_fec_device *d = dev->data->dev_private;
848 : : #ifdef RTE_LIBRTE_BBDEV_DEBUG
849 : : if (d == NULL) {
850 : : rte_bbdev_log(ERR, "Invalid device pointer");
851 : : return -1;
852 : : }
853 : : #endif
854 : 0 : struct fpga_5gnr_queue *q = dev->data->queues[queue_id].queue_private;
855 : 0 : uint32_t offset = FPGA_5GNR_FEC_RING_CTRL_REGS +
856 : 0 : (sizeof(struct fpga_5gnr_ring_ctrl_reg) * q->q_idx);
857 : : uint8_t payload = 0x01;
858 : : uint8_t counter = 0;
859 : : uint8_t timeout = FPGA_5GNR_QUEUE_FLUSH_TIMEOUT_US / FPGA_5GNR_TIMEOUT_CHECK_INTERVAL;
860 : :
861 : : /* Set flush_queue_en bit to trigger queue flushing */
862 : 0 : fpga_5gnr_reg_write_8(d->mmio_base,
863 : : offset + FPGA_5GNR_FEC_RING_FLUSH_QUEUE_EN, payload);
864 : :
865 : : /** Check if queue flush is completed.
866 : : * FPGA 5GNR will update the completion flag after queue flushing is
867 : : * completed. If completion flag is not updated within 1ms it is
868 : : * considered as a failure.
869 : : */
870 [ # # ]: 0 : while (!(*((volatile uint8_t *)d->flush_queue_status + q->q_idx) & payload)) {
871 [ # # ]: 0 : if (counter > timeout) {
872 : 0 : rte_bbdev_log(ERR, "FPGA 5GNR Queue Flush failed for queue %d", queue_id);
873 : 0 : return -1;
874 : : }
875 : 0 : usleep(FPGA_5GNR_TIMEOUT_CHECK_INTERVAL);
876 : 0 : counter++;
877 : : }
878 : :
879 : : /* Disable queue */
880 : : payload = 0x00;
881 : 0 : fpga_5gnr_reg_write_8(d->mmio_base, offset + FPGA_5GNR_FEC_RING_ENABLE, payload);
882 : :
883 : : rte_bbdev_log_debug("FPGA 5GNR Queue[%d] stopped", queue_id);
884 : 0 : return 0;
885 : : }
886 : :
887 : : static inline uint16_t
888 : : get_queue_id(struct rte_bbdev_data *data, uint8_t q_idx)
889 : : {
890 : : uint16_t queue_id;
891 : :
892 [ # # ]: 0 : for (queue_id = 0; queue_id < data->num_queues; ++queue_id) {
893 : 0 : struct fpga_5gnr_queue *q = data->queues[queue_id].queue_private;
894 [ # # # # ]: 0 : if (q != NULL && q->q_idx == q_idx)
895 : : return queue_id;
896 : : }
897 : :
898 : : return -1;
899 : : }
900 : :
901 : : /* Interrupt handler triggered by FPGA 5GNR dev for handling specific interrupt. */
902 : : static void
903 : 0 : fpga_5gnr_dev_interrupt_handler(void *cb_arg)
904 : : {
905 : : struct rte_bbdev *dev = cb_arg;
906 : 0 : struct fpga_5gnr_fec_device *d = dev->data->dev_private;
907 : : struct fpga_5gnr_queue *q;
908 : : uint64_t ring_head;
909 : : uint64_t q_idx;
910 : : uint16_t queue_id;
911 : : uint8_t i;
912 : :
913 : : /* Scan queue assigned to this device */
914 [ # # ]: 0 : for (i = 0; i < d->total_num_queues; ++i) {
915 : 0 : q_idx = 1ULL << i;
916 [ # # ]: 0 : if (d->q_bound_bit_map & q_idx) {
917 : 0 : queue_id = get_queue_id(dev->data, i);
918 [ # # ]: 0 : if (queue_id == (uint16_t) -1)
919 : 0 : continue;
920 : :
921 : : /* Check if completion head was changed */
922 : 0 : q = dev->data->queues[queue_id].queue_private;
923 : 0 : ring_head = *q->ring_head_addr;
924 [ # # ]: 0 : if (q->shadow_completion_head != ring_head &&
925 [ # # ]: 0 : q->irq_enable == 1) {
926 : 0 : q->shadow_completion_head = ring_head;
927 : 0 : rte_bbdev_pmd_callback_process(
928 : : dev,
929 : : RTE_BBDEV_EVENT_DEQUEUE,
930 : : &queue_id);
931 : : }
932 : : }
933 : : }
934 : 0 : }
935 : :
936 : : static int
937 : 0 : fpga_5gnr_queue_intr_enable(struct rte_bbdev *dev, uint16_t queue_id)
938 : : {
939 : 0 : struct fpga_5gnr_queue *q = dev->data->queues[queue_id].queue_private;
940 : :
941 [ # # ]: 0 : if (!rte_intr_cap_multiple(dev->intr_handle))
942 : : return -ENOTSUP;
943 : :
944 : 0 : q->irq_enable = 1;
945 : :
946 : 0 : return 0;
947 : : }
948 : :
949 : : static int
950 : 0 : fpga_5gnr_queue_intr_disable(struct rte_bbdev *dev, uint16_t queue_id)
951 : : {
952 : 0 : struct fpga_5gnr_queue *q = dev->data->queues[queue_id].queue_private;
953 : 0 : q->irq_enable = 0;
954 : :
955 : 0 : return 0;
956 : : }
957 : :
958 : : static int
959 : 0 : fpga_5gnr_intr_enable(struct rte_bbdev *dev)
960 : : {
961 : : int ret;
962 : : uint8_t i;
963 : 0 : struct fpga_5gnr_fec_device *d = dev->data->dev_private;
964 : : uint8_t num_intr_vec;
965 : :
966 : 0 : num_intr_vec = d->total_num_queues - RTE_INTR_VEC_RXTX_OFFSET;
967 [ # # ]: 0 : if (!rte_intr_cap_multiple(dev->intr_handle)) {
968 : 0 : rte_bbdev_log(ERR, "Multiple intr vector is not supported by FPGA (%s)",
969 : : dev->data->name);
970 : 0 : return -ENOTSUP;
971 : : }
972 : :
973 : : /* Create event file descriptors for each of the supported queues (Maximum 64).
974 : : * Event fds will be mapped to FPGA IRQs in rte_intr_enable().
975 : : * This is a 1:1 mapping where the IRQ number is a direct translation to the queue number.
976 : : *
977 : : * num_intr_vec event fds are created as rte_intr_enable()
978 : : * mapped the first IRQ to already created interrupt event file
979 : : * descriptor (intr_handle->fd).
980 : : */
981 [ # # ]: 0 : if (rte_intr_efd_enable(dev->intr_handle, num_intr_vec)) {
982 : 0 : rte_bbdev_log(ERR, "Failed to create fds for %u queues", dev->data->num_queues);
983 : 0 : return -1;
984 : : }
985 : :
986 : : /* TODO Each event file descriptor is overwritten by interrupt event
987 : : * file descriptor. That descriptor is added to epoll observed list.
988 : : * It ensures that callback function assigned to that descriptor will
989 : : * invoked when any FPGA queue issues interrupt.
990 : : */
991 [ # # ]: 0 : for (i = 0; i < num_intr_vec; ++i) {
992 [ # # ]: 0 : if (rte_intr_efds_index_set(dev->intr_handle, i,
993 : 0 : rte_intr_fd_get(dev->intr_handle)))
994 : 0 : return -rte_errno;
995 : : }
996 : :
997 [ # # ]: 0 : if (rte_intr_vec_list_alloc(dev->intr_handle, "intr_vec", dev->data->num_queues)) {
998 : 0 : rte_bbdev_log(ERR, "Failed to allocate %u vectors", dev->data->num_queues);
999 : 0 : return -ENOMEM;
1000 : : }
1001 : :
1002 : 0 : ret = rte_intr_enable(dev->intr_handle);
1003 [ # # ]: 0 : if (ret < 0) {
1004 : 0 : rte_bbdev_log(ERR,
1005 : : "Couldn't enable interrupts for device: %s",
1006 : : dev->data->name);
1007 : 0 : return ret;
1008 : : }
1009 : :
1010 : 0 : ret = rte_intr_callback_register(dev->intr_handle, fpga_5gnr_dev_interrupt_handler, dev);
1011 [ # # ]: 0 : if (ret < 0) {
1012 : 0 : rte_bbdev_log(ERR,
1013 : : "Couldn't register interrupt callback for device: %s",
1014 : : dev->data->name);
1015 : 0 : return ret;
1016 : : }
1017 : :
1018 : : return 0;
1019 : : }
1020 : :
1021 : : static const struct rte_bbdev_ops fpga_5gnr_ops = {
1022 : : .setup_queues = fpga_5gnr_setup_queues,
1023 : : .intr_enable = fpga_5gnr_intr_enable,
1024 : : .close = fpga_5gnr_dev_close,
1025 : : .info_get = fpga_5gnr_dev_info_get,
1026 : : .queue_setup = fpga_5gnr_queue_setup,
1027 : : .queue_stop = fpga_5gnr_queue_stop,
1028 : : .queue_start = fpga_5gnr_queue_start,
1029 : : .queue_release = fpga_5gnr_queue_release,
1030 : : .queue_intr_enable = fpga_5gnr_queue_intr_enable,
1031 : : .queue_intr_disable = fpga_5gnr_queue_intr_disable
1032 : : };
1033 : :
1034 : : /* Provide the descriptor index on a given queue */
1035 : : static inline uint16_t
1036 : : fpga_5gnr_desc_idx(struct fpga_5gnr_queue *q, uint16_t offset)
1037 : : {
1038 : 0 : return (q->head_free_desc + offset) & q->sw_ring_wrap_mask;
1039 : : }
1040 : :
1041 : : /* Provide the VC 5GNR descriptor pointer on a given queue */
1042 : : static inline union vc_5gnr_dma_desc*
1043 : : vc_5gnr_get_desc(struct fpga_5gnr_queue *q, uint16_t offset)
1044 : : {
1045 : 0 : return q->vc_5gnr_ring_addr + fpga_5gnr_desc_idx(q, offset);
1046 : : }
1047 : :
1048 : : /* Provide the AGX100 descriptor pointer on a given queue */
1049 : : static inline union agx100_dma_desc*
1050 : : agx100_get_desc(struct fpga_5gnr_queue *q, uint16_t offset)
1051 : : {
1052 : 0 : return q->agx100_ring_addr + fpga_5gnr_desc_idx(q, offset);
1053 : : }
1054 : :
1055 : : /* Provide the descriptor index for the tail of a given queue */
1056 : : static inline uint16_t
1057 : : fpga_5gnr_desc_idx_tail(struct fpga_5gnr_queue *q, uint16_t offset)
1058 : : {
1059 : 0 : return (q->tail + offset) & q->sw_ring_wrap_mask;
1060 : : }
1061 : :
1062 : : /* Provide the descriptor tail pointer on a given queue */
1063 : : static inline union vc_5gnr_dma_desc*
1064 : : vc_5gnr_get_desc_tail(struct fpga_5gnr_queue *q, uint16_t offset)
1065 : : {
1066 : 0 : return q->vc_5gnr_ring_addr + fpga_5gnr_desc_idx_tail(q, offset);
1067 : : }
1068 : :
1069 : : /* Provide the descriptor tail pointer on a given queue */
1070 : : static inline union agx100_dma_desc*
1071 : : agx100_get_desc_tail(struct fpga_5gnr_queue *q, uint16_t offset)
1072 : : {
1073 : 0 : return q->agx100_ring_addr + fpga_5gnr_desc_idx_tail(q, offset);
1074 : : }
1075 : :
1076 : : static inline void
1077 : : fpga_5gnr_dma_enqueue(struct fpga_5gnr_queue *q, uint16_t num_desc,
1078 : : struct rte_bbdev_stats *queue_stats)
1079 : : {
1080 : : uint64_t start_time = 0;
1081 : 0 : queue_stats->acc_offload_cycles = 0;
1082 : :
1083 : : /* Update tail and shadow_tail register */
1084 : 0 : q->tail = fpga_5gnr_desc_idx_tail(q, num_desc);
1085 : :
1086 : : rte_wmb();
1087 : :
1088 : : /* Start time measurement for enqueue function offload. */
1089 : : start_time = rte_rdtsc_precise();
1090 : 0 : mmio_write_16(q->shadow_tail_addr, q->tail);
1091 : :
1092 : : rte_wmb();
1093 : 0 : queue_stats->acc_offload_cycles += rte_rdtsc_precise() - start_time;
1094 : : }
1095 : :
1096 : : /* Read flag value 0/1/ from bitmap */
1097 : : static inline bool
1098 : : check_bit(uint32_t bitmap, uint32_t bitmask)
1099 : : {
1100 : 0 : return bitmap & bitmask;
1101 : : }
1102 : :
1103 : : /* Vista Creek 5GNR FPGA descriptor errors.
1104 : : * Print an error if a descriptor error has occurred.
1105 : : * Return 0 on success, 1 on failure.
1106 : : */
1107 : : static inline int
1108 : 0 : vc_5gnr_check_desc_error(uint32_t error_code) {
1109 [ # # # # : 0 : switch (error_code) {
# # # # #
# # # # ]
1110 : : case VC_5GNR_DESC_ERR_NO_ERR:
1111 : : return 0;
1112 : 0 : case VC_5GNR_DESC_ERR_K_P_OUT_OF_RANGE:
1113 : 0 : rte_bbdev_log(ERR, "Encode block size K' is out of range");
1114 : 0 : break;
1115 : 0 : case VC_5GNR_DESC_ERR_Z_C_NOT_LEGAL:
1116 : 0 : rte_bbdev_log(ERR, "Zc is illegal");
1117 : 0 : break;
1118 : 0 : case VC_5GNR_DESC_ERR_DESC_OFFSET_ERR:
1119 : 0 : rte_bbdev_log(ERR,
1120 : : "Queue offset does not meet the expectation in the FPGA"
1121 : : );
1122 : 0 : break;
1123 : 0 : case VC_5GNR_DESC_ERR_DESC_READ_FAIL:
1124 : 0 : rte_bbdev_log(ERR, "Unsuccessful completion for descriptor read");
1125 : 0 : break;
1126 : 0 : case VC_5GNR_DESC_ERR_DESC_READ_TIMEOUT:
1127 : 0 : rte_bbdev_log(ERR, "Descriptor read time-out");
1128 : 0 : break;
1129 : 0 : case VC_5GNR_DESC_ERR_DESC_READ_TLP_POISONED:
1130 : 0 : rte_bbdev_log(ERR, "Descriptor read TLP poisoned");
1131 : 0 : break;
1132 : 0 : case VC_5GNR_DESC_ERR_HARQ_INPUT_LEN:
1133 : 0 : rte_bbdev_log(ERR, "HARQ input length is invalid");
1134 : 0 : break;
1135 : 0 : case VC_5GNR_DESC_ERR_CB_READ_FAIL:
1136 : 0 : rte_bbdev_log(ERR, "Unsuccessful completion for code block");
1137 : 0 : break;
1138 : 0 : case VC_5GNR_DESC_ERR_CB_READ_TIMEOUT:
1139 : 0 : rte_bbdev_log(ERR, "Code block read time-out");
1140 : 0 : break;
1141 : 0 : case VC_5GNR_DESC_ERR_CB_READ_TLP_POISONED:
1142 : 0 : rte_bbdev_log(ERR, "Code block read TLP poisoned");
1143 : 0 : break;
1144 : 0 : case VC_5GNR_DESC_ERR_HBSTORE_ERR:
1145 : 0 : rte_bbdev_log(ERR, "Hbstroe exceeds HARQ buffer size.");
1146 : 0 : break;
1147 : 0 : default:
1148 : 0 : rte_bbdev_log(ERR, "Descriptor error unknown error code %u", error_code);
1149 : 0 : break;
1150 : : }
1151 : : return 1;
1152 : : }
1153 : :
1154 : : /* AGX100 FPGA descriptor errors
1155 : : * Print an error if a descriptor error has occurred.
1156 : : * Return 0 on success, 1 on failure
1157 : : */
1158 : : static inline int
1159 : 0 : agx100_check_desc_error(uint32_t error_code, uint32_t error_msg) {
1160 : 0 : uint8_t error = error_code << 4 | error_msg;
1161 [ # # # # : 0 : switch (error) {
# # # # #
# # # # #
# # # ]
1162 : : case AGX100_DESC_ERR_NO_ERR:
1163 : : return 0;
1164 : 0 : case AGX100_DESC_ERR_E_NOT_LEGAL:
1165 : 0 : rte_bbdev_log(ERR, "Invalid output length of rate matcher E");
1166 : 0 : break;
1167 : 0 : case AGX100_DESC_ERR_K_P_OUT_OF_RANGE:
1168 : 0 : rte_bbdev_log(ERR, "Encode block size K' is out of range");
1169 : 0 : break;
1170 : 0 : case AGX100_DESC_ERR_NCB_OUT_OF_RANGE:
1171 : 0 : rte_bbdev_log(ERR, "Ncb circular buffer size is out of range");
1172 : 0 : break;
1173 : 0 : case AGX100_DESC_ERR_Z_C_NOT_LEGAL:
1174 : 0 : rte_bbdev_log(ERR, "Zc is illegal");
1175 : 0 : break;
1176 : 0 : case AGX100_DESC_ERR_DESC_INDEX_ERR:
1177 : 0 : rte_bbdev_log(ERR,
1178 : : "Desc_index received does not meet the expectation in the AGX100"
1179 : : );
1180 : 0 : break;
1181 : 0 : case AGX100_DESC_ERR_HARQ_INPUT_LEN_A:
1182 : 0 : rte_bbdev_log(ERR, "HARQ input length A is invalid.");
1183 : 0 : break;
1184 : 0 : case AGX100_DESC_ERR_HARQ_INPUT_LEN_B:
1185 : 0 : rte_bbdev_log(ERR, "HARQ input length B is invalid.");
1186 : 0 : break;
1187 : 0 : case AGX100_DESC_ERR_HBSTORE_OFFSET_ERR:
1188 : 0 : rte_bbdev_log(ERR, "Hbstore exceeds HARQ buffer size.");
1189 : 0 : break;
1190 : 0 : case AGX100_DESC_ERR_TB_CBG_ERR:
1191 : 0 : rte_bbdev_log(ERR, "Total CB number C=0 or CB number with Ea Ca=0 or Ca>C.");
1192 : 0 : break;
1193 : 0 : case AGX100_DESC_ERR_CBG_OUT_OF_RANGE:
1194 : 0 : rte_bbdev_log(ERR, "Cbgti or max_cbg is out of range");
1195 : 0 : break;
1196 : 0 : case AGX100_DESC_ERR_CW_RM_NOT_LEGAL:
1197 : 0 : rte_bbdev_log(ERR, "Cw_rm is illegal");
1198 : 0 : break;
1199 : 0 : case AGX100_DESC_ERR_UNSUPPORTED_REQ:
1200 : 0 : rte_bbdev_log(ERR, "Unsupported request for descriptor");
1201 : 0 : break;
1202 : 0 : case AGX100_DESC_ERR_RESERVED:
1203 : 0 : rte_bbdev_log(ERR, "Reserved");
1204 : 0 : break;
1205 : 0 : case AGX100_DESC_ERR_DESC_ABORT:
1206 : 0 : rte_bbdev_log(ERR, "Completed abort for descriptor");
1207 : 0 : break;
1208 : 0 : case AGX100_DESC_ERR_DESC_READ_TLP_POISONED:
1209 : 0 : rte_bbdev_log(ERR, "Descriptor read TLP poisoned");
1210 : 0 : break;
1211 : 0 : default:
1212 : 0 : rte_bbdev_log(ERR,
1213 : : "Descriptor error unknown error code %u error msg %u",
1214 : : error_code, error_msg);
1215 : 0 : break;
1216 : : }
1217 : : return 1;
1218 : : }
1219 : :
1220 : : /* Compute value of k0.
1221 : : * Based on 3GPP 38.212 Table 5.4.2.1-2
1222 : : * Starting position of different redundancy versions, k0
1223 : : */
1224 : : static inline uint16_t
1225 : 0 : get_k0(uint16_t n_cb, uint16_t z_c, uint8_t bg, uint8_t rv_index)
1226 : : {
1227 [ # # ]: 0 : uint16_t n = (bg == 1 ? N_ZC_1 : N_ZC_2) * z_c;
1228 [ # # ]: 0 : if (rv_index == 0)
1229 : : return 0;
1230 [ # # ]: 0 : if (z_c == 0)
1231 : : return 0;
1232 [ # # ]: 0 : if (n_cb == n) {
1233 [ # # ]: 0 : if (rv_index == 1)
1234 [ # # ]: 0 : return (bg == 1 ? K0_1_1 : K0_1_2) * z_c;
1235 [ # # ]: 0 : else if (rv_index == 2)
1236 [ # # ]: 0 : return (bg == 1 ? K0_2_1 : K0_2_2) * z_c;
1237 : : else
1238 [ # # ]: 0 : return (bg == 1 ? K0_3_1 : K0_3_2) * z_c;
1239 : : }
1240 : : /* LBRM case - includes a division by N */
1241 [ # # ]: 0 : if (rv_index == 1)
1242 [ # # ]: 0 : return (((bg == 1 ? K0_1_1 : K0_1_2) * n_cb)
1243 : 0 : / n) * z_c;
1244 [ # # ]: 0 : else if (rv_index == 2)
1245 [ # # ]: 0 : return (((bg == 1 ? K0_2_1 : K0_2_2) * n_cb)
1246 : 0 : / n) * z_c;
1247 : : else
1248 [ # # ]: 0 : return (((bg == 1 ? K0_3_1 : K0_3_2) * n_cb)
1249 : 0 : / n) * z_c;
1250 : : }
1251 : :
1252 : : /**
1253 : : * Vista Creek 5GNR FPGA
1254 : : * Set DMA descriptor for encode operation (1 Code Block)
1255 : : *
1256 : : * @param op
1257 : : * Pointer to a single encode operation.
1258 : : * @param desc
1259 : : * Pointer to DMA descriptor.
1260 : : * @param input
1261 : : * Pointer to pointer to input data which will be decoded.
1262 : : * @param e
1263 : : * E value (length of output in bits).
1264 : : * @param ncb
1265 : : * Ncb value (size of the soft buffer).
1266 : : * @param out_length
1267 : : * Length of output buffer
1268 : : * @param in_offset
1269 : : * Input offset in rte_mbuf structure. It is used for calculating the point
1270 : : * where data is starting.
1271 : : * @param out_offset
1272 : : * Output offset in rte_mbuf structure. It is used for calculating the point
1273 : : * where hard output data will be stored.
1274 : : * @param cbs_in_op
1275 : : * Number of CBs contained in one operation.
1276 : : */
1277 : : static inline int
1278 : 0 : vc_5gnr_dma_desc_te_fill(struct rte_bbdev_enc_op *op,
1279 : : struct vc_5gnr_dma_enc_desc *desc, struct rte_mbuf *input,
1280 : : struct rte_mbuf *output, uint16_t k_, uint16_t e,
1281 : : uint32_t in_offset, uint32_t out_offset, uint16_t desc_offset,
1282 : : uint8_t cbs_in_op)
1283 : : {
1284 : : /* reset */
1285 : 0 : desc->done = 0;
1286 : 0 : desc->error = 0;
1287 : 0 : desc->k_ = k_;
1288 : 0 : desc->rm_e = e;
1289 : 0 : desc->desc_idx = desc_offset;
1290 : 0 : desc->zc = op->ldpc_enc.z_c;
1291 : 0 : desc->bg_idx = op->ldpc_enc.basegraph - 1;
1292 : 0 : desc->qm_idx = op->ldpc_enc.q_m / 2;
1293 : 0 : desc->crc_en = check_bit(op->ldpc_enc.op_flags,
1294 : : RTE_BBDEV_LDPC_CRC_24B_ATTACH);
1295 : 0 : desc->irq_en = 0;
1296 : 0 : desc->k0 = get_k0(op->ldpc_enc.n_cb, op->ldpc_enc.z_c,
1297 : 0 : op->ldpc_enc.basegraph, op->ldpc_enc.rv_index);
1298 : 0 : desc->ncb = op->ldpc_enc.n_cb;
1299 : 0 : desc->num_null = op->ldpc_enc.n_filler;
1300 : : /* Set inbound data buffer address */
1301 : 0 : desc->in_addr_hi = (uint32_t)(
1302 : 0 : rte_pktmbuf_iova_offset(input, in_offset) >> 32);
1303 : 0 : desc->in_addr_lw = (uint32_t)(
1304 : 0 : rte_pktmbuf_iova_offset(input, in_offset));
1305 : :
1306 : 0 : desc->out_addr_hi = (uint32_t)(
1307 : 0 : rte_pktmbuf_iova_offset(output, out_offset) >> 32);
1308 : 0 : desc->out_addr_lw = (uint32_t)(
1309 : 0 : rte_pktmbuf_iova_offset(output, out_offset));
1310 : : /* Save software context needed for dequeue */
1311 : 0 : desc->op_addr = op;
1312 : : /* Set total number of CBs in an op */
1313 : 0 : desc->cbs_in_op = cbs_in_op;
1314 : 0 : return 0;
1315 : : }
1316 : :
1317 : : /**
1318 : : * AGX100 FPGA
1319 : : * Set DMA descriptor for encode operation (1 Code Block)
1320 : : *
1321 : : * @param op
1322 : : * Pointer to a single encode operation.
1323 : : * @param desc
1324 : : * Pointer to DMA descriptor.
1325 : : * @param input
1326 : : * Pointer to pointer to input data which will be decoded.
1327 : : * @param e
1328 : : * E value (length of output in bits).
1329 : : * @param ncb
1330 : : * Ncb value (size of the soft buffer).
1331 : : * @param out_length
1332 : : * Length of output buffer
1333 : : * @param in_offset
1334 : : * Input offset in rte_mbuf structure. It is used for calculating the point
1335 : : * where data is starting.
1336 : : * @param out_offset
1337 : : * Output offset in rte_mbuf structure. It is used for calculating the point
1338 : : * where hard output data will be stored.
1339 : : * @param cbs_in_op
1340 : : * Number of CBs contained in one operation.
1341 : : */
1342 : : static inline int
1343 : 0 : agx100_dma_desc_le_fill(struct rte_bbdev_enc_op *op,
1344 : : struct agx100_dma_enc_desc *desc, struct rte_mbuf *input,
1345 : : struct rte_mbuf *output, uint16_t k_, uint32_t e,
1346 : : uint32_t in_offset, uint32_t out_offset, uint16_t desc_offset,
1347 : : uint8_t cbs_in_op)
1348 : : {
1349 : : /* reset. */
1350 : 0 : desc->done = 0;
1351 : 0 : desc->error_msg = 0;
1352 : 0 : desc->error_code = 0;
1353 : 0 : desc->ncb = op->ldpc_enc.n_cb;
1354 : 0 : desc->bg_idx = op->ldpc_enc.basegraph - 1;
1355 : 0 : desc->qm_idx = op->ldpc_enc.q_m >> 1;
1356 : 0 : desc->zc = op->ldpc_enc.z_c;
1357 : 0 : desc->rv = op->ldpc_enc.rv_index;
1358 : 0 : desc->int_en = 0; /**< Set by device externally. */
1359 : 0 : desc->max_cbg = 0; /**< TODO: CBG specific. */
1360 : 0 : desc->cbgti = 0; /**< TODO: CBG specific. */
1361 : 0 : desc->cbgs = 0; /**< TODO: CBG specific. */
1362 : 0 : desc->desc_idx = desc_offset;
1363 : 0 : desc->ca = 0; /**< TODO: CBG specific. */
1364 : 0 : desc->c = 0; /**< TODO: CBG specific. */
1365 : 0 : desc->num_null = op->ldpc_enc.n_filler;
1366 : 0 : desc->ea = e;
1367 : 0 : desc->eb = e; /**< TODO: TB/CBG specific. */
1368 : 0 : desc->k_ = k_;
1369 : 0 : desc->en_slice_ts = 0; /**< TODO: Slice specific. */
1370 : 0 : desc->en_host_ts = 0; /**< TODO: Slice specific. */
1371 : 0 : desc->en_cb_wr_status = 0; /**< TODO: Event Queue specific. */
1372 : 0 : desc->en_output_sg = 0; /**< TODO: Slice specific. */
1373 : 0 : desc->en_input_sg = 0; /**< TODO: Slice specific. */
1374 : 0 : desc->tb_cb = 0; /**< Descriptor for CB. TODO: Add TB and CBG logic. */
1375 : 0 : desc->crc_en = check_bit(op->ldpc_enc.op_flags,
1376 : : RTE_BBDEV_LDPC_CRC_24B_ATTACH);
1377 : :
1378 : : /* Set inbound/outbound data buffer address. */
1379 : : /* TODO: add logic for input_slice. */
1380 : 0 : desc->output_start_addr_hi = (uint32_t)(
1381 : 0 : rte_pktmbuf_iova_offset(output, out_offset) >> 32);
1382 : 0 : desc->output_start_addr_lo = (uint32_t)(
1383 : 0 : rte_pktmbuf_iova_offset(output, out_offset));
1384 : 0 : desc->input_start_addr_hi = (uint32_t)(
1385 : 0 : rte_pktmbuf_iova_offset(input, in_offset) >> 32);
1386 : 0 : desc->input_start_addr_lo = (uint32_t)(
1387 : 0 : rte_pktmbuf_iova_offset(input, in_offset));
1388 : 0 : desc->output_length = (e + 7) >> 3; /* in bytes. */
1389 : 0 : desc->input_length = input->data_len;
1390 : 0 : desc->enqueue_timestamp = 0;
1391 : 0 : desc->completion_timestamp = 0;
1392 : : /* Save software context needed for dequeue. */
1393 : 0 : desc->op_addr = op;
1394 : : /* Set total number of CBs in an op. */
1395 : 0 : desc->cbs_in_op = cbs_in_op;
1396 : 0 : return 0;
1397 : : }
1398 : :
1399 : : /**
1400 : : * Vista Creek 5GNR FPGA
1401 : : * Set DMA descriptor for decode operation (1 Code Block)
1402 : : *
1403 : : * @param op
1404 : : * Pointer to a single encode operation.
1405 : : * @param desc
1406 : : * Pointer to DMA descriptor.
1407 : : * @param input
1408 : : * Pointer to pointer to input data which will be decoded.
1409 : : * @param in_offset
1410 : : * Input offset in rte_mbuf structure. It is used for calculating the point
1411 : : * where data is starting.
1412 : : * @param out_offset
1413 : : * Output offset in rte_mbuf structure. It is used for calculating the point
1414 : : * where hard output data will be stored.
1415 : : * @param cbs_in_op
1416 : : * Number of CBs contained in one operation.
1417 : : */
1418 : : static inline int
1419 : 0 : vc_5gnr_dma_desc_ld_fill(struct rte_bbdev_dec_op *op,
1420 : : struct vc_5gnr_dma_dec_desc *desc,
1421 : : struct rte_mbuf *input, struct rte_mbuf *output,
1422 : : uint16_t harq_in_length,
1423 : : uint32_t in_offset, uint32_t out_offset,
1424 : : uint32_t harq_offset,
1425 : : uint16_t desc_offset,
1426 : : uint8_t cbs_in_op)
1427 : : {
1428 : : /* reset */
1429 : 0 : desc->done = 0;
1430 : 0 : desc->error = 0;
1431 : : /* Set inbound data buffer address */
1432 : 0 : desc->in_addr_hi = (uint32_t)(
1433 : 0 : rte_pktmbuf_iova_offset(input, in_offset) >> 32);
1434 : 0 : desc->in_addr_lw = (uint32_t)(
1435 : 0 : rte_pktmbuf_iova_offset(input, in_offset));
1436 : 0 : desc->rm_e = op->ldpc_dec.cb_params.e;
1437 : 0 : desc->harq_input_length = harq_in_length;
1438 : 0 : desc->et_dis = !check_bit(op->ldpc_dec.op_flags,
1439 : : RTE_BBDEV_LDPC_ITERATION_STOP_ENABLE);
1440 : 0 : desc->rv = op->ldpc_dec.rv_index;
1441 : 0 : desc->crc24b_ind = check_bit(op->ldpc_dec.op_flags,
1442 : : RTE_BBDEV_LDPC_CRC_TYPE_24B_CHECK);
1443 : 0 : desc->drop_crc24b = check_bit(op->ldpc_dec.op_flags,
1444 : : RTE_BBDEV_LDPC_CRC_TYPE_24B_DROP);
1445 : 0 : desc->desc_idx = desc_offset;
1446 : 0 : desc->ncb = op->ldpc_dec.n_cb;
1447 : 0 : desc->num_null = op->ldpc_dec.n_filler;
1448 : 0 : desc->hbstroe_offset = harq_offset >> 10;
1449 : 0 : desc->zc = op->ldpc_dec.z_c;
1450 : 0 : desc->harqin_en = check_bit(op->ldpc_dec.op_flags,
1451 : : RTE_BBDEV_LDPC_HQ_COMBINE_IN_ENABLE);
1452 : 0 : desc->bg_idx = op->ldpc_dec.basegraph - 1;
1453 : 0 : desc->max_iter = op->ldpc_dec.iter_max;
1454 : 0 : desc->qm_idx = op->ldpc_dec.q_m / 2;
1455 : 0 : desc->out_addr_hi = (uint32_t)(
1456 : 0 : rte_pktmbuf_iova_offset(output, out_offset) >> 32);
1457 : 0 : desc->out_addr_lw = (uint32_t)(
1458 : 0 : rte_pktmbuf_iova_offset(output, out_offset));
1459 : : /* Save software context needed for dequeue */
1460 : 0 : desc->op_addr = op;
1461 : : /* Set total number of CBs in an op */
1462 : 0 : desc->cbs_in_op = cbs_in_op;
1463 : :
1464 : 0 : return 0;
1465 : : }
1466 : :
1467 : : /**
1468 : : * AGX100 FPGA
1469 : : * Set DMA descriptor for decode operation (1 Code Block)
1470 : : *
1471 : : * @param op
1472 : : * Pointer to a single encode operation.
1473 : : * @param desc
1474 : : * Pointer to DMA descriptor.
1475 : : * @param input
1476 : : * Pointer to pointer to input data which will be decoded.
1477 : : * @param in_offset
1478 : : * Input offset in rte_mbuf structure. It is used for calculating the point
1479 : : * where data is starting.
1480 : : * @param out_offset
1481 : : * Output offset in rte_mbuf structure. It is used for calculating the point
1482 : : * where hard output data will be stored.
1483 : : * @param cbs_in_op
1484 : : * Number of CBs contained in one operation.
1485 : : */
1486 : : static inline int
1487 : 0 : agx100_dma_desc_ld_fill(struct rte_bbdev_dec_op *op,
1488 : : struct agx100_dma_dec_desc *desc,
1489 : : struct rte_mbuf *input, struct rte_mbuf *output,
1490 : : uint16_t harq_in_length,
1491 : : uint32_t in_offset, uint32_t out_offset,
1492 : : uint32_t harq_in_offset,
1493 : : uint32_t harq_out_offset,
1494 : : uint16_t desc_offset,
1495 : : uint8_t cbs_in_op)
1496 : : {
1497 : : /* reset. */
1498 : 0 : desc->done = 0;
1499 : 0 : desc->tb_crc_pass = 0;
1500 : 0 : desc->cb_crc_all_pass = 0;
1501 : 0 : desc->cb_all_et_pass = 0;
1502 : 0 : desc->max_iter_ret = 0;
1503 : 0 : desc->cgb_crc_bitmap = 0; /**< TODO: CBG specific. */
1504 : 0 : desc->error_msg = 0;
1505 : 0 : desc->error_code = 0;
1506 : 0 : desc->et_dis = !check_bit(op->ldpc_dec.op_flags,
1507 : : RTE_BBDEV_LDPC_ITERATION_STOP_ENABLE);
1508 : 0 : desc->harq_in_en = check_bit(op->ldpc_dec.op_flags,
1509 : : RTE_BBDEV_LDPC_HQ_COMBINE_IN_ENABLE);
1510 : 0 : desc->max_iter = op->ldpc_dec.iter_max;
1511 : 0 : desc->ncb = op->ldpc_dec.n_cb;
1512 : 0 : desc->bg_idx = op->ldpc_dec.basegraph - 1;
1513 : 0 : desc->qm_idx = op->ldpc_dec.q_m >> 1;
1514 : 0 : desc->zc = op->ldpc_dec.z_c;
1515 : 0 : desc->rv = op->ldpc_dec.rv_index;
1516 : 0 : desc->int_en = 0; /**< Set by device externally. */
1517 : 0 : desc->max_cbg = 0; /**< TODO: CBG specific. */
1518 : 0 : desc->cbgti = 0; /**< TODO: CBG specific. */
1519 : 0 : desc->cbgfi = 0; /**< TODO: CBG specific. */
1520 : 0 : desc->cbgs = 0; /**< TODO: CBG specific. */
1521 : 0 : desc->desc_idx = desc_offset;
1522 : 0 : desc->ca = 0; /**< TODO: CBG specific. */
1523 : 0 : desc->c = 0; /**< TODO: CBG specific. */
1524 : 0 : desc->llr_pckg = 0; /**< TODO: Not implemented yet. */
1525 : 0 : desc->syndrome_check_mode = 1; /**< TODO: Make it configurable. */
1526 : 0 : desc->num_null = op->ldpc_dec.n_filler;
1527 : 0 : desc->ea = op->ldpc_dec.cb_params.e; /**< TODO: TB/CBG specific. */
1528 : 0 : desc->eba = 0; /**< TODO: TB/CBG specific. */
1529 : 0 : desc->hbstore_offset_out = harq_out_offset >> 10;
1530 : 0 : desc->hbstore_offset_in = harq_in_offset >> 10;
1531 : 0 : desc->en_slice_ts = 0; /**< TODO: Slice specific. */
1532 : 0 : desc->en_host_ts = 0; /**< TODO: Slice specific. */
1533 : 0 : desc->en_cb_wr_status = 0; /**< TODO: Event Queue specific. */
1534 : 0 : desc->en_output_sg = 0; /**< TODO: Slice specific. */
1535 : 0 : desc->en_input_sg = 0; /**< TODO: Slice specific. */
1536 : 0 : desc->tb_cb = 0; /**< Descriptor for CB. TODO: Add TB and CBG logic. */
1537 : 0 : desc->crc24b_ind = check_bit(op->ldpc_dec.op_flags,
1538 : : RTE_BBDEV_LDPC_CRC_TYPE_24B_CHECK);
1539 : 0 : desc->drop_crc24b = check_bit(op->ldpc_dec.op_flags,
1540 : : RTE_BBDEV_LDPC_CRC_TYPE_24B_DROP);
1541 : 0 : desc->harq_input_length_a =
1542 : : harq_in_length; /**< Descriptor for CB. TODO: Add TB and CBG logic. */
1543 [ # # ]: 0 : desc->harq_input_length_b = 0; /**< Descriptor for CB. TODO: Add TB and CBG logic. */
1544 : : /* Set inbound/outbound data buffer address. */
1545 : : /* TODO: add logic for input_slice. */
1546 : 0 : desc->output_start_addr_hi = (uint32_t)(
1547 : 0 : rte_pktmbuf_iova_offset(output, out_offset) >> 32);
1548 : 0 : desc->output_start_addr_lo = (uint32_t)(
1549 : 0 : rte_pktmbuf_iova_offset(output, out_offset));
1550 : 0 : desc->input_start_addr_hi = (uint32_t)(
1551 : 0 : rte_pktmbuf_iova_offset(input, in_offset) >> 32);
1552 : 0 : desc->input_start_addr_lo = (uint32_t)(
1553 : 0 : rte_pktmbuf_iova_offset(input, in_offset));
1554 [ # # ]: 0 : desc->output_length = (((op->ldpc_dec.basegraph == 1) ? 22 : 10) * op->ldpc_dec.z_c
1555 : 0 : - op->ldpc_dec.n_filler - desc->drop_crc24b * 24) >> 3;
1556 : 0 : desc->input_length = op->ldpc_dec.cb_params.e; /**< TODO: TB/CBG specific. */
1557 : 0 : desc->enqueue_timestamp = 0;
1558 : 0 : desc->completion_timestamp = 0;
1559 : : /* Save software context needed for dequeue. */
1560 : 0 : desc->op_addr = op;
1561 : : /* Set total number of CBs in an op. */
1562 : 0 : desc->cbs_in_op = cbs_in_op;
1563 : 0 : return 0;
1564 : : }
1565 : :
1566 : : /* Validates LDPC encoder parameters for VC 5GNR FPGA. */
1567 : : static inline int
1568 : 0 : vc_5gnr_validate_ldpc_enc_op(struct rte_bbdev_enc_op *op)
1569 : : {
1570 : : struct rte_bbdev_op_ldpc_enc *ldpc_enc = &op->ldpc_enc;
1571 : : int z_c, n_filler, K, Kp, q_m, n_cb, N, k0, crc24;
1572 : : int32_t L, Lcb, cw, cw_rm, e;
1573 : :
1574 [ # # ]: 0 : if (ldpc_enc->input.data == NULL) {
1575 : 0 : rte_bbdev_log(ERR, "Invalid input pointer");
1576 : 0 : return -1;
1577 : : }
1578 [ # # ]: 0 : if (ldpc_enc->output.data == NULL) {
1579 : 0 : rte_bbdev_log(ERR, "Invalid output pointer");
1580 : 0 : return -1;
1581 : : }
1582 [ # # ]: 0 : if (ldpc_enc->input.length == 0) {
1583 : 0 : rte_bbdev_log(ERR, "CB size (%u) is null",
1584 : : ldpc_enc->input.length);
1585 : 0 : return -1;
1586 : : }
1587 [ # # ]: 0 : if ((ldpc_enc->basegraph > 2) || (ldpc_enc->basegraph == 0)) {
1588 : 0 : rte_bbdev_log(ERR,
1589 : : "BG (%u) is out of range 1 <= value <= 2",
1590 : : ldpc_enc->basegraph);
1591 : 0 : return -1;
1592 : : }
1593 [ # # ]: 0 : if (ldpc_enc->rv_index > 3) {
1594 : 0 : rte_bbdev_log(ERR,
1595 : : "rv_index (%u) is out of range 0 <= value <= 3",
1596 : : ldpc_enc->rv_index);
1597 : 0 : return -1;
1598 : : }
1599 [ # # ]: 0 : if (ldpc_enc->code_block_mode > RTE_BBDEV_CODE_BLOCK) {
1600 : 0 : rte_bbdev_log(ERR,
1601 : : "code_block_mode (%u) is out of range 0 <= value <= 1",
1602 : : ldpc_enc->code_block_mode);
1603 : 0 : return -1;
1604 : : }
1605 : :
1606 [ # # ]: 0 : if (ldpc_enc->input.length >
1607 : : RTE_BBDEV_LDPC_MAX_CB_SIZE >> 3) {
1608 : 0 : rte_bbdev_log(ERR, "CB size (%u) is too big, max: %d",
1609 : : ldpc_enc->input.length,
1610 : : RTE_BBDEV_LDPC_MAX_CB_SIZE);
1611 : 0 : return -1;
1612 : : }
1613 : :
1614 : 0 : z_c = ldpc_enc->z_c;
1615 : : /* Check Zc is valid value */
1616 [ # # ]: 0 : if ((z_c > 384) || (z_c < 4)) {
1617 : 0 : rte_bbdev_log(ERR, "Zc (%u) is out of range", z_c);
1618 : 0 : return -1;
1619 : : }
1620 [ # # ]: 0 : if (z_c > 256) {
1621 [ # # ]: 0 : if ((z_c % 32) != 0) {
1622 : 0 : rte_bbdev_log(ERR, "Invalid Zc %d", z_c);
1623 : 0 : return -1;
1624 : : }
1625 [ # # ]: 0 : } else if (z_c > 128) {
1626 [ # # ]: 0 : if ((z_c % 16) != 0) {
1627 : 0 : rte_bbdev_log(ERR, "Invalid Zc %d", z_c);
1628 : 0 : return -1;
1629 : : }
1630 [ # # ]: 0 : } else if (z_c > 64) {
1631 [ # # ]: 0 : if ((z_c % 8) != 0) {
1632 : 0 : rte_bbdev_log(ERR, "Invalid Zc %d", z_c);
1633 : 0 : return -1;
1634 : : }
1635 [ # # ]: 0 : } else if (z_c > 32) {
1636 [ # # ]: 0 : if ((z_c % 4) != 0) {
1637 : 0 : rte_bbdev_log(ERR, "Invalid Zc %d", z_c);
1638 : 0 : return -1;
1639 : : }
1640 [ # # ]: 0 : } else if (z_c > 16) {
1641 [ # # ]: 0 : if ((z_c % 2) != 0) {
1642 : 0 : rte_bbdev_log(ERR, "Invalid Zc %d", z_c);
1643 : 0 : return -1;
1644 : : }
1645 : : }
1646 : :
1647 : 0 : n_filler = ldpc_enc->n_filler;
1648 [ # # ]: 0 : K = (ldpc_enc->basegraph == 1 ? 22 : 10) * ldpc_enc->z_c;
1649 : 0 : Kp = K - n_filler;
1650 : 0 : q_m = ldpc_enc->q_m;
1651 : 0 : n_cb = ldpc_enc->n_cb;
1652 [ # # ]: 0 : N = (ldpc_enc->basegraph == 1 ? N_ZC_1 : N_ZC_2) * z_c;
1653 : 0 : k0 = get_k0(n_cb, z_c, ldpc_enc->basegraph, ldpc_enc->rv_index);
1654 : : crc24 = 0;
1655 : 0 : e = ldpc_enc->cb_params.e;
1656 : :
1657 [ # # ]: 0 : if (check_bit(op->ldpc_enc.op_flags, RTE_BBDEV_LDPC_CRC_24B_ATTACH))
1658 : : crc24 = 24;
1659 : :
1660 [ # # ]: 0 : if (K < (int) (ldpc_enc->input.length * 8 + n_filler) + crc24) {
1661 : 0 : rte_bbdev_log(ERR, "K and F not matching input size %u %u %u",
1662 : : K, n_filler, ldpc_enc->input.length);
1663 : 0 : return -1;
1664 : : }
1665 [ # # ]: 0 : if (ldpc_enc->code_block_mode == RTE_BBDEV_TRANSPORT_BLOCK) {
1666 : 0 : rte_bbdev_log(ERR, "TB mode not supported");
1667 : 0 : return -1;
1668 : :
1669 : : }
1670 : :
1671 : : /* K' range check */
1672 [ # # ]: 0 : if (Kp % 8 > 0) {
1673 : 0 : rte_bbdev_log(ERR, "K' not byte aligned %u", Kp);
1674 : 0 : return -1;
1675 : : }
1676 [ # # ]: 0 : if ((crc24 > 0) && (Kp < 292)) {
1677 : 0 : rte_bbdev_log(ERR, "Invalid CRC24 for small block %u", Kp);
1678 : 0 : return -1;
1679 : : }
1680 [ # # ]: 0 : if (Kp < 24) {
1681 : 0 : rte_bbdev_log(ERR, "K' too small %u", Kp);
1682 : 0 : return -1;
1683 : : }
1684 [ # # ]: 0 : if (n_filler >= (K - 2 * z_c)) {
1685 : 0 : rte_bbdev_log(ERR, "K - F invalid %u %u", K, n_filler);
1686 : 0 : return -1;
1687 : : }
1688 : : /* Ncb range check */
1689 [ # # # # ]: 0 : if ((n_cb > N) || (n_cb < 32) || (n_cb <= (Kp - crc24))) {
1690 : 0 : rte_bbdev_log(ERR, "Ncb (%u) is out of range K %d N %d", n_cb, K, N);
1691 : 0 : return -1;
1692 : : }
1693 : : /* Qm range check */
1694 [ # # # # ]: 0 : if (!check_bit(op->ldpc_enc.op_flags, RTE_BBDEV_LDPC_INTERLEAVER_BYPASS) &&
1695 [ # # # # : 0 : ((q_m == 0) || ((q_m > 2) && ((q_m % 2) == 1)) || (q_m > 8))) {
# # ]
1696 : 0 : rte_bbdev_log(ERR, "Qm (%u) is out of range", q_m);
1697 : 0 : return -1;
1698 : : }
1699 : : /* K0 range check */
1700 [ # # # # : 0 : if (((k0 % z_c) > 0) || (k0 >= n_cb) || ((k0 >= (Kp - 2 * z_c)) && (k0 < (K - 2 * z_c)))) {
# # # # ]
1701 : 0 : rte_bbdev_log(ERR, "K0 (%u) is out of range", k0);
1702 : 0 : return -1;
1703 : : }
1704 : : /* E range check */
1705 [ # # ]: 0 : if (e <= RTE_MAX(32, z_c)) {
1706 : 0 : rte_bbdev_log(ERR, "E is too small %"PRIu32"", e);
1707 : 0 : return -1;
1708 : : }
1709 [ # # ]: 0 : if ((e > 0xFFFF)) {
1710 : 0 : rte_bbdev_log(ERR, "E is too large for N3000 %"PRIu32" > 64k", e);
1711 : 0 : return -1;
1712 : : }
1713 [ # # ]: 0 : if (q_m > 0) {
1714 [ # # ]: 0 : if (e % q_m > 0) {
1715 : 0 : rte_bbdev_log(ERR, "E %"PRIu32" not multiple of qm %d", e, q_m);
1716 : 0 : return -1;
1717 : : }
1718 : : }
1719 : : /* Code word in RM range check */
1720 [ # # ]: 0 : if (k0 > (Kp - 2 * z_c))
1721 : 0 : L = k0 + e;
1722 : : else
1723 : 0 : L = k0 + e + n_filler;
1724 : 0 : Lcb = RTE_MIN(L, n_cb);
1725 [ # # ]: 0 : if (ldpc_enc->basegraph == 1) {
1726 [ # # ]: 0 : if (Lcb <= 25 * z_c)
1727 : : cw = 25 * z_c;
1728 [ # # ]: 0 : else if (Lcb <= 27 * z_c)
1729 : : cw = 27 * z_c;
1730 [ # # ]: 0 : else if (Lcb <= 30 * z_c)
1731 : : cw = 30 * z_c;
1732 [ # # ]: 0 : else if (Lcb <= 33 * z_c)
1733 : : cw = 33 * z_c;
1734 [ # # ]: 0 : else if (Lcb <= 44 * z_c)
1735 : : cw = 44 * z_c;
1736 [ # # ]: 0 : else if (Lcb <= 55 * z_c)
1737 : : cw = 55 * z_c;
1738 : : else
1739 : 0 : cw = 66 * z_c;
1740 : : } else {
1741 [ # # ]: 0 : if (Lcb <= 15 * z_c)
1742 : : cw = 15 * z_c;
1743 [ # # ]: 0 : else if (Lcb <= 20 * z_c)
1744 : : cw = 20 * z_c;
1745 [ # # ]: 0 : else if (Lcb <= 25 * z_c)
1746 : : cw = 25 * z_c;
1747 [ # # ]: 0 : else if (Lcb <= 30 * z_c)
1748 : : cw = 30 * z_c;
1749 : : else
1750 : 0 : cw = 50 * z_c;
1751 : : }
1752 [ # # ]: 0 : if (n_cb < Kp - 2 * z_c)
1753 : : cw_rm = n_cb;
1754 [ # # ]: 0 : else if ((Kp - 2 * z_c <= n_cb) && (n_cb < K - 2 * z_c))
1755 : : cw_rm = Kp - 2 * z_c;
1756 [ # # # # ]: 0 : else if ((K - 2 * z_c <= n_cb) && (n_cb < cw))
1757 : 0 : cw_rm = n_cb - n_filler;
1758 : : else
1759 : 0 : cw_rm = cw - n_filler;
1760 [ # # ]: 0 : if (cw_rm <= 32) {
1761 : 0 : rte_bbdev_log(ERR, "Invalid Ratematching");
1762 : 0 : return -1;
1763 : : }
1764 : : return 0;
1765 : : }
1766 : :
1767 : : /* Validates LDPC decoder parameters for VC 5GNR FPGA. */
1768 : : static inline int
1769 : 0 : vc_5gnr_validate_ldpc_dec_op(struct rte_bbdev_dec_op *op)
1770 : : {
1771 : : struct rte_bbdev_op_ldpc_dec *ldpc_dec = &op->ldpc_dec;
1772 : : int z_c, n_filler, K, Kp, q_m, n_cb, N, k0, crc24;
1773 : : int32_t L, Lcb, cw, cw_rm, e;
1774 : :
1775 [ # # ]: 0 : if (check_bit(ldpc_dec->op_flags, RTE_BBDEV_LDPC_INTERNAL_HARQ_MEMORY_LOOPBACK))
1776 : : return 0;
1777 [ # # ]: 0 : if (ldpc_dec->input.data == NULL) {
1778 : 0 : rte_bbdev_log(ERR, "Invalid input pointer");
1779 : 0 : return -1;
1780 : : }
1781 [ # # ]: 0 : if (ldpc_dec->hard_output.data == NULL) {
1782 : 0 : rte_bbdev_log(ERR, "Invalid output pointer");
1783 : 0 : return -1;
1784 : : }
1785 [ # # ]: 0 : if (ldpc_dec->input.length == 0) {
1786 : 0 : rte_bbdev_log(ERR, "input is null");
1787 : 0 : return -1;
1788 : : }
1789 [ # # ]: 0 : if ((ldpc_dec->basegraph > 2) || (ldpc_dec->basegraph == 0)) {
1790 : 0 : rte_bbdev_log(ERR,
1791 : : "BG (%u) is out of range 1 <= value <= 2",
1792 : : ldpc_dec->basegraph);
1793 : 0 : return -1;
1794 : : }
1795 [ # # ]: 0 : if (ldpc_dec->iter_max == 0) {
1796 : 0 : rte_bbdev_log(ERR,
1797 : : "iter_max (%u) is equal to 0",
1798 : : ldpc_dec->iter_max);
1799 : 0 : return -1;
1800 : : }
1801 [ # # ]: 0 : if (ldpc_dec->rv_index > 3) {
1802 : 0 : rte_bbdev_log(ERR,
1803 : : "rv_index (%u) is out of range 0 <= value <= 3",
1804 : : ldpc_dec->rv_index);
1805 : 0 : return -1;
1806 : : }
1807 [ # # ]: 0 : if (ldpc_dec->code_block_mode > RTE_BBDEV_CODE_BLOCK) {
1808 : 0 : rte_bbdev_log(ERR,
1809 : : "code_block_mode (%u) is out of range 0 <= value <= 1",
1810 : : ldpc_dec->code_block_mode);
1811 : 0 : return -1;
1812 : : }
1813 [ # # ]: 0 : if (check_bit(op->ldpc_dec.op_flags, RTE_BBDEV_LDPC_DECODE_BYPASS)) {
1814 : 0 : rte_bbdev_log(ERR, "Avoid LDPC Decode bypass");
1815 : 0 : return -1;
1816 : : }
1817 : :
1818 : 0 : z_c = ldpc_dec->z_c;
1819 : : /* Check Zc is valid value */
1820 [ # # ]: 0 : if ((z_c > 384) || (z_c < 4)) {
1821 : 0 : rte_bbdev_log(ERR, "Zc (%u) is out of range", z_c);
1822 : 0 : return -1;
1823 : : }
1824 [ # # ]: 0 : if (z_c > 256) {
1825 [ # # ]: 0 : if ((z_c % 32) != 0) {
1826 : 0 : rte_bbdev_log(ERR, "Invalid Zc %d", z_c);
1827 : 0 : return -1;
1828 : : }
1829 [ # # ]: 0 : } else if (z_c > 128) {
1830 [ # # ]: 0 : if ((z_c % 16) != 0) {
1831 : 0 : rte_bbdev_log(ERR, "Invalid Zc %d", z_c);
1832 : 0 : return -1;
1833 : : }
1834 [ # # ]: 0 : } else if (z_c > 64) {
1835 [ # # ]: 0 : if ((z_c % 8) != 0) {
1836 : 0 : rte_bbdev_log(ERR, "Invalid Zc %d", z_c);
1837 : 0 : return -1;
1838 : : }
1839 [ # # ]: 0 : } else if (z_c > 32) {
1840 [ # # ]: 0 : if ((z_c % 4) != 0) {
1841 : 0 : rte_bbdev_log(ERR, "Invalid Zc %d", z_c);
1842 : 0 : return -1;
1843 : : }
1844 [ # # ]: 0 : } else if (z_c > 16) {
1845 [ # # ]: 0 : if ((z_c % 2) != 0) {
1846 : 0 : rte_bbdev_log(ERR, "Invalid Zc %d", z_c);
1847 : 0 : return -1;
1848 : : }
1849 : : }
1850 : :
1851 : 0 : n_filler = ldpc_dec->n_filler;
1852 [ # # ]: 0 : K = (ldpc_dec->basegraph == 1 ? 22 : 10) * ldpc_dec->z_c;
1853 : 0 : Kp = K - n_filler;
1854 : 0 : q_m = ldpc_dec->q_m;
1855 : 0 : n_cb = ldpc_dec->n_cb;
1856 [ # # ]: 0 : N = (ldpc_dec->basegraph == 1 ? N_ZC_1 : N_ZC_2) * z_c;
1857 : 0 : k0 = get_k0(n_cb, z_c, ldpc_dec->basegraph, ldpc_dec->rv_index);
1858 : : crc24 = 0;
1859 : 0 : e = ldpc_dec->cb_params.e;
1860 : :
1861 [ # # ]: 0 : if (check_bit(op->ldpc_dec.op_flags, RTE_BBDEV_LDPC_CRC_TYPE_24B_CHECK))
1862 : : crc24 = 24;
1863 : :
1864 [ # # ]: 0 : if (ldpc_dec->code_block_mode == RTE_BBDEV_TRANSPORT_BLOCK) {
1865 : 0 : rte_bbdev_log(ERR, "TB mode not supported");
1866 : 0 : return -1;
1867 : : }
1868 : : /* Enforce HARQ input length */
1869 : 0 : ldpc_dec->harq_combined_input.length = RTE_MIN((uint32_t) n_cb,
1870 : : ldpc_dec->harq_combined_input.length);
1871 [ # # # # ]: 0 : if ((ldpc_dec->harq_combined_input.length == 0) &&
1872 : : check_bit(ldpc_dec->op_flags,
1873 : : RTE_BBDEV_LDPC_HQ_COMBINE_IN_ENABLE)) {
1874 : 0 : rte_bbdev_log(ERR,
1875 : : "HARQ input length (%u) should not be null",
1876 : : ldpc_dec->harq_combined_input.length);
1877 : 0 : return -1;
1878 : : }
1879 [ # # # # ]: 0 : if ((ldpc_dec->harq_combined_input.length > 0) &&
1880 : : !check_bit(ldpc_dec->op_flags,
1881 : : RTE_BBDEV_LDPC_HQ_COMBINE_IN_ENABLE)) {
1882 : 0 : ldpc_dec->harq_combined_input.length = 0;
1883 : : }
1884 : :
1885 : : /* K' range check */
1886 [ # # ]: 0 : if (Kp % 8 > 0) {
1887 : 0 : rte_bbdev_log(ERR, "K' not byte aligned %u", Kp);
1888 : 0 : return -1;
1889 : : }
1890 [ # # ]: 0 : if ((crc24 > 0) && (Kp < 292)) {
1891 : 0 : rte_bbdev_log(ERR, "Invalid CRC24 for small block %u", Kp);
1892 : 0 : return -1;
1893 : : }
1894 [ # # ]: 0 : if (Kp < 24) {
1895 : 0 : rte_bbdev_log(ERR, "K' too small %u", Kp);
1896 : 0 : return -1;
1897 : : }
1898 [ # # ]: 0 : if (n_filler >= (K - 2 * z_c)) {
1899 : 0 : rte_bbdev_log(ERR, "K - F invalid %u %u", K, n_filler);
1900 : 0 : return -1;
1901 : : }
1902 : : /* Ncb range check */
1903 [ # # ]: 0 : if (n_cb != N) {
1904 : 0 : rte_bbdev_log(ERR, "Ncb (%u) is out of range K %d N %d", n_cb, K, N);
1905 : 0 : return -1;
1906 : : }
1907 : : /* Qm range check */
1908 [ # # ]: 0 : if (!check_bit(op->ldpc_dec.op_flags,
1909 [ # # ]: 0 : RTE_BBDEV_LDPC_INTERLEAVER_BYPASS) &&
1910 [ # # # # ]: 0 : ((q_m == 0) || ((q_m > 2) && ((q_m % 2) == 1))
1911 [ # # ]: 0 : || (q_m > 8))) {
1912 : 0 : rte_bbdev_log(ERR, "Qm (%u) is out of range", q_m);
1913 : 0 : return -1;
1914 : : }
1915 : : /* K0 range check */
1916 [ # # # # : 0 : if (((k0 % z_c) > 0) || (k0 >= n_cb) || ((k0 >= (Kp - 2 * z_c)) && (k0 < (K - 2 * z_c)))) {
# # # # ]
1917 : 0 : rte_bbdev_log(ERR, "K0 (%u) is out of range", k0);
1918 : 0 : return -1;
1919 : : }
1920 : : /* E range check */
1921 [ # # ]: 0 : if (e <= RTE_MAX(32, z_c)) {
1922 : 0 : rte_bbdev_log(ERR, "E is too small");
1923 : 0 : return -1;
1924 : : }
1925 [ # # ]: 0 : if ((e > 0xFFFF)) {
1926 : 0 : rte_bbdev_log(ERR, "E is too large");
1927 : 0 : return -1;
1928 : : }
1929 [ # # ]: 0 : if (q_m > 0) {
1930 [ # # ]: 0 : if (e % q_m > 0) {
1931 : 0 : rte_bbdev_log(ERR, "E not multiple of qm %d", q_m);
1932 : 0 : return -1;
1933 : : }
1934 : : }
1935 : : /* Code word in RM range check */
1936 [ # # ]: 0 : if (k0 > (Kp - 2 * z_c))
1937 : 0 : L = k0 + e;
1938 : : else
1939 : 0 : L = k0 + e + n_filler;
1940 : :
1941 : 0 : Lcb = RTE_MIN(n_cb, RTE_MAX(L, (int32_t) ldpc_dec->harq_combined_input.length));
1942 [ # # ]: 0 : if (ldpc_dec->basegraph == 1) {
1943 [ # # ]: 0 : if (Lcb <= 25 * z_c)
1944 : : cw = 25 * z_c;
1945 [ # # ]: 0 : else if (Lcb <= 27 * z_c)
1946 : : cw = 27 * z_c;
1947 [ # # ]: 0 : else if (Lcb <= 30 * z_c)
1948 : : cw = 30 * z_c;
1949 [ # # ]: 0 : else if (Lcb <= 33 * z_c)
1950 : : cw = 33 * z_c;
1951 [ # # ]: 0 : else if (Lcb <= 44 * z_c)
1952 : : cw = 44 * z_c;
1953 [ # # ]: 0 : else if (Lcb <= 55 * z_c)
1954 : : cw = 55 * z_c;
1955 : : else
1956 : 0 : cw = 66 * z_c;
1957 : : } else {
1958 [ # # ]: 0 : if (Lcb <= 15 * z_c)
1959 : : cw = 15 * z_c;
1960 [ # # ]: 0 : else if (Lcb <= 20 * z_c)
1961 : : cw = 20 * z_c;
1962 [ # # ]: 0 : else if (Lcb <= 25 * z_c)
1963 : : cw = 25 * z_c;
1964 [ # # ]: 0 : else if (Lcb <= 30 * z_c)
1965 : : cw = 30 * z_c;
1966 : : else
1967 : 0 : cw = 50 * z_c;
1968 : : }
1969 : 0 : cw_rm = cw - n_filler;
1970 [ # # ]: 0 : if (cw_rm <= 32) {
1971 : 0 : rte_bbdev_log(ERR, "Invalid Ratematching");
1972 : 0 : return -1;
1973 : : }
1974 : : return 0;
1975 : : }
1976 : :
1977 : : static inline char *
1978 : : mbuf_append(struct rte_mbuf *m_head, struct rte_mbuf *m, uint16_t len)
1979 : : {
1980 [ # # # # : 0 : if (unlikely(len > rte_pktmbuf_tailroom(m)))
# # # # #
# ]
1981 : : return NULL;
1982 : :
1983 : 0 : char *tail = (char *)m->buf_addr + m->data_off + m->data_len;
1984 : 0 : m->data_len = (uint16_t)(m->data_len + len);
1985 : 0 : m_head->pkt_len = (m_head->pkt_len + len);
1986 : 0 : return tail;
1987 : : }
1988 : :
1989 : : static inline void
1990 : 0 : fpga_5gnr_mutex_acquisition(struct fpga_5gnr_queue *q)
1991 : : {
1992 : : uint32_t mutex_ctrl, mutex_read, cnt = 0;
1993 : : /* Assign a unique id for the duration of the DDR access */
1994 : 0 : q->ddr_mutex_uuid = rte_rand();
1995 : : /* Request and wait for acquisition of the mutex */
1996 : 0 : mutex_ctrl = (q->ddr_mutex_uuid << 16) + 1;
1997 : : do {
1998 [ # # ]: 0 : if (cnt > 0)
1999 : 0 : usleep(FPGA_5GNR_TIMEOUT_CHECK_INTERVAL);
2000 : : rte_bbdev_log_debug("Acquiring Mutex for %x\n", q->ddr_mutex_uuid);
2001 [ # # ]: 0 : fpga_5gnr_reg_write_32(q->d->mmio_base, FPGA_5GNR_FEC_MUTEX, mutex_ctrl);
2002 : : mutex_read = fpga_5gnr_reg_read_32(q->d->mmio_base, FPGA_5GNR_FEC_MUTEX);
2003 : : rte_bbdev_log_debug("Mutex %x cnt %d owner %x\n",
2004 : : mutex_read, cnt, q->ddr_mutex_uuid);
2005 : 0 : cnt++;
2006 [ # # ]: 0 : } while ((mutex_read >> 16) != q->ddr_mutex_uuid);
2007 : 0 : }
2008 : :
2009 : : static inline void
2010 : : fpga_5gnr_mutex_free(struct fpga_5gnr_queue *q)
2011 : : {
2012 : 0 : uint32_t mutex_ctrl = q->ddr_mutex_uuid << 16;
2013 : 0 : fpga_5gnr_reg_write_32(q->d->mmio_base, FPGA_5GNR_FEC_MUTEX, mutex_ctrl);
2014 : : }
2015 : :
2016 : : static inline int
2017 : 0 : fpga_5gnr_harq_write_loopback(struct fpga_5gnr_queue *q,
2018 : : struct rte_mbuf *harq_input, uint16_t harq_in_length,
2019 : : uint32_t harq_in_offset, uint32_t harq_out_offset)
2020 : : {
2021 : 0 : fpga_5gnr_mutex_acquisition(q);
2022 : : uint32_t out_offset = harq_out_offset;
2023 : : uint32_t in_offset = harq_in_offset;
2024 : 0 : uint32_t left_length = harq_in_length;
2025 : : uint32_t reg_32, increment = 0;
2026 : : uint64_t *input = NULL;
2027 : 0 : uint32_t last_transaction = left_length % FPGA_5GNR_DDR_WR_DATA_LEN_IN_BYTES;
2028 : : uint64_t last_word;
2029 : 0 : struct fpga_5gnr_fec_device *d = q->d;
2030 : :
2031 [ # # ]: 0 : if (last_transaction > 0)
2032 : 0 : left_length -= last_transaction;
2033 [ # # ]: 0 : if (d->fpga_variant == VC_5GNR_FPGA_VARIANT) {
2034 : : /*
2035 : : * Get HARQ buffer size for each VF/PF: When 0x00, there is no
2036 : : * available DDR space for the corresponding VF/PF.
2037 : : */
2038 [ # # ]: 0 : reg_32 = fpga_5gnr_reg_read_32(q->d->mmio_base, FPGA_5GNR_FEC_HARQ_BUF_SIZE_REGS);
2039 [ # # ]: 0 : if (reg_32 < harq_in_length) {
2040 : : left_length = reg_32;
2041 : 0 : rte_bbdev_log(ERR, "HARQ in length > HARQ buffer size\n");
2042 : : }
2043 : : }
2044 : :
2045 : 0 : input = (uint64_t *)rte_pktmbuf_mtod_offset(harq_input, uint8_t *, in_offset);
2046 : :
2047 [ # # ]: 0 : while (left_length > 0) {
2048 [ # # ]: 0 : if (fpga_5gnr_reg_read_8(q->d->mmio_base, FPGA_5GNR_FEC_DDR4_ADDR_RDY_REGS) == 1) {
2049 [ # # ]: 0 : if (d->fpga_variant == AGX100_FPGA_VARIANT) {
2050 : 0 : fpga_5gnr_reg_write_32(q->d->mmio_base,
2051 : : FPGA_5GNR_FEC_DDR4_WR_ADDR_REGS,
2052 : : out_offset >> 3);
2053 : : } else {
2054 : : fpga_5gnr_reg_write_32(q->d->mmio_base,
2055 : : FPGA_5GNR_FEC_DDR4_WR_ADDR_REGS,
2056 : : out_offset);
2057 : : }
2058 : 0 : fpga_5gnr_reg_write_64(q->d->mmio_base,
2059 : : FPGA_5GNR_FEC_DDR4_WR_DATA_REGS,
2060 : 0 : input[increment]);
2061 : 0 : left_length -= FPGA_5GNR_DDR_WR_DATA_LEN_IN_BYTES;
2062 : 0 : out_offset += FPGA_5GNR_DDR_WR_DATA_LEN_IN_BYTES;
2063 : 0 : increment++;
2064 : : fpga_5gnr_reg_write_8(q->d->mmio_base, FPGA_5GNR_FEC_DDR4_WR_DONE_REGS, 1);
2065 : : }
2066 : : }
2067 [ # # ]: 0 : while (last_transaction > 0) {
2068 [ # # ]: 0 : if (fpga_5gnr_reg_read_8(q->d->mmio_base, FPGA_5GNR_FEC_DDR4_ADDR_RDY_REGS) == 1) {
2069 [ # # ]: 0 : if (d->fpga_variant == AGX100_FPGA_VARIANT) {
2070 : 0 : fpga_5gnr_reg_write_32(q->d->mmio_base,
2071 : : FPGA_5GNR_FEC_DDR4_WR_ADDR_REGS,
2072 : : out_offset >> 3);
2073 : : } else {
2074 : : fpga_5gnr_reg_write_32(q->d->mmio_base,
2075 : : FPGA_5GNR_FEC_DDR4_WR_ADDR_REGS,
2076 : : out_offset);
2077 : : }
2078 : 0 : last_word = input[increment];
2079 : 0 : last_word &= (uint64_t)(1ULL << (last_transaction * 4)) - 1;
2080 : : fpga_5gnr_reg_write_64(q->d->mmio_base,
2081 : : FPGA_5GNR_FEC_DDR4_WR_DATA_REGS,
2082 : : last_word);
2083 : : fpga_5gnr_reg_write_8(q->d->mmio_base, FPGA_5GNR_FEC_DDR4_WR_DONE_REGS, 1);
2084 : : last_transaction = 0;
2085 : : }
2086 : : }
2087 : : fpga_5gnr_mutex_free(q);
2088 : 0 : return 1;
2089 : : }
2090 : :
2091 : : static inline int
2092 : 0 : fpga_5gnr_harq_read_loopback(struct fpga_5gnr_queue *q,
2093 : : struct rte_mbuf *harq_output, uint16_t harq_in_length,
2094 : : uint32_t harq_in_offset, uint32_t harq_out_offset)
2095 : : {
2096 : 0 : fpga_5gnr_mutex_acquisition(q);
2097 : : uint32_t left_length, in_offset = harq_in_offset;
2098 : : uint64_t reg;
2099 : : uint32_t increment = 0;
2100 : : uint64_t *input = NULL;
2101 : 0 : uint32_t last_transaction = harq_in_length % FPGA_5GNR_DDR_WR_DATA_LEN_IN_BYTES;
2102 : 0 : struct fpga_5gnr_fec_device *d = q->d;
2103 : :
2104 [ # # ]: 0 : if (last_transaction > 0)
2105 : 0 : harq_in_length += (8 - last_transaction);
2106 : :
2107 [ # # ]: 0 : if (d->fpga_variant == VC_5GNR_FPGA_VARIANT) {
2108 [ # # ]: 0 : reg = fpga_5gnr_reg_read_32(q->d->mmio_base, FPGA_5GNR_FEC_HARQ_BUF_SIZE_REGS);
2109 [ # # ]: 0 : if (reg < harq_in_length) {
2110 : 0 : harq_in_length = reg;
2111 : 0 : rte_bbdev_log(ERR, "HARQ in length > HARQ buffer size\n");
2112 : : }
2113 : : }
2114 : :
2115 [ # # # # ]: 0 : if (!mbuf_append(harq_output, harq_output, harq_in_length)) {
2116 : 0 : rte_bbdev_log(ERR, "HARQ output buffer warning %d %d\n",
2117 : : harq_output->buf_len - rte_pktmbuf_headroom(harq_output),
2118 : : harq_in_length);
2119 [ # # ]: 0 : harq_in_length = harq_output->buf_len - rte_pktmbuf_headroom(harq_output);
2120 [ # # # # ]: 0 : if (!mbuf_append(harq_output, harq_output, harq_in_length)) {
2121 : 0 : rte_bbdev_log(ERR, "HARQ output buffer issue %d %d\n",
2122 : : harq_output->buf_len, harq_in_length);
2123 : 0 : return -1;
2124 : : }
2125 : : }
2126 : 0 : left_length = harq_in_length;
2127 : :
2128 : 0 : input = (uint64_t *)rte_pktmbuf_mtod_offset(harq_output, uint8_t *, harq_out_offset);
2129 : :
2130 [ # # ]: 0 : while (left_length > 0) {
2131 [ # # ]: 0 : if (d->fpga_variant == AGX100_FPGA_VARIANT) {
2132 : 0 : fpga_5gnr_reg_write_32(q->d->mmio_base,
2133 : : FPGA_5GNR_FEC_DDR4_RD_ADDR_REGS,
2134 : : in_offset >> 3);
2135 : : } else {
2136 : 0 : fpga_5gnr_reg_write_32(q->d->mmio_base,
2137 : : FPGA_5GNR_FEC_DDR4_RD_ADDR_REGS,
2138 : : in_offset);
2139 : : }
2140 : 0 : fpga_5gnr_reg_write_8(q->d->mmio_base, FPGA_5GNR_FEC_DDR4_RD_DONE_REGS, 1);
2141 : 0 : reg = fpga_5gnr_reg_read_8(q->d->mmio_base, FPGA_5GNR_FEC_DDR4_RD_RDY_REGS);
2142 [ # # ]: 0 : while (reg != 1) {
2143 : 0 : reg = fpga_5gnr_reg_read_8(q->d->mmio_base, FPGA_5GNR_FEC_DDR4_RD_RDY_REGS);
2144 [ # # ]: 0 : if (reg == FPGA_5GNR_DDR_OVERFLOW) {
2145 : 0 : rte_bbdev_log(ERR, "Read address is overflow!\n");
2146 : 0 : return -1;
2147 : : }
2148 : : }
2149 [ # # ]: 0 : input[increment] = fpga_5gnr_reg_read_64(q->d->mmio_base,
2150 : : FPGA_5GNR_FEC_DDR4_RD_DATA_REGS);
2151 : 0 : left_length -= FPGA_5GNR_DDR_RD_DATA_LEN_IN_BYTES;
2152 : 0 : in_offset += FPGA_5GNR_DDR_WR_DATA_LEN_IN_BYTES;
2153 : 0 : increment++;
2154 [ # # ]: 0 : if (d->fpga_variant == AGX100_FPGA_VARIANT)
2155 : : fpga_5gnr_reg_write_8(q->d->mmio_base, FPGA_5GNR_FEC_DDR4_RD_RDY_REGS, 0);
2156 : : else
2157 : : fpga_5gnr_reg_write_8(q->d->mmio_base, FPGA_5GNR_FEC_DDR4_RD_DONE_REGS, 0);
2158 : : }
2159 : : fpga_5gnr_mutex_free(q);
2160 : 0 : return 1;
2161 : : }
2162 : :
2163 : : static inline int
2164 : 0 : enqueue_ldpc_enc_one_op_cb(struct fpga_5gnr_queue *q, struct rte_bbdev_enc_op *op,
2165 : : uint16_t desc_offset)
2166 : : {
2167 : : union vc_5gnr_dma_desc *vc_5gnr_desc;
2168 : : union agx100_dma_desc *agx100_desc;
2169 : : int ret;
2170 : : uint8_t c, crc24_bits = 0;
2171 : : struct rte_bbdev_op_ldpc_enc *enc = &op->ldpc_enc;
2172 : 0 : uint16_t in_offset = enc->input.offset;
2173 : 0 : uint16_t out_offset = enc->output.offset;
2174 : 0 : struct rte_mbuf *m_in = enc->input.data;
2175 : 0 : struct rte_mbuf *m_out = enc->output.data;
2176 : : struct rte_mbuf *m_out_head = enc->output.data;
2177 : : uint32_t in_length, out_length, e;
2178 : : uint16_t total_left = enc->input.length;
2179 : : uint16_t ring_offset;
2180 : : uint16_t K, k_;
2181 : 0 : struct fpga_5gnr_fec_device *d = q->d;
2182 : :
2183 [ # # ]: 0 : if (d->fpga_variant == VC_5GNR_FPGA_VARIANT) {
2184 [ # # ]: 0 : if (vc_5gnr_validate_ldpc_enc_op(op) == -1) {
2185 : 0 : rte_bbdev_log(ERR, "LDPC encoder validation rejected");
2186 : 0 : return -EINVAL;
2187 : : }
2188 : : }
2189 : :
2190 : : /* Clear op status */
2191 : 0 : op->status = 0;
2192 : :
2193 [ # # ]: 0 : if (m_in == NULL || m_out == NULL) {
2194 : 0 : rte_bbdev_log(ERR, "Invalid mbuf pointer");
2195 : 0 : op->status = 1 << RTE_BBDEV_DATA_ERROR;
2196 : 0 : return -EINVAL;
2197 : : }
2198 : :
2199 [ # # ]: 0 : if (enc->op_flags & RTE_BBDEV_LDPC_CRC_24B_ATTACH)
2200 : : crc24_bits = 24;
2201 : :
2202 [ # # ]: 0 : if (enc->code_block_mode == RTE_BBDEV_TRANSPORT_BLOCK) {
2203 : : /* TODO: For Transport Block mode. */
2204 : 0 : rte_bbdev_log(ERR, "Transport Block not supported yet");
2205 : 0 : return -1;
2206 : : }
2207 : : /* For Code Block mode. */
2208 : : c = 1;
2209 : 0 : e = enc->cb_params.e;
2210 : :
2211 : : /* Update total_left */
2212 [ # # ]: 0 : K = (enc->basegraph == 1 ? 22 : 10) * enc->z_c;
2213 : 0 : k_ = K - enc->n_filler;
2214 : 0 : in_length = (k_ - crc24_bits) >> 3;
2215 : 0 : out_length = (e + 7) >> 3;
2216 : :
2217 : 0 : total_left = rte_pktmbuf_data_len(m_in) - in_offset;
2218 : :
2219 : : /* Update offsets */
2220 [ # # ]: 0 : if (total_left != in_length) {
2221 : 0 : op->status |= 1 << RTE_BBDEV_DATA_ERROR;
2222 : 0 : rte_bbdev_log(ERR,
2223 : : "Mismatch between mbuf length and included CBs sizes %d",
2224 : : total_left);
2225 : : }
2226 : :
2227 [ # # ]: 0 : mbuf_append(m_out_head, m_out, out_length);
2228 : :
2229 : : /* Offset into the ring. */
2230 : : ring_offset = fpga_5gnr_desc_idx_tail(q, desc_offset);
2231 : :
2232 [ # # ]: 0 : if (d->fpga_variant == VC_5GNR_FPGA_VARIANT) {
2233 : : /* Setup DMA Descriptor. */
2234 : : vc_5gnr_desc = vc_5gnr_get_desc_tail(q, desc_offset);
2235 : 0 : ret = vc_5gnr_dma_desc_te_fill(op, &vc_5gnr_desc->enc_req, m_in, m_out,
2236 : : k_, e, in_offset, out_offset, ring_offset, c);
2237 : : } else {
2238 : : /* Setup DMA Descriptor. */
2239 : : agx100_desc = agx100_get_desc_tail(q, desc_offset);
2240 : 0 : ret = agx100_dma_desc_le_fill(op, &agx100_desc->enc_req, m_in, m_out,
2241 : : k_, e, in_offset, out_offset, ring_offset, c);
2242 : : }
2243 : :
2244 [ # # ]: 0 : if (unlikely(ret < 0))
2245 : : return ret;
2246 : :
2247 : : /* Update lengths */
2248 : 0 : total_left -= in_length;
2249 : 0 : op->ldpc_enc.output.length += out_length;
2250 : :
2251 [ # # ]: 0 : if (total_left > 0) {
2252 : 0 : rte_bbdev_log(ERR,
2253 : : "Mismatch between mbuf length and included CB sizes: mbuf len %u, cb len %u",
2254 : : total_left, in_length);
2255 : 0 : return -1;
2256 : : }
2257 : :
2258 : : #ifdef RTE_LIBRTE_BBDEV_DEBUG
2259 : : if (d->fpga_variant == VC_5GNR_FPGA_VARIANT)
2260 : : vc_5gnr_print_dma_enc_desc_debug_info(vc_5gnr_desc);
2261 : : else
2262 : : agx100_print_dma_enc_desc_debug_info(agx100_desc);
2263 : : #endif
2264 : : return 1;
2265 : : }
2266 : :
2267 : : static inline int
2268 : 0 : vc_5gnr_enqueue_ldpc_dec_one_op_cb(struct fpga_5gnr_queue *q, struct rte_bbdev_dec_op *op,
2269 : : uint16_t desc_offset)
2270 : : {
2271 : : union vc_5gnr_dma_desc *desc;
2272 : : int ret;
2273 : : uint16_t ring_offset;
2274 : : uint8_t c;
2275 : : uint16_t e, in_length, out_length, k0, l, seg_total_left, sys_cols;
2276 : : uint16_t K, parity_offset, harq_in_length = 0, harq_out_length = 0;
2277 : : uint16_t crc24_overlap = 0;
2278 : : struct rte_bbdev_op_ldpc_dec *dec = &op->ldpc_dec;
2279 : 0 : struct rte_mbuf *m_in = dec->input.data;
2280 : 0 : struct rte_mbuf *m_out = dec->hard_output.data;
2281 : : struct rte_mbuf *m_out_head = dec->hard_output.data;
2282 : 0 : uint16_t in_offset = dec->input.offset;
2283 : 0 : uint16_t out_offset = dec->hard_output.offset;
2284 : : uint32_t harq_offset = 0;
2285 : :
2286 [ # # ]: 0 : if (vc_5gnr_validate_ldpc_dec_op(op) == -1) {
2287 : 0 : rte_bbdev_log(ERR, "LDPC decoder validation rejected");
2288 : 0 : return -EINVAL;
2289 : : }
2290 : :
2291 : : /* Clear op status */
2292 : 0 : op->status = 0;
2293 : :
2294 : : /* Setup DMA Descriptor */
2295 : : ring_offset = fpga_5gnr_desc_idx_tail(q, desc_offset);
2296 : : desc = vc_5gnr_get_desc_tail(q, desc_offset);
2297 : :
2298 [ # # ]: 0 : if (check_bit(dec->op_flags, RTE_BBDEV_LDPC_INTERNAL_HARQ_MEMORY_LOOPBACK)) {
2299 : 0 : struct rte_mbuf *harq_in = dec->harq_combined_input.data;
2300 : 0 : struct rte_mbuf *harq_out = dec->harq_combined_output.data;
2301 : 0 : harq_in_length = dec->harq_combined_input.length;
2302 : 0 : uint32_t harq_in_offset = dec->harq_combined_input.offset;
2303 : 0 : uint32_t harq_out_offset = dec->harq_combined_output.offset;
2304 : :
2305 [ # # ]: 0 : if (check_bit(dec->op_flags, RTE_BBDEV_LDPC_INTERNAL_HARQ_MEMORY_OUT_ENABLE)) {
2306 : 0 : ret = fpga_5gnr_harq_write_loopback(q, harq_in,
2307 : : harq_in_length, harq_in_offset,
2308 : : harq_out_offset);
2309 [ # # ]: 0 : } else if (check_bit(dec->op_flags,
2310 : : RTE_BBDEV_LDPC_INTERNAL_HARQ_MEMORY_IN_ENABLE
2311 : : )) {
2312 : 0 : ret = fpga_5gnr_harq_read_loopback(q, harq_out,
2313 : : harq_in_length, harq_in_offset,
2314 : : harq_out_offset);
2315 : 0 : dec->harq_combined_output.length = harq_in_length;
2316 : : } else {
2317 : 0 : rte_bbdev_log(ERR, "OP flag Err!");
2318 : : ret = -1;
2319 : : }
2320 : :
2321 : : /* Set descriptor for dequeue */
2322 : 0 : desc->dec_req.done = 1;
2323 : 0 : desc->dec_req.error = 0;
2324 : 0 : desc->dec_req.op_addr = op;
2325 : 0 : desc->dec_req.cbs_in_op = 1;
2326 : :
2327 : : /* Mark this dummy descriptor to be dropped by HW */
2328 : 0 : desc->dec_req.desc_idx = (ring_offset + 1) & q->sw_ring_wrap_mask;
2329 : :
2330 : 0 : return ret; /* Error or number of CB */
2331 : : }
2332 : :
2333 [ # # ]: 0 : if (m_in == NULL || m_out == NULL) {
2334 : 0 : rte_bbdev_log(ERR, "Invalid mbuf pointer");
2335 : 0 : op->status = 1 << RTE_BBDEV_DATA_ERROR;
2336 : 0 : return -1;
2337 : : }
2338 : :
2339 : : c = 1;
2340 : 0 : e = dec->cb_params.e;
2341 : :
2342 [ # # ]: 0 : if (check_bit(dec->op_flags, RTE_BBDEV_LDPC_CRC_TYPE_24B_DROP))
2343 : : crc24_overlap = 24;
2344 : :
2345 [ # # ]: 0 : sys_cols = (dec->basegraph == 1) ? 22 : 10;
2346 : 0 : K = sys_cols * dec->z_c;
2347 : 0 : parity_offset = K - 2 * dec->z_c;
2348 : :
2349 : 0 : out_length = ((K - crc24_overlap - dec->n_filler) >> 3);
2350 : : in_length = e;
2351 : 0 : seg_total_left = dec->input.length;
2352 : :
2353 [ # # ]: 0 : if (check_bit(dec->op_flags, RTE_BBDEV_LDPC_HQ_COMBINE_IN_ENABLE))
2354 : 0 : harq_in_length = RTE_MIN(dec->harq_combined_input.length, (uint32_t)dec->n_cb);
2355 : :
2356 [ # # ]: 0 : if (check_bit(dec->op_flags, RTE_BBDEV_LDPC_HQ_COMBINE_OUT_ENABLE)) {
2357 : 0 : k0 = get_k0(dec->n_cb, dec->z_c, dec->basegraph, dec->rv_index);
2358 [ # # ]: 0 : if (k0 > parity_offset)
2359 : 0 : l = k0 + e;
2360 : : else
2361 : 0 : l = k0 + e + dec->n_filler;
2362 : 0 : harq_out_length = RTE_MIN(RTE_MAX(harq_in_length, l), dec->n_cb);
2363 : 0 : dec->harq_combined_output.length = harq_out_length;
2364 : : }
2365 : :
2366 : : mbuf_append(m_out_head, m_out, out_length);
2367 : :
2368 [ # # ]: 0 : if (check_bit(dec->op_flags, RTE_BBDEV_LDPC_HQ_COMBINE_IN_ENABLE))
2369 : 0 : harq_offset = dec->harq_combined_input.offset;
2370 [ # # ]: 0 : else if (check_bit(dec->op_flags, RTE_BBDEV_LDPC_HQ_COMBINE_OUT_ENABLE))
2371 : 0 : harq_offset = dec->harq_combined_output.offset;
2372 : :
2373 [ # # ]: 0 : if ((harq_offset & 0x3FF) > 0) {
2374 : 0 : rte_bbdev_log(ERR, "Invalid HARQ offset %d", harq_offset);
2375 : 0 : op->status = 1 << RTE_BBDEV_DATA_ERROR;
2376 : 0 : return -1;
2377 : : }
2378 : :
2379 : 0 : ret = vc_5gnr_dma_desc_ld_fill(op, &desc->dec_req, m_in, m_out,
2380 : : harq_in_length, in_offset, out_offset, harq_offset,
2381 : : ring_offset, c);
2382 : :
2383 [ # # ]: 0 : if (unlikely(ret < 0))
2384 : : return ret;
2385 : : /* Update lengths */
2386 : 0 : seg_total_left -= in_length;
2387 : 0 : op->ldpc_dec.hard_output.length += out_length;
2388 [ # # ]: 0 : if (seg_total_left > 0) {
2389 : 0 : rte_bbdev_log(ERR,
2390 : : "Mismatch between mbuf length and included CB sizes: mbuf len %u, cb len %u",
2391 : : seg_total_left, in_length);
2392 : 0 : return -1;
2393 : : }
2394 : :
2395 : : #ifdef RTE_LIBRTE_BBDEV_DEBUG
2396 : : vc_5gnr_print_dma_dec_desc_debug_info(desc);
2397 : : #endif
2398 : :
2399 : : return 1;
2400 : : }
2401 : :
2402 : : static inline int
2403 : 0 : agx100_enqueue_ldpc_dec_one_op_cb(struct fpga_5gnr_queue *q, struct rte_bbdev_dec_op *op,
2404 : : uint16_t desc_offset)
2405 : : {
2406 : : union agx100_dma_desc *desc;
2407 : : int ret;
2408 : : uint16_t ring_offset;
2409 : : uint8_t c;
2410 : : uint16_t e, in_length, out_length, k0, l, seg_total_left, sys_cols;
2411 : : uint16_t K, parity_offset, harq_in_length = 0, harq_out_length = 0;
2412 : : uint16_t crc24_overlap = 0;
2413 : : struct rte_bbdev_op_ldpc_dec *dec = &op->ldpc_dec;
2414 : 0 : struct rte_mbuf *m_in = dec->input.data;
2415 : 0 : struct rte_mbuf *m_out = dec->hard_output.data;
2416 : : struct rte_mbuf *m_out_head = dec->hard_output.data;
2417 : 0 : uint16_t in_offset = dec->input.offset;
2418 : 0 : uint16_t out_offset = dec->hard_output.offset;
2419 : : uint32_t harq_in_offset = 0;
2420 : : uint32_t harq_out_offset = 0;
2421 : :
2422 : : /* Clear op status. */
2423 : 0 : op->status = 0;
2424 : :
2425 : : /* Setup DMA Descriptor. */
2426 : : ring_offset = fpga_5gnr_desc_idx_tail(q, desc_offset);
2427 : : desc = agx100_get_desc_tail(q, desc_offset);
2428 : :
2429 [ # # ]: 0 : if (check_bit(dec->op_flags, RTE_BBDEV_LDPC_INTERNAL_HARQ_MEMORY_LOOPBACK)) {
2430 : 0 : struct rte_mbuf *harq_in = dec->harq_combined_input.data;
2431 : 0 : struct rte_mbuf *harq_out = dec->harq_combined_output.data;
2432 : 0 : harq_in_length = dec->harq_combined_input.length;
2433 : 0 : uint32_t harq_in_offset = dec->harq_combined_input.offset;
2434 : 0 : uint32_t harq_out_offset = dec->harq_combined_output.offset;
2435 : :
2436 [ # # ]: 0 : if (check_bit(dec->op_flags, RTE_BBDEV_LDPC_INTERNAL_HARQ_MEMORY_OUT_ENABLE)) {
2437 : 0 : ret = fpga_5gnr_harq_write_loopback(q, harq_in,
2438 : : harq_in_length, harq_in_offset,
2439 : : harq_out_offset);
2440 [ # # ]: 0 : } else if (check_bit(dec->op_flags,
2441 : : RTE_BBDEV_LDPC_INTERNAL_HARQ_MEMORY_IN_ENABLE)) {
2442 : 0 : ret = fpga_5gnr_harq_read_loopback(q, harq_out,
2443 : : harq_in_length, harq_in_offset,
2444 : : harq_out_offset);
2445 : 0 : dec->harq_combined_output.length = harq_in_length;
2446 : : } else {
2447 : 0 : rte_bbdev_log(ERR, "OP flag Err!");
2448 : : ret = -1;
2449 : : }
2450 : :
2451 : : /* Set descriptor for dequeue. */
2452 : 0 : desc->dec_req.done = 1;
2453 : 0 : desc->dec_req.error_code = 0;
2454 : 0 : desc->dec_req.error_msg = 0;
2455 : 0 : desc->dec_req.op_addr = op;
2456 : 0 : desc->dec_req.cbs_in_op = 1;
2457 : :
2458 : : /* Mark this dummy descriptor to be dropped by HW. */
2459 : 0 : desc->dec_req.desc_idx = (ring_offset + 1) & q->sw_ring_wrap_mask;
2460 : :
2461 : 0 : return ret; /* Error or number of CB. */
2462 : : }
2463 : :
2464 [ # # ]: 0 : if (m_in == NULL || m_out == NULL) {
2465 : 0 : rte_bbdev_log(ERR, "Invalid mbuf pointer");
2466 : 0 : op->status = 1 << RTE_BBDEV_DATA_ERROR;
2467 : 0 : return -1;
2468 : : }
2469 : :
2470 : : c = 1;
2471 : 0 : e = dec->cb_params.e;
2472 : :
2473 [ # # ]: 0 : if (check_bit(dec->op_flags, RTE_BBDEV_LDPC_CRC_TYPE_24B_DROP))
2474 : : crc24_overlap = 24;
2475 : :
2476 [ # # ]: 0 : sys_cols = (dec->basegraph == 1) ? 22 : 10;
2477 : 0 : K = sys_cols * dec->z_c;
2478 : 0 : parity_offset = K - 2 * dec->z_c;
2479 : :
2480 : 0 : out_length = ((K - crc24_overlap - dec->n_filler) >> 3);
2481 : : in_length = e;
2482 : 0 : seg_total_left = dec->input.length;
2483 : :
2484 [ # # ]: 0 : if (check_bit(dec->op_flags, RTE_BBDEV_LDPC_HQ_COMBINE_IN_ENABLE))
2485 : 0 : harq_in_length = RTE_MIN(dec->harq_combined_input.length, (uint32_t)dec->n_cb);
2486 : :
2487 [ # # ]: 0 : if (check_bit(dec->op_flags, RTE_BBDEV_LDPC_HQ_COMBINE_OUT_ENABLE)) {
2488 : 0 : k0 = get_k0(dec->n_cb, dec->z_c, dec->basegraph, dec->rv_index);
2489 [ # # ]: 0 : if (k0 > parity_offset)
2490 : 0 : l = k0 + e;
2491 : : else
2492 : 0 : l = k0 + e + dec->n_filler;
2493 : 0 : harq_out_length = RTE_MIN(RTE_MAX(harq_in_length, l), dec->n_cb);
2494 : 0 : dec->harq_combined_output.length = harq_out_length;
2495 : : }
2496 : :
2497 : : mbuf_append(m_out_head, m_out, out_length);
2498 : 0 : harq_in_offset = dec->harq_combined_input.offset;
2499 : 0 : harq_out_offset = dec->harq_combined_output.offset;
2500 : :
2501 : 0 : ret = agx100_dma_desc_ld_fill(op, &desc->dec_req, m_in, m_out,
2502 : : harq_in_length, in_offset, out_offset, harq_in_offset,
2503 : : harq_out_offset, ring_offset, c);
2504 : :
2505 [ # # ]: 0 : if (unlikely(ret < 0))
2506 : : return ret;
2507 : : /* Update lengths. */
2508 : 0 : seg_total_left -= in_length;
2509 : 0 : op->ldpc_dec.hard_output.length += out_length;
2510 [ # # ]: 0 : if (seg_total_left > 0) {
2511 : 0 : rte_bbdev_log(ERR,
2512 : : "Mismatch between mbuf length and included CB sizes: mbuf len %u, cb len %u",
2513 : : seg_total_left, in_length);
2514 : 0 : return -1;
2515 : : }
2516 : :
2517 : : #ifdef RTE_LIBRTE_BBDEV_DEBUG
2518 : : agx100_print_dma_dec_desc_debug_info(desc);
2519 : : #endif
2520 : :
2521 : : return 1;
2522 : : }
2523 : :
2524 : : static uint16_t
2525 : 0 : fpga_5gnr_enqueue_ldpc_enc(struct rte_bbdev_queue_data *q_data,
2526 : : struct rte_bbdev_enc_op **ops, uint16_t num)
2527 : : {
2528 : : uint16_t i, total_enqueued_cbs = 0;
2529 : : int32_t avail;
2530 : : int enqueued_cbs;
2531 : 0 : struct fpga_5gnr_queue *q = q_data->queue_private;
2532 : : union vc_5gnr_dma_desc *vc_5gnr_desc;
2533 : : union agx100_dma_desc *agx100_desc;
2534 : 0 : struct fpga_5gnr_fec_device *d = q->d;
2535 : :
2536 : : /* Check if queue is not full */
2537 [ # # ]: 0 : if (unlikely((fpga_5gnr_desc_idx_tail(q, 1)) == q->head_free_desc))
2538 : : return 0;
2539 : :
2540 : : /* Calculates available space */
2541 : : avail = (q->head_free_desc > q->tail) ?
2542 [ # # ]: 0 : q->head_free_desc - q->tail - 1 :
2543 : 0 : q->ring_ctrl_reg.ring_size + q->head_free_desc - q->tail - 1;
2544 : :
2545 [ # # ]: 0 : for (i = 0; i < num; ++i) {
2546 : : /* Check if there is available space for further
2547 : : * processing
2548 : : */
2549 [ # # ]: 0 : if (unlikely(avail - 1 < 0))
2550 : : break;
2551 : 0 : avail -= 1;
2552 : 0 : enqueued_cbs = enqueue_ldpc_enc_one_op_cb(q, ops[i], total_enqueued_cbs);
2553 : :
2554 [ # # ]: 0 : if (enqueued_cbs < 0)
2555 : : break;
2556 : :
2557 : 0 : total_enqueued_cbs += enqueued_cbs;
2558 : :
2559 : : rte_bbdev_log_debug("enqueuing enc ops [%d/%d] | head %d | tail %d",
2560 : : total_enqueued_cbs, num,
2561 : : q->head_free_desc, q->tail);
2562 : : }
2563 : :
2564 : : /* Set interrupt bit for last CB in enqueued ops. FPGA issues interrupt
2565 : : * only when all previous CBs were already processed.
2566 : : */
2567 [ # # ]: 0 : if (d->fpga_variant == VC_5GNR_FPGA_VARIANT) {
2568 : 0 : vc_5gnr_desc = vc_5gnr_get_desc_tail(q, total_enqueued_cbs - 1);
2569 : 0 : vc_5gnr_desc->enc_req.irq_en = q->irq_enable;
2570 : : } else {
2571 : 0 : agx100_desc = agx100_get_desc_tail(q, total_enqueued_cbs - 1);
2572 : 0 : agx100_desc->enc_req.int_en = q->irq_enable;
2573 : : }
2574 : :
2575 : : fpga_5gnr_dma_enqueue(q, total_enqueued_cbs, &q_data->queue_stats);
2576 : :
2577 : : /* Update stats */
2578 : 0 : q_data->queue_stats.enqueued_count += i;
2579 : 0 : q_data->queue_stats.enqueue_err_count += num - i;
2580 : :
2581 : 0 : return i;
2582 : : }
2583 : :
2584 : : static uint16_t
2585 : 0 : fpga_5gnr_enqueue_ldpc_dec(struct rte_bbdev_queue_data *q_data,
2586 : : struct rte_bbdev_dec_op **ops, uint16_t num)
2587 : : {
2588 : : uint16_t i, total_enqueued_cbs = 0;
2589 : : int32_t avail;
2590 : : int enqueued_cbs;
2591 : 0 : struct fpga_5gnr_queue *q = q_data->queue_private;
2592 : : union vc_5gnr_dma_desc *vc_5gnr_desc;
2593 : : union agx100_dma_desc *agx100_desc;
2594 : 0 : struct fpga_5gnr_fec_device *d = q->d;
2595 : :
2596 : : /* Check if queue is not full */
2597 [ # # ]: 0 : if (unlikely((fpga_5gnr_desc_idx_tail(q, 1)) == q->head_free_desc))
2598 : : return 0;
2599 : :
2600 : : /* Calculates available space */
2601 : : avail = (q->head_free_desc > q->tail) ?
2602 [ # # ]: 0 : q->head_free_desc - q->tail - 1 :
2603 : 0 : q->ring_ctrl_reg.ring_size + q->head_free_desc - q->tail - 1;
2604 : :
2605 [ # # ]: 0 : for (i = 0; i < num; ++i) {
2606 : :
2607 : : /* Check if there is available space for further
2608 : : * processing
2609 : : */
2610 [ # # ]: 0 : if (unlikely(avail - 1 < 0))
2611 : : break;
2612 : 0 : avail -= 1;
2613 [ # # ]: 0 : if (q->d->fpga_variant == VC_5GNR_FPGA_VARIANT) {
2614 : 0 : enqueued_cbs = vc_5gnr_enqueue_ldpc_dec_one_op_cb(q, ops[i],
2615 : : total_enqueued_cbs);
2616 : : } else {
2617 : 0 : enqueued_cbs = agx100_enqueue_ldpc_dec_one_op_cb(q, ops[i],
2618 : : total_enqueued_cbs);
2619 : : }
2620 : :
2621 [ # # ]: 0 : if (enqueued_cbs < 0)
2622 : : break;
2623 : :
2624 : 0 : total_enqueued_cbs += enqueued_cbs;
2625 : :
2626 : : rte_bbdev_log_debug("enqueuing dec ops [%d/%d] | head %d | tail %d",
2627 : : total_enqueued_cbs, num,
2628 : : q->head_free_desc, q->tail);
2629 : : }
2630 : :
2631 : : /* Update stats */
2632 : 0 : q_data->queue_stats.enqueued_count += i;
2633 : 0 : q_data->queue_stats.enqueue_err_count += num - i;
2634 : :
2635 : : /* Set interrupt bit for last CB in enqueued ops. FPGA issues interrupt
2636 : : * only when all previous CBs were already processed.
2637 : : */
2638 [ # # ]: 0 : if (d->fpga_variant == VC_5GNR_FPGA_VARIANT) {
2639 : 0 : vc_5gnr_desc = vc_5gnr_get_desc_tail(q, total_enqueued_cbs - 1);
2640 : 0 : vc_5gnr_desc->enc_req.irq_en = q->irq_enable;
2641 : : } else {
2642 : 0 : agx100_desc = agx100_get_desc_tail(q, total_enqueued_cbs - 1);
2643 : 0 : agx100_desc->enc_req.int_en = q->irq_enable;
2644 : : }
2645 : :
2646 : : fpga_5gnr_dma_enqueue(q, total_enqueued_cbs, &q_data->queue_stats);
2647 : 0 : return i;
2648 : : }
2649 : :
2650 : :
2651 : : static inline int
2652 : 0 : vc_5gnr_dequeue_ldpc_enc_one_op_cb(struct fpga_5gnr_queue *q, struct rte_bbdev_enc_op **op,
2653 : : uint16_t desc_offset)
2654 : : {
2655 : : union vc_5gnr_dma_desc *desc;
2656 : : int desc_error;
2657 : : /* Set current desc */
2658 : : desc = vc_5gnr_get_desc(q, desc_offset);
2659 : :
2660 : : /*check if done */
2661 [ # # ]: 0 : if (desc->enc_req.done == 0)
2662 : : return -1;
2663 : :
2664 : : /* make sure the response is read atomically */
2665 : 0 : rte_smp_rmb();
2666 : :
2667 : : rte_bbdev_log_debug("DMA response desc %p", desc);
2668 : :
2669 : : #ifdef RTE_LIBRTE_BBDEV_DEBUG
2670 : : vc_5gnr_print_dma_enc_desc_debug_info(desc);
2671 : : #endif
2672 : 0 : *op = desc->enc_req.op_addr;
2673 : : /* Check the descriptor error field, return 1 on error */
2674 : 0 : desc_error = vc_5gnr_check_desc_error(desc->enc_req.error);
2675 : 0 : (*op)->status = desc_error << RTE_BBDEV_DATA_ERROR;
2676 : :
2677 : 0 : return 1;
2678 : : }
2679 : :
2680 : : static inline int
2681 : 0 : agx100_dequeue_ldpc_enc_one_op_cb(struct fpga_5gnr_queue *q, struct rte_bbdev_enc_op **op,
2682 : : uint16_t desc_offset)
2683 : : {
2684 : : union agx100_dma_desc *desc;
2685 : : int desc_error;
2686 : :
2687 : : /* Set current desc. */
2688 : : desc = agx100_get_desc(q, desc_offset);
2689 : : /*check if done */
2690 [ # # ]: 0 : if (desc->enc_req.done == 0)
2691 : : return -1;
2692 : :
2693 : : /* make sure the response is read atomically. */
2694 : 0 : rte_smp_rmb();
2695 : :
2696 : : rte_bbdev_log_debug("DMA response desc %p", desc);
2697 : :
2698 : : #ifdef RTE_LIBRTE_BBDEV_DEBUG
2699 : : agx100_print_dma_enc_desc_debug_info(desc);
2700 : : #endif
2701 : 0 : *op = desc->enc_req.op_addr;
2702 : : /* Check the descriptor error field, return 1 on error. */
2703 : 0 : desc_error = agx100_check_desc_error(desc->enc_req.error_code,
2704 : 0 : desc->enc_req.error_msg);
2705 : :
2706 : 0 : (*op)->status = desc_error << RTE_BBDEV_DATA_ERROR;
2707 : :
2708 : 0 : return 1;
2709 : : }
2710 : :
2711 : : static inline int
2712 : 0 : vc_5gnr_dequeue_ldpc_dec_one_op_cb(struct fpga_5gnr_queue *q, struct rte_bbdev_dec_op **op,
2713 : : uint16_t desc_offset)
2714 : : {
2715 : : union vc_5gnr_dma_desc *desc;
2716 : : int desc_error;
2717 : :
2718 : : /* Set descriptor */
2719 : : desc = vc_5gnr_get_desc(q, desc_offset);
2720 : :
2721 : : /* Verify done bit is set */
2722 [ # # ]: 0 : if (desc->dec_req.done == 0)
2723 : : return -1;
2724 : :
2725 : : /* make sure the response is read atomically */
2726 : 0 : rte_smp_rmb();
2727 : :
2728 : : #ifdef RTE_LIBRTE_BBDEV_DEBUG
2729 : : vc_5gnr_print_dma_dec_desc_debug_info(desc);
2730 : : #endif
2731 : :
2732 : 0 : *op = desc->dec_req.op_addr;
2733 : :
2734 [ # # ]: 0 : if (check_bit((*op)->ldpc_dec.op_flags,
2735 : : RTE_BBDEV_LDPC_INTERNAL_HARQ_MEMORY_LOOPBACK)) {
2736 : 0 : (*op)->status = 0;
2737 : 0 : return 1;
2738 : : }
2739 : :
2740 : : /* FPGA reports iterations based on round-up minus 1 */
2741 : 0 : (*op)->ldpc_dec.iter_count = desc->dec_req.iter + 1;
2742 : :
2743 : : /* CRC Check criteria */
2744 [ # # # # ]: 0 : if (desc->dec_req.crc24b_ind && !(desc->dec_req.crcb_pass))
2745 : 0 : (*op)->status = 1 << RTE_BBDEV_CRC_ERROR;
2746 : :
2747 : : /* et_pass = 0 when decoder fails */
2748 [ # # ]: 0 : (*op)->status |= !(desc->dec_req.et_pass) << RTE_BBDEV_SYNDROME_ERROR;
2749 : :
2750 : : /* Check the descriptor error field, return 1 on error */
2751 : 0 : desc_error = vc_5gnr_check_desc_error(desc->dec_req.error);
2752 : :
2753 : 0 : (*op)->status |= desc_error << RTE_BBDEV_DATA_ERROR;
2754 : :
2755 : 0 : return 1;
2756 : : }
2757 : :
2758 : : static inline int
2759 : 0 : agx100_dequeue_ldpc_dec_one_op_cb(struct fpga_5gnr_queue *q, struct rte_bbdev_dec_op **op,
2760 : : uint16_t desc_offset)
2761 : : {
2762 : : union agx100_dma_desc *desc;
2763 : : int desc_error;
2764 : :
2765 : : /* Set descriptor. */
2766 : : desc = agx100_get_desc(q, desc_offset);
2767 : : /* Verify done bit is set. */
2768 [ # # ]: 0 : if (desc->dec_req.done == 0)
2769 : : return -1;
2770 : :
2771 : : /* make sure the response is read atomically. */
2772 : 0 : rte_smp_rmb();
2773 : :
2774 : : #ifdef RTE_LIBRTE_BBDEV_DEBUG
2775 : : agx100_print_dma_dec_desc_debug_info(desc);
2776 : : #endif
2777 : :
2778 : 0 : *op = desc->dec_req.op_addr;
2779 : :
2780 [ # # ]: 0 : if (check_bit((*op)->ldpc_dec.op_flags, RTE_BBDEV_LDPC_INTERNAL_HARQ_MEMORY_LOOPBACK)) {
2781 : 0 : (*op)->status = 0;
2782 : 0 : return 1;
2783 : : }
2784 : :
2785 : : /* FPGA reports iterations based on round-up minus 1. */
2786 : 0 : (*op)->ldpc_dec.iter_count = desc->dec_req.max_iter_ret + 1;
2787 : :
2788 : : /* CRC Check criteria. */
2789 [ # # # # ]: 0 : if (desc->dec_req.crc24b_ind && !(desc->dec_req.cb_crc_all_pass))
2790 : 0 : (*op)->status = 1 << RTE_BBDEV_CRC_ERROR;
2791 : :
2792 : : /* et_pass = 0 when decoder fails. */
2793 [ # # ]: 0 : (*op)->status |= !(desc->dec_req.cb_all_et_pass) << RTE_BBDEV_SYNDROME_ERROR;
2794 : :
2795 : : /* Check the descriptor error field, return 1 on error. */
2796 : 0 : desc_error = agx100_check_desc_error(desc->dec_req.error_code,
2797 : 0 : desc->dec_req.error_msg);
2798 : :
2799 : 0 : (*op)->status |= desc_error << RTE_BBDEV_DATA_ERROR;
2800 : 0 : return 1;
2801 : : }
2802 : :
2803 : : static uint16_t
2804 : 0 : fpga_5gnr_dequeue_ldpc_enc(struct rte_bbdev_queue_data *q_data,
2805 : : struct rte_bbdev_enc_op **ops, uint16_t num)
2806 : : {
2807 : 0 : struct fpga_5gnr_queue *q = q_data->queue_private;
2808 : 0 : uint32_t avail = (q->tail - q->head_free_desc) & q->sw_ring_wrap_mask;
2809 : : uint16_t i;
2810 : : uint16_t dequeued_cbs = 0;
2811 : : int ret;
2812 : :
2813 [ # # # # ]: 0 : for (i = 0; (i < num) && (dequeued_cbs < avail); ++i) {
2814 [ # # ]: 0 : if (q->d->fpga_variant == VC_5GNR_FPGA_VARIANT)
2815 : 0 : ret = vc_5gnr_dequeue_ldpc_enc_one_op_cb(q, &ops[i], dequeued_cbs);
2816 : : else
2817 : 0 : ret = agx100_dequeue_ldpc_enc_one_op_cb(q, &ops[i], dequeued_cbs);
2818 : :
2819 [ # # ]: 0 : if (ret < 0)
2820 : : break;
2821 : :
2822 : 0 : dequeued_cbs += ret;
2823 : :
2824 : : rte_bbdev_log_debug("dequeuing enc ops [%d/%d] | head %d | tail %d",
2825 : : dequeued_cbs, num, q->head_free_desc, q->tail);
2826 : : }
2827 : :
2828 : : /* Update head */
2829 : 0 : q->head_free_desc = fpga_5gnr_desc_idx(q, dequeued_cbs);
2830 : :
2831 : : /* Update stats */
2832 : 0 : q_data->queue_stats.dequeued_count += i;
2833 : :
2834 : 0 : return i;
2835 : : }
2836 : :
2837 : : static uint16_t
2838 : 0 : fpga_5gnr_dequeue_ldpc_dec(struct rte_bbdev_queue_data *q_data,
2839 : : struct rte_bbdev_dec_op **ops, uint16_t num)
2840 : : {
2841 : 0 : struct fpga_5gnr_queue *q = q_data->queue_private;
2842 : 0 : uint32_t avail = (q->tail - q->head_free_desc) & q->sw_ring_wrap_mask;
2843 : : uint16_t i;
2844 : : uint16_t dequeued_cbs = 0;
2845 : : int ret;
2846 : :
2847 [ # # # # ]: 0 : for (i = 0; (i < num) && (dequeued_cbs < avail); ++i) {
2848 [ # # ]: 0 : if (q->d->fpga_variant == VC_5GNR_FPGA_VARIANT)
2849 : 0 : ret = vc_5gnr_dequeue_ldpc_dec_one_op_cb(q, &ops[i], dequeued_cbs);
2850 : : else
2851 : 0 : ret = agx100_dequeue_ldpc_dec_one_op_cb(q, &ops[i], dequeued_cbs);
2852 : :
2853 [ # # ]: 0 : if (ret < 0)
2854 : : break;
2855 : :
2856 : 0 : dequeued_cbs += ret;
2857 : :
2858 : : rte_bbdev_log_debug("dequeuing dec ops [%d/%d] | head %d | tail %d",
2859 : : dequeued_cbs, num, q->head_free_desc, q->tail);
2860 : : }
2861 : :
2862 : : /* Update head */
2863 : 0 : q->head_free_desc = fpga_5gnr_desc_idx(q, dequeued_cbs);
2864 : :
2865 : : /* Update stats */
2866 : 0 : q_data->queue_stats.dequeued_count += i;
2867 : :
2868 : 0 : return i;
2869 : : }
2870 : :
2871 : :
2872 : : /* Initialization Function */
2873 : : static void
2874 : 0 : fpga_5gnr_fec_init(struct rte_bbdev *dev, struct rte_pci_driver *drv)
2875 : : {
2876 : 0 : struct rte_pci_device *pci_dev = RTE_DEV_TO_PCI(dev->device);
2877 : :
2878 : 0 : dev->dev_ops = &fpga_5gnr_ops;
2879 : 0 : dev->enqueue_ldpc_enc_ops = fpga_5gnr_enqueue_ldpc_enc;
2880 : 0 : dev->enqueue_ldpc_dec_ops = fpga_5gnr_enqueue_ldpc_dec;
2881 : 0 : dev->dequeue_ldpc_enc_ops = fpga_5gnr_dequeue_ldpc_enc;
2882 : 0 : dev->dequeue_ldpc_dec_ops = fpga_5gnr_dequeue_ldpc_dec;
2883 : :
2884 : : /* Device variant specific handling. */
2885 [ # # ]: 0 : if ((pci_dev->id.device_id == AGX100_PF_DEVICE_ID) ||
2886 : : (pci_dev->id.device_id == AGX100_VF_DEVICE_ID)) {
2887 : 0 : ((struct fpga_5gnr_fec_device *) dev->data->dev_private)->fpga_variant =
2888 : : AGX100_FPGA_VARIANT;
2889 : 0 : ((struct fpga_5gnr_fec_device *) dev->data->dev_private)->pf_device =
2890 : 0 : !strcmp(drv->driver.name, RTE_STR(FPGA_5GNR_FEC_PF_DRIVER_NAME));
2891 : 0 : ((struct fpga_5gnr_fec_device *) dev->data->dev_private)->mmio_base =
2892 : 0 : pci_dev->mem_resource[0].addr;
2893 : : /* Maximum number of queues possible for this device. */
2894 : 0 : ((struct fpga_5gnr_fec_device *) dev->data->dev_private)->total_num_queues =
2895 : : fpga_5gnr_reg_read_32(pci_dev->mem_resource[0].addr,
2896 : 0 : FPGA_5GNR_FEC_VERSION_ID) >> 24;
2897 : : } else {
2898 : 0 : ((struct fpga_5gnr_fec_device *) dev->data->dev_private)->fpga_variant =
2899 : : VC_5GNR_FPGA_VARIANT;
2900 : 0 : ((struct fpga_5gnr_fec_device *) dev->data->dev_private)->pf_device =
2901 : 0 : !strcmp(drv->driver.name, RTE_STR(FPGA_5GNR_FEC_PF_DRIVER_NAME));
2902 : 0 : ((struct fpga_5gnr_fec_device *) dev->data->dev_private)->mmio_base =
2903 : 0 : pci_dev->mem_resource[0].addr;
2904 : 0 : ((struct fpga_5gnr_fec_device *) dev->data->dev_private)->total_num_queues =
2905 : : VC_5GNR_TOTAL_NUM_QUEUES;
2906 : : }
2907 : :
2908 : : rte_bbdev_log_debug(
2909 : : "Init device %s [%s] @ virtaddr %p phyaddr %#"PRIx64,
2910 : : drv->driver.name, dev->data->name,
2911 : : (void *)pci_dev->mem_resource[0].addr,
2912 : : pci_dev->mem_resource[0].phys_addr);
2913 : 0 : }
2914 : :
2915 : : static int
2916 : 0 : fpga_5gnr_fec_probe(struct rte_pci_driver *pci_drv,
2917 : : struct rte_pci_device *pci_dev)
2918 : : {
2919 : : struct rte_bbdev *bbdev = NULL;
2920 : : char dev_name[RTE_BBDEV_NAME_MAX_LEN];
2921 : : struct fpga_5gnr_fec_device *d;
2922 : :
2923 [ # # ]: 0 : if (pci_dev == NULL) {
2924 : 0 : rte_bbdev_log(ERR, "NULL PCI device");
2925 : 0 : return -EINVAL;
2926 : : }
2927 : :
2928 : 0 : rte_pci_device_name(&pci_dev->addr, dev_name, sizeof(dev_name));
2929 : :
2930 : : /* Allocate memory to be used privately by drivers */
2931 : 0 : bbdev = rte_bbdev_allocate(pci_dev->device.name);
2932 [ # # ]: 0 : if (bbdev == NULL)
2933 : : return -ENODEV;
2934 : :
2935 : : /* allocate device private memory */
2936 : 0 : bbdev->data->dev_private = rte_zmalloc_socket(dev_name,
2937 : : sizeof(struct fpga_5gnr_fec_device),
2938 : : RTE_CACHE_LINE_SIZE,
2939 : : pci_dev->device.numa_node);
2940 : :
2941 [ # # ]: 0 : if (bbdev->data->dev_private == NULL) {
2942 : 0 : rte_bbdev_log(CRIT,
2943 : : "Allocate of %zu bytes for device \"%s\" failed",
2944 : : sizeof(struct fpga_5gnr_fec_device), dev_name);
2945 : 0 : rte_bbdev_release(bbdev);
2946 : 0 : return -ENOMEM;
2947 : : }
2948 : :
2949 : : /* Fill HW specific part of device structure */
2950 : 0 : bbdev->device = &pci_dev->device;
2951 : 0 : bbdev->intr_handle = pci_dev->intr_handle;
2952 : 0 : bbdev->data->socket_id = pci_dev->device.numa_node;
2953 : :
2954 : : /* Invoke FPGA 5GNR FEC device initialization function */
2955 : 0 : fpga_5gnr_fec_init(bbdev, pci_drv);
2956 : :
2957 : : rte_bbdev_log_debug("bbdev id = %u [%s]",
2958 : : bbdev->data->dev_id, dev_name);
2959 : :
2960 : : d = bbdev->data->dev_private;
2961 [ # # ]: 0 : if (d->fpga_variant == VC_5GNR_FPGA_VARIANT) {
2962 : 0 : uint32_t version_id = fpga_5gnr_reg_read_32(d->mmio_base, FPGA_5GNR_FEC_VERSION_ID);
2963 : 0 : rte_bbdev_log(INFO, "Vista Creek FPGA RTL v%u.%u",
2964 : : ((uint16_t)(version_id >> 16)), ((uint16_t)version_id));
2965 : : } else {
2966 : 0 : uint32_t version_num_queues = fpga_5gnr_reg_read_32(d->mmio_base,
2967 : : FPGA_5GNR_FEC_VERSION_ID);
2968 : 0 : uint8_t major_version_id = version_num_queues >> 16;
2969 : 0 : uint8_t minor_version_id = version_num_queues >> 8;
2970 : : uint8_t patch_id = version_num_queues;
2971 : :
2972 : 0 : rte_bbdev_log(INFO, "AGX100 RTL v%u.%u.%u",
2973 : : major_version_id, minor_version_id, patch_id);
2974 : : }
2975 : :
2976 : : #ifdef RTE_LIBRTE_BBDEV_DEBUG
2977 : : print_static_reg_debug_info(d->mmio_base, d->fpga_variant);
2978 : : #endif
2979 : : return 0;
2980 : : }
2981 : :
2982 : : static int
2983 : 0 : fpga_5gnr_fec_remove(struct rte_pci_device *pci_dev)
2984 : : {
2985 : : struct rte_bbdev *bbdev;
2986 : : int ret;
2987 : : uint8_t dev_id;
2988 : :
2989 [ # # ]: 0 : if (pci_dev == NULL)
2990 : : return -EINVAL;
2991 : :
2992 : : /* Find device */
2993 : 0 : bbdev = rte_bbdev_get_named_dev(pci_dev->device.name);
2994 [ # # ]: 0 : if (bbdev == NULL) {
2995 : 0 : rte_bbdev_log(CRIT,
2996 : : "Couldn't find HW dev \"%s\" to uninitialise it",
2997 : : pci_dev->device.name);
2998 : 0 : return -ENODEV;
2999 : : }
3000 : 0 : dev_id = bbdev->data->dev_id;
3001 : :
3002 : : /* free device private memory before close */
3003 : 0 : rte_free(bbdev->data->dev_private);
3004 : :
3005 : : /* Close device */
3006 : 0 : ret = rte_bbdev_close(dev_id);
3007 [ # # ]: 0 : if (ret < 0)
3008 : 0 : rte_bbdev_log(ERR,
3009 : : "Device %i failed to close during uninit: %i",
3010 : : dev_id, ret);
3011 : :
3012 : : /* release bbdev from library */
3013 : 0 : ret = rte_bbdev_release(bbdev);
3014 [ # # ]: 0 : if (ret)
3015 : 0 : rte_bbdev_log(ERR, "Device %i failed to uninit: %i", dev_id, ret);
3016 : :
3017 : : rte_bbdev_log_debug("Destroyed bbdev = %u", dev_id);
3018 : :
3019 : : return 0;
3020 : : }
3021 : :
3022 : : static inline void
3023 : : fpga_5gnr_set_default_conf(struct rte_fpga_5gnr_fec_conf *def_conf)
3024 : : {
3025 : : /* clear default configuration before initialization */
3026 : : memset(def_conf, 0, sizeof(struct rte_fpga_5gnr_fec_conf));
3027 : : /* Set pf mode to true */
3028 : 0 : def_conf->pf_mode_en = true;
3029 : :
3030 : : /* Set ratio between UL and DL to 1:1 (unit of weight is 3 CBs) */
3031 : 0 : def_conf->ul_bandwidth = 3;
3032 : 0 : def_conf->dl_bandwidth = 3;
3033 : :
3034 : : /* Set Load Balance Factor to 64 */
3035 : 0 : def_conf->dl_load_balance = 64;
3036 : 0 : def_conf->ul_load_balance = 64;
3037 : : }
3038 : :
3039 : : /* Initial configuration of Vista Creek device. */
3040 : 0 : static int vc_5gnr_configure(const char *dev_name, const struct rte_fpga_5gnr_fec_conf *conf)
3041 : : {
3042 : : uint32_t payload_32, address;
3043 : : uint16_t payload_16;
3044 : : uint8_t payload_8;
3045 : : uint16_t q_id, vf_id, total_q_id, total_ul_q_id, total_dl_q_id;
3046 : 0 : struct rte_bbdev *bbdev = rte_bbdev_get_named_dev(dev_name);
3047 : : struct rte_fpga_5gnr_fec_conf def_conf;
3048 : :
3049 [ # # ]: 0 : if (bbdev == NULL) {
3050 : 0 : rte_bbdev_log(ERR,
3051 : : "Invalid dev_name (%s), or device is not yet initialised",
3052 : : dev_name);
3053 : 0 : return -ENODEV;
3054 : : }
3055 : :
3056 : 0 : struct fpga_5gnr_fec_device *d = bbdev->data->dev_private;
3057 : :
3058 [ # # ]: 0 : if (conf == NULL) {
3059 : 0 : rte_bbdev_log(ERR, "VC FPGA Configuration was not provided.");
3060 : 0 : rte_bbdev_log(ERR, "Default configuration will be loaded.");
3061 : : fpga_5gnr_set_default_conf(&def_conf);
3062 : : conf = &def_conf;
3063 : : }
3064 : :
3065 : : /*
3066 : : * Configure UL:DL ratio.
3067 : : * [7:0]: UL weight
3068 : : * [15:8]: DL weight
3069 : : */
3070 : 0 : payload_16 = (conf->dl_bandwidth << 8) | conf->ul_bandwidth;
3071 : : address = VC_5GNR_CONFIGURATION;
3072 : 0 : fpga_5gnr_reg_write_16(d->mmio_base, address, payload_16);
3073 : :
3074 : : /* Clear all queues registers */
3075 : : payload_32 = FPGA_5GNR_INVALID_HW_QUEUE_ID;
3076 [ # # ]: 0 : for (q_id = 0; q_id < d->total_num_queues; ++q_id) {
3077 : 0 : address = (q_id << 2) + VC_5GNR_QUEUE_MAP;
3078 : : fpga_5gnr_reg_write_32(d->mmio_base, address, payload_32);
3079 : : }
3080 : :
3081 : : /*
3082 : : * If PF mode is enabled allocate all queues for PF only.
3083 : : *
3084 : : * For VF mode each VF can have different number of UL and DL queues.
3085 : : * Total number of queues to configure cannot exceed VC FPGA
3086 : : * capabilities - 64 queues - 32 queues for UL and 32 queues for DL.
3087 : : * Queues mapping is done according to configuration:
3088 : : *
3089 : : * UL queues:
3090 : : * | Q_ID | VF_ID |
3091 : : * | 0 | 0 |
3092 : : * | ... | 0 |
3093 : : * | conf->vf_dl_queues_number[0] - 1 | 0 |
3094 : : * | conf->vf_dl_queues_number[0] | 1 |
3095 : : * | ... | 1 |
3096 : : * | conf->vf_dl_queues_number[1] - 1 | 1 |
3097 : : * | ... | ... |
3098 : : * | conf->vf_dl_queues_number[7] - 1 | 7 |
3099 : : *
3100 : : * DL queues:
3101 : : * | Q_ID | VF_ID |
3102 : : * | 32 | 0 |
3103 : : * | ... | 0 |
3104 : : * | conf->vf_ul_queues_number[0] - 1 | 0 |
3105 : : * | conf->vf_ul_queues_number[0] | 1 |
3106 : : * | ... | 1 |
3107 : : * | conf->vf_ul_queues_number[1] - 1 | 1 |
3108 : : * | ... | ... |
3109 : : * | conf->vf_ul_queues_number[7] - 1 | 7 |
3110 : : *
3111 : : * Example of configuration:
3112 : : * conf->vf_ul_queues_number[0] = 4; -> 4 UL queues for VF0
3113 : : * conf->vf_dl_queues_number[0] = 4; -> 4 DL queues for VF0
3114 : : * conf->vf_ul_queues_number[1] = 2; -> 2 UL queues for VF1
3115 : : * conf->vf_dl_queues_number[1] = 2; -> 2 DL queues for VF1
3116 : : *
3117 : : * UL:
3118 : : * | Q_ID | VF_ID |
3119 : : * | 0 | 0 |
3120 : : * | 1 | 0 |
3121 : : * | 2 | 0 |
3122 : : * | 3 | 0 |
3123 : : * | 4 | 1 |
3124 : : * | 5 | 1 |
3125 : : *
3126 : : * DL:
3127 : : * | Q_ID | VF_ID |
3128 : : * | 32 | 0 |
3129 : : * | 33 | 0 |
3130 : : * | 34 | 0 |
3131 : : * | 35 | 0 |
3132 : : * | 36 | 1 |
3133 : : * | 37 | 1 |
3134 : : */
3135 [ # # ]: 0 : if (conf->pf_mode_en) {
3136 : : payload_32 = 0x1;
3137 [ # # ]: 0 : for (q_id = 0; q_id < d->total_num_queues; ++q_id) {
3138 : 0 : address = (q_id << 2) + VC_5GNR_QUEUE_MAP;
3139 : : fpga_5gnr_reg_write_32(d->mmio_base, address, payload_32);
3140 : : }
3141 : : } else {
3142 : : /* Calculate total number of UL and DL queues to configure */
3143 : : total_ul_q_id = total_dl_q_id = 0;
3144 [ # # ]: 0 : for (vf_id = 0; vf_id < FPGA_5GNR_FEC_NUM_VFS; ++vf_id) {
3145 : 0 : total_ul_q_id += conf->vf_ul_queues_number[vf_id];
3146 : 0 : total_dl_q_id += conf->vf_dl_queues_number[vf_id];
3147 : : }
3148 : 0 : total_q_id = total_dl_q_id + total_ul_q_id;
3149 : : /*
3150 : : * Check if total number of queues to configure does not exceed
3151 : : * FPGA capabilities (64 queues - 32 UL and 32 DL queues)
3152 : : */
3153 : 0 : if ((total_ul_q_id > VC_5GNR_NUM_UL_QUEUES) ||
3154 [ # # # # ]: 0 : (total_dl_q_id > VC_5GNR_NUM_DL_QUEUES) ||
3155 : : (total_q_id > d->total_num_queues)) {
3156 : 0 : rte_bbdev_log(ERR,
3157 : : "VC 5GNR FPGA Configuration failed. Too many queues to configure: UL_Q %u, DL_Q %u, FPGA_Q %u",
3158 : : total_ul_q_id, total_dl_q_id,
3159 : : d->total_num_queues);
3160 : 0 : return -EINVAL;
3161 : : }
3162 : : total_ul_q_id = 0;
3163 [ # # ]: 0 : for (vf_id = 0; vf_id < FPGA_5GNR_FEC_NUM_VFS; ++vf_id) {
3164 [ # # ]: 0 : for (q_id = 0; q_id < conf->vf_ul_queues_number[vf_id];
3165 : 0 : ++q_id, ++total_ul_q_id) {
3166 : 0 : address = (total_ul_q_id << 2) + VC_5GNR_QUEUE_MAP;
3167 : 0 : payload_32 = ((0x80 + vf_id) << 16) | 0x1;
3168 : : fpga_5gnr_reg_write_32(d->mmio_base, address,
3169 : : payload_32);
3170 : : }
3171 : : }
3172 : : total_dl_q_id = 0;
3173 [ # # ]: 0 : for (vf_id = 0; vf_id < FPGA_5GNR_FEC_NUM_VFS; ++vf_id) {
3174 [ # # ]: 0 : for (q_id = 0; q_id < conf->vf_dl_queues_number[vf_id];
3175 : 0 : ++q_id, ++total_dl_q_id) {
3176 : 0 : address = ((total_dl_q_id + VC_5GNR_NUM_UL_QUEUES)
3177 : 0 : << 2) + VC_5GNR_QUEUE_MAP;
3178 : 0 : payload_32 = ((0x80 + vf_id) << 16) | 0x1;
3179 : : fpga_5gnr_reg_write_32(d->mmio_base, address,
3180 : : payload_32);
3181 : : }
3182 : : }
3183 : : }
3184 : :
3185 : : /* Setting Load Balance Factor */
3186 : 0 : payload_16 = (conf->dl_load_balance << 8) | (conf->ul_load_balance);
3187 : : address = FPGA_5GNR_FEC_LOAD_BALANCE_FACTOR;
3188 : : fpga_5gnr_reg_write_16(d->mmio_base, address, payload_16);
3189 : :
3190 : : /* Setting length of ring descriptor entry */
3191 : : payload_16 = FPGA_5GNR_RING_DESC_ENTRY_LENGTH;
3192 : : address = FPGA_5GNR_FEC_RING_DESC_LEN;
3193 : : fpga_5gnr_reg_write_16(d->mmio_base, address, payload_16);
3194 : :
3195 : : /* Queue PF/VF mapping table is ready */
3196 : : payload_8 = 0x1;
3197 : : address = FPGA_5GNR_FEC_QUEUE_PF_VF_MAP_DONE;
3198 : : fpga_5gnr_reg_write_8(d->mmio_base, address, payload_8);
3199 : :
3200 : : rte_bbdev_log_debug("PF Vista Creek 5GNR FPGA configuration complete for %s", dev_name);
3201 : :
3202 : : #ifdef RTE_LIBRTE_BBDEV_DEBUG
3203 : : print_static_reg_debug_info(d->mmio_base, d->fpga_variant);
3204 : : #endif
3205 : 0 : return 0;
3206 : : }
3207 : :
3208 : : /* Initial configuration of AGX100 device. */
3209 : 0 : static int agx100_configure(const char *dev_name, const struct rte_fpga_5gnr_fec_conf *conf)
3210 : : {
3211 : : uint32_t payload_32, address;
3212 : : uint16_t payload_16;
3213 : : uint8_t payload_8;
3214 : : uint16_t q_id, vf_id, total_q_id, total_ul_q_id, total_dl_q_id;
3215 : 0 : struct rte_bbdev *bbdev = rte_bbdev_get_named_dev(dev_name);
3216 : : struct rte_fpga_5gnr_fec_conf def_conf;
3217 : :
3218 [ # # ]: 0 : if (bbdev == NULL) {
3219 : 0 : rte_bbdev_log(ERR,
3220 : : "Invalid dev_name (%s), or device is not yet initialised",
3221 : : dev_name);
3222 : 0 : return -ENODEV;
3223 : : }
3224 : :
3225 : 0 : struct fpga_5gnr_fec_device *d = bbdev->data->dev_private;
3226 : :
3227 [ # # ]: 0 : if (conf == NULL) {
3228 : 0 : rte_bbdev_log(ERR, "AGX100 Configuration was not provided.");
3229 : 0 : rte_bbdev_log(ERR, "Default configuration will be loaded.");
3230 : : fpga_5gnr_set_default_conf(&def_conf);
3231 : : conf = &def_conf;
3232 : : }
3233 : :
3234 : 0 : uint8_t total_num_queues = d->total_num_queues;
3235 : 0 : uint8_t num_ul_queues = total_num_queues >> 1;
3236 : : uint8_t num_dl_queues = total_num_queues >> 1;
3237 : :
3238 : : /* Clear all queues registers */
3239 : : payload_32 = FPGA_5GNR_INVALID_HW_QUEUE_ID;
3240 [ # # ]: 0 : for (q_id = 0; q_id < total_num_queues; ++q_id) {
3241 : 0 : address = (q_id << 2) + AGX100_QUEUE_MAP;
3242 : 0 : fpga_5gnr_reg_write_32(d->mmio_base, address, payload_32);
3243 : : }
3244 : :
3245 : : /*
3246 : : * If PF mode is enabled allocate all queues for PF only.
3247 : : *
3248 : : * For VF mode each VF can have different number of UL and DL queues.
3249 : : * Total number of queues to configure cannot exceed AGX100
3250 : : * capabilities - 64 queues - 32 queues for UL and 32 queues for DL.
3251 : : * Queues mapping is done according to configuration:
3252 : : *
3253 : : * UL queues:
3254 : : * | Q_ID | VF_ID |
3255 : : * | 0 | 0 |
3256 : : * | ... | 0 |
3257 : : * | conf->vf_dl_queues_number[0] - 1 | 0 |
3258 : : * | conf->vf_dl_queues_number[0] | 1 |
3259 : : * | ... | 1 |
3260 : : * | conf->vf_dl_queues_number[1] - 1 | 1 |
3261 : : * | ... | ... |
3262 : : * | conf->vf_dl_queues_number[7] - 1 | 7 |
3263 : : *
3264 : : * DL queues:
3265 : : * | Q_ID | VF_ID |
3266 : : * | 32 | 0 |
3267 : : * | ... | 0 |
3268 : : * | conf->vf_ul_queues_number[0] - 1 | 0 |
3269 : : * | conf->vf_ul_queues_number[0] | 1 |
3270 : : * | ... | 1 |
3271 : : * | conf->vf_ul_queues_number[1] - 1 | 1 |
3272 : : * | ... | ... |
3273 : : * | conf->vf_ul_queues_number[7] - 1 | 7 |
3274 : : *
3275 : : * Example of configuration:
3276 : : * conf->vf_ul_queues_number[0] = 4; -> 4 UL queues for VF0
3277 : : * conf->vf_dl_queues_number[0] = 4; -> 4 DL queues for VF0
3278 : : * conf->vf_ul_queues_number[1] = 2; -> 2 UL queues for VF1
3279 : : * conf->vf_dl_queues_number[1] = 2; -> 2 DL queues for VF1
3280 : : *
3281 : : * UL:
3282 : : * | Q_ID | VF_ID |
3283 : : * | 0 | 0 |
3284 : : * | 1 | 0 |
3285 : : * | 2 | 0 |
3286 : : * | 3 | 0 |
3287 : : * | 4 | 1 |
3288 : : * | 5 | 1 |
3289 : : *
3290 : : * DL:
3291 : : * | Q_ID | VF_ID |
3292 : : * | 32 | 0 |
3293 : : * | 33 | 0 |
3294 : : * | 34 | 0 |
3295 : : * | 35 | 0 |
3296 : : * | 36 | 1 |
3297 : : * | 37 | 1 |
3298 : : */
3299 [ # # ]: 0 : if (conf->pf_mode_en) {
3300 : : payload_32 = 0x1;
3301 [ # # ]: 0 : for (q_id = 0; q_id < total_num_queues; ++q_id) {
3302 : 0 : address = (q_id << 2) + AGX100_QUEUE_MAP;
3303 : 0 : fpga_5gnr_reg_write_32(d->mmio_base, address, payload_32);
3304 : : }
3305 : : } else {
3306 : : /* Calculate total number of UL and DL queues to configure. */
3307 : : total_ul_q_id = total_dl_q_id = 0;
3308 [ # # ]: 0 : for (vf_id = 0; vf_id < FPGA_5GNR_FEC_NUM_VFS; ++vf_id) {
3309 : 0 : total_ul_q_id += conf->vf_ul_queues_number[vf_id];
3310 : 0 : total_dl_q_id += conf->vf_dl_queues_number[vf_id];
3311 : : }
3312 : 0 : total_q_id = total_dl_q_id + total_ul_q_id;
3313 : : /*
3314 : : * Check if total number of queues to configure does not exceed
3315 : : * AGX100 capabilities (64 queues - 32 UL and 32 DL queues)
3316 : : */
3317 [ # # # # ]: 0 : if ((total_ul_q_id > num_ul_queues) ||
3318 [ # # ]: 0 : (total_dl_q_id > num_dl_queues) ||
3319 : : (total_q_id > total_num_queues)) {
3320 : 0 : rte_bbdev_log(ERR,
3321 : : "AGX100 Configuration failed. Too many queues to configure: UL_Q %u, DL_Q %u, AGX100_Q %u",
3322 : : total_ul_q_id, total_dl_q_id,
3323 : : total_num_queues);
3324 : 0 : return -EINVAL;
3325 : : }
3326 : : total_ul_q_id = 0;
3327 [ # # ]: 0 : for (vf_id = 0; vf_id < FPGA_5GNR_FEC_NUM_VFS; ++vf_id) {
3328 [ # # ]: 0 : for (q_id = 0; q_id < conf->vf_ul_queues_number[vf_id];
3329 : 0 : ++q_id, ++total_ul_q_id) {
3330 : 0 : address = (total_ul_q_id << 2) + AGX100_QUEUE_MAP;
3331 : 0 : payload_32 = ((0x80 + vf_id) << 16) | 0x1;
3332 : 0 : fpga_5gnr_reg_write_32(d->mmio_base, address, payload_32);
3333 : : }
3334 : : }
3335 : : total_dl_q_id = 0;
3336 [ # # ]: 0 : for (vf_id = 0; vf_id < FPGA_5GNR_FEC_NUM_VFS; ++vf_id) {
3337 [ # # ]: 0 : for (q_id = 0; q_id < conf->vf_dl_queues_number[vf_id];
3338 : 0 : ++q_id, ++total_dl_q_id) {
3339 : 0 : address = ((total_dl_q_id + num_ul_queues)
3340 : 0 : << 2) + AGX100_QUEUE_MAP;
3341 : 0 : payload_32 = ((0x80 + vf_id) << 16) | 0x1;
3342 : 0 : fpga_5gnr_reg_write_32(d->mmio_base, address, payload_32);
3343 : : }
3344 : : }
3345 : : }
3346 : :
3347 : : /* Setting Load Balance Factor. */
3348 : 0 : payload_16 = (conf->dl_load_balance << 8) | (conf->ul_load_balance);
3349 : : address = FPGA_5GNR_FEC_LOAD_BALANCE_FACTOR;
3350 : 0 : fpga_5gnr_reg_write_16(d->mmio_base, address, payload_16);
3351 : :
3352 : : /* Setting length of ring descriptor entry. */
3353 : : payload_16 = FPGA_5GNR_RING_DESC_ENTRY_LENGTH;
3354 : : address = FPGA_5GNR_FEC_RING_DESC_LEN;
3355 : : fpga_5gnr_reg_write_16(d->mmio_base, address, payload_16);
3356 : :
3357 : : /* Queue PF/VF mapping table is ready. */
3358 : : payload_8 = 0x1;
3359 : : address = FPGA_5GNR_FEC_QUEUE_PF_VF_MAP_DONE;
3360 : : fpga_5gnr_reg_write_8(d->mmio_base, address, payload_8);
3361 : :
3362 : : rte_bbdev_log_debug("PF AGX100 configuration complete for %s", dev_name);
3363 : :
3364 : : #ifdef RTE_LIBRTE_BBDEV_DEBUG
3365 : : print_static_reg_debug_info(d->mmio_base, d->fpga_variant);
3366 : : #endif
3367 : 0 : return 0;
3368 : : }
3369 : :
3370 : 0 : int rte_fpga_5gnr_fec_configure(const char *dev_name, const struct rte_fpga_5gnr_fec_conf *conf)
3371 : : {
3372 : 0 : struct rte_bbdev *bbdev = rte_bbdev_get_named_dev(dev_name);
3373 [ # # ]: 0 : if (bbdev == NULL) {
3374 : 0 : rte_bbdev_log(ERR, "Invalid dev_name (%s), or device is not yet initialised",
3375 : : dev_name);
3376 : 0 : return -ENODEV;
3377 : : }
3378 : 0 : struct rte_pci_device *pci_dev = RTE_DEV_TO_PCI(bbdev->device);
3379 : 0 : rte_bbdev_log(INFO, "Configure dev id %x\n", pci_dev->id.device_id);
3380 [ # # ]: 0 : if (pci_dev->id.device_id == VC_5GNR_PF_DEVICE_ID)
3381 : 0 : return vc_5gnr_configure(dev_name, conf);
3382 [ # # ]: 0 : else if (pci_dev->id.device_id == AGX100_PF_DEVICE_ID)
3383 : 0 : return agx100_configure(dev_name, conf);
3384 : :
3385 : 0 : rte_bbdev_log(ERR, "Invalid device_id (%d)", pci_dev->id.device_id);
3386 : 0 : return -ENODEV;
3387 : : }
3388 : :
3389 : : /* FPGA 5GNR FEC PCI PF address map */
3390 : : static struct rte_pci_id pci_id_fpga_5gnr_fec_pf_map[] = {
3391 : : {
3392 : : RTE_PCI_DEVICE(AGX100_VENDOR_ID, AGX100_PF_DEVICE_ID)
3393 : : },
3394 : : {
3395 : : RTE_PCI_DEVICE(VC_5GNR_VENDOR_ID, VC_5GNR_PF_DEVICE_ID)
3396 : : },
3397 : : {.device_id = 0},
3398 : : };
3399 : :
3400 : : static struct rte_pci_driver fpga_5gnr_fec_pci_pf_driver = {
3401 : : .probe = fpga_5gnr_fec_probe,
3402 : : .remove = fpga_5gnr_fec_remove,
3403 : : .id_table = pci_id_fpga_5gnr_fec_pf_map,
3404 : : .drv_flags = RTE_PCI_DRV_NEED_MAPPING
3405 : : };
3406 : :
3407 : : /* FPGA 5GNR FEC PCI VF address map */
3408 : : static struct rte_pci_id pci_id_fpga_5gnr_fec_vf_map[] = {
3409 : : {
3410 : : RTE_PCI_DEVICE(AGX100_VENDOR_ID, AGX100_VF_DEVICE_ID)
3411 : : },
3412 : : {
3413 : : RTE_PCI_DEVICE(VC_5GNR_VENDOR_ID, VC_5GNR_VF_DEVICE_ID)
3414 : : },
3415 : : {.device_id = 0},
3416 : : };
3417 : :
3418 : : static struct rte_pci_driver fpga_5gnr_fec_pci_vf_driver = {
3419 : : .probe = fpga_5gnr_fec_probe,
3420 : : .remove = fpga_5gnr_fec_remove,
3421 : : .id_table = pci_id_fpga_5gnr_fec_vf_map,
3422 : : .drv_flags = RTE_PCI_DRV_NEED_MAPPING
3423 : : };
3424 : :
3425 : :
3426 : 238 : RTE_PMD_REGISTER_PCI(FPGA_5GNR_FEC_PF_DRIVER_NAME, fpga_5gnr_fec_pci_pf_driver);
3427 : : RTE_PMD_REGISTER_PCI_TABLE(FPGA_5GNR_FEC_PF_DRIVER_NAME, pci_id_fpga_5gnr_fec_pf_map);
3428 : 238 : RTE_PMD_REGISTER_PCI(FPGA_5GNR_FEC_VF_DRIVER_NAME, fpga_5gnr_fec_pci_vf_driver);
3429 : : RTE_PMD_REGISTER_PCI_TABLE(FPGA_5GNR_FEC_VF_DRIVER_NAME, pci_id_fpga_5gnr_fec_vf_map);
|