aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/virtio
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2014-10-18 13:25:09 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2014-10-18 13:25:09 -0400
commit0e6e58f941176033fd9a224b39527b12f9cbb05e (patch)
tree0095a8bb546ff788ea451f272165f50c8df5e20f /drivers/virtio
parent50edb5cc22c7b2ea7df095913596e5a649bd6b41 (diff)
parent1bbc26062754b012656d34103215f7552e02b999 (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: "One cc: stable commit, the rest are a series of minor cleanups which have been sitting in MST's tree during my vacation. I changed a function name and made one trivial change, then they spent two days in linux-next" * tag 'virtio-next-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/rusty/linux: (25 commits) virtio-rng: refactor probe error handling virtio_scsi: drop scan callback virtio_balloon: enable VQs early on restore virtio_scsi: fix race on device removal virito_scsi: use freezable WQ for events virtio_net: enable VQs early on restore virtio_console: enable VQs early on restore virtio_scsi: enable VQs early on restore virtio_blk: enable VQs early on restore virtio_scsi: move kick event out from virtscsi_init virtio_net: fix use after free on allocation failure 9p/trans_virtio: enable VQs early virtio_console: enable VQs early virtio_blk: enable VQs early virtio_net: enable VQs early virtio: add API to enable VQs early virtio_net: minor cleanup virtio-net: drop config_mutex virtio_net: drop config_enable virtio-blk: drop config_mutex ...
Diffstat (limited to 'drivers/virtio')
-rw-r--r--drivers/virtio/virtio.c103
-rw-r--r--drivers/virtio/virtio_balloon.c2
-rw-r--r--drivers/virtio/virtio_mmio.c7
-rw-r--r--drivers/virtio/virtio_pci.c33
4 files changed, 110 insertions, 35 deletions
diff --git a/drivers/virtio/virtio.c b/drivers/virtio/virtio.c
index fed0ce198ae3..df598dd8c5c8 100644
--- a/drivers/virtio/virtio.c
+++ b/drivers/virtio/virtio.c
@@ -117,6 +117,43 @@ void virtio_check_driver_offered_feature(const struct virtio_device *vdev,
117} 117}
118EXPORT_SYMBOL_GPL(virtio_check_driver_offered_feature); 118EXPORT_SYMBOL_GPL(virtio_check_driver_offered_feature);
119 119
120static void __virtio_config_changed(struct virtio_device *dev)
121{
122 struct virtio_driver *drv = drv_to_virtio(dev->dev.driver);
123
124 if (!dev->config_enabled)
125 dev->config_change_pending = true;
126 else if (drv && drv->config_changed)
127 drv->config_changed(dev);
128}
129
130void virtio_config_changed(struct virtio_device *dev)
131{
132 unsigned long flags;
133
134 spin_lock_irqsave(&dev->config_lock, flags);
135 __virtio_config_changed(dev);
136 spin_unlock_irqrestore(&dev->config_lock, flags);
137}
138EXPORT_SYMBOL_GPL(virtio_config_changed);
139
140static void virtio_config_disable(struct virtio_device *dev)
141{
142 spin_lock_irq(&dev->config_lock);
143 dev->config_enabled = false;
144 spin_unlock_irq(&dev->config_lock);
145}
146
147static void virtio_config_enable(struct virtio_device *dev)
148{
149 spin_lock_irq(&dev->config_lock);
150 dev->config_enabled = true;
151 if (dev->config_change_pending)
152 __virtio_config_changed(dev);
153 dev->config_change_pending = false;
154 spin_unlock_irq(&dev->config_lock);
155}
156
120static int virtio_dev_probe(struct device *_d) 157static int virtio_dev_probe(struct device *_d)
121{ 158{
122 int err, i; 159 int err, i;
@@ -153,6 +190,8 @@ static int virtio_dev_probe(struct device *_d)
153 add_status(dev, VIRTIO_CONFIG_S_DRIVER_OK); 190 add_status(dev, VIRTIO_CONFIG_S_DRIVER_OK);
154 if (drv->scan) 191 if (drv->scan)
155 drv->scan(dev); 192 drv->scan(dev);
193
194 virtio_config_enable(dev);
156 } 195 }
157 196
158 return err; 197 return err;
@@ -163,6 +202,8 @@ static int virtio_dev_remove(struct device *_d)
163 struct virtio_device *dev = dev_to_virtio(_d); 202 struct virtio_device *dev = dev_to_virtio(_d);
164 struct virtio_driver *drv = drv_to_virtio(dev->dev.driver); 203 struct virtio_driver *drv = drv_to_virtio(dev->dev.driver);
165 204
205 virtio_config_disable(dev);
206
166 drv->remove(dev); 207 drv->remove(dev);
167 208
168 /* Driver should have reset device. */ 209 /* Driver should have reset device. */
@@ -211,6 +252,10 @@ int register_virtio_device(struct virtio_device *dev)
211 dev->index = err; 252 dev->index = err;
212 dev_set_name(&dev->dev, "virtio%u", dev->index); 253 dev_set_name(&dev->dev, "virtio%u", dev->index);
213 254
255 spin_lock_init(&dev->config_lock);
256 dev->config_enabled = false;
257 dev->config_change_pending = false;
258
214 /* We always start by resetting the device, in case a previous 259 /* We always start by resetting the device, in case a previous
215 * driver messed it up. This also tests that code path a little. */ 260 * driver messed it up. This also tests that code path a little. */
216 dev->config->reset(dev); 261 dev->config->reset(dev);
@@ -239,6 +284,64 @@ void unregister_virtio_device(struct virtio_device *dev)
239} 284}
240EXPORT_SYMBOL_GPL(unregister_virtio_device); 285EXPORT_SYMBOL_GPL(unregister_virtio_device);
241 286
287#ifdef CONFIG_PM_SLEEP
288int virtio_device_freeze(struct virtio_device *dev)
289{
290 struct virtio_driver *drv = drv_to_virtio(dev->dev.driver);
291
292 virtio_config_disable(dev);
293
294 dev->failed = dev->config->get_status(dev) & VIRTIO_CONFIG_S_FAILED;
295
296 if (drv && drv->freeze)
297 return drv->freeze(dev);
298
299 return 0;
300}
301EXPORT_SYMBOL_GPL(virtio_device_freeze);
302
303int virtio_device_restore(struct virtio_device *dev)
304{
305 struct virtio_driver *drv = drv_to_virtio(dev->dev.driver);
306
307 /* We always start by resetting the device, in case a previous
308 * driver messed it up. */
309 dev->config->reset(dev);
310
311 /* Acknowledge that we've seen the device. */
312 add_status(dev, VIRTIO_CONFIG_S_ACKNOWLEDGE);
313
314 /* Maybe driver failed before freeze.
315 * Restore the failed status, for debugging. */
316 if (dev->failed)
317 add_status(dev, VIRTIO_CONFIG_S_FAILED);
318
319 if (!drv)
320 return 0;
321
322 /* We have a driver! */
323 add_status(dev, VIRTIO_CONFIG_S_DRIVER);
324
325 dev->config->finalize_features(dev);
326
327 if (drv->restore) {
328 int ret = drv->restore(dev);
329 if (ret) {
330 add_status(dev, VIRTIO_CONFIG_S_FAILED);
331 return ret;
332 }
333 }
334
335 /* Finally, tell the device we're all set */
336 add_status(dev, VIRTIO_CONFIG_S_DRIVER_OK);
337
338 virtio_config_enable(dev);
339
340 return 0;
341}
342EXPORT_SYMBOL_GPL(virtio_device_restore);
343#endif
344
242static int virtio_init(void) 345static int virtio_init(void)
243{ 346{
244 if (bus_register(&virtio_bus) != 0) 347 if (bus_register(&virtio_bus) != 0)
diff --git a/drivers/virtio/virtio_balloon.c b/drivers/virtio/virtio_balloon.c
index f893148a107b..c9703d4d6f67 100644
--- a/drivers/virtio/virtio_balloon.c
+++ b/drivers/virtio/virtio_balloon.c
@@ -504,6 +504,8 @@ static int virtballoon_restore(struct virtio_device *vdev)
504 if (ret) 504 if (ret)
505 return ret; 505 return ret;
506 506
507 virtio_device_ready(vdev);
508
507 fill_balloon(vb, towards_target(vb)); 509 fill_balloon(vb, towards_target(vb));
508 update_balloon_size(vb); 510 update_balloon_size(vb);
509 return 0; 511 return 0;
diff --git a/drivers/virtio/virtio_mmio.c b/drivers/virtio/virtio_mmio.c
index c600ccfd6922..ef9a1650bb80 100644
--- a/drivers/virtio/virtio_mmio.c
+++ b/drivers/virtio/virtio_mmio.c
@@ -234,8 +234,6 @@ static irqreturn_t vm_interrupt(int irq, void *opaque)
234{ 234{
235 struct virtio_mmio_device *vm_dev = opaque; 235 struct virtio_mmio_device *vm_dev = opaque;
236 struct virtio_mmio_vq_info *info; 236 struct virtio_mmio_vq_info *info;
237 struct virtio_driver *vdrv = container_of(vm_dev->vdev.dev.driver,
238 struct virtio_driver, driver);
239 unsigned long status; 237 unsigned long status;
240 unsigned long flags; 238 unsigned long flags;
241 irqreturn_t ret = IRQ_NONE; 239 irqreturn_t ret = IRQ_NONE;
@@ -244,9 +242,8 @@ static irqreturn_t vm_interrupt(int irq, void *opaque)
244 status = readl(vm_dev->base + VIRTIO_MMIO_INTERRUPT_STATUS); 242 status = readl(vm_dev->base + VIRTIO_MMIO_INTERRUPT_STATUS);
245 writel(status, vm_dev->base + VIRTIO_MMIO_INTERRUPT_ACK); 243 writel(status, vm_dev->base + VIRTIO_MMIO_INTERRUPT_ACK);
246 244
247 if (unlikely(status & VIRTIO_MMIO_INT_CONFIG) 245 if (unlikely(status & VIRTIO_MMIO_INT_CONFIG)) {
248 && vdrv && vdrv->config_changed) { 246 virtio_config_changed(&vm_dev->vdev);
249 vdrv->config_changed(&vm_dev->vdev);
250 ret = IRQ_HANDLED; 247 ret = IRQ_HANDLED;
251 } 248 }
252 249
diff --git a/drivers/virtio/virtio_pci.c b/drivers/virtio/virtio_pci.c
index 3d1463c6b120..d34ebfa604f3 100644
--- a/drivers/virtio/virtio_pci.c
+++ b/drivers/virtio/virtio_pci.c
@@ -57,9 +57,6 @@ struct virtio_pci_device
57 /* Vectors allocated, excluding per-vq vectors if any */ 57 /* Vectors allocated, excluding per-vq vectors if any */
58 unsigned msix_used_vectors; 58 unsigned msix_used_vectors;
59 59
60 /* Status saved during hibernate/restore */
61 u8 saved_status;
62
63 /* Whether we have vector per vq */ 60 /* Whether we have vector per vq */
64 bool per_vq_vectors; 61 bool per_vq_vectors;
65}; 62};
@@ -211,12 +208,8 @@ static bool vp_notify(struct virtqueue *vq)
211static irqreturn_t vp_config_changed(int irq, void *opaque) 208static irqreturn_t vp_config_changed(int irq, void *opaque)
212{ 209{
213 struct virtio_pci_device *vp_dev = opaque; 210 struct virtio_pci_device *vp_dev = opaque;
214 struct virtio_driver *drv;
215 drv = container_of(vp_dev->vdev.dev.driver,
216 struct virtio_driver, driver);
217 211
218 if (drv && drv->config_changed) 212 virtio_config_changed(&vp_dev->vdev);
219 drv->config_changed(&vp_dev->vdev);
220 return IRQ_HANDLED; 213 return IRQ_HANDLED;
221} 214}
222 215
@@ -768,16 +761,9 @@ static int virtio_pci_freeze(struct device *dev)
768{ 761{
769 struct pci_dev *pci_dev = to_pci_dev(dev); 762 struct pci_dev *pci_dev = to_pci_dev(dev);
770 struct virtio_pci_device *vp_dev = pci_get_drvdata(pci_dev); 763 struct virtio_pci_device *vp_dev = pci_get_drvdata(pci_dev);
771 struct virtio_driver *drv;
772 int ret; 764 int ret;
773 765
774 drv = container_of(vp_dev->vdev.dev.driver, 766 ret = virtio_device_freeze(&vp_dev->vdev);
775 struct virtio_driver, driver);
776
777 ret = 0;
778 vp_dev->saved_status = vp_get_status(&vp_dev->vdev);
779 if (drv && drv->freeze)
780 ret = drv->freeze(&vp_dev->vdev);
781 767
782 if (!ret) 768 if (!ret)
783 pci_disable_device(pci_dev); 769 pci_disable_device(pci_dev);
@@ -788,27 +774,14 @@ static int virtio_pci_restore(struct device *dev)
788{ 774{
789 struct pci_dev *pci_dev = to_pci_dev(dev); 775 struct pci_dev *pci_dev = to_pci_dev(dev);
790 struct virtio_pci_device *vp_dev = pci_get_drvdata(pci_dev); 776 struct virtio_pci_device *vp_dev = pci_get_drvdata(pci_dev);
791 struct virtio_driver *drv;
792 int ret; 777 int ret;
793 778
794 drv = container_of(vp_dev->vdev.dev.driver,
795 struct virtio_driver, driver);
796
797 ret = pci_enable_device(pci_dev); 779 ret = pci_enable_device(pci_dev);
798 if (ret) 780 if (ret)
799 return ret; 781 return ret;
800 782
801 pci_set_master(pci_dev); 783 pci_set_master(pci_dev);
802 vp_finalize_features(&vp_dev->vdev); 784 return virtio_device_restore(&vp_dev->vdev);
803
804 if (drv && drv->restore)
805 ret = drv->restore(&vp_dev->vdev);
806
807 /* Finally, tell the device we're all set */
808 if (!ret)
809 vp_set_status(&vp_dev->vdev, vp_dev->saved_status);
810
811 return ret;
812} 785}
813 786
814static const struct dev_pm_ops virtio_pci_pm_ops = { 787static const struct dev_pm_ops virtio_pci_pm_ops = {