aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/crypto/virtio/virtio_crypto_mgr.c
diff options
context:
space:
mode:
authorGonglei <arei.gonglei@huawei.com>2016-12-14 21:03:16 -0500
committerMichael S. Tsirkin <mst@redhat.com>2016-12-15 17:13:32 -0500
commitdbaf0624ffa57ae6e7d87a823185ccd9a7852d3c (patch)
treebca0d89ad92a6907449fcddcf0aa4ae60dc5e912 /drivers/crypto/virtio/virtio_crypto_mgr.c
parent809ecb9bca6a9424ccd392d67e368160f8b76c92 (diff)
crypto: add virtio-crypto driver
This patch introduces virtio-crypto driver for Linux Kernel. The virtio crypto device is a virtual cryptography device as well as a kind of virtual hardware accelerator for virtual machines. The encryption anddecryption requests are placed in the data queue and are ultimately handled by thebackend crypto accelerators. The second queue is the control queue used to create or destroy sessions for symmetric algorithms and will control some advanced features in the future. The virtio crypto device provides the following cryptoservices: CIPHER, MAC, HASH, and AEAD. For more information about virtio-crypto device, please see: http://qemu-project.org/Features/VirtioCrypto CC: Michael S. Tsirkin <mst@redhat.com> CC: Cornelia Huck <cornelia.huck@de.ibm.com> CC: Stefan Hajnoczi <stefanha@redhat.com> CC: Herbert Xu <herbert@gondor.apana.org.au> CC: Halil Pasic <pasic@linux.vnet.ibm.com> CC: David S. Miller <davem@davemloft.net> CC: Zeng Xin <xin.zeng@intel.com> Signed-off-by: Gonglei <arei.gonglei@huawei.com> Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Diffstat (limited to 'drivers/crypto/virtio/virtio_crypto_mgr.c')
-rw-r--r--drivers/crypto/virtio/virtio_crypto_mgr.c264
1 files changed, 264 insertions, 0 deletions
diff --git a/drivers/crypto/virtio/virtio_crypto_mgr.c b/drivers/crypto/virtio/virtio_crypto_mgr.c
new file mode 100644
index 000000000000..a69ff71de2c4
--- /dev/null
+++ b/drivers/crypto/virtio/virtio_crypto_mgr.c
@@ -0,0 +1,264 @@
1 /* Management for virtio crypto devices (refer to adf_dev_mgr.c)
2 *
3 * Copyright 2016 HUAWEI TECHNOLOGIES CO., LTD.
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, see <http://www.gnu.org/licenses/>.
17 */
18
19#include <linux/mutex.h>
20#include <linux/list.h>
21#include <linux/module.h>
22
23#include <uapi/linux/virtio_crypto.h>
24#include "virtio_crypto_common.h"
25
26static LIST_HEAD(virtio_crypto_table);
27static uint32_t num_devices;
28
29/* The table_lock protects the above global list and num_devices */
30static DEFINE_MUTEX(table_lock);
31
32#define VIRTIO_CRYPTO_MAX_DEVICES 32
33
34
35/*
36 * virtcrypto_devmgr_add_dev() - Add vcrypto_dev to the acceleration
37 * framework.
38 * @vcrypto_dev: Pointer to virtio crypto device.
39 *
40 * Function adds virtio crypto device to the global list.
41 * To be used by virtio crypto device specific drivers.
42 *
43 * Return: 0 on success, error code othewise.
44 */
45int virtcrypto_devmgr_add_dev(struct virtio_crypto *vcrypto_dev)
46{
47 struct list_head *itr;
48
49 mutex_lock(&table_lock);
50 if (num_devices == VIRTIO_CRYPTO_MAX_DEVICES) {
51 pr_info("virtio_crypto: only support up to %d devices\n",
52 VIRTIO_CRYPTO_MAX_DEVICES);
53 mutex_unlock(&table_lock);
54 return -EFAULT;
55 }
56
57 list_for_each(itr, &virtio_crypto_table) {
58 struct virtio_crypto *ptr =
59 list_entry(itr, struct virtio_crypto, list);
60
61 if (ptr == vcrypto_dev) {
62 mutex_unlock(&table_lock);
63 return -EEXIST;
64 }
65 }
66 atomic_set(&vcrypto_dev->ref_count, 0);
67 list_add_tail(&vcrypto_dev->list, &virtio_crypto_table);
68 vcrypto_dev->dev_id = num_devices++;
69 mutex_unlock(&table_lock);
70 return 0;
71}
72
73struct list_head *virtcrypto_devmgr_get_head(void)
74{
75 return &virtio_crypto_table;
76}
77
78/*
79 * virtcrypto_devmgr_rm_dev() - Remove vcrypto_dev from the acceleration
80 * framework.
81 * @vcrypto_dev: Pointer to virtio crypto device.
82 *
83 * Function removes virtio crypto device from the acceleration framework.
84 * To be used by virtio crypto device specific drivers.
85 *
86 * Return: void
87 */
88void virtcrypto_devmgr_rm_dev(struct virtio_crypto *vcrypto_dev)
89{
90 mutex_lock(&table_lock);
91 list_del(&vcrypto_dev->list);
92 num_devices--;
93 mutex_unlock(&table_lock);
94}
95
96/*
97 * virtcrypto_devmgr_get_first()
98 *
99 * Function returns the first virtio crypto device from the acceleration
100 * framework.
101 *
102 * To be used by virtio crypto device specific drivers.
103 *
104 * Return: pointer to vcrypto_dev or NULL if not found.
105 */
106struct virtio_crypto *virtcrypto_devmgr_get_first(void)
107{
108 struct virtio_crypto *dev = NULL;
109
110 mutex_lock(&table_lock);
111 if (!list_empty(&virtio_crypto_table))
112 dev = list_first_entry(&virtio_crypto_table,
113 struct virtio_crypto,
114 list);
115 mutex_unlock(&table_lock);
116 return dev;
117}
118
119/*
120 * virtcrypto_dev_in_use() - Check whether vcrypto_dev is currently in use
121 * @vcrypto_dev: Pointer to virtio crypto device.
122 *
123 * To be used by virtio crypto device specific drivers.
124 *
125 * Return: 1 when device is in use, 0 otherwise.
126 */
127int virtcrypto_dev_in_use(struct virtio_crypto *vcrypto_dev)
128{
129 return atomic_read(&vcrypto_dev->ref_count) != 0;
130}
131
132/*
133 * virtcrypto_dev_get() - Increment vcrypto_dev reference count
134 * @vcrypto_dev: Pointer to virtio crypto device.
135 *
136 * Increment the vcrypto_dev refcount and if this is the first time
137 * incrementing it during this period the vcrypto_dev is in use,
138 * increment the module refcount too.
139 * To be used by virtio crypto device specific drivers.
140 *
141 * Return: 0 when successful, EFAULT when fail to bump module refcount
142 */
143int virtcrypto_dev_get(struct virtio_crypto *vcrypto_dev)
144{
145 if (atomic_add_return(1, &vcrypto_dev->ref_count) == 1)
146 if (!try_module_get(vcrypto_dev->owner))
147 return -EFAULT;
148 return 0;
149}
150
151/*
152 * virtcrypto_dev_put() - Decrement vcrypto_dev reference count
153 * @vcrypto_dev: Pointer to virtio crypto device.
154 *
155 * Decrement the vcrypto_dev refcount and if this is the last time
156 * decrementing it during this period the vcrypto_dev is in use,
157 * decrement the module refcount too.
158 * To be used by virtio crypto device specific drivers.
159 *
160 * Return: void
161 */
162void virtcrypto_dev_put(struct virtio_crypto *vcrypto_dev)
163{
164 if (atomic_sub_return(1, &vcrypto_dev->ref_count) == 0)
165 module_put(vcrypto_dev->owner);
166}
167
168/*
169 * virtcrypto_dev_started() - Check whether device has started
170 * @vcrypto_dev: Pointer to virtio crypto device.
171 *
172 * To be used by virtio crypto device specific drivers.
173 *
174 * Return: 1 when the device has started, 0 otherwise
175 */
176int virtcrypto_dev_started(struct virtio_crypto *vcrypto_dev)
177{
178 return (vcrypto_dev->status & VIRTIO_CRYPTO_S_HW_READY);
179}
180
181/*
182 * virtcrypto_get_dev_node() - Get vcrypto_dev on the node.
183 * @node: Node id the driver works.
184 *
185 * Function returns the virtio crypto device used fewest on the node.
186 *
187 * To be used by virtio crypto device specific drivers.
188 *
189 * Return: pointer to vcrypto_dev or NULL if not found.
190 */
191struct virtio_crypto *virtcrypto_get_dev_node(int node)
192{
193 struct virtio_crypto *vcrypto_dev = NULL, *tmp_dev;
194 unsigned long best = ~0;
195 unsigned long ctr;
196
197 mutex_lock(&table_lock);
198 list_for_each_entry(tmp_dev, virtcrypto_devmgr_get_head(), list) {
199
200 if ((node == dev_to_node(&tmp_dev->vdev->dev) ||
201 dev_to_node(&tmp_dev->vdev->dev) < 0) &&
202 virtcrypto_dev_started(tmp_dev)) {
203 ctr = atomic_read(&tmp_dev->ref_count);
204 if (best > ctr) {
205 vcrypto_dev = tmp_dev;
206 best = ctr;
207 }
208 }
209 }
210
211 if (!vcrypto_dev) {
212 pr_info("virtio_crypto: Could not find a device on node %d\n",
213 node);
214 /* Get any started device */
215 list_for_each_entry(tmp_dev,
216 virtcrypto_devmgr_get_head(), list) {
217 if (virtcrypto_dev_started(tmp_dev)) {
218 vcrypto_dev = tmp_dev;
219 break;
220 }
221 }
222 }
223 mutex_unlock(&table_lock);
224 if (!vcrypto_dev)
225 return NULL;
226
227 virtcrypto_dev_get(vcrypto_dev);
228 return vcrypto_dev;
229}
230
231/*
232 * virtcrypto_dev_start() - Start virtio crypto device
233 * @vcrypto: Pointer to virtio crypto device.
234 *
235 * Function notifies all the registered services that the virtio crypto device
236 * is ready to be used.
237 * To be used by virtio crypto device specific drivers.
238 *
239 * Return: 0 on success, EFAULT when fail to register algorithms
240 */
241int virtcrypto_dev_start(struct virtio_crypto *vcrypto)
242{
243 if (virtio_crypto_algs_register()) {
244 pr_err("virtio_crypto: Failed to register crypto algs\n");
245 return -EFAULT;
246 }
247
248 return 0;
249}
250
251/*
252 * virtcrypto_dev_stop() - Stop virtio crypto device
253 * @vcrypto: Pointer to virtio crypto device.
254 *
255 * Function notifies all the registered services that the virtio crypto device
256 * is ready to be used.
257 * To be used by virtio crypto device specific drivers.
258 *
259 * Return: void
260 */
261void virtcrypto_dev_stop(struct virtio_crypto *vcrypto)
262{
263 virtio_crypto_algs_unregister();
264}