# This is a BitKeeper generated patch for the following project: # Project Name: Linux kernel tree # This patch format is intended for GNU patch command version 2.5 or higher. # This patch includes the following deltas: # ChangeSet 1.655 -> 1.656 # drivers/usb/host/ehci-q.c 1.25 -> 1.26 # drivers/usb/host/ehci-hcd.c 1.27 -> 1.28 # drivers/usb/host/ehci.h 1.10 -> 1.11 # # The following is the BitKeeper ChangeSet Log # -------------------------------------------- # 02/09/11 david-b@pacbell.net 1.656 # [PATCH] ehci, async idle timout # # One more patch: this turns off async schedule processing # if there are no control or bulk transactions for a while # (currently HZ/3). Consequence: no PCI accesses unless # there's work to do. (And a FIXME comment is gone!) # -------------------------------------------- # diff -Nru a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c --- a/drivers/usb/host/ehci-hcd.c Thu Sep 12 10:25:42 2002 +++ b/drivers/usb/host/ehci-hcd.c Thu Sep 12 10:25:42 2002 @@ -111,6 +111,7 @@ #define EHCI_TUNE_MULT_TT 1 #define EHCI_WATCHDOG_JIFFIES (HZ/100) /* arbitrary; ~10 msec */ +#define EHCI_ASYNC_JIFFIES (HZ/3) /* async idle timeout */ /* Initial IRQ latency: lower than default */ static int log2_irq_thresh = 0; // 0 to 6 @@ -247,9 +248,14 @@ struct ehci_hcd *ehci = (struct ehci_hcd *) param; unsigned long flags; - /* guard against lost IAA, which wedges everything */ spin_lock_irqsave (&ehci->lock, flags); + /* guard against lost IAA, which wedges everything */ ehci_irq (&ehci->hcd); + /* unlink the last qh after it's idled a while */ + if (ehci->async_idle) { + start_unlink_async (ehci, ehci->async); + ehci->async_idle = 0; + } spin_unlock_irqrestore (&ehci->lock, flags); } diff -Nru a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c --- a/drivers/usb/host/ehci-q.c Thu Sep 12 10:25:42 2002 +++ b/drivers/usb/host/ehci-q.c Thu Sep 12 10:25:42 2002 @@ -736,6 +736,8 @@ } qh->qh_state = QH_STATE_LINKED; /* qtd completions reported later by interrupt */ + + ehci->async_idle = 0; } /*-------------------------------------------------------------------------*/ @@ -1004,16 +1006,18 @@ } /* unlink idle entries, reducing HC PCI usage as - * well as HCD schedule-scanning costs + * well as HCD schedule-scanning costs. removing + * the last qh is deferred, since it's costly. */ if (list_empty (&qh->qtd_list) && !ehci->reclaim) { if (qh->qh_next.qh != qh) { // dbg ("irq/empty"); start_unlink_async (ehci, qh); - } else { - // FIXME: arrange to stop - // after it's been idle a while. - // stop/restart isn't free... + } else if (!timer_pending (&ehci->watchdog)) { + /* can't use IAA for last entry */ + ehci->async_idle = 1; + mod_timer (&ehci->watchdog, + jiffies + EHCI_ASYNC_JIFFIES); } } qh = qh->qh_next.qh; diff -Nru a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h --- a/drivers/usb/host/ehci.h Thu Sep 12 10:25:42 2002 +++ b/drivers/usb/host/ehci.h Thu Sep 12 10:25:42 2002 @@ -39,7 +39,8 @@ /* async schedule support */ struct ehci_qh *async; struct ehci_qh *reclaim; - int reclaim_ready; + int reclaim_ready : 1, + async_idle : 1; /* periodic schedule support */ #define DEFAULT_I_TDPS 1024 /* some HCs can do less */