diff options
| author | Suresh Siddha <suresh.b.siddha@intel.com> | 2009-03-16 20:04:56 -0400 |
|---|---|---|
| committer | H. Peter Anvin <hpa@linux.intel.com> | 2009-03-17 18:39:20 -0400 |
| commit | eba67e5da6e971993b2899d2cdf459ce77d3dbc5 (patch) | |
| tree | 1776415c0ed65e6ad309b6790110941fadef243f | |
| parent | 9d783ba042771284fb4ee5013c3d94220755ae7f (diff) | |
x86, dmar: routines for disabling queued invalidation and intr remapping
Impact: new interfaces (not yet used)
Routines for disabling queued invalidation and interrupt remapping.
Signed-off-by: Suresh Siddha <suresh.b.siddha@intel.com>
Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>
| -rw-r--r-- | drivers/pci/dmar.c | 36 | ||||
| -rw-r--r-- | drivers/pci/intr_remapping.c | 27 | ||||
| -rw-r--r-- | include/linux/intel-iommu.h | 1 |
3 files changed, 64 insertions, 0 deletions
diff --git a/drivers/pci/dmar.c b/drivers/pci/dmar.c index bb4ed985f9c7..932e5e3930fc 100644 --- a/drivers/pci/dmar.c +++ b/drivers/pci/dmar.c | |||
| @@ -754,6 +754,42 @@ int qi_flush_iotlb(struct intel_iommu *iommu, u16 did, u64 addr, | |||
| 754 | } | 754 | } |
| 755 | 755 | ||
| 756 | /* | 756 | /* |
| 757 | * Disable Queued Invalidation interface. | ||
| 758 | */ | ||
| 759 | void dmar_disable_qi(struct intel_iommu *iommu) | ||
| 760 | { | ||
| 761 | unsigned long flags; | ||
| 762 | u32 sts; | ||
| 763 | cycles_t start_time = get_cycles(); | ||
| 764 | |||
| 765 | if (!ecap_qis(iommu->ecap)) | ||
| 766 | return; | ||
| 767 | |||
| 768 | spin_lock_irqsave(&iommu->register_lock, flags); | ||
| 769 | |||
| 770 | sts = dmar_readq(iommu->reg + DMAR_GSTS_REG); | ||
| 771 | if (!(sts & DMA_GSTS_QIES)) | ||
| 772 | goto end; | ||
| 773 | |||
| 774 | /* | ||
| 775 | * Give a chance to HW to complete the pending invalidation requests. | ||
| 776 | */ | ||
| 777 | while ((readl(iommu->reg + DMAR_IQT_REG) != | ||
| 778 | readl(iommu->reg + DMAR_IQH_REG)) && | ||
| 779 | (DMAR_OPERATION_TIMEOUT > (get_cycles() - start_time))) | ||
| 780 | cpu_relax(); | ||
| 781 | |||
| 782 | iommu->gcmd &= ~DMA_GCMD_QIE; | ||
| 783 | |||
| 784 | writel(iommu->gcmd, iommu->reg + DMAR_GCMD_REG); | ||
| 785 | |||
| 786 | IOMMU_WAIT_OP(iommu, DMAR_GSTS_REG, readl, | ||
| 787 | !(sts & DMA_GSTS_QIES), sts); | ||
| 788 | end: | ||
| 789 | spin_unlock_irqrestore(&iommu->register_lock, flags); | ||
| 790 | } | ||
| 791 | |||
| 792 | /* | ||
| 757 | * Enable Queued Invalidation interface. This is a must to support | 793 | * Enable Queued Invalidation interface. This is a must to support |
| 758 | * interrupt-remapping. Also used by DMA-remapping, which replaces | 794 | * interrupt-remapping. Also used by DMA-remapping, which replaces |
| 759 | * register based IOTLB invalidation. | 795 | * register based IOTLB invalidation. |
diff --git a/drivers/pci/intr_remapping.c b/drivers/pci/intr_remapping.c index c38e3f437a81..0d202d73a1ac 100644 --- a/drivers/pci/intr_remapping.c +++ b/drivers/pci/intr_remapping.c | |||
| @@ -467,6 +467,33 @@ static int setup_intr_remapping(struct intel_iommu *iommu, int mode) | |||
| 467 | return 0; | 467 | return 0; |
| 468 | } | 468 | } |
| 469 | 469 | ||
| 470 | /* | ||
| 471 | * Disable Interrupt Remapping. | ||
| 472 | */ | ||
| 473 | static void disable_intr_remapping(struct intel_iommu *iommu) | ||
| 474 | { | ||
| 475 | unsigned long flags; | ||
| 476 | u32 sts; | ||
| 477 | |||
| 478 | if (!ecap_ir_support(iommu->ecap)) | ||
| 479 | return; | ||
| 480 | |||
| 481 | spin_lock_irqsave(&iommu->register_lock, flags); | ||
| 482 | |||
| 483 | sts = dmar_readq(iommu->reg + DMAR_GSTS_REG); | ||
| 484 | if (!(sts & DMA_GSTS_IRES)) | ||
| 485 | goto end; | ||
| 486 | |||
| 487 | iommu->gcmd &= ~DMA_GCMD_IRE; | ||
| 488 | writel(iommu->gcmd, iommu->reg + DMAR_GCMD_REG); | ||
| 489 | |||
| 490 | IOMMU_WAIT_OP(iommu, DMAR_GSTS_REG, | ||
| 491 | readl, !(sts & DMA_GSTS_IRES), sts); | ||
| 492 | |||
| 493 | end: | ||
| 494 | spin_unlock_irqrestore(&iommu->register_lock, flags); | ||
| 495 | } | ||
| 496 | |||
| 470 | int __init enable_intr_remapping(int eim) | 497 | int __init enable_intr_remapping(int eim) |
| 471 | { | 498 | { |
| 472 | struct dmar_drhd_unit *drhd; | 499 | struct dmar_drhd_unit *drhd; |
diff --git a/include/linux/intel-iommu.h b/include/linux/intel-iommu.h index a9563840644b..78c1262e8704 100644 --- a/include/linux/intel-iommu.h +++ b/include/linux/intel-iommu.h | |||
| @@ -321,6 +321,7 @@ extern struct dmar_drhd_unit * dmar_find_matched_drhd_unit(struct pci_dev *dev); | |||
| 321 | extern int alloc_iommu(struct dmar_drhd_unit *drhd); | 321 | extern int alloc_iommu(struct dmar_drhd_unit *drhd); |
| 322 | extern void free_iommu(struct intel_iommu *iommu); | 322 | extern void free_iommu(struct intel_iommu *iommu); |
| 323 | extern int dmar_enable_qi(struct intel_iommu *iommu); | 323 | extern int dmar_enable_qi(struct intel_iommu *iommu); |
| 324 | extern void dmar_disable_qi(struct intel_iommu *iommu); | ||
| 324 | extern void qi_global_iec(struct intel_iommu *iommu); | 325 | extern void qi_global_iec(struct intel_iommu *iommu); |
| 325 | 326 | ||
| 326 | extern int qi_flush_context(struct intel_iommu *iommu, u16 did, u16 sid, | 327 | extern int qi_flush_context(struct intel_iommu *iommu, u16 did, u16 sid, |
