David Brownell wrote:
> 
> Worked for me too, though I don't think I've seen that failure.
> 
> - Dave
> 
The patch is mainly for the MPC850 kind of USB hosts. 
Without the patch the USB subsystem often hangs during 
bootup (with an USB-ethernet dongle connected). 
With the patch it does not hang anymore.
You probably will not see this with OHCI and UHCI very 
often but I think there is a minimal chance that this 
happens at OHCI too.
(The callback has a higher handicap.
Therefore it depends on how high this handicap is
so that the right one always wins the race)

The MPC850 generates interrupts at the end of a transfer 
and not just at the end of a frame. So for short transfers 
this can be about ~20 microseconds after the submition of 
an urb. And if there is another interrupt pending the 
done-interrupt will follow immediately after and so the 
submission thread will lose the race and the callback 
will be called earlier.

- Roman

> ----- Original Message -----
> From: "Roman Weissgaerber" <[EMAIL PROTECTED]>
> To: <[EMAIL PROTECTED]>
> Cc: <[EMAIL PROTECTED]>
> Sent: Tuesday, March 13, 2001 3:37 AM
> Subject: [linux-usb-devel] pegasus driver
> 
> > Hi Petkan,
> >
> > there are some races in the pegasus driver.
> >
> > When you submit an URB please keep in mind that the
> > callback of the URB can be called earlier than
> > the URB-submition returns. In this case you wake up the
> > thread first and than put it to sleep.
> > This **really** happens on
> > a CPU time eating HC architecture.
> >
> > The attached patch against kernel 2.4.2ac20 solves
> > this.
> >
> >
> > - Roman
> 
> --------------------------------------------------------------------------------
> 
> > --- linux-2.4.2ac20/drivers/usb/pegasus.c Tue Mar 13 12:18:21 2001
> > +++ usb/pegasus.c Tue Mar 13 12:23:09 2001
> > @@ -124,7 +124,8 @@
> >  static int get_registers(pegasus_t *pegasus, __u16 indx, __u16 size, void *data)
> >  {
> >   int ret;
> > -
> > + DECLARE_WAITQUEUE (wait, current);
> > +
> >   while ( pegasus->flags & ETH_REGS_CHANGED ) {
> >   pegasus->flags |= CTRL_URB_SLEEP;
> >   interruptible_sleep_on( &pegasus->ctrl_wait );
> > @@ -140,13 +141,18 @@
> >     usb_rcvctrlpipe(pegasus->usb,0),
> >     (char *)&pegasus->dr,
> >     data, size, ctrl_callback, pegasus );
> > -
> > +
> > + add_wait_queue (&pegasus->ctrl_wait, &wait);
> > + set_current_state(TASK_INTERRUPTIBLE);
> > + pegasus->flags |= CTRL_URB_SLEEP;
> > +
> >   if ( (ret = usb_submit_urb( &pegasus->ctrl_urb )) ) {
> >   err( __FUNCTION__ " BAD CTRLs %d", ret);
> >   goto out;
> >   }
> > - pegasus->flags |= CTRL_URB_SLEEP;
> > - interruptible_sleep_on( &pegasus->ctrl_wait );
> > +
> > + schedule();
> > + remove_wait_queue (&pegasus->ctrl_wait, &wait);
> >  out:
> >   return ret;
> >  }
> > @@ -155,7 +161,8 @@
> >  static int set_registers(pegasus_t *pegasus, __u16 indx, __u16 size, void *data)
> >  {
> >   int ret;
> > -
> > + DECLARE_WAITQUEUE (wait, current);
> > +
> >   while ( pegasus->flags & ETH_REGS_CHANGED ) {
> >   pegasus->flags |= CTRL_URB_SLEEP ;
> >   interruptible_sleep_on( &pegasus->ctrl_wait );
> > @@ -171,14 +178,18 @@
> >     usb_sndctrlpipe(pegasus->usb,0),
> >     (char *)&pegasus->dr,
> >     data, size, ctrl_callback, pegasus );
> > -
> > +
> > + add_wait_queue (&pegasus->ctrl_wait, &wait);
> > + set_current_state(TASK_INTERRUPTIBLE);
> > + pegasus->flags |= CTRL_URB_SLEEP;
> > +
> >   if ( (ret = usb_submit_urb( &pegasus->ctrl_urb )) ) {
> >   err( __FUNCTION__ " BAD CTRL %d", ret);
> >   return ret;
> >   }
> > - pegasus->flags |= CTRL_URB_SLEEP;
> > - interruptible_sleep_on( &pegasus->ctrl_wait );
> > -
> > +
> > + schedule();
> > + remove_wait_queue (&pegasus->ctrl_wait, &wait);
> >   return ret;
> >  }
> >
> > @@ -187,7 +198,8 @@
> >  {
> >   int ret;
> >   __u16 dat = data;
> > -
> > + DECLARE_WAITQUEUE (wait, current);
> > +
> >   while ( pegasus->flags & ETH_REGS_CHANGED ) {
> >   pegasus->flags |= CTRL_URB_SLEEP;
> >   interruptible_sleep_on( &pegasus->ctrl_wait );
> > @@ -204,13 +216,18 @@
> >     (char *)&pegasus->dr,
> >     &data, 1, ctrl_callback, pegasus );
> >
> > + add_wait_queue (&pegasus->ctrl_wait, &wait);
> > + set_current_state(TASK_INTERRUPTIBLE);
> > + pegasus->flags |= CTRL_URB_SLEEP;
> > +
> >   if ( (ret = usb_submit_urb( &pegasus->ctrl_urb )) ) {
> >   err( __FUNCTION__ " BAD CTRL %d", ret);
> >   return ret;
> >   }
> > - pegasus->flags |= CTRL_URB_SLEEP;
> > - interruptible_sleep_on( &pegasus->ctrl_wait );
> >
> > + schedule();
> > + remove_wait_queue (&pegasus->ctrl_wait, &wait);
> > +
> >   return ret;
> >  }
> >
> >
> 
> _______________________________________________
> [EMAIL PROTECTED]
> To unsubscribe, use the last form field at:
> http://lists.sourceforge.net/lists/listinfo/linux-usb-devel

_______________________________________________
[EMAIL PROTECTED]
To unsubscribe, use the last form field at:
http://lists.sourceforge.net/lists/listinfo/linux-usb-devel

Reply via email to