New upstream version 18.08
[deb_dpdk.git] / drivers / bus / vdev / vdev.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2016 RehiveTech. All rights reserved.
3  */
4
5 #include <string.h>
6 #include <inttypes.h>
7 #include <stdio.h>
8 #include <stdlib.h>
9 #include <stdint.h>
10 #include <stdbool.h>
11 #include <sys/queue.h>
12
13 #include <rte_eal.h>
14 #include <rte_dev.h>
15 #include <rte_bus.h>
16 #include <rte_common.h>
17 #include <rte_devargs.h>
18 #include <rte_memory.h>
19 #include <rte_tailq.h>
20 #include <rte_spinlock.h>
21 #include <rte_string_fns.h>
22 #include <rte_errno.h>
23
24 #include "rte_bus_vdev.h"
25 #include "vdev_logs.h"
26
27 #define VDEV_MP_KEY     "bus_vdev_mp"
28
29 int vdev_logtype_bus;
30
31 /* Forward declare to access virtual bus name */
32 static struct rte_bus rte_vdev_bus;
33
34 /** Double linked list of virtual device drivers. */
35 TAILQ_HEAD(vdev_device_list, rte_vdev_device);
36
37 static struct vdev_device_list vdev_device_list =
38         TAILQ_HEAD_INITIALIZER(vdev_device_list);
39 /* The lock needs to be recursive because a vdev can manage another vdev. */
40 static rte_spinlock_recursive_t vdev_device_list_lock =
41         RTE_SPINLOCK_RECURSIVE_INITIALIZER;
42
43 struct vdev_driver_list vdev_driver_list =
44         TAILQ_HEAD_INITIALIZER(vdev_driver_list);
45
46 struct vdev_custom_scan {
47         TAILQ_ENTRY(vdev_custom_scan) next;
48         rte_vdev_scan_callback callback;
49         void *user_arg;
50 };
51 TAILQ_HEAD(vdev_custom_scans, vdev_custom_scan);
52 static struct vdev_custom_scans vdev_custom_scans =
53         TAILQ_HEAD_INITIALIZER(vdev_custom_scans);
54 static rte_spinlock_t vdev_custom_scan_lock = RTE_SPINLOCK_INITIALIZER;
55
56 /* register a driver */
57 void
58 rte_vdev_register(struct rte_vdev_driver *driver)
59 {
60         TAILQ_INSERT_TAIL(&vdev_driver_list, driver, next);
61 }
62
63 /* unregister a driver */
64 void
65 rte_vdev_unregister(struct rte_vdev_driver *driver)
66 {
67         TAILQ_REMOVE(&vdev_driver_list, driver, next);
68 }
69
70 int
71 rte_vdev_add_custom_scan(rte_vdev_scan_callback callback, void *user_arg)
72 {
73         struct vdev_custom_scan *custom_scan;
74
75         rte_spinlock_lock(&vdev_custom_scan_lock);
76
77         /* check if already registered */
78         TAILQ_FOREACH(custom_scan, &vdev_custom_scans, next) {
79                 if (custom_scan->callback == callback &&
80                                 custom_scan->user_arg == user_arg)
81                         break;
82         }
83
84         if (custom_scan == NULL) {
85                 custom_scan = malloc(sizeof(struct vdev_custom_scan));
86                 if (custom_scan != NULL) {
87                         custom_scan->callback = callback;
88                         custom_scan->user_arg = user_arg;
89                         TAILQ_INSERT_TAIL(&vdev_custom_scans, custom_scan, next);
90                 }
91         }
92
93         rte_spinlock_unlock(&vdev_custom_scan_lock);
94
95         return (custom_scan == NULL) ? -1 : 0;
96 }
97
98 int
99 rte_vdev_remove_custom_scan(rte_vdev_scan_callback callback, void *user_arg)
100 {
101         struct vdev_custom_scan *custom_scan, *tmp_scan;
102
103         rte_spinlock_lock(&vdev_custom_scan_lock);
104         TAILQ_FOREACH_SAFE(custom_scan, &vdev_custom_scans, next, tmp_scan) {
105                 if (custom_scan->callback != callback ||
106                                 (custom_scan->user_arg != (void *)-1 &&
107                                 custom_scan->user_arg != user_arg))
108                         continue;
109                 TAILQ_REMOVE(&vdev_custom_scans, custom_scan, next);
110                 free(custom_scan);
111         }
112         rte_spinlock_unlock(&vdev_custom_scan_lock);
113
114         return 0;
115 }
116
117 static int
118 vdev_parse(const char *name, void *addr)
119 {
120         struct rte_vdev_driver **out = addr;
121         struct rte_vdev_driver *driver = NULL;
122
123         TAILQ_FOREACH(driver, &vdev_driver_list, next) {
124                 if (strncmp(driver->driver.name, name,
125                             strlen(driver->driver.name)) == 0)
126                         break;
127                 if (driver->driver.alias &&
128                     strncmp(driver->driver.alias, name,
129                             strlen(driver->driver.alias)) == 0)
130                         break;
131         }
132         if (driver != NULL &&
133             addr != NULL)
134                 *out = driver;
135         return driver == NULL;
136 }
137
138 static int
139 vdev_probe_all_drivers(struct rte_vdev_device *dev)
140 {
141         const char *name;
142         struct rte_vdev_driver *driver;
143         int ret;
144
145         name = rte_vdev_device_name(dev);
146
147         VDEV_LOG(DEBUG, "Search driver %s to probe device %s", name,
148                 rte_vdev_device_name(dev));
149
150         if (vdev_parse(name, &driver))
151                 return -1;
152         dev->device.driver = &driver->driver;
153         ret = driver->probe(dev);
154         if (ret)
155                 dev->device.driver = NULL;
156         return ret;
157 }
158
159 /* The caller shall be responsible for thread-safe */
160 static struct rte_vdev_device *
161 find_vdev(const char *name)
162 {
163         struct rte_vdev_device *dev;
164
165         if (!name)
166                 return NULL;
167
168         TAILQ_FOREACH(dev, &vdev_device_list, next) {
169                 const char *devname = rte_vdev_device_name(dev);
170
171                 if (!strcmp(devname, name))
172                         return dev;
173         }
174
175         return NULL;
176 }
177
178 static struct rte_devargs *
179 alloc_devargs(const char *name, const char *args)
180 {
181         struct rte_devargs *devargs;
182         int ret;
183
184         devargs = calloc(1, sizeof(*devargs));
185         if (!devargs)
186                 return NULL;
187
188         devargs->bus = &rte_vdev_bus;
189         if (args)
190                 devargs->args = strdup(args);
191         else
192                 devargs->args = strdup("");
193
194         ret = snprintf(devargs->name, sizeof(devargs->name), "%s", name);
195         if (ret < 0 || ret >= (int)sizeof(devargs->name)) {
196                 free(devargs->args);
197                 free(devargs);
198                 return NULL;
199         }
200
201         return devargs;
202 }
203
204 static int
205 insert_vdev(const char *name, const char *args, struct rte_vdev_device **p_dev)
206 {
207         struct rte_vdev_device *dev;
208         struct rte_devargs *devargs;
209         int ret;
210
211         if (name == NULL)
212                 return -EINVAL;
213
214         devargs = alloc_devargs(name, args);
215         if (!devargs)
216                 return -ENOMEM;
217
218         dev = calloc(1, sizeof(*dev));
219         if (!dev) {
220                 ret = -ENOMEM;
221                 goto fail;
222         }
223
224         dev->device.devargs = devargs;
225         dev->device.numa_node = SOCKET_ID_ANY;
226         dev->device.name = devargs->name;
227
228         if (find_vdev(name)) {
229                 ret = -EEXIST;
230                 goto fail;
231         }
232
233         TAILQ_INSERT_TAIL(&vdev_device_list, dev, next);
234         rte_devargs_insert(devargs);
235
236         if (p_dev)
237                 *p_dev = dev;
238
239         return 0;
240 fail:
241         free(devargs->args);
242         free(devargs);
243         free(dev);
244         return ret;
245 }
246
247 int
248 rte_vdev_init(const char *name, const char *args)
249 {
250         struct rte_vdev_device *dev;
251         struct rte_devargs *devargs;
252         int ret;
253
254         rte_spinlock_recursive_lock(&vdev_device_list_lock);
255         ret = insert_vdev(name, args, &dev);
256         if (ret == 0) {
257                 ret = vdev_probe_all_drivers(dev);
258                 if (ret) {
259                         if (ret > 0)
260                                 VDEV_LOG(ERR, "no driver found for %s", name);
261                         /* If fails, remove it from vdev list */
262                         devargs = dev->device.devargs;
263                         TAILQ_REMOVE(&vdev_device_list, dev, next);
264                         rte_devargs_remove(devargs->bus->name, devargs->name);
265                         free(dev);
266                 }
267         }
268         rte_spinlock_recursive_unlock(&vdev_device_list_lock);
269         return ret;
270 }
271
272 static int
273 vdev_remove_driver(struct rte_vdev_device *dev)
274 {
275         const char *name = rte_vdev_device_name(dev);
276         const struct rte_vdev_driver *driver;
277
278         if (!dev->device.driver) {
279                 VDEV_LOG(DEBUG, "no driver attach to device %s", name);
280                 return 1;
281         }
282
283         driver = container_of(dev->device.driver, const struct rte_vdev_driver,
284                 driver);
285         return driver->remove(dev);
286 }
287
288 int
289 rte_vdev_uninit(const char *name)
290 {
291         struct rte_vdev_device *dev;
292         struct rte_devargs *devargs;
293         int ret;
294
295         if (name == NULL)
296                 return -EINVAL;
297
298         rte_spinlock_recursive_lock(&vdev_device_list_lock);
299
300         dev = find_vdev(name);
301         if (!dev) {
302                 ret = -ENOENT;
303                 goto unlock;
304         }
305
306         ret = vdev_remove_driver(dev);
307         if (ret)
308                 goto unlock;
309
310         TAILQ_REMOVE(&vdev_device_list, dev, next);
311         devargs = dev->device.devargs;
312         rte_devargs_remove(devargs->bus->name, devargs->name);
313         free(dev);
314
315 unlock:
316         rte_spinlock_recursive_unlock(&vdev_device_list_lock);
317         return ret;
318 }
319
320 struct vdev_param {
321 #define VDEV_SCAN_REQ   1
322 #define VDEV_SCAN_ONE   2
323 #define VDEV_SCAN_REP   3
324         int type;
325         int num;
326         char name[RTE_DEV_NAME_MAX_LEN];
327 };
328
329 static int vdev_plug(struct rte_device *dev);
330
331 /**
332  * This function works as the action for both primary and secondary process
333  * for static vdev discovery when a secondary process is booting.
334  *
335  * step 1, secondary process sends a sync request to ask for vdev in primary;
336  * step 2, primary process receives the request, and send vdevs one by one;
337  * step 3, primary process sends back reply, which indicates how many vdevs
338  * are sent.
339  */
340 static int
341 vdev_action(const struct rte_mp_msg *mp_msg, const void *peer)
342 {
343         struct rte_vdev_device *dev;
344         struct rte_mp_msg mp_resp;
345         struct vdev_param *ou = (struct vdev_param *)&mp_resp.param;
346         const struct vdev_param *in = (const struct vdev_param *)mp_msg->param;
347         const char *devname;
348         int num;
349
350         strlcpy(mp_resp.name, VDEV_MP_KEY, sizeof(mp_resp.name));
351         mp_resp.len_param = sizeof(*ou);
352         mp_resp.num_fds = 0;
353
354         switch (in->type) {
355         case VDEV_SCAN_REQ:
356                 ou->type = VDEV_SCAN_ONE;
357                 ou->num = 1;
358                 num = 0;
359
360                 rte_spinlock_recursive_lock(&vdev_device_list_lock);
361                 TAILQ_FOREACH(dev, &vdev_device_list, next) {
362                         devname = rte_vdev_device_name(dev);
363                         if (strlen(devname) == 0) {
364                                 VDEV_LOG(INFO, "vdev with no name is not sent");
365                                 continue;
366                         }
367                         VDEV_LOG(INFO, "send vdev, %s", devname);
368                         strlcpy(ou->name, devname, RTE_DEV_NAME_MAX_LEN);
369                         if (rte_mp_sendmsg(&mp_resp) < 0)
370                                 VDEV_LOG(ERR, "send vdev, %s, failed, %s",
371                                          devname, strerror(rte_errno));
372                         num++;
373                 }
374                 rte_spinlock_recursive_unlock(&vdev_device_list_lock);
375
376                 ou->type = VDEV_SCAN_REP;
377                 ou->num = num;
378                 if (rte_mp_reply(&mp_resp, peer) < 0)
379                         VDEV_LOG(ERR, "Failed to reply a scan request");
380                 break;
381         case VDEV_SCAN_ONE:
382                 VDEV_LOG(INFO, "receive vdev, %s", in->name);
383                 if (insert_vdev(in->name, NULL, NULL) < 0)
384                         VDEV_LOG(ERR, "failed to add vdev, %s", in->name);
385                 break;
386         default:
387                 VDEV_LOG(ERR, "vdev cannot recognize this message");
388         }
389
390         return 0;
391 }
392
393 static int
394 vdev_scan(void)
395 {
396         struct rte_vdev_device *dev;
397         struct rte_devargs *devargs;
398         struct vdev_custom_scan *custom_scan;
399
400         if (rte_mp_action_register(VDEV_MP_KEY, vdev_action) < 0 &&
401             rte_errno != EEXIST) {
402                 VDEV_LOG(ERR, "Failed to add vdev mp action");
403                 return -1;
404         }
405
406         if (rte_eal_process_type() == RTE_PROC_SECONDARY) {
407                 struct rte_mp_msg mp_req, *mp_rep;
408                 struct rte_mp_reply mp_reply;
409                 struct timespec ts = {.tv_sec = 5, .tv_nsec = 0};
410                 struct vdev_param *req = (struct vdev_param *)mp_req.param;
411                 struct vdev_param *resp;
412
413                 strlcpy(mp_req.name, VDEV_MP_KEY, sizeof(mp_req.name));
414                 mp_req.len_param = sizeof(*req);
415                 mp_req.num_fds = 0;
416                 req->type = VDEV_SCAN_REQ;
417                 if (rte_mp_request_sync(&mp_req, &mp_reply, &ts) == 0 &&
418                     mp_reply.nb_received == 1) {
419                         mp_rep = &mp_reply.msgs[0];
420                         resp = (struct vdev_param *)mp_rep->param;
421                         VDEV_LOG(INFO, "Received %d vdevs", resp->num);
422                 } else
423                         VDEV_LOG(ERR, "Failed to request vdev from primary");
424
425                 /* Fall through to allow private vdevs in secondary process */
426         }
427
428         /* call custom scan callbacks if any */
429         rte_spinlock_lock(&vdev_custom_scan_lock);
430         TAILQ_FOREACH(custom_scan, &vdev_custom_scans, next) {
431                 if (custom_scan->callback != NULL)
432                         /*
433                          * the callback should update devargs list
434                          * by calling rte_devargs_insert() with
435                          *     devargs.bus = rte_bus_find_by_name("vdev");
436                          *     devargs.type = RTE_DEVTYPE_VIRTUAL;
437                          *     devargs.policy = RTE_DEV_WHITELISTED;
438                          */
439                         custom_scan->callback(custom_scan->user_arg);
440         }
441         rte_spinlock_unlock(&vdev_custom_scan_lock);
442
443         /* for virtual devices we scan the devargs_list populated via cmdline */
444         RTE_EAL_DEVARGS_FOREACH("vdev", devargs) {
445
446                 dev = calloc(1, sizeof(*dev));
447                 if (!dev)
448                         return -1;
449
450                 rte_spinlock_recursive_lock(&vdev_device_list_lock);
451
452                 if (find_vdev(devargs->name)) {
453                         rte_spinlock_recursive_unlock(&vdev_device_list_lock);
454                         free(dev);
455                         continue;
456                 }
457
458                 dev->device.devargs = devargs;
459                 dev->device.numa_node = SOCKET_ID_ANY;
460                 dev->device.name = devargs->name;
461
462                 TAILQ_INSERT_TAIL(&vdev_device_list, dev, next);
463
464                 rte_spinlock_recursive_unlock(&vdev_device_list_lock);
465         }
466
467         return 0;
468 }
469
470 static int
471 vdev_probe(void)
472 {
473         struct rte_vdev_device *dev;
474         int ret = 0;
475
476         /* call the init function for each virtual device */
477         TAILQ_FOREACH(dev, &vdev_device_list, next) {
478                 /* we don't use the vdev lock here, as it's only used in DPDK
479                  * initialization; and we don't want to hold such a lock when
480                  * we call each driver probe.
481                  */
482
483                 if (dev->device.driver)
484                         continue;
485
486                 if (vdev_probe_all_drivers(dev)) {
487                         VDEV_LOG(ERR, "failed to initialize %s device",
488                                 rte_vdev_device_name(dev));
489                         ret = -1;
490                 }
491         }
492
493         return ret;
494 }
495
496 static struct rte_device *
497 vdev_find_device(const struct rte_device *start, rte_dev_cmp_t cmp,
498                  const void *data)
499 {
500         const struct rte_vdev_device *vstart;
501         struct rte_vdev_device *dev;
502
503         rte_spinlock_recursive_lock(&vdev_device_list_lock);
504         if (start != NULL) {
505                 vstart = RTE_DEV_TO_VDEV_CONST(start);
506                 dev = TAILQ_NEXT(vstart, next);
507         } else {
508                 dev = TAILQ_FIRST(&vdev_device_list);
509         }
510         while (dev != NULL) {
511                 if (cmp(&dev->device, data) == 0)
512                         break;
513                 dev = TAILQ_NEXT(dev, next);
514         }
515         rte_spinlock_recursive_unlock(&vdev_device_list_lock);
516
517         return dev ? &dev->device : NULL;
518 }
519
520 static int
521 vdev_plug(struct rte_device *dev)
522 {
523         return vdev_probe_all_drivers(RTE_DEV_TO_VDEV(dev));
524 }
525
526 static int
527 vdev_unplug(struct rte_device *dev)
528 {
529         return rte_vdev_uninit(dev->name);
530 }
531
532 static struct rte_bus rte_vdev_bus = {
533         .scan = vdev_scan,
534         .probe = vdev_probe,
535         .find_device = vdev_find_device,
536         .plug = vdev_plug,
537         .unplug = vdev_unplug,
538         .parse = vdev_parse,
539 };
540
541 RTE_REGISTER_BUS(vdev, rte_vdev_bus);
542
543 RTE_INIT(vdev_init_log)
544 {
545         vdev_logtype_bus = rte_log_register("bus.vdev");
546         if (vdev_logtype_bus >= 0)
547                 rte_log_set_level(vdev_logtype_bus, RTE_LOG_NOTICE);
548 }