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

Generated by: LCOV version 1.14