1 /***************************************************************************
3 * This file is provided under a dual BSD/GPLv2 license. When using or
4 * redistributing this file, you may do so under either license.
8 * Copyright(c) 2007,2008 Intel Corporation. All rights reserved.
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of version 2 of the GNU General Public License as
12 * published by the Free Software Foundation.
14 * This program is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
22 * The full GNU General Public License is included in this distribution
23 * in the file called LICENSE.GPL.
25 * Contact Information:
30 * Copyright(c) 2007,2008 Intel Corporation. All rights reserved.
31 * All rights reserved.
33 * Redistribution and use in source and binary forms, with or without
34 * modification, are permitted provided that the following conditions
37 * * Redistributions of source code must retain the above copyright
38 * notice, this list of conditions and the following disclaimer.
39 * * Redistributions in binary form must reproduce the above copyright
40 * notice, this list of conditions and the following disclaimer in
41 * the documentation and/or other materials provided with the
43 * * Neither the name of Intel Corporation nor the names of its
44 * contributors may be used to endorse or promote products derived
45 * from this software without specific prior written permission.
47 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
48 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
49 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
50 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
51 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
52 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
53 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
54 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
55 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
56 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
57 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
60 * version: Security.L.1.0.130
62 ***************************************************************************/
65 * An OCF module that uses IntelĀ® QuickAssist Integrated Accelerator to do the
68 * This driver requires the ICP Access Library that is available from Intel in
74 #define ICP_OCF_COMP_NAME "ICP_OCF"
75 #define ICP_OCF_VER_MAIN (2)
76 #define ICP_OCF_VER_MJR (0)
77 #define ICP_OCF_VER_MNR (0)
79 #define MAX_DEREG_RETRIES (100)
80 #define DEFAULT_DEREG_RETRIES (10)
81 #define DEFAULT_DEREG_DELAY_IN_JIFFIES (10)
83 /* This defines the maximum number of sessions possible between OCF
84 and the OCF 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)
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;
99 /*Slab zones for flatbuffers and bufferlist*/
100 struct kmem_cache *drvFlatBuffer_zone = NULL;
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);
107 int32_t icp_ocfDrvDriverId = INVALID_DRIVER_ID;
109 /* Module parameter - gives the number of times LAC deregistration shall be
111 int num_dereg_retries = DEFAULT_DEREG_RETRIES;
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;
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;
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);
125 /* This is used to show how many lac sessions were not deregistered*/
126 atomic_t lac_session_failed_dereg_count = ATOMIC_INIT(0);
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);
134 /* Head of linked list used to store session data */
135 struct list_head icp_ocfDrvGlobalSymListHead;
136 struct list_head icp_ocfDrvGlobalSymListHead_FreeMemList;
138 spinlock_t icp_ocfDrvSymSessInfoListSpinlock = SPIN_LOCK_UNLOCKED;
139 rwlock_t icp_kmem_cache_destroy_alloc_lock = RW_LOCK_UNLOCKED;
141 struct workqueue_struct *icp_ocfDrvFreeLacSessionWorkQ;
143 struct icp_drvBuffListInfo defBuffListInfo;
146 softc_device_decl sc_dev;
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),
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);
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)");
171 /* Name : icp_ocfDrvInit
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
177 static int __init icp_ocfDrvInit(void)
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);
184 if (MAX_DEREG_RETRIES < num_dereg_retries) {
185 EPRINTK("Session deregistration retry count set to greater "
186 "than %d", MAX_DEREG_RETRIES);
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");
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,
203 EPRINTK("Failed to get bufferlist memory info.\n");
207 /*Register OCF Tolapai Driver with OCF */
208 memset(&icpDev, 0, sizeof(icpDev));
209 softc_device_init(&icpDev, "icp", 0, icp_methods);
211 icp_ocfDrvDriverId = crypto_get_driverid(softc_get_device(&icpDev),
212 CRYPTOCAP_F_HARDWARE);
214 if (icp_ocfDrvDriverId < 0) {
215 EPRINTK("%s : ICP driver failed to register with OCF!\n",
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);
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.
230 kmem_cache_create("ICP Op Data", sizeof(struct icp_drvOpData) +
231 defBuffListInfo.metaSize ,0, SLAB_HWCACHE_ALIGN, NULL, NULL);
234 ICP_CACHE_NULL_CHECK(drvOpData_zone);
236 drvDH_zone = ICP_CACHE_CREATE("ICP DH data", CpaCyDhPhase1KeyGenOpData);
237 ICP_CACHE_NULL_CHECK(drvDH_zone);
240 ICP_CACHE_CREATE("ICP ModExp data", CpaCyLnModExpOpData);
241 ICP_CACHE_NULL_CHECK(drvLnModExp_zone);
244 ICP_CACHE_CREATE("ICP RSA decrypt data", CpaCyRsaDecryptOpData);
245 ICP_CACHE_NULL_CHECK(drvRSADecrypt_zone);
247 drvRSAPrivateKey_zone =
248 ICP_CACHE_CREATE("ICP RSA private key data", CpaCyRsaPrivateKey);
249 ICP_CACHE_NULL_CHECK(drvRSAPrivateKey_zone);
252 ICP_CACHE_CREATE("ICP DSA Sign", CpaCyDsaRSSignOpData);
253 ICP_CACHE_NULL_CHECK(drvDSARSSign_zone);
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);
263 ICP_CACHE_CREATE("ICP DSA Verify", CpaCyDsaVerifyOpData);
264 ICP_CACHE_NULL_CHECK(drvDSAVerify_zone);
267 ICP_CACHE_CREATE("ICP Flat Buffers", CpaFlatBuffer);
268 ICP_CACHE_NULL_CHECK(drvFlatBuffer_zone);
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);
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);
294 /* Register the ICP random number generator support */
295 if (OCF_REGISTRATION_STATUS_SUCCESS ==
296 crypto_rregister(icp_ocfDrvDriverId, icp_ocfDrvReadRandom, NULL)) {
300 if (OCF_ZERO_FUNCTIONALITY_REGISTERED == ocfStatus) {
301 DPRINTK("%s: Failed to register any device capabilities\n",
303 icp_ocfDrvFreeCaches();
304 icp_ocfDrvDriverId = INVALID_DRIVER_ID;
308 DPRINTK("%s: Registered %d of %d device capabilities\n",
309 __FUNCTION__, ocfStatus, NUM_SUPPORTED_CAPABILITIES);
311 /*Session data linked list used during module exit*/
312 INIT_LIST_HEAD(&icp_ocfDrvGlobalSymListHead);
313 INIT_LIST_HEAD(&icp_ocfDrvGlobalSymListHead_FreeMemList);
315 icp_ocfDrvFreeLacSessionWorkQ =
316 create_singlethread_workqueue("ocfLacDeregWorkQueue");
321 /* Name : icp_ocfDrvExit
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.
328 static void icp_ocfDrvExit(void)
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. */
339 atomic_inc(&icp_ocfDrvIsExiting);
341 /*Existing sessions will be routed to another driver after these calls */
342 crypto_unregister_all(icp_ocfDrvDriverId);
343 crypto_runregister_all(icp_ocfDrvDriverId);
345 /*If any sessions are waiting to be deregistered, do that. This also
346 flushes the work queue */
347 destroy_workqueue(icp_ocfDrvFreeLacSessionWorkQ);
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) {
357 cpaCySymRemoveSession
358 (CPA_INSTANCE_HANDLE_SINGLE,
359 tempSessionData->sessHandle);
360 if (CPA_STATUS_SUCCESS == lacStatus) {
361 /* Succesfully deregistered */
363 } else if (CPA_STATUS_RETRY != lacStatus) {
365 (&lac_session_failed_dereg_count);
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 =
376 (remaining_delay_time_in_jiffies);
380 ("%s(): Retry %d to deregistrate the session\n",
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);
393 /*EXIT CRITICAL SECTION */
394 spin_unlock_bh(&icp_ocfDrvSymSessInfoListSpinlock);
396 /*set back to initial values */
398 /*still have a reference in our list! */
399 tempSessionData = NULL;
401 list_for_each_entry_safe(tempSessionData, sessionData,
402 &icp_ocfDrvGlobalSymListHead_FreeMemList,
405 list_del(&(tempSessionData->listNode));
406 /* Free allocated CpaCySymSessionCtx */
407 if (NULL != tempSessionData->sessHandle) {
408 kfree(tempSessionData->sessHandle);
410 memset(tempSessionData, 0, sizeof(struct icp_drvSessionData));
411 kmem_cache_free(drvSessionData_zone, tempSessionData);
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",
418 atomic_read(&lac_session_failed_dereg_count));
421 icp_ocfDrvFreeCaches();
422 icp_ocfDrvDriverId = INVALID_DRIVER_ID;
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);
434 /* Name : icp_ocfDrvFreeCaches
436 * Description : This function deregisters all slab caches
438 static void icp_ocfDrvFreeCaches(void)
440 if (atomic_read(&icp_ocfDrvIsExiting) != CPA_TRUE) {
441 atomic_set(&icp_ocfDrvIsExiting, 1);
445 ICP_CACHE_DESTROY(drvSessionData_zone);
446 ICP_CACHE_DESTROY(drvOpData_zone);
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);
457 /*FlatBuffer and BufferList Zones */
458 ICP_CACHE_DESTROY(drvFlatBuffer_zone);
462 /* Name : icp_ocfDrvDeregRetry
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
469 int icp_ocfDrvDeregRetry(CpaCySymSessionCtx sessionToDeregister)
471 struct icp_ocfDrvFreeLacSession *workstore = NULL;
473 DPRINTK("%s(): Retry - Deregistering session (%p)\n",
474 __FUNCTION__, sessionToDeregister);
476 /*make sure the session is not available to be allocated during this
478 atomic_inc(&lac_session_failed_dereg_count);
480 /*Farm off to work queue */
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__);
489 workstore->sessionToDeregister = sessionToDeregister;
491 INIT_WORK(&(workstore->work), icp_ocfDrvDeferedFreeLacSessionProcess,
493 queue_work(icp_ocfDrvFreeLacSessionWorkQ, &(workstore->work));
495 return ICP_OCF_DRV_STATUS_SUCCESS;
499 /* Name : icp_ocfDrvDeferedFreeLacSessionProcess
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
506 static void icp_ocfDrvDeferedFreeLacSessionProcess(void *arg)
508 struct icp_ocfDrvFreeLacSession *workstore = NULL;
509 CpaCySymSessionCtx sessionToDeregister = NULL;
511 int remaining_delay_time_in_jiffies = 0;
512 CpaStatus lacStatus = CPA_STATUS_SUCCESS;
514 workstore = (struct icp_ocfDrvFreeLacSession *)arg;
515 if (NULL == workstore) {
516 DPRINTK("%s() function called with null parameter \n",
521 sessionToDeregister = workstore->sessionToDeregister;
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);
529 if (lacStatus != CPA_STATUS_SUCCESS) {
530 DPRINTK("%s() Failed to Dereg LAC session %p "
531 "during module exit\n", __FUNCTION__,
532 sessionToDeregister);
536 atomic_dec(&lac_session_failed_dereg_count);
540 for (i = 0; i <= num_dereg_retries; i++) {
541 lacStatus = cpaCySymRemoveSession(CPA_INSTANCE_HANDLE_SINGLE,
542 sessionToDeregister);
544 if (lacStatus == CPA_STATUS_SUCCESS) {
545 atomic_dec(&lac_session_failed_dereg_count);
548 if (lacStatus != CPA_STATUS_RETRY) {
549 DPRINTK("%s() Failed to deregister session - lacStatus "
550 " = %d", __FUNCTION__, lacStatus);
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);
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));
569 /* Name : icp_ocfDrvPtrAndLenToFlatBuffer
571 * Description : This function converts a "pointer and length" buffer
572 * structure to Fredericksburg Flat Buffer (CpaFlatBuffer) format.
574 * This function assumes that the data passed in are valid.
577 icp_ocfDrvPtrAndLenToFlatBuffer(void *pData, uint32_t len,
578 CpaFlatBuffer * pFlatBuffer)
580 pFlatBuffer->pData = pData;
581 pFlatBuffer->dataLenInBytes = len;
584 /* Name : icp_ocfDrvSingleSkBuffToFlatBuffer
586 * Description : This function converts a single socket buffer (sk_buff)
587 * structure to a Fredericksburg Flat Buffer (CpaFlatBuffer) format.
589 * This function assumes that the data passed in are valid.
592 icp_ocfDrvSingleSkBuffToFlatBuffer(struct sk_buff *pSkb,
593 CpaFlatBuffer * pFlatBuffer)
595 pFlatBuffer->pData = pSkb->data;
596 pFlatBuffer->dataLenInBytes = skb_headlen(pSkb);
599 /* Name : icp_ocfDrvSkBuffToBufferList
601 * Description : This function converts a socket buffer (sk_buff) structure to
602 * Fredericksburg Scatter/Gather (CpaBufferList) buffer format.
604 * This function assumes that the bufferlist has been allocated with the correct
605 * number of buffer arrays.
609 icp_ocfDrvSkBuffToBufferList(struct sk_buff *pSkb, CpaBufferList * bufferList)
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;
617 DPRINTK("%s(): Entry Point\n", __FUNCTION__);
620 * In all cases, the first skb needs to be translated to FlatBuffer.
621 * Perform a buffer translation for the first skbuff
623 curFlatBuffer = bufferList->pBuffers;
624 icp_ocfDrvSingleSkBuffToFlatBuffer(pSkb, curFlatBuffer);
626 /* Set the userData to point to the original sk_buff */
627 bufferList->pUserData = (void *)pSkb;
629 /* We now know we'll have at least one element in the SGL */
630 bufferList->numBuffers = 1;
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;
639 pShInfo = skb_shinfo(pSkb);
640 if (pShInfo->frag_list != NULL && pShInfo->nr_frags != 0) {
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) {
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.
651 for (pCurFrag = pShInfo->frag_list;
652 pCurFrag != NULL; pCurFrag = pCurFrag->next) {
653 icp_ocfDrvSingleSkBuffToFlatBuffer(pCurFrag,
656 bufferList->numBuffers++;
658 } else if (pShInfo->nr_frags != 0) {
660 * Perform translation for each fragment in frags array
661 * and add to the BufferList
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;
668 /* Convert a pointer and length to a flat buffer */
669 icp_ocfDrvPtrAndLenToFlatBuffer(skbuffPageAddr +
671 pShInfo->frags[i].size,
674 bufferList->numBuffers++;
677 EPRINTK("%s():" "Could not recognize skbuff fragments!\n",
679 return ICP_OCF_DRV_STATUS_FAIL;
682 DPRINTK("%s(): Exit Point\n", __FUNCTION__);
683 return ICP_OCF_DRV_STATUS_SUCCESS;
686 /* Name : icp_ocfDrvBufferListToSkBuff
688 * Description : This function converts a Fredericksburg Scatter/Gather
689 * (CpaBufferList) buffer format to socket buffer structure.
692 icp_ocfDrvBufferListToSkBuff(CpaBufferList * bufferList, struct sk_buff **skb)
694 DPRINTK("%s(): Entry Point\n", __FUNCTION__);
696 /* Retrieve the orignal skbuff */
697 *skb = (struct sk_buff *)bufferList->pUserData;
700 "Error on converting from a BufferList. "
701 "The BufferList does not contain an sk_buff.\n",
703 return ICP_OCF_DRV_STATUS_FAIL;
705 DPRINTK("%s(): Exit Point\n", __FUNCTION__);
706 return ICP_OCF_DRV_STATUS_SUCCESS;
709 /* Name : icp_ocfDrvPtrAndLenToBufferList
711 * Description : This function converts a "pointer and length" buffer
712 * structure to Fredericksburg Scatter/Gather Buffer (CpaBufferList) format.
714 * This function assumes that the data passed in are valid.
717 icp_ocfDrvPtrAndLenToBufferList(void *pDataIn, uint32_t length,
718 CpaBufferList * pBufferList)
720 pBufferList->numBuffers = 1;
721 pBufferList->pBuffers->pData = pDataIn;
722 pBufferList->pBuffers->dataLenInBytes = length;
725 /* Name : icp_ocfDrvBufferListToPtrAndLen
727 * Description : This function converts Fredericksburg Scatter/Gather Buffer
728 * (CpaBufferList) format to a "pointer and length" buffer structure.
730 * This function assumes that the data passed in are valid.
733 icp_ocfDrvBufferListToPtrAndLen(CpaBufferList * pBufferList,
734 void **ppDataOut, uint32_t * pLength)
736 *ppDataOut = pBufferList->pBuffers->pData;
737 *pLength = pBufferList->pBuffers->dataLenInBytes;
740 /* Name : icp_ocfDrvBufferListMemInfo
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.
747 icp_ocfDrvBufferListMemInfo(uint16_t numBuffers,
748 struct icp_drvBuffListInfo *buffListInfo)
750 buffListInfo->numBuffers = numBuffers;
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",
758 return ICP_OCF_DRV_STATUS_FAIL;
761 return ICP_OCF_DRV_STATUS_SUCCESS;
764 /* Name : icp_ocfDrvGetSkBuffFrags
766 * Description : This function will determine the number of
767 * fragments in a socket buffer(sk_buff).
769 inline uint16_t icp_ocfDrvGetSkBuffFrags(struct sk_buff * pSkb)
771 uint16_t numFrags = 0;
772 struct sk_buff *pCurFrag = NULL;
773 struct skb_shared_info *pShInfo = NULL;
779 if (0 == skb_is_nonlinear(pSkb)) {
780 /* Linear buffer - it's a single skbuff */
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__);
789 } else if (0 != pShInfo->nr_frags) {
790 numFrags += pShInfo->nr_frags;
792 } else if (NULL != pShInfo->frag_list) {
793 for (pCurFrag = pShInfo->frag_list;
794 pCurFrag != NULL; pCurFrag = pCurFrag->next) {
803 /* Name : icp_ocfDrvFreeFlatBuffer
805 * Description : This function will deallocate flat buffer.
807 inline void icp_ocfDrvFreeFlatBuffer(CpaFlatBuffer * pFlatBuffer)
809 if (pFlatBuffer != NULL) {
810 memset(pFlatBuffer, 0, sizeof(CpaFlatBuffer));
811 kmem_cache_free(drvFlatBuffer_zone, pFlatBuffer);
815 /* Name : icp_ocfDrvAllocMetaData
817 * Description : This function will allocate memory for the
818 * pPrivateMetaData member of CpaBufferList.
821 icp_ocfDrvAllocMetaData(CpaBufferList * pBufferList,
822 const struct icp_drvOpData *pOpData)
826 if (pBufferList->numBuffers <= ICP_OCF_DRV_DEFAULT_BUFFLIST_ARRAYS){
827 void *pOpDataStartAddr = (void *)pOpData;
829 if (0 == defBuffListInfo.metaSize) {
830 pBufferList->pPrivateMetaData = NULL;
831 return ICP_OCF_DRV_STATUS_SUCCESS;
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.
838 pBufferList->pPrivateMetaData = pOpDataStartAddr +
839 sizeof(struct icp_drvOpData);
841 if (CPA_STATUS_SUCCESS !=
842 cpaCyBufferListGetMetaSize(CPA_INSTANCE_HANDLE_SINGLE,
843 pBufferList->numBuffers,
845 EPRINTK("%s() Failed to get buffer list meta size.\n",
847 return ICP_OCF_DRV_STATUS_FAIL;
851 pBufferList->pPrivateMetaData = NULL;
852 return ICP_OCF_DRV_STATUS_SUCCESS;
855 pBufferList->pPrivateMetaData = kmalloc(metaSize, GFP_ATOMIC);
857 if (NULL == pBufferList->pPrivateMetaData) {
858 EPRINTK("%s() Failed to allocate pPrivateMetaData.\n",
860 return ICP_OCF_DRV_STATUS_FAIL;
863 return ICP_OCF_DRV_STATUS_SUCCESS;
866 /* Name : icp_ocfDrvFreeMetaData
868 * Description : This function will deallocate pPrivateMetaData memory.
870 inline void icp_ocfDrvFreeMetaData(CpaBufferList * pBufferList)
872 if (NULL == pBufferList->pPrivateMetaData) {
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
882 if (ICP_OCF_DRV_DEFAULT_BUFFLIST_ARRAYS < pBufferList->numBuffers){
883 kfree(pBufferList->pPrivateMetaData);
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");