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