[Intel-gfx] [PATCH 3/3] drm/i915: Lookup stolen region reserved during early PCI quirk processing

Chris Wilson chris at chris-wilson.co.uk
Fri Jul 26 00:27:17 CEST 2013


As we now hook into the early PCI quirk table to earmark the Intel
Graphics Stolen region (inserting it into the iomem_resource) to prevent
it conflicting with any later resource allocations, we can simply walk
the iomem_resource tree and find it for our use. Thereby removing all of
our own code to define the stolen region.

Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>
---
 drivers/char/agp/intel-gtt.c           | 93 +++-------------------------------
 drivers/gpu/drm/i915/i915_drv.h        |  3 +-
 drivers/gpu/drm/i915/i915_gem_gtt.c    | 15 +-----
 drivers/gpu/drm/i915/i915_gem_stolen.c | 70 +++++--------------------
 include/drm/intel-gtt.h                |  2 +-
 5 files changed, 26 insertions(+), 157 deletions(-)

diff --git a/drivers/char/agp/intel-gtt.c b/drivers/char/agp/intel-gtt.c
index b8e2014..586efed 100644
--- a/drivers/char/agp/intel-gtt.c
+++ b/drivers/char/agp/intel-gtt.c
@@ -343,90 +343,14 @@ static const struct aper_size_info_fixed intel_fake_agp_sizes[] = {
 
 static unsigned int intel_gtt_stolen_size(void)
 {
-	u16 gmch_ctrl;
-	u8 rdct;
-	int local = 0;
-	static const int ddt[4] = { 0, 16, 32, 64 };
-	unsigned int stolen_size = 0;
-
-	if (INTEL_GTT_GEN == 1)
-		return 0; /* no stolen mem on i81x */
-
-	pci_read_config_word(intel_private.bridge_dev,
-			     I830_GMCH_CTRL, &gmch_ctrl);
-
-	if (intel_private.bridge_dev->device == PCI_DEVICE_ID_INTEL_82830_HB ||
-	    intel_private.bridge_dev->device == PCI_DEVICE_ID_INTEL_82845G_HB) {
-		switch (gmch_ctrl & I830_GMCH_GMS_MASK) {
-		case I830_GMCH_GMS_STOLEN_512:
-			stolen_size = KB(512);
-			break;
-		case I830_GMCH_GMS_STOLEN_1024:
-			stolen_size = MB(1);
-			break;
-		case I830_GMCH_GMS_STOLEN_8192:
-			stolen_size = MB(8);
-			break;
-		case I830_GMCH_GMS_LOCAL:
-			rdct = readb(intel_private.registers+I830_RDRAM_CHANNEL_TYPE);
-			stolen_size = (I830_RDRAM_ND(rdct) + 1) *
-					MB(ddt[I830_RDRAM_DDT(rdct)]);
-			local = 1;
-			break;
-		default:
-			stolen_size = 0;
-			break;
-		}
-	} else {
-		switch (gmch_ctrl & I855_GMCH_GMS_MASK) {
-		case I855_GMCH_GMS_STOLEN_1M:
-			stolen_size = MB(1);
-			break;
-		case I855_GMCH_GMS_STOLEN_4M:
-			stolen_size = MB(4);
-			break;
-		case I855_GMCH_GMS_STOLEN_8M:
-			stolen_size = MB(8);
-			break;
-		case I855_GMCH_GMS_STOLEN_16M:
-			stolen_size = MB(16);
-			break;
-		case I855_GMCH_GMS_STOLEN_32M:
-			stolen_size = MB(32);
-			break;
-		case I915_GMCH_GMS_STOLEN_48M:
-			stolen_size = MB(48);
-			break;
-		case I915_GMCH_GMS_STOLEN_64M:
-			stolen_size = MB(64);
-			break;
-		case G33_GMCH_GMS_STOLEN_128M:
-			stolen_size = MB(128);
-			break;
-		case G33_GMCH_GMS_STOLEN_256M:
-			stolen_size = MB(256);
-			break;
-		case INTEL_GMCH_GMS_STOLEN_96M:
-			stolen_size = MB(96);
-			break;
-		case INTEL_GMCH_GMS_STOLEN_160M:
-			stolen_size = MB(160);
-			break;
-		case INTEL_GMCH_GMS_STOLEN_224M:
-			stolen_size = MB(224);
-			break;
-		case INTEL_GMCH_GMS_STOLEN_352M:
-			stolen_size = MB(352);
-			break;
-		default:
-			stolen_size = 0;
-			break;
-		}
-	}
+	struct resource *r;
+	unsigned int stolen_size;
 
-	if (stolen_size > 0) {
-		dev_info(&intel_private.bridge_dev->dev, "detected %dK %s memory\n",
-		       stolen_size / KB(1), local ? "local" : "stolen");
+	r = lookup_resource_by_name(&iomem_resource, E820_STOLEN_IGFX_STRING);
+	if (r) {
+		stolen_size = r->end - r->start + 1;
+		dev_info(&intel_private.bridge_dev->dev, "detected %dK stolen memory\n",
+		       stolen_size / KB(1));
 	} else {
 		dev_info(&intel_private.bridge_dev->dev,
 		       "no pre-allocated video memory detected\n");
@@ -1404,11 +1328,10 @@ int intel_gmch_probe(struct pci_dev *bridge_pdev, struct pci_dev *gpu_pdev,
 }
 EXPORT_SYMBOL(intel_gmch_probe);
 
-void intel_gtt_get(size_t *gtt_total, size_t *stolen_size,
+void intel_gtt_get(size_t *gtt_total,
 		   phys_addr_t *mappable_base, unsigned long *mappable_end)
 {
 	*gtt_total = intel_private.gtt_total_entries << PAGE_SHIFT;
-	*stolen_size = intel_private.stolen_size;
 	*mappable_base = intel_private.gma_bus_addr;
 	*mappable_end = intel_private.gtt_mappable_entries << PAGE_SHIFT;
 }
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index ae36612..ec14124 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -513,7 +513,6 @@ struct i915_address_space {
  */
 struct i915_gtt {
 	struct i915_address_space base;
-	size_t stolen_size;		/* Total size of stolen memory */
 
 	unsigned long mappable_end;	/* End offset that we can CPU map */
 	struct io_mapping *mappable;	/* Mapping to our CPU mappable region */
@@ -528,7 +527,7 @@ struct i915_gtt {
 
 	/* global gtt ops */
 	int (*gtt_probe)(struct drm_device *dev, size_t *gtt_total,
-			  size_t *stolen, phys_addr_t *mappable_base,
+			  phys_addr_t *mappable_base,
 			  unsigned long *mappable_end);
 };
 #define gtt_total_entries(gtt) ((gtt).base.total >> PAGE_SHIFT)
diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c
index 3b639a9..1294cee 100644
--- a/drivers/gpu/drm/i915/i915_gem_gtt.c
+++ b/drivers/gpu/drm/i915/i915_gem_gtt.c
@@ -784,16 +784,8 @@ static inline unsigned int gen6_get_total_gtt_size(u16 snb_gmch_ctl)
 	return snb_gmch_ctl << 20;
 }
 
-static inline size_t gen6_get_stolen_size(u16 snb_gmch_ctl)
-{
-	snb_gmch_ctl >>= SNB_GMCH_GMS_SHIFT;
-	snb_gmch_ctl &= SNB_GMCH_GMS_MASK;
-	return snb_gmch_ctl << 25; /* 32 MB units */
-}
-
 static int gen6_gmch_probe(struct drm_device *dev,
 			   size_t *gtt_total,
-			   size_t *stolen,
 			   phys_addr_t *mappable_base,
 			   unsigned long *mappable_end)
 {
@@ -820,7 +812,6 @@ static int gen6_gmch_probe(struct drm_device *dev,
 	pci_read_config_word(dev->pdev, SNB_GMCH_CTRL, &snb_gmch_ctl);
 	gtt_size = gen6_get_total_gtt_size(snb_gmch_ctl);
 
-	*stolen = gen6_get_stolen_size(snb_gmch_ctl);
 	*gtt_total = (gtt_size / sizeof(gen6_gtt_pte_t)) << PAGE_SHIFT;
 
 	/* For Modern GENs the PTEs and register space are split in the BAR */
@@ -853,7 +844,6 @@ static void gen6_gmch_remove(struct i915_address_space *vm)
 
 static int i915_gmch_probe(struct drm_device *dev,
 			   size_t *gtt_total,
-			   size_t *stolen,
 			   phys_addr_t *mappable_base,
 			   unsigned long *mappable_end)
 {
@@ -866,7 +856,7 @@ static int i915_gmch_probe(struct drm_device *dev,
 		return -EIO;
 	}
 
-	intel_gtt_get(gtt_total, stolen, mappable_base, mappable_end);
+	intel_gtt_get(gtt_total, mappable_base, mappable_end);
 
 	dev_priv->gtt.do_idle_maps = needs_idle_maps(dev_priv->dev);
 	dev_priv->gtt.base.clear_range = i915_ggtt_clear_range;
@@ -902,7 +892,7 @@ int i915_gem_gtt_init(struct drm_device *dev)
 			gtt->base.pte_encode = gen6_pte_encode;
 	}
 
-	ret = gtt->gtt_probe(dev, &gtt->base.total, &gtt->stolen_size,
+	ret = gtt->gtt_probe(dev, &gtt->base.total,
 			     &gtt->mappable_base, &gtt->mappable_end);
 	if (ret)
 		return ret;
@@ -913,7 +903,6 @@ int i915_gem_gtt_init(struct drm_device *dev)
 	DRM_INFO("Memory usable by graphics device = %zdM\n",
 		 gtt->base.total >> 20);
 	DRM_DEBUG_DRIVER("GMADR size = %ldM\n", gtt->mappable_end >> 20);
-	DRM_DEBUG_DRIVER("GTT stolen size = %zdM\n", gtt->stolen_size >> 20);
 
 	return 0;
 }
diff --git a/drivers/gpu/drm/i915/i915_gem_stolen.c b/drivers/gpu/drm/i915/i915_gem_stolen.c
index cacf769..f1f41f6 100644
--- a/drivers/gpu/drm/i915/i915_gem_stolen.c
+++ b/drivers/gpu/drm/i915/i915_gem_stolen.c
@@ -28,6 +28,7 @@
 
 #include <drm/drmP.h>
 #include <drm/i915_drm.h>
+#include <uapi/asm/e820.h>
 #include "i915_drv.h"
 
 /*
@@ -42,54 +43,6 @@
  * for is a boon.
  */
 
-static unsigned long i915_stolen_to_physical(struct drm_device *dev)
-{
-	struct drm_i915_private *dev_priv = dev->dev_private;
-	struct resource *r;
-	u32 base;
-
-	/* Almost universally we can find the Graphics Base of Stolen Memory
-	 * at offset 0x5c in the igfx configuration space. On a few (desktop)
-	 * machines this is also mirrored in the bridge device at different
-	 * locations, or in the MCHBAR. On gen2, the layout is again slightly
-	 * different with the Graphics Segment immediately following Top of
-	 * Memory (or Top of Usable DRAM). Note it appears that TOUD is only
-	 * reported by 865g, so we just use the top of memory as determined
-	 * by the e820 probe.
-	 *
-	 * XXX However gen2 requires an unavailable symbol.
-	 */
-	base = 0;
-	if (INTEL_INFO(dev)->gen >= 3) {
-		/* Read Graphics Base of Stolen Memory directly */
-		pci_read_config_dword(dev->pdev, 0x5c, &base);
-		base &= ~((1<<20) - 1);
-	} else { /* GEN2 */
-#if 0
-		/* Stolen is immediately above Top of Memory */
-		base = max_low_pfn_mapped << PAGE_SHIFT;
-#endif
-	}
-
-	if (base == 0)
-		return 0;
-
-	/* Verify that nothing else uses this physical address. Stolen
-	 * memory should be reserved by the BIOS and hidden from the
-	 * kernel. So if the region is already marked as busy, something
-	 * is seriously wrong.
-	 */
-	r = devm_request_mem_region(dev->dev, base, dev_priv->gtt.stolen_size,
-				    "Graphics Stolen Memory");
-	if (r == NULL) {
-		DRM_ERROR("conflict detected with stolen region: [0x%08x - 0x%08x]\n",
-			  base, base + (uint32_t)dev_priv->gtt.stolen_size);
-		base = 0;
-	}
-
-	return base;
-}
-
 static int i915_setup_compression(struct drm_device *dev, int size)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
@@ -188,24 +141,29 @@ void i915_gem_cleanup_stolen(struct drm_device *dev)
 int i915_gem_init_stolen(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct resource *r;
 	int bios_reserved = 0;
+	size_t size;
 
-	dev_priv->mm.stolen_base = i915_stolen_to_physical(dev);
-	if (dev_priv->mm.stolen_base == 0)
+	/* Did we reserve our stolen region during early PCI quirks? */
+	r = lookup_resource_by_name(&iomem_resource, E820_STOLEN_IGFX_STRING);
+	if (r == NULL)
 		return 0;
 
-	DRM_DEBUG_KMS("found %zd bytes of stolen memory at %08lx\n",
-		      dev_priv->gtt.stolen_size, dev_priv->mm.stolen_base);
+	size = r->end - r->start + 1;
+	DRM_DEBUG_DRIVER("found %zd bytes of stolen memory at %08qx\n",
+			 size, r->start);
+
+	dev_priv->mm.stolen_base = r->start;
 
 	if (IS_VALLEYVIEW(dev))
 		bios_reserved = 1024*1024; /* top 1M on VLV/BYT */
 
-	if (WARN_ON(bios_reserved > dev_priv->gtt.stolen_size))
+	if (WARN_ON(bios_reserved > size))
 		return 0;
 
 	/* Basic memrange allocator for stolen space */
-	drm_mm_init(&dev_priv->mm.stolen, 0, dev_priv->gtt.stolen_size -
-		    bios_reserved);
+	drm_mm_init(&dev_priv->mm.stolen, 0, size - bios_reserved);
 
 	return 0;
 }
@@ -219,7 +177,7 @@ i915_pages_create_for_stolen(struct drm_device *dev,
 	struct scatterlist *sg;
 
 	DRM_DEBUG_DRIVER("offset=0x%x, size=%d\n", offset, size);
-	BUG_ON(offset > dev_priv->gtt.stolen_size - size);
+	BUG_ON(offset > dev_priv->mm.stolen.head_node.size - size);
 
 	/* We hide that we have no struct page backing our stolen object
 	 * by wrapping the contiguous physical allocation with a fake
diff --git a/include/drm/intel-gtt.h b/include/drm/intel-gtt.h
index b08bdad..c0b5602 100644
--- a/include/drm/intel-gtt.h
+++ b/include/drm/intel-gtt.h
@@ -3,7 +3,7 @@
 #ifndef _DRM_INTEL_GTT_H
 #define	_DRM_INTEL_GTT_H
 
-void intel_gtt_get(size_t *gtt_total, size_t *stolen_size,
+void intel_gtt_get(size_t *gtt_total,
 		   phys_addr_t *mappable_base, unsigned long *mappable_end);
 
 int intel_gmch_probe(struct pci_dev *bridge_pdev, struct pci_dev *gpu_pdev,
-- 
1.8.3.2




More information about the Intel-gfx mailing list