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