From: Chengwen Feng Date: Wed, 13 Oct 2021 12:24:58 +0000 (+0800) Subject: dmadev: support multi-process X-Git-Url: http://git.droids-corp.org/?a=commitdiff_plain;h=2ece65f00f71c383c12c567502840ac1584757d5;p=dpdk.git dmadev: support multi-process This patch add multi-process support for dmadev. Signed-off-by: Chengwen Feng Acked-by: Bruce Richardson Acked-by: Morten Brørup Reviewed-by: Kevin Laatz Reviewed-by: Conor Walsh --- diff --git a/doc/guides/rel_notes/release_21_11.rst b/doc/guides/rel_notes/release_21_11.rst index 6a162cc22e..d5435a64aa 100644 --- a/doc/guides/rel_notes/release_21_11.rst +++ b/doc/guides/rel_notes/release_21_11.rst @@ -73,6 +73,7 @@ New Features hardware and software DMA devices. * Added generic API which support a number of different DMA operations. + * Added multi-process support. * **Added new RSS offload types for IPv4/L4 checksum in RSS flow.** diff --git a/lib/dmadev/rte_dmadev.c b/lib/dmadev/rte_dmadev.c index 54e15817fa..7099bbb28d 100644 --- a/lib/dmadev/rte_dmadev.c +++ b/lib/dmadev/rte_dmadev.c @@ -19,6 +19,13 @@ static int16_t dma_devices_max; struct rte_dma_fp_object *rte_dma_fp_objs; struct rte_dma_dev *rte_dma_devices; +static struct { + /* Hold the dev_max information of the primary process. This field is + * set by the primary process and is read by the secondary process. + */ + int16_t dev_max; + struct rte_dma_dev_data data[0]; +} *dma_devices_shared_data; RTE_LOG_REGISTER_DEFAULT(rte_dma_logtype, INFO); #define RTE_DMA_LOG(level, ...) \ @@ -70,11 +77,11 @@ dma_find_free_id(void) { int16_t i; - if (rte_dma_devices == NULL) + if (rte_dma_devices == NULL || dma_devices_shared_data == NULL) return -1; for (i = 0; i < dma_devices_max; i++) { - if (rte_dma_devices[i].state == RTE_DMA_DEV_UNUSED) + if (dma_devices_shared_data->data[i].dev_name[0] == '\0') return i; } @@ -91,7 +98,7 @@ dma_find_by_name(const char *name) for (i = 0; i < dma_devices_max; i++) { if ((rte_dma_devices[i].state != RTE_DMA_DEV_UNUSED) && - (!strcmp(name, rte_dma_devices[i].dev_name))) + (!strcmp(name, rte_dma_devices[i].data->dev_name))) return &rte_dma_devices[i]; } @@ -147,23 +154,71 @@ dma_dev_data_prepare(void) return 0; } +static int +dma_shared_data_prepare(void) +{ + const char *mz_name = "rte_dma_dev_data"; + const struct rte_memzone *mz; + size_t size; + + if (dma_devices_shared_data != NULL) + return 0; + + size = sizeof(*dma_devices_shared_data) + + sizeof(struct rte_dma_dev_data) * dma_devices_max; + + if (rte_eal_process_type() == RTE_PROC_PRIMARY) + mz = rte_memzone_reserve(mz_name, size, rte_socket_id(), 0); + else + mz = rte_memzone_lookup(mz_name); + if (mz == NULL) + return -ENOMEM; + + dma_devices_shared_data = mz->addr; + if (rte_eal_process_type() == RTE_PROC_PRIMARY) { + memset(dma_devices_shared_data, 0, size); + dma_devices_shared_data->dev_max = dma_devices_max; + } else { + dma_devices_max = dma_devices_shared_data->dev_max; + } + + return 0; +} + static int dma_data_prepare(void) { int ret; - if (dma_devices_max == 0) - dma_devices_max = RTE_DMADEV_DEFAULT_MAX; - - ret = dma_fp_data_prepare(); - if (ret) - return ret; + if (rte_eal_process_type() == RTE_PROC_PRIMARY) { + if (dma_devices_max == 0) + dma_devices_max = RTE_DMADEV_DEFAULT_MAX; + ret = dma_fp_data_prepare(); + if (ret) + return ret; + ret = dma_dev_data_prepare(); + if (ret) + return ret; + ret = dma_shared_data_prepare(); + if (ret) + return ret; + } else { + ret = dma_shared_data_prepare(); + if (ret) + return ret; + ret = dma_fp_data_prepare(); + if (ret) + return ret; + ret = dma_dev_data_prepare(); + if (ret) + return ret; + } - return dma_dev_data_prepare(); + return 0; } static struct rte_dma_dev * -dma_allocate(const char *name, int numa_node, size_t private_data_size) +dma_allocate_primary(const char *name, int numa_node, size_t private_data_size) { struct rte_dma_dev *dev; void *dev_private; @@ -197,12 +252,59 @@ dma_allocate(const char *name, int numa_node, size_t private_data_size) } dev = &rte_dma_devices[dev_id]; - rte_strscpy(dev->dev_name, name, sizeof(dev->dev_name)); - dev->dev_id = dev_id; - dev->numa_node = numa_node; - dev->dev_private = dev_private; - dev->fp_obj = &rte_dma_fp_objs[dev_id]; - dma_fp_object_dummy(dev->fp_obj); + dev->data = &dma_devices_shared_data->data[dev_id]; + rte_strscpy(dev->data->dev_name, name, sizeof(dev->data->dev_name)); + dev->data->dev_id = dev_id; + dev->data->numa_node = numa_node; + dev->data->dev_private = dev_private; + + return dev; +} + +static struct rte_dma_dev * +dma_attach_secondary(const char *name) +{ + struct rte_dma_dev *dev; + int16_t i; + int ret; + + ret = dma_data_prepare(); + if (ret < 0) { + RTE_DMA_LOG(ERR, "Cannot initialize dmadevs data"); + return NULL; + } + + for (i = 0; i < dma_devices_max; i++) { + if (!strcmp(dma_devices_shared_data->data[i].dev_name, name)) + break; + } + if (i == dma_devices_max) { + RTE_DMA_LOG(ERR, + "Device %s is not driven by the primary process", + name); + return NULL; + } + + dev = &rte_dma_devices[i]; + dev->data = &dma_devices_shared_data->data[i]; + + return dev; +} + +static struct rte_dma_dev * +dma_allocate(const char *name, int numa_node, size_t private_data_size) +{ + struct rte_dma_dev *dev; + + if (rte_eal_process_type() == RTE_PROC_PRIMARY) + dev = dma_allocate_primary(name, numa_node, private_data_size); + else + dev = dma_attach_secondary(name); + + if (dev) { + dev->fp_obj = &rte_dma_fp_objs[dev->data->dev_id]; + dma_fp_object_dummy(dev->fp_obj); + } return dev; } @@ -210,7 +312,11 @@ dma_allocate(const char *name, int numa_node, size_t private_data_size) static void dma_release(struct rte_dma_dev *dev) { - rte_free(dev->dev_private); + if (rte_eal_process_type() == RTE_PROC_PRIMARY) { + rte_free(dev->data->dev_private); + memset(dev->data, 0, sizeof(struct rte_dma_dev_data)); + } + dma_fp_object_dummy(dev->fp_obj); memset(dev, 0, sizeof(struct rte_dma_dev)); } @@ -245,7 +351,7 @@ rte_dma_pmd_release(const char *name) return -EINVAL; if (dev->state == RTE_DMA_DEV_READY) - return rte_dma_close(dev->dev_id); + return rte_dma_close(dev->data->dev_id); dma_release(dev); return 0; @@ -263,7 +369,7 @@ rte_dma_get_dev_id_by_name(const char *name) if (dev == NULL) return -EINVAL; - return dev->dev_id; + return dev->data->dev_id; } bool @@ -307,9 +413,9 @@ rte_dma_info_get(int16_t dev_id, struct rte_dma_info *dev_info) if (ret != 0) return ret; - dev_info->dev_name = dev->dev_name; + dev_info->dev_name = dev->data->dev_name; dev_info->numa_node = dev->device->numa_node; - dev_info->nb_vchans = dev->dev_conf.nb_vchans; + dev_info->nb_vchans = dev->data->dev_conf.nb_vchans; return 0; } @@ -324,7 +430,7 @@ rte_dma_configure(int16_t dev_id, const struct rte_dma_conf *dev_conf) if (!rte_dma_is_valid(dev_id) || dev_conf == NULL) return -EINVAL; - if (dev->dev_started != 0) { + if (dev->data->dev_started != 0) { RTE_DMA_LOG(ERR, "Device %d must be stopped to allow configuration", dev_id); @@ -356,7 +462,8 @@ rte_dma_configure(int16_t dev_id, const struct rte_dma_conf *dev_conf) ret = (*dev->dev_ops->dev_configure)(dev, dev_conf, sizeof(struct rte_dma_conf)); if (ret == 0) - memcpy(&dev->dev_conf, dev_conf, sizeof(struct rte_dma_conf)); + memcpy(&dev->data->dev_conf, dev_conf, + sizeof(struct rte_dma_conf)); return ret; } @@ -370,12 +477,12 @@ rte_dma_start(int16_t dev_id) if (!rte_dma_is_valid(dev_id)) return -EINVAL; - if (dev->dev_conf.nb_vchans == 0) { + if (dev->data->dev_conf.nb_vchans == 0) { RTE_DMA_LOG(ERR, "Device %d must be configured first", dev_id); return -EINVAL; } - if (dev->dev_started != 0) { + if (dev->data->dev_started != 0) { RTE_DMA_LOG(WARNING, "Device %d already started", dev_id); return 0; } @@ -388,7 +495,7 @@ rte_dma_start(int16_t dev_id) return ret; mark_started: - dev->dev_started = 1; + dev->data->dev_started = 1; return 0; } @@ -401,7 +508,7 @@ rte_dma_stop(int16_t dev_id) if (!rte_dma_is_valid(dev_id)) return -EINVAL; - if (dev->dev_started == 0) { + if (dev->data->dev_started == 0) { RTE_DMA_LOG(WARNING, "Device %d already stopped", dev_id); return 0; } @@ -414,7 +521,7 @@ rte_dma_stop(int16_t dev_id) return ret; mark_stopped: - dev->dev_started = 0; + dev->data->dev_started = 0; return 0; } @@ -428,7 +535,7 @@ rte_dma_close(int16_t dev_id) return -EINVAL; /* Device must be stopped before it can be closed */ - if (dev->dev_started == 1) { + if (dev->data->dev_started == 1) { RTE_DMA_LOG(ERR, "Device %d must be stopped before closing", dev_id); return -EBUSY; @@ -454,7 +561,7 @@ rte_dma_vchan_setup(int16_t dev_id, uint16_t vchan, if (!rte_dma_is_valid(dev_id) || conf == NULL) return -EINVAL; - if (dev->dev_started != 0) { + if (dev->data->dev_started != 0) { RTE_DMA_LOG(ERR, "Device %d must be stopped to allow configuration", dev_id); @@ -466,7 +573,7 @@ rte_dma_vchan_setup(int16_t dev_id, uint16_t vchan, RTE_DMA_LOG(ERR, "Device %d get device info fail", dev_id); return -EINVAL; } - if (dev->dev_conf.nb_vchans == 0) { + if (dev->data->dev_conf.nb_vchans == 0) { RTE_DMA_LOG(ERR, "Device %d must be configured first", dev_id); return -EINVAL; } @@ -540,7 +647,7 @@ rte_dma_stats_get(int16_t dev_id, uint16_t vchan, struct rte_dma_stats *stats) if (!rte_dma_is_valid(dev_id) || stats == NULL) return -EINVAL; - if (vchan >= dev->dev_conf.nb_vchans && + if (vchan >= dev->data->dev_conf.nb_vchans && vchan != RTE_DMA_ALL_VCHAN) { RTE_DMA_LOG(ERR, "Device %d vchan %u out of range", dev_id, vchan); @@ -561,7 +668,7 @@ rte_dma_stats_reset(int16_t dev_id, uint16_t vchan) if (!rte_dma_is_valid(dev_id)) return -EINVAL; - if (vchan >= dev->dev_conf.nb_vchans && + if (vchan >= dev->data->dev_conf.nb_vchans && vchan != RTE_DMA_ALL_VCHAN) { RTE_DMA_LOG(ERR, "Device %d vchan %u out of range", dev_id, vchan); @@ -634,14 +741,14 @@ rte_dma_dump(int16_t dev_id, FILE *f) } (void)fprintf(f, "DMA Dev %d, '%s' [%s]\n", - dev->dev_id, - dev->dev_name, - dev->dev_started ? "started" : "stopped"); + dev->data->dev_id, + dev->data->dev_name, + dev->data->dev_started ? "started" : "stopped"); dma_dump_capability(f, dev_info.dev_capa); (void)fprintf(f, " max_vchans_supported: %u\n", dev_info.max_vchans); (void)fprintf(f, " nb_vchans_configured: %u\n", dev_info.nb_vchans); (void)fprintf(f, " silent_mode: %s\n", - dev->dev_conf.enable_silent ? "on" : "off"); + dev->data->dev_conf.enable_silent ? "on" : "off"); if (dev->dev_ops->dev_dump != NULL) return (*dev->dev_ops->dev_dump)(dev, f); diff --git a/lib/dmadev/rte_dmadev_core.h b/lib/dmadev/rte_dmadev_core.h index a6946052db..236d9d38e5 100644 --- a/lib/dmadev/rte_dmadev_core.h +++ b/lib/dmadev/rte_dmadev_core.h @@ -60,7 +60,7 @@ typedef uint16_t (*rte_dma_completed_status_t)(void *dev_private, */ struct rte_dma_fp_object { /** PMD-specific private data. The driver should copy - * rte_dma_dev.dev_private to this field during initialization. + * rte_dma_dev.data->dev_private to this field during initialization. */ void *dev_private; rte_dma_copy_t copy; diff --git a/lib/dmadev/rte_dmadev_pmd.h b/lib/dmadev/rte_dmadev_pmd.h index d6d2161306..23b07a4e1c 100644 --- a/lib/dmadev/rte_dmadev_pmd.h +++ b/lib/dmadev/rte_dmadev_pmd.h @@ -76,6 +76,27 @@ struct rte_dma_dev_ops { rte_dma_dump_t dev_dump; }; + +/** + * @internal + * The data part, with no function pointers, associated with each DMA device. + * + * This structure is safe to place in shared memory to be common among different + * processes in a multi-process configuration. + * + * @see struct rte_dma_dev::data + */ +struct rte_dma_dev_data { + char dev_name[RTE_DEV_NAME_MAX_LEN]; /**< Unique identifier name */ + int16_t dev_id; /**< Device [external] identifier. */ + int16_t numa_node; /**< Local NUMA memory ID. -1 if unknown. */ + void *dev_private; /**< PMD-specific private data. */ + struct rte_dma_conf dev_conf; /**< DMA device configuration. */ + __extension__ + uint8_t dev_started : 1; /**< Device state: STARTED(1)/STOPPED(0). */ + uint64_t reserved[2]; /**< Reserved for future fields */ +} __rte_cache_aligned; + /** * Possible states of a DMA device. * @@ -94,20 +115,14 @@ enum rte_dma_dev_state { * The generic data structure associated with each DMA device. */ struct rte_dma_dev { - char dev_name[RTE_DEV_NAME_MAX_LEN]; /**< Unique identifier name */ - int16_t dev_id; /**< Device [external] identifier. */ - int16_t numa_node; /**< Local NUMA memory ID. -1 if unknown. */ - void *dev_private; /**< PMD-specific private data. */ /** Device info which supplied during device initialization. */ struct rte_device *device; + struct rte_dma_dev_data *data; /**< Pointer to shared device data. */ /**< Fast-path functions and related data. */ struct rte_dma_fp_object *fp_obj; /** Functions implemented by PMD. */ const struct rte_dma_dev_ops *dev_ops; - struct rte_dma_conf dev_conf; /**< DMA device configuration. */ enum rte_dma_dev_state state; /**< Flag indicating the device state. */ - __extension__ - uint8_t dev_started : 1; /**< Device state: STARTED(1)/STOPPED(0). */ uint64_t reserved[2]; /**< Reserved for future fields. */ } __rte_cache_aligned;