x86_irq_Rename_X86_IRQ_ALLOC_TYPE_MSI_to_reflect_PCI_dependency
[linux-2.6-microblaze.git] / drivers / iommu / amd / iommu.c
index ba9f3db..cf26b73 100644 (file)
@@ -2659,7 +2659,12 @@ static int amd_iommu_def_domain_type(struct device *dev)
        if (!dev_data)
                return 0;
 
-       if (dev_data->iommu_v2)
+       /*
+        * Do not identity map IOMMUv2 capable devices when memory encryption is
+        * active, because some of those devices (AMD GPUs) don't have the
+        * encryption bit in their DMA-mask and require remapping.
+        */
+       if (!mem_encrypt_active() && dev_data->iommu_v2)
                return IOMMU_DOMAIN_IDENTITY;
 
        return 0;
@@ -3292,6 +3297,7 @@ out:
 static int modify_irte_ga(u16 devid, int index, struct irte_ga *irte,
                          struct amd_ir_data *data)
 {
+       bool ret;
        struct irq_remap_table *table;
        struct amd_iommu *iommu;
        unsigned long flags;
@@ -3309,10 +3315,18 @@ static int modify_irte_ga(u16 devid, int index, struct irte_ga *irte,
 
        entry = (struct irte_ga *)table->table;
        entry = &entry[index];
-       entry->lo.fields_remap.valid = 0;
-       entry->hi.val = irte->hi.val;
-       entry->lo.val = irte->lo.val;
-       entry->lo.fields_remap.valid = 1;
+
+       ret = cmpxchg_double(&entry->lo.val, &entry->hi.val,
+                            entry->lo.val, entry->hi.val,
+                            irte->lo.val, irte->hi.val);
+       /*
+        * We use cmpxchg16 to atomically update the 128-bit IRTE,
+        * and it cannot be updated by the hardware or other processors
+        * behind us, so the return value of cmpxchg16 should be the
+        * same as the old value.
+        */
+       WARN_ON(!ret);
+
        if (data)
                data->ref = entry;
 
@@ -3514,8 +3528,8 @@ static int get_devid(struct irq_alloc_info *info)
        case X86_IRQ_ALLOC_TYPE_HPET:
                devid     = get_hpet_devid(info->hpet_id);
                break;
-       case X86_IRQ_ALLOC_TYPE_MSI:
-       case X86_IRQ_ALLOC_TYPE_MSIX:
+       case X86_IRQ_ALLOC_TYPE_PCI_MSI:
+       case X86_IRQ_ALLOC_TYPE_PCI_MSIX:
                devid = get_device_id(&info->msi_dev->dev);
                break;
        default:
@@ -3553,8 +3567,8 @@ static struct irq_domain *get_irq_domain(struct irq_alloc_info *info)
                return NULL;
 
        switch (info->type) {
-       case X86_IRQ_ALLOC_TYPE_MSI:
-       case X86_IRQ_ALLOC_TYPE_MSIX:
+       case X86_IRQ_ALLOC_TYPE_PCI_MSI:
+       case X86_IRQ_ALLOC_TYPE_PCI_MSIX:
                devid = get_device_id(&info->msi_dev->dev);
                if (devid < 0)
                        return NULL;
@@ -3615,8 +3629,8 @@ static void irq_remapping_prepare_irte(struct amd_ir_data *data,
                break;
 
        case X86_IRQ_ALLOC_TYPE_HPET:
-       case X86_IRQ_ALLOC_TYPE_MSI:
-       case X86_IRQ_ALLOC_TYPE_MSIX:
+       case X86_IRQ_ALLOC_TYPE_PCI_MSI:
+       case X86_IRQ_ALLOC_TYPE_PCI_MSIX:
                msg->address_hi = MSI_ADDR_BASE_HI;
                msg->address_lo = MSI_ADDR_BASE_LO;
                msg->data = irte_info->index;
@@ -3660,15 +3674,15 @@ static int irq_remapping_alloc(struct irq_domain *domain, unsigned int virq,
 
        if (!info)
                return -EINVAL;
-       if (nr_irqs > 1 && info->type != X86_IRQ_ALLOC_TYPE_MSI &&
-           info->type != X86_IRQ_ALLOC_TYPE_MSIX)
+       if (nr_irqs > 1 && info->type != X86_IRQ_ALLOC_TYPE_PCI_MSI &&
+           info->type != X86_IRQ_ALLOC_TYPE_PCI_MSIX)
                return -EINVAL;
 
        /*
         * With IRQ remapping enabled, don't need contiguous CPU vectors
         * to support multiple MSI interrupts.
         */
-       if (info->type == X86_IRQ_ALLOC_TYPE_MSI)
+       if (info->type == X86_IRQ_ALLOC_TYPE_PCI_MSI)
                info->flags &= ~X86_IRQ_ALLOC_CONTIGUOUS_VECTORS;
 
        devid = get_devid(info);
@@ -3700,9 +3714,9 @@ static int irq_remapping_alloc(struct irq_domain *domain, unsigned int virq,
                } else {
                        index = -ENOMEM;
                }
-       } else if (info->type == X86_IRQ_ALLOC_TYPE_MSI ||
-                  info->type == X86_IRQ_ALLOC_TYPE_MSIX) {
-               bool align = (info->type == X86_IRQ_ALLOC_TYPE_MSI);
+       } else if (info->type == X86_IRQ_ALLOC_TYPE_PCI_MSI ||
+                  info->type == X86_IRQ_ALLOC_TYPE_PCI_MSIX) {
+               bool align = (info->type == X86_IRQ_ALLOC_TYPE_PCI_MSI);
 
                index = alloc_irq_index(devid, nr_irqs, align, info->msi_dev);
        } else {
@@ -3717,8 +3731,8 @@ static int irq_remapping_alloc(struct irq_domain *domain, unsigned int virq,
 
        for (i = 0; i < nr_irqs; i++) {
                irq_data = irq_domain_get_irq_data(domain, virq + i);
-               cfg = irqd_cfg(irq_data);
-               if (!irq_data || !cfg) {
+               cfg = irq_data ? irqd_cfg(irq_data) : NULL;
+               if (!cfg) {
                        ret = -EINVAL;
                        goto out_free_data;
                }
@@ -3850,6 +3864,7 @@ int amd_iommu_deactivate_guest_mode(void *data)
        struct amd_ir_data *ir_data = (struct amd_ir_data *)data;
        struct irte_ga *entry = (struct irte_ga *) ir_data->entry;
        struct irq_cfg *cfg = ir_data->cfg;
+       u64 valid = entry->lo.fields_remap.valid;
 
        if (!AMD_IOMMU_GUEST_IR_VAPIC(amd_iommu_guest_ir) ||
            !entry || !entry->lo.fields_vapic.guest_mode)
@@ -3858,6 +3873,7 @@ int amd_iommu_deactivate_guest_mode(void *data)
        entry->lo.val = 0;
        entry->hi.val = 0;
 
+       entry->lo.fields_remap.valid       = valid;
        entry->lo.fields_remap.dm          = apic->irq_dest_mode;
        entry->lo.fields_remap.int_type    = apic->irq_delivery_mode;
        entry->hi.fields.vector            = cfg->vector;