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 : : }
|