> -----Original Message----- > From: dev <dev-boun...@dpdk.org> On Behalf Of Xueming Li > Sent: Tuesday, April 13, 2021 11:23 > To: Thomas Monjalon <tho...@monjalon.net> > Cc: dev@dpdk.org; xuemi...@nvidia.com; Asaf Penso <as...@nvidia.com>; Parav > Pandit <pa...@nvidia.com>; > Ray Kinsella <m...@ashroe.eu>; Neil Horman <nhor...@tuxdriver.com> > Subject: [dpdk-dev] [PATCH v1] bus/auxiliary: introduce auxiliary bus > > Auxiliary [1] provides a way to split function into child-devices > representing sub-domains of functionality. Each auxiliary_device > represents a part of its parent functionality. > > Auxiliary device is identified by unique device name, sysfs path: > /sys/bus/auxiliary/devices/<name> > > [1] kernel auxiliary bus document: > https://www.kernel.org/doc/html/latest/driver-api/auxiliary_bus.html > > Signed-off-by: Xueming Li <xuemi...@nvidia.com> > --- > MAINTAINERS | 5 + > drivers/bus/auxiliary/auxiliary_common.c | 391 ++++++++++++++++++++++ > drivers/bus/auxiliary/auxiliary_params.c | 58 ++++ > drivers/bus/auxiliary/linux/auxiliary.c | 147 ++++++++ > drivers/bus/auxiliary/meson.build | 17 + > drivers/bus/auxiliary/private.h | 118 +++++++ > drivers/bus/auxiliary/rte_bus_auxiliary.h | 180 ++++++++++ > drivers/bus/auxiliary/version.map | 10 + > drivers/bus/meson.build | 2 +- > 9 files changed, 927 insertions(+), 1 deletion(-) > create mode 100644 drivers/bus/auxiliary/auxiliary_common.c > create mode 100644 drivers/bus/auxiliary/auxiliary_params.c > create mode 100644 drivers/bus/auxiliary/linux/auxiliary.c > create mode 100644 drivers/bus/auxiliary/meson.build > create mode 100644 drivers/bus/auxiliary/private.h > create mode 100644 drivers/bus/auxiliary/rte_bus_auxiliary.h > create mode 100644 drivers/bus/auxiliary/version.map >
> --- /dev/null > +++ b/drivers/bus/auxiliary/auxiliary_common.c > @@ -0,0 +1,391 @@ > +/* SPDX-License-Identifier: BSD-3-Clause > + * Copyright 2021 Mellanox Technologies, Ltd > + */ > + > +#include <string.h> > +#include <inttypes.h> > +#include <stdint.h> > +#include <stdbool.h> > +#include <stdlib.h> > +#include <stdio.h> > +#include <sys/queue.h> > +#include <rte_errno.h> > +#include <rte_interrupts.h> > +#include <rte_log.h> > +#include <rte_bus.h> > +#include <rte_per_lcore.h> > +#include <rte_memory.h> > +#include <rte_eal.h> > +#include <rte_eal_paging.h> > +#include <rte_string_fns.h> > +#include <rte_common.h> > +#include <rte_devargs.h> > + > +#include "private.h" > +#include "rte_bus_auxiliary.h" > + > + > +int auxiliary_bus_logtype; > + > +static struct rte_devargs * > +auxiliary_devargs_lookup(const char *name) > +{ > + struct rte_devargs *devargs; > + > + RTE_EAL_DEVARGS_FOREACH("auxiliary", devargs) { > + if (strcmp(devargs->name, name) == 0) > + return devargs; > + } > + return NULL; > +} > + > +void > +auxiliary_on_scan(struct rte_auxiliary_device *dev) > +{ > + struct rte_devargs *devargs; > + > + devargs = auxiliary_devargs_lookup(dev->name); > + dev->device.devargs = devargs; Can be simple as: dev->device.devargs = auxiliary_devargs_lookup(dev->name); > +} > + > +/* > + * Match the auxiliary Driver and Device using driver function. > + */ > +bool > +auxiliary_match(const struct rte_auxiliary_driver *auxiliary_drv, > + const struct rte_auxiliary_device *auxiliary_dev) How about these auxiliary variable name style ? const struct rte_auxiliary_driver *aux_drv, const struct rte_auxiliary_device *aux_dev > +{ > + if (auxiliary_drv->match == NULL) > + return false; > + return auxiliary_drv->match(auxiliary_dev->name); > +} > + > +/* > + * Call the probe() function of the driver. > + */ > +static int > +rte_auxiliary_probe_one_driver(struct rte_auxiliary_driver *dr, > + struct rte_auxiliary_device *dev) > +{ > + int ret; > + enum rte_iova_mode iova_mode; > + RCT style ? enum rte_iova_mode iova_mode; int ret; > + if ((dr == NULL) || (dev == NULL)) > + return -EINVAL; > + > + /* The device is not blocked; Check if driver supports it */ > + if (!auxiliary_match(dr, dev)) > + /* Match of device and driver failed */ > + return 1; > + > + AUXILIARY_LOG(DEBUG, "Auxiliary device %s on NUMA socket %i\n", > + dev->name, dev->device.numa_node); > + > + /* no initialization when marked as blocked, return without error */ > + if (dev->device.devargs != NULL && > + dev->device.devargs->policy == RTE_DEV_BLOCKED) { > + AUXILIARY_LOG(INFO, " Device is blocked, not initializing\n"); > + return -1; > + } > + > + if (dev->device.numa_node < 0) { > + AUXILIARY_LOG(WARNING, " Invalid NUMA socket, default to 0\n"); > + dev->device.numa_node = 0; > + } > + > + AUXILIARY_LOG(DEBUG, " Probe driver: %s\n", dr->driver.name); > + > + iova_mode = rte_eal_iova_mode(); > + if ((dr->drv_flags & RTE_AUXILIARY_DRV_NEED_IOVA_AS_VA) > 0 && '(dr->drv_flags & RTE_AUXILIARY_DRV_NEED_IOVA_AS_VA)' should work, no need '> 0' > + iova_mode != RTE_IOVA_VA) { > + AUXILIARY_LOG(ERR, " Expecting VA IOVA mode but current mode > is PA, not initializing\n"); > + return -EINVAL; > + } > + > + dev->driver = dr; > + > + AUXILIARY_LOG(INFO, "Probe auxiliary driver: %s device: %s (socket > %i)\n", > + dr->driver.name, dev->name, dev->device.numa_node); > + ret = dr->probe(dr, dev); > + if (ret) > + dev->driver = NULL; > + else > + dev->device.driver = &dr->driver; > + > + return ret; > +} > + > +/* > + * Call the remove() function of the driver. > + */ > +static int > +rte_auxiliary_driver_remove_dev(struct rte_auxiliary_device *dev) > +{ > + struct rte_auxiliary_driver *dr; > + int ret = 0; > + > + if (dev == NULL) > + return -EINVAL; > + > + dr = dev->driver; > + > + AUXILIARY_LOG(DEBUG, "Auxiliary device %s on NUMA socket %i\n", > + dev->name, dev->device.numa_node); > + > + AUXILIARY_LOG(DEBUG, " remove driver: %s %s\n", > + dev->name, dr->driver.name); > + > + if (dr->remove) { > + ret = dr->remove(dev); > + if (ret < 0) > + return ret; > + } > + > + /* clear driver structure */ > + dev->driver = NULL; > + dev->device.driver = NULL; > + > + return 0; > +} > + > +/* > + * Call the probe() function of all registered driver for the given device. > + * Return < 0 if initialization failed. > + * Return 1 if no driver is found for this device. > + */ > +static int > +auxiliary_probe_all_drivers(struct rte_auxiliary_device *dev) > +{ > + struct rte_auxiliary_driver *dr = NULL; > + int rc = 0; These two variables need no initialization. > + > + if (dev == NULL) > + return -EINVAL; > + > + FOREACH_DRIVER_ON_AUXILIARYBUS(dr) { > + if (!dr->match(dev->name)) > + continue; > + > + rc = rte_auxiliary_probe_one_driver(dr, dev); > + if (rc < 0) > + /* negative value is an error */ > + return rc; > + if (rc > 0) > + /* positive value means driver doesn't support it */ > + continue; > + return 0; > + } > + return 1; > +} > + > +static int > +auxiliary_dma_map(struct rte_device *dev, void *addr, uint64_t iova, size_t > len) > +{ > + struct rte_auxiliary_device *adev = RTE_DEV_TO_AUXILIARY(dev); How about to use 'aux_dev', instead of 'adev' ? > + > + if (!adev || !adev->driver) { ' RTE_DEV_TO_AUXILIARY' is container of 'dev', so it should check 'dev != NULL', not '!adev'. ; -) > + rte_errno = EINVAL; > + return -1; > + } > + if (adev->driver->dma_map) > + return adev->driver->dma_map(adev, addr, iova, len); > + rte_errno = ENOTSUP; > + return -1; > +} > + > +static int > +auxiliary_dma_unmap(struct rte_device *dev, void *addr, uint64_t iova, > + size_t len) > +{ > + struct rte_auxiliary_device *adev = RTE_DEV_TO_AUXILIARY(dev); > + > + if (!adev || !adev->driver) { The same comment as 'auxiliary_dma_map' > + rte_errno = EINVAL; > + return -1; > + } > + if (adev->driver->dma_unmap) > + return adev->driver->dma_unmap(adev, addr, iova, len); > + rte_errno = ENOTSUP; > + return -1; > +} > + > --- /dev/null > +++ b/drivers/bus/auxiliary/auxiliary_params.c > @@ -0,0 +1,58 @@ > +/* SPDX-License-Identifier: BSD-3-Clause > + * Copyright 2021 Mellanox Technologies, Ltd > + */ > + > +#include <string.h> > + > +#include <rte_bus.h> > +#include <rte_dev.h> > +#include <rte_errno.h> > +#include <rte_kvargs.h> > + > +#include "private.h" > +#include "rte_bus_auxiliary.h" > + > +enum auxiliary_params { > + RTE_AUXILIARY_PARAM_NAME, > +}; > + > +static const char * const auxiliary_params_keys[] = { > + [RTE_AUXILIARY_PARAM_NAME] = "name", > +}; > + > +static int > +auxiliary_dev_match(const struct rte_device *dev, > + const void *_kvlist) > +{ > + int ret; > + const struct rte_kvargs *kvlist = _kvlist; > + RCT. > + ret = rte_kvargs_process(kvlist, > + auxiliary_params_keys[RTE_AUXILIARY_PARAM_NAME], > + rte_kvargs_strcmp, (void *)(uintptr_t)dev->name); > + > + return ret != 0 ? -1 : 0; > +} > + > +void * > +auxiliary_dev_iterate(const void *start, > + const char *str, > + const struct rte_dev_iterator *it __rte_unused) > +{ > + rte_bus_find_device_t find_device; > + struct rte_kvargs *kvargs = NULL; > + struct rte_device *dev; > + > + if (str != NULL) { > + kvargs = rte_kvargs_parse(str, auxiliary_params_keys); > + if (kvargs == NULL) { > + RTE_LOG(ERR, EAL, "cannot parse argument list\n"); > + rte_errno = EINVAL; > + return NULL; > + } > + } > + find_device = auxiliary_bus.bus.find_device; > + dev = find_device(start, auxiliary_dev_match, kvargs); > + rte_kvargs_free(kvargs); > + return dev; > +} > diff --git a/drivers/bus/auxiliary/linux/auxiliary.c > b/drivers/bus/auxiliary/linux/auxiliary.c > new file mode 100644 > index 0000000000..7888b6c5da > --- /dev/null > +++ b/drivers/bus/auxiliary/linux/auxiliary.c ^ | Seems no need to add one more directory 'linux' layer, as the meson said "linux only". > @@ -0,0 +1,147 @@ > +/* SPDX-License-Identifier: BSD-3-Clause > + * Copyright 2021 Mellanox Technologies, Ltd > + */ > + > +#include <string.h> > +#include <dirent.h> > + > +#include <rte_log.h> > +#include <rte_bus.h> > +#include <rte_malloc.h> > +#include <rte_devargs.h> > +#include <rte_memcpy.h> > +#include <eal_filesystem.h> > + > +#include "../rte_bus_auxiliary.h" > +#include "../private.h" > + > +#define AUXILIARY_SYSFS_PATH "/sys/bus/auxiliary/devices" > + > +/** > + * @file > + * Linux auxiliary probing. > + */ > + > +/* Scan one auxiliary sysfs entry, and fill the devices list from it. */ > +static int > +auxiliary_scan_one(const char *dirname, const char *name) > +{ > + struct rte_auxiliary_device *dev; > + struct rte_auxiliary_device *dev2; > + char filename[PATH_MAX]; > + unsigned long tmp; > + int ret; > + > + dev = malloc(sizeof(*dev)); > + if (dev == NULL) > + return -1; > + > + memset(dev, 0, sizeof(*dev)); > + if (rte_strscpy(dev->name, name, sizeof(dev->name)) < 0) { > + free(dev); > + return -1; > + } > + dev->device.name = dev->name; > + dev->device.bus = &auxiliary_bus.bus; > + > + /* Get numa node, default to 0 if not present */ > + snprintf(filename, sizeof(filename), "%s/%s/numa_node", > + dirname, name); > + if (access(filename, F_OK) != -1) { > + if (eal_parse_sysfs_value(filename, &tmp) == 0) > + dev->device.numa_node = tmp; > + else > + dev->device.numa_node = -1; > + } else { > + dev->device.numa_node = 0; > + } > + > + auxiliary_on_scan(dev); > + > + /* Device is valid, add in list (sorted) */ > + TAILQ_FOREACH(dev2, &auxiliary_bus.device_list, next) { > + ret = strcmp(dev->name, dev2->name); > + if (ret > 0) > + continue; > + if (ret < 0) { > + auxiliary_insert_device(dev2, dev); > + } else { /* already registered */ > + if (rte_dev_is_probed(&dev2->device) && > + dev2->device.devargs != dev->device.devargs) { > + /* To probe device with new devargs. */ > + rte_devargs_remove(dev2->device.devargs); > + auxiliary_on_scan(dev2); > + } > + free(dev); > + } > + return 0; > + } > + auxiliary_add_device(dev); > + return 0; > +} > + > +/* > + * Test whether the auxiliary device exist > + */ > +bool > +auxiliary_exists(const char *name) is_auxiliary_support() ? > +{ > + DIR *dir; > + char dirname[PATH_MAX]; > + > + snprintf(dirname, sizeof(dirname), "%s/%s", > + AUXILIARY_SYSFS_PATH, name); > + dir = opendir(AUXILIARY_SYSFS_PATH); > + if (dir == NULL) > + return true; false > + closedir(dir); > + return false; true > -- > 2.25.1