13c32e89fSLee Daly /* SPDX-License-Identifier: BSD-3-Clause 23c32e89fSLee Daly * Copyright(c) 2018 Intel Corporation 33c32e89fSLee Daly */ 4c720cd2bSLee Daly #include <isa-l.h> 53c32e89fSLee Daly 63c32e89fSLee Daly #include <rte_bus_vdev.h> 7490e725bSLee Daly #include <rte_common.h> 8490e725bSLee Daly #include <rte_malloc.h> 9dc49e6aaSLee Daly #include <rte_mbuf.h> 103c32e89fSLee Daly #include <rte_compressdev_pmd.h> 113c32e89fSLee Daly 12490e725bSLee Daly #include "isal_compress_pmd_private.h" 13490e725bSLee Daly 14c720cd2bSLee Daly #define RTE_COMP_ISAL_WINDOW_SIZE 15 15c720cd2bSLee Daly #define RTE_COMP_ISAL_LEVEL_ZERO 0 /* ISA-L Level 0 used for fixed Huffman */ 16c720cd2bSLee Daly #define RTE_COMP_ISAL_LEVEL_ONE 1 17c720cd2bSLee Daly #define RTE_COMP_ISAL_LEVEL_TWO 2 18c720cd2bSLee Daly #define RTE_COMP_ISAL_LEVEL_THREE 3 /* Optimised for AVX512 & AVX2 only */ 19*bd03d3f1SLee Daly #define CHKSUM_SZ_CRC 8 20*bd03d3f1SLee Daly #define CHKSUM_SZ_ADLER 4 21c720cd2bSLee Daly 22490e725bSLee Daly int isal_logtype_driver; 23490e725bSLee Daly 24c720cd2bSLee Daly /* Verify and set private xform parameters */ 25c720cd2bSLee Daly int 26c720cd2bSLee Daly isal_comp_set_priv_xform_parameters(struct isal_priv_xform *priv_xform, 27c720cd2bSLee Daly const struct rte_comp_xform *xform) 28c720cd2bSLee Daly { 29c720cd2bSLee Daly if (xform == NULL) 30c720cd2bSLee Daly return -EINVAL; 31c720cd2bSLee Daly 32c720cd2bSLee Daly /* Set compression private xform variables */ 33c720cd2bSLee Daly if (xform->type == RTE_COMP_COMPRESS) { 34c720cd2bSLee Daly /* Set private xform type - COMPRESS/DECOMPRESS */ 35c720cd2bSLee Daly priv_xform->type = RTE_COMP_COMPRESS; 36c720cd2bSLee Daly 37c720cd2bSLee Daly /* Set private xform algorithm */ 38c720cd2bSLee Daly if (xform->compress.algo != RTE_COMP_ALGO_DEFLATE) { 39c720cd2bSLee Daly if (xform->compress.algo == RTE_COMP_ALGO_NULL) { 40c720cd2bSLee Daly ISAL_PMD_LOG(ERR, "By-pass not supported\n"); 41c720cd2bSLee Daly return -ENOTSUP; 42c720cd2bSLee Daly } 43c720cd2bSLee Daly ISAL_PMD_LOG(ERR, "Algorithm not supported\n"); 44c720cd2bSLee Daly return -ENOTSUP; 45c720cd2bSLee Daly } 46c720cd2bSLee Daly priv_xform->compress.algo = RTE_COMP_ALGO_DEFLATE; 47c720cd2bSLee Daly 48c720cd2bSLee Daly /* Set private xform window size, 32K supported */ 49c720cd2bSLee Daly if (xform->compress.window_size == RTE_COMP_ISAL_WINDOW_SIZE) 50c720cd2bSLee Daly priv_xform->compress.window_size = 51c720cd2bSLee Daly RTE_COMP_ISAL_WINDOW_SIZE; 52c720cd2bSLee Daly else { 53c720cd2bSLee Daly ISAL_PMD_LOG(ERR, "Window size not supported\n"); 54c720cd2bSLee Daly return -ENOTSUP; 55c720cd2bSLee Daly } 56c720cd2bSLee Daly 57c720cd2bSLee Daly /* Set private xform huffman type */ 58c720cd2bSLee Daly switch (xform->compress.deflate.huffman) { 59c720cd2bSLee Daly case(RTE_COMP_HUFFMAN_DEFAULT): 60c720cd2bSLee Daly priv_xform->compress.deflate.huffman = 61c720cd2bSLee Daly RTE_COMP_HUFFMAN_DEFAULT; 62c720cd2bSLee Daly break; 63c720cd2bSLee Daly case(RTE_COMP_HUFFMAN_FIXED): 64c720cd2bSLee Daly priv_xform->compress.deflate.huffman = 65c720cd2bSLee Daly RTE_COMP_HUFFMAN_FIXED; 66c720cd2bSLee Daly break; 67c720cd2bSLee Daly case(RTE_COMP_HUFFMAN_DYNAMIC): 68c720cd2bSLee Daly priv_xform->compress.deflate.huffman = 69c720cd2bSLee Daly RTE_COMP_HUFFMAN_DYNAMIC; 70c720cd2bSLee Daly break; 71c720cd2bSLee Daly default: 72c720cd2bSLee Daly ISAL_PMD_LOG(ERR, "Huffman code not supported\n"); 73c720cd2bSLee Daly return -ENOTSUP; 74c720cd2bSLee Daly } 75c720cd2bSLee Daly 76*bd03d3f1SLee Daly /* Set private xform checksum */ 77*bd03d3f1SLee Daly switch (xform->compress.chksum) { 78*bd03d3f1SLee Daly /* Raw deflate by default */ 79*bd03d3f1SLee Daly case(RTE_COMP_CHECKSUM_NONE): 80*bd03d3f1SLee Daly priv_xform->compress.chksum = IGZIP_DEFLATE; 81*bd03d3f1SLee Daly break; 82*bd03d3f1SLee Daly case(RTE_COMP_CHECKSUM_CRC32): 83*bd03d3f1SLee Daly priv_xform->compress.chksum = IGZIP_GZIP_NO_HDR; 84*bd03d3f1SLee Daly break; 85*bd03d3f1SLee Daly case(RTE_COMP_CHECKSUM_ADLER32): 86*bd03d3f1SLee Daly priv_xform->compress.chksum = IGZIP_ZLIB_NO_HDR; 87*bd03d3f1SLee Daly break; 88*bd03d3f1SLee Daly case(RTE_COMP_CHECKSUM_CRC32_ADLER32): 89*bd03d3f1SLee Daly ISAL_PMD_LOG(ERR, "Combined CRC and ADLER checksum not" 90*bd03d3f1SLee Daly " supported\n"); 91*bd03d3f1SLee Daly return -ENOTSUP; 92*bd03d3f1SLee Daly default: 93*bd03d3f1SLee Daly ISAL_PMD_LOG(ERR, "Checksum type not supported\n"); 94*bd03d3f1SLee Daly priv_xform->compress.chksum = IGZIP_DEFLATE; 95*bd03d3f1SLee Daly break; 96*bd03d3f1SLee Daly } 97*bd03d3f1SLee Daly 98c720cd2bSLee Daly /* Set private xform level. 99c720cd2bSLee Daly * Checking compliance with compressdev API, -1 <= level => 9 100c720cd2bSLee Daly */ 101c720cd2bSLee Daly if (xform->compress.level < RTE_COMP_LEVEL_PMD_DEFAULT || 102c720cd2bSLee Daly xform->compress.level > RTE_COMP_LEVEL_MAX) { 103c720cd2bSLee Daly ISAL_PMD_LOG(ERR, "Compression level out of range\n"); 104c720cd2bSLee Daly return -EINVAL; 105c720cd2bSLee Daly } 106c720cd2bSLee Daly /* Check for Compressdev API level 0, No compression 107c720cd2bSLee Daly * not supported in ISA-L 108c720cd2bSLee Daly */ 109c720cd2bSLee Daly else if (xform->compress.level == RTE_COMP_LEVEL_NONE) { 110c720cd2bSLee Daly ISAL_PMD_LOG(ERR, "No Compression not supported\n"); 111c720cd2bSLee Daly return -ENOTSUP; 112c720cd2bSLee Daly } 113c720cd2bSLee Daly /* If using fixed huffman code, level must be 0 */ 114c720cd2bSLee Daly else if (priv_xform->compress.deflate.huffman == 115c720cd2bSLee Daly RTE_COMP_HUFFMAN_FIXED) { 116c720cd2bSLee Daly ISAL_PMD_LOG(DEBUG, "ISA-L level 0 used due to a" 117c720cd2bSLee Daly " fixed huffman code\n"); 118c720cd2bSLee Daly priv_xform->compress.level = RTE_COMP_ISAL_LEVEL_ZERO; 119c720cd2bSLee Daly priv_xform->level_buffer_size = 120c720cd2bSLee Daly ISAL_DEF_LVL0_DEFAULT; 121c720cd2bSLee Daly } else { 122c720cd2bSLee Daly /* Mapping API levels to ISA-L levels 1,2 & 3 */ 123c720cd2bSLee Daly switch (xform->compress.level) { 124c720cd2bSLee Daly case RTE_COMP_LEVEL_PMD_DEFAULT: 125c720cd2bSLee Daly /* Default is 1 if not using fixed huffman */ 126c720cd2bSLee Daly priv_xform->compress.level = 127c720cd2bSLee Daly RTE_COMP_ISAL_LEVEL_ONE; 128c720cd2bSLee Daly priv_xform->level_buffer_size = 129c720cd2bSLee Daly ISAL_DEF_LVL1_DEFAULT; 130c720cd2bSLee Daly break; 131c720cd2bSLee Daly case RTE_COMP_LEVEL_MIN: 132c720cd2bSLee Daly priv_xform->compress.level = 133c720cd2bSLee Daly RTE_COMP_ISAL_LEVEL_ONE; 134c720cd2bSLee Daly priv_xform->level_buffer_size = 135c720cd2bSLee Daly ISAL_DEF_LVL1_DEFAULT; 136c720cd2bSLee Daly break; 137c720cd2bSLee Daly case RTE_COMP_ISAL_LEVEL_TWO: 138c720cd2bSLee Daly priv_xform->compress.level = 139c720cd2bSLee Daly RTE_COMP_ISAL_LEVEL_TWO; 140c720cd2bSLee Daly priv_xform->level_buffer_size = 141c720cd2bSLee Daly ISAL_DEF_LVL2_DEFAULT; 142c720cd2bSLee Daly break; 143c720cd2bSLee Daly /* Level 3 or higher requested */ 144c720cd2bSLee Daly default: 145c720cd2bSLee Daly /* Check for AVX512, to use ISA-L level 3 */ 146c720cd2bSLee Daly if (rte_cpu_get_flag_enabled( 147c720cd2bSLee Daly RTE_CPUFLAG_AVX512F)) { 148c720cd2bSLee Daly priv_xform->compress.level = 149c720cd2bSLee Daly RTE_COMP_ISAL_LEVEL_THREE; 150c720cd2bSLee Daly priv_xform->level_buffer_size = 151c720cd2bSLee Daly ISAL_DEF_LVL3_DEFAULT; 152c720cd2bSLee Daly } 153c720cd2bSLee Daly /* Check for AVX2, to use ISA-L level 3 */ 154c720cd2bSLee Daly else if (rte_cpu_get_flag_enabled( 155c720cd2bSLee Daly RTE_CPUFLAG_AVX2)) { 156c720cd2bSLee Daly priv_xform->compress.level = 157c720cd2bSLee Daly RTE_COMP_ISAL_LEVEL_THREE; 158c720cd2bSLee Daly priv_xform->level_buffer_size = 159c720cd2bSLee Daly ISAL_DEF_LVL3_DEFAULT; 160c720cd2bSLee Daly } else { 161c720cd2bSLee Daly ISAL_PMD_LOG(DEBUG, "Requested ISA-L level" 162c720cd2bSLee Daly " 3 or above; Level 3 optimized" 163c720cd2bSLee Daly " for AVX512 & AVX2 only." 164c720cd2bSLee Daly " level changed to 2.\n"); 165c720cd2bSLee Daly priv_xform->compress.level = 166c720cd2bSLee Daly RTE_COMP_ISAL_LEVEL_TWO; 167c720cd2bSLee Daly priv_xform->level_buffer_size = 168c720cd2bSLee Daly ISAL_DEF_LVL2_DEFAULT; 169c720cd2bSLee Daly } 170c720cd2bSLee Daly } 171c720cd2bSLee Daly } 172c720cd2bSLee Daly } 173c720cd2bSLee Daly 174c720cd2bSLee Daly /* Set decompression private xform variables */ 175c720cd2bSLee Daly else if (xform->type == RTE_COMP_DECOMPRESS) { 176c720cd2bSLee Daly 177c720cd2bSLee Daly /* Set private xform type - COMPRESS/DECOMPRESS */ 178c720cd2bSLee Daly priv_xform->type = RTE_COMP_DECOMPRESS; 179c720cd2bSLee Daly 180c720cd2bSLee Daly /* Set private xform algorithm */ 181c720cd2bSLee Daly if (xform->decompress.algo != RTE_COMP_ALGO_DEFLATE) { 182c720cd2bSLee Daly if (xform->decompress.algo == RTE_COMP_ALGO_NULL) { 183c720cd2bSLee Daly ISAL_PMD_LOG(ERR, "By pass not supported\n"); 184c720cd2bSLee Daly return -ENOTSUP; 185c720cd2bSLee Daly } 186c720cd2bSLee Daly ISAL_PMD_LOG(ERR, "Algorithm not supported\n"); 187c720cd2bSLee Daly return -ENOTSUP; 188c720cd2bSLee Daly } 189c720cd2bSLee Daly priv_xform->decompress.algo = RTE_COMP_ALGO_DEFLATE; 190c720cd2bSLee Daly 191*bd03d3f1SLee Daly /* Set private xform checksum */ 192*bd03d3f1SLee Daly switch (xform->decompress.chksum) { 193*bd03d3f1SLee Daly /* Raw deflate by default */ 194*bd03d3f1SLee Daly case(RTE_COMP_CHECKSUM_NONE): 195*bd03d3f1SLee Daly priv_xform->decompress.chksum = ISAL_DEFLATE; 196*bd03d3f1SLee Daly break; 197*bd03d3f1SLee Daly case(RTE_COMP_CHECKSUM_CRC32): 198*bd03d3f1SLee Daly priv_xform->decompress.chksum = ISAL_GZIP_NO_HDR_VER; 199*bd03d3f1SLee Daly break; 200*bd03d3f1SLee Daly case(RTE_COMP_CHECKSUM_ADLER32): 201*bd03d3f1SLee Daly priv_xform->decompress.chksum = ISAL_ZLIB_NO_HDR_VER; 202*bd03d3f1SLee Daly break; 203*bd03d3f1SLee Daly case(RTE_COMP_CHECKSUM_CRC32_ADLER32): 204*bd03d3f1SLee Daly ISAL_PMD_LOG(ERR, "Combined CRC and ADLER checksum not" 205*bd03d3f1SLee Daly " supported\n"); 206c720cd2bSLee Daly return -ENOTSUP; 207*bd03d3f1SLee Daly default: 208*bd03d3f1SLee Daly ISAL_PMD_LOG(ERR, "Checksum type not supported\n"); 209*bd03d3f1SLee Daly priv_xform->decompress.chksum = ISAL_DEFLATE; 210*bd03d3f1SLee Daly break; 211c720cd2bSLee Daly } 212c720cd2bSLee Daly 213c720cd2bSLee Daly /* Set private xform window size, 32K supported */ 214c720cd2bSLee Daly if (xform->decompress.window_size == RTE_COMP_ISAL_WINDOW_SIZE) 215c720cd2bSLee Daly priv_xform->decompress.window_size = 216c720cd2bSLee Daly RTE_COMP_ISAL_WINDOW_SIZE; 217c720cd2bSLee Daly else { 218c720cd2bSLee Daly ISAL_PMD_LOG(ERR, "Window size not supported\n"); 219c720cd2bSLee Daly return -ENOTSUP; 220c720cd2bSLee Daly } 221c720cd2bSLee Daly } 222c720cd2bSLee Daly return 0; 223c720cd2bSLee Daly } 224c720cd2bSLee Daly 225788e748dSLee Daly /* Compression using chained mbufs for input/output data */ 226788e748dSLee Daly static int 227788e748dSLee Daly chained_mbuf_compression(struct rte_comp_op *op, struct isal_comp_qp *qp) 228788e748dSLee Daly { 229788e748dSLee Daly int ret; 230788e748dSLee Daly uint32_t remaining_offset; 231788e748dSLee Daly uint32_t remaining_data = op->src.length; 232788e748dSLee Daly struct rte_mbuf *src = op->m_src; 233788e748dSLee Daly struct rte_mbuf *dst = op->m_dst; 234788e748dSLee Daly 235788e748dSLee Daly /* check for source/destination offset passing multiple segments 236788e748dSLee Daly * and point compression stream to input/output buffer. 237788e748dSLee Daly */ 238788e748dSLee Daly remaining_offset = op->src.offset; 239788e748dSLee Daly while (remaining_offset >= src->data_len) { 240788e748dSLee Daly remaining_offset -= src->data_len; 241788e748dSLee Daly src = src->next; 242788e748dSLee Daly } 243788e748dSLee Daly qp->stream->avail_in = RTE_MIN(src->data_len - remaining_offset, 244788e748dSLee Daly op->src.length); 245788e748dSLee Daly qp->stream->next_in = rte_pktmbuf_mtod_offset(src, uint8_t *, 246788e748dSLee Daly remaining_offset); 247788e748dSLee Daly 248788e748dSLee Daly remaining_offset = op->dst.offset; 249788e748dSLee Daly while (remaining_offset >= dst->data_len) { 250788e748dSLee Daly remaining_offset -= dst->data_len; 251788e748dSLee Daly dst = dst->next; 252788e748dSLee Daly } 253788e748dSLee Daly qp->stream->avail_out = dst->data_len - remaining_offset; 254788e748dSLee Daly qp->stream->next_out = rte_pktmbuf_mtod_offset(dst, uint8_t *, 255788e748dSLee Daly remaining_offset); 256788e748dSLee Daly 257788e748dSLee Daly if (unlikely(!qp->stream->next_in || !qp->stream->next_out)) { 258788e748dSLee Daly ISAL_PMD_LOG(ERR, "Invalid source or destination buffer\n"); 259788e748dSLee Daly op->status = RTE_COMP_OP_STATUS_INVALID_ARGS; 260788e748dSLee Daly return -1; 261788e748dSLee Daly } 262788e748dSLee Daly 263788e748dSLee Daly while (qp->stream->internal_state.state != ZSTATE_END) { 264788e748dSLee Daly /* Last segment of data */ 265788e748dSLee Daly if (remaining_data <= src->data_len) 266788e748dSLee Daly qp->stream->end_of_stream = 1; 267788e748dSLee Daly 268788e748dSLee Daly /* Execute compression operation */ 269788e748dSLee Daly ret = isal_deflate(qp->stream); 270788e748dSLee Daly 271788e748dSLee Daly remaining_data = op->src.length - qp->stream->total_in; 272788e748dSLee Daly 273788e748dSLee Daly if (ret != COMP_OK) { 274788e748dSLee Daly ISAL_PMD_LOG(ERR, "Compression operation failed\n"); 275788e748dSLee Daly op->status = RTE_COMP_OP_STATUS_ERROR; 276788e748dSLee Daly return ret; 277788e748dSLee Daly } 278788e748dSLee Daly 279788e748dSLee Daly if (qp->stream->avail_in == 0 && 280788e748dSLee Daly qp->stream->total_in != op->src.length) { 281788e748dSLee Daly if (src->next != NULL) { 282788e748dSLee Daly src = src->next; 283788e748dSLee Daly qp->stream->next_in = 284788e748dSLee Daly rte_pktmbuf_mtod(src, uint8_t *); 285788e748dSLee Daly qp->stream->avail_in = 286788e748dSLee Daly RTE_MIN(remaining_data, src->data_len); 287788e748dSLee Daly } else { 288788e748dSLee Daly ISAL_PMD_LOG(ERR, 289788e748dSLee Daly "Not enough input buffer segments\n"); 290788e748dSLee Daly op->status = RTE_COMP_OP_STATUS_INVALID_ARGS; 291788e748dSLee Daly return -1; 292788e748dSLee Daly } 293788e748dSLee Daly } 294788e748dSLee Daly 295788e748dSLee Daly if (qp->stream->avail_out == 0 && 296788e748dSLee Daly qp->stream->internal_state.state != ZSTATE_END) { 297788e748dSLee Daly if (dst->next != NULL) { 298788e748dSLee Daly dst = dst->next; 299788e748dSLee Daly qp->stream->next_out = 300788e748dSLee Daly rte_pktmbuf_mtod(dst, uint8_t *); 301788e748dSLee Daly qp->stream->avail_out = dst->data_len; 302788e748dSLee Daly } else { 303788e748dSLee Daly ISAL_PMD_LOG(ERR, 304788e748dSLee Daly "Not enough output buffer segments\n"); 305788e748dSLee Daly op->status = 306788e748dSLee Daly RTE_COMP_OP_STATUS_OUT_OF_SPACE_TERMINATED; 307788e748dSLee Daly return -1; 308788e748dSLee Daly } 309788e748dSLee Daly } 310788e748dSLee Daly } 311788e748dSLee Daly 312788e748dSLee Daly return 0; 313788e748dSLee Daly } 314788e748dSLee Daly 315788e748dSLee Daly /* Decompression using chained mbufs for input/output data */ 316788e748dSLee Daly static int 317788e748dSLee Daly chained_mbuf_decompression(struct rte_comp_op *op, struct isal_comp_qp *qp) 318788e748dSLee Daly { 319788e748dSLee Daly int ret; 320788e748dSLee Daly uint32_t consumed_data, src_remaining_offset, dst_remaining_offset; 321788e748dSLee Daly uint32_t remaining_data = op->src.length; 322788e748dSLee Daly struct rte_mbuf *src = op->m_src; 323788e748dSLee Daly struct rte_mbuf *dst = op->m_dst; 324788e748dSLee Daly 325788e748dSLee Daly /* check for offset passing multiple segments 326788e748dSLee Daly * and point decompression state to input/output buffer 327788e748dSLee Daly */ 328788e748dSLee Daly src_remaining_offset = op->src.offset; 329788e748dSLee Daly while (src_remaining_offset >= src->data_len) { 330788e748dSLee Daly src_remaining_offset -= src->data_len; 331788e748dSLee Daly src = src->next; 332788e748dSLee Daly } 333788e748dSLee Daly qp->state->avail_in = RTE_MIN(src->data_len - src_remaining_offset, 334788e748dSLee Daly op->src.length); 335788e748dSLee Daly qp->state->next_in = rte_pktmbuf_mtod_offset(src, uint8_t *, 336788e748dSLee Daly src_remaining_offset); 337788e748dSLee Daly 338788e748dSLee Daly dst_remaining_offset = op->dst.offset; 339788e748dSLee Daly while (dst_remaining_offset >= dst->data_len) { 340788e748dSLee Daly dst_remaining_offset -= dst->data_len; 341788e748dSLee Daly dst = dst->next; 342788e748dSLee Daly } 343788e748dSLee Daly qp->state->avail_out = dst->data_len - dst_remaining_offset; 344788e748dSLee Daly qp->state->next_out = rte_pktmbuf_mtod_offset(dst, uint8_t *, 345788e748dSLee Daly dst_remaining_offset); 346788e748dSLee Daly 347788e748dSLee Daly while (qp->state->block_state != ISAL_BLOCK_FINISH) { 348788e748dSLee Daly 349788e748dSLee Daly ret = isal_inflate(qp->state); 350788e748dSLee Daly 351788e748dSLee Daly if (ret != ISAL_DECOMP_OK) { 352788e748dSLee Daly ISAL_PMD_LOG(ERR, "Decompression operation failed\n"); 353788e748dSLee Daly op->status = RTE_COMP_OP_STATUS_ERROR; 354788e748dSLee Daly return ret; 355788e748dSLee Daly } 356788e748dSLee Daly 3571713ad8bSLee Daly /* Check for first segment, offset needs to be accounted for */ 3581713ad8bSLee Daly if (remaining_data == op->src.length) { 3591713ad8bSLee Daly consumed_data = src->data_len - src_remaining_offset; 3601713ad8bSLee Daly } else 3611713ad8bSLee Daly consumed_data = src->data_len; 3621713ad8bSLee Daly 363788e748dSLee Daly if (qp->state->avail_in == 0 364788e748dSLee Daly && op->consumed != op->src.length) { 3651713ad8bSLee Daly op->consumed += consumed_data; 3661713ad8bSLee Daly remaining_data -= consumed_data; 3671713ad8bSLee Daly 368788e748dSLee Daly if (src->next != NULL) { 369788e748dSLee Daly src = src->next; 370788e748dSLee Daly qp->state->next_in = 371788e748dSLee Daly rte_pktmbuf_mtod(src, uint8_t *); 372788e748dSLee Daly qp->state->avail_in = 373788e748dSLee Daly RTE_MIN(remaining_data, src->data_len); 374788e748dSLee Daly } 375788e748dSLee Daly } 376788e748dSLee Daly 377788e748dSLee Daly if (qp->state->avail_out == 0 && 378788e748dSLee Daly qp->state->block_state != ISAL_BLOCK_FINISH) { 379788e748dSLee Daly if (dst->next != NULL) { 380788e748dSLee Daly dst = dst->next; 381788e748dSLee Daly qp->state->next_out = 382788e748dSLee Daly rte_pktmbuf_mtod(dst, uint8_t *); 383788e748dSLee Daly qp->state->avail_out = dst->data_len; 384788e748dSLee Daly } else { 385788e748dSLee Daly ISAL_PMD_LOG(ERR, 386788e748dSLee Daly "Not enough output buffer segments\n"); 387788e748dSLee Daly op->status = 388788e748dSLee Daly RTE_COMP_OP_STATUS_OUT_OF_SPACE_TERMINATED; 389788e748dSLee Daly return -1; 390788e748dSLee Daly } 391788e748dSLee Daly } 392788e748dSLee Daly } 393788e748dSLee Daly 394788e748dSLee Daly return 0; 395788e748dSLee Daly } 396788e748dSLee Daly 397dc49e6aaSLee Daly /* Stateless Compression Function */ 398dc49e6aaSLee Daly static int 399dc49e6aaSLee Daly process_isal_deflate(struct rte_comp_op *op, struct isal_comp_qp *qp, 400dc49e6aaSLee Daly struct isal_priv_xform *priv_xform) 401dc49e6aaSLee Daly { 402dc49e6aaSLee Daly int ret = 0; 403dc49e6aaSLee Daly op->status = RTE_COMP_OP_STATUS_SUCCESS; 404dc49e6aaSLee Daly 405dc49e6aaSLee Daly /* Required due to init clearing level_buf */ 406dc49e6aaSLee Daly uint8_t *temp_level_buf = qp->stream->level_buf; 407dc49e6aaSLee Daly 408dc49e6aaSLee Daly /* Initialize compression stream */ 409dc49e6aaSLee Daly isal_deflate_stateless_init(qp->stream); 410dc49e6aaSLee Daly 411dc49e6aaSLee Daly qp->stream->level_buf = temp_level_buf; 412dc49e6aaSLee Daly 413*bd03d3f1SLee Daly /* Set Checksum flag */ 414*bd03d3f1SLee Daly qp->stream->gzip_flag = priv_xform->compress.chksum; 415*bd03d3f1SLee Daly 416dc49e6aaSLee Daly /* Stateless operation, input will be consumed in one go */ 417dc49e6aaSLee Daly qp->stream->flush = NO_FLUSH; 418dc49e6aaSLee Daly 419788e748dSLee Daly /* set compression level & intermediate level buffer size */ 420dc49e6aaSLee Daly qp->stream->level = priv_xform->compress.level; 421dc49e6aaSLee Daly qp->stream->level_buf_size = priv_xform->level_buffer_size; 422dc49e6aaSLee Daly 423dc49e6aaSLee Daly /* Set op huffman code */ 424dc49e6aaSLee Daly if (priv_xform->compress.deflate.huffman == RTE_COMP_HUFFMAN_FIXED) 425dc49e6aaSLee Daly isal_deflate_set_hufftables(qp->stream, NULL, 426dc49e6aaSLee Daly IGZIP_HUFFTABLE_STATIC); 427dc49e6aaSLee Daly else if (priv_xform->compress.deflate.huffman == 428dc49e6aaSLee Daly RTE_COMP_HUFFMAN_DEFAULT) 429dc49e6aaSLee Daly isal_deflate_set_hufftables(qp->stream, NULL, 430dc49e6aaSLee Daly IGZIP_HUFFTABLE_DEFAULT); 431dc49e6aaSLee Daly /* Dynamically change the huffman code to suit the input data */ 432dc49e6aaSLee Daly else if (priv_xform->compress.deflate.huffman == 433dc49e6aaSLee Daly RTE_COMP_HUFFMAN_DYNAMIC) 434dc49e6aaSLee Daly isal_deflate_set_hufftables(qp->stream, NULL, 435dc49e6aaSLee Daly IGZIP_HUFFTABLE_DEFAULT); 436dc49e6aaSLee Daly 437788e748dSLee Daly if (op->m_src->pkt_len < (op->src.length + op->src.offset)) { 438788e748dSLee Daly ISAL_PMD_LOG(ERR, "Input mbuf(s) not big enough.\n"); 4396a000343SLee Daly op->status = RTE_COMP_OP_STATUS_INVALID_ARGS; 4406a000343SLee Daly return -1; 4416a000343SLee Daly } 4426a000343SLee Daly 4437f474b43SLee Daly if (op->dst.offset >= op->m_dst->pkt_len) { 4447f474b43SLee Daly ISAL_PMD_LOG(ERR, "Output mbuf(s) not big enough" 4457f474b43SLee Daly " for offset provided.\n"); 4466a000343SLee Daly op->status = RTE_COMP_OP_STATUS_INVALID_ARGS; 4476a000343SLee Daly return -1; 4486a000343SLee Daly } 449788e748dSLee Daly 450788e748dSLee Daly /* Chained mbufs */ 451788e748dSLee Daly if (op->m_src->nb_segs > 1 || op->m_dst->nb_segs > 1) { 452788e748dSLee Daly ret = chained_mbuf_compression(op, qp); 453788e748dSLee Daly if (ret < 0) 454788e748dSLee Daly return ret; 455788e748dSLee Daly } else { 456788e748dSLee Daly /* Linear buffer */ 457788e748dSLee Daly qp->stream->end_of_stream = 1; /* All input consumed in one */ 458788e748dSLee Daly /* Point compression stream to input buffer */ 459788e748dSLee Daly qp->stream->avail_in = op->src.length; 460788e748dSLee Daly qp->stream->next_in = rte_pktmbuf_mtod_offset(op->m_src, 461788e748dSLee Daly uint8_t *, op->src.offset); 462788e748dSLee Daly 4636a000343SLee Daly /* Point compression stream to output buffer */ 4646a000343SLee Daly qp->stream->avail_out = op->m_dst->data_len - op->dst.offset; 465788e748dSLee Daly qp->stream->next_out = rte_pktmbuf_mtod_offset(op->m_dst, 466788e748dSLee Daly uint8_t *, op->dst.offset); 4676a000343SLee Daly 4686a000343SLee Daly if (unlikely(!qp->stream->next_in || !qp->stream->next_out)) { 469788e748dSLee Daly ISAL_PMD_LOG(ERR, "Invalid source or destination" 470788e748dSLee Daly " buffers\n"); 4716a000343SLee Daly op->status = RTE_COMP_OP_STATUS_INVALID_ARGS; 4726a000343SLee Daly return -1; 4736a000343SLee Daly } 4746a000343SLee Daly 475dc49e6aaSLee Daly /* Execute compression operation */ 476dc49e6aaSLee Daly ret = isal_deflate_stateless(qp->stream); 477dc49e6aaSLee Daly 478dc49e6aaSLee Daly /* Check that output buffer did not run out of space */ 479dc49e6aaSLee Daly if (ret == STATELESS_OVERFLOW) { 480dc49e6aaSLee Daly ISAL_PMD_LOG(ERR, "Output buffer not big enough\n"); 481dc49e6aaSLee Daly op->status = RTE_COMP_OP_STATUS_OUT_OF_SPACE_TERMINATED; 482dc49e6aaSLee Daly return ret; 483dc49e6aaSLee Daly } 484dc49e6aaSLee Daly 485dc49e6aaSLee Daly /* Check that input buffer has been fully consumed */ 486dc49e6aaSLee Daly if (qp->stream->avail_in != (uint32_t)0) { 487788e748dSLee Daly ISAL_PMD_LOG(ERR, "Input buffer could not be read" 488788e748dSLee Daly " entirely\n"); 489dc49e6aaSLee Daly op->status = RTE_COMP_OP_STATUS_ERROR; 490dc49e6aaSLee Daly return -1; 491dc49e6aaSLee Daly } 492dc49e6aaSLee Daly 493dc49e6aaSLee Daly if (ret != COMP_OK) { 494788e748dSLee Daly ISAL_PMD_LOG(ERR, "Compression operation failed\n"); 495dc49e6aaSLee Daly op->status = RTE_COMP_OP_STATUS_ERROR; 496dc49e6aaSLee Daly return ret; 497dc49e6aaSLee Daly } 498788e748dSLee Daly } 499*bd03d3f1SLee Daly 500dc49e6aaSLee Daly op->consumed = qp->stream->total_in; 501*bd03d3f1SLee Daly if (qp->stream->gzip_flag == IGZIP_DEFLATE) { 502dc49e6aaSLee Daly op->produced = qp->stream->total_out; 503*bd03d3f1SLee Daly } else if (qp->stream->gzip_flag == IGZIP_ZLIB_NO_HDR) { 504*bd03d3f1SLee Daly op->produced = qp->stream->total_out - CHKSUM_SZ_ADLER; 505*bd03d3f1SLee Daly op->output_chksum = qp->stream->internal_state.crc + 1; 506*bd03d3f1SLee Daly } else { 507*bd03d3f1SLee Daly op->produced = qp->stream->total_out - CHKSUM_SZ_CRC; 508*bd03d3f1SLee Daly op->output_chksum = qp->stream->internal_state.crc; 509*bd03d3f1SLee Daly } 510*bd03d3f1SLee Daly 5111713ad8bSLee Daly isal_deflate_reset(qp->stream); 512dc49e6aaSLee Daly 513dc49e6aaSLee Daly return ret; 514dc49e6aaSLee Daly } 515dc49e6aaSLee Daly 5167bf4f063SLee Daly /* Stateless Decompression Function */ 5177bf4f063SLee Daly static int 518*bd03d3f1SLee Daly process_isal_inflate(struct rte_comp_op *op, struct isal_comp_qp *qp, 519*bd03d3f1SLee Daly struct isal_priv_xform *priv_xform) 5207bf4f063SLee Daly { 5217bf4f063SLee Daly int ret = 0; 5227bf4f063SLee Daly 5237bf4f063SLee Daly op->status = RTE_COMP_OP_STATUS_SUCCESS; 5247bf4f063SLee Daly 5257bf4f063SLee Daly /* Initialize decompression state */ 5267bf4f063SLee Daly isal_inflate_init(qp->state); 5277bf4f063SLee Daly 528*bd03d3f1SLee Daly /* Set Checksum flag */ 529*bd03d3f1SLee Daly qp->state->crc_flag = priv_xform->decompress.chksum; 530*bd03d3f1SLee Daly 531788e748dSLee Daly if (op->m_src->pkt_len < (op->src.length + op->src.offset)) { 532788e748dSLee Daly ISAL_PMD_LOG(ERR, "Input mbuf(s) not big enough.\n"); 533788e748dSLee Daly op->status = RTE_COMP_OP_STATUS_INVALID_ARGS; 534788e748dSLee Daly return -1; 535788e748dSLee Daly } 536788e748dSLee Daly 5377f474b43SLee Daly if (op->dst.offset >= op->m_dst->pkt_len) { 5387f474b43SLee Daly ISAL_PMD_LOG(ERR, "Output mbuf not big enough for " 5396a000343SLee Daly "offset provided.\n"); 5406a000343SLee Daly op->status = RTE_COMP_OP_STATUS_INVALID_ARGS; 5416a000343SLee Daly return -1; 5426a000343SLee Daly } 543788e748dSLee Daly 544788e748dSLee Daly /* Chained mbufs */ 545788e748dSLee Daly if (op->m_src->nb_segs > 1 || op->m_dst->nb_segs > 1) { 546788e748dSLee Daly ret = chained_mbuf_decompression(op, qp); 547788e748dSLee Daly if (ret != 0) 548788e748dSLee Daly return ret; 549788e748dSLee Daly } else { 550788e748dSLee Daly /* Linear buffer */ 5516a000343SLee Daly /* Point decompression state to input buffer */ 5527bf4f063SLee Daly qp->state->avail_in = op->src.length; 553788e748dSLee Daly qp->state->next_in = rte_pktmbuf_mtod_offset(op->m_src, 554788e748dSLee Daly uint8_t *, op->src.offset); 5556a000343SLee Daly 5566a000343SLee Daly /* Point decompression state to output buffer */ 5576a000343SLee Daly qp->state->avail_out = op->m_dst->data_len - op->dst.offset; 558788e748dSLee Daly qp->state->next_out = rte_pktmbuf_mtod_offset(op->m_dst, 559788e748dSLee Daly uint8_t *, op->dst.offset); 5607bf4f063SLee Daly 5617bf4f063SLee Daly if (unlikely(!qp->state->next_in || !qp->state->next_out)) { 562788e748dSLee Daly ISAL_PMD_LOG(ERR, "Invalid source or destination" 563788e748dSLee Daly " buffers\n"); 5647bf4f063SLee Daly op->status = RTE_COMP_OP_STATUS_INVALID_ARGS; 5657bf4f063SLee Daly return -1; 5667bf4f063SLee Daly } 5677bf4f063SLee Daly 5687bf4f063SLee Daly /* Execute decompression operation */ 5697bf4f063SLee Daly ret = isal_inflate_stateless(qp->state); 5707bf4f063SLee Daly 5717bf4f063SLee Daly if (ret == ISAL_OUT_OVERFLOW) { 5727bf4f063SLee Daly ISAL_PMD_LOG(ERR, "Output buffer not big enough\n"); 5737bf4f063SLee Daly op->status = RTE_COMP_OP_STATUS_OUT_OF_SPACE_TERMINATED; 5747bf4f063SLee Daly return ret; 5757bf4f063SLee Daly } 5767bf4f063SLee Daly 5777bf4f063SLee Daly /* Check that input buffer has been fully consumed */ 5787bf4f063SLee Daly if (qp->state->avail_in != (uint32_t)0) { 579788e748dSLee Daly ISAL_PMD_LOG(ERR, "Input buffer could not be read" 580788e748dSLee Daly " entirely\n"); 5817bf4f063SLee Daly op->status = RTE_COMP_OP_STATUS_ERROR; 5827bf4f063SLee Daly return -1; 5837bf4f063SLee Daly } 5847bf4f063SLee Daly 585*bd03d3f1SLee Daly if (ret != ISAL_DECOMP_OK && ret != ISAL_END_INPUT) { 586*bd03d3f1SLee Daly ISAL_PMD_LOG(ERR, "Decompression operation failed\n"); 5877bf4f063SLee Daly op->status = RTE_COMP_OP_STATUS_ERROR; 5887bf4f063SLee Daly return ret; 5897bf4f063SLee Daly } 5907bf4f063SLee Daly op->consumed = op->src.length - qp->state->avail_in; 591788e748dSLee Daly } 5927bf4f063SLee Daly op->produced = qp->state->total_out; 593*bd03d3f1SLee Daly op->output_chksum = qp->state->crc; 594*bd03d3f1SLee Daly 5951713ad8bSLee Daly isal_inflate_reset(qp->state); 5967bf4f063SLee Daly 5977bf4f063SLee Daly return ret; 5987bf4f063SLee Daly } 5997bf4f063SLee Daly 60021fd1e59SLee Daly /* Process compression/decompression operation */ 60121fd1e59SLee Daly static int 602dc49e6aaSLee Daly process_op(struct isal_comp_qp *qp, struct rte_comp_op *op, 60321fd1e59SLee Daly struct isal_priv_xform *priv_xform) 60421fd1e59SLee Daly { 60521fd1e59SLee Daly switch (priv_xform->type) { 60621fd1e59SLee Daly case RTE_COMP_COMPRESS: 607dc49e6aaSLee Daly process_isal_deflate(op, qp, priv_xform); 60821fd1e59SLee Daly break; 60921fd1e59SLee Daly case RTE_COMP_DECOMPRESS: 610*bd03d3f1SLee Daly process_isal_inflate(op, qp, priv_xform); 61121fd1e59SLee Daly break; 61221fd1e59SLee Daly default: 61321fd1e59SLee Daly ISAL_PMD_LOG(ERR, "Operation Not Supported\n"); 61421fd1e59SLee Daly return -ENOTSUP; 61521fd1e59SLee Daly } 61621fd1e59SLee Daly return 0; 61721fd1e59SLee Daly } 61821fd1e59SLee Daly 61921fd1e59SLee Daly /* Enqueue burst */ 62021fd1e59SLee Daly static uint16_t 62121fd1e59SLee Daly isal_comp_pmd_enqueue_burst(void *queue_pair, struct rte_comp_op **ops, 62221fd1e59SLee Daly uint16_t nb_ops) 62321fd1e59SLee Daly { 62421fd1e59SLee Daly struct isal_comp_qp *qp = queue_pair; 62521fd1e59SLee Daly uint16_t i; 62621fd1e59SLee Daly int retval; 62721fd1e59SLee Daly int16_t num_enq = RTE_MIN(qp->num_free_elements, nb_ops); 62821fd1e59SLee Daly 62921fd1e59SLee Daly for (i = 0; i < num_enq; i++) { 63021fd1e59SLee Daly if (unlikely(ops[i]->op_type != RTE_COMP_OP_STATELESS)) { 63121fd1e59SLee Daly ops[i]->status = RTE_COMP_OP_STATUS_INVALID_ARGS; 63221fd1e59SLee Daly ISAL_PMD_LOG(ERR, "Stateful operation not Supported\n"); 63321fd1e59SLee Daly qp->qp_stats.enqueue_err_count++; 63421fd1e59SLee Daly continue; 63521fd1e59SLee Daly } 63621fd1e59SLee Daly retval = process_op(qp, ops[i], ops[i]->private_xform); 63721fd1e59SLee Daly if (unlikely(retval < 0) || 63821fd1e59SLee Daly ops[i]->status != RTE_COMP_OP_STATUS_SUCCESS) { 63921fd1e59SLee Daly qp->qp_stats.enqueue_err_count++; 64021fd1e59SLee Daly } 64121fd1e59SLee Daly } 64221fd1e59SLee Daly 64321fd1e59SLee Daly retval = rte_ring_enqueue_burst(qp->processed_pkts, (void *)ops, 64421fd1e59SLee Daly num_enq, NULL); 64521fd1e59SLee Daly qp->num_free_elements -= retval; 64621fd1e59SLee Daly qp->qp_stats.enqueued_count += retval; 64721fd1e59SLee Daly 64821fd1e59SLee Daly return retval; 64921fd1e59SLee Daly } 65021fd1e59SLee Daly 65121fd1e59SLee Daly /* Dequeue burst */ 65221fd1e59SLee Daly static uint16_t 65321fd1e59SLee Daly isal_comp_pmd_dequeue_burst(void *queue_pair, struct rte_comp_op **ops, 65421fd1e59SLee Daly uint16_t nb_ops) 65521fd1e59SLee Daly { 65621fd1e59SLee Daly struct isal_comp_qp *qp = queue_pair; 65721fd1e59SLee Daly uint16_t nb_dequeued; 65821fd1e59SLee Daly 65921fd1e59SLee Daly nb_dequeued = rte_ring_dequeue_burst(qp->processed_pkts, (void **)ops, 66021fd1e59SLee Daly nb_ops, NULL); 66121fd1e59SLee Daly qp->num_free_elements += nb_dequeued; 66221fd1e59SLee Daly qp->qp_stats.dequeued_count += nb_dequeued; 66321fd1e59SLee Daly 66421fd1e59SLee Daly return nb_dequeued; 66521fd1e59SLee Daly } 66621fd1e59SLee Daly 667490e725bSLee Daly /* Create ISA-L compression device */ 668490e725bSLee Daly static int 669490e725bSLee Daly compdev_isal_create(const char *name, struct rte_vdev_device *vdev, 670490e725bSLee Daly struct rte_compressdev_pmd_init_params *init_params) 671490e725bSLee Daly { 672490e725bSLee Daly struct rte_compressdev *dev; 673490e725bSLee Daly 674490e725bSLee Daly dev = rte_compressdev_pmd_create(name, &vdev->device, 675490e725bSLee Daly sizeof(struct isal_comp_private), init_params); 676490e725bSLee Daly if (dev == NULL) { 677490e725bSLee Daly ISAL_PMD_LOG(ERR, "failed to create compressdev vdev"); 678490e725bSLee Daly return -EFAULT; 679490e725bSLee Daly } 680490e725bSLee Daly 681490e725bSLee Daly dev->dev_ops = isal_compress_pmd_ops; 682490e725bSLee Daly 68321fd1e59SLee Daly /* register rx/tx burst functions for data path */ 68421fd1e59SLee Daly dev->dequeue_burst = isal_comp_pmd_dequeue_burst; 68521fd1e59SLee Daly dev->enqueue_burst = isal_comp_pmd_enqueue_burst; 68621fd1e59SLee Daly 687490e725bSLee Daly return 0; 688490e725bSLee Daly } 689490e725bSLee Daly 6903c32e89fSLee Daly /** Remove compression device */ 6913c32e89fSLee Daly static int 692490e725bSLee Daly compdev_isal_remove_dev(struct rte_vdev_device *vdev) 6933c32e89fSLee Daly { 694490e725bSLee Daly struct rte_compressdev *compdev; 695490e725bSLee Daly const char *name; 696490e725bSLee Daly 697490e725bSLee Daly name = rte_vdev_device_name(vdev); 698490e725bSLee Daly if (name == NULL) 699490e725bSLee Daly return -EINVAL; 700490e725bSLee Daly 701490e725bSLee Daly compdev = rte_compressdev_pmd_get_named_dev(name); 702490e725bSLee Daly if (compdev == NULL) 703490e725bSLee Daly return -ENODEV; 704490e725bSLee Daly 705490e725bSLee Daly return rte_compressdev_pmd_destroy(compdev); 7063c32e89fSLee Daly } 7073c32e89fSLee Daly 7083c32e89fSLee Daly /** Initialise ISA-L compression device */ 7093c32e89fSLee Daly static int 710490e725bSLee Daly compdev_isal_probe(struct rte_vdev_device *dev) 7113c32e89fSLee Daly { 712490e725bSLee Daly struct rte_compressdev_pmd_init_params init_params = { 713490e725bSLee Daly "", 714490e725bSLee Daly rte_socket_id(), 715490e725bSLee Daly }; 716490e725bSLee Daly const char *name, *args; 717490e725bSLee Daly int retval; 718490e725bSLee Daly 719490e725bSLee Daly name = rte_vdev_device_name(dev); 720490e725bSLee Daly if (name == NULL) 721490e725bSLee Daly return -EINVAL; 722490e725bSLee Daly 723490e725bSLee Daly args = rte_vdev_device_args(dev); 724490e725bSLee Daly 725490e725bSLee Daly retval = rte_compressdev_pmd_parse_input_args(&init_params, args); 726490e725bSLee Daly if (retval) { 727490e725bSLee Daly ISAL_PMD_LOG(ERR, 728490e725bSLee Daly "Failed to parse initialisation arguments[%s]\n", args); 729490e725bSLee Daly return -EINVAL; 730490e725bSLee Daly } 731490e725bSLee Daly 732490e725bSLee Daly return compdev_isal_create(name, dev, &init_params); 7333c32e89fSLee Daly } 7343c32e89fSLee Daly 7353c32e89fSLee Daly static struct rte_vdev_driver compdev_isal_pmd_drv = { 7363c32e89fSLee Daly .probe = compdev_isal_probe, 7373c32e89fSLee Daly .remove = compdev_isal_remove_dev, 7383c32e89fSLee Daly }; 7393c32e89fSLee Daly 7403c32e89fSLee Daly RTE_PMD_REGISTER_VDEV(COMPDEV_NAME_ISAL_PMD, compdev_isal_pmd_drv); 7413c32e89fSLee Daly RTE_PMD_REGISTER_PARAM_STRING(COMPDEV_NAME_ISAL_PMD, 7423c32e89fSLee Daly "socket_id=<int>"); 743490e725bSLee Daly 744f8e99896SThomas Monjalon RTE_INIT(isal_init_log) 745490e725bSLee Daly { 74623edc362SPablo de Lara isal_logtype_driver = rte_log_register("pmd.compress.isal"); 747490e725bSLee Daly if (isal_logtype_driver >= 0) 748490e725bSLee Daly rte_log_set_level(isal_logtype_driver, RTE_LOG_INFO); 749490e725bSLee Daly } 750