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