aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlan Stern <stern@rowland.harvard.edu>2012-07-11 11:23:10 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2012-07-16 19:56:48 -0400
commitc4f3476436f7452b97c8accb5dd7d53219a11a3f (patch)
tree95711a24bb4357dab53d4641aae5a09292974fb8
parentf42890782241a60d107f23d08089a4a12b507a11 (diff)
USB: EHCI: fix up locking
This patch (as1588) adjusts the locking in ehci-hcd's various halt, shutdown, and suspend/resume pathways. We want to hold the spinlock while writing device registers and accessing shared variables, but not while polling in a loop. In addition, there's no need to call ehci_work() at times when no URBs can be active, i.e., in ehci_stop() and ehci_bus_suspend(). Finally, ehci_adjust_port_wakeup_flags() is called only in situations where interrupts are enabled; therefore it can use spin_lock_irq rather than spin_lock_irqsave. Signed-off-by: Alan Stern <stern@rowland.harvard.edu> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--drivers/usb/host/ehci-hcd.c48
-rw-r--r--drivers/usb/host/ehci-hub.c41
-rw-r--r--drivers/usb/host/ehci-tegra.c5
3 files changed, 64 insertions, 30 deletions
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index 340c9c4894bf..ac4c8ddde20a 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -167,21 +167,24 @@ static int tdi_in_host_mode (struct ehci_hcd *ehci)
167 return (tmp & 3) == USBMODE_CM_HC; 167 return (tmp & 3) == USBMODE_CM_HC;
168} 168}
169 169
170/* force HC to halt state from unknown (EHCI spec section 2.3) */ 170/*
171 * Force HC to halt state from unknown (EHCI spec section 2.3).
172 * Must be called with interrupts enabled and the lock not held.
173 */
171static int ehci_halt (struct ehci_hcd *ehci) 174static int ehci_halt (struct ehci_hcd *ehci)
172{ 175{
173 u32 temp = ehci_readl(ehci, &ehci->regs->status); 176 u32 temp;
177
178 spin_lock_irq(&ehci->lock);
174 179
175 /* disable any irqs left enabled by previous code */ 180 /* disable any irqs left enabled by previous code */
176 ehci_writel(ehci, 0, &ehci->regs->intr_enable); 181 ehci_writel(ehci, 0, &ehci->regs->intr_enable);
177 182
178 if (ehci_is_TDI(ehci) && tdi_in_host_mode(ehci) == 0) { 183 if (ehci_is_TDI(ehci) && !tdi_in_host_mode(ehci)) {
184 spin_unlock_irq(&ehci->lock);
179 return 0; 185 return 0;
180 } 186 }
181 187
182 if ((temp & STS_HALT) != 0)
183 return 0;
184
185 /* 188 /*
186 * This routine gets called during probe before ehci->command 189 * This routine gets called during probe before ehci->command
187 * has been initialized, so we can't rely on its value. 190 * has been initialized, so we can't rely on its value.
@@ -190,7 +193,11 @@ static int ehci_halt (struct ehci_hcd *ehci)
190 temp = ehci_readl(ehci, &ehci->regs->command); 193 temp = ehci_readl(ehci, &ehci->regs->command);
191 temp &= ~(CMD_RUN | CMD_IAAD); 194 temp &= ~(CMD_RUN | CMD_IAAD);
192 ehci_writel(ehci, temp, &ehci->regs->command); 195 ehci_writel(ehci, temp, &ehci->regs->command);
193 return handshake (ehci, &ehci->regs->status, 196
197 spin_unlock_irq(&ehci->lock);
198 synchronize_irq(ehci_to_hcd(ehci)->irq);
199
200 return handshake(ehci, &ehci->regs->status,
194 STS_HALT, STS_HALT, 16 * 125); 201 STS_HALT, STS_HALT, 16 * 125);
195} 202}
196 203
@@ -210,7 +217,10 @@ static void tdi_reset (struct ehci_hcd *ehci)
210 ehci_writel(ehci, tmp, &ehci->regs->usbmode); 217 ehci_writel(ehci, tmp, &ehci->regs->usbmode);
211} 218}
212 219
213/* reset a non-running (STS_HALT == 1) controller */ 220/*
221 * Reset a non-running (STS_HALT == 1) controller.
222 * Must be called with interrupts enabled and the lock not held.
223 */
214static int ehci_reset (struct ehci_hcd *ehci) 224static int ehci_reset (struct ehci_hcd *ehci)
215{ 225{
216 int retval; 226 int retval;
@@ -248,7 +258,10 @@ static int ehci_reset (struct ehci_hcd *ehci)
248 return retval; 258 return retval;
249} 259}
250 260
251/* idle the controller (from running) */ 261/*
262 * Idle the controller (turn off the schedules).
263 * Must be called with interrupts enabled and the lock not held.
264 */
252static void ehci_quiesce (struct ehci_hcd *ehci) 265static void ehci_quiesce (struct ehci_hcd *ehci)
253{ 266{
254 u32 temp; 267 u32 temp;
@@ -261,8 +274,10 @@ static void ehci_quiesce (struct ehci_hcd *ehci)
261 handshake(ehci, &ehci->regs->status, STS_ASS | STS_PSS, temp, 16 * 125); 274 handshake(ehci, &ehci->regs->status, STS_ASS | STS_PSS, temp, 16 * 125);
262 275
263 /* then disable anything that's still active */ 276 /* then disable anything that's still active */
277 spin_lock_irq(&ehci->lock);
264 ehci->command &= ~(CMD_ASE | CMD_PSE); 278 ehci->command &= ~(CMD_ASE | CMD_PSE);
265 ehci_writel(ehci, ehci->command, &ehci->regs->command); 279 ehci_writel(ehci, ehci->command, &ehci->regs->command);
280 spin_unlock_irq(&ehci->lock);
266 281
267 /* hardware can take 16 microframes to turn off ... */ 282 /* hardware can take 16 microframes to turn off ... */
268 handshake(ehci, &ehci->regs->status, STS_ASS | STS_PSS, 0, 16 * 125); 283 handshake(ehci, &ehci->regs->status, STS_ASS | STS_PSS, 0, 16 * 125);
@@ -301,11 +316,14 @@ static void ehci_turn_off_all_ports(struct ehci_hcd *ehci)
301 316
302/* 317/*
303 * Halt HC, turn off all ports, and let the BIOS use the companion controllers. 318 * Halt HC, turn off all ports, and let the BIOS use the companion controllers.
304 * Should be called with ehci->lock held. 319 * Must be called with interrupts enabled and the lock not held.
305 */ 320 */
306static void ehci_silence_controller(struct ehci_hcd *ehci) 321static void ehci_silence_controller(struct ehci_hcd *ehci)
307{ 322{
308 ehci_halt(ehci); 323 ehci_halt(ehci);
324
325 spin_lock_irq(&ehci->lock);
326 ehci->rh_state = EHCI_RH_HALTED;
309 ehci_turn_off_all_ports(ehci); 327 ehci_turn_off_all_ports(ehci);
310 328
311 /* make BIOS/etc use companion controller during reboot */ 329 /* make BIOS/etc use companion controller during reboot */
@@ -313,6 +331,7 @@ static void ehci_silence_controller(struct ehci_hcd *ehci)
313 331
314 /* unblock posted writes */ 332 /* unblock posted writes */
315 ehci_readl(ehci, &ehci->regs->configured_flag); 333 ehci_readl(ehci, &ehci->regs->configured_flag);
334 spin_unlock_irq(&ehci->lock);
316} 335}
317 336
318/* ehci_shutdown kick in for silicon on any bus (not just pci, etc). 337/* ehci_shutdown kick in for silicon on any bus (not just pci, etc).
@@ -325,10 +344,11 @@ static void ehci_shutdown(struct usb_hcd *hcd)
325 344
326 spin_lock_irq(&ehci->lock); 345 spin_lock_irq(&ehci->lock);
327 ehci->rh_state = EHCI_RH_STOPPING; 346 ehci->rh_state = EHCI_RH_STOPPING;
328 ehci_silence_controller(ehci);
329 ehci->enabled_hrtimer_events = 0; 347 ehci->enabled_hrtimer_events = 0;
330 spin_unlock_irq(&ehci->lock); 348 spin_unlock_irq(&ehci->lock);
331 349
350 ehci_silence_controller(ehci);
351
332 hrtimer_cancel(&ehci->hrtimer); 352 hrtimer_cancel(&ehci->hrtimer);
333} 353}
334 354
@@ -400,11 +420,11 @@ static void ehci_stop (struct usb_hcd *hcd)
400 420
401 spin_lock_irq(&ehci->lock); 421 spin_lock_irq(&ehci->lock);
402 ehci->enabled_hrtimer_events = 0; 422 ehci->enabled_hrtimer_events = 0;
403 ehci_quiesce(ehci); 423 spin_unlock_irq(&ehci->lock);
404 424
425 ehci_quiesce(ehci);
405 ehci_silence_controller(ehci); 426 ehci_silence_controller(ehci);
406 ehci_reset (ehci); 427 ehci_reset (ehci);
407 spin_unlock_irq(&ehci->lock);
408 428
409 hrtimer_cancel(&ehci->hrtimer); 429 hrtimer_cancel(&ehci->hrtimer);
410 remove_sysfs_files(ehci); 430 remove_sysfs_files(ehci);
@@ -412,8 +432,6 @@ static void ehci_stop (struct usb_hcd *hcd)
412 432
413 /* root hub is shut down separately (first, when possible) */ 433 /* root hub is shut down separately (first, when possible) */
414 spin_lock_irq (&ehci->lock); 434 spin_lock_irq (&ehci->lock);
415 if (ehci->async)
416 ehci_work (ehci);
417 end_free_itds(ehci); 435 end_free_itds(ehci);
418 spin_unlock_irq (&ehci->lock); 436 spin_unlock_irq (&ehci->lock);
419 ehci_mem_cleanup (ehci); 437 ehci_mem_cleanup (ehci);
diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c
index 05490d387fd2..ffc5f27df725 100644
--- a/drivers/usb/host/ehci-hub.c
+++ b/drivers/usb/host/ehci-hub.c
@@ -59,6 +59,7 @@ static void ehci_handover_companion_ports(struct ehci_hcd *ehci)
59 /* Give the connections some time to appear */ 59 /* Give the connections some time to appear */
60 msleep(20); 60 msleep(20);
61 61
62 spin_lock_irq(&ehci->lock);
62 port = HCS_N_PORTS(ehci->hcs_params); 63 port = HCS_N_PORTS(ehci->hcs_params);
63 while (port--) { 64 while (port--) {
64 if (test_bit(port, &ehci->owned_ports)) { 65 if (test_bit(port, &ehci->owned_ports)) {
@@ -70,23 +71,30 @@ static void ehci_handover_companion_ports(struct ehci_hcd *ehci)
70 clear_bit(port, &ehci->owned_ports); 71 clear_bit(port, &ehci->owned_ports);
71 else if (test_bit(port, &ehci->companion_ports)) 72 else if (test_bit(port, &ehci->companion_ports))
72 ehci_writel(ehci, status & ~PORT_PE, reg); 73 ehci_writel(ehci, status & ~PORT_PE, reg);
73 else 74 else {
75 spin_unlock_irq(&ehci->lock);
74 ehci_hub_control(hcd, SetPortFeature, 76 ehci_hub_control(hcd, SetPortFeature,
75 USB_PORT_FEAT_RESET, port + 1, 77 USB_PORT_FEAT_RESET, port + 1,
76 NULL, 0); 78 NULL, 0);
79 spin_lock_irq(&ehci->lock);
80 }
77 } 81 }
78 } 82 }
83 spin_unlock_irq(&ehci->lock);
79 84
80 if (!ehci->owned_ports) 85 if (!ehci->owned_ports)
81 return; 86 return;
82 msleep(90); /* Wait for resets to complete */ 87 msleep(90); /* Wait for resets to complete */
83 88
89 spin_lock_irq(&ehci->lock);
84 port = HCS_N_PORTS(ehci->hcs_params); 90 port = HCS_N_PORTS(ehci->hcs_params);
85 while (port--) { 91 while (port--) {
86 if (test_bit(port, &ehci->owned_ports)) { 92 if (test_bit(port, &ehci->owned_ports)) {
93 spin_unlock_irq(&ehci->lock);
87 ehci_hub_control(hcd, GetPortStatus, 94 ehci_hub_control(hcd, GetPortStatus,
88 0, port + 1, 95 0, port + 1,
89 (char *) &buf, sizeof(buf)); 96 (char *) &buf, sizeof(buf));
97 spin_lock_irq(&ehci->lock);
90 98
91 /* The companion should now own the port, 99 /* The companion should now own the port,
92 * but if something went wrong the port must not 100 * but if something went wrong the port must not
@@ -105,6 +113,7 @@ static void ehci_handover_companion_ports(struct ehci_hcd *ehci)
105 } 113 }
106 114
107 ehci->owned_ports = 0; 115 ehci->owned_ports = 0;
116 spin_unlock_irq(&ehci->lock);
108} 117}
109 118
110static int ehci_port_change(struct ehci_hcd *ehci) 119static int ehci_port_change(struct ehci_hcd *ehci)
@@ -133,7 +142,6 @@ static void ehci_adjust_port_wakeup_flags(struct ehci_hcd *ehci,
133{ 142{
134 int port; 143 int port;
135 u32 temp; 144 u32 temp;
136 unsigned long flags;
137 145
138 /* If remote wakeup is enabled for the root hub but disabled 146 /* If remote wakeup is enabled for the root hub but disabled
139 * for the controller, we must adjust all the port wakeup flags 147 * for the controller, we must adjust all the port wakeup flags
@@ -143,7 +151,7 @@ static void ehci_adjust_port_wakeup_flags(struct ehci_hcd *ehci,
143 if (!ehci_to_hcd(ehci)->self.root_hub->do_remote_wakeup || do_wakeup) 151 if (!ehci_to_hcd(ehci)->self.root_hub->do_remote_wakeup || do_wakeup)
144 return; 152 return;
145 153
146 spin_lock_irqsave(&ehci->lock, flags); 154 spin_lock_irq(&ehci->lock);
147 155
148 /* clear phy low-power mode before changing wakeup flags */ 156 /* clear phy low-power mode before changing wakeup flags */
149 if (ehci->has_hostpc) { 157 if (ehci->has_hostpc) {
@@ -154,9 +162,9 @@ static void ehci_adjust_port_wakeup_flags(struct ehci_hcd *ehci,
154 temp = ehci_readl(ehci, hostpc_reg); 162 temp = ehci_readl(ehci, hostpc_reg);
155 ehci_writel(ehci, temp & ~HOSTPC_PHCD, hostpc_reg); 163 ehci_writel(ehci, temp & ~HOSTPC_PHCD, hostpc_reg);
156 } 164 }
157 spin_unlock_irqrestore(&ehci->lock, flags); 165 spin_unlock_irq(&ehci->lock);
158 msleep(5); 166 msleep(5);
159 spin_lock_irqsave(&ehci->lock, flags); 167 spin_lock_irq(&ehci->lock);
160 } 168 }
161 169
162 port = HCS_N_PORTS(ehci->hcs_params); 170 port = HCS_N_PORTS(ehci->hcs_params);
@@ -194,7 +202,7 @@ static void ehci_adjust_port_wakeup_flags(struct ehci_hcd *ehci,
194 if (!suspending && ehci_port_change(ehci)) 202 if (!suspending && ehci_port_change(ehci))
195 usb_hcd_resume_root_hub(ehci_to_hcd(ehci)); 203 usb_hcd_resume_root_hub(ehci_to_hcd(ehci));
196 204
197 spin_unlock_irqrestore(&ehci->lock, flags); 205 spin_unlock_irq(&ehci->lock);
198} 206}
199 207
200static int ehci_bus_suspend (struct usb_hcd *hcd) 208static int ehci_bus_suspend (struct usb_hcd *hcd)
@@ -209,6 +217,9 @@ static int ehci_bus_suspend (struct usb_hcd *hcd)
209 if (time_before (jiffies, ehci->next_statechange)) 217 if (time_before (jiffies, ehci->next_statechange))
210 msleep(5); 218 msleep(5);
211 219
220 /* stop the schedules */
221 ehci_quiesce(ehci);
222
212 spin_lock_irq (&ehci->lock); 223 spin_lock_irq (&ehci->lock);
213 224
214 /* Once the controller is stopped, port resumes that are already 225 /* Once the controller is stopped, port resumes that are already
@@ -224,10 +235,6 @@ static int ehci_bus_suspend (struct usb_hcd *hcd)
224 } 235 }
225 } 236 }
226 237
227 /* stop schedules, clean any completed work */
228 ehci_quiesce(ehci);
229 ehci_work(ehci);
230
231 /* Unlike other USB host controller types, EHCI doesn't have 238 /* Unlike other USB host controller types, EHCI doesn't have
232 * any notion of "global" or bus-wide suspend. The driver has 239 * any notion of "global" or bus-wide suspend. The driver has
233 * to manually suspend all the active unsuspended ports, and 240 * to manually suspend all the active unsuspended ports, and
@@ -289,6 +296,7 @@ static int ehci_bus_suspend (struct usb_hcd *hcd)
289 "succeeded" : "failed"); 296 "succeeded" : "failed");
290 } 297 }
291 } 298 }
299 spin_unlock_irq(&ehci->lock);
292 300
293 /* Apparently some devices need a >= 1-uframe delay here */ 301 /* Apparently some devices need a >= 1-uframe delay here */
294 if (ehci->bus_suspended) 302 if (ehci->bus_suspended)
@@ -296,6 +304,8 @@ static int ehci_bus_suspend (struct usb_hcd *hcd)
296 304
297 /* turn off now-idle HC */ 305 /* turn off now-idle HC */
298 ehci_halt (ehci); 306 ehci_halt (ehci);
307
308 spin_lock_irq(&ehci->lock);
299 ehci->rh_state = EHCI_RH_SUSPENDED; 309 ehci->rh_state = EHCI_RH_SUSPENDED;
300 310
301 end_unlink_async(ehci); 311 end_unlink_async(ehci);
@@ -424,13 +434,14 @@ static int ehci_bus_resume (struct usb_hcd *hcd)
424 } 434 }
425 435
426 ehci->next_statechange = jiffies + msecs_to_jiffies(5); 436 ehci->next_statechange = jiffies + msecs_to_jiffies(5);
437 spin_unlock_irq(&ehci->lock);
438
439 ehci_handover_companion_ports(ehci);
427 440
428 /* Now we can safely re-enable irqs */ 441 /* Now we can safely re-enable irqs */
429 ehci_writel(ehci, INTR_MASK, &ehci->regs->intr_enable); 442 ehci_writel(ehci, INTR_MASK, &ehci->regs->intr_enable);
430 (void) ehci_readl(ehci, &ehci->regs->intr_enable); 443 (void) ehci_readl(ehci, &ehci->regs->intr_enable);
431 444
432 spin_unlock_irq (&ehci->lock);
433 ehci_handover_companion_ports(ehci);
434 return 0; 445 return 0;
435} 446}
436 447
@@ -1018,7 +1029,9 @@ static int ehci_hub_control (
1018 case USB_PORT_FEAT_TEST: 1029 case USB_PORT_FEAT_TEST:
1019 if (!selector || selector > 5) 1030 if (!selector || selector > 5)
1020 goto error; 1031 goto error;
1032 spin_unlock_irqrestore(&ehci->lock, flags);
1021 ehci_quiesce(ehci); 1033 ehci_quiesce(ehci);
1034 spin_lock_irqsave(&ehci->lock, flags);
1022 1035
1023 /* Put all enabled ports into suspend */ 1036 /* Put all enabled ports into suspend */
1024 while (ports--) { 1037 while (ports--) {
@@ -1030,7 +1043,11 @@ static int ehci_hub_control (
1030 ehci_writel(ehci, temp | PORT_SUSPEND, 1043 ehci_writel(ehci, temp | PORT_SUSPEND,
1031 sreg); 1044 sreg);
1032 } 1045 }
1046
1047 spin_unlock_irqrestore(&ehci->lock, flags);
1033 ehci_halt(ehci); 1048 ehci_halt(ehci);
1049 spin_lock_irqsave(&ehci->lock, flags);
1050
1034 temp = ehci_readl(ehci, status_reg); 1051 temp = ehci_readl(ehci, status_reg);
1035 temp |= selector << 16; 1052 temp |= selector << 16;
1036 ehci_writel(ehci, temp, status_reg); 1053 ehci_writel(ehci, temp, status_reg);
diff --git a/drivers/usb/host/ehci-tegra.c b/drivers/usb/host/ehci-tegra.c
index f7f3ce3275b8..65360945df78 100644
--- a/drivers/usb/host/ehci-tegra.c
+++ b/drivers/usb/host/ehci-tegra.c
@@ -445,12 +445,11 @@ static int controller_suspend(struct device *dev)
445 if (time_before(jiffies, ehci->next_statechange)) 445 if (time_before(jiffies, ehci->next_statechange))
446 msleep(10); 446 msleep(10);
447 447
448 spin_lock_irqsave(&ehci->lock, flags); 448 ehci_halt(ehci);
449 449
450 spin_lock_irqsave(&ehci->lock, flags);
450 tegra->port_speed = (readl(&hw->port_status[0]) >> 26) & 0x3; 451 tegra->port_speed = (readl(&hw->port_status[0]) >> 26) & 0x3;
451 ehci_halt(ehci);
452 clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); 452 clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
453
454 spin_unlock_irqrestore(&ehci->lock, flags); 453 spin_unlock_irqrestore(&ehci->lock, flags);
455 454
456 tegra_ehci_power_down(hcd); 455 tegra_ehci_power_down(hcd);