Gitweb:     
http://git.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=95cf82f99cfbd697c15572c444bd4f54f19745b0
Commit:     95cf82f99cfbd697c15572c444bd4f54f19745b0
Parent:     5ad4f71e2f19a06f738463da1f09ea7fda3a3db2
Author:     Alan Stern <[EMAIL PROTECTED]>
AuthorDate: Mon Sep 10 11:33:05 2007 -0400
Committer:  Greg Kroah-Hartman <[EMAIL PROTECTED]>
CommitDate: Fri Oct 12 14:55:26 2007 -0700

    USB: break apart flush_endpoint and disable_endpoint
    
    This patch (as988) breaks usb_hcd_endpoint_disable() apart into two
    routines.  The first, usb_hcd_flush_endpoint() does the -ESHUTDOWN
    unlinking of all URBs in the endpoint's queue and waits for them to
    complete.  The second, usb_hcd_disable_endpoint() -- renamed for
    better grammatical style -- merely calls the HCD's endpoint_disable
    method.  The changeover is easy because the routine currently has only
    one caller.
    
    This separation of function will be exploited in the following patch:
    When a device is suspended, the core will be able to cancel all
    outstanding URBs for that device while leaving the HCD's
    endpoint-related data structures intact for later.
    
    As an added benefit, HCDs no longer need to check for existing URBs in
    their endpoint_disable methods.  It is now guaranteed that there will
    be none.
    
    Signed-off-by: Alan Stern <[EMAIL PROTECTED]>
    Signed-off-by: Greg Kroah-Hartman <[EMAIL PROTECTED]>
---
 drivers/usb/core/hcd.c     |   48 ++++++++++++++++++++++++-------------------
 drivers/usb/core/hcd.h     |    4 ++-
 drivers/usb/core/message.c |    3 +-
 3 files changed, 32 insertions(+), 23 deletions(-)

diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
index 1c5e5d3..e5874e8 100644
--- a/drivers/usb/core/hcd.c
+++ b/drivers/usb/core/hcd.c
@@ -1289,24 +1289,22 @@ EXPORT_SYMBOL (usb_hcd_giveback_urb);
 
 /*-------------------------------------------------------------------------*/
 
-/* disables the endpoint: cancels any pending urbs, then synchronizes with
- * the hcd to make sure all endpoint state is gone from hardware, and then
- * waits until the endpoint's queue is completely drained. use for
- * set_configuration, set_interface, driver removal, physical disconnect.
- *
- * example:  a qh stored in ep->hcpriv, holding state related to endpoint
- * type, maxpacket size, toggle, halt status, and scheduling.
+/* Cancel all URBs pending on this endpoint and wait for the endpoint's
+ * queue to drain completely.  The caller must first insure that no more
+ * URBs can be submitted for this endpoint.
  */
-void usb_hcd_endpoint_disable (struct usb_device *udev,
+void usb_hcd_flush_endpoint(struct usb_device *udev,
                struct usb_host_endpoint *ep)
 {
        struct usb_hcd          *hcd;
        struct urb              *urb;
 
+       if (!ep)
+               return;
        might_sleep();
        hcd = bus_to_hcd(udev->bus);
 
-       /* ep is already gone from udev->ep_{in,out}[]; no more submits */
+       /* No more submits can occur */
 rescan:
        spin_lock_irq(&hcd_urb_list_lock);
        list_for_each_entry (urb, &ep->urb_list, urb_list) {
@@ -1345,18 +1343,7 @@ rescan:
        }
        spin_unlock_irq(&hcd_urb_list_lock);
 
-       /* synchronize with the hardware, so old configuration state
-        * clears out immediately (and will be freed).
-        */
-       if (hcd->driver->endpoint_disable)
-               hcd->driver->endpoint_disable (hcd, ep);
-
-       /* Wait until the endpoint queue is completely empty.  Most HCDs
-        * will have done this already in their endpoint_disable method,
-        * but some might not.  And there could be root-hub control URBs
-        * still pending since they aren't affected by the HCDs'
-        * endpoint_disable methods.
-        */
+       /* Wait until the endpoint queue is completely empty */
        while (!list_empty (&ep->urb_list)) {
                spin_lock_irq(&hcd_urb_list_lock);
 
@@ -1376,6 +1363,25 @@ rescan:
        }
 }
 
+/* Disables the endpoint: synchronizes with the hcd to make sure all
+ * endpoint state is gone from hardware.  usb_hcd_flush_endpoint() must
+ * have been called previously.  Use for set_configuration, set_interface,
+ * driver removal, physical disconnect.
+ *
+ * example:  a qh stored in ep->hcpriv, holding state related to endpoint
+ * type, maxpacket size, toggle, halt status, and scheduling.
+ */
+void usb_hcd_disable_endpoint(struct usb_device *udev,
+               struct usb_host_endpoint *ep)
+{
+       struct usb_hcd          *hcd;
+
+       might_sleep();
+       hcd = bus_to_hcd(udev->bus);
+       if (hcd->driver->endpoint_disable)
+               hcd->driver->endpoint_disable(hcd, ep);
+}
+
 /*-------------------------------------------------------------------------*/
 
 /* called in any context */
diff --git a/drivers/usb/core/hcd.h b/drivers/usb/core/hcd.h
index 0fc7b95..1396141 100644
--- a/drivers/usb/core/hcd.h
+++ b/drivers/usb/core/hcd.h
@@ -219,7 +219,9 @@ extern int usb_hcd_submit_urb (struct urb *urb, gfp_t 
mem_flags);
 extern int usb_hcd_unlink_urb (struct urb *urb, int status);
 extern void usb_hcd_giveback_urb(struct usb_hcd *hcd, struct urb *urb,
                int status);
-extern void usb_hcd_endpoint_disable (struct usb_device *udev,
+extern void usb_hcd_flush_endpoint(struct usb_device *udev,
+               struct usb_host_endpoint *ep);
+extern void usb_hcd_disable_endpoint(struct usb_device *udev,
                struct usb_host_endpoint *ep);
 extern int usb_hcd_get_frame_number (struct usb_device *udev);
 
diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c
index d638375..98fcddb 100644
--- a/drivers/usb/core/message.c
+++ b/drivers/usb/core/message.c
@@ -1017,7 +1017,8 @@ void usb_disable_endpoint(struct usb_device *dev, 
unsigned int epaddr)
        }
        if (ep) {
                ep->enabled = 0;
-               usb_hcd_endpoint_disable(dev, ep);
+               usb_hcd_flush_endpoint(dev, ep);
+               usb_hcd_disable_endpoint(dev, ep);
        }
 }
 
-
To unsubscribe from this list: send the line "unsubscribe git-commits-head" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to