diff options
| author | Amit Shah <amit.shah@redhat.com> | 2009-12-21 11:45:30 -0500 |
|---|---|---|
| committer | Rusty Russell <rusty@rustcorp.com.au> | 2010-02-23 22:52:57 -0500 |
| commit | 88f251ac58b2460ed16ff619a020ad3ef365e607 (patch) | |
| tree | c44ba54bfc42897e554399ca66f19ca720f8a751 | |
| parent | 431edb8a8bca71008fefceadf53b9315ef7196ec (diff) | |
virtio: console: Remove cached data on port close
Remove any data that we might have in a port's inbuf when closing a port
or when any data is received when a port is closed.
Signed-off-by: Amit Shah <amit.shah@redhat.com>
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
| -rw-r--r-- | drivers/char/virtio_console.c | 40 |
1 files changed, 40 insertions, 0 deletions
diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c index 99d182b132c4..5506ff8bdf03 100644 --- a/drivers/char/virtio_console.c +++ b/drivers/char/virtio_console.c | |||
| @@ -316,6 +316,31 @@ static int add_inbuf(struct virtqueue *vq, struct port_buffer *buf) | |||
| 316 | return ret; | 316 | return ret; |
| 317 | } | 317 | } |
| 318 | 318 | ||
| 319 | /* Discard any unread data this port has. Callers lockers. */ | ||
| 320 | static void discard_port_data(struct port *port) | ||
| 321 | { | ||
| 322 | struct port_buffer *buf; | ||
| 323 | struct virtqueue *vq; | ||
| 324 | unsigned int len; | ||
| 325 | |||
| 326 | vq = port->in_vq; | ||
| 327 | if (port->inbuf) | ||
| 328 | buf = port->inbuf; | ||
| 329 | else | ||
| 330 | buf = vq->vq_ops->get_buf(vq, &len); | ||
| 331 | |||
| 332 | if (!buf) | ||
| 333 | return; | ||
| 334 | |||
| 335 | if (add_inbuf(vq, buf) < 0) { | ||
| 336 | buf->len = buf->offset = 0; | ||
| 337 | dev_warn(port->dev, "Error adding buffer back to vq\n"); | ||
| 338 | return; | ||
| 339 | } | ||
| 340 | |||
| 341 | port->inbuf = NULL; | ||
| 342 | } | ||
| 343 | |||
| 319 | static bool port_has_data(struct port *port) | 344 | static bool port_has_data(struct port *port) |
| 320 | { | 345 | { |
| 321 | unsigned long flags; | 346 | unsigned long flags; |
| @@ -534,8 +559,13 @@ static int port_fops_release(struct inode *inode, struct file *filp) | |||
| 534 | /* Notify host of port being closed */ | 559 | /* Notify host of port being closed */ |
| 535 | send_control_msg(port, VIRTIO_CONSOLE_PORT_OPEN, 0); | 560 | send_control_msg(port, VIRTIO_CONSOLE_PORT_OPEN, 0); |
| 536 | 561 | ||
| 562 | spin_lock_irq(&port->inbuf_lock); | ||
| 537 | port->guest_connected = false; | 563 | port->guest_connected = false; |
| 538 | 564 | ||
| 565 | discard_port_data(port); | ||
| 566 | |||
| 567 | spin_unlock_irq(&port->inbuf_lock); | ||
| 568 | |||
| 539 | return 0; | 569 | return 0; |
| 540 | } | 570 | } |
| 541 | 571 | ||
| @@ -872,6 +902,16 @@ static void in_intr(struct virtqueue *vq) | |||
| 872 | spin_lock_irqsave(&port->inbuf_lock, flags); | 902 | spin_lock_irqsave(&port->inbuf_lock, flags); |
| 873 | port->inbuf = get_inbuf(port); | 903 | port->inbuf = get_inbuf(port); |
| 874 | 904 | ||
| 905 | /* | ||
| 906 | * Don't queue up data when port is closed. This condition | ||
| 907 | * can be reached when a console port is not yet connected (no | ||
| 908 | * tty is spawned) and the host sends out data to console | ||
| 909 | * ports. For generic serial ports, the host won't | ||
| 910 | * (shouldn't) send data till the guest is connected. | ||
| 911 | */ | ||
| 912 | if (!port->guest_connected) | ||
| 913 | discard_port_data(port); | ||
| 914 | |||
| 875 | spin_unlock_irqrestore(&port->inbuf_lock, flags); | 915 | spin_unlock_irqrestore(&port->inbuf_lock, flags); |
| 876 | 916 | ||
| 877 | wake_up_interruptible(&port->waitqueue); | 917 | wake_up_interruptible(&port->waitqueue); |
