diff -Nurb linux-2.6.16.1/drivers/usb/host/ehci.h linux-patched/drivers/usb/host/ehci.h --- linux-2.6.16.1/drivers/usb/host/ehci.h 2006-03-27 22:49:02.000000000 -0800 +++ linux-patched/drivers/usb/host/ehci.h 2006-04-07 12:07:30.000000000 -0700 @@ -82,6 +82,7 @@ struct dma_pool *sitd_pool; /* sitd per split iso urb */ struct timer_list watchdog; + struct timer_list softirq; unsigned long actions; unsigned stamp; unsigned long next_statechange; diff -Nurb linux-2.6.16.1/drivers/usb/host/ehci-hcd.c linux-patched/drivers/usb/host/ehci-hcd.c --- linux-2.6.16.1/drivers/usb/host/ehci-hcd.c 2006-03-27 22:49:02.000000000 -0800 +++ linux-patched/drivers/usb/host/ehci-hcd.c 2006-04-07 13:20:13.000000000 -0700 @@ -116,6 +116,7 @@ #define EHCI_IO_JIFFIES (HZ/10) /* io watchdog > irq_thresh */ #define EHCI_ASYNC_JIFFIES (HZ/20) /* async idle timeout */ #define EHCI_SHRINK_JIFFIES (HZ/200) /* async qh unlink delay */ +#define EHCI_SOFTIRQ (HZ/400) /* Initial IRQ latency: faster than hw default */ static int log2_irq_thresh = 0; // 0 to 6 @@ -263,6 +264,16 @@ #include "ehci-sched.c" /*-------------------------------------------------------------------------*/ +static irqreturn_t ehci_irq (struct usb_hcd *hcd); + +static void ehci_softirq (unsigned long param) +{ + struct ehci_hcd *ehci = (struct ehci_hcd *) param; + + if (ehci_irq(ehci_to_hcd(ehci)) != IRQ_NONE) + set_bit(HCD_FLAG_SAW_IRQ, &(ehci_to_hcd(ehci))->flags); + mod_timer (&ehci->softirq, jiffies + EHCI_SOFTIRQ); +} static void ehci_watchdog (unsigned long param) { @@ -280,6 +291,10 @@ COUNT (ehci->stats.lost_iaa); writel (STS_IAA, &ehci->regs->status); ehci->reclaim_ready = 1; + if (!timer_pending(&ehci->softirq)) { + ehci_info(ehci, "switching to softirq\n"); + mod_timer (&ehci->softirq, jiffies + EHCI_SOFTIRQ); + } } } @@ -371,6 +388,7 @@ /* no more interrupts ... */ del_timer_sync (&ehci->watchdog); + del_timer_sync (&ehci->softirq); spin_lock_irq(&ehci->lock); if (HC_IS_RUNNING (hcd->state)) @@ -418,6 +436,10 @@ ehci->watchdog.function = ehci_watchdog; ehci->watchdog.data = (unsigned long) ehci; + init_timer(&ehci->softirq); + ehci->softirq.function = ehci_softirq; + ehci->softirq.data = (unsigned long) ehci; + /* * hw default: 1K periodic list heads, one per frame. * periodic_size can shrink by USBCMD update if hcc_params allows.