#include "cpa.h"
#include "cpa_cy_key.h"
#include "cpa_cy_ln.h"
#include "cpa_cy_dh.h"
#include "cpa_cy_dsa.h"
#include "cpa_cy_rsa.h"
#include "cpa_cy_ec.h"
#include "cpa_cy_prime.h"
#include "cpa_cy_sym.h"
#include "cpa_dc.h"
#include "qat_utils.h"
#include "icp_adf_init.h"
#include "icp_adf_transport.h"
#include "icp_accel_devices.h"
#include "icp_adf_cfg.h"
#include "icp_adf_init.h"
#include "icp_adf_accel_mgr.h"
#include "icp_adf_debug.h"
#include "icp_qat_fw_la.h"
#include "lac_mem.h"
#include "lac_mem_pools.h"
#include "lac_list.h"
#include "lac_hooks.h"
#include "sal_string_parse.h"
#include "lac_common.h"
#include "lac_sal_types.h"
#include "lac_sal.h"
#include "lac_sal_ctrl.h"
#include "icp_sal_versions.h"
#define MAX_SUBSYSTEM_RETRY 64
static char *subsystem_name = "SAL";
static char *cy_dir_name = "cy";
static char *asym_dir_name = "asym";
static char *sym_dir_name = "sym";
static char *dc_dir_name = "dc";
static char *ver_file_name = "version";
static subservice_registation_handle_t sal_service_reg_handle;
CpaStatus
SalCtrl_GetEnabledServices(icp_accel_dev_t *device, Cpa32U *pEnabledServices)
{
CpaStatus status = CPA_STATUS_SUCCESS;
char param_value[ADF_CFG_MAX_VAL_LEN_IN_BYTES] = { 0 };
char *token = NULL;
char *running = NULL;
*pEnabledServices = 0;
memset(param_value, 0, ADF_CFG_MAX_VAL_LEN_IN_BYTES);
status = icp_adf_cfgGetParamValue(device,
LAC_CFG_SECTION_GENERAL,
"ServicesEnabled",
param_value);
if (CPA_STATUS_SUCCESS == status) {
running = param_value;
token = strsep(&running, ";");
while (NULL != token) {
do {
if (strncmp(token, "asym", strlen("asym")) ==
0) {
*pEnabledServices |=
SAL_SERVICE_TYPE_CRYPTO_ASYM;
break;
}
if (strncmp(token, "sym", strlen("sym")) == 0) {
*pEnabledServices |=
SAL_SERVICE_TYPE_CRYPTO_SYM;
break;
}
if (strncmp(token, "cy", strlen("cy")) == 0) {
*pEnabledServices |=
SAL_SERVICE_TYPE_CRYPTO;
break;
}
if (strncmp(token, "dc", strlen("dc")) == 0) {
*pEnabledServices |=
SAL_SERVICE_TYPE_COMPRESSION;
break;
}
QAT_UTILS_LOG(
"Error parsing enabled services from ADF.\n");
return CPA_STATUS_FAIL;
} while (0);
token = strsep(&running, ";");
}
} else {
QAT_UTILS_LOG("Failed to get enabled services from ADF.\n");
}
return status;
}
CpaBoolean
SalCtrl_IsServiceEnabled(Cpa32U enabled_services, sal_service_type_t service)
{
return (CpaBoolean)((enabled_services & (Cpa32U)(service)) != 0);
}
CpaStatus
SalCtrl_GetSupportedServices(icp_accel_dev_t *device, Cpa32U enabled_services)
{
CpaStatus status = CPA_STATUS_SUCCESS;
Cpa32U capabilitiesMask = 0;
status = icp_amgr_getAccelDevCapabilities(device, &capabilitiesMask);
if (CPA_STATUS_SUCCESS == status) {
if (SalCtrl_IsServiceEnabled(enabled_services,
SAL_SERVICE_TYPE_CRYPTO)) {
if (!(capabilitiesMask &
ICP_ACCEL_CAPABILITIES_CRYPTO_SYMMETRIC) ||
!(capabilitiesMask &
ICP_ACCEL_CAPABILITIES_CRYPTO_ASYMMETRIC)) {
QAT_UTILS_LOG(
"Device does not support Crypto service\n");
status = CPA_STATUS_FAIL;
}
}
if (SalCtrl_IsServiceEnabled(enabled_services,
SAL_SERVICE_TYPE_CRYPTO_ASYM)) {
if (!(capabilitiesMask &
ICP_ACCEL_CAPABILITIES_CRYPTO_ASYMMETRIC)) {
QAT_UTILS_LOG(
"Device does not support Asym service\n");
status = CPA_STATUS_FAIL;
}
}
if (SalCtrl_IsServiceEnabled(enabled_services,
SAL_SERVICE_TYPE_CRYPTO_SYM)) {
if (!(capabilitiesMask &
ICP_ACCEL_CAPABILITIES_CRYPTO_SYMMETRIC)) {
QAT_UTILS_LOG(
"Device does not support Sym service\n");
status = CPA_STATUS_FAIL;
}
}
if (SalCtrl_IsServiceEnabled(enabled_services,
SAL_SERVICE_TYPE_COMPRESSION)) {
if (!(capabilitiesMask &
ICP_ACCEL_CAPABILITIES_COMPRESSION)) {
QAT_UTILS_LOG(
"Device does not support Compression service.\n");
status = CPA_STATUS_FAIL;
}
}
}
return status;
}
CpaBoolean
SalCtrl_IsServiceSupported(icp_accel_dev_t *device,
sal_service_type_t service_to_check)
{
CpaStatus status = CPA_STATUS_SUCCESS;
Cpa32U capabilitiesMask = 0;
CpaBoolean service_supported = CPA_TRUE;
if (!(SalCtrl_IsServiceEnabled((Cpa32U)service_to_check,
SAL_SERVICE_TYPE_CRYPTO)) &&
!(SalCtrl_IsServiceEnabled((Cpa32U)service_to_check,
SAL_SERVICE_TYPE_CRYPTO_ASYM)) &&
!(SalCtrl_IsServiceEnabled((Cpa32U)service_to_check,
SAL_SERVICE_TYPE_CRYPTO_SYM)) &&
!(SalCtrl_IsServiceEnabled((Cpa32U)service_to_check,
SAL_SERVICE_TYPE_COMPRESSION))) {
QAT_UTILS_LOG("Invalid service type\n");
service_supported = CPA_FALSE;
}
status = icp_amgr_getAccelDevCapabilities(device, &capabilitiesMask);
if (CPA_STATUS_SUCCESS != status) {
QAT_UTILS_LOG("Can not get device capabilities.\n");
return CPA_FALSE;
}
if (SalCtrl_IsServiceEnabled((Cpa32U)service_to_check,
SAL_SERVICE_TYPE_CRYPTO)) {
if (!(capabilitiesMask &
ICP_ACCEL_CAPABILITIES_CRYPTO_SYMMETRIC) ||
!(capabilitiesMask &
ICP_ACCEL_CAPABILITIES_CRYPTO_ASYMMETRIC)) {
QAT_UTILS_LOG(
"Device does not support Crypto service\n");
service_supported = CPA_FALSE;
}
}
if (SalCtrl_IsServiceEnabled((Cpa32U)service_to_check,
SAL_SERVICE_TYPE_CRYPTO_ASYM)) {
if (!(capabilitiesMask &
ICP_ACCEL_CAPABILITIES_CRYPTO_ASYMMETRIC)) {
QAT_UTILS_LOG("Device does not support Asym service\n");
service_supported = CPA_FALSE;
}
}
if (SalCtrl_IsServiceEnabled((Cpa32U)service_to_check,
SAL_SERVICE_TYPE_CRYPTO_SYM)) {
if (!(capabilitiesMask &
ICP_ACCEL_CAPABILITIES_CRYPTO_SYMMETRIC)) {
QAT_UTILS_LOG("Device does not support Sym service\n");
service_supported = CPA_FALSE;
}
}
if (SalCtrl_IsServiceEnabled((Cpa32U)service_to_check,
SAL_SERVICE_TYPE_COMPRESSION)) {
if (!(capabilitiesMask & ICP_ACCEL_CAPABILITIES_COMPRESSION)) {
QAT_UTILS_LOG(
"Device does not support Compression service.\n");
service_supported = CPA_FALSE;
}
}
return service_supported;
}
static CpaStatus
SalCtrl_GetInstanceCount(icp_accel_dev_t *device, char *key, Cpa32U *pCount)
{
CpaStatus status = CPA_STATUS_FAIL;
char param_value[ADF_CFG_MAX_VAL_LEN_IN_BYTES];
memset(param_value, 0, ADF_CFG_MAX_VAL_LEN_IN_BYTES);
status = icp_adf_cfgGetParamValue(device,
icpGetProcessName(),
key,
param_value);
if (CPA_STATUS_SUCCESS == status) {
*pCount =
(Cpa32U)(Sal_Strtoul(param_value, NULL, SAL_CFG_BASE_DEC));
if (*pCount > SAL_MAX_NUM_INSTANCES_PER_DEV) {
QAT_UTILS_LOG("Number of instances is out of range.\n");
status = CPA_STATUS_FAIL;
}
}
return status;
}
static CpaStatus
SalCtrl_ServiceShutdown(icp_accel_dev_t *device,
sal_list_t **services,
debug_dir_info_t **debug_dir,
sal_service_type_t svc_type)
{
CpaStatus status = CPA_STATUS_SUCCESS;
sal_list_t *dyn_service = NULL;
sal_service_t *inst = NULL;
SAL_FOR_EACH(*services, sal_service_t, device, shutdown, status);
if (*debug_dir) {
icp_adf_debugRemoveDir(*debug_dir);
LAC_OS_FREE(*debug_dir);
*debug_dir = NULL;
}
if (!icp_adf_is_dev_in_reset(device)) {
dyn_service = *services;
while (dyn_service) {
inst = (sal_service_t *)SalList_getObject(dyn_service);
if (CPA_TRUE == inst->is_dyn) {
icp_adf_putDynInstance(device,
(adf_service_type_t)
svc_type,
inst->instance);
}
dyn_service = SalList_next(dyn_service);
}
SalList_free(services);
} else {
sal_list_t *curr_element = NULL;
sal_service_t *service = NULL;
curr_element = *services;
while (NULL != curr_element) {
service =
(sal_service_t *)SalList_getObject(curr_element);
service->state = SAL_SERVICE_STATE_RESTARTING;
curr_element = SalList_next(curr_element);
}
}
return status;
}
static CpaStatus
selectGeneration(device_type_t deviceType, sal_service_t *pInst)
{
switch (deviceType) {
case DEVICE_C62X:
case DEVICE_C62XVF:
case DEVICE_DH895XCC:
case DEVICE_DH895XCCVF:
case DEVICE_C3XXX:
case DEVICE_C3XXXVF:
case DEVICE_200XX:
case DEVICE_200XXVF:
pInst->gen = GEN2;
break;
case DEVICE_C4XXX:
case DEVICE_C4XXXVF:
pInst->gen = GEN3;
break;
case DEVICE_4XXX:
case DEVICE_4XXXVF:
pInst->gen = GEN4;
break;
default:
QAT_UTILS_LOG("deviceType not initialised\n");
return CPA_STATUS_FAIL;
}
return CPA_STATUS_SUCCESS;
}
static CpaStatus
SalCtrl_ServiceInit(icp_accel_dev_t *device,
sal_list_t **services,
debug_dir_info_t **dbg_dir,
char *dbg_dir_name,
sal_list_t *tail_list,
Cpa32U instance_count,
sal_service_type_t svc_type)
{
CpaStatus status = CPA_STATUS_SUCCESS;
sal_service_t *pInst = NULL;
Cpa32U i = 0;
debug_dir_info_t *debug_dir = NULL;
debug_dir = LAC_OS_MALLOC(sizeof(debug_dir_info_t));
if (NULL == debug_dir) {
QAT_UTILS_LOG("Failed to allocate memory for debug dir.\n");
return CPA_STATUS_RESOURCE;
}
debug_dir->name = dbg_dir_name;
debug_dir->parent = NULL;
status = icp_adf_debugAddDir(device, debug_dir);
if (CPA_STATUS_SUCCESS != status) {
QAT_UTILS_LOG("Failed to add debug dir.\n");
LAC_OS_FREE(debug_dir);
debug_dir = NULL;
return status;
}
if (!icp_adf_is_dev_in_reset(device)) {
for (i = 0; i < instance_count; i++) {
status = SalCtrl_ServiceCreate(svc_type, i, &pInst);
if (CPA_STATUS_SUCCESS != status) {
break;
}
pInst->debug_parent_dir = debug_dir;
pInst->capabilitiesMask = device->accelCapabilitiesMask;
status = selectGeneration(device->deviceType, pInst);
if (CPA_STATUS_SUCCESS == status) {
status =
SalList_add(services, &tail_list, pInst);
}
if (CPA_STATUS_SUCCESS != status) {
free(pInst, M_QAT);
}
}
} else {
sal_list_t *curr_element = *services;
sal_service_t *service = NULL;
while (NULL != curr_element) {
service =
(sal_service_t *)SalList_getObject(curr_element);
service->debug_parent_dir = debug_dir;
if (CPA_TRUE == service->isInstanceStarted) {
icp_qa_dev_get(device);
}
curr_element = SalList_next(curr_element);
}
}
if (CPA_STATUS_SUCCESS != status) {
QAT_UTILS_LOG("Failed to allocate all instances.\n");
icp_adf_debugRemoveDir(debug_dir);
LAC_OS_FREE(debug_dir);
debug_dir = NULL;
SalList_free(services);
return status;
}
SAL_FOR_EACH(*services, sal_service_t, device, init, status);
if (CPA_STATUS_SUCCESS != status) {
QAT_UTILS_LOG("Failed to initialise all service instances.\n");
SAL_FOR_EACH_STATE(*services,
sal_service_t,
device,
shutdown,
SAL_SERVICE_STATE_INITIALIZED);
icp_adf_debugRemoveDir(debug_dir);
LAC_OS_FREE(debug_dir);
debug_dir = NULL;
SalList_free(services);
return status;
}
*dbg_dir = debug_dir;
return status;
}
static CpaStatus
SalCtrl_ServiceStart(icp_accel_dev_t *device, sal_list_t *services)
{
CpaStatus status = CPA_STATUS_SUCCESS;
SAL_FOR_EACH(services, sal_service_t, device, start, status);
if (CPA_STATUS_SUCCESS != status) {
QAT_UTILS_LOG("Failed to start all instances.\n");
SAL_FOR_EACH_STATE(services,
sal_service_t,
device,
stop,
SAL_SERVICE_STATE_RUNNING);
return status;
}
if (icp_adf_is_dev_in_reset(device)) {
sal_list_t *curr_element = services;
sal_service_t *service = NULL;
while (NULL != curr_element) {
service =
(sal_service_t *)SalList_getObject(curr_element);
if (service->notification_cb) {
service->notification_cb(
service,
service->cb_tag,
CPA_INSTANCE_EVENT_RESTARTED);
}
curr_element = SalList_next(curr_element);
}
}
return status;
}
static CpaStatus
SalCtrl_ServiceStop(icp_accel_dev_t *device, sal_list_t *services)
{
CpaStatus status = CPA_STATUS_SUCCESS;
if (icp_adf_is_dev_in_reset(device)) {
sal_list_t *curr_element = services;
sal_service_t *service = NULL;
while (NULL != curr_element) {
service =
(sal_service_t *)SalList_getObject(curr_element);
if (service->notification_cb) {
service->notification_cb(
service,
service->cb_tag,
CPA_INSTANCE_EVENT_RESTARTING);
}
curr_element = SalList_next(curr_element);
}
}
SAL_FOR_EACH(services, sal_service_t, device, stop, status);
return status;
}
static CpaStatus
SalCtrl_ServiceError(icp_accel_dev_t *device, sal_list_t *services)
{
CpaStatus status = CPA_STATUS_SUCCESS;
sal_list_t *curr_element = services;
sal_service_t *service = NULL;
while (NULL != curr_element) {
service = (sal_service_t *)SalList_getObject(curr_element);
if (service->notification_cb) {
service->notification_cb(
service,
service->cb_tag,
CPA_INSTANCE_EVENT_FATAL_ERROR);
}
curr_element = SalList_next(curr_element);
}
return status;
}
static int
SalCtrl_VersionDebug(void *private_data, char *data, int size, int offset)
{
CpaStatus status = CPA_STATUS_SUCCESS;
Cpa32U len = 0;
icp_accel_dev_t *device = (icp_accel_dev_t *)private_data;
char param_value[ADF_CFG_MAX_VAL_LEN_IN_BYTES] = { 0 };
len += snprintf(
data + len,
size - len,
SEPARATOR BORDER
" Hardware and Software versions for device %d " BORDER
"\n" SEPARATOR,
device->accelId);
memset(param_value, 0, ADF_CFG_MAX_VAL_LEN_IN_BYTES);
status = icp_adf_cfgGetParamValue(device,
LAC_CFG_SECTION_GENERAL,
ICP_CFG_HW_REV_ID_KEY,
param_value);
LAC_CHECK_STATUS(status);
len += snprintf(data + len,
size - len,
" Hardware Version: %s %s \n",
param_value,
get_sku_info(device->sku));
memset(param_value, 0, ADF_CFG_MAX_VAL_LEN_IN_BYTES);
status = icp_adf_cfgGetParamValue(device,
LAC_CFG_SECTION_GENERAL,
ICP_CFG_UOF_VER_KEY,
param_value);
LAC_CHECK_STATUS(status);
len += snprintf(data + len,
size - len,
" Firmware Version: %s \n",
param_value);
memset(param_value, 0, ADF_CFG_MAX_VAL_LEN_IN_BYTES);
status = icp_adf_cfgGetParamValue(device,
LAC_CFG_SECTION_GENERAL,
ICP_CFG_MMP_VER_KEY,
param_value);
LAC_CHECK_STATUS(status);
len += snprintf(data + len,
size - len,
" MMP Version: %s \n",
param_value);
len += snprintf(data + len,
size - len,
" Driver Version: %d.%d.%d \n",
SAL_INFO2_DRIVER_SW_VERSION_MAJ_NUMBER,
SAL_INFO2_DRIVER_SW_VERSION_MIN_NUMBER,
SAL_INFO2_DRIVER_SW_VERSION_PATCH_NUMBER);
memset(param_value, 0, ADF_CFG_MAX_VAL_LEN_IN_BYTES);
status = icp_adf_cfgGetParamValue(device,
LAC_CFG_SECTION_GENERAL,
ICP_CFG_LO_COMPATIBLE_DRV_KEY,
param_value);
LAC_CHECK_STATUS(status);
len += snprintf(data + len,
size - len,
" Lowest Compatible Driver: %s \n",
param_value);
len += snprintf(data + len,
size - len,
" QuickAssist API CY Version: %d.%d \n",
CPA_CY_API_VERSION_NUM_MAJOR,
CPA_CY_API_VERSION_NUM_MINOR);
len += snprintf(data + len,
size - len,
" QuickAssist API DC Version: %d.%d \n",
CPA_DC_API_VERSION_NUM_MAJOR,
CPA_DC_API_VERSION_NUM_MINOR);
len += snprintf(data + len, size - len, SEPARATOR);
return 0;
}
static CpaStatus
SalCtrl_ServiceEventShutdown(icp_accel_dev_t *device, Cpa32U enabled_services)
{
CpaStatus status = CPA_STATUS_SUCCESS;
CpaStatus ret_status = CPA_STATUS_SUCCESS;
sal_t *service_container = (sal_t *)device->pSalHandle;
if (NULL == service_container) {
QAT_UTILS_LOG("Private data is NULL\n");
return CPA_STATUS_FATAL;
}
if (SalCtrl_IsServiceEnabled(enabled_services,
SAL_SERVICE_TYPE_CRYPTO)) {
status =
SalCtrl_ServiceShutdown(device,
&service_container->crypto_services,
&service_container->cy_dir,
SAL_SERVICE_TYPE_CRYPTO);
if (CPA_STATUS_SUCCESS != status) {
ret_status = status;
}
}
if (SalCtrl_IsServiceEnabled(enabled_services,
SAL_SERVICE_TYPE_CRYPTO_ASYM)) {
status =
SalCtrl_ServiceShutdown(device,
&service_container->asym_services,
&service_container->asym_dir,
SAL_SERVICE_TYPE_CRYPTO_ASYM);
if (CPA_STATUS_SUCCESS != status) {
ret_status = status;
}
}
if (SalCtrl_IsServiceEnabled(enabled_services,
SAL_SERVICE_TYPE_CRYPTO_SYM)) {
status =
SalCtrl_ServiceShutdown(device,
&service_container->sym_services,
&service_container->sym_dir,
SAL_SERVICE_TYPE_CRYPTO_SYM);
if (CPA_STATUS_SUCCESS != status) {
ret_status = status;
}
}
if (SalCtrl_IsServiceEnabled(enabled_services,
SAL_SERVICE_TYPE_COMPRESSION)) {
status = SalCtrl_ServiceShutdown(
device,
&service_container->compression_services,
&service_container->dc_dir,
SAL_SERVICE_TYPE_COMPRESSION);
if (CPA_STATUS_SUCCESS != status) {
ret_status = status;
}
}
if (service_container->ver_file) {
icp_adf_debugRemoveFile(service_container->ver_file);
LAC_OS_FREE(service_container->ver_file);
service_container->ver_file = NULL;
}
if (!icp_adf_is_dev_in_reset(device)) {
free(service_container, M_QAT);
device->pSalHandle = NULL;
}
return ret_status;
}
static CpaStatus
SalCtrl_ServiceEventInit(icp_accel_dev_t *device, Cpa32U enabled_services)
{
sal_t *service_container = NULL;
CpaStatus status = CPA_STATUS_SUCCESS;
sal_list_t *tail_list = NULL;
Cpa32U instance_count = 0;
status = SalCtrl_GetSupportedServices(device, enabled_services);
if (CPA_STATUS_SUCCESS != status) {
QAT_UTILS_LOG("Failed to get supported services.\n");
return status;
}
if (!icp_adf_is_dev_in_reset(device)) {
service_container = malloc(sizeof(sal_t), M_QAT, M_WAITOK);
device->pSalHandle = service_container;
service_container->asym_services = NULL;
service_container->sym_services = NULL;
service_container->crypto_services = NULL;
service_container->compression_services = NULL;
} else {
service_container = device->pSalHandle;
}
service_container->asym_dir = NULL;
service_container->sym_dir = NULL;
service_container->cy_dir = NULL;
service_container->dc_dir = NULL;
service_container->ver_file = NULL;
service_container->ver_file = LAC_OS_MALLOC(sizeof(debug_file_info_t));
if (NULL == service_container->ver_file) {
free(service_container, M_QAT);
return CPA_STATUS_RESOURCE;
}
memset(service_container->ver_file, 0, sizeof(debug_file_info_t));
service_container->ver_file->name = ver_file_name;
service_container->ver_file->seq_read = SalCtrl_VersionDebug;
service_container->ver_file->private_data = device;
service_container->ver_file->parent = NULL;
status = icp_adf_debugAddFile(device, service_container->ver_file);
if (CPA_STATUS_SUCCESS != status) {
LAC_OS_FREE(service_container->ver_file);
free(service_container, M_QAT);
return status;
}
if (SalCtrl_IsServiceEnabled(enabled_services,
SAL_SERVICE_TYPE_CRYPTO_ASYM)) {
status = SalCtrl_GetInstanceCount(device,
"NumberCyInstances",
&instance_count);
if (CPA_STATUS_SUCCESS != status) {
instance_count = 0;
}
status = SalCtrl_ServiceInit(device,
&service_container->asym_services,
&service_container->asym_dir,
asym_dir_name,
tail_list,
instance_count,
SAL_SERVICE_TYPE_CRYPTO_ASYM);
if (CPA_STATUS_SUCCESS != status) {
goto err_init;
}
}
if (SalCtrl_IsServiceEnabled(enabled_services,
SAL_SERVICE_TYPE_CRYPTO_SYM)) {
status = SalCtrl_GetInstanceCount(device,
"NumberCyInstances",
&instance_count);
if (CPA_STATUS_SUCCESS != status) {
instance_count = 0;
}
status = SalCtrl_ServiceInit(device,
&service_container->sym_services,
&service_container->sym_dir,
sym_dir_name,
tail_list,
instance_count,
SAL_SERVICE_TYPE_CRYPTO_SYM);
if (CPA_STATUS_SUCCESS != status) {
goto err_init;
}
}
if (SalCtrl_IsServiceEnabled(enabled_services,
SAL_SERVICE_TYPE_CRYPTO)) {
status = SalCtrl_GetInstanceCount(device,
"NumberCyInstances",
&instance_count);
if (CPA_STATUS_SUCCESS != status) {
instance_count = 0;
}
status =
SalCtrl_ServiceInit(device,
&service_container->crypto_services,
&service_container->cy_dir,
cy_dir_name,
tail_list,
instance_count,
SAL_SERVICE_TYPE_CRYPTO);
if (CPA_STATUS_SUCCESS != status) {
goto err_init;
}
}
if (SalCtrl_IsServiceEnabled(enabled_services,
SAL_SERVICE_TYPE_COMPRESSION)) {
status = SalCtrl_GetInstanceCount(device,
"NumberDcInstances",
&instance_count);
if (CPA_STATUS_SUCCESS != status) {
instance_count = 0;
}
status = SalCtrl_ServiceInit(
device,
&service_container->compression_services,
&service_container->dc_dir,
dc_dir_name,
tail_list,
instance_count,
SAL_SERVICE_TYPE_COMPRESSION);
if (CPA_STATUS_SUCCESS != status) {
goto err_init;
}
}
return status;
err_init:
SalCtrl_ServiceEventShutdown(device, enabled_services);
return status;
}
static CpaStatus
SalCtrl_ServiceEventStop(icp_accel_dev_t *device, Cpa32U enabled_services)
{
CpaStatus status = CPA_STATUS_SUCCESS;
CpaStatus ret_status = CPA_STATUS_SUCCESS;
sal_t *service_container = device->pSalHandle;
if (service_container == NULL) {
QAT_UTILS_LOG("Private data is NULL.\n");
return CPA_STATUS_FATAL;
}
if (SalCtrl_IsServiceEnabled(enabled_services,
SAL_SERVICE_TYPE_CRYPTO_ASYM)) {
status = SalCtrl_ServiceStop(device,
service_container->asym_services);
if (CPA_STATUS_SUCCESS != status) {
ret_status = status;
}
}
if (SalCtrl_IsServiceEnabled(enabled_services,
SAL_SERVICE_TYPE_CRYPTO_SYM)) {
status = SalCtrl_ServiceStop(device,
service_container->sym_services);
if (CPA_STATUS_SUCCESS != status) {
ret_status = status;
}
}
if (SalCtrl_IsServiceEnabled(enabled_services,
SAL_SERVICE_TYPE_CRYPTO)) {
status =
SalCtrl_ServiceStop(device,
service_container->crypto_services);
if (CPA_STATUS_SUCCESS != status) {
ret_status = status;
}
}
if (SalCtrl_IsServiceEnabled(enabled_services,
SAL_SERVICE_TYPE_COMPRESSION)) {
status = SalCtrl_ServiceStop(
device, service_container->compression_services);
if (CPA_STATUS_SUCCESS != status) {
ret_status = status;
}
}
return ret_status;
}
static CpaStatus
SalCtrl_ServiceEventError(icp_accel_dev_t *device, Cpa32U enabled_services)
{
CpaStatus status = CPA_STATUS_SUCCESS;
CpaStatus ret_status = CPA_STATUS_SUCCESS;
sal_t *service_container = device->pSalHandle;
if (service_container == NULL) {
QAT_UTILS_LOG("Private data is NULL\n");
return CPA_STATUS_FATAL;
}
if (SalCtrl_IsServiceEnabled(enabled_services,
SAL_SERVICE_TYPE_CRYPTO_ASYM)) {
status = SalCtrl_ServiceError(device,
service_container->asym_services);
if (CPA_STATUS_SUCCESS != status) {
ret_status = status;
}
}
if (SalCtrl_IsServiceEnabled(enabled_services,
SAL_SERVICE_TYPE_CRYPTO_SYM)) {
status = SalCtrl_ServiceError(device,
service_container->sym_services);
if (CPA_STATUS_SUCCESS != status) {
ret_status = status;
}
}
if (SalCtrl_IsServiceEnabled(enabled_services,
SAL_SERVICE_TYPE_CRYPTO)) {
status =
SalCtrl_ServiceError(device,
service_container->crypto_services);
if (CPA_STATUS_SUCCESS != status) {
ret_status = status;
}
}
if (SalCtrl_IsServiceEnabled(enabled_services,
SAL_SERVICE_TYPE_COMPRESSION)) {
status = SalCtrl_ServiceError(
device, service_container->compression_services);
if (CPA_STATUS_SUCCESS != status) {
ret_status = status;
}
}
return ret_status;
}
static CpaStatus
SalCtrl_ServiceEventStart(icp_accel_dev_t *device, Cpa32U enabled_services)
{
CpaStatus status = CPA_STATUS_SUCCESS;
sal_t *service_container = device->pSalHandle;
if (service_container == NULL) {
QAT_UTILS_LOG("Private data is NULL.\n");
return CPA_STATUS_FATAL;
}
if (SalCtrl_IsServiceEnabled(enabled_services,
SAL_SERVICE_TYPE_CRYPTO_ASYM)) {
status = SalCtrl_ServiceStart(device,
service_container->asym_services);
if (CPA_STATUS_SUCCESS != status) {
goto err_start;
}
}
if (SalCtrl_IsServiceEnabled(enabled_services,
SAL_SERVICE_TYPE_CRYPTO_SYM)) {
status = SalCtrl_ServiceStart(device,
service_container->sym_services);
if (CPA_STATUS_SUCCESS != status) {
goto err_start;
}
}
if (SalCtrl_IsServiceEnabled(enabled_services,
SAL_SERVICE_TYPE_CRYPTO)) {
status =
SalCtrl_ServiceStart(device,
service_container->crypto_services);
if (CPA_STATUS_SUCCESS != status) {
goto err_start;
}
}
if (SalCtrl_IsServiceEnabled(enabled_services,
SAL_SERVICE_TYPE_COMPRESSION)) {
status = SalCtrl_ServiceStart(
device, service_container->compression_services);
if (CPA_STATUS_SUCCESS != status) {
goto err_start;
}
}
return status;
err_start:
SalCtrl_ServiceEventStop(device, enabled_services);
return status;
}
static CpaStatus
SalCtrl_ServiceEventHandler(icp_accel_dev_t *device,
icp_adf_subsystemEvent_t event,
void *param)
{
CpaStatus status = CPA_STATUS_SUCCESS;
CpaStatus stats_status = CPA_STATUS_SUCCESS;
Cpa32U enabled_services = 0;
status = SalCtrl_GetEnabledServices(device, &enabled_services);
if (CPA_STATUS_SUCCESS != status) {
QAT_UTILS_LOG("Failed to get enabled services.\n");
return status;
}
switch (event) {
case ICP_ADF_EVENT_INIT: {
if (NULL == device->pQatStats) {
status = SalStatistics_InitStatisticsCollection(device);
}
if (CPA_STATUS_SUCCESS != status) {
return status;
}
status = SalCtrl_ServiceEventInit(device, enabled_services);
break;
}
case ICP_ADF_EVENT_START: {
status = SalCtrl_ServiceEventStart(device, enabled_services);
break;
}
case ICP_ADF_EVENT_STOP: {
status = SalCtrl_ServiceEventStop(device, enabled_services);
break;
}
case ICP_ADF_EVENT_SHUTDOWN: {
status = SalCtrl_ServiceEventShutdown(device, enabled_services);
stats_status = SalStatistics_CleanStatisticsCollection(device);
if (CPA_STATUS_SUCCESS != status ||
CPA_STATUS_SUCCESS != stats_status) {
return CPA_STATUS_FAIL;
}
break;
}
case ICP_ADF_EVENT_ERROR: {
status = SalCtrl_ServiceEventError(device, enabled_services);
break;
}
default:
status = CPA_STATUS_SUCCESS;
break;
}
return status;
}
CpaStatus
SalCtrl_AdfServicesRegister(void)
{
sal_service_reg_handle.subserviceEventHandler =
SalCtrl_ServiceEventHandler;
sal_service_reg_handle.subsystem_name = subsystem_name;
return icp_adf_subsystemRegister(&sal_service_reg_handle);
}
CpaStatus
SalCtrl_AdfServicesUnregister(void)
{
return icp_adf_subsystemUnregister(&sal_service_reg_handle);
}
CpaStatus
SalCtrl_AdfServicesStartedCheck(void)
{
CpaStatus status = CPA_STATUS_SUCCESS;
Cpa32U retry_num = 0;
CpaBoolean state = CPA_FALSE;
do {
state = icp_adf_isSubsystemStarted(&sal_service_reg_handle);
retry_num++;
} while ((CPA_FALSE == state) && (retry_num < MAX_SUBSYSTEM_RETRY));
if (CPA_FALSE == state) {
QAT_UTILS_LOG("Sal Ctrl failed to start in given time.\n");
status = CPA_STATUS_FAIL;
}
return status;
}
CpaStatus
validateConcurrRequest(Cpa32U numConcurrRequests)
{
Cpa32U baseReq = SAL_64_CONCURR_REQUESTS;
if (SAL_64_CONCURR_REQUESTS > numConcurrRequests) {
QAT_UTILS_LOG(
"Invalid numConcurrRequests, it is less than min value.\n");
return CPA_STATUS_FAIL;
}
while (SAL_MAX_CONCURR_REQUESTS >= baseReq) {
if (baseReq != numConcurrRequests) {
baseReq = baseReq << 1;
} else {
break;
}
}
if (SAL_MAX_CONCURR_REQUESTS < baseReq) {
QAT_UTILS_LOG(
"Invalid baseReg, it is greater than max value.\n");
return CPA_STATUS_FAIL;
}
return CPA_STATUS_SUCCESS;
}