Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright(c) 2024 ZTE Corporation
3 : : */
4 : :
5 : : #include <stdint.h>
6 : : #include <string.h>
7 : :
8 : : #include <ethdev_driver.h>
9 : : #include <rte_malloc.h>
10 : : #include <rte_memcpy.h>
11 : :
12 : : #include "zxdh_ethdev.h"
13 : : #include "zxdh_logs.h"
14 : : #include "zxdh_msg.h"
15 : : #include "zxdh_common.h"
16 : :
17 : : #define ZXDH_MSG_RSP_SIZE_MAX 512
18 : :
19 : : #define ZXDH_COMMON_TABLE_READ 0
20 : : #define ZXDH_COMMON_TABLE_WRITE 1
21 : :
22 : : #define ZXDH_COMMON_FIELD_PHYPORT 6
23 : : #define ZXDH_COMMON_FIELD_DATACH 3
24 : :
25 : : #define ZXDH_RSC_TBL_CONTENT_LEN_MAX (257 * 2)
26 : :
27 : : #define ZXDH_REPS_HEADER_OFFSET 4
28 : : #define ZXDH_TBL_MSG_PRO_SUCCESS 0xaa
29 : :
30 : : struct __rte_packed_begin zxdh_common_msg {
31 : : uint8_t type; /* 0:read table 1:write table */
32 : : uint8_t field;
33 : : uint16_t pcie_id;
34 : : uint16_t slen; /* Data length for write table */
35 : : uint16_t reserved;
36 : : } __rte_packed_end;
37 : :
38 : : struct __rte_packed_begin zxdh_common_rsp_hdr {
39 : : uint8_t rsp_status;
40 : : uint16_t rsp_len;
41 : : uint8_t reserved;
42 : : uint8_t payload_status;
43 : : uint8_t rsv;
44 : : uint16_t payload_len;
45 : : } __rte_packed_end;
46 : :
47 : : struct zxdh_tbl_msg_header {
48 : : uint8_t type;
49 : : uint8_t field;
50 : : uint16_t pcieid;
51 : : uint16_t slen;
52 : : uint16_t rsv;
53 : : };
54 : :
55 : : struct zxdh_tbl_msg_reps_header {
56 : : uint8_t check;
57 : : uint8_t rsv;
58 : : uint16_t len;
59 : : };
60 : :
61 : : static int32_t
62 : 0 : zxdh_fill_common_msg(struct zxdh_hw *hw, struct zxdh_pci_bar_msg *desc,
63 : : uint8_t type, uint8_t field,
64 : : void *buff, uint16_t buff_size)
65 : : {
66 : 0 : uint64_t msg_len = sizeof(struct zxdh_common_msg) + buff_size;
67 : :
68 : 0 : desc->payload_addr = rte_zmalloc(NULL, msg_len, 0);
69 [ # # ]: 0 : if (unlikely(desc->payload_addr == NULL)) {
70 : 0 : PMD_DRV_LOG(ERR, "Failed to allocate msg_data");
71 : 0 : return -ENOMEM;
72 : : }
73 : : memset(desc->payload_addr, 0, msg_len);
74 : 0 : desc->payload_len = msg_len;
75 : : struct zxdh_common_msg *msg_data = (struct zxdh_common_msg *)desc->payload_addr;
76 : :
77 : 0 : msg_data->type = type;
78 : 0 : msg_data->field = field;
79 : 0 : msg_data->pcie_id = hw->pcie_id;
80 : 0 : msg_data->slen = buff_size;
81 [ # # ]: 0 : if (buff_size != 0)
82 [ # # ]: 0 : rte_memcpy(msg_data + 1, buff, buff_size);
83 : :
84 : : return 0;
85 : : }
86 : :
87 : : static int32_t
88 : 0 : zxdh_send_command(struct zxdh_hw *hw, struct zxdh_pci_bar_msg *desc,
89 : : enum ZXDH_BAR_MODULE_ID module_id,
90 : : struct zxdh_msg_recviver_mem *msg_rsp)
91 : : {
92 : 0 : desc->virt_addr = (uint64_t)(hw->bar_addr[ZXDH_BAR0_INDEX] + ZXDH_CTRLCH_OFFSET);
93 [ # # ]: 0 : desc->src = hw->is_pf ? ZXDH_MSG_CHAN_END_PF : ZXDH_MSG_CHAN_END_VF;
94 : 0 : desc->dst = ZXDH_MSG_CHAN_END_RISC;
95 : 0 : desc->module_id = module_id;
96 : 0 : desc->src_pcieid = hw->pcie_id;
97 : :
98 : 0 : msg_rsp->buffer_len = ZXDH_MSG_RSP_SIZE_MAX;
99 : 0 : msg_rsp->recv_buffer = rte_zmalloc(NULL, msg_rsp->buffer_len, 0);
100 [ # # ]: 0 : if (unlikely(msg_rsp->recv_buffer == NULL)) {
101 : 0 : PMD_DRV_LOG(ERR, "Failed to allocate messages response");
102 : 0 : return -ENOMEM;
103 : : }
104 : :
105 [ # # ]: 0 : if (zxdh_bar_chan_sync_msg_send(desc, msg_rsp) != ZXDH_BAR_MSG_OK) {
106 : 0 : PMD_DRV_LOG(ERR, "Failed to send sync messages or receive response");
107 : 0 : rte_free(msg_rsp->recv_buffer);
108 : 0 : return -1;
109 : : }
110 : :
111 : : return 0;
112 : : }
113 : :
114 : : static int32_t
115 : 0 : zxdh_common_rsp_check(struct zxdh_msg_recviver_mem *msg_rsp,
116 : : void *buff, uint16_t len)
117 : : {
118 : 0 : struct zxdh_common_rsp_hdr *rsp_hdr = (struct zxdh_common_rsp_hdr *)msg_rsp->recv_buffer;
119 : :
120 [ # # # # ]: 0 : if (rsp_hdr->payload_status != 0xaa || rsp_hdr->payload_len != len) {
121 : 0 : PMD_DRV_LOG(ERR, "Common response is invalid, status:0x%x rsp_len:%d",
122 : : rsp_hdr->payload_status, rsp_hdr->payload_len);
123 : 0 : return -1;
124 : : }
125 [ # # ]: 0 : if (len != 0)
126 [ # # ]: 0 : rte_memcpy(buff, rsp_hdr + 1, len);
127 : :
128 : : return 0;
129 : : }
130 : :
131 : : static int32_t
132 : 0 : zxdh_common_table_read(struct zxdh_hw *hw, uint8_t field,
133 : : void *buff, uint16_t buff_size)
134 : : {
135 : : struct zxdh_msg_recviver_mem msg_rsp;
136 : : struct zxdh_pci_bar_msg desc;
137 : : int32_t ret = 0;
138 : :
139 [ # # ]: 0 : if (!hw->msg_chan_init) {
140 : 0 : PMD_DRV_LOG(ERR, "Bar messages channel not initialized");
141 : 0 : return -1;
142 : : }
143 : :
144 : 0 : ret = zxdh_fill_common_msg(hw, &desc, ZXDH_COMMON_TABLE_READ, field, NULL, 0);
145 [ # # ]: 0 : if (ret != 0) {
146 : 0 : PMD_DRV_LOG(ERR, "Failed to fill common msg");
147 : 0 : return ret;
148 : : }
149 : :
150 : 0 : ret = zxdh_send_command(hw, &desc, ZXDH_BAR_MODULE_TBL, &msg_rsp);
151 [ # # ]: 0 : if (ret != 0)
152 : 0 : goto free_msg_data;
153 : :
154 : 0 : ret = zxdh_common_rsp_check(&msg_rsp, buff, buff_size);
155 : : if (ret != 0)
156 : : goto free_rsp_data;
157 : :
158 : : free_rsp_data:
159 : 0 : rte_free(msg_rsp.recv_buffer);
160 : 0 : free_msg_data:
161 : 0 : rte_free(desc.payload_addr);
162 : 0 : return ret;
163 : : }
164 : :
165 : : int32_t
166 : 0 : zxdh_phyport_get(struct rte_eth_dev *dev, uint8_t *phyport)
167 : : {
168 : 0 : struct zxdh_hw *hw = dev->data->dev_private;
169 : :
170 : 0 : int32_t ret = zxdh_common_table_read(hw, ZXDH_COMMON_FIELD_PHYPORT,
171 : : (void *)phyport, sizeof(*phyport));
172 : 0 : return ret;
173 : : }
174 : :
175 : : static inline void
176 : : zxdh_fill_res_para(struct rte_eth_dev *dev, struct zxdh_res_para *param)
177 : : {
178 : 0 : struct zxdh_hw *hw = dev->data->dev_private;
179 : :
180 : 0 : param->pcie_id = hw->pcie_id;
181 : 0 : param->virt_addr = hw->bar_addr[0] + ZXDH_CTRLCH_OFFSET;
182 : 0 : param->src_type = ZXDH_BAR_MODULE_TBL;
183 : : }
184 : :
185 : : static int
186 : 0 : zxdh_get_res_info(struct zxdh_res_para *dev, uint8_t field, uint8_t *res, uint16_t *len)
187 : : {
188 : 0 : struct zxdh_pci_bar_msg in = {0};
189 : 0 : uint8_t recv_buf[ZXDH_RSC_TBL_CONTENT_LEN_MAX + 8] = {0};
190 : : int ret = 0;
191 : :
192 [ # # ]: 0 : if (!res || !dev)
193 : : return ZXDH_BAR_MSG_ERR_NULL;
194 : :
195 : 0 : struct zxdh_tbl_msg_header tbl_msg = {
196 : : .type = ZXDH_TBL_TYPE_READ,
197 : : .field = field,
198 : 0 : .pcieid = dev->pcie_id,
199 : : .slen = 0,
200 : : .rsv = 0,
201 : : };
202 : :
203 : 0 : in.virt_addr = dev->virt_addr;
204 : 0 : in.payload_addr = &tbl_msg;
205 : 0 : in.payload_len = sizeof(tbl_msg);
206 : 0 : in.src = dev->src_type;
207 : 0 : in.dst = ZXDH_MSG_CHAN_END_RISC;
208 : 0 : in.module_id = ZXDH_BAR_MODULE_TBL;
209 : 0 : in.src_pcieid = dev->pcie_id;
210 : :
211 : 0 : struct zxdh_msg_recviver_mem result = {
212 : : .recv_buffer = recv_buf,
213 : : .buffer_len = sizeof(recv_buf),
214 : : };
215 : 0 : ret = zxdh_bar_chan_sync_msg_send(&in, &result);
216 : :
217 [ # # ]: 0 : if (ret != ZXDH_BAR_MSG_OK) {
218 : 0 : PMD_DRV_LOG(ERR,
219 : : "send sync_msg failed. pcieid: 0x%x, ret: %d", dev->pcie_id, ret);
220 : 0 : return ret;
221 : : }
222 : : struct zxdh_tbl_msg_reps_header *tbl_reps =
223 : : (struct zxdh_tbl_msg_reps_header *)(recv_buf + ZXDH_REPS_HEADER_OFFSET);
224 : :
225 [ # # ]: 0 : if (tbl_reps->check != ZXDH_TBL_MSG_PRO_SUCCESS) {
226 : 0 : PMD_DRV_LOG(ERR,
227 : : "get resource_field failed. pcieid: 0x%x, ret: %d", dev->pcie_id, ret);
228 : 0 : return ret;
229 : : }
230 : 0 : *len = tbl_reps->len;
231 [ # # ]: 0 : rte_memcpy(res, (recv_buf + ZXDH_REPS_HEADER_OFFSET +
232 : : sizeof(struct zxdh_tbl_msg_reps_header)), *len);
233 : : return ret;
234 : : }
235 : :
236 : : static int
237 : 0 : zxdh_get_res_panel_id(struct zxdh_res_para *in, uint8_t *panel_id)
238 : : {
239 : 0 : uint8_t reps = 0;
240 : 0 : uint16_t reps_len = 0;
241 : :
242 [ # # ]: 0 : if (zxdh_get_res_info(in, ZXDH_TBL_FIELD_PNLID, &reps, &reps_len) != ZXDH_BAR_MSG_OK)
243 : : return -1;
244 : :
245 : 0 : *panel_id = reps;
246 : 0 : return ZXDH_BAR_MSG_OK;
247 : : }
248 : :
249 : : int32_t
250 : 0 : zxdh_panelid_get(struct rte_eth_dev *dev, uint8_t *panelid)
251 : : {
252 : : struct zxdh_res_para param;
253 : :
254 : : zxdh_fill_res_para(dev, ¶m);
255 : 0 : int32_t ret = zxdh_get_res_panel_id(¶m, panelid);
256 : 0 : return ret;
257 : : }
258 : :
259 : : static int
260 : 0 : zxdh_get_res_hash_id(struct zxdh_res_para *in, uint8_t *hash_id)
261 : : {
262 : 0 : uint8_t reps = 0;
263 : 0 : uint16_t reps_len = 0;
264 : :
265 [ # # ]: 0 : if (zxdh_get_res_info(in, ZXDH_TBL_FIELD_HASHID, &reps, &reps_len) != ZXDH_BAR_MSG_OK)
266 : : return -1;
267 : :
268 : 0 : *hash_id = reps;
269 : 0 : return ZXDH_BAR_MSG_OK;
270 : : }
271 : :
272 : : int32_t
273 : 0 : zxdh_hashidx_get(struct rte_eth_dev *dev, uint8_t *hash_idx)
274 : : {
275 : : struct zxdh_res_para param;
276 : :
277 : : zxdh_fill_res_para(dev, ¶m);
278 : 0 : int32_t ret = zxdh_get_res_hash_id(¶m, hash_idx);
279 : :
280 : 0 : return ret;
281 : : }
282 : :
283 : : uint32_t
284 : 0 : zxdh_read_bar_reg(struct rte_eth_dev *dev, uint32_t bar, uint32_t reg)
285 : : {
286 : 0 : struct zxdh_hw *hw = dev->data->dev_private;
287 : 0 : uint64_t baseaddr = (uint64_t)(hw->bar_addr[bar]);
288 : 0 : uint32_t val = *((volatile uint32_t *)(baseaddr + reg));
289 : 0 : return val;
290 : : }
291 : :
292 : : void
293 : 0 : zxdh_write_bar_reg(struct rte_eth_dev *dev, uint32_t bar, uint32_t reg, uint32_t val)
294 : : {
295 : 0 : struct zxdh_hw *hw = dev->data->dev_private;
296 : 0 : uint64_t baseaddr = (uint64_t)(hw->bar_addr[bar]);
297 : 0 : *((volatile uint32_t *)(baseaddr + reg)) = val;
298 : 0 : }
299 : :
300 : : static bool
301 : : zxdh_try_lock(struct zxdh_hw *hw)
302 : : {
303 : 0 : uint32_t var = zxdh_read_comm_reg((uint64_t)hw->common_cfg, ZXDH_VF_LOCK_REG);
304 : :
305 : : /* check whether lock is used */
306 [ # # ]: 0 : if (!(var & ZXDH_VF_LOCK_ENABLE_MASK))
307 : : return false;
308 : :
309 : : return true;
310 : : }
311 : :
312 : : int32_t
313 : 0 : zxdh_timedlock(struct zxdh_hw *hw, uint32_t us)
314 : : {
315 : : uint16_t timeout = 0;
316 : :
317 [ # # ]: 0 : while ((timeout++) < ZXDH_ACQUIRE_CHANNEL_NUM_MAX) {
318 : 0 : rte_delay_us_block(us);
319 : : /* acquire hw lock */
320 : 0 : if (!zxdh_try_lock(hw)) {
321 : 0 : PMD_DRV_LOG(ERR, "Acquiring hw lock got failed, timeout: %d", timeout);
322 : 0 : continue;
323 : : }
324 : : break;
325 : : }
326 [ # # ]: 0 : if (timeout >= ZXDH_ACQUIRE_CHANNEL_NUM_MAX) {
327 : 0 : PMD_DRV_LOG(ERR, "Failed to acquire channel");
328 : 0 : return -1;
329 : : }
330 : : return 0;
331 : : }
332 : :
333 : : void
334 : 0 : zxdh_release_lock(struct zxdh_hw *hw)
335 : : {
336 : 0 : uint32_t var = zxdh_read_comm_reg((uint64_t)hw->common_cfg, ZXDH_VF_LOCK_REG);
337 : :
338 [ # # ]: 0 : if (var & ZXDH_VF_LOCK_ENABLE_MASK) {
339 : 0 : var &= ~ZXDH_VF_LOCK_ENABLE_MASK;
340 : 0 : zxdh_write_comm_reg((uint64_t)hw->common_cfg, ZXDH_VF_LOCK_REG, var);
341 : : }
342 : 0 : }
343 : :
344 : : uint32_t
345 : 0 : zxdh_read_comm_reg(uint64_t pci_comm_cfg_baseaddr, uint32_t reg)
346 : : {
347 : 0 : uint32_t val = *((volatile uint32_t *)(pci_comm_cfg_baseaddr + reg));
348 : 0 : return val;
349 : : }
350 : :
351 : : void
352 : 0 : zxdh_write_comm_reg(uint64_t pci_comm_cfg_baseaddr, uint32_t reg, uint32_t val)
353 : : {
354 : 0 : *((volatile uint32_t *)(pci_comm_cfg_baseaddr + reg)) = val;
355 : 0 : }
356 : :
357 : : static int32_t
358 : 0 : zxdh_common_table_write(struct zxdh_hw *hw, uint8_t field,
359 : : void *buff, uint16_t buff_size)
360 : : {
361 : : struct zxdh_pci_bar_msg desc;
362 : : struct zxdh_msg_recviver_mem msg_rsp;
363 : : int32_t ret = 0;
364 : :
365 [ # # ]: 0 : if (!hw->msg_chan_init) {
366 : 0 : PMD_DRV_LOG(ERR, "Bar messages channel not initialized");
367 : 0 : return -1;
368 : : }
369 [ # # ]: 0 : if (buff_size != 0 && buff == NULL) {
370 : 0 : PMD_DRV_LOG(ERR, "Buff is invalid");
371 : 0 : return -1;
372 : : }
373 : :
374 : 0 : ret = zxdh_fill_common_msg(hw, &desc, ZXDH_COMMON_TABLE_WRITE,
375 : : field, buff, buff_size);
376 : :
377 [ # # ]: 0 : if (ret != 0) {
378 : 0 : PMD_DRV_LOG(ERR, "Failed to fill common msg");
379 : 0 : return ret;
380 : : }
381 : :
382 : 0 : ret = zxdh_send_command(hw, &desc, ZXDH_BAR_MODULE_TBL, &msg_rsp);
383 [ # # ]: 0 : if (ret != 0)
384 : 0 : goto free_msg_data;
385 : :
386 : 0 : ret = zxdh_common_rsp_check(&msg_rsp, NULL, 0);
387 : : if (ret != 0)
388 : : goto free_rsp_data;
389 : :
390 : : free_rsp_data:
391 : 0 : rte_free(msg_rsp.recv_buffer);
392 : 0 : free_msg_data:
393 : 0 : rte_free(desc.payload_addr);
394 : 0 : return ret;
395 : : }
396 : :
397 : : int32_t
398 : 0 : zxdh_datach_set(struct rte_eth_dev *dev)
399 : : {
400 : 0 : struct zxdh_hw *hw = dev->data->dev_private;
401 : 0 : uint16_t buff_size = (hw->queue_num + 1) * 2;
402 : : int32_t ret = 0;
403 : : uint16_t i;
404 : :
405 : 0 : void *buff = rte_zmalloc(NULL, buff_size, 0);
406 [ # # ]: 0 : if (unlikely(buff == NULL)) {
407 : 0 : PMD_DRV_LOG(ERR, "Failed to allocate buff");
408 : 0 : return -ENOMEM;
409 : : }
410 : : memset(buff, 0, buff_size);
411 : : uint16_t *pdata = (uint16_t *)buff;
412 : 0 : *pdata++ = hw->queue_num;
413 : :
414 [ # # ]: 0 : for (i = 0; i < hw->queue_num; i++)
415 : 0 : *(pdata + i) = hw->channel_context[i].ph_chno;
416 : :
417 : 0 : ret = zxdh_common_table_write(hw, ZXDH_COMMON_FIELD_DATACH,
418 : : (void *)buff, buff_size);
419 [ # # ]: 0 : if (ret != 0)
420 : 0 : PMD_DRV_LOG(ERR, "Failed to setup data channel of common table");
421 : :
422 : 0 : rte_free(buff);
423 : 0 : return ret;
424 : : }
|