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 : : #include <rte_string_fns.h>
19 : :
20 : : #include "xsc_log.h"
21 : : #include "xsc_defs.h"
22 : : #include "xsc_dev.h"
23 : : #include "xsc_cmd.h"
24 : :
25 : : #define XSC_DEV_DEF_FLOW_MODE 7
26 : :
27 : : TAILQ_HEAD(xsc_dev_ops_list, xsc_dev_ops);
28 : : static struct xsc_dev_ops_list dev_ops_list = TAILQ_HEAD_INITIALIZER(dev_ops_list);
29 : :
30 : : static const struct xsc_dev_ops *
31 : : xsc_dev_ops_get(enum rte_pci_kernel_driver kdrv)
32 : : {
33 : : const struct xsc_dev_ops *ops;
34 : :
35 [ # # ]: 0 : TAILQ_FOREACH(ops, &dev_ops_list, entry) {
36 [ # # ]: 0 : if (ops->kdrv == kdrv)
37 : : return ops;
38 : : }
39 : :
40 : : return NULL;
41 : : }
42 : :
43 : : void
44 : 253 : xsc_dev_ops_register(struct xsc_dev_ops *new_ops)
45 : : {
46 : : struct xsc_dev_ops *ops;
47 : :
48 [ - + ]: 253 : TAILQ_FOREACH(ops, &dev_ops_list, entry) {
49 [ # # ]: 0 : if (ops->kdrv == new_ops->kdrv) {
50 : 0 : PMD_DRV_LOG(ERR, "xsc dev ops exists, kdrv=%d", new_ops->kdrv);
51 : 0 : return;
52 : : }
53 : : }
54 : :
55 : 253 : TAILQ_INSERT_TAIL(&dev_ops_list, new_ops, entry);
56 : : }
57 : :
58 : : int
59 : 0 : xsc_dev_mailbox_exec(struct xsc_dev *xdev, void *data_in,
60 : : int in_len, void *data_out, int out_len)
61 : : {
62 : 0 : return xdev->dev_ops->mailbox_exec(xdev, data_in, in_len,
63 : : data_out, out_len);
64 : : }
65 : :
66 : : int
67 : 0 : xsc_dev_link_status_set(struct xsc_dev *xdev, uint16_t status)
68 : : {
69 [ # # ]: 0 : if (xdev->dev_ops->link_status_set == NULL)
70 : : return -ENOTSUP;
71 : :
72 : 0 : return xdev->dev_ops->link_status_set(xdev, status);
73 : : }
74 : :
75 : : int
76 : 0 : xsc_dev_link_get(struct xsc_dev *xdev, struct rte_eth_link *link)
77 : : {
78 [ # # ]: 0 : if (xdev->dev_ops->link_get == NULL)
79 : : return -ENOTSUP;
80 : :
81 : 0 : return xdev->dev_ops->link_get(xdev, link);
82 : : }
83 : :
84 : : int
85 : 0 : xsc_dev_set_mtu(struct xsc_dev *xdev, uint16_t mtu)
86 : : {
87 : 0 : return xdev->dev_ops->set_mtu(xdev, mtu);
88 : : }
89 : :
90 : : int
91 : 0 : xsc_dev_get_mac(struct xsc_dev *xdev, uint8_t *mac)
92 : : {
93 : 0 : return xdev->dev_ops->get_mac(xdev, mac);
94 : : }
95 : :
96 : : int
97 : 0 : xsc_dev_destroy_qp(struct xsc_dev *xdev, void *qp)
98 : : {
99 : 0 : return xdev->dev_ops->destroy_qp(qp);
100 : : }
101 : :
102 : : int
103 : 0 : xsc_dev_destroy_cq(struct xsc_dev *xdev, void *cq)
104 : : {
105 : 0 : return xdev->dev_ops->destroy_cq(cq);
106 : : }
107 : :
108 : : int
109 : 0 : xsc_dev_modify_qp_status(struct xsc_dev *xdev, uint32_t qpn, int num, int opcode)
110 : : {
111 : 0 : return xdev->dev_ops->modify_qp_status(xdev, qpn, num, opcode);
112 : : }
113 : :
114 : : int
115 : 0 : xsc_dev_modify_qp_qostree(struct xsc_dev *xdev, uint16_t qpn)
116 : : {
117 : 0 : return xdev->dev_ops->modify_qp_qostree(xdev, qpn);
118 : : }
119 : :
120 : : int
121 : 0 : xsc_dev_rx_cq_create(struct xsc_dev *xdev, struct xsc_rx_cq_params *cq_params,
122 : : struct xsc_rx_cq_info *cq_info)
123 : : {
124 : 0 : return xdev->dev_ops->rx_cq_create(xdev, cq_params, cq_info);
125 : : }
126 : :
127 : : int
128 : 0 : xsc_dev_tx_cq_create(struct xsc_dev *xdev, struct xsc_tx_cq_params *cq_params,
129 : : struct xsc_tx_cq_info *cq_info)
130 : : {
131 : 0 : return xdev->dev_ops->tx_cq_create(xdev, cq_params, cq_info);
132 : : }
133 : :
134 : : int
135 : 0 : xsc_dev_tx_qp_create(struct xsc_dev *xdev, struct xsc_tx_qp_params *qp_params,
136 : : struct xsc_tx_qp_info *qp_info)
137 : : {
138 : 0 : return xdev->dev_ops->tx_qp_create(xdev, qp_params, qp_info);
139 : : }
140 : :
141 : : int
142 : 0 : xsc_dev_close(struct xsc_dev *xdev, int repr_id)
143 : : {
144 : 0 : xsc_dev_clear_pct(xdev, repr_id);
145 : :
146 [ # # ]: 0 : if (repr_id == xdev->num_repr_ports - 1)
147 : 0 : return xdev->dev_ops->dev_close(xdev);
148 : : return 0;
149 : : }
150 : :
151 : : int
152 : 0 : xsc_dev_rss_key_modify(struct xsc_dev *xdev, uint8_t *rss_key, uint8_t rss_key_len)
153 : : {
154 : 0 : struct xsc_cmd_modify_nic_hca_mbox_in in = {};
155 : 0 : struct xsc_cmd_modify_nic_hca_mbox_out out = {};
156 : : uint8_t rss_caps_mask = 0;
157 : : int ret, key_len = 0;
158 : :
159 : 0 : in.hdr.opcode = rte_cpu_to_be_16(XSC_CMD_OP_MODIFY_NIC_HCA);
160 : :
161 : 0 : key_len = RTE_MIN(rss_key_len, XSC_RSS_HASH_KEY_LEN);
162 [ # # ]: 0 : rte_memcpy(in.rss.hash_key, rss_key, key_len);
163 : : rss_caps_mask |= RTE_BIT32(XSC_RSS_HASH_KEY_UPDATE);
164 : :
165 : 0 : in.rss.caps_mask = rss_caps_mask;
166 : 0 : in.rss.rss_en = 1;
167 : 0 : in.nic.caps_mask = rte_cpu_to_be_16(RTE_BIT32(XSC_TBM_CAP_RSS));
168 : 0 : in.nic.caps = in.nic.caps_mask;
169 : :
170 : 0 : ret = xsc_dev_mailbox_exec(xdev, &in, sizeof(in), &out, sizeof(out));
171 [ # # # # ]: 0 : if (ret != 0 || out.hdr.status != 0)
172 : 0 : return -1;
173 : : return 0;
174 : : }
175 : :
176 : : static int
177 : 0 : xsc_dev_alloc_vfos_info(struct xsc_dev *xdev)
178 : : {
179 : : struct xsc_hwinfo *hwinfo;
180 : : int base_lp = 0;
181 : :
182 [ # # ]: 0 : if (xsc_dev_is_vf(xdev))
183 : : return 0;
184 : :
185 : : hwinfo = &xdev->hwinfo;
186 [ # # ]: 0 : if (hwinfo->pcie_no == 1) {
187 : 0 : xdev->vfrep_offset = hwinfo->func_id -
188 : 0 : hwinfo->pcie1_pf_funcid_base +
189 : 0 : hwinfo->pcie0_pf_funcid_top -
190 : 0 : hwinfo->pcie0_pf_funcid_base + 1;
191 : : } else {
192 : 0 : xdev->vfrep_offset = hwinfo->func_id - hwinfo->pcie0_pf_funcid_base;
193 : : }
194 : :
195 : : base_lp = XSC_VFREP_BASE_LOGICAL_PORT;
196 [ # # ]: 0 : if (xdev->devargs.nic_mode == XSC_NIC_MODE_LEGACY)
197 : 0 : base_lp += xdev->vfrep_offset;
198 : 0 : xdev->vfos_logical_in_port = base_lp;
199 : 0 : return 0;
200 : : }
201 : :
202 : : static void
203 : 0 : xsc_dev_args_parse(struct xsc_dev *xdev, struct rte_devargs *devargs)
204 : : {
205 : : struct rte_kvargs *kvlist;
206 : : struct xsc_devargs *xdevargs = &xdev->devargs;
207 : : const char *tmp;
208 : :
209 : 0 : kvlist = rte_kvargs_parse(devargs->args, NULL);
210 [ # # ]: 0 : if (kvlist == NULL)
211 : : return;
212 : :
213 : 0 : tmp = rte_kvargs_get(kvlist, XSC_PPH_MODE_ARG);
214 [ # # ]: 0 : if (tmp != NULL)
215 : 0 : xdevargs->pph_mode = atoi(tmp);
216 : : else
217 : 0 : xdevargs->pph_mode = XSC_PPH_NONE;
218 : :
219 : 0 : tmp = rte_kvargs_get(kvlist, XSC_NIC_MODE_ARG);
220 [ # # ]: 0 : if (tmp != NULL)
221 : 0 : xdevargs->nic_mode = atoi(tmp);
222 : : else
223 : 0 : xdevargs->nic_mode = XSC_NIC_MODE_LEGACY;
224 : :
225 : 0 : tmp = rte_kvargs_get(kvlist, XSC_FLOW_MODE_ARG);
226 [ # # ]: 0 : if (tmp != NULL)
227 : 0 : xdevargs->flow_mode = atoi(tmp);
228 : : else
229 : 0 : xdevargs->flow_mode = XSC_DEV_DEF_FLOW_MODE;
230 : :
231 : 0 : rte_kvargs_free(kvlist);
232 : : }
233 : :
234 : : int
235 : 0 : xsc_dev_qp_set_id_get(struct xsc_dev *xdev, int repr_id)
236 : : {
237 [ # # ]: 0 : if (xsc_dev_is_vf(xdev))
238 : : return 0;
239 : :
240 : 0 : return (repr_id % 511 + 1);
241 : : }
242 : :
243 : : static void
244 : 0 : xsc_repr_info_init(struct xsc_dev *xdev, struct xsc_repr_info *info,
245 : : enum xsc_port_type port_type,
246 : : enum xsc_funcid_type funcid_type, int32_t repr_id)
247 : : {
248 : : int qp_set_id, logical_port;
249 : : struct xsc_hwinfo *hwinfo = &xdev->hwinfo;
250 : :
251 : 0 : info->repr_id = repr_id;
252 : 0 : info->port_type = port_type;
253 [ # # ]: 0 : if (port_type == XSC_PORT_TYPE_UPLINK_BOND) {
254 : 0 : info->pf_bond = 1;
255 : 0 : info->funcid = XSC_PHYPORT_LAG_FUNCID << 14;
256 [ # # ]: 0 : } else if (port_type == XSC_PORT_TYPE_UPLINK) {
257 : 0 : info->pf_bond = -1;
258 : 0 : info->funcid = funcid_type << 14;
259 [ # # ]: 0 : } else if (port_type == XSC_PORT_TYPE_PFVF) {
260 : 0 : info->funcid = funcid_type << 14;
261 : : }
262 : :
263 : 0 : qp_set_id = xsc_dev_qp_set_id_get(xdev, repr_id);
264 [ # # ]: 0 : if (xsc_dev_is_vf(xdev))
265 : 0 : logical_port = xdev->hwinfo.func_id +
266 : 0 : xdev->hwinfo.funcid_to_logic_port_off;
267 : : else
268 : 0 : logical_port = xdev->vfos_logical_in_port + qp_set_id - 1;
269 : :
270 : 0 : info->logical_port = logical_port;
271 : 0 : info->local_dstinfo = logical_port;
272 : 0 : info->peer_logical_port = hwinfo->mac_phy_port;
273 : 0 : info->peer_dstinfo = hwinfo->mac_phy_port;
274 : 0 : }
275 : :
276 : : int
277 : 0 : xsc_dev_repr_ports_probe(struct xsc_dev *xdev, int nb_repr_ports, int max_eth_ports)
278 : : {
279 : : int funcid_type;
280 : : struct xsc_repr_port *repr_port;
281 : : int i;
282 : :
283 : 0 : PMD_INIT_FUNC_TRACE();
284 : :
285 : 0 : xdev->num_repr_ports = nb_repr_ports + XSC_PHY_PORT_NUM;
286 [ # # ]: 0 : if (xdev->num_repr_ports > max_eth_ports) {
287 : 0 : PMD_DRV_LOG(ERR, "Repr ports num %d, should be less than max %d",
288 : : xdev->num_repr_ports, max_eth_ports);
289 : 0 : return -EINVAL;
290 : : }
291 : :
292 : 0 : xdev->repr_ports = rte_zmalloc(NULL,
293 : 0 : sizeof(struct xsc_repr_port) * xdev->num_repr_ports,
294 : : RTE_CACHE_LINE_SIZE);
295 [ # # ]: 0 : if (xdev->repr_ports == NULL) {
296 : 0 : PMD_DRV_LOG(ERR, "Failed to allocate memory for repr ports");
297 : 0 : return -ENOMEM;
298 : : }
299 : :
300 : 0 : funcid_type = (xdev->devargs.nic_mode == XSC_NIC_MODE_SWITCHDEV) ?
301 [ # # ]: 0 : XSC_VF_IOCTL_FUNCID : XSC_PHYPORT_MAC_FUNCID;
302 : :
303 : : /* PF representor use the last repr_ports */
304 : 0 : repr_port = &xdev->repr_ports[xdev->num_repr_ports - 1];
305 : 0 : xsc_repr_info_init(xdev, &repr_port->info, XSC_PORT_TYPE_UPLINK,
306 : : XSC_PHYPORT_MAC_FUNCID, xdev->num_repr_ports - 1);
307 : 0 : repr_port->info.ifindex = xdev->ifindex;
308 : 0 : repr_port->xdev = xdev;
309 : 0 : LIST_INIT(&repr_port->def_pct_list);
310 : :
311 : : /* VF representor start from 0 */
312 [ # # ]: 0 : for (i = 0; i < nb_repr_ports; i++) {
313 : 0 : repr_port = &xdev->repr_ports[i];
314 : 0 : xsc_repr_info_init(xdev, &repr_port->info,
315 : : XSC_PORT_TYPE_PFVF, funcid_type, i);
316 : 0 : repr_port->xdev = xdev;
317 : 0 : LIST_INIT(&repr_port->def_pct_list);
318 : : }
319 : :
320 : : return 0;
321 : : }
322 : :
323 : : static void
324 : 0 : xsc_dev_reg_addr_init(struct xsc_dev *xdev)
325 : : {
326 : : struct xsc_dev_reg_addr *reg = &xdev->reg_addr;
327 : 0 : uint8_t *bar_addr = xdev->bar_addr;
328 : :
329 [ # # # # ]: 0 : if (xsc_dev_is_vf(xdev) || xdev->bar_len != XSC_DEV_BAR_LEN_256M) {
330 : 0 : reg->rxq_db_addr = (uint32_t *)(bar_addr + XSC_VF_RX_DB_ADDR);
331 : 0 : reg->txq_db_addr = (uint32_t *)(bar_addr + XSC_VF_TX_DB_ADDR);
332 : 0 : reg->cq_db_addr = (uint32_t *)(bar_addr + XSC_VF_CQ_DB_ADDR);
333 : 0 : reg->cq_pi_start = XSC_VF_CQ_PID_START_ADDR;
334 : : } else {
335 : 0 : reg->rxq_db_addr = (uint32_t *)(bar_addr + XSC_PF_RX_DB_ADDR);
336 : 0 : reg->txq_db_addr = (uint32_t *)(bar_addr + XSC_PF_TX_DB_ADDR);
337 : 0 : reg->cq_db_addr = (uint32_t *)(bar_addr + XSC_PF_CQ_DB_ADDR);
338 : 0 : reg->cq_pi_start = XSC_PF_CQ_PID_START_ADDR;
339 : : }
340 : 0 : }
341 : :
342 : : void
343 : 0 : xsc_dev_uninit(struct xsc_dev *xdev)
344 : : {
345 : 0 : PMD_INIT_FUNC_TRACE();
346 : 0 : xsc_dev_pct_uninit(xdev);
347 : 0 : xsc_dev_close(xdev, XSC_DEV_REPR_ID_INVALID);
348 : 0 : rte_free(xdev);
349 : 0 : }
350 : :
351 : : int
352 : 0 : xsc_dev_init(struct rte_pci_device *pci_dev, struct xsc_dev **xdev)
353 : : {
354 : : struct xsc_dev *d;
355 : : int ret;
356 : :
357 : 0 : PMD_INIT_FUNC_TRACE();
358 : :
359 : 0 : d = rte_zmalloc(NULL, sizeof(*d), RTE_CACHE_LINE_SIZE);
360 [ # # ]: 0 : if (d == NULL) {
361 : 0 : PMD_DRV_LOG(ERR, "Failed to alloc memory for xsc_dev");
362 : 0 : return -ENOMEM;
363 : : }
364 : :
365 : 0 : d->dev_ops = xsc_dev_ops_get(pci_dev->kdrv);
366 [ # # ]: 0 : if (d->dev_ops == NULL) {
367 : 0 : PMD_DRV_LOG(ERR, "Could not get dev_ops, kdrv=%d", pci_dev->kdrv);
368 : 0 : return -ENODEV;
369 : : }
370 : :
371 : 0 : d->pci_dev = pci_dev;
372 : :
373 [ # # ]: 0 : if (d->dev_ops->dev_init)
374 : 0 : d->dev_ops->dev_init(d);
375 : :
376 : 0 : xsc_dev_reg_addr_init(d);
377 : 0 : xsc_dev_args_parse(d, pci_dev->device.devargs);
378 : :
379 : 0 : ret = xsc_dev_alloc_vfos_info(d);
380 [ # # ]: 0 : if (ret) {
381 : 0 : PMD_DRV_LOG(ERR, "Failed to alloc vfos info");
382 : : ret = -EINVAL;
383 : 0 : goto hwinfo_init_fail;
384 : : }
385 : :
386 : 0 : ret = xsc_dev_mac_port_init(d);
387 [ # # ]: 0 : if (ret)
388 : 0 : goto hwinfo_init_fail;
389 : :
390 : 0 : ret = xsc_dev_pct_init(d);
391 [ # # ]: 0 : if (ret) {
392 : 0 : PMD_DRV_LOG(ERR, "Failed to init xsc pct");
393 : : ret = -EINVAL;
394 : 0 : goto hwinfo_init_fail;
395 : : }
396 : :
397 : 0 : *xdev = d;
398 : :
399 : 0 : return 0;
400 : :
401 : 0 : hwinfo_init_fail:
402 : 0 : xsc_dev_uninit(d);
403 : 0 : return ret;
404 : : }
405 : :
406 : : bool
407 : 0 : xsc_dev_is_vf(struct xsc_dev *xdev)
408 : : {
409 : 0 : uint16_t device_id = xdev->pci_dev->id.device_id;
410 : :
411 : 0 : if (device_id == XSC_PCI_DEV_ID_MSVF ||
412 [ # # ]: 0 : device_id == XSC_PCI_DEV_ID_MVHVF)
413 : 0 : return true;
414 : :
415 : : return false;
416 : : }
417 : :
418 : : int
419 : 0 : xsc_dev_fw_version_get(struct xsc_dev *xdev, char *fw_version, size_t fw_size)
420 : : {
421 : 0 : size_t size = strnlen(xdev->hwinfo.fw_ver, sizeof(xdev->hwinfo.fw_ver)) + 1;
422 : :
423 [ # # ]: 0 : if (fw_size < size)
424 : 0 : return size;
425 : : rte_strlcpy(fw_version, xdev->hwinfo.fw_ver, fw_size);
426 : :
427 : 0 : return 0;
428 : : }
429 : :
430 : : static int
431 : 0 : xsc_dev_access_reg(struct xsc_dev *xdev, void *data_in, int size_in,
432 : : void *data_out, int size_out, uint16_t reg_num)
433 : : {
434 : : struct xsc_cmd_access_reg_mbox_in *in;
435 : : struct xsc_cmd_access_reg_mbox_out *out;
436 : : int ret = -1;
437 : :
438 : 0 : in = malloc(sizeof(*in) + size_in);
439 [ # # ]: 0 : if (in == NULL) {
440 : 0 : rte_errno = ENOMEM;
441 : 0 : PMD_DRV_LOG(ERR, "Failed to malloc access reg mbox in memory");
442 : 0 : return -rte_errno;
443 : : }
444 : : memset(in, 0, sizeof(*in) + size_in);
445 : :
446 : 0 : out = malloc(sizeof(*out) + size_out);
447 [ # # ]: 0 : if (out == NULL) {
448 : 0 : rte_errno = ENOMEM;
449 : 0 : PMD_DRV_LOG(ERR, "Failed to malloc access reg mbox out memory");
450 : 0 : goto alloc_out_fail;
451 : : }
452 : : memset(out, 0, sizeof(*out) + size_out);
453 : :
454 [ # # ]: 0 : memcpy(in->data, data_in, size_in);
455 : 0 : in->hdr.opcode = rte_cpu_to_be_16(XSC_CMD_OP_ACCESS_REG);
456 : 0 : in->arg = 0;
457 [ # # ]: 0 : in->register_id = rte_cpu_to_be_16(reg_num);
458 : :
459 : 0 : ret = xsc_dev_mailbox_exec(xdev, in, sizeof(*in) + size_in, out,
460 : 0 : sizeof(*out) + size_out);
461 [ # # # # ]: 0 : if (ret != 0 || out->hdr.status != 0) {
462 : 0 : rte_errno = ENOEXEC;
463 : 0 : PMD_DRV_LOG(ERR, "Failed to access reg");
464 : 0 : goto exit;
465 : : }
466 : :
467 : 0 : memcpy(data_out, out->data, size_out);
468 : :
469 : 0 : exit:
470 : 0 : free(out);
471 : :
472 : 0 : alloc_out_fail:
473 : 0 : free(in);
474 : 0 : return ret;
475 : : }
476 : :
477 : : static int
478 : 0 : xsc_dev_query_mcia(struct xsc_dev *xdev,
479 : : struct xsc_module_eeprom_query_params *params,
480 : : uint8_t *data)
481 : : {
482 : 0 : struct xsc_dev_reg_mcia in = { };
483 : 0 : struct xsc_dev_reg_mcia out = { };
484 : : int ret;
485 : : void *ptr;
486 : : uint16_t size;
487 : :
488 : 0 : size = RTE_MIN(params->size, XSC_EEPROM_MAX_BYTES);
489 : 0 : in.i2c_device_address = params->i2c_address;
490 : 0 : in.module = params->module_number & 0x000000FF;
491 : 0 : in.device_address = params->offset;
492 : 0 : in.page_number = params->page;
493 : 0 : in.size = size;
494 : :
495 : 0 : ret = xsc_dev_access_reg(xdev, &in, sizeof(in), &out, sizeof(out), XSC_REG_MCIA);
496 [ # # ]: 0 : if (ret != 0)
497 : : return ret;
498 : :
499 : : ptr = out.dword_0;
500 : 0 : memcpy(data, ptr, size);
501 : :
502 : 0 : return size;
503 : : }
504 : :
505 : : static void
506 : : xsc_dev_sfp_eeprom_params_set(uint16_t *i2c_addr, uint32_t *page_num, uint16_t *offset)
507 : : {
508 : 0 : *i2c_addr = XSC_I2C_ADDR_LOW;
509 : : *page_num = 0;
510 : :
511 [ # # ]: 0 : if (*offset < XSC_EEPROM_PAGE_LENGTH)
512 : : return;
513 : :
514 : 0 : *i2c_addr = XSC_I2C_ADDR_HIGH;
515 : 0 : *offset -= XSC_EEPROM_PAGE_LENGTH;
516 : : }
517 : :
518 : : static int
519 : : xsc_dev_qsfp_eeprom_page(uint16_t offset)
520 : : {
521 : 0 : if (offset < XSC_EEPROM_PAGE_LENGTH)
522 : : /* Addresses between 0-255 - page 00 */
523 : : return 0;
524 : :
525 : : /*
526 : : * Addresses between 256 - 639 belongs to pages 01, 02 and 03
527 : : * For example, offset = 400 belongs to page 02:
528 : : * 1 + ((400 - 256)/128) = 2
529 : : */
530 : 0 : return 1 + ((offset - XSC_EEPROM_PAGE_LENGTH) / XSC_EEPROM_HIGH_PAGE_LENGTH);
531 : : }
532 : :
533 : : static int
534 : : xsc_dev_qsfp_eeprom_high_page_offset(int page_num)
535 : : {
536 : : /* Page 0 always start from low page */
537 : : if (!page_num)
538 : : return 0;
539 : :
540 : : /* High page */
541 : 0 : return page_num * XSC_EEPROM_HIGH_PAGE_LENGTH;
542 : : }
543 : :
544 : : static void
545 : : xsc_dev_qsfp_eeprom_params_set(uint16_t *i2c_addr, uint32_t *page_num, uint16_t *offset)
546 : : {
547 : 0 : *i2c_addr = XSC_I2C_ADDR_LOW;
548 [ # # ]: 0 : *page_num = xsc_dev_qsfp_eeprom_page(*offset);
549 : 0 : *offset -= xsc_dev_qsfp_eeprom_high_page_offset(*page_num);
550 : 0 : }
551 : :
552 : : static int
553 : 0 : xsc_dev_query_module_id(struct xsc_dev *xdev, uint32_t module_num, uint8_t *module_id)
554 : : {
555 : 0 : struct xsc_dev_reg_mcia in = { 0 };
556 : 0 : struct xsc_dev_reg_mcia out = { 0 };
557 : : int ret;
558 : : uint8_t *ptr;
559 : :
560 : 0 : in.i2c_device_address = XSC_I2C_ADDR_LOW;
561 : 0 : in.module = module_num & 0x000000FF;
562 : : in.device_address = 0;
563 : : in.page_number = 0;
564 : 0 : in.size = 1;
565 : :
566 : 0 : ret = xsc_dev_access_reg(xdev, &in, sizeof(in), &out, sizeof(out), XSC_REG_MCIA);
567 [ # # ]: 0 : if (ret != 0)
568 : : return ret;
569 : :
570 : : ptr = out.dword_0;
571 : 0 : *module_id = ptr[0];
572 : 0 : return 0;
573 : : }
574 : :
575 : : int
576 : 0 : xsc_dev_query_module_eeprom(struct xsc_dev *xdev, uint16_t offset,
577 : : uint16_t size, uint8_t *data)
578 : : {
579 : 0 : struct xsc_module_eeprom_query_params query = { 0 };
580 : : uint8_t module_id;
581 : : int ret;
582 : :
583 : 0 : query.module_number = xdev->hwinfo.mac_phy_port;
584 : 0 : ret = xsc_dev_query_module_id(xdev, query.module_number, &module_id);
585 [ # # ]: 0 : if (ret != 0)
586 : : return ret;
587 : :
588 [ # # # ]: 0 : switch (module_id) {
589 : : case XSC_MODULE_ID_SFP:
590 : : xsc_dev_sfp_eeprom_params_set(&query.i2c_address, &query.page, &offset);
591 : : break;
592 : : case XSC_MODULE_ID_QSFP:
593 : : case XSC_MODULE_ID_QSFP_PLUS:
594 : : case XSC_MODULE_ID_QSFP28:
595 : : case XSC_MODULE_ID_QSFP_DD:
596 : : case XSC_MODULE_ID_DSFP:
597 : : case XSC_MODULE_ID_QSFP_PLUS_CMIS:
598 : : xsc_dev_qsfp_eeprom_params_set(&query.i2c_address, &query.page, &offset);
599 : : break;
600 : 0 : default:
601 : 0 : PMD_DRV_LOG(ERR, "Module ID not recognized: 0x%x", module_id);
602 : 0 : return -EINVAL;
603 : : }
604 : :
605 [ # # ]: 0 : if (offset + size > XSC_EEPROM_PAGE_LENGTH)
606 : : /* Cross pages read, read until offset 256 in low page */
607 : 0 : size = XSC_EEPROM_PAGE_LENGTH - offset;
608 : :
609 : 0 : query.size = size;
610 : 0 : query.offset = offset;
611 : :
612 : 0 : return xsc_dev_query_mcia(xdev, &query, data);
613 : : }
614 : :
615 : : int
616 : 0 : xsc_dev_intr_event_get(struct xsc_dev *xdev)
617 : : {
618 [ # # ]: 0 : if (xdev->dev_ops->intr_event_get == NULL)
619 : : return -ENOTSUP;
620 : :
621 : 0 : return xdev->dev_ops->intr_event_get(xdev);
622 : : }
623 : :
624 : : int
625 : 0 : xsc_dev_intr_handler_install(struct xsc_dev *xdev, rte_intr_callback_fn cb, void *cb_arg)
626 : : {
627 [ # # ]: 0 : if (xdev->dev_ops->intr_handler_install == NULL)
628 : : return -ENOTSUP;
629 : :
630 : 0 : return xdev->dev_ops->intr_handler_install(xdev, cb, cb_arg);
631 : : }
632 : :
633 : : int
634 : 0 : xsc_dev_intr_handler_uninstall(struct xsc_dev *xdev)
635 : : {
636 [ # # ]: 0 : if (xdev->dev_ops->intr_handler_uninstall == NULL)
637 : : return -ENOTSUP;
638 : :
639 : 0 : return xdev->dev_ops->intr_handler_uninstall(xdev);
640 : : }
641 : :
642 : : int
643 : 0 : xsc_dev_fec_get(struct xsc_dev *xdev, uint32_t *fec_capa)
644 : : {
645 : 0 : struct xsc_cmd_query_fecparam_mbox_in in = { };
646 : 0 : struct xsc_cmd_query_fecparam_mbox_out out = { };
647 : : int ret = 0, fec;
648 : :
649 : 0 : in.hdr.opcode = rte_cpu_to_be_16(XSC_CMD_OP_QUERY_FEC_PARAM);
650 : 0 : ret = xsc_dev_mailbox_exec(xdev, &in, sizeof(in), &out, sizeof(out));
651 [ # # # # ]: 0 : if (ret != 0 || out.hdr.status != 0) {
652 : 0 : PMD_DRV_LOG(ERR, "Failed to get fec, ret=%d, status=%u",
653 : : ret, out.hdr.status);
654 : 0 : rte_errno = ENOEXEC;
655 : 0 : return -rte_errno;
656 : : }
657 : :
658 [ # # ]: 0 : fec = rte_be_to_cpu_32(out.active_fec);
659 [ # # # ]: 0 : switch (fec) {
660 : : case XSC_DEV_FEC_OFF:
661 : : fec = RTE_ETH_FEC_MODE_CAPA_MASK(NOFEC);
662 : : break;
663 : 0 : case XSC_DEV_FEC_BASER:
664 : : fec = RTE_ETH_FEC_MODE_CAPA_MASK(BASER);
665 : 0 : break;
666 : 0 : case XSC_DEV_FEC_RS:
667 : : fec = RTE_ETH_FEC_MODE_CAPA_MASK(RS);
668 : 0 : break;
669 : : default:
670 : : fec = RTE_ETH_FEC_MODE_CAPA_MASK(NOFEC);
671 : : break;
672 : : }
673 : :
674 : 0 : *fec_capa = fec;
675 : :
676 : 0 : return 0;
677 : : }
678 : :
679 : : int
680 : 0 : xsc_dev_fec_set(struct xsc_dev *xdev, uint32_t mode)
681 : : {
682 : 0 : struct xsc_cmd_modify_fecparam_mbox_in in = { };
683 : 0 : struct xsc_cmd_modify_fecparam_mbox_out out = { };
684 : : int ret = 0;
685 : :
686 : 0 : in.hdr.opcode = rte_cpu_to_be_16(XSC_CMD_OP_MODIFY_FEC_PARAM);
687 [ # # # # : 0 : switch (mode) {
# ]
688 : : case RTE_ETH_FEC_MODE_CAPA_MASK(NOFEC):
689 : : mode = XSC_DEV_FEC_OFF;
690 : : break;
691 : 0 : case RTE_ETH_FEC_MODE_CAPA_MASK(AUTO):
692 : : mode = XSC_DEV_FEC_AUTO;
693 : 0 : break;
694 : 0 : case RTE_ETH_FEC_MODE_CAPA_MASK(BASER):
695 : : mode = XSC_DEV_FEC_BASER;
696 : 0 : break;
697 : 0 : case RTE_ETH_FEC_MODE_CAPA_MASK(RS):
698 : : mode = XSC_DEV_FEC_RS;
699 : 0 : break;
700 : 0 : default:
701 : 0 : PMD_DRV_LOG(ERR, "Failed to set fec, fec mode %u not support", mode);
702 : 0 : return 0;
703 : : }
704 : :
705 [ # # ]: 0 : in.fec = rte_cpu_to_be_32(mode);
706 : 0 : ret = xsc_dev_mailbox_exec(xdev, &in, sizeof(in), &out, sizeof(out));
707 [ # # # # ]: 0 : if (ret != 0 || out.hdr.status != 0) {
708 : 0 : PMD_DRV_LOG(ERR, "Failed to set fec param, ret=%d, status=%u",
709 : : ret, out.hdr.status);
710 : 0 : rte_errno = ENOEXEC;
711 : 0 : return -rte_errno;
712 : : }
713 : :
714 : : return 0;
715 : : }
716 : :
717 : : int
718 : 0 : xsc_dev_mac_port_init(struct xsc_dev *xdev)
719 : : {
720 : : uint32_t i;
721 : : uint8_t num = 0;
722 : 0 : uint32_t mac_port = xdev->hwinfo.mac_phy_port;
723 : 0 : uint8_t mac_bit = xdev->hwinfo.mac_bit;
724 : : uint8_t *mac_idx = &xdev->hwinfo.mac_port_idx;
725 : : uint8_t *mac_num = &xdev->hwinfo.mac_port_num;
726 : : uint8_t bit_sz = sizeof(mac_bit) * 8;
727 : :
728 : 0 : *mac_idx = 0xff;
729 [ # # ]: 0 : for (i = 0; i < bit_sz; i++) {
730 [ # # ]: 0 : if (mac_bit & (1U << i)) {
731 [ # # ]: 0 : if (i == mac_port)
732 : 0 : *mac_idx = num;
733 : 0 : num++;
734 : : }
735 : : }
736 : 0 : *mac_num = num;
737 : :
738 [ # # # # ]: 0 : if (*mac_num == 0 || *mac_idx == 0xff) {
739 : 0 : PMD_DRV_LOG(ERR, "Failed to parse mac port %u index, mac bit 0x%x",
740 : : mac_port, mac_bit);
741 : 0 : return -1;
742 : : }
743 : :
744 : 0 : PMD_DRV_LOG(DEBUG, "Mac port num %u, mac port %u, mac index %u",
745 : : *mac_num, mac_port, *mac_idx);
746 : 0 : return 0;
747 : : }
|