diff options
author | Maarten Lankhorst <maarten.lankhorst@linux.intel.com> | 2015-06-24 02:59:25 -0400 |
---|---|---|
committer | Daniel Vetter <daniel.vetter@ffwll.ch> | 2015-07-07 02:58:19 -0400 |
commit | ec9f932ed41622d120de52a5b525e4d77b9ef17e (patch) | |
tree | 9fb31bee516c49e25327444afa0d64dc2824d68f /drivers/gpu/drm/drm_atomic.c | |
parent | 3cb43cc0b408c4672ba94fe28406a90a94b1edfe (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.c | 64 |
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 | ||
1544 | out: | ||
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 | ||
1569 | fail: | 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 | |||
1587 | backoff: | ||
1588 | drm_atomic_state_clear(state); | ||
1589 | drm_modeset_backoff(&ctx); | ||
1590 | |||
1591 | goto retry; | ||
1592 | } | 1588 | } |