#include "cpa.h"
#include "qat_utils.h"
#include "icp_accel_devices.h"
#include "icp_adf_init.h"
#include "icp_adf_transport.h"
#include "icp_adf_debug.h"
#include "lac_lock_free_stack.h"
#include "lac_mem_pools.h"
#include "lac_mem.h"
#include "lac_common.h"
#include "cpa_dc.h"
#include "dc_session.h"
#include "dc_datapath.h"
#include "icp_qat_fw_comp.h"
#include "icp_buffer_desc.h"
#include "lac_sym.h"
#define LAC_MEM_POOLS_NUM_SUPPORTED 32000
#define LAC_MEM_POOLS_NAME_SIZE 17
typedef struct lac_mem_pool_hdr_s {
lock_free_stack_t stack;
char poolName[LAC_MEM_POOLS_NAME_SIZE];
unsigned int numElementsInPool;
unsigned int blkSizeInBytes;
unsigned int blkAlignmentInBytes;
lac_mem_blk_t **trackBlks;
volatile size_t availBlks;
} lac_mem_pool_hdr_t;
static lac_mem_pool_hdr_t *lac_mem_pools[LAC_MEM_POOLS_NUM_SUPPORTED] = {
NULL
};
LAC_DECLARE_HIGHEST_BIT_OF(lac_mem_blk_t);
void Lac_MemPoolCleanUpInternal(lac_mem_pool_hdr_t *pPoolID);
static inline Cpa32U
Lac_MemPoolGetElementRealSize(Cpa32U blkSizeInBytes, Cpa32U blkAlignmentInBytes)
{
Cpa32U addSize = (blkAlignmentInBytes >= sizeof(lac_mem_blk_t) ?
blkAlignmentInBytes :
1 << (highest_bit_of_lac_mem_blk_t + 1));
return blkSizeInBytes + addSize;
}
CpaStatus
Lac_MemPoolCreate(lac_memory_pool_id_t *pPoolID,
char *poolName,
unsigned int numElementsInPool,
unsigned int blkSizeInBytes,
unsigned int blkAlignmentInBytes,
CpaBoolean trackMemory,
Cpa32U node)
{
unsigned int poolSearch = 0;
unsigned int counter = 0;
lac_mem_blk_t *pMemBlkCurrent = NULL;
void *pMemBlk = NULL;
if (pPoolID == NULL) {
QAT_UTILS_LOG("Invalid Pool ID param\n");
return CPA_STATUS_INVALID_PARAM;
}
while (lac_mem_pools[poolSearch] != NULL) {
poolSearch++;
if (LAC_MEM_POOLS_NUM_SUPPORTED == poolSearch) {
QAT_UTILS_LOG(
"No more memory pools available for allocation.\n");
return CPA_STATUS_FAIL;
}
}
lac_mem_pools[poolSearch] = LAC_OS_MALLOC(sizeof(lac_mem_pool_hdr_t));
if (NULL == lac_mem_pools[poolSearch]) {
QAT_UTILS_LOG(
"Unable to allocate memory for creation of the pool.\n");
return CPA_STATUS_RESOURCE;
}
memset(lac_mem_pools[poolSearch], 0, sizeof(lac_mem_pool_hdr_t));
if (poolName != NULL) {
snprintf(lac_mem_pools[poolSearch]->poolName,
LAC_MEM_POOLS_NAME_SIZE,
"%s",
poolName);
} else {
LAC_OS_FREE(lac_mem_pools[poolSearch]);
lac_mem_pools[poolSearch] = NULL;
QAT_UTILS_LOG("Invalid Pool Name pointer\n");
return CPA_STATUS_INVALID_PARAM;
}
if (CPA_TRUE == trackMemory) {
lac_mem_pools[poolSearch]->trackBlks = LAC_OS_MALLOC(
(sizeof(lac_mem_blk_t *) * numElementsInPool));
if (NULL == lac_mem_pools[poolSearch]->trackBlks) {
LAC_OS_FREE(lac_mem_pools[poolSearch]);
lac_mem_pools[poolSearch] = NULL;
QAT_UTILS_LOG(
"Unable to allocate memory for tracking memory blocks.\n");
return CPA_STATUS_RESOURCE;
}
} else {
lac_mem_pools[poolSearch]->trackBlks = NULL;
}
lac_mem_pools[poolSearch]->availBlks = 0;
lac_mem_pools[poolSearch]->stack = _init_stack();
for (counter = 0; counter < numElementsInPool; counter++) {
CpaPhysicalAddr physAddr = 0;
Cpa32U realSize =
Lac_MemPoolGetElementRealSize(blkSizeInBytes,
blkAlignmentInBytes);
Cpa32U addSize = realSize - blkSizeInBytes;
if (CPA_STATUS_SUCCESS != LAC_OS_CAMALLOC(&pMemBlk,
realSize,
blkAlignmentInBytes,
node)) {
Lac_MemPoolCleanUpInternal(lac_mem_pools[poolSearch]);
lac_mem_pools[poolSearch] = NULL;
QAT_UTILS_LOG(
"Unable to allocate contiguous chunk of memory.\n");
return CPA_STATUS_RESOURCE;
}
physAddr = LAC_OS_VIRT_TO_PHYS_INTERNAL(
(void *)((LAC_ARCH_UINT)pMemBlk + addSize));
pMemBlkCurrent =
(lac_mem_blk_t *)(((LAC_ARCH_UINT)(pMemBlk)) + addSize -
sizeof(lac_mem_blk_t));
pMemBlkCurrent->physDataPtr = physAddr;
pMemBlkCurrent->pMemAllocPtr = pMemBlk;
pMemBlkCurrent->pPoolID = lac_mem_pools[poolSearch];
pMemBlkCurrent->isInUse = CPA_FALSE;
pMemBlkCurrent->pNext = NULL;
push(&lac_mem_pools[poolSearch]->stack, pMemBlkCurrent);
if (lac_mem_pools[poolSearch]->trackBlks != NULL) {
(lac_mem_pools[poolSearch]->trackBlks[counter]) =
(lac_mem_blk_t *)pMemBlkCurrent;
}
__sync_add_and_fetch(&lac_mem_pools[poolSearch]->availBlks, 1);
(lac_mem_pools[poolSearch])->numElementsInPool = counter + 1;
}
(lac_mem_pools[poolSearch])->blkSizeInBytes = blkSizeInBytes;
(lac_mem_pools[poolSearch])->blkAlignmentInBytes = blkAlignmentInBytes;
*pPoolID = (LAC_ARCH_UINT)(lac_mem_pools[poolSearch]);
return CPA_STATUS_SUCCESS;
}
void *
Lac_MemPoolEntryAlloc(lac_memory_pool_id_t poolID)
{
lac_mem_pool_hdr_t *pPoolID = (lac_mem_pool_hdr_t *)poolID;
lac_mem_blk_t *pMemBlkCurrent = NULL;
if (pPoolID == NULL) {
QAT_UTILS_LOG("Invalid Pool ID");
return NULL;
}
pMemBlkCurrent = pop(&pPoolID->stack);
if (NULL == pMemBlkCurrent) {
return (void *)CPA_STATUS_RETRY;
}
__sync_sub_and_fetch(&pPoolID->availBlks, 1);
pMemBlkCurrent->isInUse = CPA_TRUE;
return (void *)((LAC_ARCH_UINT)(pMemBlkCurrent) +
sizeof(lac_mem_blk_t));
}
void
Lac_MemPoolEntryFree(void *pEntry)
{
lac_mem_blk_t *pMemBlk = NULL;
if (pEntry == NULL) {
QAT_UTILS_LOG("Memory Handle NULL");
return;
}
pMemBlk =
(lac_mem_blk_t *)((LAC_ARCH_UINT)pEntry - sizeof(lac_mem_blk_t));
pMemBlk->isInUse = CPA_FALSE;
push(&pMemBlk->pPoolID->stack, pMemBlk);
__sync_add_and_fetch(&pMemBlk->pPoolID->availBlks, 1);
}
void
Lac_MemPoolDestroy(lac_memory_pool_id_t poolID)
{
unsigned int poolSearch = 0;
lac_mem_pool_hdr_t *pPoolID = (lac_mem_pool_hdr_t *)poolID;
if (pPoolID != NULL) {
while (lac_mem_pools[poolSearch] != pPoolID) {
poolSearch++;
if (LAC_MEM_POOLS_NUM_SUPPORTED == poolSearch) {
QAT_UTILS_LOG("Invalid Pool ID submitted.\n");
return;
}
}
lac_mem_pools[poolSearch] = NULL;
Lac_MemPoolCleanUpInternal(pPoolID);
}
}
void
Lac_MemPoolCleanUpInternal(lac_mem_pool_hdr_t *pPoolID)
{
lac_mem_blk_t *pCurrentBlk = NULL;
void *pFreePtr = NULL;
Cpa32U count = 0;
if (pPoolID->trackBlks == NULL) {
pCurrentBlk = pop(&pPoolID->stack);
while (pCurrentBlk != NULL) {
pFreePtr = pCurrentBlk->pMemAllocPtr;
pCurrentBlk = pop(&pPoolID->stack);
LAC_OS_CAFREE(pFreePtr);
}
} else {
for (count = 0; count < pPoolID->numElementsInPool; count++) {
pFreePtr = (pPoolID->trackBlks[count])->pMemAllocPtr;
LAC_OS_CAFREE(pFreePtr);
}
LAC_OS_FREE(pPoolID->trackBlks);
}
LAC_OS_FREE(pPoolID);
}
unsigned int
Lac_MemPoolAvailableEntries(lac_memory_pool_id_t poolID)
{
lac_mem_pool_hdr_t *pPoolID = (lac_mem_pool_hdr_t *)poolID;
if (pPoolID == NULL) {
QAT_UTILS_LOG("Invalid Pool ID\n");
return 0;
}
return pPoolID->availBlks;
}
void
Lac_MemPoolStatsShow(void)
{
unsigned int index = 0;
QAT_UTILS_LOG(SEPARATOR BORDER
" Memory Pools Stats\n" SEPARATOR);
while (index < LAC_MEM_POOLS_NUM_SUPPORTED) {
if (lac_mem_pools[index] != NULL) {
QAT_UTILS_LOG(
BORDER " Pool Name: %s \n" BORDER
" No. Elements in Pool: %10u \n" BORDER
" Element Size in Bytes: %10u \n" BORDER
" Alignment in Bytes: %10u \n" BORDER
" No. Available Blocks: %10zu \n" SEPARATOR,
lac_mem_pools[index]->poolName,
lac_mem_pools[index]->numElementsInPool,
lac_mem_pools[index]->blkSizeInBytes,
lac_mem_pools[index]->blkAlignmentInBytes,
lac_mem_pools[index]->availBlks);
}
index++;
}
}
static void
Lac_MemPoolInitSymCookies(lac_sym_cookie_t *pSymCookie)
{
pSymCookie->keyContentDescPhyAddr =
LAC_OS_VIRT_TO_PHYS_INTERNAL(pSymCookie->u.keyCookie.contentDesc);
pSymCookie->keyHashStateBufferPhyAddr = LAC_OS_VIRT_TO_PHYS_INTERNAL(
pSymCookie->u.keyCookie.hashStateBuffer);
pSymCookie->keySslKeyInputPhyAddr = LAC_OS_VIRT_TO_PHYS_INTERNAL(
&(pSymCookie->u.keyCookie.u.sslKeyInput));
pSymCookie->keyTlsKeyInputPhyAddr = LAC_OS_VIRT_TO_PHYS_INTERNAL(
&(pSymCookie->u.keyCookie.u.tlsKeyInput));
}
CpaStatus
Lac_MemPoolInitSymCookiesPhyAddr(lac_memory_pool_id_t poolID)
{
lac_mem_pool_hdr_t *pPoolID = (lac_mem_pool_hdr_t *)poolID;
lac_sym_cookie_t *pSymCookie = NULL;
lac_mem_blk_t *pCurrentBlk = NULL;
if (NULL == pPoolID) {
QAT_UTILS_LOG("Invalid Pool ID\n");
return CPA_STATUS_FAIL;
}
if (pPoolID->trackBlks == NULL) {
pCurrentBlk = top(&pPoolID->stack);
while (pCurrentBlk != NULL) {
pSymCookie =
(lac_sym_cookie_t *)((LAC_ARCH_UINT)(pCurrentBlk) +
sizeof(lac_mem_blk_t));
pCurrentBlk = pCurrentBlk->pNext;
Lac_MemPoolInitSymCookies(pSymCookie);
}
} else {
Cpa32U count = 0;
for (count = 0; count < pPoolID->numElementsInPool; count++) {
pCurrentBlk = pPoolID->trackBlks[count];
pSymCookie =
(lac_sym_cookie_t *)((LAC_ARCH_UINT)(pCurrentBlk) +
sizeof(lac_mem_blk_t));
Lac_MemPoolInitSymCookies(pSymCookie);
}
}
return CPA_STATUS_SUCCESS;
}
CpaStatus
Lac_MemPoolInitDcCookiePhyAddr(lac_memory_pool_id_t poolID)
{
lac_mem_pool_hdr_t *pPoolID = (lac_mem_pool_hdr_t *)poolID;
lac_mem_blk_t *pCurrentBlk = NULL;
if (NULL == pPoolID) {
QAT_UTILS_LOG("Invalid Pool ID\n");
return CPA_STATUS_FAIL;
}
if (NULL == pPoolID->trackBlks) {
pCurrentBlk = top(&pPoolID->stack);
while (pCurrentBlk != NULL) {
pCurrentBlk = pCurrentBlk->pNext;
}
} else {
Cpa32U count = 0;
for (count = 0; count < pPoolID->numElementsInPool; count++) {
pCurrentBlk = pPoolID->trackBlks[count];
}
}
return CPA_STATUS_SUCCESS;
}