]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - drivers/char/hvc_console.c
[POWERPC] Quiet section mismatch in hvc_rtas.c
[linux-2.6-omap-h63xx.git] / drivers / char / hvc_console.c
index ca2f538e549e3fe6e87a3a850d3961e9b06ffeb9..83c1151ec7a21559257f3663a59d0f59e4d92abc 100644 (file)
@@ -38,6 +38,7 @@
 #include <linux/sched.h>
 #include <linux/spinlock.h>
 #include <linux/delay.h>
+#include <linux/freezer.h>
 
 #include <asm/uaccess.h>
 
@@ -46,8 +47,6 @@
 #define HVC_MAJOR      229
 #define HVC_MINOR      0
 
-#define TIMEOUT                (10)
-
 /*
  * Wait this long per iteration while trying to push buffered data to the
  * hypervisor before allowing the tty to complete a close operation.
@@ -80,7 +79,8 @@ struct hvc_struct {
        struct tty_struct *tty;
        unsigned int count;
        int do_wakeup;
-       char outbuf[N_OUTBUF] __ALIGNED__;
+       char *outbuf;
+       int outbuf_size;
        int n_outbuf;
        uint32_t vtermno;
        struct hv_ops *ops;
@@ -102,16 +102,16 @@ static DEFINE_SPINLOCK(hvc_structs_lock);
 /*
  * This value is used to assign a tty->index value to a hvc_struct based
  * upon order of exposure via hvc_probe(), when we can not match it to
- * a console canidate registered with hvc_instantiate().
+ * a console candidate registered with hvc_instantiate().
  */
 static int last_hvc = -1;
 
 /*
- * Do not call this function with either the hvc_strucst_lock or the hvc_struct
+ * Do not call this function with either the hvc_structs_lock or the hvc_struct
  * lock held.  If successful, this function increments the kobject reference
  * count against the target hvc_struct so it should be released when finished.
  */
-struct hvc_struct *hvc_get_by_index(int index)
+static struct hvc_struct *hvc_get_by_index(int index)
 {
        struct hvc_struct *hp;
        unsigned long flags;
@@ -150,7 +150,8 @@ static uint32_t vtermnos[MAX_NR_HVC_CONSOLES] =
  * hvc_console_setup() finds adapters.
  */
 
-void hvc_console_print(struct console *co, const char *b, unsigned count)
+static void hvc_console_print(struct console *co, const char *b,
+                             unsigned count)
 {
        char c[N_OUTBUF] __ALIGNED__;
        unsigned i = 0, n = 0;
@@ -160,7 +161,7 @@ void hvc_console_print(struct console *co, const char *b, unsigned count)
        if (index >= MAX_NR_HVC_CONSOLES)
                return;
 
-       /* This console adapter was removed so it is not useable. */
+       /* This console adapter was removed so it is not usable. */
        if (vtermnos[index] < 0)
                return;
 
@@ -208,7 +209,7 @@ static int __init hvc_console_setup(struct console *co, char *options)
        return 0;
 }
 
-struct console hvc_con_driver = {
+static struct console hvc_con_driver = {
        .name           = "hvc",
        .write          = hvc_console_print,
        .device         = hvc_console_device,
@@ -218,7 +219,7 @@ struct console hvc_con_driver = {
 };
 
 /*
- * Early console initialization.  Preceeds driver initialization.
+ * Early console initialization.  Precedes driver initialization.
  *
  * (1) we are first, and the user specified another driver
  * -- index will remain -1
@@ -255,7 +256,7 @@ int hvc_instantiate(uint32_t vtermno, int index, struct hv_ops *ops)
        if (vtermnos[index] != -1)
                return -1;
 
-       /* make sure no no tty has been registerd in this index */
+       /* make sure no no tty has been registered in this index */
        hp = hvc_get_by_index(index);
        if (hp) {
                kobject_put(&hp->kobj);
@@ -265,7 +266,7 @@ int hvc_instantiate(uint32_t vtermno, int index, struct hv_ops *ops)
        vtermnos[index] = vtermno;
        cons_ops[index] = ops;
 
-       /* reserve all indices upto and including this index */
+       /* reserve all indices up to and including this index */
        if (last_hvc < index)
                last_hvc = index;
 
@@ -278,7 +279,6 @@ int hvc_instantiate(uint32_t vtermno, int index, struct hv_ops *ops)
 
        return 0;
 }
-EXPORT_SYMBOL(hvc_instantiate);
 
 /* Wake the sleeping khvcd */
 static void hvc_kick(void)
@@ -293,7 +293,7 @@ static int hvc_poll(struct hvc_struct *hp);
  * NOTE: This API isn't used if the console adapter doesn't support interrupts.
  * In this case the console is poll driven.
  */
-static irqreturn_t hvc_handle_interrupt(int irq, void *dev_instance, struct pt_regs *regs)
+static irqreturn_t hvc_handle_interrupt(int irq, void *dev_instance)
 {
        /* if hvc_poll request a repoll, then kick the hvcd thread */
        if (hvc_poll(dev_instance))
@@ -314,15 +314,13 @@ static int hvc_open(struct tty_struct *tty, struct file * filp)
 {
        struct hvc_struct *hp;
        unsigned long flags;
-       int irq = NO_IRQ;
+       int irq = 0;
        int rc = 0;
        struct kobject *kobjp;
 
        /* Auto increments kobject reference if found. */
-       if (!(hp = hvc_get_by_index(tty->index))) {
-               printk(KERN_WARNING "hvc_console: tty open failed, no vty associated with tty.\n");
+       if (!(hp = hvc_get_by_index(tty->index)))
                return -ENODEV;
-       }
 
        spin_lock_irqsave(&hp->lock, flags);
        /* Check and then increment for fast path open. */
@@ -338,14 +336,14 @@ static int hvc_open(struct tty_struct *tty, struct file * filp)
        hp->tty = tty;
        /* Save for request_irq outside of spin_lock. */
        irq = hp->irq;
-       if (irq != NO_IRQ)
+       if (irq)
                hp->irq_requested = 1;
 
        kobjp = &hp->kobj;
 
        spin_unlock_irqrestore(&hp->lock, flags);
        /* check error, fallback to non-irq */
-       if (irq != NO_IRQ)
+       if (irq)
                rc = request_irq(irq, hvc_handle_interrupt, IRQF_DISABLED, "hvc_console", hp);
 
        /*
@@ -373,7 +371,7 @@ static void hvc_close(struct tty_struct *tty, struct file * filp)
 {
        struct hvc_struct *hp;
        struct kobject *kobjp;
-       int irq = NO_IRQ;
+       int irq = 0;
        unsigned long flags;
 
        if (tty_hung_up_p(filp))
@@ -407,7 +405,7 @@ static void hvc_close(struct tty_struct *tty, struct file * filp)
                 */
                tty_wait_until_sent(tty, HVC_CLOSE_WAIT);
 
-               if (irq != NO_IRQ)
+               if (irq)
                        free_irq(irq, hp);
 
        } else {
@@ -424,7 +422,7 @@ static void hvc_hangup(struct tty_struct *tty)
 {
        struct hvc_struct *hp = tty->driver_data;
        unsigned long flags;
-       int irq = NO_IRQ;
+       int irq = 0;
        int temp_open_count;
        struct kobject *kobjp;
 
@@ -453,7 +451,7 @@ static void hvc_hangup(struct tty_struct *tty)
                irq = hp->irq;
        hp->irq_requested = 0;
        spin_unlock_irqrestore(&hp->lock, flags);
-       if (irq != NO_IRQ)
+       if (irq)
                free_irq(irq, hp);
        while(temp_open_count) {
                --temp_open_count;
@@ -505,7 +503,7 @@ static int hvc_write(struct tty_struct *tty, const unsigned char *buf, int count
        if (hp->n_outbuf > 0)
                hvc_push(hp);
 
-       while (count > 0 && (rsize = N_OUTBUF - hp->n_outbuf) > 0) {
+       while (count > 0 && (rsize = hp->outbuf_size - hp->n_outbuf) > 0) {
                if (rsize > count)
                        rsize = count;
                memcpy(hp->outbuf + hp->n_outbuf, buf, rsize);
@@ -528,7 +526,7 @@ static int hvc_write(struct tty_struct *tty, const unsigned char *buf, int count
 
 /*
  * This is actually a contract between the driver and the tty layer outlining
- * how much write room the driver can guarentee will be sent OR BUFFERED.  This
+ * how much write room the driver can guarantee will be sent OR BUFFERED.  This
  * driver MUST honor the return value.
  */
 static int hvc_write_room(struct tty_struct *tty)
@@ -538,7 +536,7 @@ static int hvc_write_room(struct tty_struct *tty)
        if (!hp)
                return -1;
 
-       return N_OUTBUF - hp->n_outbuf;
+       return hp->outbuf_size - hp->n_outbuf;
 }
 
 static int hvc_chars_in_buffer(struct tty_struct *tty)
@@ -550,6 +548,18 @@ static int hvc_chars_in_buffer(struct tty_struct *tty)
        return hp->n_outbuf;
 }
 
+/*
+ * timeout will vary between the MIN and MAX values defined here.  By default
+ * and during console activity we will use a default MIN_TIMEOUT of 10.  When
+ * the console is idle, we increase the timeout value on each pass through
+ * msleep until we reach the max.  This may be noticeable as a brief (average
+ * one second) delay on the console before the console responds to input when
+ * there has been no input for some time.
+ */
+#define MIN_TIMEOUT            (10)
+#define MAX_TIMEOUT            (2000)
+static u32 timeout = MIN_TIMEOUT;
+
 #define HVC_POLL_READ  0x00000001
 #define HVC_POLL_WRITE 0x00000002
 
@@ -583,7 +593,7 @@ static int hvc_poll(struct hvc_struct *hp)
        /* If we aren't interrupt driven and aren't throttled, we always
         * request a reschedule
         */
-       if (hp->irq == NO_IRQ)
+       if (hp->irq == 0)
                poll_mask |= HVC_POLL_READ;
 
        /* Read data if any */
@@ -622,7 +632,7 @@ static int hvc_poll(struct hvc_struct *hp)
                                        sysrq_pressed = 1;
                                        continue;
                                } else if (sysrq_pressed) {
-                                       handle_sysrq(buf[i], NULL, tty);
+                                       handle_sysrq(buf[i], tty);
                                        sysrq_pressed = 0;
                                        continue;
                                }
@@ -642,9 +652,14 @@ static int hvc_poll(struct hvc_struct *hp)
  bail:
        spin_unlock_irqrestore(&hp->lock, flags);
 
-       if (read_total)
+       if (read_total) {
+               /* Activity is occurring, so reset the polling backoff value to
+                  a minimum for performance. */
+               timeout = MIN_TIMEOUT;
+
                tty_flip_buffer_push(tty);
-       
+       }
+
        return poll_mask;
 }
 
@@ -659,15 +674,17 @@ static const cpumask_t cpus_in_xmon = CPU_MASK_NONE;
  * calling hvc_poll() who determines whether a console adapter support
  * interrupts.
  */
-int khvcd(void *unused)
+static int khvcd(void *unused)
 {
        int poll_mask;
        struct hvc_struct *hp;
 
+       set_freezable();
        __set_current_state(TASK_RUNNING);
        do {
                poll_mask = 0;
                hvc_kicked = 0;
+               try_to_freeze();
                wmb();
                if (cpus_empty(cpus_in_xmon)) {
                        spin_lock(&hvc_structs_lock);
@@ -687,8 +704,12 @@ int khvcd(void *unused)
                if (!hvc_kicked) {
                        if (poll_mask == 0)
                                schedule();
-                       else
-                               msleep_interruptible(TIMEOUT);
+                       else {
+                               if (timeout < MAX_TIMEOUT)
+                                       timeout += (timeout >> 6) + 1;
+
+                               msleep_interruptible(timeout);
+                       }
                }
                __set_current_state(TASK_RUNNING);
        } while (!kthread_should_stop());
@@ -696,7 +717,7 @@ int khvcd(void *unused)
        return 0;
 }
 
-static struct tty_operations hvc_ops = {
+static const struct tty_operations hvc_ops = {
        .open = hvc_open,
        .close = hvc_close,
        .write = hvc_write,
@@ -728,12 +749,13 @@ static struct kobj_type hvc_kobj_type = {
 };
 
 struct hvc_struct __devinit *hvc_alloc(uint32_t vtermno, int irq,
-                                       struct hv_ops *ops)
+                                       struct hv_ops *ops, int outbuf_size)
 {
        struct hvc_struct *hp;
        int i;
 
-       hp = kmalloc(sizeof(*hp), GFP_KERNEL);
+       hp = kmalloc(ALIGN(sizeof(*hp), sizeof(long)) + outbuf_size,
+                       GFP_KERNEL);
        if (!hp)
                return ERR_PTR(-ENOMEM);
 
@@ -742,6 +764,8 @@ struct hvc_struct __devinit *hvc_alloc(uint32_t vtermno, int irq,
        hp->vtermno = vtermno;
        hp->irq = irq;
        hp->ops = ops;
+       hp->outbuf_size = outbuf_size;
+       hp->outbuf = &((char *)hp)[ALIGN(sizeof(*hp), sizeof(long))];
 
        kobject_init(&hp->kobj);
        hp->kobj.ktype = &hvc_kobj_type;
@@ -769,7 +793,6 @@ struct hvc_struct __devinit *hvc_alloc(uint32_t vtermno, int irq,
 
        return hp;
 }
-EXPORT_SYMBOL(hvc_alloc);
 
 int __devexit hvc_remove(struct hvc_struct *hp)
 {
@@ -790,7 +813,7 @@ int __devexit hvc_remove(struct hvc_struct *hp)
 
        /*
         * We 'put' the instance that was grabbed when the kobject instance
-        * was intialized using kobject_init().  Let the last holder of this
+        * was initialized using kobject_init().  Let the last holder of this
         * kobject cause it to be removed, which will probably be the tty_hangup
         * below.
         */
@@ -805,11 +828,10 @@ int __devexit hvc_remove(struct hvc_struct *hp)
                tty_hangup(tty);
        return 0;
 }
-EXPORT_SYMBOL(hvc_remove);
 
 /* Driver initialization.  Follow console initialization.  This is where the TTY
  * interfaces start to become available. */
-int __init hvc_init(void)
+static int __init hvc_init(void)
 {
        struct tty_driver *drv;
 
@@ -846,7 +868,7 @@ int __init hvc_init(void)
 }
 module_init(hvc_init);
 
-/* This isn't particularily necessary due to this being a console driver
+/* This isn't particularly necessary due to this being a console driver
  * but it is nice to be thorough.
  */
 static void __exit hvc_exit(void)