diff options
author | Chris Wilson <chris@chris-wilson.co.uk> | 2017-04-03 07:34:26 -0400 |
---|---|---|
committer | Chris Wilson <chris@chris-wilson.co.uk> | 2017-04-03 08:53:14 -0400 |
commit | 1a5788bf2729c6e98444c7f56f960957694472c2 (patch) | |
tree | 9f20cb72e891fc6397e4d5a23df2bea927acaa33 /drivers/gpu/drm/i915/intel_ringbuffer.c | |
parent | d822bb18ce96391245d877d5bada8913b88a15cf (diff) |
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: Chris 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.uk
Reviewed-by: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
Diffstat (limited to 'drivers/gpu/drm/i915/intel_ringbuffer.c')
-rw-r--r-- | drivers/gpu/drm/i915/intel_ringbuffer.c | 77 |
1 files changed, 36 insertions, 41 deletions
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index 5e7634c00cbd..c98acc27279a 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c | |||
@@ -1259,6 +1259,8 @@ static int init_phys_status_page(struct intel_engine_cs *engine) | |||
1259 | { | 1259 | { |
1260 | struct drm_i915_private *dev_priv = engine->i915; | 1260 | struct drm_i915_private *dev_priv = engine->i915; |
1261 | 1261 | ||
1262 | GEM_BUG_ON(engine->id != RCS); | ||
1263 | |||
1262 | dev_priv->status_page_dmah = | 1264 | dev_priv->status_page_dmah = |
1263 | drm_pci_alloc(&dev_priv->drm, PAGE_SIZE, PAGE_SIZE); | 1265 | drm_pci_alloc(&dev_priv->drm, PAGE_SIZE, PAGE_SIZE); |
1264 | if (!dev_priv->status_page_dmah) | 1266 | if (!dev_priv->status_page_dmah) |
@@ -1481,76 +1483,69 @@ static void intel_ring_context_unpin(struct intel_engine_cs *engine, | |||
1481 | static int intel_init_ring_buffer(struct intel_engine_cs *engine) | 1483 | static int intel_init_ring_buffer(struct intel_engine_cs *engine) |
1482 | { | 1484 | { |
1483 | struct intel_ring *ring; | 1485 | struct intel_ring *ring; |
1484 | int ret; | 1486 | int err; |
1485 | |||
1486 | WARN_ON(engine->buffer); | ||
1487 | 1487 | ||
1488 | intel_engine_setup_common(engine); | 1488 | intel_engine_setup_common(engine); |
1489 | 1489 | ||
1490 | ret = intel_engine_init_common(engine); | 1490 | err = intel_engine_init_common(engine); |
1491 | if (ret) | 1491 | if (err) |
1492 | goto error; | 1492 | goto err; |
1493 | 1493 | ||
1494 | if (HWS_NEEDS_PHYSICAL(engine->i915)) { | 1494 | if (HWS_NEEDS_PHYSICAL(engine->i915)) |
1495 | WARN_ON(engine->id != RCS); | 1495 | err = init_phys_status_page(engine); |
1496 | ret = init_phys_status_page(engine); | 1496 | else |
1497 | if (ret) | 1497 | err = init_status_page(engine); |
1498 | goto error; | 1498 | if (err) |
1499 | } else { | 1499 | goto err; |
1500 | ret = init_status_page(engine); | ||
1501 | if (ret) | ||
1502 | goto error; | ||
1503 | } | ||
1504 | 1500 | ||
1505 | ring = intel_engine_create_ring(engine, 32 * PAGE_SIZE); | 1501 | ring = intel_engine_create_ring(engine, 32 * PAGE_SIZE); |
1506 | if (IS_ERR(ring)) { | 1502 | if (IS_ERR(ring)) { |
1507 | ret = PTR_ERR(ring); | 1503 | err = PTR_ERR(ring); |
1508 | goto error; | 1504 | goto err_hws; |
1509 | } | 1505 | } |
1510 | 1506 | ||
1511 | /* Ring wraparound at offset 0 sometimes hangs. No idea why. */ | 1507 | /* Ring wraparound at offset 0 sometimes hangs. No idea why. */ |
1512 | ret = intel_ring_pin(ring, engine->i915, I915_GTT_PAGE_SIZE); | 1508 | err = intel_ring_pin(ring, engine->i915, I915_GTT_PAGE_SIZE); |
1513 | if (ret) { | 1509 | if (err) |
1514 | intel_ring_free(ring); | 1510 | goto err_ring; |
1515 | goto error; | 1511 | |
1516 | } | 1512 | GEM_BUG_ON(engine->buffer); |
1517 | engine->buffer = ring; | 1513 | engine->buffer = ring; |
1518 | 1514 | ||
1519 | return 0; | 1515 | return 0; |
1520 | 1516 | ||
1521 | error: | 1517 | err_ring: |
1522 | intel_engine_cleanup(engine); | 1518 | intel_ring_free(ring); |
1523 | return ret; | 1519 | err_hws: |
1520 | if (HWS_NEEDS_PHYSICAL(engine->i915)) | ||
1521 | cleanup_phys_status_page(engine); | ||
1522 | else | ||
1523 | cleanup_status_page(engine); | ||
1524 | err: | ||
1525 | intel_engine_cleanup_common(engine); | ||
1526 | return err; | ||
1524 | } | 1527 | } |
1525 | 1528 | ||
1526 | void intel_engine_cleanup(struct intel_engine_cs *engine) | 1529 | void intel_engine_cleanup(struct intel_engine_cs *engine) |
1527 | { | 1530 | { |
1528 | struct drm_i915_private *dev_priv; | 1531 | struct drm_i915_private *dev_priv = engine->i915; |
1529 | |||
1530 | dev_priv = engine->i915; | ||
1531 | 1532 | ||
1532 | if (engine->buffer) { | 1533 | WARN_ON(INTEL_GEN(dev_priv) > 2 && |
1533 | WARN_ON(INTEL_GEN(dev_priv) > 2 && | 1534 | (I915_READ_MODE(engine) & MODE_IDLE) == 0); |
1534 | (I915_READ_MODE(engine) & MODE_IDLE) == 0); | ||
1535 | 1535 | ||
1536 | intel_ring_unpin(engine->buffer); | 1536 | intel_ring_unpin(engine->buffer); |
1537 | intel_ring_free(engine->buffer); | 1537 | intel_ring_free(engine->buffer); |
1538 | engine->buffer = NULL; | ||
1539 | } | ||
1540 | 1538 | ||
1541 | if (engine->cleanup) | 1539 | if (engine->cleanup) |
1542 | engine->cleanup(engine); | 1540 | engine->cleanup(engine); |
1543 | 1541 | ||
1544 | if (HWS_NEEDS_PHYSICAL(dev_priv)) { | 1542 | if (HWS_NEEDS_PHYSICAL(dev_priv)) |
1545 | WARN_ON(engine->id != RCS); | ||
1546 | cleanup_phys_status_page(engine); | 1543 | cleanup_phys_status_page(engine); |
1547 | } else { | 1544 | else |
1548 | cleanup_status_page(engine); | 1545 | cleanup_status_page(engine); |
1549 | } | ||
1550 | 1546 | ||
1551 | intel_engine_cleanup_common(engine); | 1547 | intel_engine_cleanup_common(engine); |
1552 | 1548 | ||
1553 | engine->i915 = NULL; | ||
1554 | dev_priv->engine[engine->id] = NULL; | 1549 | dev_priv->engine[engine->id] = NULL; |
1555 | kfree(engine); | 1550 | kfree(engine); |
1556 | } | 1551 | } |