diff options
Diffstat (limited to 'drivers/gpu/drm/drm_atomic.c')
-rw-r--r-- | drivers/gpu/drm/drm_atomic.c | 61 |
1 files changed, 42 insertions, 19 deletions
diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c index 7bb3845d9974..aeee083c7f95 100644 --- a/drivers/gpu/drm/drm_atomic.c +++ b/drivers/gpu/drm/drm_atomic.c | |||
@@ -1432,6 +1432,45 @@ static int atomic_set_prop(struct drm_atomic_state *state, | |||
1432 | return ret; | 1432 | return ret; |
1433 | } | 1433 | } |
1434 | 1434 | ||
1435 | /** | ||
1436 | * drm_atomic_update_old_fb -- Unset old_fb pointers and set plane->fb pointers. | ||
1437 | * | ||
1438 | * @dev: drm device to check. | ||
1439 | * @plane_mask: plane mask for planes that were updated. | ||
1440 | * @ret: return value, can be -EDEADLK for a retry. | ||
1441 | * | ||
1442 | * Before doing an update plane->old_fb is set to plane->fb, | ||
1443 | * but before dropping the locks old_fb needs to be set to NULL | ||
1444 | * and plane->fb updated. This is a common operation for each | ||
1445 | * atomic update, so this call is split off as a helper. | ||
1446 | */ | ||
1447 | void drm_atomic_clean_old_fb(struct drm_device *dev, | ||
1448 | unsigned plane_mask, | ||
1449 | int ret) | ||
1450 | { | ||
1451 | struct drm_plane *plane; | ||
1452 | |||
1453 | /* if succeeded, fixup legacy plane crtc/fb ptrs before dropping | ||
1454 | * locks (ie. while it is still safe to deref plane->state). We | ||
1455 | * need to do this here because the driver entry points cannot | ||
1456 | * distinguish between legacy and atomic ioctls. | ||
1457 | */ | ||
1458 | drm_for_each_plane_mask(plane, dev, plane_mask) { | ||
1459 | if (ret == 0) { | ||
1460 | struct drm_framebuffer *new_fb = plane->state->fb; | ||
1461 | if (new_fb) | ||
1462 | drm_framebuffer_reference(new_fb); | ||
1463 | plane->fb = new_fb; | ||
1464 | plane->crtc = plane->state->crtc; | ||
1465 | |||
1466 | if (plane->old_fb) | ||
1467 | drm_framebuffer_unreference(plane->old_fb); | ||
1468 | } | ||
1469 | plane->old_fb = NULL; | ||
1470 | } | ||
1471 | } | ||
1472 | EXPORT_SYMBOL(drm_atomic_clean_old_fb); | ||
1473 | |||
1435 | int drm_mode_atomic_ioctl(struct drm_device *dev, | 1474 | int drm_mode_atomic_ioctl(struct drm_device *dev, |
1436 | void *data, struct drm_file *file_priv) | 1475 | void *data, struct drm_file *file_priv) |
1437 | { | 1476 | { |
@@ -1446,7 +1485,7 @@ int drm_mode_atomic_ioctl(struct drm_device *dev, | |||
1446 | struct drm_plane *plane; | 1485 | struct drm_plane *plane; |
1447 | struct drm_crtc *crtc; | 1486 | struct drm_crtc *crtc; |
1448 | struct drm_crtc_state *crtc_state; | 1487 | struct drm_crtc_state *crtc_state; |
1449 | unsigned plane_mask = 0; | 1488 | unsigned plane_mask; |
1450 | int ret = 0; | 1489 | int ret = 0; |
1451 | unsigned int i, j; | 1490 | unsigned int i, j; |
1452 | 1491 | ||
@@ -1486,6 +1525,7 @@ int drm_mode_atomic_ioctl(struct drm_device *dev, | |||
1486 | state->allow_modeset = !!(arg->flags & DRM_MODE_ATOMIC_ALLOW_MODESET); | 1525 | state->allow_modeset = !!(arg->flags & DRM_MODE_ATOMIC_ALLOW_MODESET); |
1487 | 1526 | ||
1488 | retry: | 1527 | retry: |
1528 | plane_mask = 0; | ||
1489 | copied_objs = 0; | 1529 | copied_objs = 0; |
1490 | copied_props = 0; | 1530 | copied_props = 0; |
1491 | 1531 | ||
@@ -1576,24 +1616,7 @@ retry: | |||
1576 | } | 1616 | } |
1577 | 1617 | ||
1578 | out: | 1618 | out: |
1579 | /* if succeeded, fixup legacy plane crtc/fb ptrs before dropping | 1619 | drm_atomic_clean_old_fb(dev, plane_mask, ret); |
1580 | * locks (ie. while it is still safe to deref plane->state). We | ||
1581 | * need to do this here because the driver entry points cannot | ||
1582 | * distinguish between legacy and atomic ioctls. | ||
1583 | */ | ||
1584 | drm_for_each_plane_mask(plane, dev, plane_mask) { | ||
1585 | if (ret == 0) { | ||
1586 | struct drm_framebuffer *new_fb = plane->state->fb; | ||
1587 | if (new_fb) | ||
1588 | drm_framebuffer_reference(new_fb); | ||
1589 | plane->fb = new_fb; | ||
1590 | plane->crtc = plane->state->crtc; | ||
1591 | |||
1592 | if (plane->old_fb) | ||
1593 | drm_framebuffer_unreference(plane->old_fb); | ||
1594 | } | ||
1595 | plane->old_fb = NULL; | ||
1596 | } | ||
1597 | 1620 | ||
1598 | if (ret && arg->flags & DRM_MODE_PAGE_FLIP_EVENT) { | 1621 | if (ret && arg->flags & DRM_MODE_PAGE_FLIP_EVENT) { |
1599 | /* | 1622 | /* |