David Brownell wrote:
This patch syncs the 2.4 version with the latest from 2.5 ...
to make it easier for folk to use this before the "host"
directory rename, I decided not to depend on that patch yet.

Whoops ... apologies. This is the version that applies to generic 2.4.21-pre5, the preceding version expects the rename to have been done.

Editors should really be able to just _know_ when you want
files to have been written out ... ;)

- Dave


--- greg-2.4/drivers/usb/hcd/ehci-dbg.c Mon Mar  3 11:11:20 2003
+++ usb-2.4/drivers/usb/hcd/ehci-dbg.c  Mon Mar  3 11:33:58 2003
@@ -615,8 +615,10 @@
        }
 
 #ifdef EHCI_STATS
-       temp = snprintf (next, size, "irq normal %ld err %ld reclaim %ld\n",
-               ehci->stats.normal, ehci->stats.error, ehci->stats.reclaim);
+       temp = snprintf (next, size,
+               "irq normal %ld err %ld reclaim %ld (lost %ld)\n",
+               ehci->stats.normal, ehci->stats.error, ehci->stats.reclaim,
+               ehci->stats.lost_iaa);
        size -= temp;
        next += temp;
 
--- greg-2.4/drivers/usb/hcd/ehci-hcd.c Mon Mar  3 11:11:20 2003
+++ usb-2.4/drivers/usb/hcd/ehci-hcd.c  Mon Mar  3 11:33:58 2003
@@ -30,6 +30,7 @@
 #include <linux/timer.h>
 #include <linux/list.h>
 #include <linux/interrupt.h>
+#include <linux/reboot.h>
 
 #ifdef CONFIG_USB_DEBUG
        #define DEBUG
@@ -261,6 +262,7 @@
 
                if (status & STS_IAA) {
                        ehci_vdbg (ehci, "lost IAA\n");
+                       COUNT (ehci->stats.lost_iaa);
                        writel (STS_IAA, &ehci->regs->status);
                        ehci->reclaim_ready = 1;
                }
@@ -307,6 +309,19 @@
        return 0;
 }
 
+static int
+ehci_reboot (struct notifier_block *self, unsigned long code, void *null)
+{
+       struct ehci_hcd         *ehci;
+
+       ehci = container_of (self, struct ehci_hcd, reboot_notifier);
+
+       /* make BIOS/etc use companion controller during reboot */
+       writel (0, &ehci->regs->configured_flag);
+       return 0;
+}
+
+
 /* called by khubd or root hub init threads */
 
 static int ehci_start (struct usb_hcd *hcd)
@@ -465,6 +480,9 @@
         * are explicitly handed to companion controller(s), so no TT is
         * involved with the root hub.
         */
+       ehci->reboot_notifier.notifier_call = ehci_reboot;
+       register_reboot_notifier (&ehci->reboot_notifier);
+
        ehci->hcd.state = USB_STATE_READY;
        writel (FLAG_CF, &ehci->regs->configured_flag);
        readl (&ehci->regs->command);   /* unblock posted write */
@@ -491,6 +509,7 @@
                        ehci_ready (ehci);
                ehci_reset (ehci);
                bus->root_hub = 0;
+               usb_free_dev (udev); 
                retval = -ENODEV;
                goto done2;
        }
@@ -520,6 +539,7 @@
 
        /* let companion controllers work when we aren't */
        writel (0, &ehci->regs->configured_flag);
+       unregister_reboot_notifier (&ehci->reboot_notifier);
 
        remove_debug_files (ehci);
 
@@ -530,8 +550,9 @@
        ehci_mem_cleanup (ehci);
 
 #ifdef EHCI_STATS
-       ehci_dbg (ehci, "irq normal %ld err %ld reclaim %ld\n",
-               ehci->stats.normal, ehci->stats.error, ehci->stats.reclaim);
+       ehci_dbg (ehci, "irq normal %ld err %ld reclaim %ld (lost %ld)\n",
+               ehci->stats.normal, ehci->stats.error, ehci->stats.reclaim,
+               ehci->stats.lost_iaa);
        ehci_dbg (ehci, "complete %ld unlink %ld\n",
                ehci->stats.complete, ehci->stats.unlink);
 #endif
--- greg-2.4/drivers/usb/hcd/ehci-q.c   Mon Mar  3 11:11:20 2003
+++ usb-2.4/drivers/usb/hcd/ehci-q.c    Mon Mar  3 11:33:58 2003
@@ -746,6 +746,11 @@
                if (!(cmd & CMD_ASE)) {
                        /* in case a clear of CMD_ASE didn't take yet */
                        (void) handshake (&ehci->regs->status, STS_ASS, 0, 150);
+
+                       /* force async head to be valid */
+                       writel ((u32)ehci->async->qh_dma,
+                                       &ehci->regs->async_next);
+
                        cmd |= CMD_ASE | CMD_RUN;
                        writel (cmd, &ehci->regs->command);
                        ehci->hcd.state = USB_STATE_RUNNING;
@@ -834,6 +839,7 @@
                                && !usb_pipecontrol (urb->pipe)) {
                        /* "never happens": drivers do stall cleanup right */
                        if (qh->qh_state != QH_STATE_IDLE
+                                       && !list_empty (&qh->qtd_list)
                                        && qh->qh_state != QH_STATE_COMPLETING)
                                ehci_warn (ehci, "clear toggle dev%d "
                                                "ep%d%s: not idle\n",
@@ -949,7 +955,7 @@
 
        del_timer (&ehci->watchdog);
 
-       qh->hw_next = cpu_to_le32 (qh->qh_dma);
+       // qh->hw_next = cpu_to_le32 (qh->qh_dma);
        qh->qh_state = QH_STATE_IDLE;
        qh->qh_next.qh = 0;
        qh_put (ehci, qh);                      // refcount from reclaim 
@@ -1048,6 +1054,7 @@
 scan_async (struct ehci_hcd *ehci, struct pt_regs *regs)
 {
        struct ehci_qh          *qh;
+       int                     unlink_delay = 0;
 
        if (!++(ehci->stamp))
                ehci->stamp++;
@@ -1074,17 +1081,25 @@
                                }
                        }
 
-                       /* unlink idle entries, reducing HC PCI usage as
-                        * well as HCD schedule-scanning costs.
-                        *
-                        * FIXME don't unlink idle entries so quickly; it
-                        * can penalize (common) half duplex protocols.
+                       /* unlink idle entries, reducing HC PCI usage as well
+                        * as HCD schedule-scanning costs.  delay for any qh
+                        * we just scanned, there's a not-unusual case that it
+                        * doesn't stay idle for long.
+                        * (plus, avoids some kind of re-activation race.)
                         */
-                       if (list_empty (&qh->qtd_list) && !ehci->reclaim) {
-                               start_unlink_async (ehci, qh);
+                       if (list_empty (&qh->qtd_list)) {
+                               if (qh->stamp == ehci->stamp)
+                                       unlink_delay = 1;
+                               else if (!ehci->reclaim) {
+                                       start_unlink_async (ehci, qh);
+                                       unlink_delay = 0;
+                               }
                        }
 
                        qh = qh->qh_next.qh;
                } while (qh);
        }
+
+       if (unlink_delay && !timer_pending (&ehci->watchdog))
+               mod_timer (&ehci->watchdog, jiffies + EHCI_WATCHDOG_JIFFIES/2);
 }
--- greg-2.4/drivers/usb/hcd/ehci.h     Mon Mar  3 11:11:20 2003
+++ usb-2.4/drivers/usb/hcd/ehci.h      Mon Mar  3 11:33:58 2003
@@ -27,6 +27,7 @@
        unsigned long           normal;
        unsigned long           error;
        unsigned long           reclaim;
+       unsigned long           lost_iaa;
 
        /* termination of urbs from core */
        unsigned long           complete;
@@ -81,8 +82,10 @@
        struct pci_pool         *sitd_pool;     /* sitd per split iso urb */
 
        struct timer_list       watchdog;
+       struct notifier_block   reboot_notifier;
        unsigned                stamp;
 
+       /* irq statistics */
 #ifdef EHCI_STATS
        struct ehci_stats       stats;
 #      define COUNT(x) do { (x)++; } while (0)

Reply via email to