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");