xref: /freebsd-src/sys/dev/qat/qat_api/common/ctrl/sal_ctrl_services.c (revision bb2d13b686e3ccf6c3ccb36209dfb7dcc108b182)
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 /*************************************************************************
462  * @ingroup SalCtrl
463  * @description
464  *      This function is used to initialise the service instances.
465  *      It allocates memory for service instances and invokes the
466  *      Init function on them.
467  *
468  * @context
469  *      This function is called from the SalCtrl_ServiceEventInit function.
470  *
471  * @assumptions
472  *      None
473  * @sideEffects
474  *      None
475  * @reentrant
476  *      No
477  * @threadSafe
478  *      Yes
479  *
480  * @param[in] device           An icp_accel_dev_t* type
481  * @param[in] services         A pointer to the container of services
482  * @param[in] dbg_dir          A pointer to the debug directory
483  * @param[in] dbg_dir_name     Name of the debug directory
484  * @param[in] tail_list        SAL's list of services
485  * @param[in] instance_count   Number of instances
486  * @param[in] svc_type         The type of the service instance
487  *
488  *************************************************************************/
489 static CpaStatus
490 SalCtrl_ServiceInit(icp_accel_dev_t *device,
491 		    sal_list_t **services,
492 		    debug_dir_info_t **dbg_dir,
493 		    char *dbg_dir_name,
494 		    sal_list_t *tail_list,
495 		    Cpa32U instance_count,
496 		    sal_service_type_t svc_type)
497 {
498 	CpaStatus status = CPA_STATUS_SUCCESS;
499 	sal_service_t *pInst = NULL;
500 	Cpa32U i = 0;
501 	debug_dir_info_t *debug_dir = NULL;
502 
503 	debug_dir = LAC_OS_MALLOC(sizeof(debug_dir_info_t));
504 	if (NULL == debug_dir) {
505 		QAT_UTILS_LOG("Failed to allocate memory for debug dir.\n");
506 		return CPA_STATUS_RESOURCE;
507 	}
508 	debug_dir->name = dbg_dir_name;
509 	debug_dir->parent = NULL;
510 	status = icp_adf_debugAddDir(device, debug_dir);
511 	if (CPA_STATUS_SUCCESS != status) {
512 		QAT_UTILS_LOG("Failed to add debug dir.\n");
513 		LAC_OS_FREE(debug_dir);
514 		debug_dir = NULL;
515 		return status;
516 	}
517 
518 	if (!icp_adf_is_dev_in_reset(device)) {
519 		for (i = 0; i < instance_count; i++) {
520 			status = SalCtrl_ServiceCreate(svc_type, i, &pInst);
521 			if (CPA_STATUS_SUCCESS != status) {
522 				break;
523 			}
524 			pInst->debug_parent_dir = debug_dir;
525 			pInst->capabilitiesMask = device->accelCapabilitiesMask;
526 			status = SalList_add(services, &tail_list, pInst);
527 			if (CPA_STATUS_SUCCESS != status) {
528 				free(pInst, M_QAT);
529 			}
530 		}
531 	} else {
532 		sal_list_t *curr_element = *services;
533 		sal_service_t *service = NULL;
534 		while (NULL != curr_element) {
535 			service =
536 			    (sal_service_t *)SalList_getObject(curr_element);
537 			service->debug_parent_dir = debug_dir;
538 
539 			if (CPA_TRUE == service->isInstanceStarted) {
540 				icp_qa_dev_get(device);
541 			}
542 
543 			curr_element = SalList_next(curr_element);
544 		}
545 	}
546 
547 	if (CPA_STATUS_SUCCESS != status) {
548 		QAT_UTILS_LOG("Failed to allocate all instances.\n");
549 		icp_adf_debugRemoveDir(debug_dir);
550 		LAC_OS_FREE(debug_dir);
551 		debug_dir = NULL;
552 		SalList_free(services);
553 		return status;
554 	}
555 
556 	/* Call init function for each service instance */
557 	SAL_FOR_EACH(*services, sal_service_t, device, init, status);
558 	if (CPA_STATUS_SUCCESS != status) {
559 		QAT_UTILS_LOG("Failed to initialise all service instances.\n");
560 		/* shutdown all instances initialised before error */
561 		SAL_FOR_EACH_STATE(*services,
562 				   sal_service_t,
563 				   device,
564 				   shutdown,
565 				   SAL_SERVICE_STATE_INITIALIZED);
566 		icp_adf_debugRemoveDir(debug_dir);
567 		LAC_OS_FREE(debug_dir);
568 		debug_dir = NULL;
569 		SalList_free(services);
570 		return status;
571 	}
572 	/* initialize the debug directory for relevant service */
573 	*dbg_dir = debug_dir;
574 
575 	return status;
576 }
577 
578 /**************************************************************************
579  * @ingroup SalCtrl
580  * @description
581  *      This function calls the start function on all the service instances.
582  *
583  * @context
584  *      This function is called from the SalCtrl_ServiceEventStart function.
585  *
586  * @assumptions
587  *      None
588  * @sideEffects
589  *      None
590  * @reentrant
591  *      No
592  * @threadSafe
593  *      Yes
594  *
595  * @param[in] device     An icp_accel_dev_t* type
596  * @param[in] services   A pointer to the container of services
597  *
598  **************************************************************************/
599 static CpaStatus
600 SalCtrl_ServiceStart(icp_accel_dev_t *device, sal_list_t *services)
601 {
602 	CpaStatus status = CPA_STATUS_SUCCESS;
603 
604 	/* Call Start function for each service instance */
605 	SAL_FOR_EACH(services, sal_service_t, device, start, status);
606 	if (CPA_STATUS_SUCCESS != status) {
607 		QAT_UTILS_LOG("Failed to start all instances.\n");
608 		/* stop all instances started before error */
609 		SAL_FOR_EACH_STATE(services,
610 				   sal_service_t,
611 				   device,
612 				   stop,
613 				   SAL_SERVICE_STATE_RUNNING);
614 		return status;
615 	}
616 
617 	if (icp_adf_is_dev_in_reset(device)) {
618 		sal_list_t *curr_element = services;
619 		sal_service_t *service = NULL;
620 		while (NULL != curr_element) {
621 			service =
622 			    (sal_service_t *)SalList_getObject(curr_element);
623 			if (service->notification_cb) {
624 				service->notification_cb(
625 				    service,
626 				    service->cb_tag,
627 				    CPA_INSTANCE_EVENT_RESTARTED);
628 			}
629 			curr_element = SalList_next(curr_element);
630 		}
631 	}
632 
633 	return status;
634 }
635 
636 /****************************************************************************
637  * @ingroup SalCtrl
638  * @description
639  *      This function calls the stop function on all the
640  *      service instances.
641  *
642  * @context
643  *      This function is called from the SalCtrl_ServiceEventStop function.
644  *
645  * @assumptions
646  *      None
647  * @sideEffects
648  *      None
649  * @reentrant
650  *      No
651  * @threadSafe
652  *      Yes
653  *
654  * @param[in] device    An icp_accel_dev_t* type
655  * @param[in] services   A pointer to the container of services
656  *
657  *************************************************************************/
658 static CpaStatus
659 SalCtrl_ServiceStop(icp_accel_dev_t *device, sal_list_t *services)
660 {
661 	CpaStatus status = CPA_STATUS_SUCCESS;
662 
663 	/* Calling restarting functions */
664 	if (icp_adf_is_dev_in_reset(device)) {
665 		sal_list_t *curr_element = services;
666 		sal_service_t *service = NULL;
667 		while (NULL != curr_element) {
668 			service =
669 			    (sal_service_t *)SalList_getObject(curr_element);
670 			if (service->notification_cb) {
671 				service->notification_cb(
672 				    service,
673 				    service->cb_tag,
674 				    CPA_INSTANCE_EVENT_RESTARTING);
675 			}
676 			curr_element = SalList_next(curr_element);
677 		}
678 	}
679 
680 	/* Call Stop function for each service instance */
681 	SAL_FOR_EACH(services, sal_service_t, device, stop, status);
682 
683 	return status;
684 }
685 
686 /*
687  * @ingroup SalCtrl
688  * @description
689  *      This function is used to print hardware and software versions in proc
690  *      filesystem entry via ADF Debug interface
691  *
692  * @context
693  *    This functions is called from proc filesystem interface
694  *
695  * @assumptions
696  *      None
697  * @sideEffects
698  *      None
699  * @reentrant
700  *      No
701  * @threadSafe
702  *      Yes
703  *
704  * @param[in]  private_data    A pointer to a private data passed to the
705  *                             function while adding a debug file.
706  * @param[out] data            Pointer to a buffer where version information
707  *                             needs to be printed to.
708  * @param[in]  size            Size of a buffer pointed by data.
709  * @param[in]  offset          Offset in a debug file
710  *
711  * @retval 0    This function always returns 0
712  */
713 static int
714 SalCtrl_VersionDebug(void *private_data, char *data, int size, int offset)
715 {
716 	CpaStatus status = CPA_STATUS_SUCCESS;
717 	Cpa32U len = 0;
718 	icp_accel_dev_t *device = (icp_accel_dev_t *)private_data;
719 	char param_value[ADF_CFG_MAX_VAL_LEN_IN_BYTES] = { 0 };
720 
721 	len += snprintf(
722 	    data + len,
723 	    size - len,
724 	    SEPARATOR BORDER
725 	    " Hardware and Software versions for device %d      " BORDER
726 	    "\n" SEPARATOR,
727 	    device->accelId);
728 
729 	memset(param_value, 0, ADF_CFG_MAX_VAL_LEN_IN_BYTES);
730 	status = icp_adf_cfgGetParamValue(device,
731 					  LAC_CFG_SECTION_GENERAL,
732 					  ICP_CFG_HW_REV_ID_KEY,
733 					  param_value);
734 	LAC_CHECK_STATUS(status);
735 
736 	len += snprintf(data + len,
737 			size - len,
738 			" Hardware Version:             %s %s \n",
739 			param_value,
740 			get_sku_info(device->sku));
741 
742 	memset(param_value, 0, ADF_CFG_MAX_VAL_LEN_IN_BYTES);
743 	status = icp_adf_cfgGetParamValue(device,
744 					  LAC_CFG_SECTION_GENERAL,
745 					  ICP_CFG_UOF_VER_KEY,
746 					  param_value);
747 	LAC_CHECK_STATUS(status);
748 
749 	len += snprintf(data + len,
750 			size - len,
751 			" Firmware Version:             %s \n",
752 			param_value);
753 	memset(param_value, 0, ADF_CFG_MAX_VAL_LEN_IN_BYTES);
754 	status = icp_adf_cfgGetParamValue(device,
755 					  LAC_CFG_SECTION_GENERAL,
756 					  ICP_CFG_MMP_VER_KEY,
757 					  param_value);
758 	LAC_CHECK_STATUS(status);
759 
760 	len += snprintf(data + len,
761 			size - len,
762 			" MMP Version:                  %s \n",
763 			param_value);
764 	len += snprintf(data + len,
765 			size - len,
766 			" Driver Version:               %d.%d.%d \n",
767 			SAL_INFO2_DRIVER_SW_VERSION_MAJ_NUMBER,
768 			SAL_INFO2_DRIVER_SW_VERSION_MIN_NUMBER,
769 			SAL_INFO2_DRIVER_SW_VERSION_PATCH_NUMBER);
770 
771 	memset(param_value, 0, ADF_CFG_MAX_VAL_LEN_IN_BYTES);
772 	status = icp_adf_cfgGetParamValue(device,
773 					  LAC_CFG_SECTION_GENERAL,
774 					  ICP_CFG_LO_COMPATIBLE_DRV_KEY,
775 					  param_value);
776 	LAC_CHECK_STATUS(status);
777 
778 	len += snprintf(data + len,
779 			size - len,
780 			" Lowest Compatible Driver:     %s \n",
781 			param_value);
782 
783 	len += snprintf(data + len,
784 			size - len,
785 			" QuickAssist API CY Version:   %d.%d \n",
786 			CPA_CY_API_VERSION_NUM_MAJOR,
787 			CPA_CY_API_VERSION_NUM_MINOR);
788 	len += snprintf(data + len,
789 			size - len,
790 			" QuickAssist API DC Version:   %d.%d \n",
791 			CPA_DC_API_VERSION_NUM_MAJOR,
792 			CPA_DC_API_VERSION_NUM_MINOR);
793 
794 	len += snprintf(data + len, size - len, SEPARATOR);
795 	return 0;
796 }
797 
798 /**************************************************************************
799  * @ingroup SalCtrl
800  * @description
801  *       This function calls the shutdown function on all the service
802  *       instances. It also frees all service instance memory
803  *       allocated at Init.
804  *
805  * @context
806  *      This function is called from the SalCtrl_ServiceEventHandler function.
807  *
808  * @assumptions
809  *      None
810  * @sideEffects
811  *      None
812  * @reentrant
813  *      No
814  * @threadSafe
815  *      Yes
816  *
817  * @param[in] device             An icp_accel_dev_t* type
818  * @param[in] enabled_services   Services enabled by user
819  *
820  ****************************************************************************/
821 static CpaStatus
822 SalCtrl_ServiceEventShutdown(icp_accel_dev_t *device, Cpa32U enabled_services)
823 {
824 	CpaStatus status = CPA_STATUS_SUCCESS;
825 	CpaStatus ret_status = CPA_STATUS_SUCCESS;
826 	sal_t *service_container = (sal_t *)device->pSalHandle;
827 
828 	if (NULL == service_container) {
829 		QAT_UTILS_LOG("Private data is NULL\n");
830 		return CPA_STATUS_FATAL;
831 	}
832 
833 	if (SalCtrl_IsServiceEnabled(enabled_services,
834 				     SAL_SERVICE_TYPE_CRYPTO)) {
835 		status =
836 		    SalCtrl_ServiceShutdown(device,
837 					    &service_container->crypto_services,
838 					    &service_container->cy_dir,
839 					    SAL_SERVICE_TYPE_CRYPTO);
840 		if (CPA_STATUS_SUCCESS != status) {
841 			ret_status = status;
842 		}
843 	}
844 
845 	if (SalCtrl_IsServiceEnabled(enabled_services,
846 				     SAL_SERVICE_TYPE_CRYPTO_ASYM)) {
847 		status =
848 		    SalCtrl_ServiceShutdown(device,
849 					    &service_container->asym_services,
850 					    &service_container->asym_dir,
851 					    SAL_SERVICE_TYPE_CRYPTO_ASYM);
852 		if (CPA_STATUS_SUCCESS != status) {
853 			ret_status = status;
854 		}
855 	}
856 
857 	if (SalCtrl_IsServiceEnabled(enabled_services,
858 				     SAL_SERVICE_TYPE_CRYPTO_SYM)) {
859 		status =
860 		    SalCtrl_ServiceShutdown(device,
861 					    &service_container->sym_services,
862 					    &service_container->sym_dir,
863 					    SAL_SERVICE_TYPE_CRYPTO_SYM);
864 		if (CPA_STATUS_SUCCESS != status) {
865 			ret_status = status;
866 		}
867 	}
868 
869 	if (SalCtrl_IsServiceEnabled(enabled_services,
870 				     SAL_SERVICE_TYPE_COMPRESSION)) {
871 		status = SalCtrl_ServiceShutdown(
872 		    device,
873 		    &service_container->compression_services,
874 		    &service_container->dc_dir,
875 		    SAL_SERVICE_TYPE_COMPRESSION);
876 		if (CPA_STATUS_SUCCESS != status) {
877 			ret_status = status;
878 		}
879 	}
880 
881 	if (service_container->ver_file) {
882 		icp_adf_debugRemoveFile(service_container->ver_file);
883 		LAC_OS_FREE(service_container->ver_file);
884 		service_container->ver_file = NULL;
885 	}
886 
887 	if (!icp_adf_is_dev_in_reset(device)) {
888 		/* Free container also */
889 		free(service_container, M_QAT);
890 		device->pSalHandle = NULL;
891 	}
892 
893 	return ret_status;
894 }
895 
896 /*************************************************************************
897  * @ingroup SalCtrl
898  * @description
899  *      This function is used to initialize the service instances.
900  *      It first checks (via ADF query) which services are enabled in the
901  *      system and the number of each services.
902  *      It then invokes the init function on them which creates the
903  *      instances and allocates memory for them.
904  *
905  * @context
906  *      This function is called from the SalCtrl_ServiceEventHandler function.
907  *
908  * @assumptions
909  *      None
910  * @sideEffects
911  *      None
912  * @reentrant
913  *      No
914  * @threadSafe
915  *      Yes
916  *
917  * @param[in] device             An icp_accel_dev_t* type
918  * @param[in] enabled_services   Services enabled by user
919  *
920  *************************************************************************/
921 static CpaStatus
922 SalCtrl_ServiceEventInit(icp_accel_dev_t *device, Cpa32U enabled_services)
923 {
924 	sal_t *service_container = NULL;
925 	CpaStatus status = CPA_STATUS_SUCCESS;
926 	sal_list_t *tail_list = NULL;
927 	Cpa32U instance_count = 0;
928 
929 	status = SalCtrl_GetSupportedServices(device, enabled_services);
930 	if (CPA_STATUS_SUCCESS != status) {
931 		QAT_UTILS_LOG("Failed to get supported services.\n");
932 		return status;
933 	}
934 
935 	if (!icp_adf_is_dev_in_reset(device)) {
936 		service_container = malloc(sizeof(sal_t), M_QAT, M_WAITOK);
937 		device->pSalHandle = service_container;
938 		service_container->asym_services = NULL;
939 		service_container->sym_services = NULL;
940 		service_container->crypto_services = NULL;
941 		service_container->compression_services = NULL;
942 	} else {
943 		service_container = device->pSalHandle;
944 	}
945 	service_container->asym_dir = NULL;
946 	service_container->sym_dir = NULL;
947 	service_container->cy_dir = NULL;
948 	service_container->dc_dir = NULL;
949 	service_container->ver_file = NULL;
950 
951 	service_container->ver_file = LAC_OS_MALLOC(sizeof(debug_file_info_t));
952 	if (NULL == service_container->ver_file) {
953 		free(service_container, M_QAT);
954 		return CPA_STATUS_RESOURCE;
955 	}
956 
957 	memset(service_container->ver_file, 0, sizeof(debug_file_info_t));
958 	service_container->ver_file->name = ver_file_name;
959 	service_container->ver_file->seq_read = SalCtrl_VersionDebug;
960 	service_container->ver_file->private_data = device;
961 	service_container->ver_file->parent = NULL;
962 
963 	status = icp_adf_debugAddFile(device, service_container->ver_file);
964 	if (CPA_STATUS_SUCCESS != status) {
965 		LAC_OS_FREE(service_container->ver_file);
966 		free(service_container, M_QAT);
967 		return status;
968 	}
969 
970 	if (SalCtrl_IsServiceEnabled(enabled_services,
971 				     SAL_SERVICE_TYPE_CRYPTO_ASYM)) {
972 		status = SalCtrl_GetInstanceCount(device,
973 						  "NumberCyInstances",
974 						  &instance_count);
975 		if (CPA_STATUS_SUCCESS != status) {
976 			instance_count = 0;
977 		}
978 		status = SalCtrl_ServiceInit(device,
979 					     &service_container->asym_services,
980 					     &service_container->asym_dir,
981 					     asym_dir_name,
982 					     tail_list,
983 					     instance_count,
984 					     SAL_SERVICE_TYPE_CRYPTO_ASYM);
985 		if (CPA_STATUS_SUCCESS != status) {
986 			goto err_init;
987 		}
988 	}
989 
990 	if (SalCtrl_IsServiceEnabled(enabled_services,
991 				     SAL_SERVICE_TYPE_CRYPTO_SYM)) {
992 		status = SalCtrl_GetInstanceCount(device,
993 						  "NumberCyInstances",
994 						  &instance_count);
995 		if (CPA_STATUS_SUCCESS != status) {
996 			instance_count = 0;
997 		}
998 		status = SalCtrl_ServiceInit(device,
999 					     &service_container->sym_services,
1000 					     &service_container->sym_dir,
1001 					     sym_dir_name,
1002 					     tail_list,
1003 					     instance_count,
1004 					     SAL_SERVICE_TYPE_CRYPTO_SYM);
1005 		if (CPA_STATUS_SUCCESS != status) {
1006 			goto err_init;
1007 		}
1008 	}
1009 
1010 	if (SalCtrl_IsServiceEnabled(enabled_services,
1011 				     SAL_SERVICE_TYPE_CRYPTO)) {
1012 		status = SalCtrl_GetInstanceCount(device,
1013 						  "NumberCyInstances",
1014 						  &instance_count);
1015 		if (CPA_STATUS_SUCCESS != status) {
1016 			instance_count = 0;
1017 		}
1018 		status =
1019 		    SalCtrl_ServiceInit(device,
1020 					&service_container->crypto_services,
1021 					&service_container->cy_dir,
1022 					cy_dir_name,
1023 					tail_list,
1024 					instance_count,
1025 					SAL_SERVICE_TYPE_CRYPTO);
1026 		if (CPA_STATUS_SUCCESS != status) {
1027 			goto err_init;
1028 		}
1029 	}
1030 	if (SalCtrl_IsServiceEnabled(enabled_services,
1031 				     SAL_SERVICE_TYPE_COMPRESSION)) {
1032 		status = SalCtrl_GetInstanceCount(device,
1033 						  "NumberDcInstances",
1034 						  &instance_count);
1035 		if (CPA_STATUS_SUCCESS != status) {
1036 			instance_count = 0;
1037 		}
1038 		status = SalCtrl_ServiceInit(
1039 		    device,
1040 		    &service_container->compression_services,
1041 		    &service_container->dc_dir,
1042 		    dc_dir_name,
1043 		    tail_list,
1044 		    instance_count,
1045 		    SAL_SERVICE_TYPE_COMPRESSION);
1046 		if (CPA_STATUS_SUCCESS != status) {
1047 			goto err_init;
1048 		}
1049 	}
1050 
1051 	return status;
1052 
1053 err_init:
1054 	SalCtrl_ServiceEventShutdown(device, enabled_services);
1055 	return status;
1056 }
1057 
1058 /****************************************************************************
1059  * @ingroup SalCtrl
1060  * @description
1061  *      This function calls the stop function on all the service instances.
1062  *
1063  * @context
1064  *      This function is called from the SalCtrl_ServiceEventHandler function.
1065  *
1066  * @assumptions
1067  *      None
1068  * @sideEffects
1069  *      None
1070  * @reentrant
1071  *      No
1072  * @threadSafe
1073  *      Yes
1074  *
1075  * @param[in] device              An icp_accel_dev_t* type
1076  * @param[in] enabled_services    Enabled services by user
1077  *
1078  *************************************************************************/
1079 static CpaStatus
1080 SalCtrl_ServiceEventStop(icp_accel_dev_t *device, Cpa32U enabled_services)
1081 {
1082 	CpaStatus status = CPA_STATUS_SUCCESS;
1083 	CpaStatus ret_status = CPA_STATUS_SUCCESS;
1084 	sal_t *service_container = device->pSalHandle;
1085 
1086 	if (service_container == NULL) {
1087 		QAT_UTILS_LOG("Private data is NULL.\n");
1088 		return CPA_STATUS_FATAL;
1089 	}
1090 
1091 	if (SalCtrl_IsServiceEnabled(enabled_services,
1092 				     SAL_SERVICE_TYPE_CRYPTO_ASYM)) {
1093 		status = SalCtrl_ServiceStop(device,
1094 					     service_container->asym_services);
1095 		if (CPA_STATUS_SUCCESS != status) {
1096 			ret_status = status;
1097 		}
1098 	}
1099 
1100 	if (SalCtrl_IsServiceEnabled(enabled_services,
1101 				     SAL_SERVICE_TYPE_CRYPTO_SYM)) {
1102 		status = SalCtrl_ServiceStop(device,
1103 					     service_container->sym_services);
1104 		if (CPA_STATUS_SUCCESS != status) {
1105 			ret_status = status;
1106 		}
1107 	}
1108 
1109 	if (SalCtrl_IsServiceEnabled(enabled_services,
1110 				     SAL_SERVICE_TYPE_CRYPTO)) {
1111 		status =
1112 		    SalCtrl_ServiceStop(device,
1113 					service_container->crypto_services);
1114 		if (CPA_STATUS_SUCCESS != status) {
1115 			ret_status = status;
1116 		}
1117 	}
1118 
1119 	if (SalCtrl_IsServiceEnabled(enabled_services,
1120 				     SAL_SERVICE_TYPE_COMPRESSION)) {
1121 		status = SalCtrl_ServiceStop(
1122 		    device, service_container->compression_services);
1123 		if (CPA_STATUS_SUCCESS != status) {
1124 			ret_status = status;
1125 		}
1126 	}
1127 
1128 	return ret_status;
1129 }
1130 
1131 /**************************************************************************
1132  * @ingroup SalCtrl
1133  * @description
1134  *      This function calls the start function on all the service instances.
1135  *
1136  * @context
1137  *      This function is called from the SalCtrl_ServiceEventHandler function.
1138  *
1139  * @assumptions
1140  *      None
1141  * @sideEffects
1142  *      None
1143  * @reentrant
1144  *      No
1145  * @threadSafe
1146  *      Yes
1147  *
1148  * @param[in] device              An icp_accel_dev_t* type
1149  * @param[in] enabled_services    Enabled services by user
1150  *
1151  **************************************************************************/
1152 static CpaStatus
1153 SalCtrl_ServiceEventStart(icp_accel_dev_t *device, Cpa32U enabled_services)
1154 {
1155 	CpaStatus status = CPA_STATUS_SUCCESS;
1156 	sal_t *service_container = device->pSalHandle;
1157 
1158 	if (service_container == NULL) {
1159 		QAT_UTILS_LOG("Private data is NULL.\n");
1160 		return CPA_STATUS_FATAL;
1161 	}
1162 
1163 	if (SalCtrl_IsServiceEnabled(enabled_services,
1164 				     SAL_SERVICE_TYPE_CRYPTO_ASYM)) {
1165 		status = SalCtrl_ServiceStart(device,
1166 					      service_container->asym_services);
1167 		if (CPA_STATUS_SUCCESS != status) {
1168 			goto err_start;
1169 		}
1170 	}
1171 
1172 	if (SalCtrl_IsServiceEnabled(enabled_services,
1173 				     SAL_SERVICE_TYPE_CRYPTO_SYM)) {
1174 		status = SalCtrl_ServiceStart(device,
1175 					      service_container->sym_services);
1176 		if (CPA_STATUS_SUCCESS != status) {
1177 			goto err_start;
1178 		}
1179 	}
1180 
1181 	if (SalCtrl_IsServiceEnabled(enabled_services,
1182 				     SAL_SERVICE_TYPE_CRYPTO)) {
1183 		status =
1184 		    SalCtrl_ServiceStart(device,
1185 					 service_container->crypto_services);
1186 		if (CPA_STATUS_SUCCESS != status) {
1187 			goto err_start;
1188 		}
1189 	}
1190 
1191 	if (SalCtrl_IsServiceEnabled(enabled_services,
1192 				     SAL_SERVICE_TYPE_COMPRESSION)) {
1193 		status = SalCtrl_ServiceStart(
1194 		    device, service_container->compression_services);
1195 		if (CPA_STATUS_SUCCESS != status) {
1196 			goto err_start;
1197 		}
1198 	}
1199 
1200 	return status;
1201 err_start:
1202 	SalCtrl_ServiceEventStop(device, enabled_services);
1203 	return status;
1204 }
1205 
1206 /*************************************************************************
1207  * @ingroup SalCtrl
1208  * @description
1209  *      This function is the events handler registered with ADF
1210  *      for the QA API services (cy, dc) - kernel and user
1211  *
1212  * @context
1213  *      This function is called from an ADF context.
1214  *
1215  * @assumptions
1216  *      None
1217  * @sideEffects
1218  *      None
1219  * @reentrant
1220  *      No
1221  * @threadSafe
1222  *      Yes
1223  *
1224  * @param[in]  device      An icp_accel_dev_t* type
1225  * @param[in]  event       Event from ADF
1226  * @param[in]  param       Parameter used for back compatibility
1227  *
1228  ***********************************************************************/
1229 static CpaStatus
1230 SalCtrl_ServiceEventHandler(icp_accel_dev_t *device,
1231 			    icp_adf_subsystemEvent_t event,
1232 			    void *param)
1233 {
1234 	CpaStatus status = CPA_STATUS_SUCCESS;
1235 	CpaStatus stats_status = CPA_STATUS_SUCCESS;
1236 	Cpa32U enabled_services = 0;
1237 
1238 	status = SalCtrl_GetEnabledServices(device, &enabled_services);
1239 	if (CPA_STATUS_SUCCESS != status) {
1240 		QAT_UTILS_LOG("Failed to get enabled services.\n");
1241 		return status;
1242 	}
1243 
1244 	switch (event) {
1245 	case ICP_ADF_EVENT_INIT: {
1246 		/* In case there is no QAT SAL needs to call InitStats */
1247 		if (NULL == device->pQatStats) {
1248 			status = SalStatistics_InitStatisticsCollection(device);
1249 		}
1250 		if (CPA_STATUS_SUCCESS != status) {
1251 			return status;
1252 		}
1253 
1254 		status = SalCtrl_ServiceEventInit(device, enabled_services);
1255 		break;
1256 	}
1257 	case ICP_ADF_EVENT_START: {
1258 		status = SalCtrl_ServiceEventStart(device, enabled_services);
1259 		break;
1260 	}
1261 	case ICP_ADF_EVENT_STOP: {
1262 		status = SalCtrl_ServiceEventStop(device, enabled_services);
1263 		break;
1264 	}
1265 	case ICP_ADF_EVENT_SHUTDOWN: {
1266 		status = SalCtrl_ServiceEventShutdown(device, enabled_services);
1267 		stats_status = SalStatistics_CleanStatisticsCollection(device);
1268 		if (CPA_STATUS_SUCCESS != status ||
1269 		    CPA_STATUS_SUCCESS != stats_status) {
1270 			return CPA_STATUS_FAIL;
1271 		}
1272 		break;
1273 	}
1274 	default:
1275 		status = CPA_STATUS_SUCCESS;
1276 		break;
1277 	}
1278 	return status;
1279 }
1280 
1281 CpaStatus
1282 SalCtrl_AdfServicesRegister(void)
1283 {
1284 	/* Fill out the global sal_service_reg_handle structure */
1285 	sal_service_reg_handle.subserviceEventHandler =
1286 	    SalCtrl_ServiceEventHandler;
1287 	/* Set subsystem name to globally defined name */
1288 	sal_service_reg_handle.subsystem_name = subsystem_name;
1289 
1290 	return icp_adf_subsystemRegister(&sal_service_reg_handle);
1291 }
1292 
1293 CpaStatus
1294 SalCtrl_AdfServicesUnregister(void)
1295 {
1296 	return icp_adf_subsystemUnregister(&sal_service_reg_handle);
1297 }
1298 
1299 CpaStatus
1300 SalCtrl_AdfServicesStartedCheck(void)
1301 {
1302 	CpaStatus status = CPA_STATUS_SUCCESS;
1303 	Cpa32U retry_num = 0;
1304 	CpaBoolean state = CPA_FALSE;
1305 
1306 	do {
1307 		state = icp_adf_isSubsystemStarted(&sal_service_reg_handle);
1308 		retry_num++;
1309 	} while ((CPA_FALSE == state) && (retry_num < MAX_SUBSYSTEM_RETRY));
1310 
1311 	if (CPA_FALSE == state) {
1312 		QAT_UTILS_LOG("Sal Ctrl failed to start in given time.\n");
1313 		status = CPA_STATUS_FAIL;
1314 	}
1315 
1316 	return status;
1317 }
1318 
1319 CpaStatus
1320 validateConcurrRequest(Cpa32U numConcurrRequests)
1321 {
1322 	Cpa32U baseReq = SAL_64_CONCURR_REQUESTS;
1323 
1324 	if (SAL_64_CONCURR_REQUESTS > numConcurrRequests) {
1325 		QAT_UTILS_LOG(
1326 		    "Invalid numConcurrRequests, it is less than min value.\n");
1327 		return CPA_STATUS_FAIL;
1328 	}
1329 
1330 	while (SAL_MAX_CONCURR_REQUESTS >= baseReq) {
1331 		if (baseReq != numConcurrRequests) {
1332 			baseReq = baseReq << 1;
1333 		} else {
1334 			break;
1335 		}
1336 	}
1337 	if (SAL_MAX_CONCURR_REQUESTS < baseReq) {
1338 		QAT_UTILS_LOG(
1339 		    "Invalid baseReg, it is greater than max value.\n");
1340 		return CPA_STATUS_FAIL;
1341 	}
1342 
1343 	return CPA_STATUS_SUCCESS;
1344 }
1345