diff options
Diffstat (limited to 'hw/char/virtio-serial-bus.c')
-rw-r--r-- | hw/char/virtio-serial-bus.c | 52 |
1 files changed, 47 insertions, 5 deletions
diff --git a/hw/char/virtio-serial-bus.c b/hw/char/virtio-serial-bus.c index 23123b730..a7b1b6898 100644 --- a/hw/char/virtio-serial-bus.c +++ b/hw/char/virtio-serial-bus.c @@ -26,6 +26,10 @@ #include "hw/virtio/virtio-serial.h" #include "hw/virtio/virtio-access.h" +struct VirtIOSerialDevices { + QLIST_HEAD(, VirtIOSerial) devices; +} vserdevices; + static VirtIOSerialPort *find_port_by_id(VirtIOSerial *vser, uint32_t id) { VirtIOSerialPort *port; @@ -52,6 +56,22 @@ static VirtIOSerialPort *find_port_by_vq(VirtIOSerial *vser, VirtQueue *vq) return NULL; } +static VirtIOSerialPort *find_port_by_name(char *name) +{ + VirtIOSerial *vser; + + QLIST_FOREACH(vser, &vserdevices.devices, next) { + VirtIOSerialPort *port; + + QTAILQ_FOREACH(port, &vser->ports, next) { + if (!strcmp(port->name, name)) { + return port; + } + } + } + return NULL; +} + static bool use_multiport(VirtIOSerial *vser) { VirtIODevice *vdev = VIRTIO_DEVICE(vser); @@ -851,6 +871,12 @@ static void virtser_port_device_realize(DeviceState *dev, Error **errp) return; } + if (port->name != NULL && find_port_by_name(port->name)) { + error_setg(errp, "virtio-serial-bus: A port already exists by name %s", + port->name); + return; + } + if (port->id == VIRTIO_CONSOLE_BAD_ID) { if (plugging_port0) { port->id = 0; @@ -878,6 +904,12 @@ static void virtser_port_device_realize(DeviceState *dev, Error **errp) } port->elem.out_num = 0; +} + +static void virtser_port_device_plug(HotplugHandler *hotplug_dev, + DeviceState *dev, Error **errp) +{ + VirtIOSerialPort *port = VIRTIO_SERIAL_PORT(dev); QTAILQ_INSERT_TAIL(&port->vser->ports, port, next); port->ivq = port->vser->ivqs[port->id]; @@ -886,7 +918,7 @@ static void virtser_port_device_realize(DeviceState *dev, Error **errp) add_port(port->vser, port->id); /* Send an update to the guest about this new port added */ - virtio_notify_config(vdev); + virtio_notify_config(VIRTIO_DEVICE(hotplug_dev)); } static void virtser_port_device_unrealize(DeviceState *dev, Error **errp) @@ -909,7 +941,6 @@ static void virtio_serial_device_realize(DeviceState *dev, Error **errp) { VirtIODevice *vdev = VIRTIO_DEVICE(dev); VirtIOSerial *vser = VIRTIO_SERIAL(dev); - BusState *bus; uint32_t i, max_supported_ports; if (!vser->serial.max_virtserial_ports) { @@ -931,8 +962,7 @@ static void virtio_serial_device_realize(DeviceState *dev, Error **errp) /* Spawn a new virtio-serial bus on which the ports will ride as devices */ qbus_create_inplace(&vser->bus, sizeof(vser->bus), TYPE_VIRTIO_SERIAL_BUS, dev, vdev->bus_name); - bus = BUS(&vser->bus); - bus->allow_hotplug = 1; + qbus_set_hotplug_handler(BUS(&vser->bus), DEVICE(vser), errp); vser->bus.vser = vser; QTAILQ_INIT(&vser->ports); @@ -983,6 +1013,8 @@ static void virtio_serial_device_realize(DeviceState *dev, Error **errp) */ register_savevm(dev, "virtio-console", -1, 3, virtio_serial_save, virtio_serial_load, vser); + + QLIST_INSERT_HEAD(&vserdevices.devices, vser, next); } static void virtio_serial_port_class_init(ObjectClass *klass, void *data) @@ -993,7 +1025,6 @@ static void virtio_serial_port_class_init(ObjectClass *klass, void *data) k->bus_type = TYPE_VIRTIO_SERIAL_BUS; k->realize = virtser_port_device_realize; k->unrealize = virtser_port_device_unrealize; - k->unplug = qdev_simple_unplug_cb; k->props = virtser_props; } @@ -1011,6 +1042,8 @@ static void virtio_serial_device_unrealize(DeviceState *dev, Error **errp) VirtIODevice *vdev = VIRTIO_DEVICE(dev); VirtIOSerial *vser = VIRTIO_SERIAL(dev); + QLIST_REMOVE(vser, next); + unregister_savevm(dev, "virtio-console", vser); g_free(vser->ivqs); @@ -1034,6 +1067,9 @@ static void virtio_serial_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); VirtioDeviceClass *vdc = VIRTIO_DEVICE_CLASS(klass); + HotplugHandlerClass *hc = HOTPLUG_HANDLER_CLASS(klass); + + QLIST_INIT(&vserdevices.devices); dc->props = virtio_serial_properties; set_bit(DEVICE_CATEGORY_INPUT, dc->categories); @@ -1045,6 +1081,8 @@ static void virtio_serial_class_init(ObjectClass *klass, void *data) vdc->reset = vser_reset; vdc->save = virtio_serial_save_device; vdc->load = virtio_serial_load_device; + hc->plug = virtser_port_device_plug; + hc->unplug = qdev_simple_device_unplug_cb; } static const TypeInfo virtio_device_info = { @@ -1052,6 +1090,10 @@ static const TypeInfo virtio_device_info = { .parent = TYPE_VIRTIO_DEVICE, .instance_size = sizeof(VirtIOSerial), .class_init = virtio_serial_class_init, + .interfaces = (InterfaceInfo[]) { + { TYPE_HOTPLUG_HANDLER }, + { } + } }; static void virtio_serial_register_types(void) |