1/*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21/*
22 * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
23 * Use is subject to license terms.
24 */
25
26#include <sys/zfs_context.h>
27#include <sys/crypto/common.h>
28#include <sys/crypto/api.h>
29#include <sys/crypto/impl.h>
30#include <sys/crypto/sched_impl.h>
31
32/*
33 * All event subscribers are put on a list. kcf_notify_list_lock
34 * protects changes to this list.
35 *
36 * The following locking order is maintained in the code - The
37 * global kcf_notify_list_lock followed by the individual lock
38 * in a kcf_ntfy_elem structure (kn_lock).
39 */
40kmutex_t		ntfy_list_lock;
41kcondvar_t		ntfy_list_cv;   /* cv the service thread waits on */
42static kcf_ntfy_elem_t *ntfy_list_head;
43
44/*
45 * crypto_mech2id()
46 *
47 * Arguments:
48 *	. mechname: A null-terminated string identifying the mechanism name.
49 *
50 * Description:
51 *	Walks the mechanisms tables, looking for an entry that matches the
52 *	mechname. Once it find it, it builds the 64-bit mech_type and returns
53 *	it.  If there are no hardware or software providers for the mechanism,
54 *	but there is an unloaded software provider, this routine will attempt
55 *	to load it.
56 *
57 * Context:
58 *	Process and interruption.
59 *
60 * Returns:
61 *	The unique mechanism identified by 'mechname', if found.
62 *	CRYPTO_MECH_INVALID otherwise.
63 */
64crypto_mech_type_t
65crypto_mech2id(char *mechname)
66{
67	return (crypto_mech2id_common(mechname, B_TRUE));
68}
69
70/*
71 * We walk the notification list and do the callbacks.
72 */
73void
74kcf_walk_ntfylist(uint32_t event, void *event_arg)
75{
76	kcf_ntfy_elem_t *nep;
77	int nelem = 0;
78
79	mutex_enter(&ntfy_list_lock);
80
81	/*
82	 * Count how many clients are on the notification list. We need
83	 * this count to ensure that clients which joined the list after we
84	 * have started this walk, are not wrongly notified.
85	 */
86	for (nep = ntfy_list_head; nep != NULL; nep = nep->kn_next)
87		nelem++;
88
89	for (nep = ntfy_list_head; (nep != NULL && nelem); nep = nep->kn_next) {
90		nelem--;
91
92		/*
93		 * Check if this client is interested in the
94		 * event.
95		 */
96		if (!(nep->kn_event_mask & event))
97			continue;
98
99		mutex_enter(&nep->kn_lock);
100		nep->kn_state = NTFY_RUNNING;
101		mutex_exit(&nep->kn_lock);
102		mutex_exit(&ntfy_list_lock);
103
104		/*
105		 * We invoke the callback routine with no locks held. Another
106		 * client could have joined the list meanwhile. This is fine
107		 * as we maintain nelem as stated above. The NULL check in the
108		 * for loop guards against shrinkage. Also, any callers of
109		 * crypto_unnotify_events() at this point cv_wait till kn_state
110		 * changes to NTFY_WAITING. Hence, nep is assured to be valid.
111		 */
112		(*nep->kn_func)(event, event_arg);
113
114		mutex_enter(&nep->kn_lock);
115		nep->kn_state = NTFY_WAITING;
116		cv_broadcast(&nep->kn_cv);
117		mutex_exit(&nep->kn_lock);
118
119		mutex_enter(&ntfy_list_lock);
120	}
121
122	mutex_exit(&ntfy_list_lock);
123}
124
125#if defined(_KERNEL)
126EXPORT_SYMBOL(crypto_mech2id);
127#endif
128