Message ID | 20210917152437.3270330-5-kevin.laatz@intel.com (mailing list archive) |
---|---|
State | Superseded, archived |
Delegated to: | Thomas Monjalon |
Headers | show |
Series | add dmadev driver for idxd devices | expand |
Context | Check | Description |
---|---|---|
ci/checkpatch | success | coding style OK |
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!
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; + *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); 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