[Intel-gfx] Failure with swiotlb

Zhenyu Wang zhenyuw at linux.intel.com
Wed Dec 30 04:02:00 CET 2009


We have .31->.32 regression as reported in
http://bugs.freedesktop.org/show_bug.cgi?id=25690
http://bugzilla.kernel.org/show_bug.cgi?id=14627

It's triggered on non VT-d machine (or machine that should have VT-d,
but no way to turn it on in BIOS.) and with large memory, and swiotlb
is used for PCI dma ops. swiotlb uses a bounce buffer to copy between
CPU pages and real pages made for DMA, but we can't make it real coherent
as we don't call pci_dma_sync_single_for_cpu() alike APIs. And in GEM
domain change, we also can't flush pages for bounce buffer. It looks like
our usual non-cache-coherent graphics device can't love swiotlb. 

This patch trys to only handle pci dma mapping in case of real iommu
hardware detected, the only case for that is VT-d. And fallback to origin
method to insert physical page directly in other case. This fixes the
GPU hang on our Q965 with 8G memory in 64-bit OS. Comments?

diff --git a/drivers/char/agp/intel-agp.c b/drivers/char/agp/intel-agp.c
index 30c36ac..0394449 100644
--- a/drivers/char/agp/intel-agp.c
+++ b/drivers/char/agp/intel-agp.c
@@ -16,9 +16,8 @@
  * on the Intel IOMMU support (CONFIG_DMAR).
  * Only newer chipsets need to bother with this, of course.
  */
-#ifdef CONFIG_DMAR
 #define USE_PCI_DMA_API 1
-#endif
+extern int iommu_detected;
 
 #define PCI_DEVICE_ID_INTEL_E7221_HB	0x2588
 #define PCI_DEVICE_ID_INTEL_E7221_IG	0x258a
@@ -191,17 +190,23 @@ static struct _intel_private {
 #ifdef USE_PCI_DMA_API
 static int intel_agp_map_page(struct page *page, dma_addr_t *ret)
 {
-	*ret = pci_map_page(intel_private.pcidev, page, 0,
-			    PAGE_SIZE, PCI_DMA_BIDIRECTIONAL);
-	if (pci_dma_mapping_error(intel_private.pcidev, *ret))
-		return -EINVAL;
+	if (iommu_detected) {
+		*ret = pci_map_page(intel_private.pcidev, page, 0,
+				    PAGE_SIZE, PCI_DMA_BIDIRECTIONAL);
+		if (pci_dma_mapping_error(intel_private.pcidev, *ret))
+			return -EINVAL;
+	} else {
+		*ret = page_to_phys(page);
+	}
 	return 0;
 }
 
 static void intel_agp_unmap_page(struct page *page, dma_addr_t dma)
 {
-	pci_unmap_page(intel_private.pcidev, dma,
-		       PAGE_SIZE, PCI_DMA_BIDIRECTIONAL);
+	if (iommu_detected) {
+		pci_unmap_page(intel_private.pcidev, dma,
+			       PAGE_SIZE, PCI_DMA_BIDIRECTIONAL);
+	}
 }
 
 static void intel_agp_free_sglist(struct agp_memory *mem)
@@ -225,6 +230,9 @@ static int intel_agp_map_memory(struct agp_memory *mem)
 
 	DBG("try mapping %lu pages\n", (unsigned long)mem->page_count);
 
+	if (!iommu_detected)
+		return 0;
+
 	if (sg_alloc_table(&st, mem->page_count, GFP_KERNEL))
 		return -ENOMEM;
 
@@ -246,17 +254,37 @@ static void intel_agp_unmap_memory(struct agp_memory *mem)
 {
 	DBG("try unmapping %lu pages\n", (unsigned long)mem->page_count);
 
+	if (!iommu_detected)
+		return;
+
 	pci_unmap_sg(intel_private.pcidev, mem->sg_list,
 		     mem->page_count, PCI_DMA_BIDIRECTIONAL);
 	intel_agp_free_sglist(mem);
 }
 
+static void intel_agp_insert_memory(struct agp_memory *mem,
+					off_t pg_start, int mask_type)
+{
+	int i, j;
+
+	for (i = 0, j = pg_start; i < mem->page_count; i++, j++) {
+		writel(agp_bridge->driver->mask_memory(agp_bridge,
+				page_to_phys(mem->pages[i]), mask_type),
+		       intel_private.gtt+j);
+	}
+
+	readl(intel_private.gtt+j-1);
+}
+
 static void intel_agp_insert_sg_entries(struct agp_memory *mem,
 					off_t pg_start, int mask_type)
 {
 	struct scatterlist *sg;
 	int i, j;
 
+	if (!iommu_detected)
+		return intel_agp_insert_memory(mem, pg_start, mask_type);
+
 	j = pg_start;
 
 	WARN_ON(!mem->num_sg);
@@ -287,22 +315,6 @@ static void intel_agp_insert_sg_entries(struct agp_memory *mem,
 	readl(intel_private.gtt+j-1);
 }
 
-#else
-
-static void intel_agp_insert_sg_entries(struct agp_memory *mem,
-					off_t pg_start, int mask_type)
-{
-	int i, j;
-
-	for (i = 0, j = pg_start; i < mem->page_count; i++, j++) {
-		writel(agp_bridge->driver->mask_memory(agp_bridge,
-				page_to_phys(mem->pages[i]), mask_type),
-		       intel_private.gtt+j);
-	}
-
-	readl(intel_private.gtt+j-1);
-}
-
 #endif
 
 static int intel_i810_fetch_size(void)

-- 
Open Source Technology Center, Intel ltd.

$gpg --keyserver wwwkeys.pgp.net --recv-keys 4D781827
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 198 bytes
Desc: Digital signature
URL: <http://lists.freedesktop.org/archives/intel-gfx/attachments/20091230/c199a28c/attachment.sig>


More information about the Intel-gfx mailing list