Skip to content

Commit

Permalink
drm/i915: cache hw power well enabled state
Browse files Browse the repository at this point in the history
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 bb4932c
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: Jesse Barnes <jesse.barnes@intel.com>
Signed-off-by: Imre Deak <imre.deak@intel.com>
Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
  • Loading branch information
Imre Deak authored and Jani Nikula committed Jun 23, 2014
1 parent a497c3b commit bfafe93
Show file tree
Hide file tree
Showing 4 changed files with 22 additions and 27 deletions.
2 changes: 2 additions & 0 deletions drivers/gpu/drm/i915/i915_drv.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
6 changes: 3 additions & 3 deletions drivers/gpu/drm/i915/intel_display.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -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;
Expand Down
4 changes: 2 additions & 2 deletions drivers/gpu/drm/i915/intel_drv.h
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
37 changes: 15 additions & 22 deletions drivers/gpu/drm/i915/intel_pm.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -5615,47 +5615,35 @@ 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;
}

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;
}

/*
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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);
}

Expand Down Expand Up @@ -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);
}

Expand Down

0 comments on commit bfafe93

Please sign in to comment.