コード例 #1
0
ファイル: tdma.c プロジェクト: 020gzh/linux
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;
}
コード例 #2
0
ファイル: hash.c プロジェクト: AK101111/linux
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);
}
コード例 #3
0
ファイル: hash.c プロジェクト: AK101111/linux
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);
}