[kernel] ocf: move all stuff into files, and fix build error on .25
[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 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 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.130
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                         (0)
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 Tolapai 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 /*Slabs zones*/
89 struct kmem_cache *drvSessionData_zone = NULL;
90 struct kmem_cache *drvOpData_zone = NULL;
91 struct kmem_cache *drvDH_zone = NULL;
92 struct kmem_cache *drvLnModExp_zone = NULL;
93 struct kmem_cache *drvRSADecrypt_zone = NULL;
94 struct kmem_cache *drvRSAPrivateKey_zone = NULL;
95 struct kmem_cache *drvDSARSSign_zone = NULL;
96 struct kmem_cache *drvDSARSSignKValue_zone = NULL;
97 struct kmem_cache *drvDSAVerify_zone = NULL;
98
99 /*Slab zones for flatbuffers and bufferlist*/
100 struct kmem_cache *drvFlatBuffer_zone = NULL;
101
102 static int icp_ocfDrvInit(void);
103 static void icp_ocfDrvExit(void);
104 static void icp_ocfDrvFreeCaches(void);
105 static void icp_ocfDrvDeferedFreeLacSessionProcess(void *arg);
106
107 int32_t icp_ocfDrvDriverId = INVALID_DRIVER_ID;
108
109 /* Module parameter - gives the number of times LAC deregistration shall be
110    re-tried */
111 int num_dereg_retries = DEFAULT_DEREG_RETRIES;
112
113 /* Module parameter - gives the delay time in jiffies before a LAC session 
114    shall be attempted to be deregistered again */
115 int dereg_retry_delay_in_jiffies = DEFAULT_DEREG_DELAY_IN_JIFFIES;
116
117 /* Module parameter - gives the maximum number of sessions possible between
118    OCF and the OCF Tolapai Driver. If set to zero, there is no limit.*/
119 int max_sessions = DEFAULT_OCF_TO_DRV_MAX_SESSION_COUNT;
120
121 /* This is set when the module is removed from the system, no further
122    processing can take place if this is set */
123 atomic_t icp_ocfDrvIsExiting = ATOMIC_INIT(0);
124
125 /* This is used to show how many lac sessions were not deregistered*/
126 atomic_t lac_session_failed_dereg_count = ATOMIC_INIT(0);
127
128 /* This is used to track the number of registered sessions between OCF and
129  * and the OCF Tolapai driver, when max_session is set to value other than
130  * zero. This ensures that the max_session set for the OCF and the driver
131  * is equal to the LAC registered sessions */
132 atomic_t num_ocf_to_drv_registered_sessions = ATOMIC_INIT(0);
133
134 /* Head of linked list used to store session data */
135 struct list_head icp_ocfDrvGlobalSymListHead;
136 struct list_head icp_ocfDrvGlobalSymListHead_FreeMemList;
137
138 spinlock_t icp_ocfDrvSymSessInfoListSpinlock = SPIN_LOCK_UNLOCKED;
139 rwlock_t icp_kmem_cache_destroy_alloc_lock = RW_LOCK_UNLOCKED;
140
141 struct workqueue_struct *icp_ocfDrvFreeLacSessionWorkQ;
142
143 struct icp_drvBuffListInfo defBuffListInfo;
144
145 static struct {
146         softc_device_decl sc_dev;
147 } icpDev;
148
149 static device_method_t icp_methods = {
150         /* crypto device methods */
151         DEVMETHOD(cryptodev_newsession, icp_ocfDrvNewSession),
152         DEVMETHOD(cryptodev_freesession, icp_ocfDrvFreeLACSession),
153         DEVMETHOD(cryptodev_process, icp_ocfDrvSymProcess),
154         DEVMETHOD(cryptodev_kprocess, icp_ocfDrvPkeProcess),
155 };
156
157 module_param(num_dereg_retries, int, S_IRUGO);
158 module_param(dereg_retry_delay_in_jiffies, int, S_IRUGO);
159 module_param(max_sessions, int, S_IRUGO);
160
161 MODULE_PARM_DESC(num_dereg_retries,
162                  "Number of times to retry LAC Sym Session Deregistration. "
163                  "Default 10, Max 100");
164 MODULE_PARM_DESC(dereg_retry_delay_in_jiffies, "Delay in jiffies "
165                  "(added to a schedule() function call) before a LAC Sym "
166                  "Session Dereg is retried. Default 10");
167 MODULE_PARM_DESC(max_sessions, "This sets the maximum number of sessions "
168                  "between OCF and this driver. If this value is set to zero, "
169                  "max session count checking is disabled. Default is zero(0)");
170
171 /* Name        : icp_ocfDrvInit
172  *
173  * Description : This function will register all the symmetric and asymmetric
174  * functionality that will be accelerated by the hardware. It will also
175  * get a unique driver ID from the OCF and initialise all slab caches
176  */
177 static int __init icp_ocfDrvInit(void)
178 {
179         int ocfStatus = 0;
180
181         IPRINTK("=== %s ver %d.%d.%d ===\n", ICP_OCF_COMP_NAME,
182                 ICP_OCF_VER_MAIN, ICP_OCF_VER_MJR, ICP_OCF_VER_MNR);
183
184         if (MAX_DEREG_RETRIES < num_dereg_retries) {
185                 EPRINTK("Session deregistration retry count set to greater "
186                         "than %d", MAX_DEREG_RETRIES);
187                 return -1;
188         }
189
190         /* Initialize and Start the Cryptographic component */
191         if (CPA_STATUS_SUCCESS !=
192             cpaCyStartInstance(CPA_INSTANCE_HANDLE_SINGLE)) {
193                 EPRINTK("Failed to initialize and start the instance "
194                         "of the Cryptographic component.\n");
195                 return -1;
196         }
197
198         /* Set the default size of BufferList to allocate */
199         memset(&defBuffListInfo, 0, sizeof(struct icp_drvBuffListInfo));
200         if (ICP_OCF_DRV_STATUS_SUCCESS !=
201             icp_ocfDrvBufferListMemInfo(ICP_OCF_DRV_DEFAULT_BUFFLIST_ARRAYS,
202                                         &defBuffListInfo)) {
203                 EPRINTK("Failed to get bufferlist memory info.\n");
204                 return -1;
205         }
206
207         /*Register OCF Tolapai Driver with OCF */
208         memset(&icpDev, 0, sizeof(icpDev));
209         softc_device_init(&icpDev, "icp", 0, icp_methods);
210
211         icp_ocfDrvDriverId = crypto_get_driverid(softc_get_device(&icpDev),
212                                                  CRYPTOCAP_F_HARDWARE);
213
214         if (icp_ocfDrvDriverId < 0) {
215                 EPRINTK("%s : ICP driver failed to register with OCF!\n",
216                         __FUNCTION__);
217                 return -ENODEV;
218         }
219
220         /*Create all the slab caches used by the OCF Tolapai Driver */
221         drvSessionData_zone =
222             ICP_CACHE_CREATE("ICP Session Data", struct icp_drvSessionData);
223         ICP_CACHE_NULL_CHECK(drvSessionData_zone);
224
225         /* 
226          * Allocation of the OpData includes the allocation space for meta data.
227          * The memory after the opData structure is reserved for this meta data.
228          */
229         drvOpData_zone =
230             kmem_cache_create("ICP Op Data", sizeof(struct icp_drvOpData) +
231                     defBuffListInfo.metaSize ,0, SLAB_HWCACHE_ALIGN, NULL, NULL);
232
233
234         ICP_CACHE_NULL_CHECK(drvOpData_zone);
235
236         drvDH_zone = ICP_CACHE_CREATE("ICP DH data", CpaCyDhPhase1KeyGenOpData);
237         ICP_CACHE_NULL_CHECK(drvDH_zone);
238
239         drvLnModExp_zone =
240             ICP_CACHE_CREATE("ICP ModExp data", CpaCyLnModExpOpData);
241         ICP_CACHE_NULL_CHECK(drvLnModExp_zone);
242
243         drvRSADecrypt_zone =
244             ICP_CACHE_CREATE("ICP RSA decrypt data", CpaCyRsaDecryptOpData);
245         ICP_CACHE_NULL_CHECK(drvRSADecrypt_zone);
246
247         drvRSAPrivateKey_zone =
248             ICP_CACHE_CREATE("ICP RSA private key data", CpaCyRsaPrivateKey);
249         ICP_CACHE_NULL_CHECK(drvRSAPrivateKey_zone);
250
251         drvDSARSSign_zone =
252             ICP_CACHE_CREATE("ICP DSA Sign", CpaCyDsaRSSignOpData);
253         ICP_CACHE_NULL_CHECK(drvDSARSSign_zone);
254
255         /*too awkward to use a macro here */
256         drvDSARSSignKValue_zone =
257             kmem_cache_create("ICP DSA Sign Rand Val",
258                               DSA_RS_SIGN_PRIMEQ_SIZE_IN_BYTES, 0,
259                               SLAB_HWCACHE_ALIGN, NULL, NULL);
260         ICP_CACHE_NULL_CHECK(drvDSARSSignKValue_zone);
261
262         drvDSAVerify_zone =
263             ICP_CACHE_CREATE("ICP DSA Verify", CpaCyDsaVerifyOpData);
264         ICP_CACHE_NULL_CHECK(drvDSAVerify_zone);
265
266         drvFlatBuffer_zone =
267             ICP_CACHE_CREATE("ICP Flat Buffers", CpaFlatBuffer);
268         ICP_CACHE_NULL_CHECK(drvFlatBuffer_zone);
269
270         /* Register the ICP symmetric crypto support. */
271         ICP_REGISTER_SYM_FUNCTIONALITY_WITH_OCF(CRYPTO_NULL_CBC);
272         ICP_REGISTER_SYM_FUNCTIONALITY_WITH_OCF(CRYPTO_DES_CBC);
273         ICP_REGISTER_SYM_FUNCTIONALITY_WITH_OCF(CRYPTO_3DES_CBC);
274         ICP_REGISTER_SYM_FUNCTIONALITY_WITH_OCF(CRYPTO_AES_CBC);
275         ICP_REGISTER_SYM_FUNCTIONALITY_WITH_OCF(CRYPTO_ARC4);
276         ICP_REGISTER_SYM_FUNCTIONALITY_WITH_OCF(CRYPTO_MD5);
277         ICP_REGISTER_SYM_FUNCTIONALITY_WITH_OCF(CRYPTO_MD5_HMAC);
278         ICP_REGISTER_SYM_FUNCTIONALITY_WITH_OCF(CRYPTO_SHA1);
279         ICP_REGISTER_SYM_FUNCTIONALITY_WITH_OCF(CRYPTO_SHA1_HMAC);
280         ICP_REGISTER_SYM_FUNCTIONALITY_WITH_OCF(CRYPTO_SHA2_256);
281         ICP_REGISTER_SYM_FUNCTIONALITY_WITH_OCF(CRYPTO_SHA2_256_HMAC);
282         ICP_REGISTER_SYM_FUNCTIONALITY_WITH_OCF(CRYPTO_SHA2_384);
283         ICP_REGISTER_SYM_FUNCTIONALITY_WITH_OCF(CRYPTO_SHA2_384_HMAC);
284         ICP_REGISTER_SYM_FUNCTIONALITY_WITH_OCF(CRYPTO_SHA2_512);
285         ICP_REGISTER_SYM_FUNCTIONALITY_WITH_OCF(CRYPTO_SHA2_512_HMAC);
286
287         /* Register the ICP asymmetric algorithm support */
288         ICP_REGISTER_ASYM_FUNCTIONALITY_WITH_OCF(CRK_DH_COMPUTE_KEY);
289         ICP_REGISTER_ASYM_FUNCTIONALITY_WITH_OCF(CRK_MOD_EXP);
290         ICP_REGISTER_ASYM_FUNCTIONALITY_WITH_OCF(CRK_MOD_EXP_CRT);
291         ICP_REGISTER_ASYM_FUNCTIONALITY_WITH_OCF(CRK_DSA_SIGN);
292         ICP_REGISTER_ASYM_FUNCTIONALITY_WITH_OCF(CRK_DSA_VERIFY);
293
294         /* Register the ICP random number generator support */
295         if (OCF_REGISTRATION_STATUS_SUCCESS ==
296             crypto_rregister(icp_ocfDrvDriverId, icp_ocfDrvReadRandom, NULL)) {
297                 ocfStatus++;
298         }
299
300         if (OCF_ZERO_FUNCTIONALITY_REGISTERED == ocfStatus) {
301                 DPRINTK("%s: Failed to register any device capabilities\n",
302                         __FUNCTION__);
303                 icp_ocfDrvFreeCaches();
304                 icp_ocfDrvDriverId = INVALID_DRIVER_ID;
305                 return -ECANCELED;
306         }
307
308         DPRINTK("%s: Registered %d of %d device capabilities\n",
309                 __FUNCTION__, ocfStatus, NUM_SUPPORTED_CAPABILITIES);
310
311 /*Session data linked list used during module exit*/
312         INIT_LIST_HEAD(&icp_ocfDrvGlobalSymListHead);
313         INIT_LIST_HEAD(&icp_ocfDrvGlobalSymListHead_FreeMemList);
314
315         icp_ocfDrvFreeLacSessionWorkQ =
316             create_singlethread_workqueue("ocfLacDeregWorkQueue");
317
318         return 0;
319 }
320
321 /* Name        : icp_ocfDrvExit
322  *
323  * Description : This function will deregister all the symmetric sessions
324  * registered with the LAC component. It will also deregister all symmetric
325  * and asymmetric functionality that can be accelerated by the hardware via OCF
326  * and random number generation if it is enabled.
327  */
328 static void icp_ocfDrvExit(void)
329 {
330         CpaStatus lacStatus = CPA_STATUS_SUCCESS;
331         struct icp_drvSessionData *sessionData = NULL;
332         struct icp_drvSessionData *tempSessionData = NULL;
333         int i, remaining_delay_time_in_jiffies = 0;
334         /* There is a possibility of a process or new session command being   */
335         /* sent before this variable is incremented. The aim of this variable */
336         /* is to stop a loop of calls creating a deadlock situation which     */
337         /* would prevent the driver from exiting.                             */
338
339         atomic_inc(&icp_ocfDrvIsExiting);
340
341         /*Existing sessions will be routed to another driver after these calls */
342         crypto_unregister_all(icp_ocfDrvDriverId);
343         crypto_runregister_all(icp_ocfDrvDriverId);
344
345         /*If any sessions are waiting to be deregistered, do that. This also 
346            flushes the work queue */
347         destroy_workqueue(icp_ocfDrvFreeLacSessionWorkQ);
348
349         /*ENTER CRITICAL SECTION */
350         spin_lock_bh(&icp_ocfDrvSymSessInfoListSpinlock);
351         list_for_each_entry_safe(tempSessionData, sessionData,
352                                  &icp_ocfDrvGlobalSymListHead, listNode) {
353                 for (i = 0; i < num_dereg_retries; i++) {
354                         /*No harm if bad input - LAC will handle error cases */
355                         if (ICP_SESSION_RUNNING == tempSessionData->inUse) {
356                                 lacStatus =
357                                     cpaCySymRemoveSession
358                                     (CPA_INSTANCE_HANDLE_SINGLE,
359                                      tempSessionData->sessHandle);
360                                 if (CPA_STATUS_SUCCESS == lacStatus) {
361                                         /* Succesfully deregistered */
362                                         break;
363                                 } else if (CPA_STATUS_RETRY != lacStatus) {
364                                         atomic_inc
365                                             (&lac_session_failed_dereg_count);
366                                         break;
367                                 }
368
369                                 /*schedule_timout returns the time left for completion if 
370                                  * this task is set to TASK_INTERRUPTIBLE */
371                                 remaining_delay_time_in_jiffies =
372                                     dereg_retry_delay_in_jiffies;
373                                 while (0 > remaining_delay_time_in_jiffies) {
374                                         remaining_delay_time_in_jiffies =
375                                             schedule_timeout
376                                             (remaining_delay_time_in_jiffies);
377                                 }
378
379                                 DPRINTK
380                                     ("%s(): Retry %d to deregistrate the session\n",
381                                      __FUNCTION__, i);
382                         }
383                 }
384
385                 /*remove from current list */
386                 list_del(&(tempSessionData->listNode));
387                 /*add to free mem linked list */
388                 list_add(&(tempSessionData->listNode),
389                          &icp_ocfDrvGlobalSymListHead_FreeMemList);
390
391         }
392
393         /*EXIT CRITICAL SECTION */
394         spin_unlock_bh(&icp_ocfDrvSymSessInfoListSpinlock);
395
396         /*set back to initial values */
397         sessionData = NULL;
398         /*still have a reference in our list! */
399         tempSessionData = NULL;
400         /*free memory */
401         list_for_each_entry_safe(tempSessionData, sessionData,
402                                  &icp_ocfDrvGlobalSymListHead_FreeMemList,
403                                  listNode) {
404
405                 list_del(&(tempSessionData->listNode));
406                 /* Free allocated CpaCySymSessionCtx */
407                 if (NULL != tempSessionData->sessHandle) {
408                         kfree(tempSessionData->sessHandle);
409                 }
410                 memset(tempSessionData, 0, sizeof(struct icp_drvSessionData));
411                 kmem_cache_free(drvSessionData_zone, tempSessionData);
412         }
413
414         if (0 != atomic_read(&lac_session_failed_dereg_count)) {
415                 DPRINTK("%s(): %d LAC sessions were not deregistered "
416                         "correctly. This is not a clean exit! \n",
417                         __FUNCTION__,
418                         atomic_read(&lac_session_failed_dereg_count));
419         }
420
421         icp_ocfDrvFreeCaches();
422         icp_ocfDrvDriverId = INVALID_DRIVER_ID;
423
424         /* Shutdown the Cryptographic component */
425         lacStatus = cpaCyStopInstance(CPA_INSTANCE_HANDLE_SINGLE);
426         if (CPA_STATUS_SUCCESS != lacStatus) {
427                 DPRINTK("%s(): Failed to stop instance of the "
428                         "Cryptographic component.(status == %d)\n",
429                         __FUNCTION__, lacStatus);
430         }
431
432 }
433
434 /* Name        : icp_ocfDrvFreeCaches
435  *
436  * Description : This function deregisters all slab caches
437  */
438 static void icp_ocfDrvFreeCaches(void)
439 {
440         if (atomic_read(&icp_ocfDrvIsExiting) != CPA_TRUE) {
441                 atomic_set(&icp_ocfDrvIsExiting, 1);
442         }
443
444         /*Sym Zones */
445         ICP_CACHE_DESTROY(drvSessionData_zone);
446         ICP_CACHE_DESTROY(drvOpData_zone);
447
448         /*Asym zones */
449         ICP_CACHE_DESTROY(drvDH_zone);
450         ICP_CACHE_DESTROY(drvLnModExp_zone);
451         ICP_CACHE_DESTROY(drvRSADecrypt_zone);
452         ICP_CACHE_DESTROY(drvRSAPrivateKey_zone);
453         ICP_CACHE_DESTROY(drvDSARSSignKValue_zone);
454         ICP_CACHE_DESTROY(drvDSARSSign_zone);
455         ICP_CACHE_DESTROY(drvDSAVerify_zone);
456
457         /*FlatBuffer and BufferList Zones */
458         ICP_CACHE_DESTROY(drvFlatBuffer_zone);
459
460 }
461
462 /* Name        : icp_ocfDrvDeregRetry
463  *
464  * Description : This function will try to farm the session deregistration
465  * off to a work queue. If it fails, nothing more can be done and it
466  * returns an error
467  */
468
469 int icp_ocfDrvDeregRetry(CpaCySymSessionCtx sessionToDeregister)
470 {
471         struct icp_ocfDrvFreeLacSession *workstore = NULL;
472
473         DPRINTK("%s(): Retry - Deregistering session (%p)\n",
474                 __FUNCTION__, sessionToDeregister);
475
476         /*make sure the session is not available to be allocated during this
477            process */
478         atomic_inc(&lac_session_failed_dereg_count);
479
480         /*Farm off to work queue */
481         workstore =
482             kmalloc(sizeof(struct icp_ocfDrvFreeLacSession), GFP_ATOMIC);
483         if (NULL == workstore) {
484                 DPRINTK("%s(): unable to free session - no memory available "
485                         "for work queue\n", __FUNCTION__);
486                 return ENOMEM;
487         }
488
489         workstore->sessionToDeregister = sessionToDeregister;
490
491         INIT_WORK(&(workstore->work), icp_ocfDrvDeferedFreeLacSessionProcess,
492                   workstore);
493         queue_work(icp_ocfDrvFreeLacSessionWorkQ, &(workstore->work));
494
495         return ICP_OCF_DRV_STATUS_SUCCESS;
496
497 }
498
499 /* Name        : icp_ocfDrvDeferedFreeLacSessionProcess
500  *
501  * Description : This function will retry (module input parameter)
502  * 'num_dereg_retries' times to deregister any symmetric session that recieves a
503  * CPA_STATUS_RETRY message from the LAC component. This function is run in
504  * Thread context because it is called from a worker thread
505  */
506 static void icp_ocfDrvDeferedFreeLacSessionProcess(void *arg)
507 {
508         struct icp_ocfDrvFreeLacSession *workstore = NULL;
509         CpaCySymSessionCtx sessionToDeregister = NULL;
510         int i = 0;
511         int remaining_delay_time_in_jiffies = 0;
512         CpaStatus lacStatus = CPA_STATUS_SUCCESS;
513
514         workstore = (struct icp_ocfDrvFreeLacSession *)arg;
515         if (NULL == workstore) {
516                 DPRINTK("%s() function called with null parameter \n",
517                         __FUNCTION__);
518                 return;
519         }
520
521         sessionToDeregister = workstore->sessionToDeregister;
522         kfree(workstore);
523
524         /*if exiting, give deregistration one more blast only */
525         if (atomic_read(&icp_ocfDrvIsExiting) == CPA_TRUE) {
526                 lacStatus = cpaCySymRemoveSession(CPA_INSTANCE_HANDLE_SINGLE,
527                                                   sessionToDeregister);
528
529                 if (lacStatus != CPA_STATUS_SUCCESS) {
530                         DPRINTK("%s() Failed to Dereg LAC session %p "
531                                 "during module exit\n", __FUNCTION__,
532                                 sessionToDeregister);
533                         return;
534                 }
535
536                 atomic_dec(&lac_session_failed_dereg_count);
537                 return;
538         }
539
540         for (i = 0; i <= num_dereg_retries; i++) {
541                 lacStatus = cpaCySymRemoveSession(CPA_INSTANCE_HANDLE_SINGLE,
542                                                   sessionToDeregister);
543
544                 if (lacStatus == CPA_STATUS_SUCCESS) {
545                         atomic_dec(&lac_session_failed_dereg_count);
546                         return;
547                 }
548                 if (lacStatus != CPA_STATUS_RETRY) {
549                         DPRINTK("%s() Failed to deregister session - lacStatus "
550                                 " = %d", __FUNCTION__, lacStatus);
551                         break;
552                 }
553
554                 /*schedule_timout returns the time left for completion if this
555                    task is set to TASK_INTERRUPTIBLE */
556                 remaining_delay_time_in_jiffies = dereg_retry_delay_in_jiffies;
557                 while (0 > remaining_delay_time_in_jiffies) {
558                         remaining_delay_time_in_jiffies =
559                             schedule_timeout(remaining_delay_time_in_jiffies);
560                 }
561
562         }
563
564         DPRINTK("%s(): Unable to deregister session\n", __FUNCTION__);
565         DPRINTK("%s(): Number of unavailable LAC sessions = %d\n", __FUNCTION__,
566                 atomic_read(&lac_session_failed_dereg_count));
567 }
568
569 /* Name        : icp_ocfDrvPtrAndLenToFlatBuffer 
570  *
571  * Description : This function converts a "pointer and length" buffer 
572  * structure to Fredericksburg Flat Buffer (CpaFlatBuffer) format.
573  *
574  * This function assumes that the data passed in are valid.
575  */
576 inline void
577 icp_ocfDrvPtrAndLenToFlatBuffer(void *pData, uint32_t len,
578                                 CpaFlatBuffer * pFlatBuffer)
579 {
580         pFlatBuffer->pData = pData;
581         pFlatBuffer->dataLenInBytes = len;
582 }
583
584 /* Name        : icp_ocfDrvSingleSkBuffToFlatBuffer 
585  *
586  * Description : This function converts a single socket buffer (sk_buff)
587  * structure to a Fredericksburg Flat Buffer (CpaFlatBuffer) format.
588  *
589  * This function assumes that the data passed in are valid.
590  */
591 static inline void
592 icp_ocfDrvSingleSkBuffToFlatBuffer(struct sk_buff *pSkb,
593                                    CpaFlatBuffer * pFlatBuffer)
594 {
595         pFlatBuffer->pData = pSkb->data;
596         pFlatBuffer->dataLenInBytes = skb_headlen(pSkb);
597 }
598
599 /* Name        : icp_ocfDrvSkBuffToBufferList 
600  *
601  * Description : This function converts a socket buffer (sk_buff) structure to
602  * Fredericksburg Scatter/Gather (CpaBufferList) buffer format.
603  *
604  * This function assumes that the bufferlist has been allocated with the correct
605  * number of buffer arrays.
606  * 
607  */
608 inline int
609 icp_ocfDrvSkBuffToBufferList(struct sk_buff *pSkb, CpaBufferList * bufferList)
610 {
611         CpaFlatBuffer *curFlatBuffer = NULL;
612         char *skbuffPageAddr = NULL;
613         struct sk_buff *pCurFrag = NULL;
614         struct skb_shared_info *pShInfo = NULL;
615         uint32_t page_offset = 0, i = 0;
616
617         DPRINTK("%s(): Entry Point\n", __FUNCTION__);
618
619         /*
620          * In all cases, the first skb needs to be translated to FlatBuffer.
621          * Perform a buffer translation for the first skbuff
622          */
623         curFlatBuffer = bufferList->pBuffers;
624         icp_ocfDrvSingleSkBuffToFlatBuffer(pSkb, curFlatBuffer);
625
626         /* Set the userData to point to the original sk_buff */
627         bufferList->pUserData = (void *)pSkb;
628
629         /* We now know we'll have at least one element in the SGL */
630         bufferList->numBuffers = 1;
631
632         if (0 == skb_is_nonlinear(pSkb)) {
633                 /* Is a linear buffer - therefore it's a single skbuff */
634                 DPRINTK("%s(): Exit Point\n", __FUNCTION__);
635                 return ICP_OCF_DRV_STATUS_SUCCESS;
636         }
637
638         curFlatBuffer++;
639         pShInfo = skb_shinfo(pSkb);
640         if (pShInfo->frag_list != NULL && pShInfo->nr_frags != 0) {
641                 EPRINTK("%s():"
642                         "Translation for a combination of frag_list "
643                         "and frags[] array not supported!\n", __FUNCTION__);
644                 return ICP_OCF_DRV_STATUS_FAIL;
645         } else if (pShInfo->frag_list != NULL) {
646                 /*
647                  * Non linear skbuff supported through frag_list 
648                  * Perform translation for each fragment (sk_buff)
649                  * in the frag_list of the first sk_buff.
650                  */
651                 for (pCurFrag = pShInfo->frag_list;
652                      pCurFrag != NULL; pCurFrag = pCurFrag->next) {
653                         icp_ocfDrvSingleSkBuffToFlatBuffer(pCurFrag,
654                                                            curFlatBuffer);
655                         curFlatBuffer++;
656                         bufferList->numBuffers++;
657                 }
658         } else if (pShInfo->nr_frags != 0) {
659                 /*
660                  * Perform translation for each fragment in frags array
661                  * and add to the BufferList
662                  */
663                 for (i = 0; i < pShInfo->nr_frags; i++) {
664                         /* Get the page address and offset of this frag */
665                         skbuffPageAddr = (char *)pShInfo->frags[i].page;
666                         page_offset = pShInfo->frags[i].page_offset;
667
668                         /* Convert a pointer and length to a flat buffer */
669                         icp_ocfDrvPtrAndLenToFlatBuffer(skbuffPageAddr +
670                                                         page_offset,
671                                                         pShInfo->frags[i].size,
672                                                         curFlatBuffer);
673                         curFlatBuffer++;
674                         bufferList->numBuffers++;
675                 }
676         } else {
677                 EPRINTK("%s():" "Could not recognize skbuff fragments!\n",
678                         __FUNCTION__);
679                 return ICP_OCF_DRV_STATUS_FAIL;
680         }
681
682         DPRINTK("%s(): Exit Point\n", __FUNCTION__);
683         return ICP_OCF_DRV_STATUS_SUCCESS;
684 }
685
686 /* Name        : icp_ocfDrvBufferListToSkBuff 
687  *
688  * Description : This function converts a Fredericksburg Scatter/Gather 
689  * (CpaBufferList) buffer format to socket buffer structure.
690  */
691 inline int
692 icp_ocfDrvBufferListToSkBuff(CpaBufferList * bufferList, struct sk_buff **skb)
693 {
694         DPRINTK("%s(): Entry Point\n", __FUNCTION__);
695
696         /* Retrieve the orignal skbuff */
697         *skb = (struct sk_buff *)bufferList->pUserData;
698         if (NULL == *skb) {
699                 EPRINTK("%s():"
700                         "Error on converting from a BufferList. "
701                         "The BufferList does not contain an sk_buff.\n",
702                         __FUNCTION__);
703                 return ICP_OCF_DRV_STATUS_FAIL;
704         }
705         DPRINTK("%s(): Exit Point\n", __FUNCTION__);
706         return ICP_OCF_DRV_STATUS_SUCCESS;
707 }
708
709 /* Name        : icp_ocfDrvPtrAndLenToBufferList
710  *
711  * Description : This function converts a "pointer and length" buffer
712  * structure to Fredericksburg Scatter/Gather Buffer (CpaBufferList) format.
713  *
714  * This function assumes that the data passed in are valid.
715  */
716 inline void
717 icp_ocfDrvPtrAndLenToBufferList(void *pDataIn, uint32_t length,
718                                 CpaBufferList * pBufferList)
719 {
720         pBufferList->numBuffers = 1;
721         pBufferList->pBuffers->pData = pDataIn;
722         pBufferList->pBuffers->dataLenInBytes = length;
723 }
724
725 /* Name        : icp_ocfDrvBufferListToPtrAndLen
726  *
727  * Description : This function converts Fredericksburg Scatter/Gather Buffer
728  * (CpaBufferList) format to a "pointer and length" buffer structure.
729  *
730  * This function assumes that the data passed in are valid.
731  */
732 inline void
733 icp_ocfDrvBufferListToPtrAndLen(CpaBufferList * pBufferList,
734                                 void **ppDataOut, uint32_t * pLength)
735 {
736         *ppDataOut = pBufferList->pBuffers->pData;
737         *pLength = pBufferList->pBuffers->dataLenInBytes;
738 }
739
740 /* Name        : icp_ocfDrvBufferListMemInfo
741  *
742  * Description : This function will set the number of flat buffers in 
743  * bufferlist, the size of memory to allocate for the pPrivateMetaData 
744  * member of the CpaBufferList.
745  */
746 int
747 icp_ocfDrvBufferListMemInfo(uint16_t numBuffers,
748                             struct icp_drvBuffListInfo *buffListInfo)
749 {
750         buffListInfo->numBuffers = numBuffers;
751
752         if (CPA_STATUS_SUCCESS !=
753             cpaCyBufferListGetMetaSize(CPA_INSTANCE_HANDLE_SINGLE,
754                                        buffListInfo->numBuffers,
755                                        &(buffListInfo->metaSize))) {
756                 EPRINTK("%s() Failed to get buffer list meta size.\n",
757                         __FUNCTION__);
758                 return ICP_OCF_DRV_STATUS_FAIL;
759         }
760
761         return ICP_OCF_DRV_STATUS_SUCCESS;
762 }
763
764 /* Name        : icp_ocfDrvGetSkBuffFrags
765  *
766  * Description : This function will determine the number of 
767  * fragments in a socket buffer(sk_buff).
768  */
769 inline uint16_t icp_ocfDrvGetSkBuffFrags(struct sk_buff * pSkb)
770 {
771         uint16_t numFrags = 0;
772         struct sk_buff *pCurFrag = NULL;
773         struct skb_shared_info *pShInfo = NULL;
774
775         if (NULL == pSkb)
776                 return 0;
777
778         numFrags = 1;
779         if (0 == skb_is_nonlinear(pSkb)) {
780                 /* Linear buffer - it's a single skbuff */
781                 return numFrags;
782         }
783
784         pShInfo = skb_shinfo(pSkb);
785         if (NULL != pShInfo->frag_list && 0 != pShInfo->nr_frags) {
786                 EPRINTK("%s(): Combination of frag_list "
787                         "and frags[] array not supported!\n", __FUNCTION__);
788                 return 0;
789         } else if (0 != pShInfo->nr_frags) {
790                 numFrags += pShInfo->nr_frags;
791                 return numFrags;
792         } else if (NULL != pShInfo->frag_list) {
793                 for (pCurFrag = pShInfo->frag_list;
794                      pCurFrag != NULL; pCurFrag = pCurFrag->next) {
795                         numFrags++;
796                 }
797                 return numFrags;
798         } else {
799                 return 0;
800         }
801 }
802
803 /* Name        : icp_ocfDrvFreeFlatBuffer
804  *
805  * Description : This function will deallocate flat buffer.
806  */
807 inline void icp_ocfDrvFreeFlatBuffer(CpaFlatBuffer * pFlatBuffer)
808 {
809         if (pFlatBuffer != NULL) {
810                 memset(pFlatBuffer, 0, sizeof(CpaFlatBuffer));
811                 kmem_cache_free(drvFlatBuffer_zone, pFlatBuffer);
812         }
813 }
814
815 /* Name        : icp_ocfDrvAllocMetaData
816  *
817  * Description : This function will allocate memory for the
818  * pPrivateMetaData member of CpaBufferList.
819  */
820 inline int
821 icp_ocfDrvAllocMetaData(CpaBufferList * pBufferList,
822         const struct icp_drvOpData *pOpData)
823 {
824         Cpa32U metaSize = 0;
825
826         if (pBufferList->numBuffers <= ICP_OCF_DRV_DEFAULT_BUFFLIST_ARRAYS){
827             void *pOpDataStartAddr = (void *)pOpData;
828
829             if (0 == defBuffListInfo.metaSize) {
830                         pBufferList->pPrivateMetaData = NULL;
831                         return ICP_OCF_DRV_STATUS_SUCCESS;
832                 }
833                 /*
834                  * The meta data allocation has been included as part of the 
835                  * op data.  It has been pre-allocated in memory just after the
836                  * icp_drvOpData structure.
837                  */
838                 pBufferList->pPrivateMetaData = pOpDataStartAddr +
839                         sizeof(struct icp_drvOpData);
840         } else {
841                 if (CPA_STATUS_SUCCESS !=
842                     cpaCyBufferListGetMetaSize(CPA_INSTANCE_HANDLE_SINGLE,
843                                                pBufferList->numBuffers,
844                                                &metaSize)) {
845                         EPRINTK("%s() Failed to get buffer list meta size.\n",
846                                 __FUNCTION__);
847                         return ICP_OCF_DRV_STATUS_FAIL;
848                 }
849
850                 if (0 == metaSize) {
851                         pBufferList->pPrivateMetaData = NULL;
852                         return ICP_OCF_DRV_STATUS_SUCCESS;
853                 }
854
855                 pBufferList->pPrivateMetaData = kmalloc(metaSize, GFP_ATOMIC);
856         }
857         if (NULL == pBufferList->pPrivateMetaData) {
858                 EPRINTK("%s() Failed to allocate pPrivateMetaData.\n",
859                         __FUNCTION__);
860                 return ICP_OCF_DRV_STATUS_FAIL;
861         }
862
863         return ICP_OCF_DRV_STATUS_SUCCESS;
864 }
865
866 /* Name        : icp_ocfDrvFreeMetaData
867  *
868  * Description : This function will deallocate pPrivateMetaData memory.
869  */
870 inline void icp_ocfDrvFreeMetaData(CpaBufferList * pBufferList)
871 {
872         if (NULL == pBufferList->pPrivateMetaData) {
873                 return;
874         }
875
876         /*
877          * Only free the meta data if the BufferList has more than 
878          * ICP_OCF_DRV_DEFAULT_BUFFLIST_ARRAYS number of buffers.
879          * Otherwise, the meta data shall be freed when the icp_drvOpData is
880          * freed.
881          */
882         if (ICP_OCF_DRV_DEFAULT_BUFFLIST_ARRAYS < pBufferList->numBuffers){
883                 kfree(pBufferList->pPrivateMetaData);
884         }
885 }
886
887 module_init(icp_ocfDrvInit);
888 module_exit(icp_ocfDrvExit);
889 MODULE_LICENSE("Dual BSD/GPL");
890 MODULE_AUTHOR("Intel");
891 MODULE_DESCRIPTION("OCF Driver for Intel Quick Assist crypto acceleration");