Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright 2025 Yunsilicon Technology Co., Ltd.
3 : : */
4 : :
5 : : #include <uapi/linux/vfio.h>
6 : :
7 : : #include <sys/mman.h>
8 : : #include <sys/types.h>
9 : : #include <sys/stat.h>
10 : : #include <fcntl.h>
11 : : #include <sys/eventfd.h>
12 : : #include <sys/ioctl.h>
13 : :
14 : : #include <rte_pci.h>
15 : : #include <ethdev_pci.h>
16 : : #include <rte_bus_pci.h>
17 : : #include <rte_bitops.h>
18 : : #include <rte_interrupts.h>
19 : :
20 : : #include "xsc_defs.h"
21 : : #include "xsc_vfio_mbox.h"
22 : : #include "xsc_ethdev.h"
23 : : #include "xsc_rxtx.h"
24 : :
25 : : #define XSC_FEATURE_ONCHIP_FT_MASK RTE_BIT32(4)
26 : : #define XSC_FEATURE_DMA_RW_TBL_MASK RTE_BIT32(8)
27 : : #define XSC_FEATURE_PCT_EXP_MASK RTE_BIT32(19)
28 : : #define XSC_HOST_PCIE_NO_DEFAULT 0
29 : : #define XSC_SOC_PCIE_NO_DEFAULT 1
30 : : #define XSC_MSIX_CPU_NUM_DEFAULT 2
31 : :
32 : : #define XSC_SW2HW_MTU(mtu) ((mtu) + 14 + 4)
33 : : #define XSC_SW2HW_RX_PKT_LEN(mtu) ((mtu) + 14 + 256)
34 : :
35 : : #define XSC_MAX_INTR_VEC_ID RTE_MAX_RXTX_INTR_VEC_ID
36 : : #define XSC_MSIX_IRQ_SET_BUF_LEN (sizeof(struct vfio_irq_set) + \
37 : : sizeof(int) * (XSC_MAX_INTR_VEC_ID))
38 : :
39 : : enum xsc_vector {
40 : : XSC_VEC_CMD = 0,
41 : : XSC_VEC_CMD_EVENT = 1,
42 : : XSC_EQ_VEC_COMP_BASE,
43 : : };
44 : :
45 : : enum xsc_cq_type {
46 : : XSC_CQ_TYPE_NORMAL = 0,
47 : : XSC_CQ_TYPE_VIRTIO = 1,
48 : : };
49 : :
50 : : enum xsc_speed_mode {
51 : : XSC_MODULE_SPEED_UNKNOWN,
52 : : XSC_MODULE_SPEED_10G,
53 : : XSC_MODULE_SPEED_25G,
54 : : XSC_MODULE_SPEED_40G_R4,
55 : : XSC_MODULE_SPEED_50G_R,
56 : : XSC_MODULE_SPEED_50G_R2,
57 : : XSC_MODULE_SPEED_100G_R2,
58 : : XSC_MODULE_SPEED_100G_R4,
59 : : XSC_MODULE_SPEED_200G_R4,
60 : : XSC_MODULE_SPEED_200G_R8,
61 : : XSC_MODULE_SPEED_400G_R8,
62 : : XSC_MODULE_SPEED_MAX,
63 : : };
64 : :
65 : : struct xsc_vfio_cq {
66 : : const struct rte_memzone *mz;
67 : : struct xsc_dev *xdev;
68 : : uint32_t cqn;
69 : : };
70 : :
71 : : struct xsc_vfio_qp {
72 : : const struct rte_memzone *mz;
73 : : struct xsc_dev *xdev;
74 : : uint32_t qpn;
75 : : };
76 : :
77 : : static const uint32_t xsc_link_speed[] = {
78 : : [XSC_MODULE_SPEED_UNKNOWN] = RTE_ETH_SPEED_NUM_UNKNOWN,
79 : : [XSC_MODULE_SPEED_10G] = RTE_ETH_SPEED_NUM_10G,
80 : : [XSC_MODULE_SPEED_25G] = RTE_ETH_SPEED_NUM_25G,
81 : : [XSC_MODULE_SPEED_40G_R4] = RTE_ETH_SPEED_NUM_40G,
82 : : [XSC_MODULE_SPEED_50G_R] = RTE_ETH_SPEED_NUM_50G,
83 : : [XSC_MODULE_SPEED_50G_R2] = RTE_ETH_SPEED_NUM_50G,
84 : : [XSC_MODULE_SPEED_100G_R2] = RTE_ETH_SPEED_NUM_100G,
85 : : [XSC_MODULE_SPEED_100G_R4] = RTE_ETH_SPEED_NUM_100G,
86 : : [XSC_MODULE_SPEED_200G_R4] = RTE_ETH_SPEED_NUM_200G,
87 : : [XSC_MODULE_SPEED_200G_R8] = RTE_ETH_SPEED_NUM_200G,
88 : : [XSC_MODULE_SPEED_400G_R8] = RTE_ETH_SPEED_NUM_400G,
89 : : };
90 : :
91 : : static void
92 : 0 : xsc_vfio_pcie_no_init(struct xsc_hwinfo *hwinfo)
93 : : {
94 : 0 : uint func_id = hwinfo->func_id;
95 : :
96 [ # # ]: 0 : if (func_id >= hwinfo->pf0_vf_funcid_base &&
97 [ # # ]: 0 : func_id <= hwinfo->pf0_vf_funcid_top)
98 : 0 : hwinfo->pcie_no = hwinfo->pcie_host;
99 [ # # ]: 0 : else if (func_id >= hwinfo->pf1_vf_funcid_base &&
100 [ # # ]: 0 : func_id <= hwinfo->pf1_vf_funcid_top)
101 : 0 : hwinfo->pcie_no = hwinfo->pcie_host;
102 [ # # ]: 0 : else if (func_id >= hwinfo->pcie0_pf_funcid_base &&
103 [ # # ]: 0 : func_id <= hwinfo->pcie0_pf_funcid_top)
104 : 0 : hwinfo->pcie_no = XSC_HOST_PCIE_NO_DEFAULT;
105 : : else
106 : 0 : hwinfo->pcie_no = XSC_SOC_PCIE_NO_DEFAULT;
107 : 0 : }
108 : :
109 : : static void
110 : 0 : xsc_vfio_fw_version_init(char *hw_fw_ver, struct xsc_cmd_fw_version *cmd_fw_ver)
111 : : {
112 [ # # ]: 0 : uint16_t patch = rte_be_to_cpu_16(cmd_fw_ver->patch);
113 [ # # ]: 0 : uint32_t tweak = rte_be_to_cpu_32(cmd_fw_ver->tweak);
114 : :
115 [ # # ]: 0 : if (tweak == 0) {
116 : 0 : snprintf(hw_fw_ver, XSC_FW_VERS_LEN, "v%hhu.%hhu.%hu",
117 : 0 : cmd_fw_ver->major, cmd_fw_ver->minor,
118 : : patch);
119 : : } else {
120 : 0 : snprintf(hw_fw_ver, XSC_FW_VERS_LEN, "v%hhu.%hhu.%hu+%u",
121 : 0 : cmd_fw_ver->major, cmd_fw_ver->minor,
122 : : patch, tweak);
123 : : }
124 : 0 : }
125 : :
126 : : static int
127 : 0 : xsc_vfio_hwinfo_init(struct xsc_dev *xdev)
128 : : {
129 : : int ret;
130 : : uint32_t feature;
131 : : int in_len, out_len, cmd_len;
132 : : struct xsc_cmd_query_hca_cap_mbox_in *in;
133 : : struct xsc_cmd_query_hca_cap_mbox_out *out;
134 : : struct xsc_cmd_hca_cap *hca_cap;
135 : : void *cmd_buf;
136 : :
137 : : in_len = sizeof(struct xsc_cmd_query_hca_cap_mbox_in);
138 : : out_len = sizeof(struct xsc_cmd_query_hca_cap_mbox_out);
139 : : cmd_len = RTE_MAX(in_len, out_len);
140 : :
141 : 0 : cmd_buf = malloc(cmd_len);
142 [ # # ]: 0 : if (cmd_buf == NULL) {
143 : 0 : PMD_DRV_LOG(ERR, "Failed to alloc dev hwinfo cmd memory");
144 : 0 : rte_errno = ENOMEM;
145 : 0 : return -rte_errno;
146 : : }
147 : :
148 : : in = cmd_buf;
149 : : memset(in, 0, cmd_len);
150 : 0 : in->hdr.opcode = rte_cpu_to_be_16(XSC_CMD_OP_QUERY_HCA_CAP);
151 : 0 : in->hdr.ver = rte_cpu_to_be_16(XSC_CMD_QUERY_HCA_CAP_V1);
152 : 0 : in->cpu_num = rte_cpu_to_be_16(XSC_MSIX_CPU_NUM_DEFAULT);
153 : : out = cmd_buf;
154 : :
155 : 0 : ret = xsc_vfio_mbox_exec(xdev, in, in_len, out, out_len);
156 [ # # # # ]: 0 : if (ret != 0 || out->hdr.status != 0) {
157 : 0 : PMD_DRV_LOG(ERR, "Failed to get dev hwinfo, err=%d, out.status=%u",
158 : : ret, out->hdr.status);
159 : 0 : rte_errno = ENOEXEC;
160 : : ret = -rte_errno;
161 : 0 : goto exit;
162 : : }
163 : :
164 : : hca_cap = &out->hca_cap;
165 : 0 : xdev->hwinfo.valid = 1;
166 [ # # ]: 0 : xdev->hwinfo.func_id = rte_be_to_cpu_32(hca_cap->glb_func_id);
167 : 0 : xdev->hwinfo.pcie_host = hca_cap->pcie_host;
168 : 0 : xdev->hwinfo.mac_phy_port = hca_cap->mac_port;
169 [ # # ]: 0 : xdev->hwinfo.funcid_to_logic_port_off = rte_be_to_cpu_16(hca_cap->funcid_to_logic_port);
170 [ # # ]: 0 : xdev->hwinfo.raw_qp_id_base = rte_be_to_cpu_16(hca_cap->raweth_qp_id_base);
171 [ # # ]: 0 : xdev->hwinfo.raw_rss_qp_id_base = rte_be_to_cpu_16(hca_cap->raweth_rss_qp_id_base);
172 [ # # ]: 0 : xdev->hwinfo.pf0_vf_funcid_base = rte_be_to_cpu_16(hca_cap->pf0_vf_funcid_base);
173 [ # # ]: 0 : xdev->hwinfo.pf0_vf_funcid_top = rte_be_to_cpu_16(hca_cap->pf0_vf_funcid_top);
174 [ # # ]: 0 : xdev->hwinfo.pf1_vf_funcid_base = rte_be_to_cpu_16(hca_cap->pf1_vf_funcid_base);
175 [ # # ]: 0 : xdev->hwinfo.pf1_vf_funcid_top = rte_be_to_cpu_16(hca_cap->pf1_vf_funcid_top);
176 [ # # ]: 0 : xdev->hwinfo.pcie0_pf_funcid_base = rte_be_to_cpu_16(hca_cap->pcie0_pf_funcid_base);
177 [ # # ]: 0 : xdev->hwinfo.pcie0_pf_funcid_top = rte_be_to_cpu_16(hca_cap->pcie0_pf_funcid_top);
178 [ # # ]: 0 : xdev->hwinfo.pcie1_pf_funcid_base = rte_be_to_cpu_16(hca_cap->pcie1_pf_funcid_base);
179 [ # # ]: 0 : xdev->hwinfo.pcie1_pf_funcid_top = rte_be_to_cpu_16(hca_cap->pcie1_pf_funcid_top);
180 : 0 : xdev->hwinfo.lag_port_start = hca_cap->lag_logic_port_ofst;
181 [ # # ]: 0 : xdev->hwinfo.raw_tpe_qp_num = rte_be_to_cpu_16(hca_cap->raw_tpe_qp_num);
182 : 0 : xdev->hwinfo.send_seg_num = hca_cap->send_seg_num;
183 : 0 : xdev->hwinfo.recv_seg_num = hca_cap->recv_seg_num;
184 [ # # ]: 0 : feature = rte_be_to_cpu_32(hca_cap->feature_flag);
185 : 0 : xdev->hwinfo.on_chip_tbl_vld = (feature & XSC_FEATURE_ONCHIP_FT_MASK) ? 1 : 0;
186 : 0 : xdev->hwinfo.dma_rw_tbl_vld = (feature & XSC_FEATURE_DMA_RW_TBL_MASK) ? 1 : 0;
187 : 0 : xdev->hwinfo.pct_compress_vld = (feature & XSC_FEATURE_PCT_EXP_MASK) ? 1 : 0;
188 [ # # ]: 0 : xdev->hwinfo.chip_version = rte_be_to_cpu_32(hca_cap->chip_ver_l);
189 [ # # ]: 0 : xdev->hwinfo.hca_core_clock = rte_be_to_cpu_32(hca_cap->hca_core_clock);
190 : 0 : xdev->hwinfo.mac_bit = hca_cap->mac_bit;
191 [ # # ]: 0 : xdev->hwinfo.msix_base = rte_be_to_cpu_16(hca_cap->msix_base);
192 [ # # ]: 0 : xdev->hwinfo.msix_num = rte_be_to_cpu_16(hca_cap->msix_num);
193 : 0 : xsc_vfio_pcie_no_init(&xdev->hwinfo);
194 : 0 : xsc_vfio_fw_version_init(xdev->hwinfo.fw_ver, &hca_cap->fw_ver);
195 : :
196 : 0 : exit:
197 : 0 : free(cmd_buf);
198 : 0 : return ret;
199 : : }
200 : :
201 : : static int
202 : 0 : xsc_vfio_dev_open(struct xsc_dev *xdev)
203 : : {
204 : 0 : struct rte_pci_addr *addr = &xdev->pci_dev->addr;
205 : : struct xsc_vfio_priv *priv;
206 : :
207 : 0 : snprintf(xdev->name, PCI_PRI_STR_SIZE, PCI_PRI_FMT,
208 : 0 : addr->domain, addr->bus, addr->devid, addr->function);
209 : :
210 : 0 : priv = rte_zmalloc(NULL, sizeof(*priv), RTE_CACHE_LINE_SIZE);
211 [ # # ]: 0 : if (priv == NULL) {
212 : 0 : PMD_DRV_LOG(ERR, "Failed to alloc xsc vfio priv");
213 : 0 : return -ENOMEM;
214 : : }
215 : :
216 : 0 : xdev->dev_priv = (void *)priv;
217 : 0 : return 0;
218 : : }
219 : :
220 : : static int
221 : 0 : xsc_vfio_bar_init(struct xsc_dev *xdev)
222 : : {
223 : : int ret;
224 : :
225 : 0 : ret = rte_pci_map_device(xdev->pci_dev);
226 [ # # ]: 0 : if (ret) {
227 : 0 : PMD_DRV_LOG(ERR, "Failed to map pci device");
228 : 0 : return -EINVAL;
229 : : }
230 : :
231 : 0 : xdev->bar_len = xdev->pci_dev->mem_resource[0].len;
232 : 0 : xdev->bar_addr = (void *)xdev->pci_dev->mem_resource[0].addr;
233 [ # # ]: 0 : if (xdev->bar_addr == NULL) {
234 : 0 : PMD_DRV_LOG(ERR, "Failed to attach dev(%s) bar", xdev->pci_dev->device.name);
235 : 0 : return -EINVAL;
236 : : }
237 : :
238 : : return 0;
239 : : }
240 : :
241 : : static int
242 : 0 : xsc_vfio_dev_close(struct xsc_dev *xdev)
243 : : {
244 : 0 : struct xsc_vfio_priv *vfio_priv = (struct xsc_vfio_priv *)xdev->dev_priv;
245 : :
246 : 0 : xsc_vfio_mbox_destroy(vfio_priv->cmdq);
247 : 0 : rte_pci_unmap_device(xdev->pci_dev);
248 : 0 : rte_free(vfio_priv);
249 : :
250 : 0 : return 0;
251 : : }
252 : :
253 : : static int
254 : 0 : xsc_vfio_destroy_qp(void *qp)
255 : : {
256 : : int ret;
257 : : int in_len, out_len, cmd_len;
258 : : struct xsc_cmd_destroy_qp_mbox_in *in;
259 : : struct xsc_cmd_destroy_qp_mbox_out *out;
260 : : struct xsc_vfio_qp *data = (struct xsc_vfio_qp *)qp;
261 : : void *cmd_buf;
262 : :
263 : : in_len = sizeof(struct xsc_cmd_destroy_qp_mbox_in);
264 : : out_len = sizeof(struct xsc_cmd_destroy_qp_mbox_out);
265 : : cmd_len = RTE_MAX(in_len, out_len);
266 : :
267 : 0 : cmd_buf = malloc(cmd_len);
268 [ # # ]: 0 : if (cmd_buf == NULL) {
269 : 0 : rte_errno = ENOMEM;
270 : 0 : PMD_DRV_LOG(ERR, "Failed to alloc qp destroy cmd memory");
271 : 0 : return -rte_errno;
272 : : }
273 : :
274 : : in = cmd_buf;
275 : : memset(in, 0, cmd_len);
276 : 0 : in->hdr.opcode = rte_cpu_to_be_16(XSC_CMD_OP_DESTROY_QP);
277 [ # # ]: 0 : in->qpn = rte_cpu_to_be_32(data->qpn);
278 : : out = cmd_buf;
279 : 0 : ret = xsc_vfio_mbox_exec(data->xdev, in, in_len, out, out_len);
280 [ # # # # ]: 0 : if (ret != 0 || out->hdr.status != 0) {
281 : 0 : PMD_DRV_LOG(ERR, "Failed to destroy qp, type=%d, err=%d, out.status=%u",
282 : : XSC_QUEUE_TYPE_RAW, ret, out->hdr.status);
283 : 0 : rte_errno = ENOEXEC;
284 : : ret = -rte_errno;
285 : 0 : goto exit;
286 : : }
287 : :
288 : 0 : rte_memzone_free(data->mz);
289 : 0 : rte_free(qp);
290 : :
291 : 0 : exit:
292 : 0 : free(cmd_buf);
293 : 0 : return ret;
294 : : }
295 : :
296 : : static int
297 : 0 : xsc_vfio_destroy_cq(void *cq)
298 : : {
299 : : int ret;
300 : : int in_len, out_len, cmd_len;
301 : : struct xsc_cmd_destroy_cq_mbox_in *in;
302 : : struct xsc_cmd_destroy_cq_mbox_out *out;
303 : : struct xsc_vfio_cq *data = (struct xsc_vfio_cq *)cq;
304 : : void *cmd_buf;
305 : :
306 : : in_len = sizeof(struct xsc_cmd_destroy_cq_mbox_in);
307 : : out_len = sizeof(struct xsc_cmd_destroy_cq_mbox_out);
308 : : cmd_len = RTE_MAX(in_len, out_len);
309 : :
310 : 0 : cmd_buf = malloc(cmd_len);
311 [ # # ]: 0 : if (cmd_buf == NULL) {
312 : 0 : rte_errno = ENOMEM;
313 : 0 : PMD_DRV_LOG(ERR, "Failed to alloc cq destroy cmd memory");
314 : 0 : return -rte_errno;
315 : : }
316 : :
317 : : in = cmd_buf;
318 : : memset(in, 0, cmd_len);
319 : :
320 : 0 : in->hdr.opcode = rte_cpu_to_be_16(XSC_CMD_OP_DESTROY_CQ);
321 [ # # ]: 0 : in->cqn = rte_cpu_to_be_32(data->cqn);
322 : : out = cmd_buf;
323 : 0 : ret = xsc_vfio_mbox_exec(data->xdev, in, in_len, out, out_len);
324 [ # # # # ]: 0 : if (ret != 0 || out->hdr.status != 0) {
325 : 0 : PMD_DRV_LOG(ERR, "Failed to destroy cq, type=%d, err=%d, out.status=%u",
326 : : XSC_QUEUE_TYPE_RAW, ret, out->hdr.status);
327 : 0 : rte_errno = ENOEXEC;
328 : : ret = -rte_errno;
329 : 0 : goto exit;
330 : : }
331 : :
332 : 0 : rte_memzone_free(data->mz);
333 : 0 : rte_free(cq);
334 : :
335 : 0 : exit:
336 : 0 : free(cmd_buf);
337 : 0 : return ret;
338 : : }
339 : :
340 : : static int
341 : 0 : xsc_vfio_set_mtu(struct xsc_dev *xdev, uint16_t mtu)
342 : : {
343 : 0 : struct xsc_cmd_set_mtu_mbox_in in = { };
344 : 0 : struct xsc_cmd_set_mtu_mbox_out out = { };
345 : : int ret;
346 : :
347 : 0 : in.hdr.opcode = rte_cpu_to_be_16(XSC_CMD_OP_SET_MTU);
348 [ # # ]: 0 : in.mtu = rte_cpu_to_be_16(XSC_SW2HW_MTU(mtu));
349 [ # # ]: 0 : in.rx_buf_sz_min = rte_cpu_to_be_16(XSC_SW2HW_RX_PKT_LEN(mtu));
350 : 0 : in.mac_port = (uint8_t)xdev->hwinfo.mac_phy_port;
351 : :
352 : 0 : ret = xsc_vfio_mbox_exec(xdev, &in, sizeof(in), &out, sizeof(out));
353 [ # # # # ]: 0 : if (ret != 0 || out.hdr.status != 0) {
354 : 0 : PMD_DRV_LOG(ERR, "Failed to set mtu, port=%d, err=%d, out.status=%u",
355 : : xdev->port_id, ret, out.hdr.status);
356 : 0 : rte_errno = ENOEXEC;
357 : : ret = -rte_errno;
358 : : }
359 : :
360 : 0 : return ret;
361 : : }
362 : :
363 : : static int
364 : 0 : xsc_vfio_get_mac(struct xsc_dev *xdev, uint8_t *mac)
365 : : {
366 : 0 : struct xsc_cmd_query_eth_mac_mbox_in in = { };
367 : 0 : struct xsc_cmd_query_eth_mac_mbox_out out = { };
368 : : int ret;
369 : :
370 : 0 : in.hdr.opcode = rte_cpu_to_be_16(XSC_CMD_OP_QUERY_ETH_MAC);
371 : 0 : ret = xsc_vfio_mbox_exec(xdev, &in, sizeof(in), &out, sizeof(out));
372 [ # # # # ]: 0 : if (ret != 0 || out.hdr.status != 0) {
373 : 0 : PMD_DRV_LOG(ERR, "Failed to get mtu, port=%d, err=%d, out.status=%u",
374 : : xdev->port_id, ret, out.hdr.status);
375 : 0 : rte_errno = ENOEXEC;
376 : 0 : return -rte_errno;
377 : : }
378 : :
379 : : memcpy(mac, out.mac, RTE_ETHER_ADDR_LEN);
380 : :
381 : 0 : return 0;
382 : : }
383 : :
384 : : static int
385 : 0 : xsc_vfio_modify_link_status(struct xsc_dev *xdev, uint16_t status)
386 : : {
387 : 0 : struct xsc_cmd_set_port_admin_status_mbox_in in = { };
388 : 0 : struct xsc_cmd_set_port_admin_status_mbox_out out = { };
389 : : int ret = 0;
390 : :
391 : 0 : in.hdr.opcode = rte_cpu_to_be_16(XSC_CMD_OP_SET_PORT_ADMIN_STATUS);
392 [ # # ]: 0 : in.admin_status = rte_cpu_to_be_16(status);
393 : :
394 : 0 : ret = xsc_vfio_mbox_exec(xdev, &in, sizeof(in), &out, sizeof(out));
395 [ # # # # ]: 0 : if (ret != 0 || out.hdr.status != 0) {
396 : 0 : PMD_DRV_LOG(ERR, "Failed to set link status, ret=%d, status=%d",
397 : : ret, out.hdr.status);
398 : 0 : return -ENOEXEC;
399 : : }
400 : :
401 : : return ret;
402 : : }
403 : :
404 : : static int
405 : 0 : xsc_vfio_link_status_set(struct xsc_dev *xdev, uint16_t status)
406 : : {
407 [ # # ]: 0 : if (status != RTE_ETH_LINK_UP && status != RTE_ETH_LINK_DOWN)
408 : : return -EINVAL;
409 : :
410 : 0 : return xsc_vfio_modify_link_status(xdev, status);
411 : : }
412 : :
413 : : static uint32_t
414 : : xsc_vfio_link_speed_translate(uint32_t mode)
415 : : {
416 [ # # ]: 0 : if (mode >= XSC_MODULE_SPEED_MAX)
417 : : return RTE_ETH_SPEED_NUM_NONE;
418 : :
419 : 0 : return xsc_link_speed[mode];
420 : : }
421 : :
422 : : static int
423 : 0 : xsc_vfio_link_get(struct xsc_dev *xdev, struct rte_eth_link *link)
424 : : {
425 : 0 : struct xsc_cmd_query_linkinfo_mbox_in in = { };
426 : 0 : struct xsc_cmd_query_linkinfo_mbox_out out = { };
427 : : struct xsc_cmd_linkinfo linkinfo;
428 : : int ret;
429 : : uint32_t speed_mode;
430 : :
431 : 0 : in.hdr.opcode = rte_cpu_to_be_16(XSC_CMD_OP_QUERY_LINK_INFO);
432 : 0 : ret = xsc_vfio_mbox_exec(xdev, &in, sizeof(in), &out, sizeof(out));
433 [ # # # # ]: 0 : if (ret != 0 || out.hdr.status != 0) {
434 : 0 : PMD_DRV_LOG(ERR, "Failed to get link info, ret=%d, status=%d",
435 : : ret, out.hdr.status);
436 : 0 : return -ENOEXEC;
437 : : }
438 : :
439 : 0 : linkinfo = out.ctx;
440 : 0 : link->link_status = linkinfo.status ? RTE_ETH_LINK_UP : RTE_ETH_LINK_DOWN;
441 [ # # ]: 0 : speed_mode = rte_be_to_cpu_32(linkinfo.linkspeed);
442 : 0 : link->link_speed = xsc_vfio_link_speed_translate(speed_mode);
443 : 0 : link->link_duplex = linkinfo.duplex;
444 : 0 : link->link_autoneg = linkinfo.autoneg;
445 : :
446 : 0 : return 0;
447 : : };
448 : :
449 : : static int
450 : 0 : xsc_vfio_modify_qp_status(struct xsc_dev *xdev, uint32_t qpn, int num, int opcode)
451 : : {
452 : : int i, ret;
453 : : int in_len, out_len, cmd_len;
454 : : struct xsc_cmd_modify_qp_mbox_in *in;
455 : : struct xsc_cmd_modify_qp_mbox_out *out;
456 : : void *cmd_buf;
457 : :
458 : : in_len = sizeof(struct xsc_cmd_modify_qp_mbox_in);
459 : : out_len = sizeof(struct xsc_cmd_modify_qp_mbox_out);
460 : : cmd_len = RTE_MAX(in_len, out_len);
461 : :
462 : 0 : cmd_buf = malloc(cmd_len);
463 [ # # ]: 0 : if (cmd_buf == NULL) {
464 : 0 : PMD_DRV_LOG(ERR, "Failed to alloc cmdq qp modify status");
465 : 0 : rte_errno = ENOMEM;
466 : 0 : return -rte_errno;
467 : : }
468 : :
469 : : in = cmd_buf;
470 : : memset(in, 0, cmd_len);
471 : : out = cmd_buf;
472 : :
473 [ # # ]: 0 : for (i = 0; i < num; i++) {
474 [ # # ]: 0 : in->hdr.opcode = rte_cpu_to_be_16(opcode);
475 : 0 : in->hdr.ver = 0;
476 [ # # ]: 0 : in->qpn = rte_cpu_to_be_32(qpn + i);
477 : 0 : in->no_need_wait = 1;
478 : :
479 : 0 : ret = xsc_vfio_mbox_exec(xdev, in, in_len, out, out_len);
480 [ # # # # ]: 0 : if (ret != 0 || out->hdr.status != 0) {
481 : 0 : PMD_DRV_LOG(ERR, "Modify qp status failed, qpn=%u, err=%d, out.status=%u",
482 : : qpn + i, ret, out->hdr.status);
483 : 0 : rte_errno = ENOEXEC;
484 : : ret = -rte_errno;
485 : 0 : goto exit;
486 : : }
487 : : }
488 : :
489 : 0 : exit:
490 : 0 : free(cmd_buf);
491 : 0 : return ret;
492 : : }
493 : :
494 : : static int
495 : 0 : xsc_vfio_modify_qp_qostree(struct xsc_dev *xdev, uint16_t qpn)
496 : : {
497 : : int ret;
498 : : int in_len, out_len, cmd_len;
499 : : struct xsc_cmd_modify_raw_qp_mbox_in *in;
500 : : struct xsc_cmd_modify_raw_qp_mbox_out *out;
501 : : void *cmd_buf;
502 : :
503 : : in_len = sizeof(struct xsc_cmd_modify_raw_qp_mbox_in);
504 : : out_len = sizeof(struct xsc_cmd_modify_raw_qp_mbox_out);
505 : : cmd_len = RTE_MAX(in_len, out_len);
506 : :
507 : 0 : cmd_buf = malloc(cmd_len);
508 [ # # ]: 0 : if (cmd_buf == NULL) {
509 : 0 : PMD_DRV_LOG(ERR, "Failed to alloc cmdq qp modify qostree");
510 : 0 : rte_errno = ENOMEM;
511 : 0 : return -rte_errno;
512 : : }
513 : :
514 : : in = cmd_buf;
515 : : memset(in, 0, cmd_len);
516 : 0 : in->hdr.opcode = rte_cpu_to_be_16(XSC_CMD_OP_MODIFY_RAW_QP);
517 : : in->req.prio = 0;
518 : 0 : in->req.qp_out_port = 0xFF;
519 [ # # ]: 0 : in->req.lag_id = rte_cpu_to_be_16(xdev->hwinfo.lag_id);
520 [ # # ]: 0 : in->req.func_id = rte_cpu_to_be_16(xdev->hwinfo.func_id);
521 : : in->req.dma_direct = 0;
522 [ # # ]: 0 : in->req.qpn = rte_cpu_to_be_16(qpn);
523 : : out = cmd_buf;
524 : :
525 : 0 : ret = xsc_vfio_mbox_exec(xdev, in, in_len, out, out_len);
526 [ # # # # ]: 0 : if (ret != 0 || out->hdr.status != 0) {
527 : 0 : PMD_DRV_LOG(ERR, "Filed to modify qp qostree, qpn=%d, err=%d, out.status=%u",
528 : : qpn, ret, out->hdr.status);
529 : 0 : rte_errno = ENOEXEC;
530 : : ret = -rte_errno;
531 : 0 : goto exit;
532 : : }
533 : :
534 : 0 : exit:
535 : 0 : free(cmd_buf);
536 : 0 : return ret;
537 : : }
538 : :
539 : : static int
540 : 0 : xsc_vfio_rx_cq_create(struct xsc_dev *xdev, struct xsc_rx_cq_params *cq_params,
541 : : struct xsc_rx_cq_info *cq_info)
542 : : {
543 : : int ret;
544 : : int pa_len;
545 : : uint16_t i;
546 : : uint16_t pa_num;
547 : : uint8_t log_cq_sz;
548 : : uint16_t cqe_n;
549 : : uint32_t cqe_total_sz;
550 : : int in_len, out_len, cmd_len;
551 : 0 : char name[RTE_ETH_NAME_MAX_LEN] = { 0 };
552 : 0 : uint16_t port_id = cq_params->port_id;
553 : 0 : uint16_t idx = cq_params->qp_id;
554 : : struct xsc_vfio_cq *cq;
555 : : const struct rte_memzone *cq_pas = NULL;
556 : : struct xsc_cqe *cqes;
557 : : struct xsc_cmd_create_cq_mbox_in *in = NULL;
558 : : struct xsc_cmd_create_cq_mbox_out *out = NULL;
559 : : void *cmd_buf;
560 : 0 : int numa_node = xdev->pci_dev->device.numa_node;
561 : :
562 [ # # ]: 0 : if (numa_node != cq_params->socket_id)
563 : 0 : PMD_DRV_LOG(WARNING, "Port %u rxq %u: cq numa_node=%u, device numa_node=%u",
564 : : port_id, idx, cq_params->socket_id, numa_node);
565 : :
566 : 0 : cqe_n = cq_params->wqe_s * 2;
567 [ # # ]: 0 : log_cq_sz = rte_log2_u32(cqe_n);
568 : 0 : cqe_total_sz = cqe_n * sizeof(struct xsc_cqe);
569 : 0 : pa_num = (cqe_total_sz + XSC_PAGE_SIZE - 1) / XSC_PAGE_SIZE;
570 : 0 : pa_len = sizeof(uint64_t) * pa_num;
571 : 0 : in_len = sizeof(struct xsc_cmd_create_cq_mbox_in) + pa_len;
572 : : out_len = sizeof(struct xsc_cmd_create_cq_mbox_out);
573 : 0 : cmd_len = RTE_MAX(in_len, out_len);
574 : :
575 : 0 : cq = rte_zmalloc(NULL, sizeof(struct xsc_vfio_cq), 0);
576 [ # # ]: 0 : if (cq == NULL) {
577 : 0 : rte_errno = ENOMEM;
578 : 0 : PMD_DRV_LOG(ERR, "Failed to alloc rx cq memory");
579 : 0 : return -rte_errno;
580 : : }
581 : :
582 : 0 : cmd_buf = malloc(cmd_len);
583 [ # # ]: 0 : if (cmd_buf == NULL) {
584 : 0 : rte_errno = ENOMEM;
585 : 0 : PMD_DRV_LOG(ERR, "Failed to alloc rx cq exec cmd memory");
586 : 0 : goto error;
587 : : }
588 : :
589 : : in = cmd_buf;
590 : : memset(in, 0, cmd_len);
591 : 0 : in->hdr.opcode = rte_cpu_to_be_16(XSC_CMD_OP_CREATE_CQ);
592 : 0 : in->ctx.eqn = 0;
593 [ # # ]: 0 : in->ctx.pa_num = rte_cpu_to_be_16(pa_num);
594 [ # # ]: 0 : in->ctx.glb_func_id = rte_cpu_to_be_16((uint16_t)xdev->hwinfo.func_id);
595 : 0 : in->ctx.log_cq_sz = log_cq_sz;
596 : 0 : in->ctx.cq_type = XSC_CQ_TYPE_NORMAL;
597 : :
598 : 0 : snprintf(name, sizeof(name), "mz_cqe_mem_rx_%u_%u", port_id, idx);
599 : 0 : cq_pas = rte_memzone_reserve_aligned(name,
600 : 0 : (XSC_PAGE_SIZE * pa_num),
601 : : cq_params->socket_id,
602 : : RTE_MEMZONE_IOVA_CONTIG,
603 : : XSC_PAGE_SIZE);
604 [ # # ]: 0 : if (cq_pas == NULL) {
605 : 0 : rte_errno = ENOMEM;
606 : 0 : PMD_DRV_LOG(ERR, "Failed to alloc rx cq pas memory");
607 : 0 : goto error;
608 : : }
609 : 0 : cq->mz = cq_pas;
610 : :
611 [ # # ]: 0 : for (i = 0; i < pa_num; i++)
612 [ # # ]: 0 : in->pas[i] = rte_cpu_to_be_64(cq_pas->iova + i * XSC_PAGE_SIZE);
613 : :
614 : : out = cmd_buf;
615 : 0 : ret = xsc_vfio_mbox_exec(xdev, in, in_len, out, out_len);
616 [ # # # # ]: 0 : if (ret != 0 || out->hdr.status != 0) {
617 : 0 : PMD_DRV_LOG(ERR,
618 : : "Failed to exec rx cq create cmd, port id=%d, err=%d, out.status=%u",
619 : : port_id, ret, out->hdr.status);
620 : 0 : rte_errno = ENOEXEC;
621 : 0 : goto error;
622 : : }
623 : :
624 : 0 : cq_info->cq = (void *)cq;
625 : 0 : cq_info->cqe_n = log_cq_sz;
626 : 0 : cqes = (struct xsc_cqe *)cq_pas->addr;
627 [ # # ]: 0 : for (i = 0; i < (1 << cq_info->cqe_n); i++)
628 : 0 : ((volatile struct xsc_cqe *)(cqes + i))->owner = 1;
629 : 0 : cq_info->cqes = cqes;
630 : 0 : cq_info->cq_db = xdev->reg_addr.cq_db_addr;
631 [ # # ]: 0 : cq_info->cqn = rte_be_to_cpu_32(out->cqn);
632 : 0 : cq->cqn = cq_info->cqn;
633 : 0 : cq->xdev = xdev;
634 : 0 : PMD_DRV_LOG(INFO, "Port id=%d, Rx cqe_n:%d, cqn:%u",
635 : : port_id, cq_info->cqe_n, cq_info->cqn);
636 : :
637 : 0 : free(cmd_buf);
638 : 0 : return 0;
639 : :
640 : 0 : error:
641 : 0 : free(cmd_buf);
642 : 0 : rte_memzone_free(cq_pas);
643 : 0 : rte_free(cq);
644 : 0 : return -rte_errno;
645 : : }
646 : :
647 : : static int
648 : 0 : xsc_vfio_tx_cq_create(struct xsc_dev *xdev, struct xsc_tx_cq_params *cq_params,
649 : : struct xsc_tx_cq_info *cq_info)
650 : : {
651 : : struct xsc_vfio_cq *cq = NULL;
652 : 0 : char name[RTE_ETH_NAME_MAX_LEN] = {0};
653 : : struct xsc_cmd_create_cq_mbox_in *in = NULL;
654 : : struct xsc_cmd_create_cq_mbox_out *out = NULL;
655 : : const struct rte_memzone *cq_pas = NULL;
656 : : struct xsc_cqe *cqes;
657 : : int in_len, out_len, cmd_len;
658 : : uint16_t pa_num;
659 : : uint16_t log_cq_sz;
660 : : int ret = 0;
661 : 0 : int cqe_s = 1 << cq_params->elts_n;
662 : : uint64_t iova;
663 : : int i;
664 : : void *cmd_buf = NULL;
665 : 0 : int numa_node = xdev->pci_dev->device.numa_node;
666 : :
667 [ # # ]: 0 : if (numa_node != cq_params->socket_id)
668 : 0 : PMD_DRV_LOG(WARNING, "Port %u txq %u: cq numa_node=%u, device numa_node=%u",
669 : : cq_params->port_id, cq_params->qp_id,
670 : : cq_params->socket_id, numa_node);
671 : :
672 : 0 : cq = rte_zmalloc(NULL, sizeof(struct xsc_vfio_cq), 0);
673 [ # # ]: 0 : if (cq == NULL) {
674 : 0 : rte_errno = ENOMEM;
675 : 0 : PMD_DRV_LOG(ERR, "Failed to alloc tx cq memory");
676 : 0 : return -rte_errno;
677 : : }
678 : :
679 [ # # ]: 0 : log_cq_sz = rte_log2_u32(cqe_s);
680 : 0 : pa_num = (((1 << log_cq_sz) * sizeof(struct xsc_cqe)) / XSC_PAGE_SIZE);
681 : :
682 : 0 : snprintf(name, sizeof(name), "mz_cqe_mem_tx_%u_%u", cq_params->port_id, cq_params->qp_id);
683 : 0 : cq_pas = rte_memzone_reserve_aligned(name,
684 : 0 : (XSC_PAGE_SIZE * pa_num),
685 : : cq_params->socket_id,
686 : : RTE_MEMZONE_IOVA_CONTIG,
687 : : XSC_PAGE_SIZE);
688 [ # # ]: 0 : if (cq_pas == NULL) {
689 : 0 : rte_errno = ENOMEM;
690 : 0 : PMD_DRV_LOG(ERR, "Failed to alloc tx cq pas memory");
691 : 0 : goto error;
692 : : }
693 : :
694 : 0 : cq->mz = cq_pas;
695 : 0 : in_len = (sizeof(struct xsc_cmd_create_cq_mbox_in) + (pa_num * sizeof(uint64_t)));
696 : : out_len = sizeof(struct xsc_cmd_create_cq_mbox_out);
697 : 0 : cmd_len = RTE_MAX(in_len, out_len);
698 : 0 : cmd_buf = malloc(cmd_len);
699 [ # # ]: 0 : if (cmd_buf == NULL) {
700 : 0 : rte_errno = ENOMEM;
701 : 0 : PMD_DRV_LOG(ERR, "Failed to alloc tx cq exec cmd memory");
702 : 0 : goto error;
703 : : }
704 : :
705 : : in = cmd_buf;
706 : : memset(in, 0, cmd_len);
707 : :
708 : 0 : in->hdr.opcode = rte_cpu_to_be_16(XSC_CMD_OP_CREATE_CQ);
709 : 0 : in->ctx.eqn = 0;
710 [ # # ]: 0 : in->ctx.pa_num = rte_cpu_to_be_16(pa_num);
711 [ # # ]: 0 : in->ctx.glb_func_id = rte_cpu_to_be_16((uint16_t)xdev->hwinfo.func_id);
712 : 0 : in->ctx.log_cq_sz = rte_log2_u32(cqe_s);
713 : 0 : in->ctx.cq_type = XSC_CQ_TYPE_NORMAL;
714 : 0 : iova = cq->mz->iova;
715 [ # # ]: 0 : for (i = 0; i < pa_num; i++)
716 [ # # ]: 0 : in->pas[i] = rte_cpu_to_be_64(iova + i * XSC_PAGE_SIZE);
717 : :
718 : : out = cmd_buf;
719 : 0 : ret = xsc_vfio_mbox_exec(xdev, in, in_len, out, out_len);
720 [ # # # # ]: 0 : if (ret != 0 || out->hdr.status != 0) {
721 : 0 : PMD_DRV_LOG(ERR, "Failed to create tx cq, port id=%u, err=%d, out.status=%u",
722 : : cq_params->port_id, ret, out->hdr.status);
723 : 0 : rte_errno = ENOEXEC;
724 : 0 : goto error;
725 : : }
726 : :
727 [ # # ]: 0 : cq->cqn = rte_be_to_cpu_32(out->cqn);
728 : 0 : cq->xdev = xdev;
729 : :
730 : 0 : cq_info->cq = cq;
731 : 0 : cqes = (struct xsc_cqe *)((uint8_t *)cq->mz->addr);
732 : 0 : cq_info->cq_db = xdev->reg_addr.cq_db_addr;
733 : 0 : cq_info->cqn = cq->cqn;
734 : 0 : cq_info->cqe_s = cqe_s;
735 : 0 : cq_info->cqe_n = log_cq_sz;
736 : :
737 [ # # ]: 0 : for (i = 0; i < cq_info->cqe_s; i++)
738 : 0 : ((volatile struct xsc_cqe *)(cqes + i))->owner = 1;
739 : 0 : cq_info->cqes = cqes;
740 : :
741 : 0 : free(cmd_buf);
742 : 0 : return 0;
743 : :
744 : 0 : error:
745 : 0 : free(cmd_buf);
746 : 0 : rte_memzone_free(cq_pas);
747 : 0 : rte_free(cq);
748 : 0 : return -rte_errno;
749 : : }
750 : :
751 : : static int
752 : 0 : xsc_vfio_tx_qp_create(struct xsc_dev *xdev, struct xsc_tx_qp_params *qp_params,
753 : : struct xsc_tx_qp_info *qp_info)
754 : : {
755 : : struct xsc_cmd_create_qp_mbox_in *in = NULL;
756 : : struct xsc_cmd_create_qp_mbox_out *out = NULL;
757 : : const struct rte_memzone *qp_pas = NULL;
758 : 0 : struct xsc_vfio_cq *cq = (struct xsc_vfio_cq *)qp_params->cq;
759 : : struct xsc_vfio_qp *qp = NULL;
760 : : int in_len, out_len, cmd_len;
761 : : int ret = 0;
762 : 0 : uint32_t send_ds_num = xdev->hwinfo.send_seg_num;
763 : 0 : int wqe_s = 1 << qp_params->elts_n;
764 : : uint16_t pa_num;
765 : : uint8_t log_ele = 0;
766 : : uint32_t log_rq_sz = 0;
767 : : uint32_t log_sq_sz = 0;
768 : : int i;
769 : : uint64_t iova;
770 : 0 : char name[RTE_ETH_NAME_MAX_LEN] = {0};
771 : : void *cmd_buf = NULL;
772 : 0 : bool tso_en = !!(qp_params->tx_offloads & RTE_ETH_TX_OFFLOAD_TCP_TSO);
773 : 0 : int numa_node = xdev->pci_dev->device.numa_node;
774 : :
775 [ # # ]: 0 : if (numa_node != qp_params->socket_id)
776 : 0 : PMD_DRV_LOG(WARNING, "Port %u: txq %u numa_node=%u, device numa_node=%u",
777 : : qp_params->port_id, qp_params->qp_id,
778 : : qp_params->socket_id, numa_node);
779 : :
780 : 0 : qp = rte_zmalloc(NULL, sizeof(struct xsc_vfio_qp), 0);
781 [ # # ]: 0 : if (qp == NULL) {
782 : 0 : rte_errno = ENOMEM;
783 : 0 : PMD_DRV_LOG(ERR, "Failed to alloc tx qp memory");
784 : 0 : return -rte_errno;
785 : : }
786 : :
787 [ # # ]: 0 : log_sq_sz = rte_log2_u32(wqe_s * send_ds_num);
788 : : log_ele = rte_log2_u32(sizeof(struct xsc_wqe_data_seg));
789 : 0 : pa_num = ((1 << (log_rq_sz + log_sq_sz + log_ele))) / XSC_PAGE_SIZE;
790 : :
791 : 0 : snprintf(name, sizeof(name), "mz_wqe_mem_tx_%u_%u", qp_params->port_id, qp_params->qp_id);
792 : 0 : qp_pas = rte_memzone_reserve_aligned(name,
793 : 0 : (XSC_PAGE_SIZE * pa_num),
794 : : qp_params->socket_id,
795 : : RTE_MEMZONE_IOVA_CONTIG,
796 : : XSC_PAGE_SIZE);
797 [ # # ]: 0 : if (qp_pas == NULL) {
798 : 0 : rte_errno = ENOMEM;
799 : 0 : PMD_DRV_LOG(ERR, "Failed to alloc tx qp pas memory");
800 : 0 : goto error;
801 : : }
802 : 0 : qp->mz = qp_pas;
803 : :
804 : 0 : in_len = (sizeof(struct xsc_cmd_create_qp_mbox_in) + (pa_num * sizeof(uint64_t)));
805 : : out_len = sizeof(struct xsc_cmd_create_qp_mbox_out);
806 : 0 : cmd_len = RTE_MAX(in_len, out_len);
807 : 0 : cmd_buf = malloc(cmd_len);
808 [ # # ]: 0 : if (cmd_buf == NULL) {
809 : 0 : rte_errno = ENOMEM;
810 : 0 : PMD_DRV_LOG(ERR, "Failed to alloc tx qp exec cmd memory");
811 : 0 : goto error;
812 : : }
813 : :
814 : : in = cmd_buf;
815 : : memset(in, 0, cmd_len);
816 : :
817 : 0 : in->hdr.opcode = rte_cpu_to_be_16(XSC_CMD_OP_CREATE_QP);
818 : 0 : in->req.input_qpn = 0;
819 [ # # ]: 0 : in->req.pa_num = rte_cpu_to_be_16(pa_num);
820 [ # # ]: 0 : in->req.qp_type = tso_en ? XSC_QUEUE_TYPE_RAW_TSO : XSC_QUEUE_TYPE_RAW_TX;
821 : 0 : in->req.log_sq_sz = log_sq_sz;
822 : 0 : in->req.log_rq_sz = log_rq_sz;
823 : 0 : in->req.dma_direct = 0;
824 : 0 : in->req.pdn = 0;
825 [ # # ]: 0 : in->req.cqn_send = rte_cpu_to_be_16((uint16_t)cq->cqn);
826 : 0 : in->req.cqn_recv = 0;
827 [ # # ]: 0 : in->req.glb_funcid = rte_cpu_to_be_16((uint16_t)xdev->hwinfo.func_id);
828 : 0 : iova = qp->mz->iova;
829 [ # # ]: 0 : for (i = 0; i < pa_num; i++)
830 [ # # ]: 0 : in->req.pas[i] = rte_cpu_to_be_64(iova + i * XSC_PAGE_SIZE);
831 : :
832 : : out = cmd_buf;
833 : 0 : ret = xsc_vfio_mbox_exec(xdev, in, in_len, out, out_len);
834 [ # # # # ]: 0 : if (ret != 0 || out->hdr.status != 0) {
835 : 0 : PMD_DRV_LOG(ERR, "Failed to create tx qp, port id=%u, err=%d, out.status=%u",
836 : : qp_params->port_id, ret, out->hdr.status);
837 : 0 : rte_errno = ENOEXEC;
838 : 0 : goto error;
839 : : }
840 : :
841 [ # # ]: 0 : qp->qpn = rte_be_to_cpu_32(out->qpn);
842 : 0 : qp->xdev = xdev;
843 : :
844 : 0 : qp_info->qp = qp;
845 : 0 : qp_info->qpn = qp->qpn;
846 [ # # ]: 0 : qp_info->wqes = (struct xsc_wqe *)qp->mz->addr;
847 : 0 : qp_info->wqe_n = rte_log2_u32(wqe_s);
848 : 0 : qp_info->tso_en = tso_en ? 1 : 0;
849 : 0 : qp_info->qp_db = xdev->reg_addr.txq_db_addr;
850 : :
851 : 0 : free(cmd_buf);
852 : 0 : return 0;
853 : :
854 : 0 : error:
855 : 0 : free(cmd_buf);
856 : 0 : rte_memzone_free(qp_pas);
857 : 0 : rte_free(qp);
858 : 0 : return -rte_errno;
859 : : }
860 : :
861 : : static int
862 : 0 : xsc_vfio_dev_init(struct xsc_dev *xdev)
863 : : {
864 : : int ret;
865 : :
866 : 0 : ret = xsc_vfio_dev_open(xdev);
867 [ # # ]: 0 : if (ret != 0)
868 : 0 : goto open_fail;
869 : :
870 : 0 : ret = xsc_vfio_bar_init(xdev);
871 [ # # ]: 0 : if (ret != 0)
872 : 0 : goto init_fail;
873 : :
874 [ # # ]: 0 : if (xsc_vfio_mbox_init(xdev) != 0)
875 : 0 : goto init_fail;
876 : :
877 : 0 : ret = xsc_vfio_hwinfo_init(xdev);
878 [ # # ]: 0 : if (ret != 0)
879 : 0 : goto init_fail;
880 : :
881 : : return 0;
882 : :
883 : 0 : init_fail:
884 : 0 : xsc_vfio_dev_close(xdev);
885 : :
886 : : open_fail:
887 : : return -1;
888 : : }
889 : :
890 : : static int
891 : 0 : xsc_vfio_irq_info_get(struct rte_intr_handle *intr_handle)
892 : : {
893 : 0 : struct vfio_irq_info irq = { .argsz = sizeof(irq) };
894 : : int rc, vfio_dev_fd;
895 : :
896 : 0 : irq.index = VFIO_PCI_MSIX_IRQ_INDEX;
897 : :
898 : 0 : vfio_dev_fd = rte_intr_dev_fd_get(intr_handle);
899 : 0 : rc = ioctl(vfio_dev_fd, VFIO_DEVICE_GET_IRQ_INFO, &irq);
900 [ # # ]: 0 : if (rc < 0) {
901 : 0 : PMD_DRV_LOG(ERR, "Failed to get IRQ info rc=%d errno=%d", rc, errno);
902 : 0 : return rc;
903 : : }
904 : :
905 : 0 : PMD_DRV_LOG(INFO, "Flags=0x%x index=0x%x count=0x%x max_intr_vec_id=0x%x",
906 : : irq.flags, irq.index, irq.count, XSC_MAX_INTR_VEC_ID);
907 : :
908 [ # # ]: 0 : if (rte_intr_max_intr_set(intr_handle, irq.count))
909 : 0 : return -1;
910 : :
911 : : return 0;
912 : : }
913 : :
914 : : static int
915 : 0 : xsc_vfio_irq_init(struct rte_intr_handle *intr_handle)
916 : : {
917 : : char irq_set_buf[XSC_MSIX_IRQ_SET_BUF_LEN];
918 : : struct vfio_irq_set *irq_set;
919 : : int len, rc, vfio_dev_fd;
920 : : int32_t *fd_ptr;
921 : : uint32_t i;
922 : :
923 [ # # ]: 0 : if (rte_intr_max_intr_get(intr_handle) > XSC_MAX_INTR_VEC_ID) {
924 : 0 : PMD_DRV_LOG(ERR, "Max_intr=%d greater than XSC_MAX_INTR_VEC_ID=%d",
925 : : rte_intr_max_intr_get(intr_handle),
926 : : XSC_MAX_INTR_VEC_ID);
927 : 0 : return -ERANGE;
928 : : }
929 : :
930 : 0 : len = sizeof(struct vfio_irq_set) +
931 : 0 : sizeof(int32_t) * rte_intr_max_intr_get(intr_handle);
932 : :
933 : : irq_set = (struct vfio_irq_set *)irq_set_buf;
934 : 0 : irq_set->argsz = len;
935 : 0 : irq_set->start = 0;
936 : 0 : irq_set->count = 10;
937 : 0 : irq_set->flags = VFIO_IRQ_SET_DATA_EVENTFD | VFIO_IRQ_SET_ACTION_TRIGGER;
938 : 0 : irq_set->index = VFIO_PCI_MSIX_IRQ_INDEX;
939 : :
940 : : fd_ptr = (int32_t *)&irq_set->data[0];
941 [ # # ]: 0 : for (i = 0; i < irq_set->count; i++)
942 : 0 : fd_ptr[i] = -1;
943 : :
944 : 0 : vfio_dev_fd = rte_intr_dev_fd_get(intr_handle);
945 : 0 : rc = ioctl(vfio_dev_fd, VFIO_DEVICE_SET_IRQS, irq_set);
946 [ # # ]: 0 : if (rc)
947 : 0 : PMD_DRV_LOG(ERR, "Failed to set irqs vector rc=%d", rc);
948 : :
949 : : return rc;
950 : : }
951 : :
952 : : static int
953 : 0 : xsc_vfio_irq_config(struct rte_intr_handle *intr_handle, unsigned int vec)
954 : : {
955 : : char irq_set_buf[XSC_MSIX_IRQ_SET_BUF_LEN];
956 : : struct vfio_irq_set *irq_set;
957 : : int len, rc, vfio_dev_fd;
958 : : int32_t *fd_ptr;
959 : :
960 [ # # ]: 0 : if (vec > (uint32_t)rte_intr_max_intr_get(intr_handle)) {
961 : 0 : PMD_DRV_LOG(INFO, "Vector=%d greater than max_intr=%d", vec,
962 : : rte_intr_max_intr_get(intr_handle));
963 : 0 : return -EINVAL;
964 : : }
965 : :
966 : : len = sizeof(struct vfio_irq_set) + sizeof(int32_t);
967 : :
968 : : irq_set = (struct vfio_irq_set *)irq_set_buf;
969 : 0 : irq_set->argsz = len;
970 : :
971 : 0 : irq_set->start = vec;
972 : 0 : irq_set->count = 1;
973 : 0 : irq_set->flags = VFIO_IRQ_SET_DATA_EVENTFD | VFIO_IRQ_SET_ACTION_TRIGGER;
974 : 0 : irq_set->index = VFIO_PCI_MSIX_IRQ_INDEX;
975 : :
976 : : /* Use vec fd to set interrupt vectors */
977 : : fd_ptr = (int32_t *)&irq_set->data[0];
978 : 0 : fd_ptr[0] = rte_intr_efds_index_get(intr_handle, vec);
979 : :
980 : 0 : vfio_dev_fd = rte_intr_dev_fd_get(intr_handle);
981 : 0 : rc = ioctl(vfio_dev_fd, VFIO_DEVICE_SET_IRQS, irq_set);
982 [ # # ]: 0 : if (rc)
983 : 0 : PMD_DRV_LOG(INFO, "Failed to set_irqs vector=0x%x rc=%d", vec, rc);
984 : :
985 : : return rc;
986 : : }
987 : :
988 : : static int
989 : 0 : xsc_vfio_irq_register(struct rte_intr_handle *intr_handle,
990 : : rte_intr_callback_fn cb, void *data, unsigned int vec)
991 : : {
992 : : struct rte_intr_handle *tmp_handle;
993 : : uint32_t nb_efd, tmp_nb_efd;
994 : : int rc, fd;
995 : :
996 [ # # ]: 0 : if (rte_intr_max_intr_get(intr_handle) == 0) {
997 : 0 : xsc_vfio_irq_info_get(intr_handle);
998 : 0 : xsc_vfio_irq_init(intr_handle);
999 : : }
1000 : :
1001 [ # # ]: 0 : if (vec > (uint32_t)rte_intr_max_intr_get(intr_handle)) {
1002 : 0 : PMD_DRV_LOG(INFO, "Vector=%d greater than max_intr=%d", vec,
1003 : : rte_intr_max_intr_get(intr_handle));
1004 : 0 : return -EINVAL;
1005 : : }
1006 : :
1007 : : tmp_handle = intr_handle;
1008 : : /* Create new eventfd for interrupt vector */
1009 : 0 : fd = eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC);
1010 [ # # ]: 0 : if (fd == -1)
1011 : : return -ENODEV;
1012 : :
1013 [ # # ]: 0 : if (rte_intr_fd_set(tmp_handle, fd))
1014 : 0 : return errno;
1015 : :
1016 : : /* Register vector interrupt callback */
1017 : 0 : rc = rte_intr_callback_register(tmp_handle, cb, data);
1018 [ # # ]: 0 : if (rc) {
1019 : 0 : PMD_DRV_LOG(INFO, "Failed to register vector:0x%x irq callback.", vec);
1020 : 0 : return rc;
1021 : : }
1022 : :
1023 : 0 : rte_intr_efds_index_set(intr_handle, vec, fd);
1024 : 0 : nb_efd = (vec > (uint32_t)rte_intr_nb_efd_get(intr_handle)) ?
1025 [ # # ]: 0 : vec : (uint32_t)rte_intr_nb_efd_get(intr_handle);
1026 : 0 : rte_intr_nb_efd_set(intr_handle, nb_efd);
1027 : :
1028 : 0 : tmp_nb_efd = rte_intr_nb_efd_get(intr_handle) + 1;
1029 [ # # ]: 0 : if (tmp_nb_efd > (uint32_t)rte_intr_max_intr_get(intr_handle))
1030 : 0 : rte_intr_max_intr_set(intr_handle, tmp_nb_efd);
1031 : :
1032 : 0 : PMD_DRV_LOG(INFO, "Enable vector:0x%x for vfio (efds: %d, max:%d)",
1033 : : vec,
1034 : : rte_intr_nb_efd_get(intr_handle),
1035 : : rte_intr_max_intr_get(intr_handle));
1036 : :
1037 : : /* Enable MSIX vectors to VFIO */
1038 : 0 : return xsc_vfio_irq_config(intr_handle, vec);
1039 : : }
1040 : :
1041 : : static int
1042 : 0 : xsc_vfio_msix_enable(struct xsc_dev *xdev)
1043 : : {
1044 : 0 : struct xsc_cmd_msix_table_info_mbox_in in = { };
1045 : 0 : struct xsc_cmd_msix_table_info_mbox_out out = { };
1046 : : int ret;
1047 : :
1048 : 0 : in.hdr.opcode = rte_cpu_to_be_16(XSC_CMD_OP_ENABLE_MSIX);
1049 : 0 : ret = xsc_vfio_mbox_exec(xdev, &in, sizeof(in), &out, sizeof(out));
1050 [ # # # # ]: 0 : if (ret != 0 || out.hdr.status != 0) {
1051 : 0 : PMD_DRV_LOG(ERR, "Failed to enable msix, ret=%d, stats=%d",
1052 : : ret, out.hdr.status);
1053 : 0 : return ret;
1054 : : }
1055 : :
1056 : 0 : rte_write32(xdev->hwinfo.msix_base,
1057 : 0 : (uint8_t *)xdev->bar_addr + XSC_HIF_CMDQM_VECTOR_ID_MEM_ADDR);
1058 : :
1059 : 0 : return 0;
1060 : : }
1061 : :
1062 : : static int
1063 : 0 : xsc_vfio_event_get(struct xsc_dev *xdev)
1064 : : {
1065 : : int ret;
1066 : 0 : struct xsc_cmd_event_query_type_mbox_in in = { };
1067 : 0 : struct xsc_cmd_event_query_type_mbox_out out = { };
1068 : :
1069 : 0 : in.hdr.opcode = rte_cpu_to_be_16(XSC_CMD_OP_QUERY_EVENT_TYPE);
1070 : 0 : ret = xsc_vfio_mbox_exec(xdev, &in, sizeof(in), &out, sizeof(out));
1071 [ # # # # ]: 0 : if (ret != 0 || out.hdr.status != 0) {
1072 : 0 : PMD_DRV_LOG(ERR, "Failed to query event type, ret=%d, stats=%d",
1073 : : ret, out.hdr.status);
1074 : 0 : return -1;
1075 : : }
1076 : :
1077 : 0 : return out.ctx.event_type;
1078 : : }
1079 : :
1080 : : static int
1081 : 0 : xsc_vfio_intr_handler_install(struct xsc_dev *xdev, rte_intr_callback_fn cb, void *cb_arg)
1082 : : {
1083 : : int ret;
1084 : 0 : struct rte_intr_handle *intr_handle = xdev->pci_dev->intr_handle;
1085 : :
1086 : 0 : ret = xsc_vfio_irq_register(intr_handle, cb, cb_arg, XSC_VEC_CMD_EVENT);
1087 [ # # ]: 0 : if (ret != 0) {
1088 : 0 : PMD_DRV_LOG(ERR, "Failed to register vfio irq, ret=%d", ret);
1089 : 0 : return ret;
1090 : : }
1091 : :
1092 : 0 : xdev->intr_cb = cb;
1093 : 0 : xdev->intr_cb_arg = cb_arg;
1094 : :
1095 : 0 : ret = xsc_vfio_msix_enable(xdev);
1096 [ # # ]: 0 : if (ret != 0) {
1097 : 0 : PMD_DRV_LOG(ERR, "Failed to enable vfio msix, ret=%d", ret);
1098 : 0 : return ret;
1099 : : }
1100 : :
1101 : : return 0;
1102 : : }
1103 : :
1104 : : static int
1105 : 0 : xsc_vfio_intr_handler_uninstall(struct xsc_dev *xdev)
1106 : : {
1107 [ # # ]: 0 : if (rte_intr_fd_get(xdev->pci_dev->intr_handle) >= 0) {
1108 : 0 : rte_intr_disable(xdev->pci_dev->intr_handle);
1109 : 0 : rte_intr_callback_unregister_sync(xdev->pci_dev->intr_handle,
1110 : : xdev->intr_cb, xdev->intr_cb_arg);
1111 : : }
1112 : :
1113 : 0 : return 0;
1114 : : }
1115 : :
1116 : : static struct xsc_dev_ops *xsc_vfio_ops = &(struct xsc_dev_ops) {
1117 : : .kdrv = RTE_PCI_KDRV_VFIO,
1118 : : .dev_init = xsc_vfio_dev_init,
1119 : : .dev_close = xsc_vfio_dev_close,
1120 : : .set_mtu = xsc_vfio_set_mtu,
1121 : : .get_mac = xsc_vfio_get_mac,
1122 : : .link_status_set = xsc_vfio_link_status_set,
1123 : : .link_get = xsc_vfio_link_get,
1124 : : .destroy_qp = xsc_vfio_destroy_qp,
1125 : : .destroy_cq = xsc_vfio_destroy_cq,
1126 : : .modify_qp_status = xsc_vfio_modify_qp_status,
1127 : : .modify_qp_qostree = xsc_vfio_modify_qp_qostree,
1128 : : .rx_cq_create = xsc_vfio_rx_cq_create,
1129 : : .tx_cq_create = xsc_vfio_tx_cq_create,
1130 : : .tx_qp_create = xsc_vfio_tx_qp_create,
1131 : : .mailbox_exec = xsc_vfio_mbox_exec,
1132 : : .intr_event_get = xsc_vfio_event_get,
1133 : : .intr_handler_install = xsc_vfio_intr_handler_install,
1134 : : .intr_handler_uninstall = xsc_vfio_intr_handler_uninstall,
1135 : : };
1136 : :
1137 : 253 : RTE_INIT(xsc_vfio_ops_reg)
1138 : : {
1139 : 253 : xsc_dev_ops_register(xsc_vfio_ops);
1140 : 253 : }
|