Merge branch 'drm-intel-fixes' of git://people.freedesktop.org/~danvet/drm-intel into drm-next
More important fixes for 3.9: - error_state improvements to help debug the new scanline wait code added for gen6+ - bug reports started popping up :( patch from Chris Wilson. - fix a panel power sequence confusion between the eDP and lvds detection code resulting in black screens - regression introduce in 3.8 (Jani Nikula) - Chris fixed the root-cause of the ilk relocation vs. evict bug. - Another piece of cargo-culted rc6 lore from Jani, fixes up a regression where a system refused to go into rc6 after suspend sometimes. * 'drm-intel-fixes' of git://people.freedesktop.org/~danvet/drm-intel: drm/i915: fix FORCEWAKE posting reads drm/i915: Invalidate the relocation presumed_offsets along the slow path drm/i915/eDP: do not write power sequence registers for ghost eDP drm/i915: Record DERRMR, FORCEWAKE and RING_CTL in error-state
This commit is contained in:
commit
ffb5fd53ef
|
@ -641,6 +641,7 @@ static void i915_ring_error_state(struct seq_file *m,
|
|||
seq_printf(m, "%s command stream:\n", ring_str(ring));
|
||||
seq_printf(m, " HEAD: 0x%08x\n", error->head[ring]);
|
||||
seq_printf(m, " TAIL: 0x%08x\n", error->tail[ring]);
|
||||
seq_printf(m, " CTL: 0x%08x\n", error->ctl[ring]);
|
||||
seq_printf(m, " ACTHD: 0x%08x\n", error->acthd[ring]);
|
||||
seq_printf(m, " IPEIR: 0x%08x\n", error->ipeir[ring]);
|
||||
seq_printf(m, " IPEHR: 0x%08x\n", error->ipehr[ring]);
|
||||
|
@ -693,6 +694,8 @@ static int i915_error_state(struct seq_file *m, void *unused)
|
|||
seq_printf(m, "EIR: 0x%08x\n", error->eir);
|
||||
seq_printf(m, "IER: 0x%08x\n", error->ier);
|
||||
seq_printf(m, "PGTBL_ER: 0x%08x\n", error->pgtbl_er);
|
||||
seq_printf(m, "FORCEWAKE: 0x%08x\n", error->forcewake);
|
||||
seq_printf(m, "DERRMR: 0x%08x\n", error->derrmr);
|
||||
seq_printf(m, "CCID: 0x%08x\n", error->ccid);
|
||||
|
||||
for (i = 0; i < dev_priv->num_fence_regs; i++)
|
||||
|
|
|
@ -188,10 +188,13 @@ struct drm_i915_error_state {
|
|||
u32 pgtbl_er;
|
||||
u32 ier;
|
||||
u32 ccid;
|
||||
u32 derrmr;
|
||||
u32 forcewake;
|
||||
bool waiting[I915_NUM_RINGS];
|
||||
u32 pipestat[I915_MAX_PIPES];
|
||||
u32 tail[I915_NUM_RINGS];
|
||||
u32 head[I915_NUM_RINGS];
|
||||
u32 ctl[I915_NUM_RINGS];
|
||||
u32 ipeir[I915_NUM_RINGS];
|
||||
u32 ipehr[I915_NUM_RINGS];
|
||||
u32 instdone[I915_NUM_RINGS];
|
||||
|
|
|
@ -539,6 +539,8 @@ i915_gem_execbuffer_relocate_slow(struct drm_device *dev,
|
|||
total = 0;
|
||||
for (i = 0; i < count; i++) {
|
||||
struct drm_i915_gem_relocation_entry __user *user_relocs;
|
||||
u64 invalid_offset = (u64)-1;
|
||||
int j;
|
||||
|
||||
user_relocs = (void __user *)(uintptr_t)exec[i].relocs_ptr;
|
||||
|
||||
|
@ -549,6 +551,25 @@ i915_gem_execbuffer_relocate_slow(struct drm_device *dev,
|
|||
goto err;
|
||||
}
|
||||
|
||||
/* As we do not update the known relocation offsets after
|
||||
* relocating (due to the complexities in lock handling),
|
||||
* we need to mark them as invalid now so that we force the
|
||||
* relocation processing next time. Just in case the target
|
||||
* object is evicted and then rebound into its old
|
||||
* presumed_offset before the next execbuffer - if that
|
||||
* happened we would make the mistake of assuming that the
|
||||
* relocations were valid.
|
||||
*/
|
||||
for (j = 0; j < exec[i].relocation_count; j++) {
|
||||
if (copy_to_user(&user_relocs[j].presumed_offset,
|
||||
&invalid_offset,
|
||||
sizeof(invalid_offset))) {
|
||||
ret = -EFAULT;
|
||||
mutex_lock(&dev->struct_mutex);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
reloc_offset[i] = total;
|
||||
total += exec[i].relocation_count;
|
||||
}
|
||||
|
|
|
@ -1157,6 +1157,7 @@ static void i915_record_ring_state(struct drm_device *dev,
|
|||
error->acthd[ring->id] = intel_ring_get_active_head(ring);
|
||||
error->head[ring->id] = I915_READ_HEAD(ring);
|
||||
error->tail[ring->id] = I915_READ_TAIL(ring);
|
||||
error->ctl[ring->id] = I915_READ_CTL(ring);
|
||||
|
||||
error->cpu_ring_head[ring->id] = ring->head;
|
||||
error->cpu_ring_tail[ring->id] = ring->tail;
|
||||
|
@ -1251,6 +1252,16 @@ static void i915_capture_error_state(struct drm_device *dev)
|
|||
else
|
||||
error->ier = I915_READ(IER);
|
||||
|
||||
if (INTEL_INFO(dev)->gen >= 6)
|
||||
error->derrmr = I915_READ(DERRMR);
|
||||
|
||||
if (IS_VALLEYVIEW(dev))
|
||||
error->forcewake = I915_READ(FORCEWAKE_VLV);
|
||||
else if (INTEL_INFO(dev)->gen >= 7)
|
||||
error->forcewake = I915_READ(FORCEWAKE_MT);
|
||||
else if (INTEL_INFO(dev)->gen == 6)
|
||||
error->forcewake = I915_READ(FORCEWAKE);
|
||||
|
||||
for_each_pipe(pipe)
|
||||
error->pipestat[pipe] = I915_READ(PIPESTAT(pipe));
|
||||
|
||||
|
|
|
@ -512,6 +512,8 @@
|
|||
#define GEN7_ERR_INT 0x44040
|
||||
#define ERR_INT_MMIO_UNCLAIMED (1<<13)
|
||||
|
||||
#define DERRMR 0x44050
|
||||
|
||||
/* GM45+ chicken bits -- debug workaround bits that may be required
|
||||
* for various sorts of correct behavior. The top 16 bits of each are
|
||||
* the enables for writing to the corresponding low bit.
|
||||
|
|
|
@ -2579,7 +2579,8 @@ intel_dp_add_properties(struct intel_dp *intel_dp, struct drm_connector *connect
|
|||
|
||||
static void
|
||||
intel_dp_init_panel_power_sequencer(struct drm_device *dev,
|
||||
struct intel_dp *intel_dp)
|
||||
struct intel_dp *intel_dp,
|
||||
struct edp_power_seq *out)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
struct edp_power_seq cur, vbt, spec, final;
|
||||
|
@ -2650,16 +2651,35 @@ intel_dp_init_panel_power_sequencer(struct drm_device *dev,
|
|||
intel_dp->panel_power_cycle_delay = get_delay(t11_t12);
|
||||
#undef get_delay
|
||||
|
||||
DRM_DEBUG_KMS("panel power up delay %d, power down delay %d, power cycle delay %d\n",
|
||||
intel_dp->panel_power_up_delay, intel_dp->panel_power_down_delay,
|
||||
intel_dp->panel_power_cycle_delay);
|
||||
|
||||
DRM_DEBUG_KMS("backlight on delay %d, off delay %d\n",
|
||||
intel_dp->backlight_on_delay, intel_dp->backlight_off_delay);
|
||||
|
||||
if (out)
|
||||
*out = final;
|
||||
}
|
||||
|
||||
static void
|
||||
intel_dp_init_panel_power_sequencer_registers(struct drm_device *dev,
|
||||
struct intel_dp *intel_dp,
|
||||
struct edp_power_seq *seq)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
u32 pp_on, pp_off, pp_div;
|
||||
|
||||
/* And finally store the new values in the power sequencer. */
|
||||
pp_on = (final.t1_t3 << PANEL_POWER_UP_DELAY_SHIFT) |
|
||||
(final.t8 << PANEL_LIGHT_ON_DELAY_SHIFT);
|
||||
pp_off = (final.t9 << PANEL_LIGHT_OFF_DELAY_SHIFT) |
|
||||
(final.t10 << PANEL_POWER_DOWN_DELAY_SHIFT);
|
||||
pp_on = (seq->t1_t3 << PANEL_POWER_UP_DELAY_SHIFT) |
|
||||
(seq->t8 << PANEL_LIGHT_ON_DELAY_SHIFT);
|
||||
pp_off = (seq->t9 << PANEL_LIGHT_OFF_DELAY_SHIFT) |
|
||||
(seq->t10 << PANEL_POWER_DOWN_DELAY_SHIFT);
|
||||
/* Compute the divisor for the pp clock, simply match the Bspec
|
||||
* formula. */
|
||||
pp_div = ((100 * intel_pch_rawclk(dev))/2 - 1)
|
||||
<< PP_REFERENCE_DIVIDER_SHIFT;
|
||||
pp_div |= (DIV_ROUND_UP(final.t11_t12, 1000)
|
||||
pp_div |= (DIV_ROUND_UP(seq->t11_t12, 1000)
|
||||
<< PANEL_POWER_CYCLE_DELAY_SHIFT);
|
||||
|
||||
/* Haswell doesn't have any port selection bits for the panel
|
||||
|
@ -2675,14 +2695,6 @@ intel_dp_init_panel_power_sequencer(struct drm_device *dev,
|
|||
I915_WRITE(PCH_PP_OFF_DELAYS, pp_off);
|
||||
I915_WRITE(PCH_PP_DIVISOR, pp_div);
|
||||
|
||||
|
||||
DRM_DEBUG_KMS("panel power up delay %d, power down delay %d, power cycle delay %d\n",
|
||||
intel_dp->panel_power_up_delay, intel_dp->panel_power_down_delay,
|
||||
intel_dp->panel_power_cycle_delay);
|
||||
|
||||
DRM_DEBUG_KMS("backlight on delay %d, off delay %d\n",
|
||||
intel_dp->backlight_on_delay, intel_dp->backlight_off_delay);
|
||||
|
||||
DRM_DEBUG_KMS("panel power sequencer register settings: PP_ON %#x, PP_OFF %#x, PP_DIV %#x\n",
|
||||
I915_READ(PCH_PP_ON_DELAYS),
|
||||
I915_READ(PCH_PP_OFF_DELAYS),
|
||||
|
@ -2699,6 +2711,7 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port,
|
|||
struct drm_device *dev = intel_encoder->base.dev;
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
struct drm_display_mode *fixed_mode = NULL;
|
||||
struct edp_power_seq power_seq = { 0 };
|
||||
enum port port = intel_dig_port->port;
|
||||
const char *name = NULL;
|
||||
int type;
|
||||
|
@ -2771,7 +2784,7 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port,
|
|||
}
|
||||
|
||||
if (is_edp(intel_dp))
|
||||
intel_dp_init_panel_power_sequencer(dev, intel_dp);
|
||||
intel_dp_init_panel_power_sequencer(dev, intel_dp, &power_seq);
|
||||
|
||||
intel_dp_i2c_init(intel_dp, intel_connector, name);
|
||||
|
||||
|
@ -2798,6 +2811,10 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port,
|
|||
return;
|
||||
}
|
||||
|
||||
/* We now know it's not a ghost, init power sequence regs. */
|
||||
intel_dp_init_panel_power_sequencer_registers(dev, intel_dp,
|
||||
&power_seq);
|
||||
|
||||
ironlake_edp_panel_vdd_on(intel_dp);
|
||||
edid = drm_get_edid(connector, &intel_dp->adapter);
|
||||
if (edid) {
|
||||
|
|
|
@ -4250,7 +4250,8 @@ static void __gen6_gt_force_wake_get(struct drm_i915_private *dev_priv)
|
|||
static void __gen6_gt_force_wake_mt_reset(struct drm_i915_private *dev_priv)
|
||||
{
|
||||
I915_WRITE_NOTRACE(FORCEWAKE_MT, _MASKED_BIT_DISABLE(0xffff));
|
||||
POSTING_READ(ECOBUS); /* something from same cacheline, but !FORCEWAKE */
|
||||
/* something from same cacheline, but !FORCEWAKE_MT */
|
||||
POSTING_READ(ECOBUS);
|
||||
}
|
||||
|
||||
static void __gen6_gt_force_wake_mt_get(struct drm_i915_private *dev_priv)
|
||||
|
@ -4267,7 +4268,8 @@ static void __gen6_gt_force_wake_mt_get(struct drm_i915_private *dev_priv)
|
|||
DRM_ERROR("Timed out waiting for forcewake old ack to clear.\n");
|
||||
|
||||
I915_WRITE_NOTRACE(FORCEWAKE_MT, _MASKED_BIT_ENABLE(FORCEWAKE_KERNEL));
|
||||
POSTING_READ(ECOBUS); /* something from same cacheline, but !FORCEWAKE */
|
||||
/* something from same cacheline, but !FORCEWAKE_MT */
|
||||
POSTING_READ(ECOBUS);
|
||||
|
||||
if (wait_for_atomic((I915_READ_NOTRACE(forcewake_ack) & 1),
|
||||
FORCEWAKE_ACK_TIMEOUT_MS))
|
||||
|
@ -4304,14 +4306,16 @@ void gen6_gt_check_fifodbg(struct drm_i915_private *dev_priv)
|
|||
static void __gen6_gt_force_wake_put(struct drm_i915_private *dev_priv)
|
||||
{
|
||||
I915_WRITE_NOTRACE(FORCEWAKE, 0);
|
||||
/* gen6_gt_check_fifodbg doubles as the POSTING_READ */
|
||||
/* something from same cacheline, but !FORCEWAKE */
|
||||
POSTING_READ(ECOBUS);
|
||||
gen6_gt_check_fifodbg(dev_priv);
|
||||
}
|
||||
|
||||
static void __gen6_gt_force_wake_mt_put(struct drm_i915_private *dev_priv)
|
||||
{
|
||||
I915_WRITE_NOTRACE(FORCEWAKE_MT, _MASKED_BIT_DISABLE(FORCEWAKE_KERNEL));
|
||||
/* gen6_gt_check_fifodbg doubles as the POSTING_READ */
|
||||
/* something from same cacheline, but !FORCEWAKE_MT */
|
||||
POSTING_READ(ECOBUS);
|
||||
gen6_gt_check_fifodbg(dev_priv);
|
||||
}
|
||||
|
||||
|
@ -4351,6 +4355,8 @@ int __gen6_gt_wait_for_fifo(struct drm_i915_private *dev_priv)
|
|||
static void vlv_force_wake_reset(struct drm_i915_private *dev_priv)
|
||||
{
|
||||
I915_WRITE_NOTRACE(FORCEWAKE_VLV, _MASKED_BIT_DISABLE(0xffff));
|
||||
/* something from same cacheline, but !FORCEWAKE_VLV */
|
||||
POSTING_READ(FORCEWAKE_ACK_VLV);
|
||||
}
|
||||
|
||||
static void vlv_force_wake_get(struct drm_i915_private *dev_priv)
|
||||
|
@ -4371,7 +4377,8 @@ static void vlv_force_wake_get(struct drm_i915_private *dev_priv)
|
|||
static void vlv_force_wake_put(struct drm_i915_private *dev_priv)
|
||||
{
|
||||
I915_WRITE_NOTRACE(FORCEWAKE_VLV, _MASKED_BIT_DISABLE(FORCEWAKE_KERNEL));
|
||||
/* The below doubles as a POSTING_READ */
|
||||
/* something from same cacheline, but !FORCEWAKE_VLV */
|
||||
POSTING_READ(FORCEWAKE_ACK_VLV);
|
||||
gen6_gt_check_fifodbg(dev_priv);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue