Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright(c) 2010-2018 Intel Corporation
3 : : */
4 : :
5 : : #include <string.h>
6 : : #include <inttypes.h>
7 : : #include <stdint.h>
8 : : #include <stdlib.h>
9 : : #include <stdio.h>
10 : : #include <sys/queue.h>
11 : : #include <sys/mman.h>
12 : : #include <sys/types.h>
13 : : #include <unistd.h>
14 : : #include <fcntl.h>
15 : :
16 : : #include <eal_export.h>
17 : : #include <rte_errno.h>
18 : : #include <bus_driver.h>
19 : : #include <rte_per_lcore.h>
20 : : #include <rte_memory.h>
21 : : #include <rte_memzone.h>
22 : : #include <rte_eal.h>
23 : : #include <rte_common.h>
24 : : #include <rte_devargs.h>
25 : : #include <rte_kvargs.h>
26 : : #include <rte_alarm.h>
27 : : #include <rte_string_fns.h>
28 : : #include <rte_debug.h>
29 : :
30 : : #include "rte_rawdev.h"
31 : : #include "rte_rawdev_pmd.h"
32 : : #include "bus_ifpga_driver.h"
33 : : #include "ifpga_logs.h"
34 : : #include "ifpga_common.h"
35 : :
36 : : /* Forward declaration to access Intel FPGA bus
37 : : * on which iFPGA devices are connected
38 : : */
39 : : static struct rte_bus rte_ifpga_bus;
40 : :
41 : : static TAILQ_HEAD(, rte_afu_device) ifpga_afu_dev_list =
42 : : TAILQ_HEAD_INITIALIZER(ifpga_afu_dev_list);
43 : : static TAILQ_HEAD(, rte_afu_driver) ifpga_afu_drv_list =
44 : : TAILQ_HEAD_INITIALIZER(ifpga_afu_drv_list);
45 : :
46 : :
47 : : /* register a ifpga bus based driver */
48 : : RTE_EXPORT_INTERNAL_SYMBOL(rte_ifpga_driver_register)
49 : 0 : void rte_ifpga_driver_register(struct rte_afu_driver *driver)
50 : : {
51 [ # # ]: 0 : RTE_VERIFY(driver);
52 : :
53 : 0 : TAILQ_INSERT_TAIL(&ifpga_afu_drv_list, driver, next);
54 : 0 : }
55 : :
56 : : /* un-register a fpga bus based driver */
57 : : RTE_EXPORT_INTERNAL_SYMBOL(rte_ifpga_driver_unregister)
58 : 0 : void rte_ifpga_driver_unregister(struct rte_afu_driver *driver)
59 : : {
60 [ # # ]: 0 : TAILQ_REMOVE(&ifpga_afu_drv_list, driver, next);
61 : 0 : }
62 : :
63 : : static struct rte_afu_device *
64 : : ifpga_find_afu_dev(const struct rte_rawdev *rdev,
65 : : const struct rte_afu_id *afu_id)
66 : : {
67 : : struct rte_afu_device *afu_dev = NULL;
68 : :
69 [ # # ]: 0 : TAILQ_FOREACH(afu_dev, &ifpga_afu_dev_list, next) {
70 [ # # ]: 0 : if (afu_dev->rawdev == rdev &&
71 : : !ifpga_afu_id_cmp(&afu_dev->id, afu_id))
72 : : return afu_dev;
73 : : }
74 : : return NULL;
75 : : }
76 : :
77 : : RTE_EXPORT_INTERNAL_SYMBOL(rte_ifpga_find_afu_by_name)
78 : : struct rte_afu_device *
79 : 0 : rte_ifpga_find_afu_by_name(const char *name)
80 : : {
81 : : struct rte_afu_device *afu_dev = NULL;
82 : :
83 [ # # ]: 0 : TAILQ_FOREACH(afu_dev, &ifpga_afu_dev_list, next) {
84 [ # # ]: 0 : if (!strcmp(afu_dev->device.name, name))
85 : 0 : return afu_dev;
86 : : }
87 : : return NULL;
88 : : }
89 : :
90 : : static const char * const valid_args[] = {
91 : : #define IFPGA_ARG_NAME "ifpga"
92 : : IFPGA_ARG_NAME,
93 : : #define IFPGA_ARG_PORT "port"
94 : : IFPGA_ARG_PORT,
95 : : #define IFPGA_AFU_BTS "afu_bts"
96 : : IFPGA_AFU_BTS,
97 : : NULL
98 : : };
99 : :
100 : : /*
101 : : * Scan the content of the FPGA bus, and the devices in the devices
102 : : * list
103 : : */
104 : : static struct rte_afu_device *
105 : 0 : ifpga_scan_one(struct rte_rawdev *rawdev,
106 : : struct rte_devargs *devargs)
107 : : {
108 : : struct rte_kvargs *kvlist = NULL;
109 : : struct rte_afu_device *afu_dev = NULL;
110 : : struct rte_afu_pr_conf afu_pr_conf;
111 : : int ret = 0;
112 : 0 : char *path = NULL;
113 : :
114 : : memset(&afu_pr_conf, 0, sizeof(struct rte_afu_pr_conf));
115 : :
116 : 0 : kvlist = rte_kvargs_parse(devargs->args, valid_args);
117 [ # # ]: 0 : if (!kvlist) {
118 : 0 : IFPGA_BUS_ERR("error when parsing param");
119 : 0 : goto end;
120 : : }
121 : :
122 [ # # ]: 0 : if (rte_kvargs_count(kvlist, IFPGA_ARG_PORT) == 1) {
123 [ # # ]: 0 : if (rte_kvargs_process(kvlist, IFPGA_ARG_PORT,
124 : : ifpga_get_integer32_arg,
125 : : &afu_pr_conf.afu_id.port) < 0) {
126 : 0 : IFPGA_BUS_ERR("error to parse %s", IFPGA_ARG_PORT);
127 : 0 : goto end;
128 : : }
129 : : } else {
130 : 0 : IFPGA_BUS_ERR("arg %s is mandatory for ifpga bus",
131 : : IFPGA_ARG_PORT);
132 : 0 : goto end;
133 : : }
134 : :
135 [ # # ]: 0 : if (rte_kvargs_count(kvlist, IFPGA_AFU_BTS) == 1) {
136 [ # # ]: 0 : if (rte_kvargs_process(kvlist, IFPGA_AFU_BTS,
137 : : ifpga_get_string_arg, &path) < 0) {
138 : 0 : IFPGA_BUS_ERR("Failed to parse %s", IFPGA_AFU_BTS);
139 : 0 : goto end;
140 : : }
141 : 0 : afu_pr_conf.pr_enable = 1;
142 : 0 : strlcpy(afu_pr_conf.bs_path, path,
143 : : sizeof(afu_pr_conf.bs_path));
144 : : } else {
145 : 0 : afu_pr_conf.pr_enable = 0;
146 : : }
147 : :
148 : 0 : afu_pr_conf.afu_id.uuid.uuid_low = 0;
149 : 0 : afu_pr_conf.afu_id.uuid.uuid_high = 0;
150 : :
151 [ # # ]: 0 : if (ifpga_find_afu_dev(rawdev, &afu_pr_conf.afu_id))
152 : 0 : goto end;
153 : :
154 : 0 : afu_dev = calloc(1, sizeof(*afu_dev));
155 [ # # ]: 0 : if (!afu_dev)
156 : 0 : goto end;
157 : :
158 : 0 : afu_dev->device.bus = &rte_ifpga_bus;
159 : 0 : afu_dev->device.devargs = devargs;
160 : 0 : afu_dev->device.numa_node = SOCKET_ID_ANY;
161 : 0 : afu_dev->device.name = devargs->name;
162 : 0 : afu_dev->rawdev = rawdev;
163 : 0 : afu_dev->id.uuid.uuid_low = 0;
164 : 0 : afu_dev->id.uuid.uuid_high = 0;
165 : 0 : afu_dev->id.port = afu_pr_conf.afu_id.port;
166 : :
167 : : /* Allocate interrupt instance */
168 : 0 : afu_dev->intr_handle =
169 : 0 : rte_intr_instance_alloc(RTE_INTR_INSTANCE_F_PRIVATE);
170 [ # # ]: 0 : if (afu_dev->intr_handle == NULL) {
171 : 0 : IFPGA_BUS_ERR("Failed to allocate intr handle");
172 : 0 : goto end;
173 : : }
174 : :
175 [ # # # # ]: 0 : if (rawdev->dev_ops && rawdev->dev_ops->dev_info_get)
176 : 0 : rawdev->dev_ops->dev_info_get(rawdev, afu_dev, sizeof(*afu_dev));
177 : :
178 [ # # ]: 0 : if (rawdev->dev_ops &&
179 [ # # # # ]: 0 : rawdev->dev_ops->dev_start &&
180 : 0 : rawdev->dev_ops->dev_start(rawdev))
181 : 0 : goto end;
182 : :
183 [ # # ]: 0 : if (rawdev->dev_ops &&
184 [ # # # # ]: 0 : rawdev->dev_ops->firmware_load &&
185 : 0 : rawdev->dev_ops->firmware_load(rawdev,
186 : : &afu_pr_conf)){
187 : 0 : IFPGA_BUS_ERR("firmware load error %d", ret);
188 : 0 : goto end;
189 : : }
190 : 0 : afu_dev->id.uuid.uuid_low = afu_pr_conf.afu_id.uuid.uuid_low;
191 : 0 : afu_dev->id.uuid.uuid_high = afu_pr_conf.afu_id.uuid.uuid_high;
192 : :
193 : 0 : rte_kvargs_free(kvlist);
194 : 0 : free(path);
195 : 0 : return afu_dev;
196 : :
197 : 0 : end:
198 : 0 : rte_kvargs_free(kvlist);
199 : 0 : free(path);
200 [ # # ]: 0 : if (afu_dev) {
201 : 0 : rte_intr_instance_free(afu_dev->intr_handle);
202 : 0 : free(afu_dev);
203 : : }
204 : :
205 : : return NULL;
206 : : }
207 : :
208 : : /*
209 : : * Scan the content of the FPGA bus, and the devices in the devices
210 : : * list
211 : : */
212 : : static int
213 : 185 : ifpga_scan(void)
214 : : {
215 : : struct rte_devargs *devargs;
216 : : struct rte_kvargs *kvlist = NULL;
217 : : struct rte_rawdev *rawdev = NULL;
218 : 185 : char *name = NULL;
219 : : char name1[RTE_RAWDEV_NAME_MAX_LEN];
220 : : struct rte_afu_device *afu_dev = NULL;
221 : :
222 : : /* for FPGA devices we scan the devargs_list populated via cmdline */
223 [ - + ]: 185 : RTE_EAL_DEVARGS_FOREACH(IFPGA_ARG_NAME, devargs) {
224 [ # # ]: 0 : if (devargs->bus != &rte_ifpga_bus)
225 : 0 : continue;
226 : :
227 : 0 : kvlist = rte_kvargs_parse(devargs->args, valid_args);
228 [ # # ]: 0 : if (!kvlist) {
229 : 0 : IFPGA_BUS_ERR("error when parsing param");
230 : 0 : goto end;
231 : : }
232 : :
233 [ # # ]: 0 : if (rte_kvargs_count(kvlist, IFPGA_ARG_NAME) == 1) {
234 [ # # ]: 0 : if (rte_kvargs_process(kvlist, IFPGA_ARG_NAME,
235 : : ifpga_get_string_arg, &name) < 0) {
236 : 0 : IFPGA_BUS_ERR("error to parse %s",
237 : : IFPGA_ARG_NAME);
238 : 0 : goto end;
239 : : }
240 : : } else {
241 : 0 : IFPGA_BUS_ERR("arg %s is mandatory for ifpga bus",
242 : : IFPGA_ARG_NAME);
243 : 0 : goto end;
244 : : }
245 : :
246 : : memset(name1, 0, sizeof(name1));
247 [ # # ]: 0 : snprintf(name1, RTE_RAWDEV_NAME_MAX_LEN, "IFPGA:%s", name);
248 : :
249 : 0 : rawdev = rte_rawdev_pmd_get_named_dev(name1);
250 [ # # ]: 0 : if (!rawdev)
251 : 0 : goto end;
252 : :
253 : 0 : afu_dev = ifpga_scan_one(rawdev, devargs);
254 [ # # ]: 0 : if (afu_dev != NULL)
255 : 0 : TAILQ_INSERT_TAIL(&ifpga_afu_dev_list, afu_dev, next);
256 : : }
257 : :
258 : 185 : end:
259 : 185 : rte_kvargs_free(kvlist);
260 : 185 : free(name);
261 : :
262 : 185 : return 0;
263 : : }
264 : :
265 : : /*
266 : : * Match the AFU Driver and AFU Device using the ID Table
267 : : */
268 : : static int
269 : : rte_afu_match(const struct rte_afu_driver *afu_drv,
270 : : const struct rte_afu_device *afu_dev)
271 : : {
272 : : const struct rte_afu_uuid *id_table;
273 : :
274 : 0 : for (id_table = afu_drv->id_table;
275 [ # # # # ]: 0 : ((id_table->uuid_low != 0) && (id_table->uuid_high != 0));
276 : 0 : id_table++) {
277 : : /* check if device's identifiers match the driver's ones */
278 [ # # ]: 0 : if ((id_table->uuid_low != afu_dev->id.uuid.uuid_low) ||
279 : : id_table->uuid_high !=
280 [ # # ]: 0 : afu_dev->id.uuid.uuid_high)
281 : : continue;
282 : :
283 : : return 1;
284 : : }
285 : :
286 : : return 0;
287 : : }
288 : :
289 : : static int
290 : 0 : ifpga_probe_one_driver(struct rte_afu_driver *drv,
291 : : struct rte_afu_device *afu_dev)
292 : : {
293 : : int ret;
294 : :
295 [ # # ]: 0 : if (!rte_afu_match(drv, afu_dev))
296 : : /* Match of device and driver failed */
297 : : return 1;
298 : :
299 : : /* reference driver structure */
300 : 0 : afu_dev->driver = drv;
301 : :
302 : : /* call the driver probe() function */
303 : 0 : ret = drv->probe(afu_dev);
304 [ # # ]: 0 : if (ret)
305 : 0 : afu_dev->driver = NULL;
306 : : else
307 : 0 : afu_dev->device.driver = &drv->driver;
308 : :
309 : : return ret;
310 : : }
311 : :
312 : : static int
313 : 0 : ifpga_probe_all_drivers(struct rte_afu_device *afu_dev)
314 : : {
315 : : struct rte_afu_driver *drv = NULL;
316 : : int ret = 0;
317 : :
318 [ # # ]: 0 : if (afu_dev == NULL)
319 : : return -1;
320 : :
321 : : /* Check if a driver is already loaded */
322 [ # # ]: 0 : if (rte_dev_is_probed(&afu_dev->device)) {
323 : 0 : IFPGA_BUS_DEBUG("Device %s is already probed",
324 : : rte_ifpga_device_name(afu_dev));
325 : 0 : return -EEXIST;
326 : : }
327 : :
328 [ # # ]: 0 : TAILQ_FOREACH(drv, &ifpga_afu_drv_list, next) {
329 : 0 : ret = ifpga_probe_one_driver(drv, afu_dev);
330 [ # # ]: 0 : if (ret < 0)
331 : : /* negative value is an error */
332 : 0 : return ret;
333 [ # # ]: 0 : if (ret > 0)
334 : : /* positive value means driver doesn't support it */
335 : : continue;
336 : : return 0;
337 : : }
338 [ # # # # ]: 0 : if ((ret > 0) && (afu_dev->driver == NULL))
339 : : return 0;
340 : : else
341 : 0 : return ret;
342 : : }
343 : :
344 : : /*
345 : : * Scan the content of the Intel FPGA bus, and call the probe() function for
346 : : * all registered drivers that have a matching entry in its id_table
347 : : * for discovered devices.
348 : : */
349 : : static int
350 : 180 : ifpga_probe(void)
351 : : {
352 : : struct rte_afu_device *afu_dev = NULL;
353 : : int ret = 0;
354 : :
355 [ - + ]: 180 : TAILQ_FOREACH(afu_dev, &ifpga_afu_dev_list, next) {
356 : 0 : ret = ifpga_probe_all_drivers(afu_dev);
357 [ # # ]: 0 : if (ret == -EEXIST)
358 : 0 : continue;
359 [ # # ]: 0 : if (ret < 0)
360 : 0 : IFPGA_BUS_ERR("failed to initialize %s device",
361 : : rte_ifpga_device_name(afu_dev));
362 : : }
363 : :
364 : 180 : return ret;
365 : : }
366 : :
367 : : /*
368 : : * Cleanup the content of the Intel FPGA bus, and call the remove() function
369 : : * for all registered devices.
370 : : */
371 : : static int
372 : 252 : ifpga_cleanup(void)
373 : : {
374 : : struct rte_afu_device *afu_dev, *tmp_dev;
375 : : int error = 0;
376 : :
377 [ - + ]: 252 : RTE_TAILQ_FOREACH_SAFE(afu_dev, &ifpga_afu_dev_list, next, tmp_dev) {
378 : 0 : struct rte_afu_driver *drv = afu_dev->driver;
379 : : int ret = 0;
380 : :
381 [ # # # # ]: 0 : if (drv == NULL || drv->remove == NULL)
382 : 0 : goto free;
383 : :
384 : 0 : ret = drv->remove(afu_dev);
385 [ # # ]: 0 : if (ret < 0) {
386 : 0 : rte_errno = errno;
387 : : error = -1;
388 : : }
389 : 0 : afu_dev->driver = NULL;
390 : 0 : afu_dev->device.driver = NULL;
391 : :
392 : 0 : free:
393 [ # # ]: 0 : TAILQ_REMOVE(&ifpga_afu_dev_list, afu_dev, next);
394 : 0 : rte_devargs_remove(afu_dev->device.devargs);
395 : 0 : rte_intr_instance_free(afu_dev->intr_handle);
396 : 0 : free(afu_dev);
397 : : }
398 : :
399 : 252 : return error;
400 : : }
401 : :
402 : : static int
403 : 0 : ifpga_plug(struct rte_device *dev)
404 : : {
405 : 0 : return ifpga_probe_all_drivers(RTE_DEV_TO_AFU(dev));
406 : : }
407 : :
408 : : static int
409 [ # # ]: 0 : ifpga_remove_driver(struct rte_afu_device *afu_dev)
410 : : {
411 : : const char *name;
412 : :
413 : : name = rte_ifpga_device_name(afu_dev);
414 [ # # ]: 0 : if (afu_dev->driver == NULL) {
415 : 0 : IFPGA_BUS_DEBUG("no driver attach to device %s", name);
416 : 0 : return 1;
417 : : }
418 : :
419 : 0 : return afu_dev->driver->remove(afu_dev);
420 : : }
421 : :
422 : : static int
423 : 0 : ifpga_unplug(struct rte_device *dev)
424 : : {
425 : : struct rte_afu_device *afu_dev = NULL;
426 : : int ret;
427 : :
428 [ # # ]: 0 : if (dev == NULL)
429 : : return -EINVAL;
430 : :
431 : 0 : afu_dev = RTE_DEV_TO_AFU(dev);
432 [ # # ]: 0 : if (!afu_dev)
433 : : return -ENOENT;
434 : :
435 : 0 : ret = ifpga_remove_driver(afu_dev);
436 [ # # ]: 0 : if (ret)
437 : : return ret;
438 : :
439 [ # # ]: 0 : TAILQ_REMOVE(&ifpga_afu_dev_list, afu_dev, next);
440 : :
441 : 0 : rte_devargs_remove(dev->devargs);
442 : 0 : rte_intr_instance_free(afu_dev->intr_handle);
443 : 0 : free(afu_dev);
444 : 0 : return 0;
445 : :
446 : : }
447 : :
448 : : static struct rte_device *
449 : 0 : ifpga_find_device(const struct rte_device *start,
450 : : rte_dev_cmp_t cmp, const void *data)
451 : : {
452 : : struct rte_afu_device *afu_dev;
453 : :
454 [ # # ]: 0 : TAILQ_FOREACH(afu_dev, &ifpga_afu_dev_list, next) {
455 [ # # # # ]: 0 : if (start && &afu_dev->device == start) {
456 : : start = NULL;
457 : 0 : continue;
458 : : }
459 [ # # ]: 0 : if (cmp(&afu_dev->device, data) == 0)
460 : 0 : return &afu_dev->device;
461 : : }
462 : :
463 : : return NULL;
464 : : }
465 : : static int
466 : 37 : ifpga_parse(const char *name, void *addr)
467 : : {
468 : : int *out = addr;
469 : : struct rte_rawdev *rawdev = NULL;
470 : : char rawdev_name[RTE_RAWDEV_NAME_MAX_LEN];
471 : : char *c1 = NULL;
472 : : char *c2 = NULL;
473 [ - + ]: 37 : int port = IFPGA_BUS_DEV_PORT_MAX;
474 : : char str_port[8];
475 : : int str_port_len = 0;
476 : : int ret;
477 : :
478 : : memset(str_port, 0, 8);
479 : 37 : c1 = strchr(name, '|');
480 [ - + ]: 37 : if (c1 != NULL) {
481 : 0 : str_port_len = c1 - name;
482 : 0 : c2 = c1 + 1;
483 : : }
484 : :
485 [ - + ]: 37 : if (str_port_len < 8 &&
486 : : str_port_len > 0) {
487 [ # # ]: 0 : memcpy(str_port, name, str_port_len);
488 : 0 : ret = sscanf(str_port, "%d", &port);
489 [ # # ]: 0 : if (ret == -1)
490 : : return 0;
491 : : }
492 : :
493 : : memset(rawdev_name, 0, sizeof(rawdev_name));
494 : : snprintf(rawdev_name, RTE_RAWDEV_NAME_MAX_LEN, "IFPGA:%s", c2);
495 : 37 : rawdev = rte_rawdev_pmd_get_named_dev(rawdev_name);
496 : :
497 [ - + ]: 37 : if ((port < IFPGA_BUS_DEV_PORT_MAX) &&
498 : 0 : rawdev &&
499 [ # # ]: 0 : (addr != NULL))
500 : 0 : *out = port;
501 : :
502 [ - + - - ]: 37 : if ((port < IFPGA_BUS_DEV_PORT_MAX) &&
503 : : rawdev)
504 : : return 0;
505 : : else
506 : 37 : return 1;
507 : : }
508 : :
509 : : static struct rte_bus rte_ifpga_bus = {
510 : : .scan = ifpga_scan,
511 : : .probe = ifpga_probe,
512 : : .cleanup = ifpga_cleanup,
513 : : .find_device = ifpga_find_device,
514 : : .plug = ifpga_plug,
515 : : .unplug = ifpga_unplug,
516 : : .parse = ifpga_parse,
517 : : };
518 : :
519 : 252 : RTE_REGISTER_BUS(IFPGA_BUS_NAME, rte_ifpga_bus);
520 [ - + ]: 252 : RTE_LOG_REGISTER_DEFAULT(ifpga_bus_logtype, NOTICE);
|