bus/auxiliary: introduce auxiliary bus

Auxiliary bus [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>

Devargs legacy syntax of auxiliary device:
  -a auxiliary:<name>[,args...]
Devargs generic syntax of auxiliary device:
  -a bus=auxiliary,name=<name>/class=<class>/driver=<driver>[,args...]

[1] kernel auxiliary bus document:
https://www.kernel.org/doc/html/latest/driver-api/auxiliary_bus.html

Signed-off-by: Xueming Li <xuemingl@nvidia.com>
Acked-by: Andrew Rybchenko <andrew.rybchenko@oktetlabs.ru>
Acked-by: Thomas Monjalon <thomas@monjalon.net>
This commit is contained in:
Xueming Li 2021-07-05 14:45:12 +08:00 committed by Thomas Monjalon
parent 35d4f17b3d
commit 1afce3086c
10 changed files with 927 additions and 0 deletions

View File

@ -525,6 +525,11 @@ F: doc/guides/mempool/octeontx2.rst
Bus Drivers Bus Drivers
----------- -----------
Auxiliary bus driver - EXPERIMENTAL
M: Parav Pandit <parav@nvidia.com>
M: Xueming Li <xuemingl@nvidia.com>
F: drivers/bus/auxiliary/
Intel FPGA bus Intel FPGA bus
M: Rosen Xu <rosen.xu@intel.com> M: Rosen Xu <rosen.xu@intel.com>
F: drivers/bus/ifpga/ F: drivers/bus/ifpga/

View File

@ -55,6 +55,12 @@ New Features
Also, make sure to start the actual text at the margin. Also, make sure to start the actual text at the margin.
======================================================= =======================================================
* **Added auxiliary bus support.**
Auxiliary bus provides a way to split function into child-devices
representing sub-domains of functionality. Each auxiliary device
represents a part of its parent functionality.
Removed Items Removed Items
------------- -------------

View File

@ -0,0 +1,408 @@
/* SPDX-License-Identifier: BSD-3-Clause
* Copyright (c) 2021 NVIDIA Corporation & Affiliates
*/
#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"
static struct rte_devargs *
auxiliary_devargs_lookup(const char *name)
{
struct rte_devargs *devargs;
RTE_EAL_DEVARGS_FOREACH(RTE_BUS_AUXILIARY_NAME, devargs) {
if (strcmp(devargs->name, name) == 0)
return devargs;
}
return NULL;
}
/*
* Test whether the auxiliary device exist.
*
* Stub for OS not supporting auxiliary bus.
*/
__rte_weak bool
auxiliary_dev_exists(const char *name)
{
RTE_SET_USED(name);
return false;
}
/*
* Scan the devices in the auxiliary bus.
*
* Stub for OS not supporting auxiliary bus.
*/
__rte_weak int
auxiliary_scan(void)
{
return 0;
}
/*
* Update a device's devargs being scanned.
*/
void
auxiliary_on_scan(struct rte_auxiliary_device *aux_dev)
{
aux_dev->device.devargs = auxiliary_devargs_lookup(aux_dev->name);
}
/*
* Match the auxiliary driver and device using driver function.
*/
bool
auxiliary_match(const struct rte_auxiliary_driver *aux_drv,
const struct rte_auxiliary_device *aux_dev)
{
if (aux_drv->match == NULL)
return false;
return aux_drv->match(aux_dev->name);
}
/*
* Call the probe() function of the driver.
*/
static int
rte_auxiliary_probe_one_driver(struct rte_auxiliary_driver *drv,
struct rte_auxiliary_device *dev)
{
enum rte_iova_mode iova_mode;
int ret;
if (drv == NULL || dev == NULL)
return -EINVAL;
/* Check if driver supports it. */
if (!auxiliary_match(drv, dev))
/* Match of device and driver failed */
return 1;
/* 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");
return -1;
}
if (dev->device.numa_node < 0) {
AUXILIARY_LOG(INFO, "Device is not NUMA-aware, defaulting NUMA node to 0");
dev->device.numa_node = 0;
}
iova_mode = rte_eal_iova_mode();
if ((drv->drv_flags & RTE_AUXILIARY_DRV_NEED_IOVA_AS_VA) > 0 &&
iova_mode != RTE_IOVA_VA) {
AUXILIARY_LOG(ERR, "Driver %s expecting VA IOVA mode but current mode is PA, not initializing",
drv->driver.name);
return -EINVAL;
}
dev->driver = drv;
AUXILIARY_LOG(INFO, "Probe auxiliary driver: %s device: %s (NUMA node %i)",
drv->driver.name, dev->name, dev->device.numa_node);
ret = drv->probe(drv, dev);
if (ret != 0)
dev->driver = NULL;
else
dev->device.driver = &drv->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 *drv;
int ret = 0;
if (dev == NULL)
return -EINVAL;
drv = dev->driver;
AUXILIARY_LOG(DEBUG, "Driver %s remove auxiliary device %s on NUMA node %i",
drv->driver.name, dev->name, dev->device.numa_node);
if (drv->remove != NULL) {
ret = drv->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 drivers 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 *drv;
int rc;
if (dev == NULL)
return -EINVAL;
FOREACH_DRIVER_ON_AUXILIARY_BUS(drv) {
if (!drv->match(dev->name))
continue;
rc = rte_auxiliary_probe_one_driver(drv, 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;
}
/*
* Scan the content of the auxiliary bus, and call the probe function for
* all registered drivers to try to probe discovered devices.
*/
static int
auxiliary_probe(void)
{
struct rte_auxiliary_device *dev = NULL;
size_t probed = 0, failed = 0;
int ret = 0;
FOREACH_DEVICE_ON_AUXILIARY_BUS(dev) {
probed++;
ret = auxiliary_probe_all_drivers(dev);
if (ret < 0) {
if (ret != -EEXIST) {
AUXILIARY_LOG(ERR, "Requested device %s cannot be used",
dev->name);
rte_errno = errno;
failed++;
}
ret = 0;
}
}
return (probed && probed == failed) ? -1 : 0;
}
static int
auxiliary_parse(const char *name, void *addr)
{
struct rte_auxiliary_driver *drv = NULL;
const char **out = addr;
/* Allow empty device name "auxiliary:" to bypass entire bus scan. */
if (strlen(name) == 0)
return 0;
FOREACH_DRIVER_ON_AUXILIARY_BUS(drv) {
if (drv->match(name))
break;
}
if (drv != NULL && addr != NULL)
*out = name;
return drv != NULL ? 0 : -1;
}
/* Register a driver */
void
rte_auxiliary_register(struct rte_auxiliary_driver *driver)
{
TAILQ_INSERT_TAIL(&auxiliary_bus.driver_list, driver, next);
driver->bus = &auxiliary_bus;
}
/* Unregister a driver */
void
rte_auxiliary_unregister(struct rte_auxiliary_driver *driver)
{
TAILQ_REMOVE(&auxiliary_bus.driver_list, driver, next);
driver->bus = NULL;
}
/* Add a device to auxiliary bus */
void
auxiliary_add_device(struct rte_auxiliary_device *aux_dev)
{
TAILQ_INSERT_TAIL(&auxiliary_bus.device_list, aux_dev, next);
}
/* Insert a device into a predefined position in auxiliary bus */
void
auxiliary_insert_device(struct rte_auxiliary_device *exist_aux_dev,
struct rte_auxiliary_device *new_aux_dev)
{
TAILQ_INSERT_BEFORE(exist_aux_dev, new_aux_dev, next);
}
/* Remove a device from auxiliary bus */
static void
rte_auxiliary_remove_device(struct rte_auxiliary_device *auxiliary_dev)
{
TAILQ_REMOVE(&auxiliary_bus.device_list, auxiliary_dev, next);
}
static struct rte_device *
auxiliary_find_device(const struct rte_device *start, rte_dev_cmp_t cmp,
const void *data)
{
const struct rte_auxiliary_device *pstart;
struct rte_auxiliary_device *adev;
if (start != NULL) {
pstart = RTE_DEV_TO_AUXILIARY_CONST(start);
adev = TAILQ_NEXT(pstart, next);
} else {
adev = TAILQ_FIRST(&auxiliary_bus.device_list);
}
while (adev != NULL) {
if (cmp(&adev->device, data) == 0)
return &adev->device;
adev = TAILQ_NEXT(adev, next);
}
return NULL;
}
static int
auxiliary_plug(struct rte_device *dev)
{
if (!auxiliary_dev_exists(dev->name))
return -ENOENT;
return auxiliary_probe_all_drivers(RTE_DEV_TO_AUXILIARY(dev));
}
static int
auxiliary_unplug(struct rte_device *dev)
{
struct rte_auxiliary_device *adev;
int ret;
adev = RTE_DEV_TO_AUXILIARY(dev);
ret = rte_auxiliary_driver_remove_dev(adev);
if (ret == 0) {
rte_auxiliary_remove_device(adev);
rte_devargs_remove(dev->devargs);
free(adev);
}
return ret;
}
static int
auxiliary_dma_map(struct rte_device *dev, void *addr, uint64_t iova, size_t len)
{
struct rte_auxiliary_device *aux_dev = RTE_DEV_TO_AUXILIARY(dev);
if (dev == NULL || aux_dev->driver == NULL) {
rte_errno = EINVAL;
return -1;
}
if (aux_dev->driver->dma_map == NULL) {
rte_errno = ENOTSUP;
return -1;
}
return aux_dev->driver->dma_map(aux_dev, addr, iova, len);
}
static int
auxiliary_dma_unmap(struct rte_device *dev, void *addr, uint64_t iova,
size_t len)
{
struct rte_auxiliary_device *aux_dev = RTE_DEV_TO_AUXILIARY(dev);
if (dev == NULL || aux_dev->driver == NULL) {
rte_errno = EINVAL;
return -1;
}
if (aux_dev->driver->dma_unmap == NULL) {
rte_errno = ENOTSUP;
return -1;
}
return aux_dev->driver->dma_unmap(aux_dev, addr, iova, len);
}
bool
auxiliary_is_ignored_device(const char *name)
{
struct rte_devargs *devargs = auxiliary_devargs_lookup(name);
switch (auxiliary_bus.bus.conf.scan_mode) {
case RTE_BUS_SCAN_ALLOWLIST:
if (devargs && devargs->policy == RTE_DEV_ALLOWED)
return false;
break;
case RTE_BUS_SCAN_UNDEFINED:
case RTE_BUS_SCAN_BLOCKLIST:
if (devargs == NULL || devargs->policy != RTE_DEV_BLOCKED)
return false;
break;
}
return true;
}
static enum rte_iova_mode
auxiliary_get_iommu_class(void)
{
const struct rte_auxiliary_driver *drv;
FOREACH_DRIVER_ON_AUXILIARY_BUS(drv) {
if ((drv->drv_flags & RTE_AUXILIARY_DRV_NEED_IOVA_AS_VA) > 0)
return RTE_IOVA_VA;
}
return RTE_IOVA_DC;
}
struct rte_auxiliary_bus auxiliary_bus = {
.bus = {
.scan = auxiliary_scan,
.probe = auxiliary_probe,
.find_device = auxiliary_find_device,
.plug = auxiliary_plug,
.unplug = auxiliary_unplug,
.parse = auxiliary_parse,
.dma_map = auxiliary_dma_map,
.dma_unmap = auxiliary_dma_unmap,
.get_iommu_class = auxiliary_get_iommu_class,
.dev_iterate = auxiliary_dev_iterate,
},
.device_list = TAILQ_HEAD_INITIALIZER(auxiliary_bus.device_list),
.driver_list = TAILQ_HEAD_INITIALIZER(auxiliary_bus.driver_list),
};
RTE_REGISTER_BUS(auxiliary, auxiliary_bus.bus);
RTE_LOG_REGISTER_DEFAULT(auxiliary_bus_logtype, NOTICE);

View File

@ -0,0 +1,59 @@
/* SPDX-License-Identifier: BSD-3-Clause
* Copyright (c) 2021 NVIDIA Corporation & Affiliates
*/
#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)
{
const struct rte_kvargs *kvlist = _kvlist;
int ret;
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) {
AUXILIARY_LOG(ERR, "cannot parse argument list %s",
str);
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;
}

View File

@ -0,0 +1,141 @@
/* SPDX-License-Identifier: BSD-3-Clause
* Copyright (c) 2021 NVIDIA Corporation & Affiliates
*/
#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"
/* 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_dev_exists(const char *name)
{
DIR *dir;
char dirname[PATH_MAX];
snprintf(dirname, sizeof(dirname), "%s/%s",
AUXILIARY_SYSFS_PATH, name);
dir = opendir(dirname);
if (dir == NULL)
return false;
closedir(dir);
return true;
}
/*
* Scan the devices in the auxiliary bus.
*/
int
auxiliary_scan(void)
{
struct dirent *e;
DIR *dir;
char dirname[PATH_MAX];
struct rte_auxiliary_driver *drv;
dir = opendir(AUXILIARY_SYSFS_PATH);
if (dir == NULL) {
AUXILIARY_LOG(INFO, "%s not found, is auxiliary module loaded?",
AUXILIARY_SYSFS_PATH);
return 0;
}
while ((e = readdir(dir)) != NULL) {
if (e->d_name[0] == '.')
continue;
if (auxiliary_is_ignored_device(e->d_name))
continue;
snprintf(dirname, sizeof(dirname), "%s/%s",
AUXILIARY_SYSFS_PATH, e->d_name);
/* Ignore if no driver can handle. */
FOREACH_DRIVER_ON_AUXILIARY_BUS(drv) {
if (drv->match(e->d_name))
break;
}
if (drv == NULL)
continue;
if (auxiliary_scan_one(dirname, e->d_name) < 0)
goto error;
}
closedir(dir);
return 0;
error:
closedir(dir);
return -1;
}

View File

@ -0,0 +1,16 @@
# SPDX-License-Identifier: BSD-3-Clause
# Copyright (c) 2021 NVIDIA Corporation & Affiliates
headers = files(
'rte_bus_auxiliary.h',
)
sources = files(
'auxiliary_common.c',
'auxiliary_params.c',
)
if is_linux
sources += files(
'linux/auxiliary.c',
)
endif
deps += ['kvargs']

View File

@ -0,0 +1,91 @@
/* SPDX-License-Identifier: BSD-3-Clause
* Copyright (c) 2021 NVIDIA Corporation & Affiliates
*/
#ifndef BUS_AUXILIARY_PRIVATE_H
#define BUS_AUXILIARY_PRIVATE_H
#include <stdbool.h>
#include <stdio.h>
#include "rte_bus_auxiliary.h"
extern struct rte_auxiliary_bus auxiliary_bus;
extern int auxiliary_bus_logtype;
#define AUXILIARY_LOG(level, ...) \
rte_log(RTE_LOG_ ## level, auxiliary_bus_logtype, \
RTE_FMT("auxiliary bus: " RTE_FMT_HEAD(__VA_ARGS__,) "\n", \
RTE_FMT_TAIL(__VA_ARGS__,)))
/* Auxiliary bus iterators */
#define FOREACH_DEVICE_ON_AUXILIARY_BUS(p) \
TAILQ_FOREACH(p, &(auxiliary_bus.device_list), next)
#define FOREACH_DRIVER_ON_AUXILIARY_BUS(p) \
TAILQ_FOREACH(p, &(auxiliary_bus.driver_list), next)
/* List of auxiliary devices. */
TAILQ_HEAD(rte_auxiliary_device_list, rte_auxiliary_device);
/* List of auxiliary drivers. */
TAILQ_HEAD(rte_auxiliary_driver_list, rte_auxiliary_driver);
/*
* Structure describing the auxiliary bus
*/
struct rte_auxiliary_bus {
struct rte_bus bus; /* Inherit the generic class */
struct rte_auxiliary_device_list device_list; /* List of devices */
struct rte_auxiliary_driver_list driver_list; /* List of drivers */
};
/*
* Test whether the auxiliary device exist.
*/
bool auxiliary_dev_exists(const char *name);
/*
* Scan the content of the auxiliary bus, and the devices in the devices
* list.
*/
int auxiliary_scan(void);
/*
* Update a device being scanned.
*/
void auxiliary_on_scan(struct rte_auxiliary_device *aux_dev);
/*
* Validate whether a device with given auxiliary device should be ignored
* or not.
*/
bool auxiliary_is_ignored_device(const char *name);
/*
* Add an auxiliary device to the auxiliary bus (append to auxiliary device
* list). This function also updates the bus references of the auxiliary
* device and the generic device object embedded within.
*/
void auxiliary_add_device(struct rte_auxiliary_device *aux_dev);
/*
* Insert an auxiliary device in the auxiliary bus at a particular location
* in the device list. It also updates the auxiliary bus reference of the
* new devices to be inserted.
*/
void auxiliary_insert_device(struct rte_auxiliary_device *exist_aux_dev,
struct rte_auxiliary_device *new_aux_dev);
/*
* Match the auxiliary driver and device by driver function.
*/
bool auxiliary_match(const struct rte_auxiliary_driver *aux_drv,
const struct rte_auxiliary_device *aux_dev);
/*
* Iterate over devices, matching any device against the provided string.
*/
void *auxiliary_dev_iterate(const void *start, const char *str,
const struct rte_dev_iterator *it);
#endif /* BUS_AUXILIARY_PRIVATE_H */

View File

@ -0,0 +1,193 @@
/* SPDX-License-Identifier: BSD-3-Clause
* Copyright (c) 2021 NVIDIA Corporation & Affiliates
*/
#ifndef RTE_BUS_AUXILIARY_H
#define RTE_BUS_AUXILIARY_H
/**
* @file
*
* Auxiliary Bus Interface.
*/
#ifdef __cplusplus
extern "C" {
#endif
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#include <errno.h>
#include <sys/queue.h>
#include <stdint.h>
#include <inttypes.h>
#include <rte_debug.h>
#include <rte_interrupts.h>
#include <rte_dev.h>
#include <rte_bus.h>
#include <rte_kvargs.h>
#define RTE_BUS_AUXILIARY_NAME "auxiliary"
/* Forward declarations */
struct rte_auxiliary_driver;
struct rte_auxiliary_bus;
struct rte_auxiliary_device;
/**
* Match function for the driver to decide if device can be handled.
*
* @param name
* Pointer to the auxiliary device name.
* @return
* Whether the driver can handle the auxiliary device.
*/
typedef bool(rte_auxiliary_match_t)(const char *name);
/**
* Initialization function for the driver called during auxiliary probing.
*
* @param drv
* Pointer to the auxiliary driver.
* @param dev
* Pointer to the auxiliary device.
* @return
* - 0 On success.
* - Negative value and rte_errno is set otherwise.
*/
typedef int(rte_auxiliary_probe_t)(struct rte_auxiliary_driver *drv,
struct rte_auxiliary_device *dev);
/**
* Uninitialization function for the driver called during hotplugging.
*
* @param dev
* Pointer to the auxiliary device.
* @return
* - 0 On success.
* - Negative value and rte_errno is set otherwise.
*/
typedef int (rte_auxiliary_remove_t)(struct rte_auxiliary_device *dev);
/**
* Driver-specific DMA mapping. After a successful call the device
* will be able to read/write from/to this segment.
*
* @param dev
* Pointer to the auxiliary device.
* @param addr
* Starting virtual address of memory to be mapped.
* @param iova
* Starting IOVA address of memory to be mapped.
* @param len
* Length of memory segment being mapped.
* @return
* - 0 On success.
* - Negative value and rte_errno is set otherwise.
*/
typedef int (rte_auxiliary_dma_map_t)(struct rte_auxiliary_device *dev,
void *addr, uint64_t iova, size_t len);
/**
* Driver-specific DMA un-mapping. After a successful call the device
* will not be able to read/write from/to this segment.
*
* @param dev
* Pointer to the auxiliary device.
* @param addr
* Starting virtual address of memory to be unmapped.
* @param iova
* Starting IOVA address of memory to be unmapped.
* @param len
* Length of memory segment being unmapped.
* @return
* - 0 On success.
* - Negative value and rte_errno is set otherwise.
*/
typedef int (rte_auxiliary_dma_unmap_t)(struct rte_auxiliary_device *dev,
void *addr, uint64_t iova, size_t len);
/**
* A structure describing an auxiliary device.
*/
struct rte_auxiliary_device {
TAILQ_ENTRY(rte_auxiliary_device) next; /**< Next probed device. */
struct rte_device device; /**< Inherit core device */
char name[RTE_DEV_NAME_MAX_LEN + 1]; /**< ASCII device name */
struct rte_intr_handle intr_handle; /**< Interrupt handle */
struct rte_auxiliary_driver *driver; /**< Device driver */
};
/**
* A structure describing an auxiliary driver.
*/
struct rte_auxiliary_driver {
TAILQ_ENTRY(rte_auxiliary_driver) next; /**< Next in list. */
struct rte_driver driver; /**< Inherit core driver. */
struct rte_auxiliary_bus *bus; /**< Auxiliary bus reference. */
rte_auxiliary_match_t *match; /**< Device match function. */
rte_auxiliary_probe_t *probe; /**< Device probe function. */
rte_auxiliary_remove_t *remove; /**< Device remove function. */
rte_auxiliary_dma_map_t *dma_map; /**< Device DMA map function. */
rte_auxiliary_dma_unmap_t *dma_unmap; /**< Device DMA unmap function. */
uint32_t drv_flags; /**< Flags RTE_AUXILIARY_DRV_*. */
};
/**
* @internal
* Helper macro for drivers that need to convert to struct rte_auxiliary_device.
*/
#define RTE_DEV_TO_AUXILIARY(ptr) \
container_of(ptr, struct rte_auxiliary_device, device)
#define RTE_DEV_TO_AUXILIARY_CONST(ptr) \
container_of(ptr, const struct rte_auxiliary_device, device)
#define RTE_ETH_DEV_TO_AUXILIARY(eth_dev) \
RTE_DEV_TO_AUXILIARY((eth_dev)->device)
/** Device driver needs IOVA as VA and cannot work with IOVA as PA */
#define RTE_AUXILIARY_DRV_NEED_IOVA_AS_VA 0x002
/**
* Register an auxiliary driver.
*
* @warning
* @b EXPERIMENTAL: this API may change without prior notice.
*
* @param driver
* A pointer to a rte_auxiliary_driver structure describing the driver
* to be registered.
*/
__rte_experimental
void rte_auxiliary_register(struct rte_auxiliary_driver *driver);
/** Helper for auxiliary device registration from driver instance */
#define RTE_PMD_REGISTER_AUXILIARY(nm, auxiliary_drv) \
RTE_INIT(auxiliaryinitfn_ ##nm) \
{ \
(auxiliary_drv).driver.name = RTE_STR(nm); \
rte_auxiliary_register(&(auxiliary_drv)); \
} \
RTE_PMD_EXPORT_NAME(nm, __COUNTER__)
/**
* Unregister an auxiliary driver.
*
* @warning
* @b EXPERIMENTAL: this API may change without prior notice.
*
* @param driver
* A pointer to a rte_auxiliary_driver structure describing the driver
* to be unregistered.
*/
__rte_experimental
void rte_auxiliary_unregister(struct rte_auxiliary_driver *driver);
#ifdef __cplusplus
}
#endif
#endif /* RTE_BUS_AUXILIARY_H */

View File

@ -0,0 +1,7 @@
EXPERIMENTAL {
global:
# added in 21.08
rte_auxiliary_register;
rte_auxiliary_unregister;
};

View File

@ -2,6 +2,7 @@
# Copyright(c) 2017 Intel Corporation # Copyright(c) 2017 Intel Corporation
drivers = [ drivers = [
'auxiliary',
'dpaa', 'dpaa',
'fslmc', 'fslmc',
'ifpga', 'ifpga',