diff options
author | Amit Shah <amit.shah@redhat.com> | 2011-12-22 06:28:30 -0500 |
---|---|---|
committer | Rusty Russell <rusty@rustcorp.com.au> | 2012-01-12 00:14:45 -0500 |
commit | f8fb5bc23a50a5398aa31a4e8c6dbbef53d2dec6 (patch) | |
tree | a8f466179ba3afdce265607703ed280231e04e3c /drivers | |
parent | 6abd6e5a4404056e28be04958a57d0286883161a (diff) |
virtio: blk: Add freeze, restore handlers to support S4
Delete the vq and flush any pending requests from the block queue on the
freeze callback to prepare for hibernation.
Re-create the vq in the restore callback to resume normal function.
Signed-off-by: Amit Shah <amit.shah@redhat.com>
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/block/virtio_blk.c | 44 |
1 files changed, 44 insertions, 0 deletions
diff --git a/drivers/block/virtio_blk.c b/drivers/block/virtio_blk.c index e8af52355bf5..ffd5ca919295 100644 --- a/drivers/block/virtio_blk.c +++ b/drivers/block/virtio_blk.c | |||
@@ -588,6 +588,46 @@ static void __devexit virtblk_remove(struct virtio_device *vdev) | |||
588 | ida_simple_remove(&vd_index_ida, index); | 588 | ida_simple_remove(&vd_index_ida, index); |
589 | } | 589 | } |
590 | 590 | ||
591 | #ifdef CONFIG_PM | ||
592 | static int virtblk_freeze(struct virtio_device *vdev) | ||
593 | { | ||
594 | struct virtio_blk *vblk = vdev->priv; | ||
595 | |||
596 | /* Ensure we don't receive any more interrupts */ | ||
597 | vdev->config->reset(vdev); | ||
598 | |||
599 | /* Prevent config work handler from accessing the device. */ | ||
600 | mutex_lock(&vblk->config_lock); | ||
601 | vblk->config_enable = false; | ||
602 | mutex_unlock(&vblk->config_lock); | ||
603 | |||
604 | flush_work(&vblk->config_work); | ||
605 | |||
606 | spin_lock_irq(vblk->disk->queue->queue_lock); | ||
607 | blk_stop_queue(vblk->disk->queue); | ||
608 | spin_unlock_irq(vblk->disk->queue->queue_lock); | ||
609 | blk_sync_queue(vblk->disk->queue); | ||
610 | |||
611 | vdev->config->del_vqs(vdev); | ||
612 | return 0; | ||
613 | } | ||
614 | |||
615 | static int virtblk_restore(struct virtio_device *vdev) | ||
616 | { | ||
617 | struct virtio_blk *vblk = vdev->priv; | ||
618 | int ret; | ||
619 | |||
620 | vblk->config_enable = true; | ||
621 | ret = init_vq(vdev->priv); | ||
622 | if (!ret) { | ||
623 | spin_lock_irq(vblk->disk->queue->queue_lock); | ||
624 | blk_start_queue(vblk->disk->queue); | ||
625 | spin_unlock_irq(vblk->disk->queue->queue_lock); | ||
626 | } | ||
627 | return ret; | ||
628 | } | ||
629 | #endif | ||
630 | |||
591 | static const struct virtio_device_id id_table[] = { | 631 | static const struct virtio_device_id id_table[] = { |
592 | { VIRTIO_ID_BLOCK, VIRTIO_DEV_ANY_ID }, | 632 | { VIRTIO_ID_BLOCK, VIRTIO_DEV_ANY_ID }, |
593 | { 0 }, | 633 | { 0 }, |
@@ -613,6 +653,10 @@ static struct virtio_driver __refdata virtio_blk = { | |||
613 | .probe = virtblk_probe, | 653 | .probe = virtblk_probe, |
614 | .remove = __devexit_p(virtblk_remove), | 654 | .remove = __devexit_p(virtblk_remove), |
615 | .config_changed = virtblk_config_changed, | 655 | .config_changed = virtblk_config_changed, |
656 | #ifdef CONFIG_PM | ||
657 | .freeze = virtblk_freeze, | ||
658 | .restore = virtblk_restore, | ||
659 | #endif | ||
616 | }; | 660 | }; |
617 | 661 | ||
618 | static int __init init(void) | 662 | static int __init init(void) |