diff options
Diffstat (limited to 'crypto/pcrypt.c')
-rw-r--r-- | crypto/pcrypt.c | 241 |
1 files changed, 183 insertions, 58 deletions
diff --git a/crypto/pcrypt.c b/crypto/pcrypt.c index 247178cb98ec..de3078215fe6 100644 --- a/crypto/pcrypt.c +++ b/crypto/pcrypt.c | |||
@@ -24,12 +24,40 @@ | |||
24 | #include <linux/init.h> | 24 | #include <linux/init.h> |
25 | #include <linux/module.h> | 25 | #include <linux/module.h> |
26 | #include <linux/slab.h> | 26 | #include <linux/slab.h> |
27 | #include <linux/notifier.h> | ||
28 | #include <linux/kobject.h> | ||
29 | #include <linux/cpu.h> | ||
27 | #include <crypto/pcrypt.h> | 30 | #include <crypto/pcrypt.h> |
28 | 31 | ||
29 | static struct padata_instance *pcrypt_enc_padata; | 32 | struct padata_pcrypt { |
30 | static struct padata_instance *pcrypt_dec_padata; | 33 | struct padata_instance *pinst; |
31 | static struct workqueue_struct *encwq; | 34 | struct workqueue_struct *wq; |
32 | static struct workqueue_struct *decwq; | 35 | |
36 | /* | ||
37 | * Cpumask for callback CPUs. It should be | ||
38 | * equal to serial cpumask of corresponding padata instance, | ||
39 | * so it is updated when padata notifies us about serial | ||
40 | * cpumask change. | ||
41 | * | ||
42 | * cb_cpumask is protected by RCU. This fact prevents us from | ||
43 | * using cpumask_var_t directly because the actual type of | ||
44 | * cpumsak_var_t depends on kernel configuration(particularly on | ||
45 | * CONFIG_CPUMASK_OFFSTACK macro). Depending on the configuration | ||
46 | * cpumask_var_t may be either a pointer to the struct cpumask | ||
47 | * or a variable allocated on the stack. Thus we can not safely use | ||
48 | * cpumask_var_t with RCU operations such as rcu_assign_pointer or | ||
49 | * rcu_dereference. So cpumask_var_t is wrapped with struct | ||
50 | * pcrypt_cpumask which makes possible to use it with RCU. | ||
51 | */ | ||
52 | struct pcrypt_cpumask { | ||
53 | cpumask_var_t mask; | ||
54 | } *cb_cpumask; | ||
55 | struct notifier_block nblock; | ||
56 | }; | ||
57 | |||
58 | static struct padata_pcrypt pencrypt; | ||
59 | static struct padata_pcrypt pdecrypt; | ||
60 | static struct kset *pcrypt_kset; | ||
33 | 61 | ||
34 | struct pcrypt_instance_ctx { | 62 | struct pcrypt_instance_ctx { |
35 | struct crypto_spawn spawn; | 63 | struct crypto_spawn spawn; |
@@ -42,25 +70,32 @@ struct pcrypt_aead_ctx { | |||
42 | }; | 70 | }; |
43 | 71 | ||
44 | static int pcrypt_do_parallel(struct padata_priv *padata, unsigned int *cb_cpu, | 72 | static int pcrypt_do_parallel(struct padata_priv *padata, unsigned int *cb_cpu, |
45 | struct padata_instance *pinst) | 73 | struct padata_pcrypt *pcrypt) |
46 | { | 74 | { |
47 | unsigned int cpu_index, cpu, i; | 75 | unsigned int cpu_index, cpu, i; |
76 | struct pcrypt_cpumask *cpumask; | ||
48 | 77 | ||
49 | cpu = *cb_cpu; | 78 | cpu = *cb_cpu; |
50 | 79 | ||
51 | if (cpumask_test_cpu(cpu, cpu_active_mask)) | 80 | rcu_read_lock_bh(); |
81 | cpumask = rcu_dereference(pcrypt->cb_cpumask); | ||
82 | if (cpumask_test_cpu(cpu, cpumask->mask)) | ||
83 | goto out; | ||
84 | |||
85 | if (!cpumask_weight(cpumask->mask)) | ||
52 | goto out; | 86 | goto out; |
53 | 87 | ||
54 | cpu_index = cpu % cpumask_weight(cpu_active_mask); | 88 | cpu_index = cpu % cpumask_weight(cpumask->mask); |
55 | 89 | ||
56 | cpu = cpumask_first(cpu_active_mask); | 90 | cpu = cpumask_first(cpumask->mask); |
57 | for (i = 0; i < cpu_index; i++) | 91 | for (i = 0; i < cpu_index; i++) |
58 | cpu = cpumask_next(cpu, cpu_active_mask); | 92 | cpu = cpumask_next(cpu, cpumask->mask); |
59 | 93 | ||
60 | *cb_cpu = cpu; | 94 | *cb_cpu = cpu; |
61 | 95 | ||
62 | out: | 96 | out: |
63 | return padata_do_parallel(pinst, padata, cpu); | 97 | rcu_read_unlock_bh(); |
98 | return padata_do_parallel(pcrypt->pinst, padata, cpu); | ||
64 | } | 99 | } |
65 | 100 | ||
66 | static int pcrypt_aead_setkey(struct crypto_aead *parent, | 101 | static int pcrypt_aead_setkey(struct crypto_aead *parent, |
@@ -142,11 +177,9 @@ static int pcrypt_aead_encrypt(struct aead_request *req) | |||
142 | req->cryptlen, req->iv); | 177 | req->cryptlen, req->iv); |
143 | aead_request_set_assoc(creq, req->assoc, req->assoclen); | 178 | aead_request_set_assoc(creq, req->assoc, req->assoclen); |
144 | 179 | ||
145 | err = pcrypt_do_parallel(padata, &ctx->cb_cpu, pcrypt_enc_padata); | 180 | err = pcrypt_do_parallel(padata, &ctx->cb_cpu, &pencrypt); |
146 | if (err) | 181 | if (!err) |
147 | return err; | 182 | return -EINPROGRESS; |
148 | else | ||
149 | err = crypto_aead_encrypt(creq); | ||
150 | 183 | ||
151 | return err; | 184 | return err; |
152 | } | 185 | } |
@@ -186,11 +219,9 @@ static int pcrypt_aead_decrypt(struct aead_request *req) | |||
186 | req->cryptlen, req->iv); | 219 | req->cryptlen, req->iv); |
187 | aead_request_set_assoc(creq, req->assoc, req->assoclen); | 220 | aead_request_set_assoc(creq, req->assoc, req->assoclen); |
188 | 221 | ||
189 | err = pcrypt_do_parallel(padata, &ctx->cb_cpu, pcrypt_dec_padata); | 222 | err = pcrypt_do_parallel(padata, &ctx->cb_cpu, &pdecrypt); |
190 | if (err) | 223 | if (!err) |
191 | return err; | 224 | return -EINPROGRESS; |
192 | else | ||
193 | err = crypto_aead_decrypt(creq); | ||
194 | 225 | ||
195 | return err; | 226 | return err; |
196 | } | 227 | } |
@@ -232,11 +263,9 @@ static int pcrypt_aead_givencrypt(struct aead_givcrypt_request *req) | |||
232 | aead_givcrypt_set_assoc(creq, areq->assoc, areq->assoclen); | 263 | aead_givcrypt_set_assoc(creq, areq->assoc, areq->assoclen); |
233 | aead_givcrypt_set_giv(creq, req->giv, req->seq); | 264 | aead_givcrypt_set_giv(creq, req->giv, req->seq); |
234 | 265 | ||
235 | err = pcrypt_do_parallel(padata, &ctx->cb_cpu, pcrypt_enc_padata); | 266 | err = pcrypt_do_parallel(padata, &ctx->cb_cpu, &pencrypt); |
236 | if (err) | 267 | if (!err) |
237 | return err; | 268 | return -EINPROGRESS; |
238 | else | ||
239 | err = crypto_aead_givencrypt(creq); | ||
240 | 269 | ||
241 | return err; | 270 | return err; |
242 | } | 271 | } |
@@ -376,6 +405,115 @@ static void pcrypt_free(struct crypto_instance *inst) | |||
376 | kfree(inst); | 405 | kfree(inst); |
377 | } | 406 | } |
378 | 407 | ||
408 | static int pcrypt_cpumask_change_notify(struct notifier_block *self, | ||
409 | unsigned long val, void *data) | ||
410 | { | ||
411 | struct padata_pcrypt *pcrypt; | ||
412 | struct pcrypt_cpumask *new_mask, *old_mask; | ||
413 | struct padata_cpumask *cpumask = (struct padata_cpumask *)data; | ||
414 | |||
415 | if (!(val & PADATA_CPU_SERIAL)) | ||
416 | return 0; | ||
417 | |||
418 | pcrypt = container_of(self, struct padata_pcrypt, nblock); | ||
419 | new_mask = kmalloc(sizeof(*new_mask), GFP_KERNEL); | ||
420 | if (!new_mask) | ||
421 | return -ENOMEM; | ||
422 | if (!alloc_cpumask_var(&new_mask->mask, GFP_KERNEL)) { | ||
423 | kfree(new_mask); | ||
424 | return -ENOMEM; | ||
425 | } | ||
426 | |||
427 | old_mask = pcrypt->cb_cpumask; | ||
428 | |||
429 | cpumask_copy(new_mask->mask, cpumask->cbcpu); | ||
430 | rcu_assign_pointer(pcrypt->cb_cpumask, new_mask); | ||
431 | synchronize_rcu_bh(); | ||
432 | |||
433 | free_cpumask_var(old_mask->mask); | ||
434 | kfree(old_mask); | ||
435 | return 0; | ||
436 | } | ||
437 | |||
438 | static int pcrypt_sysfs_add(struct padata_instance *pinst, const char *name) | ||
439 | { | ||
440 | int ret; | ||
441 | |||
442 | pinst->kobj.kset = pcrypt_kset; | ||
443 | ret = kobject_add(&pinst->kobj, NULL, name); | ||
444 | if (!ret) | ||
445 | kobject_uevent(&pinst->kobj, KOBJ_ADD); | ||
446 | |||
447 | return ret; | ||
448 | } | ||
449 | |||
450 | static int pcrypt_init_padata(struct padata_pcrypt *pcrypt, | ||
451 | const char *name) | ||
452 | { | ||
453 | int ret = -ENOMEM; | ||
454 | struct pcrypt_cpumask *mask; | ||
455 | |||
456 | get_online_cpus(); | ||
457 | |||
458 | pcrypt->wq = create_workqueue(name); | ||
459 | if (!pcrypt->wq) | ||
460 | goto err; | ||
461 | |||
462 | pcrypt->pinst = padata_alloc_possible(pcrypt->wq); | ||
463 | if (!pcrypt->pinst) | ||
464 | goto err_destroy_workqueue; | ||
465 | |||
466 | mask = kmalloc(sizeof(*mask), GFP_KERNEL); | ||
467 | if (!mask) | ||
468 | goto err_free_padata; | ||
469 | if (!alloc_cpumask_var(&mask->mask, GFP_KERNEL)) { | ||
470 | kfree(mask); | ||
471 | goto err_free_padata; | ||
472 | } | ||
473 | |||
474 | cpumask_and(mask->mask, cpu_possible_mask, cpu_active_mask); | ||
475 | rcu_assign_pointer(pcrypt->cb_cpumask, mask); | ||
476 | |||
477 | pcrypt->nblock.notifier_call = pcrypt_cpumask_change_notify; | ||
478 | ret = padata_register_cpumask_notifier(pcrypt->pinst, &pcrypt->nblock); | ||
479 | if (ret) | ||
480 | goto err_free_cpumask; | ||
481 | |||
482 | ret = pcrypt_sysfs_add(pcrypt->pinst, name); | ||
483 | if (ret) | ||
484 | goto err_unregister_notifier; | ||
485 | |||
486 | put_online_cpus(); | ||
487 | |||
488 | return ret; | ||
489 | |||
490 | err_unregister_notifier: | ||
491 | padata_unregister_cpumask_notifier(pcrypt->pinst, &pcrypt->nblock); | ||
492 | err_free_cpumask: | ||
493 | free_cpumask_var(mask->mask); | ||
494 | kfree(mask); | ||
495 | err_free_padata: | ||
496 | padata_free(pcrypt->pinst); | ||
497 | err_destroy_workqueue: | ||
498 | destroy_workqueue(pcrypt->wq); | ||
499 | err: | ||
500 | put_online_cpus(); | ||
501 | |||
502 | return ret; | ||
503 | } | ||
504 | |||
505 | static void pcrypt_fini_padata(struct padata_pcrypt *pcrypt) | ||
506 | { | ||
507 | kobject_put(&pcrypt->pinst->kobj); | ||
508 | free_cpumask_var(pcrypt->cb_cpumask->mask); | ||
509 | kfree(pcrypt->cb_cpumask); | ||
510 | |||
511 | padata_stop(pcrypt->pinst); | ||
512 | padata_unregister_cpumask_notifier(pcrypt->pinst, &pcrypt->nblock); | ||
513 | destroy_workqueue(pcrypt->wq); | ||
514 | padata_free(pcrypt->pinst); | ||
515 | } | ||
516 | |||
379 | static struct crypto_template pcrypt_tmpl = { | 517 | static struct crypto_template pcrypt_tmpl = { |
380 | .name = "pcrypt", | 518 | .name = "pcrypt", |
381 | .alloc = pcrypt_alloc, | 519 | .alloc = pcrypt_alloc, |
@@ -385,52 +523,39 @@ static struct crypto_template pcrypt_tmpl = { | |||
385 | 523 | ||
386 | static int __init pcrypt_init(void) | 524 | static int __init pcrypt_init(void) |
387 | { | 525 | { |
388 | encwq = create_workqueue("pencrypt"); | 526 | int err = -ENOMEM; |
389 | if (!encwq) | ||
390 | goto err; | ||
391 | |||
392 | decwq = create_workqueue("pdecrypt"); | ||
393 | if (!decwq) | ||
394 | goto err_destroy_encwq; | ||
395 | 527 | ||
528 | pcrypt_kset = kset_create_and_add("pcrypt", NULL, kernel_kobj); | ||
529 | if (!pcrypt_kset) | ||
530 | goto err; | ||
396 | 531 | ||
397 | pcrypt_enc_padata = padata_alloc(cpu_possible_mask, encwq); | 532 | err = pcrypt_init_padata(&pencrypt, "pencrypt"); |
398 | if (!pcrypt_enc_padata) | 533 | if (err) |
399 | goto err_destroy_decwq; | 534 | goto err_unreg_kset; |
400 | 535 | ||
401 | pcrypt_dec_padata = padata_alloc(cpu_possible_mask, decwq); | 536 | err = pcrypt_init_padata(&pdecrypt, "pdecrypt"); |
402 | if (!pcrypt_dec_padata) | 537 | if (err) |
403 | goto err_free_padata; | 538 | goto err_deinit_pencrypt; |
404 | 539 | ||
405 | padata_start(pcrypt_enc_padata); | 540 | padata_start(pencrypt.pinst); |
406 | padata_start(pcrypt_dec_padata); | 541 | padata_start(pdecrypt.pinst); |
407 | 542 | ||
408 | return crypto_register_template(&pcrypt_tmpl); | 543 | return crypto_register_template(&pcrypt_tmpl); |
409 | 544 | ||
410 | err_free_padata: | 545 | err_deinit_pencrypt: |
411 | padata_free(pcrypt_enc_padata); | 546 | pcrypt_fini_padata(&pencrypt); |
412 | 547 | err_unreg_kset: | |
413 | err_destroy_decwq: | 548 | kset_unregister(pcrypt_kset); |
414 | destroy_workqueue(decwq); | ||
415 | |||
416 | err_destroy_encwq: | ||
417 | destroy_workqueue(encwq); | ||
418 | |||
419 | err: | 549 | err: |
420 | return -ENOMEM; | 550 | return err; |
421 | } | 551 | } |
422 | 552 | ||
423 | static void __exit pcrypt_exit(void) | 553 | static void __exit pcrypt_exit(void) |
424 | { | 554 | { |
425 | padata_stop(pcrypt_enc_padata); | 555 | pcrypt_fini_padata(&pencrypt); |
426 | padata_stop(pcrypt_dec_padata); | 556 | pcrypt_fini_padata(&pdecrypt); |
427 | |||
428 | destroy_workqueue(encwq); | ||
429 | destroy_workqueue(decwq); | ||
430 | |||
431 | padata_free(pcrypt_enc_padata); | ||
432 | padata_free(pcrypt_dec_padata); | ||
433 | 557 | ||
558 | kset_unregister(pcrypt_kset); | ||
434 | crypto_unregister_template(&pcrypt_tmpl); | 559 | crypto_unregister_template(&pcrypt_tmpl); |
435 | } | 560 | } |
436 | 561 | ||