kernel: revert an upstream linux-stable commit that is causing usb regressions on...
[15.05/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);