Skip to content

Commit dccf1ba

Browse files
Minas HarutyunyanFelipe Balbi
Minas Harutyunyan
authored and
Felipe Balbi
committed
usb: dwc2: Disable all EP's on disconnect
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. Changed from version 1: Changed lock acquire flow in dwc2_hsotg_ep_disable() function. Signed-off-by: Minas Harutyunyan <[email protected]> Signed-off-by: Felipe Balbi <[email protected]>
1 parent 4c19cc1 commit dccf1ba

File tree

1 file changed

+23
-7
lines changed

1 file changed

+23
-7
lines changed

drivers/usb/dwc2/gadget.c

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3109,6 +3109,8 @@ static void kill_all_requests(struct dwc2_hsotg *hsotg,
31093109
dwc2_hsotg_txfifo_flush(hsotg, ep->fifo_index);
31103110
}
31113111

3112+
static int dwc2_hsotg_ep_disable(struct usb_ep *ep);
3113+
31123114
/**
31133115
* dwc2_hsotg_disconnect - disconnect service
31143116
* @hsotg: The device state.
@@ -3127,13 +3129,12 @@ void dwc2_hsotg_disconnect(struct dwc2_hsotg *hsotg)
31273129
hsotg->connected = 0;
31283130
hsotg->test_mode = 0;
31293131

3132+
/* all endpoints should be shutdown */
31303133
for (ep = 0; ep < hsotg->num_of_eps; ep++) {
31313134
if (hsotg->eps_in[ep])
3132-
kill_all_requests(hsotg, hsotg->eps_in[ep],
3133-
-ESHUTDOWN);
3135+
dwc2_hsotg_ep_disable(&hsotg->eps_in[ep]->ep);
31343136
if (hsotg->eps_out[ep])
3135-
kill_all_requests(hsotg, hsotg->eps_out[ep],
3136-
-ESHUTDOWN);
3137+
dwc2_hsotg_ep_disable(&hsotg->eps_out[ep]->ep);
31373138
}
31383139

31393140
call_gadget(hsotg, disconnect);
@@ -3191,13 +3192,23 @@ void dwc2_hsotg_core_init_disconnected(struct dwc2_hsotg *hsotg,
31913192
u32 val;
31923193
u32 usbcfg;
31933194
u32 dcfg = 0;
3195+
int ep;
31943196

31953197
/* Kill any ep0 requests as controller will be reinitialized */
31963198
kill_all_requests(hsotg, hsotg->eps_out[0], -ECONNRESET);
31973199

3198-
if (!is_usb_reset)
3200+
if (!is_usb_reset) {
31993201
if (dwc2_core_reset(hsotg, true))
32003202
return;
3203+
} else {
3204+
/* all endpoints should be shutdown */
3205+
for (ep = 1; ep < hsotg->num_of_eps; ep++) {
3206+
if (hsotg->eps_in[ep])
3207+
dwc2_hsotg_ep_disable(&hsotg->eps_in[ep]->ep);
3208+
if (hsotg->eps_out[ep])
3209+
dwc2_hsotg_ep_disable(&hsotg->eps_out[ep]->ep);
3210+
}
3211+
}
32013212

32023213
/*
32033214
* 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)
39934004
unsigned long flags;
39944005
u32 epctrl_reg;
39954006
u32 ctrl;
4007+
int locked;
39964008

39974009
dev_dbg(hsotg->dev, "%s(ep %p)\n", __func__, ep);
39984010

@@ -4008,7 +4020,9 @@ static int dwc2_hsotg_ep_disable(struct usb_ep *ep)
40084020

40094021
epctrl_reg = dir_in ? DIEPCTL(index) : DOEPCTL(index);
40104022

4011-
spin_lock_irqsave(&hsotg->lock, flags);
4023+
locked = spin_is_locked(&hsotg->lock);
4024+
if (!locked)
4025+
spin_lock_irqsave(&hsotg->lock, flags);
40124026

40134027
ctrl = dwc2_readl(hsotg, epctrl_reg);
40144028

@@ -4032,7 +4046,9 @@ static int dwc2_hsotg_ep_disable(struct usb_ep *ep)
40324046
hs_ep->fifo_index = 0;
40334047
hs_ep->fifo_size = 0;
40344048

4035-
spin_unlock_irqrestore(&hsotg->lock, flags);
4049+
if (!locked)
4050+
spin_unlock_irqrestore(&hsotg->lock, flags);
4051+
40364052
return 0;
40374053
}
40384054

0 commit comments

Comments
 (0)