diff options
author | Maarten Lankhorst <maarten.lankhorst@linux.intel.com> | 2015-11-11 05:29:10 -0500 |
---|---|---|
committer | Jani Nikula <jani.nikula@intel.com> | 2015-11-17 06:02:14 -0500 |
commit | f72c6b33edda439acff81a0da612f2bcd1f46f35 (patch) | |
tree | 008194388572c3ff7b594f06214a23b0406efc04 | |
parent | 0f45c26fc302c02b0576db37d4849baa53a2bb41 (diff) |
drm/core: Fix old_fb handling in restore_fbdev_mode_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-5-git-send-email-maarten.lankhorst@ubuntu.com
-rw-r--r-- | drivers/gpu/drm/drm_fb_helper.c | 21 |
1 files changed, 6 insertions, 15 deletions
diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c index e673c13c7391..abd50863506e 100644 --- a/drivers/gpu/drm/drm_fb_helper.c +++ b/drivers/gpu/drm/drm_fb_helper.c | |||
@@ -342,6 +342,7 @@ static int restore_fbdev_mode_atomic(struct drm_fb_helper *fb_helper) | |||
342 | struct drm_plane *plane; | 342 | struct drm_plane *plane; |
343 | struct drm_atomic_state *state; | 343 | struct drm_atomic_state *state; |
344 | int i, ret; | 344 | int i, ret; |
345 | unsigned plane_mask; | ||
345 | 346 | ||
346 | state = drm_atomic_state_alloc(dev); | 347 | state = drm_atomic_state_alloc(dev); |
347 | if (!state) | 348 | if (!state) |
@@ -349,11 +350,10 @@ static int restore_fbdev_mode_atomic(struct drm_fb_helper *fb_helper) | |||
349 | 350 | ||
350 | state->acquire_ctx = dev->mode_config.acquire_ctx; | 351 | state->acquire_ctx = dev->mode_config.acquire_ctx; |
351 | retry: | 352 | retry: |
353 | plane_mask = 0; | ||
352 | drm_for_each_plane(plane, dev) { | 354 | drm_for_each_plane(plane, dev) { |
353 | struct drm_plane_state *plane_state; | 355 | struct drm_plane_state *plane_state; |
354 | 356 | ||
355 | plane->old_fb = plane->fb; | ||
356 | |||
357 | plane_state = drm_atomic_get_plane_state(state, plane); | 357 | plane_state = drm_atomic_get_plane_state(state, plane); |
358 | if (IS_ERR(plane_state)) { | 358 | if (IS_ERR(plane_state)) { |
359 | ret = PTR_ERR(plane_state); | 359 | ret = PTR_ERR(plane_state); |
@@ -362,6 +362,9 @@ retry: | |||
362 | 362 | ||
363 | plane_state->rotation = BIT(DRM_ROTATE_0); | 363 | plane_state->rotation = BIT(DRM_ROTATE_0); |
364 | 364 | ||
365 | plane->old_fb = plane->fb; | ||
366 | plane_mask |= 1 << drm_plane_index(plane); | ||
367 | |||
365 | /* disable non-primary: */ | 368 | /* disable non-primary: */ |
366 | if (plane->type == DRM_PLANE_TYPE_PRIMARY) | 369 | if (plane->type == DRM_PLANE_TYPE_PRIMARY) |
367 | continue; | 370 | continue; |
@@ -382,19 +385,7 @@ retry: | |||
382 | ret = drm_atomic_commit(state); | 385 | ret = drm_atomic_commit(state); |
383 | 386 | ||
384 | fail: | 387 | fail: |
385 | drm_for_each_plane(plane, dev) { | 388 | drm_atomic_clean_old_fb(dev, plane_mask, ret); |
386 | if (ret == 0) { | ||
387 | struct drm_framebuffer *new_fb = plane->state->fb; | ||
388 | if (new_fb) | ||
389 | drm_framebuffer_reference(new_fb); | ||
390 | plane->fb = new_fb; | ||
391 | plane->crtc = plane->state->crtc; | ||
392 | |||
393 | if (plane->old_fb) | ||
394 | drm_framebuffer_unreference(plane->old_fb); | ||
395 | } | ||
396 | plane->old_fb = NULL; | ||
397 | } | ||
398 | 389 | ||
399 | if (ret == -EDEADLK) | 390 | if (ret == -EDEADLK) |
400 | goto backoff; | 391 | goto backoff; |