root/sys/dev/qat/qat_api/common/ctrl/sal_crypto.c
/* SPDX-License-Identifier: BSD-3-Clause */
/* Copyright(c) 2007-2025 Intel Corporation */

/**
 ***************************************************************************
 * @file sal_crypto.c     Instance handling functions for crypto
 *
 * @ingroup SalCtrl
 *
 ***************************************************************************/

/*
*******************************************************************************
* Include public/global header files
*******************************************************************************
*/

/* QAT-API includes */
#include "cpa.h"
#include "cpa_types.h"
#include "cpa_cy_common.h"
#include "cpa_cy_im.h"
#include "cpa_cy_key.h"
#include "cpa_cy_sym.h"

#include "qat_utils.h"

/* ADF includes */
#include "icp_adf_init.h"
#include "icp_adf_transport.h"
#include "icp_accel_devices.h"
#include "icp_adf_cfg.h"
#include "icp_adf_accel_mgr.h"
#include "icp_adf_poll.h"
#include "icp_adf_debug.h"

/* SAL includes */
#include "lac_log.h"
#include "lac_mem.h"
#include "lac_mem_pools.h"
#include "sal_statistics.h"
#include "lac_common.h"
#include "lac_list.h"
#include "lac_hooks.h"
#include "lac_sym_qat_hash_defs_lookup.h"
#include "lac_sym.h"
#include "lac_sym_key.h"
#include "lac_sym_hash.h"
#include "lac_sym_cb.h"
#include "lac_sym_stats.h"
#include "lac_sal_types_crypto.h"
#include "lac_sal.h"
#include "lac_sal_ctrl.h"
#include "sal_string_parse.h"
#include "sal_service_state.h"
#include "icp_sal_poll.h"
#include "lac_sync.h"
#include "lac_sym_qat.h"
#include "icp_sal_versions.h"
#include "icp_sal_user.h"
#include "sal_hw_gen.h"

#define HMAC_MODE_1 1
#define HMAC_MODE_2 2
#define TH_CY_RX_0 0
#define TH_CY_RX_1 1
#define MAX_CY_RX_RINGS 2

#define DOUBLE_INCR 2

#define TH_SINGLE_RX 0
#define NUM_CRYPTO_SYM_RX_RINGS 1
#define NUM_CRYPTO_ASYM_RX_RINGS 1
#define NUM_CRYPTO_NRBG_RX_RINGS 1

CpaStatus Lac_GetCyInstancesByType(
    const CpaAccelerationServiceType accelerationServiceType,
    Cpa16U numInstances,
    CpaInstanceHandle *pInstances);

CpaStatus Lac_GetCyNumInstancesByType(
    const CpaAccelerationServiceType accelerationServiceType,
    Cpa16U *pNumInstances);

static CpaInstanceHandle
Lac_CryptoGetFirstHandle(void)
{
        CpaInstanceHandle instHandle;
        instHandle = Lac_GetFirstHandle(SAL_SERVICE_TYPE_CRYPTO);
        if (!instHandle) {
                instHandle = Lac_GetFirstHandle(SAL_SERVICE_TYPE_CRYPTO_SYM);
                if (!instHandle) {
                        instHandle =
                            Lac_GetFirstHandle(SAL_SERVICE_TYPE_CRYPTO_ASYM);
                }
        }
        return instHandle;
}

/* Function to release the sym handles. */
static CpaStatus
SalCtrl_SymReleaseTransHandle(sal_service_t *service)
{

        CpaStatus status = CPA_STATUS_SUCCESS;
        CpaStatus ret_status = CPA_STATUS_SUCCESS;
        sal_crypto_service_t *pCryptoService = (sal_crypto_service_t *)service;

        if (NULL != pCryptoService->trans_handle_sym_tx) {
                status = icp_adf_transReleaseHandle(
                    pCryptoService->trans_handle_sym_tx);
                if (CPA_STATUS_SUCCESS != status) {
                        ret_status = status;
                }
        }
        if (NULL != pCryptoService->trans_handle_sym_rx) {
                status = icp_adf_transReleaseHandle(
                    pCryptoService->trans_handle_sym_rx);
                if (CPA_STATUS_SUCCESS != status) {
                        ret_status = status;
                }
        }

        return ret_status;
}

/*
 * @ingroup sal_crypto
 *     Frees resources (memory and transhandles) if allocated
 *
 * @param[in]  pCryptoService       Pointer to sym service instance
 * @retval                          SUCCESS if transhandles released
 *                                  successfully.
*/
static CpaStatus
SalCtrl_SymFreeResources(sal_crypto_service_t *pCryptoService)
{

        CpaStatus status = CPA_STATUS_SUCCESS;

        /* Free memory pools if not NULL */
        Lac_MemPoolDestroy(pCryptoService->lac_sym_cookie_pool);

        /* Free misc memory if allocated */
        /* Frees memory allocated for Hmac precomputes */
        LacSymHash_HmacPrecompShutdown(pCryptoService);
        /* Free memory allocated for key labels
           Also clears key stats  */
        LacSymKey_Shutdown(pCryptoService);
        /* Free hash lookup table if allocated */
        if (NULL != pCryptoService->pLacHashLookupDefs) {
                LAC_OS_FREE(pCryptoService->pLacHashLookupDefs);
        }

        /* Free statistics */
        LacSym_StatsFree(pCryptoService);

        /* Free transport handles */
        status = SalCtrl_SymReleaseTransHandle((sal_service_t *)pCryptoService);
        return status;
}

/**
 ***********************************************************************
 * @ingroup SalCtrl
 *   This macro verifies that the status is _SUCCESS
 *   If status is not _SUCCESS then Sym Instance resources are
 *   freed before the function returns the error
 *
 * @param[in] status    status we are checking
 *
 * @return void         status is ok (CPA_STATUS_SUCCESS)
 * @return status       The value in the status parameter is an error one
 *
 ****************************************************************************/
#define LAC_CHECK_STATUS_SYM_INIT(status)                                      \
        do {                                                                   \
                if (CPA_STATUS_SUCCESS != status) {                            \
                        SalCtrl_SymFreeResources(pCryptoService);              \
                        return status;                                         \
                }                                                              \
        } while (0)

/* Function that creates the Sym Handles. */
static CpaStatus
SalCtrl_SymCreateTransHandle(icp_accel_dev_t *device,
                             sal_service_t *service,
                             Cpa32U numSymRequests,
                             char *section)
{
        CpaStatus status = CPA_STATUS_SUCCESS;
        char temp_string[SAL_CFG_MAX_VAL_LEN_IN_BYTES] = { 0 };
        sal_crypto_service_t *pCryptoService = (sal_crypto_service_t *)service;
        icp_resp_deliv_method rx_resp_type = ICP_RESP_TYPE_IRQ;
        Cpa32U msgSize = 0;

        if (SAL_RESP_POLL_CFG_FILE == pCryptoService->isPolled) {
                rx_resp_type = ICP_RESP_TYPE_POLL;
        }

        if (CPA_FALSE == pCryptoService->generic_service_info.is_dyn) {
                section = icpGetProcessName();
        }

        /* Parse Sym ring details */
        status =
            Sal_StringParsing("Cy",
                              pCryptoService->generic_service_info.instance,
                              "RingSymTx",
                              temp_string);

        /* Need to free resources in case not _SUCCESS from here */
        LAC_CHECK_STATUS_SYM_INIT(status);

        msgSize = LAC_QAT_SYM_REQ_SZ_LW * LAC_LONG_WORD_IN_BYTES;
        status =
            icp_adf_transCreateHandle(device,
                                      ICP_TRANS_TYPE_ETR,
                                      section,
                                      pCryptoService->acceleratorNum,
                                      pCryptoService->bankNumSym,
                                      temp_string,
                                      lac_getRingType(SAL_RING_TYPE_A_SYM_HI),
                                      NULL,
                                      ICP_RESP_TYPE_NONE,
                                      numSymRequests,
                                      msgSize,
                                      (icp_comms_trans_handle *)&(
                                          pCryptoService->trans_handle_sym_tx));
        LAC_CHECK_STATUS_SYM_INIT(status);

        status =
            Sal_StringParsing("Cy",
                              pCryptoService->generic_service_info.instance,
                              "RingSymRx",
                              temp_string);
        LAC_CHECK_STATUS_SYM_INIT(status);

        msgSize = LAC_QAT_SYM_RESP_SZ_LW * LAC_LONG_WORD_IN_BYTES;
        status = icp_adf_transCreateHandle(
            device,
            ICP_TRANS_TYPE_ETR,
            section,
            pCryptoService->acceleratorNum,
            pCryptoService->bankNumSym,
            temp_string,
            lac_getRingType(SAL_RING_TYPE_NONE),
            (icp_trans_callback)LacSymQat_SymRespHandler,
            rx_resp_type,
            numSymRequests,
            msgSize,
            (icp_comms_trans_handle *)&(pCryptoService->trans_handle_sym_rx));
        LAC_CHECK_STATUS_SYM_INIT(status);

        return status;
}

static int
SalCtrl_CryptoDebug(void *private_data, char *data, int size, int offset)
{
        CpaStatus status = CPA_STATUS_SUCCESS;
        Cpa32U len = 0;
        sal_crypto_service_t *pCryptoService =
            (sal_crypto_service_t *)private_data;

        switch (offset) {
        case SAL_STATS_SYM: {
                CpaCySymStats64 symStats = { 0 };
                if (CPA_TRUE !=
                    pCryptoService->generic_service_info.stats
                        ->bSymStatsEnabled) {
                        break;
                }
                status = cpaCySymQueryStats64(pCryptoService, &symStats);
                if (status != CPA_STATUS_SUCCESS) {
                        LAC_LOG_ERROR("cpaCySymQueryStats64 returned error\n");
                        return 0;
                }

                /* Engine Info */
                len += snprintf(
                    data + len,
                    size - len,
                    SEPARATOR BORDER
                    " Statistics for Instance %24s |\n" BORDER
                    " Symmetric Stats                                  " BORDER
                    "\n" SEPARATOR,
                    pCryptoService->debug_file->name);

                /* Session Info */
                len += snprintf(
                    data + len,
                    size - len,
                    BORDER " Sessions Initialized:           %16llu " BORDER
                           "\n" BORDER
                           " Sessions Removed:               %16llu " BORDER
                           "\n" BORDER
                           " Session Errors:                 %16llu " BORDER
                           "\n" SEPARATOR,
                    (long long unsigned int)symStats.numSessionsInitialized,
                    (long long unsigned int)symStats.numSessionsRemoved,
                    (long long unsigned int)symStats.numSessionErrors);

                /* Session info */
                len += snprintf(
                    data + len,
                    size - len,
                    BORDER " Symmetric Requests:             %16llu " BORDER
                           "\n" BORDER
                           " Symmetric Request Errors:       %16llu " BORDER
                           "\n" BORDER
                           " Symmetric Completed:            %16llu " BORDER
                           "\n" BORDER
                           " Symmetric Completed Errors:     %16llu " BORDER
                           "\n" BORDER
                           " Symmetric Verify Failures:      %16llu " BORDER
                           "\n",
                    (long long unsigned int)symStats.numSymOpRequests,
                    (long long unsigned int)symStats.numSymOpRequestErrors,
                    (long long unsigned int)symStats.numSymOpCompleted,
                    (long long unsigned int)symStats.numSymOpCompletedErrors,
                    (long long unsigned int)symStats.numSymOpVerifyFailures);
                break;
        }
        default: {
                len += snprintf(data + len, size - len, SEPARATOR);
                return 0;
        }
        }
        return ++offset;
}

static CpaStatus
SalCtrl_SymInit(icp_accel_dev_t *device, sal_service_t *service)
{
        CpaStatus status = CPA_STATUS_SUCCESS;
        Cpa32U qatHmacMode = 0;
        Cpa32U numSymConcurrentReq = 0;
        char adfGetParam[ADF_CFG_MAX_VAL_LEN_IN_BYTES] = { 0 };
        char temp_string[SAL_CFG_MAX_VAL_LEN_IN_BYTES] = { 0 };
        sal_crypto_service_t *pCryptoService = (sal_crypto_service_t *)service;
        char *section = DYN_SEC;

        /*Instance may not in the DYN section*/
        if (CPA_FALSE == pCryptoService->generic_service_info.is_dyn) {
                section = icpGetProcessName();
        }

        /* Register callbacks for the symmetric services
        * (Hash, Cipher, Algorithm-Chaining) (returns void)*/
        LacSymCb_CallbacksRegister();

        qatHmacMode = (Cpa32U)Sal_Strtoul(adfGetParam, NULL, SAL_CFG_BASE_DEC);
        switch (qatHmacMode) {
        case HMAC_MODE_1:
                pCryptoService->qatHmacMode = ICP_QAT_HW_AUTH_MODE1;
                break;
        case HMAC_MODE_2:
                pCryptoService->qatHmacMode = ICP_QAT_HW_AUTH_MODE2;
                break;
        default:
                pCryptoService->qatHmacMode = ICP_QAT_HW_AUTH_MODE1;
                break;
        }

        /* Get num concurrent requests from config file */
        status =
            Sal_StringParsing("Cy",
                              pCryptoService->generic_service_info.instance,
                              "NumConcurrentSymRequests",
                              temp_string);
        LAC_CHECK_STATUS(status);
        status =
            icp_adf_cfgGetParamValue(device, section, temp_string, adfGetParam);
        if (CPA_STATUS_SUCCESS != status) {
                QAT_UTILS_LOG("Failed to get %s from configuration file\n",
                              temp_string);
                return status;
        }

        numSymConcurrentReq =
            (Cpa32U)Sal_Strtoul(adfGetParam, NULL, SAL_CFG_BASE_DEC);
        if (CPA_STATUS_FAIL == validateConcurrRequest(numSymConcurrentReq)) {
                LAC_LOG_ERROR("Invalid NumConcurrentSymRequests, valid "
                              "values {64, 128, 256, ... 32768, 65536}");
                return CPA_STATUS_FAIL;
        }

        /* ADF does not allow us to completely fill the ring for batch requests
         */
        pCryptoService->maxNumSymReqBatch =
            (numSymConcurrentReq - SAL_BATCH_SUBMIT_FREE_SPACE);

        /* Create transport handles */
        status = SalCtrl_SymCreateTransHandle(device,
                                              service,
                                              numSymConcurrentReq,
                                              section);
        LAC_CHECK_STATUS(status);

        /* Allocates memory pools */

        /* Create and initialise symmetric cookie memory pool */
        pCryptoService->lac_sym_cookie_pool = LAC_MEM_POOL_INIT_POOL_ID;
        status =
            Sal_StringParsing("Cy",
                              pCryptoService->generic_service_info.instance,
                              "SymPool",
                              temp_string);
        LAC_CHECK_STATUS_SYM_INIT(status);
        /* Note we need twice (i.e. <<1) the number of sym cookies to
           support sym ring pairs (and some, for partials) */
        status =
            Lac_MemPoolCreate(&pCryptoService->lac_sym_cookie_pool,
                              temp_string,
                              ((numSymConcurrentReq + numSymConcurrentReq + 1)
                               << 1),
                              sizeof(lac_sym_cookie_t),
                              LAC_64BYTE_ALIGNMENT,
                              CPA_FALSE,
                              pCryptoService->nodeAffinity);
        LAC_CHECK_STATUS_SYM_INIT(status);
        /* For all sym cookies fill out the physical address of data that
           will be set to QAT */
        Lac_MemPoolInitSymCookiesPhyAddr(pCryptoService->lac_sym_cookie_pool);

        /* Clear stats */
        /* Clears Key stats and allocate memory of SSL and TLS labels
            These labels are initialised to standard values */
        status = LacSymKey_Init(pCryptoService);
        LAC_CHECK_STATUS_SYM_INIT(status);

        /* Initialises the hash lookup table*/
        status = LacSymQat_Init(pCryptoService);
        LAC_CHECK_STATUS_SYM_INIT(status);

        /* Fills out content descriptor for precomputes and registers the
           hash precompute callback */
        status = LacSymHash_HmacPrecompInit(pCryptoService);
        LAC_CHECK_STATUS_SYM_INIT(status);

        /* Init the Sym stats */
        status = LacSym_StatsInit(pCryptoService);
        LAC_CHECK_STATUS_SYM_INIT(status);

        return status;
}

static void
SalCtrl_DebugShutdown(icp_accel_dev_t *device, sal_service_t *service)
{
        sal_crypto_service_t *pCryptoService = (sal_crypto_service_t *)service;
        sal_statistics_collection_t *pStatsCollection =
            (sal_statistics_collection_t *)device->pQatStats;

        if (CPA_TRUE == pStatsCollection->bStatsEnabled) {
                /* Clean stats */
                if (NULL != pCryptoService->debug_file) {
                        icp_adf_debugRemoveFile(pCryptoService->debug_file);
                        LAC_OS_FREE(pCryptoService->debug_file->name);
                        LAC_OS_FREE(pCryptoService->debug_file);
                        pCryptoService->debug_file = NULL;
                }
        }
        pCryptoService->generic_service_info.stats = NULL;
}

static CpaStatus
SalCtrl_DebugInit(icp_accel_dev_t *device, sal_service_t *service)
{
        char adfGetParam[ADF_CFG_MAX_VAL_LEN_IN_BYTES] = { 0 };
        char temp_string[SAL_CFG_MAX_VAL_LEN_IN_BYTES] = { 0 };
        char *instance_name = NULL;
        sal_crypto_service_t *pCryptoService = (sal_crypto_service_t *)service;
        sal_statistics_collection_t *pStatsCollection =
            (sal_statistics_collection_t *)device->pQatStats;
        CpaStatus status = CPA_STATUS_SUCCESS;
        char *section = DYN_SEC;

        /*Instance may not in the DYN section*/
        if (CPA_FALSE == pCryptoService->generic_service_info.is_dyn) {
                section = icpGetProcessName();
        }

        if (CPA_TRUE == pStatsCollection->bStatsEnabled) {
                /* Get instance name for stats */
                instance_name = LAC_OS_MALLOC(ADF_CFG_MAX_VAL_LEN_IN_BYTES);
                if (NULL == instance_name) {
                        return CPA_STATUS_RESOURCE;
                }

                status = Sal_StringParsing(
                    "Cy",
                    pCryptoService->generic_service_info.instance,
                    "Name",
                    temp_string);
                if (CPA_STATUS_SUCCESS != status) {
                        LAC_OS_FREE(instance_name);
                        return status;
                }
                status = icp_adf_cfgGetParamValue(device,
                                                  section,
                                                  temp_string,
                                                  adfGetParam);
                if (CPA_STATUS_SUCCESS != status) {
                        QAT_UTILS_LOG(
                            "Failed to get %s from configuration file\n",
                            temp_string);
                        LAC_OS_FREE(instance_name);
                        return status;
                }
                snprintf(instance_name,
                         ADF_CFG_MAX_VAL_LEN_IN_BYTES,
                         "%s",
                         adfGetParam);

                pCryptoService->debug_file =
                    LAC_OS_MALLOC(sizeof(debug_file_info_t));
                if (NULL == pCryptoService->debug_file) {
                        LAC_OS_FREE(instance_name);
                        return CPA_STATUS_RESOURCE;
                }

                memset(pCryptoService->debug_file,
                       0,
                       sizeof(debug_file_info_t));
                pCryptoService->debug_file->name = instance_name;
                pCryptoService->debug_file->seq_read = SalCtrl_CryptoDebug;
                pCryptoService->debug_file->private_data = pCryptoService;
                pCryptoService->debug_file->parent =
                    pCryptoService->generic_service_info.debug_parent_dir;

                status =
                    icp_adf_debugAddFile(device, pCryptoService->debug_file);
                if (CPA_STATUS_SUCCESS != status) {
                        LAC_OS_FREE(instance_name);
                        LAC_OS_FREE(pCryptoService->debug_file);
                        return status;
                }
        }
        pCryptoService->generic_service_info.stats = pStatsCollection;

        return status;
}

static CpaStatus
SalCtrl_GetBankNum(icp_accel_dev_t *device,
                   Cpa32U inst,
                   char *section,
                   char *bank_name,
                   Cpa16U *bank)
{
        char adfParamValue[ADF_CFG_MAX_VAL_LEN_IN_BYTES] = { 0 };
        char adfParamName[SAL_CFG_MAX_VAL_LEN_IN_BYTES] = { 0 };
        CpaStatus status = CPA_STATUS_SUCCESS;

        status = Sal_StringParsing("Cy", inst, bank_name, adfParamName);
        LAC_CHECK_STATUS(status);
        status = icp_adf_cfgGetParamValue(device,
                                          section,
                                          adfParamName,
                                          adfParamValue);
        if (CPA_STATUS_SUCCESS != status) {
                QAT_UTILS_LOG("Failed to get %s from configuration file\n",
                              adfParamName);
                return status;
        }
        *bank = (Cpa16U)Sal_Strtoul(adfParamValue, NULL, SAL_CFG_BASE_DEC);
        return status;
}

static CpaStatus
SalCtr_InstInit(icp_accel_dev_t *device, sal_service_t *service)
{
        char adfGetParam[ADF_CFG_MAX_VAL_LEN_IN_BYTES] = { 0 };
        char temp_string[SAL_CFG_MAX_VAL_LEN_IN_BYTES] = { 0 };
        char temp_string2[SAL_CFG_MAX_VAL_LEN_IN_BYTES] = { 0 };
        sal_crypto_service_t *pCryptoService = (sal_crypto_service_t *)service;
        CpaStatus status = CPA_STATUS_SUCCESS;
        char *section = DYN_SEC;

        /*Instance may not in the DYN section*/
        if (CPA_FALSE == pCryptoService->generic_service_info.is_dyn) {
                section = icpGetProcessName();
        }

        /* Get Config Info: Accel Num, bank Num, packageID,
                                coreAffinity, nodeAffinity and response mode */

        pCryptoService->acceleratorNum = 0;

        /* Gen4, a bank only has 2 rings (1 ring pair), only one type of service
           can be assigned one time. asym and sym will be in different bank*/
        if (isCyGen4x(pCryptoService)) {
                switch (service->type) {
                case SAL_SERVICE_TYPE_CRYPTO_ASYM:
                        status = SalCtrl_GetBankNum(
                            device,
                            pCryptoService->generic_service_info.instance,
                            section,
                            "BankNumberAsym",
                            &pCryptoService->bankNumAsym);
                        if (CPA_STATUS_SUCCESS != status)
                                return status;
                        break;
                case SAL_SERVICE_TYPE_CRYPTO_SYM:
                        status = SalCtrl_GetBankNum(
                            device,
                            pCryptoService->generic_service_info.instance,
                            section,
                            "BankNumberSym",
                            &pCryptoService->bankNumSym);
                        if (CPA_STATUS_SUCCESS != status)
                                return status;
                        break;
                case SAL_SERVICE_TYPE_CRYPTO:
                        status = SalCtrl_GetBankNum(
                            device,
                            pCryptoService->generic_service_info.instance,
                            section,
                            "BankNumberAsym",
                            &pCryptoService->bankNumAsym);
                        if (CPA_STATUS_SUCCESS != status)
                                return status;
                        status = SalCtrl_GetBankNum(
                            device,
                            pCryptoService->generic_service_info.instance,
                            section,
                            "BankNumberSym",
                            &pCryptoService->bankNumSym);
                        if (CPA_STATUS_SUCCESS != status)
                                return status;
                        break;
                default:
                        return CPA_STATUS_FAIL;
                }
        } else {
                status = SalCtrl_GetBankNum(
                    device,
                    pCryptoService->generic_service_info.instance,
                    section,
                    "BankNumber",
                    &pCryptoService->bankNumSym);
                if (CPA_STATUS_SUCCESS != status)
                        return status;
                pCryptoService->bankNumAsym = pCryptoService->bankNumSym;
        }

        status =
            Sal_StringParsing("Cy",
                              pCryptoService->generic_service_info.instance,
                              "IsPolled",
                              temp_string);
        LAC_CHECK_STATUS(status);
        status =
            icp_adf_cfgGetParamValue(device, section, temp_string, adfGetParam);
        if (CPA_STATUS_SUCCESS != status) {
                QAT_UTILS_LOG("Failed to get %s from configuration file\n",
                              temp_string);
                return status;
        }
        pCryptoService->isPolled =
            (Cpa8U)Sal_Strtoul(adfGetParam, NULL, SAL_CFG_BASE_DEC);

        /* Kernel instances do not support epoll mode */
        if (SAL_RESP_EPOLL_CFG_FILE == pCryptoService->isPolled) {
                QAT_UTILS_LOG(
                    "IsPolled %u is not supported for kernel instance %s",
                    pCryptoService->isPolled,
                    temp_string);
                return CPA_STATUS_FAIL;
        }

        status = icp_adf_cfgGetParamValue(device,
                                          LAC_CFG_SECTION_GENERAL,
                                          ADF_DEV_PKG_ID,
                                          adfGetParam);
        if (CPA_STATUS_SUCCESS != status) {
                QAT_UTILS_LOG("Failed to get %s from configuration file\n",
                              ADF_DEV_PKG_ID);
                return status;
        }
        pCryptoService->pkgID =
            (Cpa16U)Sal_Strtoul(adfGetParam, NULL, SAL_CFG_BASE_DEC);

        status = icp_adf_cfgGetParamValue(device,
                                          LAC_CFG_SECTION_GENERAL,
                                          ADF_DEV_NODE_ID,
                                          adfGetParam);
        if (CPA_STATUS_SUCCESS != status) {
                QAT_UTILS_LOG("Failed to get %s from configuration file\n",
                              ADF_DEV_NODE_ID);
                return status;
        }
        pCryptoService->nodeAffinity =
            (Cpa32U)Sal_Strtoul(adfGetParam, NULL, SAL_CFG_BASE_DEC);
        /* In case of interrupt instance, use the bank affinity set by adf_ctl
         * Otherwise, use the instance affinity for backwards compatibility */
        if (SAL_RESP_POLL_CFG_FILE != pCryptoService->isPolled) {
                /* Next need to read the [AcceleratorX] section of the config
                 * file */
                status = Sal_StringParsing("Accelerator",
                                           pCryptoService->acceleratorNum,
                                           "",
                                           temp_string2);
                LAC_CHECK_STATUS(status);
                if (service->type == SAL_SERVICE_TYPE_CRYPTO_ASYM)
                        status = Sal_StringParsing("Bank",
                                                   pCryptoService->bankNumAsym,
                                                   "CoreAffinity",
                                                   temp_string);
                else
                        /* For cy service, asym bank and sym bank will set the
                           same core affinity. So Just read one*/
                        status = Sal_StringParsing("Bank",
                                                   pCryptoService->bankNumSym,
                                                   "CoreAffinity",
                                                   temp_string);
                LAC_CHECK_STATUS(status);
        } else {
                strncpy(temp_string2, section, (strlen(section) + 1));
                status = Sal_StringParsing(
                    "Cy",
                    pCryptoService->generic_service_info.instance,
                    "CoreAffinity",
                    temp_string);
                LAC_CHECK_STATUS(status);
        }

        status = icp_adf_cfgGetParamValue(device,
                                          temp_string2,
                                          temp_string,
                                          adfGetParam);
        if (CPA_STATUS_SUCCESS != status) {
                QAT_UTILS_LOG("Failed to get %s from configuration file\n",
                              temp_string);
                return status;
        }
        pCryptoService->coreAffinity =
            (Cpa32U)Sal_Strtoul(adfGetParam, NULL, SAL_CFG_BASE_DEC);

        /*No Execution Engine in DH895xcc, so make sure it is zero*/
        pCryptoService->executionEngine = 0;

        return status;
}

/* This function:
 * 1. Creates sym and asym transport handles
 * 2. Allocates memory pools required by sym and asym services
.* 3. Clears the sym and asym stats counters
 * 4. In case service asym or sym is enabled then this function
 *    only allocates resources for these services. i.e if the
 *    service asym is enabled then only asym transport handles
 *    are created and vice versa.
 */
CpaStatus
SalCtrl_CryptoInit(icp_accel_dev_t *device, sal_service_t *service)
{
        CpaStatus status = CPA_STATUS_SUCCESS;
        sal_crypto_service_t *pCryptoService = (sal_crypto_service_t *)service;
        sal_service_type_t svc_type = service->type;

        SAL_SERVICE_GOOD_FOR_INIT(pCryptoService);
        pCryptoService->generic_service_info.state =
            SAL_SERVICE_STATE_INITIALIZING;

        /* Set up the instance parameters such as bank number,
         * coreAffinity, pkgId and node affinity etc
         */
        status = SalCtr_InstInit(device, service);
        LAC_CHECK_STATUS(status);
        /* Create debug directory for service */
        status = SalCtrl_DebugInit(device, service);
        LAC_CHECK_STATUS(status);

        switch (svc_type) {
        case SAL_SERVICE_TYPE_CRYPTO_ASYM:
                break;
        case SAL_SERVICE_TYPE_CRYPTO_SYM:
                status = SalCtrl_SymInit(device, service);
                if (CPA_STATUS_SUCCESS != status) {
                        SalCtrl_DebugShutdown(device, service);
                        return status;
                }
                break;
        case SAL_SERVICE_TYPE_CRYPTO:
                status = SalCtrl_SymInit(device, service);
                if (CPA_STATUS_SUCCESS != status) {
                        SalCtrl_DebugShutdown(device, service);
                        return status;
                }
                break;
        default:
                LAC_LOG_ERROR("Invalid service type\n");
                status = CPA_STATUS_FAIL;
                break;
        }

        pCryptoService->generic_service_info.state =
            SAL_SERVICE_STATE_INITIALIZED;

        return status;
}

CpaStatus
SalCtrl_CryptoStart(icp_accel_dev_t *device, sal_service_t *service)
{
        sal_crypto_service_t *pCryptoService = (sal_crypto_service_t *)service;
        CpaStatus status = CPA_STATUS_SUCCESS;

        if (pCryptoService->generic_service_info.state !=
            SAL_SERVICE_STATE_INITIALIZED) {
                LAC_LOG_ERROR("Not in the correct state to call start\n");
                return CPA_STATUS_FAIL;
        }

        pCryptoService->generic_service_info.state = SAL_SERVICE_STATE_RUNNING;
        return status;
}

CpaStatus
SalCtrl_CryptoStop(icp_accel_dev_t *device, sal_service_t *service)
{
        sal_crypto_service_t *pCryptoService = (sal_crypto_service_t *)service;

        if (SAL_SERVICE_STATE_RUNNING !=
            pCryptoService->generic_service_info.state) {
                LAC_LOG_ERROR("Not in the correct state to call stop");
        }

        pCryptoService->generic_service_info.state =
            SAL_SERVICE_STATE_SHUTTING_DOWN;
        return CPA_STATUS_SUCCESS;
}

CpaStatus
SalCtrl_CryptoShutdown(icp_accel_dev_t *device, sal_service_t *service)
{
        sal_crypto_service_t *pCryptoService = (sal_crypto_service_t *)service;
        CpaStatus status = CPA_STATUS_SUCCESS;
        sal_service_type_t svc_type = service->type;

        if ((SAL_SERVICE_STATE_INITIALIZED !=
             pCryptoService->generic_service_info.state) &&
            (SAL_SERVICE_STATE_SHUTTING_DOWN !=
             pCryptoService->generic_service_info.state)) {
                LAC_LOG_ERROR("Not in the correct state to call shutdown \n");
                return CPA_STATUS_FAIL;
        }

        /* Free memory and transhandles */
        switch (svc_type) {
        case SAL_SERVICE_TYPE_CRYPTO_ASYM:
                break;
        case SAL_SERVICE_TYPE_CRYPTO_SYM:
                if (SalCtrl_SymFreeResources(pCryptoService)) {
                        status = CPA_STATUS_FAIL;
                }
                break;
        case SAL_SERVICE_TYPE_CRYPTO:
                if (SalCtrl_SymFreeResources(pCryptoService)) {
                        status = CPA_STATUS_FAIL;
                }
                break;
        default:
                LAC_LOG_ERROR("Invalid service type\n");
                status = CPA_STATUS_FAIL;
                break;
        }

        SalCtrl_DebugShutdown(device, service);

        pCryptoService->generic_service_info.state = SAL_SERVICE_STATE_SHUTDOWN;

        return status;
}

/**
 ******************************************************************************
 * @ingroup cpaCyCommon
 *****************************************************************************/
CpaStatus
cpaCyGetStatusText(const CpaInstanceHandle instanceHandle,
                   CpaStatus errStatus,
                   Cpa8S *pStatusText)
{
        CpaStatus status = CPA_STATUS_SUCCESS;

        LAC_CHECK_NULL_PARAM(pStatusText);

        switch (errStatus) {
        case CPA_STATUS_SUCCESS:
                LAC_COPY_STRING(pStatusText, CPA_STATUS_STR_SUCCESS);
                break;
        case CPA_STATUS_FAIL:
                LAC_COPY_STRING(pStatusText, CPA_STATUS_STR_FAIL);
                break;
        case CPA_STATUS_RETRY:
                LAC_COPY_STRING(pStatusText, CPA_STATUS_STR_RETRY);
                break;
        case CPA_STATUS_RESOURCE:
                LAC_COPY_STRING(pStatusText, CPA_STATUS_STR_RESOURCE);
                break;
        case CPA_STATUS_INVALID_PARAM:
                LAC_COPY_STRING(pStatusText, CPA_STATUS_STR_INVALID_PARAM);
                break;
        case CPA_STATUS_FATAL:
                LAC_COPY_STRING(pStatusText, CPA_STATUS_STR_FATAL);
                break;
        case CPA_STATUS_UNSUPPORTED:
                LAC_COPY_STRING(pStatusText, CPA_STATUS_STR_UNSUPPORTED);
                break;
        default:
                status = CPA_STATUS_INVALID_PARAM;
                break;
        }
        return status;
}

void
SalCtrl_CyQueryCapabilities(sal_service_t *pGenericService,
                            CpaCyCapabilitiesInfo *pCapInfo)
{
        memset(pCapInfo, 0, sizeof(CpaCyCapabilitiesInfo));

        if (SAL_SERVICE_TYPE_CRYPTO == pGenericService->type ||
            SAL_SERVICE_TYPE_CRYPTO_SYM == pGenericService->type) {
                pCapInfo->symSupported = CPA_TRUE;
                if (pGenericService->capabilitiesMask &
                    ICP_ACCEL_CAPABILITIES_EXT_ALGCHAIN) {
                        pCapInfo->extAlgchainSupported = CPA_TRUE;
                }

                if (pGenericService->capabilitiesMask &
                    ICP_ACCEL_CAPABILITIES_HKDF) {
                        pCapInfo->hkdfSupported = CPA_TRUE;
                }
        }

        if (pGenericService->capabilitiesMask &
            ICP_ACCEL_CAPABILITIES_ECEDMONT) {
                pCapInfo->ecEdMontSupported = CPA_TRUE;
        }

        if (pGenericService->capabilitiesMask &
            ICP_ACCEL_CAPABILITIES_RANDOM_NUMBER) {
                pCapInfo->nrbgSupported = CPA_TRUE;
        }

        pCapInfo->drbgSupported = CPA_FALSE;
        pCapInfo->randSupported = CPA_FALSE;
        pCapInfo->nrbgSupported = CPA_FALSE;
}

/**
 ******************************************************************************
 * @ingroup cpaCyCommon
 *****************************************************************************/
CpaStatus
cpaCyStartInstance(CpaInstanceHandle instanceHandle_in)
{
        CpaInstanceHandle instanceHandle = NULL;
/* Structure initializer is supported by C99, but it is
 * not supported by some former Intel compilers.
 */
        CpaInstanceInfo2 info = { 0 };
        icp_accel_dev_t *dev = NULL;
        CpaStatus status = CPA_STATUS_SUCCESS;
        sal_crypto_service_t *pService = NULL;

        if (CPA_INSTANCE_HANDLE_SINGLE == instanceHandle_in) {
                instanceHandle = Lac_GetFirstHandle(SAL_SERVICE_TYPE_CRYPTO);
                if (!instanceHandle) {
                        instanceHandle =
                            Lac_GetFirstHandle(SAL_SERVICE_TYPE_CRYPTO_SYM);
                }
        } else {
                instanceHandle = instanceHandle_in;
        }
        LAC_CHECK_NULL_PARAM(instanceHandle);
        SAL_CHECK_INSTANCE_TYPE(instanceHandle,
                                (SAL_SERVICE_TYPE_CRYPTO |
                                 SAL_SERVICE_TYPE_CRYPTO_ASYM |
                                 SAL_SERVICE_TYPE_CRYPTO_SYM));

        pService = (sal_crypto_service_t *)instanceHandle;

        status = cpaCyInstanceGetInfo2(instanceHandle, &info);
        if (CPA_STATUS_SUCCESS != status) {
                LAC_LOG_ERROR("Can not get instance info\n");
                return status;
        }
        dev = icp_adf_getAccelDevByAccelId(info.physInstId.packageId);
        if (NULL == dev) {
                LAC_LOG_ERROR("Can not find device for the instance\n");
                return CPA_STATUS_FAIL;
        }

        pService->generic_service_info.isInstanceStarted = CPA_TRUE;

        /* Increment dev ref counter */
        icp_qa_dev_get(dev);
        return CPA_STATUS_SUCCESS;
}

/**
 ******************************************************************************
 * @ingroup cpaCyCommon
 *****************************************************************************/
CpaStatus
cpaCyStopInstance(CpaInstanceHandle instanceHandle_in)
{
        CpaInstanceHandle instanceHandle = NULL;
/* Structure initializer is supported by C99, but it is
 * not supported by some former Intel compilers.
 */
        CpaInstanceInfo2 info = { 0 };
        icp_accel_dev_t *dev = NULL;
        CpaStatus status = CPA_STATUS_SUCCESS;
        sal_crypto_service_t *pService = NULL;

        if (CPA_INSTANCE_HANDLE_SINGLE == instanceHandle_in) {
                instanceHandle = Lac_CryptoGetFirstHandle();
        } else {
                instanceHandle = instanceHandle_in;
        }
        LAC_CHECK_NULL_PARAM(instanceHandle);
        SAL_CHECK_INSTANCE_TYPE(instanceHandle,
                                (SAL_SERVICE_TYPE_CRYPTO |
                                 SAL_SERVICE_TYPE_CRYPTO_ASYM |
                                 SAL_SERVICE_TYPE_CRYPTO_SYM));

        status = cpaCyInstanceGetInfo2(instanceHandle, &info);
        if (CPA_STATUS_SUCCESS != status) {
                LAC_LOG_ERROR("Can not get instance info\n");
                return status;
        }
        dev = icp_adf_getAccelDevByAccelId(info.physInstId.packageId);
        if (NULL == dev) {
                LAC_LOG_ERROR("Can not find device for the instance\n");
                return CPA_STATUS_FAIL;
        }

        pService = (sal_crypto_service_t *)instanceHandle;

        pService->generic_service_info.isInstanceStarted = CPA_FALSE;

        /* Decrement dev ref counter */
        icp_qa_dev_put(dev);
        return CPA_STATUS_SUCCESS;
}

/**
 ******************************************************************************
 * @ingroup cpaCyCommon
 *****************************************************************************/
CpaStatus
cpaCyInstanceSetNotificationCb(
    const CpaInstanceHandle instanceHandle,
    const CpaCyInstanceNotificationCbFunc pInstanceNotificationCb,
    void *pCallbackTag)
{
        CpaStatus status = CPA_STATUS_SUCCESS;
        sal_service_t *gen_handle = instanceHandle;

        LAC_CHECK_NULL_PARAM(gen_handle);
        gen_handle->notification_cb = pInstanceNotificationCb;
        gen_handle->cb_tag = pCallbackTag;
        return status;
}

/**
 ******************************************************************************
 * @ingroup cpaCyCommon
 *****************************************************************************/
CpaStatus
cpaCyGetNumInstances(Cpa16U *pNumInstances)
{
        return Lac_GetCyNumInstancesByType(CPA_ACC_SVC_TYPE_CRYPTO,
                                           pNumInstances);
}

/**
 ******************************************************************************
 * @ingroup cpaCyCommon
 *****************************************************************************/
CpaStatus
cpaCyGetInstances(Cpa16U numInstances, CpaInstanceHandle *pCyInstances)
{
        return Lac_GetCyInstancesByType(CPA_ACC_SVC_TYPE_CRYPTO,
                                        numInstances,
                                        pCyInstances);
}

/**
 ******************************************************************************
 * @ingroup cpaCyCommon
 *****************************************************************************/
CpaStatus
cpaCyInstanceGetInfo(const CpaInstanceHandle instanceHandle_in,
                     struct _CpaInstanceInfo *pInstanceInfo)
{
        CpaInstanceHandle instanceHandle = NULL;
        sal_crypto_service_t *pCryptoService = NULL;
        sal_service_t *pGenericService = NULL;

        Cpa8U name[CPA_INST_NAME_SIZE] =
            "Intel(R) DH89XXCC instance number: %02x, type: Crypto";

        if (CPA_INSTANCE_HANDLE_SINGLE == instanceHandle_in) {
                instanceHandle = Lac_CryptoGetFirstHandle();
        } else {
                instanceHandle = instanceHandle_in;
        }

        LAC_CHECK_NULL_PARAM(instanceHandle);
        LAC_CHECK_NULL_PARAM(pInstanceInfo);
        SAL_CHECK_INSTANCE_TYPE(instanceHandle,
                                (SAL_SERVICE_TYPE_CRYPTO |
                                 SAL_SERVICE_TYPE_CRYPTO_ASYM |
                                 SAL_SERVICE_TYPE_CRYPTO_SYM));

        pCryptoService = (sal_crypto_service_t *)instanceHandle;

        pInstanceInfo->type = CPA_INSTANCE_TYPE_CRYPTO;

        /* According to cpa.h instance state is initialized and ready for use
         * or shutdown. Therefore need to map our running state to initialised
         * or shutdown */
        if (SAL_SERVICE_STATE_RUNNING ==
            pCryptoService->generic_service_info.state) {
                pInstanceInfo->state = CPA_INSTANCE_STATE_INITIALISED;
        } else {
                pInstanceInfo->state = CPA_INSTANCE_STATE_SHUTDOWN;
        }

        pGenericService = (sal_service_t *)instanceHandle;
        snprintf((char *)pInstanceInfo->name,
                 CPA_INST_NAME_SIZE,
                 (char *)name,
                 pGenericService->instance);

        pInstanceInfo->name[CPA_INST_NAME_SIZE - 1] = '\0';

        snprintf((char *)pInstanceInfo->version,
                 CPA_INSTANCE_MAX_NAME_SIZE_IN_BYTES,
                 "%d.%d",
                 CPA_CY_API_VERSION_NUM_MAJOR,
                 CPA_CY_API_VERSION_NUM_MINOR);

        pInstanceInfo->version[CPA_INSTANCE_MAX_VERSION_SIZE_IN_BYTES - 1] =
            '\0';
        return CPA_STATUS_SUCCESS;
}

/**
 ******************************************************************************
 * @ingroup cpaCyCommon
 *****************************************************************************/
CpaStatus
cpaCyInstanceGetInfo2(const CpaInstanceHandle instanceHandle_in,
                      CpaInstanceInfo2 *pInstanceInfo2)
{
        CpaInstanceHandle instanceHandle = NULL;
        sal_crypto_service_t *pCryptoService = NULL;
        icp_accel_dev_t *dev = NULL;
        CpaStatus status = CPA_STATUS_SUCCESS;
        char keyStr[ADF_CFG_MAX_KEY_LEN_IN_BYTES] = { 0 };
        char valStr[ADF_CFG_MAX_VAL_LEN_IN_BYTES] = { 0 };
        char *section = DYN_SEC;

        if (CPA_INSTANCE_HANDLE_SINGLE == instanceHandle_in) {
                instanceHandle = Lac_CryptoGetFirstHandle();
        } else {
                instanceHandle = instanceHandle_in;
        }

        LAC_CHECK_NULL_PARAM(instanceHandle);
        LAC_CHECK_NULL_PARAM(pInstanceInfo2);
        SAL_CHECK_INSTANCE_TYPE(instanceHandle,
                                (SAL_SERVICE_TYPE_CRYPTO |
                                 SAL_SERVICE_TYPE_CRYPTO_ASYM |
                                 SAL_SERVICE_TYPE_CRYPTO_SYM));

        LAC_OS_BZERO(pInstanceInfo2, sizeof(CpaInstanceInfo2));
        pInstanceInfo2->accelerationServiceType = CPA_ACC_SVC_TYPE_CRYPTO;
        snprintf((char *)pInstanceInfo2->vendorName,
                 CPA_INST_VENDOR_NAME_SIZE,
                 "%s",
                 SAL_INFO2_VENDOR_NAME);
        pInstanceInfo2->vendorName[CPA_INST_VENDOR_NAME_SIZE - 1] = '\0';

        snprintf((char *)pInstanceInfo2->swVersion,
                 CPA_INST_SW_VERSION_SIZE,
                 "Version %d.%d",
                 SAL_INFO2_DRIVER_SW_VERSION_MAJ_NUMBER,
                 SAL_INFO2_DRIVER_SW_VERSION_MIN_NUMBER);
        pInstanceInfo2->swVersion[CPA_INST_SW_VERSION_SIZE - 1] = '\0';

        /* Note we can safely read the contents of the crypto service instance
           here because icp_amgr_getAllAccelDevByCapabilities() only returns
           devs
           that have started */
        pCryptoService = (sal_crypto_service_t *)instanceHandle;
        pInstanceInfo2->physInstId.packageId = pCryptoService->pkgID;
        pInstanceInfo2->physInstId.acceleratorId =
            pCryptoService->acceleratorNum;
        pInstanceInfo2->physInstId.executionEngineId =
            pCryptoService->executionEngine;
        pInstanceInfo2->physInstId.busAddress =
            icp_adf_get_busAddress(pInstanceInfo2->physInstId.packageId);

        /*set coreAffinity to zero before use */
        LAC_OS_BZERO(pInstanceInfo2->coreAffinity,
                     sizeof(pInstanceInfo2->coreAffinity));
        CPA_BITMAP_BIT_SET(pInstanceInfo2->coreAffinity,
                           pCryptoService->coreAffinity);
        pInstanceInfo2->nodeAffinity = pCryptoService->nodeAffinity;

        if (SAL_SERVICE_STATE_RUNNING ==
            pCryptoService->generic_service_info.state) {
                pInstanceInfo2->operState = CPA_OPER_STATE_UP;
        } else {
                pInstanceInfo2->operState = CPA_OPER_STATE_DOWN;
        }

        pInstanceInfo2->requiresPhysicallyContiguousMemory = CPA_TRUE;
        if (SAL_RESP_POLL_CFG_FILE == pCryptoService->isPolled) {
                pInstanceInfo2->isPolled = CPA_TRUE;
        } else {
                pInstanceInfo2->isPolled = CPA_FALSE;
        }
        pInstanceInfo2->isOffloaded = CPA_TRUE;

        /* Get the instance name and part name */
        dev = icp_adf_getAccelDevByAccelId(pCryptoService->pkgID);
        if (NULL == dev ||
            0 == strnlen(dev->deviceName, ADF_DEVICE_TYPE_LENGTH + 1)) {
                LAC_LOG_ERROR("Can not find device for the instance\n");
                LAC_OS_BZERO(pInstanceInfo2, sizeof(CpaInstanceInfo2));
                return CPA_STATUS_FAIL;
        }
        snprintf((char *)pInstanceInfo2->partName,
                 CPA_INST_PART_NAME_SIZE,
                 SAL_INFO2_PART_NAME,
                 dev->deviceName);
        pInstanceInfo2->partName[CPA_INST_PART_NAME_SIZE - 1] = '\0';

        status =
            Sal_StringParsing("Cy",
                              pCryptoService->generic_service_info.instance,
                              "Name",
                              keyStr);
        LAC_CHECK_STATUS(status);

        if (CPA_FALSE == pCryptoService->generic_service_info.is_dyn) {
                section = icpGetProcessName();
        }

        status = icp_adf_cfgGetParamValue(dev, section, keyStr, valStr);
        LAC_CHECK_STATUS(status);

        snprintf((char *)pInstanceInfo2->instName,
                 CPA_INST_NAME_SIZE,
                 "%s",
                 valStr);
        snprintf((char *)pInstanceInfo2->instID,
                 CPA_INST_ID_SIZE,
                 "%s_%s",
                 section,
                 valStr);
        return CPA_STATUS_SUCCESS;
}

/**
 ******************************************************************************
 * @ingroup cpaCyCommon
 *****************************************************************************/

CpaStatus
cpaCyQueryCapabilities(const CpaInstanceHandle instanceHandle_in,
                       CpaCyCapabilitiesInfo *pCapInfo)
{
        /* Verify Instance exists */
        CpaInstanceHandle instanceHandle = NULL;

        if (CPA_INSTANCE_HANDLE_SINGLE == instanceHandle_in) {
                instanceHandle = Lac_CryptoGetFirstHandle();
        } else {
                instanceHandle = instanceHandle_in;
        }

        LAC_CHECK_NULL_PARAM(instanceHandle);
        SAL_CHECK_INSTANCE_TYPE(instanceHandle,
                                (SAL_SERVICE_TYPE_CRYPTO |
                                 SAL_SERVICE_TYPE_CRYPTO_ASYM |
                                 SAL_SERVICE_TYPE_CRYPTO_SYM));
        LAC_CHECK_NULL_PARAM(pCapInfo);

        SalCtrl_CyQueryCapabilities((sal_service_t *)instanceHandle, pCapInfo);

        return CPA_STATUS_SUCCESS;
}

/**
 ******************************************************************************
 * @ingroup cpaCySym
 *****************************************************************************/
CpaStatus
cpaCySymQueryCapabilities(const CpaInstanceHandle instanceHandle_in,
                          CpaCySymCapabilitiesInfo *pCapInfo)
{
        sal_crypto_service_t *pCryptoService = NULL;
        sal_service_t *pGenericService = NULL;
        CpaInstanceHandle instanceHandle = NULL;

        /* Verify Instance exists */
        if (CPA_INSTANCE_HANDLE_SINGLE == instanceHandle_in) {
                instanceHandle = Lac_GetFirstHandle(SAL_SERVICE_TYPE_CRYPTO);
                if (!instanceHandle) {
                        instanceHandle =
                            Lac_GetFirstHandle(SAL_SERVICE_TYPE_CRYPTO_SYM);
                }
        } else {
                instanceHandle = instanceHandle_in;
        }

        LAC_CHECK_NULL_PARAM(instanceHandle);
        SAL_CHECK_INSTANCE_TYPE(instanceHandle,
                                (SAL_SERVICE_TYPE_CRYPTO |
                                 SAL_SERVICE_TYPE_CRYPTO_ASYM |
                                 SAL_SERVICE_TYPE_CRYPTO_SYM));
        LAC_CHECK_NULL_PARAM(pCapInfo);

        pCryptoService = (sal_crypto_service_t *)instanceHandle;
        pGenericService = &(pCryptoService->generic_service_info);

        memset(pCapInfo, '\0', sizeof(CpaCySymCapabilitiesInfo));
        /* An asym crypto instance does not support sym service */
        if (SAL_SERVICE_TYPE_CRYPTO_ASYM == pGenericService->type) {
                return CPA_STATUS_SUCCESS;
        }

        CPA_BITMAP_BIT_SET(pCapInfo->ciphers, CPA_CY_SYM_CIPHER_NULL);
        CPA_BITMAP_BIT_SET(pCapInfo->ciphers, CPA_CY_SYM_CIPHER_AES_ECB);
        CPA_BITMAP_BIT_SET(pCapInfo->ciphers, CPA_CY_SYM_CIPHER_AES_CBC);
        CPA_BITMAP_BIT_SET(pCapInfo->ciphers, CPA_CY_SYM_CIPHER_AES_CTR);
        CPA_BITMAP_BIT_SET(pCapInfo->ciphers, CPA_CY_SYM_CIPHER_AES_CCM);
        CPA_BITMAP_BIT_SET(pCapInfo->ciphers, CPA_CY_SYM_CIPHER_AES_GCM);
        CPA_BITMAP_BIT_SET(pCapInfo->ciphers, CPA_CY_SYM_CIPHER_AES_XTS);
        if (isCyGen2x(pCryptoService)) {
                CPA_BITMAP_BIT_SET(pCapInfo->ciphers, CPA_CY_SYM_CIPHER_ARC4);
                CPA_BITMAP_BIT_SET(pCapInfo->ciphers,
                                   CPA_CY_SYM_CIPHER_DES_ECB);
                CPA_BITMAP_BIT_SET(pCapInfo->ciphers,
                                   CPA_CY_SYM_CIPHER_DES_CBC);
                CPA_BITMAP_BIT_SET(pCapInfo->ciphers,
                                   CPA_CY_SYM_CIPHER_3DES_ECB);
                CPA_BITMAP_BIT_SET(pCapInfo->ciphers,
                                   CPA_CY_SYM_CIPHER_3DES_CBC);
                CPA_BITMAP_BIT_SET(pCapInfo->ciphers,
                                   CPA_CY_SYM_CIPHER_3DES_CTR);
                CPA_BITMAP_BIT_SET(pCapInfo->ciphers,
                                   CPA_CY_SYM_CIPHER_KASUMI_F8);
                CPA_BITMAP_BIT_SET(pCapInfo->ciphers,
                                   CPA_CY_SYM_CIPHER_SNOW3G_UEA2);
                CPA_BITMAP_BIT_SET(pCapInfo->ciphers, CPA_CY_SYM_CIPHER_AES_F8);
        }

        CPA_BITMAP_BIT_SET(pCapInfo->hashes, CPA_CY_SYM_HASH_SHA1);
        CPA_BITMAP_BIT_SET(pCapInfo->hashes, CPA_CY_SYM_HASH_SHA224);
        CPA_BITMAP_BIT_SET(pCapInfo->hashes, CPA_CY_SYM_HASH_SHA256);
        CPA_BITMAP_BIT_SET(pCapInfo->hashes, CPA_CY_SYM_HASH_SHA384);
        CPA_BITMAP_BIT_SET(pCapInfo->hashes, CPA_CY_SYM_HASH_SHA512);
        CPA_BITMAP_BIT_SET(pCapInfo->hashes, CPA_CY_SYM_HASH_AES_XCBC);
        CPA_BITMAP_BIT_SET(pCapInfo->hashes, CPA_CY_SYM_HASH_AES_CCM);
        CPA_BITMAP_BIT_SET(pCapInfo->hashes, CPA_CY_SYM_HASH_AES_GCM);
        CPA_BITMAP_BIT_SET(pCapInfo->hashes, CPA_CY_SYM_HASH_AES_CMAC);
        CPA_BITMAP_BIT_SET(pCapInfo->hashes, CPA_CY_SYM_HASH_AES_GMAC);
        CPA_BITMAP_BIT_SET(pCapInfo->hashes, CPA_CY_SYM_HASH_AES_CBC_MAC);
        if (isCyGen2x(pCryptoService)) {
                CPA_BITMAP_BIT_SET(pCapInfo->hashes, CPA_CY_SYM_HASH_MD5);
                CPA_BITMAP_BIT_SET(pCapInfo->hashes, CPA_CY_SYM_HASH_KASUMI_F9);
                CPA_BITMAP_BIT_SET(pCapInfo->hashes,
                                   CPA_CY_SYM_HASH_SNOW3G_UIA2);
        }

        if (pGenericService->capabilitiesMask &
            ICP_ACCEL_CAPABILITIES_CRYPTO_ZUC) {
                CPA_BITMAP_BIT_SET(pCapInfo->ciphers,
                                   CPA_CY_SYM_CIPHER_ZUC_EEA3);
                CPA_BITMAP_BIT_SET(pCapInfo->hashes, CPA_CY_SYM_HASH_ZUC_EIA3);
        }

        if (pGenericService->capabilitiesMask &
            ICP_ACCEL_CAPABILITIES_CHACHA_POLY) {
                CPA_BITMAP_BIT_SET(pCapInfo->hashes, CPA_CY_SYM_HASH_POLY);
                CPA_BITMAP_BIT_SET(pCapInfo->ciphers, CPA_CY_SYM_CIPHER_CHACHA);
        }

        if (pGenericService->capabilitiesMask & ICP_ACCEL_CAPABILITIES_SM3) {
                CPA_BITMAP_BIT_SET(pCapInfo->hashes, CPA_CY_SYM_HASH_SM3);
        }

        pCapInfo->partialPacketSupported = CPA_TRUE;

        if (pGenericService->capabilitiesMask & ICP_ACCEL_CAPABILITIES_SHA3) {
                CPA_BITMAP_BIT_SET(pCapInfo->hashes, CPA_CY_SYM_HASH_SHA3_256);
                pCapInfo->partialPacketSupported = CPA_FALSE;
        }

        if (pGenericService->capabilitiesMask &
            ICP_ACCEL_CAPABILITIES_SHA3_EXT) {
                CPA_BITMAP_BIT_SET(pCapInfo->hashes, CPA_CY_SYM_HASH_SHA3_224);
                CPA_BITMAP_BIT_SET(pCapInfo->hashes, CPA_CY_SYM_HASH_SHA3_256);
                CPA_BITMAP_BIT_SET(pCapInfo->hashes, CPA_CY_SYM_HASH_SHA3_384);
                CPA_BITMAP_BIT_SET(pCapInfo->hashes, CPA_CY_SYM_HASH_SHA3_512);
                pCapInfo->partialPacketSupported = CPA_FALSE;
        }

        if (pGenericService->capabilitiesMask & ICP_ACCEL_CAPABILITIES_SM4) {
                CPA_BITMAP_BIT_SET(pCapInfo->ciphers,
                                   CPA_CY_SYM_CIPHER_SM4_ECB);
                CPA_BITMAP_BIT_SET(pCapInfo->ciphers,
                                   CPA_CY_SYM_CIPHER_SM4_CBC);
                CPA_BITMAP_BIT_SET(pCapInfo->ciphers,
                                   CPA_CY_SYM_CIPHER_SM4_CTR);
                pCapInfo->partialPacketSupported = CPA_FALSE;
        }

        return CPA_STATUS_SUCCESS;
}

/**
 ******************************************************************************
 * @ingroup cpaCyCommon
 *****************************************************************************/
CpaStatus
cpaCySetAddressTranslation(const CpaInstanceHandle instanceHandle_in,
                           CpaVirtualToPhysical virtual2physical)
{

        CpaInstanceHandle instanceHandle = NULL;
        sal_service_t *pService = NULL;

        if (CPA_INSTANCE_HANDLE_SINGLE == instanceHandle_in) {
                instanceHandle = Lac_CryptoGetFirstHandle();
        } else {
                instanceHandle = instanceHandle_in;
        }

        LAC_CHECK_NULL_PARAM(instanceHandle);
        SAL_CHECK_INSTANCE_TYPE(instanceHandle,
                                (SAL_SERVICE_TYPE_CRYPTO |
                                 SAL_SERVICE_TYPE_CRYPTO_ASYM |
                                 SAL_SERVICE_TYPE_CRYPTO_SYM));
        LAC_CHECK_NULL_PARAM(virtual2physical);

        pService = (sal_service_t *)instanceHandle;

        pService->virt2PhysClient = virtual2physical;

        return CPA_STATUS_SUCCESS;
}

/**
 ******************************************************************************
 * @ingroup cpaCyCommon
 * Crypto specific polling function which polls a crypto instance.
 *****************************************************************************/
CpaStatus
icp_sal_CyPollInstance(CpaInstanceHandle instanceHandle_in,
                       Cpa32U response_quota)
{
        CpaStatus status = CPA_STATUS_SUCCESS;
        sal_crypto_service_t *crypto_handle = NULL;
        sal_service_t *gen_handle = NULL;
        icp_comms_trans_handle trans_hndTable[MAX_CY_RX_RINGS] = { 0 };
        Cpa32U num_rx_rings = 0;

        if (CPA_INSTANCE_HANDLE_SINGLE == instanceHandle_in) {
                crypto_handle =
                    (sal_crypto_service_t *)Lac_CryptoGetFirstHandle();
        } else {
                crypto_handle = (sal_crypto_service_t *)instanceHandle_in;
        }
        LAC_CHECK_NULL_PARAM(crypto_handle);
        SAL_RUNNING_CHECK(crypto_handle);
        SAL_CHECK_INSTANCE_TYPE(crypto_handle,
                                (SAL_SERVICE_TYPE_CRYPTO |
                                 SAL_SERVICE_TYPE_CRYPTO_ASYM |
                                 SAL_SERVICE_TYPE_CRYPTO_SYM));

        gen_handle = &(crypto_handle->generic_service_info);

        /*
         * From the instanceHandle we must get the trans_handle and send
         * down to adf for polling.
         * Populate our trans handle table with the appropriate handles.
         */

        switch (gen_handle->type) {
        case SAL_SERVICE_TYPE_CRYPTO_ASYM:
                trans_hndTable[TH_CY_RX_0] =
                    crypto_handle->trans_handle_asym_rx;
                num_rx_rings = 1;
                break;
        case SAL_SERVICE_TYPE_CRYPTO_SYM:
                trans_hndTable[TH_CY_RX_0] = crypto_handle->trans_handle_sym_rx;
                num_rx_rings = 1;
                break;
        case SAL_SERVICE_TYPE_CRYPTO:
                trans_hndTable[TH_CY_RX_0] = crypto_handle->trans_handle_sym_rx;
                trans_hndTable[TH_CY_RX_1] =
                    crypto_handle->trans_handle_asym_rx;
                num_rx_rings = MAX_CY_RX_RINGS;
                break;
        default:
                break;
        }

        /* Call adf to do the polling. */
        status =
            icp_adf_pollInstance(trans_hndTable, num_rx_rings, response_quota);

        return status;
}

/**
 ******************************************************************************
 * @ingroup cpaCyCommon
 * Crypto specific polling function which polls sym crypto ring.
 *****************************************************************************/
CpaStatus
icp_sal_CyPollSymRing(CpaInstanceHandle instanceHandle_in,
                      Cpa32U response_quota)
{
        CpaStatus status = CPA_STATUS_SUCCESS;
        sal_crypto_service_t *crypto_handle = NULL;
        icp_comms_trans_handle trans_hndTable[NUM_CRYPTO_SYM_RX_RINGS] = { 0 };

        if (CPA_INSTANCE_HANDLE_SINGLE == instanceHandle_in) {
                crypto_handle = (sal_crypto_service_t *)Lac_GetFirstHandle(
                    SAL_SERVICE_TYPE_CRYPTO_SYM);
        } else {
                crypto_handle = (sal_crypto_service_t *)instanceHandle_in;
        }
        LAC_CHECK_NULL_PARAM(crypto_handle);
        SAL_CHECK_INSTANCE_TYPE(crypto_handle,
                                (SAL_SERVICE_TYPE_CRYPTO |
                                 SAL_SERVICE_TYPE_CRYPTO_SYM));
        SAL_RUNNING_CHECK(crypto_handle);

        /*
         * From the instanceHandle we must get the trans_handle and send
         * down to adf for polling.
         * Populate our trans handle table with the appropriate handles.
         */
        trans_hndTable[TH_SINGLE_RX] = crypto_handle->trans_handle_sym_rx;
        /* Call adf to do the polling. */
        status = icp_adf_pollInstance(trans_hndTable,
                                      NUM_CRYPTO_SYM_RX_RINGS,
                                      response_quota);
        return status;
}

/**
 ******************************************************************************
 * @ingroup cpaCyCommon
 * Crypto specific polling function which polls an nrbg crypto ring.
 *****************************************************************************/
CpaStatus
icp_sal_CyPollNRBGRing(CpaInstanceHandle instanceHandle_in,
                       Cpa32U response_quota)
{
        return CPA_STATUS_UNSUPPORTED;
}

/* Returns the handle to the first asym crypto instance */
static CpaInstanceHandle
Lac_GetFirstAsymHandle(icp_accel_dev_t *adfInsts[ADF_MAX_DEVICES],
                       Cpa16U num_dev)
{
        CpaStatus status = CPA_STATUS_SUCCESS;
        icp_accel_dev_t *dev_addr = NULL;
        sal_t *base_addr = NULL;
        sal_list_t *list_temp = NULL;
        CpaInstanceHandle cyInst = NULL;
        CpaInstanceInfo2 info;
        Cpa16U i = 0;

        for (i = 0; i < num_dev; i++) {
                dev_addr = (icp_accel_dev_t *)adfInsts[i];
                base_addr = dev_addr->pSalHandle;
                if (NULL == base_addr) {
                        continue;
                }
                list_temp = base_addr->asym_services;
                while (NULL != list_temp) {
                        cyInst = SalList_getObject(list_temp);
                        status = cpaCyInstanceGetInfo2(cyInst, &info);
                        list_temp = SalList_next(list_temp);
                        if (CPA_STATUS_SUCCESS != status ||
                            CPA_TRUE != info.isPolled) {
                                cyInst = NULL;
                                continue;
                        }
                        break;
                }
                if (cyInst) {
                        break;
                }
        }

        return cyInst;
}

/* Returns the handle to the first sym crypto instance */
static CpaInstanceHandle
Lac_GetFirstSymHandle(icp_accel_dev_t *adfInsts[ADF_MAX_DEVICES],
                      Cpa16U num_dev)
{
        CpaStatus status = CPA_STATUS_SUCCESS;
        icp_accel_dev_t *dev_addr = NULL;
        sal_t *base_addr = NULL;
        sal_list_t *list_temp = NULL;
        CpaInstanceHandle cyInst = NULL;
        CpaInstanceInfo2 info;
        Cpa16U i = 0;

        for (i = 0; i < num_dev; i++) {
                dev_addr = (icp_accel_dev_t *)adfInsts[i];
                base_addr = dev_addr->pSalHandle;
                if (NULL == base_addr) {
                        continue;
                }
                list_temp = base_addr->sym_services;
                while (NULL != list_temp) {
                        cyInst = SalList_getObject(list_temp);
                        status = cpaCyInstanceGetInfo2(cyInst, &info);
                        list_temp = SalList_next(list_temp);
                        if (CPA_STATUS_SUCCESS != status ||
                            CPA_TRUE != info.isPolled) {
                                cyInst = NULL;
                                continue;
                        }
                        break;
                }
                if (cyInst) {
                        break;
                }
        }

        return cyInst;
}

/* Returns the handle to the first crypto instance
 * Note that the crypto instance in this case supports
 * both asym and sym services */
static CpaInstanceHandle
Lac_GetFirstCyHandle(icp_accel_dev_t *adfInsts[ADF_MAX_DEVICES], Cpa16U num_dev)
{
        CpaStatus status = CPA_STATUS_SUCCESS;
        icp_accel_dev_t *dev_addr = NULL;
        sal_t *base_addr = NULL;
        sal_list_t *list_temp = NULL;
        CpaInstanceHandle cyInst = NULL;
        CpaInstanceInfo2 info;
        Cpa16U i = 0;

        for (i = 0; i < num_dev; i++) {
                dev_addr = (icp_accel_dev_t *)adfInsts[i];
                base_addr = dev_addr->pSalHandle;
                if (NULL == base_addr) {
                        continue;
                }
                list_temp = base_addr->crypto_services;
                while (NULL != list_temp) {
                        cyInst = SalList_getObject(list_temp);
                        status = cpaCyInstanceGetInfo2(cyInst, &info);
                        list_temp = SalList_next(list_temp);
                        if (CPA_STATUS_SUCCESS != status ||
                            CPA_TRUE != info.isPolled) {
                                cyInst = NULL;
                                continue;
                        }
                        break;
                }
                if (cyInst) {
                        break;
                }
        }

        return cyInst;
}

CpaInstanceHandle
Lac_GetFirstHandle(sal_service_type_t svc_type)
{
        CpaStatus status = CPA_STATUS_SUCCESS;
        static icp_accel_dev_t *adfInsts[ADF_MAX_DEVICES] = { 0 };
        CpaInstanceHandle cyInst = NULL;
        Cpa16U num_cy_dev = 0;
        Cpa32U capabilities = 0;

        switch (svc_type) {
        case SAL_SERVICE_TYPE_CRYPTO_ASYM:
                capabilities = ICP_ACCEL_CAPABILITIES_CRYPTO_ASYMMETRIC;
                break;
        case SAL_SERVICE_TYPE_CRYPTO_SYM:
                capabilities = ICP_ACCEL_CAPABILITIES_CRYPTO_SYMMETRIC;
                break;
        case SAL_SERVICE_TYPE_CRYPTO:
                capabilities = ICP_ACCEL_CAPABILITIES_CRYPTO_ASYMMETRIC;
                capabilities |= ICP_ACCEL_CAPABILITIES_CRYPTO_SYMMETRIC;
                break;
        default:
                LAC_LOG_ERROR("Invalid service type\n");
                return NULL;
        }
        /* Only need 1 dev with crypto enabled - so check all devices*/
        status = icp_amgr_getAllAccelDevByEachCapability(capabilities,
                                                         adfInsts,
                                                         &num_cy_dev);
        if ((0 == num_cy_dev) || (CPA_STATUS_SUCCESS != status)) {
                LAC_LOG_ERROR("No crypto devices enabled in the system\n");
                return NULL;
        }

        switch (svc_type) {
        case SAL_SERVICE_TYPE_CRYPTO_ASYM:
                /* Try to find an asym only instance first */
                cyInst = Lac_GetFirstAsymHandle(adfInsts, num_cy_dev);
                /* Try to find a cy instance since it also supports asym */
                if (NULL == cyInst) {
                        cyInst = Lac_GetFirstCyHandle(adfInsts, num_cy_dev);
                }
                break;
        case SAL_SERVICE_TYPE_CRYPTO_SYM:
                /* Try to find a sym only instance first */
                cyInst = Lac_GetFirstSymHandle(adfInsts, num_cy_dev);
                /* Try to find a cy instance since it also supports sym */
                if (NULL == cyInst) {
                        cyInst = Lac_GetFirstCyHandle(adfInsts, num_cy_dev);
                }
                break;
        case SAL_SERVICE_TYPE_CRYPTO:
                /* Try to find a cy instance */
                cyInst = Lac_GetFirstCyHandle(adfInsts, num_cy_dev);
                break;
        default:
                break;
        }
        if (NULL == cyInst) {
                LAC_LOG_ERROR("No remaining crypto instances available\n");
        }
        return cyInst;
}

CpaStatus
icp_sal_NrbgGetInflightRequests(CpaInstanceHandle instanceHandle_in,
                                Cpa32U *maxInflightRequests,
                                Cpa32U *numInflightRequests)
{
        return CPA_STATUS_UNSUPPORTED;
}

CpaStatus
icp_sal_SymGetInflightRequests(CpaInstanceHandle instanceHandle,
                               Cpa32U *maxInflightRequests,
                               Cpa32U *numInflightRequests)
{
        sal_crypto_service_t *crypto_handle = NULL;

        crypto_handle = (sal_crypto_service_t *)instanceHandle;

        LAC_CHECK_NULL_PARAM(crypto_handle);
        LAC_CHECK_NULL_PARAM(maxInflightRequests);
        LAC_CHECK_NULL_PARAM(numInflightRequests);
        SAL_RUNNING_CHECK(crypto_handle);

        return icp_adf_getInflightRequests(crypto_handle->trans_handle_sym_tx,
                                           maxInflightRequests,
                                           numInflightRequests);
}

CpaStatus
icp_sal_dp_SymGetInflightRequests(CpaInstanceHandle instanceHandle,
                                  Cpa32U *maxInflightRequests,
                                  Cpa32U *numInflightRequests)
{
        sal_crypto_service_t *crypto_handle = NULL;

        crypto_handle = (sal_crypto_service_t *)instanceHandle;

        return icp_adf_dp_getInflightRequests(
            crypto_handle->trans_handle_sym_tx,
            maxInflightRequests,
            numInflightRequests);
}

CpaStatus
icp_sal_setForceAEADMACVerify(CpaInstanceHandle instanceHandle,
                              CpaBoolean forceAEADMacVerify)
{
        sal_crypto_service_t *crypto_handle = NULL;

        crypto_handle = (sal_crypto_service_t *)instanceHandle;
        LAC_CHECK_NULL_PARAM(crypto_handle);
        crypto_handle->forceAEADMacVerify = forceAEADMacVerify;

        return CPA_STATUS_SUCCESS;
}