Remove port data; deregister from the hvc core if it's a console port. Signed-off-by: Amit Shah <amit.shah@xxxxxxxxxx> --- drivers/char/virtio_console.c | 64 ++++++++++++++++++++++++++++++++++++++++ include/linux/virtio_console.h | 2 + 2 files changed, 66 insertions(+), 0 deletions(-) diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c index 90bb221..9035f80 100644 --- a/drivers/char/virtio_console.c +++ b/drivers/char/virtio_console.c @@ -719,6 +719,42 @@ int init_port_console(struct virtio_console_port *port) return ret; } +static struct attribute_group virtcon_attribute_group; + +/* Remove port-specific data. */ +static int virtcons_remove_port_data(struct virtio_console_port *port) +{ + struct virtio_console_port_buffer *buf, *buf2; + struct virtio_console_control cpkt; + + if (port->guest_connected) { + cpkt.event = VIRTIO_CONSOLE_PORT_OPEN; + cpkt.value = 0; + send_buf(port, (char *)&cpkt, sizeof(cpkt), + VIRTIO_CONSOLE_ID_CONTROL, false); + } + if (is_console_port(port)) + hvc_remove(port->hvc); + + sysfs_remove_group(&port->dev->kobj, &virtcon_attribute_group); + device_destroy(virtconsole.class, port->dev->devt); + unregister_chrdev_region(port->dev->devt, 1); + cdev_del(&port->cdev); + + kfree(port->name); + + /* Remove the buffers in which we have unconsumed data */ + spin_lock(&port->readbuf_list_lock); + list_for_each_entry_safe(buf, buf2, &port->readbuf_head, list) { + list_del(&buf->list); + kfree(buf->buf); + kfree(buf); + } + spin_unlock(&port->readbuf_list_lock); + debugfs_remove(port->debugfs_file); + return 0; +} + /* Any private messages that the Host and Guest want to share */ static void handle_control_message(struct virtio_console_port *port, struct virtio_console_port_buffer *buf) @@ -799,6 +835,30 @@ static void handle_control_message(struct virtio_console_port *port, case VIRTIO_CONSOLE_CACHE_BUFFERS: port->cache_buffers = cpkt->value; break; + case VIRTIO_CONSOLE_PORT_REMOVE: + /* + * Hot unplug the port. We don't decrement nr_ports + * since we don't want to deal with extra complexities + * of using the lowest-available port id: We can just + * pick up the nr_ports number as the id and not have + * userspace send it to us. This helps us in two ways: + * + * - We don't need to have a 'port_id' field in the + * config space when a port is hot-added. This is a + * good thing as we might queue up multiple hotplug + * requests issued in our workqueue. + * + * - Another way to deal with this would have been to + * use a bitmap of the active ports and select the + * lowest non-active port from that map. That bloats + * the already tight config space and we would end + * up artificially limiting the max. number of ports + * to sizeof(bitmap). Right now we can support 2^32 + * ports (as the port id is stored in a u32 type). + * + */ + virtcons_remove_port_data(port); + break; } } @@ -1280,6 +1340,9 @@ static int __devinit virtcons_probe(struct virtio_device *vdev) if (virtio_has_feature(vdev, VIRTIO_CONSOLE_F_CACHING)) vdev->features[0] |= 1 << VIRTIO_CONSOLE_F_CACHING; + if (virtio_has_feature(vdev, VIRTIO_CONSOLE_F_UNPLUG)) + vdev->features[0] |= 1 << VIRTIO_CONSOLE_F_UNPLUG; + vdev->config->finalize_features(vdev); /* Find the queues. */ /* FIXME: This is why we want to wean off hvc: we do nothing @@ -1333,6 +1396,7 @@ static unsigned int features[] = { VIRTIO_CONSOLE_F_MULTIPORT, VIRTIO_CONSOLE_F_THROTTLE, VIRTIO_CONSOLE_F_CACHING, + VIRTIO_CONSOLE_F_UNPLUG, }; static struct virtio_driver virtio_console = { diff --git a/include/linux/virtio_console.h b/include/linux/virtio_console.h index ce5eef2..703696a 100644 --- a/include/linux/virtio_console.h +++ b/include/linux/virtio_console.h @@ -15,6 +15,7 @@ #define VIRTIO_CONSOLE_F_MULTIPORT 1 /* Does host provide multiple ports? */ #define VIRTIO_CONSOLE_F_THROTTLE 2 /* Do we throttle data to prevent OOM */ #define VIRTIO_CONSOLE_F_CACHING 3 /* Do we cache data after port close? */ +#define VIRTIO_CONSOLE_F_UNPLUG 4 /* Can we hot-unplug ports? */ struct virtio_console_config { /* colums of the screens */ @@ -42,6 +43,7 @@ struct virtio_console_control { #define VIRTIO_CONSOLE_THROTTLE_PORT 4 #define VIRTIO_CONSOLE_BUFFER_LIMIT 5 #define VIRTIO_CONSOLE_CACHE_BUFFERS 6 +#define VIRTIO_CONSOLE_PORT_REMOVE 7 /* * This struct is put in each buffer that gets passed to userspace and -- 1.6.2.5 _______________________________________________ Virtualization mailing list Virtualization@xxxxxxxxxxxxxxxxxxxxxxxxxx https://lists.linux-foundation.org/mailman/listinfo/virtualization