]> git.proxmox.com Git - qemu.git/blobdiff - hw/virtio-serial-bus.c
qdev: move qdev->info to class
[qemu.git] / hw / virtio-serial-bus.c
index c5eb931095848a6a88cbb374266807fd6fc8c6d3..982ffbf66870001ef6d3e11129d967399c862eb8 100644 (file)
@@ -13,6 +13,9 @@
  *
  * This work is licensed under the terms of the GNU GPL, version 2.  See
  * the COPYING file in the top-level directory.
+ *
+ * Contributions after 2012-01-13 are licensed under the terms of the
+ * GNU GPL, version 2 or (at your option) any later version.
  */
 
 #include "iov.h"
@@ -135,7 +138,7 @@ static void do_flush_queued_data(VirtIOSerialPort *port, VirtQueue *vq,
     assert(port);
     assert(virtio_queue_ready(vq));
 
-    info = DO_UPCAST(VirtIOSerialPortInfo, qdev, port->dev.info);
+    info = DO_UPCAST(VirtIOSerialPortInfo, qdev, qdev_get_info(&port->dev));
 
     while (!port->throttled) {
         unsigned int i;
@@ -163,7 +166,19 @@ static void do_flush_queued_data(VirtIOSerialPort *port, VirtQueue *vq,
                 abort();
             }
             if (ret == -EAGAIN || (ret >= 0 && ret < buf_size)) {
-                virtio_serial_throttle_port(port, true);
+               /*
+                 * this is a temporary check until chardevs can signal to
+                 * frontends that they are writable again. This prevents
+                 * the console from going into throttled mode (forever)
+                 * if virtio-console is connected to a pty without a
+                 * listener. Otherwise the guest spins forever.
+                 * We can revert this if
+                 * 1: chardevs can notify frondends
+                 * 2: the guest driver does not spin in these cases
+                 */
+                if (!info->is_console) {
+                    virtio_serial_throttle_port(port, true);
+                }
                 port->iov_idx = i;
                 if (ret > 0) {
                     port->iov_offset += ret;
@@ -358,7 +373,7 @@ static void handle_control_message(VirtIOSerial *vser, void *buf, size_t len)
 
     trace_virtio_serial_handle_control_message_port(port->id);
 
-    info = DO_UPCAST(VirtIOSerialPortInfo, qdev, port->dev.info);
+    info = DO_UPCAST(VirtIOSerialPortInfo, qdev, qdev_get_info(&port->dev));
 
     switch(cpkt.event) {
     case VIRTIO_CONSOLE_PORT_READY:
@@ -383,14 +398,14 @@ static void handle_control_message(VirtIOSerial *vser, void *buf, size_t len)
             stw_p(&cpkt.value, 1);
 
             buffer_len = sizeof(cpkt) + strlen(port->name) + 1;
-            buffer = qemu_malloc(buffer_len);
+            buffer = g_malloc(buffer_len);
 
             memcpy(buffer, &cpkt, sizeof(cpkt));
             memcpy(buffer + sizeof(cpkt), port->name, strlen(port->name));
             buffer[buffer_len - 1] = 0;
 
             send_control_msg(port, buffer, buffer_len);
-            qemu_free(buffer);
+            g_free(buffer);
         }
 
         if (port->host_connected) {
@@ -447,9 +462,9 @@ static void control_out(VirtIODevice *vdev, VirtQueue *vq)
          * if the size of the buf differs
          */
         if (cur_len > len) {
-            qemu_free(buf);
+            g_free(buf);
 
-            buf = qemu_malloc(cur_len);
+            buf = g_malloc(cur_len);
             len = cur_len;
         }
         copied = iov_to_buf(elem.out_sg, elem.out_num, buf, 0, len);
@@ -457,7 +472,7 @@ static void control_out(VirtIODevice *vdev, VirtQueue *vq)
         handle_control_message(vser, buf, copied);
         virtqueue_push(vq, &elem, 0);
     }
-    qemu_free(buf);
+    g_free(buf);
     virtio_notify(vdev, vq);
 }
 
@@ -466,13 +481,11 @@ static void handle_output(VirtIODevice *vdev, VirtQueue *vq)
 {
     VirtIOSerial *vser;
     VirtIOSerialPort *port;
-    VirtIOSerialPortInfo *info;
 
     vser = DO_UPCAST(VirtIOSerial, vdev, vdev);
     port = find_port_by_vq(vser, vq);
-    info = port ? DO_UPCAST(VirtIOSerialPortInfo, qdev, port->dev.info) : NULL;
 
-    if (!port || !port->host_connected || !info->have_data) {
+    if (!port || !port->host_connected) {
         discard_vq_data(vq, vdev);
         return;
     }
@@ -746,6 +759,8 @@ static int virtser_port_qdev_init(DeviceState *qdev, DeviceInfo *base)
     port->vser = bus->vser;
     port->bh = qemu_bh_new(flush_queued_data_bh, port);
 
+    assert(info->have_data);
+
     /*
      * Is the first console port we're seeing? If so, put it up at
      * location 0. This is done for backward compatibility (old
@@ -809,7 +824,7 @@ static int virtser_port_qdev_exit(DeviceState *qdev)
 {
     VirtIOSerialPort *port = DO_UPCAST(VirtIOSerialPort, dev, qdev);
     VirtIOSerialPortInfo *info = DO_UPCAST(VirtIOSerialPortInfo, qdev,
-                                           port->dev.info);
+                                           qdev_get_info(&port->dev));
     VirtIOSerial *vser = port->vser;
 
     qemu_bh_delete(port->bh);
@@ -862,8 +877,8 @@ VirtIODevice *virtio_serial_init(DeviceState *dev, virtio_serial_conf *conf)
     QTAILQ_INIT(&vser->ports);
 
     vser->bus.max_nr_ports = conf->max_virtserial_ports;
-    vser->ivqs = qemu_malloc(conf->max_virtserial_ports * sizeof(VirtQueue *));
-    vser->ovqs = qemu_malloc(conf->max_virtserial_ports * sizeof(VirtQueue *));
+    vser->ivqs = g_malloc(conf->max_virtserial_ports * sizeof(VirtQueue *));
+    vser->ovqs = g_malloc(conf->max_virtserial_ports * sizeof(VirtQueue *));
 
     /* Add a queue for host to guest transfers for port 0 (backward compat) */
     vser->ivqs[0] = virtio_add_queue(vdev, 128, handle_input);
@@ -889,7 +904,7 @@ VirtIODevice *virtio_serial_init(DeviceState *dev, virtio_serial_conf *conf)
     }
 
     vser->config.max_nr_ports = tswap32(conf->max_virtserial_ports);
-    vser->ports_map = qemu_mallocz(((conf->max_virtserial_ports + 31) / 32)
+    vser->ports_map = g_malloc0(((conf->max_virtserial_ports + 31) / 32)
         * sizeof(vser->ports_map[0]));
     /*
      * Reserve location 0 for a console port for backward compat
@@ -919,9 +934,9 @@ void virtio_serial_exit(VirtIODevice *vdev)
 
     unregister_savevm(vser->qdev, "virtio-console", vser);
 
-    qemu_free(vser->ivqs);
-    qemu_free(vser->ovqs);
-    qemu_free(vser->ports_map);
+    g_free(vser->ivqs);
+    g_free(vser->ovqs);
+    g_free(vser->ports_map);
 
     virtio_cleanup(vdev);
 }