[v2] drm/i915: Implement stolen reserved detection for ctg/elk
diff mbox

Message ID 1442428130-26192-1-git-send-email-ville.syrjala@linux.intel.com
State New
Headers show

Commit Message

Ville Syrjala Sept. 16, 2015, 6:28 p.m. UTC
From: Ville Syrjälä <ville.syrjala@linux.intel.com>

Finally managed to dig up enough hints as to where the stolen
reserved stuff lives on ctg/elk. So add the code to decode it.
This was a combination of old chipset specs, diggin up an old
elk grits release with an ctg/elk AubLoad etc.

This was only tested on an elk as I don't have a ctg here
unfortunately.

This leaves ilk as the only platform that doesn't have a way
to detect this stuff. Looking at the register contents on my
ilk, it might be that the elk way works there too, but I
can't be sure since I can't affect the amount of reserved
memory on that machine, and if I am to trust the register
contents, by default it would reserve 0 bytes.

v2: s/WARN_ON_ONCE/WARN_ON/ since it's in one time init code
    anyway (Paulo)

Cc: Paulo Zanoni <paulo.r.zanoni@intel.com>
Cc: Chris Wilson <chris@chris-wilson.co.uk>
Acked-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/i915/i915_gem_stolen.c | 31 ++++++++++++++++++++++++++++---
 drivers/gpu/drm/i915/i915_reg.h        |  5 +++++
 2 files changed, 33 insertions(+), 3 deletions(-)

Comments

Daniel Vetter Sept. 23, 2015, 9:14 a.m. UTC | #1
On Wed, Sep 16, 2015 at 09:28:50PM +0300, ville.syrjala@linux.intel.com wrote:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> 
> Finally managed to dig up enough hints as to where the stolen
> reserved stuff lives on ctg/elk. So add the code to decode it.
> This was a combination of old chipset specs, diggin up an old
> elk grits release with an ctg/elk AubLoad etc.
> 
> This was only tested on an elk as I don't have a ctg here
> unfortunately.
> 
> This leaves ilk as the only platform that doesn't have a way
> to detect this stuff. Looking at the register contents on my
> ilk, it might be that the elk way works there too, but I
> can't be sure since I can't affect the amount of reserved
> memory on that machine, and if I am to trust the register
> contents, by default it would reserve 0 bytes.
> 
> v2: s/WARN_ON_ONCE/WARN_ON/ since it's in one time init code
>     anyway (Paulo)
> 
> Cc: Paulo Zanoni <paulo.r.zanoni@intel.com>
> Cc: Chris Wilson <chris@chris-wilson.co.uk>
> Acked-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>

Queued for -next, thanks for the patch.
-Daniel

> ---
>  drivers/gpu/drm/i915/i915_gem_stolen.c | 31 ++++++++++++++++++++++++++++---
>  drivers/gpu/drm/i915/i915_reg.h        |  5 +++++
>  2 files changed, 33 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/i915_gem_stolen.c b/drivers/gpu/drm/i915/i915_gem_stolen.c
> index bf26ecc..0a3cffb 100644
> --- a/drivers/gpu/drm/i915/i915_gem_stolen.c
> +++ b/drivers/gpu/drm/i915/i915_gem_stolen.c
> @@ -186,6 +186,29 @@ void i915_gem_cleanup_stolen(struct drm_device *dev)
>  	drm_mm_takedown(&dev_priv->mm.stolen);
>  }
>  
> +static void g4x_get_stolen_reserved(struct drm_i915_private *dev_priv,
> +				    unsigned long *base, unsigned long *size)
> +{
> +	uint32_t reg_val = I915_READ(IS_GM45(dev_priv) ?
> +				     CTG_STOLEN_RESERVED :
> +				     ELK_STOLEN_RESERVED);
> +	unsigned long stolen_top = dev_priv->mm.stolen_base +
> +		dev_priv->gtt.stolen_size;
> +
> +	*base = (reg_val & G4X_STOLEN_RESERVED_ADDR2_MASK) << 16;
> +
> +	WARN_ON((reg_val & G4X_STOLEN_RESERVED_ADDR1_MASK) < *base);
> +
> +	/* On these platforms, the register doesn't have a size field, so the
> +	 * size is the distance between the base and the top of the stolen
> +	 * memory. We also have the genuine case where base is zero and there's
> +	 * nothing reserved. */
> +	if (*base == 0)
> +		*size = 0;
> +	else
> +		*size = stolen_top - *base;
> +}
> +
>  static void gen6_get_stolen_reserved(struct drm_i915_private *dev_priv,
>  				     unsigned long *base, unsigned long *size)
>  {
> @@ -305,10 +328,12 @@ int i915_gem_init_stolen(struct drm_device *dev)
>  	switch (INTEL_INFO(dev_priv)->gen) {
>  	case 2:
>  	case 3:
> +		break;
>  	case 4:
> -		if (!IS_G4X(dev))
> -			break;
> -		/* fall through */
> +		if (IS_G4X(dev))
> +			g4x_get_stolen_reserved(dev_priv, &reserved_base,
> +						&reserved_size);
> +		break;
>  	case 5:
>  		/* Assume the gen6 maximum for the older platforms. */
>  		reserved_size = 1024 * 1024;
> diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
> index 812b7b2..4f570b2 100644
> --- a/drivers/gpu/drm/i915/i915_reg.h
> +++ b/drivers/gpu/drm/i915/i915_reg.h
> @@ -2494,6 +2494,11 @@ enum skl_disp_power_wells {
>  
>  #define MCHBAR_MIRROR_BASE_SNB	0x140000
>  
> +#define CTG_STOLEN_RESERVED		(MCHBAR_MIRROR_BASE + 0x34)
> +#define ELK_STOLEN_RESERVED		(MCHBAR_MIRROR_BASE + 0x48)
> +#define G4X_STOLEN_RESERVED_ADDR1_MASK	(0xFFFF << 16)
> +#define G4X_STOLEN_RESERVED_ADDR2_MASK	(0xFFF << 4)
> +
>  /* Memory controller frequency in MCHBAR for Haswell (possible SNB+) */
>  #define DCLK (MCHBAR_MIRROR_BASE_SNB + 0x5e04)
>  
> -- 
> 2.4.6
> 
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx

Patch
diff mbox

diff --git a/drivers/gpu/drm/i915/i915_gem_stolen.c b/drivers/gpu/drm/i915/i915_gem_stolen.c
index bf26ecc..0a3cffb 100644
--- a/drivers/gpu/drm/i915/i915_gem_stolen.c
+++ b/drivers/gpu/drm/i915/i915_gem_stolen.c
@@ -186,6 +186,29 @@  void i915_gem_cleanup_stolen(struct drm_device *dev)
 	drm_mm_takedown(&dev_priv->mm.stolen);
 }
 
+static void g4x_get_stolen_reserved(struct drm_i915_private *dev_priv,
+				    unsigned long *base, unsigned long *size)
+{
+	uint32_t reg_val = I915_READ(IS_GM45(dev_priv) ?
+				     CTG_STOLEN_RESERVED :
+				     ELK_STOLEN_RESERVED);
+	unsigned long stolen_top = dev_priv->mm.stolen_base +
+		dev_priv->gtt.stolen_size;
+
+	*base = (reg_val & G4X_STOLEN_RESERVED_ADDR2_MASK) << 16;
+
+	WARN_ON((reg_val & G4X_STOLEN_RESERVED_ADDR1_MASK) < *base);
+
+	/* On these platforms, the register doesn't have a size field, so the
+	 * size is the distance between the base and the top of the stolen
+	 * memory. We also have the genuine case where base is zero and there's
+	 * nothing reserved. */
+	if (*base == 0)
+		*size = 0;
+	else
+		*size = stolen_top - *base;
+}
+
 static void gen6_get_stolen_reserved(struct drm_i915_private *dev_priv,
 				     unsigned long *base, unsigned long *size)
 {
@@ -305,10 +328,12 @@  int i915_gem_init_stolen(struct drm_device *dev)
 	switch (INTEL_INFO(dev_priv)->gen) {
 	case 2:
 	case 3:
+		break;
 	case 4:
-		if (!IS_G4X(dev))
-			break;
-		/* fall through */
+		if (IS_G4X(dev))
+			g4x_get_stolen_reserved(dev_priv, &reserved_base,
+						&reserved_size);
+		break;
 	case 5:
 		/* Assume the gen6 maximum for the older platforms. */
 		reserved_size = 1024 * 1024;
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index 812b7b2..4f570b2 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -2494,6 +2494,11 @@  enum skl_disp_power_wells {
 
 #define MCHBAR_MIRROR_BASE_SNB	0x140000
 
+#define CTG_STOLEN_RESERVED		(MCHBAR_MIRROR_BASE + 0x34)
+#define ELK_STOLEN_RESERVED		(MCHBAR_MIRROR_BASE + 0x48)
+#define G4X_STOLEN_RESERVED_ADDR1_MASK	(0xFFFF << 16)
+#define G4X_STOLEN_RESERVED_ADDR2_MASK	(0xFFF << 4)
+
 /* Memory controller frequency in MCHBAR for Haswell (possible SNB+) */
 #define DCLK (MCHBAR_MIRROR_BASE_SNB + 0x5e04)