diff options
Diffstat (limited to 'hw/virtio-serial-bus.c')
-rw-r--r-- | hw/virtio-serial-bus.c | 31 |
1 files changed, 30 insertions, 1 deletions
diff --git a/hw/virtio-serial-bus.c b/hw/virtio-serial-bus.c index 26d5841154..74ba5ec3d3 100644 --- a/hw/virtio-serial-bus.c +++ b/hw/virtio-serial-bus.c @@ -41,6 +41,8 @@ struct VirtIOSerial { VirtIOSerialBus *bus; + DeviceState *qdev; + QTAILQ_HEAD(, VirtIOSerialPort) ports; /* bitmap for identifying active ports */ @@ -117,6 +119,7 @@ static void do_flush_queued_data(VirtIOSerialPort *port, VirtQueue *vq, VirtQueueElement elem; assert(port || discard); + assert(virtio_queue_ready(vq)); while ((discard || !port->throttled) && virtqueue_pop(vq, &elem)) { uint8_t *buf; @@ -139,6 +142,9 @@ static void flush_queued_data(VirtIOSerialPort *port, bool discard) { assert(port); + if (!virtio_queue_ready(port->ovq)) { + return; + } do_flush_queued_data(port, port->ovq, &port->vser->vdev, discard); } @@ -730,11 +736,19 @@ VirtIODevice *virtio_serial_init(DeviceState *dev, uint32_t max_nr_ports) { VirtIOSerial *vser; VirtIODevice *vdev; - uint32_t i; + uint32_t i, max_supported_ports; if (!max_nr_ports) return NULL; + /* Each port takes 2 queues, and one pair is for the control queue */ + max_supported_ports = VIRTIO_PCI_QUEUE_MAX / 2 - 1; + + if (max_nr_ports > max_supported_ports) { + error_report("maximum ports supported: %u", max_supported_ports); + return NULL; + } + vdev = virtio_common_init("virtio-serial", VIRTIO_ID_CONSOLE, sizeof(struct virtio_console_config), sizeof(VirtIOSerial)); @@ -780,6 +794,8 @@ VirtIODevice *virtio_serial_init(DeviceState *dev, uint32_t max_nr_ports) vser->vdev.get_config = get_config; vser->vdev.set_config = set_config; + vser->qdev = dev; + /* * Register for the savevm section with the virtio-console name * to preserve backward compat @@ -789,3 +805,16 @@ VirtIODevice *virtio_serial_init(DeviceState *dev, uint32_t max_nr_ports) return vdev; } + +void virtio_serial_exit(VirtIODevice *vdev) +{ + VirtIOSerial *vser = DO_UPCAST(VirtIOSerial, vdev, vdev); + + unregister_savevm(vser->qdev, "virtio-console", vser); + + qemu_free(vser->ivqs); + qemu_free(vser->ovqs); + qemu_free(vser->ports_map); + + virtio_cleanup(vdev); +} |