tree 64cd816ac2f9e119d8c1afd330e8f737ab643617
parent f8d23d309809ae69c763520dababb7e845938272
author Olav Kongas <[EMAIL PROTECTED]> Fri, 05 Aug 2005 14:23:35 +0300
committer Greg Kroah-Hartman <[EMAIL PROTECTED]> Fri, 09 Sep 2005 06:22:48 -0700

[PATCH] USB: Switch isp116x-hcd over to root hub interrupt

Switch isp116x-hcd over from root hub polling to interrupt.  This change closes
also a race that was present with the old polling scheme: status polling could
happen in a time window, where root hub status bits were not stable.

Signed-off-by: Olav Kongas <[EMAIL PROTECTED]>
Signed-off-by: Greg Kroah-Hartman <[EMAIL PROTECTED]>

 drivers/usb/host/isp116x-hcd.c |   35 ++++++++++++++++++++++-------------
 1 files changed, 22 insertions(+), 13 deletions(-)

diff --git a/drivers/usb/host/isp116x-hcd.c b/drivers/usb/host/isp116x-hcd.c
--- a/drivers/usb/host/isp116x-hcd.c
+++ b/drivers/usb/host/isp116x-hcd.c
@@ -83,7 +83,7 @@
 #include "../core/hcd.h"
 #include "isp116x.h"
 
-#define DRIVER_VERSION "08 Apr 2005"
+#define DRIVER_VERSION "05 Aug 2005"
 #define DRIVER_DESC    "ISP116x USB Host Controller Driver"
 
 MODULE_DESCRIPTION(DRIVER_DESC);
@@ -629,14 +629,12 @@ static irqreturn_t isp116x_irq(struct us
                        ERR("Unrecoverable error\n");
                        /* What should we do here? Reset?  */
                }
-               if (intstat & HCINT_RHSC) {
-                       isp116x->rhstatus =
-                           isp116x_read_reg32(isp116x, HCRHSTATUS);
-                       isp116x->rhport[0] =
-                           isp116x_read_reg32(isp116x, HCRHPORT1);
-                       isp116x->rhport[1] =
-                           isp116x_read_reg32(isp116x, HCRHPORT2);
-               }
+               if (intstat & HCINT_RHSC)
+                       /* When root hub or any of its ports is going
+                          to come out of suspend, it may take more
+                          than 10ms for status bits to stabilize. */
+                       mod_timer(&hcd->rh_timer, jiffies
+                                 + msecs_to_jiffies(20) + 1);
                if (intstat & HCINT_RD) {
                        DBG("---- remote wakeup\n");
                        schedule_work(&isp116x->rh_resume);
@@ -925,20 +923,27 @@ static int isp116x_hub_status_data(struc
 {
        struct isp116x *isp116x = hcd_to_isp116x(hcd);
        int ports, i, changed = 0;
+       unsigned long flags;
 
        if (!HC_IS_RUNNING(hcd->state))
                return -ESHUTDOWN;
 
-       ports = isp116x->rhdesca & RH_A_NDP;
+       /* Report no status change now, if we are scheduled to be
+          called later */
+       if (timer_pending(&hcd->rh_timer))
+               return 0;
 
-       /* init status */
+       ports = isp116x->rhdesca & RH_A_NDP;
+       spin_lock_irqsave(&isp116x->lock, flags);
+       isp116x->rhstatus = isp116x_read_reg32(isp116x, HCRHSTATUS);
        if (isp116x->rhstatus & (RH_HS_LPSC | RH_HS_OCIC))
                buf[0] = changed = 1;
        else
                buf[0] = 0;
 
        for (i = 0; i < ports; i++) {
-               u32 status = isp116x->rhport[i];
+               u32 status = isp116x->rhport[i] =
+                   isp116x_read_reg32(isp116x, i ? HCRHPORT2 : HCRHPORT1);
 
                if (status & (RH_PS_CSC | RH_PS_PESC | RH_PS_PSSC
                              | RH_PS_OCIC | RH_PS_PRSC)) {
@@ -947,6 +952,7 @@ static int isp116x_hub_status_data(struc
                        continue;
                }
        }
+       spin_unlock_irqrestore(&isp116x->lock, flags);
        return changed;
 }
 
@@ -1536,6 +1542,9 @@ static int isp116x_start(struct usb_hcd 
                return -ENODEV;
        }
 
+       /* To be removed in future */
+       hcd->uses_new_polling = 1;
+
        isp116x_write_reg16(isp116x, HCITLBUFLEN, ISP116x_ITL_BUFSIZE);
        isp116x_write_reg16(isp116x, HCATLBUFLEN, ISP116x_ATL_BUFSIZE);
 
@@ -1639,7 +1648,7 @@ static int __init_or_module isp116x_remo
        struct platform_device *pdev;
        struct resource *res;
 
-       if(!hcd)
+       if (!hcd)
                return 0;
        isp116x = hcd_to_isp116x(hcd);
        pdev = container_of(dev, struct platform_device, dev);
-
To unsubscribe from this list: send the line "unsubscribe git-commits-head" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to