aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/char
diff options
context:
space:
mode:
authorSasha Levin <sasha.levin@oracle.com>2014-05-15 22:12:43 -0400
committerRusty Russell <rusty@rustcorp.com.au>2014-05-18 19:56:40 -0400
commita17597d3b418ca5a394d14724ccfc295cb3186c8 (patch)
treea2421dacd4bef70854f146bdaf01eb6305160338 /drivers/char
parente5d23a8cc38c555f9f3a40dcc5d14030105df9a8 (diff)
virtio-rng: fixes for device registration/unregistration
There are several fixes in this patch (mostly because it's hard splitting them up): - Revert the name field in struct hwrng back to 'const'. Also, don't do an extra kmalloc for the name - just wasteful. - Deal with allocation failures properly. - Use IDA to allocate device number instead of brute forcing one. Signed-off-by: Sasha Levin <sasha.levin@oracle.com> Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Diffstat (limited to 'drivers/char')
-rw-r--r--drivers/char/hw_random/virtio-rng.c41
1 files changed, 23 insertions, 18 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
28static DEFINE_IDA(rng_index_ida);
28 29
29struct virtrng_info { 30struct 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
38static void random_recv_done(struct virtqueue *vq) 41static void random_recv_done(struct virtqueue *vq)
@@ -92,41 +95,45 @@ static void virtio_cleanup(struct hwrng *rng)
92 95
93static int probe_common(struct virtio_device *vdev) 96static 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
149static int virtrng_probe(struct virtio_device *vdev) 154static int virtrng_probe(struct virtio_device *vdev)