Commit b31f821c authored by Pete Zaitcev's avatar Pete Zaitcev Committed by Greg Kroah-Hartman

[PATCH] USB: ub 04 Loss of timer and a hang

If SCSI commands are submitted while other commands are still processed,
the dispatch loop turns, and we stop the work_timer. Then, if URB fails
to complete, ub hangs until the device is unplugged.

This does not happen often, becase we only allow one SCSI command per
block device, but does happen (on multi-LUN devices, for example).

The fix is to stop timer only when we actually going to change the state.

The nicest code would be to have the timer stopped in URB callback, but
this is impossible, because it can be called from inside a timer, through
the urb_unlink. Then we get BUG in timer.c:cascade(). So, we do it a
little dirtier.
Signed-off-by: default avatarPete Zaitcev <zaitcev@redhat.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
parent 65b4fe55
...@@ -1106,7 +1106,8 @@ static void ub_urb_timeout(unsigned long arg) ...@@ -1106,7 +1106,8 @@ static void ub_urb_timeout(unsigned long arg)
unsigned long flags; unsigned long flags;
spin_lock_irqsave(sc->lock, flags); spin_lock_irqsave(sc->lock, flags);
usb_unlink_urb(&sc->work_urb); if (!ub_is_completed(&sc->work_done))
usb_unlink_urb(&sc->work_urb);
spin_unlock_irqrestore(sc->lock, flags); spin_unlock_irqrestore(sc->lock, flags);
} }
...@@ -1131,7 +1132,6 @@ static void ub_scsi_action(unsigned long _dev) ...@@ -1131,7 +1132,6 @@ static void ub_scsi_action(unsigned long _dev)
unsigned long flags; unsigned long flags;
spin_lock_irqsave(sc->lock, flags); spin_lock_irqsave(sc->lock, flags);
del_timer(&sc->work_timer);
ub_scsi_dispatch(sc); ub_scsi_dispatch(sc);
spin_unlock_irqrestore(sc->lock, flags); spin_unlock_irqrestore(sc->lock, flags);
} }
...@@ -1155,6 +1155,7 @@ static void ub_scsi_dispatch(struct ub_dev *sc) ...@@ -1155,6 +1155,7 @@ static void ub_scsi_dispatch(struct ub_dev *sc)
} else { } else {
if (!ub_is_completed(&sc->work_done)) if (!ub_is_completed(&sc->work_done))
break; break;
del_timer(&sc->work_timer);
ub_scsi_urb_compl(sc, cmd); ub_scsi_urb_compl(sc, cmd);
} }
} }
......
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