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 /drivers/char | |
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>
Diffstat (limited to 'drivers/char')
-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); |