New upstream version 17.11-rc3
[deb_dpdk.git] / lib / librte_eal / common / eal_common_bus.c
1 /*-
2  *   BSD LICENSE
3  *
4  *   Copyright 2016 NXP.
5  *
6  *   Redistribution and use in source and binary forms, with or without
7  *   modification, are permitted provided that the following conditions
8  *   are met:
9  *
10  *     * Redistributions of source code must retain the above copyright
11  *       notice, this list of conditions and the following disclaimer.
12  *     * Redistributions in binary form must reproduce the above copyright
13  *       notice, this list of conditions and the following disclaimer in
14  *       the documentation and/or other materials provided with the
15  *       distribution.
16  *     * Neither the name of NXP nor the names of its
17  *       contributors may be used to endorse or promote products derived
18  *       from this software without specific prior written permission.
19  *
20  *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21  *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22  *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23  *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24  *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25  *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26  *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27  *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28  *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29  *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30  *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  */
32
33 #include <stdio.h>
34 #include <string.h>
35 #include <sys/queue.h>
36
37 #include <rte_bus.h>
38 #include <rte_debug.h>
39
40 #include "eal_private.h"
41
42 struct rte_bus_list rte_bus_list =
43         TAILQ_HEAD_INITIALIZER(rte_bus_list);
44
45 void
46 rte_bus_register(struct rte_bus *bus)
47 {
48         RTE_VERIFY(bus);
49         RTE_VERIFY(bus->name && strlen(bus->name));
50         /* A bus should mandatorily have the scan implemented */
51         RTE_VERIFY(bus->scan);
52         RTE_VERIFY(bus->probe);
53         RTE_VERIFY(bus->find_device);
54         /* Buses supporting driver plug also require unplug. */
55         RTE_VERIFY(!bus->plug || bus->unplug);
56
57         TAILQ_INSERT_TAIL(&rte_bus_list, bus, next);
58         RTE_LOG(DEBUG, EAL, "Registered [%s] bus.\n", bus->name);
59 }
60
61 void
62 rte_bus_unregister(struct rte_bus *bus)
63 {
64         TAILQ_REMOVE(&rte_bus_list, bus, next);
65         RTE_LOG(DEBUG, EAL, "Unregistered [%s] bus.\n", bus->name);
66 }
67
68 /* Scan all the buses for registered devices */
69 int
70 rte_bus_scan(void)
71 {
72         int ret;
73         struct rte_bus *bus = NULL;
74
75         TAILQ_FOREACH(bus, &rte_bus_list, next) {
76                 ret = bus->scan();
77                 if (ret)
78                         RTE_LOG(ERR, EAL, "Scan for (%s) bus failed.\n",
79                                 bus->name);
80         }
81
82         return 0;
83 }
84
85 /* Probe all devices of all buses */
86 int
87 rte_bus_probe(void)
88 {
89         int ret;
90         struct rte_bus *bus, *vbus = NULL;
91
92         TAILQ_FOREACH(bus, &rte_bus_list, next) {
93                 if (!strcmp(bus->name, "vdev")) {
94                         vbus = bus;
95                         continue;
96                 }
97
98                 ret = bus->probe();
99                 if (ret)
100                         RTE_LOG(ERR, EAL, "Bus (%s) probe failed.\n",
101                                 bus->name);
102         }
103
104         if (vbus) {
105                 ret = vbus->probe();
106                 if (ret)
107                         RTE_LOG(ERR, EAL, "Bus (%s) probe failed.\n",
108                                 vbus->name);
109         }
110
111         return 0;
112 }
113
114 /* Dump information of a single bus */
115 static int
116 bus_dump_one(FILE *f, struct rte_bus *bus)
117 {
118         int ret;
119
120         /* For now, dump only the bus name */
121         ret = fprintf(f, " %s\n", bus->name);
122
123         /* Error in case of inability in writing to stream */
124         if (ret < 0)
125                 return ret;
126
127         return 0;
128 }
129
130 void
131 rte_bus_dump(FILE *f)
132 {
133         int ret;
134         struct rte_bus *bus;
135
136         TAILQ_FOREACH(bus, &rte_bus_list, next) {
137                 ret = bus_dump_one(f, bus);
138                 if (ret) {
139                         RTE_LOG(ERR, EAL, "Unable to write to stream (%d)\n",
140                                 ret);
141                         break;
142                 }
143         }
144 }
145
146 struct rte_bus *
147 rte_bus_find(const struct rte_bus *start, rte_bus_cmp_t cmp,
148              const void *data)
149 {
150         struct rte_bus *bus;
151
152         if (start != NULL)
153                 bus = TAILQ_NEXT(start, next);
154         else
155                 bus = TAILQ_FIRST(&rte_bus_list);
156         while (bus != NULL) {
157                 if (cmp(bus, data) == 0)
158                         break;
159                 bus = TAILQ_NEXT(bus, next);
160         }
161         return bus;
162 }
163
164 static int
165 cmp_rte_device(const struct rte_device *dev1, const void *_dev2)
166 {
167         const struct rte_device *dev2 = _dev2;
168
169         return dev1 != dev2;
170 }
171
172 static int
173 bus_find_device(const struct rte_bus *bus, const void *_dev)
174 {
175         struct rte_device *dev;
176
177         dev = bus->find_device(NULL, cmp_rte_device, _dev);
178         return dev == NULL;
179 }
180
181 struct rte_bus *
182 rte_bus_find_by_device(const struct rte_device *dev)
183 {
184         return rte_bus_find(NULL, bus_find_device, (const void *)dev);
185 }
186
187 static int
188 cmp_bus_name(const struct rte_bus *bus, const void *_name)
189 {
190         const char *name = _name;
191
192         return strcmp(bus->name, name);
193 }
194
195 struct rte_bus *
196 rte_bus_find_by_name(const char *busname)
197 {
198         return rte_bus_find(NULL, cmp_bus_name, (const void *)busname);
199 }
200
201 static int
202 bus_can_parse(const struct rte_bus *bus, const void *_name)
203 {
204         const char *name = _name;
205
206         return !(bus->parse && bus->parse(name, NULL) == 0);
207 }
208
209 struct rte_bus *
210 rte_bus_find_by_device_name(const char *str)
211 {
212         char name[RTE_DEV_NAME_MAX_LEN];
213         char *c;
214
215         snprintf(name, sizeof(name), "%s", str);
216         c = strchr(name, ',');
217         if (c != NULL)
218                 c[0] = '\0';
219         return rte_bus_find(NULL, bus_can_parse, name);
220 }
221
222
223 /*
224  * Get iommu class of devices on the bus.
225  */
226 enum rte_iova_mode
227 rte_bus_get_iommu_class(void)
228 {
229         int mode = RTE_IOVA_DC;
230         struct rte_bus *bus;
231
232         TAILQ_FOREACH(bus, &rte_bus_list, next) {
233
234                 if (bus->get_iommu_class)
235                         mode |= bus->get_iommu_class();
236         }
237
238         if (mode != RTE_IOVA_VA) {
239                 /* Use default IOVA mode */
240                 mode = RTE_IOVA_PA;
241         }
242         return mode;
243 }