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