From 25cbff1660d3f4c059a178a1e5b851be6d70c5e8 Mon Sep 17 00:00:00 2001 From: Sheng Yang Date: Sat, 12 Jun 2010 19:21:42 +0800 Subject: intel-iommu: Fix reference by physical address in intel_iommu_attach_device() Commit a99c47a2 "intel-iommu: errors with smaller iommu widths" replace the dmar_domain->pgd with the first entry of page table when iommu's supported width is smaller than dmar_domain's. But it use physical address directly for new dmar_domain->pgd... This result in KVM oops with VT-d on some machines. Reported-by: Allen Kay Cc: Tom Lyon Signed-off-by: Sheng Yang Signed-off-by: David Woodhouse --- drivers/pci/intel-iommu.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/pci') diff --git a/drivers/pci/intel-iommu.c b/drivers/pci/intel-iommu.c index 796828fce34..3bd30557ce2 100644 --- a/drivers/pci/intel-iommu.c +++ b/drivers/pci/intel-iommu.c @@ -3603,7 +3603,8 @@ static int intel_iommu_attach_device(struct iommu_domain *domain, pte = dmar_domain->pgd; if (dma_pte_present(pte)) { free_pgtable_page(dmar_domain->pgd); - dmar_domain->pgd = (struct dma_pte *)dma_pte_addr(pte); + dmar_domain->pgd = (struct dma_pte *) + phys_to_virt(dma_pte_addr(pte)); } dmar_domain->agaw--; } -- cgit v1.2.3-70-g09d2 From 00dfff77e7184140dc45724c7232e99302f6bf97 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Mon, 14 Jun 2010 17:17:32 +0200 Subject: intel-iommu: Fix double lock in get_domain_for_dev() stanse found the following double lock. In get_domain_for_dev: spin_lock_irqsave(&device_domain_lock, flags); domain_exit(domain); domain_remove_dev_info(domain); spin_lock_irqsave(&device_domain_lock, flags); spin_unlock_irqrestore(&device_domain_lock, flags); spin_unlock_irqrestore(&device_domain_lock, flags); This happens when the domain is created by another CPU at the same time as this function is creating one, and the other CPU wins the race to attach it to the device in question, so we have to destroy our own newly-created one. Signed-off-by: David Woodhouse --- drivers/pci/intel-iommu.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/pci') diff --git a/drivers/pci/intel-iommu.c b/drivers/pci/intel-iommu.c index 3bd30557ce2..bf8fd913d06 100644 --- a/drivers/pci/intel-iommu.c +++ b/drivers/pci/intel-iommu.c @@ -1874,14 +1874,15 @@ static struct dmar_domain *get_domain_for_dev(struct pci_dev *pdev, int gaw) } } if (found) { + spin_unlock_irqrestore(&device_domain_lock, flags); free_devinfo_mem(info); domain_exit(domain); domain = found; } else { list_add(&info->link, &domain->devices); list_add(&info->global, &device_domain_list); + spin_unlock_irqrestore(&device_domain_lock, flags); } - spin_unlock_irqrestore(&device_domain_lock, flags); } found_domain: -- cgit v1.2.3-70-g09d2 From 2d9e667efdfb4e986074d98e7d9a424003c7c43b Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Tue, 15 Jun 2010 10:57:57 +0100 Subject: intel-iommu: Force-disable IOMMU for iGFX on broken Cantiga revisions. Certain revisions of this chipset appear to be broken. There is a shadow GTT which mirrors the real GTT but contains pre-translated physical addresses, for performance reasons. When a GTT update happens, the translations are done once and the resulting physical addresses written back to the shadow GTT. Except sometimes, the physical address is actually written back to the _real_ GTT, not the shadow GTT. Thus we start to see faults when that physical address is fed through translation again. Signed-off-by: David Woodhouse --- drivers/pci/intel-iommu.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'drivers/pci') diff --git a/drivers/pci/intel-iommu.c b/drivers/pci/intel-iommu.c index bf8fd913d06..c9171be7456 100644 --- a/drivers/pci/intel-iommu.c +++ b/drivers/pci/intel-iommu.c @@ -340,7 +340,7 @@ int dmar_disabled = 0; int dmar_disabled = 1; #endif /*CONFIG_DMAR_DEFAULT_ON*/ -static int __initdata dmar_map_gfx = 1; +static int dmar_map_gfx = 1; static int dmar_forcedac; static int intel_iommu_strict; @@ -3721,6 +3721,12 @@ static void __devinit quirk_iommu_rwbf(struct pci_dev *dev) */ printk(KERN_INFO "DMAR: Forcing write-buffer flush capability\n"); rwbf_quirk = 1; + + /* https://bugzilla.redhat.com/show_bug.cgi?id=538163 */ + if (dev->revision == 0x07) { + printk(KERN_INFO "DMAR: Disabling IOMMU for graphics on this chipset\n"); + dmar_map_gfx = 0; + } } DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2a40, quirk_iommu_rwbf); -- cgit v1.2.3-70-g09d2 From b27759f880018b0cd43543dc94c921341b64b5ec Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Fri, 18 Jun 2010 17:04:22 +0200 Subject: PCI/PM: Do not use native PCIe PME by default MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Commit c7f486567c1d0acd2e4166c47069835b9f75e77b (PCI PM: PCIe PME root port service driver) causes the native PCIe PME signaling to be used by default, if the BIOS allows the kernel to control the standard configuration registers of PCIe root ports. However, the native PCIe PME is coupled to the native PCIe hotplug and calling pcie_pme_acpi_setup() makes some BIOSes expect that the native PCIe hotplug will be used as well. That, in turn, causes problems to appear on systems where the PCIe hotplug driver is not loaded. The usual symptom, as reported by Jaroslav KamenĂ­k and others, is that the ACPI GPE associated with PCIe hotplug keeps firing continuously causing kacpid to take substantial percentage of CPU time. To work around this issue, change the default so that the native PCIe PME signaling is only used if directly requested with the help of the pcie_pme= command line switch. Fixes https://bugzilla.kernel.org/show_bug.cgi?id=15924 , which is a listed regression from 2.6.33. Signed-off-by: Rafael J. Wysocki Reported-by: Jaroslav KamenĂ­k Tested-by: Antoni Grzymala Signed-off-by: Jesse Barnes --- Documentation/kernel-parameters.txt | 4 +++- drivers/pci/pcie/pme/pcie_pme.c | 19 +++++++++++++------ 2 files changed, 16 insertions(+), 7 deletions(-) (limited to 'drivers/pci') diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index 1808f1157f3..82d6aeb5228 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt @@ -2048,7 +2048,9 @@ and is between 256 and 4096 characters. It is defined in the file WARNING: Forcing ASPM on may cause system lockups. pcie_pme= [PCIE,PM] Native PCIe PME signaling options: - off Do not use native PCIe PME signaling. + Format: {auto|force}[,nomsi] + auto Use native PCIe PME signaling if the BIOS allows the + kernel to control PCIe config registers of root ports. force Use native PCIe PME signaling even if the BIOS refuses to allow the kernel to control the relevant PCIe config registers. diff --git a/drivers/pci/pcie/pme/pcie_pme.c b/drivers/pci/pcie/pme/pcie_pme.c index aac285a16b6..d672a0a6381 100644 --- a/drivers/pci/pcie/pme/pcie_pme.c +++ b/drivers/pci/pcie/pme/pcie_pme.c @@ -34,7 +34,7 @@ * being registered. Consequently, the interrupt-based PCIe PME signaling will * not be used by any PCIe root ports in that case. */ -static bool pcie_pme_disabled; +static bool pcie_pme_disabled = true; /* * The PCI Express Base Specification 2.0, Section 6.1.8, states the following: @@ -64,12 +64,19 @@ bool pcie_pme_msi_disabled; static int __init pcie_pme_setup(char *str) { - if (!strcmp(str, "off")) - pcie_pme_disabled = true; - else if (!strcmp(str, "force")) + if (!strncmp(str, "auto", 4)) + pcie_pme_disabled = false; + else if (!strncmp(str, "force", 5)) pcie_pme_force_enable = true; - else if (!strcmp(str, "nomsi")) - pcie_pme_msi_disabled = true; + + str = strchr(str, ','); + if (str) { + str++; + str += strspn(str, " \t"); + if (*str && !strcmp(str, "nomsi")) + pcie_pme_msi_disabled = true; + } + return 1; } __setup("pcie_pme=", pcie_pme_setup); -- cgit v1.2.3-70-g09d2 From b03214d559471359e2a85ae256686381d0672f29 Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Wed, 23 Jun 2010 22:49:06 -0600 Subject: virtio-pci: disable msi at startup virtio-pci resets the device at startup by writing to the status register, but this does not clear the pci config space, specifically msi enable status which affects register layout. This breaks things like kdump when they try to use e.g. virtio-blk. Fix by forcing msi off at startup. Since pci.c already has a routine to do this, we export and use it instead of duplicating code. Signed-off-by: Michael S. Tsirkin Tested-by: Vivek Goyal Acked-by: Jesse Barnes Cc: linux-pci@vger.kernel.org Signed-off-by: Rusty Russell Cc: stable@kernel.org --- drivers/pci/pci.c | 1 + drivers/virtio/virtio_pci.c | 3 +++ 2 files changed, 4 insertions(+) (limited to 'drivers/pci') diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 60f30e7f1c8..740fb4ea966 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -2292,6 +2292,7 @@ void pci_msi_off(struct pci_dev *dev) pci_write_config_word(dev, pos + PCI_MSIX_FLAGS, control); } } +EXPORT_SYMBOL_GPL(pci_msi_off); #ifndef HAVE_ARCH_PCI_SET_DMA_MAX_SEGMENT_SIZE int pci_set_dma_max_seg_size(struct pci_dev *dev, unsigned int size) diff --git a/drivers/virtio/virtio_pci.c b/drivers/virtio/virtio_pci.c index 95896f38792..ef8d9d558fc 100644 --- a/drivers/virtio/virtio_pci.c +++ b/drivers/virtio/virtio_pci.c @@ -636,6 +636,9 @@ static int __devinit virtio_pci_probe(struct pci_dev *pci_dev, INIT_LIST_HEAD(&vp_dev->virtqueues); spin_lock_init(&vp_dev->lock); + /* Disable MSI/MSIX to bring device to a known good state. */ + pci_msi_off(pci_dev); + /* enable the device */ err = pci_enable_device(pci_dev); if (err) -- cgit v1.2.3-70-g09d2