On Tue, Mar 08, 2005 at 12:05:45PM -0500, Alan Stern wrote: > On Mon, 7 Mar 2005, Nishanth Aravamudan wrote: > > > Ah, this is the same problem Vojtech had with a different patch I had > > sent. Does the attached fix seem better / more appropriate? > > There are still some things to consider. See below. > > > --- 2.6.11-v/drivers/usb/class/usb-midi.c 2005-03-01 23:37:45.000000000 > > -0800 > > +++ 2.6.11/drivers/usb/class/usb-midi.c 2005-03-07 15:25:07.000000000 > > -0800 > > @@ -317,7 +317,7 @@ static int usb_write( struct midi_out_en > > int pipe; > > int ret = 0; > > int status; > > - int maxretry = 50; > > + unsigned long timeout = 500; > > _Please_ don't set timeout to 500 jiffies! Use msecs_to_jiffies(500) > instead.
I was trying to keep to the current code as closely as possible, sorry. It loops at 10 jiffy intervals up to 50 times, which is a total of 500 jiffies. If the intent was to use milliseconds, though, then interruptible_sleep_on_timeout() was a much more broken usage than I thought. Trust me, if I thought milliseconds should be used, I would have used them :) > > DECLARE_WAITQUEUE(wait,current); > > init_waitqueue_head(&ep->wait); > > @@ -335,20 +335,14 @@ static int usb_write( struct midi_out_en > > goto error; > > } > > > > - add_wait_queue( &ep->wait, &wait ); > > - set_current_state( TASK_INTERRUPTIBLE ); > > - > > - while( ep->urb->status == -EINPROGRESS ) { > > - if ( maxretry-- < 0 ) { > > - printk(KERN_ERR "usbmidi: usb_bulk_msg timed out\n"); > > - ret = -ETIME; > > - break; > > - } > > - interruptible_sleep_on_timeout( &ep->wait, 10 ); > > - } > > - set_current_state( TASK_RUNNING ); > > - remove_wait_queue( &ep->wait, &wait ); > > + set_current_state(TASK_UNINTERRUPTIBLE); > > + add_wait_queue(&ep->wait, &wait); > > > > + /* if no wq events in 500 jiffies */ > > + if (!schedule_timeout(timeout)) > > + ret = -ETIME; > > + > > + remove_wait_queue(&ep->wait, &wait); > > error: > > return ret; > > } > > You removed the error message. Should it remain present? Yes, I will fix that. > Note that schedule_timeout can return before the timeout has elapsed, even > though the condition you're waiting for (URB completed) hasn't happened > yet. People use a loop to catch these things, and you definitely need a > way to test for URB completed. But seeing if ep->urb->status is equal to > -EINPROGRESS is not the correct way to do it. I see that the completion > handler, usb_write_callback, doesn't do anything but wake up the > waitqueue. That's not good enough; it needs to set a flag in the ep > structure for you to test. I was banking on schedule_timeout() returning early. Because it now uses TASK_UNINTERRUPTIBLE, only wait-queue events should cause the timeout to return a non-zero value. I just changed the wake_up_interruptible() call in the callback to wake_up() so it will catch the UNINTERRUPTIBLE tasks as well. Unfortunately other paths also wake-up the same wq, so the fix is, as you said, incomplete. I have no means of testing this device or my patches, though. And, to be frank, don't care too much about the device beyond a general feeling of making Linux better :) I have to get some other work done in the mean time, but I will try to get a revised patch out. > Note also that the test must be made _before_ calling schedule_timeout. > Otherwise you have a race; the URB may complete before you have managed to > call add_wait_queue. Ok, I will verify this is the case in the new patch. Thanks, Nish ------------------------------------------------------- SF email is sponsored by - The IT Product Guide Read honest & candid reviews on hundreds of IT Products from real users. Discover which products truly live up to the hype. Start reading now. http://ads.osdn.com/?ad_id=6595&alloc_id=14396&op=click _______________________________________________ linux-usb-devel@lists.sourceforge.net To unsubscribe, use the last form field at: https://lists.sourceforge.net/lists/listinfo/linux-usb-devel