This patch adds a parallel crypto template that takes a crypto
algorithm and converts it to process the crypto transforms in
parallel. For the moment only aead is supported.
Signed-off-by: Steffen Klassert
---
crypto/Kconfig| 13 ++
crypto/Makefile |2 +
crypto/pcrypt.c | 415 +
crypto/pcrypt_core.c | 106
include/crypto/pcrypt.h | 56 ++
include/linux/crypto.h|2 +
include/linux/interrupt.h |2 +
kernel/softirq.c |3 +-
8 files changed, 598 insertions(+), 1 deletions(-)
create mode 100644 crypto/pcrypt.c
create mode 100644 crypto/pcrypt_core.c
create mode 100644 include/crypto/pcrypt.h
diff --git a/crypto/Kconfig b/crypto/Kconfig
index 74d0e62..b05fc95 100644
--- a/crypto/Kconfig
+++ b/crypto/Kconfig
@@ -112,6 +112,19 @@ config CRYPTO_NULL
help
These are 'Null' algorithms, used by IPsec, which do nothing.
+config CRYPTO_PCRYPT_CORE
+ bool
+ select CRYPTO_AEAD
+
+config CRYPTO_PCRYPT
+ tristate "Parallel crypto engine (EXPERIMENTAL)"
+ depends on USE_GENERIC_SMP_HELPERS && EXPERIMENTAL
+ select CRYPTO_MANAGER
+ select CRYPTO_PCRYPT_CORE
+ help
+ This converts an arbitrary crypto algorithm into a parallel
+ algorithm that is executed in a softirq.
+
config CRYPTO_WORKQUEUE
tristate
diff --git a/crypto/Makefile b/crypto/Makefile
index 673d9f7..84b9d17 100644
--- a/crypto/Makefile
+++ b/crypto/Makefile
@@ -56,6 +56,8 @@ obj-$(CONFIG_CRYPTO_XTS) += xts.o
obj-$(CONFIG_CRYPTO_CTR) += ctr.o
obj-$(CONFIG_CRYPTO_GCM) += gcm.o
obj-$(CONFIG_CRYPTO_CCM) += ccm.o
+obj-$(CONFIG_CRYPTO_PCRYPT_CORE) += pcrypt_core.o
+obj-$(CONFIG_CRYPTO_PCRYPT) += pcrypt.o
obj-$(CONFIG_CRYPTO_CRYPTD) += cryptd.o
obj-$(CONFIG_CRYPTO_DES) += des_generic.o
obj-$(CONFIG_CRYPTO_FCRYPT) += fcrypt.o
diff --git a/crypto/pcrypt.c b/crypto/pcrypt.c
new file mode 100644
index 000..23f7eb7
--- /dev/null
+++ b/crypto/pcrypt.c
@@ -0,0 +1,415 @@
+/*
+ * pcrypt - Parallel crypto wrapper.
+ *
+ * Copyright (C) 2009 secunet Security Networks AG
+ * Copyright (C) 2009 Steffen Klassert
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+struct pcrypt_instance_ctx {
+ struct crypto_spawn spawn;
+ unsigned int tfm_count;
+};
+
+struct pcrypt_aead_ctx {
+ struct crypto_aead *child;
+ unsigned int tfm_nr;
+};
+
+static int pcrypt_do_parallel(struct padata_priv *padata, unsigned int tfm_nr,
+ unsigned int softirq, unsigned int padata_nr)
+{
+ unsigned int cpu, cpu_index, num_cpus, cb_cpu;
+ cpumask_t cpu_map;
+
+ cpu_map = padata_get_cpumap(padata_nr);
+ num_cpus = cpus_weight(cpu_map);
+
+ cpu_index = tfm_nr % num_cpus;
+
+ cb_cpu = first_cpu(cpu_map);
+ for (cpu = 0; cpu < cpu_index; cpu++)
+ cb_cpu = next_cpu(cb_cpu, cpu_map);
+
+ return padata_do_parallel(softirq, padata_nr, padata, cb_cpu);
+}
+
+static int pcrypt_aead_setkey(struct crypto_aead *parent,
+ const u8 *key, unsigned int keylen)
+{
+ struct pcrypt_aead_ctx *ctx = crypto_aead_ctx(parent);
+
+ return crypto_aead_setkey(ctx->child, key, keylen);
+}
+
+static int pcrypt_aead_setauthsize(struct crypto_aead *parent,
+ unsigned int authsize)
+{
+ struct pcrypt_aead_ctx *ctx = crypto_aead_ctx(parent);
+
+ return crypto_aead_setauthsize(ctx->child, authsize);
+}
+
+static void pcrypt_aead_serial(struct padata_priv *padata)
+{
+ struct pcrypt_request *preq = pcrypt_padata_request(padata);
+ struct aead_request *req = pcrypt_request_ctx(preq);
+
+ aead_request_complete(req->base.data, padata->info);
+}
+
+static void pcrypt_aead_giv_serial(struct padata_priv *padata)
+{
+ struct pcrypt_request *preq = pcrypt_padata_request(padata);
+ struct aead_givcrypt_request *req = pcrypt_request_ctx(preq);
+
+ aead_request_complete(req->areq.base.data, padata->info);
+}
+
+static void pcrypt_aead_done(struct crypto_async_request *areq, int err)
+{
+ struct aead_request *req = areq->data;
+ struct pcrypt_request *preq = aead_request_ctx(req);