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