Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright(c) 2023 Napatech A/S
3 : : */
4 : :
5 : : #include "rte_spinlock.h"
6 : : #include "nt_util.h"
7 : : #include "ntlog.h"
8 : :
9 : : #include "nthw_drv.h"
10 : : #include "nthw_register.h"
11 : : #include "nthw_rac.h"
12 : :
13 : : #define RAB_DMA_WAIT (1000000)
14 : :
15 : : #define RAB_READ (0x01)
16 : : #define RAB_WRITE (0x02)
17 : : #define RAB_ECHO (0x08)
18 : : #define RAB_COMPLETION (0x0F)
19 : :
20 : : #define RAB_OPR_LO (28)
21 : :
22 : : #define RAB_CNT_LO (20)
23 : : #define RAB_CNT_BW (8)
24 : :
25 : : #define RAB_BUSID_LO (16)
26 : : #define RAB_BUSID_BW (4)
27 : :
28 : : #define RAB_ADDR_BW (16)
29 : :
30 : 0 : nthw_rac_t *nthw_rac_new(void)
31 : : {
32 : 0 : nthw_rac_t *p = malloc(sizeof(nthw_rac_t));
33 : :
34 [ # # ]: 0 : if (p)
35 : : memset(p, 0, sizeof(nthw_rac_t));
36 : :
37 : 0 : return p;
38 : : }
39 : :
40 : 0 : int nthw_rac_init(nthw_rac_t *p, nthw_fpga_t *p_fpga, struct fpga_info_s *p_fpga_info)
41 : : {
42 : : RTE_ASSERT(p_fpga_info);
43 : :
44 : 0 : const char *const p_adapter_id_str = p_fpga_info->mp_adapter_id_str;
45 : 0 : nthw_module_t *p_mod = nthw_fpga_query_module(p_fpga, MOD_RAC, 0);
46 : :
47 [ # # ]: 0 : if (p == NULL)
48 [ # # ]: 0 : return p_mod == NULL ? -1 : 0;
49 : :
50 [ # # ]: 0 : if (p_mod == NULL) {
51 : 0 : NT_LOG(ERR, NTHW, "%s: RAC %d: no such instance", p_adapter_id_str, 0);
52 : 0 : return -1;
53 : : }
54 : :
55 : 0 : p->mp_fpga = p_fpga;
56 : 0 : p->mp_mod_rac = p_mod;
57 : :
58 : 0 : p->mn_param_rac_rab_interfaces =
59 : 0 : nthw_fpga_get_product_param(p->mp_fpga, NT_RAC_RAB_INTERFACES, 3);
60 : 0 : NT_LOG(DBG, NTHW, "%s: NT_RAC_RAB_INTERFACES=%d", p_adapter_id_str,
61 : : p->mn_param_rac_rab_interfaces);
62 : :
63 : 0 : p->mn_param_rac_rab_ob_update =
64 : 0 : nthw_fpga_get_product_param(p->mp_fpga, NT_RAC_RAB_OB_UPDATE, 0);
65 : 0 : NT_LOG(DBG, NTHW, "%s: NT_RAC_RAB_OB_UPDATE=%d", p_adapter_id_str,
66 : : p->mn_param_rac_rab_ob_update);
67 : :
68 : : /* Optional dummy test registers */
69 : 0 : p->mp_reg_dummy0 = nthw_module_query_register(p->mp_mod_rac, RAC_DUMMY0);
70 : 0 : p->mp_reg_dummy1 = nthw_module_query_register(p->mp_mod_rac, RAC_DUMMY1);
71 : 0 : p->mp_reg_dummy2 = nthw_module_query_register(p->mp_mod_rac, RAC_DUMMY2);
72 : :
73 : 0 : p->mp_reg_rab_init = nthw_module_get_register(p->mp_mod_rac, RAC_RAB_INIT);
74 : 0 : p->mp_fld_rab_init = nthw_register_get_field(p->mp_reg_rab_init, RAC_RAB_INIT_RAB);
75 : 0 : p->mn_fld_rab_init_bw = nthw_field_get_bit_width(p->mp_fld_rab_init);
76 : 0 : p->mn_fld_rab_init_mask = nthw_field_get_mask(p->mp_fld_rab_init);
77 : :
78 : : /* RAC_RAB_INIT_RAB reg/field sanity checks: */
79 : : RTE_ASSERT(p->mn_fld_rab_init_mask == ((1UL << p->mn_fld_rab_init_bw) - 1));
80 : : RTE_ASSERT(p->mn_fld_rab_init_bw == p->mn_param_rac_rab_interfaces);
81 : :
82 : 0 : p->mp_reg_dbg_ctrl = nthw_module_query_register(p->mp_mod_rac, RAC_DBG_CTRL);
83 : :
84 [ # # ]: 0 : if (p->mp_reg_dbg_ctrl)
85 : 0 : p->mp_fld_dbg_ctrl = nthw_register_query_field(p->mp_reg_dbg_ctrl, RAC_DBG_CTRL_C);
86 : :
87 : : else
88 : 0 : p->mp_fld_dbg_ctrl = NULL;
89 : :
90 : 0 : p->mp_reg_dbg_data = nthw_module_query_register(p->mp_mod_rac, RAC_DBG_DATA);
91 : :
92 [ # # ]: 0 : if (p->mp_reg_dbg_data)
93 : 0 : p->mp_fld_dbg_data = nthw_register_query_field(p->mp_reg_dbg_data, RAC_DBG_DATA_D);
94 : :
95 : 0 : p->mp_reg_rab_ib_data = nthw_module_get_register(p->mp_mod_rac, RAC_RAB_IB_DATA);
96 : 0 : p->mp_fld_rab_ib_data = nthw_register_get_field(p->mp_reg_rab_ib_data, RAC_RAB_IB_DATA_D);
97 : :
98 : 0 : p->mp_reg_rab_ob_data = nthw_module_get_register(p->mp_mod_rac, RAC_RAB_OB_DATA);
99 : 0 : p->mp_fld_rab_ob_data = nthw_register_get_field(p->mp_reg_rab_ob_data, RAC_RAB_OB_DATA_D);
100 : :
101 : 0 : p->mp_reg_rab_buf_free = nthw_module_get_register(p->mp_mod_rac, RAC_RAB_BUF_FREE);
102 : 0 : p->mp_fld_rab_buf_free_ib_free =
103 : 0 : nthw_register_get_field(p->mp_reg_rab_buf_free, RAC_RAB_BUF_FREE_IB_FREE);
104 : 0 : p->mp_fld_rab_buf_free_ib_ovf =
105 : 0 : nthw_register_get_field(p->mp_reg_rab_buf_free, RAC_RAB_BUF_FREE_IB_OVF);
106 : 0 : p->mp_fld_rab_buf_free_ob_free =
107 : 0 : nthw_register_get_field(p->mp_reg_rab_buf_free, RAC_RAB_BUF_FREE_OB_FREE);
108 : 0 : p->mp_fld_rab_buf_free_ob_ovf =
109 : 0 : nthw_register_get_field(p->mp_reg_rab_buf_free, RAC_RAB_BUF_FREE_OB_OVF);
110 : 0 : p->mp_fld_rab_buf_free_timeout =
111 : 0 : nthw_register_get_field(p->mp_reg_rab_buf_free, RAC_RAB_BUF_FREE_TIMEOUT);
112 : :
113 : 0 : p->mp_reg_rab_buf_used = nthw_module_get_register(p->mp_mod_rac, RAC_RAB_BUF_USED);
114 : 0 : p->mp_fld_rab_buf_used_ib_used =
115 : 0 : nthw_register_get_field(p->mp_reg_rab_buf_used, RAC_RAB_BUF_USED_IB_USED);
116 : 0 : p->mp_fld_rab_buf_used_ob_used =
117 : 0 : nthw_register_get_field(p->mp_reg_rab_buf_used, RAC_RAB_BUF_USED_OB_USED);
118 : 0 : p->mp_fld_rab_buf_used_flush =
119 : 0 : nthw_register_get_field(p->mp_reg_rab_buf_used, RAC_RAB_BUF_USED_FLUSH);
120 : :
121 : : /*
122 : : * RAC_RAB_DMA regs are optional - only found in real
123 : : * NT4GA - not found in 9231/9232 and earlier
124 : : */
125 : 0 : p->mp_reg_rab_dma_ib_lo = nthw_module_get_register(p->mp_mod_rac, RAC_RAB_DMA_IB_LO);
126 : 0 : p->mp_fld_rab_dma_ib_lo_phy_addr =
127 : 0 : nthw_register_get_field(p->mp_reg_rab_dma_ib_lo, RAC_RAB_DMA_IB_LO_PHYADDR);
128 : :
129 : 0 : p->mp_reg_rab_dma_ib_hi = nthw_module_get_register(p->mp_mod_rac, RAC_RAB_DMA_IB_HI);
130 : 0 : p->mp_fld_rab_dma_ib_hi_phy_addr =
131 : 0 : nthw_register_get_field(p->mp_reg_rab_dma_ib_hi, RAC_RAB_DMA_IB_HI_PHYADDR);
132 : :
133 : 0 : p->mp_reg_rab_dma_ob_lo = nthw_module_get_register(p->mp_mod_rac, RAC_RAB_DMA_OB_LO);
134 : 0 : p->mp_fld_rab_dma_ob_lo_phy_addr =
135 : 0 : nthw_register_get_field(p->mp_reg_rab_dma_ob_lo, RAC_RAB_DMA_OB_LO_PHYADDR);
136 : :
137 : 0 : p->mp_reg_rab_dma_ob_hi = nthw_module_get_register(p->mp_mod_rac, RAC_RAB_DMA_OB_HI);
138 : 0 : p->mp_fld_rab_dma_ob_hi_phy_addr =
139 : 0 : nthw_register_get_field(p->mp_reg_rab_dma_ob_hi, RAC_RAB_DMA_OB_HI_PHYADDR);
140 : :
141 : 0 : p->mp_reg_rab_dma_ib_wr = nthw_module_get_register(p->mp_mod_rac, RAC_RAB_DMA_IB_WR);
142 : 0 : p->mp_fld_rab_dma_ib_wr_ptr =
143 : 0 : nthw_register_get_field(p->mp_reg_rab_dma_ib_wr, RAC_RAB_DMA_IB_WR_PTR);
144 : :
145 : 0 : p->mp_reg_rab_dma_ib_rd = nthw_module_get_register(p->mp_mod_rac, RAC_RAB_DMA_IB_RD);
146 : 0 : p->mp_fld_rab_dma_ib_rd_ptr =
147 : 0 : nthw_register_get_field(p->mp_reg_rab_dma_ib_rd, RAC_RAB_DMA_IB_RD_PTR);
148 : :
149 : 0 : p->mp_reg_rab_dma_ob_wr = nthw_module_get_register(p->mp_mod_rac, RAC_RAB_DMA_OB_WR);
150 : 0 : p->mp_fld_rab_dma_ob_wr_ptr =
151 : 0 : nthw_register_get_field(p->mp_reg_rab_dma_ob_wr, RAC_RAB_DMA_OB_WR_PTR);
152 : :
153 : 0 : p->RAC_RAB_INIT_ADDR = nthw_register_get_address(p->mp_reg_rab_init);
154 : 0 : p->RAC_RAB_IB_DATA_ADDR = nthw_register_get_address(p->mp_reg_rab_ib_data);
155 : 0 : p->RAC_RAB_OB_DATA_ADDR = nthw_register_get_address(p->mp_reg_rab_ob_data);
156 : 0 : p->RAC_RAB_BUF_FREE_ADDR = nthw_register_get_address(p->mp_reg_rab_buf_free);
157 : 0 : p->RAC_RAB_BUF_USED_ADDR = nthw_register_get_address(p->mp_reg_rab_buf_used);
158 : :
159 : : /*
160 : : * RAC_RAB_DMA regs are optional - only found in real NT4GA - not found in 9231/9232 and
161 : : * earlier
162 : : */
163 : :
164 : 0 : p->RAC_RAB_DMA_IB_LO_ADDR = nthw_register_get_address(p->mp_reg_rab_dma_ib_lo);
165 : 0 : p->RAC_RAB_DMA_IB_HI_ADDR = nthw_register_get_address(p->mp_reg_rab_dma_ib_hi);
166 : 0 : p->RAC_RAB_DMA_OB_LO_ADDR = nthw_register_get_address(p->mp_reg_rab_dma_ob_lo);
167 : 0 : p->RAC_RAB_DMA_OB_HI_ADDR = nthw_register_get_address(p->mp_reg_rab_dma_ob_hi);
168 : 0 : p->RAC_RAB_DMA_IB_RD_ADDR = nthw_register_get_address(p->mp_reg_rab_dma_ib_rd);
169 : 0 : p->RAC_RAB_DMA_OB_WR_ADDR = nthw_register_get_address(p->mp_reg_rab_dma_ob_wr);
170 : 0 : p->RAC_RAB_DMA_IB_WR_ADDR = nthw_register_get_address(p->mp_reg_rab_dma_ib_wr);
171 : :
172 : 0 : p->RAC_RAB_BUF_FREE_IB_FREE_MASK = nthw_field_get_mask(p->mp_fld_rab_buf_free_ib_free);
173 : 0 : p->RAC_RAB_BUF_FREE_OB_FREE_MASK = nthw_field_get_mask(p->mp_fld_rab_buf_free_ob_free);
174 : 0 : p->RAC_RAB_BUF_USED_IB_USED_MASK = nthw_field_get_mask(p->mp_fld_rab_buf_used_ib_used);
175 : 0 : p->RAC_RAB_BUF_USED_OB_USED_MASK = nthw_field_get_mask(p->mp_fld_rab_buf_used_ob_used);
176 : :
177 : 0 : p->RAC_RAB_BUF_USED_FLUSH_MASK = nthw_field_get_mask(p->mp_fld_rab_buf_used_flush);
178 : :
179 : 0 : p->RAC_RAB_BUF_USED_OB_USED_LOW =
180 : 0 : nthw_field_get_bit_pos_low(p->mp_fld_rab_buf_used_ob_used);
181 : :
182 : 0 : p->mp_reg_rab_nmb_rd = nthw_module_query_register(p->mp_mod_rac, RAC_NMB_RD_ADR);
183 : :
184 [ # # ]: 0 : if (p->mp_reg_rab_nmb_rd)
185 : 0 : p->RAC_NMB_RD_ADR_ADDR = nthw_register_get_address(p->mp_reg_rab_nmb_rd);
186 : :
187 : 0 : p->mp_reg_rab_nmb_data = nthw_module_query_register(p->mp_mod_rac, RAC_NMB_DATA);
188 : :
189 [ # # ]: 0 : if (p->mp_reg_rab_nmb_data)
190 : 0 : p->RAC_NMB_DATA_ADDR = nthw_register_get_address(p->mp_reg_rab_nmb_data);
191 : :
192 : 0 : p->mp_reg_rab_nmb_wr = nthw_module_query_register(p->mp_mod_rac, RAC_NMB_WR_ADR);
193 : :
194 [ # # ]: 0 : if (p->mp_reg_rab_nmb_wr)
195 : 0 : p->RAC_NMB_WR_ADR_ADDR = nthw_register_get_address(p->mp_reg_rab_nmb_wr);
196 : :
197 : 0 : p->mp_reg_rab_nmb_status = nthw_module_query_register(p->mp_mod_rac, RAC_NMB_STATUS);
198 : :
199 [ # # ]: 0 : if (p->mp_reg_rab_nmb_status)
200 : 0 : p->RAC_NMB_STATUS_ADDR = nthw_register_get_address(p->mp_reg_rab_nmb_status);
201 : :
202 : 0 : p->m_dma = NULL;
203 : :
204 : : {
205 : : /*
206 : : * RAC is a primary communication channel - debug will be messy
207 : : * turn off debug by default - except for rac_rab_init
208 : : * NOTE: currently debug will not work - due to optimizations
209 : : */
210 : 0 : const int n_debug_mode = nthw_module_get_debug_mode(p->mp_mod_rac);
211 : :
212 [ # # ]: 0 : if (n_debug_mode && n_debug_mode <= 0xff) {
213 : 0 : nthw_module_set_debug_mode(p->mp_mod_rac, 0);
214 : 0 : nthw_register_set_debug_mode(p->mp_reg_rab_init, n_debug_mode);
215 : : }
216 : : }
217 : :
218 : : rte_spinlock_init(&p->m_mutex);
219 : :
220 : 0 : return 0;
221 : : }
222 : :
223 : : static int nthw_rac_get_rab_interface_count(const nthw_rac_t *p)
224 : : {
225 : 0 : return p->mn_param_rac_rab_interfaces;
226 : : }
227 : :
228 : : /* private function for internal RAC operations -
229 : : * improves log flexibility and prevents log flooding
230 : : */
231 : : static void nthw_rac_reg_read32(const struct fpga_info_s *p_fpga_info, uint32_t reg_addr,
232 : : uint32_t *p_data)
233 : : {
234 : 0 : *p_data = *(volatile uint32_t *)((uint8_t *)p_fpga_info->bar0_addr + reg_addr);
235 : : }
236 : :
237 : : /* private function for internal RAC operations -
238 : : * improves log flexibility and prevents log flooding
239 : : */
240 : : static void nthw_rac_reg_write32(const struct fpga_info_s *p_fpga_info, uint32_t reg_addr,
241 : : uint32_t n_data)
242 : : {
243 : 0 : *(volatile uint32_t *)((uint8_t *)p_fpga_info->bar0_addr + reg_addr) = n_data;
244 : 0 : }
245 : :
246 : 0 : static inline int _nthw_rac_wait_for_rab_done(const nthw_rac_t *p, uint32_t address,
247 : : uint32_t word_cnt)
248 : : {
249 : 0 : const struct fpga_info_s *const p_fpga_info = p->mp_fpga->p_fpga_info;
250 : 0 : const char *const p_adapter_id_str = p_fpga_info->mp_adapter_id_str;
251 : : uint32_t used = 0;
252 : : uint32_t retry;
253 : :
254 [ # # ]: 0 : for (retry = 0; retry < 100000; retry++) {
255 : 0 : nthw_rac_reg_read32(p_fpga_info, p->RAC_RAB_BUF_USED_ADDR, &used);
256 : 0 : used = (used & p->RAC_RAB_BUF_USED_OB_USED_MASK) >>
257 : 0 : p->RAC_RAB_BUF_USED_OB_USED_LOW;
258 : :
259 [ # # ]: 0 : if (used >= word_cnt)
260 : : break;
261 : : }
262 : :
263 [ # # ]: 0 : if (used < word_cnt) {
264 : 0 : NT_LOG(ERR, NTHW, "%s: Fail rab bus r/w addr=0x%08X used=%x wordcount=%" PRIu32 "",
265 : : p_adapter_id_str, address, used, word_cnt);
266 : 0 : return -1;
267 : : }
268 : :
269 : : return 0;
270 : : }
271 : :
272 : : /*
273 : : * NT_PCI_REG_P9xyz_RAC_RAB_INIT
274 : : *
275 : : * Initializes (resets) the programmable registers on the Register Access Buses (RAB).
276 : : * This initialization must be performed by software as part of the driver load procedure.
277 : : *
278 : : * Bit n of this field initializes the programmable registers on RAB interface n.
279 : : * Software must write one to the bit and then clear the bit again.
280 : : *
281 : : * All RAB module registers will be reset to their defaults.
282 : : * This includes the product specific RESET module (eg RST9xyz)
283 : : * As a consequence of this behavior the official reset sequence
284 : : * must be excersised - as all RAB modules will be held in reset.
285 : : */
286 : 0 : int nthw_rac_rab_init(nthw_rac_t *p, uint32_t n_rab_intf_mask)
287 : : {
288 : : /*
289 : : * Write rac_rab_init
290 : : * Perform operation twice - first to get trace of operation -
291 : : * second to get things done...
292 : : */
293 : 0 : const struct fpga_info_s *const p_fpga_info = p->mp_fpga->p_fpga_info;
294 : 0 : nthw_field_set_val_flush32(p->mp_fld_rab_init, n_rab_intf_mask);
295 : 0 : nthw_rac_reg_write32(p_fpga_info, p->RAC_RAB_INIT_ADDR, n_rab_intf_mask);
296 : 0 : return 0;
297 : : }
298 : :
299 : 0 : int nthw_rac_rab_reset(nthw_rac_t *p)
300 : : {
301 : 0 : const struct fpga_info_s *const p_fpga_info = p->mp_fpga->p_fpga_info;
302 : 0 : const char *const p_adapter_id_str = p_fpga_info->mp_adapter_id_str;
303 : : (void)p_adapter_id_str;
304 : :
305 : : /* RAC RAB bus "flip/flip" reset */
306 : : const int n_rac_rab_bus_count = nthw_rac_get_rab_interface_count(p);
307 : 0 : const int n_rac_rab_bus_mask = (1 << n_rac_rab_bus_count) - 1;
308 : :
309 : 0 : NT_LOG(DBG, NTHW, "%s: NT_RAC_RAB_INTERFACES=%d (0x%02X)", p_adapter_id_str,
310 : : n_rac_rab_bus_count, n_rac_rab_bus_mask);
311 : : RTE_ASSERT(n_rac_rab_bus_count);
312 : : RTE_ASSERT(n_rac_rab_bus_mask);
313 : :
314 : : /* RAC RAB bus "flip/flip" reset first stage - new impl (ref RMT#37020) */
315 : 0 : nthw_rac_rab_init(p, 0);
316 : 0 : nthw_rac_rab_init(p, n_rac_rab_bus_mask);
317 : 0 : nthw_rac_rab_init(p, n_rac_rab_bus_mask & ~0x01);
318 : :
319 : 0 : return 0;
320 : : }
321 : :
322 : 0 : int nthw_rac_rab_setup(nthw_rac_t *p)
323 : : {
324 : : int rc = 0;
325 : :
326 : 0 : const struct fpga_info_s *const p_fpga_info = p->mp_fpga->p_fpga_info;
327 : : uint32_t n_dma_buf_size = 2L * RAB_DMA_BUF_CNT * sizeof(uint32_t);
328 : 0 : const size_t align_size = nthw_util_align_size(n_dma_buf_size);
329 : 0 : int numa_node = p_fpga_info->numa_node;
330 : : uint64_t dma_addr;
331 : : uint32_t buf;
332 : :
333 [ # # ]: 0 : if (!p->m_dma) {
334 : : struct nt_dma_s *vfio_dma;
335 : : /* FPGA needs Page alignment (4K) */
336 : 0 : vfio_dma = nthw_dma_alloc(align_size, 0x1000, numa_node);
337 : :
338 [ # # ]: 0 : if (vfio_dma == NULL) {
339 : 0 : NT_LOG(ERR, NTNIC, "nthw_dma_alloc failed");
340 : 0 : return -1;
341 : : }
342 : :
343 : 0 : p->m_dma_in_buf = (uint32_t *)vfio_dma->addr;
344 : 0 : p->m_dma_out_buf = p->m_dma_in_buf + RAB_DMA_BUF_CNT;
345 : 0 : p->m_dma = vfio_dma;
346 : : }
347 : :
348 : : /* Setup DMA on the adapter */
349 : 0 : dma_addr = p->m_dma->iova;
350 : 0 : nthw_rac_reg_write32(p_fpga_info, p->RAC_RAB_DMA_IB_LO_ADDR, dma_addr & 0xffffffff);
351 : 0 : nthw_rac_reg_write32(p_fpga_info, p->RAC_RAB_DMA_IB_HI_ADDR,
352 : 0 : (uint32_t)(dma_addr >> 32) & 0xffffffff);
353 : 0 : dma_addr += RAB_DMA_BUF_CNT * sizeof(uint32_t);
354 : 0 : nthw_rac_reg_write32(p_fpga_info, p->RAC_RAB_DMA_OB_LO_ADDR, dma_addr & 0xffffffff);
355 : 0 : nthw_rac_reg_write32(p_fpga_info, p->RAC_RAB_DMA_OB_HI_ADDR,
356 : 0 : (uint32_t)(dma_addr >> 32) & 0xffffffff);
357 : :
358 : : /* Set initial value of internal pointers */
359 : 0 : nthw_rac_reg_read32(p_fpga_info, p->RAC_RAB_DMA_IB_RD_ADDR, &buf);
360 : 0 : p->m_dma_in_ptr_wr = (uint16_t)(buf / sizeof(uint32_t));
361 : 0 : nthw_rac_reg_read32(p_fpga_info, p->RAC_RAB_DMA_OB_WR_ADDR, &buf);
362 : 0 : p->m_dma_out_ptr_rd = (uint16_t)(buf / sizeof(uint32_t));
363 : 0 : p->m_in_free = RAB_DMA_BUF_CNT;
364 : :
365 : 0 : return rc;
366 : : }
367 : :
368 : 0 : void nthw_rac_bar0_read32(const struct fpga_info_s *p_fpga_info, uint32_t reg_addr,
369 : : uint32_t word_cnt, uint32_t *p_data)
370 : : {
371 : : volatile const uint32_t *const src_addr =
372 : 0 : (uint32_t *)((uint8_t *)p_fpga_info->bar0_addr + reg_addr);
373 : :
374 [ # # ]: 0 : for (uint32_t i = 0; i < word_cnt; i++)
375 : 0 : p_data[i] = src_addr[i];
376 : 0 : }
377 : :
378 : 0 : void nthw_rac_bar0_write32(const struct fpga_info_s *p_fpga_info, uint32_t reg_addr,
379 : : uint32_t word_cnt, const uint32_t *p_data)
380 : : {
381 : : volatile uint32_t *const dst_addr =
382 : 0 : (uint32_t *)((uint8_t *)p_fpga_info->bar0_addr + reg_addr);
383 : :
384 [ # # ]: 0 : for (uint32_t i = 0; i < word_cnt; i++)
385 : 0 : dst_addr[i] = p_data[i];
386 : 0 : }
387 : :
388 : 0 : int nthw_rac_rab_dma_begin(nthw_rac_t *p)
389 : : {
390 : 0 : p->m_dma_active = true;
391 : :
392 : 0 : return 0;
393 : : }
394 : :
395 : 0 : static void nthw_rac_rab_dma_activate(nthw_rac_t *p)
396 : : {
397 : 0 : const struct fpga_info_s *const p_fpga_info = p->mp_fpga->p_fpga_info;
398 : : const uint32_t completion = RAB_COMPLETION << RAB_OPR_LO;
399 : :
400 : : /* Write completion word */
401 : 0 : p->m_dma_in_buf[p->m_dma_in_ptr_wr] = completion;
402 : 0 : p->m_dma_in_ptr_wr = (uint16_t)((p->m_dma_in_ptr_wr + 1) & (RAB_DMA_BUF_CNT - 1));
403 : :
404 : : /* Clear output completion word */
405 : 0 : p->m_dma_out_buf[p->m_dma_out_ptr_rd] = 0;
406 : :
407 : : /* Update DMA pointer and start transfer */
408 : 0 : nthw_rac_reg_write32(p_fpga_info, p->RAC_RAB_DMA_IB_WR_ADDR,
409 : 0 : (uint32_t)(p->m_dma_in_ptr_wr * sizeof(uint32_t)));
410 : 0 : }
411 : :
412 : 0 : static int nthw_rac_rab_dma_wait(nthw_rac_t *p)
413 : : {
414 : 0 : const struct fpga_info_s *const p_fpga_info = p->mp_fpga->p_fpga_info;
415 : 0 : const char *const p_adapter_id_str = p_fpga_info->mp_adapter_id_str;
416 : : const uint32_t completion = RAB_COMPLETION << RAB_OPR_LO;
417 : : uint32_t i;
418 : :
419 [ # # ]: 0 : for (i = 0; i < RAB_DMA_WAIT; i++) {
420 : 0 : nthw_os_wait_usec_poll(1);
421 : :
422 [ # # ]: 0 : if ((p->m_dma_out_buf[p->m_dma_out_ptr_rd] & completion) == completion)
423 : : break;
424 : : }
425 : :
426 [ # # ]: 0 : if (i == RAB_DMA_WAIT) {
427 : 0 : NT_LOG(ERR, NTHW, "%s: RAB: Unexpected value of completion (0x%08X)",
428 : : p_adapter_id_str, p->m_dma_out_buf[p->m_dma_out_ptr_rd]);
429 : 0 : return -1;
430 : : }
431 : :
432 : 0 : p->m_dma_out_ptr_rd = (uint16_t)((p->m_dma_out_ptr_rd + 1) & (RAB_DMA_BUF_CNT - 1));
433 : 0 : p->m_in_free = RAB_DMA_BUF_CNT;
434 : :
435 : 0 : return 0;
436 : : }
437 : :
438 : 0 : int nthw_rac_rab_dma_commit(nthw_rac_t *p)
439 : : {
440 : : int ret;
441 : :
442 : 0 : nthw_rac_rab_dma_activate(p);
443 : 0 : ret = nthw_rac_rab_dma_wait(p);
444 : :
445 : 0 : p->m_dma_active = false;
446 : :
447 : 0 : return ret;
448 : : }
449 : :
450 : 0 : uint32_t nthw_rac_rab_get_free(nthw_rac_t *p)
451 : : {
452 [ # # ]: 0 : if (!p->m_dma_active) {
453 : : /* Expecting mutex not to be locked! */
454 : : RTE_ASSERT(0); /* alert developer that something is wrong */
455 : : return -1;
456 : : }
457 : :
458 : 0 : return p->m_in_free;
459 : : }
460 : :
461 : 0 : int nthw_rac_rab_write32_dma(nthw_rac_t *p, nthw_rab_bus_id_t bus_id, uint32_t address,
462 : : uint32_t word_cnt, const uint32_t *p_data)
463 : : {
464 : 0 : const struct fpga_info_s *const p_fpga_info = p->mp_fpga->p_fpga_info;
465 : 0 : const char *const p_adapter_id_str = p_fpga_info->mp_adapter_id_str;
466 : :
467 [ # # ]: 0 : if (word_cnt == 0 || word_cnt > 256) {
468 : 0 : NT_LOG(ERR, NTHW,
469 : : "%s: Failed rab dma write length check - bus: %d addr: 0x%08X wordcount: %"
470 : : PRIu32 " - inBufFree: 0x%08X",
471 : : p_adapter_id_str, bus_id, address, word_cnt, p->m_in_free);
472 : : RTE_ASSERT(0); /* alert developer that something is wrong */
473 : 0 : return -1;
474 : : }
475 : :
476 [ # # ]: 0 : if (p->m_in_free < (word_cnt + 3)) {
477 : : /*
478 : : * No more memory available.
479 : : * nthw_rac_rab_dma_commit() needs to be called to start and finish pending
480 : : * transfers.
481 : : */
482 : : return -1;
483 : : }
484 : :
485 : 0 : p->m_in_free -= (word_cnt + 1);
486 : :
487 : : /* Write the command word */
488 : 0 : p->m_dma_in_buf[p->m_dma_in_ptr_wr] = (RAB_WRITE << RAB_OPR_LO) |
489 : 0 : ((word_cnt & ((1 << RAB_CNT_BW) - 1)) << RAB_CNT_LO) | (bus_id << RAB_BUSID_LO) |
490 : : address;
491 : 0 : p->m_dma_in_ptr_wr = (uint16_t)((p->m_dma_in_ptr_wr + 1) & (RAB_DMA_BUF_CNT - 1));
492 : :
493 [ # # ]: 0 : for (uint32_t i = 0; i < word_cnt; i++) {
494 : 0 : p->m_dma_in_buf[p->m_dma_in_ptr_wr] = p_data[i];
495 : 0 : p->m_dma_in_ptr_wr = (uint16_t)((p->m_dma_in_ptr_wr + 1) & (RAB_DMA_BUF_CNT - 1));
496 : : }
497 : :
498 : : return 0;
499 : : }
500 : :
501 : 0 : int nthw_rac_rab_read32_dma(nthw_rac_t *p, nthw_rab_bus_id_t bus_id, uint32_t address,
502 : : uint32_t word_cnt, struct dma_buf_ptr *buf_ptr)
503 : : {
504 : 0 : const struct fpga_info_s *const p_fpga_info = p->mp_fpga->p_fpga_info;
505 : 0 : const char *const p_adapter_id_str = p_fpga_info->mp_adapter_id_str;
506 : :
507 [ # # ]: 0 : if (word_cnt == 0 || word_cnt > 256) {
508 : 0 : NT_LOG(ERR, NTHW,
509 : : "%s: Failed rab dma read length check - bus: %d addr: 0x%08X wordcount: %"
510 : : PRIu32 " - inBufFree: 0x%08X",
511 : : p_adapter_id_str, bus_id, address, word_cnt, p->m_in_free);
512 : : RTE_ASSERT(0); /* alert developer that something is wrong */
513 : 0 : return -1;
514 : : }
515 : :
516 [ # # ]: 0 : if (p->m_in_free < 3) {
517 : : /*
518 : : * No more memory available.
519 : : * nthw_rac_rab_dma_commit() needs to be called to start and finish pending
520 : : * transfers.
521 : : */
522 : : return -1;
523 : : }
524 : :
525 : 0 : p->m_in_free -= 1;
526 : :
527 : : /* Write the command word */
528 : 0 : p->m_dma_in_buf[p->m_dma_in_ptr_wr] = (RAB_READ << RAB_OPR_LO) |
529 : 0 : ((word_cnt & ((1 << RAB_CNT_BW) - 1)) << RAB_CNT_LO) | (bus_id << RAB_BUSID_LO) |
530 : : address;
531 : 0 : p->m_dma_in_ptr_wr = (uint16_t)((p->m_dma_in_ptr_wr + 1) & (RAB_DMA_BUF_CNT - 1));
532 : :
533 : 0 : buf_ptr->index = p->m_dma_out_ptr_rd;
534 : 0 : buf_ptr->size = RAB_DMA_BUF_CNT;
535 : 0 : buf_ptr->base = p->m_dma_out_buf;
536 : 0 : p->m_dma_out_ptr_rd =
537 : 0 : (uint16_t)((p->m_dma_out_ptr_rd + word_cnt) & (RAB_DMA_BUF_CNT - 1U));
538 : :
539 : 0 : return 0;
540 : : }
541 : :
542 : 0 : int nthw_rac_rab_write32(nthw_rac_t *p, bool trc, nthw_rab_bus_id_t bus_id, uint32_t address,
543 : : uint32_t word_cnt, const uint32_t *p_data)
544 : : {
545 : 0 : const struct fpga_info_s *const p_fpga_info = p->mp_fpga->p_fpga_info;
546 : 0 : const char *const p_adapter_id_str = p_fpga_info->mp_adapter_id_str;
547 : : uint32_t buf_used;
548 : : uint32_t buf_free;
549 : : uint32_t in_buf_free;
550 : : uint32_t out_buf_free;
551 : : int res = 0;
552 : :
553 [ # # ]: 0 : if (address > (1 << RAB_ADDR_BW)) {
554 : 0 : NT_LOG(ERR, NTHW, "%s: RAB: Illegal address: value too large %" PRIu32 " - max %d",
555 : : p_adapter_id_str, address, (1 << RAB_ADDR_BW));
556 : 0 : return -1;
557 : : }
558 : :
559 [ # # ]: 0 : if (bus_id > (1 << RAB_BUSID_BW)) {
560 : 0 : NT_LOG(ERR, NTHW, "%s: RAB: Illegal bus id: value too large %" PRIu32 " - max %d",
561 : : p_adapter_id_str, bus_id, (1 << RAB_BUSID_BW));
562 : 0 : return -1;
563 : : }
564 : :
565 [ # # ]: 0 : if (word_cnt == 0) {
566 : 0 : NT_LOG(ERR, NTHW, "%s: RAB: Illegal word count: value is zero (%" PRIu32 ")",
567 : : p_adapter_id_str, word_cnt);
568 : 0 : return -1;
569 : : }
570 : :
571 [ # # ]: 0 : if (word_cnt > (1 << RAB_CNT_BW)) {
572 : 0 : NT_LOG(ERR, NTHW, "%s: RAB: Illegal word count: value too large %d - max %d",
573 : : p_adapter_id_str, word_cnt, (1 << RAB_CNT_BW));
574 : 0 : return -1;
575 : : }
576 : :
577 : 0 : rte_spinlock_lock(&p->m_mutex);
578 : :
579 [ # # ]: 0 : if (p->m_dma_active) {
580 : 0 : NT_LOG(ERR, NTHW, "%s: RAB: Illegal operation: DMA enabled", p_adapter_id_str);
581 : : res = -1;
582 : 0 : goto exit_unlock_res;
583 : : }
584 : :
585 : : /* Read buffer free register */
586 : 0 : nthw_rac_reg_read32(p_fpga_info, p->RAC_RAB_BUF_FREE_ADDR, &buf_free);
587 : :
588 : 0 : in_buf_free = buf_free & p->RAC_RAB_BUF_FREE_IB_FREE_MASK;
589 : 0 : out_buf_free = (buf_free & p->RAC_RAB_BUF_FREE_OB_FREE_MASK) >> 16;
590 : :
591 : : /* Read buffer used register */
592 : 0 : nthw_rac_reg_read32(p_fpga_info, p->RAC_RAB_BUF_USED_ADDR, &buf_used);
593 : :
594 : : buf_used =
595 : 0 : buf_used & (p->RAC_RAB_BUF_USED_IB_USED_MASK | p->RAC_RAB_BUF_USED_OB_USED_MASK);
596 : :
597 : : /*
598 : : * Verify that output buffer can hold one completion word,
599 : : * input buffer can hold the number of words to be written +
600 : : * one write and one completion command
601 : : * and that the input and output "used" buffer is 0
602 : : */
603 [ # # # # : 0 : if (out_buf_free >= 1 && in_buf_free >= word_cnt + 2 && buf_used == 0) {
# # ]
604 : : const uint32_t rab_oper_cmpl = (RAB_COMPLETION << RAB_OPR_LO);
605 : : uint32_t rab_echo_oper_cmpl;
606 : : uint32_t word_cnt_expected = 1;
607 : : uint32_t rab_oper_wr;
608 : : uint32_t i;
609 : :
610 : 0 : rab_oper_wr = (RAB_WRITE << RAB_OPR_LO) |
611 : 0 : ((word_cnt & ((1 << RAB_CNT_BW) - 1)) << RAB_CNT_LO) |
612 : 0 : (bus_id << RAB_BUSID_LO) | address;
613 : :
614 [ # # ]: 0 : if (trc) {
615 : 0 : rab_oper_wr |= (RAB_ECHO << RAB_OPR_LO);
616 : : word_cnt_expected += word_cnt + 1;
617 : : }
618 : :
619 : : /* Write command */
620 : 0 : nthw_rac_reg_write32(p_fpga_info, p->RAC_RAB_IB_DATA_ADDR, rab_oper_wr);
621 : :
622 : : /* Write data to input buffer */
623 [ # # ]: 0 : for (i = 0; i < word_cnt; i++)
624 : 0 : nthw_rac_reg_write32(p_fpga_info, p->RAC_RAB_IB_DATA_ADDR, p_data[i]);
625 : :
626 : : /* Write completion command */
627 : 0 : nthw_rac_reg_write32(p_fpga_info, p->RAC_RAB_IB_DATA_ADDR, rab_oper_cmpl);
628 : :
629 : : /* Wait until done */
630 [ # # ]: 0 : if (_nthw_rac_wait_for_rab_done(p, address, word_cnt_expected)) {
631 : : res = -1;
632 : 0 : goto exit_unlock_res;
633 : : }
634 : :
635 [ # # ]: 0 : if (trc) {
636 : : uint32_t rab_echo_oper_wr;
637 : 0 : nthw_rac_reg_read32(p_fpga_info, p->RAC_RAB_OB_DATA_ADDR,
638 : : &rab_echo_oper_wr);
639 : :
640 [ # # ]: 0 : if (p->mn_param_rac_rab_ob_update)
641 : : nthw_rac_reg_write32(p_fpga_info, p->RAC_RAB_OB_DATA_ADDR, 0);
642 : :
643 [ # # ]: 0 : if (rab_oper_wr != rab_echo_oper_wr) {
644 : 0 : NT_LOG(ERR, NTHW,
645 : : "%s: expected rab read echo oper (0x%08X) - read (0x%08X)",
646 : : p_adapter_id_str, rab_oper_wr, rab_echo_oper_wr);
647 : : }
648 : : }
649 : :
650 : : {
651 : : /* Read data from output buffer */
652 : : uint32_t data;
653 : : char *tmp_string;
654 : :
655 [ # # ]: 0 : if (trc) {
656 : 0 : tmp_string = nthw_log_helper_str_alloc("Register::write");
657 : 0 : nthw_log_helper_str_add(tmp_string,
658 : : "(Dev: NA, Bus: RAB%u, Addr: 0x%08X, Cnt: %d, Data:",
659 : : bus_id, address, word_cnt);
660 : : }
661 : :
662 [ # # ]: 0 : for (i = 0; i < word_cnt; i++) {
663 : 0 : nthw_rac_reg_read32(p_fpga_info, p->RAC_RAB_OB_DATA_ADDR, &data);
664 : :
665 [ # # ]: 0 : if (p->mn_param_rac_rab_ob_update) {
666 : : nthw_rac_reg_write32(p_fpga_info, p->RAC_RAB_OB_DATA_ADDR,
667 : : 0);
668 : : }
669 : :
670 [ # # ]: 0 : if (trc)
671 : 0 : nthw_log_helper_str_add(tmp_string, " 0x%08X", data);
672 : : }
673 : :
674 [ # # ]: 0 : if (trc) {
675 : 0 : nthw_log_helper_str_add(tmp_string, ")");
676 : 0 : NT_LOG(DBG, NTHW, "%s", tmp_string);
677 : 0 : nthw_log_helper_str_free(tmp_string);
678 : : }
679 : : }
680 : :
681 : : /* Read completion from out buffer */
682 : 0 : nthw_rac_reg_read32(p_fpga_info, p->RAC_RAB_OB_DATA_ADDR, &rab_echo_oper_cmpl);
683 : :
684 [ # # ]: 0 : if (p->mn_param_rac_rab_ob_update)
685 : : nthw_rac_reg_write32(p_fpga_info, p->RAC_RAB_OB_DATA_ADDR, 0);
686 : :
687 [ # # ]: 0 : if (rab_echo_oper_cmpl != rab_oper_cmpl) {
688 : 0 : NT_LOG(ERR, NTHW,
689 : : "%s: RAB: Unexpected value of completion (0x%08X)- inBufFree: 0x%08X, outBufFree: 0x%08X, bufUsed: 0x%08X",
690 : : p_adapter_id_str, rab_echo_oper_cmpl, in_buf_free, out_buf_free,
691 : : buf_used);
692 : : res = -1;
693 : 0 : goto exit_unlock_res;
694 : : }
695 : :
696 : : /* Read buffer free register */
697 : 0 : nthw_rac_reg_read32(p_fpga_info, p->RAC_RAB_BUF_FREE_ADDR, &buf_free);
698 : :
699 [ # # ]: 0 : if (buf_free & 0x80000000) {
700 : : /* Clear Timeout and overflow bits */
701 : : nthw_rac_reg_write32(p_fpga_info, p->RAC_RAB_BUF_FREE_ADDR, 0x0);
702 : 0 : NT_LOG(ERR, NTHW,
703 : : "%s: RAB: timeout - Access outside register - bus: %d addr: 0x%08X - inBufFree: 0x%08X, outBufFree: 0x%08X, bufUsed: 0x%08X",
704 : : p_adapter_id_str, bus_id, address, in_buf_free, out_buf_free,
705 : : buf_used);
706 : : res = -1;
707 : 0 : goto exit_unlock_res;
708 : : }
709 : :
710 : : res = 0;
711 : 0 : goto exit_unlock_res;
712 : :
713 : : } else {
714 : 0 : NT_LOG(ERR, NTHW,
715 : : "%s: RAB: Fail rab bus buffer check - bus: %d addr: 0x%08X wordcount: %d - inBufFree: 0x%08X, outBufFree: 0x%08X, bufUsed: 0x%08X",
716 : : p_adapter_id_str, bus_id, address, word_cnt, in_buf_free, out_buf_free,
717 : : buf_used);
718 : : res = -1;
719 : 0 : goto exit_unlock_res;
720 : : }
721 : :
722 : 0 : exit_unlock_res:
723 : : rte_spinlock_unlock(&p->m_mutex);
724 : 0 : return res;
725 : : }
726 : :
727 : 0 : int nthw_rac_rab_read32(nthw_rac_t *p, bool trc, nthw_rab_bus_id_t bus_id, uint32_t address,
728 : : uint32_t word_cnt, uint32_t *p_data)
729 : : {
730 : 0 : const struct fpga_info_s *const p_fpga_info = p->mp_fpga->p_fpga_info;
731 : 0 : const char *const p_adapter_id_str = p_fpga_info->mp_adapter_id_str;
732 : : uint32_t buf_used;
733 : : uint32_t buf_free;
734 : : uint32_t in_buf_free;
735 : : uint32_t out_buf_free;
736 : : int res = 0;
737 : :
738 : 0 : rte_spinlock_lock(&p->m_mutex);
739 : :
740 [ # # ]: 0 : if (address > (1 << RAB_ADDR_BW)) {
741 : 0 : NT_LOG(ERR, NTHW, "%s: RAB: Illegal address: value too large %" PRIu32 " - max %d",
742 : : p_adapter_id_str, address, (1 << RAB_ADDR_BW));
743 : : res = -1;
744 : 0 : goto exit_unlock_res;
745 : : }
746 : :
747 [ # # ]: 0 : if (bus_id > (1 << RAB_BUSID_BW)) {
748 : 0 : NT_LOG(ERR, NTHW, "%s: RAB: Illegal bus id: value too large %" PRIu32 " - max %d",
749 : : p_adapter_id_str, bus_id, (1 << RAB_BUSID_BW));
750 : : res = -1;
751 : 0 : goto exit_unlock_res;
752 : : }
753 : :
754 [ # # ]: 0 : if (word_cnt == 0) {
755 : 0 : NT_LOG(ERR, NTHW, "%s: RAB: Illegal word count: value is zero (%" PRIu32 ")",
756 : : p_adapter_id_str, word_cnt);
757 : : res = -1;
758 : 0 : goto exit_unlock_res;
759 : : }
760 : :
761 [ # # ]: 0 : if (word_cnt > (1 << RAB_CNT_BW)) {
762 : 0 : NT_LOG(ERR, NTHW, "%s: RAB: Illegal word count: value too large %" PRIu32 " - max %d",
763 : : p_adapter_id_str, word_cnt, (1 << RAB_CNT_BW));
764 : : res = -1;
765 : 0 : goto exit_unlock_res;
766 : : }
767 : :
768 : : /* Read buffer free register */
769 : 0 : nthw_rac_reg_read32(p_fpga_info, p->RAC_RAB_BUF_FREE_ADDR, &buf_free);
770 : :
771 : 0 : in_buf_free = buf_free & p->RAC_RAB_BUF_FREE_IB_FREE_MASK;
772 : 0 : out_buf_free = (buf_free & p->RAC_RAB_BUF_FREE_OB_FREE_MASK) >> 16;
773 : :
774 : : /* Read buffer used register */
775 : 0 : nthw_rac_reg_read32(p_fpga_info, p->RAC_RAB_BUF_USED_ADDR, &buf_used);
776 : :
777 : : buf_used =
778 : 0 : buf_used & (p->RAC_RAB_BUF_USED_IB_USED_MASK | p->RAC_RAB_BUF_USED_OB_USED_MASK);
779 : :
780 : : /*
781 : : * Verify that output buffer can hold the number of words to be read,
782 : : * input buffer can hold one read command
783 : : * and that the input and output "used" buffer is 0
784 : : */
785 [ # # # # ]: 0 : if (out_buf_free >= word_cnt && in_buf_free >= 1 && buf_used == 0) {
786 : : const uint32_t rab_oper_cmpl = (RAB_COMPLETION << RAB_OPR_LO);
787 : : uint32_t rab_read_oper_cmpl;
788 : 0 : uint32_t word_cnt_expected = word_cnt + 1;
789 : : uint32_t rab_oper_rd;
790 : :
791 : 0 : rab_oper_rd = (RAB_READ << RAB_OPR_LO) |
792 : 0 : ((word_cnt & ((1 << RAB_CNT_BW) - 1)) << RAB_CNT_LO) |
793 : 0 : (bus_id << RAB_BUSID_LO) | address;
794 : :
795 [ # # ]: 0 : if (trc) {
796 : 0 : rab_oper_rd |= (RAB_ECHO << RAB_OPR_LO);
797 : 0 : word_cnt_expected++;
798 : : }
799 : :
800 : : /* Write command */
801 : 0 : nthw_rac_reg_write32(p_fpga_info, p->RAC_RAB_IB_DATA_ADDR, rab_oper_rd);
802 : :
803 : : /* Write completion command */
804 : 0 : nthw_rac_reg_write32(p_fpga_info, p->RAC_RAB_IB_DATA_ADDR, rab_oper_cmpl);
805 : :
806 : : /* Wait until done */
807 [ # # ]: 0 : if (_nthw_rac_wait_for_rab_done(p, address, word_cnt_expected)) {
808 : : res = -1;
809 : 0 : goto exit_unlock_res;
810 : : }
811 : :
812 [ # # ]: 0 : if (trc) {
813 : : uint32_t rab_echo_oper_rd;
814 : 0 : nthw_rac_reg_read32(p_fpga_info, p->RAC_RAB_OB_DATA_ADDR,
815 : : &rab_echo_oper_rd);
816 : :
817 [ # # ]: 0 : if (p->mn_param_rac_rab_ob_update)
818 : : nthw_rac_reg_write32(p_fpga_info, p->RAC_RAB_OB_DATA_ADDR, 0);
819 : :
820 [ # # ]: 0 : if (rab_oper_rd != rab_echo_oper_rd) {
821 : 0 : NT_LOG(ERR, NTHW,
822 : : "%s: RAB: expected rab read echo oper (0x%08X) - read (0x%08X)",
823 : : p_adapter_id_str, rab_oper_rd, rab_echo_oper_rd);
824 : : }
825 : : }
826 : :
827 : : {
828 : : /* Read data from output buffer */
829 : : uint32_t i;
830 : :
831 [ # # ]: 0 : for (i = 0; i < word_cnt; i++) {
832 : 0 : nthw_rac_reg_read32(p_fpga_info, p->RAC_RAB_OB_DATA_ADDR,
833 : 0 : &p_data[i]);
834 : :
835 [ # # ]: 0 : if (p->mn_param_rac_rab_ob_update) {
836 : 0 : nthw_rac_reg_write32(p_fpga_info, p->RAC_RAB_OB_DATA_ADDR,
837 : : 0);
838 : : }
839 : : }
840 : :
841 [ # # ]: 0 : if (trc) {
842 : 0 : char *tmp_string = nthw_log_helper_str_alloc("Register::read");
843 : 0 : nthw_log_helper_str_add(tmp_string,
844 : : "(Dev: NA, Bus: RAB%u, Addr: 0x%08X, Cnt: %d, Data:",
845 : : bus_id, address, word_cnt);
846 : :
847 [ # # ]: 0 : for (i = 0; i < word_cnt; i++)
848 : 0 : nthw_log_helper_str_add(tmp_string, " 0x%08X", p_data[i]);
849 : :
850 : 0 : nthw_log_helper_str_add(tmp_string, ")");
851 : 0 : NT_LOG(DBG, NTHW, "%s", tmp_string);
852 : 0 : nthw_log_helper_str_free(tmp_string);
853 : : }
854 : : }
855 : :
856 : : /* Read completion from out buffer */
857 : 0 : nthw_rac_reg_read32(p_fpga_info, p->RAC_RAB_OB_DATA_ADDR, &rab_read_oper_cmpl);
858 : :
859 [ # # ]: 0 : if (p->mn_param_rac_rab_ob_update)
860 : : nthw_rac_reg_write32(p_fpga_info, p->RAC_RAB_OB_DATA_ADDR, 0);
861 : :
862 [ # # ]: 0 : if (rab_read_oper_cmpl != rab_oper_cmpl) {
863 : 0 : NT_LOG(ERR, NTHW,
864 : : "%s: RAB: Unexpected value of completion (0x%08X)- inBufFree: 0x%08X, outBufFree: 0x%08X, bufUsed: 0x%08X",
865 : : p_adapter_id_str, rab_read_oper_cmpl, in_buf_free, out_buf_free,
866 : : buf_used);
867 : : res = -1;
868 : 0 : goto exit_unlock_res;
869 : : }
870 : :
871 : : /* Read buffer free register */
872 : 0 : nthw_rac_reg_read32(p_fpga_info, p->RAC_RAB_BUF_FREE_ADDR, &buf_free);
873 : :
874 [ # # ]: 0 : if (buf_free & 0x80000000) {
875 : : /* Clear Timeout and overflow bits */
876 : : nthw_rac_reg_write32(p_fpga_info, p->RAC_RAB_BUF_FREE_ADDR, 0x0);
877 : 0 : NT_LOG(ERR, NTHW,
878 : : "%s: RAB: timeout - Access outside register - bus: %d addr: 0x%08X - inBufFree: 0x%08X, outBufFree: 0x%08X, bufUsed: 0x%08X",
879 : : p_adapter_id_str, bus_id, address, in_buf_free, out_buf_free,
880 : : buf_used);
881 : : res = -1;
882 : 0 : goto exit_unlock_res;
883 : : }
884 : :
885 : : res = 0;
886 : 0 : goto exit_unlock_res;
887 : :
888 : : } else {
889 : 0 : NT_LOG(ERR, NTHW,
890 : : "%s: RAB: Fail rab bus buffer check - bus: %d addr: 0x%08X wordcount: %d - inBufFree: 0x%08X, outBufFree: 0x%08X, bufUsed: 0x%08X",
891 : : p_adapter_id_str, bus_id, address, word_cnt, in_buf_free, out_buf_free,
892 : : buf_used);
893 : : res = -1;
894 : 0 : goto exit_unlock_res;
895 : : }
896 : :
897 : 0 : exit_unlock_res:
898 : : rte_spinlock_unlock(&p->m_mutex);
899 : 0 : return res;
900 : : }
901 : :
902 : 0 : int nthw_rac_rab_flush(nthw_rac_t *p)
903 : : {
904 : 0 : const struct fpga_info_s *const p_fpga_info = p->mp_fpga->p_fpga_info;
905 : 0 : const char *const p_adapter_id_str = p_fpga_info->mp_adapter_id_str;
906 : : uint32_t data = 0;
907 : : uint32_t retry;
908 : : int res = 0;
909 : :
910 : 0 : rte_spinlock_lock(&p->m_mutex);
911 : :
912 : : /* Set the flush bit */
913 : 0 : nthw_rac_reg_write32(p_fpga_info, p->RAC_RAB_BUF_USED_ADDR,
914 : : p->RAC_RAB_BUF_USED_FLUSH_MASK);
915 : :
916 : : /* Reset BUF FREE register */
917 : 0 : nthw_rac_reg_write32(p_fpga_info, p->RAC_RAB_BUF_FREE_ADDR, 0x0);
918 : :
919 : : /* Wait until OB_USED and IB_USED are 0 */
920 [ # # ]: 0 : for (retry = 0; retry < 100000; retry++) {
921 : 0 : nthw_rac_reg_read32(p_fpga_info, p->RAC_RAB_BUF_USED_ADDR, &data);
922 : :
923 [ # # ]: 0 : if ((data & 0xFFFFFFFF) == p->RAC_RAB_BUF_USED_FLUSH_MASK)
924 : : break;
925 : : }
926 : :
927 [ # # ]: 0 : if (data != p->RAC_RAB_BUF_USED_FLUSH_MASK) {
928 : 0 : NT_LOG(ERR, NTHW, "%s: RAB: Rab bus flush error.", p_adapter_id_str);
929 : : res = -1;
930 : : }
931 : :
932 : : /* Clear flush bit when done */
933 : 0 : nthw_rac_reg_write32(p_fpga_info, p->RAC_RAB_BUF_USED_ADDR, 0x0);
934 : :
935 : : rte_spinlock_unlock(&p->m_mutex);
936 : 0 : return res;
937 : : }
|