[v5,04/16] dma/idxd: create dmadev instances on bus probe
Checks
Commit Message
When a suitable device is found during the bus scan/probe, create a dmadev
instance for each HW queue. Internal structures required for device
creation are also added.
Signed-off-by: Bruce Richardson <bruce.richardson@intel.com>
Signed-off-by: Kevin Laatz <kevin.laatz@intel.com>
Reviewed-by: Conor Walsh <conor.walsh@intel.com>
---
v4:
- fix 'vdev' naming, changed to 'bus'
- rebase changes
---
drivers/dma/idxd/idxd_bus.c | 19 ++++++++
drivers/dma/idxd/idxd_common.c | 76 ++++++++++++++++++++++++++++++++
drivers/dma/idxd/idxd_internal.h | 40 +++++++++++++++++
drivers/dma/idxd/meson.build | 1 +
4 files changed, 136 insertions(+)
create mode 100644 drivers/dma/idxd/idxd_common.c
Comments
On 2021/9/17 23:24, Kevin Laatz wrote:
> When a suitable device is found during the bus scan/probe, create a dmadev
> instance for each HW queue. Internal structures required for device
> creation are also added.
>
> Signed-off-by: Bruce Richardson <bruce.richardson@intel.com>
> Signed-off-by: Kevin Laatz <kevin.laatz@intel.com>
> Reviewed-by: Conor Walsh <conor.walsh@intel.com>
>
> ---
> v4:
> - fix 'vdev' naming, changed to 'bus'
> - rebase changes
> ---
> drivers/dma/idxd/idxd_bus.c | 19 ++++++++
> drivers/dma/idxd/idxd_common.c | 76 ++++++++++++++++++++++++++++++++
> drivers/dma/idxd/idxd_internal.h | 40 +++++++++++++++++
> drivers/dma/idxd/meson.build | 1 +
> 4 files changed, 136 insertions(+)
> create mode 100644 drivers/dma/idxd/idxd_common.c
>
> diff --git a/drivers/dma/idxd/idxd_bus.c b/drivers/dma/idxd/idxd_bus.c
> index ef589af30e..b48fa954ed 100644
> --- a/drivers/dma/idxd/idxd_bus.c
> +++ b/drivers/dma/idxd/idxd_bus.c
> @@ -85,6 +85,18 @@ dsa_get_sysfs_path(void)
> return path ? path : DSA_SYSFS_PATH;
> }
>
> +static int
> +idxd_dev_close(struct rte_dma_dev *dev)
> +{
> + struct idxd_dmadev *idxd = dev->data->dev_private;
> + munmap(idxd->portal, 0x1000);
> + return 0;
> +}
> +
> +static const struct rte_dma_dev_ops idxd_bus_ops = {
> + .dev_close = idxd_dev_close,
> +};
> +
> static void *
> idxd_bus_mmap_wq(struct rte_dsa_device *dev)
> {
> @@ -206,6 +218,7 @@ idxd_probe_dsa(struct rte_dsa_device *dev)
> return -1;
> idxd.max_batch_size = ret;
> idxd.qid = dev->addr.wq_id;
> + idxd.u.bus.dsa_id = dev->addr.device_id;
> idxd.sva_support = 1;
>
> idxd.portal = idxd_bus_mmap_wq(dev);
> @@ -214,6 +227,12 @@ idxd_probe_dsa(struct rte_dsa_device *dev)
> return -ENOENT;
> }
>
> + ret = idxd_dmadev_create(dev->wq_name, &dev->device, &idxd, &idxd_bus_ops);
> + if (ret) {
> + IDXD_PMD_ERR("Failed to create rawdev %s", dev->wq_name);
> + return ret;
> + }
> +
> return 0;
> }
>
> diff --git a/drivers/dma/idxd/idxd_common.c b/drivers/dma/idxd/idxd_common.c
> new file mode 100644
> index 0000000000..8afad637fc
> --- /dev/null
> +++ b/drivers/dma/idxd/idxd_common.c
> @@ -0,0 +1,76 @@
> +/* SPDX-License-Identifier: BSD-3-Clause
> + * Copyright 2021 Intel Corporation
> + */
> +
> +#include <rte_dmadev_pmd.h>
> +#include <rte_malloc.h>
> +#include <rte_common.h>
> +
> +#include "idxd_internal.h"
> +
> +#define IDXD_PMD_NAME_STR "dmadev_idxd"
> +
> +int
> +idxd_dmadev_create(const char *name, struct rte_device *dev,
> + const struct idxd_dmadev *base_idxd,
> + const struct rte_dma_dev_ops *ops)
> +{
> + struct idxd_dmadev *idxd;
> + struct rte_dma_dev *dmadev = NULL;
> + int ret = 0;
> +
> + if (!name) {
> + IDXD_PMD_ERR("Invalid name of the device!");
> + ret = -EINVAL;
> + goto cleanup;
> + }
> +
> + /* Allocate device structure */
> + dmadev = rte_dma_pmd_allocate(name, dev->numa_node,
> + sizeof(dmadev->dev_private));
> + if (dmadev == NULL) {
> + IDXD_PMD_ERR("Unable to allocate raw device");
> + ret = -ENOMEM;
> + goto cleanup;
> + }
> + dmadev->dev_ops = ops;
> + dmadev->device = dev;
> +
> + idxd = rte_malloc_socket(NULL, sizeof(struct idxd_dmadev), 0, dev->numa_node);
> + if (idxd == NULL) {
> + IDXD_PMD_ERR("Unable to allocate memory for device");
> + ret = -ENOMEM;
> + goto cleanup;
> + }
> + dmadev->data->dev_private = idxd;
> + dmadev->dev_private = idxd;
The dmadev->dev_private and dmadev->data->dev_private already inited by rte_dma_pmd_allocate,
and the driver only needs to pass in the correct parameters.
Recommended:
dmadev = rte_dma_pmd_allocate(name, dev->name, sizeof(struct idxd_dmadev));
> + *idxd = *base_idxd; /* copy over the main fields already passed in */
> + idxd->dmadev = dmadev;
> +
> + /* allocate batch index ring and completion ring.
> + * The +1 is because we can never fully use
> + * the ring, otherwise read == write means both full and empty.
> + */
> + idxd->batch_comp_ring = rte_zmalloc(NULL, (sizeof(idxd->batch_idx_ring[0]) +
> + sizeof(idxd->batch_comp_ring[0])) * (idxd->max_batches + 1),
> + sizeof(idxd->batch_comp_ring[0]));
> + if (idxd->batch_comp_ring == NULL) {
> + IDXD_PMD_ERR("Unable to reserve memory for batch data\n");
> + ret = -ENOMEM;
> + goto cleanup;
> + }
> + idxd->batch_idx_ring = (void *)&idxd->batch_comp_ring[idxd->max_batches+1];
> + idxd->batch_iova = rte_mem_virt2iova(idxd->batch_comp_ring);
> +
Once init one dmadev successful, driver need changes it's state to READY, like:
dmadev->state = RTE_DMA_DEV_READY;
This was useful when call rte_dma_pmd_release: if the state is ready, lib will call
rte_dma_close() to release the dmadev, else it only clean the struct which lib holds.
> + return 0;
> +
> +cleanup:
> + if (dmadev)
> + rte_dma_pmd_release(name);
> +
> + return ret;
> +}
> +
> +int idxd_pmd_logtype;
> +
> +RTE_LOG_REGISTER_DEFAULT(idxd_pmd_logtype, WARNING);
> diff --git a/drivers/dma/idxd/idxd_internal.h b/drivers/dma/idxd/idxd_internal.h
> index c6a7dcd72f..fa6f053f72 100644
> --- a/drivers/dma/idxd/idxd_internal.h
> +++ b/drivers/dma/idxd/idxd_internal.h
> @@ -24,4 +24,44 @@ extern int idxd_pmd_logtype;
> #define IDXD_PMD_ERR(fmt, args...) IDXD_PMD_LOG(ERR, fmt, ## args)
> #define IDXD_PMD_WARN(fmt, args...) IDXD_PMD_LOG(WARNING, fmt, ## args)
>
> +struct idxd_dmadev {
> + /* counters to track the batches */
> + unsigned short max_batches;
> + unsigned short batch_idx_read;
> + unsigned short batch_idx_write;
> +
> + /* track descriptors and handles */
> + unsigned short desc_ring_mask;
> + unsigned short ids_avail; /* handles for ops completed */
> + unsigned short ids_returned; /* the read pointer for hdls/desc rings */
> + unsigned short batch_start; /* start+size == write pointer for hdls/desc */
> + unsigned short batch_size;
> +
> + void *portal; /* address to write the batch descriptor */
> +
> + struct idxd_completion *batch_comp_ring;
> + unsigned short *batch_idx_ring; /* store where each batch ends */
> +
> + struct rte_dma_stats stats;
> +
> + rte_iova_t batch_iova; /* base address of the batch comp ring */
> + rte_iova_t desc_iova; /* base address of desc ring, needed for completions */
> +
> + unsigned short max_batch_size;
> +
> + struct rte_dma_dev *dmadev;
> + struct rte_dma_vchan_conf qcfg;
> + uint8_t sva_support;
> + uint8_t qid;
> +
> + union {
> + struct {
> + unsigned int dsa_id;
> + } bus;
> + } u;
> +};
> +
> +int idxd_dmadev_create(const char *name, struct rte_device *dev,
> + const struct idxd_dmadev *base_idxd, const struct rte_dma_dev_ops *ops);
> +
> #endif /* _IDXD_INTERNAL_H_ */
> diff --git a/drivers/dma/idxd/meson.build b/drivers/dma/idxd/meson.build
> index c864fce3b3..36dbd3e518 100644
> --- a/drivers/dma/idxd/meson.build
> +++ b/drivers/dma/idxd/meson.build
> @@ -8,5 +8,6 @@ endif
> deps += ['bus_pci']
> sources = files(
> 'idxd_bus.c',
> + 'idxd_common.c',
> 'idxd_pci.c'
> )
> \ No newline at end of file
>
On 22/09/2021 03:04, fengchengwen wrote:
> On 2021/9/17 23:24, Kevin Laatz wrote:
>> When a suitable device is found during the bus scan/probe, create a dmadev
>> instance for each HW queue. Internal structures required for device
>> creation are also added.
>>
>> Signed-off-by: Bruce Richardson <bruce.richardson@intel.com>
>> Signed-off-by: Kevin Laatz <kevin.laatz@intel.com>
>> Reviewed-by: Conor Walsh <conor.walsh@intel.com>
>>
>> ---
>> v4:
>> - fix 'vdev' naming, changed to 'bus'
>> - rebase changes
>> ---
>> drivers/dma/idxd/idxd_bus.c | 19 ++++++++
>> drivers/dma/idxd/idxd_common.c | 76 ++++++++++++++++++++++++++++++++
>> drivers/dma/idxd/idxd_internal.h | 40 +++++++++++++++++
>> drivers/dma/idxd/meson.build | 1 +
>> 4 files changed, 136 insertions(+)
>> create mode 100644 drivers/dma/idxd/idxd_common.c
>>
>> diff --git a/drivers/dma/idxd/idxd_bus.c b/drivers/dma/idxd/idxd_bus.c
>> index ef589af30e..b48fa954ed 100644
>> --- a/drivers/dma/idxd/idxd_bus.c
>> +++ b/drivers/dma/idxd/idxd_bus.c
>> @@ -85,6 +85,18 @@ dsa_get_sysfs_path(void)
>> return path ? path : DSA_SYSFS_PATH;
>> }
>>
>> +static int
>> +idxd_dev_close(struct rte_dma_dev *dev)
>> +{
>> + struct idxd_dmadev *idxd = dev->data->dev_private;
>> + munmap(idxd->portal, 0x1000);
>> + return 0;
>> +}
>> +
>> +static const struct rte_dma_dev_ops idxd_bus_ops = {
>> + .dev_close = idxd_dev_close,
>> +};
>> +
>> static void *
>> idxd_bus_mmap_wq(struct rte_dsa_device *dev)
>> {
>> @@ -206,6 +218,7 @@ idxd_probe_dsa(struct rte_dsa_device *dev)
>> return -1;
>> idxd.max_batch_size = ret;
>> idxd.qid = dev->addr.wq_id;
>> + idxd.u.bus.dsa_id = dev->addr.device_id;
>> idxd.sva_support = 1;
>>
>> idxd.portal = idxd_bus_mmap_wq(dev);
>> @@ -214,6 +227,12 @@ idxd_probe_dsa(struct rte_dsa_device *dev)
>> return -ENOENT;
>> }
>>
>> + ret = idxd_dmadev_create(dev->wq_name, &dev->device, &idxd, &idxd_bus_ops);
>> + if (ret) {
>> + IDXD_PMD_ERR("Failed to create rawdev %s", dev->wq_name);
>> + return ret;
>> + }
>> +
>> return 0;
>> }
>>
>> diff --git a/drivers/dma/idxd/idxd_common.c b/drivers/dma/idxd/idxd_common.c
>> new file mode 100644
>> index 0000000000..8afad637fc
>> --- /dev/null
>> +++ b/drivers/dma/idxd/idxd_common.c
>> @@ -0,0 +1,76 @@
>> +/* SPDX-License-Identifier: BSD-3-Clause
>> + * Copyright 2021 Intel Corporation
>> + */
>> +
>> +#include <rte_dmadev_pmd.h>
>> +#include <rte_malloc.h>
>> +#include <rte_common.h>
>> +
>> +#include "idxd_internal.h"
>> +
>> +#define IDXD_PMD_NAME_STR "dmadev_idxd"
>> +
>> +int
>> +idxd_dmadev_create(const char *name, struct rte_device *dev,
>> + const struct idxd_dmadev *base_idxd,
>> + const struct rte_dma_dev_ops *ops)
>> +{
>> + struct idxd_dmadev *idxd;
>> + struct rte_dma_dev *dmadev = NULL;
>> + int ret = 0;
>> +
>> + if (!name) {
>> + IDXD_PMD_ERR("Invalid name of the device!");
>> + ret = -EINVAL;
>> + goto cleanup;
>> + }
>> +
>> + /* Allocate device structure */
>> + dmadev = rte_dma_pmd_allocate(name, dev->numa_node,
>> + sizeof(dmadev->dev_private));
>> + if (dmadev == NULL) {
>> + IDXD_PMD_ERR("Unable to allocate raw device");
>> + ret = -ENOMEM;
>> + goto cleanup;
>> + }
>> + dmadev->dev_ops = ops;
>> + dmadev->device = dev;
>> +
>> + idxd = rte_malloc_socket(NULL, sizeof(struct idxd_dmadev), 0, dev->numa_node);
>> + if (idxd == NULL) {
>> + IDXD_PMD_ERR("Unable to allocate memory for device");
>> + ret = -ENOMEM;
>> + goto cleanup;
>> + }
>> + dmadev->data->dev_private = idxd;
>> + dmadev->dev_private = idxd;
> The dmadev->dev_private and dmadev->data->dev_private already inited by rte_dma_pmd_allocate,
> and the driver only needs to pass in the correct parameters.
>
> Recommended:
> dmadev = rte_dma_pmd_allocate(name, dev->name, sizeof(struct idxd_dmadev));
>
>
>> + *idxd = *base_idxd; /* copy over the main fields already passed in */
>> + idxd->dmadev = dmadev;
>> +
>> + /* allocate batch index ring and completion ring.
>> + * The +1 is because we can never fully use
>> + * the ring, otherwise read == write means both full and empty.
>> + */
>> + idxd->batch_comp_ring = rte_zmalloc(NULL, (sizeof(idxd->batch_idx_ring[0]) +
>> + sizeof(idxd->batch_comp_ring[0])) * (idxd->max_batches + 1),
>> + sizeof(idxd->batch_comp_ring[0]));
>> + if (idxd->batch_comp_ring == NULL) {
>> + IDXD_PMD_ERR("Unable to reserve memory for batch data\n");
>> + ret = -ENOMEM;
>> + goto cleanup;
>> + }
>> + idxd->batch_idx_ring = (void *)&idxd->batch_comp_ring[idxd->max_batches+1];
>> + idxd->batch_iova = rte_mem_virt2iova(idxd->batch_comp_ring);
>> +
> Once init one dmadev successful, driver need changes it's state to READY, like:
> dmadev->state = RTE_DMA_DEV_READY;
> This was useful when call rte_dma_pmd_release: if the state is ready, lib will call
> rte_dma_close() to release the dmadev, else it only clean the struct which lib holds.
Will make these changes in v6, thanks!
@@ -85,6 +85,18 @@ dsa_get_sysfs_path(void)
return path ? path : DSA_SYSFS_PATH;
}
+static int
+idxd_dev_close(struct rte_dma_dev *dev)
+{
+ struct idxd_dmadev *idxd = dev->data->dev_private;
+ munmap(idxd->portal, 0x1000);
+ return 0;
+}
+
+static const struct rte_dma_dev_ops idxd_bus_ops = {
+ .dev_close = idxd_dev_close,
+};
+
static void *
idxd_bus_mmap_wq(struct rte_dsa_device *dev)
{
@@ -206,6 +218,7 @@ idxd_probe_dsa(struct rte_dsa_device *dev)
return -1;
idxd.max_batch_size = ret;
idxd.qid = dev->addr.wq_id;
+ idxd.u.bus.dsa_id = dev->addr.device_id;
idxd.sva_support = 1;
idxd.portal = idxd_bus_mmap_wq(dev);
@@ -214,6 +227,12 @@ idxd_probe_dsa(struct rte_dsa_device *dev)
return -ENOENT;
}
+ ret = idxd_dmadev_create(dev->wq_name, &dev->device, &idxd, &idxd_bus_ops);
+ if (ret) {
+ IDXD_PMD_ERR("Failed to create rawdev %s", dev->wq_name);
+ return ret;
+ }
+
return 0;
}
new file mode 100644
@@ -0,0 +1,76 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright 2021 Intel Corporation
+ */
+
+#include <rte_dmadev_pmd.h>
+#include <rte_malloc.h>
+#include <rte_common.h>
+
+#include "idxd_internal.h"
+
+#define IDXD_PMD_NAME_STR "dmadev_idxd"
+
+int
+idxd_dmadev_create(const char *name, struct rte_device *dev,
+ const struct idxd_dmadev *base_idxd,
+ const struct rte_dma_dev_ops *ops)
+{
+ struct idxd_dmadev *idxd;
+ struct rte_dma_dev *dmadev = NULL;
+ int ret = 0;
+
+ if (!name) {
+ IDXD_PMD_ERR("Invalid name of the device!");
+ ret = -EINVAL;
+ goto cleanup;
+ }
+
+ /* Allocate device structure */
+ dmadev = rte_dma_pmd_allocate(name, dev->numa_node,
+ sizeof(dmadev->dev_private));
+ if (dmadev == NULL) {
+ IDXD_PMD_ERR("Unable to allocate raw device");
+ ret = -ENOMEM;
+ goto cleanup;
+ }
+ dmadev->dev_ops = ops;
+ dmadev->device = dev;
+
+ idxd = rte_malloc_socket(NULL, sizeof(struct idxd_dmadev), 0, dev->numa_node);
+ if (idxd == NULL) {
+ IDXD_PMD_ERR("Unable to allocate memory for device");
+ ret = -ENOMEM;
+ goto cleanup;
+ }
+ dmadev->data->dev_private = idxd;
+ dmadev->dev_private = idxd;
+ *idxd = *base_idxd; /* copy over the main fields already passed in */
+ idxd->dmadev = dmadev;
+
+ /* allocate batch index ring and completion ring.
+ * The +1 is because we can never fully use
+ * the ring, otherwise read == write means both full and empty.
+ */
+ idxd->batch_comp_ring = rte_zmalloc(NULL, (sizeof(idxd->batch_idx_ring[0]) +
+ sizeof(idxd->batch_comp_ring[0])) * (idxd->max_batches + 1),
+ sizeof(idxd->batch_comp_ring[0]));
+ if (idxd->batch_comp_ring == NULL) {
+ IDXD_PMD_ERR("Unable to reserve memory for batch data\n");
+ ret = -ENOMEM;
+ goto cleanup;
+ }
+ idxd->batch_idx_ring = (void *)&idxd->batch_comp_ring[idxd->max_batches+1];
+ idxd->batch_iova = rte_mem_virt2iova(idxd->batch_comp_ring);
+
+ return 0;
+
+cleanup:
+ if (dmadev)
+ rte_dma_pmd_release(name);
+
+ return ret;
+}
+
+int idxd_pmd_logtype;
+
+RTE_LOG_REGISTER_DEFAULT(idxd_pmd_logtype, WARNING);
@@ -24,4 +24,44 @@ extern int idxd_pmd_logtype;
#define IDXD_PMD_ERR(fmt, args...) IDXD_PMD_LOG(ERR, fmt, ## args)
#define IDXD_PMD_WARN(fmt, args...) IDXD_PMD_LOG(WARNING, fmt, ## args)
+struct idxd_dmadev {
+ /* counters to track the batches */
+ unsigned short max_batches;
+ unsigned short batch_idx_read;
+ unsigned short batch_idx_write;
+
+ /* track descriptors and handles */
+ unsigned short desc_ring_mask;
+ unsigned short ids_avail; /* handles for ops completed */
+ unsigned short ids_returned; /* the read pointer for hdls/desc rings */
+ unsigned short batch_start; /* start+size == write pointer for hdls/desc */
+ unsigned short batch_size;
+
+ void *portal; /* address to write the batch descriptor */
+
+ struct idxd_completion *batch_comp_ring;
+ unsigned short *batch_idx_ring; /* store where each batch ends */
+
+ struct rte_dma_stats stats;
+
+ rte_iova_t batch_iova; /* base address of the batch comp ring */
+ rte_iova_t desc_iova; /* base address of desc ring, needed for completions */
+
+ unsigned short max_batch_size;
+
+ struct rte_dma_dev *dmadev;
+ struct rte_dma_vchan_conf qcfg;
+ uint8_t sva_support;
+ uint8_t qid;
+
+ union {
+ struct {
+ unsigned int dsa_id;
+ } bus;
+ } u;
+};
+
+int idxd_dmadev_create(const char *name, struct rte_device *dev,
+ const struct idxd_dmadev *base_idxd, const struct rte_dma_dev_ops *ops);
+
#endif /* _IDXD_INTERNAL_H_ */
@@ -8,5 +8,6 @@ endif
deps += ['bus_pci']
sources = files(
'idxd_bus.c',
+ 'idxd_common.c',
'idxd_pci.c'
)
\ No newline at end of file