842.c 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  1. /*
  2. * Cryptographic API for the 842 compression algorithm.
  3. *
  4. * This program is free software; you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License as published by
  6. * the Free Software Foundation; either version 2 of the License, or
  7. * (at your option) any later version.
  8. *
  9. * This program is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License
  15. * along with this program; if not, write to the Free Software
  16. * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  17. *
  18. * Copyright (C) IBM Corporation, 2011
  19. *
  20. * Authors: Robert Jennings <rcj@linux.vnet.ibm.com>
  21. * Seth Jennings <sjenning@linux.vnet.ibm.com>
  22. */
  23. #include <linux/init.h>
  24. #include <linux/module.h>
  25. #include <linux/crypto.h>
  26. #include <linux/vmalloc.h>
  27. #include <linux/nx842.h>
  28. #include <linux/lzo.h>
  29. #include <linux/timer.h>
  30. static int nx842_uselzo;
  31. struct nx842_ctx {
  32. void *nx842_wmem; /* working memory for 842/lzo */
  33. };
  34. enum nx842_crypto_type {
  35. NX842_CRYPTO_TYPE_842,
  36. NX842_CRYPTO_TYPE_LZO
  37. };
  38. #define NX842_SENTINEL 0xdeadbeef
  39. struct nx842_crypto_header {
  40. unsigned int sentinel; /* debug */
  41. enum nx842_crypto_type type;
  42. };
  43. static int nx842_init(struct crypto_tfm *tfm)
  44. {
  45. struct nx842_ctx *ctx = crypto_tfm_ctx(tfm);
  46. int wmemsize;
  47. wmemsize = max_t(int, nx842_get_workmem_size(), LZO1X_MEM_COMPRESS);
  48. ctx->nx842_wmem = kmalloc(wmemsize, GFP_NOFS);
  49. if (!ctx->nx842_wmem)
  50. return -ENOMEM;
  51. return 0;
  52. }
  53. static void nx842_exit(struct crypto_tfm *tfm)
  54. {
  55. struct nx842_ctx *ctx = crypto_tfm_ctx(tfm);
  56. kfree(ctx->nx842_wmem);
  57. }
  58. static void nx842_reset_uselzo(unsigned long data)
  59. {
  60. nx842_uselzo = 0;
  61. }
  62. static DEFINE_TIMER(failover_timer, nx842_reset_uselzo, 0, 0);
  63. static int nx842_crypto_compress(struct crypto_tfm *tfm, const u8 *src,
  64. unsigned int slen, u8 *dst, unsigned int *dlen)
  65. {
  66. struct nx842_ctx *ctx = crypto_tfm_ctx(tfm);
  67. struct nx842_crypto_header *hdr;
  68. unsigned int tmp_len = *dlen;
  69. size_t lzodlen; /* needed for lzo */
  70. int err;
  71. *dlen = 0;
  72. hdr = (struct nx842_crypto_header *)dst;
  73. hdr->sentinel = NX842_SENTINEL; /* debug */
  74. dst += sizeof(struct nx842_crypto_header);
  75. tmp_len -= sizeof(struct nx842_crypto_header);
  76. lzodlen = tmp_len;
  77. if (likely(!nx842_uselzo)) {
  78. err = nx842_compress(src, slen, dst, &tmp_len, ctx->nx842_wmem);
  79. if (likely(!err)) {
  80. hdr->type = NX842_CRYPTO_TYPE_842;
  81. *dlen = tmp_len + sizeof(struct nx842_crypto_header);
  82. return 0;
  83. }
  84. /* hardware failed */
  85. nx842_uselzo = 1;
  86. /* set timer to check for hardware again in 1 second */
  87. mod_timer(&failover_timer, jiffies + msecs_to_jiffies(1000));
  88. }
  89. /* no hardware, use lzo */
  90. err = lzo1x_1_compress(src, slen, dst, &lzodlen, ctx->nx842_wmem);
  91. if (err != LZO_E_OK)
  92. return -EINVAL;
  93. hdr->type = NX842_CRYPTO_TYPE_LZO;
  94. *dlen = lzodlen + sizeof(struct nx842_crypto_header);
  95. return 0;
  96. }
  97. static int nx842_crypto_decompress(struct crypto_tfm *tfm, const u8 *src,
  98. unsigned int slen, u8 *dst, unsigned int *dlen)
  99. {
  100. struct nx842_ctx *ctx = crypto_tfm_ctx(tfm);
  101. struct nx842_crypto_header *hdr;
  102. unsigned int tmp_len = *dlen;
  103. size_t lzodlen; /* needed for lzo */
  104. int err;
  105. *dlen = 0;
  106. hdr = (struct nx842_crypto_header *)src;
  107. if (unlikely(hdr->sentinel != NX842_SENTINEL))
  108. return -EINVAL;
  109. src += sizeof(struct nx842_crypto_header);
  110. slen -= sizeof(struct nx842_crypto_header);
  111. if (likely(hdr->type == NX842_CRYPTO_TYPE_842)) {
  112. err = nx842_decompress(src, slen, dst, &tmp_len,
  113. ctx->nx842_wmem);
  114. if (err)
  115. return -EINVAL;
  116. *dlen = tmp_len;
  117. } else if (hdr->type == NX842_CRYPTO_TYPE_LZO) {
  118. lzodlen = tmp_len;
  119. err = lzo1x_decompress_safe(src, slen, dst, &lzodlen);
  120. if (err != LZO_E_OK)
  121. return -EINVAL;
  122. *dlen = lzodlen;
  123. } else
  124. return -EINVAL;
  125. return 0;
  126. }
  127. static struct crypto_alg alg = {
  128. .cra_name = "842",
  129. .cra_flags = CRYPTO_ALG_TYPE_COMPRESS,
  130. .cra_ctxsize = sizeof(struct nx842_ctx),
  131. .cra_module = THIS_MODULE,
  132. .cra_init = nx842_init,
  133. .cra_exit = nx842_exit,
  134. .cra_u = { .compress = {
  135. .coa_compress = nx842_crypto_compress,
  136. .coa_decompress = nx842_crypto_decompress } }
  137. };
  138. static int __init nx842_mod_init(void)
  139. {
  140. del_timer(&failover_timer);
  141. return crypto_register_alg(&alg);
  142. }
  143. static void __exit nx842_mod_exit(void)
  144. {
  145. crypto_unregister_alg(&alg);
  146. }
  147. module_init(nx842_mod_init);
  148. module_exit(nx842_mod_exit);
  149. MODULE_LICENSE("GPL");
  150. MODULE_DESCRIPTION("842 Compression Algorithm");