ChangeSet 1.1557.49.18, 2004/02/18 13:11:47-08:00, david-b@pacbell.net [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 drivers/usb/core/message.c | 26 ++++++++++++++++---------- 1 files changed, 16 insertions(+), 10 deletions(-) diff -Nru a/drivers/usb/core/message.c b/drivers/usb/core/message.c --- a/drivers/usb/core/message.c Thu Feb 19 17:21:37 2004 +++ b/drivers/usb/core/message.c Thu Feb 19 17:21:37 2004 @@ -213,9 +213,8 @@ static void sg_complete (struct urb *urb, struct pt_regs *regs) { 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 * reports, until the completion callback (this!) returns. That lets @@ -269,7 +268,7 @@ if (!io->count) complete (&io->complete); - spin_unlock_irqrestore (&io->lock, flags); + spin_unlock (&io->lock); } @@ -441,12 +440,11 @@ */ void usb_sg_wait (struct usb_sg_request *io) { - int i; - unsigned long flags; + int i, entries = io->entries; /* queue the urbs. */ - spin_lock_irqsave (&io->lock, flags); - for (i = 0; i < io->entries && !io->status; i++) { + spin_lock_irq (&io->lock); + for (i = 0; i < entries && !io->status; i++) { int retval; io->urbs [i]->dev = io->dev; @@ -455,7 +453,7 @@ /* after we submit, let completions or cancelations fire; * we handshake using io->status. */ - spin_unlock_irqrestore (&io->lock, flags); + spin_unlock_irq (&io->lock); switch (retval) { /* maybe we retrying will recover */ case -ENXIO: // hc didn't queue this one @@ -479,17 +477,25 @@ /* fail any uncompleted urbs */ 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]->status = retval; dev_dbg (&io->dev->dev, "%s, submit --> %d\n", __FUNCTION__, retval); usb_sg_cancel (io); } - spin_lock_irqsave (&io->lock, flags); + spin_lock_irq (&io->lock); if (retval && io->status == -ECONNRESET) io->status = retval; } - spin_unlock_irqrestore (&io->lock, flags); + spin_unlock_irq (&io->lock); /* OK, yes, this could be packaged as non-blocking. * So could the submit loop above ... but it's easier to