GNU Linux-libre 4.19.304-gnu1
[releases.git] / drivers / char / hw_random / virtio-rng.c
1 /*
2  * Randomness driver for virtio
3  *  Copyright (C) 2007, 2008 Rusty Russell IBM Corporation
4  *
5  *  This program is free software; you can redistribute it and/or modify
6  *  it under the terms of the GNU General Public License as published by
7  *  the Free Software Foundation; either version 2 of the License, or
8  *  (at your option) any later version.
9  *
10  *  This program is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  *  GNU General Public License for more details.
14  *
15  *  You should have received a copy of the GNU General Public License
16  *  along with this program; if not, write to the Free Software
17  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
18  */
19
20 #include <asm/barrier.h>
21 #include <linux/err.h>
22 #include <linux/hw_random.h>
23 #include <linux/scatterlist.h>
24 #include <linux/spinlock.h>
25 #include <linux/virtio.h>
26 #include <linux/virtio_rng.h>
27 #include <linux/module.h>
28
29 static DEFINE_IDA(rng_index_ida);
30
31 struct virtrng_info {
32         struct hwrng hwrng;
33         struct virtqueue *vq;
34         char name[25];
35         int index;
36         bool hwrng_register_done;
37         bool hwrng_removed;
38         /* data transfer */
39         struct completion have_data;
40         unsigned int data_avail;
41         unsigned int data_idx;
42         /* minimal size returned by rng_buffer_size() */
43 #if SMP_CACHE_BYTES < 32
44         u8 data[32];
45 #else
46         u8 data[SMP_CACHE_BYTES];
47 #endif
48 };
49
50 static void random_recv_done(struct virtqueue *vq)
51 {
52         struct virtrng_info *vi = vq->vdev->priv;
53         unsigned int len;
54
55         /* We can get spurious callbacks, e.g. shared IRQs + virtio_pci. */
56         if (!virtqueue_get_buf(vi->vq, &len))
57                 return;
58
59         smp_store_release(&vi->data_avail, len);
60         complete(&vi->have_data);
61 }
62
63 static void request_entropy(struct virtrng_info *vi)
64 {
65         struct scatterlist sg;
66
67         reinit_completion(&vi->have_data);
68         vi->data_idx = 0;
69
70         sg_init_one(&sg, vi->data, sizeof(vi->data));
71
72         /* There should always be room for one buffer. */
73         virtqueue_add_inbuf(vi->vq, &sg, 1, vi->data, GFP_KERNEL);
74
75         virtqueue_kick(vi->vq);
76 }
77
78 static unsigned int copy_data(struct virtrng_info *vi, void *buf,
79                               unsigned int size)
80 {
81         size = min_t(unsigned int, size, vi->data_avail);
82         memcpy(buf, vi->data + vi->data_idx, size);
83         vi->data_idx += size;
84         vi->data_avail -= size;
85         if (vi->data_avail == 0)
86                 request_entropy(vi);
87         return size;
88 }
89
90 static int virtio_read(struct hwrng *rng, void *buf, size_t size, bool wait)
91 {
92         int ret;
93         struct virtrng_info *vi = (struct virtrng_info *)rng->priv;
94         unsigned int chunk;
95         size_t read;
96
97         if (vi->hwrng_removed)
98                 return -ENODEV;
99
100         read = 0;
101
102         /* copy available data */
103         if (smp_load_acquire(&vi->data_avail)) {
104                 chunk = copy_data(vi, buf, size);
105                 size -= chunk;
106                 read += chunk;
107         }
108
109         if (!wait)
110                 return read;
111
112         /* We have already copied available entropy,
113          * so either size is 0 or data_avail is 0
114          */
115         while (size != 0) {
116                 /* data_avail is 0 but a request is pending */
117                 ret = wait_for_completion_killable(&vi->have_data);
118                 if (ret < 0)
119                         return ret;
120                 /* if vi->data_avail is 0, we have been interrupted
121                  * by a cleanup, but buffer stays in the queue
122                  */
123                 if (vi->data_avail == 0)
124                         return read;
125
126                 chunk = copy_data(vi, buf + read, size);
127                 size -= chunk;
128                 read += chunk;
129         }
130
131         return read;
132 }
133
134 static void virtio_cleanup(struct hwrng *rng)
135 {
136         struct virtrng_info *vi = (struct virtrng_info *)rng->priv;
137
138         complete(&vi->have_data);
139 }
140
141 static int probe_common(struct virtio_device *vdev)
142 {
143         int err, index;
144         struct virtrng_info *vi = NULL;
145
146         vi = kzalloc(sizeof(struct virtrng_info), GFP_KERNEL);
147         if (!vi)
148                 return -ENOMEM;
149
150         vi->index = index = ida_simple_get(&rng_index_ida, 0, 0, GFP_KERNEL);
151         if (index < 0) {
152                 err = index;
153                 goto err_ida;
154         }
155         sprintf(vi->name, "virtio_rng.%d", index);
156         init_completion(&vi->have_data);
157
158         vi->hwrng = (struct hwrng) {
159                 .read = virtio_read,
160                 .cleanup = virtio_cleanup,
161                 .priv = (unsigned long)vi,
162                 .name = vi->name,
163                 .quality = 1000,
164         };
165         vdev->priv = vi;
166
167         /* We expect a single virtqueue. */
168         vi->vq = virtio_find_single_vq(vdev, random_recv_done, "input");
169         if (IS_ERR(vi->vq)) {
170                 err = PTR_ERR(vi->vq);
171                 goto err_find;
172         }
173
174         /* we always have a pending entropy request */
175         request_entropy(vi);
176
177         return 0;
178
179 err_find:
180         ida_simple_remove(&rng_index_ida, index);
181 err_ida:
182         kfree(vi);
183         return err;
184 }
185
186 static void remove_common(struct virtio_device *vdev)
187 {
188         struct virtrng_info *vi = vdev->priv;
189
190         vi->hwrng_removed = true;
191         vi->data_avail = 0;
192         vi->data_idx = 0;
193         complete(&vi->have_data);
194         vdev->config->reset(vdev);
195         if (vi->hwrng_register_done)
196                 hwrng_unregister(&vi->hwrng);
197         vdev->config->del_vqs(vdev);
198         ida_simple_remove(&rng_index_ida, vi->index);
199         kfree(vi);
200 }
201
202 static int virtrng_probe(struct virtio_device *vdev)
203 {
204         return probe_common(vdev);
205 }
206
207 static void virtrng_remove(struct virtio_device *vdev)
208 {
209         remove_common(vdev);
210 }
211
212 static void virtrng_scan(struct virtio_device *vdev)
213 {
214         struct virtrng_info *vi = vdev->priv;
215         int err;
216
217         err = hwrng_register(&vi->hwrng);
218         if (!err)
219                 vi->hwrng_register_done = true;
220 }
221
222 #ifdef CONFIG_PM_SLEEP
223 static int virtrng_freeze(struct virtio_device *vdev)
224 {
225         remove_common(vdev);
226         return 0;
227 }
228
229 static int virtrng_restore(struct virtio_device *vdev)
230 {
231         int err;
232
233         err = probe_common(vdev);
234         if (!err) {
235                 struct virtrng_info *vi = vdev->priv;
236
237                 /*
238                  * Set hwrng_removed to ensure that virtio_read()
239                  * does not block waiting for data before the
240                  * registration is complete.
241                  */
242                 vi->hwrng_removed = true;
243                 err = hwrng_register(&vi->hwrng);
244                 if (!err) {
245                         vi->hwrng_register_done = true;
246                         vi->hwrng_removed = false;
247                 }
248         }
249
250         return err;
251 }
252 #endif
253
254 static struct virtio_device_id id_table[] = {
255         { VIRTIO_ID_RNG, VIRTIO_DEV_ANY_ID },
256         { 0 },
257 };
258
259 static struct virtio_driver virtio_rng_driver = {
260         .driver.name =  KBUILD_MODNAME,
261         .driver.owner = THIS_MODULE,
262         .id_table =     id_table,
263         .probe =        virtrng_probe,
264         .remove =       virtrng_remove,
265         .scan =         virtrng_scan,
266 #ifdef CONFIG_PM_SLEEP
267         .freeze =       virtrng_freeze,
268         .restore =      virtrng_restore,
269 #endif
270 };
271
272 module_virtio_driver(virtio_rng_driver);
273 MODULE_DEVICE_TABLE(virtio, id_table);
274 MODULE_DESCRIPTION("Virtio random number driver");
275 MODULE_LICENSE("GPL");