The new way of handling hot-plug as well as unplug is via a config interrupt. Signed-off-by: Amit Shah <amit.shah@xxxxxxxxxx> --- drivers/char/virtio_console.c | 53 +++++++++++++++++++++++++++++++++++++---- 1 files changed, 48 insertions(+), 5 deletions(-) diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c index 9f2cbf0..06ca95c 100644 --- a/drivers/char/virtio_console.c +++ b/drivers/char/virtio_console.c @@ -1268,22 +1268,65 @@ static struct virtio_console_config *get_config(struct virtio_device *vdev, } /* - * The workhandler for config-space updates. + * The workhandler for config-space updates. Only called when + * multiport is supported. * - * This is called when ports are hot-added. + * This is called when ports are hot-added and hot-removed. */ static void config_work_handler(struct work_struct *work) { - struct virtio_console_config virtconconf; + struct virtio_console_config *config; struct ports_device *portdev; struct virtio_device *vdev; - int err; + unsigned int i, changed; portdev = container_of(work, struct ports_device, config_work); vdev = portdev->vdev; - /* FIXME: Handle port hotplug/unplug */ + config = get_config(vdev, true); + if (!config) { + dev_warn(&vdev->dev, + "Running out of memory on config change events\n"); + return; + } + + if (config->max_nr_ports != portdev->config->max_nr_ports) { + dev_warn(&vdev->dev, + "Host updated max_nr_ports, can't handle that now.\n"); + goto free; + } + + changed = 0; + for (i = 0; i < (config->max_nr_ports + 31) / 32; i++) { + u32 map; + + map = config->ports_map[i] ^ portdev->config->ports_map[i]; + while (map) { + struct port *port; + u32 port_nr; + + changed++; + port_nr = find_next_bit_in_map(&map) + i * 32; + port = find_port_by_id(portdev, port_nr); + if (port) + remove_port(port); + else + add_port(portdev, port_nr); + } + portdev->config->ports_map[i] = config->ports_map[i]; + } + if (!changed && find_port_by_id(portdev, 0)) { + /* + * No hot-plug / unplug activity. Port 0 might have + * been hot-added. Just send a 'ready' message in + * that case, since we already have it added. + */ + send_control_msg(find_port_by_id(portdev, 0), + VIRTIO_CONSOLE_PORT_READY, 1); + } +free: + kfree(config); } static int init_vqs(struct ports_device *portdev) -- 1.6.2.5 _______________________________________________ Virtualization mailing list Virtualization@xxxxxxxxxxxxxxxxxxxxxxxxxx https://lists.linux-foundation.org/mailman/listinfo/virtualization