brcm2708: add linux 4.19 support
[openwrt/staging/wigyori.git] / target / linux / brcm2708 / patches-4.19 / 950-0312-usb-dwc2-Disable-all-EP-s-on-disconnect.patch
1 From e87be7d6627b4dc1ebd9173b1bf29c16b4ebd93f Mon Sep 17 00:00:00 2001
2 From: Minas Harutyunyan <Minas.Harutyunyan@synopsys.com>
3 Date: Wed, 19 Sep 2018 18:13:52 +0400
4 Subject: [PATCH 312/703] usb: dwc2: Disable all EP's on disconnect
5
6 commit dccf1bad4be7eaa096c1f3697bd37883f9a08ecb upstream.
7
8 Disabling all EP's allow to reset EP's to initial state.
9 On disconnect disable all EP's instead of just killing
10 all requests. Because of some platform didn't catch
11 disconnect event, same stuff added to
12 dwc2_hsotg_core_init_disconnected() function when USB
13 reset detected on the bus.
14
15 Changed from version 1:
16 Changed lock acquire flow in dwc2_hsotg_ep_disable()
17 function.
18
19 Signed-off-by: Minas Harutyunyan <hminas@synopsys.com>
20 Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com>
21 ---
22 drivers/usb/dwc2/gadget.c | 30 +++++++++++++++++++++++-------
23 1 file changed, 23 insertions(+), 7 deletions(-)
24
25 --- a/drivers/usb/dwc2/gadget.c
26 +++ b/drivers/usb/dwc2/gadget.c
27 @@ -3107,6 +3107,8 @@ static void kill_all_requests(struct dwc
28 dwc2_hsotg_txfifo_flush(hsotg, ep->fifo_index);
29 }
30
31 +static int dwc2_hsotg_ep_disable(struct usb_ep *ep);
32 +
33 /**
34 * dwc2_hsotg_disconnect - disconnect service
35 * @hsotg: The device state.
36 @@ -3125,13 +3127,12 @@ void dwc2_hsotg_disconnect(struct dwc2_h
37 hsotg->connected = 0;
38 hsotg->test_mode = 0;
39
40 + /* all endpoints should be shutdown */
41 for (ep = 0; ep < hsotg->num_of_eps; ep++) {
42 if (hsotg->eps_in[ep])
43 - kill_all_requests(hsotg, hsotg->eps_in[ep],
44 - -ESHUTDOWN);
45 + dwc2_hsotg_ep_disable(&hsotg->eps_in[ep]->ep);
46 if (hsotg->eps_out[ep])
47 - kill_all_requests(hsotg, hsotg->eps_out[ep],
48 - -ESHUTDOWN);
49 + dwc2_hsotg_ep_disable(&hsotg->eps_out[ep]->ep);
50 }
51
52 call_gadget(hsotg, disconnect);
53 @@ -3189,13 +3190,23 @@ void dwc2_hsotg_core_init_disconnected(s
54 u32 val;
55 u32 usbcfg;
56 u32 dcfg = 0;
57 + int ep;
58
59 /* Kill any ep0 requests as controller will be reinitialized */
60 kill_all_requests(hsotg, hsotg->eps_out[0], -ECONNRESET);
61
62 - if (!is_usb_reset)
63 + if (!is_usb_reset) {
64 if (dwc2_core_reset(hsotg, true))
65 return;
66 + } else {
67 + /* all endpoints should be shutdown */
68 + for (ep = 1; ep < hsotg->num_of_eps; ep++) {
69 + if (hsotg->eps_in[ep])
70 + dwc2_hsotg_ep_disable(&hsotg->eps_in[ep]->ep);
71 + if (hsotg->eps_out[ep])
72 + dwc2_hsotg_ep_disable(&hsotg->eps_out[ep]->ep);
73 + }
74 + }
75
76 /*
77 * we must now enable ep0 ready for host detection and then
78 @@ -3996,6 +4007,7 @@ static int dwc2_hsotg_ep_disable(struct
79 unsigned long flags;
80 u32 epctrl_reg;
81 u32 ctrl;
82 + int locked;
83
84 dev_dbg(hsotg->dev, "%s(ep %p)\n", __func__, ep);
85
86 @@ -4011,7 +4023,9 @@ static int dwc2_hsotg_ep_disable(struct
87
88 epctrl_reg = dir_in ? DIEPCTL(index) : DOEPCTL(index);
89
90 - spin_lock_irqsave(&hsotg->lock, flags);
91 + locked = spin_is_locked(&hsotg->lock);
92 + if (!locked)
93 + spin_lock_irqsave(&hsotg->lock, flags);
94
95 ctrl = dwc2_readl(hsotg, epctrl_reg);
96
97 @@ -4035,7 +4049,9 @@ static int dwc2_hsotg_ep_disable(struct
98 hs_ep->fifo_index = 0;
99 hs_ep->fifo_size = 0;
100
101 - spin_unlock_irqrestore(&hsotg->lock, flags);
102 + if (!locked)
103 + spin_unlock_irqrestore(&hsotg->lock, flags);
104 +
105 return 0;
106 }
107