4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 #pragma ident "%Z%%M% %I% %E% SMI"
30 * crypto_bufcall(9F) group of routines.
33 #include <sys/types.h>
34 #include <sys/sunddi.h>
35 #include <sys/callb.h>
36 #include <sys/ksynch.h>
37 #include <sys/systm.h>
38 #include <sys/taskq_impl.h>
39 #include <sys/crypto/api.h>
40 #include <sys/crypto/sched_impl.h>
43 * All pending crypto bufcalls are put on a list. cbuf_list_lock
44 * protects changes to this list.
46 * The following locking order is maintained in the code - The
47 * global cbuf_list_lock followed by the individual lock
48 * in a crypto bufcall structure (kc_lock).
50 kmutex_t cbuf_list_lock
;
51 kcondvar_t cbuf_list_cv
; /* cv the service thread waits on */
52 static kcf_cbuf_elem_t
*cbuf_list_head
;
53 static kcf_cbuf_elem_t
*cbuf_list_tail
;
56 * Allocate and return a handle to be used for crypto_bufcall().
57 * Can be called from user context only.
60 crypto_bufcall_alloc(void)
62 kcf_cbuf_elem_t
*cbufp
;
64 cbufp
= kmem_zalloc(sizeof (kcf_cbuf_elem_t
), KM_SLEEP
);
65 mutex_init(&cbufp
->kc_lock
, NULL
, MUTEX_DEFAULT
, NULL
);
66 cv_init(&cbufp
->kc_cv
, NULL
, CV_DEFAULT
, NULL
);
67 cbufp
->kc_state
= CBUF_FREE
;
73 * Free the handle if possible. Returns CRYPTO_SUCCESS if the handle
74 * is freed. Else it returns CRYPTO_BUSY.
76 * The client should do a crypto_unbufcall() if it receives a
79 * Can be called both from user and interrupt context.
82 crypto_bufcall_free(crypto_bc_t bc
)
84 kcf_cbuf_elem_t
*cbufp
= (kcf_cbuf_elem_t
*)bc
;
86 mutex_enter(&cbufp
->kc_lock
);
87 if (cbufp
->kc_state
!= CBUF_FREE
) {
88 mutex_exit(&cbufp
->kc_lock
);
91 mutex_exit(&cbufp
->kc_lock
);
93 mutex_destroy(&cbufp
->kc_lock
);
94 cv_destroy(&cbufp
->kc_cv
);
95 kmem_free(cbufp
, sizeof (kcf_cbuf_elem_t
));
97 return (CRYPTO_SUCCESS
);
101 * Schedule func() to be called when queue space is available to
102 * submit a crypto request.
104 * Can be called both from user and interrupt context.
107 crypto_bufcall(crypto_bc_t bc
, void (*func
)(void *arg
), void *arg
)
109 kcf_cbuf_elem_t
*cbufp
;
111 cbufp
= (kcf_cbuf_elem_t
*)bc
;
112 if (cbufp
== NULL
|| func
== NULL
) {
113 return (CRYPTO_ARGUMENTS_BAD
);
116 mutex_enter(&cbuf_list_lock
);
117 mutex_enter(&cbufp
->kc_lock
);
118 if (cbufp
->kc_state
!= CBUF_FREE
) {
119 mutex_exit(&cbufp
->kc_lock
);
120 mutex_exit(&cbuf_list_lock
);
121 return (CRYPTO_BUSY
);
124 cbufp
->kc_state
= CBUF_WAITING
;
125 cbufp
->kc_func
= func
;
127 cbufp
->kc_prev
= cbufp
->kc_next
= NULL
;
129 if (cbuf_list_head
== NULL
) {
130 cbuf_list_head
= cbuf_list_tail
= cbufp
;
132 cbuf_list_tail
->kc_next
= cbufp
;
133 cbufp
->kc_prev
= cbuf_list_tail
;
134 cbuf_list_tail
= cbufp
;
138 * Signal the crypto_bufcall_service thread to start
139 * working on this crypto bufcall request.
141 cv_signal(&cbuf_list_cv
);
142 mutex_exit(&cbufp
->kc_lock
);
143 mutex_exit(&cbuf_list_lock
);
145 return (CRYPTO_SUCCESS
);
149 * Cancel a pending crypto bufcall request. If the bufcall
150 * is currently executing, we wait till it is complete.
152 * Can only be called from user context.
155 crypto_unbufcall(crypto_bc_t bc
)
157 kcf_cbuf_elem_t
*cbufp
= (kcf_cbuf_elem_t
*)bc
;
159 mutex_enter(&cbuf_list_lock
);
160 mutex_enter(&cbufp
->kc_lock
);
162 if (cbufp
->kc_state
== CBUF_WAITING
) {
163 kcf_cbuf_elem_t
*nextp
= cbufp
->kc_next
;
164 kcf_cbuf_elem_t
*prevp
= cbufp
->kc_prev
;
167 nextp
->kc_prev
= prevp
;
169 cbuf_list_tail
= prevp
;
172 prevp
->kc_next
= nextp
;
174 cbuf_list_head
= nextp
;
175 cbufp
->kc_state
= CBUF_FREE
;
176 } else if (cbufp
->kc_state
== CBUF_RUNNING
) {
177 mutex_exit(&cbuf_list_lock
);
179 * crypto_bufcall_service thread is working
180 * on this element. We will wait for that
181 * thread to signal us when done.
183 while (cbufp
->kc_state
== CBUF_RUNNING
)
184 cv_wait(&cbufp
->kc_cv
, &cbufp
->kc_lock
);
185 mutex_exit(&cbufp
->kc_lock
);
187 return (CRYPTO_SUCCESS
);
190 mutex_exit(&cbufp
->kc_lock
);
191 mutex_exit(&cbuf_list_lock
);
193 return (CRYPTO_SUCCESS
);
197 * We sample the number of jobs. We do not hold the lock
198 * as it is not necessary to get the exact count.
200 #define KCF_GSWQ_AVAIL (gswq->gs_maxjobs - gswq->gs_njobs)
203 * One queue space each for init, update, and final.
205 #define GSWQ_MINFREE 3
208 * Go through the list of crypto bufcalls and do the necessary
212 kcf_run_cbufcalls(void)
214 kcf_cbuf_elem_t
*cbufp
;
217 mutex_enter(&cbuf_list_lock
);
220 * Get estimate of available queue space from KCF_GSWQ_AVAIL.
221 * We can call 'n' crypto bufcall callback functions where
222 * n * GSWQ_MINFREE <= available queue space.
224 * TO DO - Extend the check to taskqs of hardware providers.
225 * For now, we handle only the software providers.
227 count
= KCF_GSWQ_AVAIL
;
228 while ((cbufp
= cbuf_list_head
) != NULL
) {
229 if (GSWQ_MINFREE
<= count
) {
230 count
-= GSWQ_MINFREE
;
231 mutex_enter(&cbufp
->kc_lock
);
232 cbuf_list_head
= cbufp
->kc_next
;
233 cbufp
->kc_state
= CBUF_RUNNING
;
234 mutex_exit(&cbufp
->kc_lock
);
235 mutex_exit(&cbuf_list_lock
);
237 (*cbufp
->kc_func
)(cbufp
->kc_arg
);
239 mutex_enter(&cbufp
->kc_lock
);
240 cbufp
->kc_state
= CBUF_FREE
;
241 cv_broadcast(&cbufp
->kc_cv
);
242 mutex_exit(&cbufp
->kc_lock
);
244 mutex_enter(&cbuf_list_lock
);
247 * There is not enough queue space in this
248 * round. We bail out and try again
254 if (cbuf_list_head
== NULL
)
255 cbuf_list_tail
= NULL
;
257 mutex_exit(&cbuf_list_lock
);
261 * Background processing of crypto bufcalls.
264 crypto_bufcall_service(void)
268 CALLB_CPR_INIT(&cprinfo
, &cbuf_list_lock
, callb_generic_cpr
,
269 "crypto_bufcall_service");
271 mutex_enter(&cbuf_list_lock
);
274 if (cbuf_list_head
!= NULL
&& KCF_GSWQ_AVAIL
>= GSWQ_MINFREE
) {
275 mutex_exit(&cbuf_list_lock
);
277 mutex_enter(&cbuf_list_lock
);
280 if (cbuf_list_head
!= NULL
) {
282 * Wait 30 seconds for queue space to become available.
283 * This number is reasonable as it does not cause
284 * much CPU overhead. We could wait on a condition
285 * variable and the global software dequeue routine can
286 * signal us. But, it adds overhead to that routine
287 * which we want to avoid. Also, the client is prepared
290 CALLB_CPR_SAFE_BEGIN(&cprinfo
);
291 mutex_exit(&cbuf_list_lock
);
293 mutex_enter(&cbuf_list_lock
);
294 CALLB_CPR_SAFE_END(&cprinfo
, &cbuf_list_lock
);
297 /* Wait for new work to arrive */
298 if (cbuf_list_head
== NULL
) {
299 CALLB_CPR_SAFE_BEGIN(&cprinfo
);
300 cv_wait(&cbuf_list_cv
, &cbuf_list_lock
);
301 CALLB_CPR_SAFE_END(&cprinfo
, &cbuf_list_lock
);