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

Generated by: LCOV version 1.14