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 : 252 : xsc_dev_ops_register(struct xsc_dev_ops *new_ops)
44 : : {
45 : : struct xsc_dev_ops *ops;
46 : :
47 [ - + ]: 252 : 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 : 252 : 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 : 0 : return xdev->dev_ops->dev_close(xdev);
154 : : }
155 : :
156 : : int
157 : 0 : xsc_dev_rss_key_modify(struct xsc_dev *xdev, uint8_t *rss_key, uint8_t rss_key_len)
158 : : {
159 : 0 : struct xsc_cmd_modify_nic_hca_mbox_in in = {};
160 : 0 : struct xsc_cmd_modify_nic_hca_mbox_out out = {};
161 : : uint8_t rss_caps_mask = 0;
162 : : int ret, key_len = 0;
163 : :
164 : 0 : in.hdr.opcode = rte_cpu_to_be_16(XSC_CMD_OP_MODIFY_NIC_HCA);
165 : :
166 : 0 : key_len = RTE_MIN(rss_key_len, XSC_RSS_HASH_KEY_LEN);
167 [ # # ]: 0 : rte_memcpy(in.rss.hash_key, rss_key, key_len);
168 : : rss_caps_mask |= RTE_BIT32(XSC_RSS_HASH_KEY_UPDATE);
169 : :
170 : 0 : in.rss.caps_mask = rss_caps_mask;
171 : 0 : in.rss.rss_en = 1;
172 : 0 : in.nic.caps_mask = rte_cpu_to_be_16(RTE_BIT32(XSC_TBM_CAP_RSS));
173 : 0 : in.nic.caps = in.nic.caps_mask;
174 : :
175 : 0 : ret = xsc_dev_mailbox_exec(xdev, &in, sizeof(in), &out, sizeof(out));
176 [ # # # # ]: 0 : if (ret != 0 || out.hdr.status != 0)
177 : 0 : return -1;
178 : : return 0;
179 : : }
180 : :
181 : : static int
182 : 0 : xsc_dev_alloc_vfos_info(struct xsc_dev *xdev)
183 : : {
184 : : struct xsc_hwinfo *hwinfo;
185 : : int base_lp = 0;
186 : :
187 [ # # ]: 0 : if (xsc_dev_is_vf(xdev))
188 : : return 0;
189 : :
190 : : hwinfo = &xdev->hwinfo;
191 [ # # ]: 0 : if (hwinfo->pcie_no == 1) {
192 : 0 : xdev->vfrep_offset = hwinfo->func_id -
193 : 0 : hwinfo->pcie1_pf_funcid_base +
194 : 0 : hwinfo->pcie0_pf_funcid_top -
195 : 0 : hwinfo->pcie0_pf_funcid_base + 1;
196 : : } else {
197 : 0 : xdev->vfrep_offset = hwinfo->func_id - hwinfo->pcie0_pf_funcid_base;
198 : : }
199 : :
200 : : base_lp = XSC_VFREP_BASE_LOGICAL_PORT;
201 [ # # ]: 0 : if (xdev->devargs.nic_mode == XSC_NIC_MODE_LEGACY)
202 : 0 : base_lp += xdev->vfrep_offset;
203 : 0 : xdev->vfos_logical_in_port = base_lp;
204 : 0 : return 0;
205 : : }
206 : :
207 : : static void
208 : 0 : xsc_dev_args_parse(struct xsc_dev *xdev, struct rte_devargs *devargs)
209 : : {
210 : : struct rte_kvargs *kvlist;
211 : : struct xsc_devargs *xdevargs = &xdev->devargs;
212 : : const char *tmp;
213 : :
214 : 0 : kvlist = rte_kvargs_parse(devargs->args, NULL);
215 [ # # ]: 0 : if (kvlist == NULL)
216 : : return;
217 : :
218 : 0 : tmp = rte_kvargs_get(kvlist, XSC_PPH_MODE_ARG);
219 [ # # ]: 0 : if (tmp != NULL)
220 : 0 : xdevargs->pph_mode = atoi(tmp);
221 : : else
222 : 0 : xdevargs->pph_mode = XSC_PPH_NONE;
223 : :
224 : 0 : tmp = rte_kvargs_get(kvlist, XSC_NIC_MODE_ARG);
225 [ # # ]: 0 : if (tmp != NULL)
226 : 0 : xdevargs->nic_mode = atoi(tmp);
227 : : else
228 : 0 : xdevargs->nic_mode = XSC_NIC_MODE_LEGACY;
229 : :
230 : 0 : tmp = rte_kvargs_get(kvlist, XSC_FLOW_MODE_ARG);
231 [ # # ]: 0 : if (tmp != NULL)
232 : 0 : xdevargs->flow_mode = atoi(tmp);
233 : : else
234 : 0 : xdevargs->flow_mode = XSC_DEV_DEF_FLOW_MODE;
235 : :
236 : 0 : rte_kvargs_free(kvlist);
237 : : }
238 : :
239 : : int
240 : 0 : xsc_dev_qp_set_id_get(struct xsc_dev *xdev, int repr_id)
241 : : {
242 [ # # ]: 0 : if (xsc_dev_is_vf(xdev))
243 : : return 0;
244 : :
245 : 0 : return (repr_id % 511 + 1);
246 : : }
247 : :
248 : : static void
249 : 0 : xsc_repr_info_init(struct xsc_dev *xdev, struct xsc_repr_info *info,
250 : : enum xsc_port_type port_type,
251 : : enum xsc_funcid_type funcid_type, int32_t repr_id)
252 : : {
253 : : int qp_set_id, logical_port;
254 : : struct xsc_hwinfo *hwinfo = &xdev->hwinfo;
255 : :
256 : 0 : info->repr_id = repr_id;
257 : 0 : info->port_type = port_type;
258 [ # # ]: 0 : if (port_type == XSC_PORT_TYPE_UPLINK_BOND) {
259 : 0 : info->pf_bond = 1;
260 : 0 : info->funcid = XSC_PHYPORT_LAG_FUNCID << 14;
261 [ # # ]: 0 : } else if (port_type == XSC_PORT_TYPE_UPLINK) {
262 : 0 : info->pf_bond = -1;
263 : 0 : info->funcid = funcid_type << 14;
264 [ # # ]: 0 : } else if (port_type == XSC_PORT_TYPE_PFVF) {
265 : 0 : info->funcid = funcid_type << 14;
266 : : }
267 : :
268 : 0 : qp_set_id = xsc_dev_qp_set_id_get(xdev, repr_id);
269 [ # # ]: 0 : if (xsc_dev_is_vf(xdev))
270 : 0 : logical_port = xdev->hwinfo.func_id +
271 : 0 : xdev->hwinfo.funcid_to_logic_port_off;
272 : : else
273 : 0 : logical_port = xdev->vfos_logical_in_port + qp_set_id - 1;
274 : :
275 : 0 : info->logical_port = logical_port;
276 : 0 : info->local_dstinfo = logical_port;
277 : 0 : info->peer_logical_port = hwinfo->mac_phy_port;
278 : 0 : info->peer_dstinfo = hwinfo->mac_phy_port;
279 : 0 : }
280 : :
281 : : int
282 : 0 : xsc_dev_repr_ports_probe(struct xsc_dev *xdev, int nb_repr_ports, int max_eth_ports)
283 : : {
284 : : int funcid_type;
285 : : struct xsc_repr_port *repr_port;
286 : : int i;
287 : :
288 : 0 : PMD_INIT_FUNC_TRACE();
289 : :
290 : 0 : xdev->num_repr_ports = nb_repr_ports + XSC_PHY_PORT_NUM;
291 [ # # ]: 0 : if (xdev->num_repr_ports > max_eth_ports) {
292 : 0 : PMD_DRV_LOG(ERR, "Repr ports num %u, should be less than max %u",
293 : : xdev->num_repr_ports, max_eth_ports);
294 : 0 : return -EINVAL;
295 : : }
296 : :
297 : 0 : xdev->repr_ports = rte_zmalloc(NULL,
298 : 0 : sizeof(struct xsc_repr_port) * xdev->num_repr_ports,
299 : : RTE_CACHE_LINE_SIZE);
300 [ # # ]: 0 : if (xdev->repr_ports == NULL) {
301 : 0 : PMD_DRV_LOG(ERR, "Failed to allocate memory for repr ports");
302 : 0 : return -ENOMEM;
303 : : }
304 : :
305 : 0 : funcid_type = (xdev->devargs.nic_mode == XSC_NIC_MODE_SWITCHDEV) ?
306 [ # # ]: 0 : XSC_VF_IOCTL_FUNCID : XSC_PHYPORT_MAC_FUNCID;
307 : :
308 : : /* PF representor use the last repr_ports */
309 : 0 : repr_port = &xdev->repr_ports[xdev->num_repr_ports - 1];
310 : 0 : xsc_repr_info_init(xdev, &repr_port->info, XSC_PORT_TYPE_UPLINK,
311 : : XSC_PHYPORT_MAC_FUNCID, xdev->num_repr_ports - 1);
312 : 0 : repr_port->info.ifindex = xdev->ifindex;
313 : 0 : repr_port->xdev = xdev;
314 : 0 : LIST_INIT(&repr_port->def_pct_list);
315 : :
316 : : /* VF representor start from 0 */
317 [ # # ]: 0 : for (i = 0; i < nb_repr_ports; i++) {
318 : 0 : repr_port = &xdev->repr_ports[i];
319 : 0 : xsc_repr_info_init(xdev, &repr_port->info,
320 : : XSC_PORT_TYPE_PFVF, funcid_type, i);
321 : 0 : repr_port->xdev = xdev;
322 : 0 : LIST_INIT(&repr_port->def_pct_list);
323 : : }
324 : :
325 : : return 0;
326 : : }
327 : :
328 : : void
329 : 0 : xsc_dev_uninit(struct xsc_dev *xdev)
330 : : {
331 : 0 : PMD_INIT_FUNC_TRACE();
332 : 0 : xsc_dev_pct_uninit();
333 : 0 : xsc_dev_close(xdev, XSC_DEV_REPR_ID_INVALID);
334 : 0 : rte_free(xdev);
335 : 0 : }
336 : :
337 : : int
338 : 0 : xsc_dev_init(struct rte_pci_device *pci_dev, struct xsc_dev **xdev)
339 : : {
340 : : struct xsc_dev *d;
341 : : int ret;
342 : :
343 : 0 : PMD_INIT_FUNC_TRACE();
344 : :
345 : 0 : d = rte_zmalloc(NULL, sizeof(*d), RTE_CACHE_LINE_SIZE);
346 [ # # ]: 0 : if (d == NULL) {
347 : 0 : PMD_DRV_LOG(ERR, "Failed to alloc memory for xsc_dev");
348 : 0 : return -ENOMEM;
349 : : }
350 : :
351 : 0 : d->dev_ops = xsc_dev_ops_get(pci_dev->kdrv);
352 [ # # ]: 0 : if (d->dev_ops == NULL) {
353 : 0 : PMD_DRV_LOG(ERR, "Could not get dev_ops, kdrv=%d", pci_dev->kdrv);
354 : 0 : return -ENODEV;
355 : : }
356 : :
357 : 0 : d->pci_dev = pci_dev;
358 : :
359 [ # # ]: 0 : if (d->dev_ops->dev_init)
360 : 0 : d->dev_ops->dev_init(d);
361 : :
362 : 0 : xsc_dev_args_parse(d, pci_dev->device.devargs);
363 : :
364 : 0 : ret = xsc_dev_alloc_vfos_info(d);
365 [ # # ]: 0 : if (ret) {
366 : 0 : PMD_DRV_LOG(ERR, "Failed to alloc vfos info");
367 : : ret = -EINVAL;
368 : 0 : goto hwinfo_init_fail;
369 : : }
370 : :
371 : 0 : ret = xsc_dev_pct_init();
372 [ # # ]: 0 : if (ret) {
373 : 0 : PMD_DRV_LOG(ERR, "Failed to init xsc pct");
374 : : ret = -EINVAL;
375 : 0 : goto hwinfo_init_fail;
376 : : }
377 : :
378 : 0 : *xdev = d;
379 : :
380 : 0 : return 0;
381 : :
382 : 0 : hwinfo_init_fail:
383 : 0 : xsc_dev_uninit(d);
384 : 0 : return ret;
385 : : }
386 : :
387 : : bool
388 : 0 : xsc_dev_is_vf(struct xsc_dev *xdev)
389 : : {
390 : 0 : uint16_t device_id = xdev->pci_dev->id.device_id;
391 : :
392 : 0 : if (device_id == XSC_PCI_DEV_ID_MSVF ||
393 [ # # ]: 0 : device_id == XSC_PCI_DEV_ID_MVHVF)
394 : 0 : return true;
395 : :
396 : : return false;
397 : : }
|