diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2013-11-14 23:28:47 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-11-14 23:28:47 -0500 |
commit | b746f9c7941f227ad582b4f0bc981f3adcbc46b2 (patch) | |
tree | fe3da3dedfe8d66f90cdcfa3d9ce847fdc411c20 | |
parent | ce6513f758b1852a2f24f76f07d0fae304d24ad3 (diff) | |
parent | 2bf4fd31394a3f875ea093ee8a209f30b378cbf3 (diff) |
Merge tag 'virtio-next-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/rusty/linux
Pull virtio updates from Rusty Russell:
"Nothing really exciting: some groundwork for changing virtio endian,
and some robustness fixes for broken virtio devices, plus minor
tweaks"
* tag 'virtio-next-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/rusty/linux:
virtio_scsi: verify if queue is broken after virtqueue_get_buf()
x86, asmlinkage, lguest: Pass in globals into assembler statement
virtio: mmio: fix signature checking for BE guests
virtio_ring: adapt to notify() returning bool
virtio_net: verify if queue is broken after virtqueue_get_buf()
virtio_console: verify if queue is broken after virtqueue_get_buf()
virtio_blk: verify if queue is broken after virtqueue_get_buf()
virtio_ring: add new function virtqueue_is_broken()
virtio_test: verify if virtqueue_kick() succeeded
virtio_net: verify if virtqueue_kick() succeeded
virtio_ring: let virtqueue_{kick()/notify()} return a bool
virtio_ring: change host notification API
virtio_config: remove virtio_config_val
virtio: use size-based config accessors.
virtio_config: introduce size-based accessors.
virtio_ring: plug kmemleak false positive.
virtio: pm: use CONFIG_PM_SLEEP instead of CONFIG_PM
-rw-r--r-- | drivers/block/virtio_blk.c | 83 | ||||
-rw-r--r-- | drivers/char/hw_random/virtio-rng.c | 4 | ||||
-rw-r--r-- | drivers/char/virtio_console.c | 25 | ||||
-rw-r--r-- | drivers/lguest/lguest_device.c | 3 | ||||
-rw-r--r-- | drivers/lguest/x86/core.c | 6 | ||||
-rw-r--r-- | drivers/net/caif/caif_virtio.c | 23 | ||||
-rw-r--r-- | drivers/net/virtio_net.c | 44 | ||||
-rw-r--r-- | drivers/remoteproc/remoteproc_virtio.c | 3 | ||||
-rw-r--r-- | drivers/s390/kvm/kvm_virtio.c | 8 | ||||
-rw-r--r-- | drivers/s390/kvm/virtio_ccw.c | 5 | ||||
-rw-r--r-- | drivers/scsi/virtio_scsi.c | 19 | ||||
-rw-r--r-- | drivers/virtio/virtio_balloon.c | 14 | ||||
-rw-r--r-- | drivers/virtio/virtio_mmio.c | 5 | ||||
-rw-r--r-- | drivers/virtio/virtio_pci.c | 3 | ||||
-rw-r--r-- | drivers/virtio/virtio_ring.c | 34 | ||||
-rw-r--r-- | include/linux/virtio.h | 6 | ||||
-rw-r--r-- | include/linux/virtio_config.h | 161 | ||||
-rw-r--r-- | include/linux/virtio_ring.h | 2 | ||||
-rw-r--r-- | net/9p/trans_virtio.c | 9 | ||||
-rw-r--r-- | tools/virtio/virtio_test.c | 6 | ||||
-rw-r--r-- | tools/virtio/vringh_test.c | 13 |
21 files changed, 310 insertions, 166 deletions
diff --git a/drivers/block/virtio_blk.c b/drivers/block/virtio_blk.c index 5cdf88b7ad9e..f3be496ac8fa 100644 --- a/drivers/block/virtio_blk.c +++ b/drivers/block/virtio_blk.c | |||
@@ -292,6 +292,8 @@ static void virtblk_done(struct virtqueue *vq) | |||
292 | req_done = true; | 292 | req_done = true; |
293 | } | 293 | } |
294 | } | 294 | } |
295 | if (unlikely(virtqueue_is_broken(vq))) | ||
296 | break; | ||
295 | } while (!virtqueue_enable_cb(vq)); | 297 | } while (!virtqueue_enable_cb(vq)); |
296 | /* In case queue is stopped waiting for more buffers. */ | 298 | /* In case queue is stopped waiting for more buffers. */ |
297 | if (req_done) | 299 | if (req_done) |
@@ -456,18 +458,15 @@ static int virtblk_ioctl(struct block_device *bdev, fmode_t mode, | |||
456 | static int virtblk_getgeo(struct block_device *bd, struct hd_geometry *geo) | 458 | static int virtblk_getgeo(struct block_device *bd, struct hd_geometry *geo) |
457 | { | 459 | { |
458 | struct virtio_blk *vblk = bd->bd_disk->private_data; | 460 | struct virtio_blk *vblk = bd->bd_disk->private_data; |
459 | struct virtio_blk_geometry vgeo; | ||
460 | int err; | ||
461 | 461 | ||
462 | /* see if the host passed in geometry config */ | 462 | /* see if the host passed in geometry config */ |
463 | err = virtio_config_val(vblk->vdev, VIRTIO_BLK_F_GEOMETRY, | 463 | if (virtio_has_feature(vblk->vdev, VIRTIO_BLK_F_GEOMETRY)) { |
464 | offsetof(struct virtio_blk_config, geometry), | 464 | virtio_cread(vblk->vdev, struct virtio_blk_config, |
465 | &vgeo); | 465 | geometry.cylinders, &geo->cylinders); |
466 | 466 | virtio_cread(vblk->vdev, struct virtio_blk_config, | |
467 | if (!err) { | 467 | geometry.heads, &geo->heads); |
468 | geo->heads = vgeo.heads; | 468 | virtio_cread(vblk->vdev, struct virtio_blk_config, |
469 | geo->sectors = vgeo.sectors; | 469 | geometry.sectors, &geo->sectors); |
470 | geo->cylinders = vgeo.cylinders; | ||
471 | } else { | 470 | } else { |
472 | /* some standard values, similar to sd */ | 471 | /* some standard values, similar to sd */ |
473 | geo->heads = 1 << 6; | 472 | geo->heads = 1 << 6; |
@@ -529,8 +528,7 @@ static void virtblk_config_changed_work(struct work_struct *work) | |||
529 | goto done; | 528 | goto done; |
530 | 529 | ||
531 | /* Host must always specify the capacity. */ | 530 | /* Host must always specify the capacity. */ |
532 | vdev->config->get(vdev, offsetof(struct virtio_blk_config, capacity), | 531 | virtio_cread(vdev, struct virtio_blk_config, capacity, &capacity); |
533 | &capacity, sizeof(capacity)); | ||
534 | 532 | ||
535 | /* If capacity is too big, truncate with warning. */ | 533 | /* If capacity is too big, truncate with warning. */ |
536 | if ((sector_t)capacity != capacity) { | 534 | if ((sector_t)capacity != capacity) { |
@@ -608,9 +606,9 @@ static int virtblk_get_cache_mode(struct virtio_device *vdev) | |||
608 | u8 writeback; | 606 | u8 writeback; |
609 | int err; | 607 | int err; |
610 | 608 | ||
611 | err = virtio_config_val(vdev, VIRTIO_BLK_F_CONFIG_WCE, | 609 | err = virtio_cread_feature(vdev, VIRTIO_BLK_F_CONFIG_WCE, |
612 | offsetof(struct virtio_blk_config, wce), | 610 | struct virtio_blk_config, wce, |
613 | &writeback); | 611 | &writeback); |
614 | if (err) | 612 | if (err) |
615 | writeback = virtio_has_feature(vdev, VIRTIO_BLK_F_WCE); | 613 | writeback = virtio_has_feature(vdev, VIRTIO_BLK_F_WCE); |
616 | 614 | ||
@@ -642,7 +640,6 @@ virtblk_cache_type_store(struct device *dev, struct device_attribute *attr, | |||
642 | struct virtio_blk *vblk = disk->private_data; | 640 | struct virtio_blk *vblk = disk->private_data; |
643 | struct virtio_device *vdev = vblk->vdev; | 641 | struct virtio_device *vdev = vblk->vdev; |
644 | int i; | 642 | int i; |
645 | u8 writeback; | ||
646 | 643 | ||
647 | BUG_ON(!virtio_has_feature(vblk->vdev, VIRTIO_BLK_F_CONFIG_WCE)); | 644 | BUG_ON(!virtio_has_feature(vblk->vdev, VIRTIO_BLK_F_CONFIG_WCE)); |
648 | for (i = ARRAY_SIZE(virtblk_cache_types); --i >= 0; ) | 645 | for (i = ARRAY_SIZE(virtblk_cache_types); --i >= 0; ) |
@@ -652,11 +649,7 @@ virtblk_cache_type_store(struct device *dev, struct device_attribute *attr, | |||
652 | if (i < 0) | 649 | if (i < 0) |
653 | return -EINVAL; | 650 | return -EINVAL; |
654 | 651 | ||
655 | writeback = i; | 652 | virtio_cwrite8(vdev, offsetof(struct virtio_blk_config, wce), i); |
656 | vdev->config->set(vdev, | ||
657 | offsetof(struct virtio_blk_config, wce), | ||
658 | &writeback, sizeof(writeback)); | ||
659 | |||
660 | virtblk_update_cache_mode(vdev); | 653 | virtblk_update_cache_mode(vdev); |
661 | return count; | 654 | return count; |
662 | } | 655 | } |
@@ -699,9 +692,9 @@ static int virtblk_probe(struct virtio_device *vdev) | |||
699 | index = err; | 692 | index = err; |
700 | 693 | ||
701 | /* We need to know how many segments before we allocate. */ | 694 | /* We need to know how many segments before we allocate. */ |
702 | err = virtio_config_val(vdev, VIRTIO_BLK_F_SEG_MAX, | 695 | err = virtio_cread_feature(vdev, VIRTIO_BLK_F_SEG_MAX, |
703 | offsetof(struct virtio_blk_config, seg_max), | 696 | struct virtio_blk_config, seg_max, |
704 | &sg_elems); | 697 | &sg_elems); |
705 | 698 | ||
706 | /* We need at least one SG element, whatever they say. */ | 699 | /* We need at least one SG element, whatever they say. */ |
707 | if (err || !sg_elems) | 700 | if (err || !sg_elems) |
@@ -772,8 +765,7 @@ static int virtblk_probe(struct virtio_device *vdev) | |||
772 | set_disk_ro(vblk->disk, 1); | 765 | set_disk_ro(vblk->disk, 1); |
773 | 766 | ||
774 | /* Host must always specify the capacity. */ | 767 | /* Host must always specify the capacity. */ |
775 | vdev->config->get(vdev, offsetof(struct virtio_blk_config, capacity), | 768 | virtio_cread(vdev, struct virtio_blk_config, capacity, &cap); |
776 | &cap, sizeof(cap)); | ||
777 | 769 | ||
778 | /* If capacity is too big, truncate with warning. */ | 770 | /* If capacity is too big, truncate with warning. */ |
779 | if ((sector_t)cap != cap) { | 771 | if ((sector_t)cap != cap) { |
@@ -794,46 +786,45 @@ static int virtblk_probe(struct virtio_device *vdev) | |||
794 | 786 | ||
795 | /* Host can optionally specify maximum segment size and number of | 787 | /* Host can optionally specify maximum segment size and number of |
796 | * segments. */ | 788 | * segments. */ |
797 | err = virtio_config_val(vdev, VIRTIO_BLK_F_SIZE_MAX, | 789 | err = virtio_cread_feature(vdev, VIRTIO_BLK_F_SIZE_MAX, |
798 | offsetof(struct virtio_blk_config, size_max), | 790 | struct virtio_blk_config, size_max, &v); |
799 | &v); | ||
800 | if (!err) | 791 | if (!err) |
801 | blk_queue_max_segment_size(q, v); | 792 | blk_queue_max_segment_size(q, v); |
802 | else | 793 | else |
803 | blk_queue_max_segment_size(q, -1U); | 794 | blk_queue_max_segment_size(q, -1U); |
804 | 795 | ||
805 | /* Host can optionally specify the block size of the device */ | 796 | /* Host can optionally specify the block size of the device */ |
806 | err = virtio_config_val(vdev, VIRTIO_BLK_F_BLK_SIZE, | 797 | err = virtio_cread_feature(vdev, VIRTIO_BLK_F_BLK_SIZE, |
807 | offsetof(struct virtio_blk_config, blk_size), | 798 | struct virtio_blk_config, blk_size, |
808 | &blk_size); | 799 | &blk_size); |
809 | if (!err) | 800 | if (!err) |
810 | blk_queue_logical_block_size(q, blk_size); | 801 | blk_queue_logical_block_size(q, blk_size); |
811 | else | 802 | else |
812 | blk_size = queue_logical_block_size(q); | 803 | blk_size = queue_logical_block_size(q); |
813 | 804 | ||
814 | /* Use topology information if available */ | 805 | /* Use topology information if available */ |
815 | err = virtio_config_val(vdev, VIRTIO_BLK_F_TOPOLOGY, | 806 | err = virtio_cread_feature(vdev, VIRTIO_BLK_F_TOPOLOGY, |
816 | offsetof(struct virtio_blk_config, physical_block_exp), | 807 | struct virtio_blk_config, physical_block_exp, |
817 | &physical_block_exp); | 808 | &physical_block_exp); |
818 | if (!err && physical_block_exp) | 809 | if (!err && physical_block_exp) |
819 | blk_queue_physical_block_size(q, | 810 | blk_queue_physical_block_size(q, |
820 | blk_size * (1 << physical_block_exp)); | 811 | blk_size * (1 << physical_block_exp)); |
821 | 812 | ||
822 | err = virtio_config_val(vdev, VIRTIO_BLK_F_TOPOLOGY, | 813 | err = virtio_cread_feature(vdev, VIRTIO_BLK_F_TOPOLOGY, |
823 | offsetof(struct virtio_blk_config, alignment_offset), | 814 | struct virtio_blk_config, alignment_offset, |
824 | &alignment_offset); | 815 | &alignment_offset); |
825 | if (!err && alignment_offset) | 816 | if (!err && alignment_offset) |
826 | blk_queue_alignment_offset(q, blk_size * alignment_offset); | 817 | blk_queue_alignment_offset(q, blk_size * alignment_offset); |
827 | 818 | ||
828 | err = virtio_config_val(vdev, VIRTIO_BLK_F_TOPOLOGY, | 819 | err = virtio_cread_feature(vdev, VIRTIO_BLK_F_TOPOLOGY, |
829 | offsetof(struct virtio_blk_config, min_io_size), | 820 | struct virtio_blk_config, min_io_size, |
830 | &min_io_size); | 821 | &min_io_size); |
831 | if (!err && min_io_size) | 822 | if (!err && min_io_size) |
832 | blk_queue_io_min(q, blk_size * min_io_size); | 823 | blk_queue_io_min(q, blk_size * min_io_size); |
833 | 824 | ||
834 | err = virtio_config_val(vdev, VIRTIO_BLK_F_TOPOLOGY, | 825 | err = virtio_cread_feature(vdev, VIRTIO_BLK_F_TOPOLOGY, |
835 | offsetof(struct virtio_blk_config, opt_io_size), | 826 | struct virtio_blk_config, opt_io_size, |
836 | &opt_io_size); | 827 | &opt_io_size); |
837 | if (!err && opt_io_size) | 828 | if (!err && opt_io_size) |
838 | blk_queue_io_opt(q, blk_size * opt_io_size); | 829 | blk_queue_io_opt(q, blk_size * opt_io_size); |
839 | 830 | ||
@@ -899,7 +890,7 @@ static void virtblk_remove(struct virtio_device *vdev) | |||
899 | ida_simple_remove(&vd_index_ida, index); | 890 | ida_simple_remove(&vd_index_ida, index); |
900 | } | 891 | } |
901 | 892 | ||
902 | #ifdef CONFIG_PM | 893 | #ifdef CONFIG_PM_SLEEP |
903 | static int virtblk_freeze(struct virtio_device *vdev) | 894 | static int virtblk_freeze(struct virtio_device *vdev) |
904 | { | 895 | { |
905 | struct virtio_blk *vblk = vdev->priv; | 896 | struct virtio_blk *vblk = vdev->priv; |
@@ -959,7 +950,7 @@ static struct virtio_driver virtio_blk = { | |||
959 | .probe = virtblk_probe, | 950 | .probe = virtblk_probe, |
960 | .remove = virtblk_remove, | 951 | .remove = virtblk_remove, |
961 | .config_changed = virtblk_config_changed, | 952 | .config_changed = virtblk_config_changed, |
962 | #ifdef CONFIG_PM | 953 | #ifdef CONFIG_PM_SLEEP |
963 | .freeze = virtblk_freeze, | 954 | .freeze = virtblk_freeze, |
964 | .restore = virtblk_restore, | 955 | .restore = virtblk_restore, |
965 | #endif | 956 | #endif |
diff --git a/drivers/char/hw_random/virtio-rng.c b/drivers/char/hw_random/virtio-rng.c index ef46a9cfd832..c12398d1517c 100644 --- a/drivers/char/hw_random/virtio-rng.c +++ b/drivers/char/hw_random/virtio-rng.c | |||
@@ -133,7 +133,7 @@ static void virtrng_remove(struct virtio_device *vdev) | |||
133 | remove_common(vdev); | 133 | remove_common(vdev); |
134 | } | 134 | } |
135 | 135 | ||
136 | #ifdef CONFIG_PM | 136 | #ifdef CONFIG_PM_SLEEP |
137 | static int virtrng_freeze(struct virtio_device *vdev) | 137 | static int virtrng_freeze(struct virtio_device *vdev) |
138 | { | 138 | { |
139 | remove_common(vdev); | 139 | remove_common(vdev); |
@@ -157,7 +157,7 @@ static struct virtio_driver virtio_rng_driver = { | |||
157 | .id_table = id_table, | 157 | .id_table = id_table, |
158 | .probe = virtrng_probe, | 158 | .probe = virtrng_probe, |
159 | .remove = virtrng_remove, | 159 | .remove = virtrng_remove, |
160 | #ifdef CONFIG_PM | 160 | #ifdef CONFIG_PM_SLEEP |
161 | .freeze = virtrng_freeze, | 161 | .freeze = virtrng_freeze, |
162 | .restore = virtrng_restore, | 162 | .restore = virtrng_restore, |
163 | #endif | 163 | #endif |
diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c index b79cf3e1b793..feea87cc6b8f 100644 --- a/drivers/char/virtio_console.c +++ b/drivers/char/virtio_console.c | |||
@@ -577,7 +577,8 @@ static ssize_t __send_control_msg(struct ports_device *portdev, u32 port_id, | |||
577 | spin_lock(&portdev->c_ovq_lock); | 577 | spin_lock(&portdev->c_ovq_lock); |
578 | if (virtqueue_add_outbuf(vq, sg, 1, &cpkt, GFP_ATOMIC) == 0) { | 578 | if (virtqueue_add_outbuf(vq, sg, 1, &cpkt, GFP_ATOMIC) == 0) { |
579 | virtqueue_kick(vq); | 579 | virtqueue_kick(vq); |
580 | while (!virtqueue_get_buf(vq, &len)) | 580 | while (!virtqueue_get_buf(vq, &len) |
581 | && !virtqueue_is_broken(vq)) | ||
581 | cpu_relax(); | 582 | cpu_relax(); |
582 | } | 583 | } |
583 | spin_unlock(&portdev->c_ovq_lock); | 584 | spin_unlock(&portdev->c_ovq_lock); |
@@ -650,7 +651,8 @@ static ssize_t __send_to_port(struct port *port, struct scatterlist *sg, | |||
650 | * we need to kmalloc a GFP_ATOMIC buffer each time the | 651 | * we need to kmalloc a GFP_ATOMIC buffer each time the |
651 | * console driver writes something out. | 652 | * console driver writes something out. |
652 | */ | 653 | */ |
653 | while (!virtqueue_get_buf(out_vq, &len)) | 654 | while (!virtqueue_get_buf(out_vq, &len) |
655 | && !virtqueue_is_broken(out_vq)) | ||
654 | cpu_relax(); | 656 | cpu_relax(); |
655 | done: | 657 | done: |
656 | spin_unlock_irqrestore(&port->outvq_lock, flags); | 658 | spin_unlock_irqrestore(&port->outvq_lock, flags); |
@@ -1837,12 +1839,8 @@ static void config_intr(struct virtio_device *vdev) | |||
1837 | struct port *port; | 1839 | struct port *port; |
1838 | u16 rows, cols; | 1840 | u16 rows, cols; |
1839 | 1841 | ||
1840 | vdev->config->get(vdev, | 1842 | virtio_cread(vdev, struct virtio_console_config, cols, &cols); |
1841 | offsetof(struct virtio_console_config, cols), | 1843 | virtio_cread(vdev, struct virtio_console_config, rows, &rows); |
1842 | &cols, sizeof(u16)); | ||
1843 | vdev->config->get(vdev, | ||
1844 | offsetof(struct virtio_console_config, rows), | ||
1845 | &rows, sizeof(u16)); | ||
1846 | 1844 | ||
1847 | port = find_port_by_id(portdev, 0); | 1845 | port = find_port_by_id(portdev, 0); |
1848 | set_console_size(port, rows, cols); | 1846 | set_console_size(port, rows, cols); |
@@ -2014,10 +2012,9 @@ static int virtcons_probe(struct virtio_device *vdev) | |||
2014 | 2012 | ||
2015 | /* Don't test MULTIPORT at all if we're rproc: not a valid feature! */ | 2013 | /* Don't test MULTIPORT at all if we're rproc: not a valid feature! */ |
2016 | if (!is_rproc_serial(vdev) && | 2014 | if (!is_rproc_serial(vdev) && |
2017 | virtio_config_val(vdev, VIRTIO_CONSOLE_F_MULTIPORT, | 2015 | virtio_cread_feature(vdev, VIRTIO_CONSOLE_F_MULTIPORT, |
2018 | offsetof(struct virtio_console_config, | 2016 | struct virtio_console_config, max_nr_ports, |
2019 | max_nr_ports), | 2017 | &portdev->config.max_nr_ports) == 0) { |
2020 | &portdev->config.max_nr_ports) == 0) { | ||
2021 | multiport = true; | 2018 | multiport = true; |
2022 | } | 2019 | } |
2023 | 2020 | ||
@@ -2142,7 +2139,7 @@ static struct virtio_device_id rproc_serial_id_table[] = { | |||
2142 | static unsigned int rproc_serial_features[] = { | 2139 | static unsigned int rproc_serial_features[] = { |
2143 | }; | 2140 | }; |
2144 | 2141 | ||
2145 | #ifdef CONFIG_PM | 2142 | #ifdef CONFIG_PM_SLEEP |
2146 | static int virtcons_freeze(struct virtio_device *vdev) | 2143 | static int virtcons_freeze(struct virtio_device *vdev) |
2147 | { | 2144 | { |
2148 | struct ports_device *portdev; | 2145 | struct ports_device *portdev; |
@@ -2220,7 +2217,7 @@ static struct virtio_driver virtio_console = { | |||
2220 | .probe = virtcons_probe, | 2217 | .probe = virtcons_probe, |
2221 | .remove = virtcons_remove, | 2218 | .remove = virtcons_remove, |
2222 | .config_changed = config_intr, | 2219 | .config_changed = config_intr, |
2223 | #ifdef CONFIG_PM | 2220 | #ifdef CONFIG_PM_SLEEP |
2224 | .freeze = virtcons_freeze, | 2221 | .freeze = virtcons_freeze, |
2225 | .restore = virtcons_restore, | 2222 | .restore = virtcons_restore, |
2226 | #endif | 2223 | #endif |
diff --git a/drivers/lguest/lguest_device.c b/drivers/lguest/lguest_device.c index b3256ff0d426..d0a1d8a45c81 100644 --- a/drivers/lguest/lguest_device.c +++ b/drivers/lguest/lguest_device.c | |||
@@ -229,7 +229,7 @@ struct lguest_vq_info { | |||
229 | * make a hypercall. We hand the physical address of the virtqueue so the Host | 229 | * make a hypercall. We hand the physical address of the virtqueue so the Host |
230 | * knows which virtqueue we're talking about. | 230 | * knows which virtqueue we're talking about. |
231 | */ | 231 | */ |
232 | static void lg_notify(struct virtqueue *vq) | 232 | static bool lg_notify(struct virtqueue *vq) |
233 | { | 233 | { |
234 | /* | 234 | /* |
235 | * We store our virtqueue information in the "priv" pointer of the | 235 | * We store our virtqueue information in the "priv" pointer of the |
@@ -238,6 +238,7 @@ static void lg_notify(struct virtqueue *vq) | |||
238 | struct lguest_vq_info *lvq = vq->priv; | 238 | struct lguest_vq_info *lvq = vq->priv; |
239 | 239 | ||
240 | hcall(LHCALL_NOTIFY, lvq->config.pfn << PAGE_SHIFT, 0, 0, 0); | 240 | hcall(LHCALL_NOTIFY, lvq->config.pfn << PAGE_SHIFT, 0, 0, 0); |
241 | return true; | ||
241 | } | 242 | } |
242 | 243 | ||
243 | /* An extern declaration inside a C file is bad form. Don't do it. */ | 244 | /* An extern declaration inside a C file is bad form. Don't do it. */ |
diff --git a/drivers/lguest/x86/core.c b/drivers/lguest/x86/core.c index 516923926335..922a1acbf652 100644 --- a/drivers/lguest/x86/core.c +++ b/drivers/lguest/x86/core.c | |||
@@ -157,7 +157,7 @@ static void run_guest_once(struct lg_cpu *cpu, struct lguest_pages *pages) | |||
157 | * stack, then the address of this call. This stack layout happens to | 157 | * stack, then the address of this call. This stack layout happens to |
158 | * exactly match the stack layout created by an interrupt... | 158 | * exactly match the stack layout created by an interrupt... |
159 | */ | 159 | */ |
160 | asm volatile("pushf; lcall *lguest_entry" | 160 | asm volatile("pushf; lcall *%4" |
161 | /* | 161 | /* |
162 | * This is how we tell GCC that %eax ("a") and %ebx ("b") | 162 | * This is how we tell GCC that %eax ("a") and %ebx ("b") |
163 | * are changed by this routine. The "=" means output. | 163 | * are changed by this routine. The "=" means output. |
@@ -169,7 +169,9 @@ static void run_guest_once(struct lg_cpu *cpu, struct lguest_pages *pages) | |||
169 | * physical address of the Guest's top-level page | 169 | * physical address of the Guest's top-level page |
170 | * directory. | 170 | * directory. |
171 | */ | 171 | */ |
172 | : "0"(pages), "1"(__pa(cpu->lg->pgdirs[cpu->cpu_pgd].pgdir)) | 172 | : "0"(pages), |
173 | "1"(__pa(cpu->lg->pgdirs[cpu->cpu_pgd].pgdir)), | ||
174 | "m"(lguest_entry) | ||
173 | /* | 175 | /* |
174 | * We tell gcc that all these registers could change, | 176 | * We tell gcc that all these registers could change, |
175 | * which means we don't have to save and restore them in | 177 | * which means we don't have to save and restore them in |
diff --git a/drivers/net/caif/caif_virtio.c b/drivers/net/caif/caif_virtio.c index b9ed1288ce2d..985608634f8c 100644 --- a/drivers/net/caif/caif_virtio.c +++ b/drivers/net/caif/caif_virtio.c | |||
@@ -686,18 +686,19 @@ static int cfv_probe(struct virtio_device *vdev) | |||
686 | goto err; | 686 | goto err; |
687 | 687 | ||
688 | /* Get the CAIF configuration from virtio config space, if available */ | 688 | /* Get the CAIF configuration from virtio config space, if available */ |
689 | #define GET_VIRTIO_CONFIG_OPS(_v, _var, _f) \ | ||
690 | ((_v)->config->get(_v, offsetof(struct virtio_caif_transf_config, _f), \ | ||
691 | &_var, \ | ||
692 | FIELD_SIZEOF(struct virtio_caif_transf_config, _f))) | ||
693 | |||
694 | if (vdev->config->get) { | 689 | if (vdev->config->get) { |
695 | GET_VIRTIO_CONFIG_OPS(vdev, cfv->tx_hr, headroom); | 690 | virtio_cread(vdev, struct virtio_caif_transf_config, headroom, |
696 | GET_VIRTIO_CONFIG_OPS(vdev, cfv->rx_hr, headroom); | 691 | &cfv->tx_hr); |
697 | GET_VIRTIO_CONFIG_OPS(vdev, cfv->tx_tr, tailroom); | 692 | virtio_cread(vdev, struct virtio_caif_transf_config, headroom, |
698 | GET_VIRTIO_CONFIG_OPS(vdev, cfv->rx_tr, tailroom); | 693 | &cfv->rx_hr); |
699 | GET_VIRTIO_CONFIG_OPS(vdev, cfv->mtu, mtu); | 694 | virtio_cread(vdev, struct virtio_caif_transf_config, tailroom, |
700 | GET_VIRTIO_CONFIG_OPS(vdev, cfv->mru, mtu); | 695 | &cfv->tx_tr); |
696 | virtio_cread(vdev, struct virtio_caif_transf_config, tailroom, | ||
697 | &cfv->rx_tr); | ||
698 | virtio_cread(vdev, struct virtio_caif_transf_config, mtu, | ||
699 | &cfv->mtu); | ||
700 | virtio_cread(vdev, struct virtio_caif_transf_config, mtu, | ||
701 | &cfv->mru); | ||
701 | } else { | 702 | } else { |
702 | cfv->tx_hr = CFV_DEF_HEADROOM; | 703 | cfv->tx_hr = CFV_DEF_HEADROOM; |
703 | cfv->rx_hr = CFV_DEF_HEADROOM; | 704 | cfv->rx_hr = CFV_DEF_HEADROOM; |
diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index bf7c734259ad..cdc7c90a6a9e 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c | |||
@@ -591,7 +591,8 @@ static bool try_fill_recv(struct receive_queue *rq, gfp_t gfp) | |||
591 | } while (rq->vq->num_free); | 591 | } while (rq->vq->num_free); |
592 | if (unlikely(rq->num > rq->max)) | 592 | if (unlikely(rq->num > rq->max)) |
593 | rq->max = rq->num; | 593 | rq->max = rq->num; |
594 | virtqueue_kick(rq->vq); | 594 | if (unlikely(!virtqueue_kick(rq->vq))) |
595 | return false; | ||
595 | return !oom; | 596 | return !oom; |
596 | } | 597 | } |
597 | 598 | ||
@@ -797,7 +798,7 @@ static netdev_tx_t start_xmit(struct sk_buff *skb, struct net_device *dev) | |||
797 | err = xmit_skb(sq, skb); | 798 | err = xmit_skb(sq, skb); |
798 | 799 | ||
799 | /* This should not happen! */ | 800 | /* This should not happen! */ |
800 | if (unlikely(err)) { | 801 | if (unlikely(err) || unlikely(!virtqueue_kick(sq->vq))) { |
801 | dev->stats.tx_fifo_errors++; | 802 | dev->stats.tx_fifo_errors++; |
802 | if (net_ratelimit()) | 803 | if (net_ratelimit()) |
803 | dev_warn(&dev->dev, | 804 | dev_warn(&dev->dev, |
@@ -806,7 +807,6 @@ static netdev_tx_t start_xmit(struct sk_buff *skb, struct net_device *dev) | |||
806 | kfree_skb(skb); | 807 | kfree_skb(skb); |
807 | return NETDEV_TX_OK; | 808 | return NETDEV_TX_OK; |
808 | } | 809 | } |
809 | virtqueue_kick(sq->vq); | ||
810 | 810 | ||
811 | /* Don't wait up for transmitted skbs to be freed. */ | 811 | /* Don't wait up for transmitted skbs to be freed. */ |
812 | skb_orphan(skb); | 812 | skb_orphan(skb); |
@@ -865,12 +865,14 @@ static bool virtnet_send_command(struct virtnet_info *vi, u8 class, u8 cmd, | |||
865 | BUG_ON(virtqueue_add_sgs(vi->cvq, sgs, out_num, in_num, vi, GFP_ATOMIC) | 865 | BUG_ON(virtqueue_add_sgs(vi->cvq, sgs, out_num, in_num, vi, GFP_ATOMIC) |
866 | < 0); | 866 | < 0); |
867 | 867 | ||
868 | virtqueue_kick(vi->cvq); | 868 | if (unlikely(!virtqueue_kick(vi->cvq))) |
869 | return status == VIRTIO_NET_OK; | ||
869 | 870 | ||
870 | /* Spin for a response, the kick causes an ioport write, trapping | 871 | /* Spin for a response, the kick causes an ioport write, trapping |
871 | * into the hypervisor, so the request should be handled immediately. | 872 | * into the hypervisor, so the request should be handled immediately. |
872 | */ | 873 | */ |
873 | while (!virtqueue_get_buf(vi->cvq, &tmp)) | 874 | while (!virtqueue_get_buf(vi->cvq, &tmp) && |
875 | !virtqueue_is_broken(vi->cvq)) | ||
874 | cpu_relax(); | 876 | cpu_relax(); |
875 | 877 | ||
876 | return status == VIRTIO_NET_OK; | 878 | return status == VIRTIO_NET_OK; |
@@ -898,8 +900,13 @@ static int virtnet_set_mac_address(struct net_device *dev, void *p) | |||
898 | return -EINVAL; | 900 | return -EINVAL; |
899 | } | 901 | } |
900 | } else if (virtio_has_feature(vdev, VIRTIO_NET_F_MAC)) { | 902 | } else if (virtio_has_feature(vdev, VIRTIO_NET_F_MAC)) { |
901 | vdev->config->set(vdev, offsetof(struct virtio_net_config, mac), | 903 | unsigned int i; |
902 | addr->sa_data, dev->addr_len); | 904 | |
905 | /* Naturally, this has an atomicity problem. */ | ||
906 | for (i = 0; i < dev->addr_len; i++) | ||
907 | virtio_cwrite8(vdev, | ||
908 | offsetof(struct virtio_net_config, mac) + | ||
909 | i, addr->sa_data[i]); | ||
903 | } | 910 | } |
904 | 911 | ||
905 | eth_commit_mac_addr_change(dev, p); | 912 | eth_commit_mac_addr_change(dev, p); |
@@ -1281,9 +1288,8 @@ static void virtnet_config_changed_work(struct work_struct *work) | |||
1281 | if (!vi->config_enable) | 1288 | if (!vi->config_enable) |
1282 | goto done; | 1289 | goto done; |
1283 | 1290 | ||
1284 | if (virtio_config_val(vi->vdev, VIRTIO_NET_F_STATUS, | 1291 | if (virtio_cread_feature(vi->vdev, VIRTIO_NET_F_STATUS, |
1285 | offsetof(struct virtio_net_config, status), | 1292 | struct virtio_net_config, status, &v) < 0) |
1286 | &v) < 0) | ||
1287 | goto done; | 1293 | goto done; |
1288 | 1294 | ||
1289 | if (v & VIRTIO_NET_S_ANNOUNCE) { | 1295 | if (v & VIRTIO_NET_S_ANNOUNCE) { |
@@ -1507,9 +1513,9 @@ static int virtnet_probe(struct virtio_device *vdev) | |||
1507 | u16 max_queue_pairs; | 1513 | u16 max_queue_pairs; |
1508 | 1514 | ||
1509 | /* Find if host supports multiqueue virtio_net device */ | 1515 | /* Find if host supports multiqueue virtio_net device */ |
1510 | err = virtio_config_val(vdev, VIRTIO_NET_F_MQ, | 1516 | err = virtio_cread_feature(vdev, VIRTIO_NET_F_MQ, |
1511 | offsetof(struct virtio_net_config, | 1517 | struct virtio_net_config, |
1512 | max_virtqueue_pairs), &max_queue_pairs); | 1518 | max_virtqueue_pairs, &max_queue_pairs); |
1513 | 1519 | ||
1514 | /* We need at least 2 queue's */ | 1520 | /* We need at least 2 queue's */ |
1515 | if (err || max_queue_pairs < VIRTIO_NET_CTRL_MQ_VQ_PAIRS_MIN || | 1521 | if (err || max_queue_pairs < VIRTIO_NET_CTRL_MQ_VQ_PAIRS_MIN || |
@@ -1561,9 +1567,11 @@ static int virtnet_probe(struct virtio_device *vdev) | |||
1561 | dev->vlan_features = dev->features; | 1567 | dev->vlan_features = dev->features; |
1562 | 1568 | ||
1563 | /* Configuration may specify what MAC to use. Otherwise random. */ | 1569 | /* Configuration may specify what MAC to use. Otherwise random. */ |
1564 | if (virtio_config_val_len(vdev, VIRTIO_NET_F_MAC, | 1570 | if (virtio_has_feature(vdev, VIRTIO_NET_F_MAC)) |
1565 | offsetof(struct virtio_net_config, mac), | 1571 | virtio_cread_bytes(vdev, |
1566 | dev->dev_addr, dev->addr_len) < 0) | 1572 | offsetof(struct virtio_net_config, mac), |
1573 | dev->dev_addr, dev->addr_len); | ||
1574 | else | ||
1567 | eth_hw_addr_random(dev); | 1575 | eth_hw_addr_random(dev); |
1568 | 1576 | ||
1569 | /* Set up our device-specific information */ | 1577 | /* Set up our device-specific information */ |
@@ -1704,7 +1712,7 @@ static void virtnet_remove(struct virtio_device *vdev) | |||
1704 | free_netdev(vi->dev); | 1712 | free_netdev(vi->dev); |
1705 | } | 1713 | } |
1706 | 1714 | ||
1707 | #ifdef CONFIG_PM | 1715 | #ifdef CONFIG_PM_SLEEP |
1708 | static int virtnet_freeze(struct virtio_device *vdev) | 1716 | static int virtnet_freeze(struct virtio_device *vdev) |
1709 | { | 1717 | { |
1710 | struct virtnet_info *vi = vdev->priv; | 1718 | struct virtnet_info *vi = vdev->priv; |
@@ -1795,7 +1803,7 @@ static struct virtio_driver virtio_net_driver = { | |||
1795 | .probe = virtnet_probe, | 1803 | .probe = virtnet_probe, |
1796 | .remove = virtnet_remove, | 1804 | .remove = virtnet_remove, |
1797 | .config_changed = virtnet_config_changed, | 1805 | .config_changed = virtnet_config_changed, |
1798 | #ifdef CONFIG_PM | 1806 | #ifdef CONFIG_PM_SLEEP |
1799 | .freeze = virtnet_freeze, | 1807 | .freeze = virtnet_freeze, |
1800 | .restore = virtnet_restore, | 1808 | .restore = virtnet_restore, |
1801 | #endif | 1809 | #endif |
diff --git a/drivers/remoteproc/remoteproc_virtio.c b/drivers/remoteproc/remoteproc_virtio.c index b09c75c21b60..a34b50690b4e 100644 --- a/drivers/remoteproc/remoteproc_virtio.c +++ b/drivers/remoteproc/remoteproc_virtio.c | |||
@@ -30,7 +30,7 @@ | |||
30 | #include "remoteproc_internal.h" | 30 | #include "remoteproc_internal.h" |
31 | 31 | ||
32 | /* kick the remote processor, and let it know which virtqueue to poke at */ | 32 | /* kick the remote processor, and let it know which virtqueue to poke at */ |
33 | static void rproc_virtio_notify(struct virtqueue *vq) | 33 | static bool rproc_virtio_notify(struct virtqueue *vq) |
34 | { | 34 | { |
35 | struct rproc_vring *rvring = vq->priv; | 35 | struct rproc_vring *rvring = vq->priv; |
36 | struct rproc *rproc = rvring->rvdev->rproc; | 36 | struct rproc *rproc = rvring->rvdev->rproc; |
@@ -39,6 +39,7 @@ static void rproc_virtio_notify(struct virtqueue *vq) | |||
39 | dev_dbg(&rproc->dev, "kicking vq index: %d\n", notifyid); | 39 | dev_dbg(&rproc->dev, "kicking vq index: %d\n", notifyid); |
40 | 40 | ||
41 | rproc->ops->kick(rproc, notifyid); | 41 | rproc->ops->kick(rproc, notifyid); |
42 | return true; | ||
42 | } | 43 | } |
43 | 44 | ||
44 | /** | 45 | /** |
diff --git a/drivers/s390/kvm/kvm_virtio.c b/drivers/s390/kvm/kvm_virtio.c index af2166fa5159..1abd0db29915 100644 --- a/drivers/s390/kvm/kvm_virtio.c +++ b/drivers/s390/kvm/kvm_virtio.c | |||
@@ -166,11 +166,15 @@ static void kvm_reset(struct virtio_device *vdev) | |||
166 | * make a hypercall. We hand the address of the virtqueue so the Host | 166 | * make a hypercall. We hand the address of the virtqueue so the Host |
167 | * knows which virtqueue we're talking about. | 167 | * knows which virtqueue we're talking about. |
168 | */ | 168 | */ |
169 | static void kvm_notify(struct virtqueue *vq) | 169 | static bool kvm_notify(struct virtqueue *vq) |
170 | { | 170 | { |
171 | long rc; | ||
171 | struct kvm_vqconfig *config = vq->priv; | 172 | struct kvm_vqconfig *config = vq->priv; |
172 | 173 | ||
173 | kvm_hypercall1(KVM_S390_VIRTIO_NOTIFY, config->address); | 174 | rc = kvm_hypercall1(KVM_S390_VIRTIO_NOTIFY, config->address); |
175 | if (rc < 0) | ||
176 | return false; | ||
177 | return true; | ||
174 | } | 178 | } |
175 | 179 | ||
176 | /* | 180 | /* |
diff --git a/drivers/s390/kvm/virtio_ccw.c b/drivers/s390/kvm/virtio_ccw.c index 779dc5136291..d6297176ab85 100644 --- a/drivers/s390/kvm/virtio_ccw.c +++ b/drivers/s390/kvm/virtio_ccw.c | |||
@@ -162,7 +162,7 @@ static inline long do_kvm_notify(struct subchannel_id schid, | |||
162 | return __rc; | 162 | return __rc; |
163 | } | 163 | } |
164 | 164 | ||
165 | static void virtio_ccw_kvm_notify(struct virtqueue *vq) | 165 | static bool virtio_ccw_kvm_notify(struct virtqueue *vq) |
166 | { | 166 | { |
167 | struct virtio_ccw_vq_info *info = vq->priv; | 167 | struct virtio_ccw_vq_info *info = vq->priv; |
168 | struct virtio_ccw_device *vcdev; | 168 | struct virtio_ccw_device *vcdev; |
@@ -171,6 +171,9 @@ static void virtio_ccw_kvm_notify(struct virtqueue *vq) | |||
171 | vcdev = to_vc_device(info->vq->vdev); | 171 | vcdev = to_vc_device(info->vq->vdev); |
172 | ccw_device_get_schid(vcdev->cdev, &schid); | 172 | ccw_device_get_schid(vcdev->cdev, &schid); |
173 | info->cookie = do_kvm_notify(schid, vq->index, info->cookie); | 173 | info->cookie = do_kvm_notify(schid, vq->index, info->cookie); |
174 | if (info->cookie < 0) | ||
175 | return false; | ||
176 | return true; | ||
174 | } | 177 | } |
175 | 178 | ||
176 | static int virtio_ccw_read_vq_conf(struct virtio_ccw_device *vcdev, | 179 | static int virtio_ccw_read_vq_conf(struct virtio_ccw_device *vcdev, |
diff --git a/drivers/scsi/virtio_scsi.c b/drivers/scsi/virtio_scsi.c index 74b88efde6ad..c3173dced870 100644 --- a/drivers/scsi/virtio_scsi.c +++ b/drivers/scsi/virtio_scsi.c | |||
@@ -224,6 +224,9 @@ static void virtscsi_vq_done(struct virtio_scsi *vscsi, | |||
224 | virtqueue_disable_cb(vq); | 224 | virtqueue_disable_cb(vq); |
225 | while ((buf = virtqueue_get_buf(vq, &len)) != NULL) | 225 | while ((buf = virtqueue_get_buf(vq, &len)) != NULL) |
226 | fn(vscsi, buf); | 226 | fn(vscsi, buf); |
227 | |||
228 | if (unlikely(virtqueue_is_broken(vq))) | ||
229 | break; | ||
227 | } while (!virtqueue_enable_cb(vq)); | 230 | } while (!virtqueue_enable_cb(vq)); |
228 | spin_unlock_irqrestore(&virtscsi_vq->vq_lock, flags); | 231 | spin_unlock_irqrestore(&virtscsi_vq->vq_lock, flags); |
229 | } | 232 | } |
@@ -710,19 +713,15 @@ static struct scsi_host_template virtscsi_host_template_multi = { | |||
710 | #define virtscsi_config_get(vdev, fld) \ | 713 | #define virtscsi_config_get(vdev, fld) \ |
711 | ({ \ | 714 | ({ \ |
712 | typeof(((struct virtio_scsi_config *)0)->fld) __val; \ | 715 | typeof(((struct virtio_scsi_config *)0)->fld) __val; \ |
713 | vdev->config->get(vdev, \ | 716 | virtio_cread(vdev, struct virtio_scsi_config, fld, &__val); \ |
714 | offsetof(struct virtio_scsi_config, fld), \ | ||
715 | &__val, sizeof(__val)); \ | ||
716 | __val; \ | 717 | __val; \ |
717 | }) | 718 | }) |
718 | 719 | ||
719 | #define virtscsi_config_set(vdev, fld, val) \ | 720 | #define virtscsi_config_set(vdev, fld, val) \ |
720 | (void)({ \ | 721 | do { \ |
721 | typeof(((struct virtio_scsi_config *)0)->fld) __val = (val); \ | 722 | typeof(((struct virtio_scsi_config *)0)->fld) __val = (val); \ |
722 | vdev->config->set(vdev, \ | 723 | virtio_cwrite(vdev, struct virtio_scsi_config, fld, &__val); \ |
723 | offsetof(struct virtio_scsi_config, fld), \ | 724 | } while(0) |
724 | &__val, sizeof(__val)); \ | ||
725 | }) | ||
726 | 725 | ||
727 | static void __virtscsi_set_affinity(struct virtio_scsi *vscsi, bool affinity) | 726 | static void __virtscsi_set_affinity(struct virtio_scsi *vscsi, bool affinity) |
728 | { | 727 | { |
@@ -954,7 +953,7 @@ static void virtscsi_remove(struct virtio_device *vdev) | |||
954 | scsi_host_put(shost); | 953 | scsi_host_put(shost); |
955 | } | 954 | } |
956 | 955 | ||
957 | #ifdef CONFIG_PM | 956 | #ifdef CONFIG_PM_SLEEP |
958 | static int virtscsi_freeze(struct virtio_device *vdev) | 957 | static int virtscsi_freeze(struct virtio_device *vdev) |
959 | { | 958 | { |
960 | virtscsi_remove_vqs(vdev); | 959 | virtscsi_remove_vqs(vdev); |
@@ -988,7 +987,7 @@ static struct virtio_driver virtio_scsi_driver = { | |||
988 | .id_table = id_table, | 987 | .id_table = id_table, |
989 | .probe = virtscsi_probe, | 988 | .probe = virtscsi_probe, |
990 | .scan = virtscsi_scan, | 989 | .scan = virtscsi_scan, |
991 | #ifdef CONFIG_PM | 990 | #ifdef CONFIG_PM_SLEEP |
992 | .freeze = virtscsi_freeze, | 991 | .freeze = virtscsi_freeze, |
993 | .restore = virtscsi_restore, | 992 | .restore = virtscsi_restore, |
994 | #endif | 993 | #endif |
diff --git a/drivers/virtio/virtio_balloon.c b/drivers/virtio/virtio_balloon.c index 1f572c00a1be..c444654fc33f 100644 --- a/drivers/virtio/virtio_balloon.c +++ b/drivers/virtio/virtio_balloon.c | |||
@@ -275,9 +275,8 @@ static inline s64 towards_target(struct virtio_balloon *vb) | |||
275 | __le32 v; | 275 | __le32 v; |
276 | s64 target; | 276 | s64 target; |
277 | 277 | ||
278 | vb->vdev->config->get(vb->vdev, | 278 | virtio_cread(vb->vdev, struct virtio_balloon_config, num_pages, &v); |
279 | offsetof(struct virtio_balloon_config, num_pages), | 279 | |
280 | &v, sizeof(v)); | ||
281 | target = le32_to_cpu(v); | 280 | target = le32_to_cpu(v); |
282 | return target - vb->num_pages; | 281 | return target - vb->num_pages; |
283 | } | 282 | } |
@@ -286,9 +285,8 @@ static void update_balloon_size(struct virtio_balloon *vb) | |||
286 | { | 285 | { |
287 | __le32 actual = cpu_to_le32(vb->num_pages); | 286 | __le32 actual = cpu_to_le32(vb->num_pages); |
288 | 287 | ||
289 | vb->vdev->config->set(vb->vdev, | 288 | virtio_cwrite(vb->vdev, struct virtio_balloon_config, num_pages, |
290 | offsetof(struct virtio_balloon_config, actual), | 289 | &actual); |
291 | &actual, sizeof(actual)); | ||
292 | } | 290 | } |
293 | 291 | ||
294 | static int balloon(void *_vballoon) | 292 | static int balloon(void *_vballoon) |
@@ -513,7 +511,7 @@ static void virtballoon_remove(struct virtio_device *vdev) | |||
513 | kfree(vb); | 511 | kfree(vb); |
514 | } | 512 | } |
515 | 513 | ||
516 | #ifdef CONFIG_PM | 514 | #ifdef CONFIG_PM_SLEEP |
517 | static int virtballoon_freeze(struct virtio_device *vdev) | 515 | static int virtballoon_freeze(struct virtio_device *vdev) |
518 | { | 516 | { |
519 | struct virtio_balloon *vb = vdev->priv; | 517 | struct virtio_balloon *vb = vdev->priv; |
@@ -556,7 +554,7 @@ static struct virtio_driver virtio_balloon_driver = { | |||
556 | .probe = virtballoon_probe, | 554 | .probe = virtballoon_probe, |
557 | .remove = virtballoon_remove, | 555 | .remove = virtballoon_remove, |
558 | .config_changed = virtballoon_changed, | 556 | .config_changed = virtballoon_changed, |
559 | #ifdef CONFIG_PM | 557 | #ifdef CONFIG_PM_SLEEP |
560 | .freeze = virtballoon_freeze, | 558 | .freeze = virtballoon_freeze, |
561 | .restore = virtballoon_restore, | 559 | .restore = virtballoon_restore, |
562 | #endif | 560 | #endif |
diff --git a/drivers/virtio/virtio_mmio.c b/drivers/virtio/virtio_mmio.c index 1ba0d6831015..c600ccfd6922 100644 --- a/drivers/virtio/virtio_mmio.c +++ b/drivers/virtio/virtio_mmio.c | |||
@@ -219,13 +219,14 @@ static void vm_reset(struct virtio_device *vdev) | |||
219 | /* Transport interface */ | 219 | /* Transport interface */ |
220 | 220 | ||
221 | /* the notify function used when creating a virt queue */ | 221 | /* the notify function used when creating a virt queue */ |
222 | static void vm_notify(struct virtqueue *vq) | 222 | static bool vm_notify(struct virtqueue *vq) |
223 | { | 223 | { |
224 | struct virtio_mmio_device *vm_dev = to_virtio_mmio_device(vq->vdev); | 224 | struct virtio_mmio_device *vm_dev = to_virtio_mmio_device(vq->vdev); |
225 | 225 | ||
226 | /* We write the queue's selector into the notification register to | 226 | /* We write the queue's selector into the notification register to |
227 | * signal the other end */ | 227 | * signal the other end */ |
228 | writel(vq->index, vm_dev->base + VIRTIO_MMIO_QUEUE_NOTIFY); | 228 | writel(vq->index, vm_dev->base + VIRTIO_MMIO_QUEUE_NOTIFY); |
229 | return true; | ||
229 | } | 230 | } |
230 | 231 | ||
231 | /* Notify all virtqueues on an interrupt. */ | 232 | /* Notify all virtqueues on an interrupt. */ |
@@ -470,7 +471,7 @@ static int virtio_mmio_probe(struct platform_device *pdev) | |||
470 | 471 | ||
471 | /* Check magic value */ | 472 | /* Check magic value */ |
472 | magic = readl(vm_dev->base + VIRTIO_MMIO_MAGIC_VALUE); | 473 | magic = readl(vm_dev->base + VIRTIO_MMIO_MAGIC_VALUE); |
473 | if (memcmp(&magic, "virt", 4) != 0) { | 474 | if (magic != ('v' | 'i' << 8 | 'r' << 16 | 't' << 24)) { |
474 | dev_warn(&pdev->dev, "Wrong magic value 0x%08lx!\n", magic); | 475 | dev_warn(&pdev->dev, "Wrong magic value 0x%08lx!\n", magic); |
475 | return -ENODEV; | 476 | return -ENODEV; |
476 | } | 477 | } |
diff --git a/drivers/virtio/virtio_pci.c b/drivers/virtio/virtio_pci.c index 98917fc872a4..a37c69941d30 100644 --- a/drivers/virtio/virtio_pci.c +++ b/drivers/virtio/virtio_pci.c | |||
@@ -197,13 +197,14 @@ static void vp_reset(struct virtio_device *vdev) | |||
197 | } | 197 | } |
198 | 198 | ||
199 | /* the notify function used when creating a virt queue */ | 199 | /* the notify function used when creating a virt queue */ |
200 | static void vp_notify(struct virtqueue *vq) | 200 | static bool vp_notify(struct virtqueue *vq) |
201 | { | 201 | { |
202 | struct virtio_pci_device *vp_dev = to_vp_device(vq->vdev); | 202 | struct virtio_pci_device *vp_dev = to_vp_device(vq->vdev); |
203 | 203 | ||
204 | /* we write the queue's selector into the notification register to | 204 | /* we write the queue's selector into the notification register to |
205 | * signal the other end */ | 205 | * signal the other end */ |
206 | iowrite16(vq->index, vp_dev->ioaddr + VIRTIO_PCI_QUEUE_NOTIFY); | 206 | iowrite16(vq->index, vp_dev->ioaddr + VIRTIO_PCI_QUEUE_NOTIFY); |
207 | return true; | ||
207 | } | 208 | } |
208 | 209 | ||
209 | /* Handle a configuration change: Tell driver if it wants to know. */ | 210 | /* Handle a configuration change: Tell driver if it wants to know. */ |
diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c index 6b4a4db4404d..28b5338fff71 100644 --- a/drivers/virtio/virtio_ring.c +++ b/drivers/virtio/virtio_ring.c | |||
@@ -81,7 +81,7 @@ struct vring_virtqueue | |||
81 | u16 last_used_idx; | 81 | u16 last_used_idx; |
82 | 82 | ||
83 | /* How to notify other side. FIXME: commonalize hcalls! */ | 83 | /* How to notify other side. FIXME: commonalize hcalls! */ |
84 | void (*notify)(struct virtqueue *vq); | 84 | bool (*notify)(struct virtqueue *vq); |
85 | 85 | ||
86 | #ifdef DEBUG | 86 | #ifdef DEBUG |
87 | /* They're supposed to lock for us. */ | 87 | /* They're supposed to lock for us. */ |
@@ -173,6 +173,8 @@ static inline int vring_add_indirect(struct vring_virtqueue *vq, | |||
173 | head = vq->free_head; | 173 | head = vq->free_head; |
174 | vq->vring.desc[head].flags = VRING_DESC_F_INDIRECT; | 174 | vq->vring.desc[head].flags = VRING_DESC_F_INDIRECT; |
175 | vq->vring.desc[head].addr = virt_to_phys(desc); | 175 | vq->vring.desc[head].addr = virt_to_phys(desc); |
176 | /* kmemleak gives a false positive, as it's hidden by virt_to_phys */ | ||
177 | kmemleak_ignore(desc); | ||
176 | vq->vring.desc[head].len = i * sizeof(struct vring_desc); | 178 | vq->vring.desc[head].len = i * sizeof(struct vring_desc); |
177 | 179 | ||
178 | /* Update free pointer */ | 180 | /* Update free pointer */ |
@@ -428,13 +430,22 @@ EXPORT_SYMBOL_GPL(virtqueue_kick_prepare); | |||
428 | * @vq: the struct virtqueue | 430 | * @vq: the struct virtqueue |
429 | * | 431 | * |
430 | * This does not need to be serialized. | 432 | * This does not need to be serialized. |
433 | * | ||
434 | * Returns false if host notify failed or queue is broken, otherwise true. | ||
431 | */ | 435 | */ |
432 | void virtqueue_notify(struct virtqueue *_vq) | 436 | bool virtqueue_notify(struct virtqueue *_vq) |
433 | { | 437 | { |
434 | struct vring_virtqueue *vq = to_vvq(_vq); | 438 | struct vring_virtqueue *vq = to_vvq(_vq); |
435 | 439 | ||
440 | if (unlikely(vq->broken)) | ||
441 | return false; | ||
442 | |||
436 | /* Prod other side to tell it about changes. */ | 443 | /* Prod other side to tell it about changes. */ |
437 | vq->notify(_vq); | 444 | if (!vq->notify(_vq)) { |
445 | vq->broken = true; | ||
446 | return false; | ||
447 | } | ||
448 | return true; | ||
438 | } | 449 | } |
439 | EXPORT_SYMBOL_GPL(virtqueue_notify); | 450 | EXPORT_SYMBOL_GPL(virtqueue_notify); |
440 | 451 | ||
@@ -447,11 +458,14 @@ EXPORT_SYMBOL_GPL(virtqueue_notify); | |||
447 | * | 458 | * |
448 | * Caller must ensure we don't call this with other virtqueue | 459 | * Caller must ensure we don't call this with other virtqueue |
449 | * operations at the same time (except where noted). | 460 | * operations at the same time (except where noted). |
461 | * | ||
462 | * Returns false if kick failed, otherwise true. | ||
450 | */ | 463 | */ |
451 | void virtqueue_kick(struct virtqueue *vq) | 464 | bool virtqueue_kick(struct virtqueue *vq) |
452 | { | 465 | { |
453 | if (virtqueue_kick_prepare(vq)) | 466 | if (virtqueue_kick_prepare(vq)) |
454 | virtqueue_notify(vq); | 467 | return virtqueue_notify(vq); |
468 | return true; | ||
455 | } | 469 | } |
456 | EXPORT_SYMBOL_GPL(virtqueue_kick); | 470 | EXPORT_SYMBOL_GPL(virtqueue_kick); |
457 | 471 | ||
@@ -742,7 +756,7 @@ struct virtqueue *vring_new_virtqueue(unsigned int index, | |||
742 | struct virtio_device *vdev, | 756 | struct virtio_device *vdev, |
743 | bool weak_barriers, | 757 | bool weak_barriers, |
744 | void *pages, | 758 | void *pages, |
745 | void (*notify)(struct virtqueue *), | 759 | bool (*notify)(struct virtqueue *), |
746 | void (*callback)(struct virtqueue *), | 760 | void (*callback)(struct virtqueue *), |
747 | const char *name) | 761 | const char *name) |
748 | { | 762 | { |
@@ -837,4 +851,12 @@ unsigned int virtqueue_get_vring_size(struct virtqueue *_vq) | |||
837 | } | 851 | } |
838 | EXPORT_SYMBOL_GPL(virtqueue_get_vring_size); | 852 | EXPORT_SYMBOL_GPL(virtqueue_get_vring_size); |
839 | 853 | ||
854 | bool virtqueue_is_broken(struct virtqueue *_vq) | ||
855 | { | ||
856 | struct vring_virtqueue *vq = to_vvq(_vq); | ||
857 | |||
858 | return vq->broken; | ||
859 | } | ||
860 | EXPORT_SYMBOL_GPL(virtqueue_is_broken); | ||
861 | |||
840 | MODULE_LICENSE("GPL"); | 862 | MODULE_LICENSE("GPL"); |
diff --git a/include/linux/virtio.h b/include/linux/virtio.h index 36d36cc89329..e4abb84199be 100644 --- a/include/linux/virtio.h +++ b/include/linux/virtio.h | |||
@@ -51,11 +51,11 @@ int virtqueue_add_sgs(struct virtqueue *vq, | |||
51 | void *data, | 51 | void *data, |
52 | gfp_t gfp); | 52 | gfp_t gfp); |
53 | 53 | ||
54 | void virtqueue_kick(struct virtqueue *vq); | 54 | bool virtqueue_kick(struct virtqueue *vq); |
55 | 55 | ||
56 | bool virtqueue_kick_prepare(struct virtqueue *vq); | 56 | bool virtqueue_kick_prepare(struct virtqueue *vq); |
57 | 57 | ||
58 | void virtqueue_notify(struct virtqueue *vq); | 58 | bool virtqueue_notify(struct virtqueue *vq); |
59 | 59 | ||
60 | void *virtqueue_get_buf(struct virtqueue *vq, unsigned int *len); | 60 | void *virtqueue_get_buf(struct virtqueue *vq, unsigned int *len); |
61 | 61 | ||
@@ -73,6 +73,8 @@ void *virtqueue_detach_unused_buf(struct virtqueue *vq); | |||
73 | 73 | ||
74 | unsigned int virtqueue_get_vring_size(struct virtqueue *vq); | 74 | unsigned int virtqueue_get_vring_size(struct virtqueue *vq); |
75 | 75 | ||
76 | bool virtqueue_is_broken(struct virtqueue *vq); | ||
77 | |||
76 | /** | 78 | /** |
77 | * virtio_device - representation of a device using virtio | 79 | * virtio_device - representation of a device using virtio |
78 | * @index: unique position on the virtio bus | 80 | * @index: unique position on the virtio bus |
diff --git a/include/linux/virtio_config.h b/include/linux/virtio_config.h index 29b9104232b4..e8f8f71e843c 100644 --- a/include/linux/virtio_config.h +++ b/include/linux/virtio_config.h | |||
@@ -96,33 +96,6 @@ static inline bool virtio_has_feature(const struct virtio_device *vdev, | |||
96 | return test_bit(fbit, vdev->features); | 96 | return test_bit(fbit, vdev->features); |
97 | } | 97 | } |
98 | 98 | ||
99 | /** | ||
100 | * virtio_config_val - look for a feature and get a virtio config entry. | ||
101 | * @vdev: the virtio device | ||
102 | * @fbit: the feature bit | ||
103 | * @offset: the type to search for. | ||
104 | * @v: a pointer to the value to fill in. | ||
105 | * | ||
106 | * The return value is -ENOENT if the feature doesn't exist. Otherwise | ||
107 | * the config value is copied into whatever is pointed to by v. */ | ||
108 | #define virtio_config_val(vdev, fbit, offset, v) \ | ||
109 | virtio_config_buf((vdev), (fbit), (offset), (v), sizeof(*v)) | ||
110 | |||
111 | #define virtio_config_val_len(vdev, fbit, offset, v, len) \ | ||
112 | virtio_config_buf((vdev), (fbit), (offset), (v), (len)) | ||
113 | |||
114 | static inline int virtio_config_buf(struct virtio_device *vdev, | ||
115 | unsigned int fbit, | ||
116 | unsigned int offset, | ||
117 | void *buf, unsigned len) | ||
118 | { | ||
119 | if (!virtio_has_feature(vdev, fbit)) | ||
120 | return -ENOENT; | ||
121 | |||
122 | vdev->config->get(vdev, offset, buf, len); | ||
123 | return 0; | ||
124 | } | ||
125 | |||
126 | static inline | 99 | static inline |
127 | struct virtqueue *virtio_find_single_vq(struct virtio_device *vdev, | 100 | struct virtqueue *virtio_find_single_vq(struct virtio_device *vdev, |
128 | vq_callback_t *c, const char *n) | 101 | vq_callback_t *c, const char *n) |
@@ -162,5 +135,139 @@ int virtqueue_set_affinity(struct virtqueue *vq, int cpu) | |||
162 | return 0; | 135 | return 0; |
163 | } | 136 | } |
164 | 137 | ||
138 | /* Config space accessors. */ | ||
139 | #define virtio_cread(vdev, structname, member, ptr) \ | ||
140 | do { \ | ||
141 | /* Must match the member's type, and be integer */ \ | ||
142 | if (!typecheck(typeof((((structname*)0)->member)), *(ptr))) \ | ||
143 | (*ptr) = 1; \ | ||
144 | \ | ||
145 | switch (sizeof(*ptr)) { \ | ||
146 | case 1: \ | ||
147 | *(ptr) = virtio_cread8(vdev, \ | ||
148 | offsetof(structname, member)); \ | ||
149 | break; \ | ||
150 | case 2: \ | ||
151 | *(ptr) = virtio_cread16(vdev, \ | ||
152 | offsetof(structname, member)); \ | ||
153 | break; \ | ||
154 | case 4: \ | ||
155 | *(ptr) = virtio_cread32(vdev, \ | ||
156 | offsetof(structname, member)); \ | ||
157 | break; \ | ||
158 | case 8: \ | ||
159 | *(ptr) = virtio_cread64(vdev, \ | ||
160 | offsetof(structname, member)); \ | ||
161 | break; \ | ||
162 | default: \ | ||
163 | BUG(); \ | ||
164 | } \ | ||
165 | } while(0) | ||
166 | |||
167 | /* Config space accessors. */ | ||
168 | #define virtio_cwrite(vdev, structname, member, ptr) \ | ||
169 | do { \ | ||
170 | /* Must match the member's type, and be integer */ \ | ||
171 | if (!typecheck(typeof((((structname*)0)->member)), *(ptr))) \ | ||
172 | BUG_ON((*ptr) == 1); \ | ||
173 | \ | ||
174 | switch (sizeof(*ptr)) { \ | ||
175 | case 1: \ | ||
176 | virtio_cwrite8(vdev, \ | ||
177 | offsetof(structname, member), \ | ||
178 | *(ptr)); \ | ||
179 | break; \ | ||
180 | case 2: \ | ||
181 | virtio_cwrite16(vdev, \ | ||
182 | offsetof(structname, member), \ | ||
183 | *(ptr)); \ | ||
184 | break; \ | ||
185 | case 4: \ | ||
186 | virtio_cwrite32(vdev, \ | ||
187 | offsetof(structname, member), \ | ||
188 | *(ptr)); \ | ||
189 | break; \ | ||
190 | case 8: \ | ||
191 | virtio_cwrite64(vdev, \ | ||
192 | offsetof(structname, member), \ | ||
193 | *(ptr)); \ | ||
194 | break; \ | ||
195 | default: \ | ||
196 | BUG(); \ | ||
197 | } \ | ||
198 | } while(0) | ||
199 | |||
200 | static inline u8 virtio_cread8(struct virtio_device *vdev, unsigned int offset) | ||
201 | { | ||
202 | u8 ret; | ||
203 | vdev->config->get(vdev, offset, &ret, sizeof(ret)); | ||
204 | return ret; | ||
205 | } | ||
206 | |||
207 | static inline void virtio_cread_bytes(struct virtio_device *vdev, | ||
208 | unsigned int offset, | ||
209 | void *buf, size_t len) | ||
210 | { | ||
211 | vdev->config->get(vdev, offset, buf, len); | ||
212 | } | ||
213 | |||
214 | static inline void virtio_cwrite8(struct virtio_device *vdev, | ||
215 | unsigned int offset, u8 val) | ||
216 | { | ||
217 | vdev->config->set(vdev, offset, &val, sizeof(val)); | ||
218 | } | ||
219 | |||
220 | static inline u16 virtio_cread16(struct virtio_device *vdev, | ||
221 | unsigned int offset) | ||
222 | { | ||
223 | u16 ret; | ||
224 | vdev->config->get(vdev, offset, &ret, sizeof(ret)); | ||
225 | return ret; | ||
226 | } | ||
227 | |||
228 | static inline void virtio_cwrite16(struct virtio_device *vdev, | ||
229 | unsigned int offset, u16 val) | ||
230 | { | ||
231 | vdev->config->set(vdev, offset, &val, sizeof(val)); | ||
232 | } | ||
233 | |||
234 | static inline u32 virtio_cread32(struct virtio_device *vdev, | ||
235 | unsigned int offset) | ||
236 | { | ||
237 | u32 ret; | ||
238 | vdev->config->get(vdev, offset, &ret, sizeof(ret)); | ||
239 | return ret; | ||
240 | } | ||
241 | |||
242 | static inline void virtio_cwrite32(struct virtio_device *vdev, | ||
243 | unsigned int offset, u32 val) | ||
244 | { | ||
245 | vdev->config->set(vdev, offset, &val, sizeof(val)); | ||
246 | } | ||
247 | |||
248 | static inline u64 virtio_cread64(struct virtio_device *vdev, | ||
249 | unsigned int offset) | ||
250 | { | ||
251 | u64 ret; | ||
252 | vdev->config->get(vdev, offset, &ret, sizeof(ret)); | ||
253 | return ret; | ||
254 | } | ||
255 | |||
256 | static inline void virtio_cwrite64(struct virtio_device *vdev, | ||
257 | unsigned int offset, u64 val) | ||
258 | { | ||
259 | vdev->config->set(vdev, offset, &val, sizeof(val)); | ||
260 | } | ||
261 | |||
262 | /* Conditional config space accessors. */ | ||
263 | #define virtio_cread_feature(vdev, fbit, structname, member, ptr) \ | ||
264 | ({ \ | ||
265 | int _r = 0; \ | ||
266 | if (!virtio_has_feature(vdev, fbit)) \ | ||
267 | _r = -ENOENT; \ | ||
268 | else \ | ||
269 | virtio_cread((vdev), structname, member, ptr); \ | ||
270 | _r; \ | ||
271 | }) | ||
165 | 272 | ||
166 | #endif /* _LINUX_VIRTIO_CONFIG_H */ | 273 | #endif /* _LINUX_VIRTIO_CONFIG_H */ |
diff --git a/include/linux/virtio_ring.h b/include/linux/virtio_ring.h index b300787af8e0..67e06fe18c03 100644 --- a/include/linux/virtio_ring.h +++ b/include/linux/virtio_ring.h | |||
@@ -71,7 +71,7 @@ struct virtqueue *vring_new_virtqueue(unsigned int index, | |||
71 | struct virtio_device *vdev, | 71 | struct virtio_device *vdev, |
72 | bool weak_barriers, | 72 | bool weak_barriers, |
73 | void *pages, | 73 | void *pages, |
74 | void (*notify)(struct virtqueue *vq), | 74 | bool (*notify)(struct virtqueue *vq), |
75 | void (*callback)(struct virtqueue *vq), | 75 | void (*callback)(struct virtqueue *vq), |
76 | const char *name); | 76 | const char *name); |
77 | void vring_del_virtqueue(struct virtqueue *vq); | 77 | void vring_del_virtqueue(struct virtqueue *vq); |
diff --git a/net/9p/trans_virtio.c b/net/9p/trans_virtio.c index 990afab2be1b..9c5a1aa34d12 100644 --- a/net/9p/trans_virtio.c +++ b/net/9p/trans_virtio.c | |||
@@ -544,9 +544,7 @@ static int p9_virtio_probe(struct virtio_device *vdev) | |||
544 | 544 | ||
545 | chan->inuse = false; | 545 | chan->inuse = false; |
546 | if (virtio_has_feature(vdev, VIRTIO_9P_MOUNT_TAG)) { | 546 | if (virtio_has_feature(vdev, VIRTIO_9P_MOUNT_TAG)) { |
547 | vdev->config->get(vdev, | 547 | virtio_cread(vdev, struct virtio_9p_config, tag_len, &tag_len); |
548 | offsetof(struct virtio_9p_config, tag_len), | ||
549 | &tag_len, sizeof(tag_len)); | ||
550 | } else { | 548 | } else { |
551 | err = -EINVAL; | 549 | err = -EINVAL; |
552 | goto out_free_vq; | 550 | goto out_free_vq; |
@@ -556,8 +554,9 @@ static int p9_virtio_probe(struct virtio_device *vdev) | |||
556 | err = -ENOMEM; | 554 | err = -ENOMEM; |
557 | goto out_free_vq; | 555 | goto out_free_vq; |
558 | } | 556 | } |
559 | vdev->config->get(vdev, offsetof(struct virtio_9p_config, tag), | 557 | |
560 | tag, tag_len); | 558 | virtio_cread_bytes(vdev, offsetof(struct virtio_9p_config, tag), |
559 | tag, tag_len); | ||
561 | chan->tag = tag; | 560 | chan->tag = tag; |
562 | chan->tag_len = tag_len; | 561 | chan->tag_len = tag_len; |
563 | err = sysfs_create_file(&(vdev->dev.kobj), &dev_attr_mount_tag.attr); | 562 | err = sysfs_create_file(&(vdev->dev.kobj), &dev_attr_mount_tag.attr); |
diff --git a/tools/virtio/virtio_test.c b/tools/virtio/virtio_test.c index da7a19558281..bdb71a26ae35 100644 --- a/tools/virtio/virtio_test.c +++ b/tools/virtio/virtio_test.c | |||
@@ -41,13 +41,14 @@ struct vdev_info { | |||
41 | struct vhost_memory *mem; | 41 | struct vhost_memory *mem; |
42 | }; | 42 | }; |
43 | 43 | ||
44 | void vq_notify(struct virtqueue *vq) | 44 | bool vq_notify(struct virtqueue *vq) |
45 | { | 45 | { |
46 | struct vq_info *info = vq->priv; | 46 | struct vq_info *info = vq->priv; |
47 | unsigned long long v = 1; | 47 | unsigned long long v = 1; |
48 | int r; | 48 | int r; |
49 | r = write(info->kick, &v, sizeof v); | 49 | r = write(info->kick, &v, sizeof v); |
50 | assert(r == sizeof v); | 50 | assert(r == sizeof v); |
51 | return true; | ||
51 | } | 52 | } |
52 | 53 | ||
53 | void vq_callback(struct virtqueue *vq) | 54 | void vq_callback(struct virtqueue *vq) |
@@ -171,7 +172,8 @@ static void run_test(struct vdev_info *dev, struct vq_info *vq, | |||
171 | GFP_ATOMIC); | 172 | GFP_ATOMIC); |
172 | if (likely(r == 0)) { | 173 | if (likely(r == 0)) { |
173 | ++started; | 174 | ++started; |
174 | virtqueue_kick(vq->vq); | 175 | if (unlikely(!virtqueue_kick(vq->vq)) |
176 | r = -1; | ||
175 | } | 177 | } |
176 | } else | 178 | } else |
177 | r = -1; | 179 | r = -1; |
diff --git a/tools/virtio/vringh_test.c b/tools/virtio/vringh_test.c index d053ea40c001..14a4f4cab5b9 100644 --- a/tools/virtio/vringh_test.c +++ b/tools/virtio/vringh_test.c | |||
@@ -22,7 +22,7 @@ static u64 user_addr_offset; | |||
22 | #define RINGSIZE 256 | 22 | #define RINGSIZE 256 |
23 | #define ALIGN 4096 | 23 | #define ALIGN 4096 |
24 | 24 | ||
25 | static void never_notify_host(struct virtqueue *vq) | 25 | static bool never_notify_host(struct virtqueue *vq) |
26 | { | 26 | { |
27 | abort(); | 27 | abort(); |
28 | } | 28 | } |
@@ -65,17 +65,22 @@ struct guest_virtio_device { | |||
65 | unsigned long notifies; | 65 | unsigned long notifies; |
66 | }; | 66 | }; |
67 | 67 | ||
68 | static void parallel_notify_host(struct virtqueue *vq) | 68 | static bool parallel_notify_host(struct virtqueue *vq) |
69 | { | 69 | { |
70 | int rc; | ||
70 | struct guest_virtio_device *gvdev; | 71 | struct guest_virtio_device *gvdev; |
71 | 72 | ||
72 | gvdev = container_of(vq->vdev, struct guest_virtio_device, vdev); | 73 | gvdev = container_of(vq->vdev, struct guest_virtio_device, vdev); |
73 | write(gvdev->to_host_fd, "", 1); | 74 | rc = write(gvdev->to_host_fd, "", 1); |
75 | if (rc < 0) | ||
76 | return false; | ||
74 | gvdev->notifies++; | 77 | gvdev->notifies++; |
78 | return true; | ||
75 | } | 79 | } |
76 | 80 | ||
77 | static void no_notify_host(struct virtqueue *vq) | 81 | static bool no_notify_host(struct virtqueue *vq) |
78 | { | 82 | { |
83 | return true; | ||
79 | } | 84 | } |
80 | 85 | ||
81 | #define NUM_XFERS (10000000) | 86 | #define NUM_XFERS (10000000) |