media: v4l2-compat-ioctl32.c: add capabilities field to, v4l2_input32
[pandora-kernel.git] / drivers / iommu / amd_iommu_init.c
index 82d2410..b7d1cdd 100644 (file)
@@ -268,7 +268,7 @@ static void iommu_set_exclusion_range(struct amd_iommu *iommu)
 }
 
 /* Programs the physical address of the device table into the IOMMU hardware */
-static void __init iommu_set_device_table(struct amd_iommu *iommu)
+static void iommu_set_device_table(struct amd_iommu *iommu)
 {
        u64 entry;
 
@@ -915,6 +915,38 @@ static void __init free_iommu_all(void)
        }
 }
 
+/*
+ * Family15h Model 10h-1fh erratum 746 (IOMMU Logging May Stall Translations)
+ * Workaround:
+ *     BIOS should disable L2B micellaneous clock gating by setting
+ *     L2_L2B_CK_GATE_CONTROL[CKGateL2BMiscDisable](D0F2xF4_x90[2]) = 1b
+ */
+static void __init amd_iommu_erratum_746_workaround(struct amd_iommu *iommu)
+{
+       u32 value;
+
+       if ((boot_cpu_data.x86 != 0x15) ||
+           (boot_cpu_data.x86_model < 0x10) ||
+           (boot_cpu_data.x86_model > 0x1f))
+               return;
+
+       pci_write_config_dword(iommu->dev, 0xf0, 0x90);
+       pci_read_config_dword(iommu->dev, 0xf4, &value);
+
+       if (value & BIT(2))
+               return;
+
+       /* Select NB indirect register 0x90 and enable writing */
+       pci_write_config_dword(iommu->dev, 0xf0, 0x90 | (1 << 8));
+
+       pci_write_config_dword(iommu->dev, 0xf4, value | 0x4);
+       pr_info("AMD-Vi: Applying erratum 746 workaround for IOMMU at %s\n",
+               dev_name(&iommu->dev->dev));
+
+       /* Clear the enable writing bit */
+       pci_write_config_dword(iommu->dev, 0xf0, 0x90);
+}
+
 /*
  * This function clues the initialization function for one IOMMU
  * together and also allocates the command buffer and programs the
@@ -943,6 +975,9 @@ static int __init init_iommu_one(struct amd_iommu *iommu, struct ivhd_header *h)
        if (!iommu->dev)
                return 1;
 
+       iommu->root_pdev = pci_get_bus_and_slot(iommu->dev->bus->number,
+                                               PCI_DEVFN(0, 0));
+
        iommu->cap_ptr = h->cap_ptr;
        iommu->pci_seg = h->pci_seg;
        iommu->mmio_phys = h->mmio_phys;
@@ -967,6 +1002,8 @@ static int __init init_iommu_one(struct amd_iommu *iommu, struct ivhd_header *h)
        if (iommu->cap & (1UL << IOMMU_CAP_NPCACHE))
                amd_iommu_np_cache = true;
 
+       amd_iommu_erratum_746_workaround(iommu);
+
        return pci_enable_device(iommu->dev);
 }
 
@@ -1033,8 +1070,9 @@ static int iommu_setup_msi(struct amd_iommu *iommu)
 {
        int r;
 
-       if (pci_enable_msi(iommu->dev))
-               return 1;
+       r = pci_enable_msi(iommu->dev);
+       if (r)
+               return r;
 
        r = request_threaded_irq(iommu->dev->irq,
                                 amd_iommu_int_handler,
@@ -1044,24 +1082,33 @@ static int iommu_setup_msi(struct amd_iommu *iommu)
 
        if (r) {
                pci_disable_msi(iommu->dev);
-               return 1;
+               return r;
        }
 
        iommu->int_enabled = true;
-       iommu_feature_enable(iommu, CONTROL_EVT_INT_EN);
 
        return 0;
 }
 
 static int iommu_init_msi(struct amd_iommu *iommu)
 {
+       int ret;
+
        if (iommu->int_enabled)
-               return 0;
+               goto enable_faults;
 
        if (pci_find_capability(iommu->dev, PCI_CAP_ID_MSI))
-               return iommu_setup_msi(iommu);
+               ret = iommu_setup_msi(iommu);
+       else
+               ret = -ENODEV;
 
-       return 1;
+       if (ret)
+               return ret;
+
+enable_faults:
+       iommu_feature_enable(iommu, CONTROL_EVT_INT_EN);
+
+       return 0;
 }
 
 /****************************************************************************
@@ -1215,20 +1262,16 @@ static void iommu_apply_resume_quirks(struct amd_iommu *iommu)
 {
        int i, j;
        u32 ioc_feature_control;
-       struct pci_dev *pdev = NULL;
+       struct pci_dev *pdev = iommu->root_pdev;
 
        /* RD890 BIOSes may not have completely reconfigured the iommu */
-       if (!is_rd890_iommu(iommu->dev))
+       if (!is_rd890_iommu(iommu->dev) || !pdev)
                return;
 
        /*
         * First, we need to ensure that the iommu is enabled. This is
         * controlled by a register in the northbridge
         */
-       pdev = pci_get_bus_and_slot(iommu->dev->bus->number, PCI_DEVFN(0, 0));
-
-       if (!pdev)
-               return;
 
        /* Select Northbridge indirect register 0x75 and enable writing */
        pci_write_config_dword(pdev, 0x60, 0x75 | (1 << 7));
@@ -1238,8 +1281,6 @@ static void iommu_apply_resume_quirks(struct amd_iommu *iommu)
        if (!(ioc_feature_control & 0x1))
                pci_write_config_dword(pdev, 0x64, ioc_feature_control | 1);
 
-       pci_dev_put(pdev);
-
        /* Restore the iommu BAR */
        pci_write_config_dword(iommu->dev, iommu->cap_ptr + 4,
                               iommu->stored_addr_lo);
@@ -1355,6 +1396,7 @@ static struct syscore_ops amd_iommu_syscore_ops = {
  */
 static int __init amd_iommu_init(void)
 {
+       struct amd_iommu *iommu;
        int i, ret = 0;
 
        /*
@@ -1403,9 +1445,6 @@ static int __init amd_iommu_init(void)
        if (amd_iommu_pd_alloc_bitmap == NULL)
                goto free;
 
-       /* init the device table */
-       init_device_table();
-
        /*
         * let all alias entries point to itself
         */
@@ -1455,12 +1494,20 @@ static int __init amd_iommu_init(void)
        if (ret)
                goto free_disable;
 
+       /* init the device table */
+       init_device_table();
+
+       for_each_iommu(iommu)
+               iommu_flush_all_caches(iommu);
+
        amd_iommu_init_api();
 
        amd_iommu_init_notifier();
 
        register_syscore_ops(&amd_iommu_syscore_ops);
 
+       x86_platform.iommu_shutdown = disable_iommus;
+
        if (iommu_pass_through)
                goto out;
 
@@ -1469,7 +1516,6 @@ static int __init amd_iommu_init(void)
        else
                printk(KERN_INFO "AMD-Vi: Lazy IO/TLB flushing enabled\n");
 
-       x86_platform.iommu_shutdown = disable_iommus;
 out:
        return ret;