On Tue, 7 Sep 2004, Andrew Pilley wrote: > Okay, here you go. I've got spare time tomorrow, so if you manage to get > this back to me in the next 12 hours, I can bang on it repeatedly until > it triggers, since I'll have time to spare.
Here's the patch. I've verified that it compiles okay but I haven't tried running it on my system, so it's possible that it won't work quite right. But it probably will. You don't need usb-storage debugging enabled for this; in fact, you shouldn't enable it. The patch will put extra messages in the system log whenever something strange happens in the particular region of code that's been causing problems. I think that will happen as often as the hangs you used to get -- the earlier patch that seemed to help didn't actually prevent funny things from happening; it just made sure the system would continue running normally when they did. Anyway, try it and see what happens. Alan Stern --- linux-usb/drivers/usb/core/message.c.orig Mon Sep 6 12:16:12 2004 +++ linux-usb/drivers/usb/core/message.c Mon Sep 6 12:23:28 2004 @@ -197,6 +197,67 @@ /*-------------------------------------------------------------------*/ +#define USB_LOG_LINE_LEN 60 + +static char usb_log_buf[USB_LOG_LINE_LEN * 50]; +static char *log_head = usb_log_buf, + *log_tail = usb_log_buf; +static int log_immediate; +static spinlock_t log_lock = SPIN_LOCK_UNLOCKED; + +#define advance_logptr(x) \ + do { \ + x += USB_LOG_LINE_LEN; \ + if (x == usb_log_buf + sizeof(usb_log_buf)) \ + x = usb_log_buf; \ + } while(0) + +static void usb_log(const char *fmt, ...) +{ + va_list args; + unsigned long flags; + + va_start(args, fmt); + spin_lock_irqsave(&log_lock, flags); + + vsnprintf(log_tail, USB_LOG_LINE_LEN, fmt, args); + advance_logptr(log_tail); + if (log_tail == log_head) + advance_logptr(log_head); + if (log_immediate) { + printk(KERN_INFO "%s", log_head); + log_head = log_tail; + } + + spin_unlock_irqrestore(&log_lock, flags); + va_end(args); +} + +static void usb_log_start_dump(void) +{ + unsigned long flags; + + spin_lock_irqsave(&log_lock, flags); + while (log_head != log_tail) { + printk(KERN_INFO "%s", log_head); + advance_logptr(log_head); + } + log_immediate = 1; + spin_unlock_irqrestore(&log_lock, flags); +} + +static void usb_log_stop_dump(void) +{ + unsigned long flags; + + spin_lock_irqsave(&log_lock, flags); + log_immediate = 0; + spin_unlock_irqrestore(&log_lock, flags); +} + + +/*-------------------------------------------------------------------*/ + static void sg_clean (struct usb_sg_request *io) { if (io->urbs) { @@ -214,6 +275,8 @@ { struct usb_sg_request *io = (struct usb_sg_request *) urb->context; + usb_log("complete %p (%d): %d\n", urb, urb->actual_length, + urb->status); spin_lock (&io->lock); /* In 2.5 we require hcds' endpoint queues not to progress after fault @@ -242,6 +305,7 @@ if (urb->status && urb->status != -ECONNRESET) { int i, found, status; + usb_log_start_dump(); io->status = urb->status; /* the previous urbs, and this one, completed already. @@ -252,6 +316,7 @@ continue; if (found) { status = usb_unlink_urb (io->urbs [i]); + usb_log("unlink1 %p: %d\n", io->urbs[i], status); if (status != -EINPROGRESS && status != -EBUSY) dev_err (&io->dev->dev, "%s, unlink --> %d\n", @@ -265,6 +330,7 @@ /* on the last completion, signal usb_sg_wait() */ io->bytes += urb->actual_length; io->count--; + usb_log("count: %d\n", io->count); if (!io->count) complete (&io->complete); @@ -391,6 +457,7 @@ io->status = 0; io->bytes = 0; init_completion (&io->complete); + usb_log("sg_init %d\n", io->entries); return 0; nomem: @@ -449,6 +516,8 @@ io->urbs [i]->dev = io->dev; retval = usb_submit_urb (io->urbs [i], SLAB_ATOMIC); + usb_log("submit %p (%d): %d\n", io->urbs[i], + io->urbs[i]->transfer_buffer_length, retval); /* after we submit, let completions or cancelations fire; * we handshake using io->status. @@ -499,6 +568,7 @@ wait_for_completion (&io->complete); sg_clean (io); + usb_log_stop_dump(); } /** @@ -513,6 +583,9 @@ { unsigned long flags; + usb_log_start_dump(); + usb_log("cancel\n"); + spin_lock_irqsave (&io->lock, flags); /* shut everything down, if it didn't already */ @@ -526,6 +599,7 @@ if (!io->urbs [i]->dev) continue; retval = usb_unlink_urb (io->urbs [i]); + usb_log("unlink2 %p: %d\n", io->urbs[i], retval); if (retval != -EINPROGRESS && retval != -EBUSY) dev_warn (&io->dev->dev, "%s, unlink --> %d\n", __FUNCTION__, retval); ------------------------------------------------------- This SF.Net email is sponsored by BEA Weblogic Workshop FREE Java Enterprise J2EE developer tools! Get your free copy of BEA WebLogic Workshop 8.1 today. http://ads.osdn.com/?ad_id=5047&alloc_id=10808&op=click _______________________________________________ [EMAIL PROTECTED] To unsubscribe, use the last form field at: https://lists.sourceforge.net/lists/listinfo/linux-usb-devel