#include "cpa.h"
#include "cpa_dc.h"
#include "cpa_dc_dp.h"
#include "dc_session.h"
#include "dc_datapath.h"
#include "sal_statistics.h"
#include "lac_common.h"
#include "lac_mem.h"
#include "lac_mem_pools.h"
#include "sal_types_compression.h"
#include "dc_stats.h"
#include "lac_buffer_desc.h"
#include "lac_sal.h"
#include "lac_log.h"
#include "lac_sync.h"
#include "sal_service_state.h"
#include "sal_qat_cmn_msg.h"
#include "sal_hw_gen.h"
#include "dc_error_counter.h"
#define DC_COMP_MAX_BUFF_SIZE (1024 * 64)
static QatUtilsAtomic dcErrorCount[MAX_DC_ERROR_TYPE];
void
dcErrorLog(CpaDcReqStatus dcError)
{
Cpa32U absError = 0;
absError = abs(dcError);
if ((dcError < CPA_DC_OK) && (absError < MAX_DC_ERROR_TYPE)) {
qatUtilsAtomicInc(&(dcErrorCount[absError]));
}
}
Cpa64U
getDcErrorCounter(CpaDcReqStatus dcError)
{
Cpa32U absError = 0;
absError = abs(dcError);
if (!(dcError >= CPA_DC_OK || dcError < CPA_DC_EMPTY_DYM_BLK)) {
return (Cpa64U)qatUtilsAtomicGet(&dcErrorCount[absError]);
}
return 0;
}
static inline void
dcUpdateXltOverflowChecksumsGen4(const dc_compression_cookie_t *pCookie,
const icp_qat_fw_resp_comp_pars_t *pRespPars,
CpaDcRqResults *pDcResults)
{
dc_session_desc_t *pSessionDesc =
DC_SESSION_DESC_FROM_CTX_GET(pCookie->pSessionHandle);
if (CPA_DC_CRC32 == pSessionDesc->checksumType) {
pDcResults->checksum = pRespPars->crc.legacy.curr_crc32;
} else if (CPA_DC_ADLER32 == pSessionDesc->checksumType) {
pDcResults->checksum = pRespPars->crc.legacy.curr_adler_32;
}
}
void
dcCompression_ProcessCallback(void *pRespMsg)
{
CpaStatus status = CPA_STATUS_SUCCESS;
icp_qat_fw_comp_resp_t *pCompRespMsg = NULL;
void *callbackTag = NULL;
Cpa64U *pReqData = NULL;
CpaDcDpOpData *pResponse = NULL;
CpaDcRqResults *pResults = NULL;
CpaDcCallbackFn pCbFunc = NULL;
dc_session_desc_t *pSessionDesc = NULL;
sal_compression_service_t *pService = NULL;
dc_compression_cookie_t *pCookie = NULL;
CpaDcOpData *pOpData = NULL;
CpaBoolean cmpPass = CPA_TRUE, xlatPass = CPA_TRUE;
CpaBoolean isDcDp = CPA_FALSE;
CpaBoolean integrityCrcCheck = CPA_FALSE;
CpaBoolean verifyHwIntegrityCrcs = CPA_FALSE;
Cpa8U cmpErr = ERR_CODE_NO_ERROR, xlatErr = ERR_CODE_NO_ERROR;
dc_request_dir_t compDecomp = DC_COMPRESSION_REQUEST;
Cpa8U opStatus = ICP_QAT_FW_COMN_STATUS_FLAG_OK;
Cpa8U hdrFlags = 0;
pCompRespMsg = (icp_qat_fw_comp_resp_t *)pRespMsg;
if (!(pCompRespMsg)) {
QAT_UTILS_LOG("pCompRespMsg is NULL\n");
return;
}
LAC_MEM_SHARED_READ_TO_PTR(pCompRespMsg->opaque_data, pReqData);
if (!(pReqData)) {
QAT_UTILS_LOG("pReqData is NULL\n");
return;
}
pCookie = (dc_compression_cookie_t *)pReqData;
pSessionDesc = DC_SESSION_DESC_FROM_CTX_GET(pCookie->pSessionHandle);
pService = (sal_compression_service_t *)(pCookie->dcInstance);
isDcDp = pSessionDesc->isDcDp;
if (CPA_TRUE == isDcDp) {
pResponse = (CpaDcDpOpData *)pReqData;
pResults = &(pResponse->results);
if (CPA_DC_DIR_DECOMPRESS == pSessionDesc->sessDirection) {
compDecomp = DC_DECOMPRESSION_REQUEST;
}
pCookie = NULL;
} else {
pResults = pCookie->pResults;
callbackTag = pCookie->callbackTag;
pCbFunc = pCookie->pSessionDesc->pCompressionCb;
compDecomp = pCookie->compDecomp;
pOpData = pCookie->pDcOpData;
}
opStatus = pCompRespMsg->comn_resp.comn_status;
if (NULL != pOpData) {
verifyHwIntegrityCrcs = pOpData->verifyHwIntegrityCrcs;
integrityCrcCheck = pOpData->integrityCrcCheck;
}
hdrFlags = pCompRespMsg->comn_resp.hdr_flags;
cmpErr = pCompRespMsg->comn_resp.comn_error.s1.cmp_err_code;
if (ICP_QAT_FW_COMN_RESP_UNSUPPORTED_REQUEST_STAT_GET(opStatus)) {
QAT_UTILS_LOG("Compression feature not supported\n");
status = CPA_STATUS_UNSUPPORTED;
pResults->status = (Cpa8S)cmpErr;
pResults->consumed = 0;
pResults->produced = 0;
if (CPA_TRUE == isDcDp) {
if (pResponse)
pResponse->responseStatus =
CPA_STATUS_UNSUPPORTED;
(pService->pDcDpCb)(pResponse);
} else {
Lac_MemPoolEntryFree(pCookie);
pCookie = NULL;
if (NULL != pCbFunc) {
pCbFunc(callbackTag, status);
}
}
if (DC_COMPRESSION_REQUEST == compDecomp) {
COMPRESSION_STAT_INC(numCompCompletedErrors, pService);
} else {
COMPRESSION_STAT_INC(numDecompCompletedErrors,
pService);
}
return;
} else {
cmpPass =
(CpaBoolean)(ICP_QAT_FW_COMN_STATUS_FLAG_OK ==
ICP_QAT_FW_COMN_RESP_CMP_STAT_GET(opStatus));
}
if (isDcGen2x(pService)) {
if (CPA_DC_INCOMPLETE_FILE_ERR == (Cpa8S)cmpErr) {
cmpPass = CPA_TRUE;
cmpErr = ERR_CODE_NO_ERROR;
}
} else {
if ((pSessionDesc->compType == CPA_DC_DEFLATE) &&
(CPA_DC_INCOMPLETE_FILE_ERR == (Cpa8S)cmpErr)) {
cmpPass = CPA_TRUE;
cmpErr = ERR_CODE_NO_ERROR;
}
}
if (ERR_CODE_SSM_ERROR == (Cpa8S)cmpErr) {
QAT_UTILS_LOG(
"Slice hang detected on the compression slice.\n");
} else if (ERR_CODE_ENDPOINT_ERROR == (Cpa8S)cmpErr) {
QAT_UTILS_LOG(
"PCIe End Point Push/Pull or TI/RI Parity error detected.\n");
}
pResults->status = (Cpa8S)cmpErr;
if ((DC_COMPRESSION_REQUEST == compDecomp) &&
(CPA_DC_HT_FULL_DYNAMIC == pSessionDesc->huffType)) {
xlatPass =
(CpaBoolean)(ICP_QAT_FW_COMN_STATUS_FLAG_OK ==
ICP_QAT_FW_COMN_RESP_XLAT_STAT_GET(opStatus));
xlatErr = pCompRespMsg->comn_resp.comn_error.s1.xlat_err_code;
if ((CPA_DC_OK == pResults->status) ||
(CPA_DC_FATALERR == (Cpa8S)xlatErr)) {
pResults->status = (Cpa8S)xlatErr;
}
}
dcErrorLog(pResults->status);
if (CPA_FALSE == isDcDp) {
if (CPA_DC_FLUSH_FINAL == pCookie->flushFlag && cmpPass &&
xlatPass) {
pSessionDesc->requestType = DC_REQUEST_FIRST;
} else {
pSessionDesc->requestType = DC_REQUEST_SUBSEQUENT;
}
if ((CPA_DC_STATEFUL == pSessionDesc->sessState) ||
((CPA_DC_STATELESS == pSessionDesc->sessState) &&
(DC_COMPRESSION_REQUEST == compDecomp))) {
if (CPA_DC_OVERFLOW == (Cpa8S)cmpErr)
cmpPass = CPA_TRUE;
if (CPA_DC_OVERFLOW == (Cpa8S)xlatErr) {
if (isDcGen4x(pService) &&
(CPA_TRUE ==
pService->comp_device_data
.translatorOverflow)) {
pResults->consumed =
pCompRespMsg->comp_resp_pars
.input_byte_counter;
dcUpdateXltOverflowChecksumsGen4(
pCookie,
&pCompRespMsg->comp_resp_pars,
pResults);
}
xlatPass = CPA_TRUE;
}
}
} else {
if (CPA_DC_OVERFLOW == (Cpa8S)cmpErr) {
cmpPass = CPA_FALSE;
}
if (CPA_DC_OVERFLOW == (Cpa8S)xlatErr) {
xlatPass = CPA_FALSE;
}
}
if ((CPA_TRUE == cmpPass) && (CPA_TRUE == xlatPass)) {
pResults->consumed =
pCompRespMsg->comp_resp_pars.input_byte_counter;
pResults->produced =
pCompRespMsg->comp_resp_pars.output_byte_counter;
pSessionDesc->cumulativeConsumedBytes += pResults->consumed;
if (CPA_TRUE ==
pService->generic_service_info.integrityCrcCheck &&
CPA_TRUE == integrityCrcCheck) {
pSessionDesc->previousChecksum =
pSessionDesc->seedSwCrc.swCrc32I;
} else if (CPA_DC_OVERFLOW != (Cpa8S)xlatErr) {
if (CPA_DC_CRC32 == pSessionDesc->checksumType) {
pResults->checksum =
pCompRespMsg->comp_resp_pars.crc.legacy
.curr_crc32;
} else if (CPA_DC_ADLER32 ==
pSessionDesc->checksumType) {
pResults->checksum =
pCompRespMsg->comp_resp_pars.crc.legacy
.curr_adler_32;
}
pSessionDesc->previousChecksum = pResults->checksum;
}
if (DC_DECOMPRESSION_REQUEST == compDecomp) {
pResults->endOfLastBlock =
(ICP_QAT_FW_COMN_STATUS_CMP_END_OF_LAST_BLK_FLAG_SET ==
ICP_QAT_FW_COMN_RESP_CMP_END_OF_LAST_BLK_FLAG_GET(
opStatus));
} else {
pResults->dataUncompressed =
ICP_QAT_FW_COMN_HDR_ST_BLK_FLAG_GET(hdrFlags);
}
if ((CPA_DC_OVERFLOW != (Cpa8S)xlatErr) &&
(CPA_TRUE == verifyHwIntegrityCrcs)) {
pSessionDesc->previousChecksum =
pSessionDesc->seedSwCrc.swCrc32I;
}
if ((DC_COMPRESSION_REQUEST == compDecomp) &&
ICP_QAT_FW_COMN_HDR_CNV_FLAG_GET(hdrFlags) &&
ICP_QAT_FW_COMN_HDR_CNVNR_FLAG_GET(hdrFlags)) {
COMPRESSION_STAT_INC(numCompCnvErrorsRecovered,
pService);
}
if (CPA_TRUE == isDcDp) {
if (pResponse)
pResponse->responseStatus = CPA_STATUS_SUCCESS;
} else {
if (DC_COMPRESSION_REQUEST == compDecomp) {
COMPRESSION_STAT_INC(numCompCompleted,
pService);
} else {
COMPRESSION_STAT_INC(numDecompCompleted,
pService);
}
}
} else {
#ifdef ICP_DC_RETURN_COUNTERS_ON_ERROR
pResults->consumed =
pCompRespMsg->comp_resp_pars.input_byte_counter;
pResults->produced =
pCompRespMsg->comp_resp_pars.output_byte_counter;
if (CPA_DC_STATEFUL == pSessionDesc->sessState) {
pSessionDesc->cumulativeConsumedBytes +=
pResults->consumed;
} else {
pSessionDesc->cumulativeConsumedBytes =
pResults->consumed;
}
#else
pResults->consumed = 0;
pResults->produced = 0;
#endif
if (CPA_DC_OVERFLOW == pResults->status &&
CPA_DC_STATELESS == pSessionDesc->sessState) {
QAT_UTILS_LOG(
"Unrecoverable error: stateless overflow. You may need to increase the size of your destination buffer.\n");
}
if (CPA_TRUE == isDcDp) {
if (pResponse)
pResponse->responseStatus = CPA_STATUS_FAIL;
} else {
if (CPA_DC_OK != pResults->status &&
CPA_DC_INCOMPLETE_FILE_ERR != pResults->status) {
status = CPA_STATUS_FAIL;
}
if (DC_COMPRESSION_REQUEST == compDecomp) {
COMPRESSION_STAT_INC(numCompCompletedErrors,
pService);
} else {
COMPRESSION_STAT_INC(numDecompCompletedErrors,
pService);
}
}
}
if (CPA_TRUE == isDcDp) {
pSessionDesc->pendingDpStatelessCbCount--;
(pService->pDcDpCb)(pResponse);
} else {
if (CPA_DC_STATELESS == pSessionDesc->sessState) {
qatUtilsAtomicDec(
&(pCookie->pSessionDesc->pendingStatelessCbCount));
} else if (0 !=
qatUtilsAtomicGet(&pCookie->pSessionDesc
->pendingStatefulCbCount)) {
qatUtilsAtomicDec(
&(pCookie->pSessionDesc->pendingStatefulCbCount));
}
Lac_MemPoolEntryFree(pCookie);
pCookie = NULL;
if (NULL != pCbFunc) {
pCbFunc(callbackTag, status);
}
}
}
CpaStatus
dcCheckOpData(sal_compression_service_t *pService, CpaDcOpData *pOpData)
{
CpaDcSkipMode skipMode = 0;
if ((pOpData->flushFlag < CPA_DC_FLUSH_NONE) ||
(pOpData->flushFlag > CPA_DC_FLUSH_FULL)) {
LAC_INVALID_PARAM_LOG("Invalid flushFlag value");
return CPA_STATUS_INVALID_PARAM;
}
skipMode = pOpData->inputSkipData.skipMode;
if ((skipMode < CPA_DC_SKIP_DISABLED) ||
(skipMode > CPA_DC_SKIP_STRIDE)) {
LAC_INVALID_PARAM_LOG("Invalid input skip mode value");
return CPA_STATUS_INVALID_PARAM;
}
skipMode = pOpData->outputSkipData.skipMode;
if ((skipMode < CPA_DC_SKIP_DISABLED) ||
(skipMode > CPA_DC_SKIP_STRIDE)) {
LAC_INVALID_PARAM_LOG("Invalid output skip mode value");
return CPA_STATUS_INVALID_PARAM;
}
if (pOpData->integrityCrcCheck == CPA_FALSE &&
pOpData->verifyHwIntegrityCrcs == CPA_TRUE) {
LAC_INVALID_PARAM_LOG(
"integrityCrcCheck must be set to true"
"in order to enable verifyHwIntegrityCrcs");
return CPA_STATUS_INVALID_PARAM;
}
if (pOpData->integrityCrcCheck != CPA_TRUE &&
pOpData->integrityCrcCheck != CPA_FALSE) {
LAC_INVALID_PARAM_LOG("Invalid integrityCrcCheck value");
return CPA_STATUS_INVALID_PARAM;
}
if (pOpData->verifyHwIntegrityCrcs != CPA_TRUE &&
pOpData->verifyHwIntegrityCrcs != CPA_FALSE) {
LAC_INVALID_PARAM_LOG("Invalid verifyHwIntegrityCrcs value");
return CPA_STATUS_INVALID_PARAM;
}
if (pOpData->compressAndVerify != CPA_TRUE &&
pOpData->compressAndVerify != CPA_FALSE) {
LAC_INVALID_PARAM_LOG("Invalid cnv decompress check value");
return CPA_STATUS_INVALID_PARAM;
}
if (CPA_TRUE == pOpData->integrityCrcCheck &&
CPA_FALSE == pService->generic_service_info.integrityCrcCheck) {
LAC_INVALID_PARAM_LOG("Integrity CRC check is not "
"supported on this device");
return CPA_STATUS_INVALID_PARAM;
}
if (CPA_TRUE == pOpData->integrityCrcCheck &&
NULL == pOpData->pCrcData) {
LAC_INVALID_PARAM_LOG("Integrity CRC data structure "
"not initialized in CpaDcOpData");
return CPA_STATUS_INVALID_PARAM;
}
return CPA_STATUS_SUCCESS;
}
static CpaStatus
dcCheckSourceData(CpaDcSessionHandle pSessionHandle,
CpaBufferList *pSrcBuff,
CpaBufferList *pDestBuff,
CpaDcRqResults *pResults,
CpaDcFlush flushFlag,
Cpa64U srcBuffSize,
CpaDcSkipData *skipData)
{
dc_session_desc_t *pSessionDesc = NULL;
LAC_CHECK_NULL_PARAM(pSessionHandle);
LAC_CHECK_NULL_PARAM(pSrcBuff);
LAC_CHECK_NULL_PARAM(pDestBuff);
LAC_CHECK_NULL_PARAM(pResults);
pSessionDesc = DC_SESSION_DESC_FROM_CTX_GET(pSessionHandle);
if (NULL == pSessionDesc) {
LAC_INVALID_PARAM_LOG("Session handle not as expected");
return CPA_STATUS_INVALID_PARAM;
}
if ((flushFlag < CPA_DC_FLUSH_NONE) ||
(flushFlag > CPA_DC_FLUSH_FULL)) {
LAC_INVALID_PARAM_LOG("Invalid flushFlag value");
return CPA_STATUS_INVALID_PARAM;
}
if (pSrcBuff == pDestBuff) {
LAC_INVALID_PARAM_LOG("In place operation not supported");
return CPA_STATUS_INVALID_PARAM;
}
if ((CPA_DC_STATELESS == pSessionDesc->sessState) &&
(0 == srcBuffSize) && (NULL == skipData)) {
LAC_INVALID_PARAM_LOG(
"The source buffer size needs to be greater than "
"zero bytes for stateless sessions");
return CPA_STATUS_INVALID_PARAM;
}
if (srcBuffSize > DC_BUFFER_MAX_SIZE) {
LAC_INVALID_PARAM_LOG(
"The source buffer size needs to be less than or "
"equal to 2^32-1 bytes");
return CPA_STATUS_INVALID_PARAM;
}
return CPA_STATUS_SUCCESS;
}
static CpaStatus
dcCheckDestinationData(sal_compression_service_t *pService,
CpaDcSessionHandle pSessionHandle,
CpaBufferList *pDestBuff,
dc_request_dir_t compDecomp)
{
dc_session_desc_t *pSessionDesc = NULL;
Cpa64U destBuffSize = 0;
LAC_CHECK_NULL_PARAM(pSessionHandle);
LAC_CHECK_NULL_PARAM(pDestBuff);
pSessionDesc = DC_SESSION_DESC_FROM_CTX_GET(pSessionHandle);
if (NULL == pSessionDesc) {
LAC_INVALID_PARAM_LOG("Session handle not as expected");
return CPA_STATUS_INVALID_PARAM;
}
if (LacBuffDesc_BufferListVerify(pDestBuff,
&destBuffSize,
LAC_NO_ALIGNMENT_SHIFT) !=
CPA_STATUS_SUCCESS) {
LAC_INVALID_PARAM_LOG(
"Invalid destination buffer list parameter");
return CPA_STATUS_INVALID_PARAM;
}
if (destBuffSize > DC_BUFFER_MAX_SIZE) {
LAC_INVALID_PARAM_LOG(
"The destination buffer size needs to be less "
"than or equal to 2^32-1 bytes");
return CPA_STATUS_INVALID_PARAM;
}
if (CPA_TRUE == pSessionDesc->isDcDp) {
LAC_INVALID_PARAM_LOG(
"The session type should not be data plane");
return CPA_STATUS_INVALID_PARAM;
}
if (DC_COMPRESSION_REQUEST == compDecomp) {
if (CPA_DC_HT_FULL_DYNAMIC == pSessionDesc->huffType) {
if ((isDcGen2x(pService)) &&
((0 == pService->pInterBuffPtrsArrayPhyAddr) ||
(NULL == pService->pInterBuffPtrsArray))) {
LAC_LOG_ERROR(
"No intermediate buffer defined for this instance "
"- see cpaDcStartInstance");
return CPA_STATUS_INVALID_PARAM;
}
if (destBuffSize < DC_DEST_BUFFER_DYN_MIN_SIZE) {
LAC_INVALID_PARAM_LOG(
"Destination buffer size should be "
"greater or equal to 128B");
return CPA_STATUS_INVALID_PARAM;
}
} else
{
if (destBuffSize <
pService->comp_device_data.minOutputBuffSize) {
LAC_INVALID_PARAM_LOG1(
"Destination buffer size should be "
"greater or equal to %d bytes",
pService->comp_device_data
.minOutputBuffSize);
return CPA_STATUS_INVALID_PARAM;
}
}
} else {
if (destBuffSize < DC_DEST_BUFFER_DEC_MIN_SIZE) {
LAC_INVALID_PARAM_LOG(
"Destination buffer size should be "
"greater than 0 bytes");
return CPA_STATUS_INVALID_PARAM;
}
}
return CPA_STATUS_SUCCESS;
}
static void
dcCompRequestParamsPopulate(icp_qat_fw_comp_req_params_t *pCompReqParams,
dc_compression_cookie_t *pCookie)
{
pCompReqParams->comp_len = pCookie->srcTotalDataLenInBytes;
pCompReqParams->out_buffer_sz = pCookie->dstTotalDataLenInBytes;
}
static CpaStatus
dcCreateRequest(dc_compression_cookie_t *pCookie,
sal_compression_service_t *pService,
dc_session_desc_t *pSessionDesc,
CpaDcSessionHandle pSessionHandle,
CpaBufferList *pSrcBuff,
CpaBufferList *pDestBuff,
CpaDcRqResults *pResults,
CpaDcFlush flushFlag,
CpaDcOpData *pOpData,
void *callbackTag,
dc_request_dir_t compDecomp,
dc_cnv_mode_t cnvMode)
{
icp_qat_fw_comp_req_t *pMsg = NULL;
icp_qat_fw_comp_req_params_t *pCompReqParams = NULL;
Cpa64U srcAddrPhys = 0, dstAddrPhys = 0;
Cpa64U srcTotalDataLenInBytes = 0, dstTotalDataLenInBytes = 0;
Cpa32U rpCmdFlags = 0;
Cpa8U sop = ICP_QAT_FW_COMP_SOP;
Cpa8U eop = ICP_QAT_FW_COMP_EOP;
Cpa8U bFinal = ICP_QAT_FW_COMP_NOT_BFINAL;
Cpa8U crcMode = ICP_QAT_FW_COMP_CRC_MODE_LEGACY;
Cpa8U cnvDecompReq = ICP_QAT_FW_COMP_NO_CNV;
Cpa8U cnvRecovery = ICP_QAT_FW_COMP_NO_CNV_RECOVERY;
CpaBoolean cnvErrorInjection = ICP_QAT_FW_COMP_NO_CNV_DFX;
CpaBoolean integrityCrcCheck = CPA_FALSE;
CpaStatus status = CPA_STATUS_SUCCESS;
CpaDcFlush flush = CPA_DC_FLUSH_NONE;
Cpa32U initial_adler = 1;
Cpa32U initial_crc32 = 0;
icp_qat_fw_comp_req_t *pReqCache = NULL;
status = LacBuffDesc_BufferListDescWriteAndGetSize(
pSrcBuff,
&srcAddrPhys,
CPA_FALSE,
&srcTotalDataLenInBytes,
&(pService->generic_service_info));
if (status != CPA_STATUS_SUCCESS) {
return status;
}
status = LacBuffDesc_BufferListDescWriteAndGetSize(
pDestBuff,
&dstAddrPhys,
CPA_FALSE,
&dstTotalDataLenInBytes,
&(pService->generic_service_info));
if (status != CPA_STATUS_SUCCESS) {
return status;
}
pCookie->dcInstance = pService;
pCookie->pSessionHandle = pSessionHandle;
pCookie->callbackTag = callbackTag;
pCookie->pSessionDesc = pSessionDesc;
pCookie->pDcOpData = pOpData;
pCookie->pResults = pResults;
pCookie->compDecomp = compDecomp;
pCookie->pUserSrcBuff = NULL;
pCookie->pUserDestBuff = NULL;
if (NULL != pOpData) {
flush = pOpData->flushFlag;
integrityCrcCheck = pOpData->integrityCrcCheck;
} else {
flush = flushFlag;
}
pCookie->flushFlag = flush;
pCookie->srcTotalDataLenInBytes = (Cpa32U)srcTotalDataLenInBytes;
if ((isDcGen2x(pService)) && (DC_COMPRESSION_REQUEST == compDecomp) &&
(CPA_DC_HT_FULL_DYNAMIC == pSessionDesc->huffType)) {
if (pService->minInterBuffSizeInBytes <
(Cpa32U)dstTotalDataLenInBytes) {
pCookie->dstTotalDataLenInBytes =
(Cpa32U)(pService->minInterBuffSizeInBytes);
} else {
pCookie->dstTotalDataLenInBytes =
(Cpa32U)dstTotalDataLenInBytes;
}
} else
{
pCookie->dstTotalDataLenInBytes =
(Cpa32U)dstTotalDataLenInBytes;
}
if (CPA_TRUE != pService->comp_device_data.oddByteDecompNobFinal) {
if ((CPA_DC_STATEFUL == pSessionDesc->sessState) &&
(CPA_DC_FLUSH_FINAL != flushFlag) &&
(DC_DECOMPRESSION_REQUEST == compDecomp) &&
(pCookie->srcTotalDataLenInBytes & 0x1)) {
pCookie->srcTotalDataLenInBytes--;
}
}
if (CPA_TRUE != pService->comp_device_data.oddByteDecompInterim) {
if ((CPA_DC_STATEFUL == pSessionDesc->sessState) &&
(CPA_DC_FLUSH_FINAL != flushFlag) &&
(CPA_DC_FLUSH_FULL != flushFlag) &&
(DC_DECOMPRESSION_REQUEST == compDecomp) &&
(pCookie->srcTotalDataLenInBytes & 0x1)) {
pCookie->srcTotalDataLenInBytes--;
}
}
pMsg = (icp_qat_fw_comp_req_t *)&pCookie->request;
if (DC_COMPRESSION_REQUEST == compDecomp) {
pReqCache = &(pSessionDesc->reqCacheComp);
} else {
pReqCache = &(pSessionDesc->reqCacheDecomp);
}
memcpy((void *)pMsg,
(void *)(pReqCache),
LAC_QAT_DC_REQ_SZ_LW * LAC_LONG_WORD_IN_BYTES);
if (DC_REQUEST_FIRST == pSessionDesc->requestType) {
initial_adler = 1;
initial_crc32 = 0;
if (CPA_DC_ADLER32 == pSessionDesc->checksumType) {
pSessionDesc->previousChecksum = initial_adler;
} else {
pSessionDesc->previousChecksum = initial_crc32;
}
} else if (CPA_DC_STATELESS == pSessionDesc->sessState) {
pSessionDesc->previousChecksum = pResults->checksum;
if (CPA_DC_ADLER32 == pSessionDesc->checksumType) {
initial_adler = pSessionDesc->previousChecksum;
} else {
initial_crc32 = pSessionDesc->previousChecksum;
}
}
pCookie->pUserSrcBuff = pSrcBuff;
pCookie->pUserDestBuff = pDestBuff;
if (CPA_TRUE == pService->generic_service_info.integrityCrcCheck &&
CPA_TRUE == integrityCrcCheck) {
pMsg->comp_pars.crc.crc_data_addr =
pSessionDesc->physDataIntegrityCrcs;
crcMode = ICP_QAT_FW_COMP_CRC_MODE_E2E;
} else {
pMsg->comp_pars.crc.legacy.initial_adler = initial_adler;
pMsg->comp_pars.crc.legacy.initial_crc32 = initial_crc32;
crcMode = ICP_QAT_FW_COMP_CRC_MODE_LEGACY;
}
if (CPA_DC_STATEFUL == pSessionDesc->sessState) {
pSessionDesc->previousRequestType = pSessionDesc->requestType;
if (DC_REQUEST_FIRST == pSessionDesc->requestType) {
pSessionDesc->requestType = DC_REQUEST_SUBSEQUENT;
pSessionDesc->cumulativeConsumedBytes = 0;
if (DC_COMPRESSION_REQUEST == compDecomp) {
pSessionDesc->isSopForCompressionProcessed =
CPA_TRUE;
} else if (DC_DECOMPRESSION_REQUEST == compDecomp) {
pSessionDesc->isSopForDecompressionProcessed =
CPA_TRUE;
}
} else {
if (DC_COMPRESSION_REQUEST == compDecomp) {
if (CPA_TRUE ==
pSessionDesc
->isSopForCompressionProcessed) {
sop = ICP_QAT_FW_COMP_NOT_SOP;
} else {
pSessionDesc
->isSopForCompressionProcessed =
CPA_TRUE;
}
} else if (DC_DECOMPRESSION_REQUEST == compDecomp) {
if (CPA_TRUE ==
pSessionDesc
->isSopForDecompressionProcessed) {
sop = ICP_QAT_FW_COMP_NOT_SOP;
} else {
pSessionDesc
->isSopForDecompressionProcessed =
CPA_TRUE;
}
}
}
if ((CPA_DC_FLUSH_FINAL == flush) ||
(CPA_DC_FLUSH_FULL == flush)) {
pSessionDesc->requestType = DC_REQUEST_FIRST;
} else {
eop = ICP_QAT_FW_COMP_NOT_EOP;
}
} else {
if (DC_REQUEST_FIRST == pSessionDesc->requestType) {
pSessionDesc->cumulativeConsumedBytes = 0;
}
}
pCompReqParams = &(pMsg->comp_pars);
dcCompRequestParamsPopulate(pCompReqParams, pCookie);
if (CPA_DC_FLUSH_FINAL == flush) {
bFinal = ICP_QAT_FW_COMP_BFINAL;
}
switch (cnvMode) {
case DC_CNVNR:
cnvRecovery = ICP_QAT_FW_COMP_CNV_RECOVERY;
case DC_CNV:
cnvDecompReq = ICP_QAT_FW_COMP_CNV;
if (isDcGen4x(pService)) {
cnvErrorInjection = pSessionDesc->cnvErrorInjection;
}
break;
case DC_NO_CNV:
cnvDecompReq = ICP_QAT_FW_COMP_NO_CNV;
cnvRecovery = ICP_QAT_FW_COMP_NO_CNV_RECOVERY;
break;
}
rpCmdFlags = ICP_QAT_FW_COMP_REQ_PARAM_FLAGS_BUILD(sop,
eop,
bFinal,
cnvDecompReq,
cnvRecovery,
cnvErrorInjection,
crcMode);
pMsg->comp_pars.req_par_flags = rpCmdFlags;
SalQatMsg_CmnMidWrite((icp_qat_fw_la_bulk_req_t *)pMsg,
pCookie,
DC_DEFAULT_QAT_PTR_TYPE,
srcAddrPhys,
dstAddrPhys,
0,
0);
return CPA_STATUS_SUCCESS;
}
static CpaStatus
dcSendRequest(dc_compression_cookie_t *pCookie,
sal_compression_service_t *pService,
dc_session_desc_t *pSessionDesc,
dc_request_dir_t compDecomp)
{
CpaStatus status = CPA_STATUS_SUCCESS;
status = icp_adf_transPutMsg(pService->trans_handle_compression_tx,
(void *)&(pCookie->request),
LAC_QAT_DC_REQ_SZ_LW);
if ((CPA_DC_STATEFUL == pSessionDesc->sessState) &&
(CPA_STATUS_RETRY == status)) {
pSessionDesc->requestType = pSessionDesc->previousRequestType;
}
return status;
}
static CpaStatus
dcCompDecompData(sal_compression_service_t *pService,
dc_session_desc_t *pSessionDesc,
CpaInstanceHandle dcInstance,
CpaDcSessionHandle pSessionHandle,
CpaBufferList *pSrcBuff,
CpaBufferList *pDestBuff,
CpaDcRqResults *pResults,
CpaDcFlush flushFlag,
CpaDcOpData *pOpData,
void *callbackTag,
dc_request_dir_t compDecomp,
CpaBoolean isAsyncMode,
dc_cnv_mode_t cnvMode)
{
CpaStatus status = CPA_STATUS_SUCCESS;
dc_compression_cookie_t *pCookie = NULL;
if ((LacSync_GenWakeupSyncCaller == pSessionDesc->pCompressionCb) &&
isAsyncMode == CPA_TRUE) {
lac_sync_op_data_t *pSyncCallbackData = NULL;
status = LacSync_CreateSyncCookie(&pSyncCallbackData);
if (CPA_STATUS_SUCCESS == status) {
status = dcCompDecompData(pService,
pSessionDesc,
dcInstance,
pSessionHandle,
pSrcBuff,
pDestBuff,
pResults,
flushFlag,
pOpData,
pSyncCallbackData,
compDecomp,
CPA_FALSE,
cnvMode);
} else {
return status;
}
if (CPA_STATUS_SUCCESS == status) {
CpaStatus syncStatus = CPA_STATUS_SUCCESS;
syncStatus =
LacSync_WaitForCallback(pSyncCallbackData,
DC_SYNC_CALLBACK_TIMEOUT,
&status,
NULL);
if (CPA_STATUS_SUCCESS != syncStatus) {
if (DC_COMPRESSION_REQUEST == compDecomp) {
COMPRESSION_STAT_INC(
numCompCompletedErrors, pService);
} else {
COMPRESSION_STAT_INC(
numDecompCompletedErrors, pService);
}
LAC_LOG_ERROR("Callback timed out");
status = syncStatus;
}
} else {
LacSync_SetSyncCookieComplete(pSyncCallbackData);
}
LacSync_DestroySyncCookie(&pSyncCallbackData);
return status;
}
pCookie = (dc_compression_cookie_t *)Lac_MemPoolEntryAlloc(
pService->compression_mem_pool);
if (NULL == pCookie) {
LAC_LOG_ERROR("Cannot get mem pool entry for compression");
status = CPA_STATUS_RESOURCE;
} else if ((void *)CPA_STATUS_RETRY == pCookie) {
pCookie = NULL;
status = CPA_STATUS_RETRY;
}
if (CPA_STATUS_SUCCESS == status) {
status = dcCreateRequest(pCookie,
pService,
pSessionDesc,
pSessionHandle,
pSrcBuff,
pDestBuff,
pResults,
flushFlag,
pOpData,
callbackTag,
compDecomp,
cnvMode);
}
if (CPA_STATUS_SUCCESS == status) {
if (CPA_DC_STATELESS == pSessionDesc->sessState) {
qatUtilsAtomicInc(
&(pSessionDesc->pendingStatelessCbCount));
}
status =
dcSendRequest(pCookie, pService, pSessionDesc, compDecomp);
}
if (CPA_STATUS_SUCCESS == status) {
if (DC_COMPRESSION_REQUEST == compDecomp) {
COMPRESSION_STAT_INC(numCompRequests, pService);
} else {
COMPRESSION_STAT_INC(numDecompRequests, pService);
}
} else {
if (DC_COMPRESSION_REQUEST == compDecomp) {
COMPRESSION_STAT_INC(numCompRequestsErrors, pService);
} else {
COMPRESSION_STAT_INC(numDecompRequestsErrors, pService);
}
if (CPA_DC_STATELESS == pSessionDesc->sessState) {
qatUtilsAtomicDec(
&(pSessionDesc->pendingStatelessCbCount));
} else {
qatUtilsAtomicDec(
&(pSessionDesc->pendingStatefulCbCount));
}
if (NULL != pCookie) {
if (status != CPA_STATUS_UNSUPPORTED) {
Lac_MemPoolEntryFree(pCookie);
pCookie = NULL;
}
}
}
return status;
}
static CpaStatus
dcZeroLengthRequests(sal_compression_service_t *pService,
dc_session_desc_t *pSessionDesc,
CpaDcRqResults *pResults,
CpaDcFlush flushFlag,
void *callbackTag,
dc_request_dir_t compDecomp)
{
CpaBoolean status = CPA_FALSE;
CpaDcCallbackFn pCbFunc = pSessionDesc->pCompressionCb;
if (DC_REQUEST_FIRST == pSessionDesc->requestType) {
pSessionDesc->cumulativeConsumedBytes = 0;
if (CPA_DC_ADLER32 == pSessionDesc->checksumType) {
pResults->checksum = 1;
} else {
pResults->checksum = 0;
}
status = CPA_TRUE;
} else if ((CPA_DC_FLUSH_NONE == flushFlag) ||
(CPA_DC_FLUSH_SYNC == flushFlag)) {
pResults->checksum = pSessionDesc->previousChecksum;
status = CPA_TRUE;
}
if (CPA_TRUE == status) {
pResults->status = CPA_DC_OK;
pResults->produced = 0;
pResults->consumed = 0;
if (DC_COMPRESSION_REQUEST == compDecomp) {
COMPRESSION_STAT_INC(numCompRequests, pService);
COMPRESSION_STAT_INC(numCompCompleted, pService);
} else {
COMPRESSION_STAT_INC(numDecompRequests, pService);
COMPRESSION_STAT_INC(numDecompCompleted, pService);
}
LAC_SPINUNLOCK(&(pSessionDesc->sessionLock));
if ((NULL != pCbFunc) &&
(LacSync_GenWakeupSyncCaller != pCbFunc)) {
pCbFunc(callbackTag, CPA_STATUS_SUCCESS);
}
return CPA_TRUE;
}
return CPA_FALSE;
}
static CpaStatus
dcParamCheck(CpaInstanceHandle dcInstance,
CpaDcSessionHandle pSessionHandle,
sal_compression_service_t *pService,
CpaBufferList *pSrcBuff,
CpaBufferList *pDestBuff,
CpaDcRqResults *pResults,
dc_session_desc_t *pSessionDesc,
CpaDcFlush flushFlag,
Cpa64U srcBuffSize)
{
if (dcCheckSourceData(pSessionHandle,
pSrcBuff,
pDestBuff,
pResults,
flushFlag,
srcBuffSize,
NULL) != CPA_STATUS_SUCCESS) {
return CPA_STATUS_INVALID_PARAM;
}
if (dcCheckDestinationData(
pService, pSessionHandle, pDestBuff, DC_COMPRESSION_REQUEST) !=
CPA_STATUS_SUCCESS) {
return CPA_STATUS_INVALID_PARAM;
}
if (CPA_DC_DIR_DECOMPRESS == pSessionDesc->sessDirection) {
LAC_INVALID_PARAM_LOG("Invalid sessDirection value");
return CPA_STATUS_INVALID_PARAM;
}
return CPA_STATUS_SUCCESS;
}
CpaStatus
cpaDcCompressData(CpaInstanceHandle dcInstance,
CpaDcSessionHandle pSessionHandle,
CpaBufferList *pSrcBuff,
CpaBufferList *pDestBuff,
CpaDcRqResults *pResults,
CpaDcFlush flushFlag,
void *callbackTag)
{
sal_compression_service_t *pService = NULL;
dc_session_desc_t *pSessionDesc = NULL;
CpaInstanceHandle insHandle = NULL;
Cpa64U srcBuffSize = 0;
if (CPA_INSTANCE_HANDLE_SINGLE == dcInstance) {
insHandle = dcGetFirstHandle();
} else {
insHandle = dcInstance;
}
pService = (sal_compression_service_t *)insHandle;
LAC_CHECK_NULL_PARAM(insHandle);
LAC_CHECK_NULL_PARAM(pSessionHandle);
SAL_RUNNING_CHECK(insHandle);
if (LacBuffDesc_BufferListVerifyNull(pSrcBuff,
&srcBuffSize,
LAC_NO_ALIGNMENT_SHIFT) !=
CPA_STATUS_SUCCESS) {
LAC_INVALID_PARAM_LOG("Invalid source buffer list parameter");
return CPA_STATUS_INVALID_PARAM;
}
SAL_CHECK_INSTANCE_TYPE(insHandle, SAL_SERVICE_TYPE_COMPRESSION);
pSessionDesc = DC_SESSION_DESC_FROM_CTX_GET(pSessionHandle);
if (CPA_STATUS_SUCCESS !=
dcParamCheck(insHandle,
pSessionHandle,
pService,
pSrcBuff,
pDestBuff,
pResults,
pSessionDesc,
flushFlag,
srcBuffSize)) {
return CPA_STATUS_INVALID_PARAM;
}
if (CPA_DC_STATEFUL == pSessionDesc->sessState) {
LAC_INVALID_PARAM_LOG(
"Invalid session state, stateful sessions "
"are not supported");
return CPA_STATUS_UNSUPPORTED;
}
if (!(pService->generic_service_info.dcExtendedFeatures &
DC_CNV_EXTENDED_CAPABILITY)) {
LAC_INVALID_PARAM_LOG(
"CompressAndVerify feature not supported");
return CPA_STATUS_UNSUPPORTED;
}
if (!(pService->generic_service_info.dcExtendedFeatures &
DC_CNVNR_EXTENDED_CAPABILITY)) {
LAC_INVALID_PARAM_LOG(
"CompressAndVerifyAndRecovery feature not supported");
return CPA_STATUS_UNSUPPORTED;
}
return dcCompDecompData(pService,
pSessionDesc,
insHandle,
pSessionHandle,
pSrcBuff,
pDestBuff,
pResults,
flushFlag,
NULL,
callbackTag,
DC_COMPRESSION_REQUEST,
CPA_TRUE,
DC_CNVNR);
}
CpaStatus
cpaDcCompressData2(CpaInstanceHandle dcInstance,
CpaDcSessionHandle pSessionHandle,
CpaBufferList *pSrcBuff,
CpaBufferList *pDestBuff,
CpaDcOpData *pOpData,
CpaDcRqResults *pResults,
void *callbackTag)
{
sal_compression_service_t *pService = NULL;
dc_session_desc_t *pSessionDesc = NULL;
CpaInstanceHandle insHandle = NULL;
Cpa64U srcBuffSize = 0;
dc_cnv_mode_t cnvMode = DC_NO_CNV;
LAC_CHECK_NULL_PARAM(pOpData);
if (((CPA_TRUE != pOpData->compressAndVerify) &&
(CPA_FALSE != pOpData->compressAndVerify)) ||
((CPA_FALSE != pOpData->compressAndVerifyAndRecover) &&
(CPA_TRUE != pOpData->compressAndVerifyAndRecover))) {
return CPA_STATUS_INVALID_PARAM;
}
if ((CPA_FALSE == pOpData->compressAndVerify) &&
(CPA_TRUE == pOpData->compressAndVerifyAndRecover)) {
return CPA_STATUS_INVALID_PARAM;
}
if ((CPA_TRUE == pOpData->compressAndVerify) &&
(CPA_TRUE == pOpData->compressAndVerifyAndRecover) &&
(CPA_FALSE == pOpData->integrityCrcCheck)) {
return cpaDcCompressData(dcInstance,
pSessionHandle,
pSrcBuff,
pDestBuff,
pResults,
pOpData->flushFlag,
callbackTag);
}
if (CPA_FALSE == pOpData->compressAndVerify) {
LAC_INVALID_PARAM_LOG(
"Data compression without verification not allowed");
return CPA_STATUS_UNSUPPORTED;
}
if (CPA_INSTANCE_HANDLE_SINGLE == dcInstance) {
insHandle = dcGetFirstHandle();
} else {
insHandle = dcInstance;
}
pService = (sal_compression_service_t *)insHandle;
LAC_CHECK_NULL_PARAM(insHandle);
LAC_CHECK_NULL_PARAM(pSessionHandle);
LAC_CHECK_NULL_PARAM(pOpData);
SAL_RUNNING_CHECK(insHandle);
if (LacBuffDesc_BufferListVerifyNull(pSrcBuff,
&srcBuffSize,
LAC_NO_ALIGNMENT_SHIFT) !=
CPA_STATUS_SUCCESS) {
LAC_INVALID_PARAM_LOG("Invalid source buffer list parameter");
return CPA_STATUS_INVALID_PARAM;
}
SAL_CHECK_INSTANCE_TYPE(insHandle, SAL_SERVICE_TYPE_COMPRESSION);
pSessionDesc = DC_SESSION_DESC_FROM_CTX_GET(pSessionHandle);
if (CPA_TRUE == pOpData->compressAndVerify &&
CPA_DC_STATEFUL == pSessionDesc->sessState) {
LAC_INVALID_PARAM_LOG(
"Invalid session state, stateful sessions "
"not supported with CNV");
return CPA_STATUS_UNSUPPORTED;
}
if (!(pService->generic_service_info.dcExtendedFeatures &
DC_CNV_EXTENDED_CAPABILITY) &&
(CPA_TRUE == pOpData->compressAndVerify)) {
LAC_INVALID_PARAM_LOG(
"CompressAndVerify feature not supported");
return CPA_STATUS_UNSUPPORTED;
}
if (CPA_STATUS_SUCCESS !=
dcParamCheck(insHandle,
pSessionHandle,
pService,
pSrcBuff,
pDestBuff,
pResults,
pSessionDesc,
pOpData->flushFlag,
srcBuffSize)) {
return CPA_STATUS_INVALID_PARAM;
}
if (CPA_STATUS_SUCCESS != dcCheckOpData(pService, pOpData)) {
return CPA_STATUS_INVALID_PARAM;
}
if (CPA_TRUE != pOpData->compressAndVerify) {
if (srcBuffSize > DC_COMP_MAX_BUFF_SIZE) {
LAC_LOG_ERROR(
"Compression payload greater than 64KB is "
"unsupported, when CnV is disabled\n");
return CPA_STATUS_UNSUPPORTED;
}
}
if (CPA_DC_STATEFUL == pSessionDesc->sessState) {
LAC_SPINLOCK(&(pSessionDesc->sessionLock));
if (0 !=
qatUtilsAtomicGet(
&(pSessionDesc->pendingStatefulCbCount))) {
LAC_LOG_ERROR(
"Only one in-flight stateful request supported");
LAC_SPINUNLOCK(&(pSessionDesc->sessionLock));
return CPA_STATUS_RETRY;
}
if (0 == srcBuffSize) {
if (CPA_TRUE ==
dcZeroLengthRequests(pService,
pSessionDesc,
pResults,
pOpData->flushFlag,
callbackTag,
DC_COMPRESSION_REQUEST)) {
return CPA_STATUS_SUCCESS;
}
}
qatUtilsAtomicInc(&(pSessionDesc->pendingStatefulCbCount));
LAC_SPINUNLOCK(&(pSessionDesc->sessionLock));
}
if (CPA_TRUE == pOpData->compressAndVerify) {
cnvMode = DC_CNV;
}
return dcCompDecompData(pService,
pSessionDesc,
insHandle,
pSessionHandle,
pSrcBuff,
pDestBuff,
pResults,
pOpData->flushFlag,
pOpData,
callbackTag,
DC_COMPRESSION_REQUEST,
CPA_TRUE,
cnvMode);
}
static CpaStatus
dcDecompressDataCheck(CpaInstanceHandle insHandle,
CpaDcSessionHandle pSessionHandle,
CpaBufferList *pSrcBuff,
CpaBufferList *pDestBuff,
CpaDcRqResults *pResults,
CpaDcFlush flushFlag,
Cpa64U *srcBufferSize)
{
sal_compression_service_t *pService = NULL;
dc_session_desc_t *pSessionDesc = NULL;
Cpa64U srcBuffSize = 0;
pService = (sal_compression_service_t *)insHandle;
LAC_CHECK_NULL_PARAM(insHandle);
SAL_RUNNING_CHECK(insHandle);
if (LacBuffDesc_BufferListVerifyNull(pSrcBuff,
&srcBuffSize,
LAC_NO_ALIGNMENT_SHIFT) !=
CPA_STATUS_SUCCESS) {
LAC_INVALID_PARAM_LOG("Invalid source buffer list parameter");
return CPA_STATUS_INVALID_PARAM;
}
SAL_CHECK_INSTANCE_TYPE(insHandle, SAL_SERVICE_TYPE_COMPRESSION);
if (dcCheckSourceData(pSessionHandle,
pSrcBuff,
pDestBuff,
pResults,
flushFlag,
srcBuffSize,
NULL) != CPA_STATUS_SUCCESS) {
return CPA_STATUS_INVALID_PARAM;
}
if (dcCheckDestinationData(pService,
pSessionHandle,
pDestBuff,
DC_DECOMPRESSION_REQUEST) !=
CPA_STATUS_SUCCESS) {
return CPA_STATUS_INVALID_PARAM;
}
pSessionDesc = DC_SESSION_DESC_FROM_CTX_GET(pSessionHandle);
if (CPA_DC_DIR_COMPRESS == pSessionDesc->sessDirection) {
LAC_INVALID_PARAM_LOG("Invalid sessDirection value");
return CPA_STATUS_INVALID_PARAM;
}
*srcBufferSize = srcBuffSize;
return CPA_STATUS_SUCCESS;
}
CpaStatus
cpaDcDecompressData(CpaInstanceHandle dcInstance,
CpaDcSessionHandle pSessionHandle,
CpaBufferList *pSrcBuff,
CpaBufferList *pDestBuff,
CpaDcRqResults *pResults,
CpaDcFlush flushFlag,
void *callbackTag)
{
sal_compression_service_t *pService = NULL;
dc_session_desc_t *pSessionDesc = NULL;
CpaInstanceHandle insHandle = NULL;
Cpa64U srcBuffSize = 0;
CpaStatus status = CPA_STATUS_SUCCESS;
if (CPA_INSTANCE_HANDLE_SINGLE == dcInstance) {
insHandle = dcGetFirstHandle();
} else {
insHandle = dcInstance;
}
status = dcDecompressDataCheck(insHandle,
pSessionHandle,
pSrcBuff,
pDestBuff,
pResults,
flushFlag,
&srcBuffSize);
if (CPA_STATUS_SUCCESS != status) {
return status;
}
pService = (sal_compression_service_t *)insHandle;
SAL_RUNNING_CHECK(insHandle);
if (CPA_STATUS_SUCCESS !=
LacBuffDesc_BufferListVerifyNull(pSrcBuff,
&srcBuffSize,
LAC_NO_ALIGNMENT_SHIFT)) {
QAT_UTILS_LOG("Invalid source buffer list parameter");
return CPA_STATUS_INVALID_PARAM;
}
SAL_CHECK_INSTANCE_TYPE(insHandle, SAL_SERVICE_TYPE_COMPRESSION);
if (dcCheckSourceData(pSessionHandle,
pSrcBuff,
pDestBuff,
pResults,
flushFlag,
srcBuffSize,
NULL) != CPA_STATUS_SUCCESS) {
return CPA_STATUS_INVALID_PARAM;
}
if (dcCheckDestinationData(pService,
pSessionHandle,
pDestBuff,
DC_DECOMPRESSION_REQUEST) !=
CPA_STATUS_SUCCESS) {
return CPA_STATUS_INVALID_PARAM;
}
pSessionDesc = DC_SESSION_DESC_FROM_CTX_GET(pSessionHandle);
if (CPA_DC_DIR_COMPRESS == pSessionDesc->sessDirection) {
QAT_UTILS_LOG("Invalid sessDirection value");
return CPA_STATUS_INVALID_PARAM;
}
if (CPA_DC_STATEFUL == pSessionDesc->sessState) {
LAC_SPINLOCK(&(pSessionDesc->sessionLock));
if (0 !=
qatUtilsAtomicGet(
&(pSessionDesc->pendingStatefulCbCount))) {
LAC_LOG_ERROR(
"Only one in-flight stateful request supported");
LAC_SPINUNLOCK(&(pSessionDesc->sessionLock));
return CPA_STATUS_RETRY;
}
if (isDcGen2x(pService)) {
if ((0 == srcBuffSize) ||
((1 == srcBuffSize) &&
(CPA_DC_FLUSH_FINAL != flushFlag) &&
(CPA_DC_FLUSH_FULL != flushFlag))) {
if (CPA_TRUE ==
dcZeroLengthRequests(
pService,
pSessionDesc,
pResults,
flushFlag,
callbackTag,
DC_DECOMPRESSION_REQUEST)) {
return CPA_STATUS_SUCCESS;
}
}
}
qatUtilsAtomicInc(&(pSessionDesc->pendingStatefulCbCount));
LAC_SPINUNLOCK(&(pSessionDesc->sessionLock));
}
return dcCompDecompData(pService,
pSessionDesc,
insHandle,
pSessionHandle,
pSrcBuff,
pDestBuff,
pResults,
flushFlag,
NULL,
callbackTag,
DC_DECOMPRESSION_REQUEST,
CPA_TRUE,
DC_NO_CNV);
}
CpaStatus
cpaDcDecompressData2(CpaInstanceHandle dcInstance,
CpaDcSessionHandle pSessionHandle,
CpaBufferList *pSrcBuff,
CpaBufferList *pDestBuff,
CpaDcOpData *pOpData,
CpaDcRqResults *pResults,
void *callbackTag)
{
sal_compression_service_t *pService = NULL;
dc_session_desc_t *pSessionDesc = NULL;
CpaInstanceHandle insHandle = NULL;
CpaStatus status = CPA_STATUS_SUCCESS;
Cpa64U srcBuffSize = 0;
LAC_CHECK_NULL_PARAM(pOpData);
if (CPA_FALSE == pOpData->integrityCrcCheck) {
return cpaDcDecompressData(dcInstance,
pSessionHandle,
pSrcBuff,
pDestBuff,
pResults,
pOpData->flushFlag,
callbackTag);
}
if (CPA_INSTANCE_HANDLE_SINGLE == dcInstance) {
insHandle = dcGetFirstHandle();
} else {
insHandle = dcInstance;
}
status = dcDecompressDataCheck(insHandle,
pSessionHandle,
pSrcBuff,
pDestBuff,
pResults,
pOpData->flushFlag,
&srcBuffSize);
if (CPA_STATUS_SUCCESS != status) {
return status;
}
pService = (sal_compression_service_t *)insHandle;
pSessionDesc = DC_SESSION_DESC_FROM_CTX_GET(pSessionHandle);
LAC_CHECK_NULL_PARAM(insHandle);
SAL_RUNNING_CHECK(insHandle);
if (CPA_STATUS_SUCCESS !=
LacBuffDesc_BufferListVerifyNull(pSrcBuff,
&srcBuffSize,
LAC_NO_ALIGNMENT_SHIFT)) {
QAT_UTILS_LOG("Invalid source buffer list parameter");
return CPA_STATUS_INVALID_PARAM;
}
SAL_CHECK_INSTANCE_TYPE(insHandle, SAL_SERVICE_TYPE_COMPRESSION);
if (CPA_STATUS_SUCCESS !=
dcCheckSourceData(pSessionHandle,
pSrcBuff,
pDestBuff,
pResults,
CPA_DC_FLUSH_NONE,
srcBuffSize,
NULL)) {
return CPA_STATUS_INVALID_PARAM;
}
if (CPA_STATUS_SUCCESS !=
dcCheckDestinationData(pService,
pSessionHandle,
pDestBuff,
DC_DECOMPRESSION_REQUEST)) {
return CPA_STATUS_INVALID_PARAM;
}
if (CPA_STATUS_SUCCESS != dcCheckOpData(pService, pOpData)) {
return CPA_STATUS_INVALID_PARAM;
}
if (CPA_DC_DIR_COMPRESS == pSessionDesc->sessDirection) {
QAT_UTILS_LOG("Invalid sessDirection value");
return CPA_STATUS_INVALID_PARAM;
}
if (CPA_DC_STATEFUL == pSessionDesc->sessState) {
LAC_SPINLOCK(&(pSessionDesc->sessionLock));
if (0 !=
qatUtilsAtomicGet(
&(pSessionDesc->pendingStatefulCbCount))) {
LAC_LOG_ERROR(
"Only one in-flight stateful request supported");
LAC_SPINUNLOCK(&(pSessionDesc->sessionLock));
return CPA_STATUS_RETRY;
}
if (isDcGen2x(pService)) {
if ((0 == srcBuffSize) ||
((1 == srcBuffSize) &&
(CPA_DC_FLUSH_FINAL != pOpData->flushFlag) &&
(CPA_DC_FLUSH_FULL != pOpData->flushFlag))) {
if (CPA_TRUE ==
dcZeroLengthRequests(
pService,
pSessionDesc,
pResults,
pOpData->flushFlag,
callbackTag,
DC_DECOMPRESSION_REQUEST)) {
return CPA_STATUS_SUCCESS;
}
}
}
qatUtilsAtomicInc(&(pSessionDesc->pendingStatefulCbCount));
LAC_SPINUNLOCK(&(pSessionDesc->sessionLock));
}
return dcCompDecompData(pService,
pSessionDesc,
insHandle,
pSessionHandle,
pSrcBuff,
pDestBuff,
pResults,
pOpData->flushFlag,
pOpData,
callbackTag,
DC_DECOMPRESSION_REQUEST,
CPA_TRUE,
DC_NO_CNV);
}