From a8d79d7bfb14f471914017103ee2329a74e5e89d Mon Sep 17 00:00:00 2001
From: Christian Lamparter <chunkeey@gmail.com>
Date: Thu, 19 Apr 2018 18:41:51 +0200
Subject: crypto: crypto4xx - performance optimizations

This patch provides a cheap 2MiB/s+ (~ 6%) performance
improvement over the current code. This is because the
compiler can now optimize several endian swap memcpy.

Signed-off-by: Christian Lamparter <chunkeey@gmail.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
---
 drivers/crypto/amcc/crypto4xx_alg.c  | 32 +++++++++++++++++++-------------
 drivers/crypto/amcc/crypto4xx_core.c | 22 +++++++++++-----------
 drivers/crypto/amcc/crypto4xx_core.h |  6 ++++--
 3 files changed, 34 insertions(+), 26 deletions(-)

--- a/drivers/crypto/amcc/crypto4xx_alg.c
+++ b/drivers/crypto/amcc/crypto4xx_alg.c
@@ -74,32 +74,38 @@ static void set_dynamic_sa_command_1(str
 	sa->sa_command_1.bf.copy_hdr = cp_hdr;
 }
 
-int crypto4xx_encrypt(struct ablkcipher_request *req)
+static inline int crypto4xx_crypt(struct ablkcipher_request *req,
+				  const unsigned int ivlen, bool decrypt)
 {
 	struct crypto4xx_ctx *ctx = crypto_tfm_ctx(req->base.tfm);
-	unsigned int ivlen = crypto_ablkcipher_ivsize(
-		crypto_ablkcipher_reqtfm(req));
 	__le32 iv[ivlen];
 
 	if (ivlen)
 		crypto4xx_memcpy_to_le32(iv, req->info, ivlen);
 
 	return crypto4xx_build_pd(&req->base, ctx, req->src, req->dst,
-		req->nbytes, iv, ivlen, ctx->sa_out, ctx->sa_len, 0);
+		req->nbytes, iv, ivlen, decrypt ? ctx->sa_in : ctx->sa_out,
+		ctx->sa_len, 0);
 }
 
-int crypto4xx_decrypt(struct ablkcipher_request *req)
+int crypto4xx_encrypt_noiv(struct ablkcipher_request *req)
 {
-	struct crypto4xx_ctx *ctx = crypto_tfm_ctx(req->base.tfm);
-	unsigned int ivlen = crypto_ablkcipher_ivsize(
-		crypto_ablkcipher_reqtfm(req));
-	__le32 iv[ivlen];
+	return crypto4xx_crypt(req, 0, false);
+}
 
-	if (ivlen)
-		crypto4xx_memcpy_to_le32(iv, req->info, ivlen);
+int crypto4xx_encrypt_iv(struct ablkcipher_request *req)
+{
+	return crypto4xx_crypt(req, AES_IV_SIZE, false);
+}
 
-	return crypto4xx_build_pd(&req->base, ctx, req->src, req->dst,
-		req->nbytes, iv, ivlen, ctx->sa_in, ctx->sa_len, 0);
+int crypto4xx_decrypt_noiv(struct ablkcipher_request *req)
+{
+	return crypto4xx_crypt(req, 0, true);
+}
+
+int crypto4xx_decrypt_iv(struct ablkcipher_request *req)
+{
+	return crypto4xx_crypt(req, AES_IV_SIZE, true);
 }
 
 /**
--- a/drivers/crypto/amcc/crypto4xx_core.c
+++ b/drivers/crypto/amcc/crypto4xx_core.c
@@ -585,7 +585,7 @@ static void crypto4xx_aead_done(struct c
 	struct scatterlist *dst = pd_uinfo->dest_va;
 	size_t cp_len = crypto_aead_authsize(
 		crypto_aead_reqtfm(aead_req));
-	u32 icv[cp_len];
+	u32 icv[AES_BLOCK_SIZE];
 	int err = 0;
 
 	if (pd_uinfo->using_sd) {
@@ -600,7 +600,7 @@ static void crypto4xx_aead_done(struct c
 	if (pd_uinfo->sa_va->sa_command_0.bf.dir == DIR_OUTBOUND) {
 		/* append icv at the end */
 		crypto4xx_memcpy_from_le32(icv, pd_uinfo->sr_va->save_digest,
-					   cp_len);
+					   sizeof(icv));
 
 		scatterwalk_map_and_copy(icv, dst, aead_req->cryptlen,
 					 cp_len, 1);
@@ -610,7 +610,7 @@ static void crypto4xx_aead_done(struct c
 			aead_req->assoclen + aead_req->cryptlen -
 			cp_len, cp_len, 0);
 
-		crypto4xx_memcpy_from_le32(icv, icv, cp_len);
+		crypto4xx_memcpy_from_le32(icv, icv, sizeof(icv));
 
 		if (crypto_memneq(icv, pd_uinfo->sr_va->save_digest, cp_len))
 			err = -EBADMSG;
@@ -1127,8 +1127,8 @@ static struct crypto4xx_alg_common crypt
 				.max_keysize 	= AES_MAX_KEY_SIZE,
 				.ivsize		= AES_IV_SIZE,
 				.setkey 	= crypto4xx_setkey_aes_cbc,
-				.encrypt 	= crypto4xx_encrypt,
-				.decrypt 	= crypto4xx_decrypt,
+				.encrypt	= crypto4xx_encrypt_iv,
+				.decrypt	= crypto4xx_decrypt_iv,
 			}
 		}
 	}},
@@ -1151,8 +1151,8 @@ static struct crypto4xx_alg_common crypt
 				.max_keysize	= AES_MAX_KEY_SIZE,
 				.ivsize		= AES_IV_SIZE,
 				.setkey		= crypto4xx_setkey_aes_cfb,
-				.encrypt	= crypto4xx_encrypt,
-				.decrypt	= crypto4xx_decrypt,
+				.encrypt	= crypto4xx_encrypt_iv,
+				.decrypt	= crypto4xx_decrypt_iv,
 			}
 		}
 	} },
@@ -1200,8 +1200,8 @@ static struct crypto4xx_alg_common crypt
 				.min_keysize	= AES_MIN_KEY_SIZE,
 				.max_keysize	= AES_MAX_KEY_SIZE,
 				.setkey		= crypto4xx_setkey_aes_ecb,
-				.encrypt	= crypto4xx_encrypt,
-				.decrypt	= crypto4xx_decrypt,
+				.encrypt	= crypto4xx_encrypt_noiv,
+				.decrypt	= crypto4xx_decrypt_noiv,
 			}
 		}
 	} },
@@ -1224,8 +1224,8 @@ static struct crypto4xx_alg_common crypt
 				.max_keysize	= AES_MAX_KEY_SIZE,
 				.ivsize		= AES_IV_SIZE,
 				.setkey		= crypto4xx_setkey_aes_ofb,
-				.encrypt	= crypto4xx_encrypt,
-				.decrypt	= crypto4xx_decrypt,
+				.encrypt	= crypto4xx_encrypt_iv,
+				.decrypt	= crypto4xx_decrypt_iv,
 			}
 		}
 	} },
--- a/drivers/crypto/amcc/crypto4xx_core.h
+++ b/drivers/crypto/amcc/crypto4xx_core.h
@@ -168,8 +168,10 @@ int crypto4xx_setkey_aes_ofb(struct cryp
 			     const u8 *key, unsigned int keylen);
 int crypto4xx_setkey_rfc3686(struct crypto_ablkcipher *cipher,
 			     const u8 *key, unsigned int keylen);
-int crypto4xx_encrypt(struct ablkcipher_request *req);
-int crypto4xx_decrypt(struct ablkcipher_request *req);
+int crypto4xx_encrypt_iv(struct ablkcipher_request *req);
+int crypto4xx_decrypt_iv(struct ablkcipher_request *req);
+int crypto4xx_encrypt_noiv(struct ablkcipher_request *req);
+int crypto4xx_decrypt_noiv(struct ablkcipher_request *req);
 int crypto4xx_rfc3686_encrypt(struct ablkcipher_request *req);
 int crypto4xx_rfc3686_decrypt(struct ablkcipher_request *req);
 int crypto4xx_sha1_alg_init(struct crypto_tfm *tfm);
