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