Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v4.10 476 lines 11 kB view raw
1 /* Driver for Virtio crypto device. 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/err.h> 20#include <linux/module.h> 21#include <linux/virtio_config.h> 22#include <linux/cpu.h> 23 24#include <uapi/linux/virtio_crypto.h> 25#include "virtio_crypto_common.h" 26 27 28static void 29virtcrypto_clear_request(struct virtio_crypto_request *vc_req) 30{ 31 if (vc_req) { 32 kzfree(vc_req->iv); 33 kzfree(vc_req->req_data); 34 kfree(vc_req->sgs); 35 } 36} 37 38static void virtcrypto_dataq_callback(struct virtqueue *vq) 39{ 40 struct virtio_crypto *vcrypto = vq->vdev->priv; 41 struct virtio_crypto_request *vc_req; 42 unsigned long flags; 43 unsigned int len; 44 struct ablkcipher_request *ablk_req; 45 int error; 46 unsigned int qid = vq->index; 47 48 spin_lock_irqsave(&vcrypto->data_vq[qid].lock, flags); 49 do { 50 virtqueue_disable_cb(vq); 51 while ((vc_req = virtqueue_get_buf(vq, &len)) != NULL) { 52 if (vc_req->type == VIRTIO_CRYPTO_SYM_OP_CIPHER) { 53 switch (vc_req->status) { 54 case VIRTIO_CRYPTO_OK: 55 error = 0; 56 break; 57 case VIRTIO_CRYPTO_INVSESS: 58 case VIRTIO_CRYPTO_ERR: 59 error = -EINVAL; 60 break; 61 case VIRTIO_CRYPTO_BADMSG: 62 error = -EBADMSG; 63 break; 64 default: 65 error = -EIO; 66 break; 67 } 68 ablk_req = vc_req->ablkcipher_req; 69 virtcrypto_clear_request(vc_req); 70 71 spin_unlock_irqrestore( 72 &vcrypto->data_vq[qid].lock, flags); 73 /* Finish the encrypt or decrypt process */ 74 ablk_req->base.complete(&ablk_req->base, error); 75 spin_lock_irqsave( 76 &vcrypto->data_vq[qid].lock, flags); 77 } 78 } 79 } while (!virtqueue_enable_cb(vq)); 80 spin_unlock_irqrestore(&vcrypto->data_vq[qid].lock, flags); 81} 82 83static int virtcrypto_find_vqs(struct virtio_crypto *vi) 84{ 85 vq_callback_t **callbacks; 86 struct virtqueue **vqs; 87 int ret = -ENOMEM; 88 int i, total_vqs; 89 const char **names; 90 91 /* 92 * We expect 1 data virtqueue, followed by 93 * possible N-1 data queues used in multiqueue mode, 94 * followed by control vq. 95 */ 96 total_vqs = vi->max_data_queues + 1; 97 98 /* Allocate space for find_vqs parameters */ 99 vqs = kcalloc(total_vqs, sizeof(*vqs), GFP_KERNEL); 100 if (!vqs) 101 goto err_vq; 102 callbacks = kcalloc(total_vqs, sizeof(*callbacks), GFP_KERNEL); 103 if (!callbacks) 104 goto err_callback; 105 names = kcalloc(total_vqs, sizeof(*names), GFP_KERNEL); 106 if (!names) 107 goto err_names; 108 109 /* Parameters for control virtqueue */ 110 callbacks[total_vqs - 1] = NULL; 111 names[total_vqs - 1] = "controlq"; 112 113 /* Allocate/initialize parameters for data virtqueues */ 114 for (i = 0; i < vi->max_data_queues; i++) { 115 callbacks[i] = virtcrypto_dataq_callback; 116 snprintf(vi->data_vq[i].name, sizeof(vi->data_vq[i].name), 117 "dataq.%d", i); 118 names[i] = vi->data_vq[i].name; 119 } 120 121 ret = vi->vdev->config->find_vqs(vi->vdev, total_vqs, vqs, callbacks, 122 names); 123 if (ret) 124 goto err_find; 125 126 vi->ctrl_vq = vqs[total_vqs - 1]; 127 128 for (i = 0; i < vi->max_data_queues; i++) { 129 spin_lock_init(&vi->data_vq[i].lock); 130 vi->data_vq[i].vq = vqs[i]; 131 } 132 133 kfree(names); 134 kfree(callbacks); 135 kfree(vqs); 136 137 return 0; 138 139err_find: 140 kfree(names); 141err_names: 142 kfree(callbacks); 143err_callback: 144 kfree(vqs); 145err_vq: 146 return ret; 147} 148 149static int virtcrypto_alloc_queues(struct virtio_crypto *vi) 150{ 151 vi->data_vq = kcalloc(vi->max_data_queues, sizeof(*vi->data_vq), 152 GFP_KERNEL); 153 if (!vi->data_vq) 154 return -ENOMEM; 155 156 return 0; 157} 158 159static void virtcrypto_clean_affinity(struct virtio_crypto *vi, long hcpu) 160{ 161 int i; 162 163 if (vi->affinity_hint_set) { 164 for (i = 0; i < vi->max_data_queues; i++) 165 virtqueue_set_affinity(vi->data_vq[i].vq, -1); 166 167 vi->affinity_hint_set = false; 168 } 169} 170 171static void virtcrypto_set_affinity(struct virtio_crypto *vcrypto) 172{ 173 int i = 0; 174 int cpu; 175 176 /* 177 * In single queue mode, we don't set the cpu affinity. 178 */ 179 if (vcrypto->curr_queue == 1 || vcrypto->max_data_queues == 1) { 180 virtcrypto_clean_affinity(vcrypto, -1); 181 return; 182 } 183 184 /* 185 * In multiqueue mode, we let the queue to be private to one cpu 186 * by setting the affinity hint to eliminate the contention. 187 * 188 * TODO: adds cpu hotplug support by register cpu notifier. 189 * 190 */ 191 for_each_online_cpu(cpu) { 192 virtqueue_set_affinity(vcrypto->data_vq[i].vq, cpu); 193 if (++i >= vcrypto->max_data_queues) 194 break; 195 } 196 197 vcrypto->affinity_hint_set = true; 198} 199 200static void virtcrypto_free_queues(struct virtio_crypto *vi) 201{ 202 kfree(vi->data_vq); 203} 204 205static int virtcrypto_init_vqs(struct virtio_crypto *vi) 206{ 207 int ret; 208 209 /* Allocate send & receive queues */ 210 ret = virtcrypto_alloc_queues(vi); 211 if (ret) 212 goto err; 213 214 ret = virtcrypto_find_vqs(vi); 215 if (ret) 216 goto err_free; 217 218 get_online_cpus(); 219 virtcrypto_set_affinity(vi); 220 put_online_cpus(); 221 222 return 0; 223 224err_free: 225 virtcrypto_free_queues(vi); 226err: 227 return ret; 228} 229 230static int virtcrypto_update_status(struct virtio_crypto *vcrypto) 231{ 232 u32 status; 233 int err; 234 235 virtio_cread(vcrypto->vdev, 236 struct virtio_crypto_config, status, &status); 237 238 /* 239 * Unknown status bits would be a host error and the driver 240 * should consider the device to be broken. 241 */ 242 if (status & (~VIRTIO_CRYPTO_S_HW_READY)) { 243 dev_warn(&vcrypto->vdev->dev, 244 "Unknown status bits: 0x%x\n", status); 245 246 virtio_break_device(vcrypto->vdev); 247 return -EPERM; 248 } 249 250 if (vcrypto->status == status) 251 return 0; 252 253 vcrypto->status = status; 254 255 if (vcrypto->status & VIRTIO_CRYPTO_S_HW_READY) { 256 err = virtcrypto_dev_start(vcrypto); 257 if (err) { 258 dev_err(&vcrypto->vdev->dev, 259 "Failed to start virtio crypto device.\n"); 260 261 return -EPERM; 262 } 263 dev_info(&vcrypto->vdev->dev, "Accelerator is ready\n"); 264 } else { 265 virtcrypto_dev_stop(vcrypto); 266 dev_info(&vcrypto->vdev->dev, "Accelerator is not ready\n"); 267 } 268 269 return 0; 270} 271 272static void virtcrypto_del_vqs(struct virtio_crypto *vcrypto) 273{ 274 struct virtio_device *vdev = vcrypto->vdev; 275 276 virtcrypto_clean_affinity(vcrypto, -1); 277 278 vdev->config->del_vqs(vdev); 279 280 virtcrypto_free_queues(vcrypto); 281} 282 283static int virtcrypto_probe(struct virtio_device *vdev) 284{ 285 int err = -EFAULT; 286 struct virtio_crypto *vcrypto; 287 u32 max_data_queues = 0, max_cipher_key_len = 0; 288 u32 max_auth_key_len = 0; 289 u64 max_size = 0; 290 291 if (!virtio_has_feature(vdev, VIRTIO_F_VERSION_1)) 292 return -ENODEV; 293 294 if (!vdev->config->get) { 295 dev_err(&vdev->dev, "%s failure: config access disabled\n", 296 __func__); 297 return -EINVAL; 298 } 299 300 if (num_possible_nodes() > 1 && dev_to_node(&vdev->dev) < 0) { 301 /* 302 * If the accelerator is connected to a node with no memory 303 * there is no point in using the accelerator since the remote 304 * memory transaction will be very slow. 305 */ 306 dev_err(&vdev->dev, "Invalid NUMA configuration.\n"); 307 return -EINVAL; 308 } 309 310 vcrypto = kzalloc_node(sizeof(*vcrypto), GFP_KERNEL, 311 dev_to_node(&vdev->dev)); 312 if (!vcrypto) 313 return -ENOMEM; 314 315 virtio_cread(vdev, struct virtio_crypto_config, 316 max_dataqueues, &max_data_queues); 317 if (max_data_queues < 1) 318 max_data_queues = 1; 319 320 virtio_cread(vdev, struct virtio_crypto_config, 321 max_cipher_key_len, &max_cipher_key_len); 322 virtio_cread(vdev, struct virtio_crypto_config, 323 max_auth_key_len, &max_auth_key_len); 324 virtio_cread(vdev, struct virtio_crypto_config, 325 max_size, &max_size); 326 327 /* Add virtio crypto device to global table */ 328 err = virtcrypto_devmgr_add_dev(vcrypto); 329 if (err) { 330 dev_err(&vdev->dev, "Failed to add new virtio crypto device.\n"); 331 goto free; 332 } 333 vcrypto->owner = THIS_MODULE; 334 vcrypto = vdev->priv = vcrypto; 335 vcrypto->vdev = vdev; 336 337 spin_lock_init(&vcrypto->ctrl_lock); 338 339 /* Use single data queue as default */ 340 vcrypto->curr_queue = 1; 341 vcrypto->max_data_queues = max_data_queues; 342 vcrypto->max_cipher_key_len = max_cipher_key_len; 343 vcrypto->max_auth_key_len = max_auth_key_len; 344 vcrypto->max_size = max_size; 345 346 dev_info(&vdev->dev, 347 "max_queues: %u, max_cipher_key_len: %u, max_auth_key_len: %u, max_size 0x%llx\n", 348 vcrypto->max_data_queues, 349 vcrypto->max_cipher_key_len, 350 vcrypto->max_auth_key_len, 351 vcrypto->max_size); 352 353 err = virtcrypto_init_vqs(vcrypto); 354 if (err) { 355 dev_err(&vdev->dev, "Failed to initialize vqs.\n"); 356 goto free_dev; 357 } 358 virtio_device_ready(vdev); 359 360 err = virtcrypto_update_status(vcrypto); 361 if (err) 362 goto free_vqs; 363 364 return 0; 365 366free_vqs: 367 vcrypto->vdev->config->reset(vdev); 368 virtcrypto_del_vqs(vcrypto); 369free_dev: 370 virtcrypto_devmgr_rm_dev(vcrypto); 371free: 372 kfree(vcrypto); 373 return err; 374} 375 376static void virtcrypto_free_unused_reqs(struct virtio_crypto *vcrypto) 377{ 378 struct virtio_crypto_request *vc_req; 379 int i; 380 struct virtqueue *vq; 381 382 for (i = 0; i < vcrypto->max_data_queues; i++) { 383 vq = vcrypto->data_vq[i].vq; 384 while ((vc_req = virtqueue_detach_unused_buf(vq)) != NULL) { 385 kfree(vc_req->req_data); 386 kfree(vc_req->sgs); 387 } 388 } 389} 390 391static void virtcrypto_remove(struct virtio_device *vdev) 392{ 393 struct virtio_crypto *vcrypto = vdev->priv; 394 395 dev_info(&vdev->dev, "Start virtcrypto_remove.\n"); 396 397 if (virtcrypto_dev_started(vcrypto)) 398 virtcrypto_dev_stop(vcrypto); 399 vdev->config->reset(vdev); 400 virtcrypto_free_unused_reqs(vcrypto); 401 virtcrypto_del_vqs(vcrypto); 402 virtcrypto_devmgr_rm_dev(vcrypto); 403 kfree(vcrypto); 404} 405 406static void virtcrypto_config_changed(struct virtio_device *vdev) 407{ 408 struct virtio_crypto *vcrypto = vdev->priv; 409 410 virtcrypto_update_status(vcrypto); 411} 412 413#ifdef CONFIG_PM_SLEEP 414static int virtcrypto_freeze(struct virtio_device *vdev) 415{ 416 struct virtio_crypto *vcrypto = vdev->priv; 417 418 vdev->config->reset(vdev); 419 virtcrypto_free_unused_reqs(vcrypto); 420 if (virtcrypto_dev_started(vcrypto)) 421 virtcrypto_dev_stop(vcrypto); 422 423 virtcrypto_del_vqs(vcrypto); 424 return 0; 425} 426 427static int virtcrypto_restore(struct virtio_device *vdev) 428{ 429 struct virtio_crypto *vcrypto = vdev->priv; 430 int err; 431 432 err = virtcrypto_init_vqs(vcrypto); 433 if (err) 434 return err; 435 436 virtio_device_ready(vdev); 437 err = virtcrypto_dev_start(vcrypto); 438 if (err) { 439 dev_err(&vdev->dev, "Failed to start virtio crypto device.\n"); 440 return -EFAULT; 441 } 442 443 return 0; 444} 445#endif 446 447static unsigned int features[] = { 448 /* none */ 449}; 450 451static struct virtio_device_id id_table[] = { 452 { VIRTIO_ID_CRYPTO, VIRTIO_DEV_ANY_ID }, 453 { 0 }, 454}; 455 456static struct virtio_driver virtio_crypto_driver = { 457 .driver.name = KBUILD_MODNAME, 458 .driver.owner = THIS_MODULE, 459 .feature_table = features, 460 .feature_table_size = ARRAY_SIZE(features), 461 .id_table = id_table, 462 .probe = virtcrypto_probe, 463 .remove = virtcrypto_remove, 464 .config_changed = virtcrypto_config_changed, 465#ifdef CONFIG_PM_SLEEP 466 .freeze = virtcrypto_freeze, 467 .restore = virtcrypto_restore, 468#endif 469}; 470 471module_virtio_driver(virtio_crypto_driver); 472 473MODULE_DEVICE_TABLE(virtio, id_table); 474MODULE_DESCRIPTION("virtio crypto device driver"); 475MODULE_LICENSE("GPL"); 476MODULE_AUTHOR("Gonglei <arei.gonglei@huawei.com>");