Commit 7317c75e66fce0c9f82fbe6f72f7e5256b315422
Committed by
Keith Packard
1 parent
c0f372b374
Exists in
master
and in
6 other branches
drm/i915: don't set unpin_work if vblank_get fails
This fixes a race where we may try to finish a page flip and decrement the refcount even if our vblank_get failed and we ended up with a spurious flip pending interrupt. Fixes https://bugs.freedesktop.org/show_bug.cgi?id=34211. Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org> Signed-off-by: Keith Packard <keithp@keithp.com>
Showing 1 changed file with 7 additions and 5 deletions Side-by-side Diff
drivers/gpu/drm/i915/intel_display.c
... | ... | @@ -7189,11 +7189,16 @@ |
7189 | 7189 | work->old_fb_obj = intel_fb->obj; |
7190 | 7190 | INIT_WORK(&work->work, intel_unpin_work_fn); |
7191 | 7191 | |
7192 | + ret = drm_vblank_get(dev, intel_crtc->pipe); | |
7193 | + if (ret) | |
7194 | + goto free_work; | |
7195 | + | |
7192 | 7196 | /* We borrow the event spin lock for protecting unpin_work */ |
7193 | 7197 | spin_lock_irqsave(&dev->event_lock, flags); |
7194 | 7198 | if (intel_crtc->unpin_work) { |
7195 | 7199 | spin_unlock_irqrestore(&dev->event_lock, flags); |
7196 | 7200 | kfree(work); |
7201 | + drm_vblank_put(dev, intel_crtc->pipe); | |
7197 | 7202 | |
7198 | 7203 | DRM_DEBUG_DRIVER("flip queue: crtc already busy\n"); |
7199 | 7204 | return -EBUSY; |
... | ... | @@ -7212,10 +7217,6 @@ |
7212 | 7217 | |
7213 | 7218 | crtc->fb = fb; |
7214 | 7219 | |
7215 | - ret = drm_vblank_get(dev, intel_crtc->pipe); | |
7216 | - if (ret) | |
7217 | - goto cleanup_objs; | |
7218 | - | |
7219 | 7220 | work->pending_flip_obj = obj; |
7220 | 7221 | |
7221 | 7222 | work->enable_stall_check = true; |
... | ... | @@ -7238,7 +7239,6 @@ |
7238 | 7239 | |
7239 | 7240 | cleanup_pending: |
7240 | 7241 | atomic_sub(1 << intel_crtc->plane, &work->old_fb_obj->pending_flip); |
7241 | -cleanup_objs: | |
7242 | 7242 | drm_gem_object_unreference(&work->old_fb_obj->base); |
7243 | 7243 | drm_gem_object_unreference(&obj->base); |
7244 | 7244 | mutex_unlock(&dev->struct_mutex); |
... | ... | @@ -7247,6 +7247,8 @@ |
7247 | 7247 | intel_crtc->unpin_work = NULL; |
7248 | 7248 | spin_unlock_irqrestore(&dev->event_lock, flags); |
7249 | 7249 | |
7250 | + drm_vblank_put(dev, intel_crtc->pipe); | |
7251 | +free_work: | |
7250 | 7252 | kfree(work); |
7251 | 7253 | |
7252 | 7254 | return ret; |