Root/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*/
89struct kmem_cache *drvSessionData_zone = NULL;
90struct kmem_cache *drvOpData_zone = NULL;
91struct kmem_cache *drvDH_zone = NULL;
92struct kmem_cache *drvLnModExp_zone = NULL;
93struct kmem_cache *drvRSADecrypt_zone = NULL;
94struct kmem_cache *drvRSAPrivateKey_zone = NULL;
95struct kmem_cache *drvDSARSSign_zone = NULL;
96struct kmem_cache *drvDSARSSignKValue_zone = NULL;
97struct kmem_cache *drvDSAVerify_zone = NULL;
98
99/*Slab zones for flatbuffers and bufferlist*/
100struct kmem_cache *drvFlatBuffer_zone = NULL;
101
102static int icp_ocfDrvInit(void);
103static void icp_ocfDrvExit(void);
104static void icp_ocfDrvFreeCaches(void);
105static void icp_ocfDrvDeferedFreeLacSessionProcess(void *arg);
106
107int32_t icp_ocfDrvDriverId = INVALID_DRIVER_ID;
108
109/* Module parameter - gives the number of times LAC deregistration shall be
110   re-tried */
111int 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 */
115int 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.*/
119int 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 */
123atomic_t icp_ocfDrvIsExiting = ATOMIC_INIT(0);
124
125/* This is used to show how many lac sessions were not deregistered*/
126atomic_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 */
132atomic_t num_ocf_to_drv_registered_sessions = ATOMIC_INIT(0);
133
134/* Head of linked list used to store session data */
135struct list_head icp_ocfDrvGlobalSymListHead;
136struct list_head icp_ocfDrvGlobalSymListHead_FreeMemList;
137
138spinlock_t icp_ocfDrvSymSessInfoListSpinlock = SPIN_LOCK_UNLOCKED;
139rwlock_t icp_kmem_cache_destroy_alloc_lock = RW_LOCK_UNLOCKED;
140
141struct workqueue_struct *icp_ocfDrvFreeLacSessionWorkQ;
142
143struct icp_drvBuffListInfo defBuffListInfo;
144
145static struct {
146    softc_device_decl sc_dev;
147} icpDev;
148
149static 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
157module_param(num_dereg_retries, int, S_IRUGO);
158module_param(dereg_retry_delay_in_jiffies, int, S_IRUGO);
159module_param(max_sessions, int, S_IRUGO);
160
161MODULE_PARM_DESC(num_dereg_retries,
162         "Number of times to retry LAC Sym Session Deregistration. "
163         "Default 10, Max 100");
164MODULE_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");
167MODULE_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 */
177static 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 */
328static 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 */
438static 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
469int 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 */
506static 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 */
576inline void
577icp_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 */
591static inline void
592icp_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 */
608inline int
609icp_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 */
691inline int
692icp_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 */
716inline void
717icp_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 */
732inline void
733icp_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 */
746int
747icp_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 */
769inline 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 */
807inline 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 */
820inline int
821icp_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 */
870inline 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
887module_init(icp_ocfDrvInit);
888module_exit(icp_ocfDrvExit);
889MODULE_LICENSE("Dual BSD/GPL");
890MODULE_AUTHOR("Intel");
891MODULE_DESCRIPTION("OCF Driver for Intel Quick Assist crypto acceleration");
892

Archive Download this file



interactive