Commit 274008e8 authored by Sagar Arun Kamble's avatar Sagar Arun Kamble Committed by Imre Deak

drm/i915/bxt: Check BIOS RC6 setup before enabling RC6

RC6 setup is shared between BIOS and Driver. BIOS sets up subset of RC6
setup registers. If those are not setup Driver should not enable RC6.
For implementing this, driver can check RC_CTRL0 and RC_CTRL1 values
to know if BIOS has enabled HW/SW RC6.
This will also enable user to control RC6 using BIOS settings alone.
RC6 related instability can be avoided by disabling via BIOS settings
till driver fixes it.

v2: Had placed logic in gen8 function by mistake. Fixed it.
Ensuring RPM is not enabled in case BIOS disabled RC6.

v3: Need to disable RPM if RC6 is disabled due to BIOS settings. (Daniel)
Runtime PM enabling happens before gen9_enable_rc6.
Moved the updation of enable_rc6 parameter in intel_uncore_sanitize.

v4: Added elaborate check for BIOS RC6 setup. Prepared check_pctx for bxt.
    (Imre)

v5: Caching reserved stolen base and size in the driver private data.
    Reorganized RC6 setup check. Moved from gen9_enable_rc6 to
    intel_uncore_sanitize. (Imre)

v6: Rebasing on the patch submitted by Imre that moves gem_init_stolen
    earlier in the load.

v7: Removed PWRCTX_MAXCNT_VCSUNIT1 check as it applies to SKL. (Imre)

v8: Fixed formatting and checkpatch issues. Fixed functional issue where
    RC6 ctx size check was missing. (Imre)

Cc: Imre Deak <imre.deak@intel.com>
Signed-off-by: default avatarSagar Arun Kamble <sagar.a.kamble@intel.com>
Signed-off-by: default avatarImre Deak <imre.deak@intel.com>
Link: http://patchwork.freedesktop.org/patch/msgid/1454697809-22113-1-git-send-email-sagar.a.kamble@intel.com
parent bfcef5d2
...@@ -342,6 +342,8 @@ struct i915_gtt { ...@@ -342,6 +342,8 @@ struct i915_gtt {
size_t stolen_size; /* Total size of stolen memory */ size_t stolen_size; /* Total size of stolen memory */
size_t stolen_usable_size; /* Total size minus BIOS reserved */ size_t stolen_usable_size; /* Total size minus BIOS reserved */
size_t stolen_reserved_base;
size_t stolen_reserved_size;
u64 mappable_end; /* End offset that we can CPU map */ u64 mappable_end; /* End offset that we can CPU map */
struct io_mapping *mappable; /* Mapping to our CPU mappable region */ struct io_mapping *mappable; /* Mapping to our CPU mappable region */
phys_addr_t mappable_base; /* PA of our GMADR */ phys_addr_t mappable_base; /* PA of our GMADR */
......
...@@ -458,6 +458,9 @@ int i915_gem_init_stolen(struct drm_device *dev) ...@@ -458,6 +458,9 @@ int i915_gem_init_stolen(struct drm_device *dev)
return 0; return 0;
} }
dev_priv->gtt.stolen_reserved_base = reserved_base;
dev_priv->gtt.stolen_reserved_size = reserved_size;
/* It is possible for the reserved area to end before the end of stolen /* It is possible for the reserved area to end before the end of stolen
* memory, so just consider the start. */ * memory, so just consider the start. */
reserved_total = stolen_top - reserved_base; reserved_total = stolen_top - reserved_base;
......
...@@ -6785,6 +6785,16 @@ enum skl_disp_power_wells { ...@@ -6785,6 +6785,16 @@ enum skl_disp_power_wells {
#define VLV_PMWGICZ _MMIO(0x1300a4) #define VLV_PMWGICZ _MMIO(0x1300a4)
#define RC6_LOCATION _MMIO(0xD40)
#define RC6_CTX_IN_DRAM (1 << 0)
#define RC6_CTX_BASE _MMIO(0xD48)
#define RC6_CTX_BASE_MASK 0xFFFFFFF0
#define PWRCTX_MAXCNT_RCSUNIT _MMIO(0x2054)
#define PWRCTX_MAXCNT_VCSUNIT0 _MMIO(0x12054)
#define PWRCTX_MAXCNT_BCSUNIT _MMIO(0x22054)
#define PWRCTX_MAXCNT_VECSUNIT _MMIO(0x1A054)
#define PWRCTX_MAXCNT_VCSUNIT1 _MMIO(0x1C054)
#define IDLE_TIME_MASK 0xFFFFF
#define FORCEWAKE _MMIO(0xA18C) #define FORCEWAKE _MMIO(0xA18C)
#define FORCEWAKE_VLV _MMIO(0x1300b0) #define FORCEWAKE_VLV _MMIO(0x1300b0)
#define FORCEWAKE_ACK_VLV _MMIO(0x1300b4) #define FORCEWAKE_ACK_VLV _MMIO(0x1300b4)
...@@ -6923,6 +6933,7 @@ enum skl_disp_power_wells { ...@@ -6923,6 +6933,7 @@ enum skl_disp_power_wells {
#define GEN6_RPDEUC _MMIO(0xA084) #define GEN6_RPDEUC _MMIO(0xA084)
#define GEN6_RPDEUCSW _MMIO(0xA088) #define GEN6_RPDEUCSW _MMIO(0xA088)
#define GEN6_RC_STATE _MMIO(0xA094) #define GEN6_RC_STATE _MMIO(0xA094)
#define RC6_STATE (1 << 18)
#define GEN6_RC1_WAKE_RATE_LIMIT _MMIO(0xA098) #define GEN6_RC1_WAKE_RATE_LIMIT _MMIO(0xA098)
#define GEN6_RC6_WAKE_RATE_LIMIT _MMIO(0xA09C) #define GEN6_RC6_WAKE_RATE_LIMIT _MMIO(0xA09C)
#define GEN6_RC6pp_WAKE_RATE_LIMIT _MMIO(0xA0A0) #define GEN6_RC6pp_WAKE_RATE_LIMIT _MMIO(0xA0A0)
......
...@@ -1566,6 +1566,7 @@ void skl_wm_get_hw_state(struct drm_device *dev); ...@@ -1566,6 +1566,7 @@ void skl_wm_get_hw_state(struct drm_device *dev);
void skl_ddb_get_hw_state(struct drm_i915_private *dev_priv, void skl_ddb_get_hw_state(struct drm_i915_private *dev_priv,
struct skl_ddb_allocation *ddb /* out */); struct skl_ddb_allocation *ddb /* out */);
uint32_t ilk_pipe_pixel_rate(const struct intel_crtc_state *pipe_config); uint32_t ilk_pipe_pixel_rate(const struct intel_crtc_state *pipe_config);
int sanitize_rc6_option(const struct drm_device *dev, int enable_rc6);
/* intel_sdvo.c */ /* intel_sdvo.c */
bool intel_sdvo_init(struct drm_device *dev, bool intel_sdvo_init(struct drm_device *dev,
......
...@@ -4562,12 +4562,62 @@ static void intel_print_rc6_info(struct drm_device *dev, u32 mode) ...@@ -4562,12 +4562,62 @@ static void intel_print_rc6_info(struct drm_device *dev, u32 mode)
onoff(mode & GEN6_RC_CTL_RC6_ENABLE)); onoff(mode & GEN6_RC_CTL_RC6_ENABLE));
} }
static int sanitize_rc6_option(const struct drm_device *dev, int enable_rc6) static bool bxt_check_bios_rc6_setup(const struct drm_device *dev)
{
struct drm_i915_private *dev_priv = dev->dev_private;
bool enable_rc6 = true;
unsigned long rc6_ctx_base;
if (!(I915_READ(RC6_LOCATION) & RC6_CTX_IN_DRAM)) {
DRM_DEBUG_KMS("RC6 Base location not set properly.\n");
enable_rc6 = false;
}
/*
* The exact context size is not known for BXT, so assume a page size
* for this check.
*/
rc6_ctx_base = I915_READ(RC6_CTX_BASE) & RC6_CTX_BASE_MASK;
if (!((rc6_ctx_base >= dev_priv->gtt.stolen_reserved_base) &&
(rc6_ctx_base + PAGE_SIZE <= dev_priv->gtt.stolen_reserved_base +
dev_priv->gtt.stolen_reserved_size))) {
DRM_DEBUG_KMS("RC6 Base address not as expected.\n");
enable_rc6 = false;
}
if (!(((I915_READ(PWRCTX_MAXCNT_RCSUNIT) & IDLE_TIME_MASK) > 1) &&
((I915_READ(PWRCTX_MAXCNT_VCSUNIT0) & IDLE_TIME_MASK) > 1) &&
((I915_READ(PWRCTX_MAXCNT_BCSUNIT) & IDLE_TIME_MASK) > 1) &&
((I915_READ(PWRCTX_MAXCNT_VECSUNIT) & IDLE_TIME_MASK) > 1))) {
DRM_DEBUG_KMS("Engine Idle wait time not set properly.\n");
enable_rc6 = false;
}
if (!(I915_READ(GEN6_RC_CONTROL) & (GEN6_RC_CTL_RC6_ENABLE |
GEN6_RC_CTL_HW_ENABLE)) &&
((I915_READ(GEN6_RC_CONTROL) & GEN6_RC_CTL_HW_ENABLE) ||
!(I915_READ(GEN6_RC_STATE) & RC6_STATE))) {
DRM_DEBUG_KMS("HW/SW RC6 is not enabled by BIOS.\n");
enable_rc6 = false;
}
return enable_rc6;
}
int sanitize_rc6_option(const struct drm_device *dev, int enable_rc6)
{ {
/* No RC6 before Ironlake and code is gone for ilk. */ /* No RC6 before Ironlake and code is gone for ilk. */
if (INTEL_INFO(dev)->gen < 6) if (INTEL_INFO(dev)->gen < 6)
return 0; return 0;
if (!enable_rc6)
return 0;
if (IS_BROXTON(dev) && !bxt_check_bios_rc6_setup(dev)) {
DRM_INFO("RC6 disabled by BIOS\n");
return 0;
}
/* Respect the kernel parameter if it is set */ /* Respect the kernel parameter if it is set */
if (enable_rc6 >= 0) { if (enable_rc6 >= 0) {
int mask; int mask;
...@@ -6057,7 +6107,6 @@ void intel_init_gt_powersave(struct drm_device *dev) ...@@ -6057,7 +6107,6 @@ void intel_init_gt_powersave(struct drm_device *dev)
{ {
struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_private *dev_priv = dev->dev_private;
i915.enable_rc6 = sanitize_rc6_option(dev, i915.enable_rc6);
/* /*
* RPM depends on RC6 to save restore the GT HW context, so make RC6 a * RPM depends on RC6 to save restore the GT HW context, so make RC6 a
* requirement. * requirement.
......
...@@ -400,6 +400,8 @@ void intel_uncore_early_sanitize(struct drm_device *dev, bool restore_forcewake) ...@@ -400,6 +400,8 @@ void intel_uncore_early_sanitize(struct drm_device *dev, bool restore_forcewake)
void intel_uncore_sanitize(struct drm_device *dev) void intel_uncore_sanitize(struct drm_device *dev)
{ {
i915.enable_rc6 = sanitize_rc6_option(dev, i915.enable_rc6);
/* BIOS often leaves RC6 enabled, but disable it for hw init */ /* BIOS often leaves RC6 enabled, but disable it for hw init */
intel_disable_gt_powersave(dev); intel_disable_gt_powersave(dev);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment