aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorImre Deak <imre.deak@intel.com>2013-11-27 15:02:02 -0500
committerDaniel Vetter <daniel.vetter@ffwll.ch>2013-11-28 09:05:06 -0500
commitddf9c536295b9d7fcfd0bfc377593b41f2a4dc02 (patch)
treec7a345c1b6eb6b692859e2fb1062389011adc2af /drivers
parent48e9212021d920fe91046ad078e1070524844059 (diff)
drm/i915: add intel_display_power_enabled_sw() for use in atomic ctx
Atm we call intel_display_power_enabled() from i915_capture_error_state() in IRQ context and then take a mutex. To fix this add a new intel_display_power_enabled_sw() which returns the domain state based on software tracking as opposed to reading the actual HW state. Since we use domain_use_count for this without locking on the reader side make sure we increase the counter only after enabling all required power wells and decrease it before disabling any of these power wells. Regression introduced in commit 1b02383464b4a915627ef3b8fd0ad7f07168c54c Author: Imre Deak <imre.deak@intel.com> Date:   Tue Sep 24 16:17:09 2013 +0300     drm/i915: support for multiple power wells Note that atm we depend on the value returned by intel_display_power_enabled_sw() in i915_capture_error_state() to avoid unclaimed register access reports. This was never guaranteed though, since another thread can disable the power concurrently. If this is a problem we need another explicit way to disable the reporting during error captures. v2: - remove barriers as the caller can't depend on the value returned from i915_capture_error_state_sw() anyway (Ville) - dump the state of pipe/transcoder power domain state (Daniel) Reported-by: Chris Wilson <chris@chris-wilson.co.uk> Signed-off-by: Imre Deak <imre.deak@intel.com> Reviewed-by: Paulo Zanoni <paulo.r.zanoni@intel.com> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/gpu/drm/i915/i915_drv.h2
-rw-r--r--drivers/gpu/drm/i915/intel_display.c15
-rw-r--r--drivers/gpu/drm/i915/intel_drv.h2
-rw-r--r--drivers/gpu/drm/i915/intel_pm.c24
4 files changed, 30 insertions, 13 deletions
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 6b18b4714d7e..64ed8f4d991f 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -976,9 +976,7 @@ struct i915_power_domains {
976 int power_well_count; 976 int power_well_count;
977 977
978 struct mutex lock; 978 struct mutex lock;
979#if IS_ENABLED(CONFIG_DEBUG_FS)
980 int domain_use_count[POWER_DOMAIN_NUM]; 979 int domain_use_count[POWER_DOMAIN_NUM];
981#endif
982 struct i915_power_well *power_wells; 980 struct i915_power_well *power_wells;
983}; 981};
984 982
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index ca467cb3c1b4..5a79088e6da1 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -11317,6 +11317,7 @@ struct intel_display_error_state {
11317 } cursor[I915_MAX_PIPES]; 11317 } cursor[I915_MAX_PIPES];
11318 11318
11319 struct intel_pipe_error_state { 11319 struct intel_pipe_error_state {
11320 bool power_domain_on;
11320 u32 source; 11321 u32 source;
11321 } pipe[I915_MAX_PIPES]; 11322 } pipe[I915_MAX_PIPES];
11322 11323
@@ -11331,6 +11332,7 @@ struct intel_display_error_state {
11331 } plane[I915_MAX_PIPES]; 11332 } plane[I915_MAX_PIPES];
11332 11333
11333 struct intel_transcoder_error_state { 11334 struct intel_transcoder_error_state {
11335 bool power_domain_on;
11334 enum transcoder cpu_transcoder; 11336 enum transcoder cpu_transcoder;
11335 11337
11336 u32 conf; 11338 u32 conf;
@@ -11368,7 +11370,9 @@ intel_display_capture_error_state(struct drm_device *dev)
11368 error->power_well_driver = I915_READ(HSW_PWR_WELL_DRIVER); 11370 error->power_well_driver = I915_READ(HSW_PWR_WELL_DRIVER);
11369 11371
11370 for_each_pipe(i) { 11372 for_each_pipe(i) {
11371 if (!intel_display_power_enabled(dev, POWER_DOMAIN_PIPE(i))) 11373 error->pipe[i].power_domain_on =
11374 intel_display_power_enabled_sw(dev, POWER_DOMAIN_PIPE(i));
11375 if (!error->pipe[i].power_domain_on)
11372 continue; 11376 continue;
11373 11377
11374 if (INTEL_INFO(dev)->gen <= 6 || IS_VALLEYVIEW(dev)) { 11378 if (INTEL_INFO(dev)->gen <= 6 || IS_VALLEYVIEW(dev)) {
@@ -11404,8 +11408,9 @@ intel_display_capture_error_state(struct drm_device *dev)
11404 for (i = 0; i < error->num_transcoders; i++) { 11408 for (i = 0; i < error->num_transcoders; i++) {
11405 enum transcoder cpu_transcoder = transcoders[i]; 11409 enum transcoder cpu_transcoder = transcoders[i];
11406 11410
11407 if (!intel_display_power_enabled(dev, 11411 error->transcoder[i].power_domain_on =
11408 POWER_DOMAIN_TRANSCODER(cpu_transcoder))) 11412 intel_display_power_enabled_sw(dev, POWER_DOMAIN_PIPE(i));
11413 if (!error->transcoder[i].power_domain_on)
11409 continue; 11414 continue;
11410 11415
11411 error->transcoder[i].cpu_transcoder = cpu_transcoder; 11416 error->transcoder[i].cpu_transcoder = cpu_transcoder;
@@ -11440,6 +11445,8 @@ intel_display_print_error_state(struct drm_i915_error_state_buf *m,
11440 error->power_well_driver); 11445 error->power_well_driver);
11441 for_each_pipe(i) { 11446 for_each_pipe(i) {
11442 err_printf(m, "Pipe [%d]:\n", i); 11447 err_printf(m, "Pipe [%d]:\n", i);
11448 err_printf(m, " Power: %s\n",
11449 error->pipe[i].power_domain_on ? "on" : "off");
11443 err_printf(m, " SRC: %08x\n", error->pipe[i].source); 11450 err_printf(m, " SRC: %08x\n", error->pipe[i].source);
11444 11451
11445 err_printf(m, "Plane [%d]:\n", i); 11452 err_printf(m, "Plane [%d]:\n", i);
@@ -11465,6 +11472,8 @@ intel_display_print_error_state(struct drm_i915_error_state_buf *m,
11465 for (i = 0; i < error->num_transcoders; i++) { 11472 for (i = 0; i < error->num_transcoders; i++) {
11466 err_printf(m, "CPU transcoder: %c\n", 11473 err_printf(m, "CPU transcoder: %c\n",
11467 transcoder_name(error->transcoder[i].cpu_transcoder)); 11474 transcoder_name(error->transcoder[i].cpu_transcoder));
11475 err_printf(m, " Power: %s\n",
11476 error->transcoder[i].power_domain_on ? "on" : "off");
11468 err_printf(m, " CONF: %08x\n", error->transcoder[i].conf); 11477 err_printf(m, " CONF: %08x\n", error->transcoder[i].conf);
11469 err_printf(m, " HTOTAL: %08x\n", error->transcoder[i].htotal); 11478 err_printf(m, " HTOTAL: %08x\n", error->transcoder[i].htotal);
11470 err_printf(m, " HBLANK: %08x\n", error->transcoder[i].hblank); 11479 err_printf(m, " HBLANK: %08x\n", error->transcoder[i].hblank);
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 02312810374d..5dea38967523 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -842,6 +842,8 @@ int intel_power_domains_init(struct drm_device *dev);
842void intel_power_domains_remove(struct drm_device *dev); 842void intel_power_domains_remove(struct drm_device *dev);
843bool intel_display_power_enabled(struct drm_device *dev, 843bool intel_display_power_enabled(struct drm_device *dev,
844 enum intel_display_power_domain domain); 844 enum intel_display_power_domain domain);
845bool intel_display_power_enabled_sw(struct drm_device *dev,
846 enum intel_display_power_domain domain);
845void intel_display_power_get(struct drm_device *dev, 847void intel_display_power_get(struct drm_device *dev,
846 enum intel_display_power_domain domain); 848 enum intel_display_power_domain domain);
847void intel_display_power_put(struct drm_device *dev, 849void intel_display_power_put(struct drm_device *dev,
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index eac7c4eb345c..ff47520f8d40 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -5641,6 +5641,17 @@ static bool hsw_power_well_enabled(struct drm_device *dev,
5641 (HSW_PWR_WELL_ENABLE_REQUEST | HSW_PWR_WELL_STATE_ENABLED); 5641 (HSW_PWR_WELL_ENABLE_REQUEST | HSW_PWR_WELL_STATE_ENABLED);
5642} 5642}
5643 5643
5644bool intel_display_power_enabled_sw(struct drm_device *dev,
5645 enum intel_display_power_domain domain)
5646{
5647 struct drm_i915_private *dev_priv = dev->dev_private;
5648 struct i915_power_domains *power_domains;
5649
5650 power_domains = &dev_priv->power_domains;
5651
5652 return power_domains->domain_use_count[domain];
5653}
5654
5644bool intel_display_power_enabled(struct drm_device *dev, 5655bool intel_display_power_enabled(struct drm_device *dev,
5645 enum intel_display_power_domain domain) 5656 enum intel_display_power_domain domain)
5646{ 5657{
@@ -5761,12 +5772,11 @@ void intel_display_power_get(struct drm_device *dev,
5761 5772
5762 mutex_lock(&power_domains->lock); 5773 mutex_lock(&power_domains->lock);
5763 5774
5764#if IS_ENABLED(CONFIG_DEBUG_FS)
5765 power_domains->domain_use_count[domain]++;
5766#endif
5767 for_each_power_well(i, power_well, BIT(domain), power_domains) 5775 for_each_power_well(i, power_well, BIT(domain), power_domains)
5768 __intel_power_well_get(dev, power_well); 5776 __intel_power_well_get(dev, power_well);
5769 5777
5778 power_domains->domain_use_count[domain]++;
5779
5770 mutex_unlock(&power_domains->lock); 5780 mutex_unlock(&power_domains->lock);
5771} 5781}
5772 5782
@@ -5782,13 +5792,11 @@ void intel_display_power_put(struct drm_device *dev,
5782 5792
5783 mutex_lock(&power_domains->lock); 5793 mutex_lock(&power_domains->lock);
5784 5794
5785 for_each_power_well_rev(i, power_well, BIT(domain), power_domains)
5786 __intel_power_well_put(dev, power_well);
5787
5788#if IS_ENABLED(CONFIG_DEBUG_FS)
5789 WARN_ON(!power_domains->domain_use_count[domain]); 5795 WARN_ON(!power_domains->domain_use_count[domain]);
5790 power_domains->domain_use_count[domain]--; 5796 power_domains->domain_use_count[domain]--;
5791#endif 5797
5798 for_each_power_well_rev(i, power_well, BIT(domain), power_domains)
5799 __intel_power_well_put(dev, power_well);
5792 5800
5793 mutex_unlock(&power_domains->lock); 5801 mutex_unlock(&power_domains->lock);
5794} 5802}