mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-16 00:34:20 +08:00
hwrng: virtio - always add a pending request
[ Upstream commit9a4b612d67
] 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> Stable-dep-of:ac52578d6e
("hwrng: virtio - Fix race on data_avail and actual data") Signed-off-by: Sasha Levin <sashal@kernel.org>
This commit is contained in:
parent
9a9ef96529
commit
64410e7b03
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user