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 26 static LIST_HEAD(virtio_crypto_table); 27 static uint32_t num_devices; 28 29 /* The table_lock protects the above global list and num_devices */ 30 static 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 */ 45 int 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 73 struct 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 */ 88 void 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 */ 106 struct 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 */ 127 int 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 */ 143 int 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 */ 162 void 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 */ 176 int 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 */ 191 struct 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 */ 241 int 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 */ 261 void virtcrypto_dev_stop(struct virtio_crypto *vcrypto) 262 { 263 virtio_crypto_algs_unregister(); 264 } 265