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 <lviv...@redhat.com>
---
 drivers/char/hw_random/virtio-rng.c | 24 ++++++++++--------------
 1 file changed, 10 insertions(+), 14 deletions(-)

diff --git a/drivers/char/hw_random/virtio-rng.c 
b/drivers/char/hw_random/virtio-rng.c
index 8ba97cf4ca8f..0b3c9b643495 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,16 @@ 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);
+
        sg_init_one(&sg, vi->data, sizeof(vi->data));
 
        /* There should always be room for one buffer. */
@@ -69,6 +68,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 +99,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 +121,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 +157,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 +178,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);
-- 
2.31.1

_______________________________________________
Virtualization mailing list
Virtualization@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/virtualization

Reply via email to