diff options
Diffstat (limited to 'drivers/s390/char')
-rw-r--r-- | drivers/s390/char/sclp_tty.c | 36 |
1 files changed, 17 insertions, 19 deletions
diff --git a/drivers/s390/char/sclp_tty.c b/drivers/s390/char/sclp_tty.c index bcf691af5336..434ba04b1309 100644 --- a/drivers/s390/char/sclp_tty.c +++ b/drivers/s390/char/sclp_tty.c @@ -13,7 +13,6 @@ #include <linux/tty.h> #include <linux/tty_driver.h> #include <linux/tty_flip.h> -#include <linux/wait.h> #include <linux/slab.h> #include <linux/err.h> #include <linux/init.h> @@ -48,8 +47,6 @@ static int sclp_tty_buffer_count; static struct sclp_buffer *sclp_ttybuf; /* Timer for delayed output of console messages. */ static struct timer_list sclp_tty_timer; -/* Waitqueue to wait for buffers to get empty. */ -static wait_queue_head_t sclp_tty_waitq; static struct tty_struct *sclp_tty; static unsigned char sclp_tty_chars[SCLP_TTY_BUF_SIZE]; @@ -128,7 +125,6 @@ sclp_ttybuf_callback(struct sclp_buffer *buffer, int rc) struct sclp_buffer, list); spin_unlock_irqrestore(&sclp_tty_lock, flags); } while (buffer && sclp_emit_buffer(buffer, sclp_ttybuf_callback)); - wake_up(&sclp_tty_waitq); /* check if the tty needs a wake up call */ if (sclp_tty != NULL) { tty_wakeup(sclp_tty); @@ -176,27 +172,27 @@ sclp_tty_timeout(unsigned long data) /* * Write a string to the sclp tty. */ -static void -sclp_tty_write_string(const unsigned char *str, int count) +static int sclp_tty_write_string(const unsigned char *str, int count, int may_fail) { unsigned long flags; void *page; int written; + int overall_written; struct sclp_buffer *buf; if (count <= 0) - return; + return 0; + overall_written = 0; spin_lock_irqsave(&sclp_tty_lock, flags); do { /* Create a sclp output buffer if none exists yet */ if (sclp_ttybuf == NULL) { while (list_empty(&sclp_tty_pages)) { spin_unlock_irqrestore(&sclp_tty_lock, flags); - if (in_interrupt()) - sclp_sync_wait(); + if (may_fail) + goto out; else - wait_event(sclp_tty_waitq, - !list_empty(&sclp_tty_pages)); + sclp_sync_wait(); spin_lock_irqsave(&sclp_tty_lock, flags); } page = sclp_tty_pages.next; @@ -206,6 +202,7 @@ sclp_tty_write_string(const unsigned char *str, int count) } /* try to write the string to the current output buffer */ written = sclp_write(sclp_ttybuf, str, count); + overall_written += written; if (written == count) break; /* @@ -231,6 +228,8 @@ sclp_tty_write_string(const unsigned char *str, int count) add_timer(&sclp_tty_timer); } spin_unlock_irqrestore(&sclp_tty_lock, flags); +out: + return overall_written; } /* @@ -242,11 +241,10 @@ static int sclp_tty_write(struct tty_struct *tty, const unsigned char *buf, int count) { if (sclp_tty_chars_count > 0) { - sclp_tty_write_string(sclp_tty_chars, sclp_tty_chars_count); + sclp_tty_write_string(sclp_tty_chars, sclp_tty_chars_count, 0); sclp_tty_chars_count = 0; } - sclp_tty_write_string(buf, count); - return count; + return sclp_tty_write_string(buf, count, 1); } /* @@ -264,9 +262,10 @@ sclp_tty_put_char(struct tty_struct *tty, unsigned char ch) { sclp_tty_chars[sclp_tty_chars_count++] = ch; if (ch == '\n' || sclp_tty_chars_count >= SCLP_TTY_BUF_SIZE) { - sclp_tty_write_string(sclp_tty_chars, sclp_tty_chars_count); + sclp_tty_write_string(sclp_tty_chars, sclp_tty_chars_count, 0); sclp_tty_chars_count = 0; - } return 1; + } + return 1; } /* @@ -277,7 +276,7 @@ static void sclp_tty_flush_chars(struct tty_struct *tty) { if (sclp_tty_chars_count > 0) { - sclp_tty_write_string(sclp_tty_chars, sclp_tty_chars_count); + sclp_tty_write_string(sclp_tty_chars, sclp_tty_chars_count, 0); sclp_tty_chars_count = 0; } } @@ -316,7 +315,7 @@ static void sclp_tty_flush_buffer(struct tty_struct *tty) { if (sclp_tty_chars_count > 0) { - sclp_tty_write_string(sclp_tty_chars, sclp_tty_chars_count); + sclp_tty_write_string(sclp_tty_chars, sclp_tty_chars_count, 0); sclp_tty_chars_count = 0; } } @@ -577,7 +576,6 @@ sclp_tty_init(void) } INIT_LIST_HEAD(&sclp_tty_outqueue); spin_lock_init(&sclp_tty_lock); - init_waitqueue_head(&sclp_tty_waitq); init_timer(&sclp_tty_timer); sclp_ttybuf = NULL; sclp_tty_buffer_count = 0; |