kernel: revert an upstream linux-stable commit that is causing usb regressions on...
[openwrt/openwrt.git] / target / linux / generic / patches-3.10 / 140-revert_usb_unbind_interfaces.patch
1 commit 032f44791457d9aa50c6a194a2d475f07e311afd
2 Author: Felix Fietkau <nbd@openwrt.org>
3 Date: Wed Jul 9 12:08:23 2014 +0200
4
5 Revert "USB: unbind all interfaces before rebinding any"
6
7 This reverts commit 59f0103d74e4a32cbaa054d5011ea287fcfb83e4.
8 The commit has been found to cause USB regressions on AR933x and
9 BCM4705.
10
11 --- a/drivers/usb/core/driver.c
12 +++ b/drivers/usb/core/driver.c
13 @@ -953,7 +953,8 @@ EXPORT_SYMBOL_GPL(usb_deregister);
14 * it doesn't support pre_reset/post_reset/reset_resume or
15 * because it doesn't support suspend/resume.
16 *
17 - * The caller must hold @intf's device's lock, but not @intf's lock.
18 + * The caller must hold @intf's device's lock, but not its pm_mutex
19 + * and not @intf->dev.sem.
20 */
21 void usb_forced_unbind_intf(struct usb_interface *intf)
22 {
23 @@ -966,37 +967,16 @@ void usb_forced_unbind_intf(struct usb_i
24 intf->needs_binding = 1;
25 }
26
27 -/*
28 - * Unbind drivers for @udev's marked interfaces. These interfaces have
29 - * the needs_binding flag set, for example by usb_resume_interface().
30 - *
31 - * The caller must hold @udev's device lock.
32 - */
33 -static void unbind_marked_interfaces(struct usb_device *udev)
34 -{
35 - struct usb_host_config *config;
36 - int i;
37 - struct usb_interface *intf;
38 -
39 - config = udev->actconfig;
40 - if (config) {
41 - for (i = 0; i < config->desc.bNumInterfaces; ++i) {
42 - intf = config->interface[i];
43 - if (intf->dev.driver && intf->needs_binding)
44 - usb_forced_unbind_intf(intf);
45 - }
46 - }
47 -}
48 -
49 /* Delayed forced unbinding of a USB interface driver and scan
50 * for rebinding.
51 *
52 - * The caller must hold @intf's device's lock, but not @intf's lock.
53 + * The caller must hold @intf's device's lock, but not its pm_mutex
54 + * and not @intf->dev.sem.
55 *
56 * Note: Rebinds will be skipped if a system sleep transition is in
57 * progress and the PM "complete" callback hasn't occurred yet.
58 */
59 -static void usb_rebind_intf(struct usb_interface *intf)
60 +void usb_rebind_intf(struct usb_interface *intf)
61 {
62 int rc;
63
64 @@ -1013,66 +993,68 @@ static void usb_rebind_intf(struct usb_i
65 }
66 }
67
68 -/*
69 - * Rebind drivers to @udev's marked interfaces. These interfaces have
70 - * the needs_binding flag set.
71 +#ifdef CONFIG_PM
72 +
73 +/* Unbind drivers for @udev's interfaces that don't support suspend/resume
74 + * There is no check for reset_resume here because it can be determined
75 + * only during resume whether reset_resume is needed.
76 *
77 * The caller must hold @udev's device lock.
78 */
79 -static void rebind_marked_interfaces(struct usb_device *udev)
80 +static void unbind_no_pm_drivers_interfaces(struct usb_device *udev)
81 {
82 struct usb_host_config *config;
83 int i;
84 struct usb_interface *intf;
85 + struct usb_driver *drv;
86
87 config = udev->actconfig;
88 if (config) {
89 for (i = 0; i < config->desc.bNumInterfaces; ++i) {
90 intf = config->interface[i];
91 - if (intf->needs_binding)
92 - usb_rebind_intf(intf);
93 +
94 + if (intf->dev.driver) {
95 + drv = to_usb_driver(intf->dev.driver);
96 + if (!drv->suspend || !drv->resume)
97 + usb_forced_unbind_intf(intf);
98 + }
99 }
100 }
101 }
102
103 -/*
104 - * Unbind all of @udev's marked interfaces and then rebind all of them.
105 - * This ordering is necessary because some drivers claim several interfaces
106 - * when they are first probed.
107 +/* Unbind drivers for @udev's interfaces that failed to support reset-resume.
108 + * These interfaces have the needs_binding flag set by usb_resume_interface().
109 *
110 * The caller must hold @udev's device lock.
111 */
112 -void usb_unbind_and_rebind_marked_interfaces(struct usb_device *udev)
113 +static void unbind_no_reset_resume_drivers_interfaces(struct usb_device *udev)
114 {
115 - unbind_marked_interfaces(udev);
116 - rebind_marked_interfaces(udev);
117 -}
118 + struct usb_host_config *config;
119 + int i;
120 + struct usb_interface *intf;
121
122 -#ifdef CONFIG_PM
123 + config = udev->actconfig;
124 + if (config) {
125 + for (i = 0; i < config->desc.bNumInterfaces; ++i) {
126 + intf = config->interface[i];
127 + if (intf->dev.driver && intf->needs_binding)
128 + usb_forced_unbind_intf(intf);
129 + }
130 + }
131 +}
132
133 -/* Unbind drivers for @udev's interfaces that don't support suspend/resume
134 - * There is no check for reset_resume here because it can be determined
135 - * only during resume whether reset_resume is needed.
136 - *
137 - * The caller must hold @udev's device lock.
138 - */
139 -static void unbind_no_pm_drivers_interfaces(struct usb_device *udev)
140 +static void do_rebind_interfaces(struct usb_device *udev)
141 {
142 struct usb_host_config *config;
143 int i;
144 struct usb_interface *intf;
145 - struct usb_driver *drv;
146
147 config = udev->actconfig;
148 if (config) {
149 for (i = 0; i < config->desc.bNumInterfaces; ++i) {
150 intf = config->interface[i];
151 -
152 - if (intf->dev.driver) {
153 - drv = to_usb_driver(intf->dev.driver);
154 - if (!drv->suspend || !drv->resume)
155 - usb_forced_unbind_intf(intf);
156 - }
157 + if (intf->needs_binding)
158 + usb_rebind_intf(intf);
159 }
160 }
161 }
162 @@ -1397,7 +1379,7 @@ int usb_resume_complete(struct device *d
163 * whose needs_binding flag is set
164 */
165 if (udev->state != USB_STATE_NOTATTACHED)
166 - rebind_marked_interfaces(udev);
167 + do_rebind_interfaces(udev);
168 return 0;
169 }
170
171 @@ -1419,7 +1401,7 @@ int usb_resume(struct device *dev, pm_me
172 pm_runtime_disable(dev);
173 pm_runtime_set_active(dev);
174 pm_runtime_enable(dev);
175 - unbind_marked_interfaces(udev);
176 + unbind_no_reset_resume_drivers_interfaces(udev);
177 }
178
179 /* Avoid PM error messages for devices disconnected while suspended
180 --- a/drivers/usb/core/hub.c
181 +++ b/drivers/usb/core/hub.c
182 @@ -5263,11 +5263,10 @@ int usb_reset_device(struct usb_device *
183 else if (cintf->condition ==
184 USB_INTERFACE_BOUND)
185 rebind = 1;
186 - if (rebind)
187 - cintf->needs_binding = 1;
188 }
189 + if (ret == 0 && rebind)
190 + usb_rebind_intf(cintf);
191 }
192 - usb_unbind_and_rebind_marked_interfaces(udev);
193 }
194
195 usb_autosuspend_device(udev);
196 --- a/drivers/usb/core/usb.h
197 +++ b/drivers/usb/core/usb.h
198 @@ -55,7 +55,7 @@ extern int usb_match_one_id_intf(struct
199 extern int usb_match_device(struct usb_device *dev,
200 const struct usb_device_id *id);
201 extern void usb_forced_unbind_intf(struct usb_interface *intf);
202 -extern void usb_unbind_and_rebind_marked_interfaces(struct usb_device *udev);
203 +extern void usb_rebind_intf(struct usb_interface *intf);
204
205 extern int usb_hub_claim_port(struct usb_device *hdev, unsigned port,
206 struct dev_state *owner);