Commit 6d28e037 authored by David Brownell's avatar David Brownell Committed by Greg Kroah-Hartman

[PATCH] USB: usb_sg_cancel() + disconnect, fewer messages

One tester reported that disconnecting in the middle of a scatterlist
operation would give a lot of confusing messages.  This should improve
that situation a bunch:  most of the messages were pointless.  It also
resolves some related FIXMEs for both queue cleanup modes (cancelation,
and after transport fault).

  - now only urbs in flight have non-null urb->dev, so we can avoid
    trying to unlink unsubmitted or (common) already-completed urbs.

  - it's ok to get -EBUSY unlink status, it just means the urb's
    already being given back (though since it's in flight, it's
    not an error to try unlinking).

Also, the relevant diagnostics now use dev_*() driver model calls,
making the kernel strings smaller and the output more useful.
parent b7bf5219
...@@ -246,21 +246,22 @@ static void sg_complete (struct urb *urb, struct pt_regs *regs) ...@@ -246,21 +246,22 @@ static void sg_complete (struct urb *urb, struct pt_regs *regs)
io->status = urb->status; io->status = urb->status;
/* the previous urbs, and this one, completed already. /* the previous urbs, and this one, completed already.
* unlink the later ones so they won't rx/tx bad data, * unlink pending urbs so they won't rx/tx bad data.
*
* FIXME don't bother unlinking urbs that haven't yet been
* submitted; those non-error cases shouldn't be syslogged
*/ */
for (i = 0, found = 0; i < io->entries; i++) { for (i = 0, found = 0; i < io->entries; i++) {
if (!io->urbs [i])
continue;
if (found) { if (found) {
status = usb_unlink_urb (io->urbs [i]); status = usb_unlink_urb (io->urbs [i]);
if (status && status != -EINPROGRESS) if (status != -EINPROGRESS && status != -EBUSY)
err ("sg_complete, unlink --> %d", dev_err (&io->dev->dev,
status); "%s, unlink --> %d\n",
__FUNCTION__, status);
} else if (urb == io->urbs [i]) } else if (urb == io->urbs [i])
found = 1; found = 1;
} }
} }
urb->dev = 0;
/* on the last completion, signal usb_sg_wait() */ /* on the last completion, signal usb_sg_wait() */
io->bytes += urb->actual_length; io->bytes += urb->actual_length;
...@@ -356,7 +357,7 @@ int usb_sg_init ( ...@@ -356,7 +357,7 @@ int usb_sg_init (
goto nomem; goto nomem;
} }
io->urbs [i]->dev = dev; io->urbs [i]->dev = 0;
io->urbs [i]->pipe = pipe; io->urbs [i]->pipe = pipe;
io->urbs [i]->interval = period; io->urbs [i]->interval = period;
io->urbs [i]->transfer_flags = urb_flags; io->urbs [i]->transfer_flags = urb_flags;
...@@ -448,6 +449,7 @@ void usb_sg_wait (struct usb_sg_request *io) ...@@ -448,6 +449,7 @@ void usb_sg_wait (struct usb_sg_request *io)
for (i = 0; i < io->entries && !io->status; i++) { for (i = 0; i < io->entries && !io->status; i++) {
int retval; int retval;
io->urbs [i]->dev = io->dev;
retval = usb_submit_urb (io->urbs [i], SLAB_ATOMIC); retval = usb_submit_urb (io->urbs [i], SLAB_ATOMIC);
/* after we submit, let completions or cancelations fire; /* after we submit, let completions or cancelations fire;
...@@ -459,9 +461,9 @@ void usb_sg_wait (struct usb_sg_request *io) ...@@ -459,9 +461,9 @@ void usb_sg_wait (struct usb_sg_request *io)
case -ENXIO: // hc didn't queue this one case -ENXIO: // hc didn't queue this one
case -EAGAIN: case -EAGAIN:
case -ENOMEM: case -ENOMEM:
io->urbs [i]->dev = 0;
retval = 0; retval = 0;
i--; i--;
// FIXME: should it usb_sg_cancel() on INTERRUPT?
yield (); yield ();
break; break;
...@@ -477,8 +479,10 @@ void usb_sg_wait (struct usb_sg_request *io) ...@@ -477,8 +479,10 @@ void usb_sg_wait (struct usb_sg_request *io)
/* fail any uncompleted urbs */ /* fail any uncompleted urbs */
default: default:
io->urbs [i]->dev = 0;
io->urbs [i]->status = retval; io->urbs [i]->status = retval;
dbg ("usb_sg_msg, submit --> %d", retval); dev_dbg (&io->dev->dev, "%s, submit --> %d\n",
__FUNCTION__, retval);
usb_sg_cancel (io); usb_sg_cancel (io);
} }
spin_lock_irqsave (&io->lock, flags); spin_lock_irqsave (&io->lock, flags);
...@@ -521,9 +525,9 @@ void usb_sg_cancel (struct usb_sg_request *io) ...@@ -521,9 +525,9 @@ void usb_sg_cancel (struct usb_sg_request *io)
if (!io->urbs [i]->dev) if (!io->urbs [i]->dev)
continue; continue;
retval = usb_unlink_urb (io->urbs [i]); retval = usb_unlink_urb (io->urbs [i]);
if (retval && retval != -EINPROGRESS) if (retval != -EINPROGRESS && retval != -EBUSY)
warn ("usb_sg_cancel, unlink --> %d", retval); dev_warn (&io->dev->dev, "%s, unlink --> %d\n",
// FIXME don't warn on "not yet submitted" error __FUNCTION__, retval);
} }
} }
spin_unlock_irqrestore (&io->lock, flags); spin_unlock_irqrestore (&io->lock, flags);
......
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