lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Message-Id: <1384964989-28760-1-git-send-email-julien.delacou@st.com>
Date:	Wed, 20 Nov 2013 17:29:49 +0100
From:	Julien DELACOU <julien.delacou@...com>
To:	Paul Zimmerman <paulz@...opsys.com>,
	Matthijs Kooijman <matthijs@...in.nl>,
	Greg Kroah-Hartman <gregkh@...uxfoundation.org>,
	Grant Likely <grant.likely@...aro.org>
Cc:	linux-kernel@...r.kernel.org, linux-usb@...r.kernel.org,
	devel@...verdev.osuosl.org, Julien Delacou <julien.delacou@...com>
Subject: [PATCH] staging: dwc2: add check on dwc2_core_reset return

If the GRSTCTL_CSFTRST self-clearing bit never comes
back to 0 for any reason, the controller is under reset
state and cannot be used. It's preferable to abort
initialization in such case.

Signed-off-by: Julien Delacou <julien.delacou@...com>
---
 drivers/staging/dwc2/core.c |   58 +++++++++++++++++++++++++++++++++----------
 1 file changed, 45 insertions(+), 13 deletions(-)

diff --git a/drivers/staging/dwc2/core.c b/drivers/staging/dwc2/core.c
index 27e1964..ecce1ef 100644
--- a/drivers/staging/dwc2/core.c
+++ b/drivers/staging/dwc2/core.c
@@ -116,7 +116,7 @@ static void dwc2_init_fs_ls_pclk_sel(struct dwc2_hsotg *hsotg)
  * Do core a soft reset of the core.  Be careful with this because it
  * resets all the internal state machines of the core.
  */
-static void dwc2_core_reset(struct dwc2_hsotg *hsotg)
+static int dwc2_core_reset(struct dwc2_hsotg *hsotg)
 {
 	u32 greset;
 	int count = 0;
@@ -131,7 +131,7 @@ static void dwc2_core_reset(struct dwc2_hsotg *hsotg)
 			dev_warn(hsotg->dev,
 				 "%s() HANG! AHB Idle GRSTCTL=%0x\n",
 				 __func__, greset);
-			return;
+			return -EBUSY;
 		}
 	} while (!(greset & GRSTCTL_AHBIDLE));
 
@@ -146,7 +146,7 @@ static void dwc2_core_reset(struct dwc2_hsotg *hsotg)
 			dev_warn(hsotg->dev,
 				 "%s() HANG! Soft Reset GRSTCTL=%0x\n",
 				 __func__, greset);
-			break;
+			return -EBUSY;
 		}
 	} while (greset & GRSTCTL_CSFTRST);
 
@@ -155,11 +155,14 @@ static void dwc2_core_reset(struct dwc2_hsotg *hsotg)
 	 * not stay in host mode after a connector ID change!
 	 */
 	usleep_range(150000, 200000);
+
+	return 0;
 }
 
-static void dwc2_fs_phy_init(struct dwc2_hsotg *hsotg, bool select_phy)
+static int dwc2_fs_phy_init(struct dwc2_hsotg *hsotg, bool select_phy)
 {
 	u32 usbcfg, i2cctl;
+	int retval = 0;
 
 	/*
 	 * core_init() is now called on every switch so only call the
@@ -172,7 +175,12 @@ static void dwc2_fs_phy_init(struct dwc2_hsotg *hsotg, bool select_phy)
 		writel(usbcfg, hsotg->regs + GUSBCFG);
 
 		/* Reset after a PHY select */
-		dwc2_core_reset(hsotg);
+		retval = dwc2_core_reset(hsotg);
+		if (retval) {
+			dev_err(hsotg->dev, "%s() Reset failed, aborting",
+					__func__);
+			return retval;
+		}
 	}
 
 	/*
@@ -200,14 +208,17 @@ static void dwc2_fs_phy_init(struct dwc2_hsotg *hsotg, bool select_phy)
 		i2cctl |= GI2CCTL_I2CEN;
 		writel(i2cctl, hsotg->regs + GI2CCTL);
 	}
+
+	return retval;
 }
 
-static void dwc2_hs_phy_init(struct dwc2_hsotg *hsotg, bool select_phy)
+static int dwc2_hs_phy_init(struct dwc2_hsotg *hsotg, bool select_phy)
 {
 	u32 usbcfg;
+	int retval = 0;
 
 	if (!select_phy)
-		return;
+		return -ENODEV;
 
 	usbcfg = readl(hsotg->regs + GUSBCFG);
 
@@ -240,20 +251,32 @@ static void dwc2_hs_phy_init(struct dwc2_hsotg *hsotg, bool select_phy)
 	writel(usbcfg, hsotg->regs + GUSBCFG);
 
 	/* Reset after setting the PHY parameters */
-	dwc2_core_reset(hsotg);
+	retval = dwc2_core_reset(hsotg);
+	if (retval) {
+		dev_err(hsotg->dev, "%s() Reset failed, aborting",
+				__func__);
+		return retval;
+	}
+
+	return retval;
 }
 
-static void dwc2_phy_init(struct dwc2_hsotg *hsotg, bool select_phy)
+static int dwc2_phy_init(struct dwc2_hsotg *hsotg, bool select_phy)
 {
 	u32 usbcfg;
+	int retval = 0;
 
 	if (hsotg->core_params->speed == DWC2_SPEED_PARAM_FULL &&
 	    hsotg->core_params->phy_type == DWC2_PHY_TYPE_PARAM_FS) {
 		/* If FS mode with FS PHY */
-		dwc2_fs_phy_init(hsotg, select_phy);
+		retval = dwc2_fs_phy_init(hsotg, select_phy);
+		if (retval)
+			return retval;
 	} else {
 		/* High speed PHY */
-		dwc2_hs_phy_init(hsotg, select_phy);
+		retval = dwc2_hs_phy_init(hsotg, select_phy);
+		if (retval)
+			return retval;
 	}
 
 	if (hsotg->hw_params.hs_phy_type == GHWCFG2_HS_PHY_TYPE_ULPI &&
@@ -270,6 +293,8 @@ static void dwc2_phy_init(struct dwc2_hsotg *hsotg, bool select_phy)
 		usbcfg &= ~GUSBCFG_ULPI_CLK_SUSP_M;
 		writel(usbcfg, hsotg->regs + GUSBCFG);
 	}
+
+	return retval;
 }
 
 static int dwc2_gahbcfg_init(struct dwc2_hsotg *hsotg)
@@ -421,12 +446,19 @@ int dwc2_core_init(struct dwc2_hsotg *hsotg, bool select_phy, int irq)
 	writel(usbcfg, hsotg->regs + GUSBCFG);
 
 	/* Reset the Controller */
-	dwc2_core_reset(hsotg);
+	retval = dwc2_core_reset(hsotg);
+	if (retval) {
+		dev_err(hsotg->dev, "%s(): Reset failed, aborting\n",
+				__func__);
+		return retval;
+	}
 
 	/*
 	 * This needs to happen in FS mode before any other programming occurs
 	 */
-	dwc2_phy_init(hsotg, select_phy);
+	retval = dwc2_phy_init(hsotg, select_phy);
+	if (retval)
+		return retval;
 
 	/* Program the GAHBCFG Register */
 	retval = dwc2_gahbcfg_init(hsotg);
-- 
1.7.9.5

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ