]> git.karo-electronics.de Git - mv-sheeva.git/blobdiff - drivers/char/virtio_console.c
Merge tag 'v2.6.38' of git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6
[mv-sheeva.git] / drivers / char / virtio_console.c
index 896a2ced1d27952d9288a48911ee406ccabe1ee7..84b164d1eb2b16d29db4d87ed6a7d745fa1938bc 100644 (file)
@@ -1,6 +1,7 @@
 /*
  * Copyright (C) 2006, 2007, 2009 Rusty Russell, IBM Corporation
- * Copyright (C) 2009, 2010 Red Hat, Inc.
+ * Copyright (C) 2009, 2010, 2011 Red Hat, Inc.
+ * Copyright (C) 2009, 2010, 2011 Amit Shah <amit.shah@redhat.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -31,7 +32,7 @@
 #include <linux/virtio_console.h>
 #include <linux/wait.h>
 #include <linux/workqueue.h>
-#include "hvc_console.h"
+#include "../tty/hvc/hvc_console.h"
 
 /*
  * This is a global struct for storing common data for all the devices
@@ -387,6 +388,10 @@ static void discard_port_data(struct port *port)
        unsigned int len;
        int ret;
 
+       if (!port->portdev) {
+               /* Device has been unplugged.  vqs are already gone. */
+               return;
+       }
        vq = port->in_vq;
        if (port->inbuf)
                buf = port->inbuf;
@@ -469,6 +474,10 @@ static void reclaim_consumed_buffers(struct port *port)
        void *buf;
        unsigned int len;
 
+       if (!port->portdev) {
+               /* Device has been unplugged.  vqs are already gone. */
+               return;
+       }
        while ((buf = virtqueue_get_buf(port->out_vq, &len))) {
                kfree(buf);
                port->outvq_full = false;
@@ -1462,6 +1471,17 @@ static void control_work_handler(struct work_struct *work)
        spin_unlock(&portdev->cvq_lock);
 }
 
+static void out_intr(struct virtqueue *vq)
+{
+       struct port *port;
+
+       port = find_port_by_vq(vq->vdev->priv, vq);
+       if (!port)
+               return;
+
+       wake_up_interruptible(&port->waitqueue);
+}
+
 static void in_intr(struct virtqueue *vq)
 {
        struct port *port;
@@ -1566,7 +1586,7 @@ static int init_vqs(struct ports_device *portdev)
         */
        j = 0;
        io_callbacks[j] = in_intr;
-       io_callbacks[j + 1] = NULL;
+       io_callbacks[j + 1] = out_intr;
        io_names[j] = "input";
        io_names[j + 1] = "output";
        j += 2;
@@ -1580,7 +1600,7 @@ static int init_vqs(struct ports_device *portdev)
                for (i = 1; i < nr_ports; i++) {
                        j += 2;
                        io_callbacks[j] = in_intr;
-                       io_callbacks[j + 1] = NULL;
+                       io_callbacks[j + 1] = out_intr;
                        io_names[j] = "input";
                        io_names[j + 1] = "output";
                }