diff options
author | Luca Boccassi <luca.boccassi@gmail.com> | 2018-08-14 18:52:30 +0100 |
---|---|---|
committer | Luca Boccassi <luca.boccassi@gmail.com> | 2018-08-14 18:53:17 +0100 |
commit | b63264c8342e6a1b6971c79550d2af2024b6a4de (patch) | |
tree | 83114aac64286fe616506c0b3dfaec2ab86ef835 /lib/librte_compressdev | |
parent | ca33590b6af032bff57d9cc70455660466a654b2 (diff) |
New upstream version 18.08upstream/18.08
Change-Id: I32fdf5e5016556d9c0a6d88ddaf1fc468961790a
Signed-off-by: Luca Boccassi <luca.boccassi@gmail.com>
Diffstat (limited to 'lib/librte_compressdev')
-rw-r--r-- | lib/librte_compressdev/Makefile | 31 | ||||
-rw-r--r-- | lib/librte_compressdev/meson.build | 12 | ||||
-rw-r--r-- | lib/librte_compressdev/rte_comp.c | 215 | ||||
-rw-r--r-- | lib/librte_compressdev/rte_comp.h | 485 | ||||
-rw-r--r-- | lib/librte_compressdev/rte_compressdev.c | 772 | ||||
-rw-r--r-- | lib/librte_compressdev/rte_compressdev.h | 540 | ||||
-rw-r--r-- | lib/librte_compressdev/rte_compressdev_internal.h | 114 | ||||
-rw-r--r-- | lib/librte_compressdev/rte_compressdev_pmd.c | 160 | ||||
-rw-r--r-- | lib/librte_compressdev/rte_compressdev_pmd.h | 390 | ||||
-rw-r--r-- | lib/librte_compressdev/rte_compressdev_version.map | 39 |
10 files changed, 2758 insertions, 0 deletions
diff --git a/lib/librte_compressdev/Makefile b/lib/librte_compressdev/Makefile new file mode 100644 index 00000000..7ef89e61 --- /dev/null +++ b/lib/librte_compressdev/Makefile @@ -0,0 +1,31 @@ +# SPDX-License-Identifier: BSD-3-Clause +# Copyright(c) 2017-2018 Intel Corporation + +include $(RTE_SDK)/mk/rte.vars.mk + +# library name +LIB = librte_compressdev.a + +# library version +LIBABIVER := 1 + +# build flags +CFLAGS += -O3 +CFLAGS += $(WERROR_FLAGS) +CFLAGS += -DALLOW_EXPERIMENTAL_API +LDLIBS += -lrte_eal -lrte_mempool -lrte_kvargs + +# library source files +SRCS-y += rte_compressdev.c rte_compressdev_pmd.c rte_comp.c + +# export include files +SYMLINK-y-include += rte_comp.h +SYMLINK-y-include += rte_compressdev.h +# export include files (for PMDs) +SYMLINK-y-include += rte_compressdev_pmd.h +SYMLINK-y-include += rte_compressdev_internal.h + +# versioning export map +EXPORT_MAP := rte_compressdev_version.map + +include $(RTE_SDK)/mk/rte.lib.mk diff --git a/lib/librte_compressdev/meson.build b/lib/librte_compressdev/meson.build new file mode 100644 index 00000000..5416571c --- /dev/null +++ b/lib/librte_compressdev/meson.build @@ -0,0 +1,12 @@ +# SPDX-License-Identifier: BSD-3-Clause +# Copyright(c) 2018 Intel Corporation + +allow_experimental_apis = true +sources = files('rte_compressdev.c', + 'rte_compressdev_pmd.c', + 'rte_comp.c') +headers = files('rte_compressdev.h', + 'rte_compressdev_pmd.h', + 'rte_compressdev_internal.h', + 'rte_comp.h') +deps += ['kvargs', 'mbuf'] diff --git a/lib/librte_compressdev/rte_comp.c b/lib/librte_compressdev/rte_comp.c new file mode 100644 index 00000000..98ad0cfd --- /dev/null +++ b/lib/librte_compressdev/rte_comp.c @@ -0,0 +1,215 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2017-2018 Intel Corporation + */ + +#include "rte_comp.h" +#include "rte_compressdev.h" +#include "rte_compressdev_internal.h" + +const char * __rte_experimental +rte_comp_get_feature_name(uint64_t flag) +{ + switch (flag) { + case RTE_COMP_FF_STATEFUL_COMPRESSION: + return "STATEFUL_COMPRESSION"; + case RTE_COMP_FF_STATEFUL_DECOMPRESSION: + return "STATEFUL_DECOMPRESSION"; + case RTE_COMP_FF_OOP_SGL_IN_SGL_OUT: + return "OOP_SGL_IN_SGL_OUT"; + case RTE_COMP_FF_OOP_SGL_IN_LB_OUT: + return "OOP_SGL_IN_LB_OUT"; + case RTE_COMP_FF_OOP_LB_IN_SGL_OUT: + return "OOP_LB_IN_SGL_OUT"; + case RTE_COMP_FF_MULTI_PKT_CHECKSUM: + return "MULTI_PKT_CHECKSUM"; + case RTE_COMP_FF_ADLER32_CHECKSUM: + return "ADLER32_CHECKSUM"; + case RTE_COMP_FF_CRC32_CHECKSUM: + return "CRC32_CHECKSUM"; + case RTE_COMP_FF_CRC32_ADLER32_CHECKSUM: + return "CRC32_ADLER32_CHECKSUM"; + case RTE_COMP_FF_NONCOMPRESSED_BLOCKS: + return "NONCOMPRESSED_BLOCKS"; + case RTE_COMP_FF_SHA1_HASH: + return "SHA1_HASH"; + case RTE_COMP_FF_SHA2_SHA256_HASH: + return "SHA2_SHA256_HASH"; + case RTE_COMP_FF_SHAREABLE_PRIV_XFORM: + return "SHAREABLE_PRIV_XFORM"; + case RTE_COMP_FF_HUFFMAN_FIXED: + return "HUFFMAN_FIXED"; + case RTE_COMP_FF_HUFFMAN_DYNAMIC: + return "HUFFMAN_DYNAMIC"; + default: + return NULL; + } +} + +/** + * Reset the fields of an operation to their default values. + * + * @note The private data associated with the operation is not zeroed. + * + * @param op + * The operation to be reset + */ +static inline void +rte_comp_op_reset(struct rte_comp_op *op) +{ + struct rte_mempool *tmp_mp = op->mempool; + rte_iova_t tmp_iova_addr = op->iova_addr; + + memset(op, 0, sizeof(struct rte_comp_op)); + op->status = RTE_COMP_OP_STATUS_NOT_PROCESSED; + op->iova_addr = tmp_iova_addr; + op->mempool = tmp_mp; +} + +/** + * Private data structure belonging to an operation pool. + */ +struct rte_comp_op_pool_private { + uint16_t user_size; + /**< Size of private user data with each operation. */ +}; + +/** + * Bulk allocate raw element from mempool and return as comp operations + * + * @param mempool + * Compress operation mempool + * @param ops + * Array to place allocated operations + * @param nb_ops + * Number of operations to allocate + * @return + * - 0: Success + * - -ENOENT: Not enough entries in the mempool; no ops are retrieved. + */ +static inline int +rte_comp_op_raw_bulk_alloc(struct rte_mempool *mempool, + struct rte_comp_op **ops, uint16_t nb_ops) +{ + if (rte_mempool_get_bulk(mempool, (void **)ops, nb_ops) == 0) + return nb_ops; + + return 0; +} + +/** Initialise rte_comp_op mempool element */ +static void +rte_comp_op_init(struct rte_mempool *mempool, + __rte_unused void *opaque_arg, + void *_op_data, + __rte_unused unsigned int i) +{ + struct rte_comp_op *op = _op_data; + + memset(_op_data, 0, mempool->elt_size); + + op->status = RTE_COMP_OP_STATUS_NOT_PROCESSED; + op->iova_addr = rte_mem_virt2iova(_op_data); + op->mempool = mempool; +} + +struct rte_mempool * __rte_experimental +rte_comp_op_pool_create(const char *name, + unsigned int nb_elts, unsigned int cache_size, + uint16_t user_size, int socket_id) +{ + struct rte_comp_op_pool_private *priv; + + unsigned int elt_size = sizeof(struct rte_comp_op) + user_size; + + /* lookup mempool in case already allocated */ + struct rte_mempool *mp = rte_mempool_lookup(name); + + if (mp != NULL) { + priv = (struct rte_comp_op_pool_private *) + rte_mempool_get_priv(mp); + + if (mp->elt_size != elt_size || + mp->cache_size < cache_size || + mp->size < nb_elts || + priv->user_size < user_size) { + mp = NULL; + COMPRESSDEV_LOG(ERR, + "Mempool %s already exists but with incompatible parameters", + name); + return NULL; + } + return mp; + } + + mp = rte_mempool_create( + name, + nb_elts, + elt_size, + cache_size, + sizeof(struct rte_comp_op_pool_private), + NULL, + NULL, + rte_comp_op_init, + NULL, + socket_id, + 0); + + if (mp == NULL) { + COMPRESSDEV_LOG(ERR, "Failed to create mempool %s", name); + return NULL; + } + + priv = (struct rte_comp_op_pool_private *) + rte_mempool_get_priv(mp); + + priv->user_size = user_size; + + return mp; +} + +struct rte_comp_op * __rte_experimental +rte_comp_op_alloc(struct rte_mempool *mempool) +{ + struct rte_comp_op *op = NULL; + int retval; + + retval = rte_comp_op_raw_bulk_alloc(mempool, &op, 1); + if (unlikely(retval < 0)) + return NULL; + + rte_comp_op_reset(op); + + return op; +} + +int __rte_experimental +rte_comp_op_bulk_alloc(struct rte_mempool *mempool, + struct rte_comp_op **ops, uint16_t nb_ops) +{ + int ret; + uint16_t i; + + ret = rte_comp_op_raw_bulk_alloc(mempool, ops, nb_ops); + if (unlikely(ret < nb_ops)) + return ret; + + for (i = 0; i < nb_ops; i++) + rte_comp_op_reset(ops[i]); + + return nb_ops; +} + +/** + * free operation structure + * If operation has been allocate from a rte_mempool, then the operation will + * be returned to the mempool. + * + * @param op + * Compress operation + */ +void __rte_experimental +rte_comp_op_free(struct rte_comp_op *op) +{ + if (op != NULL && op->mempool != NULL) + rte_mempool_put(op->mempool, op); +} diff --git a/lib/librte_compressdev/rte_comp.h b/lib/librte_compressdev/rte_comp.h new file mode 100644 index 00000000..ee9056ea --- /dev/null +++ b/lib/librte_compressdev/rte_comp.h @@ -0,0 +1,485 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2017-2018 Intel Corporation + */ + +#ifndef _RTE_COMP_H_ +#define _RTE_COMP_H_ + +/** + * @file rte_comp.h + * + * RTE definitions for Data Compression Service + * + */ + +#ifdef __cplusplus +extern "C" { +#endif + +#include <rte_mempool.h> +#include <rte_mbuf.h> + +/** + * compression service feature flags + * + * @note New features flags should be added to the end of the list + * + * Keep these flags synchronised with rte_comp_get_feature_name() + */ +#define RTE_COMP_FF_STATEFUL_COMPRESSION (1ULL << 0) +/**< Stateful compression is supported */ +#define RTE_COMP_FF_STATEFUL_DECOMPRESSION (1ULL << 1) +/**< Stateful decompression is supported */ +#define RTE_COMP_FF_OOP_SGL_IN_SGL_OUT (1ULL << 2) +/**< Out-of-place Scatter-gather (SGL) buffers, + * with multiple segments, are supported in input and output + */ +#define RTE_COMP_FF_OOP_SGL_IN_LB_OUT (1ULL << 3) +/**< Out-of-place Scatter-gather (SGL) buffers are supported + * in input, combined with linear buffers (LB), with a + * single segment, in output + */ +#define RTE_COMP_FF_OOP_LB_IN_SGL_OUT (1ULL << 4) +/**< Out-of-place Scatter-gather (SGL) buffers are supported + * in output, combined with linear buffers (LB) in input + */ +#define RTE_COMP_FF_ADLER32_CHECKSUM (1ULL << 5) +/**< Adler-32 Checksum is supported */ +#define RTE_COMP_FF_CRC32_CHECKSUM (1ULL << 6) +/**< CRC32 Checksum is supported */ +#define RTE_COMP_FF_CRC32_ADLER32_CHECKSUM (1ULL << 7) +/**< Adler-32/CRC32 Checksum is supported */ +#define RTE_COMP_FF_MULTI_PKT_CHECKSUM (1ULL << 8) +/**< Generation of checksum across multiple stateless packets is supported */ +#define RTE_COMP_FF_SHA1_HASH (1ULL << 9) +/**< SHA1 Hash is supported */ +#define RTE_COMP_FF_SHA2_SHA256_HASH (1ULL << 10) +/**< SHA256 Hash of SHA2 family is supported */ +#define RTE_COMP_FF_NONCOMPRESSED_BLOCKS (1ULL << 11) +/**< Creation of non-compressed blocks using RTE_COMP_LEVEL_NONE is supported */ +#define RTE_COMP_FF_SHAREABLE_PRIV_XFORM (1ULL << 12) +/**< Private xforms created by the PMD can be shared + * across multiple stateless operations. If not set, then app needs + * to create as many priv_xforms as it expects to have stateless + * operations in-flight. + */ +#define RTE_COMP_FF_HUFFMAN_FIXED (1ULL << 13) +/**< Fixed huffman encoding is supported */ +#define RTE_COMP_FF_HUFFMAN_DYNAMIC (1ULL << 14) +/**< Dynamic huffman encoding is supported */ + +/** Status of comp operation */ +enum rte_comp_op_status { + RTE_COMP_OP_STATUS_SUCCESS = 0, + /**< Operation completed successfully */ + RTE_COMP_OP_STATUS_NOT_PROCESSED, + /**< Operation has not yet been processed by the device */ + RTE_COMP_OP_STATUS_INVALID_ARGS, + /**< Operation failed due to invalid arguments in request */ + RTE_COMP_OP_STATUS_ERROR, + /**< Error handling operation */ + RTE_COMP_OP_STATUS_INVALID_STATE, + /**< Operation is invoked in invalid state */ + RTE_COMP_OP_STATUS_OUT_OF_SPACE_TERMINATED, + /**< Output buffer ran out of space before operation completed. + * Error case. Application must resubmit all data with a larger + * output buffer. + */ + RTE_COMP_OP_STATUS_OUT_OF_SPACE_RECOVERABLE, + /**< Output buffer ran out of space before operation completed, but this + * is not an error case. Output data up to op.produced can be used and + * next op in the stream should continue on from op.consumed+1. + */ +}; + +/** Compression Algorithms */ +enum rte_comp_algorithm { + RTE_COMP_ALGO_UNSPECIFIED = 0, + /** No Compression algorithm */ + RTE_COMP_ALGO_NULL, + /**< No compression. + * Pass-through, data is copied unchanged from source buffer to + * destination buffer. + */ + RTE_COMP_ALGO_DEFLATE, + /**< DEFLATE compression algorithm + * https://tools.ietf.org/html/rfc1951 + */ + RTE_COMP_ALGO_LZS, + /**< LZS compression algorithm + * https://tools.ietf.org/html/rfc2395 + */ + RTE_COMP_ALGO_LIST_END +}; + +/** Compression Hash Algorithms */ +enum rte_comp_hash_algorithm { + RTE_COMP_HASH_ALGO_NONE = 0, + /**< No hash */ + RTE_COMP_HASH_ALGO_SHA1, + /**< SHA1 hash algorithm */ + RTE_COMP_HASH_ALGO_SHA2_256, + /**< SHA256 hash algorithm of SHA2 family */ + RTE_COMP_HASH_ALGO_LIST_END +}; + +/**< Compression Level. + * The number is interpreted by each PMD differently. However, lower numbers + * give fastest compression, at the expense of compression ratio while + * higher numbers may give better compression ratios but are likely slower. + */ +#define RTE_COMP_LEVEL_PMD_DEFAULT (-1) +/** Use PMD Default */ +#define RTE_COMP_LEVEL_NONE (0) +/** Output uncompressed blocks if supported by the specified algorithm */ +#define RTE_COMP_LEVEL_MIN (1) +/** Use minimum compression level supported by the PMD */ +#define RTE_COMP_LEVEL_MAX (9) +/** Use maximum compression level supported by the PMD */ + +/** Compression checksum types */ +enum rte_comp_checksum_type { + RTE_COMP_CHECKSUM_NONE, + /**< No checksum generated */ + RTE_COMP_CHECKSUM_CRC32, + /**< Generates a CRC32 checksum, as used by gzip */ + RTE_COMP_CHECKSUM_ADLER32, + /**< Generates an Adler-32 checksum, as used by zlib */ + RTE_COMP_CHECKSUM_CRC32_ADLER32, + /**< Generates both Adler-32 and CRC32 checksums, concatenated. + * CRC32 is in the lower 32bits, Adler-32 in the upper 32 bits. + */ +}; + + +/** Compression Huffman Type - used by DEFLATE algorithm */ +enum rte_comp_huffman { + RTE_COMP_HUFFMAN_DEFAULT, + /**< PMD may choose which Huffman codes to use */ + RTE_COMP_HUFFMAN_FIXED, + /**< Use Fixed Huffman codes */ + RTE_COMP_HUFFMAN_DYNAMIC, + /**< Use Dynamic Huffman codes */ +}; + +/** Compression flush flags */ +enum rte_comp_flush_flag { + RTE_COMP_FLUSH_NONE, + /**< Data is not flushed. Output may remain in the compressor and be + * processed during a following op. It may not be possible to decompress + * output until a later op with some other flush flag has been sent. + */ + RTE_COMP_FLUSH_SYNC, + /**< All data should be flushed to output buffer. Output data can be + * decompressed. However state and history is not cleared, so future + * operations may use history from this operation. + */ + RTE_COMP_FLUSH_FULL, + /**< All data should be flushed to output buffer. Output data can be + * decompressed. State and history data is cleared, so future + * ops will be independent of ops processed before this. + */ + RTE_COMP_FLUSH_FINAL + /**< Same as RTE_COMP_FLUSH_FULL but if op.algo is RTE_COMP_ALGO_DEFLATE + * then bfinal bit is set in the last block. + */ +}; + +/** Compression transform types */ +enum rte_comp_xform_type { + RTE_COMP_COMPRESS, + /**< Compression service - compress */ + RTE_COMP_DECOMPRESS, + /**< Compression service - decompress */ +}; + +/** Compression operation type */ +enum rte_comp_op_type { + RTE_COMP_OP_STATELESS, + /**< All data to be processed is submitted in the op, no state or + * history from previous ops is used and none will be stored for future + * ops. Flush flag must be set to either FLUSH_FULL or FLUSH_FINAL. + */ + RTE_COMP_OP_STATEFUL + /**< There may be more data to be processed after this op, it's part of + * a stream of data. State and history from previous ops can be used + * and resulting state and history can be stored for future ops, + * depending on flush flag. + */ +}; + + +/** Parameters specific to the deflate algorithm */ +struct rte_comp_deflate_params { + enum rte_comp_huffman huffman; + /**< Compression huffman encoding type */ +}; + +/** Setup Data for compression */ +struct rte_comp_compress_xform { + enum rte_comp_algorithm algo; + /**< Algorithm to use for compress operation */ + union { + struct rte_comp_deflate_params deflate; + /**< Parameters specific to the deflate algorithm */ + }; /**< Algorithm specific parameters */ + int level; + /**< Compression level */ + uint8_t window_size; + /**< Base two log value of sliding window to be used. If window size + * can't be supported by the PMD then it may fall back to a smaller + * size. This is likely to result in a worse compression ratio. + */ + enum rte_comp_checksum_type chksum; + /**< Type of checksum to generate on the uncompressed data */ + enum rte_comp_hash_algorithm hash_algo; + /**< Hash algorithm to be used with compress operation. Hash is always + * done on plaintext. + */ +}; + +/** + * Setup Data for decompression. + */ +struct rte_comp_decompress_xform { + enum rte_comp_algorithm algo; + /**< Algorithm to use for decompression */ + enum rte_comp_checksum_type chksum; + /**< Type of checksum to generate on the decompressed data */ + uint8_t window_size; + /**< Base two log value of sliding window which was used to generate + * compressed data. If window size can't be supported by the PMD then + * setup of stream or private_xform should fail. + */ + enum rte_comp_hash_algorithm hash_algo; + /**< Hash algorithm to be used with decompress operation. Hash is always + * done on plaintext. + */ +}; + +/** + * Compression transform structure. + * + * This is used to specify the compression transforms required. + * Each transform structure can hold a single transform, the type field is + * used to specify which transform is contained within the union. + */ +struct rte_comp_xform { + enum rte_comp_xform_type type; + /**< xform type */ + union { + struct rte_comp_compress_xform compress; + /**< xform for compress operation */ + struct rte_comp_decompress_xform decompress; + /**< decompress xform */ + }; +}; + +/** + * Compression Operation. + * + * This structure contains data relating to performing a compression + * operation on the referenced mbuf data buffers. + * + * Comp operations are enqueued and dequeued in comp PMDs using the + * rte_compressdev_enqueue_burst() / rte_compressdev_dequeue_burst() APIs + */ +struct rte_comp_op { + enum rte_comp_op_type op_type; + union { + void *private_xform; + /**< Stateless private PMD data derived from an rte_comp_xform. + * A handle returned by rte_compressdev_private_xform_create() + * must be attached to operations of op_type RTE_COMP_STATELESS. + */ + void *stream; + /**< Private PMD data derived initially from an rte_comp_xform, + * which holds state and history data and evolves as operations + * are processed. rte_compressdev_stream_create() must be called + * on a device for all STATEFUL data streams and the resulting + * stream attached to the one or more operations associated + * with the data stream. + * All operations in a stream must be sent to the same device. + */ + }; + + struct rte_mempool *mempool; + /**< Pool from which operation is allocated */ + rte_iova_t iova_addr; + /**< IOVA address of this operation */ + struct rte_mbuf *m_src; + /**< source mbuf + * The total size of the input buffer(s) can be retrieved using + * rte_pktmbuf_data_len(m_src). The max data size which can fit in a + * single mbuf is limited by the uint16_t rte_mbuf.data_len to 64k-1. + * If the input data is bigger than this it can be passed to the PMD in + * a chain of mbufs if the PMD's capabilities indicate it supports this. + */ + struct rte_mbuf *m_dst; + /**< destination mbuf + * The total size of the output buffer(s) can be retrieved using + * rte_pktmbuf_data_len(m_dst). The max data size which can fit in a + * single mbuf is limited by the uint16_t rte_mbuf.data_len to 64k-1. + * If the output data is expected to be bigger than this a chain of + * mbufs can be passed to the PMD if the PMD's capabilities indicate + * it supports this. + */ + + struct { + uint32_t offset; + /**< Starting point for compression or decompression, + * specified as number of bytes from start of packet in + * source buffer. + * This offset starts from the first segment + * of the buffer, in case the m_src is a chain of mbufs. + * Starting point for checksum generation in compress direction. + */ + uint32_t length; + /**< The length, in bytes, of the data in source buffer + * to be compressed or decompressed. + * Also the length of the data over which the checksum + * should be generated in compress direction + */ + } src; + struct { + uint32_t offset; + /**< Starting point for writing output data, specified as + * number of bytes from start of packet in dest + * buffer. + * This offset starts from the first segment + * of the buffer, in case the m_dst is a chain of mbufs. + * Starting point for checksum generation in + * decompress direction. + */ + } dst; + struct { + uint8_t *digest; + /**< Output buffer to store hash output, if enabled in xform. + * Buffer would contain valid value only after an op with + * flush flag = RTE_COMP_FLUSH_FULL/FLUSH_FINAL is processed + * successfully. + * + * Length of buffer should be contiguous and large enough to + * accommodate digest produced by specific hash algo. + */ + rte_iova_t iova_addr; + /**< IO address of the buffer */ + } hash; + enum rte_comp_flush_flag flush_flag; + /**< Defines flush characteristics for the output data. + * Only applicable in compress direction + */ + uint64_t input_chksum; + /**< An input checksum can be provided to generate a + * cumulative checksum across sequential blocks in a STATELESS stream. + * Checksum type is as specified in xform chksum_type + */ + uint64_t output_chksum; + /**< If a checksum is generated it will be written in here. + * Checksum type is as specified in xform chksum_type. + */ + uint32_t consumed; + /**< The number of bytes from the source buffer + * which were compressed/decompressed. + */ + uint32_t produced; + /**< The number of bytes written to the destination buffer + * which were compressed/decompressed. + */ + uint64_t debug_status; + /**< + * Status of the operation is returned in the status param. + * This field allows the PMD to pass back extra + * pmd-specific debug information. Value is not defined on the API. + */ + uint8_t status; + /**< + * Operation status - use values from enum rte_comp_status. + * This is reset to + * RTE_COMP_OP_STATUS_NOT_PROCESSED on allocation from mempool and + * will be set to RTE_COMP_OP_STATUS_SUCCESS after operation + * is successfully processed by a PMD + */ +} __rte_cache_aligned; + +/** + * Creates an operation pool + * + * @param name + * Compress pool name + * @param nb_elts + * Number of elements in pool + * @param cache_size + * Number of elements to cache on lcore, see + * *rte_mempool_create* for further details about cache size + * @param user_size + * Size of private data to allocate for user with each operation + * @param socket_id + * Socket to identifier allocate memory on + * @return + * - On success pointer to mempool + * - On failure NULL + */ +struct rte_mempool * __rte_experimental +rte_comp_op_pool_create(const char *name, + unsigned int nb_elts, unsigned int cache_size, + uint16_t user_size, int socket_id); + +/** + * Allocate an operation from a mempool with default parameters set + * + * @param mempool + * Compress operation mempool + * + * @return + * - On success returns a valid rte_comp_op structure + * - On failure returns NULL + */ +struct rte_comp_op * __rte_experimental +rte_comp_op_alloc(struct rte_mempool *mempool); + +/** + * Bulk allocate operations from a mempool with default parameters set + * + * @param mempool + * Compress operation mempool + * @param ops + * Array to place allocated operations + * @param nb_ops + * Number of operations to allocate + * @return + * - 0: Success + * - -ENOENT: Not enough entries in the mempool; no ops are retrieved. + */ +int __rte_experimental +rte_comp_op_bulk_alloc(struct rte_mempool *mempool, + struct rte_comp_op **ops, uint16_t nb_ops); + +/** + * Free operation structure + * If operation has been allocate from a rte_mempool, then the operation will + * be returned to the mempool. + * + * @param op + * Compress operation + */ +void __rte_experimental +rte_comp_op_free(struct rte_comp_op *op); + +/** + * Get the name of a compress service feature flag + * + * @param flag + * The mask describing the flag + * + * @return + * The name of this flag, or NULL if it's not a valid feature flag. + */ +const char * __rte_experimental +rte_comp_get_feature_name(uint64_t flag); + +#ifdef __cplusplus +} +#endif + +#endif /* _RTE_COMP_H_ */ diff --git a/lib/librte_compressdev/rte_compressdev.c b/lib/librte_compressdev/rte_compressdev.c new file mode 100644 index 00000000..9091dd6e --- /dev/null +++ b/lib/librte_compressdev/rte_compressdev.c @@ -0,0 +1,772 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2017-2018 Intel Corporation + */ + +#include <string.h> +#include <stdarg.h> +#include <stdio.h> +#include <inttypes.h> + +#include <rte_malloc.h> +#include <rte_eal.h> +#include <rte_memzone.h> + +#include "rte_compressdev.h" +#include "rte_compressdev_internal.h" +#include "rte_compressdev_pmd.h" + +#define RTE_COMPRESSDEV_DETACHED (0) +#define RTE_COMPRESSDEV_ATTACHED (1) + +struct rte_compressdev rte_comp_devices[RTE_COMPRESS_MAX_DEVS]; + +struct rte_compressdev *rte_compressdevs = &rte_comp_devices[0]; + +static struct rte_compressdev_global compressdev_globals = { + .devs = &rte_comp_devices[0], + .data = { NULL }, + .nb_devs = 0, + .max_devs = RTE_COMPRESS_MAX_DEVS +}; + +struct rte_compressdev_global *rte_compressdev_globals = &compressdev_globals; + +const struct rte_compressdev_capabilities * __rte_experimental +rte_compressdev_capability_get(uint8_t dev_id, + enum rte_comp_algorithm algo) +{ + const struct rte_compressdev_capabilities *capability; + struct rte_compressdev_info dev_info; + int i = 0; + + if (dev_id >= compressdev_globals.nb_devs) { + COMPRESSDEV_LOG(ERR, "Invalid dev_id=%d", dev_id); + return NULL; + } + rte_compressdev_info_get(dev_id, &dev_info); + + while ((capability = &dev_info.capabilities[i++])->algo != + RTE_COMP_ALGO_UNSPECIFIED){ + if (capability->algo == algo) + return capability; + } + + return NULL; +} + +const char * __rte_experimental +rte_compressdev_get_feature_name(uint64_t flag) +{ + switch (flag) { + case RTE_COMPDEV_FF_HW_ACCELERATED: + return "HW_ACCELERATED"; + case RTE_COMPDEV_FF_CPU_SSE: + return "CPU_SSE"; + case RTE_COMPDEV_FF_CPU_AVX: + return "CPU_AVX"; + case RTE_COMPDEV_FF_CPU_AVX2: + return "CPU_AVX2"; + case RTE_COMPDEV_FF_CPU_AVX512: + return "CPU_AVX512"; + case RTE_COMPDEV_FF_CPU_NEON: + return "CPU_NEON"; + default: + return NULL; + } +} + +static struct rte_compressdev * +rte_compressdev_get_dev(uint8_t dev_id) +{ + return &rte_compressdev_globals->devs[dev_id]; +} + +struct rte_compressdev * __rte_experimental +rte_compressdev_pmd_get_named_dev(const char *name) +{ + struct rte_compressdev *dev; + unsigned int i; + + if (name == NULL) + return NULL; + + for (i = 0; i < rte_compressdev_globals->max_devs; i++) { + dev = &rte_compressdev_globals->devs[i]; + + if ((dev->attached == RTE_COMPRESSDEV_ATTACHED) && + (strcmp(dev->data->name, name) == 0)) + return dev; + } + + return NULL; +} + +static unsigned int +rte_compressdev_is_valid_dev(uint8_t dev_id) +{ + struct rte_compressdev *dev = NULL; + + if (dev_id >= rte_compressdev_globals->nb_devs) + return 0; + + dev = rte_compressdev_get_dev(dev_id); + if (dev->attached != RTE_COMPRESSDEV_ATTACHED) + return 0; + else + return 1; +} + + +int __rte_experimental +rte_compressdev_get_dev_id(const char *name) +{ + unsigned int i; + + if (name == NULL) + return -1; + + for (i = 0; i < rte_compressdev_globals->nb_devs; i++) + if ((strcmp(rte_compressdev_globals->devs[i].data->name, name) + == 0) && + (rte_compressdev_globals->devs[i].attached == + RTE_COMPRESSDEV_ATTACHED)) + return i; + + return -1; +} + +uint8_t __rte_experimental +rte_compressdev_count(void) +{ + return rte_compressdev_globals->nb_devs; +} + +uint8_t __rte_experimental +rte_compressdev_devices_get(const char *driver_name, uint8_t *devices, + uint8_t nb_devices) +{ + uint8_t i, count = 0; + struct rte_compressdev *devs = rte_compressdev_globals->devs; + uint8_t max_devs = rte_compressdev_globals->max_devs; + + for (i = 0; i < max_devs && count < nb_devices; i++) { + + if (devs[i].attached == RTE_COMPRESSDEV_ATTACHED) { + int cmp; + + cmp = strncmp(devs[i].device->driver->name, + driver_name, + strlen(driver_name)); + + if (cmp == 0) + devices[count++] = devs[i].data->dev_id; + } + } + + return count; +} + +int __rte_experimental +rte_compressdev_socket_id(uint8_t dev_id) +{ + struct rte_compressdev *dev; + + if (!rte_compressdev_is_valid_dev(dev_id)) + return -1; + + dev = rte_compressdev_get_dev(dev_id); + + return dev->data->socket_id; +} + +static inline int +rte_compressdev_data_alloc(uint8_t dev_id, struct rte_compressdev_data **data, + int socket_id) +{ + char mz_name[RTE_COMPRESSDEV_NAME_MAX_LEN]; + const struct rte_memzone *mz; + int n; + + /* generate memzone name */ + n = snprintf(mz_name, sizeof(mz_name), + "rte_compressdev_data_%u", dev_id); + if (n >= (int)sizeof(mz_name)) + return -EINVAL; + + if (rte_eal_process_type() == RTE_PROC_PRIMARY) { + mz = rte_memzone_reserve(mz_name, + sizeof(struct rte_compressdev_data), + socket_id, 0); + } else + mz = rte_memzone_lookup(mz_name); + + if (mz == NULL) + return -ENOMEM; + + *data = mz->addr; + if (rte_eal_process_type() == RTE_PROC_PRIMARY) + memset(*data, 0, sizeof(struct rte_compressdev_data)); + + return 0; +} + +static uint8_t +rte_compressdev_find_free_device_index(void) +{ + uint8_t dev_id; + + for (dev_id = 0; dev_id < RTE_COMPRESS_MAX_DEVS; dev_id++) { + if (rte_comp_devices[dev_id].attached == + RTE_COMPRESSDEV_DETACHED) + return dev_id; + } + return RTE_COMPRESS_MAX_DEVS; +} + +struct rte_compressdev * __rte_experimental +rte_compressdev_pmd_allocate(const char *name, int socket_id) +{ + struct rte_compressdev *compressdev; + uint8_t dev_id; + + if (rte_compressdev_pmd_get_named_dev(name) != NULL) { + COMPRESSDEV_LOG(ERR, + "comp device with name %s already allocated!", name); + return NULL; + } + + dev_id = rte_compressdev_find_free_device_index(); + if (dev_id == RTE_COMPRESS_MAX_DEVS) { + COMPRESSDEV_LOG(ERR, "Reached maximum number of comp devices"); + return NULL; + } + compressdev = rte_compressdev_get_dev(dev_id); + + if (compressdev->data == NULL) { + struct rte_compressdev_data *compressdev_data = + compressdev_globals.data[dev_id]; + + int retval = rte_compressdev_data_alloc(dev_id, + &compressdev_data, socket_id); + + if (retval < 0 || compressdev_data == NULL) + return NULL; + + compressdev->data = compressdev_data; + + snprintf(compressdev->data->name, RTE_COMPRESSDEV_NAME_MAX_LEN, + "%s", name); + + compressdev->data->dev_id = dev_id; + compressdev->data->socket_id = socket_id; + compressdev->data->dev_started = 0; + + compressdev->attached = RTE_COMPRESSDEV_ATTACHED; + + compressdev_globals.nb_devs++; + } + + return compressdev; +} + +int __rte_experimental +rte_compressdev_pmd_release_device(struct rte_compressdev *compressdev) +{ + int ret; + + if (compressdev == NULL) + return -EINVAL; + + /* Close device only if device operations have been set */ + if (compressdev->dev_ops) { + ret = rte_compressdev_close(compressdev->data->dev_id); + if (ret < 0) + return ret; + } + + compressdev->attached = RTE_COMPRESSDEV_DETACHED; + compressdev_globals.nb_devs--; + return 0; +} + +uint16_t __rte_experimental +rte_compressdev_queue_pair_count(uint8_t dev_id) +{ + struct rte_compressdev *dev; + + dev = &rte_comp_devices[dev_id]; + return dev->data->nb_queue_pairs; +} + +static int +rte_compressdev_queue_pairs_config(struct rte_compressdev *dev, + uint16_t nb_qpairs, int socket_id) +{ + struct rte_compressdev_info dev_info; + void **qp; + unsigned int i; + + if ((dev == NULL) || (nb_qpairs < 1)) { + COMPRESSDEV_LOG(ERR, "invalid param: dev %p, nb_queues %u", + dev, nb_qpairs); + return -EINVAL; + } + + COMPRESSDEV_LOG(DEBUG, "Setup %d queues pairs on device %u", + nb_qpairs, dev->data->dev_id); + + memset(&dev_info, 0, sizeof(struct rte_compressdev_info)); + + RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->dev_infos_get, -ENOTSUP); + (*dev->dev_ops->dev_infos_get)(dev, &dev_info); + + if ((dev_info.max_nb_queue_pairs != 0) && + (nb_qpairs > dev_info.max_nb_queue_pairs)) { + COMPRESSDEV_LOG(ERR, "Invalid num queue_pairs (%u) for dev %u", + nb_qpairs, dev->data->dev_id); + return -EINVAL; + } + + if (dev->data->queue_pairs == NULL) { /* first time configuration */ + dev->data->queue_pairs = rte_zmalloc_socket( + "compressdev->queue_pairs", + sizeof(dev->data->queue_pairs[0]) * nb_qpairs, + RTE_CACHE_LINE_SIZE, socket_id); + + if (dev->data->queue_pairs == NULL) { + dev->data->nb_queue_pairs = 0; + COMPRESSDEV_LOG(ERR, + "failed to get memory for qp meta data, nb_queues %u", + nb_qpairs); + return -(ENOMEM); + } + } else { /* re-configure */ + int ret; + uint16_t old_nb_queues = dev->data->nb_queue_pairs; + + qp = dev->data->queue_pairs; + + RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->queue_pair_release, + -ENOTSUP); + + for (i = nb_qpairs; i < old_nb_queues; i++) { + ret = (*dev->dev_ops->queue_pair_release)(dev, i); + if (ret < 0) + return ret; + } + + qp = rte_realloc(qp, sizeof(qp[0]) * nb_qpairs, + RTE_CACHE_LINE_SIZE); + if (qp == NULL) { + COMPRESSDEV_LOG(ERR, + "failed to realloc qp meta data, nb_queues %u", + nb_qpairs); + return -(ENOMEM); + } + + if (nb_qpairs > old_nb_queues) { + uint16_t new_qs = nb_qpairs - old_nb_queues; + + memset(qp + old_nb_queues, 0, + sizeof(qp[0]) * new_qs); + } + + dev->data->queue_pairs = qp; + + } + dev->data->nb_queue_pairs = nb_qpairs; + return 0; +} + +static int +rte_compressdev_queue_pairs_release(struct rte_compressdev *dev) +{ + uint16_t num_qps, i; + int ret; + + if (dev == NULL) { + COMPRESSDEV_LOG(ERR, "invalid param: dev %p", dev); + return -EINVAL; + } + + num_qps = dev->data->nb_queue_pairs; + + if (num_qps == 0) + return 0; + + COMPRESSDEV_LOG(DEBUG, "Free %d queues pairs on device %u", + dev->data->nb_queue_pairs, dev->data->dev_id); + + RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->queue_pair_release, + -ENOTSUP); + + for (i = 0; i < num_qps; i++) { + ret = (*dev->dev_ops->queue_pair_release)(dev, i); + if (ret < 0) + return ret; + } + + if (dev->data->queue_pairs != NULL) + rte_free(dev->data->queue_pairs); + dev->data->queue_pairs = NULL; + dev->data->nb_queue_pairs = 0; + + return 0; +} + +int __rte_experimental +rte_compressdev_configure(uint8_t dev_id, struct rte_compressdev_config *config) +{ + struct rte_compressdev *dev; + int diag; + + if (!rte_compressdev_is_valid_dev(dev_id)) { + COMPRESSDEV_LOG(ERR, "Invalid dev_id=%" PRIu8, dev_id); + return -EINVAL; + } + + dev = &rte_comp_devices[dev_id]; + + if (dev->data->dev_started) { + COMPRESSDEV_LOG(ERR, + "device %d must be stopped to allow configuration", dev_id); + return -EBUSY; + } + + RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->dev_configure, -ENOTSUP); + + /* Setup new number of queue pairs and reconfigure device. */ + diag = rte_compressdev_queue_pairs_config(dev, config->nb_queue_pairs, + config->socket_id); + if (diag != 0) { + COMPRESSDEV_LOG(ERR, + "dev%d rte_comp_dev_queue_pairs_config = %d", + dev_id, diag); + return diag; + } + + return (*dev->dev_ops->dev_configure)(dev, config); +} + +int __rte_experimental +rte_compressdev_start(uint8_t dev_id) +{ + struct rte_compressdev *dev; + int diag; + + COMPRESSDEV_LOG(DEBUG, "Start dev_id=%" PRIu8, dev_id); + + if (!rte_compressdev_is_valid_dev(dev_id)) { + COMPRESSDEV_LOG(ERR, "Invalid dev_id=%" PRIu8, dev_id); + return -EINVAL; + } + + dev = &rte_comp_devices[dev_id]; + + RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->dev_start, -ENOTSUP); + + if (dev->data->dev_started != 0) { + COMPRESSDEV_LOG(ERR, + "Device with dev_id=%" PRIu8 " already started", dev_id); + return 0; + } + + diag = (*dev->dev_ops->dev_start)(dev); + if (diag == 0) + dev->data->dev_started = 1; + else + return diag; + + return 0; +} + +void __rte_experimental +rte_compressdev_stop(uint8_t dev_id) +{ + struct rte_compressdev *dev; + + if (!rte_compressdev_is_valid_dev(dev_id)) { + COMPRESSDEV_LOG(ERR, "Invalid dev_id=%" PRIu8, dev_id); + return; + } + + dev = &rte_comp_devices[dev_id]; + + RTE_FUNC_PTR_OR_RET(*dev->dev_ops->dev_stop); + + if (dev->data->dev_started == 0) { + COMPRESSDEV_LOG(ERR, + "Device with dev_id=%" PRIu8 " already stopped", dev_id); + return; + } + + (*dev->dev_ops->dev_stop)(dev); + dev->data->dev_started = 0; +} + +int __rte_experimental +rte_compressdev_close(uint8_t dev_id) +{ + struct rte_compressdev *dev; + int retval; + + if (!rte_compressdev_is_valid_dev(dev_id)) { + COMPRESSDEV_LOG(ERR, "Invalid dev_id=%" PRIu8, dev_id); + return -1; + } + + dev = &rte_comp_devices[dev_id]; + + /* Device must be stopped before it can be closed */ + if (dev->data->dev_started == 1) { + COMPRESSDEV_LOG(ERR, "Device %u must be stopped before closing", + dev_id); + return -EBUSY; + } + + /* Free queue pairs memory */ + retval = rte_compressdev_queue_pairs_release(dev); + + if (retval < 0) + return retval; + + RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->dev_close, -ENOTSUP); + retval = (*dev->dev_ops->dev_close)(dev); + + if (retval < 0) + return retval; + + return 0; +} + +int __rte_experimental +rte_compressdev_queue_pair_setup(uint8_t dev_id, uint16_t queue_pair_id, + uint32_t max_inflight_ops, int socket_id) +{ + struct rte_compressdev *dev; + + if (!rte_compressdev_is_valid_dev(dev_id)) { + COMPRESSDEV_LOG(ERR, "Invalid dev_id=%" PRIu8, dev_id); + return -EINVAL; + } + + dev = &rte_comp_devices[dev_id]; + if (queue_pair_id >= dev->data->nb_queue_pairs) { + COMPRESSDEV_LOG(ERR, "Invalid queue_pair_id=%d", queue_pair_id); + return -EINVAL; + } + + if (dev->data->dev_started) { + COMPRESSDEV_LOG(ERR, + "device %d must be stopped to allow configuration", dev_id); + return -EBUSY; + } + + if (max_inflight_ops == 0) { + COMPRESSDEV_LOG(ERR, + "Invalid maximum number of inflight operations"); + return -EINVAL; + } + + RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->queue_pair_setup, -ENOTSUP); + + return (*dev->dev_ops->queue_pair_setup)(dev, queue_pair_id, + max_inflight_ops, socket_id); +} + +uint16_t __rte_experimental +rte_compressdev_dequeue_burst(uint8_t dev_id, uint16_t qp_id, + struct rte_comp_op **ops, uint16_t nb_ops) +{ + struct rte_compressdev *dev = &rte_compressdevs[dev_id]; + + nb_ops = (*dev->dequeue_burst) + (dev->data->queue_pairs[qp_id], ops, nb_ops); + + return nb_ops; +} + +uint16_t __rte_experimental +rte_compressdev_enqueue_burst(uint8_t dev_id, uint16_t qp_id, + struct rte_comp_op **ops, uint16_t nb_ops) +{ + struct rte_compressdev *dev = &rte_compressdevs[dev_id]; + + return (*dev->enqueue_burst)( + dev->data->queue_pairs[qp_id], ops, nb_ops); +} + +int __rte_experimental +rte_compressdev_stats_get(uint8_t dev_id, struct rte_compressdev_stats *stats) +{ + struct rte_compressdev *dev; + + if (!rte_compressdev_is_valid_dev(dev_id)) { + COMPRESSDEV_LOG(ERR, "Invalid dev_id=%d", dev_id); + return -ENODEV; + } + + if (stats == NULL) { + COMPRESSDEV_LOG(ERR, "Invalid stats ptr"); + return -EINVAL; + } + + dev = &rte_comp_devices[dev_id]; + memset(stats, 0, sizeof(*stats)); + + RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->stats_get, -ENOTSUP); + (*dev->dev_ops->stats_get)(dev, stats); + return 0; +} + +void __rte_experimental +rte_compressdev_stats_reset(uint8_t dev_id) +{ + struct rte_compressdev *dev; + + if (!rte_compressdev_is_valid_dev(dev_id)) { + COMPRESSDEV_LOG(ERR, "Invalid dev_id=%" PRIu8, dev_id); + return; + } + + dev = &rte_comp_devices[dev_id]; + + RTE_FUNC_PTR_OR_RET(*dev->dev_ops->stats_reset); + (*dev->dev_ops->stats_reset)(dev); +} + + +void __rte_experimental +rte_compressdev_info_get(uint8_t dev_id, struct rte_compressdev_info *dev_info) +{ + struct rte_compressdev *dev; + + if (dev_id >= compressdev_globals.nb_devs) { + COMPRESSDEV_LOG(ERR, "Invalid dev_id=%d", dev_id); + return; + } + + dev = &rte_comp_devices[dev_id]; + + memset(dev_info, 0, sizeof(struct rte_compressdev_info)); + + RTE_FUNC_PTR_OR_RET(*dev->dev_ops->dev_infos_get); + (*dev->dev_ops->dev_infos_get)(dev, dev_info); + + dev_info->driver_name = dev->device->driver->name; +} + +int __rte_experimental +rte_compressdev_private_xform_create(uint8_t dev_id, + const struct rte_comp_xform *xform, + void **priv_xform) +{ + struct rte_compressdev *dev; + int ret; + + dev = rte_compressdev_get_dev(dev_id); + + if (xform == NULL || priv_xform == NULL || dev == NULL) + return -EINVAL; + + RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->private_xform_create, -ENOTSUP); + ret = (*dev->dev_ops->private_xform_create)(dev, xform, priv_xform); + if (ret < 0) { + COMPRESSDEV_LOG(ERR, + "dev_id %d failed to create private_xform: err=%d", + dev_id, ret); + return ret; + }; + + return 0; +} + +int __rte_experimental +rte_compressdev_private_xform_free(uint8_t dev_id, void *priv_xform) +{ + struct rte_compressdev *dev; + int ret; + + dev = rte_compressdev_get_dev(dev_id); + + if (dev == NULL || priv_xform == NULL) + return -EINVAL; + + RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->private_xform_free, -ENOTSUP); + ret = dev->dev_ops->private_xform_free(dev, priv_xform); + if (ret < 0) { + COMPRESSDEV_LOG(ERR, + "dev_id %d failed to free private xform: err=%d", + dev_id, ret); + return ret; + }; + + return 0; +} + +int __rte_experimental +rte_compressdev_stream_create(uint8_t dev_id, + const struct rte_comp_xform *xform, + void **stream) +{ + struct rte_compressdev *dev; + int ret; + + dev = rte_compressdev_get_dev(dev_id); + + if (xform == NULL || dev == NULL || stream == NULL) + return -EINVAL; + + RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->stream_create, -ENOTSUP); + ret = (*dev->dev_ops->stream_create)(dev, xform, stream); + if (ret < 0) { + COMPRESSDEV_LOG(ERR, + "dev_id %d failed to create stream: err=%d", + dev_id, ret); + return ret; + }; + + return 0; +} + + +int __rte_experimental +rte_compressdev_stream_free(uint8_t dev_id, void *stream) +{ + struct rte_compressdev *dev; + int ret; + + dev = rte_compressdev_get_dev(dev_id); + + if (dev == NULL || stream == NULL) + return -EINVAL; + + RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->stream_free, -ENOTSUP); + ret = dev->dev_ops->stream_free(dev, stream); + if (ret < 0) { + COMPRESSDEV_LOG(ERR, + "dev_id %d failed to free stream: err=%d", + dev_id, ret); + return ret; + }; + + return 0; +} + +const char * __rte_experimental +rte_compressdev_name_get(uint8_t dev_id) +{ + struct rte_compressdev *dev = rte_compressdev_get_dev(dev_id); + + if (dev == NULL) + return NULL; + + return dev->data->name; +} + +RTE_INIT(rte_compressdev_log) +{ + compressdev_logtype = rte_log_register("lib.compressdev"); + if (compressdev_logtype >= 0) + rte_log_set_level(compressdev_logtype, RTE_LOG_NOTICE); +} diff --git a/lib/librte_compressdev/rte_compressdev.h b/lib/librte_compressdev/rte_compressdev.h new file mode 100644 index 00000000..5b4fca4d --- /dev/null +++ b/lib/librte_compressdev/rte_compressdev.h @@ -0,0 +1,540 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2017-2018 Intel Corporation + */ + +#ifndef _RTE_COMPRESSDEV_H_ +#define _RTE_COMPRESSDEV_H_ + +/** + * @file rte_compressdev.h + * + * RTE Compression Device APIs + * + * Defines comp device APIs for the provisioning of compression operations. + */ + +#ifdef __cplusplus +extern "C" { +#endif + +#include <rte_common.h> + +#include "rte_comp.h" + +/** + * Parameter log base 2 range description. + * Final value will be 2^value. + */ +struct rte_param_log2_range { + uint8_t min; /**< Minimum log2 value */ + uint8_t max; /**< Maximum log2 value */ + uint8_t increment; + /**< If a range of sizes are supported, + * this parameter is used to indicate + * increments in base 2 log byte value + * that are supported between the minimum and maximum + */ +}; + +/** Structure used to capture a capability of a comp device */ +struct rte_compressdev_capabilities { + enum rte_comp_algorithm algo; + /* Compression algorithm */ + uint64_t comp_feature_flags; + /**< Bitmask of flags for compression service features */ + struct rte_param_log2_range window_size; + /**< Window size range in base two log byte values */ +}; + +/** Macro used at end of comp PMD list */ +#define RTE_COMP_END_OF_CAPABILITIES_LIST() \ + { RTE_COMP_ALGO_UNSPECIFIED } + +const struct rte_compressdev_capabilities * __rte_experimental +rte_compressdev_capability_get(uint8_t dev_id, + enum rte_comp_algorithm algo); + +/** + * compression device supported feature flags + * + * @note New features flags should be added to the end of the list + * + * Keep these flags synchronised with rte_compressdev_get_feature_name() + */ +#define RTE_COMPDEV_FF_HW_ACCELERATED (1ULL << 0) +/**< Operations are off-loaded to an external hardware accelerator */ +#define RTE_COMPDEV_FF_CPU_SSE (1ULL << 1) +/**< Utilises CPU SIMD SSE instructions */ +#define RTE_COMPDEV_FF_CPU_AVX (1ULL << 2) +/**< Utilises CPU SIMD AVX instructions */ +#define RTE_COMPDEV_FF_CPU_AVX2 (1ULL << 3) +/**< Utilises CPU SIMD AVX2 instructions */ +#define RTE_COMPDEV_FF_CPU_AVX512 (1ULL << 4) +/**< Utilises CPU SIMD AVX512 instructions */ +#define RTE_COMPDEV_FF_CPU_NEON (1ULL << 5) +/**< Utilises CPU NEON instructions */ + +/** + * Get the name of a compress device feature flag. + * + * @param flag + * The mask describing the flag + * + * @return + * The name of this flag, or NULL if it's not a valid feature flag. + */ +const char * __rte_experimental +rte_compressdev_get_feature_name(uint64_t flag); + +/** comp device information */ +struct rte_compressdev_info { + const char *driver_name; /**< Driver name. */ + uint64_t feature_flags; /**< Feature flags */ + const struct rte_compressdev_capabilities *capabilities; + /**< Array of devices supported capabilities */ + uint16_t max_nb_queue_pairs; + /**< Maximum number of queues pairs supported by device. + * (If 0, there is no limit in maximum number of queue pairs) + */ +}; + +/** comp device statistics */ +struct rte_compressdev_stats { + uint64_t enqueued_count; + /**< Count of all operations enqueued */ + uint64_t dequeued_count; + /**< Count of all operations dequeued */ + + uint64_t enqueue_err_count; + /**< Total error count on operations enqueued */ + uint64_t dequeue_err_count; + /**< Total error count on operations dequeued */ +}; + + +/** + * Get the device identifier for the named compress device. + * + * @param name + * Device name to select the device structure + * @return + * - Returns compress device identifier on success. + * - Return -1 on failure to find named compress device. + */ +int __rte_experimental +rte_compressdev_get_dev_id(const char *name); + +/** + * Get the compress device name given a device identifier. + * + * @param dev_id + * Compress device identifier + * @return + * - Returns compress device name. + * - Returns NULL if compress device is not present. + */ +const char * __rte_experimental +rte_compressdev_name_get(uint8_t dev_id); + +/** + * Get the total number of compress devices that have been successfully + * initialised. + * + * @return + * - The total number of usable compress devices. + */ +uint8_t __rte_experimental +rte_compressdev_count(void); + +/** + * Get number and identifiers of attached comp devices that + * use the same compress driver. + * + * @param driver_name + * Driver name + * @param devices + * Output devices identifiers + * @param nb_devices + * Maximal number of devices + * + * @return + * Returns number of attached compress devices. + */ +uint8_t __rte_experimental +rte_compressdev_devices_get(const char *driver_name, uint8_t *devices, + uint8_t nb_devices); + +/* + * Return the NUMA socket to which a device is connected. + * + * @param dev_id + * Compress device identifier + * @return + * The NUMA socket id to which the device is connected or + * a default of zero if the socket could not be determined. + * -1 if returned is the dev_id value is out of range. + */ +int __rte_experimental +rte_compressdev_socket_id(uint8_t dev_id); + +/** Compress device configuration structure */ +struct rte_compressdev_config { + int socket_id; + /**< Socket on which to allocate resources */ + uint16_t nb_queue_pairs; + /**< Total number of queue pairs to configure on a device */ + uint16_t max_nb_priv_xforms; + /**< Max number of private_xforms which will be created on the device */ + uint16_t max_nb_streams; + /**< Max number of streams which will be created on the device */ +}; + +/** + * Configure a device. + * + * This function must be invoked first before any other function in the + * API. This function can also be re-invoked when a device is in the + * stopped state. + * + * @param dev_id + * Compress device identifier + * @param config + * The compress device configuration + * @return + * - 0: Success, device configured. + * - <0: Error code returned by the driver configuration function. + */ +int __rte_experimental +rte_compressdev_configure(uint8_t dev_id, + struct rte_compressdev_config *config); + +/** + * Start a device. + * + * The device start step is called after configuring the device and setting up + * its queue pairs. + * On success, data-path functions exported by the API (enqueue/dequeue, etc) + * can be invoked. + * + * @param dev_id + * Compress device identifier + * @return + * - 0: Success, device started. + * - <0: Error code of the driver device start function. + */ +int __rte_experimental +rte_compressdev_start(uint8_t dev_id); + +/** + * Stop a device. The device can be restarted with a call to + * rte_compressdev_start() + * + * @param dev_id + * Compress device identifier + */ +void __rte_experimental +rte_compressdev_stop(uint8_t dev_id); + +/** + * Close an device. + * The memory allocated in the device gets freed. + * After calling this function, in order to use + * the device again, it is required to + * configure the device again. + * + * @param dev_id + * Compress device identifier + * + * @return + * - 0 on successfully closing device + * - <0 on failure to close device + */ +int __rte_experimental +rte_compressdev_close(uint8_t dev_id); + +/** + * Allocate and set up a receive queue pair for a device. + * This should only be called when the device is stopped. + * + * + * @param dev_id + * Compress device identifier + * @param queue_pair_id + * The index of the queue pairs to set up. The + * value must be in the range [0, nb_queue_pair - 1] + * previously supplied to rte_compressdev_configure() + * @param max_inflight_ops + * Max number of ops which the qp will have to + * accommodate simultaneously + * @param socket_id + * The *socket_id* argument is the socket identifier + * in case of NUMA. The value can be *SOCKET_ID_ANY* + * if there is no NUMA constraint for the DMA memory + * allocated for the receive queue pair + * @return + * - 0: Success, queue pair correctly set up. + * - <0: Queue pair configuration failed + */ +int __rte_experimental +rte_compressdev_queue_pair_setup(uint8_t dev_id, uint16_t queue_pair_id, + uint32_t max_inflight_ops, int socket_id); + +/** + * Get the number of queue pairs on a specific comp device + * + * @param dev_id + * Compress device identifier + * @return + * - The number of configured queue pairs. + */ +uint16_t __rte_experimental +rte_compressdev_queue_pair_count(uint8_t dev_id); + + +/** + * Retrieve the general I/O statistics of a device. + * + * @param dev_id + * The identifier of the device + * @param stats + * A pointer to a structure of type + * *rte_compressdev_stats* to be filled with the + * values of device counters + * @return + * - Zero if successful. + * - Non-zero otherwise. + */ +int __rte_experimental +rte_compressdev_stats_get(uint8_t dev_id, struct rte_compressdev_stats *stats); + +/** + * Reset the general I/O statistics of a device. + * + * @param dev_id + * The identifier of the device. + */ +void __rte_experimental +rte_compressdev_stats_reset(uint8_t dev_id); + +/** + * Retrieve the contextual information of a device. + * + * @param dev_id + * Compress device identifier + * @param dev_info + * A pointer to a structure of type *rte_compressdev_info* + * to be filled with the contextual information of the device + * + * @note The capabilities field of dev_info is set to point to the first + * element of an array of struct rte_compressdev_capabilities. + * The element after the last valid element has it's op field set to + * RTE_COMP_ALGO_LIST_END. + */ +void __rte_experimental +rte_compressdev_info_get(uint8_t dev_id, struct rte_compressdev_info *dev_info); + +/** + * + * Dequeue a burst of processed compression operations from a queue on the comp + * device. The dequeued operation are stored in *rte_comp_op* structures + * whose pointers are supplied in the *ops* array. + * + * The rte_compressdev_dequeue_burst() function returns the number of ops + * actually dequeued, which is the number of *rte_comp_op* data structures + * effectively supplied into the *ops* array. + * + * A return value equal to *nb_ops* indicates that the queue contained + * at least *nb_ops* operations, and this is likely to signify that other + * processed operations remain in the devices output queue. Applications + * implementing a "retrieve as many processed operations as possible" policy + * can check this specific case and keep invoking the + * rte_compressdev_dequeue_burst() function until a value less than + * *nb_ops* is returned. + * + * The rte_compressdev_dequeue_burst() function does not provide any error + * notification to avoid the corresponding overhead. + * + * @note: operation ordering is not maintained within the queue pair. + * + * @note: In case op status = OUT_OF_SPACE_TERMINATED, op.consumed=0 and the + * op must be resubmitted with the same input data and a larger output buffer. + * op.produced is usually 0, but in decompression cases a PMD may return > 0 + * and the application may find it useful to inspect that data. + * This status is only returned on STATELESS ops. + * + * @note: In case op status = OUT_OF_SPACE_RECOVERABLE, op.produced can be used + * and next op in stream should continue on from op.consumed+1 with a fresh + * output buffer. + * Consumed=0, produced=0 is an unusual but allowed case. There may be useful + * state/history stored in the PMD, even though no output was produced yet. + * + * + * @param dev_id + * Compress device identifier + * @param qp_id + * The index of the queue pair from which to retrieve + * processed operations. The value must be in the range + * [0, nb_queue_pair - 1] previously supplied to + * rte_compressdev_configure() + * @param ops + * The address of an array of pointers to + * *rte_comp_op* structures that must be + * large enough to store *nb_ops* pointers in it + * @param nb_ops + * The maximum number of operations to dequeue + * @return + * - The number of operations actually dequeued, which is the number + * of pointers to *rte_comp_op* structures effectively supplied to the + * *ops* array. + */ +uint16_t __rte_experimental +rte_compressdev_dequeue_burst(uint8_t dev_id, uint16_t qp_id, + struct rte_comp_op **ops, uint16_t nb_ops); + +/** + * Enqueue a burst of operations for processing on a compression device. + * + * The rte_compressdev_enqueue_burst() function is invoked to place + * comp operations on the queue *qp_id* of the device designated by + * its *dev_id*. + * + * The *nb_ops* parameter is the number of operations to process which are + * supplied in the *ops* array of *rte_comp_op* structures. + * + * The rte_compressdev_enqueue_burst() function returns the number of + * operations it actually enqueued for processing. A return value equal to + * *nb_ops* means that all packets have been enqueued. + * + * @note All compression operations are Out-of-place (OOP) operations, + * as the size of the output data is different to the size of the input data. + * + * @note The flush flag only applies to operations which return SUCCESS. + * In OUT_OF_SPACE cases whether STATEFUL or STATELESS, data in dest buffer + * is as if flush flag was FLUSH_NONE. + * @note flush flag only applies in compression direction. It has no meaning + * for decompression. + * @note: operation ordering is not maintained within the queue pair. + * + * @param dev_id + * Compress device identifier + * @param qp_id + * The index of the queue pair on which operations + * are to be enqueued for processing. The value + * must be in the range [0, nb_queue_pairs - 1] + * previously supplied to *rte_compressdev_configure* + * @param ops + * The address of an array of *nb_ops* pointers + * to *rte_comp_op* structures which contain + * the operations to be processed + * @param nb_ops + * The number of operations to process + * @return + * The number of operations actually enqueued on the device. The return + * value can be less than the value of the *nb_ops* parameter when the + * comp devices queue is full or if invalid parameters are specified in + * a *rte_comp_op*. + */ +uint16_t __rte_experimental +rte_compressdev_enqueue_burst(uint8_t dev_id, uint16_t qp_id, + struct rte_comp_op **ops, uint16_t nb_ops); + +/** + * This should alloc a stream from the device's mempool and initialise it. + * The application should call this API when setting up for the stateful + * processing of a set of data on a device. The API can be called multiple + * times to set up a stream for each data set. The handle returned is only for + * use with ops of op_type STATEFUL and must be passed to the PMD + * with every op in the data stream + * + * @param dev_id + * Compress device identifier + * @param xform + * xform data + * @param stream + * Pointer to where PMD's private stream handle should be stored + * + * @return + * - 0 if successful and valid stream handle + * - <0 in error cases + * - Returns -EINVAL if input parameters are invalid. + * - Returns -ENOTSUP if comp device does not support STATEFUL operations. + * - Returns -ENOTSUP if comp device does not support the comp transform. + * - Returns -ENOMEM if the private stream could not be allocated. + * + */ +int __rte_experimental +rte_compressdev_stream_create(uint8_t dev_id, + const struct rte_comp_xform *xform, + void **stream); + +/** + * This should clear the stream and return it to the device's mempool. + * + * @param dev_id + * Compress device identifier + * + * @param stream + * PMD's private stream data + * + * @return + * - 0 if successful + * - <0 in error cases + * - Returns -EINVAL if input parameters are invalid. + * - Returns -ENOTSUP if comp device does not support STATEFUL operations. + * - Returns -EBUSY if can't free stream as there are inflight operations + */ +int __rte_experimental +rte_compressdev_stream_free(uint8_t dev_id, void *stream); + +/** + * This should alloc a private_xform from the device's mempool and initialise + * it. The application should call this API when setting up for stateless + * processing on a device. If it returns non-shareable, then the appl cannot + * share this handle with multiple in-flight ops and should call this API again + * to get a separate handle for every in-flight op. + * The handle returned is only valid for use with ops of op_type STATELESS. + * + * @param dev_id + * Compress device identifier + * @param xform + * xform data + * @param private_xform + * Pointer to where PMD's private_xform handle should be stored + * + * @return + * - if successful returns 0 + * and valid private_xform handle + * - <0 in error cases + * - Returns -EINVAL if input parameters are invalid. + * - Returns -ENOTSUP if comp device does not support the comp transform. + * - Returns -ENOMEM if the private_xform could not be allocated. + */ +int __rte_experimental +rte_compressdev_private_xform_create(uint8_t dev_id, + const struct rte_comp_xform *xform, + void **private_xform); + +/** + * This should clear the private_xform and return it to the device's mempool. + * It is the application's responsibility to ensure that private_xform data + * is not cleared while there are still in-flight operations using it. + * + * @param dev_id + * Compress device identifier + * + * @param private_xform + * PMD's private_xform data + * + * @return + * - 0 if successful + * - <0 in error cases + * - Returns -EINVAL if input parameters are invalid. + */ +int __rte_experimental +rte_compressdev_private_xform_free(uint8_t dev_id, void *private_xform); + +#ifdef __cplusplus +} +#endif + +#endif /* _RTE_COMPRESSDEV_H_ */ diff --git a/lib/librte_compressdev/rte_compressdev_internal.h b/lib/librte_compressdev/rte_compressdev_internal.h new file mode 100644 index 00000000..22ceac66 --- /dev/null +++ b/lib/librte_compressdev/rte_compressdev_internal.h @@ -0,0 +1,114 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2017-2018 Intel Corporation + */ + +#ifndef _RTE_COMPRESSDEV_INTERNAL_H_ +#define _RTE_COMPRESSDEV_INTERNAL_H_ + +/* rte_compressdev_internal.h + * This file holds Compressdev private data structures. + */ +#include <rte_log.h> + +#include "rte_comp.h" + +#define RTE_COMPRESSDEV_NAME_MAX_LEN (64) +/**< Max length of name of comp PMD */ + +/* Logging Macros */ +extern int compressdev_logtype; +#define COMPRESSDEV_LOG(level, fmt, args...) \ + rte_log(RTE_LOG_ ## level, compressdev_logtype, "%s(): "fmt "\n", \ + __func__, ##args) + +/** + * Dequeue processed packets from queue pair of a device. + * + * @param qp + * The queue pair from which to retrieve + * processed operations. + * @param ops + * The address of an array of pointers to + * *rte_comp_op* structures that must be + * large enough to store *nb_ops* pointers in it + * @param nb_ops + * The maximum number of operations to dequeue + * @return + * - The number of operations actually dequeued, which is the number + * of pointers to *rte_comp_op* structures effectively supplied to the + * *ops* array. + */ +typedef uint16_t (*compressdev_dequeue_pkt_burst_t)(void *qp, + struct rte_comp_op **ops, uint16_t nb_ops); + +/** + * Enqueue a burst of operations for processing. + * + * @param qp + * The queue pair on which operations + * are to be enqueued for processing + * @param ops + * The address of an array of *nb_ops* pointers + * to *rte_comp_op* structures which contain + * the operations to be processed + * @param nb_ops + * The number of operations to process + * @return + * The number of operations actually enqueued on the device. The return + * value can be less than the value of the *nb_ops* parameter when the + * comp devices queue is full or if invalid parameters are specified in + * a *rte_comp_op*. + */ + +typedef uint16_t (*compressdev_enqueue_pkt_burst_t)(void *qp, + struct rte_comp_op **ops, uint16_t nb_ops); + +/** The data structure associated with each comp device. */ +struct rte_compressdev { + compressdev_dequeue_pkt_burst_t dequeue_burst; + /**< Pointer to PMD receive function */ + compressdev_enqueue_pkt_burst_t enqueue_burst; + /**< Pointer to PMD transmit function */ + + struct rte_compressdev_data *data; + /**< Pointer to device data */ + struct rte_compressdev_ops *dev_ops; + /**< Functions exported by PMD */ + uint64_t feature_flags; + /**< Supported features */ + struct rte_device *device; + /**< Backing device */ + + __extension__ + uint8_t attached : 1; + /**< Flag indicating the device is attached */ +} __rte_cache_aligned; + +/** + * + * The data part, with no function pointers, associated with each device. + * + * This structure is safe to place in shared memory to be common among + * different processes in a multi-process configuration. + */ +struct rte_compressdev_data { + uint8_t dev_id; + /**< Compress device identifier */ + uint8_t socket_id; + /**< Socket identifier where memory is allocated */ + char name[RTE_COMPRESSDEV_NAME_MAX_LEN]; + /**< Unique identifier name */ + + __extension__ + uint8_t dev_started : 1; + /**< Device state: STARTED(1)/STOPPED(0) */ + + void **queue_pairs; + /**< Array of pointers to queue pairs. */ + uint16_t nb_queue_pairs; + /**< Number of device queue pairs */ + + void *dev_private; + /**< PMD-specific private data */ +} __rte_cache_aligned; +#endif diff --git a/lib/librte_compressdev/rte_compressdev_pmd.c b/lib/librte_compressdev/rte_compressdev_pmd.c new file mode 100644 index 00000000..7de4f339 --- /dev/null +++ b/lib/librte_compressdev/rte_compressdev_pmd.c @@ -0,0 +1,160 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2017-2018 Intel Corporation + */ + +#include <rte_malloc.h> +#include <rte_kvargs.h> +#include <rte_eal.h> + +#include "rte_compressdev_internal.h" +#include "rte_compressdev_pmd.h" + +int compressdev_logtype; + +/** + * Parse name from argument + */ +static int +rte_compressdev_pmd_parse_name_arg(const char *key __rte_unused, + const char *value, void *extra_args) +{ + struct rte_compressdev_pmd_init_params *params = extra_args; + int n; + + n = snprintf(params->name, RTE_COMPRESSDEV_NAME_MAX_LEN, "%s", value); + if (n >= RTE_COMPRESSDEV_NAME_MAX_LEN) + return -EINVAL; + + return 0; +} + +/** + * Parse unsigned integer from argument + */ +static int +rte_compressdev_pmd_parse_uint_arg(const char *key __rte_unused, + const char *value, void *extra_args) +{ + int i; + char *end; + + errno = 0; + i = strtol(value, &end, 10); + if (*end != 0 || errno != 0 || i < 0) + return -EINVAL; + + *((uint32_t *)extra_args) = i; + return 0; +} + +int __rte_experimental +rte_compressdev_pmd_parse_input_args( + struct rte_compressdev_pmd_init_params *params, + const char *args) +{ + struct rte_kvargs *kvlist = NULL; + int ret = 0; + + if (params == NULL) + return -EINVAL; + + if (args) { + kvlist = rte_kvargs_parse(args, compressdev_pmd_valid_params); + if (kvlist == NULL) + return -EINVAL; + + ret = rte_kvargs_process(kvlist, + RTE_COMPRESSDEV_PMD_SOCKET_ID_ARG, + &rte_compressdev_pmd_parse_uint_arg, + ¶ms->socket_id); + if (ret < 0) + goto free_kvlist; + + ret = rte_kvargs_process(kvlist, + RTE_COMPRESSDEV_PMD_NAME_ARG, + &rte_compressdev_pmd_parse_name_arg, + params); + if (ret < 0) + goto free_kvlist; + } + +free_kvlist: + rte_kvargs_free(kvlist); + return ret; +} + +struct rte_compressdev * __rte_experimental +rte_compressdev_pmd_create(const char *name, + struct rte_device *device, + size_t private_data_size, + struct rte_compressdev_pmd_init_params *params) +{ + struct rte_compressdev *compressdev; + + if (params->name[0] != '\0') { + COMPRESSDEV_LOG(INFO, "[%s] User specified device name = %s\n", + device->driver->name, params->name); + name = params->name; + } + + COMPRESSDEV_LOG(INFO, "[%s] - Creating compressdev %s\n", + device->driver->name, name); + + COMPRESSDEV_LOG(INFO, + "[%s] - Init parameters - name: %s, socket id: %d", + device->driver->name, name, + params->socket_id); + + /* allocate device structure */ + compressdev = rte_compressdev_pmd_allocate(name, params->socket_id); + if (compressdev == NULL) { + COMPRESSDEV_LOG(ERR, "[%s] Failed to allocate comp device %s", + device->driver->name, name); + return NULL; + } + + /* allocate private device structure */ + if (rte_eal_process_type() == RTE_PROC_PRIMARY) { + compressdev->data->dev_private = + rte_zmalloc_socket("compressdev device private", + private_data_size, + RTE_CACHE_LINE_SIZE, + params->socket_id); + + if (compressdev->data->dev_private == NULL) { + COMPRESSDEV_LOG(ERR, + "[%s] Cannot allocate memory for compressdev %s private data", + device->driver->name, name); + + rte_compressdev_pmd_release_device(compressdev); + return NULL; + } + } + + compressdev->device = device; + + return compressdev; +} + +int __rte_experimental +rte_compressdev_pmd_destroy(struct rte_compressdev *compressdev) +{ + int retval; + + COMPRESSDEV_LOG(INFO, "[%s] Closing comp device %s", + compressdev->device->driver->name, + compressdev->device->name); + + /* free comp device */ + retval = rte_compressdev_pmd_release_device(compressdev); + if (retval) + return retval; + + if (rte_eal_process_type() == RTE_PROC_PRIMARY) + rte_free(compressdev->data->dev_private); + + compressdev->device = NULL; + compressdev->data = NULL; + + return 0; +} diff --git a/lib/librte_compressdev/rte_compressdev_pmd.h b/lib/librte_compressdev/rte_compressdev_pmd.h new file mode 100644 index 00000000..38e9ea02 --- /dev/null +++ b/lib/librte_compressdev/rte_compressdev_pmd.h @@ -0,0 +1,390 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2017-2018 Intel Corporation + */ + +#ifndef _RTE_COMPRESSDEV_PMD_H_ +#define _RTE_COMPRESSDEV_PMD_H_ + +/** @file + * RTE comp PMD APIs + * + * @note + * These APIs are for comp PMDs only and user applications should not call + * them directly. + */ + +#ifdef __cplusplus +extern "C" { +#endif + +#include <string.h> + +#include <rte_dev.h> +#include <rte_common.h> + +#include "rte_compressdev.h" +#include "rte_compressdev_internal.h" + +#define RTE_COMPRESSDEV_PMD_NAME_ARG ("name") +#define RTE_COMPRESSDEV_PMD_SOCKET_ID_ARG ("socket_id") + +static const char * const compressdev_pmd_valid_params[] = { + RTE_COMPRESSDEV_PMD_NAME_ARG, + RTE_COMPRESSDEV_PMD_SOCKET_ID_ARG +}; + +/** + * @internal + * Initialisation parameters for comp devices + */ +struct rte_compressdev_pmd_init_params { + char name[RTE_COMPRESSDEV_NAME_MAX_LEN]; + int socket_id; +}; + +/** Global structure used for maintaining state of allocated comp devices */ +struct rte_compressdev_global { + struct rte_compressdev *devs; /**< Device information array */ + struct rte_compressdev_data *data[RTE_COMPRESS_MAX_DEVS]; + /**< Device private data */ + uint8_t nb_devs; /**< Number of devices found */ + uint8_t max_devs; /**< Max number of devices */ +}; + +/** Pointer to global array of comp devices */ +extern struct rte_compressdev *rte_compressdevs; +/** Pointer to global comp devices data structure */ +extern struct rte_compressdev_global *rte_compressdev_globals; + +/** + * Get the rte_compressdev structure device pointer for the named device. + * + * @param name + * Compress device name + * @return + * - The rte_compressdev structure pointer for the given device identifier. + */ +struct rte_compressdev * __rte_experimental +rte_compressdev_pmd_get_named_dev(const char *name); + +/** + * Definitions of all functions exported by a driver through the + * the generic structure of type *comp_dev_ops* supplied in the + * *rte_compressdev* structure associated with a device. + */ + +/** + * Function used to configure device. + * + * @param dev + * Compress device + * @param config + * Compress device configurations + * @return + * Returns 0 on success + */ +typedef int (*compressdev_configure_t)(struct rte_compressdev *dev, + struct rte_compressdev_config *config); + +/** + * Function used to start a configured device. + * + * @param dev + * Compress device + * @return + * Returns 0 on success + */ +typedef int (*compressdev_start_t)(struct rte_compressdev *dev); + +/** + * Function used to stop a configured device. + * + * @param dev + * Compress device + */ +typedef void (*compressdev_stop_t)(struct rte_compressdev *dev); + +/** + * Function used to close a configured device. + * + * @param dev + * Compress device + * @return + * - 0 on success. + * - EAGAIN if can't close as device is busy + */ +typedef int (*compressdev_close_t)(struct rte_compressdev *dev); + + +/** + * Function used to get statistics of a device. + * + * @param dev + * Compress device + * @param stats + * Compress device stats to populate + */ +typedef void (*compressdev_stats_get_t)(struct rte_compressdev *dev, + struct rte_compressdev_stats *stats); + + +/** + * Function used to reset statistics of a device. + * + * @param dev + * Compress device + */ +typedef void (*compressdev_stats_reset_t)(struct rte_compressdev *dev); + + +/** + * Function used to get specific information of a device. + * + * @param dev + * Compress device + */ +typedef void (*compressdev_info_get_t)(struct rte_compressdev *dev, + struct rte_compressdev_info *dev_info); + +/** + * Setup a queue pair for a device. + * + * @param dev + * Compress device + * @param qp_id + * Queue pair identifier + * @param max_inflight_ops + * Max inflight ops which qp must accommodate + * @param socket_id + * Socket identifier + * @return + * Returns 0 on success. + */ +typedef int (*compressdev_queue_pair_setup_t)(struct rte_compressdev *dev, + uint16_t qp_id, uint32_t max_inflight_ops, int socket_id); + +/** + * Release memory resources allocated by given queue pair. + * + * @param dev + * Compress device + * @param qp_id + * Queue pair identifier + * @return + * - 0 on success. + * - EAGAIN if can't close as device is busy + */ +typedef int (*compressdev_queue_pair_release_t)(struct rte_compressdev *dev, + uint16_t qp_id); + +/** + * Get number of available queue pairs of a device. + * + * @param dev + * Compress device + * @return + * Returns number of queue pairs on success. + */ +typedef uint32_t (*compressdev_queue_pair_count_t)(struct rte_compressdev *dev); + +/** + * Create driver private stream data. + * + * @param dev + * Compressdev device + * @param xform + * xform data + * @param stream + * ptr where handle of pmd's private stream data should be stored + * @return + * - Returns 0 if private stream structure has been created successfully. + * - Returns -EINVAL if input parameters are invalid. + * - Returns -ENOTSUP if comp device does not support STATEFUL operations. + * - Returns -ENOTSUP if comp device does not support the comp transform. + * - Returns -ENOMEM if the private stream could not be allocated. + */ +typedef int (*compressdev_stream_create_t)(struct rte_compressdev *dev, + const struct rte_comp_xform *xform, void **stream); + +/** + * Free driver private stream data. + * + * @param dev + * Compressdev device + * @param stream + * handle of pmd's private stream data + * @return + * - 0 if successful + * - <0 in error cases + * - Returns -EINVAL if input parameters are invalid. + * - Returns -ENOTSUP if comp device does not support STATEFUL operations. + * - Returns -EBUSY if can't free stream as there are inflight operations + */ +typedef int (*compressdev_stream_free_t)(struct rte_compressdev *dev, + void *stream); + +/** + * Create driver private_xform data. + * + * @param dev + * Compressdev device + * @param xform + * xform data + * @param private_xform + * ptr where handle of pmd's private_xform data should be stored + * @return + * - if successful returns 0 + * and valid private_xform handle + * - <0 in error cases + * - Returns -EINVAL if input parameters are invalid. + * - Returns -ENOTSUP if comp device does not support the comp transform. + * - Returns -ENOMEM if the private_xform could not be allocated. + */ +typedef int (*compressdev_private_xform_create_t)(struct rte_compressdev *dev, + const struct rte_comp_xform *xform, void **private_xform); + +/** + * Free driver private_xform data. + * + * @param dev + * Compressdev device + * @param private_xform + * handle of pmd's private_xform data + * @return + * - 0 if successful + * - <0 in error cases + * - Returns -EINVAL if input parameters are invalid. + * - Returns -EBUSY if can't free private_xform due to inflight operations + */ +typedef int (*compressdev_private_xform_free_t)(struct rte_compressdev *dev, + void *private_xform); + +/** comp device operations function pointer table */ +struct rte_compressdev_ops { + compressdev_configure_t dev_configure; /**< Configure device. */ + compressdev_start_t dev_start; /**< Start device. */ + compressdev_stop_t dev_stop; /**< Stop device. */ + compressdev_close_t dev_close; /**< Close device. */ + + compressdev_info_get_t dev_infos_get; /**< Get device info. */ + + compressdev_stats_get_t stats_get; + /**< Get device statistics. */ + compressdev_stats_reset_t stats_reset; + /**< Reset device statistics. */ + + compressdev_queue_pair_setup_t queue_pair_setup; + /**< Set up a device queue pair. */ + compressdev_queue_pair_release_t queue_pair_release; + /**< Release a queue pair. */ + + compressdev_stream_create_t stream_create; + /**< Create a comp stream and initialise its private data. */ + compressdev_stream_free_t stream_free; + /**< Free a comp stream's private data. */ + + compressdev_private_xform_create_t private_xform_create; + /**< Create a comp private_xform and initialise its private data. */ + compressdev_private_xform_free_t private_xform_free; + /**< Free a comp private_xform's data. */ +}; + +/** + * @internal + * + * Function for internal use by dummy drivers primarily, e.g. ring-based + * driver. + * Allocates a new compressdev slot for an comp device and returns the pointer + * to that slot for the driver to use. + * + * @param name + * Unique identifier name for each device + * @param socket_id + * Socket to allocate resources on + * @return + * - Slot in the rte_dev_devices array for a new device; + */ +struct rte_compressdev * __rte_experimental +rte_compressdev_pmd_allocate(const char *name, int socket_id); + +/** + * @internal + * + * Function for internal use by dummy drivers primarily, e.g. ring-based + * driver. + * Release the specified compressdev device. + * + * @param dev + * Compress device + * @return + * - 0 on success, negative on error + */ +int __rte_experimental +rte_compressdev_pmd_release_device(struct rte_compressdev *dev); + + +/** + * @internal + * + * PMD assist function to parse initialisation arguments for comp driver + * when creating a new comp PMD device instance. + * + * PMD driver should set default values for that PMD before calling function, + * these default values will be over-written with successfully parsed values + * from args string. + * + * @param params + * Parsed PMD initialisation parameters + * @param args + * Input argument string to parse + * @return + * - 0 on success + * - errno on failure + */ +int __rte_experimental +rte_compressdev_pmd_parse_input_args( + struct rte_compressdev_pmd_init_params *params, + const char *args); + +/** + * @internal + * + * PMD assist function to provide boiler plate code for comp driver to create + * and allocate resources for a new comp PMD device instance. + * + * @param name + * Compress device name + * @param device + * Base device instance + * @param params + * PMD initialisation parameters + * @return + * - comp device instance on success + * - NULL on creation failure + */ +struct rte_compressdev * __rte_experimental +rte_compressdev_pmd_create(const char *name, + struct rte_device *device, + size_t private_data_size, + struct rte_compressdev_pmd_init_params *params); + +/** + * @internal + * + * PMD assist function to provide boiler plate code for comp driver to + * destroy and free resources associated with a comp PMD device instance. + * + * @param dev + * Compress device + * @return + * - 0 on success + * - errno on failure + */ +int __rte_experimental +rte_compressdev_pmd_destroy(struct rte_compressdev *dev); + +#ifdef __cplusplus +} +#endif + +#endif /* _RTE_COMPRESSDEV_PMD_H_ */ diff --git a/lib/librte_compressdev/rte_compressdev_version.map b/lib/librte_compressdev/rte_compressdev_version.map new file mode 100644 index 00000000..6f900b67 --- /dev/null +++ b/lib/librte_compressdev/rte_compressdev_version.map @@ -0,0 +1,39 @@ +EXPERIMENTAL { + global: + + rte_compressdev_capability_get; + rte_compressdev_close; + rte_compressdev_configure; + rte_compressdev_count; + rte_compressdev_dequeue_burst; + rte_compressdev_devices_get; + rte_compressdev_enqueue_burst; + rte_compressdev_get_dev_id; + rte_compressdev_get_feature_name; + rte_compressdev_info_get; + rte_compressdev_name_get; + rte_compressdev_pmd_allocate; + rte_compressdev_pmd_create; + rte_compressdev_pmd_destroy; + rte_compressdev_pmd_get_named_dev; + rte_compressdev_pmd_parse_input_args; + rte_compressdev_pmd_release_device; + rte_compressdev_private_xform_create; + rte_compressdev_private_xform_free; + rte_compressdev_queue_pair_count; + rte_compressdev_queue_pair_setup; + rte_compressdev_socket_id; + rte_compressdev_start; + rte_compressdev_stats_get; + rte_compressdev_stats_reset; + rte_compressdev_stop; + rte_compressdev_stream_create; + rte_compressdev_stream_free; + rte_comp_get_feature_name; + rte_comp_op_alloc; + rte_comp_op_bulk_alloc; + rte_comp_op_free; + rte_comp_op_pool_create; + + local: *; +}; |