Merge branches 'acpi-video', 'device-properties', 'pm-sleep' and 'pm-cpuidle'
[cascardo/linux.git] / drivers / iommu / intel_irq_remapping.c
index 3bcb459..80f1d14 100644 (file)
@@ -581,6 +581,26 @@ error:
        return -ENODEV;
 }
 
+/*
+ * Set Posted-Interrupts capability.
+ */
+static inline void set_irq_posting_cap(void)
+{
+       struct dmar_drhd_unit *drhd;
+       struct intel_iommu *iommu;
+
+       if (!disable_irq_post) {
+               intel_irq_remap_ops.capability |= 1 << IRQ_POSTING_CAP;
+
+               for_each_iommu(iommu, drhd)
+                       if (!cap_pi_support(iommu->cap)) {
+                               intel_irq_remap_ops.capability &=
+                                               ~(1 << IRQ_POSTING_CAP);
+                               break;
+                       }
+       }
+}
+
 static int __init intel_enable_irq_remapping(void)
 {
        struct dmar_drhd_unit *drhd;
@@ -656,6 +676,8 @@ static int __init intel_enable_irq_remapping(void)
 
        irq_remapping_enabled = 1;
 
+       set_irq_posting_cap();
+
        pr_info("Enabled IRQ remapping in %s mode\n", eim ? "x2apic" : "xapic");
 
        return eim ? IRQ_REMAP_X2APIC_MODE : IRQ_REMAP_XAPIC_MODE;
@@ -856,6 +878,12 @@ static void disable_irq_remapping(void)
 
                iommu_disable_irq_remapping(iommu);
        }
+
+       /*
+        * Clear Posted-Interrupts capability.
+        */
+       if (!disable_irq_post)
+               intel_irq_remap_ops.capability &= ~(1 << IRQ_POSTING_CAP);
 }
 
 static int reenable_irq_remapping(int eim)
@@ -883,6 +911,8 @@ static int reenable_irq_remapping(int eim)
        if (!setup)
                goto error;
 
+       set_irq_posting_cap();
+
        return 0;
 
 error:
@@ -1325,6 +1355,9 @@ int dmar_ir_hotplug(struct dmar_drhd_unit *dmaru, bool insert)
                return -EINVAL;
        if (!ecap_ir_support(iommu->ecap))
                return 0;
+       if (irq_remapping_cap(IRQ_POSTING_CAP) &&
+           !cap_pi_support(iommu->cap))
+               return -EBUSY;
 
        if (insert) {
                if (!iommu->ir_table)