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