]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - drivers/pci/dmar.c
Merge branch 'omap-pool'
[linux-2.6-omap-h63xx.git] / drivers / pci / dmar.c
index d313039e2fdf8179dbc3324e7778b7e2e6bed964..25a00ce4f24d3f3a897c159f48d0b931200add54 100644 (file)
@@ -180,6 +180,7 @@ dmar_parse_one_drhd(struct acpi_dmar_header *header)
        dmaru->hdr = header;
        drhd = (struct acpi_dmar_hardware_unit *)header;
        dmaru->reg_base_addr = drhd->address;
+       dmaru->segment = drhd->segment;
        dmaru->include_all = drhd->flags & 0x1; /* BIT0: INCLUDE_ALL */
 
        ret = alloc_iommu(dmaru);
@@ -789,6 +790,35 @@ end:
        spin_unlock_irqrestore(&iommu->register_lock, flags);
 }
 
+/*
+ * Enable queued invalidation.
+ */
+static void __dmar_enable_qi(struct intel_iommu *iommu)
+{
+       u32 cmd, sts;
+       unsigned long flags;
+       struct q_inval *qi = iommu->qi;
+
+       qi->free_head = qi->free_tail = 0;
+       qi->free_cnt = QI_LENGTH;
+
+       spin_lock_irqsave(&iommu->register_lock, flags);
+
+       /* write zero to the tail reg */
+       writel(0, iommu->reg + DMAR_IQT_REG);
+
+       dmar_writeq(iommu->reg + DMAR_IQA_REG, virt_to_phys(qi->desc));
+
+       cmd = iommu->gcmd | DMA_GCMD_QIE;
+       iommu->gcmd |= DMA_GCMD_QIE;
+       writel(cmd, iommu->reg + DMAR_GCMD_REG);
+
+       /* Make sure hardware complete it */
+       IOMMU_WAIT_OP(iommu, DMAR_GSTS_REG, readl, (sts & DMA_GSTS_QIES), sts);
+
+       spin_unlock_irqrestore(&iommu->register_lock, flags);
+}
+
 /*
  * Enable Queued Invalidation interface. This is a must to support
  * interrupt-remapping. Also used by DMA-remapping, which replaces
@@ -796,8 +826,6 @@ end:
  */
 int dmar_enable_qi(struct intel_iommu *iommu)
 {
-       u32 cmd, sts;
-       unsigned long flags;
        struct q_inval *qi;
 
        if (!ecap_qis(iommu->ecap))
@@ -835,19 +863,7 @@ int dmar_enable_qi(struct intel_iommu *iommu)
 
        spin_lock_init(&qi->q_lock);
 
-       spin_lock_irqsave(&iommu->register_lock, flags);
-       /* write zero to the tail reg */
-       writel(0, iommu->reg + DMAR_IQT_REG);
-
-       dmar_writeq(iommu->reg + DMAR_IQA_REG, virt_to_phys(qi->desc));
-
-       cmd = iommu->gcmd | DMA_GCMD_QIE;
-       iommu->gcmd |= DMA_GCMD_QIE;
-       writel(cmd, iommu->reg + DMAR_GCMD_REG);
-
-       /* Make sure hardware complete it */
-       IOMMU_WAIT_OP(iommu, DMAR_GSTS_REG, readl, (sts & DMA_GSTS_QIES), sts);
-       spin_unlock_irqrestore(&iommu->register_lock, flags);
+       __dmar_enable_qi(iommu);
 
        return 0;
 }
@@ -1102,3 +1118,28 @@ int __init enable_drhd_fault_handling(void)
 
        return 0;
 }
+
+/*
+ * Re-enable Queued Invalidation interface.
+ */
+int dmar_reenable_qi(struct intel_iommu *iommu)
+{
+       if (!ecap_qis(iommu->ecap))
+               return -ENOENT;
+
+       if (!iommu->qi)
+               return -ENOENT;
+
+       /*
+        * First disable queued invalidation.
+        */
+       dmar_disable_qi(iommu);
+       /*
+        * Then enable queued invalidation again. Since there is no pending
+        * invalidation requests now, it's safe to re-enable queued
+        * invalidation.
+        */
+       __dmar_enable_qi(iommu);
+
+       return 0;
+}