summaryrefslogtreecommitdiff
path: root/target/linux/apm821xx
diff options
context:
space:
mode:
authorChristian Lamparter <chunkeey@gmail.com>2018-01-07 21:27:50 +0100
committerMathias Kresin <dev@kresin.me>2018-01-12 08:00:04 +0100
commit780477d17c0e73e54397a0f3cebff08634e7231a (patch)
tree098826be0c3cbfb24fc1fc15219eed83d915e84a /target/linux/apm821xx
parente4371779d2691553e6321e87d86212beaaa8b89d (diff)
downloadmtk-20170518-780477d17c0e73e54397a0f3cebff08634e7231a.zip
mtk-20170518-780477d17c0e73e54397a0f3cebff08634e7231a.tar.gz
mtk-20170518-780477d17c0e73e54397a0f3cebff08634e7231a.tar.bz2
apm821xx: backport crypto4xx patches from 4.15
This patch backports changes to crypto4xx in order to get the crypto4xx operational. Signed-off-by: Christian Lamparter <chunkeey@gmail.com>
Diffstat (limited to 'target/linux/apm821xx')
-rw-r--r--target/linux/apm821xx/patches-4.14/010-crypto-gcm-add-GCM-IV-size-constant.patch27
-rw-r--r--target/linux/apm821xx/patches-4.14/020-0001-crypto-crypto4xx-remove-bad-list_del.patch32
-rw-r--r--target/linux/apm821xx/patches-4.14/020-0002-crypto-crypto4xx-remove-unused-definitions-and-write.patch120
-rw-r--r--target/linux/apm821xx/patches-4.14/020-0003-crypto-crypto4xx-set-CRYPTO_ALG_KERN_DRIVER_ONLY-fla.patch31
-rw-r--r--target/linux/apm821xx/patches-4.14/020-0004-crypto-crypto4xx-remove-extern-statement-before-func.patch76
-rw-r--r--target/linux/apm821xx/patches-4.14/020-0005-crypto-crypto4xx-remove-double-assignment-of-pd_uinf.patch24
-rw-r--r--target/linux/apm821xx/patches-4.14/020-0006-crypto-crypto4xx-fix-dynamic_sa_ctl-s-sa_contents-de.patch87
-rw-r--r--target/linux/apm821xx/patches-4.14/020-0007-crypto-crypto4xx-move-and-refactor-dynamic_contents-.patch234
-rw-r--r--target/linux/apm821xx/patches-4.14/020-0008-crypto-crypto4xx-enable-AES-RFC3686-ECB-CFB-and-OFB-.patch248
-rw-r--r--target/linux/apm821xx/patches-4.14/020-0009-crypto-crypto4xx-refactor-crypto4xx_copy_pkt_to_dst.patch171
-rw-r--r--target/linux/apm821xx/patches-4.14/020-0010-crypto-crypto4xx-replace-crypto4xx_dev-s-scatter_buf.patch59
-rw-r--r--target/linux/apm821xx/patches-4.14/020-0011-crypto-crypto4xx-fix-crypto4xx_build_pdr-crypto4xx_b.patch84
-rw-r--r--target/linux/apm821xx/patches-4.14/020-0012-crypto-crypto4xx-pointer-arithmetic-overhaul.patch373
-rw-r--r--target/linux/apm821xx/patches-4.14/020-0013-crypto-crypto4xx-wire-up-hmac_mc-to-hmac_muting.patch25
-rw-r--r--target/linux/apm821xx/patches-4.14/020-0014-crypto-crypto4xx-fix-off-by-one-AES-OFB.patch49
-rw-r--r--target/linux/apm821xx/patches-4.14/020-0015-crypto-crypto4xx-fix-type-mismatch-compiler-error.patch29
-rw-r--r--target/linux/apm821xx/patches-4.14/020-0017-crypto-crypto4xx-add-backlog-queue-support.patch161
-rw-r--r--target/linux/apm821xx/patches-4.14/020-0018-crypto-crypto4xx-use-the-correct-LE32-format-for-IV-.patch236
-rw-r--r--target/linux/apm821xx/patches-4.14/020-0019-crypto-crypto4xx-overhaul-crypto4xx_build_pd.patch535
-rw-r--r--target/linux/apm821xx/patches-4.14/020-0020-crypto-crypto4xx-fix-various-warnings.patch62
-rw-r--r--target/linux/apm821xx/patches-4.14/020-0021-crypto-crypto4xx-fix-stalls-under-heavy-load.patch112
-rw-r--r--target/linux/apm821xx/patches-4.14/020-0022-crypto-crypto4xx-simplify-sa-and-state-context-acqui.patch209
-rw-r--r--target/linux/apm821xx/patches-4.14/020-0023-crypto-crypto4xx-prepare-for-AEAD-support.patch617
-rw-r--r--target/linux/apm821xx/patches-4.14/020-0024-crypto-crypto4xx-add-aes-ccm-support.patch256
-rw-r--r--target/linux/apm821xx/patches-4.14/020-0025-crypto-crypto4xx-add-aes-gcm-support.patch220
-rw-r--r--target/linux/apm821xx/patches-4.14/120-0001-crypto-crypto4xx-shuffle-iomap-in-front-of-request_i.patch71
-rw-r--r--target/linux/apm821xx/patches-4.14/120-0002-crypto-crypto4xx-support-Revision-B-parts.patch150
-rw-r--r--target/linux/apm821xx/patches-4.14/120-0003-crypto-crypto4xx-fix-missing-irq-devname.patch37
-rw-r--r--target/linux/apm821xx/patches-4.14/120-0004-crypto-crypto4xx-kill-MODULE_NAME.patch47
-rw-r--r--target/linux/apm821xx/patches-4.14/120-0005-crypto-crypto4xx-perform-aead-icv-check-in-the-drive.patch146
-rw-r--r--target/linux/apm821xx/patches-4.14/120-0006-crypto-crypto4xx-performance-optimizations.patch158
31 files changed, 4686 insertions, 0 deletions
diff --git a/target/linux/apm821xx/patches-4.14/010-crypto-gcm-add-GCM-IV-size-constant.patch b/target/linux/apm821xx/patches-4.14/010-crypto-gcm-add-GCM-IV-size-constant.patch
new file mode 100644
index 0000000..6f0cc60
--- /dev/null
+++ b/target/linux/apm821xx/patches-4.14/010-crypto-gcm-add-GCM-IV-size-constant.patch
@@ -0,0 +1,27 @@
+From ef780324592dd639e4bfbc5b9bf8934b234b7c99 Mon Sep 17 00:00:00 2001
+From: Corentin LABBE <clabbe.montjoie@gmail.com>
+Date: Tue, 22 Aug 2017 10:08:08 +0200
+Subject: [PATCH] crypto: gcm - add GCM IV size constant
+
+Many GCM users use directly GCM IV size instead of using some constant.
+
+This patch add all IV size constant used by GCM.
+
+Signed-off-by: Corentin Labbe <clabbe.montjoie@gmail.com>
+Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
+---
+ include/crypto/gcm.h | 8 ++++++++
+ 1 file changed, 8 insertions(+)
+ create mode 100644 include/crypto/gcm.h
+
+--- /dev/null
++++ b/include/crypto/gcm.h
+@@ -0,0 +1,8 @@
++#ifndef _CRYPTO_GCM_H
++#define _CRYPTO_GCM_H
++
++#define GCM_AES_IV_SIZE 12
++#define GCM_RFC4106_IV_SIZE 8
++#define GCM_RFC4543_IV_SIZE 8
++
++#endif
diff --git a/target/linux/apm821xx/patches-4.14/020-0001-crypto-crypto4xx-remove-bad-list_del.patch b/target/linux/apm821xx/patches-4.14/020-0001-crypto-crypto4xx-remove-bad-list_del.patch
new file mode 100644
index 0000000..8df0937
--- /dev/null
+++ b/target/linux/apm821xx/patches-4.14/020-0001-crypto-crypto4xx-remove-bad-list_del.patch
@@ -0,0 +1,32 @@
+From a728a196d253530f17da5c86dc7dfbe58c5f7094 Mon Sep 17 00:00:00 2001
+From: Christian Lamparter <chunkeey@googlemail.com>
+Date: Fri, 25 Aug 2017 15:47:14 +0200
+Subject: [PATCH 01/25] crypto: crypto4xx - remove bad list_del
+
+alg entries are only added to the list, after the registration
+was successful. If the registration failed, it was never added
+to the list in the first place.
+
+Signed-off-by: Christian Lamparter <chunkeey@googlemail.com>
+Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
+---
+ drivers/crypto/amcc/crypto4xx_core.c | 6 ++----
+ 1 file changed, 2 insertions(+), 4 deletions(-)
+
+--- a/drivers/crypto/amcc/crypto4xx_core.c
++++ b/drivers/crypto/amcc/crypto4xx_core.c
+@@ -1033,12 +1033,10 @@ int crypto4xx_register_alg(struct crypto
+ break;
+ }
+
+- if (rc) {
+- list_del(&alg->entry);
++ if (rc)
+ kfree(alg);
+- } else {
++ else
+ list_add_tail(&alg->entry, &sec_dev->alg_list);
+- }
+ }
+
+ return 0;
diff --git a/target/linux/apm821xx/patches-4.14/020-0002-crypto-crypto4xx-remove-unused-definitions-and-write.patch b/target/linux/apm821xx/patches-4.14/020-0002-crypto-crypto4xx-remove-unused-definitions-and-write.patch
new file mode 100644
index 0000000..5983246
--- /dev/null
+++ b/target/linux/apm821xx/patches-4.14/020-0002-crypto-crypto4xx-remove-unused-definitions-and-write.patch
@@ -0,0 +1,120 @@
+From 81065f66dd99b3af58626a914b8c0fcff6b8b0ba Mon Sep 17 00:00:00 2001
+From: Christian Lamparter <chunkeey@googlemail.com>
+Date: Fri, 25 Aug 2017 15:47:15 +0200
+Subject: [PATCH 02/25] crypto: crypto4xx - remove unused definitions and
+ write-only variables
+
+This patch removes several unused code and definitons
+(structs, variables, ...).
+
+Signed-off-by: Christian Lamparter <chunkeey@googlemail.com>
+Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
+---
+ drivers/crypto/amcc/crypto4xx_alg.c | 6 ------
+ drivers/crypto/amcc/crypto4xx_core.c | 2 +-
+ drivers/crypto/amcc/crypto4xx_core.h | 16 ----------------
+ 3 files changed, 1 insertion(+), 23 deletions(-)
+
+--- a/drivers/crypto/amcc/crypto4xx_alg.c
++++ b/drivers/crypto/amcc/crypto4xx_alg.c
+@@ -75,7 +75,6 @@ int crypto4xx_encrypt(struct ablkcipher_
+ struct crypto4xx_ctx *ctx = crypto_tfm_ctx(req->base.tfm);
+
+ ctx->direction = DIR_OUTBOUND;
+- ctx->hash_final = 0;
+ ctx->is_hash = 0;
+ ctx->pd_ctl = 0x1;
+
+@@ -89,7 +88,6 @@ int crypto4xx_decrypt(struct ablkcipher_
+ struct crypto4xx_ctx *ctx = crypto_tfm_ctx(req->base.tfm);
+
+ ctx->direction = DIR_INBOUND;
+- ctx->hash_final = 0;
+ ctx->is_hash = 0;
+ ctx->pd_ctl = 1;
+
+@@ -136,7 +134,6 @@ static int crypto4xx_setkey_aes(struct c
+ }
+ /* Setup SA */
+ sa = (struct dynamic_sa_ctl *) ctx->sa_in;
+- ctx->hash_final = 0;
+
+ set_dynamic_sa_command_0(sa, SA_NOT_SAVE_HASH, SA_NOT_SAVE_IV,
+ SA_LOAD_HASH_FROM_SA, SA_LOAD_IV_FROM_STATE,
+@@ -191,7 +188,6 @@ static int crypto4xx_hash_alg_init(struc
+
+ ctx->dev = my_alg->dev;
+ ctx->is_hash = 1;
+- ctx->hash_final = 0;
+
+ /* Create SA */
+ if (ctx->sa_in_dma_addr || ctx->sa_out_dma_addr)
+@@ -256,7 +252,6 @@ int crypto4xx_hash_update(struct ahash_r
+ struct crypto4xx_ctx *ctx = crypto_tfm_ctx(req->base.tfm);
+
+ ctx->is_hash = 1;
+- ctx->hash_final = 0;
+ ctx->pd_ctl = 0x11;
+ ctx->direction = DIR_INBOUND;
+
+@@ -274,7 +269,6 @@ int crypto4xx_hash_digest(struct ahash_r
+ {
+ struct crypto4xx_ctx *ctx = crypto_tfm_ctx(req->base.tfm);
+
+- ctx->hash_final = 1;
+ ctx->pd_ctl = 0x11;
+ ctx->direction = DIR_INBOUND;
+
+--- a/drivers/crypto/amcc/crypto4xx_core.c
++++ b/drivers/crypto/amcc/crypto4xx_core.c
+@@ -962,7 +962,7 @@ u32 crypto4xx_build_pd(struct crypto_asy
+
+ sa->sa_command_1.bf.hash_crypto_offset = 0;
+ pd->pd_ctl.w = ctx->pd_ctl;
+- pd->pd_ctl_len.w = 0x00400000 | (ctx->bypass << 24) | datalen;
++ pd->pd_ctl_len.w = 0x00400000 | datalen;
+ pd_uinfo->state = PD_ENTRY_INUSE;
+ wmb();
+ /* write any value to push engine to read a pd */
+--- a/drivers/crypto/amcc/crypto4xx_core.h
++++ b/drivers/crypto/amcc/crypto4xx_core.h
+@@ -72,7 +72,6 @@ struct pd_uinfo {
+ struct crypto4xx_device {
+ struct crypto4xx_core_device *core_dev;
+ char *name;
+- u64 ce_phy_address;
+ void __iomem *ce_base;
+ void __iomem *trng_base;
+
+@@ -127,21 +126,9 @@ struct crypto4xx_ctx {
+ u32 sa_len;
+ u32 offset_to_sr_ptr; /* offset to state ptr, in dynamic sa */
+ u32 direction;
+- u32 next_hdr;
+ u32 save_iv;
+- u32 pd_ctl_len;
+ u32 pd_ctl;
+- u32 bypass;
+ u32 is_hash;
+- u32 hash_final;
+-};
+-
+-struct crypto4xx_req_ctx {
+- struct crypto4xx_device *dev; /* Device in which
+- operation to send to */
+- void *sa;
+- u32 sa_dma_addr;
+- u16 sa_len;
+ };
+
+ struct crypto4xx_alg_common {
+@@ -172,9 +159,6 @@ static inline struct crypto4xx_alg *cryp
+
+ extern int crypto4xx_alloc_sa(struct crypto4xx_ctx *ctx, u32 size);
+ extern void crypto4xx_free_sa(struct crypto4xx_ctx *ctx);
+-extern u32 crypto4xx_alloc_sa_rctx(struct crypto4xx_ctx *ctx,
+- struct crypto4xx_ctx *rctx);
+-extern void crypto4xx_free_sa_rctx(struct crypto4xx_ctx *rctx);
+ extern void crypto4xx_free_ctx(struct crypto4xx_ctx *ctx);
+ extern u32 crypto4xx_alloc_state_record(struct crypto4xx_ctx *ctx);
+ extern u32 get_dynamic_sa_offset_state_ptr_field(struct crypto4xx_ctx *ctx);
diff --git a/target/linux/apm821xx/patches-4.14/020-0003-crypto-crypto4xx-set-CRYPTO_ALG_KERN_DRIVER_ONLY-fla.patch b/target/linux/apm821xx/patches-4.14/020-0003-crypto-crypto4xx-set-CRYPTO_ALG_KERN_DRIVER_ONLY-fla.patch
new file mode 100644
index 0000000..e50a418
--- /dev/null
+++ b/target/linux/apm821xx/patches-4.14/020-0003-crypto-crypto4xx-set-CRYPTO_ALG_KERN_DRIVER_ONLY-fla.patch
@@ -0,0 +1,31 @@
+From 1ef52a95ea53c3c54b061e3f1af85976356c7132 Mon Sep 17 00:00:00 2001
+From: Christian Lamparter <chunkeey@googlemail.com>
+Date: Fri, 25 Aug 2017 15:47:16 +0200
+Subject: [PATCH 03/25] crypto: crypto4xx - set CRYPTO_ALG_KERN_DRIVER_ONLY
+ flag
+
+The security offload function is performed by a cryptographic
+engine core attached to the 128-bit PLB (processor local bus)
+with builtin DMA and interrupt controllers. This, I think,
+satisfies the requirement for the CRYPTO_ALG_KERN_DRIVER_ONLY
+flag.
+
+Signed-off-by: Christian Lamparter <chunkeey@googlemail.com>
+Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
+---
+ drivers/crypto/amcc/crypto4xx_core.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+--- a/drivers/crypto/amcc/crypto4xx_core.c
++++ b/drivers/crypto/amcc/crypto4xx_core.c
+@@ -1114,7 +1114,9 @@ struct crypto4xx_alg_common crypto4xx_al
+ .cra_name = "cbc(aes)",
+ .cra_driver_name = "cbc-aes-ppc4xx",
+ .cra_priority = CRYPTO4XX_CRYPTO_PRIORITY,
+- .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
++ .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER |
++ CRYPTO_ALG_ASYNC |
++ CRYPTO_ALG_KERN_DRIVER_ONLY,
+ .cra_blocksize = AES_BLOCK_SIZE,
+ .cra_ctxsize = sizeof(struct crypto4xx_ctx),
+ .cra_type = &crypto_ablkcipher_type,
diff --git a/target/linux/apm821xx/patches-4.14/020-0004-crypto-crypto4xx-remove-extern-statement-before-func.patch b/target/linux/apm821xx/patches-4.14/020-0004-crypto-crypto4xx-remove-extern-statement-before-func.patch
new file mode 100644
index 0000000..cd61ac7
--- /dev/null
+++ b/target/linux/apm821xx/patches-4.14/020-0004-crypto-crypto4xx-remove-extern-statement-before-func.patch
@@ -0,0 +1,76 @@
+From 886c251fd4ca40a27697afec7bc44c115e803d78 Mon Sep 17 00:00:00 2001
+From: Christian Lamparter <chunkeey@googlemail.com>
+Date: Fri, 25 Aug 2017 15:47:17 +0200
+Subject: [PATCH 04/25] crypto: crypto4xx - remove extern statement before
+ function declaration
+
+All function declarations are "extern" by default, there is no need to
+specify it explicitly.
+
+For C99 states in 6.2.2.5:
+"If the declaration of an identifier for a function has no
+storage-class specifier, its linkage is determined exactly
+as if it were declared with the storage-class specifier
+extern."
+
+Signed-off-by: Christian Lamparter <chunkeey@googlemail.com>
+Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
+---
+ drivers/crypto/amcc/crypto4xx_core.h | 48 ++++++++++++++++++------------------
+ 1 file changed, 24 insertions(+), 24 deletions(-)
+
+--- a/drivers/crypto/amcc/crypto4xx_core.h
++++ b/drivers/crypto/amcc/crypto4xx_core.h
+@@ -157,28 +157,28 @@ static inline struct crypto4xx_alg *cryp
+ return container_of(x, struct crypto4xx_alg, alg.u.cipher);
+ }
+
+-extern int crypto4xx_alloc_sa(struct crypto4xx_ctx *ctx, u32 size);
+-extern void crypto4xx_free_sa(struct crypto4xx_ctx *ctx);
+-extern void crypto4xx_free_ctx(struct crypto4xx_ctx *ctx);
+-extern u32 crypto4xx_alloc_state_record(struct crypto4xx_ctx *ctx);
+-extern u32 get_dynamic_sa_offset_state_ptr_field(struct crypto4xx_ctx *ctx);
+-extern u32 get_dynamic_sa_offset_key_field(struct crypto4xx_ctx *ctx);
+-extern u32 get_dynamic_sa_iv_size(struct crypto4xx_ctx *ctx);
+-extern void crypto4xx_memcpy_le(unsigned int *dst,
+- const unsigned char *buf, int len);
+-extern u32 crypto4xx_build_pd(struct crypto_async_request *req,
+- struct crypto4xx_ctx *ctx,
+- struct scatterlist *src,
+- struct scatterlist *dst,
+- unsigned int datalen,
+- void *iv, u32 iv_len);
+-extern int crypto4xx_setkey_aes_cbc(struct crypto_ablkcipher *cipher,
+- const u8 *key, unsigned int keylen);
+-extern int crypto4xx_encrypt(struct ablkcipher_request *req);
+-extern int crypto4xx_decrypt(struct ablkcipher_request *req);
+-extern int crypto4xx_sha1_alg_init(struct crypto_tfm *tfm);
+-extern int crypto4xx_hash_digest(struct ahash_request *req);
+-extern int crypto4xx_hash_final(struct ahash_request *req);
+-extern int crypto4xx_hash_update(struct ahash_request *req);
+-extern int crypto4xx_hash_init(struct ahash_request *req);
++int crypto4xx_alloc_sa(struct crypto4xx_ctx *ctx, u32 size);
++void crypto4xx_free_sa(struct crypto4xx_ctx *ctx);
++void crypto4xx_free_ctx(struct crypto4xx_ctx *ctx);
++u32 crypto4xx_alloc_state_record(struct crypto4xx_ctx *ctx);
++u32 get_dynamic_sa_offset_state_ptr_field(struct crypto4xx_ctx *ctx);
++u32 get_dynamic_sa_offset_key_field(struct crypto4xx_ctx *ctx);
++u32 get_dynamic_sa_iv_size(struct crypto4xx_ctx *ctx);
++void crypto4xx_memcpy_le(unsigned int *dst,
++ const unsigned char *buf, int len);
++u32 crypto4xx_build_pd(struct crypto_async_request *req,
++ struct crypto4xx_ctx *ctx,
++ struct scatterlist *src,
++ struct scatterlist *dst,
++ unsigned int datalen,
++ void *iv, u32 iv_len);
++int crypto4xx_setkey_aes_cbc(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_sha1_alg_init(struct crypto_tfm *tfm);
++int crypto4xx_hash_digest(struct ahash_request *req);
++int crypto4xx_hash_final(struct ahash_request *req);
++int crypto4xx_hash_update(struct ahash_request *req);
++int crypto4xx_hash_init(struct ahash_request *req);
+ #endif
diff --git a/target/linux/apm821xx/patches-4.14/020-0005-crypto-crypto4xx-remove-double-assignment-of-pd_uinf.patch b/target/linux/apm821xx/patches-4.14/020-0005-crypto-crypto4xx-remove-double-assignment-of-pd_uinf.patch
new file mode 100644
index 0000000..4fc3617
--- /dev/null
+++ b/target/linux/apm821xx/patches-4.14/020-0005-crypto-crypto4xx-remove-double-assignment-of-pd_uinf.patch
@@ -0,0 +1,24 @@
+From c587e65deacf8c86de2d7c51f1e81d0a4a9147a8 Mon Sep 17 00:00:00 2001
+From: Christian Lamparter <chunkeey@googlemail.com>
+Date: Fri, 25 Aug 2017 15:47:18 +0200
+Subject: [PATCH 05/25] crypto: crypto4xx - remove double assignment of
+ pd_uinfo->state
+
+crypto4xx_put_pd_to_pdr() already clears the flag.
+
+Signed-off-by: Christian Lamparter <chunkeey@googlemail.com>
+Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
+---
+ drivers/crypto/amcc/crypto4xx_core.c | 1 -
+ 1 file changed, 1 deletion(-)
+
+--- a/drivers/crypto/amcc/crypto4xx_core.c
++++ b/drivers/crypto/amcc/crypto4xx_core.c
+@@ -1079,7 +1079,6 @@ static void crypto4xx_bh_tasklet_cb(unsi
+ pd->pd_ctl.bf.pe_done = 0;
+ crypto4xx_pd_done(core_dev->dev, tail);
+ crypto4xx_put_pd_to_pdr(core_dev->dev, tail);
+- pd_uinfo->state = PD_ENTRY_FREE;
+ } else {
+ /* if tail not done, break */
+ break;
diff --git a/target/linux/apm821xx/patches-4.14/020-0006-crypto-crypto4xx-fix-dynamic_sa_ctl-s-sa_contents-de.patch b/target/linux/apm821xx/patches-4.14/020-0006-crypto-crypto4xx-fix-dynamic_sa_ctl-s-sa_contents-de.patch
new file mode 100644
index 0000000..84063d3
--- /dev/null
+++ b/target/linux/apm821xx/patches-4.14/020-0006-crypto-crypto4xx-fix-dynamic_sa_ctl-s-sa_contents-de.patch
@@ -0,0 +1,87 @@
+From 453e3090b9c3f5da70b21648c2244e9821f0916d Mon Sep 17 00:00:00 2001
+From: Christian Lamparter <chunkeey@googlemail.com>
+Date: Fri, 25 Aug 2017 15:47:19 +0200
+Subject: [PATCH 06/25] crypto: crypto4xx - fix dynamic_sa_ctl's sa_contents
+ declaration
+
+The driver had a union dynamic_sa_contents in place that
+described the meaning of the bits in the sa_contents
+variable.
+
+Signed-off-by: Christian Lamparter <chunkeey@googlemail.com>
+Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
+---
+ drivers/crypto/amcc/crypto4xx_alg.c | 4 ++--
+ drivers/crypto/amcc/crypto4xx_sa.c | 12 ++++++------
+ drivers/crypto/amcc/crypto4xx_sa.h | 2 +-
+ 3 files changed, 9 insertions(+), 9 deletions(-)
+
+--- a/drivers/crypto/amcc/crypto4xx_alg.c
++++ b/drivers/crypto/amcc/crypto4xx_alg.c
+@@ -149,7 +149,7 @@ static int crypto4xx_setkey_aes(struct c
+ SA_NOT_COPY_HDR);
+ crypto4xx_memcpy_le(ctx->sa_in + get_dynamic_sa_offset_key_field(ctx),
+ key, keylen);
+- sa->sa_contents = SA_AES_CONTENTS | (keylen << 2);
++ sa->sa_contents.w = SA_AES_CONTENTS | (keylen << 2);
+ sa->sa_command_1.bf.key_len = keylen >> 3;
+ ctx->is_hash = 0;
+ ctx->direction = DIR_INBOUND;
+@@ -219,7 +219,7 @@ static int crypto4xx_hash_alg_init(struc
+ SA_NOT_COPY_PAD, SA_NOT_COPY_PAYLOAD,
+ SA_NOT_COPY_HDR);
+ ctx->direction = DIR_INBOUND;
+- sa->sa_contents = SA_HASH160_CONTENTS;
++ sa->sa_contents.w = SA_HASH160_CONTENTS;
+ sa_in = (struct dynamic_sa_hash160 *) ctx->sa_in;
+ /* Need to zero hash digest in SA */
+ memset(sa_in->inner_digest, 0, sizeof(sa_in->inner_digest));
+--- a/drivers/crypto/amcc/crypto4xx_sa.c
++++ b/drivers/crypto/amcc/crypto4xx_sa.c
+@@ -40,9 +40,9 @@ u32 get_dynamic_sa_offset_state_ptr_fiel
+ union dynamic_sa_contents cts;
+
+ if (ctx->direction == DIR_INBOUND)
+- cts.w = ((struct dynamic_sa_ctl *) ctx->sa_in)->sa_contents;
++ cts.w = ((struct dynamic_sa_ctl *) ctx->sa_in)->sa_contents.w;
+ else
+- cts.w = ((struct dynamic_sa_ctl *) ctx->sa_out)->sa_contents;
++ cts.w = ((struct dynamic_sa_ctl *) ctx->sa_out)->sa_contents.w;
+ offset = cts.bf.key_size
+ + cts.bf.inner_size
+ + cts.bf.outer_size
+@@ -66,9 +66,9 @@ u32 get_dynamic_sa_iv_size(struct crypto
+ union dynamic_sa_contents cts;
+
+ if (ctx->direction == DIR_INBOUND)
+- cts.w = ((struct dynamic_sa_ctl *) ctx->sa_in)->sa_contents;
++ cts.w = ((struct dynamic_sa_ctl *) ctx->sa_in)->sa_contents.w;
+ else
+- cts.w = ((struct dynamic_sa_ctl *) ctx->sa_out)->sa_contents;
++ cts.w = ((struct dynamic_sa_ctl *) ctx->sa_out)->sa_contents.w;
+ return (cts.bf.iv0 + cts.bf.iv1 + cts.bf.iv2 + cts.bf.iv3) * 4;
+ }
+
+@@ -77,9 +77,9 @@ u32 get_dynamic_sa_offset_key_field(stru
+ union dynamic_sa_contents cts;
+
+ if (ctx->direction == DIR_INBOUND)
+- cts.w = ((struct dynamic_sa_ctl *) ctx->sa_in)->sa_contents;
++ cts.w = ((struct dynamic_sa_ctl *) ctx->sa_in)->sa_contents.w;
+ else
+- cts.w = ((struct dynamic_sa_ctl *) ctx->sa_out)->sa_contents;
++ cts.w = ((struct dynamic_sa_ctl *) ctx->sa_out)->sa_contents.w;
+
+ return sizeof(struct dynamic_sa_ctl);
+ }
+--- a/drivers/crypto/amcc/crypto4xx_sa.h
++++ b/drivers/crypto/amcc/crypto4xx_sa.h
+@@ -169,7 +169,7 @@ union sa_command_1 {
+ } __attribute__((packed));
+
+ struct dynamic_sa_ctl {
+- u32 sa_contents;
++ union dynamic_sa_contents sa_contents;
+ union sa_command_0 sa_command_0;
+ union sa_command_1 sa_command_1;
+ } __attribute__((packed));
diff --git a/target/linux/apm821xx/patches-4.14/020-0007-crypto-crypto4xx-move-and-refactor-dynamic_contents-.patch b/target/linux/apm821xx/patches-4.14/020-0007-crypto-crypto4xx-move-and-refactor-dynamic_contents-.patch
new file mode 100644
index 0000000..c7c32e5
--- /dev/null
+++ b/target/linux/apm821xx/patches-4.14/020-0007-crypto-crypto4xx-move-and-refactor-dynamic_contents-.patch
@@ -0,0 +1,234 @@
+From 249c8d98ea339325dca481d5dae93686cd494059 Mon Sep 17 00:00:00 2001
+From: Christian Lamparter <chunkeey@googlemail.com>
+Date: Fri, 25 Aug 2017 15:47:20 +0200
+Subject: [PATCH 07/25] crypto: crypto4xx - move and refactor dynamic_contents
+ helpers
+
+This patch refactors and moves the dynamic_contents helper
+functions into the crypto4xx_sa.h header file.
+
+ * get_dynamic_sa_iv_size is no longer needed, as the cryptoapi
+ provides the required IV size information as well.
+
+ * refactor the function declarations to use the a pointer to the
+ dynamic_sa_contents union, instead of the crypto4xx_ctx.
+
+ * rename get_dynamic_sa_offset_key_field to get_dynamic_sa_key_field.
+ It returns the pointer to the key directly.
+
+Signed-off-by: Christian Lamparter <chunkeey@googlemail.com>
+Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
+---
+ drivers/crypto/amcc/Makefile | 2 +-
+ drivers/crypto/amcc/crypto4xx_alg.c | 20 ++++-----
+ drivers/crypto/amcc/crypto4xx_core.h | 3 --
+ drivers/crypto/amcc/crypto4xx_sa.c | 85 ------------------------------------
+ drivers/crypto/amcc/crypto4xx_sa.h | 28 ++++++++++++
+ 5 files changed, 39 insertions(+), 99 deletions(-)
+ delete mode 100644 drivers/crypto/amcc/crypto4xx_sa.c
+
+--- a/drivers/crypto/amcc/Makefile
++++ b/drivers/crypto/amcc/Makefile
+@@ -1,3 +1,3 @@
+ obj-$(CONFIG_CRYPTO_DEV_PPC4XX) += crypto4xx.o
+-crypto4xx-y := crypto4xx_core.o crypto4xx_alg.o crypto4xx_sa.o
++crypto4xx-y := crypto4xx_core.o crypto4xx_alg.o
+ crypto4xx-$(CONFIG_HW_RANDOM_PPC4XX) += crypto4xx_trng.o
+--- a/drivers/crypto/amcc/crypto4xx_alg.c
++++ b/drivers/crypto/amcc/crypto4xx_alg.c
+@@ -29,8 +29,8 @@
+ #include <crypto/aes.h>
+ #include <crypto/sha.h>
+ #include "crypto4xx_reg_def.h"
+-#include "crypto4xx_sa.h"
+ #include "crypto4xx_core.h"
++#include "crypto4xx_sa.h"
+
+ static void set_dynamic_sa_command_0(struct dynamic_sa_ctl *sa, u32 save_h,
+ u32 save_iv, u32 ld_h, u32 ld_iv,
+@@ -79,8 +79,8 @@ int crypto4xx_encrypt(struct ablkcipher_
+ ctx->pd_ctl = 0x1;
+
+ return crypto4xx_build_pd(&req->base, ctx, req->src, req->dst,
+- req->nbytes, req->info,
+- get_dynamic_sa_iv_size(ctx));
++ req->nbytes, req->info,
++ crypto_ablkcipher_ivsize(crypto_ablkcipher_reqtfm(req)));
+ }
+
+ int crypto4xx_decrypt(struct ablkcipher_request *req)
+@@ -92,8 +92,8 @@ int crypto4xx_decrypt(struct ablkcipher_
+ ctx->pd_ctl = 1;
+
+ return crypto4xx_build_pd(&req->base, ctx, req->src, req->dst,
+- req->nbytes, req->info,
+- get_dynamic_sa_iv_size(ctx));
++ req->nbytes, req->info,
++ crypto_ablkcipher_ivsize(crypto_ablkcipher_reqtfm(req)));
+ }
+
+ /**
+@@ -147,15 +147,15 @@ static int crypto4xx_setkey_aes(struct c
+ SA_SEQ_MASK_OFF, SA_MC_ENABLE,
+ SA_NOT_COPY_PAD, SA_NOT_COPY_PAYLOAD,
+ SA_NOT_COPY_HDR);
+- crypto4xx_memcpy_le(ctx->sa_in + get_dynamic_sa_offset_key_field(ctx),
++ crypto4xx_memcpy_le(get_dynamic_sa_key_field(sa),
+ key, keylen);
+ sa->sa_contents.w = SA_AES_CONTENTS | (keylen << 2);
+ sa->sa_command_1.bf.key_len = keylen >> 3;
+ ctx->is_hash = 0;
+ ctx->direction = DIR_INBOUND;
+- memcpy(ctx->sa_in + get_dynamic_sa_offset_state_ptr_field(ctx),
+- (void *)&ctx->state_record_dma_addr, 4);
+- ctx->offset_to_sr_ptr = get_dynamic_sa_offset_state_ptr_field(ctx);
++ memcpy(sa + get_dynamic_sa_offset_state_ptr_field(sa),
++ (void *)&ctx->state_record_dma_addr, 4);
++ ctx->offset_to_sr_ptr = get_dynamic_sa_offset_state_ptr_field(sa);
+
+ memcpy(ctx->sa_out, ctx->sa_in, ctx->sa_len * 4);
+ sa = (struct dynamic_sa_ctl *) ctx->sa_out;
+@@ -225,7 +225,7 @@ static int crypto4xx_hash_alg_init(struc
+ memset(sa_in->inner_digest, 0, sizeof(sa_in->inner_digest));
+ memset(sa_in->outer_digest, 0, sizeof(sa_in->outer_digest));
+ sa_in->state_ptr = ctx->state_record_dma_addr;
+- ctx->offset_to_sr_ptr = get_dynamic_sa_offset_state_ptr_field(ctx);
++ ctx->offset_to_sr_ptr = get_dynamic_sa_offset_state_ptr_field(sa);
+
+ return 0;
+ }
+--- a/drivers/crypto/amcc/crypto4xx_core.h
++++ b/drivers/crypto/amcc/crypto4xx_core.h
+@@ -161,9 +161,6 @@ int crypto4xx_alloc_sa(struct crypto4xx_
+ void crypto4xx_free_sa(struct crypto4xx_ctx *ctx);
+ void crypto4xx_free_ctx(struct crypto4xx_ctx *ctx);
+ u32 crypto4xx_alloc_state_record(struct crypto4xx_ctx *ctx);
+-u32 get_dynamic_sa_offset_state_ptr_field(struct crypto4xx_ctx *ctx);
+-u32 get_dynamic_sa_offset_key_field(struct crypto4xx_ctx *ctx);
+-u32 get_dynamic_sa_iv_size(struct crypto4xx_ctx *ctx);
+ void crypto4xx_memcpy_le(unsigned int *dst,
+ const unsigned char *buf, int len);
+ u32 crypto4xx_build_pd(struct crypto_async_request *req,
+--- a/drivers/crypto/amcc/crypto4xx_sa.c
++++ /dev/null
+@@ -1,85 +0,0 @@
+-/**
+- * AMCC SoC PPC4xx Crypto Driver
+- *
+- * Copyright (c) 2008 Applied Micro Circuits Corporation.
+- * All rights reserved. James Hsiao <jhsiao@amcc.com>
+- *
+- * 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.
+- *
+- * @file crypto4xx_sa.c
+- *
+- * This file implements the security context
+- * associate format.
+- */
+-#include <linux/kernel.h>
+-#include <linux/module.h>
+-#include <linux/moduleparam.h>
+-#include <linux/mod_devicetable.h>
+-#include <linux/interrupt.h>
+-#include <linux/spinlock_types.h>
+-#include <linux/highmem.h>
+-#include <linux/scatterlist.h>
+-#include <linux/crypto.h>
+-#include <crypto/algapi.h>
+-#include <crypto/des.h>
+-#include "crypto4xx_reg_def.h"
+-#include "crypto4xx_sa.h"
+-#include "crypto4xx_core.h"
+-
+-u32 get_dynamic_sa_offset_state_ptr_field(struct crypto4xx_ctx *ctx)
+-{
+- u32 offset;
+- union dynamic_sa_contents cts;
+-
+- if (ctx->direction == DIR_INBOUND)
+- cts.w = ((struct dynamic_sa_ctl *) ctx->sa_in)->sa_contents.w;
+- else
+- cts.w = ((struct dynamic_sa_ctl *) ctx->sa_out)->sa_contents.w;
+- offset = cts.bf.key_size
+- + cts.bf.inner_size
+- + cts.bf.outer_size
+- + cts.bf.spi
+- + cts.bf.seq_num0
+- + cts.bf.seq_num1
+- + cts.bf.seq_num_mask0
+- + cts.bf.seq_num_mask1
+- + cts.bf.seq_num_mask2
+- + cts.bf.seq_num_mask3
+- + cts.bf.iv0
+- + cts.bf.iv1
+- + cts.bf.iv2
+- + cts.bf.iv3;
+-
+- return sizeof(struct dynamic_sa_ctl) + offset * 4;
+-}
+-
+-u32 get_dynamic_sa_iv_size(struct crypto4xx_ctx *ctx)
+-{
+- union dynamic_sa_contents cts;
+-
+- if (ctx->direction == DIR_INBOUND)
+- cts.w = ((struct dynamic_sa_ctl *) ctx->sa_in)->sa_contents.w;
+- else
+- cts.w = ((struct dynamic_sa_ctl *) ctx->sa_out)->sa_contents.w;
+- return (cts.bf.iv0 + cts.bf.iv1 + cts.bf.iv2 + cts.bf.iv3) * 4;
+-}
+-
+-u32 get_dynamic_sa_offset_key_field(struct crypto4xx_ctx *ctx)
+-{
+- union dynamic_sa_contents cts;
+-
+- if (ctx->direction == DIR_INBOUND)
+- cts.w = ((struct dynamic_sa_ctl *) ctx->sa_in)->sa_contents.w;
+- else
+- cts.w = ((struct dynamic_sa_ctl *) ctx->sa_out)->sa_contents.w;
+-
+- return sizeof(struct dynamic_sa_ctl);
+-}
+--- a/drivers/crypto/amcc/crypto4xx_sa.h
++++ b/drivers/crypto/amcc/crypto4xx_sa.h
+@@ -240,4 +240,32 @@ struct dynamic_sa_hash160 {
+ #define SA_HASH160_LEN (sizeof(struct dynamic_sa_hash160)/4)
+ #define SA_HASH160_CONTENTS 0x2000a502
+
++static inline u32
++get_dynamic_sa_offset_state_ptr_field(struct dynamic_sa_ctl *cts)
++{
++ u32 offset;
++
++ offset = cts->sa_contents.bf.key_size
++ + cts->sa_contents.bf.inner_size
++ + cts->sa_contents.bf.outer_size
++ + cts->sa_contents.bf.spi
++ + cts->sa_contents.bf.seq_num0
++ + cts->sa_contents.bf.seq_num1
++ + cts->sa_contents.bf.seq_num_mask0
++ + cts->sa_contents.bf.seq_num_mask1
++ + cts->sa_contents.bf.seq_num_mask2
++ + cts->sa_contents.bf.seq_num_mask3
++ + cts->sa_contents.bf.iv0
++ + cts->sa_contents.bf.iv1
++ + cts->sa_contents.bf.iv2
++ + cts->sa_contents.bf.iv3;
++
++ return sizeof(struct dynamic_sa_ctl) + offset * 4;
++}
++
++static inline u8 *get_dynamic_sa_key_field(struct dynamic_sa_ctl *cts)
++{
++ return (u8 *) ((unsigned long)cts + sizeof(struct dynamic_sa_ctl));
++}
++
+ #endif
diff --git a/target/linux/apm821xx/patches-4.14/020-0008-crypto-crypto4xx-enable-AES-RFC3686-ECB-CFB-and-OFB-.patch b/target/linux/apm821xx/patches-4.14/020-0008-crypto-crypto4xx-enable-AES-RFC3686-ECB-CFB-and-OFB-.patch
new file mode 100644
index 0000000..9977c60
--- /dev/null
+++ b/target/linux/apm821xx/patches-4.14/020-0008-crypto-crypto4xx-enable-AES-RFC3686-ECB-CFB-and-OFB-.patch
@@ -0,0 +1,248 @@
+From f2a13e7cba9e2b16f4888fbd9cf2bc25b95945be Mon Sep 17 00:00:00 2001
+From: Christian Lamparter <chunkeey@googlemail.com>
+Date: Fri, 25 Aug 2017 15:47:21 +0200
+Subject: [PATCH 08/25] crypto: crypto4xx - enable AES RFC3686, ECB, CFB and
+ OFB offloads
+
+The crypto engine supports more than just aes-cbc. This patch
+enables the remaining AES block cipher modes that pass the
+testmanager's test vectors.
+
+Signed-off-by: Christian Lamparter <chunkeey@googlemail.com>
+Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
+---
+ drivers/crypto/amcc/crypto4xx_alg.c | 66 ++++++++++++++++++++++++
+ drivers/crypto/amcc/crypto4xx_core.c | 98 ++++++++++++++++++++++++++++++++++++
+ drivers/crypto/amcc/crypto4xx_core.h | 10 ++++
+ drivers/crypto/amcc/crypto4xx_sa.h | 3 ++
+ 4 files changed, 177 insertions(+)
+
+--- a/drivers/crypto/amcc/crypto4xx_alg.c
++++ b/drivers/crypto/amcc/crypto4xx_alg.c
+@@ -28,6 +28,7 @@
+ #include <crypto/algapi.h>
+ #include <crypto/aes.h>
+ #include <crypto/sha.h>
++#include <crypto/ctr.h>
+ #include "crypto4xx_reg_def.h"
+ #include "crypto4xx_core.h"
+ #include "crypto4xx_sa.h"
+@@ -171,6 +172,71 @@ int crypto4xx_setkey_aes_cbc(struct cryp
+ CRYPTO_FEEDBACK_MODE_NO_FB);
+ }
+
++int crypto4xx_setkey_aes_cfb(struct crypto_ablkcipher *cipher,
++ const u8 *key, unsigned int keylen)
++{
++ return crypto4xx_setkey_aes(cipher, key, keylen, CRYPTO_MODE_CFB,
++ CRYPTO_FEEDBACK_MODE_128BIT_CFB);
++}
++
++int crypto4xx_setkey_aes_ecb(struct crypto_ablkcipher *cipher,
++ const u8 *key, unsigned int keylen)
++{
++ return crypto4xx_setkey_aes(cipher, key, keylen, CRYPTO_MODE_ECB,
++ CRYPTO_FEEDBACK_MODE_NO_FB);
++}
++
++int crypto4xx_setkey_aes_ofb(struct crypto_ablkcipher *cipher,
++ const u8 *key, unsigned int keylen)
++{
++ return crypto4xx_setkey_aes(cipher, key, keylen, CRYPTO_MODE_OFB,
++ CRYPTO_FEEDBACK_MODE_64BIT_OFB);
++}
++
++int crypto4xx_setkey_rfc3686(struct crypto_ablkcipher *cipher,
++ const u8 *key, unsigned int keylen)
++{
++ struct crypto_tfm *tfm = crypto_ablkcipher_tfm(cipher);
++ struct crypto4xx_ctx *ctx = crypto_tfm_ctx(tfm);
++ int rc;
++
++ rc = crypto4xx_setkey_aes(cipher, key, keylen - CTR_RFC3686_NONCE_SIZE,
++ CRYPTO_MODE_CTR, CRYPTO_FEEDBACK_MODE_NO_FB);
++ if (rc)
++ return rc;
++
++ memcpy(ctx->state_record,
++ key + keylen - CTR_RFC3686_NONCE_SIZE, CTR_RFC3686_NONCE_SIZE);
++
++ return 0;
++}
++
++int crypto4xx_rfc3686_encrypt(struct ablkcipher_request *req)
++{
++ struct crypto4xx_ctx *ctx = crypto_tfm_ctx(req->base.tfm);
++ __be32 iv[AES_IV_SIZE / 4] = { *(u32 *)ctx->state_record,
++ *(u32 *) req->info, *(u32 *) (req->info + 4), cpu_to_be32(1) };
++
++ ctx->direction = DIR_OUTBOUND;
++ ctx->pd_ctl = 1;
++
++ return crypto4xx_build_pd(&req->base, ctx, req->src, req->dst,
++ req->nbytes, iv, AES_IV_SIZE);
++}
++
++int crypto4xx_rfc3686_decrypt(struct ablkcipher_request *req)
++{
++ struct crypto4xx_ctx *ctx = crypto_tfm_ctx(req->base.tfm);
++ __be32 iv[AES_IV_SIZE / 4] = { *(u32 *)ctx->state_record,
++ *(u32 *) req->info, *(u32 *) (req->info + 4), cpu_to_be32(1) };
++
++ ctx->direction = DIR_INBOUND;
++ ctx->pd_ctl = 1;
++
++ return crypto4xx_build_pd(&req->base, ctx, req->src, req->dst,
++ req->nbytes, iv, AES_IV_SIZE);
++}
++
+ /**
+ * HASH SHA1 Functions
+ */
+--- a/drivers/crypto/amcc/crypto4xx_core.c
++++ b/drivers/crypto/amcc/crypto4xx_core.c
+@@ -36,6 +36,7 @@
+ #include <asm/dcr-regs.h>
+ #include <asm/cacheflush.h>
+ #include <crypto/aes.h>
++#include <crypto/ctr.h>
+ #include <crypto/sha.h>
+ #include "crypto4xx_reg_def.h"
+ #include "crypto4xx_core.h"
+@@ -1133,6 +1134,103 @@ struct crypto4xx_alg_common crypto4xx_al
+ }
+ }
+ }},
++ { .type = CRYPTO_ALG_TYPE_ABLKCIPHER, .u.cipher = {
++ .cra_name = "cfb(aes)",
++ .cra_driver_name = "cfb-aes-ppc4xx",
++ .cra_priority = CRYPTO4XX_CRYPTO_PRIORITY,
++ .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER |
++ CRYPTO_ALG_ASYNC |
++ CRYPTO_ALG_KERN_DRIVER_ONLY,
++ .cra_blocksize = AES_BLOCK_SIZE,
++ .cra_ctxsize = sizeof(struct crypto4xx_ctx),
++ .cra_type = &crypto_ablkcipher_type,
++ .cra_init = crypto4xx_alg_init,
++ .cra_exit = crypto4xx_alg_exit,
++ .cra_module = THIS_MODULE,
++ .cra_u = {
++ .ablkcipher = {
++ .min_keysize = AES_MIN_KEY_SIZE,
++ .max_keysize = AES_MAX_KEY_SIZE,
++ .ivsize = AES_IV_SIZE,
++ .setkey = crypto4xx_setkey_aes_cfb,
++ .encrypt = crypto4xx_encrypt,
++ .decrypt = crypto4xx_decrypt,
++ }
++ }
++ } },
++ { .type = CRYPTO_ALG_TYPE_ABLKCIPHER, .u.cipher = {
++ .cra_name = "rfc3686(ctr(aes))",
++ .cra_driver_name = "rfc3686-ctr-aes-ppc4xx",
++ .cra_priority = CRYPTO4XX_CRYPTO_PRIORITY,
++ .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER |
++ CRYPTO_ALG_ASYNC |
++ CRYPTO_ALG_KERN_DRIVER_ONLY,
++ .cra_blocksize = AES_BLOCK_SIZE,
++ .cra_ctxsize = sizeof(struct crypto4xx_ctx),
++ .cra_type = &crypto_ablkcipher_type,
++ .cra_init = crypto4xx_alg_init,
++ .cra_exit = crypto4xx_alg_exit,
++ .cra_module = THIS_MODULE,
++ .cra_u = {
++ .ablkcipher = {
++ .min_keysize = AES_MIN_KEY_SIZE +
++ CTR_RFC3686_NONCE_SIZE,
++ .max_keysize = AES_MAX_KEY_SIZE +
++ CTR_RFC3686_NONCE_SIZE,
++ .ivsize = CTR_RFC3686_IV_SIZE,
++ .setkey = crypto4xx_setkey_rfc3686,
++ .encrypt = crypto4xx_rfc3686_encrypt,
++ .decrypt = crypto4xx_rfc3686_decrypt,
++ }
++ }
++ } },
++ { .type = CRYPTO_ALG_TYPE_ABLKCIPHER, .u.cipher = {
++ .cra_name = "ecb(aes)",
++ .cra_driver_name = "ecb-aes-ppc4xx",
++ .cra_priority = CRYPTO4XX_CRYPTO_PRIORITY,
++ .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER |
++ CRYPTO_ALG_ASYNC |
++ CRYPTO_ALG_KERN_DRIVER_ONLY,
++ .cra_blocksize = AES_BLOCK_SIZE,
++ .cra_ctxsize = sizeof(struct crypto4xx_ctx),
++ .cra_type = &crypto_ablkcipher_type,
++ .cra_init = crypto4xx_alg_init,
++ .cra_exit = crypto4xx_alg_exit,
++ .cra_module = THIS_MODULE,
++ .cra_u = {
++ .ablkcipher = {
++ .min_keysize = AES_MIN_KEY_SIZE,
++ .max_keysize = AES_MAX_KEY_SIZE,
++ .setkey = crypto4xx_setkey_aes_ecb,
++ .encrypt = crypto4xx_encrypt,
++ .decrypt = crypto4xx_decrypt,
++ }
++ }
++ } },
++ { .type = CRYPTO_ALG_TYPE_ABLKCIPHER, .u.cipher = {
++ .cra_name = "ofb(aes)",
++ .cra_driver_name = "ofb-aes-ppc4xx",
++ .cra_priority = CRYPTO4XX_CRYPTO_PRIORITY,
++ .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER |
++ CRYPTO_ALG_ASYNC |
++ CRYPTO_ALG_KERN_DRIVER_ONLY,
++ .cra_blocksize = AES_BLOCK_SIZE,
++ .cra_ctxsize = sizeof(struct crypto4xx_ctx),
++ .cra_type = &crypto_ablkcipher_type,
++ .cra_init = crypto4xx_alg_init,
++ .cra_exit = crypto4xx_alg_exit,
++ .cra_module = THIS_MODULE,
++ .cra_u = {
++ .ablkcipher = {
++ .min_keysize = AES_MIN_KEY_SIZE,
++ .max_keysize = AES_MAX_KEY_SIZE,
++ .ivsize = AES_IV_SIZE,
++ .setkey = crypto4xx_setkey_aes_cbc,
++ .encrypt = crypto4xx_encrypt,
++ .decrypt = crypto4xx_decrypt,
++ }
++ }
++ } },
+ };
+
+ /**
+--- a/drivers/crypto/amcc/crypto4xx_core.h
++++ b/drivers/crypto/amcc/crypto4xx_core.h
+@@ -171,8 +171,18 @@ u32 crypto4xx_build_pd(struct crypto_asy
+ void *iv, u32 iv_len);
+ int crypto4xx_setkey_aes_cbc(struct crypto_ablkcipher *cipher,
+ const u8 *key, unsigned int keylen);
++int crypto4xx_setkey_aes_cfb(struct crypto_ablkcipher *cipher,
++ const u8 *key, unsigned int keylen);
++int crypto4xx_setkey_aes_ecb(struct crypto_ablkcipher *cipher,
++ const u8 *key, unsigned int keylen);
++int crypto4xx_setkey_aes_ofb(struct crypto_ablkcipher *cipher,
++ 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_rfc3686_encrypt(struct ablkcipher_request *req);
++int crypto4xx_rfc3686_decrypt(struct ablkcipher_request *req);
+ int crypto4xx_sha1_alg_init(struct crypto_tfm *tfm);
+ int crypto4xx_hash_digest(struct ahash_request *req);
+ int crypto4xx_hash_final(struct ahash_request *req);
+--- a/drivers/crypto/amcc/crypto4xx_sa.h
++++ b/drivers/crypto/amcc/crypto4xx_sa.h
+@@ -112,6 +112,9 @@ union sa_command_0 {
+
+ #define CRYPTO_MODE_ECB 0
+ #define CRYPTO_MODE_CBC 1
++#define CRYPTO_MODE_OFB 2
++#define CRYPTO_MODE_CFB 3
++#define CRYPTO_MODE_CTR 4
+
+ #define CRYPTO_FEEDBACK_MODE_NO_FB 0
+ #define CRYPTO_FEEDBACK_MODE_64BIT_OFB 0
diff --git a/target/linux/apm821xx/patches-4.14/020-0009-crypto-crypto4xx-refactor-crypto4xx_copy_pkt_to_dst.patch b/target/linux/apm821xx/patches-4.14/020-0009-crypto-crypto4xx-refactor-crypto4xx_copy_pkt_to_dst.patch
new file mode 100644
index 0000000..c6ccade
--- /dev/null
+++ b/target/linux/apm821xx/patches-4.14/020-0009-crypto-crypto4xx-refactor-crypto4xx_copy_pkt_to_dst.patch
@@ -0,0 +1,171 @@
+From 5c727f92ea5e019fd216f73009eee2b6e0867726 Mon Sep 17 00:00:00 2001
+From: Christian Lamparter <chunkeey@googlemail.com>
+Date: Fri, 25 Aug 2017 15:47:22 +0200
+Subject: [PATCH 09/25] crypto: crypto4xx - refactor
+ crypto4xx_copy_pkt_to_dst()
+
+This patch refactors the crypto4xx_copy_pkt_to_dst() to use
+scatterwalk_map_and_copy() to copy the processed data between
+the crypto engine's scatter ring buffer and the destination
+specified by the ablkcipher_request.
+
+This also makes the crypto4xx_fill_one_page() function redundant.
+
+Signed-off-by: Christian Lamparter <chunkeey@googlemail.com>
+Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
+---
+ drivers/crypto/amcc/crypto4xx_core.c | 126 +++++++++--------------------------
+ 1 file changed, 30 insertions(+), 96 deletions(-)
+
+--- a/drivers/crypto/amcc/crypto4xx_core.c
++++ b/drivers/crypto/amcc/crypto4xx_core.c
+@@ -38,6 +38,7 @@
+ #include <crypto/aes.h>
+ #include <crypto/ctr.h>
+ #include <crypto/sha.h>
++#include <crypto/scatterwalk.h>
+ #include "crypto4xx_reg_def.h"
+ #include "crypto4xx_core.h"
+ #include "crypto4xx_sa.h"
+@@ -481,111 +482,44 @@ static inline struct ce_sd *crypto4xx_ge
+ return (struct ce_sd *)(dev->sdr + sizeof(struct ce_sd) * idx);
+ }
+
+-static u32 crypto4xx_fill_one_page(struct crypto4xx_device *dev,
+- dma_addr_t *addr, u32 *length,
+- u32 *idx, u32 *offset, u32 *nbytes)
+-{
+- u32 len;
+-
+- if (*length > dev->scatter_buffer_size) {
+- memcpy(phys_to_virt(*addr),
+- dev->scatter_buffer_va +
+- *idx * dev->scatter_buffer_size + *offset,
+- dev->scatter_buffer_size);
+- *offset = 0;
+- *length -= dev->scatter_buffer_size;
+- *nbytes -= dev->scatter_buffer_size;
+- if (*idx == PPC4XX_LAST_SD)
+- *idx = 0;
+- else
+- (*idx)++;
+- *addr = *addr + dev->scatter_buffer_size;
+- return 1;
+- } else if (*length < dev->scatter_buffer_size) {
+- memcpy(phys_to_virt(*addr),
+- dev->scatter_buffer_va +
+- *idx * dev->scatter_buffer_size + *offset, *length);
+- if ((*offset + *length) == dev->scatter_buffer_size) {
+- if (*idx == PPC4XX_LAST_SD)
+- *idx = 0;
+- else
+- (*idx)++;
+- *nbytes -= *length;
+- *offset = 0;
+- } else {
+- *nbytes -= *length;
+- *offset += *length;
+- }
+-
+- return 0;
+- } else {
+- len = (*nbytes <= dev->scatter_buffer_size) ?
+- (*nbytes) : dev->scatter_buffer_size;
+- memcpy(phys_to_virt(*addr),
+- dev->scatter_buffer_va +
+- *idx * dev->scatter_buffer_size + *offset,
+- len);
+- *offset = 0;
+- *nbytes -= len;
+-
+- if (*idx == PPC4XX_LAST_SD)
+- *idx = 0;
+- else
+- (*idx)++;
+-
+- return 0;
+- }
+-}
+-
+ static void crypto4xx_copy_pkt_to_dst(struct crypto4xx_device *dev,
+ struct ce_pd *pd,
+ struct pd_uinfo *pd_uinfo,
+ u32 nbytes,
+ struct scatterlist *dst)
+ {
+- dma_addr_t addr;
+- u32 this_sd;
+- u32 offset;
+- u32 len;
+- u32 i;
+- u32 sg_len;
+- struct scatterlist *sg;
+-
+- this_sd = pd_uinfo->first_sd;
+- offset = 0;
+- i = 0;
++ unsigned int first_sd = pd_uinfo->first_sd;
++ unsigned int last_sd;
++ unsigned int overflow = 0;
++ unsigned int to_copy;
++ unsigned int dst_start = 0;
++
++ /*
++ * Because the scatter buffers are all neatly organized in one
++ * big continuous ringbuffer; scatterwalk_map_and_copy() can
++ * be instructed to copy a range of buffers in one go.
++ */
++
++ last_sd = (first_sd + pd_uinfo->num_sd);
++ if (last_sd > PPC4XX_LAST_SD) {
++ last_sd = PPC4XX_LAST_SD;
++ overflow = last_sd % PPC4XX_NUM_SD;
++ }
+
+ while (nbytes) {
+- sg = &dst[i];
+- sg_len = sg->length;
+- addr = dma_map_page(dev->core_dev->device, sg_page(sg),
+- sg->offset, sg->length, DMA_TO_DEVICE);
+-
+- if (offset == 0) {
+- len = (nbytes <= sg->length) ? nbytes : sg->length;
+- while (crypto4xx_fill_one_page(dev, &addr, &len,
+- &this_sd, &offset, &nbytes))
+- ;
+- if (!nbytes)
+- return;
+- i++;
+- } else {
+- len = (nbytes <= (dev->scatter_buffer_size - offset)) ?
+- nbytes : (dev->scatter_buffer_size - offset);
+- len = (sg->length < len) ? sg->length : len;
+- while (crypto4xx_fill_one_page(dev, &addr, &len,
+- &this_sd, &offset, &nbytes))
+- ;
+- if (!nbytes)
+- return;
+- sg_len -= len;
+- if (sg_len) {
+- addr += len;
+- while (crypto4xx_fill_one_page(dev, &addr,
+- &sg_len, &this_sd, &offset, &nbytes))
+- ;
+- }
+- i++;
++ void *buf = dev->scatter_buffer_va +
++ first_sd * PPC4XX_SD_BUFFER_SIZE;
++
++ to_copy = min(nbytes, PPC4XX_SD_BUFFER_SIZE *
++ (1 + last_sd - first_sd));
++ scatterwalk_map_and_copy(buf, dst, dst_start, to_copy, 1);
++ nbytes -= to_copy;
++
++ if (overflow) {
++ first_sd = 0;
++ last_sd = overflow;
++ dst_start += to_copy;
++ overflow = 0;
+ }
+ }
+ }
diff --git a/target/linux/apm821xx/patches-4.14/020-0010-crypto-crypto4xx-replace-crypto4xx_dev-s-scatter_buf.patch b/target/linux/apm821xx/patches-4.14/020-0010-crypto-crypto4xx-replace-crypto4xx_dev-s-scatter_buf.patch
new file mode 100644
index 0000000..90a6dab
--- /dev/null
+++ b/target/linux/apm821xx/patches-4.14/020-0010-crypto-crypto4xx-replace-crypto4xx_dev-s-scatter_buf.patch
@@ -0,0 +1,59 @@
+From 40e3b847bff70edc28c5290d209e531da6f9e534 Mon Sep 17 00:00:00 2001
+From: Christian Lamparter <chunkeey@googlemail.com>
+Date: Fri, 25 Aug 2017 15:47:23 +0200
+Subject: [PATCH 10/25] crypto: crypto4xx - replace crypto4xx_dev's
+ scatter_buffer_size with constant
+
+scatter_buffer_size is always set to PPC4XX_SD_BUFFER_SIZE.
+I don't think there's any point in keeping the variable
+around.
+
+Signed-off-by: Christian Lamparter <chunkeey@googlemail.com>
+Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
+---
+ drivers/crypto/amcc/crypto4xx_core.c | 7 +++----
+ drivers/crypto/amcc/crypto4xx_core.h | 1 -
+ 2 files changed, 3 insertions(+), 5 deletions(-)
+
+--- a/drivers/crypto/amcc/crypto4xx_core.c
++++ b/drivers/crypto/amcc/crypto4xx_core.c
+@@ -394,10 +394,9 @@ static u32 crypto4xx_build_sdr(struct cr
+ if (!dev->sdr)
+ return -ENOMEM;
+
+- dev->scatter_buffer_size = PPC4XX_SD_BUFFER_SIZE;
+ dev->scatter_buffer_va =
+ dma_alloc_coherent(dev->core_dev->device,
+- dev->scatter_buffer_size * PPC4XX_NUM_SD,
++ PPC4XX_SD_BUFFER_SIZE * PPC4XX_NUM_SD,
+ &dev->scatter_buffer_pa, GFP_ATOMIC);
+ if (!dev->scatter_buffer_va) {
+ dma_free_coherent(dev->core_dev->device,
+@@ -410,7 +409,7 @@ static u32 crypto4xx_build_sdr(struct cr
+
+ for (i = 0; i < PPC4XX_NUM_SD; i++) {
+ sd_array[i].ptr = dev->scatter_buffer_pa +
+- dev->scatter_buffer_size * i;
++ PPC4XX_SD_BUFFER_SIZE * i;
+ }
+
+ return 0;
+@@ -425,7 +424,7 @@ static void crypto4xx_destroy_sdr(struct
+
+ if (dev->scatter_buffer_va != NULL)
+ dma_free_coherent(dev->core_dev->device,
+- dev->scatter_buffer_size * PPC4XX_NUM_SD,
++ PPC4XX_SD_BUFFER_SIZE * PPC4XX_NUM_SD,
+ dev->scatter_buffer_va,
+ dev->scatter_buffer_pa);
+ }
+--- a/drivers/crypto/amcc/crypto4xx_core.h
++++ b/drivers/crypto/amcc/crypto4xx_core.h
+@@ -87,7 +87,6 @@ struct crypto4xx_device {
+ program ce sdr_base_register */
+ void *scatter_buffer_va;
+ dma_addr_t scatter_buffer_pa;
+- u32 scatter_buffer_size;
+
+ void *shadow_sa_pool; /* pool of memory for sa in pd_uinfo */
+ dma_addr_t shadow_sa_pool_pa;
diff --git a/target/linux/apm821xx/patches-4.14/020-0011-crypto-crypto4xx-fix-crypto4xx_build_pdr-crypto4xx_b.patch b/target/linux/apm821xx/patches-4.14/020-0011-crypto-crypto4xx-fix-crypto4xx_build_pdr-crypto4xx_b.patch
new file mode 100644
index 0000000..837fbdc
--- /dev/null
+++ b/target/linux/apm821xx/patches-4.14/020-0011-crypto-crypto4xx-fix-crypto4xx_build_pdr-crypto4xx_b.patch
@@ -0,0 +1,84 @@
+From 5d59ad6eea82ef8df92b4109615a0dde9d8093e9 Mon Sep 17 00:00:00 2001
+From: Christian Lamparter <chunkeey@googlemail.com>
+Date: Fri, 25 Aug 2017 15:47:24 +0200
+Subject: [PATCH 11/25] crypto: crypto4xx - fix crypto4xx_build_pdr,
+ crypto4xx_build_sdr leak
+
+If one of the later memory allocations in rypto4xx_build_pdr()
+fails: dev->pdr (and/or) dev->pdr_uinfo wouldn't be freed.
+
+crypto4xx_build_sdr() has the same issue with dev->sdr.
+
+Signed-off-by: Christian Lamparter <chunkeey@googlemail.com>
+Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
+---
+ drivers/crypto/amcc/crypto4xx_core.c | 17 +++++++++--------
+ 1 file changed, 9 insertions(+), 8 deletions(-)
+
+--- a/drivers/crypto/amcc/crypto4xx_core.c
++++ b/drivers/crypto/amcc/crypto4xx_core.c
+@@ -209,7 +209,7 @@ static u32 crypto4xx_build_pdr(struct cr
+ dev->pdr_pa);
+ return -ENOMEM;
+ }
+- memset(dev->pdr, 0, sizeof(struct ce_pd) * PPC4XX_NUM_PD);
++ memset(dev->pdr, 0, sizeof(struct ce_pd) * PPC4XX_NUM_PD);
+ dev->shadow_sa_pool = dma_alloc_coherent(dev->core_dev->device,
+ 256 * PPC4XX_NUM_PD,
+ &dev->shadow_sa_pool_pa,
+@@ -242,13 +242,15 @@ static u32 crypto4xx_build_pdr(struct cr
+
+ static void crypto4xx_destroy_pdr(struct crypto4xx_device *dev)
+ {
+- if (dev->pdr != NULL)
++ if (dev->pdr)
+ dma_free_coherent(dev->core_dev->device,
+ sizeof(struct ce_pd) * PPC4XX_NUM_PD,
+ dev->pdr, dev->pdr_pa);
++
+ if (dev->shadow_sa_pool)
+ dma_free_coherent(dev->core_dev->device, 256 * PPC4XX_NUM_PD,
+ dev->shadow_sa_pool, dev->shadow_sa_pool_pa);
++
+ if (dev->shadow_sr_pool)
+ dma_free_coherent(dev->core_dev->device,
+ sizeof(struct sa_state_record) * PPC4XX_NUM_PD,
+@@ -417,12 +419,12 @@ static u32 crypto4xx_build_sdr(struct cr
+
+ static void crypto4xx_destroy_sdr(struct crypto4xx_device *dev)
+ {
+- if (dev->sdr != NULL)
++ if (dev->sdr)
+ dma_free_coherent(dev->core_dev->device,
+ sizeof(struct ce_sd) * PPC4XX_NUM_SD,
+ dev->sdr, dev->sdr_pa);
+
+- if (dev->scatter_buffer_va != NULL)
++ if (dev->scatter_buffer_va)
+ dma_free_coherent(dev->core_dev->device,
+ PPC4XX_SD_BUFFER_SIZE * PPC4XX_NUM_SD,
+ dev->scatter_buffer_va,
+@@ -1223,7 +1225,7 @@ static int crypto4xx_probe(struct platfo
+
+ rc = crypto4xx_build_gdr(core_dev->dev);
+ if (rc)
+- goto err_build_gdr;
++ goto err_build_pdr;
+
+ rc = crypto4xx_build_sdr(core_dev->dev);
+ if (rc)
+@@ -1266,12 +1268,11 @@ err_iomap:
+ err_request_irq:
+ irq_dispose_mapping(core_dev->irq);
+ tasklet_kill(&core_dev->tasklet);
+- crypto4xx_destroy_sdr(core_dev->dev);
+ err_build_sdr:
++ crypto4xx_destroy_sdr(core_dev->dev);
+ crypto4xx_destroy_gdr(core_dev->dev);
+-err_build_gdr:
+- crypto4xx_destroy_pdr(core_dev->dev);
+ err_build_pdr:
++ crypto4xx_destroy_pdr(core_dev->dev);
+ kfree(core_dev->dev);
+ err_alloc_dev:
+ kfree(core_dev);
diff --git a/target/linux/apm821xx/patches-4.14/020-0012-crypto-crypto4xx-pointer-arithmetic-overhaul.patch b/target/linux/apm821xx/patches-4.14/020-0012-crypto-crypto4xx-pointer-arithmetic-overhaul.patch
new file mode 100644
index 0000000..ee7ee11
--- /dev/null
+++ b/target/linux/apm821xx/patches-4.14/020-0012-crypto-crypto4xx-pointer-arithmetic-overhaul.patch
@@ -0,0 +1,373 @@
+From 9e0a0b3a192af20193f074ed2ad9dd85a2e48d00 Mon Sep 17 00:00:00 2001
+From: Christian Lamparter <chunkeey@googlemail.com>
+Date: Fri, 25 Aug 2017 15:47:25 +0200
+Subject: [PATCH 12/25] crypto: crypto4xx - pointer arithmetic overhaul
+
+This patch improves the readability of various functions,
+by replacing various void* pointers declarations with
+their respective structs *. This makes it possible to go
+for the eye-friendly array-indexing methods.
+
+Signed-off-by: Christian Lamparter <chunkeey@googlemail.com>
+Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
+---
+ drivers/crypto/amcc/crypto4xx_alg.c | 26 ++++++++--------
+ drivers/crypto/amcc/crypto4xx_core.c | 60 +++++++++++++++---------------------
+ drivers/crypto/amcc/crypto4xx_core.h | 41 +++++++++++++-----------
+ 3 files changed, 59 insertions(+), 68 deletions(-)
+
+--- a/drivers/crypto/amcc/crypto4xx_alg.c
++++ b/drivers/crypto/amcc/crypto4xx_alg.c
+@@ -134,7 +134,7 @@ static int crypto4xx_setkey_aes(struct c
+ }
+ }
+ /* Setup SA */
+- sa = (struct dynamic_sa_ctl *) ctx->sa_in;
++ sa = ctx->sa_in;
+
+ set_dynamic_sa_command_0(sa, SA_NOT_SAVE_HASH, SA_NOT_SAVE_IV,
+ SA_LOAD_HASH_FROM_SA, SA_LOAD_IV_FROM_STATE,
+@@ -159,7 +159,7 @@ static int crypto4xx_setkey_aes(struct c
+ ctx->offset_to_sr_ptr = get_dynamic_sa_offset_state_ptr_field(sa);
+
+ memcpy(ctx->sa_out, ctx->sa_in, ctx->sa_len * 4);
+- sa = (struct dynamic_sa_ctl *) ctx->sa_out;
++ sa = ctx->sa_out;
+ sa->sa_command_0.bf.dir = DIR_OUTBOUND;
+
+ return 0;
+@@ -248,8 +248,7 @@ static int crypto4xx_hash_alg_init(struc
+ struct crypto_alg *alg = tfm->__crt_alg;
+ struct crypto4xx_alg *my_alg = crypto_alg_to_crypto4xx_alg(alg);
+ struct crypto4xx_ctx *ctx = crypto_tfm_ctx(tfm);
+- struct dynamic_sa_ctl *sa;
+- struct dynamic_sa_hash160 *sa_in;
++ struct dynamic_sa_hash160 *sa;
+ int rc;
+
+ ctx->dev = my_alg->dev;
+@@ -273,25 +272,24 @@ static int crypto4xx_hash_alg_init(struc
+
+ crypto_ahash_set_reqsize(__crypto_ahash_cast(tfm),
+ sizeof(struct crypto4xx_ctx));
+- sa = (struct dynamic_sa_ctl *) ctx->sa_in;
+- set_dynamic_sa_command_0(sa, SA_SAVE_HASH, SA_NOT_SAVE_IV,
++ sa = (struct dynamic_sa_hash160 *)ctx->sa_in;
++ set_dynamic_sa_command_0(&sa->ctrl, SA_SAVE_HASH, SA_NOT_SAVE_IV,
+ SA_NOT_LOAD_HASH, SA_LOAD_IV_FROM_SA,
+ SA_NO_HEADER_PROC, ha, SA_CIPHER_ALG_NULL,
+ SA_PAD_TYPE_ZERO, SA_OP_GROUP_BASIC,
+ SA_OPCODE_HASH, DIR_INBOUND);
+- set_dynamic_sa_command_1(sa, 0, SA_HASH_MODE_HASH,
++ set_dynamic_sa_command_1(&sa->ctrl, 0, SA_HASH_MODE_HASH,
+ CRYPTO_FEEDBACK_MODE_NO_FB, SA_EXTENDED_SN_OFF,
+ SA_SEQ_MASK_OFF, SA_MC_ENABLE,
+ SA_NOT_COPY_PAD, SA_NOT_COPY_PAYLOAD,
+ SA_NOT_COPY_HDR);
+ ctx->direction = DIR_INBOUND;
+- sa->sa_contents.w = SA_HASH160_CONTENTS;
+- sa_in = (struct dynamic_sa_hash160 *) ctx->sa_in;
+ /* Need to zero hash digest in SA */
+- memset(sa_in->inner_digest, 0, sizeof(sa_in->inner_digest));
+- memset(sa_in->outer_digest, 0, sizeof(sa_in->outer_digest));
+- sa_in->state_ptr = ctx->state_record_dma_addr;
+- ctx->offset_to_sr_ptr = get_dynamic_sa_offset_state_ptr_field(sa);
++ memset(sa->inner_digest, 0, sizeof(sa->inner_digest));
++ memset(sa->outer_digest, 0, sizeof(sa->outer_digest));
++ sa->state_ptr = ctx->state_record_dma_addr;
++ ctx->offset_to_sr_ptr =
++ get_dynamic_sa_offset_state_ptr_field(&sa->ctrl);
+
+ return 0;
+ }
+@@ -302,7 +300,7 @@ int crypto4xx_hash_init(struct ahash_req
+ int ds;
+ struct dynamic_sa_ctl *sa;
+
+- sa = (struct dynamic_sa_ctl *) ctx->sa_in;
++ sa = ctx->sa_in;
+ ds = crypto_ahash_digestsize(
+ __crypto_ahash_cast(req->base.tfm));
+ sa->sa_command_0.bf.digest_len = ds >> 2;
+--- a/drivers/crypto/amcc/crypto4xx_core.c
++++ b/drivers/crypto/amcc/crypto4xx_core.c
+@@ -211,7 +211,7 @@ static u32 crypto4xx_build_pdr(struct cr
+ }
+ memset(dev->pdr, 0, sizeof(struct ce_pd) * PPC4XX_NUM_PD);
+ dev->shadow_sa_pool = dma_alloc_coherent(dev->core_dev->device,
+- 256 * PPC4XX_NUM_PD,
++ sizeof(union shadow_sa_buf) * PPC4XX_NUM_PD,
+ &dev->shadow_sa_pool_pa,
+ GFP_ATOMIC);
+ if (!dev->shadow_sa_pool)
+@@ -223,16 +223,14 @@ static u32 crypto4xx_build_pdr(struct cr
+ if (!dev->shadow_sr_pool)
+ return -ENOMEM;
+ for (i = 0; i < PPC4XX_NUM_PD; i++) {
+- pd_uinfo = (struct pd_uinfo *) (dev->pdr_uinfo +
+- sizeof(struct pd_uinfo) * i);
++ pd_uinfo = &dev->pdr_uinfo[i];
+
+ /* alloc 256 bytes which is enough for any kind of dynamic sa */
+- pd_uinfo->sa_va = dev->shadow_sa_pool + 256 * i;
++ pd_uinfo->sa_va = &dev->shadow_sa_pool[i].sa;
+ pd_uinfo->sa_pa = dev->shadow_sa_pool_pa + 256 * i;
+
+ /* alloc state record */
+- pd_uinfo->sr_va = dev->shadow_sr_pool +
+- sizeof(struct sa_state_record) * i;
++ pd_uinfo->sr_va = &dev->shadow_sr_pool[i];
+ pd_uinfo->sr_pa = dev->shadow_sr_pool_pa +
+ sizeof(struct sa_state_record) * i;
+ }
+@@ -248,8 +246,9 @@ static void crypto4xx_destroy_pdr(struct
+ dev->pdr, dev->pdr_pa);
+
+ if (dev->shadow_sa_pool)
+- dma_free_coherent(dev->core_dev->device, 256 * PPC4XX_NUM_PD,
+- dev->shadow_sa_pool, dev->shadow_sa_pool_pa);
++ dma_free_coherent(dev->core_dev->device,
++ sizeof(union shadow_sa_buf) * PPC4XX_NUM_PD,
++ dev->shadow_sa_pool, dev->shadow_sa_pool_pa);
+
+ if (dev->shadow_sr_pool)
+ dma_free_coherent(dev->core_dev->device,
+@@ -277,11 +276,9 @@ static u32 crypto4xx_get_pd_from_pdr_nol
+
+ static u32 crypto4xx_put_pd_to_pdr(struct crypto4xx_device *dev, u32 idx)
+ {
+- struct pd_uinfo *pd_uinfo;
++ struct pd_uinfo *pd_uinfo = &dev->pdr_uinfo[idx];
+ unsigned long flags;
+
+- pd_uinfo = (struct pd_uinfo *)(dev->pdr_uinfo +
+- sizeof(struct pd_uinfo) * idx);
+ spin_lock_irqsave(&dev->core_dev->lock, flags);
+ if (dev->pdr_tail != PPC4XX_LAST_PD)
+ dev->pdr_tail++;
+@@ -298,7 +295,7 @@ static struct ce_pd *crypto4xx_get_pdp(s
+ {
+ *pd_dma = dev->pdr_pa + sizeof(struct ce_pd) * idx;
+
+- return dev->pdr + sizeof(struct ce_pd) * idx;
++ return &dev->pdr[idx];
+ }
+
+ /**
+@@ -376,7 +373,7 @@ static inline struct ce_gd *crypto4xx_ge
+ {
+ *gd_dma = dev->gdr_pa + sizeof(struct ce_gd) * idx;
+
+- return (struct ce_gd *) (dev->gdr + sizeof(struct ce_gd) * idx);
++ return &dev->gdr[idx];
+ }
+
+ /**
+@@ -387,7 +384,6 @@ static inline struct ce_gd *crypto4xx_ge
+ static u32 crypto4xx_build_sdr(struct crypto4xx_device *dev)
+ {
+ int i;
+- struct ce_sd *sd_array;
+
+ /* alloc memory for scatter descriptor ring */
+ dev->sdr = dma_alloc_coherent(dev->core_dev->device,
+@@ -407,10 +403,8 @@ static u32 crypto4xx_build_sdr(struct cr
+ return -ENOMEM;
+ }
+
+- sd_array = dev->sdr;
+-
+ for (i = 0; i < PPC4XX_NUM_SD; i++) {
+- sd_array[i].ptr = dev->scatter_buffer_pa +
++ dev->sdr[i].ptr = dev->scatter_buffer_pa +
+ PPC4XX_SD_BUFFER_SIZE * i;
+ }
+
+@@ -480,7 +474,7 @@ static inline struct ce_sd *crypto4xx_ge
+ {
+ *sd_dma = dev->sdr_pa + sizeof(struct ce_sd) * idx;
+
+- return (struct ce_sd *)(dev->sdr + sizeof(struct ce_sd) * idx);
++ return &dev->sdr[idx];
+ }
+
+ static void crypto4xx_copy_pkt_to_dst(struct crypto4xx_device *dev,
+@@ -529,11 +523,10 @@ static u32 crypto4xx_copy_digest_to_dst(
+ struct crypto4xx_ctx *ctx)
+ {
+ struct dynamic_sa_ctl *sa = (struct dynamic_sa_ctl *) ctx->sa_in;
+- struct sa_state_record *state_record =
+- (struct sa_state_record *) pd_uinfo->sr_va;
+
+ if (sa->sa_command_0.bf.hash_alg == SA_HASH_ALG_SHA1) {
+- memcpy((void *) pd_uinfo->dest_va, state_record->save_digest,
++ memcpy((void *) pd_uinfo->dest_va,
++ pd_uinfo->sr_va->save_digest,
+ SA_HASH_ALG_SHA1_DIGEST_SIZE);
+ }
+
+@@ -607,11 +600,9 @@ static u32 crypto4xx_ahash_done(struct c
+
+ static u32 crypto4xx_pd_done(struct crypto4xx_device *dev, u32 idx)
+ {
+- struct ce_pd *pd;
+- struct pd_uinfo *pd_uinfo;
++ struct ce_pd *pd = &dev->pdr[idx];
++ struct pd_uinfo *pd_uinfo = &dev->pdr_uinfo[idx];
+
+- pd = dev->pdr + sizeof(struct ce_pd)*idx;
+- pd_uinfo = dev->pdr_uinfo + sizeof(struct pd_uinfo)*idx;
+ if (crypto_tfm_alg_type(pd_uinfo->async_req->tfm) ==
+ CRYPTO_ALG_TYPE_ABLKCIPHER)
+ return crypto4xx_ablkcipher_done(dev, pd_uinfo, pd);
+@@ -712,7 +703,6 @@ u32 crypto4xx_build_pd(struct crypto_asy
+ unsigned long flags;
+ struct pd_uinfo *pd_uinfo = NULL;
+ unsigned int nbytes = datalen, idx;
+- unsigned int ivlen = 0;
+ u32 gd_idx = 0;
+
+ /* figure how many gd is needed */
+@@ -771,17 +761,15 @@ u32 crypto4xx_build_pd(struct crypto_asy
+ }
+ spin_unlock_irqrestore(&dev->core_dev->lock, flags);
+
+- pd_uinfo = (struct pd_uinfo *)(dev->pdr_uinfo +
+- sizeof(struct pd_uinfo) * pd_entry);
++ pd_uinfo = &dev->pdr_uinfo[pd_entry];
+ pd = crypto4xx_get_pdp(dev, &pd_dma, pd_entry);
+ pd_uinfo->async_req = req;
+ pd_uinfo->num_gd = num_gd;
+ pd_uinfo->num_sd = num_sd;
+
+ if (iv_len || ctx->is_hash) {
+- ivlen = iv_len;
+ pd->sa = pd_uinfo->sa_pa;
+- sa = (struct dynamic_sa_ctl *) pd_uinfo->sa_va;
++ sa = pd_uinfo->sa_va;
+ if (ctx->direction == DIR_INBOUND)
+ memcpy(sa, ctx->sa_in, ctx->sa_len * 4);
+ else
+@@ -791,14 +779,15 @@ u32 crypto4xx_build_pd(struct crypto_asy
+ &pd_uinfo->sr_pa, 4);
+
+ if (iv_len)
+- crypto4xx_memcpy_le(pd_uinfo->sr_va, iv, iv_len);
++ crypto4xx_memcpy_le(pd_uinfo->sr_va->save_iv,
++ iv, iv_len);
+ } else {
+ if (ctx->direction == DIR_INBOUND) {
+ pd->sa = ctx->sa_in_dma_addr;
+- sa = (struct dynamic_sa_ctl *) ctx->sa_in;
++ sa = ctx->sa_in;
+ } else {
+ pd->sa = ctx->sa_out_dma_addr;
+- sa = (struct dynamic_sa_ctl *) ctx->sa_out;
++ sa = ctx->sa_out;
+ }
+ }
+ pd->sa_len = ctx->sa_len;
+@@ -1006,9 +995,8 @@ static void crypto4xx_bh_tasklet_cb(unsi
+
+ while (core_dev->dev->pdr_head != core_dev->dev->pdr_tail) {
+ tail = core_dev->dev->pdr_tail;
+- pd_uinfo = core_dev->dev->pdr_uinfo +
+- sizeof(struct pd_uinfo)*tail;
+- pd = core_dev->dev->pdr + sizeof(struct ce_pd) * tail;
++ pd_uinfo = &core_dev->dev->pdr_uinfo[tail];
++ pd = &core_dev->dev->pdr[tail];
+ if ((pd_uinfo->state == PD_ENTRY_INUSE) &&
+ pd->pd_ctl.bf.pe_done &&
+ !pd->pd_ctl.bf.host_ready) {
+--- a/drivers/crypto/amcc/crypto4xx_core.h
++++ b/drivers/crypto/amcc/crypto4xx_core.h
+@@ -23,6 +23,8 @@
+ #define __CRYPTO4XX_CORE_H__
+
+ #include <crypto/internal/hash.h>
++#include "crypto4xx_reg_def.h"
++#include "crypto4xx_sa.h"
+
+ #define MODULE_NAME "crypto4xx"
+
+@@ -48,6 +50,13 @@
+
+ struct crypto4xx_device;
+
++union shadow_sa_buf {
++ struct dynamic_sa_ctl sa;
++
++ /* alloc 256 bytes which is enough for any kind of dynamic sa */
++ u8 buf[256];
++} __packed;
++
+ struct pd_uinfo {
+ struct crypto4xx_device *dev;
+ u32 state;
+@@ -60,9 +69,9 @@ struct pd_uinfo {
+ used by this packet */
+ u32 num_sd; /* number of scatter discriptors
+ used by this packet */
+- void *sa_va; /* shadow sa, when using cp from ctx->sa */
++ struct dynamic_sa_ctl *sa_va; /* shadow sa */
+ u32 sa_pa;
+- void *sr_va; /* state record for shadow sa */
++ struct sa_state_record *sr_va; /* state record for shadow sa */
+ u32 sr_pa;
+ struct scatterlist *dest_va;
+ struct crypto_async_request *async_req; /* base crypto request
+@@ -75,22 +84,18 @@ struct crypto4xx_device {
+ void __iomem *ce_base;
+ void __iomem *trng_base;
+
+- void *pdr; /* base address of packet
+- descriptor ring */
+- dma_addr_t pdr_pa; /* physical address used to
+- program ce pdr_base_register */
+- void *gdr; /* gather descriptor ring */
+- dma_addr_t gdr_pa; /* physical address used to
+- program ce gdr_base_register */
+- void *sdr; /* scatter descriptor ring */
+- dma_addr_t sdr_pa; /* physical address used to
+- program ce sdr_base_register */
++ struct ce_pd *pdr; /* base address of packet descriptor ring */
++ dma_addr_t pdr_pa; /* physical address of pdr_base_register */
++ struct ce_gd *gdr; /* gather descriptor ring */
++ dma_addr_t gdr_pa; /* physical address of gdr_base_register */
++ struct ce_sd *sdr; /* scatter descriptor ring */
++ dma_addr_t sdr_pa; /* physical address of sdr_base_register */
+ void *scatter_buffer_va;
+ dma_addr_t scatter_buffer_pa;
+
+- void *shadow_sa_pool; /* pool of memory for sa in pd_uinfo */
++ union shadow_sa_buf *shadow_sa_pool;
+ dma_addr_t shadow_sa_pool_pa;
+- void *shadow_sr_pool; /* pool of memory for sr in pd_uinfo */
++ struct sa_state_record *shadow_sr_pool;
+ dma_addr_t shadow_sr_pool_pa;
+ u32 pdr_tail;
+ u32 pdr_head;
+@@ -98,7 +103,7 @@ struct crypto4xx_device {
+ u32 gdr_head;
+ u32 sdr_tail;
+ u32 sdr_head;
+- void *pdr_uinfo;
++ struct pd_uinfo *pdr_uinfo;
+ struct list_head alg_list; /* List of algorithm supported
+ by this device */
+ };
+@@ -116,11 +121,11 @@ struct crypto4xx_core_device {
+
+ struct crypto4xx_ctx {
+ struct crypto4xx_device *dev;
+- void *sa_in;
++ struct dynamic_sa_ctl *sa_in;
+ dma_addr_t sa_in_dma_addr;
+- void *sa_out;
++ struct dynamic_sa_ctl *sa_out;
+ dma_addr_t sa_out_dma_addr;
+- void *state_record;
++ struct sa_state_record *state_record;
+ dma_addr_t state_record_dma_addr;
+ u32 sa_len;
+ u32 offset_to_sr_ptr; /* offset to state ptr, in dynamic sa */
diff --git a/target/linux/apm821xx/patches-4.14/020-0013-crypto-crypto4xx-wire-up-hmac_mc-to-hmac_muting.patch b/target/linux/apm821xx/patches-4.14/020-0013-crypto-crypto4xx-wire-up-hmac_mc-to-hmac_muting.patch
new file mode 100644
index 0000000..9ddfcb9
--- /dev/null
+++ b/target/linux/apm821xx/patches-4.14/020-0013-crypto-crypto4xx-wire-up-hmac_mc-to-hmac_muting.patch
@@ -0,0 +1,25 @@
+From 5a4326d3a03f03c2518a2c255be33a7114af3230 Mon Sep 17 00:00:00 2001
+From: Christian Lamparter <chunkeey@gmail.com>
+Date: Wed, 4 Oct 2017 01:00:05 +0200
+Subject: [PATCH 13/25] crypto: crypto4xx - wire up hmac_mc to hmac_muting
+
+The hmac_mc parameter of set_dynamic_sa_command_1()
+was defined but not used. On closer inspection it
+turns out, it was never wired up.
+
+Signed-off-by: Christian Lamparter <chunkeey@gmail.com>
+Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
+---
+ drivers/crypto/amcc/crypto4xx_alg.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/drivers/crypto/amcc/crypto4xx_alg.c
++++ b/drivers/crypto/amcc/crypto4xx_alg.c
+@@ -63,6 +63,7 @@ static void set_dynamic_sa_command_1(str
+ sa->sa_command_1.bf.crypto_mode9_8 = cm & 3;
+ sa->sa_command_1.bf.feedback_mode = cfb,
+ sa->sa_command_1.bf.sa_rev = 1;
++ sa->sa_command_1.bf.hmac_muting = hmac_mc;
+ sa->sa_command_1.bf.extended_seq_num = esn;
+ sa->sa_command_1.bf.seq_num_mask = sn_mask;
+ sa->sa_command_1.bf.mutable_bit_proc = mute;
diff --git a/target/linux/apm821xx/patches-4.14/020-0014-crypto-crypto4xx-fix-off-by-one-AES-OFB.patch b/target/linux/apm821xx/patches-4.14/020-0014-crypto-crypto4xx-fix-off-by-one-AES-OFB.patch
new file mode 100644
index 0000000..acded24
--- /dev/null
+++ b/target/linux/apm821xx/patches-4.14/020-0014-crypto-crypto4xx-fix-off-by-one-AES-OFB.patch
@@ -0,0 +1,49 @@
+From e9b8e4e1129d0886094cfe013cdbaafc4ce0de76 Mon Sep 17 00:00:00 2001
+From: Christian Lamparter <chunkeey@gmail.com>
+Date: Wed, 4 Oct 2017 01:00:06 +0200
+Subject: [PATCH 14/25] crypto: crypto4xx - fix off-by-one AES-OFB
+
+I used aes-cbc as a template for ofb. But sadly I forgot
+to update set_key method to crypto4xx_setkey_aes_ofb().
+
+this was caught by the testmgr:
+alg: skcipher: Test 1 failed (invalid result) on encr. for ofb-aes-ppc4xx
+00000000: 76 49 ab ac 81 19 b2 46 ce e9 8e 9b 12 e9 19 7d
+00000010: 50 86 cb 9b 50 72 19 ee 95 db 11 3a 91 76 78 b2
+00000020: 73 be d6 b8 e3 c1 74 3b 71 16 e6 9e 22 22 95 16
+00000030: 3f f1 ca a1 68 1f ac 09 12 0e ca 30 75 86 e1 a7
+
+With the correct set_key method, the aes-ofb cipher passes the test.
+
+name : ofb(aes)
+driver : ofb-aes-ppc4xx
+module : crypto4xx
+priority : 300
+refcnt : 1
+selftest : passed
+internal : no
+type : ablkcipher
+async : yes
+blocksize : 16
+min keysize : 16
+max keysize : 32
+ivsize : 16
+geniv : <default>
+
+Signed-off-by: Christian Lamparter <chunkeey@gmail.com>
+Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
+---
+ drivers/crypto/amcc/crypto4xx_core.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/crypto/amcc/crypto4xx_core.c
++++ b/drivers/crypto/amcc/crypto4xx_core.c
+@@ -1148,7 +1148,7 @@ struct crypto4xx_alg_common crypto4xx_al
+ .min_keysize = AES_MIN_KEY_SIZE,
+ .max_keysize = AES_MAX_KEY_SIZE,
+ .ivsize = AES_IV_SIZE,
+- .setkey = crypto4xx_setkey_aes_cbc,
++ .setkey = crypto4xx_setkey_aes_ofb,
+ .encrypt = crypto4xx_encrypt,
+ .decrypt = crypto4xx_decrypt,
+ }
diff --git a/target/linux/apm821xx/patches-4.14/020-0015-crypto-crypto4xx-fix-type-mismatch-compiler-error.patch b/target/linux/apm821xx/patches-4.14/020-0015-crypto-crypto4xx-fix-type-mismatch-compiler-error.patch
new file mode 100644
index 0000000..f0f1d0e
--- /dev/null
+++ b/target/linux/apm821xx/patches-4.14/020-0015-crypto-crypto4xx-fix-type-mismatch-compiler-error.patch
@@ -0,0 +1,29 @@
+From 333eb3edda3842f3e5dbd723cb18bbe47eb0508b Mon Sep 17 00:00:00 2001
+From: Christian Lamparter <chunkeey@gmail.com>
+Date: Wed, 4 Oct 2017 01:00:07 +0200
+Subject: [PATCH 15/25] crypto: crypto4xx - fix type mismatch compiler error
+
+This patch fixes a type mismatch error that I accidentally
+introduced when I moved and refactored the dynamic_contents
+helpers.
+
+Signed-off-by: Christian Lamparter <chunkeey@gmail.com>
+Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
+---
+ drivers/crypto/amcc/crypto4xx_sa.h | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/drivers/crypto/amcc/crypto4xx_sa.h
++++ b/drivers/crypto/amcc/crypto4xx_sa.h
+@@ -266,9 +266,9 @@ get_dynamic_sa_offset_state_ptr_field(st
+ return sizeof(struct dynamic_sa_ctl) + offset * 4;
+ }
+
+-static inline u8 *get_dynamic_sa_key_field(struct dynamic_sa_ctl *cts)
++static inline u32 *get_dynamic_sa_key_field(struct dynamic_sa_ctl *cts)
+ {
+- return (u8 *) ((unsigned long)cts + sizeof(struct dynamic_sa_ctl));
++ return (u32 *) ((unsigned long)cts + sizeof(struct dynamic_sa_ctl));
+ }
+
+ #endif
diff --git a/target/linux/apm821xx/patches-4.14/020-0017-crypto-crypto4xx-add-backlog-queue-support.patch b/target/linux/apm821xx/patches-4.14/020-0017-crypto-crypto4xx-add-backlog-queue-support.patch
new file mode 100644
index 0000000..046dd9c
--- /dev/null
+++ b/target/linux/apm821xx/patches-4.14/020-0017-crypto-crypto4xx-add-backlog-queue-support.patch
@@ -0,0 +1,161 @@
+From 8ef8d195430ca3542d0434cf25e5115484b9fa32 Mon Sep 17 00:00:00 2001
+From: Christian Lamparter <chunkeey@gmail.com>
+Date: Wed, 4 Oct 2017 01:00:09 +0200
+Subject: [PATCH 17/25] crypto: crypto4xx - add backlog queue support
+
+Previously, If the crypto4xx driver used all available
+security contexts, it would simply refuse new requests
+with -EAGAIN. CRYPTO_TFM_REQ_MAY_BACKLOG was ignored.
+
+in case of dm-crypt.c's crypt_convert() function this was
+causing the following errors to manifest, if the system was
+pushed hard enough:
+
+| EXT4-fs warning (dm-1): ext4_end_bio:314: I/O error -5 writing to ino ..
+| EXT4-fs warning (dm-1): ext4_end_bio:314: I/O error -5 writing to ino ..
+| EXT4-fs warning (dm-1): ext4_end_bio:314: I/O error -5 writing to ino ..
+| JBD2: Detected IO errors while flushing file data on dm-1-8
+| Aborting journal on device dm-1-8.
+| EXT4-fs error : ext4_journal_check_start:56: Detected aborted journal
+| EXT4-fs (dm-1): Remounting filesystem read-only
+| EXT4-fs : ext4_writepages: jbd2_start: 2048 pages, inode 498...; err -30
+
+(This did cause corruptions due to failed writes)
+
+To fix this mess, the crypto4xx driver needs to notifiy the
+user to slow down. This can be achieved by returning -EBUSY
+on requests, once the crypto hardware was falling behind.
+
+Note: -EBUSY has two different meanings. Setting the flag
+CRYPTO_TFM_REQ_MAY_BACKLOG implies that the request was
+successfully queued, by the crypto driver. To achieve this
+requirement, the implementation introduces a threshold check and
+adds logic to the completion routines in much the same way as
+AMD's Cryptographic Coprocessor (CCP) driver do.
+
+Note2: Tests showed that dm-crypt starved ipsec traffic.
+Under load, ipsec links dropped to 0 Kbits/s. This is because
+dm-crypt's callback would instantly queue the next request.
+In order to not starve ipsec, the driver reserves a small
+portion of the available crypto contexts for this purpose.
+
+Signed-off-by: Christian Lamparter <chunkeey@gmail.com>
+Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
+---
+ drivers/crypto/amcc/crypto4xx_core.c | 47 ++++++++++++++++++++++++++++++------
+ drivers/crypto/amcc/crypto4xx_core.h | 3 ++-
+ 2 files changed, 41 insertions(+), 9 deletions(-)
+
+--- a/drivers/crypto/amcc/crypto4xx_core.c
++++ b/drivers/crypto/amcc/crypto4xx_core.c
+@@ -39,6 +39,7 @@
+ #include <crypto/ctr.h>
+ #include <crypto/sha.h>
+ #include <crypto/scatterwalk.h>
++#include <crypto/internal/skcipher.h>
+ #include "crypto4xx_reg_def.h"
+ #include "crypto4xx_core.h"
+ #include "crypto4xx_sa.h"
+@@ -573,8 +574,10 @@ static u32 crypto4xx_ablkcipher_done(str
+ dst->offset, dst->length, DMA_FROM_DEVICE);
+ }
+ crypto4xx_ret_sg_desc(dev, pd_uinfo);
+- if (ablk_req->base.complete != NULL)
+- ablk_req->base.complete(&ablk_req->base, 0);
++
++ if (pd_uinfo->state & PD_ENTRY_BUSY)
++ ablkcipher_request_complete(ablk_req, -EINPROGRESS);
++ ablkcipher_request_complete(ablk_req, 0);
+
+ return 0;
+ }
+@@ -591,9 +594,10 @@ static u32 crypto4xx_ahash_done(struct c
+ crypto4xx_copy_digest_to_dst(pd_uinfo,
+ crypto_tfm_ctx(ahash_req->base.tfm));
+ crypto4xx_ret_sg_desc(dev, pd_uinfo);
+- /* call user provided callback function x */
+- if (ahash_req->base.complete != NULL)
+- ahash_req->base.complete(&ahash_req->base, 0);
++
++ if (pd_uinfo->state & PD_ENTRY_BUSY)
++ ahash_request_complete(ahash_req, -EINPROGRESS);
++ ahash_request_complete(ahash_req, 0);
+
+ return 0;
+ }
+@@ -704,6 +708,7 @@ u32 crypto4xx_build_pd(struct crypto_asy
+ struct pd_uinfo *pd_uinfo = NULL;
+ unsigned int nbytes = datalen, idx;
+ u32 gd_idx = 0;
++ bool is_busy;
+
+ /* figure how many gd is needed */
+ num_gd = sg_nents_for_len(src, datalen);
+@@ -734,6 +739,31 @@ u32 crypto4xx_build_pd(struct crypto_asy
+ * already got must be return the original place.
+ */
+ spin_lock_irqsave(&dev->core_dev->lock, flags);
++ /*
++ * Let the caller know to slow down, once more than 13/16ths = 81%
++ * of the available data contexts are being used simultaneously.
++ *
++ * With PPC4XX_NUM_PD = 256, this will leave a "backlog queue" for
++ * 31 more contexts. Before new requests have to be rejected.
++ */
++ if (req->flags & CRYPTO_TFM_REQ_MAY_BACKLOG) {
++ is_busy = ((dev->pdr_head - dev->pdr_tail) % PPC4XX_NUM_PD) >=
++ ((PPC4XX_NUM_PD * 13) / 16);
++ } else {
++ /*
++ * To fix contention issues between ipsec (no blacklog) and
++ * dm-crypto (backlog) reserve 32 entries for "no backlog"
++ * data contexts.
++ */
++ is_busy = ((dev->pdr_head - dev->pdr_tail) % PPC4XX_NUM_PD) >=
++ ((PPC4XX_NUM_PD * 15) / 16);
++
++ if (is_busy) {
++ spin_unlock_irqrestore(&dev->core_dev->lock, flags);
++ return -EBUSY;
++ }
++ }
++
+ if (num_gd) {
+ fst_gd = crypto4xx_get_n_gd(dev, num_gd);
+ if (fst_gd == ERING_WAS_FULL) {
+@@ -888,11 +918,12 @@ u32 crypto4xx_build_pd(struct crypto_asy
+ sa->sa_command_1.bf.hash_crypto_offset = 0;
+ pd->pd_ctl.w = ctx->pd_ctl;
+ pd->pd_ctl_len.w = 0x00400000 | datalen;
+- pd_uinfo->state = PD_ENTRY_INUSE;
++ pd_uinfo->state = PD_ENTRY_INUSE | (is_busy ? PD_ENTRY_BUSY : 0);
++
+ wmb();
+ /* write any value to push engine to read a pd */
+ writel(1, dev->ce_base + CRYPTO4XX_INT_DESCR_RD);
+- return -EINPROGRESS;
++ return is_busy ? -EBUSY : -EINPROGRESS;
+ }
+
+ /**
+@@ -997,7 +1028,7 @@ static void crypto4xx_bh_tasklet_cb(unsi
+ tail = core_dev->dev->pdr_tail;
+ pd_uinfo = &core_dev->dev->pdr_uinfo[tail];
+ pd = &core_dev->dev->pdr[tail];
+- if ((pd_uinfo->state == PD_ENTRY_INUSE) &&
++ if ((pd_uinfo->state & PD_ENTRY_INUSE) &&
+ pd->pd_ctl.bf.pe_done &&
+ !pd->pd_ctl.bf.host_ready) {
+ pd->pd_ctl.bf.pe_done = 0;
+--- a/drivers/crypto/amcc/crypto4xx_core.h
++++ b/drivers/crypto/amcc/crypto4xx_core.h
+@@ -44,7 +44,8 @@
+ #define PPC4XX_LAST_SD (PPC4XX_NUM_SD - 1)
+ #define PPC4XX_SD_BUFFER_SIZE 2048
+
+-#define PD_ENTRY_INUSE 1
++#define PD_ENTRY_BUSY BIT(1)
++#define PD_ENTRY_INUSE BIT(0)
+ #define PD_ENTRY_FREE 0
+ #define ERING_WAS_FULL 0xffffffff
+
diff --git a/target/linux/apm821xx/patches-4.14/020-0018-crypto-crypto4xx-use-the-correct-LE32-format-for-IV-.patch b/target/linux/apm821xx/patches-4.14/020-0018-crypto-crypto4xx-use-the-correct-LE32-format-for-IV-.patch
new file mode 100644
index 0000000..22d2a31
--- /dev/null
+++ b/target/linux/apm821xx/patches-4.14/020-0018-crypto-crypto4xx-use-the-correct-LE32-format-for-IV-.patch
@@ -0,0 +1,236 @@
+From 4865b122d4aff5151c88d2f7442d5a87f7e795ae Mon Sep 17 00:00:00 2001
+From: Christian Lamparter <chunkeey@gmail.com>
+Date: Wed, 4 Oct 2017 01:00:10 +0200
+Subject: [PATCH 18/25] crypto: crypto4xx - use the correct LE32 format for IV
+ and key defs
+
+The hardware expects that the keys, IVs (and inner/outer hashes)
+are in the le32 format.
+
+This patch changes all hardware interface declarations to use
+the correct LE32 data format for each field.
+
+In order to pass __CHECK_ENDIAN__ checks, crypto4xx_memcpy_le
+has to be honest about the endianness of its parameters.
+The function was split and moved to the common crypto4xx_core.h
+header. This allows the compiler to generate better code if the
+sizes/len is a constant (various *_IV_LEN).
+
+Please note that the hardware isn't consistent with the endiannes
+of the save_digest field in the state record struct though.
+The hashes produced by GHASH and CBC (for CCM) will be in LE32.
+Whereas md5 and sha{1/,256,...} do not need any conversion.
+
+Signed-off-by: Christian Lamparter <chunkeey@gmail.com>
+Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
+---
+ drivers/crypto/amcc/crypto4xx_alg.c | 4 +--
+ drivers/crypto/amcc/crypto4xx_core.c | 40 ++----------------------------
+ drivers/crypto/amcc/crypto4xx_core.h | 47 +++++++++++++++++++++++++++++++++---
+ drivers/crypto/amcc/crypto4xx_sa.h | 29 ++++++++++++----------
+ 4 files changed, 64 insertions(+), 56 deletions(-)
+
+--- a/drivers/crypto/amcc/crypto4xx_alg.c
++++ b/drivers/crypto/amcc/crypto4xx_alg.c
+@@ -149,8 +149,8 @@ static int crypto4xx_setkey_aes(struct c
+ SA_SEQ_MASK_OFF, SA_MC_ENABLE,
+ SA_NOT_COPY_PAD, SA_NOT_COPY_PAYLOAD,
+ SA_NOT_COPY_HDR);
+- crypto4xx_memcpy_le(get_dynamic_sa_key_field(sa),
+- key, keylen);
++ crypto4xx_memcpy_to_le32(get_dynamic_sa_key_field(sa),
++ key, keylen);
+ sa->sa_contents.w = SA_AES_CONTENTS | (keylen << 2);
+ sa->sa_command_1.bf.key_len = keylen >> 3;
+ ctx->is_hash = 0;
+--- a/drivers/crypto/amcc/crypto4xx_core.c
++++ b/drivers/crypto/amcc/crypto4xx_core.c
+@@ -614,42 +614,6 @@ static u32 crypto4xx_pd_done(struct cryp
+ return crypto4xx_ahash_done(dev, pd_uinfo);
+ }
+
+-/**
+- * Note: Only use this function to copy items that is word aligned.
+- */
+-void crypto4xx_memcpy_le(unsigned int *dst,
+- const unsigned char *buf,
+- int len)
+-{
+- u8 *tmp;
+- for (; len >= 4; buf += 4, len -= 4)
+- *dst++ = cpu_to_le32(*(unsigned int *) buf);
+-
+- tmp = (u8 *)dst;
+- switch (len) {
+- case 3:
+- *tmp++ = 0;
+- *tmp++ = *(buf+2);
+- *tmp++ = *(buf+1);
+- *tmp++ = *buf;
+- break;
+- case 2:
+- *tmp++ = 0;
+- *tmp++ = 0;
+- *tmp++ = *(buf+1);
+- *tmp++ = *buf;
+- break;
+- case 1:
+- *tmp++ = 0;
+- *tmp++ = 0;
+- *tmp++ = 0;
+- *tmp++ = *buf;
+- break;
+- default:
+- break;
+- }
+-}
+-
+ static void crypto4xx_stop_all(struct crypto4xx_core_device *core_dev)
+ {
+ crypto4xx_destroy_pdr(core_dev->dev);
+@@ -809,8 +773,8 @@ u32 crypto4xx_build_pd(struct crypto_asy
+ &pd_uinfo->sr_pa, 4);
+
+ if (iv_len)
+- crypto4xx_memcpy_le(pd_uinfo->sr_va->save_iv,
+- iv, iv_len);
++ crypto4xx_memcpy_to_le32(pd_uinfo->sr_va->save_iv,
++ iv, iv_len);
+ } else {
+ if (ctx->direction == DIR_INBOUND) {
+ pd->sa = ctx->sa_in_dma_addr;
+--- a/drivers/crypto/amcc/crypto4xx_core.h
++++ b/drivers/crypto/amcc/crypto4xx_core.h
+@@ -166,9 +166,7 @@ int crypto4xx_alloc_sa(struct crypto4xx_
+ void crypto4xx_free_sa(struct crypto4xx_ctx *ctx);
+ void crypto4xx_free_ctx(struct crypto4xx_ctx *ctx);
+ u32 crypto4xx_alloc_state_record(struct crypto4xx_ctx *ctx);
+-void crypto4xx_memcpy_le(unsigned int *dst,
+- const unsigned char *buf, int len);
+-u32 crypto4xx_build_pd(struct crypto_async_request *req,
++int crypto4xx_build_pd(struct crypto_async_request *req,
+ struct crypto4xx_ctx *ctx,
+ struct scatterlist *src,
+ struct scatterlist *dst,
+@@ -193,4 +191,47 @@ int crypto4xx_hash_digest(struct ahash_r
+ int crypto4xx_hash_final(struct ahash_request *req);
+ int crypto4xx_hash_update(struct ahash_request *req);
+ int crypto4xx_hash_init(struct ahash_request *req);
++
++/**
++ * Note: Only use this function to copy items that is word aligned.
++ */
++static inline void crypto4xx_memcpy_swab32(u32 *dst, const void *buf,
++ size_t len)
++{
++ for (; len >= 4; buf += 4, len -= 4)
++ *dst++ = __swab32p((u32 *) buf);
++
++ if (len) {
++ const u8 *tmp = (u8 *)buf;
++
++ switch (len) {
++ case 3:
++ *dst = (tmp[2] << 16) |
++ (tmp[1] << 8) |
++ tmp[0];
++ break;
++ case 2:
++ *dst = (tmp[1] << 8) |
++ tmp[0];
++ break;
++ case 1:
++ *dst = tmp[0];
++ break;
++ default:
++ break;
++ }
++ }
++}
++
++static inline void crypto4xx_memcpy_from_le32(u32 *dst, const void *buf,
++ size_t len)
++{
++ crypto4xx_memcpy_swab32(dst, buf, len);
++}
++
++static inline void crypto4xx_memcpy_to_le32(__le32 *dst, const void *buf,
++ size_t len)
++{
++ crypto4xx_memcpy_swab32((u32 *)dst, buf, len);
++}
+ #endif
+--- a/drivers/crypto/amcc/crypto4xx_sa.h
++++ b/drivers/crypto/amcc/crypto4xx_sa.h
+@@ -181,9 +181,12 @@ struct dynamic_sa_ctl {
+ * State Record for Security Association (SA)
+ */
+ struct sa_state_record {
+- u32 save_iv[4];
+- u32 save_hash_byte_cnt[2];
+- u32 save_digest[16];
++ __le32 save_iv[4];
++ __le32 save_hash_byte_cnt[2];
++ union {
++ u32 save_digest[16]; /* for MD5/SHA */
++ __le32 save_digest_le32[16]; /* GHASH / CBC */
++ };
+ } __attribute__((packed));
+
+ /**
+@@ -192,8 +195,8 @@ struct sa_state_record {
+ */
+ struct dynamic_sa_aes128 {
+ struct dynamic_sa_ctl ctrl;
+- u32 key[4];
+- u32 iv[4]; /* for CBC, OFC, and CFB mode */
++ __le32 key[4];
++ __le32 iv[4]; /* for CBC, OFC, and CFB mode */
+ u32 state_ptr;
+ u32 reserved;
+ } __attribute__((packed));
+@@ -206,8 +209,8 @@ struct dynamic_sa_aes128 {
+ */
+ struct dynamic_sa_aes192 {
+ struct dynamic_sa_ctl ctrl;
+- u32 key[6];
+- u32 iv[4]; /* for CBC, OFC, and CFB mode */
++ __le32 key[6];
++ __le32 iv[4]; /* for CBC, OFC, and CFB mode */
+ u32 state_ptr;
+ u32 reserved;
+ } __attribute__((packed));
+@@ -220,8 +223,8 @@ struct dynamic_sa_aes192 {
+ */
+ struct dynamic_sa_aes256 {
+ struct dynamic_sa_ctl ctrl;
+- u32 key[8];
+- u32 iv[4]; /* for CBC, OFC, and CFB mode */
++ __le32 key[8];
++ __le32 iv[4]; /* for CBC, OFC, and CFB mode */
+ u32 state_ptr;
+ u32 reserved;
+ } __attribute__((packed));
+@@ -235,8 +238,8 @@ struct dynamic_sa_aes256 {
+ */
+ struct dynamic_sa_hash160 {
+ struct dynamic_sa_ctl ctrl;
+- u32 inner_digest[5];
+- u32 outer_digest[5];
++ __le32 inner_digest[5];
++ __le32 outer_digest[5];
+ u32 state_ptr;
+ u32 reserved;
+ } __attribute__((packed));
+@@ -266,9 +269,9 @@ get_dynamic_sa_offset_state_ptr_field(st
+ return sizeof(struct dynamic_sa_ctl) + offset * 4;
+ }
+
+-static inline u32 *get_dynamic_sa_key_field(struct dynamic_sa_ctl *cts)
++static inline __le32 *get_dynamic_sa_key_field(struct dynamic_sa_ctl *cts)
+ {
+- return (u32 *) ((unsigned long)cts + sizeof(struct dynamic_sa_ctl));
++ return (__le32 *) ((unsigned long)cts + sizeof(struct dynamic_sa_ctl));
+ }
+
+ #endif
diff --git a/target/linux/apm821xx/patches-4.14/020-0019-crypto-crypto4xx-overhaul-crypto4xx_build_pd.patch b/target/linux/apm821xx/patches-4.14/020-0019-crypto-crypto4xx-overhaul-crypto4xx_build_pd.patch
new file mode 100644
index 0000000..7b739c6
--- /dev/null
+++ b/target/linux/apm821xx/patches-4.14/020-0019-crypto-crypto4xx-overhaul-crypto4xx_build_pd.patch
@@ -0,0 +1,535 @@
+From cd4dcd6da7a2610e0562a6e130bb68cc544a8fb1 Mon Sep 17 00:00:00 2001
+From: Christian Lamparter <chunkeey@gmail.com>
+Date: Wed, 4 Oct 2017 01:00:11 +0200
+Subject: [PATCH 19/25] crypto: crypto4xx - overhaul crypto4xx_build_pd()
+
+This patch overhauls and fixes code related to crypto4xx_build_pd()
+
+ * crypto4xx_build_pd() did not handle chained source scatterlist.
+ This is fixed by replacing the buggy indexed-access of &src[idx]
+ with sg_next() in the gather array setup loop.
+
+ * The redundant is_hash, direction, save_iv and pd_ctl members
+ in the crypto4xx_ctx struct have been removed.
+ - is_hash can be derived from the crypto_async_request parameter.
+ - direction is already part of the security association's
+ bf.dir bitfield.
+ - save_iv is unused.
+ - pd_ctl always had the host_ready bit enabled anyway.
+ (the hash_final case is rather pointless, since the ahash
+ code has been deactivated).
+
+ * make crypto4xx_build_pd()'s caller responsible for converting
+ the IV to the LE32 format.
+
+ * change crypto4xx_ahash_update() and crypto4xx_ahash_digest() to
+ initialize a temporary destination scatterlist. This allows the
+ removal of an ugly cast of req->result (which is a pointer to an
+ u8-array) to a scatterlist pointer.
+
+ * change crypto4xx_build_pd() return type to int. After all
+ it returns -EINPROGRESS/-EBUSY.
+
+ * fix crypto4xx_build_pd() thread-unsafe sa handling.
+
+Signed-off-by: Christian Lamparter <chunkeey@gmail.com>
+Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
+---
+ drivers/crypto/amcc/crypto4xx_alg.c | 87 +++++++++++-------------
+ drivers/crypto/amcc/crypto4xx_core.c | 128 ++++++++++++++++-------------------
+ drivers/crypto/amcc/crypto4xx_core.h | 12 ++--
+ 3 files changed, 103 insertions(+), 124 deletions(-)
+
+--- a/drivers/crypto/amcc/crypto4xx_alg.c
++++ b/drivers/crypto/amcc/crypto4xx_alg.c
+@@ -75,27 +75,29 @@ static void set_dynamic_sa_command_1(str
+ int crypto4xx_encrypt(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];
+
+- ctx->direction = DIR_OUTBOUND;
+- ctx->is_hash = 0;
+- ctx->pd_ctl = 0x1;
++ if (ivlen)
++ crypto4xx_memcpy_to_le32(iv, req->info, ivlen);
+
+ return crypto4xx_build_pd(&req->base, ctx, req->src, req->dst,
+- req->nbytes, req->info,
+- crypto_ablkcipher_ivsize(crypto_ablkcipher_reqtfm(req)));
++ req->nbytes, iv, ivlen, ctx->sa_out, ctx->sa_len);
+ }
+
+ int crypto4xx_decrypt(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];
+
+- ctx->direction = DIR_INBOUND;
+- ctx->is_hash = 0;
+- ctx->pd_ctl = 1;
++ if (ivlen)
++ crypto4xx_memcpy_to_le32(iv, req->info, ivlen);
+
+ return crypto4xx_build_pd(&req->base, ctx, req->src, req->dst,
+- req->nbytes, req->info,
+- crypto_ablkcipher_ivsize(crypto_ablkcipher_reqtfm(req)));
++ req->nbytes, iv, ivlen, ctx->sa_in, ctx->sa_len);
+ }
+
+ /**
+@@ -153,11 +155,6 @@ static int crypto4xx_setkey_aes(struct c
+ key, keylen);
+ sa->sa_contents.w = SA_AES_CONTENTS | (keylen << 2);
+ sa->sa_command_1.bf.key_len = keylen >> 3;
+- ctx->is_hash = 0;
+- ctx->direction = DIR_INBOUND;
+- memcpy(sa + get_dynamic_sa_offset_state_ptr_field(sa),
+- (void *)&ctx->state_record_dma_addr, 4);
+- ctx->offset_to_sr_ptr = get_dynamic_sa_offset_state_ptr_field(sa);
+
+ memcpy(ctx->sa_out, ctx->sa_in, ctx->sa_len * 4);
+ sa = ctx->sa_out;
+@@ -206,7 +203,7 @@ int crypto4xx_setkey_rfc3686(struct cryp
+ if (rc)
+ return rc;
+
+- memcpy(ctx->state_record,
++ crypto4xx_memcpy_to_le32(ctx->state_record->save_iv,
+ key + keylen - CTR_RFC3686_NONCE_SIZE, CTR_RFC3686_NONCE_SIZE);
+
+ return 0;
+@@ -215,27 +212,29 @@ int crypto4xx_setkey_rfc3686(struct cryp
+ int crypto4xx_rfc3686_encrypt(struct ablkcipher_request *req)
+ {
+ struct crypto4xx_ctx *ctx = crypto_tfm_ctx(req->base.tfm);
+- __be32 iv[AES_IV_SIZE / 4] = { *(u32 *)ctx->state_record,
+- *(u32 *) req->info, *(u32 *) (req->info + 4), cpu_to_be32(1) };
+-
+- ctx->direction = DIR_OUTBOUND;
+- ctx->pd_ctl = 1;
++ __le32 iv[AES_IV_SIZE / 4] = {
++ ctx->state_record->save_iv[0],
++ cpu_to_le32p((u32 *) req->info),
++ cpu_to_le32p((u32 *) (req->info + 4)),
++ cpu_to_le32(1) };
+
+ return crypto4xx_build_pd(&req->base, ctx, req->src, req->dst,
+- req->nbytes, iv, AES_IV_SIZE);
++ req->nbytes, iv, AES_IV_SIZE,
++ ctx->sa_out, ctx->sa_len);
+ }
+
+ int crypto4xx_rfc3686_decrypt(struct ablkcipher_request *req)
+ {
+ struct crypto4xx_ctx *ctx = crypto_tfm_ctx(req->base.tfm);
+- __be32 iv[AES_IV_SIZE / 4] = { *(u32 *)ctx->state_record,
+- *(u32 *) req->info, *(u32 *) (req->info + 4), cpu_to_be32(1) };
+-
+- ctx->direction = DIR_INBOUND;
+- ctx->pd_ctl = 1;
++ __le32 iv[AES_IV_SIZE / 4] = {
++ ctx->state_record->save_iv[0],
++ cpu_to_le32p((u32 *) req->info),
++ cpu_to_le32p((u32 *) (req->info + 4)),
++ cpu_to_le32(1) };
+
+ return crypto4xx_build_pd(&req->base, ctx, req->src, req->dst,
+- req->nbytes, iv, AES_IV_SIZE);
++ req->nbytes, iv, AES_IV_SIZE,
++ ctx->sa_out, ctx->sa_len);
+ }
+
+ /**
+@@ -253,7 +252,6 @@ static int crypto4xx_hash_alg_init(struc
+ int rc;
+
+ ctx->dev = my_alg->dev;
+- ctx->is_hash = 1;
+
+ /* Create SA */
+ if (ctx->sa_in_dma_addr || ctx->sa_out_dma_addr)
+@@ -284,13 +282,9 @@ static int crypto4xx_hash_alg_init(struc
+ SA_SEQ_MASK_OFF, SA_MC_ENABLE,
+ SA_NOT_COPY_PAD, SA_NOT_COPY_PAYLOAD,
+ SA_NOT_COPY_HDR);
+- ctx->direction = DIR_INBOUND;
+ /* Need to zero hash digest in SA */
+ memset(sa->inner_digest, 0, sizeof(sa->inner_digest));
+ memset(sa->outer_digest, 0, sizeof(sa->outer_digest));
+- sa->state_ptr = ctx->state_record_dma_addr;
+- ctx->offset_to_sr_ptr =
+- get_dynamic_sa_offset_state_ptr_field(&sa->ctrl);
+
+ return 0;
+ }
+@@ -306,23 +300,22 @@ int crypto4xx_hash_init(struct ahash_req
+ __crypto_ahash_cast(req->base.tfm));
+ sa->sa_command_0.bf.digest_len = ds >> 2;
+ sa->sa_command_0.bf.load_hash_state = SA_LOAD_HASH_FROM_SA;
+- ctx->is_hash = 1;
+- ctx->direction = DIR_INBOUND;
+
+ return 0;
+ }
+
+ int crypto4xx_hash_update(struct ahash_request *req)
+ {
++ struct crypto_ahash *ahash = crypto_ahash_reqtfm(req);
+ struct crypto4xx_ctx *ctx = crypto_tfm_ctx(req->base.tfm);
++ struct scatterlist dst;
++ unsigned int ds = crypto_ahash_digestsize(ahash);
++
++ sg_init_one(&dst, req->result, ds);
+
+- ctx->is_hash = 1;
+- ctx->pd_ctl = 0x11;
+- ctx->direction = DIR_INBOUND;
+-
+- return crypto4xx_build_pd(&req->base, ctx, req->src,
+- (struct scatterlist *) req->result,
+- req->nbytes, NULL, 0);
++ return crypto4xx_build_pd(&req->base, ctx, req->src, &dst,
++ req->nbytes, NULL, 0, ctx->sa_in,
++ ctx->sa_len);
+ }
+
+ int crypto4xx_hash_final(struct ahash_request *req)
+@@ -332,14 +325,16 @@ int crypto4xx_hash_final(struct ahash_re
+
+ int crypto4xx_hash_digest(struct ahash_request *req)
+ {
++ struct crypto_ahash *ahash = crypto_ahash_reqtfm(req);
+ struct crypto4xx_ctx *ctx = crypto_tfm_ctx(req->base.tfm);
++ struct scatterlist dst;
++ unsigned int ds = crypto_ahash_digestsize(ahash);
+
+- ctx->pd_ctl = 0x11;
+- ctx->direction = DIR_INBOUND;
++ sg_init_one(&dst, req->result, ds);
+
+- return crypto4xx_build_pd(&req->base, ctx, req->src,
+- (struct scatterlist *) req->result,
+- req->nbytes, NULL, 0);
++ return crypto4xx_build_pd(&req->base, ctx, req->src, &dst,
++ req->nbytes, NULL, 0, ctx->sa_in,
++ ctx->sa_len);
+ }
+
+ /**
+--- a/drivers/crypto/amcc/crypto4xx_core.c
++++ b/drivers/crypto/amcc/crypto4xx_core.c
+@@ -194,7 +194,6 @@ void crypto4xx_free_state_record(struct
+ static u32 crypto4xx_build_pdr(struct crypto4xx_device *dev)
+ {
+ int i;
+- struct pd_uinfo *pd_uinfo;
+ dev->pdr = dma_alloc_coherent(dev->core_dev->device,
+ sizeof(struct ce_pd) * PPC4XX_NUM_PD,
+ &dev->pdr_pa, GFP_ATOMIC);
+@@ -224,11 +223,14 @@ static u32 crypto4xx_build_pdr(struct cr
+ if (!dev->shadow_sr_pool)
+ return -ENOMEM;
+ for (i = 0; i < PPC4XX_NUM_PD; i++) {
+- pd_uinfo = &dev->pdr_uinfo[i];
++ struct ce_pd *pd = &dev->pdr[i];
++ struct pd_uinfo *pd_uinfo = &dev->pdr_uinfo[i];
++
++ pd->sa = dev->shadow_sa_pool_pa +
++ sizeof(union shadow_sa_buf) * i;
+
+ /* alloc 256 bytes which is enough for any kind of dynamic sa */
+ pd_uinfo->sa_va = &dev->shadow_sa_pool[i].sa;
+- pd_uinfo->sa_pa = dev->shadow_sa_pool_pa + 256 * i;
+
+ /* alloc state record */
+ pd_uinfo->sr_va = &dev->shadow_sr_pool[i];
+@@ -291,14 +293,6 @@ static u32 crypto4xx_put_pd_to_pdr(struc
+ return 0;
+ }
+
+-static struct ce_pd *crypto4xx_get_pdp(struct crypto4xx_device *dev,
+- dma_addr_t *pd_dma, u32 idx)
+-{
+- *pd_dma = dev->pdr_pa + sizeof(struct ce_pd) * idx;
+-
+- return &dev->pdr[idx];
+-}
+-
+ /**
+ * alloc memory for the gather ring
+ * no need to alloc buf for the ring
+@@ -520,18 +514,16 @@ static void crypto4xx_copy_pkt_to_dst(st
+ }
+ }
+
+-static u32 crypto4xx_copy_digest_to_dst(struct pd_uinfo *pd_uinfo,
++static void crypto4xx_copy_digest_to_dst(void *dst,
++ struct pd_uinfo *pd_uinfo,
+ struct crypto4xx_ctx *ctx)
+ {
+ struct dynamic_sa_ctl *sa = (struct dynamic_sa_ctl *) ctx->sa_in;
+
+ if (sa->sa_command_0.bf.hash_alg == SA_HASH_ALG_SHA1) {
+- memcpy((void *) pd_uinfo->dest_va,
+- pd_uinfo->sr_va->save_digest,
++ memcpy(dst, pd_uinfo->sr_va->save_digest,
+ SA_HASH_ALG_SHA1_DIGEST_SIZE);
+ }
+-
+- return 0;
+ }
+
+ static void crypto4xx_ret_sg_desc(struct crypto4xx_device *dev,
+@@ -591,7 +583,7 @@ static u32 crypto4xx_ahash_done(struct c
+ ahash_req = ahash_request_cast(pd_uinfo->async_req);
+ ctx = crypto_tfm_ctx(ahash_req->base.tfm);
+
+- crypto4xx_copy_digest_to_dst(pd_uinfo,
++ crypto4xx_copy_digest_to_dst(ahash_req->result, pd_uinfo,
+ crypto_tfm_ctx(ahash_req->base.tfm));
+ crypto4xx_ret_sg_desc(dev, pd_uinfo);
+
+@@ -651,17 +643,17 @@ static u32 get_next_sd(u32 current)
+ return 0;
+ }
+
+-u32 crypto4xx_build_pd(struct crypto_async_request *req,
++int crypto4xx_build_pd(struct crypto_async_request *req,
+ struct crypto4xx_ctx *ctx,
+ struct scatterlist *src,
+ struct scatterlist *dst,
+- unsigned int datalen,
+- void *iv, u32 iv_len)
++ const unsigned int datalen,
++ const __le32 *iv, const u32 iv_len,
++ const struct dynamic_sa_ctl *req_sa,
++ const unsigned int sa_len)
+ {
+ struct crypto4xx_device *dev = ctx->dev;
+- dma_addr_t addr, pd_dma, sd_dma, gd_dma;
+ struct dynamic_sa_ctl *sa;
+- struct scatterlist *sg;
+ struct ce_gd *gd;
+ struct ce_pd *pd;
+ u32 num_gd, num_sd;
+@@ -669,8 +661,9 @@ u32 crypto4xx_build_pd(struct crypto_asy
+ u32 fst_sd = 0xffffffff;
+ u32 pd_entry;
+ unsigned long flags;
+- struct pd_uinfo *pd_uinfo = NULL;
+- unsigned int nbytes = datalen, idx;
++ struct pd_uinfo *pd_uinfo;
++ unsigned int nbytes = datalen;
++ size_t offset_to_sr_ptr;
+ u32 gd_idx = 0;
+ bool is_busy;
+
+@@ -684,7 +677,7 @@ u32 crypto4xx_build_pd(struct crypto_asy
+ num_gd = 0;
+
+ /* figure how many sd is needed */
+- if (sg_is_last(dst) || ctx->is_hash) {
++ if (sg_is_last(dst)) {
+ num_sd = 0;
+ } else {
+ if (datalen > PPC4XX_SD_BUFFER_SIZE) {
+@@ -755,37 +748,27 @@ u32 crypto4xx_build_pd(struct crypto_asy
+ }
+ spin_unlock_irqrestore(&dev->core_dev->lock, flags);
+
++ pd = &dev->pdr[pd_entry];
++ pd->sa_len = sa_len;
++
+ pd_uinfo = &dev->pdr_uinfo[pd_entry];
+- pd = crypto4xx_get_pdp(dev, &pd_dma, pd_entry);
+ pd_uinfo->async_req = req;
+ pd_uinfo->num_gd = num_gd;
+ pd_uinfo->num_sd = num_sd;
+
+- if (iv_len || ctx->is_hash) {
+- pd->sa = pd_uinfo->sa_pa;
+- sa = pd_uinfo->sa_va;
+- if (ctx->direction == DIR_INBOUND)
+- memcpy(sa, ctx->sa_in, ctx->sa_len * 4);
+- else
+- memcpy(sa, ctx->sa_out, ctx->sa_len * 4);
++ if (iv_len)
++ memcpy(pd_uinfo->sr_va->save_iv, iv, iv_len);
+
+- memcpy((void *) sa + ctx->offset_to_sr_ptr,
+- &pd_uinfo->sr_pa, 4);
++ sa = pd_uinfo->sa_va;
++ memcpy(sa, req_sa, sa_len * 4);
++
++ offset_to_sr_ptr = get_dynamic_sa_offset_state_ptr_field(sa);
++ *(u32 *)((unsigned long)sa + offset_to_sr_ptr) = pd_uinfo->sr_pa;
+
+- if (iv_len)
+- crypto4xx_memcpy_to_le32(pd_uinfo->sr_va->save_iv,
+- iv, iv_len);
+- } else {
+- if (ctx->direction == DIR_INBOUND) {
+- pd->sa = ctx->sa_in_dma_addr;
+- sa = ctx->sa_in;
+- } else {
+- pd->sa = ctx->sa_out_dma_addr;
+- sa = ctx->sa_out;
+- }
+- }
+- pd->sa_len = ctx->sa_len;
+ if (num_gd) {
++ dma_addr_t gd_dma;
++ struct scatterlist *sg;
++
+ /* get first gd we are going to use */
+ gd_idx = fst_gd;
+ pd_uinfo->first_gd = fst_gd;
+@@ -794,27 +777,30 @@ u32 crypto4xx_build_pd(struct crypto_asy
+ pd->src = gd_dma;
+ /* enable gather */
+ sa->sa_command_0.bf.gather = 1;
+- idx = 0;
+- src = &src[0];
+ /* walk the sg, and setup gather array */
++
++ sg = src;
+ while (nbytes) {
+- sg = &src[idx];
+- addr = dma_map_page(dev->core_dev->device, sg_page(sg),
+- sg->offset, sg->length, DMA_TO_DEVICE);
+- gd->ptr = addr;
+- gd->ctl_len.len = sg->length;
++ size_t len;
++
++ len = min(sg->length, nbytes);
++ gd->ptr = dma_map_page(dev->core_dev->device,
++ sg_page(sg), sg->offset, len, DMA_TO_DEVICE);
++ gd->ctl_len.len = len;
+ gd->ctl_len.done = 0;
+ gd->ctl_len.ready = 1;
+- if (sg->length >= nbytes)
++ if (len >= nbytes)
+ break;
++
+ nbytes -= sg->length;
+ gd_idx = get_next_gd(gd_idx);
+ gd = crypto4xx_get_gdp(dev, &gd_dma, gd_idx);
+- idx++;
++ sg = sg_next(sg);
+ }
+ } else {
+ pd->src = (u32)dma_map_page(dev->core_dev->device, sg_page(src),
+- src->offset, src->length, DMA_TO_DEVICE);
++ src->offset, min(nbytes, src->length),
++ DMA_TO_DEVICE);
+ /*
+ * Disable gather in sa command
+ */
+@@ -825,25 +811,24 @@ u32 crypto4xx_build_pd(struct crypto_asy
+ pd_uinfo->first_gd = 0xffffffff;
+ pd_uinfo->num_gd = 0;
+ }
+- if (ctx->is_hash || sg_is_last(dst)) {
++ if (sg_is_last(dst)) {
+ /*
+ * we know application give us dst a whole piece of memory
+ * no need to use scatter ring.
+- * In case of is_hash, the icv is always at end of src data.
+ */
+ pd_uinfo->using_sd = 0;
+ pd_uinfo->first_sd = 0xffffffff;
+ pd_uinfo->num_sd = 0;
+ pd_uinfo->dest_va = dst;
+ sa->sa_command_0.bf.scatter = 0;
+- if (ctx->is_hash)
+- pd->dest = virt_to_phys((void *)dst);
+- else
+- pd->dest = (u32)dma_map_page(dev->core_dev->device,
+- sg_page(dst), dst->offset,
+- dst->length, DMA_TO_DEVICE);
++ pd->dest = (u32)dma_map_page(dev->core_dev->device,
++ sg_page(dst), dst->offset,
++ min(datalen, dst->length),
++ DMA_TO_DEVICE);
+ } else {
++ dma_addr_t sd_dma;
+ struct ce_sd *sd = NULL;
++
+ u32 sd_idx = fst_sd;
+ nbytes = datalen;
+ sa->sa_command_0.bf.scatter = 1;
+@@ -857,7 +842,6 @@ u32 crypto4xx_build_pd(struct crypto_asy
+ sd->ctl.done = 0;
+ sd->ctl.rdy = 1;
+ /* sd->ptr should be setup by sd_init routine*/
+- idx = 0;
+ if (nbytes >= PPC4XX_SD_BUFFER_SIZE)
+ nbytes -= PPC4XX_SD_BUFFER_SIZE;
+ else
+@@ -868,19 +852,23 @@ u32 crypto4xx_build_pd(struct crypto_asy
+ /* setup scatter descriptor */
+ sd->ctl.done = 0;
+ sd->ctl.rdy = 1;
+- if (nbytes >= PPC4XX_SD_BUFFER_SIZE)
++ if (nbytes >= PPC4XX_SD_BUFFER_SIZE) {
+ nbytes -= PPC4XX_SD_BUFFER_SIZE;
+- else
++ } else {
+ /*
+ * SD entry can hold PPC4XX_SD_BUFFER_SIZE,
+ * which is more than nbytes, so done.
+ */
+ nbytes = 0;
++ }
+ }
+ }
+
+ sa->sa_command_1.bf.hash_crypto_offset = 0;
+- pd->pd_ctl.w = ctx->pd_ctl;
++ pd->pd_ctl.w = 0;
++ pd->pd_ctl.bf.hash_final =
++ (crypto_tfm_alg_type(req->tfm) == CRYPTO_ALG_TYPE_AHASH);
++ pd->pd_ctl.bf.host_ready = 1;
+ pd->pd_ctl_len.w = 0x00400000 | datalen;
+ pd_uinfo->state = PD_ENTRY_INUSE | (is_busy ? PD_ENTRY_BUSY : 0);
+
+--- a/drivers/crypto/amcc/crypto4xx_core.h
++++ b/drivers/crypto/amcc/crypto4xx_core.h
+@@ -71,7 +71,6 @@ struct pd_uinfo {
+ u32 num_sd; /* number of scatter discriptors
+ used by this packet */
+ struct dynamic_sa_ctl *sa_va; /* shadow sa */
+- u32 sa_pa;
+ struct sa_state_record *sr_va; /* state record for shadow sa */
+ u32 sr_pa;
+ struct scatterlist *dest_va;
+@@ -129,11 +128,6 @@ struct crypto4xx_ctx {
+ struct sa_state_record *state_record;
+ dma_addr_t state_record_dma_addr;
+ u32 sa_len;
+- u32 offset_to_sr_ptr; /* offset to state ptr, in dynamic sa */
+- u32 direction;
+- u32 save_iv;
+- u32 pd_ctl;
+- u32 is_hash;
+ };
+
+ struct crypto4xx_alg_common {
+@@ -170,8 +164,10 @@ int crypto4xx_build_pd(struct crypto_asy
+ struct crypto4xx_ctx *ctx,
+ struct scatterlist *src,
+ struct scatterlist *dst,
+- unsigned int datalen,
+- void *iv, u32 iv_len);
++ const unsigned int datalen,
++ const __le32 *iv, const u32 iv_len,
++ const struct dynamic_sa_ctl *sa,
++ const unsigned int sa_len);
+ int crypto4xx_setkey_aes_cbc(struct crypto_ablkcipher *cipher,
+ const u8 *key, unsigned int keylen);
+ int crypto4xx_setkey_aes_cfb(struct crypto_ablkcipher *cipher,
diff --git a/target/linux/apm821xx/patches-4.14/020-0020-crypto-crypto4xx-fix-various-warnings.patch b/target/linux/apm821xx/patches-4.14/020-0020-crypto-crypto4xx-fix-various-warnings.patch
new file mode 100644
index 0000000..8847d1f
--- /dev/null
+++ b/target/linux/apm821xx/patches-4.14/020-0020-crypto-crypto4xx-fix-various-warnings.patch
@@ -0,0 +1,62 @@
+From 64e1062b2371cb8d6126d4e970832365a1a84562 Mon Sep 17 00:00:00 2001
+From: Christian Lamparter <chunkeey@gmail.com>
+Date: Wed, 4 Oct 2017 01:00:12 +0200
+Subject: [PATCH 20/25] crypto: crypto4xx - fix various warnings
+
+crypto4xx_core.c:179:6: warning: symbol 'crypto4xx_free_state_record'
+ was not declared. Should it be static?
+crypto4xx_core.c:331:5: warning: symbol 'crypto4xx_get_n_gd'
+ was not declared. Should it be static?
+crypto4xx_core.c:652:6: warning: symbol 'crypto4xx_return_pd'
+ was not declared. Should it be static?
+
+crypto4xx_return_pd() is not used by anything. Therefore it is removed.
+
+Signed-off-by: Christian Lamparter <chunkeey@gmail.com>
+Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
+---
+ drivers/crypto/amcc/crypto4xx_core.c | 16 +++-------------
+ 1 file changed, 3 insertions(+), 13 deletions(-)
+
+--- a/drivers/crypto/amcc/crypto4xx_core.c
++++ b/drivers/crypto/amcc/crypto4xx_core.c
+@@ -176,7 +176,7 @@ u32 crypto4xx_alloc_state_record(struct
+ return 0;
+ }
+
+-void crypto4xx_free_state_record(struct crypto4xx_ctx *ctx)
++static void crypto4xx_free_state_record(struct crypto4xx_ctx *ctx)
+ {
+ if (ctx->state_record != NULL)
+ dma_free_coherent(ctx->dev->core_dev->device,
+@@ -322,10 +322,11 @@ static inline void crypto4xx_destroy_gdr
+ * when this function is called.
+ * preemption or interrupt must be disabled
+ */
+-u32 crypto4xx_get_n_gd(struct crypto4xx_device *dev, int n)
++static u32 crypto4xx_get_n_gd(struct crypto4xx_device *dev, int n)
+ {
+ u32 retval;
+ u32 tmp;
++
+ if (n >= PPC4XX_NUM_GD)
+ return ERING_WAS_FULL;
+
+@@ -616,17 +617,6 @@ static void crypto4xx_stop_all(struct cr
+ kfree(core_dev);
+ }
+
+-void crypto4xx_return_pd(struct crypto4xx_device *dev,
+- u32 pd_entry, struct ce_pd *pd,
+- struct pd_uinfo *pd_uinfo)
+-{
+- /* irq should be already disabled */
+- dev->pdr_head = pd_entry;
+- pd->pd_ctl.w = 0;
+- pd->pd_ctl_len.w = 0;
+- pd_uinfo->state = PD_ENTRY_FREE;
+-}
+-
+ static u32 get_next_gd(u32 current)
+ {
+ if (current != PPC4XX_LAST_GD)
diff --git a/target/linux/apm821xx/patches-4.14/020-0021-crypto-crypto4xx-fix-stalls-under-heavy-load.patch b/target/linux/apm821xx/patches-4.14/020-0021-crypto-crypto4xx-fix-stalls-under-heavy-load.patch
new file mode 100644
index 0000000..aa621c5
--- /dev/null
+++ b/target/linux/apm821xx/patches-4.14/020-0021-crypto-crypto4xx-fix-stalls-under-heavy-load.patch
@@ -0,0 +1,112 @@
+From 4b5b79998af61db8b0506fba6c0f33b57ea457bd Mon Sep 17 00:00:00 2001
+From: Christian Lamparter <chunkeey@gmail.com>
+Date: Wed, 4 Oct 2017 01:00:13 +0200
+Subject: [PATCH 21/25] crypto: crypto4xx - fix stalls under heavy load
+
+If the crypto4xx device is continuously loaded by dm-crypt
+and ipsec work, it will start to work intermittent after a
+few (between 20-30) seconds, hurting throughput and latency.
+
+This patch contains various stability improvements in order
+to fix this issue. So far, the hardware has survived more
+than a day without suffering any stalls under the continuous
+load.
+
+Signed-off-by: Christian Lamparter <chunkeey@gmail.com>
+Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
+---
+ drivers/crypto/amcc/crypto4xx_core.c | 33 ++++++++++++++++++---------------
+ drivers/crypto/amcc/crypto4xx_reg_def.h | 3 +++
+ 2 files changed, 21 insertions(+), 15 deletions(-)
+
+--- a/drivers/crypto/amcc/crypto4xx_core.c
++++ b/drivers/crypto/amcc/crypto4xx_core.c
+@@ -280,17 +280,20 @@ static u32 crypto4xx_get_pd_from_pdr_nol
+ static u32 crypto4xx_put_pd_to_pdr(struct crypto4xx_device *dev, u32 idx)
+ {
+ struct pd_uinfo *pd_uinfo = &dev->pdr_uinfo[idx];
++ u32 tail;
+ unsigned long flags;
+
+ spin_lock_irqsave(&dev->core_dev->lock, flags);
++ pd_uinfo->state = PD_ENTRY_FREE;
++
+ if (dev->pdr_tail != PPC4XX_LAST_PD)
+ dev->pdr_tail++;
+ else
+ dev->pdr_tail = 0;
+- pd_uinfo->state = PD_ENTRY_FREE;
++ tail = dev->pdr_tail;
+ spin_unlock_irqrestore(&dev->core_dev->lock, flags);
+
+- return 0;
++ return tail;
+ }
+
+ /**
+@@ -854,16 +857,16 @@ int crypto4xx_build_pd(struct crypto_asy
+ }
+ }
+
+- sa->sa_command_1.bf.hash_crypto_offset = 0;
+- pd->pd_ctl.w = 0;
+- pd->pd_ctl.bf.hash_final =
+- (crypto_tfm_alg_type(req->tfm) == CRYPTO_ALG_TYPE_AHASH);
+- pd->pd_ctl.bf.host_ready = 1;
++ pd->pd_ctl.w = PD_CTL_HOST_READY |
++ ((crypto_tfm_alg_type(req->tfm) == CRYPTO_ALG_TYPE_AHASH) |
++ (crypto_tfm_alg_type(req->tfm) == CRYPTO_ALG_TYPE_AEAD) ?
++ PD_CTL_HASH_FINAL : 0);
+ pd->pd_ctl_len.w = 0x00400000 | datalen;
+ pd_uinfo->state = PD_ENTRY_INUSE | (is_busy ? PD_ENTRY_BUSY : 0);
+
+ wmb();
+ /* write any value to push engine to read a pd */
++ writel(0, dev->ce_base + CRYPTO4XX_INT_DESCR_RD);
+ writel(1, dev->ce_base + CRYPTO4XX_INT_DESCR_RD);
+ return is_busy ? -EBUSY : -EINPROGRESS;
+ }
+@@ -964,23 +967,23 @@ static void crypto4xx_bh_tasklet_cb(unsi
+ struct crypto4xx_core_device *core_dev = dev_get_drvdata(dev);
+ struct pd_uinfo *pd_uinfo;
+ struct ce_pd *pd;
+- u32 tail;
++ u32 tail = core_dev->dev->pdr_tail;
++ u32 head = core_dev->dev->pdr_head;
+
+- while (core_dev->dev->pdr_head != core_dev->dev->pdr_tail) {
+- tail = core_dev->dev->pdr_tail;
++ do {
+ pd_uinfo = &core_dev->dev->pdr_uinfo[tail];
+ pd = &core_dev->dev->pdr[tail];
+ if ((pd_uinfo->state & PD_ENTRY_INUSE) &&
+- pd->pd_ctl.bf.pe_done &&
+- !pd->pd_ctl.bf.host_ready) {
+- pd->pd_ctl.bf.pe_done = 0;
++ ((READ_ONCE(pd->pd_ctl.w) &
++ (PD_CTL_PE_DONE | PD_CTL_HOST_READY)) ==
++ PD_CTL_PE_DONE)) {
+ crypto4xx_pd_done(core_dev->dev, tail);
+- crypto4xx_put_pd_to_pdr(core_dev->dev, tail);
++ tail = crypto4xx_put_pd_to_pdr(core_dev->dev, tail);
+ } else {
+ /* if tail not done, break */
+ break;
+ }
+- }
++ } while (head != tail);
+ }
+
+ /**
+--- a/drivers/crypto/amcc/crypto4xx_reg_def.h
++++ b/drivers/crypto/amcc/crypto4xx_reg_def.h
+@@ -261,6 +261,9 @@ union ce_pd_ctl {
+ } bf;
+ u32 w;
+ } __attribute__((packed));
++#define PD_CTL_HASH_FINAL BIT(4)
++#define PD_CTL_PE_DONE BIT(1)
++#define PD_CTL_HOST_READY BIT(0)
+
+ union ce_pd_ctl_len {
+ struct {
diff --git a/target/linux/apm821xx/patches-4.14/020-0022-crypto-crypto4xx-simplify-sa-and-state-context-acqui.patch b/target/linux/apm821xx/patches-4.14/020-0022-crypto-crypto4xx-simplify-sa-and-state-context-acqui.patch
new file mode 100644
index 0000000..06ab798
--- /dev/null
+++ b/target/linux/apm821xx/patches-4.14/020-0022-crypto-crypto4xx-simplify-sa-and-state-context-acqui.patch
@@ -0,0 +1,209 @@
+From 2f77690dcb96e525bc6b57bce4a0eaecaa2878d1 Mon Sep 17 00:00:00 2001
+From: Christian Lamparter <chunkeey@gmail.com>
+Date: Wed, 4 Oct 2017 01:00:14 +0200
+Subject: [PATCH 22/25] crypto: crypto4xx - simplify sa and state context
+ acquisition
+
+Thanks to the big overhaul of crypto4xx_build_pd(), the request-local
+sa_in, sa_out and state_record allocation can be simplified.
+
+There's no need to setup any dma coherent memory anymore and
+much of the support code can be removed.
+
+Signed-off-by: Christian Lamparter <chunkeey@gmail.com>
+Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
+---
+ drivers/crypto/amcc/crypto4xx_alg.c | 27 +++++--------------
+ drivers/crypto/amcc/crypto4xx_core.c | 50 ++++++------------------------------
+ drivers/crypto/amcc/crypto4xx_core.h | 6 +----
+ 3 files changed, 15 insertions(+), 68 deletions(-)
+
+--- a/drivers/crypto/amcc/crypto4xx_alg.c
++++ b/drivers/crypto/amcc/crypto4xx_alg.c
+@@ -122,20 +122,13 @@ static int crypto4xx_setkey_aes(struct c
+ }
+
+ /* Create SA */
+- if (ctx->sa_in_dma_addr || ctx->sa_out_dma_addr)
++ if (ctx->sa_in || ctx->sa_out)
+ crypto4xx_free_sa(ctx);
+
+ rc = crypto4xx_alloc_sa(ctx, SA_AES128_LEN + (keylen-16) / 4);
+ if (rc)
+ return rc;
+
+- if (ctx->state_record_dma_addr == 0) {
+- rc = crypto4xx_alloc_state_record(ctx);
+- if (rc) {
+- crypto4xx_free_sa(ctx);
+- return rc;
+- }
+- }
+ /* Setup SA */
+ sa = ctx->sa_in;
+
+@@ -203,8 +196,8 @@ int crypto4xx_setkey_rfc3686(struct cryp
+ if (rc)
+ return rc;
+
+- crypto4xx_memcpy_to_le32(ctx->state_record->save_iv,
+- key + keylen - CTR_RFC3686_NONCE_SIZE, CTR_RFC3686_NONCE_SIZE);
++ ctx->iv_nonce = cpu_to_le32p((u32 *)&key[keylen -
++ CTR_RFC3686_NONCE_SIZE]);
+
+ return 0;
+ }
+@@ -213,7 +206,7 @@ int crypto4xx_rfc3686_encrypt(struct abl
+ {
+ struct crypto4xx_ctx *ctx = crypto_tfm_ctx(req->base.tfm);
+ __le32 iv[AES_IV_SIZE / 4] = {
+- ctx->state_record->save_iv[0],
++ ctx->iv_nonce,
+ cpu_to_le32p((u32 *) req->info),
+ cpu_to_le32p((u32 *) (req->info + 4)),
+ cpu_to_le32(1) };
+@@ -227,7 +220,7 @@ int crypto4xx_rfc3686_decrypt(struct abl
+ {
+ struct crypto4xx_ctx *ctx = crypto_tfm_ctx(req->base.tfm);
+ __le32 iv[AES_IV_SIZE / 4] = {
+- ctx->state_record->save_iv[0],
++ ctx->iv_nonce,
+ cpu_to_le32p((u32 *) req->info),
+ cpu_to_le32p((u32 *) (req->info + 4)),
+ cpu_to_le32(1) };
+@@ -254,21 +247,13 @@ static int crypto4xx_hash_alg_init(struc
+ ctx->dev = my_alg->dev;
+
+ /* Create SA */
+- if (ctx->sa_in_dma_addr || ctx->sa_out_dma_addr)
++ if (ctx->sa_in || ctx->sa_out)
+ crypto4xx_free_sa(ctx);
+
+ rc = crypto4xx_alloc_sa(ctx, sa_len);
+ if (rc)
+ return rc;
+
+- if (ctx->state_record_dma_addr == 0) {
+- crypto4xx_alloc_state_record(ctx);
+- if (!ctx->state_record_dma_addr) {
+- crypto4xx_free_sa(ctx);
+- return -ENOMEM;
+- }
+- }
+-
+ crypto_ahash_set_reqsize(__crypto_ahash_cast(tfm),
+ sizeof(struct crypto4xx_ctx));
+ sa = (struct dynamic_sa_hash160 *)ctx->sa_in;
+--- a/drivers/crypto/amcc/crypto4xx_core.c
++++ b/drivers/crypto/amcc/crypto4xx_core.c
+@@ -130,21 +130,17 @@ static void crypto4xx_hw_init(struct cry
+
+ int crypto4xx_alloc_sa(struct crypto4xx_ctx *ctx, u32 size)
+ {
+- ctx->sa_in = dma_alloc_coherent(ctx->dev->core_dev->device, size * 4,
+- &ctx->sa_in_dma_addr, GFP_ATOMIC);
++ ctx->sa_in = kzalloc(size * 4, GFP_ATOMIC);
+ if (ctx->sa_in == NULL)
+ return -ENOMEM;
+
+- ctx->sa_out = dma_alloc_coherent(ctx->dev->core_dev->device, size * 4,
+- &ctx->sa_out_dma_addr, GFP_ATOMIC);
++ ctx->sa_out = kzalloc(size * 4, GFP_ATOMIC);
+ if (ctx->sa_out == NULL) {
+- dma_free_coherent(ctx->dev->core_dev->device, size * 4,
+- ctx->sa_in, ctx->sa_in_dma_addr);
++ kfree(ctx->sa_in);
++ ctx->sa_in = NULL;
+ return -ENOMEM;
+ }
+
+- memset(ctx->sa_in, 0, size * 4);
+- memset(ctx->sa_out, 0, size * 4);
+ ctx->sa_len = size;
+
+ return 0;
+@@ -152,40 +148,13 @@ int crypto4xx_alloc_sa(struct crypto4xx_
+
+ void crypto4xx_free_sa(struct crypto4xx_ctx *ctx)
+ {
+- if (ctx->sa_in != NULL)
+- dma_free_coherent(ctx->dev->core_dev->device, ctx->sa_len * 4,
+- ctx->sa_in, ctx->sa_in_dma_addr);
+- if (ctx->sa_out != NULL)
+- dma_free_coherent(ctx->dev->core_dev->device, ctx->sa_len * 4,
+- ctx->sa_out, ctx->sa_out_dma_addr);
+-
+- ctx->sa_in_dma_addr = 0;
+- ctx->sa_out_dma_addr = 0;
++ kfree(ctx->sa_in);
++ ctx->sa_in = NULL;
++ kfree(ctx->sa_out);
++ ctx->sa_out = NULL;
+ ctx->sa_len = 0;
+ }
+
+-u32 crypto4xx_alloc_state_record(struct crypto4xx_ctx *ctx)
+-{
+- ctx->state_record = dma_alloc_coherent(ctx->dev->core_dev->device,
+- sizeof(struct sa_state_record),
+- &ctx->state_record_dma_addr, GFP_ATOMIC);
+- if (!ctx->state_record_dma_addr)
+- return -ENOMEM;
+- memset(ctx->state_record, 0, sizeof(struct sa_state_record));
+-
+- return 0;
+-}
+-
+-static void crypto4xx_free_state_record(struct crypto4xx_ctx *ctx)
+-{
+- if (ctx->state_record != NULL)
+- dma_free_coherent(ctx->dev->core_dev->device,
+- sizeof(struct sa_state_record),
+- ctx->state_record,
+- ctx->state_record_dma_addr);
+- ctx->state_record_dma_addr = 0;
+-}
+-
+ /**
+ * alloc memory for the gather ring
+ * no need to alloc buf for the ring
+@@ -883,8 +852,6 @@ static int crypto4xx_alg_init(struct cry
+ ctx->dev = amcc_alg->dev;
+ ctx->sa_in = NULL;
+ ctx->sa_out = NULL;
+- ctx->sa_in_dma_addr = 0;
+- ctx->sa_out_dma_addr = 0;
+ ctx->sa_len = 0;
+
+ switch (alg->cra_flags & CRYPTO_ALG_TYPE_MASK) {
+@@ -905,7 +872,6 @@ static void crypto4xx_alg_exit(struct cr
+ struct crypto4xx_ctx *ctx = crypto_tfm_ctx(tfm);
+
+ crypto4xx_free_sa(ctx);
+- crypto4xx_free_state_record(ctx);
+ }
+
+ int crypto4xx_register_alg(struct crypto4xx_device *sec_dev,
+--- a/drivers/crypto/amcc/crypto4xx_core.h
++++ b/drivers/crypto/amcc/crypto4xx_core.h
+@@ -122,11 +122,8 @@ struct crypto4xx_core_device {
+ struct crypto4xx_ctx {
+ struct crypto4xx_device *dev;
+ struct dynamic_sa_ctl *sa_in;
+- dma_addr_t sa_in_dma_addr;
+ struct dynamic_sa_ctl *sa_out;
+- dma_addr_t sa_out_dma_addr;
+- struct sa_state_record *state_record;
+- dma_addr_t state_record_dma_addr;
++ __le32 iv_nonce;
+ u32 sa_len;
+ };
+
+@@ -159,7 +156,6 @@ static inline struct crypto4xx_alg *cryp
+ int crypto4xx_alloc_sa(struct crypto4xx_ctx *ctx, u32 size);
+ void crypto4xx_free_sa(struct crypto4xx_ctx *ctx);
+ void crypto4xx_free_ctx(struct crypto4xx_ctx *ctx);
+-u32 crypto4xx_alloc_state_record(struct crypto4xx_ctx *ctx);
+ int crypto4xx_build_pd(struct crypto_async_request *req,
+ struct crypto4xx_ctx *ctx,
+ struct scatterlist *src,
diff --git a/target/linux/apm821xx/patches-4.14/020-0023-crypto-crypto4xx-prepare-for-AEAD-support.patch b/target/linux/apm821xx/patches-4.14/020-0023-crypto-crypto4xx-prepare-for-AEAD-support.patch
new file mode 100644
index 0000000..ff19c4f
--- /dev/null
+++ b/target/linux/apm821xx/patches-4.14/020-0023-crypto-crypto4xx-prepare-for-AEAD-support.patch
@@ -0,0 +1,617 @@
+From a0aae821ba3d35a49d4d0143dfb0c07eee22130e Mon Sep 17 00:00:00 2001
+From: Christian Lamparter <chunkeey@gmail.com>
+Date: Wed, 4 Oct 2017 01:00:15 +0200
+Subject: [PATCH 23/25] crypto: crypto4xx - prepare for AEAD support
+
+This patch enhances existing interfaces and
+functions to support AEAD ciphers in the next
+patches.
+
+Signed-off-by: Christian Lamparter <chunkeey@gmail.com>
+Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
+---
+ drivers/crypto/amcc/crypto4xx_alg.c | 19 +--
+ drivers/crypto/amcc/crypto4xx_core.c | 217 +++++++++++++++++++++++++++--------
+ drivers/crypto/amcc/crypto4xx_core.h | 22 ++--
+ drivers/crypto/amcc/crypto4xx_sa.h | 41 +++++++
+ 4 files changed, 226 insertions(+), 73 deletions(-)
+
+--- a/drivers/crypto/amcc/crypto4xx_alg.c
++++ b/drivers/crypto/amcc/crypto4xx_alg.c
+@@ -26,6 +26,7 @@
+ #include <crypto/internal/hash.h>
+ #include <linux/dma-mapping.h>
+ #include <crypto/algapi.h>
++#include <crypto/aead.h>
+ #include <crypto/aes.h>
+ #include <crypto/sha.h>
+ #include <crypto/ctr.h>
+@@ -83,7 +84,7 @@ int crypto4xx_encrypt(struct ablkcipher_
+ 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);
++ req->nbytes, iv, ivlen, ctx->sa_out, ctx->sa_len, 0);
+ }
+
+ int crypto4xx_decrypt(struct ablkcipher_request *req)
+@@ -97,7 +98,7 @@ int crypto4xx_decrypt(struct ablkcipher_
+ 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_in, ctx->sa_len);
++ req->nbytes, iv, ivlen, ctx->sa_in, ctx->sa_len, 0);
+ }
+
+ /**
+@@ -213,7 +214,7 @@ int crypto4xx_rfc3686_encrypt(struct abl
+
+ return crypto4xx_build_pd(&req->base, ctx, req->src, req->dst,
+ req->nbytes, iv, AES_IV_SIZE,
+- ctx->sa_out, ctx->sa_len);
++ ctx->sa_out, ctx->sa_len, 0);
+ }
+
+ int crypto4xx_rfc3686_decrypt(struct ablkcipher_request *req)
+@@ -227,7 +228,7 @@ int crypto4xx_rfc3686_decrypt(struct abl
+
+ return crypto4xx_build_pd(&req->base, ctx, req->src, req->dst,
+ req->nbytes, iv, AES_IV_SIZE,
+- ctx->sa_out, ctx->sa_len);
++ ctx->sa_out, ctx->sa_len, 0);
+ }
+
+ /**
+@@ -239,11 +240,13 @@ static int crypto4xx_hash_alg_init(struc
+ unsigned char hm)
+ {
+ struct crypto_alg *alg = tfm->__crt_alg;
+- struct crypto4xx_alg *my_alg = crypto_alg_to_crypto4xx_alg(alg);
++ struct crypto4xx_alg *my_alg;
+ struct crypto4xx_ctx *ctx = crypto_tfm_ctx(tfm);
+ struct dynamic_sa_hash160 *sa;
+ int rc;
+
++ my_alg = container_of(__crypto_ahash_alg(alg), struct crypto4xx_alg,
++ alg.u.hash);
+ ctx->dev = my_alg->dev;
+
+ /* Create SA */
+@@ -300,7 +303,7 @@ int crypto4xx_hash_update(struct ahash_r
+
+ return crypto4xx_build_pd(&req->base, ctx, req->src, &dst,
+ req->nbytes, NULL, 0, ctx->sa_in,
+- ctx->sa_len);
++ ctx->sa_len, 0);
+ }
+
+ int crypto4xx_hash_final(struct ahash_request *req)
+@@ -319,7 +322,7 @@ int crypto4xx_hash_digest(struct ahash_r
+
+ return crypto4xx_build_pd(&req->base, ctx, req->src, &dst,
+ req->nbytes, NULL, 0, ctx->sa_in,
+- ctx->sa_len);
++ ctx->sa_len, 0);
+ }
+
+ /**
+@@ -330,5 +333,3 @@ int crypto4xx_sha1_alg_init(struct crypt
+ return crypto4xx_hash_alg_init(tfm, SA_HASH160_LEN, SA_HASH_ALG_SHA1,
+ SA_HASH_MODE_HASH);
+ }
+-
+-
+--- a/drivers/crypto/amcc/crypto4xx_core.c
++++ b/drivers/crypto/amcc/crypto4xx_core.c
+@@ -35,10 +35,12 @@
+ #include <asm/dcr.h>
+ #include <asm/dcr-regs.h>
+ #include <asm/cacheflush.h>
++#include <crypto/aead.h>
+ #include <crypto/aes.h>
+ #include <crypto/ctr.h>
+ #include <crypto/sha.h>
+ #include <crypto/scatterwalk.h>
++#include <crypto/internal/aead.h>
+ #include <crypto/internal/skcipher.h>
+ #include "crypto4xx_reg_def.h"
+ #include "crypto4xx_core.h"
+@@ -518,7 +520,7 @@ static void crypto4xx_ret_sg_desc(struct
+ }
+ }
+
+-static u32 crypto4xx_ablkcipher_done(struct crypto4xx_device *dev,
++static void crypto4xx_ablkcipher_done(struct crypto4xx_device *dev,
+ struct pd_uinfo *pd_uinfo,
+ struct ce_pd *pd)
+ {
+@@ -543,11 +545,9 @@ static u32 crypto4xx_ablkcipher_done(str
+ if (pd_uinfo->state & PD_ENTRY_BUSY)
+ ablkcipher_request_complete(ablk_req, -EINPROGRESS);
+ ablkcipher_request_complete(ablk_req, 0);
+-
+- return 0;
+ }
+
+-static u32 crypto4xx_ahash_done(struct crypto4xx_device *dev,
++static void crypto4xx_ahash_done(struct crypto4xx_device *dev,
+ struct pd_uinfo *pd_uinfo)
+ {
+ struct crypto4xx_ctx *ctx;
+@@ -563,20 +563,88 @@ static u32 crypto4xx_ahash_done(struct c
+ if (pd_uinfo->state & PD_ENTRY_BUSY)
+ ahash_request_complete(ahash_req, -EINPROGRESS);
+ ahash_request_complete(ahash_req, 0);
++}
+
+- return 0;
++static void crypto4xx_aead_done(struct crypto4xx_device *dev,
++ struct pd_uinfo *pd_uinfo,
++ struct ce_pd *pd)
++{
++ struct aead_request *aead_req;
++ struct crypto4xx_ctx *ctx;
++ struct scatterlist *dst = pd_uinfo->dest_va;
++ int err = 0;
++
++ aead_req = container_of(pd_uinfo->async_req, struct aead_request,
++ base);
++ ctx = crypto_tfm_ctx(aead_req->base.tfm);
++
++ if (pd_uinfo->using_sd) {
++ crypto4xx_copy_pkt_to_dst(dev, pd, pd_uinfo,
++ pd->pd_ctl_len.bf.pkt_len,
++ dst);
++ } else {
++ __dma_sync_page(sg_page(dst), dst->offset, dst->length,
++ DMA_FROM_DEVICE);
++ }
++
++ if (pd_uinfo->sa_va->sa_command_0.bf.dir == DIR_OUTBOUND) {
++ /* append icv at the end */
++ size_t cp_len = crypto_aead_authsize(
++ crypto_aead_reqtfm(aead_req));
++ u32 icv[cp_len];
++
++ crypto4xx_memcpy_from_le32(icv, pd_uinfo->sr_va->save_digest,
++ cp_len);
++
++ scatterwalk_map_and_copy(icv, dst, aead_req->cryptlen,
++ cp_len, 1);
++ }
++
++ crypto4xx_ret_sg_desc(dev, pd_uinfo);
++
++ if (pd->pd_ctl.bf.status & 0xff) {
++ if (pd->pd_ctl.bf.status & 0x1) {
++ /* authentication error */
++ err = -EBADMSG;
++ } else {
++ if (!__ratelimit(&dev->aead_ratelimit)) {
++ if (pd->pd_ctl.bf.status & 2)
++ pr_err("pad fail error\n");
++ if (pd->pd_ctl.bf.status & 4)
++ pr_err("seqnum fail\n");
++ if (pd->pd_ctl.bf.status & 8)
++ pr_err("error _notify\n");
++ pr_err("aead return err status = 0x%02x\n",
++ pd->pd_ctl.bf.status & 0xff);
++ pr_err("pd pad_ctl = 0x%08x\n",
++ pd->pd_ctl.bf.pd_pad_ctl);
++ }
++ err = -EINVAL;
++ }
++ }
++
++ if (pd_uinfo->state & PD_ENTRY_BUSY)
++ aead_request_complete(aead_req, -EINPROGRESS);
++
++ aead_request_complete(aead_req, err);
+ }
+
+-static u32 crypto4xx_pd_done(struct crypto4xx_device *dev, u32 idx)
++static void crypto4xx_pd_done(struct crypto4xx_device *dev, u32 idx)
+ {
+ struct ce_pd *pd = &dev->pdr[idx];
+ struct pd_uinfo *pd_uinfo = &dev->pdr_uinfo[idx];
+
+- if (crypto_tfm_alg_type(pd_uinfo->async_req->tfm) ==
+- CRYPTO_ALG_TYPE_ABLKCIPHER)
+- return crypto4xx_ablkcipher_done(dev, pd_uinfo, pd);
+- else
+- return crypto4xx_ahash_done(dev, pd_uinfo);
++ switch (crypto_tfm_alg_type(pd_uinfo->async_req->tfm)) {
++ case CRYPTO_ALG_TYPE_ABLKCIPHER:
++ crypto4xx_ablkcipher_done(dev, pd_uinfo, pd);
++ break;
++ case CRYPTO_ALG_TYPE_AEAD:
++ crypto4xx_aead_done(dev, pd_uinfo, pd);
++ break;
++ case CRYPTO_ALG_TYPE_AHASH:
++ crypto4xx_ahash_done(dev, pd_uinfo);
++ break;
++ }
+ }
+
+ static void crypto4xx_stop_all(struct crypto4xx_core_device *core_dev)
+@@ -612,8 +680,10 @@ int crypto4xx_build_pd(struct crypto_asy
+ const unsigned int datalen,
+ const __le32 *iv, const u32 iv_len,
+ const struct dynamic_sa_ctl *req_sa,
+- const unsigned int sa_len)
++ const unsigned int sa_len,
++ const unsigned int assoclen)
+ {
++ struct scatterlist _dst[2];
+ struct crypto4xx_device *dev = ctx->dev;
+ struct dynamic_sa_ctl *sa;
+ struct ce_gd *gd;
+@@ -627,18 +697,25 @@ int crypto4xx_build_pd(struct crypto_asy
+ unsigned int nbytes = datalen;
+ size_t offset_to_sr_ptr;
+ u32 gd_idx = 0;
++ int tmp;
+ bool is_busy;
+
+- /* figure how many gd is needed */
+- num_gd = sg_nents_for_len(src, datalen);
+- if ((int)num_gd < 0) {
++ /* figure how many gd are needed */
++ tmp = sg_nents_for_len(src, assoclen + datalen);
++ if (tmp < 0) {
+ dev_err(dev->core_dev->device, "Invalid number of src SG.\n");
+- return -EINVAL;
++ return tmp;
+ }
+- if (num_gd == 1)
+- num_gd = 0;
++ if (tmp == 1)
++ tmp = 0;
++ num_gd = tmp;
+
+- /* figure how many sd is needed */
++ if (assoclen) {
++ nbytes += assoclen;
++ dst = scatterwalk_ffwd(_dst, dst, assoclen);
++ }
++
++ /* figure how many sd are needed */
+ if (sg_is_last(dst)) {
+ num_sd = 0;
+ } else {
+@@ -724,6 +801,7 @@ int crypto4xx_build_pd(struct crypto_asy
+ sa = pd_uinfo->sa_va;
+ memcpy(sa, req_sa, sa_len * 4);
+
++ sa->sa_command_1.bf.hash_crypto_offset = (assoclen >> 2);
+ offset_to_sr_ptr = get_dynamic_sa_offset_state_ptr_field(sa);
+ *(u32 *)((unsigned long)sa + offset_to_sr_ptr) = pd_uinfo->sr_pa;
+
+@@ -830,7 +908,7 @@ int crypto4xx_build_pd(struct crypto_asy
+ ((crypto_tfm_alg_type(req->tfm) == CRYPTO_ALG_TYPE_AHASH) |
+ (crypto_tfm_alg_type(req->tfm) == CRYPTO_ALG_TYPE_AEAD) ?
+ PD_CTL_HASH_FINAL : 0);
+- pd->pd_ctl_len.w = 0x00400000 | datalen;
++ pd->pd_ctl_len.w = 0x00400000 | (assoclen + datalen);
+ pd_uinfo->state = PD_ENTRY_INUSE | (is_busy ? PD_ENTRY_BUSY : 0);
+
+ wmb();
+@@ -843,40 +921,68 @@ int crypto4xx_build_pd(struct crypto_asy
+ /**
+ * Algorithm Registration Functions
+ */
+-static int crypto4xx_alg_init(struct crypto_tfm *tfm)
++static void crypto4xx_ctx_init(struct crypto4xx_alg *amcc_alg,
++ struct crypto4xx_ctx *ctx)
+ {
+- struct crypto_alg *alg = tfm->__crt_alg;
+- struct crypto4xx_alg *amcc_alg = crypto_alg_to_crypto4xx_alg(alg);
+- struct crypto4xx_ctx *ctx = crypto_tfm_ctx(tfm);
+-
+ ctx->dev = amcc_alg->dev;
+ ctx->sa_in = NULL;
+ ctx->sa_out = NULL;
+ ctx->sa_len = 0;
++}
+
+- switch (alg->cra_flags & CRYPTO_ALG_TYPE_MASK) {
+- default:
+- tfm->crt_ablkcipher.reqsize = sizeof(struct crypto4xx_ctx);
+- break;
+- case CRYPTO_ALG_TYPE_AHASH:
+- crypto_ahash_set_reqsize(__crypto_ahash_cast(tfm),
+- sizeof(struct crypto4xx_ctx));
+- break;
+- }
++static int crypto4xx_ablk_init(struct crypto_tfm *tfm)
++{
++ struct crypto_alg *alg = tfm->__crt_alg;
++ struct crypto4xx_alg *amcc_alg;
++ struct crypto4xx_ctx *ctx = crypto_tfm_ctx(tfm);
+
++ amcc_alg = container_of(alg, struct crypto4xx_alg, alg.u.cipher);
++ crypto4xx_ctx_init(amcc_alg, ctx);
++ tfm->crt_ablkcipher.reqsize = sizeof(struct crypto4xx_ctx);
+ return 0;
+ }
+
+-static void crypto4xx_alg_exit(struct crypto_tfm *tfm)
++static void crypto4xx_common_exit(struct crypto4xx_ctx *ctx)
+ {
+- struct crypto4xx_ctx *ctx = crypto_tfm_ctx(tfm);
+-
+ crypto4xx_free_sa(ctx);
+ }
+
+-int crypto4xx_register_alg(struct crypto4xx_device *sec_dev,
+- struct crypto4xx_alg_common *crypto_alg,
+- int array_size)
++static void crypto4xx_ablk_exit(struct crypto_tfm *tfm)
++{
++ crypto4xx_common_exit(crypto_tfm_ctx(tfm));
++}
++
++static int crypto4xx_aead_init(struct crypto_aead *tfm)
++{
++ struct aead_alg *alg = crypto_aead_alg(tfm);
++ struct crypto4xx_ctx *ctx = crypto_aead_ctx(tfm);
++ struct crypto4xx_alg *amcc_alg;
++
++ ctx->sw_cipher.aead = crypto_alloc_aead(alg->base.cra_name, 0,
++ CRYPTO_ALG_NEED_FALLBACK |
++ CRYPTO_ALG_ASYNC);
++ if (IS_ERR(ctx->sw_cipher.aead))
++ return PTR_ERR(ctx->sw_cipher.aead);
++
++ amcc_alg = container_of(alg, struct crypto4xx_alg, alg.u.aead);
++ crypto4xx_ctx_init(amcc_alg, ctx);
++ crypto_aead_set_reqsize(tfm, sizeof(struct aead_request) +
++ max(sizeof(struct crypto4xx_ctx), 32 +
++ crypto_aead_reqsize(ctx->sw_cipher.aead)));
++ return 0;
++}
++
++static void crypto4xx_aead_exit(struct crypto_aead *tfm)
++{
++ struct crypto4xx_ctx *ctx = crypto_aead_ctx(tfm);
++
++ crypto4xx_common_exit(ctx);
++ crypto_free_aead(ctx->sw_cipher.aead);
++}
++
++static int crypto4xx_register_alg(struct crypto4xx_device *sec_dev,
++ struct crypto4xx_alg_common *crypto_alg,
++ int array_size)
+ {
+ struct crypto4xx_alg *alg;
+ int i;
+@@ -891,6 +997,10 @@ int crypto4xx_register_alg(struct crypto
+ alg->dev = sec_dev;
+
+ switch (alg->alg.type) {
++ case CRYPTO_ALG_TYPE_AEAD:
++ rc = crypto_register_aead(&alg->alg.u.aead);
++ break;
++
+ case CRYPTO_ALG_TYPE_AHASH:
+ rc = crypto_register_ahash(&alg->alg.u.hash);
+ break;
+@@ -920,6 +1030,10 @@ static void crypto4xx_unregister_alg(str
+ crypto_unregister_ahash(&alg->alg.u.hash);
+ break;
+
++ case CRYPTO_ALG_TYPE_AEAD:
++ crypto_unregister_aead(&alg->alg.u.aead);
++ break;
++
+ default:
+ crypto_unregister_alg(&alg->alg.u.cipher);
+ }
+@@ -973,7 +1087,7 @@ static irqreturn_t crypto4xx_ce_interrup
+ /**
+ * Supported Crypto Algorithms
+ */
+-struct crypto4xx_alg_common crypto4xx_alg[] = {
++static struct crypto4xx_alg_common crypto4xx_alg[] = {
+ /* Crypto AES modes */
+ { .type = CRYPTO_ALG_TYPE_ABLKCIPHER, .u.cipher = {
+ .cra_name = "cbc(aes)",
+@@ -985,8 +1099,8 @@ struct crypto4xx_alg_common crypto4xx_al
+ .cra_blocksize = AES_BLOCK_SIZE,
+ .cra_ctxsize = sizeof(struct crypto4xx_ctx),
+ .cra_type = &crypto_ablkcipher_type,
+- .cra_init = crypto4xx_alg_init,
+- .cra_exit = crypto4xx_alg_exit,
++ .cra_init = crypto4xx_ablk_init,
++ .cra_exit = crypto4xx_ablk_exit,
+ .cra_module = THIS_MODULE,
+ .cra_u = {
+ .ablkcipher = {
+@@ -1009,8 +1123,8 @@ struct crypto4xx_alg_common crypto4xx_al
+ .cra_blocksize = AES_BLOCK_SIZE,
+ .cra_ctxsize = sizeof(struct crypto4xx_ctx),
+ .cra_type = &crypto_ablkcipher_type,
+- .cra_init = crypto4xx_alg_init,
+- .cra_exit = crypto4xx_alg_exit,
++ .cra_init = crypto4xx_ablk_init,
++ .cra_exit = crypto4xx_ablk_exit,
+ .cra_module = THIS_MODULE,
+ .cra_u = {
+ .ablkcipher = {
+@@ -1033,8 +1147,8 @@ struct crypto4xx_alg_common crypto4xx_al
+ .cra_blocksize = AES_BLOCK_SIZE,
+ .cra_ctxsize = sizeof(struct crypto4xx_ctx),
+ .cra_type = &crypto_ablkcipher_type,
+- .cra_init = crypto4xx_alg_init,
+- .cra_exit = crypto4xx_alg_exit,
++ .cra_init = crypto4xx_ablk_init,
++ .cra_exit = crypto4xx_ablk_exit,
+ .cra_module = THIS_MODULE,
+ .cra_u = {
+ .ablkcipher = {
+@@ -1059,8 +1173,8 @@ struct crypto4xx_alg_common crypto4xx_al
+ .cra_blocksize = AES_BLOCK_SIZE,
+ .cra_ctxsize = sizeof(struct crypto4xx_ctx),
+ .cra_type = &crypto_ablkcipher_type,
+- .cra_init = crypto4xx_alg_init,
+- .cra_exit = crypto4xx_alg_exit,
++ .cra_init = crypto4xx_ablk_init,
++ .cra_exit = crypto4xx_ablk_exit,
+ .cra_module = THIS_MODULE,
+ .cra_u = {
+ .ablkcipher = {
+@@ -1082,8 +1196,8 @@ struct crypto4xx_alg_common crypto4xx_al
+ .cra_blocksize = AES_BLOCK_SIZE,
+ .cra_ctxsize = sizeof(struct crypto4xx_ctx),
+ .cra_type = &crypto_ablkcipher_type,
+- .cra_init = crypto4xx_alg_init,
+- .cra_exit = crypto4xx_alg_exit,
++ .cra_init = crypto4xx_ablk_init,
++ .cra_exit = crypto4xx_ablk_exit,
+ .cra_module = THIS_MODULE,
+ .cra_u = {
+ .ablkcipher = {
+@@ -1149,6 +1263,7 @@ static int crypto4xx_probe(struct platfo
+ core_dev->device = dev;
+ spin_lock_init(&core_dev->lock);
+ INIT_LIST_HEAD(&core_dev->dev->alg_list);
++ ratelimit_default_init(&core_dev->dev->aead_ratelimit);
+ rc = crypto4xx_build_pdr(core_dev->dev);
+ if (rc)
+ goto err_build_pdr;
+--- a/drivers/crypto/amcc/crypto4xx_core.h
++++ b/drivers/crypto/amcc/crypto4xx_core.h
+@@ -22,7 +22,9 @@
+ #ifndef __CRYPTO4XX_CORE_H__
+ #define __CRYPTO4XX_CORE_H__
+
++#include <linux/ratelimit.h>
+ #include <crypto/internal/hash.h>
++#include <crypto/internal/aead.h>
+ #include "crypto4xx_reg_def.h"
+ #include "crypto4xx_sa.h"
+
+@@ -106,6 +108,7 @@ struct crypto4xx_device {
+ struct pd_uinfo *pdr_uinfo;
+ struct list_head alg_list; /* List of algorithm supported
+ by this device */
++ struct ratelimit_state aead_ratelimit;
+ };
+
+ struct crypto4xx_core_device {
+@@ -125,6 +128,9 @@ struct crypto4xx_ctx {
+ struct dynamic_sa_ctl *sa_out;
+ __le32 iv_nonce;
+ u32 sa_len;
++ union {
++ struct crypto_aead *aead;
++ } sw_cipher;
+ };
+
+ struct crypto4xx_alg_common {
+@@ -132,6 +138,7 @@ struct crypto4xx_alg_common {
+ union {
+ struct crypto_alg cipher;
+ struct ahash_alg hash;
++ struct aead_alg aead;
+ } u;
+ };
+
+@@ -141,18 +148,6 @@ struct crypto4xx_alg {
+ struct crypto4xx_device *dev;
+ };
+
+-static inline struct crypto4xx_alg *crypto_alg_to_crypto4xx_alg(
+- struct crypto_alg *x)
+-{
+- switch (x->cra_flags & CRYPTO_ALG_TYPE_MASK) {
+- case CRYPTO_ALG_TYPE_AHASH:
+- return container_of(__crypto_ahash_alg(x),
+- struct crypto4xx_alg, alg.u.hash);
+- }
+-
+- return container_of(x, struct crypto4xx_alg, alg.u.cipher);
+-}
+-
+ int crypto4xx_alloc_sa(struct crypto4xx_ctx *ctx, u32 size);
+ void crypto4xx_free_sa(struct crypto4xx_ctx *ctx);
+ void crypto4xx_free_ctx(struct crypto4xx_ctx *ctx);
+@@ -163,7 +158,8 @@ int crypto4xx_build_pd(struct crypto_asy
+ const unsigned int datalen,
+ const __le32 *iv, const u32 iv_len,
+ const struct dynamic_sa_ctl *sa,
+- const unsigned int sa_len);
++ const unsigned int sa_len,
++ const unsigned int assoclen);
+ int crypto4xx_setkey_aes_cbc(struct crypto_ablkcipher *cipher,
+ const u8 *key, unsigned int keylen);
+ int crypto4xx_setkey_aes_cfb(struct crypto_ablkcipher *cipher,
+--- a/drivers/crypto/amcc/crypto4xx_sa.h
++++ b/drivers/crypto/amcc/crypto4xx_sa.h
+@@ -55,6 +55,8 @@ union dynamic_sa_contents {
+ #define SA_OP_GROUP_BASIC 0
+ #define SA_OPCODE_ENCRYPT 0
+ #define SA_OPCODE_DECRYPT 0
++#define SA_OPCODE_ENCRYPT_HASH 1
++#define SA_OPCODE_HASH_DECRYPT 1
+ #define SA_OPCODE_HASH 3
+ #define SA_CIPHER_ALG_DES 0
+ #define SA_CIPHER_ALG_3DES 1
+@@ -65,6 +67,8 @@ union dynamic_sa_contents {
+
+ #define SA_HASH_ALG_MD5 0
+ #define SA_HASH_ALG_SHA1 1
++#define SA_HASH_ALG_GHASH 12
++#define SA_HASH_ALG_CBC_MAC 14
+ #define SA_HASH_ALG_NULL 15
+ #define SA_HASH_ALG_SHA1_DIGEST_SIZE 20
+
+@@ -234,6 +238,36 @@ struct dynamic_sa_aes256 {
+ #define SA_AES_CONTENTS 0x3e000002
+
+ /**
++ * Security Association (SA) for AES128 CCM
++ */
++struct dynamic_sa_aes128_ccm {
++ struct dynamic_sa_ctl ctrl;
++ __le32 key[4];
++ __le32 iv[4];
++ u32 state_ptr;
++ u32 reserved;
++} __packed;
++#define SA_AES128_CCM_LEN (sizeof(struct dynamic_sa_aes128_ccm)/4)
++#define SA_AES128_CCM_CONTENTS 0x3e000042
++#define SA_AES_CCM_CONTENTS 0x3e000002
++
++/**
++ * Security Association (SA) for AES128_GCM
++ */
++struct dynamic_sa_aes128_gcm {
++ struct dynamic_sa_ctl ctrl;
++ __le32 key[4];
++ __le32 inner_digest[4];
++ __le32 iv[4];
++ u32 state_ptr;
++ u32 reserved;
++} __packed;
++
++#define SA_AES128_GCM_LEN (sizeof(struct dynamic_sa_aes128_gcm)/4)
++#define SA_AES128_GCM_CONTENTS 0x3e000442
++#define SA_AES_GCM_CONTENTS 0x3e000402
++
++/**
+ * Security Association (SA) for HASH160: HMAC-SHA1
+ */
+ struct dynamic_sa_hash160 {
+@@ -274,4 +308,11 @@ static inline __le32 *get_dynamic_sa_key
+ return (__le32 *) ((unsigned long)cts + sizeof(struct dynamic_sa_ctl));
+ }
+
++static inline __le32 *get_dynamic_sa_inner_digest(struct dynamic_sa_ctl *cts)
++{
++ return (__le32 *) ((unsigned long)cts +
++ sizeof(struct dynamic_sa_ctl) +
++ cts->sa_contents.bf.key_size * 4);
++}
++
+ #endif
diff --git a/target/linux/apm821xx/patches-4.14/020-0024-crypto-crypto4xx-add-aes-ccm-support.patch b/target/linux/apm821xx/patches-4.14/020-0024-crypto-crypto4xx-add-aes-ccm-support.patch
new file mode 100644
index 0000000..73283f6
--- /dev/null
+++ b/target/linux/apm821xx/patches-4.14/020-0024-crypto-crypto4xx-add-aes-ccm-support.patch
@@ -0,0 +1,256 @@
+From 65ea8b678fcf385ac18864743bae66c0643e6842 Mon Sep 17 00:00:00 2001
+From: Christian Lamparter <chunkeey@gmail.com>
+Date: Wed, 4 Oct 2017 01:00:16 +0200
+Subject: [PATCH 24/25] crypto: crypto4xx - add aes-ccm support
+
+This patch adds aes-ccm support.
+
+Signed-off-by: Christian Lamparter <chunkeey@gmail.com>
+Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
+---
+ drivers/crypto/amcc/crypto4xx_alg.c | 185 +++++++++++++++++++++++++++++++++++
+ drivers/crypto/amcc/crypto4xx_core.c | 23 +++++
+ drivers/crypto/amcc/crypto4xx_core.h | 8 ++
+ 3 files changed, 216 insertions(+)
+
+--- a/drivers/crypto/amcc/crypto4xx_alg.c
++++ b/drivers/crypto/amcc/crypto4xx_alg.c
+@@ -231,6 +231,191 @@ int crypto4xx_rfc3686_decrypt(struct abl
+ ctx->sa_out, ctx->sa_len, 0);
+ }
+
++static inline bool crypto4xx_aead_need_fallback(struct aead_request *req,
++ bool is_ccm, bool decrypt)
++{
++ struct crypto_aead *aead = crypto_aead_reqtfm(req);
++
++ /* authsize has to be a multiple of 4 */
++ if (aead->authsize & 3)
++ return true;
++
++ /*
++ * hardware does not handle cases where cryptlen
++ * is less than a block
++ */
++ if (req->cryptlen < AES_BLOCK_SIZE)
++ return true;
++
++ /* assoc len needs to be a multiple of 4 */
++ if (req->assoclen & 0x3)
++ return true;
++
++ /* CCM supports only counter field length of 2 and 4 bytes */
++ if (is_ccm && !(req->iv[0] == 1 || req->iv[0] == 3))
++ return true;
++
++ /* CCM - fix CBC MAC mismatch in special case */
++ if (is_ccm && decrypt && !req->assoclen)
++ return true;
++
++ return false;
++}
++
++static int crypto4xx_aead_fallback(struct aead_request *req,
++ struct crypto4xx_ctx *ctx, bool do_decrypt)
++{
++ char aead_req_data[sizeof(struct aead_request) +
++ crypto_aead_reqsize(ctx->sw_cipher.aead)]
++ __aligned(__alignof__(struct aead_request));
++
++ struct aead_request *subreq = (void *) aead_req_data;
++
++ memset(subreq, 0, sizeof(aead_req_data));
++
++ aead_request_set_tfm(subreq, ctx->sw_cipher.aead);
++ aead_request_set_callback(subreq, req->base.flags,
++ req->base.complete, req->base.data);
++ aead_request_set_crypt(subreq, req->src, req->dst, req->cryptlen,
++ req->iv);
++ aead_request_set_ad(subreq, req->assoclen);
++ return do_decrypt ? crypto_aead_decrypt(subreq) :
++ crypto_aead_encrypt(subreq);
++}
++
++static int crypto4xx_setup_fallback(struct crypto4xx_ctx *ctx,
++ struct crypto_aead *cipher,
++ const u8 *key,
++ unsigned int keylen)
++{
++ int rc;
++
++ crypto_aead_clear_flags(ctx->sw_cipher.aead, CRYPTO_TFM_REQ_MASK);
++ crypto_aead_set_flags(ctx->sw_cipher.aead,
++ crypto_aead_get_flags(cipher) & CRYPTO_TFM_REQ_MASK);
++ rc = crypto_aead_setkey(ctx->sw_cipher.aead, key, keylen);
++ crypto_aead_clear_flags(cipher, CRYPTO_TFM_RES_MASK);
++ crypto_aead_set_flags(cipher,
++ crypto_aead_get_flags(ctx->sw_cipher.aead) &
++ CRYPTO_TFM_RES_MASK);
++
++ return rc;
++}
++
++/**
++ * AES-CCM Functions
++ */
++
++int crypto4xx_setkey_aes_ccm(struct crypto_aead *cipher, const u8 *key,
++ unsigned int keylen)
++{
++ struct crypto_tfm *tfm = crypto_aead_tfm(cipher);
++ struct crypto4xx_ctx *ctx = crypto_tfm_ctx(tfm);
++ struct dynamic_sa_ctl *sa;
++ int rc = 0;
++
++ rc = crypto4xx_setup_fallback(ctx, cipher, key, keylen);
++ if (rc)
++ return rc;
++
++ if (ctx->sa_in || ctx->sa_out)
++ crypto4xx_free_sa(ctx);
++
++ rc = crypto4xx_alloc_sa(ctx, SA_AES128_CCM_LEN + (keylen - 16) / 4);
++ if (rc)
++ return rc;
++
++ /* Setup SA */
++ sa = (struct dynamic_sa_ctl *) ctx->sa_in;
++ sa->sa_contents.w = SA_AES_CCM_CONTENTS | (keylen << 2);
++
++ set_dynamic_sa_command_0(sa, SA_NOT_SAVE_HASH, SA_NOT_SAVE_IV,
++ SA_LOAD_HASH_FROM_SA, SA_LOAD_IV_FROM_STATE,
++ SA_NO_HEADER_PROC, SA_HASH_ALG_CBC_MAC,
++ SA_CIPHER_ALG_AES,
++ SA_PAD_TYPE_ZERO, SA_OP_GROUP_BASIC,
++ SA_OPCODE_HASH_DECRYPT, DIR_INBOUND);
++
++ set_dynamic_sa_command_1(sa, CRYPTO_MODE_CTR, SA_HASH_MODE_HASH,
++ CRYPTO_FEEDBACK_MODE_NO_FB, SA_EXTENDED_SN_OFF,
++ SA_SEQ_MASK_OFF, SA_MC_ENABLE,
++ SA_NOT_COPY_PAD, SA_COPY_PAYLOAD,
++ SA_NOT_COPY_HDR);
++
++ sa->sa_command_1.bf.key_len = keylen >> 3;
++
++ crypto4xx_memcpy_to_le32(get_dynamic_sa_key_field(sa), key, keylen);
++
++ memcpy(ctx->sa_out, ctx->sa_in, ctx->sa_len * 4);
++ sa = (struct dynamic_sa_ctl *) ctx->sa_out;
++
++ set_dynamic_sa_command_0(sa, SA_SAVE_HASH, SA_NOT_SAVE_IV,
++ SA_LOAD_HASH_FROM_SA, SA_LOAD_IV_FROM_STATE,
++ SA_NO_HEADER_PROC, SA_HASH_ALG_CBC_MAC,
++ SA_CIPHER_ALG_AES,
++ SA_PAD_TYPE_ZERO, SA_OP_GROUP_BASIC,
++ SA_OPCODE_ENCRYPT_HASH, DIR_OUTBOUND);
++
++ set_dynamic_sa_command_1(sa, CRYPTO_MODE_CTR, SA_HASH_MODE_HASH,
++ CRYPTO_FEEDBACK_MODE_NO_FB, SA_EXTENDED_SN_OFF,
++ SA_SEQ_MASK_OFF, SA_MC_ENABLE,
++ SA_COPY_PAD, SA_COPY_PAYLOAD,
++ SA_NOT_COPY_HDR);
++
++ sa->sa_command_1.bf.key_len = keylen >> 3;
++ return 0;
++}
++
++static int crypto4xx_crypt_aes_ccm(struct aead_request *req, bool decrypt)
++{
++ struct crypto4xx_ctx *ctx = crypto_tfm_ctx(req->base.tfm);
++ struct crypto_aead *aead = crypto_aead_reqtfm(req);
++ unsigned int len = req->cryptlen;
++ __le32 iv[16];
++ u32 tmp_sa[ctx->sa_len * 4];
++ struct dynamic_sa_ctl *sa = (struct dynamic_sa_ctl *)tmp_sa;
++
++ if (crypto4xx_aead_need_fallback(req, true, decrypt))
++ return crypto4xx_aead_fallback(req, ctx, decrypt);
++
++ if (decrypt)
++ len -= crypto_aead_authsize(aead);
++
++ memcpy(tmp_sa, decrypt ? ctx->sa_in : ctx->sa_out, sizeof(tmp_sa));
++ sa->sa_command_0.bf.digest_len = crypto_aead_authsize(aead) >> 2;
++
++ if (req->iv[0] == 1) {
++ /* CRYPTO_MODE_AES_ICM */
++ sa->sa_command_1.bf.crypto_mode9_8 = 1;
++ }
++
++ iv[3] = cpu_to_le32(0);
++ crypto4xx_memcpy_to_le32(iv, req->iv, 16 - (req->iv[0] + 1));
++
++ return crypto4xx_build_pd(&req->base, ctx, req->src, req->dst,
++ len, iv, sizeof(iv),
++ sa, ctx->sa_len, req->assoclen);
++}
++
++int crypto4xx_encrypt_aes_ccm(struct aead_request *req)
++{
++ return crypto4xx_crypt_aes_ccm(req, false);
++}
++
++int crypto4xx_decrypt_aes_ccm(struct aead_request *req)
++{
++ return crypto4xx_crypt_aes_ccm(req, true);
++}
++
++int crypto4xx_setauthsize_aead(struct crypto_aead *cipher,
++ unsigned int authsize)
++{
++ struct crypto_tfm *tfm = crypto_aead_tfm(cipher);
++ struct crypto4xx_ctx *ctx = crypto_tfm_ctx(tfm);
++
++ return crypto_aead_setauthsize(ctx->sw_cipher.aead, authsize);
++}
++
+ /**
+ * HASH SHA1 Functions
+ */
+--- a/drivers/crypto/amcc/crypto4xx_core.c
++++ b/drivers/crypto/amcc/crypto4xx_core.c
+@@ -1210,6 +1210,29 @@ static struct crypto4xx_alg_common crypt
+ }
+ }
+ } },
++
++ /* AEAD */
++ { .type = CRYPTO_ALG_TYPE_AEAD, .u.aead = {
++ .setkey = crypto4xx_setkey_aes_ccm,
++ .setauthsize = crypto4xx_setauthsize_aead,
++ .encrypt = crypto4xx_encrypt_aes_ccm,
++ .decrypt = crypto4xx_decrypt_aes_ccm,
++ .init = crypto4xx_aead_init,
++ .exit = crypto4xx_aead_exit,
++ .ivsize = AES_BLOCK_SIZE,
++ .maxauthsize = 16,
++ .base = {
++ .cra_name = "ccm(aes)",
++ .cra_driver_name = "ccm-aes-ppc4xx",
++ .cra_priority = CRYPTO4XX_CRYPTO_PRIORITY,
++ .cra_flags = CRYPTO_ALG_ASYNC |
++ CRYPTO_ALG_NEED_FALLBACK |
++ CRYPTO_ALG_KERN_DRIVER_ONLY,
++ .cra_blocksize = 1,
++ .cra_ctxsize = sizeof(struct crypto4xx_ctx),
++ .cra_module = THIS_MODULE,
++ },
++ } },
+ };
+
+ /**
+--- a/drivers/crypto/amcc/crypto4xx_core.h
++++ b/drivers/crypto/amcc/crypto4xx_core.h
+@@ -222,4 +222,12 @@ static inline void crypto4xx_memcpy_to_l
+ {
+ crypto4xx_memcpy_swab32((u32 *)dst, buf, len);
+ }
++
++int crypto4xx_setauthsize_aead(struct crypto_aead *ciper,
++ unsigned int authsize);
++int crypto4xx_setkey_aes_ccm(struct crypto_aead *cipher,
++ const u8 *key, unsigned int keylen);
++int crypto4xx_encrypt_aes_ccm(struct aead_request *req);
++int crypto4xx_decrypt_aes_ccm(struct aead_request *req);
++
+ #endif
diff --git a/target/linux/apm821xx/patches-4.14/020-0025-crypto-crypto4xx-add-aes-gcm-support.patch b/target/linux/apm821xx/patches-4.14/020-0025-crypto-crypto4xx-add-aes-gcm-support.patch
new file mode 100644
index 0000000..3a2ed31
--- /dev/null
+++ b/target/linux/apm821xx/patches-4.14/020-0025-crypto-crypto4xx-add-aes-gcm-support.patch
@@ -0,0 +1,220 @@
+From 59231368d3a959fc30c5142c406a045f49130daa Mon Sep 17 00:00:00 2001
+From: Christian Lamparter <chunkeey@gmail.com>
+Date: Wed, 4 Oct 2017 01:00:17 +0200
+Subject: [PATCH 25/25] crypto: crypto4xx - add aes-gcm support
+
+This patch adds aes-gcm support to crypto4xx.
+
+Signed-off-by: Christian Lamparter <chunkeey@gmail.com>
+Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
+---
+ drivers/crypto/amcc/crypto4xx_alg.c | 139 +++++++++++++++++++++++++++++++++++
+ drivers/crypto/amcc/crypto4xx_core.c | 22 ++++++
+ drivers/crypto/amcc/crypto4xx_core.h | 4 +
+ 3 files changed, 165 insertions(+)
+
+--- a/drivers/crypto/amcc/crypto4xx_alg.c
++++ b/drivers/crypto/amcc/crypto4xx_alg.c
+@@ -28,6 +28,7 @@
+ #include <crypto/algapi.h>
+ #include <crypto/aead.h>
+ #include <crypto/aes.h>
++#include <crypto/gcm.h>
+ #include <crypto/sha.h>
+ #include <crypto/ctr.h>
+ #include "crypto4xx_reg_def.h"
+@@ -417,6 +418,144 @@ int crypto4xx_setauthsize_aead(struct cr
+ }
+
+ /**
++ * AES-GCM Functions
++ */
++
++static int crypto4xx_aes_gcm_validate_keylen(unsigned int keylen)
++{
++ switch (keylen) {
++ case 16:
++ case 24:
++ case 32:
++ return 0;
++ default:
++ return -EINVAL;
++ }
++}
++
++static int crypto4xx_compute_gcm_hash_key_sw(__le32 *hash_start, const u8 *key,
++ unsigned int keylen)
++{
++ struct crypto_cipher *aes_tfm = NULL;
++ uint8_t src[16] = { 0 };
++ int rc = 0;
++
++ aes_tfm = crypto_alloc_cipher("aes", 0, CRYPTO_ALG_ASYNC |
++ CRYPTO_ALG_NEED_FALLBACK);
++ if (IS_ERR(aes_tfm)) {
++ rc = PTR_ERR(aes_tfm);
++ pr_warn("could not load aes cipher driver: %d\n", rc);
++ return rc;
++ }
++
++ rc = crypto_cipher_setkey(aes_tfm, key, keylen);
++ if (rc) {
++ pr_err("setkey() failed: %d\n", rc);
++ goto out;
++ }
++
++ crypto_cipher_encrypt_one(aes_tfm, src, src);
++ crypto4xx_memcpy_to_le32(hash_start, src, 16);
++out:
++ crypto_free_cipher(aes_tfm);
++ return rc;
++}
++
++int crypto4xx_setkey_aes_gcm(struct crypto_aead *cipher,
++ const u8 *key, unsigned int keylen)
++{
++ struct crypto_tfm *tfm = crypto_aead_tfm(cipher);
++ struct crypto4xx_ctx *ctx = crypto_tfm_ctx(tfm);
++ struct dynamic_sa_ctl *sa;
++ int rc = 0;
++
++ if (crypto4xx_aes_gcm_validate_keylen(keylen) != 0) {
++ crypto_aead_set_flags(cipher, CRYPTO_TFM_RES_BAD_KEY_LEN);
++ return -EINVAL;
++ }
++
++ rc = crypto4xx_setup_fallback(ctx, cipher, key, keylen);
++ if (rc)
++ return rc;
++
++ if (ctx->sa_in || ctx->sa_out)
++ crypto4xx_free_sa(ctx);
++
++ rc = crypto4xx_alloc_sa(ctx, SA_AES128_GCM_LEN + (keylen - 16) / 4);
++ if (rc)
++ return rc;
++
++ sa = (struct dynamic_sa_ctl *) ctx->sa_in;
++
++ sa->sa_contents.w = SA_AES_GCM_CONTENTS | (keylen << 2);
++ set_dynamic_sa_command_0(sa, SA_SAVE_HASH, SA_NOT_SAVE_IV,
++ SA_LOAD_HASH_FROM_SA, SA_LOAD_IV_FROM_STATE,
++ SA_NO_HEADER_PROC, SA_HASH_ALG_GHASH,
++ SA_CIPHER_ALG_AES, SA_PAD_TYPE_ZERO,
++ SA_OP_GROUP_BASIC, SA_OPCODE_HASH_DECRYPT,
++ DIR_INBOUND);
++ set_dynamic_sa_command_1(sa, CRYPTO_MODE_CTR, SA_HASH_MODE_HASH,
++ CRYPTO_FEEDBACK_MODE_NO_FB, SA_EXTENDED_SN_OFF,
++ SA_SEQ_MASK_ON, SA_MC_DISABLE,
++ SA_NOT_COPY_PAD, SA_COPY_PAYLOAD,
++ SA_NOT_COPY_HDR);
++
++ sa->sa_command_1.bf.key_len = keylen >> 3;
++
++ crypto4xx_memcpy_to_le32(get_dynamic_sa_key_field(sa),
++ key, keylen);
++
++ rc = crypto4xx_compute_gcm_hash_key_sw(get_dynamic_sa_inner_digest(sa),
++ key, keylen);
++ if (rc) {
++ pr_err("GCM hash key setting failed = %d\n", rc);
++ goto err;
++ }
++
++ memcpy(ctx->sa_out, ctx->sa_in, ctx->sa_len * 4);
++ sa = (struct dynamic_sa_ctl *) ctx->sa_out;
++ sa->sa_command_0.bf.dir = DIR_OUTBOUND;
++ sa->sa_command_0.bf.opcode = SA_OPCODE_ENCRYPT_HASH;
++
++ return 0;
++err:
++ crypto4xx_free_sa(ctx);
++ return rc;
++}
++
++static inline int crypto4xx_crypt_aes_gcm(struct aead_request *req,
++ bool decrypt)
++{
++ struct crypto4xx_ctx *ctx = crypto_tfm_ctx(req->base.tfm);
++ unsigned int len = req->cryptlen;
++ __le32 iv[4];
++
++ if (crypto4xx_aead_need_fallback(req, false, decrypt))
++ return crypto4xx_aead_fallback(req, ctx, decrypt);
++
++ crypto4xx_memcpy_to_le32(iv, req->iv, GCM_AES_IV_SIZE);
++ iv[3] = cpu_to_le32(1);
++
++ if (decrypt)
++ len -= crypto_aead_authsize(crypto_aead_reqtfm(req));
++
++ return crypto4xx_build_pd(&req->base, ctx, req->src, req->dst,
++ len, iv, sizeof(iv),
++ decrypt ? ctx->sa_in : ctx->sa_out,
++ ctx->sa_len, req->assoclen);
++}
++
++int crypto4xx_encrypt_aes_gcm(struct aead_request *req)
++{
++ return crypto4xx_crypt_aes_gcm(req, false);
++}
++
++int crypto4xx_decrypt_aes_gcm(struct aead_request *req)
++{
++ return crypto4xx_crypt_aes_gcm(req, true);
++}
++
++/**
+ * HASH SHA1 Functions
+ */
+ static int crypto4xx_hash_alg_init(struct crypto_tfm *tfm,
+--- a/drivers/crypto/amcc/crypto4xx_core.c
++++ b/drivers/crypto/amcc/crypto4xx_core.c
+@@ -38,6 +38,7 @@
+ #include <crypto/aead.h>
+ #include <crypto/aes.h>
+ #include <crypto/ctr.h>
++#include <crypto/gcm.h>
+ #include <crypto/sha.h>
+ #include <crypto/scatterwalk.h>
+ #include <crypto/internal/aead.h>
+@@ -1227,6 +1228,27 @@ static struct crypto4xx_alg_common crypt
+ .cra_priority = CRYPTO4XX_CRYPTO_PRIORITY,
+ .cra_flags = CRYPTO_ALG_ASYNC |
+ CRYPTO_ALG_NEED_FALLBACK |
++ CRYPTO_ALG_KERN_DRIVER_ONLY,
++ .cra_blocksize = 1,
++ .cra_ctxsize = sizeof(struct crypto4xx_ctx),
++ .cra_module = THIS_MODULE,
++ },
++ } },
++ { .type = CRYPTO_ALG_TYPE_AEAD, .u.aead = {
++ .setkey = crypto4xx_setkey_aes_gcm,
++ .setauthsize = crypto4xx_setauthsize_aead,
++ .encrypt = crypto4xx_encrypt_aes_gcm,
++ .decrypt = crypto4xx_decrypt_aes_gcm,
++ .init = crypto4xx_aead_init,
++ .exit = crypto4xx_aead_exit,
++ .ivsize = GCM_AES_IV_SIZE,
++ .maxauthsize = 16,
++ .base = {
++ .cra_name = "gcm(aes)",
++ .cra_driver_name = "gcm-aes-ppc4xx",
++ .cra_priority = CRYPTO4XX_CRYPTO_PRIORITY,
++ .cra_flags = CRYPTO_ALG_ASYNC |
++ CRYPTO_ALG_NEED_FALLBACK |
+ CRYPTO_ALG_KERN_DRIVER_ONLY,
+ .cra_blocksize = 1,
+ .cra_ctxsize = sizeof(struct crypto4xx_ctx),
+--- a/drivers/crypto/amcc/crypto4xx_core.h
++++ b/drivers/crypto/amcc/crypto4xx_core.h
+@@ -229,5 +229,9 @@ int crypto4xx_setkey_aes_ccm(struct cryp
+ const u8 *key, unsigned int keylen);
+ int crypto4xx_encrypt_aes_ccm(struct aead_request *req);
+ int crypto4xx_decrypt_aes_ccm(struct aead_request *req);
++int crypto4xx_setkey_aes_gcm(struct crypto_aead *cipher,
++ const u8 *key, unsigned int keylen);
++int crypto4xx_encrypt_aes_gcm(struct aead_request *req);
++int crypto4xx_decrypt_aes_gcm(struct aead_request *req);
+
+ #endif
diff --git a/target/linux/apm821xx/patches-4.14/120-0001-crypto-crypto4xx-shuffle-iomap-in-front-of-request_i.patch b/target/linux/apm821xx/patches-4.14/120-0001-crypto-crypto4xx-shuffle-iomap-in-front-of-request_i.patch
new file mode 100644
index 0000000..fc8df38
--- /dev/null
+++ b/target/linux/apm821xx/patches-4.14/120-0001-crypto-crypto4xx-shuffle-iomap-in-front-of-request_i.patch
@@ -0,0 +1,71 @@
+From 4baa099377d73ea99c7802a9685815b32e8bf119 Mon Sep 17 00:00:00 2001
+From: Christian Lamparter <chunkeey@gmail.com>
+Date: Thu, 21 Dec 2017 15:08:18 +0100
+Subject: [PATCH 1/6] crypto: crypto4xx - shuffle iomap in front of request_irq
+
+It is possible to avoid the ce_base null pointer check in the
+drivers' interrupt handler routine "crypto4xx_ce_interrupt_handler()"
+by simply doing the iomap in front of the IRQ registration.
+
+This way, the ce_base will always be valid in the handler and
+a branch in an critical path can be avoided.
+
+Signed-off-by: Christian Lamparter <chunkeey@gmail.com>
+---
+ drivers/crypto/amcc/crypto4xx_core.c | 21 +++++++++------------
+ 1 file changed, 9 insertions(+), 12 deletions(-)
+
+--- a/drivers/crypto/amcc/crypto4xx_core.c
++++ b/drivers/crypto/amcc/crypto4xx_core.c
+@@ -1075,9 +1075,6 @@ static irqreturn_t crypto4xx_ce_interrup
+ struct device *dev = (struct device *)data;
+ struct crypto4xx_core_device *core_dev = dev_get_drvdata(dev);
+
+- if (!core_dev->dev->ce_base)
+- return 0;
+-
+ writel(PPC4XX_INTERRUPT_CLR,
+ core_dev->dev->ce_base + CRYPTO4XX_INT_CLR);
+ tasklet_schedule(&core_dev->tasklet);
+@@ -1325,13 +1322,6 @@ static int crypto4xx_probe(struct platfo
+ tasklet_init(&core_dev->tasklet, crypto4xx_bh_tasklet_cb,
+ (unsigned long) dev);
+
+- /* Register for Crypto isr, Crypto Engine IRQ */
+- core_dev->irq = irq_of_parse_and_map(ofdev->dev.of_node, 0);
+- rc = request_irq(core_dev->irq, crypto4xx_ce_interrupt_handler, 0,
+- core_dev->dev->name, dev);
+- if (rc)
+- goto err_request_irq;
+-
+ core_dev->dev->ce_base = of_iomap(ofdev->dev.of_node, 0);
+ if (!core_dev->dev->ce_base) {
+ dev_err(dev, "failed to of_iomap\n");
+@@ -1339,6 +1329,13 @@ static int crypto4xx_probe(struct platfo
+ goto err_iomap;
+ }
+
++ /* Register for Crypto isr, Crypto Engine IRQ */
++ core_dev->irq = irq_of_parse_and_map(ofdev->dev.of_node, 0);
++ rc = request_irq(core_dev->irq, crypto4xx_ce_interrupt_handler, 0,
++ core_dev->dev->name, dev);
++ if (rc)
++ goto err_request_irq;
++
+ /* need to setup pdr, rdr, gdr and sdr before this */
+ crypto4xx_hw_init(core_dev->dev);
+
+@@ -1352,11 +1349,11 @@ static int crypto4xx_probe(struct platfo
+ return 0;
+
+ err_start_dev:
+- iounmap(core_dev->dev->ce_base);
+-err_iomap:
+ free_irq(core_dev->irq, dev);
+ err_request_irq:
+ irq_dispose_mapping(core_dev->irq);
++ iounmap(core_dev->dev->ce_base);
++err_iomap:
+ tasklet_kill(&core_dev->tasklet);
+ err_build_sdr:
+ crypto4xx_destroy_sdr(core_dev->dev);
diff --git a/target/linux/apm821xx/patches-4.14/120-0002-crypto-crypto4xx-support-Revision-B-parts.patch b/target/linux/apm821xx/patches-4.14/120-0002-crypto-crypto4xx-support-Revision-B-parts.patch
new file mode 100644
index 0000000..1adad96
--- /dev/null
+++ b/target/linux/apm821xx/patches-4.14/120-0002-crypto-crypto4xx-support-Revision-B-parts.patch
@@ -0,0 +1,150 @@
+From 1e932b627e79aa2c70e2c7278e4ac930303faa3f Mon Sep 17 00:00:00 2001
+From: Christian Lamparter <chunkeey@gmail.com>
+Date: Thu, 21 Dec 2017 15:09:18 +0100
+Subject: [PATCH 2/6] crypto: crypto4xx - support Revision B parts
+
+This patch adds support for the crypto4xx RevB cores
+found in the 460EX, 460SX and later cores (like the APM821xx).
+
+Without this patch, the crypto4xx driver will not be
+able to process any offloaded requests and simply hang
+indefinitely.
+
+Signed-off-by: Christian Lamparter <chunkeey@gmail.com>
+---
+ drivers/crypto/amcc/crypto4xx_core.c | 48 +++++++++++++++++++++++++++++----
+ drivers/crypto/amcc/crypto4xx_core.h | 1 +
+ drivers/crypto/amcc/crypto4xx_reg_def.h | 4 ++-
+ 3 files changed, 47 insertions(+), 6 deletions(-)
+
+--- a/drivers/crypto/amcc/crypto4xx_core.c
++++ b/drivers/crypto/amcc/crypto4xx_core.c
+@@ -128,7 +128,14 @@ static void crypto4xx_hw_init(struct cry
+ writel(PPC4XX_INT_DESCR_CNT, dev->ce_base + CRYPTO4XX_INT_DESCR_CNT);
+ writel(PPC4XX_INT_DESCR_CNT, dev->ce_base + CRYPTO4XX_INT_DESCR_CNT);
+ writel(PPC4XX_INT_CFG, dev->ce_base + CRYPTO4XX_INT_CFG);
+- writel(PPC4XX_PD_DONE_INT, dev->ce_base + CRYPTO4XX_INT_EN);
++ if (dev->is_revb) {
++ writel(PPC4XX_INT_TIMEOUT_CNT_REVB << 10,
++ dev->ce_base + CRYPTO4XX_INT_TIMEOUT_CNT);
++ writel(PPC4XX_PD_DONE_INT | PPC4XX_TMO_ERR_INT,
++ dev->ce_base + CRYPTO4XX_INT_EN);
++ } else {
++ writel(PPC4XX_PD_DONE_INT, dev->ce_base + CRYPTO4XX_INT_EN);
++ }
+ }
+
+ int crypto4xx_alloc_sa(struct crypto4xx_ctx *ctx, u32 size)
+@@ -1070,18 +1077,29 @@ static void crypto4xx_bh_tasklet_cb(unsi
+ /**
+ * Top Half of isr.
+ */
+-static irqreturn_t crypto4xx_ce_interrupt_handler(int irq, void *data)
++static inline irqreturn_t crypto4xx_interrupt_handler(int irq, void *data,
++ u32 clr_val)
+ {
+ struct device *dev = (struct device *)data;
+ struct crypto4xx_core_device *core_dev = dev_get_drvdata(dev);
+
+- writel(PPC4XX_INTERRUPT_CLR,
+- core_dev->dev->ce_base + CRYPTO4XX_INT_CLR);
++ writel(clr_val, core_dev->dev->ce_base + CRYPTO4XX_INT_CLR);
+ tasklet_schedule(&core_dev->tasklet);
+
+ return IRQ_HANDLED;
+ }
+
++static irqreturn_t crypto4xx_ce_interrupt_handler(int irq, void *data)
++{
++ return crypto4xx_interrupt_handler(irq, data, PPC4XX_INTERRUPT_CLR);
++}
++
++static irqreturn_t crypto4xx_ce_interrupt_handler_revb(int irq, void *data)
++{
++ return crypto4xx_interrupt_handler(irq, data, PPC4XX_INTERRUPT_CLR |
++ PPC4XX_TMO_ERR_INT);
++}
++
+ /**
+ * Supported Crypto Algorithms
+ */
+@@ -1263,6 +1281,8 @@ static int crypto4xx_probe(struct platfo
+ struct resource res;
+ struct device *dev = &ofdev->dev;
+ struct crypto4xx_core_device *core_dev;
++ u32 pvr;
++ bool is_revb = true;
+
+ rc = of_address_to_resource(ofdev->dev.of_node, 0, &res);
+ if (rc)
+@@ -1279,6 +1299,7 @@ static int crypto4xx_probe(struct platfo
+ mfdcri(SDR0, PPC405EX_SDR0_SRST) | PPC405EX_CE_RESET);
+ mtdcri(SDR0, PPC405EX_SDR0_SRST,
+ mfdcri(SDR0, PPC405EX_SDR0_SRST) & ~PPC405EX_CE_RESET);
++ is_revb = false;
+ } else if (of_find_compatible_node(NULL, NULL,
+ "amcc,ppc460sx-crypto")) {
+ mtdcri(SDR0, PPC460SX_SDR0_SRST,
+@@ -1301,7 +1322,22 @@ static int crypto4xx_probe(struct platfo
+ if (!core_dev->dev)
+ goto err_alloc_dev;
+
++ /*
++ * Older version of 460EX/GT have a hardware bug.
++ * Hence they do not support H/W based security intr coalescing
++ */
++ pvr = mfspr(SPRN_PVR);
++ if (is_revb && ((pvr >> 4) == 0x130218A)) {
++ u32 min = PVR_MIN(pvr);
++
++ if (min < 4) {
++ dev_info(dev, "RevA detected - disable interrupt coalescing\n");
++ is_revb = false;
++ }
++ }
++
+ core_dev->dev->core_dev = core_dev;
++ core_dev->dev->is_revb = is_revb;
+ core_dev->device = dev;
+ spin_lock_init(&core_dev->lock);
+ INIT_LIST_HEAD(&core_dev->dev->alg_list);
+@@ -1331,7 +1367,9 @@ static int crypto4xx_probe(struct platfo
+
+ /* Register for Crypto isr, Crypto Engine IRQ */
+ core_dev->irq = irq_of_parse_and_map(ofdev->dev.of_node, 0);
+- rc = request_irq(core_dev->irq, crypto4xx_ce_interrupt_handler, 0,
++ rc = request_irq(core_dev->irq, is_revb ?
++ crypto4xx_ce_interrupt_handler_revb :
++ crypto4xx_ce_interrupt_handler, 0,
+ core_dev->dev->name, dev);
+ if (rc)
+ goto err_request_irq;
+--- a/drivers/crypto/amcc/crypto4xx_core.h
++++ b/drivers/crypto/amcc/crypto4xx_core.h
+@@ -109,6 +109,7 @@ struct crypto4xx_device {
+ struct list_head alg_list; /* List of algorithm supported
+ by this device */
+ struct ratelimit_state aead_ratelimit;
++ bool is_revb;
+ };
+
+ struct crypto4xx_core_device {
+--- a/drivers/crypto/amcc/crypto4xx_reg_def.h
++++ b/drivers/crypto/amcc/crypto4xx_reg_def.h
+@@ -121,13 +121,15 @@
+ #define PPC4XX_PD_SIZE 6
+ #define PPC4XX_CTX_DONE_INT 0x2000
+ #define PPC4XX_PD_DONE_INT 0x8000
++#define PPC4XX_TMO_ERR_INT 0x40000
+ #define PPC4XX_BYTE_ORDER 0x22222
+ #define PPC4XX_INTERRUPT_CLR 0x3ffff
+ #define PPC4XX_PRNG_CTRL_AUTO_EN 0x3
+ #define PPC4XX_DC_3DES_EN 1
+ #define PPC4XX_TRNG_EN 0x00020000
+-#define PPC4XX_INT_DESCR_CNT 4
++#define PPC4XX_INT_DESCR_CNT 7
+ #define PPC4XX_INT_TIMEOUT_CNT 0
++#define PPC4XX_INT_TIMEOUT_CNT_REVB 0x3FF
+ #define PPC4XX_INT_CFG 1
+ /**
+ * all follow define are ad hoc
diff --git a/target/linux/apm821xx/patches-4.14/120-0003-crypto-crypto4xx-fix-missing-irq-devname.patch b/target/linux/apm821xx/patches-4.14/120-0003-crypto-crypto4xx-fix-missing-irq-devname.patch
new file mode 100644
index 0000000..a295fa4
--- /dev/null
+++ b/target/linux/apm821xx/patches-4.14/120-0003-crypto-crypto4xx-fix-missing-irq-devname.patch
@@ -0,0 +1,37 @@
+From 00179ef6e3c4e5db6258cd6e273e4063b8437d18 Mon Sep 17 00:00:00 2001
+From: Christian Lamparter <chunkeey@gmail.com>
+Date: Thu, 21 Dec 2017 15:10:18 +0100
+Subject: [PATCH 3/6] crypto: crypto4xx - fix missing irq devname
+
+crypto4xx_device's name variable is not set to anything.
+The common devname for request_irq seems to be the module
+name. This will fix the seemingly anonymous interrupt
+entry in /proc/interrupts for crypto4xx.
+
+Signed-off-by: Christian Lamparter <chunkeey@gmail.com>
+---
+ drivers/crypto/amcc/crypto4xx_core.c | 2 +-
+ drivers/crypto/amcc/crypto4xx_core.h | 1 -
+ 2 files changed, 1 insertion(+), 2 deletions(-)
+
+--- a/drivers/crypto/amcc/crypto4xx_core.c
++++ b/drivers/crypto/amcc/crypto4xx_core.c
+@@ -1370,7 +1370,7 @@ static int crypto4xx_probe(struct platfo
+ rc = request_irq(core_dev->irq, is_revb ?
+ crypto4xx_ce_interrupt_handler_revb :
+ crypto4xx_ce_interrupt_handler, 0,
+- core_dev->dev->name, dev);
++ KBUILD_MODNAME, dev);
+ if (rc)
+ goto err_request_irq;
+
+--- a/drivers/crypto/amcc/crypto4xx_core.h
++++ b/drivers/crypto/amcc/crypto4xx_core.h
+@@ -82,7 +82,6 @@ struct pd_uinfo {
+
+ struct crypto4xx_device {
+ struct crypto4xx_core_device *core_dev;
+- char *name;
+ void __iomem *ce_base;
+ void __iomem *trng_base;
+
diff --git a/target/linux/apm821xx/patches-4.14/120-0004-crypto-crypto4xx-kill-MODULE_NAME.patch b/target/linux/apm821xx/patches-4.14/120-0004-crypto-crypto4xx-kill-MODULE_NAME.patch
new file mode 100644
index 0000000..4ee99f4
--- /dev/null
+++ b/target/linux/apm821xx/patches-4.14/120-0004-crypto-crypto4xx-kill-MODULE_NAME.patch
@@ -0,0 +1,47 @@
+From c3621f23fed7d6fff33083ae538004ea59c01d8f Mon Sep 17 00:00:00 2001
+From: Christian Lamparter <chunkeey@gmail.com>
+Date: Thu, 21 Dec 2017 15:11:18 +0100
+Subject: [PATCH 4/6] crypto: crypto4xx - kill MODULE_NAME
+
+KBUILD_MODNAME provides the same value.
+
+Signed-off-by: Christian Lamparter <chunkeey@gmail.com>
+---
+ drivers/crypto/amcc/crypto4xx_core.c | 2 +-
+ drivers/crypto/amcc/crypto4xx_core.h | 2 --
+ drivers/crypto/amcc/crypto4xx_trng.c | 2 +-
+ 3 files changed, 2 insertions(+), 4 deletions(-)
+
+--- a/drivers/crypto/amcc/crypto4xx_core.c
++++ b/drivers/crypto/amcc/crypto4xx_core.c
+@@ -1432,7 +1432,7 @@ MODULE_DEVICE_TABLE(of, crypto4xx_match)
+
+ static struct platform_driver crypto4xx_driver = {
+ .driver = {
+- .name = MODULE_NAME,
++ .name = KBUILD_MODNAME,
+ .of_match_table = crypto4xx_match,
+ },
+ .probe = crypto4xx_probe,
+--- a/drivers/crypto/amcc/crypto4xx_core.h
++++ b/drivers/crypto/amcc/crypto4xx_core.h
+@@ -28,8 +28,6 @@
+ #include "crypto4xx_reg_def.h"
+ #include "crypto4xx_sa.h"
+
+-#define MODULE_NAME "crypto4xx"
+-
+ #define PPC460SX_SDR0_SRST 0x201
+ #define PPC405EX_SDR0_SRST 0x200
+ #define PPC460EX_SDR0_SRST 0x201
+--- a/drivers/crypto/amcc/crypto4xx_trng.c
++++ b/drivers/crypto/amcc/crypto4xx_trng.c
+@@ -92,7 +92,7 @@ void ppc4xx_trng_probe(struct crypto4xx_
+ if (!rng)
+ goto err_out;
+
+- rng->name = MODULE_NAME;
++ rng->name = KBUILD_MODNAME;
+ rng->data_present = ppc4xx_trng_data_present;
+ rng->data_read = ppc4xx_trng_data_read;
+ rng->priv = (unsigned long) dev;
diff --git a/target/linux/apm821xx/patches-4.14/120-0005-crypto-crypto4xx-perform-aead-icv-check-in-the-drive.patch b/target/linux/apm821xx/patches-4.14/120-0005-crypto-crypto4xx-perform-aead-icv-check-in-the-drive.patch
new file mode 100644
index 0000000..0dbd924
--- /dev/null
+++ b/target/linux/apm821xx/patches-4.14/120-0005-crypto-crypto4xx-perform-aead-icv-check-in-the-drive.patch
@@ -0,0 +1,146 @@
+From 5b3856d1d98e6f6a58b70c1c0d7da3fb5f042e9c Mon Sep 17 00:00:00 2001
+From: Christian Lamparter <chunkeey@gmail.com>
+Date: Thu, 21 Dec 2017 16:00:01 +0100
+Subject: [PATCH 5/6] crypto: crypto4xx - perform aead icv check in the driver
+
+The ccm-aes-ppc4xx now fails one of testmgr's expected
+failure test cases as such:
+
+alg: aead: decryption failed on test 10 for ccm-aes-ppc4xx: ret was 0, expected -EBADMSG
+
+Upon closer inspection, it turned out that the hardware's
+crypto flags that would indicate an authentification failure
+are not set by the hardware. The original vendor source from
+which this was ported does not have any special code or notes
+about why this would happen or if there are any WAs.
+
+Hence, this patch converts the aead_done callback handler to
+perform the icv check in the driver. And this fixes the false
+negative and the ccm-aes-ppc4xx passes the selftests once again.
+
+|name : ccm(aes)
+|driver : ccm-aes-ppc4xx
+|module : crypto4xx
+|priority : 300
+|refcnt : 1
+|selftest : passed
+|internal : no
+|type : aead
+|async : yes
+|blocksize : 1
+|ivsize : 16
+|maxauthsize : 16
+|geniv : <none>
+
+Signed-off-by: Christian Lamparter <chunkeey@gmail.com>
+---
+ drivers/crypto/amcc/crypto4xx_alg.c | 6 +---
+ drivers/crypto/amcc/crypto4xx_core.c | 54 ++++++++++++++++++------------------
+ 2 files changed, 28 insertions(+), 32 deletions(-)
+
+--- a/drivers/crypto/amcc/crypto4xx_alg.c
++++ b/drivers/crypto/amcc/crypto4xx_alg.c
+@@ -256,10 +256,6 @@ static inline bool crypto4xx_aead_need_f
+ if (is_ccm && !(req->iv[0] == 1 || req->iv[0] == 3))
+ return true;
+
+- /* CCM - fix CBC MAC mismatch in special case */
+- if (is_ccm && decrypt && !req->assoclen)
+- return true;
+-
+ return false;
+ }
+
+@@ -330,7 +326,7 @@ int crypto4xx_setkey_aes_ccm(struct cryp
+ sa = (struct dynamic_sa_ctl *) ctx->sa_in;
+ sa->sa_contents.w = SA_AES_CCM_CONTENTS | (keylen << 2);
+
+- set_dynamic_sa_command_0(sa, SA_NOT_SAVE_HASH, SA_NOT_SAVE_IV,
++ set_dynamic_sa_command_0(sa, SA_SAVE_HASH, SA_NOT_SAVE_IV,
+ SA_LOAD_HASH_FROM_SA, SA_LOAD_IV_FROM_STATE,
+ SA_NO_HEADER_PROC, SA_HASH_ALG_CBC_MAC,
+ SA_CIPHER_ALG_AES,
+--- a/drivers/crypto/amcc/crypto4xx_core.c
++++ b/drivers/crypto/amcc/crypto4xx_core.c
+@@ -577,15 +577,14 @@ static void crypto4xx_aead_done(struct c
+ struct pd_uinfo *pd_uinfo,
+ struct ce_pd *pd)
+ {
+- struct aead_request *aead_req;
+- struct crypto4xx_ctx *ctx;
++ struct aead_request *aead_req = container_of(pd_uinfo->async_req,
++ struct aead_request, base);
+ struct scatterlist *dst = pd_uinfo->dest_va;
++ size_t cp_len = crypto_aead_authsize(
++ crypto_aead_reqtfm(aead_req));
++ u32 icv[cp_len];
+ int err = 0;
+
+- aead_req = container_of(pd_uinfo->async_req, struct aead_request,
+- base);
+- ctx = crypto_tfm_ctx(aead_req->base.tfm);
+-
+ if (pd_uinfo->using_sd) {
+ crypto4xx_copy_pkt_to_dst(dev, pd, pd_uinfo,
+ pd->pd_ctl_len.bf.pkt_len,
+@@ -597,38 +596,39 @@ static void crypto4xx_aead_done(struct c
+
+ if (pd_uinfo->sa_va->sa_command_0.bf.dir == DIR_OUTBOUND) {
+ /* append icv at the end */
+- size_t cp_len = crypto_aead_authsize(
+- crypto_aead_reqtfm(aead_req));
+- u32 icv[cp_len];
+-
+ crypto4xx_memcpy_from_le32(icv, pd_uinfo->sr_va->save_digest,
+ cp_len);
+
+ scatterwalk_map_and_copy(icv, dst, aead_req->cryptlen,
+ cp_len, 1);
++ } else {
++ /* check icv at the end */
++ scatterwalk_map_and_copy(icv, aead_req->src,
++ aead_req->assoclen + aead_req->cryptlen -
++ cp_len, cp_len, 0);
++
++ crypto4xx_memcpy_from_le32(icv, icv, cp_len);
++
++ if (crypto_memneq(icv, pd_uinfo->sr_va->save_digest, cp_len))
++ err = -EBADMSG;
+ }
+
+ crypto4xx_ret_sg_desc(dev, pd_uinfo);
+
+ if (pd->pd_ctl.bf.status & 0xff) {
+- if (pd->pd_ctl.bf.status & 0x1) {
+- /* authentication error */
+- err = -EBADMSG;
+- } else {
+- if (!__ratelimit(&dev->aead_ratelimit)) {
+- if (pd->pd_ctl.bf.status & 2)
+- pr_err("pad fail error\n");
+- if (pd->pd_ctl.bf.status & 4)
+- pr_err("seqnum fail\n");
+- if (pd->pd_ctl.bf.status & 8)
+- pr_err("error _notify\n");
+- pr_err("aead return err status = 0x%02x\n",
+- pd->pd_ctl.bf.status & 0xff);
+- pr_err("pd pad_ctl = 0x%08x\n",
+- pd->pd_ctl.bf.pd_pad_ctl);
+- }
+- err = -EINVAL;
++ if (!__ratelimit(&dev->aead_ratelimit)) {
++ if (pd->pd_ctl.bf.status & 2)
++ pr_err("pad fail error\n");
++ if (pd->pd_ctl.bf.status & 4)
++ pr_err("seqnum fail\n");
++ if (pd->pd_ctl.bf.status & 8)
++ pr_err("error _notify\n");
++ pr_err("aead return err status = 0x%02x\n",
++ pd->pd_ctl.bf.status & 0xff);
++ pr_err("pd pad_ctl = 0x%08x\n",
++ pd->pd_ctl.bf.pd_pad_ctl);
+ }
++ err = -EINVAL;
+ }
+
+ if (pd_uinfo->state & PD_ENTRY_BUSY)
diff --git a/target/linux/apm821xx/patches-4.14/120-0006-crypto-crypto4xx-performance-optimizations.patch b/target/linux/apm821xx/patches-4.14/120-0006-crypto-crypto4xx-performance-optimizations.patch
new file mode 100644
index 0000000..0475fda
--- /dev/null
+++ b/target/linux/apm821xx/patches-4.14/120-0006-crypto-crypto4xx-performance-optimizations.patch
@@ -0,0 +1,158 @@
+From 30afcbb01a750a1ef0cee8a0861a347912c2e4fb Mon Sep 17 00:00:00 2001
+From: Christian Lamparter <chunkeey@gmail.com>
+Date: Thu, 21 Dec 2017 16:00:01 +0100
+Subject: [PATCH 6/6] 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>
+---
+ 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
+@@ -582,7 +582,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) {
+@@ -597,7 +597,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);
+@@ -607,7 +607,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;
+@@ -1124,8 +1124,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,
+ }
+ }
+ }},
+@@ -1148,8 +1148,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,
+ }
+ }
+ } },
+@@ -1197,8 +1197,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,
+ }
+ }
+ } },
+@@ -1221,8 +1221,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);