aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/i915/intel_ringbuffer.c
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2017-04-03 07:34:26 -0400
committerChris Wilson <chris@chris-wilson.co.uk>2017-04-03 08:53:14 -0400
commit1a5788bf2729c6e98444c7f56f960957694472c2 (patch)
tree9f20cb72e891fc6397e4d5a23df2bea927acaa33 /drivers/gpu/drm/i915/intel_ringbuffer.c
parentd822bb18ce96391245d877d5bada8913b88a15cf (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.c77
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,
1481static int intel_init_ring_buffer(struct intel_engine_cs *engine) 1483static 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
1521error: 1517err_ring:
1522 intel_engine_cleanup(engine); 1518 intel_ring_free(ring);
1523 return ret; 1519err_hws:
1520 if (HWS_NEEDS_PHYSICAL(engine->i915))
1521 cleanup_phys_status_page(engine);
1522 else
1523 cleanup_status_page(engine);
1524err:
1525 intel_engine_cleanup_common(engine);
1526 return err;
1524} 1527}
1525 1528
1526void intel_engine_cleanup(struct intel_engine_cs *engine) 1529void 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}