usb: dwc3: gadget: fix time out waiting for setup phase when stop gadget

If dwc3 failed to init ep0 in __dwc3_gadget_start(), the ep0state will
be uninitialized, aka, ep0state is EP0_UNCONNECTED, in this case, we
don't need to wait for control transfer completion when stop gadget
because no usb control transfer in process. This patch can help to avoid
the following warning in RK356x Boards during shutdown process.

[   30.735323] usb ffs open    D    0   309      1 0x0400002d
[   30.735330] Call trace:
[   30.735336]  __switch_to+0xe4/0x138
[   30.735348]  __schedule+0x2f4/0x930
[   30.735358]  schedule+0x38/0xa0
[   30.735368]  schedule_timeout+0x194/0x478
[   30.735378]  wait_for_common+0x130/0x1e8
[   30.735388]  wait_for_completion_timeout+0x10/0x18
[   30.735399]  dwc3_gadget_pullup+0x68/0xc8
[   30.735411]  usb_gadget_disconnect+0xf0/0x110
[   30.735422]  usb_gadget_remove_driver+0x24/0x70
[   30.735431]  usb_gadget_unregister_driver+0xd0/0x120
[   30.735441]  unregister_gadget+0x20/0x50
[   30.735450]  unregister_gadget_item+0x24/0x38
[   30.735461]  ffs_data_clear+0x120/0x130
[   30.735471]  ffs_data_reset+0x14/0x58
[   30.735480]  ffs_data_closed+0x88/0xd8
[   30.735490]  ffs_ep0_release+0x10/0x20
[   30.735501]  __fput+0x88/0x1b8
[   30.735510]  ____fput+0xc/0x18
[   30.735521]  task_work_run+0x94/0xb0
[   30.735531]  do_exit+0x334/0xa28
[   30.735540]  do_group_exit+0x34/0x98
[   30.735550]  get_signal+0xe4/0x828
[   30.735557]  do_signal+0x1c0/0x298
[   30.735563]  do_notify_resume+0xd0/0x118
[   30.735568]  work_pending+0x8/0x10
[   30.735602] sysrq: Kill All Tasks

Change-Id: I3534b710804e099d857149b0b0b58a7a7236b8fc
Signed-off-by: William Wu <william.wu@rock-chips.com>
This commit is contained in:
William Wu
2020-12-09 15:52:08 +08:00
committed by Tao Huang
parent 277709af3f
commit ec222455e4

View File

@@ -2471,7 +2471,8 @@ static int dwc3_gadget_pullup(struct usb_gadget *g, int is_on)
* Per databook, when we want to stop the gadget, if a control transfer
* is still in process, complete it and get the core into setup phase.
*/
if (!is_on && dwc->ep0state != EP0_SETUP_PHASE) {
if (!is_on && dwc->ep0state != EP0_SETUP_PHASE &&
dwc->ep0state != EP0_UNCONNECTED) {
reinit_completion(&dwc->ep0_in_setup);
ret = wait_for_completion_timeout(&dwc->ep0_in_setup,