Skip to content

Commit

Permalink
Merge tag 'drm-intel-fixes-2019-12-12' of git://anongit.freedesktop.o…
Browse files Browse the repository at this point in the history
…rg/drm/drm-intel into drm-fixes

- Fix user reported issue #673: GPU hang on transition to idle
- Avoid corruption on the top of the screen on GLK+ by disabling FBC
- Fix non-privileged access to OA on Tigerlake
- Fix HDCP code not to touch global state when just computing commit
- Fix CI splat by saving irqstate around virtual_context_destroy
- Serialise context retirement possibly on another CPU

Signed-off-by: Dave Airlie <airlied@redhat.com>
From: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20191212100759.GA22260@jlahtine-desk.ger.corp.intel.com
  • Loading branch information
airlied committed Dec 13, 2019
2 parents 7315c0e + 750bde2 commit 82e50ec
Show file tree
Hide file tree
Showing 9 changed files with 177 additions and 148 deletions.
5 changes: 4 additions & 1 deletion drivers/gpu/drm/i915/display/intel_ddi.c
Original file line number Diff line number Diff line change
Expand Up @@ -3986,6 +3986,7 @@ static void intel_enable_ddi(struct intel_encoder *encoder,
if (conn_state->content_protection ==
DRM_MODE_CONTENT_PROTECTION_DESIRED)
intel_hdcp_enable(to_intel_connector(conn_state->connector),
crtc_state->cpu_transcoder,
(u8)conn_state->hdcp_content_type);
}

Expand Down Expand Up @@ -4089,7 +4090,9 @@ static void intel_ddi_update_pipe(struct intel_encoder *encoder,
if (conn_state->content_protection ==
DRM_MODE_CONTENT_PROTECTION_DESIRED ||
content_protection_type_changed)
intel_hdcp_enable(connector, (u8)conn_state->hdcp_content_type);
intel_hdcp_enable(connector,
crtc_state->cpu_transcoder,
(u8)conn_state->hdcp_content_type);
}

static void
Expand Down
3 changes: 0 additions & 3 deletions drivers/gpu/drm/i915/display/intel_dp.c
Original file line number Diff line number Diff line change
Expand Up @@ -2414,9 +2414,6 @@ intel_dp_compute_config(struct intel_encoder *encoder,

intel_psr_compute_config(intel_dp, pipe_config);

intel_hdcp_transcoder_config(intel_connector,
pipe_config->cpu_transcoder);

return 0;
}

Expand Down
2 changes: 1 addition & 1 deletion drivers/gpu/drm/i915/display/intel_fbc.c
Original file line number Diff line number Diff line change
Expand Up @@ -1284,7 +1284,7 @@ static int intel_sanitize_fbc_option(struct drm_i915_private *dev_priv)
return 0;

/* https://bugs.freedesktop.org/show_bug.cgi?id=108085 */
if (IS_GEMINILAKE(dev_priv))
if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv))
return 0;

if (IS_BROADWELL(dev_priv) || INTEL_GEN(dev_priv) >= 9)
Expand Down
26 changes: 8 additions & 18 deletions drivers/gpu/drm/i915/display/intel_hdcp.c
Original file line number Diff line number Diff line change
Expand Up @@ -1821,23 +1821,6 @@ enum mei_fw_tc intel_get_mei_fw_tc(enum transcoder cpu_transcoder)
}
}

void intel_hdcp_transcoder_config(struct intel_connector *connector,
enum transcoder cpu_transcoder)
{
struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
struct intel_hdcp *hdcp = &connector->hdcp;

if (!hdcp->shim)
return;

if (INTEL_GEN(dev_priv) >= 12) {
mutex_lock(&hdcp->mutex);
hdcp->cpu_transcoder = cpu_transcoder;
hdcp->port_data.fw_tc = intel_get_mei_fw_tc(cpu_transcoder);
mutex_unlock(&hdcp->mutex);
}
}

static inline int initialize_hdcp_port_data(struct intel_connector *connector,
const struct intel_hdcp_shim *shim)
{
Expand Down Expand Up @@ -1959,8 +1942,10 @@ int intel_hdcp_init(struct intel_connector *connector,
return 0;
}

int intel_hdcp_enable(struct intel_connector *connector, u8 content_type)
int intel_hdcp_enable(struct intel_connector *connector,
enum transcoder cpu_transcoder, u8 content_type)
{
struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
struct intel_hdcp *hdcp = &connector->hdcp;
unsigned long check_link_interval = DRM_HDCP_CHECK_PERIOD_MS;
int ret = -EINVAL;
Expand All @@ -1972,6 +1957,11 @@ int intel_hdcp_enable(struct intel_connector *connector, u8 content_type)
WARN_ON(hdcp->value == DRM_MODE_CONTENT_PROTECTION_ENABLED);
hdcp->content_type = content_type;

if (INTEL_GEN(dev_priv) >= 12) {
hdcp->cpu_transcoder = cpu_transcoder;
hdcp->port_data.fw_tc = intel_get_mei_fw_tc(cpu_transcoder);
}

/*
* Considering that HDCP2.2 is more secure than HDCP1.4, If the setup
* is capable of HDCP2.2, it is preferred to use HDCP2.2.
Expand Down
5 changes: 2 additions & 3 deletions drivers/gpu/drm/i915/display/intel_hdcp.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,10 @@ enum transcoder;
void intel_hdcp_atomic_check(struct drm_connector *connector,
struct drm_connector_state *old_state,
struct drm_connector_state *new_state);
void intel_hdcp_transcoder_config(struct intel_connector *connector,
enum transcoder cpu_transcoder);
int intel_hdcp_init(struct intel_connector *connector,
const struct intel_hdcp_shim *hdcp_shim);
int intel_hdcp_enable(struct intel_connector *connector, u8 content_type);
int intel_hdcp_enable(struct intel_connector *connector,
enum transcoder cpu_transcoder, u8 content_type);
int intel_hdcp_disable(struct intel_connector *connector);
bool is_hdcp_supported(struct drm_i915_private *dev_priv, enum port port);
bool intel_hdcp_capable(struct intel_connector *connector);
Expand Down
3 changes: 0 additions & 3 deletions drivers/gpu/drm/i915/display/intel_hdmi.c
Original file line number Diff line number Diff line change
Expand Up @@ -2489,9 +2489,6 @@ int intel_hdmi_compute_config(struct intel_encoder *encoder,
return -EINVAL;
}

intel_hdcp_transcoder_config(intel_hdmi->attached_connector,
pipe_config->cpu_transcoder);

return 0;
}

Expand Down
51 changes: 24 additions & 27 deletions drivers/gpu/drm/i915/gt/intel_lrc.c
Original file line number Diff line number Diff line change
Expand Up @@ -845,12 +845,6 @@ static const u8 *reg_offsets(const struct intel_engine_cs *engine)
}
}

static void unwind_wa_tail(struct i915_request *rq)
{
rq->tail = intel_ring_wrap(rq->ring, rq->wa_tail - WA_TAIL_BYTES);
assert_ring_tail_valid(rq->ring, rq->tail);
}

static struct i915_request *
__unwind_incomplete_requests(struct intel_engine_cs *engine)
{
Expand All @@ -863,12 +857,10 @@ __unwind_incomplete_requests(struct intel_engine_cs *engine)
list_for_each_entry_safe_reverse(rq, rn,
&engine->active.requests,
sched.link) {

if (i915_request_completed(rq))
continue; /* XXX */

__i915_request_unsubmit(rq);
unwind_wa_tail(rq);

/*
* Push the request back into the queue for later resubmission.
Expand Down Expand Up @@ -1161,13 +1153,29 @@ execlists_schedule_out(struct i915_request *rq)
i915_request_put(rq);
}

static u64 execlists_update_context(const struct i915_request *rq)
static u64 execlists_update_context(struct i915_request *rq)
{
struct intel_context *ce = rq->hw_context;
u64 desc;
u64 desc = ce->lrc_desc;
u32 tail;

ce->lrc_reg_state[CTX_RING_TAIL] =
intel_ring_set_tail(rq->ring, rq->tail);
/*
* WaIdleLiteRestore:bdw,skl
*
* We should never submit the context with the same RING_TAIL twice
* just in case we submit an empty ring, which confuses the HW.
*
* We append a couple of NOOPs (gen8_emit_wa_tail) after the end of
* the normal request to be able to always advance the RING_TAIL on
* subsequent resubmissions (for lite restore). Should that fail us,
* and we try and submit the same tail again, force the context
* reload.
*/
tail = intel_ring_set_tail(rq->ring, rq->tail);
if (unlikely(ce->lrc_reg_state[CTX_RING_TAIL] == tail))
desc |= CTX_DESC_FORCE_RESTORE;
ce->lrc_reg_state[CTX_RING_TAIL] = tail;
rq->tail = rq->wa_tail;

/*
* Make sure the context image is complete before we submit it to HW.
Expand All @@ -1186,13 +1194,11 @@ static u64 execlists_update_context(const struct i915_request *rq)
*/
mb();

desc = ce->lrc_desc;
ce->lrc_desc &= ~CTX_DESC_FORCE_RESTORE;

/* Wa_1607138340:tgl */
if (IS_TGL_REVID(rq->i915, TGL_REVID_A0, TGL_REVID_A0))
desc |= CTX_DESC_FORCE_RESTORE;

ce->lrc_desc &= ~CTX_DESC_FORCE_RESTORE;
return desc;
}

Expand Down Expand Up @@ -1703,16 +1709,6 @@ static void execlists_dequeue(struct intel_engine_cs *engine)

return;
}

/*
* WaIdleLiteRestore:bdw,skl
* Apply the wa NOOPs to prevent
* ring:HEAD == rq:TAIL as we resubmit the
* request. See gen8_emit_fini_breadcrumb() for
* where we prepare the padding after the
* end of the request.
*/
last->tail = last->wa_tail;
}
}

Expand Down Expand Up @@ -4120,17 +4116,18 @@ static void virtual_context_destroy(struct kref *kref)
for (n = 0; n < ve->num_siblings; n++) {
struct intel_engine_cs *sibling = ve->siblings[n];
struct rb_node *node = &ve->nodes[sibling->id].rb;
unsigned long flags;

if (RB_EMPTY_NODE(node))
continue;

spin_lock_irq(&sibling->active.lock);
spin_lock_irqsave(&sibling->active.lock, flags);

/* Detachment is lazily performed in the execlists tasklet */
if (!RB_EMPTY_NODE(node))
rb_erase_cached(node, &sibling->execlists.virtual);

spin_unlock_irq(&sibling->active.lock);
spin_unlock_irqrestore(&sibling->active.lock, flags);
}
GEM_BUG_ON(__tasklet_is_scheduled(&ve->base.execlists.tasklet));

Expand Down
26 changes: 23 additions & 3 deletions drivers/gpu/drm/i915/i915_gem.c
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
#include "gem/i915_gem_context.h"
#include "gem/i915_gem_ioctls.h"
#include "gem/i915_gem_pm.h"
#include "gt/intel_context.h"
#include "gt/intel_engine_user.h"
#include "gt/intel_gt.h"
#include "gt/intel_gt_pm.h"
Expand Down Expand Up @@ -1053,6 +1054,18 @@ i915_gem_madvise_ioctl(struct drm_device *dev, void *data,
return err;
}

static int __intel_context_flush_retire(struct intel_context *ce)
{
struct intel_timeline *tl;

tl = intel_context_timeline_lock(ce);
if (IS_ERR(tl))
return PTR_ERR(tl);

intel_context_timeline_unlock(tl);
return 0;
}

static int __intel_engines_record_defaults(struct intel_gt *gt)
{
struct i915_request *requests[I915_NUM_ENGINES] = {};
Expand Down Expand Up @@ -1121,13 +1134,20 @@ static int __intel_engines_record_defaults(struct intel_gt *gt)
if (!rq)
continue;

/* We want to be able to unbind the state from the GGTT */
GEM_BUG_ON(intel_context_is_pinned(rq->hw_context));

GEM_BUG_ON(!test_bit(CONTEXT_ALLOC_BIT,
&rq->hw_context->flags));
state = rq->hw_context->state;
if (!state)
continue;

/* Serialise with retirement on another CPU */
err = __intel_context_flush_retire(rq->hw_context);
if (err)
goto out;

/* We want to be able to unbind the state from the GGTT */
GEM_BUG_ON(intel_context_is_pinned(rq->hw_context));

/*
* As we will hold a reference to the logical state, it will
* not be torn down with the context, and importantly the
Expand Down
Loading

0 comments on commit 82e50ec

Please sign in to comment.