diff mbox series

usb: dwc2: Disable all EP's on disconnect

Message ID d56e95e0e6e7d9ad5d1f3d8d659ab3f572dc9df3.1537280238.git.hminas@synopsys.com (mailing list archive)
State New, archived
Headers show
Series usb: dwc2: Disable all EP's on disconnect | expand

Commit Message

Minas Harutyunyan Sept. 18, 2018, 2:18 p.m. UTC
Disabling all EP's allow to reset EP's to initial state.
On disconnect disable all EP's instead of just killing
all requests. Because of some platform didn't catch
disconnect event, same stuff added to
dwc2_hsotg_core_init_disconnected() function when USB
reset detected on the bus.
In dwc2_hsotg_ep_disable() function before locking
hsotg->lock, check if it locked by calling functions
then unlock. Lock again on exit if it was locked.
Same lock checking flow added to dwc2_hsotg_udc_stop()
function.

Signed-off-by: Minas Harutyunyan <hminas@synopsys.com>
---
 drivers/usb/dwc2/gadget.c | 32 +++++++++++++++++++++++++++-----
 1 file changed, 27 insertions(+), 5 deletions(-)

Comments

kernel test robot Sept. 19, 2018, 5:05 a.m. UTC | #1
Hi Minas,

I love your patch! Perhaps something to improve:

[auto build test WARNING on balbi-usb/next]
[also build test WARNING on v4.19-rc4 next-20180918]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url:    https://github.com/0day-ci/linux/commits/Minas-Harutyunyan/usb-dwc2-Disable-all-EP-s-on-disconnect/20180919-104259
base:   https://git.kernel.org/pub/scm/linux/kernel/git/balbi/usb.git next
config: x86_64-allmodconfig (attached as .config)
compiler: gcc-7 (Debian 7.3.0-1) 7.3.0
reproduce:
        # save the attached .config to linux build tree
        make ARCH=x86_64 

All warnings (new ones prefixed by >>):

>> drivers/usb/dwc2/gadget.c:4053:9: warning: context imbalance in 'dwc2_hsotg_ep_disable' - different lock contexts for basic block
>> drivers/usb/dwc2/gadget.c:4361:28: warning: context imbalance in 'dwc2_hsotg_udc_stop' - different lock contexts for basic block

vim +/dwc2_hsotg_ep_disable +4053 drivers/usb/dwc2/gadget.c

5b7d70c6d drivers/usb/gadget/s3c-hsotg.c Ben Dooks          2009-06-02  3993  
8b9bc4608 drivers/usb/gadget/s3c-hsotg.c Lukasz Majewski    2012-05-04  3994  /**
1f91b4cc0 drivers/usb/dwc2/gadget.c      Felipe Balbi       2015-08-06  3995   * dwc2_hsotg_ep_disable - disable given endpoint
8b9bc4608 drivers/usb/gadget/s3c-hsotg.c Lukasz Majewski    2012-05-04  3996   * @ep: The endpoint to disable.
8b9bc4608 drivers/usb/gadget/s3c-hsotg.c Lukasz Majewski    2012-05-04  3997   */
1f91b4cc0 drivers/usb/dwc2/gadget.c      Felipe Balbi       2015-08-06  3998  static int dwc2_hsotg_ep_disable(struct usb_ep *ep)
5b7d70c6d drivers/usb/gadget/s3c-hsotg.c Ben Dooks          2009-06-02  3999  {
1f91b4cc0 drivers/usb/dwc2/gadget.c      Felipe Balbi       2015-08-06  4000  	struct dwc2_hsotg_ep *hs_ep = our_ep(ep);
941fcce4f drivers/usb/dwc2/gadget.c      Dinh Nguyen        2014-11-11  4001  	struct dwc2_hsotg *hsotg = hs_ep->parent;
5b7d70c6d drivers/usb/gadget/s3c-hsotg.c Ben Dooks          2009-06-02  4002  	int dir_in = hs_ep->dir_in;
5b7d70c6d drivers/usb/gadget/s3c-hsotg.c Ben Dooks          2009-06-02  4003  	int index = hs_ep->index;
5b7d70c6d drivers/usb/gadget/s3c-hsotg.c Ben Dooks          2009-06-02  4004  	unsigned long flags;
5b7d70c6d drivers/usb/gadget/s3c-hsotg.c Ben Dooks          2009-06-02  4005  	u32 epctrl_reg;
5b7d70c6d drivers/usb/gadget/s3c-hsotg.c Ben Dooks          2009-06-02  4006  	u32 ctrl;
a4705c3fe drivers/usb/dwc2/gadget.c      Minas Harutyunyan  2018-09-18  4007  	int locked;
5b7d70c6d drivers/usb/gadget/s3c-hsotg.c Ben Dooks          2009-06-02  4008  
1e0112937 drivers/usb/dwc2/gadget.c      Marek Szyprowski   2014-09-09  4009  	dev_dbg(hsotg->dev, "%s(ep %p)\n", __func__, ep);
5b7d70c6d drivers/usb/gadget/s3c-hsotg.c Ben Dooks          2009-06-02  4010  
c6f5c050e drivers/usb/dwc2/gadget.c      Mian Yousaf Kaukab 2015-01-09  4011  	if (ep == &hsotg->eps_out[0]->ep) {
5b7d70c6d drivers/usb/gadget/s3c-hsotg.c Ben Dooks          2009-06-02  4012  		dev_err(hsotg->dev, "%s: called for ep0\n", __func__);
5b7d70c6d drivers/usb/gadget/s3c-hsotg.c Ben Dooks          2009-06-02  4013  		return -EINVAL;
9b481092c drivers/usb/dwc2/gadget.c      John Stultz        2017-10-23  4014  	}
9b481092c drivers/usb/dwc2/gadget.c      John Stultz        2017-10-23  4015  
9b481092c drivers/usb/dwc2/gadget.c      John Stultz        2017-10-23  4016  	if (hsotg->op_state != OTG_STATE_B_PERIPHERAL) {
9b481092c drivers/usb/dwc2/gadget.c      John Stultz        2017-10-23  4017  		dev_err(hsotg->dev, "%s: called in host mode?\n", __func__);
9b481092c drivers/usb/dwc2/gadget.c      John Stultz        2017-10-23  4018  		return -EINVAL;
5b7d70c6d drivers/usb/gadget/s3c-hsotg.c Ben Dooks          2009-06-02  4019  	}
5b7d70c6d drivers/usb/gadget/s3c-hsotg.c Ben Dooks          2009-06-02  4020  
94cb8fd63 drivers/usb/gadget/s3c-hsotg.c Lukasz Majewski    2012-05-04  4021  	epctrl_reg = dir_in ? DIEPCTL(index) : DOEPCTL(index);
5b7d70c6d drivers/usb/gadget/s3c-hsotg.c Ben Dooks          2009-06-02  4022  
a4705c3fe drivers/usb/dwc2/gadget.c      Minas Harutyunyan  2018-09-18  4023  	locked = spin_trylock(&hsotg->lock);
a4705c3fe drivers/usb/dwc2/gadget.c      Minas Harutyunyan  2018-09-18  4024  	spin_unlock(&hsotg->lock);
5ad1d3160 drivers/usb/gadget/s3c-hsotg.c Lukasz Majewski    2012-06-14  4025  	spin_lock_irqsave(&hsotg->lock, flags);
5b7d70c6d drivers/usb/gadget/s3c-hsotg.c Ben Dooks          2009-06-02  4026  
f25c42b8d drivers/usb/dwc2/gadget.c      Gevorg Sahakyan    2018-07-26  4027  	ctrl = dwc2_readl(hsotg, epctrl_reg);
a4f827714 drivers/usb/dwc2/gadget.c      Vahram Aharonyan   2016-11-14  4028  
a4f827714 drivers/usb/dwc2/gadget.c      Vahram Aharonyan   2016-11-14  4029  	if (ctrl & DXEPCTL_EPENA)
a4f827714 drivers/usb/dwc2/gadget.c      Vahram Aharonyan   2016-11-14  4030  		dwc2_hsotg_ep_stop_xfr(hsotg, hs_ep);
a4f827714 drivers/usb/dwc2/gadget.c      Vahram Aharonyan   2016-11-14  4031  
47a1685f1 drivers/usb/dwc2/gadget.c      Dinh Nguyen        2014-04-14  4032  	ctrl &= ~DXEPCTL_EPENA;
47a1685f1 drivers/usb/dwc2/gadget.c      Dinh Nguyen        2014-04-14  4033  	ctrl &= ~DXEPCTL_USBACTEP;
47a1685f1 drivers/usb/dwc2/gadget.c      Dinh Nguyen        2014-04-14  4034  	ctrl |= DXEPCTL_SNAK;
5b7d70c6d drivers/usb/gadget/s3c-hsotg.c Ben Dooks          2009-06-02  4035  
5b7d70c6d drivers/usb/gadget/s3c-hsotg.c Ben Dooks          2009-06-02  4036  	dev_dbg(hsotg->dev, "%s: DxEPCTL=0x%08x\n", __func__, ctrl);
f25c42b8d drivers/usb/dwc2/gadget.c      Gevorg Sahakyan    2018-07-26  4037  	dwc2_writel(hsotg, ctrl, epctrl_reg);
5b7d70c6d drivers/usb/gadget/s3c-hsotg.c Ben Dooks          2009-06-02  4038  
5b7d70c6d drivers/usb/gadget/s3c-hsotg.c Ben Dooks          2009-06-02  4039  	/* disable endpoint interrupts */
1f91b4cc0 drivers/usb/dwc2/gadget.c      Felipe Balbi       2015-08-06  4040  	dwc2_hsotg_ctrl_epint(hsotg, hs_ep->index, hs_ep->dir_in, 0);
5b7d70c6d drivers/usb/gadget/s3c-hsotg.c Ben Dooks          2009-06-02  4041  
1141ea01d drivers/usb/dwc2/gadget.c      Mian Yousaf Kaukab 2015-01-09  4042  	/* terminate all requests with shutdown */
1141ea01d drivers/usb/dwc2/gadget.c      Mian Yousaf Kaukab 2015-01-09  4043  	kill_all_requests(hsotg, hs_ep, -ESHUTDOWN);
1141ea01d drivers/usb/dwc2/gadget.c      Mian Yousaf Kaukab 2015-01-09  4044  
1c07b20ea drivers/usb/dwc2/gadget.c      Robert Baldyga     2016-08-29  4045  	hsotg->fifo_map &= ~(1 << hs_ep->fifo_index);
1c07b20ea drivers/usb/dwc2/gadget.c      Robert Baldyga     2016-08-29  4046  	hs_ep->fifo_index = 0;
1c07b20ea drivers/usb/dwc2/gadget.c      Robert Baldyga     2016-08-29  4047  	hs_ep->fifo_size = 0;
1c07b20ea drivers/usb/dwc2/gadget.c      Robert Baldyga     2016-08-29  4048  
22258f490 drivers/usb/gadget/s3c-hsotg.c Lukasz Majewski    2012-06-14  4049  	spin_unlock_irqrestore(&hsotg->lock, flags);
a4705c3fe drivers/usb/dwc2/gadget.c      Minas Harutyunyan  2018-09-18  4050  	if (!locked)
a4705c3fe drivers/usb/dwc2/gadget.c      Minas Harutyunyan  2018-09-18  4051  		spin_lock(&hsotg->lock);
a4705c3fe drivers/usb/dwc2/gadget.c      Minas Harutyunyan  2018-09-18  4052  
5b7d70c6d drivers/usb/gadget/s3c-hsotg.c Ben Dooks          2009-06-02 @4053  	return 0;
5b7d70c6d drivers/usb/gadget/s3c-hsotg.c Ben Dooks          2009-06-02  4054  }
5b7d70c6d drivers/usb/gadget/s3c-hsotg.c Ben Dooks          2009-06-02  4055  

:::::: The code at line 4053 was first introduced by commit
:::::: 5b7d70c6dbf2db786395cbd21750a1a4ce222f84 USB: Gadget driver for Samsung HS/OtG block

:::::: TO: Ben Dooks <ben@simtec.co.uk>
:::::: CC: Greg Kroah-Hartman <gregkh@suse.de>

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation
Dan Carpenter Sept. 20, 2018, 9:48 a.m. UTC | #2
Hi Minas,

url:    https://github.com/0day-ci/linux/commits/Minas-Harutyunyan/usb-dwc2-Disable-all-EP-s-on-disconnect/20180919-104259
base:   https://git.kernel.org/pub/scm/linux/kernel/git/balbi/usb.git next

smatch warnings:
drivers/usb/dwc2/gadget.c:4024 dwc2_hsotg_ep_disable() error: double unlock 'spin_lock:&hsotg->lock'
drivers/usb/dwc2/gadget.c:4350 dwc2_hsotg_udc_stop() error: double unlock 'spin_lock:&hsotg->lock'

# https://github.com/0day-ci/linux/commit/a4705c3fee2053e95791210eb435a04b665f6dc3
git remote add linux-review https://github.com/0day-ci/linux
git remote update linux-review
git checkout a4705c3fee2053e95791210eb435a04b665f6dc3
vim +4024 drivers/usb/dwc2/gadget.c

5b7d70c6d drivers/usb/gadget/s3c-hsotg.c Ben Dooks          2009-06-02  3993  
8b9bc4608 drivers/usb/gadget/s3c-hsotg.c Lukasz Majewski    2012-05-04  3994  /**
1f91b4cc0 drivers/usb/dwc2/gadget.c      Felipe Balbi       2015-08-06  3995   * dwc2_hsotg_ep_disable - disable given endpoint
8b9bc4608 drivers/usb/gadget/s3c-hsotg.c Lukasz Majewski    2012-05-04  3996   * @ep: The endpoint to disable.
8b9bc4608 drivers/usb/gadget/s3c-hsotg.c Lukasz Majewski    2012-05-04  3997   */
1f91b4cc0 drivers/usb/dwc2/gadget.c      Felipe Balbi       2015-08-06  3998  static int dwc2_hsotg_ep_disable(struct usb_ep *ep)
5b7d70c6d drivers/usb/gadget/s3c-hsotg.c Ben Dooks          2009-06-02  3999  {
1f91b4cc0 drivers/usb/dwc2/gadget.c      Felipe Balbi       2015-08-06  4000  	struct dwc2_hsotg_ep *hs_ep = our_ep(ep);
941fcce4f drivers/usb/dwc2/gadget.c      Dinh Nguyen        2014-11-11  4001  	struct dwc2_hsotg *hsotg = hs_ep->parent;
5b7d70c6d drivers/usb/gadget/s3c-hsotg.c Ben Dooks          2009-06-02  4002  	int dir_in = hs_ep->dir_in;
5b7d70c6d drivers/usb/gadget/s3c-hsotg.c Ben Dooks          2009-06-02  4003  	int index = hs_ep->index;
5b7d70c6d drivers/usb/gadget/s3c-hsotg.c Ben Dooks          2009-06-02  4004  	unsigned long flags;
5b7d70c6d drivers/usb/gadget/s3c-hsotg.c Ben Dooks          2009-06-02  4005  	u32 epctrl_reg;
5b7d70c6d drivers/usb/gadget/s3c-hsotg.c Ben Dooks          2009-06-02  4006  	u32 ctrl;
a4705c3fe drivers/usb/dwc2/gadget.c      Minas Harutyunyan  2018-09-18  4007  	int locked;
5b7d70c6d drivers/usb/gadget/s3c-hsotg.c Ben Dooks          2009-06-02  4008  
1e0112937 drivers/usb/dwc2/gadget.c      Marek Szyprowski   2014-09-09  4009  	dev_dbg(hsotg->dev, "%s(ep %p)\n", __func__, ep);
5b7d70c6d drivers/usb/gadget/s3c-hsotg.c Ben Dooks          2009-06-02  4010  
c6f5c050e drivers/usb/dwc2/gadget.c      Mian Yousaf Kaukab 2015-01-09  4011  	if (ep == &hsotg->eps_out[0]->ep) {
5b7d70c6d drivers/usb/gadget/s3c-hsotg.c Ben Dooks          2009-06-02  4012  		dev_err(hsotg->dev, "%s: called for ep0\n", __func__);
5b7d70c6d drivers/usb/gadget/s3c-hsotg.c Ben Dooks          2009-06-02  4013  		return -EINVAL;
9b481092c drivers/usb/dwc2/gadget.c      John Stultz        2017-10-23  4014  	}
9b481092c drivers/usb/dwc2/gadget.c      John Stultz        2017-10-23  4015  
9b481092c drivers/usb/dwc2/gadget.c      John Stultz        2017-10-23  4016  	if (hsotg->op_state != OTG_STATE_B_PERIPHERAL) {
9b481092c drivers/usb/dwc2/gadget.c      John Stultz        2017-10-23  4017  		dev_err(hsotg->dev, "%s: called in host mode?\n", __func__);
9b481092c drivers/usb/dwc2/gadget.c      John Stultz        2017-10-23  4018  		return -EINVAL;
5b7d70c6d drivers/usb/gadget/s3c-hsotg.c Ben Dooks          2009-06-02  4019  	}
5b7d70c6d drivers/usb/gadget/s3c-hsotg.c Ben Dooks          2009-06-02  4020  
94cb8fd63 drivers/usb/gadget/s3c-hsotg.c Lukasz Majewski    2012-05-04  4021  	epctrl_reg = dir_in ? DIEPCTL(index) : DOEPCTL(index);
5b7d70c6d drivers/usb/gadget/s3c-hsotg.c Ben Dooks          2009-06-02  4022  
a4705c3fe drivers/usb/dwc2/gadget.c      Minas Harutyunyan  2018-09-18  4023  	locked = spin_trylock(&hsotg->lock);
a4705c3fe drivers/usb/dwc2/gadget.c      Minas Harutyunyan  2018-09-18 @4024  	spin_unlock(&hsotg->lock);
5ad1d3160 drivers/usb/gadget/s3c-hsotg.c Lukasz Majewski    2012-06-14  4025  	spin_lock_irqsave(&hsotg->lock, flags);


This is obviously deliberate that we drop the other thread's lock and
then take it ourselves.  But I don't think that can be right at all.
How do we know that it's safe for the other thread to drop the lock?

There should at least be a long comment in front of the code explaining
why it's safe to steal the lock like this.


5b7d70c6d drivers/usb/gadget/s3c-hsotg.c Ben Dooks          2009-06-02  4026  
f25c42b8d drivers/usb/dwc2/gadget.c      Gevorg Sahakyan    2018-07-26  4027  	ctrl = dwc2_readl(hsotg, epctrl_reg);
a4f827714 drivers/usb/dwc2/gadget.c      Vahram Aharonyan   2016-11-14  4028  
a4f827714 drivers/usb/dwc2/gadget.c      Vahram Aharonyan   2016-11-14  4029  	if (ctrl & DXEPCTL_EPENA)
a4f827714 drivers/usb/dwc2/gadget.c      Vahram Aharonyan   2016-11-14  4030  		dwc2_hsotg_ep_stop_xfr(hsotg, hs_ep);
a4f827714 drivers/usb/dwc2/gadget.c      Vahram Aharonyan   2016-11-14  4031  
47a1685f1 drivers/usb/dwc2/gadget.c      Dinh Nguyen        2014-04-14  4032  	ctrl &= ~DXEPCTL_EPENA;
47a1685f1 drivers/usb/dwc2/gadget.c      Dinh Nguyen        2014-04-14  4033  	ctrl &= ~DXEPCTL_USBACTEP;
47a1685f1 drivers/usb/dwc2/gadget.c      Dinh Nguyen        2014-04-14  4034  	ctrl |= DXEPCTL_SNAK;
5b7d70c6d drivers/usb/gadget/s3c-hsotg.c Ben Dooks          2009-06-02  4035  
5b7d70c6d drivers/usb/gadget/s3c-hsotg.c Ben Dooks          2009-06-02  4036  	dev_dbg(hsotg->dev, "%s: DxEPCTL=0x%08x\n", __func__, ctrl);
f25c42b8d drivers/usb/dwc2/gadget.c      Gevorg Sahakyan    2018-07-26  4037  	dwc2_writel(hsotg, ctrl, epctrl_reg);
5b7d70c6d drivers/usb/gadget/s3c-hsotg.c Ben Dooks          2009-06-02  4038  
5b7d70c6d drivers/usb/gadget/s3c-hsotg.c Ben Dooks          2009-06-02  4039  	/* disable endpoint interrupts */
1f91b4cc0 drivers/usb/dwc2/gadget.c      Felipe Balbi       2015-08-06  4040  	dwc2_hsotg_ctrl_epint(hsotg, hs_ep->index, hs_ep->dir_in, 0);
5b7d70c6d drivers/usb/gadget/s3c-hsotg.c Ben Dooks          2009-06-02  4041  
1141ea01d drivers/usb/dwc2/gadget.c      Mian Yousaf Kaukab 2015-01-09  4042  	/* terminate all requests with shutdown */
1141ea01d drivers/usb/dwc2/gadget.c      Mian Yousaf Kaukab 2015-01-09  4043  	kill_all_requests(hsotg, hs_ep, -ESHUTDOWN);
1141ea01d drivers/usb/dwc2/gadget.c      Mian Yousaf Kaukab 2015-01-09  4044  
1c07b20ea drivers/usb/dwc2/gadget.c      Robert Baldyga     2016-08-29  4045  	hsotg->fifo_map &= ~(1 << hs_ep->fifo_index);
1c07b20ea drivers/usb/dwc2/gadget.c      Robert Baldyga     2016-08-29  4046  	hs_ep->fifo_index = 0;
1c07b20ea drivers/usb/dwc2/gadget.c      Robert Baldyga     2016-08-29  4047  	hs_ep->fifo_size = 0;
1c07b20ea drivers/usb/dwc2/gadget.c      Robert Baldyga     2016-08-29  4048  
22258f490 drivers/usb/gadget/s3c-hsotg.c Lukasz Majewski    2012-06-14  4049  	spin_unlock_irqrestore(&hsotg->lock, flags);
a4705c3fe drivers/usb/dwc2/gadget.c      Minas Harutyunyan  2018-09-18  4050  	if (!locked)
a4705c3fe drivers/usb/dwc2/gadget.c      Minas Harutyunyan  2018-09-18  4051  		spin_lock(&hsotg->lock);
a4705c3fe drivers/usb/dwc2/gadget.c      Minas Harutyunyan  2018-09-18  4052  
5b7d70c6d drivers/usb/gadget/s3c-hsotg.c Ben Dooks          2009-06-02  4053  	return 0;
5b7d70c6d drivers/usb/gadget/s3c-hsotg.c Ben Dooks          2009-06-02  4054  }
5b7d70c6d drivers/usb/gadget/s3c-hsotg.c Ben Dooks          2009-06-02  4055  

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation
Minas Harutyunyan Sept. 20, 2018, 10:21 a.m. UTC | #3
Hi Dan,

On 9/20/2018 1:49 PM, Dan Carpenter wrote:
> is is obviously deliberate that we drop the other thread's lock and
> then take it ourselves.  But I don't think that can be right at all.
> How do we know that it's safe for the other thread to drop the lock?
> 
> There should at least be a long comment in front of the code explaining
> why it's safe to steal the lock like this.

Please review patch version 2: "[PATCH v2] usb: dwc2: Disable all EP's 
on disconnect"
Thanks,
Minas
Dan Carpenter Sept. 20, 2018, 10:30 a.m. UTC | #4
On Thu, Sep 20, 2018 at 10:21:26AM +0000, Minas Harutyunyan wrote:
> Hi Dan,
> 
> On 9/20/2018 1:49 PM, Dan Carpenter wrote:
> > is is obviously deliberate that we drop the other thread's lock and
> > then take it ourselves.  But I don't think that can be right at all.
> > How do we know that it's safe for the other thread to drop the lock?
> > 
> > There should at least be a long comment in front of the code explaining
> > why it's safe to steal the lock like this.
> 
> Please review patch version 2: "[PATCH v2] usb: dwc2: Disable all EP's 
> on disconnect"

These are automated emails from the kbuild bot.  I just review them and
forward them.  I'm not on the list.

I'm going to trust that you fixed it in an appropriate way.  :)

regards,
dan carpenter
diff mbox series

Patch

diff --git a/drivers/usb/dwc2/gadget.c b/drivers/usb/dwc2/gadget.c
index 220c0f9b89b0..30975731812e 100644
--- a/drivers/usb/dwc2/gadget.c
+++ b/drivers/usb/dwc2/gadget.c
@@ -3109,6 +3109,8 @@  static void kill_all_requests(struct dwc2_hsotg *hsotg,
 		dwc2_hsotg_txfifo_flush(hsotg, ep->fifo_index);
 }
 
+static int dwc2_hsotg_ep_disable(struct usb_ep *ep);
+
 /**
  * dwc2_hsotg_disconnect - disconnect service
  * @hsotg: The device state.
@@ -3127,13 +3129,12 @@  void dwc2_hsotg_disconnect(struct dwc2_hsotg *hsotg)
 	hsotg->connected = 0;
 	hsotg->test_mode = 0;
 
+	/* all endpoints should be shutdown */
 	for (ep = 0; ep < hsotg->num_of_eps; ep++) {
 		if (hsotg->eps_in[ep])
-			kill_all_requests(hsotg, hsotg->eps_in[ep],
-					  -ESHUTDOWN);
+			dwc2_hsotg_ep_disable(&hsotg->eps_in[ep]->ep);
 		if (hsotg->eps_out[ep])
-			kill_all_requests(hsotg, hsotg->eps_out[ep],
-					  -ESHUTDOWN);
+			dwc2_hsotg_ep_disable(&hsotg->eps_out[ep]->ep);
 	}
 
 	call_gadget(hsotg, disconnect);
@@ -3191,13 +3192,23 @@  void dwc2_hsotg_core_init_disconnected(struct dwc2_hsotg *hsotg,
 	u32 val;
 	u32 usbcfg;
 	u32 dcfg = 0;
+	int ep;
 
 	/* Kill any ep0 requests as controller will be reinitialized */
 	kill_all_requests(hsotg, hsotg->eps_out[0], -ECONNRESET);
 
-	if (!is_usb_reset)
+	if (!is_usb_reset) {
 		if (dwc2_core_reset(hsotg, true))
 			return;
+	} else {
+		/* all endpoints should be shutdown */
+		for (ep = 1; ep < hsotg->num_of_eps; ep++) {
+			if (hsotg->eps_in[ep])
+				dwc2_hsotg_ep_disable(&hsotg->eps_in[ep]->ep);
+			if (hsotg->eps_out[ep])
+				dwc2_hsotg_ep_disable(&hsotg->eps_out[ep]->ep);
+		}
+	}
 
 	/*
 	 * we must now enable ep0 ready for host detection and then
@@ -3993,6 +4004,7 @@  static int dwc2_hsotg_ep_disable(struct usb_ep *ep)
 	unsigned long flags;
 	u32 epctrl_reg;
 	u32 ctrl;
+	int locked;
 
 	dev_dbg(hsotg->dev, "%s(ep %p)\n", __func__, ep);
 
@@ -4008,6 +4020,8 @@  static int dwc2_hsotg_ep_disable(struct usb_ep *ep)
 
 	epctrl_reg = dir_in ? DIEPCTL(index) : DOEPCTL(index);
 
+	locked = spin_trylock(&hsotg->lock);
+	spin_unlock(&hsotg->lock);
 	spin_lock_irqsave(&hsotg->lock, flags);
 
 	ctrl = dwc2_readl(hsotg, epctrl_reg);
@@ -4033,6 +4047,9 @@  static int dwc2_hsotg_ep_disable(struct usb_ep *ep)
 	hs_ep->fifo_size = 0;
 
 	spin_unlock_irqrestore(&hsotg->lock, flags);
+	if (!locked)
+		spin_lock(&hsotg->lock);
+
 	return 0;
 }
 
@@ -4316,6 +4333,7 @@  static int dwc2_hsotg_udc_stop(struct usb_gadget *gadget)
 	struct dwc2_hsotg *hsotg = to_hsotg(gadget);
 	unsigned long flags = 0;
 	int ep;
+	int locked;
 
 	if (!hsotg)
 		return -ENODEV;
@@ -4328,6 +4346,8 @@  static int dwc2_hsotg_udc_stop(struct usb_gadget *gadget)
 			dwc2_hsotg_ep_disable(&hsotg->eps_out[ep]->ep);
 	}
 
+	locked = spin_trylock(&hsotg->lock);
+	spin_unlock(&hsotg->lock);
 	spin_lock_irqsave(&hsotg->lock, flags);
 
 	hsotg->driver = NULL;
@@ -4335,6 +4355,8 @@  static int dwc2_hsotg_udc_stop(struct usb_gadget *gadget)
 	hsotg->enabled = 0;
 
 	spin_unlock_irqrestore(&hsotg->lock, flags);
+	if (!locked)
+		spin_lock(&hsotg->lock);
 
 	if (!IS_ERR_OR_NULL(hsotg->uphy))
 		otg_set_peripheral(hsotg->uphy->otg, NULL);