aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/s390
diff options
context:
space:
mode:
authorMartin Schwidefsky <schwidefsky@de.ibm.com>2014-07-15 11:53:12 -0400
committerMartin Schwidefsky <schwidefsky@de.ibm.com>2014-07-28 04:02:39 -0400
commit26d766c60f4ea08cd14f0f3435a6db3d6cc2ae96 (patch)
treeae07e275a923cb86018da35c1cb0ef984bfb4a00 /drivers/s390
parente2213e04c1b1e44a09a9d05b79809b7e63c9217e (diff)
s390/3215: fix hanging console issue
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>
Diffstat (limited to 'drivers/s390')
-rw-r--r--drivers/s390/char/con3215.c32
1 files changed, 17 insertions, 15 deletions
diff --git a/drivers/s390/char/con3215.c b/drivers/s390/char/con3215.c
index 5af7f0bd6125..a6d47e5eee9e 100644
--- a/drivers/s390/char/con3215.c
+++ b/drivers/s390/char/con3215.c
@@ -288,12 +288,16 @@ static void raw3215_timeout(unsigned long __data)
288 unsigned long flags; 288 unsigned long flags;
289 289
290 spin_lock_irqsave(get_ccwdev_lock(raw->cdev), flags); 290 spin_lock_irqsave(get_ccwdev_lock(raw->cdev), flags);
291 if (raw->flags & RAW3215_TIMER_RUNS) { 291 raw->flags &= ~RAW3215_TIMER_RUNS;
292 del_timer(&raw->timer); 292 if (!(raw->port.flags & ASYNC_SUSPENDED)) {
293 raw->flags &= ~RAW3215_TIMER_RUNS; 293 raw3215_mk_write_req(raw);
294 if (!(raw->port.flags & ASYNC_SUSPENDED)) { 294 raw3215_start_io(raw);
295 raw3215_mk_write_req(raw); 295 if ((raw->queued_read || raw->queued_write) &&
296 raw3215_start_io(raw); 296 !(raw->flags & RAW3215_WORKING) &&
297 !(raw->flags & RAW3215_TIMER_RUNS)) {
298 raw->timer.expires = RAW3215_TIMEOUT + jiffies;
299 add_timer(&raw->timer);
300 raw->flags |= RAW3215_TIMER_RUNS;
297 } 301 }
298 } 302 }
299 spin_unlock_irqrestore(get_ccwdev_lock(raw->cdev), flags); 303 spin_unlock_irqrestore(get_ccwdev_lock(raw->cdev), flags);
@@ -317,17 +321,15 @@ static inline void raw3215_try_io(struct raw3215_info *raw)
317 (raw->flags & RAW3215_FLUSHING)) { 321 (raw->flags & RAW3215_FLUSHING)) {
318 /* execute write requests bigger than minimum size */ 322 /* execute write requests bigger than minimum size */
319 raw3215_start_io(raw); 323 raw3215_start_io(raw);
320 if (raw->flags & RAW3215_TIMER_RUNS) {
321 del_timer(&raw->timer);
322 raw->flags &= ~RAW3215_TIMER_RUNS;
323 }
324 } else if (!(raw->flags & RAW3215_TIMER_RUNS)) {
325 /* delay small writes */
326 raw->timer.expires = RAW3215_TIMEOUT + jiffies;
327 add_timer(&raw->timer);
328 raw->flags |= RAW3215_TIMER_RUNS;
329 } 324 }
330 } 325 }
326 if ((raw->queued_read || raw->queued_write) &&
327 !(raw->flags & RAW3215_WORKING) &&
328 !(raw->flags & RAW3215_TIMER_RUNS)) {
329 raw->timer.expires = RAW3215_TIMEOUT + jiffies;
330 add_timer(&raw->timer);
331 raw->flags |= RAW3215_TIMER_RUNS;
332 }
331} 333}
332 334
333/* 335/*