drivers/crypto/aspeed/aspeed-hace-hash.c

Source file repositories/reference/linux-study-clean/drivers/crypto/aspeed/aspeed-hace-hash.c

File Facts

System
Linux kernel
Corpus path
drivers/crypto/aspeed/aspeed-hace-hash.c
Extension
.c
Size
23770 bytes
Lines
826
Domain
Driver Families
Bucket
drivers/crypto
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

else if (rctx->flags & SHA_FLAGS_FINUP) {
		if (round_up(length, rctx->block_size) + rctx->block_size >
		    ASPEED_CRYPTO_SRC_DMA_BUF_LEN)
			length = round_down(length - 1, rctx->block_size);
		else
			final = true;
	} else
		length -= remain;
	memcpy_from_sglist(hash_engine->ahash_src_addr, rctx->src_sg, rctx->offset, length);
	aspeed_ahash_update_counter(rctx, length);
	if (final)
		length += aspeed_ahash_fill_padding(
			hace_dev, rctx, hash_engine->ahash_src_addr + length);

	rctx->digest_dma_addr = dma_map_single(hace_dev->dev, rctx->digest,
					       SHA512_DIGEST_SIZE,
					       DMA_BIDIRECTIONAL);
	if (dma_mapping_error(hace_dev->dev, rctx->digest_dma_addr)) {
		dev_warn(hace_dev->dev, "dma_map() rctx digest error\n");
		return -ENOMEM;
	}

	hash_engine->src_length = length;
	hash_engine->src_dma = hash_engine->ahash_src_dma_addr;
	hash_engine->digest_dma = rctx->digest_dma_addr;

	return 0;
}

/*
 * Prepare DMA buffer as SG list buffer before
 * hardware engine processing.
 */
static int aspeed_ahash_dma_prepare_sg(struct aspeed_hace_dev *hace_dev)
{
	struct aspeed_engine_hash *hash_engine = &hace_dev->hash_engine;
	struct ahash_request *req = hash_engine->req;
	struct aspeed_sham_reqctx *rctx = ahash_request_ctx(req);
	bool final = rctx->flags & SHA_FLAGS_FINUP;
	int remain, sg_len, i, max_sg_nents;
	unsigned int length, offset, total;
	struct aspeed_sg_list *src_list;
	struct scatterlist *s;
	int rc = 0;

	offset = rctx->offset;
	length = rctx->total - offset;
	remain = final ? 0 : length - round_down(length, rctx->block_size);
	length -= remain;

	AHASH_DBG(hace_dev, "%s:0x%x, %s:0x%x, %s:0x%x\n",
		  "rctx total", rctx->total,
		  "length", length, "remain", remain);

	sg_len = dma_map_sg(hace_dev->dev, rctx->src_sg, rctx->src_nents,
			    DMA_TO_DEVICE);
	if (!sg_len) {
		dev_warn(hace_dev->dev, "dma_map_sg() src error\n");
		rc = -ENOMEM;
		goto end;
	}

	max_sg_nents = ASPEED_HASH_SRC_DMA_BUF_LEN / sizeof(*src_list) - final;
	sg_len = min(sg_len, max_sg_nents);
	src_list = (struct aspeed_sg_list *)hash_engine->ahash_src_addr;
	rctx->digest_dma_addr = dma_map_single(hace_dev->dev, rctx->digest,
					       SHA512_DIGEST_SIZE,
					       DMA_BIDIRECTIONAL);
	if (dma_mapping_error(hace_dev->dev, rctx->digest_dma_addr)) {
		dev_warn(hace_dev->dev, "dma_map() rctx digest error\n");
		rc = -ENOMEM;
		goto free_src_sg;
	}

	total = 0;
	for_each_sg(rctx->src_sg, s, sg_len, i) {
		u32 phy_addr = sg_dma_address(s);
		u32 len = sg_dma_len(s);

		if (len <= offset) {
			offset -= len;
			continue;
		}

		len -= offset;
		phy_addr += offset;
		offset = 0;

		if (length > len)
			length -= len;

Annotation

Implementation Notes