musb: make initial HNP roleswitch work (v2)
Minor HNP bugfixes, so the initial role switch works:
- A-Device:
* disconnect-during-suspend enters A_PERIPHERAL state
* kill OTG timer after reset as A_PERIPHERAL ...
* ... and also pass that reset to the gadget
* once HNP succeeds, clear the "ignore_disconnect" flag
* from A_PERIPHERAL, disconnect transitions to A_WAIT_BCON
- B-Device:
* kill OTG timer on entry to B_HOST state (HNP succeeded)
* once HNP succeeds, clear "ignore_disconnect" flag
* kick the root hub only _after_ the state is adjusted
Other state transitions are left alone. Notably, exit paths from
the "roles have switched" state ... A_PERIPHERAL handling of that
stays seriously broken.
Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
diff --git a/drivers/usb/musb/musb_virthub.c b/drivers/usb/musb/musb_virthub.c
index d7e1bc4..c85a82a 100644
--- a/drivers/usb/musb/musb_virthub.c
+++ b/drivers/usb/musb/musb_virthub.c
@@ -187,8 +187,17 @@
musb->is_active = 0;
switch (musb->xceiv->state) {
- case OTG_STATE_A_HOST:
case OTG_STATE_A_SUSPEND:
+#ifdef CONFIG_USB_MUSB_OTG
+ if (is_otg_enabled(musb)
+ && musb->xceiv->host->b_hnp_enable) {
+ musb->xceiv->state = OTG_STATE_A_PERIPHERAL;
+ musb->g.is_a_peripheral = 1;
+ break;
+ }
+#endif
+ /* FALLTHROUGH */
+ case OTG_STATE_A_HOST:
musb->xceiv->state = OTG_STATE_A_WAIT_BCON;
musb->is_active = 0;
break;