LCOV - code coverage report
Current view: top level - drivers/net/xsc - xsc_dev.c (source / functions) Hit Total Coverage
Test: Code coverage Lines: 3 321 0.9 %
Date: 2025-11-01 17:50:34 Functions: 1 35 2.9 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 1 135 0.7 %

           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                 :            : }

Generated by: LCOV version 1.14