diff options
Diffstat (limited to 'drivers/pci')
-rw-r--r-- | drivers/pci/intr_remapping.c | 61 |
1 files changed, 59 insertions, 2 deletions
diff --git a/drivers/pci/intr_remapping.c b/drivers/pci/intr_remapping.c index b041a409f4a7..c26633d7e7da 100644 --- a/drivers/pci/intr_remapping.c +++ b/drivers/pci/intr_remapping.c | |||
@@ -470,7 +470,7 @@ static int setup_intr_remapping(struct intel_iommu *iommu, int mode) | |||
470 | /* | 470 | /* |
471 | * Disable Interrupt Remapping. | 471 | * Disable Interrupt Remapping. |
472 | */ | 472 | */ |
473 | static void disable_intr_remapping(struct intel_iommu *iommu) | 473 | static void iommu_disable_intr_remapping(struct intel_iommu *iommu) |
474 | { | 474 | { |
475 | unsigned long flags; | 475 | unsigned long flags; |
476 | u32 sts; | 476 | u32 sts; |
@@ -478,6 +478,12 @@ static void disable_intr_remapping(struct intel_iommu *iommu) | |||
478 | if (!ecap_ir_support(iommu->ecap)) | 478 | if (!ecap_ir_support(iommu->ecap)) |
479 | return; | 479 | return; |
480 | 480 | ||
481 | /* | ||
482 | * global invalidation of interrupt entry cache before disabling | ||
483 | * interrupt-remapping. | ||
484 | */ | ||
485 | qi_global_iec(iommu); | ||
486 | |||
481 | spin_lock_irqsave(&iommu->register_lock, flags); | 487 | spin_lock_irqsave(&iommu->register_lock, flags); |
482 | 488 | ||
483 | sts = dmar_readq(iommu->reg + DMAR_GSTS_REG); | 489 | sts = dmar_readq(iommu->reg + DMAR_GSTS_REG); |
@@ -511,7 +517,7 @@ int __init enable_intr_remapping(int eim) | |||
511 | * Disable intr remapping and queued invalidation, if already | 517 | * Disable intr remapping and queued invalidation, if already |
512 | * enabled prior to OS handover. | 518 | * enabled prior to OS handover. |
513 | */ | 519 | */ |
514 | disable_intr_remapping(iommu); | 520 | iommu_disable_intr_remapping(iommu); |
515 | 521 | ||
516 | dmar_disable_qi(iommu); | 522 | dmar_disable_qi(iommu); |
517 | } | 523 | } |
@@ -639,3 +645,54 @@ int __init parse_ioapics_under_ir(void) | |||
639 | 645 | ||
640 | return ir_supported; | 646 | return ir_supported; |
641 | } | 647 | } |
648 | |||
649 | void disable_intr_remapping(void) | ||
650 | { | ||
651 | struct dmar_drhd_unit *drhd; | ||
652 | struct intel_iommu *iommu = NULL; | ||
653 | |||
654 | /* | ||
655 | * Disable Interrupt-remapping for all the DRHD's now. | ||
656 | */ | ||
657 | for_each_iommu(iommu, drhd) { | ||
658 | if (!ecap_ir_support(iommu->ecap)) | ||
659 | continue; | ||
660 | |||
661 | iommu_disable_intr_remapping(iommu); | ||
662 | } | ||
663 | } | ||
664 | |||
665 | int reenable_intr_remapping(int eim) | ||
666 | { | ||
667 | struct dmar_drhd_unit *drhd; | ||
668 | int setup = 0; | ||
669 | struct intel_iommu *iommu = NULL; | ||
670 | |||
671 | for_each_iommu(iommu, drhd) | ||
672 | if (iommu->qi) | ||
673 | dmar_reenable_qi(iommu); | ||
674 | |||
675 | /* | ||
676 | * Setup Interrupt-remapping for all the DRHD's now. | ||
677 | */ | ||
678 | for_each_iommu(iommu, drhd) { | ||
679 | if (!ecap_ir_support(iommu->ecap)) | ||
680 | continue; | ||
681 | |||
682 | /* Set up interrupt remapping for iommu.*/ | ||
683 | iommu_set_intr_remapping(iommu, eim); | ||
684 | setup = 1; | ||
685 | } | ||
686 | |||
687 | if (!setup) | ||
688 | goto error; | ||
689 | |||
690 | return 0; | ||
691 | |||
692 | error: | ||
693 | /* | ||
694 | * handle error condition gracefully here! | ||
695 | */ | ||
696 | return -1; | ||
697 | } | ||
698 | |||