Use time_after() to avoid looping forever.

Signed-off-by: Felipe Balbi <[email protected]>
---
 drivers/usb/host/ehci-omap.c |   87 +++++++++++++++++++++++++++++++++++++-----
 1 files changed, 77 insertions(+), 10 deletions(-)

diff --git a/drivers/usb/host/ehci-omap.c b/drivers/usb/host/ehci-omap.c
index 2bdc978..35c645d 100644
--- a/drivers/usb/host/ehci-omap.c
+++ b/drivers/usb/host/ehci-omap.c
@@ -182,6 +182,7 @@ struct ehci_omap_clock_defs {
 
 static void omap_usb_utmi_init(struct usb_hcd *hcd, u8 tll_channel_mask)
 {
+       unsigned long timeout = jiffies + msecs_to_jiffies(100);
        int i;
 
        /* Use UTMI Ports of TLL */
@@ -193,9 +194,15 @@ static void omap_usb_utmi_init(struct usb_hcd *hcd, u8 
tll_channel_mask)
                                                OMAP_UHH_HOSTCONFIG);
        /* Enusre bit is set */
        while (!(omap_readl(OMAP_UHH_HOSTCONFIG)
-                       & (1 << OMAP_UHH_HOSTCONFIG_ULPI_BYPASS_SHIFT)))
+                       & (1 << OMAP_UHH_HOSTCONFIG_ULPI_BYPASS_SHIFT))) {
                cpu_relax();
 
+               if (time_after(timeout, jiffies)) {
+                       dev_dbg(hcd->self.controller, "operation timed out\n");
+                       return;
+               }
+       }
+
        dev_dbg(hcd->self.controller, "Entered UTMI MODE: success\n");
 
        /* Program the 3 TLL channels upfront */
@@ -254,6 +261,7 @@ static void omap_usb_utmi_init(struct usb_hcd *hcd, u8 
tll_channel_mask)
 static int omap_start_ehc(struct platform_device *dev, struct usb_hcd *hcd)
 {
        struct ehci_omap_clock_defs *ehci_clocks;
+       unsigned long timeout = jiffies + msecs_to_jiffies(100);
 
        dev_dbg(hcd->self.controller, "starting TI EHCI USB Controller\n");
 
@@ -278,10 +286,16 @@ static int omap_start_ehc(struct platform_device *dev, 
struct usb_hcd *hcd)
                        PLL_MOD, OMAP3430ES2_CM_CLKEN2);
 
        while (!(cm_read_mod_reg(PLL_MOD, CM_IDLEST2) &
-                               OMAP3430ES2_ST_PERIPH2_CLK_MASK))
+                               OMAP3430ES2_ST_PERIPH2_CLK_MASK)) {
                dev_dbg(hcd->self.controller,
                        "idlest2 = 0x%x\n",
                        cm_read_mod_reg(PLL_MOD, CM_IDLEST2));
+
+               if (time_after(timeout, jiffies)) {
+                       dev_dbg(hcd->self.controller, "operation timed out\n");
+                       return -EINVAL;
+               }
+       }
        /* End DPLL5 programming */
 
 
@@ -347,17 +361,30 @@ static int omap_start_ehc(struct platform_device *dev, 
struct usb_hcd *hcd)
 
        /* Wait for TLL to be Active */
        while ((cm_read_mod_reg(CORE_MOD, OMAP2430_CM_IDLEST3)
-                       & (1 << OMAP3430ES2_ST_USBTLL_SHIFT)))
+                       & (1 << OMAP3430ES2_ST_USBTLL_SHIFT))) {
                cpu_relax();
 
+               if (time_after(timeout, jiffies)) {
+                       dev_dbg(hcd->self.controller, "operation timed out\n");
+                       return -EINVAL;
+               }
+       }
+
        /* perform TLL soft reset, and wait until reset is complete */
        omap_writel(1 << OMAP_USBTLL_SYSCONFIG_SOFTRESET_SHIFT,
                        OMAP_USBTLL_SYSCONFIG);
+
        /* Wait for TLL reset to complete */
        while (!(omap_readl(OMAP_USBTLL_SYSSTATUS)
-                       & (1 << OMAP_USBTLL_SYSSTATUS_RESETDONE_SHIFT)))
+                       & (1 << OMAP_USBTLL_SYSSTATUS_RESETDONE_SHIFT))) {
                cpu_relax();
 
+               if (time_after(timeout, jiffies)) {
+                       dev_dbg(hcd->self.controller, "operation timed out\n");
+                       return -EINVAL;
+               }
+       }
+
        dev_dbg(hcd->self.controller, "TLL RESET DONE\n");
 
        /* (1<<3) = no idle mode only for initial debugging */
@@ -383,11 +410,18 @@ static int omap_start_ehc(struct platform_device *dev, 
struct usb_hcd *hcd)
                        (1 << OMAP_UHH_HOSTCONFIG_INCR16_BURST_EN_SHIFT)|
                        (0 << OMAP_UHH_HOSTCONFIG_INCRX_ALIGN_EN_SHIFT),
                                                OMAP_UHH_HOSTCONFIG);
+
        /* Ensure that BYPASS is set */
        while (omap_readl(OMAP_UHH_HOSTCONFIG)
-                       & (1 << OMAP_UHH_HOSTCONFIG_ULPI_BYPASS_SHIFT))
+                       & (1 << OMAP_UHH_HOSTCONFIG_ULPI_BYPASS_SHIFT)) {
                cpu_relax();
 
+               if (time_after(timeout, jiffies)) {
+                       dev_dbg(hcd->self.controller, "operation timed out\n");
+                       return -EINVAL;
+               }
+       }
+
        dev_dbg(hcd->self.controller, "Entered ULPI PHY MODE: success\n");
 
 #else
@@ -422,9 +456,15 @@ static int omap_start_ehc(struct platform_device *dev, 
struct usb_hcd *hcd)
                        EHCI_INSNREG05_ULPI);
 
        while (!(omap_readl(EHCI_INSNREG05_ULPI)
-                       & (1 << EHCI_INSNREG05_ULPI_CONTROL_SHIFT)))
+                       & (1 << EHCI_INSNREG05_ULPI_CONTROL_SHIFT))) {
                cpu_relax();
 
+               if (time_after(timeout, jiffies)) {
+                       dev_dbg(hcd->self.controller, "operation timed out\n");
+                       return -EINVAL;
+               }
+       }
+
 #endif
 
        return 0;
@@ -433,6 +473,7 @@ static int omap_start_ehc(struct platform_device *dev, 
struct usb_hcd *hcd)
 static void omap_stop_ehc(struct platform_device *dev, struct usb_hcd *hcd)
 {
        struct ehci_omap_clock_defs *ehci_clocks;
+       unsigned long timeout = jiffies + msecs_to_jiffies(100);
 
        ehci_clocks = (struct ehci_omap_clock_defs *)
                        (((char *)hcd_to_ehci(hcd)) + sizeof(struct ehci_hcd));
@@ -441,19 +482,45 @@ static void omap_stop_ehc(struct platform_device *dev, 
struct usb_hcd *hcd)
 
        /* Reset OMAP modules for insmod/rmmod to work */
        omap_writel((1 << 1), OMAP_UHH_SYSCONFIG);
-       while (!(omap_readl(OMAP_UHH_SYSSTATUS) & (1 << 0)))
+       while (!(omap_readl(OMAP_UHH_SYSSTATUS) & (1 << 0))) {
                cpu_relax();
-       while (!(omap_readl(OMAP_UHH_SYSSTATUS) & (1 << 1)))
+
+               if (time_after(timeout, jiffies)) {
+                       dev_dbg(hcd->self.controller, "operation timed out\n");
+                       return;
+               }
+       }
+
+       while (!(omap_readl(OMAP_UHH_SYSSTATUS) & (1 << 1))) {
                cpu_relax();
-       while (!(omap_readl(OMAP_UHH_SYSSTATUS) & (1 << 2)))
+
+               if (time_after(timeout, jiffies)) {
+                       dev_dbg(hcd->self.controller, "operation timed out\n");
+                       return;
+               }
+       }
+
+       while (!(omap_readl(OMAP_UHH_SYSSTATUS) & (1 << 2))) {
                cpu_relax();
+
+               if (time_after(timeout, jiffies)) {
+                       dev_dbg(hcd->self.controller, "operation timed out\n");
+                       return;
+               }
+       }
        dev_dbg(hcd->self.controller,
                "UHH RESET DONE OMAP_UHH_SYSSTATUS %x !!\n",
                        omap_readl(OMAP_UHH_SYSSTATUS));
 
        omap_writel((1 << 1), OMAP_USBTLL_SYSCONFIG);
-       while (!(omap_readl(OMAP_USBTLL_SYSSTATUS) & (1 << 0)))
+       while (!(omap_readl(OMAP_USBTLL_SYSSTATUS) & (1 << 0))) {
                cpu_relax();
+
+               if (time_after(timeout, jiffies)) {
+                       dev_dbg(hcd->self.controller, "operation timed out\n");
+                       return;
+               }
+       }
        dev_dbg(hcd->self.controller, "TLL RESET DONE\n");
 
        if (ehci_clocks->usbtll_fck_clk != NULL) {
-- 
1.6.1.3

--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to