diff options
| -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). |
