drivers/crypto/marvell/cesa/tdma.c

Source file repositories/reference/linux-study-clean/drivers/crypto/marvell/cesa/tdma.c

File Facts

System
Linux kernel
Corpus path
drivers/crypto/marvell/cesa/tdma.c
Extension
.c
Size
10440 bytes
Lines
414
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

if (tdma->flags & CESA_TDMA_END_OF_REQ) {
			struct crypto_async_request *backlog = NULL;
			struct mv_cesa_ctx *ctx;
			u32 current_status;

			spin_lock_bh(&engine->lock);
			/*
			 * if req is NULL, this means we're processing the
			 * request in engine->req.
			 */
			if (!req)
				req = engine->req;
			else
				req = mv_cesa_dequeue_req_locked(engine,
								 &backlog);

			/* Re-chaining to the next request */
			engine->chain_hw.first = tdma->next;
			tdma->next = NULL;

			/* If this is the last request, clear the chain */
			if (engine->chain_hw.first == NULL)
				engine->chain_hw.last  = NULL;
			spin_unlock_bh(&engine->lock);

			ctx = crypto_tfm_ctx(req->tfm);
			current_status = (tdma->cur_dma == tdma_cur) ?
					  status : CESA_SA_INT_ACC0_IDMA_DONE;
			res = ctx->ops->process(req, current_status);
			ctx->ops->complete(req);

			if (res == 0)
				mv_cesa_engine_enqueue_complete_request(engine,
									req);

			if (backlog)
				crypto_request_complete(backlog, -EINPROGRESS);
		}

		if (res || tdma->cur_dma == tdma_cur)
			break;
	}

	/*
	 * Save the last request in error to engine->req, so that the core
	 * knows which request was faulty
	 */
	if (res) {
		spin_lock_bh(&engine->lock);
		engine->req = req;
		spin_unlock_bh(&engine->lock);
	}

	return res;
}

static struct mv_cesa_tdma_desc *
mv_cesa_dma_add_desc(struct mv_cesa_tdma_chain *chain, gfp_t flags)
{
	struct mv_cesa_tdma_desc *new_tdma = NULL;
	dma_addr_t dma_handle;

	new_tdma = dma_pool_zalloc(cesa_dev->dma->tdma_desc_pool, flags,
				   &dma_handle);
	if (!new_tdma)
		return ERR_PTR(-ENOMEM);

	new_tdma->cur_dma = dma_handle;
	if (chain->last) {
		chain->last->next_dma = cpu_to_le32(dma_handle);
		chain->last->next = new_tdma;
	} else {
		chain->first = new_tdma;
	}

	chain->last = new_tdma;

	return new_tdma;
}

int mv_cesa_dma_add_result_op(struct mv_cesa_tdma_chain *chain, dma_addr_t src,
			  u32 size, u32 flags, gfp_t gfp_flags)
{
	struct mv_cesa_tdma_desc *tdma, *op_desc;

	tdma = mv_cesa_dma_add_desc(chain, gfp_flags);
	if (IS_ERR(tdma))
		return PTR_ERR(tdma);

	/* We re-use an existing op_desc object to retrieve the context

Annotation

Implementation Notes