aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2012-07-30 16:24:37 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2012-07-30 16:24:37 -0400
commit95b18e69950ca7fd9acfa55964e929f58bec9379 (patch)
tree5168f81b49cdfa2bcf363e4bd86cbfd669493ebd /drivers
parent6d8a97af63222c5cbc7fe63ae19345e74e153e90 (diff)
parent6a743897144500fb4c4566ced3a498d5180fbb5b (diff)
Merge tag 'virtio-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/rusty/linux-2.6-for-linus
Pull virtio update from Rusty Russell: "Virtio patches, mainly hotplugging fixes." * tag 'virtio-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/rusty/linux-2.6-for-linus: virtio-blk: return VIRTIO_BLK_F_FLUSH to header. virtio-blk: allow toggling host cache between writeback and writethrough virtio-blk: Use block layer provided spinlock virtio-blk: Reset device after blk_cleanup_queue() virtio-blk: Call del_gendisk() before disable guest kick virtio: rng: s3/s4 support virtio: rng: split out common code in probe / remove for s3/s4 ops virtio: rng: don't wait on host when module is going away virtio: rng: allow tasks to be killed that are waiting for rng input virtio ids: fix comment for virtio-rng
Diffstat (limited to 'drivers')
-rw-r--r--drivers/block/virtio_blk.c115
-rw-r--r--drivers/char/hw_random/virtio-rng.c37
2 files changed, 127 insertions, 25 deletions
diff --git a/drivers/block/virtio_blk.c b/drivers/block/virtio_blk.c
index 693187df7601..c0bbeb470754 100644
--- a/drivers/block/virtio_blk.c
+++ b/drivers/block/virtio_blk.c
@@ -21,8 +21,6 @@ struct workqueue_struct *virtblk_wq;
21 21
22struct virtio_blk 22struct virtio_blk
23{ 23{
24 spinlock_t lock;
25
26 struct virtio_device *vdev; 24 struct virtio_device *vdev;
27 struct virtqueue *vq; 25 struct virtqueue *vq;
28 26
@@ -65,7 +63,7 @@ static void blk_done(struct virtqueue *vq)
65 unsigned int len; 63 unsigned int len;
66 unsigned long flags; 64 unsigned long flags;
67 65
68 spin_lock_irqsave(&vblk->lock, flags); 66 spin_lock_irqsave(vblk->disk->queue->queue_lock, flags);
69 while ((vbr = virtqueue_get_buf(vblk->vq, &len)) != NULL) { 67 while ((vbr = virtqueue_get_buf(vblk->vq, &len)) != NULL) {
70 int error; 68 int error;
71 69
@@ -99,7 +97,7 @@ static void blk_done(struct virtqueue *vq)
99 } 97 }
100 /* In case queue is stopped waiting for more buffers. */ 98 /* In case queue is stopped waiting for more buffers. */
101 blk_start_queue(vblk->disk->queue); 99 blk_start_queue(vblk->disk->queue);
102 spin_unlock_irqrestore(&vblk->lock, flags); 100 spin_unlock_irqrestore(vblk->disk->queue->queue_lock, flags);
103} 101}
104 102
105static bool do_req(struct request_queue *q, struct virtio_blk *vblk, 103static bool do_req(struct request_queue *q, struct virtio_blk *vblk,
@@ -397,6 +395,83 @@ static int virtblk_name_format(char *prefix, int index, char *buf, int buflen)
397 return 0; 395 return 0;
398} 396}
399 397
398static int virtblk_get_cache_mode(struct virtio_device *vdev)
399{
400 u8 writeback;
401 int err;
402
403 err = virtio_config_val(vdev, VIRTIO_BLK_F_CONFIG_WCE,
404 offsetof(struct virtio_blk_config, wce),
405 &writeback);
406 if (err)
407 writeback = virtio_has_feature(vdev, VIRTIO_BLK_F_WCE);
408
409 return writeback;
410}
411
412static void virtblk_update_cache_mode(struct virtio_device *vdev)
413{
414 u8 writeback = virtblk_get_cache_mode(vdev);
415 struct virtio_blk *vblk = vdev->priv;
416
417 if (writeback)
418 blk_queue_flush(vblk->disk->queue, REQ_FLUSH);
419 else
420 blk_queue_flush(vblk->disk->queue, 0);
421
422 revalidate_disk(vblk->disk);
423}
424
425static const char *const virtblk_cache_types[] = {
426 "write through", "write back"
427};
428
429static ssize_t
430virtblk_cache_type_store(struct device *dev, struct device_attribute *attr,
431 const char *buf, size_t count)
432{
433 struct gendisk *disk = dev_to_disk(dev);
434 struct virtio_blk *vblk = disk->private_data;
435 struct virtio_device *vdev = vblk->vdev;
436 int i;
437 u8 writeback;
438
439 BUG_ON(!virtio_has_feature(vblk->vdev, VIRTIO_BLK_F_CONFIG_WCE));
440 for (i = ARRAY_SIZE(virtblk_cache_types); --i >= 0; )
441 if (sysfs_streq(buf, virtblk_cache_types[i]))
442 break;
443
444 if (i < 0)
445 return -EINVAL;
446
447 writeback = i;
448 vdev->config->set(vdev,
449 offsetof(struct virtio_blk_config, wce),
450 &writeback, sizeof(writeback));
451
452 virtblk_update_cache_mode(vdev);
453 return count;
454}
455
456static ssize_t
457virtblk_cache_type_show(struct device *dev, struct device_attribute *attr,
458 char *buf)
459{
460 struct gendisk *disk = dev_to_disk(dev);
461 struct virtio_blk *vblk = disk->private_data;
462 u8 writeback = virtblk_get_cache_mode(vblk->vdev);
463
464 BUG_ON(writeback >= ARRAY_SIZE(virtblk_cache_types));
465 return snprintf(buf, 40, "%s\n", virtblk_cache_types[writeback]);
466}
467
468static const struct device_attribute dev_attr_cache_type_ro =
469 __ATTR(cache_type, S_IRUGO,
470 virtblk_cache_type_show, NULL);
471static const struct device_attribute dev_attr_cache_type_rw =
472 __ATTR(cache_type, S_IRUGO|S_IWUSR,
473 virtblk_cache_type_show, virtblk_cache_type_store);
474
400static int __devinit virtblk_probe(struct virtio_device *vdev) 475static int __devinit virtblk_probe(struct virtio_device *vdev)
401{ 476{
402 struct virtio_blk *vblk; 477 struct virtio_blk *vblk;
@@ -431,7 +506,6 @@ static int __devinit virtblk_probe(struct virtio_device *vdev)
431 goto out_free_index; 506 goto out_free_index;
432 } 507 }
433 508
434 spin_lock_init(&vblk->lock);
435 vblk->vdev = vdev; 509 vblk->vdev = vdev;
436 vblk->sg_elems = sg_elems; 510 vblk->sg_elems = sg_elems;
437 sg_init_table(vblk->sg, vblk->sg_elems); 511 sg_init_table(vblk->sg, vblk->sg_elems);
@@ -456,7 +530,7 @@ static int __devinit virtblk_probe(struct virtio_device *vdev)
456 goto out_mempool; 530 goto out_mempool;
457 } 531 }
458 532
459 q = vblk->disk->queue = blk_init_queue(do_virtblk_request, &vblk->lock); 533 q = vblk->disk->queue = blk_init_queue(do_virtblk_request, NULL);
460 if (!q) { 534 if (!q) {
461 err = -ENOMEM; 535 err = -ENOMEM;
462 goto out_put_disk; 536 goto out_put_disk;
@@ -474,8 +548,7 @@ static int __devinit virtblk_probe(struct virtio_device *vdev)
474 vblk->index = index; 548 vblk->index = index;
475 549
476 /* configure queue flush support */ 550 /* configure queue flush support */
477 if (virtio_has_feature(vdev, VIRTIO_BLK_F_FLUSH)) 551 virtblk_update_cache_mode(vdev);
478 blk_queue_flush(q, REQ_FLUSH);
479 552
480 /* If disk is read-only in the host, the guest should obey */ 553 /* If disk is read-only in the host, the guest should obey */
481 if (virtio_has_feature(vdev, VIRTIO_BLK_F_RO)) 554 if (virtio_has_feature(vdev, VIRTIO_BLK_F_RO))
@@ -553,6 +626,14 @@ static int __devinit virtblk_probe(struct virtio_device *vdev)
553 if (err) 626 if (err)
554 goto out_del_disk; 627 goto out_del_disk;
555 628
629 if (virtio_has_feature(vdev, VIRTIO_BLK_F_CONFIG_WCE))
630 err = device_create_file(disk_to_dev(vblk->disk),
631 &dev_attr_cache_type_rw);
632 else
633 err = device_create_file(disk_to_dev(vblk->disk),
634 &dev_attr_cache_type_ro);
635 if (err)
636 goto out_del_disk;
556 return 0; 637 return 0;
557 638
558out_del_disk: 639out_del_disk:
@@ -576,30 +657,20 @@ static void __devexit virtblk_remove(struct virtio_device *vdev)
576{ 657{
577 struct virtio_blk *vblk = vdev->priv; 658 struct virtio_blk *vblk = vdev->priv;
578 int index = vblk->index; 659 int index = vblk->index;
579 struct virtblk_req *vbr;
580 unsigned long flags;
581 660
582 /* Prevent config work handler from accessing the device. */ 661 /* Prevent config work handler from accessing the device. */
583 mutex_lock(&vblk->config_lock); 662 mutex_lock(&vblk->config_lock);
584 vblk->config_enable = false; 663 vblk->config_enable = false;
585 mutex_unlock(&vblk->config_lock); 664 mutex_unlock(&vblk->config_lock);
586 665
666 del_gendisk(vblk->disk);
667 blk_cleanup_queue(vblk->disk->queue);
668
587 /* Stop all the virtqueues. */ 669 /* Stop all the virtqueues. */
588 vdev->config->reset(vdev); 670 vdev->config->reset(vdev);
589 671
590 flush_work(&vblk->config_work); 672 flush_work(&vblk->config_work);
591 673
592 del_gendisk(vblk->disk);
593
594 /* Abort requests dispatched to driver. */
595 spin_lock_irqsave(&vblk->lock, flags);
596 while ((vbr = virtqueue_detach_unused_buf(vblk->vq))) {
597 __blk_end_request_all(vbr->req, -EIO);
598 mempool_free(vbr, vblk->pool);
599 }
600 spin_unlock_irqrestore(&vblk->lock, flags);
601
602 blk_cleanup_queue(vblk->disk->queue);
603 put_disk(vblk->disk); 674 put_disk(vblk->disk);
604 mempool_destroy(vblk->pool); 675 mempool_destroy(vblk->pool);
605 vdev->config->del_vqs(vdev); 676 vdev->config->del_vqs(vdev);
@@ -655,7 +726,7 @@ static const struct virtio_device_id id_table[] = {
655static unsigned int features[] = { 726static unsigned int features[] = {
656 VIRTIO_BLK_F_SEG_MAX, VIRTIO_BLK_F_SIZE_MAX, VIRTIO_BLK_F_GEOMETRY, 727 VIRTIO_BLK_F_SEG_MAX, VIRTIO_BLK_F_SIZE_MAX, VIRTIO_BLK_F_GEOMETRY,
657 VIRTIO_BLK_F_RO, VIRTIO_BLK_F_BLK_SIZE, VIRTIO_BLK_F_SCSI, 728 VIRTIO_BLK_F_RO, VIRTIO_BLK_F_BLK_SIZE, VIRTIO_BLK_F_SCSI,
658 VIRTIO_BLK_F_FLUSH, VIRTIO_BLK_F_TOPOLOGY 729 VIRTIO_BLK_F_WCE, VIRTIO_BLK_F_TOPOLOGY, VIRTIO_BLK_F_CONFIG_WCE
659}; 730};
660 731
661/* 732/*
diff --git a/drivers/char/hw_random/virtio-rng.c b/drivers/char/hw_random/virtio-rng.c
index 723725bbb96b..5708299507d0 100644
--- a/drivers/char/hw_random/virtio-rng.c
+++ b/drivers/char/hw_random/virtio-rng.c
@@ -55,6 +55,7 @@ static void register_buffer(u8 *buf, size_t size)
55 55
56static int virtio_read(struct hwrng *rng, void *buf, size_t size, bool wait) 56static int virtio_read(struct hwrng *rng, void *buf, size_t size, bool wait)
57{ 57{
58 int ret;
58 59
59 if (!busy) { 60 if (!busy) {
60 busy = true; 61 busy = true;
@@ -65,7 +66,9 @@ static int virtio_read(struct hwrng *rng, void *buf, size_t size, bool wait)
65 if (!wait) 66 if (!wait)
66 return 0; 67 return 0;
67 68
68 wait_for_completion(&have_data); 69 ret = wait_for_completion_killable(&have_data);
70 if (ret < 0)
71 return ret;
69 72
70 busy = false; 73 busy = false;
71 74
@@ -85,7 +88,7 @@ static struct hwrng virtio_hwrng = {
85 .read = virtio_read, 88 .read = virtio_read,
86}; 89};
87 90
88static int virtrng_probe(struct virtio_device *vdev) 91static int probe_common(struct virtio_device *vdev)
89{ 92{
90 int err; 93 int err;
91 94
@@ -103,13 +106,37 @@ static int virtrng_probe(struct virtio_device *vdev)
103 return 0; 106 return 0;
104} 107}
105 108
106static void __devexit virtrng_remove(struct virtio_device *vdev) 109static void remove_common(struct virtio_device *vdev)
107{ 110{
108 vdev->config->reset(vdev); 111 vdev->config->reset(vdev);
112 busy = false;
109 hwrng_unregister(&virtio_hwrng); 113 hwrng_unregister(&virtio_hwrng);
110 vdev->config->del_vqs(vdev); 114 vdev->config->del_vqs(vdev);
111} 115}
112 116
117static int virtrng_probe(struct virtio_device *vdev)
118{
119 return probe_common(vdev);
120}
121
122static void __devexit virtrng_remove(struct virtio_device *vdev)
123{
124 remove_common(vdev);
125}
126
127#ifdef CONFIG_PM
128static int virtrng_freeze(struct virtio_device *vdev)
129{
130 remove_common(vdev);
131 return 0;
132}
133
134static int virtrng_restore(struct virtio_device *vdev)
135{
136 return probe_common(vdev);
137}
138#endif
139
113static struct virtio_device_id id_table[] = { 140static struct virtio_device_id id_table[] = {
114 { VIRTIO_ID_RNG, VIRTIO_DEV_ANY_ID }, 141 { VIRTIO_ID_RNG, VIRTIO_DEV_ANY_ID },
115 { 0 }, 142 { 0 },
@@ -121,6 +148,10 @@ static struct virtio_driver virtio_rng_driver = {
121 .id_table = id_table, 148 .id_table = id_table,
122 .probe = virtrng_probe, 149 .probe = virtrng_probe,
123 .remove = __devexit_p(virtrng_remove), 150 .remove = __devexit_p(virtrng_remove),
151#ifdef CONFIG_PM
152 .freeze = virtrng_freeze,
153 .restore = virtrng_restore,
154#endif
124}; 155};
125 156
126static int __init init(void) 157static int __init init(void)