From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mga04.intel.com (mga04.intel.com [192.55.52.120]) by dpdk.org (Postfix) with ESMTP id EAAC82BC7 for ; Sat, 31 Mar 2018 18:00:25 +0200 (CEST) X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from fmsmga006.fm.intel.com ([10.253.24.20]) by fmsmga104.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 31 Mar 2018 09:00:22 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.48,387,1517904000"; d="scan'208";a="216378567" Received: from dpdkx8602.sh.intel.com ([10.67.110.200]) by fmsmga006.fm.intel.com with ESMTP; 31 Mar 2018 09:00:20 -0700 From: Rosen Xu To: dev@dpdk.org Cc: declan.doherty@intel.com, bruce.richardson@intel.com, shreyansh.jain@nxp.com, ferruh.yigit@intel.com, konstantin.ananyev@intel.com, tianfei.zhang@intel.com, hao.wu@intel.com, gaetan.rivet@6wind.com Date: Sun, 1 Apr 2018 00:03:00 +0800 Message-Id: <1522512182-182441-2-git-send-email-rosen.xu@intel.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1522512182-182441-1-git-send-email-rosen.xu@intel.com> References: <1521553556-62982-1-git-send-email-rosen.xu@intel.com> <1522512182-182441-1-git-send-email-rosen.xu@intel.com> Subject: [dpdk-dev] [PATCH v4 1/3] Add Intel FPGA BUS Lib Code X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 31 Mar 2018 16:00:26 -0000 Signed-off-by: Rosen Xu --- config/common_base | 5 + drivers/bus/Makefile | 1 + drivers/bus/ifpga/Makefile | 33 ++ drivers/bus/ifpga/ifpga_bus.c | 517 ++++++++++++++++++++++++++++ drivers/bus/ifpga/ifpga_common.c | 141 ++++++++ drivers/bus/ifpga/ifpga_common.h | 22 ++ drivers/bus/ifpga/ifpga_logs.h | 31 ++ drivers/bus/ifpga/rte_bus_ifpga.h | 175 ++++++++++ drivers/bus/ifpga/rte_bus_ifpga_version.map | 8 + mk/rte.app.mk | 2 + 10 files changed, 935 insertions(+) create mode 100644 drivers/bus/ifpga/Makefile create mode 100644 drivers/bus/ifpga/ifpga_bus.c create mode 100644 drivers/bus/ifpga/ifpga_common.c create mode 100644 drivers/bus/ifpga/ifpga_common.h create mode 100644 drivers/bus/ifpga/ifpga_logs.h create mode 100644 drivers/bus/ifpga/rte_bus_ifpga.h create mode 100644 drivers/bus/ifpga/rte_bus_ifpga_version.map diff --git a/config/common_base b/config/common_base index ad03cf4..49f6b09 100644 --- a/config/common_base +++ b/config/common_base @@ -134,6 +134,11 @@ CONFIG_RTE_LIBRTE_PCI_BUS=y CONFIG_RTE_LIBRTE_VDEV_BUS=y # +# Compile the Intel FPGA bus +# +CONFIG_RTE_LIBRTE_IFPGA_BUS=y + +# # Compile ARK PMD # CONFIG_RTE_LIBRTE_ARK_PMD=y diff --git a/drivers/bus/Makefile b/drivers/bus/Makefile index 7ef2593..55d2dfe 100644 --- a/drivers/bus/Makefile +++ b/drivers/bus/Makefile @@ -7,5 +7,6 @@ DIRS-$(CONFIG_RTE_LIBRTE_DPAA_BUS) += dpaa DIRS-$(CONFIG_RTE_LIBRTE_FSLMC_BUS) += fslmc DIRS-$(CONFIG_RTE_LIBRTE_PCI_BUS) += pci DIRS-$(CONFIG_RTE_LIBRTE_VDEV_BUS) += vdev +DIRS-$(CONFIG_RTE_LIBRTE_IFPGA_BUS) += ifpga include $(RTE_SDK)/mk/rte.subdir.mk diff --git a/drivers/bus/ifpga/Makefile b/drivers/bus/ifpga/Makefile new file mode 100644 index 0000000..1b569af --- /dev/null +++ b/drivers/bus/ifpga/Makefile @@ -0,0 +1,33 @@ +# SPDX-License-Identifier: BSD-3-Clause +# Copyright(c) 2018 Intel Corporation + +include $(RTE_SDK)/mk/rte.vars.mk + +# +# library name +# +LIB = librte_bus_ifpga.a + +CFLAGS += -O3 +CFLAGS += $(WERROR_FLAGS) + +# versioning export map +EXPORT_MAP := rte_bus_ifpga_version.map + +# library version +LIBABIVER := 1 + +VPATH += $(SRCDIR)/base + +SRCS-y += \ + ifpga_bus.c \ + ifpga_common.c + +LDLIBS += -lrte_eal + +# +# Export include files +# +SYMLINK-y-include += rte_bus_ifpga.h + +include $(RTE_SDK)/mk/rte.lib.mk diff --git a/drivers/bus/ifpga/ifpga_bus.c b/drivers/bus/ifpga/ifpga_bus.c new file mode 100644 index 0000000..eba2615 --- /dev/null +++ b/drivers/bus/ifpga/ifpga_bus.c @@ -0,0 +1,517 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2010-2018 Intel Corporation + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "rte_rawdev.h" +#include "rte_rawdev_pmd.h" +#include "rte_bus_ifpga.h" +#include "ifpga_logs.h" +#include "ifpga_common.h" + +int ifpga_bus_logtype; + +/* register a ifpga bus based driver */ +void rte_ifpga_driver_register(struct rte_afu_driver *driver) +{ + RTE_VERIFY(driver); + + TAILQ_INSERT_TAIL(&rte_ifpga_bus.driver_list, driver, next); +} + +/* un-register a fpga bus based driver */ +void rte_ifpga_driver_unregister(struct rte_afu_driver *driver) +{ + TAILQ_REMOVE(&rte_ifpga_bus.driver_list, driver, next); +} + +static struct rte_ifpga_device * +ifpga_find_ifpga_dev(const struct rte_pci_addr *pci_addr) +{ + struct rte_ifpga_device *ifpga_dev = NULL; + + TAILQ_FOREACH(ifpga_dev, &rte_ifpga_bus.ifpga_list, next) { + if (!rte_pci_addr_cmp(&ifpga_dev->pci_addr, pci_addr)) + return ifpga_dev; + } + return NULL; +} + +static struct rte_afu_device * +ifpga_find_afu_dev(const struct rte_ifpga_device *ifpga_dev, + const struct rte_afu_id *afu_id) +{ + struct rte_afu_device *afu_dev = NULL; + + TAILQ_FOREACH(afu_dev, &ifpga_dev->afu_list, next) { + if (!ifpga_afu_id_cmp(&afu_dev->id, afu_id)) + return afu_dev; + } + return NULL; +} + +static const char * const valid_args[] = { +#define IFPGA_ARG_BDF "bdf" + IFPGA_ARG_BDF, +#define IFPGA_ARG_PORT "port" + IFPGA_ARG_PORT, +#define IFPGA_AFU_BTS "afu_bts" + IFPGA_AFU_BTS, + NULL +}; + +/* + * Scan the content of the FPGA bus, and the devices in the devices + * list + */ +static struct rte_afu_device * +rte_ifpga_scan_one(struct rte_devargs *devargs, + struct rte_ifpga_device *ifpga_dev) +{ + struct rte_kvargs *kvlist = NULL; + struct rte_rawdev *rawdev = NULL; + struct rte_afu_device *afu_dev = NULL; + struct rte_afu_pr_conf afu_pr_conf; + int ret = 0; + char *path = NULL; + + memset((char *)(&afu_pr_conf), 0, sizeof(struct rte_afu_pr_conf)); + + kvlist = rte_kvargs_parse(devargs->args, valid_args); + if (!kvlist) { + IFPGA_BUS_ERR("error when parsing param"); + goto end; + } + + if (rte_kvargs_count(kvlist, IFPGA_ARG_BDF) == 1) { + if (rte_kvargs_process(kvlist, IFPGA_ARG_BDF, + &ifpga_get_bdf_arg, &afu_pr_conf.afu_id.pci_addr) < 0) { + IFPGA_BUS_ERR("error to parse %s", IFPGA_ARG_BDF); + goto end; + } + } else { + IFPGA_BUS_ERR("arg %s is mandatory for ifpga bus", + IFPGA_ARG_BDF); + goto end; + } + + if (rte_kvargs_count(kvlist, IFPGA_ARG_PORT) == 1) { + if (rte_kvargs_process(kvlist, IFPGA_ARG_PORT, + &ifpga_get_integer32_arg, &afu_pr_conf.afu_id.port) < 0) { + IFPGA_BUS_ERR("error to parse %s", + IFPGA_ARG_PORT); + goto end; + } + } else { + IFPGA_BUS_ERR("arg %s is mandatory for ifpga bus", + IFPGA_ARG_PORT); + goto end; + } + + if (rte_kvargs_count(kvlist, IFPGA_AFU_BTS) == 1) { + if (rte_kvargs_process(kvlist, IFPGA_AFU_BTS, + &ifpga_get_string_arg, &path) < 0) { + IFPGA_BUS_ERR("error to parse %s", + IFPGA_AFU_BTS); + goto end; + } + } else { + IFPGA_BUS_ERR("arg %s is mandatory for ifpga bus", + IFPGA_AFU_BTS); + goto end; + } + + afu_pr_conf.afu_id.uuid_low = 0; + afu_pr_conf.afu_id.uuid_high = 0; + afu_pr_conf.pr_enable = path?1:0; + + rawdev = ifpga_dev->rdev; + if (ifpga_find_afu_dev(ifpga_dev, &afu_pr_conf.afu_id)) + goto end; + + afu_dev = calloc(1, sizeof(*afu_dev)); + if (!afu_dev) + goto end; + + afu_dev->device.devargs = devargs; + afu_dev->device.numa_node = SOCKET_ID_ANY; + afu_dev->device.name = devargs->name; + afu_dev->rawdev = rawdev; + afu_dev->id.pci_addr.domain = afu_pr_conf.afu_id.pci_addr.domain; + afu_dev->id.pci_addr.bus = afu_pr_conf.afu_id.pci_addr.bus; + afu_dev->id.pci_addr.devid = afu_pr_conf.afu_id.pci_addr.devid; + afu_dev->id.pci_addr.function = afu_pr_conf.afu_id.pci_addr.function; + afu_dev->id.uuid_low = 0; + afu_dev->id.uuid_high = 0; + afu_dev->id.port = afu_pr_conf.afu_id.port; + afu_dev->ifpga_dev = ifpga_dev; + + if (rawdev->dev_ops && rawdev->dev_ops->dev_info_get) + rawdev->dev_ops->dev_info_get(rawdev, afu_dev); + + if (rawdev->dev_ops && + rawdev->dev_ops->dev_start && + rawdev->dev_ops->dev_start(rawdev)) + goto free_dev; + if (path) { + strncpy(afu_pr_conf.bs_path, path, strlen(path)); + if (rawdev->dev_ops->firmware_load && + rawdev->dev_ops->firmware_load(rawdev, + &afu_pr_conf)){ + printf("firmware load error %d\n", ret); + goto free_dev; + } + afu_dev->id.uuid_low = afu_pr_conf.afu_id.uuid_low; + afu_dev->id.uuid_high = afu_pr_conf.afu_id.uuid_high; + } + + return afu_dev; + +free_dev: + free(afu_dev); +end: + if (kvlist) + rte_kvargs_free(kvlist); + if (path) + free(path); + + return NULL; +} + +/* + * Scan the content of the FPGA bus, and the devices in the devices + * list + */ +static int +rte_ifpga_scan(void) +{ + struct rte_ifpga_device *ifpga_dev; + struct rte_devargs *devargs; + struct rte_kvargs *kvlist = NULL; + struct rte_pci_addr pci_addr; + struct rte_rawdev *rawdev = NULL; + char name[RTE_RAWDEV_NAME_MAX_LEN]; + struct rte_afu_device *afu_dev = NULL; + + /* for FPGA devices we scan the devargs_list populated via cmdline */ + TAILQ_FOREACH(devargs, &devargs_list, next) { + if (devargs->bus != &rte_ifpga_bus.bus) + continue; + + kvlist = rte_kvargs_parse(devargs->args, valid_args); + if (!kvlist) { + IFPGA_BUS_ERR("error when parsing param"); + goto end; + } + + if (rte_kvargs_count(kvlist, IFPGA_ARG_BDF) == 1) { + if (rte_kvargs_process(kvlist, IFPGA_ARG_BDF, + &ifpga_get_bdf_arg, &pci_addr) < 0) { + IFPGA_BUS_ERR("error to parse %s", + IFPGA_ARG_BDF); + goto end; + } + } else { + IFPGA_BUS_ERR("arg %s is mandatory for ifpga bus", + IFPGA_ARG_BDF); + goto end; + } + + memset(name, 0, sizeof(name)); + snprintf(name, RTE_RAWDEV_NAME_MAX_LEN, "IFPGA:%x:%x:%x", + pci_addr.bus, pci_addr.devid, pci_addr.function); + + rawdev = rte_rawdev_pmd_get_named_dev(name); + if (!rawdev) + goto end; + + if (ifpga_find_ifpga_dev(&pci_addr)) + continue; + + ifpga_dev = calloc(1, sizeof(*ifpga_dev)); + if (!ifpga_dev) + goto end; + + ifpga_dev->pci_addr.domain = pci_addr.domain; + ifpga_dev->pci_addr.bus = pci_addr.bus; + ifpga_dev->pci_addr.devid = pci_addr.devid; + ifpga_dev->pci_addr.function = pci_addr.function; + ifpga_dev->rdev = rawdev; + TAILQ_INIT(&ifpga_dev->afu_list); + + TAILQ_INSERT_TAIL(&rte_ifpga_bus.ifpga_list, ifpga_dev, next); + afu_dev = rte_ifpga_scan_one(devargs, ifpga_dev); + if (afu_dev != NULL) + TAILQ_INSERT_TAIL(&ifpga_dev->afu_list, afu_dev, next); + } + +end: + if (kvlist) + rte_kvargs_free(kvlist); + + return 0; +} + +/* + * Match the AFU Driver and AFU Device using the ID Table + */ +static int +rte_afu_match(const struct rte_afu_driver *afu_drv, + const struct rte_afu_device *afu_dev) +{ + const struct rte_afu_uuid *id_table; + + for (id_table = afu_drv->id_table; + ((id_table->uuid_low != 0) && (id_table->uuid_high != 0)); + id_table++) { + /* check if device's identifiers match the driver's ones */ + if ((id_table->uuid_low != afu_dev->id.uuid_low) || + (id_table->uuid_high != afu_dev->id.uuid_high)) + continue; + + return 1; + } + + return 0; +} + +static int +ifpga_probe_one_driver(struct rte_afu_driver *drv, + struct rte_afu_device *afu_dev) +{ + int ret; + + if (!rte_afu_match(drv, afu_dev)) + /* Match of device and driver failed */ + return 1; + + /* reference driver structure */ + afu_dev->driver = drv; + afu_dev->device.driver = &drv->driver; + + /* call the driver probe() function */ + ret = drv->probe(afu_dev); + if (ret) { + afu_dev->driver = NULL; + afu_dev->device.driver = NULL; + } + + /* return positive value if driver doesn't support this device */ + return 0; +} + +static int +ifpga_probe_all_drivers(struct rte_afu_device *afu_dev) +{ + struct rte_afu_driver *drv = NULL; + int rc; + + if (afu_dev == NULL) + return -1; + + /* Check if a driver is already loaded */ + if (afu_dev->driver != NULL) + return 0; + + TAILQ_FOREACH(drv, &rte_ifpga_bus.driver_list, next) { + rc = ifpga_probe_one_driver(drv, afu_dev); + if (rc < 0) + /* negative value is an error */ + return -1; + if (rc > 0) + /* positive value means driver doesn't support it */ + continue; + return 0; + } + return 1; +} + +/* + * Scan the content of the PCI bus, and call the probe() function for + * all registered drivers that have a matching entry in its id_table + * for discovered devices. + */ +static int +rte_ifpga_probe(void) +{ + struct rte_ifpga_device *ifpga_dev; + struct rte_afu_device *afu_dev = NULL; + int ret = 0; + + TAILQ_FOREACH(ifpga_dev, &rte_ifpga_bus.ifpga_list, next) { + TAILQ_FOREACH(afu_dev, &ifpga_dev->afu_list, next) { + + if (afu_dev->device.driver) + continue; + + ret = ifpga_probe_all_drivers(afu_dev); + if (ret < 0) + IFPGA_BUS_ERR("failed to initialize %s device\n", + rte_ifpga_device_name(afu_dev)); + } + } + + return 0; +} + +static int +rte_ifpga_plug(struct rte_device *dev) +{ + return ifpga_probe_all_drivers(RTE_DEV_TO_AFU(dev)); +} + +static int ifpga_remove_driver(struct rte_afu_device *afu_dev) +{ + const char *name; + const struct rte_afu_driver *driver; + + name = rte_ifpga_device_name(afu_dev); + if (!afu_dev->device.driver) { + IFPGA_BUS_DEBUG("no driver attach to device %s\n", name); + return 1; + } + + driver = container_of(afu_dev->device.driver, + const struct rte_afu_driver, + driver); + return driver->remove(afu_dev); +} + +static int +rte_ifpga_unplug(struct rte_device *dev) +{ + struct rte_ifpga_device *ifpga_dev = NULL; + struct rte_afu_device *afu_dev = NULL; + struct rte_devargs *devargs = NULL; + int ret; + + if (dev == NULL) + return -EINVAL; + + afu_dev = RTE_DEV_TO_AFU(dev); + if (!dev) + return -ENOENT; + + ifpga_dev = afu_dev->ifpga_dev; + devargs = dev->devargs; + + ret = ifpga_remove_driver(afu_dev); + if (ret) + return ret; + + TAILQ_REMOVE(&ifpga_dev->afu_list, afu_dev, next); + + TAILQ_REMOVE(&devargs_list, devargs, next); + + free(devargs->args); + free(devargs); + free(afu_dev); + return 0; + +} + +static struct rte_device * +rte_ifpga_find_device(const struct rte_device *start, + rte_dev_cmp_t cmp, const void *data) +{ + struct rte_ifpga_device *ifpga_dev; + struct rte_afu_device *afu_dev; + + TAILQ_FOREACH(ifpga_dev, &rte_ifpga_bus.ifpga_list, next) { + TAILQ_FOREACH(afu_dev, &ifpga_dev->afu_list, next) { + if (start && &afu_dev->device == start) { + start = NULL; + continue; + } + if (cmp(&afu_dev->device, data) == 0) + return &afu_dev->device; + } + } + return NULL; +} +static int +rte_ifpga_parse(const char *name, void *addr) +{ + int *out = addr; + struct rte_rawdev *rawdev = NULL; + char rawdev_name[RTE_RAWDEV_NAME_MAX_LEN]; + char *c1 = NULL, *c2 = NULL; + int port = IFPGA_BUS_DEV_PORT_MAX; + char str_port[8]; + int str_port_len = 0; + + memset(str_port, 0, 8); + c1 = strchr(name, '|'); + if (c1 != NULL) { + str_port_len = c1-name; + c2 = c1+1; + } + + if (str_port_len < 8 && + str_port_len > 0) { + memcpy(str_port, name, str_port_len); + sscanf(str_port, "%d", &port); + } + + memset(rawdev_name, 0, sizeof(rawdev_name)); + snprintf(rawdev_name, RTE_RAWDEV_NAME_MAX_LEN, "IFPGA:%s", c2); + rawdev = rte_rawdev_pmd_get_named_dev(rawdev_name); + + if ((port < IFPGA_BUS_DEV_PORT_MAX) && + rawdev && + (addr != NULL)) + *out = port; + + if ((port < IFPGA_BUS_DEV_PORT_MAX) && + rawdev) + return 0; + else + return 1; +} + +struct rte_ifpga_bus rte_ifpga_bus = { + .bus = { + .scan = rte_ifpga_scan, + .probe = rte_ifpga_probe, + .find_device = rte_ifpga_find_device, + .plug = rte_ifpga_plug, + .unplug = rte_ifpga_unplug, + .parse = rte_ifpga_parse, + }, + .ifpga_list = TAILQ_HEAD_INITIALIZER(rte_ifpga_bus.ifpga_list), + .driver_list = TAILQ_HEAD_INITIALIZER(rte_ifpga_bus.driver_list), +}; + +RTE_REGISTER_BUS(IFPGA_BUS_NAME, rte_ifpga_bus.bus); + +RTE_INIT(ifpga_init_log) +{ + ifpga_bus_logtype = rte_log_register("bus.ifpga"); + if (ifpga_bus_logtype >= 0) + rte_log_set_level(ifpga_bus_logtype, RTE_LOG_NOTICE); +} + diff --git a/drivers/bus/ifpga/ifpga_common.c b/drivers/bus/ifpga/ifpga_common.c new file mode 100644 index 0000000..124ffd2 --- /dev/null +++ b/drivers/bus/ifpga/ifpga_common.c @@ -0,0 +1,141 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2010-2018 Intel Corporation + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "rte_bus_ifpga.h" +#include "ifpga_logs.h" +#include "ifpga_common.h" + +int ifpga_get_string_arg(const char *key __rte_unused, + const char *value, void *extra_args) +{ + if (!value || !extra_args) + return -EINVAL; + + *(char **)extra_args = strdup(value); + + if (!*(char **)extra_args) + return -ENOMEM; + + return 0; +} +int ifpga_get_integer32_arg(const char *key __rte_unused, + const char *value, void *extra_args) +{ + if (!value || !extra_args) + return -EINVAL; + + *(int *)extra_args = strtoull(value, NULL, 0); + + return 0; +} +int ifpga_get_integer64_arg(const char *key __rte_unused, + const char *value, void *extra_args) +{ + if (!value || !extra_args) + return -EINVAL; + + *(uint64_t *)extra_args = strtoull(value, NULL, 0); + + return 0; +} +int ifpga_get_unsigned_long(const char *str, int base) +{ + unsigned long num; + char *end = NULL; + + errno = 0; + + num = strtoul(str, &end, base); + if ((str[0] == '\0') || (end == NULL) || (*end != '\0') || (errno != 0)) + return -1; + + return num; + +} +int ifpga_get_bdf_arg(const char *key __rte_unused, + const char *value, void *extra_args) +{ +#define MAX_PATH_LEN 1024 + struct rte_pci_addr *addr; + int num[4]; + char str[MAX_PATH_LEN]; + int i, j; + + if (!value || !extra_args) + return -EINVAL; + + addr = (struct rte_pci_addr *)extra_args; + strcpy(str, value); + memset(num, 0, 4 * sizeof(num[0])); + i = strlen(str) - 1; + j = 3; + while (i > 0 && j >= 0) { + while ((str[i - 1] != ':' && str[i - 1] != '.') && i > 0) + i--; + num[j--] = ifpga_get_unsigned_long(&str[i], 16); + i--; + if (i >= 0) + str[i] = '\0'; + } + addr->domain = num[0]; + addr->bus = num[1]; + addr->devid = num[2]; + addr->function = num[3]; + printf("[%s]: bdf %04d:%02d:%02d.%02d\n", + __func__, + addr->domain, + addr->bus, + addr->devid, + addr->function); + + return 0; +} + +int ifpga_afu_id_cmp(const struct rte_afu_id *afu_id0, + const struct rte_afu_id *afu_id1) +{ + if ((afu_id0->pci_addr.bus == afu_id1->pci_addr.bus) && + (afu_id0->pci_addr.devid == afu_id1->pci_addr.devid) && + (afu_id0->pci_addr.function == afu_id1->pci_addr.function) && + (afu_id0->uuid_low == afu_id1->uuid_low) && + (afu_id0->uuid_high == afu_id1->uuid_high) && + (afu_id0->port == afu_id1->port)) { + return 0; + } else + return 1; +} +int ifpga_pci_addr_cmp(const struct rte_device *dev, + const void *_pci_addr) +{ + struct rte_pci_device *pdev; + const struct rte_pci_addr *paddr = _pci_addr; + + pdev = RTE_DEV_TO_PCI(*(struct rte_device **)(void *)&dev); + return rte_eal_compare_pci_addr(&pdev->addr, paddr); +} diff --git a/drivers/bus/ifpga/ifpga_common.h b/drivers/bus/ifpga/ifpga_common.h new file mode 100644 index 0000000..1c85bd3 --- /dev/null +++ b/drivers/bus/ifpga/ifpga_common.h @@ -0,0 +1,22 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2010-2018 Intel Corporation + */ + +#ifndef _IFPGA_COMMON_H_ +#define _IFPGA_COMMON_H_ + +int ifpga_get_string_arg(const char *key __rte_unused, + const char *value, void *extra_args); +int ifpga_get_integer32_arg(const char *key __rte_unused, + const char *value, void *extra_args); +int ifpga_get_integer64_arg(const char *key __rte_unused, + const char *value, void *extra_args); +int ifpga_get_unsigned_long(const char *str, int base); +int ifpga_get_bdf_arg(const char *key __rte_unused, + const char *value, void *extra_args); +int ifpga_afu_id_cmp(const struct rte_afu_id *afu_id0, + const struct rte_afu_id *afu_id1); +int ifpga_pci_addr_cmp(const struct rte_device *dev, + const void *_pci_addr); + +#endif /* _IFPGA_COMMON_H_ */ diff --git a/drivers/bus/ifpga/ifpga_logs.h b/drivers/bus/ifpga/ifpga_logs.h new file mode 100644 index 0000000..873e0a4 --- /dev/null +++ b/drivers/bus/ifpga/ifpga_logs.h @@ -0,0 +1,31 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2010-2018 Intel Corporation + */ + +#ifndef _IFPGA_LOGS_H_ +#define _IFPGA_LOGS_H_ + +#include + +extern int ifpga_bus_logtype; + +#define IFPGA_LOG(level, fmt, args...) \ + rte_log(RTE_LOG_ ## level, ifpga_bus_logtype, "%s(): " fmt "\n", \ + __func__, ##args) + +#define IFPGA_BUS_LOG(level, fmt, args...) \ + rte_log(RTE_LOG_ ## level, ifpga_bus_logtype, "%s(): " fmt "\n", \ + __func__, ##args) + +#define IFPGA_BUS_FUNC_TRACE() IFPGA_BUS_LOG(DEBUG, ">>") + +#define IFPGA_BUS_DEBUG(fmt, args...) \ + IFPGA_BUS_LOG(DEBUG, fmt, ## args) +#define IFPGA_BUS_INFO(fmt, args...) \ + IFPGA_BUS_LOG(INFO, fmt, ## args) +#define IFPGA_BUS_ERR(fmt, args...) \ + IFPGA_BUS_LOG(ERR, fmt, ## args) +#define IFPGA_BUS_WARN(fmt, args...) \ + IFPGA_BUS_LOG(WARNING, fmt, ## args) + +#endif /* _IFPGA_BUS_LOGS_H_ */ diff --git a/drivers/bus/ifpga/rte_bus_ifpga.h b/drivers/bus/ifpga/rte_bus_ifpga.h new file mode 100644 index 0000000..e22ab4e --- /dev/null +++ b/drivers/bus/ifpga/rte_bus_ifpga.h @@ -0,0 +1,175 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2010-2018 Intel Corporation + */ + +#ifndef _RTE_BUS_IFPGA_H_ +#define _RTE_BUS_IFPGA_H_ + +/** + * @file + * + * RTE PCI Bus Interface + */ + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include + +/** Name of Intel FPGA Bus */ +#define IFPGA_BUS_NAME ifpga + +/* Forward declarations */ +struct rte_ifpga_device; +struct rte_afu_device; +struct rte_afu_driver; + +/** List of Intel FPGA devices */ +TAILQ_HEAD(rte_ifpga_device_list, rte_ifpga_device); +/** List of Intel AFU devices */ +TAILQ_HEAD(rte_afu_device_list, rte_afu_device); +/** List of AFU drivers */ +TAILQ_HEAD(rte_afu_driver_list, rte_afu_driver); + +#define IFPGA_BUS_BITSTREAM_PATH_MAX_LEN 256 + +struct rte_afu_uuid { + uint64_t uuid_low; + uint64_t uuid_high; +} __attribute__ ((packed)); + +#define IFPGA_BUS_DEV_PORT_MAX 4 + +/** + * A structure describing an ID for a AFU driver. Each driver provides a + * table of these IDs for each device that it supports. + */ +struct rte_afu_id { + struct rte_pci_addr pci_addr; + uint64_t uuid_low; + uint64_t uuid_high; + int port; +} __attribute__ ((packed)); + +/** + * A structure pr configuration AFU driver. + */ + +struct rte_afu_pr_conf { + struct rte_afu_id afu_id; + int pr_enable; + char bs_path[IFPGA_BUS_BITSTREAM_PATH_MAX_LEN]; +}; + +#define AFU_PRI_STR_SIZE (PCI_PRI_STR_SIZE + 8) + +/** + * A structure describing a fpga device. + */ +struct rte_ifpga_device { + TAILQ_ENTRY(rte_ifpga_device) next; /**< Next in device list. */ + struct rte_pci_addr pci_addr; + struct rte_rawdev *rdev; + struct rte_afu_device_list afu_list; /**< List of AFU devices */ +}; + +/** + * A structure describing a AFU device. + */ +struct rte_afu_device { + TAILQ_ENTRY(rte_afu_device) next; /**< Next in device list. */ + struct rte_device device; /**< Inherit core device */ + struct rte_rawdev *rawdev; /**< Point Rawdev */ + struct rte_ifpga_device *ifpga_dev; /**< Point ifpga device */ + struct rte_afu_id id; /**< AFU id within FPGA. */ + uint32_t num_region; /**< number of regions found */ + struct rte_mem_resource mem_resource[PCI_MAX_RESOURCE]; + /**< PCI Memory Resource */ + struct rte_intr_handle intr_handle; /**< Interrupt handle */ + struct rte_afu_driver *driver; /**< Associated driver */ + char path[IFPGA_BUS_BITSTREAM_PATH_MAX_LEN]; +} __attribute__ ((packed)); + +/** + * @internal + * Helper macro for drivers that need to convert to struct rte_afu_device. + */ +#define RTE_DEV_TO_AFU(ptr) \ + container_of(ptr, struct rte_afu_device, device) + +/** + * Initialisation function for the driver called during PCI probing. + */ +typedef int (afu_probe_t)(struct rte_afu_device *); + +/** + * Uninitialisation function for the driver called during hotplugging. + */ +typedef int (afu_remove_t)(struct rte_afu_device *); + +/** + * A structure describing a PCI device. + */ +struct rte_afu_driver { + TAILQ_ENTRY(rte_afu_driver) next; /**< Next afu driver. */ + struct rte_driver driver; /**< Inherit core driver. */ + afu_probe_t *probe; /**< Device Probe function. */ + afu_remove_t *remove; /**< Device Remove function. */ + const struct rte_afu_uuid *id_table; /**< AFU uuid within FPGA. */ + uint32_t drv_flags; /**< Flags contolling handling of device. */ +}; + +/** + * Structure describing the Intel FPGA bus + */ +struct rte_ifpga_bus { + struct rte_bus bus; /**< Inherit the generic class */ + struct rte_ifpga_device_list ifpga_list; /**< List of FPGA devices */ + struct rte_afu_driver_list driver_list; /**< List of FPGA drivers */ +}; + +static inline const char * +rte_ifpga_device_name(const struct rte_afu_device *afu) +{ + if (afu && afu->device.name) + return afu->device.name; + return NULL; +} + +extern struct rte_ifpga_bus rte_ifpga_bus; + +/** + * Register a ifpga afu device driver. + * + * @param driver + * A pointer to a rte_afu_driver structure describing the driver + * to be registered. + */ +void rte_ifpga_driver_register(struct rte_afu_driver *driver); + +/** + * Unregister a ifpga afu device driver. + * + * @param driver + * A pointer to a rte_afu_driver structure describing the driver + * to be unregistered. + */ +void rte_ifpga_driver_unregister(struct rte_afu_driver *driver); + +#define RTE_PMD_REGISTER_AFU(nm, afudrv)\ +RTE_INIT(afudrvinitfn_ ##afudrv);\ +static const char *afudrvinit_ ## nm ## _alias;\ +static void afudrvinitfn_ ##afudrv(void)\ +{\ + (afudrv).driver.name = RTE_STR(nm);\ + (afudrv).driver.alias = afudrvinit_ ## nm ## _alias;\ + rte_ifpga_driver_register(&afudrv);\ +} \ +RTE_PMD_EXPORT_NAME(nm, __COUNTER__) + +#define RTE_PMD_REGISTER_AFU_ALIAS(nm, alias)\ +static const char *afudrvinit_ ## nm ## _alias = RTE_STR(alias) + +#endif /* _RTE_BUS_IFPGA_H_ */ diff --git a/drivers/bus/ifpga/rte_bus_ifpga_version.map b/drivers/bus/ifpga/rte_bus_ifpga_version.map new file mode 100644 index 0000000..4edc9c0 --- /dev/null +++ b/drivers/bus/ifpga/rte_bus_ifpga_version.map @@ -0,0 +1,8 @@ +DPDK_18.05 { + global: + + rte_ifpga_driver_register; + rte_ifpga_driver_unregister; + + local: *; +}; diff --git a/mk/rte.app.mk b/mk/rte.app.mk index 3eb41d1..929c3d8 100644 --- a/mk/rte.app.mk +++ b/mk/rte.app.mk @@ -107,6 +107,8 @@ _LDLIBS-$(CONFIG_RTE_LIBRTE_CMDLINE) += -lrte_cmdline _LDLIBS-$(CONFIG_RTE_LIBRTE_REORDER) += -lrte_reorder _LDLIBS-$(CONFIG_RTE_LIBRTE_SCHED) += -lrte_sched +_LDLIBS-$(CONFIG_RTE_LIBRTE_IFPGA_BUS) += -lrte_bus_ifpga + ifeq ($(CONFIG_RTE_EXEC_ENV_LINUXAPP),y) _LDLIBS-$(CONFIG_RTE_LIBRTE_KNI) += -lrte_kni endif -- 1.8.3.1