clear-pkgs-linux-iot-lts2018/0642-INTERNAL-IOTG-drm-i915...

362 lines
14 KiB
Diff

From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Vivek Kasireddy <vivek.kasireddy@intel.com>
Date: Thu, 8 Mar 2018 15:10:34 -0800
Subject: [PATCH] INTERNAL [IOTG] drm/i915: Decouple pipe and crtc index
dependencies
i915 driver had assumptions that pipe and the crtc index always
matched, but with plane restrictions feature, this assuumption is no
longer true.
In virualized environment guest Oses may have pipes with no planes
attached and no crtc should be created for that pipe (but for
service OS, CRTC still needs to be created to do the initial modeset).
In cases were no CRTC was created for some pipes, the index and pipe
won't
match and was causing issues. These changes are to decouple the pipe and
index dependencies in the driver.
v2(ssingh) : Ported this patch to 4.19 kernel.
Signed-off-by: Satyeshwar Singh <satyeshwar.singh@intel.com>
Signed-off-by: Anitha Chrisanthus <anitha.chrisanthus@intel.com>
Signed-off-by: Vivek Kasireddy <vivek.kasireddy@intel.com>
Change-Id: Iccf6b54c254e2b3d7053620c1b64ad8dda7632b8
---
drivers/gpu/drm/i915/i915_drv.h | 10 +++---
drivers/gpu/drm/i915/i915_irq.c | 32 ++++++++++++-----
drivers/gpu/drm/i915/i915_trace.h | 2 +-
drivers/gpu/drm/i915/intel_display.c | 40 ++++++++++++++++++----
drivers/gpu/drm/i915/intel_dpll_mgr.c | 5 +--
drivers/gpu/drm/i915/intel_drv.h | 10 +++++-
drivers/gpu/drm/i915/intel_fifo_underrun.c | 11 ++++--
drivers/gpu/drm/i915/intel_pm.c | 7 ++--
8 files changed, 87 insertions(+), 30 deletions(-)
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 3b7e5160b7ca..7fbffa47fc37 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -2837,18 +2837,18 @@ ilk_disable_display_irq(struct drm_i915_private *dev_priv, uint32_t bits)
ilk_update_display_irq(dev_priv, bits, 0);
}
void bdw_update_pipe_irq(struct drm_i915_private *dev_priv,
- enum pipe pipe,
+ unsigned int crtc_index,
uint32_t interrupt_mask,
uint32_t enabled_irq_mask);
static inline void bdw_enable_pipe_irq(struct drm_i915_private *dev_priv,
- enum pipe pipe, uint32_t bits)
+ unsigned int crtc_index, uint32_t bits)
{
- bdw_update_pipe_irq(dev_priv, pipe, bits, bits);
+ bdw_update_pipe_irq(dev_priv, crtc_index, bits, bits);
}
static inline void bdw_disable_pipe_irq(struct drm_i915_private *dev_priv,
- enum pipe pipe, uint32_t bits)
+ unsigned int crtc_index, uint32_t bits)
{
- bdw_update_pipe_irq(dev_priv, pipe, bits, 0);
+ bdw_update_pipe_irq(dev_priv, crtc_index, bits, 0);
}
void ibx_display_interrupt_update(struct drm_i915_private *dev_priv,
uint32_t interrupt_mask,
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index 5428de8e8c59..6aec41be56f9 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -626,11 +626,12 @@ static void bdw_update_port_irq(struct drm_i915_private *dev_priv,
* @enabled_irq_mask: mask of interrupt bits to enable
*/
void bdw_update_pipe_irq(struct drm_i915_private *dev_priv,
- enum pipe pipe,
+ unsigned int crtc_index,
uint32_t interrupt_mask,
uint32_t enabled_irq_mask)
{
uint32_t new_val;
+ enum pipe pipe;
lockdep_assert_held(&dev_priv->irq_lock);
@@ -639,6 +640,9 @@ void bdw_update_pipe_irq(struct drm_i915_private *dev_priv,
if (WARN_ON(!intel_irqs_enabled(dev_priv)))
return;
+ if(get_pipe_from_crtc_index(&dev_priv->drm, crtc_index, &pipe))
+ return;
+
new_val = dev_priv->de_irq_mask[pipe];
new_val &= ~interrupt_mask;
new_val |= (~enabled_irq_mask & interrupt_mask);
@@ -884,9 +888,14 @@ static u32 i915_get_vblank_counter(struct drm_device *dev, unsigned int pipe)
return (((high1 << 8) | low) + (pixel >= vbl_start)) & 0xffffff;
}
-static u32 g4x_get_vblank_counter(struct drm_device *dev, unsigned int pipe)
+static u32 g4x_get_vblank_counter(struct drm_device *dev,
+ unsigned int crtc_index)
{
struct drm_i915_private *dev_priv = to_i915(dev);
+ enum pipe pipe;
+
+ if(get_pipe_from_crtc_index(dev, crtc_index, &pipe))
+ return 0;
return I915_READ(PIPE_FRMCOUNT_G4X(pipe));
}
@@ -1002,18 +1011,21 @@ static int __intel_get_crtc_scanline(struct intel_crtc *crtc)
return (position + crtc->scanline_offset) % vtotal;
}
-static bool i915_get_crtc_scanoutpos(struct drm_device *dev, unsigned int pipe,
- bool in_vblank_irq, int *vpos, int *hpos,
- ktime_t *stime, ktime_t *etime,
- const struct drm_display_mode *mode)
+static bool i915_get_crtc_scanoutpos(struct drm_device *dev, unsigned int crtc_index,
+ bool in_vblank_irq, int *vpos, int *hpos,
+ ktime_t *stime, ktime_t *etime,
+ const struct drm_display_mode *mode)
{
struct drm_i915_private *dev_priv = to_i915(dev);
- struct intel_crtc *intel_crtc = intel_get_crtc_for_pipe(dev_priv,
- pipe);
+ struct intel_crtc *intel_crtc;
+ enum pipe pipe;
int position;
int vbl_start, vbl_end, hsync_start, htotal, vtotal;
unsigned long irqflags;
+ intel_crtc = get_intel_crtc_from_index(dev, crtc_index);
+ pipe = intel_crtc->pipe;
+
if (WARN_ON(!mode->crtc_clock)) {
DRM_DEBUG_DRIVER("trying to get scanoutpos for disabled "
"pipe %c\n", pipe_name(pipe));
@@ -2748,6 +2760,7 @@ gen8_de_irq_handler(struct drm_i915_private *dev_priv, u32 master_ctl)
irqreturn_t ret = IRQ_NONE;
u32 iir;
enum pipe pipe;
+ struct intel_crtc *crtc;
if (master_ctl & GEN8_DE_MISC_IRQ) {
iir = I915_READ(GEN8_DE_MISC_IIR);
@@ -2858,8 +2871,9 @@ gen8_de_irq_handler(struct drm_i915_private *dev_priv, u32 master_ctl)
ret = IRQ_HANDLED;
I915_WRITE(GEN8_DE_PIPE_IIR(pipe), iir);
+ crtc = intel_get_crtc_for_pipe(dev_priv, pipe);
if (iir & GEN8_PIPE_VBLANK) {
- drm_handle_vblank(&dev_priv->drm, pipe);
+ drm_handle_vblank(&dev_priv->drm, drm_crtc_index(&crtc->base));
#if IS_ENABLED(CONFIG_DRM_I915_GVT)
gvt_notify_vblank(dev_priv, pipe);
#endif
diff --git a/drivers/gpu/drm/i915/i915_trace.h b/drivers/gpu/drm/i915/i915_trace.h
index af592e3d09a9..6f25961ad9ad 100644
--- a/drivers/gpu/drm/i915/i915_trace.h
+++ b/drivers/gpu/drm/i915/i915_trace.h
@@ -281,7 +281,7 @@ TRACE_EVENT(i915_pipe_update_start,
TP_fast_assign(
__entry->pipe = crtc->pipe;
__entry->frame = crtc->base.dev->driver->get_vblank_counter(crtc->base.dev,
- crtc->pipe);
+ drm_crtc_index(&crtc->base));
__entry->scanline = intel_get_crtc_scanline(crtc);
__entry->min = crtc->debug.min_vbl;
__entry->max = crtc->debug.max_vbl;
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 0a5c04d92d9a..0ebc35641211 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -11979,11 +11979,13 @@ verify_single_dpll_state(struct drm_i915_private *dev_priv,
if (new_state->active)
I915_STATE_WARN(!(pll->active_mask & crtc_mask),
"pll active mismatch (expected pipe %c in active mask 0x%02x)\n",
- pipe_name(drm_crtc_index(crtc)), pll->active_mask);
+ pipe_name(to_intel_crtc(crtc)->pipe),
+ pll->active_mask);
else
I915_STATE_WARN(pll->active_mask & crtc_mask,
"pll active mismatch (didn't expect pipe %c in active mask 0x%02x)\n",
- pipe_name(drm_crtc_index(crtc)), pll->active_mask);
+ pipe_name(to_intel_crtc(crtc)->pipe),
+ pll->active_mask);
I915_STATE_WARN(!(pll->state.crtc_mask & crtc_mask),
"pll enabled crtcs mismatch (expected 0x%x in 0x%02x)\n",
@@ -12014,10 +12016,10 @@ verify_shared_dpll_state(struct drm_device *dev, struct drm_crtc *crtc,
I915_STATE_WARN(pll->active_mask & crtc_mask,
"pll active mismatch (didn't expect pipe %c in active mask)\n",
- pipe_name(drm_crtc_index(crtc)));
+ pipe_name(to_intel_crtc(crtc)->pipe));
I915_STATE_WARN(pll->state.crtc_mask & crtc_mask,
"pll enabled crtcs mismatch (found %x in enabled mask)\n",
- pipe_name(drm_crtc_index(crtc)));
+ pipe_name(to_intel_crtc(crtc)->pipe));
}
}
@@ -12432,7 +12434,8 @@ u32 intel_crtc_get_vblank_counter(struct intel_crtc *crtc)
if (!dev->max_vblank_count)
return (u32)drm_crtc_accurate_vblank_count(&crtc->base);
- return dev->driver->get_vblank_counter(dev, crtc->pipe);
+ return dev->driver->get_vblank_counter(dev,
+ drm_crtc_index(&crtc->base));
}
static void intel_update_crtc(struct drm_crtc *crtc,
@@ -14083,6 +14086,27 @@ int intel_get_pipe_from_crtc_id_ioctl(struct drm_device *dev, void *data,
return 0;
}
+int get_pipe_from_crtc_index(struct drm_device *dev, unsigned int index, enum pipe *pipe)
+{
+ struct drm_crtc *c = drm_crtc_from_index(dev, index);
+
+ if (WARN_ON(!c))
+ return -ENOENT;
+
+ *pipe = (to_intel_crtc(c)->pipe);
+ return 0;
+}
+
+struct intel_crtc *get_intel_crtc_from_index(struct drm_device *dev,
+ unsigned int index)
+{
+ struct drm_crtc *c = drm_crtc_from_index(dev, index);
+
+ WARN_ON(!c);
+ return to_intel_crtc(c);
+}
+
+
static int intel_encoder_clones(struct intel_encoder *encoder)
{
struct drm_device *dev = encoder->base.dev;
@@ -15670,7 +15694,8 @@ static void intel_modeset_readout_hw_state(struct drm_device *dev)
crtc->active = crtc_state->base.active;
if (crtc_state->base.active)
- dev_priv->active_crtcs |= 1 << crtc->pipe;
+ dev_priv->active_crtcs |=
+ 1 << drm_crtc_index(&crtc->base);
DRM_DEBUG_KMS("[CRTC:%d:%s] hw state readout: %s\n",
crtc->base.base.id, crtc->base.name,
@@ -15691,7 +15716,8 @@ static void intel_modeset_readout_hw_state(struct drm_device *dev)
if (crtc_state->base.active &&
crtc_state->shared_dpll == pll)
- pll->state.crtc_mask |= 1 << crtc->pipe;
+ pll->state.crtc_mask |=
+ 1 << drm_crtc_index(&crtc->base);
}
pll->active_mask = pll->state.crtc_mask;
diff --git a/drivers/gpu/drm/i915/intel_dpll_mgr.c b/drivers/gpu/drm/i915/intel_dpll_mgr.c
index b51ad2917dbe..47b1dfe06152 100644
--- a/drivers/gpu/drm/i915/intel_dpll_mgr.c
+++ b/drivers/gpu/drm/i915/intel_dpll_mgr.c
@@ -303,7 +303,7 @@ intel_reference_shared_dpll(struct intel_shared_dpll *pll,
DRM_DEBUG_DRIVER("using %s for pipe %c\n", pll->info->name,
pipe_name(crtc->pipe));
- shared_dpll[id].crtc_mask |= 1 << crtc->pipe;
+ shared_dpll[id].crtc_mask |= 1 << (drm_crtc_index(&crtc->base));
}
/**
@@ -3285,7 +3285,8 @@ void intel_release_shared_dpll(struct intel_shared_dpll *dpll,
struct intel_shared_dpll_state *shared_dpll_state;
shared_dpll_state = intel_atomic_get_shared_dpll_state(state);
- shared_dpll_state[dpll->info->id].crtc_mask &= ~(1 << crtc->pipe);
+ shared_dpll_state[dpll->info->id].crtc_mask &=
+ ~(1 << drm_crtc_index(&crtc->base));
}
/**
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index d68c5a855b5a..a4b6325c219e 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -1530,6 +1530,9 @@ enum tc_port intel_port_to_tc(struct drm_i915_private *dev_priv,
enum pipe intel_get_pipe_from_connector(struct intel_connector *connector);
int intel_get_pipe_from_crtc_id_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv);
+int get_pipe_from_crtc_index(struct drm_device *dev, unsigned int index, enum pipe *pipe);
+struct intel_crtc *get_intel_crtc_from_index(struct drm_device *dev,
+ unsigned int index);
enum transcoder intel_pipe_to_cpu_transcoder(struct drm_i915_private *dev_priv,
enum pipe pipe);
static inline bool
@@ -1549,7 +1552,12 @@ intel_crtc_has_dp_encoder(const struct intel_crtc_state *crtc_state)
static inline void
intel_wait_for_vblank(struct drm_i915_private *dev_priv, enum pipe pipe)
{
- drm_wait_one_vblank(&dev_priv->drm, pipe);
+ struct intel_crtc *crtc;
+
+ crtc = intel_get_crtc_for_pipe(dev_priv, pipe);
+ if (crtc)
+ drm_wait_one_vblank(&dev_priv->drm,
+ drm_crtc_index(&crtc->base));
}
static inline void
intel_wait_for_vblank_if_active(struct drm_i915_private *dev_priv, int pipe)
diff --git a/drivers/gpu/drm/i915/intel_fifo_underrun.c b/drivers/gpu/drm/i915/intel_fifo_underrun.c
index 77c123cc8817..83ed6f56ed56 100644
--- a/drivers/gpu/drm/i915/intel_fifo_underrun.c
+++ b/drivers/gpu/drm/i915/intel_fifo_underrun.c
@@ -181,11 +181,18 @@ static void broadwell_set_fifo_underrun_reporting(struct drm_device *dev,
enum pipe pipe, bool enable)
{
struct drm_i915_private *dev_priv = to_i915(dev);
+ struct intel_crtc *crtc = intel_get_crtc_for_pipe(dev_priv, pipe);
+ if (!crtc) {
+ DRM_DEBUG("No crtc for pipe=%d\n", pipe);
+ return;
+ }
if (enable)
- bdw_enable_pipe_irq(dev_priv, pipe, GEN8_PIPE_FIFO_UNDERRUN);
+ bdw_enable_pipe_irq(dev_priv, drm_crtc_index(&crtc->base),
+ GEN8_PIPE_FIFO_UNDERRUN);
else
- bdw_disable_pipe_irq(dev_priv, pipe, GEN8_PIPE_FIFO_UNDERRUN);
+ bdw_disable_pipe_irq(dev_priv, drm_crtc_index(&crtc->base),
+ GEN8_PIPE_FIFO_UNDERRUN);
}
static void ibx_set_fifo_underrun_reporting(struct drm_device *dev,
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index 6f27daf76ef5..62d8ab6aabab 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -3757,7 +3757,6 @@ bool intel_can_enable_sagv(struct drm_atomic_state *state)
struct intel_crtc *crtc;
struct intel_plane *plane;
struct intel_crtc_state *cstate;
- enum pipe pipe;
int level, latency;
int sagv_block_time_us;
@@ -3783,8 +3782,10 @@ bool intel_can_enable_sagv(struct drm_atomic_state *state)
return false;
/* Since we're now guaranteed to only have one active CRTC... */
- pipe = ffs(intel_state->active_crtcs) - 1;
- crtc = intel_get_crtc_for_pipe(dev_priv, pipe);
+ crtc = get_intel_crtc_from_index(dev,
+ ffs(intel_state->active_crtcs) - 1);
+ if (!crtc)
+ return false;
cstate = to_intel_crtc_state(crtc->base.state);
if (crtc->base.state->adjusted_mode.flags & DRM_MODE_FLAG_INTERLACE)
--
https://clearlinux.org