drivers/char/hw_random/s390-trng.c

Source file repositories/reference/linux-study-clean/drivers/char/hw_random/s390-trng.c

File Facts

System
Linux kernel
Corpus path
drivers/char/hw_random/s390-trng.c
Extension
.c
Size
5527 bytes
Lines
257
Domain
Driver Families
Bucket
drivers/char
Inferred role
Driver Families: operation-table or driver-model contract
Status
pattern 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

static const struct file_operations trng_fops = {
	.owner		= THIS_MODULE,
	.open		= &trng_open,
	.release	= NULL,
	.read		= &trng_read,
	.llseek		= noop_llseek,
};

static struct miscdevice trng_dev = {
	.name	= "trng",
	.minor	= MISC_DYNAMIC_MINOR,
	.mode	= 0444,
	.fops	= &trng_fops,
	.groups = trng_dev_attr_groups,
};


/* hwrng_register */

static inline void _trng_hwrng_read(u8 *buf, size_t len)
{
	cpacf_trng(NULL, 0, buf, len);
	atomic64_add(len, &trng_hwrng_counter);
}

static int trng_hwrng_data_read(struct hwrng *rng, u32 *data)
{
	size_t len = sizeof(*data);

	_trng_hwrng_read((u8 *) data, len);

	DEBUG_DBG("trng_hwrng_data_read()=%zu\n", len);

	return len;
}

static int trng_hwrng_read(struct hwrng *rng, void *data, size_t max, bool wait)
{
	size_t len = max <= PAGE_SIZE ? max : PAGE_SIZE;

	_trng_hwrng_read((u8 *) data, len);

	DEBUG_DBG("trng_hwrng_read()=%zu\n", len);

	return len;
}

/*
 * hwrng register struct
 * The trng is supposed to have 100% entropy, and thus we register with a very
 * high quality value. If we ever have a better driver in the future, we should
 * change this value again when we merge this driver.
 */
static struct hwrng trng_hwrng_dev = {
	.name		= "s390-trng",
	.data_read	= trng_hwrng_data_read,
	.read		= trng_hwrng_read,
};


/* init and exit */

static void __init trng_debug_init(void)
{
	debug_info = debug_register("trng", 1, 1, 4 * sizeof(long));
	debug_register_view(debug_info, &debug_sprintf_view);
	debug_set_level(debug_info, 3);
}

static void trng_debug_exit(void)
{
	debug_unregister(debug_info);
}

static int __init trng_init(void)
{
	int ret;

	trng_debug_init();

	/* check if subfunction CPACF_PRNO_TRNG is available */
	if (!cpacf_query_func(CPACF_PRNO, CPACF_PRNO_TRNG)) {
		DEBUG_INFO("trng_init CPACF_PRNO_TRNG not available\n");
		ret = -ENODEV;
		goto out_dbg;
	}

	ret = misc_register(&trng_dev);
	if (ret) {
		DEBUG_WARN("trng_init misc_register() failed rc=%d\n", ret);

Annotation

Implementation Notes