[S390] dasd: fix idaw boundary checking for track based ccw
[cascardo/linux.git] / drivers / s390 / char / sclp_tty.c
index bcf691a..434ba04 100644 (file)
@@ -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;