@@ -361,6 +361,55 @@ void crypto_shoot_alg(struct crypto_alg *alg)
}
EXPORT_SYMBOL_GPL(crypto_shoot_alg);
+struct crypto_tfm *__crypto_alloc_tfm_percpu(struct crypto_alg *alg, u32 type,
+ u32 mask)
+{
+ struct crypto_tfm *tfm = NULL;
+ struct crypto_tfm *tfm_percpu = NULL;
+ unsigned int tfm_size, cpu, cpu_err;
+ int err = -ENOMEM;
+
+ tfm_size = sizeof(*tfm) + crypto_ctxsize(alg, type, mask);
+
+ tfm_percpu = __alloc_percpu(tfm_size);
+ if (tfm_percpu == NULL)
+ goto out_err;
+
+ for_each_possible_cpu(cpu) {
+
+ tfm = per_cpu_ptr(tfm_percpu, cpu);
+
+ tfm->__crt_alg = alg;
+
+ err = crypto_init_ops(tfm, type, mask);
+ if (err)
+ goto out_free_tfm;
+
+ if (alg->cra_init && (err = alg->cra_init(tfm))) {
+ if (err == -EAGAIN)
+ crypto_shoot_alg(alg);
+ goto cra_init_failed;
+ }
+ }
+
+ goto out;
+
+cra_init_failed:
+ for_each_possible_cpu(cpu_err) {
+ tfm = per_cpu_ptr(tfm_percpu, cpu);
+ crypto_exit_ops(tfm);
+ if (cpu_err == cpu)
+ break;
+ }
+out_free_tfm:
+ free_percpu(tfm_percpu);
+out_err:
+ tfm_percpu = ERR_PTR(err);
+out:
+ return tfm_percpu;
+}
+EXPORT_SYMBOL_GPL(__crypto_alloc_tfm_percpu);
+
struct crypto_tfm *__crypto_alloc_tfm(struct crypto_alg *alg, u32 type,
u32 mask)
{
@@ -450,15 +499,8 @@ err:
return ERR_PTR(err);
}
EXPORT_SYMBOL_GPL(crypto_alloc_base);
-
-/*
- * crypto_free_tfm - Free crypto transform
- * @tfm: Transform to free
- *
- * crypto_free_tfm() frees up the transform and any associated resources,
- * then drops the refcount on the associated algorithm.
- */
-void crypto_free_tfm(struct crypto_tfm *tfm)
+
+void __crypto_free_tfm(struct crypto_tfm *tfm)
{
struct crypto_alg *alg;
int size;
@@ -474,11 +516,35 @@ void crypto_free_tfm(struct crypto_tfm *tfm)
crypto_exit_ops(tfm);
crypto_mod_put(alg);
memset(tfm, 0, size);
- kfree(tfm);
}
+/*
+ * crypto_free_tfm - Free crypto transform
+ * @tfm: Transform to free
+ *
+ * crypto_free_tfm() frees up the transform and any associated resources,
+ * then drops the refcount on the associated algorithm.
+ */
+void crypto_free_tfm(struct crypto_tfm *tfm)
+{
+ __crypto_free_tfm(tfm);
+ kfree(tfm);
+}
EXPORT_SYMBOL_GPL(crypto_free_tfm);
+void crypto_free_tfm_percpu(struct crypto_tfm *tfm_percpu)
+{
+ unsigned int cpu;
+ struct crypto_tfm *tfm;
+
+ for_each_possible_cpu(cpu) {
+ tfm = per_cpu_ptr(tfm_percpu, cpu);
+ __crypto_free_tfm(tfm);
+ }
+ free_percpu(tfm_percpu);
+}
+EXPORT_SYMBOL_GPL(crypto_free_tfm_percpu);
+
int crypto_has_alg(const char *name, u32 type, u32 mask)
{
int ret = 0;
@@ -109,6 +109,9 @@ void crypto_alg_tested(const char *name, int err);
void crypto_shoot_alg(struct crypto_alg *alg);
struct crypto_tfm *__crypto_alloc_tfm(struct crypto_alg *alg, u32 type,
u32 mask);
+struct crypto_tfm *__crypto_alloc_tfm_percpu(struct crypto_alg *alg, u32 type,
+ u32 mask);
+void __crypto_free_tfm(struct crypto_tfm *tfm);
int crypto_register_instance(struct crypto_template *tmpl,
struct crypto_instance *inst);
@@ -548,6 +548,7 @@ struct crypto_attr_u32 {
struct crypto_tfm *crypto_alloc_tfm(const char *alg_name, u32 tfm_flags);
struct crypto_tfm *crypto_alloc_base(const char *alg_name, u32 type, u32 mask);
void crypto_free_tfm(struct crypto_tfm *tfm);
+void crypto_free_tfm_percpu(struct crypto_tfm *tfm);
int alg_test(const char *driver, const char *alg, u32 type, u32 mask);