aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/drm_atomic.c
diff options
context:
space:
mode:
authorMaarten Lankhorst <maarten.lankhorst@linux.intel.com>2015-06-24 02:59:25 -0400
committerDaniel Vetter <daniel.vetter@ffwll.ch>2015-07-07 02:58:19 -0400
commitec9f932ed41622d120de52a5b525e4d77b9ef17e (patch)
tree9fb31bee516c49e25327444afa0d64dc2824d68f /drivers/gpu/drm/drm_atomic.c
parent3cb43cc0b408c4672ba94fe28406a90a94b1edfe (diff)
drm/atomic: Cleanup on error properly in the atomic ioctl.
It's probably allowed to leave old_fb set to garbage when unlocking, but to prevent undefined behavior unset it just in case. Also crtc_state->event could be NULL on memory allocation failure, in which case event_space is increased for no reason. Note: Contains some general simplification of the cleanup code too. Signed-off-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com> [danvet: Add note about the other changes in here. And fix long line while at it.] Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Diffstat (limited to 'drivers/gpu/drm/drm_atomic.c')
-rw-r--r--drivers/gpu/drm/drm_atomic.c64
1 files changed, 30 insertions, 34 deletions
diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c
index bd7f723c708e..acebd1617264 100644
--- a/drivers/gpu/drm/drm_atomic.c
+++ b/drivers/gpu/drm/drm_atomic.c
@@ -1463,18 +1463,18 @@ retry:
1463 1463
1464 if (get_user(obj_id, objs_ptr + copied_objs)) { 1464 if (get_user(obj_id, objs_ptr + copied_objs)) {
1465 ret = -EFAULT; 1465 ret = -EFAULT;
1466 goto fail; 1466 goto out;
1467 } 1467 }
1468 1468
1469 obj = drm_mode_object_find(dev, obj_id, DRM_MODE_OBJECT_ANY); 1469 obj = drm_mode_object_find(dev, obj_id, DRM_MODE_OBJECT_ANY);
1470 if (!obj || !obj->properties) { 1470 if (!obj || !obj->properties) {
1471 ret = -ENOENT; 1471 ret = -ENOENT;
1472 goto fail; 1472 goto out;
1473 } 1473 }
1474 1474
1475 if (get_user(count_props, count_props_ptr + copied_objs)) { 1475 if (get_user(count_props, count_props_ptr + copied_objs)) {
1476 ret = -EFAULT; 1476 ret = -EFAULT;
1477 goto fail; 1477 goto out;
1478 } 1478 }
1479 1479
1480 copied_objs++; 1480 copied_objs++;
@@ -1486,25 +1486,25 @@ retry:
1486 1486
1487 if (get_user(prop_id, props_ptr + copied_props)) { 1487 if (get_user(prop_id, props_ptr + copied_props)) {
1488 ret = -EFAULT; 1488 ret = -EFAULT;
1489 goto fail; 1489 goto out;
1490 } 1490 }
1491 1491
1492 prop = drm_property_find(dev, prop_id); 1492 prop = drm_property_find(dev, prop_id);
1493 if (!prop) { 1493 if (!prop) {
1494 ret = -ENOENT; 1494 ret = -ENOENT;
1495 goto fail; 1495 goto out;
1496 } 1496 }
1497 1497
1498 if (copy_from_user(&prop_value, 1498 if (copy_from_user(&prop_value,
1499 prop_values_ptr + copied_props, 1499 prop_values_ptr + copied_props,
1500 sizeof(prop_value))) { 1500 sizeof(prop_value))) {
1501 ret = -EFAULT; 1501 ret = -EFAULT;
1502 goto fail; 1502 goto out;
1503 } 1503 }
1504 1504
1505 ret = atomic_set_prop(state, obj, prop, prop_value); 1505 ret = atomic_set_prop(state, obj, prop, prop_value);
1506 if (ret) 1506 if (ret)
1507 goto fail; 1507 goto out;
1508 1508
1509 copied_props++; 1509 copied_props++;
1510 } 1510 }
@@ -1523,7 +1523,7 @@ retry:
1523 e = create_vblank_event(dev, file_priv, arg->user_data); 1523 e = create_vblank_event(dev, file_priv, arg->user_data);
1524 if (!e) { 1524 if (!e) {
1525 ret = -ENOMEM; 1525 ret = -ENOMEM;
1526 goto fail; 1526 goto out;
1527 } 1527 }
1528 1528
1529 crtc_state->event = e; 1529 crtc_state->event = e;
@@ -1533,13 +1533,15 @@ retry:
1533 if (arg->flags & DRM_MODE_ATOMIC_TEST_ONLY) { 1533 if (arg->flags & DRM_MODE_ATOMIC_TEST_ONLY) {
1534 ret = drm_atomic_check_only(state); 1534 ret = drm_atomic_check_only(state);
1535 /* _check_only() does not free state, unlike _commit() */ 1535 /* _check_only() does not free state, unlike _commit() */
1536 drm_atomic_state_free(state); 1536 if (!ret)
1537 drm_atomic_state_free(state);
1537 } else if (arg->flags & DRM_MODE_ATOMIC_NONBLOCK) { 1538 } else if (arg->flags & DRM_MODE_ATOMIC_NONBLOCK) {
1538 ret = drm_atomic_async_commit(state); 1539 ret = drm_atomic_async_commit(state);
1539 } else { 1540 } else {
1540 ret = drm_atomic_commit(state); 1541 ret = drm_atomic_commit(state);
1541 } 1542 }
1542 1543
1544out:
1543 /* if succeeded, fixup legacy plane crtc/fb ptrs before dropping 1545 /* if succeeded, fixup legacy plane crtc/fb ptrs before dropping
1544 * locks (ie. while it is still safe to deref plane->state). We 1546 * locks (ie. while it is still safe to deref plane->state). We
1545 * need to do this here because the driver entry points cannot 1547 * need to do this here because the driver entry points cannot
@@ -1552,41 +1554,35 @@ retry:
1552 drm_framebuffer_reference(new_fb); 1554 drm_framebuffer_reference(new_fb);
1553 plane->fb = new_fb; 1555 plane->fb = new_fb;
1554 plane->crtc = plane->state->crtc; 1556 plane->crtc = plane->state->crtc;
1555 } else { 1557
1556 plane->old_fb = NULL; 1558 if (plane->old_fb)
1557 } 1559 drm_framebuffer_unreference(plane->old_fb);
1558 if (plane->old_fb) {
1559 drm_framebuffer_unreference(plane->old_fb);
1560 plane->old_fb = NULL;
1561 } 1560 }
1561 plane->old_fb = NULL;
1562 } 1562 }
1563 1563
1564 drm_modeset_drop_locks(&ctx); 1564 if (ret == -EDEADLK) {
1565 drm_modeset_acquire_fini(&ctx); 1565 drm_atomic_state_clear(state);
1566 1566 drm_modeset_backoff(&ctx);
1567 return ret; 1567 goto retry;
1568 }
1568 1569
1569fail: 1570 if (ret) {
1570 if (ret == -EDEADLK) 1571 if (arg->flags & DRM_MODE_PAGE_FLIP_EVENT) {
1571 goto backoff; 1572 for_each_crtc_in_state(state, crtc, crtc_state, i) {
1573 if (!crtc_state->event)
1574 continue;
1572 1575
1573 if (arg->flags & DRM_MODE_PAGE_FLIP_EVENT) { 1576 destroy_vblank_event(dev, file_priv,
1574 for_each_crtc_in_state(state, crtc, crtc_state, i) { 1577 crtc_state->event);
1575 destroy_vblank_event(dev, file_priv, crtc_state->event); 1578 }
1576 crtc_state->event = NULL;
1577 } 1579 }
1578 }
1579 1580
1580 drm_atomic_state_free(state); 1581 drm_atomic_state_free(state);
1582 }
1581 1583
1582 drm_modeset_drop_locks(&ctx); 1584 drm_modeset_drop_locks(&ctx);
1583 drm_modeset_acquire_fini(&ctx); 1585 drm_modeset_acquire_fini(&ctx);
1584 1586
1585 return ret; 1587 return ret;
1586
1587backoff:
1588 drm_atomic_state_clear(state);
1589 drm_modeset_backoff(&ctx);
1590
1591 goto retry;
1592} 1588}