diff options
Diffstat (limited to 'target/linux/layerscape/patches-4.14/820-sec-support-layerscape.patch')
-rw-r--r-- | target/linux/layerscape/patches-4.14/820-sec-support-layerscape.patch | 15294 |
1 files changed, 0 insertions, 15294 deletions
diff --git a/target/linux/layerscape/patches-4.14/820-sec-support-layerscape.patch b/target/linux/layerscape/patches-4.14/820-sec-support-layerscape.patch deleted file mode 100644 index 63f6540be0..0000000000 --- a/target/linux/layerscape/patches-4.14/820-sec-support-layerscape.patch +++ /dev/null @@ -1,15294 +0,0 @@ -From ba8e92b322a3763880fdc4d19e9c7085f5504be7 Mon Sep 17 00:00:00 2001 -From: Biwen Li <biwen.li@nxp.com> -Date: Tue, 23 Apr 2019 17:41:43 +0800 -Subject: [PATCH] sec: support layerscape -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -This is an integrated patch of sec for layerscape - -Signed-off-by: Alex Porosanu <alexandru.porosanu@nxp.com> -Signed-off-by: Arnd Bergmann <arnd@arndb.de> -Signed-off-by: Biwen Li <biwen.li@nxp.com> -Signed-off-by: Carmen Iorga <carmen.iorga@nxp.com> -Signed-off-by: Cristian Stoica <cristian.stoica@nxp.com> -Signed-off-by: Guanhua Gao <guanhua.gao@nxp.com> -Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au> -Signed-off-by: Horia Geantă <horia.geanta@nxp.com> -Signed-off-by: Ioana Ciornei <ioana.ciornei@nxp.com> -Signed-off-by: Radu Alexe <radu.alexe@nxp.com> -Signed-off-by: Tudor Ambarus <tudor-dan.ambarus@nxp.com> -Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com> -Signed-off-by: Zhao Qiang <qiang.zhao@nxp.com> ---- - crypto/Kconfig | 20 + - crypto/Makefile | 1 + - crypto/chacha20poly1305.c | 2 - - crypto/tcrypt.c | 27 +- - crypto/testmgr.c | 244 ++ - crypto/testmgr.h | 219 ++ - crypto/tls.c | 607 ++++ - drivers/crypto/Makefile | 2 +- - drivers/crypto/caam/Kconfig | 85 +- - drivers/crypto/caam/Makefile | 26 +- - drivers/crypto/caam/caamalg.c | 468 +++- - drivers/crypto/caam/caamalg_desc.c | 903 +++++- - drivers/crypto/caam/caamalg_desc.h | 52 +- - drivers/crypto/caam/caamalg_qi.c | 1060 ++++++- - drivers/crypto/caam/caamalg_qi2.c | 5843 +++++++++++++++++++++++++++++++++++ - drivers/crypto/caam/caamalg_qi2.h | 276 ++ - drivers/crypto/caam/caamhash.c | 192 +- - drivers/crypto/caam/caamhash_desc.c | 108 + - drivers/crypto/caam/caamhash_desc.h | 49 + - drivers/crypto/caam/caampkc.c | 52 +- - drivers/crypto/caam/caamrng.c | 52 +- - drivers/crypto/caam/compat.h | 4 + - drivers/crypto/caam/ctrl.c | 194 +- - drivers/crypto/caam/desc.h | 89 +- - drivers/crypto/caam/desc_constr.h | 59 +- - drivers/crypto/caam/dpseci.c | 865 ++++++ - drivers/crypto/caam/dpseci.h | 433 +++ - drivers/crypto/caam/dpseci_cmd.h | 287 ++ - drivers/crypto/caam/error.c | 81 +- - drivers/crypto/caam/error.h | 6 +- - drivers/crypto/caam/intern.h | 102 +- - drivers/crypto/caam/jr.c | 84 + - drivers/crypto/caam/jr.h | 2 + - drivers/crypto/caam/key_gen.c | 30 - - drivers/crypto/caam/key_gen.h | 30 + - drivers/crypto/caam/qi.c | 134 +- - drivers/crypto/caam/qi.h | 2 +- - drivers/crypto/caam/regs.h | 76 +- - drivers/crypto/caam/sg_sw_qm.h | 46 +- - drivers/crypto/talitos.c | 8 + - include/crypto/chacha20.h | 1 + - 41 files changed, 12088 insertions(+), 733 deletions(-) - create mode 100644 crypto/tls.c - create mode 100644 drivers/crypto/caam/caamalg_qi2.c - create mode 100644 drivers/crypto/caam/caamalg_qi2.h - create mode 100644 drivers/crypto/caam/caamhash_desc.c - create mode 100644 drivers/crypto/caam/caamhash_desc.h - create mode 100644 drivers/crypto/caam/dpseci.c - create mode 100644 drivers/crypto/caam/dpseci.h - create mode 100644 drivers/crypto/caam/dpseci_cmd.h - ---- a/crypto/Kconfig -+++ b/crypto/Kconfig -@@ -312,6 +312,26 @@ config CRYPTO_ECHAINIV - a sequence number xored with a salt. This is the default - algorithm for CBC. - -+config CRYPTO_TLS -+ tristate "TLS support" -+ select CRYPTO_AEAD -+ select CRYPTO_BLKCIPHER -+ select CRYPTO_MANAGER -+ select CRYPTO_HASH -+ select CRYPTO_NULL -+ select CRYPTO_AUTHENC -+ help -+ Support for TLS 1.0 record encryption and decryption -+ -+ This module adds support for encryption/decryption of TLS 1.0 frames -+ using blockcipher algorithms. The name of the resulting algorithm is -+ "tls10(hmac(<digest>),cbc(<cipher>))". By default, the generic base -+ algorithms are used (e.g. aes-generic, sha1-generic), but hardware -+ accelerated versions will be used automatically if available. -+ -+ User-space applications (OpenSSL, GnuTLS) can offload TLS 1.0 -+ operations through AF_ALG or cryptodev interfaces -+ - comment "Block modes" - - config CRYPTO_CBC ---- a/crypto/Makefile -+++ b/crypto/Makefile -@@ -118,6 +118,7 @@ obj-$(CONFIG_CRYPTO_CRC32C) += crc32c_ge - obj-$(CONFIG_CRYPTO_CRC32) += crc32_generic.o - obj-$(CONFIG_CRYPTO_CRCT10DIF) += crct10dif_common.o crct10dif_generic.o - obj-$(CONFIG_CRYPTO_AUTHENC) += authenc.o authencesn.o -+obj-$(CONFIG_CRYPTO_TLS) += tls.o - obj-$(CONFIG_CRYPTO_LZO) += lzo.o - obj-$(CONFIG_CRYPTO_LZ4) += lz4.o - obj-$(CONFIG_CRYPTO_LZ4HC) += lz4hc.o ---- a/crypto/chacha20poly1305.c -+++ b/crypto/chacha20poly1305.c -@@ -22,8 +22,6 @@ - - #include "internal.h" - --#define CHACHAPOLY_IV_SIZE 12 -- - struct chachapoly_instance_ctx { - struct crypto_skcipher_spawn chacha; - struct crypto_ahash_spawn poly; ---- a/crypto/tcrypt.c -+++ b/crypto/tcrypt.c -@@ -76,7 +76,7 @@ static char *check[] = { - "khazad", "wp512", "wp384", "wp256", "tnepres", "xeta", "fcrypt", - "camellia", "seed", "salsa20", "rmd128", "rmd160", "rmd256", "rmd320", - "lzo", "cts", "zlib", "sha3-224", "sha3-256", "sha3-384", "sha3-512", -- NULL -+ "rsa", NULL - }; - - struct tcrypt_result { -@@ -355,11 +355,13 @@ static void test_aead_speed(const char * - iv); - aead_request_set_ad(req, aad_size); - -- if (secs) -+ if (secs) { - ret = test_aead_jiffies(req, enc, *b_size, - secs); -- else -+ cond_resched(); -+ } else { - ret = test_aead_cycles(req, enc, *b_size); -+ } - - if (ret) { - pr_err("%s() failed return code=%d\n", e, ret); -@@ -736,12 +738,14 @@ static void test_ahash_speed_common(cons - - ahash_request_set_crypt(req, sg, output, speed[i].plen); - -- if (secs) -+ if (secs) { - ret = test_ahash_jiffies(req, speed[i].blen, - speed[i].plen, output, secs); -- else -+ cond_resched(); -+ } else { - ret = test_ahash_cycles(req, speed[i].blen, - speed[i].plen, output); -+ } - - if (ret) { - pr_err("hashing failed ret=%d\n", ret); -@@ -959,12 +963,14 @@ static void test_skcipher_speed(const ch - - skcipher_request_set_crypt(req, sg, sg, *b_size, iv); - -- if (secs) -+ if (secs) { - ret = test_acipher_jiffies(req, enc, - *b_size, secs); -- else -+ cond_resched(); -+ } else { - ret = test_acipher_cycles(req, enc, - *b_size); -+ } - - if (ret) { - pr_err("%s() failed flags=%x\n", e, -@@ -1336,6 +1342,10 @@ static int do_test(const char *alg, u32 - ret += tcrypt_test("hmac(sha3-512)"); - break; - -+ case 115: -+ ret += tcrypt_test("rsa"); -+ break; -+ - case 150: - ret += tcrypt_test("ansi_cprng"); - break; -@@ -1397,6 +1407,9 @@ static int do_test(const char *alg, u32 - case 190: - ret += tcrypt_test("authenc(hmac(sha512),cbc(des3_ede))"); - break; -+ case 191: -+ ret += tcrypt_test("tls10(hmac(sha1),cbc(aes))"); -+ break; - case 200: - test_cipher_speed("ecb(aes)", ENCRYPT, sec, NULL, 0, - speed_template_16_24_32); ---- a/crypto/testmgr.c -+++ b/crypto/testmgr.c -@@ -117,6 +117,13 @@ struct drbg_test_suite { - unsigned int count; - }; - -+struct tls_test_suite { -+ struct { -+ struct tls_testvec *vecs; -+ unsigned int count; -+ } enc, dec; -+}; -+ - struct akcipher_test_suite { - const struct akcipher_testvec *vecs; - unsigned int count; -@@ -140,6 +147,7 @@ struct alg_test_desc { - struct hash_test_suite hash; - struct cprng_test_suite cprng; - struct drbg_test_suite drbg; -+ struct tls_test_suite tls; - struct akcipher_test_suite akcipher; - struct kpp_test_suite kpp; - } suite; -@@ -991,6 +999,233 @@ static int test_aead(struct crypto_aead - return 0; - } - -+static int __test_tls(struct crypto_aead *tfm, int enc, -+ struct tls_testvec *template, unsigned int tcount, -+ const bool diff_dst) -+{ -+ const char *algo = crypto_tfm_alg_driver_name(crypto_aead_tfm(tfm)); -+ unsigned int i, k, authsize; -+ char *q; -+ struct aead_request *req; -+ struct scatterlist *sg; -+ struct scatterlist *sgout; -+ const char *e, *d; -+ struct tcrypt_result result; -+ void *input; -+ void *output; -+ void *assoc; -+ char *iv; -+ char *key; -+ char *xbuf[XBUFSIZE]; -+ char *xoutbuf[XBUFSIZE]; -+ char *axbuf[XBUFSIZE]; -+ int ret = -ENOMEM; -+ -+ if (testmgr_alloc_buf(xbuf)) -+ goto out_noxbuf; -+ -+ if (diff_dst && testmgr_alloc_buf(xoutbuf)) -+ goto out_nooutbuf; -+ -+ if (testmgr_alloc_buf(axbuf)) -+ goto out_noaxbuf; -+ -+ iv = kzalloc(MAX_IVLEN, GFP_KERNEL); -+ if (!iv) -+ goto out_noiv; -+ -+ key = kzalloc(MAX_KEYLEN, GFP_KERNEL); -+ if (!key) -+ goto out_nokey; -+ -+ sg = kmalloc(sizeof(*sg) * 8 * (diff_dst ? 2 : 1), GFP_KERNEL); -+ if (!sg) -+ goto out_nosg; -+ -+ sgout = sg + 8; -+ -+ d = diff_dst ? "-ddst" : ""; -+ e = enc ? "encryption" : "decryption"; -+ -+ init_completion(&result.completion); -+ -+ req = aead_request_alloc(tfm, GFP_KERNEL); -+ if (!req) { -+ pr_err("alg: tls%s: Failed to allocate request for %s\n", -+ d, algo); -+ goto out; -+ } -+ -+ aead_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG, -+ tcrypt_complete, &result); -+ -+ for (i = 0; i < tcount; i++) { -+ input = xbuf[0]; -+ assoc = axbuf[0]; -+ -+ ret = -EINVAL; -+ if (WARN_ON(template[i].ilen > PAGE_SIZE || -+ template[i].alen > PAGE_SIZE)) -+ goto out; -+ -+ memcpy(assoc, template[i].assoc, template[i].alen); -+ memcpy(input, template[i].input, template[i].ilen); -+ -+ if (template[i].iv) -+ memcpy(iv, template[i].iv, MAX_IVLEN); -+ else -+ memset(iv, 0, MAX_IVLEN); -+ -+ crypto_aead_clear_flags(tfm, ~0); -+ -+ if (template[i].klen > MAX_KEYLEN) { -+ pr_err("alg: aead%s: setkey failed on test %d for %s: key size %d > %d\n", -+ d, i, algo, template[i].klen, MAX_KEYLEN); -+ ret = -EINVAL; -+ goto out; -+ } -+ memcpy(key, template[i].key, template[i].klen); -+ -+ ret = crypto_aead_setkey(tfm, key, template[i].klen); -+ if (!ret == template[i].fail) { -+ pr_err("alg: tls%s: setkey failed on test %d for %s: flags=%x\n", -+ d, i, algo, crypto_aead_get_flags(tfm)); -+ goto out; -+ } else if (ret) -+ continue; -+ -+ authsize = 20; -+ ret = crypto_aead_setauthsize(tfm, authsize); -+ if (ret) { -+ pr_err("alg: aead%s: Failed to set authsize to %u on test %d for %s\n", -+ d, authsize, i, algo); -+ goto out; -+ } -+ -+ k = !!template[i].alen; -+ sg_init_table(sg, k + 1); -+ sg_set_buf(&sg[0], assoc, template[i].alen); -+ sg_set_buf(&sg[k], input, (enc ? template[i].rlen : -+ template[i].ilen)); -+ output = input; -+ -+ if (diff_dst) { -+ sg_init_table(sgout, k + 1); -+ sg_set_buf(&sgout[0], assoc, template[i].alen); -+ -+ output = xoutbuf[0]; -+ sg_set_buf(&sgout[k], output, -+ (enc ? template[i].rlen : template[i].ilen)); -+ } -+ -+ aead_request_set_crypt(req, sg, (diff_dst) ? sgout : sg, -+ template[i].ilen, iv); -+ -+ aead_request_set_ad(req, template[i].alen); -+ -+ ret = enc ? crypto_aead_encrypt(req) : crypto_aead_decrypt(req); -+ -+ switch (ret) { -+ case 0: -+ if (template[i].novrfy) { -+ /* verification was supposed to fail */ -+ pr_err("alg: tls%s: %s failed on test %d for %s: ret was 0, expected -EBADMSG\n", -+ d, e, i, algo); -+ /* so really, we got a bad message */ -+ ret = -EBADMSG; -+ goto out; -+ } -+ break; -+ case -EINPROGRESS: -+ case -EBUSY: -+ wait_for_completion(&result.completion); -+ reinit_completion(&result.completion); -+ ret = result.err; -+ if (!ret) -+ break; -+ case -EBADMSG: -+ /* verification failure was expected */ -+ if (template[i].novrfy) -+ continue; -+ /* fall through */ -+ default: -+ pr_err("alg: tls%s: %s failed on test %d for %s: ret=%d\n", -+ d, e, i, algo, -ret); -+ goto out; -+ } -+ -+ q = output; -+ if (memcmp(q, template[i].result, template[i].rlen)) { -+ pr_err("alg: tls%s: Test %d failed on %s for %s\n", -+ d, i, e, algo); -+ hexdump(q, template[i].rlen); -+ pr_err("should be:\n"); -+ hexdump(template[i].result, template[i].rlen); -+ ret = -EINVAL; -+ goto out; -+ } -+ } -+ -+out: -+ aead_request_free(req); -+ -+ kfree(sg); -+out_nosg: -+ kfree(key); -+out_nokey: -+ kfree(iv); -+out_noiv: -+ testmgr_free_buf(axbuf); -+out_noaxbuf: -+ if (diff_dst) -+ testmgr_free_buf(xoutbuf); -+out_nooutbuf: -+ testmgr_free_buf(xbuf); -+out_noxbuf: -+ return ret; -+} -+ -+static int test_tls(struct crypto_aead *tfm, int enc, -+ struct tls_testvec *template, unsigned int tcount) -+{ -+ int ret; -+ /* test 'dst == src' case */ -+ ret = __test_tls(tfm, enc, template, tcount, false); -+ if (ret) -+ return ret; -+ /* test 'dst != src' case */ -+ return __test_tls(tfm, enc, template, tcount, true); -+} -+ -+static int alg_test_tls(const struct alg_test_desc *desc, const char *driver, -+ u32 type, u32 mask) -+{ -+ struct crypto_aead *tfm; -+ int err = 0; -+ -+ tfm = crypto_alloc_aead(driver, type, mask); -+ if (IS_ERR(tfm)) { -+ pr_err("alg: aead: Failed to load transform for %s: %ld\n", -+ driver, PTR_ERR(tfm)); -+ return PTR_ERR(tfm); -+ } -+ -+ if (desc->suite.tls.enc.vecs) { -+ err = test_tls(tfm, ENCRYPT, desc->suite.tls.enc.vecs, -+ desc->suite.tls.enc.count); -+ if (err) -+ goto out; -+ } -+ -+ if (!err && desc->suite.tls.dec.vecs) -+ err = test_tls(tfm, DECRYPT, desc->suite.tls.dec.vecs, -+ desc->suite.tls.dec.count); -+ -+out: -+ crypto_free_aead(tfm); -+ return err; -+} -+ - static int test_cipher(struct crypto_cipher *tfm, int enc, - const struct cipher_testvec *template, - unsigned int tcount) -@@ -3524,6 +3759,15 @@ static const struct alg_test_desc alg_te - .hash = __VECS(tgr192_tv_template) - } - }, { -+ .alg = "tls10(hmac(sha1),cbc(aes))", -+ .test = alg_test_tls, -+ .suite = { -+ .tls = { -+ .enc = __VECS(tls_enc_tv_template), -+ .dec = __VECS(tls_dec_tv_template) -+ } -+ } -+ }, { - .alg = "vmac(aes)", - .test = alg_test_hash, - .suite = { ---- a/crypto/testmgr.h -+++ b/crypto/testmgr.h -@@ -125,6 +125,20 @@ struct drbg_testvec { - size_t expectedlen; - }; - -+struct tls_testvec { -+ char *key; /* wrapped keys for encryption and authentication */ -+ char *iv; /* initialization vector */ -+ char *input; /* input data */ -+ char *assoc; /* associated data: seq num, type, version, input len */ -+ char *result; /* result data */ -+ unsigned char fail; /* the test failure is expected */ -+ unsigned char novrfy; /* dec verification failure expected */ -+ unsigned char klen; /* key length */ -+ unsigned short ilen; /* input data length */ -+ unsigned short alen; /* associated data length */ -+ unsigned short rlen; /* result length */ -+}; -+ - struct akcipher_testvec { - const unsigned char *key; - const unsigned char *m; -@@ -153,6 +167,211 @@ struct kpp_testvec { - static const char zeroed_string[48]; - - /* -+ * TLS1.0 synthetic test vectors -+ */ -+static struct tls_testvec tls_enc_tv_template[] = { -+ { -+#ifdef __LITTLE_ENDIAN -+ .key = "\x08\x00" /* rta length */ -+ "\x01\x00" /* rta type */ -+#else -+ .key = "\x00\x08" /* rta length */ -+ "\x00\x01" /* rta type */ -+#endif -+ "\x00\x00\x00\x10" /* enc key length */ -+ "authenticationkey20benckeyis16_bytes", -+ .klen = 8 + 20 + 16, -+ .iv = "iv0123456789abcd", -+ .input = "Single block msg", -+ .ilen = 16, -+ .assoc = "\x00\x01\x02\x03\x04\x05\x06\x07" -+ "\x00\x03\x01\x00\x10", -+ .alen = 13, -+ .result = "\xd5\xac\xb\xd2\xac\xad\x3f\xb1" -+ "\x59\x79\x1e\x91\x5f\x52\x14\x9c" -+ "\xc0\x75\xd8\x4c\x97\x0f\x07\x73" -+ "\xdc\x89\x47\x49\x49\xcb\x30\x6b" -+ "\x1b\x45\x23\xa1\xd0\x51\xcf\x02" -+ "\x2e\xa8\x5d\xa0\xfe\xca\x82\x61", -+ .rlen = 16 + 20 + 12, -+ }, { -+#ifdef __LITTLE_ENDIAN -+ .key = "\x08\x00" /* rta length */ -+ "\x01\x00" /* rta type */ -+#else -+ .key = "\x00\x08" /* rta length */ -+ "\x00\x01" /* rta type */ -+#endif -+ "\x00\x00\x00\x10" /* enc key length */ -+ "authenticationkey20benckeyis16_bytes", -+ .klen = 8 + 20 + 16, -+ .iv = "iv0123456789abcd", -+ .input = "", -+ .ilen = 0, -+ .assoc = "\x00\x01\x02\x03\x04\x05\x06\x07" -+ "\x00\x03\x01\x00\x00", -+ .alen = 13, -+ .result = "\x58\x2a\x11\xc\x86\x8e\x4b\x67" -+ "\x2d\x16\x26\x1a\xac\x4b\xe2\x1a" -+ "\xe9\x6a\xcc\x4d\x6f\x79\x8a\x45" -+ "\x1f\x4e\x27\xf2\xa7\x59\xb4\x5a", -+ .rlen = 20 + 12, -+ }, { -+#ifdef __LITTLE_ENDIAN -+ .key = "\x08\x00" /* rta length */ -+ "\x01\x00" /* rta type */ -+#else -+ .key = "\x00\x08" /* rta length */ -+ "\x00\x01" /* rta type */ -+#endif -+ "\x00\x00\x00\x10" /* enc key length */ -+ "authenticationkey20benckeyis16_bytes", -+ .klen = 8 + 20 + 16, -+ .iv = "iv0123456789abcd", -+ .input = "285 bytes plaintext285 bytes plaintext285 bytes" -+ " plaintext285 bytes plaintext285 bytes plaintext285" -+ " bytes plaintext285 bytes plaintext285 bytes" -+ " plaintext285 bytes plaintext285 bytes plaintext285" -+ " bytes plaintext285 bytes plaintext285 bytes" -+ " plaintext285 bytes plaintext285 bytes plaintext285" -+ " bytes plaintext285 bytes plaintext", -+ .ilen = 285, -+ .assoc = "\x00\x01\x02\x03\x04\x05\x06\x07" -+ "\x00\x03\x01\x01\x1d", -+ .alen = 13, -+ .result = "\x80\x23\x82\x44\x14\x2a\x1d\x94\xc\xc2\x1d\xd" -+ "\x3a\x32\x89\x4c\x57\x30\xa8\x89\x76\x46\xcc\x90" -+ "\x1d\x88\xb8\xa6\x1a\x58\xe\x2d\xeb\x2c\xc7\x3a" -+ "\x52\x4e\xdb\xb3\x1e\x83\x11\xf5\x3c\xce\x6e\x94" -+ "\xd3\x26\x6a\x9a\xd\xbd\xc7\x98\xb9\xb3\x3a\x51" -+ "\x1e\x4\x84\x8a\x8f\x54\x9a\x51\x69\x9c\xce\x31" -+ "\x8d\x5d\x8b\xee\x5f\x70\xc\xc9\xb8\x50\x54\xf8" -+ "\xb2\x4a\x7a\xcd\xeb\x7a\x82\x81\xc6\x41\xc8\x50" -+ "\x91\x8d\xc8\xed\xcd\x40\x8f\x55\xd1\xec\xc9\xac" -+ "\x15\x18\xf9\x20\xa0\xed\x18\xa1\xe3\x56\xe3\x14" -+ "\xe5\xe8\x66\x63\x20\xed\xe4\x62\x9d\xa3\xa4\x1d" -+ "\x81\x89\x18\xf2\x36\xae\xc8\x8a\x2b\xbc\xc3\xb8" -+ "\x80\xf\x97\x21\x36\x39\x8\x84\x23\x18\x9e\x9c" -+ "\x72\x32\x75\x2d\x2e\xf9\x60\xb\xe8\xcc\xd9\x74" -+ "\x4\x1b\x8e\x99\xc1\x94\xee\xd0\xac\x4e\xfc\x7e" -+ "\xf1\x96\xb3\xe7\x14\xb8\xf2\xc\x25\x97\x82\x6b" -+ "\xbd\x0\x65\xab\x5c\xe3\x16\xfb\x68\xef\xea\x9d" -+ "\xff\x44\x1d\x2a\x44\xf5\xc8\x56\x77\xb7\xbf\x13" -+ "\xc8\x54\xdb\x92\xfe\x16\x4c\xbe\x18\xe9\xb\x8d" -+ "\xb\xd4\x43\x58\x43\xaa\xf4\x3\x80\x97\x62\xd5" -+ "\xdf\x3c\x28\xaa\xee\x48\x4b\x55\x41\x1b\x31\x2" -+ "\xbe\xa0\x1c\xbd\xb7\x22\x2a\xe5\x53\x72\x73\x20" -+ "\x44\x4f\xe6\x1\x2b\x34\x33\x11\x7d\xfb\x10\xc1" -+ "\x66\x7c\xa6\xf4\x48\x36\x5e\x2\xda\x41\x4b\x3e" -+ "\xe7\x80\x17\x17\xce\xf1\x3e\x6a\x8e\x26\xf3\xb7" -+ "\x2b\x85\xd\x31\x8d\xba\x6c\x22\xb4\x28\x55\x7e" -+ "\x2a\x9e\x26\xf1\x3d\x21\xac\x65", -+ .rlen = 285 + 20 + 15, -+ } -+}; -+ -+static struct tls_testvec tls_dec_tv_template[] = { -+ { -+#ifdef __LITTLE_ENDIAN -+ .key = "\x08\x00" /* rta length */ -+ "\x01\x00" /* rta type */ -+#else -+ .key = "\x00\x08" /* rta length */ -+ "\x00\x01" /* rta type */ -+#endif -+ "\x00\x00\x00\x10" /* enc key length */ -+ "authenticationkey20benckeyis16_bytes", -+ .klen = 8 + 20 + 16, -+ .iv = "iv0123456789abcd", -+ .input = "\xd5\xac\xb\xd2\xac\xad\x3f\xb1" -+ "\x59\x79\x1e\x91\x5f\x52\x14\x9c" -+ "\xc0\x75\xd8\x4c\x97\x0f\x07\x73" -+ "\xdc\x89\x47\x49\x49\xcb\x30\x6b" -+ "\x1b\x45\x23\xa1\xd0\x51\xcf\x02" -+ "\x2e\xa8\x5d\xa0\xfe\xca\x82\x61", -+ .ilen = 16 + 20 + 12, -+ .assoc = "\x00\x01\x02\x03\x04\x05\x06\x07" -+ "\x00\x03\x01\x00\x30", -+ .alen = 13, -+ .result = "Single block msg", -+ .rlen = 16, -+ }, { -+#ifdef __LITTLE_ENDIAN -+ .key = "\x08\x00" /* rta length */ -+ "\x01\x00" /* rta type */ -+#else -+ .key = "\x00\x08" /* rta length */ -+ "\x00\x01" /* rta type */ -+#endif -+ "\x00\x00\x00\x10" /* enc key length */ -+ "authenticationkey20benckeyis16_bytes", -+ .klen = 8 + 20 + 16, -+ .iv = "iv0123456789abcd", -+ .input = "\x58\x2a\x11\xc\x86\x8e\x4b\x67" -+ "\x2d\x16\x26\x1a\xac\x4b\xe2\x1a" -+ "\xe9\x6a\xcc\x4d\x6f\x79\x8a\x45" -+ "\x1f\x4e\x27\xf2\xa7\x59\xb4\x5a", -+ .ilen = 20 + 12, -+ .assoc = "\x00\x01\x02\x03\x04\x05\x06\x07" -+ "\x00\x03\x01\x00\x20", -+ .alen = 13, -+ .result = "", -+ .rlen = 0, -+ }, { -+#ifdef __LITTLE_ENDIAN -+ .key = "\x08\x00" /* rta length */ -+ "\x01\x00" /* rta type */ -+#else -+ .key = "\x00\x08" /* rta length */ -+ "\x00\x01" /* rta type */ -+#endif -+ "\x00\x00\x00\x10" /* enc key length */ -+ "authenticationkey20benckeyis16_bytes", -+ .klen = 8 + 20 + 16, -+ .iv = "iv0123456789abcd", -+ .input = "\x80\x23\x82\x44\x14\x2a\x1d\x94\xc\xc2\x1d\xd" -+ "\x3a\x32\x89\x4c\x57\x30\xa8\x89\x76\x46\xcc\x90" -+ "\x1d\x88\xb8\xa6\x1a\x58\xe\x2d\xeb\x2c\xc7\x3a" -+ "\x52\x4e\xdb\xb3\x1e\x83\x11\xf5\x3c\xce\x6e\x94" -+ "\xd3\x26\x6a\x9a\xd\xbd\xc7\x98\xb9\xb3\x3a\x51" -+ "\x1e\x4\x84\x8a\x8f\x54\x9a\x51\x69\x9c\xce\x31" -+ "\x8d\x5d\x8b\xee\x5f\x70\xc\xc9\xb8\x50\x54\xf8" -+ "\xb2\x4a\x7a\xcd\xeb\x7a\x82\x81\xc6\x41\xc8\x50" -+ "\x91\x8d\xc8\xed\xcd\x40\x8f\x55\xd1\xec\xc9\xac" -+ "\x15\x18\xf9\x20\xa0\xed\x18\xa1\xe3\x56\xe3\x14" -+ "\xe5\xe8\x66\x63\x20\xed\xe4\x62\x9d\xa3\xa4\x1d" -+ "\x81\x89\x18\xf2\x36\xae\xc8\x8a\x2b\xbc\xc3\xb8" -+ "\x80\xf\x97\x21\x36\x39\x8\x84\x23\x18\x9e\x9c" -+ "\x72\x32\x75\x2d\x2e\xf9\x60\xb\xe8\xcc\xd9\x74" -+ "\x4\x1b\x8e\x99\xc1\x94\xee\xd0\xac\x4e\xfc\x7e" -+ "\xf1\x96\xb3\xe7\x14\xb8\xf2\xc\x25\x97\x82\x6b" -+ "\xbd\x0\x65\xab\x5c\xe3\x16\xfb\x68\xef\xea\x9d" -+ "\xff\x44\x1d\x2a\x44\xf5\xc8\x56\x77\xb7\xbf\x13" -+ "\xc8\x54\xdb\x92\xfe\x16\x4c\xbe\x18\xe9\xb\x8d" -+ "\xb\xd4\x43\x58\x43\xaa\xf4\x3\x80\x97\x62\xd5" -+ "\xdf\x3c\x28\xaa\xee\x48\x4b\x55\x41\x1b\x31\x2" -+ "\xbe\xa0\x1c\xbd\xb7\x22\x2a\xe5\x53\x72\x73\x20" -+ "\x44\x4f\xe6\x1\x2b\x34\x33\x11\x7d\xfb\x10\xc1" -+ "\x66\x7c\xa6\xf4\x48\x36\x5e\x2\xda\x41\x4b\x3e" -+ "\xe7\x80\x17\x17\xce\xf1\x3e\x6a\x8e\x26\xf3\xb7" -+ "\x2b\x85\xd\x31\x8d\xba\x6c\x22\xb4\x28\x55\x7e" -+ "\x2a\x9e\x26\xf1\x3d\x21\xac\x65", -+ -+ .ilen = 285 + 20 + 15, -+ .assoc = "\x00\x01\x02\x03\x04\x05\x06\x07" -+ "\x00\x03\x01\x01\x40", -+ .alen = 13, -+ .result = "285 bytes plaintext285 bytes plaintext285 bytes" -+ " plaintext285 bytes plaintext285 bytes plaintext285" -+ " bytes plaintext285 bytes plaintext285 bytes" -+ " plaintext285 bytes plaintext285 bytes plaintext285" -+ " bytes plaintext285 bytes plaintext285 bytes" -+ " plaintext285 bytes plaintext285 bytes plaintext", -+ .rlen = 285, -+ } -+}; -+ -+/* - * RSA test vectors. Borrowed from openSSL. - */ - static const struct akcipher_testvec rsa_tv_template[] = { ---- /dev/null -+++ b/crypto/tls.c -@@ -0,0 +1,607 @@ -+/* -+ * Copyright 2013 Freescale Semiconductor, Inc. -+ * Copyright 2017 NXP Semiconductor, Inc. -+ * -+ * 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. -+ * -+ */ -+ -+#include <crypto/internal/aead.h> -+#include <crypto/internal/hash.h> -+#include <crypto/internal/skcipher.h> -+#include <crypto/authenc.h> -+#include <crypto/null.h> -+#include <crypto/scatterwalk.h> -+#include <linux/err.h> -+#include <linux/init.h> -+#include <linux/module.h> -+#include <linux/rtnetlink.h> -+ -+struct tls_instance_ctx { -+ struct crypto_ahash_spawn auth; -+ struct crypto_skcipher_spawn enc; -+}; -+ -+struct crypto_tls_ctx { -+ unsigned int reqoff; -+ struct crypto_ahash *auth; -+ struct crypto_skcipher *enc; -+ struct crypto_skcipher *null; -+}; -+ -+struct tls_request_ctx { -+ /* -+ * cryptlen holds the payload length in the case of encryption or -+ * payload_len + icv_len + padding_len in case of decryption -+ */ -+ unsigned int cryptlen; -+ /* working space for partial results */ -+ struct scatterlist tmp[2]; -+ struct scatterlist cipher[2]; -+ struct scatterlist dst[2]; -+ char tail[]; -+}; -+ -+struct async_op { -+ struct completion completion; -+ int err; -+}; -+ -+static void tls_async_op_done(struct crypto_async_request *req, int err) -+{ -+ struct async_op *areq = req->data; -+ -+ if (err == -EINPROGRESS) -+ return; -+ -+ areq->err = err; -+ complete(&areq->completion); -+} -+ -+static int crypto_tls_setkey(struct crypto_aead *tls, const u8 *key, -+ unsigned int keylen) -+{ -+ struct crypto_tls_ctx *ctx = crypto_aead_ctx(tls); -+ struct crypto_ahash *auth = ctx->auth; -+ struct crypto_skcipher *enc = ctx->enc; -+ struct crypto_authenc_keys keys; -+ int err = -EINVAL; -+ -+ if (crypto_authenc_extractkeys(&keys, key, keylen) != 0) -+ goto badkey; -+ -+ crypto_ahash_clear_flags(auth, CRYPTO_TFM_REQ_MASK); -+ crypto_ahash_set_flags(auth, crypto_aead_get_flags(tls) & -+ CRYPTO_TFM_REQ_MASK); -+ err = crypto_ahash_setkey(auth, keys.authkey, keys.authkeylen); -+ crypto_aead_set_flags(tls, crypto_ahash_get_flags(auth) & -+ CRYPTO_TFM_RES_MASK); -+ -+ if (err) -+ goto out; -+ -+ crypto_skcipher_clear_flags(enc, CRYPTO_TFM_REQ_MASK); -+ crypto_skcipher_set_flags(enc, crypto_aead_get_flags(tls) & -+ CRYPTO_TFM_REQ_MASK); -+ err = crypto_skcipher_setkey(enc, keys.enckey, keys.enckeylen); -+ crypto_aead_set_flags(tls, crypto_skcipher_get_flags(enc) & -+ CRYPTO_TFM_RES_MASK); -+ -+out: -+ return err; -+ -+badkey: -+ crypto_aead_set_flags(tls, CRYPTO_TFM_RES_BAD_KEY_LEN); -+ goto out; -+} -+ -+/** -+ * crypto_tls_genicv - Calculate hmac digest for a TLS record -+ * @hash: (output) buffer to save the digest into -+ * @src: (input) scatterlist with the assoc and payload data -+ * @srclen: (input) size of the source buffer (assoclen + cryptlen) -+ * @req: (input) aead request -+ **/ -+static int crypto_tls_genicv(u8 *hash, struct scatterlist *src, -+ unsigned int srclen, struct aead_request *req) -+{ -+ struct crypto_aead *tls = crypto_aead_reqtfm(req); -+ struct crypto_tls_ctx *ctx = crypto_aead_ctx(tls); -+ struct tls_request_ctx *treq_ctx = aead_request_ctx(req); -+ struct async_op ahash_op; -+ struct ahash_request *ahreq = (void *)(treq_ctx->tail + ctx->reqoff); -+ unsigned int flags = CRYPTO_TFM_REQ_MAY_SLEEP; -+ int err = -EBADMSG; -+ -+ /* Bail out if the request assoc len is 0 */ -+ if (!req->assoclen) -+ return err; -+ -+ init_completion(&ahash_op.completion); -+ -+ /* the hash transform to be executed comes from the original request */ -+ ahash_request_set_tfm(ahreq, ctx->auth); -+ /* prepare the hash request with input data and result pointer */ -+ ahash_request_set_crypt(ahreq, src, hash, srclen); -+ /* set the notifier for when the async hash function returns */ -+ ahash_request_set_callback(ahreq, aead_request_flags(req) & flags, -+ tls_async_op_done, &ahash_op); -+ -+ /* Calculate the digest on the given data. The result is put in hash */ -+ err = crypto_ahash_digest(ahreq); -+ if (err == -EINPROGRESS) { -+ err = wait_for_completion_interruptible(&ahash_op.completion); -+ if (!err) -+ err = ahash_op.err; -+ } -+ -+ return err; -+} -+ -+/** -+ * crypto_tls_gen_padicv - Calculate and pad hmac digest for a TLS record -+ * @hash: (output) buffer to save the digest and padding into -+ * @phashlen: (output) the size of digest + padding -+ * @req: (input) aead request -+ **/ -+static int crypto_tls_gen_padicv(u8 *hash, unsigned int *phashlen, -+ struct aead_request *req) -+{ -+ struct crypto_aead *tls = crypto_aead_reqtfm(req); -+ unsigned int hash_size = crypto_aead_authsize(tls); -+ unsigned int block_size = crypto_aead_blocksize(tls); -+ unsigned int srclen = req->cryptlen + hash_size; -+ unsigned int icvlen = req->cryptlen + req->assoclen; -+ unsigned int padlen; -+ int err; -+ -+ err = crypto_tls_genicv(hash, req->src, icvlen, req); -+ if (err) -+ goto out; -+ -+ /* add padding after digest */ -+ padlen = block_size - (srclen % block_size); -+ memset(hash + hash_size, padlen - 1, padlen); -+ -+ *phashlen = hash_size + padlen; -+out: -+ return err; -+} -+ -+static int crypto_tls_copy_data(struct aead_request *req, -+ struct scatterlist *src, -+ struct scatterlist *dst, -+ unsigned int len) -+{ -+ struct crypto_aead *tls = crypto_aead_reqtfm(req); -+ struct crypto_tls_ctx *ctx = crypto_aead_ctx(tls); -+ SKCIPHER_REQUEST_ON_STACK(skreq, ctx->null); -+ -+ skcipher_request_set_tfm(skreq, ctx->null); -+ skcipher_request_set_callback(skreq, aead_request_flags(req), -+ NULL, NULL); -+ skcipher_request_set_crypt(skreq, src, dst, len, NULL); -+ -+ return crypto_skcipher_encrypt(skreq); -+} -+ -+static int crypto_tls_encrypt(struct aead_request *req) -+{ -+ struct crypto_aead *tls = crypto_aead_reqtfm(req); -+ struct crypto_tls_ctx *ctx = crypto_aead_ctx(tls); -+ struct tls_request_ctx *treq_ctx = aead_request_ctx(req); -+ struct skcipher_request *skreq; -+ struct scatterlist *cipher = treq_ctx->cipher; -+ struct scatterlist *tmp = treq_ctx->tmp; -+ struct scatterlist *sg, *src, *dst; -+ unsigned int cryptlen, phashlen; -+ u8 *hash = treq_ctx->tail; -+ int err; -+ -+ /* -+ * The hash result is saved at the beginning of the tls request ctx -+ * and is aligned as required by the hash transform. Enough space was -+ * allocated in crypto_tls_init_tfm to accommodate the difference. The -+ * requests themselves start later at treq_ctx->tail + ctx->reqoff so -+ * the result is not overwritten by the second (cipher) request. -+ */ -+ hash = (u8 *)ALIGN((unsigned long)hash + -+ crypto_ahash_alignmask(ctx->auth), -+ crypto_ahash_alignmask(ctx->auth) + 1); -+ -+ /* -+ * STEP 1: create ICV together with necessary padding -+ */ -+ err = crypto_tls_gen_padicv(hash, &phashlen, req); -+ if (err) -+ return err; -+ -+ /* -+ * STEP 2: Hash and padding are combined with the payload -+ * depending on the form it arrives. Scatter tables must have at least -+ * one page of data before chaining with another table and can't have -+ * an empty data page. The following code addresses these requirements. -+ * -+ * If the payload is empty, only the hash is encrypted, otherwise the -+ * payload scatterlist is merged with the hash. A special merging case -+ * is when the payload has only one page of data. In that case the -+ * payload page is moved to another scatterlist and prepared there for -+ * encryption. -+ */ -+ if (req->cryptlen) { -+ src = scatterwalk_ffwd(tmp, req->src, req->assoclen); -+ -+ sg_init_table(cipher, 2); -+ sg_set_buf(cipher + 1, hash, phashlen); -+ -+ if (sg_is_last(src)) { -+ sg_set_page(cipher, sg_page(src), req->cryptlen, -+ src->offset); -+ src = cipher; -+ } else { -+ unsigned int rem_len = req->cryptlen; -+ -+ for (sg = src; rem_len > sg->length; sg = sg_next(sg)) -+ rem_len -= min(rem_len, sg->length); -+ -+ sg_set_page(cipher, sg_page(sg), rem_len, sg->offset); -+ sg_chain(sg, 1, cipher); -+ } -+ } else { -+ sg_init_one(cipher, hash, phashlen); -+ src = cipher; -+ } -+ -+ /** -+ * If src != dst copy the associated data from source to destination. -+ * In both cases fast-forward passed the associated data in the dest. -+ */ -+ if (req->src != req->dst) { -+ err = crypto_tls_copy_data(req, req->src, req->dst, -+ req->assoclen); -+ if (err) -+ return err; -+ } -+ dst = scatterwalk_ffwd(treq_ctx->dst, req->dst, req->assoclen); -+ -+ /* -+ * STEP 3: encrypt the frame and return the result -+ */ -+ cryptlen = req->cryptlen + phashlen; -+ -+ /* -+ * The hash and the cipher are applied at different times and their -+ * requests can use the same memory space without interference -+ */ -+ skreq = (void *)(treq_ctx->tail + ctx->reqoff); -+ skcipher_request_set_tfm(skreq, ctx->enc); -+ skcipher_request_set_crypt(skreq, src, dst, cryptlen, req->iv); -+ skcipher_request_set_callback(skreq, aead_request_flags(req), -+ req->base.complete, req->base.data); -+ /* -+ * Apply the cipher transform. The result will be in req->dst when the -+ * asynchronuous call terminates -+ */ -+ err = crypto_skcipher_encrypt(skreq); -+ -+ return err; -+} -+ -+static int crypto_tls_decrypt(struct aead_request *req) -+{ -+ struct crypto_aead *tls = crypto_aead_reqtfm(req); -+ struct crypto_tls_ctx *ctx = crypto_aead_ctx(tls); -+ struct tls_request_ctx *treq_ctx = aead_request_ctx(req); -+ unsigned int cryptlen = req->cryptlen; -+ unsigned int hash_size = crypto_aead_authsize(tls); -+ unsigned int block_size = crypto_aead_blocksize(tls); -+ struct skcipher_request *skreq = (void *)(treq_ctx->tail + ctx->reqoff); -+ struct scatterlist *tmp = treq_ctx->tmp; -+ struct scatterlist *src, *dst; -+ -+ u8 padding[255]; /* padding can be 0-255 bytes */ -+ u8 pad_size; -+ u16 *len_field; -+ u8 *ihash, *hash = treq_ctx->tail; -+ -+ int paderr = 0; -+ int err = -EINVAL; -+ int i; -+ struct async_op ciph_op; -+ -+ /* -+ * Rule out bad packets. The input packet length must be at least one -+ * byte more than the hash_size -+ */ -+ if (cryptlen <= hash_size || cryptlen % block_size) -+ goto out; -+ -+ /* -+ * Step 1 - Decrypt the source. Fast-forward past the associated data -+ * to the encrypted data. The result will be overwritten in place so -+ * that the decrypted data will be adjacent to the associated data. The -+ * last step (computing the hash) will have it's input data already -+ * prepared and ready to be accessed at req->src. -+ */ -+ src = scatterwalk_ffwd(tmp, req->src, req->assoclen); -+ dst = src; -+ -+ init_completion(&ciph_op.completion); -+ skcipher_request_set_tfm(skreq, ctx->enc); -+ skcipher_request_set_callback(skreq, aead_request_flags(req), -+ tls_async_op_done, &ciph_op); -+ skcipher_request_set_crypt(skreq, src, dst, cryptlen, req->iv); -+ err = crypto_skcipher_decrypt(skreq); -+ if (err == -EINPROGRESS) { -+ err = wait_for_completion_interruptible(&ciph_op.completion); -+ if (!err) -+ err = ciph_op.err; -+ } -+ if (err) -+ goto out; -+ -+ /* -+ * Step 2 - Verify padding -+ * Retrieve the last byte of the payload; this is the padding size. -+ */ -+ cryptlen -= 1; -+ scatterwalk_map_and_copy(&pad_size, dst, cryptlen, 1, 0); -+ -+ /* RFC recommendation for invalid padding size. */ -+ if (cryptlen < pad_size + hash_size) { -+ pad_size = 0; -+ paderr = -EBADMSG; -+ } -+ cryptlen -= pad_size; -+ scatterwalk_map_and_copy(padding, dst, cryptlen, pad_size, 0); -+ -+ /* Padding content must be equal with pad_size. We verify it all */ -+ for (i = 0; i < pad_size; i++) -+ if (padding[i] != pad_size) -+ paderr = -EBADMSG; -+ -+ /* -+ * Step 3 - Verify hash -+ * Align the digest result as required by the hash transform. Enough -+ * space was allocated in crypto_tls_init_tfm -+ */ -+ hash = (u8 *)ALIGN((unsigned long)hash + -+ crypto_ahash_alignmask(ctx->auth), -+ crypto_ahash_alignmask(ctx->auth) + 1); -+ /* -+ * Two bytes at the end of the associated data make the length field. -+ * It must be updated with the length of the cleartext message before -+ * the hash is calculated. -+ */ -+ len_field = sg_virt(req->src) + req->assoclen - 2; -+ cryptlen -= hash_size; -+ *len_field = htons(cryptlen); -+ -+ /* This is the hash from the decrypted packet. Save it for later */ -+ ihash = hash + hash_size; -+ scatterwalk_map_and_copy(ihash, dst, cryptlen, hash_size, 0); -+ -+ /* Now compute and compare our ICV with the one from the packet */ -+ err = crypto_tls_genicv(hash, req->src, cryptlen + req->assoclen, req); -+ if (!err) -+ err = memcmp(hash, ihash, hash_size) ? -EBADMSG : 0; -+ -+ if (req->src != req->dst) { -+ err = crypto_tls_copy_data(req, req->src, req->dst, cryptlen + -+ req->assoclen); -+ if (err) -+ goto out; -+ } -+ -+ /* return the first found error */ -+ if (paderr) -+ err = paderr; -+ -+out: -+ aead_request_complete(req, err); -+ return err; -+} -+ -+static int crypto_tls_init_tfm(struct crypto_aead *tfm) -+{ -+ struct aead_instance *inst = aead_alg_instance(tfm); -+ struct tls_instance_ctx *ictx = aead_instance_ctx(inst); -+ struct crypto_tls_ctx *ctx = crypto_aead_ctx(tfm); -+ struct crypto_ahash *auth; -+ struct crypto_skcipher *enc; -+ struct crypto_skcipher *null; -+ int err; -+ -+ auth = crypto_spawn_ahash(&ictx->auth); -+ if (IS_ERR(auth)) -+ return PTR_ERR(auth); -+ -+ enc = crypto_spawn_skcipher(&ictx->enc); -+ err = PTR_ERR(enc); -+ if (IS_ERR(enc)) -+ goto err_free_ahash; -+ -+ null = crypto_get_default_null_skcipher2(); -+ err = PTR_ERR(null); -+ if (IS_ERR(null)) -+ goto err_free_skcipher; -+ -+ ctx->auth = auth; -+ ctx->enc = enc; -+ ctx->null = null; -+ -+ /* -+ * Allow enough space for two digests. The two digests will be compared -+ * during the decryption phase. One will come from the decrypted packet -+ * and the other will be calculated. For encryption, one digest is -+ * padded (up to a cipher blocksize) and chained with the payload -+ */ -+ ctx->reqoff = ALIGN(crypto_ahash_digestsize(auth) + -+ crypto_ahash_alignmask(auth), -+ crypto_ahash_alignmask(auth) + 1) + -+ max(crypto_ahash_digestsize(auth), -+ crypto_skcipher_blocksize(enc)); -+ -+ crypto_aead_set_reqsize(tfm, -+ sizeof(struct tls_request_ctx) + -+ ctx->reqoff + -+ max_t(unsigned int, -+ crypto_ahash_reqsize(auth) + -+ sizeof(struct ahash_request), -+ crypto_skcipher_reqsize(enc) + -+ sizeof(struct skcipher_request))); -+ -+ return 0; -+ -+err_free_skcipher: -+ crypto_free_skcipher(enc); -+err_free_ahash: -+ crypto_free_ahash(auth); -+ return err; -+} -+ -+static void crypto_tls_exit_tfm(struct crypto_aead *tfm) -+{ -+ struct crypto_tls_ctx *ctx = crypto_aead_ctx(tfm); -+ -+ crypto_free_ahash(ctx->auth); -+ crypto_free_skcipher(ctx->enc); -+ crypto_put_default_null_skcipher2(); -+} -+ -+static void crypto_tls_free(struct aead_instance *inst) -+{ -+ struct tls_instance_ctx *ctx = aead_instance_ctx(inst); -+ -+ crypto_drop_skcipher(&ctx->enc); -+ crypto_drop_ahash(&ctx->auth); -+ kfree(inst); -+} -+ -+static int crypto_tls_create(struct crypto_template *tmpl, struct rtattr **tb) -+{ -+ struct crypto_attr_type *algt; -+ struct aead_instance *inst; -+ struct hash_alg_common *auth; -+ struct crypto_alg *auth_base; -+ struct skcipher_alg *enc; -+ struct tls_instance_ctx *ctx; -+ const char *enc_name; -+ int err; -+ -+ algt = crypto_get_attr_type(tb); -+ if (IS_ERR(algt)) -+ return PTR_ERR(algt); -+ -+ if ((algt->type ^ CRYPTO_ALG_TYPE_AEAD) & algt->mask) -+ return -EINVAL; -+ -+ auth = ahash_attr_alg(tb[1], CRYPTO_ALG_TYPE_HASH, -+ CRYPTO_ALG_TYPE_AHASH_MASK | -+ crypto_requires_sync(algt->type, algt->mask)); -+ if (IS_ERR(auth)) -+ return PTR_ERR(auth); -+ -+ auth_base = &auth->base; -+ -+ enc_name = crypto_attr_alg_name(tb[2]); -+ err = PTR_ERR(enc_name); -+ if (IS_ERR(enc_name)) -+ goto out_put_auth; -+ -+ inst = kzalloc(sizeof(*inst) + sizeof(*ctx), GFP_KERNEL); -+ err = -ENOMEM; -+ if (!inst) -+ goto out_put_auth; -+ -+ ctx = aead_instance_ctx(inst); -+ -+ err = crypto_init_ahash_spawn(&ctx->auth, auth, -+ aead_crypto_instance(inst)); -+ if (err) -+ goto err_free_inst; -+ -+ crypto_set_skcipher_spawn(&ctx->enc, aead_crypto_instance(inst)); -+ err = crypto_grab_skcipher(&ctx->enc, enc_name, 0, -+ crypto_requires_sync(algt->type, -+ algt->mask)); -+ if (err) -+ goto err_drop_auth; -+ -+ enc = crypto_spawn_skcipher_alg(&ctx->enc); -+ -+ err = -ENAMETOOLONG; -+ if (snprintf(inst->alg.base.cra_name, CRYPTO_MAX_ALG_NAME, -+ "tls10(%s,%s)", auth_base->cra_name, -+ enc->base.cra_name) >= CRYPTO_MAX_ALG_NAME) -+ goto err_drop_enc; -+ -+ if (snprintf(inst->alg.base.cra_driver_name, CRYPTO_MAX_ALG_NAME, -+ "tls10(%s,%s)", auth_base->cra_driver_name, -+ enc->base.cra_driver_name) >= CRYPTO_MAX_ALG_NAME) -+ goto err_drop_enc; -+ -+ inst->alg.base.cra_flags = (auth_base->cra_flags | -+ enc->base.cra_flags) & CRYPTO_ALG_ASYNC; -+ inst->alg.base.cra_priority = enc->base.cra_priority * 10 + -+ auth_base->cra_priority; -+ inst->alg.base.cra_blocksize = enc->base.cra_blocksize; -+ inst->alg.base.cra_alignmask = auth_base->cra_alignmask | -+ enc->base.cra_alignmask; -+ inst->alg.base.cra_ctxsize = sizeof(struct crypto_tls_ctx); -+ -+ inst->alg.ivsize = crypto_skcipher_alg_ivsize(enc); -+ inst->alg.chunksize = crypto_skcipher_alg_chunksize(enc); -+ inst->alg.maxauthsize = auth->digestsize; -+ -+ inst->alg.init = crypto_tls_init_tfm; -+ inst->alg.exit = crypto_tls_exit_tfm; -+ -+ inst->alg.setkey = crypto_tls_setkey; -+ inst->alg.encrypt = crypto_tls_encrypt; -+ inst->alg.decrypt = crypto_tls_decrypt; -+ -+ inst->free = crypto_tls_free; -+ -+ err = aead_register_instance(tmpl, inst); -+ if (err) -+ goto err_drop_enc; -+ -+out: -+ crypto_mod_put(auth_base); -+ return err; -+ -+err_drop_enc: -+ crypto_drop_skcipher(&ctx->enc); -+err_drop_auth: -+ crypto_drop_ahash(&ctx->auth); -+err_free_inst: -+ kfree(inst); -+out_put_auth: -+ goto out; -+} -+ -+static struct crypto_template crypto_tls_tmpl = { -+ .name = "tls10", -+ .create = crypto_tls_create, -+ .module = THIS_MODULE, -+}; -+ -+static int __init crypto_tls_module_init(void) -+{ -+ return crypto_register_template(&crypto_tls_tmpl); -+} -+ -+static void __exit crypto_tls_module_exit(void) -+{ -+ crypto_unregister_template(&crypto_tls_tmpl); -+} -+ -+module_init(crypto_tls_module_init); -+module_exit(crypto_tls_module_exit); -+ -+MODULE_LICENSE("GPL"); -+MODULE_DESCRIPTION("TLS 1.0 record encryption"); ---- a/drivers/crypto/Makefile -+++ b/drivers/crypto/Makefile -@@ -10,7 +10,7 @@ obj-$(CONFIG_CRYPTO_DEV_CHELSIO) += chel - obj-$(CONFIG_CRYPTO_DEV_CPT) += cavium/cpt/ - obj-$(CONFIG_CRYPTO_DEV_NITROX) += cavium/nitrox/ - obj-$(CONFIG_CRYPTO_DEV_EXYNOS_RNG) += exynos-rng.o --obj-$(CONFIG_CRYPTO_DEV_FSL_CAAM) += caam/ -+obj-$(CONFIG_CRYPTO_DEV_FSL_CAAM_COMMON) += caam/ - obj-$(CONFIG_CRYPTO_DEV_GEODE) += geode-aes.o - obj-$(CONFIG_CRYPTO_DEV_HIFN_795X) += hifn_795x.o - obj-$(CONFIG_CRYPTO_DEV_IMGTEC_HASH) += img-hash.o ---- a/drivers/crypto/caam/Kconfig -+++ b/drivers/crypto/caam/Kconfig -@@ -1,7 +1,17 @@ -+config CRYPTO_DEV_FSL_CAAM_COMMON -+ tristate -+ -+config CRYPTO_DEV_FSL_CAAM_CRYPTO_API_DESC -+ tristate -+ -+config CRYPTO_DEV_FSL_CAAM_AHASH_API_DESC -+ tristate -+ - config CRYPTO_DEV_FSL_CAAM -- tristate "Freescale CAAM-Multicore driver backend" -+ tristate "Freescale CAAM-Multicore platform driver backend" - depends on FSL_SOC || ARCH_MXC || ARCH_LAYERSCAPE - select SOC_BUS -+ select CRYPTO_DEV_FSL_CAAM_COMMON - help - Enables the driver module for Freescale's Cryptographic Accelerator - and Assurance Module (CAAM), also known as the SEC version 4 (SEC4). -@@ -12,9 +22,16 @@ config CRYPTO_DEV_FSL_CAAM - To compile this driver as a module, choose M here: the module - will be called caam. - -+if CRYPTO_DEV_FSL_CAAM -+ -+config CRYPTO_DEV_FSL_CAAM_DEBUG -+ bool "Enable debug output in CAAM driver" -+ help -+ Selecting this will enable printing of various debug -+ information in the CAAM driver. -+ - config CRYPTO_DEV_FSL_CAAM_JR - tristate "Freescale CAAM Job Ring driver backend" -- depends on CRYPTO_DEV_FSL_CAAM - default y - help - Enables the driver module for Job Rings which are part of -@@ -25,9 +42,10 @@ config CRYPTO_DEV_FSL_CAAM_JR - To compile this driver as a module, choose M here: the module - will be called caam_jr. - -+if CRYPTO_DEV_FSL_CAAM_JR -+ - config CRYPTO_DEV_FSL_CAAM_RINGSIZE - int "Job Ring size" -- depends on CRYPTO_DEV_FSL_CAAM_JR - range 2 9 - default "9" - help -@@ -45,7 +63,6 @@ config CRYPTO_DEV_FSL_CAAM_RINGSIZE - - config CRYPTO_DEV_FSL_CAAM_INTC - bool "Job Ring interrupt coalescing" -- depends on CRYPTO_DEV_FSL_CAAM_JR - help - Enable the Job Ring's interrupt coalescing feature. - -@@ -74,9 +91,9 @@ config CRYPTO_DEV_FSL_CAAM_INTC_TIME_THL - threshold. Range is 1-65535. - - config CRYPTO_DEV_FSL_CAAM_CRYPTO_API -- tristate "Register algorithm implementations with the Crypto API" -- depends on CRYPTO_DEV_FSL_CAAM_JR -+ bool "Register algorithm implementations with the Crypto API" - default y -+ select CRYPTO_DEV_FSL_CAAM_CRYPTO_API_DESC - select CRYPTO_AEAD - select CRYPTO_AUTHENC - select CRYPTO_BLKCIPHER -@@ -85,13 +102,11 @@ config CRYPTO_DEV_FSL_CAAM_CRYPTO_API - scatterlist crypto API (such as the linux native IPSec - stack) to the SEC4 via job ring. - -- To compile this as a module, choose M here: the module -- will be called caamalg. -- - config CRYPTO_DEV_FSL_CAAM_CRYPTO_API_QI -- tristate "Queue Interface as Crypto API backend" -- depends on CRYPTO_DEV_FSL_CAAM_JR && FSL_DPAA && NET -+ bool "Queue Interface as Crypto API backend" -+ depends on FSL_SDK_DPA && NET - default y -+ select CRYPTO_DEV_FSL_CAAM_CRYPTO_API_DESC - select CRYPTO_AUTHENC - select CRYPTO_BLKCIPHER - help -@@ -102,36 +117,26 @@ config CRYPTO_DEV_FSL_CAAM_CRYPTO_API_QI - assigned to the kernel should also be more than the number of - job rings. - -- To compile this as a module, choose M here: the module -- will be called caamalg_qi. -- - config CRYPTO_DEV_FSL_CAAM_AHASH_API -- tristate "Register hash algorithm implementations with Crypto API" -- depends on CRYPTO_DEV_FSL_CAAM_JR -+ bool "Register hash algorithm implementations with Crypto API" - default y -+ select CRYPTO_DEV_FSL_CAAM_AHASH_API_DESC - select CRYPTO_HASH - help - Selecting this will offload ahash for users of the - scatterlist crypto API to the SEC4 via job ring. - -- To compile this as a module, choose M here: the module -- will be called caamhash. -- - config CRYPTO_DEV_FSL_CAAM_PKC_API -- tristate "Register public key cryptography implementations with Crypto API" -- depends on CRYPTO_DEV_FSL_CAAM_JR -+ bool "Register public key cryptography implementations with Crypto API" - default y - select CRYPTO_RSA - help - Selecting this will allow SEC Public key support for RSA. - Supported cryptographic primitives: encryption, decryption, - signature and verification. -- To compile this as a module, choose M here: the module -- will be called caam_pkc. - - config CRYPTO_DEV_FSL_CAAM_RNG_API -- tristate "Register caam device for hwrng API" -- depends on CRYPTO_DEV_FSL_CAAM_JR -+ bool "Register caam device for hwrng API" - default y - select CRYPTO_RNG - select HW_RANDOM -@@ -139,16 +144,24 @@ config CRYPTO_DEV_FSL_CAAM_RNG_API - Selecting this will register the SEC4 hardware rng to - the hw_random API for suppying the kernel entropy pool. - -- To compile this as a module, choose M here: the module -- will be called caamrng. -+endif # CRYPTO_DEV_FSL_CAAM_JR - --config CRYPTO_DEV_FSL_CAAM_DEBUG -- bool "Enable debug output in CAAM driver" -- depends on CRYPTO_DEV_FSL_CAAM -- help -- Selecting this will enable printing of various debug -- information in the CAAM driver. -+endif # CRYPTO_DEV_FSL_CAAM - --config CRYPTO_DEV_FSL_CAAM_CRYPTO_API_DESC -- def_tristate (CRYPTO_DEV_FSL_CAAM_CRYPTO_API || \ -- CRYPTO_DEV_FSL_CAAM_CRYPTO_API_QI) -+config CRYPTO_DEV_FSL_DPAA2_CAAM -+ tristate "QorIQ DPAA2 CAAM (DPSECI) driver" -+ depends on FSL_MC_DPIO -+ select CRYPTO_DEV_FSL_CAAM_COMMON -+ select CRYPTO_DEV_FSL_CAAM_CRYPTO_API_DESC -+ select CRYPTO_DEV_FSL_CAAM_AHASH_API_DESC -+ select CRYPTO_BLKCIPHER -+ select CRYPTO_AUTHENC -+ select CRYPTO_AEAD -+ select CRYPTO_HASH -+ ---help--- -+ CAAM driver for QorIQ Data Path Acceleration Architecture 2. -+ It handles DPSECI DPAA2 objects that sit on the Management Complex -+ (MC) fsl-mc bus. -+ -+ To compile this as a module, choose M here: the module -+ will be called dpaa2_caam. ---- a/drivers/crypto/caam/Makefile -+++ b/drivers/crypto/caam/Makefile -@@ -6,19 +6,27 @@ ifeq ($(CONFIG_CRYPTO_DEV_FSL_CAAM_DEBUG - ccflags-y := -DDEBUG - endif - -+ccflags-y += -DVERSION=\"\" -+ -+obj-$(CONFIG_CRYPTO_DEV_FSL_CAAM_COMMON) += error.o - obj-$(CONFIG_CRYPTO_DEV_FSL_CAAM) += caam.o - obj-$(CONFIG_CRYPTO_DEV_FSL_CAAM_JR) += caam_jr.o --obj-$(CONFIG_CRYPTO_DEV_FSL_CAAM_CRYPTO_API) += caamalg.o --obj-$(CONFIG_CRYPTO_DEV_FSL_CAAM_CRYPTO_API_QI) += caamalg_qi.o - obj-$(CONFIG_CRYPTO_DEV_FSL_CAAM_CRYPTO_API_DESC) += caamalg_desc.o --obj-$(CONFIG_CRYPTO_DEV_FSL_CAAM_AHASH_API) += caamhash.o --obj-$(CONFIG_CRYPTO_DEV_FSL_CAAM_RNG_API) += caamrng.o --obj-$(CONFIG_CRYPTO_DEV_FSL_CAAM_PKC_API) += caam_pkc.o -- --caam-objs := ctrl.o --caam_jr-objs := jr.o key_gen.o error.o --caam_pkc-y := caampkc.o pkc_desc.o -+obj-$(CONFIG_CRYPTO_DEV_FSL_CAAM_AHASH_API_DESC) += caamhash_desc.o -+ -+caam-y := ctrl.o -+caam_jr-y := jr.o key_gen.o -+caam_jr-$(CONFIG_CRYPTO_DEV_FSL_CAAM_CRYPTO_API) += caamalg.o -+caam_jr-$(CONFIG_CRYPTO_DEV_FSL_CAAM_CRYPTO_API_QI) += caamalg_qi.o -+caam_jr-$(CONFIG_CRYPTO_DEV_FSL_CAAM_AHASH_API) += caamhash.o -+caam_jr-$(CONFIG_CRYPTO_DEV_FSL_CAAM_RNG_API) += caamrng.o -+caam_jr-$(CONFIG_CRYPTO_DEV_FSL_CAAM_PKC_API) += caampkc.o pkc_desc.o -+ -+caam-$(CONFIG_CRYPTO_DEV_FSL_CAAM_CRYPTO_API_QI) += qi.o - ifneq ($(CONFIG_CRYPTO_DEV_FSL_CAAM_CRYPTO_API_QI),) - ccflags-y += -DCONFIG_CAAM_QI -- caam-objs += qi.o - endif -+ -+obj-$(CONFIG_CRYPTO_DEV_FSL_DPAA2_CAAM) += dpaa2_caam.o -+ -+dpaa2_caam-y := caamalg_qi2.o dpseci.o ---- a/drivers/crypto/caam/caamalg.c -+++ b/drivers/crypto/caam/caamalg.c -@@ -71,6 +71,8 @@ - #define AUTHENC_DESC_JOB_IO_LEN (AEAD_DESC_JOB_IO_LEN + \ - CAAM_CMD_SZ * 5) - -+#define CHACHAPOLY_DESC_JOB_IO_LEN (AEAD_DESC_JOB_IO_LEN + CAAM_CMD_SZ * 6) -+ - #define DESC_MAX_USED_BYTES (CAAM_DESC_BYTES_MAX - DESC_JOB_IO_LEN) - #define DESC_MAX_USED_LEN (DESC_MAX_USED_BYTES / CAAM_CMD_SZ) - -@@ -108,6 +110,7 @@ struct caam_ctx { - dma_addr_t sh_desc_dec_dma; - dma_addr_t sh_desc_givenc_dma; - dma_addr_t key_dma; -+ enum dma_data_direction dir; - struct device *jrdev; - struct alginfo adata; - struct alginfo cdata; -@@ -118,6 +121,7 @@ static int aead_null_set_sh_desc(struct - { - struct caam_ctx *ctx = crypto_aead_ctx(aead); - struct device *jrdev = ctx->jrdev; -+ struct caam_drv_private *ctrlpriv = dev_get_drvdata(jrdev->parent); - u32 *desc; - int rem_bytes = CAAM_DESC_BYTES_MAX - AEAD_DESC_JOB_IO_LEN - - ctx->adata.keylen_pad; -@@ -136,9 +140,10 @@ static int aead_null_set_sh_desc(struct - - /* aead_encrypt shared descriptor */ - desc = ctx->sh_desc_enc; -- cnstr_shdsc_aead_null_encap(desc, &ctx->adata, ctx->authsize); -+ cnstr_shdsc_aead_null_encap(desc, &ctx->adata, ctx->authsize, -+ ctrlpriv->era); - dma_sync_single_for_device(jrdev, ctx->sh_desc_enc_dma, -- desc_bytes(desc), DMA_TO_DEVICE); -+ desc_bytes(desc), ctx->dir); - - /* - * Job Descriptor and Shared Descriptors -@@ -154,9 +159,10 @@ static int aead_null_set_sh_desc(struct - - /* aead_decrypt shared descriptor */ - desc = ctx->sh_desc_dec; -- cnstr_shdsc_aead_null_decap(desc, &ctx->adata, ctx->authsize); -+ cnstr_shdsc_aead_null_decap(desc, &ctx->adata, ctx->authsize, -+ ctrlpriv->era); - dma_sync_single_for_device(jrdev, ctx->sh_desc_dec_dma, -- desc_bytes(desc), DMA_TO_DEVICE); -+ desc_bytes(desc), ctx->dir); - - return 0; - } -@@ -168,6 +174,7 @@ static int aead_set_sh_desc(struct crypt - unsigned int ivsize = crypto_aead_ivsize(aead); - struct caam_ctx *ctx = crypto_aead_ctx(aead); - struct device *jrdev = ctx->jrdev; -+ struct caam_drv_private *ctrlpriv = dev_get_drvdata(jrdev->parent); - u32 ctx1_iv_off = 0; - u32 *desc, *nonce = NULL; - u32 inl_mask; -@@ -234,9 +241,9 @@ static int aead_set_sh_desc(struct crypt - desc = ctx->sh_desc_enc; - cnstr_shdsc_aead_encap(desc, &ctx->cdata, &ctx->adata, ivsize, - ctx->authsize, is_rfc3686, nonce, ctx1_iv_off, -- false); -+ false, ctrlpriv->era); - dma_sync_single_for_device(jrdev, ctx->sh_desc_enc_dma, -- desc_bytes(desc), DMA_TO_DEVICE); -+ desc_bytes(desc), ctx->dir); - - skip_enc: - /* -@@ -266,9 +273,9 @@ skip_enc: - desc = ctx->sh_desc_dec; - cnstr_shdsc_aead_decap(desc, &ctx->cdata, &ctx->adata, ivsize, - ctx->authsize, alg->caam.geniv, is_rfc3686, -- nonce, ctx1_iv_off, false); -+ nonce, ctx1_iv_off, false, ctrlpriv->era); - dma_sync_single_for_device(jrdev, ctx->sh_desc_dec_dma, -- desc_bytes(desc), DMA_TO_DEVICE); -+ desc_bytes(desc), ctx->dir); - - if (!alg->caam.geniv) - goto skip_givenc; -@@ -300,9 +307,9 @@ skip_enc: - desc = ctx->sh_desc_enc; - cnstr_shdsc_aead_givencap(desc, &ctx->cdata, &ctx->adata, ivsize, - ctx->authsize, is_rfc3686, nonce, -- ctx1_iv_off, false); -+ ctx1_iv_off, false, ctrlpriv->era); - dma_sync_single_for_device(jrdev, ctx->sh_desc_enc_dma, -- desc_bytes(desc), DMA_TO_DEVICE); -+ desc_bytes(desc), ctx->dir); - - skip_givenc: - return 0; -@@ -323,6 +330,7 @@ static int gcm_set_sh_desc(struct crypto - { - struct caam_ctx *ctx = crypto_aead_ctx(aead); - struct device *jrdev = ctx->jrdev; -+ unsigned int ivsize = crypto_aead_ivsize(aead); - u32 *desc; - int rem_bytes = CAAM_DESC_BYTES_MAX - GCM_DESC_JOB_IO_LEN - - ctx->cdata.keylen; -@@ -344,9 +352,9 @@ static int gcm_set_sh_desc(struct crypto - } - - desc = ctx->sh_desc_enc; -- cnstr_shdsc_gcm_encap(desc, &ctx->cdata, ctx->authsize); -+ cnstr_shdsc_gcm_encap(desc, &ctx->cdata, ivsize, ctx->authsize, false); - dma_sync_single_for_device(jrdev, ctx->sh_desc_enc_dma, -- desc_bytes(desc), DMA_TO_DEVICE); -+ desc_bytes(desc), ctx->dir); - - /* - * Job Descriptor and Shared Descriptors -@@ -361,9 +369,9 @@ static int gcm_set_sh_desc(struct crypto - } - - desc = ctx->sh_desc_dec; -- cnstr_shdsc_gcm_decap(desc, &ctx->cdata, ctx->authsize); -+ cnstr_shdsc_gcm_decap(desc, &ctx->cdata, ivsize, ctx->authsize, false); - dma_sync_single_for_device(jrdev, ctx->sh_desc_dec_dma, -- desc_bytes(desc), DMA_TO_DEVICE); -+ desc_bytes(desc), ctx->dir); - - return 0; - } -@@ -382,6 +390,7 @@ static int rfc4106_set_sh_desc(struct cr - { - struct caam_ctx *ctx = crypto_aead_ctx(aead); - struct device *jrdev = ctx->jrdev; -+ unsigned int ivsize = crypto_aead_ivsize(aead); - u32 *desc; - int rem_bytes = CAAM_DESC_BYTES_MAX - GCM_DESC_JOB_IO_LEN - - ctx->cdata.keylen; -@@ -403,9 +412,10 @@ static int rfc4106_set_sh_desc(struct cr - } - - desc = ctx->sh_desc_enc; -- cnstr_shdsc_rfc4106_encap(desc, &ctx->cdata, ctx->authsize); -+ cnstr_shdsc_rfc4106_encap(desc, &ctx->cdata, ivsize, ctx->authsize, -+ false); - dma_sync_single_for_device(jrdev, ctx->sh_desc_enc_dma, -- desc_bytes(desc), DMA_TO_DEVICE); -+ desc_bytes(desc), ctx->dir); - - /* - * Job Descriptor and Shared Descriptors -@@ -420,9 +430,10 @@ static int rfc4106_set_sh_desc(struct cr - } - - desc = ctx->sh_desc_dec; -- cnstr_shdsc_rfc4106_decap(desc, &ctx->cdata, ctx->authsize); -+ cnstr_shdsc_rfc4106_decap(desc, &ctx->cdata, ivsize, ctx->authsize, -+ false); - dma_sync_single_for_device(jrdev, ctx->sh_desc_dec_dma, -- desc_bytes(desc), DMA_TO_DEVICE); -+ desc_bytes(desc), ctx->dir); - - return 0; - } -@@ -442,6 +453,7 @@ static int rfc4543_set_sh_desc(struct cr - { - struct caam_ctx *ctx = crypto_aead_ctx(aead); - struct device *jrdev = ctx->jrdev; -+ unsigned int ivsize = crypto_aead_ivsize(aead); - u32 *desc; - int rem_bytes = CAAM_DESC_BYTES_MAX - GCM_DESC_JOB_IO_LEN - - ctx->cdata.keylen; -@@ -463,9 +475,10 @@ static int rfc4543_set_sh_desc(struct cr - } - - desc = ctx->sh_desc_enc; -- cnstr_shdsc_rfc4543_encap(desc, &ctx->cdata, ctx->authsize); -+ cnstr_shdsc_rfc4543_encap(desc, &ctx->cdata, ivsize, ctx->authsize, -+ false); - dma_sync_single_for_device(jrdev, ctx->sh_desc_enc_dma, -- desc_bytes(desc), DMA_TO_DEVICE); -+ desc_bytes(desc), ctx->dir); - - /* - * Job Descriptor and Shared Descriptors -@@ -480,9 +493,10 @@ static int rfc4543_set_sh_desc(struct cr - } - - desc = ctx->sh_desc_dec; -- cnstr_shdsc_rfc4543_decap(desc, &ctx->cdata, ctx->authsize); -+ cnstr_shdsc_rfc4543_decap(desc, &ctx->cdata, ivsize, ctx->authsize, -+ false); - dma_sync_single_for_device(jrdev, ctx->sh_desc_dec_dma, -- desc_bytes(desc), DMA_TO_DEVICE); -+ desc_bytes(desc), ctx->dir); - - return 0; - } -@@ -498,11 +512,67 @@ static int rfc4543_setauthsize(struct cr - return 0; - } - -+static int chachapoly_set_sh_desc(struct crypto_aead *aead) -+{ -+ struct caam_ctx *ctx = crypto_aead_ctx(aead); -+ struct device *jrdev = ctx->jrdev; -+ unsigned int ivsize = crypto_aead_ivsize(aead); -+ u32 *desc; -+ -+ if (!ctx->cdata.keylen || !ctx->authsize) -+ return 0; -+ -+ desc = ctx->sh_desc_enc; -+ cnstr_shdsc_chachapoly(desc, &ctx->cdata, &ctx->adata, ivsize, -+ ctx->authsize, true, false); -+ dma_sync_single_for_device(jrdev, ctx->sh_desc_enc_dma, -+ desc_bytes(desc), ctx->dir); -+ -+ desc = ctx->sh_desc_dec; -+ cnstr_shdsc_chachapoly(desc, &ctx->cdata, &ctx->adata, ivsize, -+ ctx->authsize, false, false); -+ dma_sync_single_for_device(jrdev, ctx->sh_desc_dec_dma, -+ desc_bytes(desc), ctx->dir); -+ -+ return 0; -+} -+ -+static int chachapoly_setauthsize(struct crypto_aead *aead, -+ unsigned int authsize) -+{ -+ struct caam_ctx *ctx = crypto_aead_ctx(aead); -+ -+ if (authsize != POLY1305_DIGEST_SIZE) -+ return -EINVAL; -+ -+ ctx->authsize = authsize; -+ return chachapoly_set_sh_desc(aead); -+} -+ -+static int chachapoly_setkey(struct crypto_aead *aead, const u8 *key, -+ unsigned int keylen) -+{ -+ struct caam_ctx *ctx = crypto_aead_ctx(aead); -+ unsigned int ivsize = crypto_aead_ivsize(aead); -+ unsigned int saltlen = CHACHAPOLY_IV_SIZE - ivsize; -+ -+ if (keylen != CHACHA20_KEY_SIZE + saltlen) { -+ crypto_aead_set_flags(aead, CRYPTO_TFM_RES_BAD_KEY_LEN); -+ return -EINVAL; -+ } -+ -+ ctx->cdata.key_virt = key; -+ ctx->cdata.keylen = keylen - saltlen; -+ -+ return chachapoly_set_sh_desc(aead); -+} -+ - static int aead_setkey(struct crypto_aead *aead, - const u8 *key, unsigned int keylen) - { - struct caam_ctx *ctx = crypto_aead_ctx(aead); - struct device *jrdev = ctx->jrdev; -+ struct caam_drv_private *ctrlpriv = dev_get_drvdata(jrdev->parent); - struct crypto_authenc_keys keys; - int ret = 0; - -@@ -517,6 +587,27 @@ static int aead_setkey(struct crypto_aea - DUMP_PREFIX_ADDRESS, 16, 4, key, keylen, 1); - #endif - -+ /* -+ * If DKP is supported, use it in the shared descriptor to generate -+ * the split key. -+ */ -+ if (ctrlpriv->era >= 6) { -+ ctx->adata.keylen = keys.authkeylen; -+ ctx->adata.keylen_pad = split_key_len(ctx->adata.algtype & -+ OP_ALG_ALGSEL_MASK); -+ -+ if (ctx->adata.keylen_pad + keys.enckeylen > CAAM_MAX_KEY_SIZE) -+ goto badkey; -+ -+ memcpy(ctx->key, keys.authkey, keys.authkeylen); -+ memcpy(ctx->key + ctx->adata.keylen_pad, keys.enckey, -+ keys.enckeylen); -+ dma_sync_single_for_device(jrdev, ctx->key_dma, -+ ctx->adata.keylen_pad + -+ keys.enckeylen, ctx->dir); -+ goto skip_split_key; -+ } -+ - ret = gen_split_key(ctx->jrdev, ctx->key, &ctx->adata, keys.authkey, - keys.authkeylen, CAAM_MAX_KEY_SIZE - - keys.enckeylen); -@@ -527,12 +618,14 @@ static int aead_setkey(struct crypto_aea - /* postpend encryption key to auth split key */ - memcpy(ctx->key + ctx->adata.keylen_pad, keys.enckey, keys.enckeylen); - dma_sync_single_for_device(jrdev, ctx->key_dma, ctx->adata.keylen_pad + -- keys.enckeylen, DMA_TO_DEVICE); -+ keys.enckeylen, ctx->dir); - #ifdef DEBUG - print_hex_dump(KERN_ERR, "ctx.key@"__stringify(__LINE__)": ", - DUMP_PREFIX_ADDRESS, 16, 4, ctx->key, - ctx->adata.keylen_pad + keys.enckeylen, 1); - #endif -+ -+skip_split_key: - ctx->cdata.keylen = keys.enckeylen; - return aead_set_sh_desc(aead); - badkey: -@@ -552,7 +645,7 @@ static int gcm_setkey(struct crypto_aead - #endif - - memcpy(ctx->key, key, keylen); -- dma_sync_single_for_device(jrdev, ctx->key_dma, keylen, DMA_TO_DEVICE); -+ dma_sync_single_for_device(jrdev, ctx->key_dma, keylen, ctx->dir); - ctx->cdata.keylen = keylen; - - return gcm_set_sh_desc(aead); -@@ -580,7 +673,7 @@ static int rfc4106_setkey(struct crypto_ - */ - ctx->cdata.keylen = keylen - 4; - dma_sync_single_for_device(jrdev, ctx->key_dma, ctx->cdata.keylen, -- DMA_TO_DEVICE); -+ ctx->dir); - return rfc4106_set_sh_desc(aead); - } - -@@ -606,7 +699,7 @@ static int rfc4543_setkey(struct crypto_ - */ - ctx->cdata.keylen = keylen - 4; - dma_sync_single_for_device(jrdev, ctx->key_dma, ctx->cdata.keylen, -- DMA_TO_DEVICE); -+ ctx->dir); - return rfc4543_set_sh_desc(aead); - } - -@@ -658,21 +751,21 @@ static int ablkcipher_setkey(struct cryp - cnstr_shdsc_ablkcipher_encap(desc, &ctx->cdata, ivsize, is_rfc3686, - ctx1_iv_off); - dma_sync_single_for_device(jrdev, ctx->sh_desc_enc_dma, -- desc_bytes(desc), DMA_TO_DEVICE); -+ desc_bytes(desc), ctx->dir); - - /* ablkcipher_decrypt shared descriptor */ - desc = ctx->sh_desc_dec; - cnstr_shdsc_ablkcipher_decap(desc, &ctx->cdata, ivsize, is_rfc3686, - ctx1_iv_off); - dma_sync_single_for_device(jrdev, ctx->sh_desc_dec_dma, -- desc_bytes(desc), DMA_TO_DEVICE); -+ desc_bytes(desc), ctx->dir); - - /* ablkcipher_givencrypt shared descriptor */ - desc = ctx->sh_desc_givenc; - cnstr_shdsc_ablkcipher_givencap(desc, &ctx->cdata, ivsize, is_rfc3686, - ctx1_iv_off); - dma_sync_single_for_device(jrdev, ctx->sh_desc_givenc_dma, -- desc_bytes(desc), DMA_TO_DEVICE); -+ desc_bytes(desc), ctx->dir); - - return 0; - } -@@ -701,13 +794,13 @@ static int xts_ablkcipher_setkey(struct - desc = ctx->sh_desc_enc; - cnstr_shdsc_xts_ablkcipher_encap(desc, &ctx->cdata); - dma_sync_single_for_device(jrdev, ctx->sh_desc_enc_dma, -- desc_bytes(desc), DMA_TO_DEVICE); -+ desc_bytes(desc), ctx->dir); - - /* xts_ablkcipher_decrypt shared descriptor */ - desc = ctx->sh_desc_dec; - cnstr_shdsc_xts_ablkcipher_decap(desc, &ctx->cdata); - dma_sync_single_for_device(jrdev, ctx->sh_desc_dec_dma, -- desc_bytes(desc), DMA_TO_DEVICE); -+ desc_bytes(desc), ctx->dir); - - return 0; - } -@@ -989,9 +1082,6 @@ static void init_aead_job(struct aead_re - append_seq_out_ptr(desc, dst_dma, - req->assoclen + req->cryptlen - authsize, - out_options); -- -- /* REG3 = assoclen */ -- append_math_add_imm_u32(desc, REG3, ZERO, IMM, req->assoclen); - } - - static void init_gcm_job(struct aead_request *req, -@@ -1006,6 +1096,7 @@ static void init_gcm_job(struct aead_req - unsigned int last; - - init_aead_job(req, edesc, all_contig, encrypt); -+ append_math_add_imm_u32(desc, REG3, ZERO, IMM, req->assoclen); - - /* BUG This should not be specific to generic GCM. */ - last = 0; -@@ -1023,6 +1114,40 @@ static void init_gcm_job(struct aead_req - /* End of blank commands */ - } - -+static void init_chachapoly_job(struct aead_request *req, -+ struct aead_edesc *edesc, bool all_contig, -+ bool encrypt) -+{ -+ struct crypto_aead *aead = crypto_aead_reqtfm(req); -+ unsigned int ivsize = crypto_aead_ivsize(aead); -+ unsigned int assoclen = req->assoclen; -+ u32 *desc = edesc->hw_desc; -+ u32 ctx_iv_off = 4; -+ -+ init_aead_job(req, edesc, all_contig, encrypt); -+ -+ if (ivsize != CHACHAPOLY_IV_SIZE) { -+ /* IPsec specific: CONTEXT1[223:128] = {NONCE, IV} */ -+ ctx_iv_off += 4; -+ -+ /* -+ * The associated data comes already with the IV but we need -+ * to skip it when we authenticate or encrypt... -+ */ -+ assoclen -= ivsize; -+ } -+ -+ append_math_add_imm_u32(desc, REG3, ZERO, IMM, assoclen); -+ -+ /* -+ * For IPsec load the IV further in the same register. -+ * For RFC7539 simply load the 12 bytes nonce in a single operation -+ */ -+ append_load_as_imm(desc, req->iv, ivsize, LDST_CLASS_1_CCB | -+ LDST_SRCDST_BYTE_CONTEXT | -+ ctx_iv_off << LDST_OFFSET_SHIFT); -+} -+ - static void init_authenc_job(struct aead_request *req, - struct aead_edesc *edesc, - bool all_contig, bool encrypt) -@@ -1032,6 +1157,7 @@ static void init_authenc_job(struct aead - struct caam_aead_alg, aead); - unsigned int ivsize = crypto_aead_ivsize(aead); - struct caam_ctx *ctx = crypto_aead_ctx(aead); -+ struct caam_drv_private *ctrlpriv = dev_get_drvdata(ctx->jrdev->parent); - const bool ctr_mode = ((ctx->cdata.algtype & OP_ALG_AAI_MASK) == - OP_ALG_AAI_CTR_MOD128); - const bool is_rfc3686 = alg->caam.rfc3686; -@@ -1055,6 +1181,15 @@ static void init_authenc_job(struct aead - - init_aead_job(req, edesc, all_contig, encrypt); - -+ /* -+ * {REG3, DPOVRD} = assoclen, depending on whether MATH command supports -+ * having DPOVRD as destination. -+ */ -+ if (ctrlpriv->era < 3) -+ append_math_add_imm_u32(desc, REG3, ZERO, IMM, req->assoclen); -+ else -+ append_math_add_imm_u32(desc, DPOVRD, ZERO, IMM, req->assoclen); -+ - if (ivsize && ((is_rfc3686 && encrypt) || !alg->caam.geniv)) - append_load_as_imm(desc, req->iv, ivsize, - LDST_CLASS_1_CCB | -@@ -1227,8 +1362,16 @@ static struct aead_edesc *aead_edesc_all - } - } - -+ /* -+ * HW reads 4 S/G entries at a time; make sure the reads don't go beyond -+ * the end of the table by allocating more S/G entries. -+ */ - sec4_sg_len = mapped_src_nents > 1 ? mapped_src_nents : 0; -- sec4_sg_len += mapped_dst_nents > 1 ? mapped_dst_nents : 0; -+ if (mapped_dst_nents > 1) -+ sec4_sg_len += ALIGN(mapped_dst_nents, 4); -+ else -+ sec4_sg_len = ALIGN(sec4_sg_len, 4); -+ - sec4_sg_bytes = sec4_sg_len * sizeof(struct sec4_sg_entry); - - /* allocate space for base edesc and hw desc commands, link tables */ -@@ -1309,6 +1452,72 @@ static int gcm_encrypt(struct aead_reque - return ret; - } - -+static int chachapoly_encrypt(struct aead_request *req) -+{ -+ struct aead_edesc *edesc; -+ struct crypto_aead *aead = crypto_aead_reqtfm(req); -+ struct caam_ctx *ctx = crypto_aead_ctx(aead); -+ struct device *jrdev = ctx->jrdev; -+ bool all_contig; -+ u32 *desc; -+ int ret; -+ -+ edesc = aead_edesc_alloc(req, CHACHAPOLY_DESC_JOB_IO_LEN, &all_contig, -+ true); -+ if (IS_ERR(edesc)) -+ return PTR_ERR(edesc); -+ -+ desc = edesc->hw_desc; -+ -+ init_chachapoly_job(req, edesc, all_contig, true); -+ print_hex_dump_debug("chachapoly jobdesc@" __stringify(__LINE__)": ", -+ DUMP_PREFIX_ADDRESS, 16, 4, desc, desc_bytes(desc), -+ 1); -+ -+ ret = caam_jr_enqueue(jrdev, desc, aead_encrypt_done, req); -+ if (!ret) { -+ ret = -EINPROGRESS; -+ } else { -+ aead_unmap(jrdev, edesc, req); -+ kfree(edesc); -+ } -+ -+ return ret; -+} -+ -+static int chachapoly_decrypt(struct aead_request *req) -+{ -+ struct aead_edesc *edesc; -+ struct crypto_aead *aead = crypto_aead_reqtfm(req); -+ struct caam_ctx *ctx = crypto_aead_ctx(aead); -+ struct device *jrdev = ctx->jrdev; -+ bool all_contig; -+ u32 *desc; -+ int ret; -+ -+ edesc = aead_edesc_alloc(req, CHACHAPOLY_DESC_JOB_IO_LEN, &all_contig, -+ false); -+ if (IS_ERR(edesc)) -+ return PTR_ERR(edesc); -+ -+ desc = edesc->hw_desc; -+ -+ init_chachapoly_job(req, edesc, all_contig, false); -+ print_hex_dump_debug("chachapoly jobdesc@" __stringify(__LINE__)": ", -+ DUMP_PREFIX_ADDRESS, 16, 4, desc, desc_bytes(desc), -+ 1); -+ -+ ret = caam_jr_enqueue(jrdev, desc, aead_decrypt_done, req); -+ if (!ret) { -+ ret = -EINPROGRESS; -+ } else { -+ aead_unmap(jrdev, edesc, req); -+ kfree(edesc); -+ } -+ -+ return ret; -+} -+ - static int ipsec_gcm_encrypt(struct aead_request *req) - { - if (req->assoclen < 8) -@@ -1496,7 +1705,25 @@ static struct ablkcipher_edesc *ablkciph - - sec4_sg_ents = 1 + mapped_src_nents; - dst_sg_idx = sec4_sg_ents; -- sec4_sg_ents += mapped_dst_nents > 1 ? mapped_dst_nents : 0; -+ -+ /* -+ * HW reads 4 S/G entries at a time; make sure the reads don't go beyond -+ * the end of the table by allocating more S/G entries. Logic: -+ * if (src != dst && output S/G) -+ * pad output S/G, if needed -+ * else if (src == dst && S/G) -+ * overlapping S/Gs; pad one of them -+ * else if (input S/G) ... -+ * pad input S/G, if needed -+ */ -+ if (mapped_dst_nents > 1) -+ sec4_sg_ents += ALIGN(mapped_dst_nents, 4); -+ else if ((req->src == req->dst) && (mapped_src_nents > 1)) -+ sec4_sg_ents = max(ALIGN(sec4_sg_ents, 4), -+ 1 + ALIGN(mapped_src_nents, 4)); -+ else -+ sec4_sg_ents = ALIGN(sec4_sg_ents, 4); -+ - sec4_sg_bytes = sec4_sg_ents * sizeof(struct sec4_sg_entry); - - /* -@@ -3199,6 +3426,50 @@ static struct caam_aead_alg driver_aeads - .geniv = true, - }, - }, -+ { -+ .aead = { -+ .base = { -+ .cra_name = "rfc7539(chacha20,poly1305)", -+ .cra_driver_name = "rfc7539-chacha20-poly1305-" -+ "caam", -+ .cra_blocksize = 1, -+ }, -+ .setkey = chachapoly_setkey, -+ .setauthsize = chachapoly_setauthsize, -+ .encrypt = chachapoly_encrypt, -+ .decrypt = chachapoly_decrypt, -+ .ivsize = CHACHAPOLY_IV_SIZE, -+ .maxauthsize = POLY1305_DIGEST_SIZE, -+ }, -+ .caam = { -+ .class1_alg_type = OP_ALG_ALGSEL_CHACHA20 | -+ OP_ALG_AAI_AEAD, -+ .class2_alg_type = OP_ALG_ALGSEL_POLY1305 | -+ OP_ALG_AAI_AEAD, -+ }, -+ }, -+ { -+ .aead = { -+ .base = { -+ .cra_name = "rfc7539esp(chacha20,poly1305)", -+ .cra_driver_name = "rfc7539esp-chacha20-" -+ "poly1305-caam", -+ .cra_blocksize = 1, -+ }, -+ .setkey = chachapoly_setkey, -+ .setauthsize = chachapoly_setauthsize, -+ .encrypt = chachapoly_encrypt, -+ .decrypt = chachapoly_decrypt, -+ .ivsize = 8, -+ .maxauthsize = POLY1305_DIGEST_SIZE, -+ }, -+ .caam = { -+ .class1_alg_type = OP_ALG_ALGSEL_CHACHA20 | -+ OP_ALG_AAI_AEAD, -+ .class2_alg_type = OP_ALG_ALGSEL_POLY1305 | -+ OP_ALG_AAI_AEAD, -+ }, -+ }, - }; - - struct caam_crypto_alg { -@@ -3207,9 +3478,11 @@ struct caam_crypto_alg { - struct caam_alg_entry caam; - }; - --static int caam_init_common(struct caam_ctx *ctx, struct caam_alg_entry *caam) -+static int caam_init_common(struct caam_ctx *ctx, struct caam_alg_entry *caam, -+ bool uses_dkp) - { - dma_addr_t dma_addr; -+ struct caam_drv_private *priv; - - ctx->jrdev = caam_jr_alloc(); - if (IS_ERR(ctx->jrdev)) { -@@ -3217,10 +3490,16 @@ static int caam_init_common(struct caam_ - return PTR_ERR(ctx->jrdev); - } - -+ priv = dev_get_drvdata(ctx->jrdev->parent); -+ if (priv->era >= 6 && uses_dkp) -+ ctx->dir = DMA_BIDIRECTIONAL; -+ else -+ ctx->dir = DMA_TO_DEVICE; -+ - dma_addr = dma_map_single_attrs(ctx->jrdev, ctx->sh_desc_enc, - offsetof(struct caam_ctx, - sh_desc_enc_dma), -- DMA_TO_DEVICE, DMA_ATTR_SKIP_CPU_SYNC); -+ ctx->dir, DMA_ATTR_SKIP_CPU_SYNC); - if (dma_mapping_error(ctx->jrdev, dma_addr)) { - dev_err(ctx->jrdev, "unable to map key, shared descriptors\n"); - caam_jr_free(ctx->jrdev); -@@ -3248,7 +3527,7 @@ static int caam_cra_init(struct crypto_t - container_of(alg, struct caam_crypto_alg, crypto_alg); - struct caam_ctx *ctx = crypto_tfm_ctx(tfm); - -- return caam_init_common(ctx, &caam_alg->caam); -+ return caam_init_common(ctx, &caam_alg->caam, false); - } - - static int caam_aead_init(struct crypto_aead *tfm) -@@ -3258,14 +3537,15 @@ static int caam_aead_init(struct crypto_ - container_of(alg, struct caam_aead_alg, aead); - struct caam_ctx *ctx = crypto_aead_ctx(tfm); - -- return caam_init_common(ctx, &caam_alg->caam); -+ return caam_init_common(ctx, &caam_alg->caam, -+ alg->setkey == aead_setkey); - } - - static void caam_exit_common(struct caam_ctx *ctx) - { - dma_unmap_single_attrs(ctx->jrdev, ctx->sh_desc_enc_dma, - offsetof(struct caam_ctx, sh_desc_enc_dma), -- DMA_TO_DEVICE, DMA_ATTR_SKIP_CPU_SYNC); -+ ctx->dir, DMA_ATTR_SKIP_CPU_SYNC); - caam_jr_free(ctx->jrdev); - } - -@@ -3279,7 +3559,7 @@ static void caam_aead_exit(struct crypto - caam_exit_common(crypto_aead_ctx(tfm)); - } - --static void __exit caam_algapi_exit(void) -+void caam_algapi_exit(void) - { - - struct caam_crypto_alg *t_alg, *n; -@@ -3358,56 +3638,52 @@ static void caam_aead_alg_init(struct ca - alg->exit = caam_aead_exit; - } - --static int __init caam_algapi_init(void) -+int caam_algapi_init(struct device *ctrldev) - { -- struct device_node *dev_node; -- struct platform_device *pdev; -- struct device *ctrldev; -- struct caam_drv_private *priv; -+ struct caam_drv_private *priv = dev_get_drvdata(ctrldev); - int i = 0, err = 0; -- u32 cha_vid, cha_inst, des_inst, aes_inst, md_inst; -+ u32 aes_vid, aes_inst, des_inst, md_vid, md_inst, ccha_inst, ptha_inst; - unsigned int md_limit = SHA512_DIGEST_SIZE; - bool registered = false; - -- dev_node = of_find_compatible_node(NULL, NULL, "fsl,sec-v4.0"); -- if (!dev_node) { -- dev_node = of_find_compatible_node(NULL, NULL, "fsl,sec4.0"); -- if (!dev_node) -- return -ENODEV; -- } -- -- pdev = of_find_device_by_node(dev_node); -- if (!pdev) { -- of_node_put(dev_node); -- return -ENODEV; -- } -- -- ctrldev = &pdev->dev; -- priv = dev_get_drvdata(ctrldev); -- of_node_put(dev_node); -- -- /* -- * If priv is NULL, it's probably because the caam driver wasn't -- * properly initialized (e.g. RNG4 init failed). Thus, bail out here. -- */ -- if (!priv) -- return -ENODEV; -- -- - INIT_LIST_HEAD(&alg_list); - - /* - * Register crypto algorithms the device supports. - * First, detect presence and attributes of DES, AES, and MD blocks. - */ -- cha_vid = rd_reg32(&priv->ctrl->perfmon.cha_id_ls); -- cha_inst = rd_reg32(&priv->ctrl->perfmon.cha_num_ls); -- des_inst = (cha_inst & CHA_ID_LS_DES_MASK) >> CHA_ID_LS_DES_SHIFT; -- aes_inst = (cha_inst & CHA_ID_LS_AES_MASK) >> CHA_ID_LS_AES_SHIFT; -- md_inst = (cha_inst & CHA_ID_LS_MD_MASK) >> CHA_ID_LS_MD_SHIFT; -+ if (priv->era < 10) { -+ u32 cha_vid, cha_inst; -+ -+ cha_vid = rd_reg32(&priv->ctrl->perfmon.cha_id_ls); -+ aes_vid = cha_vid & CHA_ID_LS_AES_MASK; -+ md_vid = (cha_vid & CHA_ID_LS_MD_MASK) >> CHA_ID_LS_MD_SHIFT; -+ -+ cha_inst = rd_reg32(&priv->ctrl->perfmon.cha_num_ls); -+ des_inst = (cha_inst & CHA_ID_LS_DES_MASK) >> -+ CHA_ID_LS_DES_SHIFT; -+ aes_inst = cha_inst & CHA_ID_LS_AES_MASK; -+ md_inst = (cha_inst & CHA_ID_LS_MD_MASK) >> CHA_ID_LS_MD_SHIFT; -+ ccha_inst = 0; -+ ptha_inst = 0; -+ } else { -+ u32 aesa, mdha; -+ -+ aesa = rd_reg32(&priv->ctrl->vreg.aesa); -+ mdha = rd_reg32(&priv->ctrl->vreg.mdha); -+ -+ aes_vid = (aesa & CHA_VER_VID_MASK) >> CHA_VER_VID_SHIFT; -+ md_vid = (mdha & CHA_VER_VID_MASK) >> CHA_VER_VID_SHIFT; -+ -+ des_inst = rd_reg32(&priv->ctrl->vreg.desa) & CHA_VER_NUM_MASK; -+ aes_inst = aesa & CHA_VER_NUM_MASK; -+ md_inst = mdha & CHA_VER_NUM_MASK; -+ ccha_inst = rd_reg32(&priv->ctrl->vreg.ccha) & CHA_VER_NUM_MASK; -+ ptha_inst = rd_reg32(&priv->ctrl->vreg.ptha) & CHA_VER_NUM_MASK; -+ } - - /* If MD is present, limit digest size based on LP256 */ -- if (md_inst && ((cha_vid & CHA_ID_LS_MD_MASK) == CHA_ID_LS_MD_LP256)) -+ if (md_inst && md_vid == CHA_VER_VID_MD_LP256) - md_limit = SHA256_DIGEST_SIZE; - - for (i = 0; i < ARRAY_SIZE(driver_algs); i++) { -@@ -3429,10 +3705,10 @@ static int __init caam_algapi_init(void) - * Check support for AES modes not available - * on LP devices. - */ -- if ((cha_vid & CHA_ID_LS_AES_MASK) == CHA_ID_LS_AES_LP) -- if ((alg->class1_alg_type & OP_ALG_AAI_MASK) == -- OP_ALG_AAI_XTS) -- continue; -+ if (aes_vid == CHA_VER_VID_AES_LP && -+ (alg->class1_alg_type & OP_ALG_AAI_MASK) == -+ OP_ALG_AAI_XTS) -+ continue; - - t_alg = caam_alg_alloc(alg); - if (IS_ERR(t_alg)) { -@@ -3471,21 +3747,28 @@ static int __init caam_algapi_init(void) - if (!aes_inst && (c1_alg_sel == OP_ALG_ALGSEL_AES)) - continue; - -+ /* Skip CHACHA20 algorithms if not supported by device */ -+ if (c1_alg_sel == OP_ALG_ALGSEL_CHACHA20 && !ccha_inst) -+ continue; -+ -+ /* Skip POLY1305 algorithms if not supported by device */ -+ if (c2_alg_sel == OP_ALG_ALGSEL_POLY1305 && !ptha_inst) -+ continue; -+ - /* - * Check support for AES algorithms not available - * on LP devices. - */ -- if ((cha_vid & CHA_ID_LS_AES_MASK) == CHA_ID_LS_AES_LP) -- if (alg_aai == OP_ALG_AAI_GCM) -- continue; -+ if (aes_vid == CHA_VER_VID_AES_LP && alg_aai == OP_ALG_AAI_GCM) -+ continue; - - /* - * Skip algorithms requiring message digests - * if MD or MD size is not supported by device. - */ -- if (c2_alg_sel && -- (!md_inst || (t_alg->aead.maxauthsize > md_limit))) -- continue; -+ if ((c2_alg_sel & ~OP_ALG_ALGSEL_SUBMASK) == 0x40 && -+ (!md_inst || t_alg->aead.maxauthsize > md_limit)) -+ continue; - - caam_aead_alg_init(t_alg); - -@@ -3505,10 +3788,3 @@ static int __init caam_algapi_init(void) - - return err; - } -- --module_init(caam_algapi_init); --module_exit(caam_algapi_exit); -- --MODULE_LICENSE("GPL"); --MODULE_DESCRIPTION("FSL CAAM support for crypto API"); --MODULE_AUTHOR("Freescale Semiconductor - NMG/STC"); ---- a/drivers/crypto/caam/caamalg_desc.c -+++ b/drivers/crypto/caam/caamalg_desc.c -@@ -45,16 +45,16 @@ static inline void append_dec_op1(u32 *d - * cnstr_shdsc_aead_null_encap - IPSec ESP encapsulation shared descriptor - * (non-protocol) with no (null) encryption. - * @desc: pointer to buffer used for descriptor construction -- * @adata: pointer to authentication transform definitions. Note that since a -- * split key is to be used, the size of the split key itself is -- * specified. Valid algorithm values - one of OP_ALG_ALGSEL_{MD5, SHA1, -- * SHA224, SHA256, SHA384, SHA512} ANDed with OP_ALG_AAI_HMAC_PRECOMP. -+ * @adata: pointer to authentication transform definitions. -+ * A split key is required for SEC Era < 6; the size of the split key -+ * is specified in this case. Valid algorithm values - one of -+ * OP_ALG_ALGSEL_{MD5, SHA1, SHA224, SHA256, SHA384, SHA512} ANDed -+ * with OP_ALG_AAI_HMAC_PRECOMP. - * @icvsize: integrity check value (ICV) size (truncated or full) -- * -- * Note: Requires an MDHA split key. -+ * @era: SEC Era - */ - void cnstr_shdsc_aead_null_encap(u32 * const desc, struct alginfo *adata, -- unsigned int icvsize) -+ unsigned int icvsize, int era) - { - u32 *key_jump_cmd, *read_move_cmd, *write_move_cmd; - -@@ -63,13 +63,18 @@ void cnstr_shdsc_aead_null_encap(u32 * c - /* Skip if already shared */ - key_jump_cmd = append_jump(desc, JUMP_JSL | JUMP_TEST_ALL | - JUMP_COND_SHRD); -- if (adata->key_inline) -- append_key_as_imm(desc, adata->key_virt, adata->keylen_pad, -- adata->keylen, CLASS_2 | KEY_DEST_MDHA_SPLIT | -- KEY_ENC); -- else -- append_key(desc, adata->key_dma, adata->keylen, CLASS_2 | -- KEY_DEST_MDHA_SPLIT | KEY_ENC); -+ if (era < 6) { -+ if (adata->key_inline) -+ append_key_as_imm(desc, adata->key_virt, -+ adata->keylen_pad, adata->keylen, -+ CLASS_2 | KEY_DEST_MDHA_SPLIT | -+ KEY_ENC); -+ else -+ append_key(desc, adata->key_dma, adata->keylen, -+ CLASS_2 | KEY_DEST_MDHA_SPLIT | KEY_ENC); -+ } else { -+ append_proto_dkp(desc, adata); -+ } - set_jump_tgt_here(desc, key_jump_cmd); - - /* assoclen + cryptlen = seqinlen */ -@@ -121,16 +126,16 @@ EXPORT_SYMBOL(cnstr_shdsc_aead_null_enca - * cnstr_shdsc_aead_null_decap - IPSec ESP decapsulation shared descriptor - * (non-protocol) with no (null) decryption. - * @desc: pointer to buffer used for descriptor construction -- * @adata: pointer to authentication transform definitions. Note that since a -- * split key is to be used, the size of the split key itself is -- * specified. Valid algorithm values - one of OP_ALG_ALGSEL_{MD5, SHA1, -- * SHA224, SHA256, SHA384, SHA512} ANDed with OP_ALG_AAI_HMAC_PRECOMP. -+ * @adata: pointer to authentication transform definitions. -+ * A split key is required for SEC Era < 6; the size of the split key -+ * is specified in this case. Valid algorithm values - one of -+ * OP_ALG_ALGSEL_{MD5, SHA1, SHA224, SHA256, SHA384, SHA512} ANDed -+ * with OP_ALG_AAI_HMAC_PRECOMP. - * @icvsize: integrity check value (ICV) size (truncated or full) -- * -- * Note: Requires an MDHA split key. -+ * @era: SEC Era - */ - void cnstr_shdsc_aead_null_decap(u32 * const desc, struct alginfo *adata, -- unsigned int icvsize) -+ unsigned int icvsize, int era) - { - u32 *key_jump_cmd, *read_move_cmd, *write_move_cmd, *jump_cmd; - -@@ -139,13 +144,18 @@ void cnstr_shdsc_aead_null_decap(u32 * c - /* Skip if already shared */ - key_jump_cmd = append_jump(desc, JUMP_JSL | JUMP_TEST_ALL | - JUMP_COND_SHRD); -- if (adata->key_inline) -- append_key_as_imm(desc, adata->key_virt, adata->keylen_pad, -- adata->keylen, CLASS_2 | -- KEY_DEST_MDHA_SPLIT | KEY_ENC); -- else -- append_key(desc, adata->key_dma, adata->keylen, CLASS_2 | -- KEY_DEST_MDHA_SPLIT | KEY_ENC); -+ if (era < 6) { -+ if (adata->key_inline) -+ append_key_as_imm(desc, adata->key_virt, -+ adata->keylen_pad, adata->keylen, -+ CLASS_2 | KEY_DEST_MDHA_SPLIT | -+ KEY_ENC); -+ else -+ append_key(desc, adata->key_dma, adata->keylen, -+ CLASS_2 | KEY_DEST_MDHA_SPLIT | KEY_ENC); -+ } else { -+ append_proto_dkp(desc, adata); -+ } - set_jump_tgt_here(desc, key_jump_cmd); - - /* Class 2 operation */ -@@ -204,7 +214,7 @@ EXPORT_SYMBOL(cnstr_shdsc_aead_null_deca - static void init_sh_desc_key_aead(u32 * const desc, - struct alginfo * const cdata, - struct alginfo * const adata, -- const bool is_rfc3686, u32 *nonce) -+ const bool is_rfc3686, u32 *nonce, int era) - { - u32 *key_jump_cmd; - unsigned int enckeylen = cdata->keylen; -@@ -224,13 +234,18 @@ static void init_sh_desc_key_aead(u32 * - if (is_rfc3686) - enckeylen -= CTR_RFC3686_NONCE_SIZE; - -- if (adata->key_inline) -- append_key_as_imm(desc, adata->key_virt, adata->keylen_pad, -- adata->keylen, CLASS_2 | -- KEY_DEST_MDHA_SPLIT | KEY_ENC); -- else -- append_key(desc, adata->key_dma, adata->keylen, CLASS_2 | -- KEY_DEST_MDHA_SPLIT | KEY_ENC); -+ if (era < 6) { -+ if (adata->key_inline) -+ append_key_as_imm(desc, adata->key_virt, -+ adata->keylen_pad, adata->keylen, -+ CLASS_2 | KEY_DEST_MDHA_SPLIT | -+ KEY_ENC); -+ else -+ append_key(desc, adata->key_dma, adata->keylen, -+ CLASS_2 | KEY_DEST_MDHA_SPLIT | KEY_ENC); -+ } else { -+ append_proto_dkp(desc, adata); -+ } - - if (cdata->key_inline) - append_key_as_imm(desc, cdata->key_virt, enckeylen, -@@ -261,26 +276,27 @@ static void init_sh_desc_key_aead(u32 * - * @cdata: pointer to block cipher transform definitions - * Valid algorithm values - one of OP_ALG_ALGSEL_{AES, DES, 3DES} ANDed - * with OP_ALG_AAI_CBC or OP_ALG_AAI_CTR_MOD128. -- * @adata: pointer to authentication transform definitions. Note that since a -- * split key is to be used, the size of the split key itself is -- * specified. Valid algorithm values - one of OP_ALG_ALGSEL_{MD5, SHA1, -- * SHA224, SHA256, SHA384, SHA512} ANDed with OP_ALG_AAI_HMAC_PRECOMP. -+ * @adata: pointer to authentication transform definitions. -+ * A split key is required for SEC Era < 6; the size of the split key -+ * is specified in this case. Valid algorithm values - one of -+ * OP_ALG_ALGSEL_{MD5, SHA1, SHA224, SHA256, SHA384, SHA512} ANDed -+ * with OP_ALG_AAI_HMAC_PRECOMP. - * @ivsize: initialization vector size - * @icvsize: integrity check value (ICV) size (truncated or full) - * @is_rfc3686: true when ctr(aes) is wrapped by rfc3686 template - * @nonce: pointer to rfc3686 nonce - * @ctx1_iv_off: IV offset in CONTEXT1 register - * @is_qi: true when called from caam/qi -- * -- * Note: Requires an MDHA split key. -+ * @era: SEC Era - */ - void cnstr_shdsc_aead_encap(u32 * const desc, struct alginfo *cdata, - struct alginfo *adata, unsigned int ivsize, - unsigned int icvsize, const bool is_rfc3686, -- u32 *nonce, const u32 ctx1_iv_off, const bool is_qi) -+ u32 *nonce, const u32 ctx1_iv_off, const bool is_qi, -+ int era) - { - /* Note: Context registers are saved. */ -- init_sh_desc_key_aead(desc, cdata, adata, is_rfc3686, nonce); -+ init_sh_desc_key_aead(desc, cdata, adata, is_rfc3686, nonce, era); - - /* Class 2 operation */ - append_operation(desc, adata->algtype | OP_ALG_AS_INITFINAL | -@@ -306,8 +322,13 @@ void cnstr_shdsc_aead_encap(u32 * const - } - - /* Read and write assoclen bytes */ -- append_math_add(desc, VARSEQINLEN, ZERO, REG3, CAAM_CMD_SZ); -- append_math_add(desc, VARSEQOUTLEN, ZERO, REG3, CAAM_CMD_SZ); -+ if (is_qi || era < 3) { -+ append_math_add(desc, VARSEQINLEN, ZERO, REG3, CAAM_CMD_SZ); -+ append_math_add(desc, VARSEQOUTLEN, ZERO, REG3, CAAM_CMD_SZ); -+ } else { -+ append_math_add(desc, VARSEQINLEN, ZERO, DPOVRD, CAAM_CMD_SZ); -+ append_math_add(desc, VARSEQOUTLEN, ZERO, DPOVRD, CAAM_CMD_SZ); -+ } - - /* Skip assoc data */ - append_seq_fifo_store(desc, 0, FIFOST_TYPE_SKIP | FIFOLDST_VLF); -@@ -350,27 +371,27 @@ EXPORT_SYMBOL(cnstr_shdsc_aead_encap); - * @cdata: pointer to block cipher transform definitions - * Valid algorithm values - one of OP_ALG_ALGSEL_{AES, DES, 3DES} ANDed - * with OP_ALG_AAI_CBC or OP_ALG_AAI_CTR_MOD128. -- * @adata: pointer to authentication transform definitions. Note that since a -- * split key is to be used, the size of the split key itself is -- * specified. Valid algorithm values - one of OP_ALG_ALGSEL_{MD5, SHA1, -- * SHA224, SHA256, SHA384, SHA512} ANDed with OP_ALG_AAI_HMAC_PRECOMP. -+ * @adata: pointer to authentication transform definitions. -+ * A split key is required for SEC Era < 6; the size of the split key -+ * is specified in this case. Valid algorithm values - one of -+ * OP_ALG_ALGSEL_{MD5, SHA1, SHA224, SHA256, SHA384, SHA512} ANDed -+ * with OP_ALG_AAI_HMAC_PRECOMP. - * @ivsize: initialization vector size - * @icvsize: integrity check value (ICV) size (truncated or full) - * @is_rfc3686: true when ctr(aes) is wrapped by rfc3686 template - * @nonce: pointer to rfc3686 nonce - * @ctx1_iv_off: IV offset in CONTEXT1 register - * @is_qi: true when called from caam/qi -- * -- * Note: Requires an MDHA split key. -+ * @era: SEC Era - */ - void cnstr_shdsc_aead_decap(u32 * const desc, struct alginfo *cdata, - struct alginfo *adata, unsigned int ivsize, - unsigned int icvsize, const bool geniv, - const bool is_rfc3686, u32 *nonce, -- const u32 ctx1_iv_off, const bool is_qi) -+ const u32 ctx1_iv_off, const bool is_qi, int era) - { - /* Note: Context registers are saved. */ -- init_sh_desc_key_aead(desc, cdata, adata, is_rfc3686, nonce); -+ init_sh_desc_key_aead(desc, cdata, adata, is_rfc3686, nonce, era); - - /* Class 2 operation */ - append_operation(desc, adata->algtype | OP_ALG_AS_INITFINAL | -@@ -397,11 +418,23 @@ void cnstr_shdsc_aead_decap(u32 * const - } - - /* Read and write assoclen bytes */ -- append_math_add(desc, VARSEQINLEN, ZERO, REG3, CAAM_CMD_SZ); -- if (geniv) -- append_math_add_imm_u32(desc, VARSEQOUTLEN, REG3, IMM, ivsize); -- else -- append_math_add(desc, VARSEQOUTLEN, ZERO, REG3, CAAM_CMD_SZ); -+ if (is_qi || era < 3) { -+ append_math_add(desc, VARSEQINLEN, ZERO, REG3, CAAM_CMD_SZ); -+ if (geniv) -+ append_math_add_imm_u32(desc, VARSEQOUTLEN, REG3, IMM, -+ ivsize); -+ else -+ append_math_add(desc, VARSEQOUTLEN, ZERO, REG3, -+ CAAM_CMD_SZ); -+ } else { -+ append_math_add(desc, VARSEQINLEN, ZERO, DPOVRD, CAAM_CMD_SZ); -+ if (geniv) -+ append_math_add_imm_u32(desc, VARSEQOUTLEN, DPOVRD, IMM, -+ ivsize); -+ else -+ append_math_add(desc, VARSEQOUTLEN, ZERO, DPOVRD, -+ CAAM_CMD_SZ); -+ } - - /* Skip assoc data */ - append_seq_fifo_store(desc, 0, FIFOST_TYPE_SKIP | FIFOLDST_VLF); -@@ -456,30 +489,29 @@ EXPORT_SYMBOL(cnstr_shdsc_aead_decap); - * @cdata: pointer to block cipher transform definitions - * Valid algorithm values - one of OP_ALG_ALGSEL_{AES, DES, 3DES} ANDed - * with OP_ALG_AAI_CBC or OP_ALG_AAI_CTR_MOD128. -- * @adata: pointer to authentication transform definitions. Note that since a -- * split key is to be used, the size of the split key itself is -- * specified. Valid algorithm values - one of OP_ALG_ALGSEL_{MD5, SHA1, -- * SHA224, SHA256, SHA384, SHA512} ANDed with OP_ALG_AAI_HMAC_PRECOMP. -- * @ivsize: initialization vector size -+ * @adata: pointer to authentication transform definitions. -+ * A split key is required for SEC Era < 6; the size of the split key -+ * is specified in this case. Valid algorithm values - one of -+ * OP_ALG_ALGSEL_{MD5, SHA1, SHA224, SHA256, SHA384, SHA512} ANDed -+ * with OP_ALG_AAI_HMAC_PRECOMP. * @ivsize: initialization vector size - * @icvsize: integrity check value (ICV) size (truncated or full) - * @is_rfc3686: true when ctr(aes) is wrapped by rfc3686 template - * @nonce: pointer to rfc3686 nonce - * @ctx1_iv_off: IV offset in CONTEXT1 register - * @is_qi: true when called from caam/qi -- * -- * Note: Requires an MDHA split key. -+ * @era: SEC Era - */ - void cnstr_shdsc_aead_givencap(u32 * const desc, struct alginfo *cdata, - struct alginfo *adata, unsigned int ivsize, - unsigned int icvsize, const bool is_rfc3686, - u32 *nonce, const u32 ctx1_iv_off, -- const bool is_qi) -+ const bool is_qi, int era) - { - u32 geniv, moveiv; - u32 *wait_cmd; - - /* Note: Context registers are saved. */ -- init_sh_desc_key_aead(desc, cdata, adata, is_rfc3686, nonce); -+ init_sh_desc_key_aead(desc, cdata, adata, is_rfc3686, nonce, era); - - if (is_qi) { - u32 *wait_load_cmd; -@@ -529,8 +561,13 @@ copy_iv: - OP_ALG_ENCRYPT); - - /* Read and write assoclen bytes */ -- append_math_add(desc, VARSEQINLEN, ZERO, REG3, CAAM_CMD_SZ); -- append_math_add(desc, VARSEQOUTLEN, ZERO, REG3, CAAM_CMD_SZ); -+ if (is_qi || era < 3) { -+ append_math_add(desc, VARSEQINLEN, ZERO, REG3, CAAM_CMD_SZ); -+ append_math_add(desc, VARSEQOUTLEN, ZERO, REG3, CAAM_CMD_SZ); -+ } else { -+ append_math_add(desc, VARSEQINLEN, ZERO, DPOVRD, CAAM_CMD_SZ); -+ append_math_add(desc, VARSEQOUTLEN, ZERO, DPOVRD, CAAM_CMD_SZ); -+ } - - /* Skip assoc data */ - append_seq_fifo_store(desc, 0, FIFOST_TYPE_SKIP | FIFOLDST_VLF); -@@ -592,14 +629,431 @@ copy_iv: - EXPORT_SYMBOL(cnstr_shdsc_aead_givencap); - - /** -+ * cnstr_shdsc_tls_encap - tls encapsulation shared descriptor -+ * @desc: pointer to buffer used for descriptor construction -+ * @cdata: pointer to block cipher transform definitions -+ * Valid algorithm values - one of OP_ALG_ALGSEL_AES ANDed -+ * with OP_ALG_AAI_CBC -+ * @adata: pointer to authentication transform definitions. -+ * A split key is required for SEC Era < 6; the size of the split key -+ * is specified in this case. Valid algorithm values OP_ALG_ALGSEL_SHA1 -+ * ANDed with OP_ALG_AAI_HMAC_PRECOMP. -+ * @assoclen: associated data length -+ * @ivsize: initialization vector size -+ * @authsize: authentication data size -+ * @blocksize: block cipher size -+ * @era: SEC Era -+ */ -+void cnstr_shdsc_tls_encap(u32 * const desc, struct alginfo *cdata, -+ struct alginfo *adata, unsigned int assoclen, -+ unsigned int ivsize, unsigned int authsize, -+ unsigned int blocksize, int era) -+{ -+ u32 *key_jump_cmd, *zero_payload_jump_cmd; -+ u32 genpad, idx_ld_datasz, idx_ld_pad, stidx; -+ -+ /* -+ * Compute the index (in bytes) for the LOAD with destination of -+ * Class 1 Data Size Register and for the LOAD that generates padding -+ */ -+ if (adata->key_inline) { -+ idx_ld_datasz = DESC_TLS10_ENC_LEN + adata->keylen_pad + -+ cdata->keylen - 4 * CAAM_CMD_SZ; -+ idx_ld_pad = DESC_TLS10_ENC_LEN + adata->keylen_pad + -+ cdata->keylen - 2 * CAAM_CMD_SZ; -+ } else { -+ idx_ld_datasz = DESC_TLS10_ENC_LEN + 2 * CAAM_PTR_SZ - -+ 4 * CAAM_CMD_SZ; -+ idx_ld_pad = DESC_TLS10_ENC_LEN + 2 * CAAM_PTR_SZ - -+ 2 * CAAM_CMD_SZ; -+ } -+ -+ stidx = 1 << HDR_START_IDX_SHIFT; -+ init_sh_desc(desc, HDR_SHARE_SERIAL | stidx); -+ -+ /* skip key loading if they are loaded due to sharing */ -+ key_jump_cmd = append_jump(desc, JUMP_JSL | JUMP_TEST_ALL | -+ JUMP_COND_SHRD); -+ -+ if (era < 6) { -+ if (adata->key_inline) -+ append_key_as_imm(desc, adata->key_virt, -+ adata->keylen_pad, adata->keylen, -+ CLASS_2 | KEY_DEST_MDHA_SPLIT | -+ KEY_ENC); -+ else -+ append_key(desc, adata->key_dma, adata->keylen, -+ CLASS_2 | KEY_DEST_MDHA_SPLIT | KEY_ENC); -+ } else { -+ append_proto_dkp(desc, adata); -+ } -+ -+ if (cdata->key_inline) -+ append_key_as_imm(desc, cdata->key_virt, cdata->keylen, -+ cdata->keylen, CLASS_1 | KEY_DEST_CLASS_REG); -+ else -+ append_key(desc, cdata->key_dma, cdata->keylen, CLASS_1 | -+ KEY_DEST_CLASS_REG); -+ -+ set_jump_tgt_here(desc, key_jump_cmd); -+ -+ /* class 2 operation */ -+ append_operation(desc, adata->algtype | OP_ALG_AS_INITFINAL | -+ OP_ALG_ENCRYPT); -+ /* class 1 operation */ -+ append_operation(desc, cdata->algtype | OP_ALG_AS_INITFINAL | -+ OP_ALG_ENCRYPT); -+ -+ /* payloadlen = input data length - (assoclen + ivlen) */ -+ append_math_sub_imm_u32(desc, REG0, SEQINLEN, IMM, assoclen + ivsize); -+ -+ /* math1 = payloadlen + icvlen */ -+ append_math_add_imm_u32(desc, REG1, REG0, IMM, authsize); -+ -+ /* padlen = block_size - math1 % block_size */ -+ append_math_and_imm_u32(desc, REG3, REG1, IMM, blocksize - 1); -+ append_math_sub_imm_u32(desc, REG2, IMM, REG3, blocksize); -+ -+ /* cryptlen = payloadlen + icvlen + padlen */ -+ append_math_add(desc, VARSEQOUTLEN, REG1, REG2, 4); -+ -+ /* -+ * update immediate data with the padding length value -+ * for the LOAD in the class 1 data size register. -+ */ -+ append_move(desc, MOVE_SRC_DESCBUF | MOVE_DEST_MATH2 | -+ (idx_ld_datasz << MOVE_OFFSET_SHIFT) | 7); -+ append_move(desc, MOVE_WAITCOMP | MOVE_SRC_MATH2 | MOVE_DEST_DESCBUF | -+ (idx_ld_datasz << MOVE_OFFSET_SHIFT) | 8); -+ -+ /* overwrite PL field for the padding iNFO FIFO entry */ -+ append_move(desc, MOVE_SRC_DESCBUF | MOVE_DEST_MATH2 | -+ (idx_ld_pad << MOVE_OFFSET_SHIFT) | 7); -+ append_move(desc, MOVE_WAITCOMP | MOVE_SRC_MATH2 | MOVE_DEST_DESCBUF | -+ (idx_ld_pad << MOVE_OFFSET_SHIFT) | 8); -+ -+ /* store encrypted payload, icv and padding */ -+ append_seq_fifo_store(desc, 0, FIFOST_TYPE_MESSAGE_DATA | LDST_VLF); -+ -+ /* if payload length is zero, jump to zero-payload commands */ -+ append_math_add(desc, VARSEQINLEN, ZERO, REG0, 4); -+ zero_payload_jump_cmd = append_jump(desc, JUMP_TEST_ALL | -+ JUMP_COND_MATH_Z); -+ -+ /* load iv in context1 */ -+ append_cmd(desc, CMD_SEQ_LOAD | LDST_SRCDST_WORD_CLASS_CTX | -+ LDST_CLASS_1_CCB | ivsize); -+ -+ /* read assoc for authentication */ -+ append_seq_fifo_load(desc, assoclen, FIFOLD_CLASS_CLASS2 | -+ FIFOLD_TYPE_MSG); -+ /* insnoop payload */ -+ append_seq_fifo_load(desc, 0, FIFOLD_CLASS_BOTH | FIFOLD_TYPE_MSG | -+ FIFOLD_TYPE_LAST2 | FIFOLDST_VLF); -+ -+ /* jump the zero-payload commands */ -+ append_jump(desc, JUMP_TEST_ALL | 3); -+ -+ /* zero-payload commands */ -+ set_jump_tgt_here(desc, zero_payload_jump_cmd); -+ -+ /* load iv in context1 */ -+ append_cmd(desc, CMD_SEQ_LOAD | LDST_SRCDST_WORD_CLASS_CTX | -+ LDST_CLASS_1_CCB | ivsize); -+ -+ /* assoc data is the only data for authentication */ -+ append_seq_fifo_load(desc, assoclen, FIFOLD_CLASS_CLASS2 | -+ FIFOLD_TYPE_MSG | FIFOLD_TYPE_LAST2); -+ -+ /* send icv to encryption */ -+ append_move(desc, MOVE_SRC_CLASS2CTX | MOVE_DEST_CLASS1INFIFO | -+ authsize); -+ -+ /* update class 1 data size register with padding length */ -+ append_load_imm_u32(desc, 0, LDST_CLASS_1_CCB | -+ LDST_SRCDST_WORD_DATASZ_REG | LDST_IMM); -+ -+ /* generate padding and send it to encryption */ -+ genpad = NFIFOENTRY_DEST_CLASS1 | NFIFOENTRY_LC1 | NFIFOENTRY_FC1 | -+ NFIFOENTRY_STYPE_PAD | NFIFOENTRY_DTYPE_MSG | NFIFOENTRY_PTYPE_N; -+ append_load_imm_u32(desc, genpad, LDST_CLASS_IND_CCB | -+ LDST_SRCDST_WORD_INFO_FIFO | LDST_IMM); -+ -+#ifdef DEBUG -+ print_hex_dump(KERN_ERR, "tls enc shdesc@" __stringify(__LINE__) ": ", -+ DUMP_PREFIX_ADDRESS, 16, 4, desc, -+ desc_bytes(desc), 1); -+#endif -+} -+EXPORT_SYMBOL(cnstr_shdsc_tls_encap); -+ -+/** -+ * cnstr_shdsc_tls_decap - tls decapsulation shared descriptor -+ * @desc: pointer to buffer used for descriptor construction -+ * @cdata: pointer to block cipher transform definitions -+ * Valid algorithm values - one of OP_ALG_ALGSEL_AES ANDed -+ * with OP_ALG_AAI_CBC -+ * @adata: pointer to authentication transform definitions. -+ * A split key is required for SEC Era < 6; the size of the split key -+ * is specified in this case. Valid algorithm values OP_ALG_ALGSEL_SHA1 -+ * ANDed with OP_ALG_AAI_HMAC_PRECOMP. -+ * @assoclen: associated data length -+ * @ivsize: initialization vector size -+ * @authsize: authentication data size -+ * @blocksize: block cipher size -+ * @era: SEC Era -+ */ -+void cnstr_shdsc_tls_decap(u32 * const desc, struct alginfo *cdata, -+ struct alginfo *adata, unsigned int assoclen, -+ unsigned int ivsize, unsigned int authsize, -+ unsigned int blocksize, int era) -+{ -+ u32 stidx, jumpback; -+ u32 *key_jump_cmd, *zero_payload_jump_cmd, *skip_zero_jump_cmd; -+ /* -+ * Pointer Size bool determines the size of address pointers. -+ * false - Pointers fit in one 32-bit word. -+ * true - Pointers fit in two 32-bit words. -+ */ -+ static const bool ps = (CAAM_PTR_SZ != CAAM_CMD_SZ); -+ -+ stidx = 1 << HDR_START_IDX_SHIFT; -+ init_sh_desc(desc, HDR_SHARE_SERIAL | stidx); -+ -+ /* skip key loading if they are loaded due to sharing */ -+ key_jump_cmd = append_jump(desc, JUMP_JSL | JUMP_TEST_ALL | -+ JUMP_COND_SHRD); -+ -+ if (era < 6) -+ append_key(desc, adata->key_dma, adata->keylen, CLASS_2 | -+ KEY_DEST_MDHA_SPLIT | KEY_ENC); -+ else -+ append_proto_dkp(desc, adata); -+ -+ append_key(desc, cdata->key_dma, cdata->keylen, CLASS_1 | -+ KEY_DEST_CLASS_REG); -+ -+ set_jump_tgt_here(desc, key_jump_cmd); -+ -+ /* class 2 operation */ -+ append_operation(desc, adata->algtype | OP_ALG_AS_INITFINAL | -+ OP_ALG_DECRYPT | OP_ALG_ICV_ON); -+ /* class 1 operation */ -+ append_operation(desc, cdata->algtype | OP_ALG_AS_INITFINAL | -+ OP_ALG_DECRYPT); -+ -+ /* VSIL = input data length - 2 * block_size */ -+ append_math_sub_imm_u32(desc, VARSEQINLEN, SEQINLEN, IMM, 2 * -+ blocksize); -+ -+ /* -+ * payloadlen + icvlen + padlen = input data length - (assoclen + -+ * ivsize) -+ */ -+ append_math_sub_imm_u32(desc, REG3, SEQINLEN, IMM, assoclen + ivsize); -+ -+ /* skip data to the last but one cipher block */ -+ append_seq_fifo_load(desc, 0, FIFOLD_CLASS_SKIP | LDST_VLF); -+ -+ /* load iv for the last cipher block */ -+ append_cmd(desc, CMD_SEQ_LOAD | LDST_SRCDST_WORD_CLASS_CTX | -+ LDST_CLASS_1_CCB | ivsize); -+ -+ /* read last cipher block */ -+ append_seq_fifo_load(desc, 0, FIFOLD_CLASS_CLASS1 | FIFOLD_TYPE_MSG | -+ FIFOLD_TYPE_LAST1 | blocksize); -+ -+ /* move decrypted block into math0 and math1 */ -+ append_move(desc, MOVE_WAITCOMP | MOVE_SRC_OUTFIFO | MOVE_DEST_MATH0 | -+ blocksize); -+ -+ /* reset AES CHA */ -+ append_load_imm_u32(desc, CCTRL_RESET_CHA_AESA, LDST_CLASS_IND_CCB | -+ LDST_SRCDST_WORD_CHACTRL | LDST_IMM); -+ -+ /* rewind input sequence */ -+ append_seq_in_ptr_intlen(desc, 0, 65535, SQIN_RTO); -+ -+ /* key1 is in decryption form */ -+ append_operation(desc, cdata->algtype | OP_ALG_AAI_DK | -+ OP_ALG_AS_INITFINAL | OP_ALG_DECRYPT); -+ -+ /* load iv in context1 */ -+ append_cmd(desc, CMD_SEQ_LOAD | LDST_CLASS_1_CCB | -+ LDST_SRCDST_WORD_CLASS_CTX | ivsize); -+ -+ /* read sequence number */ -+ append_seq_fifo_load(desc, 8, FIFOLD_CLASS_CLASS2 | FIFOLD_TYPE_MSG); -+ /* load Type, Version and Len fields in math0 */ -+ append_cmd(desc, CMD_SEQ_LOAD | LDST_CLASS_DECO | -+ LDST_SRCDST_WORD_DECO_MATH0 | (3 << LDST_OFFSET_SHIFT) | 5); -+ -+ /* compute (padlen - 1) */ -+ append_math_and_imm_u64(desc, REG1, REG1, IMM, 255); -+ -+ /* math2 = icvlen + (padlen - 1) + 1 */ -+ append_math_add_imm_u32(desc, REG2, REG1, IMM, authsize + 1); -+ -+ append_jump(desc, JUMP_TEST_ALL | JUMP_COND_CALM | 1); -+ -+ /* VSOL = payloadlen + icvlen + padlen */ -+ append_math_add(desc, VARSEQOUTLEN, ZERO, REG3, 4); -+ -+ if (caam_little_end) -+ append_moveb(desc, MOVE_WAITCOMP | -+ MOVE_SRC_MATH0 | MOVE_DEST_MATH0 | 8); -+ -+ /* update Len field */ -+ append_math_sub(desc, REG0, REG0, REG2, 8); -+ -+ /* store decrypted payload, icv and padding */ -+ append_seq_fifo_store(desc, 0, FIFOST_TYPE_MESSAGE_DATA | LDST_VLF); -+ -+ /* VSIL = (payloadlen + icvlen + padlen) - (icvlen + padlen)*/ -+ append_math_sub(desc, VARSEQINLEN, REG3, REG2, 4); -+ -+ zero_payload_jump_cmd = append_jump(desc, JUMP_TEST_ALL | -+ JUMP_COND_MATH_Z); -+ -+ /* send Type, Version and Len(pre ICV) fields to authentication */ -+ append_move(desc, MOVE_WAITCOMP | -+ MOVE_SRC_MATH0 | MOVE_DEST_CLASS2INFIFO | -+ (3 << MOVE_OFFSET_SHIFT) | 5); -+ -+ /* outsnooping payload */ -+ append_seq_fifo_load(desc, 0, FIFOLD_CLASS_BOTH | -+ FIFOLD_TYPE_MSG1OUT2 | FIFOLD_TYPE_LAST2 | -+ FIFOLDST_VLF); -+ skip_zero_jump_cmd = append_jump(desc, JUMP_TEST_ALL | 2); -+ -+ set_jump_tgt_here(desc, zero_payload_jump_cmd); -+ /* send Type, Version and Len(pre ICV) fields to authentication */ -+ append_move(desc, MOVE_WAITCOMP | MOVE_AUX_LS | -+ MOVE_SRC_MATH0 | MOVE_DEST_CLASS2INFIFO | -+ (3 << MOVE_OFFSET_SHIFT) | 5); -+ -+ set_jump_tgt_here(desc, skip_zero_jump_cmd); -+ append_math_add(desc, VARSEQINLEN, ZERO, REG2, 4); -+ -+ /* load icvlen and padlen */ -+ append_seq_fifo_load(desc, 0, FIFOLD_CLASS_CLASS1 | FIFOLD_TYPE_MSG | -+ FIFOLD_TYPE_LAST1 | FIFOLDST_VLF); -+ -+ /* VSIL = (payloadlen + icvlen + padlen) - icvlen + padlen */ -+ append_math_sub(desc, VARSEQINLEN, REG3, REG2, 4); -+ -+ /* -+ * Start a new input sequence using the SEQ OUT PTR command options, -+ * pointer and length used when the current output sequence was defined. -+ */ -+ if (ps) { -+ /* -+ * Move the lower 32 bits of Shared Descriptor address, the -+ * SEQ OUT PTR command, Output Pointer (2 words) and -+ * Output Length into math registers. -+ */ -+ if (caam_little_end) -+ append_move(desc, MOVE_WAITCOMP | MOVE_SRC_DESCBUF | -+ MOVE_DEST_MATH0 | -+ (55 * 4 << MOVE_OFFSET_SHIFT) | 20); -+ else -+ append_move(desc, MOVE_WAITCOMP | MOVE_SRC_DESCBUF | -+ MOVE_DEST_MATH0 | -+ (54 * 4 << MOVE_OFFSET_SHIFT) | 20); -+ -+ /* Transform SEQ OUT PTR command in SEQ IN PTR command */ -+ append_math_and_imm_u32(desc, REG0, REG0, IMM, -+ ~(CMD_SEQ_IN_PTR ^ CMD_SEQ_OUT_PTR)); -+ /* Append a JUMP command after the copied fields */ -+ jumpback = CMD_JUMP | (char)-9; -+ append_load_imm_u32(desc, jumpback, LDST_CLASS_DECO | LDST_IMM | -+ LDST_SRCDST_WORD_DECO_MATH2 | -+ (4 << LDST_OFFSET_SHIFT)); -+ append_jump(desc, JUMP_TEST_ALL | JUMP_COND_CALM | 1); -+ /* Move the updated fields back to the Job Descriptor */ -+ if (caam_little_end) -+ append_move(desc, MOVE_WAITCOMP | MOVE_SRC_MATH0 | -+ MOVE_DEST_DESCBUF | -+ (55 * 4 << MOVE_OFFSET_SHIFT) | 24); -+ else -+ append_move(desc, MOVE_WAITCOMP | MOVE_SRC_MATH0 | -+ MOVE_DEST_DESCBUF | -+ (54 * 4 << MOVE_OFFSET_SHIFT) | 24); -+ -+ /* -+ * Read the new SEQ IN PTR command, Input Pointer, Input Length -+ * and then jump back to the next command from the -+ * Shared Descriptor. -+ */ -+ append_jump(desc, JUMP_TEST_ALL | JUMP_COND_CALM | 6); -+ } else { -+ /* -+ * Move the SEQ OUT PTR command, Output Pointer (1 word) and -+ * Output Length into math registers. -+ */ -+ if (caam_little_end) -+ append_move(desc, MOVE_WAITCOMP | MOVE_SRC_DESCBUF | -+ MOVE_DEST_MATH0 | -+ (54 * 4 << MOVE_OFFSET_SHIFT) | 12); -+ else -+ append_move(desc, MOVE_WAITCOMP | MOVE_SRC_DESCBUF | -+ MOVE_DEST_MATH0 | -+ (53 * 4 << MOVE_OFFSET_SHIFT) | 12); -+ -+ /* Transform SEQ OUT PTR command in SEQ IN PTR command */ -+ append_math_and_imm_u64(desc, REG0, REG0, IMM, -+ ~(((u64)(CMD_SEQ_IN_PTR ^ -+ CMD_SEQ_OUT_PTR)) << 32)); -+ /* Append a JUMP command after the copied fields */ -+ jumpback = CMD_JUMP | (char)-7; -+ append_load_imm_u32(desc, jumpback, LDST_CLASS_DECO | LDST_IMM | -+ LDST_SRCDST_WORD_DECO_MATH1 | -+ (4 << LDST_OFFSET_SHIFT)); -+ append_jump(desc, JUMP_TEST_ALL | JUMP_COND_CALM | 1); -+ /* Move the updated fields back to the Job Descriptor */ -+ if (caam_little_end) -+ append_move(desc, MOVE_WAITCOMP | MOVE_SRC_MATH0 | -+ MOVE_DEST_DESCBUF | -+ (54 * 4 << MOVE_OFFSET_SHIFT) | 16); -+ else -+ append_move(desc, MOVE_WAITCOMP | MOVE_SRC_MATH0 | -+ MOVE_DEST_DESCBUF | -+ (53 * 4 << MOVE_OFFSET_SHIFT) | 16); -+ -+ /* -+ * Read the new SEQ IN PTR command, Input Pointer, Input Length -+ * and then jump back to the next command from the -+ * Shared Descriptor. -+ */ -+ append_jump(desc, JUMP_TEST_ALL | JUMP_COND_CALM | 5); -+ } -+ -+ /* skip payload */ -+ append_seq_fifo_load(desc, 0, FIFOLD_CLASS_SKIP | FIFOLDST_VLF); -+ /* check icv */ -+ append_seq_fifo_load(desc, 0, FIFOLD_CLASS_CLASS2 | FIFOLD_TYPE_ICV | -+ FIFOLD_TYPE_LAST2 | authsize); -+ -+#ifdef DEBUG -+ print_hex_dump(KERN_ERR, "tls dec shdesc@" __stringify(__LINE__) ": ", -+ DUMP_PREFIX_ADDRESS, 16, 4, desc, -+ desc_bytes(desc), 1); -+#endif -+} -+EXPORT_SYMBOL(cnstr_shdsc_tls_decap); -+ -+/** - * cnstr_shdsc_gcm_encap - gcm encapsulation shared descriptor - * @desc: pointer to buffer used for descriptor construction - * @cdata: pointer to block cipher transform definitions - * Valid algorithm values - OP_ALG_ALGSEL_AES ANDed with OP_ALG_AAI_GCM. -+ * @ivsize: initialization vector size - * @icvsize: integrity check value (ICV) size (truncated or full) -+ * @is_qi: true when called from caam/qi - */ - void cnstr_shdsc_gcm_encap(u32 * const desc, struct alginfo *cdata, -- unsigned int icvsize) -+ unsigned int ivsize, unsigned int icvsize, -+ const bool is_qi) - { - u32 *key_jump_cmd, *zero_payload_jump_cmd, *zero_assoc_jump_cmd1, - *zero_assoc_jump_cmd2; -@@ -621,11 +1075,35 @@ void cnstr_shdsc_gcm_encap(u32 * const d - append_operation(desc, cdata->algtype | OP_ALG_AS_INITFINAL | - OP_ALG_ENCRYPT); - -+ if (is_qi) { -+ u32 *wait_load_cmd; -+ -+ /* REG3 = assoclen */ -+ append_seq_load(desc, 4, LDST_CLASS_DECO | -+ LDST_SRCDST_WORD_DECO_MATH3 | -+ (4 << LDST_OFFSET_SHIFT)); -+ -+ wait_load_cmd = append_jump(desc, JUMP_JSL | JUMP_TEST_ALL | -+ JUMP_COND_CALM | JUMP_COND_NCP | -+ JUMP_COND_NOP | JUMP_COND_NIP | -+ JUMP_COND_NIFP); -+ set_jump_tgt_here(desc, wait_load_cmd); -+ -+ append_math_sub_imm_u32(desc, VARSEQOUTLEN, SEQINLEN, IMM, -+ ivsize); -+ } else { -+ append_math_sub(desc, VARSEQOUTLEN, SEQINLEN, REG0, -+ CAAM_CMD_SZ); -+ } -+ - /* if assoclen + cryptlen is ZERO, skip to ICV write */ -- append_math_sub(desc, VARSEQOUTLEN, SEQINLEN, REG0, CAAM_CMD_SZ); - zero_assoc_jump_cmd2 = append_jump(desc, JUMP_TEST_ALL | - JUMP_COND_MATH_Z); - -+ if (is_qi) -+ append_seq_fifo_load(desc, ivsize, FIFOLD_CLASS_CLASS1 | -+ FIFOLD_TYPE_IV | FIFOLD_TYPE_FLUSH1); -+ - /* if assoclen is ZERO, skip reading the assoc data */ - append_math_add(desc, VARSEQINLEN, ZERO, REG3, CAAM_CMD_SZ); - zero_assoc_jump_cmd1 = append_jump(desc, JUMP_TEST_ALL | -@@ -657,8 +1135,11 @@ void cnstr_shdsc_gcm_encap(u32 * const d - append_seq_fifo_load(desc, 0, FIFOLD_CLASS_CLASS1 | FIFOLDST_VLF | - FIFOLD_TYPE_MSG | FIFOLD_TYPE_LAST1); - -- /* jump the zero-payload commands */ -- append_jump(desc, JUMP_TEST_ALL | 2); -+ /* jump to ICV writing */ -+ if (is_qi) -+ append_jump(desc, JUMP_TEST_ALL | 4); -+ else -+ append_jump(desc, JUMP_TEST_ALL | 2); - - /* zero-payload commands */ - set_jump_tgt_here(desc, zero_payload_jump_cmd); -@@ -666,10 +1147,18 @@ void cnstr_shdsc_gcm_encap(u32 * const d - /* read assoc data */ - append_seq_fifo_load(desc, 0, FIFOLD_CLASS_CLASS1 | FIFOLDST_VLF | - FIFOLD_TYPE_AAD | FIFOLD_TYPE_LAST1); -+ if (is_qi) -+ /* jump to ICV writing */ -+ append_jump(desc, JUMP_TEST_ALL | 2); - - /* There is no input data */ - set_jump_tgt_here(desc, zero_assoc_jump_cmd2); - -+ if (is_qi) -+ append_seq_fifo_load(desc, ivsize, FIFOLD_CLASS_CLASS1 | -+ FIFOLD_TYPE_IV | FIFOLD_TYPE_FLUSH1 | -+ FIFOLD_TYPE_LAST1); -+ - /* write ICV */ - append_seq_store(desc, icvsize, LDST_CLASS_1_CCB | - LDST_SRCDST_BYTE_CONTEXT); -@@ -686,10 +1175,13 @@ EXPORT_SYMBOL(cnstr_shdsc_gcm_encap); - * @desc: pointer to buffer used for descriptor construction - * @cdata: pointer to block cipher transform definitions - * Valid algorithm values - OP_ALG_ALGSEL_AES ANDed with OP_ALG_AAI_GCM. -+ * @ivsize: initialization vector size - * @icvsize: integrity check value (ICV) size (truncated or full) -+ * @is_qi: true when called from caam/qi - */ - void cnstr_shdsc_gcm_decap(u32 * const desc, struct alginfo *cdata, -- unsigned int icvsize) -+ unsigned int ivsize, unsigned int icvsize, -+ const bool is_qi) - { - u32 *key_jump_cmd, *zero_payload_jump_cmd, *zero_assoc_jump_cmd1; - -@@ -710,6 +1202,24 @@ void cnstr_shdsc_gcm_decap(u32 * const d - append_operation(desc, cdata->algtype | OP_ALG_AS_INITFINAL | - OP_ALG_DECRYPT | OP_ALG_ICV_ON); - -+ if (is_qi) { -+ u32 *wait_load_cmd; -+ -+ /* REG3 = assoclen */ -+ append_seq_load(desc, 4, LDST_CLASS_DECO | -+ LDST_SRCDST_WORD_DECO_MATH3 | -+ (4 << LDST_OFFSET_SHIFT)); -+ -+ wait_load_cmd = append_jump(desc, JUMP_JSL | JUMP_TEST_ALL | -+ JUMP_COND_CALM | JUMP_COND_NCP | -+ JUMP_COND_NOP | JUMP_COND_NIP | -+ JUMP_COND_NIFP); -+ set_jump_tgt_here(desc, wait_load_cmd); -+ -+ append_seq_fifo_load(desc, ivsize, FIFOLD_CLASS_CLASS1 | -+ FIFOLD_TYPE_IV | FIFOLD_TYPE_FLUSH1); -+ } -+ - /* if assoclen is ZERO, skip reading the assoc data */ - append_math_add(desc, VARSEQINLEN, ZERO, REG3, CAAM_CMD_SZ); - zero_assoc_jump_cmd1 = append_jump(desc, JUMP_TEST_ALL | -@@ -762,10 +1272,13 @@ EXPORT_SYMBOL(cnstr_shdsc_gcm_decap); - * @desc: pointer to buffer used for descriptor construction - * @cdata: pointer to block cipher transform definitions - * Valid algorithm values - OP_ALG_ALGSEL_AES ANDed with OP_ALG_AAI_GCM. -+ * @ivsize: initialization vector size - * @icvsize: integrity check value (ICV) size (truncated or full) -+ * @is_qi: true when called from caam/qi - */ - void cnstr_shdsc_rfc4106_encap(u32 * const desc, struct alginfo *cdata, -- unsigned int icvsize) -+ unsigned int ivsize, unsigned int icvsize, -+ const bool is_qi) - { - u32 *key_jump_cmd; - -@@ -786,7 +1299,29 @@ void cnstr_shdsc_rfc4106_encap(u32 * con - append_operation(desc, cdata->algtype | OP_ALG_AS_INITFINAL | - OP_ALG_ENCRYPT); - -- append_math_sub_imm_u32(desc, VARSEQINLEN, REG3, IMM, 8); -+ if (is_qi) { -+ u32 *wait_load_cmd; -+ -+ /* REG3 = assoclen */ -+ append_seq_load(desc, 4, LDST_CLASS_DECO | -+ LDST_SRCDST_WORD_DECO_MATH3 | -+ (4 << LDST_OFFSET_SHIFT)); -+ -+ wait_load_cmd = append_jump(desc, JUMP_JSL | JUMP_TEST_ALL | -+ JUMP_COND_CALM | JUMP_COND_NCP | -+ JUMP_COND_NOP | JUMP_COND_NIP | -+ JUMP_COND_NIFP); -+ set_jump_tgt_here(desc, wait_load_cmd); -+ -+ /* Read salt and IV */ -+ append_fifo_load_as_imm(desc, (void *)(cdata->key_virt + -+ cdata->keylen), 4, FIFOLD_CLASS_CLASS1 | -+ FIFOLD_TYPE_IV); -+ append_seq_fifo_load(desc, ivsize, FIFOLD_CLASS_CLASS1 | -+ FIFOLD_TYPE_IV | FIFOLD_TYPE_FLUSH1); -+ } -+ -+ append_math_sub_imm_u32(desc, VARSEQINLEN, REG3, IMM, ivsize); - append_math_add(desc, VARSEQOUTLEN, ZERO, REG3, CAAM_CMD_SZ); - - /* Read assoc data */ -@@ -794,7 +1329,7 @@ void cnstr_shdsc_rfc4106_encap(u32 * con - FIFOLD_TYPE_AAD | FIFOLD_TYPE_FLUSH1); - - /* Skip IV */ -- append_seq_fifo_load(desc, 8, FIFOLD_CLASS_SKIP); -+ append_seq_fifo_load(desc, ivsize, FIFOLD_CLASS_SKIP); - - /* Will read cryptlen bytes */ - append_math_sub(desc, VARSEQINLEN, SEQINLEN, REG0, CAAM_CMD_SZ); -@@ -833,10 +1368,13 @@ EXPORT_SYMBOL(cnstr_shdsc_rfc4106_encap) - * @desc: pointer to buffer used for descriptor construction - * @cdata: pointer to block cipher transform definitions - * Valid algorithm values - OP_ALG_ALGSEL_AES ANDed with OP_ALG_AAI_GCM. -+ * @ivsize: initialization vector size - * @icvsize: integrity check value (ICV) size (truncated or full) -+ * @is_qi: true when called from caam/qi - */ - void cnstr_shdsc_rfc4106_decap(u32 * const desc, struct alginfo *cdata, -- unsigned int icvsize) -+ unsigned int ivsize, unsigned int icvsize, -+ const bool is_qi) - { - u32 *key_jump_cmd; - -@@ -858,7 +1396,29 @@ void cnstr_shdsc_rfc4106_decap(u32 * con - append_operation(desc, cdata->algtype | OP_ALG_AS_INITFINAL | - OP_ALG_DECRYPT | OP_ALG_ICV_ON); - -- append_math_sub_imm_u32(desc, VARSEQINLEN, REG3, IMM, 8); -+ if (is_qi) { -+ u32 *wait_load_cmd; -+ -+ /* REG3 = assoclen */ -+ append_seq_load(desc, 4, LDST_CLASS_DECO | -+ LDST_SRCDST_WORD_DECO_MATH3 | -+ (4 << LDST_OFFSET_SHIFT)); -+ -+ wait_load_cmd = append_jump(desc, JUMP_JSL | JUMP_TEST_ALL | -+ JUMP_COND_CALM | JUMP_COND_NCP | -+ JUMP_COND_NOP | JUMP_COND_NIP | -+ JUMP_COND_NIFP); -+ set_jump_tgt_here(desc, wait_load_cmd); -+ -+ /* Read salt and IV */ -+ append_fifo_load_as_imm(desc, (void *)(cdata->key_virt + -+ cdata->keylen), 4, FIFOLD_CLASS_CLASS1 | -+ FIFOLD_TYPE_IV); -+ append_seq_fifo_load(desc, ivsize, FIFOLD_CLASS_CLASS1 | -+ FIFOLD_TYPE_IV | FIFOLD_TYPE_FLUSH1); -+ } -+ -+ append_math_sub_imm_u32(desc, VARSEQINLEN, REG3, IMM, ivsize); - append_math_add(desc, VARSEQOUTLEN, ZERO, REG3, CAAM_CMD_SZ); - - /* Read assoc data */ -@@ -866,7 +1426,7 @@ void cnstr_shdsc_rfc4106_decap(u32 * con - FIFOLD_TYPE_AAD | FIFOLD_TYPE_FLUSH1); - - /* Skip IV */ -- append_seq_fifo_load(desc, 8, FIFOLD_CLASS_SKIP); -+ append_seq_fifo_load(desc, ivsize, FIFOLD_CLASS_SKIP); - - /* Will read cryptlen bytes */ - append_math_sub(desc, VARSEQINLEN, SEQOUTLEN, REG3, CAAM_CMD_SZ); -@@ -905,10 +1465,13 @@ EXPORT_SYMBOL(cnstr_shdsc_rfc4106_decap) - * @desc: pointer to buffer used for descriptor construction - * @cdata: pointer to block cipher transform definitions - * Valid algorithm values - OP_ALG_ALGSEL_AES ANDed with OP_ALG_AAI_GCM. -+ * @ivsize: initialization vector size - * @icvsize: integrity check value (ICV) size (truncated or full) -+ * @is_qi: true when called from caam/qi - */ - void cnstr_shdsc_rfc4543_encap(u32 * const desc, struct alginfo *cdata, -- unsigned int icvsize) -+ unsigned int ivsize, unsigned int icvsize, -+ const bool is_qi) - { - u32 *key_jump_cmd, *read_move_cmd, *write_move_cmd; - -@@ -929,6 +1492,18 @@ void cnstr_shdsc_rfc4543_encap(u32 * con - append_operation(desc, cdata->algtype | OP_ALG_AS_INITFINAL | - OP_ALG_ENCRYPT); - -+ if (is_qi) { -+ /* assoclen is not needed, skip it */ -+ append_seq_fifo_load(desc, 4, FIFOLD_CLASS_SKIP); -+ -+ /* Read salt and IV */ -+ append_fifo_load_as_imm(desc, (void *)(cdata->key_virt + -+ cdata->keylen), 4, FIFOLD_CLASS_CLASS1 | -+ FIFOLD_TYPE_IV); -+ append_seq_fifo_load(desc, ivsize, FIFOLD_CLASS_CLASS1 | -+ FIFOLD_TYPE_IV | FIFOLD_TYPE_FLUSH1); -+ } -+ - /* assoclen + cryptlen = seqinlen */ - append_math_sub(desc, REG3, SEQINLEN, REG0, CAAM_CMD_SZ); - -@@ -940,7 +1515,7 @@ void cnstr_shdsc_rfc4543_encap(u32 * con - read_move_cmd = append_move(desc, MOVE_SRC_DESCBUF | MOVE_DEST_MATH3 | - (0x6 << MOVE_LEN_SHIFT)); - write_move_cmd = append_move(desc, MOVE_SRC_MATH3 | MOVE_DEST_DESCBUF | -- (0x8 << MOVE_LEN_SHIFT)); -+ (0x8 << MOVE_LEN_SHIFT) | MOVE_WAITCOMP); - - /* Will read assoclen + cryptlen bytes */ - append_math_sub(desc, VARSEQINLEN, SEQINLEN, REG0, CAAM_CMD_SZ); -@@ -975,10 +1550,13 @@ EXPORT_SYMBOL(cnstr_shdsc_rfc4543_encap) - * @desc: pointer to buffer used for descriptor construction - * @cdata: pointer to block cipher transform definitions - * Valid algorithm values - OP_ALG_ALGSEL_AES ANDed with OP_ALG_AAI_GCM. -+ * @ivsize: initialization vector size - * @icvsize: integrity check value (ICV) size (truncated or full) -+ * @is_qi: true when called from caam/qi - */ - void cnstr_shdsc_rfc4543_decap(u32 * const desc, struct alginfo *cdata, -- unsigned int icvsize) -+ unsigned int ivsize, unsigned int icvsize, -+ const bool is_qi) - { - u32 *key_jump_cmd, *read_move_cmd, *write_move_cmd; - -@@ -999,6 +1577,18 @@ void cnstr_shdsc_rfc4543_decap(u32 * con - append_operation(desc, cdata->algtype | OP_ALG_AS_INITFINAL | - OP_ALG_DECRYPT | OP_ALG_ICV_ON); - -+ if (is_qi) { -+ /* assoclen is not needed, skip it */ -+ append_seq_fifo_load(desc, 4, FIFOLD_CLASS_SKIP); -+ -+ /* Read salt and IV */ -+ append_fifo_load_as_imm(desc, (void *)(cdata->key_virt + -+ cdata->keylen), 4, FIFOLD_CLASS_CLASS1 | -+ FIFOLD_TYPE_IV); -+ append_seq_fifo_load(desc, ivsize, FIFOLD_CLASS_CLASS1 | -+ FIFOLD_TYPE_IV | FIFOLD_TYPE_FLUSH1); -+ } -+ - /* assoclen + cryptlen = seqoutlen */ - append_math_sub(desc, REG3, SEQOUTLEN, REG0, CAAM_CMD_SZ); - -@@ -1010,7 +1600,7 @@ void cnstr_shdsc_rfc4543_decap(u32 * con - read_move_cmd = append_move(desc, MOVE_SRC_DESCBUF | MOVE_DEST_MATH3 | - (0x6 << MOVE_LEN_SHIFT)); - write_move_cmd = append_move(desc, MOVE_SRC_MATH3 | MOVE_DEST_DESCBUF | -- (0x8 << MOVE_LEN_SHIFT)); -+ (0x8 << MOVE_LEN_SHIFT) | MOVE_WAITCOMP); - - /* Will read assoclen + cryptlen bytes */ - append_math_sub(desc, VARSEQINLEN, SEQOUTLEN, REG0, CAAM_CMD_SZ); -@@ -1044,6 +1634,138 @@ void cnstr_shdsc_rfc4543_decap(u32 * con - } - EXPORT_SYMBOL(cnstr_shdsc_rfc4543_decap); - -+/** -+ * cnstr_shdsc_chachapoly - Chacha20 + Poly1305 generic AEAD (rfc7539) and -+ * IPsec ESP (rfc7634, a.k.a. rfc7539esp) shared -+ * descriptor (non-protocol). -+ * @desc: pointer to buffer used for descriptor construction -+ * @cdata: pointer to block cipher transform definitions -+ * Valid algorithm values - OP_ALG_ALGSEL_CHACHA20 ANDed with -+ * OP_ALG_AAI_AEAD. -+ * @adata: pointer to authentication transform definitions -+ * Valid algorithm values - OP_ALG_ALGSEL_POLY1305 ANDed with -+ * OP_ALG_AAI_AEAD. -+ * @ivsize: initialization vector size -+ * @icvsize: integrity check value (ICV) size (truncated or full) -+ * @encap: true if encapsulation, false if decapsulation -+ * @is_qi: true when called from caam/qi -+ */ -+void cnstr_shdsc_chachapoly(u32 * const desc, struct alginfo *cdata, -+ struct alginfo *adata, unsigned int ivsize, -+ unsigned int icvsize, const bool encap, -+ const bool is_qi) -+{ -+ u32 *key_jump_cmd, *wait_cmd; -+ u32 nfifo; -+ const bool is_ipsec = (ivsize != CHACHAPOLY_IV_SIZE); -+ -+ /* Note: Context registers are saved. */ -+ init_sh_desc(desc, HDR_SHARE_SERIAL | HDR_SAVECTX); -+ -+ /* skip key loading if they are loaded due to sharing */ -+ key_jump_cmd = append_jump(desc, JUMP_JSL | JUMP_TEST_ALL | -+ JUMP_COND_SHRD); -+ -+ append_key_as_imm(desc, cdata->key_virt, cdata->keylen, cdata->keylen, -+ CLASS_1 | KEY_DEST_CLASS_REG); -+ -+ /* For IPsec load the salt from keymat in the context register */ -+ if (is_ipsec) -+ append_load_as_imm(desc, cdata->key_virt + cdata->keylen, 4, -+ LDST_CLASS_1_CCB | LDST_SRCDST_BYTE_CONTEXT | -+ 4 << LDST_OFFSET_SHIFT); -+ -+ set_jump_tgt_here(desc, key_jump_cmd); -+ -+ /* Class 2 and 1 operations: Poly & ChaCha */ -+ if (encap) { -+ append_operation(desc, adata->algtype | OP_ALG_AS_INITFINAL | -+ OP_ALG_ENCRYPT); -+ append_operation(desc, cdata->algtype | OP_ALG_AS_INITFINAL | -+ OP_ALG_ENCRYPT); -+ } else { -+ append_operation(desc, adata->algtype | OP_ALG_AS_INITFINAL | -+ OP_ALG_DECRYPT | OP_ALG_ICV_ON); -+ append_operation(desc, cdata->algtype | OP_ALG_AS_INITFINAL | -+ OP_ALG_DECRYPT); -+ } -+ -+ if (is_qi) { -+ u32 *wait_load_cmd; -+ u32 ctx1_iv_off = is_ipsec ? 8 : 4; -+ -+ /* REG3 = assoclen */ -+ append_seq_load(desc, 4, LDST_CLASS_DECO | -+ LDST_SRCDST_WORD_DECO_MATH3 | -+ 4 << LDST_OFFSET_SHIFT); -+ -+ wait_load_cmd = append_jump(desc, JUMP_JSL | JUMP_TEST_ALL | -+ JUMP_COND_CALM | JUMP_COND_NCP | -+ JUMP_COND_NOP | JUMP_COND_NIP | -+ JUMP_COND_NIFP); -+ set_jump_tgt_here(desc, wait_load_cmd); -+ -+ append_seq_load(desc, ivsize, LDST_CLASS_1_CCB | -+ LDST_SRCDST_BYTE_CONTEXT | -+ ctx1_iv_off << LDST_OFFSET_SHIFT); -+ } -+ -+ /* -+ * MAGIC with NFIFO -+ * Read associated data from the input and send them to class1 and -+ * class2 alignment blocks. From class1 send data to output fifo and -+ * then write it to memory since we don't need to encrypt AD. -+ */ -+ nfifo = NFIFOENTRY_DEST_BOTH | NFIFOENTRY_FC1 | NFIFOENTRY_FC2 | -+ NFIFOENTRY_DTYPE_POLY | NFIFOENTRY_BND; -+ append_load_imm_u32(desc, nfifo, LDST_CLASS_IND_CCB | -+ LDST_SRCDST_WORD_INFO_FIFO_SM | LDLEN_MATH3); -+ -+ append_math_add(desc, VARSEQINLEN, ZERO, REG3, CAAM_CMD_SZ); -+ append_math_add(desc, VARSEQOUTLEN, ZERO, REG3, CAAM_CMD_SZ); -+ append_seq_fifo_load(desc, 0, FIFOLD_TYPE_NOINFOFIFO | -+ FIFOLD_CLASS_CLASS1 | LDST_VLF); -+ append_move_len(desc, MOVE_AUX_LS | MOVE_SRC_AUX_ABLK | -+ MOVE_DEST_OUTFIFO | MOVELEN_MRSEL_MATH3); -+ append_seq_fifo_store(desc, 0, FIFOST_TYPE_MESSAGE_DATA | LDST_VLF); -+ -+ /* IPsec - copy IV at the output */ -+ if (is_ipsec) -+ append_seq_fifo_store(desc, ivsize, FIFOST_TYPE_METADATA | -+ 0x2 << 25); -+ -+ wait_cmd = append_jump(desc, JUMP_JSL | JUMP_TYPE_LOCAL | -+ JUMP_COND_NOP | JUMP_TEST_ALL); -+ set_jump_tgt_here(desc, wait_cmd); -+ -+ if (encap) { -+ /* Read and write cryptlen bytes */ -+ append_math_add(desc, VARSEQINLEN, SEQINLEN, REG0, CAAM_CMD_SZ); -+ append_math_add(desc, VARSEQOUTLEN, SEQINLEN, REG0, -+ CAAM_CMD_SZ); -+ aead_append_src_dst(desc, FIFOLD_TYPE_MSG1OUT2); -+ -+ /* Write ICV */ -+ append_seq_store(desc, icvsize, LDST_CLASS_2_CCB | -+ LDST_SRCDST_BYTE_CONTEXT); -+ } else { -+ /* Read and write cryptlen bytes */ -+ append_math_add(desc, VARSEQINLEN, SEQOUTLEN, REG0, CAAM_CMD_SZ); -+ append_math_add(desc, VARSEQOUTLEN, SEQOUTLEN, REG0, -+ CAAM_CMD_SZ); -+ aead_append_src_dst(desc, FIFOLD_TYPE_MSG); -+ -+ /* Load ICV for verification */ -+ append_seq_fifo_load(desc, icvsize, FIFOLD_CLASS_CLASS2 | -+ FIFOLD_TYPE_LAST2 | FIFOLD_TYPE_ICV); -+ } -+ -+ print_hex_dump_debug("chachapoly shdesc@" __stringify(__LINE__)": ", -+ DUMP_PREFIX_ADDRESS, 16, 4, desc, desc_bytes(desc), -+ 1); -+} -+EXPORT_SYMBOL(cnstr_shdsc_chachapoly); -+ - /* - * For ablkcipher encrypt and decrypt, read from req->src and - * write to req->dst -@@ -1062,7 +1784,8 @@ static inline void ablkcipher_append_src - * @desc: pointer to buffer used for descriptor construction - * @cdata: pointer to block cipher transform definitions - * Valid algorithm values - one of OP_ALG_ALGSEL_{AES, DES, 3DES} ANDed -- * with OP_ALG_AAI_CBC or OP_ALG_AAI_CTR_MOD128. -+ * with OP_ALG_AAI_CBC or OP_ALG_AAI_CTR_MOD128 -+ * - OP_ALG_ALGSEL_CHACHA20 - * @ivsize: initialization vector size - * @is_rfc3686: true when ctr(aes) is wrapped by rfc3686 template - * @ctx1_iv_off: IV offset in CONTEXT1 register -@@ -1084,7 +1807,7 @@ void cnstr_shdsc_ablkcipher_encap(u32 * - - /* Load nonce into CONTEXT1 reg */ - if (is_rfc3686) { -- u8 *nonce = cdata->key_virt + cdata->keylen; -+ const u8 *nonce = cdata->key_virt + cdata->keylen; - - append_load_as_imm(desc, nonce, CTR_RFC3686_NONCE_SIZE, - LDST_CLASS_IND_CCB | -@@ -1127,7 +1850,8 @@ EXPORT_SYMBOL(cnstr_shdsc_ablkcipher_enc - * @desc: pointer to buffer used for descriptor construction - * @cdata: pointer to block cipher transform definitions - * Valid algorithm values - one of OP_ALG_ALGSEL_{AES, DES, 3DES} ANDed -- * with OP_ALG_AAI_CBC or OP_ALG_AAI_CTR_MOD128. -+ * with OP_ALG_AAI_CBC or OP_ALG_AAI_CTR_MOD128 -+ * - OP_ALG_ALGSEL_CHACHA20 - * @ivsize: initialization vector size - * @is_rfc3686: true when ctr(aes) is wrapped by rfc3686 template - * @ctx1_iv_off: IV offset in CONTEXT1 register -@@ -1149,7 +1873,7 @@ void cnstr_shdsc_ablkcipher_decap(u32 * - - /* Load nonce into CONTEXT1 reg */ - if (is_rfc3686) { -- u8 *nonce = cdata->key_virt + cdata->keylen; -+ const u8 *nonce = cdata->key_virt + cdata->keylen; - - append_load_as_imm(desc, nonce, CTR_RFC3686_NONCE_SIZE, - LDST_CLASS_IND_CCB | -@@ -1218,7 +1942,7 @@ void cnstr_shdsc_ablkcipher_givencap(u32 - - /* Load Nonce into CONTEXT1 reg */ - if (is_rfc3686) { -- u8 *nonce = cdata->key_virt + cdata->keylen; -+ const u8 *nonce = cdata->key_virt + cdata->keylen; - - append_load_as_imm(desc, nonce, CTR_RFC3686_NONCE_SIZE, - LDST_CLASS_IND_CCB | ---- a/drivers/crypto/caam/caamalg_desc.h -+++ b/drivers/crypto/caam/caamalg_desc.h -@@ -17,6 +17,9 @@ - #define DESC_QI_AEAD_DEC_LEN (DESC_AEAD_DEC_LEN + 3 * CAAM_CMD_SZ) - #define DESC_QI_AEAD_GIVENC_LEN (DESC_AEAD_GIVENC_LEN + 3 * CAAM_CMD_SZ) - -+#define DESC_TLS_BASE (4 * CAAM_CMD_SZ) -+#define DESC_TLS10_ENC_LEN (DESC_TLS_BASE + 29 * CAAM_CMD_SZ) -+ - /* Note: Nonce is counted in cdata.keylen */ - #define DESC_AEAD_CTR_RFC3686_LEN (4 * CAAM_CMD_SZ) - -@@ -27,14 +30,20 @@ - #define DESC_GCM_BASE (3 * CAAM_CMD_SZ) - #define DESC_GCM_ENC_LEN (DESC_GCM_BASE + 16 * CAAM_CMD_SZ) - #define DESC_GCM_DEC_LEN (DESC_GCM_BASE + 12 * CAAM_CMD_SZ) -+#define DESC_QI_GCM_ENC_LEN (DESC_GCM_ENC_LEN + 6 * CAAM_CMD_SZ) -+#define DESC_QI_GCM_DEC_LEN (DESC_GCM_DEC_LEN + 3 * CAAM_CMD_SZ) - - #define DESC_RFC4106_BASE (3 * CAAM_CMD_SZ) - #define DESC_RFC4106_ENC_LEN (DESC_RFC4106_BASE + 13 * CAAM_CMD_SZ) - #define DESC_RFC4106_DEC_LEN (DESC_RFC4106_BASE + 13 * CAAM_CMD_SZ) -+#define DESC_QI_RFC4106_ENC_LEN (DESC_RFC4106_ENC_LEN + 5 * CAAM_CMD_SZ) -+#define DESC_QI_RFC4106_DEC_LEN (DESC_RFC4106_DEC_LEN + 5 * CAAM_CMD_SZ) - - #define DESC_RFC4543_BASE (3 * CAAM_CMD_SZ) - #define DESC_RFC4543_ENC_LEN (DESC_RFC4543_BASE + 11 * CAAM_CMD_SZ) - #define DESC_RFC4543_DEC_LEN (DESC_RFC4543_BASE + 12 * CAAM_CMD_SZ) -+#define DESC_QI_RFC4543_ENC_LEN (DESC_RFC4543_ENC_LEN + 4 * CAAM_CMD_SZ) -+#define DESC_QI_RFC4543_DEC_LEN (DESC_RFC4543_DEC_LEN + 4 * CAAM_CMD_SZ) - - #define DESC_ABLKCIPHER_BASE (3 * CAAM_CMD_SZ) - #define DESC_ABLKCIPHER_ENC_LEN (DESC_ABLKCIPHER_BASE + \ -@@ -43,46 +52,67 @@ - 15 * CAAM_CMD_SZ) - - void cnstr_shdsc_aead_null_encap(u32 * const desc, struct alginfo *adata, -- unsigned int icvsize); -+ unsigned int icvsize, int era); - - void cnstr_shdsc_aead_null_decap(u32 * const desc, struct alginfo *adata, -- unsigned int icvsize); -+ unsigned int icvsize, int era); - - void cnstr_shdsc_aead_encap(u32 * const desc, struct alginfo *cdata, - struct alginfo *adata, unsigned int ivsize, - unsigned int icvsize, const bool is_rfc3686, - u32 *nonce, const u32 ctx1_iv_off, -- const bool is_qi); -+ const bool is_qi, int era); - - void cnstr_shdsc_aead_decap(u32 * const desc, struct alginfo *cdata, - struct alginfo *adata, unsigned int ivsize, - unsigned int icvsize, const bool geniv, - const bool is_rfc3686, u32 *nonce, -- const u32 ctx1_iv_off, const bool is_qi); -+ const u32 ctx1_iv_off, const bool is_qi, int era); - - void cnstr_shdsc_aead_givencap(u32 * const desc, struct alginfo *cdata, - struct alginfo *adata, unsigned int ivsize, - unsigned int icvsize, const bool is_rfc3686, - u32 *nonce, const u32 ctx1_iv_off, -- const bool is_qi); -+ const bool is_qi, int era); -+ -+void cnstr_shdsc_tls_encap(u32 *const desc, struct alginfo *cdata, -+ struct alginfo *adata, unsigned int assoclen, -+ unsigned int ivsize, unsigned int authsize, -+ unsigned int blocksize, int era); -+ -+void cnstr_shdsc_tls_decap(u32 *const desc, struct alginfo *cdata, -+ struct alginfo *adata, unsigned int assoclen, -+ unsigned int ivsize, unsigned int authsize, -+ unsigned int blocksize, int era); - - void cnstr_shdsc_gcm_encap(u32 * const desc, struct alginfo *cdata, -- unsigned int icvsize); -+ unsigned int ivsize, unsigned int icvsize, -+ const bool is_qi); - - void cnstr_shdsc_gcm_decap(u32 * const desc, struct alginfo *cdata, -- unsigned int icvsize); -+ unsigned int ivsize, unsigned int icvsize, -+ const bool is_qi); - - void cnstr_shdsc_rfc4106_encap(u32 * const desc, struct alginfo *cdata, -- unsigned int icvsize); -+ unsigned int ivsize, unsigned int icvsize, -+ const bool is_qi); - - void cnstr_shdsc_rfc4106_decap(u32 * const desc, struct alginfo *cdata, -- unsigned int icvsize); -+ unsigned int ivsize, unsigned int icvsize, -+ const bool is_qi); - - void cnstr_shdsc_rfc4543_encap(u32 * const desc, struct alginfo *cdata, -- unsigned int icvsize); -+ unsigned int ivsize, unsigned int icvsize, -+ const bool is_qi); - - void cnstr_shdsc_rfc4543_decap(u32 * const desc, struct alginfo *cdata, -- unsigned int icvsize); -+ unsigned int ivsize, unsigned int icvsize, -+ const bool is_qi); -+ -+void cnstr_shdsc_chachapoly(u32 * const desc, struct alginfo *cdata, -+ struct alginfo *adata, unsigned int ivsize, -+ unsigned int icvsize, const bool encap, -+ const bool is_qi); - - void cnstr_shdsc_ablkcipher_encap(u32 * const desc, struct alginfo *cdata, - unsigned int ivsize, const bool is_rfc3686, ---- a/drivers/crypto/caam/caamalg_qi.c -+++ b/drivers/crypto/caam/caamalg_qi.c -@@ -7,7 +7,7 @@ - */ - - #include "compat.h" -- -+#include "ctrl.h" - #include "regs.h" - #include "intern.h" - #include "desc_constr.h" -@@ -53,6 +53,7 @@ struct caam_ctx { - u32 sh_desc_givenc[DESC_MAX_USED_LEN]; - u8 key[CAAM_MAX_KEY_SIZE]; - dma_addr_t key_dma; -+ enum dma_data_direction dir; - struct alginfo adata; - struct alginfo cdata; - unsigned int authsize; -@@ -74,6 +75,7 @@ static int aead_set_sh_desc(struct crypt - const bool ctr_mode = ((ctx->cdata.algtype & OP_ALG_AAI_MASK) == - OP_ALG_AAI_CTR_MOD128); - const bool is_rfc3686 = alg->caam.rfc3686; -+ struct caam_drv_private *ctrlpriv = dev_get_drvdata(ctx->jrdev->parent); - - if (!ctx->cdata.keylen || !ctx->authsize) - return 0; -@@ -124,7 +126,7 @@ static int aead_set_sh_desc(struct crypt - - cnstr_shdsc_aead_encap(ctx->sh_desc_enc, &ctx->cdata, &ctx->adata, - ivsize, ctx->authsize, is_rfc3686, nonce, -- ctx1_iv_off, true); -+ ctx1_iv_off, true, ctrlpriv->era); - - skip_enc: - /* aead_decrypt shared descriptor */ -@@ -149,7 +151,8 @@ skip_enc: - - cnstr_shdsc_aead_decap(ctx->sh_desc_dec, &ctx->cdata, &ctx->adata, - ivsize, ctx->authsize, alg->caam.geniv, -- is_rfc3686, nonce, ctx1_iv_off, true); -+ is_rfc3686, nonce, ctx1_iv_off, true, -+ ctrlpriv->era); - - if (!alg->caam.geniv) - goto skip_givenc; -@@ -176,7 +179,7 @@ skip_enc: - - cnstr_shdsc_aead_givencap(ctx->sh_desc_enc, &ctx->cdata, &ctx->adata, - ivsize, ctx->authsize, is_rfc3686, nonce, -- ctx1_iv_off, true); -+ ctx1_iv_off, true, ctrlpriv->era); - - skip_givenc: - return 0; -@@ -197,6 +200,7 @@ static int aead_setkey(struct crypto_aea - { - struct caam_ctx *ctx = crypto_aead_ctx(aead); - struct device *jrdev = ctx->jrdev; -+ struct caam_drv_private *ctrlpriv = dev_get_drvdata(jrdev->parent); - struct crypto_authenc_keys keys; - int ret = 0; - -@@ -211,6 +215,27 @@ static int aead_setkey(struct crypto_aea - DUMP_PREFIX_ADDRESS, 16, 4, key, keylen, 1); - #endif - -+ /* -+ * If DKP is supported, use it in the shared descriptor to generate -+ * the split key. -+ */ -+ if (ctrlpriv->era >= 6) { -+ ctx->adata.keylen = keys.authkeylen; -+ ctx->adata.keylen_pad = split_key_len(ctx->adata.algtype & -+ OP_ALG_ALGSEL_MASK); -+ -+ if (ctx->adata.keylen_pad + keys.enckeylen > CAAM_MAX_KEY_SIZE) -+ goto badkey; -+ -+ memcpy(ctx->key, keys.authkey, keys.authkeylen); -+ memcpy(ctx->key + ctx->adata.keylen_pad, keys.enckey, -+ keys.enckeylen); -+ dma_sync_single_for_device(jrdev->parent, ctx->key_dma, -+ ctx->adata.keylen_pad + -+ keys.enckeylen, ctx->dir); -+ goto skip_split_key; -+ } -+ - ret = gen_split_key(jrdev, ctx->key, &ctx->adata, keys.authkey, - keys.authkeylen, CAAM_MAX_KEY_SIZE - - keys.enckeylen); -@@ -220,13 +245,14 @@ static int aead_setkey(struct crypto_aea - /* postpend encryption key to auth split key */ - memcpy(ctx->key + ctx->adata.keylen_pad, keys.enckey, keys.enckeylen); - dma_sync_single_for_device(jrdev, ctx->key_dma, ctx->adata.keylen_pad + -- keys.enckeylen, DMA_TO_DEVICE); -+ keys.enckeylen, ctx->dir); - #ifdef DEBUG - print_hex_dump(KERN_ERR, "ctx.key@" __stringify(__LINE__)": ", - DUMP_PREFIX_ADDRESS, 16, 4, ctx->key, - ctx->adata.keylen_pad + keys.enckeylen, 1); - #endif - -+skip_split_key: - ctx->cdata.keylen = keys.enckeylen; - - ret = aead_set_sh_desc(aead); -@@ -258,6 +284,468 @@ badkey: - return -EINVAL; - } - -+static int tls_set_sh_desc(struct crypto_aead *tls) -+{ -+ struct caam_ctx *ctx = crypto_aead_ctx(tls); -+ unsigned int ivsize = crypto_aead_ivsize(tls); -+ unsigned int blocksize = crypto_aead_blocksize(tls); -+ unsigned int assoclen = 13; /* always 13 bytes for TLS */ -+ unsigned int data_len[2]; -+ u32 inl_mask; -+ struct caam_drv_private *ctrlpriv = dev_get_drvdata(ctx->jrdev->parent); -+ -+ if (!ctx->cdata.keylen || !ctx->authsize) -+ return 0; -+ -+ /* -+ * TLS 1.0 encrypt shared descriptor -+ * Job Descriptor and Shared Descriptor -+ * must fit into the 64-word Descriptor h/w Buffer -+ */ -+ data_len[0] = ctx->adata.keylen_pad; -+ data_len[1] = ctx->cdata.keylen; -+ -+ if (desc_inline_query(DESC_TLS10_ENC_LEN, DESC_JOB_IO_LEN, data_len, -+ &inl_mask, ARRAY_SIZE(data_len)) < 0) -+ return -EINVAL; -+ -+ if (inl_mask & 1) -+ ctx->adata.key_virt = ctx->key; -+ else -+ ctx->adata.key_dma = ctx->key_dma; -+ -+ if (inl_mask & 2) -+ ctx->cdata.key_virt = ctx->key + ctx->adata.keylen_pad; -+ else -+ ctx->cdata.key_dma = ctx->key_dma + ctx->adata.keylen_pad; -+ -+ ctx->adata.key_inline = !!(inl_mask & 1); -+ ctx->cdata.key_inline = !!(inl_mask & 2); -+ -+ cnstr_shdsc_tls_encap(ctx->sh_desc_enc, &ctx->cdata, &ctx->adata, -+ assoclen, ivsize, ctx->authsize, blocksize, -+ ctrlpriv->era); -+ -+ /* -+ * TLS 1.0 decrypt shared descriptor -+ * Keys do not fit inline, regardless of algorithms used -+ */ -+ ctx->adata.key_inline = false; -+ ctx->adata.key_dma = ctx->key_dma; -+ ctx->cdata.key_dma = ctx->key_dma + ctx->adata.keylen_pad; -+ -+ cnstr_shdsc_tls_decap(ctx->sh_desc_dec, &ctx->cdata, &ctx->adata, -+ assoclen, ivsize, ctx->authsize, blocksize, -+ ctrlpriv->era); -+ -+ return 0; -+} -+ -+static int tls_setauthsize(struct crypto_aead *tls, unsigned int authsize) -+{ -+ struct caam_ctx *ctx = crypto_aead_ctx(tls); -+ -+ ctx->authsize = authsize; -+ tls_set_sh_desc(tls); -+ -+ return 0; -+} -+ -+static int tls_setkey(struct crypto_aead *tls, const u8 *key, -+ unsigned int keylen) -+{ -+ struct caam_ctx *ctx = crypto_aead_ctx(tls); -+ struct device *jrdev = ctx->jrdev; -+ struct caam_drv_private *ctrlpriv = dev_get_drvdata(jrdev->parent); -+ struct crypto_authenc_keys keys; -+ int ret = 0; -+ -+ if (crypto_authenc_extractkeys(&keys, key, keylen) != 0) -+ goto badkey; -+ -+#ifdef DEBUG -+ dev_err(jrdev, "keylen %d enckeylen %d authkeylen %d\n", -+ keys.authkeylen + keys.enckeylen, keys.enckeylen, -+ keys.authkeylen); -+ print_hex_dump(KERN_ERR, "key in @" __stringify(__LINE__)": ", -+ DUMP_PREFIX_ADDRESS, 16, 4, key, keylen, 1); -+#endif -+ -+ /* -+ * If DKP is supported, use it in the shared descriptor to generate -+ * the split key. -+ */ -+ if (ctrlpriv->era >= 6) { -+ ctx->adata.keylen = keys.authkeylen; -+ ctx->adata.keylen_pad = split_key_len(ctx->adata.algtype & -+ OP_ALG_ALGSEL_MASK); -+ -+ if (ctx->adata.keylen_pad + keys.enckeylen > CAAM_MAX_KEY_SIZE) -+ goto badkey; -+ -+ memcpy(ctx->key, keys.authkey, keys.authkeylen); -+ memcpy(ctx->key + ctx->adata.keylen_pad, keys.enckey, -+ keys.enckeylen); -+ dma_sync_single_for_device(jrdev, ctx->key_dma, -+ ctx->adata.keylen_pad + -+ keys.enckeylen, ctx->dir); -+ goto skip_split_key; -+ } -+ -+ ret = gen_split_key(jrdev, ctx->key, &ctx->adata, keys.authkey, -+ keys.authkeylen, CAAM_MAX_KEY_SIZE - -+ keys.enckeylen); -+ if (ret) -+ goto badkey; -+ -+ /* postpend encryption key to auth split key */ -+ memcpy(ctx->key + ctx->adata.keylen_pad, keys.enckey, keys.enckeylen); -+ dma_sync_single_for_device(jrdev, ctx->key_dma, ctx->adata.keylen_pad + -+ keys.enckeylen, ctx->dir); -+ -+#ifdef DEBUG -+ dev_err(jrdev, "split keylen %d split keylen padded %d\n", -+ ctx->adata.keylen, ctx->adata.keylen_pad); -+ print_hex_dump(KERN_ERR, "ctx.key@" __stringify(__LINE__)": ", -+ DUMP_PREFIX_ADDRESS, 16, 4, ctx->key, -+ ctx->adata.keylen_pad + keys.enckeylen, 1); -+#endif -+ -+skip_split_key: -+ ctx->cdata.keylen = keys.enckeylen; -+ -+ ret = tls_set_sh_desc(tls); -+ if (ret) -+ goto badkey; -+ -+ /* Now update the driver contexts with the new shared descriptor */ -+ if (ctx->drv_ctx[ENCRYPT]) { -+ ret = caam_drv_ctx_update(ctx->drv_ctx[ENCRYPT], -+ ctx->sh_desc_enc); -+ if (ret) { -+ dev_err(jrdev, "driver enc context update failed\n"); -+ goto badkey; -+ } -+ } -+ -+ if (ctx->drv_ctx[DECRYPT]) { -+ ret = caam_drv_ctx_update(ctx->drv_ctx[DECRYPT], -+ ctx->sh_desc_dec); -+ if (ret) { -+ dev_err(jrdev, "driver dec context update failed\n"); -+ goto badkey; -+ } -+ } -+ -+ return ret; -+badkey: -+ crypto_aead_set_flags(tls, CRYPTO_TFM_RES_BAD_KEY_LEN); -+ return -EINVAL; -+} -+ -+static int gcm_set_sh_desc(struct crypto_aead *aead) -+{ -+ struct caam_ctx *ctx = crypto_aead_ctx(aead); -+ unsigned int ivsize = crypto_aead_ivsize(aead); -+ int rem_bytes = CAAM_DESC_BYTES_MAX - DESC_JOB_IO_LEN - -+ ctx->cdata.keylen; -+ -+ if (!ctx->cdata.keylen || !ctx->authsize) -+ return 0; -+ -+ /* -+ * Job Descriptor and Shared Descriptor -+ * must fit into the 64-word Descriptor h/w Buffer -+ */ -+ if (rem_bytes >= DESC_QI_GCM_ENC_LEN) { -+ ctx->cdata.key_inline = true; -+ ctx->cdata.key_virt = ctx->key; -+ } else { -+ ctx->cdata.key_inline = false; -+ ctx->cdata.key_dma = ctx->key_dma; -+ } -+ -+ cnstr_shdsc_gcm_encap(ctx->sh_desc_enc, &ctx->cdata, ivsize, -+ ctx->authsize, true); -+ -+ /* -+ * Job Descriptor and Shared Descriptor -+ * must fit into the 64-word Descriptor h/w Buffer -+ */ -+ if (rem_bytes >= DESC_QI_GCM_DEC_LEN) { -+ ctx->cdata.key_inline = true; -+ ctx->cdata.key_virt = ctx->key; -+ } else { -+ ctx->cdata.key_inline = false; -+ ctx->cdata.key_dma = ctx->key_dma; -+ } -+ -+ cnstr_shdsc_gcm_decap(ctx->sh_desc_dec, &ctx->cdata, ivsize, -+ ctx->authsize, true); -+ -+ return 0; -+} -+ -+static int gcm_setauthsize(struct crypto_aead *authenc, unsigned int authsize) -+{ -+ struct caam_ctx *ctx = crypto_aead_ctx(authenc); -+ -+ ctx->authsize = authsize; -+ gcm_set_sh_desc(authenc); -+ -+ return 0; -+} -+ -+static int gcm_setkey(struct crypto_aead *aead, -+ const u8 *key, unsigned int keylen) -+{ -+ struct caam_ctx *ctx = crypto_aead_ctx(aead); -+ struct device *jrdev = ctx->jrdev; -+ int ret; -+ -+#ifdef DEBUG -+ print_hex_dump(KERN_ERR, "key in @" __stringify(__LINE__)": ", -+ DUMP_PREFIX_ADDRESS, 16, 4, key, keylen, 1); -+#endif -+ -+ memcpy(ctx->key, key, keylen); -+ dma_sync_single_for_device(jrdev, ctx->key_dma, keylen, ctx->dir); -+ ctx->cdata.keylen = keylen; -+ -+ ret = gcm_set_sh_desc(aead); -+ if (ret) -+ return ret; -+ -+ /* Now update the driver contexts with the new shared descriptor */ -+ if (ctx->drv_ctx[ENCRYPT]) { -+ ret = caam_drv_ctx_update(ctx->drv_ctx[ENCRYPT], -+ ctx->sh_desc_enc); -+ if (ret) { -+ dev_err(jrdev, "driver enc context update failed\n"); -+ return ret; -+ } -+ } -+ -+ if (ctx->drv_ctx[DECRYPT]) { -+ ret = caam_drv_ctx_update(ctx->drv_ctx[DECRYPT], -+ ctx->sh_desc_dec); -+ if (ret) { -+ dev_err(jrdev, "driver dec context update failed\n"); -+ return ret; -+ } -+ } -+ -+ return 0; -+} -+ -+static int rfc4106_set_sh_desc(struct crypto_aead *aead) -+{ -+ struct caam_ctx *ctx = crypto_aead_ctx(aead); -+ unsigned int ivsize = crypto_aead_ivsize(aead); -+ int rem_bytes = CAAM_DESC_BYTES_MAX - DESC_JOB_IO_LEN - -+ ctx->cdata.keylen; -+ -+ if (!ctx->cdata.keylen || !ctx->authsize) -+ return 0; -+ -+ ctx->cdata.key_virt = ctx->key; -+ -+ /* -+ * Job Descriptor and Shared Descriptor -+ * must fit into the 64-word Descriptor h/w Buffer -+ */ -+ if (rem_bytes >= DESC_QI_RFC4106_ENC_LEN) { -+ ctx->cdata.key_inline = true; -+ } else { -+ ctx->cdata.key_inline = false; -+ ctx->cdata.key_dma = ctx->key_dma; -+ } -+ -+ cnstr_shdsc_rfc4106_encap(ctx->sh_desc_enc, &ctx->cdata, ivsize, -+ ctx->authsize, true); -+ -+ /* -+ * Job Descriptor and Shared Descriptor -+ * must fit into the 64-word Descriptor h/w Buffer -+ */ -+ if (rem_bytes >= DESC_QI_RFC4106_DEC_LEN) { -+ ctx->cdata.key_inline = true; -+ } else { -+ ctx->cdata.key_inline = false; -+ ctx->cdata.key_dma = ctx->key_dma; -+ } -+ -+ cnstr_shdsc_rfc4106_decap(ctx->sh_desc_dec, &ctx->cdata, ivsize, -+ ctx->authsize, true); -+ -+ return 0; -+} -+ -+static int rfc4106_setauthsize(struct crypto_aead *authenc, -+ unsigned int authsize) -+{ -+ struct caam_ctx *ctx = crypto_aead_ctx(authenc); -+ -+ ctx->authsize = authsize; -+ rfc4106_set_sh_desc(authenc); -+ -+ return 0; -+} -+ -+static int rfc4106_setkey(struct crypto_aead *aead, -+ const u8 *key, unsigned int keylen) -+{ -+ struct caam_ctx *ctx = crypto_aead_ctx(aead); -+ struct device *jrdev = ctx->jrdev; -+ int ret; -+ -+ if (keylen < 4) -+ return -EINVAL; -+ -+#ifdef DEBUG -+ print_hex_dump(KERN_ERR, "key in @" __stringify(__LINE__)": ", -+ DUMP_PREFIX_ADDRESS, 16, 4, key, keylen, 1); -+#endif -+ -+ memcpy(ctx->key, key, keylen); -+ /* -+ * The last four bytes of the key material are used as the salt value -+ * in the nonce. Update the AES key length. -+ */ -+ ctx->cdata.keylen = keylen - 4; -+ dma_sync_single_for_device(jrdev, ctx->key_dma, ctx->cdata.keylen, -+ ctx->dir); -+ -+ ret = rfc4106_set_sh_desc(aead); -+ if (ret) -+ return ret; -+ -+ /* Now update the driver contexts with the new shared descriptor */ -+ if (ctx->drv_ctx[ENCRYPT]) { -+ ret = caam_drv_ctx_update(ctx->drv_ctx[ENCRYPT], -+ ctx->sh_desc_enc); -+ if (ret) { -+ dev_err(jrdev, "driver enc context update failed\n"); -+ return ret; -+ } -+ } -+ -+ if (ctx->drv_ctx[DECRYPT]) { -+ ret = caam_drv_ctx_update(ctx->drv_ctx[DECRYPT], -+ ctx->sh_desc_dec); -+ if (ret) { -+ dev_err(jrdev, "driver dec context update failed\n"); -+ return ret; -+ } -+ } -+ -+ return 0; -+} -+ -+static int rfc4543_set_sh_desc(struct crypto_aead *aead) -+{ -+ struct caam_ctx *ctx = crypto_aead_ctx(aead); -+ unsigned int ivsize = crypto_aead_ivsize(aead); -+ int rem_bytes = CAAM_DESC_BYTES_MAX - DESC_JOB_IO_LEN - -+ ctx->cdata.keylen; -+ -+ if (!ctx->cdata.keylen || !ctx->authsize) -+ return 0; -+ -+ ctx->cdata.key_virt = ctx->key; -+ -+ /* -+ * Job Descriptor and Shared Descriptor -+ * must fit into the 64-word Descriptor h/w Buffer -+ */ -+ if (rem_bytes >= DESC_QI_RFC4543_ENC_LEN) { -+ ctx->cdata.key_inline = true; -+ } else { -+ ctx->cdata.key_inline = false; -+ ctx->cdata.key_dma = ctx->key_dma; -+ } -+ -+ cnstr_shdsc_rfc4543_encap(ctx->sh_desc_enc, &ctx->cdata, ivsize, -+ ctx->authsize, true); -+ -+ /* -+ * Job Descriptor and Shared Descriptor -+ * must fit into the 64-word Descriptor h/w Buffer -+ */ -+ if (rem_bytes >= DESC_QI_RFC4543_DEC_LEN) { -+ ctx->cdata.key_inline = true; -+ } else { -+ ctx->cdata.key_inline = false; -+ ctx->cdata.key_dma = ctx->key_dma; -+ } -+ -+ cnstr_shdsc_rfc4543_decap(ctx->sh_desc_dec, &ctx->cdata, ivsize, -+ ctx->authsize, true); -+ -+ return 0; -+} -+ -+static int rfc4543_setauthsize(struct crypto_aead *authenc, -+ unsigned int authsize) -+{ -+ struct caam_ctx *ctx = crypto_aead_ctx(authenc); -+ -+ ctx->authsize = authsize; -+ rfc4543_set_sh_desc(authenc); -+ -+ return 0; -+} -+ -+static int rfc4543_setkey(struct crypto_aead *aead, -+ const u8 *key, unsigned int keylen) -+{ -+ struct caam_ctx *ctx = crypto_aead_ctx(aead); -+ struct device *jrdev = ctx->jrdev; -+ int ret; -+ -+ if (keylen < 4) -+ return -EINVAL; -+ -+#ifdef DEBUG -+ print_hex_dump(KERN_ERR, "key in @" __stringify(__LINE__)": ", -+ DUMP_PREFIX_ADDRESS, 16, 4, key, keylen, 1); -+#endif -+ -+ memcpy(ctx->key, key, keylen); -+ /* -+ * The last four bytes of the key material are used as the salt value -+ * in the nonce. Update the AES key length. -+ */ -+ ctx->cdata.keylen = keylen - 4; -+ dma_sync_single_for_device(jrdev, ctx->key_dma, ctx->cdata.keylen, -+ ctx->dir); -+ -+ ret = rfc4543_set_sh_desc(aead); -+ if (ret) -+ return ret; -+ -+ /* Now update the driver contexts with the new shared descriptor */ -+ if (ctx->drv_ctx[ENCRYPT]) { -+ ret = caam_drv_ctx_update(ctx->drv_ctx[ENCRYPT], -+ ctx->sh_desc_enc); -+ if (ret) { -+ dev_err(jrdev, "driver enc context update failed\n"); -+ return ret; -+ } -+ } -+ -+ if (ctx->drv_ctx[DECRYPT]) { -+ ret = caam_drv_ctx_update(ctx->drv_ctx[DECRYPT], -+ ctx->sh_desc_dec); -+ if (ret) { -+ dev_err(jrdev, "driver dec context update failed\n"); -+ return ret; -+ } -+ } -+ -+ return 0; -+} -+ - static int ablkcipher_setkey(struct crypto_ablkcipher *ablkcipher, - const u8 *key, unsigned int keylen) - { -@@ -414,6 +902,29 @@ struct aead_edesc { - }; - - /* -+ * tls_edesc - s/w-extended tls descriptor -+ * @src_nents: number of segments in input scatterlist -+ * @dst_nents: number of segments in output scatterlist -+ * @iv_dma: dma address of iv for checking continuity and link table -+ * @qm_sg_bytes: length of dma mapped h/w link table -+ * @tmp: array of scatterlists used by 'scatterwalk_ffwd' -+ * @qm_sg_dma: bus physical mapped address of h/w link table -+ * @drv_req: driver-specific request structure -+ * @sgt: the h/w link table, followed by IV -+ */ -+struct tls_edesc { -+ int src_nents; -+ int dst_nents; -+ dma_addr_t iv_dma; -+ int qm_sg_bytes; -+ dma_addr_t qm_sg_dma; -+ struct scatterlist tmp[2]; -+ struct scatterlist *dst; -+ struct caam_drv_req drv_req; -+ struct qm_sg_entry sgt[0]; -+}; -+ -+/* - * ablkcipher_edesc - s/w-extended ablkcipher descriptor - * @src_nents: number of segments in input scatterlist - * @dst_nents: number of segments in output scatterlist -@@ -508,6 +1019,19 @@ static void aead_unmap(struct device *de - dma_unmap_single(dev, edesc->assoclen_dma, 4, DMA_TO_DEVICE); - } - -+static void tls_unmap(struct device *dev, -+ struct tls_edesc *edesc, -+ struct aead_request *req) -+{ -+ struct crypto_aead *aead = crypto_aead_reqtfm(req); -+ int ivsize = crypto_aead_ivsize(aead); -+ -+ caam_unmap(dev, req->src, edesc->dst, edesc->src_nents, -+ edesc->dst_nents, edesc->iv_dma, ivsize, -+ edesc->drv_req.drv_ctx->op_type, edesc->qm_sg_dma, -+ edesc->qm_sg_bytes); -+} -+ - static void ablkcipher_unmap(struct device *dev, - struct ablkcipher_edesc *edesc, - struct ablkcipher_request *req) -@@ -532,8 +1056,18 @@ static void aead_done(struct caam_drv_re - qidev = caam_ctx->qidev; - - if (unlikely(status)) { -+ u32 ssrc = status & JRSTA_SSRC_MASK; -+ u8 err_id = status & JRSTA_CCBERR_ERRID_MASK; -+ - caam_jr_strstatus(qidev, status); -- ecode = -EIO; -+ /* -+ * verify hw auth check passed else return -EBADMSG -+ */ -+ if (ssrc == JRSTA_SSRC_CCB_ERROR && -+ err_id == JRSTA_CCBERR_ERRID_ICVCHK) -+ ecode = -EBADMSG; -+ else -+ ecode = -EIO; - } - - edesc = container_of(drv_req, typeof(*edesc), drv_req); -@@ -647,9 +1181,24 @@ static struct aead_edesc *aead_edesc_all - /* - * Create S/G table: req->assoclen, [IV,] req->src [, req->dst]. - * Input is not contiguous. -+ * HW reads 4 S/G entries at a time; make sure the reads don't go beyond -+ * the end of the table by allocating more S/G entries. Logic: -+ * if (src != dst && output S/G) -+ * pad output S/G, if needed -+ * else if (src == dst && S/G) -+ * overlapping S/Gs; pad one of them -+ * else if (input S/G) ... -+ * pad input S/G, if needed - */ -- qm_sg_ents = 1 + !!ivsize + mapped_src_nents + -- (mapped_dst_nents > 1 ? mapped_dst_nents : 0); -+ qm_sg_ents = 1 + !!ivsize + mapped_src_nents; -+ if (mapped_dst_nents > 1) -+ qm_sg_ents += ALIGN(mapped_dst_nents, 4); -+ else if ((req->src == req->dst) && (mapped_src_nents > 1)) -+ qm_sg_ents = max(ALIGN(qm_sg_ents, 4), -+ 1 + !!ivsize + ALIGN(mapped_src_nents, 4)); -+ else -+ qm_sg_ents = ALIGN(qm_sg_ents, 4); -+ - sg_table = &edesc->sgt[0]; - qm_sg_bytes = qm_sg_ents * sizeof(*sg_table); - if (unlikely(offsetof(struct aead_edesc, sgt) + qm_sg_bytes + ivsize > -@@ -785,6 +1334,260 @@ static int aead_decrypt(struct aead_requ - return aead_crypt(req, false); - } - -+static int ipsec_gcm_encrypt(struct aead_request *req) -+{ -+ if (req->assoclen < 8) -+ return -EINVAL; -+ -+ return aead_crypt(req, true); -+} -+ -+static int ipsec_gcm_decrypt(struct aead_request *req) -+{ -+ if (req->assoclen < 8) -+ return -EINVAL; -+ -+ return aead_crypt(req, false); -+} -+ -+static void tls_done(struct caam_drv_req *drv_req, u32 status) -+{ -+ struct device *qidev; -+ struct tls_edesc *edesc; -+ struct aead_request *aead_req = drv_req->app_ctx; -+ struct crypto_aead *aead = crypto_aead_reqtfm(aead_req); -+ struct caam_ctx *caam_ctx = crypto_aead_ctx(aead); -+ int ecode = 0; -+ -+ qidev = caam_ctx->qidev; -+ -+ if (unlikely(status)) { -+ caam_jr_strstatus(qidev, status); -+ ecode = -EIO; -+ } -+ -+ edesc = container_of(drv_req, typeof(*edesc), drv_req); -+ tls_unmap(qidev, edesc, aead_req); -+ -+ aead_request_complete(aead_req, ecode); -+ qi_cache_free(edesc); -+} -+ -+/* -+ * allocate and map the tls extended descriptor -+ */ -+static struct tls_edesc *tls_edesc_alloc(struct aead_request *req, bool encrypt) -+{ -+ struct crypto_aead *aead = crypto_aead_reqtfm(req); -+ struct caam_ctx *ctx = crypto_aead_ctx(aead); -+ unsigned int blocksize = crypto_aead_blocksize(aead); -+ unsigned int padsize, authsize; -+ struct caam_aead_alg *alg = container_of(crypto_aead_alg(aead), -+ typeof(*alg), aead); -+ struct device *qidev = ctx->qidev; -+ gfp_t flags = (req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP) ? -+ GFP_KERNEL : GFP_ATOMIC; -+ int src_nents, mapped_src_nents, dst_nents = 0, mapped_dst_nents = 0; -+ struct tls_edesc *edesc; -+ dma_addr_t qm_sg_dma, iv_dma = 0; -+ int ivsize = 0; -+ u8 *iv; -+ int qm_sg_index, qm_sg_ents = 0, qm_sg_bytes; -+ int in_len, out_len; -+ struct qm_sg_entry *sg_table, *fd_sgt; -+ struct caam_drv_ctx *drv_ctx; -+ enum optype op_type = encrypt ? ENCRYPT : DECRYPT; -+ struct scatterlist *dst; -+ -+ if (encrypt) { -+ padsize = blocksize - ((req->cryptlen + ctx->authsize) % -+ blocksize); -+ authsize = ctx->authsize + padsize; -+ } else { -+ authsize = ctx->authsize; -+ } -+ -+ drv_ctx = get_drv_ctx(ctx, op_type); -+ if (unlikely(IS_ERR_OR_NULL(drv_ctx))) -+ return (struct tls_edesc *)drv_ctx; -+ -+ /* allocate space for base edesc, link tables and IV */ -+ edesc = qi_cache_alloc(GFP_DMA | flags); -+ if (unlikely(!edesc)) { -+ dev_err(qidev, "could not allocate extended descriptor\n"); -+ return ERR_PTR(-ENOMEM); -+ } -+ -+ if (likely(req->src == req->dst)) { -+ src_nents = sg_nents_for_len(req->src, req->assoclen + -+ req->cryptlen + -+ (encrypt ? authsize : 0)); -+ if (unlikely(src_nents < 0)) { -+ dev_err(qidev, "Insufficient bytes (%d) in src S/G\n", -+ req->assoclen + req->cryptlen + -+ (encrypt ? authsize : 0)); -+ qi_cache_free(edesc); -+ return ERR_PTR(src_nents); -+ } -+ -+ mapped_src_nents = dma_map_sg(qidev, req->src, src_nents, -+ DMA_BIDIRECTIONAL); -+ if (unlikely(!mapped_src_nents)) { -+ dev_err(qidev, "unable to map source\n"); -+ qi_cache_free(edesc); -+ return ERR_PTR(-ENOMEM); -+ } -+ dst = req->dst; -+ } else { -+ src_nents = sg_nents_for_len(req->src, req->assoclen + -+ req->cryptlen); -+ if (unlikely(src_nents < 0)) { -+ dev_err(qidev, "Insufficient bytes (%d) in src S/G\n", -+ req->assoclen + req->cryptlen); -+ qi_cache_free(edesc); -+ return ERR_PTR(src_nents); -+ } -+ -+ dst = scatterwalk_ffwd(edesc->tmp, req->dst, req->assoclen); -+ dst_nents = sg_nents_for_len(dst, req->cryptlen + -+ (encrypt ? authsize : 0)); -+ if (unlikely(dst_nents < 0)) { -+ dev_err(qidev, "Insufficient bytes (%d) in dst S/G\n", -+ req->cryptlen + -+ (encrypt ? authsize : 0)); -+ qi_cache_free(edesc); -+ return ERR_PTR(dst_nents); -+ } -+ -+ if (src_nents) { -+ mapped_src_nents = dma_map_sg(qidev, req->src, -+ src_nents, DMA_TO_DEVICE); -+ if (unlikely(!mapped_src_nents)) { -+ dev_err(qidev, "unable to map source\n"); -+ qi_cache_free(edesc); -+ return ERR_PTR(-ENOMEM); -+ } -+ } else { -+ mapped_src_nents = 0; -+ } -+ -+ mapped_dst_nents = dma_map_sg(qidev, dst, dst_nents, -+ DMA_FROM_DEVICE); -+ if (unlikely(!mapped_dst_nents)) { -+ dev_err(qidev, "unable to map destination\n"); -+ dma_unmap_sg(qidev, req->src, src_nents, DMA_TO_DEVICE); -+ qi_cache_free(edesc); -+ return ERR_PTR(-ENOMEM); -+ } -+ } -+ -+ /* -+ * Create S/G table: IV, src, dst. -+ * Input is not contiguous. -+ */ -+ qm_sg_ents = 1 + mapped_src_nents + -+ (mapped_dst_nents > 1 ? mapped_dst_nents : 0); -+ sg_table = &edesc->sgt[0]; -+ qm_sg_bytes = qm_sg_ents * sizeof(*sg_table); -+ -+ ivsize = crypto_aead_ivsize(aead); -+ iv = (u8 *)(sg_table + qm_sg_ents); -+ /* Make sure IV is located in a DMAable area */ -+ memcpy(iv, req->iv, ivsize); -+ iv_dma = dma_map_single(qidev, iv, ivsize, DMA_TO_DEVICE); -+ if (dma_mapping_error(qidev, iv_dma)) { -+ dev_err(qidev, "unable to map IV\n"); -+ caam_unmap(qidev, req->src, dst, src_nents, dst_nents, 0, 0, 0, -+ 0, 0); -+ qi_cache_free(edesc); -+ return ERR_PTR(-ENOMEM); -+ } -+ -+ edesc->src_nents = src_nents; -+ edesc->dst_nents = dst_nents; -+ edesc->dst = dst; -+ edesc->iv_dma = iv_dma; -+ edesc->drv_req.app_ctx = req; -+ edesc->drv_req.cbk = tls_done; -+ edesc->drv_req.drv_ctx = drv_ctx; -+ -+ dma_to_qm_sg_one(sg_table, iv_dma, ivsize, 0); -+ qm_sg_index = 1; -+ -+ sg_to_qm_sg_last(req->src, mapped_src_nents, sg_table + qm_sg_index, 0); -+ qm_sg_index += mapped_src_nents; -+ -+ if (mapped_dst_nents > 1) -+ sg_to_qm_sg_last(dst, mapped_dst_nents, sg_table + -+ qm_sg_index, 0); -+ -+ qm_sg_dma = dma_map_single(qidev, sg_table, qm_sg_bytes, DMA_TO_DEVICE); -+ if (dma_mapping_error(qidev, qm_sg_dma)) { -+ dev_err(qidev, "unable to map S/G table\n"); -+ caam_unmap(qidev, req->src, dst, src_nents, dst_nents, iv_dma, -+ ivsize, op_type, 0, 0); -+ qi_cache_free(edesc); -+ return ERR_PTR(-ENOMEM); -+ } -+ -+ edesc->qm_sg_dma = qm_sg_dma; -+ edesc->qm_sg_bytes = qm_sg_bytes; -+ -+ out_len = req->cryptlen + (encrypt ? authsize : 0); -+ in_len = ivsize + req->assoclen + req->cryptlen; -+ -+ fd_sgt = &edesc->drv_req.fd_sgt[0]; -+ -+ dma_to_qm_sg_one_last_ext(&fd_sgt[1], qm_sg_dma, in_len, 0); -+ -+ if (req->dst == req->src) -+ dma_to_qm_sg_one_ext(&fd_sgt[0], qm_sg_dma + -+ (sg_nents_for_len(req->src, req->assoclen) + -+ 1) * sizeof(*sg_table), out_len, 0); -+ else if (mapped_dst_nents == 1) -+ dma_to_qm_sg_one(&fd_sgt[0], sg_dma_address(dst), out_len, 0); -+ else -+ dma_to_qm_sg_one_ext(&fd_sgt[0], qm_sg_dma + sizeof(*sg_table) * -+ qm_sg_index, out_len, 0); -+ -+ return edesc; -+} -+ -+static int tls_crypt(struct aead_request *req, bool encrypt) -+{ -+ struct tls_edesc *edesc; -+ struct crypto_aead *aead = crypto_aead_reqtfm(req); -+ struct caam_ctx *ctx = crypto_aead_ctx(aead); -+ int ret; -+ -+ if (unlikely(caam_congested)) -+ return -EAGAIN; -+ -+ edesc = tls_edesc_alloc(req, encrypt); -+ if (IS_ERR_OR_NULL(edesc)) -+ return PTR_ERR(edesc); -+ -+ ret = caam_qi_enqueue(ctx->qidev, &edesc->drv_req); -+ if (!ret) { -+ ret = -EINPROGRESS; -+ } else { -+ tls_unmap(ctx->qidev, edesc, req); -+ qi_cache_free(edesc); -+ } -+ -+ return ret; -+} -+ -+static int tls_encrypt(struct aead_request *req) -+{ -+ return tls_crypt(req, true); -+} -+ -+static int tls_decrypt(struct aead_request *req) -+{ -+ return tls_crypt(req, false); -+} -+ - static void ablkcipher_done(struct caam_drv_req *drv_req, u32 status) - { - struct ablkcipher_edesc *edesc; -@@ -900,7 +1703,24 @@ static struct ablkcipher_edesc *ablkciph - qm_sg_ents = 1 + mapped_src_nents; - dst_sg_idx = qm_sg_ents; - -- qm_sg_ents += mapped_dst_nents > 1 ? mapped_dst_nents : 0; -+ /* -+ * HW reads 4 S/G entries at a time; make sure the reads don't go beyond -+ * the end of the table by allocating more S/G entries. Logic: -+ * if (src != dst && output S/G) -+ * pad output S/G, if needed -+ * else if (src == dst && S/G) -+ * overlapping S/Gs; pad one of them -+ * else if (input S/G) ... -+ * pad input S/G, if needed -+ */ -+ if (mapped_dst_nents > 1) -+ qm_sg_ents += ALIGN(mapped_dst_nents, 4); -+ else if ((req->src == req->dst) && (mapped_src_nents > 1)) -+ qm_sg_ents = max(ALIGN(qm_sg_ents, 4), -+ 1 + ALIGN(mapped_src_nents, 4)); -+ else -+ qm_sg_ents = ALIGN(qm_sg_ents, 4); -+ - qm_sg_bytes = qm_sg_ents * sizeof(struct qm_sg_entry); - if (unlikely(offsetof(struct ablkcipher_edesc, sgt) + qm_sg_bytes + - ivsize > CAAM_QI_MEMCACHE_SIZE)) { -@@ -1308,6 +2128,61 @@ static struct caam_alg_template driver_a - }; - - static struct caam_aead_alg driver_aeads[] = { -+ { -+ .aead = { -+ .base = { -+ .cra_name = "rfc4106(gcm(aes))", -+ .cra_driver_name = "rfc4106-gcm-aes-caam-qi", -+ .cra_blocksize = 1, -+ }, -+ .setkey = rfc4106_setkey, -+ .setauthsize = rfc4106_setauthsize, -+ .encrypt = ipsec_gcm_encrypt, -+ .decrypt = ipsec_gcm_decrypt, -+ .ivsize = 8, -+ .maxauthsize = AES_BLOCK_SIZE, -+ }, -+ .caam = { -+ .class1_alg_type = OP_ALG_ALGSEL_AES | OP_ALG_AAI_GCM, -+ }, -+ }, -+ { -+ .aead = { -+ .base = { -+ .cra_name = "rfc4543(gcm(aes))", -+ .cra_driver_name = "rfc4543-gcm-aes-caam-qi", -+ .cra_blocksize = 1, -+ }, -+ .setkey = rfc4543_setkey, -+ .setauthsize = rfc4543_setauthsize, -+ .encrypt = ipsec_gcm_encrypt, -+ .decrypt = ipsec_gcm_decrypt, -+ .ivsize = 8, -+ .maxauthsize = AES_BLOCK_SIZE, -+ }, -+ .caam = { -+ .class1_alg_type = OP_ALG_ALGSEL_AES | OP_ALG_AAI_GCM, -+ }, -+ }, -+ /* Galois Counter Mode */ -+ { -+ .aead = { -+ .base = { -+ .cra_name = "gcm(aes)", -+ .cra_driver_name = "gcm-aes-caam-qi", -+ .cra_blocksize = 1, -+ }, -+ .setkey = gcm_setkey, -+ .setauthsize = gcm_setauthsize, -+ .encrypt = aead_encrypt, -+ .decrypt = aead_decrypt, -+ .ivsize = 12, -+ .maxauthsize = AES_BLOCK_SIZE, -+ }, -+ .caam = { -+ .class1_alg_type = OP_ALG_ALGSEL_AES | OP_ALG_AAI_GCM, -+ } -+ }, - /* single-pass ipsec_esp descriptor */ - { - .aead = { -@@ -2118,6 +2993,26 @@ static struct caam_aead_alg driver_aeads - .geniv = true, - } - }, -+ { -+ .aead = { -+ .base = { -+ .cra_name = "tls10(hmac(sha1),cbc(aes))", -+ .cra_driver_name = "tls10-hmac-sha1-cbc-aes-caam-qi", -+ .cra_blocksize = AES_BLOCK_SIZE, -+ }, -+ .setkey = tls_setkey, -+ .setauthsize = tls_setauthsize, -+ .encrypt = tls_encrypt, -+ .decrypt = tls_decrypt, -+ .ivsize = AES_BLOCK_SIZE, -+ .maxauthsize = SHA1_DIGEST_SIZE, -+ }, -+ .caam = { -+ .class1_alg_type = OP_ALG_ALGSEL_AES | OP_ALG_AAI_CBC, -+ .class2_alg_type = OP_ALG_ALGSEL_SHA1 | -+ OP_ALG_AAI_HMAC_PRECOMP, -+ } -+ } - }; - - struct caam_crypto_alg { -@@ -2126,9 +3021,21 @@ struct caam_crypto_alg { - struct caam_alg_entry caam; - }; - --static int caam_init_common(struct caam_ctx *ctx, struct caam_alg_entry *caam) -+static int caam_init_common(struct caam_ctx *ctx, struct caam_alg_entry *caam, -+ bool uses_dkp) - { - struct caam_drv_private *priv; -+ struct device *dev; -+ /* Digest sizes for MD5, SHA1, SHA-224, SHA-256, SHA-384, SHA-512 */ -+ static const u8 digest_size[] = { -+ MD5_DIGEST_SIZE, -+ SHA1_DIGEST_SIZE, -+ SHA224_DIGEST_SIZE, -+ SHA256_DIGEST_SIZE, -+ SHA384_DIGEST_SIZE, -+ SHA512_DIGEST_SIZE -+ }; -+ u8 op_id; - - /* - * distribute tfms across job rings to ensure in-order -@@ -2140,10 +3047,19 @@ static int caam_init_common(struct caam_ - return PTR_ERR(ctx->jrdev); - } - -- ctx->key_dma = dma_map_single(ctx->jrdev, ctx->key, sizeof(ctx->key), -- DMA_TO_DEVICE); -- if (dma_mapping_error(ctx->jrdev, ctx->key_dma)) { -- dev_err(ctx->jrdev, "unable to map key\n"); -+ priv = dev_get_drvdata(ctx->jrdev->parent); -+ if (priv->era >= 6 && uses_dkp) { -+ ctx->dir = DMA_BIDIRECTIONAL; -+ dev = ctx->jrdev->parent; -+ } else { -+ ctx->dir = DMA_TO_DEVICE; -+ dev = ctx->jrdev; -+ } -+ -+ ctx->key_dma = dma_map_single(dev, ctx->key, sizeof(ctx->key), -+ ctx->dir); -+ if (dma_mapping_error(dev, ctx->key_dma)) { -+ dev_err(dev, "unable to map key\n"); - caam_jr_free(ctx->jrdev); - return -ENOMEM; - } -@@ -2152,8 +3068,23 @@ static int caam_init_common(struct caam_ - ctx->cdata.algtype = OP_TYPE_CLASS1_ALG | caam->class1_alg_type; - ctx->adata.algtype = OP_TYPE_CLASS2_ALG | caam->class2_alg_type; - -- priv = dev_get_drvdata(ctx->jrdev->parent); -- ctx->qidev = priv->qidev; -+ if (ctx->adata.algtype) { -+ op_id = (ctx->adata.algtype & OP_ALG_ALGSEL_SUBMASK) -+ >> OP_ALG_ALGSEL_SHIFT; -+ if (op_id < ARRAY_SIZE(digest_size)) { -+ ctx->authsize = digest_size[op_id]; -+ } else { -+ dev_err(ctx->jrdev, -+ "incorrect op_id %d; must be less than %zu\n", -+ op_id, ARRAY_SIZE(digest_size)); -+ caam_jr_free(ctx->jrdev); -+ return -EINVAL; -+ } -+ } else { -+ ctx->authsize = 0; -+ } -+ -+ ctx->qidev = ctx->jrdev->parent; - - spin_lock_init(&ctx->lock); - ctx->drv_ctx[ENCRYPT] = NULL; -@@ -2170,7 +3101,7 @@ static int caam_cra_init(struct crypto_t - crypto_alg); - struct caam_ctx *ctx = crypto_tfm_ctx(tfm); - -- return caam_init_common(ctx, &caam_alg->caam); -+ return caam_init_common(ctx, &caam_alg->caam, false); - } - - static int caam_aead_init(struct crypto_aead *tfm) -@@ -2180,17 +3111,25 @@ static int caam_aead_init(struct crypto_ - aead); - struct caam_ctx *ctx = crypto_aead_ctx(tfm); - -- return caam_init_common(ctx, &caam_alg->caam); -+ return caam_init_common(ctx, &caam_alg->caam, -+ (alg->setkey == aead_setkey) || -+ (alg->setkey == tls_setkey)); - } - - static void caam_exit_common(struct caam_ctx *ctx) - { -+ struct device *dev; -+ - caam_drv_ctx_rel(ctx->drv_ctx[ENCRYPT]); - caam_drv_ctx_rel(ctx->drv_ctx[DECRYPT]); - caam_drv_ctx_rel(ctx->drv_ctx[GIVENCRYPT]); - -- dma_unmap_single(ctx->jrdev, ctx->key_dma, sizeof(ctx->key), -- DMA_TO_DEVICE); -+ if (ctx->dir == DMA_BIDIRECTIONAL) -+ dev = ctx->jrdev->parent; -+ else -+ dev = ctx->jrdev; -+ -+ dma_unmap_single(dev, ctx->key_dma, sizeof(ctx->key), ctx->dir); - - caam_jr_free(ctx->jrdev); - } -@@ -2206,7 +3145,7 @@ static void caam_aead_exit(struct crypto - } - - static struct list_head alg_list; --static void __exit caam_qi_algapi_exit(void) -+void caam_qi_algapi_exit(void) - { - struct caam_crypto_alg *t_alg, *n; - int i; -@@ -2282,53 +3221,48 @@ static void caam_aead_alg_init(struct ca - alg->exit = caam_aead_exit; - } - --static int __init caam_qi_algapi_init(void) -+int caam_qi_algapi_init(struct device *ctrldev) - { -- struct device_node *dev_node; -- struct platform_device *pdev; -- struct device *ctrldev; -- struct caam_drv_private *priv; -+ struct caam_drv_private *priv = dev_get_drvdata(ctrldev); - int i = 0, err = 0; -- u32 cha_vid, cha_inst, des_inst, aes_inst, md_inst; -+ u32 aes_vid, aes_inst, des_inst, md_vid, md_inst; - unsigned int md_limit = SHA512_DIGEST_SIZE; - bool registered = false; - -- dev_node = of_find_compatible_node(NULL, NULL, "fsl,sec-v4.0"); -- if (!dev_node) { -- dev_node = of_find_compatible_node(NULL, NULL, "fsl,sec4.0"); -- if (!dev_node) -- return -ENODEV; -- } -- -- pdev = of_find_device_by_node(dev_node); -- of_node_put(dev_node); -- if (!pdev) -- return -ENODEV; -- -- ctrldev = &pdev->dev; -- priv = dev_get_drvdata(ctrldev); -- -- /* -- * If priv is NULL, it's probably because the caam driver wasn't -- * properly initialized (e.g. RNG4 init failed). Thus, bail out here. -- */ -- if (!priv || !priv->qi_present) -- return -ENODEV; -- - INIT_LIST_HEAD(&alg_list); - - /* - * Register crypto algorithms the device supports. - * First, detect presence and attributes of DES, AES, and MD blocks. - */ -- cha_vid = rd_reg32(&priv->ctrl->perfmon.cha_id_ls); -- cha_inst = rd_reg32(&priv->ctrl->perfmon.cha_num_ls); -- des_inst = (cha_inst & CHA_ID_LS_DES_MASK) >> CHA_ID_LS_DES_SHIFT; -- aes_inst = (cha_inst & CHA_ID_LS_AES_MASK) >> CHA_ID_LS_AES_SHIFT; -- md_inst = (cha_inst & CHA_ID_LS_MD_MASK) >> CHA_ID_LS_MD_SHIFT; -+ if (priv->era < 10) { -+ u32 cha_vid, cha_inst; -+ -+ cha_vid = rd_reg32(&priv->ctrl->perfmon.cha_id_ls); -+ aes_vid = cha_vid & CHA_ID_LS_AES_MASK; -+ md_vid = (cha_vid & CHA_ID_LS_MD_MASK) >> CHA_ID_LS_MD_SHIFT; -+ -+ cha_inst = rd_reg32(&priv->ctrl->perfmon.cha_num_ls); -+ des_inst = (cha_inst & CHA_ID_LS_DES_MASK) >> -+ CHA_ID_LS_DES_SHIFT; -+ aes_inst = cha_inst & CHA_ID_LS_AES_MASK; -+ md_inst = (cha_inst & CHA_ID_LS_MD_MASK) >> CHA_ID_LS_MD_SHIFT; -+ } else { -+ u32 aesa, mdha; -+ -+ aesa = rd_reg32(&priv->ctrl->vreg.aesa); -+ mdha = rd_reg32(&priv->ctrl->vreg.mdha); -+ -+ aes_vid = (aesa & CHA_VER_VID_MASK) >> CHA_VER_VID_SHIFT; -+ md_vid = (mdha & CHA_VER_VID_MASK) >> CHA_VER_VID_SHIFT; -+ -+ des_inst = rd_reg32(&priv->ctrl->vreg.desa) & CHA_VER_NUM_MASK; -+ aes_inst = aesa & CHA_VER_NUM_MASK; -+ md_inst = mdha & CHA_VER_NUM_MASK; -+ } - - /* If MD is present, limit digest size based on LP256 */ -- if (md_inst && ((cha_vid & CHA_ID_LS_MD_MASK) == CHA_ID_LS_MD_LP256)) -+ if (md_inst && md_vid == CHA_VER_VID_MD_LP256) - md_limit = SHA256_DIGEST_SIZE; - - for (i = 0; i < ARRAY_SIZE(driver_algs); i++) { -@@ -2349,14 +3283,14 @@ static int __init caam_qi_algapi_init(vo - t_alg = caam_alg_alloc(alg); - if (IS_ERR(t_alg)) { - err = PTR_ERR(t_alg); -- dev_warn(priv->qidev, "%s alg allocation failed\n", -+ dev_warn(ctrldev, "%s alg allocation failed\n", - alg->driver_name); - continue; - } - - err = crypto_register_alg(&t_alg->crypto_alg); - if (err) { -- dev_warn(priv->qidev, "%s alg registration failed\n", -+ dev_warn(ctrldev, "%s alg registration failed\n", - t_alg->crypto_alg.cra_driver_name); - kfree(t_alg); - continue; -@@ -2388,8 +3322,7 @@ static int __init caam_qi_algapi_init(vo - * Check support for AES algorithms not available - * on LP devices. - */ -- if (((cha_vid & CHA_ID_LS_AES_MASK) == CHA_ID_LS_AES_LP) && -- (alg_aai == OP_ALG_AAI_GCM)) -+ if (aes_vid == CHA_VER_VID_AES_LP && alg_aai == OP_ALG_AAI_GCM) - continue; - - /* -@@ -2414,14 +3347,7 @@ static int __init caam_qi_algapi_init(vo - } - - if (registered) -- dev_info(priv->qidev, "algorithms registered in /proc/crypto\n"); -+ dev_info(ctrldev, "algorithms registered in /proc/crypto\n"); - - return err; - } -- --module_init(caam_qi_algapi_init); --module_exit(caam_qi_algapi_exit); -- --MODULE_LICENSE("GPL"); --MODULE_DESCRIPTION("Support for crypto API using CAAM-QI backend"); --MODULE_AUTHOR("Freescale Semiconductor"); ---- /dev/null -+++ b/drivers/crypto/caam/caamalg_qi2.c -@@ -0,0 +1,5843 @@ -+// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) -+/* -+ * Copyright 2015-2016 Freescale Semiconductor Inc. -+ * Copyright 2017-2018 NXP -+ */ -+ -+#include <linux/fsl/mc.h> -+#include "compat.h" -+#include "regs.h" -+#include "caamalg_qi2.h" -+#include "dpseci_cmd.h" -+#include "desc_constr.h" -+#include "error.h" -+#include "sg_sw_sec4.h" -+#include "sg_sw_qm2.h" -+#include "key_gen.h" -+#include "caamalg_desc.h" -+#include "caamhash_desc.h" -+#include "../../../drivers/staging/fsl-mc/include/dpaa2-io.h" -+#include "../../../drivers/staging/fsl-mc/include/dpaa2-fd.h" -+ -+#define CAAM_CRA_PRIORITY 2000 -+ -+/* max key is sum of AES_MAX_KEY_SIZE, max split key size */ -+#define CAAM_MAX_KEY_SIZE (AES_MAX_KEY_SIZE + CTR_RFC3686_NONCE_SIZE + \ -+ SHA512_DIGEST_SIZE * 2) -+ -+/* -+ * This is a a cache of buffers, from which the users of CAAM QI driver -+ * can allocate short buffers. It's speedier than doing kmalloc on the hotpath. -+ * NOTE: A more elegant solution would be to have some headroom in the frames -+ * being processed. This can be added by the dpaa2-eth driver. This would -+ * pose a problem for userspace application processing which cannot -+ * know of this limitation. So for now, this will work. -+ * NOTE: The memcache is SMP-safe. No need to handle spinlocks in-here -+ */ -+static struct kmem_cache *qi_cache; -+ -+struct caam_alg_entry { -+ struct device *dev; -+ int class1_alg_type; -+ int class2_alg_type; -+ bool rfc3686; -+ bool geniv; -+}; -+ -+struct caam_aead_alg { -+ struct aead_alg aead; -+ struct caam_alg_entry caam; -+ bool registered; -+}; -+ -+struct caam_skcipher_alg { -+ struct skcipher_alg skcipher; -+ struct caam_alg_entry caam; -+ bool registered; -+}; -+ -+/** -+ * caam_ctx - per-session context -+ * @flc: Flow Contexts array -+ * @key: virtual address of the key(s): [authentication key], encryption key -+ * @flc_dma: I/O virtual addresses of the Flow Contexts -+ * @key_dma: I/O virtual address of the key -+ * @dir: DMA direction for mapping key and Flow Contexts -+ * @dev: dpseci device -+ * @adata: authentication algorithm details -+ * @cdata: encryption algorithm details -+ * @authsize: authentication tag (a.k.a. ICV / MAC) size -+ */ -+struct caam_ctx { -+ struct caam_flc flc[NUM_OP]; -+ u8 key[CAAM_MAX_KEY_SIZE]; -+ dma_addr_t flc_dma[NUM_OP]; -+ dma_addr_t key_dma; -+ enum dma_data_direction dir; -+ struct device *dev; -+ struct alginfo adata; -+ struct alginfo cdata; -+ unsigned int authsize; -+}; -+ -+void *dpaa2_caam_iova_to_virt(struct dpaa2_caam_priv *priv, -+ dma_addr_t iova_addr) -+{ -+ phys_addr_t phys_addr; -+ -+ phys_addr = priv->domain ? iommu_iova_to_phys(priv->domain, iova_addr) : -+ iova_addr; -+ -+ return phys_to_virt(phys_addr); -+} -+ -+/* -+ * qi_cache_zalloc - Allocate buffers from CAAM-QI cache -+ * -+ * Allocate data on the hotpath. Instead of using kzalloc, one can use the -+ * services of the CAAM QI memory cache (backed by kmem_cache). The buffers -+ * will have a size of CAAM_QI_MEMCACHE_SIZE, which should be sufficient for -+ * hosting 16 SG entries. -+ * -+ * @flags - flags that would be used for the equivalent kmalloc(..) call -+ * -+ * Returns a pointer to a retrieved buffer on success or NULL on failure. -+ */ -+static inline void *qi_cache_zalloc(gfp_t flags) -+{ -+ return kmem_cache_zalloc(qi_cache, flags); -+} -+ -+/* -+ * qi_cache_free - Frees buffers allocated from CAAM-QI cache -+ * -+ * @obj - buffer previously allocated by qi_cache_zalloc -+ * -+ * No checking is being done, the call is a passthrough call to -+ * kmem_cache_free(...) -+ */ -+static inline void qi_cache_free(void *obj) -+{ -+ kmem_cache_free(qi_cache, obj); -+} -+ -+static struct caam_request *to_caam_req(struct crypto_async_request *areq) -+{ -+ switch (crypto_tfm_alg_type(areq->tfm)) { -+ case CRYPTO_ALG_TYPE_SKCIPHER: -+ return skcipher_request_ctx(skcipher_request_cast(areq)); -+ case CRYPTO_ALG_TYPE_AEAD: -+ return aead_request_ctx(container_of(areq, struct aead_request, -+ base)); -+ case CRYPTO_ALG_TYPE_AHASH: -+ return ahash_request_ctx(ahash_request_cast(areq)); -+ default: -+ return ERR_PTR(-EINVAL); -+ } -+} -+ -+static void caam_unmap(struct device *dev, struct scatterlist *src, -+ struct scatterlist *dst, int src_nents, -+ int dst_nents, dma_addr_t iv_dma, int ivsize, -+ dma_addr_t qm_sg_dma, int qm_sg_bytes) -+{ -+ if (dst != src) { -+ if (src_nents) -+ dma_unmap_sg(dev, src, src_nents, DMA_TO_DEVICE); -+ dma_unmap_sg(dev, dst, dst_nents, DMA_FROM_DEVICE); -+ } else { -+ dma_unmap_sg(dev, src, src_nents, DMA_BIDIRECTIONAL); -+ } -+ -+ if (iv_dma) -+ dma_unmap_single(dev, iv_dma, ivsize, DMA_TO_DEVICE); -+ -+ if (qm_sg_bytes) -+ dma_unmap_single(dev, qm_sg_dma, qm_sg_bytes, DMA_TO_DEVICE); -+} -+ -+static int aead_set_sh_desc(struct crypto_aead *aead) -+{ -+ struct caam_aead_alg *alg = container_of(crypto_aead_alg(aead), -+ typeof(*alg), aead); -+ struct caam_ctx *ctx = crypto_aead_ctx(aead); -+ unsigned int ivsize = crypto_aead_ivsize(aead); -+ struct device *dev = ctx->dev; -+ struct dpaa2_caam_priv *priv = dev_get_drvdata(dev); -+ struct caam_flc *flc; -+ u32 *desc; -+ u32 ctx1_iv_off = 0; -+ u32 *nonce = NULL; -+ unsigned int data_len[2]; -+ u32 inl_mask; -+ const bool ctr_mode = ((ctx->cdata.algtype & OP_ALG_AAI_MASK) == -+ OP_ALG_AAI_CTR_MOD128); -+ const bool is_rfc3686 = alg->caam.rfc3686; -+ -+ if (!ctx->cdata.keylen || !ctx->authsize) -+ return 0; -+ -+ /* -+ * AES-CTR needs to load IV in CONTEXT1 reg -+ * at an offset of 128bits (16bytes) -+ * CONTEXT1[255:128] = IV -+ */ -+ if (ctr_mode) -+ ctx1_iv_off = 16; -+ -+ /* -+ * RFC3686 specific: -+ * CONTEXT1[255:128] = {NONCE, IV, COUNTER} -+ */ -+ if (is_rfc3686) { -+ ctx1_iv_off = 16 + CTR_RFC3686_NONCE_SIZE; -+ nonce = (u32 *)((void *)ctx->key + ctx->adata.keylen_pad + -+ ctx->cdata.keylen - CTR_RFC3686_NONCE_SIZE); -+ } -+ -+ data_len[0] = ctx->adata.keylen_pad; -+ data_len[1] = ctx->cdata.keylen; -+ -+ /* aead_encrypt shared descriptor */ -+ if (desc_inline_query((alg->caam.geniv ? DESC_QI_AEAD_GIVENC_LEN : -+ DESC_QI_AEAD_ENC_LEN) + -+ (is_rfc3686 ? DESC_AEAD_CTR_RFC3686_LEN : 0), -+ DESC_JOB_IO_LEN, data_len, &inl_mask, -+ ARRAY_SIZE(data_len)) < 0) -+ return -EINVAL; -+ -+ if (inl_mask & 1) -+ ctx->adata.key_virt = ctx->key; -+ else -+ ctx->adata.key_dma = ctx->key_dma; -+ -+ if (inl_mask & 2) -+ ctx->cdata.key_virt = ctx->key + ctx->adata.keylen_pad; -+ else -+ ctx->cdata.key_dma = ctx->key_dma + ctx->adata.keylen_pad; -+ -+ ctx->adata.key_inline = !!(inl_mask & 1); -+ ctx->cdata.key_inline = !!(inl_mask & 2); -+ -+ flc = &ctx->flc[ENCRYPT]; -+ desc = flc->sh_desc; -+ -+ if (alg->caam.geniv) -+ cnstr_shdsc_aead_givencap(desc, &ctx->cdata, &ctx->adata, -+ ivsize, ctx->authsize, is_rfc3686, -+ nonce, ctx1_iv_off, true, -+ priv->sec_attr.era); -+ else -+ cnstr_shdsc_aead_encap(desc, &ctx->cdata, &ctx->adata, -+ ivsize, ctx->authsize, is_rfc3686, nonce, -+ ctx1_iv_off, true, priv->sec_attr.era); -+ -+ flc->flc[1] = cpu_to_caam32(desc_len(desc)); /* SDL */ -+ dma_sync_single_for_device(dev, ctx->flc_dma[ENCRYPT], -+ sizeof(flc->flc) + desc_bytes(desc), -+ ctx->dir); -+ -+ /* aead_decrypt shared descriptor */ -+ if (desc_inline_query(DESC_QI_AEAD_DEC_LEN + -+ (is_rfc3686 ? DESC_AEAD_CTR_RFC3686_LEN : 0), -+ DESC_JOB_IO_LEN, data_len, &inl_mask, -+ ARRAY_SIZE(data_len)) < 0) -+ return -EINVAL; -+ -+ if (inl_mask & 1) -+ ctx->adata.key_virt = ctx->key; -+ else -+ ctx->adata.key_dma = ctx->key_dma; -+ -+ if (inl_mask & 2) -+ ctx->cdata.key_virt = ctx->key + ctx->adata.keylen_pad; -+ else -+ ctx->cdata.key_dma = ctx->key_dma + ctx->adata.keylen_pad; -+ -+ ctx->adata.key_inline = !!(inl_mask & 1); -+ ctx->cdata.key_inline = !!(inl_mask & 2); -+ -+ flc = &ctx->flc[DECRYPT]; -+ desc = flc->sh_desc; -+ cnstr_shdsc_aead_decap(desc, &ctx->cdata, &ctx->adata, -+ ivsize, ctx->authsize, alg->caam.geniv, -+ is_rfc3686, nonce, ctx1_iv_off, true, -+ priv->sec_attr.era); -+ flc->flc[1] = cpu_to_caam32(desc_len(desc)); /* SDL */ -+ dma_sync_single_for_device(dev, ctx->flc_dma[DECRYPT], -+ sizeof(flc->flc) + desc_bytes(desc), -+ ctx->dir); -+ -+ return 0; -+} -+ -+static int aead_setauthsize(struct crypto_aead *authenc, unsigned int authsize) -+{ -+ struct caam_ctx *ctx = crypto_aead_ctx(authenc); -+ -+ ctx->authsize = authsize; -+ aead_set_sh_desc(authenc); -+ -+ return 0; -+} -+ -+struct split_key_sh_result { -+ struct completion completion; -+ int err; -+ struct device *dev; -+}; -+ -+static void split_key_sh_done(void *cbk_ctx, u32 err) -+{ -+ struct split_key_sh_result *res = cbk_ctx; -+ -+#ifdef DEBUG -+ dev_err(res->dev, "%s %d: err 0x%x\n", __func__, __LINE__, err); -+#endif -+ -+ if (err) -+ caam_qi2_strstatus(res->dev, err); -+ -+ res->err = err; -+ complete(&res->completion); -+} -+ -+static int aead_setkey(struct crypto_aead *aead, const u8 *key, -+ unsigned int keylen) -+{ -+ struct caam_ctx *ctx = crypto_aead_ctx(aead); -+ struct device *dev = ctx->dev; -+ struct crypto_authenc_keys keys; -+ -+ if (crypto_authenc_extractkeys(&keys, key, keylen) != 0) -+ goto badkey; -+ -+#ifdef DEBUG -+ dev_err(dev, "keylen %d enckeylen %d authkeylen %d\n", -+ keys.authkeylen + keys.enckeylen, keys.enckeylen, -+ keys.authkeylen); -+ print_hex_dump(KERN_ERR, "key in @" __stringify(__LINE__)": ", -+ DUMP_PREFIX_ADDRESS, 16, 4, key, keylen, 1); -+#endif -+ -+ ctx->adata.keylen = keys.authkeylen; -+ ctx->adata.keylen_pad = split_key_len(ctx->adata.algtype & -+ OP_ALG_ALGSEL_MASK); -+ -+ if (ctx->adata.keylen_pad + keys.enckeylen > CAAM_MAX_KEY_SIZE) -+ goto badkey; -+ -+ memcpy(ctx->key, keys.authkey, keys.authkeylen); -+ memcpy(ctx->key + ctx->adata.keylen_pad, keys.enckey, keys.enckeylen); -+ dma_sync_single_for_device(dev, ctx->key_dma, ctx->adata.keylen_pad + -+ keys.enckeylen, ctx->dir); -+#ifdef DEBUG -+ print_hex_dump(KERN_ERR, "ctx.key@" __stringify(__LINE__)": ", -+ DUMP_PREFIX_ADDRESS, 16, 4, ctx->key, -+ ctx->adata.keylen_pad + keys.enckeylen, 1); -+#endif -+ -+ ctx->cdata.keylen = keys.enckeylen; -+ -+ return aead_set_sh_desc(aead); -+badkey: -+ crypto_aead_set_flags(aead, CRYPTO_TFM_RES_BAD_KEY_LEN); -+ return -EINVAL; -+} -+ -+static struct aead_edesc *aead_edesc_alloc(struct aead_request *req, -+ bool encrypt) -+{ -+ struct crypto_aead *aead = crypto_aead_reqtfm(req); -+ struct caam_request *req_ctx = aead_request_ctx(req); -+ struct dpaa2_fl_entry *in_fle = &req_ctx->fd_flt[1]; -+ struct dpaa2_fl_entry *out_fle = &req_ctx->fd_flt[0]; -+ struct caam_ctx *ctx = crypto_aead_ctx(aead); -+ struct caam_aead_alg *alg = container_of(crypto_aead_alg(aead), -+ typeof(*alg), aead); -+ struct device *dev = ctx->dev; -+ gfp_t flags = (req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP) ? -+ GFP_KERNEL : GFP_ATOMIC; -+ int src_nents, mapped_src_nents, dst_nents = 0, mapped_dst_nents = 0; -+ struct aead_edesc *edesc; -+ dma_addr_t qm_sg_dma, iv_dma = 0; -+ int ivsize = 0; -+ unsigned int authsize = ctx->authsize; -+ int qm_sg_index = 0, qm_sg_nents = 0, qm_sg_bytes; -+ int in_len, out_len; -+ struct dpaa2_sg_entry *sg_table; -+ -+ /* allocate space for base edesc, link tables and IV */ -+ edesc = qi_cache_zalloc(GFP_DMA | flags); -+ if (unlikely(!edesc)) { -+ dev_err(dev, "could not allocate extended descriptor\n"); -+ return ERR_PTR(-ENOMEM); -+ } -+ -+ if (unlikely(req->dst != req->src)) { -+ src_nents = sg_nents_for_len(req->src, req->assoclen + -+ req->cryptlen); -+ if (unlikely(src_nents < 0)) { -+ dev_err(dev, "Insufficient bytes (%d) in src S/G\n", -+ req->assoclen + req->cryptlen); -+ qi_cache_free(edesc); -+ return ERR_PTR(src_nents); -+ } -+ -+ dst_nents = sg_nents_for_len(req->dst, req->assoclen + -+ req->cryptlen + -+ (encrypt ? authsize : -+ (-authsize))); -+ if (unlikely(dst_nents < 0)) { -+ dev_err(dev, "Insufficient bytes (%d) in dst S/G\n", -+ req->assoclen + req->cryptlen + -+ (encrypt ? authsize : (-authsize))); -+ qi_cache_free(edesc); -+ return ERR_PTR(dst_nents); -+ } -+ -+ if (src_nents) { -+ mapped_src_nents = dma_map_sg(dev, req->src, src_nents, -+ DMA_TO_DEVICE); -+ if (unlikely(!mapped_src_nents)) { -+ dev_err(dev, "unable to map source\n"); -+ qi_cache_free(edesc); -+ return ERR_PTR(-ENOMEM); -+ } -+ } else { -+ mapped_src_nents = 0; -+ } -+ -+ mapped_dst_nents = dma_map_sg(dev, req->dst, dst_nents, -+ DMA_FROM_DEVICE); -+ if (unlikely(!mapped_dst_nents)) { -+ dev_err(dev, "unable to map destination\n"); -+ dma_unmap_sg(dev, req->src, src_nents, DMA_TO_DEVICE); -+ qi_cache_free(edesc); -+ return ERR_PTR(-ENOMEM); -+ } -+ } else { -+ src_nents = sg_nents_for_len(req->src, req->assoclen + -+ req->cryptlen + -+ (encrypt ? authsize : 0)); -+ if (unlikely(src_nents < 0)) { -+ dev_err(dev, "Insufficient bytes (%d) in src S/G\n", -+ req->assoclen + req->cryptlen + -+ (encrypt ? authsize : 0)); -+ qi_cache_free(edesc); -+ return ERR_PTR(src_nents); -+ } -+ -+ mapped_src_nents = dma_map_sg(dev, req->src, src_nents, -+ DMA_BIDIRECTIONAL); -+ if (unlikely(!mapped_src_nents)) { -+ dev_err(dev, "unable to map source\n"); -+ qi_cache_free(edesc); -+ return ERR_PTR(-ENOMEM); -+ } -+ } -+ -+ if ((alg->caam.rfc3686 && encrypt) || !alg->caam.geniv) -+ ivsize = crypto_aead_ivsize(aead); -+ -+ /* -+ * Create S/G table: req->assoclen, [IV,] req->src [, req->dst]. -+ * Input is not contiguous. -+ */ -+ qm_sg_nents = 1 + !!ivsize + mapped_src_nents + -+ (mapped_dst_nents > 1 ? mapped_dst_nents : 0); -+ sg_table = &edesc->sgt[0]; -+ qm_sg_bytes = qm_sg_nents * sizeof(*sg_table); -+ if (unlikely(offsetof(struct aead_edesc, sgt) + qm_sg_bytes + ivsize > -+ CAAM_QI_MEMCACHE_SIZE)) { -+ dev_err(dev, "No space for %d S/G entries and/or %dB IV\n", -+ qm_sg_nents, ivsize); -+ caam_unmap(dev, req->src, req->dst, src_nents, dst_nents, 0, -+ 0, 0, 0); -+ qi_cache_free(edesc); -+ return ERR_PTR(-ENOMEM); -+ } -+ -+ if (ivsize) { -+ u8 *iv = (u8 *)(sg_table + qm_sg_nents); -+ -+ /* Make sure IV is located in a DMAable area */ -+ memcpy(iv, req->iv, ivsize); -+ -+ iv_dma = dma_map_single(dev, iv, ivsize, DMA_TO_DEVICE); -+ if (dma_mapping_error(dev, iv_dma)) { -+ dev_err(dev, "unable to map IV\n"); -+ caam_unmap(dev, req->src, req->dst, src_nents, -+ dst_nents, 0, 0, 0, 0); -+ qi_cache_free(edesc); -+ return ERR_PTR(-ENOMEM); -+ } -+ } -+ -+ edesc->src_nents = src_nents; -+ edesc->dst_nents = dst_nents; -+ edesc->iv_dma = iv_dma; -+ -+ if ((alg->caam.class1_alg_type & OP_ALG_ALGSEL_MASK) == -+ OP_ALG_ALGSEL_CHACHA20 && ivsize != CHACHAPOLY_IV_SIZE) -+ /* -+ * The associated data comes already with the IV but we need -+ * to skip it when we authenticate or encrypt... -+ */ -+ edesc->assoclen = cpu_to_caam32(req->assoclen - ivsize); -+ else -+ edesc->assoclen = cpu_to_caam32(req->assoclen); -+ edesc->assoclen_dma = dma_map_single(dev, &edesc->assoclen, 4, -+ DMA_TO_DEVICE); -+ if (dma_mapping_error(dev, edesc->assoclen_dma)) { -+ dev_err(dev, "unable to map assoclen\n"); -+ caam_unmap(dev, req->src, req->dst, src_nents, dst_nents, -+ iv_dma, ivsize, 0, 0); -+ qi_cache_free(edesc); -+ return ERR_PTR(-ENOMEM); -+ } -+ -+ dma_to_qm_sg_one(sg_table, edesc->assoclen_dma, 4, 0); -+ qm_sg_index++; -+ if (ivsize) { -+ dma_to_qm_sg_one(sg_table + qm_sg_index, iv_dma, ivsize, 0); -+ qm_sg_index++; -+ } -+ sg_to_qm_sg_last(req->src, mapped_src_nents, sg_table + qm_sg_index, 0); -+ qm_sg_index += mapped_src_nents; -+ -+ if (mapped_dst_nents > 1) -+ sg_to_qm_sg_last(req->dst, mapped_dst_nents, sg_table + -+ qm_sg_index, 0); -+ -+ qm_sg_dma = dma_map_single(dev, sg_table, qm_sg_bytes, DMA_TO_DEVICE); -+ if (dma_mapping_error(dev, qm_sg_dma)) { -+ dev_err(dev, "unable to map S/G table\n"); -+ dma_unmap_single(dev, edesc->assoclen_dma, 4, DMA_TO_DEVICE); -+ caam_unmap(dev, req->src, req->dst, src_nents, dst_nents, -+ iv_dma, ivsize, 0, 0); -+ qi_cache_free(edesc); -+ return ERR_PTR(-ENOMEM); -+ } -+ -+ edesc->qm_sg_dma = qm_sg_dma; -+ edesc->qm_sg_bytes = qm_sg_bytes; -+ -+ out_len = req->assoclen + req->cryptlen + -+ (encrypt ? ctx->authsize : (-ctx->authsize)); -+ in_len = 4 + ivsize + req->assoclen + req->cryptlen; -+ -+ memset(&req_ctx->fd_flt, 0, sizeof(req_ctx->fd_flt)); -+ dpaa2_fl_set_final(in_fle, true); -+ dpaa2_fl_set_format(in_fle, dpaa2_fl_sg); -+ dpaa2_fl_set_addr(in_fle, qm_sg_dma); -+ dpaa2_fl_set_len(in_fle, in_len); -+ -+ if (req->dst == req->src) { -+ if (mapped_src_nents == 1) { -+ dpaa2_fl_set_format(out_fle, dpaa2_fl_single); -+ dpaa2_fl_set_addr(out_fle, sg_dma_address(req->src)); -+ } else { -+ dpaa2_fl_set_format(out_fle, dpaa2_fl_sg); -+ dpaa2_fl_set_addr(out_fle, qm_sg_dma + -+ (1 + !!ivsize) * sizeof(*sg_table)); -+ } -+ } else if (mapped_dst_nents == 1) { -+ dpaa2_fl_set_format(out_fle, dpaa2_fl_single); -+ dpaa2_fl_set_addr(out_fle, sg_dma_address(req->dst)); -+ } else { -+ dpaa2_fl_set_format(out_fle, dpaa2_fl_sg); -+ dpaa2_fl_set_addr(out_fle, qm_sg_dma + qm_sg_index * -+ sizeof(*sg_table)); -+ } -+ -+ dpaa2_fl_set_len(out_fle, out_len); -+ -+ return edesc; -+} -+ -+static int chachapoly_set_sh_desc(struct crypto_aead *aead) -+{ -+ struct caam_ctx *ctx = crypto_aead_ctx(aead); -+ unsigned int ivsize = crypto_aead_ivsize(aead); -+ struct device *dev = ctx->dev; -+ struct caam_flc *flc; -+ u32 *desc; -+ -+ if (!ctx->cdata.keylen || !ctx->authsize) -+ return 0; -+ -+ flc = &ctx->flc[ENCRYPT]; -+ desc = flc->sh_desc; -+ cnstr_shdsc_chachapoly(desc, &ctx->cdata, &ctx->adata, ivsize, -+ ctx->authsize, true, true); -+ flc->flc[1] = cpu_to_caam32(desc_len(desc)); /* SDL */ -+ dma_sync_single_for_device(dev, ctx->flc_dma[ENCRYPT], -+ sizeof(flc->flc) + desc_bytes(desc), -+ ctx->dir); -+ -+ flc = &ctx->flc[DECRYPT]; -+ desc = flc->sh_desc; -+ cnstr_shdsc_chachapoly(desc, &ctx->cdata, &ctx->adata, ivsize, -+ ctx->authsize, false, true); -+ flc->flc[1] = cpu_to_caam32(desc_len(desc)); /* SDL */ -+ dma_sync_single_for_device(dev, ctx->flc_dma[DECRYPT], -+ sizeof(flc->flc) + desc_bytes(desc), -+ ctx->dir); -+ -+ return 0; -+} -+ -+static int chachapoly_setauthsize(struct crypto_aead *aead, -+ unsigned int authsize) -+{ -+ struct caam_ctx *ctx = crypto_aead_ctx(aead); -+ -+ if (authsize != POLY1305_DIGEST_SIZE) -+ return -EINVAL; -+ -+ ctx->authsize = authsize; -+ return chachapoly_set_sh_desc(aead); -+} -+ -+static int chachapoly_setkey(struct crypto_aead *aead, const u8 *key, -+ unsigned int keylen) -+{ -+ struct caam_ctx *ctx = crypto_aead_ctx(aead); -+ unsigned int ivsize = crypto_aead_ivsize(aead); -+ unsigned int saltlen = CHACHAPOLY_IV_SIZE - ivsize; -+ -+ if (keylen != CHACHA20_KEY_SIZE + saltlen) { -+ crypto_aead_set_flags(aead, CRYPTO_TFM_RES_BAD_KEY_LEN); -+ return -EINVAL; -+ } -+ -+ ctx->cdata.key_virt = key; -+ ctx->cdata.keylen = keylen - saltlen; -+ -+ return chachapoly_set_sh_desc(aead); -+} -+ -+static struct tls_edesc *tls_edesc_alloc(struct aead_request *req, -+ bool encrypt) -+{ -+ struct crypto_aead *tls = crypto_aead_reqtfm(req); -+ unsigned int blocksize = crypto_aead_blocksize(tls); -+ unsigned int padsize, authsize; -+ struct caam_request *req_ctx = aead_request_ctx(req); -+ struct dpaa2_fl_entry *in_fle = &req_ctx->fd_flt[1]; -+ struct dpaa2_fl_entry *out_fle = &req_ctx->fd_flt[0]; -+ struct caam_ctx *ctx = crypto_aead_ctx(tls); -+ struct caam_aead_alg *alg = container_of(crypto_aead_alg(tls), -+ typeof(*alg), aead); -+ struct device *dev = ctx->dev; -+ gfp_t flags = (req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP) ? -+ GFP_KERNEL : GFP_ATOMIC; -+ int src_nents, mapped_src_nents, dst_nents = 0, mapped_dst_nents = 0; -+ struct tls_edesc *edesc; -+ dma_addr_t qm_sg_dma, iv_dma = 0; -+ int ivsize = 0; -+ u8 *iv; -+ int qm_sg_index, qm_sg_ents = 0, qm_sg_bytes; -+ int in_len, out_len; -+ struct dpaa2_sg_entry *sg_table; -+ struct scatterlist *dst; -+ -+ if (encrypt) { -+ padsize = blocksize - ((req->cryptlen + ctx->authsize) % -+ blocksize); -+ authsize = ctx->authsize + padsize; -+ } else { -+ authsize = ctx->authsize; -+ } -+ -+ /* allocate space for base edesc, link tables and IV */ -+ edesc = qi_cache_zalloc(GFP_DMA | flags); -+ if (unlikely(!edesc)) { -+ dev_err(dev, "could not allocate extended descriptor\n"); -+ return ERR_PTR(-ENOMEM); -+ } -+ -+ if (likely(req->src == req->dst)) { -+ src_nents = sg_nents_for_len(req->src, req->assoclen + -+ req->cryptlen + -+ (encrypt ? authsize : 0)); -+ if (unlikely(src_nents < 0)) { -+ dev_err(dev, "Insufficient bytes (%d) in src S/G\n", -+ req->assoclen + req->cryptlen + -+ (encrypt ? authsize : 0)); -+ qi_cache_free(edesc); -+ return ERR_PTR(src_nents); -+ } -+ -+ mapped_src_nents = dma_map_sg(dev, req->src, src_nents, -+ DMA_BIDIRECTIONAL); -+ if (unlikely(!mapped_src_nents)) { -+ dev_err(dev, "unable to map source\n"); -+ qi_cache_free(edesc); -+ return ERR_PTR(-ENOMEM); -+ } -+ dst = req->dst; -+ } else { -+ src_nents = sg_nents_for_len(req->src, req->assoclen + -+ req->cryptlen); -+ if (unlikely(src_nents < 0)) { -+ dev_err(dev, "Insufficient bytes (%d) in src S/G\n", -+ req->assoclen + req->cryptlen); -+ qi_cache_free(edesc); -+ return ERR_PTR(src_nents); -+ } -+ -+ dst = scatterwalk_ffwd(edesc->tmp, req->dst, req->assoclen); -+ dst_nents = sg_nents_for_len(dst, req->cryptlen + -+ (encrypt ? authsize : 0)); -+ if (unlikely(dst_nents < 0)) { -+ dev_err(dev, "Insufficient bytes (%d) in dst S/G\n", -+ req->cryptlen + -+ (encrypt ? authsize : 0)); -+ qi_cache_free(edesc); -+ return ERR_PTR(dst_nents); -+ } -+ -+ if (src_nents) { -+ mapped_src_nents = dma_map_sg(dev, req->src, -+ src_nents, DMA_TO_DEVICE); -+ if (unlikely(!mapped_src_nents)) { -+ dev_err(dev, "unable to map source\n"); -+ qi_cache_free(edesc); -+ return ERR_PTR(-ENOMEM); -+ } -+ } else { -+ mapped_src_nents = 0; -+ } -+ -+ mapped_dst_nents = dma_map_sg(dev, dst, dst_nents, -+ DMA_FROM_DEVICE); -+ if (unlikely(!mapped_dst_nents)) { -+ dev_err(dev, "unable to map destination\n"); -+ dma_unmap_sg(dev, req->src, src_nents, DMA_TO_DEVICE); -+ qi_cache_free(edesc); -+ return ERR_PTR(-ENOMEM); -+ } -+ } -+ -+ /* -+ * Create S/G table: IV, src, dst. -+ * Input is not contiguous. -+ */ -+ qm_sg_ents = 1 + mapped_src_nents + -+ (mapped_dst_nents > 1 ? mapped_dst_nents : 0); -+ sg_table = &edesc->sgt[0]; -+ qm_sg_bytes = qm_sg_ents * sizeof(*sg_table); -+ -+ ivsize = crypto_aead_ivsize(tls); -+ iv = (u8 *)(sg_table + qm_sg_ents); -+ /* Make sure IV is located in a DMAable area */ -+ memcpy(iv, req->iv, ivsize); -+ iv_dma = dma_map_single(dev, iv, ivsize, DMA_TO_DEVICE); -+ if (dma_mapping_error(dev, iv_dma)) { -+ dev_err(dev, "unable to map IV\n"); -+ caam_unmap(dev, req->src, dst, src_nents, dst_nents, 0, 0, 0, -+ 0); -+ qi_cache_free(edesc); -+ return ERR_PTR(-ENOMEM); -+ } -+ -+ edesc->src_nents = src_nents; -+ edesc->dst_nents = dst_nents; -+ edesc->dst = dst; -+ edesc->iv_dma = iv_dma; -+ -+ dma_to_qm_sg_one(sg_table, iv_dma, ivsize, 0); -+ qm_sg_index = 1; -+ -+ sg_to_qm_sg_last(req->src, mapped_src_nents, sg_table + qm_sg_index, 0); -+ qm_sg_index += mapped_src_nents; -+ -+ if (mapped_dst_nents > 1) -+ sg_to_qm_sg_last(dst, mapped_dst_nents, sg_table + -+ qm_sg_index, 0); -+ -+ qm_sg_dma = dma_map_single(dev, sg_table, qm_sg_bytes, DMA_TO_DEVICE); -+ if (dma_mapping_error(dev, qm_sg_dma)) { -+ dev_err(dev, "unable to map S/G table\n"); -+ caam_unmap(dev, req->src, dst, src_nents, dst_nents, iv_dma, -+ ivsize, 0, 0); -+ qi_cache_free(edesc); -+ return ERR_PTR(-ENOMEM); -+ } -+ -+ edesc->qm_sg_dma = qm_sg_dma; -+ edesc->qm_sg_bytes = qm_sg_bytes; -+ -+ out_len = req->cryptlen + (encrypt ? authsize : 0); -+ in_len = ivsize + req->assoclen + req->cryptlen; -+ -+ memset(&req_ctx->fd_flt, 0, sizeof(req_ctx->fd_flt)); -+ dpaa2_fl_set_final(in_fle, true); -+ dpaa2_fl_set_format(in_fle, dpaa2_fl_sg); -+ dpaa2_fl_set_addr(in_fle, qm_sg_dma); -+ dpaa2_fl_set_len(in_fle, in_len); -+ -+ if (req->dst == req->src) { -+ dpaa2_fl_set_format(out_fle, dpaa2_fl_sg); -+ dpaa2_fl_set_addr(out_fle, qm_sg_dma + -+ (sg_nents_for_len(req->src, req->assoclen) + -+ 1) * sizeof(*sg_table)); -+ } else if (mapped_dst_nents == 1) { -+ dpaa2_fl_set_format(out_fle, dpaa2_fl_single); -+ dpaa2_fl_set_addr(out_fle, sg_dma_address(dst)); -+ } else { -+ dpaa2_fl_set_format(out_fle, dpaa2_fl_sg); -+ dpaa2_fl_set_addr(out_fle, qm_sg_dma + qm_sg_index * -+ sizeof(*sg_table)); -+ } -+ -+ dpaa2_fl_set_len(out_fle, out_len); -+ -+ return edesc; -+} -+ -+static int tls_set_sh_desc(struct crypto_aead *tls) -+{ -+ struct caam_ctx *ctx = crypto_aead_ctx(tls); -+ unsigned int ivsize = crypto_aead_ivsize(tls); -+ unsigned int blocksize = crypto_aead_blocksize(tls); -+ struct device *dev = ctx->dev; -+ struct dpaa2_caam_priv *priv = dev_get_drvdata(dev); -+ struct caam_flc *flc; -+ u32 *desc; -+ unsigned int assoclen = 13; /* always 13 bytes for TLS */ -+ unsigned int data_len[2]; -+ u32 inl_mask; -+ -+ if (!ctx->cdata.keylen || !ctx->authsize) -+ return 0; -+ -+ /* -+ * TLS 1.0 encrypt shared descriptor -+ * Job Descriptor and Shared Descriptor -+ * must fit into the 64-word Descriptor h/w Buffer -+ */ -+ data_len[0] = ctx->adata.keylen_pad; -+ data_len[1] = ctx->cdata.keylen; -+ -+ if (desc_inline_query(DESC_TLS10_ENC_LEN, DESC_JOB_IO_LEN, data_len, -+ &inl_mask, ARRAY_SIZE(data_len)) < 0) -+ return -EINVAL; -+ -+ if (inl_mask & 1) -+ ctx->adata.key_virt = ctx->key; -+ else -+ ctx->adata.key_dma = ctx->key_dma; -+ -+ if (inl_mask & 2) -+ ctx->cdata.key_virt = ctx->key + ctx->adata.keylen_pad; -+ else -+ ctx->cdata.key_dma = ctx->key_dma + ctx->adata.keylen_pad; -+ -+ ctx->adata.key_inline = !!(inl_mask & 1); -+ ctx->cdata.key_inline = !!(inl_mask & 2); -+ -+ flc = &ctx->flc[ENCRYPT]; -+ desc = flc->sh_desc; -+ cnstr_shdsc_tls_encap(desc, &ctx->cdata, &ctx->adata, -+ assoclen, ivsize, ctx->authsize, blocksize, -+ priv->sec_attr.era); -+ flc->flc[1] = cpu_to_caam32(desc_len(desc)); -+ dma_sync_single_for_device(dev, ctx->flc_dma[ENCRYPT], -+ sizeof(flc->flc) + desc_bytes(desc), -+ ctx->dir); -+ -+ /* -+ * TLS 1.0 decrypt shared descriptor -+ * Keys do not fit inline, regardless of algorithms used -+ */ -+ ctx->adata.key_inline = false; -+ ctx->adata.key_dma = ctx->key_dma; -+ ctx->cdata.key_dma = ctx->key_dma + ctx->adata.keylen_pad; -+ -+ flc = &ctx->flc[DECRYPT]; -+ desc = flc->sh_desc; -+ cnstr_shdsc_tls_decap(desc, &ctx->cdata, &ctx->adata, assoclen, ivsize, -+ ctx->authsize, blocksize, priv->sec_attr.era); -+ flc->flc[1] = cpu_to_caam32(desc_len(desc)); /* SDL */ -+ dma_sync_single_for_device(dev, ctx->flc_dma[DECRYPT], -+ sizeof(flc->flc) + desc_bytes(desc), -+ ctx->dir); -+ -+ return 0; -+} -+ -+static int tls_setkey(struct crypto_aead *tls, const u8 *key, -+ unsigned int keylen) -+{ -+ struct caam_ctx *ctx = crypto_aead_ctx(tls); -+ struct device *dev = ctx->dev; -+ struct crypto_authenc_keys keys; -+ -+ if (crypto_authenc_extractkeys(&keys, key, keylen) != 0) -+ goto badkey; -+ -+#ifdef DEBUG -+ dev_err(dev, "keylen %d enckeylen %d authkeylen %d\n", -+ keys.authkeylen + keys.enckeylen, keys.enckeylen, -+ keys.authkeylen); -+ print_hex_dump(KERN_ERR, "key in @" __stringify(__LINE__)": ", -+ DUMP_PREFIX_ADDRESS, 16, 4, key, keylen, 1); -+#endif -+ -+ ctx->adata.keylen = keys.authkeylen; -+ ctx->adata.keylen_pad = split_key_len(ctx->adata.algtype & -+ OP_ALG_ALGSEL_MASK); -+ -+ if (ctx->adata.keylen_pad + keys.enckeylen > CAAM_MAX_KEY_SIZE) -+ goto badkey; -+ -+ memcpy(ctx->key, keys.authkey, keys.authkeylen); -+ memcpy(ctx->key + ctx->adata.keylen_pad, keys.enckey, keys.enckeylen); -+ dma_sync_single_for_device(dev, ctx->key_dma, ctx->adata.keylen_pad + -+ keys.enckeylen, ctx->dir); -+#ifdef DEBUG -+ print_hex_dump(KERN_ERR, "ctx.key@" __stringify(__LINE__)": ", -+ DUMP_PREFIX_ADDRESS, 16, 4, ctx->key, -+ ctx->adata.keylen_pad + keys.enckeylen, 1); -+#endif -+ -+ ctx->cdata.keylen = keys.enckeylen; -+ -+ return tls_set_sh_desc(tls); -+badkey: -+ crypto_aead_set_flags(tls, CRYPTO_TFM_RES_BAD_KEY_LEN); -+ return -EINVAL; -+} -+ -+static int tls_setauthsize(struct crypto_aead *tls, unsigned int authsize) -+{ -+ struct caam_ctx *ctx = crypto_aead_ctx(tls); -+ -+ ctx->authsize = authsize; -+ tls_set_sh_desc(tls); -+ -+ return 0; -+} -+ -+static int gcm_set_sh_desc(struct crypto_aead *aead) -+{ -+ struct caam_ctx *ctx = crypto_aead_ctx(aead); -+ struct device *dev = ctx->dev; -+ unsigned int ivsize = crypto_aead_ivsize(aead); -+ struct caam_flc *flc; -+ u32 *desc; -+ int rem_bytes = CAAM_DESC_BYTES_MAX - DESC_JOB_IO_LEN - -+ ctx->cdata.keylen; -+ -+ if (!ctx->cdata.keylen || !ctx->authsize) -+ return 0; -+ -+ /* -+ * AES GCM encrypt shared descriptor -+ * Job Descriptor and Shared Descriptor -+ * must fit into the 64-word Descriptor h/w Buffer -+ */ -+ if (rem_bytes >= DESC_QI_GCM_ENC_LEN) { -+ ctx->cdata.key_inline = true; -+ ctx->cdata.key_virt = ctx->key; -+ } else { -+ ctx->cdata.key_inline = false; -+ ctx->cdata.key_dma = ctx->key_dma; -+ } -+ -+ flc = &ctx->flc[ENCRYPT]; -+ desc = flc->sh_desc; -+ cnstr_shdsc_gcm_encap(desc, &ctx->cdata, ivsize, ctx->authsize, true); -+ flc->flc[1] = cpu_to_caam32(desc_len(desc)); /* SDL */ -+ dma_sync_single_for_device(dev, ctx->flc_dma[ENCRYPT], -+ sizeof(flc->flc) + desc_bytes(desc), -+ ctx->dir); -+ -+ /* -+ * Job Descriptor and Shared Descriptors -+ * must all fit into the 64-word Descriptor h/w Buffer -+ */ -+ if (rem_bytes >= DESC_QI_GCM_DEC_LEN) { -+ ctx->cdata.key_inline = true; -+ ctx->cdata.key_virt = ctx->key; -+ } else { -+ ctx->cdata.key_inline = false; -+ ctx->cdata.key_dma = ctx->key_dma; -+ } -+ -+ flc = &ctx->flc[DECRYPT]; -+ desc = flc->sh_desc; -+ cnstr_shdsc_gcm_decap(desc, &ctx->cdata, ivsize, ctx->authsize, true); -+ flc->flc[1] = cpu_to_caam32(desc_len(desc)); /* SDL */ -+ dma_sync_single_for_device(dev, ctx->flc_dma[DECRYPT], -+ sizeof(flc->flc) + desc_bytes(desc), -+ ctx->dir); -+ -+ return 0; -+} -+ -+static int gcm_setauthsize(struct crypto_aead *authenc, unsigned int authsize) -+{ -+ struct caam_ctx *ctx = crypto_aead_ctx(authenc); -+ -+ ctx->authsize = authsize; -+ gcm_set_sh_desc(authenc); -+ -+ return 0; -+} -+ -+static int gcm_setkey(struct crypto_aead *aead, -+ const u8 *key, unsigned int keylen) -+{ -+ struct caam_ctx *ctx = crypto_aead_ctx(aead); -+ struct device *dev = ctx->dev; -+ -+#ifdef DEBUG -+ print_hex_dump(KERN_ERR, "key in @" __stringify(__LINE__)": ", -+ DUMP_PREFIX_ADDRESS, 16, 4, key, keylen, 1); -+#endif -+ -+ memcpy(ctx->key, key, keylen); -+ dma_sync_single_for_device(dev, ctx->key_dma, keylen, ctx->dir); -+ ctx->cdata.keylen = keylen; -+ -+ return gcm_set_sh_desc(aead); -+} -+ -+static int rfc4106_set_sh_desc(struct crypto_aead *aead) -+{ -+ struct caam_ctx *ctx = crypto_aead_ctx(aead); -+ struct device *dev = ctx->dev; -+ unsigned int ivsize = crypto_aead_ivsize(aead); -+ struct caam_flc *flc; -+ u32 *desc; -+ int rem_bytes = CAAM_DESC_BYTES_MAX - DESC_JOB_IO_LEN - -+ ctx->cdata.keylen; -+ -+ if (!ctx->cdata.keylen || !ctx->authsize) -+ return 0; -+ -+ ctx->cdata.key_virt = ctx->key; -+ -+ /* -+ * RFC4106 encrypt shared descriptor -+ * Job Descriptor and Shared Descriptor -+ * must fit into the 64-word Descriptor h/w Buffer -+ */ -+ if (rem_bytes >= DESC_QI_RFC4106_ENC_LEN) { -+ ctx->cdata.key_inline = true; -+ } else { -+ ctx->cdata.key_inline = false; -+ ctx->cdata.key_dma = ctx->key_dma; -+ } -+ -+ flc = &ctx->flc[ENCRYPT]; -+ desc = flc->sh_desc; -+ cnstr_shdsc_rfc4106_encap(desc, &ctx->cdata, ivsize, ctx->authsize, -+ true); -+ flc->flc[1] = cpu_to_caam32(desc_len(desc)); /* SDL */ -+ dma_sync_single_for_device(dev, ctx->flc_dma[ENCRYPT], -+ sizeof(flc->flc) + desc_bytes(desc), -+ ctx->dir); -+ -+ /* -+ * Job Descriptor and Shared Descriptors -+ * must all fit into the 64-word Descriptor h/w Buffer -+ */ -+ if (rem_bytes >= DESC_QI_RFC4106_DEC_LEN) { -+ ctx->cdata.key_inline = true; -+ } else { -+ ctx->cdata.key_inline = false; -+ ctx->cdata.key_dma = ctx->key_dma; -+ } -+ -+ flc = &ctx->flc[DECRYPT]; -+ desc = flc->sh_desc; -+ cnstr_shdsc_rfc4106_decap(desc, &ctx->cdata, ivsize, ctx->authsize, -+ true); -+ flc->flc[1] = cpu_to_caam32(desc_len(desc)); /* SDL */ -+ dma_sync_single_for_device(dev, ctx->flc_dma[DECRYPT], -+ sizeof(flc->flc) + desc_bytes(desc), -+ ctx->dir); -+ -+ return 0; -+} -+ -+static int rfc4106_setauthsize(struct crypto_aead *authenc, -+ unsigned int authsize) -+{ -+ struct caam_ctx *ctx = crypto_aead_ctx(authenc); -+ -+ ctx->authsize = authsize; -+ rfc4106_set_sh_desc(authenc); -+ -+ return 0; -+} -+ -+static int rfc4106_setkey(struct crypto_aead *aead, -+ const u8 *key, unsigned int keylen) -+{ -+ struct caam_ctx *ctx = crypto_aead_ctx(aead); -+ struct device *dev = ctx->dev; -+ -+ if (keylen < 4) -+ return -EINVAL; -+ -+#ifdef DEBUG -+ print_hex_dump(KERN_ERR, "key in @" __stringify(__LINE__)": ", -+ DUMP_PREFIX_ADDRESS, 16, 4, key, keylen, 1); -+#endif -+ -+ memcpy(ctx->key, key, keylen); -+ /* -+ * The last four bytes of the key material are used as the salt value -+ * in the nonce. Update the AES key length. -+ */ -+ ctx->cdata.keylen = keylen - 4; -+ dma_sync_single_for_device(dev, ctx->key_dma, ctx->cdata.keylen, -+ ctx->dir); -+ -+ return rfc4106_set_sh_desc(aead); -+} -+ -+static int rfc4543_set_sh_desc(struct crypto_aead *aead) -+{ -+ struct caam_ctx *ctx = crypto_aead_ctx(aead); -+ struct device *dev = ctx->dev; -+ unsigned int ivsize = crypto_aead_ivsize(aead); -+ struct caam_flc *flc; -+ u32 *desc; -+ int rem_bytes = CAAM_DESC_BYTES_MAX - DESC_JOB_IO_LEN - -+ ctx->cdata.keylen; -+ -+ if (!ctx->cdata.keylen || !ctx->authsize) -+ return 0; -+ -+ ctx->cdata.key_virt = ctx->key; -+ -+ /* -+ * RFC4543 encrypt shared descriptor -+ * Job Descriptor and Shared Descriptor -+ * must fit into the 64-word Descriptor h/w Buffer -+ */ -+ if (rem_bytes >= DESC_QI_RFC4543_ENC_LEN) { -+ ctx->cdata.key_inline = true; -+ } else { -+ ctx->cdata.key_inline = false; -+ ctx->cdata.key_dma = ctx->key_dma; -+ } -+ -+ flc = &ctx->flc[ENCRYPT]; -+ desc = flc->sh_desc; -+ cnstr_shdsc_rfc4543_encap(desc, &ctx->cdata, ivsize, ctx->authsize, -+ true); -+ flc->flc[1] = cpu_to_caam32(desc_len(desc)); /* SDL */ -+ dma_sync_single_for_device(dev, ctx->flc_dma[ENCRYPT], -+ sizeof(flc->flc) + desc_bytes(desc), -+ ctx->dir); -+ -+ /* -+ * Job Descriptor and Shared Descriptors -+ * must all fit into the 64-word Descriptor h/w Buffer -+ */ -+ if (rem_bytes >= DESC_QI_RFC4543_DEC_LEN) { -+ ctx->cdata.key_inline = true; -+ } else { -+ ctx->cdata.key_inline = false; -+ ctx->cdata.key_dma = ctx->key_dma; -+ } -+ -+ flc = &ctx->flc[DECRYPT]; -+ desc = flc->sh_desc; -+ cnstr_shdsc_rfc4543_decap(desc, &ctx->cdata, ivsize, ctx->authsize, -+ true); -+ flc->flc[1] = cpu_to_caam32(desc_len(desc)); /* SDL */ -+ dma_sync_single_for_device(dev, ctx->flc_dma[DECRYPT], -+ sizeof(flc->flc) + desc_bytes(desc), -+ ctx->dir); -+ -+ return 0; -+} -+ -+static int rfc4543_setauthsize(struct crypto_aead *authenc, -+ unsigned int authsize) -+{ -+ struct caam_ctx *ctx = crypto_aead_ctx(authenc); -+ -+ ctx->authsize = authsize; -+ rfc4543_set_sh_desc(authenc); -+ -+ return 0; -+} -+ -+static int rfc4543_setkey(struct crypto_aead *aead, -+ const u8 *key, unsigned int keylen) -+{ -+ struct caam_ctx *ctx = crypto_aead_ctx(aead); -+ struct device *dev = ctx->dev; -+ -+ if (keylen < 4) -+ return -EINVAL; -+ -+#ifdef DEBUG -+ print_hex_dump(KERN_ERR, "key in @" __stringify(__LINE__)": ", -+ DUMP_PREFIX_ADDRESS, 16, 4, key, keylen, 1); -+#endif -+ -+ memcpy(ctx->key, key, keylen); -+ /* -+ * The last four bytes of the key material are used as the salt value -+ * in the nonce. Update the AES key length. -+ */ -+ ctx->cdata.keylen = keylen - 4; -+ dma_sync_single_for_device(dev, ctx->key_dma, ctx->cdata.keylen, -+ ctx->dir); -+ -+ return rfc4543_set_sh_desc(aead); -+} -+ -+static int skcipher_setkey(struct crypto_skcipher *skcipher, const u8 *key, -+ unsigned int keylen) -+{ -+ struct caam_ctx *ctx = crypto_skcipher_ctx(skcipher); -+ struct caam_skcipher_alg *alg = -+ container_of(crypto_skcipher_alg(skcipher), -+ struct caam_skcipher_alg, skcipher); -+ struct device *dev = ctx->dev; -+ struct caam_flc *flc; -+ unsigned int ivsize = crypto_skcipher_ivsize(skcipher); -+ u32 *desc; -+ u32 ctx1_iv_off = 0; -+ const bool ctr_mode = ((ctx->cdata.algtype & OP_ALG_AAI_MASK) == -+ OP_ALG_AAI_CTR_MOD128) && -+ ((ctx->cdata.algtype & OP_ALG_ALGSEL_MASK) != -+ OP_ALG_ALGSEL_CHACHA20); -+ const bool is_rfc3686 = alg->caam.rfc3686; -+ -+#ifdef DEBUG -+ print_hex_dump(KERN_ERR, "key in @" __stringify(__LINE__)": ", -+ DUMP_PREFIX_ADDRESS, 16, 4, key, keylen, 1); -+#endif -+ /* -+ * AES-CTR needs to load IV in CONTEXT1 reg -+ * at an offset of 128bits (16bytes) -+ * CONTEXT1[255:128] = IV -+ */ -+ if (ctr_mode) -+ ctx1_iv_off = 16; -+ -+ /* -+ * RFC3686 specific: -+ * | CONTEXT1[255:128] = {NONCE, IV, COUNTER} -+ * | *key = {KEY, NONCE} -+ */ -+ if (is_rfc3686) { -+ ctx1_iv_off = 16 + CTR_RFC3686_NONCE_SIZE; -+ keylen -= CTR_RFC3686_NONCE_SIZE; -+ } -+ -+ ctx->cdata.keylen = keylen; -+ ctx->cdata.key_virt = key; -+ ctx->cdata.key_inline = true; -+ -+ /* skcipher_encrypt shared descriptor */ -+ flc = &ctx->flc[ENCRYPT]; -+ desc = flc->sh_desc; -+ cnstr_shdsc_ablkcipher_encap(desc, &ctx->cdata, ivsize, -+ is_rfc3686, ctx1_iv_off); -+ flc->flc[1] = cpu_to_caam32(desc_len(desc)); /* SDL */ -+ dma_sync_single_for_device(dev, ctx->flc_dma[ENCRYPT], -+ sizeof(flc->flc) + desc_bytes(desc), -+ ctx->dir); -+ -+ /* skcipher_decrypt shared descriptor */ -+ flc = &ctx->flc[DECRYPT]; -+ desc = flc->sh_desc; -+ cnstr_shdsc_ablkcipher_decap(desc, &ctx->cdata, ivsize, -+ is_rfc3686, ctx1_iv_off); -+ flc->flc[1] = cpu_to_caam32(desc_len(desc)); /* SDL */ -+ dma_sync_single_for_device(dev, ctx->flc_dma[DECRYPT], -+ sizeof(flc->flc) + desc_bytes(desc), -+ ctx->dir); -+ -+ return 0; -+} -+ -+static int xts_skcipher_setkey(struct crypto_skcipher *skcipher, const u8 *key, -+ unsigned int keylen) -+{ -+ struct caam_ctx *ctx = crypto_skcipher_ctx(skcipher); -+ struct device *dev = ctx->dev; -+ struct caam_flc *flc; -+ u32 *desc; -+ -+ if (keylen != 2 * AES_MIN_KEY_SIZE && keylen != 2 * AES_MAX_KEY_SIZE) { -+ dev_err(dev, "key size mismatch\n"); -+ crypto_skcipher_set_flags(skcipher, CRYPTO_TFM_RES_BAD_KEY_LEN); -+ return -EINVAL; -+ } -+ -+ ctx->cdata.keylen = keylen; -+ ctx->cdata.key_virt = key; -+ ctx->cdata.key_inline = true; -+ -+ /* xts_skcipher_encrypt shared descriptor */ -+ flc = &ctx->flc[ENCRYPT]; -+ desc = flc->sh_desc; -+ cnstr_shdsc_xts_ablkcipher_encap(desc, &ctx->cdata); -+ flc->flc[1] = cpu_to_caam32(desc_len(desc)); /* SDL */ -+ dma_sync_single_for_device(dev, ctx->flc_dma[ENCRYPT], -+ sizeof(flc->flc) + desc_bytes(desc), -+ ctx->dir); -+ -+ /* xts_skcipher_decrypt shared descriptor */ -+ flc = &ctx->flc[DECRYPT]; -+ desc = flc->sh_desc; -+ cnstr_shdsc_xts_ablkcipher_decap(desc, &ctx->cdata); -+ flc->flc[1] = cpu_to_caam32(desc_len(desc)); /* SDL */ -+ dma_sync_single_for_device(dev, ctx->flc_dma[DECRYPT], -+ sizeof(flc->flc) + desc_bytes(desc), -+ ctx->dir); -+ -+ return 0; -+} -+ -+static struct skcipher_edesc *skcipher_edesc_alloc(struct skcipher_request *req) -+{ -+ struct crypto_skcipher *skcipher = crypto_skcipher_reqtfm(req); -+ struct caam_request *req_ctx = skcipher_request_ctx(req); -+ struct dpaa2_fl_entry *in_fle = &req_ctx->fd_flt[1]; -+ struct dpaa2_fl_entry *out_fle = &req_ctx->fd_flt[0]; -+ struct caam_ctx *ctx = crypto_skcipher_ctx(skcipher); -+ struct device *dev = ctx->dev; -+ gfp_t flags = (req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP) ? -+ GFP_KERNEL : GFP_ATOMIC; -+ int src_nents, mapped_src_nents, dst_nents = 0, mapped_dst_nents = 0; -+ struct skcipher_edesc *edesc; -+ dma_addr_t iv_dma; -+ u8 *iv; -+ int ivsize = crypto_skcipher_ivsize(skcipher); -+ int dst_sg_idx, qm_sg_ents, qm_sg_bytes; -+ struct dpaa2_sg_entry *sg_table; -+ -+ src_nents = sg_nents_for_len(req->src, req->cryptlen); -+ if (unlikely(src_nents < 0)) { -+ dev_err(dev, "Insufficient bytes (%d) in src S/G\n", -+ req->cryptlen); -+ return ERR_PTR(src_nents); -+ } -+ -+ if (unlikely(req->dst != req->src)) { -+ dst_nents = sg_nents_for_len(req->dst, req->cryptlen); -+ if (unlikely(dst_nents < 0)) { -+ dev_err(dev, "Insufficient bytes (%d) in dst S/G\n", -+ req->cryptlen); -+ return ERR_PTR(dst_nents); -+ } -+ -+ mapped_src_nents = dma_map_sg(dev, req->src, src_nents, -+ DMA_TO_DEVICE); -+ if (unlikely(!mapped_src_nents)) { -+ dev_err(dev, "unable to map source\n"); -+ return ERR_PTR(-ENOMEM); -+ } -+ -+ mapped_dst_nents = dma_map_sg(dev, req->dst, dst_nents, -+ DMA_FROM_DEVICE); -+ if (unlikely(!mapped_dst_nents)) { -+ dev_err(dev, "unable to map destination\n"); -+ dma_unmap_sg(dev, req->src, src_nents, DMA_TO_DEVICE); -+ return ERR_PTR(-ENOMEM); -+ } -+ } else { -+ mapped_src_nents = dma_map_sg(dev, req->src, src_nents, -+ DMA_BIDIRECTIONAL); -+ if (unlikely(!mapped_src_nents)) { -+ dev_err(dev, "unable to map source\n"); -+ return ERR_PTR(-ENOMEM); -+ } -+ } -+ -+ qm_sg_ents = 1 + mapped_src_nents; -+ dst_sg_idx = qm_sg_ents; -+ -+ qm_sg_ents += mapped_dst_nents > 1 ? mapped_dst_nents : 0; -+ qm_sg_bytes = qm_sg_ents * sizeof(struct dpaa2_sg_entry); -+ if (unlikely(offsetof(struct skcipher_edesc, sgt) + qm_sg_bytes + -+ ivsize > CAAM_QI_MEMCACHE_SIZE)) { -+ dev_err(dev, "No space for %d S/G entries and/or %dB IV\n", -+ qm_sg_ents, ivsize); -+ caam_unmap(dev, req->src, req->dst, src_nents, dst_nents, 0, -+ 0, 0, 0); -+ return ERR_PTR(-ENOMEM); -+ } -+ -+ /* allocate space for base edesc, link tables and IV */ -+ edesc = qi_cache_zalloc(GFP_DMA | flags); -+ if (unlikely(!edesc)) { -+ dev_err(dev, "could not allocate extended descriptor\n"); -+ caam_unmap(dev, req->src, req->dst, src_nents, dst_nents, 0, -+ 0, 0, 0); -+ return ERR_PTR(-ENOMEM); -+ } -+ -+ /* Make sure IV is located in a DMAable area */ -+ sg_table = &edesc->sgt[0]; -+ iv = (u8 *)(sg_table + qm_sg_ents); -+ memcpy(iv, req->iv, ivsize); -+ -+ iv_dma = dma_map_single(dev, iv, ivsize, DMA_TO_DEVICE); -+ if (dma_mapping_error(dev, iv_dma)) { -+ dev_err(dev, "unable to map IV\n"); -+ caam_unmap(dev, req->src, req->dst, src_nents, dst_nents, 0, -+ 0, 0, 0); -+ qi_cache_free(edesc); -+ return ERR_PTR(-ENOMEM); -+ } -+ -+ edesc->src_nents = src_nents; -+ edesc->dst_nents = dst_nents; -+ edesc->iv_dma = iv_dma; -+ edesc->qm_sg_bytes = qm_sg_bytes; -+ -+ dma_to_qm_sg_one(sg_table, iv_dma, ivsize, 0); -+ sg_to_qm_sg_last(req->src, mapped_src_nents, sg_table + 1, 0); -+ -+ if (mapped_dst_nents > 1) -+ sg_to_qm_sg_last(req->dst, mapped_dst_nents, sg_table + -+ dst_sg_idx, 0); -+ -+ edesc->qm_sg_dma = dma_map_single(dev, sg_table, edesc->qm_sg_bytes, -+ DMA_TO_DEVICE); -+ if (dma_mapping_error(dev, edesc->qm_sg_dma)) { -+ dev_err(dev, "unable to map S/G table\n"); -+ caam_unmap(dev, req->src, req->dst, src_nents, dst_nents, -+ iv_dma, ivsize, 0, 0); -+ qi_cache_free(edesc); -+ return ERR_PTR(-ENOMEM); -+ } -+ -+ memset(&req_ctx->fd_flt, 0, sizeof(req_ctx->fd_flt)); -+ dpaa2_fl_set_final(in_fle, true); -+ dpaa2_fl_set_len(in_fle, req->cryptlen + ivsize); -+ dpaa2_fl_set_len(out_fle, req->cryptlen); -+ -+ dpaa2_fl_set_format(in_fle, dpaa2_fl_sg); -+ dpaa2_fl_set_addr(in_fle, edesc->qm_sg_dma); -+ -+ if (req->src == req->dst) { -+ dpaa2_fl_set_format(out_fle, dpaa2_fl_sg); -+ dpaa2_fl_set_addr(out_fle, edesc->qm_sg_dma + -+ sizeof(*sg_table)); -+ } else if (mapped_dst_nents > 1) { -+ dpaa2_fl_set_format(out_fle, dpaa2_fl_sg); -+ dpaa2_fl_set_addr(out_fle, edesc->qm_sg_dma + dst_sg_idx * -+ sizeof(*sg_table)); -+ } else { -+ dpaa2_fl_set_format(out_fle, dpaa2_fl_single); -+ dpaa2_fl_set_addr(out_fle, sg_dma_address(req->dst)); -+ } -+ -+ return edesc; -+} -+ -+static void aead_unmap(struct device *dev, struct aead_edesc *edesc, -+ struct aead_request *req) -+{ -+ struct crypto_aead *aead = crypto_aead_reqtfm(req); -+ int ivsize = crypto_aead_ivsize(aead); -+ -+ caam_unmap(dev, req->src, req->dst, edesc->src_nents, edesc->dst_nents, -+ edesc->iv_dma, ivsize, edesc->qm_sg_dma, edesc->qm_sg_bytes); -+ dma_unmap_single(dev, edesc->assoclen_dma, 4, DMA_TO_DEVICE); -+} -+ -+static void tls_unmap(struct device *dev, struct tls_edesc *edesc, -+ struct aead_request *req) -+{ -+ struct crypto_aead *tls = crypto_aead_reqtfm(req); -+ int ivsize = crypto_aead_ivsize(tls); -+ -+ caam_unmap(dev, req->src, edesc->dst, edesc->src_nents, -+ edesc->dst_nents, edesc->iv_dma, ivsize, edesc->qm_sg_dma, -+ edesc->qm_sg_bytes); -+} -+ -+static void skcipher_unmap(struct device *dev, struct skcipher_edesc *edesc, -+ struct skcipher_request *req) -+{ -+ struct crypto_skcipher *skcipher = crypto_skcipher_reqtfm(req); -+ int ivsize = crypto_skcipher_ivsize(skcipher); -+ -+ caam_unmap(dev, req->src, req->dst, edesc->src_nents, edesc->dst_nents, -+ edesc->iv_dma, ivsize, edesc->qm_sg_dma, edesc->qm_sg_bytes); -+} -+ -+static void aead_encrypt_done(void *cbk_ctx, u32 status) -+{ -+ struct crypto_async_request *areq = cbk_ctx; -+ struct aead_request *req = container_of(areq, struct aead_request, -+ base); -+ struct caam_request *req_ctx = to_caam_req(areq); -+ struct aead_edesc *edesc = req_ctx->edesc; -+ struct crypto_aead *aead = crypto_aead_reqtfm(req); -+ struct caam_ctx *ctx = crypto_aead_ctx(aead); -+ int ecode = 0; -+ -+#ifdef DEBUG -+ dev_err(ctx->dev, "%s %d: err 0x%x\n", __func__, __LINE__, status); -+#endif -+ -+ if (unlikely(status)) { -+ caam_qi2_strstatus(ctx->dev, status); -+ ecode = -EIO; -+ } -+ -+ aead_unmap(ctx->dev, edesc, req); -+ qi_cache_free(edesc); -+ aead_request_complete(req, ecode); -+} -+ -+static void aead_decrypt_done(void *cbk_ctx, u32 status) -+{ -+ struct crypto_async_request *areq = cbk_ctx; -+ struct aead_request *req = container_of(areq, struct aead_request, -+ base); -+ struct caam_request *req_ctx = to_caam_req(areq); -+ struct aead_edesc *edesc = req_ctx->edesc; -+ struct crypto_aead *aead = crypto_aead_reqtfm(req); -+ struct caam_ctx *ctx = crypto_aead_ctx(aead); -+ int ecode = 0; -+ -+#ifdef DEBUG -+ dev_err(ctx->dev, "%s %d: err 0x%x\n", __func__, __LINE__, status); -+#endif -+ -+ if (unlikely(status)) { -+ caam_qi2_strstatus(ctx->dev, status); -+ /* -+ * verify hw auth check passed else return -EBADMSG -+ */ -+ if ((status & JRSTA_CCBERR_ERRID_MASK) == -+ JRSTA_CCBERR_ERRID_ICVCHK) -+ ecode = -EBADMSG; -+ else -+ ecode = -EIO; -+ } -+ -+ aead_unmap(ctx->dev, edesc, req); -+ qi_cache_free(edesc); -+ aead_request_complete(req, ecode); -+} -+ -+static int aead_encrypt(struct aead_request *req) -+{ -+ struct aead_edesc *edesc; -+ struct crypto_aead *aead = crypto_aead_reqtfm(req); -+ struct caam_ctx *ctx = crypto_aead_ctx(aead); -+ struct caam_request *caam_req = aead_request_ctx(req); -+ int ret; -+ -+ /* allocate extended descriptor */ -+ edesc = aead_edesc_alloc(req, true); -+ if (IS_ERR(edesc)) -+ return PTR_ERR(edesc); -+ -+ caam_req->flc = &ctx->flc[ENCRYPT]; -+ caam_req->flc_dma = ctx->flc_dma[ENCRYPT]; -+ caam_req->cbk = aead_encrypt_done; -+ caam_req->ctx = &req->base; -+ caam_req->edesc = edesc; -+ ret = dpaa2_caam_enqueue(ctx->dev, caam_req); -+ if (ret != -EINPROGRESS && -+ !(ret == -EBUSY && req->base.flags & CRYPTO_TFM_REQ_MAY_BACKLOG)) { -+ aead_unmap(ctx->dev, edesc, req); -+ qi_cache_free(edesc); -+ } -+ -+ return ret; -+} -+ -+static int aead_decrypt(struct aead_request *req) -+{ -+ struct aead_edesc *edesc; -+ struct crypto_aead *aead = crypto_aead_reqtfm(req); -+ struct caam_ctx *ctx = crypto_aead_ctx(aead); -+ struct caam_request *caam_req = aead_request_ctx(req); -+ int ret; -+ -+ /* allocate extended descriptor */ -+ edesc = aead_edesc_alloc(req, false); -+ if (IS_ERR(edesc)) -+ return PTR_ERR(edesc); -+ -+ caam_req->flc = &ctx->flc[DECRYPT]; -+ caam_req->flc_dma = ctx->flc_dma[DECRYPT]; -+ caam_req->cbk = aead_decrypt_done; -+ caam_req->ctx = &req->base; -+ caam_req->edesc = edesc; -+ ret = dpaa2_caam_enqueue(ctx->dev, caam_req); -+ if (ret != -EINPROGRESS && -+ !(ret == -EBUSY && req->base.flags & CRYPTO_TFM_REQ_MAY_BACKLOG)) { -+ aead_unmap(ctx->dev, edesc, req); -+ qi_cache_free(edesc); -+ } -+ -+ return ret; -+} -+ -+static void tls_encrypt_done(void *cbk_ctx, u32 status) -+{ -+ struct crypto_async_request *areq = cbk_ctx; -+ struct aead_request *req = container_of(areq, struct aead_request, -+ base); -+ struct caam_request *req_ctx = to_caam_req(areq); -+ struct tls_edesc *edesc = req_ctx->edesc; -+ struct crypto_aead *tls = crypto_aead_reqtfm(req); -+ struct caam_ctx *ctx = crypto_aead_ctx(tls); -+ int ecode = 0; -+ -+#ifdef DEBUG -+ dev_err(ctx->dev, "%s %d: err 0x%x\n", __func__, __LINE__, status); -+#endif -+ -+ if (unlikely(status)) { -+ caam_qi2_strstatus(ctx->dev, status); -+ ecode = -EIO; -+ } -+ -+ tls_unmap(ctx->dev, edesc, req); -+ qi_cache_free(edesc); -+ aead_request_complete(req, ecode); -+} -+ -+static void tls_decrypt_done(void *cbk_ctx, u32 status) -+{ -+ struct crypto_async_request *areq = cbk_ctx; -+ struct aead_request *req = container_of(areq, struct aead_request, -+ base); -+ struct caam_request *req_ctx = to_caam_req(areq); -+ struct tls_edesc *edesc = req_ctx->edesc; -+ struct crypto_aead *tls = crypto_aead_reqtfm(req); -+ struct caam_ctx *ctx = crypto_aead_ctx(tls); -+ int ecode = 0; -+ -+#ifdef DEBUG -+ dev_err(ctx->dev, "%s %d: err 0x%x\n", __func__, __LINE__, status); -+#endif -+ -+ if (unlikely(status)) { -+ caam_qi2_strstatus(ctx->dev, status); -+ /* -+ * verify hw auth check passed else return -EBADMSG -+ */ -+ if ((status & JRSTA_CCBERR_ERRID_MASK) == -+ JRSTA_CCBERR_ERRID_ICVCHK) -+ ecode = -EBADMSG; -+ else -+ ecode = -EIO; -+ } -+ -+ tls_unmap(ctx->dev, edesc, req); -+ qi_cache_free(edesc); -+ aead_request_complete(req, ecode); -+} -+ -+static int tls_encrypt(struct aead_request *req) -+{ -+ struct tls_edesc *edesc; -+ struct crypto_aead *tls = crypto_aead_reqtfm(req); -+ struct caam_ctx *ctx = crypto_aead_ctx(tls); -+ struct caam_request *caam_req = aead_request_ctx(req); -+ int ret; -+ -+ /* allocate extended descriptor */ -+ edesc = tls_edesc_alloc(req, true); -+ if (IS_ERR(edesc)) -+ return PTR_ERR(edesc); -+ -+ caam_req->flc = &ctx->flc[ENCRYPT]; -+ caam_req->flc_dma = ctx->flc_dma[ENCRYPT]; -+ caam_req->cbk = tls_encrypt_done; -+ caam_req->ctx = &req->base; -+ caam_req->edesc = edesc; -+ ret = dpaa2_caam_enqueue(ctx->dev, caam_req); -+ if (ret != -EINPROGRESS && -+ !(ret == -EBUSY && req->base.flags & CRYPTO_TFM_REQ_MAY_BACKLOG)) { -+ tls_unmap(ctx->dev, edesc, req); -+ qi_cache_free(edesc); -+ } -+ -+ return ret; -+} -+ -+static int tls_decrypt(struct aead_request *req) -+{ -+ struct tls_edesc *edesc; -+ struct crypto_aead *tls = crypto_aead_reqtfm(req); -+ struct caam_ctx *ctx = crypto_aead_ctx(tls); -+ struct caam_request *caam_req = aead_request_ctx(req); -+ int ret; -+ -+ /* allocate extended descriptor */ -+ edesc = tls_edesc_alloc(req, false); -+ if (IS_ERR(edesc)) -+ return PTR_ERR(edesc); -+ -+ caam_req->flc = &ctx->flc[DECRYPT]; -+ caam_req->flc_dma = ctx->flc_dma[DECRYPT]; -+ caam_req->cbk = tls_decrypt_done; -+ caam_req->ctx = &req->base; -+ caam_req->edesc = edesc; -+ ret = dpaa2_caam_enqueue(ctx->dev, caam_req); -+ if (ret != -EINPROGRESS && -+ !(ret == -EBUSY && req->base.flags & CRYPTO_TFM_REQ_MAY_BACKLOG)) { -+ tls_unmap(ctx->dev, edesc, req); -+ qi_cache_free(edesc); -+ } -+ -+ return ret; -+} -+ -+static int ipsec_gcm_encrypt(struct aead_request *req) -+{ -+ if (req->assoclen < 8) -+ return -EINVAL; -+ -+ return aead_encrypt(req); -+} -+ -+static int ipsec_gcm_decrypt(struct aead_request *req) -+{ -+ if (req->assoclen < 8) -+ return -EINVAL; -+ -+ return aead_decrypt(req); -+} -+ -+static void skcipher_encrypt_done(void *cbk_ctx, u32 status) -+{ -+ struct crypto_async_request *areq = cbk_ctx; -+ struct skcipher_request *req = skcipher_request_cast(areq); -+ struct caam_request *req_ctx = to_caam_req(areq); -+ struct crypto_skcipher *skcipher = crypto_skcipher_reqtfm(req); -+ struct caam_ctx *ctx = crypto_skcipher_ctx(skcipher); -+ struct skcipher_edesc *edesc = req_ctx->edesc; -+ int ecode = 0; -+ int ivsize = crypto_skcipher_ivsize(skcipher); -+ -+#ifdef DEBUG -+ dev_err(ctx->dev, "%s %d: err 0x%x\n", __func__, __LINE__, status); -+#endif -+ -+ if (unlikely(status)) { -+ caam_qi2_strstatus(ctx->dev, status); -+ ecode = -EIO; -+ } -+ -+#ifdef DEBUG -+ print_hex_dump(KERN_ERR, "dstiv @" __stringify(__LINE__)": ", -+ DUMP_PREFIX_ADDRESS, 16, 4, req->iv, -+ edesc->src_nents > 1 ? 100 : ivsize, 1); -+ caam_dump_sg(KERN_ERR, "dst @" __stringify(__LINE__)": ", -+ DUMP_PREFIX_ADDRESS, 16, 4, req->dst, -+ edesc->dst_nents > 1 ? 100 : req->cryptlen, 1); -+#endif -+ -+ skcipher_unmap(ctx->dev, edesc, req); -+ -+ /* -+ * The crypto API expects us to set the IV (req->iv) to the last -+ * ciphertext block. This is used e.g. by the CTS mode. -+ */ -+ scatterwalk_map_and_copy(req->iv, req->dst, req->cryptlen - ivsize, -+ ivsize, 0); -+ -+ qi_cache_free(edesc); -+ skcipher_request_complete(req, ecode); -+} -+ -+static void skcipher_decrypt_done(void *cbk_ctx, u32 status) -+{ -+ struct crypto_async_request *areq = cbk_ctx; -+ struct skcipher_request *req = skcipher_request_cast(areq); -+ struct caam_request *req_ctx = to_caam_req(areq); -+ struct crypto_skcipher *skcipher = crypto_skcipher_reqtfm(req); -+ struct caam_ctx *ctx = crypto_skcipher_ctx(skcipher); -+ struct skcipher_edesc *edesc = req_ctx->edesc; -+ int ecode = 0; -+#ifdef DEBUG -+ int ivsize = crypto_skcipher_ivsize(skcipher); -+ -+ dev_err(ctx->dev, "%s %d: err 0x%x\n", __func__, __LINE__, status); -+#endif -+ -+ if (unlikely(status)) { -+ caam_qi2_strstatus(ctx->dev, status); -+ ecode = -EIO; -+ } -+ -+#ifdef DEBUG -+ print_hex_dump(KERN_ERR, "dstiv @" __stringify(__LINE__)": ", -+ DUMP_PREFIX_ADDRESS, 16, 4, req->iv, -+ edesc->src_nents > 1 ? 100 : ivsize, 1); -+ caam_dump_sg(KERN_ERR, "dst @" __stringify(__LINE__)": ", -+ DUMP_PREFIX_ADDRESS, 16, 4, req->dst, -+ edesc->dst_nents > 1 ? 100 : req->cryptlen, 1); -+#endif -+ -+ skcipher_unmap(ctx->dev, edesc, req); -+ qi_cache_free(edesc); -+ skcipher_request_complete(req, ecode); -+} -+ -+static int skcipher_encrypt(struct skcipher_request *req) -+{ -+ struct skcipher_edesc *edesc; -+ struct crypto_skcipher *skcipher = crypto_skcipher_reqtfm(req); -+ struct caam_ctx *ctx = crypto_skcipher_ctx(skcipher); -+ struct caam_request *caam_req = skcipher_request_ctx(req); -+ int ret; -+ -+ /* allocate extended descriptor */ -+ edesc = skcipher_edesc_alloc(req); -+ if (IS_ERR(edesc)) -+ return PTR_ERR(edesc); -+ -+ caam_req->flc = &ctx->flc[ENCRYPT]; -+ caam_req->flc_dma = ctx->flc_dma[ENCRYPT]; -+ caam_req->cbk = skcipher_encrypt_done; -+ caam_req->ctx = &req->base; -+ caam_req->edesc = edesc; -+ ret = dpaa2_caam_enqueue(ctx->dev, caam_req); -+ if (ret != -EINPROGRESS && -+ !(ret == -EBUSY && req->base.flags & CRYPTO_TFM_REQ_MAY_BACKLOG)) { -+ skcipher_unmap(ctx->dev, edesc, req); -+ qi_cache_free(edesc); -+ } -+ -+ return ret; -+} -+ -+static int skcipher_decrypt(struct skcipher_request *req) -+{ -+ struct skcipher_edesc *edesc; -+ struct crypto_skcipher *skcipher = crypto_skcipher_reqtfm(req); -+ struct caam_ctx *ctx = crypto_skcipher_ctx(skcipher); -+ struct caam_request *caam_req = skcipher_request_ctx(req); -+ int ivsize = crypto_skcipher_ivsize(skcipher); -+ int ret; -+ -+ /* allocate extended descriptor */ -+ edesc = skcipher_edesc_alloc(req); -+ if (IS_ERR(edesc)) -+ return PTR_ERR(edesc); -+ -+ /* -+ * The crypto API expects us to set the IV (req->iv) to the last -+ * ciphertext block. -+ */ -+ scatterwalk_map_and_copy(req->iv, req->src, req->cryptlen - ivsize, -+ ivsize, 0); -+ -+ caam_req->flc = &ctx->flc[DECRYPT]; -+ caam_req->flc_dma = ctx->flc_dma[DECRYPT]; -+ caam_req->cbk = skcipher_decrypt_done; -+ caam_req->ctx = &req->base; -+ caam_req->edesc = edesc; -+ ret = dpaa2_caam_enqueue(ctx->dev, caam_req); -+ if (ret != -EINPROGRESS && -+ !(ret == -EBUSY && req->base.flags & CRYPTO_TFM_REQ_MAY_BACKLOG)) { -+ skcipher_unmap(ctx->dev, edesc, req); -+ qi_cache_free(edesc); -+ } -+ -+ return ret; -+} -+ -+static int caam_cra_init(struct caam_ctx *ctx, struct caam_alg_entry *caam, -+ bool uses_dkp) -+{ -+ dma_addr_t dma_addr; -+ int i; -+ -+ /* copy descriptor header template value */ -+ ctx->cdata.algtype = OP_TYPE_CLASS1_ALG | caam->class1_alg_type; -+ ctx->adata.algtype = OP_TYPE_CLASS2_ALG | caam->class2_alg_type; -+ -+ ctx->dev = caam->dev; -+ ctx->dir = uses_dkp ? DMA_BIDIRECTIONAL : DMA_TO_DEVICE; -+ -+ dma_addr = dma_map_single_attrs(ctx->dev, ctx->flc, -+ offsetof(struct caam_ctx, flc_dma), -+ ctx->dir, DMA_ATTR_SKIP_CPU_SYNC); -+ if (dma_mapping_error(ctx->dev, dma_addr)) { -+ dev_err(ctx->dev, "unable to map key, shared descriptors\n"); -+ return -ENOMEM; -+ } -+ -+ for (i = 0; i < NUM_OP; i++) -+ ctx->flc_dma[i] = dma_addr + i * sizeof(ctx->flc[i]); -+ ctx->key_dma = dma_addr + NUM_OP * sizeof(ctx->flc[0]); -+ -+ return 0; -+} -+ -+static int caam_cra_init_skcipher(struct crypto_skcipher *tfm) -+{ -+ struct skcipher_alg *alg = crypto_skcipher_alg(tfm); -+ struct caam_skcipher_alg *caam_alg = -+ container_of(alg, typeof(*caam_alg), skcipher); -+ -+ crypto_skcipher_set_reqsize(tfm, sizeof(struct caam_request)); -+ return caam_cra_init(crypto_skcipher_ctx(tfm), &caam_alg->caam, false); -+} -+ -+static int caam_cra_init_aead(struct crypto_aead *tfm) -+{ -+ struct aead_alg *alg = crypto_aead_alg(tfm); -+ struct caam_aead_alg *caam_alg = container_of(alg, typeof(*caam_alg), -+ aead); -+ -+ crypto_aead_set_reqsize(tfm, sizeof(struct caam_request)); -+ return caam_cra_init(crypto_aead_ctx(tfm), &caam_alg->caam, -+ (alg->setkey == aead_setkey) || -+ (alg->setkey == tls_setkey)); -+} -+ -+static void caam_exit_common(struct caam_ctx *ctx) -+{ -+ dma_unmap_single_attrs(ctx->dev, ctx->flc_dma[0], -+ offsetof(struct caam_ctx, flc_dma), ctx->dir, -+ DMA_ATTR_SKIP_CPU_SYNC); -+} -+ -+static void caam_cra_exit(struct crypto_skcipher *tfm) -+{ -+ caam_exit_common(crypto_skcipher_ctx(tfm)); -+} -+ -+static void caam_cra_exit_aead(struct crypto_aead *tfm) -+{ -+ caam_exit_common(crypto_aead_ctx(tfm)); -+} -+ -+static struct caam_skcipher_alg driver_algs[] = { -+ { -+ .skcipher = { -+ .base = { -+ .cra_name = "cbc(aes)", -+ .cra_driver_name = "cbc-aes-caam-qi2", -+ .cra_blocksize = AES_BLOCK_SIZE, -+ }, -+ .setkey = skcipher_setkey, -+ .encrypt = skcipher_encrypt, -+ .decrypt = skcipher_decrypt, -+ .min_keysize = AES_MIN_KEY_SIZE, -+ .max_keysize = AES_MAX_KEY_SIZE, -+ .ivsize = AES_BLOCK_SIZE, -+ }, -+ .caam.class1_alg_type = OP_ALG_ALGSEL_AES | OP_ALG_AAI_CBC, -+ }, -+ { -+ .skcipher = { -+ .base = { -+ .cra_name = "cbc(des3_ede)", -+ .cra_driver_name = "cbc-3des-caam-qi2", -+ .cra_blocksize = DES3_EDE_BLOCK_SIZE, -+ }, -+ .setkey = skcipher_setkey, -+ .encrypt = skcipher_encrypt, -+ .decrypt = skcipher_decrypt, -+ .min_keysize = DES3_EDE_KEY_SIZE, -+ .max_keysize = DES3_EDE_KEY_SIZE, -+ .ivsize = DES3_EDE_BLOCK_SIZE, -+ }, -+ .caam.class1_alg_type = OP_ALG_ALGSEL_3DES | OP_ALG_AAI_CBC, -+ }, -+ { -+ .skcipher = { -+ .base = { -+ .cra_name = "cbc(des)", -+ .cra_driver_name = "cbc-des-caam-qi2", -+ .cra_blocksize = DES_BLOCK_SIZE, -+ }, -+ .setkey = skcipher_setkey, -+ .encrypt = skcipher_encrypt, -+ .decrypt = skcipher_decrypt, -+ .min_keysize = DES_KEY_SIZE, -+ .max_keysize = DES_KEY_SIZE, -+ .ivsize = DES_BLOCK_SIZE, -+ }, -+ .caam.class1_alg_type = OP_ALG_ALGSEL_DES | OP_ALG_AAI_CBC, -+ }, -+ { -+ .skcipher = { -+ .base = { -+ .cra_name = "ctr(aes)", -+ .cra_driver_name = "ctr-aes-caam-qi2", -+ .cra_blocksize = 1, -+ }, -+ .setkey = skcipher_setkey, -+ .encrypt = skcipher_encrypt, -+ .decrypt = skcipher_decrypt, -+ .min_keysize = AES_MIN_KEY_SIZE, -+ .max_keysize = AES_MAX_KEY_SIZE, -+ .ivsize = AES_BLOCK_SIZE, -+ .chunksize = AES_BLOCK_SIZE, -+ }, -+ .caam.class1_alg_type = OP_ALG_ALGSEL_AES | -+ OP_ALG_AAI_CTR_MOD128, -+ }, -+ { -+ .skcipher = { -+ .base = { -+ .cra_name = "rfc3686(ctr(aes))", -+ .cra_driver_name = "rfc3686-ctr-aes-caam-qi2", -+ .cra_blocksize = 1, -+ }, -+ .setkey = skcipher_setkey, -+ .encrypt = skcipher_encrypt, -+ .decrypt = skcipher_decrypt, -+ .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, -+ .chunksize = AES_BLOCK_SIZE, -+ }, -+ .caam = { -+ .class1_alg_type = OP_ALG_ALGSEL_AES | -+ OP_ALG_AAI_CTR_MOD128, -+ .rfc3686 = true, -+ }, -+ }, -+ { -+ .skcipher = { -+ .base = { -+ .cra_name = "xts(aes)", -+ .cra_driver_name = "xts-aes-caam-qi2", -+ .cra_blocksize = AES_BLOCK_SIZE, -+ }, -+ .setkey = xts_skcipher_setkey, -+ .encrypt = skcipher_encrypt, -+ .decrypt = skcipher_decrypt, -+ .min_keysize = 2 * AES_MIN_KEY_SIZE, -+ .max_keysize = 2 * AES_MAX_KEY_SIZE, -+ .ivsize = AES_BLOCK_SIZE, -+ }, -+ .caam.class1_alg_type = OP_ALG_ALGSEL_AES | OP_ALG_AAI_XTS, -+ }, -+ { -+ .skcipher = { -+ .base = { -+ .cra_name = "chacha20", -+ .cra_driver_name = "chacha20-caam-qi2", -+ .cra_blocksize = 1, -+ }, -+ .setkey = skcipher_setkey, -+ .encrypt = skcipher_encrypt, -+ .decrypt = skcipher_decrypt, -+ .min_keysize = CHACHA20_KEY_SIZE, -+ .max_keysize = CHACHA20_KEY_SIZE, -+ .ivsize = CHACHA20_IV_SIZE, -+ }, -+ .caam.class1_alg_type = OP_ALG_ALGSEL_CHACHA20, -+ }, -+}; -+ -+static struct caam_aead_alg driver_aeads[] = { -+ { -+ .aead = { -+ .base = { -+ .cra_name = "rfc4106(gcm(aes))", -+ .cra_driver_name = "rfc4106-gcm-aes-caam-qi2", -+ .cra_blocksize = 1, -+ }, -+ .setkey = rfc4106_setkey, -+ .setauthsize = rfc4106_setauthsize, -+ .encrypt = ipsec_gcm_encrypt, -+ .decrypt = ipsec_gcm_decrypt, -+ .ivsize = 8, -+ .maxauthsize = AES_BLOCK_SIZE, -+ }, -+ .caam = { -+ .class1_alg_type = OP_ALG_ALGSEL_AES | OP_ALG_AAI_GCM, -+ }, -+ }, -+ { -+ .aead = { -+ .base = { -+ .cra_name = "rfc4543(gcm(aes))", -+ .cra_driver_name = "rfc4543-gcm-aes-caam-qi2", -+ .cra_blocksize = 1, -+ }, -+ .setkey = rfc4543_setkey, -+ .setauthsize = rfc4543_setauthsize, -+ .encrypt = ipsec_gcm_encrypt, -+ .decrypt = ipsec_gcm_decrypt, -+ .ivsize = 8, -+ .maxauthsize = AES_BLOCK_SIZE, -+ }, -+ .caam = { -+ .class1_alg_type = OP_ALG_ALGSEL_AES | OP_ALG_AAI_GCM, -+ }, -+ }, -+ /* Galois Counter Mode */ -+ { -+ .aead = { -+ .base = { -+ .cra_name = "gcm(aes)", -+ .cra_driver_name = "gcm-aes-caam-qi2", -+ .cra_blocksize = 1, -+ }, -+ .setkey = gcm_setkey, -+ .setauthsize = gcm_setauthsize, -+ .encrypt = aead_encrypt, -+ .decrypt = aead_decrypt, -+ .ivsize = 12, -+ .maxauthsize = AES_BLOCK_SIZE, -+ }, -+ .caam = { -+ .class1_alg_type = OP_ALG_ALGSEL_AES | OP_ALG_AAI_GCM, -+ } -+ }, -+ /* single-pass ipsec_esp descriptor */ -+ { -+ .aead = { -+ .base = { -+ .cra_name = "authenc(hmac(md5),cbc(aes))", -+ .cra_driver_name = "authenc-hmac-md5-" -+ "cbc-aes-caam-qi2", -+ .cra_blocksize = AES_BLOCK_SIZE, -+ }, -+ .setkey = aead_setkey, -+ .setauthsize = aead_setauthsize, -+ .encrypt = aead_encrypt, -+ .decrypt = aead_decrypt, -+ .ivsize = AES_BLOCK_SIZE, -+ .maxauthsize = MD5_DIGEST_SIZE, -+ }, -+ .caam = { -+ .class1_alg_type = OP_ALG_ALGSEL_AES | OP_ALG_AAI_CBC, -+ .class2_alg_type = OP_ALG_ALGSEL_MD5 | -+ OP_ALG_AAI_HMAC_PRECOMP, -+ } -+ }, -+ { -+ .aead = { -+ .base = { -+ .cra_name = "echainiv(authenc(hmac(md5)," -+ "cbc(aes)))", -+ .cra_driver_name = "echainiv-authenc-hmac-md5-" -+ "cbc-aes-caam-qi2", -+ .cra_blocksize = AES_BLOCK_SIZE, -+ }, -+ .setkey = aead_setkey, -+ .setauthsize = aead_setauthsize, -+ .encrypt = aead_encrypt, -+ .decrypt = aead_decrypt, -+ .ivsize = AES_BLOCK_SIZE, -+ .maxauthsize = MD5_DIGEST_SIZE, -+ }, -+ .caam = { -+ .class1_alg_type = OP_ALG_ALGSEL_AES | OP_ALG_AAI_CBC, -+ .class2_alg_type = OP_ALG_ALGSEL_MD5 | -+ OP_ALG_AAI_HMAC_PRECOMP, -+ .geniv = true, -+ } -+ }, -+ { -+ .aead = { -+ .base = { -+ .cra_name = "authenc(hmac(sha1),cbc(aes))", -+ .cra_driver_name = "authenc-hmac-sha1-" -+ "cbc-aes-caam-qi2", -+ .cra_blocksize = AES_BLOCK_SIZE, -+ }, -+ .setkey = aead_setkey, -+ .setauthsize = aead_setauthsize, -+ .encrypt = aead_encrypt, -+ .decrypt = aead_decrypt, -+ .ivsize = AES_BLOCK_SIZE, -+ .maxauthsize = SHA1_DIGEST_SIZE, -+ }, -+ .caam = { -+ .class1_alg_type = OP_ALG_ALGSEL_AES | OP_ALG_AAI_CBC, -+ .class2_alg_type = OP_ALG_ALGSEL_SHA1 | -+ OP_ALG_AAI_HMAC_PRECOMP, -+ } -+ }, -+ { -+ .aead = { -+ .base = { -+ .cra_name = "echainiv(authenc(hmac(sha1)," -+ "cbc(aes)))", -+ .cra_driver_name = "echainiv-authenc-" -+ "hmac-sha1-cbc-aes-caam-qi2", -+ .cra_blocksize = AES_BLOCK_SIZE, -+ }, -+ .setkey = aead_setkey, -+ .setauthsize = aead_setauthsize, -+ .encrypt = aead_encrypt, -+ .decrypt = aead_decrypt, -+ .ivsize = AES_BLOCK_SIZE, -+ .maxauthsize = SHA1_DIGEST_SIZE, -+ }, -+ .caam = { -+ .class1_alg_type = OP_ALG_ALGSEL_AES | OP_ALG_AAI_CBC, -+ .class2_alg_type = OP_ALG_ALGSEL_SHA1 | -+ OP_ALG_AAI_HMAC_PRECOMP, -+ .geniv = true, -+ }, -+ }, -+ { -+ .aead = { -+ .base = { -+ .cra_name = "authenc(hmac(sha224),cbc(aes))", -+ .cra_driver_name = "authenc-hmac-sha224-" -+ "cbc-aes-caam-qi2", -+ .cra_blocksize = AES_BLOCK_SIZE, -+ }, -+ .setkey = aead_setkey, -+ .setauthsize = aead_setauthsize, -+ .encrypt = aead_encrypt, -+ .decrypt = aead_decrypt, -+ .ivsize = AES_BLOCK_SIZE, -+ .maxauthsize = SHA224_DIGEST_SIZE, -+ }, -+ .caam = { -+ .class1_alg_type = OP_ALG_ALGSEL_AES | OP_ALG_AAI_CBC, -+ .class2_alg_type = OP_ALG_ALGSEL_SHA224 | -+ OP_ALG_AAI_HMAC_PRECOMP, -+ } -+ }, -+ { -+ .aead = { -+ .base = { -+ .cra_name = "echainiv(authenc(hmac(sha224)," -+ "cbc(aes)))", -+ .cra_driver_name = "echainiv-authenc-" -+ "hmac-sha224-cbc-aes-caam-qi2", -+ .cra_blocksize = AES_BLOCK_SIZE, -+ }, -+ .setkey = aead_setkey, -+ .setauthsize = aead_setauthsize, -+ .encrypt = aead_encrypt, -+ .decrypt = aead_decrypt, -+ .ivsize = AES_BLOCK_SIZE, -+ .maxauthsize = SHA224_DIGEST_SIZE, -+ }, -+ .caam = { -+ .class1_alg_type = OP_ALG_ALGSEL_AES | OP_ALG_AAI_CBC, -+ .class2_alg_type = OP_ALG_ALGSEL_SHA224 | -+ OP_ALG_AAI_HMAC_PRECOMP, -+ .geniv = true, -+ } -+ }, -+ { -+ .aead = { -+ .base = { -+ .cra_name = "authenc(hmac(sha256),cbc(aes))", -+ .cra_driver_name = "authenc-hmac-sha256-" -+ "cbc-aes-caam-qi2", -+ .cra_blocksize = AES_BLOCK_SIZE, -+ }, -+ .setkey = aead_setkey, -+ .setauthsize = aead_setauthsize, -+ .encrypt = aead_encrypt, -+ .decrypt = aead_decrypt, -+ .ivsize = AES_BLOCK_SIZE, -+ .maxauthsize = SHA256_DIGEST_SIZE, -+ }, -+ .caam = { -+ .class1_alg_type = OP_ALG_ALGSEL_AES | OP_ALG_AAI_CBC, -+ .class2_alg_type = OP_ALG_ALGSEL_SHA256 | -+ OP_ALG_AAI_HMAC_PRECOMP, -+ } -+ }, -+ { -+ .aead = { -+ .base = { -+ .cra_name = "echainiv(authenc(hmac(sha256)," -+ "cbc(aes)))", -+ .cra_driver_name = "echainiv-authenc-" -+ "hmac-sha256-cbc-aes-" -+ "caam-qi2", -+ .cra_blocksize = AES_BLOCK_SIZE, -+ }, -+ .setkey = aead_setkey, -+ .setauthsize = aead_setauthsize, -+ .encrypt = aead_encrypt, -+ .decrypt = aead_decrypt, -+ .ivsize = AES_BLOCK_SIZE, -+ .maxauthsize = SHA256_DIGEST_SIZE, -+ }, -+ .caam = { -+ .class1_alg_type = OP_ALG_ALGSEL_AES | OP_ALG_AAI_CBC, -+ .class2_alg_type = OP_ALG_ALGSEL_SHA256 | -+ OP_ALG_AAI_HMAC_PRECOMP, -+ .geniv = true, -+ } -+ }, -+ { -+ .aead = { -+ .base = { -+ .cra_name = "authenc(hmac(sha384),cbc(aes))", -+ .cra_driver_name = "authenc-hmac-sha384-" -+ "cbc-aes-caam-qi2", -+ .cra_blocksize = AES_BLOCK_SIZE, -+ }, -+ .setkey = aead_setkey, -+ .setauthsize = aead_setauthsize, -+ .encrypt = aead_encrypt, -+ .decrypt = aead_decrypt, -+ .ivsize = AES_BLOCK_SIZE, -+ .maxauthsize = SHA384_DIGEST_SIZE, -+ }, -+ .caam = { -+ .class1_alg_type = OP_ALG_ALGSEL_AES | OP_ALG_AAI_CBC, -+ .class2_alg_type = OP_ALG_ALGSEL_SHA384 | -+ OP_ALG_AAI_HMAC_PRECOMP, -+ } -+ }, -+ { -+ .aead = { -+ .base = { -+ .cra_name = "echainiv(authenc(hmac(sha384)," -+ "cbc(aes)))", -+ .cra_driver_name = "echainiv-authenc-" -+ "hmac-sha384-cbc-aes-" -+ "caam-qi2", -+ .cra_blocksize = AES_BLOCK_SIZE, -+ }, -+ .setkey = aead_setkey, -+ .setauthsize = aead_setauthsize, -+ .encrypt = aead_encrypt, -+ .decrypt = aead_decrypt, -+ .ivsize = AES_BLOCK_SIZE, -+ .maxauthsize = SHA384_DIGEST_SIZE, -+ }, -+ .caam = { -+ .class1_alg_type = OP_ALG_ALGSEL_AES | OP_ALG_AAI_CBC, -+ .class2_alg_type = OP_ALG_ALGSEL_SHA384 | -+ OP_ALG_AAI_HMAC_PRECOMP, -+ .geniv = true, -+ } -+ }, -+ { -+ .aead = { -+ .base = { -+ .cra_name = "authenc(hmac(sha512),cbc(aes))", -+ .cra_driver_name = "authenc-hmac-sha512-" -+ "cbc-aes-caam-qi2", -+ .cra_blocksize = AES_BLOCK_SIZE, -+ }, -+ .setkey = aead_setkey, -+ .setauthsize = aead_setauthsize, -+ .encrypt = aead_encrypt, -+ .decrypt = aead_decrypt, -+ .ivsize = AES_BLOCK_SIZE, -+ .maxauthsize = SHA512_DIGEST_SIZE, -+ }, -+ .caam = { -+ .class1_alg_type = OP_ALG_ALGSEL_AES | OP_ALG_AAI_CBC, -+ .class2_alg_type = OP_ALG_ALGSEL_SHA512 | -+ OP_ALG_AAI_HMAC_PRECOMP, -+ } -+ }, -+ { -+ .aead = { -+ .base = { -+ .cra_name = "echainiv(authenc(hmac(sha512)," -+ "cbc(aes)))", -+ .cra_driver_name = "echainiv-authenc-" -+ "hmac-sha512-cbc-aes-" -+ "caam-qi2", -+ .cra_blocksize = AES_BLOCK_SIZE, -+ }, -+ .setkey = aead_setkey, -+ .setauthsize = aead_setauthsize, -+ .encrypt = aead_encrypt, -+ .decrypt = aead_decrypt, -+ .ivsize = AES_BLOCK_SIZE, -+ .maxauthsize = SHA512_DIGEST_SIZE, -+ }, -+ .caam = { -+ .class1_alg_type = OP_ALG_ALGSEL_AES | OP_ALG_AAI_CBC, -+ .class2_alg_type = OP_ALG_ALGSEL_SHA512 | -+ OP_ALG_AAI_HMAC_PRECOMP, -+ .geniv = true, -+ } -+ }, -+ { -+ .aead = { -+ .base = { -+ .cra_name = "authenc(hmac(md5),cbc(des3_ede))", -+ .cra_driver_name = "authenc-hmac-md5-" -+ "cbc-des3_ede-caam-qi2", -+ .cra_blocksize = DES3_EDE_BLOCK_SIZE, -+ }, -+ .setkey = aead_setkey, -+ .setauthsize = aead_setauthsize, -+ .encrypt = aead_encrypt, -+ .decrypt = aead_decrypt, -+ .ivsize = DES3_EDE_BLOCK_SIZE, -+ .maxauthsize = MD5_DIGEST_SIZE, -+ }, -+ .caam = { -+ .class1_alg_type = OP_ALG_ALGSEL_3DES | OP_ALG_AAI_CBC, -+ .class2_alg_type = OP_ALG_ALGSEL_MD5 | -+ OP_ALG_AAI_HMAC_PRECOMP, -+ } -+ }, -+ { -+ .aead = { -+ .base = { -+ .cra_name = "echainiv(authenc(hmac(md5)," -+ "cbc(des3_ede)))", -+ .cra_driver_name = "echainiv-authenc-hmac-md5-" -+ "cbc-des3_ede-caam-qi2", -+ .cra_blocksize = DES3_EDE_BLOCK_SIZE, -+ }, -+ .setkey = aead_setkey, -+ .setauthsize = aead_setauthsize, -+ .encrypt = aead_encrypt, -+ .decrypt = aead_decrypt, -+ .ivsize = DES3_EDE_BLOCK_SIZE, -+ .maxauthsize = MD5_DIGEST_SIZE, -+ }, -+ .caam = { -+ .class1_alg_type = OP_ALG_ALGSEL_3DES | OP_ALG_AAI_CBC, -+ .class2_alg_type = OP_ALG_ALGSEL_MD5 | -+ OP_ALG_AAI_HMAC_PRECOMP, -+ .geniv = true, -+ } -+ }, -+ { -+ .aead = { -+ .base = { -+ .cra_name = "authenc(hmac(sha1)," -+ "cbc(des3_ede))", -+ .cra_driver_name = "authenc-hmac-sha1-" -+ "cbc-des3_ede-caam-qi2", -+ .cra_blocksize = DES3_EDE_BLOCK_SIZE, -+ }, -+ .setkey = aead_setkey, -+ .setauthsize = aead_setauthsize, -+ .encrypt = aead_encrypt, -+ .decrypt = aead_decrypt, -+ .ivsize = DES3_EDE_BLOCK_SIZE, -+ .maxauthsize = SHA1_DIGEST_SIZE, -+ }, -+ .caam = { -+ .class1_alg_type = OP_ALG_ALGSEL_3DES | OP_ALG_AAI_CBC, -+ .class2_alg_type = OP_ALG_ALGSEL_SHA1 | -+ OP_ALG_AAI_HMAC_PRECOMP, -+ }, -+ }, -+ { -+ .aead = { -+ .base = { -+ .cra_name = "echainiv(authenc(hmac(sha1)," -+ "cbc(des3_ede)))", -+ .cra_driver_name = "echainiv-authenc-" -+ "hmac-sha1-" -+ "cbc-des3_ede-caam-qi2", -+ .cra_blocksize = DES3_EDE_BLOCK_SIZE, -+ }, -+ .setkey = aead_setkey, -+ .setauthsize = aead_setauthsize, -+ .encrypt = aead_encrypt, -+ .decrypt = aead_decrypt, -+ .ivsize = DES3_EDE_BLOCK_SIZE, -+ .maxauthsize = SHA1_DIGEST_SIZE, -+ }, -+ .caam = { -+ .class1_alg_type = OP_ALG_ALGSEL_3DES | OP_ALG_AAI_CBC, -+ .class2_alg_type = OP_ALG_ALGSEL_SHA1 | -+ OP_ALG_AAI_HMAC_PRECOMP, -+ .geniv = true, -+ } -+ }, -+ { -+ .aead = { -+ .base = { -+ .cra_name = "authenc(hmac(sha224)," -+ "cbc(des3_ede))", -+ .cra_driver_name = "authenc-hmac-sha224-" -+ "cbc-des3_ede-caam-qi2", -+ .cra_blocksize = DES3_EDE_BLOCK_SIZE, -+ }, -+ .setkey = aead_setkey, -+ .setauthsize = aead_setauthsize, -+ .encrypt = aead_encrypt, -+ .decrypt = aead_decrypt, -+ .ivsize = DES3_EDE_BLOCK_SIZE, -+ .maxauthsize = SHA224_DIGEST_SIZE, -+ }, -+ .caam = { -+ .class1_alg_type = OP_ALG_ALGSEL_3DES | OP_ALG_AAI_CBC, -+ .class2_alg_type = OP_ALG_ALGSEL_SHA224 | -+ OP_ALG_AAI_HMAC_PRECOMP, -+ }, -+ }, -+ { -+ .aead = { -+ .base = { -+ .cra_name = "echainiv(authenc(hmac(sha224)," -+ "cbc(des3_ede)))", -+ .cra_driver_name = "echainiv-authenc-" -+ "hmac-sha224-" -+ "cbc-des3_ede-caam-qi2", -+ .cra_blocksize = DES3_EDE_BLOCK_SIZE, -+ }, -+ .setkey = aead_setkey, -+ .setauthsize = aead_setauthsize, -+ .encrypt = aead_encrypt, -+ .decrypt = aead_decrypt, -+ .ivsize = DES3_EDE_BLOCK_SIZE, -+ .maxauthsize = SHA224_DIGEST_SIZE, -+ }, -+ .caam = { -+ .class1_alg_type = OP_ALG_ALGSEL_3DES | OP_ALG_AAI_CBC, -+ .class2_alg_type = OP_ALG_ALGSEL_SHA224 | -+ OP_ALG_AAI_HMAC_PRECOMP, -+ .geniv = true, -+ } -+ }, -+ { -+ .aead = { -+ .base = { -+ .cra_name = "authenc(hmac(sha256)," -+ "cbc(des3_ede))", -+ .cra_driver_name = "authenc-hmac-sha256-" -+ "cbc-des3_ede-caam-qi2", -+ .cra_blocksize = DES3_EDE_BLOCK_SIZE, -+ }, -+ .setkey = aead_setkey, -+ .setauthsize = aead_setauthsize, -+ .encrypt = aead_encrypt, -+ .decrypt = aead_decrypt, -+ .ivsize = DES3_EDE_BLOCK_SIZE, -+ .maxauthsize = SHA256_DIGEST_SIZE, -+ }, -+ .caam = { -+ .class1_alg_type = OP_ALG_ALGSEL_3DES | OP_ALG_AAI_CBC, -+ .class2_alg_type = OP_ALG_ALGSEL_SHA256 | -+ OP_ALG_AAI_HMAC_PRECOMP, -+ }, -+ }, -+ { -+ .aead = { -+ .base = { -+ .cra_name = "echainiv(authenc(hmac(sha256)," -+ "cbc(des3_ede)))", -+ .cra_driver_name = "echainiv-authenc-" -+ "hmac-sha256-" -+ "cbc-des3_ede-caam-qi2", -+ .cra_blocksize = DES3_EDE_BLOCK_SIZE, -+ }, -+ .setkey = aead_setkey, -+ .setauthsize = aead_setauthsize, -+ .encrypt = aead_encrypt, -+ .decrypt = aead_decrypt, -+ .ivsize = DES3_EDE_BLOCK_SIZE, -+ .maxauthsize = SHA256_DIGEST_SIZE, -+ }, -+ .caam = { -+ .class1_alg_type = OP_ALG_ALGSEL_3DES | OP_ALG_AAI_CBC, -+ .class2_alg_type = OP_ALG_ALGSEL_SHA256 | -+ OP_ALG_AAI_HMAC_PRECOMP, -+ .geniv = true, -+ } -+ }, -+ { -+ .aead = { -+ .base = { -+ .cra_name = "authenc(hmac(sha384)," -+ "cbc(des3_ede))", -+ .cra_driver_name = "authenc-hmac-sha384-" -+ "cbc-des3_ede-caam-qi2", -+ .cra_blocksize = DES3_EDE_BLOCK_SIZE, -+ }, -+ .setkey = aead_setkey, -+ .setauthsize = aead_setauthsize, -+ .encrypt = aead_encrypt, -+ .decrypt = aead_decrypt, -+ .ivsize = DES3_EDE_BLOCK_SIZE, -+ .maxauthsize = SHA384_DIGEST_SIZE, -+ }, -+ .caam = { -+ .class1_alg_type = OP_ALG_ALGSEL_3DES | OP_ALG_AAI_CBC, -+ .class2_alg_type = OP_ALG_ALGSEL_SHA384 | -+ OP_ALG_AAI_HMAC_PRECOMP, -+ }, -+ }, -+ { -+ .aead = { -+ .base = { -+ .cra_name = "echainiv(authenc(hmac(sha384)," -+ "cbc(des3_ede)))", -+ .cra_driver_name = "echainiv-authenc-" -+ "hmac-sha384-" -+ "cbc-des3_ede-caam-qi2", -+ .cra_blocksize = DES3_EDE_BLOCK_SIZE, -+ }, -+ .setkey = aead_setkey, -+ .setauthsize = aead_setauthsize, -+ .encrypt = aead_encrypt, -+ .decrypt = aead_decrypt, -+ .ivsize = DES3_EDE_BLOCK_SIZE, -+ .maxauthsize = SHA384_DIGEST_SIZE, -+ }, -+ .caam = { -+ .class1_alg_type = OP_ALG_ALGSEL_3DES | OP_ALG_AAI_CBC, -+ .class2_alg_type = OP_ALG_ALGSEL_SHA384 | -+ OP_ALG_AAI_HMAC_PRECOMP, -+ .geniv = true, -+ } -+ }, -+ { -+ .aead = { -+ .base = { -+ .cra_name = "authenc(hmac(sha512)," -+ "cbc(des3_ede))", -+ .cra_driver_name = "authenc-hmac-sha512-" -+ "cbc-des3_ede-caam-qi2", -+ .cra_blocksize = DES3_EDE_BLOCK_SIZE, -+ }, -+ .setkey = aead_setkey, -+ .setauthsize = aead_setauthsize, -+ .encrypt = aead_encrypt, -+ .decrypt = aead_decrypt, -+ .ivsize = DES3_EDE_BLOCK_SIZE, -+ .maxauthsize = SHA512_DIGEST_SIZE, -+ }, -+ .caam = { -+ .class1_alg_type = OP_ALG_ALGSEL_3DES | OP_ALG_AAI_CBC, -+ .class2_alg_type = OP_ALG_ALGSEL_SHA512 | -+ OP_ALG_AAI_HMAC_PRECOMP, -+ }, -+ }, -+ { -+ .aead = { -+ .base = { -+ .cra_name = "echainiv(authenc(hmac(sha512)," -+ "cbc(des3_ede)))", -+ .cra_driver_name = "echainiv-authenc-" -+ "hmac-sha512-" -+ "cbc-des3_ede-caam-qi2", -+ .cra_blocksize = DES3_EDE_BLOCK_SIZE, -+ }, -+ .setkey = aead_setkey, -+ .setauthsize = aead_setauthsize, -+ .encrypt = aead_encrypt, -+ .decrypt = aead_decrypt, -+ .ivsize = DES3_EDE_BLOCK_SIZE, -+ .maxauthsize = SHA512_DIGEST_SIZE, -+ }, -+ .caam = { -+ .class1_alg_type = OP_ALG_ALGSEL_3DES | OP_ALG_AAI_CBC, -+ .class2_alg_type = OP_ALG_ALGSEL_SHA512 | -+ OP_ALG_AAI_HMAC_PRECOMP, -+ .geniv = true, -+ } -+ }, -+ { -+ .aead = { -+ .base = { -+ .cra_name = "authenc(hmac(md5),cbc(des))", -+ .cra_driver_name = "authenc-hmac-md5-" -+ "cbc-des-caam-qi2", -+ .cra_blocksize = DES_BLOCK_SIZE, -+ }, -+ .setkey = aead_setkey, -+ .setauthsize = aead_setauthsize, -+ .encrypt = aead_encrypt, -+ .decrypt = aead_decrypt, -+ .ivsize = DES_BLOCK_SIZE, -+ .maxauthsize = MD5_DIGEST_SIZE, -+ }, -+ .caam = { -+ .class1_alg_type = OP_ALG_ALGSEL_DES | OP_ALG_AAI_CBC, -+ .class2_alg_type = OP_ALG_ALGSEL_MD5 | -+ OP_ALG_AAI_HMAC_PRECOMP, -+ }, -+ }, -+ { -+ .aead = { -+ .base = { -+ .cra_name = "echainiv(authenc(hmac(md5)," -+ "cbc(des)))", -+ .cra_driver_name = "echainiv-authenc-hmac-md5-" -+ "cbc-des-caam-qi2", -+ .cra_blocksize = DES_BLOCK_SIZE, -+ }, -+ .setkey = aead_setkey, -+ .setauthsize = aead_setauthsize, -+ .encrypt = aead_encrypt, -+ .decrypt = aead_decrypt, -+ .ivsize = DES_BLOCK_SIZE, -+ .maxauthsize = MD5_DIGEST_SIZE, -+ }, -+ .caam = { -+ .class1_alg_type = OP_ALG_ALGSEL_DES | OP_ALG_AAI_CBC, -+ .class2_alg_type = OP_ALG_ALGSEL_MD5 | -+ OP_ALG_AAI_HMAC_PRECOMP, -+ .geniv = true, -+ } -+ }, -+ { -+ .aead = { -+ .base = { -+ .cra_name = "authenc(hmac(sha1),cbc(des))", -+ .cra_driver_name = "authenc-hmac-sha1-" -+ "cbc-des-caam-qi2", -+ .cra_blocksize = DES_BLOCK_SIZE, -+ }, -+ .setkey = aead_setkey, -+ .setauthsize = aead_setauthsize, -+ .encrypt = aead_encrypt, -+ .decrypt = aead_decrypt, -+ .ivsize = DES_BLOCK_SIZE, -+ .maxauthsize = SHA1_DIGEST_SIZE, -+ }, -+ .caam = { -+ .class1_alg_type = OP_ALG_ALGSEL_DES | OP_ALG_AAI_CBC, -+ .class2_alg_type = OP_ALG_ALGSEL_SHA1 | -+ OP_ALG_AAI_HMAC_PRECOMP, -+ }, -+ }, -+ { -+ .aead = { -+ .base = { -+ .cra_name = "echainiv(authenc(hmac(sha1)," -+ "cbc(des)))", -+ .cra_driver_name = "echainiv-authenc-" -+ "hmac-sha1-cbc-des-caam-qi2", -+ .cra_blocksize = DES_BLOCK_SIZE, -+ }, -+ .setkey = aead_setkey, -+ .setauthsize = aead_setauthsize, -+ .encrypt = aead_encrypt, -+ .decrypt = aead_decrypt, -+ .ivsize = DES_BLOCK_SIZE, -+ .maxauthsize = SHA1_DIGEST_SIZE, -+ }, -+ .caam = { -+ .class1_alg_type = OP_ALG_ALGSEL_DES | OP_ALG_AAI_CBC, -+ .class2_alg_type = OP_ALG_ALGSEL_SHA1 | -+ OP_ALG_AAI_HMAC_PRECOMP, -+ .geniv = true, -+ } -+ }, -+ { -+ .aead = { -+ .base = { -+ .cra_name = "authenc(hmac(sha224),cbc(des))", -+ .cra_driver_name = "authenc-hmac-sha224-" -+ "cbc-des-caam-qi2", -+ .cra_blocksize = DES_BLOCK_SIZE, -+ }, -+ .setkey = aead_setkey, -+ .setauthsize = aead_setauthsize, -+ .encrypt = aead_encrypt, -+ .decrypt = aead_decrypt, -+ .ivsize = DES_BLOCK_SIZE, -+ .maxauthsize = SHA224_DIGEST_SIZE, -+ }, -+ .caam = { -+ .class1_alg_type = OP_ALG_ALGSEL_DES | OP_ALG_AAI_CBC, -+ .class2_alg_type = OP_ALG_ALGSEL_SHA224 | -+ OP_ALG_AAI_HMAC_PRECOMP, -+ }, -+ }, -+ { -+ .aead = { -+ .base = { -+ .cra_name = "echainiv(authenc(hmac(sha224)," -+ "cbc(des)))", -+ .cra_driver_name = "echainiv-authenc-" -+ "hmac-sha224-cbc-des-" -+ "caam-qi2", -+ .cra_blocksize = DES_BLOCK_SIZE, -+ }, -+ .setkey = aead_setkey, -+ .setauthsize = aead_setauthsize, -+ .encrypt = aead_encrypt, -+ .decrypt = aead_decrypt, -+ .ivsize = DES_BLOCK_SIZE, -+ .maxauthsize = SHA224_DIGEST_SIZE, -+ }, -+ .caam = { -+ .class1_alg_type = OP_ALG_ALGSEL_DES | OP_ALG_AAI_CBC, -+ .class2_alg_type = OP_ALG_ALGSEL_SHA224 | -+ OP_ALG_AAI_HMAC_PRECOMP, -+ .geniv = true, -+ } -+ }, -+ { -+ .aead = { -+ .base = { -+ .cra_name = "authenc(hmac(sha256),cbc(des))", -+ .cra_driver_name = "authenc-hmac-sha256-" -+ "cbc-des-caam-qi2", -+ .cra_blocksize = DES_BLOCK_SIZE, -+ }, -+ .setkey = aead_setkey, -+ .setauthsize = aead_setauthsize, -+ .encrypt = aead_encrypt, -+ .decrypt = aead_decrypt, -+ .ivsize = DES_BLOCK_SIZE, -+ .maxauthsize = SHA256_DIGEST_SIZE, -+ }, -+ .caam = { -+ .class1_alg_type = OP_ALG_ALGSEL_DES | OP_ALG_AAI_CBC, -+ .class2_alg_type = OP_ALG_ALGSEL_SHA256 | -+ OP_ALG_AAI_HMAC_PRECOMP, -+ }, -+ }, -+ { -+ .aead = { -+ .base = { -+ .cra_name = "echainiv(authenc(hmac(sha256)," -+ "cbc(des)))", -+ .cra_driver_name = "echainiv-authenc-" -+ "hmac-sha256-cbc-desi-" -+ "caam-qi2", -+ .cra_blocksize = DES_BLOCK_SIZE, -+ }, -+ .setkey = aead_setkey, -+ .setauthsize = aead_setauthsize, -+ .encrypt = aead_encrypt, -+ .decrypt = aead_decrypt, -+ .ivsize = DES_BLOCK_SIZE, -+ .maxauthsize = SHA256_DIGEST_SIZE, -+ }, -+ .caam = { -+ .class1_alg_type = OP_ALG_ALGSEL_DES | OP_ALG_AAI_CBC, -+ .class2_alg_type = OP_ALG_ALGSEL_SHA256 | -+ OP_ALG_AAI_HMAC_PRECOMP, -+ .geniv = true, -+ }, -+ }, -+ { -+ .aead = { -+ .base = { -+ .cra_name = "authenc(hmac(sha384),cbc(des))", -+ .cra_driver_name = "authenc-hmac-sha384-" -+ "cbc-des-caam-qi2", -+ .cra_blocksize = DES_BLOCK_SIZE, -+ }, -+ .setkey = aead_setkey, -+ .setauthsize = aead_setauthsize, -+ .encrypt = aead_encrypt, -+ .decrypt = aead_decrypt, -+ .ivsize = DES_BLOCK_SIZE, -+ .maxauthsize = SHA384_DIGEST_SIZE, -+ }, -+ .caam = { -+ .class1_alg_type = OP_ALG_ALGSEL_DES | OP_ALG_AAI_CBC, -+ .class2_alg_type = OP_ALG_ALGSEL_SHA384 | -+ OP_ALG_AAI_HMAC_PRECOMP, -+ }, -+ }, -+ { -+ .aead = { -+ .base = { -+ .cra_name = "echainiv(authenc(hmac(sha384)," -+ "cbc(des)))", -+ .cra_driver_name = "echainiv-authenc-" -+ "hmac-sha384-cbc-des-" -+ "caam-qi2", -+ .cra_blocksize = DES_BLOCK_SIZE, -+ }, -+ .setkey = aead_setkey, -+ .setauthsize = aead_setauthsize, -+ .encrypt = aead_encrypt, -+ .decrypt = aead_decrypt, -+ .ivsize = DES_BLOCK_SIZE, -+ .maxauthsize = SHA384_DIGEST_SIZE, -+ }, -+ .caam = { -+ .class1_alg_type = OP_ALG_ALGSEL_DES | OP_ALG_AAI_CBC, -+ .class2_alg_type = OP_ALG_ALGSEL_SHA384 | -+ OP_ALG_AAI_HMAC_PRECOMP, -+ .geniv = true, -+ } -+ }, -+ { -+ .aead = { -+ .base = { -+ .cra_name = "authenc(hmac(sha512),cbc(des))", -+ .cra_driver_name = "authenc-hmac-sha512-" -+ "cbc-des-caam-qi2", -+ .cra_blocksize = DES_BLOCK_SIZE, -+ }, -+ .setkey = aead_setkey, -+ .setauthsize = aead_setauthsize, -+ .encrypt = aead_encrypt, -+ .decrypt = aead_decrypt, -+ .ivsize = DES_BLOCK_SIZE, -+ .maxauthsize = SHA512_DIGEST_SIZE, -+ }, -+ .caam = { -+ .class1_alg_type = OP_ALG_ALGSEL_DES | OP_ALG_AAI_CBC, -+ .class2_alg_type = OP_ALG_ALGSEL_SHA512 | -+ OP_ALG_AAI_HMAC_PRECOMP, -+ } -+ }, -+ { -+ .aead = { -+ .base = { -+ .cra_name = "echainiv(authenc(hmac(sha512)," -+ "cbc(des)))", -+ .cra_driver_name = "echainiv-authenc-" -+ "hmac-sha512-cbc-des-" -+ "caam-qi2", -+ .cra_blocksize = DES_BLOCK_SIZE, -+ }, -+ .setkey = aead_setkey, -+ .setauthsize = aead_setauthsize, -+ .encrypt = aead_encrypt, -+ .decrypt = aead_decrypt, -+ .ivsize = DES_BLOCK_SIZE, -+ .maxauthsize = SHA512_DIGEST_SIZE, -+ }, -+ .caam = { -+ .class1_alg_type = OP_ALG_ALGSEL_DES | OP_ALG_AAI_CBC, -+ .class2_alg_type = OP_ALG_ALGSEL_SHA512 | -+ OP_ALG_AAI_HMAC_PRECOMP, -+ .geniv = true, -+ } -+ }, -+ { -+ .aead = { -+ .base = { -+ .cra_name = "authenc(hmac(md5)," -+ "rfc3686(ctr(aes)))", -+ .cra_driver_name = "authenc-hmac-md5-" -+ "rfc3686-ctr-aes-caam-qi2", -+ .cra_blocksize = 1, -+ }, -+ .setkey = aead_setkey, -+ .setauthsize = aead_setauthsize, -+ .encrypt = aead_encrypt, -+ .decrypt = aead_decrypt, -+ .ivsize = CTR_RFC3686_IV_SIZE, -+ .maxauthsize = MD5_DIGEST_SIZE, -+ }, -+ .caam = { -+ .class1_alg_type = OP_ALG_ALGSEL_AES | -+ OP_ALG_AAI_CTR_MOD128, -+ .class2_alg_type = OP_ALG_ALGSEL_MD5 | -+ OP_ALG_AAI_HMAC_PRECOMP, -+ .rfc3686 = true, -+ }, -+ }, -+ { -+ .aead = { -+ .base = { -+ .cra_name = "seqiv(authenc(" -+ "hmac(md5),rfc3686(ctr(aes))))", -+ .cra_driver_name = "seqiv-authenc-hmac-md5-" -+ "rfc3686-ctr-aes-caam-qi2", -+ .cra_blocksize = 1, -+ }, -+ .setkey = aead_setkey, -+ .setauthsize = aead_setauthsize, -+ .encrypt = aead_encrypt, -+ .decrypt = aead_decrypt, -+ .ivsize = CTR_RFC3686_IV_SIZE, -+ .maxauthsize = MD5_DIGEST_SIZE, -+ }, -+ .caam = { -+ .class1_alg_type = OP_ALG_ALGSEL_AES | -+ OP_ALG_AAI_CTR_MOD128, -+ .class2_alg_type = OP_ALG_ALGSEL_MD5 | -+ OP_ALG_AAI_HMAC_PRECOMP, -+ .rfc3686 = true, -+ .geniv = true, -+ }, -+ }, -+ { -+ .aead = { -+ .base = { -+ .cra_name = "authenc(hmac(sha1)," -+ "rfc3686(ctr(aes)))", -+ .cra_driver_name = "authenc-hmac-sha1-" -+ "rfc3686-ctr-aes-caam-qi2", -+ .cra_blocksize = 1, -+ }, -+ .setkey = aead_setkey, -+ .setauthsize = aead_setauthsize, -+ .encrypt = aead_encrypt, -+ .decrypt = aead_decrypt, -+ .ivsize = CTR_RFC3686_IV_SIZE, -+ .maxauthsize = SHA1_DIGEST_SIZE, -+ }, -+ .caam = { -+ .class1_alg_type = OP_ALG_ALGSEL_AES | -+ OP_ALG_AAI_CTR_MOD128, -+ .class2_alg_type = OP_ALG_ALGSEL_SHA1 | -+ OP_ALG_AAI_HMAC_PRECOMP, -+ .rfc3686 = true, -+ }, -+ }, -+ { -+ .aead = { -+ .base = { -+ .cra_name = "seqiv(authenc(" -+ "hmac(sha1),rfc3686(ctr(aes))))", -+ .cra_driver_name = "seqiv-authenc-hmac-sha1-" -+ "rfc3686-ctr-aes-caam-qi2", -+ .cra_blocksize = 1, -+ }, -+ .setkey = aead_setkey, -+ .setauthsize = aead_setauthsize, -+ .encrypt = aead_encrypt, -+ .decrypt = aead_decrypt, -+ .ivsize = CTR_RFC3686_IV_SIZE, -+ .maxauthsize = SHA1_DIGEST_SIZE, -+ }, -+ .caam = { -+ .class1_alg_type = OP_ALG_ALGSEL_AES | -+ OP_ALG_AAI_CTR_MOD128, -+ .class2_alg_type = OP_ALG_ALGSEL_SHA1 | -+ OP_ALG_AAI_HMAC_PRECOMP, -+ .rfc3686 = true, -+ .geniv = true, -+ }, -+ }, -+ { -+ .aead = { -+ .base = { -+ .cra_name = "authenc(hmac(sha224)," -+ "rfc3686(ctr(aes)))", -+ .cra_driver_name = "authenc-hmac-sha224-" -+ "rfc3686-ctr-aes-caam-qi2", -+ .cra_blocksize = 1, -+ }, -+ .setkey = aead_setkey, -+ .setauthsize = aead_setauthsize, -+ .encrypt = aead_encrypt, -+ .decrypt = aead_decrypt, -+ .ivsize = CTR_RFC3686_IV_SIZE, -+ .maxauthsize = SHA224_DIGEST_SIZE, -+ }, -+ .caam = { -+ .class1_alg_type = OP_ALG_ALGSEL_AES | -+ OP_ALG_AAI_CTR_MOD128, -+ .class2_alg_type = OP_ALG_ALGSEL_SHA224 | -+ OP_ALG_AAI_HMAC_PRECOMP, -+ .rfc3686 = true, -+ }, -+ }, -+ { -+ .aead = { -+ .base = { -+ .cra_name = "seqiv(authenc(" -+ "hmac(sha224),rfc3686(ctr(aes))))", -+ .cra_driver_name = "seqiv-authenc-hmac-sha224-" -+ "rfc3686-ctr-aes-caam-qi2", -+ .cra_blocksize = 1, -+ }, -+ .setkey = aead_setkey, -+ .setauthsize = aead_setauthsize, -+ .encrypt = aead_encrypt, -+ .decrypt = aead_decrypt, -+ .ivsize = CTR_RFC3686_IV_SIZE, -+ .maxauthsize = SHA224_DIGEST_SIZE, -+ }, -+ .caam = { -+ .class1_alg_type = OP_ALG_ALGSEL_AES | -+ OP_ALG_AAI_CTR_MOD128, -+ .class2_alg_type = OP_ALG_ALGSEL_SHA224 | -+ OP_ALG_AAI_HMAC_PRECOMP, -+ .rfc3686 = true, -+ .geniv = true, -+ }, -+ }, -+ { -+ .aead = { -+ .base = { -+ .cra_name = "authenc(hmac(sha256)," -+ "rfc3686(ctr(aes)))", -+ .cra_driver_name = "authenc-hmac-sha256-" -+ "rfc3686-ctr-aes-caam-qi2", -+ .cra_blocksize = 1, -+ }, -+ .setkey = aead_setkey, -+ .setauthsize = aead_setauthsize, -+ .encrypt = aead_encrypt, -+ .decrypt = aead_decrypt, -+ .ivsize = CTR_RFC3686_IV_SIZE, -+ .maxauthsize = SHA256_DIGEST_SIZE, -+ }, -+ .caam = { -+ .class1_alg_type = OP_ALG_ALGSEL_AES | -+ OP_ALG_AAI_CTR_MOD128, -+ .class2_alg_type = OP_ALG_ALGSEL_SHA256 | -+ OP_ALG_AAI_HMAC_PRECOMP, -+ .rfc3686 = true, -+ }, -+ }, -+ { -+ .aead = { -+ .base = { -+ .cra_name = "seqiv(authenc(hmac(sha256)," -+ "rfc3686(ctr(aes))))", -+ .cra_driver_name = "seqiv-authenc-hmac-sha256-" -+ "rfc3686-ctr-aes-caam-qi2", -+ .cra_blocksize = 1, -+ }, -+ .setkey = aead_setkey, -+ .setauthsize = aead_setauthsize, -+ .encrypt = aead_encrypt, -+ .decrypt = aead_decrypt, -+ .ivsize = CTR_RFC3686_IV_SIZE, -+ .maxauthsize = SHA256_DIGEST_SIZE, -+ }, -+ .caam = { -+ .class1_alg_type = OP_ALG_ALGSEL_AES | -+ OP_ALG_AAI_CTR_MOD128, -+ .class2_alg_type = OP_ALG_ALGSEL_SHA256 | -+ OP_ALG_AAI_HMAC_PRECOMP, -+ .rfc3686 = true, -+ .geniv = true, -+ }, -+ }, -+ { -+ .aead = { -+ .base = { -+ .cra_name = "authenc(hmac(sha384)," -+ "rfc3686(ctr(aes)))", -+ .cra_driver_name = "authenc-hmac-sha384-" -+ "rfc3686-ctr-aes-caam-qi2", -+ .cra_blocksize = 1, -+ }, -+ .setkey = aead_setkey, -+ .setauthsize = aead_setauthsize, -+ .encrypt = aead_encrypt, -+ .decrypt = aead_decrypt, -+ .ivsize = CTR_RFC3686_IV_SIZE, -+ .maxauthsize = SHA384_DIGEST_SIZE, -+ }, -+ .caam = { -+ .class1_alg_type = OP_ALG_ALGSEL_AES | -+ OP_ALG_AAI_CTR_MOD128, -+ .class2_alg_type = OP_ALG_ALGSEL_SHA384 | -+ OP_ALG_AAI_HMAC_PRECOMP, -+ .rfc3686 = true, -+ }, -+ }, -+ { -+ .aead = { -+ .base = { -+ .cra_name = "seqiv(authenc(hmac(sha384)," -+ "rfc3686(ctr(aes))))", -+ .cra_driver_name = "seqiv-authenc-hmac-sha384-" -+ "rfc3686-ctr-aes-caam-qi2", -+ .cra_blocksize = 1, -+ }, -+ .setkey = aead_setkey, -+ .setauthsize = aead_setauthsize, -+ .encrypt = aead_encrypt, -+ .decrypt = aead_decrypt, -+ .ivsize = CTR_RFC3686_IV_SIZE, -+ .maxauthsize = SHA384_DIGEST_SIZE, -+ }, -+ .caam = { -+ .class1_alg_type = OP_ALG_ALGSEL_AES | -+ OP_ALG_AAI_CTR_MOD128, -+ .class2_alg_type = OP_ALG_ALGSEL_SHA384 | -+ OP_ALG_AAI_HMAC_PRECOMP, -+ .rfc3686 = true, -+ .geniv = true, -+ }, -+ }, -+ { -+ .aead = { -+ .base = { -+ .cra_name = "rfc7539(chacha20,poly1305)", -+ .cra_driver_name = "rfc7539-chacha20-poly1305-" -+ "caam-qi2", -+ .cra_blocksize = 1, -+ }, -+ .setkey = chachapoly_setkey, -+ .setauthsize = chachapoly_setauthsize, -+ .encrypt = aead_encrypt, -+ .decrypt = aead_decrypt, -+ .ivsize = CHACHAPOLY_IV_SIZE, -+ .maxauthsize = POLY1305_DIGEST_SIZE, -+ }, -+ .caam = { -+ .class1_alg_type = OP_ALG_ALGSEL_CHACHA20 | -+ OP_ALG_AAI_AEAD, -+ .class2_alg_type = OP_ALG_ALGSEL_POLY1305 | -+ OP_ALG_AAI_AEAD, -+ }, -+ }, -+ { -+ .aead = { -+ .base = { -+ .cra_name = "rfc7539esp(chacha20,poly1305)", -+ .cra_driver_name = "rfc7539esp-chacha20-" -+ "poly1305-caam-qi2", -+ .cra_blocksize = 1, -+ }, -+ .setkey = chachapoly_setkey, -+ .setauthsize = chachapoly_setauthsize, -+ .encrypt = aead_encrypt, -+ .decrypt = aead_decrypt, -+ .ivsize = 8, -+ .maxauthsize = POLY1305_DIGEST_SIZE, -+ }, -+ .caam = { -+ .class1_alg_type = OP_ALG_ALGSEL_CHACHA20 | -+ OP_ALG_AAI_AEAD, -+ .class2_alg_type = OP_ALG_ALGSEL_POLY1305 | -+ OP_ALG_AAI_AEAD, -+ }, -+ }, -+ { -+ .aead = { -+ .base = { -+ .cra_name = "authenc(hmac(sha512)," -+ "rfc3686(ctr(aes)))", -+ .cra_driver_name = "authenc-hmac-sha512-" -+ "rfc3686-ctr-aes-caam-qi2", -+ .cra_blocksize = 1, -+ }, -+ .setkey = aead_setkey, -+ .setauthsize = aead_setauthsize, -+ .encrypt = aead_encrypt, -+ .decrypt = aead_decrypt, -+ .ivsize = CTR_RFC3686_IV_SIZE, -+ .maxauthsize = SHA512_DIGEST_SIZE, -+ }, -+ .caam = { -+ .class1_alg_type = OP_ALG_ALGSEL_AES | -+ OP_ALG_AAI_CTR_MOD128, -+ .class2_alg_type = OP_ALG_ALGSEL_SHA512 | -+ OP_ALG_AAI_HMAC_PRECOMP, -+ .rfc3686 = true, -+ }, -+ }, -+ { -+ .aead = { -+ .base = { -+ .cra_name = "seqiv(authenc(hmac(sha512)," -+ "rfc3686(ctr(aes))))", -+ .cra_driver_name = "seqiv-authenc-hmac-sha512-" -+ "rfc3686-ctr-aes-caam-qi2", -+ .cra_blocksize = 1, -+ }, -+ .setkey = aead_setkey, -+ .setauthsize = aead_setauthsize, -+ .encrypt = aead_encrypt, -+ .decrypt = aead_decrypt, -+ .ivsize = CTR_RFC3686_IV_SIZE, -+ .maxauthsize = SHA512_DIGEST_SIZE, -+ }, -+ .caam = { -+ .class1_alg_type = OP_ALG_ALGSEL_AES | -+ OP_ALG_AAI_CTR_MOD128, -+ .class2_alg_type = OP_ALG_ALGSEL_SHA512 | -+ OP_ALG_AAI_HMAC_PRECOMP, -+ .rfc3686 = true, -+ .geniv = true, -+ }, -+ }, -+ { -+ .aead = { -+ .base = { -+ .cra_name = "tls10(hmac(sha1),cbc(aes))", -+ .cra_driver_name = "tls10-hmac-sha1-cbc-aes-caam-qi2", -+ .cra_blocksize = AES_BLOCK_SIZE, -+ }, -+ .setkey = tls_setkey, -+ .setauthsize = tls_setauthsize, -+ .encrypt = tls_encrypt, -+ .decrypt = tls_decrypt, -+ .ivsize = AES_BLOCK_SIZE, -+ .maxauthsize = SHA1_DIGEST_SIZE, -+ }, -+ .caam = { -+ .class1_alg_type = OP_ALG_ALGSEL_AES | OP_ALG_AAI_CBC, -+ .class2_alg_type = OP_ALG_ALGSEL_SHA1 | -+ OP_ALG_AAI_HMAC_PRECOMP, -+ }, -+ }, -+}; -+ -+static void caam_skcipher_alg_init(struct caam_skcipher_alg *t_alg) -+{ -+ struct skcipher_alg *alg = &t_alg->skcipher; -+ -+ alg->base.cra_module = THIS_MODULE; -+ alg->base.cra_priority = CAAM_CRA_PRIORITY; -+ alg->base.cra_ctxsize = sizeof(struct caam_ctx); -+ alg->base.cra_flags = CRYPTO_ALG_ASYNC | CRYPTO_ALG_KERN_DRIVER_ONLY; -+ -+ alg->init = caam_cra_init_skcipher; -+ alg->exit = caam_cra_exit; -+} -+ -+static void caam_aead_alg_init(struct caam_aead_alg *t_alg) -+{ -+ struct aead_alg *alg = &t_alg->aead; -+ -+ alg->base.cra_module = THIS_MODULE; -+ alg->base.cra_priority = CAAM_CRA_PRIORITY; -+ alg->base.cra_ctxsize = sizeof(struct caam_ctx); -+ alg->base.cra_flags = CRYPTO_ALG_ASYNC | CRYPTO_ALG_KERN_DRIVER_ONLY; -+ -+ alg->init = caam_cra_init_aead; -+ alg->exit = caam_cra_exit_aead; -+} -+ -+/* max hash key is max split key size */ -+#define CAAM_MAX_HASH_KEY_SIZE (SHA512_DIGEST_SIZE * 2) -+ -+#define CAAM_MAX_HASH_BLOCK_SIZE SHA512_BLOCK_SIZE -+#define CAAM_MAX_HASH_DIGEST_SIZE SHA512_DIGEST_SIZE -+ -+#define DESC_HASH_MAX_USED_BYTES (DESC_AHASH_FINAL_LEN + \ -+ CAAM_MAX_HASH_KEY_SIZE) -+#define DESC_HASH_MAX_USED_LEN (DESC_HASH_MAX_USED_BYTES / CAAM_CMD_SZ) -+ -+/* caam context sizes for hashes: running digest + 8 */ -+#define HASH_MSG_LEN 8 -+#define MAX_CTX_LEN (HASH_MSG_LEN + SHA512_DIGEST_SIZE) -+ -+enum hash_optype { -+ UPDATE = 0, -+ UPDATE_FIRST, -+ FINALIZE, -+ DIGEST, -+ HASH_NUM_OP -+}; -+ -+/** -+ * caam_hash_ctx - ahash per-session context -+ * @flc: Flow Contexts array -+ * @flc_dma: I/O virtual addresses of the Flow Contexts -+ * @key: virtual address of the authentication key -+ * @dev: dpseci device -+ * @ctx_len: size of Context Register -+ * @adata: hashing algorithm details -+ */ -+struct caam_hash_ctx { -+ struct caam_flc flc[HASH_NUM_OP]; -+ dma_addr_t flc_dma[HASH_NUM_OP]; -+ u8 key[CAAM_MAX_HASH_KEY_SIZE]; -+ struct device *dev; -+ int ctx_len; -+ struct alginfo adata; -+}; -+ -+/* ahash state */ -+struct caam_hash_state { -+ struct caam_request caam_req; -+ dma_addr_t buf_dma; -+ dma_addr_t ctx_dma; -+ u8 buf_0[CAAM_MAX_HASH_BLOCK_SIZE] ____cacheline_aligned; -+ int buflen_0; -+ u8 buf_1[CAAM_MAX_HASH_BLOCK_SIZE] ____cacheline_aligned; -+ int buflen_1; -+ u8 caam_ctx[MAX_CTX_LEN] ____cacheline_aligned; -+ int (*update)(struct ahash_request *req); -+ int (*final)(struct ahash_request *req); -+ int (*finup)(struct ahash_request *req); -+ int current_buf; -+}; -+ -+struct caam_export_state { -+ u8 buf[CAAM_MAX_HASH_BLOCK_SIZE]; -+ u8 caam_ctx[MAX_CTX_LEN]; -+ int buflen; -+ int (*update)(struct ahash_request *req); -+ int (*final)(struct ahash_request *req); -+ int (*finup)(struct ahash_request *req); -+}; -+ -+static inline void switch_buf(struct caam_hash_state *state) -+{ -+ state->current_buf ^= 1; -+} -+ -+static inline u8 *current_buf(struct caam_hash_state *state) -+{ -+ return state->current_buf ? state->buf_1 : state->buf_0; -+} -+ -+static inline u8 *alt_buf(struct caam_hash_state *state) -+{ -+ return state->current_buf ? state->buf_0 : state->buf_1; -+} -+ -+static inline int *current_buflen(struct caam_hash_state *state) -+{ -+ return state->current_buf ? &state->buflen_1 : &state->buflen_0; -+} -+ -+static inline int *alt_buflen(struct caam_hash_state *state) -+{ -+ return state->current_buf ? &state->buflen_0 : &state->buflen_1; -+} -+ -+/* Map current buffer in state (if length > 0) and put it in link table */ -+static inline int buf_map_to_qm_sg(struct device *dev, -+ struct dpaa2_sg_entry *qm_sg, -+ struct caam_hash_state *state) -+{ -+ int buflen = *current_buflen(state); -+ -+ if (!buflen) -+ return 0; -+ -+ state->buf_dma = dma_map_single(dev, current_buf(state), buflen, -+ DMA_TO_DEVICE); -+ if (dma_mapping_error(dev, state->buf_dma)) { -+ dev_err(dev, "unable to map buf\n"); -+ state->buf_dma = 0; -+ return -ENOMEM; -+ } -+ -+ dma_to_qm_sg_one(qm_sg, state->buf_dma, buflen, 0); -+ -+ return 0; -+} -+ -+/* Map state->caam_ctx, and add it to link table */ -+static inline int ctx_map_to_qm_sg(struct device *dev, -+ struct caam_hash_state *state, int ctx_len, -+ struct dpaa2_sg_entry *qm_sg, u32 flag) -+{ -+ state->ctx_dma = dma_map_single(dev, state->caam_ctx, ctx_len, flag); -+ if (dma_mapping_error(dev, state->ctx_dma)) { -+ dev_err(dev, "unable to map ctx\n"); -+ state->ctx_dma = 0; -+ return -ENOMEM; -+ } -+ -+ dma_to_qm_sg_one(qm_sg, state->ctx_dma, ctx_len, 0); -+ -+ return 0; -+} -+ -+static int ahash_set_sh_desc(struct crypto_ahash *ahash) -+{ -+ struct caam_hash_ctx *ctx = crypto_ahash_ctx(ahash); -+ int digestsize = crypto_ahash_digestsize(ahash); -+ struct dpaa2_caam_priv *priv = dev_get_drvdata(ctx->dev); -+ struct caam_flc *flc; -+ u32 *desc; -+ -+ ctx->adata.key_virt = ctx->key; -+ ctx->adata.key_inline = true; -+ -+ /* ahash_update shared descriptor */ -+ flc = &ctx->flc[UPDATE]; -+ desc = flc->sh_desc; -+ cnstr_shdsc_ahash(desc, &ctx->adata, OP_ALG_AS_UPDATE, ctx->ctx_len, -+ ctx->ctx_len, true, priv->sec_attr.era); -+ flc->flc[1] = cpu_to_caam32(desc_len(desc)); /* SDL */ -+ dma_sync_single_for_device(ctx->dev, ctx->flc_dma[UPDATE], -+ desc_bytes(desc), DMA_BIDIRECTIONAL); -+#ifdef DEBUG -+ print_hex_dump(KERN_ERR, -+ "ahash update shdesc@" __stringify(__LINE__)": ", -+ DUMP_PREFIX_ADDRESS, 16, 4, desc, desc_bytes(desc), 1); -+#endif -+ -+ /* ahash_update_first shared descriptor */ -+ flc = &ctx->flc[UPDATE_FIRST]; -+ desc = flc->sh_desc; -+ cnstr_shdsc_ahash(desc, &ctx->adata, OP_ALG_AS_INIT, ctx->ctx_len, -+ ctx->ctx_len, false, priv->sec_attr.era); -+ flc->flc[1] = cpu_to_caam32(desc_len(desc)); /* SDL */ -+ dma_sync_single_for_device(ctx->dev, ctx->flc_dma[UPDATE_FIRST], -+ desc_bytes(desc), DMA_BIDIRECTIONAL); -+#ifdef DEBUG -+ print_hex_dump(KERN_ERR, -+ "ahash update first shdesc@" __stringify(__LINE__)": ", -+ DUMP_PREFIX_ADDRESS, 16, 4, desc, desc_bytes(desc), 1); -+#endif -+ -+ /* ahash_final shared descriptor */ -+ flc = &ctx->flc[FINALIZE]; -+ desc = flc->sh_desc; -+ cnstr_shdsc_ahash(desc, &ctx->adata, OP_ALG_AS_FINALIZE, digestsize, -+ ctx->ctx_len, true, priv->sec_attr.era); -+ flc->flc[1] = cpu_to_caam32(desc_len(desc)); /* SDL */ -+ dma_sync_single_for_device(ctx->dev, ctx->flc_dma[FINALIZE], -+ desc_bytes(desc), DMA_BIDIRECTIONAL); -+#ifdef DEBUG -+ print_hex_dump(KERN_ERR, -+ "ahash final shdesc@" __stringify(__LINE__)": ", -+ DUMP_PREFIX_ADDRESS, 16, 4, desc, desc_bytes(desc), 1); -+#endif -+ -+ /* ahash_digest shared descriptor */ -+ flc = &ctx->flc[DIGEST]; -+ desc = flc->sh_desc; -+ cnstr_shdsc_ahash(desc, &ctx->adata, OP_ALG_AS_INITFINAL, digestsize, -+ ctx->ctx_len, false, priv->sec_attr.era); -+ flc->flc[1] = cpu_to_caam32(desc_len(desc)); /* SDL */ -+ dma_sync_single_for_device(ctx->dev, ctx->flc_dma[DIGEST], -+ desc_bytes(desc), DMA_BIDIRECTIONAL); -+#ifdef DEBUG -+ print_hex_dump(KERN_ERR, -+ "ahash digest shdesc@" __stringify(__LINE__)": ", -+ DUMP_PREFIX_ADDRESS, 16, 4, desc, desc_bytes(desc), 1); -+#endif -+ -+ return 0; -+} -+ -+/* Digest hash size if it is too large */ -+static int hash_digest_key(struct caam_hash_ctx *ctx, const u8 *key_in, -+ u32 *keylen, u8 *key_out, u32 digestsize) -+{ -+ struct caam_request *req_ctx; -+ u32 *desc; -+ struct split_key_sh_result result; -+ dma_addr_t src_dma, dst_dma; -+ struct caam_flc *flc; -+ dma_addr_t flc_dma; -+ int ret = -ENOMEM; -+ struct dpaa2_fl_entry *in_fle, *out_fle; -+ -+ req_ctx = kzalloc(sizeof(*req_ctx), GFP_KERNEL | GFP_DMA); -+ if (!req_ctx) -+ return -ENOMEM; -+ -+ in_fle = &req_ctx->fd_flt[1]; -+ out_fle = &req_ctx->fd_flt[0]; -+ -+ flc = kzalloc(sizeof(*flc), GFP_KERNEL | GFP_DMA); -+ if (!flc) -+ goto err_flc; -+ -+ src_dma = dma_map_single(ctx->dev, (void *)key_in, *keylen, -+ DMA_TO_DEVICE); -+ if (dma_mapping_error(ctx->dev, src_dma)) { -+ dev_err(ctx->dev, "unable to map key input memory\n"); -+ goto err_src_dma; -+ } -+ dst_dma = dma_map_single(ctx->dev, (void *)key_out, digestsize, -+ DMA_FROM_DEVICE); -+ if (dma_mapping_error(ctx->dev, dst_dma)) { -+ dev_err(ctx->dev, "unable to map key output memory\n"); -+ goto err_dst_dma; -+ } -+ -+ desc = flc->sh_desc; -+ -+ init_sh_desc(desc, 0); -+ -+ /* descriptor to perform unkeyed hash on key_in */ -+ append_operation(desc, ctx->adata.algtype | OP_ALG_ENCRYPT | -+ OP_ALG_AS_INITFINAL); -+ append_seq_fifo_load(desc, *keylen, FIFOLD_CLASS_CLASS2 | -+ FIFOLD_TYPE_LAST2 | FIFOLD_TYPE_MSG); -+ append_seq_store(desc, digestsize, LDST_CLASS_2_CCB | -+ LDST_SRCDST_BYTE_CONTEXT); -+ -+ flc->flc[1] = cpu_to_caam32(desc_len(desc)); /* SDL */ -+ flc_dma = dma_map_single(ctx->dev, flc, sizeof(flc->flc) + -+ desc_bytes(desc), DMA_TO_DEVICE); -+ if (dma_mapping_error(ctx->dev, flc_dma)) { -+ dev_err(ctx->dev, "unable to map shared descriptor\n"); -+ goto err_flc_dma; -+ } -+ -+ dpaa2_fl_set_final(in_fle, true); -+ dpaa2_fl_set_format(in_fle, dpaa2_fl_single); -+ dpaa2_fl_set_addr(in_fle, src_dma); -+ dpaa2_fl_set_len(in_fle, *keylen); -+ dpaa2_fl_set_format(out_fle, dpaa2_fl_single); -+ dpaa2_fl_set_addr(out_fle, dst_dma); -+ dpaa2_fl_set_len(out_fle, digestsize); -+ -+#ifdef DEBUG -+ print_hex_dump(KERN_ERR, "key_in@" __stringify(__LINE__)": ", -+ DUMP_PREFIX_ADDRESS, 16, 4, key_in, *keylen, 1); -+ print_hex_dump(KERN_ERR, "shdesc@" __stringify(__LINE__)": ", -+ DUMP_PREFIX_ADDRESS, 16, 4, desc, desc_bytes(desc), 1); -+#endif -+ -+ result.err = 0; -+ init_completion(&result.completion); -+ result.dev = ctx->dev; -+ -+ req_ctx->flc = flc; -+ req_ctx->flc_dma = flc_dma; -+ req_ctx->cbk = split_key_sh_done; -+ req_ctx->ctx = &result; -+ -+ ret = dpaa2_caam_enqueue(ctx->dev, req_ctx); -+ if (ret == -EINPROGRESS) { -+ /* in progress */ -+ wait_for_completion(&result.completion); -+ ret = result.err; -+#ifdef DEBUG -+ print_hex_dump(KERN_ERR, -+ "digested key@" __stringify(__LINE__)": ", -+ DUMP_PREFIX_ADDRESS, 16, 4, key_in, digestsize, -+ 1); -+#endif -+ } -+ -+ dma_unmap_single(ctx->dev, flc_dma, sizeof(flc->flc) + desc_bytes(desc), -+ DMA_TO_DEVICE); -+err_flc_dma: -+ dma_unmap_single(ctx->dev, dst_dma, digestsize, DMA_FROM_DEVICE); -+err_dst_dma: -+ dma_unmap_single(ctx->dev, src_dma, *keylen, DMA_TO_DEVICE); -+err_src_dma: -+ kfree(flc); -+err_flc: -+ kfree(req_ctx); -+ -+ *keylen = digestsize; -+ -+ return ret; -+} -+ -+static int ahash_setkey(struct crypto_ahash *ahash, const u8 *key, -+ unsigned int keylen) -+{ -+ struct caam_hash_ctx *ctx = crypto_ahash_ctx(ahash); -+ unsigned int blocksize = crypto_tfm_alg_blocksize(&ahash->base); -+ unsigned int digestsize = crypto_ahash_digestsize(ahash); -+ int ret; -+ u8 *hashed_key = NULL; -+ -+#ifdef DEBUG -+ dev_err(ctx->dev, "keylen %d blocksize %d\n", keylen, blocksize); -+#endif -+ -+ if (keylen > blocksize) { -+ hashed_key = kmalloc_array(digestsize, sizeof(*hashed_key), -+ GFP_KERNEL | GFP_DMA); -+ if (!hashed_key) -+ return -ENOMEM; -+ ret = hash_digest_key(ctx, key, &keylen, hashed_key, -+ digestsize); -+ if (ret) -+ goto bad_free_key; -+ key = hashed_key; -+ } -+ -+ ctx->adata.keylen = keylen; -+ ctx->adata.keylen_pad = split_key_len(ctx->adata.algtype & -+ OP_ALG_ALGSEL_MASK); -+ if (ctx->adata.keylen_pad > CAAM_MAX_HASH_KEY_SIZE) -+ goto bad_free_key; -+ -+ memcpy(ctx->key, key, keylen); -+ -+ kfree(hashed_key); -+ return ahash_set_sh_desc(ahash); -+bad_free_key: -+ kfree(hashed_key); -+ crypto_ahash_set_flags(ahash, CRYPTO_TFM_RES_BAD_KEY_LEN); -+ return -EINVAL; -+} -+ -+static inline void ahash_unmap(struct device *dev, struct ahash_edesc *edesc, -+ struct ahash_request *req, int dst_len) -+{ -+ struct caam_hash_state *state = ahash_request_ctx(req); -+ -+ if (edesc->src_nents) -+ dma_unmap_sg(dev, req->src, edesc->src_nents, DMA_TO_DEVICE); -+ if (edesc->dst_dma) -+ dma_unmap_single(dev, edesc->dst_dma, dst_len, DMA_FROM_DEVICE); -+ -+ if (edesc->qm_sg_bytes) -+ dma_unmap_single(dev, edesc->qm_sg_dma, edesc->qm_sg_bytes, -+ DMA_TO_DEVICE); -+ -+ if (state->buf_dma) { -+ dma_unmap_single(dev, state->buf_dma, *current_buflen(state), -+ DMA_TO_DEVICE); -+ state->buf_dma = 0; -+ } -+} -+ -+static inline void ahash_unmap_ctx(struct device *dev, -+ struct ahash_edesc *edesc, -+ struct ahash_request *req, int dst_len, -+ u32 flag) -+{ -+ struct crypto_ahash *ahash = crypto_ahash_reqtfm(req); -+ struct caam_hash_ctx *ctx = crypto_ahash_ctx(ahash); -+ struct caam_hash_state *state = ahash_request_ctx(req); -+ -+ if (state->ctx_dma) { -+ dma_unmap_single(dev, state->ctx_dma, ctx->ctx_len, flag); -+ state->ctx_dma = 0; -+ } -+ ahash_unmap(dev, edesc, req, dst_len); -+} -+ -+static void ahash_done(void *cbk_ctx, u32 status) -+{ -+ struct crypto_async_request *areq = cbk_ctx; -+ struct ahash_request *req = ahash_request_cast(areq); -+ struct crypto_ahash *ahash = crypto_ahash_reqtfm(req); -+ struct caam_hash_state *state = ahash_request_ctx(req); -+ struct ahash_edesc *edesc = state->caam_req.edesc; -+ struct caam_hash_ctx *ctx = crypto_ahash_ctx(ahash); -+ int digestsize = crypto_ahash_digestsize(ahash); -+ int ecode = 0; -+ -+#ifdef DEBUG -+ dev_err(ctx->dev, "%s %d: err 0x%x\n", __func__, __LINE__, status); -+#endif -+ -+ if (unlikely(status)) { -+ caam_qi2_strstatus(ctx->dev, status); -+ ecode = -EIO; -+ } -+ -+ ahash_unmap(ctx->dev, edesc, req, digestsize); -+ qi_cache_free(edesc); -+ -+#ifdef DEBUG -+ print_hex_dump(KERN_ERR, "ctx@" __stringify(__LINE__)": ", -+ DUMP_PREFIX_ADDRESS, 16, 4, state->caam_ctx, -+ ctx->ctx_len, 1); -+ if (req->result) -+ print_hex_dump(KERN_ERR, "result@" __stringify(__LINE__)": ", -+ DUMP_PREFIX_ADDRESS, 16, 4, req->result, -+ digestsize, 1); -+#endif -+ -+ req->base.complete(&req->base, ecode); -+} -+ -+static void ahash_done_bi(void *cbk_ctx, u32 status) -+{ -+ struct crypto_async_request *areq = cbk_ctx; -+ struct ahash_request *req = ahash_request_cast(areq); -+ struct crypto_ahash *ahash = crypto_ahash_reqtfm(req); -+ struct caam_hash_state *state = ahash_request_ctx(req); -+ struct ahash_edesc *edesc = state->caam_req.edesc; -+ struct caam_hash_ctx *ctx = crypto_ahash_ctx(ahash); -+ int ecode = 0; -+#ifdef DEBUG -+ int digestsize = crypto_ahash_digestsize(ahash); -+ -+ dev_err(ctx->dev, "%s %d: err 0x%x\n", __func__, __LINE__, status); -+#endif -+ -+ if (unlikely(status)) { -+ caam_qi2_strstatus(ctx->dev, status); -+ ecode = -EIO; -+ } -+ -+ ahash_unmap_ctx(ctx->dev, edesc, req, ctx->ctx_len, DMA_BIDIRECTIONAL); -+ switch_buf(state); -+ qi_cache_free(edesc); -+ -+#ifdef DEBUG -+ print_hex_dump(KERN_ERR, "ctx@" __stringify(__LINE__)": ", -+ DUMP_PREFIX_ADDRESS, 16, 4, state->caam_ctx, -+ ctx->ctx_len, 1); -+ if (req->result) -+ print_hex_dump(KERN_ERR, "result@" __stringify(__LINE__)": ", -+ DUMP_PREFIX_ADDRESS, 16, 4, req->result, -+ digestsize, 1); -+#endif -+ -+ req->base.complete(&req->base, ecode); -+} -+ -+static void ahash_done_ctx_src(void *cbk_ctx, u32 status) -+{ -+ struct crypto_async_request *areq = cbk_ctx; -+ struct ahash_request *req = ahash_request_cast(areq); -+ struct crypto_ahash *ahash = crypto_ahash_reqtfm(req); -+ struct caam_hash_state *state = ahash_request_ctx(req); -+ struct ahash_edesc *edesc = state->caam_req.edesc; -+ struct caam_hash_ctx *ctx = crypto_ahash_ctx(ahash); -+ int digestsize = crypto_ahash_digestsize(ahash); -+ int ecode = 0; -+ -+#ifdef DEBUG -+ dev_err(ctx->dev, "%s %d: err 0x%x\n", __func__, __LINE__, status); -+#endif -+ -+ if (unlikely(status)) { -+ caam_qi2_strstatus(ctx->dev, status); -+ ecode = -EIO; -+ } -+ -+ ahash_unmap_ctx(ctx->dev, edesc, req, digestsize, DMA_TO_DEVICE); -+ qi_cache_free(edesc); -+ -+#ifdef DEBUG -+ print_hex_dump(KERN_ERR, "ctx@" __stringify(__LINE__)": ", -+ DUMP_PREFIX_ADDRESS, 16, 4, state->caam_ctx, -+ ctx->ctx_len, 1); -+ if (req->result) -+ print_hex_dump(KERN_ERR, "result@" __stringify(__LINE__)": ", -+ DUMP_PREFIX_ADDRESS, 16, 4, req->result, -+ digestsize, 1); -+#endif -+ -+ req->base.complete(&req->base, ecode); -+} -+ -+static void ahash_done_ctx_dst(void *cbk_ctx, u32 status) -+{ -+ struct crypto_async_request *areq = cbk_ctx; -+ struct ahash_request *req = ahash_request_cast(areq); -+ struct crypto_ahash *ahash = crypto_ahash_reqtfm(req); -+ struct caam_hash_state *state = ahash_request_ctx(req); -+ struct ahash_edesc *edesc = state->caam_req.edesc; -+ struct caam_hash_ctx *ctx = crypto_ahash_ctx(ahash); -+ int ecode = 0; -+#ifdef DEBUG -+ int digestsize = crypto_ahash_digestsize(ahash); -+ -+ dev_err(ctx->dev, "%s %d: err 0x%x\n", __func__, __LINE__, status); -+#endif -+ -+ if (unlikely(status)) { -+ caam_qi2_strstatus(ctx->dev, status); -+ ecode = -EIO; -+ } -+ -+ ahash_unmap_ctx(ctx->dev, edesc, req, ctx->ctx_len, DMA_FROM_DEVICE); -+ switch_buf(state); -+ qi_cache_free(edesc); -+ -+#ifdef DEBUG -+ print_hex_dump(KERN_ERR, "ctx@" __stringify(__LINE__)": ", -+ DUMP_PREFIX_ADDRESS, 16, 4, state->caam_ctx, -+ ctx->ctx_len, 1); -+ if (req->result) -+ print_hex_dump(KERN_ERR, "result@" __stringify(__LINE__)": ", -+ DUMP_PREFIX_ADDRESS, 16, 4, req->result, -+ digestsize, 1); -+#endif -+ -+ req->base.complete(&req->base, ecode); -+} -+ -+static int ahash_update_ctx(struct ahash_request *req) -+{ -+ struct crypto_ahash *ahash = crypto_ahash_reqtfm(req); -+ struct caam_hash_ctx *ctx = crypto_ahash_ctx(ahash); -+ struct caam_hash_state *state = ahash_request_ctx(req); -+ struct caam_request *req_ctx = &state->caam_req; -+ struct dpaa2_fl_entry *in_fle = &req_ctx->fd_flt[1]; -+ struct dpaa2_fl_entry *out_fle = &req_ctx->fd_flt[0]; -+ gfp_t flags = (req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP) ? -+ GFP_KERNEL : GFP_ATOMIC; -+ u8 *buf = current_buf(state); -+ int *buflen = current_buflen(state); -+ u8 *next_buf = alt_buf(state); -+ int *next_buflen = alt_buflen(state), last_buflen; -+ int in_len = *buflen + req->nbytes, to_hash; -+ int src_nents, mapped_nents, qm_sg_bytes, qm_sg_src_index; -+ struct ahash_edesc *edesc; -+ int ret = 0; -+ -+ last_buflen = *next_buflen; -+ *next_buflen = in_len & (crypto_tfm_alg_blocksize(&ahash->base) - 1); -+ to_hash = in_len - *next_buflen; -+ -+ if (to_hash) { -+ struct dpaa2_sg_entry *sg_table; -+ -+ src_nents = sg_nents_for_len(req->src, -+ req->nbytes - (*next_buflen)); -+ if (src_nents < 0) { -+ dev_err(ctx->dev, "Invalid number of src SG.\n"); -+ return src_nents; -+ } -+ -+ if (src_nents) { -+ mapped_nents = dma_map_sg(ctx->dev, req->src, src_nents, -+ DMA_TO_DEVICE); -+ if (!mapped_nents) { -+ dev_err(ctx->dev, "unable to DMA map source\n"); -+ return -ENOMEM; -+ } -+ } else { -+ mapped_nents = 0; -+ } -+ -+ /* allocate space for base edesc and link tables */ -+ edesc = qi_cache_zalloc(GFP_DMA | flags); -+ if (!edesc) { -+ dma_unmap_sg(ctx->dev, req->src, src_nents, -+ DMA_TO_DEVICE); -+ return -ENOMEM; -+ } -+ -+ edesc->src_nents = src_nents; -+ qm_sg_src_index = 1 + (*buflen ? 1 : 0); -+ qm_sg_bytes = (qm_sg_src_index + mapped_nents) * -+ sizeof(*sg_table); -+ sg_table = &edesc->sgt[0]; -+ -+ ret = ctx_map_to_qm_sg(ctx->dev, state, ctx->ctx_len, sg_table, -+ DMA_BIDIRECTIONAL); -+ if (ret) -+ goto unmap_ctx; -+ -+ ret = buf_map_to_qm_sg(ctx->dev, sg_table + 1, state); -+ if (ret) -+ goto unmap_ctx; -+ -+ if (mapped_nents) { -+ sg_to_qm_sg_last(req->src, mapped_nents, -+ sg_table + qm_sg_src_index, 0); -+ if (*next_buflen) -+ scatterwalk_map_and_copy(next_buf, req->src, -+ to_hash - *buflen, -+ *next_buflen, 0); -+ } else { -+ dpaa2_sg_set_final(sg_table + qm_sg_src_index - 1, -+ true); -+ } -+ -+ edesc->qm_sg_dma = dma_map_single(ctx->dev, sg_table, -+ qm_sg_bytes, DMA_TO_DEVICE); -+ if (dma_mapping_error(ctx->dev, edesc->qm_sg_dma)) { -+ dev_err(ctx->dev, "unable to map S/G table\n"); -+ ret = -ENOMEM; -+ goto unmap_ctx; -+ } -+ edesc->qm_sg_bytes = qm_sg_bytes; -+ -+ memset(&req_ctx->fd_flt, 0, sizeof(req_ctx->fd_flt)); -+ dpaa2_fl_set_final(in_fle, true); -+ dpaa2_fl_set_format(in_fle, dpaa2_fl_sg); -+ dpaa2_fl_set_addr(in_fle, edesc->qm_sg_dma); -+ dpaa2_fl_set_len(in_fle, ctx->ctx_len + to_hash); -+ dpaa2_fl_set_format(out_fle, dpaa2_fl_single); -+ dpaa2_fl_set_addr(out_fle, state->ctx_dma); -+ dpaa2_fl_set_len(out_fle, ctx->ctx_len); -+ -+ req_ctx->flc = &ctx->flc[UPDATE]; -+ req_ctx->flc_dma = ctx->flc_dma[UPDATE]; -+ req_ctx->cbk = ahash_done_bi; -+ req_ctx->ctx = &req->base; -+ req_ctx->edesc = edesc; -+ -+ ret = dpaa2_caam_enqueue(ctx->dev, req_ctx); -+ if (ret != -EINPROGRESS && -+ !(ret == -EBUSY && -+ req->base.flags & CRYPTO_TFM_REQ_MAY_BACKLOG)) -+ goto unmap_ctx; -+ } else if (*next_buflen) { -+ scatterwalk_map_and_copy(buf + *buflen, req->src, 0, -+ req->nbytes, 0); -+ *buflen = *next_buflen; -+ *next_buflen = last_buflen; -+ } -+#ifdef DEBUG -+ print_hex_dump(KERN_ERR, "buf@" __stringify(__LINE__)": ", -+ DUMP_PREFIX_ADDRESS, 16, 4, buf, *buflen, 1); -+ print_hex_dump(KERN_ERR, "next buf@" __stringify(__LINE__)": ", -+ DUMP_PREFIX_ADDRESS, 16, 4, next_buf, -+ *next_buflen, 1); -+#endif -+ -+ return ret; -+unmap_ctx: -+ ahash_unmap_ctx(ctx->dev, edesc, req, ctx->ctx_len, DMA_BIDIRECTIONAL); -+ qi_cache_free(edesc); -+ return ret; -+} -+ -+static int ahash_final_ctx(struct ahash_request *req) -+{ -+ struct crypto_ahash *ahash = crypto_ahash_reqtfm(req); -+ struct caam_hash_ctx *ctx = crypto_ahash_ctx(ahash); -+ struct caam_hash_state *state = ahash_request_ctx(req); -+ struct caam_request *req_ctx = &state->caam_req; -+ struct dpaa2_fl_entry *in_fle = &req_ctx->fd_flt[1]; -+ struct dpaa2_fl_entry *out_fle = &req_ctx->fd_flt[0]; -+ gfp_t flags = (req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP) ? -+ GFP_KERNEL : GFP_ATOMIC; -+ int buflen = *current_buflen(state); -+ int qm_sg_bytes, qm_sg_src_index; -+ int digestsize = crypto_ahash_digestsize(ahash); -+ struct ahash_edesc *edesc; -+ struct dpaa2_sg_entry *sg_table; -+ int ret; -+ -+ /* allocate space for base edesc and link tables */ -+ edesc = qi_cache_zalloc(GFP_DMA | flags); -+ if (!edesc) -+ return -ENOMEM; -+ -+ qm_sg_src_index = 1 + (buflen ? 1 : 0); -+ qm_sg_bytes = qm_sg_src_index * sizeof(*sg_table); -+ sg_table = &edesc->sgt[0]; -+ -+ ret = ctx_map_to_qm_sg(ctx->dev, state, ctx->ctx_len, sg_table, -+ DMA_TO_DEVICE); -+ if (ret) -+ goto unmap_ctx; -+ -+ ret = buf_map_to_qm_sg(ctx->dev, sg_table + 1, state); -+ if (ret) -+ goto unmap_ctx; -+ -+ dpaa2_sg_set_final(sg_table + qm_sg_src_index - 1, true); -+ -+ edesc->qm_sg_dma = dma_map_single(ctx->dev, sg_table, qm_sg_bytes, -+ DMA_TO_DEVICE); -+ if (dma_mapping_error(ctx->dev, edesc->qm_sg_dma)) { -+ dev_err(ctx->dev, "unable to map S/G table\n"); -+ ret = -ENOMEM; -+ goto unmap_ctx; -+ } -+ edesc->qm_sg_bytes = qm_sg_bytes; -+ -+ edesc->dst_dma = dma_map_single(ctx->dev, req->result, digestsize, -+ DMA_FROM_DEVICE); -+ if (dma_mapping_error(ctx->dev, edesc->dst_dma)) { -+ dev_err(ctx->dev, "unable to map dst\n"); -+ edesc->dst_dma = 0; -+ ret = -ENOMEM; -+ goto unmap_ctx; -+ } -+ -+ memset(&req_ctx->fd_flt, 0, sizeof(req_ctx->fd_flt)); -+ dpaa2_fl_set_final(in_fle, true); -+ dpaa2_fl_set_format(in_fle, dpaa2_fl_sg); -+ dpaa2_fl_set_addr(in_fle, edesc->qm_sg_dma); -+ dpaa2_fl_set_len(in_fle, ctx->ctx_len + buflen); -+ dpaa2_fl_set_format(out_fle, dpaa2_fl_single); -+ dpaa2_fl_set_addr(out_fle, edesc->dst_dma); -+ dpaa2_fl_set_len(out_fle, digestsize); -+ -+ req_ctx->flc = &ctx->flc[FINALIZE]; -+ req_ctx->flc_dma = ctx->flc_dma[FINALIZE]; -+ req_ctx->cbk = ahash_done_ctx_src; -+ req_ctx->ctx = &req->base; -+ req_ctx->edesc = edesc; -+ -+ ret = dpaa2_caam_enqueue(ctx->dev, req_ctx); -+ if (ret == -EINPROGRESS || -+ (ret == -EBUSY && req->base.flags & CRYPTO_TFM_REQ_MAY_BACKLOG)) -+ return ret; -+ -+unmap_ctx: -+ ahash_unmap_ctx(ctx->dev, edesc, req, digestsize, DMA_FROM_DEVICE); -+ qi_cache_free(edesc); -+ return ret; -+} -+ -+static int ahash_finup_ctx(struct ahash_request *req) -+{ -+ struct crypto_ahash *ahash = crypto_ahash_reqtfm(req); -+ struct caam_hash_ctx *ctx = crypto_ahash_ctx(ahash); -+ struct caam_hash_state *state = ahash_request_ctx(req); -+ struct caam_request *req_ctx = &state->caam_req; -+ struct dpaa2_fl_entry *in_fle = &req_ctx->fd_flt[1]; -+ struct dpaa2_fl_entry *out_fle = &req_ctx->fd_flt[0]; -+ gfp_t flags = (req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP) ? -+ GFP_KERNEL : GFP_ATOMIC; -+ int buflen = *current_buflen(state); -+ int qm_sg_bytes, qm_sg_src_index; -+ int src_nents, mapped_nents; -+ int digestsize = crypto_ahash_digestsize(ahash); -+ struct ahash_edesc *edesc; -+ struct dpaa2_sg_entry *sg_table; -+ int ret; -+ -+ src_nents = sg_nents_for_len(req->src, req->nbytes); -+ if (src_nents < 0) { -+ dev_err(ctx->dev, "Invalid number of src SG.\n"); -+ return src_nents; -+ } -+ -+ if (src_nents) { -+ mapped_nents = dma_map_sg(ctx->dev, req->src, src_nents, -+ DMA_TO_DEVICE); -+ if (!mapped_nents) { -+ dev_err(ctx->dev, "unable to DMA map source\n"); -+ return -ENOMEM; -+ } -+ } else { -+ mapped_nents = 0; -+ } -+ -+ /* allocate space for base edesc and link tables */ -+ edesc = qi_cache_zalloc(GFP_DMA | flags); -+ if (!edesc) { -+ dma_unmap_sg(ctx->dev, req->src, src_nents, DMA_TO_DEVICE); -+ return -ENOMEM; -+ } -+ -+ edesc->src_nents = src_nents; -+ qm_sg_src_index = 1 + (buflen ? 1 : 0); -+ qm_sg_bytes = (qm_sg_src_index + mapped_nents) * sizeof(*sg_table); -+ sg_table = &edesc->sgt[0]; -+ -+ ret = ctx_map_to_qm_sg(ctx->dev, state, ctx->ctx_len, sg_table, -+ DMA_TO_DEVICE); -+ if (ret) -+ goto unmap_ctx; -+ -+ ret = buf_map_to_qm_sg(ctx->dev, sg_table + 1, state); -+ if (ret) -+ goto unmap_ctx; -+ -+ sg_to_qm_sg_last(req->src, mapped_nents, sg_table + qm_sg_src_index, 0); -+ -+ edesc->qm_sg_dma = dma_map_single(ctx->dev, sg_table, qm_sg_bytes, -+ DMA_TO_DEVICE); -+ if (dma_mapping_error(ctx->dev, edesc->qm_sg_dma)) { -+ dev_err(ctx->dev, "unable to map S/G table\n"); -+ ret = -ENOMEM; -+ goto unmap_ctx; -+ } -+ edesc->qm_sg_bytes = qm_sg_bytes; -+ -+ edesc->dst_dma = dma_map_single(ctx->dev, req->result, digestsize, -+ DMA_FROM_DEVICE); -+ if (dma_mapping_error(ctx->dev, edesc->dst_dma)) { -+ dev_err(ctx->dev, "unable to map dst\n"); -+ edesc->dst_dma = 0; -+ ret = -ENOMEM; -+ goto unmap_ctx; -+ } -+ -+ memset(&req_ctx->fd_flt, 0, sizeof(req_ctx->fd_flt)); -+ dpaa2_fl_set_final(in_fle, true); -+ dpaa2_fl_set_format(in_fle, dpaa2_fl_sg); -+ dpaa2_fl_set_addr(in_fle, edesc->qm_sg_dma); -+ dpaa2_fl_set_len(in_fle, ctx->ctx_len + buflen + req->nbytes); -+ dpaa2_fl_set_format(out_fle, dpaa2_fl_single); -+ dpaa2_fl_set_addr(out_fle, edesc->dst_dma); -+ dpaa2_fl_set_len(out_fle, digestsize); -+ -+ req_ctx->flc = &ctx->flc[FINALIZE]; -+ req_ctx->flc_dma = ctx->flc_dma[FINALIZE]; -+ req_ctx->cbk = ahash_done_ctx_src; -+ req_ctx->ctx = &req->base; -+ req_ctx->edesc = edesc; -+ -+ ret = dpaa2_caam_enqueue(ctx->dev, req_ctx); -+ if (ret == -EINPROGRESS || -+ (ret == -EBUSY && req->base.flags & CRYPTO_TFM_REQ_MAY_BACKLOG)) -+ return ret; -+ -+unmap_ctx: -+ ahash_unmap_ctx(ctx->dev, edesc, req, digestsize, DMA_FROM_DEVICE); -+ qi_cache_free(edesc); -+ return ret; -+} -+ -+static int ahash_digest(struct ahash_request *req) -+{ -+ struct crypto_ahash *ahash = crypto_ahash_reqtfm(req); -+ struct caam_hash_ctx *ctx = crypto_ahash_ctx(ahash); -+ struct caam_hash_state *state = ahash_request_ctx(req); -+ struct caam_request *req_ctx = &state->caam_req; -+ struct dpaa2_fl_entry *in_fle = &req_ctx->fd_flt[1]; -+ struct dpaa2_fl_entry *out_fle = &req_ctx->fd_flt[0]; -+ gfp_t flags = (req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP) ? -+ GFP_KERNEL : GFP_ATOMIC; -+ int digestsize = crypto_ahash_digestsize(ahash); -+ int src_nents, mapped_nents; -+ struct ahash_edesc *edesc; -+ int ret = -ENOMEM; -+ -+ state->buf_dma = 0; -+ -+ src_nents = sg_nents_for_len(req->src, req->nbytes); -+ if (src_nents < 0) { -+ dev_err(ctx->dev, "Invalid number of src SG.\n"); -+ return src_nents; -+ } -+ -+ if (src_nents) { -+ mapped_nents = dma_map_sg(ctx->dev, req->src, src_nents, -+ DMA_TO_DEVICE); -+ if (!mapped_nents) { -+ dev_err(ctx->dev, "unable to map source for DMA\n"); -+ return ret; -+ } -+ } else { -+ mapped_nents = 0; -+ } -+ -+ /* allocate space for base edesc and link tables */ -+ edesc = qi_cache_zalloc(GFP_DMA | flags); -+ if (!edesc) { -+ dma_unmap_sg(ctx->dev, req->src, src_nents, DMA_TO_DEVICE); -+ return ret; -+ } -+ -+ edesc->src_nents = src_nents; -+ memset(&req_ctx->fd_flt, 0, sizeof(req_ctx->fd_flt)); -+ -+ if (mapped_nents > 1) { -+ int qm_sg_bytes; -+ struct dpaa2_sg_entry *sg_table = &edesc->sgt[0]; -+ -+ qm_sg_bytes = mapped_nents * sizeof(*sg_table); -+ sg_to_qm_sg_last(req->src, mapped_nents, sg_table, 0); -+ edesc->qm_sg_dma = dma_map_single(ctx->dev, sg_table, -+ qm_sg_bytes, DMA_TO_DEVICE); -+ if (dma_mapping_error(ctx->dev, edesc->qm_sg_dma)) { -+ dev_err(ctx->dev, "unable to map S/G table\n"); -+ goto unmap; -+ } -+ edesc->qm_sg_bytes = qm_sg_bytes; -+ dpaa2_fl_set_format(in_fle, dpaa2_fl_sg); -+ dpaa2_fl_set_addr(in_fle, edesc->qm_sg_dma); -+ } else { -+ dpaa2_fl_set_format(in_fle, dpaa2_fl_single); -+ dpaa2_fl_set_addr(in_fle, sg_dma_address(req->src)); -+ } -+ -+ edesc->dst_dma = dma_map_single(ctx->dev, req->result, digestsize, -+ DMA_FROM_DEVICE); -+ if (dma_mapping_error(ctx->dev, edesc->dst_dma)) { -+ dev_err(ctx->dev, "unable to map dst\n"); -+ edesc->dst_dma = 0; -+ goto unmap; -+ } -+ -+ dpaa2_fl_set_final(in_fle, true); -+ dpaa2_fl_set_len(in_fle, req->nbytes); -+ dpaa2_fl_set_format(out_fle, dpaa2_fl_single); -+ dpaa2_fl_set_addr(out_fle, edesc->dst_dma); -+ dpaa2_fl_set_len(out_fle, digestsize); -+ -+ req_ctx->flc = &ctx->flc[DIGEST]; -+ req_ctx->flc_dma = ctx->flc_dma[DIGEST]; -+ req_ctx->cbk = ahash_done; -+ req_ctx->ctx = &req->base; -+ req_ctx->edesc = edesc; -+ ret = dpaa2_caam_enqueue(ctx->dev, req_ctx); -+ if (ret == -EINPROGRESS || -+ (ret == -EBUSY && req->base.flags & CRYPTO_TFM_REQ_MAY_BACKLOG)) -+ return ret; -+ -+unmap: -+ ahash_unmap(ctx->dev, edesc, req, digestsize); -+ qi_cache_free(edesc); -+ return ret; -+} -+ -+static int ahash_final_no_ctx(struct ahash_request *req) -+{ -+ struct crypto_ahash *ahash = crypto_ahash_reqtfm(req); -+ struct caam_hash_ctx *ctx = crypto_ahash_ctx(ahash); -+ struct caam_hash_state *state = ahash_request_ctx(req); -+ struct caam_request *req_ctx = &state->caam_req; -+ struct dpaa2_fl_entry *in_fle = &req_ctx->fd_flt[1]; -+ struct dpaa2_fl_entry *out_fle = &req_ctx->fd_flt[0]; -+ gfp_t flags = (req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP) ? -+ GFP_KERNEL : GFP_ATOMIC; -+ u8 *buf = current_buf(state); -+ int buflen = *current_buflen(state); -+ int digestsize = crypto_ahash_digestsize(ahash); -+ struct ahash_edesc *edesc; -+ int ret = -ENOMEM; -+ -+ /* allocate space for base edesc and link tables */ -+ edesc = qi_cache_zalloc(GFP_DMA | flags); -+ if (!edesc) -+ return ret; -+ -+ state->buf_dma = dma_map_single(ctx->dev, buf, buflen, DMA_TO_DEVICE); -+ if (dma_mapping_error(ctx->dev, state->buf_dma)) { -+ dev_err(ctx->dev, "unable to map src\n"); -+ goto unmap; -+ } -+ -+ edesc->dst_dma = dma_map_single(ctx->dev, req->result, digestsize, -+ DMA_FROM_DEVICE); -+ if (dma_mapping_error(ctx->dev, edesc->dst_dma)) { -+ dev_err(ctx->dev, "unable to map dst\n"); -+ edesc->dst_dma = 0; -+ goto unmap; -+ } -+ -+ memset(&req_ctx->fd_flt, 0, sizeof(req_ctx->fd_flt)); -+ dpaa2_fl_set_final(in_fle, true); -+ dpaa2_fl_set_format(in_fle, dpaa2_fl_single); -+ dpaa2_fl_set_addr(in_fle, state->buf_dma); -+ dpaa2_fl_set_len(in_fle, buflen); -+ dpaa2_fl_set_format(out_fle, dpaa2_fl_single); -+ dpaa2_fl_set_addr(out_fle, edesc->dst_dma); -+ dpaa2_fl_set_len(out_fle, digestsize); -+ -+ req_ctx->flc = &ctx->flc[DIGEST]; -+ req_ctx->flc_dma = ctx->flc_dma[DIGEST]; -+ req_ctx->cbk = ahash_done; -+ req_ctx->ctx = &req->base; -+ req_ctx->edesc = edesc; -+ -+ ret = dpaa2_caam_enqueue(ctx->dev, req_ctx); -+ if (ret == -EINPROGRESS || -+ (ret == -EBUSY && req->base.flags & CRYPTO_TFM_REQ_MAY_BACKLOG)) -+ return ret; -+ -+unmap: -+ ahash_unmap(ctx->dev, edesc, req, digestsize); -+ qi_cache_free(edesc); -+ return ret; -+} -+ -+static int ahash_update_no_ctx(struct ahash_request *req) -+{ -+ struct crypto_ahash *ahash = crypto_ahash_reqtfm(req); -+ struct caam_hash_ctx *ctx = crypto_ahash_ctx(ahash); -+ struct caam_hash_state *state = ahash_request_ctx(req); -+ struct caam_request *req_ctx = &state->caam_req; -+ struct dpaa2_fl_entry *in_fle = &req_ctx->fd_flt[1]; -+ struct dpaa2_fl_entry *out_fle = &req_ctx->fd_flt[0]; -+ gfp_t flags = (req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP) ? -+ GFP_KERNEL : GFP_ATOMIC; -+ u8 *buf = current_buf(state); -+ int *buflen = current_buflen(state); -+ u8 *next_buf = alt_buf(state); -+ int *next_buflen = alt_buflen(state); -+ int in_len = *buflen + req->nbytes, to_hash; -+ int qm_sg_bytes, src_nents, mapped_nents; -+ struct ahash_edesc *edesc; -+ int ret = 0; -+ -+ *next_buflen = in_len & (crypto_tfm_alg_blocksize(&ahash->base) - 1); -+ to_hash = in_len - *next_buflen; -+ -+ if (to_hash) { -+ struct dpaa2_sg_entry *sg_table; -+ -+ src_nents = sg_nents_for_len(req->src, -+ req->nbytes - *next_buflen); -+ if (src_nents < 0) { -+ dev_err(ctx->dev, "Invalid number of src SG.\n"); -+ return src_nents; -+ } -+ -+ if (src_nents) { -+ mapped_nents = dma_map_sg(ctx->dev, req->src, src_nents, -+ DMA_TO_DEVICE); -+ if (!mapped_nents) { -+ dev_err(ctx->dev, "unable to DMA map source\n"); -+ return -ENOMEM; -+ } -+ } else { -+ mapped_nents = 0; -+ } -+ -+ /* allocate space for base edesc and link tables */ -+ edesc = qi_cache_zalloc(GFP_DMA | flags); -+ if (!edesc) { -+ dma_unmap_sg(ctx->dev, req->src, src_nents, -+ DMA_TO_DEVICE); -+ return -ENOMEM; -+ } -+ -+ edesc->src_nents = src_nents; -+ qm_sg_bytes = (1 + mapped_nents) * sizeof(*sg_table); -+ sg_table = &edesc->sgt[0]; -+ -+ ret = buf_map_to_qm_sg(ctx->dev, sg_table, state); -+ if (ret) -+ goto unmap_ctx; -+ -+ sg_to_qm_sg_last(req->src, mapped_nents, sg_table + 1, 0); -+ -+ if (*next_buflen) -+ scatterwalk_map_and_copy(next_buf, req->src, -+ to_hash - *buflen, -+ *next_buflen, 0); -+ -+ edesc->qm_sg_dma = dma_map_single(ctx->dev, sg_table, -+ qm_sg_bytes, DMA_TO_DEVICE); -+ if (dma_mapping_error(ctx->dev, edesc->qm_sg_dma)) { -+ dev_err(ctx->dev, "unable to map S/G table\n"); -+ ret = -ENOMEM; -+ goto unmap_ctx; -+ } -+ edesc->qm_sg_bytes = qm_sg_bytes; -+ -+ state->ctx_dma = dma_map_single(ctx->dev, state->caam_ctx, -+ ctx->ctx_len, DMA_FROM_DEVICE); -+ if (dma_mapping_error(ctx->dev, state->ctx_dma)) { -+ dev_err(ctx->dev, "unable to map ctx\n"); -+ state->ctx_dma = 0; -+ ret = -ENOMEM; -+ goto unmap_ctx; -+ } -+ -+ memset(&req_ctx->fd_flt, 0, sizeof(req_ctx->fd_flt)); -+ dpaa2_fl_set_final(in_fle, true); -+ dpaa2_fl_set_format(in_fle, dpaa2_fl_sg); -+ dpaa2_fl_set_addr(in_fle, edesc->qm_sg_dma); -+ dpaa2_fl_set_len(in_fle, to_hash); -+ dpaa2_fl_set_format(out_fle, dpaa2_fl_single); -+ dpaa2_fl_set_addr(out_fle, state->ctx_dma); -+ dpaa2_fl_set_len(out_fle, ctx->ctx_len); -+ -+ req_ctx->flc = &ctx->flc[UPDATE_FIRST]; -+ req_ctx->flc_dma = ctx->flc_dma[UPDATE_FIRST]; -+ req_ctx->cbk = ahash_done_ctx_dst; -+ req_ctx->ctx = &req->base; -+ req_ctx->edesc = edesc; -+ -+ ret = dpaa2_caam_enqueue(ctx->dev, req_ctx); -+ if (ret != -EINPROGRESS && -+ !(ret == -EBUSY && -+ req->base.flags & CRYPTO_TFM_REQ_MAY_BACKLOG)) -+ goto unmap_ctx; -+ -+ state->update = ahash_update_ctx; -+ state->finup = ahash_finup_ctx; -+ state->final = ahash_final_ctx; -+ } else if (*next_buflen) { -+ scatterwalk_map_and_copy(buf + *buflen, req->src, 0, -+ req->nbytes, 0); -+ *buflen = *next_buflen; -+ *next_buflen = 0; -+ } -+#ifdef DEBUG -+ print_hex_dump(KERN_ERR, "buf@" __stringify(__LINE__)": ", -+ DUMP_PREFIX_ADDRESS, 16, 4, buf, *buflen, 1); -+ print_hex_dump(KERN_ERR, "next buf@" __stringify(__LINE__)": ", -+ DUMP_PREFIX_ADDRESS, 16, 4, next_buf, -+ *next_buflen, 1); -+#endif -+ -+ return ret; -+unmap_ctx: -+ ahash_unmap_ctx(ctx->dev, edesc, req, ctx->ctx_len, DMA_TO_DEVICE); -+ qi_cache_free(edesc); -+ return ret; -+} -+ -+static int ahash_finup_no_ctx(struct ahash_request *req) -+{ -+ struct crypto_ahash *ahash = crypto_ahash_reqtfm(req); -+ struct caam_hash_ctx *ctx = crypto_ahash_ctx(ahash); -+ struct caam_hash_state *state = ahash_request_ctx(req); -+ struct caam_request *req_ctx = &state->caam_req; -+ struct dpaa2_fl_entry *in_fle = &req_ctx->fd_flt[1]; -+ struct dpaa2_fl_entry *out_fle = &req_ctx->fd_flt[0]; -+ gfp_t flags = (req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP) ? -+ GFP_KERNEL : GFP_ATOMIC; -+ int buflen = *current_buflen(state); -+ int qm_sg_bytes, src_nents, mapped_nents; -+ int digestsize = crypto_ahash_digestsize(ahash); -+ struct ahash_edesc *edesc; -+ struct dpaa2_sg_entry *sg_table; -+ int ret; -+ -+ src_nents = sg_nents_for_len(req->src, req->nbytes); -+ if (src_nents < 0) { -+ dev_err(ctx->dev, "Invalid number of src SG.\n"); -+ return src_nents; -+ } -+ -+ if (src_nents) { -+ mapped_nents = dma_map_sg(ctx->dev, req->src, src_nents, -+ DMA_TO_DEVICE); -+ if (!mapped_nents) { -+ dev_err(ctx->dev, "unable to DMA map source\n"); -+ return -ENOMEM; -+ } -+ } else { -+ mapped_nents = 0; -+ } -+ -+ /* allocate space for base edesc and link tables */ -+ edesc = qi_cache_zalloc(GFP_DMA | flags); -+ if (!edesc) { -+ dma_unmap_sg(ctx->dev, req->src, src_nents, DMA_TO_DEVICE); -+ return -ENOMEM; -+ } -+ -+ edesc->src_nents = src_nents; -+ qm_sg_bytes = (2 + mapped_nents) * sizeof(*sg_table); -+ sg_table = &edesc->sgt[0]; -+ -+ ret = buf_map_to_qm_sg(ctx->dev, sg_table, state); -+ if (ret) -+ goto unmap; -+ -+ sg_to_qm_sg_last(req->src, mapped_nents, sg_table + 1, 0); -+ -+ edesc->qm_sg_dma = dma_map_single(ctx->dev, sg_table, qm_sg_bytes, -+ DMA_TO_DEVICE); -+ if (dma_mapping_error(ctx->dev, edesc->qm_sg_dma)) { -+ dev_err(ctx->dev, "unable to map S/G table\n"); -+ ret = -ENOMEM; -+ goto unmap; -+ } -+ edesc->qm_sg_bytes = qm_sg_bytes; -+ -+ edesc->dst_dma = dma_map_single(ctx->dev, req->result, digestsize, -+ DMA_FROM_DEVICE); -+ if (dma_mapping_error(ctx->dev, edesc->dst_dma)) { -+ dev_err(ctx->dev, "unable to map dst\n"); -+ edesc->dst_dma = 0; -+ ret = -ENOMEM; -+ goto unmap; -+ } -+ -+ memset(&req_ctx->fd_flt, 0, sizeof(req_ctx->fd_flt)); -+ dpaa2_fl_set_final(in_fle, true); -+ dpaa2_fl_set_format(in_fle, dpaa2_fl_sg); -+ dpaa2_fl_set_addr(in_fle, edesc->qm_sg_dma); -+ dpaa2_fl_set_len(in_fle, buflen + req->nbytes); -+ dpaa2_fl_set_format(out_fle, dpaa2_fl_single); -+ dpaa2_fl_set_addr(out_fle, edesc->dst_dma); -+ dpaa2_fl_set_len(out_fle, digestsize); -+ -+ req_ctx->flc = &ctx->flc[DIGEST]; -+ req_ctx->flc_dma = ctx->flc_dma[DIGEST]; -+ req_ctx->cbk = ahash_done; -+ req_ctx->ctx = &req->base; -+ req_ctx->edesc = edesc; -+ ret = dpaa2_caam_enqueue(ctx->dev, req_ctx); -+ if (ret != -EINPROGRESS && -+ !(ret == -EBUSY && req->base.flags & CRYPTO_TFM_REQ_MAY_BACKLOG)) -+ goto unmap; -+ -+ return ret; -+unmap: -+ ahash_unmap(ctx->dev, edesc, req, digestsize); -+ qi_cache_free(edesc); -+ return -ENOMEM; -+} -+ -+static int ahash_update_first(struct ahash_request *req) -+{ -+ struct crypto_ahash *ahash = crypto_ahash_reqtfm(req); -+ struct caam_hash_ctx *ctx = crypto_ahash_ctx(ahash); -+ struct caam_hash_state *state = ahash_request_ctx(req); -+ struct caam_request *req_ctx = &state->caam_req; -+ struct dpaa2_fl_entry *in_fle = &req_ctx->fd_flt[1]; -+ struct dpaa2_fl_entry *out_fle = &req_ctx->fd_flt[0]; -+ gfp_t flags = (req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP) ? -+ GFP_KERNEL : GFP_ATOMIC; -+ u8 *next_buf = alt_buf(state); -+ int *next_buflen = alt_buflen(state); -+ int to_hash; -+ int src_nents, mapped_nents; -+ struct ahash_edesc *edesc; -+ int ret = 0; -+ -+ *next_buflen = req->nbytes & (crypto_tfm_alg_blocksize(&ahash->base) - -+ 1); -+ to_hash = req->nbytes - *next_buflen; -+ -+ if (to_hash) { -+ struct dpaa2_sg_entry *sg_table; -+ -+ src_nents = sg_nents_for_len(req->src, -+ req->nbytes - (*next_buflen)); -+ if (src_nents < 0) { -+ dev_err(ctx->dev, "Invalid number of src SG.\n"); -+ return src_nents; -+ } -+ -+ if (src_nents) { -+ mapped_nents = dma_map_sg(ctx->dev, req->src, src_nents, -+ DMA_TO_DEVICE); -+ if (!mapped_nents) { -+ dev_err(ctx->dev, "unable to map source for DMA\n"); -+ return -ENOMEM; -+ } -+ } else { -+ mapped_nents = 0; -+ } -+ -+ /* allocate space for base edesc and link tables */ -+ edesc = qi_cache_zalloc(GFP_DMA | flags); -+ if (!edesc) { -+ dma_unmap_sg(ctx->dev, req->src, src_nents, -+ DMA_TO_DEVICE); -+ return -ENOMEM; -+ } -+ -+ edesc->src_nents = src_nents; -+ sg_table = &edesc->sgt[0]; -+ -+ memset(&req_ctx->fd_flt, 0, sizeof(req_ctx->fd_flt)); -+ dpaa2_fl_set_final(in_fle, true); -+ dpaa2_fl_set_len(in_fle, to_hash); -+ -+ if (mapped_nents > 1) { -+ int qm_sg_bytes; -+ -+ sg_to_qm_sg_last(req->src, mapped_nents, sg_table, 0); -+ qm_sg_bytes = mapped_nents * sizeof(*sg_table); -+ edesc->qm_sg_dma = dma_map_single(ctx->dev, sg_table, -+ qm_sg_bytes, -+ DMA_TO_DEVICE); -+ if (dma_mapping_error(ctx->dev, edesc->qm_sg_dma)) { -+ dev_err(ctx->dev, "unable to map S/G table\n"); -+ ret = -ENOMEM; -+ goto unmap_ctx; -+ } -+ edesc->qm_sg_bytes = qm_sg_bytes; -+ dpaa2_fl_set_format(in_fle, dpaa2_fl_sg); -+ dpaa2_fl_set_addr(in_fle, edesc->qm_sg_dma); -+ } else { -+ dpaa2_fl_set_format(in_fle, dpaa2_fl_single); -+ dpaa2_fl_set_addr(in_fle, sg_dma_address(req->src)); -+ } -+ -+ if (*next_buflen) -+ scatterwalk_map_and_copy(next_buf, req->src, to_hash, -+ *next_buflen, 0); -+ -+ state->ctx_dma = dma_map_single(ctx->dev, state->caam_ctx, -+ ctx->ctx_len, DMA_FROM_DEVICE); -+ if (dma_mapping_error(ctx->dev, state->ctx_dma)) { -+ dev_err(ctx->dev, "unable to map ctx\n"); -+ state->ctx_dma = 0; -+ ret = -ENOMEM; -+ goto unmap_ctx; -+ } -+ -+ dpaa2_fl_set_format(out_fle, dpaa2_fl_single); -+ dpaa2_fl_set_addr(out_fle, state->ctx_dma); -+ dpaa2_fl_set_len(out_fle, ctx->ctx_len); -+ -+ req_ctx->flc = &ctx->flc[UPDATE_FIRST]; -+ req_ctx->flc_dma = ctx->flc_dma[UPDATE_FIRST]; -+ req_ctx->cbk = ahash_done_ctx_dst; -+ req_ctx->ctx = &req->base; -+ req_ctx->edesc = edesc; -+ -+ ret = dpaa2_caam_enqueue(ctx->dev, req_ctx); -+ if (ret != -EINPROGRESS && -+ !(ret == -EBUSY && req->base.flags & -+ CRYPTO_TFM_REQ_MAY_BACKLOG)) -+ goto unmap_ctx; -+ -+ state->update = ahash_update_ctx; -+ state->finup = ahash_finup_ctx; -+ state->final = ahash_final_ctx; -+ } else if (*next_buflen) { -+ state->update = ahash_update_no_ctx; -+ state->finup = ahash_finup_no_ctx; -+ state->final = ahash_final_no_ctx; -+ scatterwalk_map_and_copy(next_buf, req->src, 0, -+ req->nbytes, 0); -+ switch_buf(state); -+ } -+#ifdef DEBUG -+ print_hex_dump(KERN_ERR, "next buf@" __stringify(__LINE__)": ", -+ DUMP_PREFIX_ADDRESS, 16, 4, next_buf, *next_buflen, 1); -+#endif -+ -+ return ret; -+unmap_ctx: -+ ahash_unmap_ctx(ctx->dev, edesc, req, ctx->ctx_len, DMA_TO_DEVICE); -+ qi_cache_free(edesc); -+ return ret; -+} -+ -+static int ahash_finup_first(struct ahash_request *req) -+{ -+ return ahash_digest(req); -+} -+ -+static int ahash_init(struct ahash_request *req) -+{ -+ struct caam_hash_state *state = ahash_request_ctx(req); -+ -+ state->update = ahash_update_first; -+ state->finup = ahash_finup_first; -+ state->final = ahash_final_no_ctx; -+ -+ state->ctx_dma = 0; -+ state->current_buf = 0; -+ state->buf_dma = 0; -+ state->buflen_0 = 0; -+ state->buflen_1 = 0; -+ -+ return 0; -+} -+ -+static int ahash_update(struct ahash_request *req) -+{ -+ struct caam_hash_state *state = ahash_request_ctx(req); -+ -+ return state->update(req); -+} -+ -+static int ahash_finup(struct ahash_request *req) -+{ -+ struct caam_hash_state *state = ahash_request_ctx(req); -+ -+ return state->finup(req); -+} -+ -+static int ahash_final(struct ahash_request *req) -+{ -+ struct caam_hash_state *state = ahash_request_ctx(req); -+ -+ return state->final(req); -+} -+ -+static int ahash_export(struct ahash_request *req, void *out) -+{ -+ struct caam_hash_state *state = ahash_request_ctx(req); -+ struct caam_export_state *export = out; -+ int len; -+ u8 *buf; -+ -+ if (state->current_buf) { -+ buf = state->buf_1; -+ len = state->buflen_1; -+ } else { -+ buf = state->buf_0; -+ len = state->buflen_0; -+ } -+ -+ memcpy(export->buf, buf, len); -+ memcpy(export->caam_ctx, state->caam_ctx, sizeof(export->caam_ctx)); -+ export->buflen = len; -+ export->update = state->update; -+ export->final = state->final; -+ export->finup = state->finup; -+ -+ return 0; -+} -+ -+static int ahash_import(struct ahash_request *req, const void *in) -+{ -+ struct caam_hash_state *state = ahash_request_ctx(req); -+ const struct caam_export_state *export = in; -+ -+ memset(state, 0, sizeof(*state)); -+ memcpy(state->buf_0, export->buf, export->buflen); -+ memcpy(state->caam_ctx, export->caam_ctx, sizeof(state->caam_ctx)); -+ state->buflen_0 = export->buflen; -+ state->update = export->update; -+ state->final = export->final; -+ state->finup = export->finup; -+ -+ return 0; -+} -+ -+struct caam_hash_template { -+ char name[CRYPTO_MAX_ALG_NAME]; -+ char driver_name[CRYPTO_MAX_ALG_NAME]; -+ char hmac_name[CRYPTO_MAX_ALG_NAME]; -+ char hmac_driver_name[CRYPTO_MAX_ALG_NAME]; -+ unsigned int blocksize; -+ struct ahash_alg template_ahash; -+ u32 alg_type; -+}; -+ -+/* ahash descriptors */ -+static struct caam_hash_template driver_hash[] = { -+ { -+ .name = "sha1", -+ .driver_name = "sha1-caam-qi2", -+ .hmac_name = "hmac(sha1)", -+ .hmac_driver_name = "hmac-sha1-caam-qi2", -+ .blocksize = SHA1_BLOCK_SIZE, -+ .template_ahash = { -+ .init = ahash_init, -+ .update = ahash_update, -+ .final = ahash_final, -+ .finup = ahash_finup, -+ .digest = ahash_digest, -+ .export = ahash_export, -+ .import = ahash_import, -+ .setkey = ahash_setkey, -+ .halg = { -+ .digestsize = SHA1_DIGEST_SIZE, -+ .statesize = sizeof(struct caam_export_state), -+ }, -+ }, -+ .alg_type = OP_ALG_ALGSEL_SHA1, -+ }, { -+ .name = "sha224", -+ .driver_name = "sha224-caam-qi2", -+ .hmac_name = "hmac(sha224)", -+ .hmac_driver_name = "hmac-sha224-caam-qi2", -+ .blocksize = SHA224_BLOCK_SIZE, -+ .template_ahash = { -+ .init = ahash_init, -+ .update = ahash_update, -+ .final = ahash_final, -+ .finup = ahash_finup, -+ .digest = ahash_digest, -+ .export = ahash_export, -+ .import = ahash_import, -+ .setkey = ahash_setkey, -+ .halg = { -+ .digestsize = SHA224_DIGEST_SIZE, -+ .statesize = sizeof(struct caam_export_state), -+ }, -+ }, -+ .alg_type = OP_ALG_ALGSEL_SHA224, -+ }, { -+ .name = "sha256", -+ .driver_name = "sha256-caam-qi2", -+ .hmac_name = "hmac(sha256)", -+ .hmac_driver_name = "hmac-sha256-caam-qi2", -+ .blocksize = SHA256_BLOCK_SIZE, -+ .template_ahash = { -+ .init = ahash_init, -+ .update = ahash_update, -+ .final = ahash_final, -+ .finup = ahash_finup, -+ .digest = ahash_digest, -+ .export = ahash_export, -+ .import = ahash_import, -+ .setkey = ahash_setkey, -+ .halg = { -+ .digestsize = SHA256_DIGEST_SIZE, -+ .statesize = sizeof(struct caam_export_state), -+ }, -+ }, -+ .alg_type = OP_ALG_ALGSEL_SHA256, -+ }, { -+ .name = "sha384", -+ .driver_name = "sha384-caam-qi2", -+ .hmac_name = "hmac(sha384)", -+ .hmac_driver_name = "hmac-sha384-caam-qi2", -+ .blocksize = SHA384_BLOCK_SIZE, -+ .template_ahash = { -+ .init = ahash_init, -+ .update = ahash_update, -+ .final = ahash_final, -+ .finup = ahash_finup, -+ .digest = ahash_digest, -+ .export = ahash_export, -+ .import = ahash_import, -+ .setkey = ahash_setkey, -+ .halg = { -+ .digestsize = SHA384_DIGEST_SIZE, -+ .statesize = sizeof(struct caam_export_state), -+ }, -+ }, -+ .alg_type = OP_ALG_ALGSEL_SHA384, -+ }, { -+ .name = "sha512", -+ .driver_name = "sha512-caam-qi2", -+ .hmac_name = "hmac(sha512)", -+ .hmac_driver_name = "hmac-sha512-caam-qi2", -+ .blocksize = SHA512_BLOCK_SIZE, -+ .template_ahash = { -+ .init = ahash_init, -+ .update = ahash_update, -+ .final = ahash_final, -+ .finup = ahash_finup, -+ .digest = ahash_digest, -+ .export = ahash_export, -+ .import = ahash_import, -+ .setkey = ahash_setkey, -+ .halg = { -+ .digestsize = SHA512_DIGEST_SIZE, -+ .statesize = sizeof(struct caam_export_state), -+ }, -+ }, -+ .alg_type = OP_ALG_ALGSEL_SHA512, -+ }, { -+ .name = "md5", -+ .driver_name = "md5-caam-qi2", -+ .hmac_name = "hmac(md5)", -+ .hmac_driver_name = "hmac-md5-caam-qi2", -+ .blocksize = MD5_BLOCK_WORDS * 4, -+ .template_ahash = { -+ .init = ahash_init, -+ .update = ahash_update, -+ .final = ahash_final, -+ .finup = ahash_finup, -+ .digest = ahash_digest, -+ .export = ahash_export, -+ .import = ahash_import, -+ .setkey = ahash_setkey, -+ .halg = { -+ .digestsize = MD5_DIGEST_SIZE, -+ .statesize = sizeof(struct caam_export_state), -+ }, -+ }, -+ .alg_type = OP_ALG_ALGSEL_MD5, -+ } -+}; -+ -+struct caam_hash_alg { -+ struct list_head entry; -+ struct device *dev; -+ int alg_type; -+ struct ahash_alg ahash_alg; -+}; -+ -+static int caam_hash_cra_init(struct crypto_tfm *tfm) -+{ -+ struct crypto_ahash *ahash = __crypto_ahash_cast(tfm); -+ struct crypto_alg *base = tfm->__crt_alg; -+ struct hash_alg_common *halg = -+ container_of(base, struct hash_alg_common, base); -+ struct ahash_alg *alg = -+ container_of(halg, struct ahash_alg, halg); -+ struct caam_hash_alg *caam_hash = -+ container_of(alg, struct caam_hash_alg, ahash_alg); -+ struct caam_hash_ctx *ctx = crypto_tfm_ctx(tfm); -+ /* Sizes for MDHA running digests: MD5, SHA1, 224, 256, 384, 512 */ -+ static const u8 runninglen[] = { HASH_MSG_LEN + MD5_DIGEST_SIZE, -+ HASH_MSG_LEN + SHA1_DIGEST_SIZE, -+ HASH_MSG_LEN + 32, -+ HASH_MSG_LEN + SHA256_DIGEST_SIZE, -+ HASH_MSG_LEN + 64, -+ HASH_MSG_LEN + SHA512_DIGEST_SIZE }; -+ dma_addr_t dma_addr; -+ int i; -+ -+ ctx->dev = caam_hash->dev; -+ -+ dma_addr = dma_map_single_attrs(ctx->dev, ctx->flc, sizeof(ctx->flc), -+ DMA_BIDIRECTIONAL, -+ DMA_ATTR_SKIP_CPU_SYNC); -+ if (dma_mapping_error(ctx->dev, dma_addr)) { -+ dev_err(ctx->dev, "unable to map shared descriptors\n"); -+ return -ENOMEM; -+ } -+ -+ for (i = 0; i < HASH_NUM_OP; i++) -+ ctx->flc_dma[i] = dma_addr + i * sizeof(ctx->flc[i]); -+ -+ /* copy descriptor header template value */ -+ ctx->adata.algtype = OP_TYPE_CLASS2_ALG | caam_hash->alg_type; -+ -+ ctx->ctx_len = runninglen[(ctx->adata.algtype & -+ OP_ALG_ALGSEL_SUBMASK) >> -+ OP_ALG_ALGSEL_SHIFT]; -+ -+ crypto_ahash_set_reqsize(__crypto_ahash_cast(tfm), -+ sizeof(struct caam_hash_state)); -+ -+ return ahash_set_sh_desc(ahash); -+} -+ -+static void caam_hash_cra_exit(struct crypto_tfm *tfm) -+{ -+ struct caam_hash_ctx *ctx = crypto_tfm_ctx(tfm); -+ -+ dma_unmap_single_attrs(ctx->dev, ctx->flc_dma[0], sizeof(ctx->flc), -+ DMA_BIDIRECTIONAL, DMA_ATTR_SKIP_CPU_SYNC); -+} -+ -+static struct caam_hash_alg *caam_hash_alloc(struct device *dev, -+ struct caam_hash_template *template, bool keyed) -+{ -+ struct caam_hash_alg *t_alg; -+ struct ahash_alg *halg; -+ struct crypto_alg *alg; -+ -+ t_alg = kzalloc(sizeof(*t_alg), GFP_KERNEL); -+ if (!t_alg) -+ return ERR_PTR(-ENOMEM); -+ -+ t_alg->ahash_alg = template->template_ahash; -+ halg = &t_alg->ahash_alg; -+ alg = &halg->halg.base; -+ -+ if (keyed) { -+ snprintf(alg->cra_name, CRYPTO_MAX_ALG_NAME, "%s", -+ template->hmac_name); -+ snprintf(alg->cra_driver_name, CRYPTO_MAX_ALG_NAME, "%s", -+ template->hmac_driver_name); -+ } else { -+ snprintf(alg->cra_name, CRYPTO_MAX_ALG_NAME, "%s", -+ template->name); -+ snprintf(alg->cra_driver_name, CRYPTO_MAX_ALG_NAME, "%s", -+ template->driver_name); -+ t_alg->ahash_alg.setkey = NULL; -+ } -+ alg->cra_module = THIS_MODULE; -+ alg->cra_init = caam_hash_cra_init; -+ alg->cra_exit = caam_hash_cra_exit; -+ alg->cra_ctxsize = sizeof(struct caam_hash_ctx); -+ alg->cra_priority = CAAM_CRA_PRIORITY; -+ alg->cra_blocksize = template->blocksize; -+ alg->cra_alignmask = 0; -+ alg->cra_flags = CRYPTO_ALG_ASYNC | CRYPTO_ALG_TYPE_AHASH; -+ alg->cra_type = &crypto_ahash_type; -+ -+ t_alg->alg_type = template->alg_type; -+ t_alg->dev = dev; -+ -+ return t_alg; -+} -+ -+static void dpaa2_caam_fqdan_cb(struct dpaa2_io_notification_ctx *nctx) -+{ -+ struct dpaa2_caam_priv_per_cpu *ppriv; -+ -+ ppriv = container_of(nctx, struct dpaa2_caam_priv_per_cpu, nctx); -+ napi_schedule_irqoff(&ppriv->napi); -+} -+ -+static int __cold dpaa2_dpseci_dpio_setup(struct dpaa2_caam_priv *priv) -+{ -+ struct device *dev = priv->dev; -+ struct dpaa2_io_notification_ctx *nctx; -+ struct dpaa2_caam_priv_per_cpu *ppriv; -+ int err, i = 0, cpu; -+ -+ for_each_online_cpu(cpu) { -+ ppriv = per_cpu_ptr(priv->ppriv, cpu); -+ ppriv->priv = priv; -+ nctx = &ppriv->nctx; -+ nctx->is_cdan = 0; -+ nctx->id = ppriv->rsp_fqid; -+ nctx->desired_cpu = cpu; -+ nctx->cb = dpaa2_caam_fqdan_cb; -+ -+ /* Register notification callbacks */ -+ ppriv->dpio = dpaa2_io_service_select(cpu); -+ err = dpaa2_io_service_register(ppriv->dpio, nctx, dev); -+ if (unlikely(err)) { -+ dev_dbg(dev, "No affine DPIO for cpu %d\n", cpu); -+ nctx->cb = NULL; -+ /* -+ * If no affine DPIO for this core, there's probably -+ * none available for next cores either. Signal we want -+ * to retry later, in case the DPIO devices weren't -+ * probed yet. -+ */ -+ err = -EPROBE_DEFER; -+ goto err; -+ } -+ -+ ppriv->store = dpaa2_io_store_create(DPAA2_CAAM_STORE_SIZE, -+ dev); -+ if (unlikely(!ppriv->store)) { -+ dev_err(dev, "dpaa2_io_store_create() failed\n"); -+ err = -ENOMEM; -+ goto err; -+ } -+ -+ if (++i == priv->num_pairs) -+ break; -+ } -+ -+ return 0; -+ -+err: -+ for_each_online_cpu(cpu) { -+ ppriv = per_cpu_ptr(priv->ppriv, cpu); -+ if (!ppriv->nctx.cb) -+ break; -+ dpaa2_io_service_deregister(ppriv->dpio, &ppriv->nctx, dev); -+ } -+ -+ for_each_online_cpu(cpu) { -+ ppriv = per_cpu_ptr(priv->ppriv, cpu); -+ if (!ppriv->store) -+ break; -+ dpaa2_io_store_destroy(ppriv->store); -+ } -+ -+ return err; -+} -+ -+static void __cold dpaa2_dpseci_dpio_free(struct dpaa2_caam_priv *priv) -+{ -+ struct dpaa2_caam_priv_per_cpu *ppriv; -+ struct device *dev = priv->dev; -+ int i = 0, cpu; -+ -+ for_each_online_cpu(cpu) { -+ ppriv = per_cpu_ptr(priv->ppriv, cpu); -+ dpaa2_io_service_deregister(ppriv->dpio, &ppriv->nctx, dev); -+ dpaa2_io_store_destroy(ppriv->store); -+ -+ if (++i == priv->num_pairs) -+ return; -+ } -+} -+ -+static int dpaa2_dpseci_bind(struct dpaa2_caam_priv *priv) -+{ -+ struct dpseci_rx_queue_cfg rx_queue_cfg; -+ struct device *dev = priv->dev; -+ struct fsl_mc_device *ls_dev = to_fsl_mc_device(dev); -+ struct dpaa2_caam_priv_per_cpu *ppriv; -+ int err = 0, i = 0, cpu; -+ -+ /* Configure Rx queues */ -+ for_each_online_cpu(cpu) { -+ ppriv = per_cpu_ptr(priv->ppriv, cpu); -+ -+ rx_queue_cfg.options = DPSECI_QUEUE_OPT_DEST | -+ DPSECI_QUEUE_OPT_USER_CTX; -+ rx_queue_cfg.order_preservation_en = 0; -+ rx_queue_cfg.dest_cfg.dest_type = DPSECI_DEST_DPIO; -+ rx_queue_cfg.dest_cfg.dest_id = ppriv->nctx.dpio_id; -+ /* -+ * Rx priority (WQ) doesn't really matter, since we use -+ * pull mode, i.e. volatile dequeues from specific FQs -+ */ -+ rx_queue_cfg.dest_cfg.priority = 0; -+ rx_queue_cfg.user_ctx = ppriv->nctx.qman64; -+ -+ err = dpseci_set_rx_queue(priv->mc_io, 0, ls_dev->mc_handle, i, -+ &rx_queue_cfg); -+ if (err) { -+ dev_err(dev, "dpseci_set_rx_queue() failed with err %d\n", -+ err); -+ return err; -+ } -+ -+ if (++i == priv->num_pairs) -+ break; -+ } -+ -+ return err; -+} -+ -+static void dpaa2_dpseci_congestion_free(struct dpaa2_caam_priv *priv) -+{ -+ struct device *dev = priv->dev; -+ -+ if (!priv->cscn_mem) -+ return; -+ -+ dma_unmap_single(dev, priv->cscn_dma, DPAA2_CSCN_SIZE, DMA_FROM_DEVICE); -+ kfree(priv->cscn_mem); -+} -+ -+static void dpaa2_dpseci_free(struct dpaa2_caam_priv *priv) -+{ -+ struct device *dev = priv->dev; -+ struct fsl_mc_device *ls_dev = to_fsl_mc_device(dev); -+ -+ dpaa2_dpseci_congestion_free(priv); -+ dpseci_close(priv->mc_io, 0, ls_dev->mc_handle); -+} -+ -+static void dpaa2_caam_process_fd(struct dpaa2_caam_priv *priv, -+ const struct dpaa2_fd *fd) -+{ -+ struct caam_request *req; -+ u32 fd_err; -+ -+ if (dpaa2_fd_get_format(fd) != dpaa2_fd_list) { -+ dev_err(priv->dev, "Only Frame List FD format is supported!\n"); -+ return; -+ } -+ -+ fd_err = dpaa2_fd_get_ctrl(fd) & FD_CTRL_ERR_MASK; -+ if (unlikely(fd_err)) -+ dev_err(priv->dev, "FD error: %08x\n", fd_err); -+ -+ /* -+ * FD[ADDR] is guaranteed to be valid, irrespective of errors reported -+ * in FD[ERR] or FD[FRC]. -+ */ -+ req = dpaa2_caam_iova_to_virt(priv, dpaa2_fd_get_addr(fd)); -+ dma_unmap_single(priv->dev, req->fd_flt_dma, sizeof(req->fd_flt), -+ DMA_BIDIRECTIONAL); -+ req->cbk(req->ctx, dpaa2_fd_get_frc(fd)); -+} -+ -+static int dpaa2_caam_pull_fq(struct dpaa2_caam_priv_per_cpu *ppriv) -+{ -+ int err; -+ -+ /* Retry while portal is busy */ -+ do { -+ err = dpaa2_io_service_pull_fq(ppriv->dpio, ppriv->rsp_fqid, -+ ppriv->store); -+ } while (err == -EBUSY); -+ -+ if (unlikely(err)) -+ dev_err(ppriv->priv->dev, "dpaa2_io_service_pull err %d", err); -+ -+ return err; -+} -+ -+static int dpaa2_caam_store_consume(struct dpaa2_caam_priv_per_cpu *ppriv) -+{ -+ struct dpaa2_dq *dq; -+ int cleaned = 0, is_last; -+ -+ do { -+ dq = dpaa2_io_store_next(ppriv->store, &is_last); -+ if (unlikely(!dq)) { -+ if (unlikely(!is_last)) { -+ dev_dbg(ppriv->priv->dev, -+ "FQ %d returned no valid frames\n", -+ ppriv->rsp_fqid); -+ /* -+ * MUST retry until we get some sort of -+ * valid response token (be it "empty dequeue" -+ * or a valid frame). -+ */ -+ continue; -+ } -+ break; -+ } -+ -+ /* Process FD */ -+ dpaa2_caam_process_fd(ppriv->priv, dpaa2_dq_fd(dq)); -+ cleaned++; -+ } while (!is_last); -+ -+ return cleaned; -+} -+ -+static int dpaa2_dpseci_poll(struct napi_struct *napi, int budget) -+{ -+ struct dpaa2_caam_priv_per_cpu *ppriv; -+ struct dpaa2_caam_priv *priv; -+ int err, cleaned = 0, store_cleaned; -+ -+ ppriv = container_of(napi, struct dpaa2_caam_priv_per_cpu, napi); -+ priv = ppriv->priv; -+ -+ if (unlikely(dpaa2_caam_pull_fq(ppriv))) -+ return 0; -+ -+ do { -+ store_cleaned = dpaa2_caam_store_consume(ppriv); -+ cleaned += store_cleaned; -+ -+ if (store_cleaned == 0 || -+ cleaned > budget - DPAA2_CAAM_STORE_SIZE) -+ break; -+ -+ /* Try to dequeue some more */ -+ err = dpaa2_caam_pull_fq(ppriv); -+ if (unlikely(err)) -+ break; -+ } while (1); -+ -+ if (cleaned < budget) { -+ napi_complete_done(napi, cleaned); -+ err = dpaa2_io_service_rearm(ppriv->dpio, &ppriv->nctx); -+ if (unlikely(err)) -+ dev_err(priv->dev, "Notification rearm failed: %d\n", -+ err); -+ } -+ -+ return cleaned; -+} -+ -+static int dpaa2_dpseci_congestion_setup(struct dpaa2_caam_priv *priv, -+ u16 token) -+{ -+ struct dpseci_congestion_notification_cfg cong_notif_cfg = { 0 }; -+ struct device *dev = priv->dev; -+ int err; -+ -+ /* -+ * Congestion group feature supported starting with DPSECI API v5.1 -+ * and only when object has been created with this capability. -+ */ -+ if ((DPSECI_VER(priv->major_ver, priv->minor_ver) < DPSECI_VER(5, 1)) || -+ !(priv->dpseci_attr.options & DPSECI_OPT_HAS_CG)) -+ return 0; -+ -+ priv->cscn_mem = kzalloc(DPAA2_CSCN_SIZE + DPAA2_CSCN_ALIGN, -+ GFP_KERNEL | GFP_DMA); -+ if (!priv->cscn_mem) -+ return -ENOMEM; -+ -+ priv->cscn_mem_aligned = PTR_ALIGN(priv->cscn_mem, DPAA2_CSCN_ALIGN); -+ priv->cscn_dma = dma_map_single(dev, priv->cscn_mem_aligned, -+ DPAA2_CSCN_SIZE, DMA_FROM_DEVICE); -+ if (dma_mapping_error(dev, priv->cscn_dma)) { -+ dev_err(dev, "Error mapping CSCN memory area\n"); -+ err = -ENOMEM; -+ goto err_dma_map; -+ } -+ -+ cong_notif_cfg.units = DPSECI_CONGESTION_UNIT_BYTES; -+ cong_notif_cfg.threshold_entry = DPAA2_SEC_CONG_ENTRY_THRESH; -+ cong_notif_cfg.threshold_exit = DPAA2_SEC_CONG_EXIT_THRESH; -+ cong_notif_cfg.message_ctx = (u64)priv; -+ cong_notif_cfg.message_iova = priv->cscn_dma; -+ cong_notif_cfg.notification_mode = DPSECI_CGN_MODE_WRITE_MEM_ON_ENTER | -+ DPSECI_CGN_MODE_WRITE_MEM_ON_EXIT | -+ DPSECI_CGN_MODE_COHERENT_WRITE; -+ -+ err = dpseci_set_congestion_notification(priv->mc_io, 0, token, -+ &cong_notif_cfg); -+ if (err) { -+ dev_err(dev, "dpseci_set_congestion_notification failed\n"); -+ goto err_set_cong; -+ } -+ -+ return 0; -+ -+err_set_cong: -+ dma_unmap_single(dev, priv->cscn_dma, DPAA2_CSCN_SIZE, DMA_FROM_DEVICE); -+err_dma_map: -+ kfree(priv->cscn_mem); -+ -+ return err; -+} -+ -+static int __cold dpaa2_dpseci_setup(struct fsl_mc_device *ls_dev) -+{ -+ struct device *dev = &ls_dev->dev; -+ struct dpaa2_caam_priv *priv; -+ struct dpaa2_caam_priv_per_cpu *ppriv; -+ int err, cpu; -+ u8 i; -+ -+ priv = dev_get_drvdata(dev); -+ -+ priv->dev = dev; -+ priv->dpsec_id = ls_dev->obj_desc.id; -+ -+ /* Get a handle for the DPSECI this interface is associate with */ -+ err = dpseci_open(priv->mc_io, 0, priv->dpsec_id, &ls_dev->mc_handle); -+ if (err) { -+ dev_err(dev, "dpsec_open() failed: %d\n", err); -+ goto err_open; -+ } -+ -+ dev_info(dev, "Opened dpseci object successfully\n"); -+ -+ err = dpseci_get_api_version(priv->mc_io, 0, &priv->major_ver, -+ &priv->minor_ver); -+ if (err) { -+ dev_err(dev, "dpseci_get_api_version() failed\n"); -+ goto err_get_vers; -+ } -+ -+ err = dpseci_get_attributes(priv->mc_io, 0, ls_dev->mc_handle, -+ &priv->dpseci_attr); -+ if (err) { -+ dev_err(dev, "dpseci_get_attributes() failed\n"); -+ goto err_get_vers; -+ } -+ -+ err = dpseci_get_sec_attr(priv->mc_io, 0, ls_dev->mc_handle, -+ &priv->sec_attr); -+ if (err) { -+ dev_err(dev, "dpseci_get_sec_attr() failed\n"); -+ goto err_get_vers; -+ } -+ -+ err = dpaa2_dpseci_congestion_setup(priv, ls_dev->mc_handle); -+ if (err) { -+ dev_err(dev, "setup_congestion() failed\n"); -+ goto err_get_vers; -+ } -+ -+ priv->num_pairs = min(priv->dpseci_attr.num_rx_queues, -+ priv->dpseci_attr.num_tx_queues); -+ if (priv->num_pairs > num_online_cpus()) { -+ dev_warn(dev, "%d queues won't be used\n", -+ priv->num_pairs - num_online_cpus()); -+ priv->num_pairs = num_online_cpus(); -+ } -+ -+ for (i = 0; i < priv->dpseci_attr.num_rx_queues; i++) { -+ err = dpseci_get_rx_queue(priv->mc_io, 0, ls_dev->mc_handle, i, -+ &priv->rx_queue_attr[i]); -+ if (err) { -+ dev_err(dev, "dpseci_get_rx_queue() failed\n"); -+ goto err_get_rx_queue; -+ } -+ } -+ -+ for (i = 0; i < priv->dpseci_attr.num_tx_queues; i++) { -+ err = dpseci_get_tx_queue(priv->mc_io, 0, ls_dev->mc_handle, i, -+ &priv->tx_queue_attr[i]); -+ if (err) { -+ dev_err(dev, "dpseci_get_tx_queue() failed\n"); -+ goto err_get_rx_queue; -+ } -+ } -+ -+ i = 0; -+ for_each_online_cpu(cpu) { -+ u8 j; -+ -+ j = i % priv->num_pairs; -+ -+ ppriv = per_cpu_ptr(priv->ppriv, cpu); -+ ppriv->req_fqid = priv->tx_queue_attr[j].fqid; -+ -+ /* -+ * Allow all cores to enqueue, while only some of them -+ * will take part in dequeuing. -+ */ -+ if (++i > priv->num_pairs) -+ continue; -+ -+ ppriv->rsp_fqid = priv->rx_queue_attr[j].fqid; -+ ppriv->prio = j; -+ -+ dev_info(dev, "pair %d: rx queue %d, tx queue %d\n", j, -+ priv->rx_queue_attr[j].fqid, -+ priv->tx_queue_attr[j].fqid); -+ -+ ppriv->net_dev.dev = *dev; -+ INIT_LIST_HEAD(&ppriv->net_dev.napi_list); -+ netif_napi_add(&ppriv->net_dev, &ppriv->napi, dpaa2_dpseci_poll, -+ DPAA2_CAAM_NAPI_WEIGHT); -+ } -+ -+ return 0; -+ -+err_get_rx_queue: -+ dpaa2_dpseci_congestion_free(priv); -+err_get_vers: -+ dpseci_close(priv->mc_io, 0, ls_dev->mc_handle); -+err_open: -+ return err; -+} -+ -+static int dpaa2_dpseci_enable(struct dpaa2_caam_priv *priv) -+{ -+ struct device *dev = priv->dev; -+ struct fsl_mc_device *ls_dev = to_fsl_mc_device(dev); -+ struct dpaa2_caam_priv_per_cpu *ppriv; -+ int err, i; -+ -+ for (i = 0; i < priv->num_pairs; i++) { -+ ppriv = per_cpu_ptr(priv->ppriv, i); -+ napi_enable(&ppriv->napi); -+ } -+ -+ err = dpseci_enable(priv->mc_io, 0, ls_dev->mc_handle); -+ if (err) { -+ dev_err(dev, "dpseci_enable() failed\n"); -+ return err; -+ } -+ -+ dev_info(dev, "DPSECI version %d.%d\n", -+ priv->major_ver, -+ priv->minor_ver); -+ -+ return 0; -+} -+ -+static int __cold dpaa2_dpseci_disable(struct dpaa2_caam_priv *priv) -+{ -+ struct device *dev = priv->dev; -+ struct dpaa2_caam_priv_per_cpu *ppriv; -+ struct fsl_mc_device *ls_dev = to_fsl_mc_device(dev); -+ int i, err = 0, enabled; -+ -+ err = dpseci_disable(priv->mc_io, 0, ls_dev->mc_handle); -+ if (err) { -+ dev_err(dev, "dpseci_disable() failed\n"); -+ return err; -+ } -+ -+ err = dpseci_is_enabled(priv->mc_io, 0, ls_dev->mc_handle, &enabled); -+ if (err) { -+ dev_err(dev, "dpseci_is_enabled() failed\n"); -+ return err; -+ } -+ -+ dev_dbg(dev, "disable: %s\n", enabled ? "false" : "true"); -+ -+ for (i = 0; i < priv->num_pairs; i++) { -+ ppriv = per_cpu_ptr(priv->ppriv, i); -+ napi_disable(&ppriv->napi); -+ netif_napi_del(&ppriv->napi); -+ } -+ -+ return 0; -+} -+ -+static struct list_head hash_list; -+ -+static int dpaa2_caam_probe(struct fsl_mc_device *dpseci_dev) -+{ -+ struct device *dev; -+ struct dpaa2_caam_priv *priv; -+ int i, err = 0; -+ bool registered = false; -+ -+ /* -+ * There is no way to get CAAM endianness - there is no direct register -+ * space access and MC f/w does not provide this attribute. -+ * All DPAA2-based SoCs have little endian CAAM, thus hard-code this -+ * property. -+ */ -+ caam_little_end = true; -+ -+ caam_imx = false; -+ -+ dev = &dpseci_dev->dev; -+ -+ priv = kzalloc(sizeof(*priv), GFP_KERNEL); -+ if (!priv) -+ return -ENOMEM; -+ -+ dev_set_drvdata(dev, priv); -+ -+ priv->domain = iommu_get_domain_for_dev(dev); -+ -+ qi_cache = kmem_cache_create("dpaa2_caamqicache", CAAM_QI_MEMCACHE_SIZE, -+ 0, SLAB_CACHE_DMA, NULL); -+ if (!qi_cache) { -+ dev_err(dev, "Can't allocate SEC cache\n"); -+ err = -ENOMEM; -+ goto err_qicache; -+ } -+ -+ err = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(49)); -+ if (err) { -+ dev_err(dev, "dma_set_mask_and_coherent() failed\n"); -+ goto err_dma_mask; -+ } -+ -+ /* Obtain a MC portal */ -+ err = fsl_mc_portal_allocate(dpseci_dev, 0, &priv->mc_io); -+ if (err) { -+ if (err == -ENXIO) -+ err = -EPROBE_DEFER; -+ else -+ dev_err(dev, "MC portal allocation failed\n"); -+ -+ goto err_dma_mask; -+ } -+ -+ priv->ppriv = alloc_percpu(*priv->ppriv); -+ if (!priv->ppriv) { -+ dev_err(dev, "alloc_percpu() failed\n"); -+ err = -ENOMEM; -+ goto err_alloc_ppriv; -+ } -+ -+ /* DPSECI initialization */ -+ err = dpaa2_dpseci_setup(dpseci_dev); -+ if (err) { -+ dev_err(dev, "dpaa2_dpseci_setup() failed\n"); -+ goto err_dpseci_setup; -+ } -+ -+ /* DPIO */ -+ err = dpaa2_dpseci_dpio_setup(priv); -+ if (err) { -+ if (err != -EPROBE_DEFER) -+ dev_err(dev, "dpaa2_dpseci_dpio_setup() failed\n"); -+ goto err_dpio_setup; -+ } -+ -+ /* DPSECI binding to DPIO */ -+ err = dpaa2_dpseci_bind(priv); -+ if (err) { -+ dev_err(dev, "dpaa2_dpseci_bind() failed\n"); -+ goto err_bind; -+ } -+ -+ /* DPSECI enable */ -+ err = dpaa2_dpseci_enable(priv); -+ if (err) { -+ dev_err(dev, "dpaa2_dpseci_enable() failed"); -+ goto err_bind; -+ } -+ -+ /* register crypto algorithms the device supports */ -+ for (i = 0; i < ARRAY_SIZE(driver_algs); i++) { -+ struct caam_skcipher_alg *t_alg = driver_algs + i; -+ u32 alg_sel = t_alg->caam.class1_alg_type & OP_ALG_ALGSEL_MASK; -+ -+ /* Skip DES algorithms if not supported by device */ -+ if (!priv->sec_attr.des_acc_num && -+ ((alg_sel == OP_ALG_ALGSEL_3DES) || -+ (alg_sel == OP_ALG_ALGSEL_DES))) -+ continue; -+ -+ /* Skip AES algorithms if not supported by device */ -+ if (!priv->sec_attr.aes_acc_num && -+ (alg_sel == OP_ALG_ALGSEL_AES)) -+ continue; -+ -+ /* Skip CHACHA20 algorithms if not supported by device */ -+ if (alg_sel == OP_ALG_ALGSEL_CHACHA20 && -+ !priv->sec_attr.ccha_acc_num) -+ continue; -+ -+ t_alg->caam.dev = dev; -+ caam_skcipher_alg_init(t_alg); -+ -+ err = crypto_register_skcipher(&t_alg->skcipher); -+ if (err) { -+ dev_warn(dev, "%s alg registration failed: %d\n", -+ t_alg->skcipher.base.cra_driver_name, err); -+ continue; -+ } -+ -+ t_alg->registered = true; -+ registered = true; -+ } -+ -+ for (i = 0; i < ARRAY_SIZE(driver_aeads); i++) { -+ struct caam_aead_alg *t_alg = driver_aeads + i; -+ u32 c1_alg_sel = t_alg->caam.class1_alg_type & -+ OP_ALG_ALGSEL_MASK; -+ u32 c2_alg_sel = t_alg->caam.class2_alg_type & -+ OP_ALG_ALGSEL_MASK; -+ -+ /* Skip DES algorithms if not supported by device */ -+ if (!priv->sec_attr.des_acc_num && -+ ((c1_alg_sel == OP_ALG_ALGSEL_3DES) || -+ (c1_alg_sel == OP_ALG_ALGSEL_DES))) -+ continue; -+ -+ /* Skip AES algorithms if not supported by device */ -+ if (!priv->sec_attr.aes_acc_num && -+ (c1_alg_sel == OP_ALG_ALGSEL_AES)) -+ continue; -+ -+ /* Skip CHACHA20 algorithms if not supported by device */ -+ if (c1_alg_sel == OP_ALG_ALGSEL_CHACHA20 && -+ !priv->sec_attr.ccha_acc_num) -+ continue; -+ -+ /* Skip POLY1305 algorithms if not supported by device */ -+ if (c2_alg_sel == OP_ALG_ALGSEL_POLY1305 && -+ !priv->sec_attr.ptha_acc_num) -+ continue; -+ -+ /* -+ * Skip algorithms requiring message digests -+ * if MD not supported by device. -+ */ -+ if ((c2_alg_sel & ~OP_ALG_ALGSEL_SUBMASK) == 0x40 && -+ !priv->sec_attr.md_acc_num) -+ continue; -+ -+ t_alg->caam.dev = dev; -+ caam_aead_alg_init(t_alg); -+ -+ err = crypto_register_aead(&t_alg->aead); -+ if (err) { -+ dev_warn(dev, "%s alg registration failed: %d\n", -+ t_alg->aead.base.cra_driver_name, err); -+ continue; -+ } -+ -+ t_alg->registered = true; -+ registered = true; -+ } -+ if (registered) -+ dev_info(dev, "algorithms registered in /proc/crypto\n"); -+ -+ /* register hash algorithms the device supports */ -+ INIT_LIST_HEAD(&hash_list); -+ -+ /* -+ * Skip registration of any hashing algorithms if MD block -+ * is not present. -+ */ -+ if (!priv->sec_attr.md_acc_num) -+ return 0; -+ -+ for (i = 0; i < ARRAY_SIZE(driver_hash); i++) { -+ struct caam_hash_alg *t_alg; -+ struct caam_hash_template *alg = driver_hash + i; -+ -+ /* register hmac version */ -+ t_alg = caam_hash_alloc(dev, alg, true); -+ if (IS_ERR(t_alg)) { -+ err = PTR_ERR(t_alg); -+ dev_warn(dev, "%s hash alg allocation failed: %d\n", -+ alg->driver_name, err); -+ continue; -+ } -+ -+ err = crypto_register_ahash(&t_alg->ahash_alg); -+ if (err) { -+ dev_warn(dev, "%s alg registration failed: %d\n", -+ t_alg->ahash_alg.halg.base.cra_driver_name, -+ err); -+ kfree(t_alg); -+ } else { -+ list_add_tail(&t_alg->entry, &hash_list); -+ } -+ -+ /* register unkeyed version */ -+ t_alg = caam_hash_alloc(dev, alg, false); -+ if (IS_ERR(t_alg)) { -+ err = PTR_ERR(t_alg); -+ dev_warn(dev, "%s alg allocation failed: %d\n", -+ alg->driver_name, err); -+ continue; -+ } -+ -+ err = crypto_register_ahash(&t_alg->ahash_alg); -+ if (err) { -+ dev_warn(dev, "%s alg registration failed: %d\n", -+ t_alg->ahash_alg.halg.base.cra_driver_name, -+ err); -+ kfree(t_alg); -+ } else { -+ list_add_tail(&t_alg->entry, &hash_list); -+ } -+ } -+ if (!list_empty(&hash_list)) -+ dev_info(dev, "hash algorithms registered in /proc/crypto\n"); -+ -+ return err; -+ -+err_bind: -+ dpaa2_dpseci_dpio_free(priv); -+err_dpio_setup: -+ dpaa2_dpseci_free(priv); -+err_dpseci_setup: -+ free_percpu(priv->ppriv); -+err_alloc_ppriv: -+ fsl_mc_portal_free(priv->mc_io); -+err_dma_mask: -+ kmem_cache_destroy(qi_cache); -+err_qicache: -+ dev_set_drvdata(dev, NULL); -+ -+ return err; -+} -+ -+static int __cold dpaa2_caam_remove(struct fsl_mc_device *ls_dev) -+{ -+ struct device *dev; -+ struct dpaa2_caam_priv *priv; -+ int i; -+ -+ dev = &ls_dev->dev; -+ priv = dev_get_drvdata(dev); -+ -+ for (i = 0; i < ARRAY_SIZE(driver_aeads); i++) { -+ struct caam_aead_alg *t_alg = driver_aeads + i; -+ -+ if (t_alg->registered) -+ crypto_unregister_aead(&t_alg->aead); -+ } -+ -+ for (i = 0; i < ARRAY_SIZE(driver_algs); i++) { -+ struct caam_skcipher_alg *t_alg = driver_algs + i; -+ -+ if (t_alg->registered) -+ crypto_unregister_skcipher(&t_alg->skcipher); -+ } -+ -+ if (hash_list.next) { -+ struct caam_hash_alg *t_hash_alg, *p; -+ -+ list_for_each_entry_safe(t_hash_alg, p, &hash_list, entry) { -+ crypto_unregister_ahash(&t_hash_alg->ahash_alg); -+ list_del(&t_hash_alg->entry); -+ kfree(t_hash_alg); -+ } -+ } -+ -+ dpaa2_dpseci_disable(priv); -+ dpaa2_dpseci_dpio_free(priv); -+ dpaa2_dpseci_free(priv); -+ free_percpu(priv->ppriv); -+ fsl_mc_portal_free(priv->mc_io); -+ dev_set_drvdata(dev, NULL); -+ kmem_cache_destroy(qi_cache); -+ -+ return 0; -+} -+ -+int dpaa2_caam_enqueue(struct device *dev, struct caam_request *req) -+{ -+ struct dpaa2_fd fd; -+ struct dpaa2_caam_priv *priv = dev_get_drvdata(dev); -+ struct dpaa2_caam_priv_per_cpu *ppriv; -+ int err = 0, i; -+ -+ if (IS_ERR(req)) -+ return PTR_ERR(req); -+ -+ if (priv->cscn_mem) { -+ dma_sync_single_for_cpu(priv->dev, priv->cscn_dma, -+ DPAA2_CSCN_SIZE, -+ DMA_FROM_DEVICE); -+ if (unlikely(dpaa2_cscn_state_congested(priv->cscn_mem_aligned))) { -+ dev_dbg_ratelimited(dev, "Dropping request\n"); -+ return -EBUSY; -+ } -+ } -+ -+ dpaa2_fl_set_flc(&req->fd_flt[1], req->flc_dma); -+ -+ req->fd_flt_dma = dma_map_single(dev, req->fd_flt, sizeof(req->fd_flt), -+ DMA_BIDIRECTIONAL); -+ if (dma_mapping_error(dev, req->fd_flt_dma)) { -+ dev_err(dev, "DMA mapping error for QI enqueue request\n"); -+ goto err_out; -+ } -+ -+ memset(&fd, 0, sizeof(fd)); -+ dpaa2_fd_set_format(&fd, dpaa2_fd_list); -+ dpaa2_fd_set_addr(&fd, req->fd_flt_dma); -+ dpaa2_fd_set_len(&fd, dpaa2_fl_get_len(&req->fd_flt[1])); -+ dpaa2_fd_set_flc(&fd, req->flc_dma); -+ -+ ppriv = this_cpu_ptr(priv->ppriv); -+ for (i = 0; i < (priv->dpseci_attr.num_tx_queues << 1); i++) { -+ err = dpaa2_io_service_enqueue_fq(ppriv->dpio, ppriv->req_fqid, -+ &fd); -+ if (err != -EBUSY) -+ break; -+ -+ cpu_relax(); -+ } -+ -+ if (unlikely(err)) { -+ dev_err_ratelimited(dev, "Error enqueuing frame: %d\n", err); -+ goto err_out; -+ } -+ -+ return -EINPROGRESS; -+ -+err_out: -+ dma_unmap_single(dev, req->fd_flt_dma, sizeof(req->fd_flt), -+ DMA_BIDIRECTIONAL); -+ return -EIO; -+} -+EXPORT_SYMBOL(dpaa2_caam_enqueue); -+ -+const struct fsl_mc_device_id dpaa2_caam_match_id_table[] = { -+ { -+ .vendor = FSL_MC_VENDOR_FREESCALE, -+ .obj_type = "dpseci", -+ }, -+ { .vendor = 0x0 } -+}; -+ -+static struct fsl_mc_driver dpaa2_caam_driver = { -+ .driver = { -+ .name = KBUILD_MODNAME, -+ .owner = THIS_MODULE, -+ }, -+ .probe = dpaa2_caam_probe, -+ .remove = dpaa2_caam_remove, -+ .match_id_table = dpaa2_caam_match_id_table -+}; -+ -+MODULE_LICENSE("Dual BSD/GPL"); -+MODULE_AUTHOR("Freescale Semiconductor, Inc"); -+MODULE_DESCRIPTION("Freescale DPAA2 CAAM Driver"); -+ -+module_fsl_mc_driver(dpaa2_caam_driver); ---- /dev/null -+++ b/drivers/crypto/caam/caamalg_qi2.h -@@ -0,0 +1,276 @@ -+/* -+ * Copyright 2015-2016 Freescale Semiconductor Inc. -+ * Copyright 2017 NXP -+ * -+ * Redistribution and use in source and binary forms, with or without -+ * modification, are permitted provided that the following conditions are met: -+ * * Redistributions of source code must retain the above copyright -+ * notice, this list of conditions and the following disclaimer. -+ * * Redistributions in binary form must reproduce the above copyright -+ * notice, this list of conditions and the following disclaimer in the -+ * documentation and/or other materials provided with the distribution. -+ * * Neither the names of the above-listed copyright holders nor the -+ * names of any contributors may be used to endorse or promote products -+ * derived from this software without specific prior written permission. -+ * -+ * -+ * ALTERNATIVELY, this software may be distributed under the terms of the -+ * GNU General Public License ("GPL") as published by the Free Software -+ * Foundation, either version 2 of that License or (at your option) any -+ * later version. -+ * -+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE -+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -+ * POSSIBILITY OF SUCH DAMAGE. -+ */ -+ -+#ifndef _CAAMALG_QI2_H_ -+#define _CAAMALG_QI2_H_ -+ -+#include "../../../drivers/staging/fsl-mc/include/dpaa2-io.h" -+#include "../../../drivers/staging/fsl-mc/include/dpaa2-fd.h" -+#include <linux/threads.h> -+#include "dpseci.h" -+#include "desc_constr.h" -+ -+#define DPAA2_CAAM_STORE_SIZE 16 -+/* NAPI weight *must* be a multiple of the store size. */ -+#define DPAA2_CAAM_NAPI_WEIGHT 64 -+ -+/* The congestion entrance threshold was chosen so that on LS2088 -+ * we support the maximum throughput for the available memory -+ */ -+#define DPAA2_SEC_CONG_ENTRY_THRESH (128 * 1024 * 1024) -+#define DPAA2_SEC_CONG_EXIT_THRESH (DPAA2_SEC_CONG_ENTRY_THRESH * 9 / 10) -+ -+/** -+ * dpaa2_caam_priv - driver private data -+ * @dpseci_id: DPSECI object unique ID -+ * @major_ver: DPSECI major version -+ * @minor_ver: DPSECI minor version -+ * @dpseci_attr: DPSECI attributes -+ * @sec_attr: SEC engine attributes -+ * @rx_queue_attr: array of Rx queue attributes -+ * @tx_queue_attr: array of Tx queue attributes -+ * @cscn_mem: pointer to memory region containing the -+ * dpaa2_cscn struct; it's size is larger than -+ * sizeof(struct dpaa2_cscn) to accommodate alignment -+ * @cscn_mem_aligned: pointer to struct dpaa2_cscn; it is computed -+ * as PTR_ALIGN(cscn_mem, DPAA2_CSCN_ALIGN) -+ * @cscn_dma: dma address used by the QMAN to write CSCN messages -+ * @dev: device associated with the DPSECI object -+ * @mc_io: pointer to MC portal's I/O object -+ * @domain: IOMMU domain -+ * @ppriv: per CPU pointers to privata data -+ */ -+struct dpaa2_caam_priv { -+ int dpsec_id; -+ -+ u16 major_ver; -+ u16 minor_ver; -+ -+ struct dpseci_attr dpseci_attr; -+ struct dpseci_sec_attr sec_attr; -+ struct dpseci_rx_queue_attr rx_queue_attr[DPSECI_MAX_QUEUE_NUM]; -+ struct dpseci_tx_queue_attr tx_queue_attr[DPSECI_MAX_QUEUE_NUM]; -+ int num_pairs; -+ -+ /* congestion */ -+ void *cscn_mem; -+ void *cscn_mem_aligned; -+ dma_addr_t cscn_dma; -+ -+ struct device *dev; -+ struct fsl_mc_io *mc_io; -+ struct iommu_domain *domain; -+ -+ struct dpaa2_caam_priv_per_cpu __percpu *ppriv; -+}; -+ -+/** -+ * dpaa2_caam_priv_per_cpu - per CPU private data -+ * @napi: napi structure -+ * @net_dev: netdev used by napi -+ * @req_fqid: (virtual) request (Tx / enqueue) FQID -+ * @rsp_fqid: (virtual) response (Rx / dequeue) FQID -+ * @prio: internal queue number - index for dpaa2_caam_priv.*_queue_attr -+ * @nctx: notification context of response FQ -+ * @store: where dequeued frames are stored -+ * @priv: backpointer to dpaa2_caam_priv -+ * @dpio: portal used for data path operations -+ */ -+struct dpaa2_caam_priv_per_cpu { -+ struct napi_struct napi; -+ struct net_device net_dev; -+ int req_fqid; -+ int rsp_fqid; -+ int prio; -+ struct dpaa2_io_notification_ctx nctx; -+ struct dpaa2_io_store *store; -+ struct dpaa2_caam_priv *priv; -+ struct dpaa2_io *dpio; -+}; -+ -+/* -+ * The CAAM QI hardware constructs a job descriptor which points -+ * to shared descriptor (as pointed by context_a of FQ to CAAM). -+ * When the job descriptor is executed by deco, the whole job -+ * descriptor together with shared descriptor gets loaded in -+ * deco buffer which is 64 words long (each 32-bit). -+ * -+ * The job descriptor constructed by QI hardware has layout: -+ * -+ * HEADER (1 word) -+ * Shdesc ptr (1 or 2 words) -+ * SEQ_OUT_PTR (1 word) -+ * Out ptr (1 or 2 words) -+ * Out length (1 word) -+ * SEQ_IN_PTR (1 word) -+ * In ptr (1 or 2 words) -+ * In length (1 word) -+ * -+ * The shdesc ptr is used to fetch shared descriptor contents -+ * into deco buffer. -+ * -+ * Apart from shdesc contents, the total number of words that -+ * get loaded in deco buffer are '8' or '11'. The remaining words -+ * in deco buffer can be used for storing shared descriptor. -+ */ -+#define MAX_SDLEN ((CAAM_DESC_BYTES_MAX - DESC_JOB_IO_LEN) / CAAM_CMD_SZ) -+ -+/* Length of a single buffer in the QI driver memory cache */ -+#define CAAM_QI_MEMCACHE_SIZE 512 -+ -+/* -+ * aead_edesc - s/w-extended aead descriptor -+ * @src_nents: number of segments in input scatterlist -+ * @dst_nents: number of segments in output scatterlist -+ * @iv_dma: dma address of iv for checking continuity and link table -+ * @qm_sg_bytes: length of dma mapped h/w link table -+ * @qm_sg_dma: bus physical mapped address of h/w link table -+ * @assoclen: associated data length, in CAAM endianness -+ * @assoclen_dma: bus physical mapped address of req->assoclen -+ * @sgt: the h/w link table, followed by IV -+ */ -+struct aead_edesc { -+ int src_nents; -+ int dst_nents; -+ dma_addr_t iv_dma; -+ int qm_sg_bytes; -+ dma_addr_t qm_sg_dma; -+ unsigned int assoclen; -+ dma_addr_t assoclen_dma; -+ struct dpaa2_sg_entry sgt[0]; -+}; -+ -+/* -+ * tls_edesc - s/w-extended tls descriptor -+ * @src_nents: number of segments in input scatterlist -+ * @dst_nents: number of segments in output scatterlist -+ * @iv_dma: dma address of iv for checking continuity and link table -+ * @qm_sg_bytes: length of dma mapped h/w link table -+ * @qm_sg_dma: bus physical mapped address of h/w link table -+ * @tmp: array of scatterlists used by 'scatterwalk_ffwd' -+ * @dst: pointer to output scatterlist, usefull for unmapping -+ * @sgt: the h/w link table, followed by IV -+ */ -+struct tls_edesc { -+ int src_nents; -+ int dst_nents; -+ dma_addr_t iv_dma; -+ int qm_sg_bytes; -+ dma_addr_t qm_sg_dma; -+ struct scatterlist tmp[2]; -+ struct scatterlist *dst; -+ struct dpaa2_sg_entry sgt[0]; -+}; -+ -+/* -+ * skcipher_edesc - s/w-extended skcipher descriptor -+ * @src_nents: number of segments in input scatterlist -+ * @dst_nents: number of segments in output scatterlist -+ * @iv_dma: dma address of iv for checking continuity and link table -+ * @qm_sg_bytes: length of dma mapped qm_sg space -+ * @qm_sg_dma: I/O virtual address of h/w link table -+ * @sgt: the h/w link table, followed by IV -+ */ -+struct skcipher_edesc { -+ int src_nents; -+ int dst_nents; -+ dma_addr_t iv_dma; -+ int qm_sg_bytes; -+ dma_addr_t qm_sg_dma; -+ struct dpaa2_sg_entry sgt[0]; -+}; -+ -+/* -+ * ahash_edesc - s/w-extended ahash descriptor -+ * @dst_dma: I/O virtual address of req->result -+ * @qm_sg_dma: I/O virtual address of h/w link table -+ * @src_nents: number of segments in input scatterlist -+ * @qm_sg_bytes: length of dma mapped qm_sg space -+ * @sgt: pointer to h/w link table -+ */ -+struct ahash_edesc { -+ dma_addr_t dst_dma; -+ dma_addr_t qm_sg_dma; -+ int src_nents; -+ int qm_sg_bytes; -+ struct dpaa2_sg_entry sgt[0]; -+}; -+ -+/** -+ * caam_flc - Flow Context (FLC) -+ * @flc: Flow Context options -+ * @sh_desc: Shared Descriptor -+ */ -+struct caam_flc { -+ u32 flc[16]; -+ u32 sh_desc[MAX_SDLEN]; -+} ____cacheline_aligned; -+ -+enum optype { -+ ENCRYPT = 0, -+ DECRYPT, -+ NUM_OP -+}; -+ -+/** -+ * caam_request - the request structure the driver application should fill while -+ * submitting a job to driver. -+ * @fd_flt: Frame list table defining input and output -+ * fd_flt[0] - FLE pointing to output buffer -+ * fd_flt[1] - FLE pointing to input buffer -+ * @fd_flt_dma: DMA address for the frame list table -+ * @flc: Flow Context -+ * @flc_dma: I/O virtual address of Flow Context -+ * @cbk: Callback function to invoke when job is completed -+ * @ctx: arbit context attached with request by the application -+ * @edesc: extended descriptor; points to one of {skcipher,aead}_edesc -+ */ -+struct caam_request { -+ struct dpaa2_fl_entry fd_flt[2]; -+ dma_addr_t fd_flt_dma; -+ struct caam_flc *flc; -+ dma_addr_t flc_dma; -+ void (*cbk)(void *ctx, u32 err); -+ void *ctx; -+ void *edesc; -+}; -+ -+/** -+ * dpaa2_caam_enqueue() - enqueue a crypto request -+ * @dev: device associated with the DPSECI object -+ * @req: pointer to caam_request -+ */ -+int dpaa2_caam_enqueue(struct device *dev, struct caam_request *req); -+ -+#endif /* _CAAMALG_QI2_H_ */ ---- a/drivers/crypto/caam/caamhash.c -+++ b/drivers/crypto/caam/caamhash.c -@@ -2,6 +2,7 @@ - * caam - Freescale FSL CAAM support for ahash functions of crypto API - * - * Copyright 2011 Freescale Semiconductor, Inc. -+ * Copyright 2018 NXP - * - * Based on caamalg.c crypto API driver. - * -@@ -62,6 +63,7 @@ - #include "error.h" - #include "sg_sw_sec4.h" - #include "key_gen.h" -+#include "caamhash_desc.h" - - #define CAAM_CRA_PRIORITY 3000 - -@@ -71,14 +73,6 @@ - #define CAAM_MAX_HASH_BLOCK_SIZE SHA512_BLOCK_SIZE - #define CAAM_MAX_HASH_DIGEST_SIZE SHA512_DIGEST_SIZE - --/* length of descriptors text */ --#define DESC_AHASH_BASE (3 * CAAM_CMD_SZ) --#define DESC_AHASH_UPDATE_LEN (6 * CAAM_CMD_SZ) --#define DESC_AHASH_UPDATE_FIRST_LEN (DESC_AHASH_BASE + 4 * CAAM_CMD_SZ) --#define DESC_AHASH_FINAL_LEN (DESC_AHASH_BASE + 5 * CAAM_CMD_SZ) --#define DESC_AHASH_FINUP_LEN (DESC_AHASH_BASE + 5 * CAAM_CMD_SZ) --#define DESC_AHASH_DIGEST_LEN (DESC_AHASH_BASE + 4 * CAAM_CMD_SZ) -- - #define DESC_HASH_MAX_USED_BYTES (DESC_AHASH_FINAL_LEN + \ - CAAM_MAX_HASH_KEY_SIZE) - #define DESC_HASH_MAX_USED_LEN (DESC_HASH_MAX_USED_BYTES / CAAM_CMD_SZ) -@@ -107,6 +101,7 @@ struct caam_hash_ctx { - dma_addr_t sh_desc_update_first_dma; - dma_addr_t sh_desc_fin_dma; - dma_addr_t sh_desc_digest_dma; -+ enum dma_data_direction dir; - struct device *jrdev; - u8 key[CAAM_MAX_HASH_KEY_SIZE]; - int ctx_len; -@@ -218,7 +213,7 @@ static inline int buf_map_to_sec4_sg(str - } - - /* Map state->caam_ctx, and add it to link table */ --static inline int ctx_map_to_sec4_sg(u32 *desc, struct device *jrdev, -+static inline int ctx_map_to_sec4_sg(struct device *jrdev, - struct caam_hash_state *state, int ctx_len, - struct sec4_sg_entry *sec4_sg, u32 flag) - { -@@ -234,68 +229,22 @@ static inline int ctx_map_to_sec4_sg(u32 - return 0; - } - --/* -- * For ahash update, final and finup (import_ctx = true) -- * import context, read and write to seqout -- * For ahash firsts and digest (import_ctx = false) -- * read and write to seqout -- */ --static inline void ahash_gen_sh_desc(u32 *desc, u32 state, int digestsize, -- struct caam_hash_ctx *ctx, bool import_ctx) --{ -- u32 op = ctx->adata.algtype; -- u32 *skip_key_load; -- -- init_sh_desc(desc, HDR_SHARE_SERIAL); -- -- /* Append key if it has been set; ahash update excluded */ -- if ((state != OP_ALG_AS_UPDATE) && (ctx->adata.keylen)) { -- /* Skip key loading if already shared */ -- skip_key_load = append_jump(desc, JUMP_JSL | JUMP_TEST_ALL | -- JUMP_COND_SHRD); -- -- append_key_as_imm(desc, ctx->key, ctx->adata.keylen_pad, -- ctx->adata.keylen, CLASS_2 | -- KEY_DEST_MDHA_SPLIT | KEY_ENC); -- -- set_jump_tgt_here(desc, skip_key_load); -- -- op |= OP_ALG_AAI_HMAC_PRECOMP; -- } -- -- /* If needed, import context from software */ -- if (import_ctx) -- append_seq_load(desc, ctx->ctx_len, LDST_CLASS_2_CCB | -- LDST_SRCDST_BYTE_CONTEXT); -- -- /* Class 2 operation */ -- append_operation(desc, op | state | OP_ALG_ENCRYPT); -- -- /* -- * Load from buf and/or src and write to req->result or state->context -- * Calculate remaining bytes to read -- */ -- append_math_add(desc, VARSEQINLEN, SEQINLEN, REG0, CAAM_CMD_SZ); -- /* Read remaining bytes */ -- append_seq_fifo_load(desc, 0, FIFOLD_CLASS_CLASS2 | FIFOLD_TYPE_LAST2 | -- FIFOLD_TYPE_MSG | KEY_VLF); -- /* Store class2 context bytes */ -- append_seq_store(desc, digestsize, LDST_CLASS_2_CCB | -- LDST_SRCDST_BYTE_CONTEXT); --} -- - static int ahash_set_sh_desc(struct crypto_ahash *ahash) - { - struct caam_hash_ctx *ctx = crypto_ahash_ctx(ahash); - int digestsize = crypto_ahash_digestsize(ahash); - struct device *jrdev = ctx->jrdev; -+ struct caam_drv_private *ctrlpriv = dev_get_drvdata(jrdev->parent); - u32 *desc; - -+ ctx->adata.key_virt = ctx->key; -+ - /* ahash_update shared descriptor */ - desc = ctx->sh_desc_update; -- ahash_gen_sh_desc(desc, OP_ALG_AS_UPDATE, ctx->ctx_len, ctx, true); -+ cnstr_shdsc_ahash(desc, &ctx->adata, OP_ALG_AS_UPDATE, ctx->ctx_len, -+ ctx->ctx_len, true, ctrlpriv->era); - dma_sync_single_for_device(jrdev, ctx->sh_desc_update_dma, -- desc_bytes(desc), DMA_TO_DEVICE); -+ desc_bytes(desc), ctx->dir); - #ifdef DEBUG - print_hex_dump(KERN_ERR, - "ahash update shdesc@"__stringify(__LINE__)": ", -@@ -304,9 +253,10 @@ static int ahash_set_sh_desc(struct cryp - - /* ahash_update_first shared descriptor */ - desc = ctx->sh_desc_update_first; -- ahash_gen_sh_desc(desc, OP_ALG_AS_INIT, ctx->ctx_len, ctx, false); -+ cnstr_shdsc_ahash(desc, &ctx->adata, OP_ALG_AS_INIT, ctx->ctx_len, -+ ctx->ctx_len, false, ctrlpriv->era); - dma_sync_single_for_device(jrdev, ctx->sh_desc_update_first_dma, -- desc_bytes(desc), DMA_TO_DEVICE); -+ desc_bytes(desc), ctx->dir); - #ifdef DEBUG - print_hex_dump(KERN_ERR, - "ahash update first shdesc@"__stringify(__LINE__)": ", -@@ -315,9 +265,10 @@ static int ahash_set_sh_desc(struct cryp - - /* ahash_final shared descriptor */ - desc = ctx->sh_desc_fin; -- ahash_gen_sh_desc(desc, OP_ALG_AS_FINALIZE, digestsize, ctx, true); -+ cnstr_shdsc_ahash(desc, &ctx->adata, OP_ALG_AS_FINALIZE, digestsize, -+ ctx->ctx_len, true, ctrlpriv->era); - dma_sync_single_for_device(jrdev, ctx->sh_desc_fin_dma, -- desc_bytes(desc), DMA_TO_DEVICE); -+ desc_bytes(desc), ctx->dir); - #ifdef DEBUG - print_hex_dump(KERN_ERR, "ahash final shdesc@"__stringify(__LINE__)": ", - DUMP_PREFIX_ADDRESS, 16, 4, desc, -@@ -326,9 +277,10 @@ static int ahash_set_sh_desc(struct cryp - - /* ahash_digest shared descriptor */ - desc = ctx->sh_desc_digest; -- ahash_gen_sh_desc(desc, OP_ALG_AS_INITFINAL, digestsize, ctx, false); -+ cnstr_shdsc_ahash(desc, &ctx->adata, OP_ALG_AS_INITFINAL, digestsize, -+ ctx->ctx_len, false, ctrlpriv->era); - dma_sync_single_for_device(jrdev, ctx->sh_desc_digest_dma, -- desc_bytes(desc), DMA_TO_DEVICE); -+ desc_bytes(desc), ctx->dir); - #ifdef DEBUG - print_hex_dump(KERN_ERR, - "ahash digest shdesc@"__stringify(__LINE__)": ", -@@ -421,6 +373,7 @@ static int ahash_setkey(struct crypto_ah - struct caam_hash_ctx *ctx = crypto_ahash_ctx(ahash); - int blocksize = crypto_tfm_alg_blocksize(&ahash->base); - int digestsize = crypto_ahash_digestsize(ahash); -+ struct caam_drv_private *ctrlpriv = dev_get_drvdata(ctx->jrdev->parent); - int ret; - u8 *hashed_key = NULL; - -@@ -441,16 +394,26 @@ static int ahash_setkey(struct crypto_ah - key = hashed_key; - } - -- ret = gen_split_key(ctx->jrdev, ctx->key, &ctx->adata, key, keylen, -- CAAM_MAX_HASH_KEY_SIZE); -- if (ret) -- goto bad_free_key; -+ /* -+ * If DKP is supported, use it in the shared descriptor to generate -+ * the split key. -+ */ -+ if (ctrlpriv->era >= 6) { -+ ctx->adata.key_inline = true; -+ ctx->adata.keylen = keylen; -+ ctx->adata.keylen_pad = split_key_len(ctx->adata.algtype & -+ OP_ALG_ALGSEL_MASK); - --#ifdef DEBUG -- print_hex_dump(KERN_ERR, "ctx.key@"__stringify(__LINE__)": ", -- DUMP_PREFIX_ADDRESS, 16, 4, ctx->key, -- ctx->adata.keylen_pad, 1); --#endif -+ if (ctx->adata.keylen_pad > CAAM_MAX_HASH_KEY_SIZE) -+ goto bad_free_key; -+ -+ memcpy(ctx->key, key, keylen); -+ } else { -+ ret = gen_split_key(ctx->jrdev, ctx->key, &ctx->adata, key, -+ keylen, CAAM_MAX_HASH_KEY_SIZE); -+ if (ret) -+ goto bad_free_key; -+ } - - kfree(hashed_key); - return ahash_set_sh_desc(ahash); -@@ -773,7 +736,7 @@ static int ahash_update_ctx(struct ahash - edesc->src_nents = src_nents; - edesc->sec4_sg_bytes = sec4_sg_bytes; - -- ret = ctx_map_to_sec4_sg(desc, jrdev, state, ctx->ctx_len, -+ ret = ctx_map_to_sec4_sg(jrdev, state, ctx->ctx_len, - edesc->sec4_sg, DMA_BIDIRECTIONAL); - if (ret) - goto unmap_ctx; -@@ -871,9 +834,8 @@ static int ahash_final_ctx(struct ahash_ - desc = edesc->hw_desc; - - edesc->sec4_sg_bytes = sec4_sg_bytes; -- edesc->src_nents = 0; - -- ret = ctx_map_to_sec4_sg(desc, jrdev, state, ctx->ctx_len, -+ ret = ctx_map_to_sec4_sg(jrdev, state, ctx->ctx_len, - edesc->sec4_sg, DMA_TO_DEVICE); - if (ret) - goto unmap_ctx; -@@ -967,7 +929,7 @@ static int ahash_finup_ctx(struct ahash_ - - edesc->src_nents = src_nents; - -- ret = ctx_map_to_sec4_sg(desc, jrdev, state, ctx->ctx_len, -+ ret = ctx_map_to_sec4_sg(jrdev, state, ctx->ctx_len, - edesc->sec4_sg, DMA_TO_DEVICE); - if (ret) - goto unmap_ctx; -@@ -1126,7 +1088,6 @@ static int ahash_final_no_ctx(struct aha - dev_err(jrdev, "unable to map dst\n"); - goto unmap; - } -- edesc->src_nents = 0; - - #ifdef DEBUG - print_hex_dump(KERN_ERR, "jobdesc@"__stringify(__LINE__)": ", -@@ -1208,7 +1169,6 @@ static int ahash_update_no_ctx(struct ah - - edesc->src_nents = src_nents; - edesc->sec4_sg_bytes = sec4_sg_bytes; -- edesc->dst_dma = 0; - - ret = buf_map_to_sec4_sg(jrdev, edesc->sec4_sg, state); - if (ret) -@@ -1420,7 +1380,6 @@ static int ahash_update_first(struct aha - } - - edesc->src_nents = src_nents; -- edesc->dst_dma = 0; - - ret = ahash_edesc_add_src(ctx, edesc, req, mapped_nents, 0, 0, - to_hash); -@@ -1722,6 +1681,7 @@ static int caam_hash_cra_init(struct cry - HASH_MSG_LEN + 64, - HASH_MSG_LEN + SHA512_DIGEST_SIZE }; - dma_addr_t dma_addr; -+ struct caam_drv_private *priv; - - /* - * Get a Job ring from Job Ring driver to ensure in-order -@@ -1733,10 +1693,13 @@ static int caam_hash_cra_init(struct cry - return PTR_ERR(ctx->jrdev); - } - -+ priv = dev_get_drvdata(ctx->jrdev->parent); -+ ctx->dir = priv->era >= 6 ? DMA_BIDIRECTIONAL : DMA_TO_DEVICE; -+ - dma_addr = dma_map_single_attrs(ctx->jrdev, ctx->sh_desc_update, - offsetof(struct caam_hash_ctx, - sh_desc_update_dma), -- DMA_TO_DEVICE, DMA_ATTR_SKIP_CPU_SYNC); -+ ctx->dir, DMA_ATTR_SKIP_CPU_SYNC); - if (dma_mapping_error(ctx->jrdev, dma_addr)) { - dev_err(ctx->jrdev, "unable to map shared descriptors\n"); - caam_jr_free(ctx->jrdev); -@@ -1771,11 +1734,11 @@ static void caam_hash_cra_exit(struct cr - dma_unmap_single_attrs(ctx->jrdev, ctx->sh_desc_update_dma, - offsetof(struct caam_hash_ctx, - sh_desc_update_dma), -- DMA_TO_DEVICE, DMA_ATTR_SKIP_CPU_SYNC); -+ ctx->dir, DMA_ATTR_SKIP_CPU_SYNC); - caam_jr_free(ctx->jrdev); - } - --static void __exit caam_algapi_hash_exit(void) -+void caam_algapi_hash_exit(void) - { - struct caam_hash_alg *t_alg, *n; - -@@ -1834,56 +1797,38 @@ caam_hash_alloc(struct caam_hash_templat - return t_alg; - } - --static int __init caam_algapi_hash_init(void) -+int caam_algapi_hash_init(struct device *ctrldev) - { -- struct device_node *dev_node; -- struct platform_device *pdev; -- struct device *ctrldev; - int i = 0, err = 0; -- struct caam_drv_private *priv; -+ struct caam_drv_private *priv = dev_get_drvdata(ctrldev); - unsigned int md_limit = SHA512_DIGEST_SIZE; -- u32 cha_inst, cha_vid; -- -- dev_node = of_find_compatible_node(NULL, NULL, "fsl,sec-v4.0"); -- if (!dev_node) { -- dev_node = of_find_compatible_node(NULL, NULL, "fsl,sec4.0"); -- if (!dev_node) -- return -ENODEV; -- } -- -- pdev = of_find_device_by_node(dev_node); -- if (!pdev) { -- of_node_put(dev_node); -- return -ENODEV; -- } -- -- ctrldev = &pdev->dev; -- priv = dev_get_drvdata(ctrldev); -- of_node_put(dev_node); -- -- /* -- * If priv is NULL, it's probably because the caam driver wasn't -- * properly initialized (e.g. RNG4 init failed). Thus, bail out here. -- */ -- if (!priv) -- return -ENODEV; -+ u32 md_inst, md_vid; - - /* - * Register crypto algorithms the device supports. First, identify - * presence and attributes of MD block. - */ -- cha_vid = rd_reg32(&priv->ctrl->perfmon.cha_id_ls); -- cha_inst = rd_reg32(&priv->ctrl->perfmon.cha_num_ls); -+ if (priv->era < 10) { -+ md_vid = (rd_reg32(&priv->ctrl->perfmon.cha_id_ls) & -+ CHA_ID_LS_MD_MASK) >> CHA_ID_LS_MD_SHIFT; -+ md_inst = (rd_reg32(&priv->ctrl->perfmon.cha_num_ls) & -+ CHA_ID_LS_MD_MASK) >> CHA_ID_LS_MD_SHIFT; -+ } else { -+ u32 mdha = rd_reg32(&priv->ctrl->vreg.mdha); -+ -+ md_vid = (mdha & CHA_VER_VID_MASK) >> CHA_VER_VID_SHIFT; -+ md_inst = mdha & CHA_VER_NUM_MASK; -+ } - - /* - * Skip registration of any hashing algorithms if MD block - * is not present. - */ -- if (!((cha_inst & CHA_ID_LS_MD_MASK) >> CHA_ID_LS_MD_SHIFT)) -+ if (!md_inst) - return -ENODEV; - - /* Limit digest size based on LP256 */ -- if ((cha_vid & CHA_ID_LS_MD_MASK) == CHA_ID_LS_MD_LP256) -+ if (md_vid == CHA_VER_VID_MD_LP256) - md_limit = SHA256_DIGEST_SIZE; - - INIT_LIST_HEAD(&hash_list); -@@ -1934,10 +1879,3 @@ static int __init caam_algapi_hash_init( - - return err; - } -- --module_init(caam_algapi_hash_init); --module_exit(caam_algapi_hash_exit); -- --MODULE_LICENSE("GPL"); --MODULE_DESCRIPTION("FSL CAAM support for ahash functions of crypto API"); --MODULE_AUTHOR("Freescale Semiconductor - NMG"); ---- /dev/null -+++ b/drivers/crypto/caam/caamhash_desc.c -@@ -0,0 +1,108 @@ -+/* -+ * Shared descriptors for ahash algorithms -+ * -+ * Copyright 2017 NXP -+ * -+ * Redistribution and use in source and binary forms, with or without -+ * modification, are permitted provided that the following conditions are met: -+ * * Redistributions of source code must retain the above copyright -+ * notice, this list of conditions and the following disclaimer. -+ * * Redistributions in binary form must reproduce the above copyright -+ * notice, this list of conditions and the following disclaimer in the -+ * documentation and/or other materials provided with the distribution. -+ * * Neither the names of the above-listed copyright holders nor the -+ * names of any contributors may be used to endorse or promote products -+ * derived from this software without specific prior written permission. -+ * -+ * -+ * ALTERNATIVELY, this software may be distributed under the terms of the -+ * GNU General Public License ("GPL") as published by the Free Software -+ * Foundation, either version 2 of that License or (at your option) any -+ * later version. -+ * -+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE -+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -+ * POSSIBILITY OF SUCH DAMAGE. -+ */ -+ -+#include "compat.h" -+#include "desc_constr.h" -+#include "caamhash_desc.h" -+ -+/** -+ * cnstr_shdsc_ahash - ahash shared descriptor -+ * @desc: pointer to buffer used for descriptor construction -+ * @adata: pointer to authentication transform definitions. -+ * A split key is required for SEC Era < 6; the size of the split key -+ * is specified in this case. -+ * Valid algorithm values - one of OP_ALG_ALGSEL_{MD5, SHA1, SHA224, -+ * SHA256, SHA384, SHA512}. -+ * @state: algorithm state OP_ALG_AS_{INIT, FINALIZE, INITFINALIZE, UPDATE} -+ * @digestsize: algorithm's digest size -+ * @ctx_len: size of Context Register -+ * @import_ctx: true if previous Context Register needs to be restored -+ * must be true for ahash update and final -+ * must be false for for ahash first and digest -+ * @era: SEC Era -+ */ -+void cnstr_shdsc_ahash(u32 * const desc, struct alginfo *adata, u32 state, -+ int digestsize, int ctx_len, bool import_ctx, int era) -+{ -+ u32 op = adata->algtype; -+ -+ init_sh_desc(desc, HDR_SHARE_SERIAL); -+ -+ /* Append key if it has been set; ahash update excluded */ -+ if (state != OP_ALG_AS_UPDATE && adata->keylen) { -+ u32 *skip_key_load; -+ -+ /* Skip key loading if already shared */ -+ skip_key_load = append_jump(desc, JUMP_JSL | JUMP_TEST_ALL | -+ JUMP_COND_SHRD); -+ -+ if (era < 6) -+ append_key_as_imm(desc, adata->key_virt, -+ adata->keylen_pad, -+ adata->keylen, CLASS_2 | -+ KEY_DEST_MDHA_SPLIT | KEY_ENC); -+ else -+ append_proto_dkp(desc, adata); -+ -+ set_jump_tgt_here(desc, skip_key_load); -+ -+ op |= OP_ALG_AAI_HMAC_PRECOMP; -+ } -+ -+ /* If needed, import context from software */ -+ if (import_ctx) -+ append_seq_load(desc, ctx_len, LDST_CLASS_2_CCB | -+ LDST_SRCDST_BYTE_CONTEXT); -+ -+ /* Class 2 operation */ -+ append_operation(desc, op | state | OP_ALG_ENCRYPT); -+ -+ /* -+ * Load from buf and/or src and write to req->result or state->context -+ * Calculate remaining bytes to read -+ */ -+ append_math_add(desc, VARSEQINLEN, SEQINLEN, REG0, CAAM_CMD_SZ); -+ /* Read remaining bytes */ -+ append_seq_fifo_load(desc, 0, FIFOLD_CLASS_CLASS2 | FIFOLD_TYPE_LAST2 | -+ FIFOLD_TYPE_MSG | KEY_VLF); -+ /* Store class2 context bytes */ -+ append_seq_store(desc, digestsize, LDST_CLASS_2_CCB | -+ LDST_SRCDST_BYTE_CONTEXT); -+} -+EXPORT_SYMBOL(cnstr_shdsc_ahash); -+ -+MODULE_LICENSE("Dual BSD/GPL"); -+MODULE_DESCRIPTION("FSL CAAM ahash descriptors support"); -+MODULE_AUTHOR("NXP Semiconductors"); ---- /dev/null -+++ b/drivers/crypto/caam/caamhash_desc.h -@@ -0,0 +1,49 @@ -+/* -+ * Shared descriptors for ahash algorithms -+ * -+ * Copyright 2017 NXP -+ * -+ * Redistribution and use in source and binary forms, with or without -+ * modification, are permitted provided that the following conditions are met: -+ * * Redistributions of source code must retain the above copyright -+ * notice, this list of conditions and the following disclaimer. -+ * * Redistributions in binary form must reproduce the above copyright -+ * notice, this list of conditions and the following disclaimer in the -+ * documentation and/or other materials provided with the distribution. -+ * * Neither the names of the above-listed copyright holders nor the -+ * names of any contributors may be used to endorse or promote products -+ * derived from this software without specific prior written permission. -+ * -+ * -+ * ALTERNATIVELY, this software may be distributed under the terms of the -+ * GNU General Public License ("GPL") as published by the Free Software -+ * Foundation, either version 2 of that License or (at your option) any -+ * later version. -+ * -+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE -+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -+ * POSSIBILITY OF SUCH DAMAGE. -+ */ -+ -+#ifndef _CAAMHASH_DESC_H_ -+#define _CAAMHASH_DESC_H_ -+ -+/* length of descriptors text */ -+#define DESC_AHASH_BASE (3 * CAAM_CMD_SZ) -+#define DESC_AHASH_UPDATE_LEN (6 * CAAM_CMD_SZ) -+#define DESC_AHASH_UPDATE_FIRST_LEN (DESC_AHASH_BASE + 4 * CAAM_CMD_SZ) -+#define DESC_AHASH_FINAL_LEN (DESC_AHASH_BASE + 5 * CAAM_CMD_SZ) -+#define DESC_AHASH_DIGEST_LEN (DESC_AHASH_BASE + 4 * CAAM_CMD_SZ) -+ -+void cnstr_shdsc_ahash(u32 * const desc, struct alginfo *adata, u32 state, -+ int digestsize, int ctx_len, bool import_ctx, int era); -+ -+#endif /* _CAAMHASH_DESC_H_ */ ---- a/drivers/crypto/caam/caampkc.c -+++ b/drivers/crypto/caam/caampkc.c -@@ -2,6 +2,7 @@ - * caam - Freescale FSL CAAM support for Public Key Cryptography - * - * Copyright 2016 Freescale Semiconductor, Inc. -+ * Copyright 2018 NXP - * - * There is no Shared Descriptor for PKC so that the Job Descriptor must carry - * all the desired key parameters, input and output pointers. -@@ -1017,46 +1018,22 @@ static struct akcipher_alg caam_rsa = { - }; - - /* Public Key Cryptography module initialization handler */ --static int __init caam_pkc_init(void) -+int caam_pkc_init(struct device *ctrldev) - { -- struct device_node *dev_node; -- struct platform_device *pdev; -- struct device *ctrldev; -- struct caam_drv_private *priv; -- u32 cha_inst, pk_inst; -+ struct caam_drv_private *priv = dev_get_drvdata(ctrldev); -+ u32 pk_inst; - int err; - -- dev_node = of_find_compatible_node(NULL, NULL, "fsl,sec-v4.0"); -- if (!dev_node) { -- dev_node = of_find_compatible_node(NULL, NULL, "fsl,sec4.0"); -- if (!dev_node) -- return -ENODEV; -- } -- -- pdev = of_find_device_by_node(dev_node); -- if (!pdev) { -- of_node_put(dev_node); -- return -ENODEV; -- } -- -- ctrldev = &pdev->dev; -- priv = dev_get_drvdata(ctrldev); -- of_node_put(dev_node); -- -- /* -- * If priv is NULL, it's probably because the caam driver wasn't -- * properly initialized (e.g. RNG4 init failed). Thus, bail out here. -- */ -- if (!priv) -- return -ENODEV; -- - /* Determine public key hardware accelerator presence. */ -- cha_inst = rd_reg32(&priv->ctrl->perfmon.cha_num_ls); -- pk_inst = (cha_inst & CHA_ID_LS_PK_MASK) >> CHA_ID_LS_PK_SHIFT; -+ if (priv->era < 10) -+ pk_inst = (rd_reg32(&priv->ctrl->perfmon.cha_num_ls) & -+ CHA_ID_LS_PK_MASK) >> CHA_ID_LS_PK_SHIFT; -+ else -+ pk_inst = rd_reg32(&priv->ctrl->vreg.pkha) & CHA_VER_NUM_MASK; - - /* Do not register algorithms if PKHA is not present. */ - if (!pk_inst) -- return -ENODEV; -+ return 0; - - err = crypto_register_akcipher(&caam_rsa); - if (err) -@@ -1068,14 +1045,7 @@ static int __init caam_pkc_init(void) - return err; - } - --static void __exit caam_pkc_exit(void) -+void caam_pkc_exit(void) - { - crypto_unregister_akcipher(&caam_rsa); - } -- --module_init(caam_pkc_init); --module_exit(caam_pkc_exit); -- --MODULE_LICENSE("Dual BSD/GPL"); --MODULE_DESCRIPTION("FSL CAAM support for PKC functions of crypto API"); --MODULE_AUTHOR("Freescale Semiconductor"); ---- a/drivers/crypto/caam/caamrng.c -+++ b/drivers/crypto/caam/caamrng.c -@@ -2,6 +2,7 @@ - * caam - Freescale FSL CAAM support for hw_random - * - * Copyright 2011 Freescale Semiconductor, Inc. -+ * Copyright 2018 NXP - * - * Based on caamalg.c crypto API driver. - * -@@ -294,49 +295,29 @@ static struct hwrng caam_rng = { - .read = caam_read, - }; - --static void __exit caam_rng_exit(void) -+void caam_rng_exit(void) - { - caam_jr_free(rng_ctx->jrdev); - hwrng_unregister(&caam_rng); - kfree(rng_ctx); - } - --static int __init caam_rng_init(void) -+int caam_rng_init(struct device *ctrldev) - { - struct device *dev; -- struct device_node *dev_node; -- struct platform_device *pdev; -- struct device *ctrldev; -- struct caam_drv_private *priv; -+ u32 rng_inst; -+ struct caam_drv_private *priv = dev_get_drvdata(ctrldev); - int err; - -- dev_node = of_find_compatible_node(NULL, NULL, "fsl,sec-v4.0"); -- if (!dev_node) { -- dev_node = of_find_compatible_node(NULL, NULL, "fsl,sec4.0"); -- if (!dev_node) -- return -ENODEV; -- } -- -- pdev = of_find_device_by_node(dev_node); -- if (!pdev) { -- of_node_put(dev_node); -- return -ENODEV; -- } -- -- ctrldev = &pdev->dev; -- priv = dev_get_drvdata(ctrldev); -- of_node_put(dev_node); -- -- /* -- * If priv is NULL, it's probably because the caam driver wasn't -- * properly initialized (e.g. RNG4 init failed). Thus, bail out here. -- */ -- if (!priv) -- return -ENODEV; -- - /* Check for an instantiated RNG before registration */ -- if (!(rd_reg32(&priv->ctrl->perfmon.cha_num_ls) & CHA_ID_LS_RNG_MASK)) -- return -ENODEV; -+ if (priv->era < 10) -+ rng_inst = (rd_reg32(&priv->ctrl->perfmon.cha_num_ls) & -+ CHA_ID_LS_RNG_MASK) >> CHA_ID_LS_RNG_SHIFT; -+ else -+ rng_inst = rd_reg32(&priv->ctrl->vreg.rng) & CHA_VER_NUM_MASK; -+ -+ if (!rng_inst) -+ return 0; - - dev = caam_jr_alloc(); - if (IS_ERR(dev)) { -@@ -364,10 +345,3 @@ free_caam_alloc: - caam_jr_free(dev); - return err; - } -- --module_init(caam_rng_init); --module_exit(caam_rng_exit); -- --MODULE_LICENSE("GPL"); --MODULE_DESCRIPTION("FSL CAAM support for hw_random API"); --MODULE_AUTHOR("Freescale Semiconductor - NMG"); ---- a/drivers/crypto/caam/compat.h -+++ b/drivers/crypto/caam/compat.h -@@ -17,6 +17,7 @@ - #include <linux/of_platform.h> - #include <linux/dma-mapping.h> - #include <linux/io.h> -+#include <linux/iommu.h> - #include <linux/spinlock.h> - #include <linux/rtnetlink.h> - #include <linux/in.h> -@@ -34,10 +35,13 @@ - #include <crypto/des.h> - #include <crypto/sha.h> - #include <crypto/md5.h> -+#include <crypto/chacha20.h> -+#include <crypto/poly1305.h> - #include <crypto/internal/aead.h> - #include <crypto/authenc.h> - #include <crypto/akcipher.h> - #include <crypto/scatterwalk.h> -+#include <crypto/skcipher.h> - #include <crypto/internal/skcipher.h> - #include <crypto/internal/hash.h> - #include <crypto/internal/rsa.h> ---- a/drivers/crypto/caam/ctrl.c -+++ b/drivers/crypto/caam/ctrl.c -@@ -2,6 +2,7 @@ - * Controller-level driver, kernel property detection, initialization - * - * Copyright 2008-2012 Freescale Semiconductor, Inc. -+ * Copyright 2018 NXP - */ - - #include <linux/device.h> -@@ -16,17 +17,15 @@ - #include "desc_constr.h" - #include "ctrl.h" - --bool caam_little_end; --EXPORT_SYMBOL(caam_little_end); - bool caam_dpaa2; - EXPORT_SYMBOL(caam_dpaa2); --bool caam_imx; --EXPORT_SYMBOL(caam_imx); - - #ifdef CONFIG_CAAM_QI - #include "qi.h" - #endif - -+static struct platform_device *caam_dma_dev; -+ - /* - * i.MX targets tend to have clock control subsystems that can - * enable/disable clocking to our device. -@@ -105,7 +104,7 @@ static inline int run_descriptor_deco0(s - struct caam_ctrl __iomem *ctrl = ctrlpriv->ctrl; - struct caam_deco __iomem *deco = ctrlpriv->deco; - unsigned int timeout = 100000; -- u32 deco_dbg_reg, flags; -+ u32 deco_dbg_reg, deco_state, flags; - int i; - - -@@ -148,13 +147,22 @@ static inline int run_descriptor_deco0(s - timeout = 10000000; - do { - deco_dbg_reg = rd_reg32(&deco->desc_dbg); -+ -+ if (ctrlpriv->era < 10) -+ deco_state = (deco_dbg_reg & DESC_DBG_DECO_STAT_MASK) >> -+ DESC_DBG_DECO_STAT_SHIFT; -+ else -+ deco_state = (rd_reg32(&deco->dbg_exec) & -+ DESC_DER_DECO_STAT_MASK) >> -+ DESC_DER_DECO_STAT_SHIFT; -+ - /* - * If an error occured in the descriptor, then - * the DECO status field will be set to 0x0D - */ -- if ((deco_dbg_reg & DESC_DBG_DECO_STAT_MASK) == -- DESC_DBG_DECO_STAT_HOST_ERR) -+ if (deco_state == DECO_STAT_HOST_ERR) - break; -+ - cpu_relax(); - } while ((deco_dbg_reg & DESC_DBG_DECO_STAT_VALID) && --timeout); - -@@ -316,15 +324,15 @@ static int caam_remove(struct platform_d - of_platform_depopulate(ctrldev); - - #ifdef CONFIG_CAAM_QI -- if (ctrlpriv->qidev) -- caam_qi_shutdown(ctrlpriv->qidev); -+ if (ctrlpriv->qi_init) -+ caam_qi_shutdown(ctrldev); - #endif - - /* - * De-initialize RNG state handles initialized by this driver. -- * In case of DPAA 2.x, RNG is managed by MC firmware. -+ * In case of SoCs with Management Complex, RNG is managed by MC f/w. - */ -- if (!caam_dpaa2 && ctrlpriv->rng4_sh_init) -+ if (!ctrlpriv->mc_en && ctrlpriv->rng4_sh_init) - deinstantiate_rng(ctrldev, ctrlpriv->rng4_sh_init); - - /* Shut down debug views */ -@@ -332,6 +340,9 @@ static int caam_remove(struct platform_d - debugfs_remove_recursive(ctrlpriv->dfs_root); - #endif - -+ if (caam_dma_dev) -+ platform_device_unregister(caam_dma_dev); -+ - /* Unmap controller region */ - iounmap(ctrl); - -@@ -433,6 +444,10 @@ static int caam_probe(struct platform_de - {.family = "Freescale i.MX"}, - {}, - }; -+ static struct platform_device_info caam_dma_pdev_info = { -+ .name = "caam-dma", -+ .id = PLATFORM_DEVID_NONE -+ }; - struct device *dev; - struct device_node *nprop, *np; - struct caam_ctrl __iomem *ctrl; -@@ -442,7 +457,7 @@ static int caam_probe(struct platform_de - struct caam_perfmon *perfmon; - #endif - u32 scfgr, comp_params; -- u32 cha_vid_ls; -+ u8 rng_vid; - int pg_size; - int BLOCK_OFFSET = 0; - -@@ -454,15 +469,54 @@ static int caam_probe(struct platform_de - dev_set_drvdata(dev, ctrlpriv); - nprop = pdev->dev.of_node; - -+ /* Get configuration properties from device tree */ -+ /* First, get register page */ -+ ctrl = of_iomap(nprop, 0); -+ if (!ctrl) { -+ dev_err(dev, "caam: of_iomap() failed\n"); -+ return -ENOMEM; -+ } -+ -+ caam_little_end = !(bool)(rd_reg32(&ctrl->perfmon.status) & -+ (CSTA_PLEND | CSTA_ALT_PLEND)); - caam_imx = (bool)soc_device_match(imx_soc); - -+ comp_params = rd_reg32(&ctrl->perfmon.comp_parms_ms); -+ caam_dpaa2 = !!(comp_params & CTPR_MS_DPAA2); -+ ctrlpriv->qi_present = !!(comp_params & CTPR_MS_QI_MASK); -+ -+#ifdef CONFIG_CAAM_QI -+ /* If (DPAA 1.x) QI present, check whether dependencies are available */ -+ if (ctrlpriv->qi_present && !caam_dpaa2) { -+ ret = qman_is_probed(); -+ if (!ret) { -+ ret = -EPROBE_DEFER; -+ goto iounmap_ctrl; -+ } else if (ret < 0) { -+ dev_err(dev, "failing probe due to qman probe error\n"); -+ ret = -ENODEV; -+ goto iounmap_ctrl; -+ } -+ -+ ret = qman_portals_probed(); -+ if (!ret) { -+ ret = -EPROBE_DEFER; -+ goto iounmap_ctrl; -+ } else if (ret < 0) { -+ dev_err(dev, "failing probe due to qman portals probe error\n"); -+ ret = -ENODEV; -+ goto iounmap_ctrl; -+ } -+ } -+#endif -+ - /* Enable clocking */ - clk = caam_drv_identify_clk(&pdev->dev, "ipg"); - if (IS_ERR(clk)) { - ret = PTR_ERR(clk); - dev_err(&pdev->dev, - "can't identify CAAM ipg clk: %d\n", ret); -- return ret; -+ goto iounmap_ctrl; - } - ctrlpriv->caam_ipg = clk; - -@@ -471,7 +525,7 @@ static int caam_probe(struct platform_de - ret = PTR_ERR(clk); - dev_err(&pdev->dev, - "can't identify CAAM mem clk: %d\n", ret); -- return ret; -+ goto iounmap_ctrl; - } - ctrlpriv->caam_mem = clk; - -@@ -480,7 +534,7 @@ static int caam_probe(struct platform_de - ret = PTR_ERR(clk); - dev_err(&pdev->dev, - "can't identify CAAM aclk clk: %d\n", ret); -- return ret; -+ goto iounmap_ctrl; - } - ctrlpriv->caam_aclk = clk; - -@@ -490,7 +544,7 @@ static int caam_probe(struct platform_de - ret = PTR_ERR(clk); - dev_err(&pdev->dev, - "can't identify CAAM emi_slow clk: %d\n", ret); -- return ret; -+ goto iounmap_ctrl; - } - ctrlpriv->caam_emi_slow = clk; - } -@@ -498,7 +552,7 @@ static int caam_probe(struct platform_de - ret = clk_prepare_enable(ctrlpriv->caam_ipg); - if (ret < 0) { - dev_err(&pdev->dev, "can't enable CAAM ipg clock: %d\n", ret); -- return ret; -+ goto iounmap_ctrl; - } - - ret = clk_prepare_enable(ctrlpriv->caam_mem); -@@ -523,25 +577,10 @@ static int caam_probe(struct platform_de - } - } - -- /* Get configuration properties from device tree */ -- /* First, get register page */ -- ctrl = of_iomap(nprop, 0); -- if (ctrl == NULL) { -- dev_err(dev, "caam: of_iomap() failed\n"); -- ret = -ENOMEM; -- goto disable_caam_emi_slow; -- } -- -- caam_little_end = !(bool)(rd_reg32(&ctrl->perfmon.status) & -- (CSTA_PLEND | CSTA_ALT_PLEND)); -- -- /* Finding the page size for using the CTPR_MS register */ -- comp_params = rd_reg32(&ctrl->perfmon.comp_parms_ms); -- pg_size = (comp_params & CTPR_MS_PG_SZ_MASK) >> CTPR_MS_PG_SZ_SHIFT; -- - /* Allocating the BLOCK_OFFSET based on the supported page size on - * the platform - */ -+ pg_size = (comp_params & CTPR_MS_PG_SZ_MASK) >> CTPR_MS_PG_SZ_SHIFT; - if (pg_size == 0) - BLOCK_OFFSET = PG_SIZE_4K; - else -@@ -563,11 +602,14 @@ static int caam_probe(struct platform_de - /* - * Enable DECO watchdogs and, if this is a PHYS_ADDR_T_64BIT kernel, - * long pointers in master configuration register. -- * In case of DPAA 2.x, Management Complex firmware performs -+ * In case of SoCs with Management Complex, MC f/w performs - * the configuration. - */ -- caam_dpaa2 = !!(comp_params & CTPR_MS_DPAA2); -- if (!caam_dpaa2) -+ np = of_find_compatible_node(NULL, NULL, "fsl,qoriq-mc"); -+ ctrlpriv->mc_en = !!np; -+ of_node_put(np); -+ -+ if (!ctrlpriv->mc_en) - clrsetbits_32(&ctrl->mcr, MCFGR_AWCACHE_MASK | MCFGR_LONG_PTR, - MCFGR_AWCACHE_CACH | MCFGR_AWCACHE_BUFF | - MCFGR_WDENABLE | MCFGR_LARGE_BURST | -@@ -612,14 +654,11 @@ static int caam_probe(struct platform_de - } - if (ret) { - dev_err(dev, "dma_set_mask_and_coherent failed (%d)\n", ret); -- goto iounmap_ctrl; -+ goto disable_caam_emi_slow; - } - -- ret = of_platform_populate(nprop, caam_match, NULL, dev); -- if (ret) { -- dev_err(dev, "JR platform devices creation error\n"); -- goto iounmap_ctrl; -- } -+ ctrlpriv->era = caam_get_era(); -+ ctrlpriv->domain = iommu_get_domain_for_dev(dev); - - #ifdef CONFIG_DEBUG_FS - /* -@@ -633,21 +672,7 @@ static int caam_probe(struct platform_de - ctrlpriv->ctl = debugfs_create_dir("ctl", ctrlpriv->dfs_root); - #endif - -- ring = 0; -- for_each_available_child_of_node(nprop, np) -- if (of_device_is_compatible(np, "fsl,sec-v4.0-job-ring") || -- of_device_is_compatible(np, "fsl,sec4.0-job-ring")) { -- ctrlpriv->jr[ring] = (struct caam_job_ring __iomem __force *) -- ((__force uint8_t *)ctrl + -- (ring + JR_BLOCK_NUMBER) * -- BLOCK_OFFSET -- ); -- ctrlpriv->total_jobrs++; -- ring++; -- } -- - /* Check to see if (DPAA 1.x) QI present. If so, enable */ -- ctrlpriv->qi_present = !!(comp_params & CTPR_MS_QI_MASK); - if (ctrlpriv->qi_present && !caam_dpaa2) { - ctrlpriv->qi = (struct caam_queue_if __iomem __force *) - ((__force uint8_t *)ctrl + -@@ -664,6 +689,25 @@ static int caam_probe(struct platform_de - #endif - } - -+ ret = of_platform_populate(nprop, caam_match, NULL, dev); -+ if (ret) { -+ dev_err(dev, "JR platform devices creation error\n"); -+ goto shutdown_qi; -+ } -+ -+ ring = 0; -+ for_each_available_child_of_node(nprop, np) -+ if (of_device_is_compatible(np, "fsl,sec-v4.0-job-ring") || -+ of_device_is_compatible(np, "fsl,sec4.0-job-ring")) { -+ ctrlpriv->jr[ring] = (struct caam_job_ring __iomem __force *) -+ ((__force uint8_t *)ctrl + -+ (ring + JR_BLOCK_NUMBER) * -+ BLOCK_OFFSET -+ ); -+ ctrlpriv->total_jobrs++; -+ ring++; -+ } -+ - /* If no QI and no rings specified, quit and go home */ - if ((!ctrlpriv->qi_present) && (!ctrlpriv->total_jobrs)) { - dev_err(dev, "no queues configured, terminating\n"); -@@ -671,15 +715,29 @@ static int caam_probe(struct platform_de - goto caam_remove; - } - -- cha_vid_ls = rd_reg32(&ctrl->perfmon.cha_id_ls); -+ caam_dma_pdev_info.parent = dev; -+ caam_dma_pdev_info.dma_mask = dma_get_mask(dev); -+ caam_dma_dev = platform_device_register_full(&caam_dma_pdev_info); -+ if (IS_ERR(caam_dma_dev)) { -+ dev_err(dev, "Unable to create and register caam-dma dev\n"); -+ caam_dma_dev = 0; -+ } else { -+ set_dma_ops(&caam_dma_dev->dev, get_dma_ops(dev)); -+ } -+ -+ if (ctrlpriv->era < 10) -+ rng_vid = (rd_reg32(&ctrl->perfmon.cha_id_ls) & -+ CHA_ID_LS_RNG_MASK) >> CHA_ID_LS_RNG_SHIFT; -+ else -+ rng_vid = (rd_reg32(&ctrl->vreg.rng) & CHA_VER_VID_MASK) >> -+ CHA_VER_VID_SHIFT; - - /* - * If SEC has RNG version >= 4 and RNG state handle has not been - * already instantiated, do RNG instantiation -- * In case of DPAA 2.x, RNG is managed by MC firmware. -+ * In case of SoCs with Management Complex, RNG is managed by MC f/w. - */ -- if (!caam_dpaa2 && -- (cha_vid_ls & CHA_ID_LS_RNG_MASK) >> CHA_ID_LS_RNG_SHIFT >= 4) { -+ if (!ctrlpriv->mc_en && rng_vid >= 4) { - ctrlpriv->rng4_sh_init = - rd_reg32(&ctrl->r4tst[0].rdsta); - /* -@@ -746,10 +804,9 @@ static int caam_probe(struct platform_de - - /* Report "alive" for developer to see */ - dev_info(dev, "device ID = 0x%016llx (Era %d)\n", caam_id, -- caam_get_era()); -- dev_info(dev, "job rings = %d, qi = %d, dpaa2 = %s\n", -- ctrlpriv->total_jobrs, ctrlpriv->qi_present, -- caam_dpaa2 ? "yes" : "no"); -+ ctrlpriv->era); -+ dev_info(dev, "job rings = %d, qi = %d\n", -+ ctrlpriv->total_jobrs, ctrlpriv->qi_present); - - #ifdef CONFIG_DEBUG_FS - debugfs_create_file("rq_dequeued", S_IRUSR | S_IRGRP | S_IROTH, -@@ -816,8 +873,11 @@ caam_remove: - caam_remove(pdev); - return ret; - --iounmap_ctrl: -- iounmap(ctrl); -+shutdown_qi: -+#ifdef CONFIG_CAAM_QI -+ if (ctrlpriv->qi_init) -+ caam_qi_shutdown(dev); -+#endif - disable_caam_emi_slow: - if (ctrlpriv->caam_emi_slow) - clk_disable_unprepare(ctrlpriv->caam_emi_slow); -@@ -827,6 +887,8 @@ disable_caam_mem: - clk_disable_unprepare(ctrlpriv->caam_mem); - disable_caam_ipg: - clk_disable_unprepare(ctrlpriv->caam_ipg); -+iounmap_ctrl: -+ iounmap(ctrl); - return ret; - } - ---- a/drivers/crypto/caam/desc.h -+++ b/drivers/crypto/caam/desc.h -@@ -4,6 +4,7 @@ - * Definitions to support CAAM descriptor instruction generation - * - * Copyright 2008-2011 Freescale Semiconductor, Inc. -+ * Copyright 2018 NXP - */ - - #ifndef DESC_H -@@ -42,6 +43,7 @@ - #define CMD_SEQ_LOAD (0x03 << CMD_SHIFT) - #define CMD_FIFO_LOAD (0x04 << CMD_SHIFT) - #define CMD_SEQ_FIFO_LOAD (0x05 << CMD_SHIFT) -+#define CMD_MOVEB (0x07 << CMD_SHIFT) - #define CMD_STORE (0x0a << CMD_SHIFT) - #define CMD_SEQ_STORE (0x0b << CMD_SHIFT) - #define CMD_FIFO_STORE (0x0c << CMD_SHIFT) -@@ -242,6 +244,7 @@ - #define LDST_SRCDST_WORD_DESCBUF_SHARED (0x42 << LDST_SRCDST_SHIFT) - #define LDST_SRCDST_WORD_DESCBUF_JOB_WE (0x45 << LDST_SRCDST_SHIFT) - #define LDST_SRCDST_WORD_DESCBUF_SHARED_WE (0x46 << LDST_SRCDST_SHIFT) -+#define LDST_SRCDST_WORD_INFO_FIFO_SM (0x71 << LDST_SRCDST_SHIFT) - #define LDST_SRCDST_WORD_INFO_FIFO (0x7a << LDST_SRCDST_SHIFT) - - /* Offset in source/destination */ -@@ -284,6 +287,12 @@ - #define LDLEN_SET_OFIFO_OFFSET_SHIFT 0 - #define LDLEN_SET_OFIFO_OFFSET_MASK (3 << LDLEN_SET_OFIFO_OFFSET_SHIFT) - -+/* Special Length definitions when dst=sm, nfifo-{sm,m} */ -+#define LDLEN_MATH0 0 -+#define LDLEN_MATH1 1 -+#define LDLEN_MATH2 2 -+#define LDLEN_MATH3 3 -+ - /* - * FIFO_LOAD/FIFO_STORE/SEQ_FIFO_LOAD/SEQ_FIFO_STORE - * Command Constructs -@@ -355,6 +364,7 @@ - #define FIFOLD_TYPE_PK_N (0x08 << FIFOLD_TYPE_SHIFT) - #define FIFOLD_TYPE_PK_A (0x0c << FIFOLD_TYPE_SHIFT) - #define FIFOLD_TYPE_PK_B (0x0d << FIFOLD_TYPE_SHIFT) -+#define FIFOLD_TYPE_IFIFO (0x0f << FIFOLD_TYPE_SHIFT) - - /* Other types. Need to OR in last/flush bits as desired */ - #define FIFOLD_TYPE_MSG_MASK (0x38 << FIFOLD_TYPE_SHIFT) -@@ -408,6 +418,7 @@ - #define FIFOST_TYPE_MESSAGE_DATA (0x30 << FIFOST_TYPE_SHIFT) - #define FIFOST_TYPE_RNGSTORE (0x34 << FIFOST_TYPE_SHIFT) - #define FIFOST_TYPE_RNGFIFO (0x35 << FIFOST_TYPE_SHIFT) -+#define FIFOST_TYPE_METADATA (0x3e << FIFOST_TYPE_SHIFT) - #define FIFOST_TYPE_SKIP (0x3f << FIFOST_TYPE_SHIFT) - - /* -@@ -444,6 +455,18 @@ - #define OP_PCLID_DSAVERIFY (0x16 << OP_PCLID_SHIFT) - #define OP_PCLID_RSAENC_PUBKEY (0x18 << OP_PCLID_SHIFT) - #define OP_PCLID_RSADEC_PRVKEY (0x19 << OP_PCLID_SHIFT) -+#define OP_PCLID_DKP_MD5 (0x20 << OP_PCLID_SHIFT) -+#define OP_PCLID_DKP_SHA1 (0x21 << OP_PCLID_SHIFT) -+#define OP_PCLID_DKP_SHA224 (0x22 << OP_PCLID_SHIFT) -+#define OP_PCLID_DKP_SHA256 (0x23 << OP_PCLID_SHIFT) -+#define OP_PCLID_DKP_SHA384 (0x24 << OP_PCLID_SHIFT) -+#define OP_PCLID_DKP_SHA512 (0x25 << OP_PCLID_SHIFT) -+#define OP_PCLID_DKP_RIF_MD5 (0x60 << OP_PCLID_SHIFT) -+#define OP_PCLID_DKP_RIF_SHA1 (0x61 << OP_PCLID_SHIFT) -+#define OP_PCLID_DKP_RIF_SHA224 (0x62 << OP_PCLID_SHIFT) -+#define OP_PCLID_DKP_RIF_SHA256 (0x63 << OP_PCLID_SHIFT) -+#define OP_PCLID_DKP_RIF_SHA384 (0x64 << OP_PCLID_SHIFT) -+#define OP_PCLID_DKP_RIF_SHA512 (0x65 << OP_PCLID_SHIFT) - - /* Assuming OP_TYPE = OP_TYPE_DECAP_PROTOCOL/ENCAP_PROTOCOL */ - #define OP_PCLID_IPSEC (0x01 << OP_PCLID_SHIFT) -@@ -1093,6 +1116,22 @@ - /* MacSec protinfos */ - #define OP_PCL_MACSEC 0x0001 - -+/* Derived Key Protocol (DKP) Protinfo */ -+#define OP_PCL_DKP_SRC_SHIFT 14 -+#define OP_PCL_DKP_SRC_MASK (3 << OP_PCL_DKP_SRC_SHIFT) -+#define OP_PCL_DKP_SRC_IMM (0 << OP_PCL_DKP_SRC_SHIFT) -+#define OP_PCL_DKP_SRC_SEQ (1 << OP_PCL_DKP_SRC_SHIFT) -+#define OP_PCL_DKP_SRC_PTR (2 << OP_PCL_DKP_SRC_SHIFT) -+#define OP_PCL_DKP_SRC_SGF (3 << OP_PCL_DKP_SRC_SHIFT) -+#define OP_PCL_DKP_DST_SHIFT 12 -+#define OP_PCL_DKP_DST_MASK (3 << OP_PCL_DKP_DST_SHIFT) -+#define OP_PCL_DKP_DST_IMM (0 << OP_PCL_DKP_DST_SHIFT) -+#define OP_PCL_DKP_DST_SEQ (1 << OP_PCL_DKP_DST_SHIFT) -+#define OP_PCL_DKP_DST_PTR (2 << OP_PCL_DKP_DST_SHIFT) -+#define OP_PCL_DKP_DST_SGF (3 << OP_PCL_DKP_DST_SHIFT) -+#define OP_PCL_DKP_KEY_SHIFT 0 -+#define OP_PCL_DKP_KEY_MASK (0xfff << OP_PCL_DKP_KEY_SHIFT) -+ - /* PKI unidirectional protocol protinfo bits */ - #define OP_PCL_PKPROT_TEST 0x0008 - #define OP_PCL_PKPROT_DECRYPT 0x0004 -@@ -1105,6 +1144,12 @@ - #define OP_ALG_TYPE_CLASS1 (2 << OP_ALG_TYPE_SHIFT) - #define OP_ALG_TYPE_CLASS2 (4 << OP_ALG_TYPE_SHIFT) - -+/* version register fields */ -+#define OP_VER_CCHA_NUM 0x000000ff /* Number CCHAs instantiated */ -+#define OP_VER_CCHA_MISC 0x0000ff00 /* CCHA Miscellaneous Information */ -+#define OP_VER_CCHA_REV 0x00ff0000 /* CCHA Revision Number */ -+#define OP_VER_CCHA_VID 0xff000000 /* CCHA Version ID */ -+ - #define OP_ALG_ALGSEL_SHIFT 16 - #define OP_ALG_ALGSEL_MASK (0xff << OP_ALG_ALGSEL_SHIFT) - #define OP_ALG_ALGSEL_SUBMASK (0x0f << OP_ALG_ALGSEL_SHIFT) -@@ -1124,6 +1169,8 @@ - #define OP_ALG_ALGSEL_KASUMI (0x70 << OP_ALG_ALGSEL_SHIFT) - #define OP_ALG_ALGSEL_CRC (0x90 << OP_ALG_ALGSEL_SHIFT) - #define OP_ALG_ALGSEL_SNOW_F9 (0xA0 << OP_ALG_ALGSEL_SHIFT) -+#define OP_ALG_ALGSEL_CHACHA20 (0xD0 << OP_ALG_ALGSEL_SHIFT) -+#define OP_ALG_ALGSEL_POLY1305 (0xE0 << OP_ALG_ALGSEL_SHIFT) - - #define OP_ALG_AAI_SHIFT 4 - #define OP_ALG_AAI_MASK (0x1ff << OP_ALG_AAI_SHIFT) -@@ -1171,6 +1218,11 @@ - #define OP_ALG_AAI_RNG4_AI (0x80 << OP_ALG_AAI_SHIFT) - #define OP_ALG_AAI_RNG4_SK (0x100 << OP_ALG_AAI_SHIFT) - -+/* Chacha20 AAI set */ -+#define OP_ALG_AAI_AEAD (0x002 << OP_ALG_AAI_SHIFT) -+#define OP_ALG_AAI_KEYSTREAM (0x001 << OP_ALG_AAI_SHIFT) -+#define OP_ALG_AAI_BC8 (0x008 << OP_ALG_AAI_SHIFT) -+ - /* hmac/smac AAI set */ - #define OP_ALG_AAI_HASH (0x00 << OP_ALG_AAI_SHIFT) - #define OP_ALG_AAI_HMAC (0x01 << OP_ALG_AAI_SHIFT) -@@ -1359,6 +1411,7 @@ - #define MOVE_SRC_MATH3 (0x07 << MOVE_SRC_SHIFT) - #define MOVE_SRC_INFIFO (0x08 << MOVE_SRC_SHIFT) - #define MOVE_SRC_INFIFO_CL (0x09 << MOVE_SRC_SHIFT) -+#define MOVE_SRC_AUX_ABLK (0x0a << MOVE_SRC_SHIFT) - - #define MOVE_DEST_SHIFT 16 - #define MOVE_DEST_MASK (0x0f << MOVE_DEST_SHIFT) -@@ -1385,6 +1438,10 @@ - - #define MOVELEN_MRSEL_SHIFT 0 - #define MOVELEN_MRSEL_MASK (0x3 << MOVE_LEN_SHIFT) -+#define MOVELEN_MRSEL_MATH0 (0 << MOVELEN_MRSEL_SHIFT) -+#define MOVELEN_MRSEL_MATH1 (1 << MOVELEN_MRSEL_SHIFT) -+#define MOVELEN_MRSEL_MATH2 (2 << MOVELEN_MRSEL_SHIFT) -+#define MOVELEN_MRSEL_MATH3 (3 << MOVELEN_MRSEL_SHIFT) - - /* - * MATH Command Constructs -@@ -1440,10 +1497,11 @@ - #define MATH_SRC1_REG2 (0x02 << MATH_SRC1_SHIFT) - #define MATH_SRC1_REG3 (0x03 << MATH_SRC1_SHIFT) - #define MATH_SRC1_IMM (0x04 << MATH_SRC1_SHIFT) --#define MATH_SRC1_DPOVRD (0x07 << MATH_SRC0_SHIFT) -+#define MATH_SRC1_DPOVRD (0x07 << MATH_SRC1_SHIFT) - #define MATH_SRC1_INFIFO (0x0a << MATH_SRC1_SHIFT) - #define MATH_SRC1_OUTFIFO (0x0b << MATH_SRC1_SHIFT) - #define MATH_SRC1_ONE (0x0c << MATH_SRC1_SHIFT) -+#define MATH_SRC1_ZERO (0x0f << MATH_SRC1_SHIFT) - - /* Destination selectors */ - #define MATH_DEST_SHIFT 8 -@@ -1452,6 +1510,7 @@ - #define MATH_DEST_REG1 (0x01 << MATH_DEST_SHIFT) - #define MATH_DEST_REG2 (0x02 << MATH_DEST_SHIFT) - #define MATH_DEST_REG3 (0x03 << MATH_DEST_SHIFT) -+#define MATH_DEST_DPOVRD (0x07 << MATH_DEST_SHIFT) - #define MATH_DEST_SEQINLEN (0x08 << MATH_DEST_SHIFT) - #define MATH_DEST_SEQOUTLEN (0x09 << MATH_DEST_SHIFT) - #define MATH_DEST_VARSEQINLEN (0x0a << MATH_DEST_SHIFT) -@@ -1560,6 +1619,7 @@ - #define NFIFOENTRY_DTYPE_IV (0x2 << NFIFOENTRY_DTYPE_SHIFT) - #define NFIFOENTRY_DTYPE_SAD (0x3 << NFIFOENTRY_DTYPE_SHIFT) - #define NFIFOENTRY_DTYPE_ICV (0xA << NFIFOENTRY_DTYPE_SHIFT) -+#define NFIFOENTRY_DTYPE_POLY (0xB << NFIFOENTRY_DTYPE_SHIFT) - #define NFIFOENTRY_DTYPE_SKIP (0xE << NFIFOENTRY_DTYPE_SHIFT) - #define NFIFOENTRY_DTYPE_MSG (0xF << NFIFOENTRY_DTYPE_SHIFT) - -@@ -1624,4 +1684,31 @@ - /* Frame Descriptor Command for Replacement Job Descriptor */ - #define FD_CMD_REPLACE_JOB_DESC 0x20000000 - -+/* CHA Control Register bits */ -+#define CCTRL_RESET_CHA_ALL 0x1 -+#define CCTRL_RESET_CHA_AESA 0x2 -+#define CCTRL_RESET_CHA_DESA 0x4 -+#define CCTRL_RESET_CHA_AFHA 0x8 -+#define CCTRL_RESET_CHA_KFHA 0x10 -+#define CCTRL_RESET_CHA_SF8A 0x20 -+#define CCTRL_RESET_CHA_PKHA 0x40 -+#define CCTRL_RESET_CHA_MDHA 0x80 -+#define CCTRL_RESET_CHA_CRCA 0x100 -+#define CCTRL_RESET_CHA_RNG 0x200 -+#define CCTRL_RESET_CHA_SF9A 0x400 -+#define CCTRL_RESET_CHA_ZUCE 0x800 -+#define CCTRL_RESET_CHA_ZUCA 0x1000 -+#define CCTRL_UNLOAD_PK_A0 0x10000 -+#define CCTRL_UNLOAD_PK_A1 0x20000 -+#define CCTRL_UNLOAD_PK_A2 0x40000 -+#define CCTRL_UNLOAD_PK_A3 0x80000 -+#define CCTRL_UNLOAD_PK_B0 0x100000 -+#define CCTRL_UNLOAD_PK_B1 0x200000 -+#define CCTRL_UNLOAD_PK_B2 0x400000 -+#define CCTRL_UNLOAD_PK_B3 0x800000 -+#define CCTRL_UNLOAD_PK_N 0x1000000 -+#define CCTRL_UNLOAD_PK_A 0x4000000 -+#define CCTRL_UNLOAD_PK_B 0x8000000 -+#define CCTRL_UNLOAD_SBOX 0x10000000 -+ - #endif /* DESC_H */ ---- a/drivers/crypto/caam/desc_constr.h -+++ b/drivers/crypto/caam/desc_constr.h -@@ -109,7 +109,7 @@ static inline void init_job_desc_shared( - append_ptr(desc, ptr); - } - --static inline void append_data(u32 * const desc, void *data, int len) -+static inline void append_data(u32 * const desc, const void *data, int len) - { - u32 *offset = desc_end(desc); - -@@ -172,7 +172,7 @@ static inline void append_cmd_ptr_extlen - append_cmd(desc, len); - } - --static inline void append_cmd_data(u32 * const desc, void *data, int len, -+static inline void append_cmd_data(u32 * const desc, const void *data, int len, - u32 command) - { - append_cmd(desc, command | IMMEDIATE | len); -@@ -189,6 +189,8 @@ static inline u32 *append_##cmd(u32 * co - } - APPEND_CMD_RET(jump, JUMP) - APPEND_CMD_RET(move, MOVE) -+APPEND_CMD_RET(moveb, MOVEB) -+APPEND_CMD_RET(move_len, MOVE_LEN) - - static inline void set_jump_tgt_here(u32 * const desc, u32 *jump_cmd) - { -@@ -271,7 +273,7 @@ APPEND_SEQ_PTR_INTLEN(in, IN) - APPEND_SEQ_PTR_INTLEN(out, OUT) - - #define APPEND_CMD_PTR_TO_IMM(cmd, op) \ --static inline void append_##cmd##_as_imm(u32 * const desc, void *data, \ -+static inline void append_##cmd##_as_imm(u32 * const desc, const void *data, \ - unsigned int len, u32 options) \ - { \ - PRINT_POS; \ -@@ -312,7 +314,7 @@ APPEND_CMD_PTR_LEN(seq_out_ptr, SEQ_OUT_ - * from length of immediate data provided, e.g., split keys - */ - #define APPEND_CMD_PTR_TO_IMM2(cmd, op) \ --static inline void append_##cmd##_as_imm(u32 * const desc, void *data, \ -+static inline void append_##cmd##_as_imm(u32 * const desc, const void *data, \ - unsigned int data_len, \ - unsigned int len, u32 options) \ - { \ -@@ -327,7 +329,11 @@ static inline void append_##cmd##_imm_## - u32 options) \ - { \ - PRINT_POS; \ -- append_cmd(desc, CMD_##op | IMMEDIATE | options | sizeof(type)); \ -+ if (options & LDST_LEN_MASK) \ -+ append_cmd(desc, CMD_##op | IMMEDIATE | options); \ -+ else \ -+ append_cmd(desc, CMD_##op | IMMEDIATE | options | \ -+ sizeof(type)); \ - append_cmd(desc, immediate); \ - } - APPEND_CMD_RAW_IMM(load, LOAD, u32); -@@ -452,7 +458,7 @@ struct alginfo { - unsigned int keylen_pad; - union { - dma_addr_t key_dma; -- void *key_virt; -+ const void *key_virt; - }; - bool key_inline; - }; -@@ -496,4 +502,45 @@ static inline int desc_inline_query(unsi - return (rem_bytes >= 0) ? 0 : -1; - } - -+/** -+ * append_proto_dkp - Derived Key Protocol (DKP): key -> split key -+ * @desc: pointer to buffer used for descriptor construction -+ * @adata: pointer to authentication transform definitions. -+ * keylen should be the length of initial key, while keylen_pad -+ * the length of the derived (split) key. -+ * Valid algorithm values - one of OP_ALG_ALGSEL_{MD5, SHA1, SHA224, -+ * SHA256, SHA384, SHA512}. -+ */ -+static inline void append_proto_dkp(u32 * const desc, struct alginfo *adata) -+{ -+ u32 protid; -+ -+ /* -+ * Quick & dirty translation from OP_ALG_ALGSEL_{MD5, SHA*} -+ * to OP_PCLID_DKP_{MD5, SHA*} -+ */ -+ protid = (adata->algtype & OP_ALG_ALGSEL_SUBMASK) | -+ (0x20 << OP_ALG_ALGSEL_SHIFT); -+ -+ if (adata->key_inline) { -+ int words; -+ -+ append_operation(desc, OP_TYPE_UNI_PROTOCOL | protid | -+ OP_PCL_DKP_SRC_IMM | OP_PCL_DKP_DST_IMM | -+ adata->keylen); -+ append_data(desc, adata->key_virt, adata->keylen); -+ -+ /* Reserve space in descriptor buffer for the derived key */ -+ words = (ALIGN(adata->keylen_pad, CAAM_CMD_SZ) - -+ ALIGN(adata->keylen, CAAM_CMD_SZ)) / CAAM_CMD_SZ; -+ if (words) -+ (*desc) = cpu_to_caam32(caam32_to_cpu(*desc) + words); -+ } else { -+ append_operation(desc, OP_TYPE_UNI_PROTOCOL | protid | -+ OP_PCL_DKP_SRC_PTR | OP_PCL_DKP_DST_PTR | -+ adata->keylen); -+ append_ptr(desc, adata->key_dma); -+ } -+} -+ - #endif /* DESC_CONSTR_H */ ---- /dev/null -+++ b/drivers/crypto/caam/dpseci.c -@@ -0,0 +1,865 @@ -+/* -+ * Copyright 2013-2016 Freescale Semiconductor Inc. -+ * Copyright 2017 NXP -+ * -+ * Redistribution and use in source and binary forms, with or without -+ * modification, are permitted provided that the following conditions are met: -+ * * Redistributions of source code must retain the above copyright -+ * notice, this list of conditions and the following disclaimer. -+ * * Redistributions in binary form must reproduce the above copyright -+ * notice, this list of conditions and the following disclaimer in the -+ * documentation and/or other materials provided with the distribution. -+ * * Neither the names of the above-listed copyright holders nor the -+ * names of any contributors may be used to endorse or promote products -+ * derived from this software without specific prior written permission. -+ * -+ * -+ * ALTERNATIVELY, this software may be distributed under the terms of the -+ * GNU General Public License ("GPL") as published by the Free Software -+ * Foundation, either version 2 of that License or (at your option) any -+ * later version. -+ * -+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE -+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -+ * POSSIBILITY OF SUCH DAMAGE. -+ */ -+ -+#include <linux/fsl/mc.h> -+#include "../../../drivers/staging/fsl-mc/include/dpopr.h" -+#include "dpseci.h" -+#include "dpseci_cmd.h" -+ -+/** -+ * dpseci_open() - Open a control session for the specified object -+ * @mc_io: Pointer to MC portal's I/O object -+ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' -+ * @dpseci_id: DPSECI unique ID -+ * @token: Returned token; use in subsequent API calls -+ * -+ * This function can be used to open a control session for an already created -+ * object; an object may have been declared in the DPL or by calling the -+ * dpseci_create() function. -+ * This function returns a unique authentication token, associated with the -+ * specific object ID and the specific MC portal; this token must be used in all -+ * subsequent commands for this specific object. -+ * -+ * Return: '0' on success, error code otherwise -+ */ -+int dpseci_open(struct fsl_mc_io *mc_io, u32 cmd_flags, int dpseci_id, -+ u16 *token) -+{ -+ struct fsl_mc_command cmd = { 0 }; -+ struct dpseci_cmd_open *cmd_params; -+ int err; -+ -+ cmd.header = mc_encode_cmd_header(DPSECI_CMDID_OPEN, -+ cmd_flags, -+ 0); -+ cmd_params = (struct dpseci_cmd_open *)cmd.params; -+ cmd_params->dpseci_id = cpu_to_le32(dpseci_id); -+ err = mc_send_command(mc_io, &cmd); -+ if (err) -+ return err; -+ -+ *token = mc_cmd_hdr_read_token(&cmd); -+ -+ return 0; -+} -+ -+/** -+ * dpseci_close() - Close the control session of the object -+ * @mc_io: Pointer to MC portal's I/O object -+ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' -+ * @token: Token of DPSECI object -+ * -+ * After this function is called, no further operations are allowed on the -+ * object without opening a new control session. -+ * -+ * Return: '0' on success, error code otherwise -+ */ -+int dpseci_close(struct fsl_mc_io *mc_io, u32 cmd_flags, u16 token) -+{ -+ struct fsl_mc_command cmd = { 0 }; -+ -+ cmd.header = mc_encode_cmd_header(DPSECI_CMDID_CLOSE, -+ cmd_flags, -+ token); -+ return mc_send_command(mc_io, &cmd); -+} -+ -+/** -+ * dpseci_create() - Create the DPSECI object -+ * @mc_io: Pointer to MC portal's I/O object -+ * @dprc_token: Parent container token; '0' for default container -+ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' -+ * @cfg: Configuration structure -+ * @obj_id: returned object id -+ * -+ * Create the DPSECI object, allocate required resources and perform required -+ * initialization. -+ * -+ * The object can be created either by declaring it in the DPL file, or by -+ * calling this function. -+ * -+ * The function accepts an authentication token of a parent container that this -+ * object should be assigned to. The token can be '0' so the object will be -+ * assigned to the default container. -+ * The newly created object can be opened with the returned object id and using -+ * the container's associated tokens and MC portals. -+ * -+ * Return: '0' on success, error code otherwise -+ */ -+int dpseci_create(struct fsl_mc_io *mc_io, u16 dprc_token, u32 cmd_flags, -+ const struct dpseci_cfg *cfg, u32 *obj_id) -+{ -+ struct fsl_mc_command cmd = { 0 }; -+ struct dpseci_cmd_create *cmd_params; -+ int i, err; -+ -+ cmd.header = mc_encode_cmd_header(DPSECI_CMDID_CREATE, -+ cmd_flags, -+ dprc_token); -+ cmd_params = (struct dpseci_cmd_create *)cmd.params; -+ for (i = 0; i < 8; i++) -+ cmd_params->priorities[i] = cfg->priorities[i]; -+ for (i = 0; i < 8; i++) -+ cmd_params->priorities2[i] = cfg->priorities[8 + i]; -+ cmd_params->num_tx_queues = cfg->num_tx_queues; -+ cmd_params->num_rx_queues = cfg->num_rx_queues; -+ cmd_params->options = cpu_to_le32(cfg->options); -+ err = mc_send_command(mc_io, &cmd); -+ if (err) -+ return err; -+ -+ *obj_id = mc_cmd_read_object_id(&cmd); -+ -+ return 0; -+} -+ -+/** -+ * dpseci_destroy() - Destroy the DPSECI object and release all its resources -+ * @mc_io: Pointer to MC portal's I/O object -+ * @dprc_token: Parent container token; '0' for default container -+ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' -+ * @object_id: The object id; it must be a valid id within the container that -+ * created this object -+ * -+ * The function accepts the authentication token of the parent container that -+ * created the object (not the one that currently owns the object). The object -+ * is searched within parent using the provided 'object_id'. -+ * All tokens to the object must be closed before calling destroy. -+ * -+ * Return: '0' on success, error code otherwise -+ */ -+int dpseci_destroy(struct fsl_mc_io *mc_io, u16 dprc_token, u32 cmd_flags, -+ u32 object_id) -+{ -+ struct fsl_mc_command cmd = { 0 }; -+ struct dpseci_cmd_destroy *cmd_params; -+ -+ cmd.header = mc_encode_cmd_header(DPSECI_CMDID_DESTROY, -+ cmd_flags, -+ dprc_token); -+ cmd_params = (struct dpseci_cmd_destroy *)cmd.params; -+ cmd_params->object_id = cpu_to_le32(object_id); -+ -+ return mc_send_command(mc_io, &cmd); -+} -+ -+/** -+ * dpseci_enable() - Enable the DPSECI, allow sending and receiving frames -+ * @mc_io: Pointer to MC portal's I/O object -+ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' -+ * @token: Token of DPSECI object -+ * -+ * Return: '0' on success, error code otherwise -+ */ -+int dpseci_enable(struct fsl_mc_io *mc_io, u32 cmd_flags, u16 token) -+{ -+ struct fsl_mc_command cmd = { 0 }; -+ -+ cmd.header = mc_encode_cmd_header(DPSECI_CMDID_ENABLE, -+ cmd_flags, -+ token); -+ return mc_send_command(mc_io, &cmd); -+} -+ -+/** -+ * dpseci_disable() - Disable the DPSECI, stop sending and receiving frames -+ * @mc_io: Pointer to MC portal's I/O object -+ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' -+ * @token: Token of DPSECI object -+ * -+ * Return: '0' on success, error code otherwise -+ */ -+int dpseci_disable(struct fsl_mc_io *mc_io, u32 cmd_flags, u16 token) -+{ -+ struct fsl_mc_command cmd = { 0 }; -+ -+ cmd.header = mc_encode_cmd_header(DPSECI_CMDID_DISABLE, -+ cmd_flags, -+ token); -+ -+ return mc_send_command(mc_io, &cmd); -+} -+ -+/** -+ * dpseci_is_enabled() - Check if the DPSECI is enabled. -+ * @mc_io: Pointer to MC portal's I/O object -+ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' -+ * @token: Token of DPSECI object -+ * @en: Returns '1' if object is enabled; '0' otherwise -+ * -+ * Return: '0' on success, error code otherwise -+ */ -+int dpseci_is_enabled(struct fsl_mc_io *mc_io, u32 cmd_flags, u16 token, -+ int *en) -+{ -+ struct fsl_mc_command cmd = { 0 }; -+ struct dpseci_rsp_is_enabled *rsp_params; -+ int err; -+ -+ cmd.header = mc_encode_cmd_header(DPSECI_CMDID_IS_ENABLED, -+ cmd_flags, -+ token); -+ err = mc_send_command(mc_io, &cmd); -+ if (err) -+ return err; -+ -+ rsp_params = (struct dpseci_rsp_is_enabled *)cmd.params; -+ *en = dpseci_get_field(rsp_params->is_enabled, ENABLE); -+ -+ return 0; -+} -+ -+/** -+ * dpseci_reset() - Reset the DPSECI, returns the object to initial state. -+ * @mc_io: Pointer to MC portal's I/O object -+ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' -+ * @token: Token of DPSECI object -+ * -+ * Return: '0' on success, error code otherwise -+ */ -+int dpseci_reset(struct fsl_mc_io *mc_io, u32 cmd_flags, u16 token) -+{ -+ struct fsl_mc_command cmd = { 0 }; -+ -+ cmd.header = mc_encode_cmd_header(DPSECI_CMDID_RESET, -+ cmd_flags, -+ token); -+ -+ return mc_send_command(mc_io, &cmd); -+} -+ -+/** -+ * dpseci_get_irq_enable() - Get overall interrupt state -+ * @mc_io: Pointer to MC portal's I/O object -+ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' -+ * @token: Token of DPSECI object -+ * @irq_index: The interrupt index to configure -+ * @en: Returned Interrupt state - enable = 1, disable = 0 -+ * -+ * Return: '0' on success, error code otherwise -+ */ -+int dpseci_get_irq_enable(struct fsl_mc_io *mc_io, u32 cmd_flags, u16 token, -+ u8 irq_index, u8 *en) -+{ -+ struct fsl_mc_command cmd = { 0 }; -+ struct dpseci_cmd_irq_enable *cmd_params; -+ struct dpseci_rsp_get_irq_enable *rsp_params; -+ int err; -+ -+ cmd.header = mc_encode_cmd_header(DPSECI_CMDID_GET_IRQ_ENABLE, -+ cmd_flags, -+ token); -+ cmd_params = (struct dpseci_cmd_irq_enable *)cmd.params; -+ cmd_params->irq_index = irq_index; -+ err = mc_send_command(mc_io, &cmd); -+ if (err) -+ return err; -+ -+ rsp_params = (struct dpseci_rsp_get_irq_enable *)cmd.params; -+ *en = rsp_params->enable_state; -+ -+ return 0; -+} -+ -+/** -+ * dpseci_set_irq_enable() - Set overall interrupt state. -+ * @mc_io: Pointer to MC portal's I/O object -+ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' -+ * @token: Token of DPSECI object -+ * @irq_index: The interrupt index to configure -+ * @en: Interrupt state - enable = 1, disable = 0 -+ * -+ * Allows GPP software to control when interrupts are generated. -+ * Each interrupt can have up to 32 causes. The enable/disable control's the -+ * overall interrupt state. If the interrupt is disabled no causes will cause -+ * an interrupt. -+ * -+ * Return: '0' on success, error code otherwise -+ */ -+int dpseci_set_irq_enable(struct fsl_mc_io *mc_io, u32 cmd_flags, u16 token, -+ u8 irq_index, u8 en) -+{ -+ struct fsl_mc_command cmd = { 0 }; -+ struct dpseci_cmd_irq_enable *cmd_params; -+ -+ cmd.header = mc_encode_cmd_header(DPSECI_CMDID_SET_IRQ_ENABLE, -+ cmd_flags, -+ token); -+ cmd_params = (struct dpseci_cmd_irq_enable *)cmd.params; -+ cmd_params->irq_index = irq_index; -+ cmd_params->enable_state = en; -+ -+ return mc_send_command(mc_io, &cmd); -+} -+ -+/** -+ * dpseci_get_irq_mask() - Get interrupt mask. -+ * @mc_io: Pointer to MC portal's I/O object -+ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' -+ * @token: Token of DPSECI object -+ * @irq_index: The interrupt index to configure -+ * @mask: Returned event mask to trigger interrupt -+ * -+ * Every interrupt can have up to 32 causes and the interrupt model supports -+ * masking/unmasking each cause independently. -+ * -+ * Return: '0' on success, error code otherwise -+ */ -+int dpseci_get_irq_mask(struct fsl_mc_io *mc_io, u32 cmd_flags, u16 token, -+ u8 irq_index, u32 *mask) -+{ -+ struct fsl_mc_command cmd = { 0 }; -+ struct dpseci_cmd_irq_mask *cmd_params; -+ int err; -+ -+ cmd.header = mc_encode_cmd_header(DPSECI_CMDID_GET_IRQ_MASK, -+ cmd_flags, -+ token); -+ cmd_params = (struct dpseci_cmd_irq_mask *)cmd.params; -+ cmd_params->irq_index = irq_index; -+ err = mc_send_command(mc_io, &cmd); -+ if (err) -+ return err; -+ -+ *mask = le32_to_cpu(cmd_params->mask); -+ -+ return 0; -+} -+ -+/** -+ * dpseci_set_irq_mask() - Set interrupt mask. -+ * @mc_io: Pointer to MC portal's I/O object -+ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' -+ * @token: Token of DPSECI object -+ * @irq_index: The interrupt index to configure -+ * @mask: event mask to trigger interrupt; -+ * each bit: -+ * 0 = ignore event -+ * 1 = consider event for asserting IRQ -+ * -+ * Every interrupt can have up to 32 causes and the interrupt model supports -+ * masking/unmasking each cause independently -+ * -+ * Return: '0' on success, error code otherwise -+ */ -+int dpseci_set_irq_mask(struct fsl_mc_io *mc_io, u32 cmd_flags, u16 token, -+ u8 irq_index, u32 mask) -+{ -+ struct fsl_mc_command cmd = { 0 }; -+ struct dpseci_cmd_irq_mask *cmd_params; -+ -+ cmd.header = mc_encode_cmd_header(DPSECI_CMDID_SET_IRQ_MASK, -+ cmd_flags, -+ token); -+ cmd_params = (struct dpseci_cmd_irq_mask *)cmd.params; -+ cmd_params->mask = cpu_to_le32(mask); -+ cmd_params->irq_index = irq_index; -+ -+ return mc_send_command(mc_io, &cmd); -+} -+ -+/** -+ * dpseci_get_irq_status() - Get the current status of any pending interrupts -+ * @mc_io: Pointer to MC portal's I/O object -+ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' -+ * @token: Token of DPSECI object -+ * @irq_index: The interrupt index to configure -+ * @status: Returned interrupts status - one bit per cause: -+ * 0 = no interrupt pending -+ * 1 = interrupt pending -+ * -+ * Return: '0' on success, error code otherwise -+ */ -+int dpseci_get_irq_status(struct fsl_mc_io *mc_io, u32 cmd_flags, u16 token, -+ u8 irq_index, u32 *status) -+{ -+ struct fsl_mc_command cmd = { 0 }; -+ struct dpseci_cmd_irq_status *cmd_params; -+ int err; -+ -+ cmd.header = mc_encode_cmd_header(DPSECI_CMDID_GET_IRQ_STATUS, -+ cmd_flags, -+ token); -+ cmd_params = (struct dpseci_cmd_irq_status *)cmd.params; -+ cmd_params->status = cpu_to_le32(*status); -+ cmd_params->irq_index = irq_index; -+ err = mc_send_command(mc_io, &cmd); -+ if (err) -+ return err; -+ -+ *status = le32_to_cpu(cmd_params->status); -+ -+ return 0; -+} -+ -+/** -+ * dpseci_clear_irq_status() - Clear a pending interrupt's status -+ * @mc_io: Pointer to MC portal's I/O object -+ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' -+ * @token: Token of DPSECI object -+ * @irq_index: The interrupt index to configure -+ * @status: bits to clear (W1C) - one bit per cause: -+ * 0 = don't change -+ * 1 = clear status bit -+ * -+ * Return: '0' on success, error code otherwise -+ */ -+int dpseci_clear_irq_status(struct fsl_mc_io *mc_io, u32 cmd_flags, u16 token, -+ u8 irq_index, u32 status) -+{ -+ struct fsl_mc_command cmd = { 0 }; -+ struct dpseci_cmd_irq_status *cmd_params; -+ -+ cmd.header = mc_encode_cmd_header(DPSECI_CMDID_CLEAR_IRQ_STATUS, -+ cmd_flags, -+ token); -+ cmd_params = (struct dpseci_cmd_irq_status *)cmd.params; -+ cmd_params->status = cpu_to_le32(status); -+ cmd_params->irq_index = irq_index; -+ -+ return mc_send_command(mc_io, &cmd); -+} -+ -+/** -+ * dpseci_get_attributes() - Retrieve DPSECI attributes -+ * @mc_io: Pointer to MC portal's I/O object -+ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' -+ * @token: Token of DPSECI object -+ * @attr: Returned object's attributes -+ * -+ * Return: '0' on success, error code otherwise -+ */ -+int dpseci_get_attributes(struct fsl_mc_io *mc_io, u32 cmd_flags, u16 token, -+ struct dpseci_attr *attr) -+{ -+ struct fsl_mc_command cmd = { 0 }; -+ struct dpseci_rsp_get_attributes *rsp_params; -+ int err; -+ -+ cmd.header = mc_encode_cmd_header(DPSECI_CMDID_GET_ATTR, -+ cmd_flags, -+ token); -+ err = mc_send_command(mc_io, &cmd); -+ if (err) -+ return err; -+ -+ rsp_params = (struct dpseci_rsp_get_attributes *)cmd.params; -+ attr->id = le32_to_cpu(rsp_params->id); -+ attr->num_tx_queues = rsp_params->num_tx_queues; -+ attr->num_rx_queues = rsp_params->num_rx_queues; -+ attr->options = le32_to_cpu(rsp_params->options); -+ -+ return 0; -+} -+ -+/** -+ * dpseci_set_rx_queue() - Set Rx queue configuration -+ * @mc_io: Pointer to MC portal's I/O object -+ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' -+ * @token: Token of DPSECI object -+ * @queue: Select the queue relative to number of priorities configured at -+ * DPSECI creation; use DPSECI_ALL_QUEUES to configure all -+ * Rx queues identically. -+ * @cfg: Rx queue configuration -+ * -+ * Return: '0' on success, error code otherwise -+ */ -+int dpseci_set_rx_queue(struct fsl_mc_io *mc_io, u32 cmd_flags, u16 token, -+ u8 queue, const struct dpseci_rx_queue_cfg *cfg) -+{ -+ struct fsl_mc_command cmd = { 0 }; -+ struct dpseci_cmd_queue *cmd_params; -+ -+ cmd.header = mc_encode_cmd_header(DPSECI_CMDID_SET_RX_QUEUE, -+ cmd_flags, -+ token); -+ cmd_params = (struct dpseci_cmd_queue *)cmd.params; -+ cmd_params->dest_id = cpu_to_le32(cfg->dest_cfg.dest_id); -+ cmd_params->priority = cfg->dest_cfg.priority; -+ cmd_params->queue = queue; -+ dpseci_set_field(cmd_params->dest_type, DEST_TYPE, -+ cfg->dest_cfg.dest_type); -+ cmd_params->user_ctx = cpu_to_le64(cfg->user_ctx); -+ cmd_params->options = cpu_to_le32(cfg->options); -+ dpseci_set_field(cmd_params->order_preservation_en, ORDER_PRESERVATION, -+ cfg->order_preservation_en); -+ -+ return mc_send_command(mc_io, &cmd); -+} -+ -+/** -+ * dpseci_get_rx_queue() - Retrieve Rx queue attributes -+ * @mc_io: Pointer to MC portal's I/O object -+ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' -+ * @token: Token of DPSECI object -+ * @queue: Select the queue relative to number of priorities configured at -+ * DPSECI creation -+ * @attr: Returned Rx queue attributes -+ * -+ * Return: '0' on success, error code otherwise -+ */ -+int dpseci_get_rx_queue(struct fsl_mc_io *mc_io, u32 cmd_flags, u16 token, -+ u8 queue, struct dpseci_rx_queue_attr *attr) -+{ -+ struct fsl_mc_command cmd = { 0 }; -+ struct dpseci_cmd_queue *cmd_params; -+ int err; -+ -+ cmd.header = mc_encode_cmd_header(DPSECI_CMDID_GET_RX_QUEUE, -+ cmd_flags, -+ token); -+ cmd_params = (struct dpseci_cmd_queue *)cmd.params; -+ cmd_params->queue = queue; -+ err = mc_send_command(mc_io, &cmd); -+ if (err) -+ return err; -+ -+ attr->dest_cfg.dest_id = le32_to_cpu(cmd_params->dest_id); -+ attr->dest_cfg.priority = cmd_params->priority; -+ attr->dest_cfg.dest_type = dpseci_get_field(cmd_params->dest_type, -+ DEST_TYPE); -+ attr->user_ctx = le64_to_cpu(cmd_params->user_ctx); -+ attr->fqid = le32_to_cpu(cmd_params->fqid); -+ attr->order_preservation_en = -+ dpseci_get_field(cmd_params->order_preservation_en, -+ ORDER_PRESERVATION); -+ -+ return 0; -+} -+ -+/** -+ * dpseci_get_tx_queue() - Retrieve Tx queue attributes -+ * @mc_io: Pointer to MC portal's I/O object -+ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' -+ * @token: Token of DPSECI object -+ * @queue: Select the queue relative to number of priorities configured at -+ * DPSECI creation -+ * @attr: Returned Tx queue attributes -+ * -+ * Return: '0' on success, error code otherwise -+ */ -+int dpseci_get_tx_queue(struct fsl_mc_io *mc_io, u32 cmd_flags, u16 token, -+ u8 queue, struct dpseci_tx_queue_attr *attr) -+{ -+ struct fsl_mc_command cmd = { 0 }; -+ struct dpseci_cmd_queue *cmd_params; -+ struct dpseci_rsp_get_tx_queue *rsp_params; -+ int err; -+ -+ cmd.header = mc_encode_cmd_header(DPSECI_CMDID_GET_TX_QUEUE, -+ cmd_flags, -+ token); -+ cmd_params = (struct dpseci_cmd_queue *)cmd.params; -+ cmd_params->queue = queue; -+ err = mc_send_command(mc_io, &cmd); -+ if (err) -+ return err; -+ -+ rsp_params = (struct dpseci_rsp_get_tx_queue *)cmd.params; -+ attr->fqid = le32_to_cpu(rsp_params->fqid); -+ attr->priority = rsp_params->priority; -+ -+ return 0; -+} -+ -+/** -+ * dpseci_get_sec_attr() - Retrieve SEC accelerator attributes -+ * @mc_io: Pointer to MC portal's I/O object -+ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' -+ * @token: Token of DPSECI object -+ * @attr: Returned SEC attributes -+ * -+ * Return: '0' on success, error code otherwise -+ */ -+int dpseci_get_sec_attr(struct fsl_mc_io *mc_io, u32 cmd_flags, u16 token, -+ struct dpseci_sec_attr *attr) -+{ -+ struct fsl_mc_command cmd = { 0 }; -+ struct dpseci_rsp_get_sec_attr *rsp_params; -+ int err; -+ -+ cmd.header = mc_encode_cmd_header(DPSECI_CMDID_GET_SEC_ATTR, -+ cmd_flags, -+ token); -+ err = mc_send_command(mc_io, &cmd); -+ if (err) -+ return err; -+ -+ rsp_params = (struct dpseci_rsp_get_sec_attr *)cmd.params; -+ attr->ip_id = le16_to_cpu(rsp_params->ip_id); -+ attr->major_rev = rsp_params->major_rev; -+ attr->minor_rev = rsp_params->minor_rev; -+ attr->era = rsp_params->era; -+ attr->deco_num = rsp_params->deco_num; -+ attr->zuc_auth_acc_num = rsp_params->zuc_auth_acc_num; -+ attr->zuc_enc_acc_num = rsp_params->zuc_enc_acc_num; -+ attr->snow_f8_acc_num = rsp_params->snow_f8_acc_num; -+ attr->snow_f9_acc_num = rsp_params->snow_f9_acc_num; -+ attr->crc_acc_num = rsp_params->crc_acc_num; -+ attr->pk_acc_num = rsp_params->pk_acc_num; -+ attr->kasumi_acc_num = rsp_params->kasumi_acc_num; -+ attr->rng_acc_num = rsp_params->rng_acc_num; -+ attr->md_acc_num = rsp_params->md_acc_num; -+ attr->arc4_acc_num = rsp_params->arc4_acc_num; -+ attr->des_acc_num = rsp_params->des_acc_num; -+ attr->aes_acc_num = rsp_params->aes_acc_num; -+ attr->ccha_acc_num = rsp_params->ccha_acc_num; -+ attr->ptha_acc_num = rsp_params->ptha_acc_num; -+ -+ return 0; -+} -+ -+/** -+ * dpseci_get_sec_counters() - Retrieve SEC accelerator counters -+ * @mc_io: Pointer to MC portal's I/O object -+ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' -+ * @token: Token of DPSECI object -+ * @counters: Returned SEC counters -+ * -+ * Return: '0' on success, error code otherwise -+ */ -+int dpseci_get_sec_counters(struct fsl_mc_io *mc_io, u32 cmd_flags, u16 token, -+ struct dpseci_sec_counters *counters) -+{ -+ struct fsl_mc_command cmd = { 0 }; -+ struct dpseci_rsp_get_sec_counters *rsp_params; -+ int err; -+ -+ cmd.header = mc_encode_cmd_header(DPSECI_CMDID_GET_SEC_COUNTERS, -+ cmd_flags, -+ token); -+ err = mc_send_command(mc_io, &cmd); -+ if (err) -+ return err; -+ -+ rsp_params = (struct dpseci_rsp_get_sec_counters *)cmd.params; -+ counters->dequeued_requests = -+ le64_to_cpu(rsp_params->dequeued_requests); -+ counters->ob_enc_requests = le64_to_cpu(rsp_params->ob_enc_requests); -+ counters->ib_dec_requests = le64_to_cpu(rsp_params->ib_dec_requests); -+ counters->ob_enc_bytes = le64_to_cpu(rsp_params->ob_enc_bytes); -+ counters->ob_prot_bytes = le64_to_cpu(rsp_params->ob_prot_bytes); -+ counters->ib_dec_bytes = le64_to_cpu(rsp_params->ib_dec_bytes); -+ counters->ib_valid_bytes = le64_to_cpu(rsp_params->ib_valid_bytes); -+ -+ return 0; -+} -+ -+/** -+ * dpseci_get_api_version() - Get Data Path SEC Interface API version -+ * @mc_io: Pointer to MC portal's I/O object -+ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' -+ * @major_ver: Major version of data path sec API -+ * @minor_ver: Minor version of data path sec API -+ * -+ * Return: '0' on success, error code otherwise -+ */ -+int dpseci_get_api_version(struct fsl_mc_io *mc_io, u32 cmd_flags, -+ u16 *major_ver, u16 *minor_ver) -+{ -+ struct fsl_mc_command cmd = { 0 }; -+ struct dpseci_rsp_get_api_version *rsp_params; -+ int err; -+ -+ cmd.header = mc_encode_cmd_header(DPSECI_CMDID_GET_API_VERSION, -+ cmd_flags, 0); -+ err = mc_send_command(mc_io, &cmd); -+ if (err) -+ return err; -+ -+ rsp_params = (struct dpseci_rsp_get_api_version *)cmd.params; -+ *major_ver = le16_to_cpu(rsp_params->major); -+ *minor_ver = le16_to_cpu(rsp_params->minor); -+ -+ return 0; -+} -+ -+/** -+ * dpseci_set_opr() - Set Order Restoration configuration -+ * @mc_io: Pointer to MC portal's I/O object -+ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' -+ * @token: Token of DPSECI object -+ * @index: The queue index -+ * @options: Configuration mode options; can be OPR_OPT_CREATE or -+ * OPR_OPT_RETIRE -+ * @cfg: Configuration options for the OPR -+ * -+ * Return: '0' on success, error code otherwise -+ */ -+int dpseci_set_opr(struct fsl_mc_io *mc_io, u32 cmd_flags, u16 token, u8 index, -+ u8 options, struct opr_cfg *cfg) -+{ -+ struct fsl_mc_command cmd = { 0 }; -+ struct dpseci_cmd_opr *cmd_params; -+ -+ cmd.header = mc_encode_cmd_header( -+ DPSECI_CMDID_SET_OPR, -+ cmd_flags, -+ token); -+ cmd_params = (struct dpseci_cmd_opr *)cmd.params; -+ cmd_params->index = index; -+ cmd_params->options = options; -+ cmd_params->oloe = cfg->oloe; -+ cmd_params->oeane = cfg->oeane; -+ cmd_params->olws = cfg->olws; -+ cmd_params->oa = cfg->oa; -+ cmd_params->oprrws = cfg->oprrws; -+ -+ return mc_send_command(mc_io, &cmd); -+} -+ -+/** -+ * dpseci_get_opr() - Retrieve Order Restoration config and query -+ * @mc_io: Pointer to MC portal's I/O object -+ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' -+ * @token: Token of DPSECI object -+ * @index: The queue index -+ * @cfg: Returned OPR configuration -+ * @qry: Returned OPR query -+ * -+ * Return: '0' on success, error code otherwise -+ */ -+int dpseci_get_opr(struct fsl_mc_io *mc_io, u32 cmd_flags, u16 token, u8 index, -+ struct opr_cfg *cfg, struct opr_qry *qry) -+{ -+ struct fsl_mc_command cmd = { 0 }; -+ struct dpseci_cmd_opr *cmd_params; -+ struct dpseci_rsp_get_opr *rsp_params; -+ int err; -+ -+ cmd.header = mc_encode_cmd_header(DPSECI_CMDID_GET_OPR, -+ cmd_flags, -+ token); -+ cmd_params = (struct dpseci_cmd_opr *)cmd.params; -+ cmd_params->index = index; -+ err = mc_send_command(mc_io, &cmd); -+ if (err) -+ return err; -+ -+ rsp_params = (struct dpseci_rsp_get_opr *)cmd.params; -+ qry->rip = dpseci_get_field(rsp_params->flags, OPR_RIP); -+ qry->enable = dpseci_get_field(rsp_params->flags, OPR_ENABLE); -+ cfg->oloe = rsp_params->oloe; -+ cfg->oeane = rsp_params->oeane; -+ cfg->olws = rsp_params->olws; -+ cfg->oa = rsp_params->oa; -+ cfg->oprrws = rsp_params->oprrws; -+ qry->nesn = le16_to_cpu(rsp_params->nesn); -+ qry->ndsn = le16_to_cpu(rsp_params->ndsn); -+ qry->ea_tseq = le16_to_cpu(rsp_params->ea_tseq); -+ qry->tseq_nlis = dpseci_get_field(rsp_params->tseq_nlis, OPR_TSEQ_NLIS); -+ qry->ea_hseq = le16_to_cpu(rsp_params->ea_hseq); -+ qry->hseq_nlis = dpseci_get_field(rsp_params->hseq_nlis, OPR_HSEQ_NLIS); -+ qry->ea_hptr = le16_to_cpu(rsp_params->ea_hptr); -+ qry->ea_tptr = le16_to_cpu(rsp_params->ea_tptr); -+ qry->opr_vid = le16_to_cpu(rsp_params->opr_vid); -+ qry->opr_id = le16_to_cpu(rsp_params->opr_id); -+ -+ return 0; -+} -+ -+/** -+ * dpseci_set_congestion_notification() - Set congestion group -+ * notification configuration -+ * @mc_io: Pointer to MC portal's I/O object -+ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' -+ * @token: Token of DPSECI object -+ * @cfg: congestion notification configuration -+ * -+ * Return: '0' on success, error code otherwise -+ */ -+int dpseci_set_congestion_notification(struct fsl_mc_io *mc_io, u32 cmd_flags, -+ u16 token, const struct dpseci_congestion_notification_cfg *cfg) -+{ -+ struct fsl_mc_command cmd = { 0 }; -+ struct dpseci_cmd_congestion_notification *cmd_params; -+ -+ cmd.header = mc_encode_cmd_header( -+ DPSECI_CMDID_SET_CONGESTION_NOTIFICATION, -+ cmd_flags, -+ token); -+ cmd_params = (struct dpseci_cmd_congestion_notification *)cmd.params; -+ cmd_params->dest_id = cpu_to_le32(cfg->dest_cfg.dest_id); -+ cmd_params->notification_mode = cpu_to_le16(cfg->notification_mode); -+ cmd_params->priority = cfg->dest_cfg.priority; -+ dpseci_set_field(cmd_params->options, CGN_DEST_TYPE, -+ cfg->dest_cfg.dest_type); -+ dpseci_set_field(cmd_params->options, CGN_UNITS, cfg->units); -+ cmd_params->message_iova = cpu_to_le64(cfg->message_iova); -+ cmd_params->message_ctx = cpu_to_le64(cfg->message_ctx); -+ cmd_params->threshold_entry = cpu_to_le32(cfg->threshold_entry); -+ cmd_params->threshold_exit = cpu_to_le32(cfg->threshold_exit); -+ -+ return mc_send_command(mc_io, &cmd); -+} -+ -+/** -+ * dpseci_get_congestion_notification() - Get congestion group notification -+ * configuration -+ * @mc_io: Pointer to MC portal's I/O object -+ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_' -+ * @token: Token of DPSECI object -+ * @cfg: congestion notification configuration -+ * -+ * Return: '0' on success, error code otherwise -+ */ -+int dpseci_get_congestion_notification(struct fsl_mc_io *mc_io, u32 cmd_flags, -+ u16 token, struct dpseci_congestion_notification_cfg *cfg) -+{ -+ struct fsl_mc_command cmd = { 0 }; -+ struct dpseci_cmd_congestion_notification *rsp_params; -+ int err; -+ -+ cmd.header = mc_encode_cmd_header( -+ DPSECI_CMDID_GET_CONGESTION_NOTIFICATION, -+ cmd_flags, -+ token); -+ err = mc_send_command(mc_io, &cmd); -+ if (err) -+ return err; -+ -+ rsp_params = (struct dpseci_cmd_congestion_notification *)cmd.params; -+ cfg->dest_cfg.dest_id = le32_to_cpu(rsp_params->dest_id); -+ cfg->notification_mode = le16_to_cpu(rsp_params->notification_mode); -+ cfg->dest_cfg.priority = rsp_params->priority; -+ cfg->dest_cfg.dest_type = dpseci_get_field(rsp_params->options, -+ CGN_DEST_TYPE); -+ cfg->units = dpseci_get_field(rsp_params->options, CGN_UNITS); -+ cfg->message_iova = le64_to_cpu(rsp_params->message_iova); -+ cfg->message_ctx = le64_to_cpu(rsp_params->message_ctx); -+ cfg->threshold_entry = le32_to_cpu(rsp_params->threshold_entry); -+ cfg->threshold_exit = le32_to_cpu(rsp_params->threshold_exit); -+ -+ return 0; -+} ---- /dev/null -+++ b/drivers/crypto/caam/dpseci.h -@@ -0,0 +1,433 @@ -+/* -+ * Copyright 2013-2016 Freescale Semiconductor Inc. -+ * Copyright 2017 NXP -+ * -+ * Redistribution and use in source and binary forms, with or without -+ * modification, are permitted provided that the following conditions are met: -+ * * Redistributions of source code must retain the above copyright -+ * notice, this list of conditions and the following disclaimer. -+ * * Redistributions in binary form must reproduce the above copyright -+ * notice, this list of conditions and the following disclaimer in the -+ * documentation and/or other materials provided with the distribution. -+ * * Neither the names of the above-listed copyright holders nor the -+ * names of any contributors may be used to endorse or promote products -+ * derived from this software without specific prior written permission. -+ * -+ * -+ * ALTERNATIVELY, this software may be distributed under the terms of the -+ * GNU General Public License ("GPL") as published by the Free Software -+ * Foundation, either version 2 of that License or (at your option) any -+ * later version. -+ * -+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE -+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -+ * POSSIBILITY OF SUCH DAMAGE. -+ */ -+#ifndef _DPSECI_H_ -+#define _DPSECI_H_ -+ -+/* -+ * Data Path SEC Interface API -+ * Contains initialization APIs and runtime control APIs for DPSECI -+ */ -+ -+struct fsl_mc_io; -+struct opr_cfg; -+struct opr_qry; -+ -+/** -+ * General DPSECI macros -+ */ -+ -+/** -+ * Maximum number of Tx/Rx queues per DPSECI object -+ */ -+#define DPSECI_MAX_QUEUE_NUM 16 -+ -+/** -+ * All queues considered; see dpseci_set_rx_queue() -+ */ -+#define DPSECI_ALL_QUEUES (u8)(-1) -+ -+int dpseci_open(struct fsl_mc_io *mc_io, u32 cmd_flags, int dpseci_id, -+ u16 *token); -+ -+int dpseci_close(struct fsl_mc_io *mc_io, u32 cmd_flags, u16 token); -+ -+/** -+ * Enable the Congestion Group support -+ */ -+#define DPSECI_OPT_HAS_CG 0x000020 -+ -+/** -+ * Enable the Order Restoration support -+ */ -+#define DPSECI_OPT_HAS_OPR 0x000040 -+ -+/** -+ * Order Point Records are shared for the entire DPSECI -+ */ -+#define DPSECI_OPT_OPR_SHARED 0x000080 -+ -+/** -+ * struct dpseci_cfg - Structure representing DPSECI configuration -+ * @options: Any combination of the following options: -+ * DPSECI_OPT_HAS_CG -+ * DPSECI_OPT_HAS_OPR -+ * DPSECI_OPT_OPR_SHARED -+ * @num_tx_queues: num of queues towards the SEC -+ * @num_rx_queues: num of queues back from the SEC -+ * @priorities: Priorities for the SEC hardware processing; -+ * each place in the array is the priority of the tx queue -+ * towards the SEC; -+ * valid priorities are configured with values 1-8; -+ */ -+struct dpseci_cfg { -+ u32 options; -+ u8 num_tx_queues; -+ u8 num_rx_queues; -+ u8 priorities[DPSECI_MAX_QUEUE_NUM]; -+}; -+ -+int dpseci_create(struct fsl_mc_io *mc_io, u16 dprc_token, u32 cmd_flags, -+ const struct dpseci_cfg *cfg, u32 *obj_id); -+ -+int dpseci_destroy(struct fsl_mc_io *mc_io, u16 dprc_token, u32 cmd_flags, -+ u32 object_id); -+ -+int dpseci_enable(struct fsl_mc_io *mc_io, u32 cmd_flags, u16 token); -+ -+int dpseci_disable(struct fsl_mc_io *mc_io, u32 cmd_flags, u16 token); -+ -+int dpseci_is_enabled(struct fsl_mc_io *mc_io, u32 cmd_flags, u16 token, -+ int *en); -+ -+int dpseci_reset(struct fsl_mc_io *mc_io, u32 cmd_flags, u16 token); -+ -+int dpseci_get_irq_enable(struct fsl_mc_io *mc_io, u32 cmd_flags, u16 token, -+ u8 irq_index, u8 *en); -+ -+int dpseci_set_irq_enable(struct fsl_mc_io *mc_io, u32 cmd_flags, u16 token, -+ u8 irq_index, u8 en); -+ -+int dpseci_get_irq_mask(struct fsl_mc_io *mc_io, u32 cmd_flags, u16 token, -+ u8 irq_index, u32 *mask); -+ -+int dpseci_set_irq_mask(struct fsl_mc_io *mc_io, u32 cmd_flags, u16 token, -+ u8 irq_index, u32 mask); -+ -+int dpseci_get_irq_status(struct fsl_mc_io *mc_io, u32 cmd_flags, u16 token, -+ u8 irq_index, u32 *status); -+ -+int dpseci_clear_irq_status(struct fsl_mc_io *mc_io, u32 cmd_flags, u16 token, -+ u8 irq_index, u32 status); -+ -+/** -+ * struct dpseci_attr - Structure representing DPSECI attributes -+ * @id: DPSECI object ID -+ * @num_tx_queues: number of queues towards the SEC -+ * @num_rx_queues: number of queues back from the SEC -+ * @options: any combination of the following options: -+ * DPSECI_OPT_HAS_CG -+ * DPSECI_OPT_HAS_OPR -+ * DPSECI_OPT_OPR_SHARED -+ */ -+struct dpseci_attr { -+ int id; -+ u8 num_tx_queues; -+ u8 num_rx_queues; -+ u32 options; -+}; -+ -+int dpseci_get_attributes(struct fsl_mc_io *mc_io, u32 cmd_flags, u16 token, -+ struct dpseci_attr *attr); -+ -+/** -+ * enum dpseci_dest - DPSECI destination types -+ * @DPSECI_DEST_NONE: Unassigned destination; The queue is set in parked mode -+ * and does not generate FQDAN notifications; user is expected to dequeue -+ * from the queue based on polling or other user-defined method -+ * @DPSECI_DEST_DPIO: The queue is set in schedule mode and generates FQDAN -+ * notifications to the specified DPIO; user is expected to dequeue from -+ * the queue only after notification is received -+ * @DPSECI_DEST_DPCON: The queue is set in schedule mode and does not generate -+ * FQDAN notifications, but is connected to the specified DPCON object; -+ * user is expected to dequeue from the DPCON channel -+ */ -+enum dpseci_dest { -+ DPSECI_DEST_NONE = 0, -+ DPSECI_DEST_DPIO, -+ DPSECI_DEST_DPCON -+}; -+ -+/** -+ * struct dpseci_dest_cfg - Structure representing DPSECI destination parameters -+ * @dest_type: Destination type -+ * @dest_id: Either DPIO ID or DPCON ID, depending on the destination type -+ * @priority: Priority selection within the DPIO or DPCON channel; valid values -+ * are 0-1 or 0-7, depending on the number of priorities in that channel; -+ * not relevant for 'DPSECI_DEST_NONE' option -+ */ -+struct dpseci_dest_cfg { -+ enum dpseci_dest dest_type; -+ int dest_id; -+ u8 priority; -+}; -+ -+/** -+ * DPSECI queue modification options -+ */ -+ -+/** -+ * Select to modify the user's context associated with the queue -+ */ -+#define DPSECI_QUEUE_OPT_USER_CTX 0x00000001 -+ -+/** -+ * Select to modify the queue's destination -+ */ -+#define DPSECI_QUEUE_OPT_DEST 0x00000002 -+ -+/** -+ * Select to modify the queue's order preservation -+ */ -+#define DPSECI_QUEUE_OPT_ORDER_PRESERVATION 0x00000004 -+ -+/** -+ * struct dpseci_rx_queue_cfg - DPSECI RX queue configuration -+ * @options: Flags representing the suggested modifications to the queue; -+ * Use any combination of 'DPSECI_QUEUE_OPT_<X>' flags -+ * @order_preservation_en: order preservation configuration for the rx queue -+ * valid only if 'DPSECI_QUEUE_OPT_ORDER_PRESERVATION' is contained in 'options' -+ * @user_ctx: User context value provided in the frame descriptor of each -+ * dequeued frame; valid only if 'DPSECI_QUEUE_OPT_USER_CTX' is contained -+ * in 'options' -+ * @dest_cfg: Queue destination parameters; valid only if -+ * 'DPSECI_QUEUE_OPT_DEST' is contained in 'options' -+ */ -+struct dpseci_rx_queue_cfg { -+ u32 options; -+ int order_preservation_en; -+ u64 user_ctx; -+ struct dpseci_dest_cfg dest_cfg; -+}; -+ -+int dpseci_set_rx_queue(struct fsl_mc_io *mc_io, u32 cmd_flags, u16 token, -+ u8 queue, const struct dpseci_rx_queue_cfg *cfg); -+ -+/** -+ * struct dpseci_rx_queue_attr - Structure representing attributes of Rx queues -+ * @user_ctx: User context value provided in the frame descriptor of each -+ * dequeued frame -+ * @order_preservation_en: Status of the order preservation configuration on the -+ * queue -+ * @dest_cfg: Queue destination configuration -+ * @fqid: Virtual FQID value to be used for dequeue operations -+ */ -+struct dpseci_rx_queue_attr { -+ u64 user_ctx; -+ int order_preservation_en; -+ struct dpseci_dest_cfg dest_cfg; -+ u32 fqid; -+}; -+ -+int dpseci_get_rx_queue(struct fsl_mc_io *mc_io, u32 cmd_flags, u16 token, -+ u8 queue, struct dpseci_rx_queue_attr *attr); -+ -+/** -+ * struct dpseci_tx_queue_attr - Structure representing attributes of Tx queues -+ * @fqid: Virtual FQID to be used for sending frames to SEC hardware -+ * @priority: SEC hardware processing priority for the queue -+ */ -+struct dpseci_tx_queue_attr { -+ u32 fqid; -+ u8 priority; -+}; -+ -+int dpseci_get_tx_queue(struct fsl_mc_io *mc_io, u32 cmd_flags, u16 token, -+ u8 queue, struct dpseci_tx_queue_attr *attr); -+ -+/** -+ * struct dpseci_sec_attr - Structure representing attributes of the SEC -+ * hardware accelerator -+ * @ip_id: ID for SEC -+ * @major_rev: Major revision number for SEC -+ * @minor_rev: Minor revision number for SEC -+ * @era: SEC Era -+ * @deco_num: The number of copies of the DECO that are implemented in this -+ * version of SEC -+ * @zuc_auth_acc_num: The number of copies of ZUCA that are implemented in this -+ * version of SEC -+ * @zuc_enc_acc_num: The number of copies of ZUCE that are implemented in this -+ * version of SEC -+ * @snow_f8_acc_num: The number of copies of the SNOW-f8 module that are -+ * implemented in this version of SEC -+ * @snow_f9_acc_num: The number of copies of the SNOW-f9 module that are -+ * implemented in this version of SEC -+ * @crc_acc_num: The number of copies of the CRC module that are implemented in -+ * this version of SEC -+ * @pk_acc_num: The number of copies of the Public Key module that are -+ * implemented in this version of SEC -+ * @kasumi_acc_num: The number of copies of the Kasumi module that are -+ * implemented in this version of SEC -+ * @rng_acc_num: The number of copies of the Random Number Generator that are -+ * implemented in this version of SEC -+ * @md_acc_num: The number of copies of the MDHA (Hashing module) that are -+ * implemented in this version of SEC -+ * @arc4_acc_num: The number of copies of the ARC4 module that are implemented -+ * in this version of SEC -+ * @des_acc_num: The number of copies of the DES module that are implemented in -+ * this version of SEC -+ * @aes_acc_num: The number of copies of the AES module that are implemented in -+ * this version of SEC -+ * @ccha_acc_num: The number of copies of the ChaCha20 module that are -+ * implemented in this version of SEC. -+ * @ptha_acc_num: The number of copies of the Poly1305 module that are -+ * implemented in this version of SEC. -+ **/ -+struct dpseci_sec_attr { -+ u16 ip_id; -+ u8 major_rev; -+ u8 minor_rev; -+ u8 era; -+ u8 deco_num; -+ u8 zuc_auth_acc_num; -+ u8 zuc_enc_acc_num; -+ u8 snow_f8_acc_num; -+ u8 snow_f9_acc_num; -+ u8 crc_acc_num; -+ u8 pk_acc_num; -+ u8 kasumi_acc_num; -+ u8 rng_acc_num; -+ u8 md_acc_num; -+ u8 arc4_acc_num; -+ u8 des_acc_num; -+ u8 aes_acc_num; -+ u8 ccha_acc_num; -+ u8 ptha_acc_num; -+}; -+ -+int dpseci_get_sec_attr(struct fsl_mc_io *mc_io, u32 cmd_flags, u16 token, -+ struct dpseci_sec_attr *attr); -+ -+/** -+ * struct dpseci_sec_counters - Structure representing global SEC counters and -+ * not per dpseci counters -+ * @dequeued_requests: Number of Requests Dequeued -+ * @ob_enc_requests: Number of Outbound Encrypt Requests -+ * @ib_dec_requests: Number of Inbound Decrypt Requests -+ * @ob_enc_bytes: Number of Outbound Bytes Encrypted -+ * @ob_prot_bytes: Number of Outbound Bytes Protected -+ * @ib_dec_bytes: Number of Inbound Bytes Decrypted -+ * @ib_valid_bytes: Number of Inbound Bytes Validated -+ */ -+struct dpseci_sec_counters { -+ u64 dequeued_requests; -+ u64 ob_enc_requests; -+ u64 ib_dec_requests; -+ u64 ob_enc_bytes; -+ u64 ob_prot_bytes; -+ u64 ib_dec_bytes; -+ u64 ib_valid_bytes; -+}; -+ -+int dpseci_get_sec_counters(struct fsl_mc_io *mc_io, u32 cmd_flags, u16 token, -+ struct dpseci_sec_counters *counters); -+ -+int dpseci_get_api_version(struct fsl_mc_io *mc_io, u32 cmd_flags, -+ u16 *major_ver, u16 *minor_ver); -+ -+int dpseci_set_opr(struct fsl_mc_io *mc_io, u32 cmd_flags, u16 token, u8 index, -+ u8 options, struct opr_cfg *cfg); -+ -+int dpseci_get_opr(struct fsl_mc_io *mc_io, u32 cmd_flags, u16 token, u8 index, -+ struct opr_cfg *cfg, struct opr_qry *qry); -+ -+/** -+ * enum dpseci_congestion_unit - DPSECI congestion units -+ * @DPSECI_CONGESTION_UNIT_BYTES: bytes units -+ * @DPSECI_CONGESTION_UNIT_FRAMES: frames units -+ */ -+enum dpseci_congestion_unit { -+ DPSECI_CONGESTION_UNIT_BYTES = 0, -+ DPSECI_CONGESTION_UNIT_FRAMES -+}; -+ -+/** -+ * CSCN message is written to message_iova once entering a -+ * congestion state (see 'threshold_entry') -+ */ -+#define DPSECI_CGN_MODE_WRITE_MEM_ON_ENTER 0x00000001 -+ -+/** -+ * CSCN message is written to message_iova once exiting a -+ * congestion state (see 'threshold_exit') -+ */ -+#define DPSECI_CGN_MODE_WRITE_MEM_ON_EXIT 0x00000002 -+ -+/** -+ * CSCN write will attempt to allocate into a cache (coherent write); -+ * valid only if 'DPSECI_CGN_MODE_WRITE_MEM_<X>' is selected -+ */ -+#define DPSECI_CGN_MODE_COHERENT_WRITE 0x00000004 -+ -+/** -+ * if 'dpseci_dest_cfg.dest_type != DPSECI_DEST_NONE' CSCN message is sent to -+ * DPIO/DPCON's WQ channel once entering a congestion state -+ * (see 'threshold_entry') -+ */ -+#define DPSECI_CGN_MODE_NOTIFY_DEST_ON_ENTER 0x00000008 -+ -+/** -+ * if 'dpseci_dest_cfg.dest_type != DPSECI_DEST_NONE' CSCN message is sent to -+ * DPIO/DPCON's WQ channel once exiting a congestion state -+ * (see 'threshold_exit') -+ */ -+#define DPSECI_CGN_MODE_NOTIFY_DEST_ON_EXIT 0x00000010 -+ -+/** -+ * if 'dpseci_dest_cfg.dest_type != DPSECI_DEST_NONE' when the CSCN is written -+ * to the sw-portal's DQRR, the DQRI interrupt is asserted immediately -+ * (if enabled) -+ */ -+#define DPSECI_CGN_MODE_INTR_COALESCING_DISABLED 0x00000020 -+ -+/** -+ * struct dpseci_congestion_notification_cfg - congestion notification -+ * configuration -+ * @units: units type -+ * @threshold_entry: above this threshold we enter a congestion state. -+ * set it to '0' to disable it -+ * @threshold_exit: below this threshold we exit the congestion state. -+ * @message_ctx: The context that will be part of the CSCN message -+ * @message_iova: I/O virtual address (must be in DMA-able memory), -+ * must be 16B aligned; -+ * @dest_cfg: CSCN can be send to either DPIO or DPCON WQ channel -+ * @notification_mode: Mask of available options; use 'DPSECI_CGN_MODE_<X>' -+ * values -+ */ -+struct dpseci_congestion_notification_cfg { -+ enum dpseci_congestion_unit units; -+ u32 threshold_entry; -+ u32 threshold_exit; -+ u64 message_ctx; -+ u64 message_iova; -+ struct dpseci_dest_cfg dest_cfg; -+ u16 notification_mode; -+}; -+ -+int dpseci_set_congestion_notification(struct fsl_mc_io *mc_io, u32 cmd_flags, -+ u16 token, const struct dpseci_congestion_notification_cfg *cfg); -+ -+int dpseci_get_congestion_notification(struct fsl_mc_io *mc_io, u32 cmd_flags, -+ u16 token, struct dpseci_congestion_notification_cfg *cfg); -+ -+#endif /* _DPSECI_H_ */ ---- /dev/null -+++ b/drivers/crypto/caam/dpseci_cmd.h -@@ -0,0 +1,287 @@ -+/* -+ * Copyright 2013-2016 Freescale Semiconductor Inc. -+ * Copyright 2017 NXP -+ * -+ * Redistribution and use in source and binary forms, with or without -+ * modification, are permitted provided that the following conditions are met: -+ * * Redistributions of source code must retain the above copyright -+ * notice, this list of conditions and the following disclaimer. -+ * * Redistributions in binary form must reproduce the above copyright -+ * notice, this list of conditions and the following disclaimer in the -+ * documentation and/or other materials provided with the distribution. -+ * * Neither the names of the above-listed copyright holders nor the -+ * names of any contributors may be used to endorse or promote products -+ * derived from this software without specific prior written permission. -+ * -+ * -+ * ALTERNATIVELY, this software may be distributed under the terms of the -+ * GNU General Public License ("GPL") as published by the Free Software -+ * Foundation, either version 2 of that License or (at your option) any -+ * later version. -+ * -+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE -+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -+ * POSSIBILITY OF SUCH DAMAGE. -+ */ -+ -+#ifndef _DPSECI_CMD_H_ -+#define _DPSECI_CMD_H_ -+ -+/* DPSECI Version */ -+#define DPSECI_VER_MAJOR 5 -+#define DPSECI_VER_MINOR 3 -+ -+#define DPSECI_VER(maj, min) (((maj) << 16) | (min)) -+#define DPSECI_VERSION DPSECI_VER(DPSECI_VER_MAJOR, DPSECI_VER_MINOR) -+ -+/* Command versioning */ -+#define DPSECI_CMD_BASE_VERSION 1 -+#define DPSECI_CMD_BASE_VERSION_V2 2 -+#define DPSECI_CMD_BASE_VERSION_V3 3 -+#define DPSECI_CMD_ID_OFFSET 4 -+ -+#define DPSECI_CMD_V1(id) (((id) << DPSECI_CMD_ID_OFFSET) | \ -+ DPSECI_CMD_BASE_VERSION) -+ -+#define DPSECI_CMD_V2(id) (((id) << DPSECI_CMD_ID_OFFSET) | \ -+ DPSECI_CMD_BASE_VERSION_V2) -+ -+#define DPSECI_CMD_V3(id) (((id) << DPSECI_CMD_ID_OFFSET) | \ -+ DPSECI_CMD_BASE_VERSION_V3) -+ -+/* Command IDs */ -+#define DPSECI_CMDID_CLOSE DPSECI_CMD_V1(0x800) -+#define DPSECI_CMDID_OPEN DPSECI_CMD_V1(0x809) -+#define DPSECI_CMDID_CREATE DPSECI_CMD_V3(0x909) -+#define DPSECI_CMDID_DESTROY DPSECI_CMD_V1(0x989) -+#define DPSECI_CMDID_GET_API_VERSION DPSECI_CMD_V1(0xa09) -+ -+#define DPSECI_CMDID_ENABLE DPSECI_CMD_V1(0x002) -+#define DPSECI_CMDID_DISABLE DPSECI_CMD_V1(0x003) -+#define DPSECI_CMDID_GET_ATTR DPSECI_CMD_V1(0x004) -+#define DPSECI_CMDID_RESET DPSECI_CMD_V1(0x005) -+#define DPSECI_CMDID_IS_ENABLED DPSECI_CMD_V1(0x006) -+ -+#define DPSECI_CMDID_SET_IRQ_ENABLE DPSECI_CMD_V1(0x012) -+#define DPSECI_CMDID_GET_IRQ_ENABLE DPSECI_CMD_V1(0x013) -+#define DPSECI_CMDID_SET_IRQ_MASK DPSECI_CMD_V1(0x014) -+#define DPSECI_CMDID_GET_IRQ_MASK DPSECI_CMD_V1(0x015) -+#define DPSECI_CMDID_GET_IRQ_STATUS DPSECI_CMD_V1(0x016) -+#define DPSECI_CMDID_CLEAR_IRQ_STATUS DPSECI_CMD_V1(0x017) -+ -+#define DPSECI_CMDID_SET_RX_QUEUE DPSECI_CMD_V1(0x194) -+#define DPSECI_CMDID_GET_RX_QUEUE DPSECI_CMD_V1(0x196) -+#define DPSECI_CMDID_GET_TX_QUEUE DPSECI_CMD_V1(0x197) -+#define DPSECI_CMDID_GET_SEC_ATTR DPSECI_CMD_V2(0x198) -+#define DPSECI_CMDID_GET_SEC_COUNTERS DPSECI_CMD_V1(0x199) -+#define DPSECI_CMDID_SET_OPR DPSECI_CMD_V1(0x19A) -+#define DPSECI_CMDID_GET_OPR DPSECI_CMD_V1(0x19B) -+#define DPSECI_CMDID_SET_CONGESTION_NOTIFICATION DPSECI_CMD_V1(0x170) -+#define DPSECI_CMDID_GET_CONGESTION_NOTIFICATION DPSECI_CMD_V1(0x171) -+ -+/* Macros for accessing command fields smaller than 1 byte */ -+#define DPSECI_MASK(field) \ -+ GENMASK(DPSECI_##field##_SHIFT + DPSECI_##field##_SIZE - 1, \ -+ DPSECI_##field##_SHIFT) -+ -+#define dpseci_set_field(var, field, val) \ -+ ((var) |= (((val) << DPSECI_##field##_SHIFT) & DPSECI_MASK(field))) -+ -+#define dpseci_get_field(var, field) \ -+ (((var) & DPSECI_MASK(field)) >> DPSECI_##field##_SHIFT) -+ -+struct dpseci_cmd_open { -+ __le32 dpseci_id; -+}; -+ -+struct dpseci_cmd_create { -+ u8 priorities[8]; -+ u8 num_tx_queues; -+ u8 num_rx_queues; -+ u8 pad0[6]; -+ __le32 options; -+ __le32 pad1; -+ u8 priorities2[8]; -+}; -+ -+struct dpseci_cmd_destroy { -+ __le32 object_id; -+}; -+ -+#define DPSECI_ENABLE_SHIFT 0 -+#define DPSECI_ENABLE_SIZE 1 -+ -+struct dpseci_rsp_is_enabled { -+ u8 is_enabled; -+}; -+ -+struct dpseci_cmd_irq_enable { -+ u8 enable_state; -+ u8 pad[3]; -+ u8 irq_index; -+}; -+ -+struct dpseci_rsp_get_irq_enable { -+ u8 enable_state; -+}; -+ -+struct dpseci_cmd_irq_mask { -+ __le32 mask; -+ u8 irq_index; -+}; -+ -+struct dpseci_cmd_irq_status { -+ __le32 status; -+ u8 irq_index; -+}; -+ -+struct dpseci_rsp_get_attributes { -+ __le32 id; -+ __le32 pad0; -+ u8 num_tx_queues; -+ u8 num_rx_queues; -+ u8 pad1[6]; -+ __le32 options; -+}; -+ -+#define DPSECI_DEST_TYPE_SHIFT 0 -+#define DPSECI_DEST_TYPE_SIZE 4 -+ -+#define DPSECI_ORDER_PRESERVATION_SHIFT 0 -+#define DPSECI_ORDER_PRESERVATION_SIZE 1 -+ -+struct dpseci_cmd_queue { -+ __le32 dest_id; -+ u8 priority; -+ u8 queue; -+ u8 dest_type; -+ u8 pad; -+ __le64 user_ctx; -+ union { -+ __le32 options; -+ __le32 fqid; -+ }; -+ u8 order_preservation_en; -+}; -+ -+struct dpseci_rsp_get_tx_queue { -+ __le32 pad; -+ __le32 fqid; -+ u8 priority; -+}; -+ -+struct dpseci_rsp_get_sec_attr { -+ __le16 ip_id; -+ u8 major_rev; -+ u8 minor_rev; -+ u8 era; -+ u8 pad0[3]; -+ u8 deco_num; -+ u8 zuc_auth_acc_num; -+ u8 zuc_enc_acc_num; -+ u8 pad1; -+ u8 snow_f8_acc_num; -+ u8 snow_f9_acc_num; -+ u8 crc_acc_num; -+ u8 pad2; -+ u8 pk_acc_num; -+ u8 kasumi_acc_num; -+ u8 rng_acc_num; -+ u8 pad3; -+ u8 md_acc_num; -+ u8 arc4_acc_num; -+ u8 des_acc_num; -+ u8 aes_acc_num; -+ u8 ccha_acc_num; -+ u8 ptha_acc_num; -+}; -+ -+struct dpseci_rsp_get_sec_counters { -+ __le64 dequeued_requests; -+ __le64 ob_enc_requests; -+ __le64 ib_dec_requests; -+ __le64 ob_enc_bytes; -+ __le64 ob_prot_bytes; -+ __le64 ib_dec_bytes; -+ __le64 ib_valid_bytes; -+}; -+ -+struct dpseci_rsp_get_api_version { -+ __le16 major; -+ __le16 minor; -+}; -+ -+struct dpseci_cmd_opr { -+ __le16 pad; -+ u8 index; -+ u8 options; -+ u8 pad1[7]; -+ u8 oloe; -+ u8 oeane; -+ u8 olws; -+ u8 oa; -+ u8 oprrws; -+}; -+ -+#define DPSECI_OPR_RIP_SHIFT 0 -+#define DPSECI_OPR_RIP_SIZE 1 -+#define DPSECI_OPR_ENABLE_SHIFT 1 -+#define DPSECI_OPR_ENABLE_SIZE 1 -+#define DPSECI_OPR_TSEQ_NLIS_SHIFT 0 -+#define DPSECI_OPR_TSEQ_NLIS_SIZE 1 -+#define DPSECI_OPR_HSEQ_NLIS_SHIFT 0 -+#define DPSECI_OPR_HSEQ_NLIS_SIZE 1 -+ -+struct dpseci_rsp_get_opr { -+ __le64 pad; -+ u8 flags; -+ u8 pad0[2]; -+ u8 oloe; -+ u8 oeane; -+ u8 olws; -+ u8 oa; -+ u8 oprrws; -+ __le16 nesn; -+ __le16 pad1; -+ __le16 ndsn; -+ __le16 pad2; -+ __le16 ea_tseq; -+ u8 tseq_nlis; -+ u8 pad3; -+ __le16 ea_hseq; -+ u8 hseq_nlis; -+ u8 pad4; -+ __le16 ea_hptr; -+ __le16 pad5; -+ __le16 ea_tptr; -+ __le16 pad6; -+ __le16 opr_vid; -+ __le16 pad7; -+ __le16 opr_id; -+}; -+ -+#define DPSECI_CGN_DEST_TYPE_SHIFT 0 -+#define DPSECI_CGN_DEST_TYPE_SIZE 4 -+#define DPSECI_CGN_UNITS_SHIFT 4 -+#define DPSECI_CGN_UNITS_SIZE 2 -+ -+struct dpseci_cmd_congestion_notification { -+ __le32 dest_id; -+ __le16 notification_mode; -+ u8 priority; -+ u8 options; -+ __le64 message_iova; -+ __le64 message_ctx; -+ __le32 threshold_entry; -+ __le32 threshold_exit; -+}; -+ -+#endif /* _DPSECI_CMD_H_ */ ---- a/drivers/crypto/caam/error.c -+++ b/drivers/crypto/caam/error.c -@@ -50,6 +50,12 @@ void caam_dump_sg(const char *level, con - #endif /* DEBUG */ - EXPORT_SYMBOL(caam_dump_sg); - -+bool caam_little_end; -+EXPORT_SYMBOL(caam_little_end); -+ -+bool caam_imx; -+EXPORT_SYMBOL(caam_imx); -+ - static const struct { - u8 value; - const char *error_text; -@@ -108,6 +114,54 @@ static const struct { - { 0xF1, "3GPP HFN matches or exceeds the Threshold" }, - }; - -+static const struct { -+ u8 value; -+ const char *error_text; -+} qi_error_list[] = { -+ { 0x1F, "Job terminated by FQ or ICID flush" }, -+ { 0x20, "FD format error"}, -+ { 0x21, "FD command format error"}, -+ { 0x23, "FL format error"}, -+ { 0x25, "CRJD specified in FD, but not enabled in FLC"}, -+ { 0x30, "Max. buffer size too small"}, -+ { 0x31, "DHR exceeds max. buffer size (allocate mode, S/G format)"}, -+ { 0x32, "SGT exceeds max. buffer size (allocate mode, S/G format"}, -+ { 0x33, "Size over/underflow (allocate mode)"}, -+ { 0x34, "Size over/underflow (reuse mode)"}, -+ { 0x35, "Length exceeds max. short length (allocate mode, S/G/ format)"}, -+ { 0x36, "Memory footprint exceeds max. value (allocate mode, S/G/ format)"}, -+ { 0x41, "SBC frame format not supported (allocate mode)"}, -+ { 0x42, "Pool 0 invalid / pool 1 size < pool 0 size (allocate mode)"}, -+ { 0x43, "Annotation output enabled but ASAR = 0 (allocate mode)"}, -+ { 0x44, "Unsupported or reserved frame format or SGHR = 1 (reuse mode)"}, -+ { 0x45, "DHR correction underflow (reuse mode, single buffer format)"}, -+ { 0x46, "Annotation length exceeds offset (reuse mode)"}, -+ { 0x48, "Annotation output enabled but ASA limited by ASAR (reuse mode)"}, -+ { 0x49, "Data offset correction exceeds input frame data length (reuse mode)"}, -+ { 0x4B, "Annotation output enabled but ASA cannote be expanded (frame list)"}, -+ { 0x51, "Unsupported IF reuse mode"}, -+ { 0x52, "Unsupported FL use mode"}, -+ { 0x53, "Unsupported RJD use mode"}, -+ { 0x54, "Unsupported inline descriptor use mode"}, -+ { 0xC0, "Table buffer pool 0 depletion"}, -+ { 0xC1, "Table buffer pool 1 depletion"}, -+ { 0xC2, "Data buffer pool 0 depletion, no OF allocated"}, -+ { 0xC3, "Data buffer pool 1 depletion, no OF allocated"}, -+ { 0xC4, "Data buffer pool 0 depletion, partial OF allocated"}, -+ { 0xC5, "Data buffer pool 1 depletion, partial OF allocated"}, -+ { 0xD0, "FLC read error"}, -+ { 0xD1, "FL read error"}, -+ { 0xD2, "FL write error"}, -+ { 0xD3, "OF SGT write error"}, -+ { 0xD4, "PTA read error"}, -+ { 0xD5, "PTA write error"}, -+ { 0xD6, "OF SGT F-bit write error"}, -+ { 0xD7, "ASA write error"}, -+ { 0xE1, "FLC[ICR]=0 ICID error"}, -+ { 0xE2, "FLC[ICR]=1 ICID error"}, -+ { 0xE4, "source of ICID flush not trusted (BDI = 0)"}, -+}; -+ - static const char * const cha_id_list[] = { - "", - "AES", -@@ -236,6 +290,27 @@ static void report_deco_status(struct de - status, error, idx_str, idx, err_str, err_err_code); - } - -+static void report_qi_status(struct device *qidev, const u32 status, -+ const char *error) -+{ -+ u8 err_id = status & JRSTA_QIERR_ERROR_MASK; -+ const char *err_str = "unidentified error value 0x"; -+ char err_err_code[3] = { 0 }; -+ int i; -+ -+ for (i = 0; i < ARRAY_SIZE(qi_error_list); i++) -+ if (qi_error_list[i].value == err_id) -+ break; -+ -+ if (i != ARRAY_SIZE(qi_error_list) && qi_error_list[i].error_text) -+ err_str = qi_error_list[i].error_text; -+ else -+ snprintf(err_err_code, sizeof(err_err_code), "%02x", err_id); -+ -+ dev_err(qidev, "%08x: %s: %s%s\n", -+ status, error, err_str, err_err_code); -+} -+ - static void report_jr_status(struct device *jrdev, const u32 status, - const char *error) - { -@@ -250,7 +325,7 @@ static void report_cond_code_status(stru - status, error, __func__); - } - --void caam_jr_strstatus(struct device *jrdev, u32 status) -+void caam_strstatus(struct device *jrdev, u32 status, bool qi_v2) - { - static const struct stat_src { - void (*report_ssed)(struct device *jrdev, const u32 status, -@@ -262,7 +337,7 @@ void caam_jr_strstatus(struct device *jr - { report_ccb_status, "CCB" }, - { report_jump_status, "Jump" }, - { report_deco_status, "DECO" }, -- { NULL, "Queue Manager Interface" }, -+ { report_qi_status, "Queue Manager Interface" }, - { report_jr_status, "Job Ring" }, - { report_cond_code_status, "Condition Code" }, - { NULL, NULL }, -@@ -288,4 +363,4 @@ void caam_jr_strstatus(struct device *jr - else - dev_err(jrdev, "%d: unknown error source\n", ssrc); - } --EXPORT_SYMBOL(caam_jr_strstatus); -+EXPORT_SYMBOL(caam_strstatus); ---- a/drivers/crypto/caam/error.h -+++ b/drivers/crypto/caam/error.h -@@ -8,7 +8,11 @@ - #ifndef CAAM_ERROR_H - #define CAAM_ERROR_H - #define CAAM_ERROR_STR_MAX 302 --void caam_jr_strstatus(struct device *jrdev, u32 status); -+ -+void caam_strstatus(struct device *dev, u32 status, bool qi_v2); -+ -+#define caam_jr_strstatus(jrdev, status) caam_strstatus(jrdev, status, false) -+#define caam_qi2_strstatus(qidev, status) caam_strstatus(qidev, status, true) - - void caam_dump_sg(const char *level, const char *prefix_str, int prefix_type, - int rowsize, int groupsize, struct scatterlist *sg, ---- a/drivers/crypto/caam/intern.h -+++ b/drivers/crypto/caam/intern.h -@@ -65,10 +65,6 @@ struct caam_drv_private_jr { - * Driver-private storage for a single CAAM block instance - */ - struct caam_drv_private { --#ifdef CONFIG_CAAM_QI -- struct device *qidev; --#endif -- - /* Physical-presence section */ - struct caam_ctrl __iomem *ctrl; /* controller region */ - struct caam_deco __iomem *deco; /* DECO/CCB views */ -@@ -76,14 +72,21 @@ struct caam_drv_private { - struct caam_queue_if __iomem *qi; /* QI control region */ - struct caam_job_ring __iomem *jr[4]; /* JobR's register space */ - -+ struct iommu_domain *domain; -+ - /* - * Detected geometry block. Filled in from device tree if powerpc, - * or from register-based version detection code - */ - u8 total_jobrs; /* Total Job Rings in device */ - u8 qi_present; /* Nonzero if QI present in device */ -+#ifdef CONFIG_CAAM_QI -+ u8 qi_init; /* Nonzero if QI has been initialized */ -+#endif -+ u8 mc_en; /* Nonzero if MC f/w is active */ - int secvio_irq; /* Security violation interrupt number */ - int virt_en; /* Virtualization enabled in CAAM */ -+ int era; /* CAAM Era (internal HW revision) */ - - #define RNG4_MAX_HANDLES 2 - /* RNG4 block */ -@@ -108,8 +111,95 @@ struct caam_drv_private { - #endif - }; - --void caam_jr_algapi_init(struct device *dev); --void caam_jr_algapi_remove(struct device *dev); -+#ifdef CONFIG_CRYPTO_DEV_FSL_CAAM_CRYPTO_API -+ -+int caam_algapi_init(struct device *dev); -+void caam_algapi_exit(void); -+ -+#else -+ -+static inline int caam_algapi_init(struct device *dev) -+{ -+ return 0; -+} -+ -+static inline void caam_algapi_exit(void) -+{ -+} -+ -+#endif /* CONFIG_CRYPTO_DEV_FSL_CAAM_CRYPTO_API */ -+ -+#ifdef CONFIG_CRYPTO_DEV_FSL_CAAM_AHASH_API -+ -+int caam_algapi_hash_init(struct device *dev); -+void caam_algapi_hash_exit(void); -+ -+#else -+ -+static inline int caam_algapi_hash_init(struct device *dev) -+{ -+ return 0; -+} -+ -+static inline void caam_algapi_hash_exit(void) -+{ -+} -+ -+#endif /* CONFIG_CRYPTO_DEV_FSL_CAAM_AHASH_API */ -+ -+#ifdef CONFIG_CRYPTO_DEV_FSL_CAAM_PKC_API -+ -+int caam_pkc_init(struct device *dev); -+void caam_pkc_exit(void); -+ -+#else -+ -+static inline int caam_pkc_init(struct device *dev) -+{ -+ return 0; -+} -+ -+static inline void caam_pkc_exit(void) -+{ -+} -+ -+#endif /* CONFIG_CRYPTO_DEV_FSL_CAAM_PKC_API */ -+ -+#ifdef CONFIG_CRYPTO_DEV_FSL_CAAM_RNG_API -+ -+int caam_rng_init(struct device *dev); -+void caam_rng_exit(void); -+ -+#else -+ -+static inline int caam_rng_init(struct device *dev) -+{ -+ return 0; -+} -+ -+static inline void caam_rng_exit(void) -+{ -+} -+ -+#endif /* CONFIG_CRYPTO_DEV_FSL_CAAM_RNG_API */ -+ -+#ifdef CONFIG_CAAM_QI -+ -+int caam_qi_algapi_init(struct device *dev); -+void caam_qi_algapi_exit(void); -+ -+#else -+ -+static inline int caam_qi_algapi_init(struct device *dev) -+{ -+ return 0; -+} -+ -+static inline void caam_qi_algapi_exit(void) -+{ -+} -+ -+#endif /* CONFIG_CAAM_QI */ - - #ifdef CONFIG_DEBUG_FS - static int caam_debugfs_u64_get(void *data, u64 *val) ---- a/drivers/crypto/caam/jr.c -+++ b/drivers/crypto/caam/jr.c -@@ -23,6 +23,52 @@ struct jr_driver_data { - - static struct jr_driver_data driver_data; - -+static int jr_driver_probed; -+ -+int caam_jr_driver_probed(void) -+{ -+ return jr_driver_probed; -+} -+EXPORT_SYMBOL(caam_jr_driver_probed); -+ -+static DEFINE_MUTEX(algs_lock); -+static unsigned int active_devs; -+ -+static void register_algs(struct device *dev) -+{ -+ mutex_lock(&algs_lock); -+ -+ if (++active_devs != 1) -+ goto algs_unlock; -+ -+ caam_algapi_init(dev); -+ caam_algapi_hash_init(dev); -+ caam_pkc_init(dev); -+ caam_rng_init(dev); -+ caam_qi_algapi_init(dev); -+ -+algs_unlock: -+ mutex_unlock(&algs_lock); -+} -+ -+static void unregister_algs(void) -+{ -+ mutex_lock(&algs_lock); -+ -+ if (--active_devs != 0) -+ goto algs_unlock; -+ -+ caam_qi_algapi_exit(); -+ -+ caam_rng_exit(); -+ caam_pkc_exit(); -+ caam_algapi_hash_exit(); -+ caam_algapi_exit(); -+ -+algs_unlock: -+ mutex_unlock(&algs_lock); -+} -+ - static int caam_reset_hw_jr(struct device *dev) - { - struct caam_drv_private_jr *jrp = dev_get_drvdata(dev); -@@ -108,6 +154,9 @@ static int caam_jr_remove(struct platfor - return -EBUSY; - } - -+ /* Unregister JR-based RNG & crypto algorithms */ -+ unregister_algs(); -+ - /* Remove the node from Physical JobR list maintained by driver */ - spin_lock(&driver_data.jr_alloc_lock); - list_del(&jrpriv->list_node); -@@ -119,6 +168,8 @@ static int caam_jr_remove(struct platfor - dev_err(jrdev, "Failed to shut down job ring\n"); - irq_dispose_mapping(jrpriv->irq); - -+ jr_driver_probed--; -+ - return ret; - } - -@@ -282,6 +333,36 @@ struct device *caam_jr_alloc(void) - EXPORT_SYMBOL(caam_jr_alloc); - - /** -+ * caam_jridx_alloc() - Alloc a specific job ring based on its index. -+ * -+ * returns : pointer to the newly allocated physical -+ * JobR dev can be written to if successful. -+ **/ -+struct device *caam_jridx_alloc(int idx) -+{ -+ struct caam_drv_private_jr *jrpriv; -+ struct device *dev = ERR_PTR(-ENODEV); -+ -+ spin_lock(&driver_data.jr_alloc_lock); -+ -+ if (list_empty(&driver_data.jr_list)) -+ goto end; -+ -+ list_for_each_entry(jrpriv, &driver_data.jr_list, list_node) { -+ if (jrpriv->ridx == idx) { -+ atomic_inc(&jrpriv->tfm_count); -+ dev = jrpriv->dev; -+ break; -+ } -+ } -+ -+end: -+ spin_unlock(&driver_data.jr_alloc_lock); -+ return dev; -+} -+EXPORT_SYMBOL(caam_jridx_alloc); -+ -+/** - * caam_jr_free() - Free the Job Ring - * @rdev - points to the dev that identifies the Job ring to - * be released. -@@ -539,6 +620,9 @@ static int caam_jr_probe(struct platform - - atomic_set(&jrpriv->tfm_count, 0); - -+ register_algs(jrdev->parent); -+ jr_driver_probed++; -+ - return 0; - } - ---- a/drivers/crypto/caam/jr.h -+++ b/drivers/crypto/caam/jr.h -@@ -9,7 +9,9 @@ - #define JR_H - - /* Prototypes for backend-level services exposed to APIs */ -+int caam_jr_driver_probed(void); - struct device *caam_jr_alloc(void); -+struct device *caam_jridx_alloc(int idx); - void caam_jr_free(struct device *rdev); - int caam_jr_enqueue(struct device *dev, u32 *desc, - void (*cbk)(struct device *dev, u32 *desc, u32 status, ---- a/drivers/crypto/caam/key_gen.c -+++ b/drivers/crypto/caam/key_gen.c -@@ -11,36 +11,6 @@ - #include "desc_constr.h" - #include "key_gen.h" - --/** -- * split_key_len - Compute MDHA split key length for a given algorithm -- * @hash: Hashing algorithm selection, one of OP_ALG_ALGSEL_* - MD5, SHA1, -- * SHA224, SHA384, SHA512. -- * -- * Return: MDHA split key length -- */ --static inline u32 split_key_len(u32 hash) --{ -- /* Sizes for MDHA pads (*not* keys): MD5, SHA1, 224, 256, 384, 512 */ -- static const u8 mdpadlen[] = { 16, 20, 32, 32, 64, 64 }; -- u32 idx; -- -- idx = (hash & OP_ALG_ALGSEL_SUBMASK) >> OP_ALG_ALGSEL_SHIFT; -- -- return (u32)(mdpadlen[idx] * 2); --} -- --/** -- * split_key_pad_len - Compute MDHA split key pad length for a given algorithm -- * @hash: Hashing algorithm selection, one of OP_ALG_ALGSEL_* - MD5, SHA1, -- * SHA224, SHA384, SHA512. -- * -- * Return: MDHA split key pad length -- */ --static inline u32 split_key_pad_len(u32 hash) --{ -- return ALIGN(split_key_len(hash), 16); --} -- - void split_key_done(struct device *dev, u32 *desc, u32 err, - void *context) - { ---- a/drivers/crypto/caam/key_gen.h -+++ b/drivers/crypto/caam/key_gen.h -@@ -6,6 +6,36 @@ - * - */ - -+/** -+ * split_key_len - Compute MDHA split key length for a given algorithm -+ * @hash: Hashing algorithm selection, one of OP_ALG_ALGSEL_* - MD5, SHA1, -+ * SHA224, SHA384, SHA512. -+ * -+ * Return: MDHA split key length -+ */ -+static inline u32 split_key_len(u32 hash) -+{ -+ /* Sizes for MDHA pads (*not* keys): MD5, SHA1, 224, 256, 384, 512 */ -+ static const u8 mdpadlen[] = { 16, 20, 32, 32, 64, 64 }; -+ u32 idx; -+ -+ idx = (hash & OP_ALG_ALGSEL_SUBMASK) >> OP_ALG_ALGSEL_SHIFT; -+ -+ return (u32)(mdpadlen[idx] * 2); -+} -+ -+/** -+ * split_key_pad_len - Compute MDHA split key pad length for a given algorithm -+ * @hash: Hashing algorithm selection, one of OP_ALG_ALGSEL_* - MD5, SHA1, -+ * SHA224, SHA384, SHA512. -+ * -+ * Return: MDHA split key pad length -+ */ -+static inline u32 split_key_pad_len(u32 hash) -+{ -+ return ALIGN(split_key_len(hash), 16); -+} -+ - struct split_key_result { - struct completion completion; - int err; ---- a/drivers/crypto/caam/qi.c -+++ b/drivers/crypto/caam/qi.c -@@ -9,7 +9,7 @@ - - #include <linux/cpumask.h> - #include <linux/kthread.h> --#include <soc/fsl/qman.h> -+#include <linux/fsl_qman.h> - - #include "regs.h" - #include "qi.h" -@@ -58,11 +58,9 @@ static DEFINE_PER_CPU(int, last_cpu); - /* - * caam_qi_priv - CAAM QI backend private params - * @cgr: QMan congestion group -- * @qi_pdev: platform device for QI backend - */ - struct caam_qi_priv { - struct qman_cgr cgr; -- struct platform_device *qi_pdev; - }; - - static struct caam_qi_priv qipriv ____cacheline_aligned; -@@ -102,26 +100,34 @@ static int mod_init_cpu; - */ - static struct kmem_cache *qi_cache; - -+static void *caam_iova_to_virt(struct iommu_domain *domain, -+ dma_addr_t iova_addr) -+{ -+ phys_addr_t phys_addr; -+ -+ phys_addr = domain ? iommu_iova_to_phys(domain, iova_addr) : iova_addr; -+ -+ return phys_to_virt(phys_addr); -+} -+ - int caam_qi_enqueue(struct device *qidev, struct caam_drv_req *req) - { - struct qm_fd fd; -- dma_addr_t addr; - int ret; - int num_retries = 0; - -- qm_fd_clear_fd(&fd); -- qm_fd_set_compound(&fd, qm_sg_entry_get_len(&req->fd_sgt[1])); -- -- addr = dma_map_single(qidev, req->fd_sgt, sizeof(req->fd_sgt), -+ fd.cmd = 0; -+ fd.format = qm_fd_compound; -+ fd.cong_weight = caam32_to_cpu(req->fd_sgt[1].length); -+ fd.addr = dma_map_single(qidev, req->fd_sgt, sizeof(req->fd_sgt), - DMA_BIDIRECTIONAL); -- if (dma_mapping_error(qidev, addr)) { -+ if (dma_mapping_error(qidev, fd.addr)) { - dev_err(qidev, "DMA mapping error for QI enqueue request\n"); - return -EIO; - } -- qm_fd_addr_set64(&fd, addr); - - do { -- ret = qman_enqueue(req->drv_ctx->req_fq, &fd); -+ ret = qman_enqueue(req->drv_ctx->req_fq, &fd, 0); - if (likely(!ret)) - return 0; - -@@ -137,20 +143,21 @@ int caam_qi_enqueue(struct device *qidev - EXPORT_SYMBOL(caam_qi_enqueue); - - static void caam_fq_ern_cb(struct qman_portal *qm, struct qman_fq *fq, -- const union qm_mr_entry *msg) -+ const struct qm_mr_entry *msg) - { - const struct qm_fd *fd; - struct caam_drv_req *drv_req; - struct device *qidev = &(raw_cpu_ptr(&pcpu_qipriv)->net_dev.dev); -+ struct caam_drv_private *priv = dev_get_drvdata(qidev); - - fd = &msg->ern.fd; - -- if (qm_fd_get_format(fd) != qm_fd_compound) { -+ if (fd->format != qm_fd_compound) { - dev_err(qidev, "Non-compound FD from CAAM\n"); - return; - } - -- drv_req = (struct caam_drv_req *)phys_to_virt(qm_fd_addr_get64(fd)); -+ drv_req = caam_iova_to_virt(priv->domain, qm_fd_addr_get64(fd)); - if (!drv_req) { - dev_err(qidev, - "Can't find original request for CAAM response\n"); -@@ -180,20 +187,22 @@ static struct qman_fq *create_caam_req_f - req_fq->cb.fqs = NULL; - - ret = qman_create_fq(0, QMAN_FQ_FLAG_DYNAMIC_FQID | -- QMAN_FQ_FLAG_TO_DCPORTAL, req_fq); -+ QMAN_FQ_FLAG_TO_DCPORTAL | QMAN_FQ_FLAG_LOCKED, -+ req_fq); - if (ret) { - dev_err(qidev, "Failed to create session req FQ\n"); - goto create_req_fq_fail; - } - -- memset(&opts, 0, sizeof(opts)); -- opts.we_mask = cpu_to_be16(QM_INITFQ_WE_FQCTRL | QM_INITFQ_WE_DESTWQ | -- QM_INITFQ_WE_CONTEXTB | -- QM_INITFQ_WE_CONTEXTA | QM_INITFQ_WE_CGID); -- opts.fqd.fq_ctrl = cpu_to_be16(QM_FQCTRL_CPCSTASH | QM_FQCTRL_CGE); -- qm_fqd_set_destwq(&opts.fqd, qm_channel_caam, 2); -- opts.fqd.context_b = cpu_to_be32(qman_fq_fqid(rsp_fq)); -- qm_fqd_context_a_set64(&opts.fqd, hwdesc); -+ opts.we_mask = QM_INITFQ_WE_FQCTRL | QM_INITFQ_WE_DESTWQ | -+ QM_INITFQ_WE_CONTEXTB | QM_INITFQ_WE_CONTEXTA | -+ QM_INITFQ_WE_CGID; -+ opts.fqd.fq_ctrl = QM_FQCTRL_CPCSTASH | QM_FQCTRL_CGE; -+ opts.fqd.dest.channel = qm_channel_caam; -+ opts.fqd.dest.wq = 2; -+ opts.fqd.context_b = qman_fq_fqid(rsp_fq); -+ opts.fqd.context_a.hi = upper_32_bits(hwdesc); -+ opts.fqd.context_a.lo = lower_32_bits(hwdesc); - opts.fqd.cgid = qipriv.cgr.cgrid; - - ret = qman_init_fq(req_fq, fq_sched_flag, &opts); -@@ -207,7 +216,7 @@ static struct qman_fq *create_caam_req_f - return req_fq; - - init_req_fq_fail: -- qman_destroy_fq(req_fq); -+ qman_destroy_fq(req_fq, 0); - create_req_fq_fail: - kfree(req_fq); - return ERR_PTR(ret); -@@ -275,7 +284,7 @@ empty_fq: - if (ret) - dev_err(qidev, "OOS of FQID: %u failed\n", fq->fqid); - -- qman_destroy_fq(fq); -+ qman_destroy_fq(fq, 0); - kfree(fq); - - return ret; -@@ -292,7 +301,7 @@ static int empty_caam_fq(struct qman_fq - if (ret) - return ret; - -- if (!qm_mcr_np_get(&np, frm_cnt)) -+ if (!np.frm_cnt) - break; - - msleep(20); -@@ -495,7 +504,7 @@ EXPORT_SYMBOL(caam_drv_ctx_rel); - int caam_qi_shutdown(struct device *qidev) - { - int i, ret; -- struct caam_qi_priv *priv = dev_get_drvdata(qidev); -+ struct caam_qi_priv *priv = &qipriv; - const cpumask_t *cpus = qman_affine_cpus(); - struct cpumask old_cpumask = current->cpus_allowed; - -@@ -528,7 +537,6 @@ int caam_qi_shutdown(struct device *qide - /* Now that we're done with the CGRs, restore the cpus allowed mask */ - set_cpus_allowed_ptr(current, &old_cpumask); - -- platform_device_unregister(priv->qi_pdev); - return ret; - } - -@@ -572,22 +580,28 @@ static enum qman_cb_dqrr_result caam_rsp - struct caam_drv_req *drv_req; - const struct qm_fd *fd; - struct device *qidev = &(raw_cpu_ptr(&pcpu_qipriv)->net_dev.dev); -- u32 status; -+ struct caam_drv_private *priv = dev_get_drvdata(qidev); - - if (caam_qi_napi_schedule(p, caam_napi)) - return qman_cb_dqrr_stop; - - fd = &dqrr->fd; -- status = be32_to_cpu(fd->status); -- if (unlikely(status)) -- dev_err(qidev, "Error: %#x in CAAM response FD\n", status); -+ if (unlikely(fd->status)) { -+ u32 ssrc = fd->status & JRSTA_SSRC_MASK; -+ u8 err_id = fd->status & JRSTA_CCBERR_ERRID_MASK; - -- if (unlikely(qm_fd_get_format(fd) != qm_fd_compound)) { -+ if (ssrc != JRSTA_SSRC_CCB_ERROR || -+ err_id != JRSTA_CCBERR_ERRID_ICVCHK) -+ dev_err(qidev, "Error: %#x in CAAM response FD\n", -+ fd->status); -+ } -+ -+ if (unlikely(fd->format != qm_fd_compound)) { - dev_err(qidev, "Non-compound FD from CAAM\n"); - return qman_cb_dqrr_consume; - } - -- drv_req = (struct caam_drv_req *)phys_to_virt(qm_fd_addr_get64(fd)); -+ drv_req = caam_iova_to_virt(priv->domain, qm_fd_addr_get64(fd)); - if (unlikely(!drv_req)) { - dev_err(qidev, - "Can't find original request for caam response\n"); -@@ -597,7 +611,7 @@ static enum qman_cb_dqrr_result caam_rsp - dma_unmap_single(drv_req->drv_ctx->qidev, qm_fd_addr(fd), - sizeof(drv_req->fd_sgt), DMA_BIDIRECTIONAL); - -- drv_req->cbk(drv_req, status); -+ drv_req->cbk(drv_req, fd->status); - return qman_cb_dqrr_consume; - } - -@@ -621,17 +635,18 @@ static int alloc_rsp_fq_cpu(struct devic - return -ENODEV; - } - -- memset(&opts, 0, sizeof(opts)); -- opts.we_mask = cpu_to_be16(QM_INITFQ_WE_FQCTRL | QM_INITFQ_WE_DESTWQ | -- QM_INITFQ_WE_CONTEXTB | -- QM_INITFQ_WE_CONTEXTA | QM_INITFQ_WE_CGID); -- opts.fqd.fq_ctrl = cpu_to_be16(QM_FQCTRL_CTXASTASHING | -- QM_FQCTRL_CPCSTASH | QM_FQCTRL_CGE); -- qm_fqd_set_destwq(&opts.fqd, qman_affine_channel(cpu), 3); -+ opts.we_mask = QM_INITFQ_WE_FQCTRL | QM_INITFQ_WE_DESTWQ | -+ QM_INITFQ_WE_CONTEXTB | QM_INITFQ_WE_CONTEXTA | -+ QM_INITFQ_WE_CGID; -+ opts.fqd.fq_ctrl = QM_FQCTRL_CTXASTASHING | QM_FQCTRL_CPCSTASH | -+ QM_FQCTRL_CGE; -+ opts.fqd.dest.channel = qman_affine_channel(cpu); -+ opts.fqd.dest.wq = 3; - opts.fqd.cgid = qipriv.cgr.cgrid; - opts.fqd.context_a.stashing.exclusive = QM_STASHING_EXCL_CTX | - QM_STASHING_EXCL_DATA; -- qm_fqd_set_stashing(&opts.fqd, 0, 1, 1); -+ opts.fqd.context_a.stashing.data_cl = 1; -+ opts.fqd.context_a.stashing.context_cl = 1; - - ret = qman_init_fq(fq, QMAN_INITFQ_FLAG_SCHED, &opts); - if (ret) { -@@ -650,9 +665,8 @@ static int init_cgr(struct device *qidev - { - int ret; - struct qm_mcc_initcgr opts; -- const u64 cpus = *(u64 *)qman_affine_cpus(); -- const int num_cpus = hweight64(cpus); -- const u64 val = num_cpus * MAX_RSP_FQ_BACKLOG_PER_CPU; -+ const u64 val = (u64)cpumask_weight(qman_affine_cpus()) * -+ MAX_RSP_FQ_BACKLOG_PER_CPU; - - ret = qman_alloc_cgrid(&qipriv.cgr.cgrid); - if (ret) { -@@ -662,8 +676,7 @@ static int init_cgr(struct device *qidev - - qipriv.cgr.cb = cgr_cb; - memset(&opts, 0, sizeof(opts)); -- opts.we_mask = cpu_to_be16(QM_CGR_WE_CSCN_EN | QM_CGR_WE_CS_THRES | -- QM_CGR_WE_MODE); -+ opts.we_mask = QM_CGR_WE_CSCN_EN | QM_CGR_WE_CS_THRES | QM_CGR_WE_MODE; - opts.cgr.cscn_en = QM_CGR_EN; - opts.cgr.mode = QMAN_CGR_MODE_FRAME; - qm_cgr_cs_thres_set64(&opts.cgr.cs_thres, val, 1); -@@ -708,15 +721,10 @@ static void free_rsp_fqs(void) - int caam_qi_init(struct platform_device *caam_pdev) - { - int err, i; -- struct platform_device *qi_pdev; - struct device *ctrldev = &caam_pdev->dev, *qidev; - struct caam_drv_private *ctrlpriv; - const cpumask_t *cpus = qman_affine_cpus(); - struct cpumask old_cpumask = current->cpus_allowed; -- static struct platform_device_info qi_pdev_info = { -- .name = "caam_qi", -- .id = PLATFORM_DEVID_NONE -- }; - - /* - * QMAN requires CGRs to be removed from same CPU+portal from where it -@@ -728,24 +736,13 @@ int caam_qi_init(struct platform_device - mod_init_cpu = cpumask_first(cpus); - set_cpus_allowed_ptr(current, get_cpu_mask(mod_init_cpu)); - -- qi_pdev_info.parent = ctrldev; -- qi_pdev_info.dma_mask = dma_get_mask(ctrldev); -- qi_pdev = platform_device_register_full(&qi_pdev_info); -- if (IS_ERR(qi_pdev)) -- return PTR_ERR(qi_pdev); -- set_dma_ops(&qi_pdev->dev, get_dma_ops(ctrldev)); -- - ctrlpriv = dev_get_drvdata(ctrldev); -- qidev = &qi_pdev->dev; -- -- qipriv.qi_pdev = qi_pdev; -- dev_set_drvdata(qidev, &qipriv); -+ qidev = ctrldev; - - /* Initialize the congestion detection */ - err = init_cgr(qidev); - if (err) { - dev_err(qidev, "CGR initialization failed: %d\n", err); -- platform_device_unregister(qi_pdev); - return err; - } - -@@ -754,7 +751,6 @@ int caam_qi_init(struct platform_device - if (err) { - dev_err(qidev, "Can't allocate CAAM response FQs: %d\n", err); - free_rsp_fqs(); -- platform_device_unregister(qi_pdev); - return err; - } - -@@ -777,15 +773,11 @@ int caam_qi_init(struct platform_device - napi_enable(irqtask); - } - -- /* Hook up QI device to parent controlling caam device */ -- ctrlpriv->qidev = qidev; -- - qi_cache = kmem_cache_create("caamqicache", CAAM_QI_MEMCACHE_SIZE, 0, - SLAB_CACHE_DMA, NULL); - if (!qi_cache) { - dev_err(qidev, "Can't allocate CAAM cache\n"); - free_rsp_fqs(); -- platform_device_unregister(qi_pdev); - return -ENOMEM; - } - -@@ -795,6 +787,8 @@ int caam_qi_init(struct platform_device - debugfs_create_file("qi_congested", 0444, ctrlpriv->ctl, - ×_congested, &caam_fops_u64_ro); - #endif -+ -+ ctrlpriv->qi_init = 1; - dev_info(qidev, "Linux CAAM Queue I/F driver initialised\n"); - return 0; - } ---- a/drivers/crypto/caam/qi.h -+++ b/drivers/crypto/caam/qi.h -@@ -9,7 +9,7 @@ - #ifndef __QI_H__ - #define __QI_H__ - --#include <soc/fsl/qman.h> -+#include <linux/fsl_qman.h> - #include "compat.h" - #include "desc.h" - #include "desc_constr.h" ---- a/drivers/crypto/caam/regs.h -+++ b/drivers/crypto/caam/regs.h -@@ -3,6 +3,7 @@ - * CAAM hardware register-level view - * - * Copyright 2008-2011 Freescale Semiconductor, Inc. -+ * Copyright 2018 NXP - */ - - #ifndef REGS_H -@@ -211,6 +212,47 @@ struct jr_outentry { - u32 jrstatus; /* Status for completed descriptor */ - } __packed; - -+/* Version registers (Era 10+) e80-eff */ -+struct version_regs { -+ u32 crca; /* CRCA_VERSION */ -+ u32 afha; /* AFHA_VERSION */ -+ u32 kfha; /* KFHA_VERSION */ -+ u32 pkha; /* PKHA_VERSION */ -+ u32 aesa; /* AESA_VERSION */ -+ u32 mdha; /* MDHA_VERSION */ -+ u32 desa; /* DESA_VERSION */ -+ u32 snw8a; /* SNW8A_VERSION */ -+ u32 snw9a; /* SNW9A_VERSION */ -+ u32 zuce; /* ZUCE_VERSION */ -+ u32 zuca; /* ZUCA_VERSION */ -+ u32 ccha; /* CCHA_VERSION */ -+ u32 ptha; /* PTHA_VERSION */ -+ u32 rng; /* RNG_VERSION */ -+ u32 trng; /* TRNG_VERSION */ -+ u32 aaha; /* AAHA_VERSION */ -+ u32 rsvd[10]; -+ u32 sr; /* SR_VERSION */ -+ u32 dma; /* DMA_VERSION */ -+ u32 ai; /* AI_VERSION */ -+ u32 qi; /* QI_VERSION */ -+ u32 jr; /* JR_VERSION */ -+ u32 deco; /* DECO_VERSION */ -+}; -+ -+/* Version registers bitfields */ -+ -+/* Number of CHAs instantiated */ -+#define CHA_VER_NUM_MASK 0xffull -+/* CHA Miscellaneous Information */ -+#define CHA_VER_MISC_SHIFT 8 -+#define CHA_VER_MISC_MASK (0xffull << CHA_VER_MISC_SHIFT) -+/* CHA Revision Number */ -+#define CHA_VER_REV_SHIFT 16 -+#define CHA_VER_REV_MASK (0xffull << CHA_VER_REV_SHIFT) -+/* CHA Version ID */ -+#define CHA_VER_VID_SHIFT 24 -+#define CHA_VER_VID_MASK (0xffull << CHA_VER_VID_SHIFT) -+ - /* - * caam_perfmon - Performance Monitor/Secure Memory Status/ - * CAAM Global Status/Component Version IDs -@@ -223,15 +265,13 @@ struct jr_outentry { - #define CHA_NUM_MS_DECONUM_MASK (0xfull << CHA_NUM_MS_DECONUM_SHIFT) - - /* -- * CHA version IDs / instantiation bitfields -+ * CHA version IDs / instantiation bitfields (< Era 10) - * Defined for use with the cha_id fields in perfmon, but the same shift/mask - * selectors can be used to pull out the number of instantiated blocks within - * cha_num fields in perfmon because the locations are the same. - */ - #define CHA_ID_LS_AES_SHIFT 0 - #define CHA_ID_LS_AES_MASK (0xfull << CHA_ID_LS_AES_SHIFT) --#define CHA_ID_LS_AES_LP (0x3ull << CHA_ID_LS_AES_SHIFT) --#define CHA_ID_LS_AES_HP (0x4ull << CHA_ID_LS_AES_SHIFT) - - #define CHA_ID_LS_DES_SHIFT 4 - #define CHA_ID_LS_DES_MASK (0xfull << CHA_ID_LS_DES_SHIFT) -@@ -241,9 +281,6 @@ struct jr_outentry { - - #define CHA_ID_LS_MD_SHIFT 12 - #define CHA_ID_LS_MD_MASK (0xfull << CHA_ID_LS_MD_SHIFT) --#define CHA_ID_LS_MD_LP256 (0x0ull << CHA_ID_LS_MD_SHIFT) --#define CHA_ID_LS_MD_LP512 (0x1ull << CHA_ID_LS_MD_SHIFT) --#define CHA_ID_LS_MD_HP (0x2ull << CHA_ID_LS_MD_SHIFT) - - #define CHA_ID_LS_RNG_SHIFT 16 - #define CHA_ID_LS_RNG_MASK (0xfull << CHA_ID_LS_RNG_SHIFT) -@@ -269,6 +306,13 @@ struct jr_outentry { - #define CHA_ID_MS_JR_SHIFT 28 - #define CHA_ID_MS_JR_MASK (0xfull << CHA_ID_MS_JR_SHIFT) - -+/* Specific CHA version IDs */ -+#define CHA_VER_VID_AES_LP 0x3ull -+#define CHA_VER_VID_AES_HP 0x4ull -+#define CHA_VER_VID_MD_LP256 0x0ull -+#define CHA_VER_VID_MD_LP512 0x1ull -+#define CHA_VER_VID_MD_HP 0x2ull -+ - struct sec_vid { - u16 ip_id; - u8 maj_rev; -@@ -473,8 +517,10 @@ struct caam_ctrl { - struct rng4tst r4tst[2]; - }; - -- u32 rsvd9[448]; -+ u32 rsvd9[416]; - -+ /* Version registers - introduced with era 10 e80-eff */ -+ struct version_regs vreg; - /* Performance Monitor f00-fff */ - struct caam_perfmon perfmon; - }; -@@ -564,8 +610,10 @@ struct caam_job_ring { - u32 rsvd11; - u32 jrcommand; /* JRCRx - JobR command */ - -- u32 rsvd12[932]; -+ u32 rsvd12[900]; - -+ /* Version registers - introduced with era 10 e80-eff */ -+ struct version_regs vreg; - /* Performance Monitor f00-fff */ - struct caam_perfmon perfmon; - }; -@@ -627,6 +675,8 @@ struct caam_job_ring { - #define JRSTA_DECOERR_INVSIGN 0x86 - #define JRSTA_DECOERR_DSASIGN 0x87 - -+#define JRSTA_QIERR_ERROR_MASK 0x00ff -+ - #define JRSTA_CCBERR_JUMP 0x08000000 - #define JRSTA_CCBERR_INDEX_MASK 0xff00 - #define JRSTA_CCBERR_INDEX_SHIFT 8 -@@ -870,13 +920,19 @@ struct caam_deco { - u32 rsvd29[48]; - u32 descbuf[64]; /* DxDESB - Descriptor buffer */ - u32 rscvd30[193]; --#define DESC_DBG_DECO_STAT_HOST_ERR 0x00D00000 - #define DESC_DBG_DECO_STAT_VALID 0x80000000 - #define DESC_DBG_DECO_STAT_MASK 0x00F00000 -+#define DESC_DBG_DECO_STAT_SHIFT 20 - u32 desc_dbg; /* DxDDR - DECO Debug Register */ -- u32 rsvd31[126]; -+ u32 rsvd31[13]; -+#define DESC_DER_DECO_STAT_MASK 0x000F0000 -+#define DESC_DER_DECO_STAT_SHIFT 16 -+ u32 dbg_exec; /* DxDER - DECO Debug Exec Register */ -+ u32 rsvd32[112]; - }; - -+#define DECO_STAT_HOST_ERR 0xD -+ - #define DECO_JQCR_WHL 0x20000000 - #define DECO_JQCR_FOUR 0x10000000 - ---- a/drivers/crypto/caam/sg_sw_qm.h -+++ b/drivers/crypto/caam/sg_sw_qm.h -@@ -34,46 +34,61 @@ - #ifndef __SG_SW_QM_H - #define __SG_SW_QM_H - --#include <soc/fsl/qman.h> -+#include <linux/fsl_qman.h> - #include "regs.h" - -+static inline void cpu_to_hw_sg(struct qm_sg_entry *qm_sg_ptr) -+{ -+ dma_addr_t addr = qm_sg_ptr->opaque; -+ -+ qm_sg_ptr->opaque = cpu_to_caam64(addr); -+ qm_sg_ptr->sgt_efl = cpu_to_caam32(qm_sg_ptr->sgt_efl); -+} -+ - static inline void __dma_to_qm_sg(struct qm_sg_entry *qm_sg_ptr, dma_addr_t dma, -- u16 offset) -+ u32 len, u16 offset) - { -- qm_sg_entry_set64(qm_sg_ptr, dma); -+ qm_sg_ptr->addr = dma; -+ qm_sg_ptr->length = len; - qm_sg_ptr->__reserved2 = 0; - qm_sg_ptr->bpid = 0; -- qm_sg_ptr->offset = cpu_to_be16(offset & QM_SG_OFF_MASK); -+ qm_sg_ptr->__reserved3 = 0; -+ qm_sg_ptr->offset = offset & QM_SG_OFFSET_MASK; -+ -+ cpu_to_hw_sg(qm_sg_ptr); - } - - static inline void dma_to_qm_sg_one(struct qm_sg_entry *qm_sg_ptr, - dma_addr_t dma, u32 len, u16 offset) - { -- __dma_to_qm_sg(qm_sg_ptr, dma, offset); -- qm_sg_entry_set_len(qm_sg_ptr, len); -+ qm_sg_ptr->extension = 0; -+ qm_sg_ptr->final = 0; -+ __dma_to_qm_sg(qm_sg_ptr, dma, len, offset); - } - - static inline void dma_to_qm_sg_one_last(struct qm_sg_entry *qm_sg_ptr, - dma_addr_t dma, u32 len, u16 offset) - { -- __dma_to_qm_sg(qm_sg_ptr, dma, offset); -- qm_sg_entry_set_f(qm_sg_ptr, len); -+ qm_sg_ptr->extension = 0; -+ qm_sg_ptr->final = 1; -+ __dma_to_qm_sg(qm_sg_ptr, dma, len, offset); - } - - static inline void dma_to_qm_sg_one_ext(struct qm_sg_entry *qm_sg_ptr, - dma_addr_t dma, u32 len, u16 offset) - { -- __dma_to_qm_sg(qm_sg_ptr, dma, offset); -- qm_sg_ptr->cfg = cpu_to_be32(QM_SG_EXT | (len & QM_SG_LEN_MASK)); -+ qm_sg_ptr->extension = 1; -+ qm_sg_ptr->final = 0; -+ __dma_to_qm_sg(qm_sg_ptr, dma, len, offset); - } - - static inline void dma_to_qm_sg_one_last_ext(struct qm_sg_entry *qm_sg_ptr, - dma_addr_t dma, u32 len, - u16 offset) - { -- __dma_to_qm_sg(qm_sg_ptr, dma, offset); -- qm_sg_ptr->cfg = cpu_to_be32(QM_SG_EXT | QM_SG_FIN | -- (len & QM_SG_LEN_MASK)); -+ qm_sg_ptr->extension = 1; -+ qm_sg_ptr->final = 1; -+ __dma_to_qm_sg(qm_sg_ptr, dma, len, offset); - } - - /* -@@ -102,7 +117,10 @@ static inline void sg_to_qm_sg_last(stru - struct qm_sg_entry *qm_sg_ptr, u16 offset) - { - qm_sg_ptr = sg_to_qm_sg(sg, sg_count, qm_sg_ptr, offset); -- qm_sg_entry_set_f(qm_sg_ptr, qm_sg_entry_get_len(qm_sg_ptr)); -+ -+ qm_sg_ptr->sgt_efl = caam32_to_cpu(qm_sg_ptr->sgt_efl); -+ qm_sg_ptr->final = 1; -+ qm_sg_ptr->sgt_efl = cpu_to_caam32(qm_sg_ptr->sgt_efl); - } - - #endif /* __SG_SW_QM_H */ ---- a/drivers/crypto/talitos.c -+++ b/drivers/crypto/talitos.c -@@ -1250,6 +1250,14 @@ static int ipsec_esp(struct talitos_edes - ret = talitos_sg_map_ext(dev, areq->src, cryptlen, edesc, &desc->ptr[4], - sg_count, areq->assoclen, tbl_off, elen); - -+ /* -+ * In case of SEC 2.x+, cipher in len must include only the ciphertext, -+ * while extent is used for ICV len. -+ */ -+ if ((edesc->desc.hdr & DESC_HDR_TYPE_IPSEC_ESP) && -+ (desc->hdr & DESC_HDR_MODE1_MDEU_CICV)) -+ desc->ptr[4].len = cpu_to_be16(cryptlen); -+ - if (ret > 1) { - tbl_off += ret; - sync_needed = true; ---- a/include/crypto/chacha20.h -+++ b/include/crypto/chacha20.h -@@ -13,6 +13,7 @@ - #define CHACHA20_IV_SIZE 16 - #define CHACHA20_KEY_SIZE 32 - #define CHACHA20_BLOCK_SIZE 64 -+#define CHACHAPOLY_IV_SIZE 12 - - struct chacha20_ctx { - u32 key[8]; |