]> git.kernelconcepts.de Git - karo-tx-linux.git/blobdiff - drivers/crypto/marvell/hash.c
Merge branch 'for-4.8/core' of git://git.kernel.dk/linux-block
[karo-tx-linux.git] / drivers / crypto / marvell / hash.c
index 7a5058da9151797cc95f48c5131a1ccedb2c1361..c35912b4fffb67c6142347d8e59bf4bdbfdccef0 100644 (file)
@@ -103,14 +103,14 @@ static inline void mv_cesa_ahash_dma_cleanup(struct ahash_request *req)
 
        dma_unmap_sg(cesa_dev->dev, req->src, creq->src_nents, DMA_TO_DEVICE);
        mv_cesa_ahash_dma_free_cache(&creq->req.dma);
-       mv_cesa_dma_cleanup(&creq->req.dma.base);
+       mv_cesa_dma_cleanup(&creq->base);
 }
 
 static inline void mv_cesa_ahash_cleanup(struct ahash_request *req)
 {
        struct mv_cesa_ahash_req *creq = ahash_request_ctx(req);
 
-       if (creq->req.base.type == CESA_DMA_REQ)
+       if (mv_cesa_req_get_type(&creq->base) == CESA_DMA_REQ)
                mv_cesa_ahash_dma_cleanup(req);
 }
 
@@ -118,7 +118,7 @@ static void mv_cesa_ahash_last_cleanup(struct ahash_request *req)
 {
        struct mv_cesa_ahash_req *creq = ahash_request_ctx(req);
 
-       if (creq->req.base.type == CESA_DMA_REQ)
+       if (mv_cesa_req_get_type(&creq->base) == CESA_DMA_REQ)
                mv_cesa_ahash_dma_last_cleanup(req);
 }
 
@@ -157,11 +157,23 @@ static void mv_cesa_ahash_std_step(struct ahash_request *req)
 {
        struct mv_cesa_ahash_req *creq = ahash_request_ctx(req);
        struct mv_cesa_ahash_std_req *sreq = &creq->req.std;
-       struct mv_cesa_engine *engine = sreq->base.engine;
+       struct mv_cesa_engine *engine = creq->base.engine;
        struct mv_cesa_op_ctx *op;
        unsigned int new_cache_ptr = 0;
        u32 frag_mode;
        size_t  len;
+       unsigned int digsize;
+       int i;
+
+       mv_cesa_adjust_op(engine, &creq->op_tmpl);
+       memcpy_toio(engine->sram, &creq->op_tmpl, sizeof(creq->op_tmpl));
+
+       digsize = crypto_ahash_digestsize(crypto_ahash_reqtfm(req));
+       for (i = 0; i < digsize / 4; i++)
+               writel_relaxed(creq->state[i], engine->regs + CESA_IVDIG(i));
+
+       mv_cesa_adjust_op(engine, &creq->op_tmpl);
+       memcpy_toio(engine->sram, &creq->op_tmpl, sizeof(creq->op_tmpl));
 
        if (creq->cache_ptr)
                memcpy_toio(engine->sram + CESA_SA_DATA_SRAM_OFFSET,
@@ -237,6 +249,8 @@ static void mv_cesa_ahash_std_step(struct ahash_request *req)
 
        mv_cesa_set_int_mask(engine, CESA_SA_INT_ACCEL0_DONE);
        writel_relaxed(CESA_SA_CFG_PARA_DIS, engine->regs + CESA_SA_CFG);
+       BUG_ON(readl(engine->regs + CESA_SA_CMD) &
+              CESA_SA_CMD_EN_CESA_SA_ACCL0);
        writel(CESA_SA_CMD_EN_CESA_SA_ACCL0, engine->regs + CESA_SA_CMD);
 }
 
@@ -254,20 +268,17 @@ static int mv_cesa_ahash_std_process(struct ahash_request *req, u32 status)
 static inline void mv_cesa_ahash_dma_prepare(struct ahash_request *req)
 {
        struct mv_cesa_ahash_req *creq = ahash_request_ctx(req);
-       struct mv_cesa_tdma_req *dreq = &creq->req.dma.base;
+       struct mv_cesa_req *basereq = &creq->base;
 
-       mv_cesa_dma_prepare(dreq, dreq->base.engine);
+       mv_cesa_dma_prepare(basereq, basereq->engine);
 }
 
 static void mv_cesa_ahash_std_prepare(struct ahash_request *req)
 {
        struct mv_cesa_ahash_req *creq = ahash_request_ctx(req);
        struct mv_cesa_ahash_std_req *sreq = &creq->req.std;
-       struct mv_cesa_engine *engine = sreq->base.engine;
 
        sreq->offset = 0;
-       mv_cesa_adjust_op(engine, &creq->op_tmpl);
-       memcpy_toio(engine->sram, &creq->op_tmpl, sizeof(creq->op_tmpl));
 }
 
 static void mv_cesa_ahash_step(struct crypto_async_request *req)
@@ -275,8 +286,8 @@ static void mv_cesa_ahash_step(struct crypto_async_request *req)
        struct ahash_request *ahashreq = ahash_request_cast(req);
        struct mv_cesa_ahash_req *creq = ahash_request_ctx(ahashreq);
 
-       if (creq->req.base.type == CESA_DMA_REQ)
-               mv_cesa_dma_step(&creq->req.dma.base);
+       if (mv_cesa_req_get_type(&creq->base) == CESA_DMA_REQ)
+               mv_cesa_dma_step(&creq->base);
        else
                mv_cesa_ahash_std_step(ahashreq);
 }
@@ -285,17 +296,20 @@ static int mv_cesa_ahash_process(struct crypto_async_request *req, u32 status)
 {
        struct ahash_request *ahashreq = ahash_request_cast(req);
        struct mv_cesa_ahash_req *creq = ahash_request_ctx(ahashreq);
-       struct mv_cesa_engine *engine = creq->req.base.engine;
-       unsigned int digsize;
-       int ret, i;
 
-       if (creq->req.base.type == CESA_DMA_REQ)
-               ret = mv_cesa_dma_process(&creq->req.dma.base, status);
-       else
-               ret = mv_cesa_ahash_std_process(ahashreq, status);
+       if (mv_cesa_req_get_type(&creq->base) == CESA_DMA_REQ)
+               return mv_cesa_dma_process(&creq->base, status);
 
-       if (ret == -EINPROGRESS)
-               return ret;
+       return mv_cesa_ahash_std_process(ahashreq, status);
+}
+
+static void mv_cesa_ahash_complete(struct crypto_async_request *req)
+{
+       struct ahash_request *ahashreq = ahash_request_cast(req);
+       struct mv_cesa_ahash_req *creq = ahash_request_ctx(ahashreq);
+       struct mv_cesa_engine *engine = creq->base.engine;
+       unsigned int digsize;
+       int i;
 
        digsize = crypto_ahash_digestsize(crypto_ahash_reqtfm(ahashreq));
        for (i = 0; i < digsize / 4; i++)
@@ -325,7 +339,7 @@ static int mv_cesa_ahash_process(struct crypto_async_request *req, u32 status)
                }
        }
 
-       return ret;
+       atomic_sub(ahashreq->nbytes, &engine->load);
 }
 
 static void mv_cesa_ahash_prepare(struct crypto_async_request *req,
@@ -333,19 +347,13 @@ static void mv_cesa_ahash_prepare(struct crypto_async_request *req,
 {
        struct ahash_request *ahashreq = ahash_request_cast(req);
        struct mv_cesa_ahash_req *creq = ahash_request_ctx(ahashreq);
-       unsigned int digsize;
-       int i;
 
-       creq->req.base.engine = engine;
+       creq->base.engine = engine;
 
-       if (creq->req.base.type == CESA_DMA_REQ)
+       if (mv_cesa_req_get_type(&creq->base) == CESA_DMA_REQ)
                mv_cesa_ahash_dma_prepare(ahashreq);
        else
                mv_cesa_ahash_std_prepare(ahashreq);
-
-       digsize = crypto_ahash_digestsize(crypto_ahash_reqtfm(ahashreq));
-       for (i = 0; i < digsize / 4; i++)
-               writel_relaxed(creq->state[i], engine->regs + CESA_IVDIG(i));
 }
 
 static void mv_cesa_ahash_req_cleanup(struct crypto_async_request *req)
@@ -362,8 +370,8 @@ static void mv_cesa_ahash_req_cleanup(struct crypto_async_request *req)
 static const struct mv_cesa_req_ops mv_cesa_ahash_req_ops = {
        .step = mv_cesa_ahash_step,
        .process = mv_cesa_ahash_process,
-       .prepare = mv_cesa_ahash_prepare,
        .cleanup = mv_cesa_ahash_req_cleanup,
+       .complete = mv_cesa_ahash_complete,
 };
 
 static int mv_cesa_ahash_init(struct ahash_request *req,
@@ -553,15 +561,14 @@ static int mv_cesa_ahash_dma_req_init(struct ahash_request *req)
        struct mv_cesa_ahash_req *creq = ahash_request_ctx(req);
        gfp_t flags = (req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP) ?
                      GFP_KERNEL : GFP_ATOMIC;
-       struct mv_cesa_ahash_dma_req *ahashdreq = &creq->req.dma;
-       struct mv_cesa_tdma_req *dreq = &ahashdreq->base;
+       struct mv_cesa_req *basereq = &creq->base;
        struct mv_cesa_ahash_dma_iter iter;
        struct mv_cesa_op_ctx *op = NULL;
        unsigned int frag_len;
        int ret;
 
-       dreq->chain.first = NULL;
-       dreq->chain.last = NULL;
+       basereq->chain.first = NULL;
+       basereq->chain.last = NULL;
 
        if (creq->src_nents) {
                ret = dma_map_sg(cesa_dev->dev, req->src, creq->src_nents,
@@ -572,14 +579,14 @@ static int mv_cesa_ahash_dma_req_init(struct ahash_request *req)
                }
        }
 
-       mv_cesa_tdma_desc_iter_init(&dreq->chain);
+       mv_cesa_tdma_desc_iter_init(&basereq->chain);
        mv_cesa_ahash_req_iter_init(&iter, req);
 
        /*
         * 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(&dreq->chain, &iter, creq, flags);
+       ret = mv_cesa_ahash_dma_add_cache(&basereq->chain, &iter, creq, flags);
        if (ret)
                goto err_free_tdma;
 
@@ -590,7 +597,7 @@ static int mv_cesa_ahash_dma_req_init(struct ahash_request *req)
                 * data. We intentionally do not add the final op block.
                 */
                while (true) {
-                       ret = mv_cesa_dma_add_op_transfers(&dreq->chain,
+                       ret = mv_cesa_dma_add_op_transfers(&basereq->chain,
                                                           &iter.base,
                                                           &iter.src, flags);
                        if (ret)
@@ -601,7 +608,7 @@ static int mv_cesa_ahash_dma_req_init(struct ahash_request *req)
                        if (!mv_cesa_ahash_req_iter_next_op(&iter))
                                break;
 
-                       op = mv_cesa_dma_add_frag(&dreq->chain, &creq->op_tmpl,
+                       op = mv_cesa_dma_add_frag(&basereq->chain, &creq->op_tmpl,
                                                  frag_len, flags);
                        if (IS_ERR(op)) {
                                ret = PTR_ERR(op);
@@ -619,10 +626,10 @@ static int mv_cesa_ahash_dma_req_init(struct ahash_request *req)
         * operation, which depends whether this is the final request.
         */
        if (creq->last_req)
-               op = mv_cesa_ahash_dma_last_req(&dreq->chain, &iter, creq,
+               op = mv_cesa_ahash_dma_last_req(&basereq->chain, &iter, creq,
                                                frag_len, flags);
        else if (frag_len)
-               op = mv_cesa_dma_add_frag(&dreq->chain, &creq->op_tmpl,
+               op = mv_cesa_dma_add_frag(&basereq->chain, &creq->op_tmpl,
                                          frag_len, flags);
 
        if (IS_ERR(op)) {
@@ -632,7 +639,7 @@ static int mv_cesa_ahash_dma_req_init(struct ahash_request *req)
 
        if (op) {
                /* Add dummy desc to wait for crypto operation end */
-               ret = mv_cesa_dma_add_dummy_end(&dreq->chain, flags);
+               ret = mv_cesa_dma_add_dummy_end(&basereq->chain, flags);
                if (ret)
                        goto err_free_tdma;
        }
@@ -643,10 +650,13 @@ static int mv_cesa_ahash_dma_req_init(struct ahash_request *req)
        else
                creq->cache_ptr = 0;
 
+       basereq->chain.last->flags |= (CESA_TDMA_END_OF_REQ |
+                                      CESA_TDMA_BREAK_CHAIN);
+
        return 0;
 
 err_free_tdma:
-       mv_cesa_dma_cleanup(dreq);
+       mv_cesa_dma_cleanup(basereq);
        dma_unmap_sg(cesa_dev->dev, req->src, creq->src_nents, DMA_TO_DEVICE);
 
 err:
@@ -660,11 +670,6 @@ static int mv_cesa_ahash_req_init(struct ahash_request *req, bool *cached)
        struct mv_cesa_ahash_req *creq = ahash_request_ctx(req);
        int ret;
 
-       if (cesa_dev->caps->has_tdma)
-               creq->req.base.type = CESA_DMA_REQ;
-       else
-               creq->req.base.type = CESA_STD_REQ;
-
        creq->src_nents = sg_nents_for_len(req->src, req->nbytes);
        if (creq->src_nents < 0) {
                dev_err(cesa_dev->dev, "Invalid number of src SG");
@@ -678,19 +683,19 @@ static int mv_cesa_ahash_req_init(struct ahash_request *req, bool *cached)
        if (*cached)
                return 0;
 
-       if (creq->req.base.type == CESA_DMA_REQ)
+       if (cesa_dev->caps->has_tdma)
                ret = mv_cesa_ahash_dma_req_init(req);
 
        return ret;
 }
 
-static int mv_cesa_ahash_update(struct ahash_request *req)
+static int mv_cesa_ahash_queue_req(struct ahash_request *req)
 {
        struct mv_cesa_ahash_req *creq = ahash_request_ctx(req);
+       struct mv_cesa_engine *engine;
        bool cached = false;
        int ret;
 
-       creq->len += req->nbytes;
        ret = mv_cesa_ahash_req_init(req, &cached);
        if (ret)
                return ret;
@@ -698,61 +703,48 @@ static int mv_cesa_ahash_update(struct ahash_request *req)
        if (cached)
                return 0;
 
-       ret = mv_cesa_queue_req(&req->base);
+       engine = mv_cesa_select_engine(req->nbytes);
+       mv_cesa_ahash_prepare(&req->base, engine);
+
+       ret = mv_cesa_queue_req(&req->base, &creq->base);
+
        if (mv_cesa_req_needs_cleanup(&req->base, ret))
                mv_cesa_ahash_cleanup(req);
 
        return ret;
 }
 
+static int mv_cesa_ahash_update(struct ahash_request *req)
+{
+       struct mv_cesa_ahash_req *creq = ahash_request_ctx(req);
+
+       creq->len += req->nbytes;
+
+       return mv_cesa_ahash_queue_req(req);
+}
+
 static int mv_cesa_ahash_final(struct ahash_request *req)
 {
        struct mv_cesa_ahash_req *creq = ahash_request_ctx(req);
        struct mv_cesa_op_ctx *tmpl = &creq->op_tmpl;
-       bool cached = false;
-       int ret;
 
        mv_cesa_set_mac_op_total_len(tmpl, creq->len);
        creq->last_req = true;
        req->nbytes = 0;
 
-       ret = mv_cesa_ahash_req_init(req, &cached);
-       if (ret)
-               return ret;
-
-       if (cached)
-               return 0;
-
-       ret = mv_cesa_queue_req(&req->base);
-       if (mv_cesa_req_needs_cleanup(&req->base, ret))
-               mv_cesa_ahash_cleanup(req);
-
-       return ret;
+       return mv_cesa_ahash_queue_req(req);
 }
 
 static int mv_cesa_ahash_finup(struct ahash_request *req)
 {
        struct mv_cesa_ahash_req *creq = ahash_request_ctx(req);
        struct mv_cesa_op_ctx *tmpl = &creq->op_tmpl;
-       bool cached = false;
-       int ret;
 
        creq->len += req->nbytes;
        mv_cesa_set_mac_op_total_len(tmpl, creq->len);
        creq->last_req = true;
 
-       ret = mv_cesa_ahash_req_init(req, &cached);
-       if (ret)
-               return ret;
-
-       if (cached)
-               return 0;
-
-       ret = mv_cesa_queue_req(&req->base);
-       if (mv_cesa_req_needs_cleanup(&req->base, ret))
-               mv_cesa_ahash_cleanup(req);
-
-       return ret;
+       return mv_cesa_ahash_queue_req(req);
 }
 
 static int mv_cesa_ahash_export(struct ahash_request *req, void *hash,