LCOV - code coverage report
Current view: top level - drivers/common/nfp - nfp_common_pci.c (source / functions) Hit Total Coverage
Test: Code coverage Lines: 44 80 55.0 %
Date: 2025-05-01 17:49:45 Functions: 4 10 40.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 31 58 53.4 %

           Branch data     Line data    Source code
       1                 :            : /* SPDX-License-Identifier: BSD-3-Clause
       2                 :            :  * Copyright (c) 2023 Corigine, Inc.
       3                 :            :  * All rights reserved.
       4                 :            :  */
       5                 :            : 
       6                 :            : #include "nfp_common_pci.h"
       7                 :            : 
       8                 :            : #include <string.h>
       9                 :            : 
      10                 :            : #include <eal_export.h>
      11                 :            : #include <rte_class.h>
      12                 :            : #include <rte_devargs.h>
      13                 :            : #include <rte_kvargs.h>
      14                 :            : 
      15                 :            : #include "nfp_common_log.h"
      16                 :            : 
      17                 :            : /* Reported driver name. */
      18                 :            : #define NFP_PCI_DRIVER_NAME "nfp_common_pci"
      19                 :            : 
      20                 :            : static struct rte_pci_driver nfp_common_pci_driver;
      21                 :            : 
      22                 :            : /* PCI ID table is build dynamically based on registered nfp drivers. */
      23                 :            : static struct rte_pci_id *nfp_pci_id_table;
      24                 :            : 
      25                 :            : /* Head of list of drivers. */
      26                 :            : static TAILQ_HEAD(nfp_drivers, nfp_class_driver) nfp_drivers_list =
      27                 :            :                 TAILQ_HEAD_INITIALIZER(nfp_drivers_list);
      28                 :            : 
      29                 :            : static bool nfp_common_initialized;
      30                 :            : 
      31                 :            : static const struct {
      32                 :            :         const char *name;
      33                 :            :         enum nfp_class drv_class;
      34                 :            : } nfp_classes[] = {
      35                 :            :         { .name = "eth",      .drv_class = NFP_CLASS_ETH },
      36                 :            :         { .name = "vdpa",     .drv_class = NFP_CLASS_VDPA },
      37                 :            : };
      38                 :            : 
      39                 :            : static enum nfp_class
      40                 :          0 : nfp_class_name_to_value(const char *class_name)
      41                 :            : {
      42                 :            :         uint32_t i;
      43                 :            : 
      44         [ #  # ]:          0 :         for (i = 0; i < RTE_DIM(nfp_classes); i++) {
      45         [ #  # ]:          0 :                 if (strcmp(class_name, nfp_classes[i].name) == 0)
      46                 :          0 :                         return nfp_classes[i].drv_class;
      47                 :            :         }
      48                 :            : 
      49                 :            :         return NFP_CLASS_INVALID;
      50                 :            : }
      51                 :            : 
      52                 :            : static uint32_t
      53                 :            : nfp_pci_id_table_size_get(const struct rte_pci_id *id_table)
      54                 :            : {
      55                 :            :         uint32_t table_size;
      56                 :            : 
      57         [ +  - ]:        756 :         if (id_table == NULL)
      58                 :            :                 return 0;
      59                 :            : 
      60   [ +  +  +  + ]:       3528 :         for (table_size = 0; id_table->vendor_id != 0; id_table++)
      61                 :       2268 :                 table_size++;
      62                 :            : 
      63                 :            :         return table_size;
      64                 :            : }
      65                 :            : 
      66                 :            : static bool
      67                 :            : nfp_pci_id_exists(const struct rte_pci_id *id,
      68                 :            :                 const struct rte_pci_id *table,
      69                 :            :                 uint32_t next_idx)
      70                 :            : {
      71                 :            :         uint32_t i;
      72                 :            : 
      73                 :       1260 :         if (next_idx == 0)
      74                 :            :                 return false;
      75                 :            : 
      76         [ +  + ]:       2772 :         for (i = 0; i < next_idx; i++) {
      77         [ +  + ]:       2016 :                 if (id->device_id == table[i].device_id &&
      78                 :            :                                 id->vendor_id == table[i].vendor_id &&
      79         [ -  + ]:        252 :                                 id->subsystem_vendor_id == table[i].subsystem_vendor_id &&
      80                 :            :                                 id->subsystem_device_id == table[i].subsystem_device_id)
      81                 :            :                         return true;
      82                 :            :         }
      83                 :            : 
      84                 :            :         return false;
      85                 :            : }
      86                 :            : 
      87                 :            : static void
      88                 :        504 : nfp_pci_id_insert(struct rte_pci_id *new_table,
      89                 :            :                 uint32_t *next_idx,
      90                 :            :                 const struct rte_pci_id *id_table)
      91                 :            : {
      92         [ +  - ]:        504 :         if (id_table == NULL)
      93                 :            :                 return;
      94                 :            : 
      95                 :            :         /* Add non duplicate entries to new table. */
      96         [ +  + ]:       1764 :         for (; id_table->vendor_id != 0; id_table++) {
      97   [ +  +  +  + ]:       2268 :                 if (!nfp_pci_id_exists(id_table, new_table, *next_idx)) {
      98                 :       1008 :                         new_table[*next_idx] = *id_table;
      99                 :       1008 :                         (*next_idx)++;
     100                 :            :                 }
     101                 :            :         }
     102                 :            : }
     103                 :            : 
     104                 :            : static int
     105                 :        756 : nfp_pci_id_table_update(const struct rte_pci_id *driver_id_table)
     106                 :            : {
     107                 :        756 :         uint32_t i = 0;
     108                 :            :         uint32_t num_ids = 0;
     109                 :            :         struct rte_pci_id *old_table;
     110                 :            :         const struct rte_pci_id *id_iter;
     111                 :            :         struct rte_pci_id *updated_table;
     112                 :            : 
     113                 :        756 :         old_table = nfp_pci_id_table;
     114         [ +  + ]:        756 :         if (old_table != NULL)
     115                 :            :                 num_ids = nfp_pci_id_table_size_get(old_table);
     116                 :        756 :         num_ids += nfp_pci_id_table_size_get(driver_id_table);
     117                 :            : 
     118                 :            :         /* Increase size by one for the termination entry of vendor_id = 0. */
     119                 :        756 :         num_ids += 1;
     120                 :        756 :         updated_table = calloc(num_ids, sizeof(struct rte_pci_id));
     121         [ +  - ]:        756 :         if (updated_table == NULL)
     122                 :            :                 return -ENOMEM;
     123                 :            : 
     124         [ +  + ]:        756 :         if (old_table == NULL) {
     125                 :            :                 /* Copy the first driver's ID table. */
     126         [ -  + ]:        252 :                 for (id_iter = driver_id_table; id_iter[i].vendor_id != 0; i++)
     127                 :          0 :                         updated_table[i] = id_iter[i];
     128                 :            :         } else {
     129                 :            :                 /* First copy existing table entries. */
     130         [ +  + ]:       1512 :                 for (id_iter = old_table; id_iter[i].vendor_id != 0; i++)
     131                 :       1008 :                         updated_table[i] = id_iter[i];
     132                 :            :                 /* New id to be added at the end of current ID table. */
     133                 :        504 :                 nfp_pci_id_insert(updated_table, &i, driver_id_table);
     134                 :            : 
     135                 :        504 :                 free(old_table);
     136                 :            :         }
     137                 :            : 
     138                 :            :         /* Terminate table with empty entry. */
     139                 :        756 :         updated_table[i].vendor_id = 0;
     140                 :        756 :         nfp_pci_id_table = updated_table;
     141                 :        756 :         nfp_common_pci_driver.id_table = nfp_pci_id_table;
     142                 :            : 
     143                 :        756 :         return 0;
     144                 :            : }
     145                 :            : 
     146                 :            : static int
     147                 :          0 : nfp_kvarg_dev_class_handler(__rte_unused const char *key,
     148                 :            :                 const char *class_str,
     149                 :            :                 void *opaque)
     150                 :            : {
     151                 :            :         enum nfp_class *dev_class = opaque;
     152                 :            : 
     153         [ #  # ]:          0 :         if (class_str == NULL)
     154                 :          0 :                 return *dev_class;
     155                 :            : 
     156                 :          0 :         *dev_class = nfp_class_name_to_value(class_str);
     157                 :            : 
     158                 :          0 :         return 0;
     159                 :            : }
     160                 :            : 
     161                 :            : static enum nfp_class
     162                 :          0 : nfp_parse_class_options(const struct rte_devargs *devargs)
     163                 :            : {
     164                 :            :         struct rte_kvargs *kvargs;
     165                 :          0 :         enum nfp_class dev_class = NFP_CLASS_ETH;
     166                 :            : 
     167         [ #  # ]:          0 :         if (devargs == NULL)
     168                 :            :                 return dev_class;
     169                 :            : 
     170                 :          0 :         kvargs = rte_kvargs_parse(devargs->args, NULL);
     171         [ #  # ]:          0 :         if (kvargs == NULL)
     172                 :          0 :                 return dev_class;
     173                 :            : 
     174                 :          0 :         rte_kvargs_process_opt(kvargs, RTE_DEVARGS_KEY_CLASS,
     175                 :            :                                nfp_kvarg_dev_class_handler, &dev_class);
     176                 :            : 
     177                 :          0 :         rte_kvargs_free(kvargs);
     178                 :            : 
     179                 :          0 :         return dev_class;
     180                 :            : }
     181                 :            : 
     182                 :            : static int
     183                 :          0 : nfp_drivers_probe(struct rte_pci_device *pci_dev,
     184                 :            :                 enum nfp_class class)
     185                 :            : {
     186                 :            :         int32_t ret = 0;
     187                 :            :         struct nfp_class_driver *driver;
     188                 :            : 
     189         [ #  # ]:          0 :         TAILQ_FOREACH(driver, &nfp_drivers_list, next) {
     190         [ #  # ]:          0 :                 if (driver->drv_class != class)
     191                 :          0 :                         continue;
     192                 :            : 
     193                 :          0 :                 ret = driver->probe(pci_dev);
     194         [ #  # ]:          0 :                 if (ret < 0) {
     195                 :          0 :                         PMD_DRV_LOG(ERR, "Failed to load driver %s.", driver->name);
     196                 :          0 :                         return ret;
     197                 :            :                 }
     198                 :            :         }
     199                 :            : 
     200                 :            :         return 0;
     201                 :            : }
     202                 :            : 
     203                 :            : static int
     204                 :          0 : nfp_common_pci_probe(struct rte_pci_driver *pci_drv __rte_unused,
     205                 :            :                 struct rte_pci_device *pci_dev)
     206                 :            : {
     207                 :            :         enum nfp_class class;
     208                 :            :         struct rte_device *eal_dev = &pci_dev->device;
     209                 :            : 
     210                 :          0 :         PMD_DRV_LOG(INFO, "Probe device %s.", eal_dev->name);
     211                 :            : 
     212                 :          0 :         class = nfp_parse_class_options(eal_dev->devargs);
     213         [ #  # ]:          0 :         if (class == NFP_CLASS_INVALID) {
     214                 :          0 :                 PMD_DRV_LOG(ERR, "Unsupported nfp class type: %s.",
     215                 :            :                                 eal_dev->devargs->args);
     216                 :          0 :                 return -ENOTSUP;
     217                 :            :         }
     218                 :            : 
     219                 :          0 :         return nfp_drivers_probe(pci_dev, class);
     220                 :            : }
     221                 :            : 
     222                 :            : static int
     223                 :          0 : nfp_common_pci_remove(__rte_unused struct rte_pci_device *pci_dev)
     224                 :            : {
     225                 :          0 :         return 0;
     226                 :            : }
     227                 :            : 
     228                 :            : static struct rte_pci_driver nfp_common_pci_driver = {
     229                 :            :         .driver = {
     230                 :            :                 .name = NFP_PCI_DRIVER_NAME,
     231                 :            :         },
     232                 :            :         .probe = nfp_common_pci_probe,
     233                 :            :         .remove = nfp_common_pci_remove,
     234                 :            : };
     235                 :            : 
     236                 :            : static void
     237                 :        504 : nfp_common_init(void)
     238                 :            : {
     239                 :        504 :         const struct rte_pci_id empty_table[] = {
     240                 :            :                 {
     241                 :            :                         .vendor_id = 0
     242                 :            :                 },
     243                 :            :         };
     244                 :            : 
     245         [ +  + ]:        504 :         if (nfp_common_initialized)
     246                 :        252 :                 return;
     247                 :            : 
     248                 :            :         /*
     249                 :            :          * All the constructor of NFP PMDs run at same priority. So any of the PMD
     250                 :            :          * including this one can register the PCI table first. If any other
     251                 :            :          * PMD(s) have registered the PCI ID table, no need to register an empty
     252                 :            :          * default one.
     253                 :            :          */
     254   [ +  -  +  - ]:        252 :         if (nfp_pci_id_table == NULL && nfp_pci_id_table_update(empty_table) != 0)
     255                 :            :                 return;
     256                 :            : 
     257                 :        252 :         rte_pci_register(&nfp_common_pci_driver);
     258                 :        252 :         nfp_common_initialized = true;
     259                 :            : }
     260                 :            : 
     261                 :            : RTE_EXPORT_INTERNAL_SYMBOL(nfp_class_driver_register)
     262                 :            : void
     263                 :        504 : nfp_class_driver_register(struct nfp_class_driver *driver)
     264                 :            : {
     265                 :        504 :         nfp_common_init();
     266                 :            : 
     267         [ +  - ]:        504 :         if (driver->id_table != NULL) {
     268         [ +  - ]:        504 :                 if (nfp_pci_id_table_update(driver->id_table) != 0)
     269                 :            :                         return;
     270                 :            :         }
     271                 :            : 
     272                 :        504 :         nfp_common_pci_driver.drv_flags |= driver->drv_flags;
     273                 :            : 
     274                 :        504 :         TAILQ_INSERT_TAIL(&nfp_drivers_list, driver, next);
     275                 :            : }

Generated by: LCOV version 1.14