|
@@ -280,13 +280,32 @@ static void mv_cesa_ahash_std_prepare(struct ahash_request *req)
|
|
sreq->offset = 0;
|
|
sreq->offset = 0;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+static void mv_cesa_ahash_dma_step(struct ahash_request *req)
|
|
|
|
+{
|
|
|
|
+ struct mv_cesa_ahash_req *creq = ahash_request_ctx(req);
|
|
|
|
+ struct mv_cesa_req *base = &creq->base;
|
|
|
|
+
|
|
|
|
+ /* We must explicitly set the digest state. */
|
|
|
|
+ if (base->chain.first->flags & CESA_TDMA_SET_STATE) {
|
|
|
|
+ struct mv_cesa_engine *engine = base->engine;
|
|
|
|
+ int i;
|
|
|
|
+
|
|
|
|
+ /* Set the hash state in the IVDIG regs. */
|
|
|
|
+ for (i = 0; i < ARRAY_SIZE(creq->state); i++)
|
|
|
|
+ writel_relaxed(creq->state[i], engine->regs +
|
|
|
|
+ CESA_IVDIG(i));
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ mv_cesa_dma_step(base);
|
|
|
|
+}
|
|
|
|
+
|
|
static void mv_cesa_ahash_step(struct crypto_async_request *req)
|
|
static void mv_cesa_ahash_step(struct crypto_async_request *req)
|
|
{
|
|
{
|
|
struct ahash_request *ahashreq = ahash_request_cast(req);
|
|
struct ahash_request *ahashreq = ahash_request_cast(req);
|
|
struct mv_cesa_ahash_req *creq = ahash_request_ctx(ahashreq);
|
|
struct mv_cesa_ahash_req *creq = ahash_request_ctx(ahashreq);
|
|
|
|
|
|
if (mv_cesa_req_get_type(&creq->base) == CESA_DMA_REQ)
|
|
if (mv_cesa_req_get_type(&creq->base) == CESA_DMA_REQ)
|
|
- mv_cesa_dma_step(&creq->base);
|
|
|
|
|
|
+ mv_cesa_ahash_dma_step(ahashreq);
|
|
else
|
|
else
|
|
mv_cesa_ahash_std_step(ahashreq);
|
|
mv_cesa_ahash_std_step(ahashreq);
|
|
}
|
|
}
|
|
@@ -584,12 +603,16 @@ static int mv_cesa_ahash_dma_req_init(struct ahash_request *req)
|
|
struct mv_cesa_ahash_dma_iter iter;
|
|
struct mv_cesa_ahash_dma_iter iter;
|
|
struct mv_cesa_op_ctx *op = NULL;
|
|
struct mv_cesa_op_ctx *op = NULL;
|
|
unsigned int frag_len;
|
|
unsigned int frag_len;
|
|
|
|
+ bool set_state = false;
|
|
int ret;
|
|
int ret;
|
|
u32 type;
|
|
u32 type;
|
|
|
|
|
|
basereq->chain.first = NULL;
|
|
basereq->chain.first = NULL;
|
|
basereq->chain.last = NULL;
|
|
basereq->chain.last = NULL;
|
|
|
|
|
|
|
|
+ if (!mv_cesa_mac_op_is_first_frag(&creq->op_tmpl))
|
|
|
|
+ set_state = true;
|
|
|
|
+
|
|
if (creq->src_nents) {
|
|
if (creq->src_nents) {
|
|
ret = dma_map_sg(cesa_dev->dev, req->src, creq->src_nents,
|
|
ret = dma_map_sg(cesa_dev->dev, req->src, creq->src_nents,
|
|
DMA_TO_DEVICE);
|
|
DMA_TO_DEVICE);
|
|
@@ -683,6 +706,15 @@ static int mv_cesa_ahash_dma_req_init(struct ahash_request *req)
|
|
if (type != CESA_TDMA_RESULT)
|
|
if (type != CESA_TDMA_RESULT)
|
|
basereq->chain.last->flags |= CESA_TDMA_BREAK_CHAIN;
|
|
basereq->chain.last->flags |= CESA_TDMA_BREAK_CHAIN;
|
|
|
|
|
|
|
|
+ if (set_state) {
|
|
|
|
+ /*
|
|
|
|
+ * Put the CESA_TDMA_SET_STATE flag on the first tdma desc to
|
|
|
|
+ * let the step logic know that the IVDIG registers should be
|
|
|
|
+ * explicitly set before launching a TDMA chain.
|
|
|
|
+ */
|
|
|
|
+ basereq->chain.first->flags |= CESA_TDMA_SET_STATE;
|
|
|
|
+ }
|
|
|
|
+
|
|
return 0;
|
|
return 0;
|
|
|
|
|
|
err_free_tdma:
|
|
err_free_tdma:
|