ChangeSet 1.879.9.1, 2003/01/06 15:47:26-08:00, [EMAIL PROTECTED]

[PATCH] ehci, remove potential hangs

These don't affect the hang I'm hunting for, but paranoia
argues the patch is better integrated than not:

- prevent resubmit-from-completion looping in_irq if the
   transfers complete really fast.  (likely never seen, but...)

- grab ehci lock before reading irq status; should be harmless
   except in one host error cleanup-after-death


diff -Nru a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
--- a/drivers/usb/host/ehci-hcd.c       Wed Jan  8 12:03:21 2003
+++ b/drivers/usb/host/ehci-hcd.c       Wed Jan  8 12:03:21 2003
@@ -637,9 +637,13 @@
 static void ehci_irq (struct usb_hcd *hcd, struct pt_regs *regs)
 {
        struct ehci_hcd         *ehci = hcd_to_ehci (hcd);
-       u32                     status = readl (&ehci->regs->status);
+       u32                     status;
        int                     bh;
 
+       spin_lock (&ehci->lock);
+
+       status = readl (&ehci->regs->status);
+
        /* e.g. cardbus physical eject */
        if (status == ~(u32) 0) {
                ehci_dbg (ehci, "device removed\n");
@@ -648,9 +652,7 @@
 
        status &= INTR_MASK;
        if (!status)                    /* irq sharing? */
-               return;
-
-       spin_lock (&ehci->lock);
+               goto done;
 
        /* clear (just) interrupts */
        writel (status, &ehci->regs->status);
@@ -693,6 +695,7 @@
 
        if (bh)
                ehci_work (ehci, regs);
+done:
        spin_unlock (&ehci->lock);
 }
 
diff -Nru a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c
--- a/drivers/usb/host/ehci-q.c Wed Jan  8 12:03:21 2003
+++ b/drivers/usb/host/ehci-q.c Wed Jan  8 12:03:21 2003
@@ -222,7 +222,7 @@
 static unsigned
 qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh, struct pt_regs *regs)
 {
-       struct ehci_qtd         *last = 0;
+       struct ehci_qtd         *last = 0, *end = qh->dummy;
        struct list_head        *entry, *tmp;
        int                     stopped = 0;
        unsigned                count = 0;
@@ -253,6 +253,10 @@
                        last = 0;
                }
 
+               /* ignore urbs submitted during completions we reported */
+               if (qtd == end)
+                       break;
+
                /* hardware copies qtd out of qh overlay */
                rmb ();
                token = le32_to_cpu (qtd->hw_token);
@@ -967,25 +971,28 @@
 scan_async (struct ehci_hcd *ehci, struct pt_regs *regs)
 {
        struct ehci_qh          *qh;
-       unsigned                count;
 
+       if (!++(ehci->stamp))
+               ehci->stamp++;
 rescan:
        qh = ehci->async->qh_next.qh;
-       count = 0;
        if (likely (qh != 0)) {
                do {
                        /* clean any finished work for this qh */
-                       if (!list_empty (&qh->qtd_list)) {
+                       if (!list_empty (&qh->qtd_list)
+                                       && qh->stamp != ehci->stamp) {
                                int temp;
 
                                /* unlinks could happen here; completion
-                                * reporting drops the lock.
+                                * reporting drops the lock.  rescan using
+                                * the latest schedule, but don't rescan
+                                * qhs we already finished (no looping).
                                 */
                                qh = qh_get (qh);
+                               qh->stamp = ehci->stamp;
                                temp = qh_completions (ehci, qh, regs);
                                qh_put (ehci, qh);
                                if (temp != 0) {
-                                       count += temp;
                                        goto rescan;
                                }
                        }
diff -Nru a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
--- a/drivers/usb/host/ehci.h   Wed Jan  8 12:03:21 2003
+++ b/drivers/usb/host/ehci.h   Wed Jan  8 12:03:21 2003
@@ -81,6 +81,7 @@
        struct pci_pool         *sitd_pool;     /* sitd per split iso urb */
 
        struct timer_list       watchdog;
+       unsigned                stamp;
 
 #ifdef EHCI_STATS
        struct ehci_stats       stats;
@@ -306,6 +307,7 @@
        struct ehci_qtd         *dummy;
 
        atomic_t                refcount;
+       unsigned                stamp;
 
        u8                      qh_state;
 #define        QH_STATE_LINKED         1               /* HC sees this */



-------------------------------------------------------
This SF.NET email is sponsored by:
SourceForge Enterprise Edition + IBM + LinuxWorld = Something 2 See!
http://www.vasoftware.com
_______________________________________________
[EMAIL PROTECTED]
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel

Reply via email to