virtio_console: use virtqueue notification for hvc_console
authorChristian Borntraeger <borntraeger@de.ibm.com>
Fri, 20 Jun 2008 13:24:15 +0000 (15:24 +0200)
committerRusty Russell <rusty@rustcorp.com.au>
Fri, 25 Jul 2008 02:06:06 +0000 (12:06 +1000)
This patch exploits the new notifier callbacks of the hvc_console. We can
use the virtio callbacks instead of the polling code.

Signed-off-by: Christian Borntraeger <borntraeger@de.ibm.com>
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
drivers/char/virtio_console.c

index dc17fe3..d0f4eb6 100644 (file)
@@ -46,6 +46,9 @@ static char *in, *inbuf;
 /* The operations for our console. */
 static struct hv_ops virtio_cons;
 
+/* The hvc device */
+static struct hvc_struct *hvc;
+
 /*D:310 The put_chars() callback is pretty straightforward.
  *
  * We turn the characters into a scatter-gather list, add it to the output
@@ -134,6 +137,27 @@ int __init virtio_cons_early_init(int (*put_chars)(u32, const char *, int))
        return hvc_instantiate(0, 0, &virtio_cons);
 }
 
+/*
+ * we support only one console, the hvc struct is a global var
+ * There is no need to do anything
+ */
+static int notifier_add_vio(struct hvc_struct *hp, int data)
+{
+       hp->irq_requested = 1;
+       return 0;
+}
+
+static void notifier_del_vio(struct hvc_struct *hp, int data)
+{
+       hp->irq_requested = 0;
+}
+
+static void hvc_handle_input(struct virtqueue *vq)
+{
+       if (hvc_poll(hvc))
+               hvc_kick();
+}
+
 /*D:370 Once we're further in boot, we get probed like any other virtio device.
  * At this stage we set up the output virtqueue.
  *
@@ -144,7 +168,6 @@ int __init virtio_cons_early_init(int (*put_chars)(u32, const char *, int))
 static int __devinit virtcons_probe(struct virtio_device *dev)
 {
        int err;
-       struct hvc_struct *hvc;
 
        vdev = dev;
 
@@ -158,7 +181,7 @@ static int __devinit virtcons_probe(struct virtio_device *dev)
        /* Find the input queue. */
        /* FIXME: This is why we want to wean off hvc: we do nothing
         * when input comes in. */
-       in_vq = vdev->config->find_vq(vdev, 0, NULL);
+       in_vq = vdev->config->find_vq(vdev, 0, hvc_handle_input);
        if (IS_ERR(in_vq)) {
                err = PTR_ERR(in_vq);
                goto free;
@@ -173,15 +196,18 @@ static int __devinit virtcons_probe(struct virtio_device *dev)
        /* Start using the new console output. */
        virtio_cons.get_chars = get_chars;
        virtio_cons.put_chars = put_chars;
+       virtio_cons.notifier_add = notifier_add_vio;
+       virtio_cons.notifier_del = notifier_del_vio;
 
        /* The first argument of hvc_alloc() is the virtual console number, so
-        * we use zero.  The second argument is the interrupt number; we
-        * currently leave this as zero: it would be better not to use the
-        * hvc mechanism and fix this (FIXME!).
+        * we use zero.  The second argument is the parameter for the
+        * notification mechanism (like irq number). We currently leave this
+        * as zero, virtqueues have implicit notifications.
         *
         * The third argument is a "struct hv_ops" containing the put_chars()
-        * and get_chars() pointers.  The final argument is the output buffer
-        * size: we can do any size, so we put PAGE_SIZE here. */
+        * get_chars(), notifier_add() and notifier_del() pointers.
+        * The final argument is the output buffer size: we can do any size,
+        * so we put PAGE_SIZE here. */
        hvc = hvc_alloc(0, 0, &virtio_cons, PAGE_SIZE);
        if (IS_ERR(hvc)) {
                err = PTR_ERR(hvc);