Commit d2a7ddda9ffb1c8961abff6714b0f1eb925c120f

Authored by Michael S. Tsirkin
Committed by Rusty Russell
1 parent 9499f5e7ed

virtio: find_vqs/del_vqs virtio operations

This replaces find_vq/del_vq with find_vqs/del_vqs virtio operations,
and updates all drivers. This is needed for MSI support, because MSI
needs to know the total number of vectors upfront.

Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au> (+ lguest/9p compile fixes)

Showing 10 changed files with 183 additions and 89 deletions Side-by-side Diff

drivers/block/virtio_blk.c
... ... @@ -288,7 +288,7 @@
288 288 sg_init_table(vblk->sg, vblk->sg_elems);
289 289  
290 290 /* We expect one virtqueue, for output. */
291   - vblk->vq = vdev->config->find_vq(vdev, 0, blk_done, "requests");
  291 + vblk->vq = virtio_find_single_vq(vdev, blk_done, "requests");
292 292 if (IS_ERR(vblk->vq)) {
293 293 err = PTR_ERR(vblk->vq);
294 294 goto out_free_vblk;
... ... @@ -388,7 +388,7 @@
388 388 out_mempool:
389 389 mempool_destroy(vblk->pool);
390 390 out_free_vq:
391   - vdev->config->del_vq(vblk->vq);
  391 + vdev->config->del_vqs(vdev);
392 392 out_free_vblk:
393 393 kfree(vblk);
394 394 out:
... ... @@ -409,7 +409,7 @@
409 409 blk_cleanup_queue(vblk->disk->queue);
410 410 put_disk(vblk->disk);
411 411 mempool_destroy(vblk->pool);
412   - vdev->config->del_vq(vblk->vq);
  412 + vdev->config->del_vqs(vdev);
413 413 kfree(vblk);
414 414 }
415 415  
drivers/char/hw_random/virtio-rng.c
... ... @@ -94,13 +94,13 @@
94 94 int err;
95 95  
96 96 /* We expect a single virtqueue. */
97   - vq = vdev->config->find_vq(vdev, 0, random_recv_done, "input");
  97 + vq = virtio_find_single_vq(vdev, random_recv_done, "input");
98 98 if (IS_ERR(vq))
99 99 return PTR_ERR(vq);
100 100  
101 101 err = hwrng_register(&virtio_hwrng);
102 102 if (err) {
103   - vdev->config->del_vq(vq);
  103 + vdev->config->del_vqs(vdev);
104 104 return err;
105 105 }
106 106  
... ... @@ -112,7 +112,7 @@
112 112 {
113 113 vdev->config->reset(vdev);
114 114 hwrng_unregister(&virtio_hwrng);
115   - vdev->config->del_vq(vq);
  115 + vdev->config->del_vqs(vdev);
116 116 }
117 117  
118 118 static struct virtio_device_id id_table[] = {
drivers/char/virtio_console.c
... ... @@ -188,6 +188,9 @@
188 188 * Finally we put our input buffer in the input queue, ready to receive. */
189 189 static int __devinit virtcons_probe(struct virtio_device *dev)
190 190 {
  191 + vq_callback_t *callbacks[] = { hvc_handle_input, NULL};
  192 + const char *names[] = { "input", "output" };
  193 + struct virtqueue *vqs[2];
191 194 int err;
192 195  
193 196 vdev = dev;
194 197  
195 198  
196 199  
... ... @@ -199,20 +202,15 @@
199 202 goto fail;
200 203 }
201 204  
202   - /* Find the input queue. */
  205 + /* Find the queues. */
203 206 /* FIXME: This is why we want to wean off hvc: we do nothing
204 207 * when input comes in. */
205   - in_vq = vdev->config->find_vq(vdev, 0, hvc_handle_input, "input");
206   - if (IS_ERR(in_vq)) {
207   - err = PTR_ERR(in_vq);
  208 + err = vdev->config->find_vqs(vdev, 2, vqs, callbacks, names);
  209 + if (err)
208 210 goto free;
209   - }
210 211  
211   - out_vq = vdev->config->find_vq(vdev, 1, NULL, "output");
212   - if (IS_ERR(out_vq)) {
213   - err = PTR_ERR(out_vq);
214   - goto free_in_vq;
215   - }
  212 + in_vq = vqs[0];
  213 + out_vq = vqs[1];
216 214  
217 215 /* Start using the new console output. */
218 216 virtio_cons.get_chars = get_chars;
219 217  
... ... @@ -233,17 +231,15 @@
233 231 hvc = hvc_alloc(0, 0, &virtio_cons, PAGE_SIZE);
234 232 if (IS_ERR(hvc)) {
235 233 err = PTR_ERR(hvc);
236   - goto free_out_vq;
  234 + goto free_vqs;
237 235 }
238 236  
239 237 /* Register the input buffer the first time. */
240 238 add_inbuf();
241 239 return 0;
242 240  
243   -free_out_vq:
244   - vdev->config->del_vq(out_vq);
245   -free_in_vq:
246   - vdev->config->del_vq(in_vq);
  241 +free_vqs:
  242 + vdev->config->del_vqs(vdev);
247 243 free:
248 244 kfree(inbuf);
249 245 fail:
drivers/lguest/lguest_device.c
... ... @@ -313,6 +313,38 @@
313 313 kfree(lvq);
314 314 }
315 315  
  316 +static void lg_del_vqs(struct virtio_device *vdev)
  317 +{
  318 + struct virtqueue *vq, *n;
  319 +
  320 + list_for_each_entry_safe(vq, n, &vdev->vqs, list)
  321 + lg_del_vq(vq);
  322 +}
  323 +
  324 +static int lg_find_vqs(struct virtio_device *vdev, unsigned nvqs,
  325 + struct virtqueue *vqs[],
  326 + vq_callback_t *callbacks[],
  327 + const char *names[])
  328 +{
  329 + struct lguest_device *ldev = to_lgdev(vdev);
  330 + int i;
  331 +
  332 + /* We must have this many virtqueues. */
  333 + if (nvqs > ldev->desc->num_vq)
  334 + return -ENOENT;
  335 +
  336 + for (i = 0; i < nvqs; ++i) {
  337 + vqs[i] = lg_find_vq(vdev, i, callbacks[i], names[i]);
  338 + if (IS_ERR(vqs[i]))
  339 + goto error;
  340 + }
  341 + return 0;
  342 +
  343 +error:
  344 + lg_del_vqs(vdev);
  345 + return PTR_ERR(vqs[i]);
  346 +}
  347 +
316 348 /* The ops structure which hooks everything together. */
317 349 static struct virtio_config_ops lguest_config_ops = {
318 350 .get_features = lg_get_features,
... ... @@ -322,8 +354,8 @@
322 354 .get_status = lg_get_status,
323 355 .set_status = lg_set_status,
324 356 .reset = lg_reset,
325   - .find_vq = lg_find_vq,
326   - .del_vq = lg_del_vq,
  357 + .find_vqs = lg_find_vqs,
  358 + .del_vqs = lg_del_vqs,
327 359 };
328 360  
329 361 /* The root device for the lguest virtio devices. This makes them appear as
drivers/net/virtio_net.c
... ... @@ -845,6 +845,10 @@
845 845 int err;
846 846 struct net_device *dev;
847 847 struct virtnet_info *vi;
  848 + struct virtqueue *vqs[3];
  849 + vq_callback_t *callbacks[] = { skb_recv_done, skb_xmit_done, NULL};
  850 + const char *names[] = { "input", "output", "control" };
  851 + int nvqs;
848 852  
849 853 /* Allocate ourselves a network device with room for our info */
850 854 dev = alloc_etherdev(sizeof(struct virtnet_info));
851 855  
852 856  
853 857  
... ... @@ -905,25 +909,19 @@
905 909 if (virtio_has_feature(vdev, VIRTIO_NET_F_MRG_RXBUF))
906 910 vi->mergeable_rx_bufs = true;
907 911  
908   - /* We expect two virtqueues, receive then send. */
909   - vi->rvq = vdev->config->find_vq(vdev, 0, skb_recv_done, "input");
910   - if (IS_ERR(vi->rvq)) {
911   - err = PTR_ERR(vi->rvq);
  912 + /* We expect two virtqueues, receive then send,
  913 + * and optionally control. */
  914 + nvqs = virtio_has_feature(vi->vdev, VIRTIO_NET_F_CTRL_VQ) ? 3 : 2;
  915 +
  916 + err = vdev->config->find_vqs(vdev, nvqs, vqs, callbacks, names);
  917 + if (err)
912 918 goto free;
913   - }
914 919  
915   - vi->svq = vdev->config->find_vq(vdev, 1, skb_xmit_done, "output");
916   - if (IS_ERR(vi->svq)) {
917   - err = PTR_ERR(vi->svq);
918   - goto free_recv;
919   - }
  920 + vi->rvq = vqs[0];
  921 + vi->svq = vqs[1];
920 922  
921 923 if (virtio_has_feature(vi->vdev, VIRTIO_NET_F_CTRL_VQ)) {
922   - vi->cvq = vdev->config->find_vq(vdev, 2, NULL, "control");
923   - if (IS_ERR(vi->cvq)) {
924   - err = PTR_ERR(vi->svq);
925   - goto free_send;
926   - }
  924 + vi->cvq = vqs[2];
927 925  
928 926 if (virtio_has_feature(vi->vdev, VIRTIO_NET_F_CTRL_VLAN))
929 927 dev->features |= NETIF_F_HW_VLAN_FILTER;
... ... @@ -941,7 +939,7 @@
941 939 err = register_netdev(dev);
942 940 if (err) {
943 941 pr_debug("virtio_net: registering device failed\n");
944   - goto free_ctrl;
  942 + goto free_vqs;
945 943 }
946 944  
947 945 /* Last of all, set up some receive buffers. */
... ... @@ -962,13 +960,8 @@
962 960  
963 961 unregister:
964 962 unregister_netdev(dev);
965   -free_ctrl:
966   - if (virtio_has_feature(vi->vdev, VIRTIO_NET_F_CTRL_VQ))
967   - vdev->config->del_vq(vi->cvq);
968   -free_send:
969   - vdev->config->del_vq(vi->svq);
970   -free_recv:
971   - vdev->config->del_vq(vi->rvq);
  963 +free_vqs:
  964 + vdev->config->del_vqs(vdev);
972 965 free:
973 966 free_netdev(dev);
974 967 return err;
975 968  
... ... @@ -994,11 +987,9 @@
994 987  
995 988 BUG_ON(vi->num != 0);
996 989  
997   - vdev->config->del_vq(vi->svq);
998   - vdev->config->del_vq(vi->rvq);
999   - if (virtio_has_feature(vi->vdev, VIRTIO_NET_F_CTRL_VQ))
1000   - vdev->config->del_vq(vi->cvq);
1001 990 unregister_netdev(vi->dev);
  991 +
  992 + vdev->config->del_vqs(vi->vdev);
1002 993  
1003 994 while (vi->pages)
1004 995 __free_pages(get_a_page(vi, GFP_KERNEL), 0);
drivers/s390/kvm/kvm_virtio.c
... ... @@ -227,6 +227,38 @@
227 227 KVM_S390_VIRTIO_RING_ALIGN));
228 228 }
229 229  
  230 +static void kvm_del_vqs(struct virtio_device *vdev)
  231 +{
  232 + struct virtqueue *vq, *n;
  233 +
  234 + list_for_each_entry_safe(vq, n, &vdev->vqs, list)
  235 + kvm_del_vq(vq);
  236 +}
  237 +
  238 +static int kvm_find_vqs(struct virtio_device *vdev, unsigned nvqs,
  239 + struct virtqueue *vqs[],
  240 + vq_callback_t *callbacks[],
  241 + const char *names[])
  242 +{
  243 + struct kvm_device *kdev = to_kvmdev(vdev);
  244 + int i;
  245 +
  246 + /* We must have this many virtqueues. */
  247 + if (nvqs > kdev->desc->num_vq)
  248 + return -ENOENT;
  249 +
  250 + for (i = 0; i < nvqs; ++i) {
  251 + vqs[i] = kvm_find_vq(vdev, i, callbacks[i], names[i]);
  252 + if (IS_ERR(vqs[i]))
  253 + goto error;
  254 + }
  255 + return 0;
  256 +
  257 +error:
  258 + kvm_del_vqs(vdev);
  259 + return PTR_ERR(vqs[i]);
  260 +}
  261 +
230 262 /*
231 263 * The config ops structure as defined by virtio config
232 264 */
... ... @@ -238,8 +270,8 @@
238 270 .get_status = kvm_get_status,
239 271 .set_status = kvm_set_status,
240 272 .reset = kvm_reset,
241   - .find_vq = kvm_find_vq,
242   - .del_vq = kvm_del_vq,
  273 + .find_vqs = kvm_find_vqs,
  274 + .del_vqs = kvm_del_vqs,
243 275 };
244 276  
245 277 /*
drivers/virtio/virtio_balloon.c
... ... @@ -204,6 +204,9 @@
204 204 static int virtballoon_probe(struct virtio_device *vdev)
205 205 {
206 206 struct virtio_balloon *vb;
  207 + struct virtqueue *vqs[2];
  208 + vq_callback_t *callbacks[] = { balloon_ack, balloon_ack };
  209 + const char *names[] = { "inflate", "deflate" };
207 210 int err;
208 211  
209 212 vdev->priv = vb = kmalloc(sizeof(*vb), GFP_KERNEL);
210 213  
211 214  
212 215  
... ... @@ -218,22 +221,17 @@
218 221 vb->vdev = vdev;
219 222  
220 223 /* We expect two virtqueues. */
221   - vb->inflate_vq = vdev->config->find_vq(vdev, 0, balloon_ack, "inflate");
222   - if (IS_ERR(vb->inflate_vq)) {
223   - err = PTR_ERR(vb->inflate_vq);
  224 + err = vdev->config->find_vqs(vdev, 2, vqs, callbacks, names);
  225 + if (err)
224 226 goto out_free_vb;
225   - }
226 227  
227   - vb->deflate_vq = vdev->config->find_vq(vdev, 1, balloon_ack, "deflate");
228   - if (IS_ERR(vb->deflate_vq)) {
229   - err = PTR_ERR(vb->deflate_vq);
230   - goto out_del_inflate_vq;
231   - }
  228 + vb->inflate_vq = vqs[0];
  229 + vb->deflate_vq = vqs[1];
232 230  
233 231 vb->thread = kthread_run(balloon, vb, "vballoon");
234 232 if (IS_ERR(vb->thread)) {
235 233 err = PTR_ERR(vb->thread);
236   - goto out_del_deflate_vq;
  234 + goto out_del_vqs;
237 235 }
238 236  
239 237 vb->tell_host_first
... ... @@ -241,10 +239,8 @@
241 239  
242 240 return 0;
243 241  
244   -out_del_deflate_vq:
245   - vdev->config->del_vq(vb->deflate_vq);
246   -out_del_inflate_vq:
247   - vdev->config->del_vq(vb->inflate_vq);
  242 +out_del_vqs:
  243 + vdev->config->del_vqs(vdev);
248 244 out_free_vb:
249 245 kfree(vb);
250 246 out:
... ... @@ -264,8 +260,7 @@
264 260 /* Now we reset the device so we can clean up the queues. */
265 261 vdev->config->reset(vdev);
266 262  
267   - vdev->config->del_vq(vb->deflate_vq);
268   - vdev->config->del_vq(vb->inflate_vq);
  263 + vdev->config->del_vqs(vdev);
269 264 kfree(vb);
270 265 }
271 266  
drivers/virtio/virtio_pci.c
... ... @@ -276,12 +276,8 @@
276 276 {
277 277 struct virtio_pci_device *vp_dev = to_vp_device(vq->vdev);
278 278 struct virtio_pci_vq_info *info = vq->priv;
279   - unsigned long flags, size;
  279 + unsigned long size;
280 280  
281   - spin_lock_irqsave(&vp_dev->lock, flags);
282   - list_del(&info->node);
283   - spin_unlock_irqrestore(&vp_dev->lock, flags);
284   -
285 281 vring_del_virtqueue(vq);
286 282  
287 283 /* Select and deactivate the queue */
288 284  
... ... @@ -293,14 +289,41 @@
293 289 kfree(info);
294 290 }
295 291  
  292 +static void vp_del_vqs(struct virtio_device *vdev)
  293 +{
  294 + struct virtqueue *vq, *n;
  295 +
  296 + list_for_each_entry_safe(vq, n, &vdev->vqs, list)
  297 + vp_del_vq(vq);
  298 +}
  299 +
  300 +static int vp_find_vqs(struct virtio_device *vdev, unsigned nvqs,
  301 + struct virtqueue *vqs[],
  302 + vq_callback_t *callbacks[],
  303 + const char *names[])
  304 +{
  305 + int i;
  306 +
  307 + for (i = 0; i < nvqs; ++i) {
  308 + vqs[i] = vp_find_vq(vdev, i, callbacks[i], names[i]);
  309 + if (IS_ERR(vqs[i]))
  310 + goto error;
  311 + }
  312 + return 0;
  313 +
  314 +error:
  315 + vp_del_vqs(vdev);
  316 + return PTR_ERR(vqs[i]);
  317 +}
  318 +
296 319 static struct virtio_config_ops virtio_pci_config_ops = {
297 320 .get = vp_get,
298 321 .set = vp_set,
299 322 .get_status = vp_get_status,
300 323 .set_status = vp_set_status,
301 324 .reset = vp_reset,
302   - .find_vq = vp_find_vq,
303   - .del_vq = vp_del_vq,
  325 + .find_vqs = vp_find_vqs,
  326 + .del_vqs = vp_del_vqs,
304 327 .get_features = vp_get_features,
305 328 .finalize_features = vp_finalize_features,
306 329 };
include/linux/virtio_config.h
... ... @@ -29,6 +29,7 @@
29 29 #define VIRTIO_F_NOTIFY_ON_EMPTY 24
30 30  
31 31 #ifdef __KERNEL__
  32 +#include <linux/err.h>
32 33 #include <linux/virtio.h>
33 34  
34 35 /**
35 36  
36 37  
... ... @@ -49,16 +50,26 @@
49 50 * @set_status: write the status byte
50 51 * vdev: the virtio_device
51 52 * status: the new status byte
  53 + * @request_vqs: request the specified number of virtqueues
  54 + * vdev: the virtio_device
  55 + * max_vqs: the max number of virtqueues we want
  56 + * If supplied, must call before any virtqueues are instantiated.
  57 + * To modify the max number of virtqueues after request_vqs has been
  58 + * called, call free_vqs and then request_vqs with a new value.
  59 + * @free_vqs: cleanup resources allocated by request_vqs
  60 + * vdev: the virtio_device
  61 + * If supplied, must call after all virtqueues have been deleted.
52 62 * @reset: reset the device
53 63 * vdev: the virtio device
54 64 * After this, status and feature negotiation must be done again
55   - * @find_vq: find a virtqueue and instantiate it.
  65 + * @find_vqs: find virtqueues and instantiate them.
56 66 * vdev: the virtio_device
57   - * index: the 0-based virtqueue number in case there's more than one.
58   - * callback: the virtqueue callback
59   - * name: the virtqueue name (mainly for debugging)
60   - * Returns the new virtqueue or ERR_PTR() (eg. -ENOENT).
61   - * @del_vq: free a virtqueue found by find_vq().
  67 + * nvqs: the number of virtqueues to find
  68 + * vqs: on success, includes new virtqueues
  69 + * callbacks: array of callbacks, for each virtqueue
  70 + * names: array of virtqueue names (mainly for debugging)
  71 + * Returns 0 on success or error status
  72 + * @del_vqs: free virtqueues found by find_vqs().
62 73 * @get_features: get the array of feature bits for this device.
63 74 * vdev: the virtio_device
64 75 * Returns the first 32 feature bits (all we currently need).
... ... @@ -67,6 +78,7 @@
67 78 * This gives the final feature bits for the device: it can change
68 79 * the dev->feature bits if it wants.
69 80 */
  81 +typedef void vq_callback_t(struct virtqueue *);
70 82 struct virtio_config_ops
71 83 {
72 84 void (*get)(struct virtio_device *vdev, unsigned offset,
... ... @@ -76,11 +88,11 @@
76 88 u8 (*get_status)(struct virtio_device *vdev);
77 89 void (*set_status)(struct virtio_device *vdev, u8 status);
78 90 void (*reset)(struct virtio_device *vdev);
79   - struct virtqueue *(*find_vq)(struct virtio_device *vdev,
80   - unsigned index,
81   - void (*callback)(struct virtqueue *),
82   - const char *name);
83   - void (*del_vq)(struct virtqueue *vq);
  91 + int (*find_vqs)(struct virtio_device *, unsigned nvqs,
  92 + struct virtqueue *vqs[],
  93 + vq_callback_t *callbacks[],
  94 + const char *names[]);
  95 + void (*del_vqs)(struct virtio_device *);
84 96 u32 (*get_features)(struct virtio_device *vdev);
85 97 void (*finalize_features)(struct virtio_device *vdev);
86 98 };
... ... @@ -127,6 +139,19 @@
127 139  
128 140 vdev->config->get(vdev, offset, buf, len);
129 141 return 0;
  142 +}
  143 +
  144 +static inline
  145 +struct virtqueue *virtio_find_single_vq(struct virtio_device *vdev,
  146 + vq_callback_t *c, const char *n)
  147 +{
  148 + vq_callback_t *callbacks[] = { c };
  149 + const char *names[] = { n };
  150 + struct virtqueue *vq;
  151 + int err = vdev->config->find_vqs(vdev, 1, &vq, callbacks, names);
  152 + if (err < 0)
  153 + return ERR_PTR(err);
  154 + return vq;
130 155 }
131 156 #endif /* __KERNEL__ */
132 157 #endif /* _LINUX_VIRTIO_CONFIG_H */
net/9p/trans_virtio.c
... ... @@ -246,7 +246,7 @@
246 246 chan->vdev = vdev;
247 247  
248 248 /* We expect one virtqueue, for requests. */
249   - chan->vq = vdev->config->find_vq(vdev, 0, req_done, "requests");
  249 + chan->vq = virtio_find_single_vq(vdev, req_done, "requests");
250 250 if (IS_ERR(chan->vq)) {
251 251 err = PTR_ERR(chan->vq);
252 252 goto out_free_vq;
... ... @@ -261,7 +261,7 @@
261 261 return 0;
262 262  
263 263 out_free_vq:
264   - vdev->config->del_vq(chan->vq);
  264 + vdev->config->del_vqs(vdev);
265 265 fail:
266 266 mutex_lock(&virtio_9p_lock);
267 267 chan_index--;
... ... @@ -332,7 +332,7 @@
332 332 BUG_ON(chan->inuse);
333 333  
334 334 if (chan->initialized) {
335   - vdev->config->del_vq(chan->vq);
  335 + vdev->config->del_vqs(vdev);
336 336 chan->initialized = false;
337 337 }
338 338 }