xref: /dpdk/drivers/bus/ifpga/ifpga_bus.c (revision f665790a5dbad7b645ff46f31d65e977324e7bfc)
105fa3d4aSRosen Xu /* SPDX-License-Identifier: BSD-3-Clause
205fa3d4aSRosen Xu  * Copyright(c) 2010-2018 Intel Corporation
305fa3d4aSRosen Xu  */
405fa3d4aSRosen Xu 
505fa3d4aSRosen Xu #include <string.h>
605fa3d4aSRosen Xu #include <inttypes.h>
705fa3d4aSRosen Xu #include <stdint.h>
805fa3d4aSRosen Xu #include <stdlib.h>
905fa3d4aSRosen Xu #include <stdio.h>
1005fa3d4aSRosen Xu #include <sys/queue.h>
1105fa3d4aSRosen Xu #include <sys/mman.h>
1205fa3d4aSRosen Xu #include <sys/types.h>
1305fa3d4aSRosen Xu #include <unistd.h>
1405fa3d4aSRosen Xu #include <fcntl.h>
1505fa3d4aSRosen Xu 
1605fa3d4aSRosen Xu #include <rte_errno.h>
17a04322f6SDavid Marchand #include <bus_driver.h>
1805fa3d4aSRosen Xu #include <rte_per_lcore.h>
1905fa3d4aSRosen Xu #include <rte_memory.h>
2005fa3d4aSRosen Xu #include <rte_memzone.h>
2105fa3d4aSRosen Xu #include <rte_eal.h>
2205fa3d4aSRosen Xu #include <rte_common.h>
2305fa3d4aSRosen Xu #include <rte_devargs.h>
2405fa3d4aSRosen Xu #include <rte_kvargs.h>
2505fa3d4aSRosen Xu #include <rte_alarm.h>
264c807894SPablo de Lara #include <rte_string_fns.h>
2761669ecbSDavid Christensen #include <rte_debug.h>
2805fa3d4aSRosen Xu 
2905fa3d4aSRosen Xu #include "rte_rawdev.h"
3005fa3d4aSRosen Xu #include "rte_rawdev_pmd.h"
31925c074eSDavid Marchand #include "bus_ifpga_driver.h"
3205fa3d4aSRosen Xu #include "ifpga_logs.h"
3305fa3d4aSRosen Xu #include "ifpga_common.h"
3405fa3d4aSRosen Xu 
3505fa3d4aSRosen Xu /* Forward declaration to access Intel FPGA bus
3605fa3d4aSRosen Xu  * on which iFPGA devices are connected
3705fa3d4aSRosen Xu  */
3805fa3d4aSRosen Xu static struct rte_bus rte_ifpga_bus;
3905fa3d4aSRosen Xu 
40925c074eSDavid Marchand static TAILQ_HEAD(, rte_afu_device) ifpga_afu_dev_list =
4105fa3d4aSRosen Xu 	TAILQ_HEAD_INITIALIZER(ifpga_afu_dev_list);
42925c074eSDavid Marchand static TAILQ_HEAD(, rte_afu_driver) ifpga_afu_drv_list =
4305fa3d4aSRosen Xu 	TAILQ_HEAD_INITIALIZER(ifpga_afu_drv_list);
4405fa3d4aSRosen Xu 
4505fa3d4aSRosen Xu 
4605fa3d4aSRosen Xu /* register a ifpga bus based driver */
4705fa3d4aSRosen Xu void rte_ifpga_driver_register(struct rte_afu_driver *driver)
4805fa3d4aSRosen Xu {
4905fa3d4aSRosen Xu 	RTE_VERIFY(driver);
5005fa3d4aSRosen Xu 
5105fa3d4aSRosen Xu 	TAILQ_INSERT_TAIL(&ifpga_afu_drv_list, driver, next);
5205fa3d4aSRosen Xu }
5305fa3d4aSRosen Xu 
5405fa3d4aSRosen Xu /* un-register a fpga bus based driver */
5505fa3d4aSRosen Xu void rte_ifpga_driver_unregister(struct rte_afu_driver *driver)
5605fa3d4aSRosen Xu {
5705fa3d4aSRosen Xu 	TAILQ_REMOVE(&ifpga_afu_drv_list, driver, next);
5805fa3d4aSRosen Xu }
5905fa3d4aSRosen Xu 
6005fa3d4aSRosen Xu static struct rte_afu_device *
6105fa3d4aSRosen Xu ifpga_find_afu_dev(const struct rte_rawdev *rdev,
6205fa3d4aSRosen Xu 	const struct rte_afu_id *afu_id)
6305fa3d4aSRosen Xu {
6405fa3d4aSRosen Xu 	struct rte_afu_device *afu_dev = NULL;
6505fa3d4aSRosen Xu 
6605fa3d4aSRosen Xu 	TAILQ_FOREACH(afu_dev, &ifpga_afu_dev_list, next) {
6762c21c38SMaxime Gouin 		if (afu_dev->rawdev == rdev &&
6805fa3d4aSRosen Xu 			!ifpga_afu_id_cmp(&afu_dev->id, afu_id))
6905fa3d4aSRosen Xu 			return afu_dev;
7005fa3d4aSRosen Xu 	}
7105fa3d4aSRosen Xu 	return NULL;
7205fa3d4aSRosen Xu }
7305fa3d4aSRosen Xu 
74dc384b50SRosen Xu struct rte_afu_device *
75dc384b50SRosen Xu rte_ifpga_find_afu_by_name(const char *name)
76dc384b50SRosen Xu {
77dc384b50SRosen Xu 	struct rte_afu_device *afu_dev = NULL;
78dc384b50SRosen Xu 
79dc384b50SRosen Xu 	TAILQ_FOREACH(afu_dev, &ifpga_afu_dev_list, next) {
8062c21c38SMaxime Gouin 		if (!strcmp(afu_dev->device.name, name))
81dc384b50SRosen Xu 			return afu_dev;
82dc384b50SRosen Xu 	}
83dc384b50SRosen Xu 	return NULL;
84dc384b50SRosen Xu }
85dc384b50SRosen Xu 
8605fa3d4aSRosen Xu static const char * const valid_args[] = {
8705fa3d4aSRosen Xu #define IFPGA_ARG_NAME         "ifpga"
8805fa3d4aSRosen Xu 	IFPGA_ARG_NAME,
8905fa3d4aSRosen Xu #define IFPGA_ARG_PORT         "port"
9005fa3d4aSRosen Xu 	IFPGA_ARG_PORT,
9105fa3d4aSRosen Xu #define IFPGA_AFU_BTS          "afu_bts"
9205fa3d4aSRosen Xu 	IFPGA_AFU_BTS,
9305fa3d4aSRosen Xu 	NULL
9405fa3d4aSRosen Xu };
9505fa3d4aSRosen Xu 
9605fa3d4aSRosen Xu /*
9705fa3d4aSRosen Xu  * Scan the content of the FPGA bus, and the devices in the devices
9805fa3d4aSRosen Xu  * list
9905fa3d4aSRosen Xu  */
10005fa3d4aSRosen Xu static struct rte_afu_device *
10105fa3d4aSRosen Xu ifpga_scan_one(struct rte_rawdev *rawdev,
10205fa3d4aSRosen Xu 		struct rte_devargs *devargs)
10305fa3d4aSRosen Xu {
10405fa3d4aSRosen Xu 	struct rte_kvargs *kvlist = NULL;
10505fa3d4aSRosen Xu 	struct rte_afu_device *afu_dev = NULL;
10605fa3d4aSRosen Xu 	struct rte_afu_pr_conf afu_pr_conf;
10705fa3d4aSRosen Xu 	int ret = 0;
10805fa3d4aSRosen Xu 	char *path = NULL;
10905fa3d4aSRosen Xu 
11005fa3d4aSRosen Xu 	memset(&afu_pr_conf, 0, sizeof(struct rte_afu_pr_conf));
11105fa3d4aSRosen Xu 
11205fa3d4aSRosen Xu 	kvlist = rte_kvargs_parse(devargs->args, valid_args);
11305fa3d4aSRosen Xu 	if (!kvlist) {
11405fa3d4aSRosen Xu 		IFPGA_BUS_ERR("error when parsing param");
11505fa3d4aSRosen Xu 		goto end;
11605fa3d4aSRosen Xu 	}
11705fa3d4aSRosen Xu 
11805fa3d4aSRosen Xu 	if (rte_kvargs_count(kvlist, IFPGA_ARG_PORT) == 1) {
11905fa3d4aSRosen Xu 		if (rte_kvargs_process(kvlist, IFPGA_ARG_PORT,
1209c89c333SDavid Marchand 				ifpga_get_integer32_arg,
1219c89c333SDavid Marchand 				&afu_pr_conf.afu_id.port) < 0) {
1229c89c333SDavid Marchand 			IFPGA_BUS_ERR("error to parse %s", IFPGA_ARG_PORT);
12305fa3d4aSRosen Xu 			goto end;
12405fa3d4aSRosen Xu 		}
12505fa3d4aSRosen Xu 	} else {
12605fa3d4aSRosen Xu 		IFPGA_BUS_ERR("arg %s is mandatory for ifpga bus",
12705fa3d4aSRosen Xu 			  IFPGA_ARG_PORT);
12805fa3d4aSRosen Xu 		goto end;
12905fa3d4aSRosen Xu 	}
13005fa3d4aSRosen Xu 
13105fa3d4aSRosen Xu 	if (rte_kvargs_count(kvlist, IFPGA_AFU_BTS) == 1) {
13205fa3d4aSRosen Xu 		if (rte_kvargs_process(kvlist, IFPGA_AFU_BTS,
1339c89c333SDavid Marchand 				ifpga_get_string_arg, &path) < 0) {
1349c89c333SDavid Marchand 			IFPGA_BUS_ERR("Failed to parse %s", IFPGA_AFU_BTS);
13505fa3d4aSRosen Xu 			goto end;
13605fa3d4aSRosen Xu 		}
1376fa4aa2bSAndy Pei 		afu_pr_conf.pr_enable = 1;
1388a0b28b4SWei Huang 		strlcpy(afu_pr_conf.bs_path, path,
1398a0b28b4SWei Huang 			sizeof(afu_pr_conf.bs_path));
14005fa3d4aSRosen Xu 	} else {
1416fa4aa2bSAndy Pei 		afu_pr_conf.pr_enable = 0;
14205fa3d4aSRosen Xu 	}
14305fa3d4aSRosen Xu 
14405fa3d4aSRosen Xu 	afu_pr_conf.afu_id.uuid.uuid_low = 0;
14505fa3d4aSRosen Xu 	afu_pr_conf.afu_id.uuid.uuid_high = 0;
14605fa3d4aSRosen Xu 
14705fa3d4aSRosen Xu 	if (ifpga_find_afu_dev(rawdev, &afu_pr_conf.afu_id))
14805fa3d4aSRosen Xu 		goto end;
14905fa3d4aSRosen Xu 
15005fa3d4aSRosen Xu 	afu_dev = calloc(1, sizeof(*afu_dev));
15105fa3d4aSRosen Xu 	if (!afu_dev)
15205fa3d4aSRosen Xu 		goto end;
15305fa3d4aSRosen Xu 
1546844d146SThomas Monjalon 	afu_dev->device.bus = &rte_ifpga_bus;
15505fa3d4aSRosen Xu 	afu_dev->device.devargs = devargs;
15605fa3d4aSRosen Xu 	afu_dev->device.numa_node = SOCKET_ID_ANY;
15705fa3d4aSRosen Xu 	afu_dev->device.name = devargs->name;
15805fa3d4aSRosen Xu 	afu_dev->rawdev = rawdev;
15905fa3d4aSRosen Xu 	afu_dev->id.uuid.uuid_low  = 0;
16005fa3d4aSRosen Xu 	afu_dev->id.uuid.uuid_high = 0;
16105fa3d4aSRosen Xu 	afu_dev->id.port      = afu_pr_conf.afu_id.port;
16205fa3d4aSRosen Xu 
163d61138d4SHarman Kalra 	/* Allocate interrupt instance */
164d61138d4SHarman Kalra 	afu_dev->intr_handle =
165d61138d4SHarman Kalra 		rte_intr_instance_alloc(RTE_INTR_INSTANCE_F_PRIVATE);
166d61138d4SHarman Kalra 	if (afu_dev->intr_handle == NULL) {
167d61138d4SHarman Kalra 		IFPGA_BUS_ERR("Failed to allocate intr handle");
168d61138d4SHarman Kalra 		goto end;
169d61138d4SHarman Kalra 	}
170d61138d4SHarman Kalra 
17105fa3d4aSRosen Xu 	if (rawdev->dev_ops && rawdev->dev_ops->dev_info_get)
17210b71caeSBruce Richardson 		rawdev->dev_ops->dev_info_get(rawdev, afu_dev, sizeof(*afu_dev));
17305fa3d4aSRosen Xu 
17405fa3d4aSRosen Xu 	if (rawdev->dev_ops &&
17505fa3d4aSRosen Xu 		rawdev->dev_ops->dev_start &&
17605fa3d4aSRosen Xu 		rawdev->dev_ops->dev_start(rawdev))
17708981819SRosen Xu 		goto end;
17805fa3d4aSRosen Xu 
179bb5c82daSRosen Xu 	if (rawdev->dev_ops &&
180bb5c82daSRosen Xu 		rawdev->dev_ops->firmware_load &&
18105fa3d4aSRosen Xu 		rawdev->dev_ops->firmware_load(rawdev,
18205fa3d4aSRosen Xu 				&afu_pr_conf)){
183*f665790aSDavid Marchand 		IFPGA_BUS_ERR("firmware load error %d", ret);
18408981819SRosen Xu 		goto end;
18505fa3d4aSRosen Xu 	}
18605fa3d4aSRosen Xu 	afu_dev->id.uuid.uuid_low  = afu_pr_conf.afu_id.uuid.uuid_low;
18705fa3d4aSRosen Xu 	afu_dev->id.uuid.uuid_high = afu_pr_conf.afu_id.uuid.uuid_high;
18805fa3d4aSRosen Xu 
18908981819SRosen Xu 	rte_kvargs_free(kvlist);
19008981819SRosen Xu 	free(path);
19105fa3d4aSRosen Xu 	return afu_dev;
19205fa3d4aSRosen Xu 
19305fa3d4aSRosen Xu end:
19405fa3d4aSRosen Xu 	rte_kvargs_free(kvlist);
19505fa3d4aSRosen Xu 	free(path);
196d61138d4SHarman Kalra 	if (afu_dev) {
197d61138d4SHarman Kalra 		rte_intr_instance_free(afu_dev->intr_handle);
19808981819SRosen Xu 		free(afu_dev);
199d61138d4SHarman Kalra 	}
20005fa3d4aSRosen Xu 
20105fa3d4aSRosen Xu 	return NULL;
20205fa3d4aSRosen Xu }
20305fa3d4aSRosen Xu 
20405fa3d4aSRosen Xu /*
20505fa3d4aSRosen Xu  * Scan the content of the FPGA bus, and the devices in the devices
20605fa3d4aSRosen Xu  * list
20705fa3d4aSRosen Xu  */
20805fa3d4aSRosen Xu static int
20905fa3d4aSRosen Xu ifpga_scan(void)
21005fa3d4aSRosen Xu {
21105fa3d4aSRosen Xu 	struct rte_devargs *devargs;
21205fa3d4aSRosen Xu 	struct rte_kvargs *kvlist = NULL;
21305fa3d4aSRosen Xu 	struct rte_rawdev *rawdev = NULL;
21405fa3d4aSRosen Xu 	char *name = NULL;
21505fa3d4aSRosen Xu 	char name1[RTE_RAWDEV_NAME_MAX_LEN];
21605fa3d4aSRosen Xu 	struct rte_afu_device *afu_dev = NULL;
21705fa3d4aSRosen Xu 
21805fa3d4aSRosen Xu 	/* for FPGA devices we scan the devargs_list populated via cmdline */
21905fa3d4aSRosen Xu 	RTE_EAL_DEVARGS_FOREACH(IFPGA_ARG_NAME, devargs) {
22005fa3d4aSRosen Xu 		if (devargs->bus != &rte_ifpga_bus)
22105fa3d4aSRosen Xu 			continue;
22205fa3d4aSRosen Xu 
22305fa3d4aSRosen Xu 		kvlist = rte_kvargs_parse(devargs->args, valid_args);
22405fa3d4aSRosen Xu 		if (!kvlist) {
22505fa3d4aSRosen Xu 			IFPGA_BUS_ERR("error when parsing param");
22605fa3d4aSRosen Xu 			goto end;
22705fa3d4aSRosen Xu 		}
22805fa3d4aSRosen Xu 
22905fa3d4aSRosen Xu 		if (rte_kvargs_count(kvlist, IFPGA_ARG_NAME) == 1) {
23005fa3d4aSRosen Xu 			if (rte_kvargs_process(kvlist, IFPGA_ARG_NAME,
2319c89c333SDavid Marchand 					ifpga_get_string_arg, &name) < 0) {
23205fa3d4aSRosen Xu 				IFPGA_BUS_ERR("error to parse %s",
23305fa3d4aSRosen Xu 				     IFPGA_ARG_NAME);
23405fa3d4aSRosen Xu 				goto end;
23505fa3d4aSRosen Xu 			}
23605fa3d4aSRosen Xu 		} else {
23705fa3d4aSRosen Xu 			IFPGA_BUS_ERR("arg %s is mandatory for ifpga bus",
23805fa3d4aSRosen Xu 			  IFPGA_ARG_NAME);
23905fa3d4aSRosen Xu 			goto end;
24005fa3d4aSRosen Xu 		}
24105fa3d4aSRosen Xu 
24205fa3d4aSRosen Xu 		memset(name1, 0, sizeof(name1));
24305fa3d4aSRosen Xu 		snprintf(name1, RTE_RAWDEV_NAME_MAX_LEN, "IFPGA:%s", name);
24405fa3d4aSRosen Xu 
24505fa3d4aSRosen Xu 		rawdev = rte_rawdev_pmd_get_named_dev(name1);
24605fa3d4aSRosen Xu 		if (!rawdev)
24705fa3d4aSRosen Xu 			goto end;
24805fa3d4aSRosen Xu 
24905fa3d4aSRosen Xu 		afu_dev = ifpga_scan_one(rawdev, devargs);
25005fa3d4aSRosen Xu 		if (afu_dev != NULL)
25105fa3d4aSRosen Xu 			TAILQ_INSERT_TAIL(&ifpga_afu_dev_list, afu_dev, next);
25205fa3d4aSRosen Xu 	}
25305fa3d4aSRosen Xu 
25405fa3d4aSRosen Xu end:
25505fa3d4aSRosen Xu 	rte_kvargs_free(kvlist);
25605fa3d4aSRosen Xu 	free(name);
25705fa3d4aSRosen Xu 
25805fa3d4aSRosen Xu 	return 0;
25905fa3d4aSRosen Xu }
26005fa3d4aSRosen Xu 
26105fa3d4aSRosen Xu /*
26205fa3d4aSRosen Xu  * Match the AFU Driver and AFU Device using the ID Table
26305fa3d4aSRosen Xu  */
26405fa3d4aSRosen Xu static int
26505fa3d4aSRosen Xu rte_afu_match(const struct rte_afu_driver *afu_drv,
26605fa3d4aSRosen Xu 	      const struct rte_afu_device *afu_dev)
26705fa3d4aSRosen Xu {
26805fa3d4aSRosen Xu 	const struct rte_afu_uuid *id_table;
26905fa3d4aSRosen Xu 
27005fa3d4aSRosen Xu 	for (id_table = afu_drv->id_table;
27105fa3d4aSRosen Xu 		((id_table->uuid_low != 0) && (id_table->uuid_high != 0));
27205fa3d4aSRosen Xu 	     id_table++) {
27305fa3d4aSRosen Xu 		/* check if device's identifiers match the driver's ones */
27405fa3d4aSRosen Xu 		if ((id_table->uuid_low != afu_dev->id.uuid.uuid_low) ||
27505fa3d4aSRosen Xu 				id_table->uuid_high !=
27605fa3d4aSRosen Xu 				 afu_dev->id.uuid.uuid_high)
27705fa3d4aSRosen Xu 			continue;
27805fa3d4aSRosen Xu 
27905fa3d4aSRosen Xu 		return 1;
28005fa3d4aSRosen Xu 	}
28105fa3d4aSRosen Xu 
28205fa3d4aSRosen Xu 	return 0;
28305fa3d4aSRosen Xu }
28405fa3d4aSRosen Xu 
28505fa3d4aSRosen Xu static int
28605fa3d4aSRosen Xu ifpga_probe_one_driver(struct rte_afu_driver *drv,
28705fa3d4aSRosen Xu 			struct rte_afu_device *afu_dev)
28805fa3d4aSRosen Xu {
28905fa3d4aSRosen Xu 	int ret;
29005fa3d4aSRosen Xu 
29105fa3d4aSRosen Xu 	if (!rte_afu_match(drv, afu_dev))
29205fa3d4aSRosen Xu 		/* Match of device and driver failed */
29305fa3d4aSRosen Xu 		return 1;
29405fa3d4aSRosen Xu 
29505fa3d4aSRosen Xu 	/* reference driver structure */
29605fa3d4aSRosen Xu 	afu_dev->driver = drv;
29705fa3d4aSRosen Xu 
29805fa3d4aSRosen Xu 	/* call the driver probe() function */
29905fa3d4aSRosen Xu 	ret = drv->probe(afu_dev);
300391797f0SThomas Monjalon 	if (ret)
30105fa3d4aSRosen Xu 		afu_dev->driver = NULL;
302391797f0SThomas Monjalon 	else
303391797f0SThomas Monjalon 		afu_dev->device.driver = &drv->driver;
30405fa3d4aSRosen Xu 
30505fa3d4aSRosen Xu 	return ret;
30605fa3d4aSRosen Xu }
30705fa3d4aSRosen Xu 
30805fa3d4aSRosen Xu static int
30905fa3d4aSRosen Xu ifpga_probe_all_drivers(struct rte_afu_device *afu_dev)
31005fa3d4aSRosen Xu {
31105fa3d4aSRosen Xu 	struct rte_afu_driver *drv = NULL;
31205fa3d4aSRosen Xu 	int ret = 0;
31305fa3d4aSRosen Xu 
31405fa3d4aSRosen Xu 	if (afu_dev == NULL)
31505fa3d4aSRosen Xu 		return -1;
31605fa3d4aSRosen Xu 
31705fa3d4aSRosen Xu 	/* Check if a driver is already loaded */
318e9d159c3SThomas Monjalon 	if (rte_dev_is_probed(&afu_dev->device)) {
319*f665790aSDavid Marchand 		IFPGA_BUS_DEBUG("Device %s is already probed",
320e9d159c3SThomas Monjalon 				rte_ifpga_device_name(afu_dev));
321e9d159c3SThomas Monjalon 		return -EEXIST;
322e9d159c3SThomas Monjalon 	}
32305fa3d4aSRosen Xu 
32405fa3d4aSRosen Xu 	TAILQ_FOREACH(drv, &ifpga_afu_drv_list, next) {
325fb87e55aSAndy Pei 		ret = ifpga_probe_one_driver(drv, afu_dev);
326fb87e55aSAndy Pei 		if (ret < 0)
327fb87e55aSAndy Pei 			/* negative value is an error */
328fb87e55aSAndy Pei 			return ret;
329fb87e55aSAndy Pei 		if (ret > 0)
330fb87e55aSAndy Pei 			/* positive value means driver doesn't support it */
331fb87e55aSAndy Pei 			continue;
332fb87e55aSAndy Pei 		return 0;
33305fa3d4aSRosen Xu 	}
334fb87e55aSAndy Pei 	if ((ret > 0) && (afu_dev->driver == NULL))
335fb87e55aSAndy Pei 		return 0;
336fb87e55aSAndy Pei 	else
33705fa3d4aSRosen Xu 		return ret;
33805fa3d4aSRosen Xu }
33905fa3d4aSRosen Xu 
34005fa3d4aSRosen Xu /*
34105fa3d4aSRosen Xu  * Scan the content of the Intel FPGA bus, and call the probe() function for
34205fa3d4aSRosen Xu  * all registered drivers that have a matching entry in its id_table
34305fa3d4aSRosen Xu  * for discovered devices.
34405fa3d4aSRosen Xu  */
34505fa3d4aSRosen Xu static int
34605fa3d4aSRosen Xu ifpga_probe(void)
34705fa3d4aSRosen Xu {
34805fa3d4aSRosen Xu 	struct rte_afu_device *afu_dev = NULL;
34905fa3d4aSRosen Xu 	int ret = 0;
35005fa3d4aSRosen Xu 
35105fa3d4aSRosen Xu 	TAILQ_FOREACH(afu_dev, &ifpga_afu_dev_list, next) {
35205fa3d4aSRosen Xu 		ret = ifpga_probe_all_drivers(afu_dev);
353e9d159c3SThomas Monjalon 		if (ret == -EEXIST)
354e9d159c3SThomas Monjalon 			continue;
35505fa3d4aSRosen Xu 		if (ret < 0)
356*f665790aSDavid Marchand 			IFPGA_BUS_ERR("failed to initialize %s device",
35705fa3d4aSRosen Xu 				rte_ifpga_device_name(afu_dev));
35805fa3d4aSRosen Xu 	}
35905fa3d4aSRosen Xu 
36005fa3d4aSRosen Xu 	return ret;
36105fa3d4aSRosen Xu }
36205fa3d4aSRosen Xu 
3634e5fc8b9SWei Huang /*
3644e5fc8b9SWei Huang  * Cleanup the content of the Intel FPGA bus, and call the remove() function
3654e5fc8b9SWei Huang  * for all registered devices.
3664e5fc8b9SWei Huang  */
3674e5fc8b9SWei Huang static int
3684e5fc8b9SWei Huang ifpga_cleanup(void)
3694e5fc8b9SWei Huang {
3704e5fc8b9SWei Huang 	struct rte_afu_device *afu_dev, *tmp_dev;
3714e5fc8b9SWei Huang 	int error = 0;
3724e5fc8b9SWei Huang 
3734e5fc8b9SWei Huang 	RTE_TAILQ_FOREACH_SAFE(afu_dev, &ifpga_afu_dev_list, next, tmp_dev) {
3744e5fc8b9SWei Huang 		struct rte_afu_driver *drv = afu_dev->driver;
3754e5fc8b9SWei Huang 		int ret = 0;
3764e5fc8b9SWei Huang 
3774e5fc8b9SWei Huang 		if (drv == NULL || drv->remove == NULL)
3784e5fc8b9SWei Huang 			goto free;
3794e5fc8b9SWei Huang 
3804e5fc8b9SWei Huang 		ret = drv->remove(afu_dev);
3814e5fc8b9SWei Huang 		if (ret < 0) {
3824e5fc8b9SWei Huang 			rte_errno = errno;
3834e5fc8b9SWei Huang 			error = -1;
3844e5fc8b9SWei Huang 		}
3854e5fc8b9SWei Huang 		afu_dev->driver = NULL;
3864e5fc8b9SWei Huang 		afu_dev->device.driver = NULL;
3874e5fc8b9SWei Huang 
3884e5fc8b9SWei Huang free:
3894e5fc8b9SWei Huang 		TAILQ_REMOVE(&ifpga_afu_dev_list, afu_dev, next);
3904e5fc8b9SWei Huang 		rte_devargs_remove(afu_dev->device.devargs);
3914e5fc8b9SWei Huang 		rte_intr_instance_free(afu_dev->intr_handle);
3924e5fc8b9SWei Huang 		free(afu_dev);
3934e5fc8b9SWei Huang 	}
3944e5fc8b9SWei Huang 
3954e5fc8b9SWei Huang 	return error;
3964e5fc8b9SWei Huang }
3974e5fc8b9SWei Huang 
39805fa3d4aSRosen Xu static int
39905fa3d4aSRosen Xu ifpga_plug(struct rte_device *dev)
40005fa3d4aSRosen Xu {
40105fa3d4aSRosen Xu 	return ifpga_probe_all_drivers(RTE_DEV_TO_AFU(dev));
40205fa3d4aSRosen Xu }
40305fa3d4aSRosen Xu 
40405fa3d4aSRosen Xu static int
40505fa3d4aSRosen Xu ifpga_remove_driver(struct rte_afu_device *afu_dev)
40605fa3d4aSRosen Xu {
40705fa3d4aSRosen Xu 	const char *name;
40805fa3d4aSRosen Xu 
40905fa3d4aSRosen Xu 	name = rte_ifpga_device_name(afu_dev);
4102ed055c5SThomas Monjalon 	if (afu_dev->driver == NULL) {
411*f665790aSDavid Marchand 		IFPGA_BUS_DEBUG("no driver attach to device %s", name);
41205fa3d4aSRosen Xu 		return 1;
41305fa3d4aSRosen Xu 	}
41405fa3d4aSRosen Xu 
4152ed055c5SThomas Monjalon 	return afu_dev->driver->remove(afu_dev);
41605fa3d4aSRosen Xu }
41705fa3d4aSRosen Xu 
41805fa3d4aSRosen Xu static int
41905fa3d4aSRosen Xu ifpga_unplug(struct rte_device *dev)
42005fa3d4aSRosen Xu {
42105fa3d4aSRosen Xu 	struct rte_afu_device *afu_dev = NULL;
42205fa3d4aSRosen Xu 	int ret;
42305fa3d4aSRosen Xu 
42405fa3d4aSRosen Xu 	if (dev == NULL)
42505fa3d4aSRosen Xu 		return -EINVAL;
42605fa3d4aSRosen Xu 
42705fa3d4aSRosen Xu 	afu_dev = RTE_DEV_TO_AFU(dev);
42807b4a8beSRosen Xu 	if (!afu_dev)
42905fa3d4aSRosen Xu 		return -ENOENT;
43005fa3d4aSRosen Xu 
43105fa3d4aSRosen Xu 	ret = ifpga_remove_driver(afu_dev);
43205fa3d4aSRosen Xu 	if (ret)
43305fa3d4aSRosen Xu 		return ret;
43405fa3d4aSRosen Xu 
43505fa3d4aSRosen Xu 	TAILQ_REMOVE(&ifpga_afu_dev_list, afu_dev, next);
43605fa3d4aSRosen Xu 
4372effa126SThomas Monjalon 	rte_devargs_remove(dev->devargs);
438d61138d4SHarman Kalra 	rte_intr_instance_free(afu_dev->intr_handle);
43905fa3d4aSRosen Xu 	free(afu_dev);
44005fa3d4aSRosen Xu 	return 0;
44105fa3d4aSRosen Xu 
44205fa3d4aSRosen Xu }
44305fa3d4aSRosen Xu 
44405fa3d4aSRosen Xu static struct rte_device *
44505fa3d4aSRosen Xu ifpga_find_device(const struct rte_device *start,
44605fa3d4aSRosen Xu 	rte_dev_cmp_t cmp, const void *data)
44705fa3d4aSRosen Xu {
44805fa3d4aSRosen Xu 	struct rte_afu_device *afu_dev;
44905fa3d4aSRosen Xu 
45005fa3d4aSRosen Xu 	TAILQ_FOREACH(afu_dev, &ifpga_afu_dev_list, next) {
45105fa3d4aSRosen Xu 		if (start && &afu_dev->device == start) {
45205fa3d4aSRosen Xu 			start = NULL;
45305fa3d4aSRosen Xu 			continue;
45405fa3d4aSRosen Xu 		}
45505fa3d4aSRosen Xu 		if (cmp(&afu_dev->device, data) == 0)
45605fa3d4aSRosen Xu 			return &afu_dev->device;
45705fa3d4aSRosen Xu 	}
45805fa3d4aSRosen Xu 
45905fa3d4aSRosen Xu 	return NULL;
46005fa3d4aSRosen Xu }
46105fa3d4aSRosen Xu static int
46205fa3d4aSRosen Xu ifpga_parse(const char *name, void *addr)
46305fa3d4aSRosen Xu {
46405fa3d4aSRosen Xu 	int *out = addr;
46505fa3d4aSRosen Xu 	struct rte_rawdev *rawdev = NULL;
46605fa3d4aSRosen Xu 	char rawdev_name[RTE_RAWDEV_NAME_MAX_LEN];
46705fa3d4aSRosen Xu 	char *c1 = NULL;
46805fa3d4aSRosen Xu 	char *c2 = NULL;
46905fa3d4aSRosen Xu 	int port = IFPGA_BUS_DEV_PORT_MAX;
47005fa3d4aSRosen Xu 	char str_port[8];
47105fa3d4aSRosen Xu 	int str_port_len = 0;
47205fa3d4aSRosen Xu 	int ret;
47305fa3d4aSRosen Xu 
47405fa3d4aSRosen Xu 	memset(str_port, 0, 8);
47505fa3d4aSRosen Xu 	c1 = strchr(name, '|');
47605fa3d4aSRosen Xu 	if (c1 != NULL) {
47705fa3d4aSRosen Xu 		str_port_len = c1 - name;
47805fa3d4aSRosen Xu 		c2 = c1 + 1;
47905fa3d4aSRosen Xu 	}
48005fa3d4aSRosen Xu 
48105fa3d4aSRosen Xu 	if (str_port_len < 8 &&
48205fa3d4aSRosen Xu 		str_port_len > 0) {
48305fa3d4aSRosen Xu 		memcpy(str_port, name, str_port_len);
48405fa3d4aSRosen Xu 		ret = sscanf(str_port, "%d", &port);
48505fa3d4aSRosen Xu 		if (ret == -1)
48605fa3d4aSRosen Xu 			return 0;
48705fa3d4aSRosen Xu 	}
48805fa3d4aSRosen Xu 
48905fa3d4aSRosen Xu 	memset(rawdev_name, 0, sizeof(rawdev_name));
49005fa3d4aSRosen Xu 	snprintf(rawdev_name, RTE_RAWDEV_NAME_MAX_LEN, "IFPGA:%s", c2);
49105fa3d4aSRosen Xu 	rawdev = rte_rawdev_pmd_get_named_dev(rawdev_name);
49205fa3d4aSRosen Xu 
49305fa3d4aSRosen Xu 	if ((port < IFPGA_BUS_DEV_PORT_MAX) &&
49405fa3d4aSRosen Xu 		rawdev &&
49505fa3d4aSRosen Xu 		(addr != NULL))
49605fa3d4aSRosen Xu 		*out = port;
49705fa3d4aSRosen Xu 
49805fa3d4aSRosen Xu 	if ((port < IFPGA_BUS_DEV_PORT_MAX) &&
49905fa3d4aSRosen Xu 		rawdev)
50005fa3d4aSRosen Xu 		return 0;
50105fa3d4aSRosen Xu 	else
50205fa3d4aSRosen Xu 		return 1;
50305fa3d4aSRosen Xu }
50405fa3d4aSRosen Xu 
50505fa3d4aSRosen Xu static struct rte_bus rte_ifpga_bus = {
50605fa3d4aSRosen Xu 	.scan        = ifpga_scan,
50705fa3d4aSRosen Xu 	.probe       = ifpga_probe,
5084e5fc8b9SWei Huang 	.cleanup     = ifpga_cleanup,
50905fa3d4aSRosen Xu 	.find_device = ifpga_find_device,
51005fa3d4aSRosen Xu 	.plug        = ifpga_plug,
51105fa3d4aSRosen Xu 	.unplug      = ifpga_unplug,
51205fa3d4aSRosen Xu 	.parse       = ifpga_parse,
51305fa3d4aSRosen Xu };
51405fa3d4aSRosen Xu 
51505fa3d4aSRosen Xu RTE_REGISTER_BUS(IFPGA_BUS_NAME, rte_ifpga_bus);
516eeded204SDavid Marchand RTE_LOG_REGISTER_DEFAULT(ifpga_bus_logtype, NOTICE);
517