Commit d2a7ddda9ffb1c8961abff6714b0f1eb925c120f
Committed by
Rusty Russell
1 parent
9499f5e7ed
Exists in
master
and in
39 other branches
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 | } |