#define CESA_TDMA_DUMMY                                0
 #define CESA_TDMA_DATA                         1
 #define CESA_TDMA_OP                           2
-#define CESA_TDMA_IV                           3
+#define CESA_TDMA_RESULT                       3
 
 /**
  * struct mv_cesa_tdma_desc - TDMA descriptor
        struct dma_pool *op_pool;
        struct dma_pool *cache_pool;
        struct dma_pool *padding_pool;
-       struct dma_pool *iv_pool;
 };
 
 /**
        memset(chain, 0, sizeof(*chain));
 }
 
-int mv_cesa_dma_add_iv_op(struct mv_cesa_tdma_chain *chain, dma_addr_t src,
+int mv_cesa_dma_add_result_op(struct mv_cesa_tdma_chain *chain, dma_addr_t src,
                          u32 size, u32 flags, gfp_t gfp_flags);
 
 struct mv_cesa_op_ctx *mv_cesa_dma_add_op(struct mv_cesa_tdma_chain *chain,
 
                struct mv_cesa_req *basereq;
 
                basereq = &creq->base;
-               memcpy(ablkreq->info, basereq->chain.last->data, ivsize);
+               memcpy(ablkreq->info, basereq->chain.last->op->ctx.blkcipher.iv,
+                      ivsize);
        } else {
                memcpy_fromio(ablkreq->info,
                              engine->sram + CESA_SA_CRYPT_IV_SRAM_OFFSET,
 
        /* Add output data for IV */
        ivsize = crypto_ablkcipher_ivsize(crypto_ablkcipher_reqtfm(req));
-       ret = mv_cesa_dma_add_iv_op(&basereq->chain, CESA_SA_CRYPT_IV_SRAM_OFFSET,
-                                   ivsize, CESA_TDMA_SRC_IN_SRAM, flags);
+       ret = mv_cesa_dma_add_result_op(&basereq->chain, CESA_SA_CFG_SRAM_OFFSET,
+                                   CESA_SA_DATA_SRAM_OFFSET,
+                                   CESA_TDMA_SRC_IN_SRAM, flags);
 
        if (ret)
                goto err_free_tdma;
 
                if (type == CESA_TDMA_OP)
                        dma_pool_free(cesa_dev->dma->op_pool, tdma->op,
                                      le32_to_cpu(tdma->src));
-               else if (type == CESA_TDMA_IV)
-                       dma_pool_free(cesa_dev->dma->iv_pool, tdma->data,
-                                     le32_to_cpu(tdma->dst));
 
                tdma = tdma->next;
                dma_pool_free(cesa_dev->dma->tdma_desc_pool, old_tdma,
        return new_tdma;
 }
 
-int mv_cesa_dma_add_iv_op(struct mv_cesa_tdma_chain *chain, dma_addr_t src,
+int mv_cesa_dma_add_result_op(struct mv_cesa_tdma_chain *chain, dma_addr_t src,
                          u32 size, u32 flags, gfp_t gfp_flags)
 {
-
-       struct mv_cesa_tdma_desc *tdma;
-       u8 *iv;
-       dma_addr_t dma_handle;
+       struct mv_cesa_tdma_desc *tdma, *op_desc;
 
        tdma = mv_cesa_dma_add_desc(chain, gfp_flags);
        if (IS_ERR(tdma))
                return PTR_ERR(tdma);
 
-       iv = dma_pool_alloc(cesa_dev->dma->iv_pool, gfp_flags, &dma_handle);
-       if (!iv)
-               return -ENOMEM;
+       /* We re-use an existing op_desc object to retrieve the context
+        * and result instead of allocating a new one.
+        * There is at least one object of this type in a CESA crypto
+        * req, just pick the first one in the chain.
+        */
+       for (op_desc = chain->first; op_desc; op_desc = op_desc->next) {
+               u32 type = op_desc->flags & CESA_TDMA_TYPE_MSK;
+
+               if (type == CESA_TDMA_OP)
+                       break;
+       }
+
+       if (!op_desc)
+               return -EIO;
 
        tdma->byte_cnt = cpu_to_le32(size | BIT(31));
        tdma->src = src;
-       tdma->dst = cpu_to_le32(dma_handle);
-       tdma->data = iv;
+       tdma->dst = op_desc->src;
+       tdma->op = op_desc->op;
 
        flags &= (CESA_TDMA_DST_IN_SRAM | CESA_TDMA_SRC_IN_SRAM);
-       tdma->flags = flags | CESA_TDMA_IV;
+       tdma->flags = flags | CESA_TDMA_RESULT;
        return 0;
 }