diff options
| -rw-r--r-- | drivers/s390/char/sclp.c | 5 | ||||
| -rw-r--r-- | drivers/s390/char/sclp_con.c | 3 | ||||
| -rw-r--r-- | drivers/s390/char/sclp_rw.c | 2 | ||||
| -rw-r--r-- | drivers/s390/char/sclp_tty.c | 24 |
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; |
