summaryrefslogtreecommitdiff
path: root/drivers/char/hw_random/virtio-rng.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/char/hw_random/virtio-rng.c')
-rw-r--r--drivers/char/hw_random/virtio-rng.c40
1 files changed, 18 insertions, 22 deletions
diff --git a/drivers/char/hw_random/virtio-rng.c b/drivers/char/hw_random/virtio-rng.c
index e9b15bc18b4d..2e3139eda93b 100644
--- a/drivers/char/hw_random/virtio-rng.c
+++ b/drivers/char/hw_random/virtio-rng.c
@@ -28,17 +28,16 @@
static DEFINE_IDA(rng_index_ida);
struct virtrng_info {
- struct virtio_device *vdev;
struct hwrng hwrng;
struct virtqueue *vq;
- unsigned int data_avail;
struct completion have_data;
- bool busy;
char name[25];
+ unsigned int data_avail;
int index;
+ bool busy;
+ bool hwrng_register_done;
};
-static bool probe_done;
static void random_recv_done(struct virtqueue *vq)
{
@@ -69,13 +68,6 @@ static int virtio_read(struct hwrng *rng, void *buf, size_t size, bool wait)
int ret;
struct virtrng_info *vi = (struct virtrng_info *)rng->priv;
- /*
- * Don't ask host for data till we're setup. This call can
- * happen during hwrng_register(), after commit d9e7972619.
- */
- if (unlikely(!probe_done))
- return 0;
-
if (!vi->busy) {
vi->busy = true;
init_completion(&vi->have_data);
@@ -124,6 +116,7 @@ static int probe_common(struct virtio_device *vdev)
.cleanup = virtio_cleanup,
.priv = (unsigned long)vi,
.name = vi->name,
+ .quality = 1000,
};
vdev->priv = vi;
@@ -137,25 +130,17 @@ static int probe_common(struct virtio_device *vdev)
return err;
}
- err = hwrng_register(&vi->hwrng);
- if (err) {
- vdev->config->del_vqs(vdev);
- vi->vq = NULL;
- kfree(vi);
- ida_simple_remove(&rng_index_ida, index);
- return err;
- }
-
- probe_done = true;
return 0;
}
static void remove_common(struct virtio_device *vdev)
{
struct virtrng_info *vi = vdev->priv;
+
vdev->config->reset(vdev);
vi->busy = false;
- hwrng_unregister(&vi->hwrng);
+ if (vi->hwrng_register_done)
+ hwrng_unregister(&vi->hwrng);
vdev->config->del_vqs(vdev);
ida_simple_remove(&rng_index_ida, vi->index);
kfree(vi);
@@ -171,6 +156,16 @@ static void virtrng_remove(struct virtio_device *vdev)
remove_common(vdev);
}
+static void virtrng_scan(struct virtio_device *vdev)
+{
+ struct virtrng_info *vi = vdev->priv;
+ int err;
+
+ err = hwrng_register(&vi->hwrng);
+ if (!err)
+ vi->hwrng_register_done = true;
+}
+
#ifdef CONFIG_PM_SLEEP
static int virtrng_freeze(struct virtio_device *vdev)
{
@@ -195,6 +190,7 @@ static struct virtio_driver virtio_rng_driver = {
.id_table = id_table,
.probe = virtrng_probe,
.remove = virtrng_remove,
+ .scan = virtrng_scan,
#ifdef CONFIG_PM_SLEEP
.freeze = virtrng_freeze,
.restore = virtrng_restore,