Freezer: make kernel threads nonfreezable by default
[safe/jmp/linux-2.6] / drivers / char / hvc_console.c
index 4053d1c..83c1151 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.
@@ -103,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;
@@ -151,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;
@@ -161,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;
 
@@ -209,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,
@@ -219,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
@@ -256,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);
@@ -266,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;
 
@@ -279,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)
@@ -294,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))
@@ -315,7 +314,7 @@ 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;
 
@@ -337,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);
 
        /*
@@ -372,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))
@@ -406,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 {
@@ -423,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;
 
@@ -452,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;
@@ -527,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)
@@ -549,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
 
@@ -582,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 */
@@ -621,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;
                                }
@@ -641,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;
 }
 
@@ -658,11 +674,12 @@ 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;
@@ -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());
@@ -772,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)
 {
@@ -793,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.
         */
@@ -808,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;
 
@@ -849,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)