diff options
author | Nicolas Ferre <nicolas.ferre@atmel.com> | 2012-05-09 04:48:54 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2012-05-09 18:22:27 -0400 |
commit | 07e4e556eff4938eb2edf2591de3aa7d7fb82b52 (patch) | |
tree | 07d5ec15744d1b6a764d55fe696791c4577d6329 /drivers/usb/host/ohci-at91.c | |
parent | 7a82f612fa3aadb5676184ae202903f5a42e4f4a (diff) |
USB: ohci-at91: add a reset function to fix race condition
A possible race condition appears because we are not initializing
the ohci->regs before calling usb_hcd_request_irqs().
We move the call to ohci_init() in hcd->driver->reset() instead of
hcd->driver->start() to fix this.
This was experienced when we share the same IRQ line between OHCI and EHCI
controllers.
Signed-off-by: Nicolas Ferre <nicolas.ferre@atmel.com>
Tested-by: Christian Eggers <christian.eggers@kathrein.de>
Cc: stable <stable@vger.kernel.org>
Acked-by: Alan Stern <stern@rowland.harvard.edu>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/usb/host/ohci-at91.c')
-rw-r--r-- | drivers/usb/host/ohci-at91.c | 11 |
1 files changed, 10 insertions, 1 deletions
diff --git a/drivers/usb/host/ohci-at91.c b/drivers/usb/host/ohci-at91.c index d4608c2d5b64..a665b3eaa746 100644 --- a/drivers/usb/host/ohci-at91.c +++ b/drivers/usb/host/ohci-at91.c | |||
@@ -223,7 +223,7 @@ static void __devexit usb_hcd_at91_remove(struct usb_hcd *hcd, | |||
223 | /*-------------------------------------------------------------------------*/ | 223 | /*-------------------------------------------------------------------------*/ |
224 | 224 | ||
225 | static int __devinit | 225 | static int __devinit |
226 | ohci_at91_start (struct usb_hcd *hcd) | 226 | ohci_at91_reset (struct usb_hcd *hcd) |
227 | { | 227 | { |
228 | struct at91_usbh_data *board = hcd->self.controller->platform_data; | 228 | struct at91_usbh_data *board = hcd->self.controller->platform_data; |
229 | struct ohci_hcd *ohci = hcd_to_ohci (hcd); | 229 | struct ohci_hcd *ohci = hcd_to_ohci (hcd); |
@@ -233,6 +233,14 @@ ohci_at91_start (struct usb_hcd *hcd) | |||
233 | return ret; | 233 | return ret; |
234 | 234 | ||
235 | ohci->num_ports = board->ports; | 235 | ohci->num_ports = board->ports; |
236 | return 0; | ||
237 | } | ||
238 | |||
239 | static int __devinit | ||
240 | ohci_at91_start (struct usb_hcd *hcd) | ||
241 | { | ||
242 | struct ohci_hcd *ohci = hcd_to_ohci (hcd); | ||
243 | int ret; | ||
236 | 244 | ||
237 | if ((ret = ohci_run(ohci)) < 0) { | 245 | if ((ret = ohci_run(ohci)) < 0) { |
238 | dev_err(hcd->self.controller, "can't start %s\n", | 246 | dev_err(hcd->self.controller, "can't start %s\n", |
@@ -419,6 +427,7 @@ static const struct hc_driver ohci_at91_hc_driver = { | |||
419 | /* | 427 | /* |
420 | * basic lifecycle operations | 428 | * basic lifecycle operations |
421 | */ | 429 | */ |
430 | .reset = ohci_at91_reset, | ||
422 | .start = ohci_at91_start, | 431 | .start = ohci_at91_start, |
423 | .stop = ohci_stop, | 432 | .stop = ohci_stop, |
424 | .shutdown = ohci_shutdown, | 433 | .shutdown = ohci_shutdown, |