Commit 2b8f41d8 authored by Amit Shah's avatar Amit Shah Committed by Rusty Russell

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: default avatarAmit Shah <amit.shah@redhat.com>
Signed-off-by: default avatarRusty Russell <rusty@rustcorp.com.au>
parent a0e2dbfc
...@@ -1844,6 +1844,60 @@ static unsigned int features[] = { ...@@ -1844,6 +1844,60 @@ static unsigned int features[] = {
VIRTIO_CONSOLE_F_MULTIPORT, VIRTIO_CONSOLE_F_MULTIPORT,
}; };
#ifdef CONFIG_PM
static int virtcons_freeze(struct virtio_device *vdev)
{
struct ports_device *portdev;
struct port *port;
portdev = vdev->priv;
vdev->config->reset(vdev);
cancel_work_sync(&portdev->control_work);
remove_controlq_data(portdev);
list_for_each_entry(port, &portdev->ports, list) {
/*
* We'll ask the host later if the new invocation has
* the port opened or closed.
*/
port->host_connected = false;
remove_port_data(port);
}
remove_vqs(portdev);
return 0;
}
static int virtcons_restore(struct virtio_device *vdev)
{
struct ports_device *portdev;
struct port *port;
int ret;
portdev = vdev->priv;
ret = init_vqs(portdev);
if (ret)
return ret;
if (use_multiport(portdev))
fill_queue(portdev->c_ivq, &portdev->cvq_lock);
list_for_each_entry(port, &portdev->ports, list) {
port->in_vq = portdev->in_vqs[port->id];
port->out_vq = portdev->out_vqs[port->id];
fill_queue(port->in_vq, &port->inbuf_lock);
/* Get port open/close status on the host */
send_control_msg(port, VIRTIO_CONSOLE_PORT_READY, 1);
}
return 0;
}
#endif
static struct virtio_driver virtio_console = { static struct virtio_driver virtio_console = {
.feature_table = features, .feature_table = features,
.feature_table_size = ARRAY_SIZE(features), .feature_table_size = ARRAY_SIZE(features),
...@@ -1853,6 +1907,10 @@ static struct virtio_driver virtio_console = { ...@@ -1853,6 +1907,10 @@ static struct virtio_driver virtio_console = {
.probe = virtcons_probe, .probe = virtcons_probe,
.remove = virtcons_remove, .remove = virtcons_remove,
.config_changed = config_intr, .config_changed = config_intr,
#ifdef CONFIG_PM
.freeze = virtcons_freeze,
.restore = virtcons_restore,
#endif
}; };
static int __init init(void) static int __init init(void)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment