aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/i915/intel_engine_cs.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/i915/intel_engine_cs.c')
-rw-r--r--drivers/gpu/drm/i915/intel_engine_cs.c88
1 files changed, 49 insertions, 39 deletions
diff --git a/drivers/gpu/drm/i915/intel_engine_cs.c b/drivers/gpu/drm/i915/intel_engine_cs.c
index ff5b7bc692ce..236cd040f271 100644
--- a/drivers/gpu/drm/i915/intel_engine_cs.c
+++ b/drivers/gpu/drm/i915/intel_engine_cs.c
@@ -261,6 +261,31 @@ static void __sprint_engine_name(char *name, const struct engine_info *info)
info->instance) >= INTEL_ENGINE_CS_MAX_NAME);
}
+void intel_engine_set_hwsp_writemask(struct intel_engine_cs *engine, u32 mask)
+{
+ struct drm_i915_private *dev_priv = engine->i915;
+ i915_reg_t hwstam;
+
+ /*
+ * Though they added more rings on g4x/ilk, they did not add
+ * per-engine HWSTAM until gen6.
+ */
+ if (INTEL_GEN(dev_priv) < 6 && engine->class != RENDER_CLASS)
+ return;
+
+ hwstam = RING_HWSTAM(engine->mmio_base);
+ if (INTEL_GEN(dev_priv) >= 3)
+ I915_WRITE(hwstam, mask);
+ else
+ I915_WRITE16(hwstam, mask);
+}
+
+static void intel_engine_sanitize_mmio(struct intel_engine_cs *engine)
+{
+ /* Mask off all writes into the unknown HWSP */
+ intel_engine_set_hwsp_writemask(engine, ~0u);
+}
+
static int
intel_engine_setup(struct drm_i915_private *dev_priv,
enum intel_engine_id id)
@@ -312,6 +337,9 @@ intel_engine_setup(struct drm_i915_private *dev_priv,
ATOMIC_INIT_NOTIFIER_HEAD(&engine->context_status_notifier);
+ /* Scrub mmio state on takeover */
+ intel_engine_sanitize_mmio(engine);
+
dev_priv->engine_class[info->class][info->instance] = engine;
dev_priv->engine[id] = engine;
return 0;
@@ -365,7 +393,7 @@ int intel_engines_init_mmio(struct drm_i915_private *dev_priv)
goto cleanup;
}
- device_info->num_rings = hweight32(mask);
+ RUNTIME_INFO(dev_priv)->num_rings = hweight32(mask);
i915_check_and_clear_faults(dev_priv);
@@ -426,27 +454,9 @@ cleanup:
return err;
}
-void intel_engine_init_global_seqno(struct intel_engine_cs *engine, u32 seqno)
+void intel_engine_write_global_seqno(struct intel_engine_cs *engine, u32 seqno)
{
- struct drm_i915_private *dev_priv = engine->i915;
-
- /* Our semaphore implementation is strictly monotonic (i.e. we proceed
- * so long as the semaphore value in the register/page is greater
- * than the sync value), so whenever we reset the seqno,
- * so long as we reset the tracking semaphore value to 0, it will
- * always be before the next request's seqno. If we don't reset
- * the semaphore value, then when the seqno moves backwards all
- * future waits will complete instantly (causing rendering corruption).
- */
- if (IS_GEN6(dev_priv) || IS_GEN7(dev_priv)) {
- I915_WRITE(RING_SYNC_0(engine->mmio_base), 0);
- I915_WRITE(RING_SYNC_1(engine->mmio_base), 0);
- if (HAS_VEBOX(dev_priv))
- I915_WRITE(RING_SYNC_2(engine->mmio_base), 0);
- }
-
intel_write_status_page(engine, I915_GEM_HWS_INDEX, seqno);
- clear_bit(ENGINE_IRQ_BREADCRUMB, &engine->irq_posted);
/* After manually advancing the seqno, fake the interrupt in case
* there are any waiters for that seqno.
@@ -495,6 +505,9 @@ void intel_engine_setup_common(struct intel_engine_cs *engine)
static void cleanup_status_page(struct intel_engine_cs *engine)
{
+ /* Prevent writes into HWSP after returning the page to the system */
+ intel_engine_set_hwsp_writemask(engine, ~0u);
+
if (HWS_NEEDS_PHYSICAL(engine->i915)) {
void *addr = fetch_and_zero(&engine->status_page.page_addr);
@@ -769,12 +782,12 @@ const char *i915_cache_level_str(struct drm_i915_private *i915, int type)
u32 intel_calculate_mcr_s_ss_select(struct drm_i915_private *dev_priv)
{
- const struct sseu_dev_info *sseu = &(INTEL_INFO(dev_priv)->sseu);
+ const struct sseu_dev_info *sseu = &RUNTIME_INFO(dev_priv)->sseu;
u32 mcr_s_ss_select;
u32 slice = fls(sseu->slice_mask);
u32 subslice = fls(sseu->subslice_mask[slice]);
- if (IS_GEN10(dev_priv))
+ if (IS_GEN(dev_priv, 10))
mcr_s_ss_select = GEN8_MCR_SLICE(slice) |
GEN8_MCR_SUBSLICE(subslice);
else if (INTEL_GEN(dev_priv) >= 11)
@@ -1030,22 +1043,34 @@ void intel_engines_reset_default_submission(struct drm_i915_private *i915)
engine->set_default_submission(engine);
}
+static bool reset_engines(struct drm_i915_private *i915)
+{
+ if (INTEL_INFO(i915)->gpu_reset_clobbers_display)
+ return false;
+
+ return intel_gpu_reset(i915, ALL_ENGINES) == 0;
+}
+
/**
* intel_engines_sanitize: called after the GPU has lost power
* @i915: the i915 device
+ * @force: ignore a failed reset and sanitize engine state anyway
*
* Anytime we reset the GPU, either with an explicit GPU reset or through a
* PCI power cycle, the GPU loses state and we must reset our state tracking
* to match. Note that calling intel_engines_sanitize() if the GPU has not
* been reset results in much confusion!
*/
-void intel_engines_sanitize(struct drm_i915_private *i915)
+void intel_engines_sanitize(struct drm_i915_private *i915, bool force)
{
struct intel_engine_cs *engine;
enum intel_engine_id id;
GEM_TRACE("\n");
+ if (!reset_engines(i915) && !force)
+ return;
+
for_each_engine(engine, i915, id) {
if (engine->reset.reset)
engine->reset.reset(engine, NULL);
@@ -1248,7 +1273,7 @@ static void intel_engine_print_registers(const struct intel_engine_cs *engine,
&engine->execlists;
u64 addr;
- if (engine->id == RCS && IS_GEN(dev_priv, 4, 7))
+ if (engine->id == RCS && IS_GEN_RANGE(dev_priv, 4, 7))
drm_printf(m, "\tCCID: 0x%08x\n", I915_READ(CCID));
drm_printf(m, "\tRING_START: 0x%08x\n",
I915_READ(RING_START(engine->mmio_base)));
@@ -1269,16 +1294,6 @@ static void intel_engine_print_registers(const struct intel_engine_cs *engine,
drm_printf(m, "\tRING_IMR: %08x\n", I915_READ_IMR(engine));
}
- if (HAS_LEGACY_SEMAPHORES(dev_priv)) {
- drm_printf(m, "\tSYNC_0: 0x%08x\n",
- I915_READ(RING_SYNC_0(engine->mmio_base)));
- drm_printf(m, "\tSYNC_1: 0x%08x\n",
- I915_READ(RING_SYNC_1(engine->mmio_base)));
- if (HAS_VEBOX(dev_priv))
- drm_printf(m, "\tSYNC_2: 0x%08x\n",
- I915_READ(RING_SYNC_2(engine->mmio_base)));
- }
-
addr = intel_engine_get_active_head(engine);
drm_printf(m, "\tACTHD: 0x%08x_%08x\n",
upper_32_bits(addr), lower_32_bits(addr));
@@ -1532,11 +1547,6 @@ void intel_engine_dump(struct intel_engine_cs *engine,
spin_unlock(&b->rb_lock);
local_irq_restore(flags);
- drm_printf(m, "IRQ? 0x%lx (breadcrumbs? %s)\n",
- engine->irq_posted,
- yesno(test_bit(ENGINE_IRQ_BREADCRUMB,
- &engine->irq_posted)));
-
drm_printf(m, "HWSP:\n");
hexdump(m, engine->status_page.page_addr, PAGE_SIZE);