3.7 kernel hangs when doing scp

Fabio Estevam festevam at gmail.com
Fri Dec 21 04:24:14 EST 2012


Hi Peter,

On Fri, Dec 21, 2012 at 12:22 AM, Peter Chen <peter.chen at freescale.com> wrote:

> Current chipidea driver only considers disable stream mode at device
> mode, in fact, it may be related to below chipidea bug, and needs
> to consider all usb modes.
>
> STAR 9000378958
> Title: Non-Double Word Aligned Buffer Address Sometimes Causes Host to Hang on OUT Retry
> www.synopsys.com/dw/star.php?c=dwc_usb2_hs_otg_controller&fixedIn=2.20a
>
> To fix this, we need to add CI13XXX_DISABLE_STREAMING after role->start/init.

Yes, setting CI13XXX_DISABLE_STREAMING inside ci_role_start does work.

If you think the patch below is fine I can properly submit it.

---
 drivers/usb/chipidea/ci.h |   39 +++++++++++++++++++++++----------------
 1 file changed, 23 insertions(+), 16 deletions(-)

diff --git a/drivers/usb/chipidea/ci.h b/drivers/usb/chipidea/ci.h
index e25d126..7fe652a 100644
--- a/drivers/usb/chipidea/ci.h
+++ b/drivers/usb/chipidea/ci.h
@@ -18,6 +18,8 @@
 #include <linux/usb.h>
 #include <linux/usb/gadget.h>

+#define USBMODE_CI_SDIS       BIT(4)
+
 /******************************************************************************
  * DEFINE
  *****************************************************************************/
@@ -173,22 +175,6 @@ static inline struct ci_role_driver
*ci_role(struct ci13xxx *ci)
 	return ci->roles[ci->role];
 }

-static inline int ci_role_start(struct ci13xxx *ci, enum ci_role role)
-{
-	int ret;
-
-	if (role >= CI_ROLE_END)
-		return -EINVAL;
-
-	if (!ci->roles[role])
-		return -ENXIO;
-
-	ret = ci->roles[role]->start(ci);
-	if (!ret)
-		ci->role = role;
-	return ret;
-}
-
 static inline void ci_role_stop(struct ci13xxx *ci)
 {
 	enum ci_role role = ci->role;
@@ -307,6 +293,27 @@ static inline u32 hw_test_and_write(struct
ci13xxx *ci, enum ci13xxx_regs reg,
 	return (val & mask) >> ffs_nr(mask);
 }

+
+static inline int ci_role_start(struct ci13xxx *ci, enum ci_role role)
+{
+	int ret;
+
+	if (role >= CI_ROLE_END)
+		return -EINVAL;
+
+	if (!ci->roles[role])
+		return -ENXIO;
+
+	ret = ci->roles[role]->start(ci);
+	if (!ret)
+		ci->role = role;
+
+	if (ci->platdata->flags & CI13XXX_DISABLE_STREAMING)
+		hw_write(ci, OP_USBMODE, USBMODE_CI_SDIS, USBMODE_CI_SDIS);
+
+	return ret;
+}
+
 int hw_device_reset(struct ci13xxx *ci, u32 mode);

 int hw_port_test_set(struct ci13xxx *ci, u8 mode);
--



More information about the linux-arm-kernel mailing list