aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pci/intr_remapping.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/pci/intr_remapping.c')
-rw-r--r--drivers/pci/intr_remapping.c84
1 files changed, 82 insertions, 2 deletions
diff --git a/drivers/pci/intr_remapping.c b/drivers/pci/intr_remapping.c
index b041a409f4a7..f5e0ea724a6f 100644
--- a/drivers/pci/intr_remapping.c
+++ b/drivers/pci/intr_remapping.c
@@ -9,6 +9,7 @@
9#include <asm/cpu.h> 9#include <asm/cpu.h>
10#include <linux/intel-iommu.h> 10#include <linux/intel-iommu.h>
11#include "intr_remapping.h" 11#include "intr_remapping.h"
12#include <acpi/acpi.h>
12 13
13static struct ioapic_scope ir_ioapic[MAX_IO_APICS]; 14static struct ioapic_scope ir_ioapic[MAX_IO_APICS];
14static int ir_ioapic_num; 15static int ir_ioapic_num;
@@ -415,12 +416,27 @@ static void iommu_set_intr_remapping(struct intel_iommu *iommu, int mode)
415 416
416 /* Set interrupt-remapping table pointer */ 417 /* Set interrupt-remapping table pointer */
417 cmd = iommu->gcmd | DMA_GCMD_SIRTP; 418 cmd = iommu->gcmd | DMA_GCMD_SIRTP;
419 iommu->gcmd |= DMA_GCMD_SIRTP;
418 writel(cmd, iommu->reg + DMAR_GCMD_REG); 420 writel(cmd, iommu->reg + DMAR_GCMD_REG);
419 421
420 IOMMU_WAIT_OP(iommu, DMAR_GSTS_REG, 422 IOMMU_WAIT_OP(iommu, DMAR_GSTS_REG,
421 readl, (sts & DMA_GSTS_IRTPS), sts); 423 readl, (sts & DMA_GSTS_IRTPS), sts);
422 spin_unlock_irqrestore(&iommu->register_lock, flags); 424 spin_unlock_irqrestore(&iommu->register_lock, flags);
423 425
426 if (mode == 0) {
427 spin_lock_irqsave(&iommu->register_lock, flags);
428
429 /* enable comaptiblity format interrupt pass through */
430 cmd = iommu->gcmd | DMA_GCMD_CFI;
431 iommu->gcmd |= DMA_GCMD_CFI;
432 writel(cmd, iommu->reg + DMAR_GCMD_REG);
433
434 IOMMU_WAIT_OP(iommu, DMAR_GSTS_REG,
435 readl, (sts & DMA_GSTS_CFIS), sts);
436
437 spin_unlock_irqrestore(&iommu->register_lock, flags);
438 }
439
424 /* 440 /*
425 * global invalidation of interrupt entry cache before enabling 441 * global invalidation of interrupt entry cache before enabling
426 * interrupt-remapping. 442 * interrupt-remapping.
@@ -470,7 +486,7 @@ static int setup_intr_remapping(struct intel_iommu *iommu, int mode)
470/* 486/*
471 * Disable Interrupt Remapping. 487 * Disable Interrupt Remapping.
472 */ 488 */
473static void disable_intr_remapping(struct intel_iommu *iommu) 489static void iommu_disable_intr_remapping(struct intel_iommu *iommu)
474{ 490{
475 unsigned long flags; 491 unsigned long flags;
476 u32 sts; 492 u32 sts;
@@ -478,6 +494,12 @@ static void disable_intr_remapping(struct intel_iommu *iommu)
478 if (!ecap_ir_support(iommu->ecap)) 494 if (!ecap_ir_support(iommu->ecap))
479 return; 495 return;
480 496
497 /*
498 * global invalidation of interrupt entry cache before disabling
499 * interrupt-remapping.
500 */
501 qi_global_iec(iommu);
502
481 spin_lock_irqsave(&iommu->register_lock, flags); 503 spin_lock_irqsave(&iommu->register_lock, flags);
482 504
483 sts = dmar_readq(iommu->reg + DMAR_GSTS_REG); 505 sts = dmar_readq(iommu->reg + DMAR_GSTS_REG);
@@ -503,6 +525,13 @@ int __init enable_intr_remapping(int eim)
503 struct intel_iommu *iommu = drhd->iommu; 525 struct intel_iommu *iommu = drhd->iommu;
504 526
505 /* 527 /*
528 * If the queued invalidation is already initialized,
529 * shouldn't disable it.
530 */
531 if (iommu->qi)
532 continue;
533
534 /*
506 * Clear previous faults. 535 * Clear previous faults.
507 */ 536 */
508 dmar_fault(-1, iommu); 537 dmar_fault(-1, iommu);
@@ -511,7 +540,7 @@ int __init enable_intr_remapping(int eim)
511 * Disable intr remapping and queued invalidation, if already 540 * Disable intr remapping and queued invalidation, if already
512 * enabled prior to OS handover. 541 * enabled prior to OS handover.
513 */ 542 */
514 disable_intr_remapping(iommu); 543 iommu_disable_intr_remapping(iommu);
515 544
516 dmar_disable_qi(iommu); 545 dmar_disable_qi(iommu);
517 } 546 }
@@ -639,3 +668,54 @@ int __init parse_ioapics_under_ir(void)
639 668
640 return ir_supported; 669 return ir_supported;
641} 670}
671
672void disable_intr_remapping(void)
673{
674 struct dmar_drhd_unit *drhd;
675 struct intel_iommu *iommu = NULL;
676
677 /*
678 * Disable Interrupt-remapping for all the DRHD's now.
679 */
680 for_each_iommu(iommu, drhd) {
681 if (!ecap_ir_support(iommu->ecap))
682 continue;
683
684 iommu_disable_intr_remapping(iommu);
685 }
686}
687
688int reenable_intr_remapping(int eim)
689{
690 struct dmar_drhd_unit *drhd;
691 int setup = 0;
692 struct intel_iommu *iommu = NULL;
693
694 for_each_iommu(iommu, drhd)
695 if (iommu->qi)
696 dmar_reenable_qi(iommu);
697
698 /*
699 * Setup Interrupt-remapping for all the DRHD's now.
700 */
701 for_each_iommu(iommu, drhd) {
702 if (!ecap_ir_support(iommu->ecap))
703 continue;
704
705 /* Set up interrupt remapping for iommu.*/
706 iommu_set_intr_remapping(iommu, eim);
707 setup = 1;
708 }
709
710 if (!setup)
711 goto error;
712
713 return 0;
714
715error:
716 /*
717 * handle error condition gracefully here!
718 */
719 return -1;
720}
721