diff options
| -rw-r--r-- | drivers/char/hw_random/virtio-rng.c | 41 | ||||
| -rw-r--r-- | include/linux/hw_random.h | 2 |
2 files changed, 24 insertions, 19 deletions
diff --git a/drivers/char/hw_random/virtio-rng.c b/drivers/char/hw_random/virtio-rng.c index 5b25daa7f798..f3e71501de54 100644 --- a/drivers/char/hw_random/virtio-rng.c +++ b/drivers/char/hw_random/virtio-rng.c | |||
| @@ -25,6 +25,7 @@ | |||
| 25 | #include <linux/virtio_rng.h> | 25 | #include <linux/virtio_rng.h> |
| 26 | #include <linux/module.h> | 26 | #include <linux/module.h> |
| 27 | 27 | ||
| 28 | static DEFINE_IDA(rng_index_ida); | ||
| 28 | 29 | ||
| 29 | struct virtrng_info { | 30 | struct virtrng_info { |
| 30 | struct virtio_device *vdev; | 31 | struct virtio_device *vdev; |
| @@ -33,6 +34,8 @@ struct virtrng_info { | |||
| 33 | unsigned int data_avail; | 34 | unsigned int data_avail; |
| 34 | struct completion have_data; | 35 | struct completion have_data; |
| 35 | bool busy; | 36 | bool busy; |
| 37 | char name[25]; | ||
| 38 | int index; | ||
| 36 | }; | 39 | }; |
| 37 | 40 | ||
| 38 | static void random_recv_done(struct virtqueue *vq) | 41 | static void random_recv_done(struct virtqueue *vq) |
| @@ -92,41 +95,45 @@ static void virtio_cleanup(struct hwrng *rng) | |||
| 92 | 95 | ||
| 93 | static int probe_common(struct virtio_device *vdev) | 96 | static int probe_common(struct virtio_device *vdev) |
| 94 | { | 97 | { |
| 95 | int err, i; | 98 | int err, index; |
| 96 | struct virtrng_info *vi = NULL; | 99 | struct virtrng_info *vi = NULL; |
| 97 | 100 | ||
| 98 | vi = kzalloc(sizeof(struct virtrng_info), GFP_KERNEL); | 101 | vi = kzalloc(sizeof(struct virtrng_info), GFP_KERNEL); |
| 99 | vi->hwrng.name = kmalloc(40, GFP_KERNEL); | 102 | if (!vi) |
| 103 | return -ENOMEM; | ||
| 104 | |||
| 105 | vi->index = index = ida_simple_get(&rng_index_ida, 0, 0, GFP_KERNEL); | ||
| 106 | if (index < 0) { | ||
| 107 | kfree(vi); | ||
| 108 | return index; | ||
| 109 | } | ||
| 110 | sprintf(vi->name, "virtio_rng.%d", index); | ||
| 100 | init_completion(&vi->have_data); | 111 | init_completion(&vi->have_data); |
| 101 | 112 | ||
| 102 | vi->hwrng.read = virtio_read; | 113 | vi->hwrng = (struct hwrng) { |
| 103 | vi->hwrng.cleanup = virtio_cleanup; | 114 | .read = virtio_read, |
| 104 | vi->hwrng.priv = (unsigned long)vi; | 115 | .cleanup = virtio_cleanup, |
| 116 | .priv = (unsigned long)vi, | ||
| 117 | .name = vi->name, | ||
| 118 | }; | ||
| 105 | vdev->priv = vi; | 119 | vdev->priv = vi; |
| 106 | 120 | ||
| 107 | /* We expect a single virtqueue. */ | 121 | /* We expect a single virtqueue. */ |
| 108 | vi->vq = virtio_find_single_vq(vdev, random_recv_done, "input"); | 122 | vi->vq = virtio_find_single_vq(vdev, random_recv_done, "input"); |
| 109 | if (IS_ERR(vi->vq)) { | 123 | if (IS_ERR(vi->vq)) { |
| 110 | err = PTR_ERR(vi->vq); | 124 | err = PTR_ERR(vi->vq); |
| 111 | kfree(vi->hwrng.name); | ||
| 112 | vi->vq = NULL; | 125 | vi->vq = NULL; |
| 113 | kfree(vi); | 126 | kfree(vi); |
| 114 | vi = NULL; | 127 | ida_simple_remove(&rng_index_ida, index); |
| 115 | return err; | 128 | return err; |
| 116 | } | 129 | } |
| 117 | 130 | ||
| 118 | i = 0; | 131 | err = hwrng_register(&vi->hwrng); |
| 119 | do { | ||
| 120 | sprintf(vi->hwrng.name, "virtio_rng.%d", i++); | ||
| 121 | err = hwrng_register(&vi->hwrng); | ||
| 122 | } while (err == -EEXIST); | ||
| 123 | |||
| 124 | if (err) { | 132 | if (err) { |
| 125 | vdev->config->del_vqs(vdev); | 133 | vdev->config->del_vqs(vdev); |
| 126 | kfree(vi->hwrng.name); | ||
| 127 | vi->vq = NULL; | 134 | vi->vq = NULL; |
| 128 | kfree(vi); | 135 | kfree(vi); |
| 129 | vi = NULL; | 136 | ida_simple_remove(&rng_index_ida, index); |
| 130 | return err; | 137 | return err; |
| 131 | } | 138 | } |
| 132 | 139 | ||
| @@ -140,10 +147,8 @@ static void remove_common(struct virtio_device *vdev) | |||
| 140 | vi->busy = false; | 147 | vi->busy = false; |
| 141 | hwrng_unregister(&vi->hwrng); | 148 | hwrng_unregister(&vi->hwrng); |
| 142 | vdev->config->del_vqs(vdev); | 149 | vdev->config->del_vqs(vdev); |
| 143 | kfree(vi->hwrng.name); | 150 | ida_simple_remove(&rng_index_ida, vi->index); |
| 144 | vi->vq = NULL; | ||
| 145 | kfree(vi); | 151 | kfree(vi); |
| 146 | vi = NULL; | ||
| 147 | } | 152 | } |
| 148 | 153 | ||
| 149 | static int virtrng_probe(struct virtio_device *vdev) | 154 | static int virtrng_probe(struct virtio_device *vdev) |
diff --git a/include/linux/hw_random.h b/include/linux/hw_random.h index 02d9c87be54c..b4b0eef5fddf 100644 --- a/include/linux/hw_random.h +++ b/include/linux/hw_random.h | |||
| @@ -31,7 +31,7 @@ | |||
| 31 | * @priv: Private data, for use by the RNG driver. | 31 | * @priv: Private data, for use by the RNG driver. |
| 32 | */ | 32 | */ |
| 33 | struct hwrng { | 33 | struct hwrng { |
| 34 | char *name; | 34 | const char *name; |
| 35 | int (*init)(struct hwrng *rng); | 35 | int (*init)(struct hwrng *rng); |
| 36 | void (*cleanup)(struct hwrng *rng); | 36 | void (*cleanup)(struct hwrng *rng); |
| 37 | int (*data_present)(struct hwrng *rng, int wait); | 37 | int (*data_present)(struct hwrng *rng, int wait); |
