remove linux 2.4 specific build system code
[15.05/openwrt.git] / target / linux / generic-2.6 / files / crypto / ocf / ep80579 / icp_common.c
1 /*************************************************************************
2  *
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.
5  * 
6  *   GPL LICENSE SUMMARY
7  * 
8  *   Copyright(c) 2007,2008,2009 Intel Corporation. All rights reserved.
9  * 
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.
13  * 
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.
18  * 
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.
24  * 
25  *   Contact Information:
26  *   Intel Corporation
27  * 
28  *   BSD LICENSE 
29  * 
30  *   Copyright(c) 2007,2008,2009 Intel Corporation. All rights reserved.
31  *   All rights reserved.
32  * 
33  *   Redistribution and use in source and binary forms, with or without 
34  *   modification, are permitted provided that the following conditions 
35  *   are met:
36  * 
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 
42  *       distribution.
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.
46  * 
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.
58  * 
59  * 
60  *  version: Security.L.1.0.2-229
61  *
62  ***************************************************************************/
63
64 /*
65  * An OCF module that uses IntelĀ® QuickAssist Integrated Accelerator to do the 
66  * crypto.
67  *
68  * This driver requires the ICP Access Library that is available from Intel in
69  * order to operate.
70  */
71
72 #include "icp_ocf.h"
73
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)
78
79 #define MAX_DEREG_RETRIES                       (100)
80 #define DEFAULT_DEREG_RETRIES                   (10)
81 #define DEFAULT_DEREG_DELAY_IN_JIFFIES          (10)
82
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)
87
88 /*Slab zone names*/
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"
99
100 /*Slabs zones*/
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;
110
111 /*Slab zones for flatbuffers and bufferlist*/
112 icp_kmem_cache drvFlatBuffer_zone = NULL;
113
114 static inline int icp_cache_null_check(void)
115 {
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);
121 }
122
123 /*Function to free all allocated slab caches before exiting the module*/
124 static void icp_ocfDrvFreeCaches(void);
125
126 int32_t icp_ocfDrvDriverId = INVALID_DRIVER_ID;
127
128 /* Module parameter - gives the number of times LAC deregistration shall be
129    re-tried */
130 int num_dereg_retries = DEFAULT_DEREG_RETRIES;
131
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;
135
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;
139
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);
143
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);
146
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);
152
153 /* Head of linked list used to store session data */
154 icp_drvSessionListHead_t icp_ocfDrvGlobalSymListHead;
155 icp_drvSessionListHead_t icp_ocfDrvGlobalSymListHead_FreeMemList;
156
157 icp_spinlock_t icp_ocfDrvSymSessInfoListSpinlock;
158
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);
163
164 struct icp_drvBuffListInfo defBuffListInfo;
165
166 /* Name        : icp_ocfDrvInit
167  *
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
171  */
172 ICP_MODULE_INIT_FUNC(icp_ocfDrvInit)
173 {
174         int ocfStatus = 0;
175
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);
178
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);
183         }
184
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);
191         }
192
193         icp_spin_lock_init(&icp_ocfDrvSymSessInfoListSpinlock);
194
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,
199                                         &defBuffListInfo)) {
200                 EPRINTK("Failed to get bufferlist memory info.\n");
201                 return icp_module_return_code(ENOMEM);
202         }
203
204         /*Register OCF EP80579 Driver with OCF */
205         icp_ocfDrvDriverId = ICP_CRYPTO_GET_DRIVERID();
206
207         if (icp_ocfDrvDriverId < 0) {
208                 EPRINTK("%s : ICP driver failed to register with OCF!\n",
209                         __FUNCTION__);
210                 return icp_module_return_code(ENODEV);
211         }
212
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);
216
217         /* 
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.
220          */
221         drvOpData_zone =
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);
227
228         drvDH_zone = ICP_CACHE_CREATE(ICP_DH_NAME, CpaCyDhPhase1KeyGenOpData);
229
230         drvLnModExp_zone =
231             ICP_CACHE_CREATE(ICP_MODEXP_NAME, CpaCyLnModExpOpData);
232
233         drvRSADecrypt_zone =
234             ICP_CACHE_CREATE(ICP_RSA_DECRYPT_NAME, CpaCyRsaDecryptOpData);
235
236         drvRSAPrivateKey_zone =
237             ICP_CACHE_CREATE(ICP_RSA_PKEY_NAME, CpaCyRsaPrivateKey);
238
239         drvDSARSSign_zone =
240             ICP_CACHE_CREATE(ICP_DSA_SIGN_NAME, CpaCyDsaRSSignOpData);
241
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);
246
247         drvDSAVerify_zone =
248             ICP_CACHE_CREATE(ICP_DSA_VER_NAME, CpaCyDsaVerifyOpData);
249
250         drvFlatBuffer_zone =
251             ICP_CACHE_CREATE(ICP_FLAT_BUFF_NAME, CpaFlatBuffer);
252
253         if (0 == icp_cache_null_check()) {
254                 icp_ocfDrvFreeCaches();
255                 EPRINTK("%s() line %d: Not enough memory!\n",
256                         __FUNCTION__, __LINE__);
257                 return ENOMEM;
258         }
259
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,
272                              ocfStatus);
273         ICP_REG_SYM_WITH_OCF(icp_ocfDrvDriverId, CRYPTO_SHA2_384, ocfStatus);
274         ICP_REG_SYM_WITH_OCF(icp_ocfDrvDriverId, CRYPTO_SHA2_384_HMAC,
275                              ocfStatus);
276         ICP_REG_SYM_WITH_OCF(icp_ocfDrvDriverId, CRYPTO_SHA2_512, ocfStatus);
277         ICP_REG_SYM_WITH_OCF(icp_ocfDrvDriverId, CRYPTO_SHA2_512_HMAC,
278                              ocfStatus);
279
280         /* Register the ICP asymmetric algorithm support */
281         ICP_REG_ASYM_WITH_OCF(icp_ocfDrvDriverId, CRK_DH_COMPUTE_KEY,
282                               ocfStatus);
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);
287
288         /* Register the ICP random number generator support */
289         ICP_REG_RAND_WITH_OCF(icp_ocfDrvDriverId,
290                               icp_ocfDrvReadRandom, NULL, ocfStatus);
291
292         if (OCF_ZERO_FUNCTIONALITY_REGISTERED == ocfStatus) {
293                 DPRINTK("%s: Failed to register any device capabilities\n",
294                         __FUNCTION__);
295                 icp_ocfDrvFreeCaches();
296                 icp_ocfDrvDriverId = INVALID_DRIVER_ID;
297                 return icp_module_return_code(ECANCELED);
298         }
299
300         DPRINTK("%s: Registered %d of %d device capabilities\n",
301                 __FUNCTION__, ocfStatus, NUM_SUPPORTED_CAPABILITIES);
302
303         /*Session data linked list used during module exit */
304         ICP_INIT_LIST_HEAD(&icp_ocfDrvGlobalSymListHead);
305         ICP_INIT_LIST_HEAD(&icp_ocfDrvGlobalSymListHead_FreeMemList);
306
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);
314         }
315
316         return icp_module_return_code(0);
317 }
318
319 /* Name        : icp_ocfDrvExit
320  *
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.
325  */
326 ICP_MODULE_EXIT_FUNC(icp_ocfDrvExit)
327 {
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;
332
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.          */
338
339     ICP_MODULE_EXIT_INV();
340
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);
346
347         /*Existing sessions will be routed to another driver after these calls */
348         crypto_unregister_all(icp_ocfDrvDriverId);
349         crypto_runregister_all(icp_ocfDrvDriverId);
350
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;
356         }
357         /*If any sessions are waiting to be deregistered, do that. This also 
358            flushes the work queue */
359         ICP_WORKQUEUE_DESTROY(icp_ocfDrvFreeLacSessionWorkQ);
360
361         /*ENTER CRITICAL SECTION */
362         icp_spin_lockbh_lock(&icp_ocfDrvSymSessInfoListSpinlock);
363
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) {
369                                 lacStatus =
370                                     cpaCySymRemoveSession
371                                     (CPA_INSTANCE_HANDLE_SINGLE,
372                                      tempSessionData->sessHandle);
373                                 if (CPA_STATUS_SUCCESS == lacStatus) {
374                                         /* Succesfully deregistered */
375                                         break;
376                                 } else if (CPA_STATUS_RETRY != lacStatus) {
377                                         icp_atomic_inc
378                                             (&lac_session_failed_dereg_count);
379                                         break;
380                                 }
381
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 =
388                                             icp_schedule_timeout
389                                             (&icp_ocfDrvSymSessInfoListSpinlock,
390                                              remaining_delay_time_in_jiffies);
391                                 }
392
393                                 DPRINTK
394                                     ("%s(): Retry %d to deregistrate the session\n",
395                                      __FUNCTION__, i);
396                         }
397                 }
398
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,
404                              listNode);
405
406         }
407
408         /*EXIT CRITICAL SECTION */
409         icp_spin_lockbh_unlock(&icp_ocfDrvSymSessInfoListSpinlock);
410
411         /*set back to initial values */
412         sessionData = NULL;
413         /*still have a reference in our list! */
414         tempSessionData = NULL;
415         /*free memory */
416
417         ICP_LIST_FOR_EACH_ENTRY_SAFE(tempSessionData, sessionData,
418                                      &icp_ocfDrvGlobalSymListHead_FreeMemList,
419                                      listNode) {
420
421                 ICP_LIST_DEL(tempSessionData, listNode);
422                 /* Free allocated CpaCySymSessionCtx */
423                 if (NULL != tempSessionData->sessHandle) {
424                         icp_kfree(tempSessionData->sessHandle);
425                 }
426                 memset(tempSessionData, 0, sizeof(struct icp_drvSessionData));
427                 ICP_CACHE_FREE(drvSessionData_zone, tempSessionData);
428         }
429
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",
433                         __FUNCTION__,
434                         icp_atomic_read(&lac_session_failed_dereg_count));
435         }
436
437         icp_ocfDrvFreeCaches();
438         icp_ocfDrvDriverId = INVALID_DRIVER_ID;
439
440         icp_spin_lock_destroy(&icp_ocfDrvSymSessInfoListSpinlock);
441
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);
448         }
449
450         return ICP_MODULE_EXIT_FUNC_RETURN_VAL;
451 }
452
453 /* Name        : icp_ocfDrvFreeCaches
454  *
455  * Description : This function deregisters all slab caches
456  */
457 static void icp_ocfDrvFreeCaches(void)
458 {
459         icp_atomic_set(&icp_ocfDrvIsExiting, 1);
460
461         /*Sym Zones */
462         ICP_CACHE_DESTROY(drvSessionData_zone);
463         ICP_CACHE_DESTROY(drvOpData_zone);
464
465         /*Asym zones */
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);
473
474         /*FlatBuffer and BufferList Zones */
475         ICP_CACHE_DESTROY(drvFlatBuffer_zone);
476
477 }
478
479 /* Name        : icp_ocfDrvDeregRetry
480  *
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
483  * returns an error
484  */
485 int icp_ocfDrvDeregRetry(CpaCySymSessionCtx sessionToDeregister)
486 {
487         struct icp_ocfDrvFreeLacSession *workstore = NULL;
488
489         DPRINTK("%s(): Retry - Deregistering session (%p)\n",
490                 __FUNCTION__, sessionToDeregister);
491
492         /*make sure the session is not available to be allocated during this
493            process */
494         icp_atomic_inc(&lac_session_failed_dereg_count);
495
496         /*Farm off to work queue */
497         workstore =
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__);
502                 return ENOMEM;
503         }
504
505         workstore->sessionToDeregister = sessionToDeregister;
506
507         icp_init_work(&(workstore->work),
508                       icp_ocfDrvDeferedFreeLacSessionTaskFn, workstore);
509
510         ICP_WORKQUEUE_ENQUEUE(icp_ocfDrvFreeLacSessionWorkQ,
511                               &(workstore->work));
512
513         return ICP_OCF_DRV_STATUS_SUCCESS;
514
515 }
516
517 /* Name        : icp_ocfDrvDeferedFreeLacSessionProcess
518  *
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
523  */
524 void icp_ocfDrvDeferedFreeLacSessionProcess(void *arg)
525 {
526         struct icp_ocfDrvFreeLacSession *workstore = NULL;
527         CpaCySymSessionCtx sessionToDeregister = NULL;
528         int i = 0;
529         int remaining_delay_time_in_jiffies = 0;
530         CpaStatus lacStatus = CPA_STATUS_SUCCESS;
531
532         workstore = (struct icp_ocfDrvFreeLacSession *)arg;
533         if (NULL == workstore) {
534                 DPRINTK("%s() function called with null parameter \n",
535                         __FUNCTION__);
536                 return;
537         }
538
539         sessionToDeregister = workstore->sessionToDeregister;
540         icp_kfree(workstore);
541
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);
546
547                 if (lacStatus != CPA_STATUS_SUCCESS) {
548                         DPRINTK("%s() Failed to Dereg LAC session %p "
549                                 "during module exit\n", __FUNCTION__,
550                                 sessionToDeregister);
551                         return;
552                 }
553
554                 icp_atomic_dec(&lac_session_failed_dereg_count);
555                 return;
556         }
557
558         for (i = 0; i <= num_dereg_retries; i++) {
559                 lacStatus = cpaCySymRemoveSession(CPA_INSTANCE_HANDLE_SINGLE,
560                                                   sessionToDeregister);
561
562                 if (lacStatus == CPA_STATUS_SUCCESS) {
563                         icp_atomic_dec(&lac_session_failed_dereg_count);
564                         return;
565                 }
566                 if (lacStatus != CPA_STATUS_RETRY) {
567                         DPRINTK("%s() Failed to deregister session - lacStatus "
568                                 " = %d", __FUNCTION__, lacStatus);
569                         break;
570                 }
571
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);
579                 }
580
581         }
582
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));
586 }
587
588 /* Name        : icp_ocfDrvPtrAndLenToFlatBuffer 
589  *
590  * Description : This function converts a "pointer and length" buffer 
591  * structure to Fredericksburg Flat Buffer (CpaFlatBuffer) format.
592  *
593  * This function assumes that the data passed in are valid.
594  */
595 inline void
596 icp_ocfDrvPtrAndLenToFlatBuffer(void *pData, uint32_t len,
597                                 CpaFlatBuffer * pFlatBuffer)
598 {
599         pFlatBuffer->pData = pData;
600         pFlatBuffer->dataLenInBytes = len;
601 }
602
603 /* Name        : icp_ocfDrvPtrAndLenToBufferList
604  *
605  * Description : This function converts a "pointer and length" buffer
606  * structure to Fredericksburg Scatter/Gather Buffer (CpaBufferList) format.
607  *
608  * This function assumes that the data passed in are valid.
609  */
610 inline void
611 icp_ocfDrvPtrAndLenToBufferList(void *pDataIn, uint32_t length,
612                                 CpaBufferList * pBufferList)
613 {
614         pBufferList->numBuffers = 1;
615         pBufferList->pBuffers->pData = pDataIn;
616         pBufferList->pBuffers->dataLenInBytes = length;
617 }
618
619 /* Name        : icp_ocfDrvBufferListToPtrAndLen
620  *
621  * Description : This function converts Fredericksburg Scatter/Gather Buffer
622  * (CpaBufferList) format to a "pointer and length" buffer structure.
623  *
624  * This function assumes that the data passed in are valid.
625  */
626 inline void
627 icp_ocfDrvBufferListToPtrAndLen(CpaBufferList * pBufferList,
628                                 void **ppDataOut, uint32_t * pLength)
629 {
630         *ppDataOut = pBufferList->pBuffers->pData;
631         *pLength = pBufferList->pBuffers->dataLenInBytes;
632 }
633
634 /* Name        : icp_ocfDrvBufferListMemInfo
635  *
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.
639  */
640 int
641 icp_ocfDrvBufferListMemInfo(uint16_t numBuffers,
642                             struct icp_drvBuffListInfo *buffListInfo)
643 {
644         buffListInfo->numBuffers = numBuffers;
645
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",
651                         __FUNCTION__);
652                 return ICP_OCF_DRV_STATUS_FAIL;
653         }
654
655         return ICP_OCF_DRV_STATUS_SUCCESS;
656 }
657
658 /* Name        : icp_ocfDrvFreeFlatBuffer
659  *
660  * Description : This function will deallocate flat buffer.
661  */
662 inline void icp_ocfDrvFreeFlatBuffer(CpaFlatBuffer * pFlatBuffer)
663 {
664         if (pFlatBuffer != NULL) {
665                 memset(pFlatBuffer, 0, sizeof(CpaFlatBuffer));
666                 ICP_CACHE_FREE(drvFlatBuffer_zone, pFlatBuffer);
667         }
668 }
669
670 /* Name        : icp_ocfDrvAllocMetaData
671  *
672  * Description : This function will allocate memory for the
673  * pPrivateMetaData member of CpaBufferList.
674  */
675 inline int
676 icp_ocfDrvAllocMetaData(CpaBufferList * pBufferList,
677                         struct icp_drvOpData *pOpData)
678 {
679         Cpa32U metaSize = 0;
680
681         if (pBufferList->numBuffers <= ICP_OCF_DRV_DEFAULT_BUFFLIST_ARRAYS) {
682                 uint8_t *pOpDataStartAddr = (uint8_t *) pOpData;
683
684                 if (0 == defBuffListInfo.metaSize) {
685                         pBufferList->pPrivateMetaData = NULL;
686                         return ICP_OCF_DRV_STATUS_SUCCESS;
687                 }
688                 /*
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.
692                  */
693                 pBufferList->pPrivateMetaData = (void *)(pOpDataStartAddr +
694                                                          sizeof(struct
695                                                                 icp_drvOpData));
696         } else {
697                 if (CPA_STATUS_SUCCESS !=
698                     cpaCyBufferListGetMetaSize(CPA_INSTANCE_HANDLE_SINGLE,
699                                                pBufferList->numBuffers,
700                                                &metaSize)) {
701                         EPRINTK("%s() Failed to get buffer list meta size.\n",
702                                 __FUNCTION__);
703                         return ICP_OCF_DRV_STATUS_FAIL;
704                 }
705
706                 if (0 == metaSize) {
707                         pBufferList->pPrivateMetaData = NULL;
708                         return ICP_OCF_DRV_STATUS_SUCCESS;
709                 }
710
711                 pBufferList->pPrivateMetaData =
712                     icp_kmalloc(metaSize, ICP_M_NOWAIT);
713         }
714         if (NULL == pBufferList->pPrivateMetaData) {
715                 EPRINTK("%s() Failed to allocate pPrivateMetaData.\n",
716                         __FUNCTION__);
717                 return ICP_OCF_DRV_STATUS_FAIL;
718         }
719
720         return ICP_OCF_DRV_STATUS_SUCCESS;
721 }
722
723 /* Name        : icp_ocfDrvFreeMetaData
724  *
725  * Description : This function will deallocate pPrivateMetaData memory.
726  */
727 inline void icp_ocfDrvFreeMetaData(CpaBufferList * pBufferList)
728 {
729         if (NULL == pBufferList->pPrivateMetaData) {
730                 return;
731         }
732
733         /*
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
737          * freed.
738          */
739         if (ICP_OCF_DRV_DEFAULT_BUFFLIST_ARRAYS < pBufferList->numBuffers) {
740                 icp_kfree(pBufferList->pPrivateMetaData);
741         }
742 }
743
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");
750
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)");
762
763 /* Module dependencies */
764 #define MODULE_MIN_VER  1
765 #define CRYPTO_MAX_VER  3
766 #define LAC_MAX_VER     2
767
768 ICP_MODULE_DEPEND(icp_ocf, crypto, MODULE_MIN_VER, MODULE_MIN_VER,
769                   CRYPTO_MAX_VER);
770 ICP_MODULE_DEPEND(icp_ocf, cryptodev, MODULE_MIN_VER, MODULE_MIN_VER,
771                   CRYPTO_MAX_VER);
772 ICP_MODULE_DEPEND(icp_ocf, icp_crypto, MODULE_MIN_VER, MODULE_MIN_VER,
773                   LAC_MAX_VER);