int mv_cesa_dma_add_op_transfers(struct mv_cesa_tdma_chain *chain, struct mv_cesa_dma_iter *dma_iter, struct mv_cesa_sg_dma_iter *sgiter, gfp_t gfp_flags) { u32 flags = sgiter->dir == DMA_TO_DEVICE ? CESA_TDMA_DST_IN_SRAM : CESA_TDMA_SRC_IN_SRAM; unsigned int len; do { dma_addr_t dst, src; int ret; len = mv_cesa_req_dma_iter_transfer_len(dma_iter, sgiter); if (sgiter->dir == DMA_TO_DEVICE) { dst = CESA_SA_DATA_SRAM_OFFSET + sgiter->op_offset; src = sg_dma_address(sgiter->sg) + sgiter->offset; } else { dst = sg_dma_address(sgiter->sg) + sgiter->offset; src = CESA_SA_DATA_SRAM_OFFSET + sgiter->op_offset; } ret = mv_cesa_dma_add_data_transfer(chain, dst, src, len, flags, gfp_flags); if (ret) return ret; } while (mv_cesa_req_dma_iter_next_transfer(dma_iter, sgiter, len)); return 0; }
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_ahash_dma_req *ahashdreq = &creq->req.dma; int ret; if (!creq->cache_ptr) return 0; ret = mv_cesa_ahash_dma_alloc_cache(ahashdreq, flags); if (ret) return ret; memcpy(ahashdreq->cache, creq->cache, creq->cache_ptr); 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, 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 the transfer is smaller than our maximum length, and we have * some data outstanding, we can ask the engine to finish the hash. */ if (creq->len <= CESA_SA_DESC_MAC_SRC_TOTAL_LEN_MAX && frag_len) { op = mv_cesa_dma_add_frag(chain, &creq->op_tmpl, frag_len, flags); if (IS_ERR(op)) return op; mv_cesa_set_mac_op_total_len(op, creq->len); mv_cesa_update_op_cfg(op, mv_cesa_mac_op_is_first_frag(op) ? CESA_SA_DESC_CFG_NOT_FRAG : CESA_SA_DESC_CFG_LAST_FRAG, CESA_SA_DESC_CFG_FRAG_MSK); return op; } /* * The request is longer than the engine can handle, or we have * no data outstanding. Manually generate the padding, adding it * as a "mid" fragment. */ ret = mv_cesa_ahash_dma_alloc_padding(ahashdreq, flags); if (ret) return ERR_PTR(ret); trailerlen = mv_cesa_ahash_pad_req(creq, ahashdreq->padding); len = min(CESA_SA_SRAM_PAYLOAD_SIZE - frag_len, trailerlen); if (len) { ret = mv_cesa_dma_add_data_transfer(chain, CESA_SA_DATA_SRAM_OFFSET + frag_len, ahashdreq->padding_dma, len, CESA_TDMA_DST_IN_SRAM, flags); if (ret) return ERR_PTR(ret); op = mv_cesa_dma_add_frag(chain, &creq->op_tmpl, frag_len + len, flags); if (IS_ERR(op)) return op; if (len == trailerlen) return op; padoff += len; } ret = mv_cesa_dma_add_data_transfer(chain, CESA_SA_DATA_SRAM_OFFSET, ahashdreq->padding_dma + padoff, trailerlen - padoff, CESA_TDMA_DST_IN_SRAM, flags); if (ret) return ERR_PTR(ret); return mv_cesa_dma_add_frag(chain, &creq->op_tmpl, trailerlen - padoff, flags); }