This change adds support for plugging and unplugging CDX devices on the CDX bus. Also, CDX dev iterator support has been added for the CDX bus.
Signed-off-by: Nipun Gupta <nipun.gu...@amd.com> --- drivers/bus/cdx/cdx.c | 142 +++++++++++++++++++++++++++++++--- drivers/bus/cdx/rte_bus_cdx.h | 1 + 2 files changed, 133 insertions(+), 10 deletions(-) diff --git a/drivers/bus/cdx/cdx.c b/drivers/bus/cdx/cdx.c index 9732a32eb1..8c72de9fe4 100644 --- a/drivers/bus/cdx/cdx.c +++ b/drivers/bus/cdx/cdx.c @@ -69,6 +69,7 @@ #include <rte_eal_paging.h> #include <rte_errno.h> #include <rte_devargs.h> +#include <rte_kvargs.h> #include <rte_malloc.h> #include <rte_memcpy.h> #include <rte_vfio.h> @@ -82,6 +83,15 @@ #define CDX_BUS_NAME cdx #define CDX_DEV_PREFIX "cdx-" +enum cdx_params { + RTE_CDX_PARAM_NAME, +}; + +static const char * const cdx_params_keys[] = { + [RTE_CDX_PARAM_NAME] = "name", + NULL, +}; + /** * @file * CDX probing using Linux sysfs. @@ -89,7 +99,7 @@ /* Add a device to CDX bus */ static void -rte_cdx_add_device(struct rte_cdx_device *cdx_dev) +cdx_add_device(struct rte_cdx_device *cdx_dev) { TAILQ_INSERT_TAIL(&rte_cdx_bus.device_list, cdx_dev, next); } @@ -259,7 +269,7 @@ cdx_scan_one(const char *dirname, const char *dev_name) } dev->id.device_id = (uint16_t)tmp; - rte_cdx_add_device(dev); + cdx_add_device(dev); return 0; @@ -276,7 +286,7 @@ cdx_scan_one(const char *dirname, const char *dev_name) * list. */ static int -rte_cdx_scan(void) +cdx_scan(void) { struct dirent *e; DIR *dir; @@ -356,7 +366,7 @@ cdx_unmap_resource(void *requested_addr, size_t size) * Match the CDX Driver and Device using device id and vendor id. */ static int -rte_cdx_match(const struct rte_cdx_driver *cdx_drv, +cdx_match(const struct rte_cdx_driver *cdx_drv, const struct rte_cdx_device *cdx_dev) { const struct rte_cdx_id *id_table; @@ -382,7 +392,7 @@ rte_cdx_match(const struct rte_cdx_driver *cdx_drv, * driver. */ static int -rte_cdx_probe_one_driver(struct rte_cdx_driver *dr, +cdx_probe_one_driver(struct rte_cdx_driver *dr, struct rte_cdx_device *dev) { const char *dev_name = dev->device.name; @@ -393,7 +403,7 @@ rte_cdx_probe_one_driver(struct rte_cdx_driver *dr, return -EINVAL; /* The device is not blocked; Check if driver supports it */ - if (!rte_cdx_match(dr, dev)) + if (!cdx_match(dr, dev)) /* Match of device and driver failed */ return 1; @@ -421,6 +431,7 @@ rte_cdx_probe_one_driver(struct rte_cdx_driver *dr, } else { dev->device.driver = &dr->driver; } + dev->driver = dr; return ret; @@ -447,7 +458,7 @@ cdx_probe_all_drivers(struct rte_cdx_device *dev) return -EINVAL; FOREACH_DRIVER_ON_CDXBUS(dr) { - rc = rte_cdx_probe_one_driver(dr, dev); + rc = cdx_probe_one_driver(dr, dev); if (rc < 0) /* negative value is an error */ return rc; @@ -566,6 +577,71 @@ cdx_find_device(const struct rte_device *start, rte_dev_cmp_t cmp, return NULL; } +/* Remove a device from CDX bus */ +static void +cdx_remove_device(struct rte_cdx_device *cdx_dev) +{ + TAILQ_REMOVE(&rte_cdx_bus.device_list, cdx_dev, next); +} + +/* + * If vendor/device ID match, call the remove() function of the + * driver. + */ +static int +cdx_detach_dev(struct rte_cdx_device *dev) +{ + struct rte_cdx_driver *dr; + int ret = 0; + + if (dev == NULL) + return -EINVAL; + + dr = dev->driver; + + CDX_BUS_DEBUG("detach device %s using driver: %s", + dev->device.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; + + rte_cdx_unmap_device(dev); + + rte_intr_instance_free(dev->intr_handle); + dev->intr_handle = NULL; + + return 0; +} + +static int +cdx_plug(struct rte_device *dev) +{ + return cdx_probe_all_drivers(RTE_DEV_TO_CDX_DEV(dev)); +} + +static int +cdx_unplug(struct rte_device *dev) +{ + struct rte_cdx_device *cdx_dev; + int ret; + + cdx_dev = RTE_DEV_TO_CDX_DEV(dev); + ret = cdx_detach_dev(cdx_dev); + if (ret == 0) { + cdx_remove_device(cdx_dev); + rte_devargs_remove(dev->devargs); + free(cdx_dev); + } + return ret; +} + static int cdx_dma_map(struct rte_device *dev, void *addr, uint64_t iova, size_t len) { @@ -595,7 +671,7 @@ cdx_dma_unmap(struct rte_device *dev, void *addr, uint64_t iova, size_t len) } static enum rte_iova_mode -rte_cdx_get_iommu_class(void) +cdx_get_iommu_class(void) { if (TAILQ_EMPTY(&rte_cdx_bus.device_list)) return RTE_IOVA_DC; @@ -603,15 +679,61 @@ rte_cdx_get_iommu_class(void) return RTE_IOVA_VA; } +static int +cdx_dev_match(const struct rte_device *dev, + const void *_kvlist) +{ + const struct rte_kvargs *kvlist = _kvlist; + const char *key = cdx_params_keys[RTE_CDX_PARAM_NAME]; + const char *name; + + /* no kvlist arg, all devices match */ + if (kvlist == NULL) + return 0; + + /* if key is present in kvlist and does not match, filter device */ + name = rte_kvargs_get(kvlist, key); + if (name != NULL && strcmp(name, dev->name)) + return -1; + + return 0; +} + +static void * +cdx_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, cdx_params_keys); + if (kvargs == NULL) { + CDX_BUS_ERR("cannot parse argument list %s", str); + rte_errno = EINVAL; + return NULL; + } + } + find_device = rte_cdx_bus.bus.find_device; + dev = find_device(start, cdx_dev_match, kvargs); + rte_kvargs_free(kvargs); + return dev; +} + struct rte_cdx_bus rte_cdx_bus = { .bus = { - .scan = rte_cdx_scan, + .scan = cdx_scan, .probe = cdx_probe, .find_device = cdx_find_device, + .plug = cdx_plug, + .unplug = cdx_unplug, .parse = cdx_parse, .dma_map = cdx_dma_map, .dma_unmap = cdx_dma_unmap, - .get_iommu_class = rte_cdx_get_iommu_class, + .get_iommu_class = cdx_get_iommu_class, + .dev_iterate = cdx_dev_iterate, }, .device_list = TAILQ_HEAD_INITIALIZER(rte_cdx_bus.device_list), .driver_list = TAILQ_HEAD_INITIALIZER(rte_cdx_bus.driver_list), diff --git a/drivers/bus/cdx/rte_bus_cdx.h b/drivers/bus/cdx/rte_bus_cdx.h index a6170347dd..a715dee50b 100644 --- a/drivers/bus/cdx/rte_bus_cdx.h +++ b/drivers/bus/cdx/rte_bus_cdx.h @@ -78,6 +78,7 @@ struct rte_cdx_id { struct rte_cdx_device { RTE_TAILQ_ENTRY(rte_cdx_device) next; /**< Next probed CDX device. */ struct rte_device device; /**< Inherit core device */ + struct rte_cdx_driver *driver; /**< CDX driver used in probing */ struct rte_cdx_id id; /**< CDX ID. */ struct rte_mem_resource mem_resource[CDX_MAX_RESOURCE]; /**< CDX Memory Resource */ -- 2.17.1