diff -drupN a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c --- a/drivers/md/dm-crypt.c 2018-08-06 17:23:04.000000000 +0300 +++ b/drivers/md/dm-crypt.c 2022-06-12 05:28:14.000000000 +0300 @@ -178,6 +178,7 @@ struct crypt_config { unsigned int key_parts; /* independent parts in key buffer */ unsigned int key_extra_size; /* additional keys length */ u8 key[0]; + bool emmc_sup_crypto; }; #define MIN_IOS 64 @@ -185,6 +186,10 @@ struct crypt_config { static void clone_init(struct dm_crypt_io *, struct bio *); static void kcryptd_queue_crypt(struct dm_crypt_io *io); static u8 *iv_of_dmreq(struct crypt_config *cc, struct dm_crypt_request *dmreq); +#ifdef CONFIG_SUNXI_EMCE +static void kcryptd_crypt_write_io_submit(struct dm_crypt_io *io, int async); +extern int sunxi_emce_set_key(const u8 *mkey, u32 len); +#endif /* * Use this to access cipher attributes that are the same for each CPU. @@ -1111,13 +1116,20 @@ static void crypt_endio(struct bio *clon /* * free the processed pages */ +#ifndef CONFIG_SUNXI_EMCE if (rw == WRITE) - crypt_free_buffer_pages(cc, clone); - +#else + if ((!(cc->emmc_sup_crypto)) && (rw == WRITE)) +#endif + crypt_free_buffer_pages(cc, clone); error = clone->bi_error; bio_put(clone); +#ifndef CONFIG_SUNXI_EMCE if (rw == READ && !error) { +#else + if ((!(cc->emmc_sup_crypto)) && (rw == READ && !error)) { +#endif kcryptd_queue_crypt(io); return; } @@ -1138,7 +1150,11 @@ static void clone_init(struct dm_crypt_i bio_set_op_attrs(clone, bio_op(io->base_bio), bio_flags(io->base_bio)); } +#ifndef CONFIG_SUNXI_EMCE static int kcryptd_io_read(struct dm_crypt_io *io, gfp_t gfp) +#else +static int kcryptd_io_only(struct dm_crypt_io *io, gfp_t gfp) +#endif { struct crypt_config *cc = io->cc; struct bio *clone; @@ -1161,6 +1177,12 @@ static int kcryptd_io_read(struct dm_cry generic_make_request(clone); return 0; } +#ifdef CONFIG_SUNXI_EMCE +static int kcryptd_io_read(struct dm_crypt_io *io, gfp_t gfp) +{ + return kcryptd_io_only(io, gfp); +} +#endif static void kcryptd_io_read_work(struct work_struct *work) { @@ -1182,9 +1204,19 @@ static void kcryptd_queue_read(struct dm static void kcryptd_io_write(struct dm_crypt_io *io) { +#ifdef CONFIG_SUNXI_EMCE + if ((io->cc->emmc_sup_crypto)) { + crypt_inc_pending(io); + if (kcryptd_io_only(io, GFP_NOIO)) + io->error = -ENOMEM; + crypt_dec_pending(io); + } else +#endif + { struct bio *clone = io->ctx.bio_out; generic_make_request(clone); + } } #define crypt_io_from_node(node) rb_entry((node), struct dm_crypt_io, rb_node) @@ -1727,6 +1759,25 @@ bad_mem: return -ENOMEM; } +#ifdef CONFIG_SUNXI_EMCE +static void kcryptd_io_read_handle(struct dm_crypt_io *io) +{ + if (kcryptd_io_read(io, GFP_NOWAIT)) + kcryptd_queue_read(io); +} +static void kcryptd_io_write_handle(struct dm_crypt_io *io) +{ + if (io->cc->emmc_sup_crypto) + kcryptd_queue_read(io); + else + kcryptd_queue_crypt(io); +} +int sunxi_crypt_need_crypt(struct bio *bio) +{ + return bio->bi_end_io == crypt_endio; +} +EXPORT_SYMBOL_GPL(sunxi_crypt_need_crypt); +#endif /* * Construct an encryption mapping: * @@ -1737,7 +1788,7 @@ static int crypt_ctr(struct dm_target *t unsigned int key_size, opt_params; unsigned long long tmpll; int ret; - size_t iv_size_padding; + size_t iv_size_padding = 0; struct dm_arg_set as; const char *opt_string; char dummy; @@ -1761,11 +1812,54 @@ static int crypt_ctr(struct dm_target *t cc->key_size = key_size; ti->private = cc; - ret = crypt_ctr_cipher(ti, argv[0], argv[1]); - if (ret < 0) - goto bad; + if (strcmp(argv[3], "/dev/block/by-name/UDISK")) { + ret = crypt_ctr_cipher(ti, argv[0], argv[1]); + if (ret < 0) + goto bad; + } else { +#ifndef CONFIG_SUNXI_EMCE + ret = crypt_ctr_cipher(ti, argv[0], argv[1]); + if (ret < 0) + goto bad; +#endif + } - cc->dmreq_start = sizeof(struct skcipher_request); +#ifdef CONFIG_SUNXI_EMCE + if (!strcmp(argv[3], "/dev/block/by-name/UDISK")) { + cc->emmc_sup_crypto = 1; + /*set key for emce*/ + if (cc->key_size && + crypt_decode_key(cc->key, argv[1], cc->key_size) < 0) { + ti->error = "crypt decode key fail"; + goto bad; + } + set_bit(DM_CRYPT_KEY_VALID, &cc->flags); + + if (sunxi_emce_set_key(cc->key, cc->key_size)) { + ti->error = "sunxi emce set key fail"; + goto bad; + } + } else { + cc->emmc_sup_crypto = 0; + cc->dmreq_start = sizeof(struct skcipher_request); + cc->dmreq_start += crypto_skcipher_reqsize(any_tfm(cc)); + cc->dmreq_start = ALIGN(cc->dmreq_start, __alignof__(struct dm_crypt_request)); + + if (crypto_skcipher_alignmask(any_tfm(cc)) < CRYPTO_MINALIGN) + /* Allocate the padding exactly */ + iv_size_padding = -(cc->dmreq_start + sizeof(struct dm_crypt_request)) + & crypto_skcipher_alignmask(any_tfm(cc)); + else { + /* + * If the cipher requires greater alignment than kmalloc + * alignment, we don't know the exact position of the + * initialization vector. We must assume worst case. + */ + iv_size_padding = crypto_skcipher_alignmask(any_tfm(cc)); + } + } +#else + cc->dmreq_start = sizeof(struct ablkcipher_request); cc->dmreq_start += crypto_skcipher_reqsize(any_tfm(cc)); cc->dmreq_start = ALIGN(cc->dmreq_start, __alignof__(struct dm_crypt_request)); @@ -1781,6 +1875,7 @@ static int crypt_ctr(struct dm_target *t */ iv_size_padding = crypto_skcipher_alignmask(any_tfm(cc)); } +#endif ret = -ENOMEM; cc->req_pool = mempool_create_kmalloc_pool(MIN_IOS, cc->dmreq_start + @@ -1866,21 +1961,48 @@ static int crypt_ctr(struct dm_target *t } ret = -ENOMEM; - cc->io_queue = alloc_workqueue("kcryptd_io", WQ_MEM_RECLAIM, 1); + cc->io_queue = alloc_workqueue("kcryptd_io", + WQ_HIGHPRI | + WQ_MEM_RECLAIM, + 1); if (!cc->io_queue) { ti->error = "Couldn't create kcryptd io queue"; goto bad; } +#ifdef CONFIG_MMC_EMCE + if (!(cc->emmc_sup_crypto)) { + if (test_bit(DM_CRYPT_SAME_CPU, &cc->flags)) + cc->crypt_queue = alloc_workqueue("kcryptd", + WQ_HIGHPRI | + WQ_MEM_RECLAIM, 1); + else + cc->crypt_queue = alloc_workqueue("kcryptd", + WQ_HIGHPRI | + WQ_MEM_RECLAIM | + WQ_UNBOUND, + num_online_cpus()); + if (!cc->crypt_queue) { + ti->error = "Couldn't create kcryptd queue"; + goto bad; + } + } +#else if (test_bit(DM_CRYPT_SAME_CPU, &cc->flags)) - cc->crypt_queue = alloc_workqueue("kcryptd", WQ_CPU_INTENSIVE | WQ_MEM_RECLAIM, 1); + cc->crypt_queue = alloc_workqueue("kcryptd", + WQ_HIGHPRI | + WQ_MEM_RECLAIM, 1); else - cc->crypt_queue = alloc_workqueue("kcryptd", WQ_CPU_INTENSIVE | WQ_MEM_RECLAIM | WQ_UNBOUND, + cc->crypt_queue = alloc_workqueue("kcryptd", + WQ_HIGHPRI | + WQ_MEM_RECLAIM | + WQ_UNBOUND, num_online_cpus()); if (!cc->crypt_queue) { ti->error = "Couldn't create kcryptd queue"; goto bad; } +#endif init_waitqueue_head(&cc->write_thread_wait); cc->write_tree = RB_ROOT; @@ -1934,11 +2056,18 @@ static int crypt_map(struct dm_target *t crypt_io_init(io, cc, bio, dm_target_offset(ti, bio->bi_iter.bi_sector)); io->ctx.req = (struct skcipher_request *)(io + 1); +#ifdef CONFIG_SUNXI_EMCE + if (bio_data_dir(io->base_bio) == READ) + kcryptd_io_read_handle(io); + else + kcryptd_io_write_handle(io); +#else if (bio_data_dir(io->base_bio) == READ) { if (kcryptd_io_read(io, GFP_NOWAIT)) kcryptd_queue_read(io); } else kcryptd_queue_crypt(io); +#endif return DM_MAPIO_SUBMITTED; }