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)
