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