1 /*************************************************************************
3 * This file is provided under a dual BSD/GPLv2 license. When using or
4 * redistributing this file, you may do so under either license.
8 * Copyright(c) 2007,2008,2009 Intel Corporation. All rights reserved.
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of version 2 of the GNU General Public License as
12 * published by the Free Software Foundation.
14 * This program is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
22 * The full GNU General Public License is included in this distribution
23 * in the file called LICENSE.GPL.
25 * Contact Information:
30 * Copyright(c) 2007,2008,2009 Intel Corporation. All rights reserved.
31 * All rights reserved.
33 * Redistribution and use in source and binary forms, with or without
34 * modification, are permitted provided that the following conditions
37 * * Redistributions of source code must retain the above copyright
38 * notice, this list of conditions and the following disclaimer.
39 * * Redistributions in binary form must reproduce the above copyright
40 * notice, this list of conditions and the following disclaimer in
41 * the documentation and/or other materials provided with the
43 * * Neither the name of Intel Corporation nor the names of its
44 * contributors may be used to endorse or promote products derived
45 * from this software without specific prior written permission.
47 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
48 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
49 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
50 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
51 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
52 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
53 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
54 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
55 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
56 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
57 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
60 * version: Security.L.1.0.2-229
62 ***************************************************************************/
65 * An OCF module that uses IntelĀ® QuickAssist Integrated Accelerator to do the
68 * This driver requires the ICP Access Library that is available from Intel in
74 #define ICP_OCF_COMP_NAME "ICP_OCF"
75 #define ICP_OCF_VER_MAIN (2)
76 #define ICP_OCF_VER_MJR (1)
77 #define ICP_OCF_VER_MNR (0)
79 #define MAX_DEREG_RETRIES (100)
80 #define DEFAULT_DEREG_RETRIES (10)
81 #define DEFAULT_DEREG_DELAY_IN_JIFFIES (10)
83 /* This defines the maximum number of sessions possible between OCF
84 and the OCF EP80579 Driver. If set to zero, there is no limit. */
85 #define DEFAULT_OCF_TO_DRV_MAX_SESSION_COUNT (0)
86 #define NUM_SUPPORTED_CAPABILITIES (21)
89 #define ICP_SESSION_DATA_NAME "icp_ocf.SesDat"
90 #define ICP_OP_DATA_NAME "icp_ocf.OpDat"
91 #define ICP_DH_NAME "icp_ocf.DH"
92 #define ICP_MODEXP_NAME "icp_ocf.ModExp"
93 #define ICP_RSA_DECRYPT_NAME "icp_ocf.RSAdec"
94 #define ICP_RSA_PKEY_NAME "icp_ocf.RSApk"
95 #define ICP_DSA_SIGN_NAME "icp_ocf.DSAsg"
96 #define ICP_DSA_VER_NAME "icp_ocf.DSAver"
97 #define ICP_RAND_VAL_NAME "icp_ocf.DSArnd"
98 #define ICP_FLAT_BUFF_NAME "icp_ocf.FB"
101 icp_kmem_cache drvSessionData_zone
= NULL
;
102 icp_kmem_cache drvOpData_zone
= NULL
;
103 icp_kmem_cache drvDH_zone
= NULL
;
104 icp_kmem_cache drvLnModExp_zone
= NULL
;
105 icp_kmem_cache drvRSADecrypt_zone
= NULL
;
106 icp_kmem_cache drvRSAPrivateKey_zone
= NULL
;
107 icp_kmem_cache drvDSARSSign_zone
= NULL
;
108 icp_kmem_cache drvDSARSSignKValue_zone
= NULL
;
109 icp_kmem_cache drvDSAVerify_zone
= NULL
;
111 /*Slab zones for flatbuffers and bufferlist*/
112 icp_kmem_cache drvFlatBuffer_zone
= NULL
;
114 static inline int icp_cache_null_check(void)
116 return (drvSessionData_zone
&& drvOpData_zone
117 && drvDH_zone
&& drvLnModExp_zone
&& drvRSADecrypt_zone
118 && drvRSAPrivateKey_zone
&& drvDSARSSign_zone
119 && drvDSARSSign_zone
&& drvDSARSSignKValue_zone
120 && drvDSAVerify_zone
&& drvFlatBuffer_zone
);
123 /*Function to free all allocated slab caches before exiting the module*/
124 static void icp_ocfDrvFreeCaches(void);
126 int32_t icp_ocfDrvDriverId
= INVALID_DRIVER_ID
;
128 /* Module parameter - gives the number of times LAC deregistration shall be
130 int num_dereg_retries
= DEFAULT_DEREG_RETRIES
;
132 /* Module parameter - gives the delay time in jiffies before a LAC session
133 shall be attempted to be deregistered again */
134 int dereg_retry_delay_in_jiffies
= DEFAULT_DEREG_DELAY_IN_JIFFIES
;
136 /* Module parameter - gives the maximum number of sessions possible between
137 OCF and the OCF EP80579 Driver. If set to zero, there is no limit.*/
138 int max_sessions
= DEFAULT_OCF_TO_DRV_MAX_SESSION_COUNT
;
140 /* This is set when the module is removed from the system, no further
141 processing can take place if this is set */
142 icp_atomic_t icp_ocfDrvIsExiting
= ICP_ATOMIC_INIT(0);
144 /* This is used to show how many lac sessions were not deregistered*/
145 icp_atomic_t lac_session_failed_dereg_count
= ICP_ATOMIC_INIT(0);
147 /* This is used to track the number of registered sessions between OCF and
148 * and the OCF EP80579 driver, when max_session is set to value other than
149 * zero. This ensures that the max_session set for the OCF and the driver
150 * is equal to the LAC registered sessions */
151 icp_atomic_t num_ocf_to_drv_registered_sessions
= ICP_ATOMIC_INIT(0);
153 /* Head of linked list used to store session data */
154 icp_drvSessionListHead_t icp_ocfDrvGlobalSymListHead
;
155 icp_drvSessionListHead_t icp_ocfDrvGlobalSymListHead_FreeMemList
;
157 icp_spinlock_t icp_ocfDrvSymSessInfoListSpinlock
;
159 /*Below pointer is only used in linux, FreeBSD uses the name to
160 create its own variable name*/
161 icp_workqueue
*icp_ocfDrvFreeLacSessionWorkQ
= NULL
;
162 ICP_WORKQUEUE_DEFINE_THREAD(icp_ocfDrvFreeLacSessionWorkQ
);
164 struct icp_drvBuffListInfo defBuffListInfo
;
166 /* Name : icp_ocfDrvInit
168 * Description : This function will register all the symmetric and asymmetric
169 * functionality that will be accelerated by the hardware. It will also
170 * get a unique driver ID from the OCF and initialise all slab caches
172 ICP_MODULE_INIT_FUNC(icp_ocfDrvInit
)
176 IPRINTK("=== %s ver %d.%d.%d ===\n", ICP_OCF_COMP_NAME
,
177 ICP_OCF_VER_MAIN
, ICP_OCF_VER_MJR
, ICP_OCF_VER_MNR
);
179 if (MAX_DEREG_RETRIES
< num_dereg_retries
) {
180 EPRINTK("Session deregistration retry count set to greater "
181 "than %d", MAX_DEREG_RETRIES
);
182 icp_module_return_code(EINVAL
);
185 /* Initialize and Start the Cryptographic component */
186 if (CPA_STATUS_SUCCESS
!=
187 cpaCyStartInstance(CPA_INSTANCE_HANDLE_SINGLE
)) {
188 EPRINTK("Failed to initialize and start the instance "
189 "of the Cryptographic component.\n");
190 return icp_module_return_code(EINVAL
);
193 icp_spin_lock_init(&icp_ocfDrvSymSessInfoListSpinlock
);
195 /* Set the default size of BufferList to allocate */
196 memset(&defBuffListInfo
, 0, sizeof(struct icp_drvBuffListInfo
));
197 if (ICP_OCF_DRV_STATUS_SUCCESS
!=
198 icp_ocfDrvBufferListMemInfo(ICP_OCF_DRV_DEFAULT_BUFFLIST_ARRAYS
,
200 EPRINTK("Failed to get bufferlist memory info.\n");
201 return icp_module_return_code(ENOMEM
);
204 /*Register OCF EP80579 Driver with OCF */
205 icp_ocfDrvDriverId
= ICP_CRYPTO_GET_DRIVERID();
207 if (icp_ocfDrvDriverId
< 0) {
208 EPRINTK("%s : ICP driver failed to register with OCF!\n",
210 return icp_module_return_code(ENODEV
);
213 /*Create all the slab caches used by the OCF EP80579 Driver */
214 drvSessionData_zone
=
215 ICP_CACHE_CREATE(ICP_SESSION_DATA_NAME
, struct icp_drvSessionData
);
218 * Allocation of the OpData includes the allocation space for meta data.
219 * The memory after the opData structure is reserved for this meta data.
222 icp_kmem_cache_create(ICP_OP_DATA_NAME
,
223 sizeof(struct icp_drvOpData
) +
224 defBuffListInfo
.metaSize
,
225 ICP_KERNEL_CACHE_ALIGN
,
226 ICP_KERNEL_CACHE_NOINIT
);
228 drvDH_zone
= ICP_CACHE_CREATE(ICP_DH_NAME
, CpaCyDhPhase1KeyGenOpData
);
231 ICP_CACHE_CREATE(ICP_MODEXP_NAME
, CpaCyLnModExpOpData
);
234 ICP_CACHE_CREATE(ICP_RSA_DECRYPT_NAME
, CpaCyRsaDecryptOpData
);
236 drvRSAPrivateKey_zone
=
237 ICP_CACHE_CREATE(ICP_RSA_PKEY_NAME
, CpaCyRsaPrivateKey
);
240 ICP_CACHE_CREATE(ICP_DSA_SIGN_NAME
, CpaCyDsaRSSignOpData
);
242 /*too awkward to use a macro here */
243 drvDSARSSignKValue_zone
=
244 ICP_CACHE_CREATE(ICP_RAND_VAL_NAME
,
245 DSA_RS_SIGN_PRIMEQ_SIZE_IN_BYTES
);
248 ICP_CACHE_CREATE(ICP_DSA_VER_NAME
, CpaCyDsaVerifyOpData
);
251 ICP_CACHE_CREATE(ICP_FLAT_BUFF_NAME
, CpaFlatBuffer
);
253 if (0 == icp_cache_null_check()) {
254 icp_ocfDrvFreeCaches();
255 EPRINTK("%s() line %d: Not enough memory!\n",
256 __FUNCTION__
, __LINE__
);
260 /* Register the ICP symmetric crypto support. */
261 ICP_REG_SYM_WITH_OCF(icp_ocfDrvDriverId
, CRYPTO_NULL_CBC
, ocfStatus
);
262 ICP_REG_SYM_WITH_OCF(icp_ocfDrvDriverId
, CRYPTO_DES_CBC
, ocfStatus
);
263 ICP_REG_SYM_WITH_OCF(icp_ocfDrvDriverId
, CRYPTO_3DES_CBC
, ocfStatus
);
264 ICP_REG_SYM_WITH_OCF(icp_ocfDrvDriverId
, CRYPTO_AES_CBC
, ocfStatus
);
265 ICP_REG_SYM_WITH_OCF(icp_ocfDrvDriverId
, CRYPTO_ARC4
, ocfStatus
);
266 ICP_REG_SYM_WITH_OCF(icp_ocfDrvDriverId
, CRYPTO_MD5
, ocfStatus
);
267 ICP_REG_SYM_WITH_OCF(icp_ocfDrvDriverId
, CRYPTO_MD5_HMAC
, ocfStatus
);
268 ICP_REG_SYM_WITH_OCF(icp_ocfDrvDriverId
, CRYPTO_SHA1
, ocfStatus
);
269 ICP_REG_SYM_WITH_OCF(icp_ocfDrvDriverId
, CRYPTO_SHA1_HMAC
, ocfStatus
);
270 ICP_REG_SYM_WITH_OCF(icp_ocfDrvDriverId
, CRYPTO_SHA2_256
, ocfStatus
);
271 ICP_REG_SYM_WITH_OCF(icp_ocfDrvDriverId
, CRYPTO_SHA2_256_HMAC
,
273 ICP_REG_SYM_WITH_OCF(icp_ocfDrvDriverId
, CRYPTO_SHA2_384
, ocfStatus
);
274 ICP_REG_SYM_WITH_OCF(icp_ocfDrvDriverId
, CRYPTO_SHA2_384_HMAC
,
276 ICP_REG_SYM_WITH_OCF(icp_ocfDrvDriverId
, CRYPTO_SHA2_512
, ocfStatus
);
277 ICP_REG_SYM_WITH_OCF(icp_ocfDrvDriverId
, CRYPTO_SHA2_512_HMAC
,
280 /* Register the ICP asymmetric algorithm support */
281 ICP_REG_ASYM_WITH_OCF(icp_ocfDrvDriverId
, CRK_DH_COMPUTE_KEY
,
283 ICP_REG_ASYM_WITH_OCF(icp_ocfDrvDriverId
, CRK_MOD_EXP
, ocfStatus
);
284 ICP_REG_ASYM_WITH_OCF(icp_ocfDrvDriverId
, CRK_MOD_EXP_CRT
, ocfStatus
);
285 ICP_REG_ASYM_WITH_OCF(icp_ocfDrvDriverId
, CRK_DSA_SIGN
, ocfStatus
);
286 ICP_REG_ASYM_WITH_OCF(icp_ocfDrvDriverId
, CRK_DSA_VERIFY
, ocfStatus
);
288 /* Register the ICP random number generator support */
289 ICP_REG_RAND_WITH_OCF(icp_ocfDrvDriverId
,
290 icp_ocfDrvReadRandom
, NULL
, ocfStatus
);
292 if (OCF_ZERO_FUNCTIONALITY_REGISTERED
== ocfStatus
) {
293 DPRINTK("%s: Failed to register any device capabilities\n",
295 icp_ocfDrvFreeCaches();
296 icp_ocfDrvDriverId
= INVALID_DRIVER_ID
;
297 return icp_module_return_code(ECANCELED
);
300 DPRINTK("%s: Registered %d of %d device capabilities\n",
301 __FUNCTION__
, ocfStatus
, NUM_SUPPORTED_CAPABILITIES
);
303 /*Session data linked list used during module exit */
304 ICP_INIT_LIST_HEAD(&icp_ocfDrvGlobalSymListHead
);
305 ICP_INIT_LIST_HEAD(&icp_ocfDrvGlobalSymListHead_FreeMemList
);
307 ICP_WORKQUEUE_CREATE(icp_ocfDrvFreeLacSessionWorkQ
, "icpwq");
308 if (ICP_WORKQUEUE_NULL_CHECK(icp_ocfDrvFreeLacSessionWorkQ
)) {
309 EPRINTK("%s: Failed to create single "
310 "thread workqueue\n", __FUNCTION__
);
311 icp_ocfDrvFreeCaches();
312 icp_ocfDrvDriverId
= INVALID_DRIVER_ID
;
313 return icp_module_return_code(ENOMEM
);
316 return icp_module_return_code(0);
319 /* Name : icp_ocfDrvExit
321 * Description : This function will deregister all the symmetric sessions
322 * registered with the LAC component. It will also deregister all symmetric
323 * and asymmetric functionality that can be accelerated by the hardware via OCF
324 * and random number generation if it is enabled.
326 ICP_MODULE_EXIT_FUNC(icp_ocfDrvExit
)
328 CpaStatus lacStatus
= CPA_STATUS_SUCCESS
;
329 struct icp_drvSessionData
*sessionData
= NULL
;
330 struct icp_drvSessionData
*tempSessionData
= NULL
;
331 int i
, remaining_delay_time_in_jiffies
= 0;
333 /* For FreeBSD the invariant macro below makes function to return */
334 /* with EBUSY value in the case of any session which has been regi- */
335 /* stered with LAC not being deregistered. */
336 /* The Linux implementation is empty since it is purely to compensate */
337 /* for a limitation of the FreeBSD 7.1 Opencrypto framework. */
339 ICP_MODULE_EXIT_INV();
341 /* There is a possibility of a process or new session command being */
342 /* sent before this variable is incremented. The aim of this variable */
343 /* is to stop a loop of calls creating a deadlock situation which */
344 /* would prevent the driver from exiting. */
345 icp_atomic_set(&icp_ocfDrvIsExiting
, 1);
347 /*Existing sessions will be routed to another driver after these calls */
348 crypto_unregister_all(icp_ocfDrvDriverId
);
349 crypto_runregister_all(icp_ocfDrvDriverId
);
351 if (ICP_WORKQUEUE_NULL_CHECK(icp_ocfDrvFreeLacSessionWorkQ
)) {
352 DPRINTK("%s: workqueue already "
353 "destroyed, therefore module exit "
354 " function already called. Exiting.\n", __FUNCTION__
);
355 return ICP_MODULE_EXIT_FUNC_RETURN_VAL
;
357 /*If any sessions are waiting to be deregistered, do that. This also
358 flushes the work queue */
359 ICP_WORKQUEUE_DESTROY(icp_ocfDrvFreeLacSessionWorkQ
);
361 /*ENTER CRITICAL SECTION */
362 icp_spin_lockbh_lock(&icp_ocfDrvSymSessInfoListSpinlock
);
364 ICP_LIST_FOR_EACH_ENTRY_SAFE(tempSessionData
, sessionData
,
365 &icp_ocfDrvGlobalSymListHead
, listNode
) {
366 for (i
= 0; i
< num_dereg_retries
; i
++) {
367 /*No harm if bad input - LAC will handle error cases */
368 if (ICP_SESSION_RUNNING
== tempSessionData
->inUse
) {
370 cpaCySymRemoveSession
371 (CPA_INSTANCE_HANDLE_SINGLE
,
372 tempSessionData
->sessHandle
);
373 if (CPA_STATUS_SUCCESS
== lacStatus
) {
374 /* Succesfully deregistered */
376 } else if (CPA_STATUS_RETRY
!= lacStatus
) {
378 (&lac_session_failed_dereg_count
);
382 /*schedule_timout returns the time left for completion if
383 * this task is set to TASK_INTERRUPTIBLE */
384 remaining_delay_time_in_jiffies
=
385 dereg_retry_delay_in_jiffies
;
386 while (0 > remaining_delay_time_in_jiffies
) {
387 remaining_delay_time_in_jiffies
=
389 (&icp_ocfDrvSymSessInfoListSpinlock
,
390 remaining_delay_time_in_jiffies
);
394 ("%s(): Retry %d to deregistrate the session\n",
399 /*remove from current list */
400 ICP_LIST_DEL(tempSessionData
, listNode
);
401 /*add to free mem linked list */
402 ICP_LIST_ADD(tempSessionData
,
403 &icp_ocfDrvGlobalSymListHead_FreeMemList
,
408 /*EXIT CRITICAL SECTION */
409 icp_spin_lockbh_unlock(&icp_ocfDrvSymSessInfoListSpinlock
);
411 /*set back to initial values */
413 /*still have a reference in our list! */
414 tempSessionData
= NULL
;
417 ICP_LIST_FOR_EACH_ENTRY_SAFE(tempSessionData
, sessionData
,
418 &icp_ocfDrvGlobalSymListHead_FreeMemList
,
421 ICP_LIST_DEL(tempSessionData
, listNode
);
422 /* Free allocated CpaCySymSessionCtx */
423 if (NULL
!= tempSessionData
->sessHandle
) {
424 icp_kfree(tempSessionData
->sessHandle
);
426 memset(tempSessionData
, 0, sizeof(struct icp_drvSessionData
));
427 ICP_CACHE_FREE(drvSessionData_zone
, tempSessionData
);
430 if (0 != icp_atomic_read(&lac_session_failed_dereg_count
)) {
431 DPRINTK("%s(): %d LAC sessions were not deregistered "
432 "correctly. This is not a clean exit! \n",
434 icp_atomic_read(&lac_session_failed_dereg_count
));
437 icp_ocfDrvFreeCaches();
438 icp_ocfDrvDriverId
= INVALID_DRIVER_ID
;
440 icp_spin_lock_destroy(&icp_ocfDrvSymSessInfoListSpinlock
);
442 /* Shutdown the Cryptographic component */
443 lacStatus
= cpaCyStopInstance(CPA_INSTANCE_HANDLE_SINGLE
);
444 if (CPA_STATUS_SUCCESS
!= lacStatus
) {
445 DPRINTK("%s(): Failed to stop instance of the "
446 "Cryptographic component.(status == %d)\n",
447 __FUNCTION__
, lacStatus
);
450 return ICP_MODULE_EXIT_FUNC_RETURN_VAL
;
453 /* Name : icp_ocfDrvFreeCaches
455 * Description : This function deregisters all slab caches
457 static void icp_ocfDrvFreeCaches(void)
459 icp_atomic_set(&icp_ocfDrvIsExiting
, 1);
462 ICP_CACHE_DESTROY(drvSessionData_zone
);
463 ICP_CACHE_DESTROY(drvOpData_zone
);
466 ICP_CACHE_DESTROY(drvDH_zone
);
467 ICP_CACHE_DESTROY(drvLnModExp_zone
);
468 ICP_CACHE_DESTROY(drvRSADecrypt_zone
);
469 ICP_CACHE_DESTROY(drvRSAPrivateKey_zone
);
470 ICP_CACHE_DESTROY(drvDSARSSignKValue_zone
);
471 ICP_CACHE_DESTROY(drvDSARSSign_zone
);
472 ICP_CACHE_DESTROY(drvDSAVerify_zone
);
474 /*FlatBuffer and BufferList Zones */
475 ICP_CACHE_DESTROY(drvFlatBuffer_zone
);
479 /* Name : icp_ocfDrvDeregRetry
481 * Description : This function will try to farm the session deregistration
482 * off to a work queue. If it fails, nothing more can be done and it
485 int icp_ocfDrvDeregRetry(CpaCySymSessionCtx sessionToDeregister
)
487 struct icp_ocfDrvFreeLacSession
*workstore
= NULL
;
489 DPRINTK("%s(): Retry - Deregistering session (%p)\n",
490 __FUNCTION__
, sessionToDeregister
);
492 /*make sure the session is not available to be allocated during this
494 icp_atomic_inc(&lac_session_failed_dereg_count
);
496 /*Farm off to work queue */
498 icp_kmalloc(sizeof(struct icp_ocfDrvFreeLacSession
), ICP_M_NOWAIT
);
499 if (NULL
== workstore
) {
500 DPRINTK("%s(): unable to free session - no memory available "
501 "for work queue\n", __FUNCTION__
);
505 workstore
->sessionToDeregister
= sessionToDeregister
;
507 icp_init_work(&(workstore
->work
),
508 icp_ocfDrvDeferedFreeLacSessionTaskFn
, workstore
);
510 ICP_WORKQUEUE_ENQUEUE(icp_ocfDrvFreeLacSessionWorkQ
,
513 return ICP_OCF_DRV_STATUS_SUCCESS
;
517 /* Name : icp_ocfDrvDeferedFreeLacSessionProcess
519 * Description : This function will retry (module input parameter)
520 * 'num_dereg_retries' times to deregister any symmetric session that recieves a
521 * CPA_STATUS_RETRY message from the LAC component. This function is run in
522 * Thread context because it is called from a worker thread
524 void icp_ocfDrvDeferedFreeLacSessionProcess(void *arg
)
526 struct icp_ocfDrvFreeLacSession
*workstore
= NULL
;
527 CpaCySymSessionCtx sessionToDeregister
= NULL
;
529 int remaining_delay_time_in_jiffies
= 0;
530 CpaStatus lacStatus
= CPA_STATUS_SUCCESS
;
532 workstore
= (struct icp_ocfDrvFreeLacSession
*)arg
;
533 if (NULL
== workstore
) {
534 DPRINTK("%s() function called with null parameter \n",
539 sessionToDeregister
= workstore
->sessionToDeregister
;
540 icp_kfree(workstore
);
542 /*if exiting, give deregistration one more blast only */
543 if (icp_atomic_read(&icp_ocfDrvIsExiting
) == CPA_TRUE
) {
544 lacStatus
= cpaCySymRemoveSession(CPA_INSTANCE_HANDLE_SINGLE
,
545 sessionToDeregister
);
547 if (lacStatus
!= CPA_STATUS_SUCCESS
) {
548 DPRINTK("%s() Failed to Dereg LAC session %p "
549 "during module exit\n", __FUNCTION__
,
550 sessionToDeregister
);
554 icp_atomic_dec(&lac_session_failed_dereg_count
);
558 for (i
= 0; i
<= num_dereg_retries
; i
++) {
559 lacStatus
= cpaCySymRemoveSession(CPA_INSTANCE_HANDLE_SINGLE
,
560 sessionToDeregister
);
562 if (lacStatus
== CPA_STATUS_SUCCESS
) {
563 icp_atomic_dec(&lac_session_failed_dereg_count
);
566 if (lacStatus
!= CPA_STATUS_RETRY
) {
567 DPRINTK("%s() Failed to deregister session - lacStatus "
568 " = %d", __FUNCTION__
, lacStatus
);
572 /*schedule_timout returns the time left for completion if this
573 task is set to TASK_INTERRUPTIBLE */
574 remaining_delay_time_in_jiffies
= dereg_retry_delay_in_jiffies
;
575 while (0 < remaining_delay_time_in_jiffies
) {
576 remaining_delay_time_in_jiffies
=
577 icp_schedule_timeout(NULL
,
578 remaining_delay_time_in_jiffies
);
583 DPRINTK("%s(): Unable to deregister session\n", __FUNCTION__
);
584 DPRINTK("%s(): Number of unavailable LAC sessions = %d\n", __FUNCTION__
,
585 icp_atomic_read(&lac_session_failed_dereg_count
));
588 /* Name : icp_ocfDrvPtrAndLenToFlatBuffer
590 * Description : This function converts a "pointer and length" buffer
591 * structure to Fredericksburg Flat Buffer (CpaFlatBuffer) format.
593 * This function assumes that the data passed in are valid.
596 icp_ocfDrvPtrAndLenToFlatBuffer(void *pData
, uint32_t len
,
597 CpaFlatBuffer
* pFlatBuffer
)
599 pFlatBuffer
->pData
= pData
;
600 pFlatBuffer
->dataLenInBytes
= len
;
603 /* Name : icp_ocfDrvPtrAndLenToBufferList
605 * Description : This function converts a "pointer and length" buffer
606 * structure to Fredericksburg Scatter/Gather Buffer (CpaBufferList) format.
608 * This function assumes that the data passed in are valid.
611 icp_ocfDrvPtrAndLenToBufferList(void *pDataIn
, uint32_t length
,
612 CpaBufferList
* pBufferList
)
614 pBufferList
->numBuffers
= 1;
615 pBufferList
->pBuffers
->pData
= pDataIn
;
616 pBufferList
->pBuffers
->dataLenInBytes
= length
;
619 /* Name : icp_ocfDrvBufferListToPtrAndLen
621 * Description : This function converts Fredericksburg Scatter/Gather Buffer
622 * (CpaBufferList) format to a "pointer and length" buffer structure.
624 * This function assumes that the data passed in are valid.
627 icp_ocfDrvBufferListToPtrAndLen(CpaBufferList
* pBufferList
,
628 void **ppDataOut
, uint32_t * pLength
)
630 *ppDataOut
= pBufferList
->pBuffers
->pData
;
631 *pLength
= pBufferList
->pBuffers
->dataLenInBytes
;
634 /* Name : icp_ocfDrvBufferListMemInfo
636 * Description : This function will set the number of flat buffers in
637 * bufferlist, the size of memory to allocate for the pPrivateMetaData
638 * member of the CpaBufferList.
641 icp_ocfDrvBufferListMemInfo(uint16_t numBuffers
,
642 struct icp_drvBuffListInfo
*buffListInfo
)
644 buffListInfo
->numBuffers
= numBuffers
;
646 if (CPA_STATUS_SUCCESS
!=
647 cpaCyBufferListGetMetaSize(CPA_INSTANCE_HANDLE_SINGLE
,
648 buffListInfo
->numBuffers
,
649 &(buffListInfo
->metaSize
))) {
650 EPRINTK("%s() Failed to get buffer list meta size.\n",
652 return ICP_OCF_DRV_STATUS_FAIL
;
655 return ICP_OCF_DRV_STATUS_SUCCESS
;
658 /* Name : icp_ocfDrvFreeFlatBuffer
660 * Description : This function will deallocate flat buffer.
662 inline void icp_ocfDrvFreeFlatBuffer(CpaFlatBuffer
* pFlatBuffer
)
664 if (pFlatBuffer
!= NULL
) {
665 memset(pFlatBuffer
, 0, sizeof(CpaFlatBuffer
));
666 ICP_CACHE_FREE(drvFlatBuffer_zone
, pFlatBuffer
);
670 /* Name : icp_ocfDrvAllocMetaData
672 * Description : This function will allocate memory for the
673 * pPrivateMetaData member of CpaBufferList.
676 icp_ocfDrvAllocMetaData(CpaBufferList
* pBufferList
,
677 struct icp_drvOpData
*pOpData
)
681 if (pBufferList
->numBuffers
<= ICP_OCF_DRV_DEFAULT_BUFFLIST_ARRAYS
) {
682 uint8_t *pOpDataStartAddr
= (uint8_t *) pOpData
;
684 if (0 == defBuffListInfo
.metaSize
) {
685 pBufferList
->pPrivateMetaData
= NULL
;
686 return ICP_OCF_DRV_STATUS_SUCCESS
;
689 * The meta data allocation has been included as part of the
690 * op data. It has been pre-allocated in memory just after the
691 * icp_drvOpData structure.
693 pBufferList
->pPrivateMetaData
= (void *)(pOpDataStartAddr
+
697 if (CPA_STATUS_SUCCESS
!=
698 cpaCyBufferListGetMetaSize(CPA_INSTANCE_HANDLE_SINGLE
,
699 pBufferList
->numBuffers
,
701 EPRINTK("%s() Failed to get buffer list meta size.\n",
703 return ICP_OCF_DRV_STATUS_FAIL
;
707 pBufferList
->pPrivateMetaData
= NULL
;
708 return ICP_OCF_DRV_STATUS_SUCCESS
;
711 pBufferList
->pPrivateMetaData
=
712 icp_kmalloc(metaSize
, ICP_M_NOWAIT
);
714 if (NULL
== pBufferList
->pPrivateMetaData
) {
715 EPRINTK("%s() Failed to allocate pPrivateMetaData.\n",
717 return ICP_OCF_DRV_STATUS_FAIL
;
720 return ICP_OCF_DRV_STATUS_SUCCESS
;
723 /* Name : icp_ocfDrvFreeMetaData
725 * Description : This function will deallocate pPrivateMetaData memory.
727 inline void icp_ocfDrvFreeMetaData(CpaBufferList
* pBufferList
)
729 if (NULL
== pBufferList
->pPrivateMetaData
) {
734 * Only free the meta data if the BufferList has more than
735 * ICP_OCF_DRV_DEFAULT_BUFFLIST_ARRAYS number of buffers.
736 * Otherwise, the meta data shall be freed when the icp_drvOpData is
739 if (ICP_OCF_DRV_DEFAULT_BUFFLIST_ARRAYS
< pBufferList
->numBuffers
) {
740 icp_kfree(pBufferList
->pPrivateMetaData
);
744 /* Module declaration, init and exit functions */
745 ICP_DECLARE_MODULE(icp_ocf
, icp_ocfDrvInit
, icp_ocfDrvExit
);
746 ICP_MODULE_DESCRIPTION("OCF Driver for Intel Quick Assist crypto acceleration");
747 ICP_MODULE_VERSION(icp_ocf
, ICP_OCF_VER_MJR
);
748 ICP_MODULE_LICENSE("Dual BSD/GPL");
749 ICP_MODULE_AUTHOR("Intel");
751 /* Module parameters */
752 ICP_MODULE_PARAM_INT(icp_ocf
, num_dereg_retries
,
753 "Number of times to retry LAC Sym Session Deregistration. "
754 "Default 10, Max 100");
755 ICP_MODULE_PARAM_INT(icp_ocf
, dereg_retry_delay_in_jiffies
, "Delay in jiffies "
756 "(added to a schedule() function call) before a LAC Sym "
757 "Session Dereg is retried. Default 10");
758 ICP_MODULE_PARAM_INT(icp_ocf
, max_sessions
,
759 "This sets the maximum number of sessions "
760 "between OCF and this driver. If this value is set to zero,"
761 "max session count checking is disabled. Default is zero(0)");
763 /* Module dependencies */
764 #define MODULE_MIN_VER 1
765 #define CRYPTO_MAX_VER 3
766 #define LAC_MAX_VER 2
768 ICP_MODULE_DEPEND(icp_ocf
, crypto
, MODULE_MIN_VER
, MODULE_MIN_VER
,
770 ICP_MODULE_DEPEND(icp_ocf
, cryptodev
, MODULE_MIN_VER
, MODULE_MIN_VER
,
772 ICP_MODULE_DEPEND(icp_ocf
, icp_crypto
, MODULE_MIN_VER
, MODULE_MIN_VER
,