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