On Tue, 8 May 2007, Oliver Neukum wrote: > Am Montag, 7. Mai 2007 21:23 schrieb Alan Stern: > > On Mon, 7 May 2007, Oliver Neukum wrote: > > > > +int usb_wait_anchor_empty_timeout(struct usb_anchor *anchor, int timeout) > > > +{ > > > + int res; > > > + > > > + res = wait_event_timeout(anchor->wait, list_empty(&anchor->urb_list), > > > timeout); > > > > Maybe make this an interruptible wait? > > For use in disconnect(), suspend() and pre_reset()? Theses can't handle > signals.
What do you mean? They don't have to handle signals. They just have to cut the timeout short when a signal arrives and then kill the outstanding URBs. Also, you don't want to contribute to the load average while you're waiting. > Ok. I've followed all other your suggestions. The usbcore part looks good (except that your kerneldoc needs to be updated and you should try to observe the 80-column limit). The usb-skeleton part is a little more questionable. > --- a/drivers/usb/usb-skeleton.c 2007-05-04 13:07:30.000000000 +0200 > +++ b/drivers/usb/usb-skeleton.c 2007-05-08 13:41:34.000000000 +0200 > @@ -54,10 +54,13 @@ struct usb_skel { > struct usb_device *udev; /* the usb device for > this device */ > struct usb_interface *interface; /* the interface for > this device */ > struct semaphore limit_sem; /* limiting the number > of writes in progress */ > + struct usb_anchor submitted; /* in case we need to > retract our submissions */ > unsigned char *bulk_in_buffer; /* the buffer to > receive data */ > size_t bulk_in_size; /* the size of the > receive buffer */ > __u8 bulk_in_endpointAddr; /* the address of the > bulk in endpoint */ > __u8 bulk_out_endpointAddr; /* the address of the > bulk out endpoint */ > + int errors; /* the last request > tanked */ > + spinlock_t err_lock; /* lock for errors */ Here we go, adding yet another lock. Isn't it starting to become excessive? > @@ -213,6 +219,15 @@ static ssize_t skel_write(struct file *f > goto exit; > } > > + spin_lock_irq(&dev->err_lock); > + if (dev->errors < 0) { > + dev->errors = 0; > + retval = -EIO; > + } > + spin_unlock_irq(&dev->err_lock); > + if (retval < 0) > + goto error; Is this really correct? You might end up reporting one user's errors to a different user. But maybe that's the standard approach; I don't know... You forgot to unanchor the URB if usb_submit_urb() failed. > @@ -391,10 +409,31 @@ static void skel_disconnect(struct usb_i > info("USB Skeleton #%d now disconnected", minor); > } > > +static int skel_suspend(struct usb_interface *intf, pm_message_t message) > +{ > + struct usb_skel *dev= usb_get_intfdata(intf); > + int time; > + > + mutex_lock(&dev->io_mutex); > + time = usb_wait_anchor_empty_timeout(&dev->submitted, 1 * HZ); > + if (!time) > + usb_kill_anchored_urbs(&dev->submitted); > + mutex_unlock(&dev->io_mutex); > + > + return 0; > +} I don't think you should use dev->io_mutex here. It is intended for synchronizing I/O with disconnect, so that the driver doesn't try to access the device after it has been unbound. But an unbind can't happen during a suspend method call, so you shouldn't need the mutex. Of course, you face a starvation problem if the user keeps writing data as fast as you keep killing URBs. That will be fixed once the autosuspend stuff is added; the usb_autopm_get_interface() call will block until skel_suspend() has returned. For now, don't bother with io_mutex. After all, the code above won't prevent more URBs from being submitted after skel_suspend() returns. Alan Stern ------------------------------------------------------------------------- This SF.net email is sponsored by DB2 Express Download DB2 Express C - the FREE version of DB2 express and take control of your XML. No limits. Just data. Click to get it now. http://sourceforge.net/powerbar/db2/ _______________________________________________ linux-usb-devel@lists.sourceforge.net To unsubscribe, use the last form field at: https://lists.sourceforge.net/lists/listinfo/linux-usb-devel