summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorLi Jun <b47624@freescale.com>2014-04-14 19:39:09 +0800
committerNitin Garg <nitin.garg@freescale.com>2014-04-16 11:02:32 -0500
commitfc47c6565c363633165e9099f5a985c74e0dc3b0 (patch)
tree680661fb02bb94b9c3bbf94da7ae206c3e6107b3 /drivers
parentcf09d8ce34d752891ef9203097d1e8cf48a5fe85 (diff)
ENGR00308442-2 usb: chipidea: otg: wait devices disconnected before stop host
This patch adds device connection check before stop host for id change to be 0, wait until there is no any devices connected, then do host stop to avoid deadlock. Signed-off-by: Li Jun <b47624@freescale.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/usb/chipidea/otg.c11
1 files changed, 11 insertions, 0 deletions
diff --git a/drivers/usb/chipidea/otg.c b/drivers/usb/chipidea/otg.c
index 0e2b2d8bcb58..31cc81bb7806 100644
--- a/drivers/usb/chipidea/otg.c
+++ b/drivers/usb/chipidea/otg.c
@@ -17,6 +17,7 @@
#include <linux/usb/otg.h>
#include <linux/usb/gadget.h>
+#include <linux/usb/hcd.h>
#include <linux/usb/chipidea.h>
#include "ci.h"
@@ -88,11 +89,21 @@ void ci_handle_vbus_change(struct ci_hdrc *ci)
static void ci_handle_id_switch(struct ci_hdrc *ci)
{
enum ci_role role = ci_otg_role(ci);
+ struct usb_device *roothub;
+ int i;
if (role != ci->role) {
dev_dbg(ci->dev, "switching from %s to %s\n",
ci_role(ci)->name, ci->roles[role]->name);
+ if ((ci->role == CI_ROLE_HOST) && ci->hcd) {
+ roothub = ci->hcd->self.root_hub;
+ for (i = 0; i < roothub->maxchild; ++i) {
+ while (usb_hub_find_child(roothub, (i + 1)))
+ usleep_range(500, 1000);
+ }
+ }
+
ci_role_stop(ci);
/* wait vbus lower than OTGSC_BSV */
hw_wait_reg(ci, OP_OTGSC, OTGSC_BSV, 0,