[RFC][PATCH 3/4][AGP] intel_agp: add support for graphics dma remapping on G33

2007-12-17 Thread Zhenyu Wang

[PATCH] [AGP] intel_agp: add support for graphics dma remapping on G33

When graphics dma remapping engine is active, we must fill
gart table with dma address from dmar engine, as now graphics
device access to graphics memory must go through dma remapping
table to get real physical address.

Add support on G33 chipset, which has graphics device specific
dmar engine avaiable.

Signed-off-by: Zhenyu Wang <[EMAIL PROTECTED]>
---
 drivers/char/agp/Kconfig |   12 +++-
 drivers/char/agp/intel-agp.c |  134 +-
 2 files changed, 141 insertions(+), 5 deletions(-)

diff --git a/drivers/char/agp/Kconfig b/drivers/char/agp/Kconfig
index ccb1fa8..e60c2b0 100644
--- a/drivers/char/agp/Kconfig
+++ b/drivers/char/agp/Kconfig
@@ -74,8 +74,16 @@ config AGP_INTEL
  on Intel 440LX/BX/GX, 815, 820, 830, 840, 845, 850, 860, 875,
  E7205 and E7505 chipsets and full support for the 810, 815, 830M,
  845G, 852GM, 855GM, 865G and I915 integrated graphics chipsets.
-
-
+   
+config AGP_INTEL_DMAR
+   bool
+   depends on AGP_INTEL && DMAR && !DMAR_GFX_WA
+   default y
+   help
+ This option will enable graphics address remapping with Intel
+ DMAR engine aka VT-d if you don't select graphics workaround on
+ Intel DMAR. The graphics address filled to gart table will be
+ changed by remapping within graphics DMAR engine for domain.
 
 config AGP_NVIDIA
tristate "NVIDIA nForce/nForce2 chipset support"
diff --git a/drivers/char/agp/intel-agp.c b/drivers/char/agp/intel-agp.c
index d879619..7424667 100644
--- a/drivers/char/agp/intel-agp.c
+++ b/drivers/char/agp/intel-agp.c
@@ -9,6 +9,9 @@
 #include 
 #include 
 #include "agp.h"
+#ifdef CONFIG_AGP_INTEL_DMAR
+#include 
+#endif
 
 #define PCI_DEVICE_ID_INTEL_82946GZ_HB  0x2970
 #define PCI_DEVICE_ID_INTEL_82946GZ_IG  0x2972
@@ -115,6 +118,97 @@ static struct _intel_private {
int gtt_entries;/* i830+ */
 } intel_private;
 
+static int intel_agp_require_remapping(void)
+{
+#ifdef CONFIG_AGP_INTEL_DMAR
+   return intel_iommu_gfx_remapping();
+#else
+   return 0;
+#endif
+}
+
+#ifdef CONFIG_AGP_INTEL_DMAR
+static int intel_agp_map_pages(struct agp_memory *mem, void *virt, dma_addr_t 
*ret, int is_single)
+{
+   int i;
+   struct scatterlist *sg;
+
+   if (is_single) {
+   *ret = pci_map_single(intel_private.pcidev, virt, PAGE_SIZE,
+   PCI_DMA_BIDIRECTIONAL);
+   if (pci_dma_mapping_error(*ret))
+   return -EINVAL;
+   return 0;
+   }
+
+   DBG("try mapping %lu pages\n", (unsigned long)mem->page_count);
+
+   if ((mem->page_count * sizeof(*mem->sg_list)) < 2*PAGE_SIZE)
+   mem->sg_list = kcalloc(mem->page_count, sizeof(*mem->sg_list), 
GFP_KERNEL);
+
+   if (mem->sg_list == NULL) {
+   mem->sg_list = vmalloc(mem->page_count * sizeof(*mem->sg_list));
+   mem->sg_vmalloc_flag = 1;
+   }
+
+   if (!mem->sg_list) {
+   mem->sg_vmalloc_flag = 0;
+   return -ENOMEM;
+   }
+   sg_init_table(mem->sg_list, mem->page_count);
+
+   sg = mem->sg_list;
+   for (i = 0 ; i < mem->page_count; i++, sg = sg_next(sg))
+   sg_set_buf(sg, gart_to_virt(mem->memory[i]), PAGE_SIZE);
+
+   mem->num_sg = pci_map_sg(intel_private.pcidev, mem->sg_list,
+   mem->page_count, PCI_DMA_BIDIRECTIONAL);
+   if (mem->num_sg == 0) {
+   if (mem->sg_vmalloc_flag)
+   vfree(mem->sg_list);
+   else
+   kfree(mem->sg_list);
+   mem->sg_list = NULL;
+   mem->sg_vmalloc_flag = 0;
+   return -ENOMEM;
+   }
+   mem->is_mapped = TRUE;
+   return 0;
+}
+
+static void intel_agp_unmap_pages(struct agp_memory *mem, dma_addr_t addr, int 
is_single)
+{
+   if (is_single) {
+   pci_unmap_single(intel_private.pcidev, addr, PAGE_SIZE,
+   PCI_DMA_BIDIRECTIONAL);
+   return;
+   }
+   DBG("try unmapping %lu pages\n", (unsigned long)mem->page_count);
+
+   if (!mem->is_mapped)
+   return;
+
+   if (mem->num_sg)
+   pci_unmap_sg(intel_private.pcidev, mem->sg_list, 
mem->page_count,
+   PCI_DMA_BIDIRECTIONAL);
+   if (mem->sg_vmalloc_flag)
+   vfree(mem->sg_list);
+   else
+   kfree(mem->sg_list);
+   mem->sg_vmalloc_flag = 0;
+   mem->sg_list = NULL;
+   mem->num_sg = 0;
+}
+#else
+static int intel_agp_map_pages(struct agp_memory *mem, void *virt, dma_addr_t 
*ret, int is_single)
+{
+return 0;
+}
+static void intel_agp_unmap_pages(struct agp_memory *mem, dma_addr_t addr, int 
is_single)
+{
+}
+#endif
+
 static int intel_i810_fetch_size(void)
 {
u32 smram_miscc;
@@ 

[RFC][PATCH 3/4][AGP] intel_agp: add support for graphics dma remapping on G33

2007-12-17 Thread Zhenyu Wang

[PATCH] [AGP] intel_agp: add support for graphics dma remapping on G33

When graphics dma remapping engine is active, we must fill
gart table with dma address from dmar engine, as now graphics
device access to graphics memory must go through dma remapping
table to get real physical address.

Add support on G33 chipset, which has graphics device specific
dmar engine avaiable.

Signed-off-by: Zhenyu Wang [EMAIL PROTECTED]
---
 drivers/char/agp/Kconfig |   12 +++-
 drivers/char/agp/intel-agp.c |  134 +-
 2 files changed, 141 insertions(+), 5 deletions(-)

diff --git a/drivers/char/agp/Kconfig b/drivers/char/agp/Kconfig
index ccb1fa8..e60c2b0 100644
--- a/drivers/char/agp/Kconfig
+++ b/drivers/char/agp/Kconfig
@@ -74,8 +74,16 @@ config AGP_INTEL
  on Intel 440LX/BX/GX, 815, 820, 830, 840, 845, 850, 860, 875,
  E7205 and E7505 chipsets and full support for the 810, 815, 830M,
  845G, 852GM, 855GM, 865G and I915 integrated graphics chipsets.
-
-
+   
+config AGP_INTEL_DMAR
+   bool
+   depends on AGP_INTEL  DMAR  !DMAR_GFX_WA
+   default y
+   help
+ This option will enable graphics address remapping with Intel
+ DMAR engine aka VT-d if you don't select graphics workaround on
+ Intel DMAR. The graphics address filled to gart table will be
+ changed by remapping within graphics DMAR engine for domain.
 
 config AGP_NVIDIA
tristate NVIDIA nForce/nForce2 chipset support
diff --git a/drivers/char/agp/intel-agp.c b/drivers/char/agp/intel-agp.c
index d879619..7424667 100644
--- a/drivers/char/agp/intel-agp.c
+++ b/drivers/char/agp/intel-agp.c
@@ -9,6 +9,9 @@
 #include linux/pagemap.h
 #include linux/agp_backend.h
 #include agp.h
+#ifdef CONFIG_AGP_INTEL_DMAR
+#include linux/dmar.h
+#endif
 
 #define PCI_DEVICE_ID_INTEL_82946GZ_HB  0x2970
 #define PCI_DEVICE_ID_INTEL_82946GZ_IG  0x2972
@@ -115,6 +118,97 @@ static struct _intel_private {
int gtt_entries;/* i830+ */
 } intel_private;
 
+static int intel_agp_require_remapping(void)
+{
+#ifdef CONFIG_AGP_INTEL_DMAR
+   return intel_iommu_gfx_remapping();
+#else
+   return 0;
+#endif
+}
+
+#ifdef CONFIG_AGP_INTEL_DMAR
+static int intel_agp_map_pages(struct agp_memory *mem, void *virt, dma_addr_t 
*ret, int is_single)
+{
+   int i;
+   struct scatterlist *sg;
+
+   if (is_single) {
+   *ret = pci_map_single(intel_private.pcidev, virt, PAGE_SIZE,
+   PCI_DMA_BIDIRECTIONAL);
+   if (pci_dma_mapping_error(*ret))
+   return -EINVAL;
+   return 0;
+   }
+
+   DBG(try mapping %lu pages\n, (unsigned long)mem-page_count);
+
+   if ((mem-page_count * sizeof(*mem-sg_list))  2*PAGE_SIZE)
+   mem-sg_list = kcalloc(mem-page_count, sizeof(*mem-sg_list), 
GFP_KERNEL);
+
+   if (mem-sg_list == NULL) {
+   mem-sg_list = vmalloc(mem-page_count * sizeof(*mem-sg_list));
+   mem-sg_vmalloc_flag = 1;
+   }
+
+   if (!mem-sg_list) {
+   mem-sg_vmalloc_flag = 0;
+   return -ENOMEM;
+   }
+   sg_init_table(mem-sg_list, mem-page_count);
+
+   sg = mem-sg_list;
+   for (i = 0 ; i  mem-page_count; i++, sg = sg_next(sg))
+   sg_set_buf(sg, gart_to_virt(mem-memory[i]), PAGE_SIZE);
+
+   mem-num_sg = pci_map_sg(intel_private.pcidev, mem-sg_list,
+   mem-page_count, PCI_DMA_BIDIRECTIONAL);
+   if (mem-num_sg == 0) {
+   if (mem-sg_vmalloc_flag)
+   vfree(mem-sg_list);
+   else
+   kfree(mem-sg_list);
+   mem-sg_list = NULL;
+   mem-sg_vmalloc_flag = 0;
+   return -ENOMEM;
+   }
+   mem-is_mapped = TRUE;
+   return 0;
+}
+
+static void intel_agp_unmap_pages(struct agp_memory *mem, dma_addr_t addr, int 
is_single)
+{
+   if (is_single) {
+   pci_unmap_single(intel_private.pcidev, addr, PAGE_SIZE,
+   PCI_DMA_BIDIRECTIONAL);
+   return;
+   }
+   DBG(try unmapping %lu pages\n, (unsigned long)mem-page_count);
+
+   if (!mem-is_mapped)
+   return;
+
+   if (mem-num_sg)
+   pci_unmap_sg(intel_private.pcidev, mem-sg_list, 
mem-page_count,
+   PCI_DMA_BIDIRECTIONAL);
+   if (mem-sg_vmalloc_flag)
+   vfree(mem-sg_list);
+   else
+   kfree(mem-sg_list);
+   mem-sg_vmalloc_flag = 0;
+   mem-sg_list = NULL;
+   mem-num_sg = 0;
+}
+#else
+static int intel_agp_map_pages(struct agp_memory *mem, void *virt, dma_addr_t 
*ret, int is_single)
+{
+return 0;
+}
+static void intel_agp_unmap_pages(struct agp_memory *mem, dma_addr_t addr, int 
is_single)
+{
+}
+#endif
+
 static int intel_i810_fetch_size(void)
 {
u32 smram_miscc;
@@ -847,9