3.10-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Martin Schwidefsky <schwidef...@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 <schwidef...@de.ibm.com>
Signed-off-by: Greg Kroah-Hartman <gre...@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;
+       }
 }
 
 /*


--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Reply via email to