1 /* SPDX-License-Identifier: BSD-3-Clause */
2 /* Copyright(c) 2007-2022 Intel Corporation */
3 /* $FreeBSD$ */
4 /**
5  *****************************************************************************
6  * @file sal_ctrl_services.c
7  *
8  * @ingroup SalCtrl
9  *
10  * @description
11  *    This file contains the core of the service controller implementation.
12  *
13  *****************************************************************************/
14 
15 /* QAT-API includes */
16 #include "cpa.h"
17 #include "cpa_cy_key.h"
18 #include "cpa_cy_ln.h"
19 #include "cpa_cy_dh.h"
20 #include "cpa_cy_dsa.h"
21 #include "cpa_cy_rsa.h"
22 #include "cpa_cy_ec.h"
23 #include "cpa_cy_prime.h"
24 #include "cpa_cy_sym.h"
25 #include "cpa_dc.h"
26 
27 /* QAT utils includes */
28 #include "qat_utils.h"
29 
30 /* ADF includes */
31 #include "icp_adf_init.h"
32 #include "icp_adf_transport.h"
33 #include "icp_accel_devices.h"
34 #include "icp_adf_cfg.h"
35 #include "icp_adf_init.h"
36 #include "icp_adf_accel_mgr.h"
37 #include "icp_adf_debug.h"
38 
39 /* FW includes */
40 #include "icp_qat_fw_la.h"
41 
42 /* SAL includes */
43 #include "lac_mem.h"
44 #include "lac_mem_pools.h"
45 #include "lac_list.h"
46 #include "lac_hooks.h"
47 #include "sal_string_parse.h"
48 #include "lac_common.h"
49 #include "lac_sal_types.h"
50 #include "lac_sal.h"
51 #include "lac_sal_ctrl.h"
52 #include "icp_sal_versions.h"
53 
54 #define MAX_SUBSYSTEM_RETRY 64
55 
56 static char *subsystem_name = "SAL";
57 /**< Name used by ADF to identify this component. */
58 static char *cy_dir_name = "cy";
59 static char *asym_dir_name = "asym";
60 static char *sym_dir_name = "sym";
61 static char *dc_dir_name = "dc";
62 /**< Stats dir names. */
63 static char *ver_file_name = "version";
64 
65 static subservice_registation_handle_t sal_service_reg_handle;
66 /**< Data structure used by ADF to keep a reference to this component. */
67 
68 /*
69  * @ingroup SalCtrl
70  * @description
71  *      This function is used to parse the results from ADF
72  *      in response to ServiceEnabled query.The results are
73  *      semi-colon separated. Internally, the bitmask represented
74  *      by the enabled_service is used to track which features are enabled.
75  *
76  * @context
77  *      This functions is called from the SalCtrl_ServiceEventInit function.
78  *
79  * @assumptions
80  *      None
81  * @sideEffects
82  *      None
83  * @reentrant
84  *      No
85  * @threadSafe
86  *      Yes
87  *
88  * @param[in] device              pointer to icp_accel_dev_t structure
89  * @param[in] pEnabledServices    pointer to memory where enabled services will
90  *                               be written.
91  * @retval Status
92  */
93 CpaStatus
94 SalCtrl_GetEnabledServices(icp_accel_dev_t *device, Cpa32U *pEnabledServices)
95 {
96 	CpaStatus status = CPA_STATUS_SUCCESS;
97 	char param_value[ADF_CFG_MAX_VAL_LEN_IN_BYTES] = { 0 };
98 	char *token = NULL;
99 	char *running = NULL;
100 
101 	*pEnabledServices = 0;
102 
103 	memset(param_value, 0, ADF_CFG_MAX_VAL_LEN_IN_BYTES);
104 	status = icp_adf_cfgGetParamValue(device,
105 					  LAC_CFG_SECTION_GENERAL,
106 					  "ServicesEnabled",
107 					  param_value);
108 
109 	if (CPA_STATUS_SUCCESS == status) {
110 		running = param_value;
111 
112 		token = strsep(&running, ";");
113 
114 		while (NULL != token) {
115 			do {
116 				if (strncmp(token, "asym", strlen("asym")) ==
117 				    0) {
118 					*pEnabledServices |=
119 					    SAL_SERVICE_TYPE_CRYPTO_ASYM;
120 					break;
121 				}
122 				if (strncmp(token, "sym", strlen("sym")) == 0) {
123 					*pEnabledServices |=
124 					    SAL_SERVICE_TYPE_CRYPTO_SYM;
125 					break;
126 				}
127 				if (strncmp(token, "cy", strlen("cy")) == 0) {
128 					*pEnabledServices |=
129 					    SAL_SERVICE_TYPE_CRYPTO;
130 					break;
131 				}
132 				if (strncmp(token, "dc", strlen("dc")) == 0) {
133 					*pEnabledServices |=
134 					    SAL_SERVICE_TYPE_COMPRESSION;
135 					break;
136 				}
137 
138 				QAT_UTILS_LOG(
139 				    "Error parsing enabled services from ADF.\n");
140 				return CPA_STATUS_FAIL;
141 
142 			} while (0);
143 			token = strsep(&running, ";");
144 		}
145 	} else {
146 		QAT_UTILS_LOG("Failed to get enabled services from ADF.\n");
147 	}
148 	return status;
149 }
150 
151 /*
152  * @ingroup SalCtrl
153  * @description
154  *      This function is used to check whether a service is enabled
155  *
156  * @context
157  *      This functions is called from the SalCtrl_ServiceEventInit function.
158  *
159  * @assumptions
160  *      None
161  * @sideEffects
162  *      None
163  * @reentrant
164  *      No
165  * @threadSafe
166  *      Yes
167  *
168  * param[in] enabled_services    It is the bitmask for the enabled services
169  * param[in] service    It is the service we want to check for
170  */
171 CpaBoolean
172 SalCtrl_IsServiceEnabled(Cpa32U enabled_services, sal_service_type_t service)
173 {
174 	return (CpaBoolean)((enabled_services & (Cpa32U)(service)) != 0);
175 }
176 
177 /*
178  * @ingroup SalCtrl
179  * @description
180  *      This function is used to check whether enabled services has associated
181  *      hardware capability support
182  *
183  * @context
184  *      This functions is called from the SalCtrl_ServiceEventInit function.
185  *
186  * @assumptions
187  *      None
188  * @sideEffects
189  *      None
190  * @reentrant
191  *      No
192  * @threadSafe
193  *      Yes
194  *
195  * param[in] device              A pointer to an icp_accel_dev_t
196  * param[in] enabled_services    It is the bitmask for the enabled services
197  */
198 
199 CpaStatus
200 SalCtrl_GetSupportedServices(icp_accel_dev_t *device, Cpa32U enabled_services)
201 {
202 	CpaStatus status = CPA_STATUS_SUCCESS;
203 	Cpa32U capabilitiesMask = 0;
204 
205 	status = icp_amgr_getAccelDevCapabilities(device, &capabilitiesMask);
206 
207 	if (CPA_STATUS_SUCCESS == status) {
208 		if (SalCtrl_IsServiceEnabled(enabled_services,
209 					     SAL_SERVICE_TYPE_CRYPTO)) {
210 			if (!(capabilitiesMask &
211 			      ICP_ACCEL_CAPABILITIES_CRYPTO_SYMMETRIC) ||
212 			    !(capabilitiesMask &
213 			      ICP_ACCEL_CAPABILITIES_CRYPTO_ASYMMETRIC)) {
214 				QAT_UTILS_LOG(
215 				    "Device does not support Crypto service\n");
216 				status = CPA_STATUS_FAIL;
217 			}
218 		}
219 		if (SalCtrl_IsServiceEnabled(enabled_services,
220 					     SAL_SERVICE_TYPE_CRYPTO_ASYM)) {
221 			if (!(capabilitiesMask &
222 			      ICP_ACCEL_CAPABILITIES_CRYPTO_ASYMMETRIC)) {
223 				QAT_UTILS_LOG(
224 				    "Device does not support Asym service\n");
225 				status = CPA_STATUS_FAIL;
226 			}
227 		}
228 		if (SalCtrl_IsServiceEnabled(enabled_services,
229 					     SAL_SERVICE_TYPE_CRYPTO_SYM)) {
230 			if (!(capabilitiesMask &
231 			      ICP_ACCEL_CAPABILITIES_CRYPTO_SYMMETRIC)) {
232 				QAT_UTILS_LOG(
233 				    "Device does not support Sym service\n");
234 				status = CPA_STATUS_FAIL;
235 			}
236 		}
237 		if (SalCtrl_IsServiceEnabled(enabled_services,
238 					     SAL_SERVICE_TYPE_COMPRESSION)) {
239 			if (!(capabilitiesMask &
240 			      ICP_ACCEL_CAPABILITIES_COMPRESSION)) {
241 				QAT_UTILS_LOG(
242 				    "Device does not support Compression service.\n");
243 				status = CPA_STATUS_FAIL;
244 			}
245 		}
246 	}
247 
248 	return status;
249 }
250 
251 /*************************************************************************
252  * @ingroup SalCtrl
253  * @description
254  *      This function is used to check if a service is supported
255  *      on the device. The key difference between this and
256  *      SalCtrl_GetSupportedServices() is that the latter treats it as
257  *      an error if the service is unsupported.
258  *
259  * @context
260  *      This can be called anywhere.
261  *
262  * @assumptions
263  *      None
264  * @sideEffects
265  *      None
266  * @reentrant
267  *      No
268  * @threadSafe
269  *      Yes
270  *
271  * param[in] device
272  * param[in] service    service or services to check
273  *
274  *************************************************************************/
275 CpaBoolean
276 SalCtrl_IsServiceSupported(icp_accel_dev_t *device,
277 			   sal_service_type_t service_to_check)
278 {
279 	CpaStatus status = CPA_STATUS_SUCCESS;
280 	Cpa32U capabilitiesMask = 0;
281 	CpaBoolean service_supported = CPA_TRUE;
282 
283 	if (!(SalCtrl_IsServiceEnabled((Cpa32U)service_to_check,
284 				       SAL_SERVICE_TYPE_CRYPTO)) &&
285 	    !(SalCtrl_IsServiceEnabled((Cpa32U)service_to_check,
286 				       SAL_SERVICE_TYPE_CRYPTO_ASYM)) &&
287 	    !(SalCtrl_IsServiceEnabled((Cpa32U)service_to_check,
288 				       SAL_SERVICE_TYPE_CRYPTO_SYM)) &&
289 	    !(SalCtrl_IsServiceEnabled((Cpa32U)service_to_check,
290 				       SAL_SERVICE_TYPE_COMPRESSION))) {
291 		QAT_UTILS_LOG("Invalid service type\n");
292 		service_supported = CPA_FALSE;
293 	}
294 
295 	status = icp_amgr_getAccelDevCapabilities(device, &capabilitiesMask);
296 
297 	if (CPA_STATUS_SUCCESS != status) {
298 		QAT_UTILS_LOG("Can not get device capabilities.\n");
299 		return CPA_FALSE;
300 	}
301 
302 	if (SalCtrl_IsServiceEnabled((Cpa32U)service_to_check,
303 				     SAL_SERVICE_TYPE_CRYPTO)) {
304 		if (!(capabilitiesMask &
305 		      ICP_ACCEL_CAPABILITIES_CRYPTO_SYMMETRIC) ||
306 		    !(capabilitiesMask &
307 		      ICP_ACCEL_CAPABILITIES_CRYPTO_ASYMMETRIC)) {
308 			QAT_UTILS_LOG(
309 			    "Device does not support Crypto service\n");
310 			service_supported = CPA_FALSE;
311 		}
312 	}
313 	if (SalCtrl_IsServiceEnabled((Cpa32U)service_to_check,
314 				     SAL_SERVICE_TYPE_CRYPTO_ASYM)) {
315 		if (!(capabilitiesMask &
316 		      ICP_ACCEL_CAPABILITIES_CRYPTO_ASYMMETRIC)) {
317 			QAT_UTILS_LOG("Device does not support Asym service\n");
318 			service_supported = CPA_FALSE;
319 		}
320 	}
321 	if (SalCtrl_IsServiceEnabled((Cpa32U)service_to_check,
322 				     SAL_SERVICE_TYPE_CRYPTO_SYM)) {
323 		if (!(capabilitiesMask &
324 		      ICP_ACCEL_CAPABILITIES_CRYPTO_SYMMETRIC)) {
325 			QAT_UTILS_LOG("Device does not support Sym service\n");
326 			service_supported = CPA_FALSE;
327 		}
328 	}
329 	if (SalCtrl_IsServiceEnabled((Cpa32U)service_to_check,
330 				     SAL_SERVICE_TYPE_COMPRESSION)) {
331 		if (!(capabilitiesMask & ICP_ACCEL_CAPABILITIES_COMPRESSION)) {
332 			QAT_UTILS_LOG(
333 			    "Device does not support Compression service.\n");
334 			service_supported = CPA_FALSE;
335 		}
336 	}
337 
338 	return service_supported;
339 }
340 
341 /*
342  * @ingroup SalCtrl
343  * @description
344  *      This function is used to retrieve how many instances are
345  *      to be configured for process specific service.
346  *
347  * @context
348  *      This functions is called from the SalCtrl_ServiceEventInit function.
349  *
350  * @assumptions
351  *      None
352  * @sideEffects
353  *      None
354  * @reentrant
355  *      No
356  * @threadSafe
357  *      Yes
358  *
359  * @param[in] device    A pointer to an icp_accel_dev_t
360  * @param[in] key       Represents the parameter's name we want to query
361  * @param[out] pCount   Pointer to memory where num instances will be stored
362  * @retval status       returned status from ADF or _FAIL if number of instances
363  *                      is out of range for the device.
364  */
365 static CpaStatus
366 SalCtrl_GetInstanceCount(icp_accel_dev_t *device, char *key, Cpa32U *pCount)
367 {
368 	CpaStatus status = CPA_STATUS_FAIL;
369 	char param_value[ADF_CFG_MAX_VAL_LEN_IN_BYTES];
370 
371 	memset(param_value, 0, ADF_CFG_MAX_VAL_LEN_IN_BYTES);
372 	status = icp_adf_cfgGetParamValue(device,
373 					  icpGetProcessName(),
374 					  key,
375 					  param_value);
376 	if (CPA_STATUS_SUCCESS == status) {
377 		*pCount =
378 		    (Cpa32U)(Sal_Strtoul(param_value, NULL, SAL_CFG_BASE_DEC));
379 		if (*pCount > SAL_MAX_NUM_INSTANCES_PER_DEV) {
380 			QAT_UTILS_LOG("Number of instances is out of range.\n");
381 			status = CPA_STATUS_FAIL;
382 		}
383 	}
384 	return status;
385 }
386 
387 /**************************************************************************
388  * @ingroup SalCtrl
389  * @description
390  *      This function calls the shutdown function on all the
391  *      service instances.
392  *      It also frees all service instance memory allocated at Init.
393  *
394  * @context
395  *      This function is called from the SalCtrl_ServiceEventShutdown
396  *      function.
397  *
398  * @assumptions
399  *      params[in] should not be NULL
400  * @sideEffects
401  *      None
402  * @reentrant
403  *      No
404  * @threadSafe
405  *      Yes
406  *
407  * @param[in] device           An icp_accel_dev_t* type
408  * @param[in] services         A pointer to the container of services
409  * @param[in] dbg_dir          A pointer to the debug directory
410  * @param[in] svc_type         The type of the service instance
411  *
412  ****************************************************************************/
413 static CpaStatus
414 SalCtrl_ServiceShutdown(icp_accel_dev_t *device,
415 			sal_list_t **services,
416 			debug_dir_info_t **debug_dir,
417 			sal_service_type_t svc_type)
418 {
419 	CpaStatus status = CPA_STATUS_SUCCESS;
420 	sal_list_t *dyn_service = NULL;
421 	sal_service_t *inst = NULL;
422 
423 	/* Call Shutdown function for each service instance */
424 	SAL_FOR_EACH(*services, sal_service_t, device, shutdown, status);
425 
426 	if (*debug_dir) {
427 		icp_adf_debugRemoveDir(*debug_dir);
428 		LAC_OS_FREE(*debug_dir);
429 		*debug_dir = NULL;
430 	}
431 
432 	if (!icp_adf_is_dev_in_reset(device)) {
433 		dyn_service = *services;
434 		while (dyn_service) {
435 			inst = (sal_service_t *)SalList_getObject(dyn_service);
436 			if (CPA_TRUE == inst->is_dyn) {
437 				icp_adf_putDynInstance(device,
438 						       (adf_service_type_t)
439 							   svc_type,
440 						       inst->instance);
441 			}
442 			dyn_service = SalList_next(dyn_service);
443 		}
444 		/* Free Sal services controller memory */
445 		SalList_free(services);
446 	} else {
447 		sal_list_t *curr_element = NULL;
448 		sal_service_t *service = NULL;
449 		curr_element = *services;
450 		while (NULL != curr_element) {
451 			service =
452 			    (sal_service_t *)SalList_getObject(curr_element);
453 			service->state = SAL_SERVICE_STATE_RESTARTING;
454 			curr_element = SalList_next(curr_element);
455 		}
456 	}
457 
458 	return status;
459 }
460 
461 static CpaStatus
462 selectGeneration(device_type_t deviceType, sal_service_t *pInst)
463 {
464 	switch (deviceType) {
465 	case DEVICE_C62X:
466 	case DEVICE_C62XVF:
467 	case DEVICE_DH895XCC:
468 	case DEVICE_DH895XCCVF:
469 	case DEVICE_C3XXX:
470 	case DEVICE_C3XXXVF:
471 	case DEVICE_200XX:
472 	case DEVICE_200XXVF:
473 		pInst->gen = GEN2;
474 		break;
475 
476 	case DEVICE_C4XXX:
477 	case DEVICE_C4XXXVF:
478 		pInst->gen = GEN3;
479 		break;
480 
481 	case DEVICE_GEN4:
482 		pInst->gen = GEN4;
483 		break;
484 
485 	default:
486 		QAT_UTILS_LOG("deviceType not initialised\n");
487 		return CPA_STATUS_FAIL;
488 	}
489 	return CPA_STATUS_SUCCESS;
490 }
491 
492 /*************************************************************************
493  * @ingroup SalCtrl
494  * @description
495  *      This function is used to initialise the service instances.
496  *      It allocates memory for service instances and invokes the
497  *      Init function on them.
498  *
499  * @context
500  *      This function is called from the SalCtrl_ServiceEventInit function.
501  *
502  * @assumptions
503  *      None
504  * @sideEffects
505  *      None
506  * @reentrant
507  *      No
508  * @threadSafe
509  *      Yes
510  *
511  * @param[in] device           An icp_accel_dev_t* type
512  * @param[in] services         A pointer to the container of services
513  * @param[in] dbg_dir          A pointer to the debug directory
514  * @param[in] dbg_dir_name     Name of the debug directory
515  * @param[in] tail_list        SAL's list of services
516  * @param[in] instance_count   Number of instances
517  * @param[in] svc_type         The type of the service instance
518  *
519  *************************************************************************/
520 static CpaStatus
521 SalCtrl_ServiceInit(icp_accel_dev_t *device,
522 		    sal_list_t **services,
523 		    debug_dir_info_t **dbg_dir,
524 		    char *dbg_dir_name,
525 		    sal_list_t *tail_list,
526 		    Cpa32U instance_count,
527 		    sal_service_type_t svc_type)
528 {
529 	CpaStatus status = CPA_STATUS_SUCCESS;
530 	sal_service_t *pInst = NULL;
531 	Cpa32U i = 0;
532 	debug_dir_info_t *debug_dir = NULL;
533 
534 	debug_dir = LAC_OS_MALLOC(sizeof(debug_dir_info_t));
535 	if (NULL == debug_dir) {
536 		QAT_UTILS_LOG("Failed to allocate memory for debug dir.\n");
537 		return CPA_STATUS_RESOURCE;
538 	}
539 	debug_dir->name = dbg_dir_name;
540 	debug_dir->parent = NULL;
541 	status = icp_adf_debugAddDir(device, debug_dir);
542 	if (CPA_STATUS_SUCCESS != status) {
543 		QAT_UTILS_LOG("Failed to add debug dir.\n");
544 		LAC_OS_FREE(debug_dir);
545 		debug_dir = NULL;
546 		return status;
547 	}
548 
549 	if (!icp_adf_is_dev_in_reset(device)) {
550 		for (i = 0; i < instance_count; i++) {
551 			status = SalCtrl_ServiceCreate(svc_type, i, &pInst);
552 			if (CPA_STATUS_SUCCESS != status) {
553 				break;
554 			}
555 			pInst->debug_parent_dir = debug_dir;
556 			pInst->capabilitiesMask = device->accelCapabilitiesMask;
557 
558 			status = selectGeneration(device->deviceType, pInst);
559 			if (CPA_STATUS_SUCCESS == status) {
560 				status =
561 				    SalList_add(services, &tail_list, pInst);
562 			}
563 			if (CPA_STATUS_SUCCESS != status) {
564 				free(pInst, M_QAT);
565 			}
566 		}
567 	} else {
568 		sal_list_t *curr_element = *services;
569 		sal_service_t *service = NULL;
570 		while (NULL != curr_element) {
571 			service =
572 			    (sal_service_t *)SalList_getObject(curr_element);
573 			service->debug_parent_dir = debug_dir;
574 
575 			if (CPA_TRUE == service->isInstanceStarted) {
576 				icp_qa_dev_get(device);
577 			}
578 
579 			curr_element = SalList_next(curr_element);
580 		}
581 	}
582 
583 	if (CPA_STATUS_SUCCESS != status) {
584 		QAT_UTILS_LOG("Failed to allocate all instances.\n");
585 		icp_adf_debugRemoveDir(debug_dir);
586 		LAC_OS_FREE(debug_dir);
587 		debug_dir = NULL;
588 		SalList_free(services);
589 		return status;
590 	}
591 
592 	/* Call init function for each service instance */
593 	SAL_FOR_EACH(*services, sal_service_t, device, init, status);
594 	if (CPA_STATUS_SUCCESS != status) {
595 		QAT_UTILS_LOG("Failed to initialise all service instances.\n");
596 		/* shutdown all instances initialised before error */
597 		SAL_FOR_EACH_STATE(*services,
598 				   sal_service_t,
599 				   device,
600 				   shutdown,
601 				   SAL_SERVICE_STATE_INITIALIZED);
602 		icp_adf_debugRemoveDir(debug_dir);
603 		LAC_OS_FREE(debug_dir);
604 		debug_dir = NULL;
605 		SalList_free(services);
606 		return status;
607 	}
608 	/* initialize the debug directory for relevant service */
609 	*dbg_dir = debug_dir;
610 
611 	return status;
612 }
613 
614 /**************************************************************************
615  * @ingroup SalCtrl
616  * @description
617  *      This function calls the start function on all the service instances.
618  *
619  * @context
620  *      This function is called from the SalCtrl_ServiceEventStart function.
621  *
622  * @assumptions
623  *      None
624  * @sideEffects
625  *      None
626  * @reentrant
627  *      No
628  * @threadSafe
629  *      Yes
630  *
631  * @param[in] device     An icp_accel_dev_t* type
632  * @param[in] services   A pointer to the container of services
633  *
634  **************************************************************************/
635 static CpaStatus
636 SalCtrl_ServiceStart(icp_accel_dev_t *device, sal_list_t *services)
637 {
638 	CpaStatus status = CPA_STATUS_SUCCESS;
639 
640 	/* Call Start function for each service instance */
641 	SAL_FOR_EACH(services, sal_service_t, device, start, status);
642 	if (CPA_STATUS_SUCCESS != status) {
643 		QAT_UTILS_LOG("Failed to start all instances.\n");
644 		/* stop all instances started before error */
645 		SAL_FOR_EACH_STATE(services,
646 				   sal_service_t,
647 				   device,
648 				   stop,
649 				   SAL_SERVICE_STATE_RUNNING);
650 		return status;
651 	}
652 
653 	if (icp_adf_is_dev_in_reset(device)) {
654 		sal_list_t *curr_element = services;
655 		sal_service_t *service = NULL;
656 		while (NULL != curr_element) {
657 			service =
658 			    (sal_service_t *)SalList_getObject(curr_element);
659 			if (service->notification_cb) {
660 				service->notification_cb(
661 				    service,
662 				    service->cb_tag,
663 				    CPA_INSTANCE_EVENT_RESTARTED);
664 			}
665 			curr_element = SalList_next(curr_element);
666 		}
667 	}
668 
669 	return status;
670 }
671 
672 /****************************************************************************
673  * @ingroup SalCtrl
674  * @description
675  *      This function calls the stop function on all the
676  *      service instances.
677  *
678  * @context
679  *      This function is called from the SalCtrl_ServiceEventStop function.
680  *
681  * @assumptions
682  *      None
683  * @sideEffects
684  *      None
685  * @reentrant
686  *      No
687  * @threadSafe
688  *      Yes
689  *
690  * @param[in] device    An icp_accel_dev_t* type
691  * @param[in] services   A pointer to the container of services
692  *
693  *************************************************************************/
694 static CpaStatus
695 SalCtrl_ServiceStop(icp_accel_dev_t *device, sal_list_t *services)
696 {
697 	CpaStatus status = CPA_STATUS_SUCCESS;
698 
699 	/* Calling restarting functions */
700 	if (icp_adf_is_dev_in_reset(device)) {
701 		sal_list_t *curr_element = services;
702 		sal_service_t *service = NULL;
703 		while (NULL != curr_element) {
704 			service =
705 			    (sal_service_t *)SalList_getObject(curr_element);
706 			if (service->notification_cb) {
707 				service->notification_cb(
708 				    service,
709 				    service->cb_tag,
710 				    CPA_INSTANCE_EVENT_RESTARTING);
711 			}
712 			curr_element = SalList_next(curr_element);
713 		}
714 	}
715 
716 	/* Call Stop function for each service instance */
717 	SAL_FOR_EACH(services, sal_service_t, device, stop, status);
718 
719 	return status;
720 }
721 
722 /*
723  * @ingroup SalCtrl
724  * @description
725  *      This function is used to print hardware and software versions in proc
726  *      filesystem entry via ADF Debug interface
727  *
728  * @context
729  *    This functions is called from proc filesystem interface
730  *
731  * @assumptions
732  *      None
733  * @sideEffects
734  *      None
735  * @reentrant
736  *      No
737  * @threadSafe
738  *      Yes
739  *
740  * @param[in]  private_data    A pointer to a private data passed to the
741  *                             function while adding a debug file.
742  * @param[out] data            Pointer to a buffer where version information
743  *                             needs to be printed to.
744  * @param[in]  size            Size of a buffer pointed by data.
745  * @param[in]  offset          Offset in a debug file
746  *
747  * @retval 0    This function always returns 0
748  */
749 static int
750 SalCtrl_VersionDebug(void *private_data, char *data, int size, int offset)
751 {
752 	CpaStatus status = CPA_STATUS_SUCCESS;
753 	Cpa32U len = 0;
754 	icp_accel_dev_t *device = (icp_accel_dev_t *)private_data;
755 	char param_value[ADF_CFG_MAX_VAL_LEN_IN_BYTES] = { 0 };
756 
757 	len += snprintf(
758 	    data + len,
759 	    size - len,
760 	    SEPARATOR BORDER
761 	    " Hardware and Software versions for device %d      " BORDER
762 	    "\n" SEPARATOR,
763 	    device->accelId);
764 
765 	memset(param_value, 0, ADF_CFG_MAX_VAL_LEN_IN_BYTES);
766 	status = icp_adf_cfgGetParamValue(device,
767 					  LAC_CFG_SECTION_GENERAL,
768 					  ICP_CFG_HW_REV_ID_KEY,
769 					  param_value);
770 	LAC_CHECK_STATUS(status);
771 
772 	len += snprintf(data + len,
773 			size - len,
774 			" Hardware Version:             %s %s \n",
775 			param_value,
776 			get_sku_info(device->sku));
777 
778 	memset(param_value, 0, ADF_CFG_MAX_VAL_LEN_IN_BYTES);
779 	status = icp_adf_cfgGetParamValue(device,
780 					  LAC_CFG_SECTION_GENERAL,
781 					  ICP_CFG_UOF_VER_KEY,
782 					  param_value);
783 	LAC_CHECK_STATUS(status);
784 
785 	len += snprintf(data + len,
786 			size - len,
787 			" Firmware Version:             %s \n",
788 			param_value);
789 	memset(param_value, 0, ADF_CFG_MAX_VAL_LEN_IN_BYTES);
790 	status = icp_adf_cfgGetParamValue(device,
791 					  LAC_CFG_SECTION_GENERAL,
792 					  ICP_CFG_MMP_VER_KEY,
793 					  param_value);
794 	LAC_CHECK_STATUS(status);
795 
796 	len += snprintf(data + len,
797 			size - len,
798 			" MMP Version:                  %s \n",
799 			param_value);
800 	len += snprintf(data + len,
801 			size - len,
802 			" Driver Version:               %d.%d.%d \n",
803 			SAL_INFO2_DRIVER_SW_VERSION_MAJ_NUMBER,
804 			SAL_INFO2_DRIVER_SW_VERSION_MIN_NUMBER,
805 			SAL_INFO2_DRIVER_SW_VERSION_PATCH_NUMBER);
806 
807 	memset(param_value, 0, ADF_CFG_MAX_VAL_LEN_IN_BYTES);
808 	status = icp_adf_cfgGetParamValue(device,
809 					  LAC_CFG_SECTION_GENERAL,
810 					  ICP_CFG_LO_COMPATIBLE_DRV_KEY,
811 					  param_value);
812 	LAC_CHECK_STATUS(status);
813 
814 	len += snprintf(data + len,
815 			size - len,
816 			" Lowest Compatible Driver:     %s \n",
817 			param_value);
818 
819 	len += snprintf(data + len,
820 			size - len,
821 			" QuickAssist API CY Version:   %d.%d \n",
822 			CPA_CY_API_VERSION_NUM_MAJOR,
823 			CPA_CY_API_VERSION_NUM_MINOR);
824 	len += snprintf(data + len,
825 			size - len,
826 			" QuickAssist API DC Version:   %d.%d \n",
827 			CPA_DC_API_VERSION_NUM_MAJOR,
828 			CPA_DC_API_VERSION_NUM_MINOR);
829 
830 	len += snprintf(data + len, size - len, SEPARATOR);
831 	return 0;
832 }
833 
834 /**************************************************************************
835  * @ingroup SalCtrl
836  * @description
837  *       This function calls the shutdown function on all the service
838  *       instances. It also frees all service instance memory
839  *       allocated at Init.
840  *
841  * @context
842  *      This function is called from the SalCtrl_ServiceEventHandler function.
843  *
844  * @assumptions
845  *      None
846  * @sideEffects
847  *      None
848  * @reentrant
849  *      No
850  * @threadSafe
851  *      Yes
852  *
853  * @param[in] device             An icp_accel_dev_t* type
854  * @param[in] enabled_services   Services enabled by user
855  *
856  ****************************************************************************/
857 static CpaStatus
858 SalCtrl_ServiceEventShutdown(icp_accel_dev_t *device, Cpa32U enabled_services)
859 {
860 	CpaStatus status = CPA_STATUS_SUCCESS;
861 	CpaStatus ret_status = CPA_STATUS_SUCCESS;
862 	sal_t *service_container = (sal_t *)device->pSalHandle;
863 
864 	if (NULL == service_container) {
865 		QAT_UTILS_LOG("Private data is NULL\n");
866 		return CPA_STATUS_FATAL;
867 	}
868 
869 	if (SalCtrl_IsServiceEnabled(enabled_services,
870 				     SAL_SERVICE_TYPE_CRYPTO)) {
871 		status =
872 		    SalCtrl_ServiceShutdown(device,
873 					    &service_container->crypto_services,
874 					    &service_container->cy_dir,
875 					    SAL_SERVICE_TYPE_CRYPTO);
876 		if (CPA_STATUS_SUCCESS != status) {
877 			ret_status = status;
878 		}
879 	}
880 
881 	if (SalCtrl_IsServiceEnabled(enabled_services,
882 				     SAL_SERVICE_TYPE_CRYPTO_ASYM)) {
883 		status =
884 		    SalCtrl_ServiceShutdown(device,
885 					    &service_container->asym_services,
886 					    &service_container->asym_dir,
887 					    SAL_SERVICE_TYPE_CRYPTO_ASYM);
888 		if (CPA_STATUS_SUCCESS != status) {
889 			ret_status = status;
890 		}
891 	}
892 
893 	if (SalCtrl_IsServiceEnabled(enabled_services,
894 				     SAL_SERVICE_TYPE_CRYPTO_SYM)) {
895 		status =
896 		    SalCtrl_ServiceShutdown(device,
897 					    &service_container->sym_services,
898 					    &service_container->sym_dir,
899 					    SAL_SERVICE_TYPE_CRYPTO_SYM);
900 		if (CPA_STATUS_SUCCESS != status) {
901 			ret_status = status;
902 		}
903 	}
904 
905 	if (SalCtrl_IsServiceEnabled(enabled_services,
906 				     SAL_SERVICE_TYPE_COMPRESSION)) {
907 		status = SalCtrl_ServiceShutdown(
908 		    device,
909 		    &service_container->compression_services,
910 		    &service_container->dc_dir,
911 		    SAL_SERVICE_TYPE_COMPRESSION);
912 		if (CPA_STATUS_SUCCESS != status) {
913 			ret_status = status;
914 		}
915 	}
916 
917 	if (service_container->ver_file) {
918 		icp_adf_debugRemoveFile(service_container->ver_file);
919 		LAC_OS_FREE(service_container->ver_file);
920 		service_container->ver_file = NULL;
921 	}
922 
923 	if (!icp_adf_is_dev_in_reset(device)) {
924 		/* Free container also */
925 		free(service_container, M_QAT);
926 		device->pSalHandle = NULL;
927 	}
928 
929 	return ret_status;
930 }
931 
932 /*************************************************************************
933  * @ingroup SalCtrl
934  * @description
935  *      This function is used to initialize the service instances.
936  *      It first checks (via ADF query) which services are enabled in the
937  *      system and the number of each services.
938  *      It then invokes the init function on them which creates the
939  *      instances and allocates memory for them.
940  *
941  * @context
942  *      This function is called from the SalCtrl_ServiceEventHandler function.
943  *
944  * @assumptions
945  *      None
946  * @sideEffects
947  *      None
948  * @reentrant
949  *      No
950  * @threadSafe
951  *      Yes
952  *
953  * @param[in] device             An icp_accel_dev_t* type
954  * @param[in] enabled_services   Services enabled by user
955  *
956  *************************************************************************/
957 static CpaStatus
958 SalCtrl_ServiceEventInit(icp_accel_dev_t *device, Cpa32U enabled_services)
959 {
960 	sal_t *service_container = NULL;
961 	CpaStatus status = CPA_STATUS_SUCCESS;
962 	sal_list_t *tail_list = NULL;
963 	Cpa32U instance_count = 0;
964 
965 	status = SalCtrl_GetSupportedServices(device, enabled_services);
966 	if (CPA_STATUS_SUCCESS != status) {
967 		QAT_UTILS_LOG("Failed to get supported services.\n");
968 		return status;
969 	}
970 
971 	if (!icp_adf_is_dev_in_reset(device)) {
972 		service_container = malloc(sizeof(sal_t), M_QAT, M_WAITOK);
973 		device->pSalHandle = service_container;
974 		service_container->asym_services = NULL;
975 		service_container->sym_services = NULL;
976 		service_container->crypto_services = NULL;
977 		service_container->compression_services = NULL;
978 	} else {
979 		service_container = device->pSalHandle;
980 	}
981 	service_container->asym_dir = NULL;
982 	service_container->sym_dir = NULL;
983 	service_container->cy_dir = NULL;
984 	service_container->dc_dir = NULL;
985 	service_container->ver_file = NULL;
986 
987 	service_container->ver_file = LAC_OS_MALLOC(sizeof(debug_file_info_t));
988 	if (NULL == service_container->ver_file) {
989 		free(service_container, M_QAT);
990 		return CPA_STATUS_RESOURCE;
991 	}
992 
993 	memset(service_container->ver_file, 0, sizeof(debug_file_info_t));
994 	service_container->ver_file->name = ver_file_name;
995 	service_container->ver_file->seq_read = SalCtrl_VersionDebug;
996 	service_container->ver_file->private_data = device;
997 	service_container->ver_file->parent = NULL;
998 
999 	status = icp_adf_debugAddFile(device, service_container->ver_file);
1000 	if (CPA_STATUS_SUCCESS != status) {
1001 		LAC_OS_FREE(service_container->ver_file);
1002 		free(service_container, M_QAT);
1003 		return status;
1004 	}
1005 
1006 	if (SalCtrl_IsServiceEnabled(enabled_services,
1007 				     SAL_SERVICE_TYPE_CRYPTO_ASYM)) {
1008 		status = SalCtrl_GetInstanceCount(device,
1009 						  "NumberCyInstances",
1010 						  &instance_count);
1011 		if (CPA_STATUS_SUCCESS != status) {
1012 			instance_count = 0;
1013 		}
1014 		status = SalCtrl_ServiceInit(device,
1015 					     &service_container->asym_services,
1016 					     &service_container->asym_dir,
1017 					     asym_dir_name,
1018 					     tail_list,
1019 					     instance_count,
1020 					     SAL_SERVICE_TYPE_CRYPTO_ASYM);
1021 		if (CPA_STATUS_SUCCESS != status) {
1022 			goto err_init;
1023 		}
1024 	}
1025 
1026 	if (SalCtrl_IsServiceEnabled(enabled_services,
1027 				     SAL_SERVICE_TYPE_CRYPTO_SYM)) {
1028 		status = SalCtrl_GetInstanceCount(device,
1029 						  "NumberCyInstances",
1030 						  &instance_count);
1031 		if (CPA_STATUS_SUCCESS != status) {
1032 			instance_count = 0;
1033 		}
1034 		status = SalCtrl_ServiceInit(device,
1035 					     &service_container->sym_services,
1036 					     &service_container->sym_dir,
1037 					     sym_dir_name,
1038 					     tail_list,
1039 					     instance_count,
1040 					     SAL_SERVICE_TYPE_CRYPTO_SYM);
1041 		if (CPA_STATUS_SUCCESS != status) {
1042 			goto err_init;
1043 		}
1044 	}
1045 
1046 	if (SalCtrl_IsServiceEnabled(enabled_services,
1047 				     SAL_SERVICE_TYPE_CRYPTO)) {
1048 		status = SalCtrl_GetInstanceCount(device,
1049 						  "NumberCyInstances",
1050 						  &instance_count);
1051 		if (CPA_STATUS_SUCCESS != status) {
1052 			instance_count = 0;
1053 		}
1054 		status =
1055 		    SalCtrl_ServiceInit(device,
1056 					&service_container->crypto_services,
1057 					&service_container->cy_dir,
1058 					cy_dir_name,
1059 					tail_list,
1060 					instance_count,
1061 					SAL_SERVICE_TYPE_CRYPTO);
1062 		if (CPA_STATUS_SUCCESS != status) {
1063 			goto err_init;
1064 		}
1065 	}
1066 	if (SalCtrl_IsServiceEnabled(enabled_services,
1067 				     SAL_SERVICE_TYPE_COMPRESSION)) {
1068 		status = SalCtrl_GetInstanceCount(device,
1069 						  "NumberDcInstances",
1070 						  &instance_count);
1071 		if (CPA_STATUS_SUCCESS != status) {
1072 			instance_count = 0;
1073 		}
1074 		status = SalCtrl_ServiceInit(
1075 		    device,
1076 		    &service_container->compression_services,
1077 		    &service_container->dc_dir,
1078 		    dc_dir_name,
1079 		    tail_list,
1080 		    instance_count,
1081 		    SAL_SERVICE_TYPE_COMPRESSION);
1082 		if (CPA_STATUS_SUCCESS != status) {
1083 			goto err_init;
1084 		}
1085 	}
1086 
1087 	return status;
1088 
1089 err_init:
1090 	SalCtrl_ServiceEventShutdown(device, enabled_services);
1091 	return status;
1092 }
1093 
1094 /****************************************************************************
1095  * @ingroup SalCtrl
1096  * @description
1097  *      This function calls the stop function on all the service instances.
1098  *
1099  * @context
1100  *      This function is called from the SalCtrl_ServiceEventHandler function.
1101  *
1102  * @assumptions
1103  *      None
1104  * @sideEffects
1105  *      None
1106  * @reentrant
1107  *      No
1108  * @threadSafe
1109  *      Yes
1110  *
1111  * @param[in] device              An icp_accel_dev_t* type
1112  * @param[in] enabled_services    Enabled services by user
1113  *
1114  *************************************************************************/
1115 static CpaStatus
1116 SalCtrl_ServiceEventStop(icp_accel_dev_t *device, Cpa32U enabled_services)
1117 {
1118 	CpaStatus status = CPA_STATUS_SUCCESS;
1119 	CpaStatus ret_status = CPA_STATUS_SUCCESS;
1120 	sal_t *service_container = device->pSalHandle;
1121 
1122 	if (service_container == NULL) {
1123 		QAT_UTILS_LOG("Private data is NULL.\n");
1124 		return CPA_STATUS_FATAL;
1125 	}
1126 
1127 	if (SalCtrl_IsServiceEnabled(enabled_services,
1128 				     SAL_SERVICE_TYPE_CRYPTO_ASYM)) {
1129 		status = SalCtrl_ServiceStop(device,
1130 					     service_container->asym_services);
1131 		if (CPA_STATUS_SUCCESS != status) {
1132 			ret_status = status;
1133 		}
1134 	}
1135 
1136 	if (SalCtrl_IsServiceEnabled(enabled_services,
1137 				     SAL_SERVICE_TYPE_CRYPTO_SYM)) {
1138 		status = SalCtrl_ServiceStop(device,
1139 					     service_container->sym_services);
1140 		if (CPA_STATUS_SUCCESS != status) {
1141 			ret_status = status;
1142 		}
1143 	}
1144 
1145 	if (SalCtrl_IsServiceEnabled(enabled_services,
1146 				     SAL_SERVICE_TYPE_CRYPTO)) {
1147 		status =
1148 		    SalCtrl_ServiceStop(device,
1149 					service_container->crypto_services);
1150 		if (CPA_STATUS_SUCCESS != status) {
1151 			ret_status = status;
1152 		}
1153 	}
1154 
1155 	if (SalCtrl_IsServiceEnabled(enabled_services,
1156 				     SAL_SERVICE_TYPE_COMPRESSION)) {
1157 		status = SalCtrl_ServiceStop(
1158 		    device, service_container->compression_services);
1159 		if (CPA_STATUS_SUCCESS != status) {
1160 			ret_status = status;
1161 		}
1162 	}
1163 
1164 	return ret_status;
1165 }
1166 
1167 /**************************************************************************
1168  * @ingroup SalCtrl
1169  * @description
1170  *      This function calls the start function on all the service instances.
1171  *
1172  * @context
1173  *      This function is called from the SalCtrl_ServiceEventHandler function.
1174  *
1175  * @assumptions
1176  *      None
1177  * @sideEffects
1178  *      None
1179  * @reentrant
1180  *      No
1181  * @threadSafe
1182  *      Yes
1183  *
1184  * @param[in] device              An icp_accel_dev_t* type
1185  * @param[in] enabled_services    Enabled services by user
1186  *
1187  **************************************************************************/
1188 static CpaStatus
1189 SalCtrl_ServiceEventStart(icp_accel_dev_t *device, Cpa32U enabled_services)
1190 {
1191 	CpaStatus status = CPA_STATUS_SUCCESS;
1192 	sal_t *service_container = device->pSalHandle;
1193 
1194 	if (service_container == NULL) {
1195 		QAT_UTILS_LOG("Private data is NULL.\n");
1196 		return CPA_STATUS_FATAL;
1197 	}
1198 
1199 	if (SalCtrl_IsServiceEnabled(enabled_services,
1200 				     SAL_SERVICE_TYPE_CRYPTO_ASYM)) {
1201 		status = SalCtrl_ServiceStart(device,
1202 					      service_container->asym_services);
1203 		if (CPA_STATUS_SUCCESS != status) {
1204 			goto err_start;
1205 		}
1206 	}
1207 
1208 	if (SalCtrl_IsServiceEnabled(enabled_services,
1209 				     SAL_SERVICE_TYPE_CRYPTO_SYM)) {
1210 		status = SalCtrl_ServiceStart(device,
1211 					      service_container->sym_services);
1212 		if (CPA_STATUS_SUCCESS != status) {
1213 			goto err_start;
1214 		}
1215 	}
1216 
1217 	if (SalCtrl_IsServiceEnabled(enabled_services,
1218 				     SAL_SERVICE_TYPE_CRYPTO)) {
1219 		status =
1220 		    SalCtrl_ServiceStart(device,
1221 					 service_container->crypto_services);
1222 		if (CPA_STATUS_SUCCESS != status) {
1223 			goto err_start;
1224 		}
1225 	}
1226 
1227 	if (SalCtrl_IsServiceEnabled(enabled_services,
1228 				     SAL_SERVICE_TYPE_COMPRESSION)) {
1229 		status = SalCtrl_ServiceStart(
1230 		    device, service_container->compression_services);
1231 		if (CPA_STATUS_SUCCESS != status) {
1232 			goto err_start;
1233 		}
1234 	}
1235 
1236 	return status;
1237 err_start:
1238 	SalCtrl_ServiceEventStop(device, enabled_services);
1239 	return status;
1240 }
1241 
1242 /*************************************************************************
1243  * @ingroup SalCtrl
1244  * @description
1245  *      This function is the events handler registered with ADF
1246  *      for the QA API services (cy, dc) - kernel and user
1247  *
1248  * @context
1249  *      This function is called from an ADF context.
1250  *
1251  * @assumptions
1252  *      None
1253  * @sideEffects
1254  *      None
1255  * @reentrant
1256  *      No
1257  * @threadSafe
1258  *      Yes
1259  *
1260  * @param[in]  device      An icp_accel_dev_t* type
1261  * @param[in]  event       Event from ADF
1262  * @param[in]  param       Parameter used for back compatibility
1263  *
1264  ***********************************************************************/
1265 static CpaStatus
1266 SalCtrl_ServiceEventHandler(icp_accel_dev_t *device,
1267 			    icp_adf_subsystemEvent_t event,
1268 			    void *param)
1269 {
1270 	CpaStatus status = CPA_STATUS_SUCCESS;
1271 	CpaStatus stats_status = CPA_STATUS_SUCCESS;
1272 	Cpa32U enabled_services = 0;
1273 
1274 	status = SalCtrl_GetEnabledServices(device, &enabled_services);
1275 	if (CPA_STATUS_SUCCESS != status) {
1276 		QAT_UTILS_LOG("Failed to get enabled services.\n");
1277 		return status;
1278 	}
1279 
1280 	switch (event) {
1281 	case ICP_ADF_EVENT_INIT: {
1282 		/* In case there is no QAT SAL needs to call InitStats */
1283 		if (NULL == device->pQatStats) {
1284 			status = SalStatistics_InitStatisticsCollection(device);
1285 		}
1286 		if (CPA_STATUS_SUCCESS != status) {
1287 			return status;
1288 		}
1289 
1290 		status = SalCtrl_ServiceEventInit(device, enabled_services);
1291 		break;
1292 	}
1293 	case ICP_ADF_EVENT_START: {
1294 		status = SalCtrl_ServiceEventStart(device, enabled_services);
1295 		break;
1296 	}
1297 	case ICP_ADF_EVENT_STOP: {
1298 		status = SalCtrl_ServiceEventStop(device, enabled_services);
1299 		break;
1300 	}
1301 	case ICP_ADF_EVENT_SHUTDOWN: {
1302 		status = SalCtrl_ServiceEventShutdown(device, enabled_services);
1303 		stats_status = SalStatistics_CleanStatisticsCollection(device);
1304 		if (CPA_STATUS_SUCCESS != status ||
1305 		    CPA_STATUS_SUCCESS != stats_status) {
1306 			return CPA_STATUS_FAIL;
1307 		}
1308 		break;
1309 	}
1310 	default:
1311 		status = CPA_STATUS_SUCCESS;
1312 		break;
1313 	}
1314 	return status;
1315 }
1316 
1317 CpaStatus
1318 SalCtrl_AdfServicesRegister(void)
1319 {
1320 	/* Fill out the global sal_service_reg_handle structure */
1321 	sal_service_reg_handle.subserviceEventHandler =
1322 	    SalCtrl_ServiceEventHandler;
1323 	/* Set subsystem name to globally defined name */
1324 	sal_service_reg_handle.subsystem_name = subsystem_name;
1325 
1326 	return icp_adf_subsystemRegister(&sal_service_reg_handle);
1327 }
1328 
1329 CpaStatus
1330 SalCtrl_AdfServicesUnregister(void)
1331 {
1332 	return icp_adf_subsystemUnregister(&sal_service_reg_handle);
1333 }
1334 
1335 CpaStatus
1336 SalCtrl_AdfServicesStartedCheck(void)
1337 {
1338 	CpaStatus status = CPA_STATUS_SUCCESS;
1339 	Cpa32U retry_num = 0;
1340 	CpaBoolean state = CPA_FALSE;
1341 
1342 	do {
1343 		state = icp_adf_isSubsystemStarted(&sal_service_reg_handle);
1344 		retry_num++;
1345 	} while ((CPA_FALSE == state) && (retry_num < MAX_SUBSYSTEM_RETRY));
1346 
1347 	if (CPA_FALSE == state) {
1348 		QAT_UTILS_LOG("Sal Ctrl failed to start in given time.\n");
1349 		status = CPA_STATUS_FAIL;
1350 	}
1351 
1352 	return status;
1353 }
1354 
1355 CpaStatus
1356 validateConcurrRequest(Cpa32U numConcurrRequests)
1357 {
1358 	Cpa32U baseReq = SAL_64_CONCURR_REQUESTS;
1359 
1360 	if (SAL_64_CONCURR_REQUESTS > numConcurrRequests) {
1361 		QAT_UTILS_LOG(
1362 		    "Invalid numConcurrRequests, it is less than min value.\n");
1363 		return CPA_STATUS_FAIL;
1364 	}
1365 
1366 	while (SAL_MAX_CONCURR_REQUESTS >= baseReq) {
1367 		if (baseReq != numConcurrRequests) {
1368 			baseReq = baseReq << 1;
1369 		} else {
1370 			break;
1371 		}
1372 	}
1373 	if (SAL_MAX_CONCURR_REQUESTS < baseReq) {
1374 		QAT_UTILS_LOG(
1375 		    "Invalid baseReg, it is greater than max value.\n");
1376 		return CPA_STATUS_FAIL;
1377 	}
1378 
1379 	return CPA_STATUS_SUCCESS;
1380 }
1381