70 lines
2.5 KiB
Diff
70 lines
2.5 KiB
Diff
From: Martin Schwidefsky <schwidefsky@de.ibm.com>
|
|
Date: Tue, 15 Jul 2014 17:53:12 +0200
|
|
Subject: s390/3215: fix hanging console issue
|
|
Origin: https://git.kernel.org/cgit/linux/kernel/git/s390/linux.git/commit?id=26d766c60f4ea08cd14f0f3435a6db3d6cc2ae96
|
|
Bug-Debian: https://bugs.debian.org/747922
|
|
|
|
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>
|
|
---
|
|
drivers/s390/char/con3215.c | 32 +++++++++++++++++---------------
|
|
1 file changed, 17 insertions(+), 15 deletions(-)
|
|
|
|
diff --git a/drivers/s390/char/con3215.c b/drivers/s390/char/con3215.c
|
|
index 5af7f0b..a6d47e5 100644
|
|
--- a/drivers/s390/char/con3215.c
|
|
+++ b/drivers/s390/char/con3215.c
|
|
@@ -288,12 +288,16 @@ static void raw3215_timeout(unsigned long __data)
|
|
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 raw3215_info *raw)
|
|
(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;
|
|
+ }
|
|
}
|
|
|
|
/*
|