diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/block/virtio_blk.c | 6 | ||||
-rw-r--r-- | drivers/char/hw_random/virtio-rng.c | 6 | ||||
-rw-r--r-- | drivers/char/virtio_console.c | 26 | ||||
-rw-r--r-- | drivers/lguest/lguest_device.c | 36 | ||||
-rw-r--r-- | drivers/net/virtio_net.c | 45 | ||||
-rw-r--r-- | drivers/s390/kvm/kvm_virtio.c | 36 | ||||
-rw-r--r-- | drivers/virtio/virtio_balloon.c | 27 | ||||
-rw-r--r-- | drivers/virtio/virtio_pci.c | 37 |
8 files changed, 144 insertions, 75 deletions
diff --git a/drivers/block/virtio_blk.c b/drivers/block/virtio_blk.c index db55a50d9f6a..07d8e595e51f 100644 --- a/drivers/block/virtio_blk.c +++ b/drivers/block/virtio_blk.c | |||
@@ -288,7 +288,7 @@ static int virtblk_probe(struct virtio_device *vdev) | |||
288 | sg_init_table(vblk->sg, vblk->sg_elems); | 288 | sg_init_table(vblk->sg, vblk->sg_elems); |
289 | 289 | ||
290 | /* We expect one virtqueue, for output. */ | 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 | if (IS_ERR(vblk->vq)) { | 292 | if (IS_ERR(vblk->vq)) { |
293 | err = PTR_ERR(vblk->vq); | 293 | err = PTR_ERR(vblk->vq); |
294 | goto out_free_vblk; | 294 | goto out_free_vblk; |
@@ -388,7 +388,7 @@ out_put_disk: | |||
388 | out_mempool: | 388 | out_mempool: |
389 | mempool_destroy(vblk->pool); | 389 | mempool_destroy(vblk->pool); |
390 | out_free_vq: | 390 | out_free_vq: |
391 | vdev->config->del_vq(vblk->vq); | 391 | vdev->config->del_vqs(vdev); |
392 | out_free_vblk: | 392 | out_free_vblk: |
393 | kfree(vblk); | 393 | kfree(vblk); |
394 | out: | 394 | out: |
@@ -409,7 +409,7 @@ static void virtblk_remove(struct virtio_device *vdev) | |||
409 | blk_cleanup_queue(vblk->disk->queue); | 409 | blk_cleanup_queue(vblk->disk->queue); |
410 | put_disk(vblk->disk); | 410 | put_disk(vblk->disk); |
411 | mempool_destroy(vblk->pool); | 411 | mempool_destroy(vblk->pool); |
412 | vdev->config->del_vq(vblk->vq); | 412 | vdev->config->del_vqs(vdev); |
413 | kfree(vblk); | 413 | kfree(vblk); |
414 | } | 414 | } |
415 | 415 | ||
diff --git a/drivers/char/hw_random/virtio-rng.c b/drivers/char/hw_random/virtio-rng.c index 2aeafcea95fe..f2041fede822 100644 --- a/drivers/char/hw_random/virtio-rng.c +++ b/drivers/char/hw_random/virtio-rng.c | |||
@@ -94,13 +94,13 @@ static int virtrng_probe(struct virtio_device *vdev) | |||
94 | int err; | 94 | int err; |
95 | 95 | ||
96 | /* We expect a single virtqueue. */ | 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 | if (IS_ERR(vq)) | 98 | if (IS_ERR(vq)) |
99 | return PTR_ERR(vq); | 99 | return PTR_ERR(vq); |
100 | 100 | ||
101 | err = hwrng_register(&virtio_hwrng); | 101 | err = hwrng_register(&virtio_hwrng); |
102 | if (err) { | 102 | if (err) { |
103 | vdev->config->del_vq(vq); | 103 | vdev->config->del_vqs(vdev); |
104 | return err; | 104 | return err; |
105 | } | 105 | } |
106 | 106 | ||
@@ -112,7 +112,7 @@ static void virtrng_remove(struct virtio_device *vdev) | |||
112 | { | 112 | { |
113 | vdev->config->reset(vdev); | 113 | vdev->config->reset(vdev); |
114 | hwrng_unregister(&virtio_hwrng); | 114 | hwrng_unregister(&virtio_hwrng); |
115 | vdev->config->del_vq(vq); | 115 | vdev->config->del_vqs(vdev); |
116 | } | 116 | } |
117 | 117 | ||
118 | static struct virtio_device_id id_table[] = { | 118 | static struct virtio_device_id id_table[] = { |
diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c index 58684e4a0814..c74dacfa6795 100644 --- a/drivers/char/virtio_console.c +++ b/drivers/char/virtio_console.c | |||
@@ -188,6 +188,9 @@ static void hvc_handle_input(struct virtqueue *vq) | |||
188 | * Finally we put our input buffer in the input queue, ready to receive. */ | 188 | * Finally we put our input buffer in the input queue, ready to receive. */ |
189 | static int __devinit virtcons_probe(struct virtio_device *dev) | 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 | int err; | 194 | int err; |
192 | 195 | ||
193 | vdev = dev; | 196 | vdev = dev; |
@@ -199,20 +202,15 @@ static int __devinit virtcons_probe(struct virtio_device *dev) | |||
199 | goto fail; | 202 | goto fail; |
200 | } | 203 | } |
201 | 204 | ||
202 | /* Find the input queue. */ | 205 | /* Find the queues. */ |
203 | /* FIXME: This is why we want to wean off hvc: we do nothing | 206 | /* FIXME: This is why we want to wean off hvc: we do nothing |
204 | * when input comes in. */ | 207 | * when input comes in. */ |
205 | in_vq = vdev->config->find_vq(vdev, 0, hvc_handle_input, "input"); | 208 | err = vdev->config->find_vqs(vdev, 2, vqs, callbacks, names); |
206 | if (IS_ERR(in_vq)) { | 209 | if (err) |
207 | err = PTR_ERR(in_vq); | ||
208 | goto free; | 210 | goto free; |
209 | } | ||
210 | 211 | ||
211 | out_vq = vdev->config->find_vq(vdev, 1, NULL, "output"); | 212 | in_vq = vqs[0]; |
212 | if (IS_ERR(out_vq)) { | 213 | out_vq = vqs[1]; |
213 | err = PTR_ERR(out_vq); | ||
214 | goto free_in_vq; | ||
215 | } | ||
216 | 214 | ||
217 | /* Start using the new console output. */ | 215 | /* Start using the new console output. */ |
218 | virtio_cons.get_chars = get_chars; | 216 | virtio_cons.get_chars = get_chars; |
@@ -233,17 +231,15 @@ static int __devinit virtcons_probe(struct virtio_device *dev) | |||
233 | hvc = hvc_alloc(0, 0, &virtio_cons, PAGE_SIZE); | 231 | hvc = hvc_alloc(0, 0, &virtio_cons, PAGE_SIZE); |
234 | if (IS_ERR(hvc)) { | 232 | if (IS_ERR(hvc)) { |
235 | err = PTR_ERR(hvc); | 233 | err = PTR_ERR(hvc); |
236 | goto free_out_vq; | 234 | goto free_vqs; |
237 | } | 235 | } |
238 | 236 | ||
239 | /* Register the input buffer the first time. */ | 237 | /* Register the input buffer the first time. */ |
240 | add_inbuf(); | 238 | add_inbuf(); |
241 | return 0; | 239 | return 0; |
242 | 240 | ||
243 | free_out_vq: | 241 | free_vqs: |
244 | vdev->config->del_vq(out_vq); | 242 | vdev->config->del_vqs(vdev); |
245 | free_in_vq: | ||
246 | vdev->config->del_vq(in_vq); | ||
247 | free: | 243 | free: |
248 | kfree(inbuf); | 244 | kfree(inbuf); |
249 | fail: | 245 | fail: |
diff --git a/drivers/lguest/lguest_device.c b/drivers/lguest/lguest_device.c index 4babed899d59..e082cdac88b4 100644 --- a/drivers/lguest/lguest_device.c +++ b/drivers/lguest/lguest_device.c | |||
@@ -313,6 +313,38 @@ static void lg_del_vq(struct virtqueue *vq) | |||
313 | kfree(lvq); | 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 | /* The ops structure which hooks everything together. */ | 348 | /* The ops structure which hooks everything together. */ |
317 | static struct virtio_config_ops lguest_config_ops = { | 349 | static struct virtio_config_ops lguest_config_ops = { |
318 | .get_features = lg_get_features, | 350 | .get_features = lg_get_features, |
@@ -322,8 +354,8 @@ static struct virtio_config_ops lguest_config_ops = { | |||
322 | .get_status = lg_get_status, | 354 | .get_status = lg_get_status, |
323 | .set_status = lg_set_status, | 355 | .set_status = lg_set_status, |
324 | .reset = lg_reset, | 356 | .reset = lg_reset, |
325 | .find_vq = lg_find_vq, | 357 | .find_vqs = lg_find_vqs, |
326 | .del_vq = lg_del_vq, | 358 | .del_vqs = lg_del_vqs, |
327 | }; | 359 | }; |
328 | 360 | ||
329 | /* The root device for the lguest virtio devices. This makes them appear as | 361 | /* The root device for the lguest virtio devices. This makes them appear as |
diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index be3b734ff5a1..7fa620ddeb21 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c | |||
@@ -845,6 +845,10 @@ static int virtnet_probe(struct virtio_device *vdev) | |||
845 | int err; | 845 | int err; |
846 | struct net_device *dev; | 846 | struct net_device *dev; |
847 | struct virtnet_info *vi; | 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 | /* Allocate ourselves a network device with room for our info */ | 853 | /* Allocate ourselves a network device with room for our info */ |
850 | dev = alloc_etherdev(sizeof(struct virtnet_info)); | 854 | dev = alloc_etherdev(sizeof(struct virtnet_info)); |
@@ -905,25 +909,19 @@ static int virtnet_probe(struct virtio_device *vdev) | |||
905 | if (virtio_has_feature(vdev, VIRTIO_NET_F_MRG_RXBUF)) | 909 | if (virtio_has_feature(vdev, VIRTIO_NET_F_MRG_RXBUF)) |
906 | vi->mergeable_rx_bufs = true; | 910 | vi->mergeable_rx_bufs = true; |
907 | 911 | ||
908 | /* We expect two virtqueues, receive then send. */ | 912 | /* We expect two virtqueues, receive then send, |
909 | vi->rvq = vdev->config->find_vq(vdev, 0, skb_recv_done, "input"); | 913 | * and optionally control. */ |
910 | if (IS_ERR(vi->rvq)) { | 914 | nvqs = virtio_has_feature(vi->vdev, VIRTIO_NET_F_CTRL_VQ) ? 3 : 2; |
911 | err = PTR_ERR(vi->rvq); | 915 | |
916 | err = vdev->config->find_vqs(vdev, nvqs, vqs, callbacks, names); | ||
917 | if (err) | ||
912 | goto free; | 918 | goto free; |
913 | } | ||
914 | 919 | ||
915 | vi->svq = vdev->config->find_vq(vdev, 1, skb_xmit_done, "output"); | 920 | vi->rvq = vqs[0]; |
916 | if (IS_ERR(vi->svq)) { | 921 | vi->svq = vqs[1]; |
917 | err = PTR_ERR(vi->svq); | ||
918 | goto free_recv; | ||
919 | } | ||
920 | 922 | ||
921 | if (virtio_has_feature(vi->vdev, VIRTIO_NET_F_CTRL_VQ)) { | 923 | if (virtio_has_feature(vi->vdev, VIRTIO_NET_F_CTRL_VQ)) { |
922 | vi->cvq = vdev->config->find_vq(vdev, 2, NULL, "control"); | 924 | vi->cvq = vqs[2]; |
923 | if (IS_ERR(vi->cvq)) { | ||
924 | err = PTR_ERR(vi->svq); | ||
925 | goto free_send; | ||
926 | } | ||
927 | 925 | ||
928 | if (virtio_has_feature(vi->vdev, VIRTIO_NET_F_CTRL_VLAN)) | 926 | if (virtio_has_feature(vi->vdev, VIRTIO_NET_F_CTRL_VLAN)) |
929 | dev->features |= NETIF_F_HW_VLAN_FILTER; | 927 | dev->features |= NETIF_F_HW_VLAN_FILTER; |
@@ -941,7 +939,7 @@ static int virtnet_probe(struct virtio_device *vdev) | |||
941 | err = register_netdev(dev); | 939 | err = register_netdev(dev); |
942 | if (err) { | 940 | if (err) { |
943 | pr_debug("virtio_net: registering device failed\n"); | 941 | pr_debug("virtio_net: registering device failed\n"); |
944 | goto free_ctrl; | 942 | goto free_vqs; |
945 | } | 943 | } |
946 | 944 | ||
947 | /* Last of all, set up some receive buffers. */ | 945 | /* Last of all, set up some receive buffers. */ |
@@ -962,13 +960,8 @@ static int virtnet_probe(struct virtio_device *vdev) | |||
962 | 960 | ||
963 | unregister: | 961 | unregister: |
964 | unregister_netdev(dev); | 962 | unregister_netdev(dev); |
965 | free_ctrl: | 963 | free_vqs: |
966 | if (virtio_has_feature(vi->vdev, VIRTIO_NET_F_CTRL_VQ)) | 964 | vdev->config->del_vqs(vdev); |
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); | ||
972 | free: | 965 | free: |
973 | free_netdev(dev); | 966 | free_netdev(dev); |
974 | return err; | 967 | return err; |
@@ -994,12 +987,10 @@ static void virtnet_remove(struct virtio_device *vdev) | |||
994 | 987 | ||
995 | BUG_ON(vi->num != 0); | 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 | unregister_netdev(vi->dev); | 990 | unregister_netdev(vi->dev); |
1002 | 991 | ||
992 | vdev->config->del_vqs(vi->vdev); | ||
993 | |||
1003 | while (vi->pages) | 994 | while (vi->pages) |
1004 | __free_pages(get_a_page(vi, GFP_KERNEL), 0); | 995 | __free_pages(get_a_page(vi, GFP_KERNEL), 0); |
1005 | 996 | ||
diff --git a/drivers/s390/kvm/kvm_virtio.c b/drivers/s390/kvm/kvm_virtio.c index ba8995fbf041..e38e5d306faf 100644 --- a/drivers/s390/kvm/kvm_virtio.c +++ b/drivers/s390/kvm/kvm_virtio.c | |||
@@ -227,6 +227,38 @@ static void kvm_del_vq(struct virtqueue *vq) | |||
227 | KVM_S390_VIRTIO_RING_ALIGN)); | 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 | * The config ops structure as defined by virtio config | 263 | * The config ops structure as defined by virtio config |
232 | */ | 264 | */ |
@@ -238,8 +270,8 @@ static struct virtio_config_ops kvm_vq_configspace_ops = { | |||
238 | .get_status = kvm_get_status, | 270 | .get_status = kvm_get_status, |
239 | .set_status = kvm_set_status, | 271 | .set_status = kvm_set_status, |
240 | .reset = kvm_reset, | 272 | .reset = kvm_reset, |
241 | .find_vq = kvm_find_vq, | 273 | .find_vqs = kvm_find_vqs, |
242 | .del_vq = kvm_del_vq, | 274 | .del_vqs = kvm_del_vqs, |
243 | }; | 275 | }; |
244 | 276 | ||
245 | /* | 277 | /* |
diff --git a/drivers/virtio/virtio_balloon.c b/drivers/virtio/virtio_balloon.c index 0fa73b4d18b0..26b278264796 100644 --- a/drivers/virtio/virtio_balloon.c +++ b/drivers/virtio/virtio_balloon.c | |||
@@ -204,6 +204,9 @@ static int balloon(void *_vballoon) | |||
204 | static int virtballoon_probe(struct virtio_device *vdev) | 204 | static int virtballoon_probe(struct virtio_device *vdev) |
205 | { | 205 | { |
206 | struct virtio_balloon *vb; | 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 | int err; | 210 | int err; |
208 | 211 | ||
209 | vdev->priv = vb = kmalloc(sizeof(*vb), GFP_KERNEL); | 212 | vdev->priv = vb = kmalloc(sizeof(*vb), GFP_KERNEL); |
@@ -218,22 +221,17 @@ static int virtballoon_probe(struct virtio_device *vdev) | |||
218 | vb->vdev = vdev; | 221 | vb->vdev = vdev; |
219 | 222 | ||
220 | /* We expect two virtqueues. */ | 223 | /* We expect two virtqueues. */ |
221 | vb->inflate_vq = vdev->config->find_vq(vdev, 0, balloon_ack, "inflate"); | 224 | err = vdev->config->find_vqs(vdev, 2, vqs, callbacks, names); |
222 | if (IS_ERR(vb->inflate_vq)) { | 225 | if (err) |
223 | err = PTR_ERR(vb->inflate_vq); | ||
224 | goto out_free_vb; | 226 | goto out_free_vb; |
225 | } | ||
226 | 227 | ||
227 | vb->deflate_vq = vdev->config->find_vq(vdev, 1, balloon_ack, "deflate"); | 228 | vb->inflate_vq = vqs[0]; |
228 | if (IS_ERR(vb->deflate_vq)) { | 229 | vb->deflate_vq = vqs[1]; |
229 | err = PTR_ERR(vb->deflate_vq); | ||
230 | goto out_del_inflate_vq; | ||
231 | } | ||
232 | 230 | ||
233 | vb->thread = kthread_run(balloon, vb, "vballoon"); | 231 | vb->thread = kthread_run(balloon, vb, "vballoon"); |
234 | if (IS_ERR(vb->thread)) { | 232 | if (IS_ERR(vb->thread)) { |
235 | err = PTR_ERR(vb->thread); | 233 | err = PTR_ERR(vb->thread); |
236 | goto out_del_deflate_vq; | 234 | goto out_del_vqs; |
237 | } | 235 | } |
238 | 236 | ||
239 | vb->tell_host_first | 237 | vb->tell_host_first |
@@ -241,10 +239,8 @@ static int virtballoon_probe(struct virtio_device *vdev) | |||
241 | 239 | ||
242 | return 0; | 240 | return 0; |
243 | 241 | ||
244 | out_del_deflate_vq: | 242 | out_del_vqs: |
245 | vdev->config->del_vq(vb->deflate_vq); | 243 | vdev->config->del_vqs(vdev); |
246 | out_del_inflate_vq: | ||
247 | vdev->config->del_vq(vb->inflate_vq); | ||
248 | out_free_vb: | 244 | out_free_vb: |
249 | kfree(vb); | 245 | kfree(vb); |
250 | out: | 246 | out: |
@@ -264,8 +260,7 @@ static void virtballoon_remove(struct virtio_device *vdev) | |||
264 | /* Now we reset the device so we can clean up the queues. */ | 260 | /* Now we reset the device so we can clean up the queues. */ |
265 | vdev->config->reset(vdev); | 261 | vdev->config->reset(vdev); |
266 | 262 | ||
267 | vdev->config->del_vq(vb->deflate_vq); | 263 | vdev->config->del_vqs(vdev); |
268 | vdev->config->del_vq(vb->inflate_vq); | ||
269 | kfree(vb); | 264 | kfree(vb); |
270 | } | 265 | } |
271 | 266 | ||
diff --git a/drivers/virtio/virtio_pci.c b/drivers/virtio/virtio_pci.c index be4047abd5ba..027f13fbe493 100644 --- a/drivers/virtio/virtio_pci.c +++ b/drivers/virtio/virtio_pci.c | |||
@@ -276,11 +276,7 @@ static void vp_del_vq(struct virtqueue *vq) | |||
276 | { | 276 | { |
277 | struct virtio_pci_device *vp_dev = to_vp_device(vq->vdev); | 277 | struct virtio_pci_device *vp_dev = to_vp_device(vq->vdev); |
278 | struct virtio_pci_vq_info *info = vq->priv; | 278 | struct virtio_pci_vq_info *info = vq->priv; |
279 | unsigned long flags, size; | 279 | unsigned long size; |
280 | |||
281 | spin_lock_irqsave(&vp_dev->lock, flags); | ||
282 | list_del(&info->node); | ||
283 | spin_unlock_irqrestore(&vp_dev->lock, flags); | ||
284 | 280 | ||
285 | vring_del_virtqueue(vq); | 281 | vring_del_virtqueue(vq); |
286 | 282 | ||
@@ -293,14 +289,41 @@ static void vp_del_vq(struct virtqueue *vq) | |||
293 | kfree(info); | 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 | static struct virtio_config_ops virtio_pci_config_ops = { | 319 | static struct virtio_config_ops virtio_pci_config_ops = { |
297 | .get = vp_get, | 320 | .get = vp_get, |
298 | .set = vp_set, | 321 | .set = vp_set, |
299 | .get_status = vp_get_status, | 322 | .get_status = vp_get_status, |
300 | .set_status = vp_set_status, | 323 | .set_status = vp_set_status, |
301 | .reset = vp_reset, | 324 | .reset = vp_reset, |
302 | .find_vq = vp_find_vq, | 325 | .find_vqs = vp_find_vqs, |
303 | .del_vq = vp_del_vq, | 326 | .del_vqs = vp_del_vqs, |
304 | .get_features = vp_get_features, | 327 | .get_features = vp_get_features, |
305 | .finalize_features = vp_finalize_features, | 328 | .finalize_features = vp_finalize_features, |
306 | }; | 329 | }; |