Am Donnerstag, 20. Dezember 2007 17:37:49 schrieb Greg KH:
> On Thu, Dec 20, 2007 at 10:32:50AM -0500, Alan Stern wrote:
> > On Thu, 20 Dec 2007, Oliver Neukum wrote:
> > 
> > > Hi,
> > > 
> > > the mos7720 driver sends two commands to the device whenever it is
> > > closed. It does so unconditionally even if the device has been 
> > > disconnected.
> > > It seems to me that this is wrong. Making sure that this does not happen
> > > for disconnected devices takes a bit of infrastructure in the generic 
> > > part.
> > > However I am not sure whether this interfeeres with hanging up the tty.
> > > What do you think?
> > 
> > There's nothing wrong with trying to send those commands if the device 
> > really is disconnected.  The attempts will fail quickly.
> > 
> > The problem arises when the device is still connected but the driver 
> > has been unbound.  That is illegal; a driver is never supposed to 
> > access a device once its unbind method has returned.
> > 
> > Do other serial drivers suffer from a similar problem?
> 
> The io_edgeport-like devices all want to send a "flush" type command
> when they are closed, and it doesn't look like they check for disconnect
> either :(

>From a more general angle, perhaps what we provide with usb_kill_urb()
is not ideally suited to combat this problem. What about a construction like
this:

Signed-off-by: Oliver Neukum <[EMAIL PROTECTED]>

        Regards
                Oliver
----

--- linux-2.6.24-rc5-vanilla/drivers/usb/core/urb.c     2007-12-20 
13:13:52.000000000 +0100
+++ linux-2.6.24-rc5-work/drivers/usb/core/urb.c        2007-12-17 
20:47:50.000000000 +0100
@@ -10,6 +10,8 @@
 
 #define to_urb(d) container_of(d, struct urb, kref)
 
+static DEFINE_MUTEX(usb_reject_mutex);
+
 static void urb_destroy(struct kref *kref)
 {
        struct urb *urb = to_urb(kref);
@@ -537,21 +539,52 @@ int usb_unlink_urb(struct urb *urb)
  */
 void usb_kill_urb(struct urb *urb)
 {
-       static DEFINE_MUTEX(reject_mutex);
-
        might_sleep();
        if (!(urb && urb->dev && urb->ep))
                return;
-       mutex_lock(&reject_mutex);
+       mutex_lock(&usb_reject_mutex);
        ++urb->reject;
-       mutex_unlock(&reject_mutex);
+       mutex_unlock(&usb_reject_mutex);
 
        usb_hcd_unlink_urb(urb, -ENOENT);
        wait_event(usb_kill_urb_queue, atomic_read(&urb->use_count) == 0);
 
-       mutex_lock(&reject_mutex);
+       mutex_lock(&usb_reject_mutex);
        --urb->reject;
-       mutex_unlock(&reject_mutex);
+       mutex_unlock(&usb_reject_mutex);
+}
+
+/**
+ * usb_poison_urb - cancel an URB, wait for it to finish, prevent its use
+ * @urb: pointer to URB describing a previously submitted request,
+ *     may be NULL
+ *
+ * This routine cancels an in-progress request.  It is guaranteed that
+ * upon return all completion handlers will have finished and the URB
+ * cannot be reused.  These features make
+ * this an ideal way to stop I/O in a disconnect() callback or close()
+ * function.  If the request has not already finished or been unlinked
+ * the completion handler will see urb->status == -ENOENT.
+ *
+ * After the routine has been run, attempts to resubmit the URB will fail
+ * with error -EPERM.  Thus even if a driver tries to resubmit, the device
+ * won't be bothered
+ *
+ * This routine may not be used in an interrupt context (such as a bottom
+ * half or a completion handler), or when holding a spinlock, or in other
+ * situations where the caller can't schedule().
+ */
+void usb_poison_urb(struct urb *urb)
+{
+       might_sleep();
+       if (!(urb && urb->dev && urb->ep))
+               return;
+       mutex_lock(&usb_reject_mutex);
+       ++urb->reject;
+       mutex_unlock(&usb_reject_mutex);
+
+       usb_hcd_unlink_urb(urb, -ENOENT);
+       wait_event(usb_kill_urb_queue, atomic_read(&urb->use_count) == 0);
 }
 
 /**
@@ -603,3 +636,4 @@ EXPORT_SYMBOL(usb_get_urb);
 EXPORT_SYMBOL(usb_submit_urb);
 EXPORT_SYMBOL(usb_unlink_urb);
 EXPORT_SYMBOL(usb_kill_urb);
+EXPORT_SYMBOL(usb_poison_urb);
-
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to