summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/s390/char/sclp.c5
-rw-r--r--drivers/s390/char/sclp_con.c3
-rw-r--r--drivers/s390/char/sclp_rw.c2
-rw-r--r--drivers/s390/char/sclp_tty.c24
4 files changed, 24 insertions, 10 deletions
diff --git a/drivers/s390/char/sclp.c b/drivers/s390/char/sclp.c
index 2aaf356845ac..0e5fc8964479 100644
--- a/drivers/s390/char/sclp.c
+++ b/drivers/s390/char/sclp.c
@@ -315,8 +315,9 @@ sclp_interrupt_handler(struct pt_regs *regs, __u16 code)
/* Head queue a read sccb if an event buffer is pending */
if (evbuf_pending)
__sclp_unconditional_read();
- /* Now clear the running bit */
- clear_bit(SCLP_RUNNING, &sclp_status);
+ /* Now clear the running bit if SCLP indicated a finished SCCB */
+ if (finished_sccb != 0U)
+ clear_bit(SCLP_RUNNING, &sclp_status);
spin_unlock(&sclp_lock);
/* and start next request on the queue */
sclp_start_request();
diff --git a/drivers/s390/char/sclp_con.c b/drivers/s390/char/sclp_con.c
index d393ab443057..5a76bea84aa3 100644
--- a/drivers/s390/char/sclp_con.c
+++ b/drivers/s390/char/sclp_con.c
@@ -149,7 +149,8 @@ sclp_console_write(struct console *console, const char *message,
count -= written;
} while (count > 0);
/* Setup timer to output current console buffer after 1/10 second */
- if (sclp_conbuf != NULL && !timer_pending(&sclp_con_timer)) {
+ if (sclp_conbuf != NULL && sclp_chars_in_buffer(sclp_conbuf) != 0 &&
+ !timer_pending(&sclp_con_timer)) {
init_timer(&sclp_con_timer);
sclp_con_timer.function = sclp_console_timeout;
sclp_con_timer.data = 0UL;
diff --git a/drivers/s390/char/sclp_rw.c b/drivers/s390/char/sclp_rw.c
index b4cdc4e42da7..296f60d95ef6 100644
--- a/drivers/s390/char/sclp_rw.c
+++ b/drivers/s390/char/sclp_rw.c
@@ -274,7 +274,7 @@ sclp_write(struct sclp_buffer *buffer, const unsigned char *msg, int count)
if (buffer->current_line != NULL)
sclp_finalize_mto(buffer);
/* skip the rest of the message including the 0 byte */
- i_msg = count;
+ i_msg = count - 1;
break;
default: /* no escape character */
/* do not output unprintable characters */
diff --git a/drivers/s390/char/sclp_tty.c b/drivers/s390/char/sclp_tty.c
index 94daea2fb396..d9c5911bf4f9 100644
--- a/drivers/s390/char/sclp_tty.c
+++ b/drivers/s390/char/sclp_tty.c
@@ -18,6 +18,7 @@
#include <linux/slab.h>
#include <linux/err.h>
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <asm/uaccess.h>
#include "ctrlchar.h"
@@ -337,8 +338,11 @@ sclp_tty_write_string(const unsigned char *str, int count)
if (sclp_ttybuf == NULL) {
while (list_empty(&sclp_tty_pages)) {
spin_unlock_irqrestore(&sclp_tty_lock, flags);
- wait_event(sclp_tty_waitq,
- !list_empty(&sclp_tty_pages));
+ if (in_interrupt())
+ sclp_sync_wait();
+ else
+ wait_event(sclp_tty_waitq,
+ !list_empty(&sclp_tty_pages));
spin_lock_irqsave(&sclp_tty_lock, flags);
}
page = sclp_tty_pages.next;
@@ -366,7 +370,9 @@ sclp_tty_write_string(const unsigned char *str, int count)
} while (count > 0);
/* Setup timer to output current console buffer after 1/10 second */
if (sclp_ioctls.final_nl) {
- if (sclp_ttybuf != NULL && !timer_pending(&sclp_tty_timer)) {
+ if (sclp_ttybuf != NULL &&
+ sclp_chars_in_buffer(sclp_ttybuf) != 0 &&
+ !timer_pending(&sclp_tty_timer)) {
init_timer(&sclp_tty_timer);
sclp_tty_timer.function = sclp_tty_timeout;
sclp_tty_timer.data = 0UL;
@@ -374,8 +380,14 @@ sclp_tty_write_string(const unsigned char *str, int count)
add_timer(&sclp_tty_timer);
}
} else {
- __sclp_ttybuf_emit(sclp_ttybuf);
- sclp_ttybuf = NULL;
+ if (sclp_ttybuf != NULL &&
+ sclp_chars_in_buffer(sclp_ttybuf) != 0) {
+ buf = sclp_ttybuf;
+ sclp_ttybuf = NULL;
+ spin_unlock_irqrestore(&sclp_tty_lock, flags);
+ __sclp_ttybuf_emit(buf);
+ spin_lock_irqsave(&sclp_tty_lock, flags);
+ }
}
spin_unlock_irqrestore(&sclp_tty_lock, flags);
}
@@ -471,7 +483,7 @@ sclp_tty_chars_in_buffer(struct tty_struct *tty)
count = sclp_chars_in_buffer(sclp_ttybuf);
list_for_each(l, &sclp_tty_outqueue) {
t = list_entry(l, struct sclp_buffer, list);
- count += sclp_chars_in_buffer(sclp_ttybuf);
+ count += sclp_chars_in_buffer(t);
}
spin_unlock_irqrestore(&sclp_tty_lock, flags);
return count;