1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /* Management for virtio crypto devices (refer to adf_dev_mgr.c)
3 *
4 * Copyright 2016 HUAWEI TECHNOLOGIES CO., LTD.
5 */
6
7 #include <linux/mutex.h>
8 #include <linux/list.h>
9 #include <linux/module.h>
10
11 #include <uapi/linux/virtio_crypto.h>
12 #include "virtio_crypto_common.h"
13
14 static LIST_HEAD(virtio_crypto_table);
15 static uint32_t num_devices;
16
17 /* The table_lock protects the above global list and num_devices */
18 static DEFINE_MUTEX(table_lock);
19
20 #define VIRTIO_CRYPTO_MAX_DEVICES 32
21
22
23 /*
24 * virtcrypto_devmgr_add_dev() - Add vcrypto_dev to the acceleration
25 * framework.
26 * @vcrypto_dev: Pointer to virtio crypto device.
27 *
28 * Function adds virtio crypto device to the global list.
29 * To be used by virtio crypto device specific drivers.
30 *
31 * Return: 0 on success, error code othewise.
32 */
virtcrypto_devmgr_add_dev(struct virtio_crypto * vcrypto_dev)33 int virtcrypto_devmgr_add_dev(struct virtio_crypto *vcrypto_dev)
34 {
35 struct list_head *itr;
36
37 mutex_lock(&table_lock);
38 if (num_devices == VIRTIO_CRYPTO_MAX_DEVICES) {
39 pr_info("virtio_crypto: only support up to %d devices\n",
40 VIRTIO_CRYPTO_MAX_DEVICES);
41 mutex_unlock(&table_lock);
42 return -EFAULT;
43 }
44
45 list_for_each(itr, &virtio_crypto_table) {
46 struct virtio_crypto *ptr =
47 list_entry(itr, struct virtio_crypto, list);
48
49 if (ptr == vcrypto_dev) {
50 mutex_unlock(&table_lock);
51 return -EEXIST;
52 }
53 }
54 atomic_set(&vcrypto_dev->ref_count, 0);
55 list_add_tail(&vcrypto_dev->list, &virtio_crypto_table);
56 vcrypto_dev->dev_id = num_devices++;
57 mutex_unlock(&table_lock);
58 return 0;
59 }
60
virtcrypto_devmgr_get_head(void)61 struct list_head *virtcrypto_devmgr_get_head(void)
62 {
63 return &virtio_crypto_table;
64 }
65
66 /*
67 * virtcrypto_devmgr_rm_dev() - Remove vcrypto_dev from the acceleration
68 * framework.
69 * @vcrypto_dev: Pointer to virtio crypto device.
70 *
71 * Function removes virtio crypto device from the acceleration framework.
72 * To be used by virtio crypto device specific drivers.
73 *
74 * Return: void
75 */
virtcrypto_devmgr_rm_dev(struct virtio_crypto * vcrypto_dev)76 void virtcrypto_devmgr_rm_dev(struct virtio_crypto *vcrypto_dev)
77 {
78 mutex_lock(&table_lock);
79 list_del(&vcrypto_dev->list);
80 num_devices--;
81 mutex_unlock(&table_lock);
82 }
83
84 /*
85 * virtcrypto_dev_get() - Increment vcrypto_dev reference count
86 * @vcrypto_dev: Pointer to virtio crypto device.
87 *
88 * Increment the vcrypto_dev refcount and if this is the first time
89 * incrementing it during this period the vcrypto_dev is in use,
90 * increment the module refcount too.
91 * To be used by virtio crypto device specific drivers.
92 *
93 * Return: 0 when successful, EFAULT when fail to bump module refcount
94 */
virtcrypto_dev_get(struct virtio_crypto * vcrypto_dev)95 int virtcrypto_dev_get(struct virtio_crypto *vcrypto_dev)
96 {
97 if (atomic_add_return(1, &vcrypto_dev->ref_count) == 1)
98 if (!try_module_get(vcrypto_dev->owner))
99 return -EFAULT;
100 return 0;
101 }
102
103 /*
104 * virtcrypto_dev_put() - Decrement vcrypto_dev reference count
105 * @vcrypto_dev: Pointer to virtio crypto device.
106 *
107 * Decrement the vcrypto_dev refcount and if this is the last time
108 * decrementing it during this period the vcrypto_dev is in use,
109 * decrement the module refcount too.
110 * To be used by virtio crypto device specific drivers.
111 *
112 * Return: void
113 */
virtcrypto_dev_put(struct virtio_crypto * vcrypto_dev)114 void virtcrypto_dev_put(struct virtio_crypto *vcrypto_dev)
115 {
116 if (atomic_sub_return(1, &vcrypto_dev->ref_count) == 0)
117 module_put(vcrypto_dev->owner);
118 }
119
120 /*
121 * virtcrypto_dev_started() - Check whether device has started
122 * @vcrypto_dev: Pointer to virtio crypto device.
123 *
124 * To be used by virtio crypto device specific drivers.
125 *
126 * Return: 1 when the device has started, 0 otherwise
127 */
virtcrypto_dev_started(struct virtio_crypto * vcrypto_dev)128 int virtcrypto_dev_started(struct virtio_crypto *vcrypto_dev)
129 {
130 return (vcrypto_dev->status & VIRTIO_CRYPTO_S_HW_READY);
131 }
132
133 /*
134 * virtcrypto_get_dev_node() - Get vcrypto_dev on the node.
135 * @node: Node id the driver works.
136 * @service: Crypto service that needs to be supported by the
137 * dev
138 * @algo: The algorithm number that needs to be supported by the
139 * dev
140 *
141 * Function returns the virtio crypto device used fewest on the node,
142 * and supports the given crypto service and algorithm.
143 *
144 * To be used by virtio crypto device specific drivers.
145 *
146 * Return: pointer to vcrypto_dev or NULL if not found.
147 */
virtcrypto_get_dev_node(int node,uint32_t service,uint32_t algo)148 struct virtio_crypto *virtcrypto_get_dev_node(int node, uint32_t service,
149 uint32_t algo)
150 {
151 struct virtio_crypto *vcrypto_dev = NULL, *tmp_dev;
152 unsigned long best = ~0;
153 unsigned long ctr;
154
155 mutex_lock(&table_lock);
156 list_for_each_entry(tmp_dev, virtcrypto_devmgr_get_head(), list) {
157
158 if ((node == dev_to_node(&tmp_dev->vdev->dev) ||
159 dev_to_node(&tmp_dev->vdev->dev) < 0) &&
160 virtcrypto_dev_started(tmp_dev) &&
161 virtcrypto_algo_is_supported(tmp_dev, service, algo)) {
162 ctr = atomic_read(&tmp_dev->ref_count);
163 if (best > ctr) {
164 vcrypto_dev = tmp_dev;
165 best = ctr;
166 }
167 }
168 }
169
170 if (!vcrypto_dev) {
171 pr_info("virtio_crypto: Could not find a device on node %d\n",
172 node);
173 /* Get any started device */
174 list_for_each_entry(tmp_dev,
175 virtcrypto_devmgr_get_head(), list) {
176 if (virtcrypto_dev_started(tmp_dev) &&
177 virtcrypto_algo_is_supported(tmp_dev,
178 service, algo)) {
179 vcrypto_dev = tmp_dev;
180 break;
181 }
182 }
183 }
184 mutex_unlock(&table_lock);
185 if (!vcrypto_dev)
186 return NULL;
187
188 virtcrypto_dev_get(vcrypto_dev);
189 return vcrypto_dev;
190 }
191
192 /*
193 * virtcrypto_dev_start() - Start virtio crypto device
194 * @vcrypto: Pointer to virtio crypto device.
195 *
196 * Function notifies all the registered services that the virtio crypto device
197 * is ready to be used.
198 * To be used by virtio crypto device specific drivers.
199 *
200 * Return: 0 on success, EFAULT when fail to register algorithms
201 */
virtcrypto_dev_start(struct virtio_crypto * vcrypto)202 int virtcrypto_dev_start(struct virtio_crypto *vcrypto)
203 {
204 if (virtio_crypto_skcipher_algs_register(vcrypto)) {
205 pr_err("virtio_crypto: Failed to register crypto skcipher algs\n");
206 return -EFAULT;
207 }
208
209 if (virtio_crypto_akcipher_algs_register(vcrypto)) {
210 pr_err("virtio_crypto: Failed to register crypto akcipher algs\n");
211 virtio_crypto_skcipher_algs_unregister(vcrypto);
212 return -EFAULT;
213 }
214
215 return 0;
216 }
217
218 /*
219 * virtcrypto_dev_stop() - Stop virtio crypto device
220 * @vcrypto: Pointer to virtio crypto device.
221 *
222 * Function notifies all the registered services that the virtio crypto device
223 * shall no longer be used.
224 * To be used by virtio crypto device specific drivers.
225 *
226 * Return: void
227 */
virtcrypto_dev_stop(struct virtio_crypto * vcrypto)228 void virtcrypto_dev_stop(struct virtio_crypto *vcrypto)
229 {
230 virtio_crypto_skcipher_algs_unregister(vcrypto);
231 virtio_crypto_akcipher_algs_unregister(vcrypto);
232 }
233
234 /*
235 * vcrypto_algo_is_supported()
236 * @vcrypto: Pointer to virtio crypto device.
237 * @service: The bit number for service validate.
238 * See VIRTIO_CRYPTO_SERVICE_*
239 * @algo : The bit number for the algorithm to validate.
240 *
241 *
242 * Validate if the virtio crypto device supports a service and
243 * algo.
244 *
245 * Return true if device supports a service and algo.
246 */
247
virtcrypto_algo_is_supported(struct virtio_crypto * vcrypto,uint32_t service,uint32_t algo)248 bool virtcrypto_algo_is_supported(struct virtio_crypto *vcrypto,
249 uint32_t service,
250 uint32_t algo)
251 {
252 uint32_t service_mask = 1u << service;
253 uint32_t algo_mask = 0;
254 bool low = true;
255
256 if (algo > 31) {
257 algo -= 32;
258 low = false;
259 }
260
261 if (!(vcrypto->crypto_services & service_mask))
262 return false;
263
264 switch (service) {
265 case VIRTIO_CRYPTO_SERVICE_CIPHER:
266 if (low)
267 algo_mask = vcrypto->cipher_algo_l;
268 else
269 algo_mask = vcrypto->cipher_algo_h;
270 break;
271
272 case VIRTIO_CRYPTO_SERVICE_HASH:
273 algo_mask = vcrypto->hash_algo;
274 break;
275
276 case VIRTIO_CRYPTO_SERVICE_MAC:
277 if (low)
278 algo_mask = vcrypto->mac_algo_l;
279 else
280 algo_mask = vcrypto->mac_algo_h;
281 break;
282
283 case VIRTIO_CRYPTO_SERVICE_AEAD:
284 algo_mask = vcrypto->aead_algo;
285 break;
286
287 case VIRTIO_CRYPTO_SERVICE_AKCIPHER:
288 algo_mask = vcrypto->akcipher_algo;
289 break;
290 }
291
292 if (!(algo_mask & (1u << algo)))
293 return false;
294
295 return true;
296 }
297