[Intel-gfx] [RFC PATCH] agp/intel: Fix cache control for Sandybridge

Zhenyu Wang zhenyuw at linux.intel.com
Thu May 27 04:55:10 CEST 2010


Sandybridge GTT has new cache control bits in PTE, which controls
graphics page cache in LLC or LLC/MLC. This one trys to setup a
new gtt driver for Gen6, and using new type mask function for that.
And this sets cache control to always LLC only by default on Gen6.

As this gtt memory cache control bits are internal to intel hw,
so I don't add new flags in agp_backend.h but add them only in
intel_gtt.c. So drm/i915 stuff needs to know these new flags too.

Signed-off-by: Zhenyu Wang <zhenyuw at linux.intel.com>
---
 drivers/char/agp/intel-agp.c    |    4 +-
 drivers/char/agp/intel-agp.h    |    6 +++
 drivers/char/agp/intel-gtt.c    |   96 +++++++++++++++++++++++++++++++++++---
 drivers/gpu/drm/i915/i915_drv.h |   10 ++++
 4 files changed, 106 insertions(+), 10 deletions(-)

diff --git a/drivers/char/agp/intel-agp.c b/drivers/char/agp/intel-agp.c
index d836a71..5bbc7be 100644
--- a/drivers/char/agp/intel-agp.c
+++ b/drivers/char/agp/intel-agp.c
@@ -816,9 +816,9 @@ static const struct intel_driver_description {
 	{ PCI_DEVICE_ID_INTEL_IRONLAKE_MC2_HB, PCI_DEVICE_ID_INTEL_IRONLAKE_M_IG,
 	    "HD Graphics", NULL, &intel_i965_driver },
 	{ PCI_DEVICE_ID_INTEL_SANDYBRIDGE_HB, PCI_DEVICE_ID_INTEL_SANDYBRIDGE_IG,
-	    "Sandybridge", NULL, &intel_i965_driver },
+	    "Sandybridge", NULL, &intel_gen6_driver },
 	{ PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_HB, PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_IG,
-	    "Sandybridge", NULL, &intel_i965_driver },
+	    "Sandybridge", NULL, &intel_gen6_driver },
 	{ 0, 0, NULL, NULL, NULL }
 };
 
diff --git a/drivers/char/agp/intel-agp.h b/drivers/char/agp/intel-agp.h
index 2547465..c05e3e5 100644
--- a/drivers/char/agp/intel-agp.h
+++ b/drivers/char/agp/intel-agp.h
@@ -60,6 +60,12 @@
 #define I810_PTE_LOCAL		0x00000002
 #define I810_PTE_VALID		0x00000001
 #define I830_PTE_SYSTEM_CACHED  0x00000006
+/* GT PTE cache control fields */
+#define GEN6_PTE_UNCACHED	0x00000002
+#define GEN6_PTE_LLC		0x00000004
+#define GEN6_PTE_LLC_MLC	0x00000006
+#define GEN6_PTE_GFDT		0x00000008
+
 #define I810_SMRAM_MISCC	0x70
 #define I810_GFX_MEM_WIN_SIZE	0x00010000
 #define I810_GFX_MEM_WIN_32M	0x00010000
diff --git a/drivers/char/agp/intel-gtt.c b/drivers/char/agp/intel-gtt.c
index e8ea682..1a255a1 100644
--- a/drivers/char/agp/intel-gtt.c
+++ b/drivers/char/agp/intel-gtt.c
@@ -45,6 +45,33 @@ static struct gatt_mask intel_i810_masks[] =
 	 .type = INTEL_AGP_CACHED_MEMORY}
 };
 
+#define INTEL_AGP_UNCACHED_MEMORY              0
+#define INTEL_AGP_CACHED_MEMORY_LLC            1
+#define INTEL_AGP_CACHED_MEMORY_LLC_GFDT       2
+#define INTEL_AGP_CACHED_MEMORY_LLC_MLC        3
+#define INTEL_AGP_CACHED_MEMORY_LLC_MLC_GFDT   4
+
+/* Don't try to pollute agp_backend.h...
+ * AGP_USER_CACHED_MEMORY default to LLC only */
+#define AGP_USER_CACHED_MEMORY_LLC_MLC (AGP_USER_TYPES + 2)
+#define AGP_USER_UNCACHED_MEMORY (AGP_USER_TYPES + 4)
+/* bit flag for GFDT type */
+#define AGP_USER_CACHED_MEMORY_GFDT (1 << 3)
+
+static struct gatt_mask intel_gen6_masks[] =
+{
+	{.mask = I810_PTE_VALID | GEN6_PTE_UNCACHED,
+	 .type = INTEL_AGP_UNCACHED_MEMORY },
+	{.mask = I810_PTE_VALID | GEN6_PTE_LLC,
+	 .type = INTEL_AGP_CACHED_MEMORY_LLC },
+	{.mask = I810_PTE_VALID | GEN6_PTE_LLC | GEN6_PTE_GFDT,
+	 .type = INTEL_AGP_CACHED_MEMORY_LLC_GFDT },
+	{.mask = I810_PTE_VALID | GEN6_PTE_LLC_MLC,
+	 .type = INTEL_AGP_CACHED_MEMORY_LLC_MLC },
+	{.mask = I810_PTE_VALID | GEN6_PTE_LLC_MLC | GEN6_PTE_GFDT,
+	 .type = INTEL_AGP_CACHED_MEMORY_LLC_MLC_GFDT },
+};
+
 static struct _intel_private {
 	struct pci_dev *pcidev;	/* device one */
 	u8 __iomem *registers;
@@ -171,13 +198,6 @@ static void intel_agp_insert_sg_entries(struct agp_memory *mem,
 					off_t pg_start, int mask_type)
 {
 	int i, j;
-	u32 cache_bits = 0;
-
-	if (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_SANDYBRIDGE_HB ||
-	    agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_HB)
-	{
-		cache_bits = I830_PTE_SYSTEM_CACHED;
-	}
 
 	for (i = 0, j = pg_start; i < mem->page_count; i++, j++) {
 		writel(agp_bridge->driver->mask_memory(agp_bridge,
@@ -310,6 +330,22 @@ static int intel_i830_type_to_mask_type(struct agp_bridge_data *bridge,
 		return 0;
 }
 
+static int intel_gen6_type_to_mask_type(struct agp_bridge_data *bridge,
+					int type)
+{
+	unsigned int type_mask = type & ~AGP_USER_CACHED_MEMORY_GFDT;
+	unsigned int gfdt = type & AGP_USER_CACHED_MEMORY_GFDT;
+
+	if (type_mask == AGP_USER_UNCACHED_MEMORY)
+		return INTEL_AGP_UNCACHED_MEMORY;
+	else if (type_mask == AGP_USER_CACHED_MEMORY_LLC_MLC)
+		return gfdt ? INTEL_AGP_CACHED_MEMORY_LLC_MLC_GFDT :
+			      INTEL_AGP_CACHED_MEMORY_LLC_MLC;
+	else /* set 'normal'/'cached' to LLC by default */
+		return gfdt ? INTEL_AGP_CACHED_MEMORY_LLC_GFDT :
+			      INTEL_AGP_CACHED_MEMORY_LLC;
+}
+
 static int intel_i810_insert_entries(struct agp_memory *mem, off_t pg_start,
 				int type)
 {
@@ -1147,7 +1183,7 @@ static int intel_i915_insert_entries(struct agp_memory *mem, off_t pg_start,
 
 	mask_type = agp_bridge->driver->agp_type_to_mask_type(agp_bridge, type);
 
-	if (mask_type != 0 && mask_type != AGP_PHYS_MEMORY &&
+	if (!IS_SNB && mask_type != 0 && mask_type != AGP_PHYS_MEMORY &&
 	    mask_type != INTEL_AGP_CACHED_MEMORY)
 		goto out_err;
 
@@ -1274,6 +1310,17 @@ static unsigned long intel_i965_mask_memory(struct agp_bridge_data *bridge,
 	return addr | bridge->driver->masks[type].mask;
 }
 
+/* GEN6 support 40-bit physical address, bits 39:32 shift to
+ * bits 11:4. And GEN6 has new memory types.
+ */
+static unsigned long intel_gen6_mask_memory(struct agp_bridge_data *bridge,
+					    dma_addr_t addr, int type)
+{
+	addr |= (addr >> 28) & 0xff;
+
+	return addr | bridge->driver->masks[type].mask;
+}
+
 static void intel_i965_get_gtt_range(int *gtt_offset, int *gtt_size)
 {
 	u16 snb_gmch_ctl;
@@ -1514,3 +1561,36 @@ static const struct agp_bridge_driver intel_g33_driver = {
 	.agp_unmap_memory	= intel_agp_unmap_memory,
 #endif
 };
+
+static const struct agp_bridge_driver intel_gen6_driver = {
+	.owner                  = THIS_MODULE,
+	.aperture_sizes         = intel_i830_sizes,
+	.size_type              = FIXED_APER_SIZE,
+	.num_aperture_sizes     = 4,
+	.needs_scratch_page     = true,
+	.configure              = intel_i915_configure,
+	.fetch_size             = intel_i9xx_fetch_size,
+	.cleanup                = intel_i915_cleanup,
+	.mask_memory            = intel_gen6_mask_memory,
+	.masks                  = intel_gen6_masks,
+	.agp_enable             = intel_i810_agp_enable,
+	.cache_flush            = global_cache_flush,
+	.create_gatt_table      = intel_i965_create_gatt_table,
+	.free_gatt_table        = intel_i830_free_gatt_table,
+	.insert_memory          = intel_i915_insert_entries,
+	.remove_memory          = intel_i915_remove_entries,
+	.alloc_by_type          = intel_i830_alloc_by_type,
+	.free_by_type           = intel_i810_free_by_type,
+	.agp_alloc_page         = agp_generic_alloc_page,
+	.agp_alloc_pages        = agp_generic_alloc_pages,
+	.agp_destroy_page       = agp_generic_destroy_page,
+	.agp_destroy_pages      = agp_generic_destroy_pages,
+	.agp_type_to_mask_type  = intel_gen6_type_to_mask_type,
+	.chipset_flush          = intel_i915_chipset_flush,
+#ifdef USE_PCI_DMA_API
+	.agp_map_page           = intel_agp_map_page,
+	.agp_unmap_page         = intel_agp_unmap_page,
+	.agp_map_memory         = intel_agp_map_memory,
+	.agp_unmap_memory       = intel_agp_unmap_memory,
+#endif
+};
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 7f797ef..9710b4b 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -1170,4 +1170,14 @@ extern int i915_wait_ring(struct drm_device * dev, int n, const char *caller);
 
 #define PRIMARY_RINGBUFFER_SIZE         (128*1024)
 
+/* Intel specific agp_memory type for Gen6,
+ * must be same as in intel_gtt.c */
+
+/* GEN6: memory only cached in LLC. As default we always make
+ * memory cached in LLC. */
+#define AGP_USER_CACHED_MEMORY_LLC_MLC (AGP_USER_TYPES + 2)
+#define AGP_USER_UNCACHED_MEMORY (AGP_USER_TYPES + 4)
+/* GFDT bit flag */
+#define AGP_USER_CACHED_MEMORY_GFDT (1 << 3)
+
 #endif
-- 
1.7.0.4




More information about the Intel-gfx mailing list