LCOV - code coverage report
Current view: top level - lib/eal/common - eal_common_bus.c (source / functions) Hit Total Coverage
Test: Code coverage Lines: 87 127 68.5 %
Date: 2026-05-01 18:54:57 Functions: 13 21 61.9 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 70 106 66.0 %

           Branch data     Line data    Source code
       1                 :            : /* SPDX-License-Identifier: BSD-3-Clause
       2                 :            :  * Copyright 2016 NXP
       3                 :            :  */
       4                 :            : 
       5                 :            : #include <stdio.h>
       6                 :            : #include <string.h>
       7                 :            : #include <sys/queue.h>
       8                 :            : 
       9                 :            : #include <bus_driver.h>
      10                 :            : #include <rte_debug.h>
      11                 :            : #include <rte_devargs.h>
      12                 :            : #include <rte_string_fns.h>
      13                 :            : #include <rte_errno.h>
      14                 :            : 
      15                 :            : #include <eal_export.h>
      16                 :            : #include "eal_private.h"
      17                 :            : 
      18                 :            : static struct rte_bus_list rte_bus_list =
      19                 :            :         TAILQ_HEAD_INITIALIZER(rte_bus_list);
      20                 :            : 
      21                 :            : RTE_EXPORT_SYMBOL(rte_bus_name)
      22                 :            : const char *
      23                 :      32073 : rte_bus_name(const struct rte_bus *bus)
      24                 :            : {
      25                 :      32073 :         return bus->name;
      26                 :            : }
      27                 :            : 
      28                 :            : RTE_EXPORT_INTERNAL_SYMBOL(rte_bus_register)
      29                 :            : void
      30                 :       3124 : rte_bus_register(struct rte_bus *bus)
      31                 :            : {
      32         [ -  + ]:       3124 :         RTE_VERIFY(bus);
      33   [ +  -  -  + ]:       3124 :         RTE_VERIFY(rte_bus_name(bus) && strlen(rte_bus_name(bus)));
      34                 :            :         /* A bus should mandatorily have the scan implemented */
      35         [ -  + ]:       3124 :         RTE_VERIFY(bus->scan);
      36         [ -  + ]:       3124 :         RTE_VERIFY(bus->probe);
      37         [ -  + ]:       3124 :         RTE_VERIFY(bus->find_device);
      38                 :            :         /* Buses supporting driver plug also require unplug. */
      39   [ +  +  -  + ]:       3124 :         RTE_VERIFY(!bus->plug || bus->unplug);
      40                 :            : 
      41                 :       3124 :         TAILQ_INSERT_TAIL(&rte_bus_list, bus, next);
      42                 :       3124 :         EAL_LOG(DEBUG, "Registered [%s] bus.", rte_bus_name(bus));
      43                 :       3124 : }
      44                 :            : 
      45                 :            : RTE_EXPORT_INTERNAL_SYMBOL(rte_bus_unregister)
      46                 :            : void
      47                 :          0 : rte_bus_unregister(struct rte_bus *bus)
      48                 :            : {
      49         [ #  # ]:          0 :         TAILQ_REMOVE(&rte_bus_list, bus, next);
      50                 :          0 :         EAL_LOG(DEBUG, "Unregistered [%s] bus.", rte_bus_name(bus));
      51                 :          0 : }
      52                 :            : 
      53                 :            : /* Scan all the buses for registered devices */
      54                 :            : RTE_EXPORT_SYMBOL(rte_bus_scan)
      55                 :            : int
      56                 :        216 : rte_bus_scan(void)
      57                 :            : {
      58                 :            :         int ret;
      59                 :            :         struct rte_bus *bus = NULL;
      60                 :            : 
      61         [ +  + ]:       2592 :         TAILQ_FOREACH(bus, &rte_bus_list, next) {
      62                 :       2376 :                 ret = bus->scan();
      63         [ -  + ]:       2376 :                 if (ret)
      64                 :          0 :                         EAL_LOG(ERR, "Scan for (%s) bus failed.",
      65                 :            :                                 rte_bus_name(bus));
      66                 :            :         }
      67                 :            : 
      68                 :        216 :         return 0;
      69                 :            : }
      70                 :            : 
      71                 :            : /* Probe all devices of all buses */
      72                 :            : RTE_EXPORT_SYMBOL(rte_bus_probe)
      73                 :            : int
      74                 :        211 : rte_bus_probe(void)
      75                 :            : {
      76                 :            :         int ret;
      77                 :            :         struct rte_bus *bus, *vbus = NULL;
      78                 :            : 
      79         [ +  + ]:       2532 :         TAILQ_FOREACH(bus, &rte_bus_list, next) {
      80         [ +  + ]:       2321 :                 if (!strcmp(rte_bus_name(bus), "vdev")) {
      81                 :            :                         vbus = bus;
      82                 :        211 :                         continue;
      83                 :            :                 }
      84                 :            : 
      85                 :       2110 :                 ret = bus->probe();
      86         [ -  + ]:       2110 :                 if (ret)
      87                 :          0 :                         EAL_LOG(ERR, "Bus (%s) probe failed.",
      88                 :            :                                 rte_bus_name(bus));
      89                 :            :         }
      90                 :            : 
      91         [ +  - ]:        211 :         if (vbus) {
      92                 :        211 :                 ret = vbus->probe();
      93         [ -  + ]:        211 :                 if (ret)
      94                 :          0 :                         EAL_LOG(ERR, "Bus (%s) probe failed.",
      95                 :            :                                 rte_bus_name(vbus));
      96                 :            :         }
      97                 :            : 
      98                 :        211 :         return 0;
      99                 :            : }
     100                 :            : 
     101                 :            : /* Clean up all devices of all buses */
     102                 :            : int
     103                 :        277 : eal_bus_cleanup(void)
     104                 :            : {
     105                 :            :         int ret = 0;
     106                 :            :         struct rte_bus *bus;
     107                 :            : 
     108         [ +  + ]:       3324 :         TAILQ_FOREACH(bus, &rte_bus_list, next) {
     109         [ +  + ]:       3047 :                 if (bus->cleanup == NULL)
     110                 :        554 :                         continue;
     111         [ -  + ]:       2493 :                 if (bus->cleanup() != 0)
     112                 :            :                         ret = -1;
     113                 :            :         }
     114                 :            : 
     115                 :        277 :         return ret;
     116                 :            : }
     117                 :            : 
     118                 :            : /* Dump information of a single bus */
     119                 :            : static int
     120                 :          0 : bus_dump_one(FILE *f, struct rte_bus *bus)
     121                 :            : {
     122                 :            :         int ret;
     123                 :            : 
     124                 :            :         /* For now, dump only the bus name */
     125                 :          0 :         ret = fprintf(f, " %s\n", rte_bus_name(bus));
     126                 :            : 
     127                 :            :         /* Error in case of inability in writing to stream */
     128                 :            :         if (ret < 0)
     129                 :            :                 return ret;
     130                 :            : 
     131                 :            :         return 0;
     132                 :            : }
     133                 :            : 
     134                 :            : RTE_EXPORT_SYMBOL(rte_bus_dump)
     135                 :            : void
     136                 :          0 : rte_bus_dump(FILE *f)
     137                 :            : {
     138                 :            :         int ret;
     139                 :            :         struct rte_bus *bus;
     140                 :            : 
     141         [ #  # ]:          0 :         TAILQ_FOREACH(bus, &rte_bus_list, next) {
     142                 :          0 :                 ret = bus_dump_one(f, bus);
     143         [ #  # ]:          0 :                 if (ret) {
     144                 :          0 :                         EAL_LOG(ERR, "Unable to write to stream (%d)",
     145                 :            :                                 ret);
     146                 :          0 :                         break;
     147                 :            :                 }
     148                 :            :         }
     149                 :          0 : }
     150                 :            : 
     151                 :            : RTE_EXPORT_SYMBOL(rte_bus_find)
     152                 :            : struct rte_bus *
     153                 :        105 : rte_bus_find(const struct rte_bus *start, rte_bus_cmp_t cmp,
     154                 :            :              const void *data)
     155                 :            : {
     156                 :            :         struct rte_bus *bus;
     157                 :            : 
     158         [ +  + ]:        105 :         if (start != NULL)
     159                 :          3 :                 bus = TAILQ_NEXT(start, next);
     160                 :            :         else
     161                 :        102 :                 bus = TAILQ_FIRST(&rte_bus_list);
     162         [ +  + ]:       1044 :         while (bus != NULL) {
     163         [ +  + ]:        986 :                 if (cmp(bus, data) == 0)
     164                 :            :                         break;
     165                 :        939 :                 bus = TAILQ_NEXT(bus, next);
     166                 :            :         }
     167                 :        105 :         return bus;
     168                 :            : }
     169                 :            : 
     170                 :            : static int
     171                 :          0 : cmp_rte_device(const struct rte_device *dev1, const void *_dev2)
     172                 :            : {
     173                 :            :         const struct rte_device *dev2 = _dev2;
     174                 :            : 
     175                 :          0 :         return dev1 != dev2;
     176                 :            : }
     177                 :            : 
     178                 :            : static int
     179                 :          0 : bus_find_device(const struct rte_bus *bus, const void *_dev)
     180                 :            : {
     181                 :            :         struct rte_device *dev;
     182                 :            : 
     183                 :          0 :         dev = bus->find_device(NULL, cmp_rte_device, _dev);
     184                 :          0 :         return dev == NULL;
     185                 :            : }
     186                 :            : 
     187                 :            : RTE_EXPORT_SYMBOL(rte_bus_find_by_device)
     188                 :            : struct rte_bus *
     189                 :          0 : rte_bus_find_by_device(const struct rte_device *dev)
     190                 :            : {
     191                 :          0 :         return rte_bus_find(NULL, bus_find_device, (const void *)dev);
     192                 :            : }
     193                 :            : 
     194                 :            : static int
     195                 :        152 : cmp_bus_name(const struct rte_bus *bus, const void *_name)
     196                 :            : {
     197                 :            :         const char *name = _name;
     198                 :            : 
     199                 :        152 :         return strcmp(rte_bus_name(bus), name);
     200                 :            : }
     201                 :            : 
     202                 :            : RTE_EXPORT_SYMBOL(rte_bus_find_by_name)
     203                 :            : struct rte_bus *
     204                 :         18 : rte_bus_find_by_name(const char *busname)
     205                 :            : {
     206                 :         18 :         return rte_bus_find(NULL, cmp_bus_name, (const void *)busname);
     207                 :            : }
     208                 :            : 
     209                 :            : RTE_EXPORT_INTERNAL_SYMBOL(rte_bus_find_devargs)
     210                 :            : struct rte_devargs *
     211                 :      18114 : rte_bus_find_devargs(const struct rte_bus *bus, const char *name)
     212                 :            : {
     213                 :      18114 :         rte_bus_dev_compare_t cmp = bus->dev_compare;
     214                 :      18114 :         const char *bus_name = rte_bus_name(bus);
     215                 :            :         struct rte_devargs *devargs;
     216                 :            : 
     217         [ +  + ]:      18114 :         if (cmp == NULL)
     218                 :            :                 cmp = strcmp;
     219                 :            : 
     220         [ +  + ]:      18627 :         RTE_EAL_DEVARGS_FOREACH(bus_name, devargs) {
     221                 :        516 :                 const char *devargs_name = devargs->name;
     222                 :            : 
     223                 :            :                 /* The name in the devargs is usually prefixed with <bus>: */
     224         [ -  + ]:        516 :                 if (strncmp(devargs_name, bus_name, strlen(bus_name)) == 0)
     225                 :          0 :                         devargs_name += strlen(bus_name) + 1;
     226         [ +  + ]:        516 :                 if (cmp(name, devargs_name) != 0)
     227                 :            :                         continue;
     228                 :          3 :                 EAL_LOG(DEBUG, "found devargs for %s:%s", bus_name, name);
     229                 :          3 :                 return devargs;
     230                 :            :         }
     231                 :            : 
     232                 :      18111 :         EAL_LOG(DEBUG, "no devargs for %s:%s", bus_name, name);
     233                 :      18111 :         return NULL;
     234                 :            : }
     235                 :            : 
     236                 :            : static int
     237                 :        372 : bus_can_parse(const struct rte_bus *bus, const void *_name)
     238                 :            : {
     239                 :            :         const char *name = _name;
     240                 :            : 
     241   [ +  -  +  + ]:        372 :         return !(bus->parse && bus->parse(name, NULL) == 0);
     242                 :            : }
     243                 :            : 
     244                 :            : struct rte_bus *
     245         [ +  + ]:         42 : rte_bus_find_by_device_name(const char *str)
     246                 :            : {
     247                 :            :         char name[RTE_DEV_NAME_MAX_LEN];
     248                 :            :         char *c;
     249                 :            : 
     250                 :            :         strlcpy(name, str, sizeof(name));
     251                 :         42 :         c = strchr(name, ',');
     252         [ +  + ]:         42 :         if (c != NULL)
     253                 :          1 :                 c[0] = '\0';
     254                 :         42 :         return rte_bus_find(NULL, bus_can_parse, name);
     255                 :            : }
     256                 :            : 
     257                 :            : RTE_EXPORT_INTERNAL_SYMBOL(rte_bus_device_is_ignored)
     258                 :            : bool
     259                 :      10417 : rte_bus_device_is_ignored(const struct rte_bus *bus, const char *dev_name)
     260                 :            : {
     261                 :      10417 :         const struct internal_config *internal_conf = eal_get_internal_configuration();
     262                 :      10417 :         struct rte_devargs *devargs = rte_bus_find_devargs(bus, dev_name);
     263                 :      10417 :         enum rte_bus_scan_mode scan_mode = bus->conf.scan_mode;
     264                 :            : 
     265         [ +  + ]:      10417 :         if (scan_mode == RTE_BUS_SCAN_UNDEFINED) {
     266         [ +  + ]:      10073 :                 if (internal_conf->no_auto_probing != 0)
     267                 :            :                         scan_mode = RTE_BUS_SCAN_ALLOWLIST;
     268                 :            :                 else
     269                 :            :                         scan_mode = RTE_BUS_SCAN_BLOCKLIST;
     270                 :            :         }
     271                 :            : 
     272         [ +  + ]:        344 :         if (scan_mode == RTE_BUS_SCAN_ALLOWLIST) {
     273   [ +  +  -  + ]:        377 :                 if (devargs && devargs->policy == RTE_DEV_ALLOWED)
     274                 :            :                         return false;
     275                 :            :         } else {
     276   [ +  +  +  - ]:      10040 :                 if (devargs == NULL || devargs->policy != RTE_DEV_BLOCKED)
     277                 :            :                         return false;
     278                 :            :         }
     279                 :            : 
     280                 :        377 :         EAL_LOG(DEBUG, "device %s:%s is ignored", rte_bus_name(bus), dev_name);
     281                 :        377 :         return true;
     282                 :            : }
     283                 :            : 
     284                 :            : /*
     285                 :            :  * Get iommu class of devices on the bus.
     286                 :            :  */
     287                 :            : RTE_EXPORT_SYMBOL(rte_bus_get_iommu_class)
     288                 :            : enum rte_iova_mode
     289                 :        216 : rte_bus_get_iommu_class(void)
     290                 :            : {
     291                 :            :         enum rte_iova_mode mode = RTE_IOVA_DC;
     292                 :            :         bool buses_want_va = false;
     293                 :            :         bool buses_want_pa = false;
     294                 :            :         struct rte_bus *bus;
     295                 :            : 
     296         [ +  + ]:       2592 :         TAILQ_FOREACH(bus, &rte_bus_list, next) {
     297                 :            :                 enum rte_iova_mode bus_iova_mode;
     298                 :            : 
     299         [ +  + ]:       2376 :                 if (bus->get_iommu_class == NULL)
     300                 :        648 :                         continue;
     301                 :            : 
     302                 :       1728 :                 bus_iova_mode = bus->get_iommu_class();
     303   [ +  +  +  - ]:       1729 :                 EAL_LOG(DEBUG, "Bus %s wants IOVA as '%s'",
     304                 :            :                         rte_bus_name(bus),
     305                 :            :                         bus_iova_mode == RTE_IOVA_DC ? "DC" :
     306                 :            :                         (bus_iova_mode == RTE_IOVA_PA ? "PA" : "VA"));
     307         [ +  - ]:       1728 :                 if (bus_iova_mode == RTE_IOVA_PA) {
     308                 :            :                         buses_want_pa = true;
     309                 :            :                         if (!RTE_IOVA_IN_MBUF)
     310                 :            :                                 EAL_LOG(WARNING,
     311                 :            :                                         "Bus %s wants IOVA as PA not compatible with 'enable_iova_as_pa=false' build option.",
     312                 :            :                                         rte_bus_name(bus));
     313         [ +  + ]:       1728 :                 } else if (bus_iova_mode == RTE_IOVA_VA)
     314                 :            :                         buses_want_va = true;
     315                 :            :         }
     316         [ +  + ]:        216 :         if (buses_want_va && !buses_want_pa) {
     317                 :            :                 mode = RTE_IOVA_VA;
     318         [ +  - ]:        215 :         } else if (buses_want_pa && !buses_want_va) {
     319                 :            :                 mode = RTE_IOVA_PA;
     320                 :            :         } else {
     321                 :            :                 mode = RTE_IOVA_DC;
     322         [ -  + ]:        215 :                 if (buses_want_va) {
     323                 :          0 :                         EAL_LOG(WARNING, "Some buses want 'VA' but forcing 'DC' because other buses want 'PA'.");
     324                 :          0 :                         EAL_LOG(WARNING, "Depending on the final decision by the EAL, not all buses may be able to initialize.");
     325                 :            :                 }
     326                 :            :         }
     327                 :            : 
     328                 :        216 :         return mode;
     329                 :            : }
     330                 :            : 
     331                 :            : static int
     332                 :          0 : bus_handle_sigbus(const struct rte_bus *bus,
     333                 :            :                         const void *failure_addr)
     334                 :            : {
     335                 :            :         int ret;
     336                 :            : 
     337         [ #  # ]:          0 :         if (!bus->sigbus_handler)
     338                 :            :                 return -1;
     339                 :            : 
     340                 :          0 :         ret = bus->sigbus_handler(failure_addr);
     341                 :            : 
     342                 :            :         /* find bus but handle failed, keep the errno be set. */
     343   [ #  #  #  # ]:          0 :         if (ret < 0 && rte_errno == 0)
     344                 :          0 :                 rte_errno = ENOTSUP;
     345                 :            : 
     346                 :          0 :         return ret > 0;
     347                 :            : }
     348                 :            : 
     349                 :            : int
     350                 :          0 : rte_bus_sigbus_handler(const void *failure_addr)
     351                 :            : {
     352                 :            :         struct rte_bus *bus;
     353                 :            : 
     354                 :            :         int ret = 0;
     355                 :          0 :         int old_errno = rte_errno;
     356                 :            : 
     357                 :          0 :         rte_errno = 0;
     358                 :            : 
     359                 :          0 :         bus = rte_bus_find(NULL, bus_handle_sigbus, failure_addr);
     360                 :            :         /* can not find bus. */
     361         [ #  # ]:          0 :         if (!bus)
     362                 :            :                 return 1;
     363                 :            :         /* find bus but handle failed, pass on the new errno. */
     364         [ #  # ]:          0 :         else if (rte_errno != 0)
     365                 :            :                 return -1;
     366                 :            : 
     367                 :            :         /* restore the old errno. */
     368                 :          0 :         rte_errno = old_errno;
     369                 :            : 
     370                 :          0 :         return ret;
     371                 :            : }

Generated by: LCOV version 1.14