drivers/crypto/caam/caamrng.c

Source file repositories/reference/linux-study-clean/drivers/crypto/caam/caamrng.c

File Facts

System
Linux kernel
Corpus path
drivers/crypto/caam/caamrng.c
Extension
.c
Size
6787 bytes
Lines
314
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

struct caam_rng_ctx {
	struct hwrng rng;
	struct device *jrdev;
	struct device *ctrldev;
	void *desc_async;
	void *desc_sync;
	struct work_struct worker;
	struct kfifo fifo;
};

struct caam_rng_job_ctx {
	struct completion *done;
	int *err;
};

static struct caam_rng_ctx *to_caam_rng_ctx(struct hwrng *r)
{
	return (struct caam_rng_ctx *)r->priv;
}

static void caam_rng_done(struct device *jrdev, u32 *desc, u32 err,
			  void *context)
{
	struct caam_rng_job_ctx *jctx = context;

	if (err)
		*jctx->err = caam_jr_strstatus(jrdev, err);

	complete(jctx->done);
}

static u32 *caam_init_desc(u32 *desc, dma_addr_t dst_dma)
{
	init_job_desc(desc, 0);	/* + 1 cmd_sz */
	/* Generate random bytes: + 1 cmd_sz */
	append_operation(desc, OP_ALG_ALGSEL_RNG | OP_TYPE_CLASS1_ALG |
			 OP_ALG_PR_ON);
	/* Store bytes: + 1 cmd_sz + caam_ptr_sz  */
	append_fifo_store(desc, dst_dma,
			  CAAM_RNG_MAX_FIFO_STORE_SIZE, FIFOST_TYPE_RNGSTORE);

	print_hex_dump_debug("rng job desc@: ", DUMP_PREFIX_ADDRESS,
			     16, 4, desc, desc_bytes(desc), 1);

	return desc;
}

static int caam_rng_read_one(struct device *jrdev,
			     void *dst, int len,
			     void *desc,
			     struct completion *done)
{
	dma_addr_t dst_dma;
	int err, ret = 0;
	struct caam_rng_job_ctx jctx = {
		.done = done,
		.err  = &ret,
	};

	len = CAAM_RNG_MAX_FIFO_STORE_SIZE;

	dst_dma = dma_map_single(jrdev, dst, len, DMA_FROM_DEVICE);
	if (dma_mapping_error(jrdev, dst_dma)) {
		dev_err(jrdev, "unable to map destination memory\n");
		return -ENOMEM;
	}

	init_completion(done);
	err = caam_jr_enqueue(jrdev,
			      caam_init_desc(desc, dst_dma),
			      caam_rng_done, &jctx);
	if (err == -EINPROGRESS) {
		wait_for_completion(done);
		err = 0;
	}

	dma_unmap_single(jrdev, dst_dma, len, DMA_FROM_DEVICE);

	return err ?: (ret ?: len);
}

static void caam_rng_fill_async(struct caam_rng_ctx *ctx)
{
	struct scatterlist sg[1];
	struct completion done;
	int len, nents;

	sg_init_table(sg, ARRAY_SIZE(sg));
	nents = kfifo_dma_in_prepare(&ctx->fifo, sg, ARRAY_SIZE(sg),
				     CAAM_RNG_MAX_FIFO_STORE_SIZE);

Annotation

Implementation Notes