| @@ -280,13 +280,32 @@ static void mv_cesa_ahash_std_prepare(struct ahash_request *req) · 279 unmodified lines |
| 280 | 280 | sreq->offset = 0; |
| 281 | 281 | } |
| 282 | 282 | |
| 283 | +static void mv_cesa_ahash_dma_step(struct ahash_request *req) |
| 284 | +{ |
| 285 | + struct mv_cesa_ahash_req *creq = ahash_request_ctx(req); |
| 286 | + struct mv_cesa_req *base = &creq->base; |
| 287 | + |
| 288 | + /* We must explicitly set the digest state. */ |
| 289 | + if (base->chain.first->flags & CESA_TDMA_SET_STATE) { |
| 290 | + struct mv_cesa_engine *engine = base->engine; |
| 291 | + int i; |
| 292 | + |
| 293 | + /* Set the hash state in the IVDIG regs. */ |
| 294 | + for (i = 0; i < ARRAY_SIZE(creq->state); i++) |
| 295 | + writel_relaxed(creq->state[i], engine->regs + |
| 296 | + CESA_IVDIG(i)); |
| 297 | + } |
| 298 | + |
| 299 | + mv_cesa_dma_step(base); |
| 300 | +} |
| 301 | + |
| 283 | 302 | static void mv_cesa_ahash_step(struct crypto_async_request *req) |
| 284 | 303 | { |
| 285 | 304 | struct ahash_request *ahashreq = ahash_request_cast(req); |
| 286 | 305 | struct mv_cesa_ahash_req *creq = ahash_request_ctx(ahashreq); |
| 287 | 306 | |
| 288 | 307 | if (mv_cesa_req_get_type(&creq->base) == CESA_DMA_REQ) |
| 289 | | − mv_cesa_dma_step(&creq->base); |
| 308 | + mv_cesa_ahash_dma_step(ahashreq); |
| 290 | 309 | else |
| 291 | 310 | mv_cesa_ahash_std_step(ahashreq); |
| 292 | 311 | } |
| @@ -584,12 +603,16 @@ static int mv_cesa_ahash_dma_req_init(struct ahash_request *req) · 291 unmodified lines |
| 584 | 603 | struct mv_cesa_ahash_dma_iter iter; |
| 585 | 604 | struct mv_cesa_op_ctx *op = NULL; |
| 586 | 605 | unsigned int frag_len; |
| 606 | + bool set_state = false; |
| 587 | 607 | int ret; |
| 588 | 608 | u32 type; |
| 589 | 609 | |
| 590 | 610 | basereq->chain.first = NULL; |
| 591 | 611 | basereq->chain.last = NULL; |
| 592 | 612 | |
| 613 | + if (!mv_cesa_mac_op_is_first_frag(&creq->op_tmpl)) |
| 614 | + set_state = true; |
| 615 | + |
| 593 | 616 | if (creq->src_nents) { |
| 594 | 617 | ret = dma_map_sg(cesa_dev->dev, req->src, creq->src_nents, |
| 595 | 618 | DMA_TO_DEVICE); |
| @@ -683,6 +706,15 @@ static int mv_cesa_ahash_dma_req_init(struct ahash_request *req) · 87 unmodified lines |
| 683 | 706 | if (type != CESA_TDMA_RESULT) |
| 684 | 707 | basereq->chain.last->flags |= CESA_TDMA_BREAK_CHAIN; |
| 685 | 708 | |
| 709 | + if (set_state) { |
| 710 | + /* |
| 711 | + * Put the CESA_TDMA_SET_STATE flag on the first tdma desc to |
| 712 | + * let the step logic know that the IVDIG registers should be |
| 713 | + * explicitly set before launching a TDMA chain. |
| 714 | + */ |
| 715 | + basereq->chain.first->flags |= CESA_TDMA_SET_STATE; |
| 716 | + } |
| 717 | + |
| 686 | 718 | return 0; |
| 687 | 719 | |
| 688 | 720 | err_free_tdma: |