78ee8d1c4c
QAT in-tree driver ported from out-of-tree release available from 01.org. The driver exposes complete cryptography and data compression API in the kernel and integrates with Open Crypto Framework. Details of supported operations, devices and usage can be found in man and on 01.org. Patch co-authored by: Krzysztof Zdziarski <krzysztofx.zdziarski@intel.com> Patch co-authored by: Michal Jaraczewski <michalx.jaraczewski@intel.com> Patch co-authored by: Michal Gulbicki <michalx.gulbicki@intel.com> Patch co-authored by: Julian Grajkowski <julianx.grajkowski@intel.com> Patch co-authored by: Piotr Kasierski <piotrx.kasierski@intel.com> Patch co-authored by: Adam Czupryna <adamx.czupryna@intel.com> Patch co-authored by: Konrad Zelazny <konradx.zelazny@intel.com> Patch co-authored by: Katarzyna Rucinska <katarzynax.kargol@intel.com> Patch co-authored by: Lukasz Kolodzinski <lukaszx.kolodzinski@intel.com> Patch co-authored by: Zbigniew Jedlinski <zbigniewx.jedlinski@intel.com> Reviewed by: markj, jhb (OCF integration) Reviewed by: debdrup, pauamma (docs) Sponsored by: Intel Corporation Differential Revision: https://reviews.freebsd.org/D34632
958 lines
30 KiB
C
958 lines
30 KiB
C
/* SPDX-License-Identifier: BSD-3-Clause */
|
|
/* Copyright(c) 2007-2022 Intel Corporation */
|
|
/* $FreeBSD$ */
|
|
/**
|
|
*****************************************************************************
|
|
* @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 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"
|
|
|
|
/**
|
|
*****************************************************************************
|
|
* @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
|
|
*
|
|
*****************************************************************************/
|
|
static CpaStatus
|
|
dcCheckSessionData(const CpaDcSessionSetupData *pSessionData,
|
|
CpaInstanceHandle dcInstance)
|
|
{
|
|
CpaDcInstanceCapabilities instanceCapabilities = { 0 };
|
|
|
|
cpaDcQueryCapabilities(dcInstance, &instanceCapabilities);
|
|
|
|
if ((pSessionData->compLevel < CPA_DC_L1) ||
|
|
(pSessionData->compLevel > CPA_DC_L9)) {
|
|
QAT_UTILS_LOG("Invalid compLevel value\n");
|
|
return CPA_STATUS_INVALID_PARAM;
|
|
}
|
|
if ((pSessionData->autoSelectBestHuffmanTree < CPA_DC_ASB_DISABLED) ||
|
|
(pSessionData->autoSelectBestHuffmanTree >
|
|
CPA_DC_ASB_UNCOMP_STATIC_DYNAMIC_WITH_NO_HDRS)) {
|
|
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(dc_session_desc_t *pSessionDesc,
|
|
icp_qat_hw_compression_config_t *pCompConfig,
|
|
dc_request_dir_t compDecomp,
|
|
icp_qat_hw_compression_delayed_match_t enableDmm)
|
|
{
|
|
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;
|
|
|
|
/* 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 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;
|
|
default:
|
|
depth = ICP_QAT_HW_COMPRESSION_DEPTH_16;
|
|
}
|
|
}
|
|
|
|
/* 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->val = ICP_QAT_HW_COMPRESSION_CONFIG_BUILD(
|
|
dir, enableDmm, algo, depth, filetype);
|
|
|
|
pCompConfig->reserved = 0;
|
|
}
|
|
|
|
/**
|
|
*****************************************************************************
|
|
* @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 */
|
|
dcCompHwBlockPopulate(pSessionDesc,
|
|
pCompConfig,
|
|
compDecomp,
|
|
pService->comp_device_data.enableDmm);
|
|
}
|
|
|
|
/**
|
|
*****************************************************************************
|
|
* @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
|
|
*
|
|
*****************************************************************************/
|
|
static 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_DEFLATE == pSessionData->compType) &&
|
|
(CPA_DC_DIR_COMPRESS != pSessionData->sessDirection)) {
|
|
*pContextSize =
|
|
pCompService->comp_device_data.inflateContextSize;
|
|
}
|
|
return CPA_STATUS_SUCCESS;
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
if (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 (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;
|
|
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;
|
|
|
|
/* Initialise seed checksums */
|
|
pSessionDesc->seedSwCrc.swCrcI = 0;
|
|
pSessionDesc->seedSwCrc.swCrcO = 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;
|
|
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_CRC_MODE_LEGACY);
|
|
|
|
cmdFlags =
|
|
ICP_QAT_FW_COMP_FLAGS_BUILD(sessType,
|
|
autoSelectBest,
|
|
enhancedAutoSelectBest,
|
|
disableType0EnhancedAutoSelectBest,
|
|
secureRam);
|
|
|
|
if (CPA_DC_DIR_DECOMPRESS != pSessionData->sessDirection) {
|
|
if (CPA_DC_HT_FULL_DYNAMIC == pSessionDesc->huffType) {
|
|
dcCmdId = (icp_qat_fw_la_cmd_id_t)(
|
|
ICP_QAT_FW_COMP_CMD_DYNAMIC);
|
|
}
|
|
|
|
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) {
|
|
dcCmdId =
|
|
(icp_qat_fw_la_cmd_id_t)(ICP_QAT_FW_COMP_CMD_DECOMPRESS);
|
|
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;
|
|
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 *)dcInstance)
|
|
->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;
|
|
}
|
|
}
|
|
/* 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
|
|
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)) {
|
|
if (CPA_STATUS_SUCCESS !=
|
|
LAC_SPINLOCK_DESTROY(
|
|
&(pSessionDesc->sessionLock))) {
|
|
QAT_UTILS_LOG(
|
|
"Failed to destory session lock.\n");
|
|
}
|
|
}
|
|
}
|
|
|
|
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);
|
|
}
|