powerpc/crypto: add 842 crypto driver
authorSeth Jennings <sjenning@linux.vnet.ibm.com>
Thu, 19 Jul 2012 14:42:41 +0000 (09:42 -0500)
committerHerbert Xu <herbert@gondor.apana.org.au>
Wed, 1 Aug 2012 09:47:56 +0000 (17:47 +0800)
This patch add the 842 cryptographic API driver that
submits compression requests to the 842 hardware compression
accelerator driver (nx-compress).

If the hardware accelerator goes offline for any reason
(dynamic disable, migration, etc...), this driver will use LZO
as a software failover for all future compression requests.
For decompression requests, the 842 hardware driver contains
a software implementation of the 842 decompressor to support
the decompression of data that was compressed before the accelerator
went offline.

Signed-off-by: Robert Jennings <rcj@linux.vnet.ibm.com>
Signed-off-by: Seth Jennings <sjenning@linux.vnet.ibm.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
crypto/842.c [new file with mode: 0644]
crypto/Kconfig
crypto/Makefile

diff --git a/crypto/842.c b/crypto/842.c
new file mode 100644 (file)
index 0000000..144767d
--- /dev/null
@@ -0,0 +1,183 @@
+/*
+ * Cryptographic API for the 842 compression algorithm.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that 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, 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ * Copyright (C) IBM Corporation, 2011
+ *
+ * Authors: Robert Jennings <rcj@linux.vnet.ibm.com>
+ *          Seth Jennings <sjenning@linux.vnet.ibm.com>
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/crypto.h>
+#include <linux/vmalloc.h>
+#include <linux/nx842.h>
+#include <linux/lzo.h>
+#include <linux/timer.h>
+
+static int nx842_uselzo;
+
+struct nx842_ctx {
+       void *nx842_wmem; /* working memory for 842/lzo */
+};
+
+enum nx842_crypto_type {
+       NX842_CRYPTO_TYPE_842,
+       NX842_CRYPTO_TYPE_LZO
+};
+
+#define NX842_SENTINEL 0xdeadbeef
+
+struct nx842_crypto_header {
+       unsigned int sentinel; /* debug */
+       enum nx842_crypto_type type;
+};
+
+static int nx842_init(struct crypto_tfm *tfm)
+{
+       struct nx842_ctx *ctx = crypto_tfm_ctx(tfm);
+       int wmemsize;
+
+       wmemsize = max_t(int, nx842_get_workmem_size(), LZO1X_MEM_COMPRESS);
+       ctx->nx842_wmem = kmalloc(wmemsize, GFP_NOFS);
+       if (!ctx->nx842_wmem)
+               return -ENOMEM;
+
+       return 0;
+}
+
+static void nx842_exit(struct crypto_tfm *tfm)
+{
+       struct nx842_ctx *ctx = crypto_tfm_ctx(tfm);
+
+       kfree(ctx->nx842_wmem);
+}
+
+static void nx842_reset_uselzo(unsigned long data)
+{
+       nx842_uselzo = 0;
+}
+
+static DEFINE_TIMER(failover_timer, nx842_reset_uselzo, 0, 0);
+
+static int nx842_crypto_compress(struct crypto_tfm *tfm, const u8 *src,
+                           unsigned int slen, u8 *dst, unsigned int *dlen)
+{
+       struct nx842_ctx *ctx = crypto_tfm_ctx(tfm);
+       struct nx842_crypto_header *hdr;
+       unsigned int tmp_len = *dlen;
+       size_t lzodlen; /* needed for lzo */
+       int err;
+
+       *dlen = 0;
+       hdr = (struct nx842_crypto_header *)dst;
+       hdr->sentinel = NX842_SENTINEL; /* debug */
+       dst += sizeof(struct nx842_crypto_header);
+       tmp_len -= sizeof(struct nx842_crypto_header);
+       lzodlen = tmp_len;
+
+       if (likely(!nx842_uselzo)) {
+               err = nx842_compress(src, slen, dst, &tmp_len, ctx->nx842_wmem);
+
+               if (likely(!err)) {
+                       hdr->type = NX842_CRYPTO_TYPE_842;
+                       *dlen = tmp_len + sizeof(struct nx842_crypto_header);
+                       return 0;
+               }
+
+               /* hardware failed */
+               nx842_uselzo = 1;
+
+               /* set timer to check for hardware again in 1 second */
+               mod_timer(&failover_timer, jiffies + msecs_to_jiffies(1000));
+       }
+
+       /* no hardware, use lzo */
+       err = lzo1x_1_compress(src, slen, dst, &lzodlen, ctx->nx842_wmem);
+       if (err != LZO_E_OK)
+               return -EINVAL;
+
+       hdr->type = NX842_CRYPTO_TYPE_LZO;
+       *dlen = lzodlen + sizeof(struct nx842_crypto_header);
+       return 0;
+}
+
+static int nx842_crypto_decompress(struct crypto_tfm *tfm, const u8 *src,
+                             unsigned int slen, u8 *dst, unsigned int *dlen)
+{
+       struct nx842_ctx *ctx = crypto_tfm_ctx(tfm);
+       struct nx842_crypto_header *hdr;
+       unsigned int tmp_len = *dlen;
+       size_t lzodlen; /* needed for lzo */
+       int err;
+
+       *dlen = 0;
+       hdr = (struct nx842_crypto_header *)src;
+
+       if (unlikely(hdr->sentinel != NX842_SENTINEL))
+               return -EINVAL;
+
+       src += sizeof(struct nx842_crypto_header);
+       slen -= sizeof(struct nx842_crypto_header);
+
+       if (likely(hdr->type == NX842_CRYPTO_TYPE_842)) {
+               err = nx842_decompress(src, slen, dst, &tmp_len,
+                       ctx->nx842_wmem);
+               if (err)
+                       return -EINVAL;
+               *dlen = tmp_len;
+       } else if (hdr->type == NX842_CRYPTO_TYPE_LZO) {
+               lzodlen = tmp_len;
+               err = lzo1x_decompress_safe(src, slen, dst, &lzodlen);
+               if (err != LZO_E_OK)
+                       return -EINVAL;
+               *dlen = lzodlen;
+       } else
+               return -EINVAL;
+
+       return 0;
+}
+
+static struct crypto_alg alg = {
+       .cra_name               = "842",
+       .cra_flags              = CRYPTO_ALG_TYPE_COMPRESS,
+       .cra_ctxsize            = sizeof(struct nx842_ctx),
+       .cra_module             = THIS_MODULE,
+       .cra_list               = LIST_HEAD_INIT(alg.cra_list),
+       .cra_init               = nx842_init,
+       .cra_exit               = nx842_exit,
+       .cra_u                  = { .compress = {
+       .coa_compress           = nx842_crypto_compress,
+       .coa_decompress         = nx842_crypto_decompress } }
+};
+
+static int __init nx842_mod_init(void)
+{
+       del_timer(&failover_timer);
+       return crypto_register_alg(&alg);
+}
+
+static void __exit nx842_mod_exit(void)
+{
+       crypto_unregister_alg(&alg);
+}
+
+module_init(nx842_mod_init);
+module_exit(nx842_mod_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("842 Compression Algorithm");
index fe8ed62..cbcc0e2 100644 (file)
@@ -1039,6 +1039,15 @@ config CRYPTO_LZO
        help
          This is the LZO algorithm.
 
+config CRYPTO_842
+       tristate "842 compression algorithm"
+       depends on CRYPTO_DEV_NX_COMPRESS
+       # 842 uses lzo if the hardware becomes unavailable
+       select LZO_COMPRESS
+       select LZO_DECOMPRESS
+       help
+         This is the 842 algorithm.
+
 comment "Random Number Generation"
 
 config CRYPTO_ANSI_CPRNG
index 396966d..a301ad2 100644 (file)
@@ -82,6 +82,7 @@ obj-$(CONFIG_CRYPTO_MICHAEL_MIC) += michael_mic.o
 obj-$(CONFIG_CRYPTO_CRC32C) += crc32c.o
 obj-$(CONFIG_CRYPTO_AUTHENC) += authenc.o authencesn.o
 obj-$(CONFIG_CRYPTO_LZO) += lzo.o
+obj-$(CONFIG_CRYPTO_842) += 842.o
 obj-$(CONFIG_CRYPTO_RNG2) += rng.o
 obj-$(CONFIG_CRYPTO_RNG2) += krng.o
 obj-$(CONFIG_CRYPTO_ANSI_CPRNG) += ansi_cprng.o