Merge tag 'mmc-v4.19-2' of git://git.kernel.org/pub/scm/linux/kernel/git/ulfh/mmc
[sfrench/cifs-2.6.git] / drivers / iommu / amd_iommu_init.c
index 904c575d1677ffadfe35c0087edf55849da3f7d2..84b3e4445d46d0a6064437dc57f1ff0ecbdd9f36 100644 (file)
@@ -153,6 +153,7 @@ bool amd_iommu_dump;
 bool amd_iommu_irq_remap __read_mostly;
 
 int amd_iommu_guest_ir = AMD_IOMMU_GUEST_IR_VAPIC;
+static int amd_iommu_xt_mode = IRQ_REMAP_X2APIC_MODE;
 
 static bool amd_iommu_detected;
 static bool __initdata amd_iommu_disabled;
@@ -280,9 +281,9 @@ static void clear_translation_pre_enabled(struct amd_iommu *iommu)
 
 static void init_translation_status(struct amd_iommu *iommu)
 {
-       u32 ctrl;
+       u64 ctrl;
 
-       ctrl = readl(iommu->mmio_base + MMIO_CONTROL_OFFSET);
+       ctrl = readq(iommu->mmio_base + MMIO_CONTROL_OFFSET);
        if (ctrl & (1<<CONTROL_IOMMU_EN))
                iommu->flags |= AMD_IOMMU_FLAG_TRANS_PRE_ENABLED;
 }
@@ -386,30 +387,30 @@ static void iommu_set_device_table(struct amd_iommu *iommu)
 /* Generic functions to enable/disable certain features of the IOMMU. */
 static void iommu_feature_enable(struct amd_iommu *iommu, u8 bit)
 {
-       u32 ctrl;
+       u64 ctrl;
 
-       ctrl = readl(iommu->mmio_base + MMIO_CONTROL_OFFSET);
-       ctrl |= (1 << bit);
-       writel(ctrl, iommu->mmio_base + MMIO_CONTROL_OFFSET);
+       ctrl = readq(iommu->mmio_base +  MMIO_CONTROL_OFFSET);
+       ctrl |= (1ULL << bit);
+       writeq(ctrl, iommu->mmio_base +  MMIO_CONTROL_OFFSET);
 }
 
 static void iommu_feature_disable(struct amd_iommu *iommu, u8 bit)
 {
-       u32 ctrl;
+       u64 ctrl;
 
-       ctrl = readl(iommu->mmio_base + MMIO_CONTROL_OFFSET);
-       ctrl &= ~(1 << bit);
-       writel(ctrl, iommu->mmio_base + MMIO_CONTROL_OFFSET);
+       ctrl = readq(iommu->mmio_base + MMIO_CONTROL_OFFSET);
+       ctrl &= ~(1ULL << bit);
+       writeq(ctrl, iommu->mmio_base + MMIO_CONTROL_OFFSET);
 }
 
 static void iommu_set_inv_tlb_timeout(struct amd_iommu *iommu, int timeout)
 {
-       u32 ctrl;
+       u64 ctrl;
 
-       ctrl = readl(iommu->mmio_base + MMIO_CONTROL_OFFSET);
+       ctrl = readq(iommu->mmio_base + MMIO_CONTROL_OFFSET);
        ctrl &= ~CTRL_INV_TO_MASK;
        ctrl |= (timeout << CONTROL_INV_TIMEOUT) & CTRL_INV_TO_MASK;
-       writel(ctrl, iommu->mmio_base + MMIO_CONTROL_OFFSET);
+       writeq(ctrl, iommu->mmio_base + MMIO_CONTROL_OFFSET);
 }
 
 /* Function to enable the hardware */
@@ -827,6 +828,19 @@ static int iommu_init_ga(struct amd_iommu *iommu)
        return ret;
 }
 
+static void iommu_enable_xt(struct amd_iommu *iommu)
+{
+#ifdef CONFIG_IRQ_REMAP
+       /*
+        * XT mode (32-bit APIC destination ID) requires
+        * GA mode (128-bit IRTE support) as a prerequisite.
+        */
+       if (AMD_IOMMU_GUEST_IR_GA(amd_iommu_guest_ir) &&
+           amd_iommu_xt_mode == IRQ_REMAP_X2APIC_MODE)
+               iommu_feature_enable(iommu, CONTROL_XT_EN);
+#endif /* CONFIG_IRQ_REMAP */
+}
+
 static void iommu_enable_gt(struct amd_iommu *iommu)
 {
        if (!iommu_feature(iommu, FEATURE_GT))
@@ -1507,6 +1521,8 @@ static int __init init_iommu_one(struct amd_iommu *iommu, struct ivhd_header *h)
                        iommu->mmio_phys_end = MMIO_CNTR_CONF_OFFSET;
                if (((h->efr_attr & (0x1 << IOMMU_FEAT_GASUP_SHIFT)) == 0))
                        amd_iommu_guest_ir = AMD_IOMMU_GUEST_IR_LEGACY;
+               if (((h->efr_attr & (0x1 << IOMMU_FEAT_XTSUP_SHIFT)) == 0))
+                       amd_iommu_xt_mode = IRQ_REMAP_XAPIC_MODE;
                break;
        case 0x11:
        case 0x40:
@@ -1516,6 +1532,8 @@ static int __init init_iommu_one(struct amd_iommu *iommu, struct ivhd_header *h)
                        iommu->mmio_phys_end = MMIO_CNTR_CONF_OFFSET;
                if (((h->efr_reg & (0x1 << IOMMU_EFR_GASUP_SHIFT)) == 0))
                        amd_iommu_guest_ir = AMD_IOMMU_GUEST_IR_LEGACY;
+               if (((h->efr_reg & (0x1 << IOMMU_EFR_XTSUP_SHIFT)) == 0))
+                       amd_iommu_xt_mode = IRQ_REMAP_XAPIC_MODE;
                break;
        default:
                return -EINVAL;
@@ -1832,6 +1850,8 @@ static void print_iommu_info(void)
                pr_info("AMD-Vi: Interrupt remapping enabled\n");
                if (AMD_IOMMU_GUEST_IR_VAPIC(amd_iommu_guest_ir))
                        pr_info("AMD-Vi: virtual APIC enabled\n");
+               if (amd_iommu_xt_mode == IRQ_REMAP_X2APIC_MODE)
+                       pr_info("AMD-Vi: X2APIC enabled\n");
        }
 }
 
@@ -2168,6 +2188,7 @@ static void early_enable_iommu(struct amd_iommu *iommu)
        iommu_enable_event_buffer(iommu);
        iommu_set_exclusion_range(iommu);
        iommu_enable_ga(iommu);
+       iommu_enable_xt(iommu);
        iommu_enable(iommu);
        iommu_flush_all_caches(iommu);
 }
@@ -2212,6 +2233,7 @@ static void early_enable_iommus(void)
                        iommu_enable_command_buffer(iommu);
                        iommu_enable_event_buffer(iommu);
                        iommu_enable_ga(iommu);
+                       iommu_enable_xt(iommu);
                        iommu_set_device_table(iommu);
                        iommu_flush_all_caches(iommu);
                }
@@ -2691,8 +2713,7 @@ int __init amd_iommu_enable(void)
                return ret;
 
        irq_remapping_enabled = 1;
-
-       return 0;
+       return amd_iommu_xt_mode;
 }
 
 void amd_iommu_disable(void)
@@ -2721,6 +2742,7 @@ int __init amd_iommu_enable_faulting(void)
  */
 static int __init amd_iommu_init(void)
 {
+       struct amd_iommu *iommu;
        int ret;
 
        ret = iommu_go_to_state(IOMMU_INITIALIZED);
@@ -2730,14 +2752,15 @@ static int __init amd_iommu_init(void)
                        disable_iommus();
                        free_iommu_resources();
                } else {
-                       struct amd_iommu *iommu;
-
                        uninit_device_table_dma();
                        for_each_iommu(iommu)
                                iommu_flush_all_caches(iommu);
                }
        }
 
+       for_each_iommu(iommu)
+               amd_iommu_debugfs_setup(iommu);
+
        return ret;
 }