raw/ioat: add configure, start and stop functions

Allow initializing a driver instance. Include selftest to validate these
functions.

Signed-off-by: Bruce Richardson <bruce.richardson@intel.com>
Acked-by: Anatoly Burakov <anatoly.burakov@intel.com>
Acked-by: Jiayu Hu <jiayu.hu@intel.com>
Tested-by: Harry van Haaren <harry.van.haaren@intel.com>
This commit is contained in:
Bruce Richardson 2019-07-02 15:12:28 +01:00 committed by Thomas Monjalon
parent b69512dda1
commit 849470d522
7 changed files with 162 additions and 2 deletions

View File

@ -36,7 +36,8 @@ test_rawdev_selftest_ioat(void)
struct rte_rawdev_info info = { .dev_private = NULL };
if (rte_rawdev_info_get(i, &info) == 0 &&
strstr(info.driver_name, "ioat") != NULL)
return TEST_SUCCESS;
return rte_rawdev_selftest(i) == 0 ?
TEST_SUCCESS : TEST_FAILED;
}
printf("No IOAT rawdev found, skipping tests\n");

View File

@ -117,3 +117,35 @@ the ``dev_private`` field in the ``rte_rawdev_info`` struct should either
be NULL, or else be set to point to a structure of type
``rte_ioat_rawdev_config``, in which case the size of the configured device
input ring will be returned in that structure.
Device Configuration
~~~~~~~~~~~~~~~~~~~~~
Configuring an IOAT rawdev device is done using the
``rte_rawdev_configure()`` API, which takes the same structure parameters
as the, previously referenced, ``rte_rawdev_info_get()`` API. The main
difference is that, because the parameter is used as input rather than
output, the ``dev_private`` structure element cannot be NULL, and must
point to a valid ``rte_ioat_rawdev_config`` structure, containing the ring
size to be used by the device. The ring size must be a power of two,
between 64 and 4096.
The following code shows how the device is configured in
``test_ioat_rawdev.c``:
.. code-block:: C
#define IOAT_TEST_RINGSIZE 512
struct rte_ioat_rawdev_config p = { .ring_size = -1 };
struct rte_rawdev_info info = { .dev_private = &p };
/* ... */
p.ring_size = IOAT_TEST_RINGSIZE;
if (rte_rawdev_configure(dev_id, &info) != 0) {
printf("Error with rte_rawdev_configure()\n");
return -1;
}
Once configured, the device can then be made ready for use by calling the
``rte_rawdev_start()`` API.

View File

@ -21,6 +21,7 @@ EXPORT_MAP := rte_pmd_ioat_version.map
# library source files
SRCS-$(CONFIG_RTE_LIBRTE_PMD_IOAT_RAWDEV) += ioat_rawdev.c
SRCS-$(CONFIG_RTE_LIBRTE_PMD_IOAT_RAWDEV) += ioat_rawdev_test.c
# export include files
SYMLINK-y-include += rte_ioat_rawdev.h

View File

@ -34,6 +34,81 @@ static struct rte_pci_driver ioat_pmd_drv;
#define IOAT_PMD_ERR(fmt, args...) IOAT_PMD_LOG(ERR, fmt, ## args)
#define IOAT_PMD_WARN(fmt, args...) IOAT_PMD_LOG(WARNING, fmt, ## args)
#define DESC_SZ sizeof(struct rte_ioat_generic_hw_desc)
#define COMPLETION_SZ sizeof(__m128i)
static int
ioat_dev_configure(const struct rte_rawdev *dev, rte_rawdev_obj_t config)
{
struct rte_ioat_rawdev_config *params = config;
struct rte_ioat_rawdev *ioat = dev->dev_private;
char mz_name[RTE_MEMZONE_NAMESIZE];
unsigned short i;
if (dev->started)
return -EBUSY;
if (params == NULL)
return -EINVAL;
if (params->ring_size > 4096 || params->ring_size < 64 ||
!rte_is_power_of_2(params->ring_size))
return -EINVAL;
ioat->ring_size = params->ring_size;
if (ioat->desc_ring != NULL) {
rte_memzone_free(ioat->desc_mz);
ioat->desc_ring = NULL;
ioat->desc_mz = NULL;
}
/* allocate one block of memory for both descriptors
* and completion handles.
*/
snprintf(mz_name, sizeof(mz_name), "rawdev%u_desc_ring", dev->dev_id);
ioat->desc_mz = rte_memzone_reserve(mz_name,
(DESC_SZ + COMPLETION_SZ) * ioat->ring_size,
dev->device->numa_node, RTE_MEMZONE_IOVA_CONTIG);
if (ioat->desc_mz == NULL)
return -ENOMEM;
ioat->desc_ring = ioat->desc_mz->addr;
ioat->hdls = (void *)&ioat->desc_ring[ioat->ring_size];
ioat->ring_addr = ioat->desc_mz->iova;
/* configure descriptor ring - each one points to next */
for (i = 0; i < ioat->ring_size; i++) {
ioat->desc_ring[i].next = ioat->ring_addr +
(((i + 1) % ioat->ring_size) * DESC_SZ);
}
return 0;
}
static int
ioat_dev_start(struct rte_rawdev *dev)
{
struct rte_ioat_rawdev *ioat = dev->dev_private;
if (ioat->ring_size == 0 || ioat->desc_ring == NULL)
return -EBUSY;
/* inform hardware of where the descriptor ring is */
ioat->regs->chainaddr = ioat->ring_addr;
/* inform hardware of where to write the status/completions */
ioat->regs->chancmp = ioat->status_addr;
/* prime the status register to be set to the last element */
ioat->status = ioat->ring_addr + ((ioat->ring_size - 1) * DESC_SZ);
return 0;
}
static void
ioat_dev_stop(struct rte_rawdev *dev)
{
RTE_SET_USED(dev);
}
static void
ioat_dev_info_get(struct rte_rawdev *dev, rte_rawdev_obj_t dev_info)
{
@ -44,11 +119,17 @@ ioat_dev_info_get(struct rte_rawdev *dev, rte_rawdev_obj_t dev_info)
cfg->ring_size = ioat->ring_size;
}
extern int ioat_rawdev_test(uint16_t dev_id);
static int
ioat_rawdev_create(const char *name, struct rte_pci_device *dev)
{
static const struct rte_rawdev_ops ioat_rawdev_ops = {
.dev_configure = ioat_dev_configure,
.dev_start = ioat_dev_start,
.dev_stop = ioat_dev_stop,
.dev_info_get = ioat_dev_info_get,
.dev_selftest = ioat_rawdev_test,
};
struct rte_rawdev *rawdev = NULL;
@ -154,6 +235,7 @@ ioat_rawdev_destroy(const char *name)
if (rdev->dev_private != NULL) {
struct rte_ioat_rawdev *ioat = rdev->dev_private;
rdev->dev_private = NULL;
rte_memzone_free(ioat->desc_mz);
rte_memzone_free(ioat->mz);
}

View File

@ -0,0 +1,41 @@
/* SPDX-License-Identifier: BSD-3-Clause
* Copyright(c) 2019 Intel Corporation
*/
#include "rte_rawdev.h"
#include "rte_ioat_rawdev.h"
int ioat_rawdev_test(uint16_t dev_id); /* pre-define to keep compiler happy */
int
ioat_rawdev_test(uint16_t dev_id)
{
#define IOAT_TEST_RINGSIZE 512
struct rte_ioat_rawdev_config p = { .ring_size = -1 };
struct rte_rawdev_info info = { .dev_private = &p };
rte_rawdev_info_get(dev_id, &info);
if (p.ring_size != 0) {
printf("Error, initial ring size is non-zero (%d)\n",
(int)p.ring_size);
return -1;
}
p.ring_size = IOAT_TEST_RINGSIZE;
if (rte_rawdev_configure(dev_id, &info) != 0) {
printf("Error with rte_rawdev_configure()\n");
return -1;
}
rte_rawdev_info_get(dev_id, &info);
if (p.ring_size != IOAT_TEST_RINGSIZE) {
printf("Error, ring size is not %d (%d)\n",
IOAT_TEST_RINGSIZE, (int)p.ring_size);
return -1;
}
if (rte_rawdev_start(dev_id) != 0) {
printf("Error with rte_rawdev_start()\n");
return -1;
}
return 0;
}

View File

@ -2,7 +2,8 @@
# Copyright 2019 Intel Corporation
build = dpdk_conf.has('RTE_ARCH_X86')
sources = files('ioat_rawdev.c')
sources = files('ioat_rawdev.c',
'ioat_rawdev_test.c')
deps += ['rawdev', 'bus_pci']
install_headers('rte_ioat_rawdev.h',

View File

@ -14,6 +14,7 @@
* @b EXPERIMENTAL: these structures and APIs may change without prior notice
*/
#include <x86intrin.h>
#include <rte_memory.h>
#include <rte_memzone.h>
#include <rte_ioat_spec.h>
@ -51,6 +52,7 @@ struct rte_ioat_rawdev {
unsigned short ring_size;
struct rte_ioat_generic_hw_desc *desc_ring;
__m128i *hdls; /* completion handles for returning to user */
/* to report completions, the device will write status back here */
volatile uint64_t status __rte_cache_aligned;