--- /dev/null
+From 26d766c60f4ea08cd14f0f3435a6db3d6cc2ae96 Mon Sep 17 00:00:00 2001
+From: Martin Schwidefsky <schwidefsky@de.ibm.com>
+Date: Tue, 15 Jul 2014 17:53:12 +0200
+Subject: s390/3215: fix hanging console issue
+
+From: Martin Schwidefsky <schwidefsky@de.ibm.com>
+
+commit 26d766c60f4ea08cd14f0f3435a6db3d6cc2ae96 upstream.
+
+The ccw_device_start in raw3215_start_io can fail. raw3215_try_io
+does not check if the request could be started and removes any
+pending timer. This can leave the system in a hanging state.
+Check for pending request after raw3215_start_io and start a
+timer if necessary.
+
+Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/s390/char/con3215.c | 32 +++++++++++++++++---------------
+ 1 file changed, 17 insertions(+), 15 deletions(-)
+
+--- a/drivers/s390/char/con3215.c
++++ b/drivers/s390/char/con3215.c
+@@ -288,12 +288,16 @@ static void raw3215_timeout(unsigned lon
+ unsigned long flags;
+
+ spin_lock_irqsave(get_ccwdev_lock(raw->cdev), flags);
+- if (raw->flags & RAW3215_TIMER_RUNS) {
+- del_timer(&raw->timer);
+- raw->flags &= ~RAW3215_TIMER_RUNS;
+- if (!(raw->port.flags & ASYNC_SUSPENDED)) {
+- raw3215_mk_write_req(raw);
+- raw3215_start_io(raw);
++ raw->flags &= ~RAW3215_TIMER_RUNS;
++ if (!(raw->port.flags & ASYNC_SUSPENDED)) {
++ raw3215_mk_write_req(raw);
++ raw3215_start_io(raw);
++ if ((raw->queued_read || raw->queued_write) &&
++ !(raw->flags & RAW3215_WORKING) &&
++ !(raw->flags & RAW3215_TIMER_RUNS)) {
++ raw->timer.expires = RAW3215_TIMEOUT + jiffies;
++ add_timer(&raw->timer);
++ raw->flags |= RAW3215_TIMER_RUNS;
+ }
+ }
+ spin_unlock_irqrestore(get_ccwdev_lock(raw->cdev), flags);
+@@ -317,17 +321,15 @@ static inline void raw3215_try_io(struct
+ (raw->flags & RAW3215_FLUSHING)) {
+ /* execute write requests bigger than minimum size */
+ raw3215_start_io(raw);
+- if (raw->flags & RAW3215_TIMER_RUNS) {
+- del_timer(&raw->timer);
+- raw->flags &= ~RAW3215_TIMER_RUNS;
+- }
+- } else if (!(raw->flags & RAW3215_TIMER_RUNS)) {
+- /* delay small writes */
+- raw->timer.expires = RAW3215_TIMEOUT + jiffies;
+- add_timer(&raw->timer);
+- raw->flags |= RAW3215_TIMER_RUNS;
+ }
+ }
++ if ((raw->queued_read || raw->queued_write) &&
++ !(raw->flags & RAW3215_WORKING) &&
++ !(raw->flags & RAW3215_TIMER_RUNS)) {
++ raw->timer.expires = RAW3215_TIMEOUT + jiffies;
++ add_timer(&raw->timer);
++ raw->flags |= RAW3215_TIMER_RUNS;
++ }
+ }
+
+ /*
--- /dev/null
+From e512d56c799517f33b301d81e9a5e0ebf30c2d1e Mon Sep 17 00:00:00 2001
+From: Martin Schwidefsky <schwidefsky@de.ibm.com>
+Date: Wed, 13 Aug 2014 12:01:30 +0200
+Subject: s390/3215: fix tty output containing tabs
+
+From: Martin Schwidefsky <schwidefsky@de.ibm.com>
+
+commit e512d56c799517f33b301d81e9a5e0ebf30c2d1e upstream.
+
+git commit 37f81fa1f63ad38e16125526bb2769ae0ea8d332
+"n_tty: do O_ONLCR translation as a single write"
+surfaced a bug in the 3215 device driver. In combination this
+broke tab expansion for tty ouput.
+
+The cause is an asymmetry in the behaviour of tty3215_ops->write
+vs tty3215_ops->put_char. The put_char function scans for '\t'
+but the write function does not.
+
+As the driver has logic for the '\t' expansion remove XTABS
+from c_oflag of the initial termios as well.
+
+Reported-by: Stephen Powell <zlinuxman@wowway.com>
+Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/s390/char/con3215.c | 20 +++++++++++++++++---
+ 1 file changed, 17 insertions(+), 3 deletions(-)
+
+--- a/drivers/s390/char/con3215.c
++++ b/drivers/s390/char/con3215.c
+@@ -1029,12 +1029,26 @@ static int tty3215_write(struct tty_stru
+ const unsigned char *buf, int count)
+ {
+ struct raw3215_info *raw;
++ int i, written;
+
+ if (!tty)
+ return 0;
+ raw = (struct raw3215_info *) tty->driver_data;
+- raw3215_write(raw, buf, count);
+- return count;
++ written = count;
++ while (count > 0) {
++ for (i = 0; i < count; i++)
++ if (buf[i] == '\t' || buf[i] == '\n')
++ break;
++ raw3215_write(raw, buf, i);
++ count -= i;
++ buf += i;
++ if (count > 0) {
++ raw3215_putchar(raw, *buf);
++ count--;
++ buf++;
++ }
++ }
++ return written;
+ }
+
+ /*
+@@ -1182,7 +1196,7 @@ static int __init tty3215_init(void)
+ driver->subtype = SYSTEM_TYPE_TTY;
+ driver->init_termios = tty_std_termios;
+ driver->init_termios.c_iflag = IGNBRK | IGNPAR;
+- driver->init_termios.c_oflag = ONLCR | XTABS;
++ driver->init_termios.c_oflag = ONLCR;
+ driver->init_termios.c_lflag = ISIG;
+ driver->flags = TTY_DRIVER_REAL_RAW;
+ tty_set_operations(driver, &tty3215_ops);