Revision 9ed7b059 hw/virtio-serial-bus.c

b/hw/virtio-serial-bus.c
111 111
    return offset;
112 112
}
113 113

  
114
static void flush_queued_data(VirtIOSerialPort *port, VirtQueue *vq,
115
                              VirtIODevice *vdev, bool discard)
114
static void do_flush_queued_data(VirtIOSerialPort *port, VirtQueue *vq,
115
                                 VirtIODevice *vdev, bool discard)
116 116
{
117 117
    VirtQueueElement elem;
118 118

  
119 119
    assert(port || discard);
120 120

  
121
    while (virtqueue_pop(vq, &elem)) {
121
    while ((discard || !port->throttled) && virtqueue_pop(vq, &elem)) {
122 122
        uint8_t *buf;
123 123
        size_t ret, buf_size;
124 124

  
......
135 135
    virtio_notify(vdev, vq);
136 136
}
137 137

  
138
static void flush_queued_data(VirtIOSerialPort *port, bool discard)
139
{
140
    assert(port || discard);
141

  
142
    do_flush_queued_data(port, port->ovq, &port->vser->vdev, discard);
143
}
144

  
138 145
static size_t send_control_msg(VirtIOSerialPort *port, void *buf, size_t len)
139 146
{
140 147
    VirtQueueElement elem;
......
186 193
int virtio_serial_close(VirtIOSerialPort *port)
187 194
{
188 195
    port->host_connected = false;
196
    /*
197
     * If there's any data the guest sent which the app didn't
198
     * consume, reset the throttling flag and discard the data.
199
     */
200
    port->throttled = false;
201
    flush_queued_data(port, true);
202

  
189 203
    send_control_event(port, VIRTIO_CONSOLE_PORT_OPEN, 0);
190 204

  
191 205
    return 0;
......
227 241
    return 0;
228 242
}
229 243

  
244
void virtio_serial_throttle_port(VirtIOSerialPort *port, bool throttle)
245
{
246
    if (!port) {
247
        return;
248
    }
249

  
250
    port->throttled = throttle;
251
    if (throttle) {
252
        return;
253
    }
254

  
255
    flush_queued_data(port, false);
256
}
257

  
230 258
/* Guest wants to notify us of some event */
231 259
static void handle_control_message(VirtIOSerial *vser, void *buf, size_t len)
232 260
{
......
380 408
        discard = true;
381 409
    }
382 410

  
383
    flush_queued_data(port, vq, vdev, discard);
411
    if (!discard && port->throttled) {
412
        return;
413
    }
414

  
415
    do_flush_queued_data(port, vq, vdev, discard);
384 416
}
385 417

  
386 418
static void handle_input(VirtIODevice *vdev, VirtQueue *vq)
......
555 587
                   indent, "", port->guest_connected);
556 588
    monitor_printf(mon, "%*s dev-prop-int: host_connected: %d\n",
557 589
                   indent, "", port->host_connected);
590
    monitor_printf(mon, "%*s dev-prop-int: throttled: %d\n",
591
                   indent, "", port->throttled);
558 592
}
559 593

  
560 594
/* This function is only used if a port id is not provided by the user */
......
592 626

  
593 627
static void remove_port(VirtIOSerial *vser, uint32_t port_id)
594 628
{
629
    VirtIOSerialPort *port;
595 630
    unsigned int i;
596 631

  
597 632
    i = port_id / 32;
598 633
    vser->ports_map[i] &= ~(1U << (port_id % 32));
599 634

  
600
    send_control_event(find_port_by_id(vser, port_id),
601
                       VIRTIO_CONSOLE_PORT_REMOVE, 1);
635
    port = find_port_by_id(vser, port_id);
636
    /* Flush out any unconsumed buffers first */
637
    flush_queued_data(port, true);
638

  
639
    send_control_event(port, VIRTIO_CONSOLE_PORT_REMOVE, 1);
602 640
}
603 641

  
604 642
static int virtser_port_qdev_init(DeviceState *qdev, DeviceInfo *base)

Also available in: Unified diff