Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright 2025 Yunsilicon Technology Co., Ltd.
3 : : */
4 : : #include <rte_malloc.h>
5 : : #include <bus_pci_driver.h>
6 : :
7 : : #include "xsc_vfio_mbox.h"
8 : : #include "xsc_log.h"
9 : :
10 : : #define XSC_MBOX_BUF_NUM 2048
11 : : #define XSC_MBOX_BUF_CACHE_SIZE 256
12 : : #define XSC_CMDQ_DEPTH_LOG 5
13 : : #define XSC_CMDQ_ELEMENT_SIZE_LOG 6
14 : : #define XSC_CMDQ_REQ_TYPE 7
15 : : #define XSC_CMDQ_WAIT_TIMEOUT 10
16 : : #define XSC_CMDQ_WAIT_DELAY_MS 100
17 : : #define XSC_CMD_OP_DUMMY 0x10d
18 : :
19 : : #define XSC_PF_CMDQ_ELEMENT_SZ 0x1020020
20 : : #define XSC_PF_CMDQ_REQ_BASE_H_ADDR 0x1022000
21 : : #define XSC_PF_CMDQ_REQ_BASE_L_ADDR 0x1024000
22 : : #define XSC_PF_CMDQ_RSP_BASE_H_ADDR 0x102a000
23 : : #define XSC_PF_CMDQ_RSP_BASE_L_ADDR 0x102c000
24 : : #define XSC_PF_CMDQ_REQ_PID 0x1026000
25 : : #define XSC_PF_CMDQ_REQ_CID 0x1028000
26 : : #define XSC_PF_CMDQ_RSP_PID 0x102e000
27 : : #define XSC_PF_CMDQ_RSP_CID 0x1030000
28 : : #define XSC_PF_CMDQ_DEPTH 0x1020028
29 : :
30 : : #define XSC_VF_CMDQ_REQ_BASE_H_ADDR 0x0
31 : : #define XSC_VF_CMDQ_REQ_BASE_L_ADDR 0x4
32 : : #define XSC_VF_CMDQ_RSP_BASE_H_ADDR 0x10
33 : : #define XSC_VF_CMDQ_RSP_BASE_L_ADDR 0x14
34 : : #define XSC_VF_CMDQ_REQ_PID 0x8
35 : : #define XSC_VF_CMDQ_REQ_CID 0xc
36 : : #define XSC_VF_CMDQ_RSP_PID 0x18
37 : : #define XSC_VF_CMDQ_RSP_CID 0x1c
38 : : #define XSC_VF_CMDQ_ELEMENT_SZ 0x28
39 : : #define XSC_VF_CMDQ_DEPTH 0x2c
40 : :
41 : : static const char * const xsc_cmd_error[] = {
42 : : "xsc cmd success",
43 : : "xsc cmd fail",
44 : : "xsc cmd timeout"
45 : : };
46 : :
47 : : static struct xsc_cmdq_config xsc_pf_config = {
48 : : .req_pid_addr = XSC_PF_CMDQ_REQ_PID,
49 : : .req_cid_addr = XSC_PF_CMDQ_REQ_CID,
50 : : .rsp_pid_addr = XSC_PF_CMDQ_RSP_PID,
51 : : .rsp_cid_addr = XSC_PF_CMDQ_RSP_CID,
52 : : .req_h_addr = XSC_PF_CMDQ_REQ_BASE_H_ADDR,
53 : : .req_l_addr = XSC_PF_CMDQ_REQ_BASE_L_ADDR,
54 : : .rsp_h_addr = XSC_PF_CMDQ_RSP_BASE_H_ADDR,
55 : : .rsp_l_addr = XSC_PF_CMDQ_RSP_BASE_L_ADDR,
56 : : .elt_sz_addr = XSC_PF_CMDQ_ELEMENT_SZ,
57 : : .depth_addr = XSC_PF_CMDQ_DEPTH,
58 : : };
59 : :
60 : : static struct xsc_cmdq_config xsc_vf_config = {
61 : : .req_pid_addr = XSC_VF_CMDQ_REQ_PID,
62 : : .req_cid_addr = XSC_VF_CMDQ_REQ_CID,
63 : : .rsp_pid_addr = XSC_VF_CMDQ_RSP_PID,
64 : : .rsp_cid_addr = XSC_VF_CMDQ_RSP_CID,
65 : : .req_h_addr = XSC_VF_CMDQ_REQ_BASE_H_ADDR,
66 : : .req_l_addr = XSC_VF_CMDQ_REQ_BASE_L_ADDR,
67 : : .rsp_h_addr = XSC_VF_CMDQ_RSP_BASE_H_ADDR,
68 : : .rsp_l_addr = XSC_VF_CMDQ_RSP_BASE_L_ADDR,
69 : : .elt_sz_addr = XSC_VF_CMDQ_ELEMENT_SZ,
70 : : .depth_addr = XSC_VF_CMDQ_DEPTH,
71 : : };
72 : :
73 : : static void
74 : : xsc_cmdq_config_init(struct xsc_dev *xdev, struct xsc_cmd_queue *cmdq)
75 : : {
76 [ # # ]: 0 : if (!xsc_dev_is_vf(xdev))
77 : 0 : cmdq->config = &xsc_pf_config;
78 : : else
79 : 0 : cmdq->config = &xsc_vf_config;
80 : : }
81 : :
82 : : static void
83 : 0 : xsc_cmdq_rsp_cid_update(struct xsc_dev *xdev, struct xsc_cmd_queue *cmdq)
84 : : {
85 : : uint32_t rsp_pid;
86 : :
87 : 0 : cmdq->rsp_cid = rte_read32((uint8_t *)xdev->bar_addr + cmdq->config->rsp_cid_addr);
88 : 0 : rsp_pid = rte_read32((uint8_t *)xdev->bar_addr + cmdq->config->rsp_pid_addr);
89 [ # # ]: 0 : if (rsp_pid != cmdq->rsp_cid) {
90 : 0 : PMD_DRV_LOG(INFO, "Update cid(%u) to latest pid(%u)",
91 : : cmdq->rsp_cid, rsp_pid);
92 : 0 : cmdq->rsp_cid = rsp_pid;
93 : 0 : rte_write32(cmdq->rsp_cid, (uint8_t *)xdev->bar_addr + cmdq->config->rsp_cid_addr);
94 : : }
95 : 0 : }
96 : :
97 : : static void
98 : : xsc_cmdq_depth_set(struct xsc_dev *xdev, struct xsc_cmd_queue *cmdq)
99 : : {
100 : 0 : cmdq->depth_n = XSC_CMDQ_DEPTH_LOG;
101 : 0 : cmdq->depth_m = (1 << XSC_CMDQ_DEPTH_LOG) - 1;
102 : 0 : rte_write32(1 << cmdq->depth_n, (uint8_t *)xdev->bar_addr + cmdq->config->depth_addr);
103 : : }
104 : :
105 : : static int
106 : 0 : xsc_cmdq_elt_size_check(struct xsc_dev *xdev, struct xsc_cmd_queue *cmdq)
107 : : {
108 : : uint32_t elts_n;
109 : :
110 : 0 : elts_n = rte_read32((uint8_t *)xdev->bar_addr + cmdq->config->elt_sz_addr);
111 [ # # ]: 0 : if (elts_n != XSC_CMDQ_ELEMENT_SIZE_LOG) {
112 : 0 : PMD_DRV_LOG(ERR, "The cmdq elt size log(%u) is error, should be %u",
113 : : elts_n, XSC_CMDQ_ELEMENT_SIZE_LOG);
114 : 0 : rte_errno = ENODEV;
115 : 0 : return -1;
116 : : }
117 : :
118 : : return 0;
119 : : }
120 : :
121 : : static void
122 : : xsc_cmdq_req_base_addr_set(struct xsc_dev *xdev, struct xsc_cmd_queue *cmdq)
123 : : {
124 : : uint32_t h_addr, l_addr;
125 : :
126 : 0 : h_addr = (uint32_t)(cmdq->req_mz->iova >> 32);
127 : 0 : l_addr = (uint32_t)(cmdq->req_mz->iova);
128 : 0 : rte_write32(h_addr, (uint8_t *)xdev->bar_addr + cmdq->config->req_h_addr);
129 : 0 : rte_write32(l_addr, (uint8_t *)xdev->bar_addr + cmdq->config->req_l_addr);
130 : : }
131 : :
132 : : static void
133 : : xsc_cmdq_rsp_base_addr_set(struct xsc_dev *xdev, struct xsc_cmd_queue *cmdq)
134 : : {
135 : : uint32_t h_addr, l_addr;
136 : :
137 : 0 : h_addr = (uint32_t)(cmdq->rsp_mz->iova >> 32);
138 : 0 : l_addr = (uint32_t)(cmdq->rsp_mz->iova);
139 : 0 : rte_write32(h_addr, (uint8_t *)xdev->bar_addr + cmdq->config->rsp_h_addr);
140 : 0 : rte_write32(l_addr, (uint8_t *)xdev->bar_addr + cmdq->config->rsp_l_addr);
141 : : }
142 : :
143 : : static void
144 : 0 : xsc_cmdq_mbox_free(struct xsc_dev *xdev, struct xsc_cmdq_mbox *mbox)
145 : : {
146 : : struct xsc_cmdq_mbox *next, *head;
147 : 0 : struct xsc_vfio_priv *priv = xdev->dev_priv;
148 : :
149 : : head = mbox;
150 [ # # ]: 0 : while (head != NULL) {
151 : 0 : next = head->next;
152 [ # # ]: 0 : if (head->buf != NULL)
153 [ # # ]: 0 : rte_mempool_put(priv->cmdq->mbox_buf_pool, head->buf);
154 : 0 : free(head);
155 : : head = next;
156 : : }
157 : 0 : }
158 : :
159 : : static struct xsc_cmdq_mbox *
160 : 0 : xsc_cmdq_mbox_alloc(struct xsc_dev *xdev)
161 : : {
162 : : struct xsc_cmdq_mbox *mbox;
163 : : int ret;
164 : 0 : struct xsc_vfio_priv *priv = (struct xsc_vfio_priv *)xdev->dev_priv;
165 : :
166 : 0 : mbox = malloc(sizeof(*mbox));
167 [ # # ]: 0 : if (mbox == NULL) {
168 : 0 : rte_errno = -ENOMEM;
169 : 0 : goto error;
170 : : }
171 : : memset(mbox, 0, sizeof(struct xsc_cmdq_mbox));
172 : :
173 [ # # ]: 0 : ret = rte_mempool_get(priv->cmdq->mbox_buf_pool, (void **)&mbox->buf);
174 [ # # ]: 0 : if (ret != 0)
175 : 0 : goto error;
176 : 0 : mbox->buf_dma = rte_mempool_virt2iova(mbox->buf);
177 : : memset(mbox->buf, 0, sizeof(struct xsc_cmdq_mbox_buf));
178 : 0 : mbox->next = NULL;
179 : :
180 : 0 : return mbox;
181 : :
182 : 0 : error:
183 : 0 : xsc_cmdq_mbox_free(xdev, mbox);
184 : 0 : return NULL;
185 : : }
186 : :
187 : : static struct xsc_cmdq_mbox *
188 : 0 : xsc_cmdq_mbox_alloc_bulk(struct xsc_dev *xdev, int n)
189 : : {
190 : : int i;
191 : : struct xsc_cmdq_mbox *head = NULL;
192 : : struct xsc_cmdq_mbox *mbox;
193 : : struct xsc_cmdq_mbox_buf *mbox_buf;
194 : :
195 [ # # ]: 0 : for (i = 0; i < n; i++) {
196 : 0 : mbox = xsc_cmdq_mbox_alloc(xdev);
197 [ # # ]: 0 : if (mbox == NULL) {
198 : 0 : PMD_DRV_LOG(ERR, "Failed to alloc mailbox");
199 : 0 : goto error;
200 : : }
201 : :
202 : 0 : mbox_buf = mbox->buf;
203 : 0 : mbox->next = head;
204 [ # # # # ]: 0 : mbox_buf->next = rte_cpu_to_be_64(mbox->next ? mbox->next->buf_dma : 0);
205 [ # # ]: 0 : mbox_buf->block_num = rte_cpu_to_be_32(n - i - 1);
206 : : head = mbox;
207 : : }
208 : :
209 : : return head;
210 : :
211 : : error:
212 : 0 : xsc_cmdq_mbox_free(xdev, head);
213 : 0 : return NULL;
214 : : }
215 : :
216 : : static void
217 : 0 : xsc_cmdq_req_msg_free(struct xsc_dev *xdev, struct xsc_cmdq_req_msg *msg)
218 : : {
219 : : struct xsc_cmdq_mbox *head;
220 : :
221 [ # # ]: 0 : if (msg == NULL)
222 : : return;
223 : :
224 : 0 : head = msg->next;
225 : 0 : xsc_cmdq_mbox_free(xdev, head);
226 : 0 : free(msg);
227 : : }
228 : :
229 : : static struct xsc_cmdq_req_msg *
230 : 0 : xsc_cmdq_req_msg_alloc(struct xsc_dev *xdev, int len)
231 : : {
232 : : struct xsc_cmdq_req_msg *msg;
233 : : struct xsc_cmdq_mbox *head = NULL;
234 : : int cmd_len, nb_mbox;
235 : :
236 : 0 : msg = malloc(sizeof(*msg));
237 [ # # ]: 0 : if (msg == NULL) {
238 : 0 : rte_errno = -ENOMEM;
239 : 0 : goto error;
240 : : }
241 : : memset(msg, 0, sizeof(*msg));
242 : :
243 : 0 : cmd_len = len - RTE_MIN(sizeof(msg->hdr.data), (uint32_t)len);
244 : 0 : nb_mbox = (cmd_len + XSC_CMDQ_DATA_SIZE - 1) / XSC_CMDQ_DATA_SIZE;
245 : 0 : head = xsc_cmdq_mbox_alloc_bulk(xdev, nb_mbox);
246 [ # # ]: 0 : if (head == NULL && nb_mbox != 0)
247 : 0 : goto error;
248 : :
249 : 0 : msg->next = head;
250 : 0 : msg->len = len;
251 : :
252 : 0 : return msg;
253 : :
254 : 0 : error:
255 : 0 : xsc_cmdq_req_msg_free(xdev, msg);
256 : 0 : return NULL;
257 : : }
258 : :
259 : : static void
260 : 0 : xsc_cmdq_rsp_msg_free(struct xsc_dev *xdev, struct xsc_cmdq_rsp_msg *msg)
261 : : {
262 : : struct xsc_cmdq_mbox *head;
263 : :
264 [ # # ]: 0 : if (msg == NULL)
265 : : return;
266 : :
267 : 0 : head = msg->next;
268 : 0 : xsc_cmdq_mbox_free(xdev, head);
269 : 0 : free(msg);
270 : : }
271 : :
272 : : static struct xsc_cmdq_rsp_msg *
273 : 0 : xsc_cmdq_rsp_msg_alloc(struct xsc_dev *xdev, int len)
274 : : {
275 : : struct xsc_cmdq_rsp_msg *msg;
276 : : struct xsc_cmdq_mbox *head = NULL;
277 : : int cmd_len, nb_mbox;
278 : :
279 : 0 : msg = malloc(sizeof(*msg));
280 [ # # ]: 0 : if (msg == NULL) {
281 : 0 : rte_errno = -ENOMEM;
282 : 0 : goto error;
283 : : }
284 : : memset(msg, 0, sizeof(*msg));
285 : :
286 : 0 : cmd_len = len - RTE_MIN(sizeof(msg->hdr.data), (uint32_t)len);
287 : 0 : nb_mbox = (cmd_len + XSC_CMDQ_DATA_SIZE - 1) / XSC_CMDQ_DATA_SIZE;
288 : 0 : head = xsc_cmdq_mbox_alloc_bulk(xdev, nb_mbox);
289 [ # # ]: 0 : if (head == NULL && nb_mbox != 0)
290 : 0 : goto error;
291 : :
292 : 0 : msg->next = head;
293 : 0 : msg->len = len;
294 : :
295 : 0 : return msg;
296 : :
297 : 0 : error:
298 : 0 : xsc_cmdq_rsp_msg_free(xdev, msg);
299 : 0 : return NULL;
300 : : }
301 : :
302 : : static void
303 : : xsc_cmdq_msg_destruct(struct xsc_dev *xdev,
304 : : struct xsc_cmdq_req_msg **req_msg,
305 : : struct xsc_cmdq_rsp_msg **rsp_msg)
306 : : {
307 : 0 : xsc_cmdq_req_msg_free(xdev, *req_msg);
308 : 0 : xsc_cmdq_rsp_msg_free(xdev, *rsp_msg);
309 : 0 : *req_msg = NULL;
310 : 0 : *rsp_msg = NULL;
311 : : }
312 : :
313 : : static int
314 : 0 : xsc_cmdq_msg_construct(struct xsc_dev *xdev,
315 : : struct xsc_cmdq_req_msg **req_msg, int in_len,
316 : : struct xsc_cmdq_rsp_msg **rsp_msg, int out_len)
317 : : {
318 : 0 : *req_msg = xsc_cmdq_req_msg_alloc(xdev, in_len);
319 [ # # ]: 0 : if (*req_msg == NULL) {
320 : 0 : PMD_DRV_LOG(ERR, "Failed to alloc xsc cmd request msg");
321 : 0 : goto error;
322 : : }
323 : :
324 : 0 : *rsp_msg = xsc_cmdq_rsp_msg_alloc(xdev, out_len);
325 [ # # ]: 0 : if (*rsp_msg == NULL) {
326 : 0 : PMD_DRV_LOG(ERR, "Failed to alloc xsc cmd response msg");
327 : 0 : goto error;
328 : : }
329 : :
330 : : return 0;
331 : :
332 : 0 : error:
333 : : xsc_cmdq_msg_destruct(xdev, req_msg, rsp_msg);
334 : 0 : return -1;
335 : : }
336 : :
337 : : static int
338 : 0 : xsc_cmdq_req_msg_copy(struct xsc_cmdq_req_msg *req_msg, void *data_in, int in_len)
339 : : {
340 : : struct xsc_cmdq_mbox_buf *mbox_buf;
341 : : struct xsc_cmdq_mbox *mbox;
342 : : int copy;
343 : : uint8_t *data = data_in;
344 : :
345 [ # # ]: 0 : if (req_msg == NULL || data == NULL)
346 : : return -1;
347 : :
348 : 0 : copy = RTE_MIN((uint32_t)in_len, sizeof(req_msg->hdr.data));
349 : 0 : memcpy(req_msg->hdr.data, data, copy);
350 : :
351 : 0 : in_len -= copy;
352 : 0 : data += copy;
353 : :
354 : 0 : mbox = req_msg->next;
355 [ # # ]: 0 : while (in_len > 0) {
356 [ # # ]: 0 : if (mbox == NULL)
357 : : return -1;
358 : :
359 : 0 : copy = RTE_MIN(in_len, XSC_CMDQ_DATA_SIZE);
360 : 0 : mbox_buf = mbox->buf;
361 : 0 : memcpy(mbox_buf->data, data, copy);
362 : 0 : mbox_buf->owner_status = 0;
363 : 0 : data += copy;
364 : 0 : in_len -= copy;
365 : 0 : mbox = mbox->next;
366 : : }
367 : :
368 : : return 0;
369 : : }
370 : :
371 : : static int
372 : 0 : xsc_cmdq_rsp_msg_copy(void *data_out, struct xsc_cmdq_rsp_msg *rsp_msg, int out_len)
373 : : {
374 : : struct xsc_cmdq_mbox_buf *mbox_buf;
375 : : struct xsc_cmdq_mbox *mbox;
376 : : int copy;
377 : : uint8_t *data = data_out;
378 : :
379 [ # # ]: 0 : if (data == NULL || rsp_msg == NULL)
380 : : return -1;
381 : :
382 : 0 : copy = RTE_MIN((uint32_t)out_len, sizeof(rsp_msg->hdr.data));
383 : 0 : memcpy(data, rsp_msg->hdr.data, copy);
384 : 0 : out_len -= copy;
385 : 0 : data += copy;
386 : :
387 : 0 : mbox = rsp_msg->next;
388 [ # # ]: 0 : while (out_len > 0) {
389 [ # # ]: 0 : if (mbox == NULL)
390 : : return -1;
391 : 0 : copy = RTE_MIN(out_len, XSC_CMDQ_DATA_SIZE);
392 : 0 : mbox_buf = mbox->buf;
393 [ # # ]: 0 : if (!mbox_buf->owner_status)
394 : 0 : PMD_DRV_LOG(ERR, "Failed to check cmd owner");
395 : 0 : memcpy(data, mbox_buf->data, copy);
396 : 0 : data += copy;
397 : 0 : out_len -= copy;
398 : 0 : mbox = mbox->next;
399 : : }
400 : :
401 : : return 0;
402 : : }
403 : :
404 : : static enum xsc_cmd_status
405 : 0 : xsc_cmdq_wait_completion(struct xsc_dev *xdev, struct xsc_cmdq_rsp_msg *rsp_msg)
406 : : {
407 : 0 : struct xsc_vfio_priv *priv = (struct xsc_vfio_priv *)xdev->dev_priv;
408 : 0 : struct xsc_cmd_queue *cmdq = priv->cmdq;
409 : : volatile struct xsc_cmdq_rsp_layout *rsp_lay;
410 : : struct xsc_cmd_outbox_hdr *out_hdr = (struct xsc_cmd_outbox_hdr *)rsp_msg->hdr.data;
411 : : int count = (XSC_CMDQ_WAIT_TIMEOUT * 1000) / XSC_CMDQ_WAIT_DELAY_MS;
412 : : uint32_t rsp_pid;
413 : : uint8_t cmd_status;
414 : : uint32_t i;
415 : :
416 [ # # ]: 0 : while (count-- > 0) {
417 : 0 : rsp_pid = rte_read32((uint8_t *)xdev->bar_addr + cmdq->config->rsp_pid_addr);
418 [ # # ]: 0 : if (rsp_pid == cmdq->rsp_cid) {
419 : : rte_delay_ms(XSC_CMDQ_WAIT_DELAY_MS);
420 : 0 : continue;
421 : : }
422 : :
423 : 0 : rsp_lay = cmdq->rsp_lay + cmdq->rsp_cid;
424 [ # # ]: 0 : if (cmdq->owner_learn == 0) {
425 : : /* First time learning owner_bit from hardware */
426 : 0 : cmdq->owner_bit = rsp_lay->owner_bit;
427 : 0 : cmdq->owner_learn = 1;
428 : : }
429 : :
430 : : /* Waiting for dma to complete */
431 [ # # ]: 0 : if (cmdq->owner_bit != rsp_lay->owner_bit)
432 : 0 : continue;
433 : :
434 [ # # ]: 0 : for (i = 0; i < XSC_CMDQ_RSP_INLINE_SIZE; i++)
435 : 0 : rsp_msg->hdr.data[i] = rsp_lay->out[i];
436 : :
437 : 0 : cmdq->rsp_cid = (cmdq->rsp_cid + 1) & cmdq->depth_m;
438 : 0 : rte_write32(cmdq->rsp_cid, (uint8_t *)xdev->bar_addr + cmdq->config->rsp_cid_addr);
439 : :
440 : : /* Change owner bit */
441 [ # # ]: 0 : if (cmdq->rsp_cid == 0)
442 : 0 : cmdq->owner_bit = !cmdq->owner_bit;
443 : :
444 : 0 : cmd_status = out_hdr->status;
445 [ # # ]: 0 : if (cmd_status != 0)
446 : 0 : return XSC_CMD_FAIL;
447 : : return XSC_CMD_SUCC;
448 : : }
449 : :
450 : : return XSC_CMD_TIMEOUT;
451 : : }
452 : :
453 : : static int
454 : 0 : xsc_cmdq_dummy_invoke(struct xsc_dev *xdev, struct xsc_cmd_queue *cmdq, uint32_t start, int num)
455 : : {
456 : : struct xsc_cmdq_dummy_mbox_in in;
457 : : struct xsc_cmdq_dummy_mbox_out out;
458 : 0 : struct xsc_cmdq_req_msg *req_msg = NULL;
459 : 0 : struct xsc_cmdq_rsp_msg *rsp_msg = NULL;
460 : : struct xsc_cmdq_req_layout *req_lay;
461 : : int in_len = sizeof(in);
462 : : int out_len = sizeof(out);
463 : : int ret, i;
464 : : uint32_t start_pid = start;
465 : :
466 : : memset(&in, 0, sizeof(in));
467 : 0 : in.hdr.opcode = rte_cpu_to_be_16(XSC_CMD_OP_DUMMY);
468 : :
469 : 0 : ret = xsc_cmdq_msg_construct(xdev, &req_msg, in_len, &rsp_msg, out_len);
470 [ # # ]: 0 : if (ret != 0) {
471 : 0 : PMD_DRV_LOG(ERR, "Failed to construct cmd msg for dummy exec");
472 : 0 : return -1;
473 : : }
474 : :
475 : 0 : ret = xsc_cmdq_req_msg_copy(req_msg, &in, in_len);
476 [ # # ]: 0 : if (ret != 0) {
477 : 0 : PMD_DRV_LOG(ERR, "Failed to copy cmd buf to request msg for dummy exec");
478 : 0 : goto error;
479 : : }
480 : :
481 : 0 : rte_spinlock_lock(&cmdq->lock);
482 : :
483 [ # # ]: 0 : for (i = 0; i < num; i++) {
484 [ # # ]: 0 : req_lay = cmdq->req_lay + start_pid;
485 : : memset(req_lay, 0, sizeof(*req_lay));
486 [ # # ]: 0 : memcpy(req_lay->in, req_msg->hdr.data, sizeof(req_lay->in));
487 [ # # ]: 0 : req_lay->inlen = rte_cpu_to_be_32(req_msg->len);
488 [ # # ]: 0 : req_lay->outlen = rte_cpu_to_be_32(rsp_msg->len);
489 : 0 : req_lay->sig = 0xff;
490 : : req_lay->idx = 0;
491 : 0 : req_lay->type = XSC_CMDQ_REQ_TYPE;
492 : 0 : start_pid = (start_pid + 1) & cmdq->depth_m;
493 : : }
494 : :
495 : : /* Ring doorbell after the descriptor is valid */
496 : 0 : rte_write32(cmdq->req_pid, (uint8_t *)xdev->bar_addr + cmdq->config->req_pid_addr);
497 : :
498 : 0 : ret = xsc_cmdq_wait_completion(xdev, rsp_msg);
499 : : rte_spinlock_unlock(&cmdq->lock);
500 : :
501 : 0 : error:
502 : : xsc_cmdq_msg_destruct(xdev, &req_msg, &rsp_msg);
503 : 0 : return ret;
504 : : }
505 : :
506 : : static int
507 : 0 : xsc_cmdq_req_status_restore(struct xsc_dev *xdev, struct xsc_cmd_queue *cmdq)
508 : : {
509 : : uint32_t req_pid, req_cid;
510 : : uint32_t cnt;
511 : :
512 : 0 : req_pid = rte_read32((uint8_t *)xdev->bar_addr + cmdq->config->req_pid_addr);
513 : 0 : req_cid = rte_read32((uint8_t *)xdev->bar_addr + cmdq->config->req_cid_addr);
514 : :
515 [ # # # # ]: 0 : if (req_pid >= (uint32_t)(1 << cmdq->depth_n) ||
516 : : req_cid >= (uint32_t)(1 << cmdq->depth_n)) {
517 : 0 : PMD_DRV_LOG(ERR, "Request pid %u and cid %u must be less than %u",
518 : : req_pid, req_cid, 1 << cmdq->depth_n);
519 : 0 : return -1;
520 : : }
521 : :
522 : 0 : cmdq->req_pid = req_pid;
523 [ # # ]: 0 : if (req_pid == req_cid)
524 : : return 0;
525 : :
526 [ # # ]: 0 : cnt = (req_pid > req_cid) ? (req_pid - req_cid) :
527 : 0 : ((1 << cmdq->depth_n) + req_pid - req_cid);
528 [ # # ]: 0 : if (xsc_cmdq_dummy_invoke(xdev, cmdq, req_cid, cnt) != 0) {
529 : 0 : PMD_DRV_LOG(ERR, "Failed to dummy invoke xsc cmd");
530 : 0 : return -1;
531 : : }
532 : :
533 : : return 0;
534 : : }
535 : :
536 : : void
537 : 0 : xsc_vfio_mbox_destroy(struct xsc_cmd_queue *cmdq)
538 : : {
539 [ # # ]: 0 : if (cmdq == NULL)
540 : : return;
541 : :
542 : 0 : rte_memzone_free(cmdq->req_mz);
543 : 0 : rte_memzone_free(cmdq->rsp_mz);
544 : 0 : rte_mempool_free(cmdq->mbox_buf_pool);
545 : 0 : rte_free(cmdq);
546 : : }
547 : :
548 : : int
549 : 0 : xsc_vfio_mbox_init(struct xsc_dev *xdev)
550 : : {
551 : : struct xsc_cmd_queue *cmdq;
552 : 0 : struct xsc_vfio_priv *priv = (struct xsc_vfio_priv *)xdev->dev_priv;
553 : 0 : char name[RTE_MEMZONE_NAMESIZE] = { 0 };
554 : : uint32_t size;
555 : :
556 : 0 : cmdq = rte_zmalloc(NULL, sizeof(*cmdq), RTE_CACHE_LINE_SIZE);
557 [ # # ]: 0 : if (cmdq == NULL) {
558 : 0 : PMD_DRV_LOG(ERR, "Failed to alloc memory for xsc_cmd_queue");
559 : 0 : return -1;
560 : : }
561 : :
562 : 0 : snprintf(name, RTE_MEMZONE_NAMESIZE, "%s_cmdq", xdev->pci_dev->device.name);
563 : : size = (1 << XSC_CMDQ_DEPTH_LOG) * sizeof(struct xsc_cmdq_req_layout);
564 : 0 : cmdq->req_mz = rte_memzone_reserve_aligned(name,
565 : : size, SOCKET_ID_ANY,
566 : : RTE_MEMZONE_IOVA_CONTIG,
567 : : XSC_PAGE_SIZE);
568 [ # # ]: 0 : if (cmdq->req_mz == NULL) {
569 : 0 : PMD_DRV_LOG(ERR, "Failed to alloc memory for cmd queue");
570 : 0 : goto error;
571 : : }
572 : 0 : cmdq->req_lay = cmdq->req_mz->addr;
573 : :
574 : 0 : snprintf(name, RTE_MEMZONE_NAMESIZE, "%s_cmd_cq", xdev->pci_dev->device.name);
575 : : size = (1 << XSC_CMDQ_DEPTH_LOG) * sizeof(struct xsc_cmdq_rsp_layout);
576 : 0 : cmdq->rsp_mz = rte_memzone_reserve_aligned(name,
577 : : size, SOCKET_ID_ANY,
578 : : RTE_MEMZONE_IOVA_CONTIG,
579 : : XSC_PAGE_SIZE);
580 [ # # ]: 0 : if (cmdq->rsp_mz == NULL) {
581 : 0 : PMD_DRV_LOG(ERR, "Failed to alloc memory for cmd cq");
582 : 0 : goto error;
583 : : }
584 : 0 : cmdq->rsp_lay = cmdq->rsp_mz->addr;
585 : :
586 : 0 : snprintf(name, RTE_MEMZONE_NAMESIZE, "%s_mempool", xdev->pci_dev->device.name);
587 : 0 : cmdq->mbox_buf_pool = rte_mempool_create(name, XSC_MBOX_BUF_NUM,
588 : : sizeof(struct xsc_cmdq_mbox_buf),
589 : : XSC_MBOX_BUF_CACHE_SIZE, 0,
590 : : NULL, NULL, NULL, NULL,
591 : : SOCKET_ID_ANY, 0);
592 [ # # ]: 0 : if (cmdq->mbox_buf_pool == NULL) {
593 : 0 : PMD_DRV_LOG(ERR, "Failed to create mailbox buf pool");
594 : 0 : goto error;
595 : : }
596 : :
597 : : xsc_cmdq_config_init(xdev, cmdq);
598 : 0 : xsc_cmdq_rsp_cid_update(xdev, cmdq);
599 : : xsc_cmdq_depth_set(xdev, cmdq);
600 [ # # ]: 0 : if (xsc_cmdq_elt_size_check(xdev, cmdq) != 0)
601 : 0 : goto error;
602 : :
603 : : xsc_cmdq_req_base_addr_set(xdev, cmdq);
604 : : xsc_cmdq_rsp_base_addr_set(xdev, cmdq);
605 : : /* Check request status and restore it */
606 [ # # ]: 0 : if (xsc_cmdq_req_status_restore(xdev, cmdq) != 0)
607 : 0 : goto error;
608 : :
609 : : rte_spinlock_init(&cmdq->lock);
610 : 0 : priv->cmdq = cmdq;
611 : 0 : return 0;
612 : :
613 : 0 : error:
614 : 0 : xsc_vfio_mbox_destroy(cmdq);
615 : 0 : return -1;
616 : : }
617 : :
618 : : static enum xsc_cmd_status
619 : 0 : xsc_cmdq_invoke(struct xsc_dev *xdev, struct xsc_cmdq_req_msg *req_msg,
620 : : struct xsc_cmdq_rsp_msg *rsp_msg)
621 : : {
622 : 0 : struct xsc_vfio_priv *priv = (struct xsc_vfio_priv *)xdev->dev_priv;
623 : 0 : struct xsc_cmd_queue *cmdq = priv->cmdq;
624 : : struct xsc_cmdq_req_layout *req_lay;
625 : : enum xsc_cmd_status status = XSC_CMD_FAIL;
626 : :
627 : 0 : rte_spinlock_lock(&cmdq->lock);
628 [ # # ]: 0 : req_lay = cmdq->req_lay + cmdq->req_pid;
629 : : memset(req_lay, 0, sizeof(*req_lay));
630 [ # # ]: 0 : memcpy(req_lay->in, req_msg->hdr.data, sizeof(req_lay->in));
631 [ # # ]: 0 : if (req_msg->next != NULL)
632 [ # # ]: 0 : req_lay->in_ptr = rte_cpu_to_be_64(req_msg->next->buf_dma);
633 [ # # ]: 0 : req_lay->inlen = rte_cpu_to_be_32(req_msg->len);
634 : :
635 [ # # ]: 0 : if (rsp_msg->next != NULL)
636 [ # # ]: 0 : req_lay->out_ptr = rte_cpu_to_be_64(rsp_msg->next->buf_dma);
637 [ # # ]: 0 : req_lay->outlen = rte_cpu_to_be_32(rsp_msg->len);
638 : :
639 : 0 : req_lay->sig = 0xff;
640 : : req_lay->idx = 0;
641 : 0 : req_lay->type = XSC_CMDQ_REQ_TYPE;
642 : :
643 : : /* Ring doorbell after the descriptor is valid */
644 : 0 : cmdq->req_pid = (cmdq->req_pid + 1) & cmdq->depth_m;
645 : 0 : rte_write32(cmdq->req_pid, (uint8_t *)xdev->bar_addr + cmdq->config->req_pid_addr);
646 : :
647 : 0 : status = xsc_cmdq_wait_completion(xdev, rsp_msg);
648 : : rte_spinlock_unlock(&cmdq->lock);
649 : :
650 : 0 : return status;
651 : : }
652 : :
653 : : int
654 : 0 : xsc_vfio_mbox_exec(struct xsc_dev *xdev, void *data_in,
655 : : int in_len, void *data_out, int out_len)
656 : : {
657 : 0 : struct xsc_cmdq_req_msg *req_msg = NULL;
658 : 0 : struct xsc_cmdq_rsp_msg *rsp_msg = NULL;
659 : : int ret;
660 : : enum xsc_cmd_status status;
661 : :
662 : 0 : ret = xsc_cmdq_msg_construct(xdev, &req_msg, in_len, &rsp_msg, out_len);
663 [ # # ]: 0 : if (ret != 0) {
664 : 0 : PMD_DRV_LOG(ERR, "Failed to construct cmd msg");
665 : 0 : return -1;
666 : : }
667 : :
668 : 0 : ret = xsc_cmdq_req_msg_copy(req_msg, data_in, in_len);
669 [ # # ]: 0 : if (ret != 0) {
670 : 0 : PMD_DRV_LOG(ERR, "Failed to copy cmd buf to request msg");
671 : 0 : goto error;
672 : : }
673 : :
674 : 0 : status = xsc_cmdq_invoke(xdev, req_msg, rsp_msg);
675 [ # # ]: 0 : if (status != XSC_CMD_SUCC) {
676 : 0 : PMD_DRV_LOG(ERR, "Failed to invoke xsc cmd, %s",
677 : : xsc_cmd_error[status]);
678 : : ret = -1;
679 : 0 : goto error;
680 : : }
681 : :
682 : 0 : ret = xsc_cmdq_rsp_msg_copy(data_out, rsp_msg, out_len);
683 [ # # ]: 0 : if (ret != 0) {
684 : 0 : PMD_DRV_LOG(ERR, "Failed to copy response msg to out data");
685 : 0 : goto error;
686 : : }
687 : :
688 : 0 : error:
689 : : xsc_cmdq_msg_destruct(xdev, &req_msg, &rsp_msg);
690 : 0 : return ret;
691 : : }
|