Greg: This patch implements the endpoint_disable method for the UHCI driver, as you requested a while back. It guarantees that during unbinding events (disconnect, configuration change, rmmod) the UHCI driver will have finished using every URB for the interface being unbound. It doesn't quite guarantee that the completion handlers will have finished running, but it would take a pretty unlikely race to violate that assumption. (I think it's the same with the OHCI and EHCI drivers.)
Despite the patch numbering this one applies _after_ as249, which is a more important bugfix. Alan Stern ===== drivers/usb/host/uhci-hcd.c 1.101 vs edited ===== --- 1.101/drivers/usb/host/uhci-hcd.c Fri Mar 26 10:19:10 2004 +++ edited/drivers/usb/host/uhci-hcd.c Wed Apr 14 10:19:54 2004 @@ -1786,6 +1786,9 @@ spin_unlock(&uhci->schedule_lock); + /* Wake up anyone waiting for an URB to complete */ + wake_up_all(&uhci->waitqh); + return IRQ_HANDLED; } @@ -2086,6 +2089,8 @@ INIT_LIST_HEAD(&uhci->complete_list); + init_waitqueue_head(&uhci->waitqh); + uhci->fl = dma_alloc_coherent(uhci_dev(uhci), sizeof(*uhci->fl), &dma_handle, 0); if (!uhci->fl) { @@ -2296,6 +2301,9 @@ uhci_free_pending_qhs(uhci); uhci_free_pending_tds(uhci); spin_unlock_irq(&uhci->schedule_lock); + + /* Wake up anyone waiting for an URB to complete */ + wake_up_all(&uhci->waitqh); release_uhci(uhci); } @@ -2361,6 +2369,46 @@ kfree(hcd_to_uhci(hcd)); } +/* Are there any URBs for a particular device/endpoint on a given list? */ +static int urbs_for_ep_list(struct list_head *head, + struct hcd_dev *hdev, int ep) +{ + struct urb_priv *urbp; + + list_for_each_entry(urbp, head, urb_list) { + struct urb *urb = urbp->urb; + + if (hdev == urb->dev->hcpriv && ep == + (usb_pipeendpoint(urb->pipe) | + usb_pipein(urb->pipe))) + return 1; + } + return 0; +} + +/* Are there any URBs for a particular device/endpoint? */ +static int urbs_for_ep(struct uhci_hcd *uhci, struct hcd_dev *hdev, int ep) +{ + int rc; + + spin_lock_irq(&uhci->schedule_lock); + rc = (urbs_for_ep_list(&uhci->urb_list, hdev, ep) || + urbs_for_ep_list(&uhci->complete_list, hdev, ep) || + urbs_for_ep_list(&uhci->urb_remove_list, hdev, ep)); + spin_unlock_irq(&uhci->schedule_lock); + return rc; +} + +/* Wait until all the URBs for a particular device/endpoint are gone */ +static void uhci_hcd_endpoint_disable(struct usb_hcd *hcd, + struct hcd_dev *hdev, int endpoint) +{ + struct uhci_hcd *uhci = hcd_to_uhci(hcd); + + wait_event_interruptible(uhci->waitqh, + !urbs_for_ep(uhci, hdev, endpoint)); +} + static int uhci_hcd_get_frame_number(struct usb_hcd *hcd) { return uhci_get_current_frame_number(hcd_to_uhci(hcd)); @@ -2390,6 +2438,7 @@ .urb_enqueue = uhci_urb_enqueue, .urb_dequeue = uhci_urb_dequeue, + .endpoint_disable = uhci_hcd_endpoint_disable, .get_frame_number = uhci_hcd_get_frame_number, .hub_status_data = uhci_hub_status_data, ===== uhci-hcd.h 1.29 vs edited ===== --- 1.29/drivers/usb/host/uhci-hcd.h Fri Mar 26 10:19:24 2004 +++ edited/drivers/usb/host/uhci-hcd.h Mon Apr 19 11:05:56 2004 @@ -370,6 +370,8 @@ int rh_numports; struct timer_list stall_timer; + + wait_queue_head_t waitqh; /* endpoint_disable waiters */ }; struct urb_priv { ------------------------------------------------------- This SF.Net email is sponsored by: IBM Linux Tutorials Free Linux tutorial presented by Daniel Robbins, President and CEO of GenToo technologies. Learn everything from fundamentals to system administration.http://ads.osdn.com/?ad_id=1470&alloc_id=3638&op=click _______________________________________________ [EMAIL PROTECTED] To unsubscribe, use the last form field at: https://lists.sourceforge.net/lists/listinfo/linux-usb-devel