mirror of https://gitee.com/openkylin/linux.git
drm/core: Fix old_fb handling in pan_display_atomic.
Don't touch plane->old_fb/fb without having the right locks held. Signed-off-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com> Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch> Signed-off-by: Jani Nikula <jani.nikula@intel.com> Link: http://patchwork.freedesktop.org/patch/msgid/1447237751-9663-6-git-send-email-maarten.lankhorst@ubuntu.com
This commit is contained in:
parent
f72c6b33ed
commit
07d3bad6c1
|
@ -1227,7 +1227,9 @@ static int pan_display_atomic(struct fb_var_screeninfo *var,
|
|||
struct drm_fb_helper *fb_helper = info->par;
|
||||
struct drm_device *dev = fb_helper->dev;
|
||||
struct drm_atomic_state *state;
|
||||
struct drm_plane *plane;
|
||||
int i, ret;
|
||||
unsigned plane_mask;
|
||||
|
||||
state = drm_atomic_state_alloc(dev);
|
||||
if (!state)
|
||||
|
@ -1235,19 +1237,22 @@ static int pan_display_atomic(struct fb_var_screeninfo *var,
|
|||
|
||||
state->acquire_ctx = dev->mode_config.acquire_ctx;
|
||||
retry:
|
||||
plane_mask = 0;
|
||||
for(i = 0; i < fb_helper->crtc_count; i++) {
|
||||
struct drm_mode_set *mode_set;
|
||||
|
||||
mode_set = &fb_helper->crtc_info[i].mode_set;
|
||||
|
||||
mode_set->crtc->primary->old_fb = mode_set->crtc->primary->fb;
|
||||
|
||||
mode_set->x = var->xoffset;
|
||||
mode_set->y = var->yoffset;
|
||||
|
||||
ret = __drm_atomic_helper_set_config(mode_set, state);
|
||||
if (ret != 0)
|
||||
goto fail;
|
||||
|
||||
plane = mode_set->crtc->primary;
|
||||
plane_mask |= drm_plane_index(plane);
|
||||
plane->old_fb = plane->fb;
|
||||
}
|
||||
|
||||
ret = drm_atomic_commit(state);
|
||||
|
@ -1259,26 +1264,7 @@ static int pan_display_atomic(struct fb_var_screeninfo *var,
|
|||
|
||||
|
||||
fail:
|
||||
for(i = 0; i < fb_helper->crtc_count; i++) {
|
||||
struct drm_mode_set *mode_set;
|
||||
struct drm_plane *plane;
|
||||
|
||||
mode_set = &fb_helper->crtc_info[i].mode_set;
|
||||
plane = mode_set->crtc->primary;
|
||||
|
||||
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;
|
||||
}
|
||||
drm_atomic_clean_old_fb(dev, plane_mask, ret);
|
||||
|
||||
if (ret == -EDEADLK)
|
||||
goto backoff;
|
||||
|
|
Loading…
Reference in New Issue