LCOV - code coverage report
Current view: top level - lib/pci - rte_pci.c (source / functions) Hit Total Coverage
Test: Code coverage Lines: 49 50 98.0 %
Date: 2025-05-01 17:49:45 Functions: 6 6 100.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 34 46 73.9 %

           Branch data     Line data    Source code
       1                 :            : /* SPDX-License-Identifier: BSD-3-Clause
       2                 :            :  * Copyright(c) 2010-2014 Intel Corporation.
       3                 :            :  * Copyright 2013-2014 6WIND S.A.
       4                 :            :  */
       5                 :            : 
       6                 :            : #include <errno.h>
       7                 :            : #include <stdint.h>
       8                 :            : #include <stdlib.h>
       9                 :            : #include <stdio.h>
      10                 :            : 
      11                 :            : #include <eal_export.h>
      12                 :            : #include <rte_debug.h>
      13                 :            : 
      14                 :            : #include "rte_pci.h"
      15                 :            : 
      16                 :            : static inline const char *
      17                 :       1471 : get_u8_pciaddr_field(const char *in, void *_u8, char dlm)
      18                 :            : {
      19                 :            :         unsigned long val;
      20                 :            :         uint8_t *u8 = _u8;
      21                 :            :         char *end;
      22                 :            : 
      23                 :            :         /* empty string is an error though strtoul() returns 0 */
      24         [ +  - ]:       1471 :         if (*in == '\0')
      25                 :            :                 return NULL;
      26                 :            : 
      27                 :            :         /* PCI field starting with spaces is forbidden.
      28                 :            :          * Negative wrap-around is not reported as an error by strtoul.
      29                 :            :          */
      30         [ +  - ]:       1471 :         if (*in == ' ' || *in == '-')
      31                 :            :                 return NULL;
      32                 :            : 
      33                 :       1471 :         errno = 0;
      34                 :       1471 :         val = strtoul(in, &end, 16);
      35   [ +  -  +  +  :       1471 :         if (errno != 0 || end[0] != dlm || val > UINT8_MAX) {
                   -  + ]
      36         [ -  + ]:        212 :                 errno = errno ? errno : EINVAL;
      37                 :        212 :                 return NULL;
      38                 :            :         }
      39                 :       1259 :         *u8 = (uint8_t)val;
      40                 :       1259 :         return end + 1;
      41                 :            : }
      42                 :            : 
      43                 :            : static int
      44                 :        383 : pci_bdf_parse(const char *input, struct rte_pci_addr *dev_addr)
      45                 :            : {
      46                 :            :         const char *in = input;
      47                 :            : 
      48                 :        383 :         dev_addr->domain = 0;
      49                 :        383 :         in = get_u8_pciaddr_field(in, &dev_addr->bus, ':');
      50         [ +  + ]:        383 :         if (in == NULL)
      51                 :            :                 return -EINVAL;
      52                 :        363 :         in = get_u8_pciaddr_field(in, &dev_addr->devid, '.');
      53         [ +  + ]:        363 :         if (in == NULL)
      54                 :            :                 return -EINVAL;
      55                 :        179 :         in = get_u8_pciaddr_field(in, &dev_addr->function, '\0');
      56         [ -  + ]:        179 :         if (in == NULL)
      57                 :          0 :                 return -EINVAL;
      58                 :            :         return 0;
      59                 :            : }
      60                 :            : 
      61                 :            : static int
      62                 :        204 : pci_dbdf_parse(const char *input, struct rte_pci_addr *dev_addr)
      63                 :            : {
      64                 :            :         const char *in = input;
      65                 :            :         unsigned long val;
      66                 :            :         char *end;
      67                 :            : 
      68                 :            :         /* PCI id starting with spaces is forbidden.
      69                 :            :          * Negative wrap-around is not reported as an error by strtoul.
      70                 :            :          */
      71         [ +  - ]:        204 :         if (*in == ' ' || *in == '-')
      72                 :            :                 return -EINVAL;
      73                 :            : 
      74                 :        204 :         errno = 0;
      75                 :        204 :         val = strtoul(in, &end, 16);
      76                 :            :         /* Empty string is not an error for strtoul, but the check
      77                 :            :          *   end[0] != ':'
      78                 :            :          * will detect the issue.
      79                 :            :          */
      80   [ +  -  +  +  :        204 :         if (errno != 0 || end[0] != ':' || val > UINT32_MAX)
                   +  - ]
      81                 :            :                 return -EINVAL;
      82                 :        184 :         dev_addr->domain = (uint32_t)val;
      83                 :        184 :         in = end + 1;
      84                 :        184 :         in = get_u8_pciaddr_field(in, &dev_addr->bus, ':');
      85         [ +  + ]:        184 :         if (in == NULL)
      86                 :            :                 return -EINVAL;
      87                 :        182 :         in = get_u8_pciaddr_field(in, &dev_addr->devid, '.');
      88         [ +  + ]:        182 :         if (in == NULL)
      89                 :            :                 return -EINVAL;
      90                 :        180 :         in = get_u8_pciaddr_field(in, &dev_addr->function, '\0');
      91         [ +  + ]:        180 :         if (in == NULL)
      92                 :          4 :                 return -EINVAL;
      93                 :            :         return 0;
      94                 :            : }
      95                 :            : 
      96                 :            : RTE_EXPORT_SYMBOL(rte_pci_device_name)
      97                 :            : void
      98                 :       7742 : rte_pci_device_name(const struct rte_pci_addr *addr,
      99                 :            :                 char *output, size_t size)
     100                 :            : {
     101         [ -  + ]:       7742 :         RTE_VERIFY(size >= PCI_PRI_STR_SIZE);
     102         [ -  + ]:       7742 :         RTE_VERIFY(snprintf(output, size, PCI_PRI_FMT,
     103                 :            :                             addr->domain, addr->bus,
     104                 :            :                             addr->devid, addr->function) >= 0);
     105                 :       7742 : }
     106                 :            : 
     107                 :            : RTE_EXPORT_SYMBOL(rte_pci_addr_cmp)
     108                 :            : int
     109                 :      67125 : rte_pci_addr_cmp(const struct rte_pci_addr *addr,
     110                 :            :              const struct rte_pci_addr *addr2)
     111                 :            : {
     112                 :            :         uint64_t dev_addr, dev_addr2;
     113                 :            : 
     114         [ +  - ]:      67125 :         if ((addr == NULL) || (addr2 == NULL))
     115                 :            :                 return -1;
     116                 :            : 
     117                 :      67125 :         dev_addr = ((uint64_t)addr->domain << 24) |
     118                 :      67125 :                 (addr->bus << 16) | (addr->devid << 8) | addr->function;
     119                 :      67125 :         dev_addr2 = ((uint64_t)addr2->domain << 24) |
     120                 :      67125 :                 (addr2->bus << 16) | (addr2->devid << 8) | addr2->function;
     121                 :            : 
     122         [ +  + ]:      67125 :         if (dev_addr > dev_addr2)
     123                 :            :                 return 1;
     124         [ +  + ]:       7143 :         else if (dev_addr < dev_addr2)
     125                 :            :                 return -1;
     126                 :            :         else
     127                 :          2 :                 return 0;
     128                 :            : }
     129                 :            : 
     130                 :            : RTE_EXPORT_SYMBOL(rte_pci_addr_parse)
     131                 :            : int
     132                 :        383 : rte_pci_addr_parse(const char *str, struct rte_pci_addr *addr)
     133                 :            : {
     134   [ +  +  +  + ]:        587 :         if (pci_bdf_parse(str, addr) == 0 ||
     135                 :        204 :             pci_dbdf_parse(str, addr) == 0)
     136                 :        355 :                 return 0;
     137                 :            :         return -1;
     138                 :            : }

Generated by: LCOV version 1.14