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>
This commit is contained in:
Родитель
5c8e933050
Коммит
9a4b612d67
|
@ -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);
|
||||
|
|
Загрузка…
Ссылка в новой задаче