On Thu, May 13, 2004 at 10:26:25PM -0400, Alan Stern wrote: > > Nothing guarantees it! That's one of the other things that needs to be > fixed. The way I eventually want it to work is that there will be a list > of urbp's that have been removed from the schedule and are waiting for the > hardware to let them go (like we have now) together with a record of the > frame number at the time they were removed. There will also be another
OK, how about this patch? -- Visit Openswan at http://www.openswan.org/ Email: Herbert Xu ~{PmV>HI~} <[EMAIL PROTECTED]> Home Page: http://gondor.apana.org.au/~herbert/ PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
===== drivers/usb/host/uhci-hcd.c 1.77 vs edited ===== --- 1.77/drivers/usb/host/uhci-hcd.c Wed Apr 14 20:19:54 2004 +++ edited/drivers/usb/host/uhci-hcd.c Wed May 19 22:59:57 2004 @@ -95,6 +95,8 @@ static int uhci_get_current_frame_number(struct uhci_hcd *uhci); static int uhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb); static void uhci_unlink_generic(struct uhci_hcd *uhci, struct urb *urb); +static void uhci_remove_pending_urbps(struct uhci_hcd *uhci); +static void uhci_finish_completion(struct usb_hcd *hcd, struct pt_regs *regs); static void hc_state_transitions(struct uhci_hcd *uhci); @@ -1512,6 +1514,7 @@ struct uhci_hcd *uhci = hcd_to_uhci(hcd); unsigned long flags; struct urb_priv *urbp; + unsigned int age; spin_lock_irqsave(&uhci->schedule_lock, flags); urbp = urb->hcpriv; @@ -1522,8 +1525,12 @@ uhci_unlink_generic(uhci, urb); /* If we're the first, set the next interrupt bit */ - if (list_empty(&uhci->urb_remove_list)) + age = uhci_get_current_frame_number(uhci); + if (list_empty(&uhci->urb_remove_list)) { + uhci->urb_remove_age = age; uhci_set_next_interrupt(uhci); + } else if (age != uhci->urb_remove_age) + uhci_remove_pending_urbps(uhci); list_add_tail(&urbp->urb_list, &uhci->urb_remove_list); done: @@ -1590,6 +1597,12 @@ INIT_LIST_HEAD(&list); spin_lock_irqsave(&uhci->schedule_lock, flags); + if (list_empty(&uhci->urb_remove_list) && + uhci_get_current_frame_number(uhci) != uhci->urb_remove_age) { + uhci_remove_pending_urbps(uhci); + uhci_finish_completion(hcd, NULL); + } + head = &uhci->urb_list; tmp = head->next; while (tmp != head) { @@ -1760,7 +1773,10 @@ uhci_free_pending_qhs(uhci); uhci_free_pending_tds(uhci); - uhci_remove_pending_urbps(uhci); + + if (!list_empty(&uhci->urb_remove_list) && + uhci_get_current_frame_number(uhci) != uhci->urb_remove_age) + uhci_remove_pending_urbps(uhci); uhci_clear_next_interrupt(uhci); ===== drivers/usb/host/uhci-hcd.h 1.23 vs edited ===== --- 1.23/drivers/usb/host/uhci-hcd.h Mon Apr 19 21:05:56 2004 +++ edited/drivers/usb/host/uhci-hcd.h Wed May 19 23:01:17 2004 @@ -363,6 +363,7 @@ /* List of asynchronously unlinked URB's */ struct list_head urb_remove_list; /* P: uhci->schedule_lock */ + unsigned int urb_remove_age; /* Age in frames */ /* List of URB's awaiting completion callback */ struct list_head complete_list; /* P: uhci->schedule_lock */