Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright 2025 Yunsilicon Technology Co., Ltd.
3 : : */
4 : :
5 : : #include <sys/mman.h>
6 : : #include <sys/types.h>
7 : : #include <sys/stat.h>
8 : : #include <fcntl.h>
9 : :
10 : : #include <rte_pci.h>
11 : : #include <ethdev_pci.h>
12 : : #include <rte_bus_pci.h>
13 : : #include <rte_bitops.h>
14 : :
15 : : #include "xsc_defs.h"
16 : : #include "xsc_vfio_mbox.h"
17 : : #include "xsc_ethdev.h"
18 : : #include "xsc_rxtx.h"
19 : :
20 : : #define XSC_FEATURE_ONCHIP_FT_MASK RTE_BIT32(4)
21 : : #define XSC_FEATURE_DMA_RW_TBL_MASK RTE_BIT32(8)
22 : : #define XSC_FEATURE_PCT_EXP_MASK RTE_BIT32(19)
23 : : #define XSC_HOST_PCIE_NO_DEFAULT 0
24 : : #define XSC_SOC_PCIE_NO_DEFAULT 1
25 : :
26 : : #define XSC_SW2HW_MTU(mtu) ((mtu) + 14 + 4)
27 : : #define XSC_SW2HW_RX_PKT_LEN(mtu) ((mtu) + 14 + 256)
28 : :
29 : : enum xsc_cq_type {
30 : : XSC_CQ_TYPE_NORMAL = 0,
31 : : XSC_CQ_TYPE_VIRTIO = 1,
32 : : };
33 : :
34 : : struct xsc_vfio_cq {
35 : : const struct rte_memzone *mz;
36 : : struct xsc_dev *xdev;
37 : : uint32_t cqn;
38 : : };
39 : :
40 : : struct xsc_vfio_qp {
41 : : const struct rte_memzone *mz;
42 : : struct xsc_dev *xdev;
43 : : uint32_t qpn;
44 : : };
45 : :
46 : : static void
47 : 0 : xsc_vfio_pcie_no_init(struct xsc_hwinfo *hwinfo)
48 : : {
49 : 0 : uint func_id = hwinfo->func_id;
50 : :
51 [ # # ]: 0 : if (func_id >= hwinfo->pf0_vf_funcid_base &&
52 [ # # ]: 0 : func_id <= hwinfo->pf0_vf_funcid_top)
53 : 0 : hwinfo->pcie_no = hwinfo->pcie_host;
54 [ # # ]: 0 : else if (func_id >= hwinfo->pf1_vf_funcid_base &&
55 [ # # ]: 0 : func_id <= hwinfo->pf1_vf_funcid_top)
56 : 0 : hwinfo->pcie_no = hwinfo->pcie_host;
57 [ # # ]: 0 : else if (func_id >= hwinfo->pcie0_pf_funcid_base &&
58 [ # # ]: 0 : func_id <= hwinfo->pcie0_pf_funcid_top)
59 : 0 : hwinfo->pcie_no = XSC_HOST_PCIE_NO_DEFAULT;
60 : : else
61 : 0 : hwinfo->pcie_no = XSC_SOC_PCIE_NO_DEFAULT;
62 : 0 : }
63 : :
64 : : static int
65 : 0 : xsc_vfio_hwinfo_init(struct xsc_dev *xdev)
66 : : {
67 : : int ret;
68 : : uint32_t feature;
69 : : int in_len, out_len, cmd_len;
70 : : struct xsc_cmd_query_hca_cap_mbox_in *in;
71 : : struct xsc_cmd_query_hca_cap_mbox_out *out;
72 : : struct xsc_cmd_hca_cap *hca_cap;
73 : : void *cmd_buf;
74 : :
75 : : in_len = sizeof(struct xsc_cmd_query_hca_cap_mbox_in);
76 : : out_len = sizeof(struct xsc_cmd_query_hca_cap_mbox_out);
77 : : cmd_len = RTE_MAX(in_len, out_len);
78 : :
79 : 0 : cmd_buf = malloc(cmd_len);
80 [ # # ]: 0 : if (cmd_buf == NULL) {
81 : 0 : PMD_DRV_LOG(ERR, "Failed to alloc dev hwinfo cmd memory");
82 : 0 : rte_errno = ENOMEM;
83 : 0 : return -rte_errno;
84 : : }
85 : :
86 : : in = cmd_buf;
87 : : memset(in, 0, cmd_len);
88 : 0 : in->hdr.opcode = rte_cpu_to_be_16(XSC_CMD_OP_QUERY_HCA_CAP);
89 : 0 : in->hdr.ver = rte_cpu_to_be_16(XSC_CMD_QUERY_HCA_CAP_V1);
90 : : out = cmd_buf;
91 : :
92 : 0 : ret = xsc_vfio_mbox_exec(xdev, in, in_len, out, out_len);
93 [ # # # # ]: 0 : if (ret != 0 || out->hdr.status != 0) {
94 : 0 : PMD_DRV_LOG(ERR, "Failed to get dev hwinfo, err=%d, out.status=%u",
95 : : ret, out->hdr.status);
96 : 0 : rte_errno = ENOEXEC;
97 : : ret = -rte_errno;
98 : 0 : goto exit;
99 : : }
100 : :
101 : : hca_cap = &out->hca_cap;
102 : 0 : xdev->hwinfo.valid = 1;
103 [ # # ]: 0 : xdev->hwinfo.func_id = rte_be_to_cpu_32(hca_cap->glb_func_id);
104 : 0 : xdev->hwinfo.pcie_host = hca_cap->pcie_host;
105 : 0 : xdev->hwinfo.mac_phy_port = hca_cap->mac_port;
106 [ # # ]: 0 : xdev->hwinfo.funcid_to_logic_port_off = rte_be_to_cpu_16(hca_cap->funcid_to_logic_port);
107 [ # # ]: 0 : xdev->hwinfo.raw_qp_id_base = rte_be_to_cpu_16(hca_cap->raweth_qp_id_base);
108 [ # # ]: 0 : xdev->hwinfo.raw_rss_qp_id_base = rte_be_to_cpu_16(hca_cap->raweth_rss_qp_id_base);
109 [ # # ]: 0 : xdev->hwinfo.pf0_vf_funcid_base = rte_be_to_cpu_16(hca_cap->pf0_vf_funcid_base);
110 [ # # ]: 0 : xdev->hwinfo.pf0_vf_funcid_top = rte_be_to_cpu_16(hca_cap->pf0_vf_funcid_top);
111 [ # # ]: 0 : xdev->hwinfo.pf1_vf_funcid_base = rte_be_to_cpu_16(hca_cap->pf1_vf_funcid_base);
112 [ # # ]: 0 : xdev->hwinfo.pf1_vf_funcid_top = rte_be_to_cpu_16(hca_cap->pf1_vf_funcid_top);
113 [ # # ]: 0 : xdev->hwinfo.pcie0_pf_funcid_base = rte_be_to_cpu_16(hca_cap->pcie0_pf_funcid_base);
114 [ # # ]: 0 : xdev->hwinfo.pcie0_pf_funcid_top = rte_be_to_cpu_16(hca_cap->pcie0_pf_funcid_top);
115 [ # # ]: 0 : xdev->hwinfo.pcie1_pf_funcid_base = rte_be_to_cpu_16(hca_cap->pcie1_pf_funcid_base);
116 [ # # ]: 0 : xdev->hwinfo.pcie1_pf_funcid_top = rte_be_to_cpu_16(hca_cap->pcie1_pf_funcid_top);
117 : 0 : xdev->hwinfo.lag_port_start = hca_cap->lag_logic_port_ofst;
118 [ # # ]: 0 : xdev->hwinfo.raw_tpe_qp_num = rte_be_to_cpu_16(hca_cap->raw_tpe_qp_num);
119 : 0 : xdev->hwinfo.send_seg_num = hca_cap->send_seg_num;
120 : 0 : xdev->hwinfo.recv_seg_num = hca_cap->recv_seg_num;
121 [ # # ]: 0 : feature = rte_be_to_cpu_32(hca_cap->feature_flag);
122 : 0 : xdev->hwinfo.on_chip_tbl_vld = (feature & XSC_FEATURE_ONCHIP_FT_MASK) ? 1 : 0;
123 : 0 : xdev->hwinfo.dma_rw_tbl_vld = (feature & XSC_FEATURE_DMA_RW_TBL_MASK) ? 1 : 0;
124 : 0 : xdev->hwinfo.pct_compress_vld = (feature & XSC_FEATURE_PCT_EXP_MASK) ? 1 : 0;
125 [ # # ]: 0 : xdev->hwinfo.chip_version = rte_be_to_cpu_32(hca_cap->chip_ver_l);
126 [ # # ]: 0 : xdev->hwinfo.hca_core_clock = rte_be_to_cpu_32(hca_cap->hca_core_clock);
127 : 0 : xdev->hwinfo.mac_bit = hca_cap->mac_bit;
128 : 0 : xsc_vfio_pcie_no_init(&xdev->hwinfo);
129 : :
130 : 0 : exit:
131 : 0 : free(cmd_buf);
132 : 0 : return ret;
133 : : }
134 : :
135 : : static int
136 : 0 : xsc_vfio_dev_open(struct xsc_dev *xdev)
137 : : {
138 : 0 : struct rte_pci_addr *addr = &xdev->pci_dev->addr;
139 : : struct xsc_vfio_priv *priv;
140 : :
141 : 0 : snprintf(xdev->name, PCI_PRI_STR_SIZE, PCI_PRI_FMT,
142 : 0 : addr->domain, addr->bus, addr->devid, addr->function);
143 : :
144 : 0 : priv = rte_zmalloc(NULL, sizeof(*priv), RTE_CACHE_LINE_SIZE);
145 [ # # ]: 0 : if (priv == NULL) {
146 : 0 : PMD_DRV_LOG(ERR, "Failed to alloc xsc vfio priv");
147 : 0 : return -ENOMEM;
148 : : }
149 : :
150 : 0 : xdev->dev_priv = (void *)priv;
151 : 0 : return 0;
152 : : }
153 : :
154 : : static int
155 : 0 : xsc_vfio_bar_init(struct xsc_dev *xdev)
156 : : {
157 : : int ret;
158 : :
159 : 0 : ret = rte_pci_map_device(xdev->pci_dev);
160 [ # # ]: 0 : if (ret) {
161 : 0 : PMD_DRV_LOG(ERR, "Failed to map pci device");
162 : 0 : return -EINVAL;
163 : : }
164 : :
165 : 0 : xdev->bar_len = xdev->pci_dev->mem_resource[0].len;
166 : 0 : xdev->bar_addr = (void *)xdev->pci_dev->mem_resource[0].addr;
167 [ # # ]: 0 : if (xdev->bar_addr == NULL) {
168 : 0 : PMD_DRV_LOG(ERR, "Failed to attach dev(%s) bar", xdev->pci_dev->device.name);
169 : 0 : return -EINVAL;
170 : : }
171 : :
172 : : return 0;
173 : : }
174 : :
175 : : static int
176 : 0 : xsc_vfio_dev_close(struct xsc_dev *xdev)
177 : : {
178 : 0 : struct xsc_vfio_priv *vfio_priv = (struct xsc_vfio_priv *)xdev->dev_priv;
179 : :
180 : 0 : xsc_vfio_mbox_destroy(vfio_priv->cmdq);
181 : 0 : rte_free(vfio_priv);
182 : :
183 : 0 : return 0;
184 : : }
185 : :
186 : : static int
187 : 0 : xsc_vfio_destroy_qp(void *qp)
188 : : {
189 : : int ret;
190 : : int in_len, out_len, cmd_len;
191 : : struct xsc_cmd_destroy_qp_mbox_in *in;
192 : : struct xsc_cmd_destroy_qp_mbox_out *out;
193 : : struct xsc_vfio_qp *data = (struct xsc_vfio_qp *)qp;
194 : : void *cmd_buf;
195 : :
196 : : in_len = sizeof(struct xsc_cmd_destroy_qp_mbox_in);
197 : : out_len = sizeof(struct xsc_cmd_destroy_qp_mbox_out);
198 : : cmd_len = RTE_MAX(in_len, out_len);
199 : :
200 : 0 : cmd_buf = malloc(cmd_len);
201 [ # # ]: 0 : if (cmd_buf == NULL) {
202 : 0 : rte_errno = ENOMEM;
203 : 0 : PMD_DRV_LOG(ERR, "Failed to alloc qp destroy cmd memory");
204 : 0 : return -rte_errno;
205 : : }
206 : :
207 : : in = cmd_buf;
208 : : memset(in, 0, cmd_len);
209 : 0 : in->hdr.opcode = rte_cpu_to_be_16(XSC_CMD_OP_DESTROY_QP);
210 [ # # ]: 0 : in->qpn = rte_cpu_to_be_32(data->qpn);
211 : : out = cmd_buf;
212 : 0 : ret = xsc_vfio_mbox_exec(data->xdev, in, in_len, out, out_len);
213 [ # # # # ]: 0 : if (ret != 0 || out->hdr.status != 0) {
214 : 0 : PMD_DRV_LOG(ERR, "Failed to destroy qp, type=%d, err=%d, out.status=%u",
215 : : XSC_QUEUE_TYPE_RAW, ret, out->hdr.status);
216 : 0 : rte_errno = ENOEXEC;
217 : : ret = -rte_errno;
218 : 0 : goto exit;
219 : : }
220 : :
221 : 0 : rte_memzone_free(data->mz);
222 : 0 : rte_free(qp);
223 : :
224 : 0 : exit:
225 : 0 : free(cmd_buf);
226 : 0 : return ret;
227 : : }
228 : :
229 : : static int
230 : 0 : xsc_vfio_destroy_cq(void *cq)
231 : : {
232 : : int ret;
233 : : int in_len, out_len, cmd_len;
234 : : struct xsc_cmd_destroy_cq_mbox_in *in;
235 : : struct xsc_cmd_destroy_cq_mbox_out *out;
236 : : struct xsc_vfio_cq *data = (struct xsc_vfio_cq *)cq;
237 : : void *cmd_buf;
238 : :
239 : : in_len = sizeof(struct xsc_cmd_destroy_cq_mbox_in);
240 : : out_len = sizeof(struct xsc_cmd_destroy_cq_mbox_out);
241 : : cmd_len = RTE_MAX(in_len, out_len);
242 : :
243 : 0 : cmd_buf = malloc(cmd_len);
244 [ # # ]: 0 : if (cmd_buf == NULL) {
245 : 0 : rte_errno = ENOMEM;
246 : 0 : PMD_DRV_LOG(ERR, "Failed to alloc cq destroy cmd memory");
247 : 0 : return -rte_errno;
248 : : }
249 : :
250 : : in = cmd_buf;
251 : : memset(in, 0, cmd_len);
252 : :
253 : 0 : in->hdr.opcode = rte_cpu_to_be_16(XSC_CMD_OP_DESTROY_CQ);
254 [ # # ]: 0 : in->cqn = rte_cpu_to_be_32(data->cqn);
255 : : out = cmd_buf;
256 : 0 : ret = xsc_vfio_mbox_exec(data->xdev, in, in_len, out, out_len);
257 [ # # # # ]: 0 : if (ret != 0 || out->hdr.status != 0) {
258 : 0 : PMD_DRV_LOG(ERR, "Failed to destroy cq, type=%d, err=%d, out.status=%u",
259 : : XSC_QUEUE_TYPE_RAW, ret, out->hdr.status);
260 : 0 : rte_errno = ENOEXEC;
261 : : ret = -rte_errno;
262 : 0 : goto exit;
263 : : }
264 : :
265 : 0 : rte_memzone_free(data->mz);
266 : 0 : rte_free(cq);
267 : :
268 : 0 : exit:
269 : 0 : free(cmd_buf);
270 : 0 : return ret;
271 : : }
272 : :
273 : : static int
274 : 0 : xsc_vfio_set_mtu(struct xsc_dev *xdev, uint16_t mtu)
275 : : {
276 : 0 : struct xsc_cmd_set_mtu_mbox_in in = { };
277 : 0 : struct xsc_cmd_set_mtu_mbox_out out = { };
278 : : int ret;
279 : :
280 : 0 : in.hdr.opcode = rte_cpu_to_be_16(XSC_CMD_OP_SET_MTU);
281 [ # # ]: 0 : in.mtu = rte_cpu_to_be_16(XSC_SW2HW_MTU(mtu));
282 [ # # ]: 0 : in.rx_buf_sz_min = rte_cpu_to_be_16(XSC_SW2HW_RX_PKT_LEN(mtu));
283 : 0 : in.mac_port = (uint8_t)xdev->hwinfo.mac_phy_port;
284 : :
285 : 0 : ret = xsc_vfio_mbox_exec(xdev, &in, sizeof(in), &out, sizeof(out));
286 [ # # # # ]: 0 : if (ret != 0 || out.hdr.status != 0) {
287 : 0 : PMD_DRV_LOG(ERR, "Failed to set mtu, port=%d, err=%d, out.status=%u",
288 : : xdev->port_id, ret, out.hdr.status);
289 : 0 : rte_errno = ENOEXEC;
290 : : ret = -rte_errno;
291 : : }
292 : :
293 : 0 : return ret;
294 : : }
295 : :
296 : : static int
297 : 0 : xsc_vfio_get_mac(struct xsc_dev *xdev, uint8_t *mac)
298 : : {
299 : 0 : struct xsc_cmd_query_eth_mac_mbox_in in = { };
300 : 0 : struct xsc_cmd_query_eth_mac_mbox_out out = { };
301 : : int ret;
302 : :
303 : 0 : in.hdr.opcode = rte_cpu_to_be_16(XSC_CMD_OP_QUERY_ETH_MAC);
304 : 0 : ret = xsc_vfio_mbox_exec(xdev, &in, sizeof(in), &out, sizeof(out));
305 [ # # # # ]: 0 : if (ret != 0 || out.hdr.status != 0) {
306 : 0 : PMD_DRV_LOG(ERR, "Failed to get mtu, port=%d, err=%d, out.status=%u",
307 : : xdev->port_id, ret, out.hdr.status);
308 : 0 : rte_errno = ENOEXEC;
309 : 0 : return -rte_errno;
310 : : }
311 : :
312 : : memcpy(mac, out.mac, RTE_ETHER_ADDR_LEN);
313 : :
314 : 0 : return 0;
315 : : }
316 : :
317 : : static int
318 : 0 : xsc_vfio_modify_qp_status(struct xsc_dev *xdev, uint32_t qpn, int num, int opcode)
319 : : {
320 : : int i, ret;
321 : : int in_len, out_len, cmd_len;
322 : : struct xsc_cmd_modify_qp_mbox_in *in;
323 : : struct xsc_cmd_modify_qp_mbox_out *out;
324 : : void *cmd_buf;
325 : :
326 : : in_len = sizeof(struct xsc_cmd_modify_qp_mbox_in);
327 : : out_len = sizeof(struct xsc_cmd_modify_qp_mbox_out);
328 : : cmd_len = RTE_MAX(in_len, out_len);
329 : :
330 : 0 : cmd_buf = malloc(cmd_len);
331 [ # # ]: 0 : if (cmd_buf == NULL) {
332 : 0 : PMD_DRV_LOG(ERR, "Failed to alloc cmdq qp modify status");
333 : 0 : rte_errno = ENOMEM;
334 : 0 : return -rte_errno;
335 : : }
336 : :
337 : : in = cmd_buf;
338 : : memset(in, 0, cmd_len);
339 : : out = cmd_buf;
340 : :
341 [ # # ]: 0 : for (i = 0; i < num; i++) {
342 [ # # ]: 0 : in->hdr.opcode = rte_cpu_to_be_16(opcode);
343 : 0 : in->hdr.ver = 0;
344 [ # # ]: 0 : in->qpn = rte_cpu_to_be_32(qpn + i);
345 : 0 : in->no_need_wait = 1;
346 : :
347 : 0 : ret = xsc_vfio_mbox_exec(xdev, in, in_len, out, out_len);
348 [ # # # # ]: 0 : if (ret != 0 || out->hdr.status != 0) {
349 : 0 : PMD_DRV_LOG(ERR, "Modify qp status failed, qpn=%u, err=%d, out.status=%u",
350 : : qpn + i, ret, out->hdr.status);
351 : 0 : rte_errno = ENOEXEC;
352 : : ret = -rte_errno;
353 : 0 : goto exit;
354 : : }
355 : : }
356 : :
357 : 0 : exit:
358 : 0 : free(cmd_buf);
359 : 0 : return ret;
360 : : }
361 : :
362 : : static int
363 : 0 : xsc_vfio_modify_qp_qostree(struct xsc_dev *xdev, uint16_t qpn)
364 : : {
365 : : int ret;
366 : : int in_len, out_len, cmd_len;
367 : : struct xsc_cmd_modify_raw_qp_mbox_in *in;
368 : : struct xsc_cmd_modify_raw_qp_mbox_out *out;
369 : : void *cmd_buf;
370 : :
371 : : in_len = sizeof(struct xsc_cmd_modify_raw_qp_mbox_in);
372 : : out_len = sizeof(struct xsc_cmd_modify_raw_qp_mbox_out);
373 : : cmd_len = RTE_MAX(in_len, out_len);
374 : :
375 : 0 : cmd_buf = malloc(cmd_len);
376 [ # # ]: 0 : if (cmd_buf == NULL) {
377 : 0 : PMD_DRV_LOG(ERR, "Failed to alloc cmdq qp modify qostree");
378 : 0 : rte_errno = ENOMEM;
379 : 0 : return -rte_errno;
380 : : }
381 : :
382 : : in = cmd_buf;
383 : : memset(in, 0, cmd_len);
384 : 0 : in->hdr.opcode = rte_cpu_to_be_16(XSC_CMD_OP_MODIFY_RAW_QP);
385 : : in->req.prio = 0;
386 : 0 : in->req.qp_out_port = 0xFF;
387 [ # # ]: 0 : in->req.lag_id = rte_cpu_to_be_16(xdev->hwinfo.lag_id);
388 [ # # ]: 0 : in->req.func_id = rte_cpu_to_be_16(xdev->hwinfo.func_id);
389 : : in->req.dma_direct = 0;
390 [ # # ]: 0 : in->req.qpn = rte_cpu_to_be_16(qpn);
391 : : out = cmd_buf;
392 : :
393 : 0 : ret = xsc_vfio_mbox_exec(xdev, in, in_len, out, out_len);
394 [ # # # # ]: 0 : if (ret != 0 || out->hdr.status != 0) {
395 : 0 : PMD_DRV_LOG(ERR, "Filed to modify qp qostree, qpn=%d, err=%d, out.status=%u",
396 : : qpn, ret, out->hdr.status);
397 : 0 : rte_errno = ENOEXEC;
398 : : ret = -rte_errno;
399 : 0 : goto exit;
400 : : }
401 : :
402 : 0 : exit:
403 : 0 : free(cmd_buf);
404 : 0 : return ret;
405 : : }
406 : :
407 : : static int
408 : 0 : xsc_vfio_rx_cq_create(struct xsc_dev *xdev, struct xsc_rx_cq_params *cq_params,
409 : : struct xsc_rx_cq_info *cq_info)
410 : : {
411 : : int ret;
412 : : int pa_len;
413 : : uint16_t i;
414 : : uint16_t pa_num;
415 : : uint8_t log_cq_sz;
416 : : uint16_t cqe_n;
417 : : uint32_t cqe_total_sz;
418 : : int in_len, out_len, cmd_len;
419 : 0 : char name[RTE_ETH_NAME_MAX_LEN] = { 0 };
420 : 0 : uint16_t port_id = cq_params->port_id;
421 : 0 : uint16_t idx = cq_params->qp_id;
422 : : struct xsc_vfio_cq *cq;
423 : : const struct rte_memzone *cq_pas = NULL;
424 : : struct xsc_cqe *cqes;
425 : : struct xsc_cmd_create_cq_mbox_in *in = NULL;
426 : : struct xsc_cmd_create_cq_mbox_out *out = NULL;
427 : : void *cmd_buf;
428 : :
429 : 0 : cqe_n = cq_params->wqe_s;
430 [ # # ]: 0 : log_cq_sz = rte_log2_u32(cqe_n);
431 : 0 : cqe_total_sz = cqe_n * sizeof(struct xsc_cqe);
432 : 0 : pa_num = (cqe_total_sz + XSC_PAGE_SIZE - 1) / XSC_PAGE_SIZE;
433 : 0 : pa_len = sizeof(uint64_t) * pa_num;
434 : 0 : in_len = sizeof(struct xsc_cmd_create_cq_mbox_in) + pa_len;
435 : : out_len = sizeof(struct xsc_cmd_create_cq_mbox_out);
436 : 0 : cmd_len = RTE_MAX(in_len, out_len);
437 : :
438 : 0 : cq = rte_zmalloc(NULL, sizeof(struct xsc_vfio_cq), 0);
439 [ # # ]: 0 : if (cq == NULL) {
440 : 0 : rte_errno = ENOMEM;
441 : 0 : PMD_DRV_LOG(ERR, "Failed to alloc rx cq memory");
442 : 0 : return -rte_errno;
443 : : }
444 : :
445 : 0 : cmd_buf = malloc(cmd_len);
446 [ # # ]: 0 : if (cmd_buf == NULL) {
447 : 0 : rte_errno = ENOMEM;
448 : 0 : PMD_DRV_LOG(ERR, "Failed to alloc rx cq exec cmd memory");
449 : 0 : goto error;
450 : : }
451 : :
452 : : in = cmd_buf;
453 : : memset(in, 0, cmd_len);
454 : 0 : in->hdr.opcode = rte_cpu_to_be_16(XSC_CMD_OP_CREATE_CQ);
455 : 0 : in->ctx.eqn = 0;
456 [ # # ]: 0 : in->ctx.pa_num = rte_cpu_to_be_16(pa_num);
457 [ # # ]: 0 : in->ctx.glb_func_id = rte_cpu_to_be_16((uint16_t)xdev->hwinfo.func_id);
458 : 0 : in->ctx.log_cq_sz = log_cq_sz;
459 : 0 : in->ctx.cq_type = XSC_CQ_TYPE_NORMAL;
460 : :
461 : 0 : snprintf(name, sizeof(name), "mz_cqe_mem_rx_%u_%u", port_id, idx);
462 : 0 : cq_pas = rte_memzone_reserve_aligned(name,
463 : 0 : (XSC_PAGE_SIZE * pa_num),
464 : : SOCKET_ID_ANY,
465 : : 0, XSC_PAGE_SIZE);
466 [ # # ]: 0 : if (cq_pas == NULL) {
467 : 0 : rte_errno = ENOMEM;
468 : 0 : PMD_DRV_LOG(ERR, "Failed to alloc rx cq pas memory");
469 : 0 : goto error;
470 : : }
471 : 0 : cq->mz = cq_pas;
472 : :
473 [ # # ]: 0 : for (i = 0; i < pa_num; i++)
474 [ # # ]: 0 : in->pas[i] = rte_cpu_to_be_64(cq_pas->iova + i * XSC_PAGE_SIZE);
475 : :
476 : : out = cmd_buf;
477 : 0 : ret = xsc_vfio_mbox_exec(xdev, in, in_len, out, out_len);
478 [ # # # # ]: 0 : if (ret != 0 || out->hdr.status != 0) {
479 : 0 : PMD_DRV_LOG(ERR,
480 : : "Failed to exec rx cq create cmd, port id=%d, err=%d, out.status=%u",
481 : : port_id, ret, out->hdr.status);
482 : 0 : rte_errno = ENOEXEC;
483 : 0 : goto error;
484 : : }
485 : :
486 : 0 : cq_info->cq = (void *)cq;
487 : 0 : cq_info->cqe_n = log_cq_sz;
488 : 0 : cqes = (struct xsc_cqe *)cq_pas->addr;
489 [ # # ]: 0 : for (i = 0; i < (1 << cq_info->cqe_n); i++)
490 : 0 : ((volatile struct xsc_cqe *)(cqes + i))->owner = 1;
491 : 0 : cq_info->cqes = cqes;
492 [ # # ]: 0 : if (xsc_dev_is_vf(xdev))
493 : 0 : cq_info->cq_db = (uint32_t *)((uint8_t *)xdev->bar_addr + XSC_VF_CQ_DB_ADDR);
494 : : else
495 : 0 : cq_info->cq_db = (uint32_t *)((uint8_t *)xdev->bar_addr + XSC_PF_CQ_DB_ADDR);
496 [ # # ]: 0 : cq_info->cqn = rte_be_to_cpu_32(out->cqn);
497 : 0 : cq->cqn = cq_info->cqn;
498 : 0 : cq->xdev = xdev;
499 : 0 : PMD_DRV_LOG(INFO, "Port id=%d, Rx cqe_n:%d, cqn:%u",
500 : : port_id, cq_info->cqe_n, cq_info->cqn);
501 : :
502 : 0 : free(cmd_buf);
503 : 0 : return 0;
504 : :
505 : 0 : error:
506 : 0 : free(cmd_buf);
507 : 0 : rte_memzone_free(cq_pas);
508 : 0 : rte_free(cq);
509 : 0 : return -rte_errno;
510 : : }
511 : :
512 : : static int
513 : 0 : xsc_vfio_tx_cq_create(struct xsc_dev *xdev, struct xsc_tx_cq_params *cq_params,
514 : : struct xsc_tx_cq_info *cq_info)
515 : : {
516 : : struct xsc_vfio_cq *cq = NULL;
517 : 0 : char name[RTE_ETH_NAME_MAX_LEN] = {0};
518 : : struct xsc_cmd_create_cq_mbox_in *in = NULL;
519 : : struct xsc_cmd_create_cq_mbox_out *out = NULL;
520 : : const struct rte_memzone *cq_pas = NULL;
521 : : struct xsc_cqe *cqes;
522 : : int in_len, out_len, cmd_len;
523 : : uint16_t pa_num;
524 : : uint16_t log_cq_sz;
525 : : int ret = 0;
526 : 0 : int cqe_s = 1 << cq_params->elts_n;
527 : : uint64_t iova;
528 : : int i;
529 : : void *cmd_buf = NULL;
530 : :
531 : 0 : cq = rte_zmalloc(NULL, sizeof(struct xsc_vfio_cq), 0);
532 [ # # ]: 0 : if (cq == NULL) {
533 : 0 : rte_errno = ENOMEM;
534 : 0 : PMD_DRV_LOG(ERR, "Failed to alloc tx cq memory");
535 : 0 : return -rte_errno;
536 : : }
537 : :
538 [ # # ]: 0 : log_cq_sz = rte_log2_u32(cqe_s);
539 : 0 : pa_num = (((1 << log_cq_sz) * sizeof(struct xsc_cqe)) / XSC_PAGE_SIZE);
540 : :
541 : 0 : snprintf(name, sizeof(name), "mz_cqe_mem_tx_%u_%u", cq_params->port_id, cq_params->qp_id);
542 : 0 : cq_pas = rte_memzone_reserve_aligned(name,
543 : 0 : (XSC_PAGE_SIZE * pa_num),
544 : : SOCKET_ID_ANY,
545 : : 0, XSC_PAGE_SIZE);
546 [ # # ]: 0 : if (cq_pas == NULL) {
547 : 0 : rte_errno = ENOMEM;
548 : 0 : PMD_DRV_LOG(ERR, "Failed to alloc tx cq pas memory");
549 : 0 : goto error;
550 : : }
551 : :
552 : 0 : cq->mz = cq_pas;
553 : 0 : in_len = (sizeof(struct xsc_cmd_create_cq_mbox_in) + (pa_num * sizeof(uint64_t)));
554 : : out_len = sizeof(struct xsc_cmd_create_cq_mbox_out);
555 : 0 : cmd_len = RTE_MAX(in_len, out_len);
556 : 0 : cmd_buf = malloc(cmd_len);
557 [ # # ]: 0 : if (cmd_buf == NULL) {
558 : 0 : rte_errno = ENOMEM;
559 : 0 : PMD_DRV_LOG(ERR, "Failed to alloc tx cq exec cmd memory");
560 : 0 : goto error;
561 : : }
562 : :
563 : : in = cmd_buf;
564 : : memset(in, 0, cmd_len);
565 : :
566 : 0 : in->hdr.opcode = rte_cpu_to_be_16(XSC_CMD_OP_CREATE_CQ);
567 : 0 : in->ctx.eqn = 0;
568 [ # # ]: 0 : in->ctx.pa_num = rte_cpu_to_be_16(pa_num);
569 [ # # ]: 0 : in->ctx.glb_func_id = rte_cpu_to_be_16((uint16_t)xdev->hwinfo.func_id);
570 : 0 : in->ctx.log_cq_sz = rte_log2_u32(cqe_s);
571 : 0 : in->ctx.cq_type = XSC_CQ_TYPE_NORMAL;
572 : 0 : iova = cq->mz->iova;
573 [ # # ]: 0 : for (i = 0; i < pa_num; i++)
574 [ # # ]: 0 : in->pas[i] = rte_cpu_to_be_64(iova + i * XSC_PAGE_SIZE);
575 : :
576 : : out = cmd_buf;
577 : 0 : ret = xsc_vfio_mbox_exec(xdev, in, in_len, out, out_len);
578 [ # # # # ]: 0 : if (ret != 0 || out->hdr.status != 0) {
579 : 0 : PMD_DRV_LOG(ERR, "Failed to create tx cq, port id=%u, err=%d, out.status=%u",
580 : : cq_params->port_id, ret, out->hdr.status);
581 : 0 : rte_errno = ENOEXEC;
582 : 0 : goto error;
583 : : }
584 : :
585 [ # # ]: 0 : cq->cqn = rte_be_to_cpu_32(out->cqn);
586 : 0 : cq->xdev = xdev;
587 : :
588 : 0 : cq_info->cq = cq;
589 : 0 : cqes = (struct xsc_cqe *)((uint8_t *)cq->mz->addr);
590 [ # # ]: 0 : if (xsc_dev_is_vf(xdev))
591 : 0 : cq_info->cq_db = (uint32_t *)((uint8_t *)xdev->bar_addr + XSC_VF_CQ_DB_ADDR);
592 : : else
593 : 0 : cq_info->cq_db = (uint32_t *)((uint8_t *)xdev->bar_addr + XSC_PF_CQ_DB_ADDR);
594 : 0 : cq_info->cqn = cq->cqn;
595 : 0 : cq_info->cqe_s = cqe_s;
596 : 0 : cq_info->cqe_n = log_cq_sz;
597 : :
598 [ # # ]: 0 : for (i = 0; i < cq_info->cqe_s; i++)
599 : 0 : ((volatile struct xsc_cqe *)(cqes + i))->owner = 1;
600 : 0 : cq_info->cqes = cqes;
601 : :
602 : 0 : free(cmd_buf);
603 : 0 : return 0;
604 : :
605 : 0 : error:
606 : 0 : free(cmd_buf);
607 : 0 : rte_memzone_free(cq_pas);
608 : 0 : rte_free(cq);
609 : 0 : return -rte_errno;
610 : : }
611 : :
612 : : static int
613 : 0 : xsc_vfio_tx_qp_create(struct xsc_dev *xdev, struct xsc_tx_qp_params *qp_params,
614 : : struct xsc_tx_qp_info *qp_info)
615 : : {
616 : : struct xsc_cmd_create_qp_mbox_in *in = NULL;
617 : : struct xsc_cmd_create_qp_mbox_out *out = NULL;
618 : : const struct rte_memzone *qp_pas = NULL;
619 : 0 : struct xsc_vfio_cq *cq = (struct xsc_vfio_cq *)qp_params->cq;
620 : : struct xsc_vfio_qp *qp = NULL;
621 : : int in_len, out_len, cmd_len;
622 : : int ret = 0;
623 : 0 : uint32_t send_ds_num = xdev->hwinfo.send_seg_num;
624 : 0 : int wqe_s = 1 << qp_params->elts_n;
625 : : uint16_t pa_num;
626 : : uint8_t log_ele = 0;
627 : : uint32_t log_rq_sz = 0;
628 : : uint32_t log_sq_sz = 0;
629 : : int i;
630 : : uint64_t iova;
631 : 0 : char name[RTE_ETH_NAME_MAX_LEN] = {0};
632 : : void *cmd_buf = NULL;
633 : :
634 : 0 : qp = rte_zmalloc(NULL, sizeof(struct xsc_vfio_qp), 0);
635 [ # # ]: 0 : if (qp == NULL) {
636 : 0 : rte_errno = ENOMEM;
637 : 0 : PMD_DRV_LOG(ERR, "Failed to alloc tx qp memory");
638 : 0 : return -rte_errno;
639 : : }
640 : :
641 [ # # ]: 0 : log_sq_sz = rte_log2_u32(wqe_s * send_ds_num);
642 : : log_ele = rte_log2_u32(sizeof(struct xsc_wqe_data_seg));
643 : 0 : pa_num = ((1 << (log_rq_sz + log_sq_sz + log_ele))) / XSC_PAGE_SIZE;
644 : :
645 : 0 : snprintf(name, sizeof(name), "mz_wqe_mem_tx_%u_%u", qp_params->port_id, qp_params->qp_id);
646 : 0 : qp_pas = rte_memzone_reserve_aligned(name,
647 : 0 : (XSC_PAGE_SIZE * pa_num),
648 : : SOCKET_ID_ANY,
649 : : 0, XSC_PAGE_SIZE);
650 [ # # ]: 0 : if (qp_pas == NULL) {
651 : 0 : rte_errno = ENOMEM;
652 : 0 : PMD_DRV_LOG(ERR, "Failed to alloc tx qp pas memory");
653 : 0 : goto error;
654 : : }
655 : 0 : qp->mz = qp_pas;
656 : :
657 : 0 : in_len = (sizeof(struct xsc_cmd_create_qp_mbox_in) + (pa_num * sizeof(uint64_t)));
658 : : out_len = sizeof(struct xsc_cmd_create_qp_mbox_out);
659 : 0 : cmd_len = RTE_MAX(in_len, out_len);
660 : 0 : cmd_buf = malloc(cmd_len);
661 [ # # ]: 0 : if (cmd_buf == NULL) {
662 : 0 : rte_errno = ENOMEM;
663 : 0 : PMD_DRV_LOG(ERR, "Failed to alloc tx qp exec cmd memory");
664 : 0 : goto error;
665 : : }
666 : :
667 : : in = cmd_buf;
668 : : memset(in, 0, cmd_len);
669 : :
670 : 0 : in->hdr.opcode = rte_cpu_to_be_16(XSC_CMD_OP_CREATE_QP);
671 : 0 : in->req.input_qpn = 0;
672 [ # # ]: 0 : in->req.pa_num = rte_cpu_to_be_16(pa_num);
673 : 0 : in->req.qp_type = XSC_QUEUE_TYPE_RAW_TX;
674 : 0 : in->req.log_sq_sz = log_sq_sz;
675 : 0 : in->req.log_rq_sz = log_rq_sz;
676 : 0 : in->req.dma_direct = 0;
677 : 0 : in->req.pdn = 0;
678 [ # # ]: 0 : in->req.cqn_send = rte_cpu_to_be_16((uint16_t)cq->cqn);
679 : 0 : in->req.cqn_recv = 0;
680 [ # # ]: 0 : in->req.glb_funcid = rte_cpu_to_be_16((uint16_t)xdev->hwinfo.func_id);
681 : 0 : iova = qp->mz->iova;
682 [ # # ]: 0 : for (i = 0; i < pa_num; i++)
683 [ # # ]: 0 : in->req.pas[i] = rte_cpu_to_be_64(iova + i * XSC_PAGE_SIZE);
684 : :
685 : : out = cmd_buf;
686 : 0 : ret = xsc_vfio_mbox_exec(xdev, in, in_len, out, out_len);
687 [ # # # # ]: 0 : if (ret != 0 || out->hdr.status != 0) {
688 : 0 : PMD_DRV_LOG(ERR, "Failed to create tx qp, port id=%u, err=%d, out.status=%u",
689 : : qp_params->port_id, ret, out->hdr.status);
690 : 0 : rte_errno = ENOEXEC;
691 : 0 : goto error;
692 : : }
693 : :
694 [ # # ]: 0 : qp->qpn = rte_be_to_cpu_32(out->qpn);
695 : 0 : qp->xdev = xdev;
696 : :
697 : 0 : qp_info->qp = qp;
698 : 0 : qp_info->qpn = qp->qpn;
699 [ # # ]: 0 : qp_info->wqes = (struct xsc_wqe *)qp->mz->addr;
700 : 0 : qp_info->wqe_n = rte_log2_u32(wqe_s);
701 : :
702 [ # # ]: 0 : if (xsc_dev_is_vf(xdev))
703 : 0 : qp_info->qp_db = (uint32_t *)((uint8_t *)xdev->bar_addr + XSC_VF_TX_DB_ADDR);
704 : : else
705 : 0 : qp_info->qp_db = (uint32_t *)((uint8_t *)xdev->bar_addr + XSC_PF_TX_DB_ADDR);
706 : :
707 : 0 : free(cmd_buf);
708 : 0 : return 0;
709 : :
710 : 0 : error:
711 : 0 : free(cmd_buf);
712 : 0 : rte_memzone_free(qp_pas);
713 : 0 : rte_free(qp);
714 : 0 : return -rte_errno;
715 : : }
716 : :
717 : : static int
718 : 0 : xsc_vfio_dev_init(struct xsc_dev *xdev)
719 : : {
720 : : int ret;
721 : :
722 : 0 : ret = xsc_vfio_dev_open(xdev);
723 [ # # ]: 0 : if (ret != 0)
724 : 0 : goto open_fail;
725 : :
726 : 0 : ret = xsc_vfio_bar_init(xdev);
727 [ # # ]: 0 : if (ret != 0)
728 : 0 : goto init_fail;
729 : :
730 [ # # ]: 0 : if (xsc_vfio_mbox_init(xdev) != 0)
731 : 0 : goto init_fail;
732 : :
733 : 0 : ret = xsc_vfio_hwinfo_init(xdev);
734 [ # # ]: 0 : if (ret != 0)
735 : 0 : goto init_fail;
736 : :
737 : : return 0;
738 : :
739 : 0 : init_fail:
740 : : xsc_vfio_dev_close(xdev);
741 : :
742 : : open_fail:
743 : : return -1;
744 : : }
745 : :
746 : : static struct xsc_dev_ops *xsc_vfio_ops = &(struct xsc_dev_ops) {
747 : : .kdrv = RTE_PCI_KDRV_VFIO,
748 : : .dev_init = xsc_vfio_dev_init,
749 : : .dev_close = xsc_vfio_dev_close,
750 : : .set_mtu = xsc_vfio_set_mtu,
751 : : .get_mac = xsc_vfio_get_mac,
752 : : .destroy_qp = xsc_vfio_destroy_qp,
753 : : .destroy_cq = xsc_vfio_destroy_cq,
754 : : .modify_qp_status = xsc_vfio_modify_qp_status,
755 : : .modify_qp_qostree = xsc_vfio_modify_qp_qostree,
756 : : .rx_cq_create = xsc_vfio_rx_cq_create,
757 : : .tx_cq_create = xsc_vfio_tx_cq_create,
758 : : .tx_qp_create = xsc_vfio_tx_qp_create,
759 : : .mailbox_exec = xsc_vfio_mbox_exec,
760 : : };
761 : :
762 : 252 : RTE_INIT(xsc_vfio_ops_reg)
763 : : {
764 : 252 : xsc_dev_ops_register(xsc_vfio_ops);
765 : 252 : }
|