Commit 9a4b612d authored by Laurent Vivier's avatar Laurent Vivier Committed by Michael S. Tsirkin

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: default avatarLaurent Vivier <lvivier@redhat.com>
Link: https://lore.kernel.org/r/20211028101111.128049-5-lvivier@redhat.comSigned-off-by: default avatarMichael S. Tsirkin <mst@redhat.com>
parent 5c8e9330
...@@ -20,7 +20,6 @@ struct virtrng_info { ...@@ -20,7 +20,6 @@ struct virtrng_info {
struct virtqueue *vq; struct virtqueue *vq;
char name[25]; char name[25];
int index; int index;
bool busy;
bool hwrng_register_done; bool hwrng_register_done;
bool hwrng_removed; bool hwrng_removed;
/* data transfer */ /* data transfer */
...@@ -44,16 +43,18 @@ static void random_recv_done(struct virtqueue *vq) ...@@ -44,16 +43,18 @@ static void random_recv_done(struct virtqueue *vq)
return; return;
vi->data_idx = 0; vi->data_idx = 0;
vi->busy = false;
complete(&vi->have_data); complete(&vi->have_data);
} }
/* The host will fill any buffer we give it with sweet, sweet randomness. */ static void request_entropy(struct virtrng_info *vi)
static void register_buffer(struct virtrng_info *vi)
{ {
struct scatterlist sg; 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)); sg_init_one(&sg, vi->data, sizeof(vi->data));
/* There should always be room for one buffer. */ /* There should always be room for one buffer. */
...@@ -69,6 +70,8 @@ static unsigned int copy_data(struct virtrng_info *vi, void *buf, ...@@ -69,6 +70,8 @@ static unsigned int copy_data(struct virtrng_info *vi, void *buf,
memcpy(buf, vi->data + vi->data_idx, size); memcpy(buf, vi->data + vi->data_idx, size);
vi->data_idx += size; vi->data_idx += size;
vi->data_avail -= size; vi->data_avail -= size;
if (vi->data_avail == 0)
request_entropy(vi);
return size; return size;
} }
...@@ -98,13 +101,7 @@ static int virtio_read(struct hwrng *rng, void *buf, size_t size, bool wait) ...@@ -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 * so either size is 0 or data_avail is 0
*/ */
while (size != 0) { while (size != 0) {
/* data_avail is 0 */ /* data_avail is 0 but a request is pending */
if (!vi->busy) {
/* no pending request, ask for more */
vi->busy = true;
reinit_completion(&vi->have_data);
register_buffer(vi);
}
ret = wait_for_completion_killable(&vi->have_data); ret = wait_for_completion_killable(&vi->have_data);
if (ret < 0) if (ret < 0)
return ret; return ret;
...@@ -126,7 +123,6 @@ static void virtio_cleanup(struct hwrng *rng) ...@@ -126,7 +123,6 @@ static void virtio_cleanup(struct hwrng *rng)
{ {
struct virtrng_info *vi = (struct virtrng_info *)rng->priv; struct virtrng_info *vi = (struct virtrng_info *)rng->priv;
if (vi->busy)
complete(&vi->have_data); complete(&vi->have_data);
} }
...@@ -163,6 +159,9 @@ static int probe_common(struct virtio_device *vdev) ...@@ -163,6 +159,9 @@ static int probe_common(struct virtio_device *vdev)
goto err_find; goto err_find;
} }
/* we always have a pending entropy request */
request_entropy(vi);
return 0; return 0;
err_find: err_find:
...@@ -181,7 +180,6 @@ static void remove_common(struct virtio_device *vdev) ...@@ -181,7 +180,6 @@ static void remove_common(struct virtio_device *vdev)
vi->data_idx = 0; vi->data_idx = 0;
complete(&vi->have_data); complete(&vi->have_data);
vdev->config->reset(vdev); vdev->config->reset(vdev);
vi->busy = false;
if (vi->hwrng_register_done) if (vi->hwrng_register_done)
hwrng_unregister(&vi->hwrng); hwrng_unregister(&vi->hwrng);
vdev->config->del_vqs(vdev); vdev->config->del_vqs(vdev);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment