// SPDX-License-Identifier: GPL-2.0 #include #include "eip123.h" #define EIP123_RNG_QUALITY 1024 #define EIP123_RNG_BUFFER_SIZE 512 #define EIP123_MAX_BYTES 64 static u8 *get_rng_buffer(struct eip123 *eip, size_t len) { struct eip123_result ret; u8 *dma_buf, *target_buf = NULL; dma_buf = kmalloc(len, GFP_KERNEL | GFP_DMA); if (!dma_buf) goto out; ret = eip123_hw_rng(eip->hw, dma_buf, len); if (ret.error) goto dma_buf; target_buf = devm_kmalloc(eip->dev, len, GFP_KERNEL); if (!target_buf) goto dma_buf; /* we cannot dma into a devm buffer */ memcpy(target_buf, dma_buf, len); dma_buf: kfree(dma_buf); out: return target_buf; } static void free_rng_buffer(struct eip123 *eip) { if (!eip->rng_buffer) return; devm_kfree(eip->dev, eip->rng_buffer); eip->rng_buffer = NULL; eip->rng_ptr = NULL; } static size_t available_bytes(struct eip123 *eip) { if (!eip->rng_buffer) return 0; return (EIP123_RNG_BUFFER_SIZE - (eip->rng_ptr - eip->rng_buffer)); } static int rng_read(struct hwrng *rng, void *data, size_t max, bool wait) { struct eip123 *eip = container_of(rng, struct eip123, rng); max = min_t(size_t, max, EIP123_MAX_BYTES); if (!max) return -EIO; if (max > available_bytes(eip)) { free_rng_buffer(eip); return -EIO; } memcpy(data, eip->rng_ptr, max); eip->rng_ptr += max; return max; } int eip123_rng_init(struct eip123 *eip) { struct hwrng *rng = &eip->rng; eip->rng_buffer = get_rng_buffer(eip, EIP123_RNG_BUFFER_SIZE); if (!eip->rng_buffer) return -EIO; eip->rng_ptr = eip->rng_buffer; rng->name = KBUILD_MODNAME; rng->read = rng_read; rng->quality = EIP123_RNG_QUALITY; return devm_hwrng_register(eip->dev, rng); }