mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Wang Zhenyu <zhenyu.z.wang@intel.com>
To: Andi Kleen <ak@suse.de>, Dave Jones <davej@redhat.com>
Cc: David Miller <davem@davemloft.net>,
	hch@infradead.org, ashok.raj@intel.com,
	linux-kernel@vger.kernel.org, akpm@osdl.org, gregkh@suse.de,
	muli@il.ibm.com, asit.k.mallick@intel.com,
	suresh.b.siddha@intel.com, anil.s.keshavamurthy@intel.com,
	arjan@linux.intel.com, shaohua.li@intel.com
Subject: Re: [patch 5/8] [Intel IOMMU] Graphics driver workarounds to provide unity map
Date: Wed, 11 Apr 2007 10:40:21 +0800	[thread overview]
Message-ID: <20070411024021.GA5897@zhen-devel.sh.intel.com> (raw)
In-Reply-To: <200704101112.17869.ak@suse.de>

[-- Attachment #1: Type: text/plain, Size: 1135 bytes --]

On 2007.04.10 11:12:17 +0000, Andi Kleen wrote:
> > > On Mon, Apr 09, 2007 at 02:55:57PM -0700, Ashok Raj wrote:
> > > > Most GFX drivers don't call standard PCI DMA APIs to allocate DMA buffer,
> > > > Such drivers will be broken with IOMMU enabled. To workaround this issue, 
> > > > we added two options.
> > > 
> > > All drm drivers do it.  If the usual out of tree crap vendors are too
> > > stupid for their own sake it's their fault.
> > > 
> > > So NACK to this patch.
> > 
> > That's my feeling as well, everything we care about should be using
> > the proper APIs or else what is the point of them...
> 
> They can't. There is no proper API to do IOMMU mappings from user space.
> And that is how Xorg on x86 works.
> 
> I had some hackish patches to enable mapping on /sys/bus/pci/.../coherent_mem, but
> you need ioctls to pass out the translated address and it wasn't
> exactly pretty. Still also not sure that's the right way.
> 

For agpgart based gfx driver, we need to enable dma mapping on agpgart module, 
which would work in the IOMMU case. I attach my current patches to do this.
Dave, how do you think about it?


[-- Attachment #2: agpgart_dma_mapping.patch --]
[-- Type: text/plain, Size: 5323 bytes --]

diff --git a/drivers/char/agp/agp.h b/drivers/char/agp/agp.h
index 552815d..0d3312d 100644
--- a/drivers/char/agp/agp.h
+++ b/drivers/char/agp/agp.h
@@ -115,6 +115,9 @@ struct agp_bridge_driver {
 	void *(*agp_alloc_page)(struct agp_bridge_data *);
 	void (*agp_destroy_page)(void *);
         int (*agp_type_to_mask_type) (struct agp_bridge_data *, int);
+	int (*agp_map_dma_pages)(struct agp_bridge_data *, struct agp_memory*);
+	void (*agp_unmap_dma_pages)(struct agp_bridge_data *, 
+			struct agp_memory *);
 };
 
 struct agp_bridge_data {
diff --git a/drivers/char/agp/generic.c b/drivers/char/agp/generic.c
index f902d71..03a001a 100644
--- a/drivers/char/agp/generic.c
+++ b/drivers/char/agp/generic.c
@@ -112,22 +112,34 @@ void agp_alloc_page_array(size_t size, s
 	mem->memory = NULL;
 	mem->vmalloc_flag = 0;
 
-	if (size <= 2*PAGE_SIZE)
+	if (size <= 2*PAGE_SIZE) {
 		mem->memory = kmalloc(size, GFP_KERNEL | __GFP_NORETRY);
+		mem->dma_memory = kmalloc(size, GFP_KERNEL | __GFP_NORETRY);
+	}
 	if (mem->memory == NULL) {
 		mem->memory = vmalloc(size);
-		mem->vmalloc_flag = 1;
+		mem->vmalloc_flag = AGP_MEMORY_VMALLOC;
+	}
+	if (mem->dma_memory == NULL) {
+		mem->dma_memory = vmalloc(size);
+		/* XXX this is a little overdo */
+		mem->vmalloc_flag |= AGP_DMA_MEMORY_VMALLOC;
 	}
 }
 EXPORT_SYMBOL(agp_alloc_page_array);
 
 void agp_free_page_array(struct agp_memory *mem)
 {
-	if (mem->vmalloc_flag) {
+	if (mem->vmalloc_flag & AGP_MEMORY_VMALLOC) {
 		vfree(mem->memory);
 	} else {
 		kfree(mem->memory);
 	}
+	if (mem->vmalloc_flag & AGP_DMA_MEMORY_VMALLOC) {
+		vfree(mem->dma_memory);
+	} else {
+		kfree(mem->dma_memory);
+	}
 }
 EXPORT_SYMBOL(agp_free_page_array);
 
@@ -155,6 +167,15 @@ static struct agp_memory *agp_create_use
 		kfree(new);
 		return NULL;
 	}
+	if (new->dma_memory == NULL) {
+		agp_free_key(new->key);
+		if (new->vmalloc_flag)
+			vfree(new->memory);
+		else
+			kfree(new->memory);
+		kfree(new);
+		return NULL;
+	}
 	new->num_scratch_pages = 0;
 	return new;
 }
@@ -181,6 +202,15 @@ struct agp_memory *agp_create_memory(int
 		kfree(new);
 		return NULL;
 	}
+	if (new->dma_memory == NULL) {
+		agp_free_key(new->key);
+		if (new->vmalloc_flag)
+			vfree(new->memory);
+		else
+			kfree(new->memory);
+		kfree(new);
+		return NULL;
+	}
 	new->num_scratch_pages = scratch_pages;
 	new->type = AGP_NORMAL_MEMORY;
 	return new;
@@ -433,6 +463,13 @@ int agp_bind_memory(struct agp_memory *c
 		curr->bridge->driver->cache_flush();
 		curr->is_flushed = TRUE;
 	}
+
+	if (curr->bridge->driver->agp_map_dma_pages) {
+		if (!curr->bridge->driver->agp_map_dma_pages(curr->bridge, curr))
+			return -EINVAL;
+		curr->is_dma_mapped = 1;
+	}
+
 	ret_val = curr->bridge->driver->insert_memory(curr, pg_start, curr->type);
 
 	if (ret_val != 0)
@@ -470,6 +507,10 @@ int agp_unbind_memory(struct agp_memory
 	if (ret_val != 0)
 		return ret_val;
 
+	if (curr->bridge->driver->agp_unmap_dma_pages)
+		curr->bridge->driver->agp_unmap_dma_pages(curr->bridge, curr);
+	curr->is_dma_mapped = 0;
+
 	curr->is_bound = FALSE;
 	curr->pg_start = 0;
 	return 0;
@@ -1094,8 +1135,13 @@ int agp_generic_insert_memory(struct agp
 	}
 
 	for (i = 0, j = pg_start; i < mem->page_count; i++, j++) {
-		writel(bridge->driver->mask_memory(bridge, mem->memory[i], mask_type),
-		       bridge->gatt_table+j);
+		if (mem->is_dma_mapped)
+			writel(bridge->driver->mask_memory(bridge, 
+						mem->dma_memory[i], mask_type),
+					bridge->gatt_table+j);
+		else
+			writel(bridge->driver->mask_memory(bridge, mem->memory[i], mask_type),
+					bridge->gatt_table+j);
 	}
 	readl(bridge->gatt_table+j-1);	/* PCI Posting. */
 
@@ -1356,3 +1406,41 @@ const struct aper_size_info_16 agp3_gene
 };
 EXPORT_SYMBOL(agp3_generic_sizes);
 
+int agp_generic_map_dma_pages(struct agp_bridge_data *bridge, struct agp_memory *mem)
+{
+	struct pci_dev *dev;
+	int i;
+
+	if (!bridge || !mem)
+		return 0;
+	dev = bridge->dev;
+	for (i = 0; i < mem->page_count; i++ ) {
+		mem->dma_memory[i] = pci_map_single(dev, 
+				gart_to_virt(mem->memory[i]), PAGE_SIZE, 
+				PCI_DMA_BIDIRECTIONAL);
+		if (pci_dma_mapping_error(mem->dma_memory[i])) {
+			int j;
+			for (j = 0; j < i; j++) {
+				pci_unmap_single(dev, mem->dma_memory[j],
+						PAGE_SIZE, 
+						PCI_DMA_BIDIRECTIONAL);
+			}
+			return 0;
+		}
+	}
+	return 1;
+}
+
+void agp_generic_unmap_dma_pages(struct agp_bridge_data *bridge, struct agp_memory *mem)
+{
+	struct pci_dev *dev;
+	int i;
+	if (!bridge || !mem)
+		return;
+	dev = bridge->dev;
+	for (i = 0; i < mem->page_count; i++ )
+		pci_unmap_single(dev, mem->dma_memory[i], PAGE_SIZE,
+				PCI_DMA_BIDIRECTIONAL);
+}
+EXPORT_SYMBOL(agp_generic_map_dma_pages);
+EXPORT_SYMBOL(agp_generic_unmap_dma_pages);
diff --git a/include/linux/agp_backend.h b/include/linux/agp_backend.h
index abc521c..abd2ca6 100644
--- a/include/linux/agp_backend.h
+++ b/include/linux/agp_backend.h
@@ -79,6 +79,8 @@ struct agp_memory {
 	struct agp_memory *prev;
 	struct agp_bridge_data *bridge;
 	unsigned long *memory;
+	dma_addr_t *dma_memory;
+	u8 is_dma_mapped;
 	size_t page_count;
 	int key;
 	int num_scratch_pages;
@@ -90,6 +92,9 @@ struct agp_memory {
         u8 vmalloc_flag;
 };
 
+#define AGP_MEMORY_VMALLOC	1
+#define AGP_DMA_MEMORY_VMALLOC  2
+
 #define AGP_NORMAL_MEMORY 0
 
 #define AGP_USER_TYPES (1 << 16)

  reply	other threads:[~2007-04-11  2:42 UTC|newest]

Thread overview: 31+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2007-04-09 21:55 [patch 0/8] [Intel IOMMU] Support for Intel Virtualization Technology for Directed I/O Ashok Raj
2007-04-09 21:55 ` [patch 1/8] [Intel IOMMU] ACPI support " Ashok Raj
2007-04-10  3:39   ` Len Brown
2007-04-10 16:26     ` Ashok Raj
2007-04-09 21:55 ` [patch 2/8] [Intel IOMMU] Some generic search functions required to lookup device relationships Ashok Raj
2007-04-10  3:46   ` Greg KH
2007-04-10  8:11     ` Shaohua Li
2007-04-10 13:03       ` Greg KH
2007-04-11  1:40         ` Shaohua Li
2007-04-11  4:36           ` Greg KH
2007-04-11  6:10         ` Shaohua Li
2007-04-09 21:55 ` [patch 3/8] [Intel IOMMU] Generic hardware support for Intel IOMMU Ashok Raj
2007-04-09 21:55 ` [patch 4/8] [Intel IOMMU] Supporting Zero Length Reads in " Ashok Raj
2007-04-09 21:55 ` [patch 5/8] [Intel IOMMU] Graphics driver workarounds to provide unity map Ashok Raj
2007-04-10  8:33   ` Christoph Hellwig
2007-04-10  9:07     ` David Miller
2007-04-10  9:12       ` Andi Kleen
2007-04-11  2:40         ` Wang Zhenyu [this message]
2007-04-10 16:29       ` Arjan van de Ven
2007-04-09 21:55 ` [patch 6/8] [Intel IOMMU] Doc updates for Intel Virtualization Technology for Directed I/O Ashok Raj
2007-04-09 21:55 ` [patch 7/8] [Intel IOMMU] Support for legacy ISA devices Ashok Raj
2007-04-09 21:56 ` [patch 8/8] [Intel IOMMU] Preserve some Virtual Address when devices cannot address entire range Ashok Raj
2007-04-10  7:49 ` [patch 0/8] [Intel IOMMU] Support for Intel Virtualization Technology for Directed I/O Andi Kleen
2007-04-10  7:57   ` Shaohua Li
2007-04-10  8:09     ` Muli Ben-Yehuda
2007-04-10  8:20       ` Shaohua Li
2007-04-10 16:31   ` Ashok Raj
2007-04-10  8:21 ` Jeff Garzik
2007-04-10  8:27   ` Shaohua Li
2007-04-10  8:34     ` Jeff Garzik
2007-04-10 16:43       ` Ashok Raj

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20070411024021.GA5897@zhen-devel.sh.intel.com \
    --to=zhenyu.z.wang@intel.com \
    --cc=ak@suse.de \
    --cc=akpm@osdl.org \
    --cc=anil.s.keshavamurthy@intel.com \
    --cc=arjan@linux.intel.com \
    --cc=ashok.raj@intel.com \
    --cc=asit.k.mallick@intel.com \
    --cc=davej@redhat.com \
    --cc=davem@davemloft.net \
    --cc=gregkh@suse.de \
    --cc=hch@infradead.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=muli@il.ibm.com \
    --cc=shaohua.li@intel.com \
    --cc=suresh.b.siddha@intel.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

Powered by JetHome