Commit 876b1343 authored by David Brownell's avatar David Brownell Committed by Greg Kroah-Hartman

[PATCH] USB: usbcore, scatterlist cleanups

[USB] minor usb_sg_wait() cleanups

  - count urb completions correctly when there's a non-recoverable
    fault during scatterlist submission ... prevents a hang (seen
    only with already-faulty usb-storage devices).

  - don't local_irq_{save,restore}() when not needed
parent 6bbdfe17
...@@ -213,9 +213,8 @@ static void sg_clean (struct usb_sg_request *io) ...@@ -213,9 +213,8 @@ static void sg_clean (struct usb_sg_request *io)
static void sg_complete (struct urb *urb, struct pt_regs *regs) static void sg_complete (struct urb *urb, struct pt_regs *regs)
{ {
struct usb_sg_request *io = (struct usb_sg_request *) urb->context; struct usb_sg_request *io = (struct usb_sg_request *) urb->context;
unsigned long flags;
spin_lock_irqsave (&io->lock, flags); spin_lock (&io->lock);
/* In 2.5 we require hcds' endpoint queues not to progress after fault /* In 2.5 we require hcds' endpoint queues not to progress after fault
* reports, until the completion callback (this!) returns. That lets * reports, until the completion callback (this!) returns. That lets
...@@ -269,7 +268,7 @@ static void sg_complete (struct urb *urb, struct pt_regs *regs) ...@@ -269,7 +268,7 @@ static void sg_complete (struct urb *urb, struct pt_regs *regs)
if (!io->count) if (!io->count)
complete (&io->complete); complete (&io->complete);
spin_unlock_irqrestore (&io->lock, flags); spin_unlock (&io->lock);
} }
...@@ -441,12 +440,11 @@ int usb_sg_init ( ...@@ -441,12 +440,11 @@ int usb_sg_init (
*/ */
void usb_sg_wait (struct usb_sg_request *io) void usb_sg_wait (struct usb_sg_request *io)
{ {
int i; int i, entries = io->entries;
unsigned long flags;
/* queue the urbs. */ /* queue the urbs. */
spin_lock_irqsave (&io->lock, flags); spin_lock_irq (&io->lock);
for (i = 0; i < io->entries && !io->status; i++) { for (i = 0; i < entries && !io->status; i++) {
int retval; int retval;
io->urbs [i]->dev = io->dev; io->urbs [i]->dev = io->dev;
...@@ -455,7 +453,7 @@ void usb_sg_wait (struct usb_sg_request *io) ...@@ -455,7 +453,7 @@ void usb_sg_wait (struct usb_sg_request *io)
/* after we submit, let completions or cancelations fire; /* after we submit, let completions or cancelations fire;
* we handshake using io->status. * we handshake using io->status.
*/ */
spin_unlock_irqrestore (&io->lock, flags); spin_unlock_irq (&io->lock);
switch (retval) { switch (retval) {
/* maybe we retrying will recover */ /* maybe we retrying will recover */
case -ENXIO: // hc didn't queue this one case -ENXIO: // hc didn't queue this one
...@@ -479,17 +477,25 @@ void usb_sg_wait (struct usb_sg_request *io) ...@@ -479,17 +477,25 @@ 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->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 = 0; io->urbs [i]->dev = 0;
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_irqsave (&io->lock, flags); spin_lock_irq (&io->lock);
if (retval && io->status == -ECONNRESET) if (retval && io->status == -ECONNRESET)
io->status = retval; io->status = retval;
} }
spin_unlock_irqrestore (&io->lock, flags); spin_unlock_irq (&io->lock);
/* OK, yes, this could be packaged as non-blocking. /* OK, yes, this could be packaged as non-blocking.
* So could the submit loop above ... but it's easier to * So could the submit loop above ... but it's easier to
......
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