Commit b3ff4326 authored by Martin Schwidefsky's avatar Martin Schwidefsky Committed by Luis Henriques

s390/3215: fix hanging console issue

commit 26d766c6 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: default avatarMartin Schwidefsky <schwidefsky@de.ibm.com>
Cc: Ben Hutchings <ben@decadent.org.uk>
Signed-off-by: default avatarLuis Henriques <luis.henriques@canonical.com>
parent e6277430
...@@ -288,12 +288,16 @@ static void raw3215_timeout(unsigned long __data) ...@@ -288,12 +288,16 @@ static void raw3215_timeout(unsigned long __data)
unsigned long flags; unsigned long flags;
spin_lock_irqsave(get_ccwdev_lock(raw->cdev), flags); spin_lock_irqsave(get_ccwdev_lock(raw->cdev), flags);
if (raw->flags & RAW3215_TIMER_RUNS) { raw->flags &= ~RAW3215_TIMER_RUNS;
del_timer(&raw->timer); if (!(raw->port.flags & ASYNC_SUSPENDED)) {
raw->flags &= ~RAW3215_TIMER_RUNS; raw3215_mk_write_req(raw);
if (!(raw->port.flags & ASYNC_SUSPENDED)) { raw3215_start_io(raw);
raw3215_mk_write_req(raw); if ((raw->queued_read || raw->queued_write) &&
raw3215_start_io(raw); !(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); spin_unlock_irqrestore(get_ccwdev_lock(raw->cdev), flags);
...@@ -317,17 +321,15 @@ static inline void raw3215_try_io(struct raw3215_info *raw) ...@@ -317,17 +321,15 @@ static inline void raw3215_try_io(struct raw3215_info *raw)
(raw->flags & RAW3215_FLUSHING)) { (raw->flags & RAW3215_FLUSHING)) {
/* execute write requests bigger than minimum size */ /* execute write requests bigger than minimum size */
raw3215_start_io(raw); 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;
}
} }
/* /*
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment