aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/char/hvc_console.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/char/hvc_console.c')
-rw-r--r--drivers/char/hvc_console.c69
1 files changed, 29 insertions, 40 deletions
diff --git a/drivers/char/hvc_console.c b/drivers/char/hvc_console.c
index a94c5b0cac52..2b6a56b2bf35 100644
--- a/drivers/char/hvc_console.c
+++ b/drivers/char/hvc_console.c
@@ -39,8 +39,10 @@
39#include <linux/sched.h> 39#include <linux/sched.h>
40#include <linux/spinlock.h> 40#include <linux/spinlock.h>
41#include <linux/delay.h> 41#include <linux/delay.h>
42
42#include <asm/uaccess.h> 43#include <asm/uaccess.h>
43#include <asm/hvconsole.h> 44
45#include "hvc_console.h"
44 46
45#define HVC_MAJOR 229 47#define HVC_MAJOR 229
46#define HVC_MINOR 0 48#define HVC_MINOR 0
@@ -54,17 +56,14 @@
54#define HVC_CLOSE_WAIT (HZ/100) /* 1/10 of a second */ 56#define HVC_CLOSE_WAIT (HZ/100) /* 1/10 of a second */
55 57
56/* 58/*
57 * The Linux TTY code does not support dynamic addition of tty derived devices 59 * These sizes are most efficient for vio, because they are the
58 * so we need to know how many tty devices we might need when space is allocated 60 * native transfer size. We could make them selectable in the
59 * for the tty device. Since this driver supports hotplug of vty adapters we 61 * future to better deal with backends that want other buffer sizes.
60 * need to make sure we have enough allocated.
61 */ 62 */
62#define HVC_ALLOC_TTY_ADAPTERS 8
63
64#define N_OUTBUF 16 63#define N_OUTBUF 16
65#define N_INBUF 16 64#define N_INBUF 16
66 65
67#define __ALIGNED__ __attribute__((__aligned__(8))) 66#define __ALIGNED__ __attribute__((__aligned__(sizeof(long))))
68 67
69static struct tty_driver *hvc_driver; 68static struct tty_driver *hvc_driver;
70static struct task_struct *hvc_task; 69static struct task_struct *hvc_task;
@@ -154,7 +153,7 @@ static uint32_t vtermnos[MAX_NR_HVC_CONSOLES] =
154 153
155void hvc_console_print(struct console *co, const char *b, unsigned count) 154void hvc_console_print(struct console *co, const char *b, unsigned count)
156{ 155{
157 char c[16] __ALIGNED__; 156 char c[N_OUTBUF] __ALIGNED__;
158 unsigned i = 0, n = 0; 157 unsigned i = 0, n = 0;
159 int r, donecr = 0, index = co->index; 158 int r, donecr = 0, index = co->index;
160 159
@@ -473,8 +472,10 @@ static void hvc_push(struct hvc_struct *hp)
473 472
474 n = hp->ops->put_chars(hp->vtermno, hp->outbuf, hp->n_outbuf); 473 n = hp->ops->put_chars(hp->vtermno, hp->outbuf, hp->n_outbuf);
475 if (n <= 0) { 474 if (n <= 0) {
476 if (n == 0) 475 if (n == 0) {
476 hp->do_wakeup = 1;
477 return; 477 return;
478 }
478 /* throw away output on error; this happens when 479 /* throw away output on error; this happens when
479 there is no session connected to the vterm. */ 480 there is no session connected to the vterm. */
480 hp->n_outbuf = 0; 481 hp->n_outbuf = 0;
@@ -486,12 +487,19 @@ static void hvc_push(struct hvc_struct *hp)
486 hp->do_wakeup = 1; 487 hp->do_wakeup = 1;
487} 488}
488 489
489static inline int __hvc_write_kernel(struct hvc_struct *hp, 490static int hvc_write(struct tty_struct *tty, const unsigned char *buf, int count)
490 const unsigned char *buf, int count)
491{ 491{
492 struct hvc_struct *hp = tty->driver_data;
492 unsigned long flags; 493 unsigned long flags;
493 int rsize, written = 0; 494 int rsize, written = 0;
494 495
496 /* This write was probably executed during a tty close. */
497 if (!hp)
498 return -EPIPE;
499
500 if (hp->count <= 0)
501 return -EIO;
502
495 spin_lock_irqsave(&hp->lock, flags); 503 spin_lock_irqsave(&hp->lock, flags);
496 504
497 /* Push pending writes */ 505 /* Push pending writes */
@@ -510,26 +518,8 @@ static inline int __hvc_write_kernel(struct hvc_struct *hp,
510 } 518 }
511 spin_unlock_irqrestore(&hp->lock, flags); 519 spin_unlock_irqrestore(&hp->lock, flags);
512 520
513 return written;
514}
515static int hvc_write(struct tty_struct *tty, const unsigned char *buf, int count)
516{
517 struct hvc_struct *hp = tty->driver_data;
518 int written;
519
520 /* This write was probably executed during a tty close. */
521 if (!hp)
522 return -EPIPE;
523
524 if (hp->count <= 0)
525 return -EIO;
526
527 written = __hvc_write_kernel(hp, buf, count);
528
529 /* 521 /*
530 * Racy, but harmless, kick thread if there is still pending data. 522 * Racy, but harmless, kick thread if there is still pending data.
531 * There really is nothing wrong with kicking the thread, even if there
532 * is no buffered data.
533 */ 523 */
534 if (hp->n_outbuf) 524 if (hp->n_outbuf)
535 hvc_kick(); 525 hvc_kick();
@@ -614,6 +604,13 @@ static int hvc_poll(struct hvc_struct *hp)
614 spin_unlock_irqrestore(&hp->lock, flags); 604 spin_unlock_irqrestore(&hp->lock, flags);
615 tty_hangup(tty); 605 tty_hangup(tty);
616 spin_lock_irqsave(&hp->lock, flags); 606 spin_lock_irqsave(&hp->lock, flags);
607 } else if ( n == -EAGAIN ) {
608 /*
609 * Some back-ends can only ensure a certain min
610 * num of bytes read, which may be > 'count'.
611 * Let the tty clear the flip buff to make room.
612 */
613 poll_mask |= HVC_POLL_READ;
617 } 614 }
618 break; 615 break;
619 } 616 }
@@ -635,16 +632,7 @@ static int hvc_poll(struct hvc_struct *hp)
635 tty_insert_flip_char(tty, buf[i], 0); 632 tty_insert_flip_char(tty, buf[i], 0);
636 } 633 }
637 634
638 /*
639 * Account for the total amount read in one loop, and if above
640 * 64 bytes, we do a quick schedule loop to let the tty grok
641 * the data and eventually throttle us.
642 */
643 read_total += n; 635 read_total += n;
644 if (read_total >= 64) {
645 poll_mask |= HVC_POLL_QUICK;
646 break;
647 }
648 } 636 }
649 throttled: 637 throttled:
650 /* Wakeup write queue if necessary */ 638 /* Wakeup write queue if necessary */
@@ -767,7 +755,8 @@ struct hvc_struct __devinit *hvc_alloc(uint32_t vtermno, int irq,
767 * see if this vterm id matches one registered for console. 755 * see if this vterm id matches one registered for console.
768 */ 756 */
769 for (i=0; i < MAX_NR_HVC_CONSOLES; i++) 757 for (i=0; i < MAX_NR_HVC_CONSOLES; i++)
770 if (vtermnos[i] == hp->vtermno) 758 if (vtermnos[i] == hp->vtermno &&
759 cons_ops[i] == hp->ops)
771 break; 760 break;
772 761
773 /* no matching slot, just use a counter */ 762 /* no matching slot, just use a counter */