crypto: marvell/cesa - rearrange last request handling
[linux-drm-fsl-dcu.git] / drivers / crypto / marvell / hash.c
index ae9272eb9c1ac23ce7461a82ffd165c711d1886f..71d29f025bbefd1c3687efa785e4638a034befbd 100644 (file)
@@ -27,10 +27,10 @@ mv_cesa_ahash_req_iter_init(struct mv_cesa_ahash_dma_iter *iter,
                            struct ahash_request *req)
 {
        struct mv_cesa_ahash_req *creq = ahash_request_ctx(req);
-       unsigned int len = req->nbytes;
+       unsigned int len = req->nbytes + creq->cache_ptr;
 
        if (!creq->last_req)
-               len = (len + creq->cache_ptr) & ~CESA_HASH_BLOCK_SIZE_MSK;
+               len &= ~CESA_HASH_BLOCK_SIZE_MSK;
 
        mv_cesa_req_dma_iter_init(&iter->base, len);
        mv_cesa_sg_dma_iter_init(&iter->src, req->src, DMA_TO_DEVICE);
@@ -179,7 +179,6 @@ static int mv_cesa_ahash_pad_len(struct mv_cesa_ahash_req *creq)
 
 static int mv_cesa_ahash_pad_req(struct mv_cesa_ahash_req *creq, u8 *buf)
 {
-       __be64 bits = cpu_to_be64(creq->len << 3);
        unsigned int index, padlen;
 
        buf[0] = 0x80;
@@ -187,7 +186,14 @@ static int mv_cesa_ahash_pad_req(struct mv_cesa_ahash_req *creq, u8 *buf)
        index = creq->len & CESA_HASH_BLOCK_SIZE_MSK;
        padlen = mv_cesa_ahash_pad_len(creq);
        memset(buf + 1, 0, padlen - 1);
-       memcpy(buf + padlen, &bits, sizeof(bits));
+
+       if (creq->algo_le) {
+               __le64 bits = cpu_to_le64(creq->len << 3);
+               memcpy(buf + padlen, &bits, sizeof(bits));
+       } else {
+               __be64 bits = cpu_to_be64(creq->len << 3);
+               memcpy(buf + padlen, &bits, sizeof(bits));
+       }
 
        return padlen + 8;
 }
@@ -347,18 +353,21 @@ static int mv_cesa_ahash_process(struct crypto_async_request *req, u32 status)
                                   ahashreq->nbytes - creq->cache_ptr);
 
        if (creq->last_req) {
-               for (i = 0; i < digsize / 4; i++) {
-                       /*
-                        * Hardware provides MD5 digest in a different
-                        * endianness than SHA-1 and SHA-256 ones.
-                        */
-                       if (digsize == MD5_DIGEST_SIZE)
-                               creq->state[i] = cpu_to_le32(creq->state[i]);
-                       else
-                               creq->state[i] = cpu_to_be32(creq->state[i]);
-               }
+               /*
+                * Hardware's MD5 digest is in little endian format, but
+                * SHA in big endian format
+                */
+               if (creq->algo_le) {
+                       __le32 *result = (void *)ahashreq->result;
+
+                       for (i = 0; i < digsize / 4; i++)
+                               result[i] = cpu_to_le32(creq->state[i]);
+               } else {
+                       __be32 *result = (void *)ahashreq->result;
 
-               memcpy(ahashreq->result, creq->state, digsize);
+                       for (i = 0; i < digsize / 4; i++)
+                               result[i] = cpu_to_be32(creq->state[i]);
+               }
        }
 
        return ret;
@@ -404,7 +413,7 @@ static const struct mv_cesa_req_ops mv_cesa_ahash_req_ops = {
 };
 
 static int mv_cesa_ahash_init(struct ahash_request *req,
-                             struct mv_cesa_op_ctx *tmpl)
+                             struct mv_cesa_op_ctx *tmpl, bool algo_le)
 {
        struct mv_cesa_ahash_req *creq = ahash_request_ctx(req);
 
@@ -418,6 +427,7 @@ static int mv_cesa_ahash_init(struct ahash_request *req,
        mv_cesa_set_mac_op_frag_len(tmpl, 0);
        creq->op_tmpl = *tmpl;
        creq->len = 0;
+       creq->algo_le = algo_le;
 
        return 0;
 }
@@ -462,97 +472,76 @@ static int mv_cesa_ahash_cache_req(struct ahash_request *req, bool *cached)
 }
 
 static struct mv_cesa_op_ctx *
-mv_cesa_ahash_dma_add_cache(struct mv_cesa_tdma_chain *chain,
-                           struct mv_cesa_ahash_dma_iter *dma_iter,
-                           struct mv_cesa_ahash_req *creq,
-                           gfp_t flags)
+mv_cesa_dma_add_frag(struct mv_cesa_tdma_chain *chain,
+                    struct mv_cesa_op_ctx *tmpl, unsigned int frag_len,
+                    gfp_t flags)
 {
-       struct mv_cesa_ahash_dma_req *ahashdreq = &creq->req.dma;
-       struct mv_cesa_op_ctx *op = NULL;
+       struct mv_cesa_op_ctx *op;
        int ret;
 
-       if (!creq->cache_ptr)
-               return NULL;
+       op = mv_cesa_dma_add_op(chain, tmpl, false, flags);
+       if (IS_ERR(op))
+               return op;
 
-       ret = mv_cesa_dma_add_data_transfer(chain,
-                                           CESA_SA_DATA_SRAM_OFFSET,
-                                           ahashdreq->cache_dma,
-                                           creq->cache_ptr,
-                                           CESA_TDMA_DST_IN_SRAM,
-                                           flags);
+       /* Set the operation block fragment length. */
+       mv_cesa_set_mac_op_frag_len(op, frag_len);
+
+       /* Append dummy desc to launch operation */
+       ret = mv_cesa_dma_add_dummy_launch(chain, flags);
        if (ret)
                return ERR_PTR(ret);
 
-       if (!dma_iter->base.op_len) {
-               op = mv_cesa_dma_add_op(chain, &creq->op_tmpl, false, flags);
-               if (IS_ERR(op))
-                       return op;
-
-               mv_cesa_set_mac_op_frag_len(op, creq->cache_ptr);
-
-               /* Add dummy desc to launch crypto operation */
-               ret = mv_cesa_dma_add_dummy_launch(chain, flags);
-               if (ret)
-                       return ERR_PTR(ret);
-       }
+       if (mv_cesa_mac_op_is_first_frag(tmpl))
+               mv_cesa_update_op_cfg(tmpl,
+                                     CESA_SA_DESC_CFG_MID_FRAG,
+                                     CESA_SA_DESC_CFG_FRAG_MSK);
 
        return op;
 }
 
-static struct mv_cesa_op_ctx *
-mv_cesa_ahash_dma_add_data(struct mv_cesa_tdma_chain *chain,
-                          struct mv_cesa_ahash_dma_iter *dma_iter,
-                          struct mv_cesa_ahash_req *creq,
-                          gfp_t flags)
+static int
+mv_cesa_ahash_dma_add_cache(struct mv_cesa_tdma_chain *chain,
+                           struct mv_cesa_ahash_dma_iter *dma_iter,
+                           struct mv_cesa_ahash_req *creq,
+                           gfp_t flags)
 {
-       struct mv_cesa_op_ctx *op;
-       int ret;
-
-       op = mv_cesa_dma_add_op(chain, &creq->op_tmpl, false, flags);
-       if (IS_ERR(op))
-               return op;
-
-       mv_cesa_set_mac_op_frag_len(op, dma_iter->base.op_len);
-
-       if ((mv_cesa_get_op_cfg(&creq->op_tmpl) & CESA_SA_DESC_CFG_FRAG_MSK) ==
-           CESA_SA_DESC_CFG_FIRST_FRAG)
-               mv_cesa_update_op_cfg(&creq->op_tmpl,
-                                     CESA_SA_DESC_CFG_MID_FRAG,
-                                     CESA_SA_DESC_CFG_FRAG_MSK);
-
-       /* Add input transfers */
-       ret = mv_cesa_dma_add_op_transfers(chain, &dma_iter->base,
-                                          &dma_iter->src, flags);
-       if (ret)
-               return ERR_PTR(ret);
+       struct mv_cesa_ahash_dma_req *ahashdreq = &creq->req.dma;
 
-       /* Add dummy desc to launch crypto operation */
-       ret = mv_cesa_dma_add_dummy_launch(chain, flags);
-       if (ret)
-               return ERR_PTR(ret);
+       if (!creq->cache_ptr)
+               return 0;
 
-       return op;
+       return mv_cesa_dma_add_data_transfer(chain,
+                                            CESA_SA_DATA_SRAM_OFFSET,
+                                            ahashdreq->cache_dma,
+                                            creq->cache_ptr,
+                                            CESA_TDMA_DST_IN_SRAM,
+                                            flags);
 }
 
 static struct mv_cesa_op_ctx *
 mv_cesa_ahash_dma_last_req(struct mv_cesa_tdma_chain *chain,
                           struct mv_cesa_ahash_dma_iter *dma_iter,
                           struct mv_cesa_ahash_req *creq,
-                          struct mv_cesa_op_ctx *op,
-                          gfp_t flags)
+                          unsigned int frag_len, gfp_t flags)
 {
        struct mv_cesa_ahash_dma_req *ahashdreq = &creq->req.dma;
        unsigned int len, trailerlen, padoff = 0;
+       struct mv_cesa_op_ctx *op;
        int ret;
 
-       if (!creq->last_req)
-               return op;
+       if (frag_len) {
+               op = mv_cesa_dma_add_frag(chain, &creq->op_tmpl, frag_len,
+                                         flags);
+               if (IS_ERR(op))
+                       return op;
+       } else {
+               op = NULL;
+       }
 
        if (op && creq->len <= CESA_SA_DESC_MAC_SRC_TOTAL_LEN_MAX) {
                u32 frag = CESA_SA_DESC_CFG_NOT_FRAG;
 
-               if ((mv_cesa_get_op_cfg(op) & CESA_SA_DESC_CFG_FRAG_MSK) !=
-                   CESA_SA_DESC_CFG_FIRST_FRAG)
+               if (!mv_cesa_mac_op_is_first_frag(op))
                        frag = CESA_SA_DESC_CFG_LAST_FRAG;
 
                mv_cesa_update_op_cfg(op, frag, CESA_SA_DESC_CFG_FRAG_MSK);
@@ -590,18 +579,11 @@ mv_cesa_ahash_dma_last_req(struct mv_cesa_tdma_chain *chain,
        if (padoff >= trailerlen)
                return op;
 
-       if ((mv_cesa_get_op_cfg(&creq->op_tmpl) & CESA_SA_DESC_CFG_FRAG_MSK) !=
-           CESA_SA_DESC_CFG_FIRST_FRAG)
+       if (!mv_cesa_mac_op_is_first_frag(&creq->op_tmpl))
                mv_cesa_update_op_cfg(&creq->op_tmpl,
                                      CESA_SA_DESC_CFG_MID_FRAG,
                                      CESA_SA_DESC_CFG_FRAG_MSK);
 
-       op = mv_cesa_dma_add_op(chain, &creq->op_tmpl, false, flags);
-       if (IS_ERR(op))
-               return op;
-
-       mv_cesa_set_mac_op_frag_len(op, trailerlen - padoff);
-
        ret = mv_cesa_dma_add_data_transfer(chain,
                                            CESA_SA_DATA_SRAM_OFFSET,
                                            ahashdreq->padding_dma +
@@ -612,12 +594,8 @@ mv_cesa_ahash_dma_last_req(struct mv_cesa_tdma_chain *chain,
        if (ret)
                return ERR_PTR(ret);
 
-       /* Add dummy desc to launch crypto operation */
-       ret = mv_cesa_dma_add_dummy_launch(chain, flags);
-       if (ret)
-               return ERR_PTR(ret);
-
-       return op;
+       return mv_cesa_dma_add_frag(chain, &creq->op_tmpl, trailerlen - padoff,
+                                   flags);
 }
 
 static int mv_cesa_ahash_dma_req_init(struct ahash_request *req)
@@ -630,6 +608,7 @@ static int mv_cesa_ahash_dma_req_init(struct ahash_request *req)
        struct mv_cesa_tdma_chain chain;
        struct mv_cesa_ahash_dma_iter iter;
        struct mv_cesa_op_ctx *op = NULL;
+       unsigned int frag_len;
        int ret;
 
        dreq->chain.first = NULL;
@@ -647,26 +626,55 @@ static int mv_cesa_ahash_dma_req_init(struct ahash_request *req)
        mv_cesa_tdma_desc_iter_init(&chain);
        mv_cesa_ahash_req_iter_init(&iter, req);
 
-       op = mv_cesa_ahash_dma_add_cache(&chain, &iter,
-                                        creq, flags);
-       if (IS_ERR(op)) {
-               ret = PTR_ERR(op);
+       /*
+        * Add the cache (left-over data from a previous block) first.
+        * This will never overflow the SRAM size.
+        */
+       ret = mv_cesa_ahash_dma_add_cache(&chain, &iter, creq, flags);
+       if (ret)
                goto err_free_tdma;
-       }
 
-       do {
-               if (!iter.base.op_len)
-                       break;
+       if (iter.src.sg) {
+               /*
+                * Add all the new data, inserting an operation block and
+                * launch command between each full SRAM block-worth of
+                * data. We intentionally do not add the final op block.
+                */
+               while (true) {
+                       ret = mv_cesa_dma_add_op_transfers(&chain, &iter.base,
+                                                          &iter.src, flags);
+                       if (ret)
+                               goto err_free_tdma;
+
+                       frag_len = iter.base.op_len;
 
-               op = mv_cesa_ahash_dma_add_data(&chain, &iter,
-                                               creq, flags);
-               if (IS_ERR(op)) {
-                       ret = PTR_ERR(op);
-                       goto err_free_tdma;
+                       if (!mv_cesa_ahash_req_iter_next_op(&iter))
+                               break;
+
+                       op = mv_cesa_dma_add_frag(&chain, &creq->op_tmpl,
+                                                 frag_len, flags);
+                       if (IS_ERR(op)) {
+                               ret = PTR_ERR(op);
+                               goto err_free_tdma;
+                       }
                }
-       } while (mv_cesa_ahash_req_iter_next_op(&iter));
+       } else {
+               /* Account for the data that was in the cache. */
+               frag_len = iter.base.op_len;
+       }
+
+       /*
+        * At this point, frag_len indicates whether we have any data
+        * outstanding which needs an operation.  Queue up the final
+        * operation, which depends whether this is the final request.
+        */
+       if (creq->last_req)
+               op = mv_cesa_ahash_dma_last_req(&chain, &iter, creq, frag_len,
+                                               flags);
+       else if (frag_len)
+               op = mv_cesa_dma_add_frag(&chain, &creq->op_tmpl, frag_len,
+                                         flags);
 
-       op = mv_cesa_ahash_dma_last_req(&chain, &iter, creq, op, flags);
        if (IS_ERR(op)) {
                ret = PTR_ERR(op);
                goto err_free_tdma;
@@ -797,47 +805,50 @@ static int mv_cesa_ahash_finup(struct ahash_request *req)
        return ret;
 }
 
-static int mv_cesa_md5_init(struct ahash_request *req)
-{
-       struct mv_cesa_op_ctx tmpl;
-
-       mv_cesa_set_op_cfg(&tmpl, CESA_SA_DESC_CFG_MACM_MD5);
-
-       mv_cesa_ahash_init(req, &tmpl);
-
-       return 0;
-}
-
-static int mv_cesa_md5_export(struct ahash_request *req, void *out)
+static int mv_cesa_ahash_export(struct ahash_request *req, void *hash,
+                               u64 *len, void *cache)
 {
-       struct md5_state *out_state = out;
        struct crypto_ahash *ahash = crypto_ahash_reqtfm(req);
        struct mv_cesa_ahash_req *creq = ahash_request_ctx(req);
        unsigned int digsize = crypto_ahash_digestsize(ahash);
+       unsigned int blocksize;
+
+       blocksize = crypto_ahash_blocksize(ahash);
 
-       out_state->byte_count = creq->len;
-       memcpy(out_state->hash, creq->state, digsize);
-       memset(out_state->block, 0, sizeof(out_state->block));
+       *len = creq->len;
+       memcpy(hash, creq->state, digsize);
+       memset(cache, 0, blocksize);
        if (creq->cache)
-               memcpy(out_state->block, creq->cache, creq->cache_ptr);
+               memcpy(cache, creq->cache, creq->cache_ptr);
 
        return 0;
 }
 
-static int mv_cesa_md5_import(struct ahash_request *req, const void *in)
+static int mv_cesa_ahash_import(struct ahash_request *req, const void *hash,
+                               u64 len, const void *cache)
 {
-       const struct md5_state *in_state = in;
        struct crypto_ahash *ahash = crypto_ahash_reqtfm(req);
        struct mv_cesa_ahash_req *creq = ahash_request_ctx(req);
        unsigned int digsize = crypto_ahash_digestsize(ahash);
+       unsigned int blocksize;
        unsigned int cache_ptr;
        int ret;
 
-       creq->len = in_state->byte_count;
-       memcpy(creq->state, in_state->hash, digsize);
+       ret = crypto_ahash_init(req);
+       if (ret)
+               return ret;
+
+       blocksize = crypto_ahash_blocksize(ahash);
+       if (len >= blocksize)
+               mv_cesa_update_op_cfg(&creq->op_tmpl,
+                                     CESA_SA_DESC_CFG_MID_FRAG,
+                                     CESA_SA_DESC_CFG_FRAG_MSK);
+
+       creq->len = len;
+       memcpy(creq->state, hash, digsize);
        creq->cache_ptr = 0;
 
-       cache_ptr = creq->len % sizeof(in_state->block);
+       cache_ptr = do_div(len, blocksize);
        if (!cache_ptr)
                return 0;
 
@@ -845,12 +856,39 @@ static int mv_cesa_md5_import(struct ahash_request *req, const void *in)
        if (ret)
                return ret;
 
-       memcpy(creq->cache, in_state->block, cache_ptr);
+       memcpy(creq->cache, cache, cache_ptr);
        creq->cache_ptr = cache_ptr;
 
        return 0;
 }
 
+static int mv_cesa_md5_init(struct ahash_request *req)
+{
+       struct mv_cesa_op_ctx tmpl = { };
+
+       mv_cesa_set_op_cfg(&tmpl, CESA_SA_DESC_CFG_MACM_MD5);
+
+       mv_cesa_ahash_init(req, &tmpl, true);
+
+       return 0;
+}
+
+static int mv_cesa_md5_export(struct ahash_request *req, void *out)
+{
+       struct md5_state *out_state = out;
+
+       return mv_cesa_ahash_export(req, out_state->hash,
+                                   &out_state->byte_count, out_state->block);
+}
+
+static int mv_cesa_md5_import(struct ahash_request *req, const void *in)
+{
+       const struct md5_state *in_state = in;
+
+       return mv_cesa_ahash_import(req, in_state->hash, in_state->byte_count,
+                                   in_state->block);
+}
+
 static int mv_cesa_md5_digest(struct ahash_request *req)
 {
        int ret;
@@ -872,6 +910,7 @@ struct ahash_alg mv_md5_alg = {
        .import = mv_cesa_md5_import,
        .halg = {
                .digestsize = MD5_DIGEST_SIZE,
+               .statesize = sizeof(struct md5_state),
                .base = {
                        .cra_name = "md5",
                        .cra_driver_name = "mv-md5",
@@ -888,11 +927,11 @@ struct ahash_alg mv_md5_alg = {
 
 static int mv_cesa_sha1_init(struct ahash_request *req)
 {
-       struct mv_cesa_op_ctx tmpl;
+       struct mv_cesa_op_ctx tmpl = { };
 
        mv_cesa_set_op_cfg(&tmpl, CESA_SA_DESC_CFG_MACM_SHA1);
 
-       mv_cesa_ahash_init(req, &tmpl);
+       mv_cesa_ahash_init(req, &tmpl, false);
 
        return 0;
 }
@@ -900,44 +939,17 @@ static int mv_cesa_sha1_init(struct ahash_request *req)
 static int mv_cesa_sha1_export(struct ahash_request *req, void *out)
 {
        struct sha1_state *out_state = out;
-       struct crypto_ahash *ahash = crypto_ahash_reqtfm(req);
-       struct mv_cesa_ahash_req *creq = ahash_request_ctx(req);
-       unsigned int digsize = crypto_ahash_digestsize(ahash);
-
-       out_state->count = creq->len;
-       memcpy(out_state->state, creq->state, digsize);
-       memset(out_state->buffer, 0, sizeof(out_state->buffer));
-       if (creq->cache)
-               memcpy(out_state->buffer, creq->cache, creq->cache_ptr);
 
-       return 0;
+       return mv_cesa_ahash_export(req, out_state->state, &out_state->count,
+                                   out_state->buffer);
 }
 
 static int mv_cesa_sha1_import(struct ahash_request *req, const void *in)
 {
        const struct sha1_state *in_state = in;
-       struct crypto_ahash *ahash = crypto_ahash_reqtfm(req);
-       struct mv_cesa_ahash_req *creq = ahash_request_ctx(req);
-       unsigned int digsize = crypto_ahash_digestsize(ahash);
-       unsigned int cache_ptr;
-       int ret;
 
-       creq->len = in_state->count;
-       memcpy(creq->state, in_state->state, digsize);
-       creq->cache_ptr = 0;
-
-       cache_ptr = creq->len % SHA1_BLOCK_SIZE;
-       if (!cache_ptr)
-               return 0;
-
-       ret = mv_cesa_ahash_alloc_cache(req);
-       if (ret)
-               return ret;
-
-       memcpy(creq->cache, in_state->buffer, cache_ptr);
-       creq->cache_ptr = cache_ptr;
-
-       return 0;
+       return mv_cesa_ahash_import(req, in_state->state, in_state->count,
+                                   in_state->buffer);
 }
 
 static int mv_cesa_sha1_digest(struct ahash_request *req)
@@ -961,6 +973,7 @@ struct ahash_alg mv_sha1_alg = {
        .import = mv_cesa_sha1_import,
        .halg = {
                .digestsize = SHA1_DIGEST_SIZE,
+               .statesize = sizeof(struct sha1_state),
                .base = {
                        .cra_name = "sha1",
                        .cra_driver_name = "mv-sha1",
@@ -977,11 +990,11 @@ struct ahash_alg mv_sha1_alg = {
 
 static int mv_cesa_sha256_init(struct ahash_request *req)
 {
-       struct mv_cesa_op_ctx tmpl;
+       struct mv_cesa_op_ctx tmpl = { };
 
        mv_cesa_set_op_cfg(&tmpl, CESA_SA_DESC_CFG_MACM_SHA256);
 
-       mv_cesa_ahash_init(req, &tmpl);
+       mv_cesa_ahash_init(req, &tmpl, false);
 
        return 0;
 }
@@ -1000,44 +1013,17 @@ static int mv_cesa_sha256_digest(struct ahash_request *req)
 static int mv_cesa_sha256_export(struct ahash_request *req, void *out)
 {
        struct sha256_state *out_state = out;
-       struct crypto_ahash *ahash = crypto_ahash_reqtfm(req);
-       struct mv_cesa_ahash_req *creq = ahash_request_ctx(req);
-       unsigned int ds = crypto_ahash_digestsize(ahash);
-
-       out_state->count = creq->len;
-       memcpy(out_state->state, creq->state, ds);
-       memset(out_state->buf, 0, sizeof(out_state->buf));
-       if (creq->cache)
-               memcpy(out_state->buf, creq->cache, creq->cache_ptr);
 
-       return 0;
+       return mv_cesa_ahash_export(req, out_state->state, &out_state->count,
+                                   out_state->buf);
 }
 
 static int mv_cesa_sha256_import(struct ahash_request *req, const void *in)
 {
        const struct sha256_state *in_state = in;
-       struct crypto_ahash *ahash = crypto_ahash_reqtfm(req);
-       struct mv_cesa_ahash_req *creq = ahash_request_ctx(req);
-       unsigned int digsize = crypto_ahash_digestsize(ahash);
-       unsigned int cache_ptr;
-       int ret;
-
-       creq->len = in_state->count;
-       memcpy(creq->state, in_state->state, digsize);
-       creq->cache_ptr = 0;
 
-       cache_ptr = creq->len % SHA256_BLOCK_SIZE;
-       if (!cache_ptr)
-               return 0;
-
-       ret = mv_cesa_ahash_alloc_cache(req);
-       if (ret)
-               return ret;
-
-       memcpy(creq->cache, in_state->buf, cache_ptr);
-       creq->cache_ptr = cache_ptr;
-
-       return 0;
+       return mv_cesa_ahash_import(req, in_state->state, in_state->count,
+                                   in_state->buf);
 }
 
 struct ahash_alg mv_sha256_alg = {
@@ -1050,6 +1036,7 @@ struct ahash_alg mv_sha256_alg = {
        .import = mv_cesa_sha256_import,
        .halg = {
                .digestsize = SHA256_DIGEST_SIZE,
+               .statesize = sizeof(struct sha256_state),
                .base = {
                        .cra_name = "sha256",
                        .cra_driver_name = "mv-sha256",
@@ -1233,12 +1220,12 @@ static int mv_cesa_ahmac_cra_init(struct crypto_tfm *tfm)
 static int mv_cesa_ahmac_md5_init(struct ahash_request *req)
 {
        struct mv_cesa_hmac_ctx *ctx = crypto_tfm_ctx(req->base.tfm);
-       struct mv_cesa_op_ctx tmpl;
+       struct mv_cesa_op_ctx tmpl = { };
 
        mv_cesa_set_op_cfg(&tmpl, CESA_SA_DESC_CFG_MACM_HMAC_MD5);
        memcpy(tmpl.ctx.hash.iv, ctx->iv, sizeof(ctx->iv));
 
-       mv_cesa_ahash_init(req, &tmpl);
+       mv_cesa_ahash_init(req, &tmpl, true);
 
        return 0;
 }
@@ -1303,12 +1290,12 @@ struct ahash_alg mv_ahmac_md5_alg = {
 static int mv_cesa_ahmac_sha1_init(struct ahash_request *req)
 {
        struct mv_cesa_hmac_ctx *ctx = crypto_tfm_ctx(req->base.tfm);
-       struct mv_cesa_op_ctx tmpl;
+       struct mv_cesa_op_ctx tmpl = { };
 
        mv_cesa_set_op_cfg(&tmpl, CESA_SA_DESC_CFG_MACM_HMAC_SHA1);
        memcpy(tmpl.ctx.hash.iv, ctx->iv, sizeof(ctx->iv));
 
-       mv_cesa_ahash_init(req, &tmpl);
+       mv_cesa_ahash_init(req, &tmpl, false);
 
        return 0;
 }
@@ -1393,12 +1380,12 @@ static int mv_cesa_ahmac_sha256_setkey(struct crypto_ahash *tfm, const u8 *key,
 static int mv_cesa_ahmac_sha256_init(struct ahash_request *req)
 {
        struct mv_cesa_hmac_ctx *ctx = crypto_tfm_ctx(req->base.tfm);
-       struct mv_cesa_op_ctx tmpl;
+       struct mv_cesa_op_ctx tmpl = { };
 
        mv_cesa_set_op_cfg(&tmpl, CESA_SA_DESC_CFG_MACM_HMAC_SHA256);
        memcpy(tmpl.ctx.hash.iv, ctx->iv, sizeof(ctx->iv));
 
-       mv_cesa_ahash_init(req, &tmpl);
+       mv_cesa_ahash_init(req, &tmpl, false);
 
        return 0;
 }