LCOV - code coverage report
Current view: top level - drivers/common/sxe2 - sxe2_common.c (source / functions) Hit Total Coverage
Test: Code coverage Lines: 62 368 16.8 %
Date: 2026-08-01 17:54:00 Functions: 8 28 28.6 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 25 221 11.3 %

           Branch data     Line data    Source code
       1                 :            : /* SPDX-License-Identifier: BSD-3-Clause
       2                 :            :  * Copyright (C), 2025, Wuxi Stars Micro System Technologies Co., Ltd.
       3                 :            :  */
       4                 :            : 
       5                 :            : #include <rte_version.h>
       6                 :            : #include <rte_pci.h>
       7                 :            : #include <rte_dev.h>
       8                 :            : #include <rte_devargs.h>
       9                 :            : #include <rte_class.h>
      10                 :            : #include <rte_malloc.h>
      11                 :            : #include <rte_errno.h>
      12                 :            : #include <rte_fbarray.h>
      13                 :            : #include <rte_eal.h>
      14                 :            : #include <eal_private.h>
      15                 :            : #include <eal_memcfg.h>
      16                 :            : #include <bus_driver.h>
      17                 :            : #include <bus_pci_driver.h>
      18                 :            : #include <eal_export.h>
      19                 :            : #include <pthread.h>
      20                 :            : 
      21                 :            : #include "sxe2_common.h"
      22                 :            : #include "sxe2_common_log.h"
      23                 :            : #include "sxe2_ioctl_chnl_func.h"
      24                 :            : 
      25                 :            : static TAILQ_HEAD(sxe2_class_drivers, sxe2_class_driver) sxe2_class_drivers_list =
      26                 :            :                                 TAILQ_HEAD_INITIALIZER(sxe2_class_drivers_list);
      27                 :            : 
      28                 :            : static TAILQ_HEAD(sxe2_common_devices, sxe2_common_device) sxe2_common_devices_list =
      29                 :            :                                 TAILQ_HEAD_INITIALIZER(sxe2_common_devices_list);
      30                 :            : 
      31                 :            : static pthread_mutex_t sxe2_common_devices_list_lock;
      32                 :            : 
      33                 :            : static struct rte_pci_id *sxe2_common_pci_id_table;
      34                 :            : 
      35                 :            : static const struct {
      36                 :            :         const char *name;
      37                 :            :         uint32_t class_type;
      38                 :            : } sxe2_class_types[] = {
      39                 :            :         { .name = "eth", .class_type = SXE2_CLASS_TYPE_ETH },
      40                 :            :         { .name = "vdpa", .class_type = SXE2_CLASS_TYPE_VDPA },
      41                 :            : };
      42                 :            : 
      43                 :          0 : static uint32_t sxe2_class_name_to_value(const char *class_name)
      44                 :            : {
      45                 :            :         uint32_t class_type = SXE2_CLASS_TYPE_INVALID;
      46                 :            :         uint32_t i;
      47                 :            : 
      48         [ #  # ]:          0 :         for (i = 0; i < RTE_DIM(sxe2_class_types); i++) {
      49         [ #  # ]:          0 :                 if (strcmp(class_name, sxe2_class_types[i].name) == 0)
      50                 :          0 :                         class_type = sxe2_class_types[i].class_type;
      51                 :            :         }
      52                 :            : 
      53                 :          0 :         return class_type;
      54                 :            : }
      55                 :            : 
      56                 :            : static struct sxe2_common_device *sxe2_rtedev_to_cdev(struct rte_device *rte_dev)
      57                 :            : {
      58                 :            :         struct sxe2_common_device *cdev = NULL;
      59                 :            : 
      60   [ #  #  #  #  :          0 :         TAILQ_FOREACH(cdev, &sxe2_common_devices_list, next) {
             #  #  #  # ]
      61   [ #  #  #  #  :          0 :                 if (rte_dev == cdev->dev)
             #  #  #  # ]
      62                 :          0 :                         goto l_end;
      63                 :            :         }
      64                 :            : 
      65                 :            :         cdev = NULL;
      66                 :          0 : l_end:
      67                 :            :         return cdev;
      68                 :            : }
      69                 :            : 
      70                 :            : static struct sxe2_class_driver *sxe2_class_driver_get(uint32_t class_type)
      71                 :            : {
      72                 :            :         struct sxe2_class_driver *cdrv = NULL;
      73                 :            : 
      74         [ #  # ]:          0 :         TAILQ_FOREACH(cdrv, &sxe2_class_drivers_list, next) {
      75         [ #  # ]:          0 :                 if (cdrv->drv_class == class_type)
      76                 :          0 :                         goto l_end;
      77                 :            :         }
      78                 :            : 
      79                 :            :         cdrv = NULL;
      80                 :          0 : l_end:
      81                 :            :         return cdrv;
      82                 :            : }
      83                 :            : 
      84                 :          0 : static int32_t sxe2_kvargs_preprocessing(struct sxe2_dev_kvargs_info *kv_info,
      85                 :            :                         const struct rte_devargs *devargs)
      86                 :            : {
      87                 :            :         const struct rte_kvargs_pair *pair;
      88                 :            :         struct rte_kvargs *kvlist;
      89                 :            :         int32_t ret = -1;
      90                 :            :         uint32_t i;
      91                 :            : 
      92                 :          0 :         kvlist = rte_kvargs_parse(devargs->args, NULL);
      93         [ #  # ]:          0 :         if (kvlist == NULL) {
      94                 :            :                 ret = -EINVAL;
      95                 :          0 :                 goto l_end;
      96                 :            :         }
      97                 :            : 
      98         [ #  # ]:          0 :         for (i = 0; i < kvlist->count; i++) {
      99                 :            :                 pair = &kvlist->pairs[i];
     100   [ #  #  #  # ]:          0 :                 if (pair->value == NULL || *(pair->value) == '\0') {
     101                 :          0 :                         PMD_LOG_ERR(COM, "Key %s has no value.", pair->key);
     102                 :          0 :                         rte_kvargs_free(kvlist);
     103                 :            :                         ret = -EINVAL;
     104                 :          0 :                         goto l_end;
     105                 :            :                 }
     106                 :            :         }
     107                 :            : 
     108                 :          0 :         kv_info->kvlist = kvlist;
     109                 :            :         ret = 0;
     110                 :          0 :         PMD_LOG_DEBUG(COM, "kvargs %d preprocessing success.",
     111                 :            :                         kv_info->kvlist->count);
     112                 :          0 : l_end:
     113                 :          0 :         return ret;
     114                 :            : }
     115                 :            : 
     116                 :            : static void sxe2_kvargs_free(struct sxe2_dev_kvargs_info *kv_info)
     117                 :            : {
     118   [ #  #  #  # ]:          0 :         if ((kv_info != NULL) && (kv_info->kvlist != NULL)) {
     119                 :          0 :                 rte_kvargs_free(kv_info->kvlist);
     120                 :          0 :                 kv_info->kvlist = NULL;
     121                 :            :         }
     122                 :            : }
     123                 :            : 
     124                 :            : RTE_EXPORT_INTERNAL_SYMBOL(sxe2_kvargs_process)
     125                 :            : int32_t
     126                 :          0 : sxe2_kvargs_process(struct sxe2_dev_kvargs_info *kv_info,
     127                 :            :                 const char *const key_match, arg_handler_t handler, void *opaque_arg)
     128                 :            : {
     129                 :            :         const struct rte_kvargs_pair *pair;
     130                 :            :         struct rte_kvargs *kvlist;
     131                 :            :         uint32_t i;
     132                 :            :         int32_t ret = 0;
     133                 :            : 
     134   [ #  #  #  #  :          0 :         if ((kv_info == NULL) || (kv_info->kvlist == NULL) ||
                   #  # ]
     135                 :            :                         (key_match == NULL)) {
     136                 :          0 :                 PMD_LOG_ERR(COM, "Failed to process kvargs, NULL parameter.");
     137                 :            :                 ret = -EINVAL;
     138                 :          0 :                 goto l_end;
     139                 :            :         }
     140                 :            :         kvlist = kv_info->kvlist;
     141                 :            : 
     142         [ #  # ]:          0 :         for (i = 0; i < kvlist->count; i++) {
     143                 :            :                 pair = &kvlist->pairs[i];
     144         [ #  # ]:          0 :                 if (strcmp(pair->key, key_match) == 0) {
     145                 :          0 :                         ret = (*handler)(pair->key, pair->value, opaque_arg);
     146         [ #  # ]:          0 :                         if (ret)
     147                 :          0 :                                 goto l_end;
     148                 :            : 
     149                 :          0 :                         kv_info->is_used[i] = true;
     150                 :          0 :                         break;
     151                 :            :                 }
     152                 :            :         }
     153                 :            : 
     154                 :          0 : l_end:
     155                 :          0 :         return ret;
     156                 :            : }
     157                 :            : 
     158                 :          0 : static int32_t sxe2_parse_class_type(const char *key, const char *value, void *args)
     159                 :            : {
     160                 :            :         uint32_t *class_type = (uint32_t *)args;
     161                 :            :         int32_t ret = 0;
     162                 :            : 
     163                 :          0 :         *class_type = sxe2_class_name_to_value(value);
     164         [ #  # ]:          0 :         if (*class_type == SXE2_CLASS_TYPE_INVALID) {
     165                 :            :                 ret = -EINVAL;
     166                 :          0 :                 PMD_LOG_ERR(COM, "Unsupported %s type: %s", key, value);
     167                 :            :         }
     168                 :            : 
     169                 :          0 :         return ret;
     170                 :            : }
     171                 :            : 
     172                 :          0 : static int32_t sxe2_parse_driver(const char *key, const char *value, void *args)
     173                 :            : {
     174                 :            :         int32_t ret = -EINVAL;
     175                 :            : 
     176         [ #  # ]:          0 :         if (value == NULL || args == NULL) {
     177                 :            :                 ret = 0;
     178                 :          0 :                 goto l_end;
     179                 :            :         }
     180                 :            : 
     181         [ #  # ]:          0 :         if (strcmp(value, "sxe2") != 0) {
     182                 :          0 :                 PMD_LOG_ERR(COM, "%s: \"%s\" is not a valid driver.",
     183                 :            :                         key, value);
     184                 :          0 :                 goto l_end;
     185                 :            :         }
     186                 :          0 : l_end:
     187                 :          0 :         return ret;
     188                 :            : }
     189                 :            : 
     190                 :          0 : static int32_t sxe2_parse_representor(const char *key, const char *value, void *args)
     191                 :            : {
     192                 :            :         int32_t ret = 0;
     193                 :            : 
     194         [ #  # ]:          0 :         if (value == NULL || args == NULL)
     195                 :          0 :                 goto l_end;
     196                 :            : 
     197                 :          0 :         PMD_LOG_INFO(COM, "representor arg %s: \"%s\".", key, value);
     198                 :            : 
     199                 :          0 : l_end:
     200                 :          0 :         return ret;
     201                 :            : }
     202                 :          0 : static int32_t sxe2_dma_mem_map(struct sxe2_common_device *cdev,
     203                 :            :                                 const void *addr, size_t len, bool do_map)
     204                 :            : {
     205                 :            :         struct rte_memseg_list *msl;
     206                 :            :         struct rte_memseg *ms;
     207                 :            :         size_t cur_len = 0;
     208                 :            :         int32_t ret = 0;
     209                 :            : 
     210                 :          0 :         msl = rte_mem_virt2memseg_list(addr);
     211         [ #  # ]:          0 :         if (msl == NULL) {
     212                 :            :                 ret = -EINVAL;
     213                 :          0 :                 PMD_LOG_ERR(COM, "Invalid virt addr=%p.", addr);
     214                 :          0 :                 goto l_end;
     215                 :            :         }
     216                 :            : 
     217         [ #  # ]:          0 :         if ((uintptr_t)addr != RTE_ALIGN((uintptr_t)addr, msl->page_sz) ||
     218         [ #  # ]:          0 :                 (len != RTE_ALIGN(len, msl->page_sz))) {
     219                 :            :                 ret = -EINVAL;
     220                 :          0 :                 PMD_LOG_ERR(COM, "Addr=%p and len=%zu not align page size=%" PRIu64 ".",
     221                 :            :                             addr, len, msl->page_sz);
     222                 :          0 :                 goto l_end;
     223                 :            :         }
     224                 :            : 
     225                 :            :         /* memsegs are contiguous in memory */
     226                 :          0 :         ms = rte_mem_virt2memseg(addr, msl);
     227         [ #  # ]:          0 :         while (cur_len < len) {
     228                 :            :                 /* some memory segments may have invalid IOVA */
     229         [ #  # ]:          0 :                 if (ms->iova == RTE_BAD_IOVA) {
     230                 :          0 :                         PMD_LOG_WARN(COM, "Memory segment at %p has bad IOVA, skipping.",
     231                 :            :                                         ms->addr);
     232                 :          0 :                         goto next;
     233                 :            :                 }
     234         [ #  # ]:          0 :                 if (do_map)
     235                 :          0 :                         sxe2_drv_dev_dma_map(cdev, ms->addr_64,
     236                 :            :                                         ms->iova, ms->len);
     237                 :            :                 else
     238                 :          0 :                         sxe2_drv_dev_dma_unmap(cdev, ms->iova);
     239                 :            : 
     240                 :          0 : next:
     241                 :          0 :                 cur_len += ms->len;
     242                 :          0 :                 ++ms;
     243                 :            :         }
     244                 :            : 
     245                 :          0 : l_end:
     246                 :          0 :         return ret;
     247                 :            : }
     248                 :            : 
     249                 :            : RTE_EXPORT_INTERNAL_SYMBOL(sxe2_common_mem_event_cb)
     250                 :            : void
     251                 :          0 : sxe2_common_mem_event_cb(enum rte_mem_event type,
     252                 :            :                 const void *addr, size_t size, void *arg __rte_unused)
     253                 :            : {
     254                 :            :         struct sxe2_common_device *cdev = NULL;
     255                 :            : 
     256         [ #  # ]:          0 :         if (rte_eal_process_type() != RTE_PROC_PRIMARY)
     257                 :          0 :                 goto l_end;
     258                 :            : 
     259                 :          0 :         pthread_mutex_lock(&sxe2_common_devices_list_lock);
     260      [ #  #  # ]:          0 :         switch (type) {
     261                 :          0 :         case RTE_MEM_EVENT_FREE:
     262         [ #  # ]:          0 :                 TAILQ_FOREACH(cdev, &sxe2_common_devices_list, next)
     263                 :          0 :                         (void)sxe2_dma_mem_map(cdev, addr, size, 0);
     264                 :            :                 break;
     265                 :          0 :         case RTE_MEM_EVENT_ALLOC:
     266         [ #  # ]:          0 :                 TAILQ_FOREACH(cdev, &sxe2_common_devices_list, next)
     267                 :          0 :                         (void)sxe2_dma_mem_map(cdev, addr, size, 1);
     268                 :            :                 break;
     269                 :            :         default:
     270                 :            :                 break;
     271                 :            :         }
     272                 :          0 :         pthread_mutex_unlock(&sxe2_common_devices_list_lock);
     273                 :          0 : l_end:
     274                 :          0 :         return;
     275                 :            : }
     276                 :            : 
     277                 :          0 : static int32_t sxe2_memseg_walk_cb(const struct rte_memseg_list *msl,
     278                 :            :                                    const struct rte_memseg *ms, void *arg)
     279                 :            : {
     280                 :            :         struct sxe2_common_device *cdev = arg;
     281                 :            :         int32_t ret = 0;
     282                 :            : 
     283   [ #  #  #  # ]:          0 :         if (msl->external && !msl->heap)
     284                 :          0 :                 goto l_end;
     285                 :            : 
     286         [ #  # ]:          0 :         if (ms->iova == RTE_BAD_IOVA)
     287                 :          0 :                 goto l_end;
     288                 :            : 
     289                 :          0 :         ret = sxe2_drv_dev_dma_map(cdev, ms->addr_64, ms->iova, ms->len);
     290         [ #  # ]:          0 :         if (ret != 0) {
     291                 :          0 :                 PMD_LOG_ERR(COM, "Fail to memseg dma map.");
     292                 :          0 :                 goto l_end;
     293                 :            :         }
     294                 :            : 
     295                 :          0 : l_end:
     296                 :          0 :         return ret;
     297                 :            : }
     298                 :            : 
     299                 :          0 : static int32_t sxe2_common_device_setup(struct sxe2_common_device *cdev)
     300                 :            : {
     301                 :          0 :         struct rte_pci_device *pci_dev = RTE_BUS_DEVICE(cdev->dev, *pci_dev);
     302                 :            :         int32_t ret = 0;
     303                 :            : 
     304         [ #  # ]:          0 :         if (rte_eal_process_type() != RTE_PROC_PRIMARY)
     305                 :          0 :                 goto l_end;
     306                 :            : 
     307                 :          0 :         ret = sxe2_drv_dev_open(cdev, pci_dev);
     308         [ #  # ]:          0 :         if (ret != 0) {
     309                 :          0 :                 PMD_LOG_ERR(COM, "Open pmd chrdev failed, ret=%d", ret);
     310                 :          0 :                 goto l_end;
     311                 :            :         }
     312                 :            : 
     313                 :          0 :         ret = sxe2_drv_dev_handshake(cdev);
     314         [ #  # ]:          0 :         if (ret != 0) {
     315                 :          0 :                 PMD_LOG_ERR(COM, "Handshake failed, ret=%d", ret);
     316                 :          0 :                 goto l_close_dev;
     317                 :            :         }
     318                 :            : 
     319                 :          0 :         rte_mcfg_mem_read_lock();
     320                 :          0 :         ret = rte_memseg_walk_thread_unsafe(sxe2_memseg_walk_cb, cdev);
     321         [ #  # ]:          0 :         if (ret) {
     322                 :          0 :                 PMD_LOG_ERR(COM, "Fail to walk memseg, ret=%d", ret);
     323                 :          0 :                 rte_mcfg_mem_read_unlock();
     324                 :          0 :                 goto l_close_dev;
     325                 :            :         }
     326                 :          0 :         rte_mcfg_mem_read_unlock();
     327                 :            : 
     328                 :          0 :         (void)rte_mem_event_callback_register("SXE2_MEM_EVENT_CB",
     329                 :            :                         sxe2_common_mem_event_cb, NULL);
     330                 :            : 
     331                 :          0 :         goto l_end;
     332                 :            : 
     333                 :          0 : l_close_dev:
     334                 :          0 :         sxe2_drv_dev_close(cdev);
     335                 :          0 : l_end:
     336                 :          0 :         return ret;
     337                 :            : }
     338                 :            : 
     339                 :          0 : static void sxe2_common_device_cleanup(struct sxe2_common_device *cdev)
     340                 :            : {
     341         [ #  # ]:          0 :         if (rte_eal_process_type() != RTE_PROC_PRIMARY)
     342                 :            :                 return;
     343                 :            : 
     344         [ #  # ]:          0 :         if (TAILQ_EMPTY(&sxe2_common_devices_list))
     345                 :          0 :                 (void)rte_mem_event_callback_unregister("SXE2_MEM_ENVENT_CB", NULL);
     346                 :            : 
     347                 :          0 :         sxe2_drv_dev_close(cdev);
     348                 :            : }
     349                 :            : 
     350                 :          0 : static struct sxe2_common_device *sxe2_common_device_alloc(
     351                 :            :                 struct rte_device *rte_dev, uint32_t class_type)
     352                 :            : {
     353                 :            :         struct sxe2_common_device *cdev = NULL;
     354                 :            : 
     355                 :          0 :         cdev = rte_zmalloc("sxe2_common_device", sizeof(*cdev), 0);
     356         [ #  # ]:          0 :         if (cdev == NULL) {
     357                 :          0 :                 PMD_LOG_ERR(COM, "Fail to alloc sxe2 common device.");
     358                 :          0 :                 goto l_end;
     359                 :            :         }
     360                 :          0 :         cdev->dev = rte_dev;
     361                 :          0 :         cdev->class_type = class_type;
     362                 :          0 :         cdev->config.cmd_fd = SXE2_CMD_FD_INVALID;
     363                 :          0 :         cdev->config.kernel_reset = false;
     364                 :          0 :         pthread_mutex_init(&cdev->config.lock, NULL);
     365                 :            : 
     366                 :          0 :         pthread_mutex_lock(&sxe2_common_devices_list_lock);
     367                 :          0 :         TAILQ_INSERT_TAIL(&sxe2_common_devices_list, cdev, next);
     368                 :          0 :         pthread_mutex_unlock(&sxe2_common_devices_list_lock);
     369                 :            : 
     370                 :          0 : l_end:
     371                 :          0 :         return cdev;
     372                 :            : }
     373                 :            : 
     374                 :          0 : static void sxe2_common_device_free(struct sxe2_common_device *cdev)
     375                 :            : {
     376                 :            : 
     377                 :          0 :         pthread_mutex_lock(&sxe2_common_devices_list_lock);
     378         [ #  # ]:          0 :         TAILQ_REMOVE(&sxe2_common_devices_list, cdev, next);
     379                 :          0 :         pthread_mutex_unlock(&sxe2_common_devices_list_lock);
     380                 :            : 
     381                 :          0 :         rte_free(cdev);
     382                 :          0 : }
     383                 :            : 
     384                 :            : static bool sxe2_dev_is_pci(const struct rte_device *dev)
     385                 :            : {
     386                 :          0 :         return strcmp(dev->bus->name, "pci") == 0;
     387                 :            : }
     388                 :            : 
     389                 :          0 : static bool sxe2_dev_pci_id_match(const struct sxe2_class_driver *cdrv,
     390                 :            :                         const struct rte_device *dev)
     391                 :            : {
     392                 :            :         const struct rte_pci_device *pci_dev;
     393                 :            :         const struct rte_pci_id *id_table;
     394                 :            :         bool ret = false;
     395                 :            : 
     396         [ #  # ]:          0 :         if (!sxe2_dev_is_pci(dev)) {
     397                 :          0 :                 PMD_LOG_ERR(COM, "Device %s is not a PCI device", dev->name);
     398                 :          0 :                 goto l_end;
     399                 :            :         }
     400                 :            : 
     401                 :            :         pci_dev = RTE_BUS_DEVICE(dev, *pci_dev);
     402         [ #  # ]:          0 :         for (id_table = cdrv->id_table; id_table->vendor_id != 0;
     403                 :          0 :                         id_table++) {
     404                 :            : 
     405   [ #  #  #  # ]:          0 :                 if (id_table->vendor_id != pci_dev->id.vendor_id &&
     406                 :            :                                 id_table->vendor_id != RTE_PCI_ANY_ID) {
     407                 :          0 :                         continue;
     408                 :            :                 }
     409   [ #  #  #  # ]:          0 :                 if (id_table->device_id != pci_dev->id.device_id &&
     410                 :            :                                 id_table->device_id != RTE_PCI_ANY_ID) {
     411                 :          0 :                         continue;
     412                 :            :                 }
     413                 :          0 :                 if (id_table->subsystem_vendor_id !=
     414   [ #  #  #  # ]:          0 :                                 pci_dev->id.subsystem_vendor_id &&
     415                 :            :                                 id_table->subsystem_vendor_id != RTE_PCI_ANY_ID) {
     416                 :          0 :                         continue;
     417                 :            :                 }
     418                 :          0 :                 if (id_table->subsystem_device_id !=
     419   [ #  #  #  # ]:          0 :                                 pci_dev->id.subsystem_device_id &&
     420                 :            :                                 id_table->subsystem_device_id != RTE_PCI_ANY_ID) {
     421                 :            : 
     422                 :          0 :                         continue;
     423                 :            :                 }
     424   [ #  #  #  # ]:          0 :                 if (id_table->class_id != pci_dev->id.class_id &&
     425                 :            :                                 id_table->class_id != RTE_CLASS_ANY_ID) {
     426                 :          0 :                         continue;
     427                 :            :                 }
     428                 :            :                 ret = true;
     429                 :            :                 break;
     430                 :            :         }
     431                 :            : 
     432                 :          0 : l_end:
     433                 :          0 :         return ret;
     434                 :            : }
     435                 :            : 
     436                 :          0 : static int32_t sxe2_classes_driver_probe(struct sxe2_common_device *cdev,
     437                 :            :                 struct sxe2_dev_kvargs_info *kv_info, uint32_t class_type)
     438                 :            : {
     439                 :            :         struct sxe2_class_driver *cdrv = NULL;
     440                 :            :         int32_t ret = -1;
     441                 :            : 
     442                 :            :         cdrv = sxe2_class_driver_get(class_type);
     443         [ #  # ]:          0 :         if (cdrv == NULL) {
     444                 :          0 :                 PMD_LOG_ERR(COM, "Fail to get class type[%u] driver.", class_type);
     445                 :          0 :                 goto l_end;
     446                 :            :         }
     447                 :            : 
     448         [ #  # ]:          0 :         if (!sxe2_dev_pci_id_match(cdrv, cdev->dev)) {
     449                 :          0 :                 PMD_LOG_ERR(COM, "Fail to match pci id for driver:%s.", cdrv->name);
     450                 :          0 :                 goto l_end;
     451                 :            :         }
     452                 :            : 
     453                 :          0 :         ret = cdrv->probe(cdev, kv_info);
     454         [ #  # ]:          0 :         if (ret) {
     455                 :            : 
     456                 :          0 :                 PMD_LOG_DEBUG(COM, "Fail to probe driver:%s.", cdrv->name);
     457                 :          0 :                 goto l_end;
     458                 :            :         }
     459                 :            : 
     460                 :          0 :         cdev->cdrv = cdrv;
     461                 :          0 : l_end:
     462                 :          0 :         return ret;
     463                 :            : }
     464                 :            : 
     465                 :            : static int32_t sxe2_classes_driver_remove(struct sxe2_common_device *cdev)
     466                 :            : {
     467                 :          0 :         struct sxe2_class_driver *cdrv = cdev->cdrv;
     468                 :            : 
     469                 :          0 :         return cdrv->remove(cdev);
     470                 :            : }
     471                 :            : 
     472                 :          0 : static int32_t sxe2_kvargs_validate(struct sxe2_dev_kvargs_info *kv_info)
     473                 :            : {
     474                 :            :         int32_t ret = 0;
     475                 :            :         uint32_t i;
     476                 :            : 
     477         [ #  # ]:          0 :         if (rte_eal_process_type() != RTE_PROC_PRIMARY)
     478                 :          0 :                 goto l_end;
     479                 :            : 
     480         [ #  # ]:          0 :         if (kv_info == NULL)
     481                 :          0 :                 goto l_end;
     482                 :            : 
     483         [ #  # ]:          0 :         for (i = 0; i < kv_info->kvlist->count; i++) {
     484         [ #  # ]:          0 :                 if (kv_info->is_used[i] == 0) {
     485                 :          0 :                         PMD_LOG_ERR(COM, "Key \"%s\" is unsupported for the class driver.",
     486                 :            :                                         kv_info->kvlist->pairs[i].key);
     487                 :            :                         ret = -EINVAL;
     488                 :          0 :                         goto l_end;
     489                 :            :                 }
     490                 :            :         }
     491                 :            : 
     492                 :          0 : l_end:
     493                 :          0 :         return ret;
     494                 :            : }
     495                 :            : 
     496                 :          0 : static int32_t sxe2_common_pci_probe(struct rte_pci_driver *pci_drv __rte_unused,
     497                 :            :                 struct rte_pci_device *pci_dev)
     498                 :            : {
     499                 :          0 :         struct rte_device *rte_dev =  &pci_dev->device;
     500                 :            :         struct sxe2_common_device *cdev;
     501                 :            :         struct sxe2_dev_kvargs_info *kv_info_p = NULL;
     502                 :            : 
     503                 :          0 :         uint32_t class_type = SXE2_CLASS_TYPE_ETH;
     504                 :            :         int32_t ret = -1;
     505                 :            : 
     506                 :          0 :         PMD_LOG_INFO(COM, "Probe pci device: %s", pci_dev->name);
     507                 :            : 
     508                 :            :         cdev = sxe2_rtedev_to_cdev(rte_dev);
     509         [ #  # ]:          0 :         if (cdev != NULL) {
     510                 :          0 :                 PMD_LOG_ERR(COM, "Device %s already probed.", rte_dev->name);
     511                 :            :                 ret = -EBUSY;
     512                 :          0 :                 goto l_end;
     513                 :            :         }
     514                 :            : 
     515   [ #  #  #  # ]:          0 :         if ((rte_dev->devargs != NULL) && (rte_dev->devargs->args != NULL)) {
     516                 :          0 :                 kv_info_p = calloc(1, sizeof(struct sxe2_dev_kvargs_info));
     517         [ #  # ]:          0 :                 if (!kv_info_p) {
     518                 :          0 :                         PMD_LOG_ERR(COM, "Failed to allocate memory for kv_info");
     519                 :          0 :                         goto l_end;
     520                 :            :                 }
     521                 :            : 
     522                 :          0 :                 ret = sxe2_kvargs_preprocessing(kv_info_p, rte_dev->devargs);
     523         [ #  # ]:          0 :                 if (ret < 0) {
     524                 :          0 :                         PMD_LOG_ERR(COM, "Unsupported device args: %s",
     525                 :            :                                 rte_dev->devargs->args);
     526                 :          0 :                         goto l_free_kvargs;
     527                 :            :                 }
     528                 :            : 
     529                 :          0 :                 ret = sxe2_kvargs_process(kv_info_p, SXE2_DEVARGS_KEY_CLASS,
     530                 :            :                                 sxe2_parse_class_type, &class_type);
     531         [ #  # ]:          0 :                 if (ret < 0) {
     532                 :          0 :                         PMD_LOG_ERR(COM, "Unsupported sxe2 driver class: %s",
     533                 :            :                                 rte_dev->devargs->args);
     534                 :          0 :                         goto l_free_args;
     535                 :            :                 }
     536                 :            : 
     537                 :          0 :                 ret = sxe2_kvargs_process(kv_info_p, SXE2_DEVARGS_KEY_DRIVER,
     538                 :            :                                 sxe2_parse_driver, NULL);
     539         [ #  # ]:          0 :                 if (ret < 0) {
     540                 :          0 :                         PMD_LOG_ERR(COM, "Unsupported sxe2 driver name: %s",
     541                 :            :                                 rte_dev->devargs->args);
     542                 :          0 :                         goto l_free_args;
     543                 :            :                 }
     544                 :            : 
     545                 :          0 :                 ret = sxe2_kvargs_process(kv_info_p, SXE2_DEVARGS_KEY_REPR,
     546                 :            :                                 sxe2_parse_representor, NULL);
     547         [ #  # ]:          0 :                 if (ret < 0) {
     548                 :          0 :                         PMD_LOG_ERR(COM, "Unsupported sxe2 driver representor: %s",
     549                 :            :                                 rte_dev->devargs->args);
     550                 :          0 :                         goto l_free_args;
     551                 :            :                 }
     552                 :            :         }
     553                 :            : 
     554                 :          0 :         cdev = sxe2_common_device_alloc(rte_dev, class_type);
     555         [ #  # ]:          0 :         if (cdev == NULL) {
     556                 :            :                 ret = -ENOMEM;
     557                 :          0 :                 goto l_free_args;
     558                 :            :         }
     559                 :            : 
     560                 :          0 :         ret = sxe2_common_device_setup(cdev);
     561         [ #  # ]:          0 :         if (ret != 0)
     562                 :          0 :                 goto l_err_setup;
     563                 :            : 
     564                 :          0 :         ret = sxe2_classes_driver_probe(cdev, kv_info_p, class_type);
     565         [ #  # ]:          0 :         if (ret != 0)
     566                 :          0 :                 goto l_err_probe;
     567                 :            : 
     568                 :          0 :         ret = sxe2_kvargs_validate(kv_info_p);
     569         [ #  # ]:          0 :         if (ret != 0) {
     570                 :          0 :                 PMD_LOG_ERR(COM, "Device args validate failed: %s",
     571                 :            :                         rte_dev->devargs->args);
     572                 :          0 :                 goto l_err_valid;
     573                 :            :         }
     574                 :          0 :         cdev->kvargs = kv_info_p;
     575                 :            : 
     576                 :          0 :         goto l_end;
     577                 :            : l_err_valid:
     578                 :            :         (void)sxe2_classes_driver_remove(cdev);
     579                 :          0 : l_err_probe:
     580                 :          0 :         sxe2_common_device_cleanup(cdev);
     581                 :          0 : l_err_setup:
     582                 :          0 :         sxe2_common_device_free(cdev);
     583         [ #  # ]:          0 : l_free_args:
     584                 :            :         sxe2_kvargs_free(kv_info_p);
     585                 :          0 : l_free_kvargs:
     586                 :          0 :         free(kv_info_p);
     587                 :          0 : l_end:
     588                 :          0 :         return ret;
     589                 :            : }
     590                 :            : 
     591                 :          0 : static int32_t sxe2_common_pci_remove(struct rte_pci_device *pci_dev)
     592                 :            : {
     593                 :            :         struct sxe2_common_device *cdev;
     594                 :            :         int32_t ret = -1;
     595                 :            : 
     596                 :          0 :         PMD_LOG_INFO(COM, "Remove pci device: %s", pci_dev->name);
     597                 :          0 :         cdev = sxe2_rtedev_to_cdev(&pci_dev->device);
     598         [ #  # ]:          0 :         if (cdev == NULL) {
     599                 :            :                 ret = -ENODEV;
     600                 :          0 :                 PMD_LOG_ERR(COM, "Fail to get device when remove.");
     601                 :          0 :                 goto l_end;
     602                 :            :         }
     603                 :            : 
     604                 :            :         ret = sxe2_classes_driver_remove(cdev);
     605         [ #  # ]:          0 :         if (ret != 0) {
     606                 :          0 :                 PMD_LOG_ERR(COM, "Fail to remove device: %s", pci_dev->name);
     607                 :          0 :                 goto l_end;
     608                 :            :         }
     609                 :            : 
     610                 :          0 :         sxe2_common_device_cleanup(cdev);
     611                 :            : 
     612         [ #  # ]:          0 :         if (cdev->kvargs != NULL) {
     613                 :            :                 sxe2_kvargs_free(cdev->kvargs);
     614                 :          0 :                 free(cdev->kvargs);
     615                 :          0 :                 cdev->kvargs = NULL;
     616                 :            :         }
     617                 :            : 
     618                 :          0 :         sxe2_common_device_free(cdev);
     619                 :            : 
     620                 :          0 : l_end:
     621                 :          0 :         return ret;
     622                 :            : }
     623                 :            : 
     624                 :          0 : static int32_t sxe2_common_pci_dma_map(struct rte_pci_device *pci_dev,
     625                 :            :                 void *addr,     uint64_t iova, size_t len)
     626                 :            : {
     627                 :            :         struct sxe2_common_device *cdev;
     628                 :            :         int32_t ret = -1;
     629                 :            : 
     630                 :          0 :         cdev = sxe2_rtedev_to_cdev(&pci_dev->device);
     631         [ #  # ]:          0 :         if (cdev == NULL) {
     632                 :            :                 ret = -ENODEV;
     633                 :          0 :                 PMD_LOG_ERR(COM, "Fail to get device when dma map.");
     634                 :          0 :                 goto l_end;
     635                 :            :         }
     636                 :            : 
     637                 :          0 :         ret = sxe2_drv_dev_dma_map(cdev, (uint64_t)(uintptr_t)addr, iova, len);
     638         [ #  # ]:          0 :         if (ret) {
     639                 :          0 :                 PMD_LOG_ERR(COM, "Fail to map dma map, ret=%d", ret);
     640                 :          0 :                 goto l_end;
     641                 :            :         }
     642                 :            : 
     643                 :          0 : l_end:
     644                 :          0 :         return ret;
     645                 :            : }
     646                 :            : 
     647                 :          0 : static int32_t sxe2_common_pci_dma_unmap(struct rte_pci_device *pci_dev,
     648                 :            :                 void *addr __rte_unused, uint64_t iova, size_t len __rte_unused)
     649                 :            : {
     650                 :            :         struct sxe2_common_device *cdev;
     651                 :            :         int32_t ret = -1;
     652                 :            : 
     653                 :          0 :         cdev = sxe2_rtedev_to_cdev(&pci_dev->device);
     654         [ #  # ]:          0 :         if (cdev == NULL) {
     655                 :            :                 ret = -ENODEV;
     656                 :          0 :                 PMD_LOG_ERR(COM, "Fail to get device when dma unmap.");
     657                 :          0 :                 goto l_end;
     658                 :            :         }
     659                 :            : 
     660                 :          0 :         ret = sxe2_drv_dev_dma_unmap(cdev, iova);
     661         [ #  # ]:          0 :         if (ret) {
     662                 :          0 :                 PMD_LOG_ERR(COM, "Fail to unmap dma map, ret=%d", ret);
     663                 :          0 :                 goto l_end;
     664                 :            :         }
     665                 :            : 
     666                 :          0 : l_end:
     667                 :          0 :         return ret;
     668                 :            : }
     669                 :            : 
     670                 :            : static struct rte_pci_driver sxe2_common_pci_driver = {
     671                 :            :         .driver = {
     672                 :            :                    .name = SXE2_COMMON_PCI_DRIVER_NAME,
     673                 :            :         },
     674                 :            :         .probe = sxe2_common_pci_probe,
     675                 :            :         .remove = sxe2_common_pci_remove,
     676                 :            :         .dma_map = sxe2_common_pci_dma_map,
     677                 :            :         .dma_unmap = sxe2_common_pci_dma_unmap,
     678                 :            : };
     679                 :            : 
     680                 :            : static uint32_t sxe2_common_pci_id_table_size_get(const struct rte_pci_id *id_table)
     681                 :            : {
     682                 :            :         uint32_t table_size = 0;
     683                 :            : 
     684   [ -  +  +  + ]:       3030 :         while (id_table->vendor_id != 0) {
     685                 :       2424 :                 table_size++;
     686                 :       2424 :                 id_table++;
     687                 :            :         }
     688                 :            : 
     689                 :            :         return table_size;
     690                 :            : }
     691                 :            : 
     692                 :            : static bool sxe2_common_pci_id_exists(const struct rte_pci_id *id,
     693                 :            :                 const struct rte_pci_id *id_table, uint32_t next_idx)
     694                 :            : {
     695                 :       2424 :         int32_t current_size = next_idx - 1;
     696                 :            :         int32_t i;
     697                 :            :         bool exists = false;
     698                 :            : 
     699         [ +  + ]:       8787 :         for (i = 0; i < current_size; i++) {
     700         [ -  + ]:       6363 :                 if ((id->device_id == id_table[i].device_id) &&
     701                 :            :                                 (id->vendor_id == id_table[i].vendor_id) &&
     702         [ #  # ]:          0 :                                 (id->subsystem_vendor_id == id_table[i].subsystem_vendor_id) &&
     703                 :            :                                 (id->subsystem_device_id == id_table[i].subsystem_device_id)) {
     704                 :            :                         exists = true;
     705                 :            :                         break;
     706                 :            :                 }
     707                 :            :         }
     708                 :            : 
     709                 :            :         return exists;
     710                 :            : }
     711                 :            : 
     712                 :        303 : static void sxe2_common_pci_id_insert(struct rte_pci_id *id_table,
     713                 :            :                 uint32_t *next_idx, const struct rte_pci_id *insert_table)
     714                 :            : {
     715         [ +  + ]:       2727 :         for (; insert_table->vendor_id != 0; insert_table++) {
     716         [ +  - ]:       4848 :                 if (!sxe2_common_pci_id_exists(insert_table, id_table, *next_idx)) {
     717                 :            : 
     718                 :       2424 :                         id_table[*next_idx] = *insert_table;
     719                 :       2424 :                         (*next_idx)++;
     720                 :            :                 }
     721                 :            :         }
     722                 :        303 : }
     723                 :            : 
     724                 :        606 : static int32_t sxe2_common_pci_id_table_update(const struct rte_pci_id *id_table)
     725                 :            : {
     726                 :            :         const struct rte_pci_id *id_iter;
     727                 :            :         struct rte_pci_id *updated_table;
     728                 :            :         struct rte_pci_id *old_table;
     729                 :            :         uint32_t num_ids = 0;
     730                 :        606 :         uint32_t i = 0;
     731                 :            :         int32_t ret = 0;
     732                 :            : 
     733                 :        606 :         old_table = sxe2_common_pci_id_table;
     734         [ +  + ]:        606 :         if (old_table)
     735                 :            :                 num_ids = sxe2_common_pci_id_table_size_get(old_table);
     736                 :            : 
     737                 :        606 :         num_ids += sxe2_common_pci_id_table_size_get(id_table);
     738                 :            : 
     739                 :        606 :         num_ids += 1;
     740                 :            : 
     741                 :        606 :         updated_table = calloc(num_ids, sizeof(*updated_table));
     742         [ -  + ]:        606 :         if (!updated_table) {
     743                 :            :                 ret = -ENOMEM;
     744                 :          0 :                 PMD_LOG_ERR(COM, "Failed to allocate memory for PCI ID table");
     745                 :          0 :                 goto l_end;
     746                 :            :         }
     747                 :            : 
     748         [ +  + ]:        606 :         if (old_table == NULL) {
     749                 :            : 
     750         [ -  + ]:        303 :                 for (id_iter = id_table; id_iter->vendor_id != 0;
     751                 :          0 :                                 id_iter++, i++)
     752                 :          0 :                         updated_table[i] = *id_iter;
     753                 :            :         } else {
     754                 :            : 
     755         [ -  + ]:        303 :                 for (id_iter = old_table; id_iter->vendor_id != 0;
     756                 :          0 :                                 id_iter++, i++)
     757                 :          0 :                         updated_table[i] = *id_iter;
     758                 :            : 
     759                 :        303 :                 sxe2_common_pci_id_insert(updated_table, &i, id_table);
     760                 :            :         }
     761                 :            : 
     762                 :        606 :         updated_table[i].vendor_id = 0;
     763                 :        606 :         sxe2_common_pci_driver.id_table = updated_table;
     764                 :        606 :         sxe2_common_pci_id_table = updated_table;
     765                 :        606 :         free(old_table);
     766                 :            : 
     767                 :        606 : l_end:
     768                 :        606 :         return ret;
     769                 :            : }
     770                 :            : 
     771                 :        303 : static void sxe2_common_driver_on_register_pci(struct sxe2_class_driver *driver)
     772                 :            : {
     773         [ +  - ]:        303 :         if (driver->id_table != NULL) {
     774         [ +  - ]:        303 :                 if (sxe2_common_pci_id_table_update(driver->id_table) != 0)
     775                 :            :                         return;
     776                 :            :         }
     777                 :            : 
     778         [ +  - ]:        303 :         if (driver->intr_lsc)
     779                 :        303 :                 sxe2_common_pci_driver.drv_flags |= RTE_PCI_DRV_INTR_LSC;
     780         [ +  - ]:        303 :         if (driver->intr_rmv)
     781                 :        303 :                 sxe2_common_pci_driver.drv_flags |= RTE_PCI_DRV_INTR_RMV;
     782                 :            : }
     783                 :            : 
     784                 :            : RTE_EXPORT_INTERNAL_SYMBOL(sxe2_class_driver_register)
     785                 :            : void
     786                 :        303 : sxe2_class_driver_register(struct sxe2_class_driver *driver)
     787                 :            : {
     788                 :        303 :         sxe2_common_driver_on_register_pci(driver);
     789                 :        303 :         TAILQ_INSERT_TAIL(&sxe2_class_drivers_list, driver, next);
     790                 :        303 : }
     791                 :            : 
     792                 :        303 : static void sxe2_common_pci_init(void)
     793                 :            : {
     794                 :        303 :         const struct rte_pci_id empty_table[] = {
     795                 :            :                 {
     796                 :            :                         .vendor_id = 0
     797                 :            :                 },
     798                 :            :         };
     799                 :            :         int32_t ret = -1;
     800                 :            : 
     801         [ +  - ]:        303 :         if (sxe2_common_pci_id_table == NULL) {
     802                 :        303 :                 ret = sxe2_common_pci_id_table_update(empty_table);
     803         [ -  + ]:        303 :                 if (ret != 0)
     804                 :          0 :                         goto l_end;
     805                 :            :         }
     806                 :        303 :         rte_pci_register(&sxe2_common_pci_driver);
     807                 :            : 
     808                 :        303 : l_end:
     809                 :        303 :         return;
     810                 :            : }
     811                 :            : 
     812                 :            : static bool sxe2_common_inited;
     813                 :            : 
     814                 :            : RTE_EXPORT_INTERNAL_SYMBOL(sxe2_common_init)
     815                 :            : void
     816                 :        303 : sxe2_common_init(void)
     817                 :            : {
     818         [ -  + ]:        303 :         if (sxe2_common_inited)
     819                 :          0 :                 goto l_end;
     820                 :            : 
     821                 :        303 :         pthread_mutex_init(&sxe2_common_devices_list_lock, NULL);
     822                 :        303 :         sxe2_common_pci_init();
     823                 :        303 :         sxe2_common_inited = true;
     824                 :            : 
     825                 :        303 : l_end:
     826                 :        303 :         return;
     827                 :            : }
     828                 :            : 
     829                 :        303 : RTE_FINI(sxe2_common_pci_finish)
     830                 :            : {
     831         [ +  - ]:        303 :         if (sxe2_common_pci_id_table != NULL) {
     832                 :        303 :                 rte_pci_unregister(&sxe2_common_pci_driver);
     833                 :        303 :                 free(sxe2_common_pci_id_table);
     834                 :            :         }
     835                 :        303 : }
     836                 :            : 
     837                 :            : RTE_PMD_EXPORT_NAME(sxe2_common_pci);
     838                 :            : 
     839         [ -  + ]:        303 : RTE_LOG_REGISTER_SUFFIX(sxe2_common_log, com, NOTICE);

Generated by: LCOV version 1.14