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_pci_unmap_device(xdev->pci_dev);
182 : 0 : rte_free(vfio_priv);
183 : :
184 : 0 : return 0;
185 : : }
186 : :
187 : : static int
188 : 0 : xsc_vfio_destroy_qp(void *qp)
189 : : {
190 : : int ret;
191 : : int in_len, out_len, cmd_len;
192 : : struct xsc_cmd_destroy_qp_mbox_in *in;
193 : : struct xsc_cmd_destroy_qp_mbox_out *out;
194 : : struct xsc_vfio_qp *data = (struct xsc_vfio_qp *)qp;
195 : : void *cmd_buf;
196 : :
197 : : in_len = sizeof(struct xsc_cmd_destroy_qp_mbox_in);
198 : : out_len = sizeof(struct xsc_cmd_destroy_qp_mbox_out);
199 : : cmd_len = RTE_MAX(in_len, out_len);
200 : :
201 : 0 : cmd_buf = malloc(cmd_len);
202 [ # # ]: 0 : if (cmd_buf == NULL) {
203 : 0 : rte_errno = ENOMEM;
204 : 0 : PMD_DRV_LOG(ERR, "Failed to alloc qp destroy cmd memory");
205 : 0 : return -rte_errno;
206 : : }
207 : :
208 : : in = cmd_buf;
209 : : memset(in, 0, cmd_len);
210 : 0 : in->hdr.opcode = rte_cpu_to_be_16(XSC_CMD_OP_DESTROY_QP);
211 [ # # ]: 0 : in->qpn = rte_cpu_to_be_32(data->qpn);
212 : : out = cmd_buf;
213 : 0 : ret = xsc_vfio_mbox_exec(data->xdev, in, in_len, out, out_len);
214 [ # # # # ]: 0 : if (ret != 0 || out->hdr.status != 0) {
215 : 0 : PMD_DRV_LOG(ERR, "Failed to destroy qp, type=%d, err=%d, out.status=%u",
216 : : XSC_QUEUE_TYPE_RAW, ret, out->hdr.status);
217 : 0 : rte_errno = ENOEXEC;
218 : : ret = -rte_errno;
219 : 0 : goto exit;
220 : : }
221 : :
222 : 0 : rte_memzone_free(data->mz);
223 : 0 : rte_free(qp);
224 : :
225 : 0 : exit:
226 : 0 : free(cmd_buf);
227 : 0 : return ret;
228 : : }
229 : :
230 : : static int
231 : 0 : xsc_vfio_destroy_cq(void *cq)
232 : : {
233 : : int ret;
234 : : int in_len, out_len, cmd_len;
235 : : struct xsc_cmd_destroy_cq_mbox_in *in;
236 : : struct xsc_cmd_destroy_cq_mbox_out *out;
237 : : struct xsc_vfio_cq *data = (struct xsc_vfio_cq *)cq;
238 : : void *cmd_buf;
239 : :
240 : : in_len = sizeof(struct xsc_cmd_destroy_cq_mbox_in);
241 : : out_len = sizeof(struct xsc_cmd_destroy_cq_mbox_out);
242 : : cmd_len = RTE_MAX(in_len, out_len);
243 : :
244 : 0 : cmd_buf = malloc(cmd_len);
245 [ # # ]: 0 : if (cmd_buf == NULL) {
246 : 0 : rte_errno = ENOMEM;
247 : 0 : PMD_DRV_LOG(ERR, "Failed to alloc cq destroy cmd memory");
248 : 0 : return -rte_errno;
249 : : }
250 : :
251 : : in = cmd_buf;
252 : : memset(in, 0, cmd_len);
253 : :
254 : 0 : in->hdr.opcode = rte_cpu_to_be_16(XSC_CMD_OP_DESTROY_CQ);
255 [ # # ]: 0 : in->cqn = rte_cpu_to_be_32(data->cqn);
256 : : out = cmd_buf;
257 : 0 : ret = xsc_vfio_mbox_exec(data->xdev, in, in_len, out, out_len);
258 [ # # # # ]: 0 : if (ret != 0 || out->hdr.status != 0) {
259 : 0 : PMD_DRV_LOG(ERR, "Failed to destroy cq, type=%d, err=%d, out.status=%u",
260 : : XSC_QUEUE_TYPE_RAW, ret, out->hdr.status);
261 : 0 : rte_errno = ENOEXEC;
262 : : ret = -rte_errno;
263 : 0 : goto exit;
264 : : }
265 : :
266 : 0 : rte_memzone_free(data->mz);
267 : 0 : rte_free(cq);
268 : :
269 : 0 : exit:
270 : 0 : free(cmd_buf);
271 : 0 : return ret;
272 : : }
273 : :
274 : : static int
275 : 0 : xsc_vfio_set_mtu(struct xsc_dev *xdev, uint16_t mtu)
276 : : {
277 : 0 : struct xsc_cmd_set_mtu_mbox_in in = { };
278 : 0 : struct xsc_cmd_set_mtu_mbox_out out = { };
279 : : int ret;
280 : :
281 : 0 : in.hdr.opcode = rte_cpu_to_be_16(XSC_CMD_OP_SET_MTU);
282 [ # # ]: 0 : in.mtu = rte_cpu_to_be_16(XSC_SW2HW_MTU(mtu));
283 [ # # ]: 0 : in.rx_buf_sz_min = rte_cpu_to_be_16(XSC_SW2HW_RX_PKT_LEN(mtu));
284 : 0 : in.mac_port = (uint8_t)xdev->hwinfo.mac_phy_port;
285 : :
286 : 0 : ret = xsc_vfio_mbox_exec(xdev, &in, sizeof(in), &out, sizeof(out));
287 [ # # # # ]: 0 : if (ret != 0 || out.hdr.status != 0) {
288 : 0 : PMD_DRV_LOG(ERR, "Failed to set mtu, port=%d, err=%d, out.status=%u",
289 : : xdev->port_id, ret, out.hdr.status);
290 : 0 : rte_errno = ENOEXEC;
291 : : ret = -rte_errno;
292 : : }
293 : :
294 : 0 : return ret;
295 : : }
296 : :
297 : : static int
298 : 0 : xsc_vfio_get_mac(struct xsc_dev *xdev, uint8_t *mac)
299 : : {
300 : 0 : struct xsc_cmd_query_eth_mac_mbox_in in = { };
301 : 0 : struct xsc_cmd_query_eth_mac_mbox_out out = { };
302 : : int ret;
303 : :
304 : 0 : in.hdr.opcode = rte_cpu_to_be_16(XSC_CMD_OP_QUERY_ETH_MAC);
305 : 0 : ret = xsc_vfio_mbox_exec(xdev, &in, sizeof(in), &out, sizeof(out));
306 [ # # # # ]: 0 : if (ret != 0 || out.hdr.status != 0) {
307 : 0 : PMD_DRV_LOG(ERR, "Failed to get mtu, port=%d, err=%d, out.status=%u",
308 : : xdev->port_id, ret, out.hdr.status);
309 : 0 : rte_errno = ENOEXEC;
310 : 0 : return -rte_errno;
311 : : }
312 : :
313 : : memcpy(mac, out.mac, RTE_ETHER_ADDR_LEN);
314 : :
315 : 0 : return 0;
316 : : }
317 : :
318 : : static int
319 : 0 : xsc_vfio_modify_qp_status(struct xsc_dev *xdev, uint32_t qpn, int num, int opcode)
320 : : {
321 : : int i, ret;
322 : : int in_len, out_len, cmd_len;
323 : : struct xsc_cmd_modify_qp_mbox_in *in;
324 : : struct xsc_cmd_modify_qp_mbox_out *out;
325 : : void *cmd_buf;
326 : :
327 : : in_len = sizeof(struct xsc_cmd_modify_qp_mbox_in);
328 : : out_len = sizeof(struct xsc_cmd_modify_qp_mbox_out);
329 : : cmd_len = RTE_MAX(in_len, out_len);
330 : :
331 : 0 : cmd_buf = malloc(cmd_len);
332 [ # # ]: 0 : if (cmd_buf == NULL) {
333 : 0 : PMD_DRV_LOG(ERR, "Failed to alloc cmdq qp modify status");
334 : 0 : rte_errno = ENOMEM;
335 : 0 : return -rte_errno;
336 : : }
337 : :
338 : : in = cmd_buf;
339 : : memset(in, 0, cmd_len);
340 : : out = cmd_buf;
341 : :
342 [ # # ]: 0 : for (i = 0; i < num; i++) {
343 [ # # ]: 0 : in->hdr.opcode = rte_cpu_to_be_16(opcode);
344 : 0 : in->hdr.ver = 0;
345 [ # # ]: 0 : in->qpn = rte_cpu_to_be_32(qpn + i);
346 : 0 : in->no_need_wait = 1;
347 : :
348 : 0 : ret = xsc_vfio_mbox_exec(xdev, in, in_len, out, out_len);
349 [ # # # # ]: 0 : if (ret != 0 || out->hdr.status != 0) {
350 : 0 : PMD_DRV_LOG(ERR, "Modify qp status failed, qpn=%u, err=%d, out.status=%u",
351 : : qpn + i, ret, out->hdr.status);
352 : 0 : rte_errno = ENOEXEC;
353 : : ret = -rte_errno;
354 : 0 : goto exit;
355 : : }
356 : : }
357 : :
358 : 0 : exit:
359 : 0 : free(cmd_buf);
360 : 0 : return ret;
361 : : }
362 : :
363 : : static int
364 : 0 : xsc_vfio_modify_qp_qostree(struct xsc_dev *xdev, uint16_t qpn)
365 : : {
366 : : int ret;
367 : : int in_len, out_len, cmd_len;
368 : : struct xsc_cmd_modify_raw_qp_mbox_in *in;
369 : : struct xsc_cmd_modify_raw_qp_mbox_out *out;
370 : : void *cmd_buf;
371 : :
372 : : in_len = sizeof(struct xsc_cmd_modify_raw_qp_mbox_in);
373 : : out_len = sizeof(struct xsc_cmd_modify_raw_qp_mbox_out);
374 : : cmd_len = RTE_MAX(in_len, out_len);
375 : :
376 : 0 : cmd_buf = malloc(cmd_len);
377 [ # # ]: 0 : if (cmd_buf == NULL) {
378 : 0 : PMD_DRV_LOG(ERR, "Failed to alloc cmdq qp modify qostree");
379 : 0 : rte_errno = ENOMEM;
380 : 0 : return -rte_errno;
381 : : }
382 : :
383 : : in = cmd_buf;
384 : : memset(in, 0, cmd_len);
385 : 0 : in->hdr.opcode = rte_cpu_to_be_16(XSC_CMD_OP_MODIFY_RAW_QP);
386 : : in->req.prio = 0;
387 : 0 : in->req.qp_out_port = 0xFF;
388 [ # # ]: 0 : in->req.lag_id = rte_cpu_to_be_16(xdev->hwinfo.lag_id);
389 [ # # ]: 0 : in->req.func_id = rte_cpu_to_be_16(xdev->hwinfo.func_id);
390 : : in->req.dma_direct = 0;
391 [ # # ]: 0 : in->req.qpn = rte_cpu_to_be_16(qpn);
392 : : out = cmd_buf;
393 : :
394 : 0 : ret = xsc_vfio_mbox_exec(xdev, in, in_len, out, out_len);
395 [ # # # # ]: 0 : if (ret != 0 || out->hdr.status != 0) {
396 : 0 : PMD_DRV_LOG(ERR, "Filed to modify qp qostree, qpn=%d, err=%d, out.status=%u",
397 : : qpn, ret, out->hdr.status);
398 : 0 : rte_errno = ENOEXEC;
399 : : ret = -rte_errno;
400 : 0 : goto exit;
401 : : }
402 : :
403 : 0 : exit:
404 : 0 : free(cmd_buf);
405 : 0 : return ret;
406 : : }
407 : :
408 : : static int
409 : 0 : xsc_vfio_rx_cq_create(struct xsc_dev *xdev, struct xsc_rx_cq_params *cq_params,
410 : : struct xsc_rx_cq_info *cq_info)
411 : : {
412 : : int ret;
413 : : int pa_len;
414 : : uint16_t i;
415 : : uint16_t pa_num;
416 : : uint8_t log_cq_sz;
417 : : uint16_t cqe_n;
418 : : uint32_t cqe_total_sz;
419 : : int in_len, out_len, cmd_len;
420 : 0 : char name[RTE_ETH_NAME_MAX_LEN] = { 0 };
421 : 0 : uint16_t port_id = cq_params->port_id;
422 : 0 : uint16_t idx = cq_params->qp_id;
423 : : struct xsc_vfio_cq *cq;
424 : : const struct rte_memzone *cq_pas = NULL;
425 : : struct xsc_cqe *cqes;
426 : : struct xsc_cmd_create_cq_mbox_in *in = NULL;
427 : : struct xsc_cmd_create_cq_mbox_out *out = NULL;
428 : : void *cmd_buf;
429 : :
430 : 0 : cqe_n = cq_params->wqe_s;
431 [ # # ]: 0 : log_cq_sz = rte_log2_u32(cqe_n);
432 : 0 : cqe_total_sz = cqe_n * sizeof(struct xsc_cqe);
433 : 0 : pa_num = (cqe_total_sz + XSC_PAGE_SIZE - 1) / XSC_PAGE_SIZE;
434 : 0 : pa_len = sizeof(uint64_t) * pa_num;
435 : 0 : in_len = sizeof(struct xsc_cmd_create_cq_mbox_in) + pa_len;
436 : : out_len = sizeof(struct xsc_cmd_create_cq_mbox_out);
437 : 0 : cmd_len = RTE_MAX(in_len, out_len);
438 : :
439 : 0 : cq = rte_zmalloc(NULL, sizeof(struct xsc_vfio_cq), 0);
440 [ # # ]: 0 : if (cq == NULL) {
441 : 0 : rte_errno = ENOMEM;
442 : 0 : PMD_DRV_LOG(ERR, "Failed to alloc rx cq memory");
443 : 0 : return -rte_errno;
444 : : }
445 : :
446 : 0 : cmd_buf = malloc(cmd_len);
447 [ # # ]: 0 : if (cmd_buf == NULL) {
448 : 0 : rte_errno = ENOMEM;
449 : 0 : PMD_DRV_LOG(ERR, "Failed to alloc rx cq exec cmd memory");
450 : 0 : goto error;
451 : : }
452 : :
453 : : in = cmd_buf;
454 : : memset(in, 0, cmd_len);
455 : 0 : in->hdr.opcode = rte_cpu_to_be_16(XSC_CMD_OP_CREATE_CQ);
456 : 0 : in->ctx.eqn = 0;
457 [ # # ]: 0 : in->ctx.pa_num = rte_cpu_to_be_16(pa_num);
458 [ # # ]: 0 : in->ctx.glb_func_id = rte_cpu_to_be_16((uint16_t)xdev->hwinfo.func_id);
459 : 0 : in->ctx.log_cq_sz = log_cq_sz;
460 : 0 : in->ctx.cq_type = XSC_CQ_TYPE_NORMAL;
461 : :
462 : 0 : snprintf(name, sizeof(name), "mz_cqe_mem_rx_%u_%u", port_id, idx);
463 : 0 : cq_pas = rte_memzone_reserve_aligned(name,
464 : 0 : (XSC_PAGE_SIZE * pa_num),
465 : : SOCKET_ID_ANY,
466 : : 0, XSC_PAGE_SIZE);
467 [ # # ]: 0 : if (cq_pas == NULL) {
468 : 0 : rte_errno = ENOMEM;
469 : 0 : PMD_DRV_LOG(ERR, "Failed to alloc rx cq pas memory");
470 : 0 : goto error;
471 : : }
472 : 0 : cq->mz = cq_pas;
473 : :
474 [ # # ]: 0 : for (i = 0; i < pa_num; i++)
475 [ # # ]: 0 : in->pas[i] = rte_cpu_to_be_64(cq_pas->iova + i * XSC_PAGE_SIZE);
476 : :
477 : : out = cmd_buf;
478 : 0 : ret = xsc_vfio_mbox_exec(xdev, in, in_len, out, out_len);
479 [ # # # # ]: 0 : if (ret != 0 || out->hdr.status != 0) {
480 : 0 : PMD_DRV_LOG(ERR,
481 : : "Failed to exec rx cq create cmd, port id=%d, err=%d, out.status=%u",
482 : : port_id, ret, out->hdr.status);
483 : 0 : rte_errno = ENOEXEC;
484 : 0 : goto error;
485 : : }
486 : :
487 : 0 : cq_info->cq = (void *)cq;
488 : 0 : cq_info->cqe_n = log_cq_sz;
489 : 0 : cqes = (struct xsc_cqe *)cq_pas->addr;
490 [ # # ]: 0 : for (i = 0; i < (1 << cq_info->cqe_n); i++)
491 : 0 : ((volatile struct xsc_cqe *)(cqes + i))->owner = 1;
492 : 0 : cq_info->cqes = cqes;
493 [ # # ]: 0 : if (xsc_dev_is_vf(xdev))
494 : 0 : cq_info->cq_db = (uint32_t *)((uint8_t *)xdev->bar_addr + XSC_VF_CQ_DB_ADDR);
495 : : else
496 : 0 : cq_info->cq_db = (uint32_t *)((uint8_t *)xdev->bar_addr + XSC_PF_CQ_DB_ADDR);
497 [ # # ]: 0 : cq_info->cqn = rte_be_to_cpu_32(out->cqn);
498 : 0 : cq->cqn = cq_info->cqn;
499 : 0 : cq->xdev = xdev;
500 : 0 : PMD_DRV_LOG(INFO, "Port id=%d, Rx cqe_n:%d, cqn:%u",
501 : : port_id, cq_info->cqe_n, cq_info->cqn);
502 : :
503 : 0 : free(cmd_buf);
504 : 0 : return 0;
505 : :
506 : 0 : error:
507 : 0 : free(cmd_buf);
508 : 0 : rte_memzone_free(cq_pas);
509 : 0 : rte_free(cq);
510 : 0 : return -rte_errno;
511 : : }
512 : :
513 : : static int
514 : 0 : xsc_vfio_tx_cq_create(struct xsc_dev *xdev, struct xsc_tx_cq_params *cq_params,
515 : : struct xsc_tx_cq_info *cq_info)
516 : : {
517 : : struct xsc_vfio_cq *cq = NULL;
518 : 0 : char name[RTE_ETH_NAME_MAX_LEN] = {0};
519 : : struct xsc_cmd_create_cq_mbox_in *in = NULL;
520 : : struct xsc_cmd_create_cq_mbox_out *out = NULL;
521 : : const struct rte_memzone *cq_pas = NULL;
522 : : struct xsc_cqe *cqes;
523 : : int in_len, out_len, cmd_len;
524 : : uint16_t pa_num;
525 : : uint16_t log_cq_sz;
526 : : int ret = 0;
527 : 0 : int cqe_s = 1 << cq_params->elts_n;
528 : : uint64_t iova;
529 : : int i;
530 : : void *cmd_buf = NULL;
531 : :
532 : 0 : cq = rte_zmalloc(NULL, sizeof(struct xsc_vfio_cq), 0);
533 [ # # ]: 0 : if (cq == NULL) {
534 : 0 : rte_errno = ENOMEM;
535 : 0 : PMD_DRV_LOG(ERR, "Failed to alloc tx cq memory");
536 : 0 : return -rte_errno;
537 : : }
538 : :
539 [ # # ]: 0 : log_cq_sz = rte_log2_u32(cqe_s);
540 : 0 : pa_num = (((1 << log_cq_sz) * sizeof(struct xsc_cqe)) / XSC_PAGE_SIZE);
541 : :
542 : 0 : snprintf(name, sizeof(name), "mz_cqe_mem_tx_%u_%u", cq_params->port_id, cq_params->qp_id);
543 : 0 : cq_pas = rte_memzone_reserve_aligned(name,
544 : 0 : (XSC_PAGE_SIZE * pa_num),
545 : : SOCKET_ID_ANY,
546 : : 0, XSC_PAGE_SIZE);
547 [ # # ]: 0 : if (cq_pas == NULL) {
548 : 0 : rte_errno = ENOMEM;
549 : 0 : PMD_DRV_LOG(ERR, "Failed to alloc tx cq pas memory");
550 : 0 : goto error;
551 : : }
552 : :
553 : 0 : cq->mz = cq_pas;
554 : 0 : in_len = (sizeof(struct xsc_cmd_create_cq_mbox_in) + (pa_num * sizeof(uint64_t)));
555 : : out_len = sizeof(struct xsc_cmd_create_cq_mbox_out);
556 : 0 : cmd_len = RTE_MAX(in_len, out_len);
557 : 0 : cmd_buf = malloc(cmd_len);
558 [ # # ]: 0 : if (cmd_buf == NULL) {
559 : 0 : rte_errno = ENOMEM;
560 : 0 : PMD_DRV_LOG(ERR, "Failed to alloc tx cq exec cmd memory");
561 : 0 : goto error;
562 : : }
563 : :
564 : : in = cmd_buf;
565 : : memset(in, 0, cmd_len);
566 : :
567 : 0 : in->hdr.opcode = rte_cpu_to_be_16(XSC_CMD_OP_CREATE_CQ);
568 : 0 : in->ctx.eqn = 0;
569 [ # # ]: 0 : in->ctx.pa_num = rte_cpu_to_be_16(pa_num);
570 [ # # ]: 0 : in->ctx.glb_func_id = rte_cpu_to_be_16((uint16_t)xdev->hwinfo.func_id);
571 : 0 : in->ctx.log_cq_sz = rte_log2_u32(cqe_s);
572 : 0 : in->ctx.cq_type = XSC_CQ_TYPE_NORMAL;
573 : 0 : iova = cq->mz->iova;
574 [ # # ]: 0 : for (i = 0; i < pa_num; i++)
575 [ # # ]: 0 : in->pas[i] = rte_cpu_to_be_64(iova + i * XSC_PAGE_SIZE);
576 : :
577 : : out = cmd_buf;
578 : 0 : ret = xsc_vfio_mbox_exec(xdev, in, in_len, out, out_len);
579 [ # # # # ]: 0 : if (ret != 0 || out->hdr.status != 0) {
580 : 0 : PMD_DRV_LOG(ERR, "Failed to create tx cq, port id=%u, err=%d, out.status=%u",
581 : : cq_params->port_id, ret, out->hdr.status);
582 : 0 : rte_errno = ENOEXEC;
583 : 0 : goto error;
584 : : }
585 : :
586 [ # # ]: 0 : cq->cqn = rte_be_to_cpu_32(out->cqn);
587 : 0 : cq->xdev = xdev;
588 : :
589 : 0 : cq_info->cq = cq;
590 : 0 : cqes = (struct xsc_cqe *)((uint8_t *)cq->mz->addr);
591 [ # # ]: 0 : if (xsc_dev_is_vf(xdev))
592 : 0 : cq_info->cq_db = (uint32_t *)((uint8_t *)xdev->bar_addr + XSC_VF_CQ_DB_ADDR);
593 : : else
594 : 0 : cq_info->cq_db = (uint32_t *)((uint8_t *)xdev->bar_addr + XSC_PF_CQ_DB_ADDR);
595 : 0 : cq_info->cqn = cq->cqn;
596 : 0 : cq_info->cqe_s = cqe_s;
597 : 0 : cq_info->cqe_n = log_cq_sz;
598 : :
599 [ # # ]: 0 : for (i = 0; i < cq_info->cqe_s; i++)
600 : 0 : ((volatile struct xsc_cqe *)(cqes + i))->owner = 1;
601 : 0 : cq_info->cqes = cqes;
602 : :
603 : 0 : free(cmd_buf);
604 : 0 : return 0;
605 : :
606 : 0 : error:
607 : 0 : free(cmd_buf);
608 : 0 : rte_memzone_free(cq_pas);
609 : 0 : rte_free(cq);
610 : 0 : return -rte_errno;
611 : : }
612 : :
613 : : static int
614 : 0 : xsc_vfio_tx_qp_create(struct xsc_dev *xdev, struct xsc_tx_qp_params *qp_params,
615 : : struct xsc_tx_qp_info *qp_info)
616 : : {
617 : : struct xsc_cmd_create_qp_mbox_in *in = NULL;
618 : : struct xsc_cmd_create_qp_mbox_out *out = NULL;
619 : : const struct rte_memzone *qp_pas = NULL;
620 : 0 : struct xsc_vfio_cq *cq = (struct xsc_vfio_cq *)qp_params->cq;
621 : : struct xsc_vfio_qp *qp = NULL;
622 : : int in_len, out_len, cmd_len;
623 : : int ret = 0;
624 : 0 : uint32_t send_ds_num = xdev->hwinfo.send_seg_num;
625 : 0 : int wqe_s = 1 << qp_params->elts_n;
626 : : uint16_t pa_num;
627 : : uint8_t log_ele = 0;
628 : : uint32_t log_rq_sz = 0;
629 : : uint32_t log_sq_sz = 0;
630 : : int i;
631 : : uint64_t iova;
632 : 0 : char name[RTE_ETH_NAME_MAX_LEN] = {0};
633 : : void *cmd_buf = NULL;
634 : :
635 : 0 : qp = rte_zmalloc(NULL, sizeof(struct xsc_vfio_qp), 0);
636 [ # # ]: 0 : if (qp == NULL) {
637 : 0 : rte_errno = ENOMEM;
638 : 0 : PMD_DRV_LOG(ERR, "Failed to alloc tx qp memory");
639 : 0 : return -rte_errno;
640 : : }
641 : :
642 [ # # ]: 0 : log_sq_sz = rte_log2_u32(wqe_s * send_ds_num);
643 : : log_ele = rte_log2_u32(sizeof(struct xsc_wqe_data_seg));
644 : 0 : pa_num = ((1 << (log_rq_sz + log_sq_sz + log_ele))) / XSC_PAGE_SIZE;
645 : :
646 : 0 : snprintf(name, sizeof(name), "mz_wqe_mem_tx_%u_%u", qp_params->port_id, qp_params->qp_id);
647 : 0 : qp_pas = rte_memzone_reserve_aligned(name,
648 : 0 : (XSC_PAGE_SIZE * pa_num),
649 : : SOCKET_ID_ANY,
650 : : 0, XSC_PAGE_SIZE);
651 [ # # ]: 0 : if (qp_pas == NULL) {
652 : 0 : rte_errno = ENOMEM;
653 : 0 : PMD_DRV_LOG(ERR, "Failed to alloc tx qp pas memory");
654 : 0 : goto error;
655 : : }
656 : 0 : qp->mz = qp_pas;
657 : :
658 : 0 : in_len = (sizeof(struct xsc_cmd_create_qp_mbox_in) + (pa_num * sizeof(uint64_t)));
659 : : out_len = sizeof(struct xsc_cmd_create_qp_mbox_out);
660 : 0 : cmd_len = RTE_MAX(in_len, out_len);
661 : 0 : cmd_buf = malloc(cmd_len);
662 [ # # ]: 0 : if (cmd_buf == NULL) {
663 : 0 : rte_errno = ENOMEM;
664 : 0 : PMD_DRV_LOG(ERR, "Failed to alloc tx qp exec cmd memory");
665 : 0 : goto error;
666 : : }
667 : :
668 : : in = cmd_buf;
669 : : memset(in, 0, cmd_len);
670 : :
671 : 0 : in->hdr.opcode = rte_cpu_to_be_16(XSC_CMD_OP_CREATE_QP);
672 : 0 : in->req.input_qpn = 0;
673 [ # # ]: 0 : in->req.pa_num = rte_cpu_to_be_16(pa_num);
674 : 0 : in->req.qp_type = XSC_QUEUE_TYPE_RAW_TX;
675 : 0 : in->req.log_sq_sz = log_sq_sz;
676 : 0 : in->req.log_rq_sz = log_rq_sz;
677 : 0 : in->req.dma_direct = 0;
678 : 0 : in->req.pdn = 0;
679 [ # # ]: 0 : in->req.cqn_send = rte_cpu_to_be_16((uint16_t)cq->cqn);
680 : 0 : in->req.cqn_recv = 0;
681 [ # # ]: 0 : in->req.glb_funcid = rte_cpu_to_be_16((uint16_t)xdev->hwinfo.func_id);
682 : 0 : iova = qp->mz->iova;
683 [ # # ]: 0 : for (i = 0; i < pa_num; i++)
684 [ # # ]: 0 : in->req.pas[i] = rte_cpu_to_be_64(iova + i * XSC_PAGE_SIZE);
685 : :
686 : : out = cmd_buf;
687 : 0 : ret = xsc_vfio_mbox_exec(xdev, in, in_len, out, out_len);
688 [ # # # # ]: 0 : if (ret != 0 || out->hdr.status != 0) {
689 : 0 : PMD_DRV_LOG(ERR, "Failed to create tx qp, port id=%u, err=%d, out.status=%u",
690 : : qp_params->port_id, ret, out->hdr.status);
691 : 0 : rte_errno = ENOEXEC;
692 : 0 : goto error;
693 : : }
694 : :
695 [ # # ]: 0 : qp->qpn = rte_be_to_cpu_32(out->qpn);
696 : 0 : qp->xdev = xdev;
697 : :
698 : 0 : qp_info->qp = qp;
699 : 0 : qp_info->qpn = qp->qpn;
700 [ # # ]: 0 : qp_info->wqes = (struct xsc_wqe *)qp->mz->addr;
701 : 0 : qp_info->wqe_n = rte_log2_u32(wqe_s);
702 : :
703 [ # # ]: 0 : if (xsc_dev_is_vf(xdev))
704 : 0 : qp_info->qp_db = (uint32_t *)((uint8_t *)xdev->bar_addr + XSC_VF_TX_DB_ADDR);
705 : : else
706 : 0 : qp_info->qp_db = (uint32_t *)((uint8_t *)xdev->bar_addr + XSC_PF_TX_DB_ADDR);
707 : :
708 : 0 : free(cmd_buf);
709 : 0 : return 0;
710 : :
711 : 0 : error:
712 : 0 : free(cmd_buf);
713 : 0 : rte_memzone_free(qp_pas);
714 : 0 : rte_free(qp);
715 : 0 : return -rte_errno;
716 : : }
717 : :
718 : : static int
719 : 0 : xsc_vfio_dev_init(struct xsc_dev *xdev)
720 : : {
721 : : int ret;
722 : :
723 : 0 : ret = xsc_vfio_dev_open(xdev);
724 [ # # ]: 0 : if (ret != 0)
725 : 0 : goto open_fail;
726 : :
727 : 0 : ret = xsc_vfio_bar_init(xdev);
728 [ # # ]: 0 : if (ret != 0)
729 : 0 : goto init_fail;
730 : :
731 [ # # ]: 0 : if (xsc_vfio_mbox_init(xdev) != 0)
732 : 0 : goto init_fail;
733 : :
734 : 0 : ret = xsc_vfio_hwinfo_init(xdev);
735 [ # # ]: 0 : if (ret != 0)
736 : 0 : goto init_fail;
737 : :
738 : : return 0;
739 : :
740 : 0 : init_fail:
741 : 0 : xsc_vfio_dev_close(xdev);
742 : :
743 : : open_fail:
744 : : return -1;
745 : : }
746 : :
747 : : static struct xsc_dev_ops *xsc_vfio_ops = &(struct xsc_dev_ops) {
748 : : .kdrv = RTE_PCI_KDRV_VFIO,
749 : : .dev_init = xsc_vfio_dev_init,
750 : : .dev_close = xsc_vfio_dev_close,
751 : : .set_mtu = xsc_vfio_set_mtu,
752 : : .get_mac = xsc_vfio_get_mac,
753 : : .destroy_qp = xsc_vfio_destroy_qp,
754 : : .destroy_cq = xsc_vfio_destroy_cq,
755 : : .modify_qp_status = xsc_vfio_modify_qp_status,
756 : : .modify_qp_qostree = xsc_vfio_modify_qp_qostree,
757 : : .rx_cq_create = xsc_vfio_rx_cq_create,
758 : : .tx_cq_create = xsc_vfio_tx_cq_create,
759 : : .tx_qp_create = xsc_vfio_tx_qp_create,
760 : : .mailbox_exec = xsc_vfio_mbox_exec,
761 : : };
762 : :
763 : 253 : RTE_INIT(xsc_vfio_ops_reg)
764 : : {
765 : 253 : xsc_dev_ops_register(xsc_vfio_ops);
766 : 253 : }
|