提交 bfafe93a 编写于 作者: I Imre Deak 提交者: Jani Nikula

drm/i915: cache hw power well enabled state

Jesse noticed that the punit communication needed to query the VLV power
well status can cause substantial delays. Since we can query the state
frequently, for example during I2C transfers, maintain a cached version
of the HW state to get rid of this delay.

This fixes at least one reported regression where boot time increased by
~4 seconds due to frequent power well state queries on VLV during eDP
EDID read.

This regression has been introduced in

commit bb4932c4
Author: Imre Deak <imre.deak@intel.com>
Date:   Mon Apr 14 20:24:33 2014 +0300

    drm/i915: vlv: check port power domain instead of only D0 for eDP VDD on
Reported-by: NJesse Barnes <jesse.barnes@intel.com>
Signed-off-by: NImre Deak <imre.deak@intel.com>
Reviewed-by: NJesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: NDaniel Vetter <daniel.vetter@ffwll.ch>
上级 a497c3ba
......@@ -977,6 +977,8 @@ struct i915_power_well {
bool always_on;
/* power well enable/disable usage count */
int count;
/* cached hw enabled state */
bool hw_enabled;
unsigned long domains;
unsigned long data;
const struct i915_power_well_ops *ops;
......
......@@ -12411,8 +12411,8 @@ intel_display_capture_error_state(struct drm_device *dev)
for_each_pipe(i) {
error->pipe[i].power_domain_on =
intel_display_power_enabled_sw(dev_priv,
POWER_DOMAIN_PIPE(i));
intel_display_power_enabled_unlocked(dev_priv,
POWER_DOMAIN_PIPE(i));
if (!error->pipe[i].power_domain_on)
continue;
......@@ -12447,7 +12447,7 @@ intel_display_capture_error_state(struct drm_device *dev)
enum transcoder cpu_transcoder = transcoders[i];
error->transcoder[i].power_domain_on =
intel_display_power_enabled_sw(dev_priv,
intel_display_power_enabled_unlocked(dev_priv,
POWER_DOMAIN_TRANSCODER(cpu_transcoder));
if (!error->transcoder[i].power_domain_on)
continue;
......
......@@ -950,8 +950,8 @@ int intel_power_domains_init(struct drm_i915_private *);
void intel_power_domains_remove(struct drm_i915_private *);
bool intel_display_power_enabled(struct drm_i915_private *dev_priv,
enum intel_display_power_domain domain);
bool intel_display_power_enabled_sw(struct drm_i915_private *dev_priv,
enum intel_display_power_domain domain);
bool intel_display_power_enabled_unlocked(struct drm_i915_private *dev_priv,
enum intel_display_power_domain domain);
void intel_display_power_get(struct drm_i915_private *dev_priv,
enum intel_display_power_domain domain);
void intel_display_power_put(struct drm_i915_private *dev_priv,
......
......@@ -5603,8 +5603,8 @@ static bool hsw_power_well_enabled(struct drm_i915_private *dev_priv,
(HSW_PWR_WELL_ENABLE_REQUEST | HSW_PWR_WELL_STATE_ENABLED);
}
bool intel_display_power_enabled_sw(struct drm_i915_private *dev_priv,
enum intel_display_power_domain domain)
bool intel_display_power_enabled_unlocked(struct drm_i915_private *dev_priv,
enum intel_display_power_domain domain)
{
struct i915_power_domains *power_domains;
struct i915_power_well *power_well;
......@@ -5615,16 +5615,19 @@ bool intel_display_power_enabled_sw(struct drm_i915_private *dev_priv,
return false;
power_domains = &dev_priv->power_domains;
is_enabled = true;
for_each_power_well_rev(i, power_well, BIT(domain), power_domains) {
if (power_well->always_on)
continue;
if (!power_well->count) {
if (!power_well->hw_enabled) {
is_enabled = false;
break;
}
}
return is_enabled;
}
......@@ -5632,30 +5635,15 @@ bool intel_display_power_enabled(struct drm_i915_private *dev_priv,
enum intel_display_power_domain domain)
{
struct i915_power_domains *power_domains;
struct i915_power_well *power_well;
bool is_enabled;
int i;
if (dev_priv->pm.suspended)
return false;
bool ret;
power_domains = &dev_priv->power_domains;
is_enabled = true;
mutex_lock(&power_domains->lock);
for_each_power_well_rev(i, power_well, BIT(domain), power_domains) {
if (power_well->always_on)
continue;
if (!power_well->ops->is_enabled(dev_priv, power_well)) {
is_enabled = false;
break;
}
}
ret = intel_display_power_enabled_unlocked(dev_priv, domain);
mutex_unlock(&power_domains->lock);
return is_enabled;
return ret;
}
/*
......@@ -5976,6 +5964,7 @@ void intel_display_power_get(struct drm_i915_private *dev_priv,
if (!power_well->count++) {
DRM_DEBUG_KMS("enabling %s\n", power_well->name);
power_well->ops->enable(dev_priv, power_well);
power_well->hw_enabled = true;
}
check_power_well_state(dev_priv, power_well);
......@@ -6005,6 +5994,7 @@ void intel_display_power_put(struct drm_i915_private *dev_priv,
if (!--power_well->count && i915.disable_power_well) {
DRM_DEBUG_KMS("disabling %s\n", power_well->name);
power_well->hw_enabled = false;
power_well->ops->disable(dev_priv, power_well);
}
......@@ -6267,8 +6257,11 @@ static void intel_power_domains_resume(struct drm_i915_private *dev_priv)
int i;
mutex_lock(&power_domains->lock);
for_each_power_well(i, power_well, POWER_DOMAIN_MASK, power_domains)
for_each_power_well(i, power_well, POWER_DOMAIN_MASK, power_domains) {
power_well->ops->sync_hw(dev_priv, power_well);
power_well->hw_enabled = power_well->ops->is_enabled(dev_priv,
power_well);
}
mutex_unlock(&power_domains->lock);
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册