root/sys/dev/qat/qat_api/common/compression/dc_session.c
/* SPDX-License-Identifier: BSD-3-Clause */
/* Copyright(c) 2007-2022 Intel Corporation */
/**
 *****************************************************************************
 * @file dc_session.c
 *
 * @ingroup Dc_DataCompression
 *
 * @description
 *      Implementation of the Data Compression session operations.
 *
 *****************************************************************************/

/*
 *******************************************************************************
 * Include public/global header files
 *******************************************************************************
 */
#include "cpa.h"
#include "cpa_dc.h"

#include "icp_qat_fw.h"
#include "icp_qat_fw_comp.h"
#include "icp_qat_hw.h"
#include "icp_qat_hw_20_comp.h"

/*
 *******************************************************************************
 * Include private header files
 *******************************************************************************
 */
#include "dc_session.h"
#include "dc_datapath.h"
#include "lac_mem_pools.h"
#include "sal_types_compression.h"
#include "lac_buffer_desc.h"
#include "sal_service_state.h"
#include "sal_qat_cmn_msg.h"
#include "sal_hw_gen.h"

/**
 *****************************************************************************
 * @ingroup Dc_DataCompression
 *      Check that pSessionData is valid
 *
 * @description
 *      Check that all the parameters defined in the pSessionData are valid
 *
 * @param[in]       pSessionData     Pointer to a user instantiated structure
 *                                   containing session data
 *
 * @retval CPA_STATUS_SUCCESS        Function executed successfully
 * @retval CPA_STATUS_FAIL           Function failed to find device
 * @retval CPA_STATUS_INVALID_PARAM  Invalid parameter passed in
 * @retval CPA_STATUS_UNSUPPORTED    Unsupported algorithm/feature
 *
 *****************************************************************************/
CpaStatus
dcCheckSessionData(const CpaDcSessionSetupData *pSessionData,
                   CpaInstanceHandle dcInstance)
{
        CpaDcInstanceCapabilities instanceCapabilities = { 0 };

        cpaDcQueryCapabilities(dcInstance, &instanceCapabilities);

        if ((pSessionData->compLevel < CPA_DC_L1) ||
            (pSessionData->compLevel > CPA_DC_L12)) {
                QAT_UTILS_LOG("Invalid compLevel value\n");
                return CPA_STATUS_INVALID_PARAM;
        }

        if ((pSessionData->autoSelectBestHuffmanTree < CPA_DC_ASB_DISABLED) ||
            (pSessionData->autoSelectBestHuffmanTree > CPA_DC_ASB_ENABLED)) {
                QAT_UTILS_LOG("Invalid autoSelectBestHuffmanTree value\n");
                return CPA_STATUS_INVALID_PARAM;
        }
        if (pSessionData->compType != CPA_DC_DEFLATE) {
                QAT_UTILS_LOG("Invalid compType value\n");
                return CPA_STATUS_INVALID_PARAM;
        }

        if ((pSessionData->huffType < CPA_DC_HT_STATIC) ||
            (pSessionData->huffType > CPA_DC_HT_FULL_DYNAMIC) ||
            (CPA_DC_HT_PRECOMP == pSessionData->huffType)) {
                QAT_UTILS_LOG("Invalid huffType value\n");
                return CPA_STATUS_INVALID_PARAM;
        }

        if ((pSessionData->sessDirection < CPA_DC_DIR_COMPRESS) ||
            (pSessionData->sessDirection > CPA_DC_DIR_COMBINED)) {
                QAT_UTILS_LOG("Invalid sessDirection value\n");
                return CPA_STATUS_INVALID_PARAM;
        }

        if ((pSessionData->sessState < CPA_DC_STATEFUL) ||
            (pSessionData->sessState > CPA_DC_STATELESS)) {
                QAT_UTILS_LOG("Invalid sessState value\n");
                return CPA_STATUS_INVALID_PARAM;
        }

        if ((pSessionData->checksum < CPA_DC_NONE) ||
            (pSessionData->checksum > CPA_DC_ADLER32)) {
                QAT_UTILS_LOG("Invalid checksum value\n");
                return CPA_STATUS_INVALID_PARAM;
        }

        return CPA_STATUS_SUCCESS;
}

/**
 *****************************************************************************
 * @ingroup Dc_DataCompression
 *      Populate the compression hardware block
 *
 * @description
 *      This function will populate the compression hardware block and update
 *      the size in bytes of the block
 *
 * @param[in]   pSessionDesc            Pointer to the session descriptor
 * @param[in]   pCompConfig             Pointer to slice config word
 * @param[in]   compDecomp              Direction of the operation
 * @param[in]   enableDmm               Delayed Match Mode
 *
 *****************************************************************************/
static void
dcCompHwBlockPopulate(sal_compression_service_t *pService,
                      dc_session_desc_t *pSessionDesc,
                      icp_qat_hw_compression_config_t *pCompConfig,
                      dc_request_dir_t compDecomp)
{
        icp_qat_hw_compression_direction_t dir =
            ICP_QAT_HW_COMPRESSION_DIR_COMPRESS;
        icp_qat_hw_compression_algo_t algo =
            ICP_QAT_HW_COMPRESSION_ALGO_DEFLATE;
        icp_qat_hw_compression_depth_t depth = ICP_QAT_HW_COMPRESSION_DEPTH_1;
        icp_qat_hw_compression_file_type_t filetype =
            ICP_QAT_HW_COMPRESSION_FILE_TYPE_0;
        icp_qat_hw_compression_delayed_match_t dmm;

        /* Set the direction */
        if (DC_COMPRESSION_REQUEST == compDecomp) {
                dir = ICP_QAT_HW_COMPRESSION_DIR_COMPRESS;
        } else {
                dir = ICP_QAT_HW_COMPRESSION_DIR_DECOMPRESS;
        }

        if (CPA_DC_DEFLATE == pSessionDesc->compType) {
                algo = ICP_QAT_HW_COMPRESSION_ALGO_DEFLATE;
        } else {
                QAT_UTILS_LOG("Algorithm not supported for Compression\n");
        }

        /* Set delay match mode */
        if (ICP_QAT_HW_COMPRESSION_DELAYED_MATCH_ENABLED ==
            pService->comp_device_data.enableDmm) {
                dmm = ICP_QAT_HW_COMPRESSION_DELAYED_MATCH_ENABLED;
        } else {
                dmm = ICP_QAT_HW_COMPRESSION_DELAYED_MATCH_DISABLED;
        }

        /* Set the depth */
        if (DC_DECOMPRESSION_REQUEST == compDecomp) {
                depth = ICP_QAT_HW_COMPRESSION_DEPTH_1;
        } else {
                switch (pSessionDesc->compLevel) {
                case CPA_DC_L1:
                        depth = ICP_QAT_HW_COMPRESSION_DEPTH_1;
                        break;
                case CPA_DC_L2:
                        depth = ICP_QAT_HW_COMPRESSION_DEPTH_4;
                        break;
                case CPA_DC_L3:
                        depth = ICP_QAT_HW_COMPRESSION_DEPTH_8;
                        break;
                case CPA_DC_L4:
                        depth = ICP_QAT_HW_COMPRESSION_DEPTH_16;
                        break;
                default:
                        depth = pService->comp_device_data
                                    .highestHwCompressionDepth;
                        break;
                }
        }

        /* The file type is set to ICP_QAT_HW_COMPRESSION_FILE_TYPE_0. The other
         * modes will be used in the future for precompiled huffman trees */
        filetype = ICP_QAT_HW_COMPRESSION_FILE_TYPE_0;

        pCompConfig->lower_val = ICP_QAT_HW_COMPRESSION_CONFIG_BUILD(
            dir, dmm, algo, depth, filetype);

        /* Upper 32-bits of the configuration word do not need to be
         * configured with legacy devices.
         */
        pCompConfig->upper_val = 0;
}

static void
dcCompHwBlockPopulateGen4(sal_compression_service_t *pService,
                          dc_session_desc_t *pSessionDesc,
                          icp_qat_hw_compression_config_t *pCompConfig,
                          dc_request_dir_t compDecomp)
{
        /* Compression related */
        if (DC_COMPRESSION_REQUEST == compDecomp) {
                icp_qat_hw_comp_20_config_csr_upper_t hw_comp_upper_csr;
                icp_qat_hw_comp_20_config_csr_lower_t hw_comp_lower_csr;

                memset(&hw_comp_upper_csr, 0, sizeof hw_comp_upper_csr);
                memset(&hw_comp_lower_csr, 0, sizeof hw_comp_lower_csr);

                /* Disable Literal + Length Limit Block Drop by default and
                 * enable it only for dynamic deflate compression.
                 */
                hw_comp_lower_csr.lllbd =
                    ICP_QAT_HW_COMP_20_LLLBD_CTRL_LLLBD_DISABLED;

                switch (pSessionDesc->compType) {
                case CPA_DC_DEFLATE:
                        /* DEFLATE algorithm settings */
                        hw_comp_lower_csr.skip_ctrl =
                            ICP_QAT_HW_COMP_20_BYTE_SKIP_3BYTE_LITERAL;

                        if (CPA_DC_HT_FULL_DYNAMIC == pSessionDesc->huffType) {
                                hw_comp_lower_csr.algo =
                                    ICP_QAT_HW_COMP_20_HW_COMP_FORMAT_ILZ77;
                        } else /* Static DEFLATE */
                        {
                                hw_comp_lower_csr.algo =
                                    ICP_QAT_HW_COMP_20_HW_COMP_FORMAT_DEFLATE;
                                hw_comp_upper_csr.scb_ctrl =
                                    ICP_QAT_HW_COMP_20_SCB_CONTROL_DISABLE;
                        }

                        if (CPA_DC_STATEFUL == pSessionDesc->sessState) {
                                hw_comp_upper_csr.som_ctrl =
                                    ICP_QAT_HW_COMP_20_SOM_CONTROL_REPLAY_MODE;
                        }
                        break;
                default:
                        QAT_UTILS_LOG("Compression algorithm not supported\n");
                        break;
                }
                /* Set the search depth */
                switch (pSessionDesc->compLevel) {
                case CPA_DC_L1:
                case CPA_DC_L2:
                case CPA_DC_L3:
                case CPA_DC_L4:
                case CPA_DC_L5:
                        hw_comp_lower_csr.sd =
                            ICP_QAT_HW_COMP_20_SEARCH_DEPTH_LEVEL_1;
                        hw_comp_lower_csr.hash_col =
                            ICP_QAT_HW_COMP_20_SKIP_HASH_COLLISION_DONT_ALLOW;
                        break;
                case CPA_DC_L6:
                case CPA_DC_L7:
                case CPA_DC_L8:
                        hw_comp_lower_csr.sd =
                            ICP_QAT_HW_COMP_20_SEARCH_DEPTH_LEVEL_6;
                        break;
                case CPA_DC_L9:
                        hw_comp_lower_csr.sd =
                            ICP_QAT_HW_COMP_20_SEARCH_DEPTH_LEVEL_9;
                        break;
                default:
                        hw_comp_lower_csr.sd = pService->comp_device_data
                                                   .highestHwCompressionDepth;
                        if ((CPA_DC_HT_FULL_DYNAMIC ==
                             pSessionDesc->huffType) &&
                            (CPA_DC_DEFLATE == pSessionDesc->compType)) {
                                /* Enable Literal + Length Limit Block Drop
                                 * with dynamic deflate compression when
                                 * highest compression levels are selected.
                                 */
                                hw_comp_lower_csr.lllbd =
                                    ICP_QAT_HW_COMP_20_LLLBD_CTRL_LLLBD_ENABLED;
                        }
                        break;
                }
                /* Same for all algorithms */
                hw_comp_lower_csr.abd = ICP_QAT_HW_COMP_20_ABD_ABD_DISABLED;
                hw_comp_lower_csr.hash_update =
                    ICP_QAT_HW_COMP_20_SKIP_HASH_UPDATE_DONT_ALLOW;
                hw_comp_lower_csr.edmm =
                    (ICP_QAT_HW_COMPRESSION_DELAYED_MATCH_ENABLED ==
                        pService->comp_device_data.enableDmm) ?
                    ICP_QAT_HW_COMP_20_EXTENDED_DELAY_MATCH_MODE_EDMM_ENABLED :
                    ICP_QAT_HW_COMP_20_EXTENDED_DELAY_MATCH_MODE_EDMM_DISABLED;

                /* Hard-coded HW-specific values */
                hw_comp_upper_csr.nice =
                    ICP_QAT_HW_COMP_20_CONFIG_CSR_NICE_PARAM_DEFAULT_VAL;
                hw_comp_upper_csr.lazy =
                    ICP_QAT_HW_COMP_20_CONFIG_CSR_LAZY_PARAM_DEFAULT_VAL;

                pCompConfig->upper_val =
                    ICP_QAT_FW_COMP_20_BUILD_CONFIG_UPPER(hw_comp_upper_csr);

                pCompConfig->lower_val =
                    ICP_QAT_FW_COMP_20_BUILD_CONFIG_LOWER(hw_comp_lower_csr);
        } else /* Decompress */
        {
                icp_qat_hw_decomp_20_config_csr_lower_t hw_decomp_lower_csr;

                memset(&hw_decomp_lower_csr, 0, sizeof hw_decomp_lower_csr);

                /* Set the algorithm */
                if (CPA_DC_DEFLATE == pSessionDesc->compType) {
                        hw_decomp_lower_csr.algo =
                            ICP_QAT_HW_DECOMP_20_HW_DECOMP_FORMAT_DEFLATE;
                } else {
                        QAT_UTILS_LOG("Algorithm not supported for "
                                      "Decompression\n");
                }

                pCompConfig->upper_val = 0;
                pCompConfig->lower_val =
                    ICP_QAT_FW_DECOMP_20_BUILD_CONFIG_LOWER(
                        hw_decomp_lower_csr);
        }
}

/**
 *****************************************************************************
 * @ingroup Dc_DataCompression
 *      Populate the compression content descriptor
 *
 * @description
 *      This function will populate the compression content descriptor
 *
 * @param[in]   pService                Pointer to the service
 * @param[in]   pSessionDesc            Pointer to the session descriptor
 * @param[in]   contextBufferAddrPhys   Physical address of the context buffer
 * @param[out]  pMsg                    Pointer to the compression message
 * @param[in]   nextSlice               Next slice
 * @param[in]   compDecomp              Direction of the operation
 *
 *****************************************************************************/
static void
dcCompContentDescPopulate(sal_compression_service_t *pService,
                          dc_session_desc_t *pSessionDesc,
                          CpaPhysicalAddr contextBufferAddrPhys,
                          icp_qat_fw_comp_req_t *pMsg,
                          icp_qat_fw_slice_t nextSlice,
                          dc_request_dir_t compDecomp)
{

        icp_qat_fw_comp_cd_hdr_t *pCompControlBlock = NULL;
        icp_qat_hw_compression_config_t *pCompConfig = NULL;
        CpaBoolean bankEnabled = CPA_FALSE;

        pCompControlBlock = (icp_qat_fw_comp_cd_hdr_t *)&(pMsg->comp_cd_ctrl);
        pCompConfig =
            (icp_qat_hw_compression_config_t *)(pMsg->cd_pars.sl
                                                    .comp_slice_cfg_word);

        ICP_QAT_FW_COMN_NEXT_ID_SET(pCompControlBlock, nextSlice);
        ICP_QAT_FW_COMN_CURR_ID_SET(pCompControlBlock, ICP_QAT_FW_SLICE_COMP);

        pCompControlBlock->comp_cfg_offset = 0;

        if ((CPA_DC_STATEFUL == pSessionDesc->sessState) &&
            (CPA_DC_DEFLATE == pSessionDesc->compType) &&
            (DC_DECOMPRESSION_REQUEST == compDecomp)) {
                /* Enable A, B, C, D, and E (CAMs).  */
                pCompControlBlock->ram_bank_flags =
                    ICP_QAT_FW_COMP_RAM_FLAGS_BUILD(
                        ICP_QAT_FW_COMP_BANK_DISABLED, /* Bank I */
                        ICP_QAT_FW_COMP_BANK_DISABLED, /* Bank H */
                        ICP_QAT_FW_COMP_BANK_DISABLED, /* Bank G */
                        ICP_QAT_FW_COMP_BANK_DISABLED, /* Bank F */
                        ICP_QAT_FW_COMP_BANK_ENABLED,  /* Bank E */
                        ICP_QAT_FW_COMP_BANK_ENABLED,  /* Bank D */
                        ICP_QAT_FW_COMP_BANK_ENABLED,  /* Bank C */
                        ICP_QAT_FW_COMP_BANK_ENABLED,  /* Bank B */
                        ICP_QAT_FW_COMP_BANK_ENABLED); /* Bank A */
                bankEnabled = CPA_TRUE;
        } else {
                /* Disable all banks */
                pCompControlBlock->ram_bank_flags =
                    ICP_QAT_FW_COMP_RAM_FLAGS_BUILD(
                        ICP_QAT_FW_COMP_BANK_DISABLED,  /* Bank I */
                        ICP_QAT_FW_COMP_BANK_DISABLED,  /* Bank H */
                        ICP_QAT_FW_COMP_BANK_DISABLED,  /* Bank G */
                        ICP_QAT_FW_COMP_BANK_DISABLED,  /* Bank F */
                        ICP_QAT_FW_COMP_BANK_DISABLED,  /* Bank E */
                        ICP_QAT_FW_COMP_BANK_DISABLED,  /* Bank D */
                        ICP_QAT_FW_COMP_BANK_DISABLED,  /* Bank C */
                        ICP_QAT_FW_COMP_BANK_DISABLED,  /* Bank B */
                        ICP_QAT_FW_COMP_BANK_DISABLED); /* Bank A */
        }

        if (DC_COMPRESSION_REQUEST == compDecomp) {
                LAC_MEM_SHARED_WRITE_VIRT_TO_PHYS_PTR_EXTERNAL(
                    pService->generic_service_info,
                    pCompControlBlock->comp_state_addr,
                    pSessionDesc->stateRegistersComp);
        } else {
                LAC_MEM_SHARED_WRITE_VIRT_TO_PHYS_PTR_EXTERNAL(
                    pService->generic_service_info,
                    pCompControlBlock->comp_state_addr,
                    pSessionDesc->stateRegistersDecomp);
        }

        if (CPA_TRUE == bankEnabled) {
                pCompControlBlock->ram_banks_addr = contextBufferAddrPhys;
        } else {
                pCompControlBlock->ram_banks_addr = 0;
        }

        pCompControlBlock->resrvd = 0;

        /* Populate Compression Hardware Setup Block */
        if (isDcGen4x(pService)) {
                dcCompHwBlockPopulateGen4(pService,
                                          pSessionDesc,
                                          pCompConfig,
                                          compDecomp);
        } else if (isDcGen2x(pService)) {
                dcCompHwBlockPopulate(pService,
                                      pSessionDesc,
                                      pCompConfig,
                                      compDecomp);
        } else {
                QAT_UTILS_LOG("Invalid QAT generation value\n");
        }
}

/**
 *****************************************************************************
 * @ingroup Dc_DataCompression
 *      Populate the translator content descriptor
 *
 * @description
 *      This function will populate the translator content descriptor
 *
 * @param[out]  pMsg                     Pointer to the compression message
 * @param[in]   nextSlice                Next slice
 *
 *****************************************************************************/
void
dcTransContentDescPopulate(icp_qat_fw_comp_req_t *pMsg,
                           icp_qat_fw_slice_t nextSlice)
{

        icp_qat_fw_xlt_cd_hdr_t *pTransControlBlock = NULL;
        pTransControlBlock = (icp_qat_fw_xlt_cd_hdr_t *)&(pMsg->u2.xlt_cd_ctrl);

        ICP_QAT_FW_COMN_NEXT_ID_SET(pTransControlBlock, nextSlice);
        ICP_QAT_FW_COMN_CURR_ID_SET(pTransControlBlock, ICP_QAT_FW_SLICE_XLAT);

        pTransControlBlock->resrvd1 = 0;
        pTransControlBlock->resrvd2 = 0;
        pTransControlBlock->resrvd3 = 0;
}

/**
 *****************************************************************************
 * @ingroup Dc_DataCompression
 *      Get the context size and the history size
 *
 * @description
 *      This function will get the size of the context buffer and the history
 *      buffer. The history buffer is a subset of the context buffer and its
 *      size is needed for stateful compression.

 * @param[in]   dcInstance         DC Instance Handle
 *
 * @param[in]   pSessionData       Pointer to a user instantiated
 *                                 structure containing session data
 * @param[out]  pContextSize       Pointer to the context size
 *
 * @retval CPA_STATUS_SUCCESS      Function executed successfully
 *
 *
 *****************************************************************************/
static CpaStatus
dcGetContextSize(CpaInstanceHandle dcInstance,
                 CpaDcSessionSetupData *pSessionData,
                 Cpa32U *pContextSize)
{
        sal_compression_service_t *pCompService = NULL;

        pCompService = (sal_compression_service_t *)dcInstance;

        *pContextSize = 0;
        if ((CPA_DC_STATEFUL == pSessionData->sessState) &&
            (CPA_DC_DIR_COMPRESS != pSessionData->sessDirection)) {
                switch (pSessionData->compType) {
                case CPA_DC_DEFLATE:
                        *pContextSize =
                            pCompService->comp_device_data.inflateContextSize;
                        break;
                default:
                        QAT_UTILS_LOG("Invalid compression algorithm.");
                        return CPA_STATUS_FAIL;
                }
        }
        return CPA_STATUS_SUCCESS;
}

CpaStatus
dcGetCompressCommandId(sal_compression_service_t *pService,
                       CpaDcSessionSetupData *pSessionData,
                       Cpa8U *pDcCmdId)
{
        CpaStatus status = CPA_STATUS_SUCCESS;
        LAC_CHECK_NULL_PARAM(pService);
        LAC_CHECK_NULL_PARAM(pSessionData);
        LAC_CHECK_NULL_PARAM(pDcCmdId);

        switch (pSessionData->compType) {
        case CPA_DC_DEFLATE:
                *pDcCmdId = (CPA_DC_HT_FULL_DYNAMIC == pSessionData->huffType) ?
                    ICP_QAT_FW_COMP_CMD_DYNAMIC :
                    ICP_QAT_FW_COMP_CMD_STATIC;
                break;
        default:
                QAT_UTILS_LOG("Algorithm not supported for "
                              "compression\n");
                status = CPA_STATUS_UNSUPPORTED;
                break;
        }

        return status;
}

CpaStatus
dcGetDecompressCommandId(sal_compression_service_t *pService,
                         CpaDcSessionSetupData *pSessionData,
                         Cpa8U *pDcCmdId)
{
        CpaStatus status = CPA_STATUS_SUCCESS;
        LAC_CHECK_NULL_PARAM(pService);
        LAC_CHECK_NULL_PARAM(pSessionData);
        LAC_CHECK_NULL_PARAM(pDcCmdId);

        switch (pSessionData->compType) {
        case CPA_DC_DEFLATE:
                *pDcCmdId = ICP_QAT_FW_COMP_CMD_DECOMPRESS;
                break;
        default:
                QAT_UTILS_LOG("Algorithm not supported for "
                              "decompression\n");
                status = CPA_STATUS_UNSUPPORTED;
                break;
        }

        return status;
}

CpaStatus
dcInitSession(CpaInstanceHandle dcInstance,
              CpaDcSessionHandle pSessionHandle,
              CpaDcSessionSetupData *pSessionData,
              CpaBufferList *pContextBuffer,
              CpaDcCallbackFn callbackFn)
{
        CpaStatus status = CPA_STATUS_SUCCESS;
        sal_compression_service_t *pService = NULL;
        icp_qat_fw_comp_req_t *pReqCache = NULL;
        dc_session_desc_t *pSessionDesc = NULL;
        CpaPhysicalAddr contextAddrPhys = 0;
        CpaPhysicalAddr physAddress = 0;
        CpaPhysicalAddr physAddressAligned = 0;
        Cpa32U minContextSize = 0, historySize = 0;
        Cpa32U rpCmdFlags = 0;
        icp_qat_fw_serv_specif_flags cmdFlags = 0;
        Cpa8U secureRam = ICP_QAT_FW_COMP_ENABLE_SECURE_RAM_USED_AS_INTMD_BUF;
        Cpa8U sessType = ICP_QAT_FW_COMP_STATELESS_SESSION;
        Cpa8U autoSelectBest = ICP_QAT_FW_COMP_NOT_AUTO_SELECT_BEST;
        Cpa8U enhancedAutoSelectBest = ICP_QAT_FW_COMP_NOT_ENH_AUTO_SELECT_BEST;
        Cpa8U disableType0EnhancedAutoSelectBest =
            ICP_QAT_FW_COMP_NOT_DISABLE_TYPE0_ENH_AUTO_SELECT_BEST;
        icp_qat_fw_la_cmd_id_t dcCmdId =
            (icp_qat_fw_la_cmd_id_t)ICP_QAT_FW_COMP_CMD_STATIC;
        icp_qat_fw_comn_flags cmnRequestFlags = 0;
        dc_integrity_crc_fw_t *pDataIntegrityCrcs = NULL;

        cmnRequestFlags =
            ICP_QAT_FW_COMN_FLAGS_BUILD(DC_DEFAULT_QAT_PTR_TYPE,
                                        QAT_COMN_CD_FLD_TYPE_16BYTE_DATA);

        pService = (sal_compression_service_t *)dcInstance;

        secureRam = pService->comp_device_data.useDevRam;

        LAC_CHECK_NULL_PARAM(pSessionHandle);
        LAC_CHECK_NULL_PARAM(pSessionData);

        /* Check that the parameters defined in the pSessionData are valid for
         * the
         * device */
        if (CPA_STATUS_SUCCESS !=
            dcCheckSessionData(pSessionData, dcInstance)) {
                return CPA_STATUS_INVALID_PARAM;
        }

        if ((CPA_DC_STATEFUL == pSessionData->sessState) &&
            (CPA_DC_DIR_DECOMPRESS != pSessionData->sessDirection)) {
                QAT_UTILS_LOG("Stateful sessions are not supported.\n");
                return CPA_STATUS_UNSUPPORTED;
        }

        /* Check for Gen4 and stateful, return error if both exist */
        if ((isDcGen4x(pService)) &&
            (CPA_DC_STATEFUL == pSessionData->sessState &&
             CPA_DC_DIR_DECOMPRESS != pSessionData->sessDirection)) {
                QAT_UTILS_LOG("Stateful sessions are not supported for "
                              "compression direction");
                return CPA_STATUS_UNSUPPORTED;
        }

        if ((isDcGen2x(pService)) &&
            (CPA_DC_HT_FULL_DYNAMIC == pSessionData->huffType)) {
                /* Test if DRAM is available for the intermediate buffers */
                if ((NULL == pService->pInterBuffPtrsArray) &&
                    (0 == pService->pInterBuffPtrsArrayPhyAddr)) {
                        if (CPA_DC_ASB_STATIC_DYNAMIC ==
                            pSessionData->autoSelectBestHuffmanTree) {
                                /* Define the Huffman tree as static */
                                pSessionData->huffType = CPA_DC_HT_STATIC;
                        } else {
                                QAT_UTILS_LOG(
                                    "No buffer defined for this instance - "
                                    "see cpaDcStartInstance.\n");
                                return CPA_STATUS_RESOURCE;
                        }
                }
        }

        if ((CPA_DC_STATEFUL == pSessionData->sessState) &&
            (CPA_DC_DEFLATE == pSessionData->compType)) {
                /* Get the size of the context buffer */
                status =
                    dcGetContextSize(dcInstance, pSessionData, &minContextSize);

                if (CPA_STATUS_SUCCESS != status) {
                        QAT_UTILS_LOG(
                            "Unable to get the context size of the session.\n");
                        return CPA_STATUS_FAIL;
                }

                /* If the minContextSize is zero it means we will not save or
                 * restore
                 * any history */
                if (0 != minContextSize) {
                        Cpa64U contextBuffSize = 0;

                        LAC_CHECK_NULL_PARAM(pContextBuffer);

                        if (LacBuffDesc_BufferListVerify(
                                pContextBuffer,
                                &contextBuffSize,
                                LAC_NO_ALIGNMENT_SHIFT) != CPA_STATUS_SUCCESS) {
                                return CPA_STATUS_INVALID_PARAM;
                        }

                        /* Ensure that the context buffer size is greater or
                         * equal
                         * to minContextSize */
                        if (contextBuffSize < minContextSize) {
                                QAT_UTILS_LOG(
                                    "Context buffer size should be greater or equal to %d.\n",
                                    minContextSize);
                                return CPA_STATUS_INVALID_PARAM;
                        }
                }
        }

        /* Re-align the session structure to 64 byte alignment */
        physAddress =
            LAC_OS_VIRT_TO_PHYS_EXTERNAL(pService->generic_service_info,
                                         (Cpa8U *)pSessionHandle +
                                             sizeof(void *));

        if (physAddress == 0) {
                QAT_UTILS_LOG(
                    "Unable to get the physical address of the session.\n");
                return CPA_STATUS_FAIL;
        }

        physAddressAligned =
            (CpaPhysicalAddr)LAC_ALIGN_POW2_ROUNDUP(physAddress,
                                                    LAC_64BYTE_ALIGNMENT);

        pSessionDesc = (dc_session_desc_t *)
            /* Move the session pointer by the physical offset
            between aligned and unaligned memory */
            ((Cpa8U *)pSessionHandle + sizeof(void *) +
             (physAddressAligned - physAddress));

        /* Save the aligned pointer in the first bytes (size of LAC_ARCH_UINT)
         * of the session memory */
        *((LAC_ARCH_UINT *)pSessionHandle) = (LAC_ARCH_UINT)pSessionDesc;

        /* Zero the compression session */
        LAC_OS_BZERO(pSessionDesc, sizeof(dc_session_desc_t));

        /* Write the buffer descriptor for context/history */
        if (0 != minContextSize) {
                status = LacBuffDesc_BufferListDescWrite(
                    pContextBuffer,
                    &contextAddrPhys,
                    CPA_FALSE,
                    &(pService->generic_service_info));

                if (status != CPA_STATUS_SUCCESS) {
                        return status;
                }

                pSessionDesc->pContextBuffer = pContextBuffer;
                pSessionDesc->historyBuffSize = historySize;
        }

        pSessionDesc->cumulativeConsumedBytes = 0;

        /* Initialise pSessionDesc */
        pSessionDesc->requestType = DC_REQUEST_FIRST;
        pSessionDesc->huffType = pSessionData->huffType;
        pSessionDesc->compType = pSessionData->compType;
        pSessionDesc->checksumType = pSessionData->checksum;
        pSessionDesc->autoSelectBestHuffmanTree =
            pSessionData->autoSelectBestHuffmanTree;
        pSessionDesc->sessDirection = pSessionData->sessDirection;
        pSessionDesc->sessState = pSessionData->sessState;
        pSessionDesc->compLevel = pSessionData->compLevel;
        pSessionDesc->isDcDp = CPA_FALSE;
        pSessionDesc->minContextSize = minContextSize;
        pSessionDesc->isSopForCompressionProcessed = CPA_FALSE;
        pSessionDesc->isSopForDecompressionProcessed = CPA_FALSE;

        if (CPA_DC_ADLER32 == pSessionDesc->checksumType) {
                pSessionDesc->previousChecksum = 1;
        } else {
                pSessionDesc->previousChecksum = 0;
        }

        if (CPA_DC_STATEFUL == pSessionData->sessState) {
                /* Init the spinlock used to lock the access to the number of
                 * stateful
                 * in-flight requests */
                status = LAC_SPINLOCK_INIT(&(pSessionDesc->sessionLock));
                if (CPA_STATUS_SUCCESS != status) {
                        QAT_UTILS_LOG(
                            "Spinlock init failed for sessionLock.\n");
                        return CPA_STATUS_RESOURCE;
                }
        }

        /* For asynchronous - use the user supplied callback
         * for synchronous - use the internal synchronous callback */
        pSessionDesc->pCompressionCb = ((void *)NULL != (void *)callbackFn) ?
            callbackFn :
            LacSync_GenWakeupSyncCaller;

        /* Reset the pending callback counters */
        qatUtilsAtomicSet(0, &pSessionDesc->pendingStatelessCbCount);
        qatUtilsAtomicSet(0, &pSessionDesc->pendingStatefulCbCount);
        pSessionDesc->pendingDpStatelessCbCount = 0;

        if (CPA_DC_DIR_DECOMPRESS != pSessionData->sessDirection) {
                if ((isDcGen2x(pService)) &&
                    CPA_DC_HT_FULL_DYNAMIC == pSessionData->huffType) {
                        /* Populate the compression section of the content
                         * descriptor */
                        dcCompContentDescPopulate(pService,
                                                  pSessionDesc,
                                                  contextAddrPhys,
                                                  &(pSessionDesc->reqCacheComp),
                                                  ICP_QAT_FW_SLICE_XLAT,
                                                  DC_COMPRESSION_REQUEST);

                        /* Populate the translator section of the content
                         * descriptor */
                        dcTransContentDescPopulate(
                            &(pSessionDesc->reqCacheComp),
                            ICP_QAT_FW_SLICE_DRAM_WR);

                        if (0 != pService->pInterBuffPtrsArrayPhyAddr) {
                                pReqCache = &(pSessionDesc->reqCacheComp);

                                pReqCache->u1.xlt_pars.inter_buff_ptr =
                                    pService->pInterBuffPtrsArrayPhyAddr;
                        }
                } else {
                        dcCompContentDescPopulate(pService,
                                                  pSessionDesc,
                                                  contextAddrPhys,
                                                  &(pSessionDesc->reqCacheComp),
                                                  ICP_QAT_FW_SLICE_DRAM_WR,
                                                  DC_COMPRESSION_REQUEST);
                }
        }

        /* Populate the compression section of the content descriptor for
         * the decompression case or combined */
        if (CPA_DC_DIR_COMPRESS != pSessionData->sessDirection) {
                dcCompContentDescPopulate(pService,
                                          pSessionDesc,
                                          contextAddrPhys,
                                          &(pSessionDesc->reqCacheDecomp),
                                          ICP_QAT_FW_SLICE_DRAM_WR,
                                          DC_DECOMPRESSION_REQUEST);
        }

        if (CPA_DC_STATEFUL == pSessionData->sessState) {
                sessType = ICP_QAT_FW_COMP_STATEFUL_SESSION;

                LAC_OS_BZERO(&pSessionDesc->stateRegistersComp,
                             sizeof(pSessionDesc->stateRegistersComp));

                LAC_OS_BZERO(&pSessionDesc->stateRegistersDecomp,
                             sizeof(pSessionDesc->stateRegistersDecomp));
        }

        /* Get physical address of E2E CRC buffer */
        pSessionDesc->physDataIntegrityCrcs = (icp_qat_addr_width_t)
            LAC_OS_VIRT_TO_PHYS_EXTERNAL(pService->generic_service_info,
                                         &pSessionDesc->dataIntegrityCrcs);
        if (0 == pSessionDesc->physDataIntegrityCrcs) {
                QAT_UTILS_LOG(
                    "Unable to get the physical address of Data Integrity buffer.\n");
                return CPA_STATUS_FAIL;
        }
        /* Initialize default CRC parameters */
        pDataIntegrityCrcs = &pSessionDesc->dataIntegrityCrcs;
        pDataIntegrityCrcs->crc32 = 0;
        pDataIntegrityCrcs->adler32 = 1;

        if (isDcGen2x(pService)) {
                pDataIntegrityCrcs->oCrc32Cpr = DC_INVALID_CRC;
                pDataIntegrityCrcs->iCrc32Cpr = DC_INVALID_CRC;
                pDataIntegrityCrcs->oCrc32Xlt = DC_INVALID_CRC;
                pDataIntegrityCrcs->iCrc32Xlt = DC_INVALID_CRC;
                pDataIntegrityCrcs->xorFlags = DC_XOR_FLAGS_DEFAULT;
                pDataIntegrityCrcs->crcPoly = DC_CRC_POLY_DEFAULT;
                pDataIntegrityCrcs->xorOut = DC_XOR_OUT_DEFAULT;
        } else {
                pDataIntegrityCrcs->iCrc64Cpr = DC_INVALID_CRC;
                pDataIntegrityCrcs->oCrc64Cpr = DC_INVALID_CRC;
                pDataIntegrityCrcs->iCrc64Xlt = DC_INVALID_CRC;
                pDataIntegrityCrcs->oCrc64Xlt = DC_INVALID_CRC;
                pDataIntegrityCrcs->crc64Poly = DC_CRC64_POLY_DEFAULT;
                pDataIntegrityCrcs->xor64Out = DC_XOR64_OUT_DEFAULT;
        }

        /* Initialise seed checksums.
         * It initializes swCrc32I, swCrc32O, too(union).
         */
        pSessionDesc->seedSwCrc.swCrc64I = 0;
        pSessionDesc->seedSwCrc.swCrc64O = 0;

        /* Populate the cmdFlags */
        switch (pSessionDesc->autoSelectBestHuffmanTree) {
        case CPA_DC_ASB_DISABLED:
                break;
        case CPA_DC_ASB_STATIC_DYNAMIC:
                autoSelectBest = ICP_QAT_FW_COMP_AUTO_SELECT_BEST;
                break;
        case CPA_DC_ASB_UNCOMP_STATIC_DYNAMIC_WITH_STORED_HDRS:
                autoSelectBest = ICP_QAT_FW_COMP_AUTO_SELECT_BEST;
                enhancedAutoSelectBest = ICP_QAT_FW_COMP_ENH_AUTO_SELECT_BEST;
                break;
        case CPA_DC_ASB_UNCOMP_STATIC_DYNAMIC_WITH_NO_HDRS:
                autoSelectBest = ICP_QAT_FW_COMP_AUTO_SELECT_BEST;
                enhancedAutoSelectBest = ICP_QAT_FW_COMP_ENH_AUTO_SELECT_BEST;
                disableType0EnhancedAutoSelectBest =
                    ICP_QAT_FW_COMP_DISABLE_TYPE0_ENH_AUTO_SELECT_BEST;
                break;
        case CPA_DC_ASB_ENABLED:
                if (pService->comp_device_data.asbEnableSupport == CPA_FALSE) {
                        autoSelectBest = ICP_QAT_FW_COMP_AUTO_SELECT_BEST;
                        enhancedAutoSelectBest =
                            ICP_QAT_FW_COMP_ENH_AUTO_SELECT_BEST;
                }
                break;
        default:
                break;
        }

        rpCmdFlags = ICP_QAT_FW_COMP_REQ_PARAM_FLAGS_BUILD(
            ICP_QAT_FW_COMP_SOP,
            ICP_QAT_FW_COMP_EOP,
            ICP_QAT_FW_COMP_BFINAL,
            ICP_QAT_FW_COMP_NO_CNV,
            ICP_QAT_FW_COMP_NO_CNV_RECOVERY,
            ICP_QAT_FW_COMP_NO_CNV_DFX,
            ICP_QAT_FW_COMP_CRC_MODE_LEGACY);

        cmdFlags =
            ICP_QAT_FW_COMP_FLAGS_BUILD(sessType,
                                        autoSelectBest,
                                        enhancedAutoSelectBest,
                                        disableType0EnhancedAutoSelectBest,
                                        secureRam);

        if (CPA_DC_DIR_DECOMPRESS != pSessionData->sessDirection) {
                status = dcGetCompressCommandId(pService,
                                                pSessionData,
                                                (Cpa8U *)&dcCmdId);
                if (CPA_STATUS_SUCCESS != status) {
                        QAT_UTILS_LOG(
                            "Couldn't get compress command ID for current "
                            "session data.");

                        return status;
                }
                pReqCache = &(pSessionDesc->reqCacheComp);
                pReqCache->comp_pars.req_par_flags = rpCmdFlags;
                pReqCache->comp_pars.crc.legacy.initial_adler = 1;
                pReqCache->comp_pars.crc.legacy.initial_crc32 = 0;

                /* Populate header of the common request message */
                SalQatMsg_CmnHdrWrite((icp_qat_fw_comn_req_t *)pReqCache,
                                      ICP_QAT_FW_COMN_REQ_CPM_FW_COMP,
                                      (uint8_t)dcCmdId,
                                      cmnRequestFlags,
                                      cmdFlags);
        }

        if (CPA_DC_DIR_COMPRESS != pSessionData->sessDirection) {
                status = dcGetDecompressCommandId(pService,
                                                  pSessionData,
                                                  (Cpa8U *)&dcCmdId);
                if (CPA_STATUS_SUCCESS != status) {
                        QAT_UTILS_LOG(
                            "Couldn't get decompress command ID for current "
                            "session data.");

                        return status;
                }
                pReqCache = &(pSessionDesc->reqCacheDecomp);
                pReqCache->comp_pars.req_par_flags = rpCmdFlags;
                pReqCache->comp_pars.crc.legacy.initial_adler = 1;
                pReqCache->comp_pars.crc.legacy.initial_crc32 = 0;

                /* Populate header of the common request message */
                SalQatMsg_CmnHdrWrite((icp_qat_fw_comn_req_t *)pReqCache,
                                      ICP_QAT_FW_COMN_REQ_CPM_FW_COMP,
                                      (uint8_t)dcCmdId,
                                      cmnRequestFlags,
                                      cmdFlags);
        }

        return status;
}

CpaStatus
cpaDcInitSession(CpaInstanceHandle dcInstance,
                 CpaDcSessionHandle pSessionHandle,
                 CpaDcSessionSetupData *pSessionData,
                 CpaBufferList *pContextBuffer,
                 CpaDcCallbackFn callbackFn)
{
        CpaInstanceHandle insHandle = NULL;
        sal_compression_service_t *pService = NULL;

        if (CPA_INSTANCE_HANDLE_SINGLE == dcInstance) {
                insHandle = dcGetFirstHandle();
        } else {
                insHandle = dcInstance;
        }

        LAC_CHECK_INSTANCE_HANDLE(insHandle);
        SAL_CHECK_INSTANCE_TYPE(insHandle, SAL_SERVICE_TYPE_COMPRESSION);

        pService = (sal_compression_service_t *)insHandle;

        /* Check if SAL is initialised otherwise return an error */
        SAL_RUNNING_CHECK(pService);

        return dcInitSession(insHandle,
                             pSessionHandle,
                             pSessionData,
                             pContextBuffer,
                             callbackFn);
}

CpaStatus
cpaDcResetSession(const CpaInstanceHandle dcInstance,
                  CpaDcSessionHandle pSessionHandle)
{
        CpaStatus status = CPA_STATUS_SUCCESS;
        CpaInstanceHandle insHandle = NULL;
        sal_compression_service_t *pService = NULL;
        dc_session_desc_t *pSessionDesc = NULL;
        Cpa64U numPendingStateless = 0;
        Cpa64U numPendingStateful = 0;
        icp_comms_trans_handle trans_handle = NULL;
        dc_integrity_crc_fw_t *pDataIntegrityCrcs = NULL;
        dc_sw_checksums_t *pSwCrcs = NULL;

        LAC_CHECK_NULL_PARAM(pSessionHandle);
        pSessionDesc = DC_SESSION_DESC_FROM_CTX_GET(pSessionHandle);
        LAC_CHECK_NULL_PARAM(pSessionDesc);

        if (CPA_TRUE == pSessionDesc->isDcDp) {
                insHandle = dcInstance;
        } else {
                if (CPA_INSTANCE_HANDLE_SINGLE == dcInstance) {
                        insHandle = dcGetFirstHandle();
                } else {
                        insHandle = dcInstance;
                }
        }
        LAC_CHECK_NULL_PARAM(insHandle);
        SAL_CHECK_INSTANCE_TYPE(insHandle, SAL_SERVICE_TYPE_COMPRESSION);
        /* Check if SAL is running otherwise return an error */
        SAL_RUNNING_CHECK(insHandle);
        if (CPA_TRUE == pSessionDesc->isDcDp) {
                trans_handle = ((sal_compression_service_t *)insHandle)
                                   ->trans_handle_compression_tx;
                if (CPA_TRUE == icp_adf_queueDataToSend(trans_handle)) {
                        /* Process the remaining messages on the ring */
                        SalQatMsg_updateQueueTail(trans_handle);
                        QAT_UTILS_LOG(
                            "There are remaining messages on the ring\n");
                        return CPA_STATUS_RETRY;
                }

                /* Check if there are stateless pending requests */
                if (0 != pSessionDesc->pendingDpStatelessCbCount) {
                        QAT_UTILS_LOG(
                            "There are %llu stateless DP requests pending.\n",
                            (unsigned long long)
                                pSessionDesc->pendingDpStatelessCbCount);
                        return CPA_STATUS_RETRY;
                }
        } else {
                numPendingStateless =
                    qatUtilsAtomicGet(&(pSessionDesc->pendingStatelessCbCount));
                numPendingStateful =
                    qatUtilsAtomicGet(&(pSessionDesc->pendingStatefulCbCount));
                /* Check if there are stateless pending requests */
                if (0 != numPendingStateless) {
                        QAT_UTILS_LOG(
                            "There are %llu stateless requests pending.\n",
                            (unsigned long long)numPendingStateless);
                        return CPA_STATUS_RETRY;
                }
                /* Check if there are stateful pending requests */
                if (0 != numPendingStateful) {
                        QAT_UTILS_LOG(
                            "There are %llu stateful requests pending.\n",
                            (unsigned long long)numPendingStateful);
                        return CPA_STATUS_RETRY;
                }

                /* Reset pSessionDesc */
                pSessionDesc->requestType = DC_REQUEST_FIRST;
                pSessionDesc->cumulativeConsumedBytes = 0;
                if (CPA_DC_ADLER32 == pSessionDesc->checksumType) {
                        pSessionDesc->previousChecksum = 1;
                } else {
                        pSessionDesc->previousChecksum = 0;
                }
                pSessionDesc->cnvErrorInjection = ICP_QAT_FW_COMP_NO_CNV_DFX;

                /* Reset integrity CRCs to default parameters. */
                pDataIntegrityCrcs = &pSessionDesc->dataIntegrityCrcs;
                memset(pDataIntegrityCrcs, 0, sizeof(dc_integrity_crc_fw_t));
                pDataIntegrityCrcs->adler32 = 1;

                pService = (sal_compression_service_t *)insHandle;
                if (isDcGen2x(pService)) {
                        pDataIntegrityCrcs->xorFlags = DC_XOR_FLAGS_DEFAULT;
                        pDataIntegrityCrcs->crcPoly = DC_CRC_POLY_DEFAULT;
                        pDataIntegrityCrcs->xorOut = DC_XOR_OUT_DEFAULT;
                } else {
                        pDataIntegrityCrcs->crc64Poly = DC_CRC64_POLY_DEFAULT;
                        pDataIntegrityCrcs->xor64Out = DC_XOR64_OUT_DEFAULT;
                }

                /* Reset seed SW checksums. */
                pSwCrcs = &pSessionDesc->seedSwCrc;
                memset(pSwCrcs, 0, sizeof(dc_sw_checksums_t));

                /* Reset integrity SW checksums. */
                pSwCrcs = &pSessionDesc->integritySwCrc;
                memset(pSwCrcs, 0, sizeof(dc_sw_checksums_t));
        }

        /* Reset the pending callback counters */
        qatUtilsAtomicSet(0, &pSessionDesc->pendingStatelessCbCount);
        qatUtilsAtomicSet(0, &pSessionDesc->pendingStatefulCbCount);
        pSessionDesc->pendingDpStatelessCbCount = 0;
        if (CPA_DC_STATEFUL == pSessionDesc->sessState) {
                LAC_OS_BZERO(&pSessionDesc->stateRegistersComp,
                             sizeof(pSessionDesc->stateRegistersComp));
                LAC_OS_BZERO(&pSessionDesc->stateRegistersDecomp,
                             sizeof(pSessionDesc->stateRegistersDecomp));
        }
        return status;
}

CpaStatus
cpaDcResetXXHashState(const CpaInstanceHandle dcInstance,
                      CpaDcSessionHandle pSessionHandle)
{
        return CPA_STATUS_UNSUPPORTED;
}

CpaStatus
cpaDcUpdateSession(const CpaInstanceHandle dcInstance,
                   CpaDcSessionHandle pSessionHandle,
                   CpaDcSessionUpdateData *pUpdateSessionData)
{
        return CPA_STATUS_UNSUPPORTED;
}

CpaStatus
cpaDcRemoveSession(const CpaInstanceHandle dcInstance,
                   CpaDcSessionHandle pSessionHandle)
{
        CpaStatus status = CPA_STATUS_SUCCESS;
        CpaInstanceHandle insHandle = NULL;
        dc_session_desc_t *pSessionDesc = NULL;
        Cpa64U numPendingStateless = 0;
        Cpa64U numPendingStateful = 0;
        icp_comms_trans_handle trans_handle = NULL;

        LAC_CHECK_NULL_PARAM(pSessionHandle);
        pSessionDesc = DC_SESSION_DESC_FROM_CTX_GET(pSessionHandle);
        LAC_CHECK_NULL_PARAM(pSessionDesc);

        if (CPA_TRUE == pSessionDesc->isDcDp) {
                insHandle = dcInstance;
        } else {
                if (CPA_INSTANCE_HANDLE_SINGLE == dcInstance) {
                        insHandle = dcGetFirstHandle();
                } else {
                        insHandle = dcInstance;
                }
        }

        LAC_CHECK_NULL_PARAM(insHandle);
        SAL_CHECK_INSTANCE_TYPE(insHandle, SAL_SERVICE_TYPE_COMPRESSION);

        /* Check if SAL is running otherwise return an error */
        SAL_RUNNING_CHECK(insHandle);

        if (CPA_TRUE == pSessionDesc->isDcDp) {
                trans_handle = ((sal_compression_service_t *)insHandle)
                                   ->trans_handle_compression_tx;

                if (CPA_TRUE == icp_adf_queueDataToSend(trans_handle)) {
                        /* Process the remaining messages on the ring */
                        SalQatMsg_updateQueueTail(trans_handle);
                        QAT_UTILS_LOG(
                            "There are remaining messages on the ring.\n");
                        return CPA_STATUS_RETRY;
                }

                /* Check if there are stateless pending requests */
                if (0 != pSessionDesc->pendingDpStatelessCbCount) {
                        QAT_UTILS_LOG(
                            "There are %llu stateless DP requests pending.\n",
                            (unsigned long long)
                                pSessionDesc->pendingDpStatelessCbCount);
                        return CPA_STATUS_RETRY;
                }
        } else {
                numPendingStateless =
                    qatUtilsAtomicGet(&(pSessionDesc->pendingStatelessCbCount));
                numPendingStateful =
                    qatUtilsAtomicGet(&(pSessionDesc->pendingStatefulCbCount));

                /* Check if there are stateless pending requests */
                if (0 != numPendingStateless) {
                        QAT_UTILS_LOG(
                            "There are %llu stateless requests pending.\n",
                            (unsigned long long)numPendingStateless);
                        status = CPA_STATUS_RETRY;
                }

                /* Check if there are stateful pending requests */
                if (0 != numPendingStateful) {
                        QAT_UTILS_LOG(
                            "There are %llu stateful requests pending.\n",
                            (unsigned long long)numPendingStateful);
                        status = CPA_STATUS_RETRY;
                }
                if ((CPA_DC_STATEFUL == pSessionDesc->sessState) &&
                    (CPA_STATUS_SUCCESS == status)) {
                        LAC_SPINLOCK_DESTROY(&(pSessionDesc->sessionLock));
                }
        }

        return status;
}

CpaStatus
dcGetSessionSize(CpaInstanceHandle dcInstance,
                 CpaDcSessionSetupData *pSessionData,
                 Cpa32U *pSessionSize,
                 Cpa32U *pContextSize)
{

        CpaStatus status = CPA_STATUS_SUCCESS;
        CpaInstanceHandle insHandle = NULL;

        if (CPA_INSTANCE_HANDLE_SINGLE == dcInstance) {
                insHandle = dcGetFirstHandle();
        } else {
                insHandle = dcInstance;
        }

        /* Check parameters */
        LAC_CHECK_NULL_PARAM(insHandle);
        LAC_CHECK_NULL_PARAM(pSessionData);
        LAC_CHECK_NULL_PARAM(pSessionSize);

        if (dcCheckSessionData(pSessionData, insHandle) != CPA_STATUS_SUCCESS) {
                return CPA_STATUS_INVALID_PARAM;
        }

        /* Get session size for session data */
        *pSessionSize = sizeof(dc_session_desc_t) + LAC_64BYTE_ALIGNMENT +
            sizeof(LAC_ARCH_UINT);

        if (NULL != pContextSize) {
                status =
                    dcGetContextSize(insHandle, pSessionData, pContextSize);

                if (CPA_STATUS_SUCCESS != status) {
                        QAT_UTILS_LOG(
                            "Unable to get the context size of the session.\n");
                        return CPA_STATUS_FAIL;
                }
        }

        return CPA_STATUS_SUCCESS;
}

CpaStatus
cpaDcGetSessionSize(CpaInstanceHandle dcInstance,
                    CpaDcSessionSetupData *pSessionData,
                    Cpa32U *pSessionSize,
                    Cpa32U *pContextSize)
{

        LAC_CHECK_NULL_PARAM(pContextSize);

        return dcGetSessionSize(dcInstance,
                                pSessionData,
                                pSessionSize,
                                pContextSize);
}

CpaStatus
dcSetCnvError(CpaInstanceHandle dcInstance, CpaDcSessionHandle pSessionHandle)
{
        LAC_CHECK_NULL_PARAM(pSessionHandle);

        dc_session_desc_t *pSessionDesc = NULL;
        CpaInstanceHandle insHandle = NULL;
        sal_compression_service_t *pService = NULL;

        if (CPA_INSTANCE_HANDLE_SINGLE == dcInstance) {
                insHandle = dcGetFirstHandle();
        } else {
                insHandle = dcInstance;
        }

        pService = (sal_compression_service_t *)insHandle;

        if (isDcGen2x(pService)) {
                QAT_UTILS_LOG("Unsupported compression feature.\n");
                return CPA_STATUS_UNSUPPORTED;
        }
        pSessionDesc = DC_SESSION_DESC_FROM_CTX_GET(pSessionHandle);

        LAC_CHECK_NULL_PARAM(pSessionDesc);

        pSessionDesc->cnvErrorInjection = ICP_QAT_FW_COMP_CNV_DFX;

        return CPA_STATUS_SUCCESS;
}