aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAmit Shah <amit.shah@redhat.com>2011-12-22 06:28:28 -0500
committerRusty Russell <rusty@rustcorp.com.au>2012-01-12 00:14:45 -0500
commit2b8f41d846990c3c1c8addbaed2cf53c3ef91d25 (patch)
treea3dbf456eb359650db0487d66d3594f1fa7be6c0
parenta0e2dbfc223028b72a1c193f94fcd3f67253ba4a (diff)
virtio: console: Add freeze and restore handlers to support S4
Remove all vqs and associated buffers in the freeze callback which prepares us to go into hibernation state. On restore, re-create all the vqs and populate the input vqs with buffers to get to the pre-hibernate state. Note: Any outstanding unconsumed buffers are discarded; which means there's a possibility of data loss in case the host or the guest didn't consume any data already present in the vqs. This can be addressed in a later patch series, perhaps in virtio common code. Signed-off-by: Amit Shah <amit.shah@redhat.com> Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
-rw-r--r--drivers/char/virtio_console.c58
1 files changed, 58 insertions, 0 deletions
diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c
index 9681ffd79904..614b84d38d7a 100644
--- a/drivers/char/virtio_console.c
+++ b/drivers/char/virtio_console.c
@@ -1844,6 +1844,60 @@ static unsigned int features[] = {
1844 VIRTIO_CONSOLE_F_MULTIPORT, 1844 VIRTIO_CONSOLE_F_MULTIPORT,
1845}; 1845};
1846 1846
1847#ifdef CONFIG_PM
1848static int virtcons_freeze(struct virtio_device *vdev)
1849{
1850 struct ports_device *portdev;
1851 struct port *port;
1852
1853 portdev = vdev->priv;
1854
1855 vdev->config->reset(vdev);
1856
1857 cancel_work_sync(&portdev->control_work);
1858 remove_controlq_data(portdev);
1859
1860 list_for_each_entry(port, &portdev->ports, list) {
1861 /*
1862 * We'll ask the host later if the new invocation has
1863 * the port opened or closed.
1864 */
1865 port->host_connected = false;
1866 remove_port_data(port);
1867 }
1868 remove_vqs(portdev);
1869
1870 return 0;
1871}
1872
1873static int virtcons_restore(struct virtio_device *vdev)
1874{
1875 struct ports_device *portdev;
1876 struct port *port;
1877 int ret;
1878
1879 portdev = vdev->priv;
1880
1881 ret = init_vqs(portdev);
1882 if (ret)
1883 return ret;
1884
1885 if (use_multiport(portdev))
1886 fill_queue(portdev->c_ivq, &portdev->cvq_lock);
1887
1888 list_for_each_entry(port, &portdev->ports, list) {
1889 port->in_vq = portdev->in_vqs[port->id];
1890 port->out_vq = portdev->out_vqs[port->id];
1891
1892 fill_queue(port->in_vq, &port->inbuf_lock);
1893
1894 /* Get port open/close status on the host */
1895 send_control_msg(port, VIRTIO_CONSOLE_PORT_READY, 1);
1896 }
1897 return 0;
1898}
1899#endif
1900
1847static struct virtio_driver virtio_console = { 1901static struct virtio_driver virtio_console = {
1848 .feature_table = features, 1902 .feature_table = features,
1849 .feature_table_size = ARRAY_SIZE(features), 1903 .feature_table_size = ARRAY_SIZE(features),
@@ -1853,6 +1907,10 @@ static struct virtio_driver virtio_console = {
1853 .probe = virtcons_probe, 1907 .probe = virtcons_probe,
1854 .remove = virtcons_remove, 1908 .remove = virtcons_remove,
1855 .config_changed = config_intr, 1909 .config_changed = config_intr,
1910#ifdef CONFIG_PM
1911 .freeze = virtcons_freeze,
1912 .restore = virtcons_restore,
1913#endif
1856}; 1914};
1857 1915
1858static int __init init(void) 1916static int __init init(void)