[PATCH 27/49] drm: Track framebuffer references at the point of assignment
Chris Wilson
chris at chris-wilson.co.uk
Fri Nov 11 20:39:56 UTC 2016
Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>
---
drivers/gpu/drm/amd/amdgpu/amdgpu_display.c | 2 +-
drivers/gpu/drm/armada/armada_crtc.c | 9 +--
drivers/gpu/drm/bochs/bochs_kms.c | 2 +-
drivers/gpu/drm/drm_atomic.c | 42 -------------
drivers/gpu/drm/drm_atomic_helper.c | 35 +----------
drivers/gpu/drm/drm_crtc.c | 16 +----
drivers/gpu/drm/drm_crtc_helper.c | 18 +++---
drivers/gpu/drm/drm_fb_helper.c | 17 +++---
drivers/gpu/drm/drm_plane.c | 95 ++++++++++++++++-------------
drivers/gpu/drm/i915/intel_display.c | 16 ++---
drivers/gpu/drm/mgag200/mgag200_mode.c | 2 +-
drivers/gpu/drm/msm/mdp/mdp4/mdp4_plane.c | 2 +-
drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c | 2 +-
drivers/gpu/drm/nouveau/nouveau_display.c | 2 +-
drivers/gpu/drm/nouveau/nv50_display.c | 7 ---
drivers/gpu/drm/qxl/qxl_display.c | 4 +-
drivers/gpu/drm/radeon/radeon_display.c | 3 +-
drivers/gpu/drm/shmobile/shmob_drm_crtc.c | 2 +-
drivers/gpu/drm/tilcdc/tilcdc_crtc.c | 4 +-
drivers/gpu/drm/udl/udl_modeset.c | 2 +-
drivers/gpu/drm/vc4/vc4_crtc.c | 2 +-
drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c | 4 +-
drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c | 10 +--
drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c | 4 +-
include/drm/drm_atomic.h | 3 -
include/drm/drm_plane.h | 19 ++++--
26 files changed, 123 insertions(+), 201 deletions(-)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c
index 741144fcc7bc..2aa4e707be1b 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c
@@ -225,7 +225,7 @@ int amdgpu_crtc_page_flip_target(struct drm_crtc *crtc,
DRM_DEBUG_DRIVER("crtc:%d[%p], pflip_stat:AMDGPU_FLIP_PENDING, work: %p,\n",
amdgpu_crtc->crtc_id, amdgpu_crtc, work);
/* update crtc fb */
- crtc->primary->fb = fb;
+ drm_plane_set_fb(crtc->primary, fb);
spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
amdgpu_flip_work_func(&work->flip_work.work);
return 0;
diff --git a/drivers/gpu/drm/armada/armada_crtc.c b/drivers/gpu/drm/armada/armada_crtc.c
index a51f8cbcfe26..e0847e209366 100644
--- a/drivers/gpu/drm/armada/armada_crtc.c
+++ b/drivers/gpu/drm/armada/armada_crtc.c
@@ -1025,13 +1025,7 @@ static int armada_drm_crtc_page_flip(struct drm_crtc *crtc,
return ret;
}
- /*
- * Don't take a reference on the new framebuffer;
- * drm_mode_page_flip_ioctl() has already grabbed a reference and
- * will _not_ drop that reference on successful return from this
- * function. Simply mark this new framebuffer as the current one.
- */
- dcrtc->crtc.primary->fb = fb;
+ drm_plane_set_fb(dcrtc->crtc.primary, fb);
/*
* Finally, if the display is blanked, we won't receive an
@@ -1040,6 +1034,7 @@ static int armada_drm_crtc_page_flip(struct drm_crtc *crtc,
if (dpms_blanked(dcrtc->dpms))
armada_drm_plane_work_run(dcrtc, drm_to_armada_plane(dcrtc->crtc.primary));
+ drm_framebuffer_unreference(fb);
return 0;
}
diff --git a/drivers/gpu/drm/bochs/bochs_kms.c b/drivers/gpu/drm/bochs/bochs_kms.c
index 0b4e5d117043..afe3bd2cd79e 100644
--- a/drivers/gpu/drm/bochs/bochs_kms.c
+++ b/drivers/gpu/drm/bochs/bochs_kms.c
@@ -103,7 +103,7 @@ static int bochs_crtc_page_flip(struct drm_crtc *crtc,
struct drm_framebuffer *old_fb = crtc->primary->fb;
unsigned long irqflags;
- crtc->primary->fb = fb;
+ drm_plane_set_fb(crtc->primary, fb);
bochs_crtc_mode_set_base(crtc, 0, 0, old_fb);
if (event) {
spin_lock_irqsave(&bochs->dev->event_lock, irqflags);
diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c
index d1c5f02e0ed9..6edab9d022f8 100644
--- a/drivers/gpu/drm/drm_atomic.c
+++ b/drivers/gpu/drm/drm_atomic.c
@@ -1740,45 +1740,6 @@ static int atomic_set_prop(struct drm_atomic_state *state,
return ret;
}
-/**
- * drm_atomic_clean_old_fb -- Unset old_fb pointers and set plane->fb pointers.
- *
- * @dev: drm device to check.
- * @plane_mask: plane mask for planes that were updated.
- * @ret: return value, can be -EDEADLK for a retry.
- *
- * Before doing an update plane->old_fb is set to plane->fb,
- * but before dropping the locks old_fb needs to be set to NULL
- * and plane->fb updated. This is a common operation for each
- * atomic update, so this call is split off as a helper.
- */
-void drm_atomic_clean_old_fb(struct drm_device *dev,
- unsigned plane_mask,
- int ret)
-{
- struct drm_plane *plane;
-
- /* if succeeded, fixup legacy plane crtc/fb ptrs before dropping
- * locks (ie. while it is still safe to deref plane->state). We
- * need to do this here because the driver entry points cannot
- * distinguish between legacy and atomic ioctls.
- */
- drm_for_each_plane_mask(plane, dev, plane_mask) {
- if (ret == 0) {
- struct drm_framebuffer *new_fb = plane->state->fb;
- if (new_fb)
- drm_framebuffer_reference(new_fb);
- plane->fb = new_fb;
- plane->crtc = plane->state->crtc;
-
- if (plane->old_fb)
- drm_framebuffer_unreference(plane->old_fb);
- }
- plane->old_fb = NULL;
- }
-}
-EXPORT_SYMBOL(drm_atomic_clean_old_fb);
-
int drm_mode_atomic_ioctl(struct drm_device *dev,
void *data, struct drm_file *file_priv)
{
@@ -1905,7 +1866,6 @@ int drm_mode_atomic_ioctl(struct drm_device *dev,
!(arg->flags & DRM_MODE_ATOMIC_TEST_ONLY)) {
plane = obj_to_plane(obj);
plane_mask |= (1 << drm_plane_index(plane));
- plane->old_fb = plane->fb;
}
drm_mode_object_unreference(obj);
}
@@ -1941,8 +1901,6 @@ int drm_mode_atomic_ioctl(struct drm_device *dev,
}
out:
- drm_atomic_clean_old_fb(dev, plane_mask, ret);
-
if (ret && arg->flags & DRM_MODE_PAGE_FLIP_EVENT) {
/*
* TEST_ONLY and PAGE_FLIP_EVENT are mutually exclusive,
diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c
index 6c014d43f814..1f180e7e7691 100644
--- a/drivers/gpu/drm/drm_atomic_helper.c
+++ b/drivers/gpu/drm/drm_atomic_helper.c
@@ -2040,6 +2040,9 @@ void drm_atomic_helper_swap_state(struct drm_atomic_state *state,
}
for_each_plane_in_state(state, plane, plane_state, i) {
+ drm_plane_set_fb(plane, plane_state->fb);
+ plane->crtc = plane_state->crtc;
+
plane->state->state = state;
swap(state->planes[i].state, plane->state);
plane->state->state = NULL;
@@ -2117,14 +2120,6 @@ int drm_atomic_helper_update_plane(struct drm_plane *plane,
backoff:
drm_atomic_state_clear(state);
drm_atomic_legacy_backoff(state);
-
- /*
- * Someone might have exchanged the framebuffer while we dropped locks
- * in the backoff code. We need to fix up the fb refcount tracking the
- * core does for us.
- */
- plane->old_fb = plane->fb;
-
goto retry;
}
EXPORT_SYMBOL(drm_atomic_helper_update_plane);
@@ -2185,14 +2180,6 @@ int drm_atomic_helper_disable_plane(struct drm_plane *plane)
backoff:
drm_atomic_state_clear(state);
drm_atomic_legacy_backoff(state);
-
- /*
- * Someone might have exchanged the framebuffer while we dropped locks
- * in the backoff code. We need to fix up the fb refcount tracking the
- * core does for us.
- */
- plane->old_fb = plane->fb;
-
goto retry;
}
EXPORT_SYMBOL(drm_atomic_helper_disable_plane);
@@ -2320,14 +2307,6 @@ int drm_atomic_helper_set_config(struct drm_mode_set *set)
backoff:
drm_atomic_state_clear(state);
drm_atomic_legacy_backoff(state);
-
- /*
- * Someone might have exchanged the framebuffer while we dropped locks
- * in the backoff code. We need to fix up the fb refcount tracking the
- * core does for us.
- */
- crtc->primary->old_fb = crtc->primary->fb;
-
goto retry;
}
EXPORT_SYMBOL(drm_atomic_helper_set_config);
@@ -2798,14 +2777,6 @@ int drm_atomic_helper_page_flip(struct drm_crtc *crtc,
backoff:
drm_atomic_state_clear(state);
drm_atomic_legacy_backoff(state);
-
- /*
- * Someone might have exchanged the framebuffer while we dropped locks
- * in the backoff code. We need to fix up the fb refcount tracking the
- * core does for us.
- */
- plane->old_fb = plane->fb;
-
goto retry;
}
EXPORT_SYMBOL(drm_atomic_helper_page_flip);
diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index ce274edb9e52..fb52a5a36881 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -654,8 +654,6 @@ int drm_mode_getcrtc(struct drm_device *dev,
int drm_mode_set_config_internal(struct drm_mode_set *set)
{
struct drm_crtc *crtc = set->crtc;
- struct drm_framebuffer *fb;
- struct drm_crtc *tmp;
int ret;
/*
@@ -663,23 +661,11 @@ int drm_mode_set_config_internal(struct drm_mode_set *set)
* connectors from it), hence we need to refcount the fbs across all
* crtcs. Atomic modeset will have saner semantics ...
*/
- drm_for_each_crtc(tmp, crtc->dev)
- tmp->primary->old_fb = tmp->primary->fb;
-
- fb = set->fb;
ret = crtc->funcs->set_config(set);
if (ret == 0) {
crtc->primary->crtc = crtc;
- crtc->primary->fb = fb;
- }
-
- drm_for_each_crtc(tmp, crtc->dev) {
- if (tmp->primary->fb)
- drm_framebuffer_reference(tmp->primary->fb);
- if (tmp->primary->old_fb)
- drm_framebuffer_unreference(tmp->primary->old_fb);
- tmp->primary->old_fb = NULL;
+ crtc->primary->fb = set->fb;
}
return ret;
diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c
index 5d2cb138eba6..9818fd8c5988 100644
--- a/drivers/gpu/drm/drm_crtc_helper.c
+++ b/drivers/gpu/drm/drm_crtc_helper.c
@@ -177,7 +177,7 @@ static void __drm_helper_disable_unused_functions(struct drm_device *dev)
(*crtc_funcs->disable)(crtc);
else
(*crtc_funcs->dpms)(crtc, DRM_MODE_DPMS_OFF);
- crtc->primary->fb = NULL;
+ drm_plane_set_fb(crtc->primary, NULL);
}
}
}
@@ -579,7 +579,7 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set)
save_set.mode = &set->crtc->mode;
save_set.x = set->crtc->x;
save_set.y = set->crtc->y;
- save_set.fb = set->crtc->primary->fb;
+ save_set.fb = drm_plane_get_fb(set->crtc->primary);
/* We should be able to check here if the fb has the same properties
* and then just flip_or_move it */
@@ -700,13 +700,14 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set)
DRM_DEBUG_KMS("attempting to set mode from"
" userspace\n");
drm_mode_debug_printmodeline(set->mode);
- set->crtc->primary->fb = set->fb;
+ drm_plane_set_fb(set->crtc->primary, set->fb);
if (!drm_crtc_helper_set_mode(set->crtc, set->mode,
set->x, set->y,
save_set.fb)) {
DRM_ERROR("failed to set mode on [CRTC:%d:%s]\n",
set->crtc->base.id, set->crtc->name);
- set->crtc->primary->fb = save_set.fb;
+ drm_plane_set_fb(set->crtc->primary,
+ save_set.fb);
ret = -EINVAL;
goto fail;
}
@@ -721,17 +722,18 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set)
} else if (fb_changed) {
set->crtc->x = set->x;
set->crtc->y = set->y;
- set->crtc->primary->fb = set->fb;
+ drm_plane_set_fb(set->crtc->primary, set->fb);
ret = crtc_funcs->mode_set_base(set->crtc,
set->x, set->y, save_set.fb);
if (ret != 0) {
set->crtc->x = save_set.x;
set->crtc->y = save_set.y;
- set->crtc->primary->fb = save_set.fb;
+ drm_plane_set_fb(set->crtc->primary, save_set.fb);
goto fail;
}
}
+ drm_framebuffer_unreference(save_set.fb);
kfree(save_connector_encoders);
kfree(save_encoder_crtcs);
return 0;
@@ -763,6 +765,7 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set)
save_set.y, save_set.fb))
DRM_ERROR("failed to restore config after modeset failure\n");
+ drm_framebuffer_unreference(save_set.fb);
kfree(save_connector_encoders);
kfree(save_encoder_crtcs);
return ret;
@@ -924,7 +927,8 @@ void drm_helper_resume_force_mode(struct drm_device *dev)
continue;
ret = drm_crtc_helper_set_mode(crtc, &crtc->mode,
- crtc->x, crtc->y, crtc->primary->fb);
+ crtc->x, crtc->y,
+ crtc->primary->fb);
/* Restoring the old config should never fail! */
if (ret == false)
diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c
index 36797c465edc..2d464699c084 100644
--- a/drivers/gpu/drm/drm_fb_helper.c
+++ b/drivers/gpu/drm/drm_fb_helper.c
@@ -277,7 +277,7 @@ static struct drm_framebuffer *drm_mode_config_fb(struct drm_crtc *crtc)
drm_for_each_crtc(c, dev) {
if (crtc->base.id == c->base.id)
- return c->primary->fb;
+ return drm_plane_get_fb(c->primary);
}
return NULL;
@@ -297,21 +297,24 @@ int drm_fb_helper_debug_leave(struct fb_info *info)
for (i = 0; i < helper->crtc_count; i++) {
struct drm_mode_set *mode_set = &helper->crtc_info[i].mode_set;
- crtc = mode_set->crtc;
- funcs = crtc->helper_private;
- fb = drm_mode_config_fb(crtc);
+ crtc = mode_set->crtc;
if (!crtc->enabled)
continue;
+ fb = drm_mode_config_fb(crtc);
if (!fb) {
DRM_ERROR("no fb to restore??\n");
continue;
}
drm_fb_helper_restore_lut_atomic(mode_set->crtc);
+
+ funcs = crtc->helper_private;
funcs->mode_set_base_atomic(mode_set->crtc, fb, crtc->x,
crtc->y, LEAVE_ATOMIC_MODE_SET);
+
+ drm_framebuffer_unreference(fb);
}
return 0;
@@ -344,7 +347,6 @@ static int restore_fbdev_mode_atomic(struct drm_fb_helper *fb_helper)
plane_state->rotation = DRM_ROTATE_0;
- plane->old_fb = plane->fb;
plane_mask |= 1 << drm_plane_index(plane);
/* disable non-primary: */
@@ -367,8 +369,6 @@ static int restore_fbdev_mode_atomic(struct drm_fb_helper *fb_helper)
ret = drm_atomic_commit(state);
fail:
- drm_atomic_clean_old_fb(dev, plane_mask, ret);
-
if (ret == -EDEADLK)
goto backoff;
@@ -1378,7 +1378,6 @@ static int pan_display_atomic(struct fb_var_screeninfo *var,
plane = mode_set->crtc->primary;
plane_mask |= (1 << drm_plane_index(plane));
- plane->old_fb = plane->fb;
}
ret = drm_atomic_commit(state);
@@ -1389,8 +1388,6 @@ static int pan_display_atomic(struct fb_var_screeninfo *var,
info->var.yoffset = var->yoffset;
fail:
- drm_atomic_clean_old_fb(dev, plane_mask, ret);
-
if (ret == -EDEADLK)
goto backoff;
diff --git a/drivers/gpu/drm/drm_plane.c b/drivers/gpu/drm/drm_plane.c
index 6b81a1b3967e..79df768e5ba7 100644
--- a/drivers/gpu/drm/drm_plane.c
+++ b/drivers/gpu/drm/drm_plane.c
@@ -284,17 +284,13 @@ void drm_plane_force_disable(struct drm_plane *plane)
if (!plane->fb)
return;
- plane->old_fb = plane->fb;
ret = plane->funcs->disable_plane(plane);
if (ret) {
DRM_ERROR("failed to disable plane with busy fb\n");
- plane->old_fb = NULL;
return;
}
/* disconnect the plane from the fb and crtc: */
- drm_framebuffer_unreference(plane->old_fb);
- plane->old_fb = NULL;
- plane->fb = NULL;
+ drm_plane_set_fb(plane, NULL);
plane->crtc = NULL;
}
EXPORT_SYMBOL(drm_plane_force_disable);
@@ -458,13 +454,10 @@ static int __setplane_internal(struct drm_plane *plane,
/* No fb means shut it down */
if (!fb) {
- plane->old_fb = plane->fb;
ret = plane->funcs->disable_plane(plane);
if (!ret) {
+ drm_plane_set_fb(plane, NULL);
plane->crtc = NULL;
- plane->fb = NULL;
- } else {
- plane->old_fb = NULL;
}
goto out;
}
@@ -500,25 +493,15 @@ static int __setplane_internal(struct drm_plane *plane,
if (ret)
goto out;
- plane->old_fb = plane->fb;
ret = plane->funcs->update_plane(plane, crtc, fb,
crtc_x, crtc_y, crtc_w, crtc_h,
src_x, src_y, src_w, src_h);
if (!ret) {
plane->crtc = crtc;
- plane->fb = fb;
- fb = NULL;
- } else {
- plane->old_fb = NULL;
+ drm_plane_set_fb(plane, fb);
}
out:
- if (fb)
- drm_framebuffer_unreference(fb);
- if (plane->old_fb)
- drm_framebuffer_unreference(plane->old_fb);
- plane->old_fb = NULL;
-
return ret;
}
@@ -549,6 +532,7 @@ int drm_mode_setplane(struct drm_device *dev, void *data,
struct drm_plane *plane;
struct drm_crtc *crtc = NULL;
struct drm_framebuffer *fb = NULL;
+ int err;
if (!drm_core_check_feature(dev, DRIVER_MODESET))
return -EINVAL;
@@ -584,11 +568,16 @@ int drm_mode_setplane(struct drm_device *dev, void *data,
* setplane_internal will take care of deref'ing either the old or new
* framebuffer depending on success.
*/
- return setplane_internal(plane, crtc, fb,
- plane_req->crtc_x, plane_req->crtc_y,
- plane_req->crtc_w, plane_req->crtc_h,
- plane_req->src_x, plane_req->src_y,
- plane_req->src_w, plane_req->src_h);
+ err = setplane_internal(plane, crtc, fb,
+ plane_req->crtc_x, plane_req->crtc_y,
+ plane_req->crtc_w, plane_req->crtc_h,
+ plane_req->src_x, plane_req->src_y,
+ plane_req->src_w, plane_req->src_h);
+
+ if (fb)
+ drm_framebuffer_unreference(fb);
+
+ return err;
}
static int drm_mode_cursor_universal(struct drm_crtc *crtc,
@@ -874,31 +863,55 @@ int drm_mode_page_flip_ioctl(struct drm_device *dev,
}
}
- crtc->primary->old_fb = crtc->primary->fb;
- if (crtc->funcs->page_flip_target)
+ if (crtc->funcs->page_flip_target) {
+ u32 current_vblank;
+
+ ret = drm_crtc_vblank_get(crtc);
+ if (ret)
+ return ret;
+
+ current_vblank = drm_crtc_vblank_count(crtc);
+
+ switch (page_flip->flags & DRM_MODE_PAGE_FLIP_TARGET) {
+ case DRM_MODE_PAGE_FLIP_TARGET_ABSOLUTE:
+ if ((int)(target_vblank - current_vblank) > 1) {
+ DRM_DEBUG("Invalid absolute flip target %u, "
+ "must be <= %u\n", target_vblank,
+ current_vblank + 1);
+ drm_crtc_vblank_put(crtc);
+ return -EINVAL;
+ }
+ break;
+ case DRM_MODE_PAGE_FLIP_TARGET_RELATIVE:
+ if (target_vblank != 0 && target_vblank != 1) {
+ DRM_DEBUG("Invalid relative flip target %u, "
+ "must be 0 or 1\n", target_vblank);
+ drm_crtc_vblank_put(crtc);
+ return -EINVAL;
+ }
+ target_vblank += current_vblank;
+ break;
+ default:
+ target_vblank = current_vblank +
+ !(page_flip->flags & DRM_MODE_PAGE_FLIP_ASYNC);
+ break;
+ }
+
ret = crtc->funcs->page_flip_target(crtc, fb, e,
page_flip->flags,
target_vblank);
- else
- ret = crtc->funcs->page_flip(crtc, fb, e, page_flip->flags);
- if (ret) {
- /* Keep the old fb, don't unref it. */
- crtc->primary->old_fb = NULL;
+ if (ret)
+ drm_crtc_vblank_put(crtc);
+ } else if (crtc->funcs->page_flip == NULL ||
+ (page_flip->flags & DRM_MODE_PAGE_FLIP_TARGET)) {
+ ret = -EINVAL;
} else {
- crtc->primary->fb = fb;
- /* Unref only the old framebuffer. */
- fb = NULL;
+ ret = crtc->funcs->page_flip(crtc, fb, e, page_flip->flags);
}
out:
- if (ret && crtc->funcs->page_flip_target)
- drm_crtc_vblank_put(crtc);
if (fb)
drm_framebuffer_unreference(fb);
- if (crtc->primary->old_fb)
- drm_framebuffer_unreference(crtc->primary->old_fb);
- crtc->primary->old_fb = NULL;
drm_modeset_unlock_crtc(crtc);
-
return ret;
}
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index e11918e95968..70d0988fdf2b 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -2819,8 +2819,8 @@ intel_find_initial_plane_obj(struct intel_crtc *intel_crtc,
if (i915_gem_object_is_tiled(obj))
dev_priv->preserve_bios_swizzle = true;
- drm_framebuffer_reference(fb);
- primary->fb = primary->state->fb = fb;
+ drm_plane_set_fb(primary, fb);
+ update_state_fb(primary);
mutex_lock(&dev->struct_mutex);
intel_state->vma =
@@ -2831,6 +2831,8 @@ intel_find_initial_plane_obj(struct intel_crtc *intel_crtc,
intel_crtc->base.state->plane_mask |= (1 << drm_plane_index(primary));
atomic_or(to_intel_plane(primary)->frontbuffer_bit,
&obj->frontbuffer_bits);
+
+ drm_framebuffer_unreference(fb);
}
static int skl_max_plane_width(const struct drm_framebuffer *fb, int plane,
@@ -12201,7 +12203,7 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc,
/* Reference the objects for the scheduled work. */
drm_framebuffer_reference(work->old_fb);
- crtc->primary->fb = fb;
+ drm_plane_set_fb(crtc->primary, fb);
update_state_fb(crtc->primary);
work->pending_flip_obj = i915_gem_object_get(obj);
@@ -12306,7 +12308,7 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc,
atomic_dec(&intel_crtc->unpin_work_count);
mutex_unlock(&dev->struct_mutex);
cleanup:
- crtc->primary->fb = old_fb;
+ drm_plane_set_fb(crtc->primary, old_fb);
update_state_fb(crtc->primary);
i915_gem_object_put(obj);
@@ -13086,7 +13088,6 @@ intel_modeset_update_crtc_state(struct drm_atomic_state *state)
if (drm_atomic_get_existing_plane_state(state, crtc->primary)) {
struct drm_plane_state *plane_state = crtc->primary->state;
- crtc->primary->fb = plane_state->fb;
crtc->x = plane_state->src_x >> 16;
crtc->y = plane_state->src_y >> 16;
}
@@ -17108,10 +17109,9 @@ void intel_modeset_gem_init(struct drm_device *dev)
if (IS_ERR(vma)) {
DRM_ERROR("failed to pin boot fb on pipe %d\n",
to_intel_crtc(c)->pipe);
- drm_framebuffer_unreference(c->primary->fb);
- c->primary->fb = NULL;
- c->primary->crtc = c->primary->state->crtc = NULL;
+ drm_plane_set_fb(c->primary, NULL);
update_state_fb(c->primary);
+ c->primary->crtc = c->primary->state->crtc = NULL;
c->state->plane_mask &= ~(1 << drm_plane_index(c->primary));
}
diff --git a/drivers/gpu/drm/mgag200/mgag200_mode.c b/drivers/gpu/drm/mgag200/mgag200_mode.c
index 6b21cb27e1cc..a2d3ba237f45 100644
--- a/drivers/gpu/drm/mgag200/mgag200_mode.c
+++ b/drivers/gpu/drm/mgag200/mgag200_mode.c
@@ -1392,7 +1392,7 @@ static void mga_crtc_disable(struct drm_crtc *crtc)
mgag200_bo_push_sysram(bo);
mgag200_bo_unreserve(bo);
}
- crtc->primary->fb = NULL;
+ drm_plane_set_fb(crtc->primary, NULL);
}
/* These provide the minimum set of functions required to handle a CRTC */
diff --git a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_plane.c b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_plane.c
index 3903dbcda763..27ac0cca98f4 100644
--- a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_plane.c
+++ b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_plane.c
@@ -180,7 +180,7 @@ static void mdp4_plane_set_scanout(struct drm_plane *plane,
mdp4_write(mdp4_kms, REG_MDP4_PIPE_SRCP3_BASE(pipe),
msm_framebuffer_iova(fb, mdp4_kms->id, 3));
- plane->fb = fb;
+ drm_plane_set_fb(plane, fb);
}
static void mdp4_write_csc_config(struct mdp4_kms *mdp4_kms,
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c
index 81c0562ab489..0191ecbcae0b 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c
@@ -425,7 +425,7 @@ static void set_scanout_locked(struct drm_plane *plane,
mdp5_write(mdp5_kms, REG_MDP5_PIPE_SRC3_ADDR(pipe),
msm_framebuffer_iova(fb, mdp5_kms->id, 3));
- plane->fb = fb;
+ drm_plane_set_fb(plane, fb);
}
/* Note: mdp5_plane->pipe_lock must be locked */
diff --git a/drivers/gpu/drm/nouveau/nouveau_display.c b/drivers/gpu/drm/nouveau/nouveau_display.c
index 75c90a8da18a..ec87f4a38aca 100644
--- a/drivers/gpu/drm/nouveau/nouveau_display.c
+++ b/drivers/gpu/drm/nouveau/nouveau_display.c
@@ -922,7 +922,7 @@ nouveau_crtc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb,
mutex_unlock(&cli->mutex);
/* Update the crtc struct and cleanup */
- crtc->primary->fb = fb;
+ drm_plane_set_fb(crtc->primary, fb);
nouveau_bo_fence(old_bo, fence, false);
ttm_bo_unreserve(&old_bo->bo);
diff --git a/drivers/gpu/drm/nouveau/nv50_display.c b/drivers/gpu/drm/nouveau/nv50_display.c
index 832cdbe3c9e8..2779489f2524 100644
--- a/drivers/gpu/drm/nouveau/nv50_display.c
+++ b/drivers/gpu/drm/nouveau/nv50_display.c
@@ -2277,13 +2277,6 @@ nv50_head_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb,
drm_atomic_state_clear(state);
drm_atomic_legacy_backoff(state);
- /*
- * Someone might have exchanged the framebuffer while we dropped locks
- * in the backoff code. We need to fix up the fb refcount tracking the
- * core does for us.
- */
- plane->old_fb = plane->fb;
-
goto retry;
}
diff --git a/drivers/gpu/drm/qxl/qxl_display.c b/drivers/gpu/drm/qxl/qxl_display.c
index a61c0d460ec2..2e01c6e5d905 100644
--- a/drivers/gpu/drm/qxl/qxl_display.c
+++ b/drivers/gpu/drm/qxl/qxl_display.c
@@ -237,7 +237,6 @@ static int qxl_crtc_page_flip(struct drm_crtc *crtc,
int one_clip_rect = 1;
int ret = 0;
- crtc->primary->fb = fb;
bo_old->is_primary = false;
bo->is_primary = true;
@@ -249,6 +248,7 @@ static int qxl_crtc_page_flip(struct drm_crtc *crtc,
if (ret)
return ret;
+ drm_plane_set_fb(crtc->primary, fb);
qxl_draw_dirty_fb(qdev, qfb_src, bo, 0, 0,
&norect, one_clip_rect, inc);
@@ -755,7 +755,7 @@ static void qxl_crtc_disable(struct drm_crtc *crtc)
ret = qxl_bo_reserve(bo, false);
qxl_bo_unpin(bo);
qxl_bo_unreserve(bo);
- crtc->primary->fb = NULL;
+ drm_plane_set_fb(crtc->primary, NULL);
}
qxl_monitors_config_set(qdev, qcrtc->index, 0, 0, 0, 0, 0);
diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c
index e7409e8a9f87..1eb004dc4cd6 100644
--- a/drivers/gpu/drm/radeon/radeon_display.c
+++ b/drivers/gpu/drm/radeon/radeon_display.c
@@ -598,8 +598,7 @@ static int radeon_crtc_page_flip_target(struct drm_crtc *crtc,
radeon_crtc->flip_work = work;
/* update crtc fb */
- crtc->primary->fb = fb;
-
+ drm_plane_set_fb(crtc->primary, fb);
spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
queue_work(radeon_crtc->flip_queue, &work->flip_work);
diff --git a/drivers/gpu/drm/shmobile/shmob_drm_crtc.c b/drivers/gpu/drm/shmobile/shmob_drm_crtc.c
index 6547b1db460a..fc5df59976cd 100644
--- a/drivers/gpu/drm/shmobile/shmob_drm_crtc.c
+++ b/drivers/gpu/drm/shmobile/shmob_drm_crtc.c
@@ -462,7 +462,7 @@ static int shmob_drm_crtc_page_flip(struct drm_crtc *crtc,
}
spin_unlock_irqrestore(&dev->event_lock, flags);
- crtc->primary->fb = fb;
+ drm_plane_set_fb(crtc->primary, fb);
shmob_drm_crtc_update_base(scrtc);
if (event) {
diff --git a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c
index 822531ebd4b0..f57154b69e9d 100644
--- a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c
+++ b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c
@@ -260,9 +260,7 @@ int tilcdc_crtc_update_fb(struct drm_crtc *crtc,
return -EBUSY;
}
- drm_framebuffer_reference(fb);
-
- crtc->primary->fb = fb;
+ drm_plane_set_fb(crtc->primary, fb);
spin_lock_irqsave(&tilcdc_crtc->irq_lock, flags);
diff --git a/drivers/gpu/drm/udl/udl_modeset.c b/drivers/gpu/drm/udl/udl_modeset.c
index f2b2481cad52..05133ef8942c 100644
--- a/drivers/gpu/drm/udl/udl_modeset.c
+++ b/drivers/gpu/drm/udl/udl_modeset.c
@@ -380,7 +380,7 @@ static int udl_crtc_page_flip(struct drm_crtc *crtc,
if (event)
drm_crtc_send_vblank_event(crtc, event);
spin_unlock_irqrestore(&dev->event_lock, flags);
- crtc->primary->fb = fb;
+ drm_plane_set_fb(crtc->primary, fb);
return 0;
}
diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c
index 7f08d681a74b..b13597b3f699 100644
--- a/drivers/gpu/drm/vc4/vc4_crtc.c
+++ b/drivers/gpu/drm/vc4/vc4_crtc.c
@@ -785,7 +785,7 @@ static int vc4_async_page_flip(struct drm_crtc *crtc,
* is released.
*/
drm_atomic_set_fb_for_plane(plane->state, fb);
- plane->fb = fb;
+ drm_plane_set_fb(plane, fb);
vc4_queue_seqno_cb(dev, &flip_state->cb, bo->seqno,
vc4_async_page_flip_complete);
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c b/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c
index 23ec673d5e16..61a3cce08dfe 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c
@@ -260,7 +260,7 @@ static int vmw_ldu_crtc_set_config(struct drm_mode_set *set)
connector->encoder = NULL;
encoder->crtc = NULL;
- crtc->primary->fb = NULL;
+ drm_plane_set_fb(crtc->primary, NULL);
crtc->enabled = false;
vmw_ldu_del_active(dev_priv, ldu);
@@ -281,7 +281,7 @@ static int vmw_ldu_crtc_set_config(struct drm_mode_set *set)
vmw_svga_enable(dev_priv);
- crtc->primary->fb = fb;
+ drm_plane_set_fb(crtc->primary, fb);
encoder->crtc = crtc;
connector->encoder = encoder;
crtc->x = set->x;
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c b/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c
index f42359084adc..573c7407c32c 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c
@@ -310,7 +310,7 @@ static int vmw_sou_crtc_set_config(struct drm_mode_set *set)
connector->encoder = NULL;
encoder->crtc = NULL;
- crtc->primary->fb = NULL;
+ drm_plane_set_fb(crtc->primary, NULL);
crtc->x = 0;
crtc->y = 0;
crtc->enabled = false;
@@ -371,7 +371,7 @@ static int vmw_sou_crtc_set_config(struct drm_mode_set *set)
connector->encoder = NULL;
encoder->crtc = NULL;
- crtc->primary->fb = NULL;
+ drm_plane_set_fb(crtc->primary, NULL);
crtc->x = 0;
crtc->y = 0;
crtc->enabled = false;
@@ -384,7 +384,7 @@ static int vmw_sou_crtc_set_config(struct drm_mode_set *set)
connector->encoder = encoder;
encoder->crtc = crtc;
crtc->mode = *mode;
- crtc->primary->fb = fb;
+ drm_plane_set_fb(crtc->primary, fb);
crtc->x = set->x;
crtc->y = set->y;
crtc->enabled = true;
@@ -407,7 +407,7 @@ static int vmw_sou_crtc_page_flip(struct drm_crtc *crtc,
if (!vmw_kms_crtc_flippable(dev_priv, crtc))
return -EINVAL;
- crtc->primary->fb = fb;
+ drm_plane_set_fb(crtc->primary, fb);
/* do a full screen dirty update */
vclips.x = crtc->x;
@@ -454,7 +454,7 @@ static int vmw_sou_crtc_page_flip(struct drm_crtc *crtc,
return ret;
out_no_fence:
- crtc->primary->fb = old_fb;
+ drm_plane_set_fb(crtc->primary, old_fb);
return ret;
}
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c b/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c
index 94ad8d2acf9a..01c4d574fa78 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c
@@ -486,7 +486,7 @@ static int vmw_stdu_bind_fb(struct vmw_private *dev_priv,
new_display_srf = NULL;
}
- crtc->primary->fb = new_fb;
+ drm_plane_set_fb(crtc->primary, new_fb);
stdu->content_fb_type = new_content_type;
return 0;
@@ -580,7 +580,7 @@ static int vmw_stdu_crtc_set_config(struct drm_mode_set *set)
if (ret)
return ret;
- crtc->primary->fb = NULL;
+ drm_plane_set_fb(crtc->primary, NULL);
crtc->enabled = false;
encoder->crtc = NULL;
connector->encoder = NULL;
diff --git a/include/drm/drm_atomic.h b/include/drm/drm_atomic.h
index 17aebddb8406..6a89ace8d151 100644
--- a/include/drm/drm_atomic.h
+++ b/include/drm/drm_atomic.h
@@ -401,9 +401,6 @@ drm_atomic_add_affected_planes(struct drm_atomic_state *state,
void drm_atomic_legacy_backoff(struct drm_atomic_state *state);
-void
-drm_atomic_clean_old_fb(struct drm_device *dev, unsigned plane_mask, int ret);
-
int __must_check drm_atomic_check_only(struct drm_atomic_state *state);
int __must_check drm_atomic_commit(struct drm_atomic_state *state);
int __must_check drm_atomic_nonblocking_commit(struct drm_atomic_state *state);
diff --git a/include/drm/drm_plane.h b/include/drm/drm_plane.h
index 5b38eb94783b..a4929ef02f6c 100644
--- a/include/drm/drm_plane.h
+++ b/include/drm/drm_plane.h
@@ -451,8 +451,6 @@ enum drm_plane_type {
* @format_default: driver hasn't supplied supported formats for the plane
* @crtc: currently bound CRTC
* @fb: currently bound fb
- * @old_fb: Temporary tracking of the old fb while a modeset is ongoing. Used by
- * drm_mode_set_config_internal() to implement correct refcounting.
* @funcs: helper functions
* @properties: property tracking for this plane
* @type: type of plane (overlay, primary, cursor)
@@ -486,8 +484,6 @@ struct drm_plane {
struct drm_crtc *crtc;
struct drm_framebuffer *fb;
- struct drm_framebuffer *old_fb;
-
const struct drm_plane_funcs *funcs;
struct drm_object_properties properties;
@@ -596,5 +592,20 @@ static inline struct drm_plane *drm_plane_find(struct drm_device *dev,
#define drm_for_each_plane(plane, dev) \
list_for_each_entry(plane, &(dev)->mode_config.plane_list, head)
+static inline void drm_plane_set_fb(struct drm_plane *plane,
+ struct drm_framebuffer *fb)
+{
+ if (plane->fb != fb)
+ drm_framebuffer_assign(&plane->fb, fb);
+}
+
+static inline struct drm_framebuffer *
+drm_plane_get_fb(struct drm_plane *plane)
+{
+ struct drm_framebuffer *fb = plane->fb;
+ if (fb)
+ drm_framebuffer_reference(fb);
+ return fb;
+}
#endif
--
2.10.2
More information about the Intel-gfx-trybot
mailing list