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 : : uint32_t
260 : 0 : zxdh_read_bar_reg(struct rte_eth_dev *dev, uint32_t bar, uint32_t reg)
261 : : {
262 : 0 : struct zxdh_hw *hw = dev->data->dev_private;
263 : 0 : uint64_t baseaddr = (uint64_t)(hw->bar_addr[bar]);
264 : 0 : uint32_t val = *((volatile uint32_t *)(baseaddr + reg));
265 : 0 : return val;
266 : : }
267 : :
268 : : void
269 : 0 : zxdh_write_bar_reg(struct rte_eth_dev *dev, uint32_t bar, uint32_t reg, uint32_t val)
270 : : {
271 : 0 : struct zxdh_hw *hw = dev->data->dev_private;
272 : 0 : uint64_t baseaddr = (uint64_t)(hw->bar_addr[bar]);
273 : 0 : *((volatile uint32_t *)(baseaddr + reg)) = val;
274 : 0 : }
275 : :
276 : : static bool
277 : : zxdh_try_lock(struct zxdh_hw *hw)
278 : : {
279 : 0 : uint32_t var = zxdh_read_comm_reg((uint64_t)hw->common_cfg, ZXDH_VF_LOCK_REG);
280 : :
281 : : /* check whether lock is used */
282 [ # # ]: 0 : if (!(var & ZXDH_VF_LOCK_ENABLE_MASK))
283 : : return false;
284 : :
285 : : return true;
286 : : }
287 : :
288 : : int32_t
289 : 0 : zxdh_timedlock(struct zxdh_hw *hw, uint32_t us)
290 : : {
291 : : uint16_t timeout = 0;
292 : :
293 [ # # ]: 0 : while ((timeout++) < ZXDH_ACQUIRE_CHANNEL_NUM_MAX) {
294 : 0 : rte_delay_us_block(us);
295 : : /* acquire hw lock */
296 : 0 : if (!zxdh_try_lock(hw)) {
297 : 0 : PMD_DRV_LOG(ERR, "Acquiring hw lock got failed, timeout: %d", timeout);
298 : 0 : continue;
299 : : }
300 : : break;
301 : : }
302 [ # # ]: 0 : if (timeout >= ZXDH_ACQUIRE_CHANNEL_NUM_MAX) {
303 : 0 : PMD_DRV_LOG(ERR, "Failed to acquire channel");
304 : 0 : return -1;
305 : : }
306 : : return 0;
307 : : }
308 : :
309 : : void
310 : 0 : zxdh_release_lock(struct zxdh_hw *hw)
311 : : {
312 : 0 : uint32_t var = zxdh_read_comm_reg((uint64_t)hw->common_cfg, ZXDH_VF_LOCK_REG);
313 : :
314 [ # # ]: 0 : if (var & ZXDH_VF_LOCK_ENABLE_MASK) {
315 : 0 : var &= ~ZXDH_VF_LOCK_ENABLE_MASK;
316 : 0 : zxdh_write_comm_reg((uint64_t)hw->common_cfg, ZXDH_VF_LOCK_REG, var);
317 : : }
318 : 0 : }
319 : :
320 : : uint32_t
321 : 0 : zxdh_read_comm_reg(uint64_t pci_comm_cfg_baseaddr, uint32_t reg)
322 : : {
323 : 0 : uint32_t val = *((volatile uint32_t *)(pci_comm_cfg_baseaddr + reg));
324 : 0 : return val;
325 : : }
326 : :
327 : : void
328 : 0 : zxdh_write_comm_reg(uint64_t pci_comm_cfg_baseaddr, uint32_t reg, uint32_t val)
329 : : {
330 : 0 : *((volatile uint32_t *)(pci_comm_cfg_baseaddr + reg)) = val;
331 : 0 : }
332 : :
333 : : static int32_t
334 : 0 : zxdh_common_table_write(struct zxdh_hw *hw, uint8_t field,
335 : : void *buff, uint16_t buff_size)
336 : : {
337 : : struct zxdh_pci_bar_msg desc;
338 : : struct zxdh_msg_recviver_mem msg_rsp;
339 : : int32_t ret = 0;
340 : :
341 [ # # ]: 0 : if (!hw->msg_chan_init) {
342 : 0 : PMD_DRV_LOG(ERR, "Bar messages channel not initialized");
343 : 0 : return -1;
344 : : }
345 [ # # ]: 0 : if (buff_size != 0 && buff == NULL) {
346 : 0 : PMD_DRV_LOG(ERR, "Buff is invalid");
347 : 0 : return -1;
348 : : }
349 : :
350 : 0 : ret = zxdh_fill_common_msg(hw, &desc, ZXDH_COMMON_TABLE_WRITE,
351 : : field, buff, buff_size);
352 : :
353 [ # # ]: 0 : if (ret != 0) {
354 : 0 : PMD_DRV_LOG(ERR, "Failed to fill common msg");
355 : 0 : return ret;
356 : : }
357 : :
358 : 0 : ret = zxdh_send_command(hw, &desc, ZXDH_BAR_MODULE_TBL, &msg_rsp);
359 [ # # ]: 0 : if (ret != 0)
360 : 0 : goto free_msg_data;
361 : :
362 : 0 : ret = zxdh_common_rsp_check(&msg_rsp, NULL, 0);
363 : : if (ret != 0)
364 : : goto free_rsp_data;
365 : :
366 : : free_rsp_data:
367 : 0 : rte_free(msg_rsp.recv_buffer);
368 : 0 : free_msg_data:
369 : 0 : rte_free(desc.payload_addr);
370 : 0 : return ret;
371 : : }
372 : :
373 : : int32_t
374 : 0 : zxdh_datach_set(struct rte_eth_dev *dev)
375 : : {
376 : 0 : struct zxdh_hw *hw = dev->data->dev_private;
377 : 0 : uint16_t buff_size = (hw->queue_num + 1) * 2;
378 : : int32_t ret = 0;
379 : : uint16_t i;
380 : :
381 : 0 : void *buff = rte_zmalloc(NULL, buff_size, 0);
382 [ # # ]: 0 : if (unlikely(buff == NULL)) {
383 : 0 : PMD_DRV_LOG(ERR, "Failed to allocate buff");
384 : 0 : return -ENOMEM;
385 : : }
386 : : memset(buff, 0, buff_size);
387 : : uint16_t *pdata = (uint16_t *)buff;
388 : 0 : *pdata++ = hw->queue_num;
389 : :
390 [ # # ]: 0 : for (i = 0; i < hw->queue_num; i++)
391 : 0 : *(pdata + i) = hw->channel_context[i].ph_chno;
392 : :
393 : 0 : ret = zxdh_common_table_write(hw, ZXDH_COMMON_FIELD_DATACH,
394 : : (void *)buff, buff_size);
395 [ # # ]: 0 : if (ret != 0)
396 : 0 : PMD_DRV_LOG(ERR, "Failed to setup data channel of common table");
397 : :
398 : 0 : rte_free(buff);
399 : 0 : return ret;
400 : : }
|