From: Greg Kroah-Hartman <[EMAIL PROTECTED]>

This reverts 26f953fd884ea4879585287917f855c63c6b2666 which caused
resume problems on the mac mini.

Cc: David Brownell <[EMAIL PROTECTED]>
Signed-off-by: Greg Kroah-Hartman <[EMAIL PROTECTED]>
---
 drivers/usb/host/ehci-dbg.c |    4 ++
 drivers/usb/host/ehci-hcd.c |   70 +++++++++++++------------------------------
 drivers/usb/host/ehci-hub.c |    2 +
 drivers/usb/host/ehci-pci.c |    2 +
 drivers/usb/host/ehci-q.c   |    6 ++--
 drivers/usb/host/ehci.h     |   22 ++++----------
 6 files changed, 37 insertions(+), 69 deletions(-)

diff --git a/drivers/usb/host/ehci-dbg.c b/drivers/usb/host/ehci-dbg.c
index 23b95b2..34b7a31 100644
--- a/drivers/usb/host/ehci-dbg.c
+++ b/drivers/usb/host/ehci-dbg.c
@@ -754,7 +754,9 @@ #endif
        }
 
        if (ehci->reclaim) {
-               temp = scnprintf (next, size, "reclaim qh %p\n", ehci->reclaim);
+               temp = scnprintf (next, size, "reclaim qh %p%s\n",
+                               ehci->reclaim,
+                               ehci->reclaim_ready ? " ready" : "");
                size -= temp;
                next += temp;
        }
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index aac6ec5..9030994 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -111,7 +111,7 @@ #define     EHCI_TUNE_MULT_HS       1       /* 1-3 trans
 #define        EHCI_TUNE_MULT_TT       1
 #define        EHCI_TUNE_FLS           2       /* (small) 256 frame schedule */
 
-#define EHCI_IAA_MSECS         10              /* arbitrary */
+#define EHCI_IAA_JIFFIES       (HZ/100)        /* arbitrary; ~10 msec */
 #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 */
@@ -254,7 +254,6 @@ #endif
 
 /*-------------------------------------------------------------------------*/
 
-static void end_unlink_async (struct ehci_hcd *ehci);
 static void ehci_work(struct ehci_hcd *ehci);
 
 #include "ehci-hub.c"
@@ -264,37 +263,25 @@ #include "ehci-sched.c"
 
 /*-------------------------------------------------------------------------*/
 
-static void ehci_iaa_watchdog (unsigned long param)
+static void ehci_watchdog (unsigned long param)
 {
        struct ehci_hcd         *ehci = (struct ehci_hcd *) param;
        unsigned long           flags;
-       u32                     status;
 
        spin_lock_irqsave (&ehci->lock, flags);
-       WARN_ON(!ehci->reclaim);
 
-       /* lost IAA irqs wedge things badly; seen first with a vt8235 */
+       /* lost IAA irqs wedge things badly; seen with a vt8235 */
        if (ehci->reclaim) {
-               status = readl (&ehci->regs->status);
+               u32             status = readl (&ehci->regs->status);
                if (status & STS_IAA) {
                        ehci_vdbg (ehci, "lost IAA\n");
                        COUNT (ehci->stats.lost_iaa);
                        writel (STS_IAA, &ehci->regs->status);
-                       end_unlink_async (ehci);
+                       ehci->reclaim_ready = 1;
                }
        }
 
-       spin_unlock_irqrestore (&ehci->lock, flags);
-}
-
-static void ehci_watchdog (unsigned long param)
-{
-       struct ehci_hcd         *ehci = (struct ehci_hcd *) param;
-       unsigned long           flags;
-
-       spin_lock_irqsave (&ehci->lock, flags);
-
-       /* stop async processing after it's idled a bit */
+       /* stop async processing after it's idled a bit */
        if (test_bit (TIMER_ASYNC_OFF, &ehci->actions))
                start_unlink_async (ehci, ehci->async);
 
@@ -345,6 +332,8 @@ static void ehci_port_power (struct ehci
 static void ehci_work (struct ehci_hcd *ehci)
 {
        timer_action_done (ehci, TIMER_IO_WATCHDOG);
+       if (ehci->reclaim_ready)
+               end_unlink_async (ehci);
 
        /* another CPU may drop ehci->lock during a schedule scan while
         * it reports urb completions.  this flag guards against bogus
@@ -379,7 +368,6 @@ static void ehci_stop (struct usb_hcd *h
 
        /* no more interrupts ... */
        del_timer_sync (&ehci->watchdog);
-       del_timer_sync (&ehci->iaa_watchdog);
 
        spin_lock_irq(&ehci->lock);
        if (HC_IS_RUNNING (hcd->state))
@@ -426,10 +414,6 @@ static int ehci_init(struct usb_hcd *hcd
        ehci->watchdog.function = ehci_watchdog;
        ehci->watchdog.data = (unsigned long) ehci;
 
-       init_timer(&ehci->iaa_watchdog);
-       ehci->iaa_watchdog.function = ehci_iaa_watchdog;
-       ehci->iaa_watchdog.data = (unsigned long) ehci;
-
        /*
         * hw default: 1K periodic list heads, one per frame.
         * periodic_size can shrink by USBCMD update if hcc_params allows.
@@ -446,6 +430,7 @@ static int ehci_init(struct usb_hcd *hcd
                ehci->i_thresh = 2 + HCC_ISOC_THRES(hcc_params);
 
        ehci->reclaim = NULL;
+       ehci->reclaim_ready = 0;
        ehci->next_uframe = -1;
 
        /*
@@ -619,7 +604,7 @@ #endif
        /* complete the unlinking of some qh [4.15.2.3] */
        if (status & STS_IAA) {
                COUNT (ehci->stats.reclaim);
-               end_unlink_async (ehci);
+               ehci->reclaim_ready = 1;
                bh = 1;
        }
 
@@ -723,14 +708,10 @@ static int ehci_urb_enqueue (
 
 static void unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh)
 {
-       // BUG_ON(qh->qh_state != QH_STATE_LINKED);
-
-       /* failfast */
-       if (!HC_IS_RUNNING (ehci_to_hcd(ehci)->state))
-               end_unlink_async (ehci);
-
-       /* defer till later if busy */
-       else if (ehci->reclaim) {
+       /* if we need to use IAA and it's busy, defer */
+       if (qh->qh_state == QH_STATE_LINKED
+                       && ehci->reclaim
+                       && HC_IS_RUNNING (ehci_to_hcd(ehci)->state)) {
                struct ehci_qh          *last;
 
                for (last = ehci->reclaim;
@@ -740,8 +721,12 @@ static void unlink_async (struct ehci_hc
                qh->qh_state = QH_STATE_UNLINK_WAIT;
                last->reclaim = qh;
 
-       /* start IAA cycle */
-       } else
+       /* bypass IAA if the hc can't care */
+       } else if (!HC_IS_RUNNING (ehci_to_hcd(ehci)->state) && ehci->reclaim)
+               end_unlink_async (ehci);
+
+       /* something else might have unlinked the qh by now */
+       if (qh->qh_state == QH_STATE_LINKED)
                start_unlink_async (ehci, qh);
 }
 
@@ -763,19 +748,7 @@ static int ehci_urb_dequeue (struct usb_
                qh = (struct ehci_qh *) urb->hcpriv;
                if (!qh)
                        break;
-               switch (qh->qh_state) {
-               case QH_STATE_LINKED:
-               case QH_STATE_COMPLETING:
-                       unlink_async (ehci, qh);
-                       break;
-               case QH_STATE_UNLINK:
-               case QH_STATE_UNLINK_WAIT:
-                       /* already started */
-                       break;
-               case QH_STATE_IDLE:
-                       WARN_ON(1);
-                       break;
-               }
+               unlink_async (ehci, qh);
                break;
 
        case PIPE_INTERRUPT:
@@ -867,7 +840,6 @@ rescan:
                unlink_async (ehci, qh);
                /* FALL THROUGH */
        case QH_STATE_UNLINK:           /* wait for hw to finish? */
-       case QH_STATE_UNLINK_WAIT:
 idle_timeout:
                spin_unlock_irqrestore (&ehci->lock, flags);
                schedule_timeout_uninterruptible(1);
diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c
index 2012213..1b20722 100644
--- a/drivers/usb/host/ehci-hub.c
+++ b/drivers/usb/host/ehci-hub.c
@@ -48,7 +48,7 @@ static int ehci_bus_suspend (struct usb_
        }
        ehci->command = readl (&ehci->regs->command);
        if (ehci->reclaim)
-               end_unlink_async (ehci);
+               ehci->reclaim_ready = 1;
        ehci_work(ehci);
 
        /* suspend any active/unsuspended ports, maybe allow wakeup */
diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c
index 35e3fab..e51c1ed 100644
--- a/drivers/usb/host/ehci-pci.c
+++ b/drivers/usb/host/ehci-pci.c
@@ -303,7 +303,7 @@ restart:
        /* emptying the schedule aborts any urbs */
        spin_lock_irq(&ehci->lock);
        if (ehci->reclaim)
-               end_unlink_async (ehci);
+               ehci->reclaim_ready = 1;
        ehci_work(ehci);
        spin_unlock_irq(&ehci->lock);
 
diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c
index 4632727..62e46dc 100644
--- a/drivers/usb/host/ehci-q.c
+++ b/drivers/usb/host/ehci-q.c
@@ -967,7 +967,7 @@ static void end_unlink_async (struct ehc
        struct ehci_qh          *qh = ehci->reclaim;
        struct ehci_qh          *next;
 
-       iaa_watchdog_done (ehci);
+       timer_action_done (ehci, TIMER_IAA_WATCHDOG);
 
        // qh->hw_next = cpu_to_le32 (qh->qh_dma);
        qh->qh_state = QH_STATE_IDLE;
@@ -977,6 +977,7 @@ static void end_unlink_async (struct ehc
        /* other unlink(s) may be pending (in QH_STATE_UNLINK_WAIT) */
        next = qh->reclaim;
        ehci->reclaim = next;
+       ehci->reclaim_ready = 0;
        qh->reclaim = NULL;
 
        qh_completions (ehci, qh);
@@ -1051,10 +1052,11 @@ #endif
                return;
        }
 
+       ehci->reclaim_ready = 0;
        cmd |= CMD_IAAD;
        writel (cmd, &ehci->regs->command);
        (void) readl (&ehci->regs->command);
-       iaa_watchdog_start (ehci);
+       timer_action (ehci, TIMER_IAA_WATCHDOG);
 }
 
 /*-------------------------------------------------------------------------*/
diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
index 6aac39f..bbc3082 100644
--- a/drivers/usb/host/ehci.h
+++ b/drivers/usb/host/ehci.h
@@ -58,6 +58,7 @@ struct ehci_hcd {                     /* one per controlle
        /* async schedule support */
        struct ehci_qh          *async;
        struct ehci_qh          *reclaim;
+       unsigned                reclaim_ready : 1;
        unsigned                scanning : 1;
 
        /* periodic schedule support */
@@ -80,7 +81,6 @@ #define       DEFAULT_I_TDPS          1024            /* some 
HC
        struct dma_pool         *itd_pool;      /* itd per iso urb */
        struct dma_pool         *sitd_pool;     /* sitd per split iso urb */
 
-       struct timer_list       iaa_watchdog;
        struct timer_list       watchdog;
        unsigned long           actions;
        unsigned                stamp;
@@ -114,21 +114,9 @@ static inline struct usb_hcd *ehci_to_hc
 }
 
 
-static inline void
-iaa_watchdog_start (struct ehci_hcd *ehci)
-{
-       WARN_ON(timer_pending(&ehci->iaa_watchdog));
-       mod_timer (&ehci->iaa_watchdog,
-                       jiffies + msecs_to_jiffies(EHCI_IAA_MSECS));
-}
-
-static inline void iaa_watchdog_done (struct ehci_hcd *ehci)
-{
-       del_timer (&ehci->iaa_watchdog);
-}
-
 enum ehci_timer_action {
        TIMER_IO_WATCHDOG,
+       TIMER_IAA_WATCHDOG,
        TIMER_ASYNC_SHRINK,
        TIMER_ASYNC_OFF,
 };
@@ -146,6 +134,9 @@ timer_action (struct ehci_hcd *ehci, enu
                unsigned long t;
 
                switch (action) {
+               case TIMER_IAA_WATCHDOG:
+                       t = EHCI_IAA_JIFFIES;
+                       break;
                case TIMER_IO_WATCHDOG:
                        t = EHCI_IO_JIFFIES;
                        break;
@@ -162,7 +153,8 @@ timer_action (struct ehci_hcd *ehci, enu
                // async queue SHRINK often precedes IAA.  while it's ready
                // to go OFF neither can matter, and afterwards the IO
                // watchdog stops unless there's still periodic traffic.
-               if (time_before_eq(t, ehci->watchdog.expires)
+               if (action != TIMER_IAA_WATCHDOG
+                               && t > ehci->watchdog.expires
                                && timer_pending (&ehci->watchdog))
                        return;
                mod_timer (&ehci->watchdog, t);
-- 
1.4.2.4


-------------------------------------------------------------------------
Using Tomcat but need to do more? Need to support web services, security?
Get stuff done quickly with pre-integrated technology to make your job easier
Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642
_______________________________________________
linux-usb-devel@lists.sourceforge.net
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel

Reply via email to