Commit 0fccad8c authored by Alan Stern's avatar Alan Stern Committed by Greg Kroah-Hartman

[PATCH] USB: Fix submission-error bug in the USB scatter-gather

This patch has been hanging around for a while and seems to have been
forgotten.  It fixes a bug in the USB scatter-gather library that crops up
when submission of an URB fails, and it fixes a bug in the cleanup routine
when some of the URBs being cleaned up have already completed.

I think David will agree that the patch is correct.  Please apply.
Signed-off-by: default avatarAlan Stern <stern@rowland.harvard.edu>
Signed-off-by: default avatarGreg Kroah-Hartman <greg@kroah.com>
parent f65d1c40
...@@ -248,7 +248,7 @@ static void sg_complete (struct urb *urb, struct pt_regs *regs) ...@@ -248,7 +248,7 @@ static void sg_complete (struct urb *urb, struct pt_regs *regs)
* unlink pending urbs so they won't rx/tx bad data. * unlink pending urbs so they won't rx/tx bad data.
*/ */
for (i = 0, found = 0; i < io->entries; i++) { for (i = 0, found = 0; i < io->entries; i++) {
if (!io->urbs [i]) if (!io->urbs [i] || !io->urbs [i]->dev)
continue; continue;
if (found) { if (found) {
status = usb_unlink_urb (io->urbs [i]); status = usb_unlink_urb (io->urbs [i]);
...@@ -337,7 +337,7 @@ int usb_sg_init ( ...@@ -337,7 +337,7 @@ int usb_sg_init (
if (io->entries <= 0) if (io->entries <= 0)
return io->entries; return io->entries;
io->count = 0; io->count = io->entries;
io->urbs = kmalloc (io->entries * sizeof *io->urbs, mem_flags); io->urbs = kmalloc (io->entries * sizeof *io->urbs, mem_flags);
if (!io->urbs) if (!io->urbs)
goto nomem; goto nomem;
...@@ -347,7 +347,7 @@ int usb_sg_init ( ...@@ -347,7 +347,7 @@ int usb_sg_init (
if (usb_pipein (pipe)) if (usb_pipein (pipe))
urb_flags |= URB_SHORT_NOT_OK; urb_flags |= URB_SHORT_NOT_OK;
for (i = 0; i < io->entries; i++, io->count = i) { for (i = 0; i < io->entries; i++) {
unsigned len; unsigned len;
io->urbs [i] = usb_alloc_urb (0, mem_flags); io->urbs [i] = usb_alloc_urb (0, mem_flags);
...@@ -477,24 +477,19 @@ void usb_sg_wait (struct usb_sg_request *io) ...@@ -477,24 +477,19 @@ void usb_sg_wait (struct usb_sg_request *io)
/* fail any uncompleted urbs */ /* fail any uncompleted urbs */
default: default:
spin_lock_irq (&io->lock); io->urbs [i]->dev = NULL;
io->count -= entries - i;
if (io->status == -EINPROGRESS)
io->status = retval;
if (io->count == 0)
complete (&io->complete);
spin_unlock_irq (&io->lock);
io->urbs[i]->dev = NULL;
io->urbs [i]->status = retval; io->urbs [i]->status = retval;
dev_dbg (&io->dev->dev, "%s, submit --> %d\n", dev_dbg (&io->dev->dev, "%s, submit --> %d\n",
__FUNCTION__, retval); __FUNCTION__, retval);
usb_sg_cancel (io); usb_sg_cancel (io);
} }
spin_lock_irq (&io->lock); spin_lock_irq (&io->lock);
if (retval && io->status == -ECONNRESET) if (retval && (io->status == 0 || io->status == -ECONNRESET))
io->status = retval; io->status = retval;
} }
io->count -= entries - i;
if (io->count == 0)
complete (&io->complete);
spin_unlock_irq (&io->lock); spin_unlock_irq (&io->lock);
/* OK, yes, this could be packaged as non-blocking. /* OK, yes, this could be packaged as non-blocking.
......
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