Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Laurent Vivier and committed by
Michael S. Tsirkin
9a4b612d 5c8e9330

+12 -14
+12 -14
drivers/char/hw_random/virtio-rng.c
··· 20 20 struct virtqueue *vq; 21 21 char name[25]; 22 22 int index; 23 - bool busy; 24 23 bool hwrng_register_done; 25 24 bool hwrng_removed; 26 25 /* data transfer */ ··· 43 44 return; 44 45 45 46 vi->data_idx = 0; 46 - vi->busy = false; 47 47 48 48 complete(&vi->have_data); 49 49 } 50 50 51 - /* The host will fill any buffer we give it with sweet, sweet randomness. */ 52 - static void register_buffer(struct virtrng_info *vi) 51 + static void request_entropy(struct virtrng_info *vi) 53 52 { 54 53 struct scatterlist sg; 54 + 55 + reinit_completion(&vi->have_data); 56 + vi->data_avail = 0; 57 + vi->data_idx = 0; 55 58 56 59 sg_init_one(&sg, vi->data, sizeof(vi->data)); 57 60 ··· 70 69 memcpy(buf, vi->data + vi->data_idx, size); 71 70 vi->data_idx += size; 72 71 vi->data_avail -= size; 72 + if (vi->data_avail == 0) 73 + request_entropy(vi); 73 74 return size; 74 75 } 75 76 ··· 101 98 * so either size is 0 or data_avail is 0 102 99 */ 103 100 while (size != 0) { 104 - /* data_avail is 0 */ 105 - if (!vi->busy) { 106 - /* no pending request, ask for more */ 107 - vi->busy = true; 108 - reinit_completion(&vi->have_data); 109 - register_buffer(vi); 110 - } 101 + /* data_avail is 0 but a request is pending */ 111 102 ret = wait_for_completion_killable(&vi->have_data); 112 103 if (ret < 0) 113 104 return ret; ··· 123 126 { 124 127 struct virtrng_info *vi = (struct virtrng_info *)rng->priv; 125 128 126 - if (vi->busy) 127 - complete(&vi->have_data); 129 + complete(&vi->have_data); 128 130 } 129 131 130 132 static int probe_common(struct virtio_device *vdev) ··· 159 163 goto err_find; 160 164 } 161 165 166 + /* we always have a pending entropy request */ 167 + request_entropy(vi); 168 + 162 169 return 0; 163 170 164 171 err_find: ··· 180 181 vi->data_idx = 0; 181 182 complete(&vi->have_data); 182 183 vdev->config->reset(vdev); 183 - vi->busy = false; 184 184 if (vi->hwrng_register_done) 185 185 hwrng_unregister(&vi->hwrng); 186 186 vdev->config->del_vqs(vdev);