1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright 2014 6WIND S.A.
5 /* This file manages the list of devices and their arguments, as given
6 * by the user at startup
14 #include <rte_class.h>
15 #include <rte_compat.h>
17 #include <rte_devargs.h>
18 #include <rte_errno.h>
19 #include <rte_kvargs.h>
21 #include <rte_tailq.h>
22 #include "eal_private.h"
24 /** user device double-linked queue type definition */
25 TAILQ_HEAD(rte_devargs_list
, rte_devargs
);
27 /** Global list of user devices */
28 static struct rte_devargs_list devargs_list
=
29 TAILQ_HEAD_INITIALIZER(devargs_list
);
32 devargs_layer_count(const char *s
)
36 while (s
!= NULL
&& s
[0] != '\0') {
44 rte_devargs_layers_parse(struct rte_devargs
*devargs
,
50 struct rte_kvargs
*kvlist
;
52 { "bus=", NULL
, NULL
, },
53 { "class=", NULL
, NULL
, },
54 { "driver=", NULL
, NULL
, },
56 struct rte_kvargs_pair
*kv
= NULL
;
57 struct rte_class
*cls
= NULL
;
58 struct rte_bus
*bus
= NULL
;
59 const char *s
= devstr
;
64 /* Split each sub-lists. */
65 nblayer
= devargs_layer_count(devstr
);
66 if (nblayer
> RTE_DIM(layers
)) {
67 RTE_LOG(ERR
, EAL
, "Invalid format: too many layers (%zu)\n",
73 /* If the devargs points the devstr
74 * as source data, then it should not allocate
75 * anything and keep referring only to it.
77 if (devargs
->data
!= devstr
) {
78 devargs
->data
= strdup(devstr
);
79 if (devargs
->data
== NULL
) {
80 RTE_LOG(ERR
, EAL
, "OOM\n");
88 if (i
>= RTE_DIM(layers
)) {
89 RTE_LOG(ERR
, EAL
, "Unrecognized layer %s\n", s
);
94 * The last layer is free-form.
95 * The "driver" key is not required (but accepted).
97 if (strncmp(layers
[i
].key
, s
, strlen(layers
[i
].key
)) &&
98 i
!= RTE_DIM(layers
) - 1)
101 layers
[i
].kvlist
= rte_kvargs_parse_delim(s
, NULL
, "/");
102 if (layers
[i
].kvlist
== NULL
) {
103 RTE_LOG(ERR
, EAL
, "Could not parse %s\n", s
);
114 /* Parse each sub-list. */
115 for (i
= 0; i
< RTE_DIM(layers
); i
++) {
116 if (layers
[i
].kvlist
== NULL
)
118 kv
= &layers
[i
].kvlist
->pairs
[0];
119 if (strcmp(kv
->key
, "bus") == 0) {
120 bus
= rte_bus_find_by_name(kv
->value
);
122 RTE_LOG(ERR
, EAL
, "Could not find bus \"%s\"\n",
127 } else if (strcmp(kv
->key
, "class") == 0) {
128 cls
= rte_class_find_by_name(kv
->value
);
130 RTE_LOG(ERR
, EAL
, "Could not find class \"%s\"\n",
135 } else if (strcmp(kv
->key
, "driver") == 0) {
141 /* Fill devargs fields. */
142 devargs
->bus_str
= layers
[0].str
;
143 devargs
->cls_str
= layers
[1].str
;
144 devargs
->drv_str
= layers
[2].str
;
148 /* If we own the data, clean up a bit
149 * the several layers string, to ease
150 * their parsing afterward.
152 if (devargs
->data
!= devstr
) {
153 char *s
= (void *)(intptr_t)(devargs
->data
);
155 while ((s
= strchr(s
, '/'))) {
162 for (i
= 0; i
< RTE_DIM(layers
); i
++) {
163 if (layers
[i
].kvlist
)
164 rte_kvargs_free(layers
[i
].kvlist
);
172 bus_name_cmp(const struct rte_bus
*bus
, const void *name
)
174 return strncmp(bus
->name
, name
, strlen(bus
->name
));
178 rte_devargs_parse(struct rte_devargs
*da
, const char *dev
)
180 struct rte_bus
*bus
= NULL
;
182 const size_t maxlen
= sizeof(da
->name
);
188 /* Retrieve eventual bus info */
191 bus
= rte_bus_find(bus
, bus_name_cmp
, dev
);
194 devname
= dev
+ strlen(bus
->name
) + 1;
195 if (rte_bus_find_by_device_name(devname
) == bus
)
198 /* Store device name */
200 while (devname
[i
] != '\0' && devname
[i
] != ',') {
201 da
->name
[i
] = devname
[i
];
204 RTE_LOG(WARNING
, EAL
, "Parsing \"%s\": device name should be shorter than %zu\n",
206 da
->name
[i
- 1] = '\0';
212 bus
= rte_bus_find_by_device_name(da
->name
);
214 RTE_LOG(ERR
, EAL
, "failed to parse device \"%s\"\n",
220 /* Parse eventual device arguments */
221 if (devname
[i
] == ',')
222 da
->args
= strdup(&devname
[i
+ 1]);
224 da
->args
= strdup("");
225 if (da
->args
== NULL
) {
226 RTE_LOG(ERR
, EAL
, "not enough memory to parse arguments\n");
233 rte_devargs_parsef(struct rte_devargs
*da
, const char *format
, ...)
243 va_start(ap
, format
);
244 len
= vsnprintf(NULL
, 0, format
, ap
);
247 dev
= calloc(1, len
+ 1);
249 RTE_LOG(ERR
, EAL
, "not enough memory to parse device\n");
253 va_start(ap
, format
);
254 vsnprintf(dev
, len
+ 1, format
, ap
);
257 ret
= rte_devargs_parse(da
, dev
);
264 rte_devargs_insert(struct rte_devargs
**da
)
266 struct rte_devargs
*listed_da
;
269 if (*da
== NULL
|| (*da
)->bus
== NULL
)
272 TAILQ_FOREACH_SAFE(listed_da
, &devargs_list
, next
, tmp
) {
273 if (listed_da
== *da
)
274 /* devargs already in the list */
276 if (strcmp(listed_da
->bus
->name
, (*da
)->bus
->name
) == 0 &&
277 strcmp(listed_da
->name
, (*da
)->name
) == 0) {
278 /* device already in devargs list, must be updated */
279 listed_da
->type
= (*da
)->type
;
280 listed_da
->policy
= (*da
)->policy
;
281 free(listed_da
->args
);
282 listed_da
->args
= (*da
)->args
;
283 listed_da
->bus
= (*da
)->bus
;
284 listed_da
->cls
= (*da
)->cls
;
285 listed_da
->bus_str
= (*da
)->bus_str
;
286 listed_da
->cls_str
= (*da
)->cls_str
;
287 listed_da
->data
= (*da
)->data
;
288 /* replace provided devargs with found one */
294 /* new device in the list */
295 TAILQ_INSERT_TAIL(&devargs_list
, *da
, next
);
299 /* store a whitelist parameter for later parsing */
301 rte_devargs_add(enum rte_devtype devtype
, const char *devargs_str
)
303 struct rte_devargs
*devargs
= NULL
;
304 struct rte_bus
*bus
= NULL
;
305 const char *dev
= devargs_str
;
307 /* use calloc instead of rte_zmalloc as it's called early at init */
308 devargs
= calloc(1, sizeof(*devargs
));
312 if (rte_devargs_parse(devargs
, dev
))
314 devargs
->type
= devtype
;
316 if (devargs
->type
== RTE_DEVTYPE_BLACKLISTED_PCI
)
317 devargs
->policy
= RTE_DEV_BLACKLISTED
;
318 if (bus
->conf
.scan_mode
== RTE_BUS_SCAN_UNDEFINED
) {
319 if (devargs
->policy
== RTE_DEV_WHITELISTED
)
320 bus
->conf
.scan_mode
= RTE_BUS_SCAN_WHITELIST
;
321 else if (devargs
->policy
== RTE_DEV_BLACKLISTED
)
322 bus
->conf
.scan_mode
= RTE_BUS_SCAN_BLACKLIST
;
324 TAILQ_INSERT_TAIL(&devargs_list
, devargs
, next
);
337 rte_devargs_remove(struct rte_devargs
*devargs
)
339 struct rte_devargs
*d
;
342 if (devargs
== NULL
|| devargs
->bus
== NULL
)
345 TAILQ_FOREACH_SAFE(d
, &devargs_list
, next
, tmp
) {
346 if (strcmp(d
->bus
->name
, devargs
->bus
->name
) == 0 &&
347 strcmp(d
->name
, devargs
->name
) == 0) {
348 TAILQ_REMOVE(&devargs_list
, d
, next
);
357 /* count the number of devices of a specified type */
359 rte_devargs_type_count(enum rte_devtype devtype
)
361 struct rte_devargs
*devargs
;
362 unsigned int count
= 0;
364 TAILQ_FOREACH(devargs
, &devargs_list
, next
) {
365 if (devargs
->type
!= devtype
)
372 /* dump the user devices on the console */
374 rte_devargs_dump(FILE *f
)
376 struct rte_devargs
*devargs
;
378 fprintf(f
, "User device list:\n");
379 TAILQ_FOREACH(devargs
, &devargs_list
, next
) {
380 fprintf(f
, " [%s]: %s %s\n",
381 (devargs
->bus
? devargs
->bus
->name
: "??"),
382 devargs
->name
, devargs
->args
);
386 /* bus-aware rte_devargs iterator. */
388 rte_devargs_next(const char *busname
, const struct rte_devargs
*start
)
390 struct rte_devargs
*da
;
393 da
= TAILQ_NEXT(start
, next
);
395 da
= TAILQ_FIRST(&devargs_list
);
397 if (busname
== NULL
||
398 (strcmp(busname
, da
->bus
->name
) == 0))
400 da
= TAILQ_NEXT(da
, next
);