diff options
author | Li Jun <b47624@freescale.com> | 2014-04-14 19:39:09 +0800 |
---|---|---|
committer | Nitin Garg <nitin.garg@freescale.com> | 2014-04-16 11:02:32 -0500 |
commit | fc47c6565c363633165e9099f5a985c74e0dc3b0 (patch) | |
tree | 680661fb02bb94b9c3bbf94da7ae206c3e6107b3 /drivers | |
parent | cf09d8ce34d752891ef9203097d1e8cf48a5fe85 (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.c | 11 |
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, |