Implement enqueue and dequeue burst operations for stateful request
support.

Signed-off-by: Nagadheeraj Rottela <rnagadhee...@marvell.com>
---
 drivers/compress/nitrox/nitrox_comp.c        |  98 +++-
 drivers/compress/nitrox/nitrox_comp.h        |   1 +
 drivers/compress/nitrox/nitrox_comp_reqmgr.c | 555 ++++++++++++++++---
 drivers/compress/nitrox/nitrox_comp_reqmgr.h |   8 +
 4 files changed, 581 insertions(+), 81 deletions(-)

diff --git a/drivers/compress/nitrox/nitrox_comp.c 
b/drivers/compress/nitrox/nitrox_comp.c
index 1fd1b12a18..97d2c4a0e8 100644
--- a/drivers/compress/nitrox/nitrox_comp.c
+++ b/drivers/compress/nitrox/nitrox_comp.c
@@ -32,7 +32,9 @@ static const struct rte_compressdev_capabilities
                                      RTE_COMP_FF_SHAREABLE_PRIV_XFORM |
                                      RTE_COMP_FF_OOP_SGL_IN_SGL_OUT |
                                      RTE_COMP_FF_OOP_SGL_IN_LB_OUT |
-                                     RTE_COMP_FF_OOP_LB_IN_SGL_OUT,
+                                     RTE_COMP_FF_OOP_LB_IN_SGL_OUT |
+                                     RTE_COMP_FF_STATEFUL_COMPRESSION |
+                                     RTE_COMP_FF_STATEFUL_DECOMPRESSION,
                .window_size = {
                        .min = NITROX_COMP_WINDOW_SIZE_MIN,
                        .max = NITROX_COMP_WINDOW_SIZE_MAX,
@@ -334,6 +336,13 @@ static int nitrox_comp_private_xform_create(struct 
rte_compressdev *dev,
                goto err_exit;
        }
 
+       nxform->context = NULL;
+       nxform->history_window = NULL;
+       nxform->window_size = 0;
+       nxform->hlen = 0;
+       nxform->exn = 0;
+       nxform->exbits = 0;
+       nxform->bf = true;
        return 0;
 err_exit:
        memset(nxform, 0, sizeof(*nxform));
@@ -357,6 +366,74 @@ static int nitrox_comp_private_xform_free(struct 
rte_compressdev *dev,
        return 0;
 }
 
+static int nitrox_comp_stream_free(struct rte_compressdev *dev, void *stream)
+{
+       struct nitrox_comp_xform *nxform = stream;
+
+       if (unlikely(nxform == NULL))
+               return -EINVAL;
+
+       rte_free(nxform->history_window);
+       nxform->history_window = NULL;
+       rte_free(nxform->context);
+       nxform->context = NULL;
+       return nitrox_comp_private_xform_free(dev, stream);
+}
+
+static int nitrox_comp_stream_create(struct rte_compressdev *dev,
+                       const struct rte_comp_xform *xform, void **stream)
+{
+       int err;
+       struct nitrox_comp_xform *nxform;
+       struct nitrox_comp_device *comp_dev = dev->data->dev_private;
+
+       err = nitrox_comp_private_xform_create(dev, xform, stream);
+       if (unlikely(err))
+               return err;
+
+       nxform = *stream;
+       if (xform->type == RTE_COMP_COMPRESS) {
+               uint8_t window_size = xform->compress.window_size;
+
+               if (unlikely(window_size < NITROX_COMP_WINDOW_SIZE_MIN ||
+                             window_size > NITROX_COMP_WINDOW_SIZE_MAX)) {
+                       NITROX_LOG(ERR, "Invalid window size %d\n",
+                                  window_size);
+                       return -EINVAL;
+               }
+
+               if (window_size == NITROX_COMP_WINDOW_SIZE_MAX)
+                       nxform->window_size = NITROX_CONSTANTS_MAX_SEARCH_DEPTH;
+               else
+                       nxform->window_size = RTE_BIT32(window_size);
+       } else {
+               nxform->window_size = NITROX_DEFAULT_DEFLATE_SEARCH_DEPTH;
+       }
+
+       nxform->history_window = rte_zmalloc_socket(NULL, nxform->window_size,
+                                       8, comp_dev->xform_pool->socket_id);
+       if (unlikely(nxform->history_window == NULL)) {
+               err = -ENOMEM;
+               goto err_exit;
+       }
+
+       if (xform->type == RTE_COMP_COMPRESS)
+               return 0;
+
+       nxform->context = rte_zmalloc_socket(NULL,
+                                       NITROX_DECOMP_CTX_SIZE, 8,
+                                       comp_dev->xform_pool->socket_id);
+       if (unlikely(nxform->context == NULL)) {
+               err = -ENOMEM;
+               goto err_exit;
+       }
+
+       return 0;
+err_exit:
+       nitrox_comp_stream_free(dev, *stream);
+       return err;
+}
+
 static int nitrox_enq_single_op(struct nitrox_qp *qp, struct rte_comp_op *op)
 {
        struct nitrox_softreq *sr;
@@ -371,8 +448,12 @@ static int nitrox_enq_single_op(struct nitrox_qp *qp, 
struct rte_comp_op *op)
                return err;
        }
 
-       nitrox_qp_enqueue(qp, nitrox_comp_instr_addr(sr), sr);
-       return 0;
+       if (op->status == RTE_COMP_OP_STATUS_SUCCESS)
+               err = nitrox_qp_enqueue_sr(qp, sr);
+       else
+               nitrox_qp_enqueue(qp, nitrox_comp_instr_addr(sr), sr);
+
+       return err;
 }
 
 static uint16_t nitrox_comp_dev_enq_burst(void *queue_pair,
@@ -382,6 +463,7 @@ static uint16_t nitrox_comp_dev_enq_burst(void *queue_pair,
        struct nitrox_qp *qp = queue_pair;
        uint16_t free_slots = 0;
        uint16_t cnt = 0;
+       uint16_t dbcnt = 0;
        bool err = false;
 
        free_slots = nitrox_qp_free_count(qp);
@@ -393,9 +475,12 @@ static uint16_t nitrox_comp_dev_enq_burst(void *queue_pair,
                        err = true;
                        break;
                }
+
+               if (ops[cnt]->status != RTE_COMP_OP_STATUS_SUCCESS)
+                       dbcnt++;
        }
 
-       nitrox_ring_dbell(qp, cnt);
+       nitrox_ring_dbell(qp, dbcnt);
        qp->stats.enqueued_count += cnt;
        if (unlikely(err))
                qp->stats.enqueue_err_count++;
@@ -458,8 +543,8 @@ static struct rte_compressdev_ops nitrox_compressdev_ops = {
 
                .private_xform_create   = nitrox_comp_private_xform_create,
                .private_xform_free     = nitrox_comp_private_xform_free,
-               .stream_create          = NULL,
-               .stream_free            = NULL
+               .stream_create          = nitrox_comp_stream_create,
+               .stream_free            = nitrox_comp_stream_free,
 };
 
 int
@@ -517,4 +602,3 @@ nitrox_comp_pmd_destroy(struct nitrox_device *ndev)
        ndev->comp_dev = NULL;
        return 0;
 }
-
diff --git a/drivers/compress/nitrox/nitrox_comp.h 
b/drivers/compress/nitrox/nitrox_comp.h
index e49debaf6b..83e5902076 100644
--- a/drivers/compress/nitrox/nitrox_comp.h
+++ b/drivers/compress/nitrox/nitrox_comp.h
@@ -8,6 +8,7 @@
 #define COMPRESSDEV_NAME_NITROX_PMD    compress_nitrox
 #define NITROX_DECOMP_CTX_SIZE 2048
 #define NITROX_CONSTANTS_MAX_SEARCH_DEPTH 31744
+#define NITROX_DEFAULT_DEFLATE_SEARCH_DEPTH 32768
 #define NITROX_COMP_WINDOW_SIZE_MIN 1
 #define NITROX_COMP_WINDOW_SIZE_MAX 15
 #define NITROX_COMP_LEVEL_LOWEST_START 1
diff --git a/drivers/compress/nitrox/nitrox_comp_reqmgr.c 
b/drivers/compress/nitrox/nitrox_comp_reqmgr.c
index 5ad1a4439a..a3a6588132 100644
--- a/drivers/compress/nitrox/nitrox_comp_reqmgr.c
+++ b/drivers/compress/nitrox/nitrox_comp_reqmgr.c
@@ -5,11 +5,13 @@
 #include <rte_compressdev_pmd.h>
 #include <rte_errno.h>
 #include <rte_malloc.h>
+#include <rte_hexdump.h>
 
 #include "nitrox_comp_reqmgr.h"
 #include "nitrox_logs.h"
 #include "rte_comp.h"
 
+#define NITROX_INSTR_BUFFER_DEBUG 0
 #define NITROX_ZIP_SGL_COUNT 16
 #define NITROX_ZIP_MAX_ZPTRS 2048
 #define NITROX_ZIP_MAX_DATASIZE ((1 << 24) - 1)
@@ -307,10 +309,222 @@ struct nitrox_softreq {
        struct rte_comp_op *op;
        struct nitrox_sgtable src;
        struct nitrox_sgtable dst;
-       struct nitrox_comp_xform xform;
        uint64_t timeout;
 };
 
+#if NITROX_INSTR_BUFFER_DEBUG
+static void nitrox_dump_databuf(const char *name, struct rte_mbuf *m,
+                               uint32_t off, uint32_t datalen)
+{
+       uint32_t mlen;
+
+       if (!rte_log_can_log(nitrox_logtype, RTE_LOG_DEBUG))
+               return;
+
+       for (; m && off > rte_pktmbuf_data_len(m); m = m->next)
+               off -= rte_pktmbuf_data_len(m);
+
+       mlen = rte_pktmbuf_data_len(m) - off;
+       if (datalen <= mlen)
+               mlen = datalen;
+
+       rte_hexdump(stderr, name, rte_pktmbuf_mtod_offset(m, char *, off),
+                   mlen);
+       for (m = m->next; m && datalen; m = m->next) {
+               mlen = rte_pktmbuf_data_len(m) < datalen ?
+                       rte_pktmbuf_data_len(m) : datalen;
+               rte_hexdump(stderr, name, rte_pktmbuf_mtod(m, char *), mlen);
+       }
+
+       fprintf(stderr, "\n");
+}
+
+static void nitrox_dump_zip_instr(struct nitrox_zip_instr *instr,
+                                 union nitrox_zip_zptr *hptr_arr,
+                                 union nitrox_zip_zptr *iptr_arr,
+                                 union nitrox_zip_zptr *optr_arr)
+{
+       uint64_t value;
+       int i = 0;
+
+       if (!rte_log_can_log(nitrox_logtype, RTE_LOG_DEBUG))
+               return;
+
+       fprintf(stderr, "\nZIP instruction..(%p)\n", instr);
+       fprintf(stderr, "\tWORD0 = 0x%016"PRIx64"\n", instr->w0.u64);
+       fprintf(stderr, "\t\tTOL        = %d\n", instr->w0.tol);
+       fprintf(stderr, "\t\tEXNUM      = %d\n", instr->w0.exn);
+       fprintf(stderr, "\t\tEXBITS     = %x\n", instr->w0.exbits);
+       fprintf(stderr, "\t\tCA         = %d\n", instr->w0.ca);
+       fprintf(stderr, "\t\tSF         = %d\n", instr->w0.sf);
+       fprintf(stderr, "\t\tSS         = %d\n", instr->w0.ss);
+       fprintf(stderr, "\t\tCC         = %d\n", instr->w0.cc);
+       fprintf(stderr, "\t\tEF         = %d\n", instr->w0.ef);
+       fprintf(stderr, "\t\tBF         = %d\n", instr->w0.bf);
+       fprintf(stderr, "\t\tCO         = %d\n", instr->w0.co);
+       fprintf(stderr, "\t\tDS         = %d\n", instr->w0.ds);
+       fprintf(stderr, "\t\tDG         = %d\n", instr->w0.dg);
+       fprintf(stderr, "\t\tHG         = %d\n", instr->w0.hg);
+       fprintf(stderr, "\n");
+
+       fprintf(stderr, "\tWORD1 = 0x%016"PRIx64"\n", instr->w1.u64);
+       fprintf(stderr, "\t\tHL         = %d\n", instr->w1.hl);
+       fprintf(stderr, "\t\tADLERCRC32 = 0x%08x\n", instr->w1.adlercrc32);
+       fprintf(stderr, "\n");
+
+       value = instr->w2.cptr;
+       fprintf(stderr, "\tWORD2 = 0x%016"PRIx64"\n", instr->w2.u64);
+       fprintf(stderr, "\t\tCPTR = 0x%11"PRIx64"\n", value);
+       fprintf(stderr, "\n");
+
+       value = instr->w3.hptr;
+       fprintf(stderr, "\tWORD3 = 0x%016"PRIx64"\n", instr->w3.u64);
+       fprintf(stderr, "\t\tHLEN       = %d\n", instr->w3.hlen);
+       fprintf(stderr, "\t\tHPTR = 0x%11"PRIx64"\n", value);
+
+       if (instr->w0.hg && hptr_arr) {
+               for (i = 0; i < instr->w3.hlen; i++) {
+                       value = hptr_arr[i].s.addr;
+                       fprintf(stderr, "\t\t\tZPTR[%d] : Length = %d Addr = 
0x%11"PRIx64"\n",
+                                    i, hptr_arr[i].s.length, value);
+               }
+       }
+
+       fprintf(stderr, "\n");
+
+       value = instr->w4.iptr;
+       fprintf(stderr, "\tWORD4 = 0x%016"PRIx64"\n", instr->w4.u64);
+       fprintf(stderr, "\t\tILEN       = %d\n", instr->w4.ilen);
+       fprintf(stderr, "\t\tIPTR       = 0x%11"PRIx64"\n", value);
+       if (instr->w0.dg && iptr_arr) {
+               for (i = 0; i < instr->w4.ilen; i++) {
+                       value = iptr_arr[i].s.addr;
+                       fprintf(stderr, "\t\t\tZPTR[%d] : Length = %d Addr = 
0x%11"PRIx64"\n",
+                                    i, iptr_arr[i].s.length, value);
+               }
+       }
+
+       fprintf(stderr, "\n");
+
+       value = instr->w5.optr;
+       fprintf(stderr, "\tWORD5 = 0x%016"PRIx64"\n", instr->w5.u64);
+       fprintf(stderr, "\t\t OLEN = %d\n", instr->w5.olen);
+       fprintf(stderr, "\t\t OPTR = 0x%11"PRIx64"\n", value);
+       if (instr->w0.ds && optr_arr) {
+               for (i = 0; i < instr->w5.olen; i++) {
+                       value = optr_arr[i].s.addr;
+                       fprintf(stderr, "\t\t\tZPTR[%d] : Length = %d Addr = 
0x%11"PRIx64"\n",
+                                    i, optr_arr[i].s.length, value);
+               }
+       }
+
+       fprintf(stderr, "\n");
+
+       value = instr->w6.rptr;
+       fprintf(stderr, "\tWORD6 = 0x%016"PRIx64"\n", instr->w6.u64);
+       fprintf(stderr, "\t\tRPTR = 0x%11"PRIx64"\n", value);
+       fprintf(stderr, "\n");
+
+       fprintf(stderr, "\tWORD7 = 0x%016"PRIx64"\n", instr->w7.u64);
+       fprintf(stderr, "\t\tGRP        = %x\n", instr->w7.grp);
+       fprintf(stderr, "\t\tADDR_MSB   = 0x%5x\n", instr->w7.addr_msb);
+       fprintf(stderr, "\n");
+}
+
+static void nitrox_dump_zip_result(struct nitrox_zip_instr *instr,
+                                  struct nitrox_zip_result *result)
+{
+       if (!rte_log_can_log(nitrox_logtype, RTE_LOG_DEBUG))
+               return;
+
+       fprintf(stderr, "ZIP result..(instr %p)\n", instr);
+       fprintf(stderr, "\tWORD0 = 0x%016"PRIx64"\n", result->w0.u64);
+       fprintf(stderr, "\t\tCRC32          = 0x%8x\n", result->w0.crc32);
+       fprintf(stderr, "\t\tADLER32        = 0x%8x\n", result->w0.adler32);
+       fprintf(stderr, "\n");
+
+       fprintf(stderr, "\tWORD1 = 0x%016"PRIx64"\n", result->w1.u64);
+       fprintf(stderr, "\t\tTBYTESWRITTEN  = %u\n", result->w1.tbyteswritten);
+       fprintf(stderr, "\t\tTBYTESREAD     = %u\n", result->w1.tbytesread);
+       fprintf(stderr, "\n");
+
+       fprintf(stderr, "\tWORD2 = 0x%016"PRIx64"\n", result->w2.u64);
+       fprintf(stderr, "\t\tTBITS          = %u\n", result->w2.tbits);
+       fprintf(stderr, "\t\tEXN            = %d\n", result->w2.exn);
+       fprintf(stderr, "\t\tEBITS          = %x\n", result->w2.exbits);
+       fprintf(stderr, "\t\tEF             = %d\n", result->w2.ef);
+       fprintf(stderr, "\t\tCOMPCODE       = 0x%2x\n", result->w2.compcode);
+       fprintf(stderr, "\n");
+}
+#else
+#define nitrox_dump_databuf(name, m, off, datalen)
+#define nitrox_dump_zip_instr(instr, hptr_arr, iptr_arr, optr_arr)
+#define nitrox_dump_zip_result(instr, result)
+#endif
+
+static int handle_zero_length_compression(struct nitrox_softreq *sr,
+                                         struct nitrox_comp_xform *xform)
+{
+       union {
+               uint32_t num;
+               uint8_t bytes[4];
+       } fblk;
+       uint32_t dstlen, rlen;
+       struct rte_mbuf *m;
+       uint32_t off;
+       uint32_t mlen;
+       uint32_t i = 0;
+       uint8_t *ptr;
+
+       fblk.num = xform->exn ? (xform->exbits & 0x7F) : 0;
+       fblk.num |= (0x3 << xform->exn);
+       memset(&sr->zip_res, 0, sizeof(sr->zip_res));
+       sr->zip_res.w1.tbytesread = xform->hlen;
+       sr->zip_res.w1.tbyteswritten = 2;
+       sr->zip_res.w2.ef = 1;
+       if (xform->exn == 7)
+               sr->zip_res.w1.tbyteswritten++;
+
+       rlen = sr->zip_res.w1.tbyteswritten;
+       dstlen = rte_pktmbuf_pkt_len(sr->op->m_dst) - sr->op->dst.offset;
+       if (unlikely(dstlen < rlen))
+               return -EIO;
+
+       off = sr->op->dst.offset;
+       for (m = sr->op->m_dst; m && off > rte_pktmbuf_data_len(m); m = m->next)
+               off -= rte_pktmbuf_data_len(m);
+
+       if (unlikely(!m))
+               return -EIO;
+
+       mlen = rte_pktmbuf_data_len(m) - off;
+       if (rlen <= mlen)
+               mlen = rlen;
+
+       ptr = rte_pktmbuf_mtod_offset(m, uint8_t *, off);
+       memcpy(ptr, fblk.bytes, mlen);
+       i += mlen;
+       rlen -= mlen;
+       for (m = m->next; m && rlen; m = m->next) {
+               mlen = rte_pktmbuf_data_len(m) < rlen ?
+                       rte_pktmbuf_data_len(m) : rlen;
+               ptr = rte_pktmbuf_mtod(m, uint8_t *);
+               memcpy(ptr, &fblk.bytes[i], mlen);
+               i += mlen;
+               rlen -= mlen;
+       }
+
+       if (unlikely(rlen != 0))
+               return -EIO;
+
+       sr->zip_res.w2.compcode = NITROX_CC_SUCCESS;
+       sr->op->status = RTE_COMP_OP_STATUS_SUCCESS;
+       sr->zip_res.w0.u64 = rte_cpu_to_be_64(sr->zip_res.w0.u64);
+       sr->zip_res.w1.u64 = rte_cpu_to_be_64(sr->zip_res.w1.u64);
+       sr->zip_res.w2.u64 = rte_cpu_to_be_64(sr->zip_res.w2.u64);
+       return 0;
+}
+
 static int create_sglist_from_mbuf(struct nitrox_sgtable *sgtbl,
                                   struct rte_mbuf *mbuf, uint32_t off,
                                   uint32_t datalen, uint8_t extra_segs,
@@ -398,10 +612,12 @@ static int create_sglist_from_mbuf(struct nitrox_sgtable 
*sgtbl,
        return 0;
 }
 
-static int softreq_init(struct nitrox_softreq *sr)
+static int softreq_init(struct nitrox_softreq *sr,
+                       struct nitrox_comp_xform *xform)
 {
        struct rte_mempool *mp;
        int err;
+       bool need_decomp_threshold;
 
        mp = rte_mempool_from_obj(sr);
        if (unlikely(mp == NULL))
@@ -413,15 +629,17 @@ static int softreq_init(struct nitrox_softreq *sr)
        if (unlikely(err))
                return err;
 
+       need_decomp_threshold = (sr->op->op_type == RTE_COMP_OP_STATELESS &&
+                                xform->op == NITROX_COMP_OP_DECOMPRESS);
        err = create_sglist_from_mbuf(&sr->dst, sr->op->m_dst,
                        sr->op->dst.offset,
                        rte_pktmbuf_pkt_len(sr->op->m_dst) - sr->op->dst.offset,
-                       (sr->xform.op == NITROX_COMP_OP_DECOMPRESS) ? 1 : 0,
+                       need_decomp_threshold ? 1 : 0,
                        mp->socket_id);
        if (unlikely(err))
                return err;
 
-       if (sr->xform.op == NITROX_COMP_OP_DECOMPRESS) {
+       if (need_decomp_threshold) {
                struct nitrox_zip_iova_addr zip_addr;
                int i;
 
@@ -459,12 +677,12 @@ static void nitrox_zip_instr_to_b64(struct nitrox_softreq 
*sr)
        instr->w7.u64 = rte_cpu_to_be_64(instr->w7.u64);
 }
 
-static int process_zip_stateless(struct nitrox_softreq *sr)
+static int process_zip_request(struct nitrox_softreq *sr)
 {
        struct nitrox_zip_instr *instr;
        struct nitrox_comp_xform *xform;
        struct nitrox_zip_iova_addr zip_addr;
-       uint64_t iptr_msb, optr_msb, rptr_msb;
+       uint64_t iptr_msb, optr_msb, rptr_msb, cptr_msb, hptr_msb;
        int err;
 
        xform = sr->op->private_xform;
@@ -473,7 +691,14 @@ static int process_zip_stateless(struct nitrox_softreq *sr)
                return -EINVAL;
        }
 
-       if (unlikely(xform->op == NITROX_COMP_OP_COMPRESS &&
+       if (unlikely(sr->op->op_type == RTE_COMP_OP_STATEFUL &&
+                    xform->op == NITROX_COMP_OP_COMPRESS &&
+                    sr->op->flush_flag == RTE_COMP_FLUSH_FINAL &&
+                    sr->op->src.length == 0))
+               return handle_zero_length_compression(sr, xform);
+
+       if (unlikely(sr->op->op_type == RTE_COMP_OP_STATELESS &&
+                    xform->op == NITROX_COMP_OP_COMPRESS &&
                     sr->op->flush_flag != RTE_COMP_FLUSH_FULL &&
                     sr->op->flush_flag != RTE_COMP_FLUSH_FINAL)) {
                NITROX_LOG(ERR, "Invalid flush flag %d in stateless op\n",
@@ -481,8 +706,7 @@ static int process_zip_stateless(struct nitrox_softreq *sr)
                return -EINVAL;
        }
 
-       sr->xform = *xform;
-       err = softreq_init(sr);
+       err = softreq_init(sr, xform);
        if (unlikely(err))
                return err;
 
@@ -490,10 +714,11 @@ static int process_zip_stateless(struct nitrox_softreq 
*sr)
        memset(instr, 0, sizeof(*instr));
        /* word 0 */
        instr->w0.tol = sr->dst.total_bytes;
-       instr->w0.exn = 0;
-       instr->w0.exbits = 0;
+       instr->w0.exn = xform->exn;
+       instr->w0.exbits = xform->exbits;
        instr->w0.ca = 0;
        if (xform->op == NITROX_COMP_OP_DECOMPRESS ||
+           sr->op->flush_flag == RTE_COMP_FLUSH_SYNC ||
            sr->op->flush_flag == RTE_COMP_FLUSH_FULL)
                instr->w0.sf = 1;
        else
@@ -501,13 +726,12 @@ static int process_zip_stateless(struct nitrox_softreq 
*sr)
 
        instr->w0.ss = xform->level;
        instr->w0.cc = xform->algo;
-       if (xform->op == NITROX_COMP_OP_COMPRESS &&
-           sr->op->flush_flag == RTE_COMP_FLUSH_FINAL)
+       if (sr->op->flush_flag == RTE_COMP_FLUSH_FINAL)
                instr->w0.ef = 1;
        else
                instr->w0.ef = 0;
 
-       instr->w0.bf = 1;
+       instr->w0.bf = xform->bf;
        instr->w0.co = xform->op;
        if (sr->dst.filled_sgls > 1)
                instr->w0.ds = 1;
@@ -522,8 +746,11 @@ static int process_zip_stateless(struct nitrox_softreq *sr)
        instr->w0.hg = 0;
 
        /* word 1 */
-       instr->w1.hl = 0;
-       if (sr->op->input_chksum != 0)
+       instr->w1.hl = xform->hlen;
+       if (sr->op->op_type == RTE_COMP_OP_STATEFUL && !xform->bf)
+               instr->w1.adlercrc32 = xform->chksum;
+       else if (sr->op->op_type == RTE_COMP_OP_STATELESS &&
+                sr->op->input_chksum != 0)
                instr->w1.adlercrc32 = sr->op->input_chksum;
        else if (xform->chksum_type == NITROX_CHKSUM_TYPE_ADLER32)
                instr->w1.adlercrc32 = 1;
@@ -531,11 +758,23 @@ static int process_zip_stateless(struct nitrox_softreq 
*sr)
                instr->w1.adlercrc32 = 0;
 
        /* word 2 */
-       instr->w2.cptr = 0;
+       if (xform->context)
+               zip_addr.u64 = rte_malloc_virt2iova(xform->context);
+       else
+               zip_addr.u64 = 0;
+
+       instr->w2.cptr = zip_addr.zda.addr;
+       cptr_msb = zip_addr.zda.addr_msb;
 
        /* word 3 */
-       instr->w3.hlen = 0;
-       instr->w3.hptr = 0;
+       instr->w3.hlen = xform->hlen;
+       if (xform->history_window)
+               zip_addr.u64 = rte_malloc_virt2iova(xform->history_window);
+       else
+               zip_addr.u64 = 0;
+
+       instr->w3.hptr = zip_addr.zda.addr;
+       hptr_msb = zip_addr.zda.addr_msb;
 
        /* word 4 */
        if (sr->src.filled_sgls == 1) {
@@ -568,7 +807,9 @@ static int process_zip_stateless(struct nitrox_softreq *sr)
        instr->w6.rptr = zip_addr.zda.addr;
        rptr_msb = zip_addr.zda.addr_msb;
 
-       if (iptr_msb != optr_msb || iptr_msb != rptr_msb) {
+       if (unlikely(iptr_msb != optr_msb || iptr_msb != rptr_msb ||
+           (xform->history_window && (iptr_msb != hptr_msb)) ||
+           (xform->context && (iptr_msb != cptr_msb)))) {
                NITROX_LOG(ERR, "addr_msb is not same for all addresses\n");
                return -ENOTSUP;
        }
@@ -577,32 +818,20 @@ static int process_zip_stateless(struct nitrox_softreq 
*sr)
        instr->w7.addr_msb = iptr_msb;
        instr->w7.grp = 0;
 
+       nitrox_dump_zip_instr(instr, NULL, sr->src.sgl, sr->dst.sgl);
+       nitrox_dump_databuf("IN", sr->op->m_src, sr->op->src.offset,
+                           sr->op->src.length);
        nitrox_zip_instr_to_b64(sr);
        return 0;
 }
 
-static int process_zip_request(struct nitrox_softreq *sr)
-{
-       int err;
-
-       switch (sr->op->op_type) {
-       case RTE_COMP_OP_STATELESS:
-               err = process_zip_stateless(sr);
-               break;
-       default:
-               err = -EINVAL;
-               break;
-       }
-
-       return err;
-}
-
 int
 nitrox_process_comp_req(struct rte_comp_op *op, struct nitrox_softreq *sr)
 {
        int err;
 
        sr->op = op;
+       sr->op->status = RTE_COMP_OP_STATUS_NOT_PROCESSED;
        err = process_zip_request(sr);
        if (unlikely(err))
                goto err_exit;
@@ -628,55 +857,239 @@ static struct nitrox_zip_result 
zip_result_to_cpu64(struct nitrox_zip_result *r)
        return out_res;
 }
 
-int
-nitrox_check_comp_req(struct nitrox_softreq *sr, struct rte_comp_op **op)
+static int post_process_zip_stateless(struct nitrox_softreq *sr,
+                                     struct nitrox_comp_xform *xform,
+                                     struct nitrox_zip_result *zip_res)
 {
-       struct nitrox_zip_result zip_res;
        int output_unused_bytes;
-       int err = 0;
-
-       zip_res = zip_result_to_cpu64(&sr->zip_res);
-       if (zip_res.w2.compcode == NITROX_CC_NOTDONE) {
-               if (rte_get_timer_cycles() >= sr->timeout) {
-                       NITROX_LOG(ERR, "Op timedout\n");
-                       sr->op->status = RTE_COMP_OP_STATUS_ERROR;
-                       err = -ETIMEDOUT;
-                       goto exit;
-               } else {
-                       return -EAGAIN;
-               }
-       }
 
-       if (unlikely(zip_res.w2.compcode != NITROX_CC_SUCCESS)) {
+       if (unlikely(zip_res->w2.compcode != NITROX_CC_SUCCESS)) {
                struct rte_comp_op *op = sr->op;
 
-               NITROX_LOG(ERR, "Op dequeue error 0x%x\n",
-                          zip_res.w2.compcode);
-               if (zip_res.w2.compcode == NITROX_CC_STOP ||
-                   zip_res.w2.compcode == NITROX_CC_DTRUNC)
+               NITROX_LOG(ERR, "Dequeue error 0x%x\n",
+                          zip_res->w2.compcode);
+               if (zip_res->w2.compcode == NITROX_CC_STOP ||
+                   zip_res->w2.compcode == NITROX_CC_DTRUNC)
                        op->status = RTE_COMP_OP_STATUS_OUT_OF_SPACE_TERMINATED;
                else
                        op->status = RTE_COMP_OP_STATUS_ERROR;
 
                op->consumed = 0;
                op->produced = 0;
-               err = -EFAULT;
-               goto exit;
+               return -EFAULT;
        }
 
-       output_unused_bytes = sr->dst.total_bytes - zip_res.w1.tbyteswritten;
-       if (unlikely(sr->xform.op == NITROX_COMP_OP_DECOMPRESS &&
+       output_unused_bytes = sr->dst.total_bytes - zip_res->w1.tbyteswritten;
+       if (unlikely(xform->op == NITROX_COMP_OP_DECOMPRESS &&
                     output_unused_bytes < NITROX_ZIP_MAX_ONFSIZE)) {
                NITROX_LOG(ERR, "TOL %d, Total bytes written %d\n",
-                          sr->dst.total_bytes, zip_res.w1.tbyteswritten);
+                          sr->dst.total_bytes, zip_res->w1.tbyteswritten);
                sr->op->status = RTE_COMP_OP_STATUS_OUT_OF_SPACE_TERMINATED;
                sr->op->consumed = 0;
                sr->op->produced = sr->dst.total_bytes - NITROX_ZIP_MAX_ONFSIZE;
-               err = -EIO;
-               goto exit;
+               return -EIO;
+       }
+
+       if (xform->chksum_type == NITROX_CHKSUM_TYPE_CRC32)
+               sr->op->output_chksum = zip_res->w0.crc32;
+       else if (xform->chksum_type == NITROX_CHKSUM_TYPE_ADLER32)
+               sr->op->output_chksum = zip_res->w0.adler32;
+
+       sr->op->consumed = RTE_MIN(sr->op->src.length,
+                                  (uint32_t)zip_res->w1.tbytesread);
+       sr->op->produced = zip_res->w1.tbyteswritten;
+       sr->op->status = RTE_COMP_OP_STATUS_SUCCESS;
+       return 0;
+}
+
+static int update_history(struct rte_mbuf *mbuf, uint32_t off, uint16_t 
datalen,
+                          uint8_t *dst)
+{
+       struct rte_mbuf *m;
+       uint32_t mlen;
+       uint16_t copied = 0;
+
+       for (m = mbuf; m && off > rte_pktmbuf_data_len(m); m = m->next)
+               off -= rte_pktmbuf_data_len(m);
+
+       if (unlikely(!m)) {
+               NITROX_LOG(ERR, "Failed to update history. Invalid mbuf\n");
+               return -EINVAL;
+       }
+
+       mlen = rte_pktmbuf_data_len(m) - off;
+       if (datalen <= mlen)
+               mlen = datalen;
+
+       memcpy(&dst[copied], rte_pktmbuf_mtod_offset(m, char *, off), mlen);
+       copied += mlen;
+       datalen -= mlen;
+       for (m = m->next; m && datalen; m = m->next) {
+               mlen = rte_pktmbuf_data_len(m) < datalen ?
+                       rte_pktmbuf_data_len(m) : datalen;
+               memcpy(&dst[copied], rte_pktmbuf_mtod(m, char *), mlen);
+               copied += mlen;
+               datalen -= mlen;
+       }
+
+       if (unlikely(datalen != 0)) {
+               NITROX_LOG(ERR, "Failed to update history. Invalid datalen\n");
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static void reset_nitrox_xform(struct nitrox_comp_xform *xform)
+{
+       xform->hlen = 0;
+       xform->exn = 0;
+       xform->exbits = 0;
+       xform->bf = true;
+}
+
+static int post_process_zip_stateful(struct nitrox_softreq *sr,
+                                    struct nitrox_comp_xform *xform,
+                                    struct nitrox_zip_result *zip_res)
+{
+       uint32_t bytesread = 0;
+       uint32_t chksum = 0;
+
+       if (unlikely(zip_res->w2.compcode == NITROX_CC_DTRUNC)) {
+               sr->op->consumed = 0;
+               sr->op->produced = 0;
+               xform->hlen = 0;
+               sr->op->status = RTE_COMP_OP_STATUS_OUT_OF_SPACE_RECOVERABLE;
+               NITROX_LOG(ERR, "Dequeue compress DTRUNC error\n");
+               return 0;
+       } else if (unlikely(zip_res->w2.compcode == NITROX_CC_STOP)) {
+               sr->op->status = RTE_COMP_OP_STATUS_OUT_OF_SPACE_RECOVERABLE;
+               NITROX_LOG(NOTICE, "Dequeue decompress dynamic STOP\n");
+       } else if (zip_res->w2.compcode == NITROX_CC_SUCCESS) {
+               sr->op->status = RTE_COMP_OP_STATUS_SUCCESS;
+       } else {
+               xform->hlen = 0;
+               xform->exn = 0;
+               xform->exbits = 0;
+               xform->bf = true;
+               sr->op->status = RTE_COMP_OP_STATUS_ERROR;
+               NITROX_LOG(ERR, "Dequeue error 0x%x\n",
+                          zip_res->w2.compcode);
+               return -EFAULT;
+       }
+
+       if (xform->op == NITROX_COMP_OP_COMPRESS) {
+               if (zip_res->w1.tbytesread < xform->hlen) {
+                       NITROX_LOG(ERR, "Invalid bytesread\n");
+                       reset_nitrox_xform(xform);
+                       sr->op->status = RTE_COMP_OP_STATUS_ERROR;
+                       return -EFAULT;
+               }
+
+               bytesread = zip_res->w1.tbytesread - xform->hlen;
+       } else {
+               bytesread = RTE_MIN(sr->op->src.length,
+                                   (uint32_t)zip_res->w1.tbytesread);
+       }
+
+       if ((xform->op == NITROX_COMP_OP_COMPRESS &&
+           (sr->op->flush_flag == RTE_COMP_FLUSH_NONE ||
+           sr->op->flush_flag == RTE_COMP_FLUSH_SYNC)) ||
+           (xform->op == NITROX_COMP_OP_DECOMPRESS && !zip_res->w2.ef)) {
+               struct rte_mbuf *mbuf;
+               uint32_t pktlen, m_off;
+               int err;
+
+               if (xform->op == NITROX_COMP_OP_COMPRESS) {
+                       mbuf = sr->op->m_src;
+                       pktlen = bytesread;
+                       m_off = sr->op->src.offset;
+               } else {
+                       mbuf = sr->op->m_dst;
+                       pktlen = zip_res->w1.tbyteswritten;
+                       m_off = sr->op->dst.offset;
+               }
+
+               if (pktlen >= xform->window_size) {
+                       m_off += pktlen - xform->window_size;
+                       err = update_history(mbuf, m_off, xform->window_size,
+                                      xform->history_window);
+                       xform->hlen = xform->window_size;
+               } else if ((xform->hlen + pktlen) <= xform->window_size) {
+                       err = update_history(mbuf, m_off, pktlen,
+                                      &xform->history_window[xform->hlen]);
+                       xform->hlen += pktlen;
+               } else {
+                       uint16_t shift_off, shift_len;
+
+                       shift_off = pktlen + xform->hlen - xform->window_size;
+                       shift_len = xform->hlen - shift_off;
+                       memmove(xform->history_window,
+                               &xform->history_window[shift_off],
+                               shift_len);
+                       err = update_history(mbuf, m_off, pktlen,
+                                      &xform->history_window[shift_len]);
+                       xform->hlen = xform->window_size;
+
+               }
+
+               if (unlikely(err)) {
+                       sr->op->status = RTE_COMP_OP_STATUS_ERROR;
+                       return err;
+               }
+
+               if (xform->op == NITROX_COMP_OP_COMPRESS) {
+                       xform->exn = zip_res->w2.exn;
+                       xform->exbits = zip_res->w2.exbits;
+               }
+
+               xform->bf = false;
+       } else {
+               reset_nitrox_xform(xform);
        }
 
-       if (sr->xform.op == NITROX_COMP_OP_COMPRESS &&
+       if (xform->chksum_type == NITROX_CHKSUM_TYPE_CRC32)
+               chksum = zip_res->w0.crc32;
+       else if (xform->chksum_type == NITROX_CHKSUM_TYPE_ADLER32)
+               chksum = zip_res->w0.adler32;
+
+       if (xform->bf)
+               sr->op->output_chksum = chksum;
+       else
+               xform->chksum = chksum;
+
+       sr->op->consumed = bytesread;
+       sr->op->produced = zip_res->w1.tbyteswritten;
+       return 0;
+}
+
+int
+nitrox_check_comp_req(struct nitrox_softreq *sr, struct rte_comp_op **op)
+{
+       struct nitrox_zip_result zip_res;
+       struct nitrox_comp_xform *xform;
+       int err = 0;
+
+       zip_res = zip_result_to_cpu64(&sr->zip_res);
+       if (zip_res.w2.compcode == NITROX_CC_NOTDONE) {
+               if (rte_get_timer_cycles() >= sr->timeout) {
+                       NITROX_LOG(ERR, "Op timedout\n");
+                       sr->op->status = RTE_COMP_OP_STATUS_ERROR;
+                       err = -ETIMEDOUT;
+                       goto exit;
+               } else {
+                       return -EAGAIN;
+               }
+       }
+
+       xform = sr->op->private_xform;
+       if (sr->op->op_type == RTE_COMP_OP_STATELESS)
+               err = post_process_zip_stateless(sr, xform, &zip_res);
+       else
+               err = post_process_zip_stateful(sr, xform, &zip_res);
+
+       if (sr->op->status == RTE_COMP_OP_STATUS_SUCCESS &&
+           xform->op == NITROX_COMP_OP_COMPRESS &&
            sr->op->flush_flag == RTE_COMP_FLUSH_FINAL &&
            zip_res.w2.exn) {
                uint32_t datalen = zip_res.w1.tbyteswritten;
@@ -696,17 +1109,11 @@ nitrox_check_comp_req(struct nitrox_softreq *sr, struct 
rte_comp_op **op)
                *last_byte = zip_res.w2.exbits & 0xFF;
        }
 
-       sr->op->consumed = zip_res.w1.tbytesread;
-       sr->op->produced = zip_res.w1.tbyteswritten;
-       if (sr->xform.chksum_type == NITROX_CHKSUM_TYPE_CRC32)
-               sr->op->output_chksum = zip_res.w0.crc32;
-       else if (sr->xform.chksum_type == NITROX_CHKSUM_TYPE_ADLER32)
-               sr->op->output_chksum = zip_res.w0.adler32;
-
-       sr->op->status = RTE_COMP_OP_STATUS_SUCCESS;
-       err = 0;
 exit:
        *op = sr->op;
+       nitrox_dump_zip_result(&sr->instr, &zip_res);
+       nitrox_dump_databuf("OUT after", sr->op->m_dst, sr->op->dst.offset,
+               sr->op->produced);
        return err;
 }
 
diff --git a/drivers/compress/nitrox/nitrox_comp_reqmgr.h 
b/drivers/compress/nitrox/nitrox_comp_reqmgr.h
index 07c65f0d5e..f0cd1eb8fd 100644
--- a/drivers/compress/nitrox/nitrox_comp_reqmgr.h
+++ b/drivers/compress/nitrox/nitrox_comp_reqmgr.h
@@ -37,6 +37,14 @@ struct nitrox_comp_xform {
        enum nitrox_comp_algo algo;
        enum nitrox_comp_level level;
        enum nitrox_chksum_type chksum_type;
+       uint8_t *context;
+       uint8_t *history_window;
+       uint32_t chksum;
+       uint16_t window_size;
+       uint16_t hlen;
+       uint8_t exn;
+       uint8_t exbits;
+       bool bf;
 };
 
 int nitrox_process_comp_req(struct rte_comp_op *op, struct nitrox_softreq *sr);
-- 
2.42.0

Reply via email to