Commit 1a5788bf authored by Chris Wilson's avatar Chris Wilson

drm/i915: Onion unwind for intel_init_ring_common()

Rather than call intel_engine_cleanup() with a partially constructed
engine, unwind the error during intel_init_ring_common().
Signed-off-by: default avatarChris Wilson <chris@chris-wilson.co.uk>
Cc: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
Link: http://patchwork.freedesktop.org/patch/msgid/20170403113426.25707-2-chris@chris-wilson.co.ukReviewed-by: default avatarJoonas Lahtinen <joonas.lahtinen@linux.intel.com>
parent d822bb18
...@@ -1259,6 +1259,8 @@ static int init_phys_status_page(struct intel_engine_cs *engine) ...@@ -1259,6 +1259,8 @@ static int init_phys_status_page(struct intel_engine_cs *engine)
{ {
struct drm_i915_private *dev_priv = engine->i915; struct drm_i915_private *dev_priv = engine->i915;
GEM_BUG_ON(engine->id != RCS);
dev_priv->status_page_dmah = dev_priv->status_page_dmah =
drm_pci_alloc(&dev_priv->drm, PAGE_SIZE, PAGE_SIZE); drm_pci_alloc(&dev_priv->drm, PAGE_SIZE, PAGE_SIZE);
if (!dev_priv->status_page_dmah) if (!dev_priv->status_page_dmah)
...@@ -1481,76 +1483,69 @@ static void intel_ring_context_unpin(struct intel_engine_cs *engine, ...@@ -1481,76 +1483,69 @@ static void intel_ring_context_unpin(struct intel_engine_cs *engine,
static int intel_init_ring_buffer(struct intel_engine_cs *engine) static int intel_init_ring_buffer(struct intel_engine_cs *engine)
{ {
struct intel_ring *ring; struct intel_ring *ring;
int ret; int err;
WARN_ON(engine->buffer);
intel_engine_setup_common(engine); intel_engine_setup_common(engine);
ret = intel_engine_init_common(engine); err = intel_engine_init_common(engine);
if (ret) if (err)
goto error; goto err;
if (HWS_NEEDS_PHYSICAL(engine->i915)) { if (HWS_NEEDS_PHYSICAL(engine->i915))
WARN_ON(engine->id != RCS); err = init_phys_status_page(engine);
ret = init_phys_status_page(engine); else
if (ret) err = init_status_page(engine);
goto error; if (err)
} else { goto err;
ret = init_status_page(engine);
if (ret)
goto error;
}
ring = intel_engine_create_ring(engine, 32 * PAGE_SIZE); ring = intel_engine_create_ring(engine, 32 * PAGE_SIZE);
if (IS_ERR(ring)) { if (IS_ERR(ring)) {
ret = PTR_ERR(ring); err = PTR_ERR(ring);
goto error; goto err_hws;
} }
/* Ring wraparound at offset 0 sometimes hangs. No idea why. */ /* Ring wraparound at offset 0 sometimes hangs. No idea why. */
ret = intel_ring_pin(ring, engine->i915, I915_GTT_PAGE_SIZE); err = intel_ring_pin(ring, engine->i915, I915_GTT_PAGE_SIZE);
if (ret) { if (err)
intel_ring_free(ring); goto err_ring;
goto error;
} GEM_BUG_ON(engine->buffer);
engine->buffer = ring; engine->buffer = ring;
return 0; return 0;
error: err_ring:
intel_engine_cleanup(engine); intel_ring_free(ring);
return ret; err_hws:
if (HWS_NEEDS_PHYSICAL(engine->i915))
cleanup_phys_status_page(engine);
else
cleanup_status_page(engine);
err:
intel_engine_cleanup_common(engine);
return err;
} }
void intel_engine_cleanup(struct intel_engine_cs *engine) void intel_engine_cleanup(struct intel_engine_cs *engine)
{ {
struct drm_i915_private *dev_priv; struct drm_i915_private *dev_priv = engine->i915;
dev_priv = engine->i915;
if (engine->buffer) {
WARN_ON(INTEL_GEN(dev_priv) > 2 && WARN_ON(INTEL_GEN(dev_priv) > 2 &&
(I915_READ_MODE(engine) & MODE_IDLE) == 0); (I915_READ_MODE(engine) & MODE_IDLE) == 0);
intel_ring_unpin(engine->buffer); intel_ring_unpin(engine->buffer);
intel_ring_free(engine->buffer); intel_ring_free(engine->buffer);
engine->buffer = NULL;
}
if (engine->cleanup) if (engine->cleanup)
engine->cleanup(engine); engine->cleanup(engine);
if (HWS_NEEDS_PHYSICAL(dev_priv)) { if (HWS_NEEDS_PHYSICAL(dev_priv))
WARN_ON(engine->id != RCS);
cleanup_phys_status_page(engine); cleanup_phys_status_page(engine);
} else { else
cleanup_status_page(engine); cleanup_status_page(engine);
}
intel_engine_cleanup_common(engine); intel_engine_cleanup_common(engine);
engine->i915 = NULL;
dev_priv->engine[engine->id] = NULL; dev_priv->engine[engine->id] = NULL;
kfree(engine); kfree(engine);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment