[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