summaryrefslogtreecommitdiffstats
path: root/drivers/char/hw_random
diff options
context:
space:
mode:
authorLaurent Vivier <lvivier@redhat.com>2021-10-28 12:11:11 +0200
committerMichael S. Tsirkin <mst@redhat.com>2021-11-01 10:26:47 +0100
commit9a4b612d675b03f7fc9fa1957ca399c8223f3954 (patch)
treeeb4288b405a7821130982fc69ace34f1f76d8d36 /drivers/char/hw_random
parenthwrng: virtio - don't waste entropy (diff)
downloadlinux-9a4b612d675b03f7fc9fa1957ca399c8223f3954.tar.xz
linux-9a4b612d675b03f7fc9fa1957ca399c8223f3954.zip
hwrng: virtio - always add a pending request
If we ensure we have already some data available by enqueuing again the buffer once data are exhausted, we can return what we have without waiting for the device answer. Signed-off-by: Laurent Vivier <lvivier@redhat.com> Link: https://lore.kernel.org/r/20211028101111.128049-5-lvivier@redhat.com Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Diffstat (limited to 'drivers/char/hw_random')
-rw-r--r--drivers/char/hw_random/virtio-rng.c26
1 files changed, 12 insertions, 14 deletions
diff --git a/drivers/char/hw_random/virtio-rng.c b/drivers/char/hw_random/virtio-rng.c
index 8ba97cf4ca8f..0a7dde135db1 100644
--- a/drivers/char/hw_random/virtio-rng.c
+++ b/drivers/char/hw_random/virtio-rng.c
@@ -20,7 +20,6 @@ struct virtrng_info {
struct virtqueue *vq;
char name[25];
int index;
- bool busy;
bool hwrng_register_done;
bool hwrng_removed;
/* data transfer */
@@ -44,16 +43,18 @@ static void random_recv_done(struct virtqueue *vq)
return;
vi->data_idx = 0;
- vi->busy = false;
complete(&vi->have_data);
}
-/* The host will fill any buffer we give it with sweet, sweet randomness. */
-static void register_buffer(struct virtrng_info *vi)
+static void request_entropy(struct virtrng_info *vi)
{
struct scatterlist sg;
+ reinit_completion(&vi->have_data);
+ vi->data_avail = 0;
+ vi->data_idx = 0;
+
sg_init_one(&sg, vi->data, sizeof(vi->data));
/* There should always be room for one buffer. */
@@ -69,6 +70,8 @@ static unsigned int copy_data(struct virtrng_info *vi, void *buf,
memcpy(buf, vi->data + vi->data_idx, size);
vi->data_idx += size;
vi->data_avail -= size;
+ if (vi->data_avail == 0)
+ request_entropy(vi);
return size;
}
@@ -98,13 +101,7 @@ static int virtio_read(struct hwrng *rng, void *buf, size_t size, bool wait)
* so either size is 0 or data_avail is 0
*/
while (size != 0) {
- /* data_avail is 0 */
- if (!vi->busy) {
- /* no pending request, ask for more */
- vi->busy = true;
- reinit_completion(&vi->have_data);
- register_buffer(vi);
- }
+ /* data_avail is 0 but a request is pending */
ret = wait_for_completion_killable(&vi->have_data);
if (ret < 0)
return ret;
@@ -126,8 +123,7 @@ static void virtio_cleanup(struct hwrng *rng)
{
struct virtrng_info *vi = (struct virtrng_info *)rng->priv;
- if (vi->busy)
- complete(&vi->have_data);
+ complete(&vi->have_data);
}
static int probe_common(struct virtio_device *vdev)
@@ -163,6 +159,9 @@ static int probe_common(struct virtio_device *vdev)
goto err_find;
}
+ /* we always have a pending entropy request */
+ request_entropy(vi);
+
return 0;
err_find:
@@ -181,7 +180,6 @@ static void remove_common(struct virtio_device *vdev)
vi->data_idx = 0;
complete(&vi->have_data);
vdev->config->reset(vdev);
- vi->busy = false;
if (vi->hwrng_register_done)
hwrng_unregister(&vi->hwrng);
vdev->config->del_vqs(vdev);