LCOV - code coverage report
Current view: top level - drivers/net/xsc - xsc_dev.c (source / functions) Hit Total Coverage
Test: Code coverage Lines: 3 308 1.0 %
Date: 2025-10-01 17:51:42 Functions: 1 34 2.9 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 1 131 0.8 %

           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                 :            : void
     324                 :          0 : xsc_dev_uninit(struct xsc_dev *xdev)
     325                 :            : {
     326                 :          0 :         PMD_INIT_FUNC_TRACE();
     327                 :          0 :         xsc_dev_pct_uninit(xdev);
     328                 :          0 :         xsc_dev_close(xdev, XSC_DEV_REPR_ID_INVALID);
     329                 :          0 :         rte_free(xdev);
     330                 :          0 : }
     331                 :            : 
     332                 :            : int
     333                 :          0 : xsc_dev_init(struct rte_pci_device *pci_dev, struct xsc_dev **xdev)
     334                 :            : {
     335                 :            :         struct xsc_dev *d;
     336                 :            :         int ret;
     337                 :            : 
     338                 :          0 :         PMD_INIT_FUNC_TRACE();
     339                 :            : 
     340                 :          0 :         d = rte_zmalloc(NULL, sizeof(*d), RTE_CACHE_LINE_SIZE);
     341         [ #  # ]:          0 :         if (d == NULL) {
     342                 :          0 :                 PMD_DRV_LOG(ERR, "Failed to alloc memory for xsc_dev");
     343                 :          0 :                 return -ENOMEM;
     344                 :            :         }
     345                 :            : 
     346                 :          0 :         d->dev_ops = xsc_dev_ops_get(pci_dev->kdrv);
     347         [ #  # ]:          0 :         if (d->dev_ops == NULL) {
     348                 :          0 :                 PMD_DRV_LOG(ERR, "Could not get dev_ops, kdrv=%d", pci_dev->kdrv);
     349                 :          0 :                 return -ENODEV;
     350                 :            :         }
     351                 :            : 
     352                 :          0 :         d->pci_dev = pci_dev;
     353                 :            : 
     354         [ #  # ]:          0 :         if (d->dev_ops->dev_init)
     355                 :          0 :                 d->dev_ops->dev_init(d);
     356                 :            : 
     357                 :          0 :         xsc_dev_args_parse(d, pci_dev->device.devargs);
     358                 :            : 
     359                 :          0 :         ret = xsc_dev_alloc_vfos_info(d);
     360         [ #  # ]:          0 :         if (ret) {
     361                 :          0 :                 PMD_DRV_LOG(ERR, "Failed to alloc vfos info");
     362                 :            :                 ret = -EINVAL;
     363                 :          0 :                 goto hwinfo_init_fail;
     364                 :            :         }
     365                 :            : 
     366                 :          0 :         ret = xsc_dev_mac_port_init(d);
     367         [ #  # ]:          0 :         if (ret)
     368                 :          0 :                 goto hwinfo_init_fail;
     369                 :            : 
     370                 :          0 :         ret = xsc_dev_pct_init(d);
     371         [ #  # ]:          0 :         if (ret) {
     372                 :          0 :                 PMD_DRV_LOG(ERR, "Failed to init xsc pct");
     373                 :            :                 ret = -EINVAL;
     374                 :          0 :                 goto hwinfo_init_fail;
     375                 :            :         }
     376                 :            : 
     377                 :          0 :         *xdev = d;
     378                 :            : 
     379                 :          0 :         return 0;
     380                 :            : 
     381                 :          0 : hwinfo_init_fail:
     382                 :          0 :         xsc_dev_uninit(d);
     383                 :          0 :         return ret;
     384                 :            : }
     385                 :            : 
     386                 :            : bool
     387                 :          0 : xsc_dev_is_vf(struct xsc_dev *xdev)
     388                 :            : {
     389                 :          0 :         uint16_t device_id = xdev->pci_dev->id.device_id;
     390                 :            : 
     391                 :          0 :         if (device_id == XSC_PCI_DEV_ID_MSVF ||
     392         [ #  # ]:          0 :             device_id == XSC_PCI_DEV_ID_MVHVF)
     393                 :          0 :                 return true;
     394                 :            : 
     395                 :            :         return false;
     396                 :            : }
     397                 :            : 
     398                 :            : int
     399                 :          0 : xsc_dev_fw_version_get(struct xsc_dev *xdev, char *fw_version, size_t fw_size)
     400                 :            : {
     401                 :          0 :         size_t size = strnlen(xdev->hwinfo.fw_ver, sizeof(xdev->hwinfo.fw_ver)) + 1;
     402                 :            : 
     403         [ #  # ]:          0 :         if (fw_size < size)
     404                 :          0 :                 return size;
     405                 :            :         rte_strlcpy(fw_version, xdev->hwinfo.fw_ver, fw_size);
     406                 :            : 
     407                 :          0 :         return 0;
     408                 :            : }
     409                 :            : 
     410                 :            : static int
     411                 :          0 : xsc_dev_access_reg(struct xsc_dev *xdev, void *data_in, int size_in,
     412                 :            :                    void *data_out, int size_out, uint16_t reg_num)
     413                 :            : {
     414                 :            :         struct xsc_cmd_access_reg_mbox_in *in;
     415                 :            :         struct xsc_cmd_access_reg_mbox_out *out;
     416                 :            :         int ret = -1;
     417                 :            : 
     418                 :          0 :         in = malloc(sizeof(*in) + size_in);
     419         [ #  # ]:          0 :         if (in == NULL) {
     420                 :          0 :                 rte_errno = ENOMEM;
     421                 :          0 :                 PMD_DRV_LOG(ERR, "Failed to malloc access reg mbox in memory");
     422                 :          0 :                 return -rte_errno;
     423                 :            :         }
     424                 :            :         memset(in, 0, sizeof(*in) + size_in);
     425                 :            : 
     426                 :          0 :         out = malloc(sizeof(*out) + size_out);
     427         [ #  # ]:          0 :         if (out == NULL) {
     428                 :          0 :                 rte_errno = ENOMEM;
     429                 :          0 :                 PMD_DRV_LOG(ERR, "Failed to malloc access reg mbox out memory");
     430                 :          0 :                 goto alloc_out_fail;
     431                 :            :         }
     432                 :            :         memset(out, 0, sizeof(*out) + size_out);
     433                 :            : 
     434         [ #  # ]:          0 :         memcpy(in->data, data_in, size_in);
     435                 :          0 :         in->hdr.opcode = rte_cpu_to_be_16(XSC_CMD_OP_ACCESS_REG);
     436                 :          0 :         in->arg = 0;
     437         [ #  # ]:          0 :         in->register_id = rte_cpu_to_be_16(reg_num);
     438                 :            : 
     439                 :          0 :         ret = xsc_dev_mailbox_exec(xdev, in, sizeof(*in) + size_in, out,
     440                 :          0 :                                    sizeof(*out) + size_out);
     441   [ #  #  #  # ]:          0 :         if (ret != 0 || out->hdr.status != 0) {
     442                 :          0 :                 rte_errno = ENOEXEC;
     443                 :          0 :                 PMD_DRV_LOG(ERR, "Failed to access reg");
     444                 :          0 :                 goto exit;
     445                 :            :         }
     446                 :            : 
     447                 :          0 :         memcpy(data_out, out->data, size_out);
     448                 :            : 
     449                 :          0 : exit:
     450                 :          0 :         free(out);
     451                 :            : 
     452                 :          0 : alloc_out_fail:
     453                 :          0 :         free(in);
     454                 :          0 :         return ret;
     455                 :            : }
     456                 :            : 
     457                 :            : static int
     458                 :          0 : xsc_dev_query_mcia(struct xsc_dev *xdev,
     459                 :            :                    struct xsc_module_eeprom_query_params *params,
     460                 :            :                    uint8_t *data)
     461                 :            : {
     462                 :          0 :         struct xsc_dev_reg_mcia in = { };
     463                 :          0 :         struct xsc_dev_reg_mcia out = { };
     464                 :            :         int ret;
     465                 :            :         void *ptr;
     466                 :            :         uint16_t size;
     467                 :            : 
     468                 :          0 :         size = RTE_MIN(params->size, XSC_EEPROM_MAX_BYTES);
     469                 :          0 :         in.i2c_device_address = params->i2c_address;
     470                 :          0 :         in.module = params->module_number & 0x000000FF;
     471                 :          0 :         in.device_address = params->offset;
     472                 :          0 :         in.page_number = params->page;
     473                 :          0 :         in.size = size;
     474                 :            : 
     475                 :          0 :         ret = xsc_dev_access_reg(xdev, &in, sizeof(in), &out, sizeof(out), XSC_REG_MCIA);
     476         [ #  # ]:          0 :         if (ret != 0)
     477                 :            :                 return ret;
     478                 :            : 
     479                 :            :         ptr = out.dword_0;
     480                 :          0 :         memcpy(data, ptr, size);
     481                 :            : 
     482                 :          0 :         return size;
     483                 :            : }
     484                 :            : 
     485                 :            : static void
     486                 :            : xsc_dev_sfp_eeprom_params_set(uint16_t *i2c_addr, uint32_t *page_num, uint16_t *offset)
     487                 :            : {
     488                 :          0 :         *i2c_addr = XSC_I2C_ADDR_LOW;
     489                 :            :         *page_num = 0;
     490                 :            : 
     491         [ #  # ]:          0 :         if (*offset < XSC_EEPROM_PAGE_LENGTH)
     492                 :            :                 return;
     493                 :            : 
     494                 :          0 :         *i2c_addr = XSC_I2C_ADDR_HIGH;
     495                 :          0 :         *offset -= XSC_EEPROM_PAGE_LENGTH;
     496                 :            : }
     497                 :            : 
     498                 :            : static int
     499                 :            : xsc_dev_qsfp_eeprom_page(uint16_t offset)
     500                 :            : {
     501                 :          0 :         if (offset < XSC_EEPROM_PAGE_LENGTH)
     502                 :            :                 /* Addresses between 0-255 - page 00 */
     503                 :            :                 return 0;
     504                 :            : 
     505                 :            :         /*
     506                 :            :          * Addresses between 256 - 639 belongs to pages 01, 02 and 03
     507                 :            :          * For example, offset = 400 belongs to page 02:
     508                 :            :          * 1 + ((400 - 256)/128) = 2
     509                 :            :          */
     510                 :          0 :         return 1 + ((offset - XSC_EEPROM_PAGE_LENGTH) / XSC_EEPROM_HIGH_PAGE_LENGTH);
     511                 :            : }
     512                 :            : 
     513                 :            : static int
     514                 :            : xsc_dev_qsfp_eeprom_high_page_offset(int page_num)
     515                 :            : {
     516                 :            :         /* Page 0 always start from low page */
     517                 :            :         if (!page_num)
     518                 :            :                 return 0;
     519                 :            : 
     520                 :            :         /* High page */
     521                 :          0 :         return page_num * XSC_EEPROM_HIGH_PAGE_LENGTH;
     522                 :            : }
     523                 :            : 
     524                 :            : static void
     525                 :            : xsc_dev_qsfp_eeprom_params_set(uint16_t *i2c_addr, uint32_t *page_num, uint16_t *offset)
     526                 :            : {
     527                 :          0 :         *i2c_addr = XSC_I2C_ADDR_LOW;
     528         [ #  # ]:          0 :         *page_num = xsc_dev_qsfp_eeprom_page(*offset);
     529                 :          0 :         *offset -=  xsc_dev_qsfp_eeprom_high_page_offset(*page_num);
     530                 :          0 : }
     531                 :            : 
     532                 :            : static int
     533                 :          0 : xsc_dev_query_module_id(struct xsc_dev *xdev, uint32_t module_num, uint8_t *module_id)
     534                 :            : {
     535                 :          0 :         struct xsc_dev_reg_mcia in = { 0 };
     536                 :          0 :         struct xsc_dev_reg_mcia out = { 0 };
     537                 :            :         int ret;
     538                 :            :         uint8_t *ptr;
     539                 :            : 
     540                 :          0 :         in.i2c_device_address = XSC_I2C_ADDR_LOW;
     541                 :          0 :         in.module = module_num & 0x000000FF;
     542                 :            :         in.device_address = 0;
     543                 :            :         in.page_number = 0;
     544                 :          0 :         in.size = 1;
     545                 :            : 
     546                 :          0 :         ret = xsc_dev_access_reg(xdev, &in, sizeof(in), &out, sizeof(out), XSC_REG_MCIA);
     547         [ #  # ]:          0 :         if (ret != 0)
     548                 :            :                 return ret;
     549                 :            : 
     550                 :            :         ptr = out.dword_0;
     551                 :          0 :         *module_id = ptr[0];
     552                 :          0 :         return 0;
     553                 :            : }
     554                 :            : 
     555                 :            : int
     556                 :          0 : xsc_dev_query_module_eeprom(struct xsc_dev *xdev, uint16_t offset,
     557                 :            :                             uint16_t size, uint8_t *data)
     558                 :            : {
     559                 :          0 :         struct xsc_module_eeprom_query_params query = { 0 };
     560                 :            :         uint8_t module_id;
     561                 :            :         int ret;
     562                 :            : 
     563                 :          0 :         query.module_number = xdev->hwinfo.mac_phy_port;
     564                 :          0 :         ret = xsc_dev_query_module_id(xdev, query.module_number, &module_id);
     565         [ #  # ]:          0 :         if (ret != 0)
     566                 :            :                 return ret;
     567                 :            : 
     568      [ #  #  # ]:          0 :         switch (module_id) {
     569                 :            :         case XSC_MODULE_ID_SFP:
     570                 :            :                 xsc_dev_sfp_eeprom_params_set(&query.i2c_address, &query.page, &offset);
     571                 :            :                 break;
     572                 :            :         case XSC_MODULE_ID_QSFP:
     573                 :            :         case XSC_MODULE_ID_QSFP_PLUS:
     574                 :            :         case XSC_MODULE_ID_QSFP28:
     575                 :            :         case XSC_MODULE_ID_QSFP_DD:
     576                 :            :         case XSC_MODULE_ID_DSFP:
     577                 :            :         case XSC_MODULE_ID_QSFP_PLUS_CMIS:
     578                 :            :                 xsc_dev_qsfp_eeprom_params_set(&query.i2c_address, &query.page, &offset);
     579                 :            :                 break;
     580                 :          0 :         default:
     581                 :          0 :                 PMD_DRV_LOG(ERR, "Module ID not recognized: 0x%x", module_id);
     582                 :          0 :                 return -EINVAL;
     583                 :            :         }
     584                 :            : 
     585         [ #  # ]:          0 :         if (offset + size > XSC_EEPROM_PAGE_LENGTH)
     586                 :            :                 /* Cross pages read, read until offset 256 in low page */
     587                 :          0 :                 size = XSC_EEPROM_PAGE_LENGTH - offset;
     588                 :            : 
     589                 :          0 :         query.size = size;
     590                 :          0 :         query.offset = offset;
     591                 :            : 
     592                 :          0 :         return xsc_dev_query_mcia(xdev, &query, data);
     593                 :            : }
     594                 :            : 
     595                 :            : int
     596                 :          0 : xsc_dev_intr_event_get(struct xsc_dev *xdev)
     597                 :            : {
     598         [ #  # ]:          0 :         if (xdev->dev_ops->intr_event_get == NULL)
     599                 :            :                 return -ENOTSUP;
     600                 :            : 
     601                 :          0 :         return xdev->dev_ops->intr_event_get(xdev);
     602                 :            : }
     603                 :            : 
     604                 :            : int
     605                 :          0 : xsc_dev_intr_handler_install(struct xsc_dev *xdev, rte_intr_callback_fn cb, void *cb_arg)
     606                 :            : {
     607         [ #  # ]:          0 :         if (xdev->dev_ops->intr_handler_install == NULL)
     608                 :            :                 return -ENOTSUP;
     609                 :            : 
     610                 :          0 :         return xdev->dev_ops->intr_handler_install(xdev, cb, cb_arg);
     611                 :            : }
     612                 :            : 
     613                 :            : int
     614                 :          0 : xsc_dev_intr_handler_uninstall(struct xsc_dev *xdev)
     615                 :            : {
     616         [ #  # ]:          0 :         if (xdev->dev_ops->intr_handler_uninstall == NULL)
     617                 :            :                 return -ENOTSUP;
     618                 :            : 
     619                 :          0 :         return xdev->dev_ops->intr_handler_uninstall(xdev);
     620                 :            : }
     621                 :            : 
     622                 :            : int
     623                 :          0 : xsc_dev_fec_get(struct xsc_dev *xdev, uint32_t *fec_capa)
     624                 :            : {
     625                 :          0 :         struct xsc_cmd_query_fecparam_mbox_in in = { };
     626                 :          0 :         struct xsc_cmd_query_fecparam_mbox_out out = { };
     627                 :            :         int ret = 0, fec;
     628                 :            : 
     629                 :          0 :         in.hdr.opcode = rte_cpu_to_be_16(XSC_CMD_OP_QUERY_FEC_PARAM);
     630                 :          0 :         ret = xsc_dev_mailbox_exec(xdev, &in, sizeof(in), &out, sizeof(out));
     631   [ #  #  #  # ]:          0 :         if (ret != 0 || out.hdr.status != 0) {
     632                 :          0 :                 PMD_DRV_LOG(ERR, "Failed to get fec, ret=%d, status=%u",
     633                 :            :                             ret, out.hdr.status);
     634                 :          0 :                 rte_errno = ENOEXEC;
     635                 :          0 :                 return -rte_errno;
     636                 :            :         }
     637                 :            : 
     638         [ #  # ]:          0 :         fec = rte_be_to_cpu_32(out.active_fec);
     639      [ #  #  # ]:          0 :         switch (fec) {
     640                 :            :         case XSC_DEV_FEC_OFF:
     641                 :            :                 fec = RTE_ETH_FEC_MODE_CAPA_MASK(NOFEC);
     642                 :            :                 break;
     643                 :          0 :         case XSC_DEV_FEC_BASER:
     644                 :            :                 fec = RTE_ETH_FEC_MODE_CAPA_MASK(BASER);
     645                 :          0 :                 break;
     646                 :          0 :         case XSC_DEV_FEC_RS:
     647                 :            :                 fec = RTE_ETH_FEC_MODE_CAPA_MASK(RS);
     648                 :          0 :                 break;
     649                 :            :         default:
     650                 :            :                 fec = RTE_ETH_FEC_MODE_CAPA_MASK(NOFEC);
     651                 :            :                 break;
     652                 :            :         }
     653                 :            : 
     654                 :          0 :         *fec_capa = fec;
     655                 :            : 
     656                 :          0 :         return 0;
     657                 :            : }
     658                 :            : 
     659                 :            : int
     660                 :          0 : xsc_dev_fec_set(struct xsc_dev *xdev, uint32_t mode)
     661                 :            : {
     662                 :          0 :         struct xsc_cmd_modify_fecparam_mbox_in in = { };
     663                 :          0 :         struct xsc_cmd_modify_fecparam_mbox_out out = { };
     664                 :            :         int ret = 0;
     665                 :            : 
     666                 :          0 :         in.hdr.opcode = rte_cpu_to_be_16(XSC_CMD_OP_MODIFY_FEC_PARAM);
     667   [ #  #  #  #  :          0 :         switch (mode) {
                      # ]
     668                 :            :         case RTE_ETH_FEC_MODE_CAPA_MASK(NOFEC):
     669                 :            :                 mode = XSC_DEV_FEC_OFF;
     670                 :            :                 break;
     671                 :          0 :         case RTE_ETH_FEC_MODE_CAPA_MASK(AUTO):
     672                 :            :                 mode = XSC_DEV_FEC_AUTO;
     673                 :          0 :                 break;
     674                 :          0 :         case RTE_ETH_FEC_MODE_CAPA_MASK(BASER):
     675                 :            :                 mode = XSC_DEV_FEC_BASER;
     676                 :          0 :                 break;
     677                 :          0 :         case RTE_ETH_FEC_MODE_CAPA_MASK(RS):
     678                 :            :                 mode = XSC_DEV_FEC_RS;
     679                 :          0 :                 break;
     680                 :          0 :         default:
     681                 :          0 :                 PMD_DRV_LOG(ERR, "Failed to set fec, fec mode %u not support", mode);
     682                 :          0 :                 return 0;
     683                 :            :         }
     684                 :            : 
     685         [ #  # ]:          0 :         in.fec = rte_cpu_to_be_32(mode);
     686                 :          0 :         ret = xsc_dev_mailbox_exec(xdev, &in, sizeof(in), &out, sizeof(out));
     687   [ #  #  #  # ]:          0 :         if (ret != 0 || out.hdr.status != 0) {
     688                 :          0 :                 PMD_DRV_LOG(ERR, "Failed to set fec param, ret=%d, status=%u",
     689                 :            :                             ret, out.hdr.status);
     690                 :          0 :                 rte_errno = ENOEXEC;
     691                 :          0 :                 return -rte_errno;
     692                 :            :         }
     693                 :            : 
     694                 :            :         return 0;
     695                 :            : }
     696                 :            : 
     697                 :            : int
     698                 :          0 : xsc_dev_mac_port_init(struct xsc_dev *xdev)
     699                 :            : {
     700                 :            :         uint32_t i;
     701                 :            :         uint8_t num = 0;
     702                 :          0 :         uint32_t mac_port = xdev->hwinfo.mac_phy_port;
     703                 :          0 :         uint8_t mac_bit = xdev->hwinfo.mac_bit;
     704                 :            :         uint8_t *mac_idx = &xdev->hwinfo.mac_port_idx;
     705                 :            :         uint8_t *mac_num = &xdev->hwinfo.mac_port_num;
     706                 :            :         uint8_t bit_sz = sizeof(mac_bit) * 8;
     707                 :            : 
     708                 :          0 :         *mac_idx = 0xff;
     709         [ #  # ]:          0 :         for (i = 0; i < bit_sz; i++) {
     710         [ #  # ]:          0 :                 if (mac_bit & (1U << i)) {
     711         [ #  # ]:          0 :                         if (i == mac_port)
     712                 :          0 :                                 *mac_idx = num;
     713                 :          0 :                         num++;
     714                 :            :                 }
     715                 :            :         }
     716                 :          0 :         *mac_num = num;
     717                 :            : 
     718   [ #  #  #  # ]:          0 :         if (*mac_num == 0 || *mac_idx == 0xff) {
     719                 :          0 :                 PMD_DRV_LOG(ERR, "Failed to parse mac port %u index, mac bit 0x%x",
     720                 :            :                             mac_port, mac_bit);
     721                 :          0 :                 return -1;
     722                 :            :         }
     723                 :            : 
     724                 :          0 :         PMD_DRV_LOG(DEBUG, "Mac port num %u, mac port %u, mac index %u",
     725                 :            :                     *mac_num, mac_port, *mac_idx);
     726                 :          0 :         return 0;
     727                 :            : }

Generated by: LCOV version 1.14