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 */

Reply via email to