diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2014-06-12 00:10:33 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-06-12 00:10:33 -0400 |
commit | 5c02c392cd2320e8d612376d6b72b6548a680923 (patch) | |
tree | 56615b31e21b34414821564cd9bf4c13d7e5d14e | |
parent | 3c81bdd9e7ec5c7e28bedf7c7bd3b8911ffee94a (diff) | |
parent | c77fba9ab058d1e96ed51d4215e56905c9ef8d2a (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:
"Main excitement is a virtio_scsi fix for alloc holding spinlock on the
abort path, which I refuse to CC stable since (1) I discovered it
myself, and (2) it's been there forever with no reports"
* tag 'virtio-next-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/rusty/linux:
virtio_scsi: don't call virtqueue_add_sgs(... GFP_NOIO) holding spinlock.
virtio-rng: fixes for device registration/unregistration
virtio-rng: fix boot with virtio-rng device
virtio-rng: support multiple virtio-rng devices
virtio_ccw: introduce device_lost in virtio_ccw_device
virtio: virtio_break_device() to mark all virtqueues broken.
-rw-r--r-- | drivers/char/hw_random/virtio-rng.c | 105 | ||||
-rw-r--r-- | drivers/s390/kvm/virtio_ccw.c | 49 | ||||
-rw-r--r-- | drivers/scsi/virtio_scsi.c | 15 | ||||
-rw-r--r-- | drivers/virtio/virtio_ring.c | 15 | ||||
-rw-r--r-- | include/linux/virtio.h | 2 |
5 files changed, 127 insertions, 59 deletions
diff --git a/drivers/char/hw_random/virtio-rng.c b/drivers/char/hw_random/virtio-rng.c index 2ce0e225e58c..f3e71501de54 100644 --- a/drivers/char/hw_random/virtio-rng.c +++ b/drivers/char/hw_random/virtio-rng.c | |||
@@ -25,88 +25,115 @@ | |||
25 | #include <linux/virtio_rng.h> | 25 | #include <linux/virtio_rng.h> |
26 | #include <linux/module.h> | 26 | #include <linux/module.h> |
27 | 27 | ||
28 | static struct virtqueue *vq; | 28 | static DEFINE_IDA(rng_index_ida); |
29 | static unsigned int data_avail; | 29 | |
30 | static DECLARE_COMPLETION(have_data); | 30 | struct virtrng_info { |
31 | static bool busy; | 31 | struct virtio_device *vdev; |
32 | struct hwrng hwrng; | ||
33 | struct virtqueue *vq; | ||
34 | unsigned int data_avail; | ||
35 | struct completion have_data; | ||
36 | bool busy; | ||
37 | char name[25]; | ||
38 | int index; | ||
39 | }; | ||
32 | 40 | ||
33 | static void random_recv_done(struct virtqueue *vq) | 41 | static void random_recv_done(struct virtqueue *vq) |
34 | { | 42 | { |
43 | struct virtrng_info *vi = vq->vdev->priv; | ||
44 | |||
35 | /* We can get spurious callbacks, e.g. shared IRQs + virtio_pci. */ | 45 | /* We can get spurious callbacks, e.g. shared IRQs + virtio_pci. */ |
36 | if (!virtqueue_get_buf(vq, &data_avail)) | 46 | if (!virtqueue_get_buf(vi->vq, &vi->data_avail)) |
37 | return; | 47 | return; |
38 | 48 | ||
39 | complete(&have_data); | 49 | complete(&vi->have_data); |
40 | } | 50 | } |
41 | 51 | ||
42 | /* The host will fill any buffer we give it with sweet, sweet randomness. */ | 52 | /* The host will fill any buffer we give it with sweet, sweet randomness. */ |
43 | static void register_buffer(u8 *buf, size_t size) | 53 | static void register_buffer(struct virtrng_info *vi, u8 *buf, size_t size) |
44 | { | 54 | { |
45 | struct scatterlist sg; | 55 | struct scatterlist sg; |
46 | 56 | ||
47 | sg_init_one(&sg, buf, size); | 57 | sg_init_one(&sg, buf, size); |
48 | 58 | ||
49 | /* There should always be room for one buffer. */ | 59 | /* There should always be room for one buffer. */ |
50 | virtqueue_add_inbuf(vq, &sg, 1, buf, GFP_KERNEL); | 60 | virtqueue_add_inbuf(vi->vq, &sg, 1, buf, GFP_KERNEL); |
51 | 61 | ||
52 | virtqueue_kick(vq); | 62 | virtqueue_kick(vi->vq); |
53 | } | 63 | } |
54 | 64 | ||
55 | static int virtio_read(struct hwrng *rng, void *buf, size_t size, bool wait) | 65 | static int virtio_read(struct hwrng *rng, void *buf, size_t size, bool wait) |
56 | { | 66 | { |
57 | int ret; | 67 | int ret; |
68 | struct virtrng_info *vi = (struct virtrng_info *)rng->priv; | ||
58 | 69 | ||
59 | if (!busy) { | 70 | if (!vi->busy) { |
60 | busy = true; | 71 | vi->busy = true; |
61 | init_completion(&have_data); | 72 | init_completion(&vi->have_data); |
62 | register_buffer(buf, size); | 73 | register_buffer(vi, buf, size); |
63 | } | 74 | } |
64 | 75 | ||
65 | if (!wait) | 76 | if (!wait) |
66 | return 0; | 77 | return 0; |
67 | 78 | ||
68 | ret = wait_for_completion_killable(&have_data); | 79 | ret = wait_for_completion_killable(&vi->have_data); |
69 | if (ret < 0) | 80 | if (ret < 0) |
70 | return ret; | 81 | return ret; |
71 | 82 | ||
72 | busy = false; | 83 | vi->busy = false; |
73 | 84 | ||
74 | return data_avail; | 85 | return vi->data_avail; |
75 | } | 86 | } |
76 | 87 | ||
77 | static void virtio_cleanup(struct hwrng *rng) | 88 | static void virtio_cleanup(struct hwrng *rng) |
78 | { | 89 | { |
79 | if (busy) | 90 | struct virtrng_info *vi = (struct virtrng_info *)rng->priv; |
80 | wait_for_completion(&have_data); | ||
81 | } | ||
82 | 91 | ||
83 | 92 | if (vi->busy) | |
84 | static struct hwrng virtio_hwrng = { | 93 | wait_for_completion(&vi->have_data); |
85 | .name = "virtio", | 94 | } |
86 | .cleanup = virtio_cleanup, | ||
87 | .read = virtio_read, | ||
88 | }; | ||
89 | 95 | ||
90 | static int probe_common(struct virtio_device *vdev) | 96 | static int probe_common(struct virtio_device *vdev) |
91 | { | 97 | { |
92 | int err; | 98 | int err, index; |
99 | struct virtrng_info *vi = NULL; | ||
100 | |||
101 | vi = kzalloc(sizeof(struct virtrng_info), GFP_KERNEL); | ||
102 | if (!vi) | ||
103 | return -ENOMEM; | ||
93 | 104 | ||
94 | if (vq) { | 105 | vi->index = index = ida_simple_get(&rng_index_ida, 0, 0, GFP_KERNEL); |
95 | /* We only support one device for now */ | 106 | if (index < 0) { |
96 | return -EBUSY; | 107 | kfree(vi); |
108 | return index; | ||
97 | } | 109 | } |
110 | sprintf(vi->name, "virtio_rng.%d", index); | ||
111 | init_completion(&vi->have_data); | ||
112 | |||
113 | vi->hwrng = (struct hwrng) { | ||
114 | .read = virtio_read, | ||
115 | .cleanup = virtio_cleanup, | ||
116 | .priv = (unsigned long)vi, | ||
117 | .name = vi->name, | ||
118 | }; | ||
119 | vdev->priv = vi; | ||
120 | |||
98 | /* We expect a single virtqueue. */ | 121 | /* We expect a single virtqueue. */ |
99 | vq = virtio_find_single_vq(vdev, random_recv_done, "input"); | 122 | vi->vq = virtio_find_single_vq(vdev, random_recv_done, "input"); |
100 | if (IS_ERR(vq)) { | 123 | if (IS_ERR(vi->vq)) { |
101 | err = PTR_ERR(vq); | 124 | err = PTR_ERR(vi->vq); |
102 | vq = NULL; | 125 | vi->vq = NULL; |
126 | kfree(vi); | ||
127 | ida_simple_remove(&rng_index_ida, index); | ||
103 | return err; | 128 | return err; |
104 | } | 129 | } |
105 | 130 | ||
106 | err = hwrng_register(&virtio_hwrng); | 131 | err = hwrng_register(&vi->hwrng); |
107 | if (err) { | 132 | if (err) { |
108 | vdev->config->del_vqs(vdev); | 133 | vdev->config->del_vqs(vdev); |
109 | vq = NULL; | 134 | vi->vq = NULL; |
135 | kfree(vi); | ||
136 | ida_simple_remove(&rng_index_ida, index); | ||
110 | return err; | 137 | return err; |
111 | } | 138 | } |
112 | 139 | ||
@@ -115,11 +142,13 @@ static int probe_common(struct virtio_device *vdev) | |||
115 | 142 | ||
116 | static void remove_common(struct virtio_device *vdev) | 143 | static void remove_common(struct virtio_device *vdev) |
117 | { | 144 | { |
145 | struct virtrng_info *vi = vdev->priv; | ||
118 | vdev->config->reset(vdev); | 146 | vdev->config->reset(vdev); |
119 | busy = false; | 147 | vi->busy = false; |
120 | hwrng_unregister(&virtio_hwrng); | 148 | hwrng_unregister(&vi->hwrng); |
121 | vdev->config->del_vqs(vdev); | 149 | vdev->config->del_vqs(vdev); |
122 | vq = NULL; | 150 | ida_simple_remove(&rng_index_ida, vi->index); |
151 | kfree(vi); | ||
123 | } | 152 | } |
124 | 153 | ||
125 | static int virtrng_probe(struct virtio_device *vdev) | 154 | static int virtrng_probe(struct virtio_device *vdev) |
diff --git a/drivers/s390/kvm/virtio_ccw.c b/drivers/s390/kvm/virtio_ccw.c index 1e1fc671f89a..d2c0b442bce5 100644 --- a/drivers/s390/kvm/virtio_ccw.c +++ b/drivers/s390/kvm/virtio_ccw.c | |||
@@ -27,6 +27,7 @@ | |||
27 | #include <linux/module.h> | 27 | #include <linux/module.h> |
28 | #include <linux/io.h> | 28 | #include <linux/io.h> |
29 | #include <linux/kvm_para.h> | 29 | #include <linux/kvm_para.h> |
30 | #include <linux/notifier.h> | ||
30 | #include <asm/setup.h> | 31 | #include <asm/setup.h> |
31 | #include <asm/irq.h> | 32 | #include <asm/irq.h> |
32 | #include <asm/cio.h> | 33 | #include <asm/cio.h> |
@@ -62,6 +63,7 @@ struct virtio_ccw_device { | |||
62 | struct vq_config_block *config_block; | 63 | struct vq_config_block *config_block; |
63 | bool is_thinint; | 64 | bool is_thinint; |
64 | bool going_away; | 65 | bool going_away; |
66 | bool device_lost; | ||
65 | void *airq_info; | 67 | void *airq_info; |
66 | }; | 68 | }; |
67 | 69 | ||
@@ -1010,11 +1012,14 @@ static void virtio_ccw_remove(struct ccw_device *cdev) | |||
1010 | unsigned long flags; | 1012 | unsigned long flags; |
1011 | struct virtio_ccw_device *vcdev = virtio_grab_drvdata(cdev); | 1013 | struct virtio_ccw_device *vcdev = virtio_grab_drvdata(cdev); |
1012 | 1014 | ||
1013 | if (vcdev && cdev->online) | 1015 | if (vcdev && cdev->online) { |
1016 | if (vcdev->device_lost) | ||
1017 | virtio_break_device(&vcdev->vdev); | ||
1014 | unregister_virtio_device(&vcdev->vdev); | 1018 | unregister_virtio_device(&vcdev->vdev); |
1015 | spin_lock_irqsave(get_ccwdev_lock(cdev), flags); | 1019 | spin_lock_irqsave(get_ccwdev_lock(cdev), flags); |
1016 | dev_set_drvdata(&cdev->dev, NULL); | 1020 | dev_set_drvdata(&cdev->dev, NULL); |
1017 | spin_unlock_irqrestore(get_ccwdev_lock(cdev), flags); | 1021 | spin_unlock_irqrestore(get_ccwdev_lock(cdev), flags); |
1022 | } | ||
1018 | cdev->handler = NULL; | 1023 | cdev->handler = NULL; |
1019 | } | 1024 | } |
1020 | 1025 | ||
@@ -1023,12 +1028,14 @@ static int virtio_ccw_offline(struct ccw_device *cdev) | |||
1023 | unsigned long flags; | 1028 | unsigned long flags; |
1024 | struct virtio_ccw_device *vcdev = virtio_grab_drvdata(cdev); | 1029 | struct virtio_ccw_device *vcdev = virtio_grab_drvdata(cdev); |
1025 | 1030 | ||
1026 | if (vcdev) { | 1031 | if (!vcdev) |
1027 | unregister_virtio_device(&vcdev->vdev); | 1032 | return 0; |
1028 | spin_lock_irqsave(get_ccwdev_lock(cdev), flags); | 1033 | if (vcdev->device_lost) |
1029 | dev_set_drvdata(&cdev->dev, NULL); | 1034 | virtio_break_device(&vcdev->vdev); |
1030 | spin_unlock_irqrestore(get_ccwdev_lock(cdev), flags); | 1035 | unregister_virtio_device(&vcdev->vdev); |
1031 | } | 1036 | spin_lock_irqsave(get_ccwdev_lock(cdev), flags); |
1037 | dev_set_drvdata(&cdev->dev, NULL); | ||
1038 | spin_unlock_irqrestore(get_ccwdev_lock(cdev), flags); | ||
1032 | return 0; | 1039 | return 0; |
1033 | } | 1040 | } |
1034 | 1041 | ||
@@ -1096,8 +1103,26 @@ out_free: | |||
1096 | 1103 | ||
1097 | static int virtio_ccw_cio_notify(struct ccw_device *cdev, int event) | 1104 | static int virtio_ccw_cio_notify(struct ccw_device *cdev, int event) |
1098 | { | 1105 | { |
1099 | /* TODO: Check whether we need special handling here. */ | 1106 | int rc; |
1100 | return 0; | 1107 | struct virtio_ccw_device *vcdev = dev_get_drvdata(&cdev->dev); |
1108 | |||
1109 | /* | ||
1110 | * Make sure vcdev is set | ||
1111 | * i.e. set_offline/remove callback not already running | ||
1112 | */ | ||
1113 | if (!vcdev) | ||
1114 | return NOTIFY_DONE; | ||
1115 | |||
1116 | switch (event) { | ||
1117 | case CIO_GONE: | ||
1118 | vcdev->device_lost = true; | ||
1119 | rc = NOTIFY_DONE; | ||
1120 | break; | ||
1121 | default: | ||
1122 | rc = NOTIFY_DONE; | ||
1123 | break; | ||
1124 | } | ||
1125 | return rc; | ||
1101 | } | 1126 | } |
1102 | 1127 | ||
1103 | static struct ccw_device_id virtio_ids[] = { | 1128 | static struct ccw_device_id virtio_ids[] = { |
diff --git a/drivers/scsi/virtio_scsi.c b/drivers/scsi/virtio_scsi.c index d4727b339474..99fdb9403944 100644 --- a/drivers/scsi/virtio_scsi.c +++ b/drivers/scsi/virtio_scsi.c | |||
@@ -393,11 +393,10 @@ static void virtscsi_event_done(struct virtqueue *vq) | |||
393 | * @cmd : command structure | 393 | * @cmd : command structure |
394 | * @req_size : size of the request buffer | 394 | * @req_size : size of the request buffer |
395 | * @resp_size : size of the response buffer | 395 | * @resp_size : size of the response buffer |
396 | * @gfp : flags to use for memory allocations | ||
397 | */ | 396 | */ |
398 | static int virtscsi_add_cmd(struct virtqueue *vq, | 397 | static int virtscsi_add_cmd(struct virtqueue *vq, |
399 | struct virtio_scsi_cmd *cmd, | 398 | struct virtio_scsi_cmd *cmd, |
400 | size_t req_size, size_t resp_size, gfp_t gfp) | 399 | size_t req_size, size_t resp_size) |
401 | { | 400 | { |
402 | struct scsi_cmnd *sc = cmd->sc; | 401 | struct scsi_cmnd *sc = cmd->sc; |
403 | struct scatterlist *sgs[4], req, resp; | 402 | struct scatterlist *sgs[4], req, resp; |
@@ -429,19 +428,19 @@ static int virtscsi_add_cmd(struct virtqueue *vq, | |||
429 | if (in) | 428 | if (in) |
430 | sgs[out_num + in_num++] = in->sgl; | 429 | sgs[out_num + in_num++] = in->sgl; |
431 | 430 | ||
432 | return virtqueue_add_sgs(vq, sgs, out_num, in_num, cmd, gfp); | 431 | return virtqueue_add_sgs(vq, sgs, out_num, in_num, cmd, GFP_ATOMIC); |
433 | } | 432 | } |
434 | 433 | ||
435 | static int virtscsi_kick_cmd(struct virtio_scsi_vq *vq, | 434 | static int virtscsi_kick_cmd(struct virtio_scsi_vq *vq, |
436 | struct virtio_scsi_cmd *cmd, | 435 | struct virtio_scsi_cmd *cmd, |
437 | size_t req_size, size_t resp_size, gfp_t gfp) | 436 | size_t req_size, size_t resp_size) |
438 | { | 437 | { |
439 | unsigned long flags; | 438 | unsigned long flags; |
440 | int err; | 439 | int err; |
441 | bool needs_kick = false; | 440 | bool needs_kick = false; |
442 | 441 | ||
443 | spin_lock_irqsave(&vq->vq_lock, flags); | 442 | spin_lock_irqsave(&vq->vq_lock, flags); |
444 | err = virtscsi_add_cmd(vq->vq, cmd, req_size, resp_size, gfp); | 443 | err = virtscsi_add_cmd(vq->vq, cmd, req_size, resp_size); |
445 | if (!err) | 444 | if (!err) |
446 | needs_kick = virtqueue_kick_prepare(vq->vq); | 445 | needs_kick = virtqueue_kick_prepare(vq->vq); |
447 | 446 | ||
@@ -484,8 +483,7 @@ static int virtscsi_queuecommand(struct virtio_scsi *vscsi, | |||
484 | memcpy(cmd->req.cmd.cdb, sc->cmnd, sc->cmd_len); | 483 | memcpy(cmd->req.cmd.cdb, sc->cmnd, sc->cmd_len); |
485 | 484 | ||
486 | if (virtscsi_kick_cmd(req_vq, cmd, | 485 | if (virtscsi_kick_cmd(req_vq, cmd, |
487 | sizeof cmd->req.cmd, sizeof cmd->resp.cmd, | 486 | sizeof cmd->req.cmd, sizeof cmd->resp.cmd) != 0) |
488 | GFP_ATOMIC) != 0) | ||
489 | return SCSI_MLQUEUE_HOST_BUSY; | 487 | return SCSI_MLQUEUE_HOST_BUSY; |
490 | return 0; | 488 | return 0; |
491 | } | 489 | } |
@@ -542,8 +540,7 @@ static int virtscsi_tmf(struct virtio_scsi *vscsi, struct virtio_scsi_cmd *cmd) | |||
542 | 540 | ||
543 | cmd->comp = ∁ | 541 | cmd->comp = ∁ |
544 | if (virtscsi_kick_cmd(&vscsi->ctrl_vq, cmd, | 542 | if (virtscsi_kick_cmd(&vscsi->ctrl_vq, cmd, |
545 | sizeof cmd->req.tmf, sizeof cmd->resp.tmf, | 543 | sizeof cmd->req.tmf, sizeof cmd->resp.tmf) < 0) |
546 | GFP_NOIO) < 0) | ||
547 | goto out; | 544 | goto out; |
548 | 545 | ||
549 | wait_for_completion(&comp); | 546 | wait_for_completion(&comp); |
diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c index 1e443629f76d..4d08f45a9c29 100644 --- a/drivers/virtio/virtio_ring.c +++ b/drivers/virtio/virtio_ring.c | |||
@@ -865,4 +865,19 @@ bool virtqueue_is_broken(struct virtqueue *_vq) | |||
865 | } | 865 | } |
866 | EXPORT_SYMBOL_GPL(virtqueue_is_broken); | 866 | EXPORT_SYMBOL_GPL(virtqueue_is_broken); |
867 | 867 | ||
868 | /* | ||
869 | * This should prevent the device from being used, allowing drivers to | ||
870 | * recover. You may need to grab appropriate locks to flush. | ||
871 | */ | ||
872 | void virtio_break_device(struct virtio_device *dev) | ||
873 | { | ||
874 | struct virtqueue *_vq; | ||
875 | |||
876 | list_for_each_entry(_vq, &dev->vqs, list) { | ||
877 | struct vring_virtqueue *vq = to_vvq(_vq); | ||
878 | vq->broken = true; | ||
879 | } | ||
880 | } | ||
881 | EXPORT_SYMBOL_GPL(virtio_break_device); | ||
882 | |||
868 | MODULE_LICENSE("GPL"); | 883 | MODULE_LICENSE("GPL"); |
diff --git a/include/linux/virtio.h b/include/linux/virtio.h index e4abb84199be..b46671e28de2 100644 --- a/include/linux/virtio.h +++ b/include/linux/virtio.h | |||
@@ -106,6 +106,8 @@ static inline struct virtio_device *dev_to_virtio(struct device *_dev) | |||
106 | int register_virtio_device(struct virtio_device *dev); | 106 | int register_virtio_device(struct virtio_device *dev); |
107 | void unregister_virtio_device(struct virtio_device *dev); | 107 | void unregister_virtio_device(struct virtio_device *dev); |
108 | 108 | ||
109 | void virtio_break_device(struct virtio_device *dev); | ||
110 | |||
109 | /** | 111 | /** |
110 | * virtio_driver - operations for a virtio I/O driver | 112 | * virtio_driver - operations for a virtio I/O driver |
111 | * @driver: underlying device driver (populate name and owner). | 113 | * @driver: underlying device driver (populate name and owner). |