diff options
author | Sebastian Andrzej Siewior <bigeasy@linutronix.de> | 2011-09-23 17:19:57 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2011-09-26 18:51:12 -0400 |
commit | 3fd1ec58734e38a3f48776b6831ad0279d92d094 (patch) | |
tree | fc89e1e28394c202b69b5903094aa99414c35b25 /drivers/usb/host | |
parent | 7b7200098011a3f2b66f702b6fe47122cba585a3 (diff) |
usb/xhci: group MSI interrupt registration into its own function
This patch moves the complete MSI/MSI-X/Legacy dance into its own
function. There is however one difference: If the XHCI_BROKEN_MSI flag
is set then we don't free and register the irq, we simply return.
This is preparation for later PCI decouple.
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb/host')
-rw-r--r-- | drivers/usb/host/xhci.c | 70 |
1 files changed, 42 insertions, 28 deletions
diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index 7bf86774b1aa..583a3e330105 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c | |||
@@ -397,6 +397,45 @@ static int xhci_run_finished(struct xhci_hcd *xhci) | |||
397 | return 0; | 397 | return 0; |
398 | } | 398 | } |
399 | 399 | ||
400 | static int xhci_try_enable_msi(struct usb_hcd *hcd) | ||
401 | { | ||
402 | struct xhci_hcd *xhci = hcd_to_xhci(hcd); | ||
403 | struct pci_dev *pdev = to_pci_dev(xhci_to_hcd(xhci)->self.controller); | ||
404 | int ret; | ||
405 | |||
406 | /* | ||
407 | * Some Fresco Logic host controllers advertise MSI, but fail to | ||
408 | * generate interrupts. Don't even try to enable MSI. | ||
409 | */ | ||
410 | if (xhci->quirks & XHCI_BROKEN_MSI) | ||
411 | return 0; | ||
412 | |||
413 | /* unregister the legacy interrupt */ | ||
414 | if (hcd->irq) | ||
415 | free_irq(hcd->irq, hcd); | ||
416 | hcd->irq = -1; | ||
417 | |||
418 | ret = xhci_setup_msix(xhci); | ||
419 | if (ret) | ||
420 | /* fall back to msi*/ | ||
421 | ret = xhci_setup_msi(xhci); | ||
422 | |||
423 | if (!ret) | ||
424 | /* hcd->irq is -1, we have MSI */ | ||
425 | return 0; | ||
426 | |||
427 | /* fall back to legacy interrupt*/ | ||
428 | ret = request_irq(pdev->irq, &usb_hcd_irq, IRQF_SHARED, | ||
429 | hcd->irq_descr, hcd); | ||
430 | if (ret) { | ||
431 | xhci_err(xhci, "request interrupt %d failed\n", | ||
432 | pdev->irq); | ||
433 | return ret; | ||
434 | } | ||
435 | hcd->irq = pdev->irq; | ||
436 | return 0; | ||
437 | } | ||
438 | |||
400 | /* | 439 | /* |
401 | * Start the HC after it was halted. | 440 | * Start the HC after it was halted. |
402 | * | 441 | * |
@@ -413,9 +452,8 @@ int xhci_run(struct usb_hcd *hcd) | |||
413 | { | 452 | { |
414 | u32 temp; | 453 | u32 temp; |
415 | u64 temp_64; | 454 | u64 temp_64; |
416 | u32 ret; | 455 | int ret; |
417 | struct xhci_hcd *xhci = hcd_to_xhci(hcd); | 456 | struct xhci_hcd *xhci = hcd_to_xhci(hcd); |
418 | struct pci_dev *pdev = to_pci_dev(xhci_to_hcd(xhci)->self.controller); | ||
419 | 457 | ||
420 | /* Start the xHCI host controller running only after the USB 2.0 roothub | 458 | /* Start the xHCI host controller running only after the USB 2.0 roothub |
421 | * is setup. | 459 | * is setup. |
@@ -426,34 +464,10 @@ int xhci_run(struct usb_hcd *hcd) | |||
426 | return xhci_run_finished(xhci); | 464 | return xhci_run_finished(xhci); |
427 | 465 | ||
428 | xhci_dbg(xhci, "xhci_run\n"); | 466 | xhci_dbg(xhci, "xhci_run\n"); |
429 | /* unregister the legacy interrupt */ | ||
430 | if (hcd->irq) | ||
431 | free_irq(hcd->irq, hcd); | ||
432 | hcd->irq = -1; | ||
433 | 467 | ||
434 | /* Some Fresco Logic host controllers advertise MSI, but fail to | 468 | ret = xhci_try_enable_msi(hcd); |
435 | * generate interrupts. Don't even try to enable MSI. | ||
436 | */ | ||
437 | if (xhci->quirks & XHCI_BROKEN_MSI) | ||
438 | goto legacy_irq; | ||
439 | |||
440 | ret = xhci_setup_msix(xhci); | ||
441 | if (ret) | 469 | if (ret) |
442 | /* fall back to msi*/ | 470 | return ret; |
443 | ret = xhci_setup_msi(xhci); | ||
444 | |||
445 | if (ret) { | ||
446 | legacy_irq: | ||
447 | /* fall back to legacy interrupt*/ | ||
448 | ret = request_irq(pdev->irq, &usb_hcd_irq, IRQF_SHARED, | ||
449 | hcd->irq_descr, hcd); | ||
450 | if (ret) { | ||
451 | xhci_err(xhci, "request interrupt %d failed\n", | ||
452 | pdev->irq); | ||
453 | return ret; | ||
454 | } | ||
455 | hcd->irq = pdev->irq; | ||
456 | } | ||
457 | 471 | ||
458 | #ifdef CONFIG_USB_XHCI_HCD_DEBUGGING | 472 | #ifdef CONFIG_USB_XHCI_HCD_DEBUGGING |
459 | init_timer(&xhci->event_ring_timer); | 473 | init_timer(&xhci->event_ring_timer); |