Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright 2025 Yunsilicon Technology Co., Ltd.
3 : : */
4 : :
5 : : #include <stdlib.h>
6 : : #include <unistd.h>
7 : : #include <sys/stat.h>
8 : : #include <fcntl.h>
9 : : #include <limits.h>
10 : : #include <sys/mman.h>
11 : :
12 : : #include <rte_pci.h>
13 : : #include <rte_bus_pci.h>
14 : : #include <bus_pci_driver.h>
15 : : #include <rte_kvargs.h>
16 : : #include <rte_eal_paging.h>
17 : : #include <rte_bitops.h>
18 : :
19 : : #include "xsc_log.h"
20 : : #include "xsc_defs.h"
21 : : #include "xsc_dev.h"
22 : : #include "xsc_cmd.h"
23 : :
24 : : #define XSC_DEV_DEF_FLOW_MODE 7
25 : :
26 : : TAILQ_HEAD(xsc_dev_ops_list, xsc_dev_ops);
27 : : static struct xsc_dev_ops_list dev_ops_list = TAILQ_HEAD_INITIALIZER(dev_ops_list);
28 : :
29 : : static const struct xsc_dev_ops *
30 : : xsc_dev_ops_get(enum rte_pci_kernel_driver kdrv)
31 : : {
32 : : const struct xsc_dev_ops *ops;
33 : :
34 [ # # ]: 0 : TAILQ_FOREACH(ops, &dev_ops_list, entry) {
35 [ # # ]: 0 : if (ops->kdrv == kdrv)
36 : : return ops;
37 : : }
38 : :
39 : : return NULL;
40 : : }
41 : :
42 : : void
43 : 253 : xsc_dev_ops_register(struct xsc_dev_ops *new_ops)
44 : : {
45 : : struct xsc_dev_ops *ops;
46 : :
47 [ - + ]: 253 : TAILQ_FOREACH(ops, &dev_ops_list, entry) {
48 [ # # ]: 0 : if (ops->kdrv == new_ops->kdrv) {
49 : 0 : PMD_DRV_LOG(ERR, "xsc dev ops exists, kdrv=%d", new_ops->kdrv);
50 : 0 : return;
51 : : }
52 : : }
53 : :
54 : 253 : TAILQ_INSERT_TAIL(&dev_ops_list, new_ops, entry);
55 : : }
56 : :
57 : : int
58 : 0 : xsc_dev_mailbox_exec(struct xsc_dev *xdev, void *data_in,
59 : : int in_len, void *data_out, int out_len)
60 : : {
61 : 0 : return xdev->dev_ops->mailbox_exec(xdev, data_in, in_len,
62 : : data_out, out_len);
63 : : }
64 : :
65 : : int
66 : 0 : xsc_dev_set_link_up(struct xsc_dev *xdev)
67 : : {
68 [ # # ]: 0 : if (xdev->dev_ops->set_link_up == NULL)
69 : : return -ENOTSUP;
70 : :
71 : 0 : return xdev->dev_ops->set_link_up(xdev);
72 : : }
73 : :
74 : : int
75 : 0 : xsc_dev_set_link_down(struct xsc_dev *xdev)
76 : : {
77 [ # # ]: 0 : if (xdev->dev_ops->set_link_down == NULL)
78 : : return -ENOTSUP;
79 : :
80 : 0 : return xdev->dev_ops->set_link_down(xdev);
81 : : }
82 : :
83 : : int
84 : 0 : xsc_dev_link_update(struct xsc_dev *xdev, uint8_t funcid_type, int wait_to_complete)
85 : : {
86 [ # # ]: 0 : if (xdev->dev_ops->link_update == NULL)
87 : : return -ENOTSUP;
88 : :
89 : 0 : return xdev->dev_ops->link_update(xdev, funcid_type, wait_to_complete);
90 : : }
91 : :
92 : : int
93 : 0 : xsc_dev_set_mtu(struct xsc_dev *xdev, uint16_t mtu)
94 : : {
95 : 0 : return xdev->dev_ops->set_mtu(xdev, mtu);
96 : : }
97 : :
98 : : int
99 : 0 : xsc_dev_get_mac(struct xsc_dev *xdev, uint8_t *mac)
100 : : {
101 : 0 : return xdev->dev_ops->get_mac(xdev, mac);
102 : : }
103 : :
104 : : int
105 : 0 : xsc_dev_destroy_qp(struct xsc_dev *xdev, void *qp)
106 : : {
107 : 0 : return xdev->dev_ops->destroy_qp(qp);
108 : : }
109 : :
110 : : int
111 : 0 : xsc_dev_destroy_cq(struct xsc_dev *xdev, void *cq)
112 : : {
113 : 0 : return xdev->dev_ops->destroy_cq(cq);
114 : : }
115 : :
116 : : int
117 : 0 : xsc_dev_modify_qp_status(struct xsc_dev *xdev, uint32_t qpn, int num, int opcode)
118 : : {
119 : 0 : return xdev->dev_ops->modify_qp_status(xdev, qpn, num, opcode);
120 : : }
121 : :
122 : : int
123 : 0 : xsc_dev_modify_qp_qostree(struct xsc_dev *xdev, uint16_t qpn)
124 : : {
125 : 0 : return xdev->dev_ops->modify_qp_qostree(xdev, qpn);
126 : : }
127 : :
128 : : int
129 : 0 : xsc_dev_rx_cq_create(struct xsc_dev *xdev, struct xsc_rx_cq_params *cq_params,
130 : : struct xsc_rx_cq_info *cq_info)
131 : : {
132 : 0 : return xdev->dev_ops->rx_cq_create(xdev, cq_params, cq_info);
133 : : }
134 : :
135 : : int
136 : 0 : xsc_dev_tx_cq_create(struct xsc_dev *xdev, struct xsc_tx_cq_params *cq_params,
137 : : struct xsc_tx_cq_info *cq_info)
138 : : {
139 : 0 : return xdev->dev_ops->tx_cq_create(xdev, cq_params, cq_info);
140 : : }
141 : :
142 : : int
143 : 0 : xsc_dev_tx_qp_create(struct xsc_dev *xdev, struct xsc_tx_qp_params *qp_params,
144 : : struct xsc_tx_qp_info *qp_info)
145 : : {
146 : 0 : return xdev->dev_ops->tx_qp_create(xdev, qp_params, qp_info);
147 : : }
148 : :
149 : : int
150 : 0 : xsc_dev_close(struct xsc_dev *xdev, int repr_id)
151 : : {
152 : 0 : xsc_dev_clear_pct(xdev, repr_id);
153 : :
154 [ # # ]: 0 : if (repr_id == xdev->num_repr_ports - 1)
155 : 0 : return xdev->dev_ops->dev_close(xdev);
156 : : return 0;
157 : : }
158 : :
159 : : int
160 : 0 : xsc_dev_rss_key_modify(struct xsc_dev *xdev, uint8_t *rss_key, uint8_t rss_key_len)
161 : : {
162 : 0 : struct xsc_cmd_modify_nic_hca_mbox_in in = {};
163 : 0 : struct xsc_cmd_modify_nic_hca_mbox_out out = {};
164 : : uint8_t rss_caps_mask = 0;
165 : : int ret, key_len = 0;
166 : :
167 : 0 : in.hdr.opcode = rte_cpu_to_be_16(XSC_CMD_OP_MODIFY_NIC_HCA);
168 : :
169 : 0 : key_len = RTE_MIN(rss_key_len, XSC_RSS_HASH_KEY_LEN);
170 [ # # ]: 0 : rte_memcpy(in.rss.hash_key, rss_key, key_len);
171 : : rss_caps_mask |= RTE_BIT32(XSC_RSS_HASH_KEY_UPDATE);
172 : :
173 : 0 : in.rss.caps_mask = rss_caps_mask;
174 : 0 : in.rss.rss_en = 1;
175 : 0 : in.nic.caps_mask = rte_cpu_to_be_16(RTE_BIT32(XSC_TBM_CAP_RSS));
176 : 0 : in.nic.caps = in.nic.caps_mask;
177 : :
178 : 0 : ret = xsc_dev_mailbox_exec(xdev, &in, sizeof(in), &out, sizeof(out));
179 [ # # # # ]: 0 : if (ret != 0 || out.hdr.status != 0)
180 : 0 : return -1;
181 : : return 0;
182 : : }
183 : :
184 : : static int
185 : 0 : xsc_dev_alloc_vfos_info(struct xsc_dev *xdev)
186 : : {
187 : : struct xsc_hwinfo *hwinfo;
188 : : int base_lp = 0;
189 : :
190 [ # # ]: 0 : if (xsc_dev_is_vf(xdev))
191 : : return 0;
192 : :
193 : : hwinfo = &xdev->hwinfo;
194 [ # # ]: 0 : if (hwinfo->pcie_no == 1) {
195 : 0 : xdev->vfrep_offset = hwinfo->func_id -
196 : 0 : hwinfo->pcie1_pf_funcid_base +
197 : 0 : hwinfo->pcie0_pf_funcid_top -
198 : 0 : hwinfo->pcie0_pf_funcid_base + 1;
199 : : } else {
200 : 0 : xdev->vfrep_offset = hwinfo->func_id - hwinfo->pcie0_pf_funcid_base;
201 : : }
202 : :
203 : : base_lp = XSC_VFREP_BASE_LOGICAL_PORT;
204 [ # # ]: 0 : if (xdev->devargs.nic_mode == XSC_NIC_MODE_LEGACY)
205 : 0 : base_lp += xdev->vfrep_offset;
206 : 0 : xdev->vfos_logical_in_port = base_lp;
207 : 0 : return 0;
208 : : }
209 : :
210 : : static void
211 : 0 : xsc_dev_args_parse(struct xsc_dev *xdev, struct rte_devargs *devargs)
212 : : {
213 : : struct rte_kvargs *kvlist;
214 : : struct xsc_devargs *xdevargs = &xdev->devargs;
215 : : const char *tmp;
216 : :
217 : 0 : kvlist = rte_kvargs_parse(devargs->args, NULL);
218 [ # # ]: 0 : if (kvlist == NULL)
219 : : return;
220 : :
221 : 0 : tmp = rte_kvargs_get(kvlist, XSC_PPH_MODE_ARG);
222 [ # # ]: 0 : if (tmp != NULL)
223 : 0 : xdevargs->pph_mode = atoi(tmp);
224 : : else
225 : 0 : xdevargs->pph_mode = XSC_PPH_NONE;
226 : :
227 : 0 : tmp = rte_kvargs_get(kvlist, XSC_NIC_MODE_ARG);
228 [ # # ]: 0 : if (tmp != NULL)
229 : 0 : xdevargs->nic_mode = atoi(tmp);
230 : : else
231 : 0 : xdevargs->nic_mode = XSC_NIC_MODE_LEGACY;
232 : :
233 : 0 : tmp = rte_kvargs_get(kvlist, XSC_FLOW_MODE_ARG);
234 [ # # ]: 0 : if (tmp != NULL)
235 : 0 : xdevargs->flow_mode = atoi(tmp);
236 : : else
237 : 0 : xdevargs->flow_mode = XSC_DEV_DEF_FLOW_MODE;
238 : :
239 : 0 : rte_kvargs_free(kvlist);
240 : : }
241 : :
242 : : int
243 : 0 : xsc_dev_qp_set_id_get(struct xsc_dev *xdev, int repr_id)
244 : : {
245 [ # # ]: 0 : if (xsc_dev_is_vf(xdev))
246 : : return 0;
247 : :
248 : 0 : return (repr_id % 511 + 1);
249 : : }
250 : :
251 : : static void
252 : 0 : xsc_repr_info_init(struct xsc_dev *xdev, struct xsc_repr_info *info,
253 : : enum xsc_port_type port_type,
254 : : enum xsc_funcid_type funcid_type, int32_t repr_id)
255 : : {
256 : : int qp_set_id, logical_port;
257 : : struct xsc_hwinfo *hwinfo = &xdev->hwinfo;
258 : :
259 : 0 : info->repr_id = repr_id;
260 : 0 : info->port_type = port_type;
261 [ # # ]: 0 : if (port_type == XSC_PORT_TYPE_UPLINK_BOND) {
262 : 0 : info->pf_bond = 1;
263 : 0 : info->funcid = XSC_PHYPORT_LAG_FUNCID << 14;
264 [ # # ]: 0 : } else if (port_type == XSC_PORT_TYPE_UPLINK) {
265 : 0 : info->pf_bond = -1;
266 : 0 : info->funcid = funcid_type << 14;
267 [ # # ]: 0 : } else if (port_type == XSC_PORT_TYPE_PFVF) {
268 : 0 : info->funcid = funcid_type << 14;
269 : : }
270 : :
271 : 0 : qp_set_id = xsc_dev_qp_set_id_get(xdev, repr_id);
272 [ # # ]: 0 : if (xsc_dev_is_vf(xdev))
273 : 0 : logical_port = xdev->hwinfo.func_id +
274 : 0 : xdev->hwinfo.funcid_to_logic_port_off;
275 : : else
276 : 0 : logical_port = xdev->vfos_logical_in_port + qp_set_id - 1;
277 : :
278 : 0 : info->logical_port = logical_port;
279 : 0 : info->local_dstinfo = logical_port;
280 : 0 : info->peer_logical_port = hwinfo->mac_phy_port;
281 : 0 : info->peer_dstinfo = hwinfo->mac_phy_port;
282 : 0 : }
283 : :
284 : : int
285 : 0 : xsc_dev_repr_ports_probe(struct xsc_dev *xdev, int nb_repr_ports, int max_eth_ports)
286 : : {
287 : : int funcid_type;
288 : : struct xsc_repr_port *repr_port;
289 : : int i;
290 : :
291 : 0 : PMD_INIT_FUNC_TRACE();
292 : :
293 : 0 : xdev->num_repr_ports = nb_repr_ports + XSC_PHY_PORT_NUM;
294 [ # # ]: 0 : if (xdev->num_repr_ports > max_eth_ports) {
295 : 0 : PMD_DRV_LOG(ERR, "Repr ports num %d, should be less than max %d",
296 : : xdev->num_repr_ports, max_eth_ports);
297 : 0 : return -EINVAL;
298 : : }
299 : :
300 : 0 : xdev->repr_ports = rte_zmalloc(NULL,
301 : 0 : sizeof(struct xsc_repr_port) * xdev->num_repr_ports,
302 : : RTE_CACHE_LINE_SIZE);
303 [ # # ]: 0 : if (xdev->repr_ports == NULL) {
304 : 0 : PMD_DRV_LOG(ERR, "Failed to allocate memory for repr ports");
305 : 0 : return -ENOMEM;
306 : : }
307 : :
308 : 0 : funcid_type = (xdev->devargs.nic_mode == XSC_NIC_MODE_SWITCHDEV) ?
309 [ # # ]: 0 : XSC_VF_IOCTL_FUNCID : XSC_PHYPORT_MAC_FUNCID;
310 : :
311 : : /* PF representor use the last repr_ports */
312 : 0 : repr_port = &xdev->repr_ports[xdev->num_repr_ports - 1];
313 : 0 : xsc_repr_info_init(xdev, &repr_port->info, XSC_PORT_TYPE_UPLINK,
314 : : XSC_PHYPORT_MAC_FUNCID, xdev->num_repr_ports - 1);
315 : 0 : repr_port->info.ifindex = xdev->ifindex;
316 : 0 : repr_port->xdev = xdev;
317 : 0 : LIST_INIT(&repr_port->def_pct_list);
318 : :
319 : : /* VF representor start from 0 */
320 [ # # ]: 0 : for (i = 0; i < nb_repr_ports; i++) {
321 : 0 : repr_port = &xdev->repr_ports[i];
322 : 0 : xsc_repr_info_init(xdev, &repr_port->info,
323 : : XSC_PORT_TYPE_PFVF, funcid_type, i);
324 : 0 : repr_port->xdev = xdev;
325 : 0 : LIST_INIT(&repr_port->def_pct_list);
326 : : }
327 : :
328 : : return 0;
329 : : }
330 : :
331 : : void
332 : 0 : xsc_dev_uninit(struct xsc_dev *xdev)
333 : : {
334 : 0 : PMD_INIT_FUNC_TRACE();
335 : 0 : xsc_dev_pct_uninit();
336 : 0 : xsc_dev_close(xdev, XSC_DEV_REPR_ID_INVALID);
337 : 0 : rte_free(xdev);
338 : 0 : }
339 : :
340 : : int
341 : 0 : xsc_dev_init(struct rte_pci_device *pci_dev, struct xsc_dev **xdev)
342 : : {
343 : : struct xsc_dev *d;
344 : : int ret;
345 : :
346 : 0 : PMD_INIT_FUNC_TRACE();
347 : :
348 : 0 : d = rte_zmalloc(NULL, sizeof(*d), RTE_CACHE_LINE_SIZE);
349 [ # # ]: 0 : if (d == NULL) {
350 : 0 : PMD_DRV_LOG(ERR, "Failed to alloc memory for xsc_dev");
351 : 0 : return -ENOMEM;
352 : : }
353 : :
354 : 0 : d->dev_ops = xsc_dev_ops_get(pci_dev->kdrv);
355 [ # # ]: 0 : if (d->dev_ops == NULL) {
356 : 0 : PMD_DRV_LOG(ERR, "Could not get dev_ops, kdrv=%d", pci_dev->kdrv);
357 : 0 : return -ENODEV;
358 : : }
359 : :
360 : 0 : d->pci_dev = pci_dev;
361 : :
362 [ # # ]: 0 : if (d->dev_ops->dev_init)
363 : 0 : d->dev_ops->dev_init(d);
364 : :
365 : 0 : xsc_dev_args_parse(d, pci_dev->device.devargs);
366 : :
367 : 0 : ret = xsc_dev_alloc_vfos_info(d);
368 [ # # ]: 0 : if (ret) {
369 : 0 : PMD_DRV_LOG(ERR, "Failed to alloc vfos info");
370 : : ret = -EINVAL;
371 : 0 : goto hwinfo_init_fail;
372 : : }
373 : :
374 : 0 : ret = xsc_dev_pct_init();
375 [ # # ]: 0 : if (ret) {
376 : 0 : PMD_DRV_LOG(ERR, "Failed to init xsc pct");
377 : : ret = -EINVAL;
378 : 0 : goto hwinfo_init_fail;
379 : : }
380 : :
381 : 0 : *xdev = d;
382 : :
383 : 0 : return 0;
384 : :
385 : 0 : hwinfo_init_fail:
386 : 0 : xsc_dev_uninit(d);
387 : 0 : return ret;
388 : : }
389 : :
390 : : bool
391 : 0 : xsc_dev_is_vf(struct xsc_dev *xdev)
392 : : {
393 : 0 : uint16_t device_id = xdev->pci_dev->id.device_id;
394 : :
395 : 0 : if (device_id == XSC_PCI_DEV_ID_MSVF ||
396 [ # # ]: 0 : device_id == XSC_PCI_DEV_ID_MVHVF)
397 : 0 : return true;
398 : :
399 : : return false;
400 : : }
|